Merge remote-tracking branch 'eurecom_gitlab/develop' into DRX_develop

This commit is contained in:
Louis Adrien Dufrene
2018-10-23 08:00:00 +02:00
311 changed files with 24047 additions and 13432 deletions
+29
View File
@@ -0,0 +1,29 @@
/*
* 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
*/
/*
* flexran_messages_def.h
*
* Created on: Apr 26, 2018
* Author: R. Schmidt
*/
MESSAGE_DEF(SOFT_RESTART_MESSAGE, MESSAGE_PRIORITY_MED_PLUS, IttiMsgEmpty, soft_restart_message)
+1
View File
@@ -25,3 +25,4 @@ MESSAGE_DEF(GTPV1U_ENB_DELETE_TUNNEL_REQ, MESSAGE_PRIORITY_MED, gtpv1u_enb_del
MESSAGE_DEF(GTPV1U_ENB_DELETE_TUNNEL_RESP, MESSAGE_PRIORITY_MED, gtpv1u_enb_delete_tunnel_resp_t, Gtpv1uDeleteTunnelResp)
MESSAGE_DEF(GTPV1U_ENB_TUNNEL_DATA_IND, MESSAGE_PRIORITY_MED, gtpv1u_enb_tunnel_data_ind_t, Gtpv1uTunnelDataInd)
MESSAGE_DEF(GTPV1U_ENB_TUNNEL_DATA_REQ, MESSAGE_PRIORITY_MED, gtpv1u_enb_tunnel_data_req_t, Gtpv1uTunnelDataReq)
MESSAGE_DEF(GTPV1U_ENB_S1_REQ, MESSAGE_PRIORITY_MED, Gtpv1uS1Req, gtpv1uS1Req)
+5
View File
@@ -33,6 +33,7 @@
#define GTPV1U_ENB_DELETE_TUNNEL_RESP(mSGpTR) (mSGpTR)->ittiMsg.Gtpv1uDeleteTunnelResp
#define GTPV1U_ENB_TUNNEL_DATA_IND(mSGpTR) (mSGpTR)->ittiMsg.Gtpv1uTunnelDataInd
#define GTPV1U_ENB_TUNNEL_DATA_REQ(mSGpTR) (mSGpTR)->ittiMsg.Gtpv1uTunnelDataReq
#define GTPV1U_ENB_S1_REQ(mSGpTR) (mSGpTR)->ittiMsg.gtpv1uS1Req
#define GTPV1U_ALL_TUNNELS_TEID (teid_t)0xFFFFFFFF
@@ -98,4 +99,8 @@ typedef struct gtpv1u_enb_tunnel_data_req_s {
rb_id_t rab_id;
} gtpv1u_enb_tunnel_data_req_t;
typedef struct {
in_addr_t enb_ip_address_for_S1u_S12_S4_up;
tcp_udp_port_t enb_port_for_S1u_S12_S4_up;
} Gtpv1uS1Req;
#endif /* GTPV1_U_MESSAGES_TYPES_H_ */
+1 -1
View File
@@ -38,4 +38,4 @@
#include "sctp_messages_def.h"
#include "udp_messages_def.h"
#include "gtpv1_u_messages_def.h"
#include "flexran_messages_def.h"
+10 -4
View File
@@ -34,9 +34,6 @@
#include <stdint.h>
#endif
#if defined(ENABLE_ITTI)
#include "itti_types.h"
#endif
//-----------------------------------------------------------------------------
// GENERIC TYPES
//-----------------------------------------------------------------------------
@@ -110,9 +107,15 @@ typedef enum {
CR_HOL = 2,
CR_LC = 3,
CR_CQI = 4,
CR_NUM = 5
CR_LCP = 5,
CR_NUM = 6
} sorting_criterion_t;
typedef enum {
POL_FAIR = 0,
POL_GREEDY = 1,
POL_NUM = 2
} accounting_policy_t;
//-----------------------------------------------------------------------------
// PHY TYPES
//-----------------------------------------------------------------------------
@@ -288,4 +291,7 @@ typedef struct protocol_ctxt_s {
(CTXT_Pp)->rnti
#define CHECK_CTXT_ARGS(CTXT_Pp)
#define exit_fun(msg) exit_function(__FILE__,__FUNCTION__,__LINE__,msg)
void exit_function(const char* file, const char* function, const int line, const char* s);
#endif
+4 -3
View File
@@ -97,9 +97,10 @@ typedef struct RrcConfigurationReq_s {
uint16_t tac;
uint16_t mcc;
uint16_t mnc;
uint8_t mnc_digit_length;
uint16_t mcc[PLMN_LIST_MAX_SIZE];
uint16_t mnc[PLMN_LIST_MAX_SIZE];
uint8_t mnc_digit_length[PLMN_LIST_MAX_SIZE];
uint8_t num_plmn;
paging_drx_t default_drx;
+11 -3
View File
@@ -325,12 +325,14 @@ typedef struct s1ap_register_enb_req_s {
/* Tracking area code */
uint16_t tac;
#define PLMN_LIST_MAX_SIZE 6
/* Mobile Country Code
* Mobile Network Code
*/
uint16_t mcc;
uint16_t mnc;
uint8_t mnc_digit_length;
uint16_t mcc[PLMN_LIST_MAX_SIZE];
uint16_t mnc[PLMN_LIST_MAX_SIZE];
uint8_t mnc_digit_length[PLMN_LIST_MAX_SIZE];
uint8_t num_plmn;
/* Default Paging DRX of the eNB as defined in TS 36.304 */
paging_drx_t default_drx;
@@ -342,6 +344,8 @@ typedef struct s1ap_register_enb_req_s {
uint8_t nb_mme;
/* List of MME to connect to */
net_ip_address_t mme_ip_address[S1AP_MAX_NB_MME_IP_ADDRESS];
uint8_t broadcast_plmn_num[S1AP_MAX_NB_MME_IP_ADDRESS];
uint8_t broadcast_plmn_index[S1AP_MAX_NB_MME_IP_ADDRESS][PLMN_LIST_MAX_SIZE];
/* Number of SCTP streams used for a mme association */
uint16_t sctp_in_streams;
@@ -372,6 +376,10 @@ typedef struct s1ap_nas_first_req_s {
/* UE id for initial connection to S1AP */
uint16_t ue_initial_id;
/* the chosen PLMN identity as index, see TS 36.331 6.2.2 RRC Connection
* Setup Complete. This index here is zero-based, unlike the standard! */
int selected_plmn_identity;
/* Establishment cause as sent by UE */
rrc_establishment_cause_t establishment_cause;
+11 -8
View File
@@ -19,11 +19,14 @@
* contact@openairinterface.org
*/
MESSAGE_DEF(SCTP_NEW_ASSOCIATION_REQ , MESSAGE_PRIORITY_MED, sctp_new_association_req_t , sctp_new_association_req)
MESSAGE_DEF(SCTP_NEW_ASSOCIATION_RESP, MESSAGE_PRIORITY_MED, sctp_new_association_resp_t , sctp_new_association_resp)
MESSAGE_DEF(SCTP_NEW_ASSOCIATION_IND , MESSAGE_PRIORITY_MED, sctp_new_association_ind_t , sctp_new_association_ind)
MESSAGE_DEF(SCTP_REGISTER_UPPER_LAYER, MESSAGE_PRIORITY_MED, sctp_listener_register_upper_layer_t, sctp_listener_register_upper_layer)
MESSAGE_DEF(SCTP_DATA_REQ, MESSAGE_PRIORITY_MED, sctp_data_req_t , sctp_data_req)
MESSAGE_DEF(SCTP_DATA_IND, MESSAGE_PRIORITY_MED, sctp_data_ind_t , sctp_data_ind)
MESSAGE_DEF(SCTP_INIT_MSG, MESSAGE_PRIORITY_MED, sctp_init_t , sctp_init)
MESSAGE_DEF(SCTP_CLOSE_ASSOCIATION, MESSAGE_PRIORITY_MAX, sctp_close_association_t , sctp_close_association)
MESSAGE_DEF(SCTP_NEW_ASSOCIATION_REQ , MESSAGE_PRIORITY_MED, sctp_new_association_req_t , sctp_new_association_req)
MESSAGE_DEF(SCTP_NEW_ASSOCIATION_REQ_MULTI, MESSAGE_PRIORITY_MED, sctp_new_association_req_multi_t , sctp_new_association_req_multi)
MESSAGE_DEF(SCTP_NEW_ASSOCIATION_RESP, MESSAGE_PRIORITY_MED, sctp_new_association_resp_t , sctp_new_association_resp)
MESSAGE_DEF(SCTP_NEW_ASSOCIATION_IND , MESSAGE_PRIORITY_MED, sctp_new_association_ind_t , sctp_new_association_ind)
MESSAGE_DEF(SCTP_REGISTER_UPPER_LAYER, MESSAGE_PRIORITY_MED, sctp_listener_register_upper_layer_t , sctp_listener_register_upper_layer)
MESSAGE_DEF(SCTP_DATA_REQ, MESSAGE_PRIORITY_MED, sctp_data_req_t , sctp_data_req)
MESSAGE_DEF(SCTP_DATA_IND, MESSAGE_PRIORITY_MED, sctp_data_ind_t , sctp_data_ind)
MESSAGE_DEF(SCTP_INIT_MSG, MESSAGE_PRIORITY_MED, sctp_init_t , sctp_init)
MESSAGE_DEF(SCTP_INIT_MSG_MULTI_REQ, MESSAGE_PRIORITY_MED, sctp_init_t , sctp_init_multi)
MESSAGE_DEF(SCTP_INIT_MSG_MULTI_CNF, MESSAGE_PRIORITY_MED, sctp_init_msg_multi_cnf_t , sctp_init_msg_multi_cnf)
MESSAGE_DEF(SCTP_CLOSE_ASSOCIATION, MESSAGE_PRIORITY_MAX, sctp_close_association_t , sctp_close_association)
+36 -7
View File
@@ -22,13 +22,16 @@
#ifndef SCTP_MESSAGES_TYPES_H_
#define SCTP_MESSAGES_TYPES_H_
#define SCTP_NEW_ASSOCIATION_REQ(mSGpTR) (mSGpTR)->ittiMsg.sctp_new_association_req
#define SCTP_NEW_ASSOCIATION_RESP(mSGpTR)(mSGpTR)->ittiMsg.sctp_new_association_resp
#define SCTP_NEW_ASSOCIATION_IND(mSGpTR) (mSGpTR)->ittiMsg.sctp_new_association_ind
#define SCTP_DATA_IND(mSGpTR) (mSGpTR)->ittiMsg.sctp_data_ind
#define SCTP_DATA_REQ(mSGpTR) (mSGpTR)->ittiMsg.sctp_data_req
#define SCTP_INIT_MSG(mSGpTR) (mSGpTR)->ittiMsg.sctp_init
#define SCTP_CLOSE_ASSOCIATION(mSGpTR) (mSGpTR)->ittiMsg.sctp_close_association
#define SCTP_NEW_ASSOCIATION_REQ(mSGpTR) (mSGpTR)->ittiMsg.sctp_new_association_req
#define SCTP_NEW_ASSOCIATION_REQ_MULTI(mSGpTR) (mSGpTR)->ittiMsg.sctp_new_association_req_multi
#define SCTP_NEW_ASSOCIATION_RESP(mSGpTR) (mSGpTR)->ittiMsg.sctp_new_association_resp
#define SCTP_NEW_ASSOCIATION_IND(mSGpTR) (mSGpTR)->ittiMsg.sctp_new_association_ind
#define SCTP_DATA_IND(mSGpTR) (mSGpTR)->ittiMsg.sctp_data_ind
#define SCTP_DATA_REQ(mSGpTR) (mSGpTR)->ittiMsg.sctp_data_req
#define SCTP_INIT_MSG(mSGpTR) (mSGpTR)->ittiMsg.sctp_init
#define SCTP_INIT_MSG_MULTI_REQ(mSGpTR) (mSGpTR)->ittiMsg.sctp_init_multi
#define SCTP_INIT_MSG_MULTI_CNF(mSGpTR) (mSGpTR)->ittiMsg.sctp_init_msg_multi_cnf
#define SCTP_CLOSE_ASSOCIATION(mSGpTR) (mSGpTR)->ittiMsg.sctp_close_association
enum sctp_state_e {
SCTP_STATE_CLOSED,
@@ -56,6 +59,32 @@ typedef struct sctp_new_association_req_s {
net_ip_address_t remote_address;
} sctp_new_association_req_t;
typedef struct sctp_new_association_req_multi_s {
/* Upper layer connexion identifier */
uint16_t ulp_cnx_id;
/* The port to connect to */
uint16_t port;
/* Payload Protocol Identifier to use */
uint32_t ppid;
/* Number of streams used for this association */
uint16_t in_streams;
uint16_t out_streams;
/* Local address to bind to */
net_ip_address_t local_address;
/* Remote address to connect to */
net_ip_address_t remote_address;
/* Multi-socket descriptor */
int multi_sd;
} sctp_new_association_req_multi_t;
typedef struct sctp_init_msg_multi_cnf_s {
int multi_sd;
} sctp_init_msg_multi_cnf_t;
typedef struct sctp_new_association_ind_s {
/* Assoc id of the new association */
int32_t assoc_id;
+21
View File
@@ -19,3 +19,24 @@
* contact@openairinterface.org
*/
/* eNB application layer -> X2AP messages */
/* ITTI LOG messages */
/* ENCODER */
MESSAGE_DEF(X2AP_RESET_REQUST_LOG , MESSAGE_PRIORITY_MED, IttiMsgText , x2ap_reset_request_log)
MESSAGE_DEF(X2AP_RESOURCE_STATUS_RESPONSE_LOG , MESSAGE_PRIORITY_MED, IttiMsgText , x2ap_resource_status_response_log)
MESSAGE_DEF(X2AP_RESOURCE_STATUS_FAILURE_LOG , MESSAGE_PRIORITY_MED, IttiMsgText , x2ap_resource_status_failure_log)
/* Messages for X2AP logging */
MESSAGE_DEF(X2AP_SETUP_REQUEST_LOG , MESSAGE_PRIORITY_MED, IttiMsgText , x2ap_setup_request_log)
/* eNB application layer -> X2AP messages */
MESSAGE_DEF(X2AP_REGISTER_ENB_REQ , MESSAGE_PRIORITY_MED, x2ap_register_enb_req_t , x2ap_register_enb_req)
/* X2AP -> eNB application layer messages */
MESSAGE_DEF(X2AP_REGISTER_ENB_CNF , MESSAGE_PRIORITY_MED, x2ap_register_enb_cnf_t , x2ap_register_enb_cnf)
MESSAGE_DEF(X2AP_DEREGISTERED_ENB_IND , MESSAGE_PRIORITY_MED, x2ap_deregistered_enb_ind_t , x2ap_deregistered_enb_ind)
/* handover messages X2AP <-> RRC */
MESSAGE_DEF(X2AP_HANDOVER_REQ , MESSAGE_PRIORITY_MED, x2ap_handover_req_t , x2ap_handover_req)
MESSAGE_DEF(X2AP_HANDOVER_REQ_ACK , MESSAGE_PRIORITY_MED, x2ap_handover_req_ack_t , x2ap_handover_req_ack)
+159
View File
@@ -19,3 +19,162 @@
* contact@openairinterface.org
*/
#ifndef X2AP_MESSAGES_TYPES_H_
#define X2AP_MESSAGES_TYPES_H_
#include "PhysCellId.h"
//-------------------------------------------------------------------------------------------//
// Defines to access message fields.
#define X2AP_REGISTER_ENB_REQ(mSGpTR) (mSGpTR)->ittiMsg.x2ap_register_enb_req
#define X2AP_HANDOVER_REQ(mSGpTR) (mSGpTR)->ittiMsg.x2ap_handover_req
#define X2AP_HANDOVER_REQ_ACK(mSGpTR) (mSGpTR)->ittiMsg.x2ap_handover_req_ack
#define X2AP_REGISTER_ENB_CNF(mSGpTR) (mSGpTR)->ittiMsg.x2ap_register_enb_cnf
#define X2AP_DEREGISTERED_ENB_IND(mSGpTR) (mSGpTR)->ittiMsg.x2ap_deregistered_enb_ind
#define X2AP_MAX_NB_ENB_IP_ADDRESS 2
// eNB application layer -> X2AP messages
typedef struct x2ap_register_enb_req_s {
/* Unique eNB_id to identify the eNB within EPC.
* For macro eNB ids this field should be 20 bits long.
* For home eNB ids this field should be 28 bits long.
*/
uint32_t eNB_id;
/* The type of the cell */
enum cell_type_e cell_type;
/* Optional name for the cell
* NOTE: the name can be NULL (i.e no name) and will be cropped to 150
* characters.
*/
char *eNB_name;
/* Tracking area code */
uint16_t tac;
/* Mobile Country Code
* Mobile Network Code
*/
uint16_t mcc;
uint16_t mnc;
uint8_t mnc_digit_length;
/*
* CC Params
*/
int16_t eutra_band[MAX_NUM_CCs];
uint32_t downlink_frequency[MAX_NUM_CCs];
int32_t uplink_frequency_offset[MAX_NUM_CCs];
uint32_t Nid_cell[MAX_NUM_CCs];
int16_t N_RB_DL[MAX_NUM_CCs];
lte_frame_type_t frame_type[MAX_NUM_CCs];
uint32_t fdd_earfcn_DL[MAX_NUM_CCs];
uint32_t fdd_earfcn_UL[MAX_NUM_CCs];
int num_cc;
/* To be considered for TDD */
//uint16_t tdd_EARFCN;
//uint16_t tdd_Transmission_Bandwidth;
/* The local eNB IP address to bind */
net_ip_address_t enb_x2_ip_address;
/* Nb of MME to connect to */
uint8_t nb_x2;
/* List of target eNB to connect to for X2*/
net_ip_address_t target_enb_x2_ip_address[X2AP_MAX_NB_ENB_IP_ADDRESS];
/* Number of SCTP streams used for associations */
uint16_t sctp_in_streams;
uint16_t sctp_out_streams;
/* eNB port for X2C*/
uint32_t enb_port_for_X2C;
} x2ap_register_enb_req_t;
//-------------------------------------------------------------------------------------------//
// X2AP -> eNB application layer messages
typedef struct x2ap_register_enb_cnf_s {
/* Nb of connected eNBs*/
uint8_t nb_x2;
} x2ap_register_enb_cnf_t;
typedef struct x2ap_deregistered_enb_ind_s {
/* Nb of connected eNBs */
uint8_t nb_x2;
} x2ap_deregistered_enb_ind_t;
//-------------------------------------------------------------------------------------------//
// X2AP <-> RRC
typedef struct x2ap_gummei_s {
uint16_t mcc;
uint16_t mnc;
uint8_t mnc_len;
uint8_t mme_code;
uint16_t mme_group_id;
} x2ap_gummei_t;
typedef struct x2ap_lastvisitedcell_info_s {
uint16_t mcc;
uint16_t mnc;
uint8_t mnc_len;
PhysCellId_t target_physCellId;
cell_type_t cell_type;
uint64_t time_UE_StayedInCell;
}x2ap_lastvisitedcell_info_t;
//used for src
typedef struct x2ap_handover_req_s {
int source_rnti; /* TODO: to be fixed/remove */
int source_x2id; /* TODO: to be fixed/remove */
unsigned old_eNB_ue_s1ap_id:24;
PhysCellId_t target_physCellId;
x2ap_gummei_t ue_gummei;
/*UE-ContextInformation */
/* MME UE id */
uint32_t mme_ue_s1ap_id;
security_capabilities_t security_capabilities;
uint8_t kenb[32]; // keNB or keNB*
/*next_hop_chaining_coun */
long int kenb_ncc;
/* UE aggregate maximum bitrate */
ambr_t ue_ambr;
uint8_t nb_e_rabs_tobesetup;
/* list of e_rab setup-ed by RRC layers */
e_rab_setup_t e_rabs_tobesetup[S1AP_MAX_E_RAB];
/* ue_context_pP->ue_context.e_rab[i].param.sgw_addr; */
x2ap_lastvisitedcell_info_t lastvisitedcell_info;
/* TODO: this parameter has to be removed */
int target_mod_id;
} x2ap_handover_req_t;
typedef struct x2ap_handover_req_ack_s {
int source_rnti; /* TODO: to be fixed/remove */
int source_x2id; /* TODO: to be fixed/remove */
/* TODO: this parameter has to be removed */
int target_mod_id;
uint8_t rrc_buffer[1024 /* arbitrary, big enough */];
int rrc_buffer_size;
uint32_t mme_ue_s1ap_id;
} x2ap_handover_req_ack_t;
#endif /* X2AP_MESSAGES_TYPES_H_ */
@@ -38,7 +38,7 @@
#include "liblfds700.h"
#include "log.h"
#include "common/utils/LOG/log.h"
/*Flags showing if a mac agent has already been registered*/
unsigned int mac_agent_registered[NUM_MAX_ENB];
@@ -52,6 +52,18 @@ struct lfds700_misc_prng_state ps[NUM_MAX_ENB];
struct lfds700_ringbuffer_element *dl_mac_config_array[NUM_MAX_ENB];
struct lfds700_ringbuffer_state ringbuffer_state[NUM_MAX_ENB];
/* the slice config as kept in the underlying system */
Protocol__FlexSliceConfig *slice_config[MAX_NUM_SLICES];
/* a structure that keeps updates which will be reflected in slice_config later */
Protocol__FlexSliceConfig *sc_update[MAX_NUM_SLICES];
/* indicates whether sc_update contains new data */
int perform_slice_config_update_count = 1;
/* queue of incoming new UE<>slice association commands */
Protocol__FlexUeConfig *ue_slice_assoc_update[MAX_NUM_SLICES];
int n_ue_slice_assoc_updates = 0;
/* mutex for sc_update: do not receive new config and write it at the same time */
pthread_mutex_t sc_update_mtx = PTHREAD_MUTEX_INITIALIZER;
int flexran_agent_mac_stats_reply(mid_t mod_id,
const report_config_t *report_config,
@@ -61,6 +73,7 @@ int flexran_agent_mac_stats_reply(mid_t mod_id,
// Protocol__FlexHeader *header;
int i, j, k;
int UE_id;
int cc_id = 0;
int enb_id = mod_id;
@@ -70,6 +83,8 @@ int flexran_agent_mac_stats_reply(mid_t mod_id,
for (i = 0; i < report_config->nr_ue; i++) {
UE_id = flexran_get_ue_id(mod_id, i);
ue_report[i]->rnti = report_config->ue_report_type[i].ue_rnti;
ue_report[i]->has_rnti = 1;
@@ -91,7 +106,7 @@ int flexran_agent_mac_stats_reply(mid_t mod_id,
/* Check flag for creation of PHR report */
if (report_config->ue_report_type[i].ue_report_flags & PROTOCOL__FLEX_UE_STATS_TYPE__FLUST_PHR) {
ue_report[i]->phr = flexran_get_ue_phr (enb_id, i); // eNB_UE_list->UE_template[UE_PCCID(enb_id,i)][i].phr_info;
ue_report[i]->phr = flexran_get_ue_phr (enb_id, UE_id); // eNB_UE_list->UE_template[UE_PCCID(enb_id,UE_id)][UE_id].phr_info;
ue_report[i]->has_phr = 1;
}
@@ -113,11 +128,11 @@ int flexran_agent_mac_stats_reply(mid_t mod_id,
protocol__flex_rlc_bsr__init(rlc_reports[j]);
rlc_reports[j]->lc_id = j+1;
rlc_reports[j]->has_lc_id = 1;
rlc_reports[j]->tx_queue_size = flexran_get_tx_queue_size(enb_id, i, j + 1);
rlc_reports[j]->tx_queue_size = flexran_get_tx_queue_size(enb_id, UE_id, j + 1);
rlc_reports[j]->has_tx_queue_size = 1;
//TODO:Set tx queue head of line delay in ms
rlc_reports[j]->tx_queue_hol_delay = flexran_get_hol_delay(enb_id, i, j + 1);
rlc_reports[j]->tx_queue_hol_delay = flexran_get_hol_delay(enb_id, UE_id, j + 1);
rlc_reports[j]->has_tx_queue_hol_delay = 1;
//TODO:Set retransmission queue size in bytes
rlc_reports[j]->retransmission_queue_size = 10;
@@ -126,7 +141,7 @@ int flexran_agent_mac_stats_reply(mid_t mod_id,
rlc_reports[j]->retransmission_queue_hol_delay = 100;
rlc_reports[j]->has_retransmission_queue_hol_delay = 0;
//TODO DONE:Set current size of the pending message in bytes
rlc_reports[j]->status_pdu_size = flexran_get_num_pdus_buffer(enb_id , i, j + 1);
rlc_reports[j]->status_pdu_size = flexran_get_num_pdus_buffer(enb_id, UE_id, j + 1);
rlc_reports[j]->has_status_pdu_size = 1;
}
@@ -140,7 +155,7 @@ int flexran_agent_mac_stats_reply(mid_t mod_id,
/* Check flag for creation of MAC CE buffer status report */
if (report_config->ue_report_type[i].ue_report_flags & PROTOCOL__FLEX_UE_STATS_TYPE__FLUST_MAC_CE_BS) {
// TODO: Fill in the actual MAC CE buffer status report
ue_report[i]->pending_mac_ces = (flexran_get_MAC_CE_bitmap_TA(enb_id,i,0) | (0 << 1) | (0 << 2) | (0 << 3)) & 15;
ue_report[i]->pending_mac_ces = (flexran_get_MAC_CE_bitmap_TA(enb_id, UE_id, 0) | (0 << 1) | (0 << 2) | (0 << 3)) & 15;
// Use as bitmap. Set one or more of the; /* Use as bitmap. Set one or more of the
// PROTOCOL__FLEX_CE_TYPE__FLPCET_ values
// found in stats_common.pb-c.h. See
@@ -161,7 +176,7 @@ int flexran_agent_mac_stats_reply(mid_t mod_id,
dl_report->sfn_sn = flexran_get_sfn_sf(enb_id);
dl_report->has_sfn_sn = 1;
//Set the number of DL CQI reports for this UE. One for each CC
dl_report->n_csi_report = flexran_get_active_CC(enb_id,i);
dl_report->n_csi_report = flexran_get_active_CC(enb_id, UE_id);
dl_report->n_csi_report = 1 ;
//Create the actual CSI reports.
Protocol__FlexDlCsi **csi_reports;
@@ -178,7 +193,7 @@ int flexran_agent_mac_stats_reply(mid_t mod_id,
csi_reports[j]->serv_cell_index = j;
csi_reports[j]->has_serv_cell_index = 1;
//The rank indicator value for this cc
csi_reports[j]->ri = flexran_get_current_RI(enb_id,i,j);
csi_reports[j]->ri = flexran_get_current_RI(enb_id, UE_id, j);
csi_reports[j]->has_ri = 1;
//TODO: the type of CSI report based on the configuration of the UE
//For now we only support type P10, which only needs a wideband value
@@ -197,7 +212,7 @@ int flexran_agent_mac_stats_reply(mid_t mod_id,
protocol__flex_csi_p10__init(csi10);
//TODO: set the wideband value
// NN: this is also depends on cc_id
csi10->wb_cqi = flexran_get_ue_wcqi (enb_id, i); //eNB_UE_list->eNB_UE_stats[UE_PCCID(enb_id,i)][i].dl_cqi;
csi10->wb_cqi = flexran_get_ue_wcqi (enb_id, UE_id); //eNB_UE_list->eNB_UE_stats[UE_PCCID(enb_id,UE_id)][UE_id].dl_cqi;
csi10->has_wb_cqi = 1;
//Add the type of measurements to the csi report in the proper union type
csi_reports[j]->p10csi = csi10;
@@ -214,26 +229,26 @@ int flexran_agent_mac_stats_reply(mid_t mod_id,
csi11->wb_cqi = malloc(sizeof(csi11->wb_cqi));
csi11->n_wb_cqi = 1;
csi11->wb_cqi[0] = flexran_get_ue_wcqi (enb_id, i);
csi11->wb_cqi[0] = flexran_get_ue_wcqi (enb_id, UE_id);
// According To spec 36.213
if (flexran_get_antenna_ports(enb_id, j) == 2 && csi_reports[j]->ri == 1) {
// TODO PMI
csi11->wb_pmi = flexran_get_ue_wpmi(enb_id, i, 0);
csi11->wb_pmi = flexran_get_ue_wpmi(enb_id, UE_id, 0);
csi11->has_wb_pmi = 1;
}
else if (flexran_get_antenna_ports(enb_id, j) == 2 && csi_reports[j]->ri == 2){
// TODO PMI
csi11->wb_pmi = flexran_get_ue_wpmi(enb_id, i, 0);
csi11->wb_pmi = flexran_get_ue_wpmi(enb_id, UE_id, 0);
csi11->has_wb_pmi = 1;
}
else if (flexran_get_antenna_ports(enb_id, j) == 4 && csi_reports[j]->ri == 2){
// TODO PMI
csi11->wb_pmi = flexran_get_ue_wpmi(enb_id, i, 0);
csi11->wb_pmi = flexran_get_ue_wpmi(enb_id, UE_id, 0);
csi11->has_wb_pmi = 1;
@@ -257,7 +272,7 @@ int flexran_agent_mac_stats_reply(mid_t mod_id,
goto error;
protocol__flex_csi_p20__init(csi20);
csi20->wb_cqi = flexran_get_ue_wcqi (enb_id, i);
csi20->wb_cqi = flexran_get_ue_wcqi (enb_id, UE_id);
csi20->has_wb_cqi = 1;
@@ -281,7 +296,7 @@ int flexran_agent_mac_stats_reply(mid_t mod_id,
// goto error;
// protocol__flex_csi_p21__init(csi21);
// csi21->wb_cqi = flexran_get_ue_wcqi (enb_id, i);
// csi21->wb_cqi = flexran_get_ue_wcqi (enb_id, UE_id);
// csi21->wb_pmi = flexran_get_ue_pmi(enb_id); //TDO inside
@@ -309,7 +324,7 @@ int flexran_agent_mac_stats_reply(mid_t mod_id,
// goto error;
// protocol__flex_csi_a12__init(csi12);
// csi12->wb_cqi = flexran_get_ue_wcqi (enb_id, i);
// csi12->wb_cqi = flexran_get_ue_wcqi (enb_id, UE_id);
// csi12->sb_pmi = 1 ; //TODO inside
@@ -324,17 +339,17 @@ int flexran_agent_mac_stats_reply(mid_t mod_id,
// goto error;
// protocol__flex_csi_a22__init(csi22);
// csi22->wb_cqi = flexran_get_ue_wcqi (enb_id, i);
// csi22->wb_cqi = flexran_get_ue_wcqi (enb_id, UE_id);
// csi22->sb_cqi = 1 ; //TODO inside
// csi22->wb_pmi = flexran_get_ue_wcqi (enb_id, i);
// csi22->wb_pmi = flexran_get_ue_wcqi (enb_id, UE_id);
// csi22->has_wb_pmi = 1;
// csi22->sb_pmi = 1 ; //TODO inside
// csi22->has_wb_pmi = 1;
// csi22->sb_list = flexran_get_ue_wcqi (enb_id, i);
// csi22->sb_list = flexran_get_ue_wcqi (enb_id, UE_id);
}
@@ -347,7 +362,7 @@ int flexran_agent_mac_stats_reply(mid_t mod_id,
// goto error;
// protocol__flex_csi_a20__init(csi20);
// csi20->wb_cqi = flexran_get_ue_wcqi (enb_id, i);
// csi20->wb_cqi = flexran_get_ue_wcqi (enb_id, UE_id);
// csi20->has_wb_cqi = 1;
// csi20>sb_cqi = 1 ; //TODO inside
@@ -477,8 +492,8 @@ int flexran_agent_mac_stats_reply(mid_t mod_id,
full_ul_report->pucch_dbm[j]->has_serv_cell_index = 1;
full_ul_report->pucch_dbm[j]->serv_cell_index = j;
if(flexran_get_p0_pucch_dbm(enb_id,i, j) != -1){
full_ul_report->pucch_dbm[j]->p0_pucch_dbm = flexran_get_p0_pucch_dbm(enb_id,i,j);
if(flexran_get_p0_pucch_dbm(enb_id, UE_id, j) != -1){
full_ul_report->pucch_dbm[j]->p0_pucch_dbm = flexran_get_p0_pucch_dbm(enb_id, UE_id, j);
full_ul_report->pucch_dbm[j]->has_p0_pucch_dbm = 1;
}
}
@@ -499,69 +514,69 @@ int flexran_agent_mac_stats_reply(mid_t mod_id,
protocol__flex_mac_stats__init(macstats);
macstats->total_bytes_sdus_dl = flexran_get_total_size_dl_mac_sdus(mod_id, i, cc_id);
macstats->total_bytes_sdus_dl = flexran_get_total_size_dl_mac_sdus(mod_id, UE_id, cc_id);
macstats->has_total_bytes_sdus_dl = 1;
macstats->total_bytes_sdus_ul = flexran_get_total_size_ul_mac_sdus(mod_id, i, cc_id);
macstats->total_bytes_sdus_ul = flexran_get_total_size_ul_mac_sdus(mod_id, UE_id, cc_id);
macstats->has_total_bytes_sdus_ul = 1;
macstats->tbs_dl = flexran_get_TBS_dl(mod_id, i, cc_id);
macstats->tbs_dl = flexran_get_TBS_dl(mod_id, UE_id, cc_id);
macstats->has_tbs_dl = 1;
macstats->tbs_ul = flexran_get_TBS_ul(mod_id, i, cc_id);
macstats->tbs_ul = flexran_get_TBS_ul(mod_id, UE_id, cc_id);
macstats->has_tbs_ul = 1;
macstats->prb_retx_dl = flexran_get_num_prb_retx_dl_per_ue(mod_id, i, cc_id);
macstats->prb_retx_dl = flexran_get_num_prb_retx_dl_per_ue(mod_id, UE_id, cc_id);
macstats->has_prb_retx_dl = 1;
macstats->prb_retx_ul = flexran_get_num_prb_retx_ul_per_ue(mod_id, i, cc_id);
macstats->prb_retx_ul = flexran_get_num_prb_retx_ul_per_ue(mod_id, UE_id, cc_id);
macstats->has_prb_retx_ul = 1;
macstats->prb_dl = flexran_get_num_prb_dl_tx_per_ue(mod_id, i, cc_id);
macstats->prb_dl = flexran_get_num_prb_dl_tx_per_ue(mod_id, UE_id, cc_id);
macstats->has_prb_dl = 1;
macstats->prb_ul = flexran_get_num_prb_ul_rx_per_ue(mod_id, i, cc_id);
macstats->prb_ul = flexran_get_num_prb_ul_rx_per_ue(mod_id, UE_id, cc_id);
macstats->has_prb_ul = 1;
macstats->mcs1_dl = flexran_get_mcs1_dl(mod_id, i, cc_id);
macstats->mcs1_dl = flexran_get_mcs1_dl(mod_id, UE_id, cc_id);
macstats->has_mcs1_dl = 1;
macstats->mcs2_dl = flexran_get_mcs2_dl(mod_id, i, cc_id);
macstats->mcs2_dl = flexran_get_mcs2_dl(mod_id, UE_id, cc_id);
macstats->has_mcs2_dl = 1;
macstats->mcs1_ul = flexran_get_mcs1_ul(mod_id, i, cc_id);
macstats->mcs1_ul = flexran_get_mcs1_ul(mod_id, UE_id, cc_id);
macstats->has_mcs1_ul = 1;
macstats->mcs2_ul = flexran_get_mcs2_ul(mod_id, i, cc_id);
macstats->mcs2_ul = flexran_get_mcs2_ul(mod_id, UE_id, cc_id);
macstats->has_mcs2_ul = 1;
macstats->total_prb_dl = flexran_get_total_prb_dl_tx_per_ue(mod_id, i, cc_id);
macstats->total_prb_dl = flexran_get_total_prb_dl_tx_per_ue(mod_id, UE_id, cc_id);
macstats->has_total_prb_dl = 1;
macstats->total_prb_ul = flexran_get_total_prb_ul_rx_per_ue(mod_id, i, cc_id);
macstats->total_prb_ul = flexran_get_total_prb_ul_rx_per_ue(mod_id, UE_id, cc_id);
macstats->has_total_prb_ul = 1;
macstats->total_pdu_dl = flexran_get_total_num_pdu_dl(mod_id, i, cc_id);
macstats->total_pdu_dl = flexran_get_total_num_pdu_dl(mod_id, UE_id, cc_id);
macstats->has_total_pdu_dl = 1;
macstats->total_pdu_ul = flexran_get_total_num_pdu_ul(mod_id, i, cc_id);
macstats->total_pdu_ul = flexran_get_total_num_pdu_ul(mod_id, UE_id, cc_id);
macstats->has_total_pdu_ul = 1;
macstats->total_tbs_dl = flexran_get_total_TBS_dl(mod_id, i, cc_id);
macstats->total_tbs_dl = flexran_get_total_TBS_dl(mod_id, UE_id, cc_id);
macstats->has_total_tbs_dl = 1;
macstats->total_tbs_ul = flexran_get_total_TBS_ul(mod_id, i, cc_id);
macstats->total_tbs_ul = flexran_get_total_TBS_ul(mod_id, UE_id, cc_id);
macstats->has_total_tbs_ul = 1;
macstats->harq_round = flexran_get_harq_round(mod_id, cc_id, i);
macstats->harq_round = flexran_get_harq_round(mod_id, cc_id, UE_id);
macstats->has_harq_round = 1;
Protocol__FlexMacSdusDl ** mac_sdus;
mac_sdus = malloc(sizeof(Protocol__FlexMacSdusDl) * flexran_get_num_mac_sdu_tx(mod_id, i, cc_id));
mac_sdus = malloc(sizeof(Protocol__FlexMacSdusDl) * flexran_get_num_mac_sdu_tx(mod_id, UE_id, cc_id));
if (mac_sdus == NULL)
goto error;
macstats->n_mac_sdus_dl = flexran_get_num_mac_sdu_tx(mod_id, i, cc_id);
macstats->n_mac_sdus_dl = flexran_get_num_mac_sdu_tx(mod_id, UE_id, cc_id);
for (j = 0; j < macstats->n_mac_sdus_dl; j++){
@@ -569,10 +584,10 @@ int flexran_agent_mac_stats_reply(mid_t mod_id,
mac_sdus[j] = malloc(sizeof(Protocol__FlexMacSdusDl));
protocol__flex_mac_sdus_dl__init(mac_sdus[j]);
mac_sdus[j]->lcid = flexran_get_mac_sdu_lcid_index(mod_id, i, cc_id, j);
mac_sdus[j]->lcid = flexran_get_mac_sdu_lcid_index(mod_id, UE_id, cc_id, j);
mac_sdus[j]->has_lcid = 1;
mac_sdus[j]->sdu_length = flexran_get_mac_sdu_size(mod_id, i, cc_id, mac_sdus[j]->lcid);
mac_sdus[j]->sdu_length = flexran_get_mac_sdu_size(mod_id, UE_id, cc_id, mac_sdus[j]->lcid);
mac_sdus[j]->has_sdu_length = 1;
@@ -882,7 +897,6 @@ int flexran_agent_mac_sf_trigger(mid_t mod_id, const void *params, Protocol__Fle
for (j = 0; j < 8; j++) {
if (RC.mac && RC.mac[mod_id] && RC.mac[mod_id]->UE_list.eNB_UE_stats[UE_PCCID(mod_id,i)][i].harq_pid == 1) {
available_harq[i] = j;
sf_trigger_msg->n_dl_info++;
break;
}
}
@@ -891,10 +905,7 @@ int flexran_agent_mac_sf_trigger(mid_t mod_id, const void *params, Protocol__Fle
// LOG_I(FLEXRAN_AGENT, "Sending subframe trigger for frame %d and subframe %d\n", flexran_get_current_frame(mod_id), (flexran_get_current_subframe(mod_id) + 1) % 10);
/*TODO: Fill in the number of dl HARQ related info, based on the number of currently
*transmitting UEs
*/
// sf_trigger_msg->n_dl_info = flexran_get_num_ues(mod_id);
sf_trigger_msg->n_dl_info = flexran_get_num_ues(mod_id);
Protocol__FlexDlInfo **dl_info = NULL;
@@ -904,33 +915,31 @@ int flexran_agent_mac_sf_trigger(mid_t mod_id, const void *params, Protocol__Fle
goto error;
i = -1;
//Fill the status of the current HARQ process for each UE
for(UE_id = 0; UE_id < MAX_MOBILES_PER_ENB; UE_id++) {
if (available_harq[UE_id] < 0) {
for(i = 0; i < sf_trigger_msg->n_dl_info; i++) {
if (available_harq[i] < 0)
continue;
} else {
i++;
}
dl_info[i] = malloc(sizeof(Protocol__FlexDlInfo));
if(dl_info[i] == NULL)
goto error;
UE_id = flexran_get_ue_id(mod_id, i);
protocol__flex_dl_info__init(dl_info[i]);
dl_info[i]->rnti = flexran_get_ue_crnti(mod_id, UE_id);
dl_info[i]->has_rnti = 1;
/*Fill in the right id of this round's HARQ process for this UE*/
// uint8_t harq_id;
//uint8_t harq_status;
// flexran_get_harq(mod_id, UE_PCCID(mod_id,i), i, frame, subframe, &harq_id, &harq_status);
// flexran_get_harq(mod_id, UE_PCCID(mod_id, UE_id), i, frame, subframe, &harq_id, &harq_status);
dl_info[i]->harq_process_id = available_harq[UE_id];
if (RC.mac && RC.mac[mod_id])
RC.mac[mod_id]->UE_list.eNB_UE_stats[UE_PCCID(mod_id,i)][UE_id].harq_pid = 0;
RC.mac[mod_id]->UE_list.eNB_UE_stats[UE_PCCID(mod_id, UE_id)][UE_id].harq_pid = 0;
dl_info[i]->has_harq_process_id = 1;
/* Fill in the status of the HARQ process (2 TBs)*/
dl_info[i]->n_harq_status = 2;
dl_info[i]->harq_status = malloc(sizeof(uint32_t) * dl_info[i]->n_harq_status);
for (j = 0; j < dl_info[i]->n_harq_status; j++) {
dl_info[i]->harq_status[j] = RC.mac[mod_id]->UE_list.UE_sched_ctrl[i].round[UE_PCCID(mod_id,i)][j];
dl_info[i]->harq_status[j] = RC.mac[mod_id]->UE_list.UE_sched_ctrl[UE_id].round[UE_PCCID(mod_id, UE_id)][j];
// TODO: This should be different per TB
}
// LOG_I(FLEXRAN_AGENT, "Sending subframe trigger for frame %d and subframe %d and harq %d (round %d)\n", flexran_get_current_frame(mod_id), (flexran_get_current_subframe(mod_id) + 1) % 10, dl_info[i]->harq_process_id, dl_info[i]->harq_status[0]);
@@ -938,7 +947,7 @@ int flexran_agent_mac_sf_trigger(mid_t mod_id, const void *params, Protocol__Fle
// LOG_I(FLEXRAN_AGENT, "[Frame %d][Subframe %d]Need to make a retransmission for harq %d (round %d)\n", flexran_get_current_frame(mod_id), flexran_get_current_subframe(mod_id), dl_info[i]->harq_process_id, dl_info[i]->harq_status[0]);
}
/*Fill in the serving cell index for this UE */
dl_info[i]->serv_cell_index = UE_PCCID(mod_id,i);
dl_info[i]->serv_cell_index = UE_PCCID(mod_id, UE_id);
dl_info[i]->has_serv_cell_index = 1;
}
}
@@ -962,18 +971,21 @@ int flexran_agent_mac_sf_trigger(mid_t mod_id, const void *params, Protocol__Fle
if(ul_info[i] == NULL)
goto error;
protocol__flex_ul_info__init(ul_info[i]);
ul_info[i]->rnti = flexran_get_ue_crnti(mod_id, i);
UE_id = flexran_get_ue_id(mod_id, i);
ul_info[i]->rnti = flexran_get_ue_crnti(mod_id, UE_id);
ul_info[i]->has_rnti = 1;
/* Fill in the Tx power control command for this UE (if available),
* primary carrier */
if(flexran_get_tpc(mod_id, i, 0) != 1){
if(flexran_get_tpc(mod_id, UE_id, 0) != 1){
/* assume primary carrier */
ul_info[i]->tpc = flexran_get_tpc(mod_id, i, 0);
ul_info[i]->tpc = flexran_get_tpc(mod_id, UE_id, 0);
ul_info[i]->has_tpc = 1;
}
else{
/* assume primary carrier */
ul_info[i]->tpc = flexran_get_tpc(mod_id, i, 0);
ul_info[i]->tpc = flexran_get_tpc(mod_id, UE_id, 0);
ul_info[i]->has_tpc = 0;
}
/*TODO: fill in the amount of data in bytes in the MAC SDU received in this subframe for the
@@ -987,7 +999,7 @@ int flexran_agent_mac_sf_trigger(mid_t mod_id, const void *params, Protocol__Fle
ul_info[i]->reception_status = PROTOCOL__FLEX_RECEPTION_STATUS__FLRS_OK;
ul_info[i]->has_reception_status = 1;
/*Fill in the serving cell index for this UE */
ul_info[i]->serv_cell_index = UE_PCCID(mod_id,i);
ul_info[i]->serv_cell_index = UE_PCCID(mod_id, UE_id);
ul_info[i]->has_serv_cell_index = 1;
}
}
@@ -1260,8 +1272,17 @@ void flexran_agent_init_mac_agent(mid_t mod_id) {
lfds700_misc_prng_init(&ps[mod_id]);
int num_elements = RINGBUFFER_SIZE + 1;
//Allow RINGBUFFER_SIZE messages to be stored in the ringbuffer at any time
dl_mac_config_array[mod_id] = malloc( sizeof(struct lfds700_ringbuffer_element) * num_elements);
lfds700_ringbuffer_init_valid_on_current_logical_core( &ringbuffer_state[mod_id], dl_mac_config_array[mod_id], num_elements, &ps[mod_id], NULL );
/* lfds700_ringbuffer_init_valid_on_current_logical_core()'s second argument
* must be aligned to LFDS700_PAL_ATOMIC_ISOLATION_IN_BYTES. From the
* documentation: "Heap allocated variables however will by no means be
* correctly aligned and an aligned malloc must be used." Therefore, we use
* posix_memalign */
i = posix_memalign((void **)&dl_mac_config_array[mod_id],
LFDS700_PAL_ATOMIC_ISOLATION_IN_BYTES,
sizeof(struct lfds700_ringbuffer_element) * num_elements);
AssertFatal(i == 0, "posix_memalign(): could not allocate aligned memory for lfds library\n");
lfds700_ringbuffer_init_valid_on_current_logical_core(&ringbuffer_state[mod_id],
dl_mac_config_array[mod_id], num_elements, &ps[mod_id], NULL);
for (i = 0; i < MAX_MOBILES_PER_ENB; i++) {
for (j = 0; j < 8; j++) {
if (RC.mac && RC.mac[mod_id])
@@ -1372,8 +1393,229 @@ int flexran_agent_unregister_mac_xface(mid_t mod_id, AGENT_MAC_xface *xface) {
return 0;
}
void flexran_create_config_structures(mid_t mod_id)
{
int i;
int n_dl = flexran_get_num_dl_slices(mod_id);
int m_ul = flexran_get_num_ul_slices(mod_id);
slice_config[mod_id] = flexran_agent_create_slice_config(n_dl, m_ul);
sc_update[mod_id] = flexran_agent_create_slice_config(n_dl, m_ul);
if (!slice_config[mod_id] || !sc_update[mod_id]) return;
flexran_agent_read_slice_config(mod_id, slice_config[mod_id]);
flexran_agent_read_slice_config(mod_id, sc_update[mod_id]);
for (i = 0; i < n_dl; i++) {
flexran_agent_read_slice_dl_config(mod_id, i, slice_config[mod_id]->dl[i]);
flexran_agent_read_slice_dl_config(mod_id, i, sc_update[mod_id]->dl[i]);
}
for (i = 0; i < m_ul; i++) {
flexran_agent_read_slice_ul_config(mod_id, i, slice_config[mod_id]->ul[i]);
flexran_agent_read_slice_ul_config(mod_id, i, sc_update[mod_id]->ul[i]);
}
}
void flexran_check_and_remove_slices(mid_t mod_id)
{
Protocol__FlexDlSlice **dl = sc_update[mod_id]->dl;
Protocol__FlexDlSlice **dlreal = slice_config[mod_id]->dl;
int i = 0;
while (i < sc_update[mod_id]->n_dl) {
/* remove slices whose percentage is zero */
if (dl[i]->percentage > 0) {
++i;
continue;
}
if (flexran_remove_dl_slice(mod_id, i) < 1) {
LOG_W(FLEXRAN_AGENT, "[%d] can not remove slice index %d ID %d\n",
mod_id, i, dl[i]->id);
++i;
continue;
}
LOG_I(FLEXRAN_AGENT, "[%d] removed slice index %d ID %d\n",
mod_id, i, dl[i]->id);
if (dl[i]->n_sorting > 0) free(dl[i]->sorting);
free(dl[i]->scheduler_name);
if (dlreal[i]->n_sorting > 0) {
dlreal[i]->n_sorting = 0;
free(dlreal[i]->sorting);
}
free(dlreal[i]->scheduler_name);
--sc_update[mod_id]->n_dl;
--slice_config[mod_id]->n_dl;
const size_t last = sc_update[mod_id]->n_dl;
/* we need to memcpy the higher slice to the position we just deleted */
memcpy(dl[i], dl[last], sizeof(*dl[last]));
memset(dl[last], 0, sizeof(*dl[last]));
memcpy(dlreal[i], dlreal[last], sizeof(*dlreal[last]));
memset(dlreal[last], 0, sizeof(*dlreal[last]));
/* dont increase i but recheck the slice which has been copied to here */
}
Protocol__FlexUlSlice **ul = sc_update[mod_id]->ul;
Protocol__FlexUlSlice **ulreal = slice_config[mod_id]->ul;
i = 0;
while (i < sc_update[mod_id]->n_ul) {
if (ul[i]->percentage > 0) {
++i;
continue;
}
if (flexran_remove_ul_slice(mod_id, i) < 1) {
LOG_W(FLEXRAN_AGENT, "[%d] can not remove slice index %d ID %d\n",
mod_id, i, ul[i]->id);
++i;
continue;
}
LOG_I(FLEXRAN_AGENT, "[%d] removed slice index %d ID %d\n",
mod_id, i, ul[i]->id);
free(ul[i]->scheduler_name);
free(ulreal[i]->scheduler_name);
--sc_update[mod_id]->n_ul;
--slice_config[mod_id]->n_ul;
const size_t last = sc_update[mod_id]->n_ul;
/* see DL remarks */
memcpy(ul[i], ul[last], sizeof(*ul[last]));
memset(ul[last], 0, sizeof(*ul[last]));
memcpy(ulreal[i], ulreal[last], sizeof(*ulreal[last]));
memset(ulreal[last], 0, sizeof(*ulreal[last]));
/* dont increase i but recheck the slice which has been copied to here */
}
}
void flexran_agent_slice_update(mid_t mod_id)
{
int i;
int changes = 0;
if (perform_slice_config_update_count <= 0) return;
perform_slice_config_update_count--;
pthread_mutex_lock(&sc_update_mtx);
if (!slice_config[mod_id]) {
/* if the configuration does not exist for agent, create from eNB structure
* and exit */
flexran_create_config_structures(mod_id);
pthread_mutex_unlock(&sc_update_mtx);
return;
}
/********* read existing config *********/
/* simply update slice_config all the time and write new config
* (apply_new_slice_dl_config() only updates if changes are necessary) */
slice_config[mod_id]->n_dl = flexran_get_num_dl_slices(mod_id);
slice_config[mod_id]->n_ul = flexran_get_num_ul_slices(mod_id);
for (i = 0; i < slice_config[mod_id]->n_dl; i++) {
flexran_agent_read_slice_dl_config(mod_id, i, slice_config[mod_id]->dl[i]);
}
for (i = 0; i < slice_config[mod_id]->n_ul; i++) {
flexran_agent_read_slice_ul_config(mod_id, i, slice_config[mod_id]->ul[i]);
}
/********* write new config *********/
/* check for removal (sc_update[X]->dl[Y].percentage == 0)
* and update sc_update & slice_config accordingly */
flexran_check_and_remove_slices(mod_id);
/* create new DL and UL slices if necessary */
for (i = slice_config[mod_id]->n_dl; i < sc_update[mod_id]->n_dl; i++) {
flexran_create_dl_slice(mod_id, sc_update[mod_id]->dl[i]->id);
}
for (i = slice_config[mod_id]->n_ul; i < sc_update[mod_id]->n_ul; i++) {
flexran_create_ul_slice(mod_id, sc_update[mod_id]->ul[i]->id);
}
slice_config[mod_id]->n_dl = flexran_get_num_dl_slices(mod_id);
slice_config[mod_id]->n_ul = flexran_get_num_ul_slices(mod_id);
changes += apply_new_slice_config(mod_id, slice_config[mod_id], sc_update[mod_id]);
for (i = 0; i < slice_config[mod_id]->n_dl; i++) {
changes += apply_new_slice_dl_config(mod_id,
slice_config[mod_id]->dl[i],
sc_update[mod_id]->dl[i]);
flexran_agent_read_slice_dl_config(mod_id, i, slice_config[mod_id]->dl[i]);
}
for (i = 0; i < slice_config[mod_id]->n_ul; i++) {
changes += apply_new_slice_ul_config(mod_id,
slice_config[mod_id]->ul[i],
sc_update[mod_id]->ul[i]);
flexran_agent_read_slice_ul_config(mod_id, i, slice_config[mod_id]->ul[i]);
}
flexran_agent_read_slice_config(mod_id, slice_config[mod_id]);
if (n_ue_slice_assoc_updates > 0) {
changes += apply_ue_slice_assoc_update(mod_id);
}
if (changes > 0)
LOG_I(FLEXRAN_AGENT, "[%d] slice configuration: applied %d changes\n", mod_id, changes);
pthread_mutex_unlock(&sc_update_mtx);
}
Protocol__FlexSliceConfig *flexran_agent_get_slice_config(mid_t mod_id)
{
if (!slice_config[mod_id]) return NULL;
Protocol__FlexSliceConfig *config = NULL;
pthread_mutex_lock(&sc_update_mtx);
config = flexran_agent_create_slice_config(slice_config[mod_id]->n_dl,
slice_config[mod_id]->n_ul);
if (!config) {
pthread_mutex_unlock(&sc_update_mtx);
return NULL;
}
config->has_intraslice_share_active = 1;
config->intraslice_share_active = slice_config[mod_id]->intraslice_share_active;
config->has_interslice_share_active = 1;
config->interslice_share_active = slice_config[mod_id]->interslice_share_active;
for (int i = 0; i < slice_config[mod_id]->n_dl; ++i) {
if (!config->dl[i]) continue;
config->dl[i]->has_id = 1;
config->dl[i]->id = slice_config[mod_id]->dl[i]->id;
config->dl[i]->has_label = 1;
config->dl[i]->label = slice_config[mod_id]->dl[i]->label;
config->dl[i]->has_percentage = 1;
config->dl[i]->percentage = slice_config[mod_id]->dl[i]->percentage;
config->dl[i]->has_isolation = 1;
config->dl[i]->isolation = slice_config[mod_id]->dl[i]->isolation;
config->dl[i]->has_priority = 1;
config->dl[i]->priority = slice_config[mod_id]->dl[i]->priority;
config->dl[i]->has_position_low = 1;
config->dl[i]->position_low = slice_config[mod_id]->dl[i]->position_low;
config->dl[i]->has_position_high = 1;
config->dl[i]->position_high = slice_config[mod_id]->dl[i]->position_high;
config->dl[i]->has_maxmcs = 1;
config->dl[i]->maxmcs = slice_config[mod_id]->dl[i]->maxmcs;
config->dl[i]->n_sorting = slice_config[mod_id]->dl[i]->n_sorting;
config->dl[i]->sorting = calloc(config->dl[i]->n_sorting, sizeof(Protocol__FlexDlSorting));
if (!config->dl[i]->sorting) config->dl[i]->n_sorting = 0;
for (int j = 0; j < config->dl[i]->n_sorting; ++j)
config->dl[i]->sorting[j] = slice_config[mod_id]->dl[i]->sorting[j];
config->dl[i]->has_accounting = 1;
config->dl[i]->accounting = slice_config[mod_id]->dl[i]->accounting;
config->dl[i]->scheduler_name = strdup(slice_config[mod_id]->dl[i]->scheduler_name);
}
for (int i = 0; i < slice_config[mod_id]->n_ul; ++i) {
if (!config->ul[i]) continue;
config->ul[i]->has_id = 1;
config->ul[i]->id = slice_config[mod_id]->ul[i]->id;
config->ul[i]->has_label = 1;
config->ul[i]->label = slice_config[mod_id]->ul[i]->label;
config->ul[i]->has_percentage = 1;
config->ul[i]->percentage = slice_config[mod_id]->ul[i]->percentage;
config->ul[i]->has_isolation = 1;
config->ul[i]->isolation = slice_config[mod_id]->ul[i]->isolation;
config->ul[i]->has_priority = 1;
config->ul[i]->priority = slice_config[mod_id]->ul[i]->priority;
config->ul[i]->has_first_rb = 1;
config->ul[i]->first_rb = slice_config[mod_id]->ul[i]->first_rb;
config->ul[i]->has_maxmcs = 1;
config->ul[i]->maxmcs = slice_config[mod_id]->ul[i]->maxmcs;
config->ul[i]->n_sorting = slice_config[mod_id]->ul[i]->n_sorting;
config->ul[i]->sorting = calloc(config->ul[i]->n_sorting, sizeof(Protocol__FlexUlSorting));
if (!config->ul[i]->sorting) config->ul[i]->n_sorting = 0;
for (int j = 0; j < config->ul[i]->n_sorting; ++j)
config->ul[i]->sorting[j] = slice_config[mod_id]->ul[i]->sorting[j];
config->ul[i]->has_accounting = 1;
config->ul[i]->accounting = slice_config[mod_id]->ul[i]->accounting;
config->ul[i]->scheduler_name = strdup(slice_config[mod_id]->ul[i]->scheduler_name);
}
pthread_mutex_unlock(&sc_update_mtx);
return config;
}
@@ -87,4 +87,14 @@ int flexran_agent_register_mac_xface(mid_t mod_id, AGENT_MAC_xface *xface);
/*Unregister technology specific callbacks*/
int flexran_agent_unregister_mac_xface(mid_t mod_id, AGENT_MAC_xface*xface);
/***************************************
* FlexRAN agent - slice configuration *
***************************************/
/* Inform controller about possibility to update slice configuration */
void flexran_agent_slice_update(mid_t mod_id);
/* return a pointer to the current config */
Protocol__FlexSliceConfig *flexran_agent_get_slice_config(mid_t mod_id);
#endif
@@ -31,6 +31,15 @@
#include "flexran_agent_common_internal.h"
#include "flexran_agent_mac_internal.h"
#include "flexran_agent_mac_slice_verification.h"
/* from flexran_agent_mac.c */
extern Protocol__FlexSliceConfig *slice_config[MAX_NUM_SLICES];
extern Protocol__FlexSliceConfig *sc_update[MAX_NUM_SLICES];
extern int perform_slice_config_update_count;
extern Protocol__FlexUeConfig *ue_slice_assoc_update[MAX_NUM_SLICES];
extern int n_ue_slice_assoc_updates;
extern pthread_mutex_t sc_update_mtx;
Protocol__FlexranMessage * flexran_agent_generate_diff_mac_stats_report(Protocol__FlexranMessage *new_message,
Protocol__FlexranMessage *old_message) {
@@ -899,3 +908,721 @@ int load_dl_scheduler_function(mid_t mod_id, const char *function_name) {
return -1;
}
Protocol__FlexSliceConfig *flexran_agent_create_slice_config(int n_dl, int m_ul)
{
int i;
Protocol__FlexSliceConfig *fsc = malloc(sizeof(Protocol__FlexSliceConfig));
if (!fsc) return NULL;
protocol__flex_slice_config__init(fsc);
/* say there are n_dl slices but reserve memory for up to MAX_NUM_SLICES so
* we don't need to reserve again later */
fsc->n_dl = n_dl;
fsc->dl = calloc(MAX_NUM_SLICES, sizeof(Protocol__FlexDlSlice *));
if (!fsc->dl) fsc->n_dl = 0;
for (i = 0; i < MAX_NUM_SLICES; i++) {
fsc->dl[i] = malloc(sizeof(Protocol__FlexDlSlice));
if (!fsc->dl[i]) continue;
protocol__flex_dl_slice__init(fsc->dl[i]);
}
/* as above */
fsc->n_ul = m_ul;
fsc->ul = calloc(MAX_NUM_SLICES, sizeof(Protocol__FlexUlSlice *));
if (!fsc->ul) fsc->n_ul = 0;
for (i = 0; i < MAX_NUM_SLICES; i++) {
fsc->ul[i] = malloc(sizeof(Protocol__FlexUlSlice));
if (!fsc->ul[i]) continue;
protocol__flex_ul_slice__init(fsc->ul[i]);
}
return fsc;
}
void flexran_agent_read_slice_config(mid_t mod_id, Protocol__FlexSliceConfig *s)
{
s->intraslice_share_active = flexran_get_intraslice_sharing_active(mod_id);
s->has_intraslice_share_active = 1;
s->interslice_share_active = flexran_get_interslice_sharing_active(mod_id);
s->has_interslice_share_active = 1;
}
void flexran_agent_read_slice_dl_config(mid_t mod_id, int slice_idx, Protocol__FlexDlSlice *dl_slice)
{
dl_slice->id = flexran_get_dl_slice_id(mod_id, slice_idx);
dl_slice->has_id = 1;
/* read label from corresponding sc_update entry or give default */
dl_slice->label = PROTOCOL__FLEX_SLICE_LABEL__xMBB;
dl_slice->has_label = 1;
for (int i = 0; i < sc_update[mod_id]->n_dl; i++) {
if (sc_update[mod_id]->dl[i]->id == dl_slice->id
&& sc_update[mod_id]->dl[i]->has_label) {
dl_slice->label = sc_update[mod_id]->dl[i]->label;
break;
}
}
dl_slice->percentage = flexran_get_dl_slice_percentage(mod_id, slice_idx);
dl_slice->has_percentage = 1;
dl_slice->isolation = flexran_get_dl_slice_isolation(mod_id, slice_idx);
dl_slice->has_isolation = 1;
dl_slice->priority = flexran_get_dl_slice_priority(mod_id, slice_idx);
dl_slice->has_priority = 1;
dl_slice->position_low = flexran_get_dl_slice_position_low(mod_id, slice_idx);
dl_slice->has_position_low = 1;
dl_slice->position_high = flexran_get_dl_slice_position_high(mod_id, slice_idx);
dl_slice->has_position_high = 1;
dl_slice->maxmcs = flexran_get_dl_slice_maxmcs(mod_id, slice_idx);
dl_slice->has_maxmcs = 1;
dl_slice->n_sorting = flexran_get_dl_slice_sorting(mod_id, slice_idx, &dl_slice->sorting);
if (dl_slice->n_sorting < 1) dl_slice->sorting = NULL;
dl_slice->accounting = flexran_get_dl_slice_accounting_policy(mod_id, slice_idx);
dl_slice->has_accounting = 1;
const char *s_name = flexran_get_dl_slice_scheduler(mod_id, slice_idx);
if (!dl_slice->scheduler_name
|| strcmp(dl_slice->scheduler_name, s_name) != 0) {
dl_slice->scheduler_name = realloc(dl_slice->scheduler_name, strlen(s_name) + 1);
strcpy(dl_slice->scheduler_name, s_name);
}
}
void flexran_agent_read_slice_ul_config(mid_t mod_id, int slice_idx, Protocol__FlexUlSlice *ul_slice)
{
ul_slice->id = flexran_get_ul_slice_id(mod_id, slice_idx);
ul_slice->has_id = 1;
/* read label from corresponding sc_update entry or give default */
ul_slice->label = PROTOCOL__FLEX_SLICE_LABEL__xMBB;
ul_slice->has_label = 1;
for (int i = 0; i < sc_update[mod_id]->n_ul; i++) {
if (sc_update[mod_id]->ul[i]->id == ul_slice->id
&& sc_update[mod_id]->ul[i]->has_label) {
ul_slice->label = sc_update[mod_id]->ul[i]->label;
break;
}
}
ul_slice->percentage = flexran_get_ul_slice_percentage(mod_id, slice_idx);
ul_slice->has_percentage = 1;
/*ul_slice->isolation = flexran_get_ul_slice_isolation(mod_id, slice_idx);*/
ul_slice->has_isolation = 0;
/*ul_slice->priority = flexran_get_ul_slice_priority(mod_id, slice_idx);*/
ul_slice->has_priority = 0;
ul_slice->first_rb = flexran_get_ul_slice_first_rb(mod_id, slice_idx);
ul_slice->has_first_rb = 1;
/*ul_slice-> = flexran_get_ul_slice_length_rb(mod_id, slice_idx);
ul_slice->has_length_rb = 0;*/
ul_slice->maxmcs = flexran_get_ul_slice_maxmcs(mod_id, slice_idx);
ul_slice->has_maxmcs = 1;
ul_slice->n_sorting = 0;
/*if (ul_slice->sorting) {
free(ul_slice->sorting);
ul_slice->sorting = NULL;
}
ul_slice->n_sorting = flexran_get_ul_slice_sorting(mod_id, slice_idx, &ul_slice->sorting);
if (ul_slice->n_sorting < 1) ul_slice->sorting = NULL;*/
/*ul_slice->accounting = flexran_get_ul_slice_accounting_policy(mod_id, slice_idx);*/
ul_slice->has_accounting = 0;
const char *s_name = flexran_get_ul_slice_scheduler(mod_id, slice_idx);
if (!ul_slice->scheduler_name
|| strcmp(ul_slice->scheduler_name, s_name) != 0) {
ul_slice->scheduler_name = realloc(ul_slice->scheduler_name, strlen(s_name) + 1);
strcpy(ul_slice->scheduler_name, s_name);
}
}
int check_dl_sorting_update(Protocol__FlexDlSlice *old, Protocol__FlexDlSlice *new)
{
/* sorting_update => true when old->n_sorting == 0 or different numbers of
* elements; otherwise will check * element-wise */
int sorting_update = old->n_sorting == 0 || (old->n_sorting != new->n_sorting);
for (int i = 0; i < old->n_sorting && !sorting_update; ++i) {
sorting_update = sorting_update || (new->sorting[i] != old->sorting[i]);
}
return sorting_update;
}
int check_ul_sorting_update(Protocol__FlexUlSlice *old, Protocol__FlexUlSlice *new)
{
/* sorting_update => true when old->n_sorting == 0 or different numbers of
* elements; otherwise will check * element-wise */
int sorting_update = old->n_sorting == 0 || (old->n_sorting != new->n_sorting);
for (int i = 0; i < old->n_sorting && !sorting_update; ++i) {
sorting_update = sorting_update || (new->sorting[i] != old->sorting[i]);
}
return sorting_update;
}
void overwrite_slice_config(mid_t mod_id, Protocol__FlexSliceConfig *exist, Protocol__FlexSliceConfig *update)
{
if (update->has_intraslice_share_active
&& exist->intraslice_share_active != update->intraslice_share_active) {
LOG_I(FLEXRAN_AGENT, "[%d] update intraslice_share_active: %d -> %d\n",
mod_id, exist->intraslice_share_active, update->intraslice_share_active);
exist->intraslice_share_active = update->intraslice_share_active;
exist->has_intraslice_share_active = 1;
}
if (update->has_interslice_share_active
&& exist->interslice_share_active != update->interslice_share_active) {
LOG_I(FLEXRAN_AGENT, "[%d] update interslice_share_active: %d -> %d\n",
mod_id, exist->interslice_share_active, update->interslice_share_active);
exist->interslice_share_active = update->interslice_share_active;
exist->has_interslice_share_active = 1;
}
}
void overwrite_slice_config_dl(mid_t mod_id, Protocol__FlexDlSlice *exist, Protocol__FlexDlSlice *update)
{
if (update->label != exist->label) {
LOG_I(FLEXRAN_AGENT, "[%d][DL slice %d] update label: %d -> %d\n",
mod_id, update->id, exist->label, update->label);
exist->label = update->label;
exist->has_label = 1;
}
if (update->percentage != exist->percentage) {
LOG_I(FLEXRAN_AGENT, "[%d][DL slice %d] update percentage: %d -> %d\n",
mod_id, update->id, exist->percentage, update->percentage);
exist->percentage = update->percentage;
exist->has_percentage = 1;
}
if (update->isolation != exist->isolation) {
LOG_I(FLEXRAN_AGENT, "[%d][DL slice %d] update isolation: %d -> %d\n",
mod_id, update->id, exist->isolation, update->isolation);
exist->isolation = update->isolation;
exist->has_isolation = 1;
}
if (update->priority != exist->priority) {
LOG_I(FLEXRAN_AGENT, "[%d][DL slice %d] update priority: %d -> %d\n",
mod_id, update->id, exist->priority, update->priority);
exist->priority = update->priority;
exist->has_priority = 1;
}
if (update->position_low != exist->position_low) {
LOG_I(FLEXRAN_AGENT, "[%d][DL slice %d] update position_low: %d -> %d\n",
mod_id, update->id, exist->position_low, update->position_low);
exist->position_low = update->position_low;
exist->has_position_low = 1;
}
if (update->position_high != exist->position_high) {
LOG_I(FLEXRAN_AGENT, "[%d][DL slice %d] update position_high: %d -> %d\n",
mod_id, update->id, exist->position_high, update->position_high);
exist->position_high = update->position_high;
exist->has_position_high = 1;
}
if (update->maxmcs != exist->maxmcs) {
LOG_I(FLEXRAN_AGENT, "[%d][DL slice %d] update maxmcs: %d -> %d\n",
mod_id, update->id, exist->maxmcs, update->maxmcs);
exist->maxmcs = update->maxmcs;
exist->has_maxmcs = 1;
}
if (check_dl_sorting_update(exist, update)) {
LOG_I(FLEXRAN_AGENT, "[%d][DL slice %d] update sorting array\n", mod_id, update->id);
if (exist->n_sorting != update->n_sorting) {
exist->n_sorting = update->n_sorting;
exist->sorting = realloc(exist->sorting, exist->n_sorting * sizeof(Protocol__FlexDlSorting));
if (!exist->sorting) exist->n_sorting = 0;
}
for (int i = 0; i < exist->n_sorting; i++)
exist->sorting[i] = update->sorting[i];
}
if (update->accounting != exist->accounting) {
LOG_I(FLEXRAN_AGENT, "[%d][DL slice %d] update accounting: %d -> %d\n",
mod_id, update->id, exist->accounting, update->accounting);
exist->accounting = update->accounting;
exist->has_accounting = 1;
}
if (!exist->scheduler_name
|| strcmp(update->scheduler_name, exist->scheduler_name) != 0) {
LOG_I(FLEXRAN_AGENT, "[%d][DL slice %d] update scheduler: %s -> %s\n",
mod_id, update->id, exist->scheduler_name, update->scheduler_name);
if (exist->scheduler_name) free(exist->scheduler_name);
exist->scheduler_name = strdup(update->scheduler_name);
}
}
void overwrite_slice_config_ul(mid_t mod_id, Protocol__FlexUlSlice *exist, Protocol__FlexUlSlice *update)
{
if (update->label != exist->label) {
LOG_I(FLEXRAN_AGENT, "[%d][UL slice %d] update label: %d -> %d\n",
mod_id, update->id, exist->label, update->label);
exist->label = update->label;
exist->has_label = 1;
}
if (update->percentage != exist->percentage) {
LOG_I(FLEXRAN_AGENT, "[%d][UL slice %d] update percentage: %d -> %d\n",
mod_id, update->id, exist->percentage, update->percentage);
exist->percentage = update->percentage;
exist->has_percentage = 1;
}
if (update->isolation != exist->isolation) {
LOG_I(FLEXRAN_AGENT, "[%d][UL slice %d] update isolation: %d -> %d\n",
mod_id, update->id, exist->isolation, update->isolation);
exist->isolation = update->isolation;
exist->has_isolation = 1;
}
if (update->priority != exist->priority) {
LOG_I(FLEXRAN_AGENT, "[%d][UL slice %d] update priority: %d -> %d\n",
mod_id, update->id, exist->priority, update->priority);
exist->priority = update->priority;
exist->has_priority = 1;
}
if (update->first_rb != exist->first_rb) {
LOG_I(FLEXRAN_AGENT, "[%d][UL slice %d] update first_rb: %d -> %d\n",
mod_id, update->id, exist->first_rb, update->first_rb);
exist->first_rb = update ->first_rb;
exist->has_first_rb = 1;
}
/*if (update->lenght_rb != exist->lenght_rb) {
LOG_I(FLEXRAN_AGENT, "[%d][UL slice %d] update lenght_rb: %d -> %d\n",
mod_id, update->id, exist->lenght_rb, update->lenght_rb);
exist->lenght_rb = update->lenght_rb;
}*/
if (update->maxmcs != exist->maxmcs) {
LOG_I(FLEXRAN_AGENT, "[%d][UL slice %d] update maxmcs: %d -> %d\n",
mod_id, update->id, exist->maxmcs, update->maxmcs);
exist->maxmcs = update->maxmcs;
exist->has_maxmcs = 1;
}
/* TODO
int sorting_update = 0;
int n = min(exist->n_sorting, update->n_sorting);
int i = 0;
while (i < n && !sorting_update) {
sorting_update = sorting_update || (update->sorting[i] != exist->sorting[i]);
i++;
}
if (sorting_update) {
LOG_I(FLEXRAN_AGENT, "[%d][UL slice %d] update sorting array\n", update->id, mod_id);
if (exist->n_sorting != update->n_sorting)
LOG_W(FLEXRAN_AGENT, "[%d][UL slice %d] only writing %d elements\n",
mod_id, update->id, n);
for (i = 0; i < n; i++)
exist->sorting[i] = update->sorting[i];
}
*/
if (update->accounting != exist->accounting) {
LOG_I(FLEXRAN_AGENT, "[%d][UL slice %d] update accounting: %d -> %d\n",
mod_id, update->id, exist->accounting, update->accounting);
exist->accounting = update->accounting;
exist->has_accounting = 1;
}
if (!exist->scheduler_name
|| strcmp(update->scheduler_name, exist->scheduler_name) != 0) {
LOG_I(FLEXRAN_AGENT, "[%d][UL slice %d] update scheduler: %s -> %s\n",
mod_id, update->id, exist->scheduler_name, update->scheduler_name);
if (exist->scheduler_name) free(exist->scheduler_name);
exist->scheduler_name = strdup(update->scheduler_name);
}
}
void fill_dl_slice(mid_t mod_id, Protocol__FlexDlSlice *s, Protocol__FlexDlSlice *from)
{
/* function fills slice with information from another slice or with default
* values (currently slice 0) if from is NULL */
/* TODO fill the slice depending on the chosen label */
if (!s->has_label) {
s->has_label = 1;
s->label = from ? from->label : sc_update[mod_id]->dl[0]->label;
}
if (!s->has_percentage) {
s->has_percentage = 1;
s->percentage = from ? from->percentage : sc_update[mod_id]->dl[0]->percentage;
}
if (!s->has_isolation) {
s->has_isolation = 1;
s->isolation = from ? from->isolation : sc_update[mod_id]->dl[0]->isolation;
}
if (!s->has_priority) {
s->has_priority = 1;
s->priority = from ? from->priority : sc_update[mod_id]->dl[0]->priority;
}
if (!s->has_position_low) {
s->has_position_low = 1;
s->position_low = from ? from->position_low : sc_update[mod_id]->dl[0]->position_low;
}
if (!s->has_position_high) {
s->has_position_high = 1;
s->position_high = from ? from->position_high : sc_update[mod_id]->dl[0]->position_high;
}
if (!s->has_maxmcs) {
s->has_maxmcs = 1;
s->maxmcs = from ? from->maxmcs : sc_update[mod_id]->dl[0]->maxmcs;
}
if (s->n_sorting == 0) {
s->n_sorting = from ? from->n_sorting : sc_update[mod_id]->dl[0]->n_sorting;
s->sorting = calloc(s->n_sorting, sizeof(Protocol__FlexDlSorting));
if (!s->sorting) s->n_sorting = 0;
for (int i = 0; i < s->n_sorting; ++i)
s->sorting[i] = from ? from->sorting[i] : sc_update[0]->dl[0]->sorting[i];
}
if (!s->has_accounting) {
s->accounting = from ? from->accounting : sc_update[mod_id]->dl[0]->accounting;
}
if (!s->scheduler_name) {
s->scheduler_name = strdup(from ? from->scheduler_name : sc_update[mod_id]->dl[0]->scheduler_name);
}
}
Protocol__FlexDlSlice *get_existing_dl_slice(mid_t mod_id, int id)
{
for (int i = 0; i < sc_update[mod_id]->n_dl; ++i) {
if (id == sc_update[mod_id]->dl[i]->id) {
return sc_update[mod_id]->dl[i];
}
}
return NULL;
}
Protocol__FlexDlSlice *create_new_dl_slice(mid_t mod_id, int id)
{
LOG_I(FLEXRAN_AGENT,
"[%d] Creating DL slice with ID %d, taking default values from DL slice 0\n",
mod_id, id);
Protocol__FlexDlSlice *to = sc_update[mod_id]->dl[sc_update[mod_id]->n_dl];
sc_update[mod_id]->n_dl++;
AssertFatal(sc_update[mod_id]->n_dl <= MAX_NUM_SLICES,
"cannot create more than MAX_NUM_SLICES\n");
to->id = id;
return to;
}
void fill_ul_slice(mid_t mod_id, Protocol__FlexUlSlice *s, Protocol__FlexUlSlice *from)
{
/* function fills slice with information from another slice or with default
* values (currently slice 0) if from is NULL */
/* TODO fill the slice depending on the chosen label */
if (!s->has_label) {
s->has_label = 1;
s->label = from ? from->label : sc_update[mod_id]->ul[0]->label;
}
if (!s->has_percentage) {
s->has_percentage = 1;
s->percentage = from ? from->percentage : sc_update[mod_id]->ul[0]->percentage;
}
if (!s->has_isolation) {
s->has_isolation = 1;
s->isolation = from ? from->isolation : sc_update[mod_id]->ul[0]->isolation;
}
if (!s->has_priority) {
s->has_priority = 1;
s->priority = from ? from->priority : sc_update[mod_id]->ul[0]->priority;
}
if (!s->has_first_rb) {
s->has_first_rb = 1;
s->first_rb = from ? from->first_rb : sc_update[mod_id]->ul[0]->first_rb;
}
if (!s->has_maxmcs) {
s->has_maxmcs = 1;
s->maxmcs = from ? from->maxmcs : sc_update[mod_id]->ul[0]->maxmcs;
}
if (s->n_sorting == 0) {
s->n_sorting = from ? from->n_sorting : sc_update[0]->ul[0]->n_sorting;
s->sorting = calloc(s->n_sorting, sizeof(Protocol__FlexUlSorting));
if (!s->sorting) s->n_sorting = 0;
for (int i = 0; i < s->n_sorting; ++i)
s->sorting[i] = from ? from->sorting[i] : sc_update[0]->ul[0]->sorting[i];
}
if (!s->has_accounting) {
s->accounting = from ? from->accounting : sc_update[0]->ul[0]->accounting;
}
if (!s->scheduler_name) {
s->scheduler_name = strdup(from ? from->scheduler_name : sc_update[mod_id]->ul[0]->scheduler_name);
}
}
Protocol__FlexUlSlice *get_existing_ul_slice(mid_t mod_id, int id)
{
for (int i = 0; i < sc_update[mod_id]->n_ul; ++i) {
if (id == sc_update[mod_id]->ul[i]->id) {
return sc_update[mod_id]->ul[i];
}
}
return NULL;
}
Protocol__FlexUlSlice *create_new_ul_slice(mid_t mod_id, int id)
{
LOG_I(FLEXRAN_AGENT,
"[%d] Creating UL slice with ID %d, taking default values from UL slice 0\n",
mod_id, id);
Protocol__FlexUlSlice *to = sc_update[mod_id]->ul[sc_update[mod_id]->n_ul];
sc_update[mod_id]->n_ul++;
AssertFatal(sc_update[mod_id]->n_ul <= MAX_NUM_SLICES,
"cannot create more than MAX_NUM_SLICES\n");
to->id = id;
return to;
}
void prepare_update_slice_config(mid_t mod_id, Protocol__FlexSliceConfig *sup)
{
int verified = 1;
if (!sc_update[mod_id]) {
LOG_E(FLEXRAN_AGENT, "Can not update slice policy (no existing slice profile)\n");
return;
}
pthread_mutex_lock(&sc_update_mtx);
/* no need for tests in the current state as there are only two protobuf
* bools for intra-/interslice sharing. The function applies new values if
* applicable */
overwrite_slice_config(mod_id, sc_update[mod_id], sup);
if (sup->n_dl == 0) {
LOG_I(FLEXRAN_AGENT, "[%d] no DL slice configuration in flex_slice_config message\n", mod_id);
} else {
/* verify slice parameters */
for (int i = 0; i < sup->n_dl; i++) {
if (!sup->dl[i]->has_id) {
verified = 0;
break;
}
Protocol__FlexDlSlice *dls = get_existing_dl_slice(mod_id, sup->dl[i]->id);
/* fill up so that the slice is complete. This way, we don't need to
* worry about it later */
fill_dl_slice(mod_id, sup->dl[i], dls);
verified = verified && flexran_verify_dl_slice(mod_id, sup->dl[i]);
if (!verified) break;
}
/* verify group-based parameters (e.g. sum percentage should not exceed
* 100%). Can be used to perform admission control */
verified = verified && flexran_verify_group_dl_slices(mod_id,
sc_update[mod_id]->dl, sc_update[mod_id]->n_dl, sup->dl, sup->n_dl);
if (verified) {
for (int i = 0; i < sup->n_dl; i++) {
/* if all verifications were successful, get existing slice for ID or
* create new one and overwrite with the update */
Protocol__FlexDlSlice *dls = get_existing_dl_slice(mod_id, sup->dl[i]->id);
if (!dls) dls = create_new_dl_slice(mod_id, sup->dl[i]->id);
overwrite_slice_config_dl(mod_id, dls, sup->dl[i]);
}
} else {
LOG_E(FLEXRAN_AGENT, "[%d] DL slice verification failed, refusing application\n", mod_id);
}
}
verified = 1;
if (sup->n_ul == 0) {
LOG_I(FLEXRAN_AGENT, "[%d] no UL slice configuration in flex_slice_config message\n", mod_id);
} else {
/* verify slice parameters */
for (int i = 0; i < sup->n_ul; i++) {
if (!sup->ul[i]->has_id) {
verified = 0;
break;
}
Protocol__FlexUlSlice *uls = get_existing_ul_slice(mod_id, sup->ul[i]->id);
/* fill up so that the slice is complete. This way, we don't need to
* worry about it later */
fill_ul_slice(mod_id, sup->ul[i], uls);
verified = verified && flexran_verify_ul_slice(mod_id, sup->ul[i]);
if (!verified) break;
}
/* verify group-based parameters (e.g. sum percentage should not exceed
* 100%). Can be used to perform admission control */
verified = verified && flexran_verify_group_ul_slices(mod_id,
sc_update[mod_id]->ul, sc_update[mod_id]->n_ul, sup->ul, sup->n_ul);
if (verified) {
for (int i = 0; i < sup->n_ul; i++) {
/* if all verifications were successful, get existing slice for ID or
* create new one and overwrite with the update */
Protocol__FlexUlSlice *uls = get_existing_ul_slice(mod_id, sup->ul[i]->id);
if (!uls) uls = create_new_ul_slice(mod_id, sup->ul[i]->id);
overwrite_slice_config_ul(mod_id, uls, sup->ul[i]);
}
} else {
LOG_E(FLEXRAN_AGENT, "[%d] UL slice verification failed, refusing application\n", mod_id);
}
}
pthread_mutex_unlock(&sc_update_mtx);
perform_slice_config_update_count = 1;
}
int apply_new_slice_config(mid_t mod_id, Protocol__FlexSliceConfig *olds, Protocol__FlexSliceConfig *news)
{
/* not setting the old configuration is intentional, as it will be picked up
* later when reading the configuration. There is thus a direct feedback
* whether it has been set. */
int changes = 0;
if (olds->intraslice_share_active != news->intraslice_share_active) {
flexran_set_intraslice_sharing_active(mod_id, news->intraslice_share_active);
changes++;
}
if (olds->interslice_share_active != news->interslice_share_active) {
flexran_set_interslice_sharing_active(mod_id, news->interslice_share_active);
changes++;
}
return changes;
}
int apply_new_slice_dl_config(mid_t mod_id, Protocol__FlexDlSlice *oldc, Protocol__FlexDlSlice *newc)
{
/* not setting the old configuration is intentional, as it will be picked up
* later when reading the configuration. There is thus a direct feedback
* whether it has been set. */
int changes = 0;
int slice_idx = flexran_find_dl_slice(mod_id, newc->id);
if (slice_idx < 0) {
LOG_W(FLEXRAN_AGENT, "[%d] cannot find index for slice ID %d\n", mod_id, newc->id);
return 0;
}
if (oldc->percentage != newc->percentage) {
flexran_set_dl_slice_percentage(mod_id, slice_idx, newc->percentage);
changes++;
}
if (oldc->isolation != newc->isolation) {
flexran_set_dl_slice_isolation(mod_id, slice_idx, newc->isolation);
changes++;
}
if (oldc->priority != newc->priority) {
flexran_set_dl_slice_priority(mod_id, slice_idx, newc->priority);
changes++;
}
if (oldc->position_low != newc->position_low) {
flexran_set_dl_slice_position_low(mod_id, slice_idx, newc->position_low);
changes++;
}
if (oldc->position_high != newc->position_high) {
flexran_set_dl_slice_position_high(mod_id, slice_idx, newc->position_high);
changes++;
}
if (oldc->maxmcs != newc->maxmcs) {
flexran_set_dl_slice_maxmcs(mod_id, slice_idx, newc->maxmcs);
changes++;
}
if (check_dl_sorting_update(oldc, newc)) {
flexran_set_dl_slice_sorting(mod_id, slice_idx, newc->sorting, newc->n_sorting);
changes++;
}
if (oldc->accounting != newc->accounting) {
flexran_set_dl_slice_accounting_policy(mod_id, slice_idx, newc->accounting);
changes++;
}
if (!oldc->scheduler_name
|| strcmp(oldc->scheduler_name, newc->scheduler_name) != 0) {
int ret = flexran_set_dl_slice_scheduler(mod_id, slice_idx, newc->scheduler_name);
AssertFatal(ret, "could not set DL slice scheduler for slice %d idx %d\n",
newc->id, slice_idx);
changes++;
}
return changes;
}
int apply_new_slice_ul_config(mid_t mod_id, Protocol__FlexUlSlice *oldc, Protocol__FlexUlSlice *newc)
{
/* not setting the old configuration is intentional, as it will be picked up
* later when reading the configuration. There is thus a direct feedback
* whether it has been set. */
int changes = 0;
int slice_idx = flexran_find_ul_slice(mod_id, newc->id);
if (slice_idx < 0) {
LOG_W(FLEXRAN_AGENT, "[%d] cannot find index for slice ID %d\n", mod_id, newc->id);
return 0;
}
if (oldc->percentage != newc->percentage) {
flexran_set_ul_slice_percentage(mod_id, slice_idx, newc->percentage);
changes++;
}
if (oldc->isolation != newc->isolation) {
/*flexran_set_ul_slice_isolation(mod_id, slice_idx, newc->isolation);
*changes++;*/
LOG_W(FLEXRAN_AGENT, "[%d][UL slice %d] setting isolation is not supported\n",
mod_id, newc->id);
}
if (oldc->priority != newc->priority) {
/*flexran_set_ul_slice_priority(mod_id, slice_idx, newc->priority);
*changes++;*/
LOG_W(FLEXRAN_AGENT, "[%d][UL slice %d] setting the priority is not supported\n",
mod_id, newc->id);
}
if (oldc->first_rb != newc->first_rb) {
flexran_set_ul_slice_first_rb(mod_id, slice_idx, newc->first_rb);
changes++;
}
/*if (oldc->length_rb != newc->length_rb) {
flexran_set_ul_slice_length_rb(mod_id, slice_idx, newc->length_rb);
changes++;
LOG_W(FLEXRAN_AGENT, "[%d][UL slice %d] setting length_rb is not supported\n",
mod_id, newc->id);
}*/
if (oldc->maxmcs != newc->maxmcs) {
flexran_set_ul_slice_maxmcs(mod_id, slice_idx, newc->maxmcs);
changes++;
}
/*if (check_ul_sorting_update(oldc, newc)) {
flexran_set_ul_slice_sorting(mod_id, slice_idx, newc->sorting, n);
changes++;
LOG_W(FLEXRAN_AGENT, "[%d][UL slice %d] setting the sorting is not supported\n",
mod_id, newc->id);
}*/
if (oldc->accounting != newc->accounting) {
/*flexran_set_ul_slice_accounting_policy(mod_id, slice_idx, newc->accounting);
*changes++;*/
LOG_W(FLEXRAN_AGENT, "[%d][UL slice %d] setting the accounting is not supported\n",
mod_id, newc->id);
}
if (!oldc->scheduler_name
|| strcmp(oldc->scheduler_name, newc->scheduler_name) != 0) {
int ret = flexran_set_ul_slice_scheduler(mod_id, slice_idx, newc->scheduler_name);
AssertFatal(ret, "could not set DL slice scheduler for slice %d idx %d\n",
newc->id, slice_idx);
changes++;
}
return changes;
}
void prepare_ue_slice_assoc_update(mid_t mod_id, Protocol__FlexUeConfig *ue_config)
{
if (n_ue_slice_assoc_updates == MAX_NUM_SLICES) {
LOG_E(FLEXRAN_AGENT,
"[%d] can not handle flex_ue_config message, buffer is full; try again later\n",
mod_id);
return;
}
if (!ue_config->has_rnti) {
LOG_E(FLEXRAN_AGENT,
"[%d] cannot update UE to slice association, no RNTI in flex_ue_config message\n",
mod_id);
return;
}
if (ue_config->has_dl_slice_id)
LOG_I(FLEXRAN_AGENT, "[%d] associating UE RNTI %#x to DL slice ID %d\n",
mod_id, ue_config->rnti, ue_config->dl_slice_id);
if (ue_config->has_ul_slice_id)
LOG_I(FLEXRAN_AGENT, "[%d] associating UE RNTI %#x to UL slice ID %d\n",
mod_id, ue_config->rnti, ue_config->ul_slice_id);
ue_slice_assoc_update[n_ue_slice_assoc_updates++] = ue_config;
perform_slice_config_update_count = 2;
}
int apply_ue_slice_assoc_update(mid_t mod_id)
{
int i;
int changes = 0;
for (i = 0; i < n_ue_slice_assoc_updates; i++) {
int ue_id = find_UE_id(mod_id, ue_slice_assoc_update[i]->rnti);
if (ue_slice_assoc_update[i]->has_dl_slice_id) {
int slice_idx = flexran_find_dl_slice(mod_id, ue_slice_assoc_update[i]->dl_slice_id);
if (flexran_dl_slice_exists(mod_id, slice_idx)) {
flexran_set_ue_dl_slice_idx(mod_id, ue_id, slice_idx);
changes++;
} else {
LOG_W(FLEXRAN_AGENT, "[%d] DL slice %d does not exist, refusing change\n",
mod_id, ue_slice_assoc_update[i]->dl_slice_id);
}
}
if (ue_slice_assoc_update[i]->has_ul_slice_id) {
int slice_idx = flexran_find_ul_slice(mod_id, ue_slice_assoc_update[i]->ul_slice_id);
if (flexran_ul_slice_exists(mod_id, slice_idx)) {
flexran_set_ue_ul_slice_idx(mod_id, ue_id, slice_idx);
changes++;
} else {
LOG_W(FLEXRAN_AGENT, "[%d] UL slice %d does not exist, refusing change\n",
mod_id, ue_slice_assoc_update[i]->ul_slice_id);
}
}
}
n_ue_slice_assoc_updates = 0;
return changes;
}
@@ -107,4 +107,45 @@ int parse_ul_scheduler_parameters(mid_t mod_id, yaml_parser_t *parser);
int load_dl_scheduler_function(mid_t mod_id, const char *function_name);
/*** Functions for handling a slice config ***/
/* allocate memory for a Protocol__FlexSliceConfig structure with n_dl DL slice
* configs and m_ul UL slice configs */
Protocol__FlexSliceConfig *flexran_agent_create_slice_config(int n_dl, int m_ul);
/* read the general slice parameters via RAN into the given
* Protocol__FlexSliceConfig struct */
void flexran_agent_read_slice_config(mid_t mod_id, Protocol__FlexSliceConfig *s);
/* read the DL slice config via the RAN into a given Protocol__FlexDlSlice
* struct */
void flexran_agent_read_slice_dl_config(mid_t mod_id, int slice_idx, Protocol__FlexDlSlice *dl_slice);
/* read the UL slice config via the RAN into a given Protocol__FlexUlSlice
* struct */
void flexran_agent_read_slice_ul_config(mid_t mod_id, int slice_idx, Protocol__FlexUlSlice *ul_slice);
/* reads content of slice over the sc_update structure, so that it can be
* applied later by performing a diff between slice_config and sc_update */
void prepare_update_slice_config(mid_t mod_id, Protocol__FlexSliceConfig *slice);
/* apply generic slice parameters (e.g. intra-/interslice sharing activated or
* not) if there are changes. Returns the number of changed parameters. */
int apply_new_slice_config(mid_t mod_id, Protocol__FlexSliceConfig *olds, Protocol__FlexSliceConfig *news);
/* apply new configuration of slice in DL if there are changes between the
* parameters. Returns the number of changed parameters. */
int apply_new_slice_dl_config(mid_t mod_id, Protocol__FlexDlSlice *oldc, Protocol__FlexDlSlice *newc);
/* apply new configuration of slice in UL if there are changes between the
* parameters. Returns the number of changed parameters. */
int apply_new_slice_ul_config(mid_t mod_id, Protocol__FlexUlSlice *oldc, Protocol__FlexUlSlice *newc);
/* inserts a new ue_config into the structure keeping ue to slice association
* updates and marks so it can be applied */
void prepare_ue_slice_assoc_update(mid_t mod_id, Protocol__FlexUeConfig *ue_config);
/* apply a new association between a UE and a slice (both DL and UL) */
int apply_ue_slice_assoc_update(mid_t mod_id);
#endif /*FLEXRAN_AGENT_MAC_INTERNAL_H_*/
@@ -0,0 +1,373 @@
/*
* 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_mac_slice_verification.c
* \brief MAC Agent slice verification helper functions
* \author Robert Schmidt
* \date 2018
* \version 0.1
*/
#include "flexran_agent_mac_slice_verification.h"
/* overlap check for UL slices, helper type */
struct sregion_s {
int start;
int length;
};
/* forward declaration of locally-used verification functions */
int flexran_dl_slice_verify_pct(int pct);
int flexran_dl_slice_verify_priority(int prio);
int flexran_dl_slice_verify_position(int pos_low, int pos_high);
int flexran_dl_slice_verify_maxmcs(int maxmcs);
int flexran_ul_slice_verify_pct(int pct);
int flexran_ul_slice_verify_priority(int prio);
int flexran_ul_slice_verify_first_rb(int first_rb);
int flexran_ul_slice_verify_maxmcs(int maxmcs);
int check_ul_slice_overlap(mid_t mod_id, struct sregion_s *sr, int n);
int flexran_verify_dl_slice(mid_t mod_id, Protocol__FlexDlSlice *dls)
{
/* check mandatory parameters */
if (!dls->has_id) {
LOG_E(FLEXRAN_AGENT, "[%d] Incoming DL slice configuration has no ID\n", mod_id);
return 0;
}
/* verify parameters individualy */
/* label is enum */
if (!flexran_dl_slice_verify_pct(dls->percentage)) {
LOG_E(FLEXRAN_AGENT, "[%d][DL slice %d] illegal DL slice percentage (%d)\n",
mod_id, dls->id, dls->percentage);
return 0;
}
/* isolation is a protobuf bool */
if (!flexran_dl_slice_verify_priority(dls->priority)) {
LOG_E(FLEXRAN_AGENT, "[%d][DL slice %d] illegal DL slice priority (%d)\n",
mod_id, dls->id, dls->priority);
return 0;
}
if (!flexran_dl_slice_verify_position(dls->position_low, dls->position_high)) {
LOG_E(FLEXRAN_AGENT,
"[%d][DL slice %d] illegal DL slice position low (%d) and/or high (%d)\n",
mod_id, dls->id, dls->position_low, dls->position_high);
return 0;
}
if (!flexran_dl_slice_verify_maxmcs(dls->maxmcs)) {
LOG_E(FLEXRAN_AGENT, "[%d][DL slice %d] illegal DL slice max mcs %d\n",
mod_id, dls->id, dls->maxmcs);
return 0;
}
if (dls->n_sorting == 0) {
LOG_E(FLEXRAN_AGENT, "[%d][DL slice %d] no sorting in DL slice\n",
mod_id, dls->id);
return 0;
}
if (!dls->sorting) {
LOG_E(FLEXRAN_AGENT, "[%d][DL slice %d] no sorting found in DL slice\n",
mod_id, dls->id);
return 0;
}
/* sorting is an enum */
/* accounting is an enum */
if (!dls->scheduler_name) {
LOG_E(FLEXRAN_AGENT, "[%d][DL slice %d] no scheduler name found\n",
mod_id, dls->id);
return 0;
}
if (strcmp(dls->scheduler_name, "schedule_ue_spec") != 0) {
LOG_E(FLEXRAN_AGENT, "[%d][DL slice %d] setting the scheduler to something "
"different than schedule_ue_spec is currently not allowed\n",
mod_id, dls->id);
return 0;
}
return 1;
}
int flexran_verify_group_dl_slices(mid_t mod_id, Protocol__FlexDlSlice **existing,
int n_ex, Protocol__FlexDlSlice **update, int n_up)
{
int i, j, n;
int pct, pct_orig;
/* for every update, array points to existing slice, or NULL if update
* creates new slice */
Protocol__FlexDlSlice *s[n_up];
for (i = 0; i < n_up; i++) {
s[i] = NULL;
for (j = 0; j < n_ex; j++) {
if (existing[j]->id == update[i]->id)
s[i] = existing[j];
}
}
/* check that number of created and number of added slices in total matches
* [1,10] */
n = n_ex;
for (i = 0; i < n_up; i++) {
/* new slice */
if (!s[i]) n += 1;
/* slice will be deleted */
else if (s[i]->percentage == 0) n -= 1;
/* else "only" an update */
}
if (n < 1 || n > MAX_NUM_SLICES) {
LOG_E(FLEXRAN_AGENT, "[%d] Illegal number of resulting DL slices (%d -> %d)\n",
mod_id, n_ex, n);
return 0;
}
/* check that the sum of all slices percentages (including removed/added
* slices) matches [1,100] */
pct = 0;
for (i = 0; i < n_ex; i++) {
pct += existing[i]->percentage;
}
pct_orig = pct;
for (i = 0; i < n_up; i++) {
/* if there is an existing slice, subtract its percentage and add the
* update's percentage */
if (s[i])
pct -= s[i]->percentage;
pct += update[i]->percentage;
}
if (pct < 1 || pct > 100) {
LOG_E(FLEXRAN_AGENT,
"[%d] invalid total RB share for DL slices (%d%% -> %d%%)\n",
mod_id, pct_orig, pct);
return 0;
}
return 1;
}
int flexran_verify_ul_slice(mid_t mod_id, Protocol__FlexUlSlice *uls)
{
/* check mandatory parameters */
if (!uls->has_id) {
LOG_E(FLEXRAN_AGENT, "[%d] Incoming UL slice configuration has no ID\n", mod_id);
return 0;
}
/* verify parameters individually */
/* label is enum */
if (!flexran_ul_slice_verify_pct(uls->percentage)) {
LOG_E(FLEXRAN_AGENT, "[%d][UL slice %d] illegal UL slice percentage (%d)\n",
mod_id, uls->id, uls->percentage);
return 0;
}
/* isolation is a protobuf bool */
if (!flexran_ul_slice_verify_priority(uls->priority)) {
LOG_E(FLEXRAN_AGENT, "[%d][UL slice %d] illegal UL slice percentage (%d)\n",
mod_id, uls->id, uls->priority);
return 0;
}
if (!flexran_ul_slice_verify_first_rb(uls->first_rb)) {
LOG_E(FLEXRAN_AGENT, "[%d][UL slice %d] illegal UL slice first RB (%d)\n",
mod_id, uls->id, uls->first_rb);
return 0;
}
if (!flexran_ul_slice_verify_maxmcs(uls->maxmcs)) {
LOG_E(FLEXRAN_AGENT, "[%d][UL slice %d] illegal UL slice max mcs (%d)\n",
mod_id, uls->id, uls->maxmcs);
return 0;
}
/* TODO
if (uls->n_sorting == 0) {
LOG_E(FLEXRAN_AGENT, "[%d][UL slice %d] no sorting in UL slice\n",
mod_id, uls->id);
return 0;
}
if (!uls->sorting) {
LOG_E(FLEXRAN_AGENT, "[%d][UL slice %d] no sorting found in UL slice\n",
mod_id, uls->id);
return 0;
}
*/
/* sorting is an enum */
/* accounting is an enum */
if (!uls->scheduler_name) {
LOG_E(FLEXRAN_AGENT, "[%d][UL slice %d] no scheduler name found\n",
mod_id, uls->id);
return 0;
}
if (strcmp(uls->scheduler_name, "schedule_ulsch_rnti") != 0) {
LOG_E(FLEXRAN_AGENT, "[%d][UL slice %d] setting the scheduler to something "
"different than schedule_ulsch_rnti is currently not allowed\n",
mod_id, uls->id);
return 0;
}
return 1;
}
int flexran_verify_group_ul_slices(mid_t mod_id, Protocol__FlexUlSlice **existing,
int n_ex, Protocol__FlexUlSlice **update, int n_up)
{
int i, j, n;
int pct, pct_orig;
/* for every update, array "s" points to existing slice, or NULL if update
* creates new slice; array "offs" gives the offset of this slice */
Protocol__FlexUlSlice *s[n_up];
int offs[n_up];
for (i = 0; i < n_up; i++) {
s[i] = NULL;
offs[i] = 0;
for (j = 0; j < n_ex; j++) {
if (existing[j]->id == update[i]->id) {
s[i] = existing[j];
offs[i] = j;
}
}
}
/* check that number of created and number of added slices in total matches
* [1,10] */
n = n_ex;
for (i = 0; i < n_up; i++) {
/* new slice */
if (!s[i]) n += 1;
/* slice will be deleted */
else if (s[i]->percentage == 0) n -= 1;
/* else "only" an update */
}
if (n < 1 || n > MAX_NUM_SLICES) {
LOG_E(FLEXRAN_AGENT, "[%d] Illegal number of resulting UL slices (%d -> %d)\n",
mod_id, n_ex, n);
return 0;
}
/* check that the sum of all slices percentages (including removed/added
* slices) matches [1,100] */
pct = 0;
for (i = 0; i < n_ex; i++) {
pct += existing[i]->percentage;
}
pct_orig = pct;
for (i = 0; i < n_up; i++) {
/* if there is an existing slice, subtract its percentage and add the
* update's percentage */
if (s[i])
pct -= s[i]->percentage;
pct += update[i]->percentage;
}
if (pct < 1 || pct > 100) {
LOG_E(FLEXRAN_AGENT, "[%d] invalid total RB share (%d%% -> %d%%)\n",
mod_id, pct_orig, pct);
return 0;
}
/* check that there is no overlap in slices resulting as the combination of
* first_rb and percentage */
struct sregion_s sregion[n];
const int N_RB = flexran_get_N_RB_UL(mod_id, 0); /* assume PCC */
int k = n_ex;
for (i = 0; i < n_ex; i++) {
sregion[i].start = existing[i]->first_rb;
sregion[i].length = existing[i]->percentage * N_RB / 100;
}
for (i = 0; i < n_up; i++) {
ptrdiff_t d = s[i] ? offs[i] : k++;
AssertFatal(d >= 0 && d < k, "illegal pointer offset (%ld, k=%d)\n", d, k);
sregion[d].start = update[i]->first_rb;
sregion[d].length = update[i]->percentage * N_RB / 100;
}
AssertFatal(k == n, "illegal number of slices while calculating overlap\n");
if (!check_ul_slice_overlap(mod_id, sregion, k)) {
LOG_E(FLEXRAN_AGENT, "[%d] UL slices are overlapping\n", mod_id);
return 0;
}
return 1;
}
int flexran_dl_slice_verify_pct(int pct)
{
return pct >= 0 && pct <= 100;
}
int flexran_dl_slice_verify_priority(int prio)
{
return prio >= 0;
}
int flexran_dl_slice_verify_position(int pos_low, int pos_high)
{
return pos_low < pos_high && pos_low >= 0 && pos_high <= N_RBG_MAX;
}
int flexran_dl_slice_verify_maxmcs(int maxmcs)
{
return maxmcs >= 0 && maxmcs <= 28;
}
int flexran_ul_slice_verify_pct(int pct)
{
return pct >= 0 && pct <= 100;
}
int flexran_ul_slice_verify_priority(int prio)
{
return prio >= 0;
}
int flexran_ul_slice_verify_first_rb(int first_rb)
{
return first_rb >= 0 && first_rb < 100;
}
int flexran_ul_slice_verify_maxmcs(int maxmcs)
{
return maxmcs >= 0 && maxmcs <= 20;
}
int sregion_compare(const void *_a, const void *_b)
{
const struct sregion_s *a = (const struct sregion_s *)_a;
const struct sregion_s *b = (const struct sregion_s *)_b;
const int res = a->start - b->start;
if (res < 0) return -1;
else if (res == 0) return 0;
else return 1;
}
int check_ul_slice_overlap(mid_t mod_id, struct sregion_s *sr, int n)
{
int i;
int overlap, op, u;
const int N_RB = flexran_get_N_RB_UL(mod_id, 0); /* assume PCC */
qsort(sr, n, sizeof(sr[0]), sregion_compare);
for (i = 0; i < n; i++) {
u = i == n-1 ? N_RB : sr[i+1].start;
AssertFatal(sr[i].start <= u, "unsorted slice list\n");
overlap = sr[i].start + sr[i].length - u;
if (overlap <= 0) continue;
op = overlap * 100 / sr[i].length;
LOG_W(FLEXRAN_AGENT, "[%d] slice overlap of %d%% detected\n", mod_id, op);
if (op >= 10) /* more than 10% overlap -> refuse */
return 0;
}
return 1;
}
@@ -0,0 +1,37 @@
/*
* 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_mac_slice_verification.h
* \brief MAC Agent slice verification helper functions
* \author Robert Schmidt
* \date 2018
* \version 0.1
*/
#include "flexran_agent_common_internal.h"
#include "flexran_agent_mac_internal.h"
int flexran_verify_dl_slice(mid_t mod_id, Protocol__FlexDlSlice *dls);
int flexran_verify_group_dl_slices(mid_t mod_id, Protocol__FlexDlSlice **existing,
int n_ex, Protocol__FlexDlSlice **update, int n_up);
int flexran_verify_ul_slice(mid_t mod_id, Protocol__FlexUlSlice *uls);
int flexran_verify_group_ul_slices(mid_t mod_id, Protocol__FlexUlSlice **existing,
int n_ex, Protocol__FlexUlSlice **update, int n_up);
@@ -78,6 +78,7 @@ int flexran_agent_pdcp_stats_reply(mid_t mod_id,
// Protocol__FlexHeader *header;
int i;
int UE_id;
// int cc_id = 0;
@@ -85,6 +86,7 @@ int flexran_agent_pdcp_stats_reply(mid_t mod_id,
if (report_config->nr_ue > 0) {
for (i = 0; i < report_config->nr_ue; i++) {
UE_id = flexran_get_ue_id(mod_id, i);
/* 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) {
@@ -95,7 +97,7 @@ int flexran_agent_pdcp_stats_reply(mid_t mod_id,
goto error;
protocol__flex_pdcp_stats__init(pdcp_aggr_stats);
flexran_agent_pdcp_aggregate_stats(mod_id, i, pdcp_aggr_stats);
flexran_agent_pdcp_aggregate_stats(mod_id, UE_id, pdcp_aggr_stats);
pdcp_aggr_stats->has_pkt_tx=1;
pdcp_aggr_stats->has_pkt_tx_bytes =1;
@@ -104,7 +106,7 @@ int flexran_agent_pdcp_stats_reply(mid_t mod_id,
pdcp_aggr_stats->has_pkt_tx_aiat =1;
pdcp_aggr_stats->has_pkt_tx_aiat_w =1;
pdcp_aggr_stats->pkt_tx_sn = flexran_get_pdcp_tx_sn(mod_id, i, DEFAULT_DRB);
pdcp_aggr_stats->pkt_tx_sn = flexran_get_pdcp_tx_sn(mod_id, UE_id, DEFAULT_DRB);
pdcp_aggr_stats->has_pkt_tx_sn =1;
pdcp_aggr_stats->has_pkt_rx =1;
@@ -115,7 +117,7 @@ int flexran_agent_pdcp_stats_reply(mid_t mod_id,
pdcp_aggr_stats->has_pkt_rx_aiat_w =1;
pdcp_aggr_stats->has_pkt_rx_oo =1;
pdcp_aggr_stats->pkt_rx_sn = flexran_get_pdcp_rx_sn(mod_id, i, DEFAULT_DRB);
pdcp_aggr_stats->pkt_rx_sn = flexran_get_pdcp_rx_sn(mod_id, UE_id, DEFAULT_DRB);
pdcp_aggr_stats->has_pkt_rx_sn =1;
pdcp_aggr_stats->sfn = flexran_get_pdcp_sfn(mod_id);
@@ -31,7 +31,7 @@
#include "liblfds700.h"
#include "log.h"
#include "common/utils/LOG/log.h"
/*Trigger boolean for RRC measurement*/
bool triggered_rrc = false;
@@ -76,147 +76,147 @@ void flexran_agent_ue_state_change(mid_t mod_id, uint32_t rnti, uint8_t state_ch
config->has_rnti = 1;
config->rnti = rnti;
} else if (state_change == PROTOCOL__FLEX_UE_STATE_CHANGE_TYPE__FLUESC_UPDATED
|| state_change == PROTOCOL__FLEX_UE_STATE_CHANGE_TYPE__FLUESC_ACTIVATED) {
int i = find_UE_id(mod_id, rnti);
config->has_rnti = 1;
config->rnti = rnti;
if(flexran_get_time_alignment_timer(mod_id,i) != -1) {
config->time_alignment_timer = flexran_get_time_alignment_timer(mod_id,i);
config->has_time_alignment_timer = 1;
}
if(flexran_get_meas_gap_config(mod_id,i) != -1){
config->meas_gap_config_pattern = flexran_get_meas_gap_config(mod_id,i);
config->has_meas_gap_config_pattern = 1;
}
if(config->has_meas_gap_config_pattern == 1 &&
config->meas_gap_config_pattern != PROTOCOL__FLEX_MEAS_GAP_CONFIG_PATTERN__FLMGCP_OFF) {
config->meas_gap_config_sf_offset = flexran_get_meas_gap_config_offset(mod_id,i);
config->has_meas_gap_config_sf_offset = 1;
}
//TODO: Set the SPS configuration (Optional)
//Not supported for now, so we do not set it
|| state_change == PROTOCOL__FLEX_UE_STATE_CHANGE_TYPE__FLUESC_ACTIVATED) {
int i = find_UE_id(mod_id, rnti);
config->has_rnti = 1;
config->rnti = rnti;
config->imsi = flexran_get_ue_imsi(mod_id, i);
config->has_imsi = 1;
config->dl_slice_id = flexran_get_ue_dl_slice_id(mod_id, i);
config->has_dl_slice_id = 1;
config->ul_slice_id = flexran_get_ue_ul_slice_id(mod_id, i);
config->has_ul_slice_id = 1;
if(flexran_get_time_alignment_timer(mod_id,i) != -1) {
config->time_alignment_timer = flexran_get_time_alignment_timer(mod_id,i);
config->has_time_alignment_timer = 1;
}
if(flexran_get_meas_gap_config(mod_id,i) != -1){
config->meas_gap_config_pattern = flexran_get_meas_gap_config(mod_id,i);
config->has_meas_gap_config_pattern = 1;
}
if(config->has_meas_gap_config_pattern == 1 &&
config->meas_gap_config_pattern != PROTOCOL__FLEX_MEAS_GAP_CONFIG_PATTERN__FLMGCP_OFF) {
config->meas_gap_config_sf_offset = flexran_get_meas_gap_config_offset(mod_id,i);
config->has_meas_gap_config_sf_offset = 1;
}
//TODO: Set the SPS configuration (Optional)
//Not supported for now, so we do not set it
//TODO: Set the SR configuration (Optional)
//We do not set it for now
//TODO: Set the SR configuration (Optional)
//We do not set it for now
//TODO: Set the CQI configuration (Optional)
//We do not set it for now
if(flexran_get_ue_transmission_mode(mod_id,i) != -1) {
config->transmission_mode = flexran_get_ue_transmission_mode(mod_id,i);
config->has_transmission_mode = 1;
}
//TODO: Set the CQI configuration (Optional)
//We do not set it for now
config->ue_aggregated_max_bitrate_ul = flexran_get_ue_aggregated_max_bitrate_ul(mod_id,i);
config->has_ue_aggregated_max_bitrate_ul = 1;
if(flexran_get_ue_transmission_mode(mod_id,i) != -1) {
config->transmission_mode = flexran_get_ue_transmission_mode(mod_id,i);
config->has_transmission_mode = 1;
}
config->ue_aggregated_max_bitrate_dl = flexran_get_ue_aggregated_max_bitrate_dl(mod_id,i);
config->has_ue_aggregated_max_bitrate_dl = 1;
config->ue_aggregated_max_bitrate_ul = flexran_get_ue_aggregated_max_bitrate_ul(mod_id,i);
config->has_ue_aggregated_max_bitrate_ul = 1;
//TODO: Set the UE capabilities
Protocol__FlexUeCapabilities *c_capabilities;
c_capabilities = malloc(sizeof(Protocol__FlexUeCapabilities));
protocol__flex_ue_capabilities__init(c_capabilities);
//TODO: Set half duplex (FDD operation)
c_capabilities->has_half_duplex = 0;
c_capabilities->half_duplex = 1;//flexran_get_half_duplex(i);
//TODO: Set intra-frame hopping flag
c_capabilities->has_intra_sf_hopping = 0;
c_capabilities->intra_sf_hopping = 1;//flexran_get_intra_sf_hopping(i);
//TODO: Set support for type 2 hopping with n_sb > 1
c_capabilities->has_type2_sb_1 = 0;
c_capabilities->type2_sb_1 = 1;//flexran_get_type2_sb_1(i);
//TODO: Set ue category
c_capabilities->has_ue_category = 0;
c_capabilities->ue_category = 1;//flexran_get_ue_category(i);
//TODO: Set UE support for resource allocation type 1
c_capabilities->has_res_alloc_type1 = 0;
c_capabilities->res_alloc_type1 = 1;//flexran_get_res_alloc_type1(i);
//Set the capabilites to the message
config->capabilities = c_capabilities;
if(flexran_get_ue_transmission_antenna(mod_id,i) != -1) {
config->has_ue_transmission_antenna = 1;
config->ue_transmission_antenna = flexran_get_ue_transmission_antenna(mod_id,i);
}
config->ue_aggregated_max_bitrate_dl = flexran_get_ue_aggregated_max_bitrate_dl(mod_id,i);
config->has_ue_aggregated_max_bitrate_dl = 1;
if(flexran_get_tti_bundling(mod_id,i) != -1) {
config->has_tti_bundling = 1;
config->tti_bundling = flexran_get_tti_bundling(mod_id,i);
}
Protocol__FlexUeCapabilities *c_capabilities;
c_capabilities = malloc(sizeof(Protocol__FlexUeCapabilities));
protocol__flex_ue_capabilities__init(c_capabilities);
c_capabilities->has_half_duplex = 1;
c_capabilities->half_duplex = flexran_get_half_duplex(mod_id, i);
c_capabilities->has_intra_sf_hopping = 1;
c_capabilities->intra_sf_hopping = flexran_get_intra_sf_hopping(mod_id, i);
c_capabilities->has_type2_sb_1 = 1;
c_capabilities->type2_sb_1 = flexran_get_type2_sb_1(mod_id, i);
c_capabilities->has_ue_category = 1;
c_capabilities->ue_category = flexran_get_ue_category(mod_id, i);
c_capabilities->has_res_alloc_type1 = 1;
c_capabilities->res_alloc_type1 = flexran_get_res_alloc_type1(mod_id, i);
//Set the capabilites to the message
config->capabilities = c_capabilities;
if(flexran_get_maxHARQ_TX(mod_id,i) != -1){
config->has_max_harq_tx = 1;
config->max_harq_tx = flexran_get_maxHARQ_TX(mod_id,i);
}
if(flexran_get_ue_transmission_antenna(mod_id,i) != -1) {
config->has_ue_transmission_antenna = 1;
config->ue_transmission_antenna = flexran_get_ue_transmission_antenna(mod_id,i);
}
if(flexran_get_beta_offset_ack_index(mod_id,i) != -1) {
config->has_beta_offset_ack_index = 1;
config->beta_offset_ack_index = flexran_get_beta_offset_ack_index(mod_id,i);
}
if(flexran_get_tti_bundling(mod_id,i) != -1) {
config->has_tti_bundling = 1;
config->tti_bundling = flexran_get_tti_bundling(mod_id,i);
}
if(flexran_get_beta_offset_ri_index(mod_id,i) != -1) {
config->has_beta_offset_ri_index = 1;
config->beta_offset_ri_index = flexran_get_beta_offset_ri_index(mod_id,i);
}
if(flexran_get_maxHARQ_TX(mod_id,i) != -1){
config->has_max_harq_tx = 1;
config->max_harq_tx = flexran_get_maxHARQ_TX(mod_id,i);
}
if(flexran_get_beta_offset_cqi_index(mod_id,i) != -1) {
config->has_beta_offset_cqi_index = 1;
config->beta_offset_cqi_index = flexran_get_beta_offset_cqi_index(mod_id,i);
}
if(flexran_get_beta_offset_ack_index(mod_id,i) != -1) {
config->has_beta_offset_ack_index = 1;
config->beta_offset_ack_index = flexran_get_beta_offset_ack_index(mod_id,i);
}
/* assume primary carrier */
if(flexran_get_ack_nack_simultaneous_trans(mod_id,i,0) != -1) {
config->has_ack_nack_simultaneous_trans = 1;
config->ack_nack_simultaneous_trans = flexran_get_ack_nack_simultaneous_trans(mod_id,i,0);
}
if(flexran_get_beta_offset_ri_index(mod_id,i) != -1) {
config->has_beta_offset_ri_index = 1;
config->beta_offset_ri_index = flexran_get_beta_offset_ri_index(mod_id,i);
}
if(flexran_get_simultaneous_ack_nack_cqi(mod_id,i) != -1) {
config->has_simultaneous_ack_nack_cqi = 1;
config->simultaneous_ack_nack_cqi = flexran_get_simultaneous_ack_nack_cqi(mod_id,i);
}
if(flexran_get_beta_offset_cqi_index(mod_id,i) != -1) {
config->has_beta_offset_cqi_index = 1;
config->beta_offset_cqi_index = flexran_get_beta_offset_cqi_index(mod_id,i);
}
if(flexran_get_aperiodic_cqi_rep_mode(mod_id,i) != -1) {
config->has_aperiodic_cqi_rep_mode = 1;
int mode = flexran_get_aperiodic_cqi_rep_mode(mod_id,i);
if (mode > 4) {
config->aperiodic_cqi_rep_mode = PROTOCOL__FLEX_APERIODIC_CQI_REPORT_MODE__FLACRM_NONE;
} else {
config->aperiodic_cqi_rep_mode = mode;
}
}
/* assume primary carrier */
if(flexran_get_ack_nack_simultaneous_trans(mod_id,i,0) != -1) {
config->has_ack_nack_simultaneous_trans = 1;
config->ack_nack_simultaneous_trans = flexran_get_ack_nack_simultaneous_trans(mod_id,i,0);
}
if(flexran_get_tdd_ack_nack_feedback_mode(mod_id, i) != -1) {
config->has_tdd_ack_nack_feedback = 1;
config->tdd_ack_nack_feedback = flexran_get_tdd_ack_nack_feedback_mode(mod_id,i);
}
if(flexran_get_simultaneous_ack_nack_cqi(mod_id,i) != -1) {
config->has_simultaneous_ack_nack_cqi = 1;
config->simultaneous_ack_nack_cqi = flexran_get_simultaneous_ack_nack_cqi(mod_id,i);
}
if(flexran_get_ack_nack_repetition_factor(mod_id, i) != -1) {
config->has_ack_nack_repetition_factor = 1;
config->ack_nack_repetition_factor = flexran_get_ack_nack_repetition_factor(mod_id,i);
}
if(flexran_get_aperiodic_cqi_rep_mode(mod_id,i) != -1) {
config->has_aperiodic_cqi_rep_mode = 1;
int mode = flexran_get_aperiodic_cqi_rep_mode(mod_id,i);
if (mode > 4) {
config->aperiodic_cqi_rep_mode = PROTOCOL__FLEX_APERIODIC_CQI_REPORT_MODE__FLACRM_NONE;
} else {
config->aperiodic_cqi_rep_mode = mode;
}
}
if(flexran_get_extended_bsr_size(mod_id, i) != -1) {
config->has_extended_bsr_size = 1;
config->extended_bsr_size = flexran_get_extended_bsr_size(mod_id,i);
}
if(flexran_get_tdd_ack_nack_feedback_mode(mod_id, i) != -1) {
config->has_tdd_ack_nack_feedback = 1;
config->tdd_ack_nack_feedback = flexran_get_tdd_ack_nack_feedback_mode(mod_id,i);
}
config->has_pcell_carrier_index = 1;
config->pcell_carrier_index = UE_PCCID(mod_id, i);
//TODO: Set carrier aggregation support (boolean)
config->has_ca_support = 0;
config->ca_support = 0;
if(config->has_ca_support){
//TODO: Set cross carrier scheduling support (boolean)
config->has_cross_carrier_sched_support = 1;
config->cross_carrier_sched_support = 0;
//TODO: Set secondary cells configuration
// We do not set it for now. No carrier aggregation support
//TODO: Set deactivation timer for secondary cell
config->has_scell_deactivation_timer = 0;
config->scell_deactivation_timer = 0;
}
if(flexran_get_ack_nack_repetition_factor(mod_id, i) != -1) {
config->has_ack_nack_repetition_factor = 1;
config->ack_nack_repetition_factor = flexran_get_ack_nack_repetition_factor(mod_id,i);
}
if(flexran_get_extended_bsr_size(mod_id, i) != -1) {
config->has_extended_bsr_size = 1;
config->extended_bsr_size = flexran_get_extended_bsr_size(mod_id,i);
}
config->has_pcell_carrier_index = 1;
config->pcell_carrier_index = UE_PCCID(mod_id, i);
//TODO: Set carrier aggregation support (boolean)
config->has_ca_support = 0;
config->ca_support = 0;
if(config->has_ca_support){
//TODO: Set cross carrier scheduling support (boolean)
config->has_cross_carrier_sched_support = 1;
config->cross_carrier_sched_support = 0;
//TODO: Set secondary cells configuration
// We do not set it for now. No carrier aggregation support
//TODO: Set deactivation timer for secondary cell
config->has_scell_deactivation_timer = 0;
config->scell_deactivation_timer = 0;
}
} else if (state_change == PROTOCOL__FLEX_UE_STATE_CHANGE_TYPE__FLUESC_MOVED) {
// TODO: Not supported for now. Leave blank
}
@@ -264,27 +264,31 @@ int flexran_agent_destroy_ue_state_change(Protocol__FlexranMessage *msg) {
/* this is called by RRC as a part of rrc xface . The controller previously requested this*/
void flexran_trigger_rrc_measurements (mid_t mod_id, MeasResults_t* measResults) {
int i;
//int i;
// int priority = 0; // Warning Preventing
// void *data;
// int size;
// err_code_t err_code = -100;
triggered_rrc = true;
int num;
//int num;
/* TODO do we need this at the current state? meas_stats is never put into a
* protobuf message?!
num = flexran_get_num_ues (mod_id);
meas_stats = malloc(sizeof(rrc_meas_stats) * num);
for (i = 0; i < num; i++){
meas_stats[i].rnti = flexran_get_ue_crnti(mod_id, i);
meas_stats[i].meas_id = flexran_get_rrc_pcell_measid(mod_id,i);
meas_stats[i].rsrp = flexran_get_rrc_pcell_rsrp(mod_id,i) - 140;
UE_id = flexran_get_ue_id(mod_id, i);
meas_stats[i].rnti = flexran_get_ue_crnti(mod_id, UE_id);
meas_stats[i].meas_id = flexran_get_rrc_pcell_measid(mod_id, UE_id);
meas_stats[i].rsrp = flexran_get_rrc_pcell_rsrp(mod_id, UE_id) - 140;
// measResults->measResultPCell.rsrpResult - 140;
meas_stats[i].rsrq = flexran_get_rrc_pcell_rsrq(mod_id,i)/2 - 20;
meas_stats[i].rsrq = flexran_get_rrc_pcell_rsrq(mod_id, UE_id)/2 - 20;
// (measResults->measResultPCell.rsrqResult)/2 - 20;
}
*/
// repl->neigh_meas = NULL;
// if (meas->measResultNeighCells != NULL) {
@@ -495,11 +499,14 @@ int flexran_agent_rrc_stats_reply(mid_t mod_id,
// Protocol__FlexHeader *header;
int i,j;
int UE_id;
/* Allocate memory for list of UE reports */
if (report_config->nr_ue > 0) {
for (i = 0; i < report_config->nr_ue; i++) {
UE_id = flexran_get_ue_id(mod_id, i);
/* 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) {
@@ -511,14 +518,14 @@ int flexran_agent_rrc_stats_reply(mid_t mod_id,
goto error;
protocol__flex_rrc_measurements__init(rrc_measurements);
rrc_measurements->measid = flexran_get_rrc_pcell_measid(mod_id,i);
rrc_measurements->has_measid = 1;
rrc_measurements->pcell_rsrp = flexran_get_rrc_pcell_rsrp(mod_id,i);
rrc_measurements->has_pcell_rsrp = 1;
rrc_measurements->pcell_rsrq = flexran_get_rrc_pcell_rsrq(mod_id,i);
rrc_measurements->has_pcell_rsrq = 1 ;
rrc_measurements->measid = flexran_get_rrc_pcell_measid(mod_id, UE_id);
rrc_measurements->has_measid = 1;
rrc_measurements->pcell_rsrp = flexran_get_rrc_pcell_rsrp(mod_id, UE_id);
rrc_measurements->has_pcell_rsrp = 1;
rrc_measurements->pcell_rsrq = flexran_get_rrc_pcell_rsrq(mod_id, UE_id);
rrc_measurements->has_pcell_rsrq = 1 ;
/* Target Cell, Neghibouring*/
@@ -529,7 +536,7 @@ int flexran_agent_rrc_stats_reply(mid_t mod_id,
protocol__flex_neigh_cells_measurements__init(neigh_meas);
neigh_meas->n_eutra_meas = flexran_get_rrc_num_ncell(mod_id, i);
neigh_meas->n_eutra_meas = flexran_get_rrc_num_ncell(mod_id, UE_id);
Protocol__FlexEutraMeasurements **eutra_meas = NULL;
@@ -547,7 +554,7 @@ int flexran_agent_rrc_stats_reply(mid_t mod_id,
protocol__flex_eutra_measurements__init(eutra_meas[j]);
eutra_meas[j]->phys_cell_id = flexran_get_rrc_neigh_phy_cell_id(mod_id, i, j);
eutra_meas[j]->phys_cell_id = flexran_get_rrc_neigh_phy_cell_id(mod_id, UE_id, j);
eutra_meas[j]->has_phys_cell_id = 1;
@@ -558,10 +565,10 @@ int flexran_agent_rrc_stats_reply(mid_t mod_id,
protocol__flex_eutra_ref_signal_meas__init(meas_result);
meas_result->rsrp = flexran_get_rrc_neigh_rsrp(mod_id, i, eutra_meas[j]->phys_cell_id);
meas_result->rsrp = flexran_get_rrc_neigh_rsrp(mod_id, UE_id, eutra_meas[j]->phys_cell_id);
meas_result->has_rsrp = 1;
meas_result->rsrq = flexran_get_rrc_neigh_rsrq(mod_id, i, eutra_meas[j]->phys_cell_id);
meas_result->rsrq = flexran_get_rrc_neigh_rsrq(mod_id, UE_id, eutra_meas[j]->phys_cell_id);
meas_result->has_rsrq = 1;
eutra_meas[j]->meas_result = meas_result;
@@ -625,8 +632,10 @@ int flexran_agent_rrc_stats_reply(mid_t mod_id,
for (i = 0; i < report_config->nr_ue; i++){
UE_id = flexran_get_ue_id(mod_id, i);
if (ue_report[i]->rrc_measurements->neigh_meas != NULL){
for (j = 0; j < flexran_get_rrc_num_ncell(mod_id, i); j++){
for (j = 0; j < flexran_get_rrc_num_ncell(mod_id, UE_id); j++){
free(ue_report[i]->rrc_measurements->neigh_meas->eutra_meas[j]);
}
@@ -58,6 +58,87 @@ enum flex_qam {
FLEQ_MOD_64QAM = 1;
}
//
// Slice config related structures and enums
//
enum flex_dl_sorting {
CR_ROUND = 0; // Highest HARQ first
CR_SRB12 = 1; // Highest SRB1+2 first
CR_HOL = 2; // Highest HOL first
CR_LC = 3; // Greatest RLC buffer first
CR_CQI = 4; // Highest CQI first
CR_LCP = 5; // Highest LC priority first
}
enum flex_ul_sorting {
CRU_ROUND = 0; // Highest HARQ first
CRU_BUF = 1; // Highest BSR first
CRU_BTS = 2; // More bytes to schedule first
CRU_MCS = 3; // Highest MCS first
CRU_LCP = 4; // Highest LC priority first
CRU_HOL = 5; // Highest HOL first
}
enum flex_dl_accounting_policy {
POL_FAIR = 0;
POL_GREEDY = 1;
POL_NUM = 2;
}
enum flex_ul_accounting_policy {
POLU_FAIR = 0;
POLU_GREEDY = 1;
POLU_NUM = 2;
}
enum flex_slice_label {
xMBB = 0;
URLLC = 1;
mMTC = 2;
xMTC = 3;
Other = 4;
}
message flex_dl_slice {
optional uint32 id = 1;
optional flex_slice_label label = 2;
// should be between 0 and 100
optional uint32 percentage = 3;
// whether this slice should be exempted form interslice sharing
optional bool isolation = 4;
// increasing value means increasing prio
optional uint32 priority = 5;
// min and max RB to use (in frequency) in the range [0, N_RBG_MAX]
optional uint32 position_low = 6;
optional uint32 position_high = 7;
// maximum MCS to be allowed in this slice
optional uint32 maxmcs = 8;
repeated flex_dl_sorting sorting = 9;
optional flex_dl_accounting_policy accounting = 10;
optional string scheduler_name = 11;
}
message flex_ul_slice {
optional uint32 id = 1;
optional flex_slice_label label = 2;
// should be between 0 and 100
optional uint32 percentage = 3;
// whether this slice should be exempted form interslice sharing
optional bool isolation = 4;
// increasing value means increasing prio
optional uint32 priority = 5;
// RB start to use (in frequency) in the range [0, N_RB_MAX]
optional uint32 first_rb = 6;
// TODO RB number
//optional uint32 length_rb = 7;
// maximum MCS to be allowed in this slice
optional uint32 maxmcs = 8;
repeated flex_ul_sorting sorting = 9;
optional flex_ul_accounting_policy accounting = 10;
optional string scheduler_name = 11;
}
//
// UE config related structures and enums
//
@@ -177,4 +258,4 @@ enum flex_ue_state_change_type {
FLUESC_ACTIVATED = 1;
FLUESC_DEACTIVATED = 2;
FLUESC_MOVED = 3;
}
}
@@ -43,6 +43,19 @@ message flex_cell_config {
optional uint32 eutra_band= 37; // operating band
optional int32 dl_pdsch_power = 38; // operating downlink power
optional int32 ul_pusch_power = 39; // operating uplink power
optional flex_slice_config slice_config = 42;
}
message flex_slice_config {
// whether remaining RBs after first intra-slice allocation will
// be allocated to UEs of the same slice
optional bool intraslice_share_active = 3;
// whether remaining RBs after slice allocation will be allocated
// to UEs of another slice. Isolated slices will be ignored.
optional bool interslice_share_active = 4;
repeated flex_dl_slice dl = 1;
repeated flex_ul_slice ul = 2;
}
message flex_ue_config {
@@ -82,6 +95,8 @@ message flex_ue_config {
repeated flex_scell_config scell_config = 28; // Secondary cells configuration
optional uint32 scell_deactivation_timer = 29;// Deactivation timer for secondary cell
optional uint64 imsi = 30;
optional uint32 dl_slice_id = 31;
optional uint32 ul_slice_id = 32;
}
message flex_lc_ue_config {
+1 -1
View File
@@ -43,7 +43,7 @@ int load_NB_IoT(void) {
RCConfig_NbIoT_f_t RCConfig;
loader_shlibfunc_t shlib_fdesc[]=NBIOT_INTERFACE_FLIST;
ret=load_module_shlib(NBIOT_MODULENAME,shlib_fdesc,sizeof(shlib_fdesc)/sizeof(loader_shlibfunc_t));
ret=load_module_shlib(NBIOT_MODULENAME,shlib_fdesc,sizeof(shlib_fdesc)/sizeof(loader_shlibfunc_t),NULL);
if (ret) {
return ret;
}
+189 -44
View File
@@ -35,17 +35,22 @@
#include "assertions.h"
#include "common/ran_context.h"
#include "log.h"
#include "common/utils/LOG/log.h"
#if defined(ENABLE_ITTI)
# include "intertask_interface.h"
# include "timer.h"
# if defined(ENABLE_USE_MME)
# include "s1ap_eNB.h"
# include "sctp_eNB_task.h"
# include "gtpv1u_eNB_task.h"
# else
# define EPC_MODE_ENABLED 0
# endif
# include "x2ap_eNB.h"
# include "x2ap_messages_types.h"
# define X2AP_ENB_REGISTER_RETRY_DELAY 10
#include "openair1/PHY/INIT/phy_init.h"
extern unsigned char NB_eNB_INST;
#endif
@@ -59,6 +64,8 @@ extern RAN_CONTEXT_t RC;
# define ENB_REGISTER_RETRY_DELAY 10
# endif
#include "targets/RT/USER/lte-softmodem.h"
/*------------------------------------------------------------------------------*/
/*
@@ -135,6 +142,30 @@ static uint32_t eNB_app_register(uint32_t enb_id_start, uint32_t enb_id_end)//,
# endif
#endif
/*------------------------------------------------------------------------------*/
static uint32_t eNB_app_register_x2(uint32_t enb_id_start, uint32_t enb_id_end)
{
uint32_t enb_id;
MessageDef *msg_p;
uint32_t register_enb_x2_pending = 0;
for (enb_id = enb_id_start; (enb_id < enb_id_end) ; enb_id++) {
{
msg_p = itti_alloc_new_message (TASK_ENB_APP, X2AP_REGISTER_ENB_REQ);
RCconfig_X2(msg_p, enb_id);
itti_send_msg_to_task (TASK_X2AP, ENB_MODULE_ID_TO_INSTANCE(enb_id), msg_p);
register_enb_x2_pending++;
}
}
return register_enb_x2_pending;
}
/*------------------------------------------------------------------------------*/
void *eNB_app_task(void *args_p)
{
@@ -143,10 +174,13 @@ void *eNB_app_task(void *args_p)
uint32_t enb_id_start = 0;
uint32_t enb_id_end = enb_id_start + enb_nb;
# if defined(ENABLE_USE_MME)
uint32_t register_enb_pending;
uint32_t register_enb_pending=0;
uint32_t registered_enb;
long enb_register_retry_timer_id;
# endif
uint32_t x2_register_enb_pending;
uint32_t x2_registered_enb;
long x2_enb_register_retry_timer_id;
uint32_t enb_id;
MessageDef *msg_p = NULL;
instance_t instance;
@@ -184,13 +218,17 @@ void *eNB_app_task(void *args_p)
# if defined(ENABLE_USE_MME)
/* Try to register each eNB */
registered_enb = 0;
register_enb_pending = eNB_app_register (enb_id_start, enb_id_end);//, enb_properties_p);
# else
registered_enb = 0;
register_enb_pending = eNB_app_register (enb_id_start, enb_id_end);//, enb_properties_p);
#else
/* Start L2L1 task */
msg_p = itti_alloc_new_message(TASK_ENB_APP, INITIALIZE_MESSAGE);
itti_send_msg_to_task(TASK_L2L1, INSTANCE_DEFAULT, msg_p);
# endif
msg_p = itti_alloc_new_message(TASK_ENB_APP, INITIALIZE_MESSAGE);
itti_send_msg_to_task(TASK_L2L1, INSTANCE_DEFAULT, msg_p);
#endif
/* Try to register each eNB with each other */
x2_registered_enb = 0;
x2_register_enb_pending = eNB_app_register_x2 (enb_id_start, enb_id_end);
do {
// Wait for a message
@@ -208,56 +246,62 @@ void *eNB_app_task(void *args_p)
LOG_I(ENB_APP, "Received %s\n", ITTI_MSG_NAME(msg_p));
break;
# if defined(ENABLE_USE_MME)
case SOFT_RESTART_MESSAGE:
handle_reconfiguration(instance);
break;
case S1AP_REGISTER_ENB_CNF:
LOG_I(ENB_APP, "[eNB %d] Received %s: associated MME %d\n", instance, ITTI_MSG_NAME (msg_p),
S1AP_REGISTER_ENB_CNF(msg_p).nb_mme);
# if defined(ENABLE_USE_MME)
LOG_I(ENB_APP, "[eNB %d] Received %s: associated MME %d\n", instance, ITTI_MSG_NAME (msg_p),
S1AP_REGISTER_ENB_CNF(msg_p).nb_mme);
DevAssert(register_enb_pending > 0);
register_enb_pending--;
DevAssert(register_enb_pending > 0);
register_enb_pending--;
/* Check if at least eNB is registered with one MME */
if (S1AP_REGISTER_ENB_CNF(msg_p).nb_mme > 0) {
registered_enb++;
}
/* Check if at least eNB is registered with one MME */
if (S1AP_REGISTER_ENB_CNF(msg_p).nb_mme > 0) {
registered_enb++;
}
/* Check if all register eNB requests have been processed */
if (register_enb_pending == 0) {
if (registered_enb == enb_nb) {
/* If all eNB are registered, start L2L1 task */
MessageDef *msg_init_p;
/* Check if all register eNB requests have been processed */
if (register_enb_pending == 0) {
if (registered_enb == enb_nb) {
/* If all eNB are registered, start L2L1 task */
MessageDef *msg_init_p;
msg_init_p = itti_alloc_new_message (TASK_ENB_APP, INITIALIZE_MESSAGE);
itti_send_msg_to_task (TASK_L2L1, INSTANCE_DEFAULT, msg_init_p);
msg_init_p = itti_alloc_new_message (TASK_ENB_APP, INITIALIZE_MESSAGE);
itti_send_msg_to_task (TASK_L2L1, INSTANCE_DEFAULT, msg_init_p);
} else {
LOG_W(ENB_APP, " %d eNB not associated with a MME, retrying registration in %d seconds ...\n",
enb_nb - registered_enb, ENB_REGISTER_RETRY_DELAY);
} else {
LOG_W(ENB_APP, " %d eNB not associated with a MME, retrying registration in %d seconds ...\n",
enb_nb - registered_enb, ENB_REGISTER_RETRY_DELAY);
/* Restart the eNB registration process in ENB_REGISTER_RETRY_DELAY seconds */
if (timer_setup (ENB_REGISTER_RETRY_DELAY, 0, TASK_ENB_APP, INSTANCE_DEFAULT, TIMER_ONE_SHOT,
NULL, &enb_register_retry_timer_id) < 0) {
LOG_E(ENB_APP, " Can not start eNB register retry timer, use \"sleep\" instead!\n");
sleep(ENB_REGISTER_RETRY_DELAY);
/* Restart the registration process */
registered_enb = 0;
register_enb_pending = eNB_app_register (enb_id_start, enb_id_end);//, enb_properties_p);
}
}
}
/* Restart the eNB registration process in ENB_REGISTER_RETRY_DELAY seconds */
if (timer_setup (ENB_REGISTER_RETRY_DELAY, 0, TASK_ENB_APP, INSTANCE_DEFAULT, TIMER_ONE_SHOT,
NULL, &enb_register_retry_timer_id) < 0) {
LOG_E(ENB_APP, " Can not start eNB register retry timer, use \"sleep\" instead!\n");
sleep(ENB_REGISTER_RETRY_DELAY);
/* Restart the registration process */
registered_enb = 0;
register_enb_pending = eNB_app_register (enb_id_start, enb_id_end);//, enb_properties_p);
}
}
}
#endif
break;
case S1AP_DEREGISTERED_ENB_IND:
LOG_W(ENB_APP, "[eNB %d] Received %s: associated MME %d\n", instance, ITTI_MSG_NAME (msg_p),
S1AP_DEREGISTERED_ENB_IND(msg_p).nb_mme);
if (EPC_MODE_ENABLED) {
LOG_W(ENB_APP, "[eNB %d] Received %s: associated MME %d\n", instance, ITTI_MSG_NAME (msg_p),
S1AP_DEREGISTERED_ENB_IND(msg_p).nb_mme);
/* TODO handle recovering of registration */
/* TODO handle recovering of registration */
}
break;
case TIMER_HAS_EXPIRED:
# if defined(ENABLE_USE_MME)
LOG_I(ENB_APP, " Received %s: timer_id %ld\n", ITTI_MSG_NAME (msg_p), TIMER_HAS_EXPIRED(msg_p).timer_id);
if (TIMER_HAS_EXPIRED (msg_p).timer_id == enb_register_retry_timer_id) {
@@ -266,8 +310,59 @@ void *eNB_app_task(void *args_p)
register_enb_pending = eNB_app_register (enb_id_start, enb_id_end);//, enb_properties_p);
}
break;
if (TIMER_HAS_EXPIRED (msg_p).timer_id == x2_enb_register_retry_timer_id) {
/* Restart the registration process */
x2_registered_enb = 0;
x2_register_enb_pending = eNB_app_register_x2 (enb_id_start, enb_id_end);
}
# endif
break;
case X2AP_DEREGISTERED_ENB_IND:
LOG_W(ENB_APP, "[eNB %d] Received %s: associated eNB %d\n", instance, ITTI_MSG_NAME (msg_p),
X2AP_DEREGISTERED_ENB_IND(msg_p).nb_x2);
/* TODO handle recovering of registration */
break;
case X2AP_REGISTER_ENB_CNF:
LOG_I(ENB_APP, "[eNB %d] Received %s: associated eNB %d\n", instance, ITTI_MSG_NAME (msg_p),
X2AP_REGISTER_ENB_CNF(msg_p).nb_x2);
DevAssert(x2_register_enb_pending > 0);
x2_register_enb_pending--;
/* Check if at least eNB is registered with one target eNB */
if (X2AP_REGISTER_ENB_CNF(msg_p).nb_x2 > 0) {
x2_registered_enb++;
}
/* Check if all register eNB requests have been processed */
if (x2_register_enb_pending == 0) {
if (x2_registered_enb == enb_nb) {
/* If all eNB are registered, start RRC HO task */
}else {
uint32_t x2_not_associated = enb_nb - x2_registered_enb;
LOG_W(ENB_APP, " %d eNB %s not associated with the target\n",
x2_not_associated, x2_not_associated > 1 ? "are" : "is");
// timer to retry
/* Restart the eNB registration process in ENB_REGISTER_RETRY_DELAY seconds */
if (timer_setup (X2AP_ENB_REGISTER_RETRY_DELAY, 0, TASK_ENB_APP,
INSTANCE_DEFAULT, TIMER_ONE_SHOT, NULL,
&x2_enb_register_retry_timer_id) < 0) {
LOG_E(ENB_APP, " Can not start eNB X2AP register: retry timer, use \"sleep\" instead!\n");
sleep(X2AP_ENB_REGISTER_RETRY_DELAY);
/* Restart the registration process */
x2_registered_enb = 0;
x2_register_enb_pending = eNB_app_register_x2 (enb_id_start, enb_id_end);
}
}
}
break;
default:
LOG_E(ENB_APP, "Received unexpected message %s\n", ITTI_MSG_NAME (msg_p));
@@ -283,3 +378,53 @@ void *eNB_app_task(void *args_p)
return NULL;
}
void handle_reconfiguration(module_id_t mod_id)
{
struct timespec start, end;
clock_gettime(CLOCK_MONOTONIC, &start);
flexran_agent_info_t *flexran = RC.flexran[mod_id];
LOG_I(ENB_APP, "lte-softmodem soft-restart requested\n");
if (ENB_WAIT == flexran->node_ctrl_state) {
/* this is already waiting, just release */
pthread_mutex_lock(&flexran->mutex_node_ctrl);
flexran->node_ctrl_state = ENB_NORMAL_OPERATION;
pthread_mutex_unlock(&flexran->mutex_node_ctrl);
pthread_cond_signal(&flexran->cond_node_ctrl);
return;
}
if (stop_L1L2(mod_id) < 0) {
LOG_E(ENB_APP, "can not stop lte-softmodem, aborting restart\n");
return;
}
/* node_ctrl_state should have value ENB_MAKE_WAIT only if this method is not
* executed by the FlexRAN thread */
if (ENB_MAKE_WAIT == flexran->node_ctrl_state) {
LOG_I(ENB_APP, " * eNB %d: Waiting for FlexRAN RTController command *\n", mod_id);
pthread_mutex_lock(&flexran->mutex_node_ctrl);
flexran->node_ctrl_state = ENB_WAIT;
while (ENB_NORMAL_OPERATION != flexran->node_ctrl_state)
pthread_cond_wait(&flexran->cond_node_ctrl, &flexran->mutex_node_ctrl);
pthread_mutex_unlock(&flexran->mutex_node_ctrl);
}
if (restart_L1L2(mod_id) < 0) {
LOG_E(ENB_APP, "can not restart, killing lte-softmodem\n");
exit_fun("can not restart L1L2, killing lte-softmodem");
return;
}
clock_gettime(CLOCK_MONOTONIC, &end);
end.tv_sec -= start.tv_sec;
if (end.tv_nsec >= start.tv_nsec) {
end.tv_nsec -= start.tv_nsec;
} else {
end.tv_sec -= 1;
end.tv_nsec = end.tv_nsec - start.tv_nsec + 1000000000;
}
LOG_I(ENB_APP, "lte-softmodem restart succeeded in %ld.%ld s\n", end.tv_sec, end.tv_nsec / 1000000);
}
+2 -2
View File
@@ -31,11 +31,11 @@
#define ENB_APP_H_
#include <stdint.h>
#include "platform_types.h"
void *eNB_app_task(void *args_p);
/* needed for flexran: start PHY and RRC when restarting */
void enb_app_start_phy_rrc(uint32_t enb_id_start, uint32_t enb_id_end);
void handle_reconfiguration(module_id_t mod_id);
#endif /* ENB_APP_H_ */
+2162 -2067
View File
File diff suppressed because it is too large Load Diff
+2 -1
View File
@@ -46,8 +46,8 @@
#else
#include "RRC/LTE/MESSAGES/SystemInformationBlockType2.h"
#endif
#include "intertask_interface_types.h"
#include "RRC/LTE/rrc_defs.h"
#include <intertask_interface.h>
#define IPV4_STR_ADDR_TO_INT_NWBO(AdDr_StR,NwBo,MeSsAgE ) do {\
struct in_addr inp;\
@@ -106,6 +106,7 @@ void ru_config_display(void);
int RCconfig_RRC(MessageDef *msg_p, uint32_t i, eNB_RRC_INST *rrc);
int RCconfig_S1(MessageDef *msg_p, uint32_t i);
int RCconfig_X2(MessageDef *msg_p, uint32_t i);
#endif /* ENB_CONFIG_H_ */
/** @} */
+129 -26
View File
@@ -55,11 +55,6 @@
#if defined(ENABLE_ITTI) && defined(ENABLE_USE_MME)
extern int asn_debug;
extern int asn1_xer_print;
#endif
#ifdef LIBCONFIG_LONG
#define libconfig_int long
#else
@@ -102,6 +97,8 @@ typedef enum {
#define CONFIG_STRING_RU_MAX_RXGAIN "max_rxgain"
#define CONFIG_STRING_RU_IF_COMPRESSION "if_compression"
#define CONFIG_STRING_RU_NBIOTRRC_LIST "NbIoT_RRC_instances"
#define CONFIG_STRING_RU_SDR_ADDRS "sdr_addrs"
#define CONFIG_STRING_RU_SDR_CLK_SRC "clock_src"
#define RU_LOCAL_IF_NAME_IDX 0
#define RU_LOCAL_ADDRESS_IDX 1
@@ -121,6 +118,8 @@ typedef enum {
#define RU_ATT_TX_IDX 15
#define RU_ATT_RX_IDX 16
#define RU_NBIOTRRC_LIST_IDX 17
#define RU_SDR_ADDRS 18
#define RU_SDR_CLK_SRC 19
@@ -147,6 +146,8 @@ typedef enum {
{CONFIG_STRING_RU_ATT_TX, NULL, 0, uptr:NULL, defintval:0, TYPE_UINT, 0}, \
{CONFIG_STRING_RU_ATT_RX, NULL, 0, uptr:NULL, defintval:0, TYPE_UINT, 0}, \
{CONFIG_STRING_RU_NBIOTRRC_LIST, NULL, 0, uptr:NULL, defintarrayval:DEFENBS, TYPE_INTARRAY, 1}, \
{CONFIG_STRING_RU_SDR_ADDRS, NULL, 0, strptr:NULL, defstrval:"type=b200", TYPE_STRING, 0}, \
{CONFIG_STRING_RU_SDR_CLK_SRC, NULL, 0, strptr:NULL, defstrval:"internal", TYPE_STRING, 0}, \
}
/*---------------------------------------------------------------------------------------------------------------------------------------*/
@@ -160,25 +161,19 @@ typedef enum {
/* global parameters, not under a specific section */
#define ENB_CONFIG_STRING_ASN1_VERBOSITY "Asn1_verbosity"
#define ENB_CONFIG_STRING_ACTIVE_ENBS "Active_eNBs"
#define ENB_CONFIG_STRING_NOS1 "noS1"
/*--------------------------------------------------------------------------------------------------------------------------------------------------------------*/
/* global configuration parameters */
/* optname helpstr paramflags XXXptr defXXXval type numelt */
/* optname helpstr paramflags XXXptr defXXXval type numelt */
/*--------------------------------------------------------------------------------------------------------------------------------------------------------------*/
#define ENBSPARAMS_DESC { \
{ENB_CONFIG_STRING_ASN1_VERBOSITY, NULL, 0, uptr:NULL, defstrval:ENB_CONFIG_STRING_ASN1_VERBOSITY_NONE, TYPE_STRING, 0}, \
{ENB_CONFIG_STRING_ACTIVE_ENBS, NULL, 0, uptr:NULL, defstrval:NULL, TYPE_STRINGLIST, 0} \
{ENB_CONFIG_STRING_ASN1_VERBOSITY, NULL, 0, uptr:NULL, defstrval:ENB_CONFIG_STRING_ASN1_VERBOSITY_NONE, TYPE_STRING, 0}, \
{ENB_CONFIG_STRING_ACTIVE_ENBS, NULL, 0, uptr:NULL, defstrval:NULL, TYPE_STRINGLIST, 0}, \
{ENB_CONFIG_STRING_NOS1, NULL, PARAMFLAG_BOOL, uptr:NULL, defintval:0, TYPE_UINT, 0}, \
}
#define ENB_ASN1_VERBOSITY_IDX 0
#define ENB_ACTIVE_ENBS_IDX 1
/*
{ENB_CONFIG_STRING_COMPONENT_CARRIERS,"", "", 0, uptr:NULL,defstrval:ENB_CONFIG_STRING_ASN1_VERBOSITY_NONE,TYPE_STRING,0}, \
{ENB_CONFIG_STRING_CC_NODE_FUNCTION,"", "", 0, uptr:NULL,defstrval:ENB_CONFIG_STRING_ASN1_VERBOSITY_NONE,TYPE_STRING,0}, \
{ENB_CONFIG_STRING_CC_NODE_TIMING,"", "", 0, uptr:NULL,defstrval:ENB_CONFIG_STRING_ASN1_VERBOSITY_NONE,TYPE_STRING,0}, \
{ENB_CONFIG_STRING_CC_NODE_SYNCH_REF,"", "", 0, uptr:NULL,defstrval:ENB_CONFIG_STRING_ASN1_VERBOSITY_NONE,TYPE_STRING,0}, \
*/
#define ENB_NOS1_IDX 2
/*------------------------------------------------------------------------------------------------------------------------------------------*/
@@ -190,8 +185,8 @@ typedef enum {
#define ENB_CONFIG_STRING_CELL_TYPE "cell_type"
#define ENB_CONFIG_STRING_ENB_NAME "eNB_name"
#define ENB_CONFIG_STRING_TRACKING_AREA_CODE "tracking_area_code"
#define ENB_CONFIG_STRING_MOBILE_COUNTRY_CODE "mobile_country_code"
#define ENB_CONFIG_STRING_MOBILE_NETWORK_CODE "mobile_network_code"
#define ENB_CONFIG_STRING_MOBILE_COUNTRY_CODE_OLD "mobile_country_code"
#define ENB_CONFIG_STRING_MOBILE_NETWORK_CODE_OLD "mobile_network_code"
#define ENB_CONFIG_STRING_TRANSPORT_S_PREFERENCE "tr_s_preference"
#define ENB_CONFIG_STRING_LOCAL_S_IF_NAME "local_s_if_name"
#define ENB_CONFIG_STRING_LOCAL_S_ADDRESS "local_s_address"
@@ -209,9 +204,9 @@ typedef enum {
{ENB_CONFIG_STRING_ENB_ID, NULL, 0, uptr:NULL, defintval:0, TYPE_UINT, 0}, \
{ENB_CONFIG_STRING_CELL_TYPE, NULL, 0, strptr:NULL, defstrval:"CELL_MACRO_ENB", TYPE_STRING, 0}, \
{ENB_CONFIG_STRING_ENB_NAME, NULL, 0, strptr:NULL, defstrval:"OAIeNodeB", TYPE_STRING, 0}, \
{ENB_CONFIG_STRING_TRACKING_AREA_CODE, NULL, 0, strptr:NULL, defstrval:"0", TYPE_STRING, 0}, \
{ENB_CONFIG_STRING_MOBILE_COUNTRY_CODE, NULL, 0, strptr:NULL, defstrval:"0", TYPE_STRING, 0}, \
{ENB_CONFIG_STRING_MOBILE_NETWORK_CODE, NULL, 0, strptr:NULL, defstrval:"0", TYPE_STRING, 0}, \
{ENB_CONFIG_STRING_TRACKING_AREA_CODE, NULL, 0, uptr:NULL, defuintval:0, TYPE_UINT, 0}, \
{ENB_CONFIG_STRING_MOBILE_COUNTRY_CODE_OLD, NULL, 0, strptr:NULL, defstrval:NULL, TYPE_STRING, 0}, \
{ENB_CONFIG_STRING_MOBILE_NETWORK_CODE_OLD, NULL, 0, strptr:NULL, defstrval:NULL, TYPE_STRING, 0}, \
{ENB_CONFIG_STRING_TRANSPORT_S_PREFERENCE, NULL, 0, strptr:NULL, defstrval:"local_mac", TYPE_STRING, 0}, \
{ENB_CONFIG_STRING_LOCAL_S_IF_NAME, NULL, 0, strptr:NULL, defstrval:"lo", TYPE_STRING, 0}, \
{ENB_CONFIG_STRING_LOCAL_S_ADDRESS, NULL, 0, strptr:NULL, defstrval:"127.0.0.1", TYPE_STRING, 0}, \
@@ -225,8 +220,8 @@ typedef enum {
#define ENB_CELL_TYPE_IDX 1
#define ENB_ENB_NAME_IDX 2
#define ENB_TRACKING_AREA_CODE_IDX 3
#define ENB_MOBILE_COUNTRY_CODE_IDX 4
#define ENB_MOBILE_NETWORK_CODE_IDX 5
#define ENB_MOBILE_COUNTRY_CODE_IDX_OLD 4
#define ENB_MOBILE_NETWORK_CODE_IDX_OLD 5
#define ENB_TRANSPORT_S_PREFERENCE_IDX 6
#define ENB_LOCAL_S_IF_NAME_IDX 7
#define ENB_LOCAL_S_ADDRESS_IDX 8
@@ -235,9 +230,56 @@ typedef enum {
#define ENB_REMOTE_S_PORTC_IDX 11
#define ENB_LOCAL_S_PORTD_IDX 12
#define ENB_REMOTE_S_PORTD_IDX 13
#define TRACKING_AREA_CODE_OKRANGE {0x0001,0xFFFD}
#define ENBPARAMS_CHECK { \
{ .s5 = { NULL } }, \
{ .s5 = { NULL } }, \
{ .s5 = { NULL } }, \
{ .s2 = { config_check_intrange, TRACKING_AREA_CODE_OKRANGE } },\
{ .s5 = { NULL } }, \
{ .s5 = { NULL } }, \
{ .s5 = { NULL } }, \
{ .s5 = { NULL } }, \
{ .s5 = { NULL } }, \
{ .s5 = { NULL } }, \
{ .s5 = { NULL } }, \
{ .s5 = { NULL } }, \
{ .s5 = { NULL } }, \
{ .s5 = { NULL } }, \
}
/*-------------------------------------------------------------------------------------------------------------------------------------------------*/
/*-------------------------------------------------------------------------------------------------------------------------------------------------*/
/* PLMN ID configuration */
#define ENB_CONFIG_STRING_PLMN_LIST "plmn_list"
#define ENB_CONFIG_STRING_MOBILE_COUNTRY_CODE "mcc"
#define ENB_CONFIG_STRING_MOBILE_NETWORK_CODE "mnc"
#define ENB_CONFIG_STRING_MNC_DIGIT_LENGTH "mnc_length"
#define ENB_MOBILE_COUNTRY_CODE_IDX 0
#define ENB_MOBILE_NETWORK_CODE_IDX 1
#define ENB_MNC_DIGIT_LENGTH 2
#define PLMNPARAMS_DESC { \
/* optname helpstr paramflags XXXptr def val type numelt */ \
{ENB_CONFIG_STRING_MOBILE_COUNTRY_CODE, "mobile country code", 0, uptr:NULL, defuintval:1000, TYPE_UINT, 0}, \
{ENB_CONFIG_STRING_MOBILE_NETWORK_CODE, "mobile network code", 0, uptr:NULL, defuintval:1000, TYPE_UINT, 0}, \
{ENB_CONFIG_STRING_MNC_DIGIT_LENGTH, "length of the MNC (2 or 3)", 0, uptr:NULL, defuintval:0, TYPE_UINT, 0}, \
}
#define MCC_MNC_OKRANGES {0,999}
#define MNC_DIGIT_LENGTH_OKVALUES {2,3}
#define PLMNPARAMS_CHECK { \
{ .s2 = { config_check_intrange, MCC_MNC_OKRANGES } }, \
{ .s2 = { config_check_intrange, MCC_MNC_OKRANGES } }, \
{ .s1 = { config_check_intval, MNC_DIGIT_LENGTH_OKVALUES, 2 } }, \
}
/* component carries configuration parameters name */
@@ -686,6 +728,7 @@ typedef enum {
#define ENB_CONFIG_STRING_MME_IPV6_ADDRESS "ipv6"
#define ENB_CONFIG_STRING_MME_IP_ADDRESS_ACTIVE "active"
#define ENB_CONFIG_STRING_MME_IP_ADDRESS_PREFERENCE "preference"
#define ENB_CONFIG_STRING_MME_BROADCAST_PLMN_INDEX "broadcast_plmn_index"
/*-------------------------------------------------------------------------------------------------------------------------------------*/
@@ -697,13 +740,40 @@ typedef enum {
{ENB_CONFIG_STRING_MME_IPV6_ADDRESS, NULL, 0, uptr:NULL, defstrval:NULL, TYPE_STRING, 0}, \
{ENB_CONFIG_STRING_MME_IP_ADDRESS_ACTIVE, NULL, 0, uptr:NULL, defstrval:NULL, TYPE_STRING, 0}, \
{ENB_CONFIG_STRING_MME_IP_ADDRESS_PREFERENCE, NULL, 0, uptr:NULL, defstrval:NULL, TYPE_STRING, 0}, \
{ENB_CONFIG_STRING_MME_BROADCAST_PLMN_INDEX, NULL, 0, uptr:NULL, defintarrayval:NULL,TYPE_UINTARRAY, 6} \
}
#define ENB_MME_IPV4_ADDRESS_IDX 0
#define ENB_MME_IPV6_ADDRESS_IDX 1
#define ENB_MME_IP_ADDRESS_ACTIVE_IDX 2
#define ENB_MME_IP_ADDRESS_PREFERENCE_IDX 3
#define ENB_MME_BROADCAST_PLMN_INDEX 4
/*---------------------------------------------------------------------------------------------------------------------------------------*/
/* X2 configuration parameters section name */
#define ENB_CONFIG_STRING_TARGET_ENB_X2_IP_ADDRESS "target_enb_x2_ip_address"
/* X2 configuration parameters names */
#define ENB_CONFIG_STRING_TARGET_ENB_X2_IPV4_ADDRESS "ipv4"
#define ENB_CONFIG_STRING_TARGET_ENB_X2_IPV6_ADDRESS "ipv6"
#define ENB_CONFIG_STRING_TARGET_ENB_X2_IP_ADDRESS_PREFERENCE "preference"
/*-------------------------------------------------------------------------------------------------------------------------------------*/
/* X2 configuration parameters */
/* optname helpstr paramflags XXXptr defXXXval type numelt */
/*-------------------------------------------------------------------------------------------------------------------------------------*/
#define X2PARAMS_DESC { \
{ENB_CONFIG_STRING_TARGET_ENB_X2_IPV4_ADDRESS, NULL, 0, uptr:NULL, defstrval:NULL, TYPE_STRING, 0}, \
{ENB_CONFIG_STRING_TARGET_ENB_X2_IPV6_ADDRESS, NULL, 0, uptr:NULL, defstrval:NULL, TYPE_STRING, 0}, \
{ENB_CONFIG_STRING_TARGET_ENB_X2_IP_ADDRESS_PREFERENCE, NULL, 0, uptr:NULL, defstrval:NULL, TYPE_STRING, 0}, \
}
#define ENB_X2_IPV4_ADDRESS_IDX 0
#define ENB_X2_IPV6_ADDRESS_IDX 1
#define ENB_X2_IP_ADDRESS_PREFERENCE_IDX 2
/*---------------------------------------------------------------------------------------------------------------------------------------*/
/* SCTP configuration parameters section name */
#define ENB_CONFIG_STRING_SCTP_CONFIG "SCTP"
@@ -735,6 +805,8 @@ typedef enum {
#define ENB_INTERFACE_NAME_FOR_S1U_IDX 2
#define ENB_IPV4_ADDR_FOR_S1U_IDX 3
#define ENB_PORT_FOR_S1U_IDX 4
#define ENB_IPV4_ADDR_FOR_X2C_IDX 5
#define ENB_PORT_FOR_X2C_IDX 6
/* S1 interface configuration parameters names */
#define ENB_CONFIG_STRING_ENB_INTERFACE_NAME_FOR_S1_MME "ENB_INTERFACE_NAME_FOR_S1_MME"
@@ -743,8 +815,12 @@ typedef enum {
#define ENB_CONFIG_STRING_ENB_IPV4_ADDR_FOR_S1U "ENB_IPV4_ADDRESS_FOR_S1U"
#define ENB_CONFIG_STRING_ENB_PORT_FOR_S1U "ENB_PORT_FOR_S1U"
/* X2 interface configuration parameters names */
#define ENB_CONFIG_STRING_ENB_IPV4_ADDR_FOR_X2C "ENB_IPV4_ADDRESS_FOR_X2C"
#define ENB_CONFIG_STRING_ENB_PORT_FOR_X2C "ENB_PORT_FOR_X2C"
/*--------------------------------------------------------------------------------------------------------------------------------------------------*/
/* S1 interface configuration parameters */
/* S1/X2 interface configuration parameters */
/* optname helpstr paramflags XXXptr defXXXval type numelt */
/*--------------------------------------------------------------------------------------------------------------------------------------------------*/
#define NETPARAMS_DESC { \
@@ -752,7 +828,9 @@ typedef enum {
{ENB_CONFIG_STRING_ENB_IPV4_ADDRESS_FOR_S1_MME, NULL, 0, strptr:NULL, defstrval:NULL, TYPE_STRING, 0}, \
{ENB_CONFIG_STRING_ENB_INTERFACE_NAME_FOR_S1U, NULL, 0, strptr:NULL, defstrval:NULL, TYPE_STRING, 0}, \
{ENB_CONFIG_STRING_ENB_IPV4_ADDR_FOR_S1U, NULL, 0, strptr:NULL, defstrval:NULL, TYPE_STRING, 0}, \
{ENB_CONFIG_STRING_ENB_PORT_FOR_S1U, NULL, 0, uptr:NULL, defintval:2152L, TYPE_UINT, 0} \
{ENB_CONFIG_STRING_ENB_PORT_FOR_S1U, NULL, 0, uptr:NULL, defintval:2152L, TYPE_UINT, 0}, \
{ENB_CONFIG_STRING_ENB_IPV4_ADDR_FOR_X2C, NULL, 0, strptr:NULL, defstrval:NULL, TYPE_STRING, 0}, \
{ENB_CONFIG_STRING_ENB_PORT_FOR_X2C, NULL, 0, uptr:NULL, defintval:0L, TYPE_UINT, 0}, \
}
@@ -851,3 +929,28 @@ typedef enum {
#define MACRLC_SCHED_MODE_IDX 17
#define MACRLC_PHY_TEST_IDX 18
/*---------------------------------------------------------------------------------------------------------------------------------------------------------*/
/* thread configuration parameters section name */
#define THREAD_CONFIG_STRING_THREAD_STRUCT "THREAD_STRUCT"
/* thread configuration parameters names */
#define THREAD_CONFIG_STRING_PARALLEL "parallel_config"
#define THREAD_CONFIG_STRING_WORKER "worker_config"
#define THREAD_PARALLEL_IDX 0
#define THREAD_WORKER_IDX 1
/*-------------------------------------------------------------------------------------------------------------------------------------------------------------*/
/* thread configuration parameters */
/* optname helpstr paramflags XXXptr defXXXval type numelt */
/*-------------------------------------------------------------------------------------------------------------------------------------------------------------*/
#define THREAD_CONF_DESC { \
{THREAD_CONFIG_STRING_PARALLEL, CONFIG_HLP_PARALLEL, 0, strptr:NULL, defstrval:"PARALLEL_RU_L1_TRX_SPLIT", TYPE_STRING, 0}, \
{THREAD_CONFIG_STRING_WORKER, CONFIG_HLP_WORKER, 0, strptr:NULL, defstrval:"WORKER_ENABLE", TYPE_STRING, 0} \
}
#define CONFIG_HLP_WORKER "coding and FEP worker thread WORKER_DISABLE or WORKER_ENABLE\n"
#define CONFIG_HLP_PARALLEL "PARALLEL_SINGLE_THREAD, PARALLEL_RU_L1_SPLIT, or PARALLEL_RU_L1_TRX_SPLIT(RU_L1_TRX_SPLIT by defult)\n"
/*-------------------------------------------------------------------------------------------------------------------------------------------------------------*/
+1 -1
View File
@@ -39,7 +39,7 @@
#include "flexran_agent_mac.h"
#include "flexran_agent_rrc.h"
#include "flexran_agent_pdcp.h"
#include "log.h"
#include "common/utils/LOG/log.h"
#include "assertions.h"
/* Initiation of the eNodeB agent */
+126 -55
View File
@@ -36,7 +36,8 @@
#include "flexran_agent_net_comm.h"
#include "flexran_agent_ran_api.h"
//#include "PHY/extern.h"
#include "log.h"
#include "common/utils/LOG/log.h"
#include "flexran_agent_mac_internal.h"
//#include "SCHED/defs.h"
#include "RRC/LTE/rrc_extern.h"
@@ -287,6 +288,23 @@ int flexran_agent_destroy_enb_config_reply(Protocol__FlexranMessage *msg) {
free(reply->cell_config[i]->si_config->si_message);
free(reply->cell_config[i]->si_config);
}
if (reply->cell_config[i]->slice_config != NULL) {
for (j = 0; j < reply->cell_config[i]->slice_config->n_dl; ++j) {
if (reply->cell_config[i]->slice_config->dl[j]->n_sorting > 0)
free(reply->cell_config[i]->slice_config->dl[j]->sorting);
free(reply->cell_config[i]->slice_config->dl[j]->scheduler_name);
free(reply->cell_config[i]->slice_config->dl[j]);
}
free(reply->cell_config[i]->slice_config->dl);
for (j = 0; j < reply->cell_config[i]->slice_config->n_ul; ++j) {
if (reply->cell_config[i]->slice_config->ul[j]->n_sorting > 0)
free(reply->cell_config[i]->slice_config->ul[j]->sorting);
free(reply->cell_config[i]->slice_config->ul[j]->scheduler_name);
free(reply->cell_config[i]->slice_config->ul[j]);
}
free(reply->cell_config[i]->slice_config->ul);
free(reply->cell_config[i]->slice_config);
}
free(reply->cell_config[i]);
}
free(reply->cell_config);
@@ -396,8 +414,14 @@ int flexran_agent_control_delegation(mid_t mod_id, const void *params, Protocol_
FILE *f;
f = fopen(target, "wb");
fwrite(control_delegation_msg->payload.data, control_delegation_msg->payload.len, 1, f);
fclose(f);
if (f) {
fwrite(control_delegation_msg->payload.data, control_delegation_msg->payload.len, 1, f);
fclose(f);
}
else {
LOG_W(FLEXRAN_AGENT, "[%d] can not write control delegation data to %s\n",
mod_id, target);
}
// long time_elapsed_nanos = timer_end(vartime);
*msg = NULL;
@@ -435,6 +459,7 @@ int flexran_agent_lc_config_reply(mid_t mod_id, const void *params, Protocol__Fl
xid = (lc_config_request_msg->header)->xid;
int i, j;
int UE_id;
Protocol__FlexLcConfigReply *lc_config_reply_msg;
lc_config_reply_msg = malloc(sizeof(Protocol__FlexLcConfigReply));
@@ -460,13 +485,15 @@ int flexran_agent_lc_config_reply(mid_t mod_id, const void *params, Protocol__Fl
lc_ue_config[i] = malloc(sizeof(Protocol__FlexLcUeConfig));
protocol__flex_lc_ue_config__init(lc_ue_config[i]);
UE_id = flexran_get_ue_id(mod_id, i);
lc_ue_config[i]->has_rnti = 1;
lc_ue_config[i]->rnti = flexran_get_ue_crnti(mod_id,i);
lc_ue_config[i]->rnti = flexran_get_ue_crnti(mod_id, UE_id);
//TODO: Set the number of LC configurations that will be reported for this UE
//Set this according to the current state of the UE. This is only a temporary fix
int status = 0;
status = mac_eNB_get_rrc_status(mod_id, flexran_get_ue_crnti(mod_id, i));
status = mac_eNB_get_rrc_status(mod_id, flexran_get_ue_crnti(mod_id, UE_id));
/* TODO needs to be revised and appropriate API to be implemented */
if (status < RRC_CONNECTED) {
lc_ue_config[i]->n_lc_config = 0;
@@ -489,14 +516,14 @@ int flexran_agent_lc_config_reply(mid_t mod_id, const void *params, Protocol__Fl
lc_config[j]->has_lcid = 1;
lc_config[j]->lcid = j+1;
int lcg = flexran_get_lcg(mod_id, i, j+1);
int lcg = flexran_get_lcg(mod_id, UE_id, j+1);
if (lcg >= 0 && lcg <= 3) {
lc_config[j]->has_lcg = 1;
lc_config[j]->lcg = flexran_get_lcg(mod_id, i,j+1);
lc_config[j]->lcg = flexran_get_lcg(mod_id, UE_id, j+1);
}
lc_config[j]->has_direction = 1;
lc_config[j]->direction = flexran_get_direction(i,j+1);
lc_config[j]->direction = flexran_get_direction(UE_id, j+1);
//TODO: Bearer type. One of FLQBT_* values. Currently only default bearer supported
lc_config[j]->has_qos_bearer_type = 1;
lc_config[j]->qos_bearer_type = PROTOCOL__FLEX_QOS_BEARER_TYPE__FLQBT_NON_GBR;
@@ -563,6 +590,7 @@ int flexran_agent_ue_config_reply(mid_t mod_id, const void *params, Protocol__Fl
xid = (ue_config_request_msg->header)->xid;
int i;
int UE_id;
Protocol__FlexUeConfigReply *ue_config_reply_msg;
ue_config_reply_msg = malloc(sizeof(Protocol__FlexUeConfigReply));
@@ -587,26 +615,31 @@ int flexran_agent_ue_config_reply(mid_t mod_id, const void *params, Protocol__Fl
ue_config[i] = malloc(sizeof(Protocol__FlexUeConfig));
protocol__flex_ue_config__init(ue_config[i]);
ue_config[i]->rnti = flexran_get_ue_crnti(mod_id,i);
UE_id = flexran_get_ue_id(mod_id, i);
ue_config[i]->rnti = flexran_get_ue_crnti(mod_id, UE_id);
ue_config[i]->has_rnti = 1;
ue_config[i]->imsi = flexran_get_ue_imsi(mod_id, i);
ue_config[i]->imsi = flexran_get_ue_imsi(mod_id, UE_id);
ue_config[i]->has_imsi = 1;
ue_config[i]->dl_slice_id = flexran_get_ue_dl_slice_id(mod_id, UE_id);
ue_config[i]->has_dl_slice_id = 1;
ue_config[i]->ul_slice_id = flexran_get_ue_ul_slice_id(mod_id, UE_id);
ue_config[i]->has_ul_slice_id = 1;
//TODO: Set the DRX configuration (optional)
//Not supported for now, so we do not set it
if (flexran_get_time_alignment_timer(mod_id,i) != -1) {
ue_config[i]->time_alignment_timer = flexran_get_time_alignment_timer(mod_id,i);
ue_config[i]->has_time_alignment_timer = 1;
if (flexran_get_time_alignment_timer(mod_id, UE_id) != -1) {
ue_config[i]->time_alignment_timer = flexran_get_time_alignment_timer(mod_id, UE_id);
ue_config[i]->has_time_alignment_timer = 1;
}
if (flexran_get_meas_gap_config(mod_id,i) != -1) {
ue_config[i]->meas_gap_config_pattern = flexran_get_meas_gap_config(mod_id,i);
ue_config[i]->has_meas_gap_config_pattern = 1;
if (flexran_get_meas_gap_config(mod_id, UE_id) != -1) {
ue_config[i]->meas_gap_config_pattern = flexran_get_meas_gap_config(mod_id, UE_id);
ue_config[i]->has_meas_gap_config_pattern = 1;
}
if (ue_config[i]->has_meas_gap_config_pattern == 1 &&
ue_config[i]->meas_gap_config_pattern != PROTOCOL__FLEX_MEAS_GAP_CONFIG_PATTERN__FLMGCP_OFF) {
ue_config[i]->meas_gap_config_sf_offset = flexran_get_meas_gap_config_offset(mod_id,i);
ue_config[i]->meas_gap_config_pattern != PROTOCOL__FLEX_MEAS_GAP_CONFIG_PATTERN__FLMGCP_OFF) {
ue_config[i]->meas_gap_config_sf_offset = flexran_get_meas_gap_config_offset(mod_id, UE_id);
ue_config[i]->has_meas_gap_config_sf_offset = 1;
}
//TODO: Set the SPS configuration (Optional)
@@ -618,77 +651,77 @@ int flexran_agent_ue_config_reply(mid_t mod_id, const void *params, Protocol__Fl
//TODO: Set the CQI configuration (Optional)
//We do not set it for now
if (flexran_get_ue_transmission_mode(mod_id,i) != -1) {
ue_config[i]->transmission_mode = flexran_get_ue_transmission_mode(mod_id,i);
if (flexran_get_ue_transmission_mode(mod_id, UE_id) != -1) {
ue_config[i]->transmission_mode = flexran_get_ue_transmission_mode(mod_id, UE_id);
ue_config[i]->has_transmission_mode = 1;
}
ue_config[i]->ue_aggregated_max_bitrate_ul = flexran_get_ue_aggregated_max_bitrate_ul(mod_id,i);
ue_config[i]->ue_aggregated_max_bitrate_ul = flexran_get_ue_aggregated_max_bitrate_ul(mod_id, UE_id);
ue_config[i]->has_ue_aggregated_max_bitrate_ul = 1;
ue_config[i]->ue_aggregated_max_bitrate_dl = flexran_get_ue_aggregated_max_bitrate_dl(mod_id,i);
ue_config[i]->ue_aggregated_max_bitrate_dl = flexran_get_ue_aggregated_max_bitrate_dl(mod_id, UE_id);
ue_config[i]->has_ue_aggregated_max_bitrate_dl = 1;
Protocol__FlexUeCapabilities *capabilities;
capabilities = malloc(sizeof(Protocol__FlexUeCapabilities));
protocol__flex_ue_capabilities__init(capabilities);
capabilities->has_half_duplex = 1;
capabilities->half_duplex = flexran_get_half_duplex(mod_id, i);
capabilities->half_duplex = flexran_get_half_duplex(mod_id, UE_id);
capabilities->has_intra_sf_hopping = 1;
capabilities->intra_sf_hopping = flexran_get_intra_sf_hopping(mod_id, i);
capabilities->intra_sf_hopping = flexran_get_intra_sf_hopping(mod_id, UE_id);
capabilities->has_type2_sb_1 = 1;
capabilities->type2_sb_1 = flexran_get_type2_sb_1(mod_id, i);
capabilities->type2_sb_1 = flexran_get_type2_sb_1(mod_id, UE_id);
capabilities->has_ue_category = 1;
capabilities->ue_category = flexran_get_ue_category(mod_id, i);
capabilities->ue_category = flexran_get_ue_category(mod_id, UE_id);
capabilities->has_res_alloc_type1 = 1;
capabilities->res_alloc_type1 = flexran_get_res_alloc_type1(mod_id, i);
capabilities->res_alloc_type1 = flexran_get_res_alloc_type1(mod_id, UE_id);
//Set the capabilites to the message
ue_config[i]->capabilities = capabilities;
if (flexran_get_ue_transmission_antenna(mod_id,i) != -1) {
if (flexran_get_ue_transmission_antenna(mod_id, UE_id) != -1) {
ue_config[i]->has_ue_transmission_antenna = 1;
ue_config[i]->ue_transmission_antenna = flexran_get_ue_transmission_antenna(mod_id,i);
ue_config[i]->ue_transmission_antenna = flexran_get_ue_transmission_antenna(mod_id, UE_id);
}
if (flexran_get_tti_bundling(mod_id,i) != -1) {
if (flexran_get_tti_bundling(mod_id, UE_id) != -1) {
ue_config[i]->has_tti_bundling = 1;
ue_config[i]->tti_bundling = flexran_get_tti_bundling(mod_id,i);
ue_config[i]->tti_bundling = flexran_get_tti_bundling(mod_id, UE_id);
}
if (flexran_get_maxHARQ_TX(mod_id,i) != -1) {
if (flexran_get_maxHARQ_TX(mod_id, UE_id) != -1) {
ue_config[i]->has_max_harq_tx = 1;
ue_config[i]->max_harq_tx = flexran_get_maxHARQ_TX(mod_id,i);
ue_config[i]->max_harq_tx = flexran_get_maxHARQ_TX(mod_id, UE_id);
}
if (flexran_get_beta_offset_ack_index(mod_id,i) != -1) {
ue_config[i]->has_beta_offset_ack_index = 1;
ue_config[i]->beta_offset_ack_index = flexran_get_beta_offset_ack_index(mod_id,i);
if (flexran_get_beta_offset_ack_index(mod_id, UE_id) != -1) {
ue_config[i]->has_beta_offset_ack_index = 1;
ue_config[i]->beta_offset_ack_index = flexran_get_beta_offset_ack_index(mod_id, UE_id);
}
if (flexran_get_beta_offset_ri_index(mod_id,i) != -1) {
if (flexran_get_beta_offset_ri_index(mod_id, UE_id) != -1) {
ue_config[i]->has_beta_offset_ri_index = 1;
ue_config[i]->beta_offset_ri_index = flexran_get_beta_offset_ri_index(mod_id,i);
ue_config[i]->beta_offset_ri_index = flexran_get_beta_offset_ri_index(mod_id, UE_id);
}
if (flexran_get_beta_offset_cqi_index(mod_id,i) != -1) {
if (flexran_get_beta_offset_cqi_index(mod_id, UE_id) != -1) {
ue_config[i]->has_beta_offset_cqi_index = 1;
ue_config[i]->beta_offset_cqi_index = flexran_get_beta_offset_cqi_index(mod_id,i);
ue_config[i]->beta_offset_cqi_index = flexran_get_beta_offset_cqi_index(mod_id, UE_id);
}
/* assume primary carrier */
if (flexran_get_ack_nack_simultaneous_trans(mod_id, i, 0) != -1) {
if (flexran_get_ack_nack_simultaneous_trans(mod_id, UE_id, 0) != -1) {
ue_config[i]->has_ack_nack_simultaneous_trans = 1;
ue_config[i]->ack_nack_simultaneous_trans = flexran_get_ack_nack_simultaneous_trans(mod_id, i, 0);
ue_config[i]->ack_nack_simultaneous_trans = flexran_get_ack_nack_simultaneous_trans(mod_id, UE_id, 0);
}
if (flexran_get_simultaneous_ack_nack_cqi(mod_id,i) != -1) {
if (flexran_get_simultaneous_ack_nack_cqi(mod_id, UE_id) != -1) {
ue_config[i]->has_simultaneous_ack_nack_cqi = 1;
ue_config[i]->simultaneous_ack_nack_cqi = flexran_get_simultaneous_ack_nack_cqi(mod_id,i);
ue_config[i]->simultaneous_ack_nack_cqi = flexran_get_simultaneous_ack_nack_cqi(mod_id, UE_id);
}
if (flexran_get_aperiodic_cqi_rep_mode(mod_id,i) != -1) {
if (flexran_get_aperiodic_cqi_rep_mode(mod_id, UE_id) != -1) {
ue_config[i]->has_aperiodic_cqi_rep_mode = 1;
int mode = flexran_get_aperiodic_cqi_rep_mode(mod_id,i);
int mode = flexran_get_aperiodic_cqi_rep_mode(mod_id, UE_id);
if (mode > 4) {
ue_config[i]->aperiodic_cqi_rep_mode = PROTOCOL__FLEX_APERIODIC_CQI_REPORT_MODE__FLACRM_NONE;
} else {
@@ -696,26 +729,26 @@ int flexran_agent_ue_config_reply(mid_t mod_id, const void *params, Protocol__Fl
}
}
if (flexran_get_tdd_ack_nack_feedback_mode(mod_id, i) != -1) {
if (flexran_get_tdd_ack_nack_feedback_mode(mod_id, UE_id) != -1) {
ue_config[i]->has_tdd_ack_nack_feedback = 1;
ue_config[i]->tdd_ack_nack_feedback = flexran_get_tdd_ack_nack_feedback_mode(mod_id,i);
ue_config[i]->tdd_ack_nack_feedback = flexran_get_tdd_ack_nack_feedback_mode(mod_id, UE_id);
}
if(flexran_get_ack_nack_repetition_factor(mod_id, i) != -1) {
if(flexran_get_ack_nack_repetition_factor(mod_id, UE_id) != -1) {
ue_config[i]->has_ack_nack_repetition_factor = 1;
ue_config[i]->ack_nack_repetition_factor = flexran_get_ack_nack_repetition_factor(mod_id,i);
ue_config[i]->ack_nack_repetition_factor = flexran_get_ack_nack_repetition_factor(mod_id, UE_id);
}
if (flexran_get_extended_bsr_size(mod_id, i) != -1) {
if (flexran_get_extended_bsr_size(mod_id, UE_id) != -1) {
ue_config[i]->has_extended_bsr_size = 1;
ue_config[i]->extended_bsr_size = flexran_get_extended_bsr_size(mod_id,i);
ue_config[i]->extended_bsr_size = flexran_get_extended_bsr_size(mod_id, UE_id);
}
//TODO: Set carrier aggregation support (boolean)
ue_config[i]->has_ca_support = 0;
ue_config[i]->ca_support = 0;
ue_config[i]->has_pcell_carrier_index = 1;
ue_config[i]->pcell_carrier_index = UE_PCCID(mod_id, i);
ue_config[i]->pcell_carrier_index = UE_PCCID(mod_id, UE_id);
if(ue_config[i]->has_ca_support){
//TODO: Set cross carrier scheduling support (boolean)
ue_config[i]->has_cross_carrier_sched_support = 0;
@@ -830,8 +863,8 @@ int flexran_agent_enb_config_reply(mid_t mod_id, const void *params, Protocol__F
cell_conf[i] = malloc(sizeof(Protocol__FlexCellConfig));
protocol__flex_cell_config__init(cell_conf[i]);
cell_conf[i]->phy_cell_id = 1;
cell_conf[i]->has_phy_cell_id = flexran_get_cell_id(mod_id,i);
cell_conf[i]->phy_cell_id = flexran_get_cell_id(mod_id,i);
cell_conf[i]->has_phy_cell_id = 1;
cell_conf[i]->cell_id = i;
cell_conf[i]->has_cell_id = 1;
@@ -1030,6 +1063,10 @@ 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;
/* get a pointer to the config which is maintained in the agent throughout
* its lifetime */
cell_conf[i]->slice_config = flexran_agent_get_slice_config(mod_id);
}
enb_config_reply_msg->cell_config=cell_conf;
}
@@ -1090,5 +1127,39 @@ int flexran_agent_destroy_rrc_measurement(Protocol__FlexranMessage *msg){
return 0;
}
int flexran_agent_handle_enb_config_reply(mid_t mod_id, const void *params, Protocol__FlexranMessage **msg)
{
Protocol__FlexranMessage *input = (Protocol__FlexranMessage *)params;
Protocol__FlexEnbConfigReply *enb_config = input->enb_config_reply_msg;
if (enb_config->n_cell_config == 0) {
LOG_W(FLEXRAN_AGENT,
"received enb_config_reply message does not contain a cell_config\n");
*msg = NULL;
return 0;
}
if (enb_config->n_cell_config > 1)
LOG_W(FLEXRAN_AGENT, "ignoring slice configs for other cell except cell 0\n");
if (enb_config->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]);
}
*msg = NULL;
return 0;
}
int flexran_agent_handle_ue_config_reply(mid_t mod_id, const void *params, Protocol__FlexranMessage **msg)
{
int i;
Protocol__FlexranMessage *input = (Protocol__FlexranMessage *)params;
Protocol__FlexUeConfigReply *ue_config_reply = input->ue_config_reply_msg;
for (i = 0; i < ue_config_reply->n_ue_config; i++)
prepare_ue_slice_assoc_update(mod_id, ue_config_reply->ue_config[i]);
*msg = NULL;
return 0;
}
+15 -1
View File
@@ -46,7 +46,6 @@
# include "tree.h"
# include "intertask_interface.h"
# include "timer.h"
#define FLEXRAN_VERSION 0
@@ -167,4 +166,19 @@ void flexran_agent_send_update_stats(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
* since we do not reply to this message (yet). Instead, the controller has to
* issue another eNB config request message. */
int flexran_agent_handle_enb_config_reply(mid_t mod_id, const void* params, Protocol__FlexranMessage **msg);
/* Handle a received UE config reply message as an "order" to reconfigure the
* association of a UE to a slice. It does not come as a reconfiguration
* message as this is a "structured" ProtoBuf message (as opposed to
* "unstructured" YAML). There is no destructor since we do not reply to this
* message (yet). Instead, the controller has to issue another eNB config
* request message. */
int flexran_agent_handle_ue_config_reply(mid_t mod_id, const void* params, Protocol__FlexranMessage **msg);
#endif
@@ -31,57 +31,7 @@
#include "flexran_agent_common_internal.h"
#include "flexran_agent_mac_internal.h"
/* needed to soft-restart the lte-softmodem */
#include "targets/RT/USER/lte-softmodem.h"
void handle_reconfiguration(mid_t mod_id)
{
struct timespec start, end;
clock_gettime(CLOCK_MONOTONIC, &start);
flexran_agent_info_t *flexran = RC.flexran[mod_id];
if (ENB_WAIT == flexran->node_ctrl_state) {
/* this is already waiting, just release */
pthread_mutex_lock(&flexran->mutex_node_ctrl);
flexran->node_ctrl_state = ENB_NORMAL_OPERATION;
pthread_mutex_unlock(&flexran->mutex_node_ctrl);
pthread_cond_signal(&flexran->cond_node_ctrl);
return;
}
if (stop_L1L2(mod_id) < 0) {
LOG_E(ENB_APP, "can not stop lte-softmodem, aborting restart\n");
return;
}
/* node_ctrl_state should have value ENB_MAKE_WAIT only if this method is not
* executed by the FlexRAN thread */
if (ENB_MAKE_WAIT == flexran->node_ctrl_state) {
LOG_I(ENB_APP, " * eNB %d: Waiting for FlexRAN RTController command *\n", mod_id);
pthread_mutex_lock(&flexran->mutex_node_ctrl);
flexran->node_ctrl_state = ENB_WAIT;
while (ENB_NORMAL_OPERATION != flexran->node_ctrl_state)
pthread_cond_wait(&flexran->cond_node_ctrl, &flexran->mutex_node_ctrl);
pthread_mutex_unlock(&flexran->mutex_node_ctrl);
}
if (restart_L1L2(mod_id) < 0) {
LOG_F(ENB_APP, "can not restart, killing lte-softmodem\n");
itti_terminate_tasks(TASK_PHY_ENB);
return;
}
clock_gettime(CLOCK_MONOTONIC, &end);
end.tv_sec -= start.tv_sec;
if (end.tv_nsec >= start.tv_nsec) {
end.tv_nsec -= start.tv_nsec;
} else {
end.tv_sec -= 1;
end.tv_nsec = end.tv_nsec - start.tv_nsec + 1000000000;
}
LOG_I(ENB_APP, "lte-softmodem restart succeeded in %ld.%ld s\n", end.tv_sec, end.tv_nsec / 1000000);
}
#include "enb_app.h"
int apply_reconfiguration_policy(mid_t mod_id, const char *policy, size_t policy_length) {
@@ -589,3 +539,32 @@ int apply_parameter_modification(void *parameter, yaml_parser_t *parser) {
return -1;
}
void initiate_soft_restart(module_id_t mod_id, Protocol__FlexCellConfig *c)
{
uint8_t cc_id = c->has_cell_id ? c->cell_id : 0;
if (c->has_eutra_band) {
flexran_agent_set_operating_eutra_band(mod_id, cc_id, c->eutra_band);
LOG_I(ENB_APP, "Setting eutra_band to %d\n", c->eutra_band);
}
if (c->has_dl_freq && c->has_ul_freq) {
flexran_agent_set_operating_dl_freq(mod_id, cc_id, c->dl_freq);
LOG_I(ENB_APP, "Setting dl_freq to %d\n", c->dl_freq);
int32_t ul_freq_offset = c->ul_freq - c->dl_freq;
flexran_agent_set_operating_ul_freq(mod_id, cc_id, ul_freq_offset);
LOG_I(ENB_APP, "Setting ul_freq to %d\n", c->ul_freq);
}
if (c->has_dl_bandwidth) {
flexran_agent_set_operating_bandwidth(mod_id, cc_id, c->dl_bandwidth);
LOG_I(ENB_APP, "Setting bandwidth to %d\n", c->dl_bandwidth);
if (c->has_ul_bandwidth && c->ul_bandwidth != c->dl_bandwidth)
LOG_W(ENB_APP, "UL/DL bandwidth mismatch, applied DL bandwidth\n");
} else if (c->has_ul_bandwidth) {
flexran_agent_set_operating_bandwidth(mod_id, cc_id, c->ul_bandwidth);
LOG_I(ENB_APP, "Setting bandwidth to %d\n", c->ul_bandwidth);
}
MessageDef *msg;
msg = itti_alloc_new_message(TASK_FLEXRAN_AGENT, SOFT_RESTART_MESSAGE);
itti_send_msg_to_task(TASK_ENB_APP, ENB_MODULE_ID_TO_INSTANCE(mod_id), msg);
}
@@ -32,6 +32,7 @@
#include <yaml.h>
#include "flexran_agent_defs.h"
#include "flexran.pb-c.h"
int apply_reconfiguration_policy(mid_t mod_id, const char *policy, size_t policy_length);
@@ -57,4 +58,7 @@ int skip_subsystem_parameters_config(yaml_parser_t *parser);
//that is not yet implmeneted in order to skip its configuration, without affecting the rest
int skip_parameter_modification(yaml_parser_t *parser);
// applies reconfiguration parameters and notifies ENB APP
void initiate_soft_restart(mid_t mod_id, Protocol__FlexCellConfig *c);
#endif
+9 -6
View File
@@ -33,7 +33,7 @@
#include "flexran_agent_pdcp.h"
#include "flexran_agent_timer.h"
#include "flexran_agent_ran_api.h"
#include "log.h"
#include "common/utils/LOG/log.h"
#include "assertions.h"
@@ -46,9 +46,9 @@ flexran_agent_message_decoded_callback agent_messages_callback[][3] = {
{0, 0, 0}, /*PROTOCOK__FLEXRAN_MESSAGE__MSG_SF_TRIGGER_MSG*/
{0, 0, 0}, /*PROTOCOL__FLEXRAN_MESSAGE__MSG_UL_SR_INFO_MSG*/
{flexran_agent_enb_config_reply, 0, 0}, /*PROTOCOL__FLEXRAN_MESSAGE__MSG_ENB_CONFIG_REQUEST_MSG*/
{0, 0, 0}, /*PROTOCOL__FLEXRAN_MESSAGE__MSG_ENB_CONFIG_REPLY_MSG*/
{flexran_agent_handle_enb_config_reply, 0, 0}, /*PROTOCOL__FLEXRAN_MESSAGE__MSG_ENB_CONFIG_REPLY_MSG*/
{flexran_agent_ue_config_reply, 0, 0}, /*PROTOCOL__FLEXRAN_MESSAGE__MSG_UE_CONFIG_REQUEST_MSG*/
{0, 0, 0}, /*PROTOCOL__FLEXRAN_MESSAGE__MSG_UE_CONFIG_REPLY_MSG*/
{flexran_agent_handle_ue_config_reply, 0, 0}, /*PROTOCOL__FLEXRAN_MESSAGE__MSG_UE_CONFIG_REPLY_MSG*/
{flexran_agent_lc_config_reply, 0, 0}, /*PROTOCOL__FLEXRAN_MESSAGE__MSG_LC_CONFIG_REQUEST_MSG*/
{0, 0, 0}, /*PROTOCOL__FLEXRAN_MESSAGE__MSG_LC_CONFIG_REPLY_MSG*/
{flexran_agent_mac_handle_dl_mac_config, 0, 0}, /*PROTOCOL__FLEXRAN_MESSAGE__MSG_DL_MAC_CONFIG_MSG*/
@@ -210,6 +210,7 @@ int flexran_agent_handle_stats(mid_t mod_id, const void *params, Protocol__Flexr
//TODO: We do not deal with multiple CCs at the moment and eNB id is 0
int enb_id = mod_id;
int UE_id;
//eNB_MAC_INST *eNB = &eNB_mac_inst[enb_id];
//UE_list_t *eNB_UE_list= &eNB->UE_list;
@@ -249,8 +250,9 @@ int flexran_agent_handle_stats(mid_t mod_id, const void *params, Protocol__Flexr
goto error;
}
for (i = 0; i < report_config.nr_ue; i++) {
report_config.ue_report_type[i].ue_rnti = flexran_get_ue_crnti(enb_id, i); //eNB_UE_list->eNB_UE_stats[UE_PCCID(enb_id,i)][i].crnti;
report_config.ue_report_type[i].ue_report_flags = ue_flags;
UE_id = flexran_get_ue_id(mod_id, i);
report_config.ue_report_type[i].ue_rnti = flexran_get_ue_crnti(enb_id, UE_id); //eNB_UE_list->eNB_UE_stats[UE_PCCID(enb_id,i)][i].crnti;
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;
@@ -359,7 +361,8 @@ int flexran_agent_handle_stats(mid_t mod_id, const void *params, Protocol__Flexr
goto error;
}
for (i = 0; i < report_config.nr_ue; i++) {
report_config.ue_report_type[i].ue_rnti = ue_req->rnti[i];
UE_id = flexran_get_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;
+523 -39
View File
@@ -26,6 +26,7 @@
* \version 0.1
*/
#include <dlfcn.h>
#include "flexran_agent_ran_api.h"
static inline int phy_is_present(mid_t mod_id, uint8_t cc_id)
@@ -112,6 +113,21 @@ int flexran_get_num_ues(mid_t mod_id)
return RC.mac[mod_id]->UE_list.num_UEs;
}
int flexran_get_ue_id(mid_t mod_id, int i)
{
int n;
if (!mac_is_present(mod_id)) return 0;
/* get the (i+1)'th active UE */
for (n = 0; n < MAX_MOBILES_PER_ENB; ++n) {
if (RC.mac[mod_id]->UE_list.active[n] == TRUE) {
if (i == 0)
return n;
--i;
}
}
return 0;
}
rnti_t flexran_get_ue_crnti(mid_t mod_id, mid_t ue_id)
{
return UE_RNTI(mod_id, ue_id);
@@ -1193,106 +1209,158 @@ void flexran_agent_set_operating_frame_type(mid_t mod_id, uint8_t cc_id, lte_fra
/*********** PDCP *************/
/*PDCP super frame counter flexRAN*/
uint32_t flexran_get_pdcp_sfn(const mid_t mod_id){
/* TODO the following is a hack. all the functions below should instead already
* receive the PDCP's uid and operate on it and the caller has the obligation
* to get the ID for this layer.
*/
static inline uint16_t flexran_get_pdcp_uid(mid_t mod_id, mid_t ue_id)
{
rnti_t rnti = flexran_get_ue_crnti(mod_id, ue_id);
if (rnti == NOT_A_RNTI) return 0;
for (uint16_t pdcp_uid = 0; pdcp_uid < MAX_MOBILES_PER_ENB; ++pdcp_uid) {
if (pdcp_enb[mod_id].rnti[pdcp_uid] == rnti)
return pdcp_uid;
}
return 0;
}
uint32_t flexran_get_pdcp_sfn(mid_t mod_id)
{
return pdcp_enb[mod_id].sfn;
}
/*PDCP super frame counter flexRAN*/
void flexran_set_pdcp_tx_stat_window(const mid_t mod_id, const mid_t ue_id, uint16_t obs_window){
void flexran_set_pdcp_tx_stat_window(mid_t mod_id, mid_t ue_id, uint16_t obs_window)
{
uint16_t uid = flexran_get_pdcp_uid(mod_id, ue_id);
if (obs_window > 0 ){
Pdcp_stats_tx_window_ms[mod_id][ue_id]=obs_window;
Pdcp_stats_tx_window_ms[mod_id][uid]=obs_window;
}
else{
Pdcp_stats_tx_window_ms[mod_id][ue_id]=1000;
Pdcp_stats_tx_window_ms[mod_id][uid]=1000;
}
}
/*PDCP super frame counter flexRAN*/
void flexran_set_pdcp_rx_stat_window(const mid_t mod_id, const mid_t ue_id, uint16_t obs_window){
void flexran_set_pdcp_rx_stat_window(mid_t mod_id, mid_t ue_id, uint16_t obs_window)
{
uint16_t uid = flexran_get_pdcp_uid(mod_id, ue_id);
if (obs_window > 0 ){
Pdcp_stats_rx_window_ms[mod_id][ue_id]=obs_window;
Pdcp_stats_rx_window_ms[mod_id][uid]=obs_window;
}
else{
Pdcp_stats_rx_window_ms[mod_id][ue_id]=1000;
Pdcp_stats_rx_window_ms[mod_id][uid]=1000;
}
}
/*PDCP num tx pdu status flexRAN*/
uint32_t flexran_get_pdcp_tx(const mid_t mod_id, const mid_t ue_id, const lcid_t lcid){
if (mod_id <0 || mod_id> MAX_NUM_CCs || ue_id<0 || ue_id> MAX_MOBILES_PER_ENB || lcid<0 || lcid>NB_RB_MAX)
uint32_t flexran_get_pdcp_tx(mid_t mod_id, mid_t ue_id, lcid_t lcid)
{
if (mod_id < 0 || mod_id > MAX_NUM_CCs || ue_id < 0 || ue_id > MAX_MOBILES_PER_ENB
|| lcid < 0 || lcid > NB_RB_MAX)
return -1;
return Pdcp_stats_tx[mod_id][ue_id][lcid];
uint16_t uid = flexran_get_pdcp_uid(mod_id, ue_id);
return Pdcp_stats_tx[mod_id][uid][lcid];
}
/*PDCP num tx bytes status flexRAN*/
uint32_t flexran_get_pdcp_tx_bytes(const mid_t mod_id, const mid_t ue_id, const lcid_t lcid){
return Pdcp_stats_tx_bytes[mod_id][ue_id][lcid];
uint32_t flexran_get_pdcp_tx_bytes(mid_t mod_id, mid_t ue_id, lcid_t lcid)
{
uint16_t uid = flexran_get_pdcp_uid(mod_id, ue_id);
return Pdcp_stats_tx_bytes[mod_id][uid][lcid];
}
/*PDCP number of transmit packet / second status flexRAN*/
uint32_t flexran_get_pdcp_tx_w(const mid_t mod_id, const mid_t ue_id, const lcid_t lcid){
return Pdcp_stats_tx_w[mod_id][ue_id][lcid];
uint32_t flexran_get_pdcp_tx_w(mid_t mod_id, mid_t ue_id, lcid_t lcid)
{
uint16_t uid = flexran_get_pdcp_uid(mod_id, ue_id);
return Pdcp_stats_tx_w[mod_id][uid][lcid];
}
/*PDCP throughput (bit/s) status flexRAN*/
uint32_t flexran_get_pdcp_tx_bytes_w(const mid_t mod_id, const mid_t ue_id, const lcid_t lcid){
return Pdcp_stats_tx_bytes_w[mod_id][ue_id][lcid];
uint32_t flexran_get_pdcp_tx_bytes_w(mid_t mod_id, mid_t ue_id, lcid_t lcid)
{
uint16_t uid = flexran_get_pdcp_uid(mod_id, ue_id);
return Pdcp_stats_tx_bytes_w[mod_id][uid][lcid];
}
/*PDCP tx sequence number flexRAN*/
uint32_t flexran_get_pdcp_tx_sn(const mid_t mod_id, const mid_t ue_id, const lcid_t lcid){
return Pdcp_stats_tx_sn[mod_id][ue_id][lcid];
uint32_t flexran_get_pdcp_tx_sn(mid_t mod_id, mid_t ue_id, lcid_t lcid)
{
uint16_t uid = flexran_get_pdcp_uid(mod_id, ue_id);
return Pdcp_stats_tx_sn[mod_id][uid][lcid];
}
/*PDCP tx aggregated packet arrival flexRAN*/
uint32_t flexran_get_pdcp_tx_aiat(const mid_t mod_id, const mid_t ue_id, const lcid_t lcid){
return Pdcp_stats_tx_aiat[mod_id][ue_id][lcid];
uint32_t flexran_get_pdcp_tx_aiat(mid_t mod_id, mid_t ue_id, lcid_t lcid)
{
uint16_t uid = flexran_get_pdcp_uid(mod_id, ue_id);
return Pdcp_stats_tx_aiat[mod_id][uid][lcid];
}
/*PDCP tx aggregated packet arrival flexRAN*/
uint32_t flexran_get_pdcp_tx_aiat_w(const mid_t mod_id, const mid_t ue_id, const lcid_t lcid){
return Pdcp_stats_tx_aiat_w[mod_id][ue_id][lcid];
uint32_t flexran_get_pdcp_tx_aiat_w(mid_t mod_id, mid_t ue_id, lcid_t lcid)
{
uint16_t uid = flexran_get_pdcp_uid(mod_id, ue_id);
return Pdcp_stats_tx_aiat_w[mod_id][uid][lcid];
}
/*PDCP num rx pdu status flexRAN*/
uint32_t flexran_get_pdcp_rx(const mid_t mod_id, const mid_t ue_id, const lcid_t lcid){
return Pdcp_stats_rx[mod_id][ue_id][lcid];
uint32_t flexran_get_pdcp_rx(mid_t mod_id, mid_t ue_id, lcid_t lcid)
{
uint16_t uid = flexran_get_pdcp_uid(mod_id, ue_id);
return Pdcp_stats_rx[mod_id][uid][lcid];
}
/*PDCP num rx bytes status flexRAN*/
uint32_t flexran_get_pdcp_rx_bytes(const mid_t mod_id, const mid_t ue_id, const lcid_t lcid){
return Pdcp_stats_rx_bytes[mod_id][ue_id][lcid];
uint32_t flexran_get_pdcp_rx_bytes(mid_t mod_id, mid_t ue_id, lcid_t lcid)
{
uint16_t uid = flexran_get_pdcp_uid(mod_id, ue_id);
return Pdcp_stats_rx_bytes[mod_id][uid][lcid];
}
/*PDCP number of received packet / second flexRAN*/
uint32_t flexran_get_pdcp_rx_w(const mid_t mod_id, const mid_t ue_id, const lcid_t lcid){
return Pdcp_stats_rx_w[mod_id][ue_id][lcid];
uint32_t flexran_get_pdcp_rx_w(mid_t mod_id, mid_t ue_id, lcid_t lcid)
{
uint16_t uid = flexran_get_pdcp_uid(mod_id, ue_id);
return Pdcp_stats_rx_w[mod_id][uid][lcid];
}
/*PDCP gootput (bit/s) status flexRAN*/
uint32_t flexran_get_pdcp_rx_bytes_w(const mid_t mod_id, const mid_t ue_id, const lcid_t lcid){
return Pdcp_stats_rx_bytes_w[mod_id][ue_id][lcid];
uint32_t flexran_get_pdcp_rx_bytes_w(mid_t mod_id, mid_t ue_id, lcid_t lcid)
{
uint16_t uid = flexran_get_pdcp_uid(mod_id, ue_id);
return Pdcp_stats_rx_bytes_w[mod_id][uid][lcid];
}
/*PDCP rx sequence number flexRAN*/
uint32_t flexran_get_pdcp_rx_sn(const mid_t mod_id, const mid_t ue_id, const lcid_t lcid){
return Pdcp_stats_rx_sn[mod_id][ue_id][lcid];
uint32_t flexran_get_pdcp_rx_sn(mid_t mod_id, mid_t ue_id, lcid_t lcid)
{
uint16_t uid = flexran_get_pdcp_uid(mod_id, ue_id);
return Pdcp_stats_rx_sn[mod_id][uid][lcid];
}
/*PDCP rx aggregated packet arrival flexRAN*/
uint32_t flexran_get_pdcp_rx_aiat(const mid_t mod_id, const mid_t ue_id, const lcid_t lcid){
return Pdcp_stats_rx_aiat[mod_id][ue_id][lcid];
uint32_t flexran_get_pdcp_rx_aiat(mid_t mod_id, mid_t ue_id, lcid_t lcid)
{
uint16_t uid = flexran_get_pdcp_uid(mod_id, ue_id);
return Pdcp_stats_rx_aiat[mod_id][uid][lcid];
}
/*PDCP rx aggregated packet arrival flexRAN*/
uint32_t flexran_get_pdcp_rx_aiat_w(const mid_t mod_id, const mid_t ue_id, const lcid_t lcid){
return Pdcp_stats_rx_aiat_w[mod_id][ue_id][lcid];
uint32_t flexran_get_pdcp_rx_aiat_w(mid_t mod_id, mid_t ue_id, lcid_t lcid)
{
uint16_t uid = flexran_get_pdcp_uid(mod_id, ue_id);
return Pdcp_stats_rx_aiat_w[mod_id][uid][lcid];
}
/*PDCP num of received outoforder pdu status flexRAN*/
uint32_t flexran_get_pdcp_rx_oo(const mid_t mod_id, const mid_t ue_id, const lcid_t lcid){
return Pdcp_stats_rx_outoforder[mod_id][ue_id][lcid];
uint32_t flexran_get_pdcp_rx_oo(mid_t mod_id, mid_t ue_id, lcid_t lcid)
{
uint16_t uid = flexran_get_pdcp_uid(mod_id, ue_id);
return Pdcp_stats_rx_outoforder[mod_id][uid][lcid];
}
/******************** RRC *****************************/
@@ -1393,3 +1461,419 @@ float flexran_get_rrc_neigh_rsrq(mid_t mod_id, mid_t ue_id, int cell_id)
if (!ue_context_p->ue_context.measResults->measResultNeighCells->choice.measResultListEUTRA.list.array[cell_id]->measResult.rsrqResult) return 0;
return RSRQ_meas_mapping[*(ue_context_p->ue_context.measResults->measResultNeighCells->choice.measResultListEUTRA.list.array[cell_id]->measResult.rsrqResult)];
}
int flexran_get_ue_dl_slice_id(mid_t mod_id, mid_t ue_id)
{
if (!mac_is_present(mod_id)) return -1;
int slice_idx = RC.mac[mod_id]->UE_list.assoc_dl_slice_idx[ue_id];
if (slice_idx >= 0 && slice_idx < RC.mac[mod_id]->slice_info.n_dl)
return RC.mac[mod_id]->slice_info.dl[slice_idx].id;
return 0;
}
void flexran_set_ue_dl_slice_idx(mid_t mod_id, mid_t ue_id, int slice_idx)
{
if (!mac_is_present(mod_id)) return;
if (flexran_get_ue_crnti(mod_id, ue_id) == NOT_A_RNTI) return;
if (!flexran_dl_slice_exists(mod_id, slice_idx)) return;
RC.mac[mod_id]->UE_list.assoc_dl_slice_idx[ue_id] = slice_idx;
}
int flexran_get_ue_ul_slice_id(mid_t mod_id, mid_t ue_id)
{
if (!mac_is_present(mod_id)) return -1;
int slice_idx = RC.mac[mod_id]->UE_list.assoc_ul_slice_idx[ue_id];
if (slice_idx >= 0 && slice_idx < RC.mac[mod_id]->slice_info.n_ul)
return RC.mac[mod_id]->slice_info.ul[slice_idx].id;
return 0;
}
void flexran_set_ue_ul_slice_idx(mid_t mod_id, mid_t ue_id, int slice_idx)
{
if (!mac_is_present(mod_id)) return;
if (flexran_get_ue_crnti(mod_id, ue_id) == NOT_A_RNTI) return;
if (!flexran_ul_slice_exists(mod_id, slice_idx)) return;
RC.mac[mod_id]->UE_list.assoc_ul_slice_idx[ue_id] = slice_idx;
}
int flexran_dl_slice_exists(mid_t mod_id, int slice_idx)
{
if (!mac_is_present(mod_id)) return -1;
return slice_idx >= 0 && slice_idx < RC.mac[mod_id]->slice_info.n_dl;
}
int flexran_create_dl_slice(mid_t mod_id, slice_id_t slice_id)
{
if (!mac_is_present(mod_id)) return -1;
int newidx = RC.mac[mod_id]->slice_info.n_dl;
if (newidx >= MAX_NUM_SLICES) return -1;
++RC.mac[mod_id]->slice_info.n_dl;
flexran_set_dl_slice_id(mod_id, newidx, slice_id);
return newidx;
}
int flexran_find_dl_slice(mid_t mod_id, slice_id_t slice_id)
{
if (!mac_is_present(mod_id)) return -1;
slice_info_t *sli = &RC.mac[mod_id]->slice_info;
int n = sli->n_dl;
for (int i = 0; i < n; i++) {
if (sli->dl[i].id == slice_id) return i;
}
return -1;
}
int flexran_remove_dl_slice(mid_t mod_id, int slice_idx)
{
if (!mac_is_present(mod_id)) return -1;
slice_info_t *sli = &RC.mac[mod_id]->slice_info;
if (sli->n_dl <= 1) return -1;
if (sli->dl[slice_idx].sched_name) free(sli->dl[slice_idx].sched_name);
--sli->n_dl;
/* move last element to the position of the removed one */
if (slice_idx != sli->n_dl)
memcpy(&sli->dl[slice_idx], &sli->dl[sli->n_dl], sizeof(sli->dl[sli->n_dl]));
memset(&sli->dl[sli->n_dl], 0, sizeof(sli->dl[sli->n_dl]));
/* all UEs that have been in the old slice are put into slice index 0 */
int *assoc_list = RC.mac[mod_id]->UE_list.assoc_dl_slice_idx;
for (int i = 0; i < MAX_MOBILES_PER_ENB; ++i) {
if (assoc_list[i] == slice_idx)
assoc_list[i] = 0;
}
return sli->n_dl;
}
int flexran_get_num_dl_slices(mid_t mod_id)
{
if (!mac_is_present(mod_id)) return -1;
return RC.mac[mod_id]->slice_info.n_dl;
}
int flexran_get_intraslice_sharing_active(mid_t mod_id)
{
if (!mac_is_present(mod_id)) return -1;
return RC.mac[mod_id]->slice_info.intraslice_share_active;
}
void flexran_set_intraslice_sharing_active(mid_t mod_id, int intraslice_active)
{
if (!mac_is_present(mod_id)) return;
RC.mac[mod_id]->slice_info.intraslice_share_active = intraslice_active;
}
int flexran_get_interslice_sharing_active(mid_t mod_id)
{
if (!mac_is_present(mod_id)) return -1;
return RC.mac[mod_id]->slice_info.interslice_share_active;
}
void flexran_set_interslice_sharing_active(mid_t mod_id, int interslice_active)
{
if (!mac_is_present(mod_id)) return;
RC.mac[mod_id]->slice_info.interslice_share_active = interslice_active;
}
slice_id_t flexran_get_dl_slice_id(mid_t mod_id, int slice_idx)
{
if (!mac_is_present(mod_id)) return -1;
return RC.mac[mod_id]->slice_info.dl[slice_idx].id;
}
void flexran_set_dl_slice_id(mid_t mod_id, int slice_idx, slice_id_t slice_id)
{
if (!mac_is_present(mod_id)) return;
RC.mac[mod_id]->slice_info.dl[slice_idx].id = slice_id;
}
int flexran_get_dl_slice_percentage(mid_t mod_id, int slice_idx)
{
if (!mac_is_present(mod_id)) return -1;
return RC.mac[mod_id]->slice_info.dl[slice_idx].pct * 100.0f;
}
void flexran_set_dl_slice_percentage(mid_t mod_id, int slice_idx, int percentage)
{
if (!mac_is_present(mod_id)) return;
RC.mac[mod_id]->slice_info.dl[slice_idx].pct = percentage / 100.0f;
}
int flexran_get_dl_slice_isolation(mid_t mod_id, int slice_idx)
{
if (!mac_is_present(mod_id)) return -1;
return RC.mac[mod_id]->slice_info.dl[slice_idx].isol;
}
void flexran_set_dl_slice_isolation(mid_t mod_id, int slice_idx, int is_isolated)
{
if (!mac_is_present(mod_id)) return;
RC.mac[mod_id]->slice_info.dl[slice_idx].isol = is_isolated;
}
int flexran_get_dl_slice_priority(mid_t mod_id, int slice_idx)
{
if (!mac_is_present(mod_id)) return -1;
return RC.mac[mod_id]->slice_info.dl[slice_idx].prio;
}
void flexran_set_dl_slice_priority(mid_t mod_id, int slice_idx, int priority)
{
if (!mac_is_present(mod_id)) return;
RC.mac[mod_id]->slice_info.dl[slice_idx].prio = priority;
}
int flexran_get_dl_slice_position_low(mid_t mod_id, int slice_idx)
{
if (!mac_is_present(mod_id)) return -1;
return RC.mac[mod_id]->slice_info.dl[slice_idx].pos_low;
}
void flexran_set_dl_slice_position_low(mid_t mod_id, int slice_idx, int poslow)
{
if (!mac_is_present(mod_id)) return;
RC.mac[mod_id]->slice_info.dl[slice_idx].pos_low = poslow;
}
int flexran_get_dl_slice_position_high(mid_t mod_id, int slice_idx)
{
if (!mac_is_present(mod_id)) return -1;
return RC.mac[mod_id]->slice_info.dl[slice_idx].pos_high;
}
void flexran_set_dl_slice_position_high(mid_t mod_id, int slice_idx, int poshigh)
{
if (!mac_is_present(mod_id)) return;
RC.mac[mod_id]->slice_info.dl[slice_idx].pos_high = poshigh;
}
int flexran_get_dl_slice_maxmcs(mid_t mod_id, int slice_idx)
{
if (!mac_is_present(mod_id)) return -1;
return RC.mac[mod_id]->slice_info.dl[slice_idx].maxmcs;
}
void flexran_set_dl_slice_maxmcs(mid_t mod_id, int slice_idx, int maxmcs)
{
if (!mac_is_present(mod_id)) return;
RC.mac[mod_id]->slice_info.dl[slice_idx].maxmcs = maxmcs;
}
int flexran_get_dl_slice_sorting(mid_t mod_id, int slice_idx, Protocol__FlexDlSorting **sorting_list)
{
if (!mac_is_present(mod_id)) return -1;
if (!(*sorting_list)) {
*sorting_list = calloc(CR_NUM, sizeof(Protocol__FlexDlSorting));
if (!(*sorting_list)) return -1;
}
uint32_t policy = RC.mac[mod_id]->slice_info.dl[slice_idx].sorting;
for (int i = 0; i < CR_NUM; i++) {
switch (policy >> 4 * (CR_NUM - 1 - i) & 0xF) {
case CR_ROUND:
(*sorting_list)[i] = PROTOCOL__FLEX_DL_SORTING__CR_ROUND;
break;
case CR_SRB12:
(*sorting_list)[i] = PROTOCOL__FLEX_DL_SORTING__CR_SRB12;
break;
case CR_HOL:
(*sorting_list)[i] = PROTOCOL__FLEX_DL_SORTING__CR_HOL;
break;
case CR_LC:
(*sorting_list)[i] = PROTOCOL__FLEX_DL_SORTING__CR_LC;
break;
case CR_CQI:
(*sorting_list)[i] = PROTOCOL__FLEX_DL_SORTING__CR_CQI;
break;
case CR_LCP:
(*sorting_list)[i] = PROTOCOL__FLEX_DL_SORTING__CR_LCP;
break;
default:
/* this should not happen, but a "default" */
(*sorting_list)[i] = PROTOCOL__FLEX_DL_SORTING__CR_ROUND;
break;
}
}
return CR_NUM;
}
void flexran_set_dl_slice_sorting(mid_t mod_id, int slice_idx, Protocol__FlexDlSorting *sorting_list, int n)
{
if (!mac_is_present(mod_id)) return;
uint32_t policy = 0;
for (int i = 0; i < n && i < CR_NUM; i++) {
switch (sorting_list[i]) {
case PROTOCOL__FLEX_DL_SORTING__CR_ROUND:
policy = policy << 4 | CR_ROUND;
break;
case PROTOCOL__FLEX_DL_SORTING__CR_SRB12:
policy = policy << 4 | CR_SRB12;
break;
case PROTOCOL__FLEX_DL_SORTING__CR_HOL:
policy = policy << 4 | CR_HOL;
break;
case PROTOCOL__FLEX_DL_SORTING__CR_LC:
policy = policy << 4 | CR_LC;
break;
case PROTOCOL__FLEX_DL_SORTING__CR_CQI:
policy = policy << 4 | CR_CQI;
break;
case PROTOCOL__FLEX_DL_SORTING__CR_LCP:
policy = policy << 4 | CR_LCP;
break;
default: /* suppresses warnings */
policy = policy << 4 | CR_ROUND;
break;
}
}
/* fill up with 0 == CR_ROUND */
if (CR_NUM > n) policy = policy << 4 * (CR_NUM - n);
RC.mac[mod_id]->slice_info.dl[slice_idx].sorting = policy;
}
Protocol__FlexDlAccountingPolicy flexran_get_dl_slice_accounting_policy(mid_t mod_id, int slice_idx)
{
if (!mac_is_present(mod_id)) return PROTOCOL__FLEX_DL_ACCOUNTING_POLICY__POL_FAIR;
switch (RC.mac[mod_id]->slice_info.dl[slice_idx].accounting) {
case POL_FAIR:
return PROTOCOL__FLEX_DL_ACCOUNTING_POLICY__POL_FAIR;
case POL_GREEDY:
return PROTOCOL__FLEX_DL_ACCOUNTING_POLICY__POL_GREEDY;
default:
return PROTOCOL__FLEX_DL_ACCOUNTING_POLICY__POL_FAIR;
}
}
void flexran_set_dl_slice_accounting_policy(mid_t mod_id, int slice_idx, Protocol__FlexDlAccountingPolicy accounting)
{
if (!mac_is_present(mod_id)) return;
switch (accounting) {
case PROTOCOL__FLEX_DL_ACCOUNTING_POLICY__POL_FAIR:
RC.mac[mod_id]->slice_info.dl[slice_idx].accounting = POL_FAIR;
return;
case PROTOCOL__FLEX_DL_ACCOUNTING_POLICY__POL_GREEDY:
RC.mac[mod_id]->slice_info.dl[slice_idx].accounting = POL_GREEDY;
return;
default:
RC.mac[mod_id]->slice_info.dl[slice_idx].accounting = POL_FAIR;
return;
}
}
char *flexran_get_dl_slice_scheduler(mid_t mod_id, int slice_idx)
{
if (!mac_is_present(mod_id)) return NULL;
return RC.mac[mod_id]->slice_info.dl[slice_idx].sched_name;
}
int flexran_set_dl_slice_scheduler(mid_t mod_id, int slice_idx, char *name)
{
if (!mac_is_present(mod_id)) return 0;
if (RC.mac[mod_id]->slice_info.dl[slice_idx].sched_name)
free(RC.mac[mod_id]->slice_info.dl[slice_idx].sched_name);
RC.mac[mod_id]->slice_info.dl[slice_idx].sched_name = strdup(name);
RC.mac[mod_id]->slice_info.dl[slice_idx].sched_cb = dlsym(NULL, name);
return RC.mac[mod_id]->slice_info.dl[slice_idx].sched_cb != NULL;
}
int flexran_create_ul_slice(mid_t mod_id, slice_id_t slice_id)
{
if (!mac_is_present(mod_id)) return -1;
int newidx = RC.mac[mod_id]->slice_info.n_ul;
if (newidx >= MAX_NUM_SLICES) return -1;
++RC.mac[mod_id]->slice_info.n_ul;
flexran_set_ul_slice_id(mod_id, newidx, slice_id);
return newidx;
}
int flexran_find_ul_slice(mid_t mod_id, slice_id_t slice_id)
{
if (!mac_is_present(mod_id)) return -1;
slice_info_t *sli = &RC.mac[mod_id]->slice_info;
int n = sli->n_ul;
for (int i = 0; i < n; i++) {
if (sli->ul[i].id == slice_id) return i;
}
return -1;
}
int flexran_remove_ul_slice(mid_t mod_id, int slice_idx)
{
if (!mac_is_present(mod_id)) return -1;
slice_info_t *sli = &RC.mac[mod_id]->slice_info;
if (sli->n_ul <= 1) return -1;
if (sli->ul[slice_idx].sched_name) free(sli->ul[slice_idx].sched_name);
--sli->n_ul;
/* move last element to the position of the removed one */
if (slice_idx != sli->n_ul)
memcpy(&sli->ul[slice_idx], &sli->ul[sli->n_ul], sizeof(sli->ul[sli->n_ul]));
memset(&sli->ul[sli->n_ul], 0, sizeof(sli->ul[sli->n_ul]));
/* all UEs that have been in the old slice are put into slice index 0 */
int *assoc_list = RC.mac[mod_id]->UE_list.assoc_ul_slice_idx;
for (int i = 0; i < MAX_MOBILES_PER_ENB; ++i) {
if (assoc_list[i] == slice_idx)
assoc_list[i] = 0;
}
return sli->n_ul;
}
int flexran_get_num_ul_slices(mid_t mod_id)
{
if (!mac_is_present(mod_id)) return -1;
return RC.mac[mod_id]->slice_info.n_ul;
}
int flexran_ul_slice_exists(mid_t mod_id, int slice_idx)
{
if (!mac_is_present(mod_id)) return -1;
return slice_idx >= 0 && slice_idx < RC.mac[mod_id]->slice_info.n_ul;
}
slice_id_t flexran_get_ul_slice_id(mid_t mod_id, int slice_idx)
{
if (!mac_is_present(mod_id)) return -1;
return RC.mac[mod_id]->slice_info.ul[slice_idx].id;
}
void flexran_set_ul_slice_id(mid_t mod_id, int slice_idx, slice_id_t slice_id)
{
if (!mac_is_present(mod_id)) return;
RC.mac[mod_id]->slice_info.ul[slice_idx].id = slice_id;
}
int flexran_get_ul_slice_percentage(mid_t mod_id, int slice_idx)
{
if (!mac_is_present(mod_id)) return -1;
return RC.mac[mod_id]->slice_info.ul[slice_idx].pct * 100.0f;
}
void flexran_set_ul_slice_percentage(mid_t mod_id, int slice_idx, int percentage)
{
if (!mac_is_present(mod_id)) return;
RC.mac[mod_id]->slice_info.ul[slice_idx].pct = percentage / 100.0f;
}
int flexran_get_ul_slice_first_rb(mid_t mod_id, int slice_idx)
{
if (!mac_is_present(mod_id)) return -1;
return RC.mac[mod_id]->slice_info.ul[slice_idx].first_rb;
}
void flexran_set_ul_slice_first_rb(mid_t mod_id, int slice_idx, int first_rb)
{
if (!mac_is_present(mod_id)) return;
RC.mac[mod_id]->slice_info.ul[slice_idx].first_rb = first_rb;
}
int flexran_get_ul_slice_maxmcs(mid_t mod_id, int slice_idx)
{
if (!mac_is_present(mod_id)) return -1;
return RC.mac[mod_id]->slice_info.ul[slice_idx].maxmcs;
}
void flexran_set_ul_slice_maxmcs(mid_t mod_id, int slice_idx, int maxmcs)
{
if (!mac_is_present(mod_id)) return;
RC.mac[mod_id]->slice_info.ul[slice_idx].maxmcs = maxmcs;
}
char *flexran_get_ul_slice_scheduler(mid_t mod_id, int slice_idx)
{
if (!mac_is_present(mod_id)) return NULL;
return RC.mac[mod_id]->slice_info.ul[slice_idx].sched_name;
}
int flexran_set_ul_slice_scheduler(mid_t mod_id, int slice_idx, char *name)
{
if (!mac_is_present(mod_id)) return 0;
if (RC.mac[mod_id]->slice_info.ul[slice_idx].sched_name)
free(RC.mac[mod_id]->slice_info.ul[slice_idx].sched_name);
RC.mac[mod_id]->slice_info.ul[slice_idx].sched_name = strdup(name);
RC.mac[mod_id]->slice_info.ul[slice_idx].sched_cb = dlsym(NULL, name);
return RC.mac[mod_id]->slice_info.ul[slice_idx].sched_cb != NULL;
}
+175 -19
View File
@@ -43,7 +43,7 @@
#include "RRC/L2_INTERFACE/openair_rrc_L2_interface.h"
#include "RRC/LTE/rrc_eNB_UE_context.h"
#include "PHY/phy_extern.h"
#include "log.h"
#include "common/utils/LOG/log.h"
/****************************
* get generic info from RAN
@@ -73,6 +73,10 @@ uint16_t flexran_get_future_sfn_sf(mid_t mod_id, int ahead_of_time);
/* Return the number of attached UEs */
int flexran_get_num_ues(mid_t mod_id);
/* Return the UE id of attached UE as opposed to the index [0,NUM UEs] (i.e.,
* the i'th active UE). Returns 0 if the i'th active UE could not be found. */
int flexran_get_ue_id(mid_t mod_id, int i);
/* Get the rnti of a UE with id ue_id */
rnti_t flexran_get_ue_crnti(mid_t mod_id, mid_t ue_id);
@@ -421,59 +425,59 @@ uint8_t flexran_get_rrc_status(mid_t mod_id, mid_t ue_id);
/***************************** PDCP ***********************/
/*PDCP superframe numberflexRAN*/
uint32_t flexran_get_pdcp_sfn(const mid_t mod_id);
uint32_t flexran_get_pdcp_sfn(mid_t mod_id);
/*PDCP pdcp tx stats window*/
void flexran_set_pdcp_tx_stat_window(const mid_t mod_id, const mid_t ue_id, uint16_t obs_window);
void flexran_set_pdcp_tx_stat_window(mid_t mod_id, mid_t ue_id, uint16_t obs_window);
/*PDCP pdcp rx stats window*/
void flexran_set_pdcp_rx_stat_window(const mid_t mod_id, const mid_t ue_id, uint16_t obs_window);
void flexran_set_pdcp_rx_stat_window(mid_t mod_id, mid_t ue_id, uint16_t obs_window);
/*PDCP num tx pdu status flexRAN*/
uint32_t flexran_get_pdcp_tx(const mid_t mod_id, const mid_t ue_id, const lcid_t lcid);
uint32_t flexran_get_pdcp_tx(mid_t mod_id, mid_t ue_id, lcid_t lcid);
/*PDCP num tx bytes status flexRAN*/
uint32_t flexran_get_pdcp_tx_bytes(const mid_t mod_id, const mid_t ue_id, const lcid_t lcid);
uint32_t flexran_get_pdcp_tx_bytes(mid_t mod_id, mid_t ue_id, lcid_t lcid);
/*PDCP number of transmit packet / second status flexRAN*/
uint32_t flexran_get_pdcp_tx_w(const mid_t mod_id, const mid_t ue_id, const lcid_t lcid);
uint32_t flexran_get_pdcp_tx_w(mid_t mod_id, mid_t ue_id, lcid_t lcid);
/*PDCP pdcp tx bytes in a given window flexRAN*/
uint32_t flexran_get_pdcp_tx_bytes_w(const mid_t mod_id, const mid_t ue_id, const lcid_t lcid);
uint32_t flexran_get_pdcp_tx_bytes_w(mid_t mod_id, mid_t ue_id, lcid_t lcid);
/*PDCP tx sequence number flexRAN*/
uint32_t flexran_get_pdcp_tx_sn(const mid_t mod_id, const mid_t ue_id, const lcid_t lcid);
uint32_t flexran_get_pdcp_tx_sn(mid_t mod_id, mid_t ue_id, lcid_t lcid);
/*PDCP tx aggregated packet arrival flexRAN*/
uint32_t flexran_get_pdcp_tx_aiat(const mid_t mod_id, const mid_t ue_id, const lcid_t lcid);
uint32_t flexran_get_pdcp_tx_aiat(mid_t mod_id, mid_t ue_id, lcid_t lcid);
/*PDCP tx aggregated packet arrival per second flexRAN*/
uint32_t flexran_get_pdcp_tx_aiat_w(const mid_t mod_id, const mid_t ue_id, const lcid_t lcid);
uint32_t flexran_get_pdcp_tx_aiat_w(mid_t mod_id, mid_t ue_id, lcid_t lcid);
/*PDCP num rx pdu status flexRAN*/
uint32_t flexran_get_pdcp_rx(const mid_t mod_id, const mid_t ue_id, const lcid_t lcid);
uint32_t flexran_get_pdcp_rx(mid_t mod_id, mid_t ue_id, lcid_t lcid);
/*PDCP num rx bytes status flexRAN*/
uint32_t flexran_get_pdcp_rx_bytes(const mid_t mod_id, const mid_t ue_id, const lcid_t lcid);
uint32_t flexran_get_pdcp_rx_bytes(mid_t mod_id, mid_t ue_id, lcid_t lcid);
/*PDCP number of received packet / second flexRAN*/
uint32_t flexran_get_pdcp_rx_w(const mid_t mod_id, const mid_t ue_id, const lcid_t lcid);
uint32_t flexran_get_pdcp_rx_w(mid_t mod_id, mid_t ue_id, lcid_t lcid);
/*PDCP gootput (bit/s) status flexRAN*/
uint32_t flexran_get_pdcp_rx_bytes_w(const mid_t mod_id, const mid_t ue_id, const lcid_t lcid);
uint32_t flexran_get_pdcp_rx_bytes_w(mid_t mod_id, mid_t ue_id, lcid_t lcid);
/*PDCP rx sequence number flexRAN*/
uint32_t flexran_get_pdcp_rx_sn(const mid_t mod_id, const mid_t ue_id, const lcid_t lcid);
uint32_t flexran_get_pdcp_rx_sn(mid_t mod_id, mid_t ue_id, lcid_t lcid);
/*PDCP rx aggregated packet arrival flexRAN*/
uint32_t flexran_get_pdcp_rx_aiat(const mid_t mod_id, const mid_t ue_id, const lcid_t lcid);
uint32_t flexran_get_pdcp_rx_aiat(mid_t mod_id, mid_t ue_id, lcid_t lcid);
/*PDCP rx aggregated packet arrival per second flexRAN*/
uint32_t flexran_get_pdcp_rx_aiat_w(const mid_t mod_id, const mid_t ue_id, const lcid_t lcid);
uint32_t flexran_get_pdcp_rx_aiat_w(mid_t mod_id, mid_t ue_id, lcid_t lcid);
/*PDCP num of received outoforder pdu status flexRAN*/
uint32_t flexran_get_pdcp_rx_oo(const mid_t mod_id, const mid_t ue_id, const lcid_t lcid);
uint32_t flexran_get_pdcp_rx_oo(mid_t mod_id, mid_t ue_id, lcid_t lcid);
/*********************RRC**********************/
/*Get primary cell measuremeant id flexRAN*/
@@ -504,3 +508,155 @@ int flexran_get_rrc_neigh_plmn_mcc(mid_t mod_id, mid_t ue_id, int cell_id); */
/*Get MNC PLMN identity neighbouring Cell*/
/* currently not implemented
int flexran_get_rrc_neigh_plmn_mnc(mid_t mod_id, mid_t ue_id, int cell_id); */
/************************** Slice configuration **************************/
/* Get the DL slice ID for a UE */
int flexran_get_ue_dl_slice_id(mid_t mod_id, mid_t ue_id);
/* Set the DL slice index(!) for a UE */
void flexran_set_ue_dl_slice_idx(mid_t mod_id, mid_t ue_id, int slice_idx);
/* Get the UL slice ID for a UE */
int flexran_get_ue_ul_slice_id(mid_t mod_id, mid_t ue_id);
/* Set the UL slice index(!) for a UE */
void flexran_set_ue_ul_slice_idx(mid_t mod_id, mid_t ue_id, int slice_idx);
/* Whether intraslice sharing is active, return boolean */
int flexran_get_intraslice_sharing_active(mid_t mod_id);
/* Set whether intraslice sharing is active */
void flexran_set_intraslice_sharing_active(mid_t mod_id, int intraslice_active);
/* Whether intraslice sharing is active, return boolean */
int flexran_get_interslice_sharing_active(mid_t mod_id);
/* Set whether intraslice sharing is active */
void flexran_set_interslice_sharing_active(mid_t mod_id, int interslice_active);
/* Get the number of slices in DL */
int flexran_get_num_dl_slices(mid_t mod_id);
/* Query slice existence in DL. Return is boolean value */
int flexran_dl_slice_exists(mid_t mod_id, int slice_idx);
/* Create slice in DL, returns the new slice index */
int flexran_create_dl_slice(mid_t mod_id, slice_id_t slice_id);
/* Finds slice in DL with given slice_id and returns slice index */
int flexran_find_dl_slice(mid_t mod_id, slice_id_t slice_id);
/* Remove slice in DL, returns new number of slices or -1 on error */
int flexran_remove_dl_slice(mid_t mod_id, int slice_idx);
/* Get the ID of a slice in DL */
slice_id_t flexran_get_dl_slice_id(mid_t mod_id, int slice_idx);
/* Set the ID of a slice in DL */
void flexran_set_dl_slice_id(mid_t mod_id, int slice_idx, slice_id_t slice_id);
/* Get the RB share a slice in DL, value 0-100 */
int flexran_get_dl_slice_percentage(mid_t mod_id, int slice_idx);
/* Set the RB share a slice in DL, value 0-100 */
void flexran_set_dl_slice_percentage(mid_t mod_id, int slice_idx, int percentage);
/* Whether a slice in DL is isolated */
int flexran_get_dl_slice_isolation(mid_t mod_id, int slice_idx);
/* Set whether a slice in DL is isolated */
void flexran_set_dl_slice_isolation(mid_t mod_id, int slice_idx, int is_isolated);
/* Get the priority of a slice in DL */
int flexran_get_dl_slice_priority(mid_t mod_id, int slice_idx);
/* Get the priority of a slice in DL */
void flexran_set_dl_slice_priority(mid_t mod_id, int slice_idx, int priority);
/* Get the lower end of the frequency range for the slice positioning in DL */
int flexran_get_dl_slice_position_low(mid_t mod_id, int slice_idx);
/* Set the lower end of the frequency range for the slice positioning in DL */
void flexran_set_dl_slice_position_low(mid_t mod_id, int slice_idx, int poslow);
/* Get the higher end of the frequency range for the slice positioning in DL */
int flexran_get_dl_slice_position_high(mid_t mod_id, int slice_idx);
/* Set the higher end of the frequency range for the slice positioning in DL */
void flexran_set_dl_slice_position_high(mid_t mod_id, int slice_idx, int poshigh);
/* Get the maximum MCS for slice in DL */
int flexran_get_dl_slice_maxmcs(mid_t mod_id, int slice_idx);
/* Set the maximum MCS for slice in DL */
void flexran_set_dl_slice_maxmcs(mid_t mod_id, int slice_idx, int maxmcs);
/* Get the sorting order of a slice in DL, return value is number of elements
* in sorting_list */
int flexran_get_dl_slice_sorting(mid_t mod_id, int slice_idx, Protocol__FlexDlSorting **sorting_list);
/* Set the sorting order of a slice in DL */
void flexran_set_dl_slice_sorting(mid_t mod_id, int slice_idx, Protocol__FlexDlSorting *sorting_list, int n);
/* Get the accounting policy for a slice in DL */
Protocol__FlexDlAccountingPolicy flexran_get_dl_slice_accounting_policy(mid_t mod_id, int slice_idx);
/* Set the accounting policy for a slice in DL */
void flexran_set_dl_slice_accounting_policy(mid_t mod_id, int slice_idx, Protocol__FlexDlAccountingPolicy accounting);
/* Get the scheduler name for a slice in DL */
char *flexran_get_dl_slice_scheduler(mid_t mod_id, int slice_idx);
/* Set the scheduler name for a slice in DL */
int flexran_set_dl_slice_scheduler(mid_t mod_id, int slice_idx, char *name);
/* Get the number of slices in UL */
int flexran_get_num_ul_slices(mid_t mod_id);
/* Query slice existence in UL. Return is boolean value */
int flexran_ul_slice_exists(mid_t mod_id, int slice_idx);
/* Create slice in UL, returns the new slice index */
int flexran_create_ul_slice(mid_t mod_id, slice_id_t slice_id);
/* Finds slice in UL with given slice_id and returns slice index */
int flexran_find_ul_slice(mid_t mod_id, slice_id_t slice_id);
/* Remove slice in UL */
int flexran_remove_ul_slice(mid_t mod_id, int slice_idx);
/* Get the ID of a slice in UL */
slice_id_t flexran_get_ul_slice_id(mid_t mod_id, int slice_idx);
/* Set the ID of a slice in UL */
void flexran_set_ul_slice_id(mid_t mod_id, int slice_idx, slice_id_t slice_id);
/* Get the RB share a slice in UL, value 0-100 */
int flexran_get_ul_slice_percentage(mid_t mod_id, int slice_idx);
/* Set the RB share a slice in UL, value 0-100 */
void flexran_set_ul_slice_percentage(mid_t mod_id, int slice_idx, int percentage);
/* TODO Whether a slice in UL is isolated */
/*int flexran_get_ul_slice_isolation(mid_t mod_id, int slice_idx);*/
/* TODO Set whether a slice in UL is isolated */
/*void flexran_set_ul_slice_isolation(mid_t mod_id, int slice_idx, int is_isolated);*/
/* TODO Get the priority of a slice in UL */
/*int flexran_get_ul_slice_priority(mid_t mod_id, int slice_idx);*/
/* TODO Set the priority of a slice in UL */
/*void flexran_set_ul_slice_priority(mid_t mod_id, int slice_idx, int priority);*/
/* Get the first RB for allocation in a slice in UL */
int flexran_get_ul_slice_first_rb(mid_t mod_id, int slice_idx);
/* Set the first RB for allocation in a slice in UL */
void flexran_set_ul_slice_first_rb(mid_t mod_id, int slice_idx, int first_rb);
/* TODO Get the number of RB for the allocation in a slice in UL */
/*int flexran_get_ul_slice_length_rb(mid_t mod_id, int slice_idx);*/
/* TODO Set the of number of RB for the allocation in a slice in UL */
/*void flexran_set_ul_slice_length_rb(mid_t mod_id, int slice_idx, int poshigh);*/
/* Get the maximum MCS for slice in UL */
int flexran_get_ul_slice_maxmcs(mid_t mod_id, int slice_idx);
/* Set the maximum MCS for slice in UL */
void flexran_set_ul_slice_maxmcs(mid_t mod_id, int slice_idx, int maxmcs);
/* TODO Get the sorting order of a slice in UL, return value is number of elements
* in sorting_list */
/*int flexran_get_ul_slice_sorting(mid_t mod_id, int slice_idx, Protocol__FlexUlSorting **sorting_list);*/
/* TODO Set the sorting order of a slice in UL */
/*void flexran_set_ul_slice_sorting(mid_t mod_id, int slice_idx, Protocol__FlexUlSorting *sorting_list, int n);*/
/* TODO Get the accounting policy for a slice in UL */
/*Protocol__UlAccountingPolicy flexran_get_ul_slice_accounting_policy(mid_t mod_id, int slice_idx);*/
/* TODO Set the accounting policy for a slice in UL */
/*void flexran_get_ul_slice_accounting_policy(mid_t mod_id, int slice_idx, Protocol__UlAccountingPolicy accountin);*/
/* Get the scheduler name for a slice in UL */
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);
-1
View File
@@ -37,7 +37,6 @@
# include "tree.h"
# include "intertask_interface.h"
# include "timer.h"
+64 -7
View File
@@ -160,6 +160,58 @@ uint32_t to_earfcn(int eutra_bandP, uint32_t dl_CarrierFreq, uint32_t bw)
(eutra_bandtable[i].N_OFFs_DL / 10));
}
uint32_t to_earfcn_DL(int eutra_bandP, long long int dl_CarrierFreq, uint32_t bw)
{
uint32_t dl_CarrierFreq_by_100k = dl_CarrierFreq / 100000;
int bw_by_100 = bw / 100;
int i;
AssertFatal(eutra_bandP < 69, "eutra_band %d > 68\n", eutra_bandP);
for (i = 0; i < 69 && eutra_bandtable[i].band != eutra_bandP; i++);
AssertFatal(dl_CarrierFreq_by_100k >= eutra_bandtable[i].dl_min,
"Band %d, bw %u : DL carrier frequency %lld Hz < %u\n",
eutra_bandP, bw, dl_CarrierFreq,
eutra_bandtable[i].dl_min);
AssertFatal(dl_CarrierFreq_by_100k <=
(eutra_bandtable[i].dl_max - bw_by_100),
"Band %d, bw %u : DL carrier frequency %lld Hz > %d\n",
eutra_bandP, bw, dl_CarrierFreq,
eutra_bandtable[i].dl_max - bw_by_100);
return (dl_CarrierFreq_by_100k - eutra_bandtable[i].dl_min +
(eutra_bandtable[i].N_OFFs_DL / 10));
}
uint32_t to_earfcn_UL(int eutra_bandP, long long int ul_CarrierFreq, uint32_t bw)
{
uint32_t ul_CarrierFreq_by_100k = ul_CarrierFreq / 100000;
int bw_by_100 = bw / 100;
int i;
AssertFatal(eutra_bandP < 69, "eutra_band %d > 68\n", eutra_bandP);
for (i = 0; i < 69 && eutra_bandtable[i].band != eutra_bandP; i++);
AssertFatal(ul_CarrierFreq_by_100k >= eutra_bandtable[i].ul_min,
"Band %d, bw %u : UL carrier frequency %lld Hz < %u\n",
eutra_bandP, bw, ul_CarrierFreq,
eutra_bandtable[i].ul_min);
AssertFatal(ul_CarrierFreq_by_100k <=
(eutra_bandtable[i].ul_max - bw_by_100),
"Band %d, bw %u : UL carrier frequency %lld Hz > %d\n",
eutra_bandP, bw, ul_CarrierFreq,
eutra_bandtable[i].ul_max - bw_by_100);
return (ul_CarrierFreq_by_100k - eutra_bandtable[i].ul_min +
((eutra_bandtable[i].N_OFFs_DL + 180000) / 10));
}
uint32_t from_earfcn(int eutra_bandP, uint32_t dl_earfcn)
{
@@ -733,7 +785,7 @@ rrc_mac_config_req_eNB(module_id_t Mod_idP,
if (RC.mac == NULL)
l2_init_eNB();
mac_top_init_eNB();
//mac_top_init_eNB();
RC.mac[Mod_idP]->common_channels[CC_idP].mib = mib;
RC.mac[Mod_idP]->common_channels[CC_idP].physCellId = physCellId;
@@ -852,16 +904,21 @@ rrc_mac_config_req_eNB(module_id_t Mod_idP,
LOG_E(MAC, "%s:%d:%s: ERROR, UE_id == -1\n", __FILE__,
__LINE__, __FUNCTION__);
} else {
if (logicalChannelConfig)
if (logicalChannelConfig) {
UE_list->
UE_template[CC_idP][UE_id].lcgidmap
[logicalChannelIdentity] =
*logicalChannelConfig->
ul_SpecificParameters->logicalChannelGroup;
else
UE_list->
UE_template[CC_idP][UE_id].lcgidmap
[logicalChannelIdentity] = 0;
ul_SpecificParameters->logicalChannelGroup;
UE_list->
UE_template[CC_idP][UE_id].lcgidpriority
[logicalChannelIdentity]=
logicalChannelConfig->ul_SpecificParameters->priority;
} else
UE_list->
UE_template[CC_idP][UE_id].lcgidmap
[logicalChannelIdentity] = 0;
}
}
+6 -2
View File
@@ -538,8 +538,8 @@ eNB_dlsch_ulsch_scheduler(module_id_t module_idP, frame_t frameP,
0 ? "in synch" : "out of sync",
UE_list->UE_template[CC_id][i].phr_info,
UE_list->UE_sched_ctrl[i].dl_cqi[CC_id],
(UE_list->UE_sched_ctrl[i].pusch_snr[CC_id] - 128) / 2,
(UE_list->UE_sched_ctrl[i].pucch1_snr[CC_id] - 128) / 2);
(5*UE_list->UE_sched_ctrl[i].pusch_snr[CC_id] - 640) / 10,
(5*UE_list->UE_sched_ctrl[i].pucch1_snr[CC_id] - 640) / 10);
}
RC.eNB[module_idP][CC_id]->pusch_stats_bsr[i][(frameP * 10) +
@@ -703,6 +703,10 @@ eNB_dlsch_ulsch_scheduler(module_id_t module_idP, frame_t frameP,
allocate_CCEs(module_idP, CC_id, frameP, subframeP, 2);
}
if (mac_agent_registered[module_idP] && subframeP == 9) {
flexran_agent_slice_update(module_idP);
}
stop_meas(&RC.mac[module_idP]->eNB_scheduler);
VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME
+6 -4
View File
@@ -988,9 +988,10 @@ generate_Msg4(module_id_t module_idP, int CC_idP, frame_t frameP,
payload[0], ra->msg4_TBsize));
if (opt_enabled == 1) {
trace_pdu(1,
trace_pdu(DIRECTION_DOWNLINK,
(uint8_t *) mac->
UE_list.DLSCH_pdu[CC_idP][0][(unsigned char)UE_id].payload[0], rrc_sdu_length, UE_id, 3,
UE_list.DLSCH_pdu[CC_idP][0][(unsigned char)UE_id].payload[0],
rrc_sdu_length, UE_id, WS_C_RNTI,
UE_RNTI(module_idP, UE_id), mac->frame,
mac->subframe, 0, 0);
LOG_D(OPT,
@@ -1193,9 +1194,10 @@ generate_Msg4(module_id_t module_idP, int CC_idP, frame_t frameP,
payload[0], ra->msg4_TBsize));
if (opt_enabled == 1) {
trace_pdu(1,
trace_pdu(DIRECTION_DOWNLINK,
(uint8_t *) mac->
UE_list.DLSCH_pdu[CC_idP][0][(unsigned char)UE_id].payload[0], rrc_sdu_length, UE_id, 3,
UE_list.DLSCH_pdu[CC_idP][0][(unsigned char)UE_id].payload[0],
rrc_sdu_length, UE_id, WS_C_RNTI,
UE_RNTI(module_idP, UE_id), mac->frame,
mac->subframe, 0, 0);
LOG_D(OPT,
+6 -6
View File
@@ -281,10 +281,10 @@ schedule_SIB1_BR(module_id_t module_idP,
eNB->TX_req[CC_id].header.message_id = NFAPI_TX_REQUEST;
if (opt_enabled == 1) {
trace_pdu(1,
trace_pdu(DIRECTION_DOWNLINK,
&cc->BCCH_BR_pdu[0].payload[0],
bcch_sdu_length,
0xffff, 4, 0xffff, eNB->frame, eNB->subframe, 0, 0);
0xffff, WS_SI_RNTI, 0xffff, eNB->frame, eNB->subframe, 0, 0);
LOG_D(OPT,
"[eNB %d][BCH] Frame %d trace pdu for CC_id %d rnti %x with size %d\n",
module_idP, frameP, CC_id, 0xffff, bcch_sdu_length);
@@ -472,11 +472,11 @@ schedule_SI_BR(module_id_t module_idP, frame_t frameP,
eNB->TX_req[CC_id].header.message_id = NFAPI_TX_REQUEST;
if (opt_enabled == 1) {
trace_pdu(1,
trace_pdu(DIRECTION_DOWNLINK,
&cc->BCCH_BR_pdu[i + 1].payload[0],
bcch_sdu_length,
0xffff,
4,
WS_SI_RNTI,
0xffff, eNB->frame, eNB->subframe, 0,
0);
LOG_D(OPT,
@@ -759,11 +759,11 @@ schedule_SI(module_id_t module_idP, frame_t frameP, sub_frame_t subframeP)
}
if (opt_enabled == 1) {
trace_pdu(1,
trace_pdu(DIRECTION_DOWNLINK,
&cc->BCCH_pdu.payload[0],
bcch_sdu_length,
0xffff,
4, 0xffff, eNB->frame, eNB->subframe, 0, 0);
WS_SI_RNTI, 0xffff, eNB->frame, eNB->subframe, 0, 0);
LOG_D(OPT,
"[eNB %d][BCH] Frame %d trace pdu for CC_id %d rnti %x with size %d\n",
module_idP, frameP, CC_id, 0xffff,
File diff suppressed because it is too large Load Diff
+50 -32
View File
@@ -542,8 +542,9 @@ void dlsch_scheduler_pre_processor_fairRR (module_id_t Mod_id,
uint16_t temp_total_rbs_count;
unsigned char temp_total_ue_count;
unsigned char MIMO_mode_indicator[MAX_NUM_CCs][N_RBG_MAX];
uint8_t slice_allocation[MAX_NUM_CCs][N_RBG_MAX];
int UE_id, i;
uint16_t j;
uint16_t j,c;
uint16_t nb_rbs_required[MAX_NUM_CCs][NUMBER_OF_UE_MAX];
uint16_t nb_rbs_required_remaining[MAX_NUM_CCs][NUMBER_OF_UE_MAX];
// uint16_t nb_rbs_required_remaining_1[MAX_NUM_CCs][NUMBER_OF_UE_MAX];
@@ -554,8 +555,6 @@ void dlsch_scheduler_pre_processor_fairRR (module_id_t Mod_id,
uint8_t CC_id;
UE_list_t *UE_list = &RC.mac[Mod_id]->UE_list;
int N_RB_DL;
int transmission_mode = 0;
UE_sched_ctrl *ue_sched_ctl;
// int rrc_status = RRC_IDLE;
COMMON_channels_t *cc;
@@ -590,14 +589,14 @@ void dlsch_scheduler_pre_processor_fairRR (module_id_t Mod_id,
dlsch_scheduler_pre_processor_reset(Mod_id,
UE_id,
CC_id,
0,
frameP,
subframeP,
N_RBG[CC_id],
min_rb_unit,
(uint16_t (*)[NUMBER_OF_UE_MAX])nb_rbs_required,
rballoc_sub,
MIMO_mode_indicator);
MIMO_mode_indicator,
mbsfn_flag);
}
}
@@ -621,7 +620,6 @@ void dlsch_scheduler_pre_processor_fairRR (module_id_t Mod_id,
average_rbs_per_user[CC_id] = 0;
cc = &RC.mac[Mod_id]->common_channels[CC_id];
// Get total available RBS count and total UE count
N_RB_DL = to_prb(cc->mib->message.dl_Bandwidth);
temp_total_rbs_count = RC.mac[Mod_id]->eNB_stats[CC_id].available_prbs;
temp_total_ue_count = dlsch_ue_select[CC_id].ue_num;
@@ -658,19 +656,22 @@ void dlsch_scheduler_pre_processor_fairRR (module_id_t Mod_id,
nb_rbs_required_remaining[CC_id][UE_id] = cmin(average_rbs_per_user[CC_id], dlsch_ue_select[CC_id].list[i].nb_rb);
}
transmission_mode = get_tmode(Mod_id,CC_id,UE_id);
/* slicing support has been introduced into the scheduler. Provide dummy
* data so that the preprocessor "simply works" */
for (c = 0; c < MAX_NUM_CCs; ++c)
for (j = 0; j < N_RBG_MAX; ++j)
slice_allocation[c][j] = 1;
LOG_T(MAC,"calling dlsch_scheduler_pre_processor_allocate .. \n ");
dlsch_scheduler_pre_processor_allocate (Mod_id,
UE_id,
CC_id,
N_RBG[CC_id],
transmission_mode,
min_rb_unit[CC_id],
N_RB_DL,
(uint16_t (*)[NUMBER_OF_UE_MAX])nb_rbs_required,
(uint16_t (*)[NUMBER_OF_UE_MAX])nb_rbs_required_remaining,
rballoc_sub,
slice_allocation,
MIMO_mode_indicator);
temp_total_rbs_count -= ue_sched_ctl->pre_nb_available_rbs[CC_id];
temp_total_ue_count--;
@@ -787,13 +788,11 @@ schedule_ue_spec_fairRR(module_id_t module_idP,
// unsigned char aggregation;
mac_rlc_status_resp_t rlc_status;
unsigned char header_len_dcch = 0, header_len_dcch_tmp = 0;
unsigned char header_len_dtch = 0, header_len_dtch_tmp =
0, header_len_dtch_last = 0;
unsigned char header_len_dtch = 0, header_len_dtch_tmp = 0, header_len_dtch_last = 0;
unsigned char ta_len = 0;
unsigned char sdu_lcids[NB_RB_MAX], lcid, offset, num_sdus = 0;
uint16_t nb_rb, nb_rb_temp, nb_available_rb;
uint16_t TBS, j, sdu_lengths[NB_RB_MAX], rnti, padding =
0, post_padding = 0;
uint16_t TBS, j, sdu_lengths[NB_RB_MAX], rnti, padding = 0, post_padding = 0;
unsigned char dlsch_buffer[MAX_DLSCH_PAYLOAD_BYTES];
unsigned char round = 0;
unsigned char harq_pid = 0;
@@ -818,7 +817,10 @@ schedule_ue_spec_fairRR(module_id_t module_idP,
nfapi_dl_config_request_pdu_t *dl_config_pdu;
int tdd_sfa;
int ta_update;
#ifdef DEBUG_eNB_SCHEDULER
int k;
#endif
start_meas(&eNB->schedule_dlsch);
VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME
(VCD_SIGNAL_DUMPER_FUNCTIONS_SCHEDULE_DLSCH, VCD_FUNCTION_IN);
@@ -1335,8 +1337,8 @@ schedule_ue_spec_fairRR(module_id_t module_idP,
"[eNB %d][DCCH] CC_id %d Got %d bytes :",
module_idP, CC_id, sdu_lengths[0]);
for (j = 0; j < sdu_lengths[0]; j++) {
LOG_T(MAC, "%x ", dlsch_buffer[j]);
for (k = 0; k < sdu_lengths[0]; k++) {
LOG_T(MAC, "%x ", dlsch_buffer[k]);
}
LOG_T(MAC, "\n");
@@ -1389,8 +1391,8 @@ schedule_ue_spec_fairRR(module_id_t module_idP,
"[eNB %d][DCCH1] CC_id %d Got %d bytes :",
module_idP, CC_id, sdu_lengths[num_sdus]);
for (j = 0; j < sdu_lengths[num_sdus]; j++) {
LOG_T(MAC, "%x ", dlsch_buffer[j]);
for (k = 0; k < sdu_lengths[num_sdus]; k++) {
LOG_T(MAC, "%x ", dlsch_buffer[k]);
}
LOG_T(MAC, "\n");
@@ -1638,8 +1640,8 @@ schedule_ue_spec_fairRR(module_id_t module_idP,
#ifdef DEBUG_eNB_SCHEDULER
LOG_T(MAC, "[eNB %d] First 16 bytes of DLSCH : \n",module_idP );
for (i = 0; i < 16; i++) {
LOG_T(MAC, "%x.", dlsch_buffer[i]);
for (k = 0; k < 16; k++) {
LOG_T(MAC, "%x.", dlsch_buffer[k]);
}
LOG_T(MAC, "\n");
@@ -1655,8 +1657,8 @@ schedule_ue_spec_fairRR(module_id_t module_idP,
}
if (opt_enabled == 1) {
trace_pdu(1, (uint8_t *)UE_list->DLSCH_pdu[CC_id][0][UE_id].payload[0],
TBS, module_idP, 3, UE_RNTI(module_idP,UE_id),
trace_pdu(DIRECTION_DOWNLINK, (uint8_t *)UE_list->DLSCH_pdu[CC_id][0][UE_id].payload[0],
TBS, module_idP, WS_RA_RNTI, UE_RNTI(module_idP,UE_id),
eNB->frame, eNB->subframe,0,0);
LOG_D(OPT,"[eNB %d][DLSCH] CC_id %d Frame %d rnti %x with size %d\n",
module_idP, CC_id, frameP, UE_RNTI(module_idP,UE_id), TBS);
@@ -1696,9 +1698,9 @@ schedule_ue_spec_fairRR(module_id_t module_idP,
// this is the normalized RX power
eNB_UE_stats = &UE_list->eNB_UE_stats[CC_id][UE_id];
/* TODO: fix how we deal with power, unit is not dBm, it's special from nfapi */
normalized_rx_power = ue_sched_ctl->pucch1_snr[CC_id];
target_rx_power = 208;
/* Unit is not dBm, it's special from nfapi */
normalized_rx_power = (5*ue_sched_ctl->pucch1_snr[CC_id]-640)/10+30;//(+eNB->measurements.n0_power_dB[0])
target_rx_power= eNB->puCch10xSnr/10 + 30;//(+eNB->measurements.n0_power_dB[0])
// this assumes accumulated tpc
// make sure that we are only sending a tpc update once a frame, otherwise the control loop will freak out
@@ -2690,9 +2692,25 @@ void schedule_ulsch_rnti_fairRR(module_id_t module_idP,
if (status < RRC_CONNECTED)
cqi_req = 0;
else if (UE_sched_ctrl->cqi_req_timer>30) {
cqi_req = 1;
UE_sched_ctrl->cqi_req_timer=0;
UE_sched_ctrl->cqi_req_flag |= 1 << sched_subframeP;
cqi_req = 1;
// To be safe , do not ask CQI in special SFs:36.213/7.2.3 CQI definition
if (cc->tdd_Config) {
switch (cc->tdd_Config->subframeAssignment) {
case 1:
if( subframeP == 1 || subframeP == 6 ) cqi_req=0;
break;
case 3:
if( subframeP == 1 ) cqi_req=0;
break;
default:
LOG_E(MAC," TDD config not supported\n");
break;
}
}
if(cqi_req == 1){
UE_sched_ctrl->cqi_req_timer=0;
UE_sched_ctrl->cqi_req_flag |= 1 << sched_subframeP;
}
}
else
cqi_req = 0;
@@ -2701,8 +2719,8 @@ void schedule_ulsch_rnti_fairRR(module_id_t module_idP,
//compute the expected ULSCH RX power (for the stats)
// this is the normalized RX power and this should be constant (regardless of mcs
normalized_rx_power = UE_sched_ctrl->pusch_snr[CC_id];
target_rx_power = 178;
normalized_rx_power = (5*UE_sched_ctrl->pusch_snr[CC_id]-640)/10+30; //(+eNB->measurements.n0_power_dB[0])
target_rx_power= eNB->puSch10xSnr/10 + 30; //(+eNB->measurements.n0_power_dB[0])
// this assumes accumulated tpc
// make sure that we are only sending a tpc update once a frame, otherwise the control loop will freak out
+1 -1
View File
@@ -767,7 +767,7 @@ 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) {
trace_pdu(1, (uint8_t *) cc->MCH_pdu.payload, TBS, module_idP, 6, 0xffff, // M_RNTI = 6 in wirehsark
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,
+15 -5
View File
@@ -202,7 +202,8 @@ void schedule_ulsch_phy_test(module_id_t module_idP,frame_t frameP,sub_frame_t s
int32_t normalized_rx_power;
int32_t target_rx_power= 178;
int CC_id = 0;
int nb_rb = 96;
int nb_rb = 24;
int N_RB_UL;
eNB_MAC_INST *mac = RC.mac[module_idP];
COMMON_channels_t *cc = &mac->common_channels[0];
UE_list_t *UE_list=&mac->UE_list;
@@ -211,8 +212,7 @@ void schedule_ulsch_phy_test(module_id_t module_idP,frame_t frameP,sub_frame_t s
int sched_frame=frameP;
int sched_subframe = (subframeP+4)%10;
uint16_t ul_req_index;
uint8_t dlsch_flag;
if (sched_subframe<subframeP) sched_frame++;
nfapi_hi_dci0_request_t *hi_dci0_req = &mac->HI_DCI0_req[CC_id][subframeP];
@@ -222,6 +222,18 @@ void schedule_ulsch_phy_test(module_id_t module_idP,frame_t frameP,sub_frame_t s
//nfapi_ul_config_request_pdu_t *ul_config_pdu = &ul_req->ul_config_pdu_list[0];;
nfapi_ul_config_request_body_t *ul_req = &mac->UL_req[CC_id].ul_config_request_body;
N_RB_UL = to_prb(cc->mib->message.dl_Bandwidth);
switch(N_RB_UL){
case 100:
nb_rb = 96;
break;
case 50:
nb_rb = 48;
break;
case 25:
nb_rb = 24;
break;
}
mac->UL_req[CC_id].sfn_sf = (sched_frame<<4) + sched_subframe;
hi_dci0_req->sfn_sf = (frameP << 4) + subframeP;
@@ -306,10 +318,8 @@ void schedule_ulsch_phy_test(module_id_t module_idP,frame_t frameP,sub_frame_t s
hi_dci0_req_body->number_of_dci++;
ul_req_index = 0;
dlsch_flag = 0;
for(ul_req_index = 0;ul_req_index < ul_req->number_of_pdus;ul_req_index++){
if(ul_req->ul_config_pdu_list[ul_req_index].pdu_type == NFAPI_UL_CONFIG_UCI_HARQ_PDU_TYPE){
dlsch_flag = 1;
LOG_D(MAC,"Frame %d, Subframe %d:rnti %x ul_req_index %d Switched UCI HARQ to ULSCH HARQ(first)\n",frameP,subframeP,rnti,ul_req_index);
break;
}
+27 -14
View File
@@ -62,8 +62,6 @@ extern uint16_t frame_cnt;
extern RAN_CONTEXT_t RC;
extern int n_active_slices;
int choose(int n, int k)
{
int res = 1;
@@ -1157,11 +1155,11 @@ program_dlsch_acknak(module_id_t module_idP, int CC_idP, int UE_idP,
}
break;
case NFAPI_UL_CONFIG_ULSCH_HARQ_PDU_TYPE:
AssertFatal(use_simultaneous_pucch_pusch == 1,
AssertFatal(use_simultaneous_pucch_pusch == 0,
"Cannot be NFAPI_UL_CONFIG_ULSCH_HARQ_PDU_TYPE, simultaneous_pucch_pusch is active");
break;
case NFAPI_UL_CONFIG_ULSCH_UCI_HARQ_PDU_TYPE:
AssertFatal(use_simultaneous_pucch_pusch == 0,
AssertFatal(use_simultaneous_pucch_pusch == 1,
"Cannot be NFAPI_UL_CONFIG_ULSCH_UCI_PDU_TYPE, simultaneous_pucch_pusch is inactive\n");
break;
@@ -1853,7 +1851,7 @@ rnti_t UE_RNTI(module_id_t mod_idP, int ue_idP)
return (rnti);
}
LOG_D(MAC, "[eNB %d] Couldn't find RNTI for UE %d\n", mod_idP, ue_idP);
//LOG_D(MAC, "[eNB %d] Couldn't find RNTI for UE %d\n", mod_idP, ue_idP);
//display_backtrace();
return (NOT_A_RNTI);
}
@@ -1963,6 +1961,9 @@ int add_new_ue(module_id_t mod_idP, int cc_idP, rnti_t rntiP, int harq_pidP
sizeof(eNB_UE_STATS));
UE_list->UE_sched_ctrl[UE_id].ue_reestablishment_reject_timer = 0;
/* default slice in case there was something different */
UE_list->assoc_dl_slice_idx[UE_id] = 0;
UE_list->assoc_ul_slice_idx[UE_id] = 0;
UE_list->UE_sched_ctrl[UE_id].ta_update = 31;
@@ -4536,19 +4537,31 @@ harq_indication(module_id_t mod_idP, int CC_idP, frame_t frameP,
// Flexran Slicing functions
uint16_t flexran_nb_rbs_allowed_slice(float rb_percentage, int total_rbs)
uint16_t nb_rbs_allowed_slice(float rb_percentage, int total_rbs)
{
return (uint16_t) floor(rb_percentage * total_rbs);
}
int ue_slice_membership(int UE_id, int slice_id)
int ue_dl_slice_membership(module_id_t mod_id, int UE_id, int slice_idx)
{
if ((slice_id < 0) || (slice_id > n_active_slices))
LOG_W(MAC, "out of range slice id %d\n", slice_id);
if ((UE_id % n_active_slices) == slice_id) {
return 1; // this ue is a member of this slice
if ((slice_idx < 0)
|| (slice_idx >= RC.mac[mod_id]->slice_info.n_dl)) {
LOG_W(MAC, "out of range slice index %d (slice ID %d)\n",
slice_idx, RC.mac[mod_id]->slice_info.dl[slice_idx].id);
return 0;
}
return 0;
return RC.mac[mod_id]->UE_list.active[UE_id] == TRUE
&& RC.mac[mod_id]->UE_list.assoc_dl_slice_idx[UE_id] == slice_idx;
}
int ue_ul_slice_membership(module_id_t mod_id, int UE_id, int slice_idx)
{
if ((slice_idx < 0)
|| (slice_idx >= RC.mac[mod_id]->slice_info.n_ul)) {
LOG_W(MAC, "out of range slice index %d (slice ID %d)\n",
slice_idx, RC.mac[mod_id]->slice_info.dl[slice_idx].id);
return 0;
}
return RC.mac[mod_id]->UE_list.active[UE_id] == TRUE
&& RC.mac[mod_id]->UE_list.assoc_ul_slice_idx[UE_id] == slice_idx;
}
+68 -164
View File
@@ -63,6 +63,9 @@
#include "T.h"
#include "common/ran_context.h"
extern RAN_CONTEXT_t RC;
#define ENABLE_MAC_PAYLOAD_DEBUG
#define DEBUG_eNB_SCHEDULER 1
@@ -72,46 +75,14 @@ extern uint16_t sfnsf_add_subframe(uint16_t frameP, uint16_t subframeP, int offs
extern int oai_nfapi_ul_config_req(nfapi_ul_config_request_t *ul_config_req);
extern uint8_t nfapi_mode;
extern uint8_t nfapi_mode;
// This table holds the allowable PRB sizes for ULSCH transmissions
uint8_t rb_table[34] =
{ 1, 2, 3, 4, 5, 6, 8, 9, 10, 12, 15, 16, 18, 20, 24, 25, 27, 30, 32,
36, 40, 45, 48, 50, 54, 60, 64, 72, 75, 80, 81, 90, 96, 100
};
/* number of active slices for past and current time*/
int n_active_slices_uplink = 1;
int n_active_slices_current_uplink = 1;
/* RB share for each slice for past and current time*/
float avg_slice_percentage_uplink=0.25;
float slice_percentage_uplink[MAX_NUM_SLICES] = {1.0, 0.0, 0.0, 0.0};
float slice_percentage_current_uplink[MAX_NUM_SLICES] = {1.0, 0.0, 0.0, 0.0};
float total_slice_percentage_uplink = 0;
float total_slice_percentage_current_uplink = 0;
// MAX MCS for each slice for past and current time
int slice_maxmcs_uplink[MAX_NUM_SLICES] = {20, 20, 20, 20};
int slice_maxmcs_current_uplink[MAX_NUM_SLICES] = {20,20,20,20};
/*resource blocks allowed*/
uint16_t nb_rbs_allowed_slice_uplink[MAX_NUM_CCs][MAX_NUM_SLICES];
/*Slice Update */
int update_ul_scheduler[MAX_NUM_SLICES] = {1, 1, 1, 1};
int update_ul_scheduler_current[MAX_NUM_SLICES] = {1, 1, 1, 1};
/* name of available scheduler*/
char *ul_scheduler_type[MAX_NUM_SLICES] = {"schedule_ulsch_rnti",
"schedule_ulsch_rnti",
"schedule_ulsch_rnti",
"schedule_ulsch_rnti"
};
extern mui_t rrc_eNB_mui;
/* Slice Function Pointer */
slice_scheduler_ul slice_sched_ul[MAX_NUM_SLICES] = {0};
void
rx_sdu(const module_id_t enb_mod_idP,
const int CC_idP,
@@ -150,7 +121,7 @@ rx_sdu(const module_id_t enb_mod_idP,
VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME
(VCD_SIGNAL_DUMPER_FUNCTIONS_RX_SDU, 1);
if (opt_enabled == 1) {
trace_pdu(0, sduP, sdu_lenP, 0, 3, current_rnti, frameP, subframeP,
trace_pdu(DIRECTION_UPLINK, sduP, sdu_lenP, 0, WS_C_RNTI, current_rnti, frameP, subframeP,
0, 0);
LOG_D(OPT, "[eNB %d][ULSCH] Frame %d rnti %x with size %d\n",
enb_mod_idP, frameP, current_rnti, sdu_lenP);
@@ -432,10 +403,10 @@ rx_sdu(const module_id_t enb_mod_idP,
UE_list->UE_template[CC_idP][UE_id].ul_buffer_info[lcgid] = BSR_TABLE[bsr];
UE_list->UE_template[CC_idP][UE_id].estimated_ul_buffer =
UE_list->UE_template[CC_idP][UE_id].ul_buffer_info[0] +
UE_list->UE_template[CC_idP][UE_id].ul_buffer_info[1] +
UE_list->UE_template[CC_idP][UE_id].ul_buffer_info[2] +
UE_list->UE_template[CC_idP][UE_id].ul_buffer_info[3];
UE_list->UE_template[CC_idP][UE_id].ul_buffer_info[LCGID0] +
UE_list->UE_template[CC_idP][UE_id].ul_buffer_info[LCGID1] +
UE_list->UE_template[CC_idP][UE_id].ul_buffer_info[LCGID2] +
UE_list->UE_template[CC_idP][UE_id].ul_buffer_info[LCGID3];
//UE_list->UE_template[CC_idP][UE_id].estimated_ul_buffer += UE_list->UE_template[CC_idP][UE_id].estimated_ul_buffer / 4;
RC.eNB[enb_mod_idP][CC_idP]->pusch_stats_bsr[UE_id][(frameP * 10) + subframeP] = (payload_ptr[0] & 0x3f);
@@ -466,10 +437,10 @@ rx_sdu(const module_id_t enb_mod_idP,
int bsr2 = ((payload_ptr[1] & 0x0F) << 2) | ((payload_ptr[2] & 0xC0) >> 6);
int bsr3 = payload_ptr[2] & 0x3F;
lcgid_updated[0] = 1;
lcgid_updated[1] = 1;
lcgid_updated[2] = 1;
lcgid_updated[3] = 1;
lcgid_updated[LCGID0] = 1;
lcgid_updated[LCGID1] = 1;
lcgid_updated[LCGID2] = 1;
lcgid_updated[LCGID3] = 1;
// update buffer info
UE_list->UE_template[CC_idP][UE_id].ul_buffer_info[LCGID0] = BSR_TABLE[bsr0];
@@ -478,10 +449,10 @@ rx_sdu(const module_id_t enb_mod_idP,
UE_list->UE_template[CC_idP][UE_id].ul_buffer_info[LCGID3] = BSR_TABLE[bsr3];
UE_list->UE_template[CC_idP][UE_id].estimated_ul_buffer =
UE_list->UE_template[CC_idP][UE_id].ul_buffer_info[0] +
UE_list->UE_template[CC_idP][UE_id].ul_buffer_info[1] +
UE_list->UE_template[CC_idP][UE_id].ul_buffer_info[2] +
UE_list->UE_template[CC_idP][UE_id].ul_buffer_info[3];
UE_list->UE_template[CC_idP][UE_id].ul_buffer_info[LCGID0] +
UE_list->UE_template[CC_idP][UE_id].ul_buffer_info[LCGID1] +
UE_list->UE_template[CC_idP][UE_id].ul_buffer_info[LCGID2] +
UE_list->UE_template[CC_idP][UE_id].ul_buffer_info[LCGID3];
//UE_list->UE_template[CC_idP][UE_id].estimated_ul_buffer += UE_list->UE_template[CC_idP][UE_id].estimated_ul_buffer / 4;
LOG_D(MAC,
@@ -951,9 +922,10 @@ void
schedule_ulsch(module_id_t module_idP, frame_t frameP,
sub_frame_t subframeP)
{
uint16_t first_rb[MAX_NUM_CCs], i;
uint16_t first_rb[NFAPI_CC_MAX], i;
int CC_id;
eNB_MAC_INST *mac = RC.mac[module_idP];
slice_info_t *sli = &RC.mac[module_idP]->slice_info;
COMMON_channels_t *cc;
start_meas(&mac->schedule_ulsch);
@@ -1034,12 +1006,10 @@ schedule_ulsch(module_id_t module_idP, frame_t frameP,
break;
}
}
if (sched_subframe < subframeP) sched_frame++;
for (CC_id = 0; CC_id < MAX_NUM_CCs; CC_id++) {
for (CC_id = 0; CC_id < RC.nb_mac_CC[module_idP]; CC_id++) {
//leave out first RB for PUCCH
first_rb[CC_id] = 1;
@@ -1066,102 +1036,9 @@ schedule_ulsch(module_id_t module_idP, frame_t frameP,
}
}
// perform slice-specifc operations
total_slice_percentage_uplink=0;
avg_slice_percentage_uplink=1.0/n_active_slices_uplink;
// reset the slice percentage for inactive slices
for (i = n_active_slices_uplink; i< MAX_NUM_SLICES; i++) {
slice_percentage_uplink[i]=0;
}
for (i = 0; i < n_active_slices_uplink; i++) {
if (slice_percentage_uplink[i] < 0 ){
LOG_W(MAC, "[eNB %d] frame %d subframe %d:invalid slice %d percentage %f. resetting to zero",
module_idP, frameP, subframeP, i, slice_percentage_uplink[i]);
slice_percentage_uplink[i]=0;
}
total_slice_percentage_uplink+=slice_percentage_uplink[i];
}
for (i = 0; i < n_active_slices_uplink; i++) {
// Load any updated functions
if (update_ul_scheduler[i] > 0 ) {
slice_sched_ul[i] = dlsym(NULL, ul_scheduler_type[i]);
update_ul_scheduler[i] = 0;
update_ul_scheduler_current[i] = 0;
//slice_percentage_current_uplink[i]= slice_percentage_uplink[i];
//total_slice_percentage_current_uplink+=slice_percentage_uplink[i];
//if (total_slice_percentage_current_uplink> 1)
//total_slice_percentage_current_uplink=1;
LOG_I(MAC,"update ul scheduler slice %d\n", i);
}
// the new total RB share is within the range
if (total_slice_percentage_uplink <= 1.0){
// check if the number of slices has changed, and log
if (n_active_slices_current_uplink != n_active_slices_uplink ){
if ((n_active_slices_uplink > 0) && (n_active_slices_uplink <= MAX_NUM_SLICES)) {
LOG_I(MAC,"[eNB %d]frame %d subframe %d: number of active UL slices has changed: %d-->%d\n",
module_idP, frameP, subframeP, n_active_slices_current_uplink, n_active_slices_uplink);
n_active_slices_current_uplink = n_active_slices_uplink;
} else {
LOG_W(MAC,"invalid number of UL slices %d, revert to the previous value %d\n",
n_active_slices_uplink, n_active_slices_current_uplink);
n_active_slices_uplink = n_active_slices_current_uplink;
}
}
// check if the slice rb share has changed, and log the console
if (slice_percentage_current_uplink[i] != slice_percentage_uplink[i]){
LOG_I(MAC,"[eNB %d][SLICE %d][UL] frame %d subframe %d: total percentage %f-->%f, slice RB percentage has changed: %f-->%f\n",
module_idP, i, frameP, subframeP, total_slice_percentage_current_uplink,
total_slice_percentage_uplink, slice_percentage_current_uplink[i], slice_percentage_uplink[i]);
total_slice_percentage_current_uplink = total_slice_percentage_uplink;
slice_percentage_current_uplink[i] = slice_percentage_uplink[i];
}
// check if the slice max MCS, and log the console
if (slice_maxmcs_current_uplink[i] != slice_maxmcs_uplink[i]){
if ((slice_maxmcs_uplink[i] >= 0) && (slice_maxmcs_uplink[i] <= 16)){
LOG_I(MAC,"[eNB %d][SLICE %d][UL] frame %d subframe %d: slice MAX MCS has changed: %d-->%d\n",
module_idP, i, frameP, subframeP, slice_maxmcs_current_uplink[i], slice_maxmcs_uplink[i]);
slice_maxmcs_current_uplink[i] = slice_maxmcs_uplink[i];
} else {
LOG_W(MAC,"[eNB %d][SLICE %d][UL] invalid slice max mcs %d, revert the previous value %d\n",
module_idP, i, slice_maxmcs_uplink[i],slice_maxmcs_current_uplink[i]);
slice_maxmcs_uplink[i] = slice_maxmcs_current_uplink[i];
}
}
// check if a new scheduler, and log the console
if (update_ul_scheduler_current[i] != update_ul_scheduler[i]){
LOG_I(MAC,"[eNB %d][SLICE %d][UL] frame %d subframe %d: UL scheduler for this slice is updated: %s \n",
module_idP, i, frameP, subframeP, ul_scheduler_type[i]);
update_ul_scheduler_current[i] = update_ul_scheduler[i];
}
} else {
if (n_active_slices_uplink == n_active_slices_current_uplink) {
LOG_W(MAC,"[eNB %d][SLICE %d][UL] invalid total RB share (%f->%f), reduce proportionally the RB share by 0.1\n",
module_idP, i, total_slice_percentage_current_uplink, total_slice_percentage_uplink);
if (slice_percentage_uplink[i] > avg_slice_percentage_uplink) {
slice_percentage_uplink[i] -= 0.1;
total_slice_percentage_uplink -= 0.1;
}
} else {
// here we can correct the values, e.g. reduce proportionally
LOG_W(MAC,"[eNB %d][SLICE %d][UL] invalid total RB share (%f->%f), revert the number of slice to its previous value (%d->%d)\n",
module_idP, i, total_slice_percentage_current_uplink,
total_slice_percentage_uplink, n_active_slices_uplink,
n_active_slices_current_uplink);
n_active_slices_uplink = n_active_slices_current_uplink;
slice_percentage_uplink[i] = slice_percentage_current_uplink[i];
}
}
for (i = 0; i < sli->n_ul; i++) {
// Run each enabled slice-specific schedulers one by one
slice_sched_ul[i](module_idP, i, frameP, subframeP, sched_subframe, first_rb);
sli->ul[i].sched_cb(module_idP, i, frameP, subframeP, sched_subframe, first_rb);
}
stop_meas(&mac->schedule_ulsch);
@@ -1169,7 +1046,7 @@ schedule_ulsch(module_id_t module_idP, frame_t frameP,
void
schedule_ulsch_rnti(module_id_t module_idP,
slice_id_t slice_id,
int slice_idx,
frame_t frameP,
sub_frame_t subframeP,
unsigned char sched_subframeP, uint16_t * first_rb)
@@ -1191,12 +1068,14 @@ schedule_ulsch_rnti(module_id_t module_idP,
eNB_MAC_INST *mac = RC.mac[module_idP];
COMMON_channels_t *cc = mac->common_channels;
UE_list_t *UE_list = &mac->UE_list;
slice_info_t *sli = &RC.mac[module_idP]->slice_info;
UE_TEMPLATE *UE_template;
UE_sched_ctrl *UE_sched_ctrl;
int sched_frame = frameP;
int rvidx_tab[4] = { 0, 2, 3, 1 };
uint16_t ul_req_index;
uint8_t dlsch_flag;
int first_rb_slice[NFAPI_CC_MAX];
if (sched_subframeP < subframeP)
sched_frame++;
@@ -1208,9 +1087,18 @@ schedule_ulsch_rnti(module_id_t module_idP,
nfapi_ul_config_request_t *ul_req_tmp = &mac->UL_req_tmp[CC_id][sched_subframeP];
nfapi_ul_config_request_body_t *ul_req_tmp_body = &ul_req_tmp->ul_config_request_body;
nfapi_ul_config_ulsch_harq_information *ulsch_harq_information;
//LOG_D(MAC, "entering ulsch preprocesor\n");
ulsch_scheduler_pre_processor(module_idP, slice_id, frameP, subframeP, sched_subframeP, first_rb);
for (CC_id = 0; CC_id < RC.nb_mac_CC[module_idP]; ++CC_id) {
N_RB_UL = to_prb(cc[CC_id].ul_Bandwidth);
UE_list->first_rb_offset[CC_id][slice_idx] = cmin(N_RB_UL, sli->ul[slice_idx].first_rb);
}
//LOG_D(MAC, "entering ulsch preprocesor\n");
ulsch_scheduler_pre_processor(module_idP, slice_idx, frameP, subframeP, sched_subframeP, first_rb);
for (CC_id = 0; CC_id < RC.nb_mac_CC[module_idP]; ++CC_id) {
first_rb_slice[CC_id] = first_rb[CC_id] + UE_list->first_rb_offset[CC_id][slice_idx];
}
//LOG_D(MAC, "exiting ulsch preprocesor\n");
hi_dci0_req->sfn_sf = (frameP << 4) + subframeP;
@@ -1219,7 +1107,7 @@ schedule_ulsch_rnti(module_id_t module_idP,
for (UE_id = UE_list->head_ul; UE_id >= 0;
UE_id = UE_list->next_ul[UE_id]) {
if (!ue_slice_membership(UE_id, slice_id))
if (!ue_ul_slice_membership(module_idP, UE_id, slice_idx))
continue;
// don't schedule if Msg4 is not received yet
@@ -1296,7 +1184,7 @@ schedule_ulsch_rnti(module_id_t module_idP,
}
/* be sure that there are some free RBs */
if (first_rb[CC_id] >= N_RB_UL - 1) {
if (first_rb_slice[CC_id] >= N_RB_UL - 1) {
LOG_W(MAC,
"[eNB %d] frame %d subframe %d, UE %d/%x CC %d: dropping, not enough RBs\n",
module_idP, frameP, subframeP, UE_id, rnti, CC_id);
@@ -1337,10 +1225,24 @@ schedule_ulsch_rnti(module_id_t module_idP,
if (status >= RRC_CONNECTED && UE_sched_ctrl->cqi_req_timer > 30) {
if (UE_sched_ctrl->cqi_received == 0) {
if (nfapi_mode) {
cqi_req = 0;
cqi_req = 0;
} else {
cqi_req = 1;
UE_sched_ctrl->cqi_req_flag |= 1 << sched_subframeP;
cqi_req = 1;
// To be safe , do not ask CQI in special Subframes:36.213/7.2.3 CQI definition
if (cc[CC_id].tdd_Config) {
switch (cc[CC_id].tdd_Config->subframeAssignment) {
case 1:
if( subframeP == 1 || subframeP == 6 ) cqi_req=0;
break;
case 3:
if( subframeP == 1 ) cqi_req=0;
break;
default:
LOG_E(MAC," TDD config not supported\n");
break;
}
}
if(cqi_req == 1) UE_sched_ctrl->cqi_req_flag |= 1 << sched_subframeP;
}
}
else if (UE_sched_ctrl->cqi_received == 1) {
@@ -1393,7 +1295,7 @@ schedule_ulsch_rnti(module_id_t module_idP,
UE_template->oldNDI_UL[harq_pid] = ndi;
UE_list->eNB_UE_stats[CC_id][UE_id].normalized_rx_power = normalized_rx_power;
UE_list->eNB_UE_stats[CC_id][UE_id].target_rx_power = target_rx_power;
UE_template->mcs_UL[harq_pid] = cmin(UE_template->pre_assigned_mcs_ul, slice_maxmcs_uplink[slice_id]);
UE_template->mcs_UL[harq_pid] = cmin(UE_template->pre_assigned_mcs_ul, sli->ul[slice_idx].maxmcs);
UE_list->eNB_UE_stats[CC_id][UE_id].ulsch_mcs1= UE_template->mcs_UL[harq_pid];
//cmin (UE_template->pre_assigned_mcs_ul, openair_daq_vars.target_ue_ul_mcs); // adjust, based on user-defined MCS
if (UE_template->pre_allocated_rb_table_index_ul >= 0) {
@@ -1407,7 +1309,7 @@ schedule_ulsch_rnti(module_id_t module_idP,
// buffer_occupancy = UE_template->ul_total_buffer;
while (((rb_table[rb_table_index] > (N_RB_UL - 1 - first_rb[CC_id]))
while (((rb_table[rb_table_index] > (N_RB_UL - first_rb_slice[CC_id]))
|| (rb_table[rb_table_index] > 45))
&& (rb_table_index > 0)) {
rb_table_index--;
@@ -1424,7 +1326,7 @@ schedule_ulsch_rnti(module_id_t module_idP,
T_INT(CC_id), T_INT(rnti), T_INT(frameP),
T_INT(subframeP), T_INT(harq_pid),
T_INT(UE_template->mcs_UL[harq_pid]),
T_INT(first_rb[CC_id]),
T_INT(first_rb_slice[CC_id]),
T_INT(rb_table[rb_table_index]),
T_INT(UE_template->TBS_UL[harq_pid]), T_INT(ndi));
@@ -1434,14 +1336,14 @@ schedule_ulsch_rnti(module_id_t module_idP,
module_idP, harq_pid, rnti, CC_id, frameP,
subframeP, UE_id,
UE_template->mcs_UL[harq_pid],
first_rb[CC_id], rb_table[rb_table_index],
first_rb_slice[CC_id], rb_table[rb_table_index],
rb_table_index,
UE_template->TBS_UL[harq_pid], harq_pid);
// bad indices : 20 (40 PRB), 21 (45 PRB), 22 (48 PRB)
//store for possible retransmission
UE_template->nb_rb_ul[harq_pid] = rb_table[rb_table_index];
UE_template->first_rb_ul[harq_pid] = first_rb[CC_id];
UE_template->first_rb_ul[harq_pid] = first_rb_slice[CC_id];
UE_sched_ctrl->ul_scheduled |= (1 << harq_pid);
if (UE_id == UE_list->head)
@@ -1473,7 +1375,7 @@ schedule_ulsch_rnti(module_id_t module_idP,
hi_dci0_pdu->dci_pdu.dci_pdu_rel8.aggregation_level = aggregation;
hi_dci0_pdu->dci_pdu.dci_pdu_rel8.rnti = rnti;
hi_dci0_pdu->dci_pdu.dci_pdu_rel8.transmission_power = 6000;
hi_dci0_pdu->dci_pdu.dci_pdu_rel8.resource_block_start = first_rb[CC_id];
hi_dci0_pdu->dci_pdu.dci_pdu_rel8.resource_block_start = first_rb_slice[CC_id];
hi_dci0_pdu->dci_pdu.dci_pdu_rel8.number_of_resource_block = rb_table[rb_table_index];
hi_dci0_pdu->dci_pdu.dci_pdu_rel8.mcs_1 = UE_template->mcs_UL[harq_pid];
hi_dci0_pdu->dci_pdu.dci_pdu_rel8.cyclic_shift_2_for_drms = cshift;
@@ -1500,7 +1402,8 @@ schedule_ulsch_rnti(module_id_t module_idP,
ul_req_index = 0;
dlsch_flag = 0;
for(ul_req_index = 0;ul_req_index < ul_req_tmp_body->number_of_pdus;ul_req_index++){
if(ul_req_tmp_body->ul_config_pdu_list[ul_req_index].pdu_type == NFAPI_UL_CONFIG_UCI_HARQ_PDU_TYPE){
if(ul_req_tmp_body->ul_config_pdu_list[ul_req_index].pdu_type == NFAPI_UL_CONFIG_UCI_HARQ_PDU_TYPE &&
ul_req_tmp_body->ul_config_pdu_list[ul_req_index].uci_harq_pdu.ue_information.ue_information_rel8.rnti == rnti){
dlsch_flag = 1;
LOG_D(MAC,"Frame %d, Subframe %d:rnti %x ul_req_index %d Switched UCI HARQ to ULSCH HARQ(first)\n",frameP,subframeP,rnti,ul_req_index);
break;
@@ -1508,7 +1411,7 @@ schedule_ulsch_rnti(module_id_t module_idP,
}
// Add UL_config PDUs
fill_nfapi_ulsch_config_request_rel8(&ul_req_tmp_body->ul_config_pdu_list[ul_req_index], cqi_req, cc, UE_template->physicalConfigDedicated, get_tmode(module_idP, CC_id, UE_id), mac->ul_handle, rnti, first_rb[CC_id], // resource_block_start
fill_nfapi_ulsch_config_request_rel8(&ul_req_tmp_body->ul_config_pdu_list[ul_req_index], cqi_req, cc, UE_template->physicalConfigDedicated, get_tmode(module_idP, CC_id, UE_id), mac->ul_handle, rnti, first_rb_slice[CC_id], // resource_block_start
rb_table[rb_table_index], // number_of_resource_blocks
UE_template->mcs_UL[harq_pid], cshift, // cyclic_shift_2_for_drms
0, // frequency_hopping_enabled_flag
@@ -1571,13 +1474,13 @@ schedule_ulsch_rnti(module_id_t module_idP,
LOG_D(MAC,"[PUSCH %d] SFN/SF:%04d%d UL_CFG:SFN/SF:%04d%d CQI:%d for UE %d/%x\n", harq_pid,frameP,subframeP,ul_sched_frame,ul_sched_subframeP,cqi_req,UE_id,rnti);
// increment first rb for next UE allocation
first_rb[CC_id] += rb_table[rb_table_index];
first_rb_slice[CC_id] += rb_table[rb_table_index];
} else { // round > 0 => retransmission
T(T_ENB_MAC_UE_UL_SCHEDULE_RETRANSMISSION,
T_INT(module_idP), T_INT(CC_id), T_INT(rnti),
T_INT(frameP), T_INT(subframeP), T_INT(harq_pid),
T_INT(UE_template->mcs_UL[harq_pid]),
T_INT(first_rb[CC_id]),
T_INT(first_rb_slice[CC_id]),
T_INT(rb_table[rb_table_index]), T_INT(round));
// Add UL_config PDUs
@@ -1588,7 +1491,8 @@ schedule_ulsch_rnti(module_id_t module_idP,
ul_req_index = 0;
dlsch_flag = 0;
for(ul_req_index = 0;ul_req_index < ul_req_tmp_body->number_of_pdus;ul_req_index++){
if(ul_req_tmp_body->ul_config_pdu_list[ul_req_index].pdu_type == NFAPI_UL_CONFIG_UCI_HARQ_PDU_TYPE){
if(ul_req_tmp_body->ul_config_pdu_list[ul_req_index].pdu_type == NFAPI_UL_CONFIG_UCI_HARQ_PDU_TYPE &&
ul_req_tmp_body->ul_config_pdu_list[ul_req_index].uci_harq_pdu.ue_information.ue_information_rel8.rnti == rnti){
dlsch_flag = 1;
LOG_D(MAC,"Frame %d, Subframe %d:rnti %x ul_req_index %d Switched UCI HARQ to ULSCH HARQ(first)\n",frameP,subframeP,rnti,ul_req_index);
break;
+134 -4
View File
@@ -159,7 +159,7 @@
#define MIN_MAC_HDR_RLC_SIZE (1 + MIN_RLC_PDU_SIZE)
/*!\brief maximum number of slices / groups */
#define MAX_NUM_SLICES 4
#define MAX_NUM_SLICES 10
#define U_PLANE_INACTIVITY_VALUE 6000
@@ -442,7 +442,7 @@ typedef struct {
/*!\brief LCID of MCCH for DL */
#define MCCH_LCHANID 0
/*!\brief LCID of MCH scheduling info for DL */
#define MCH_SCHDL_INFO 3
#define MCH_SCHDL_INFO 30
/*!\brief LCID of Carrier component activation/deactivation */
#define CC_ACT_DEACT 27
//TTN (for D2D)
@@ -849,6 +849,9 @@ typedef struct {
/// LCGID mapping
long lcgidmap[11];
///UE logical channel priority
long lcgidpriority[11];
/// phr information
int8_t phr_info;
@@ -1099,6 +1102,10 @@ typedef struct {
/// Sorting criteria for the UE list in the MAC preprocessor
uint16_t sorting_criteria[MAX_NUM_SLICES][CR_NUM];
uint16_t first_rb_offset[NFAPI_CC_MAX][MAX_NUM_SLICES];
int assoc_dl_slice_idx[MAX_MOBILES_PER_ENB];
int assoc_ul_slice_idx[MAX_MOBILES_PER_ENB];
} UE_list_t;
@@ -1118,6 +1125,117 @@ typedef struct {
int tail_freelist; ///the tail position of the delete list
} UE_free_list_t;
/// Structure for saving the output of each pre_processor instance
typedef struct {
uint16_t nb_rbs_required[NFAPI_CC_MAX][MAX_MOBILES_PER_ENB];
uint16_t nb_rbs_accounted[NFAPI_CC_MAX][MAX_MOBILES_PER_ENB];
uint16_t nb_rbs_remaining[NFAPI_CC_MAX][MAX_MOBILES_PER_ENB];
uint8_t slice_allocation_mask[NFAPI_CC_MAX][N_RBG_MAX];
uint8_t MIMO_mode_indicator[NFAPI_CC_MAX][N_RBG_MAX];
uint32_t bytes_lcid[MAX_MOBILES_PER_ENB][MAX_NUM_LCID];
uint32_t wb_pmi[NFAPI_CC_MAX][MAX_MOBILES_PER_ENB];
uint8_t mcs[NFAPI_CC_MAX][MAX_MOBILES_PER_ENB];
} pre_processor_results_t;
/**
* slice specific scheduler for the DL
*/
typedef void (*slice_scheduler_dl)(module_id_t mod_id,
int slice_idx,
frame_t frame,
sub_frame_t subframe,
int *mbsfn_flag);
typedef struct {
slice_id_t id;
/// RB share for each slice
float pct;
/// whether this slice is isolated from the others
int isol;
int prio;
/// Frequency ranges for slice positioning
int pos_low;
int pos_high;
// max mcs for each slice
int maxmcs;
/// criteria for sorting policies of the slices
uint32_t sorting;
/// Accounting policy (just greedy(1) or fair(0) setting for now)
int accounting;
/// name of available scheduler
char *sched_name;
/// pointer to the slice specific scheduler in DL
slice_scheduler_dl sched_cb;
} slice_sched_conf_dl_t;
typedef void (*slice_scheduler_ul)(module_id_t mod_id,
int slice_idx,
frame_t frame,
sub_frame_t subframe,
unsigned char sched_subframe,
uint16_t *first_rb);
typedef struct {
slice_id_t id;
/// RB share for each slice
float pct;
// MAX MCS for each slice
int maxmcs;
/// criteria for sorting policies of the slices
uint32_t sorting;
/// starting RB (RB offset) of UL scheduling
int first_rb;
/// name of available scheduler
char *sched_name;
/// pointer to the slice specific scheduler in UL
slice_scheduler_ul sched_cb;
} slice_sched_conf_ul_t;
typedef struct {
/// counter used to indicate when all slices have pre-allocated UEs
//int slice_counter;
/// indicates whether remaining RBs after first intra-slice allocation will
/// be allocated to UEs of the same slice
int intraslice_share_active;
/// indicates whether remaining RBs after slice allocation will be
/// allocated to UEs of another slice. Isolated slices will be ignored
int interslice_share_active;
/// number of active DL slices
int n_dl;
slice_sched_conf_dl_t dl[MAX_NUM_SLICES];
/// number of active UL slices
int n_ul;
slice_sched_conf_ul_t ul[MAX_NUM_SLICES];
pre_processor_results_t pre_processor_results[MAX_NUM_SLICES];
/// common rb allocation list between slices
uint8_t rballoc_sub[NFAPI_CC_MAX][N_RBG_MAX];
} slice_info_t;
/*! \brief eNB common channels */
typedef struct {
int physCellId;
@@ -1238,7 +1356,10 @@ typedef struct eNB_MAC_INST_s {
/// UL handle
uint32_t ul_handle;
UE_list_t UE_list;
/// slice-related configuration
slice_info_t slice_info;
///subband bitmap configuration
SBMAP_CONF sbmap_conf;
/// CCE table used to build DCI scheduling information
@@ -1502,7 +1623,16 @@ typedef struct {
/// MCCH status
uint8_t mcch_status;
/// MSI status
uint8_t msi_status; // could be an array if there are >1 MCH in one MBSFN area
uint8_t msi_status_v[28];
uint8_t msi_current_alloc;
uint8_t msi_pmch;
struct MBSFN_SubframeConfig *commonSF_Alloc_r9_mbsfn_SubframeConfig[8]; // FIXME replace 8 by MAX_MBSFN_AREA?
uint8_t commonSF_AllocPeriod_r9;
int common_num_sf_alloc;
uint8_t pmch_lcids[28];
uint16_t pmch_stop_mtch[28];
#endif
//#ifdef CBA
/// CBA RNTI for each group
+80 -56
View File
@@ -36,22 +36,6 @@
* @{
*/
/**
* slice specific scheduler
*/
typedef void (*slice_scheduler_dl)(module_id_t mod_id,
slice_id_t slice_id,
frame_t frame,
sub_frame_t subframe,
int *mbsfn_flag);
typedef void (*slice_scheduler_ul)(module_id_t mod_id,
slice_id_t slice_id,
frame_t frame,
sub_frame_t subframe,
unsigned char sched_subframe,
uint16_t *first_rb);
/** \fn void schedule_mib(module_id_t module_idP,frame_t frameP,sub_frame_t subframe);
\brief MIB scheduling for PBCH. This function requests the MIB from RRC and provides it to L1.
@param Mod_id Instance ID of eNB
@@ -119,12 +103,12 @@ void schedule_ulsch(module_id_t module_idP, frame_t frameP,
/** \brief ULSCH Scheduling per RNTI
@param Mod_id Instance ID of eNB
@param slice_id Instance slice for this eNB
@param slice_idx Slice instance index for this eNB
@param frame Frame index
@param subframe Subframe number on which to act
@param sched_subframe Subframe number where PUSCH is transmitted (for DAI lookup)
*/
void schedule_ulsch_rnti(module_id_t module_idP, slice_id_t slice_idP, frame_t frameP,
void schedule_ulsch_rnti(module_id_t module_idP, int slice_idx, frame_t frameP,
sub_frame_t subframe,
unsigned char sched_subframe,
uint16_t * first_rb);
@@ -147,7 +131,7 @@ void fill_DLSCH_dci(module_id_t module_idP,frame_t frameP,sub_frame_t subframe,i
void schedule_dlsch(module_id_t module_idP, frame_t frameP,
sub_frame_t subframe, int *mbsfn_flag);
void schedule_ue_spec(module_id_t module_idP, slice_id_t slice_idP,
void schedule_ue_spec(module_id_t module_idP, int slice_idxP,
frame_t frameP,sub_frame_t subframe, int *mbsfn_flag);
void schedule_ue_spec_phy_test(module_id_t module_idP,frame_t frameP,sub_frame_t subframe,int *mbsfn_flag);
@@ -181,6 +165,10 @@ void add_msg3(module_id_t module_idP, int CC_id, RA_t * ra, frame_t frameP,
//main.c
void init_UE_list(UE_list_t *UE_list);
void init_slice_info(slice_info_t *sli);
int mac_top_init(int eMBMS_active, char *uecap_xer,
uint8_t cba_group_active, uint8_t HO_active);
@@ -204,24 +192,11 @@ void mac_UE_out_of_sync_ind(module_id_t module_idP, frame_t frameP,
void clear_nfapi_information(eNB_MAC_INST * eNB, int CC_idP,
frame_t frameP, sub_frame_t subframeP);
void dlsch_scheduler_pre_processor_reset(int module_idP, int UE_id,
uint8_t CC_id,
int frameP,
int subframeP,
int N_RBG,
uint16_t
nb_rbs_required[NFAPI_CC_MAX]
[MAX_MOBILES_PER_ENB],
unsigned char
rballoc_sub[NFAPI_CC_MAX]
[N_RBG_MAX],
unsigned char
MIMO_mode_indicator[NFAPI_CC_MAX]
[N_RBG_MAX]);
// eNB functions
/* \brief This function assigns pre-available RBS to each UE in specified sub-bands before scheduling is done
@param Mod_id Instance ID of eNB
@param slice_idxP Slice instance index for the slice in which scheduling happens
@param frame Index of frame
@param subframe Index of current subframe
@param N_RBS Number of resource block groups
@@ -229,24 +204,73 @@ void dlsch_scheduler_pre_processor_reset(int module_idP, int UE_id,
void dlsch_scheduler_pre_processor(module_id_t module_idP,
slice_id_t slice_idP,
frame_t frameP,
sub_frame_t subframe,
int N_RBG[NFAPI_CC_MAX],
int *mbsfn_flag);
int slice_idxP,
frame_t frameP,
sub_frame_t subframe,
int *mbsfn_flag,
uint8_t rballoc_sub[NFAPI_CC_MAX][N_RBG_MAX]);
void dlsch_scheduler_pre_processor_reset(module_id_t module_idP,
int slice_idx,
frame_t frameP,
sub_frame_t subframeP,
int min_rb_unit[NFAPI_CC_MAX],
uint16_t nb_rbs_required[NFAPI_CC_MAX][MAX_MOBILES_PER_ENB],
uint8_t rballoc_sub[NFAPI_CC_MAX][N_RBG_MAX],
uint8_t MIMO_mode_indicator[NFAPI_CC_MAX][N_RBG_MAX],
int *mbsfn_flag);
void dlsch_scheduler_pre_processor_partitioning(module_id_t Mod_id,
int slice_idx,
const uint8_t rbs_retx[NFAPI_CC_MAX]);
void dlsch_scheduler_pre_processor_accounting(module_id_t Mod_id,
int slice_idx,
frame_t frameP,
sub_frame_t subframeP,
int min_rb_unit[NFAPI_CC_MAX],
uint16_t nb_rbs_required[NFAPI_CC_MAX][MAX_MOBILES_PER_ENB],
uint16_t nb_rbs_accounted[NFAPI_CC_MAX][MAX_MOBILES_PER_ENB]);
void dlsch_scheduler_pre_processor_positioning(module_id_t Mod_id,
int slice_idx,
int min_rb_unit[NFAPI_CC_MAX],
uint16_t nb_rbs_required[NFAPI_CC_MAX][MAX_MOBILES_PER_ENB],
uint16_t nb_rbs_accounted[NFAPI_CC_MAX][MAX_MOBILES_PER_ENB],
uint16_t nb_rbs_remaining[NFAPI_CC_MAX][MAX_MOBILES_PER_ENB],
uint8_t rballoc_sub[NFAPI_CC_MAX][N_RBG_MAX],
uint8_t MIMO_mode_indicator[NFAPI_CC_MAX][N_RBG_MAX]);
void dlsch_scheduler_pre_processor_intraslice_sharing(module_id_t Mod_id,
int slice_idx,
int min_rb_unit[NFAPI_CC_MAX],
uint16_t nb_rbs_required[NFAPI_CC_MAX][MAX_MOBILES_PER_ENB],
uint16_t nb_rbs_accounted[NFAPI_CC_MAX][MAX_MOBILES_PER_ENB],
uint16_t nb_rbs_remaining[NFAPI_CC_MAX][MAX_MOBILES_PER_ENB],
uint8_t rballoc_sub[NFAPI_CC_MAX][N_RBG_MAX],
uint8_t MIMO_mode_indicator[NFAPI_CC_MAX][N_RBG_MAX]);
void slice_priority_sort(module_id_t Mod_id, int slice_list[MAX_NUM_SLICES]);
void dlsch_scheduler_interslice_multiplexing(module_id_t Mod_id,
int frameP,
sub_frame_t subframeP,
uint8_t rballoc_sub[NFAPI_CC_MAX][N_RBG_MAX]);
void dlsch_scheduler_qos_multiplexing(module_id_t Mod_id,
int frameP,
sub_frame_t subframeP);
void dlsch_scheduler_pre_processor_allocate(module_id_t Mod_id,
int UE_id,
uint8_t CC_id,
int N_RBG,
int transmission_mode,
int min_rb_unit,
uint8_t N_RB_DL,
uint16_t nb_rbs_required[NFAPI_CC_MAX][MAX_MOBILES_PER_ENB],
uint16_t nb_rbs_required_remaining[NFAPI_CC_MAX][MAX_MOBILES_PER_ENB],
unsigned char rballoc_sub[NFAPI_CC_MAX][N_RBG_MAX],
unsigned char MIMO_mode_indicator[NFAPI_CC_MAX][N_RBG_MAX]);
int UE_id,
uint8_t CC_id,
int N_RBG,
int min_rb_unit,
uint16_t nb_rbs_required[NFAPI_CC_MAX][MAX_MOBILES_PER_ENB],
uint16_t nb_rbs_remaining[NFAPI_CC_MAX][MAX_MOBILES_PER_ENB],
uint8_t rballoc_sub[NFAPI_CC_MAX][N_RBG_MAX],
uint8_t slice_allocation_mask[NFAPI_CC_MAX][N_RBG_MAX],
uint8_t MIMO_mode_indicator[NFAPI_CC_MAX][N_RBG_MAX]);
/* \brief Function to trigger the eNB scheduling procedure. It is called by PHY at the beginning of each subframe, \f$n$\f
and generates all DLSCH allocations for subframe \f$n\f$ and ULSCH allocations for subframe \f$n+k$\f.
@@ -676,8 +700,8 @@ int add_new_ue(module_id_t Mod_id, int CC_id, rnti_t rnti, int harq_pid
);
int rrc_mac_remove_ue(module_id_t Mod_id, rnti_t rntiP);
void store_dlsch_buffer(module_id_t Mod_id, slice_id_t slice_id, frame_t frameP, sub_frame_t subframeP);
void assign_rbs_required(module_id_t Mod_id, slice_id_t slice_id, frame_t frameP, sub_frame_t subframe, uint16_t nb_rbs_required[NFAPI_CC_MAX][MAX_MOBILES_PER_ENB], int min_rb_unit[NFAPI_CC_MAX]);
void store_dlsch_buffer(module_id_t Mod_id, int slice_idx, frame_t frameP, sub_frame_t subframeP);
void assign_rbs_required(module_id_t Mod_id, int slice_idx, frame_t frameP, sub_frame_t subframe, uint16_t nb_rbs_required[NFAPI_CC_MAX][MAX_MOBILES_PER_ENB], int min_rb_unit[NFAPI_CC_MAX]);
int maxround(module_id_t Mod_id, uint16_t rnti, int frame,
sub_frame_t subframe, uint8_t ul_flag);
@@ -696,20 +720,20 @@ void set_ul_DAI(int module_idP,
int frameP,
int subframeP);
void ulsch_scheduler_pre_processor(module_id_t module_idP, slice_id_t slice_id, int frameP,
void ulsch_scheduler_pre_processor(module_id_t module_idP, int slice_idx, int frameP,
sub_frame_t subframeP,
unsigned char sched_subframeP,
uint16_t * first_rb);
void store_ulsch_buffer(module_id_t module_idP, int frameP,
sub_frame_t subframeP);
void sort_ue_ul(module_id_t module_idP, int frameP, sub_frame_t subframeP);
void assign_max_mcs_min_rb(module_id_t module_idP, int slice_id, int frameP,
void assign_max_mcs_min_rb(module_id_t module_idP, int slice_idx, int frameP,
sub_frame_t subframeP, uint16_t * first_rb);
void adjust_bsr_info(int buffer_occupancy, uint16_t TBS,
UE_TEMPLATE * UE_template);
int phy_stats_exist(module_id_t Mod_id, int rnti);
void sort_UEs(module_id_t Mod_idP, slice_id_t slice_id, int frameP, sub_frame_t subframeP);
void sort_UEs(module_id_t Mod_idP, int slice_idx, int frameP, sub_frame_t subframeP);
/*! \fn UE_L2_state_t ue_scheduler(const module_id_t module_idP,const frame_t frameP, const sub_frame_t subframe, const lte_subframe_t direction,const uint8_t eNB_index)
\brief UE scheduler where all the ue background tasks are done. This function performs the following: 1) Trigger PDCP every 5ms 2) Call RRC for link status return to PHY3) Perform SR/BSR procedures for scheduling feedback 4) Perform PHR procedures.
@@ -1244,9 +1268,9 @@ void pre_scd_nb_rbs_required( module_id_t module_idP,
#endif
/*Slice related functions */
uint16_t flexran_nb_rbs_allowed_slice(float rb_percentage, int total_rbs);
int ue_slice_membership(int UE_id, int slice_id);
uint16_t nb_rbs_allowed_slice(float rb_percentage, int total_rbs);
int ue_dl_slice_membership(module_id_t mod_id, int UE_id, int slice_idx);
int ue_ul_slice_membership(module_id_t mod_id, int UE_id, int slice_idx);
/* from here: prototypes to get rid of compilation warnings: doc to be written by function author */
uint8_t ul_subframe2_k_phich(COMMON_channels_t * cc, sub_frame_t ul_subframe);
+95 -77
View File
@@ -29,6 +29,7 @@
*/
#include <dlfcn.h>
#include "mac.h"
#include "mac_proto.h"
#include "mac_extern.h"
@@ -45,96 +46,113 @@
extern RAN_CONTEXT_t RC;
void init_UE_list(UE_list_t *UE_list)
{
int list_el;
UE_list->num_UEs = 0;
UE_list->head = -1;
UE_list->head_ul = -1;
UE_list->avail = 0;
for (list_el = 0; list_el < MAX_MOBILES_PER_ENB - 1; list_el++) {
UE_list->next[list_el] = list_el + 1;
UE_list->next_ul[list_el] = list_el + 1;
}
UE_list->next[list_el] = -1;
UE_list->next_ul[list_el] = -1;
memset(UE_list->DLSCH_pdu, 0, sizeof(UE_list->DLSCH_pdu));
memset(UE_list->UE_template, 0, sizeof(UE_list->UE_template));
memset(UE_list->eNB_UE_stats, 0, sizeof(UE_list->eNB_UE_stats));
memset(UE_list->UE_sched_ctrl, 0, sizeof(UE_list->UE_sched_ctrl));
memset(UE_list->active, 0, sizeof(UE_list->active));
memset(UE_list->assoc_dl_slice_idx, 0, sizeof(UE_list->assoc_dl_slice_idx));
memset(UE_list->assoc_ul_slice_idx, 0, sizeof(UE_list->assoc_ul_slice_idx));
}
void init_slice_info(slice_info_t *sli)
{
sli->intraslice_share_active = 1;
sli->interslice_share_active = 1;
sli->n_dl = 1;
memset(sli->dl, 0, sizeof(slice_sched_conf_dl_t) * MAX_NUM_SLICES);
sli->dl[0].pct = 1.0;
sli->dl[0].prio = 10;
sli->dl[0].pos_high = N_RBG_MAX;
sli->dl[0].maxmcs = 28;
sli->dl[0].sorting = 0x012345;
sli->dl[0].sched_name = "schedule_ue_spec";
sli->dl[0].sched_cb = dlsym(NULL, sli->dl[0].sched_name);
AssertFatal(sli->dl[0].sched_cb, "DLSCH scheduler callback is NULL\n");
sli->n_ul = 1;
memset(sli->ul, 0, sizeof(slice_sched_conf_ul_t) * MAX_NUM_SLICES);
sli->ul[0].pct = 1.0;
sli->ul[0].maxmcs = 20;
sli->ul[0].sorting = 0x0123;
sli->ul[0].sched_name = "schedule_ulsch_rnti";
sli->ul[0].sched_cb = dlsym(NULL, sli->ul[0].sched_name);
AssertFatal(sli->ul[0].sched_cb, "ULSCH scheduler callback is NULL\n");
}
void mac_top_init_eNB(void)
{
module_id_t i, j;
eNB_MAC_INST **mac;
module_id_t i, j;
int list_el;
UE_list_t *UE_list;
eNB_MAC_INST *mac;
LOG_I(MAC, "[MAIN] Init function start:nb_macrlc_inst=%d\n",
RC.nb_macrlc_inst);
LOG_I(MAC, "[MAIN] Init function start:nb_macrlc_inst=%d\n",
RC.nb_macrlc_inst);
if (RC.nb_macrlc_inst <= 0) {
RC.mac = NULL;
return;
}
if (RC.nb_macrlc_inst > 0) {
if (RC.mac == NULL){
RC.mac =
(eNB_MAC_INST **) malloc16(RC.nb_macrlc_inst *
sizeof(eNB_MAC_INST *));
bzero(RC.mac, RC.nb_macrlc_inst * sizeof(eNB_MAC_INST *));
}
AssertFatal(RC.mac != NULL,
"can't ALLOCATE %zu Bytes for %d eNB_MAC_INST with size %zu \n",
RC.nb_macrlc_inst * sizeof(eNB_MAC_INST *),
RC.nb_macrlc_inst, sizeof(eNB_MAC_INST));
for (i = 0; i < RC.nb_macrlc_inst; i++) {
if (RC.mac[i] == NULL) {
RC.mac[i] = (eNB_MAC_INST *) malloc16(sizeof(eNB_MAC_INST));
AssertFatal(RC.mac[i] != NULL,
"can't ALLOCATE %zu Bytes for %d eNB_MAC_INST with size %zu \n",
RC.nb_macrlc_inst * sizeof(eNB_MAC_INST *),
RC.nb_macrlc_inst, sizeof(eNB_MAC_INST));
LOG_D(MAC,
"[MAIN] ALLOCATE %zu Bytes for %d eNB_MAC_INST @ %p\n",
sizeof(eNB_MAC_INST), RC.nb_macrlc_inst, RC.mac);
bzero(RC.mac[i], sizeof(eNB_MAC_INST));
}
RC.mac[i]->Mod_id = i;
for (j = 0; j < MAX_NUM_CCs; j++) {
RC.mac[i]->DL_req[j].dl_config_request_body.
dl_config_pdu_list = RC.mac[i]->dl_config_pdu_list[j];
RC.mac[i]->UL_req[j].ul_config_request_body.
ul_config_pdu_list = RC.mac[i]->ul_config_pdu_list[j];
for (int k = 0; k < 10; k++)
RC.mac[i]->UL_req_tmp[j][k].
ul_config_request_body.ul_config_pdu_list =
RC.mac[i]->ul_config_pdu_list_tmp[j][k];
for(int sf=0;sf<10;sf++){
RC.mac[i]->HI_DCI0_req[j][sf].hi_dci0_request_body.hi_dci0_pdu_list =RC.mac[i]->hi_dci0_pdu_list[j][sf];
}
RC.mac[i]->TX_req[j].tx_request_body.tx_pdu_list =
RC.mac[i]->tx_request_pdu[j];
RC.mac[i]->ul_handle = 0;
}
}
AssertFatal(rlc_module_init() == 0,
"Could not initialize RLC layer\n");
// These should be out of here later
pdcp_layer_init();
rrc_init_global_param();
} else {
RC.mac = NULL;
mac = malloc16(RC.nb_macrlc_inst * sizeof(eNB_MAC_INST *));
AssertFatal(mac != NULL,
"can't ALLOCATE %zu Bytes for %d eNB_MAC_INST with size %zu \n",
RC.nb_macrlc_inst * sizeof(eNB_MAC_INST *),
RC.nb_macrlc_inst, sizeof(eNB_MAC_INST));
for (i = 0; i < RC.nb_macrlc_inst; i++) {
mac[i] = malloc16(sizeof(eNB_MAC_INST));
AssertFatal(mac[i] != NULL,
"can't ALLOCATE %zu Bytes for %d eNB_MAC_INST with size %zu \n",
RC.nb_macrlc_inst * sizeof(eNB_MAC_INST *),
RC.nb_macrlc_inst, sizeof(eNB_MAC_INST));
LOG_D(MAC,
"[MAIN] ALLOCATE %zu Bytes for %d eNB_MAC_INST @ %p\n",
sizeof(eNB_MAC_INST), RC.nb_macrlc_inst, mac);
bzero(mac[i], sizeof(eNB_MAC_INST));
mac[i]->Mod_id = i;
for (j = 0; j < MAX_NUM_CCs; j++) {
mac[i]->DL_req[j].dl_config_request_body.dl_config_pdu_list =
mac[i]->dl_config_pdu_list[j];
mac[i]->UL_req[j].ul_config_request_body.ul_config_pdu_list =
mac[i]->ul_config_pdu_list[j];
for (int k = 0; k < 10; k++)
mac[i]->UL_req_tmp[j][k].ul_config_request_body.ul_config_pdu_list =
mac[i]->ul_config_pdu_list_tmp[j][k];
for(int sf=0;sf<10;sf++)
mac[i]->HI_DCI0_req[j][sf].hi_dci0_request_body.hi_dci0_pdu_list =
mac[i]->hi_dci0_pdu_list[j][sf];
mac[i]->TX_req[j].tx_request_body.tx_pdu_list = mac[i]->tx_request_pdu[j];
mac[i]->ul_handle = 0;
}
// Initialize Linked-List for Active UEs
for (i = 0; i < RC.nb_macrlc_inst; i++) {
mac = RC.mac[i];
mac[i]->if_inst = IF_Module_init(i);
init_UE_list(&mac[i]->UE_list);
init_slice_info(&mac[i]->slice_info);
}
mac->if_inst = IF_Module_init(i);
RC.mac = mac;
UE_list = &mac->UE_list;
AssertFatal(rlc_module_init() == 0,
"Could not initialize RLC layer\n");
UE_list->num_UEs = 0;
UE_list->head = -1;
UE_list->head_ul = -1;
UE_list->avail = 0;
for (list_el = 0; list_el < MAX_MOBILES_PER_ENB - 1; list_el++) {
UE_list->next[list_el] = list_el + 1;
UE_list->next_ul[list_el] = list_el + 1;
}
UE_list->next[list_el] = -1;
UE_list->next_ul[list_el] = -1;
}
// These should be out of here later
pdcp_layer_init();
rrc_init_global_param();
}
void mac_init_cell_params(int Mod_idP, int CC_idP)
File diff suppressed because it is too large Load Diff
+3 -3
View File
@@ -248,7 +248,7 @@ Msg1_transmitted(module_id_t module_idP, uint8_t CC_id,
UE_mac_inst[module_idP].RA_attempt_number++;
if (opt_enabled) {
trace_pdu(0, NULL, 0, module_idP, 0,
trace_pdu(DIRECTION_UPLINK, NULL, 0, module_idP, WS_NO_RNTI,
UE_mac_inst[module_idP].RA_prach_resources.
ra_PreambleIndex, UE_mac_inst[module_idP].txFrame,
UE_mac_inst[module_idP].txSubframe, 0,
@@ -277,8 +277,8 @@ Msg3_transmitted(module_id_t module_idP, uint8_t CC_id,
UE_mac_inst[module_idP].RA_contention_resolution_timer_active = 1;
if (opt_enabled) { // msg3
trace_pdu(0, &UE_mac_inst[module_idP].CCCH_pdu.payload[0],
UE_mac_inst[module_idP].RA_Msg3_size, module_idP, 3,
trace_pdu(DIRECTION_UPLINK , &UE_mac_inst[module_idP].CCCH_pdu.payload[0],
UE_mac_inst[module_idP].RA_Msg3_size, module_idP, WS_C_RNTI,
UE_mac_inst[module_idP].crnti,
UE_mac_inst[module_idP].txFrame,
UE_mac_inst[module_idP].txSubframe, 0, 0);
+2 -2
View File
@@ -96,7 +96,7 @@ fill_rar(const module_id_t module_idP,
((ra->msg3_ULdelay & 1) << 1) | (ra->msg3_cqireq & 1);
if (opt_enabled) {
trace_pdu(1, dlsch_buffer, input_buffer_length, module_idP, 2, 1,
trace_pdu(DIRECTION_DOWNLINK , dlsch_buffer, input_buffer_length, module_idP, WS_RA_RNTI , 1,
RC.mac[module_idP]->frame, RC.mac[module_idP]->subframe,
0, 0);
LOG_D(OPT,
@@ -181,7 +181,7 @@ fill_rar_br(eNB_MAC_INST * eNB,
ra->preamble_index, ra->timing_offset);
if (opt_enabled) {
trace_pdu(1, dlsch_buffer, input_buffer_length, eNB->Mod_id, 2, 1,
trace_pdu(DIRECTION_DOWNLINK , dlsch_buffer, input_buffer_length, eNB->Mod_id, WS_RA_RNTI , 1,
eNB->frame, eNB->subframe, 0, 0);
LOG_D(OPT,
"[RAPROC] RAR Frame %d trace pdu for rnti %x and rapid %d size %d\n",
+2 -2
View File
@@ -119,8 +119,8 @@ uint16_t ue_process_rar(const module_id_t module_idP, const int CC_id, const fra
LOG_D(OPT,
"[UE %d][RAPROC] CC_id %d RAR Frame %d trace pdu for ra-RNTI %x\n",
module_idP, CC_id, frameP, ra_rnti);
trace_pdu(1, (uint8_t *) dlsch_buffer, n_rarh + n_rarpy * 6,
module_idP, 2, ra_rnti, UE_mac_inst[module_idP].rxFrame,
trace_pdu(DIRECTION_DOWNLINK, (uint8_t *) dlsch_buffer, n_rarh + n_rarpy * 6,
module_idP, WS_RA_RNTI, ra_rnti, UE_mac_inst[module_idP].rxFrame,
UE_mac_inst[module_idP].rxSubframe, 0, 0);
}
File diff suppressed because it is too large Load Diff
+66 -29
View File
@@ -30,6 +30,8 @@
#define PDCP_C
//#define DEBUG_PDCP_FIFO_FLUSH_SDU
#define MBMS_MULTICAST_OUT
#include "assertions.h"
#include "hashtable.h"
#include "pdcp.h"
@@ -66,6 +68,17 @@ extern int otg_enabled;
#include "common/ran_context.h"
extern RAN_CONTEXT_t RC;
#ifdef MBMS_MULTICAST_OUT
# include <sys/types.h>
# include <sys/socket.h>
# include <netinet/in.h>
# include <netinet/ip.h>
# include <netinet/udp.h>
# include <unistd.h>
static int mbms_socket = -1;
#endif
//-----------------------------------------------------------------------------
/*
* If PDCP_UNIT_TEST is set here then data flow between PDCP and RLC is broken
@@ -349,16 +362,10 @@ boolean_t pdcp_data_req(
* Ask sublayer to transmit data and check return value
* to see if RLC succeeded
*/
#ifdef PDCP_MSG_PRINT
int i=0;
LOG_F(PDCP,"[MSG] PDCP DL %s PDU on rb_id %d\n", (srb_flagP)? "CONTROL" : "DATA", rb_idP);
for (i = 0; i < pdcp_pdu_size; i++) {
LOG_F(PDCP,"%02x ", ((uint8_t*)pdcp_pdu_p->data)[i]);
}
LOG_DUMPMSG(PDCP,DEBUG_PDCP,(char *)pdcp_pdu_p->data,pdcp_pdu_size,
"[MSG] PDCP DL %s PDU on rb_id %d\n",(srb_flagP)? "CONTROL" : "DATA", rb_idP);
LOG_F(PDCP,"\n");
#endif
rlc_status = rlc_data_req(ctxt_pP, srb_flagP, MBMS_FLAG_NO, rb_idP, muiP, confirmP, pdcp_pdu_size, pdcp_pdu_p
#if (RRC_VERSION >= MAKE_VERSION(14, 0, 0))
,sourceL2Id
@@ -405,9 +412,9 @@ boolean_t pdcp_data_req(
* Control arrives here only if rlc_data_req() returns RLC_OP_STATUS_OK
* so we return TRUE afterwards
*/
for (pdcp_uid=0; pdcp_uid< MAX_MOBILES_PER_ENB;pdcp_uid++){
if (pdcp_enb[ctxt_pP->module_id].rnti[pdcp_uid] == ctxt_pP->rnti )
if (pdcp_enb[ctxt_pP->module_id].rnti[pdcp_uid] == ctxt_pP->rnti )
break;
}
@@ -461,17 +468,8 @@ pdcp_data_ind(
VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_PDCP_DATA_IND,VCD_FUNCTION_IN);
#ifdef PDCP_MSG_PRINT
int i=0;
LOG_F(PDCP,"[MSG] PDCP UL %s PDU on rb_id %d\n", (srb_flagP)? "CONTROL" : "DATA", rb_idP);
for (i = 0; i < sdu_buffer_sizeP; i++) {
LOG_F(PDCP,"%02x ", ((uint8_t*)sdu_buffer_pP->data)[i]);
}
LOG_F(PDCP,"\n");
#endif
LOG_DUMPMSG(PDCP,DEBUG_PDCP,(char *)sdu_buffer_pP->data,sdu_buffer_sizeP,
"[MSG] PDCP UL %s PDU on rb_id %d\n", (srb_flagP)? "CONTROL" : "DATA", rb_idP);
#if T_TRACER
if (ctxt_pP->enb_flag != ENB_FLAG_NO)
@@ -758,11 +756,26 @@ pdcp_data_ind(
packet_forwarded = FALSE;
#endif
#ifdef MBMS_MULTICAST_OUT
if ((MBMS_flagP != 0) && (mbms_socket != -1)) {
struct iphdr *ip_header = (struct iphdr*)&sdu_buffer_pP->data[payload_offset];
struct udphdr *udp_header = (struct udphdr*)&sdu_buffer_pP->data[payload_offset + sizeof(struct iphdr)];
struct sockaddr_in dest_addr;
dest_addr.sin_family = AF_INET;
dest_addr.sin_port = udp_header->dest;
dest_addr.sin_addr.s_addr = ip_header->daddr;
sendto(mbms_socket, &sdu_buffer_pP->data[payload_offset], sdu_buffer_sizeP - payload_offset, MSG_DONTWAIT, (struct sockaddr*)&dest_addr, sizeof(dest_addr));
packet_forwarded = TRUE;
}
#endif
if (FALSE == packet_forwarded) {
new_sdu_p = get_free_mem_block(sdu_buffer_sizeP - payload_offset + sizeof (pdcp_data_ind_header_t), __func__);
if (new_sdu_p) {
if (pdcp_p->rlc_mode == RLC_MODE_AM ) {
if ((MBMS_flagP == 0) && (pdcp_p->rlc_mode == RLC_MODE_AM)) {
pdcp_p->last_submitted_pdcp_rx_sn = sequence_number;
}
@@ -803,7 +816,6 @@ pdcp_data_ind(
}
}
/* Print octets of incoming data in hexadecimal form */
LOG_D(PDCP, "Following content has been received from RLC (%d,%d)(PDCP header has already been removed):\n",
@@ -839,13 +851,14 @@ pdcp_data_ind(
#if defined(STOP_ON_IP_TRAFFIC_OVERLOAD)
else {
AssertFatal(0, PROTOCOL_PDCP_CTXT_FMT" PDCP_DATA_IND SDU DROPPED, OUT OF MEMORY \n",
PROTOCOL_PDCP_CTXT_ARGS(ctxt_pP, pdcp_p));
}
else {
AssertFatal(0, PROTOCOL_PDCP_CTXT_FMT" PDCP_DATA_IND SDU DROPPED, OUT OF MEMORY \n",
PROTOCOL_PDCP_CTXT_ARGS(ctxt_pP, pdcp_p));
}
#endif
}
free_mem_block(sdu_buffer_pP, __func__);
if (ctxt_pP->enb_flag) {
@@ -1458,8 +1471,12 @@ rrc_pdcp_config_asn1_req (
for (j=0; j<mbms_SessionInfoList_r9_p->list.count; j++) {
MBMS_SessionInfo_p = mbms_SessionInfoList_r9_p->list.array[j];
lc_id = MBMS_SessionInfo_p->sessionId_r9->buf[0];
if (MBMS_SessionInfo_p->sessionId_r9)
lc_id = MBMS_SessionInfo_p->sessionId_r9->buf[0];
else
lc_id = MBMS_SessionInfo_p->logicalChannelIdentity_r9;
mch_id = MBMS_SessionInfo_p->tmgi_r9.serviceId_r9.buf[2]; //serviceId is 3-octet string
// mch_id = j;
// can set the mch_id = i
if (ctxt_pP->enb_flag) {
@@ -1480,6 +1497,14 @@ rrc_pdcp_config_asn1_req (
}
}
LOG_D(PDCP, "lc_id (%02ld) mch_id(%02x,%02x,%02x) drb_id(%ld) action(%d)\n",
lc_id,
MBMS_SessionInfo_p->tmgi_r9.serviceId_r9.buf[0],
MBMS_SessionInfo_p->tmgi_r9.serviceId_r9.buf[1],
MBMS_SessionInfo_p->tmgi_r9.serviceId_r9.buf[2],
drb_id,
action);
pdcp_config_req_asn1 (
ctxt_pP,
NULL, // unused for MBMS
@@ -2018,6 +2043,12 @@ void pdcp_layer_init(void)
#endif
}
#ifdef MBMS_MULTICAST_OUT
mbms_socket = socket(AF_INET, SOCK_RAW, IPPROTO_RAW);
if (mbms_socket == -1)
LOG_W(PDCP, "Could not create RAW socket, MBMS packets will not be put to the network\n");
#endif
LOG_I(PDCP, "PDCP layer has been initialized\n");
pdcp_output_sdu_bytes_to_write=0;
@@ -2068,6 +2099,12 @@ void pdcp_layer_cleanup (void)
{
list_free (&pdcp_sdu_list);
hashtable_destroy(pdcp_coll_p);
#ifdef MBMS_MULTICAST_OUT
if(mbms_socket != -1) {
close(mbms_socket);
mbms_socket = -1;
}
#endif
}
#ifdef PDCP_USE_RT_FIFO
+6 -6
View File
@@ -760,10 +760,10 @@ int pdcp_fifo_read_input_sdus (const protocol_ctxt_t* const ctxt_pP)
0,
MSC_AS_TIME_FMT" DATA-REQ inst %u rb %u rab %u size %u",
MSC_AS_TIME_ARGS(ctxt_pP),
pc5s_header.inst,
pc5s_header.rb_id,
pc5s_header->inst,
pc5s_header->rb_id,
rab_id,
pc5s_header.data_size);
pc5s_header->data_size);
pdcp_data_req(
&ctxt,
@@ -787,10 +787,10 @@ int pdcp_fifo_read_input_sdus (const protocol_ctxt_t* const ctxt_pP)
0,
MSC_AS_TIME_FMT" DATA-REQ inst %u rb %u rab %u size %u",
MSC_AS_TIME_ARGS(ctxt_pP),
pc5s_header.inst,
pc5s_header.rb_id,
pc5s_header->inst,
pc5s_header->rb_id,
rab_id,
pc5s_header.data_size);
pc5s_header->data_size);
LOG_D(PDCP,
"[FRAME %5u][UE][IP][INSTANCE %u][RB %u][--- PDCP_DATA_REQ / %d Bytes ---X][PDCP][MOD %u][UE %u][RB %u] NON INSTANCIATED INSTANCE key 0x%"PRIx64", DROPPED\n",
ctxt.frame,
+1 -1
View File
@@ -208,7 +208,7 @@ rlc_mbms_id_t rlc_mbms_lcid2service_session_id_eNB[MAX_eNB][RLC_MAX_MBMS_
#define rlc_mbms_ue_get_lcid_by_rb_id(uE_mOD,rB_iD) rlc_mbms_rbid2lcid_ue[uE_mOD][rB_iD]
#define rlc_mbms_ue_set_lcid_by_rb_id(uE_mOD,rB_iD,lOG_cH_iD) do { \
AssertFatal(rB_iD<NB_RB_MAX, "INVALID RB ID %u", rB_iD); \
AssertFatal(rB_iD<NB_RB_MBMS_MAX, "INVALID RB ID %u", rB_iD); \
rlc_mbms_rbid2lcid_ue[uE_mOD][rB_iD] = lOG_cH_iD; \
} while (0);
+5 -1
View File
@@ -414,9 +414,13 @@ rlc_op_status_t rrc_rlc_config_asn1_req (const protocol_ctxt_t * const ctxt_pP
for (j=0; j<mbms_SessionInfoList_r9_p->list.count; j++) {
MBMS_SessionInfo_p = mbms_SessionInfoList_r9_p->list.array[j];
mbms_session_id = MBMS_SessionInfo_p->sessionId_r9->buf[0];
if (MBMS_SessionInfo_p->sessionId_r9)
mbms_session_id = MBMS_SessionInfo_p->sessionId_r9->buf[0];
else
mbms_session_id = MBMS_SessionInfo_p->logicalChannelIdentity_r9;
lc_id = mbms_session_id;
mbms_service_id = MBMS_SessionInfo_p->tmgi_r9.serviceId_r9.buf[2]; //serviceId is 3-octet string
// mbms_service_id = j;
// can set the mch_id = i
if (ctxt_pP->enb_flag) {
+1 -1
View File
@@ -333,7 +333,7 @@ void oai_nw_drv_common_class_wireless2ip(uint16_t dlen,
printk("\n");
#endif //OAI_DRV_DEBUG_RECEIVE
netif_rx(skb);
netif_rx_ni(skb);
#ifdef OAI_DRV_DEBUG_RECEIVE
printk("[OAI_IP_DRV][%s] end\n",__FUNCTION__);
#endif
+2 -2
View File
@@ -410,7 +410,7 @@ struct cx_entity *nas_CLASS_cx6(struct sk_buff *skb,
#endif //NAS_DEBUG_CLASS
//if ((dst = (unsigned int*)&(((struct rt6_info *)skbdst)->rt6i_gateway)) == 0){
if ((dst = ((struct iphdr*)(skb_network_header(skb)))->daddr) == 0) {
if ( (dst = &((struct iphdr*)(skb_network_header(skb)))->daddr) == NULL) {
printk("nas_CLASS_cx6: dst addr is null \n");
p = p->next;
@@ -475,7 +475,7 @@ struct cx_entity *nas_CLASS_cx4(struct sk_buff *skb,
if (skb!=NULL) {
daddr = ((struct iphdr*)(skb_network_header(skb)))->daddr;
if (daddr!=NULL) {
if (daddr!=0) {
#ifdef NAS_DEBUG_CLASS
printk("[NAS][CLASS][IPv4] Searching for %d.%d.%d.%d\n",
+4 -5
View File
@@ -53,17 +53,14 @@ void nas_COMMON_receive(uint16_t dlen,
struct sk_buff *skb;
struct ipversion *ipv;
struct nas_priv *gpriv=netdev_priv(nasdev[inst]);
uint32_t odaddr,osaddr;
//int i;
unsigned char protocol;
unsigned char /**addr,*/ *daddr,*saddr,*ifaddr /*,sn*/;
//struct udphdr *uh;
//struct tcphdr *th;
uint16_t *cksum,check;
struct iphdr *network_header;
@@ -114,11 +111,12 @@ void nas_COMMON_receive(uint16_t dlen,
// Make the third byte of both the source and destination equal to the fourth of the destination
unsigned char * ifaddr, *saddr, daddr;
daddr = (unsigned char *)&((struct iphdr *)skb->data)->daddr;
odaddr = ((struct iphdr *)skb->data)->daddr;
// sn = addr[3];
saddr = (unsigned char *)&((struct iphdr *)skb->data)->saddr;
uint32_t odaddr,osaddr;
osaddr = ((struct iphdr *)skb->data)->saddr;
if (daddr[0] == saddr[0]) {// same network
@@ -219,6 +217,7 @@ void nas_COMMON_receive(uint16_t dlen,
case IPPROTO_TCP:
uint16_t *cksum,check;
cksum = (uint16_t*)&(((struct tcphdr*)(((char *)network_header + (network_header->ihl<<2))))->check);
//check = csum_tcpudp_magic(((struct iphdr *)network_header)->saddr, ((struct iphdr *)network_header)->daddr, tcp_hdrlen(skb), IPPROTO_TCP, ~(*cksum));
@@ -309,7 +308,7 @@ void nas_COMMON_receive(uint16_t dlen,
printk("\n");
#endif //NAS_DEBUG_RECEIVE
netif_rx(skb);
netif_rx_ni(skb);
#ifdef NAS_DEBUG_RECEIVE
printk("NAS_COMMON_RECEIVE: end\n");
#endif
+3 -3
View File
@@ -241,7 +241,7 @@ int nas_hard_start_xmit(struct sk_buff *skb, struct net_device *dev)
// End debug information
netif_stop_queue(dev);
#if LINUX_VERSION_CODE >= KERNEL_VERSION(4,7,0) || RHEL_RELEASE_CODE>=1796
#if LINUX_VERSION_CODE >= KERNEL_VERSION(4,7,0) || (defined RHEL_RELEASE_CODE && RHEL_RELEASE_CODE>=1796)
netif_trans_update(dev);
#else
dev->trans_start = jiffies;
@@ -306,7 +306,7 @@ void nas_tx_timeout(struct net_device *dev)
printk("TX_TIMEOUT: begin\n");
// (struct nas_priv *)(dev->priv)->stats.tx_errors++;
(priv->stats).tx_errors++;
#if LINUX_VERSION_CODE >= KERNEL_VERSION(4,7,0) || RHEL_RELEASE_CODE>=1796
#if LINUX_VERSION_CODE >= KERNEL_VERSION(4,7,0) || (defined RHEL_RELEASE_CODE && RHEL_RELEASE_CODE>=1796)
netif_trans_update(dev);
#else
dev->trans_start = jiffies;
@@ -324,7 +324,7 @@ static const struct net_device_ops nasmesh_netdev_ops = {
.ndo_set_mac_address = NULL,
.ndo_set_config = nas_set_config,
.ndo_do_ioctl = nas_CTL_ioctl,
#if RHEL_RELEASE_CODE>=1797
#if (defined RHEL_RELEASE_CODE && RHEL_RELEASE_CODE>=1797)
.extended.ndo_change_mtu = nas_change_mtu,
#else
.ndo_change_mtu = nas_change_mtu,
+14 -2
View File
@@ -30,7 +30,7 @@
***************************************************************************/
#include <linux/version.h>
#include "local.h"
#include "proto_extern.h"
@@ -155,10 +155,18 @@ void nas_mesh_start_default_sclassifier(struct cx_entity *cx,struct rb_entity *r
}
//---------------------------------------------------------------------------
#if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 15, 0))
void nas_mesh_timer(struct timer_list *t)
#else
void nas_mesh_timer(unsigned long data)
#endif
{
//---------------------------------------------------------------------------
#if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 15, 0))
struct nas_priv *gpriv=from_timer(gpriv, t, timer);
#else
struct nas_priv *gpriv=(struct nas_priv *) data;
#endif
uint8_t cxi;
struct cx_entity *cx;
struct rb_entity *rb;
@@ -166,10 +174,14 @@ void nas_mesh_timer(unsigned long data)
#ifdef NAS_DEBUG_TIMER
printk("NAS_MESH_TIMER - begin \n");
#endif
#if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 15, 0))
timer_setup(&gpriv->timer, nas_mesh_timer, 0);
mod_timer(&gpriv->timer, jiffies+NAS_TIMER_TICK);
#else
(gpriv->timer).function=nas_mesh_timer;
(gpriv->timer).expires=jiffies+NAS_TIMER_TICK;
(gpriv->timer).data=data;
#endif
return;
@@ -195,7 +195,6 @@ void nas_mesh_init(int inst //!< Instance ID
);
void nas_mesh_timer(unsigned long data);
int nas_mesh_DC_receive(struct cx_entity *cx,struct nas_priv *gpriv);
int nas_mesh_GC_receive(struct nas_priv *gpriv);
+2 -2
View File
@@ -679,11 +679,11 @@ void print_TOOL_pk_all(struct sk_buff *skb)
switch (ntohs(skb->protocol)) {
case ETH_P_IPV6:
print_TOOL_pk_ipv6((struct ipv6hdr *)skb->network_header);
print_TOOL_pk_ipv6((struct ipv6hdr *)skb_network_header(skb));
break;
case ETH_P_IP:
print_TOOL_pk_ipv4((struct iphdr *)skb->network_header);
print_TOOL_pk_ipv4((struct iphdr *)skb_network_header(skb));
break;
}
}
+1 -1
View File
@@ -222,7 +222,7 @@ skb_p->mark = rb_idP;
printk("\n");
#endif //OAI_DRV_DEBUG_RECEIVE
netif_rx(skb_p);
netif_rx_ni(skb_p);
#ifdef OAI_DRV_DEBUG_RECEIVE
printk("[UE_IP_DRV][%s] end\n",__FUNCTION__);
#endif
+26 -33
View File
@@ -43,9 +43,6 @@
#include "flexran_agent_extern.h"
//#define RRC_DATA_REQ_DEBUG
//#define DEBUG_RRC 1
extern RAN_CONTEXT_t RC;
@@ -68,10 +65,9 @@ mac_rrc_data_req(
uint8_t sfn = (uint8_t)((frameP>>2)&0xff);
#ifdef DEBUG_RRC
int i;
LOG_I(RRC,"[eNB %d] mac_rrc_data_req to SRB ID=%d\n",Mod_idP,Srb_id);
#endif
if (LOG_DEBUGFLAG(DEBUG_RRC)) {
LOG_D(RRC,"[eNB %d] mac_rrc_data_req to SRB ID=%d\n",Mod_idP,Srb_id);
}
eNB_RRC_INST *rrc;
rrc_eNB_carrier_data_t *carrier;
@@ -96,15 +92,15 @@ mac_rrc_data_req(
RC.rrc[Mod_idP]->carrier[CC_id].SIB1,
RC.rrc[Mod_idP]->carrier[CC_id].sizeof_SIB1);
#ifdef DEBUG_RRC
LOG_T(RRC,"[eNB %d] Frame %d : BCCH request => SIB 1\n",Mod_idP,frameP);
if (LOG_DEBUGFLAG(DEBUG_RRC)) {
LOG_T(RRC,"[eNB %d] Frame %d : BCCH request => SIB 1\n",Mod_idP,frameP);
for (i=0; i<RC.rrc[Mod_idP]->carrier[CC_id].sizeof_SIB1; i++) {
LOG_T(RRC,"%x.",buffer_pP[i]);
}
for (int i=0; i<RC.rrc[Mod_idP]->carrier[CC_id].sizeof_SIB1; i++) {
LOG_T(RRC,"%x.",buffer_pP[i]);
}
LOG_T(RRC,"\n");
#endif
LOG_T(RRC,"\n");
} /* LOG_DEBUGFLAG(DEBUG_RRC) */
return (RC.rrc[Mod_idP]->carrier[CC_id].sizeof_SIB1);
} // All RFN mod 8 transmit SIB2-3 in SF 5
@@ -113,15 +109,15 @@ mac_rrc_data_req(
RC.rrc[Mod_idP]->carrier[CC_id].SIB23,
RC.rrc[Mod_idP]->carrier[CC_id].sizeof_SIB23);
#ifdef DEBUG_RRC
LOG_T(RRC,"[eNB %d] Frame %d BCCH request => SIB 2-3\n",Mod_idP,frameP);
if (LOG_DEBUGFLAG(DEBUG_RRC)) {
LOG_T(RRC,"[eNB %d] Frame %d BCCH request => SIB 2-3\n",Mod_idP,frameP);
for (i=0; i<RC.rrc[Mod_idP]->carrier[CC_id].sizeof_SIB23; i++) {
LOG_T(RRC,"%x.",buffer_pP[i]);
}
for (int i=0; i<RC.rrc[Mod_idP]->carrier[CC_id].sizeof_SIB23; i++) {
LOG_T(RRC,"%x.",buffer_pP[i]);
}
LOG_T(RRC,"\n");
#endif
LOG_T(RRC,"\n");
} /* LOG_DEBUGFLAG(DEBUG_RRC) */
return(RC.rrc[Mod_idP]->carrier[CC_id].sizeof_SIB23);
} else {
return(0);
@@ -193,20 +189,17 @@ mac_rrc_data_req(
RC.rrc[Mod_idP]->carrier[CC_id].MCCH_MESSAGE[mbsfn_sync_area],
RC.rrc[Mod_idP]->carrier[CC_id].sizeof_MCCH_MESSAGE[mbsfn_sync_area]);
#ifdef DEBUG_RRC
LOG_D(RRC,"[eNB %d] Frame %d : MCCH request => MCCH_MESSAGE \n",Mod_idP,frameP);
if (LOG_DEBUGFLAG(DEBUG_RRC)) {
LOG_D(RRC,"[eNB %d] Frame %d : MCCH request => MCCH_MESSAGE \n",Mod_idP,frameP);
for (i=0; i<RC.rrc[Mod_idP]->carrier[CC_id].sizeof_MCCH_MESSAGE[mbsfn_sync_area]; i++) {
LOG_T(RRC,"%x.",buffer_pP[i]);
}
for (int i=0; i<RC.rrc[Mod_idP]->carrier[CC_id].sizeof_MCCH_MESSAGE[mbsfn_sync_area]; i++) {
LOG_T(RRC,"%x.",buffer_pP[i]);
}
LOG_T(RRC,"\n");
#endif
LOG_T(RRC,"\n");
} /* LOG_DEBUGFLAG(DEBUG_RRC) */
return (RC.rrc[Mod_idP]->carrier[CC_id].sizeof_MCCH_MESSAGE[mbsfn_sync_area]);
// }
//else
//return(0);
return (RC.rrc[Mod_idP]->carrier[CC_id].sizeof_MCCH_MESSAGE[mbsfn_sync_area]);
}
#endif // #if (RRC_VERSION >= MAKE_VERSION(10, 0, 0))
@@ -329,7 +322,7 @@ void mac_eNB_rrc_ul_failure(const module_id_t Mod_instP,
rntiP,
PROTOCOL__FLEX_UE_STATE_CHANGE_TYPE__FLUESC_DEACTIVATED);
}
// rrc_mac_remove_ue(Mod_instP,rntiP);
rrc_mac_remove_ue(Mod_instP,rntiP);
}
void mac_eNB_rrc_uplane_failure(const module_id_t Mod_instP,
+1 -5
View File
@@ -42,7 +42,6 @@
#endif
//#define RRC_DATA_REQ_DEBUG
//#define DEBUG_RRC 1
@@ -61,10 +60,7 @@ mac_rrc_data_req_ue(
//--------------------------------------------------------------------------
{
#ifdef DEBUG_RRC
int i;
LOG_I(RRC,"[eNB %d] mac_rrc_data_req to SRB ID=%d\n",Mod_idP,Srb_id);
#endif
LOG_D(RRC,"[eNB %d] mac_rrc_data_req to SRB ID=%d\n",Mod_idP,Srb_id);
#if (RRC_VERSION >= MAKE_VERSION(14, 0, 0))
+89 -85
View File
@@ -91,7 +91,6 @@
#define msg printf
#endif
//#define XER_PRINT
typedef struct xer_sprint_string_s {
char *string;
@@ -346,8 +345,13 @@ uint8_t do_SIB1(rrc_eNB_carrier_data_t *carrier,
{
// SystemInformation_t systemInformation;
PLMN_IdentityInfo_t PLMN_identity_info;
MCC_MNC_Digit_t dummy_mcc[3],dummy_mnc[3];
#if defined(ENABLE_ITTI)
int num_plmn = configuration->num_plmn;
#else
int num_plmn = 1;
#endif
PLMN_IdentityInfo_t PLMN_identity_info[num_plmn];
MCC_MNC_Digit_t dummy_mcc[num_plmn][3], dummy_mnc[num_plmn][3];
asn_enc_rval_t enc_rval;
SchedulingInfo_t schedulingInfo;
SIB_Type_t sib_type;
@@ -355,6 +359,7 @@ uint8_t do_SIB1(rrc_eNB_carrier_data_t *carrier,
uint8_t *buffer = carrier->SIB1;
BCCH_DL_SCH_Message_t *bcch_message = &carrier->siblock1;
SystemInformationBlockType1_t **sib1 = &carrier->sib1;
int i;
memset(bcch_message,0,sizeof(BCCH_DL_SCH_Message_t));
@@ -364,67 +369,68 @@ uint8_t do_SIB1(rrc_eNB_carrier_data_t *carrier,
*sib1 = &bcch_message->message.choice.c1.choice.systemInformationBlockType1;
memset(&PLMN_identity_info,0,sizeof(PLMN_IdentityInfo_t));
memset(PLMN_identity_info,0,num_plmn * sizeof(PLMN_IdentityInfo_t));
memset(&schedulingInfo,0,sizeof(SchedulingInfo_t));
memset(&sib_type,0,sizeof(SIB_Type_t));
/* as per TS 36.311, up to 6 PLMN_identity_info are allowed in list -> add one by one */
for (i = 0; i < configuration->num_plmn; ++i) {
PLMN_identity_info[i].plmn_Identity.mcc = CALLOC(1,sizeof(*PLMN_identity_info[i].plmn_Identity.mcc));
memset(PLMN_identity_info[i].plmn_Identity.mcc,0,sizeof(*PLMN_identity_info[i].plmn_Identity.mcc));
PLMN_identity_info.plmn_Identity.mcc = CALLOC(1,sizeof(*PLMN_identity_info.plmn_Identity.mcc));
memset(PLMN_identity_info.plmn_Identity.mcc,0,sizeof(*PLMN_identity_info.plmn_Identity.mcc));
asn_set_empty(&PLMN_identity_info.plmn_Identity.mcc->list);//.size=0;
asn_set_empty(&PLMN_identity_info[i].plmn_Identity.mcc->list);//.size=0;
#if defined(ENABLE_ITTI)
dummy_mcc[0] = (configuration->mcc / 100) % 10;
dummy_mcc[1] = (configuration->mcc / 10) % 10;
dummy_mcc[2] = (configuration->mcc / 1) % 10;
dummy_mcc[i][0] = (configuration->mcc[i] / 100) % 10;
dummy_mcc[i][1] = (configuration->mcc[i] / 10) % 10;
dummy_mcc[i][2] = (configuration->mcc[i] / 1) % 10;
#else
dummy_mcc[0] = 0;
dummy_mcc[1] = 0;
dummy_mcc[2] = 1;
dummy_mcc[i][0] = 0;
dummy_mcc[i][1] = 0;
dummy_mcc[i][2] = 1;
#endif
ASN_SEQUENCE_ADD(&PLMN_identity_info.plmn_Identity.mcc->list,&dummy_mcc[0]);
ASN_SEQUENCE_ADD(&PLMN_identity_info.plmn_Identity.mcc->list,&dummy_mcc[1]);
ASN_SEQUENCE_ADD(&PLMN_identity_info.plmn_Identity.mcc->list,&dummy_mcc[2]);
ASN_SEQUENCE_ADD(&PLMN_identity_info[i].plmn_Identity.mcc->list,&dummy_mcc[i][0]);
ASN_SEQUENCE_ADD(&PLMN_identity_info[i].plmn_Identity.mcc->list,&dummy_mcc[i][1]);
ASN_SEQUENCE_ADD(&PLMN_identity_info[i].plmn_Identity.mcc->list,&dummy_mcc[i][2]);
PLMN_identity_info.plmn_Identity.mnc.list.size=0;
PLMN_identity_info.plmn_Identity.mnc.list.count=0;
PLMN_identity_info[i].plmn_Identity.mnc.list.size=0;
PLMN_identity_info[i].plmn_Identity.mnc.list.count=0;
#if defined(ENABLE_ITTI)
if (configuration->mnc >= 100) {
dummy_mnc[0] = (configuration->mnc / 100) % 10;
dummy_mnc[1] = (configuration->mnc / 10) % 10;
dummy_mnc[2] = (configuration->mnc / 1) % 10;
} else {
if (configuration->mnc_digit_length == 2) {
dummy_mnc[0] = (configuration->mnc / 10) % 10;
dummy_mnc[1] = (configuration->mnc / 1) % 10;
dummy_mnc[2] = 0xf;
if (configuration->mnc[i] >= 100) {
dummy_mnc[i][0] = (configuration->mnc[i] / 100) % 10;
dummy_mnc[i][1] = (configuration->mnc[i] / 10) % 10;
dummy_mnc[i][2] = (configuration->mnc[i] / 1) % 10;
} else {
dummy_mnc[0] = (configuration->mnc / 100) % 100;
dummy_mnc[1] = (configuration->mnc / 10) % 10;
dummy_mnc[2] = (configuration->mnc / 1) % 10;
if (configuration->mnc_digit_length[i] == 2) {
dummy_mnc[i][0] = (configuration->mnc[i] / 10) % 10;
dummy_mnc[i][1] = (configuration->mnc[i] / 1) % 10;
dummy_mnc[i][2] = 0xf;
} else {
dummy_mnc[i][0] = (configuration->mnc[i] / 100) % 100;
dummy_mnc[i][1] = (configuration->mnc[i] / 10) % 10;
dummy_mnc[i][2] = (configuration->mnc[i] / 1) % 10;
}
}
}
#else
dummy_mnc[0] = 0;
dummy_mnc[1] = 1;
dummy_mnc[2] = 0xf;
dummy_mnc[i][0] = 0;
dummy_mnc[i][1] = 1;
dummy_mnc[i][2] = 0xf;
#endif
ASN_SEQUENCE_ADD(&PLMN_identity_info.plmn_Identity.mnc.list,&dummy_mnc[0]);
ASN_SEQUENCE_ADD(&PLMN_identity_info.plmn_Identity.mnc.list,&dummy_mnc[1]);
ASN_SEQUENCE_ADD(&PLMN_identity_info[i].plmn_Identity.mnc.list,&dummy_mnc[i][0]);
ASN_SEQUENCE_ADD(&PLMN_identity_info[i].plmn_Identity.mnc.list,&dummy_mnc[i][1]);
if (dummy_mnc[2] != 0xf) {
ASN_SEQUENCE_ADD(&PLMN_identity_info.plmn_Identity.mnc.list,&dummy_mnc[2]);
if (dummy_mnc[i][2] != 0xf) {
ASN_SEQUENCE_ADD(&PLMN_identity_info[i].plmn_Identity.mnc.list,&dummy_mnc[i][2]);
}
//assign_enum(&PLMN_identity_info.cellReservedForOperatorUse,PLMN_IdentityInfo__cellReservedForOperatorUse_notReserved);
PLMN_identity_info[i].cellReservedForOperatorUse=PLMN_IdentityInfo__cellReservedForOperatorUse_notReserved;
ASN_SEQUENCE_ADD(&(*sib1)->cellAccessRelatedInfo.plmn_IdentityList.list,&PLMN_identity_info[i]);
}
//assign_enum(&PLMN_identity_info.cellReservedForOperatorUse,PLMN_IdentityInfo__cellReservedForOperatorUse_notReserved);
PLMN_identity_info.cellReservedForOperatorUse=PLMN_IdentityInfo__cellReservedForOperatorUse_notReserved;
ASN_SEQUENCE_ADD(&(*sib1)->cellAccessRelatedInfo.plmn_IdentityList.list,&PLMN_identity_info);
// 16 bits
(*sib1)->cellAccessRelatedInfo.trackingAreaCode.buf = MALLOC(2);
@@ -1356,9 +1362,9 @@ uint8_t do_SIB23(uint8_t Mod_id,
}
#endif
#ifdef XER_PRINT
xer_fprint(stdout, &asn_DEF_BCCH_DL_SCH_Message, (void*)bcch_message);
#endif
if ( LOG_DEBUGFLAG(DEBUG_ASN1) ) {
xer_fprint(stdout, &asn_DEF_BCCH_DL_SCH_Message, (void*)bcch_message);
}
enc_rval = uper_encode_to_buffer(&asn_DEF_BCCH_DL_SCH_Message,
NULL,
(void*)bcch_message,
@@ -1610,9 +1616,9 @@ uint8_t do_SidelinkUEInformation(uint8_t Mod_id, uint8_t *buffer, SL_Destinatio
break;
}
#ifdef XER_PRINT
xer_fprint(stdout, &asn_DEF_UL_DCCH_Message, (void*)&ul_dcch_msg);
#endif
if ( LOG_DEBUGFLAG(DEBUG_ASN1) ) {
xer_fprint(stdout, &asn_DEF_UL_DCCH_Message, (void*)&ul_dcch_msg);
}
enc_rval = uper_encode_to_buffer(&asn_DEF_UL_DCCH_Message,
@@ -1674,10 +1680,7 @@ uint8_t do_RRCConnectionSetupComplete(uint8_t Mod_id, uint8_t *buffer, const uin
rrcConnectionSetupComplete->criticalExtensions.choice.c1.choice.rrcConnectionSetupComplete_r8.nonCriticalExtension=CALLOC(1,
sizeof(*rrcConnectionSetupComplete->criticalExtensions.choice.c1.choice.rrcConnectionSetupComplete_r8.nonCriticalExtension));
if(usim_test == 0)
rrcConnectionSetupComplete->criticalExtensions.choice.c1.choice.rrcConnectionSetupComplete_r8.selectedPLMN_Identity= 2;
else
rrcConnectionSetupComplete->criticalExtensions.choice.c1.choice.rrcConnectionSetupComplete_r8.selectedPLMN_Identity= 1;
rrcConnectionSetupComplete->criticalExtensions.choice.c1.choice.rrcConnectionSetupComplete_r8.selectedPLMN_Identity= 1;
rrcConnectionSetupComplete->criticalExtensions.choice.c1.choice.rrcConnectionSetupComplete_r8.registeredMME =
NULL;//calloc(1,sizeof(*rrcConnectionSetupComplete->criticalExtensions.choice.c1.choice.rrcConnectionSetupComplete_r8.registeredMME));
@@ -2168,9 +2171,9 @@ do_RRCConnectionSetup(
#endif
#ifdef XER_PRINT
xer_fprint(stdout, &asn_DEF_DL_CCCH_Message, (void*)&dl_ccch_msg);
#endif
if ( LOG_DEBUGFLAG(DEBUG_ASN1) ) {
xer_fprint(stdout, &asn_DEF_DL_CCCH_Message, (void*)&dl_ccch_msg);
}
enc_rval = uper_encode_to_buffer(&asn_DEF_DL_CCCH_Message,
NULL,
(void*)&dl_ccch_msg,
@@ -2243,9 +2246,9 @@ do_SecurityModeCommand(
dl_dcch_msg.message.choice.c1.choice.securityModeCommand.criticalExtensions.choice.c1.choice.securityModeCommand_r8.securityConfigSMC.securityAlgorithmConfig.integrityProtAlgorithm
= (e_SecurityAlgorithmConfig__integrityProtAlgorithm)integrityProtAlgorithm;
#ifdef XER_PRINT
xer_fprint(stdout, &asn_DEF_DL_DCCH_Message, (void*)&dl_dcch_msg);
#endif
if ( LOG_DEBUGFLAG(DEBUG_ASN1) ) {
xer_fprint(stdout, &asn_DEF_DL_DCCH_Message, (void*)&dl_dcch_msg);
}
enc_rval = uper_encode_to_buffer(&asn_DEF_DL_DCCH_Message,
NULL,
(void*)&dl_dcch_msg,
@@ -2323,9 +2326,9 @@ do_UECapabilityEnquiry(
ASN_SEQUENCE_ADD(&dl_dcch_msg.message.choice.c1.choice.ueCapabilityEnquiry.criticalExtensions.choice.c1.choice.ueCapabilityEnquiry_r8.ue_CapabilityRequest.list,
&rat);
#ifdef XER_PRINT
xer_fprint(stdout, &asn_DEF_DL_DCCH_Message, (void*)&dl_dcch_msg);
#endif
if ( LOG_DEBUGFLAG(DEBUG_ASN1) ) {
xer_fprint(stdout, &asn_DEF_DL_DCCH_Message, (void*)&dl_dcch_msg);
}
enc_rval = uper_encode_to_buffer(&asn_DEF_DL_DCCH_Message,
NULL,
(void*)&dl_dcch_msg,
@@ -2542,9 +2545,9 @@ do_RRCConnectionReconfiguration(
enc_rval.failed_type->name, enc_rval.encoded);
return -1;
}
#ifdef XER_PRINT
xer_fprint(stdout,&asn_DEF_DL_DCCH_Message,(void*)&dl_dcch_msg);
#endif
if ( LOG_DEBUGFLAG(DEBUG_ASN1) ) {
xer_fprint(stdout,&asn_DEF_DL_DCCH_Message,(void*)&dl_dcch_msg);
}
#if defined(ENABLE_ITTI)
# if !defined(DISABLE_XER_SPRINT)
@@ -2745,9 +2748,9 @@ do_RRCConnectionReestablishment(
rrcConnectionReestablishment->criticalExtensions.choice.c1.choice.rrcConnectionReestablishment_r8.nonCriticalExtension = NULL;
#ifdef XER_PRINT
xer_fprint(stdout, &asn_DEF_DL_CCCH_Message, (void*)&dl_ccch_msg);
#endif
if ( LOG_DEBUGFLAG(DEBUG_ASN1) ) {
xer_fprint(stdout, &asn_DEF_DL_CCCH_Message, (void*)&dl_ccch_msg);
}
enc_rval = uper_encode_to_buffer(&asn_DEF_DL_CCCH_Message,
NULL,
(void*)&dl_ccch_msg,
@@ -2807,9 +2810,9 @@ do_RRCConnectionReestablishmentReject(
// RRCConnectionReestablishmentReject
rrcConnectionReestablishmentReject->criticalExtensions.present = RRCConnectionReestablishmentReject__criticalExtensions_PR_rrcConnectionReestablishmentReject_r8;
#ifdef XER_PRINT
xer_fprint(stdout, &asn_DEF_DL_CCCH_Message, (void*)&dl_ccch_msg);
#endif
if ( LOG_DEBUGFLAG(DEBUG_ASN1) ) {
xer_fprint(stdout, &asn_DEF_DL_CCCH_Message, (void*)&dl_ccch_msg);
}
enc_rval = uper_encode_to_buffer(&asn_DEF_DL_CCCH_Message,
NULL,
(void*)&dl_ccch_msg,
@@ -2870,9 +2873,9 @@ do_RRCConnectionReject(
/* let's put a wait time of 1s for the moment */
rrcConnectionReject->criticalExtensions.choice.c1.choice.rrcConnectionReject_r8.waitTime = 1;
#ifdef XER_PRINT
xer_fprint(stdout, &asn_DEF_DL_CCCH_Message, (void*)&dl_ccch_msg);
#endif
if ( LOG_DEBUGFLAG(DEBUG_ASN1) ) {
xer_fprint(stdout, &asn_DEF_DL_CCCH_Message, (void*)&dl_ccch_msg);
}
enc_rval = uper_encode_to_buffer(&asn_DEF_DL_CCCH_Message,
NULL,
(void*)&dl_ccch_msg,
@@ -3064,9 +3067,9 @@ uint8_t do_MBSFNAreaConfig(uint8_t Mod_id,
*/
ASN_SEQUENCE_ADD(&(*mbsfnAreaConfiguration)->pmch_InfoList_r9.list,pmch_Info_1);
#ifdef XER_PRINT
xer_fprint(stdout,&asn_DEF_MCCH_Message,(void*)mcch_message);
#endif
if ( LOG_DEBUGFLAG(DEBUG_ASN1) ) {
xer_fprint(stdout,&asn_DEF_MCCH_Message,(void*)mcch_message);
}
enc_rval = uper_encode_to_buffer(&asn_DEF_MCCH_Message,
NULL,
(void*)mcch_message,
@@ -3317,6 +3320,7 @@ uint8_t do_Paging(uint8_t Mod_id, uint8_t *buffer, ue_paging_identity_t ue_pagin
&paging_record_p->ue_Identity.choice.s_TMSI.m_TMSI);
paging_record_p->ue_Identity.choice.s_TMSI.m_TMSI.bits_unused = 0;
} else if (ue_paging_identity.presenceMask == UE_PAGING_IDENTITY_imsi) {
paging_record_p->ue_Identity.present = PagingUE_Identity_PR_imsi;
IMSI_Digit_t imsi_digit[21];
for (j = 0; j< ue_paging_identity.choice.imsi.length; j++) { /* IMSI size */
imsi_digit[j] = (IMSI_Digit_t)ue_paging_identity.choice.imsi.buffer[j];
@@ -3342,9 +3346,9 @@ uint8_t do_Paging(uint8_t Mod_id, uint8_t *buffer, ue_paging_identity_t ue_pagin
enc_rval.failed_type->name, enc_rval.encoded);
return -1;
}
#ifdef XER_PRINT
xer_fprint(stdout, &asn_DEF_PCCH_Message, (void*)&pcch_msg);
#endif
if ( LOG_DEBUGFLAG(DEBUG_ASN1) ) {
xer_fprint(stdout, &asn_DEF_PCCH_Message, (void*)&pcch_msg);
}
return((enc_rval.encoded+7)/8);
}
@@ -3507,9 +3511,9 @@ OAI_UECapability_t *fill_ue_capability(char *UE_EUTRA_Capability_xer_fname)
}
UECapability.UE_EUTRA_Capability = UE_EUTRA_Capability;
#ifdef XER_PRINT
xer_fprint(stdout,&asn_DEF_UE_EUTRA_Capability,(void *)UE_EUTRA_Capability);
#endif
if ( LOG_DEBUGFLAG(DEBUG_ASN1) ) {
xer_fprint(stdout,&asn_DEF_UE_EUTRA_Capability,(void *)UE_EUTRA_Capability);
}
enc_rval = uper_encode_to_buffer(&asn_DEF_UE_EUTRA_Capability,
NULL,
(void*)UE_EUTRA_Capability,
+36 -36
View File
@@ -136,7 +136,7 @@ uint8_t do_MIB_NB_IoT(
carrier->MIB_NB_IoT,
100);
if(enc_rval.encoded <= 0) {
LOG_F(RRC, "ASN1 message encoding failed (%s, %lu)!\n",
LOG_E(RRC, "ASN1 message encoding failed (%s, %lu)!\n",
enc_rval.failed_type->name, enc_rval.encoded);
}
@@ -382,9 +382,9 @@ uint8_t do_SIB1_NB_IoT(uint8_t Mod_id, int CC_id,
ASN_SEQUENCE_ADD(&(*sib1_NB_IoT)->systemInfoValueTagList_r13->list,&systemInfoValueTagSI);
#ifdef XER_PRINT //generate xml files
xer_fprint(stdout, &asn_DEF_BCCH_DL_SCH_Message_NB, (void*)bcch_message);
#endif
if ( LOG_DEBUGFLAG(DEBUG_ASN1) ) {
xer_fprint(stdout, &asn_DEF_BCCH_DL_SCH_Message_NB, (void*)bcch_message);
}
enc_rval = uper_encode_to_buffer(&asn_DEF_BCCH_DL_SCH_Message_NB,
@@ -394,7 +394,7 @@ uint8_t do_SIB1_NB_IoT(uint8_t Mod_id, int CC_id,
100);
if (enc_rval.encoded > 0){
LOG_F(RRC,"ASN1 message encoding failed (%s, %lu)!\n",
LOG_E(RRC,"ASN1 message encoding failed (%s, %lu)!\n",
enc_rval.failed_type->name, enc_rval.encoded);
}
@@ -667,9 +667,9 @@ uint8_t do_SIB23_NB_IoT(uint8_t Mod_id,
ASN_SEQUENCE_ADD(&bcch_message->message.choice.c1.choice.systemInformation_r13.criticalExtensions.choice.systemInformation_r13.sib_TypeAndInfo_r13.list,
sib3_NB_part);
#ifdef XER_PRINT
xer_fprint(stdout, &asn_DEF_BCCH_DL_SCH_Message_NB, (void*)bcch_message);
#endif
if ( LOG_DEBUGFLAG(DEBUG_ASN1) ) {
xer_fprint(stdout, &asn_DEF_BCCH_DL_SCH_Message_NB, (void*)bcch_message);
}
enc_rval = uper_encode_to_buffer(&asn_DEF_BCCH_DL_SCH_Message_NB,
NULL,
(void*)bcch_message,
@@ -887,9 +887,9 @@ uint8_t do_RRCConnectionSetup_NB_IoT(
rrcConnectionSetup_NB_IoT->criticalExtensions.choice.c1.choice.rrcConnectionSetup_r13.radioResourceConfigDedicated_r13.physicalConfigDedicated_r13 = physicalConfigDedicated2_NB_IoT;
rrcConnectionSetup_NB_IoT->criticalExtensions.choice.c1.choice.rrcConnectionSetup_r13.radioResourceConfigDedicated_r13.mac_MainConfig_r13 = NULL;
#ifdef XER_PRINT
xer_fprint(stdout, &asn_DEF_DL_CCCH_Message, (void*)&dl_ccch_msg);
#endif
if ( LOG_DEBUGFLAG(DEBUG_ASN1) ) {
xer_fprint(stdout, &asn_DEF_DL_CCCH_Message_NB, (void*)&dl_ccch_msg_NB_IoT);
}
enc_rval = uper_encode_to_buffer(&asn_DEF_DL_CCCH_Message_NB,
NULL,
(void*)&dl_ccch_msg_NB_IoT,
@@ -897,7 +897,7 @@ uint8_t do_RRCConnectionSetup_NB_IoT(
100);
if (enc_rval.encoded <= 0) {
LOG_F(RRC, "ASN1 message encoding failed (%s, %lu)!\n",
LOG_E(RRC, "ASN1 message encoding failed (%s, %lu)!\n",
enc_rval.failed_type->name, enc_rval.encoded);
}
@@ -939,16 +939,16 @@ uint8_t do_SecurityModeCommand_NB_IoT(
= (e_SecurityAlgorithmConfig__integrityProtAlgorithm)integrityProtAlgorithm;
//only changed "asn_DEF_DL_DCCH_Message_NB"
#ifdef XER_PRINT
xer_fprint(stdout, &asn_DEF_DL_DCCH_Message_NB, (void*)&dl_dcch_msg_NB_IoT);
#endif
if ( LOG_DEBUGFLAG(DEBUG_ASN1) ) {
xer_fprint(stdout, &asn_DEF_DL_DCCH_Message_NB, (void*)&dl_dcch_msg_NB_IoT);
}
enc_rval = uper_encode_to_buffer(&asn_DEF_DL_DCCH_Message_NB,
NULL,
(void*)&dl_dcch_msg_NB_IoT,
buffer,
100);
if (enc_rval.encoded <= 0) {
LOG_F(RRC, "ASN1 message encoding failed (%s, %lu)!\n",
LOG_E(RRC, "ASN1 message encoding failed (%s, %lu)!\n",
enc_rval.failed_type->name, enc_rval.encoded);
}
@@ -1001,16 +1001,16 @@ uint8_t do_UECapabilityEnquiry_NB_IoT(
//no ue_CapabilityRequest (list of RAT_Type)
//only changed "asn_DEF_DL_DCCH_Message_NB"
#ifdef XER_PRINT
xer_fprint(stdout, &asn_DEF_DL_DCCH_Message_NB, (void*)&dl_dcch_msg_NB_IoT);
#endif
if ( LOG_DEBUGFLAG(DEBUG_ASN1) ) {
xer_fprint(stdout, &asn_DEF_DL_DCCH_Message_NB, (void*)&dl_dcch_msg_NB_IoT);
}
enc_rval = uper_encode_to_buffer(&asn_DEF_DL_DCCH_Message_NB,
NULL,
(void*)&dl_dcch_msg_NB_IoT,
buffer,
100);
if (enc_rval.encoded <= 0) {
LOG_F(RRC, "ASN1 message encoding failed (%s, %lu)!\n",
LOG_E(RRC, "ASN1 message encoding failed (%s, %lu)!\n",
enc_rval.failed_type->name, enc_rval.encoded);
}
@@ -1105,14 +1105,14 @@ uint16_t do_RRCConnectionReconfiguration_NB_IoT(
buffer,
RRC_BUF_SIZE);
if (enc_rval.encoded <= 0) {
LOG_F(RRC, "ASN1 message encoding failed %s, %li\n",
LOG_E(RRC, "ASN1 message encoding failed %s, %li\n",
enc_rval.failed_type->name, enc_rval.encoded);
}
//changed only asn_DEF_DL_DCCH_Message_NB
#ifdef XER_PRINT
xer_fprint(stdout,&asn_DEF_DL_DCCH_Message_NB,(void*)&dl_dcch_msg_NB_IoT);
#endif
if ( LOG_DEBUGFLAG(DEBUG_ASN1) ) {
xer_fprint(stdout,&asn_DEF_DL_DCCH_Message_NB,(void*)&dl_dcch_msg_NB_IoT);
}
//#if defined(ENABLE_ITTI)
//# if !defined(DISABLE_XER_SPRINT)...
@@ -1143,16 +1143,16 @@ uint8_t do_RRCConnectionReestablishmentReject_NB_IoT(
rrcConnectionReestablishmentReject->criticalExtensions.present = RRCConnectionReestablishmentReject__criticalExtensions_PR_rrcConnectionReestablishmentReject_r8;
//Only change in "asn_DEF_DL_CCCH_Message_NB"
#ifdef XER_PRINT
xer_fprint(stdout, &asn_DEF_DL_CCCH_Message_NB, (void*)&dl_ccch_msg_NB_IoT);
#endif
if ( LOG_DEBUGFLAG(DEBUG_ASN1) ) {
xer_fprint(stdout, &asn_DEF_DL_CCCH_Message_NB, (void*)&dl_ccch_msg_NB_IoT);
}
enc_rval = uper_encode_to_buffer(&asn_DEF_DL_CCCH_Message_NB,
NULL,
(void*)&dl_ccch_msg_NB_IoT,
buffer,
100);
if (enc_rval.encoded <= 0) {
LOG_F(RRC,"ASN1 message encoding failed (%s, %lu)!\n",
LOG_E(RRC,"ASN1 message encoding failed (%s, %lu)!\n",
enc_rval.failed_type->name, enc_rval.encoded);
}
@@ -1214,16 +1214,16 @@ uint8_t do_RRCConnectionReject_NB_IoT(
RRCConnectionReject_NB_r13_IEs__rrc_SuspendIndication_r13_true;
//Only Modified "asn_DEF_DL_CCCH_Message_NB"
#ifdef XER_PRINT
xer_fprint(stdout, &asn_DEF_DL_CCCH_Message_NB, (void*)&dl_ccch_msg);
#endif
if ( LOG_DEBUGFLAG(DEBUG_ASN1) ) {
xer_fprint(stdout, &asn_DEF_DL_CCCH_Message_NB, (void*)&dl_ccch_msg_NB_IoT);
}
enc_rval = uper_encode_to_buffer(&asn_DEF_DL_CCCH_Message_NB,
NULL,
(void*)&dl_ccch_msg_NB_IoT,
buffer,
100);
if (enc_rval.encoded <= 0) {
LOG_F(RRC, "ASN1 message encoding failed (%s, %ld)!\n",
LOG_E(RRC, "ASN1 message encoding failed (%s, %ld)!\n",
enc_rval.failed_type->name, enc_rval.encoded);
}
@@ -1351,13 +1351,13 @@ uint8_t do_RRCConnectionReestablishment_NB_IoT(
RRC_BUF_SIZE);
if (enc_rval.encoded <= 0) {
LOG_F(RRC, "ASN1 message encoding failed (%s, %li)!\n",
LOG_E(RRC, "ASN1 message encoding failed (%s, %li)!\n",
enc_rval.failed_type->name, enc_rval.encoded);
}
#ifdef XER_PRINT
xer_fprint(stdout,&asn_DEF_DL_CCCH_Message_NB,(void*)&dl_ccch_msg_NB_IoT);
#endif
if ( LOG_DEBUGFLAG(DEBUG_ASN1) ) {
xer_fprint(stdout,&asn_DEF_DL_CCCH_Message_NB,(void*)&dl_ccch_msg_NB_IoT);
}
#if defined(ENABLE_ITTI)
# if !defined(DISABLE_XER_SPRINT)
+83 -67
View File
@@ -99,10 +99,6 @@ int send_ue_information = 0;
// for malloc_clear
#include "PHY/defs_UE.h"
//#define XER_PRINT
extern void pdcp_config_set_security(
const protocol_ctxt_t* const ctxt_pP,
pdcp_t * const pdcp_pP,
@@ -733,9 +729,9 @@ int rrc_ue_decode_ccch( const protocol_ctxt_t* const ctxt_pP, const SRB_INFO* co
(uint8_t*)Srb_info->Rx_buffer.Payload,
100,0,0);
#ifdef XER_PRINT
xer_fprint(stdout,&asn_DEF_DL_CCCH_Message,(void*)dl_ccch_msg);
#endif
if ( LOG_DEBUGFLAG(DEBUG_ASN1) ) {
xer_fprint(stdout,&asn_DEF_DL_CCCH_Message,(void*)dl_ccch_msg);
}
#if defined(ENABLE_ITTI)
# if defined(DISABLE_ITTI_XER_PRINT)
@@ -1931,9 +1927,9 @@ rrc_ue_process_securityModeCommand(
AssertFatal (enc_rval.encoded > 0, "ASN1 message encoding failed (%s, %jd)!\n",
enc_rval.failed_type->name, enc_rval.encoded);
#ifdef XER_PRINT
xer_fprint(stdout, &asn_DEF_UL_DCCH_Message, (void*)&ul_dcch_msg);
#endif
if ( LOG_DEBUGFLAG(DEBUG_ASN1) ) {
xer_fprint(stdout, &asn_DEF_UL_DCCH_Message, (void*)&ul_dcch_msg);
}
#if defined(ENABLE_ITTI)
# if !defined(DISABLE_XER_SPRINT)
@@ -2042,9 +2038,9 @@ rrc_ue_process_ueCapabilityEnquiry(
AssertFatal (enc_rval.encoded > 0, "ASN1 message encoding failed (%s, %jd)!\n",
enc_rval.failed_type->name, enc_rval.encoded);
#ifdef XER_PRINT
xer_fprint(stdout, &asn_DEF_UL_DCCH_Message, (void*)&ul_dcch_msg);
#endif
if ( LOG_DEBUGFLAG(DEBUG_ASN1) ) {
xer_fprint(stdout, &asn_DEF_UL_DCCH_Message, (void*)&ul_dcch_msg);
}
#if defined(ENABLE_ITTI)
# if !defined(DISABLE_XER_SPRINT)
@@ -2429,9 +2425,9 @@ rrc_ue_decode_dcch(
(uint8_t*)Buffer,
RRC_BUF_SIZE,0,0);
#ifdef XER_PRINT
xer_fprint(stdout,&asn_DEF_DL_DCCH_Message,(void*)dl_dcch_msg);
#endif
if ( LOG_DEBUGFLAG(DEBUG_ASN1) ) {
xer_fprint(stdout,&asn_DEF_DL_DCCH_Message,(void*)dl_dcch_msg);
}
#if defined(ENABLE_ITTI)
# if defined(DISABLE_ITTI_XER_PRINT)
@@ -4560,9 +4556,9 @@ int decode_MCCH_Message( const protocol_ctxt_t* const ctxt_pP, const uint8_t eNB
return -1;
}
#ifdef XER_PRINT
xer_fprint(stdout, &asn_DEF_MCCH_Message, (void*)mcch);
#endif
if ( LOG_DEBUGFLAG(DEBUG_ASN1) ) {
xer_fprint(stdout, &asn_DEF_MCCH_Message, (void*)mcch);
}
if (mcch->message.present == MCCH_MessageType_PR_c1) {
LOG_D(RRC,"[UE %d] Found mcch message \n",
@@ -4594,10 +4590,30 @@ int decode_MCCH_Message( const protocol_ctxt_t* const ctxt_pP, const uint8_t eNB
//-----------------------------------------------------------------------------
void decode_MBSFNAreaConfiguration( module_id_t ue_mod_idP, uint8_t eNB_index, frame_t frameP, uint8_t mbsfn_sync_area )
{
uint8_t i;
protocol_ctxt_t ctxt;
LOG_I(RRC,"[UE %d] Frame %d : Number of MCH(s) in the MBSFN Sync Area %d is %d\n",
ue_mod_idP, frameP, mbsfn_sync_area, UE_rrc_inst[ue_mod_idP].mcch_message[eNB_index]->pmch_InfoList_r9.list.count);
// Configure commonSF_Alloc
for(i=0; i< UE_rrc_inst[ue_mod_idP].mcch_message[eNB_index]->commonSF_Alloc_r9.list.count;i++){
LOG_W(RRC,"[UE %d] Frame %d, commonSF_Alloc_r9: radioframeAllocationPeriod(%ldn),radioframeAllocationOffset(%ld), subframeAllocation(%x,%x,%x)\n",
ue_mod_idP, frameP,
UE_rrc_inst[ue_mod_idP].mcch_message[eNB_index]->commonSF_Alloc_r9.list.array[i]->radioframeAllocationPeriod<<1,
UE_rrc_inst[ue_mod_idP].mcch_message[eNB_index]->commonSF_Alloc_r9.list.array[i]->radioframeAllocationOffset,
UE_rrc_inst[ue_mod_idP].mcch_message[eNB_index]->commonSF_Alloc_r9.list.array[i]->subframeAllocation.choice.oneFrame.buf[0],
UE_rrc_inst[ue_mod_idP].mcch_message[eNB_index]->commonSF_Alloc_r9.list.array[i]->subframeAllocation.choice.oneFrame.buf[1],
UE_rrc_inst[ue_mod_idP].mcch_message[eNB_index]->commonSF_Alloc_r9.list.array[i]->subframeAllocation.choice.oneFrame.buf[2]);
UE_mac_inst[ue_mod_idP].commonSF_Alloc_r9_mbsfn_SubframeConfig[i] = UE_rrc_inst[ue_mod_idP].mcch_message[eNB_index]->commonSF_Alloc_r9.list.array[i];
}
LOG_W(RRC,"[UE %d] Frame %d, commonSF_AllocPeriod_r9 %drf \n",
ue_mod_idP, frameP,
4<<UE_rrc_inst[ue_mod_idP].mcch_message[eNB_index]->commonSF_AllocPeriod_r9);
// Configure commonSF_AllocPeriod
UE_mac_inst[ue_mod_idP].commonSF_AllocPeriod_r9 = UE_rrc_inst[ue_mod_idP].mcch_message[eNB_index]->commonSF_AllocPeriod_r9;
// store to MAC/PHY necessary parameters for receiving MTCHs
rrc_mac_config_req_ue(ue_mod_idP,0,eNB_index,
@@ -5558,9 +5574,9 @@ void *rrc_control_socket_thread_fct(void *arg)
//process the message
switch (sl_ctrl_msg_recv->type) {
case SESSION_INIT_REQ:
LOG_DEBUG_BEGIN(DEBUG_CTRLSOCKET)
LOG_UI(RRC,"Received SessionInitializationRequest on socket from ProSe App (msg type: %d)\n", sl_ctrl_msg_recv->type);
LOG_DEBUG_END
if (LOG_DEBUGFLAG(DEBUG_CTRLSOCKET)){
LOG_UI(RRC,"Received SessionInitializationRequest on socket from ProSe App (msg type: %d)\n", sl_ctrl_msg_recv->type);
}
//TODO: get SL_UE_STATE from lower layer
LOG_I(RRC,"Send UEStateInformation to ProSe App \n");
@@ -5579,12 +5595,12 @@ LOG_DEBUG_END
exit(EXIT_FAILURE);
}
LOG_DEBUG_BEGIN(DEBUG_CTRLSOCKET)
struct sidelink_ctrl_element *ptr_ctrl_msg = NULL;
ptr_ctrl_msg = (struct sidelink_ctrl_element *) send_buf;
LOG_UI(RRC,"[UEStateInformation] msg type: %d\n",ptr_ctrl_msg->type);
LOG_UI(RRC,"[UEStateInformation] UE state: %d\n",ptr_ctrl_msg->sidelinkPrimitive.ue_state);
LOG_DEBUG_END
if (LOG_DEBUGFLAG(DEBUG_CTRLSOCKET)){
struct sidelink_ctrl_element *ptr_ctrl_msg = NULL;
ptr_ctrl_msg = (struct sidelink_ctrl_element *) send_buf;
LOG_UI(RRC,"[UEStateInformation] msg type: %d\n",ptr_ctrl_msg->type);
LOG_UI(RRC,"[UEStateInformation] UE state: %d\n",ptr_ctrl_msg->sidelinkPrimitive.ue_state);
}
/* if (enable_notification > 0) {
//create thread to send status notification (for testing purpose, status notification will be sent e.g., every 20 seconds)
pthread_t notification_thread;
@@ -5599,12 +5615,12 @@ LOG_DEBUG_END
sourceL2Id = sl_ctrl_msg_recv->sidelinkPrimitive.group_comm_establish_req.sourceL2Id;
groupL2Id = sl_ctrl_msg_recv->sidelinkPrimitive.group_comm_establish_req.groupL2Id;
LOG_DEBUG_BEGIN(DEBUG_CTRLSOCKET)
LOG_UI(RRC,"[GroupCommunicationEstablishReq] Received on socket from ProSe App (msg type: %d)\n",sl_ctrl_msg_recv->type);
LOG_UI(RRC,"[GroupCommunicationEstablishReq] source Id: 0x%08x\n",sl_ctrl_msg_recv->sidelinkPrimitive.group_comm_establish_req.sourceL2Id);
LOG_UI(RRC,"[GroupCommunicationEstablishReq] group Id: 0x%08x\n",sl_ctrl_msg_recv->sidelinkPrimitive.group_comm_establish_req.groupL2Id);
LOG_UI(RRC,"[GroupCommunicationEstablishReq] group IP Address: " IPV4_ADDR "\n",IPV4_ADDR_FORMAT(sl_ctrl_msg_recv->sidelinkPrimitive.group_comm_establish_req.groupIpAddress));
LOG_DEBUG_END
if (LOG_DEBUGFLAG(DEBUG_CTRLSOCKET)){
LOG_UI(RRC,"[GroupCommunicationEstablishReq] Received on socket from ProSe App (msg type: %d)\n",sl_ctrl_msg_recv->type);
LOG_UI(RRC,"[GroupCommunicationEstablishReq] source Id: 0x%08x\n",sl_ctrl_msg_recv->sidelinkPrimitive.group_comm_establish_req.sourceL2Id);
LOG_UI(RRC,"[GroupCommunicationEstablishReq] group Id: 0x%08x\n",sl_ctrl_msg_recv->sidelinkPrimitive.group_comm_establish_req.groupL2Id);
LOG_UI(RRC,"[GroupCommunicationEstablishReq] group IP Address: " IPV4_ADDR "\n",IPV4_ADDR_FORMAT(sl_ctrl_msg_recv->sidelinkPrimitive.group_comm_establish_req.groupIpAddress));
}
//store sourceL2Id/groupL2Id
UE_rrc_inst[module_id].sourceL2Id = sourceL2Id;
@@ -5764,20 +5780,20 @@ LOG_DEBUG_END
exit(EXIT_FAILURE);
}
LOG_DEBUG_BEGIN(DEBUG_CTRLSOCKET)
struct sidelink_ctrl_element *ptr_ctrl_msg = NULL;
ptr_ctrl_msg = (struct sidelink_ctrl_element *) send_buf;
LOG_UI(RRC,"[GroupCommunicationEstablishResponse] msg type: %d\n",ptr_ctrl_msg->type);
LOG_UI(RRC,"[GroupCommunicationEstablishResponse] slrb_id: %d\n",ptr_ctrl_msg->sidelinkPrimitive.slrb_id);
LOG_DEBUG_END
if (LOG_DEBUGFLAG(DEBUG_CTRLSOCKET)){
struct sidelink_ctrl_element *ptr_ctrl_msg = NULL;
ptr_ctrl_msg = (struct sidelink_ctrl_element *) send_buf;
LOG_UI(RRC,"[GroupCommunicationEstablishResponse] msg type: %d\n",ptr_ctrl_msg->type);
LOG_UI(RRC,"[GroupCommunicationEstablishResponse] slrb_id: %d\n",ptr_ctrl_msg->sidelinkPrimitive.slrb_id);
}
break;
case GROUP_COMMUNICATION_RELEASE_REQ:
printf("-----------------------------------\n");
LOG_DEBUG_BEGIN(DEBUG_CTRLSOCKET)
LOG_UI(RRC,"[GroupCommunicationReleaseRequest] Received on socket from ProSe App (msg type: %d)\n",sl_ctrl_msg_recv->type);
LOG_UI(RRC,"[GroupCommunicationReleaseRequest] Slrb Id: %i\n",sl_ctrl_msg_recv->sidelinkPrimitive.slrb_id);
LOG_DEBUG_END
if (LOG_DEBUGFLAG(DEBUG_CTRLSOCKET)){
LOG_UI(RRC,"[GroupCommunicationReleaseRequest] Received on socket from ProSe App (msg type: %d)\n",sl_ctrl_msg_recv->type);
LOG_UI(RRC,"[GroupCommunicationReleaseRequest] Slrb Id: %i\n",sl_ctrl_msg_recv->sidelinkPrimitive.slrb_id);
}
//reset groupL2ID from MAC LAYER
UE_rrc_inst[module_id].groupL2Id = 0x00000000;
sourceL2Id = UE_rrc_inst[module_id].sourceL2Id;
@@ -5849,11 +5865,11 @@ LOG_DEBUG_END
sourceL2Id = sl_ctrl_msg_recv->sidelinkPrimitive.direct_comm_establish_req.sourceL2Id;
destinationL2Id = sl_ctrl_msg_recv->sidelinkPrimitive.direct_comm_establish_req.destinationL2Id;
LOG_DEBUG_BEGIN(DEBUG_CTRLSOCKET)
LOG_UI(RRC,"[DirectCommunicationEstablishReq] Received on socket from ProSe App (msg type: %d)\n",sl_ctrl_msg_recv->type);
LOG_UI(RRC,"[DirectCommunicationEstablishReq] source Id: 0x%08x\n",sl_ctrl_msg_recv->sidelinkPrimitive.group_comm_establish_req.sourceL2Id);
LOG_UI(RRC,"[DirectCommunicationEstablishReq] destination Id: 0x%08x\n",sl_ctrl_msg_recv->sidelinkPrimitive.group_comm_establish_req.groupL2Id);
LOG_DEBUG_END
if (LOG_DEBUGFLAG(DEBUG_CTRLSOCKET)){
LOG_UI(RRC,"[DirectCommunicationEstablishReq] Received on socket from ProSe App (msg type: %d)\n",sl_ctrl_msg_recv->type);
LOG_UI(RRC,"[DirectCommunicationEstablishReq] source Id: 0x%08x\n",sl_ctrl_msg_recv->sidelinkPrimitive.group_comm_establish_req.sourceL2Id);
LOG_UI(RRC,"[DirectCommunicationEstablishReq] destination Id: 0x%08x\n",sl_ctrl_msg_recv->sidelinkPrimitive.group_comm_establish_req.groupL2Id);
}
//store sourceL2Id/destinationL2Id
UE_rrc_inst[module_id].sourceL2Id = sourceL2Id;
@@ -6013,27 +6029,27 @@ LOG_DEBUG_END
}
LOG_DEBUG_BEGIN(DEBUG_CTRLSOCKET)
struct sidelink_ctrl_element *ptr_ctrl_msg = NULL;
ptr_ctrl_msg = (struct sidelink_ctrl_element *) send_buf;
LOG_UI(RRC,"[DirectCommunicationEstablishResponse] msg type: %d\n",ptr_ctrl_msg->type);
LOG_UI(RRC,"[DirectCommunicationEstablishResponse] slrb_id: %d\n",ptr_ctrl_msg->sidelinkPrimitive.slrb_id);
LOG_DEBUG_END
if (LOG_DEBUGFLAG(DEBUG_CTRLSOCKET)){
struct sidelink_ctrl_element *ptr_ctrl_msg = NULL;
ptr_ctrl_msg = (struct sidelink_ctrl_element *) send_buf;
LOG_UI(RRC,"[DirectCommunicationEstablishResponse] msg type: %d\n",ptr_ctrl_msg->type);
LOG_UI(RRC,"[DirectCommunicationEstablishResponse] slrb_id: %d\n",ptr_ctrl_msg->sidelinkPrimitive.slrb_id);
}
break;
case PC5S_ESTABLISH_REQ:
type = sl_ctrl_msg_recv->sidelinkPrimitive.pc5s_establish_req.type;
sourceL2Id = sl_ctrl_msg_recv->sidelinkPrimitive.pc5s_establish_req.sourceL2Id;
LOG_DEBUG_BEGIN(DEBUG_CTRLSOCKET)
LOG_UI(RRC,"[PC5EstablishReq] Received on socket from ProSe App (msg type: %d)\n",sl_ctrl_msg_recv->type);
LOG_UI(RRC,"[PC5EstablishReq] type: %d\n",sl_ctrl_msg_recv->sidelinkPrimitive.pc5s_establish_req.type); //RX/TX
LOG_UI(RRC,"[PC5EstablishReq] source Id: 0x%08x \n",sl_ctrl_msg_recv->sidelinkPrimitive.pc5s_establish_req.sourceL2Id);
LOG_DEBUG_END
type = sl_ctrl_msg_recv->sidelinkPrimitive.pc5s_establish_req.type;
sourceL2Id = sl_ctrl_msg_recv->sidelinkPrimitive.pc5s_establish_req.sourceL2Id;
if (LOG_DEBUGFLAG(DEBUG_CTRLSOCKET)){
LOG_UI(RRC,"[PC5EstablishReq] Received on socket from ProSe App (msg type: %d)\n",sl_ctrl_msg_recv->type);
LOG_UI(RRC,"[PC5EstablishReq] type: %d\n",sl_ctrl_msg_recv->sidelinkPrimitive.pc5s_establish_req.type); //RX/TX
LOG_UI(RRC,"[PC5EstablishReq] source Id: 0x%08x \n",sl_ctrl_msg_recv->sidelinkPrimitive.pc5s_establish_req.sourceL2Id);
}
if (type > 0) {
destinationL2Id = sl_ctrl_msg_recv->sidelinkPrimitive.pc5s_establish_req.destinationL2Id;
LOG_DEBUG_BEGIN(DEBUG_CTRLSOCKET)
LOG_UI(RRC,"[PC5EstablishReq] destination Id: 0x%08x \n",sl_ctrl_msg_recv->sidelinkPrimitive.pc5s_establish_req.destinationL2Id);
LOG_DEBUG_END
if (LOG_DEBUGFLAG(DEBUG_CTRLSOCKET)){
LOG_UI(RRC,"[PC5EstablishReq] destination Id: 0x%08x \n",sl_ctrl_msg_recv->sidelinkPrimitive.pc5s_establish_req.destinationL2Id);
}
}
//store sourceL2Id/destinationL2Id
@@ -6244,9 +6260,9 @@ LOG_DEBUG_END
case PC5_DISCOVERY_MESSAGE:
LOG_DEBUG_BEGIN(DEBUG_CTRLSOCKET)
if (LOG_DEBUGFLAG(DEBUG_CTRLSOCKET)){
LOG_UI(RRC,"[PC5DiscoveryMessage] Received on socket from ProSe App (msg type: %d)\n",sl_ctrl_msg_recv->type);
LOG_DEBUG_END
}
//prepare SL_Discovery buffer
if (UE_rrc_inst) {
memcpy((void*)&UE_rrc_inst[module_id].SL_Discovery[0].Tx_buffer.Payload[0], (void*)&sl_ctrl_msg_recv->sidelinkPrimitive.pc5_discovery_message.payload[0], PC5_DISCOVERY_PAYLOAD_SIZE);
-1
View File
@@ -43,7 +43,6 @@
#include "rrc_eNB_UE_context.h"
#include "common/ran_context.h"
#define DEBUG_RRC 1
extern RAN_CONTEXT_t RC;
extern UE_MAC_INST *UE_mac_inst;
-7
View File
@@ -699,13 +699,6 @@ typedef struct eNB_RRC_INST_s {
#if defined(ENABLE_ITTI)
RrcConfigurationReq configuration;
#endif
// other PLMN parameters
/// Mobile country code
int mcc;
/// Mobile network code
int mnc;
/// number of mnc digits
int mnc_digit_length;
// other RAN parameters
int srb1_timer_poll_retransmit;
+212 -384
View File
@@ -85,6 +85,8 @@
# else
# include "../../S1AP/s1ap_eNB.h"
# endif
#else
# define EPC_MODE_ENABLED 0
#endif
#include "pdcp.h"
@@ -100,7 +102,6 @@
#include "SIMULATION/TOOLS/sim.h" // for taus
//#define XER_PRINT
extern RAN_CONTEXT_t RC;
@@ -839,11 +840,6 @@ rrc_eNB_free_UE(const module_id_t enb_mod_idP,const struct rrc_eNB_ue_context_s*
protocol_ctxt_t ctxt;
#if !defined(ENABLE_USE_MME)
module_id_t ue_module_id;
/* avoid gcc warnings */
(void)ue_module_id;
#endif
rnti_t rnti = ue_context_pP->ue_context.rnti;
if (enb_mod_idP >= NB_eNB_INST) {
LOG_I(RRC, "eNB inst invalid (%d/%d) for UE %x!\n",enb_mod_idP, NB_eNB_INST,rnti);
@@ -858,20 +854,21 @@ rrc_eNB_free_UE(const module_id_t enb_mod_idP,const struct rrc_eNB_ue_context_s*
PROTOCOL_CTXT_SET_BY_MODULE_ID(&ctxt, enb_mod_idP, ENB_FLAG_YES, rnti, 0, 0,enb_mod_idP);
LOG_W(RRC, "[eNB %d] Removing UE RNTI %x\n", enb_mod_idP, rnti);
#if defined(ENABLE_USE_MME)
if((ue_context_pP->ue_context.ul_failure_timer >= 20000) &&
(mac_eNB_get_rrc_status(enb_mod_idP,rnti) >= RRC_CONNECTED)) {
LOG_I(RRC, "[eNB %d] S1AP_UE_CONTEXT_RELEASE_REQ RNTI %x\n", enb_mod_idP, rnti);
rrc_eNB_send_S1AP_UE_CONTEXT_RELEASE_REQ(enb_mod_idP, ue_context_pP, S1AP_CAUSE_RADIO_NETWORK, 21); // send cause 21: connection with ue lost
/* From 3GPP 36300v10 p129 : 19.2.2.2.2 S1 UE Context Release Request (eNB triggered)
* If the E-UTRAN internal reason is a radio link failure detected in the eNB, the eNB shall wait a sufficient time before
* triggering the S1 UE Context Release Request procedure
* in order to allow the UE to perform the NAS recovery
* procedure, see TS 23.401 [17].
*/
return;
if(EPC_MODE_ENABLED) {
if((ue_context_pP->ue_context.ul_failure_timer >= 20000) &&
(mac_eNB_get_rrc_status(enb_mod_idP,rnti) >= RRC_CONNECTED)) {
LOG_I(RRC, "[eNB %d] S1AP_UE_CONTEXT_RELEASE_REQ RNTI %x\n", enb_mod_idP, rnti);
rrc_eNB_send_S1AP_UE_CONTEXT_RELEASE_REQ(enb_mod_idP, ue_context_pP, S1AP_CAUSE_RADIO_NETWORK, 21); // send cause 21: connection with ue lost
/* From 3GPP 36300v10 p129 : 19.2.2.2.2 S1 UE Context Release Request (eNB triggered)
* If the E-UTRAN internal reason is a radio link failure detected in the eNB, the eNB shall wait a sufficient time before
* triggering the S1 UE Context Release Request procedure
* in order to allow the UE to perform the NAS recovery
* procedure, see TS 23.401 [17].
*/
return;
}
#endif
}
// add UE info to freeList
LOG_I(RRC, "put UE %x into freeList\n", rnti);
put_UE_in_freelist(enb_mod_idP, rnti, 1);
@@ -1018,17 +1015,13 @@ rrc_eNB_process_RRCConnectionSetupComplete(
T(T_ENB_RRC_CONNECTION_SETUP_COMPLETE, T_INT(ctxt_pP->module_id), T_INT(ctxt_pP->frame),
T_INT(ctxt_pP->subframe), T_INT(ctxt_pP->rnti));
#if defined(ENABLE_USE_MME)
if (EPC_MODE_ENABLED == 1) {
// Forward message to S1AP layer
rrc_eNB_send_S1AP_NAS_FIRST_REQ(
ctxt_pP,
ue_context_pP,
rrcConnectionSetupComplete);
} else
#endif
{
} else {
// RRC loop back (no S1AP), send SecurityModeCommand to UE
rrc_eNB_generate_SecurityModeCommand(
ctxt_pP,
@@ -1058,16 +1051,8 @@ rrc_eNB_generate_SecurityModeCommand(
ue_context_pP->ue_context.ciphering_algorithm,
ue_context_pP->ue_context.integrity_algorithm);
#ifdef RRC_MSG_PRINT
uint16_t i=0;
LOG_F(RRC,"[MSG] RRC Security Mode Command\n");
for (i = 0; i < size; i++) {
LOG_F(RRC,"%02x ", ((uint8_t*)buffer)[i]);
}
LOG_F(RRC,"\n");
#endif
LOG_DUMPMSG(RRC,DEBUG_RRC,(char *)buffer,size,"[MSG] RRC Security Mode Command\n");
LOG_I(RRC,
PROTOCOL_RRC_CTXT_UE_FMT" Logical Channel DL-DCCH, Generate SecurityModeCommand (bytes %d)\n",
@@ -1166,9 +1151,6 @@ rrc_eNB_generate_RRCConnectionReject(
)
//-----------------------------------------------------------------------------
{
#ifdef RRC_MSG_PRINT
int cnt;
#endif
T(T_ENB_RRC_CONNECTION_REJECT, T_INT(ctxt_pP->module_id), T_INT(ctxt_pP->frame),
T_INT(ctxt_pP->subframe), T_INT(ctxt_pP->rnti));
@@ -1177,15 +1159,10 @@ rrc_eNB_generate_RRCConnectionReject(
do_RRCConnectionReject(ctxt_pP->module_id,
(uint8_t*) RC.rrc[ctxt_pP->module_id]->carrier[CC_id].Srb0.Tx_buffer.Payload);
#ifdef RRC_MSG_PRINT
LOG_F(RRC,"[MSG] RRCConnectionReject\n");
for (cnt = 0; cnt < RC.rrc[ctxt_pP->module_id]->carrier[CC_id].Srb0.Tx_buffer.payload_size; cnt++) {
LOG_F(RRC,"%02x ", ((uint8_t*)RC.rrc[ctxt_pP->module_id]->Srb0.Tx_buffer.Payload)[cnt]);
}
LOG_F(RRC,"\n");
#endif
LOG_DUMPMSG(RRC,DEBUG_RRC,
(char *)(RC.rrc[ctxt_pP->module_id]->carrier[CC_id].Srb0.Tx_buffer.Payload),
RC.rrc[ctxt_pP->module_id]->carrier[CC_id].Srb0.Tx_buffer.payload_size,
"[MSG] RRCConnectionReject\n");
MSC_LOG_TX_MESSAGE(
MSC_RRC_ENB,
@@ -1230,17 +1207,11 @@ rrc_eNB_generate_RRCConnectionReestablishment(
rrc_eNB_get_next_transaction_identifier(ctxt_pP->module_id),
SRB_configList,
&ue_context_pP->ue_context.physicalConfigDedicated);
#ifdef RRC_MSG_PRINT
LOG_F(RRC,"[MSG] RRCConnectionReestablishment\n");
for (cnt = 0; cnt < RC.rrc[ctxt_pP->module_id]->carrier[CC_id].Srb0.Tx_buffer.payload_size; cnt++) {
LOG_F(RRC,"%02x ", ((uint8_t*)RC.rrc[ctxt_pP->module_id]->carrier[CC_id].Srb0.Tx_buffer.Payload)[cnt]);
}
LOG_F(RRC,"\n");
#endif
LOG_DUMPMSG(RRC,DEBUG_RRC,
(char *)(RC.rrc[ctxt_pP->module_id]->carrier[CC_id].Srb0.Tx_buffer.Payload),
RC.rrc[ctxt_pP->module_id]->carrier[CC_id].Srb0.Tx_buffer.payload_size,
"[MSG] RRCConnectionReestablishment\n"
);
// configure SRB1 for UE
if (*SRB_configList != NULL) {
@@ -1356,10 +1327,6 @@ rrc_eNB_process_RRCConnectionReestablishmentComplete(
struct SRB_ToAddMod *SRB2_config = NULL;
struct DRB_ToAddMod *DRB_config = NULL;
int i = 0;
# if defined(ENABLE_USE_MME)
int j = 0;
hashtable_rc_t h_rc;
#endif
uint8_t buffer[RRC_BUF_SIZE];
uint16_t size;
MeasObjectToAddModList_t *MeasObj_list = NULL;
@@ -1450,59 +1417,61 @@ rrc_eNB_process_RRCConnectionReestablishmentComplete(
ue_context_pP->ue_context.Srb1.Active = 1;
//ue_context_pP->ue_context.Srb2.Srb_info.Srb_id = 2;
# if defined(ENABLE_USE_MME)
rrc_ue_s1ap_ids_t* rrc_ue_s1ap_ids_p = NULL;
uint16_t ue_initial_id = ue_context_pP->ue_context.ue_initial_id;
uint32_t eNB_ue_s1ap_id = ue_context_pP->ue_context.eNB_ue_s1ap_id;
eNB_RRC_INST *rrc_instance_p = RC.rrc[ENB_INSTANCE_TO_MODULE_ID(ctxt_pP->instance)];
if (eNB_ue_s1ap_id > 0) {
h_rc = hashtable_get(rrc_instance_p->s1ap_id2_s1ap_ids, (hash_key_t)eNB_ue_s1ap_id, (void**)&rrc_ue_s1ap_ids_p);
if (h_rc == HASH_TABLE_OK) {
rrc_ue_s1ap_ids_p->ue_rnti = ctxt_pP->rnti;
#if defined(ENABLE_USE_MME)
hashtable_rc_t h_rc;
int j;
rrc_ue_s1ap_ids_t* rrc_ue_s1ap_ids_p = NULL;
uint16_t ue_initial_id = ue_context_pP->ue_context.ue_initial_id;
uint32_t eNB_ue_s1ap_id = ue_context_pP->ue_context.eNB_ue_s1ap_id;
eNB_RRC_INST *rrc_instance_p = RC.rrc[ENB_INSTANCE_TO_MODULE_ID(ctxt_pP->instance)];
if (eNB_ue_s1ap_id > 0) {
h_rc = hashtable_get(rrc_instance_p->s1ap_id2_s1ap_ids, (hash_key_t)eNB_ue_s1ap_id, (void**)&rrc_ue_s1ap_ids_p);
if (h_rc == HASH_TABLE_OK) {
rrc_ue_s1ap_ids_p->ue_rnti = ctxt_pP->rnti;
}
}
}
if (ue_initial_id != 0) {
h_rc = hashtable_get(rrc_instance_p->initial_id2_s1ap_ids, (hash_key_t)ue_initial_id, (void**)&rrc_ue_s1ap_ids_p);
if (h_rc == HASH_TABLE_OK) {
rrc_ue_s1ap_ids_p->ue_rnti = ctxt_pP->rnti;
if (ue_initial_id != 0) {
h_rc = hashtable_get(rrc_instance_p->initial_id2_s1ap_ids, (hash_key_t)ue_initial_id, (void**)&rrc_ue_s1ap_ids_p);
if (h_rc == HASH_TABLE_OK) {
rrc_ue_s1ap_ids_p->ue_rnti = ctxt_pP->rnti;
}
}
}
gtpv1u_enb_create_tunnel_req_t create_tunnel_req;
gtpv1u_enb_create_tunnel_req_t create_tunnel_req;
/* Save e RAB information for later */
memset(&create_tunnel_req, 0 , sizeof(create_tunnel_req));
/* Save e RAB information for later */
memset(&create_tunnel_req, 0 , sizeof(create_tunnel_req));
for (j = 0, i = 0; i < NB_RB_MAX; i++) {
if (ue_context_pP->ue_context.e_rab[i].status == E_RAB_STATUS_ESTABLISHED || ue_context_pP->ue_context.e_rab[i].status == E_RAB_STATUS_DONE) {
create_tunnel_req.eps_bearer_id[j] = ue_context_pP->ue_context.e_rab[i].param.e_rab_id;
create_tunnel_req.sgw_S1u_teid[j] = ue_context_pP->ue_context.e_rab[i].param.gtp_teid;
for ( j = 0, i = 0; i < NB_RB_MAX; i++) {
if (ue_context_pP->ue_context.e_rab[i].status == E_RAB_STATUS_ESTABLISHED || ue_context_pP->ue_context.e_rab[i].status == E_RAB_STATUS_DONE) {
create_tunnel_req.eps_bearer_id[j] = ue_context_pP->ue_context.e_rab[i].param.e_rab_id;
create_tunnel_req.sgw_S1u_teid[j] = ue_context_pP->ue_context.e_rab[i].param.gtp_teid;
memcpy(&create_tunnel_req.sgw_addr[j],
&ue_context_pP->ue_context.e_rab[i].param.sgw_addr,
sizeof(transport_layer_addr_t));
j++;
memcpy(&create_tunnel_req.sgw_addr[j],
&ue_context_pP->ue_context.e_rab[i].param.sgw_addr,
sizeof(transport_layer_addr_t));
j++;
}
}
}
create_tunnel_req.rnti = ctxt_pP->rnti; // warning put zero above
create_tunnel_req.num_tunnels = j;
create_tunnel_req.rnti = ctxt_pP->rnti; // warning put zero above
create_tunnel_req.num_tunnels = j;
gtpv1u_update_s1u_tunnel(
ctxt_pP->instance,
&create_tunnel_req,
reestablish_rnti);
gtpv1u_update_s1u_tunnel(
ctxt_pP->instance,
&create_tunnel_req,
reestablish_rnti);
#endif
/* Update RNTI in ue_context */
ue_context_pP->ue_id_rnti = ctxt_pP->rnti; // here ue_id_rnti is just a key, may be something else
ue_context_pP->ue_context.rnti = ctxt_pP->rnti;
# if defined(ENABLE_USE_MME)
uint8_t send_security_mode_command = FALSE;
rrc_pdcp_config_security(
ctxt_pP,
ue_context_pP,
send_security_mode_command);
LOG_D(RRC, "set security successfully \n");
#if defined(ENABLE_USE_MME)
uint8_t send_security_mode_command = FALSE;
rrc_pdcp_config_security(
ctxt_pP,
ue_context_pP,
send_security_mode_command);
LOG_D(RRC, "set security successfully \n");
#endif
// Measurement ID list
MeasId_list = CALLOC(1, sizeof(*MeasId_list));
@@ -1869,15 +1838,9 @@ rrc_eNB_process_RRCConnectionReestablishmentComplete(
, (SCellToAddMod_r10_t*)NULL
#endif
);
LOG_DUMPMSG(RRC,DEBUG_RRC,(char *)buffer,size,
"[MSG] RRC Connection Reconfiguration\n");
#ifdef RRC_MSG_PRINT
LOG_F(RRC,"[MSG] RRC Connection Reconfiguration\n");
for (i = 0; i < size; i++) {
LOG_F(RRC,"%02x ", ((uint8_t*)buffer)[i]);
}
LOG_F(RRC,"\n");
////////////////////////////////////////
#endif
#if defined(ENABLE_ITTI)
@@ -1977,9 +1940,6 @@ rrc_eNB_generate_RRCConnectionReestablishmentReject(
)
//-----------------------------------------------------------------------------
{
#ifdef RRC_MSG_PRINT
int cnt;
#endif
int UE_id = find_UE_id(ctxt_pP->module_id, ctxt_pP->rnti);
if(UE_id != -1){
RC.mac[ctxt_pP->module_id]->UE_list.UE_sched_ctrl[UE_id].ue_reestablishment_reject_timer = 1;
@@ -1997,15 +1957,11 @@ rrc_eNB_generate_RRCConnectionReestablishmentReject(
do_RRCConnectionReestablishmentReject(ctxt_pP->module_id,
(uint8_t*) RC.rrc[ctxt_pP->module_id]->carrier[CC_id].Srb0.Tx_buffer.Payload);
#ifdef RRC_MSG_PRINT
LOG_F(RRC,"[MSG] RRCConnectionReestablishmentReject\n");
LOG_DUMPMSG(RRC,DEBUG_RRC,
(char *)(RC.rrc[ctxt_pP->module_id]->carrier[CC_id].Srb0.Tx_buffer.Payload),
RC.rrc[ctxt_pP->module_id]->carrier[CC_id].Srb0.Tx_buffer.payload_size,
"[MSG] RRCConnectionReestablishmentReject\n");
for (cnt = 0; cnt < RC.rrc[ctxt_pP->module_id]->carrier[CC_id].Srb0.Tx_buffer.payload_size; cnt++) {
LOG_F(RRC,"%02x ", ((uint8_t*)RC.rrc[ctxt_pP->module_id]->carrier[CC_id].Srb0.Tx_buffer.Payload)[cnt]);
}
LOG_F(RRC,"\n");
#endif
MSC_LOG_TX_MESSAGE(
MSC_RRC_ENB,
@@ -2336,15 +2292,8 @@ rrc_eNB_generate_dedicatedRRCConnectionReconfiguration(const protocol_ctxt_t* co
#endif
);
LOG_DUMPMSG(RRC,DEBUG_RRC,(char *)buffer,size,"[MSG] RRC Connection Reconfiguration\n");
#ifdef RRC_MSG_PRINT
LOG_F(RRC,"[MSG] RRC Connection Reconfiguration\n");
for (i = 0; i < size; i++) {
LOG_F(RRC,"%02x ", ((uint8_t*)buffer)[i]);
}
LOG_F(RRC,"\n");
////////////////////////////////////////
#endif
#if defined(ENABLE_ITTI)
@@ -2606,15 +2555,8 @@ rrc_eNB_modify_dedicatedRRCConnectionReconfiguration(const protocol_ctxt_t* cons
#endif
);
#ifdef RRC_MSG_PRINT
LOG_F(RRC,"[MSG] RRC Connection Reconfiguration\n");
for (i = 0; i < size; i++) {
LOG_F(RRC,"%02x ", ((uint8_t*)buffer)[i]);
}
LOG_F(RRC,"\n");
////////////////////////////////////////
#endif
LOG_DUMPMSG(RRC,DEBUG_RRC,(char *)buffer,size,
"[MSG] RRC Connection Reconfiguration\n");
#if defined(ENABLE_ITTI)
@@ -2731,15 +2673,8 @@ rrc_eNB_generate_dedicatedRRCConnectionReconfiguration_release( const protocol_
#endif
);
ue_context_pP->ue_context.e_rab_release_command_flag = 1;
#ifdef RRC_MSG_PRINT
LOG_F(RRC,"[MSG] RRC Connection Reconfiguration\n");
for (i = 0; i < size; i++) {
LOG_F(RRC,"%02x ", ((uint8_t*)buffer)[i]);
}
LOG_F(RRC,"\n");
////////////////////////////////////////
#endif
LOG_DUMPMSG(RRC,DEBUG_RRC,(char *)buffer,size,
"[MSG] RRC Connection Reconfiguration\n");
#if defined(ENABLE_ITTI)
/* Free all NAS PDUs */
@@ -3460,15 +3395,8 @@ rrc_eNB_generate_defaultRRCConnectionReconfiguration(const protocol_ctxt_t* cons
, (SCellToAddMod_r10_t*)NULL
#endif
);
#ifdef RRC_MSG_PRINT
LOG_F(RRC,"[MSG] RRC Connection Reconfiguration\n");
for (i = 0; i < size; i++) {
LOG_F(RRC,"%02x ", ((uint8_t*)buffer)[i]);
}
LOG_F(RRC,"\n");
////////////////////////////////////////
#endif
LOG_DUMPMSG(RRC,DEBUG_RRC,(char *)buffer,size,
"[MSG] RRC Connection Reconfiguration\n");
#if defined(ENABLE_ITTI)
@@ -4052,15 +3980,8 @@ flexran_rrc_eNB_generate_defaultRRCConnectionReconfiguration(const protocol_ctxt
, (SCellToAddMod_r10_t*)NULL
#endif
);
#ifdef RRC_MSG_PRINT
LOG_F(RRC,"[MSG] RRC Connection Reconfiguration\n");
for (i = 0; i < size; i++) {
LOG_F(RRC,"%02x ", ((uint8_t*)buffer)[i]);
}
LOG_F(RRC,"\n");
////////////////////////////////////////
#endif
LOG_DUMPMSG(RRC,DEBUG_RRC,(char *)buffer,size,
"[MSG] RRC Connection Reconfiguration\n");
#if defined(ENABLE_ITTI)
@@ -5438,11 +5359,9 @@ rrc_eNB_process_RRCConnectionReconfigurationComplete(
#ifdef PDCP_USE_NETLINK
int oip_ifup = 0;
int dest_ip_offset = 0;
module_id_t ue_module_id = -1;
/* avoid gcc warnings */
(void)oip_ifup;
(void)dest_ip_offset;
(void)ue_module_id;
#endif
uint8_t *kRRCenc = NULL;
@@ -5585,6 +5504,7 @@ rrc_eNB_process_RRCConnectionReconfigurationComplete(
ctxt_pP->module_id + 1); // fourth octet
if (oip_ifup == 0) { // interface is up --> send a config the DRB
module_id_t ue_module_id;
dest_ip_offset = 8;
LOG_I(OIP,
"[eNB %d] Config the oai%d to send/receive pkt on DRB %ld to/from the protocol stack\n",
@@ -5754,16 +5674,10 @@ rrc_eNB_generate_RRCConnectionSetup(
SRB_configList,
&ue_context_pP->ue_context.physicalConfigDedicated);
#ifdef RRC_MSG_PRINT
LOG_F(RRC,"[MSG] RRC Connection Setup\n");
for (cnt = 0; cnt < RC.rrc[ctxt_pP->module_id]->carrier[CC_id].Srb0.Tx_buffer.payload_size; cnt++) {
LOG_F(RRC,"%02x ", ((uint8_t*)RC.rrc[ctxt_pP->module_id]->Srb0.Tx_buffer.Payload)[cnt]);
}
LOG_F(RRC,"\n");
//////////////////////////////////
#endif
LOG_DUMPMSG(RRC,DEBUG_RRC,
(char *)(RC.rrc[ctxt_pP->module_id]->carrier[CC_id].Srb0.Tx_buffer.Payload),
RC.rrc[ctxt_pP->module_id]->carrier[CC_id].Srb0.Tx_buffer.payload_size,
"[MSG] RRC Connection Setup\n");
// configure SRB1/SRB2, PhysicalConfigDedicated, MAC_MainConfig for UE
@@ -6111,15 +6025,10 @@ rrc_eNB_decode_ccch(
T(T_ENB_RRC_CONNECTION_REESTABLISHMENT_REQUEST, T_INT(ctxt_pP->module_id), T_INT(ctxt_pP->frame),
T_INT(ctxt_pP->subframe), T_INT(ctxt_pP->rnti));
#ifdef RRC_MSG_PRINT
LOG_F(RRC,"[MSG] RRC Connection Reestablishment Request\n");
LOG_DUMPMSG(RRC,DEBUG_RRC,(char *)(Srb_info->Rx_buffer.Payload),
Srb_info->Rx_buffer.payload_size,
"[MSG] RRC Connection Reestablishment Request\n");
for (i = 0; i < Srb_info->Rx_buffer.payload_size; i++) {
LOG_F(RRC,"%02x ", ((uint8_t*)Srb_info->Rx_buffer.Payload)[i]);
}
LOG_F(RRC,"\n");
#endif
LOG_D(RRC,
PROTOCOL_RRC_CTXT_UE_FMT"MAC_eNB--- MAC_DATA_IND (rrcConnectionReestablishmentRequest on SRB0) --> RRC_eNB\n",
PROTOCOL_RRC_CTXT_UE_ARGS(ctxt_pP));
@@ -6336,15 +6245,10 @@ rrc_eNB_decode_ccch(
T(T_ENB_RRC_CONNECTION_REQUEST, T_INT(ctxt_pP->module_id), T_INT(ctxt_pP->frame),
T_INT(ctxt_pP->subframe), T_INT(ctxt_pP->rnti));
#ifdef RRC_MSG_PRINT
LOG_F(RRC,"[MSG] RRC Connection Request\n");
LOG_DUMPMSG(RRC,DEBUG_RRC,(char *)(Srb_info->Rx_buffer.Payload),
Srb_info->Rx_buffer.payload_size,
"[MSG] RRC Connection Request\n");
for (i = 0; i < Srb_info->Rx_buffer.payload_size; i++) {
LOG_F(RRC,"%02x ", ((uint8_t*)Srb_info->Rx_buffer.Payload)[i]);
}
LOG_F(RRC,"\n");
#endif
LOG_D(RRC,
PROTOCOL_RRC_CTXT_UE_FMT"MAC_eNB --- MAC_DATA_IND (rrcConnectionRequest on SRB0) --> RRC_eNB\n",
PROTOCOL_RRC_CTXT_UE_ARGS(ctxt_pP));
@@ -6631,36 +6535,7 @@ rrc_eNB_decode_dcch(
sdu_sizeP,
0,
0);
/*
#if defined(ENABLE_ITTI)
# if defined(DISABLE_ITTI_XER_PRINT)
{
MessageDef *message_p;
message_p = itti_alloc_new_message(TASK_RRC_ENB, RRC_UL_DCCH_MESSAGE);
memcpy(&message_p->ittiMsg, (void *)ul_dcch_msg, sizeof(RrcUlDcchMessage));
itti_send_msg_to_task(TASK_UNKNOWN, ctxt_pP->instance, message_p);
}
# else
{
char message_string[10000];
size_t message_string_size;
if ((message_string_size =
xer_sprint(message_string, sizeof(message_string), &asn_DEF_UL_DCCH_Message, (void *)ul_dcch_msg)) >= 0) {
MessageDef *msg_p;
msg_p = itti_alloc_new_message_sized(TASK_RRC_ENB, RRC_UL_DCCH, message_string_size + sizeof(IttiMsgText));
msg_p->ittiMsg.rrc_ul_dcch.size = message_string_size;
memcpy(&msg_p->ittiMsg.rrc_ul_dcch.text, message_string, message_string_size);
itti_send_msg_to_task(TASK_UNKNOWN, ctxt_pP->instance, msg_p);
}
}
# endif
#endif
*/
{
for (i = 0; i < sdu_sizeP; i++) {
LOG_T(RRC, "%x.", Rx_sdu[i]);
@@ -6714,15 +6589,9 @@ rrc_eNB_decode_dcch(
LOG_I(RRC, "Processing RRCConnectionReconfigurationComplete UE %x, ue_context_p is NULL\n", ctxt_pP->rnti);
break;
}
#ifdef RRC_MSG_PRINT
LOG_F(RRC,"[MSG] RRC Connection Reconfiguration Complete\n");
LOG_DUMPMSG(RRC,DEBUG_RRC,(char *)(Rx_sdu),sdu_sizeP,
"[MSG] RRC Connection Reconfiguration Complete\n");
for (i = 0; i < sdu_sizeP; i++) {
LOG_F(RRC,"%02x ", ((uint8_t*)Rx_sdu)[i]);
}
LOG_F(RRC,"\n");
#endif
MSC_LOG_RX_MESSAGE(
MSC_RRC_ENB,
MSC_RRC_UE,
@@ -6745,42 +6614,42 @@ rrc_eNB_decode_dcch(
RRCConnectionReconfigurationComplete__criticalExtensions_PR_rrcConnectionReconfigurationComplete_r8) {
/*NN: revise the condition */
/*FK: left the condition as is for the case MME is used (S1 mode) but setting dedicated_DRB = 1 otherwise (noS1 mode) so that no second RRCReconfiguration message activationg more DRB is sent as this causes problems with the nasmesh driver.*/
#if defined(ENABLE_USE_MME)
if (ue_context_p->ue_context.Status == RRC_RECONFIGURED){
dedicated_DRB = 1;
LOG_I(RRC,
PROTOCOL_RRC_CTXT_UE_FMT" UE State = RRC_RECONFIGURED (dedicated DRB, xid %ld)\n",
PROTOCOL_RRC_CTXT_UE_ARGS(ctxt_pP),ul_dcch_msg->message.choice.c1.choice.rrcConnectionReconfigurationComplete.rrc_TransactionIdentifier);
//clear
int16_t UE_id = find_UE_id(ctxt_pP->module_id, ctxt_pP->rnti);
if(UE_id == -1){
LOG_E(RRC,
PROTOCOL_RRC_CTXT_UE_FMT" RRCConnectionReconfigurationComplete without rnti %x, fault\n",
PROTOCOL_RRC_CTXT_UE_ARGS(ctxt_pP),ctxt_pP->rnti);
break;
}
if(RC.mac[ctxt_pP->module_id]->UE_list.UE_sched_ctrl[UE_id].crnti_reconfigurationcomplete_flag == 1){
LOG_I(RRC,
PROTOCOL_RRC_CTXT_UE_FMT" UE State = RRC_RECONFIGURED (dedicated DRB, xid %ld) C-RNTI Complete\n",
PROTOCOL_RRC_CTXT_UE_ARGS(ctxt_pP),ul_dcch_msg->message.choice.c1.choice.rrcConnectionReconfigurationComplete.rrc_TransactionIdentifier);
dedicated_DRB = 2;
RC.mac[ctxt_pP->module_id]->UE_list.UE_sched_ctrl[UE_id].crnti_reconfigurationcomplete_flag = 0;
}
} else {
dedicated_DRB = 0;
ue_context_p->ue_context.Status = RRC_RECONFIGURED;
LOG_I(RRC,
PROTOCOL_RRC_CTXT_UE_FMT" UE State = RRC_RECONFIGURED (default DRB, xid %ld)\n",
PROTOCOL_RRC_CTXT_UE_ARGS(ctxt_pP),ul_dcch_msg->message.choice.c1.choice.rrcConnectionReconfigurationComplete.rrc_TransactionIdentifier);
}
ue_context_p->ue_context.reestablishment_xid = -1;
#else
dedicated_DRB = 1;
ue_context_p->ue_context.Status = RRC_RECONFIGURED;
LOG_I(RRC,
PROTOCOL_RRC_CTXT_UE_FMT" UE State = RRC_RECONFIGURED (dedicated DRB, xid %ld)\n",
PROTOCOL_RRC_CTXT_UE_ARGS(ctxt_pP),ul_dcch_msg->message.choice.c1.choice.rrcConnectionReconfigurationComplete.rrc_TransactionIdentifier);
#endif
if (EPC_MODE_ENABLED) {
if (ue_context_p->ue_context.Status == RRC_RECONFIGURED){
dedicated_DRB = 1;
LOG_I(RRC,
PROTOCOL_RRC_CTXT_UE_FMT" UE State = RRC_RECONFIGURED (dedicated DRB, xid %ld)\n",
PROTOCOL_RRC_CTXT_UE_ARGS(ctxt_pP),ul_dcch_msg->message.choice.c1.choice.rrcConnectionReconfigurationComplete.rrc_TransactionIdentifier);
//clear
int16_t UE_id = find_UE_id(ctxt_pP->module_id, ctxt_pP->rnti);
if(UE_id == -1){
LOG_E(RRC,
PROTOCOL_RRC_CTXT_UE_FMT" RRCConnectionReconfigurationComplete without rnti %x, fault\n",
PROTOCOL_RRC_CTXT_UE_ARGS(ctxt_pP),ctxt_pP->rnti);
break;
}
if(RC.mac[ctxt_pP->module_id]->UE_list.UE_sched_ctrl[UE_id].crnti_reconfigurationcomplete_flag == 1){
LOG_I(RRC,
PROTOCOL_RRC_CTXT_UE_FMT" UE State = RRC_RECONFIGURED (dedicated DRB, xid %ld) C-RNTI Complete\n",
PROTOCOL_RRC_CTXT_UE_ARGS(ctxt_pP),ul_dcch_msg->message.choice.c1.choice.rrcConnectionReconfigurationComplete.rrc_TransactionIdentifier);
dedicated_DRB = 2;
RC.mac[ctxt_pP->module_id]->UE_list.UE_sched_ctrl[UE_id].crnti_reconfigurationcomplete_flag = 0;
}
} else {
dedicated_DRB = 0;
ue_context_p->ue_context.Status = RRC_RECONFIGURED;
LOG_I(RRC,
PROTOCOL_RRC_CTXT_UE_FMT" UE State = RRC_RECONFIGURED (default DRB, xid %ld)\n",
PROTOCOL_RRC_CTXT_UE_ARGS(ctxt_pP),ul_dcch_msg->message.choice.c1.choice.rrcConnectionReconfigurationComplete.rrc_TransactionIdentifier);
}
ue_context_p->ue_context.reestablishment_xid = -1;
} else {
dedicated_DRB = 1;
ue_context_p->ue_context.Status = RRC_RECONFIGURED;
LOG_I(RRC,
PROTOCOL_RRC_CTXT_UE_FMT" UE State = RRC_RECONFIGURED (dedicated DRB, xid %ld)\n",
PROTOCOL_RRC_CTXT_UE_ARGS(ctxt_pP),ul_dcch_msg->message.choice.c1.choice.rrcConnectionReconfigurationComplete.rrc_TransactionIdentifier);
}
rrc_eNB_process_RRCConnectionReconfigurationComplete(
ctxt_pP,
@@ -6789,14 +6658,13 @@ rrc_eNB_decode_dcch(
//WARNING:Inform the controller about the UE activation. Should be moved to RRC agent in the future
if (rrc_agent_registered[ctxt_pP->module_id]) {
agent_rrc_xface[ctxt_pP->eNB_index]->flexran_agent_notify_ue_state_change(ctxt_pP->module_id,
agent_rrc_xface[ctxt_pP->module_id]->flexran_agent_notify_ue_state_change(ctxt_pP->module_id,
ue_context_p->ue_id_rnti,
PROTOCOL__FLEX_UE_STATE_CHANGE_TYPE__FLUESC_UPDATED);
}
}
#if defined(ENABLE_ITTI)
# if defined(ENABLE_USE_MME)
if (EPC_MODE_ENABLED == 1) {
#if defined(ENABLE_USE_MME)
if (dedicated_DRB == 1){
// rrc_eNB_send_S1AP_E_RAB_SETUP_RESP(ctxt_pP,
// ue_context_p,
@@ -6861,14 +6729,12 @@ if (ue_context_p->ue_context.nb_of_modify_e_rabs > 0) {
}
}
}
}
#endif
#else // establish a dedicated bearer
if (dedicated_DRB == 0 ) {
// ue_context_p->ue_context.e_rab[0].status = E_RAB_STATUS_ESTABLISHED;
rrc_eNB_reconfigure_DRBs(ctxt_pP,ue_context_p);
}
#endif
#endif
break;
@@ -6876,15 +6742,8 @@ if (ue_context_p->ue_context.nb_of_modify_e_rabs > 0) {
T(T_ENB_RRC_CONNECTION_REESTABLISHMENT_COMPLETE, T_INT(ctxt_pP->module_id), T_INT(ctxt_pP->frame),
T_INT(ctxt_pP->subframe), T_INT(ctxt_pP->rnti));
#ifdef RRC_MSG_PRINT
LOG_F(RRC,"[MSG] RRC Connection Reestablishment Complete\n");
for (i = 0; i < sdu_sizeP; i++) {
LOG_F(RRC,"%02x ", ((uint8_t*)Rx_sdu)[i]);
}
LOG_F(RRC,"\n");
#endif
LOG_DUMPMSG(RRC,DEBUG_RRC,(char *)Rx_sdu,sdu_sizeP,
"[MSG] RRC Connection Reestablishment Complete\n");
MSC_LOG_RX_MESSAGE(
MSC_RRC_ENB,
@@ -6945,7 +6804,7 @@ if (ue_context_p->ue_context.nb_of_modify_e_rabs > 0) {
//WARNING:Inform the controller about the UE activation. Should be moved to RRC agent in the future
if (mac_agent_registered[ctxt_pP->module_id]) {
agent_rrc_xface[ctxt_pP->eNB_index]->flexran_agent_notify_ue_state_change(ctxt_pP->module_id,
agent_rrc_xface[ctxt_pP->module_id]->flexran_agent_notify_ue_state_change(ctxt_pP->module_id,
ue_context_p->ue_id_rnti,
PROTOCOL__FLEX_UE_STATE_CHANGE_TYPE__FLUESC_ACTIVATED);
}
@@ -6963,15 +6822,8 @@ if (ue_context_p->ue_context.nb_of_modify_e_rabs > 0) {
LOG_I(RRC, "Processing RRCConnectionSetupComplete UE %x, ue_context_p is NULL\n", ctxt_pP->rnti);
break;
}
#ifdef RRC_MSG_PRINT
LOG_F(RRC,"[MSG] RRC Connection SetupComplete\n");
for (i = 0; i < sdu_sizeP; i++) {
LOG_F(RRC,"%02x ", ((uint8_t*)Rx_sdu)[i]);
}
LOG_F(RRC,"\n");
#endif
LOG_DUMPMSG(RRC,DEBUG_RRC,(char *)Rx_sdu,sdu_sizeP,
"[MSG] RRC Connection SetupComplete\n");
MSC_LOG_RX_MESSAGE(
MSC_RRC_ENB,
@@ -7005,7 +6857,7 @@ if (ue_context_p->ue_context.nb_of_modify_e_rabs > 0) {
//WARNING:Inform the controller about the UE activation. Should be moved to RRC agent in the future
if (rrc_agent_registered[ctxt_pP->module_id]) {
agent_rrc_xface[ctxt_pP->eNB_index]->flexran_agent_notify_ue_state_change(ctxt_pP->module_id,
agent_rrc_xface[ctxt_pP->module_id]->flexran_agent_notify_ue_state_change(ctxt_pP->module_id,
ue_context_p->ue_id_rnti,
PROTOCOL__FLEX_UE_STATE_CHANGE_TYPE__FLUESC_ACTIVATED);
}
@@ -7023,15 +6875,9 @@ if (ue_context_p->ue_context.nb_of_modify_e_rabs > 0) {
LOG_I(RRC, "Processing securityModeComplete UE %x, ue_context_p is NULL\n", ctxt_pP->rnti);
break;
}
#ifdef RRC_MSG_PRINT
LOG_F(RRC,"[MSG] RRC Security Mode Complete\n");
LOG_DUMPMSG(RRC,DEBUG_RRC,(char *)Rx_sdu,sdu_sizeP,
"[MSG] RRC Security Mode Complete\n");
for (i = 0; i < sdu_sizeP; i++) eNB->pusch_vars[UE_id]{
LOG_F(RRC,"%02x ", ((uint8_t*)Rx_sdu)[i]);
}
LOG_F(RRC,"\n");
#endif
MSC_LOG_RX_MESSAGE(
MSC_RRC_ENB,
@@ -7053,9 +6899,9 @@ if (ue_context_p->ue_context.nb_of_modify_e_rabs > 0) {
PROTOCOL_RRC_CTXT_UE_ARGS(ctxt_pP),
DCCH,
sdu_sizeP);
#ifdef XER_PRINT
xer_fprint(stdout, &asn_DEF_UL_DCCH_Message, (void *)ul_dcch_msg);
#endif
if ( LOG_DEBUGFLAG(DEBUG_ASN1) ) {
xer_fprint(stdout, &asn_DEF_UL_DCCH_Message, (void *)ul_dcch_msg);
}
// confirm with PDCP about the security mode for DCCH
//rrc_pdcp_config_req (enb_mod_idP, frameP, 1,CONFIG_ACTION_SET_SECURITY_MODE, (ue_mod_idP * NB_RB_MAX) + DCCH, 0x77);
// continue the procedure
@@ -7068,15 +6914,8 @@ if (ue_context_p->ue_context.nb_of_modify_e_rabs > 0) {
T(T_ENB_RRC_SECURITY_MODE_FAILURE, T_INT(ctxt_pP->module_id), T_INT(ctxt_pP->frame),
T_INT(ctxt_pP->subframe), T_INT(ctxt_pP->rnti));
#ifdef RRC_MSG_PRINT
LOG_F(RRC,"[MSG] RRC Security Mode Failure\n");
for (i = 0; i < sdu_sizeP; i++) {
LOG_F(RRC,"%02x ", ((uint8_t*)Rx_sdu)[i]);
}
LOG_F(RRC,"\n");
#endif
LOG_DUMPMSG(RRC,DEBUG_RRC,(char *)Rx_sdu,sdu_sizeP,
"[MSG] RRC Security Mode Failure\n");
MSC_LOG_RX_MESSAGE(
MSC_RRC_ENB,
@@ -7094,9 +6933,9 @@ if (ue_context_p->ue_context.nb_of_modify_e_rabs > 0) {
PROTOCOL_RRC_CTXT_UE_ARGS(ctxt_pP),
DCCH,
sdu_sizeP);
#ifdef XER_PRINT
xer_fprint(stdout, &asn_DEF_UL_DCCH_Message, (void *)ul_dcch_msg);
#endif
if ( LOG_DEBUGFLAG(DEBUG_ASN1) ) {
xer_fprint(stdout, &asn_DEF_UL_DCCH_Message, (void *)ul_dcch_msg);
}
// cancel the security mode in PDCP
// followup with the remaining procedure
@@ -7112,15 +6951,9 @@ if (ue_context_p->ue_context.nb_of_modify_e_rabs > 0) {
LOG_I(RRC, "Processing ueCapabilityInformation UE %x, ue_context_p is NULL\n", ctxt_pP->rnti);
break;
}
#ifdef RRC_MSG_PRINT
LOG_F(RRC,"[MSG] RRC UECapablility Information \n");
for (i = 0; i < sdu_sizeP; i++) {
LOG_F(RRC,"%02x ", ((uint8_t*)Rx_sdu)[i]);
}
LOG_F(RRC,"\n");
#endif
LOG_DUMPMSG(RRC,DEBUG_RRC,(char *)Rx_sdu,sdu_sizeP,
"[MSG] RRC UECapablility Information\n");
MSC_LOG_RX_MESSAGE(
MSC_RRC_ENB,
@@ -7142,9 +6975,9 @@ if (ue_context_p->ue_context.nb_of_modify_e_rabs > 0) {
PROTOCOL_RRC_CTXT_UE_ARGS(ctxt_pP),
DCCH,
sdu_sizeP);
#ifdef XER_PRINT
xer_fprint(stdout, &asn_DEF_UL_DCCH_Message, (void *)ul_dcch_msg);
#endif
if ( LOG_DEBUGFLAG(DEBUG_ASN1) ) {
xer_fprint(stdout, &asn_DEF_UL_DCCH_Message, (void *)ul_dcch_msg);
}
LOG_I(RRC, "got UE capabilities for UE %x\n", ctxt_pP->rnti);
if (ue_context_p->ue_context.UE_Capability) {
LOG_I(RRC, "freeing old UE capabilities for UE %x\n", ctxt_pP->rnti);
@@ -7161,9 +6994,9 @@ if (ue_context_p->ue_context.nb_of_modify_e_rabs > 0) {
ul_dcch_msg->message.choice.c1.choice.ueCapabilityInformation.criticalExtensions.
choice.c1.choice.ueCapabilityInformation_r8.ue_CapabilityRAT_ContainerList.list.
array[0]->ueCapabilityRAT_Container.size, 0, 0);
#ifdef XER_PRINT
xer_fprint(stdout, &asn_DEF_UE_EUTRA_Capability, ue_context_p->ue_context.UE_Capability);
#endif
if ( LOG_DEBUGFLAG(DEBUG_ASN1) ) {
xer_fprint(stdout, &asn_DEF_UE_EUTRA_Capability, ue_context_p->ue_context.UE_Capability);
}
if ((dec_rval.code != RC_OK) && (dec_rval.consumed == 0)) {
LOG_E(RRC, PROTOCOL_RRC_CTXT_UE_FMT" Failed to decode UE capabilities (%zu bytes)\n",
@@ -7174,22 +7007,22 @@ if (ue_context_p->ue_context.nb_of_modify_e_rabs > 0) {
ue_context_p->ue_context.UE_Capability = 0;
}
#if defined(ENABLE_USE_MME)
if (EPC_MODE_ENABLED) {
if (EPC_MODE_ENABLED == 1) {
rrc_eNB_send_S1AP_UE_CAPABILITIES_IND(ctxt_pP,
ue_context_p,
ul_dcch_msg);
if (EPC_MODE_ENABLED == 1) {
rrc_eNB_send_S1AP_UE_CAPABILITIES_IND(ctxt_pP,
ue_context_p,
ul_dcch_msg);
}
} else {
ue_context_p->ue_context.nb_of_e_rabs = 1;
for (i = 0; i < ue_context_p->ue_context.nb_of_e_rabs; i++){
ue_context_p->ue_context.e_rab[i].status = E_RAB_STATUS_NEW;
ue_context_p->ue_context.e_rab[i].param.e_rab_id = 1+i;
ue_context_p->ue_context.e_rab[i].param.qos.qci=9;
}
ue_context_p->ue_context.setup_e_rabs =ue_context_p->ue_context.nb_of_e_rabs;
}
#else
ue_context_p->ue_context.nb_of_e_rabs = 1;
for (i = 0; i < ue_context_p->ue_context.nb_of_e_rabs; i++){
ue_context_p->ue_context.e_rab[i].status = E_RAB_STATUS_NEW;
ue_context_p->ue_context.e_rab[i].param.e_rab_id = 1+i;
ue_context_p->ue_context.e_rab[i].param.qos.qci=9;
}
ue_context_p->ue_context.setup_e_rabs =ue_context_p->ue_context.nb_of_e_rabs;
#endif
rrc_eNB_generate_defaultRRCConnectionReconfiguration(ctxt_pP,
ue_context_p,
@@ -7212,16 +7045,8 @@ if (ue_context_p->ue_context.nb_of_modify_e_rabs > 0) {
}
LOG_D(RRC,"[MSG] RRC UL Information Transfer \n");
#ifdef RRC_MSG_PRINT
LOG_F(RRC,"[MSG] RRC UL Information Transfer \n");
for (i = 0; i < sdu_sizeP; i++) {
LOG_F(RRC,"%02x ", ((uint8_t*)Rx_sdu)[i]);
}
LOG_F(RRC,"\n");
#endif
LOG_DUMPMSG(RRC,DEBUG_RRC,(char *)Rx_sdu,sdu_sizeP,
"[MSG] RRC UL Information Transfer \n");
MSC_LOG_RX_MESSAGE(
MSC_RRC_ENB,
@@ -7233,15 +7058,11 @@ if (ue_context_p->ue_context.nb_of_modify_e_rabs > 0) {
ue_context_p->ue_context.rnti,
sdu_sizeP);
#if defined(ENABLE_USE_MME)
if (EPC_MODE_ENABLED == 1) {
rrc_eNB_send_S1AP_UPLINK_NAS(ctxt_pP,
ue_context_p,
ul_dcch_msg);
}
#endif
break;
case UL_DCCH_MessageType__c1_PR_counterCheckResponse:
@@ -7307,15 +7128,8 @@ if (ue_context_p->ue_context.nb_of_modify_e_rabs > 0) {
//case UL_DCCH_MessageType__messageClassExtension__c2_PR_sidelinkUEInformation_r12: //SidelinkUEInformation
LOG_I(RRC,"THINH [UL_DCCH_MessageType__messageClassExtension_PR_c2]\n");
#ifdef RRC_MSG_PRINT
LOG_F(RRC,"[MSG] SidelinkUEInformation\n");
for (i = 0; i < sdu_sizeP; i++) {
LOG_F(RRC,"%02x ", ((uint8_t*)Rx_sdu)[i]);
}
LOG_F(RRC,"\n");
#endif
LOG_DUMPMSG(RRC,DEBUG_RRC,(char *)Rx_sdu,sdu_sizeP,
"[MSG] RRC SidelinkUEInformation \n");
MSC_LOG_RX_MESSAGE(
MSC_RRC_ENB,
@@ -7387,29 +7201,24 @@ void rrc_eNB_reconfigure_DRBs (const protocol_ctxt_t* const ctxt_pP,
rrc_eNB_generate_dedicatedRRCConnectionReconfiguration(ctxt_pP, ue_context_pP, 0);
}
//-----------------------------------------------------------------------------
void*
rrc_enb_task(
void* args_p
)
//-----------------------------------------------------------------------------
{
MessageDef *msg_p;
const char *msg_name_p;
instance_t instance;
int result;
SRB_INFO *srb_info_p;
int CC_id;
protocol_ctxt_t ctxt;
void rrc_enb_init(void) {
pthread_mutex_init(&lock_ue_freelist, NULL);
pthread_mutex_init(&rrc_release_freelist, NULL);
memset(&rrc_release_info,0,sizeof(RRC_release_list_t));
itti_mark_task_ready(TASK_RRC_ENB);
LOG_I(RRC,"Entering main loop of RRC message task\n");
while (1) {
}
//-----------------------------------------------------------------------------
void *rrc_enb_process_itti_msg(void *notUsed) {
MessageDef *msg_p;
const char *msg_name_p;
instance_t instance;
int result;
SRB_INFO *srb_info_p;
int CC_id;
protocol_ctxt_t ctxt;
// Wait for a message
itti_receive_msg(TASK_RRC_ENB, &msg_p);
@@ -7549,9 +7358,28 @@ rrc_enb_task(
result = itti_free(ITTI_MSG_ORIGIN_ID(msg_p), msg_p);
if (result != EXIT_SUCCESS) {
LOG_I(RRC, "Failed to free memory (%d)!\n",result);
continue;
}
msg_p = NULL;
return NULL;
}
//-----------------------------------------------------------------------------
void*
rrc_enb_task(
void* args_p
)
//-----------------------------------------------------------------------------
{
rrc_enb_init();
itti_mark_task_ready(TASK_RRC_ENB);
LOG_I(RRC,"Entering main loop of RRC message task\n");
while (1) {
(void) rrc_enb_process_itti_msg(NULL);
}
}
#endif
+135 -165
View File
@@ -467,43 +467,20 @@ rrc_pdcp_config_security(
&kRRCint);
#if !defined(USRP_REC_PLAY)
#define DEBUG_SECURITY 1
SET_LOG_DUMP(DEBUG_SECURITY) ;
#endif
#if defined (DEBUG_SECURITY)
#undef msg
#define msg printf
if (print_keys ==1 ) {
print_keys =0;
int i;
msg("\nKeNB:");
if ( LOG_DUMPFLAG( DEBUG_SECURITY ) ) {
if (print_keys ==1 ) {
print_keys =0;
for(i = 0; i < 32; i++) {
msg("%02x", ue_context_pP->ue_context.kenb[i]);
LOG_DUMPMSG(RRC, DEBUG_SECURITY, ue_context_pP->ue_context.kenb, 32,"\nKeNB:" );
LOG_DUMPMSG(RRC, DEBUG_SECURITY, kRRCenc, 32,"\nKRRCenc:" );
LOG_DUMPMSG(RRC, DEBUG_SECURITY, kRRCint, 32,"\nKRRCint:" );
}
msg("\n");
msg("\nKRRCenc:");
for(i = 0; i < 32; i++) {
msg("%02x", kRRCenc[i]);
}
msg("\n");
msg("\nKRRCint:");
for(i = 0; i < 32; i++) {
msg("%02x", kRRCint[i]);
}
msg("\n");
}
#endif //DEBUG_SECURITY
key = PDCP_COLL_KEY_VALUE(ctxt_pP->module_id, ctxt_pP->rnti, ctxt_pP->enb_flag, DCCH, SRB_FLAG_YES);
h_rc = hashtable_get(pdcp_coll_p, key, (void**)&pdcp_p);
@@ -778,17 +755,20 @@ rrc_eNB_send_S1AP_NAS_FIRST_REQ(
ue_context_pP->ue_context.rnti);
}
/* selected_plmn_identity: IE is 1-based, convert to 0-based (C array) */
int selected_plmn_identity = rrcConnectionSetupComplete->selectedPLMN_Identity - 1;
S1AP_NAS_FIRST_REQ(message_p).selected_plmn_identity = selected_plmn_identity;
if (rrcConnectionSetupComplete->registeredMME != NULL) {
/* Fill GUMMEI */
struct RegisteredMME *r_mme = rrcConnectionSetupComplete->registeredMME;
//int selected_plmn_identity = rrcConnectionSetupComplete->selectedPLMN_Identity;
S1AP_NAS_FIRST_REQ (message_p).ue_identity.presenceMask |= UE_IDENTITIES_gummei;
if (r_mme->plmn_Identity != NULL) {
if ((r_mme->plmn_Identity->mcc != NULL) && (r_mme->plmn_Identity->mcc->list.count > 0)) {
/* Use first indicated PLMN MCC if it is defined */
S1AP_NAS_FIRST_REQ (message_p).ue_identity.gummei.mcc = *r_mme->plmn_Identity->mcc->list.array[0];
S1AP_NAS_FIRST_REQ (message_p).ue_identity.gummei.mcc = *r_mme->plmn_Identity->mcc->list.array[selected_plmn_identity];
LOG_I(S1AP, "[eNB %d] Build S1AP_NAS_FIRST_REQ adding in s_TMSI: GUMMEI MCC %u ue %x\n",
ctxt_pP->module_id,
S1AP_NAS_FIRST_REQ (message_p).ue_identity.gummei.mcc,
@@ -797,20 +777,16 @@ rrc_eNB_send_S1AP_NAS_FIRST_REQ(
if (r_mme->plmn_Identity->mnc.list.count > 0) {
/* Use first indicated PLMN MNC if it is defined */
S1AP_NAS_FIRST_REQ (message_p).ue_identity.gummei.mnc = *r_mme->plmn_Identity->mnc.list.array[0];
S1AP_NAS_FIRST_REQ (message_p).ue_identity.gummei.mnc = *r_mme->plmn_Identity->mnc.list.array[selected_plmn_identity];
LOG_I(S1AP, "[eNB %d] Build S1AP_NAS_FIRST_REQ adding in s_TMSI: GUMMEI MNC %u ue %x\n",
ctxt_pP->module_id,
S1AP_NAS_FIRST_REQ (message_p).ue_identity.gummei.mnc,
ue_context_pP->ue_context.rnti);
}
} else {
// const Enb_properties_array_t *enb_properties_p = NULL;
// enb_properties_p = enb_config_get();
// actually the eNB configuration contains only one PLMN (can be up to 6)
S1AP_NAS_FIRST_REQ (message_p).ue_identity.gummei.mcc = rrc->mcc;
S1AP_NAS_FIRST_REQ (message_p).ue_identity.gummei.mnc = rrc->mnc;
S1AP_NAS_FIRST_REQ (message_p).ue_identity.gummei.mnc_len = rrc->mnc_digit_length;
S1AP_NAS_FIRST_REQ(message_p).ue_identity.gummei.mcc = rrc->configuration.mcc[selected_plmn_identity];
S1AP_NAS_FIRST_REQ(message_p).ue_identity.gummei.mnc = rrc->configuration.mnc[selected_plmn_identity];
S1AP_NAS_FIRST_REQ(message_p).ue_identity.gummei.mnc_len = rrc->configuration.mnc_digit_length[selected_plmn_identity];
}
S1AP_NAS_FIRST_REQ (message_p).ue_identity.gummei.mme_code = BIT_STRING_to_uint8 (&r_mme->mmec);
@@ -945,16 +921,8 @@ rrc_eNB_process_S1AP_DOWNLINK_NAS(
S1AP_DOWNLINK_NAS (msg_p).nas_pdu.length,
S1AP_DOWNLINK_NAS (msg_p).nas_pdu.buffer);
#ifdef RRC_MSG_PRINT
int i=0;
LOG_F(RRC,"[MSG] RRC DL Information Transfer\n");
LOG_DUMPMSG(RRC,DEBUG_RRC,buffer,length,"[MSG] RRC DL Information Transfer\n");
for (i = 0; i < length; i++) {
LOG_F(RRC,"%02x ", ((uint8_t*)buffer)[i]);
}
LOG_F(RRC,"\n");
#endif
/*
* switch UL or DL NAS message without RRC piggybacked to SRB2 if active.
*/
@@ -1881,125 +1849,127 @@ int rrc_eNB_process_PAGING_IND(MessageDef *msg_p, const char *msg_name, instance
for (uint16_t tai_size = 0; tai_size < S1AP_PAGING_IND(msg_p).tai_size; tai_size++) {
LOG_D(RRC,"[eNB %d] In S1AP_PAGING_IND: MCC %d, MNC %d, TAC %d\n", instance, S1AP_PAGING_IND(msg_p).plmn_identity[tai_size].mcc,
S1AP_PAGING_IND(msg_p).plmn_identity[tai_size].mnc, S1AP_PAGING_IND(msg_p).tac[tai_size]);
if (RC.rrc[instance]->configuration.mcc == S1AP_PAGING_IND(msg_p).plmn_identity[tai_size].mcc
&& RC.rrc[instance]->configuration.mnc == S1AP_PAGING_IND(msg_p).plmn_identity[tai_size].mnc
&& RC.rrc[instance]->configuration.tac == S1AP_PAGING_IND(msg_p).tac[tai_size]) {
for (uint8_t CC_id = 0; CC_id < MAX_NUM_CCs; CC_id++) {
lte_frame_type_t frame_type = RC.eNB[instance][CC_id]->frame_parms.frame_type;
/* get nB from configuration */
/* get default DRX cycle from configuration */
Tc = (uint8_t)RC.rrc[instance]->configuration.pcch_defaultPagingCycle[CC_id];
if (Tc < PCCH_Config__defaultPagingCycle_rf32 || Tc > PCCH_Config__defaultPagingCycle_rf256) {
continue;
}
Tue = (uint8_t)S1AP_PAGING_IND(msg_p).paging_drx;
/* set T = min(Tc,Tue) */
T = Tc < Tue ? Ttab[Tc] : Ttab[Tue];
/* set pcch_nB = PCCH-Config->nB */
pcch_nB = (uint32_t)RC.rrc[instance]->configuration.pcch_nB[CC_id];
switch (pcch_nB) {
case PCCH_Config__nB_fourT:
Ns = 4;
break;
case PCCH_Config__nB_twoT:
Ns = 2;
break;
default:
Ns = 1;
break;
}
/* set N = min(T,nB) */
if (pcch_nB > PCCH_Config__nB_oneT) {
switch (pcch_nB) {
case PCCH_Config__nB_halfT:
N = T/2;
break;
case PCCH_Config__nB_quarterT:
N = T/4;
break;
case PCCH_Config__nB_oneEighthT:
N = T/8;
break;
case PCCH_Config__nB_oneSixteenthT:
N = T/16;
break;
case PCCH_Config__nB_oneThirtySecondT:
N = T/32;
break;
default:
/* pcch_nB error */
LOG_E(RRC, "[eNB %d] In S1AP_PAGING_IND: pcch_nB error (pcch_nB %d) \n",
instance, pcch_nB);
return (-1);
}
} else {
N = T;
}
/* insert data to UE_PF_PO or update data in UE_PF_PO */
pthread_mutex_lock(&ue_pf_po_mutex);
uint16_t i = 0;
for (i = 0; i < MAX_MOBILES_PER_ENB; i++) {
if ((UE_PF_PO[CC_id][i].enable_flag == TRUE && UE_PF_PO[CC_id][i].ue_index_value == (uint16_t)(S1AP_PAGING_IND(msg_p).ue_index_value))
|| (UE_PF_PO[CC_id][i].enable_flag != TRUE)) {
/* set T = min(Tc,Tue) */
UE_PF_PO[CC_id][i].T = T;
/* set UE_ID */
UE_PF_PO[CC_id][i].ue_index_value = (uint16_t)S1AP_PAGING_IND(msg_p).ue_index_value;
/* calculate PF and PO */
/* set PF_min : SFN mod T = (T div N)*(UE_ID mod N) */
UE_PF_PO[CC_id][i].PF_min = (T / N) * (UE_PF_PO[CC_id][i].ue_index_value % N);
/* set PO */
/* i_s = floor(UE_ID/N) mod Ns */
i_s = (uint8_t)((UE_PF_PO[CC_id][i].ue_index_value / N) % Ns);
if (Ns == 1) {
UE_PF_PO[CC_id][i].PO = (frame_type==FDD) ? 9 : 0;
} else if (Ns==2) {
UE_PF_PO[CC_id][i].PO = (frame_type==FDD) ? (4+(5*i_s)) : (5*i_s);
} else if (Ns==4) {
UE_PF_PO[CC_id][i].PO = (frame_type==FDD) ? (4*(i_s&1)+(5*(i_s>>1))) : ((i_s&1)+(5*(i_s>>1)));
for (uint8_t j = 0; j < RC.rrc[instance]->configuration.num_plmn; j++) {
if (RC.rrc[instance]->configuration.mcc[j] == S1AP_PAGING_IND(msg_p).plmn_identity[tai_size].mcc
&& RC.rrc[instance]->configuration.mnc[j] == S1AP_PAGING_IND(msg_p).plmn_identity[tai_size].mnc
&& RC.rrc[instance]->configuration.tac == S1AP_PAGING_IND(msg_p).tac[tai_size]) {
for (uint8_t CC_id = 0; CC_id < MAX_NUM_CCs; CC_id++) {
lte_frame_type_t frame_type = RC.eNB[instance][CC_id]->frame_parms.frame_type;
/* get nB from configuration */
/* get default DRX cycle from configuration */
Tc = (uint8_t)RC.rrc[instance]->configuration.pcch_defaultPagingCycle[CC_id];
if (Tc < PCCH_Config__defaultPagingCycle_rf32 || Tc > PCCH_Config__defaultPagingCycle_rf256) {
continue;
}
Tue = (uint8_t)S1AP_PAGING_IND(msg_p).paging_drx;
/* set T = min(Tc,Tue) */
T = Tc < Tue ? Ttab[Tc] : Ttab[Tue];
/* set pcch_nB = PCCH-Config->nB */
pcch_nB = (uint32_t)RC.rrc[instance]->configuration.pcch_nB[CC_id];
switch (pcch_nB) {
case PCCH_Config__nB_fourT:
Ns = 4;
break;
case PCCH_Config__nB_twoT:
Ns = 2;
break;
default:
Ns = 1;
break;
}
/* set N = min(T,nB) */
if (pcch_nB > PCCH_Config__nB_oneT) {
switch (pcch_nB) {
case PCCH_Config__nB_halfT:
N = T/2;
break;
case PCCH_Config__nB_quarterT:
N = T/4;
break;
case PCCH_Config__nB_oneEighthT:
N = T/8;
break;
case PCCH_Config__nB_oneSixteenthT:
N = T/16;
break;
case PCCH_Config__nB_oneThirtySecondT:
N = T/32;
break;
default:
/* pcch_nB error */
LOG_E(RRC, "[eNB %d] In S1AP_PAGING_IND: pcch_nB error (pcch_nB %d) \n",
instance, pcch_nB);
return (-1);
}
if (UE_PF_PO[CC_id][i].enable_flag == TRUE) {
//paging exist UE log
LOG_D(RRC,"[eNB %d] CC_id %d In S1AP_PAGING_IND: Update exist UE %d, T %d, PF %d, PO %d\n", instance, CC_id, UE_PF_PO[CC_id][i].ue_index_value, T, UE_PF_PO[CC_id][i].PF_min, UE_PF_PO[CC_id][i].PO);
} else {
/* set enable_flag */
UE_PF_PO[CC_id][i].enable_flag = TRUE;
//paging new UE log
LOG_D(RRC,"[eNB %d] CC_id %d In S1AP_PAGING_IND: Insert a new UE %d, T %d, PF %d, PO %d\n", instance, CC_id, UE_PF_PO[CC_id][i].ue_index_value, T, UE_PF_PO[CC_id][i].PF_min, UE_PF_PO[CC_id][i].PO);
}
break;
}
}
pthread_mutex_unlock(&ue_pf_po_mutex);
} else {
N = T;
}
uint32_t length;
uint8_t buffer[RRC_BUF_SIZE];
uint8_t *message_buffer;
/* Transfer data to PDCP */
MessageDef *message_p;
message_p = itti_alloc_new_message (TASK_RRC_ENB, RRC_PCCH_DATA_REQ);
/* Create message for PDCP (DLInformationTransfer_t) */
length = do_Paging (instance,
buffer,
S1AP_PAGING_IND(msg_p).ue_paging_identity,
S1AP_PAGING_IND(msg_p).cn_domain);
if(length == -1)
{
LOG_I(RRC, "do_Paging error");
return -1;
/* insert data to UE_PF_PO or update data in UE_PF_PO */
pthread_mutex_lock(&ue_pf_po_mutex);
uint8_t i = 0;
for (i = 0; i < MAX_MOBILES_PER_ENB; i++) {
if ((UE_PF_PO[CC_id][i].enable_flag == TRUE && UE_PF_PO[CC_id][i].ue_index_value == (uint16_t)(S1AP_PAGING_IND(msg_p).ue_index_value))
|| (UE_PF_PO[CC_id][i].enable_flag != TRUE)) {
/* set T = min(Tc,Tue) */
UE_PF_PO[CC_id][i].T = T;
/* set UE_ID */
UE_PF_PO[CC_id][i].ue_index_value = (uint16_t)S1AP_PAGING_IND(msg_p).ue_index_value;
/* calculate PF and PO */
/* set PF_min : SFN mod T = (T div N)*(UE_ID mod N) */
UE_PF_PO[CC_id][i].PF_min = (T / N) * (UE_PF_PO[CC_id][i].ue_index_value % N);
/* set PO */
/* i_s = floor(UE_ID/N) mod Ns */
i_s = (uint8_t)((UE_PF_PO[CC_id][i].ue_index_value / N) % Ns);
if (Ns == 1) {
UE_PF_PO[CC_id][i].PO = (frame_type==FDD) ? 9 : 0;
} else if (Ns==2) {
UE_PF_PO[CC_id][i].PO = (frame_type==FDD) ? (4+(5*i_s)) : (5*i_s);
} else if (Ns==4) {
UE_PF_PO[CC_id][i].PO = (frame_type==FDD) ? (4*(i_s&1)+(5*(i_s>>1))) : ((i_s&1)+(5*(i_s>>1)));
}
if (UE_PF_PO[CC_id][i].enable_flag == TRUE) {
//paging exist UE log
LOG_D(RRC,"[eNB %d] CC_id %d In S1AP_PAGING_IND: Update exist UE %d, T %d, PF %d, PO %d\n", instance, CC_id, UE_PF_PO[CC_id][i].ue_index_value, T, UE_PF_PO[CC_id][i].PF_min, UE_PF_PO[CC_id][i].PO);
} else {
/* set enable_flag */
UE_PF_PO[CC_id][i].enable_flag = TRUE;
//paging new UE log
LOG_D(RRC,"[eNB %d] CC_id %d In S1AP_PAGING_IND: Insert a new UE %d, T %d, PF %d, PO %d\n", instance, CC_id, UE_PF_PO[CC_id][i].ue_index_value, T, UE_PF_PO[CC_id][i].PF_min, UE_PF_PO[CC_id][i].PO);
}
break;
}
}
pthread_mutex_unlock(&ue_pf_po_mutex);
uint32_t length;
uint8_t buffer[RRC_BUF_SIZE];
uint8_t *message_buffer;
/* Transfer data to PDCP */
MessageDef *message_p;
message_p = itti_alloc_new_message (TASK_RRC_ENB, RRC_PCCH_DATA_REQ);
/* Create message for PDCP (DLInformationTransfer_t) */
length = do_Paging (instance,
buffer,
S1AP_PAGING_IND(msg_p).ue_paging_identity,
S1AP_PAGING_IND(msg_p).cn_domain);
if(length == -1)
{
LOG_I(RRC, "do_Paging error");
return -1;
}
message_buffer = itti_malloc (TASK_RRC_ENB, TASK_PDCP_ENB, length);
/* Uses a new buffer to avoid issue with PDCP buffer content that could be changed by PDCP (asynchronous message handling). */
memcpy (message_buffer, buffer, length);
RRC_PCCH_DATA_REQ (message_p).sdu_size = length;
RRC_PCCH_DATA_REQ (message_p).sdu_p = message_buffer;
RRC_PCCH_DATA_REQ (message_p).mode = PDCP_TRANSMISSION_MODE_TRANSPARENT; /* not used */
RRC_PCCH_DATA_REQ (message_p).rnti = P_RNTI;
RRC_PCCH_DATA_REQ (message_p).ue_index = i;
RRC_PCCH_DATA_REQ (message_p).CC_id = CC_id;
LOG_D(RRC, "[eNB %d] CC_id %d In S1AP_PAGING_IND: send encdoed buffer to PDCP buffer_size %d\n", instance, CC_id, length);
itti_send_msg_to_task (TASK_PDCP_ENB, instance, message_p);
}
message_buffer = itti_malloc (TASK_RRC_ENB, TASK_PDCP_ENB, length);
/* Uses a new buffer to avoid issue with PDCP buffer content that could be changed by PDCP (asynchronous message handling). */
memcpy (message_buffer, buffer, length);
RRC_PCCH_DATA_REQ (message_p).sdu_size = length;
RRC_PCCH_DATA_REQ (message_p).sdu_p = message_buffer;
RRC_PCCH_DATA_REQ (message_p).mode = PDCP_TRANSMISSION_MODE_TRANSPARENT; /* not used */
RRC_PCCH_DATA_REQ (message_p).rnti = P_RNTI;
RRC_PCCH_DATA_REQ (message_p).ue_index = i;
RRC_PCCH_DATA_REQ (message_p).CC_id = CC_id;
LOG_D(RRC, "[eNB %d] CC_id %d In S1AP_PAGING_IND: send encdoed buffer to PDCP buffer_size %d\n", instance, CC_id, length);
itti_send_msg_to_task (TASK_PDCP_ENB, instance, message_p);
}
}
}
+1 -1
View File
@@ -75,7 +75,7 @@ extern uint32_t timeToTrigger_ms[16];
extern float RSRP_meas_mapping[98];
extern float RSRQ_meas_mapping[35];
extern UE_PF_PO_t UE_PF_PO[MAX_NUM_CCs][MAX_MOBILES_PER_ENB];
extern UE_PF_PO_t UE_PF_PO[NFAPI_CC_MAX][MAX_MOBILES_PER_ENB];
extern pthread_mutex_t ue_pf_po_mutex;
extern uint16_t reestablish_rnti_map[MAX_MOBILES_PER_ENB][2];
+4
View File
@@ -336,6 +336,10 @@ rrc_eNB_reconfigure_DRBs (const protocol_ctxt_t* const ctxt_pP,
rrc_eNB_ue_context_t* ue_context_pP);
#if defined(ENABLE_ITTI)
void rrc_enb_init(void);
void *rrc_enb_process_itti_msg(void *);
/**\brief RRC eNB task.
\param void *args_p Pointer on arguments to start the task. */
void *rrc_enb_task(void *args_p);
+1 -1
View File
@@ -36,7 +36,7 @@
#include "COMMON/mac_rrc_primitives.h"
#include "LAYER2/MAC/mac.h"
UE_PF_PO_t UE_PF_PO[MAX_NUM_CCs][MAX_MOBILES_PER_ENB];
UE_PF_PO_t UE_PF_PO[NFAPI_CC_MAX][MAX_MOBILES_PER_ENB];
pthread_mutex_t ue_pf_po_mutex;
UE_RRC_INST *UE_rrc_inst;
#include "LAYER2/MAC/mac_extern.h"
+35
View File
@@ -44,6 +44,8 @@
#include<linux/types.h>
#include<stdlib.h>
#include<sys/queue.h>
#include <string.h>
#include "UTIL/MEM/mem_block.h"
@@ -103,4 +105,37 @@ void totable (double*, struct list*);
int compare (const void * a, const void * b);
int32_t calculate_median(struct list *loc_list);
typedef struct {
size_t size;
size_t mallocedSize;
size_t atomSize;
size_t increment;
} varArray_t;
static inline varArray_t * initVarArray(size_t increment, size_t atomSize) {
varArray_t * tmp=malloc(sizeof(varArray_t)+increment*atomSize);
tmp->size=0;
tmp->atomSize=atomSize;
tmp->mallocedSize=increment;
tmp->increment=increment;
return(tmp);
}
static inline void * dataArray(varArray_t * input) {
return input+1;
}
static inline void appendVarArray(varArray_t * input, void* data) {
if (input->size>=input->mallocedSize) {
input->mallocedSize+=input->increment;
input=realloc(input,sizeof(varArray_t)+input->mallocedSize*input->atomSize);
}
memcpy((uint8_t*)(input+1)+input->atomSize*input->size++, data, input->atomSize);
}
static inline void freeVarArray(varArray_t * input) {
free(input);
}
#endif
+2
View File
@@ -61,6 +61,7 @@ uint32_t counters[14] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
/*
* initialize all ures
*/
extern mem_pool *memBlockVar;
void *
pool_buffer_init (void)
{
@@ -68,6 +69,7 @@ pool_buffer_init (void)
uint32_t index, mb_index, pool_index;
mem_pool *memory = (mem_pool *) &mem_block_var;
memBlockVar=malloc(sizeof(mem_pool));
int pool_sizes[14] = { MEM_MNGT_MB0_NB_BLOCKS, MEM_MNGT_MB1_NB_BLOCKS,
MEM_MNGT_MB2_NB_BLOCKS, MEM_MNGT_MB3_NB_BLOCKS,
MEM_MNGT_MB4_NB_BLOCKS, MEM_MNGT_MB5_NB_BLOCKS,
+10 -2
View File
@@ -32,12 +32,17 @@
# define __MEM_BLOCK_H__
#include <stdint.h>
#include <stddef.h>
#ifdef __cplusplus
extern "C" {
#endif
#include "openair2/COMMON/platform_constants.h"
//-----------------------------------------------------------------------------
typedef struct mem_block_t {
struct mem_block_t *next;
struct mem_block_t *previous;
size_t size;
unsigned char pool_id;
unsigned char *data;
} mem_block_t;
@@ -173,7 +178,10 @@ typedef struct {
} mem_pool;
mem_pool mem_block_var;
mem_pool *memBlockVar;
#define mem_block_var (*memBlockVar)
#ifdef __cplusplus
}
#endif
#endif
+5 -1
View File
@@ -1,9 +1,13 @@
2012 07 10 - Working version
How to configure wireshark for dissecting LTE protocols:
- start the wireshark as a sudoers
- goto analyze->enabled prototols
=> enable mac_lte_udp and rlc_lte_udp
- goto edit/preferences and expand Protocols
- select UDP and check "try heuristic sub-dissectors first"
- select MAC-LTE, and check all the options (checkboxes), and set the "which layer info to show in info column" to "MAC info"
- select RLC-LTE, and check all the options except the "May see RLC headers only", and set the "call PDCP dissector for DRB PDUs" to "12-bit SN". Optionally you may select the sequence analysis for RLC AM/UM.
How to use
- start eNB or UE with option -W (or -P if you want to make a pcap file)
- capture on local interface "lo"
- filter out the ICMP/DNS/TCP messages (e.g. "!icmp && !dns && !tcp")
+1 -8
View File
@@ -42,11 +42,4 @@ typedef struct MAC_Context_Info_t {
unsigned int subframesSinceCaptureStart;
} MAC_Context_Info_t;
pcap_hdr_t file_header = {
0xa1b2c3d4, /* magic number */
2, 4, /* version number is 2.4 */
0, /* timezone */
0, /* sigfigs - apparently all tools do this */
65535, /* snaplen - this should be long enough */
MAC_LTE_DLT /* Data Link Type (DLT). Set as unused value 147 for now */
};
+12 -2
View File
@@ -55,6 +55,16 @@ This header file must be included */
#include "PHY/impl_defs_lte.h"
#endif
#define PACKET_MAC_LTE_DEFAULT_UDP_PORT (9999)
typedef uint8_t guint8;
typedef uint16_t guint16;
typedef uint32_t guint32;
typedef guint8 gboolean;
#include "packet-mac-lte.h"
#include "mac_pcap.h"
#ifdef OCP_FRAMEWORK
#include <enums.h>
#else
@@ -74,7 +84,7 @@ typedef enum radio_type_e {
extern trace_mode_t opt_type;
extern char in_ip[40];
extern char in_path[100];
extern char in_path[FILENAME_MAX];
/**
* function def
@@ -84,7 +94,7 @@ void trace_pdu(int direction, uint8_t *pdu_buffer, unsigned int pdu_buffer_size,
int ueid, int rntiType, int rnti, uint16_t sysFrame, uint8_t subframe,
int oob_event, int oob_event_value);
int init_opt(char *path, char *ip, char *port, radio_type_t radio_type_p);
int init_opt(char *path, char *ip);
void terminate_opt(void);
+275 -125
View File
@@ -1,41 +1,36 @@
/* packet-mac-lte.h
*
* Martin Mathieson
* $Id: packet-mac-lte.h 42240 2012-04-25 20:02:12Z pascal $
*
* Wireshark - Network traffic analyzer
* By Gerald Combs <gerald@wireshark.org>
* Copyright 1998 Gerald Combs
*
* SPDX-License-Identifier: GPL-2.0-or-later
*
* This header file may also be distributed under
* the terms of the BSD Licence as follows:
*
* Copyright (C) 2009 Martin Mathieson. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY AUTHOR AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL AUTHOR OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE
* SPDX-License-Identifier: BSD-2-Clause
*/
/*
this is wireshark, commit: commit eda834b6e29c36e05a63a6056afa98390ff79357
Date: Wed Aug 22 14:36:20 2018 +0200
modified to be used in OpenAir to create the LTE MAC/RLC encapsulated in UDP as per Wireshark feature
*/
#ifndef PACKET_MAC_LTE_H_
#define PACKET_MAC_LTE_H_
#include "ws_symbol_export.h"
/** data structure to hold time values with nanosecond resolution*/
typedef struct {
time_t secs;
int nsecs;
} nstime_t;
/* radioType */
#define FDD_RADIO 1
@@ -45,105 +40,190 @@
#define DIRECTION_UPLINK 0
#define DIRECTION_DOWNLINK 1
/* SR: no need to declare following part: */
/* rntiType */
#define WS_NO_RNTI 0
#define WS_P_RNTI 1
#define WS_RA_RNTI 2
#define WS_C_RNTI 3
#define WS_SI_RNTI 4
#define WS_SPS_RNTI 5
#define WS_M_RNTI 6
#define WS_SL_BCH_RNTI 7
#define WS_SL_RNTI 8
#define WS_SC_RNTI 9
#define WS_G_RNTI 10
typedef enum mac_lte_oob_event {
ltemac_send_preamble,
ltemac_send_sr,
ltemac_sr_failure
ltemac_send_preamble,
ltemac_send_sr,
ltemac_sr_failure
} mac_lte_oob_event;
typedef enum mac_lte_dl_retx {
dl_retx_no,
dl_retx_yes,
dl_retx_unknown
dl_retx_no,
dl_retx_yes,
dl_retx_unknown
} mac_lte_dl_retx;
typedef enum mac_lte_crc_status {
crc_fail = 0,
crc_success = 1,
crc_high_code_rate = 2,
crc_pdsch_lost = 3,
crc_duplicate_nonzero_rv = 4
crc_fail = 0,
crc_success = 1,
crc_high_code_rate = 2,
crc_pdsch_lost = 3,
crc_duplicate_nonzero_rv = 4,
crc_false_dci = 5
} mac_lte_crc_status;
/* N.B. for SCellIndex-r13 extends to 31 */
typedef enum mac_lte_carrier_id {
carrier_id_primary,
carrier_id_secondary_1,
carrier_id_secondary_2,
carrier_id_secondary_3,
carrier_id_secondary_4,
carrier_id_secondary_5,
carrier_id_secondary_6,
carrier_id_secondary_7
} mac_lte_carrier_id;
typedef enum mac_lte_ce_mode {
no_ce_mode = 0,
ce_mode_a = 1,
ce_mode_b = 2
} mac_lte_ce_mode;
typedef enum mac_lte_nb_mode {
no_nb_mode = 0,
nb_mode = 1
} mac_lte_nb_mode;
/* Context info attached to each LTE MAC frame */
typedef struct mac_lte_info {
/* Needed for decode */
guint8 radioType;
guint8 direction;
guint8 rntiType;
typedef struct mac_lte_info
{
/* Needed for decode */
guint8 radioType;
guint8 direction;
guint8 rntiType;
/* Extra info to display */
guint16 rnti;
guint16 ueid;
/* Extra info to display */
guint16 rnti;
guint16 ueid;
/* Timing info */
guint16 sysframeNumber;
guint16 subframeNumber;
/* Timing info */
guint16 sysframeNumber;
guint16 subframeNumber;
/* Optional field. More interesting for TDD (FDD is always -4 subframeNumber) */
gboolean subframeNumberOfGrantPresent;
guint16 subframeNumberOfGrant;
/* Optional field. More interesting for TDD (FDD is always -4 subframeNumber) */
gboolean subframeNumberOfGrantPresent;
guint16 subframeNumberOfGrant;
/* Flag set only if doing PHY-level data test - i.e. there may not be a
well-formed MAC PDU so just show as raw data */
gboolean isPredefinedData;
/* Flag set only if doing PHY-level data test - i.e. there may not be a
well-formed MAC PDU so just show as raw data */
gboolean isPredefinedData;
/* Length of DL PDU or UL grant size in bytes */
guint16 length;
/* Length of DL PDU or UL grant size in bytes */
guint16 length;
/* UL only. 0=newTx, 1=first-retx, etc */
guint8 reTxCount;
guint8 isPHICHNACK; /* FALSE=PDCCH retx grant, TRUE=PHICH NACK */
/* 0=newTx, 1=first-retx, etc */
guint8 reTxCount;
guint8 isPHICHNACK; /* FALSE=PDCCH retx grant, TRUE=PHICH NACK */
/* UL only. Indicates if the R10 extendedBSR-Sizes parameter is set */
gboolean isExtendedBSRSizes;
/* UL only. Indicates if the R10 extendedBSR-Sizes parameter is set */
gboolean isExtendedBSRSizes;
/* DL only. Status of CRC check */
mac_lte_crc_status crcStatusValid;
/* UL only. Indicates if the R10 simultaneousPUCCH-PUSCH parameter is set for PCell */
gboolean isSimultPUCCHPUSCHPCell;
/* DL only. Is this known to be a retransmission? */
mac_lte_dl_retx dl_retx;
/* UL only. Indicates if the R10 extendedBSR-Sizes parameter is set for PSCell */
gboolean isSimultPUCCHPUSCHPSCell;
/* More Physical layer info (see direction above for which side of union to use) */
union {
struct mac_lte_ul_phy_info {
guint8 present; /* Remaining UL fields are present and should be displayed */
guint8 modulation_type;
guint8 tbs_index;
guint8 resource_block_length;
guint8 resource_block_start;
guint8 harq_id;
gboolean ndi;
} ul_info;
struct mac_lte_dl_phy_info {
guint8 present; /* Remaining UL fields are present and should be displayed */
guint8 dci_format;
guint8 resource_allocation_type;
guint8 aggregation_level;
guint8 mcs_index;
guint8 redundancy_version_index;
guint8 resource_block_length;
mac_lte_crc_status crc_status;
guint8 harq_id;
gboolean ndi;
guint8 transport_block; /* 1..2 */
} dl_info;
} detailed_phy_info;
/* Status of CRC check. For UE it is DL only. For eNodeB it is UL
only. For an analyzer, it is present for both DL and UL. */
gboolean crcStatusValid;
mac_lte_crc_status crcStatus;
/* Relating to out-of-band events */
/* N.B. dissector will only look to these fields if length is 0... */
mac_lte_oob_event oob_event;
guint8 rapid;
guint8 rach_attempt_number;
#define MAX_SRs 20
guint16 number_of_srs;
guint16 oob_ueid[MAX_SRs];
guint16 oob_rnti[MAX_SRs];
/* Carrier ID */
mac_lte_carrier_id carrierId;
/* DL only. Is this known to be a retransmission? */
mac_lte_dl_retx dl_retx;
/* DL only. CE mode to be used for RAR decoding */
mac_lte_ce_mode ceMode;
/* DL and UL. NB-IoT mode of the UE */
mac_lte_nb_mode nbMode;
/* UL only, for now used for CE mode A RAR decoding */
guint8 nUlRb;
/* More Physical layer info (see direction above for which side of union to use) */
union {
struct mac_lte_ul_phy_info
{
guint8 present; /* Remaining UL fields are present and should be displayed */
guint8 modulation_type;
guint8 tbs_index;
guint8 resource_block_length;
guint8 resource_block_start;
guint8 harq_id;
gboolean ndi;
} ul_info;
struct mac_lte_dl_phy_info
{
guint8 present; /* Remaining DL fields are present and should be displayed */
guint8 dci_format;
guint8 resource_allocation_type;
guint8 aggregation_level;
guint8 mcs_index;
guint8 redundancy_version_index;
guint8 resource_block_length;
guint8 harq_id;
gboolean ndi;
guint8 transport_block; /* 0..1 */
} dl_info;
} detailed_phy_info;
/* Relating to out-of-band events */
/* N.B. dissector will only look to these fields if length is 0... */
mac_lte_oob_event oob_event;
guint8 rapid;
guint8 rach_attempt_number;
#define MAX_SRs 20
guint16 number_of_srs;
guint16 oob_ueid[MAX_SRs];
guint16 oob_rnti[MAX_SRs];
} mac_lte_info;
/* Accessor function to check if a frame was considered to be ReTx */
//int is_mac_lte_frame_retx(packet_info *pinfo, guint8 direction);
typedef struct mac_lte_tap_info {
/* Info from context */
guint16 rnti;
guint16 ueid;
guint8 rntiType;
guint8 isPredefinedData;
gboolean crcStatusValid;
mac_lte_crc_status crcStatus;
guint8 direction;
guint8 isPHYRetx;
guint16 ueInTTI;
nstime_t mac_lte_time;
/* Number of bytes (which part is used depends upon context settings) */
guint32 single_number_of_bytes;
guint32 bytes_for_lcid[11];
guint32 sdus_for_lcid[11];
guint8 number_of_rars;
guint8 number_of_paging_ids;
/* Number of padding bytes includes padding subheaders and trailing padding */
guint16 padding_bytes;
guint16 raw_length;
} mac_lte_tap_info;
/*****************************************************************/
/* UDP framing format */
@@ -153,12 +233,10 @@ typedef struct mac_lte_info {
/* and implemented by this dissector, using the definitions */
/* below. A link to an example program showing you how to encode */
/* these headers and send LTE MAC PDUs on a UDP socket is */
/* provided at http://wiki.wireshark.org/MAC-LTE */
/* provided at https://wiki.wireshark.org/MAC-LTE */
/* */
/* A heuristic dissecter (enabled by a preference) will */
/* recognise a signature at the beginning of these frames . */
/* Until someone is using this format, suggestions for changes */
/* are welcome. */
/* A heuristic dissector (enabled by a preference) will */
/* recognise a signature at the beginning of these frames. */
/*****************************************************************/
@@ -177,7 +255,7 @@ typedef struct mac_lte_info {
to show you display/filter/plot/add-custom-columns on these fields, so should
be added if available.
The format is to have the tag, followed by the value (there is no length field,
its implicit from the tag) */
it's implicit from the tag) */
#define MAC_LTE_RNTI_TAG 0x02
/* 2 bytes, network order */
@@ -185,8 +263,8 @@ typedef struct mac_lte_info {
#define MAC_LTE_UEID_TAG 0x03
/* 2 bytes, network order */
#define MAC_LTE_SUBFRAME_TAG 0x04
/* 2 bytes, network order */
#define MAC_LTE_FRAME_SUBFRAME_TAG 0x04
/* 2 bytes, network order, SFN is stored in 12 MSB and SF in 4 LSB */
#define MAC_LTE_PREDEFINED_DATA_TAG 0x05
/* 1 byte */
@@ -200,29 +278,101 @@ typedef struct mac_lte_info {
#define MAC_LTE_EXT_BSR_SIZES_TAG 0x08
/* 0 byte */
#define MAC_LTE_OOB_EVENT_TAG 0x09
/* 3 byte */
#define MAC_LTE_SEND_PREAMBLE_TAG 0x09
/* 2 bytes, RAPID value (1 byte) followed by RACH attempt number (1 byte) */
#define MAC_LTE_CARRIER_ID_TAG 0x0A
/* 1 byte */
#define MAC_LTE_PHY_TAG 0x0B
/* variable length, length (1 byte) then depending on direction
in UL: modulation type (1 byte), TBS index (1 byte), RB length (1 byte),
RB start (1 byte), HARQ id (1 byte), NDI (1 byte)
in DL: DCI format (1 byte), resource allocation type (1 byte), aggregation level (1 byte),
MCS index (1 byte), redundancy version (1 byte), resource block length (1 byte),
HARQ id (1 byte), NDI (1 byte), TB (1 byte), DL reTx (1 byte) */
#define MAC_LTE_SIMULT_PUCCH_PUSCH_PCELL_TAG 0x0C
/* 0 byte */
#define MAC_LTE_SIMULT_PUCCH_PUSCH_PSCELL_TAG 0x0D
/* 0 byte */
#define MAC_LTE_CE_MODE_TAG 0x0E
/* 1 byte containing mac_lte_ce_mode enum value */
#define MAC_LTE_NB_MODE_TAG 0x0F
/* 1 byte containing mac_lte_nb_mode enum value */
#define MAC_LTE_N_UL_RB_TAG 0x10
/* 1 byte containing the number of UL resource blocks: 6, 15, 25, 50, 75 or 100 */
#define MAC_LTE_SR_TAG 0x11
/* 2 bytes for the number of items, followed by that number of ueid, rnti (2 bytes each) */
/* MAC PDU. Following this tag comes the actual MAC PDU (there is no length, the PDU
continues until the end of the frame) */
#define MAC_LTE_PAYLOAD_TAG 0x01
/* Set details of an LCID -> drb channel mapping. To be called from
configuration protocol (e.g. RRC) */
/*void set_mac_lte_channel_mapping(guint16 ueid, guint8 lcid,
guint8 srbid, guint8 drbid,
guint8 rlcMode, guint8 um_sn_length,
guint8 ul_priority);
*/
/* Functions to be called from outside this module (e.g. in a plugin, where mac_lte_info
isn't available) to get/set per-packet data */
//mac_lte_info *get_mac_lte_proto_data(packet_info *pinfo);
//void set_mac_lte_proto_data(packet_info *pinfo, mac_lte_info *p_mac_lte_info);
/* Type to store parameters for configuring LCID->RLC channel settings for DRB */
/* Some are optional, and may not be seen (e.g. on reestablishment) */
typedef struct drb_mapping_t
{
guint16 ueid; /* Mandatory */
guint8 drbid; /* Mandatory */
gboolean lcid_present;
guint8 lcid; /* Part of LogicalChannelConfig - optional */
gboolean rlcMode_present;
guint8 rlcMode; /* Part of RLC config - optional */
gboolean rlc_ul_ext_li_field; /* Part of RLC config - optional */
gboolean rlc_dl_ext_li_field; /* Part of RLC config - optional */
gboolean rlc_ul_ext_am_sn; /* Part of RLC config - optional */
gboolean rlc_dl_ext_am_sn; /* Part of RLC config - optional */
gboolean um_sn_length_present;
guint8 um_sn_length; /* Part of RLC config - optional */
gboolean ul_priority_present;
guint8 ul_priority; /* Part of LogicalChannelConfig - optional */
gboolean pdcp_sn_size_present;
guint8 pdcp_sn_size; /* Part of pdcp-Config - optional */
} drb_mapping_t;
/* Function to attempt to populate p_mac_lte_info using framing definition above */
/*gboolean dissect_mac_lte_context_fields(struct mac_lte_info *p_mac_lte_info, tvbuff_t *tvb,
gint *p_offset);
*/
#endif /* PACKET_MAC_LTE_H_ */
/* Dedicated DRX config. Used to verify that a sensible config is given.
Also, beginning to configure MAC with this config and (optionally) show
DRX config and state (cycles/timers) attached to each UL/DL PDU! */
typedef struct drx_config_t {
gboolean configured;
guint32 frameNum;
guint32 previousFrameNum;
guint32 onDurationTimer;
guint32 inactivityTimer;
guint32 retransmissionTimer;
guint32 longCycle;
guint32 cycleOffset;
/* Optional Short cycle */
gboolean shortCycleConfigured;
guint32 shortCycle;
guint32 shortCycleTimer;
} drx_config_t;
/* RRC can indicate whether simultaneous PUCCH/PUSCH is used */
typedef enum {
SIMULT_PUCCH_PUSCH_PCELL = 0,
SIMULT_PUCCH_PUSCH_PSCELL
} simult_pucch_pusch_cell_type;
/*
* Editor modelines - http://www.wireshark.org/tools/modelines.html
*
* Local variables:
* c-basic-offset: 4
* tab-width: 8
* indent-tabs-mode: nil
* End:
*
* vi: set shiftwidth=4 tabstop=8 expandtab:
* :indentSize=4:tabSize=8:noTabs=true:
*/
+32 -42
View File
@@ -95,26 +95,22 @@ what about the implementation
int opt_enabled=0;
#define PACKET_MAC_LTE_DEFAULT_UDP_PORT (9999)
typedef uint8_t guint8;
typedef uint16_t guint16;
typedef uint32_t guint32;
typedef guint8 gboolean;
#include "packet-mac-lte.h"
#include "mac_pcap.h"
//static unsigned char g_PDUBuffer[1600];
//static unsigned int g_PDUOffset;
char in_ip[40];
char in_path[100];
char in_path[FILENAME_MAX];
FILE *file_fd = NULL;
pcap_hdr_t file_header = {
0xa1b2c3d4, /* magic number */
2, 4, /* version number is 2.4 */
0, /* timezone */
0, /* sigfigs - apparently all tools do this */
65535, /* snaplen - this should be long enough */
MAC_LTE_DLT /* Data Link Type (DLT). Set as unused value 147 for now */
};
trace_mode_t opt_type = OPT_NONE;
static radio_type_t radio_type;
static unsigned int subframesSinceCaptureStart;
static int g_socksd = -1;/* UDP socket used for sending frames */
@@ -237,22 +233,13 @@ static void SendFrame(guint8 radioType, guint8 direction, guint8 rntiType,
guint8 oob_event, guint8 oob_event_value,
uint8_t *pdu_buffer, unsigned int pdu_buffer_size)
{
#ifdef JUMBO_FRAME
static unsigned char frameBuffer[9000];
#else
static unsigned char frameBuffer[1600];
#endif
static unsigned int frameOffset;
unsigned char frameBuffer[9000];
unsigned int frameOffset;
ssize_t bytesSent;
frameOffset = 0;
uint16_t tmp16;
/********************************************************************/
/* Fixed start to each frame (allowing heuristic dissector to work) */
/* Not NULL terminated */
memset(frameBuffer+frameOffset, 0, sizeof(mac_lte_info)+pdu_buffer_size + 8);
memcpy(frameBuffer+frameOffset, MAC_LTE_START_STRING,
strlen(MAC_LTE_START_STRING));
frameOffset += strlen(MAC_LTE_START_STRING);
@@ -279,7 +266,7 @@ static void SendFrame(guint8 radioType, guint8 direction, guint8 rntiType,
frameOffset += 2;
/* Subframe number */
frameBuffer[frameOffset++] = MAC_LTE_SUBFRAME_TAG;
frameBuffer[frameOffset++] = MAC_LTE_FRAME_SUBFRAME_TAG;
tmp16 = htons(sfnSf); // frame counter : this will give an expert info as wireshark expects SF and not F
memcpy(frameBuffer+frameOffset, &tmp16, 2);
frameOffset += 2;
@@ -313,26 +300,29 @@ static void SendFrame(guint8 radioType, guint8 direction, guint8 rntiType,
if (pdu_buffer_size==0) {
switch (oob_event) {
case ltemac_send_preamble :
LOG_D(OPT,"oob ltemac_send_preamble event %02x."
LOG_D(OPT,"ltemac_send_preamble event %02x."
//"%02x."
"%02x.%02x\n",
MAC_LTE_OOB_EVENT_TAG,
MAC_LTE_SEND_PREAMBLE_TAG,
//ltemac_send_preamble,
rnti,
oob_event_value);
//frameBuffer[frameOffset++]=0;
//frameBuffer[frameOffset++]=0;
//frameBuffer[frameOffset++]=0;
frameBuffer[frameOffset++] = MAC_LTE_OOB_EVENT_TAG;
frameBuffer[frameOffset++] = MAC_LTE_SEND_PREAMBLE_TAG;
//frameBuffer[frameOffset++]=ltemac_send_preamble;
frameBuffer[frameOffset++]=rnti; // is the preamble
frameBuffer[frameOffset++]=oob_event_value;
break;
case ltemac_send_sr:
frameBuffer[frameOffset++]=ltemac_send_sr;
frameBuffer[frameOffset++]=MAC_LTE_SR_TAG ;
frameOffset+=2;
frameBuffer[frameOffset++]=rnti;
frameOffset++;
frameBuffer[frameOffset++]=oob_event_value;
frameOffset++;
break;
case ltemac_sr_failure:
@@ -394,7 +384,7 @@ static int MAC_LTE_PCAP_WritePDU(MAC_Context_Info_t *context,
offset += 2;
/* Subframe number */
context_header[offset++] = MAC_LTE_SUBFRAME_TAG;
context_header[offset++] = MAC_LTE_FRAME_SUBFRAME_TAG;
tmp16 = htons(context->subFrameNumber);
memcpy(context_header+offset, &tmp16, 2);
offset += 2;
@@ -423,21 +413,27 @@ static int MAC_LTE_PCAP_WritePDU(MAC_Context_Info_t *context,
return 1;
}
#include <common/ran_context.h>
extern RAN_CONTEXT_t RC;
#include <openair1/PHY/phy_extern_ue.h>
/* Remote serveraddress (where Wireshark is running) */
void trace_pdu(int direction, uint8_t *pdu_buffer, unsigned int pdu_buffer_size,
int ueid, int rntiType, int rnti, uint16_t sysFrameNumber, uint8_t subFrameNumber, int oob_event,
int oob_event_value)
{
MAC_Context_Info_t pdu_context;
int radioType=FDD_RADIO;
if (RC.eNB[0][0]!=NULL)
radioType=RC.eNB[0][0]->frame_parms.frame_type== FDD ? FDD_RADIO:TDD_RADIO;
if (PHY_vars_UE_g[0][0] != NULL)
radioType=PHY_vars_UE_g[0][0]->frame_parms.frame_type== FDD ? FDD_RADIO:TDD_RADIO;
switch (opt_type) {
case OPT_WIRESHARK :
if (g_socksd == -1) {
return;
}
SendFrame(radio_type,
SendFrame( radioType,
(direction == DIRECTION_DOWNLINK) ? DIRECTION_DOWNLINK : DIRECTION_UPLINK,
rntiType, rnti, ueid, (sysFrameNumber<<4) + subFrameNumber,
1, 0, 1, //guint8 isPredefinedData, guint8 retx, guint8 crcStatus
@@ -450,7 +446,7 @@ void trace_pdu(int direction, uint8_t *pdu_buffer, unsigned int pdu_buffer_size,
return;
}
pdu_context.radioType = radio_type;
pdu_context.radioType = radioType;
pdu_context.direction = (direction == DIRECTION_DOWNLINK) ? DIRECTION_DOWNLINK
: DIRECTION_UPLINK;
pdu_context.rntiType = rntiType;
@@ -470,7 +466,7 @@ void trace_pdu(int direction, uint8_t *pdu_buffer, unsigned int pdu_buffer_size,
}
}
/*---------------------------------------------------*/
int init_opt(char *path, char *ip, char *port, radio_type_t radio_type_p)
int init_opt(char *path, char *ip)
{
uint16_t in_port;
subframesSinceCaptureStart = 0;
@@ -489,13 +485,7 @@ int init_opt(char *path, char *ip, char *port, radio_type_t radio_type_p)
strcpy( in_ip, "127.0.0.1" );
}
if (port != NULL) {
in_port = atoi(port);
} else {
in_port = PACKET_MAC_LTE_DEFAULT_UDP_PORT;
}
radio_type = radio_type_p;
in_port = PACKET_MAC_LTE_DEFAULT_UDP_PORT;
// trace_mode
switch (opt_type) {
+138
View File
@@ -0,0 +1,138 @@
/* ws_compiler_tests.h
*
* Wireshark - Network traffic analyzer
* By Gerald Combs <gerald@wireshark.org>
* Copyright 1998 Gerald Combs
*
* SPDX-License-Identifier: GPL-2.0-or-later
*/
#ifndef __WS_COMPILER_TESTS_H__
#define __WS_COMPILER_TESTS_H__
/*
* This was introduced by Clang:
*
* http://clang.llvm.org/docs/LanguageExtensions.html#has-attribute
*
* in some version (which version?); it has been picked up by GCC 5.0.
*/
#ifndef __has_attribute
/*
* It's a macro, so you can check whether it's defined to check
* whether it's supported.
*
* If it's not, define it to always return 0, so that we move on to
* the fallback checks.
*/
#define __has_attribute(x) 0
#endif
/*
* Note that the C90 spec's "6.8.1 Conditional inclusion" and the
* C99 spec's and C11 spec's "6.10.1 Conditional inclusion" say:
*
* Prior to evaluation, macro invocations in the list of preprocessing
* tokens that will become the controlling constant expression are
* replaced (except for those macro names modified by the defined unary
* operator), just as in normal text. If the token "defined" is
* generated as a result of this replacement process or use of the
* "defined" unary operator does not match one of the two specified
* forms prior to macro replacement, the behavior is undefined.
*
* so you shouldn't use defined() in a #define that's used in #if or
* #elif. Some versions of Clang, for example, will warn about this.
*
* Instead, we check whether the pre-defined macros for particular
* compilers are defined and, if not, define the "is this version XXX
* or a later version of this compiler" macros as 0.
*/
/*
* Check whether this is GCC major.minor or a later release, or some
* compiler that claims to be "just like GCC" of that version or a
* later release.
*/
#if !defined(__GNUC__)
#define WS_IS_AT_LEAST_GNUC_VERSION(major, minor) 0
#else
#define WS_IS_AT_LEAST_GNUC_VERSION(major, minor) \
(__GNUC__ > (major) || \
(__GNUC__ == (major) && __GNUC_MINOR__ >= (minor)))
#endif
/*
* Check whether this is Clang major.minor or a later release.
*/
#if !defined(__clang__)
#define WS_IS_AT_LEAST_CLANG_VERSION(major, minor) 0
#else
#define WS_IS_AT_LEAST_CLANG_VERSION(major, minor) \
(__clang_major__ > (major) || \
(__clang_major__ == (major) && __clang_minor__ >= (minor)))
#endif
/*
* Check whether this is Sun C/SunPro C/Oracle Studio major.minor
* or a later release.
*
* The version number in __SUNPRO_C is encoded in hex BCD, with the
* uppermost hex digit being the major version number, the next
* one or two hex digits being the minor version number, and
* the last digit being the patch version.
*
* It represents the *compiler* version, not the product version;
* see
*
* https://sourceforge.net/p/predef/wiki/Compilers/
*
* for a partial mapping, which we assume continues for later
* 12.x product releases.
*/
#if !defined(__SUNPRO_C)
#define WS_IS_AT_LEAST_SUNC_VERSION(major, minor) 0
#else
#define WS_SUNPRO_VERSION_TO_BCD(major, minor) \
(((minor) >= 10) ? \
(((major) << 12) | (((minor)/10) << 8) | (((minor)%10) << 4)) : \
(((major) << 8) | ((minor) << 4)))
#define WS_IS_AT_LEAST_SUNC_VERSION(major, minor) \
(__SUNPRO_C >= WS_SUNPRO_VERSION_TO_BCD((major), (minor)))
#endif
/*
* Check whether this is IBM XL C major.minor or a later release.
*
* The version number in __xlC__ has the major version in the
* upper 8 bits and the minor version in the lower 8 bits.
*/
#if !defined(__xlC__)
#define WS_IS_AT_LEAST_XL_C_VERSION(major, minor) 0
#else
#define WS_IS_AT_LEAST_XL_C_VERSION(major, minor) \
(__xlC__ >= (((major) << 8) | (minor)))
#endif
/*
* Check whether this is HP aC++/HP C major.minor or a later release.
*
* The version number in __HP_aCC is encoded in zero-padded decimal BCD,
* with the "A." stripped off, the uppermost two decimal digits being
* the major version number, the next two decimal digits being the minor
* version number, and the last two decimal digits being the patch version.
* (Strip off the A., remove the . between the major and minor version
* number, and add two digits of patch.)
*/
#if !defined(__HP_aCC)
#define WS_IS_AT_LEAST_HP_C_VERSION(major, minor) 0
#else
#define WS_IS_AT_LEAST_HP_C_VERSION(major, minor) \
(__HP_aCC >= ((major)*10000 + (minor)*100))
#endif
#endif /* __WS_COMPILER_TESTS_H__ */
+202
View File
@@ -0,0 +1,202 @@
/*
* Cross platform defines for exporting symbols from shared libraries
*
* Wireshark - Network traffic analyzer
* By Balint Reczey <balint@balintreczey.hu>
* Copyright 2013 Balint Reczey
*
* SPDX-License-Identifier: GPL-2.0-or-later
*/
#include "ws_compiler_tests.h"
/** Reset symbol export behavior.
* If you {un}define WS_BUILD_DLL on the fly you'll have to define this
* as well.
*/
#ifdef RESET_SYMBOL_EXPORT
#ifdef SYMBOL_EXPORT_H
#undef SYMBOL_EXPORT_H
#endif
#ifdef WS_DLL_PUBLIC
#undef WS_DLL_PUBLIC
#endif
#ifdef WS_DLL_PUBLIC_DEF
#undef WS_DLL_PUBLIC_DEF
#endif
#ifdef WS_DLL_LOCAL
#undef WS_DLL_LOCAL
#endif
#endif /* RESET_SYMBOL_EXPORT */
#ifndef SYMBOL_EXPORT_H
#define SYMBOL_EXPORT_H
/*
* NOTE: G_HAVE_GNUC_VISIBILITY is defined only if all of
*
* __attribute__ ((visibility ("hidden")))
*
* __attribute__ ((visibility ("internal")))
*
* __attribute__ ((visibility ("protected")))
*
* __attribute__ ((visibility ("default")))
*
* are supported, and at least some versions of GCC from Apple support
* "default" and "hidden" but not "internal" or "protected", so it
* shouldn't be used to determine whether "hidden" or "default" is
* supported.
*
* This also means that we shouldn't use G_GNUC_INTERNAL instead of
* WS_DLL_LOCAL, as GLib uses G_HAVE_GNUC_VISIBILITY to determine
* whether to use __attribute__ ((visibility ("hidden"))) for
* G_GNUC_INTERNAL, and that will not use it even with compilers
* that support it.
*/
/* Originally copied from GCC Wiki at http://gcc.gnu.org/wiki/Visibility */
#if defined _WIN32 || defined __CYGWIN__
/* Compiling for Windows, so we use the Windows DLL declarations. */
#ifdef WS_BUILD_DLL
/*
* Building a DLL; for all definitions, we want dllexport, and
* (presumably so source from DLL and source from a program using the
* DLL can both include a header that declares APIs and exported data
* for the DLL), for declarations, either dllexport or dllimport will
* work (they mean the same thing for a declaration when building a DLL).
*/
#ifdef __GNUC__
/* GCC */
#define WS_DLL_PUBLIC_DEF __attribute__ ((dllexport))
#else /* ! __GNUC__ */
/*
* Presumably MSVC.
* Note: actually gcc seems to also support this syntax.
*/
#define WS_DLL_PUBLIC_DEF __declspec(dllexport)
#endif /* __GNUC__ */
#else /* WS_BUILD_DLL */
/*
* Building a program; we should only see declarations, not definitions,
* with WS_DLL_PUBLIC, and they all represent APIs or data imported
* from a DLL, so use dllimport.
*
* For functions, export shouldn't be necessary; for data, it might
* be necessary, e.g. if what's declared is an array whose size is
* not given in the declaration.
*/
#ifdef __GNUC__
/* GCC */
#define WS_DLL_PUBLIC_DEF __attribute__ ((dllimport))
#elif ! (defined ENABLE_STATIC) /* ! __GNUC__ */
/*
* Presumably MSVC, and we're not building all-static.
* Note: actually gcc seems to also support this syntax.
*/
#define WS_DLL_PUBLIC_DEF __declspec(dllimport)
#else /* ! __GNUC__ && ENABLE_STATIC */
/*
* Presumably MSVC, and we're building all-static, so we're
* not building any DLLs.
*/
#define WS_DLL_PUBLIC_DEF
#endif /* __GNUC__ */
#endif /* WS_BUILD_DLL */
/*
* Symbols in a DLL are *not* exported unless they're specifically
* flagged as exported, so, for a non-static but non-exported
* symbol, we don't have to do anything.
*/
#define WS_DLL_LOCAL
#else /* defined _WIN32 || defined __CYGWIN__ */
/*
* Compiling for UN*X, where the dllimport and dllexport stuff
* is neither necessary nor supported; just specify the
* visibility if we have a compiler that supports doing so.
*/
#if WS_IS_AT_LEAST_GNUC_VERSION(3,4) \
|| WS_IS_AT_LEAST_XL_C_VERSION(12,0)
/*
* GCC 3.4 or later, or some compiler asserting compatibility with
* GCC 3.4 or later, or XL C 13.0 or later, so we have
* __attribute__((visibility()).
*/
/*
* Symbols exported from libraries.
*/
#define WS_DLL_PUBLIC_DEF __attribute__ ((visibility ("default")))
/*
* Non-static symbols *not* exported from libraries.
*/
#define WS_DLL_LOCAL __attribute__ ((visibility ("hidden")))
#elif WS_IS_AT_LEAST_SUNC_VERSION(5,5)
/*
* Sun C 5.5 or later, so we have __global and __hidden.
* (Sun C 5.9 and later also have __attribute__((visibility()),
* but there's no reason to prefer it with Sun C.)
*/
/*
* Symbols exported from libraries.
*/
#define WS_DLL_PUBLIC_DEF __global
/*
* Non-static symbols *not* exported from libraries.
*/
#define WS_DLL_LOCAL __hidden
#else
/*
* We have neither a way to make stuff not explicitly marked as
* visible invisible outside a library nor a way to make stuff
* explicitly marked as local invisible outside the library.
*/
/*
* Symbols exported from libraries.
*/
#define WS_DLL_PUBLIC_DEF
/*
* Non-static symbols *not* exported from libraries.
*/
#define WS_DLL_LOCAL
#endif
#endif
/*
* You *must* use this for exported data *declarations*; if you use
* WS_DLL_PUBLIC_DEF, some compilers, such as MSVC++, will complain
* about array definitions with no size.
*
* You must *not* use this for exported data *definitions*, as that
* will, for some compilers, cause warnings about items being initialized
* and declared extern.
*
* Either can be used for exported *function* declarations and definitions.
*/
#define WS_DLL_PUBLIC WS_DLL_PUBLIC_DEF extern
#endif /* SYMBOL_EXPORT_H */
/*
* Editor modelines - http://www.wireshark.org/tools/modelines.html
*
* Local Variables:
* c-basic-offset: 2
* tab-width: 8
* indent-tabs-mode: nil
* End:
*
* vi: set shiftwidth=2 tabstop=8 expandtab:
* :indentSize=2:tabSize=8:noTabs=true:
*/
+3 -3
View File
@@ -66,7 +66,7 @@ ssize_t x2ap_generate_initiating_message(
pdu.present = X2AP_X2AP_PDU_PR_initiatingMessage;
pdu.choice.initiatingMessage.procedureCode = procedureCode;
pdu.choice.initiatingMessage.criticality = criticality;
ANY_fromType_aper(&pdu.choice.initiatingMessage.value, td, sptr);
ANY_fromType_aper((ANY_t *)&pdu.choice.initiatingMessage.value, td, sptr);
if (asn1_xer_print) {
xer_fprint(stdout, &asn_DEF_X2AP_X2AP_PDU, (void *)&pdu);
@@ -98,7 +98,7 @@ ssize_t x2ap_generate_successfull_outcome(
pdu.present = X2AP_X2AP_PDU_PR_successfulOutcome;
pdu.choice.successfulOutcome.procedureCode = procedureCode;
pdu.choice.successfulOutcome.criticality = criticality;
ANY_fromType_aper(&pdu.choice.successfulOutcome.value, td, sptr);
ANY_fromType_aper((ANY_t *)&pdu.choice.successfulOutcome.value, td, sptr);
if (asn1_xer_print) {
xer_fprint(stdout, &asn_DEF_X2AP_X2AP_PDU, (void *)&pdu);
@@ -130,7 +130,7 @@ ssize_t x2ap_generate_unsuccessfull_outcome(
pdu.present = X2AP_X2AP_PDU_PR_unsuccessfulOutcome;
pdu.choice.successfulOutcome.procedureCode = procedureCode;
pdu.choice.successfulOutcome.criticality = criticality;
ANY_fromType_aper(&pdu.choice.successfulOutcome.value, td, sptr);
ANY_fromType_aper((ANY_t *)&pdu.choice.successfulOutcome.value, td, sptr);
if (asn1_xer_print) {
xer_fprint(stdout, &asn_DEF_X2AP_X2AP_PDU, (void *)&pdu);
+6 -7
View File
@@ -28,12 +28,12 @@
#include "X2AP_InitiatingMessage.h"
#include "X2AP_SuccessfulOutcome.h"
#include "X2AP_UnsuccessfulOutcome.h"
#include "X2AP_ProtocolIE-Field.h"
#include "X2AP_ProtocolIE-FieldPair.h"
#include "X2AP_ProtocolIE-ContainerPair.h"
#include "X2AP_ProtocolExtensionField.h"
#include "X2AP_ProtocolExtensionContainer.h"
#include "X2AP_asn_constant.h"
#include "intertask_interface.h"
#ifndef X2AP_COMMON_H_
#define X2AP_COMMON_H_
@@ -57,15 +57,16 @@
#define FALSE 0
#endif
extern int asn_debug;
extern int asn1_xer_print;
#if defined(ENB_MODE)
# include "log.h"
# include "common/utils/LOG/log.h"
# define X2AP_INFO(x, args...) LOG_I(X2AP, x, ##args)
# define X2AP_ERROR(x, args...) LOG_E(X2AP, x, ##args)
# define X2AP_WARN(x, args...) LOG_W(X2AP, x, ##args)
# define X2AP_DEBUG(x, args...) LOG_D(X2AP, x, ##args)
#else
# define X2AP_INFO(x, args...) do { fprintf(stdout, "[X2AP][I]"x, ##args); } while(0)
# define X2AP_ERROR(x, args...) do { fprintf(stdout, "[X2AP][E]"x, ##args); } while(0)
# define X2AP_WARN(x, args...) do { fprintf(stdout, "[X2AP][W]"x, ##args); } while(0)
# define X2AP_DEBUG(x, args...) do { fprintf(stdout, "[X2AP][D]"x, ##args); } while(0)
@@ -86,15 +87,13 @@ extern int asn1_xer_print;
if (mandatory) DevAssert(ie != NULL); \
} while(0)
//Forward declaration
struct x2ap_message_s;
/** \brief Function callback prototype.
**/
typedef int (*x2ap_message_decoded_callback)(
instance_t instance,
uint32_t assocId,
uint32_t stream,
struct x2ap_message_s *message);
X2AP_X2AP_PDU_t *pdu);
/** \brief Encode a successfull outcome message
\param buffer pointer to buffer in which data will be encoded
+467
View File
@@ -0,0 +1,467 @@
/*
* 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
*/
#include <pthread.h>
#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
#include <arpa/inet.h>
#include "intertask_interface.h"
#include "x2ap_eNB.h"
#include "x2ap_eNB_defs.h"
#include "x2ap_eNB_management_procedures.h"
#include "x2ap_eNB_handler.h"
#include "x2ap_eNB_generate_messages.h"
#include "x2ap_common.h"
#include "queue.h"
#include "assertions.h"
#include "conversions.h"
struct x2ap_enb_map;
struct x2ap_eNB_data_s;
RB_PROTOTYPE(x2ap_enb_map, x2ap_eNB_data_s, entry, x2ap_eNB_compare_assoc_id);
static
void x2ap_eNB_handle_sctp_data_ind(instance_t instance, sctp_data_ind_t *sctp_data_ind);
static
void x2ap_eNB_handle_sctp_association_resp(instance_t instance, sctp_new_association_resp_t *sctp_new_association_resp);
static
void x2ap_eNB_handle_sctp_association_ind(instance_t instance, sctp_new_association_ind_t *sctp_new_association_ind);
static
void x2ap_eNB_handle_register_eNB(instance_t instance,
x2ap_register_enb_req_t *x2ap_register_eNB);
static
void x2ap_eNB_register_eNB(x2ap_eNB_instance_t *instance_p,
net_ip_address_t *target_eNB_ip_addr,
net_ip_address_t *local_ip_addr,
uint16_t in_streams,
uint16_t out_streams,
uint32_t enb_port_for_X2C,
int multi_sd);
static
void x2ap_eNB_handle_sctp_data_ind(instance_t instance, sctp_data_ind_t *sctp_data_ind) {
int result;
DevAssert(sctp_data_ind != NULL);
x2ap_eNB_handle_message(instance, sctp_data_ind->assoc_id, sctp_data_ind->stream,
sctp_data_ind->buffer, sctp_data_ind->buffer_length);
result = itti_free(TASK_UNKNOWN, sctp_data_ind->buffer);
AssertFatal (result == EXIT_SUCCESS, "Failed to free memory (%d)!\n", result);
}
static
void x2ap_eNB_handle_sctp_association_resp(instance_t instance, sctp_new_association_resp_t *sctp_new_association_resp)
{
x2ap_eNB_instance_t *instance_p;
x2ap_eNB_data_t *x2ap_enb_data_p;
DevAssert(sctp_new_association_resp != NULL);
printf("x2ap_eNB_handle_sctp_association_resp at 1\n");
dump_trees();
instance_p = x2ap_eNB_get_instance(instance);
DevAssert(instance_p != NULL);
/* if the assoc_id is already known, it is certainly because an IND was received
* before. In this case, just update streams and return
*/
if (sctp_new_association_resp->assoc_id != -1) {
x2ap_enb_data_p = x2ap_get_eNB(instance_p, sctp_new_association_resp->assoc_id,
sctp_new_association_resp->ulp_cnx_id);
if (x2ap_enb_data_p != NULL) {
/* some sanity check - to be refined at some point */
if (sctp_new_association_resp->sctp_state != SCTP_STATE_ESTABLISHED) {
X2AP_ERROR("x2ap_enb_data_p not NULL and sctp state not SCTP_STATE_ESTABLISHED, what to do?\n");
abort();
}
x2ap_enb_data_p->in_streams = sctp_new_association_resp->in_streams;
x2ap_enb_data_p->out_streams = sctp_new_association_resp->out_streams;
return;
}
}
x2ap_enb_data_p = x2ap_get_eNB(instance_p, -1,
sctp_new_association_resp->ulp_cnx_id);
DevAssert(x2ap_enb_data_p != NULL);
printf("x2ap_eNB_handle_sctp_association_resp at 2\n");
dump_trees();
if (sctp_new_association_resp->sctp_state != SCTP_STATE_ESTABLISHED) {
X2AP_WARN("Received unsuccessful result for SCTP association (%u), instance %d, cnx_id %u\n",
sctp_new_association_resp->sctp_state,
instance,
sctp_new_association_resp->ulp_cnx_id);
x2ap_handle_x2_setup_message(x2ap_enb_data_p,
sctp_new_association_resp->sctp_state == SCTP_STATE_SHUTDOWN);
return;
}
printf("x2ap_eNB_handle_sctp_association_resp at 3\n");
dump_trees();
/* Update parameters */
x2ap_enb_data_p->assoc_id = sctp_new_association_resp->assoc_id;
x2ap_enb_data_p->in_streams = sctp_new_association_resp->in_streams;
x2ap_enb_data_p->out_streams = sctp_new_association_resp->out_streams;
printf("x2ap_eNB_handle_sctp_association_resp at 4\n");
dump_trees();
/* Prepare new x2 Setup Request */
x2ap_eNB_generate_x2_setup_request(instance_p, x2ap_enb_data_p);
}
static
void x2ap_eNB_handle_sctp_association_ind(instance_t instance, sctp_new_association_ind_t *sctp_new_association_ind)
{
x2ap_eNB_instance_t *instance_p;
x2ap_eNB_data_t *x2ap_enb_data_p;
printf("x2ap_eNB_handle_sctp_association_ind at 1 (called for instance %d)\n", instance);
dump_trees();
DevAssert(sctp_new_association_ind != NULL);
instance_p = x2ap_eNB_get_instance(instance);
DevAssert(instance_p != NULL);
x2ap_enb_data_p = x2ap_get_eNB(instance_p, sctp_new_association_ind->assoc_id, -1);
if (x2ap_enb_data_p != NULL) abort();
// DevAssert(x2ap_enb_data_p != NULL);
if (x2ap_enb_data_p == NULL) {
/* Create new eNB descriptor */
x2ap_enb_data_p = calloc(1, sizeof(*x2ap_enb_data_p));
DevAssert(x2ap_enb_data_p != NULL);
x2ap_enb_data_p->cnx_id = x2ap_eNB_fetch_add_global_cnx_id();
x2ap_enb_data_p->x2ap_eNB_instance = instance_p;
/* Insert the new descriptor in list of known eNB
* but not yet associated.
*/
RB_INSERT(x2ap_enb_map, &instance_p->x2ap_enb_head, x2ap_enb_data_p);
x2ap_enb_data_p->state = X2AP_ENB_STATE_CONNECTED;
instance_p->x2_target_enb_nb++;
if (instance_p->x2_target_enb_pending_nb > 0) {
instance_p->x2_target_enb_pending_nb--;
}
} else {
X2AP_WARN("x2ap_enb_data_p already exists\n");
}
printf("x2ap_eNB_handle_sctp_association_ind at 2\n");
dump_trees();
/* Update parameters */
x2ap_enb_data_p->assoc_id = sctp_new_association_ind->assoc_id;
x2ap_enb_data_p->in_streams = sctp_new_association_ind->in_streams;
x2ap_enb_data_p->out_streams = sctp_new_association_ind->out_streams;
printf("x2ap_eNB_handle_sctp_association_ind at 3\n");
dump_trees();
}
int x2ap_eNB_init_sctp (x2ap_eNB_instance_t *instance_p,
net_ip_address_t *local_ip_addr,
uint32_t enb_port_for_X2C)
{
// Create and alloc new message
MessageDef *message;
sctp_init_t *sctp_init = NULL;
DevAssert(instance_p != NULL);
DevAssert(local_ip_addr != NULL);
message = itti_alloc_new_message (TASK_X2AP, SCTP_INIT_MSG_MULTI_REQ);
sctp_init = &message->ittiMsg.sctp_init_multi;
sctp_init->port = enb_port_for_X2C;
sctp_init->ppid = X2AP_SCTP_PPID;
sctp_init->ipv4 = 1;
sctp_init->ipv6 = 0;
sctp_init->nb_ipv4_addr = 1;
#if 0
memcpy(&sctp_init->ipv4_address,
local_ip_addr,
sizeof(*local_ip_addr));
#endif
sctp_init->ipv4_address[0] = inet_addr(local_ip_addr->ipv4_address);
/*
* SR WARNING: ipv6 multi-homing fails sometimes for localhost.
* * * * Disable it for now.
*/
sctp_init->nb_ipv6_addr = 0;
sctp_init->ipv6_address[0] = "0:0:0:0:0:0:0:1";
return itti_send_msg_to_task (TASK_SCTP, instance_p->instance, message);
}
static void x2ap_eNB_register_eNB(x2ap_eNB_instance_t *instance_p,
net_ip_address_t *target_eNB_ip_address,
net_ip_address_t *local_ip_addr,
uint16_t in_streams,
uint16_t out_streams,
uint32_t enb_port_for_X2C,
int multi_sd)
{
MessageDef *message = NULL;
sctp_new_association_req_multi_t *sctp_new_association_req = NULL;
x2ap_eNB_data_t *x2ap_enb_data = NULL;
DevAssert(instance_p != NULL);
DevAssert(target_eNB_ip_address != NULL);
message = itti_alloc_new_message(TASK_X2AP, SCTP_NEW_ASSOCIATION_REQ_MULTI);
sctp_new_association_req = &message->ittiMsg.sctp_new_association_req_multi;
sctp_new_association_req->port = enb_port_for_X2C;
sctp_new_association_req->ppid = X2AP_SCTP_PPID;
sctp_new_association_req->in_streams = in_streams;
sctp_new_association_req->out_streams = out_streams;
sctp_new_association_req->multi_sd = multi_sd;
memcpy(&sctp_new_association_req->remote_address,
target_eNB_ip_address,
sizeof(*target_eNB_ip_address));
memcpy(&sctp_new_association_req->local_address,
local_ip_addr,
sizeof(*local_ip_addr));
/* Create new eNB descriptor */
x2ap_enb_data = calloc(1, sizeof(*x2ap_enb_data));
DevAssert(x2ap_enb_data != NULL);
x2ap_enb_data->cnx_id = x2ap_eNB_fetch_add_global_cnx_id();
sctp_new_association_req->ulp_cnx_id = x2ap_enb_data->cnx_id;
x2ap_enb_data->assoc_id = -1;
x2ap_enb_data->x2ap_eNB_instance = instance_p;
/* Insert the new descriptor in list of known eNB
* but not yet associated.
*/
RB_INSERT(x2ap_enb_map, &instance_p->x2ap_enb_head, x2ap_enb_data);
x2ap_enb_data->state = X2AP_ENB_STATE_WAITING;
instance_p->x2_target_enb_nb ++;
instance_p->x2_target_enb_pending_nb ++;
itti_send_msg_to_task(TASK_SCTP, instance_p->instance, message);
}
static
void x2ap_eNB_handle_register_eNB(instance_t instance,
x2ap_register_enb_req_t *x2ap_register_eNB)
{
x2ap_eNB_instance_t *new_instance;
DevAssert(x2ap_register_eNB != NULL);
/* Look if the provided instance already exists */
new_instance = x2ap_eNB_get_instance(instance);
if (new_instance != NULL) {
/* Checks if it is a retry on the same eNB */
DevCheck(new_instance->eNB_id == x2ap_register_eNB->eNB_id, new_instance->eNB_id, x2ap_register_eNB->eNB_id, 0);
DevCheck(new_instance->cell_type == x2ap_register_eNB->cell_type, new_instance->cell_type, x2ap_register_eNB->cell_type, 0);
DevCheck(new_instance->tac == x2ap_register_eNB->tac, new_instance->tac, x2ap_register_eNB->tac, 0);
DevCheck(new_instance->mcc == x2ap_register_eNB->mcc, new_instance->mcc, x2ap_register_eNB->mcc, 0);
DevCheck(new_instance->mnc == x2ap_register_eNB->mnc, new_instance->mnc, x2ap_register_eNB->mnc, 0);
X2AP_WARN("eNB[%d] already registered\n", instance);
}
else {
new_instance = calloc(1, sizeof(x2ap_eNB_instance_t));
DevAssert(new_instance != NULL);
RB_INIT(&new_instance->x2ap_enb_head);
/* Copy usefull parameters */
new_instance->instance = instance;
new_instance->eNB_name = x2ap_register_eNB->eNB_name;
new_instance->eNB_id = x2ap_register_eNB->eNB_id;
new_instance->cell_type = x2ap_register_eNB->cell_type;
new_instance->tac = x2ap_register_eNB->tac;
new_instance->mcc = x2ap_register_eNB->mcc;
new_instance->mnc = x2ap_register_eNB->mnc;
new_instance->mnc_digit_length = x2ap_register_eNB->mnc_digit_length;
new_instance->num_cc = x2ap_register_eNB->num_cc;
for (int i = 0; i< x2ap_register_eNB->num_cc; i++){
new_instance->eutra_band[i] = x2ap_register_eNB->eutra_band[i];
new_instance->downlink_frequency[i] = x2ap_register_eNB->downlink_frequency[i];
new_instance->uplink_frequency_offset[i] = x2ap_register_eNB->uplink_frequency_offset[i];
new_instance->Nid_cell[i] = x2ap_register_eNB->Nid_cell[i];
new_instance->N_RB_DL[i] = x2ap_register_eNB->N_RB_DL[i];
new_instance->frame_type[i] = x2ap_register_eNB->frame_type[i];
new_instance->fdd_earfcn_DL[i] = x2ap_register_eNB->fdd_earfcn_DL[i];
new_instance->fdd_earfcn_UL[i] = x2ap_register_eNB->fdd_earfcn_UL[i];
}
DevCheck(x2ap_register_eNB->nb_x2 <= X2AP_MAX_NB_ENB_IP_ADDRESS,
X2AP_MAX_NB_ENB_IP_ADDRESS, x2ap_register_eNB->nb_x2, 0);
memcpy(new_instance->target_enb_x2_ip_address,
x2ap_register_eNB->target_enb_x2_ip_address,
x2ap_register_eNB->nb_x2 * sizeof(net_ip_address_t));
new_instance->nb_x2 = x2ap_register_eNB->nb_x2;
new_instance->enb_x2_ip_address = x2ap_register_eNB->enb_x2_ip_address;
new_instance->sctp_in_streams = x2ap_register_eNB->sctp_in_streams;
new_instance->sctp_out_streams = x2ap_register_eNB->sctp_out_streams;
new_instance->enb_port_for_X2C = x2ap_register_eNB->enb_port_for_X2C;
/* Add the new instance to the list of eNB (meaningfull in virtual mode) */
x2ap_eNB_insert_new_instance(new_instance);
X2AP_INFO("Registered new eNB[%d] and %s eNB id %u\n",
instance,
x2ap_register_eNB->cell_type == CELL_MACRO_ENB ? "macro" : "home",
x2ap_register_eNB->eNB_id);
/* initiate the SCTP listener */
if (x2ap_eNB_init_sctp(new_instance,&x2ap_register_eNB->enb_x2_ip_address,x2ap_register_eNB->enb_port_for_X2C) < 0 ) {
X2AP_ERROR ("Error while sending SCTP_INIT_MSG to SCTP \n");
return;
}
X2AP_INFO("eNB[%d] eNB id %u acting as a listner (server)\n",
instance, x2ap_register_eNB->eNB_id);
}
}
static
void x2ap_eNB_handle_sctp_init_msg_multi_cnf(
instance_t instance_id,
sctp_init_msg_multi_cnf_t *m)
{
x2ap_eNB_instance_t *instance;
int index;
DevAssert(m != NULL);
instance = x2ap_eNB_get_instance(instance_id);
DevAssert(instance != NULL);
instance->multi_sd = m->multi_sd;
/* Exit if CNF message reports failure.
* Failure means multi_sd < 0.
*/
if (instance->multi_sd < 0) {
X2AP_ERROR("Error: be sure to properly configure X2 in your configuration file.\n");
DevAssert(instance->multi_sd >= 0);
}
/* Trying to connect to the provided list of eNB ip address */
for (index = 0; index < instance->nb_x2; index++) {
X2AP_INFO("eNB[%d] eNB id %u acting as an initiator (client)\n",
instance_id, instance->eNB_id);
x2ap_eNB_register_eNB(instance,
&instance->target_enb_x2_ip_address[index],
&instance->enb_x2_ip_address,
instance->sctp_in_streams,
instance->sctp_out_streams,
instance->enb_port_for_X2C,
instance->multi_sd);
}
}
void *x2ap_task(void *arg)
{
MessageDef *received_msg = NULL;
int result;
X2AP_DEBUG("Starting X2AP layer\n");
x2ap_eNB_prepare_internal_data();
itti_mark_task_ready(TASK_X2AP);
while (1) {
itti_receive_msg(TASK_X2AP, &received_msg);
switch (ITTI_MSG_ID(received_msg)) {
case TERMINATE_MESSAGE:
X2AP_WARN(" *** Exiting X2AP thread\n");
itti_exit_task();
break;
case X2AP_REGISTER_ENB_REQ:
x2ap_eNB_handle_register_eNB(ITTI_MESSAGE_GET_INSTANCE(received_msg),
&X2AP_REGISTER_ENB_REQ(received_msg));
break;
case SCTP_INIT_MSG_MULTI_CNF:
x2ap_eNB_handle_sctp_init_msg_multi_cnf(ITTI_MESSAGE_GET_INSTANCE(received_msg),
&received_msg->ittiMsg.sctp_init_msg_multi_cnf);
break;
case SCTP_NEW_ASSOCIATION_RESP:
x2ap_eNB_handle_sctp_association_resp(ITTI_MESSAGE_GET_INSTANCE(received_msg),
&received_msg->ittiMsg.sctp_new_association_resp);
break;
case SCTP_NEW_ASSOCIATION_IND:
x2ap_eNB_handle_sctp_association_ind(ITTI_MESSAGE_GET_INSTANCE(received_msg),
&received_msg->ittiMsg.sctp_new_association_ind);
break;
case SCTP_DATA_IND:
x2ap_eNB_handle_sctp_data_ind(ITTI_MESSAGE_GET_INSTANCE(received_msg),
&received_msg->ittiMsg.sctp_data_ind);
break;
default:
X2AP_ERROR("Received unhandled message: %d:%s\n",
ITTI_MSG_ID(received_msg), ITTI_MSG_NAME(received_msg));
break;
}
result = itti_free (ITTI_MSG_ORIGIN_ID(received_msg), received_msg);
AssertFatal (result == EXIT_SUCCESS, "Failed to free memory (%d)!\n", result);
received_msg = NULL;
}
return NULL;
}
@@ -30,10 +30,12 @@
#ifndef X2AP_H_
#define X2AP_H_
typedef struct x2ap_config_s {
} x2ap_config_t;
#define X2AP_SCTP_PPID (27) ///< X2AP SCTP Payload Protocol Identifier (PPID)
#include "x2ap_eNB_defs.h"
extern x2ap_config_t x2ap_config;
int x2ap_eNB_init_sctp (x2ap_eNB_instance_t *instance_p,
net_ip_address_t *local_ip_addr,
uint32_t enb_port_for_X2C);
void *x2ap_task(void *arg);
+127
View File
@@ -0,0 +1,127 @@
/*
* 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
*/
#include <stdio.h>
#include "assertions.h"
#include "intertask_interface.h"
#include "x2ap_common.h"
#include "x2ap_eNB_decoder.h"
static int x2ap_eNB_decode_initiating_message(X2AP_X2AP_PDU_t *pdu)
{
DevAssert(pdu != NULL);
switch(pdu->choice.initiatingMessage.procedureCode) {
case X2AP_ProcedureCode_id_x2Setup:
asn_encode_to_new_buffer(NULL, ATS_CANONICAL_XER, &asn_DEF_X2AP_X2AP_PDU, pdu);
X2AP_INFO("x2ap_eNB_decode_initiating_message!\n");
break;
default:
X2AP_ERROR("Unknown procedure ID (%d) for initiating message\n",
(int)pdu->choice.initiatingMessage.procedureCode);
AssertFatal( 0, "Unknown procedure ID (%d) for initiating message\n",
(int)pdu->choice.initiatingMessage.procedureCode);
return -1;
}
return 0;
}
static int x2ap_eNB_decode_successful_outcome(X2AP_X2AP_PDU_t *pdu)
{
DevAssert(pdu != NULL);
switch(pdu->choice.successfulOutcome.procedureCode) {
case X2AP_ProcedureCode_id_x2Setup:
asn_encode_to_new_buffer(NULL, ATS_CANONICAL_XER, &asn_DEF_X2AP_X2AP_PDU, pdu);
X2AP_INFO("x2ap_eNB_decode_successfuloutcome_message!\n");
break;
default:
X2AP_ERROR("Unknown procedure ID (%d) for successfull outcome message\n",
(int)pdu->choice.successfulOutcome.procedureCode);
return -1;
}
return 0;
}
static int x2ap_eNB_decode_unsuccessful_outcome(X2AP_X2AP_PDU_t *pdu)
{
DevAssert(pdu != NULL);
switch(pdu->choice.unsuccessfulOutcome.procedureCode) {
case X2AP_ProcedureCode_id_x2Setup:
asn_encode_to_new_buffer(NULL, ATS_CANONICAL_XER, &asn_DEF_X2AP_X2AP_PDU, pdu);
X2AP_INFO("x2ap_eNB_decode_unsuccessfuloutcome_message!\n");
break;
default:
X2AP_ERROR("Unknown procedure ID (%d) for unsuccessfull outcome message\n",
(int)pdu->choice.unsuccessfulOutcome.procedureCode);
return -1;
}
return 0;
}
int x2ap_eNB_decode_pdu(X2AP_X2AP_PDU_t *pdu, const uint8_t *const buffer, uint32_t length)
{
asn_dec_rval_t dec_ret;
DevAssert(buffer != NULL);
dec_ret = aper_decode(NULL,
&asn_DEF_X2AP_X2AP_PDU,
(void **)&pdu,
buffer,
length,
0,
0);
xer_fprint(stdout, &asn_DEF_X2AP_X2AP_PDU, pdu);
if (dec_ret.code != RC_OK) {
X2AP_ERROR("Failed to decode pdu\n");
return -1;
}
switch(pdu->present) {
case X2AP_X2AP_PDU_PR_initiatingMessage:
return x2ap_eNB_decode_initiating_message(pdu);
case X2AP_X2AP_PDU_PR_successfulOutcome:
return x2ap_eNB_decode_successful_outcome(pdu);
case X2AP_X2AP_PDU_PR_unsuccessfulOutcome:
return x2ap_eNB_decode_unsuccessful_outcome(pdu);
default:
X2AP_DEBUG("Unknown presence (%d) or not implemented\n", (int)pdu->present);
break;
}
return -1;
}
+29
View File
@@ -0,0 +1,29 @@
/*
* 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 X2AP_ENB_DECODER_H_
#define X2AP_ENB_DECODER_H_
int x2ap_eNB_decode_pdu(X2AP_X2AP_PDU_t *pdu, const uint8_t *const buffer, uint32_t length)
__attribute__ ((warn_unused_result));
#endif /* X2AP_ENB_DECODER_H_ */
+195
View File
@@ -0,0 +1,195 @@
/*
* 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
*/
#include <stdint.h>
#include "queue.h"
#include "tree.h"
#include "sctp_eNB_defs.h"
#ifndef X2AP_ENB_DEFS_H_
#define X2AP_ENB_DEFS_H_
#define X2AP_ENB_NAME_LENGTH_MAX (150)
typedef enum {
/* Disconnected state: initial state for any association. */
X2AP_ENB_STATE_DISCONNECTED = 0x0,
/* State waiting for x2 Setup response message if the target eNB accepts or
* X2 Setup failure if rejects the eNB.
*/
X2AP_ENB_STATE_WAITING = 0x1,
/* The eNB is successfully connected to another eNB. */
X2AP_ENB_STATE_CONNECTED = 0x2,
/* X2AP is ready, and the eNB is successfully connected to another eNB. */
X2AP_ENB_STATE_READY = 0x3,
X2AP_ENB_STATE_OVERLOAD = 0x4,
X2AP_ENB_STATE_RESETTING = 0x5,
/* Max number of states available */
X2AP_ENB_STATE_MAX,
} x2ap_eNB_state_t;
/* Served PLMN identity element */
struct plmn_identity_s {
uint16_t mcc;
uint16_t mnc;
uint8_t mnc_digit_length;
STAILQ_ENTRY(plmn_identity_s) next;
};
/* Served group id element */
struct served_group_id_s {
uint16_t enb_group_id;
STAILQ_ENTRY(served_group_id_s) next;
};
/* Served enn code for a particular eNB */
struct enb_code_s {
uint8_t enb_code;
STAILQ_ENTRY(enb_code_s) next;
};
struct x2ap_eNB_instance_s;
/* This structure describes association of a eNB to another eNB */
typedef struct x2ap_eNB_data_s {
/* eNB descriptors tree, ordered by sctp assoc id */
RB_ENTRY(x2ap_eNB_data_s) entry;
/* This is the optional name provided by the MME */
char *eNB_name;
/* target eNB ID */
uint32_t eNB_id;
/* Current eNB load information (if any). */
//x2ap_load_state_t overload_state;
/* Current eNB->eNB X2AP association state */
x2ap_eNB_state_t state;
/* Next usable stream for UE signalling */
int32_t nextstream;
/* Number of input/ouput streams */
uint16_t in_streams;
uint16_t out_streams;
/* Connexion id used between SCTP/X2AP */
uint16_t cnx_id;
/* SCTP association id */
int32_t assoc_id;
/* Only meaningfull in virtual mode */
struct x2ap_eNB_instance_s *x2ap_eNB_instance;
} x2ap_eNB_data_t;
typedef struct x2ap_eNB_instance_s {
/* used in simulation to store multiple eNB instances*/
STAILQ_ENTRY(x2ap_eNB_instance_s) x2ap_eNB_entries;
/* Number of target eNBs requested by eNB (tree size) */
uint32_t x2_target_enb_nb;
/* Number of target eNBs for which association is pending */
uint32_t x2_target_enb_pending_nb;
/* Number of target eNB successfully associated to eNB */
uint32_t x2_target_enb_associated_nb;
/* Tree of X2AP eNB associations ordered by association ID */
RB_HEAD(x2ap_enb_map, x2ap_eNB_data_s) x2ap_enb_head;
/* Tree of UE ordered by eNB_ue_x2ap_id's */
// RB_HEAD(x2ap_ue_map, x2ap_eNB_ue_context_s) x2ap_ue_head;
/* For virtual mode, mod_id as defined in the rest of the L1/L2 stack */
instance_t instance;
/* Displayable name of eNB */
char *eNB_name;
/* Unique eNB_id to identify the eNB within EPC.
* In our case the eNB is a macro eNB so the id will be 20 bits long.
* For Home eNB id, this field should be 28 bits long.
*/
uint32_t eNB_id;
/* The type of the cell */
cell_type_t cell_type;
/* Tracking area code */
uint16_t tac;
/* Mobile Country Code
* Mobile Network Code
*/
uint16_t mcc;
uint16_t mnc;
uint8_t mnc_digit_length;
/* CC params */
int16_t eutra_band[MAX_NUM_CCs];
uint32_t downlink_frequency[MAX_NUM_CCs];
int32_t uplink_frequency_offset[MAX_NUM_CCs];
uint32_t Nid_cell[MAX_NUM_CCs];
int16_t N_RB_DL[MAX_NUM_CCs];
lte_frame_type_t frame_type[MAX_NUM_CCs];
uint32_t fdd_earfcn_DL[MAX_NUM_CCs];
uint32_t fdd_earfcn_UL[MAX_NUM_CCs];
int num_cc;
net_ip_address_t target_enb_x2_ip_address[X2AP_MAX_NB_ENB_IP_ADDRESS];
uint8_t nb_x2;
net_ip_address_t enb_x2_ip_address;
uint16_t sctp_in_streams;
uint16_t sctp_out_streams;
uint32_t enb_port_for_X2C;
int multi_sd;
} x2ap_eNB_instance_t;
typedef struct {
/* List of served eNBs
* Only used for virtual mode
*/
STAILQ_HEAD(x2ap_eNB_instances_head_s, x2ap_eNB_instance_s) x2ap_eNB_instances_head;
/* Nb of registered eNBs */
uint8_t nb_registered_eNBs;
/* Generate a unique connexion id used between X2AP and SCTP */
uint16_t global_cnx_id;
} x2ap_eNB_internal_data_t;
int x2ap_eNB_compare_assoc_id(struct x2ap_eNB_data_s *p1, struct x2ap_eNB_data_s *p2);
/* Generate the tree management functions */
struct x2ap_eNB_map;
struct x2ap_eNB_data_s;
RB_PROTOTYPE(x2ap_eNB_map, x2ap_eNB_data_s, entry, x2ap_eNB_compare_assoc_id);
#endif /* X2AP_ENB_DEFS_H_ */
@@ -19,53 +19,36 @@
* contact@openairinterface.org
*/
#include <pthread.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stdint.h>
#include "intertask_interface.h"
#include "x2ap.h"
#include "assertions.h"
#include "conversions.h"
#include "intertask_interface.h"
#include "x2ap_common.h"
#include "x2ap_eNB_encoder.h"
void *x2ap_task(void *arg)
int x2ap_eNB_encode_pdu(X2AP_X2AP_PDU_t *pdu, uint8_t **buffer, uint32_t *len)
{
MessageDef *received_msg = NULL;
int result;
ssize_t encoded;
X2AP_DEBUG("Starting X2AP layer\n");
DevAssert(pdu != NULL);
DevAssert(buffer != NULL);
DevAssert(len != NULL);
x2ap_prepare_internal_data();
itti_mark_task_ready(TASK_X2AP);
while (1) {
itti_receive_msg(TASK_X2AP, &received_msg);
switch (ITTI_MSG_ID(received_msg)) {
case TERMINATE_MESSAGE:
X2AP_WARN(" *** Exiting X2AP thread\n");
itti_exit_task();
break;
default:
X2AP_ERROR("Received unhandled message: %d:%s\n",
ITTI_MSG_ID(received_msg), ITTI_MSG_NAME(received_msg));
break;
}
result = itti_free (ITTI_MSG_ORIGIN_ID(received_msg), received_msg);
AssertFatal (result == EXIT_SUCCESS, "Failed to free memory (%d)!\n", result);
received_msg = NULL;
if (asn1_xer_print) {
xer_fprint(stdout, &asn_DEF_X2AP_X2AP_PDU, (void *)pdu);
}
return NULL;
encoded = aper_encode_to_new_buffer(&asn_DEF_X2AP_X2AP_PDU, 0, pdu, (void **)buffer);
if (encoded < 0) {
return -1;
}
*len = encoded;
ASN_STRUCT_FREE_CONTENTS_ONLY(asn_DEF_X2AP_X2AP_PDU, pdu);
return encoded;
}
+28
View File
@@ -0,0 +1,28 @@
/*
* 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 X2AP_ENB_ENCODER_H_
#define X2AP_ENB_ENCODER_H_
int x2ap_eNB_encode_pdu(X2AP_X2AP_PDU_t *pdu, uint8_t **buffer, uint32_t *len)
__attribute__ ((warn_unused_result));
#endif /* X2AP_ENB_ENCODER_H_ */
+405
View File
@@ -0,0 +1,405 @@
/*
* 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
*/
#include "intertask_interface.h"
#include "x2ap_common.h"
#include "x2ap_eNB.h"
#include "x2ap_eNB_generate_messages.h"
#include "x2ap_eNB_encoder.h"
#include "x2ap_eNB_itti_messaging.h"
#include "msc.h"
#include "assertions.h"
#include "conversions.h"
int x2ap_eNB_generate_x2_setup_request(
x2ap_eNB_instance_t *instance_p, x2ap_eNB_data_t *x2ap_eNB_data_p)
{
X2AP_X2AP_PDU_t pdu;
X2AP_X2SetupRequest_t *out;
X2AP_X2SetupRequest_IEs_t *ie;
X2AP_PLMN_Identity_t *plmn;
ServedCells__Member *servedCellMember;
X2AP_GU_Group_ID_t *gu;
uint8_t *buffer;
uint32_t len;
int ret = 0;
DevAssert(instance_p != NULL);
DevAssert(x2ap_eNB_data_p != NULL);
x2ap_eNB_data_p->state = X2AP_ENB_STATE_WAITING;
/* Prepare the X2AP message to encode */
memset(&pdu, 0, sizeof(pdu));
pdu.present = X2AP_X2AP_PDU_PR_initiatingMessage;
pdu.choice.initiatingMessage.procedureCode = X2AP_ProcedureCode_id_x2Setup;
pdu.choice.initiatingMessage.criticality = X2AP_Criticality_reject;
pdu.choice.initiatingMessage.value.present = X2AP_InitiatingMessage__value_PR_X2SetupRequest;
out = &pdu.choice.initiatingMessage.value.choice.X2SetupRequest;
/* mandatory */
ie = (X2AP_X2SetupRequest_IEs_t *)calloc(1, sizeof(X2AP_X2SetupRequest_IEs_t));
ie->id = X2AP_ProtocolIE_ID_id_GlobalENB_ID;
ie->criticality = X2AP_Criticality_reject;
ie->value.present = X2AP_X2SetupRequest_IEs__value_PR_GlobalENB_ID;
MCC_MNC_TO_PLMNID(instance_p->mcc, instance_p->mnc, instance_p->mnc_digit_length,
&ie->value.choice.GlobalENB_ID.pLMN_Identity);
ie->value.choice.GlobalENB_ID.eNB_ID.present = X2AP_ENB_ID_PR_macro_eNB_ID;
MACRO_ENB_ID_TO_BIT_STRING(instance_p->eNB_id,
&ie->value.choice.GlobalENB_ID.eNB_ID.choice.macro_eNB_ID);
X2AP_INFO("%d -> %02x%02x%02x\n", instance_p->eNB_id,
ie->value.choice.GlobalENB_ID.eNB_ID.choice.macro_eNB_ID.buf[0],
ie->value.choice.GlobalENB_ID.eNB_ID.choice.macro_eNB_ID.buf[1],
ie->value.choice.GlobalENB_ID.eNB_ID.choice.macro_eNB_ID.buf[2]);
ASN_SEQUENCE_ADD(&out->protocolIEs.list, ie);
/* mandatory */
ie = (X2AP_X2SetupRequest_IEs_t *)calloc(1, sizeof(X2AP_X2SetupRequest_IEs_t));
ie->id = X2AP_ProtocolIE_ID_id_ServedCells;
ie->criticality = X2AP_Criticality_reject;
ie->value.present = X2AP_X2SetupRequest_IEs__value_PR_ServedCells;
{
for (int i = 0; i<instance_p->num_cc; i++){
servedCellMember = (ServedCells__Member *)calloc(1,sizeof(ServedCells__Member));
{
servedCellMember->servedCellInfo.pCI = instance_p->Nid_cell[i];
MCC_MNC_TO_PLMNID(instance_p->mcc, instance_p->mnc, instance_p->mnc_digit_length,
&servedCellMember->servedCellInfo.cellId.pLMN_Identity);
MACRO_ENB_ID_TO_CELL_IDENTITY(instance_p->eNB_id,0,
&servedCellMember->servedCellInfo.cellId.eUTRANcellIdentifier);
INT16_TO_OCTET_STRING(instance_p->tac, &servedCellMember->servedCellInfo.tAC);
plmn = (X2AP_PLMN_Identity_t *)calloc(1,sizeof(X2AP_PLMN_Identity_t));
{
MCC_MNC_TO_PLMNID(instance_p->mcc, instance_p->mnc, instance_p->mnc_digit_length, plmn);
ASN_SEQUENCE_ADD(&servedCellMember->servedCellInfo.broadcastPLMNs.list, plmn);
}
if (instance_p->frame_type[i] == FDD) {
servedCellMember->servedCellInfo.eUTRA_Mode_Info.present = X2AP_EUTRA_Mode_Info_PR_fDD;
servedCellMember->servedCellInfo.eUTRA_Mode_Info.choice.fDD.dL_EARFCN = instance_p->fdd_earfcn_DL[i];
servedCellMember->servedCellInfo.eUTRA_Mode_Info.choice.fDD.uL_EARFCN = instance_p->fdd_earfcn_UL[i];
switch (instance_p->N_RB_DL[i]) {
case 6:
servedCellMember->servedCellInfo.eUTRA_Mode_Info.choice.fDD.uL_Transmission_Bandwidth = X2AP_Transmission_Bandwidth_bw6;
servedCellMember->servedCellInfo.eUTRA_Mode_Info.choice.fDD.dL_Transmission_Bandwidth = X2AP_Transmission_Bandwidth_bw6;
break;
case 15:
servedCellMember->servedCellInfo.eUTRA_Mode_Info.choice.fDD.uL_Transmission_Bandwidth = X2AP_Transmission_Bandwidth_bw15;
servedCellMember->servedCellInfo.eUTRA_Mode_Info.choice.fDD.dL_Transmission_Bandwidth = X2AP_Transmission_Bandwidth_bw15;
break;
case 25:
servedCellMember->servedCellInfo.eUTRA_Mode_Info.choice.fDD.uL_Transmission_Bandwidth = X2AP_Transmission_Bandwidth_bw25;
servedCellMember->servedCellInfo.eUTRA_Mode_Info.choice.fDD.dL_Transmission_Bandwidth = X2AP_Transmission_Bandwidth_bw25;
break;
case 50:
servedCellMember->servedCellInfo.eUTRA_Mode_Info.choice.fDD.uL_Transmission_Bandwidth = X2AP_Transmission_Bandwidth_bw50;
servedCellMember->servedCellInfo.eUTRA_Mode_Info.choice.fDD.dL_Transmission_Bandwidth = X2AP_Transmission_Bandwidth_bw50;
break;
case 75:
servedCellMember->servedCellInfo.eUTRA_Mode_Info.choice.fDD.uL_Transmission_Bandwidth = X2AP_Transmission_Bandwidth_bw75;
servedCellMember->servedCellInfo.eUTRA_Mode_Info.choice.fDD.dL_Transmission_Bandwidth = X2AP_Transmission_Bandwidth_bw75;
break;
case 100:
servedCellMember->servedCellInfo.eUTRA_Mode_Info.choice.fDD.uL_Transmission_Bandwidth = X2AP_Transmission_Bandwidth_bw100;
servedCellMember->servedCellInfo.eUTRA_Mode_Info.choice.fDD.dL_Transmission_Bandwidth = X2AP_Transmission_Bandwidth_bw100;
break;
default:
AssertFatal(0,"Failed: Check value for N_RB_DL/N_RB_UL");
break;
}
}
else {
AssertFatal(0,"X2Setuprequest not supported for TDD!");
}
}
ASN_SEQUENCE_ADD(&ie->value.choice.ServedCells.list, servedCellMember);
}
}
ASN_SEQUENCE_ADD(&out->protocolIEs.list, ie);
/* mandatory */
ie = (X2AP_X2SetupRequest_IEs_t *)calloc(1, sizeof(X2AP_X2SetupRequest_IEs_t));
ie->id = X2AP_ProtocolIE_ID_id_GUGroupIDList;
ie->criticality = X2AP_Criticality_reject;
ie->value.present = X2AP_X2SetupRequest_IEs__value_PR_GUGroupIDList;
{
gu = (X2AP_GU_Group_ID_t *)calloc(1, sizeof(X2AP_GU_Group_ID_t));
{
MCC_MNC_TO_PLMNID(instance_p->mcc, instance_p->mnc, instance_p->mnc_digit_length,
&gu->pLMN_Identity);
//@TODO: consider to update this value
INT16_TO_OCTET_STRING(0, &gu->mME_Group_ID);
}
ASN_SEQUENCE_ADD(&ie->value.choice.GUGroupIDList.list, gu);
}
ASN_SEQUENCE_ADD(&out->protocolIEs.list, ie);
if (x2ap_eNB_encode_pdu(&pdu, &buffer, &len) < 0) {
X2AP_ERROR("Failed to encode X2 setup request\n");
return -1;
}
MSC_LOG_TX_MESSAGE (MSC_X2AP_SRC_ENB, MSC_X2AP_TARGET_ENB, NULL, 0, "0 X2Setup/initiatingMessage assoc_id %u", x2ap_eNB_data_p->assoc_id);
x2ap_eNB_itti_send_sctp_data_req(instance_p->instance, x2ap_eNB_data_p->assoc_id, buffer, len, 0);
return ret;
}
int x2ap_eNB_generate_x2_setup_response(x2ap_eNB_data_t *x2ap_eNB_data_p)
{
X2AP_X2AP_PDU_t pdu;
X2AP_X2SetupResponse_t *out;
X2AP_X2SetupResponse_IEs_t *ie;
X2AP_PLMN_Identity_t *plmn;
ServedCells__Member *servedCellMember;
X2AP_GU_Group_ID_t *gu;
x2ap_eNB_instance_t *instance_p;
uint8_t *buffer;
uint32_t len;
int ret = 0;
DevAssert(x2ap_eNB_data_p != NULL);
/* get the eNB instance */
instance_p = x2ap_eNB_data_p->x2ap_eNB_instance;
DevAssert(instance_p != NULL);
/* Prepare the X2AP message to encode */
memset(&pdu, 0, sizeof(pdu));
pdu.present = X2AP_X2AP_PDU_PR_successfulOutcome;
pdu.choice.successfulOutcome.procedureCode = X2AP_ProcedureCode_id_x2Setup;
pdu.choice.successfulOutcome.criticality = X2AP_Criticality_reject;
pdu.choice.successfulOutcome.value.present = X2AP_SuccessfulOutcome__value_PR_X2SetupResponse;
out = &pdu.choice.successfulOutcome.value.choice.X2SetupResponse;
/* mandatory */
ie = (X2AP_X2SetupResponse_IEs_t *)calloc(1, sizeof(X2AP_X2SetupResponse_IEs_t));
ie->id = X2AP_ProtocolIE_ID_id_GlobalENB_ID;
ie->criticality = X2AP_Criticality_reject;
ie->value.present = X2AP_X2SetupResponse_IEs__value_PR_GlobalENB_ID;
MCC_MNC_TO_PLMNID(instance_p->mcc, instance_p->mnc, instance_p->mnc_digit_length,
&ie->value.choice.GlobalENB_ID.pLMN_Identity);
ie->value.choice.GlobalENB_ID.eNB_ID.present = X2AP_ENB_ID_PR_macro_eNB_ID;
MACRO_ENB_ID_TO_BIT_STRING(instance_p->eNB_id,
&ie->value.choice.GlobalENB_ID.eNB_ID.choice.macro_eNB_ID);
X2AP_INFO("%d -> %02x%02x%02x\n", instance_p->eNB_id,
ie->value.choice.GlobalENB_ID.eNB_ID.choice.macro_eNB_ID.buf[0],
ie->value.choice.GlobalENB_ID.eNB_ID.choice.macro_eNB_ID.buf[1],
ie->value.choice.GlobalENB_ID.eNB_ID.choice.macro_eNB_ID.buf[2]);
ASN_SEQUENCE_ADD(&out->protocolIEs.list, ie);
/* mandatory */
ie = (X2AP_X2SetupResponse_IEs_t *)calloc(1, sizeof(X2AP_X2SetupResponse_IEs_t));
ie->id = X2AP_ProtocolIE_ID_id_ServedCells;
ie->criticality = X2AP_Criticality_reject;
ie->value.present = X2AP_X2SetupResponse_IEs__value_PR_ServedCells;
{
for (int i = 0; i<instance_p->num_cc; i++){
servedCellMember = (ServedCells__Member *)calloc(1,sizeof(ServedCells__Member));
{
servedCellMember->servedCellInfo.pCI = instance_p->Nid_cell[i];
MCC_MNC_TO_PLMNID(instance_p->mcc, instance_p->mnc, instance_p->mnc_digit_length,
&servedCellMember->servedCellInfo.cellId.pLMN_Identity);
MACRO_ENB_ID_TO_CELL_IDENTITY(instance_p->eNB_id,0,
&servedCellMember->servedCellInfo.cellId.eUTRANcellIdentifier);
INT16_TO_OCTET_STRING(instance_p->tac, &servedCellMember->servedCellInfo.tAC);
plmn = (X2AP_PLMN_Identity_t *)calloc(1,sizeof(X2AP_PLMN_Identity_t));
{
MCC_MNC_TO_PLMNID(instance_p->mcc, instance_p->mnc, instance_p->mnc_digit_length, plmn);
ASN_SEQUENCE_ADD(&servedCellMember->servedCellInfo.broadcastPLMNs.list, plmn);
}
if (instance_p->frame_type[i] == FDD) {
servedCellMember->servedCellInfo.eUTRA_Mode_Info.present = X2AP_EUTRA_Mode_Info_PR_fDD;
servedCellMember->servedCellInfo.eUTRA_Mode_Info.choice.fDD.dL_EARFCN = instance_p->fdd_earfcn_DL[i];
servedCellMember->servedCellInfo.eUTRA_Mode_Info.choice.fDD.uL_EARFCN = instance_p->fdd_earfcn_UL[i];
switch (instance_p->N_RB_DL[i]) {
case 6:
servedCellMember->servedCellInfo.eUTRA_Mode_Info.choice.fDD.uL_Transmission_Bandwidth = X2AP_Transmission_Bandwidth_bw6;
servedCellMember->servedCellInfo.eUTRA_Mode_Info.choice.fDD.dL_Transmission_Bandwidth = X2AP_Transmission_Bandwidth_bw6;
break;
case 15:
servedCellMember->servedCellInfo.eUTRA_Mode_Info.choice.fDD.uL_Transmission_Bandwidth = X2AP_Transmission_Bandwidth_bw15;
servedCellMember->servedCellInfo.eUTRA_Mode_Info.choice.fDD.dL_Transmission_Bandwidth = X2AP_Transmission_Bandwidth_bw15;
break;
case 25:
servedCellMember->servedCellInfo.eUTRA_Mode_Info.choice.fDD.uL_Transmission_Bandwidth = X2AP_Transmission_Bandwidth_bw25;
servedCellMember->servedCellInfo.eUTRA_Mode_Info.choice.fDD.dL_Transmission_Bandwidth = X2AP_Transmission_Bandwidth_bw25;
break;
case 50:
servedCellMember->servedCellInfo.eUTRA_Mode_Info.choice.fDD.uL_Transmission_Bandwidth = X2AP_Transmission_Bandwidth_bw50;
servedCellMember->servedCellInfo.eUTRA_Mode_Info.choice.fDD.dL_Transmission_Bandwidth = X2AP_Transmission_Bandwidth_bw50;
break;
case 75:
servedCellMember->servedCellInfo.eUTRA_Mode_Info.choice.fDD.uL_Transmission_Bandwidth = X2AP_Transmission_Bandwidth_bw75;
servedCellMember->servedCellInfo.eUTRA_Mode_Info.choice.fDD.dL_Transmission_Bandwidth = X2AP_Transmission_Bandwidth_bw75;
break;
case 100:
servedCellMember->servedCellInfo.eUTRA_Mode_Info.choice.fDD.uL_Transmission_Bandwidth = X2AP_Transmission_Bandwidth_bw100;
servedCellMember->servedCellInfo.eUTRA_Mode_Info.choice.fDD.dL_Transmission_Bandwidth = X2AP_Transmission_Bandwidth_bw100;
break;
default:
AssertFatal(0,"Failed: Check value for N_RB_DL/N_RB_UL");
break;
}
}
else {
AssertFatal(0,"X2Setupresponse not supported for TDD!");
}
}
ASN_SEQUENCE_ADD(&ie->value.choice.ServedCells.list, servedCellMember);
}
}
ASN_SEQUENCE_ADD(&out->protocolIEs.list, ie);
/* mandatory */
ie = (X2AP_X2SetupResponse_IEs_t *)calloc(1, sizeof(X2AP_X2SetupResponse_IEs_t));
ie->id = X2AP_ProtocolIE_ID_id_GUGroupIDList;
ie->criticality = X2AP_Criticality_reject;
ie->value.present = X2AP_X2SetupResponse_IEs__value_PR_GUGroupIDList;
{
gu = (X2AP_GU_Group_ID_t *)calloc(1, sizeof(X2AP_GU_Group_ID_t));
{
MCC_MNC_TO_PLMNID(instance_p->mcc, instance_p->mnc, instance_p->mnc_digit_length,
&gu->pLMN_Identity);
//@TODO: consider to update this value
INT16_TO_OCTET_STRING(0, &gu->mME_Group_ID);
}
ASN_SEQUENCE_ADD(&ie->value.choice.GUGroupIDList.list, gu);
}
ASN_SEQUENCE_ADD(&out->protocolIEs.list, ie);
if (x2ap_eNB_encode_pdu(&pdu, &buffer, &len) < 0) {
X2AP_ERROR("Failed to encode X2 setup response\n");
return -1;
}
x2ap_eNB_data_p->state = X2AP_ENB_STATE_READY;
MSC_LOG_TX_MESSAGE (MSC_X2AP_SRC_ENB, MSC_X2AP_TARGET_ENB, NULL, 0, "0 X2Setup/successfulOutcome assoc_id %u", x2ap_eNB_data_p->assoc_id);
x2ap_eNB_itti_send_sctp_data_req(instance_p->instance, x2ap_eNB_data_p->assoc_id, buffer, len, 0);
return ret;
}
int x2ap_eNB_generate_x2_setup_failure(instance_t instance,
uint32_t assoc_id,
X2AP_Cause_PR cause_type,
long cause_value,
long time_to_wait)
{
X2AP_X2AP_PDU_t pdu;
X2AP_X2SetupFailure_t *out;
X2AP_X2SetupFailure_IEs_t *ie;
uint8_t *buffer;
uint32_t len;
int ret = 0;
/* Prepare the X2AP message to encode */
memset(&pdu, 0, sizeof(pdu));
pdu.present = X2AP_X2AP_PDU_PR_unsuccessfulOutcome;
pdu.choice.unsuccessfulOutcome.procedureCode = X2AP_ProcedureCode_id_x2Setup;
pdu.choice.unsuccessfulOutcome.criticality = X2AP_Criticality_reject;
pdu.choice.unsuccessfulOutcome.value.present = X2AP_UnsuccessfulOutcome__value_PR_X2SetupFailure;
out = &pdu.choice.unsuccessfulOutcome.value.choice.X2SetupFailure;
/* mandatory */
ie = (X2AP_X2SetupFailure_IEs_t *)calloc(1, sizeof(X2AP_X2SetupFailure_IEs_t));
ie->id = X2AP_ProtocolIE_ID_id_Cause;
ie->criticality = X2AP_Criticality_ignore;
ie->value.present = X2AP_X2SetupFailure_IEs__value_PR_Cause;
x2ap_eNB_set_cause (&ie->value.choice.Cause, cause_type, cause_value);
ASN_SEQUENCE_ADD(&out->protocolIEs.list, ie);
/* optional: consider to handle this later */
ie = (X2AP_X2SetupFailure_IEs_t *)calloc(1, sizeof(X2AP_X2SetupFailure_IEs_t));
ie->id = X2AP_ProtocolIE_ID_id_TimeToWait;
ie->criticality = X2AP_Criticality_ignore;
ie->value.present = X2AP_X2SetupFailure_IEs__value_PR_TimeToWait;
if (time_to_wait > -1) {
ie->value.choice.TimeToWait = time_to_wait;
}
ASN_SEQUENCE_ADD(&out->protocolIEs.list, ie);
if (x2ap_eNB_encode_pdu(&pdu, &buffer, &len) < 0) {
X2AP_ERROR("Failed to encode X2 setup failure\n");
return -1;
}
MSC_LOG_TX_MESSAGE (MSC_X2AP_SRC_ENB,
MSC_X2AP_TARGET_ENB, NULL, 0,
"0 X2Setup/unsuccessfulOutcome assoc_id %u cause %u value %u",
assoc_id, cause_type, cause_value);
x2ap_eNB_itti_send_sctp_data_req(instance, assoc_id, buffer, len, 0);
return ret;
}
int x2ap_eNB_set_cause (X2AP_Cause_t * cause_p,
X2AP_Cause_PR cause_type,
long cause_value)
{
DevAssert (cause_p != NULL);
cause_p->present = cause_type;
switch (cause_type) {
case X2AP_Cause_PR_radioNetwork:
cause_p->choice.misc = cause_value;
break;
case X2AP_Cause_PR_transport:
cause_p->choice.misc = cause_value;
break;
case X2AP_Cause_PR_protocol:
cause_p->choice.misc = cause_value;
break;
case X2AP_Cause_PR_misc:
cause_p->choice.misc = cause_value;
break;
default:
return -1;
}
return 0;
}
@@ -0,0 +1,44 @@
/*
* 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 X2AP_ENB_GENERATE_MESSAGES_H_
#define X2AP_ENB_GENERATE_MESSAGES_H_
#include "x2ap_eNB_defs.h"
#include "x2ap_common.h"
int x2ap_eNB_generate_x2_setup_request(x2ap_eNB_instance_t *instance_p,
x2ap_eNB_data_t *x2ap_enb_data_p);
int x2ap_eNB_generate_x2_setup_response(x2ap_eNB_data_t *x2ap_enb_data_p);
int x2ap_eNB_generate_x2_setup_failure(instance_t instance,
uint32_t assoc_id,
X2AP_Cause_PR cause_type,
long cause_value,
long time_to_wait);
int x2ap_eNB_set_cause (X2AP_Cause_t * cause_p,
X2AP_Cause_PR cause_type,
long cause_value);
#endif /* X2AP_ENB_GENERATE_MESSAGES_H_ */
+432
View File
@@ -0,0 +1,432 @@
/*
* 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
*/
#include <stdint.h>
#include "intertask_interface.h"
#include "asn1_conversions.h"
#include "x2ap_common.h"
#include "x2ap_eNB_defs.h"
#include "x2ap_eNB_handler.h"
#include "x2ap_eNB_decoder.h"
#include "x2ap_eNB_management_procedures.h"
#include "x2ap_eNB_generate_messages.h"
#include "msc.h"
#include "assertions.h"
#include "conversions.h"
static
int x2ap_eNB_handle_x2_setup_request (instance_t instance,
uint32_t assoc_id,
uint32_t stream,
X2AP_X2AP_PDU_t *pdu);
static
int x2ap_eNB_handle_x2_setup_response (instance_t instance,
uint32_t assoc_id,
uint32_t stream,
X2AP_X2AP_PDU_t *pdu);
static
int x2ap_eNB_handle_x2_setup_failure (instance_t instance,
uint32_t assoc_id,
uint32_t stream,
X2AP_X2AP_PDU_t *pdu);
/* Handlers matrix. Only eNB related procedure present here */
x2ap_message_decoded_callback x2ap_messages_callback[][3] = {
{ 0, 0, 0 }, /* handoverPreparation */
{ 0, 0, 0 }, /* handoverCancel */
{ 0, 0, 0 }, /* loadIndication */
{ 0, 0, 0 }, /* errorIndication */
{ 0, 0, 0 }, /* snStatusTransfer */
{ 0, 0, 0 }, /* uEContextRelease */
{ x2ap_eNB_handle_x2_setup_request, x2ap_eNB_handle_x2_setup_response, x2ap_eNB_handle_x2_setup_failure }, /* x2Setup */
{ 0, 0, 0 }, /* reset */
{ 0, 0, 0 }, /* eNBConfigurationUpdate */
{ 0, 0, 0 }, /* resourceStatusReportingInitiation */
{ 0, 0, 0 }, /* resourceStatusReporting */
{ 0, 0, 0 }, /* privateMessage */
{ 0, 0, 0 }, /* mobilitySettingsChange */
{ 0, 0, 0 }, /* rLFIndication */
{ 0, 0, 0 }, /* handoverReport */
{ 0, 0, 0 }, /* cellActivation */
{ 0, 0, 0 }, /* x2Release */
{ 0, 0, 0 }, /* x2APMessageTransfer */
{ 0, 0, 0 }, /* x2Removal */
{ 0, 0, 0 }, /* seNBAdditionPreparation */
{ 0, 0, 0 }, /* seNBReconfigurationCompletion */
{ 0, 0, 0 }, /* meNBinitiatedSeNBModificationPreparation */
{ 0, 0, 0 }, /* seNBinitiatedSeNBModification */
{ 0, 0, 0 }, /* meNBinitiatedSeNBRelease */
{ 0, 0, 0 }, /* seNBinitiatedSeNBRelease */
{ 0, 0, 0 }, /* seNBCounterCheck */
{ 0, 0, 0 } /* retrieveUEContext */
};
char *x2ap_direction2String(int x2ap_dir) {
static char *x2ap_direction_String[] = {
"", /* Nothing */
"Originating message", /* originating message */
"Successfull outcome", /* successfull outcome */
"UnSuccessfull outcome", /* successfull outcome */
};
return(x2ap_direction_String[x2ap_dir]);
}
void x2ap_handle_x2_setup_message(x2ap_eNB_data_t *enb_desc_p, int sctp_shutdown)
{
if (sctp_shutdown) {
/* A previously connected eNB has been shutdown */
/* TODO check if it was used by some eNB and send a message to inform these eNB if there is no more associated eNB */
if (enb_desc_p->state == X2AP_ENB_STATE_CONNECTED) {
enb_desc_p->state = X2AP_ENB_STATE_DISCONNECTED;
if (enb_desc_p->x2ap_eNB_instance-> x2_target_enb_associated_nb > 0) {
/* Decrease associated eNB number */
enb_desc_p->x2ap_eNB_instance-> x2_target_enb_associated_nb --;
}
/* If there are no more associated eNB, inform eNB app */
if (enb_desc_p->x2ap_eNB_instance->x2_target_enb_associated_nb == 0) {
MessageDef *message_p;
message_p = itti_alloc_new_message(TASK_X2AP, X2AP_DEREGISTERED_ENB_IND);
X2AP_DEREGISTERED_ENB_IND(message_p).nb_x2 = 0;
itti_send_msg_to_task(TASK_ENB_APP, enb_desc_p->x2ap_eNB_instance->instance, message_p);
}
}
} else {
/* Check that at least one setup message is pending */
DevCheck(enb_desc_p->x2ap_eNB_instance->x2_target_enb_pending_nb > 0,
enb_desc_p->x2ap_eNB_instance->instance,
enb_desc_p->x2ap_eNB_instance->x2_target_enb_pending_nb, 0);
if (enb_desc_p->x2ap_eNB_instance->x2_target_enb_pending_nb > 0) {
/* Decrease pending messages number */
enb_desc_p->x2ap_eNB_instance->x2_target_enb_pending_nb --;
}
/* If there are no more pending messages, inform eNB app */
if (enb_desc_p->x2ap_eNB_instance->x2_target_enb_pending_nb == 0) {
MessageDef *message_p;
message_p = itti_alloc_new_message(TASK_X2AP, X2AP_REGISTER_ENB_CNF);
X2AP_REGISTER_ENB_CNF(message_p).nb_x2 = enb_desc_p->x2ap_eNB_instance->x2_target_enb_associated_nb;
itti_send_msg_to_task(TASK_ENB_APP, enb_desc_p->x2ap_eNB_instance->instance, message_p);
}
}
}
int x2ap_eNB_handle_message(instance_t instance, uint32_t assoc_id, int32_t stream,
const uint8_t *const data, const uint32_t data_length)
{
X2AP_X2AP_PDU_t pdu;
int ret;
DevAssert(data != NULL);
memset(&pdu, 0, sizeof(pdu));
if (x2ap_eNB_decode_pdu(&pdu, data, data_length) < 0) {
X2AP_ERROR("Failed to decode PDU\n");
return -1;
}
/* Checking procedure Code and direction of message */
if (pdu.choice.initiatingMessage.procedureCode > sizeof(x2ap_messages_callback) / (3 * sizeof(
x2ap_message_decoded_callback))
|| (pdu.present > X2AP_X2AP_PDU_PR_unsuccessfulOutcome)) {
X2AP_ERROR("[SCTP %d] Either procedureCode %ld or direction %d exceed expected\n",
assoc_id, pdu.choice.initiatingMessage.procedureCode, pdu.present);
ASN_STRUCT_FREE_CONTENTS_ONLY(asn_DEF_X2AP_X2AP_PDU, &pdu);
return -1;
}
/* No handler present.
* This can mean not implemented or no procedure for eNB (wrong direction).
*/
if (x2ap_messages_callback[pdu.choice.initiatingMessage.procedureCode][pdu.present - 1] == NULL) {
X2AP_ERROR("[SCTP %d] No handler for procedureCode %ld in %s\n",
assoc_id, pdu.choice.initiatingMessage.procedureCode,
x2ap_direction2String(pdu.present - 1));
ASN_STRUCT_FREE_CONTENTS_ONLY(asn_DEF_X2AP_X2AP_PDU, &pdu);
return -1;
}
/* Calling the right handler */
ret = (*x2ap_messages_callback[pdu.choice.initiatingMessage.procedureCode][pdu.present - 1])
(instance, assoc_id, stream, &pdu);
ASN_STRUCT_FREE_CONTENTS_ONLY(asn_DEF_X2AP_X2AP_PDU, &pdu);
return ret;
}
int
x2ap_eNB_handle_x2_setup_request(instance_t instance,
uint32_t assoc_id,
uint32_t stream,
X2AP_X2AP_PDU_t *pdu)
{
X2AP_X2SetupRequest_t *x2SetupRequest;
X2AP_X2SetupRequest_IEs_t *ie;
x2ap_eNB_data_t *x2ap_eNB_data;
uint32_t eNB_id = 0;
DevAssert (pdu != NULL);
x2SetupRequest = &pdu->choice.initiatingMessage.value.choice.X2SetupRequest;
/*
* We received a new valid X2 Setup Request on a stream != 0.
* * * * This should not happen -> reject eNB x2 setup request.
*/
if (stream != 0) {
X2AP_ERROR("Received new x2 setup request on stream != 0\n");
/*
* Send a x2 setup failure with protocol cause unspecified
*/
return x2ap_eNB_generate_x2_setup_failure (instance,
assoc_id,
X2AP_Cause_PR_protocol,
X2AP_CauseProtocol_unspecified,
-1);
}
X2AP_DEBUG("Received a new X2 setup request\n");
X2AP_FIND_PROTOCOLIE_BY_ID(X2AP_X2SetupRequest_IEs_t, ie, x2SetupRequest,
X2AP_ProtocolIE_ID_id_GlobalENB_ID, true);
if (ie->value.choice.GlobalENB_ID.eNB_ID.present == X2AP_ENB_ID_PR_home_eNB_ID) {
// Home eNB ID = 28 bits
uint8_t *eNB_id_buf = ie->value.choice.GlobalENB_ID.eNB_ID.choice.home_eNB_ID.buf;
if (ie->value.choice.GlobalENB_ID.eNB_ID.choice.macro_eNB_ID.size != 28) {
//TODO: handle case were size != 28 -> notify ? reject ?
}
eNB_id = (eNB_id_buf[0] << 20) + (eNB_id_buf[1] << 12) + (eNB_id_buf[2] << 4) + ((eNB_id_buf[3] & 0xf0) >> 4);
X2AP_DEBUG("Home eNB id: %07x\n", eNB_id);
} else {
// Macro eNB = 20 bits
uint8_t *eNB_id_buf = ie->value.choice.GlobalENB_ID.eNB_ID.choice.macro_eNB_ID.buf;
if (ie->value.choice.GlobalENB_ID.eNB_ID.choice.macro_eNB_ID.size != 20) {
//TODO: handle case were size != 20 -> notify ? reject ?
}
eNB_id = (eNB_id_buf[0] << 12) + (eNB_id_buf[1] << 4) + ((eNB_id_buf[2] & 0xf0) >> 4);
X2AP_DEBUG("macro eNB id: %05x\n", eNB_id);
}
X2AP_DEBUG("Adding eNB to the list of associated eNBs\n");
if ((x2ap_eNB_data = x2ap_is_eNB_id_in_list (eNB_id)) == NULL) {
/*
* eNB has not been found in list of associated eNB,
* * * * Add it to the tail of list and initialize data
*/
if ((x2ap_eNB_data = x2ap_is_eNB_assoc_id_in_list (assoc_id)) == NULL) {
/*
* ??
*/
return -1;
} else {
x2ap_eNB_data->state = X2AP_ENB_STATE_RESETTING;
x2ap_eNB_data->eNB_id = eNB_id;
}
} else {
x2ap_eNB_data->state = X2AP_ENB_STATE_RESETTING;
/*
* eNB has been found in list, consider the x2 setup request as a reset connection,
* * * * reseting any previous UE state if sctp association is != than the previous one
*/
if (x2ap_eNB_data->assoc_id != assoc_id) {
/*
* ??: Send an overload cause...
*/
X2AP_ERROR("Rejecting x2 setup request as eNB id %d is already associated to an active sctp association" "Previous known: %d, new one: %d\n", eNB_id, x2ap_eNB_data->assoc_id, assoc_id);
DevAssert(x2ap_eNB_data->x2ap_eNB_instance != NULL);
x2ap_eNB_generate_x2_setup_failure (x2ap_eNB_data->x2ap_eNB_instance->instance,
assoc_id,
X2AP_Cause_PR_protocol,
X2AP_CauseProtocol_unspecified,
-1);
return -1;
}
/*
* TODO: call the reset procedure
*/
}
return x2ap_eNB_generate_x2_setup_response(x2ap_eNB_data);
}
static
int x2ap_eNB_handle_x2_setup_response(instance_t instance,
uint32_t assoc_id,
uint32_t stream,
X2AP_X2AP_PDU_t *pdu)
{
X2AP_X2SetupResponse_t *x2SetupResponse;
X2AP_X2SetupResponse_IEs_t *ie;
x2ap_eNB_data_t *x2ap_eNB_data;
uint32_t eNB_id = 0;
DevAssert (pdu != NULL);
x2SetupResponse = &pdu->choice.successfulOutcome.value.choice.X2SetupResponse;
/*
* We received a new valid X2 Setup Response on a stream != 0.
* * * * This should not happen -> reject eNB x2 setup response.
*/
if (stream != 0) {
X2AP_ERROR("Received new x2 setup response on stream != 0\n");
}
if ((x2ap_eNB_data = x2ap_get_eNB(NULL, assoc_id, 0)) == NULL) {
X2AP_ERROR("[SCTP %d] Received X2 setup response for non existing "
"eNB context\n", assoc_id);
return -1;
}
X2AP_DEBUG("Received a new X2 setup response\n");
X2AP_FIND_PROTOCOLIE_BY_ID(X2AP_X2SetupResponse_IEs_t, ie, x2SetupResponse,
X2AP_ProtocolIE_ID_id_GlobalENB_ID, true);
if (ie->value.choice.GlobalENB_ID.eNB_ID.present == X2AP_ENB_ID_PR_home_eNB_ID) {
// Home eNB ID = 28 bits
uint8_t *eNB_id_buf = ie->value.choice.GlobalENB_ID.eNB_ID.choice.home_eNB_ID.buf;
if (ie->value.choice.GlobalENB_ID.eNB_ID.choice.macro_eNB_ID.size != 28) {
//TODO: handle case were size != 28 -> notify ? reject ?
}
eNB_id = (eNB_id_buf[0] << 20) + (eNB_id_buf[1] << 12) + (eNB_id_buf[2] << 4) + ((eNB_id_buf[3] & 0xf0) >> 4);
X2AP_DEBUG("Home eNB id: %07x\n", eNB_id);
} else {
// Macro eNB = 20 bits
uint8_t *eNB_id_buf = ie->value.choice.GlobalENB_ID.eNB_ID.choice.macro_eNB_ID.buf;
if (ie->value.choice.GlobalENB_ID.eNB_ID.choice.macro_eNB_ID.size != 20) {
//TODO: handle case were size != 20 -> notify ? reject ?
}
eNB_id = (eNB_id_buf[0] << 12) + (eNB_id_buf[1] << 4) + ((eNB_id_buf[2] & 0xf0) >> 4);
X2AP_DEBUG("macro eNB id: %05x\n", eNB_id);
}
X2AP_DEBUG("Adding eNB to the list of associated eNBs\n");
if ((x2ap_eNB_data = x2ap_is_eNB_id_in_list (eNB_id)) == NULL) {
/*
* eNB has not been found in list of associated eNB,
* * * * Add it to the tail of list and initialize data
*/
if ((x2ap_eNB_data = x2ap_is_eNB_assoc_id_in_list (assoc_id)) == NULL) {
/*
* ??: Send an overload cause...
*/
return -1;
} else {
x2ap_eNB_data->state = X2AP_ENB_STATE_RESETTING;
x2ap_eNB_data->eNB_id = eNB_id;
}
} else {
x2ap_eNB_data->state = X2AP_ENB_STATE_RESETTING;
/*
* TODO: call the reset procedure
*/
}
/* Optionaly set the target eNB name */
/* The association is now ready as source and target eNBs know parameters of each other.
* Mark the association as connected.
*/
x2ap_eNB_data->state = X2AP_ENB_STATE_READY;
x2ap_eNB_data->x2ap_eNB_instance->x2_target_enb_associated_nb ++;
x2ap_handle_x2_setup_message(x2ap_eNB_data, 0);
return 0;
}
static
int x2ap_eNB_handle_x2_setup_failure(instance_t instance,
uint32_t assoc_id,
uint32_t stream,
X2AP_X2AP_PDU_t *pdu)
{
X2AP_X2SetupFailure_t *x2SetupFailure;
X2AP_X2SetupFailure_IEs_t *ie;
x2ap_eNB_data_t *x2ap_eNB_data;
DevAssert(pdu != NULL);
x2SetupFailure = &pdu->choice.unsuccessfulOutcome.value.choice.X2SetupFailure;
/*
* We received a new valid X2 Setup Failure on a stream != 0.
* * * * This should not happen -> reject eNB x2 setup failure.
*/
if (stream != 0) {
X2AP_WARN("[SCTP %d] Received x2 setup failure on stream != 0 (%d)\n",
assoc_id, stream);
}
if ((x2ap_eNB_data = x2ap_get_eNB (NULL, assoc_id, 0)) == NULL) {
X2AP_ERROR("[SCTP %d] Received X2 setup failure for non existing "
"eNB context\n", assoc_id);
return -1;
}
X2AP_DEBUG("Received a new X2 setup failure\n");
X2AP_FIND_PROTOCOLIE_BY_ID(X2AP_X2SetupFailure_IEs_t, ie, x2SetupFailure,
X2AP_ProtocolIE_ID_id_Cause, true);
// need a FSM to handle all cases
if ((ie->value.choice.Cause.present == X2AP_Cause_PR_misc) &&
(ie->value.choice.Cause.choice.misc == X2AP_CauseMisc_unspecified)) {
X2AP_WARN("Received X2 setup failure for eNB ... eNB is not ready\n");
} else {
X2AP_ERROR("Received x2 setup failure for eNB... please check your parameters\n");
}
x2ap_eNB_data->state = X2AP_ENB_STATE_WAITING;
x2ap_handle_x2_setup_message(x2ap_eNB_data, 0);
return 0;
}

Some files were not shown because too many files have changed in this diff Show More