diff --git a/nfapi/debug.h b/nfapi/debug.h new file mode 100644 index 0000000000000000000000000000000000000000..05e987054f8d137a0b98915fdb84ed1e24204216 --- /dev/null +++ b/nfapi/debug.h @@ -0,0 +1,50 @@ +/* + * Copyright 2017 Cisco Systems, Inc. + * + * Licensed under the Apache License, Version 2.0 (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.apache.org/licenses/LICENSE-2.0 + * + * 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. + */ + + +#ifndef _DEBUG_H_ +#define _DEBUG_H_ + +/*! The trace levels used by the nfapi libraries */ +typedef enum nfapi_trace_level +{ + NFAPI_TRACE_ERROR = 1, + NFAPI_TRACE_WARN, + NFAPI_TRACE_NOTE, + NFAPI_TRACE_INFO, + + NFAPI_TRACE_LEVEL_MAX +} nfapi_trace_level_t; + +/*! The trace function pointer */ +typedef void (*nfapi_trace_fn_t)(nfapi_trace_level_t level, const char* format, ...); + +/*! Global trace function */ +extern nfapi_trace_fn_t nfapi_trace_g; + +/*! Global trace level */ +extern nfapi_trace_level_t nfapi_trace_level_g; + +/*! NFAPI trace macro */ +#define NFAPI_TRACE(level, format, ...) { if(nfapi_trace_g && ((nfapi_trace_level_t)level <= nfapi_trace_level_g)) (*nfapi_trace_g)(level, format, ##__VA_ARGS__); } + +/*! Function to change the trace level + * \param new_level The modified trace level + */ + +void nfapi_set_trace_level(nfapi_trace_level_t new_level); + +#endif /* _DEBUG_H_ */ diff --git a/nfapi/nfapi_pnf_interface.h b/nfapi/nfapi_pnf_interface.h new file mode 100644 index 0000000000000000000000000000000000000000..e48b93250ec051aa8e88d44a5c6af5b167ac61d9 --- /dev/null +++ b/nfapi/nfapi_pnf_interface.h @@ -0,0 +1,803 @@ +/* + * Copyright 2017 Cisco Systems, Inc. + * + * Licensed under the Apache License, Version 2.0 (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.apache.org/licenses/LICENSE-2.0 + * + * 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. + */ + + +#ifndef _NFAPI_PNF_INTERFACE_H_ +#define _NFAPI_PNF_INTERFACE_H_ + +#if defined(__cplusplus) +extern "C" { +#endif + +#include "nfapi_interface.h" +#include "debug.h" + +#include <sys/types.h> + +/*! This enum is used to describe the states of the pnf + */ +typedef enum +{ + NFAPI_PNF_IDLE = 0, + NFAPI_PNF_CONFIGURED, + NFAPI_PNF_RUNNING +} nfapi_pnf_state_e; + +/*! This enum is used to describe the states of a phy instance of a pnf + */ +typedef enum +{ + NFAPI_PNF_PHY_IDLE = 0, + NFAPI_PNF_PHY_CONFIGURED = 1, + NFAPI_PNF_PHY_RUNNING = 2 +} nfapi_pnf_phy_state_e; + +typedef struct nfapi_pnf_phy_config nfapi_pnf_phy_config_t; + +/*! Configuration information for a pnf phy instance + */ +typedef struct nfapi_pnf_phy_config +{ + /*! The PHY id*/ + uint16_t phy_id; + + /*! The state of the PNF PHY instance*/ + nfapi_pnf_phy_state_e state; + + /*! Optional user defined data that will be passed back in the callbacks*/ + void* user_data; + + /*! Pointer for use in a linked list */ + struct nfapi_pnf_phy_config* next; +} nfapi_pnf_phy_config_t; + +typedef struct nfapi_pnf_config nfapi_pnf_config_t; + +/*! Configuration information for the pnf created by calling nfapi_pnf_create + */ +typedef struct nfapi_pnf_config +{ + /*! A user define callback to override the default memory allocation + * \param size The size of the data buffer to allocate + * \return A pointer to a data buffer + */ + void* (*malloc)(size_t size); + + /*! A user define callback to override the default memory deallocation + * \param ptr Pointer to a data buffer to be deallocated + */ + void (*free)(void* ptr); + + /*! A user define callback to handle trace from the pnf + * \param level The trace level + * \param message The trace string + * + * This is a vardic function. + */ + void (*trace)(nfapi_trace_level_t level, const char* message, ...); + + /*! The ip address of the VNF + * + */ + char* vnf_ip_addr; + + /*! The ip port of the VNF + */ + int vnf_p5_port; + + /*! The state of the PNF */ + nfapi_pnf_state_e state; + + /*! List of PHY instances configured for this PNF */ + nfapi_pnf_phy_config_t* phys; + + /*! Configuation option of the p4 p5 encode decode functions */ + nfapi_p4_p5_codec_config_t codec_config; + + /*! Optional user defined data that will be passed back in the callbacks*/ + void* user_data; + + + /*! A callback for the PNF_PARAM.request + * \param config A pointer to the pnf configuration + * \param req A data structure for the decoded PNF_PARAM.request. This will have + * been allocated on the stack + * \return not currently used + * + * The client is expected to send the PNF_PARAM.response after receiving the + * PNF_PARAM.request. This can be done in the call back. + */ + int (*pnf_param_req)(nfapi_pnf_config_t* config, nfapi_pnf_param_request_t* req); + + /*! A callback for the PNF_CONFIG.request + * \param config A pointer to the pnf configuration + * \param req A data structure for the decoded PNF_CONFIG.request. This will have + * been allocated on the stack + * \return not currently used + * + * The client is expected to send the PNF_CONFIG.response after receiving the + * PNF_CONFIG.request. This can be done in the call back. + */ + int (*pnf_config_req)(nfapi_pnf_config_t* config, nfapi_pnf_config_request_t* req); + + /*! A callback for the PNF_START.request + * \param config A pointer to the pnf configuration + * \param req A data structure for the decoded PNF_CONFIG.request. This will have + * been allocated on the stack + * \return not currently used + * + * The client is expected to send the PNF_START.response after receiving the + * PNF_START.request. This can be done in the call back. + */ + int (*pnf_start_req)(nfapi_pnf_config_t* config, nfapi_pnf_start_request_t* req); + + /*! A callback for the PNF_STOP.request + * \param config A pointer to the pnf configuration + * \param req A data structure for the decoded PNF_STOP.request. This will have + * been allocated on the stack + * \return not currently used + * + * The client is expected to send the PNF_STOP.response after receiving the + * PNF_STOP.request. This can be done in the call back. + */ + int (*pnf_stop_req)(nfapi_pnf_config_t* config, nfapi_pnf_stop_request_t* req); + + /*! A callback for the PARAM.request + * \param config A pointer to the pnf configuration + * \param phy A pointer to the pnf phy configuration + * \param req A data structure for the decoded PARAM.request. This will have + * been allocated on the stack + * \return not currently used + * + * The client is expected to send the PARAM.response after receiving the + * PARAM.request. This can be done in the call back. + */ + int (*param_req)(nfapi_pnf_config_t* config, nfapi_pnf_phy_config_t* phy, nfapi_param_request_t* req); + + /*! A callback for the CONFIG.request + * \param config A pointer to the pnf configuration + * \param phy A pointer to the pnf phy configuration + * \param req A data structure for the decoded CONFIG.request. This will have + * been allocated on the stack + * \return not currently used + * + * The client is expected to send the CONFIG.response after receiving the + * CONFIG.request. This can be done in the call back. + */ + int (*config_req)(nfapi_pnf_config_t* config, nfapi_pnf_phy_config_t* phy, nfapi_config_request_t* req); + + /*! A callback for the START.request + * \param config A pointer to the pnf configuration + * \param phy A pointer to the pnf phy configuration + * \param req A data structure for the decoded START.request. This will have + * been allocated on the stack + * \return not currently used + * + * The client is expected to send the START.response after the client has received the + * first subframe indication from FAPI. + */ + int (*start_req)(nfapi_pnf_config_t* config, nfapi_pnf_phy_config_t* phy, nfapi_start_request_t* req); + + /*! A callback for the STOP.request + * \param config A pointer to the pnf configuration + * \param phy A pointer to the pnf phy configuration + * \param req A data structure for the decoded STOP.request. This will have + * been allocated on the stack + * \return not currently used + * + * The client is expected to send the STOP.response after receiving the + * STOP.request. This can be done in the call back. + */ + int (*stop_req)(nfapi_pnf_config_t* config, nfapi_pnf_phy_config_t* phy, nfapi_stop_request_t* req); + + /*! A callback for the MEASUREMENT.request + * \param config A pointer to the pnf configuration + * \param phy A pointer to the pnf phy configuration + * \param req A data structure for the decoded MEASUREMENT.request. This will have + * been allocated on the stack + * \return not currently used + * + * The client is expected to send the MEASUREMENT.response after receiving the + * MEASUREMENT.request. This can be done in the call back. + */ + int (*measurement_req)(nfapi_pnf_config_t* config, nfapi_pnf_phy_config_t* phy, nfapi_measurement_request_t* req); + + /*! A callback for the RSSI.request + * \param config A pointer to the pnf configuration + * \param phy A pointer to the pnf phy configuration + * \param req A data structure for the decoded RSSI.request. This will have + * been allocated on the stack + * \return not currently used + * + * The client is expected to send the RSSI.response after receiving the + * RSSI.request. This can be done in the call back. + */ + int (*rssi_req)(nfapi_pnf_config_t* config, nfapi_pnf_phy_config_t* phy, nfapi_rssi_request_t* req); + + /*! A callback for the CELL_SEARCH.request + * \param config A pointer to the pnf configuration + * \param phy A pointer to the pnf phy configuration + * \param req A data structure for the decoded CELL_SEARCH.request. This will have + * been allocated on the stack + * \return not currently used + * + * The client is expected to send the CELL_SEARCH.response after receiving the + * CELL_SEARCH.request. This can be done in the call back. + */ + int (*cell_search_req)(nfapi_pnf_config_t* config, nfapi_pnf_phy_config_t* phy, nfapi_cell_search_request_t* req); + + /*! A callback for the BROADCAST_DETECT.request + * \param config A pointer to the pnf configuration + * \param phy A pointer to the pnf phy configuration + * \param req A data structure for the decoded BROADCAST_DETECT.request. This will have + * been allocated on the stack + * \return not currently used + * + * The client is expected to send the BROADCAST_DETECT.response after receiving the + * BROADCAST_DETECT.request. This can be done in the call back. + */ + int (*broadcast_detect_req)(nfapi_pnf_config_t* config, nfapi_pnf_phy_config_t* phy, nfapi_broadcast_detect_request_t* req); + + /*! A callback for the SYSTEM_INFORMATION_SCHEDULE.request + * \param config A pointer to the pnf configuration + * \param phy A pointer to the pnf phy configuration + * \param req A data structure for the decoded SYSTEM_INFORMATION_SCHEDULE.request. This will have + * been allocated on the stack + * \return not currently used + * + * The client is expected to send the SYSTEM_INFORMATION_SCHEDULE.response after receiving the + * SYSTEM_INFORMATION_SCHEDULE.request. This can be done in the call back. + */ + int (*system_information_schedule_req)(nfapi_pnf_config_t* config, nfapi_pnf_phy_config_t* phy, nfapi_system_information_schedule_request_t* req); + + /*! A callback for the SYSTEM_INFORMATION.request + * \param config A pointer to the pnf configuration + * \param phy A pointer to the pnf phy configuration + * \param req A data structure for the decoded SYSTEM_INFORMATION.request. This will have + * been allocated on the stack + * \return not currently used + * + * The client is expected to send the SYSTEM_INFORMATION.response after receiving the + * SYSTEM_INFORMATION.request. This can be done in the call back. + */ + int (*system_information_req)(nfapi_pnf_config_t* config, nfapi_pnf_phy_config_t* phy, nfapi_system_information_request_t* req); + + /*! A callback for the NMM_STOP.request + * \param config A pointer to the pnf configuration + * \param phy A pointer to the pnf phy configuration + * \param req A data structure for the decoded NMM_STOP.request. This will have + * been allocated on the stack + * \return not currently used + * + * The client is expected to send the NMM_STOP.response after receiving the + * NMM_STOP.request. This can be done in the call back. + */ + int (*nmm_stop_req)(nfapi_pnf_config_t* config, nfapi_pnf_phy_config_t* phy, nfapi_nmm_stop_request_t* req); + + /*! A callback for any vendor extension messages recevied + * \param config A pointer to the pnf configuration + * \param msg A pointer to the decode P4/P5 message + * \return not current used + */ + int (*vendor_ext)(nfapi_pnf_config_t* config, nfapi_p4_p5_message_header_t* msg); + + /*! A callback to allocate vendor extension message + * \param message_id The message id from the decode P4/P5 message header + * \param msg_size A pointer a the size of the allocated message structure. The callee should set this + * \return A pointer to a allocated P4/P5 message structure + */ + nfapi_p4_p5_message_header_t* (*allocate_p4_p5_vendor_ext)(uint16_t message_id, uint16_t* msg_size); + + /*! A callback to deallocate vendor extension message + * \param header A pointer to an P4/P5 message structure + */ + void (*deallocate_p4_p5_vendor_ext)(nfapi_p4_p5_message_header_t* header); + + + +} nfapi_pnf_config_t; + +/*! Create a pnf configuration + * \return A pointer to a pnf configuration struture + * + * This function will create and initialize a pnf instance. It is expected that + * the client will set the callback and parameters need before calling nfapi_pnf_start + * + * 0 will be returned if it fails. + * + * \code + * nfapi_pnf_config_t* config = nfapi_pnf_config_create(void); + * \endcode + */ +nfapi_pnf_config_t* nfapi_pnf_config_create(void); + +/*! Delete a pnf configuration + * \param config A pointer to a pnf configuraiton + * \return 0 is success, -1 for failure + */ +int nfapi_pnf_config_destroy(nfapi_pnf_config_t* config); + +/*! Start the PNF library. + * \param config A pointer to the pnf configuration + * \return 0 is success, -1 for failure + * + * This function will not return until nfapi_pnf_stop is called + * + * \code + * // Create the pnf config + * nfapi_pnf_config_t* config = nfapi_pnf_config_create(void); + * + * // Assumed that the vnf_address and vnf_port are provided over the P9 interface + * config->vnf_ip_addr = vnf_address; + * config->vnf_p5_port = vnf_port; + * + * // Set the required callbacks + * config->pnf_param_req = &pnf_param_request; + * ... + * + * // Call start for the PNF to initiate a connection to the VNF + * nfai_pnf_start(config); + * + * \endcode + */ +int nfapi_pnf_start(nfapi_pnf_config_t* config); + +/*! Stop the PNF library. + * \param config A pointer to the pnf configuration + * \return 0 is success, -1 for failure + * + * This function will cause the nfapi_pnf_start function to return + */ +int nfapi_pnf_stop(nfapi_pnf_config_t* config); + +/*! Send the PNF_PARAM.response + * \param config A pointer to a pnf configuraiton + * \param resp A pointer to the message structure + * \return 0 for success, -1 for failure + * + */ +int nfapi_pnf_pnf_param_resp(nfapi_pnf_config_t* config, nfapi_pnf_param_response_t* resp); + +/*! Send the PNF_CONFIG.response + * \param config A pointer to a pnf configuraiton + * \param resp A pointer to the message structure + * \return 0 for success, -1 for failure + * + */ +int nfapi_pnf_pnf_config_resp(nfapi_pnf_config_t* config, nfapi_pnf_config_response_t* resp); + +/*! Send the PNF_START.response + * \param config A pointer to a pnf configuraiton + * \param resp A pointer to the message structure + * \return 0 for success, -1 for failure + * + */ +int nfapi_pnf_pnf_start_resp(nfapi_pnf_config_t* config, nfapi_pnf_start_response_t* resp); + +/*! Send the PNF_STOP.response + * \param config A pointer to a pnf configuraiton + * \param resp A pointer to the message structure + * \return 0 for success, -1 for failure + * + */ +int nfapi_pnf_pnf_stop_resp(nfapi_pnf_config_t* config, nfapi_pnf_stop_response_t* resp); + +/*! Send the PARAM.response + * \param config A pointer to a pnf configuraiton + * \param resp A pointer to the message structure + * \return 0 for success, -1 for failure + * + */ +int nfapi_pnf_param_resp(nfapi_pnf_config_t* config, nfapi_param_response_t* resp); + +/*! Send the CONFIG.response + * \param config A pointer to a pnf configuraiton + * \param resp A pointer to the message structure + * \return 0 for success, -1 for failure + * + */ +int nfapi_pnf_config_resp(nfapi_pnf_config_t* config, nfapi_config_response_t* resp); + +/*! Send the START.response + * \param config A pointer to a pnf configuraiton + * \param resp A pointer to the message structure + * \return 0 for success, -1 for failure + * + */ +int nfapi_pnf_start_resp(nfapi_pnf_config_t* config, nfapi_start_response_t* resp); + +/*! Send the STOP.response + * \param config A pointer to a pnf configuraiton + * \param resp A pointer to the message structure + * \return 0 for success, -1 for failure + * + */ +int nfapi_pnf_stop_resp(nfapi_pnf_config_t* config, nfapi_stop_response_t* resp); + +/*! Send the MEASUREMENT.response + * \param config A pointer to a pnf configuraiton + * \param resp A pointer to the message structure + * \return 0 for success, -1 for failure + * + */ +int nfapi_pnf_measurement_resp(nfapi_pnf_config_t* config, nfapi_measurement_response_t* resp); + +/*! Send the RSSI.response + * \param config A pointer to a pnf configuraiton + * \param resp A pointer to the message structure + * \return 0 for success, -1 for failure + * + */ +int nfapi_pnf_rssi_resp(nfapi_pnf_config_t* config, nfapi_rssi_response_t* resp); + +/*! Send the RSSI.indication + * \param config A pointer to a pnf configuraiton + * \param ind A pointer to the message structure + * \return 0 for success, -1 for failure + * + */ +int nfapi_pnf_rssi_ind(nfapi_pnf_config_t* config, nfapi_rssi_indication_t* ind); + +/*! Send the CELL_SEARCH.response + * \param config A pointer to a pnf configuraiton + * \param resp A pointer to the message structure + * \return 0 for success, -1 for failure + * + */ +int nfapi_pnf_cell_search_resp(nfapi_pnf_config_t* config, nfapi_cell_search_response_t* resp); + +/*! Send the CELL_SEARCH.indication + * \param config A pointer to a pnf configuraiton + * \param ind A pointer to the message structure + * \return 0 for success, -1 for failure + * + */ +int nfapi_pnf_cell_search_ind(nfapi_pnf_config_t* config, nfapi_cell_search_indication_t* ind); + +/*! Send the BROADCAST_DETECT.response + * \param config A pointer to a pnf configuraiton + * \param resp A pointer to the message structure + * \return 0 for success, -1 for failure + * + */ +int nfapi_pnf_broadcast_detect_resp(nfapi_pnf_config_t* config, nfapi_broadcast_detect_response_t* resp); + +/*! Send the BROADCAST_DETECT.indication + * \param config A pointer to a pnf configuraiton + * \param ind A pointer to the message structure + * \return 0 for success, -1 for failure + * + */ +int nfapi_pnf_broadcast_detect_ind(nfapi_pnf_config_t* config, nfapi_broadcast_detect_indication_t* ind); + +/*! Send the SYSTEM_INFORMATION_SCHEDULE.response + * \param config A pointer to a pnf configuraiton + * \param resp A pointer to the message structure + * \return 0 for success, -1 for failure + * + */ +int nfapi_pnf_system_information_schedule_resp(nfapi_pnf_config_t* config, nfapi_system_information_schedule_response_t* resp); + +/*! Send the SYSTEM_INFORMATION_SCHEDULE.indication + * \param config A pointer to a pnf configuraiton + * \param ind A pointer to the message structure + * \return 0 for success, -1 for failure + * + */ +int nfapi_pnf_system_information_schedule_ind(nfapi_pnf_config_t* config, nfapi_system_information_schedule_indication_t* ind); + +/*! Send the SYSTEM_INFORMATION.response + * \param config A pointer to a pnf configuraiton + * \param resp A pointer to the message structure + * \return 0 for success, -1 for failure + * + */ +int nfapi_pnf_system_information_resp(nfapi_pnf_config_t* config, nfapi_system_information_response_t* resp); + +/*! Send the SYSTEM_INFORMATION.indication + * \param config A pointer to a pnf configuraiton + * \param ind A pointer to the message structure + * \return 0 for success, -1 for failure + * + */ +int nfapi_pnf_system_information_ind(nfapi_pnf_config_t* config, nfapi_system_information_indication_t* ind); + +/*! Send the NMM_STOP.response + * \param config A pointer to a pnf configuraiton + * \param resp A pointer to the message structure + * \return 0 for success, -1 for failure + * + */ +int nfapi_pnf_nmm_stop_resp(nfapi_pnf_config_t* config, nfapi_nmm_stop_response_t* resp); + +/*! Send a vendor extension message + * \param config A pointer to a pnf configuraiton + * \param msg A pointer to the vendor extention message structure + * \param msg_len The size of the vendor extention message structure + * \return 0 for success, -1 for failure + * + */ +int nfapi_pnf_vendor_extension(nfapi_pnf_config_t* config, nfapi_p4_p5_message_header_t* msg, uint32_t msg_len); + +//-------------------------- + +/*! A subframe buffer structure which can be used by the client to + * to configure the dummy information + */ +typedef struct +{ + uint16_t sfn_sf; + + nfapi_dl_config_request_t* dl_config_req; + nfapi_ul_config_request_t* ul_config_req; + nfapi_hi_dci0_request_t* hi_dci0_req; + nfapi_tx_request_t* tx_req; + nfapi_lbt_dl_config_request_t* lbt_dl_config_req; + +} nfapi_pnf_p7_subframe_buffer_t; + +typedef struct nfapi_pnf_p7_config nfapi_pnf_p7_config_t; + +/*! The nfapi PNF PHY P7 configuration information created using the nfapi_pnf_p7_create function + */ +typedef struct nfapi_pnf_p7_config +{ + /*! A user define callback to override the default memory allocation + * \param size The size of the buffer to allocate + * \return An allocated buffer. 0 in the case of failure + * + * If not set malloc will be used + */ + void* (*malloc)(size_t size); + + /*! A user define callback to override the default memory deallocation + * \param ptr Pointer to a buffer to dellocate + * + * If not set free will be used + */ + void (*free)(void* ptr); + + /*! A user define callback to handle trace from the pnf + * \param level The trace level + * \param message The message string + */ + void (*trace)(nfapi_trace_level_t level, const char* message, ...); + + /*! The PHY id*/ + uint16_t phy_id; + + // remote + /*! The VNF P7 UDP port */ + int remote_p7_port; + /*! The VNF P7 UDP address */ + char* remote_p7_addr; + + // local + /*! The PNF P7 UDP port */ + int local_p7_port; + /*! The PNF P7 UDP address */ + char* local_p7_addr; + + /*! Flag to indicate of the pnf should use the P7 checksum */ + uint8_t checksum_enabled; + + /*! The maxium size of a P7 segement. If a message is large that this it + * will be segemented */ + uint16_t segment_size; + + /*! The dummy subframe buffer structure that should be used in case there + * are no 'valid' subframe messages */ + nfapi_pnf_p7_subframe_buffer_t dummy_subframe; + + /*! Configuration options for the p7 pack unpack functions*/ + nfapi_p7_codec_config_t codec_config; + + /*! Optional userdata that will be passed back in the callbacks*/ + void* user_data; + + // tdb : if these should be public + uint16_t subframe_buffer_size; + uint8_t timing_info_mode_periodic; // 0:false 1:true + uint8_t timing_info_mode_aperiodic; // 0:false 1:true + uint8_t timing_info_period; // 1..225 in subframes + + /*! A callback for the DL_CONFIG.request + * \param config A poiner to the PNF P7 config + * \param req A pointer to the dl config request message structure + * \return not currently used + */ + int (*dl_config_req)(nfapi_pnf_p7_config_t* config, nfapi_dl_config_request_t* req); + + /*! A callback for the UL_CONFIG.request + * \param config A poiner to the PNF P7 config + * \param req A pointer to the ul config request message structure + * \return not currently used + */ + int (*ul_config_req)(nfapi_pnf_p7_config_t* config, nfapi_ul_config_request_t* req); + + /*! A callback for the HI_DCI0.request + * \param config A poiner to the PNF P7 config + * \param req A pointer to the hi dci0 request message structure + * \return not currently used + */ + int (*hi_dci0_req)(nfapi_pnf_p7_config_t* config, nfapi_hi_dci0_request_t* req); + + /*! A callback for the TX_REQ.request + * \param config A poiner to the PNF P7 config + * \param req A pointer to the tx request message structure + * \return not currently used + * + * The TX request contains pointers to the downlink PDUs to be sent. In the case that the FAPI interface + * will 'keep' the pointers until they are transmitted the callee should set the pointers in the req to 0 + * and then use the p7 codec config free function to release the pdu's when appropriate. + */ + int (*tx_req)(nfapi_pnf_p7_config_t* config, nfapi_tx_request_t* req); + + /*! A callback for the LBT_DL_CONFIG.request + * \param config A poiner to the PNF P7 config + * \param req A pointer to the lbt dl request message structure + * \return not currently used + */ + int (*lbt_dl_config_req)(nfapi_pnf_p7_config_t* config, nfapi_lbt_dl_config_request_t* req); + + /*! A callback for vendor extension messages + * \param config A poiner to the PNF P7 config + * \param msg A pointer to a decode vendor extention message + * \return not currently used + */ + int (*vendor_ext)(nfapi_pnf_p7_config_t* config, nfapi_p7_message_header_t* msg); + + /*! A callback to allocate vendor extension message + * \param message_id The vendor extention message id from the decode message header + * \param msg_size A pointer to size of the allocate vendor extention message. Set by the callee + * \return A pointer to an allocated vendor extention message structure. 0 if failed + * + * + */ + nfapi_p7_message_header_t* (*allocate_p7_vendor_ext)(uint16_t message_id, uint16_t* msg_size); + + /*! A callback to deallocate vendor extension message + * \param header A pointer to a p7 vendor extention message + */ + void (*deallocate_p7_vendor_ext)(nfapi_p7_message_header_t* header); + + + +} nfapi_pnf_p7_config_t; + +/*! Create and initialise a nfapi_pnf_p7_config structure + * \return A pointer to a PNF P7 config structure + */ +nfapi_pnf_p7_config_t* nfapi_pnf_p7_config_create(void); + +/*! Delete an nfapi_pnf_p7_config structure + * \param config + */ +int nfapi_pnf_p7_config_destroy(nfapi_pnf_p7_config_t* config); + + +/*! Start the PNF P7 library. + * \param config A pointer to a PNF P7 config + * \return 0 means success, -1 means failure + * + * This function will not return until nfapi_pnf_p7_stop is called. + */ +int nfapi_pnf_p7_start(nfapi_pnf_p7_config_t* config); + +/*! Stop the PNF P7 library. + * \param config A pointer to a PNF P7 config + * \return 0 means success, -1 means failure + * + * This function will cause the nfapi_pnf_p7_start to return + */ +int nfapi_pnf_p7_stop(nfapi_pnf_p7_config_t* config); + +/*! Subframe indication + * \param config A pointer to a PNF P7 config + * \param phy_id The phy_id for the phy instance + * \param sfn_sf The SFN and SF in the format of FAPI + * \return 0 means success, -1 means failure + * + * The client should call the subframe indication every 1ms. The PNF will + * respond by invoking the pnf p7 subframe callbacks with the messages from the subframe buffer + * + * If messages are not in the subframe buffer, they dummy subframe messages will be sent + */ +int nfapi_pnf_p7_subframe_ind(nfapi_pnf_p7_config_t* config, uint16_t phy_id, uint16_t sfn_sf); + +/*! Send the HARQ.indication + * \param config A pointer to a PNF P7 config + * \param ind A pointer to the harq indication message structure + * \return 0 means success, -1 means failure + */ +int nfapi_pnf_p7_harq_ind(nfapi_pnf_p7_config_t* config, nfapi_harq_indication_t* ind); + +/*! Send the CRC.indication + * \param config A pointer to a PNF P7 config + * \param ind A pointer to the crc indication message structure + * \return 0 means success, -1 means failure + */ +int nfapi_pnf_p7_crc_ind(nfapi_pnf_p7_config_t* config, nfapi_crc_indication_t* ind); + +/*! Send the RX.indication + * \param config A pointer to a PNF P7 config + * \param ind A pointer to the rx indication message structure + * \return 0 means success, -1 means failure + */ +int nfapi_pnf_p7_rx_ind(nfapi_pnf_p7_config_t* config, nfapi_rx_indication_t* ind); + +/*! Send the RACH.indication + * \param config A pointer to a PNF P7 config + * \param ind A pointer to the rach indication message structure + * \return 0 means success, -1 means failure + */ +int nfapi_pnf_p7_rach_ind(nfapi_pnf_p7_config_t* config, nfapi_rach_indication_t* ind); + +/*! Send the SRS.indication + * \param config A pointer to a PNF P7 config + * \param ind A pointer to the srs indication message structure + * \return 0 means success, -1 means failure + */ +int nfapi_pnf_p7_srs_ind(nfapi_pnf_p7_config_t* config, nfapi_srs_indication_t* ind); + +/*! Send the SR.indication + * \param config A pointer to a PNF P7 config + * \param ind A pointer to the sr indication message structure + * \return 0 means success, -1 means failure + */ +int nfapi_pnf_p7_sr_ind(nfapi_pnf_p7_config_t* config, nfapi_sr_indication_t* ind); + +/*! Send the CQI.indication + * \param config A pointer to a PNF P7 config + * \param ind A pointer to the cqi indication message structure + * \return 0 means success, -1 means failure + */ +int nfapi_pnf_p7_cqi_ind(nfapi_pnf_p7_config_t* config, nfapi_cqi_indication_t* ind); + +/*! Send the LBT_DL.indication + * \param config A pointer to a PNF P7 config + * \param ind A pointer to the lbt dl indication message structure + * \return 0 means success, -1 means failure + */ +int nfapi_pnf_p7_lbt_dl_ind(nfapi_pnf_p7_config_t* config, nfapi_lbt_dl_indication_t* ind); + +/*! Send the NB_HARQ.indication + * \param config A pointer to a PNF P7 config + * \param ind A pointer to the lbt dl indication message structure + * \return 0 means success, -1 means failure + */ +int nfapi_pnf_p7_nb_harq_ind(nfapi_pnf_p7_config_t* config, nfapi_nb_harq_indication_t* ind); + +/*! Send the NRACH.indication + * \param config A pointer to a PNF P7 config + * \param ind A pointer to the lbt dl indication message structure + * \return 0 means success, -1 means failure + */ +int nfapi_pnf_p7_nrach_ind(nfapi_pnf_p7_config_t* config, nfapi_nrach_indication_t* ind); + + +/*! Send a vendor exntesion message + * \param config A pointer to a PNF P7 config + * \param msg A pointer to the lbt dl indication message structure + * \return 0 means success, -1 means failure + */ +int nfapi_pnf_p7_vendor_extension(nfapi_pnf_p7_config_t* config, nfapi_p7_message_header_t* msg); + +#if defined(__cplusplus) +} +#endif + +#endif // _NFAPI_PNF_INTERFACE_H_ diff --git a/openair1/SCHED/phy_procedures_lte_ue.c b/openair1/SCHED/phy_procedures_lte_ue.c index 1f85d226f5dd97638b4742cdeff7098a6b46825d..15f735c5c91a92e455ef3630534663619d8d9b44 100644 --- a/openair1/SCHED/phy_procedures_lte_ue.c +++ b/openair1/SCHED/phy_procedures_lte_ue.c @@ -1766,7 +1766,6 @@ void ue_ulsch_uespec_procedures(PHY_VARS_UE *ue,UE_rxtx_proc_t *proc,uint8_t eNB if (ue->mac_enabled == 1) { // signal MAC that Msg3 was sent - // Substitute call to this function by call to fill_Tx_indication (UE_MAC_Tx_IND_Msg3_TYPE) Msg3_transmitted(Mod_id, CC_id, frame_tx, @@ -1784,9 +1783,6 @@ void ue_ulsch_uespec_procedures(PHY_VARS_UE *ue,UE_rxtx_proc_t *proc,uint8_t eNB //if (ue->ulsch[eNB_id]->harq_processes[harq_pid]->calibration_flag == 0) { access_mode=SCHEDULED_ACCESS; - // Panos: Remove the call to ue_get_sdu here and use - // the corresponding Tx.request PDU, instead of ulsch_input_buffer, below. - ue_get_sdu(Mod_id, CC_id, frame_tx, diff --git a/openair2/LAYER2/MAC/ue_procedures.c b/openair2/LAYER2/MAC/ue_procedures.c index 173ef442562cf6a16a82d62099f83caa2d20a13d..f411d3ff8beaddd988899453a7186e6bbb45cd0d 100644 --- a/openair2/LAYER2/MAC/ue_procedures.c +++ b/openair2/LAYER2/MAC/ue_procedures.c @@ -52,6 +52,7 @@ #include "UTIL/OPT/opt.h" #include "OCG.h" #include "OCG_extern.h" +#include "openair2/PHY_INTERFACE/phy_stub_UE.h" #ifdef PHY_EMUL # include "SIMULATION/simulation_defs.h" @@ -71,6 +72,8 @@ extern uint8_t usim_test; +extern UL_IND_t *UL_INFO; + /* #ifndef USER_MODE #define msg debug_msg @@ -1586,7 +1589,9 @@ for (lcid=DCCH; (lcid < MAX_NUM_LCID) && (is_all_lcid_processed == FALSE) ; lcid // build PHR and update the timers if (phr_ce_len == sizeof(POWER_HEADROOM_CMD)) { - phr_p->PH = get_phr_mapping(module_idP,CC_id,eNB_index); + //Panos: Substitute with a static value for the MAC layer abstraction + //phr_p->PH = get_phr_mapping(module_idP,CC_id,eNB_index); + phr_p->PH = 40; phr_p->R = 0; LOG_D(MAC,"[UE %d] Frame %d report PHR with mapping (%d->%d) for LCID %d\n", module_idP,frameP, get_PHR(module_idP,CC_id,eNB_index), phr_p->PH,POWER_HEADROOM); @@ -1595,6 +1600,7 @@ for (lcid=DCCH; (lcid < MAX_NUM_LCID) && (is_all_lcid_processed == FALSE) ; lcid phr_p=NULL; } + LOG_T(MAC,"[UE %d] Frame %d: bsr s %p bsr_l %p, phr_p %p\n", module_idP,frameP,bsr_s, bsr_l, phr_p); @@ -1804,7 +1810,6 @@ for (lcid=DCCH; (lcid < MAX_NUM_LCID) && (is_all_lcid_processed == FALSE) ; lcid stop_meas(&UE_mac_inst[module_idP].tx_ulsch_sdu); #endif - // Panos: Tx_request should be filled from the ulsch_buffer here. if (opt_enabled) { trace_pdu(0, ulsch_buffer, buflen, module_idP, 3, UE_mac_inst[module_idP].crnti, UE_mac_inst[module_idP].txFrame, UE_mac_inst[module_idP].txSubframe, 0, 0); @@ -1813,6 +1818,8 @@ for (lcid=DCCH; (lcid < MAX_NUM_LCID) && (is_all_lcid_processed == FALSE) ; lcid } } + + //------------------------------------------------------------------------------ // called at each subframe // Performs : diff --git a/openair2/PHY_INTERFACE/phy_stub_UE.c b/openair2/PHY_INTERFACE/phy_stub_UE.c index 8a5e05c50d9025b7d004d2646f06ab318d56fc0e..7072b5e0386605de91946850efbe1da6c444a072 100644 --- a/openair2/PHY_INTERFACE/phy_stub_UE.c +++ b/openair2/PHY_INTERFACE/phy_stub_UE.c @@ -7,11 +7,15 @@ #include "openair2/LAYER2/MAC/vars.h" //#include "common/ran_context.h" #include "openair2/PHY_INTERFACE/phy_stub_UE.h" +//#include "nfapi_pnf_interface.h" +//#include "nfapi.h" +//#include "nfapi_pnf.h" -//extern uint8_t nfapi_pnf; +//extern uint8_t nfapi_pnf; +//UL_IND_t *UL_INFO; void handle_nfapi_UE_Rx(uint8_t Mod_id, Sched_Rsp_t *Sched_INFO, int eNB_id){ @@ -80,11 +84,11 @@ void handle_nfapi_UE_Rx(uint8_t Mod_id, Sched_Rsp_t *Sched_INFO, int eNB_id){ // C-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 c_rnti = UE_mac_inst[Mod_id].crnti; + rnti_t c_rnti = UE_mac_inst[Mod_id].crnti; ue_process_rar(Mod_id, CC_id, frame, dl_config_pdu_tmp->dlsch_pdu.dlsch_pdu_rel8.rnti, //RA-RNTI Tx_req->tx_request_body.tx_pdu_list[dl_config_pdu_tmp->dlsch_pdu.dlsch_pdu_rel8.pdu_index].segments[0].segment_data, - c_rnti, + &c_rnti, UE_mac_inst[Mod_id].RA_prach_resources.ra_PreambleIndex, Tx_req->tx_request_body.tx_pdu_list[dl_config_pdu_tmp->dlsch_pdu.dlsch_pdu_rel8.pdu_index].segments[0].segment_data); } @@ -102,15 +106,18 @@ void handle_nfapi_UE_Rx(uint8_t Mod_id, Sched_Rsp_t *Sched_INFO, int eNB_id){ } -void fill_rx_indication_UE_MAC(int Mod_id,int frame,int subframe, UL_IND_t *UL_INFO, uint8_t *ulsch_buffer, uint16_t buflen) + +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) { nfapi_rx_indication_pdu_t *pdu; int timing_advance_update; //int sync_pos; - /*uint32_t harq_pid = subframe2harq_pid(&eNB->frame_parms, - frame,subframe);*/ + //uint32_t harq_pid = subframe2harq_pid(&eNB->frame_parms, + // frame,subframe); + + //UL_IND_t *UL_INFO = (UL_IND_t*)malloc16(sizeof(UL_IND_t)); pthread_mutex_lock(&UE_mac_inst[Mod_id].UL_INFO_mutex); @@ -122,7 +129,7 @@ void fill_rx_indication_UE_MAC(int Mod_id,int frame,int subframe, UL_IND_t *UL_I // 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 = UE_mac_inst[Mod_id].crnti; + pdu->rx_ue_information.rnti = rnti; pdu->rx_indication_rel8.tl.tag = NFAPI_RX_INDICATION_REL8_TAG; //pdu->rx_indication_rel8.length = eNB->ulsch[UE_id]->harq_processes[harq_pid]->TBS>>3; pdu->rx_indication_rel8.length = buflen; @@ -134,7 +141,7 @@ void fill_rx_indication_UE_MAC(int Mod_id,int frame,int subframe, UL_IND_t *UL_I pdu->rx_indication_rel8.timing_advance = timing_advance_update; // if (timing_advance_update > 10) { dump_ulsch(eNB,frame,subframe,UE_id); exit(-1);} - // if (timing_advance_update < -10) { dump_ulsch(eNB,frame,subframe,UE_id); exit(-1);} + // if (timing_advance_update < -10) { dump_ulsch(eNB,frame,subframe,UE_id); exit(-1);}*/ /*switch (eNB->frame_parms.N_RB_DL) { case 6: pdu->rx_indication_rel8.timing_advance = timing_advance_update; @@ -182,7 +189,7 @@ void fill_rx_indication_UE_MAC(int Mod_id,int frame,int subframe, UL_IND_t *UL_I } -void fill_sr_indication_UE_MAC(int Mod_id,int frame,int subframe, UL_IND_t *UL_INFO) { +void fill_sr_indication_UE_MAC(int Mod_id,int frame,int subframe, UL_IND_t *UL_INFO, uint16_t rnti) { pthread_mutex_lock(&UE_mac_inst[Mod_id].UL_INFO_mutex); nfapi_sr_indication_pdu_t *pdu = &UL_INFO->sr_ind.sr_pdu_list[UL_INFO->rx_ind.number_of_pdus]; @@ -190,7 +197,7 @@ void fill_sr_indication_UE_MAC(int Mod_id,int frame,int subframe, UL_IND_t *UL_I 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 = UE_mac_inst[Mod_id].crnti;; //Panos: Is this the right RNTI? + pdu->rx_ue_information.rnti = rnti; //UE_mac_inst[Mod_id].crnti;; //Panos: Is this the right RNTI? // Panos dependency from PHY not sure how to substitute this. Should we hardcode it? @@ -244,6 +251,7 @@ void fill_rach_indication_UE_MAC(int Mod_id,int frame,int subframe, UL_IND_t *UL //Panos: The two following should get extracted from the call to get_prach_resources(). UL_INFO->rach_ind.preamble_list[0].preamble_rel8.preamble = ra_PreambleIndex; UL_INFO->rach_ind.preamble_list[0].preamble_rel8.rnti = ra_RNTI; + UL_INFO->rach_ind.number_of_preambles++; UL_INFO->rach_ind.preamble_list[0].preamble_rel13.rach_resource_type = 0; @@ -253,10 +261,14 @@ void fill_rach_indication_UE_MAC(int Mod_id,int frame,int subframe, UL_IND_t *UL // If NFAPI PNF then we need to send the message to the VNF //if (nfapi_pnf == 1) //{ - nfapi_rach_indication_t rach_ind; - rach_ind.header.message_id = NFAPI_RACH_INDICATION; - rach_ind.sfn_sf = frame<<4 | subframe; - rach_ind.rach_indication_body = UL_INFO->rach_ind; + //Panos: Not sure if we need the following. They refer to nfapi_rach_indication_t type + //so we cannot insert it to the UL_INFO which has an nfapi_rach_indication_body_t type. + //Probably it should be part of UL_indication() function before calling oai_nfapi_rach_ind(&rach_ind). + + /*nfapi_rach_indication_t *rach_ind; + rach_ind->header.message_id = NFAPI_RACH_INDICATION; + rach_ind->sfn_sf = frame<<4 | subframe; + rach_ind->rach_indication_body = UL_INFO->rach_ind;*/ LOG_E(PHY,"\n\n\n\nDJP - this needs to be sent to VNF **********************************************\n\n\n\n"); LOG_E(PHY,"UE Filling NFAPI indication for RACH : TA %d, Preamble %d, rnti %x, rach_resource_type %d\n", @@ -275,12 +287,12 @@ void fill_rach_indication_UE_MAC(int Mod_id,int frame,int subframe, UL_IND_t *UL } -void fill_ulsch_cqi_indication(int Mod_id, uint16_t frame,uint8_t subframe, UL_IND_t *UL_INFO) { +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(&UE_mac_inst[Mod_id].UL_INFO_mutex); nfapi_cqi_indication_pdu_t *pdu = &UL_INFO->cqi_ind.cqi_pdu_list[UL_INFO->cqi_ind.number_of_cqis]; nfapi_cqi_indication_raw_pdu_t *raw_pdu = &UL_INFO->cqi_ind.cqi_raw_pdu_list[UL_INFO->cqi_ind.number_of_cqis]; - pdu->rx_ue_information.rnti = UE_mac_inst[Mod_id].crnti;; + pdu->rx_ue_information.rnti = rnti; //if (ulsch_harq->cqi_crc_status != 1) //Panos: Since we assume that CRC flag is always 0 (ACK) I guess that data_offset should always be 0. pdu->cqi_indication_rel9.data_offset = 0; @@ -315,6 +327,452 @@ void fill_ulsch_cqi_indication(int Mod_id, uint16_t frame,uint8_t subframe, UL_I } +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) +{ + + //int UE_id = find_dlsch(rnti,eNB,SEARCH_EXIST); + //AssertFatal(UE_id>=0,"UE_id doesn't exist\n"); + + pthread_mutex_lock(&UE_mac_inst[Mod_id].UL_INFO_mutex); + nfapi_harq_indication_pdu_t *pdu = &UL_INFO->harq_ind.harq_pdu_list[UL_INFO->harq_ind.number_of_harqs]; + int i; + + pdu->instance_length = 0; // don't know what to do with this + // pdu->rx_ue_information.handle = handle; + pdu->rx_ue_information.rnti = rnti; + + //Panos: For now we consider only FDD + //if (eNB->frame_parms.frame_type == FDD) { + pdu->harq_indication_fdd_rel13.mode = 0; + pdu->harq_indication_fdd_rel13.number_of_ack_nack = harq_information->harq_information_rel10.harq_size; + + //Panos: 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 (i=0;i<harq_information->harq_information_rel10.harq_size;i++) { + //AssertFatal(ulsch_harq->o_ACK[i] == 0 || ulsch_harq->o_ACK[i] == 1, "harq_ack[%d] is %d, should be 1,2 or 4\n",i,ulsch_harq->o_ACK[i]); + + pdu->harq_indication_fdd_rel13.harq_tb_n[i] = 1; //Panos: Assuming always an ACK (No NACK or DTX) + // release DLSCH if needed + //if (ulsch_harq->o_ACK[i] == 1) release_harq(eNB,UE_id,i,frame,subframe,0xffff); + + } + //} + /*else { // TDD + M=ul_ACK_subframe2_M(&eNB->frame_parms, + subframe); + + pdu->harq_indication_fdd_rel13.mode = 1-bundling; + pdu->harq_indication_fdd_rel13.number_of_ack_nack = ulsch_harq->O_ACK; + + for (i=0;i<ulsch_harq->O_ACK;i++) { + AssertFatal(ulsch_harq->o_ACK[i] == 0 || ulsch_harq->o_ACK[i] == 1, "harq_ack[%d] is %d, should be 1,2 or 4\n",i,ulsch_harq->o_ACK[i]); + + pdu->harq_indication_tdd_rel13.harq_data[0].multiplex.value_0 = 2-ulsch_harq->o_ACK[i]; + // release DLSCH if needed + if (ulsch_harq->o_ACK[i] == 1) release_harq(eNB,UE_id,i,frame,subframe,0xffff); + if (M==1 && ulsch_harq->O_ACK==1 && ulsch_harq->o_ACK[i] == 1) release_harq(eNB,UE_id,0,frame,subframe,0xffff); + else if (M==1 && ulsch_harq->O_ACK==2 && ulsch_harq->o_ACK[i] == 1) release_harq(eNB,UE_id,i,frame,subframe,0xffff); + else if (M>1 && ulsch_harq->o_ACK[i] == 1) { + // spatial bundling + release_harq(eNB,UE_id,0,frame,subframe,1<<i); + release_harq(eNB,UE_id,1,frame,subframe,1<<i); + } + } + }*/ + + UL_INFO->harq_ind.number_of_harqs++; + pthread_mutex_unlock(&UE_mac_inst[Mod_id].UL_INFO_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 + /*uint8_t tdd_mapping_mode, + uint16_t tdd_multiplexing_mask*/) { + + //int UE_id=find_dlsch(uci->rnti,eNB,SEARCH_EXIST); + //AssertFatal(UE_id>=0,"UE_id doesn't exist\n"); + + + pthread_mutex_lock(&UE_mac_inst[Mod_id].UL_INFO_mutex); + nfapi_harq_indication_pdu_t *pdu = &UL_INFO->harq_ind.harq_pdu_list[UL_INFO->harq_ind.number_of_harqs]; + + pdu->instance_length = 0; // don't know what to do with this + // pdu->rx_ue_information.handle = handle; + pdu->rx_ue_information.rnti = rnti; + + // estimate UL_CQI for MAC (from antenna port 0 only) + + // Panos: Set static SNR for now + //int SNRtimes10 = dB_fixed_times10(uci->stat) - 200;//(10*eNB->measurements.n0_power_dB[0]); + int SNRtimes10 = 640; + + //if (SNRtimes10 < -100) LOG_I(PHY,"uci->stat %d \n",uci->stat); + + 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; + + //Panos: Considering only FDD for now + //if (eNB->frame_parms.frame_type == FDD) { + + //Panos: Condition taken from fapi_l1::handle_uci_harq_information() function + if ((harq_information->harq_information_rel9_fdd.ack_nack_mode == 0) && + (harq_information->harq_information_rel9_fdd.harq_size == 1)) { + //if (uci->pucch_fmt == pucch_format1a) { + 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; //Panos: 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.mode = 0; + pdu->harq_indication_fdd_rel13.number_of_ack_nack = 2; + //AssertFatal(harq_ack[0] == 1 || harq_ack[0] == 2 || harq_ack[1] == 4, "harq_ack[0] is %d, should be 0,1 or 4\n",harq_ack[0]); + //AssertFatal(harq_ack[1] == 1 || harq_ack[1] == 2 || harq_ack[1] == 4, "harq_ack[1] is %d, should be 0,1 or 4\n",harq_ack[1]); + pdu->harq_indication_fdd_rel13.harq_tb_n[0] = 1; //Panos: Assuming always an ACK (No NACK or DTX) + pdu->harq_indication_fdd_rel13.harq_tb_n[1] = 1; //Panos: Assuming always an ACK (No NACK or DTX) + // release DLSCH if needed + //if (harq_ack[0] == 1) release_harq(eNB,UE_id,0,frame,subframe,0xffff); + //if (harq_ack[1] == 1) release_harq(eNB,UE_id,1,frame,subframe,0xffff); + } + else AssertFatal(1==0,"only format 1a/b for now, received \n"); + //} + /*else { // TDD + + AssertFatal(tdd_mapping_mode==0 || tdd_mapping_mode==1 || tdd_mapping_mode==2, + "Illegal tdd_mapping_mode %d\n",tdd_mapping_mode); + + pdu->harq_indication_tdd_rel13.mode = tdd_mapping_mode; + + switch (tdd_mapping_mode) { + case 0: // bundling + + if (uci->pucch_fmt == pucch_format1a) { + pdu->harq_indication_tdd_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_tdd_rel13.harq_data[0].bundling.value_0 = harq_ack[0]; + // release all bundled DLSCH if needed + if (harq_ack[0] == 1) release_harq(eNB,UE_id,0,frame,subframe,0xffff); + } + else if (uci->pucch_fmt == pucch_format1b) { + pdu->harq_indication_tdd_rel13.number_of_ack_nack = 2; + AssertFatal(harq_ack[0] == 1 || harq_ack[0] == 2 || harq_ack[1] == 4, "harq_ack[0] is %d, should be 0,1 or 4\n",harq_ack[0]); + AssertFatal(harq_ack[1] == 1 || harq_ack[1] == 2 || harq_ack[1] == 4, "harq_ack[1] is %d, should be 0,1 or 4\n",harq_ack[1]); + pdu->harq_indication_tdd_rel13.harq_data[0].bundling.value_0 = harq_ack[0]; + pdu->harq_indication_tdd_rel13.harq_data[1].bundling.value_0 = harq_ack[1]; + // release all DLSCH if needed + if (harq_ack[0] == 1) release_harq(eNB,UE_id,0,frame,subframe,0xffff); + if (harq_ack[1] == 1) release_harq(eNB,UE_id,1,frame,subframe,0xffff); + } + break; + case 1: // multiplexing + AssertFatal(uci->pucch_fmt == pucch_format1b,"uci->pucch_format %d is not format1b\n",uci->pucch_fmt); + + if (uci->num_pucch_resources == 1 && uci->pucch_fmt == pucch_format1a) { + pdu->harq_indication_tdd_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_tdd_rel13.harq_data[0].multiplex.value_0 = harq_ack[0]; + // release all DLSCH if needed + if (harq_ack[0] == 1) release_harq(eNB,UE_id,0,frame,subframe,0xffff); + } + else if (uci->num_pucch_resources == 1 && uci->pucch_fmt == pucch_format1b) { + pdu->harq_indication_tdd_rel13.number_of_ack_nack = 2; + AssertFatal(harq_ack[0] == 1 || harq_ack[0] == 2 || harq_ack[1] == 4, "harq_ack[0] is %d, should be 0,1 or 4\n",harq_ack[0]); + AssertFatal(harq_ack[1] == 1 || harq_ack[1] == 2 || harq_ack[1] == 4, "harq_ack[1] is %d, should be 0,1 or 4\n",harq_ack[1]); + pdu->harq_indication_tdd_rel13.harq_data[0].multiplex.value_0 = harq_ack[0]; + pdu->harq_indication_tdd_rel13.harq_data[1].multiplex.value_0 = harq_ack[1]; + // release all DLSCH if needed + if (harq_ack[0] == 1) release_harq(eNB,UE_id,0,frame,subframe,0xffff); + if (harq_ack[1] == 1) release_harq(eNB,UE_id,1,frame,subframe,0xffff); + } + else { // num_pucch_resources (M) > 1 + pdu->harq_indication_tdd_rel13.number_of_ack_nack = uci->num_pucch_resources; + + pdu->harq_indication_tdd_rel13.harq_data[0].multiplex.value_0 = harq_ack[0]; + pdu->harq_indication_tdd_rel13.harq_data[1].multiplex.value_0 = harq_ack[1]; + if (uci->num_pucch_resources == 3) pdu->harq_indication_tdd_rel13.harq_data[2].multiplex.value_0 = harq_ack[2]; + if (uci->num_pucch_resources == 4) pdu->harq_indication_tdd_rel13.harq_data[3].multiplex.value_0 = harq_ack[3]; + // spatial-bundling in this case so release both HARQ if necessary + release_harq(eNB,UE_id,0,frame,subframe,tdd_multiplexing_mask); + release_harq(eNB,UE_id,1,frame,subframe,tdd_multiplexing_mask); + } + break; + case 2: // special bundling (SR collision) + pdu->harq_indication_tdd_rel13.number_of_ack_nack = 1; + int tdd_config5_sf2scheds=0; + if (eNB->frame_parms.tdd_config==5) tdd_config5_sf2scheds = getM(eNB,frame,subframe); + + switch (harq_ack[0]) { + case 0: + break; + case 1: // check if M=1,4,7 + if (uci->num_pucch_resources == 1 || uci->num_pucch_resources == 4 || + tdd_config5_sf2scheds == 1 || tdd_config5_sf2scheds == 4 || tdd_config5_sf2scheds == 7) { + release_harq(eNB,UE_id,0,frame,subframe,0xffff); + release_harq(eNB,UE_id,1,frame,subframe,0xffff); + } + break; + case 2: // check if M=2,5,8 + if (uci->num_pucch_resources == 2 || tdd_config5_sf2scheds == 2 || + tdd_config5_sf2scheds == 5 || tdd_config5_sf2scheds == 8) { + release_harq(eNB,UE_id,0,frame,subframe,0xffff); + release_harq(eNB,UE_id,1,frame,subframe,0xffff); + } + break; + case 3: // check if M=3,6,9 + if (uci->num_pucch_resources == 3 || tdd_config5_sf2scheds == 3 || + tdd_config5_sf2scheds == 6 || tdd_config5_sf2scheds == 9) { + release_harq(eNB,UE_id,0,frame,subframe,0xffff); + release_harq(eNB,UE_id,1,frame,subframe,0xffff); + } + break; + } + break; + + } + } //TDD*/ + + + UL_INFO->harq_ind.number_of_harqs++; + LOG_E(PHY,"Incremented eNB->UL_INFO.harq_ind.number_of_harqs:%d\n", UL_INFO->harq_ind.number_of_harqs); + pthread_mutex_unlock(&UE_mac_inst[Mod_id].UL_INFO_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) +{ + nfapi_ul_config_ulsch_pdu_rel8_t *rel8 = &ul_config_pdu->ulsch_pdu.ulsch_pdu_rel8; + + //int8_t UE_id; + + // check if we have received a dci for this ue and ulsch descriptor is configured + + if (ul_config_pdu->pdu_type == NFAPI_UL_CONFIG_ULSCH_PDU_TYPE) { + //AssertFatal((UE_id = find_ulsch(ul_config_pdu->ulsch_pdu.ulsch_pdu_rel8.rnti,eNB,SEARCH_EXIST_OR_FREE))>=0, + // "No existing UE ULSCH for rnti %x\n",rel8->rnti); + LOG_D(PHY,"Applying UL config for UE, rnti %x for frame %d, subframe %d\n", + 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){ + ue_get_sdu( Mod_id, 0, frame, subframe, 0, ulsch_buffer, buflen, &access_mode); + fill_rx_indication_UE_MAC(Mod_id, frame, subframe, UL_INFO, ulsch_buffer,buflen, rnti); + } + } + + 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){ + ue_get_sdu( Mod_id, 0, frame, subframe, 0, ulsch_buffer, buflen, &access_mode); + fill_rx_indication_UE_MAC(Mod_id, frame, subframe, UL_INFO, ulsch_buffer,buflen, rnti); + } + + if(ulsch_harq_information) + fill_ulsch_harq_indication_UE_MAC(Mod_id, frame, subframe, UL_INFO, ulsch_harq_information, rnti); + + } + else if (ul_config_pdu->pdu_type == NFAPI_UL_CONFIG_ULSCH_CQI_RI_PDU_TYPE) { + //AssertFatal((UE_id = find_ulsch(ul_config_pdu->ulsch_cqi_ri_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_cqi_ri_pdu.ulsch_pdu.ulsch_pdu_rel8.rnti); + 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){ + ue_get_sdu( Mod_id, 0, frame, subframe, 0, ulsch_buffer, buflen, &access_mode); + fill_rx_indication_UE_MAC(Mod_id, frame, subframe, UL_INFO, ulsch_buffer,buflen, rnti); + } + fill_ulsch_cqi_indication_UE_MAC(Mod_id, frame, subframe, UL_INFO, rnti); + + } + else if (ul_config_pdu->pdu_type == NFAPI_UL_CONFIG_ULSCH_CQI_HARQ_RI_PDU_TYPE) { + //AssertFatal((UE_id = find_ulsch(ul_config_pdu->ulsch_cqi_harq_ri_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_cqi_harq_ri_pdu.ulsch_pdu.ulsch_pdu_rel8.rnti); + + 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){ + ue_get_sdu( Mod_id, 0, frame, subframe, 0, ulsch_buffer, buflen, &access_mode); + fill_rx_indication_UE_MAC(Mod_id, frame, subframe, UL_INFO, ulsch_buffer,buflen, rnti); + } + + if(ulsch_harq_information) + fill_ulsch_harq_indication_UE_MAC(Mod_id, frame, subframe, UL_INFO, ulsch_harq_information, rnti); + fill_ulsch_cqi_indication_UE_MAC(Mod_id, frame, subframe, UL_INFO, rnti); + + } + else if (ul_config_pdu->pdu_type == NFAPI_UL_CONFIG_UCI_HARQ_PDU_TYPE) { + // AssertFatal((UE_id = find_uci(ul_config_pdu->uci_harq_pdu.ue_information.ue_information_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_harq_pdu.ue_information.ue_information_rel8.rnti); + + 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; + + fill_uci_harq_indication_UE_MAC(Mod_id, frame, subframe, UL_INFO,ulsch_harq_information, rnti); + } + 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) { + //AssertFatal((UE_id = find_uci(ul_config_pdu->uci_sr_pdu.ue_information.ue_information_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_pdu.ue_information.ue_information_rel8.rnti); + uint16_t rnti = ul_config_pdu->uci_sr_pdu.ue_information.ue_information_rel8.rnti; + + fill_sr_indication_UE_MAC(Mod_id, frame, subframe, UL_INFO, rnti); + + } + 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); + + nfapi_ul_config_harq_information *ulsch_harq_information = &ul_config_pdu->uci_sr_harq_pdu.harq_information; + fill_uci_harq_indication_UE_MAC(Mod_id, frame, subframe, UL_INFO,ulsch_harq_information, rnti); + + } + /*else if (ul_config_pdu->pdu_type == NFAPI_UL_CONFIG_SRS_PDU_TYPE) { + handle_srs_pdu(eNB,ul_config_pdu,frame,subframe); + }*/ +} + + + + + + +int ul_config_req_UE_MAC(nfapi_pnf_p7_config_t* pnf_p7, nfapi_ul_config_request_t* req) +{ + 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 + ); + + /*if (RC.ru == 0) + { + return -1; + } + + if (RC.eNB == 0) + { + return -2; + } + + if (RC.eNB[0][0] == 0) + { + return -3; + } + + if (sync_var != 0) + { + NFAPI_TRACE(NFAPI_TRACE_INFO, "%s() Main system not up - is this a dummy subframe?\n", __FUNCTION__); + return -4; + }*/ + + int sfn = NFAPI_SFNSF2SFN(req->sfn_sf); + int sf = NFAPI_SFNSF2SF(req->sfn_sf); + + //struct PHY_VARS_eNB_s *eNB = RC.eNB[0][0]; + //eNB_rxtx_proc_t *proc = &eNB->proc.proc_rxtx[0]; + + module_id_t Mod_id = 0; //Panos: Currently static (only for one UE) but this should change. + nfapi_ul_config_request_pdu_t* ul_config_pdu_list = req->ul_config_request_body.ul_config_pdu_list; + + //Panos: Not sure whether we should put the memory allocation here. + //*** Note we should find the right place to call free(UL_INFO). + UL_INFO = (UL_IND_t*)malloc(sizeof(UL_IND_t)); + + uint8_t is_rach = req->ul_config_request_body.rach_prach_frequency_resources; + if(is_rach) { + PRACH_RESOURCES_t *prach_resources = ue_get_rach(Mod_id, 0, sfn, 0, sf); + fill_rach_indication_UE_MAC(Mod_id, sfn ,sf, UL_INFO, prach_resources->ra_PreambleIndex, prach_resources->ra_RNTI); + } + + // subframe works off TX SFN/SF which is 4 ahead, need to put it back to RX SFN/SF + // probably could just use proc->frame_rx + + // PanosQ: This an eNB MAC function. Are we allowed to call it from here? + // Also, it is only in the nfapi-RU-RAU-split + //subtract_subframe(&sfn, &sf, 4); + + + for (int i=0;i<req->ul_config_request_body.number_of_pdus;i++) + { + //NFAPI_TRACE(NFAPI_TRACE_INFO, "%s() sfn/sf:%d PDU[%d] size:%d\n", __FUNCTION__, NFAPI_SFNSF2DEC(req->sfn_sf), i, ul_config_pdu_list[i].pdu_size); + + if ( + ul_config_pdu_list[i].pdu_type == NFAPI_UL_CONFIG_ULSCH_PDU_TYPE || + ul_config_pdu_list[i].pdu_type == NFAPI_UL_CONFIG_ULSCH_HARQ_PDU_TYPE || + ul_config_pdu_list[i].pdu_type == NFAPI_UL_CONFIG_ULSCH_CQI_RI_PDU_TYPE || + ul_config_pdu_list[i].pdu_type == NFAPI_UL_CONFIG_ULSCH_CQI_HARQ_RI_PDU_TYPE || + ul_config_pdu_list[i].pdu_type == NFAPI_UL_CONFIG_UCI_HARQ_PDU_TYPE || + ul_config_pdu_list[i].pdu_type == NFAPI_UL_CONFIG_UCI_SR_PDU_TYPE || + ul_config_pdu_list[i].pdu_type == NFAPI_UL_CONFIG_UCI_SR_HARQ_PDU_TYPE + ) + { + //NFAPI_TRACE(NFAPI_TRACE_INFO, "%s() handle_nfapi_ul_pdu() for PDU:%d\n", __FUNCTION__, i); + + + handle_nfapi_ul_pdu_UE_MAC(Mod_id,&ul_config_pdu_list[i],sfn,sf,req->ul_config_request_body.srs_present); + } + else + { + //NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s() PDU:%i UNKNOWN type :%d\n", __FUNCTION__, i, ul_config_pdu_list[i].pdu_type); + } + } + + return 0; +} + + + + diff --git a/openair2/PHY_INTERFACE/phy_stub_UE.h b/openair2/PHY_INTERFACE/phy_stub_UE.h index 58ce7346f76de813535999c6b7fbd2aa34457740..b3b07b60b32e98f29ee5bdcf8569c2a6a3a41f10 100644 --- a/openair2/PHY_INTERFACE/phy_stub_UE.h +++ b/openair2/PHY_INTERFACE/phy_stub_UE.h @@ -11,10 +11,15 @@ #include <stdint.h> #include "openair2/PHY_INTERFACE/IF_Module.h" +#include "nfapi_interface.h" +#include "nfapi_pnf_interface.h" //#include "openair1/PHY/LTE_TRANSPORT/defs.h" //#include "openair1/PHY/defs.h" //#include "openair1/PHY/LTE_TRANSPORT/defs.h" +UL_IND_t *UL_INFO; + + // Panos: This function should return all the sched_response config messages which concern a specific UE. Inside this // function we should somehow make the translation of config message's rnti to Mod_ID. @@ -24,6 +29,8 @@ Sched_Rsp_t get_nfapi_sched_response(uint8_t Mod_id); // namely:ue_send_sdu(), or ue_decode_si(), or ue_decode_p(), or ue_process_rar() based on the rnti type. void handle_nfapi_UE_Rx(uint8_t Mod_id, Sched_Rsp_t *Sched_INFO, int eNB_id); +int pnf_ul_config_req_UE_MAC(nfapi_pnf_p7_config_t* pnf_p7, nfapi_ul_config_request_t* req); + // This function will be processing UL and HI_DCI0 config requests to trigger all the MAC Tx related calls // at the UE side, namely: ue_get_SR(), ue_get_rach(), ue_get_sdu() based on the pdu configuration type. // The output of these calls will be put to an UL_IND_t structure which will then be the input to @@ -35,12 +42,15 @@ void send_nfapi_UL_indications(UL_IND_t UL_INFO); // This function should be filling the nfapi ULSCH indications at the MAC level of the UE in a similar manner // as fill_rx_indication() does. It should get called from ue_get_SDU() -void fill_rx_indication_UE_MAC(int Mod_id,int frame,int subframe, UL_IND_t *UL_INFO, uint8_t *ulsch_buffer, uint16_t buflen); + +//void fill_rx_indication_UE_MAC(module_id_t Mod_id,int frame,int subframe); + +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); // This function should be indicating directly to the eNB when there is a planned scheduling request at the MAC layer // of the UE. It should get called from ue_get_SR() -void fill_sr_indication_UE_MAC(int Mod_id,int frame,int subframe, UL_IND_t *UL_INFO); +void fill_sr_indication_UE_MAC(int Mod_id,int frame,int subframe, UL_IND_t *UL_INFO, uint16_t rnti); // In our case the this function will be always indicating ACK to the MAC of the eNB (i.e. always assuming) // successful decoding. @@ -50,7 +60,21 @@ void fill_crc_indication_UE_MAC(int Mod_id,int frame,int subframe, UL_IND_t *UL_ 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); -void fill_ulsch_cqi_indication(int Mod_id, uint16_t frame,uint8_t subframe, UL_IND_t *UL_INFO); +void fill_ulsch_cqi_indication_UE_MAC(int Mod_id, uint16_t frame,uint8_t subframe, UL_IND_t *UL_INFO, uint16_t rnti); + + +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); + +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 + /*uint8_t tdd_mapping_mode, + uint16_t tdd_multiplexing_mask*/); + +int ul_config_req_UE_MAC(nfapi_pnf_p7_config_t* pnf_p7, nfapi_ul_config_request_t* req); + +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); + #endif /* PHY_STUB_UE_H_ */