Merge remote-tracking branch 'eurecom_gitlab/develop' into DRX_develop
This commit is contained in:
@@ -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)
|
||||
@@ -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)
|
||||
|
||||
@@ -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_ */
|
||||
|
||||
@@ -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"
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -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
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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
File diff suppressed because it is too large
Load Diff
@@ -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
@@ -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"
|
||||
/*-------------------------------------------------------------------------------------------------------------------------------------------------------------*/
|
||||
|
||||
@@ -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 */
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -37,7 +37,6 @@
|
||||
|
||||
# include "tree.h"
|
||||
# include "intertask_interface.h"
|
||||
# include "timer.h"
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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
@@ -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
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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
@@ -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
|
||||
|
||||
@@ -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
@@ -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)
|
||||
|
||||
+1228
-898
File diff suppressed because it is too large
Load Diff
@@ -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);
|
||||
|
||||
@@ -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",
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
|
||||
+597
-383
File diff suppressed because it is too large
Load Diff
@@ -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
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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);
|
||||
|
||||
|
||||
@@ -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) {
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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",
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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))
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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
@@ -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);
|
||||
|
||||
@@ -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;
|
||||
|
||||
|
||||
@@ -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
@@ -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
@@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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];
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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"
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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")
|
||||
|
||||
@@ -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
@@ -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
@@ -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
@@ -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) {
|
||||
|
||||
@@ -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__ */
|
||||
@@ -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:
|
||||
*/
|
||||
@@ -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);
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
@@ -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_ */
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
@@ -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_ */
|
||||
@@ -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_ */
|
||||
|
||||
@@ -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
Reference in New Issue
Block a user