/* * 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 "openair2/LAYER2/MAC/mac_extern.h" #include "openair2/LAYER2/MAC/mac.h" #include "openair2/LAYER2/MAC/mac_proto.h" #include "openair1/SCHED_UE/sched_UE.h" #include "nfapi/open-nFAPI/nfapi/public_inc/nfapi_interface.h" #include "openair2/PHY_INTERFACE/phy_stub_UE.h" #include "openair2/ENB_APP/L1_paramdef.h" #include "openair2/ENB_APP/enb_paramdef.h" #include "targets/ARCH/ETHERNET/USERSPACE/LIB/if_defs.h" #include "common/config/config_load_configmodule.h" #include "common/config/config_userapi.h" #include <arpa/inet.h> #include <string.h> #include <errno.h> extern int oai_nfapi_rach_ind(nfapi_rach_indication_t *rach_ind); void configure_nfapi_pnf(char *vnf_ip_addr, int vnf_p5_port, char *pnf_ip_addr, int pnf_p7_port, int vnf_p7_port); UL_IND_t *UL_INFO = NULL; queue_t dl_config_req_queue; queue_t tx_req_pdu_queue; queue_t ul_config_req_queue; queue_t hi_dci0_req_queue; int current_sfn_sf; sem_t sfn_semaphore; static int ue_tx_sock_descriptor = -1; static int ue_rx_sock_descriptor = -1; extern nfapi_tx_request_pdu_t* tx_request_pdu[1023][10][10]; //extern int timer_subframe; //extern int timer_frame; extern uint16_t sf_ahead; void Msg1_transmitted(module_id_t module_idP,uint8_t CC_id,frame_t frameP, uint8_t eNB_id); void Msg3_transmitted(module_id_t module_idP,uint8_t CC_id,frame_t frameP, uint8_t eNB_id); void fill_rx_indication_UE_MAC(module_id_t Mod_id, int frame, int subframe, UL_IND_t *UL_INFO, uint8_t *ulsch_buffer, uint16_t buflen, uint16_t rnti, int index, nfapi_ul_config_request_t *ul_config_req) { nfapi_rx_indication_pdu_t *pdu; int timing_advance_update; pthread_mutex_lock(&fill_ul_mutex.rx_mutex); UL_INFO->rx_ind.header.message_id = NFAPI_RX_ULSCH_INDICATION; UL_INFO->rx_ind.sfn_sf = frame << 4 | subframe; UL_INFO->rx_ind.rx_indication_body.tl.tag = NFAPI_RX_INDICATION_BODY_TAG; UL_INFO->rx_ind.vendor_extension = ul_config_req->vendor_extension; pdu = &UL_INFO->rx_ind.rx_indication_body .rx_pdu_list[UL_INFO->rx_ind.rx_indication_body.number_of_pdus]; // pdu = &UL_INFO->rx_ind.rx_indication_body.rx_pdu_list[index]; // pdu->rx_ue_information.handle = eNB->ulsch[UE_id]->handle; pdu->rx_ue_information.tl.tag = NFAPI_RX_UE_INFORMATION_TAG; pdu->rx_ue_information.rnti = rnti; pdu->rx_indication_rel8.tl.tag = NFAPI_RX_INDICATION_REL8_TAG; pdu->rx_indication_rel8.length = buflen; pdu->rx_indication_rel8.offset = 1; pdu->rx_indication_rel9.tl.tag = NFAPI_RX_INDICATION_REL9_TAG; pdu->rx_indication_rel9.timing_advance_r9 = 0; // ulsch_buffer is necessary to keep its value. pdu->data = malloc(buflen); memcpy(pdu->data, ulsch_buffer, buflen); // estimate timing advance for MAC timing_advance_update = 0; // Don't know what to put here pdu->rx_indication_rel8.timing_advance = timing_advance_update; int SNRtimes10 = 640; if (SNRtimes10 < -640) pdu->rx_indication_rel8.ul_cqi = 0; else if (SNRtimes10 > 635) pdu->rx_indication_rel8.ul_cqi = 255; else pdu->rx_indication_rel8.ul_cqi = (640 + SNRtimes10) / 5; UL_INFO->rx_ind.rx_indication_body.number_of_pdus++; UL_INFO->rx_ind.sfn_sf = frame << 4 | subframe; pthread_mutex_unlock(&fill_ul_mutex.rx_mutex); } void fill_sr_indication_UE_MAC(int Mod_id, int frame, int subframe, UL_IND_t *UL_INFO, uint16_t rnti, nfapi_ul_config_request_t *ul_config_req) { pthread_mutex_lock(&fill_ul_mutex.sr_mutex); LOG_I(MAC, "Entered fill_sr_indication_UE_MAC\n"); nfapi_sr_indication_t *sr_ind = &UL_INFO->sr_ind; nfapi_sr_indication_body_t *sr_ind_body = &sr_ind->sr_indication_body; nfapi_sr_indication_pdu_t *pdu = &sr_ind_body->sr_pdu_list[sr_ind_body->number_of_srs]; UL_INFO->sr_ind.vendor_extension = ul_config_req->vendor_extension; sr_ind->sfn_sf = frame << 4 | subframe; sr_ind->header.message_id = NFAPI_RX_SR_INDICATION; sr_ind_body->tl.tag = NFAPI_SR_INDICATION_BODY_TAG; pdu->instance_length = 0; // don't know what to do with this // pdu->rx_ue_information.handle = handle; pdu->rx_ue_information.tl.tag = NFAPI_RX_UE_INFORMATION_TAG; pdu->rx_ue_information.rnti = rnti; // UE_mac_inst[Mod_id].crnti pdu->ul_cqi_information.tl.tag = NFAPI_UL_CQI_INFORMATION_TAG; pdu->ul_cqi_information.channel = 0; int SNRtimes10 = 640; if (SNRtimes10 < -640) pdu->ul_cqi_information.ul_cqi = 0; else if (SNRtimes10 > 635) pdu->ul_cqi_information.ul_cqi = 255; else pdu->ul_cqi_information.ul_cqi = (640 + SNRtimes10) / 5; // UL_INFO->rx_ind.rx_indication_body.number_of_pdus++; sr_ind_body->number_of_srs++; pthread_mutex_unlock(&fill_ul_mutex.sr_mutex); } void fill_crc_indication_UE_MAC(int Mod_id, int frame, int subframe, UL_IND_t *UL_INFO, uint8_t crc_flag, int index, uint16_t rnti, nfapi_ul_config_request_t *ul_config_req) { pthread_mutex_lock(&fill_ul_mutex.crc_mutex); LOG_I(MAC, "Entered fill_crc_indication_UE_MAC Frame %d Subframe %d\n", frame, subframe); nfapi_crc_indication_pdu_t *pdu = &UL_INFO->crc_ind.crc_indication_body .crc_pdu_list[UL_INFO->crc_ind.crc_indication_body.number_of_crcs]; UL_INFO->crc_ind.sfn_sf = frame << 4 | subframe; UL_INFO->crc_ind.vendor_extension = ul_config_req->vendor_extension; UL_INFO->crc_ind.header.message_id = NFAPI_CRC_INDICATION; UL_INFO->crc_ind.crc_indication_body.tl.tag = NFAPI_CRC_INDICATION_BODY_TAG; pdu->instance_length = 0; pdu->rx_ue_information.tl.tag = NFAPI_RX_UE_INFORMATION_TAG; pdu->rx_ue_information.rnti = rnti; pdu->crc_indication_rel8.tl.tag = NFAPI_CRC_INDICATION_REL8_TAG; pdu->crc_indication_rel8.crc_flag = crc_flag; UL_INFO->crc_ind.crc_indication_body.number_of_crcs++; LOG_D(PHY, "%s() rnti:%04x pdus:%d\n", __FUNCTION__, pdu->rx_ue_information.rnti, UL_INFO->crc_ind.crc_indication_body.number_of_crcs); pthread_mutex_unlock(&fill_ul_mutex.crc_mutex); } void fill_rach_indication_UE_MAC(int Mod_id, int frame, int subframe, UL_IND_t *UL_INFO, uint8_t ra_PreambleIndex, uint16_t ra_RNTI) { LOG_D(MAC, "fill_rach_indication_UE_MAC 1 \n"); pthread_mutex_lock(&fill_ul_mutex.rach_mutex); UL_INFO->rach_ind.rach_indication_body.number_of_preambles = 1; UL_INFO->rach_ind.header.message_id = NFAPI_RACH_INDICATION; UL_INFO->rach_ind.sfn_sf = frame << 4 | subframe; UL_INFO->rach_ind.vendor_extension = NULL; UL_INFO->rach_ind.rach_indication_body.tl.tag = NFAPI_RACH_INDICATION_BODY_TAG; const int np = UL_INFO->rach_ind.rach_indication_body.number_of_preambles; UL_INFO->rach_ind.rach_indication_body.preamble_list = calloc(np, sizeof(nfapi_preamble_pdu_t)); UL_INFO->rach_ind.rach_indication_body.preamble_list[0].preamble_rel8.tl.tag = NFAPI_PREAMBLE_REL8_TAG; UL_INFO->rach_ind.rach_indication_body.preamble_list[0] .preamble_rel8.timing_advance = 0; // Not sure about that // The two following should get extracted from the call to // get_prach_resources(). UL_INFO->rach_ind.rach_indication_body.preamble_list[0] .preamble_rel8.preamble = ra_PreambleIndex; UL_INFO->rach_ind.rach_indication_body.preamble_list[0].preamble_rel8.rnti = ra_RNTI; // UL_INFO->rach_ind.rach_indication_body.number_of_preambles++; UL_INFO->rach_ind.rach_indication_body.preamble_list[0] .preamble_rel13.rach_resource_type = 0; UL_INFO->rach_ind.rach_indication_body.preamble_list[0].instance_length = 0; LOG_D(PHY, "UE Filling NFAPI indication for RACH : TA %d, Preamble %d, rnti %x, " "rach_resource_type %d\n", UL_INFO->rach_ind.rach_indication_body.preamble_list[0] .preamble_rel8.timing_advance, UL_INFO->rach_ind.rach_indication_body.preamble_list[0] .preamble_rel8.preamble, UL_INFO->rach_ind.rach_indication_body.preamble_list[0] .preamble_rel8.rnti, UL_INFO->rach_ind.rach_indication_body.preamble_list[0] .preamble_rel13.rach_resource_type); // This function is currently defined only in the nfapi-RU-RAU-split so we // should call it when we merge with that branch. // TODO Andrew - send proxy specific socket instead of oai_nfapi_rach_ind Send the whole UL_INFO struct // as soon as numberof preambles if (NFAPI_MODE == NFAPI_MODE_STANDALONE_PNF) { send_standalone_msg(UL_INFO, UL_INFO->rach_ind.header.message_id); } else { oai_nfapi_rach_ind(&UL_INFO->rach_ind); } free(UL_INFO->rach_ind.rach_indication_body.preamble_list); pthread_mutex_unlock(&fill_ul_mutex.rach_mutex); } void fill_ulsch_cqi_indication_UE_MAC(int Mod_id, uint16_t frame, uint8_t subframe, UL_IND_t *UL_INFO, uint16_t rnti) { pthread_mutex_lock(&fill_ul_mutex.cqi_mutex); nfapi_cqi_indication_pdu_t *pdu = &UL_INFO->cqi_ind.cqi_indication_body .cqi_pdu_list[UL_INFO->cqi_ind.cqi_indication_body.number_of_cqis]; nfapi_cqi_indication_raw_pdu_t *raw_pdu = &UL_INFO->cqi_ind.cqi_indication_body.cqi_raw_pdu_list [UL_INFO->cqi_ind.cqi_indication_body.number_of_cqis]; LOG_I(MAC, "Entered fill_ulsch_cqi_indication_UE_MAC\n"); UL_INFO->cqi_ind.sfn_sf = frame << 4 | subframe; // because of nfapi_vnf.c:733, set message id to 0, not // NFAPI_RX_CQI_INDICATION; UL_INFO->cqi_ind.header.message_id = NFAPI_RX_CQI_INDICATION; UL_INFO->cqi_ind.cqi_indication_body.tl.tag = NFAPI_CQI_INDICATION_BODY_TAG; pdu->rx_ue_information.tl.tag = NFAPI_RX_UE_INFORMATION_TAG; pdu->rx_ue_information.rnti = rnti; // Since we assume that CRC flag is always 0 (ACK) I guess that data_offset // should always be 0. pdu->cqi_indication_rel8.data_offset = 0; pdu->cqi_indication_rel8.tl.tag = NFAPI_CQI_INDICATION_REL8_TAG; pdu->cqi_indication_rel8.length = 1; pdu->cqi_indication_rel8.ri = 0; pdu->cqi_indication_rel8.timing_advance = 0; // pdu->cqi_indication_rel8.number_of_cc_reported = 1; pdu->ul_cqi_information.tl.tag = NFAPI_UL_CQI_INFORMATION_TAG; pdu->ul_cqi_information.channel = 1; // PUSCH // eNB_scheduler_primitives.c:4839: the upper four bits seem to be the CQI const int cqi = 15; raw_pdu->pdu[0] = cqi << 4; UL_INFO->cqi_ind.cqi_indication_body.number_of_cqis++; pthread_mutex_unlock(&fill_ul_mutex.cqi_mutex); } void fill_ulsch_harq_indication_UE_MAC( int Mod_id, int frame, int subframe, UL_IND_t *UL_INFO, nfapi_ul_config_ulsch_harq_information *harq_information, uint16_t rnti, nfapi_ul_config_request_t *ul_config_req) { pthread_mutex_lock(&fill_ul_mutex.harq_mutex); LOG_I(MAC, "Entered fill_ulsch_harq_indication_UE_MAC\n"); nfapi_harq_indication_pdu_t *pdu = &UL_INFO->harq_ind.harq_indication_body.harq_pdu_list [UL_INFO->harq_ind.harq_indication_body.number_of_harqs]; UL_INFO->harq_ind.header.message_id = NFAPI_HARQ_INDICATION; UL_INFO->harq_ind.sfn_sf = frame << 4 | subframe; UL_INFO->harq_ind.vendor_extension = ul_config_req->vendor_extension; UL_INFO->harq_ind.harq_indication_body.tl.tag = NFAPI_HARQ_INDICATION_BODY_TAG; pdu->instance_length = 0; // don't know what to do with this // pdu->rx_ue_information.handle = handle; pdu->rx_ue_information.tl.tag = NFAPI_RX_UE_INFORMATION_TAG; pdu->rx_ue_information.rnti = rnti; // For now we consider only FDD // if (eNB->frame_parms.frame_type == FDD) { pdu->harq_indication_fdd_rel13.tl.tag = NFAPI_HARQ_INDICATION_FDD_REL13_TAG; pdu->harq_indication_fdd_rel13.mode = 0; pdu->harq_indication_fdd_rel13.number_of_ack_nack = harq_information->harq_information_rel10.harq_size; // Could this be wrong? Is the number_of_ack_nack field equivalent to O_ACK? // pdu->harq_indication_fdd_rel13.number_of_ack_nack = ulsch_harq->O_ACK; for (int i = 0; i < harq_information->harq_information_rel10.harq_size; i++) { pdu->harq_indication_fdd_rel13.harq_tb_n[i] = 1; // Assume always ACK (No NACK or DTX) } UL_INFO->harq_ind.harq_indication_body.number_of_harqs++; pthread_mutex_unlock(&fill_ul_mutex.harq_mutex); } void fill_uci_harq_indication_UE_MAC(int Mod_id, int frame, int subframe, UL_IND_t *UL_INFO, nfapi_ul_config_harq_information *harq_information, uint16_t rnti, nfapi_ul_config_request_t *ul_config_req) { pthread_mutex_lock(&fill_ul_mutex.harq_mutex); nfapi_harq_indication_t *ind = &UL_INFO->harq_ind; nfapi_harq_indication_body_t *body = &ind->harq_indication_body; nfapi_harq_indication_pdu_t *pdu = &body->harq_pdu_list[UL_INFO->harq_ind.harq_indication_body .number_of_harqs]; LOG_I(MAC, "Entered fill_uci_harq_indication_UE_MAC\n"); UL_INFO->harq_ind.vendor_extension = ul_config_req->vendor_extension; ind->sfn_sf = frame << 4 | subframe; ind->header.message_id = NFAPI_HARQ_INDICATION; body->tl.tag = NFAPI_HARQ_INDICATION_BODY_TAG; pdu->rx_ue_information.tl.tag = NFAPI_RX_UE_INFORMATION_TAG; pdu->instance_length = 0; // don't know what to do with this pdu->rx_ue_information.rnti = rnti; pdu->ul_cqi_information.tl.tag = NFAPI_UL_CQI_INFORMATION_TAG; int SNRtimes10 = 640; if (SNRtimes10 < -640) pdu->ul_cqi_information.ul_cqi = 0; else if (SNRtimes10 > 635) pdu->ul_cqi_information.ul_cqi = 255; else pdu->ul_cqi_information.ul_cqi = (640 + SNRtimes10) / 5; pdu->ul_cqi_information.channel = 0; if (harq_information->harq_information_rel9_fdd.tl.tag == NFAPI_UL_CONFIG_REQUEST_HARQ_INFORMATION_REL9_FDD_TAG) { if ((harq_information->harq_information_rel9_fdd.ack_nack_mode == 0) && (harq_information->harq_information_rel9_fdd.harq_size == 1)) { pdu->harq_indication_fdd_rel13.tl.tag = NFAPI_HARQ_INDICATION_FDD_REL13_TAG; pdu->harq_indication_fdd_rel13.mode = 0; pdu->harq_indication_fdd_rel13.number_of_ack_nack = 1; // AssertFatal(harq_ack[0] == 1 || harq_ack[0] == 2 || harq_ack[0] == 4, // "harq_ack[0] is %d, should be 1,2 or 4\n",harq_ack[0]); pdu->harq_indication_fdd_rel13.harq_tb_n[0] = 1; // Assuming always an ACK (No NACK or DTX) } else if ((harq_information->harq_information_rel9_fdd.ack_nack_mode == 0) && (harq_information->harq_information_rel9_fdd.harq_size == 2)) { pdu->harq_indication_fdd_rel13.tl.tag = NFAPI_HARQ_INDICATION_FDD_REL13_TAG; pdu->harq_indication_fdd_rel13.mode = 0; pdu->harq_indication_fdd_rel13.number_of_ack_nack = 2; pdu->harq_indication_fdd_rel13.harq_tb_n[0] = 1; // Assuming always an ACK (No NACK or DTX) pdu->harq_indication_fdd_rel13.harq_tb_n[1] = 1; // Assuming always an ACK (No NACK or DTX) } } else if (harq_information->harq_information_rel10_tdd.tl.tag == NFAPI_UL_CONFIG_REQUEST_HARQ_INFORMATION_REL10_TDD_TAG) { if ((harq_information->harq_information_rel10_tdd.ack_nack_mode == 0) && (harq_information->harq_information_rel10_tdd.harq_size == 1)) { pdu->harq_indication_tdd_rel13.tl.tag = NFAPI_HARQ_INDICATION_TDD_REL13_TAG; pdu->harq_indication_tdd_rel13.mode = 0; pdu->harq_indication_tdd_rel13.number_of_ack_nack = 1; pdu->harq_indication_tdd_rel13.harq_data[0].bundling.value_0 = 1; } else if ((harq_information->harq_information_rel10_tdd.ack_nack_mode == 1) && (harq_information->harq_information_rel10_tdd.harq_size == 2)) { pdu->harq_indication_tdd_rel13.tl.tag = NFAPI_HARQ_INDICATION_TDD_REL13_TAG; pdu->harq_indication_tdd_rel13.mode = 0; pdu->harq_indication_tdd_rel13.number_of_ack_nack = 1; pdu->harq_indication_tdd_rel13.harq_data[0].bundling.value_0 = 1; pdu->harq_indication_tdd_rel13.harq_data[1].bundling.value_0 = 1; } } else AssertFatal(1 == 0, "only format 1a/b for now, received \n"); UL_INFO->harq_ind.harq_indication_body.number_of_harqs++; LOG_D(PHY, "Incremented eNB->UL_INFO.harq_ind.number_of_harqs:%d\n", UL_INFO->harq_ind.harq_indication_body.number_of_harqs); pthread_mutex_unlock(&fill_ul_mutex.harq_mutex); } void handle_nfapi_ul_pdu_UE_MAC(module_id_t Mod_id, nfapi_ul_config_request_pdu_t *ul_config_pdu, uint16_t frame, uint8_t subframe, uint8_t srs_present, int index, nfapi_ul_config_request_t *ul_config_req) { if (ul_config_pdu->pdu_type == NFAPI_UL_CONFIG_ULSCH_PDU_TYPE) { LOG_D(PHY, "Applying UL config for UE, rnti %x for frame %d, subframe %d\n", (ul_config_pdu->ulsch_pdu.ulsch_pdu_rel8).rnti, frame, subframe); uint8_t ulsch_buffer[5477] __attribute__((aligned(32))); uint16_t buflen = ul_config_pdu->ulsch_pdu.ulsch_pdu_rel8.size; uint16_t rnti = ul_config_pdu->ulsch_pdu.ulsch_pdu_rel8.rnti; uint8_t access_mode = SCHEDULED_ACCESS; if (buflen > 0) { if (UE_mac_inst[Mod_id].first_ULSCH_Tx == 1) { // Msg3 case LOG_D(MAC, "handle_nfapi_ul_pdu_UE_MAC 2.2, Mod_id:%d, SFN/SF: %d/%d \n", Mod_id, frame, subframe); fill_crc_indication_UE_MAC(Mod_id, frame, subframe, UL_INFO, 0, index, rnti, ul_config_req); fill_rx_indication_UE_MAC(Mod_id, frame, subframe, UL_INFO, UE_mac_inst[Mod_id].RA_prach_resources.Msg3, buflen, rnti, index, ul_config_req); Msg3_transmitted(Mod_id, 0, frame, 0); // Modification UE_mac_inst[Mod_id].UE_mode[0] = PUSCH; UE_mac_inst[Mod_id].first_ULSCH_Tx = 0; // This should be done after the reception of the respective hi_dci0 // UE_mac_inst[Mod_id].first_ULSCH_Tx = 0; } else { ue_get_sdu(Mod_id, 0, frame, subframe, 0, ulsch_buffer, buflen, &access_mode); fill_crc_indication_UE_MAC(Mod_id, frame, subframe, UL_INFO, 0, index, rnti, ul_config_req); fill_rx_indication_UE_MAC(Mod_id, frame, subframe, UL_INFO, ulsch_buffer, buflen, rnti, index, ul_config_req); } } } else if (ul_config_pdu->pdu_type == NFAPI_UL_CONFIG_ULSCH_HARQ_PDU_TYPE) { // AssertFatal((UE_id = // find_ulsch(ul_config_pdu->ulsch_harq_pdu.ulsch_pdu.ulsch_pdu_rel8.rnti,eNB,SEARCH_EXIST_OR_FREE))>=0, // "No available UE ULSCH for rnti // %x\n",ul_config_pdu->ulsch_harq_pdu.ulsch_pdu.ulsch_pdu_rel8.rnti); uint8_t ulsch_buffer[5477] __attribute__((aligned(32))); uint16_t buflen = ul_config_pdu->ulsch_harq_pdu.ulsch_pdu.ulsch_pdu_rel8.size; nfapi_ul_config_ulsch_harq_information *ulsch_harq_information = &ul_config_pdu->ulsch_harq_pdu.harq_information; uint16_t rnti = ul_config_pdu->ulsch_harq_pdu.ulsch_pdu.ulsch_pdu_rel8.rnti; uint8_t access_mode = SCHEDULED_ACCESS; if (buflen > 0) { if (UE_mac_inst[Mod_id].first_ULSCH_Tx == 1) { // Msg3 case fill_crc_indication_UE_MAC(Mod_id, frame, subframe, UL_INFO, 0, index, rnti, ul_config_req); fill_rx_indication_UE_MAC(Mod_id, frame, subframe, UL_INFO, UE_mac_inst[Mod_id].RA_prach_resources.Msg3, buflen, rnti, index, ul_config_req); Msg3_transmitted(Mod_id, 0, frame, 0); // UE_mac_inst[Mod_id].first_ULSCH_Tx = 0; // Modification UE_mac_inst[Mod_id].UE_mode[0] = PUSCH; UE_mac_inst[Mod_id].first_ULSCH_Tx = 0; } else { ue_get_sdu(Mod_id, 0, frame, subframe, 0, ulsch_buffer, buflen, &access_mode); fill_crc_indication_UE_MAC(Mod_id, frame, subframe, UL_INFO, 0, index, rnti, ul_config_req); fill_rx_indication_UE_MAC(Mod_id, frame, subframe, UL_INFO, ulsch_buffer, buflen, rnti, index, ul_config_req); } } if (ulsch_harq_information != NULL) fill_ulsch_harq_indication_UE_MAC( Mod_id, frame, subframe, UL_INFO, ulsch_harq_information, rnti, ul_config_req); } else if (ul_config_pdu->pdu_type == NFAPI_UL_CONFIG_ULSCH_CQI_RI_PDU_TYPE) { uint8_t ulsch_buffer[5477] __attribute__((aligned(32))); uint16_t buflen = ul_config_pdu->ulsch_cqi_ri_pdu.ulsch_pdu.ulsch_pdu_rel8.size; uint16_t rnti = ul_config_pdu->ulsch_cqi_ri_pdu.ulsch_pdu.ulsch_pdu_rel8.rnti; uint8_t access_mode = SCHEDULED_ACCESS; if (buflen > 0) { if (UE_mac_inst[Mod_id].first_ULSCH_Tx == 1) { // Msg3 case fill_crc_indication_UE_MAC(Mod_id, frame, subframe, UL_INFO, 0, index, rnti, ul_config_req); fill_rx_indication_UE_MAC(Mod_id, frame, subframe, UL_INFO, UE_mac_inst[Mod_id].RA_prach_resources.Msg3, buflen, rnti, index, ul_config_req); Msg3_transmitted(Mod_id, 0, frame, 0); // UE_mac_inst[Mod_id].first_ULSCH_Tx = 0; // Modification UE_mac_inst[Mod_id].UE_mode[0] = PUSCH; UE_mac_inst[Mod_id].first_ULSCH_Tx = 0; } else { ue_get_sdu(Mod_id, 0, frame, subframe, 0, ulsch_buffer, buflen, &access_mode); fill_crc_indication_UE_MAC(Mod_id, frame, subframe, UL_INFO, 0, index, rnti, ul_config_req); fill_rx_indication_UE_MAC(Mod_id, frame, subframe, UL_INFO, ulsch_buffer, buflen, rnti, index, ul_config_req); } } } else if (ul_config_pdu->pdu_type == NFAPI_UL_CONFIG_ULSCH_CQI_HARQ_RI_PDU_TYPE) { uint8_t ulsch_buffer[5477] __attribute__((aligned(32))); uint16_t buflen = ul_config_pdu->ulsch_cqi_harq_ri_pdu.ulsch_pdu.ulsch_pdu_rel8.size; nfapi_ul_config_ulsch_harq_information *ulsch_harq_information = &ul_config_pdu->ulsch_cqi_harq_ri_pdu.harq_information; uint16_t rnti = ul_config_pdu->ulsch_cqi_harq_ri_pdu.ulsch_pdu.ulsch_pdu_rel8.rnti; uint8_t access_mode = SCHEDULED_ACCESS; if (buflen > 0) { if (UE_mac_inst[Mod_id].first_ULSCH_Tx == 1) { // Msg3 case fill_crc_indication_UE_MAC(Mod_id, frame, subframe, UL_INFO, 0, index, rnti, ul_config_req); fill_rx_indication_UE_MAC(Mod_id, frame, subframe, UL_INFO, UE_mac_inst[Mod_id].RA_prach_resources.Msg3, buflen, rnti, index, ul_config_req); Msg3_transmitted(Mod_id, 0, frame, 0); // UE_mac_inst[Mod_id].first_ULSCH_Tx = 0; // Modification UE_mac_inst[Mod_id].UE_mode[0] = PUSCH; UE_mac_inst[Mod_id].first_ULSCH_Tx = 0; } else { ue_get_sdu(Mod_id, 0, frame, subframe, 0, ulsch_buffer, buflen, &access_mode); fill_crc_indication_UE_MAC(Mod_id, frame, subframe, UL_INFO, 0, index, rnti, ul_config_req); fill_rx_indication_UE_MAC(Mod_id, frame, subframe, UL_INFO, ulsch_buffer, buflen, rnti, index, ul_config_req); } } if (ulsch_harq_information != NULL) fill_ulsch_harq_indication_UE_MAC(Mod_id, frame, subframe, UL_INFO, ulsch_harq_information, rnti, ul_config_req); } else if (ul_config_pdu->pdu_type == NFAPI_UL_CONFIG_UCI_HARQ_PDU_TYPE) { uint16_t rnti = ul_config_pdu->uci_harq_pdu.ue_information.ue_information_rel8.rnti; nfapi_ul_config_harq_information *ulsch_harq_information = &ul_config_pdu->uci_harq_pdu.harq_information; if (ulsch_harq_information != NULL) fill_uci_harq_indication_UE_MAC(Mod_id, frame, subframe, UL_INFO, ulsch_harq_information, rnti, ul_config_req); } else if (ul_config_pdu->pdu_type == NFAPI_UL_CONFIG_UCI_CQI_PDU_TYPE) { AssertFatal(1 == 0, "NFAPI_UL_CONFIG_UCI_CQI_PDU_TYPE not handled yet\n"); } else if (ul_config_pdu->pdu_type == NFAPI_UL_CONFIG_UCI_CQI_HARQ_PDU_TYPE) { AssertFatal(1 == 0, "NFAPI_UL_CONFIG_UCI_CQI_HARQ_PDU_TYPE not handled yet\n"); } else if (ul_config_pdu->pdu_type == NFAPI_UL_CONFIG_UCI_CQI_SR_PDU_TYPE) { AssertFatal(1 == 0, "NFAPI_UL_CONFIG_UCI_CQI_SR_PDU_TYPE not handled yet\n"); } else if (ul_config_pdu->pdu_type == NFAPI_UL_CONFIG_UCI_SR_PDU_TYPE) { uint16_t rnti = ul_config_pdu->uci_sr_pdu.ue_information.ue_information_rel8.rnti; if (ue_get_SR(Mod_id, 0, frame, 0, rnti, subframe)) fill_sr_indication_UE_MAC(Mod_id, frame, subframe, UL_INFO, rnti, ul_config_req); } else if (ul_config_pdu->pdu_type == NFAPI_UL_CONFIG_UCI_SR_HARQ_PDU_TYPE) { // AssertFatal((UE_id = // find_uci(rel8->rnti,proc->frame_tx,proc->subframe_tx,eNB,SEARCH_EXIST_OR_FREE))>=0, // "No available UE UCI for rnti // %x\n",ul_config_pdu->uci_sr_harq_pdu.ue_information.ue_information_rel8.rnti); uint16_t rnti = ul_config_pdu->uci_sr_harq_pdu.ue_information.ue_information_rel8.rnti; // We fill the sr_indication only if ue_get_sr() would normally instruct PHY // to send a SR. if (ue_get_SR(Mod_id, 0, frame, 0, rnti, subframe)) fill_sr_indication_UE_MAC(Mod_id, frame, subframe, UL_INFO, rnti, ul_config_req); nfapi_ul_config_harq_information *ulsch_harq_information = &ul_config_pdu->uci_sr_harq_pdu.harq_information; if (ulsch_harq_information != NULL) fill_uci_harq_indication_UE_MAC( Mod_id, frame, subframe, UL_INFO, ulsch_harq_information, rnti, ul_config_req); } } int ul_config_req_UE_MAC(nfapi_ul_config_request_t *req, int timer_frame, int timer_subframe, module_id_t Mod_id) { LOG_D(PHY, "[PNF] UL_CONFIG_REQ %s() sfn_sf:%d pdu:%d " "rach_prach_frequency_resources:%d srs_present:%u\n", __FUNCTION__, NFAPI_SFNSF2DEC(req->sfn_sf), req->ul_config_request_body.number_of_pdus, req->ul_config_request_body.rach_prach_frequency_resources, req->ul_config_request_body.srs_present); // int sfn = timer_frame; // Needs the ul_config_req sfn_sf // int sf = timer_subframe; LOG_D(MAC, "ul_config_req Frame: %d Subframe: %d Proxy Frame: %u Subframe: %u\n", NFAPI_SFNSF2SFN(req->sfn_sf), NFAPI_SFNSF2SF(req->sfn_sf), timer_frame, timer_subframe); int sfn = NFAPI_SFNSF2SFN(req->sfn_sf); // Needs the ul_config_req sfn_sf int sf = NFAPI_SFNSF2SF(req->sfn_sf); LOG_D(MAC, "ul_config_req_UE_MAC() TOTAL NUMBER OF UL_CONFIG PDUs: %d, SFN/SF: " "%d/%d \n", req->ul_config_request_body.number_of_pdus, timer_frame, timer_subframe); const rnti_t rnti = UE_mac_inst[Mod_id].crnti; for (int i = 0; i < req->ul_config_request_body.number_of_pdus; i++) { nfapi_ul_config_request_pdu_t* pdu = &req->ul_config_request_body.ul_config_pdu_list[i]; const int pdu_type = pdu->pdu_type; if ( (pdu_type == NFAPI_UL_CONFIG_ULSCH_PDU_TYPE && pdu->ulsch_pdu.ulsch_pdu_rel8.rnti == rnti) || (pdu_type == NFAPI_UL_CONFIG_ULSCH_HARQ_PDU_TYPE && pdu->ulsch_harq_pdu.ulsch_pdu.ulsch_pdu_rel8.rnti == rnti) || (pdu_type == NFAPI_UL_CONFIG_ULSCH_CQI_RI_PDU_TYPE && pdu->ulsch_cqi_ri_pdu.ulsch_pdu.ulsch_pdu_rel8.rnti == rnti) || (pdu_type == NFAPI_UL_CONFIG_ULSCH_CQI_HARQ_RI_PDU_TYPE && pdu->ulsch_cqi_harq_ri_pdu.ulsch_pdu.ulsch_pdu_rel8.rnti == rnti) || (pdu_type == NFAPI_UL_CONFIG_UCI_HARQ_PDU_TYPE && pdu->uci_cqi_harq_pdu.ue_information.ue_information_rel8.rnti == rnti) || (pdu_type == NFAPI_UL_CONFIG_UCI_SR_PDU_TYPE && pdu->uci_sr_pdu.ue_information.ue_information_rel8.rnti == rnti) || (pdu_type == NFAPI_UL_CONFIG_UCI_SR_HARQ_PDU_TYPE && pdu->uci_cqi_sr_harq_pdu.ue_information.ue_information_rel8.rnti == rnti)) { handle_nfapi_ul_pdu_UE_MAC( Mod_id, pdu, sfn, sf, req->ul_config_request_body.srs_present, i, req); } else { // NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s() PDU:%i UNKNOWN type :%d\n", // __FUNCTION__, i, ul_config_pdu_list[i].pdu_type); } } return 0; } int tx_req_UE_MAC(nfapi_tx_request_t *req) { LOG_D(PHY, "%s() SFN/SF:%d/%d PDUs:%d\n", __FUNCTION__, NFAPI_SFNSF2SFN(req->sfn_sf), NFAPI_SFNSF2SF(req->sfn_sf), req->tx_request_body.number_of_pdus); for (int i = 0; i < req->tx_request_body.number_of_pdus; i++) { LOG_D(PHY, "%s() SFN/SF:%d/%d number_of_pdus:%d [PDU:%d] pdu_length:%d " "pdu_index:%d num_segments:%d\n", __FUNCTION__, NFAPI_SFNSF2SFN(req->sfn_sf), NFAPI_SFNSF2SF(req->sfn_sf), req->tx_request_body.number_of_pdus, i, req->tx_request_body.tx_pdu_list[i].pdu_length, req->tx_request_body.tx_pdu_list[i].pdu_index, req->tx_request_body.tx_pdu_list[i].num_segments); } return 0; } void dl_config_req_UE_MAC_dci(int sfn, int sf, nfapi_dl_config_request_pdu_t *dci, nfapi_dl_config_request_pdu_t *dlsch, int num_ue, nfapi_tx_request_pdu_t *tx_request_pdu_list) { DevAssert(dci->pdu_type == NFAPI_DL_CONFIG_DCI_DL_PDU_TYPE); DevAssert(dlsch->pdu_type == NFAPI_DL_CONFIG_DLSCH_PDU_TYPE); const rnti_t rnti = dci->dci_dl_pdu.dci_dl_pdu_rel8.rnti; const int rnti_type = dci->dci_dl_pdu.dci_dl_pdu_rel8.rnti_type; if (rnti != dlsch->dlsch_pdu.dlsch_pdu_rel8.rnti) { LOG_E(MAC, "%s(): sfn/sf %d.%d DLSCH PDU RNTI %x does not match DCI RNTI %x\n", __func__, sfn, sf, rnti, dlsch->dlsch_pdu.dlsch_pdu_rel8.rnti); return; } const int pdu_index = dlsch->dlsch_pdu.dlsch_pdu_rel8.pdu_index; if (pdu_index < 0 || pdu_index >= tx_req_num_elems) { // LOG_E(MAC, // "%s(): Problem with receiving data: " // "sfn/sf:%d.%d PDU size:%d, TX_PDU index: %d\n", // __func__, // sfn, sf, dci->pdu_size, dlsch->dlsch_pdu.dlsch_pdu_rel8.pdu_index); return; } if (rnti_type == 1) { // C-RNTI (Normal DLSCH case) for (int ue_id = 0; ue_id < num_ue; ue_id++) { if (UE_mac_inst[ue_id].crnti == rnti) { LOG_D(MAC, "%s() Received data: sfn/sf:%d.%d " "size:%d, TX_PDU index: %d, tx_req_num_elems: %d \n", __func__, sfn, sf, dci->pdu_size, dlsch->dlsch_pdu.dlsch_pdu_rel8.pdu_index, tx_req_num_elems); ue_send_sdu(ue_id, 0, sfn, sf, tx_request_pdu_list[pdu_index].segments[0].segment_data, tx_request_pdu_list[pdu_index].segments[0].segment_length, 0); return; } } } else if (rnti_type == 2) { if (rnti == 0xFFFF) { /* SI-RNTI */ for (int ue_id = 0; ue_id < num_ue; ue_id++) { if (UE_mac_inst[ue_id].UE_mode[0] == NOT_SYNCHED) continue; ue_decode_si(ue_id, 0, sfn, 0, tx_request_pdu_list[pdu_index].segments[0].segment_data, tx_request_pdu_list[pdu_index].segments[0].segment_length); } } else if (rnti == 0xFFFE) { /* PI-RNTI */ for (int ue_id = 0; ue_id < num_ue; ue_id++) { LOG_I(MAC, "%s() Received paging message: sfn/sf:%d.%d\n", __func__, sfn, sf); ue_decode_p(ue_id, 0, sfn, 0, tx_request_pdu_list[pdu_index].segments[0].segment_data, tx_request_pdu_list[pdu_index].segments[0].segment_length); } } else if (rnti == 0x0002) { /* RA-RNTI */ for (int ue_id = 0; ue_id < num_ue; ue_id++) { if (UE_mac_inst[ue_id].UE_mode[0] != RA_RESPONSE) { LOG_D(MAC, "UE %d not awaiting RAR, is in mode %d\n", ue_id, UE_mac_inst[ue_id].UE_mode[0]); continue; } // RNTI parameter not actually used. Provided only to comply with // existing function definition. Not sure about parameters to fill // the preamble index. const rnti_t ra_rnti = UE_mac_inst[ue_id].RA_prach_resources.ra_RNTI; DevAssert(ra_rnti == 0x0002); if (UE_mac_inst[ue_id].UE_mode[0] != PUSCH && UE_mac_inst[ue_id].RA_prach_resources.Msg3 != NULL && ra_rnti == dlsch->dlsch_pdu.dlsch_pdu_rel8.rnti) { LOG_E(MAC, "%s(): Received RAR, PreambleIndex: %d\n", __func__, UE_mac_inst[ue_id].RA_prach_resources.ra_PreambleIndex); ue_process_rar(ue_id, 0, sfn, ra_rnti, //RA-RNTI tx_request_pdu_list[pdu_index].segments[0].segment_data, &UE_mac_inst[ue_id].crnti, //t-crnti UE_mac_inst[ue_id].RA_prach_resources.ra_PreambleIndex, tx_request_pdu_list[pdu_index].segments[0].segment_data); UE_mac_inst[ue_id].UE_mode[0] = RA_RESPONSE; // Expecting an UL_CONFIG_ULSCH_PDU to enable Msg3 Txon (first // ULSCH Txon for the UE) UE_mac_inst[ue_id].first_ULSCH_Tx = 1; } } } else { LOG_W(MAC, "can not handle special RNTI %x\n", rnti); } } } void dl_config_req_UE_MAC_bch(int sfn, int sf, nfapi_dl_config_request_pdu_t *bch, int num_ue) { DevAssert(bch->pdu_type == NFAPI_DL_CONFIG_BCH_PDU_TYPE); for (int ue_id = 0; ue_id < num_ue; ue_id++) { if (UE_mac_inst[ue_id].UE_mode[0] == NOT_SYNCHED){ dl_phy_sync_success(ue_id, sfn, 0, 1); LOG_E(MAC, "%s(): Received MIB: UE_mode: %d, sfn/sf: %d.%d\n", __func__, UE_mac_inst[ue_id].UE_mode[0], sfn, sf); UE_mac_inst[ue_id].UE_mode[0] = PRACH; } else { dl_phy_sync_success(ue_id, sfn, 0, 0); } } } void dl_config_req_UE_MAC_mch(int sfn, int sf, nfapi_dl_config_request_pdu_t *mch, int num_ue, nfapi_tx_request_pdu_t *tx_request_pdu_list) { DevAssert(mch->pdu_type == NFAPI_DL_CONFIG_MCH_PDU_TYPE); for (int ue_id = 0; ue_id < num_ue; ue_id++) { if (UE_mac_inst[ue_id].UE_mode[0] == NOT_SYNCHED){ LOG_D(MAC, "%s(): Received MCH in NOT_SYNCHED: UE_mode: %d, sfn/sf: %d.%d\n", __func__, UE_mac_inst[ue_id].UE_mode[0], sfn, sf); return; } else { const int pdu_index = mch->mch_pdu.mch_pdu_rel8.pdu_index; if (pdu_index < 0 || pdu_index >= tx_req_num_elems) { // LOG_E(MAC, // "%s(): Problem with receiving data: " // "sfn/sf:%d.%d PDU size:%d, TX_PDU index: %d\n", // __func__, // sfn, sf, mch->pdu_size, mch->mch_pdu.mch_pdu_rel8.pdu_index); return; } ue_send_mch_sdu(ue_id, 0, sfn, tx_request_pdu_list[pdu_index].segments[0].segment_data, tx_request_pdu_list[pdu_index].segments[0].segment_length, 0,0); } } } void hi_dci0_req_UE_MAC(int sfn, int sf, nfapi_hi_dci0_request_pdu_t* hi_dci0, int num_ue) { if (hi_dci0->pdu_type != NFAPI_HI_DCI0_DCI_PDU_TYPE) return; const nfapi_hi_dci0_dci_pdu_rel8_t *dci = &hi_dci0->dci_pdu.dci_pdu_rel8; if (!dci->cqi_csi_request) return; for (int ue_id = 0; ue_id < num_ue; ue_id++) { if (dci->rnti == UE_mac_inst[ue_id].crnti) { fill_ulsch_cqi_indication_UE_MAC(ue_id, sfn, sf, UL_INFO, dci->rnti); return; } } } // The following set of memcpy functions should be getting called as callback // functions from pnf_p7_subframe_ind. int memcpy_dl_config_req(L1_rxtx_proc_t *proc, nfapi_pnf_p7_config_t *pnf_p7, nfapi_dl_config_request_t *req) { nfapi_dl_config_request_t *p = malloc(sizeof(nfapi_dl_config_request_t)); // UE_mac_inst[Mod_id].p->header = req->header; p->sfn_sf = req->sfn_sf; p->vendor_extension = req->vendor_extension; p->dl_config_request_body.number_dci = req->dl_config_request_body.number_dci; p->dl_config_request_body.number_pdcch_ofdm_symbols = req->dl_config_request_body.number_pdcch_ofdm_symbols; p->dl_config_request_body.number_pdsch_rnti = req->dl_config_request_body.number_pdsch_rnti; p->dl_config_request_body.number_pdu = req->dl_config_request_body.number_pdu; p->dl_config_request_body.tl.tag = req->dl_config_request_body.tl.tag; p->dl_config_request_body.tl.length = req->dl_config_request_body.tl.length; p->dl_config_request_body.dl_config_pdu_list = calloc(req->dl_config_request_body.number_pdu, sizeof(nfapi_dl_config_request_pdu_t)); for (int i = 0; i < p->dl_config_request_body.number_pdu; i++) { p->dl_config_request_body.dl_config_pdu_list[i] = req->dl_config_request_body.dl_config_pdu_list[i]; } if (!put_queue(&dl_config_req_queue, p)) { free(p); } return 0; } int memcpy_ul_config_req (L1_rxtx_proc_t *proc, nfapi_pnf_p7_config_t* pnf_p7, nfapi_ul_config_request_t* req) { nfapi_ul_config_request_t *p = malloc(sizeof(nfapi_ul_config_request_t)); p->sfn_sf = req->sfn_sf; p->vendor_extension = req->vendor_extension; p->ul_config_request_body.number_of_pdus = req->ul_config_request_body.number_of_pdus; p->ul_config_request_body.rach_prach_frequency_resources = req->ul_config_request_body.rach_prach_frequency_resources; p->ul_config_request_body.srs_present = req->ul_config_request_body.srs_present; p->ul_config_request_body.tl.tag = req->ul_config_request_body.tl.tag; p->ul_config_request_body.tl.length = req->ul_config_request_body.tl.length; p->ul_config_request_body.ul_config_pdu_list = calloc(req->ul_config_request_body.number_of_pdus, sizeof(nfapi_ul_config_request_pdu_t)); for (int i = 0; i < p->ul_config_request_body.number_of_pdus; i++) { p->ul_config_request_body.ul_config_pdu_list[i] = req->ul_config_request_body.ul_config_pdu_list[i]; } if (!put_queue(&ul_config_req_queue, p)) { free(p); } return 0; } int memcpy_tx_req(nfapi_pnf_p7_config_t *pnf_p7, nfapi_tx_request_t *req) { tx_req_num_elems = req->tx_request_body.number_of_pdus; nfapi_tx_request_pdu_t *p = calloc(tx_req_num_elems, sizeof(nfapi_tx_request_pdu_t)); for (int i = 0; i < tx_req_num_elems; i++) { p[i].num_segments = req->tx_request_body.tx_pdu_list[i].num_segments; p[i].pdu_index = req->tx_request_body.tx_pdu_list[i].pdu_index; p[i].pdu_length = req->tx_request_body.tx_pdu_list[i].pdu_length; for (int j = 0; j < req->tx_request_body.tx_pdu_list[i].num_segments; j++) { p[i].segments[j].segment_length = req->tx_request_body.tx_pdu_list[i].segments[j].segment_length; if (p[i].segments[j].segment_length > 0) { p[i].segments[j].segment_data = calloc( p[i].segments[j].segment_length, sizeof(uint8_t)); memcpy(p[i].segments[j].segment_data, req->tx_request_body.tx_pdu_list[i].segments[j].segment_data, p[i].segments[j].segment_length); } } } if (!put_queue(&tx_req_pdu_queue, p)) { free(p); } return 0; } int memcpy_hi_dci0_req (L1_rxtx_proc_t *proc, nfapi_pnf_p7_config_t* pnf_p7, nfapi_hi_dci0_request_t* req) { nfapi_hi_dci0_request_t *p = (nfapi_hi_dci0_request_t *)malloc(sizeof(nfapi_hi_dci0_request_t)); //if(req!=0){ p->sfn_sf = req->sfn_sf; p->vendor_extension = req->vendor_extension; p->hi_dci0_request_body.number_of_dci = req->hi_dci0_request_body.number_of_dci; p->hi_dci0_request_body.number_of_hi = req->hi_dci0_request_body.number_of_hi; p->hi_dci0_request_body.sfnsf = req->hi_dci0_request_body.sfnsf; // UE_mac_inst[Mod_id].p->hi_dci0_request_body.tl = // req->hi_dci0_request_body.tl; p->hi_dci0_request_body.tl.tag = req->hi_dci0_request_body.tl.tag; p->hi_dci0_request_body.tl.length = req->hi_dci0_request_body.tl.length; int total_pdus = p->hi_dci0_request_body.number_of_dci + p->hi_dci0_request_body.number_of_hi; p->hi_dci0_request_body.hi_dci0_pdu_list = calloc(total_pdus, sizeof(nfapi_hi_dci0_request_pdu_t)); for (int i = 0; i < total_pdus; i++) { p->hi_dci0_request_body.hi_dci0_pdu_list[i] = req->hi_dci0_request_body.hi_dci0_pdu_list[i]; // LOG_I(MAC, "Original hi_dci0 req. type:%d, Copy type: %d // \n",req->hi_dci0_request_body.hi_dci0_pdu_list[i].pdu_type, // UE_mac_inst[Mod_id].p->hi_dci0_request_body.hi_dci0_pdu_list[i].pdu_type); } if (!put_queue(&hi_dci0_req_queue, p)) { free(p); } return 0; } void UE_config_stub_pnf(void) { int j; paramdef_t L1_Params[] = L1PARAMS_DESC; paramlist_def_t L1_ParamList = {CONFIG_STRING_L1_LIST, NULL, 0}; config_getlist(&L1_ParamList, L1_Params, sizeof(L1_Params) / sizeof(paramdef_t), NULL); if (L1_ParamList.numelt > 0) { for (j = 0; j < L1_ParamList.numelt; j++) { // nb_L1_CC = *(L1_ParamList.paramarray[j][L1_CC_IDX].uptr); // Number of // component carriers is of no use for the // phy_stub mode UE pnf. Maybe we can completely skip it. if (strcmp(*(L1_ParamList.paramarray[j][L1_TRANSPORT_N_PREFERENCE_IDX].strptr), "local_mac") == 0) { sf_ahead = 4; // Need 4 subframe gap between RX and TX } // Right now that we have only one UE (thread) it is ok to put the // eth_params in the UE_mac_inst. Later I think we have to change that to // attribute eth_params to a global element for all the UEs. else if (strcmp(*(L1_ParamList.paramarray[j][L1_TRANSPORT_N_PREFERENCE_IDX].strptr), "nfapi") == 0) { stub_eth_params.local_if_name = strdup( *(L1_ParamList.paramarray[j][L1_LOCAL_N_IF_NAME_IDX].strptr)); stub_eth_params.my_addr = strdup( *(L1_ParamList.paramarray[j][L1_LOCAL_N_ADDRESS_IDX].strptr)); stub_eth_params.remote_addr = strdup( *(L1_ParamList.paramarray[j][L1_REMOTE_N_ADDRESS_IDX].strptr)); stub_eth_params.my_portc = *(L1_ParamList.paramarray[j][L1_LOCAL_N_PORTC_IDX].iptr); stub_eth_params.remote_portc = *(L1_ParamList.paramarray[j][L1_REMOTE_N_PORTC_IDX].iptr); stub_eth_params.my_portd = *(L1_ParamList.paramarray[j][L1_LOCAL_N_PORTD_IDX].iptr); stub_eth_params.remote_portd = *(L1_ParamList.paramarray[j][L1_REMOTE_N_PORTD_IDX].iptr); stub_eth_params.transp_preference = ETH_UDP_MODE; sf_ahead = 2; // Cannot cope with 4 subframes betweem RX and TX - set it to 2 // configure_nfapi_pnf(UE_mac_inst[0].eth_params_n.remote_addr, // UE_mac_inst[0].eth_params_n.remote_portc, // UE_mac_inst[0].eth_params_n.my_addr, // UE_mac_inst[0].eth_params_n.my_portd, // UE_mac_inst[0].eth_params_n.remote_portd); configure_nfapi_pnf(stub_eth_params.remote_addr, stub_eth_params.remote_portc, stub_eth_params.my_addr, stub_eth_params.my_portd, stub_eth_params.remote_portd); } } } } void ue_init_standalone_socket(const char *addr, int tx_port, int rx_port) { { struct sockaddr_in server_address; int addr_len = sizeof(server_address); memset(&server_address, 0, addr_len); server_address.sin_family = AF_INET; server_address.sin_port = htons(tx_port); int sd = socket(server_address.sin_family, SOCK_DGRAM, 0); if (sd < 0) { LOG_E(MAC, "Socket creation error standalone PNF\n"); return; } if (inet_pton(server_address.sin_family, addr, &server_address.sin_addr) <= 0) { LOG_E(MAC, "Invalid standalone PNF Address\n"); close(sd); return; } // Using connect to use send() instead of sendto() if (connect(sd, (struct sockaddr *)&server_address, addr_len) < 0) { LOG_E(MAC, "Connection to standalone PNF failed: %s\n", strerror(errno)); close(sd); return; } LOG_I(MAC, "Succeeded Now\n"); assert(ue_tx_sock_descriptor == -1); ue_tx_sock_descriptor = sd; } { struct sockaddr_in server_address; int addr_len = sizeof(server_address); memset(&server_address, 0, addr_len); server_address.sin_family = AF_INET; server_address.sin_port = htons(rx_port); int sd = socket(server_address.sin_family, SOCK_DGRAM, 0); if (sd < 0) { LOG_E(MAC, "Socket creation error standalone PNF\n"); return; } if (inet_pton(server_address.sin_family, addr, &server_address.sin_addr) <= 0) { LOG_E(MAC, "Invalid standalone PNF Address\n"); close(sd); return; } if (bind(sd, (struct sockaddr *)&server_address, addr_len) < 0) { LOG_E(MAC, "Connection to standalone PNF failed: %s\n", strerror(errno)); close(sd); return; } LOG_I(MAC, "Succeeded Now\n"); assert(ue_rx_sock_descriptor == -1); ue_rx_sock_descriptor = sd; } } void *ue_standalone_pnf_task(void *context) { struct sockaddr_in server_address; socklen_t addr_len = sizeof(server_address); char buffer[1024]; int sd = ue_rx_sock_descriptor; assert(sd > 0); while (true) { ssize_t len = recvfrom(sd, buffer, sizeof(buffer), 0, (struct sockaddr *)&server_address, &addr_len); if (len == -1) { LOG_E(MAC, "reading from standalone pnf sctp socket failed \n"); continue; } if (len == sizeof(uint16_t)) { uint16_t sfn_sf = 0; memcpy((void *)&sfn_sf, buffer, sizeof(sfn_sf)); current_sfn_sf = sfn_sf; if (sem_post(&sfn_semaphore) != 0) { LOG_E(MAC, "sem_post() error\n"); abort(); } } else { nfapi_p7_message_header_t header; if (nfapi_p7_message_header_unpack((void *)buffer, len, &header, sizeof(header), NULL) < 0) { LOG_E(MAC, "Header unpack failed for standalone pnf\n"); continue; } switch (header.message_id) { case NFAPI_DL_CONFIG_REQUEST: { nfapi_dl_config_request_t dl_config_req; if (nfapi_p7_message_unpack((void *)buffer, len, &dl_config_req, sizeof(dl_config_req), NULL) < 0) { LOG_E(MAC, "Message dl_config_req failed to unpack\n"); } else { // check to see if dl_config_req is null memcpy_dl_config_req(NULL, NULL, &dl_config_req); } break; } case NFAPI_TX_REQUEST: { nfapi_tx_request_t tx_req; // lock this tx_req if (nfapi_p7_message_unpack((void *)buffer, len, &tx_req, sizeof(tx_req), NULL) < 0) { LOG_E(MAC, "Message tx_req failed to unpack\n"); } else { // check to see if tx_req is null memcpy_tx_req(NULL, &tx_req); } break; } case NFAPI_HI_DCI0_REQUEST: { nfapi_hi_dci0_request_t hi_dci0_req; // lock this hi_dci0_req if (nfapi_p7_message_unpack((void *)buffer, len, &hi_dci0_req, sizeof(hi_dci0_req), NULL) < 0) { LOG_E(MAC, "Message hi_dci0_req failed to unpack\n"); } else { // check to see if hi_dci0_req is null memcpy_hi_dci0_req(NULL, NULL, &hi_dci0_req); } break; } case NFAPI_UL_CONFIG_REQUEST: { nfapi_ul_config_request_t ul_config_req; // lock this ul_config_req if (nfapi_p7_message_unpack((void *)buffer, len, &ul_config_req, sizeof(ul_config_req), NULL) < 0) { LOG_E(MAC, "Message ul_config_req failed to unpack\n"); } else { // check to see if ul_config_req is null memcpy_ul_config_req(NULL, NULL, &ul_config_req); } break; } default: LOG_E(MAC, "Case Statement has no corresponding nfapi message\n"); break; } } } } const char *hexdump(const void *data, size_t data_len, char *out, size_t out_len) { char *p = out; char *endp = out + out_len; const uint8_t *q = data; snprintf(p, endp - p, "[%zu]", data_len); p += strlen(p); for (size_t i = 0; i < data_len; ++i) { if (p >= endp) { static const char ellipses[] = "..."; char *s = endp - sizeof(ellipses); if (s >= p) { strcpy(s, ellipses); } break; } snprintf(p, endp - p, " %02X", *q++); p += strlen(p); } return out; } void send_standalone_msg(UL_IND_t *UL, nfapi_message_id_e msg_type) { int encoded_size = -1; char buffer[1024]; switch (msg_type) { case NFAPI_RACH_INDICATION: encoded_size = nfapi_p7_message_pack(&UL->rach_ind, buffer, sizeof(buffer), NULL); LOG_E(MAC, "RACH_IND sent to Proxy, Size: %d Frame %d Subframe %d\n", encoded_size, NFAPI_SFNSF2SFN(UL->rach_ind.sfn_sf), NFAPI_SFNSF2SF(UL->rach_ind.sfn_sf)); break; case NFAPI_CRC_INDICATION: encoded_size = nfapi_p7_message_pack(&UL->crc_ind, buffer, sizeof(buffer), NULL); LOG_E(MAC, "CRC_IND sent to Proxy, Size: %d Frame %d Subframe %d\n", encoded_size, NFAPI_SFNSF2SFN(UL->crc_ind.sfn_sf), NFAPI_SFNSF2SF(UL->crc_ind.sfn_sf)); break; case NFAPI_RX_ULSCH_INDICATION: // is this the right nfapi message_id? Ask Raymond encoded_size = nfapi_p7_message_pack(&UL->rx_ind, buffer, sizeof(buffer), NULL); LOG_E(MAC, "RX_IND sent to Proxy, Size: %d Frame %d Subframe %d\n", encoded_size, NFAPI_SFNSF2SFN(UL->rx_ind.sfn_sf), NFAPI_SFNSF2SF(UL->rx_ind.sfn_sf)); break; case NFAPI_RX_CQI_INDICATION: // is this the right nfapi message_id? Ask Raymond encoded_size = nfapi_p7_message_pack(&UL->cqi_ind, buffer, sizeof(buffer), NULL); LOG_E(MAC, "CQI_IND sent to Proxy, Size: %d\n", encoded_size); break; case NFAPI_HARQ_INDICATION: encoded_size = nfapi_p7_message_pack(&UL->harq_ind, buffer, sizeof(buffer), NULL); LOG_E(MAC, "HARQ_IND sent to Proxy, Size: %d Frame %d Subframe %d\n", encoded_size, NFAPI_SFNSF2SFN(UL->harq_ind.sfn_sf), NFAPI_SFNSF2SF(UL->harq_ind.sfn_sf)); break; case NFAPI_RX_SR_INDICATION: // is this the right nfapi message_id? Ask Raymond encoded_size = nfapi_p7_message_pack(&UL->sr_ind, buffer, sizeof(buffer), NULL); LOG_E(MAC, "SR_IND sent to Proxy, Size: %d\n", encoded_size); break; default: LOG_E(MAC, "%s Unknown Message msg_type :: %u\n", __func__, msg_type); return; } if (encoded_size < 0) { LOG_E(MAC, "standalone pack failed\n"); return; } if (send(ue_tx_sock_descriptor, buffer, encoded_size, 0) < 0) { LOG_E(MAC, "Send Proxy UE failed\n"); return; } } void send_standalone_dummy() { static const uint16_t dummy[] = {0, 0}; // LOG_E(MAC, "Dummy sent to Proxy, Size: %zu\n", sizeof(dummy)); if (send(ue_tx_sock_descriptor, dummy, sizeof(dummy), 0) < 0) { LOG_E(MAC, "send dummy to OAI UE failed: %s\n", strerror(errno)); return; } } /* Dummy functions*/ void handle_nfapi_hi_dci0_dci_pdu( PHY_VARS_eNB * eNB, int frame, int subframe, L1_rxtx_proc_t *proc, nfapi_hi_dci0_request_pdu_t *hi_dci0_config_pdu) { } void handle_nfapi_hi_dci0_hi_pdu( PHY_VARS_eNB * eNB, int frame, int subframe, L1_rxtx_proc_t *proc, nfapi_hi_dci0_request_pdu_t *hi_dci0_config_pdu) { } void handle_nfapi_dci_dl_pdu(PHY_VARS_eNB * eNB, int frame, int subframe, L1_rxtx_proc_t *proc, nfapi_dl_config_request_pdu_t *dl_config_pdu) { } void handle_nfapi_bch_pdu(PHY_VARS_eNB * eNB, L1_rxtx_proc_t * proc, nfapi_dl_config_request_pdu_t * dl_config_pdu, uint8_t * sdu) { } void handle_nfapi_dlsch_pdu(PHY_VARS_eNB * eNB, int frame, int subframe, L1_rxtx_proc_t *proc, nfapi_dl_config_request_pdu_t *dl_config_pdu, uint8_t codeword_index, uint8_t *sdu) { } void handle_nfapi_ul_pdu(PHY_VARS_eNB * eNB, L1_rxtx_proc_t * proc, nfapi_ul_config_request_pdu_t * ul_config_pdu, uint16_t frame, uint8_t subframe, uint8_t srs_present) { } void handle_nfapi_mch_pdu(PHY_VARS_eNB * eNB, L1_rxtx_proc_t * proc, nfapi_dl_config_request_pdu_t * dl_config_pdu, uint8_t * sdu) { } void phy_config_request(PHY_Config_t * phy_config) { } void phy_config_update_sib2_request(PHY_Config_t * phy_config) { } void phy_config_update_sib13_request(PHY_Config_t * phy_config) { } uint32_t from_earfcn(int eutra_bandP, uint32_t dl_earfcn) { return (0); } int32_t get_uldl_offset(int eutra_bandP) { return (0); } int l1_north_init_eNB(void) { return 0; } void init_eNB_afterRU(void) { }