Files
openairinterface5g/openair2/LAYER2/PDCP_v10.1.0/pdcp_fifo.c
T

664 lines
28 KiB
C
Executable File

/*******************************************************************************
Eurecom OpenAirInterface
Copyright(c) 1999 - 2011 Eurecom
This program is free software; you can redistribute it and/or modify it
under the terms and conditions of the GNU General Public License,
version 2, as published by the Free Software Foundation.
This program is distributed in the hope it will be useful, but WITHOUT
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
more details.
You should have received a copy of the GNU General Public License along with
this program; if not, write to the Free Software Foundation, Inc.,
51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
The full GNU General Public License is included in this distribution in
the file called "COPYING".
Contact Information
Openair Admin: openair_admin@eurecom.fr
Openair Tech : openair_tech@eurecom.fr
Forums : http://forums.eurecom.fsr/openairinterface
Address : Eurecom, 2229, route des crêtes, 06560 Valbonne Sophia Antipolis, France
*******************************************************************************/
/*! \file pdcp_fifo.c
* \brief pdcp interface with linux IP interface, have a look at http://man7.org/linux/man-pages/man7/netlink.7.html for netlink
* \author Lionel GAUTHIER and Navid Nikaein
* \date 2009
* \version 0.5
* \warning This component can be runned only in user-space
* @ingroup pdcp
*/
#define PDCP_FIFO_C
#define PDCP_DEBUG 1
//#define IDROMEL_NEMO 1
#ifndef OAI_EMU
extern int otg_enabled;
#endif
#include "pdcp.h"
#include "pdcp_primitives.h"
#ifdef USER_MODE
#include <errno.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#define rtf_put write
#define rtf_get read
#else
#include <rtai_fifos.h>
#endif //USER_MODE
#include "../MAC/extern.h"
#include "RRC/L2_INTERFACE/openair_rrc_L2_interface.h"
#include "NAS/DRIVER/LITE/constant.h"
#include "SIMULATION/ETH_TRANSPORT/extern.h"
#include "UTIL/OCG/OCG.h"
#include "UTIL/OCG/OCG_extern.h"
#include "UTIL/LOG/log.h"
#include "UTIL/OTG/otg_tx.h"
#include "UTIL/FIFO/pad_list.h"
#include "platform_constants.h"
#include "assertions.h"
#ifdef NAS_NETLINK
#include <sys/socket.h>
#include <linux/netlink.h>
extern char nl_rx_buf[NL_MAX_PAYLOAD];
extern struct sockaddr_nl nas_src_addr, nas_dest_addr;
extern struct nlmsghdr *nas_nlh_tx;
extern struct nlmsghdr *nas_nlh_rx;
extern struct iovec nas_iov_tx;
extern struct iovec nas_iov_rx;
extern int nas_sock_fd;
extern struct msghdr nas_msg_tx;
extern struct msghdr nas_msg_rx;
#define MAX_PAYLOAD 1600
unsigned char pdcp_read_state = 0;
//unsigned char pdcp_read_payload[MAX_PAYLOAD];
#endif
extern Packet_OTG_List *otg_pdcp_buffer;
pdcp_data_req_header_t pdcp_read_header;
//-----------------------------------------------------------------------------
int pdcp_fifo_flush_sdus(u32_t frame, u8 eNB_flag, u8 eNB_id, u8 UE_id)
{
//-----------------------------------------------------------------------------
mem_block_t *sdu = list_get_head (&pdcp_sdu_list);
int bytes_wrote = 0;
int pdcp_nb_sdu_sent = 0;
u8 cont = 1;
int mcs_inst;
#if defined(NAS_NETLINK) && defined(LINUX)
int ret = 0;
#endif
while (sdu && cont) {
#if defined(OAI_EMU)
mcs_inst = ((pdcp_data_ind_header_t *)(sdu->data))->inst;
// asjust the instance id when passing sdu to IP
((pdcp_data_ind_header_t *)(sdu->data))->inst = (((pdcp_data_ind_header_t *)(sdu->data))->inst >= NB_eNB_INST) ?
((pdcp_data_ind_header_t *)(sdu->data))->inst - NB_eNB_INST +oai_emulation.info.nb_enb_local - oai_emulation.info.first_ue_local :// UE
((pdcp_data_ind_header_t *)(sdu->data))->inst - oai_emulation.info.first_ue_local; // ENB
#else
((pdcp_data_ind_header_t *)(sdu->data))->inst = 0;
#endif
#ifdef PDCP_DEBUG
LOG_I(PDCP, "PDCP->IP TTI %d INST %d: Preparing %d Bytes of data from rab %d to Nas_mesh\n",
frame, ((pdcp_data_ind_header_t *)(sdu->data))->inst,
((pdcp_data_ind_header_t *)(sdu->data))->data_size, ((pdcp_data_ind_header_t *)(sdu->data))->rb_id);
#endif //PDCP_DEBUG
cont = 0;
if (!pdcp_output_sdu_bytes_to_write) {
if (!pdcp_output_header_bytes_to_write) {
pdcp_output_header_bytes_to_write = sizeof (pdcp_data_ind_header_t);
}
#ifdef NAS_FIFO
bytes_wrote = rtf_put (PDCP2NAS_FIFO,
&(((u8 *) sdu->data)[sizeof (pdcp_data_ind_header_t) - pdcp_output_header_bytes_to_write]),
pdcp_output_header_bytes_to_write);
#else
#ifdef NAS_NETLINK
#ifdef LINUX
memcpy(NLMSG_DATA(nas_nlh_tx), &(((u8 *) sdu->data)[sizeof (pdcp_data_ind_header_t) - pdcp_output_header_bytes_to_write]),
pdcp_output_header_bytes_to_write);
nas_nlh_tx->nlmsg_len = pdcp_output_header_bytes_to_write;
#endif //LINUX
#endif //NAS_NETLINK
bytes_wrote = pdcp_output_header_bytes_to_write;
#endif //NAS_FIFO
#ifdef PDCP_DEBUG
LOG_I(PDCP, "Frame %d Sent %d Bytes of header to Nas_mesh\n",
frame,
bytes_wrote);
#endif //PDCP_DEBUG
if (bytes_wrote > 0) {
pdcp_output_header_bytes_to_write = pdcp_output_header_bytes_to_write - bytes_wrote;
if (!pdcp_output_header_bytes_to_write) { // continue with sdu
pdcp_output_sdu_bytes_to_write = ((pdcp_data_ind_header_t *) sdu->data)->data_size;
#ifdef NAS_FIFO
bytes_wrote = rtf_put (PDCP2NAS_FIFO, &(sdu->data[sizeof (pdcp_data_ind_header_t)]), pdcp_output_sdu_bytes_to_write);
#else
#ifdef NAS_NETLINK
#ifdef LINUX
memcpy(NLMSG_DATA(nas_nlh_tx)+sizeof(pdcp_data_ind_header_t), &(sdu->data[sizeof (pdcp_data_ind_header_t)]), pdcp_output_sdu_bytes_to_write);
nas_nlh_tx->nlmsg_len += pdcp_output_sdu_bytes_to_write;
ret = sendmsg(nas_sock_fd,&nas_msg_tx,0);
if (ret<0) {
LOG_D(PDCP, "[PDCP_FIFOS] sendmsg returns %d (errno: %d)\n", ret, errno);
mac_xface->macphy_exit("sendmsg failed for nas_sock_fd\n");
break;
}
#endif // LINUX
#endif //NAS_NETLINK
bytes_wrote= pdcp_output_sdu_bytes_to_write;
#endif // NAS_FIFO
#ifdef PDCP_DEBUG
LOG_I(PDCP, "PDCP->IP Frame %d INST %d: Sent %d Bytes of data from rab %d to Nas_mesh\n",
frame,
((pdcp_data_ind_header_t *)(sdu->data))->inst,
bytes_wrote,
((pdcp_data_ind_header_t *)(sdu->data))->rb_id);
#endif //PDCP_DEBUG
if (bytes_wrote > 0) {
pdcp_output_sdu_bytes_to_write -= bytes_wrote;
if (!pdcp_output_sdu_bytes_to_write) { // OK finish with this SDU
// LOG_D(PDCP, "rb sent a sdu qos_sap %d\n", sapiP);
LOG_D(PDCP,
"[MSC_MSG][FRAME %05d][PDCP][MOD %02d][RB %02d][--- PDCP_DATA_IND / %d Bytes --->][IP][MOD %02d][]\n",
frame,
mcs_inst, //((pdcp_data_ind_header_t *)(sdu->data))->inst,
((pdcp_data_ind_header_t *)(sdu->data))->rb_id,
((pdcp_data_ind_header_t *)(sdu->data))->data_size,
mcs_inst); //((pdcp_data_ind_header_t *)(sdu->data))->inst
list_remove_head (&pdcp_sdu_list);
free_mem_block (sdu);
cont = 1;
pdcp_nb_sdu_sent += 1;
sdu = list_get_head (&pdcp_sdu_list);
}
} else {
LOG_W(PDCP, "RADIO->IP SEND SDU CONGESTION!\n");
}
} else {
LOG_W(PDCP, "RADIO->IP SEND SDU CONGESTION!\n");
}
}
} else {
// continue writing sdu
#ifdef NAS_FIFO
bytes_wrote = rtf_put (PDCP2NAS_FIFO,
(u8 *) (&(sdu->data[sizeof (pdcp_data_ind_header_t) + ((pdcp_data_ind_header_t *) sdu->data)->data_size - pdcp_output_sdu_bytes_to_write])),
pdcp_output_sdu_bytes_to_write);
#else // NAS_FIFO
bytes_wrote = pdcp_output_sdu_bytes_to_write;
#endif // NAS_FIFO
if (bytes_wrote > 0) {
pdcp_output_sdu_bytes_to_write -= bytes_wrote;
if (!pdcp_output_sdu_bytes_to_write) { // OK finish with this SDU
//PRINT_RB_SEND_OUTPUT_SDU ("[PDCP] RADIO->IP SEND SDU\n");
list_remove_head (&pdcp_sdu_list);
free_mem_block (sdu);
cont = 1;
pdcp_nb_sdu_sent += 1;
sdu = list_get_head (&pdcp_sdu_list);
// LOG_D(PDCP, "rb sent a sdu from rab\n");
}
}
}
}
#ifdef NAS_FIFO
if ((pdcp_nb_sdu_sent)) {
if ((pdcp_2_nas_irq > 0)) {
#ifdef PDCP_DEBUG
LOG_I(PDCP, "Frame %d : Trigger NAS RX interrupt\n",
frame);
#endif //PDCP_DEBUG
rt_pend_linux_srq (pdcp_2_nas_irq);
} else {
LOG_E(PDCP, "Frame %d: ERROR IF IP STACK WANTED : NOTIF PACKET(S) pdcp_2_nas_irq not initialized : %d\n",
frame,
pdcp_2_nas_irq);
}
}
#endif //NAS_FIFO
return pdcp_nb_sdu_sent;
}
//-----------------------------------------------------------------------------
/*
* returns a positive value if whole bytes that had to be read were read
* returns zero value if whole bytes that had to be read were not read at all
* returns a negative value if an error was encountered while reading the rt fifo
*/
int pdcp_fifo_read_input_sdus_remaining_bytes (u32_t frame, u8_t eNB_flag)
{
//-----------------------------------------------------------------------------
sdu_size_t bytes_read = 0;
rb_id_t rab_id = 0;
pdcp_t *pdcp;
u8 UE_id = 0;
u8 eNB_id;
u8 rb_id;
int result;
// if remaining bytes to read
if (pdcp_input_sdu_remaining_size_to_read > 0) {
bytes_read = rtf_get (NAS2PDCP_FIFO,
&(pdcp_input_sdu_buffer[pdcp_input_sdu_size_read]),
pdcp_input_sdu_remaining_size_to_read);
if (bytes_read > 0) {
LOG_D(PDCP, "[PDCP_FIFOS] Read %d remaining bytes of data from Nas_mesh\n", bytes_read);
pdcp_input_sdu_remaining_size_to_read = pdcp_input_sdu_remaining_size_to_read - bytes_read;
pdcp_input_sdu_size_read = pdcp_input_sdu_size_read + bytes_read;
if (pdcp_input_sdu_remaining_size_to_read != 0) {
return 0;
} else {
#ifdef PDCP_DEBUG
LOG_I(PDCP, "Frame %d: IP->RADIO RECEIVED COMPLETE SDU size %d inst %d rb %d\n",
frame,
pdcp_input_sdu_size_read,
pdcp_input_header.inst,
pdcp_input_header.rb_id);
#endif //PDCP_DEBUG
pdcp_input_sdu_size_read = 0;
#ifdef IDROMEL_NEMO
pdcp_read_header.inst = 0;
#endif
if (eNB_flag == 0) {
UE_id = pdcp_read_header.inst;
rb_id = pdcp_read_header.rb_id % NB_RB_MAX;
eNB_id = 0;
DevCheck4(UE_id < NB_UE_INST, UE_id, NB_UE_INST, pdcp_read_header.rb_id, NB_RB_MAX);
DevCheck4(eNB_id < NB_eNB_INST, eNB_id, NB_eNB_INST, pdcp_read_header.rb_id, NB_RB_MAX);
pdcp = &pdcp_array_ue[UE_id][rb_id];
} else {
UE_id = pdcp_read_header.rb_id / NB_RB_MAX;
rb_id = pdcp_read_header.rb_id % NB_RB_MAX;
eNB_id = pdcp_read_header.inst;
pdcp = &pdcp_array_eNB[eNB_id][UE_id][rb_id];
}
if (pdcp_input_header.rb_id != 0) {
LOG_D(PDCP, "[MSC_MSG][FRAME %05d][IP][MOD %02d][][--- PDCP_DATA_REQ / %d Bytes --->][PDCP][MOD %02d][RB %02d]\n",
frame, pdcp_read_header.inst, pdcp_read_header.data_size, pdcp_read_header.inst, pdcp_read_header.rb_id);
if (pdcp->instanciated_instance) {
result = pdcp_data_req (eNB_id, UE_id,
frame, eNB_flag,
pdcp_input_header.rb_id,
RLC_MUI_UNDEFINED,
RLC_SDU_CONFIRM_NO,
pdcp_input_header.data_size,
pdcp_input_sdu_buffer,
PDCP_DATA_PDU);
AssertFatal (result == TRUE, "PDCP data request failed!\n");
}
} else if ((pdcp_input_header.traffic_type == OAI_NW_DRV_IPV6_ADDR_TYPE_MULTICAST) || (pdcp_input_header.traffic_type == OAI_NW_DRV_IPV4_ADDR_TYPE_MULTICAST)) {
LOG_D(PDCP, "[MSC_MSG][FRAME %05d][IP][MOD %02d][][--- PDCP_DATA_REQ on MBMS bearer/ %d Bytes --->][PDCP][MOD %02d][RB %02d]\n",
frame, pdcp_read_header.inst, pdcp_read_header.data_size, pdcp_read_header.inst, pdcp_read_header.rb_id);
if (pdcp->instanciated_instance) {
result = pdcp_data_req (eNB_id,
UE_id,
frame,
eNB_flag,
pdcp_input_header.rb_id,
RLC_MUI_UNDEFINED,
RLC_SDU_CONFIRM_NO,
pdcp_input_header.data_size,
pdcp_input_sdu_buffer,
PDCP_TM);
AssertFatal (result == TRUE, "PDCP data request failed!\n");
}
} else if (eNB_flag) {
// is a broadcast packet, we have to send this packet on all default RABS of all connected UEs
LOG_D(PDCP, "Checking if could sent on default rabs\n");
#warning CODE TO BE REVIEWED, ONLY WORK FOR SIMPLE TOPOLOGY CASES
for (rab_id = DEFAULT_RAB_ID; rab_id < MAX_RB; rab_id = rab_id + NB_RB_MAX) {
LOG_D(PDCP, "Checking if could sent on default rab id %d\n", rab_id);
if (pdcp->instanciated_instance == (pdcp_input_header.inst + 1)) {
result = pdcp_data_req (eNB_id,
UE_id,
frame, eNB_flag,
rab_id,
RLC_MUI_UNDEFINED,
RLC_SDU_CONFIRM_NO,
pdcp_input_header.data_size,
pdcp_input_sdu_buffer,
PDCP_DATA_PDU);
AssertFatal (result == TRUE, "PDCP data request failed!\n");
}
}
} else {
LOG_D(PDCP, "Forcing send on DEFAULT_RAB_ID\n");
result = pdcp_data_req (eNB_id,
UE_id,
frame, eNB_flag,
DEFAULT_RAB_ID,
RLC_MUI_UNDEFINED,
RLC_SDU_CONFIRM_NO,
pdcp_input_header.data_size,
pdcp_input_sdu_buffer,
PDCP_DATA_PDU);
AssertFatal (result == TRUE, "PDCP data request failed!\n");
}
// not necessary
//memset(pdcp_input_sdu_buffer, 0, MAX_IP_PACKET_SIZE);
return 1;
}
} else {
return bytes_read;
}
}
return 1;
}
//-----------------------------------------------------------------------------
int pdcp_fifo_read_input_sdus (u32_t frame, u8_t eNB_flag, u8_t UE_index, u8_t eNB_index)
{
#ifdef NAS_NETLINK
# if defined(ENABLE_PDCP_NETLINK_FIFO)
rb_id_t rab_id;
pdcp_t *pdcp;
struct pdcp_netlink_element_s *data = NULL;
while (pdcp_netlink_dequeue_element(eNB_flag, UE_index, eNB_index, &data) != 0) {
DevAssert(data != NULL);
if (eNB_flag == 0) {
rab_id = data->pdcp_read_header.rb_id;
pdcp = &pdcp_array_ue[UE_index][rab_id];
} else {
rab_id = data->pdcp_read_header.rb_id % NB_RAB_MAX;
UE_index = data->pdcp_read_header.rb_id / NB_RAB_MAX;
pdcp = &pdcp_array_eNB[eNB_index][UE_index][rab_id];
}
if (data->pdcp_read_header.rb_id != 0) {
if (pdcp->instanciated_instance) {
LOG_D(PDCP, "[FRAME %05d][IP][MOD %02d][][--- PDCP_DATA_REQ "
"/ %d Bytes --->][PDCP][MOD %02d][RB %02d]\n",
frame, data->pdcp_read_header.inst, data->pdcp_read_header.data_size,
data->pdcp_read_header.inst, data->pdcp_read_header.rb_id);
pdcp_data_req(eNB_index,
UE_index,
frame,
eNB_flag,
rab_id,
RLC_MUI_UNDEFINED,
RLC_SDU_CONFIRM_NO,
data->pdcp_read_header.data_size,
data->data,
PDCP_DATA_PDU);
} else {
LOG_E(PDCP, "Received packet for non-instanciated instance %u with rb_id %u, UE_index %d, eNB_flag %d\n",
data->pdcp_read_header.inst, data->pdcp_read_header.rb_id, UE_index, eNB_flag);
}
} else if (eNB_flag) {
/* rb_id = 0, thus interpreated as broadcast and transported as
* multiple unicast is a broadcast packet, we have to send this
* packet on all default RABS of all connected UEs
*/
#warning CODE TO BE REVIEWED, ONLY WORK FOR SIMPLE TOPOLOGY CASES
for (rab_id = DEFAULT_RAB_ID; rab_id < MAX_RB; rab_id = rab_id + NB_RB_MAX) {
if (pdcp->instanciated_instance) {
pdcp_data_req(eNB_index,
UE_index,
frame,
eNB_flag,
rab_id,
RLC_MUI_UNDEFINED,
RLC_SDU_CONFIRM_NO,
data->pdcp_read_header.data_size,
data->data,
PDCP_DATA_PDU);
}
}
} else {
LOG_D(PDCP, "Forcing send on DEFAULT_RAB_ID\n");
pdcp_data_req(eNB_index,
UE_index,
frame, eNB_flag,
DEFAULT_RAB_ID,
RLC_MUI_UNDEFINED,
RLC_SDU_CONFIRM_NO,
data->pdcp_read_header.data_size,
data->data,
PDCP_DATA_PDU);
}
free(data->data);
free(data);
data = NULL;
}
return 0;
# else
int len = 1;
rb_id_t rab_id = 0;
while (len > 0) {
len = recvmsg(nas_sock_fd, &nas_msg_rx, 0);
if (len<=0) {
// nothing in pdcp NAS socket
//LOG_I(PDCP, "[PDCP][NETLINK] Nothing in socket, length %d \n", len);
} else {
for (nas_nlh_rx = (struct nlmsghdr *) nl_rx_buf;
NLMSG_OK (nas_nlh_rx, len);
nas_nlh_rx = NLMSG_NEXT (nas_nlh_rx, len)) {
if (nas_nlh_rx->nlmsg_type == NLMSG_DONE) {
LOG_I(PDCP, "[PDCP][NETLINK] RX NLMSG_DONE\n");
//return;
}
if (nas_nlh_rx->nlmsg_type == NLMSG_ERROR) {
LOG_I(PDCP, "[PDCP][NETLINK] RX NLMSG_ERROR\n");
}
if (pdcp_read_state == 0) {
if (nas_nlh_rx->nlmsg_len == sizeof (pdcp_data_req_header_t) + sizeof(struct nlmsghdr)) {
pdcp_read_state = 1; //get
memcpy((void *)&pdcp_read_header, (void *)NLMSG_DATA(nas_nlh_rx), sizeof(pdcp_data_req_header_t));
LOG_I(PDCP, "[PDCP][NETLINK] RX pdcp_data_req_header_t inst %u, rb_id %u data_size %d\n", pdcp_read_header.inst, pdcp_read_header.rb_id, pdcp_read_header.data_size);
} else {
LOG_E(PDCP, "[PDCP][NETLINK] WRONG size %d should be sizeof (pdcp_data_req_header_t) + sizeof(struct nlmsghdr)\n", nas_nlh_rx->nlmsg_len);
}
} else {
pdcp_read_state = 0;
// print_active_requests()
#ifdef PDCP_DEBUG
LOG_I(PDCP, "[PDCP][NETLINK] Something in socket, length %d \n", nas_nlh_rx->nlmsg_len - sizeof(struct nlmsghdr));
#endif
//memcpy(pdcp_read_payload, (unsigned char *)NLMSG_DATA(nas_nlh_rx), nas_nlh_rx->nlmsg_len - sizeof(struct nlmsghdr));
#ifdef OAI_EMU
pdcp_read_header.inst = (pdcp_read_header.inst >= oai_emulation.info.nb_enb_local) ? \
pdcp_read_header.inst - oai_emulation.info.nb_enb_local+ NB_eNB_INST + oai_emulation.info.first_ue_local :
pdcp_read_header.inst + oai_emulation.info.first_enb_local;
#else
pdcp_read_header.inst = 0;
#endif
if (pdcp_read_header.rb_id != 0) {
if (pdcp_array[pdcp_read_header.inst][pdcp_read_header.rb_id%NB_RB_MAX].instanciated_instance) {
#ifdef PDCP_DEBUG
LOG_I(PDCP, "[PDCP][NETLINK][IP->PDCP] TTI %d, INST %d: Received socket with length %d (nlmsg_len = %d) on Rab %d \n",
frame, pdcp_read_header.inst, len, nas_nlh_rx->nlmsg_len-sizeof(struct nlmsghdr), pdcp_read_header.rb_id);
LOG_D(PDCP, "[MSC_MSG][FRAME %05d][IP][MOD %02d][][--- PDCP_DATA_REQ / %d Bytes --->][PDCP][MOD %02d][RB %02d]\n",
frame, pdcp_read_header.inst, pdcp_read_header.data_size, pdcp_read_header.inst, pdcp_read_header.rb_id);
#endif
pdcp_data_req(pdcp_read_header.inst,
frame,
eNB_flag,
pdcp_read_header.rb_id,
RLC_MUI_UNDEFINED,
RLC_SDU_CONFIRM_NO,
pdcp_read_header.data_size,
(unsigned char *)NLMSG_DATA(nas_nlh_rx),
PDCP_DATA_PDU);
} else {
LOG_E(PDCP, "Received packet for non-instanciated instance %u with rb_id %u\n",
pdcp_read_header.inst, pdcp_read_header.rb_id);
}
} else if (eNB_flag) { // rb_id =0, thus interpreated as broadcast and transported as multiple unicast
// is a broadcast packet, we have to send this packet on all default RABS of all connected UEs
#warning CODE TO BE REVIEWED, ONLY WORK FOR SIMPLE TOPOLOGY CASES
for (rab_id = DEFAULT_RAB_ID; rab_id < MAX_RB; rab_id = rab_id + NB_RB_MAX) {
if (pdcp_array[pdcp_input_header.inst][rab_id%NB_RB_MAX].instanciated_instance == (pdcp_input_header.inst + 1)) {
pdcp_data_req (pdcp_read_header.inst, frame, eNB_flag, rab_id, RLC_MUI_UNDEFINED,RLC_SDU_CONFIRM_NO,
pdcp_read_header.data_size,
(unsigned char *)NLMSG_DATA(nas_nlh_rx),
PDCP_DATA_PDU);
}
}
} else {
LOG_D(PDCP, "Forcing send on DEFAULT_RAB_ID\n");
pdcp_data_req (pdcp_read_header.inst,
frame, eNB_flag,
DEFAULT_RAB_ID,
RLC_MUI_UNDEFINED,
RLC_SDU_CONFIRM_NO,
pdcp_read_header.data_size,
(unsigned char *)NLMSG_DATA(nas_nlh_rx),
PDCP_DATA_PDU);
}
}
}
}
}
return len;
# endif
#else // neither NAS_NETLINK nor NAS_FIFO
return 0;
#endif // NAS_NETLINK
}
void pdcp_fifo_read_input_sdus_from_otg (u32_t frame, u8_t eNB_flag, u8 UE_index, u8 eNB_index) {
unsigned char *otg_pkt=NULL;
int src_id, module_id; // src for otg
int dst_id, rb_id; // dst for otg
int pkt_size=0, pkt_cnt=0;
u8 pdcp_mode, is_ue=0;
Packet_otg_elt * otg_pkt_info;
int result;
src_id = eNB_index;
// we need to add conditions to avoid transmitting data when the UE is not RRC connected.
#if defined(USER_MODE) && defined(OAI_EMU)
if (oai_emulation.info.otg_enabled ==1 ){
module_id = (eNB_flag == 1) ? eNB_index : NB_eNB_INST + UE_index ;
//rb_id = (eNB_flag == 1) ? eNB_index * MAX_NUM_RB + DTCH : (NB_eNB_INST + UE_index -1 ) * MAX_NUM_RB + DTCH ;
while ((otg_pkt_info = pkt_list_remove_head(&(otg_pdcp_buffer[module_id]))) != NULL) {
LOG_I(OTG,"Mod_id %d Frame %d Got a packet (%p), HEAD of otg_pdcp_buffer[%d] is %p and Nb elements is %d\n",
module_id,frame, otg_pkt_info, module_id, pkt_list_get_head(&(otg_pdcp_buffer[module_id])), otg_pdcp_buffer[module_id].nb_elements);
//otg_pkt_info = pkt_list_remove_head(&(otg_pdcp_buffer[module_id]));
dst_id = (otg_pkt_info->otg_pkt).dst_id;
module_id = (otg_pkt_info->otg_pkt).module_id;
rb_id = (otg_pkt_info->otg_pkt).rb_id;
is_ue = (otg_pkt_info->otg_pkt).is_ue;
pdcp_mode = (otg_pkt_info->otg_pkt).mode;
// LOG_I(PDCP,"pdcp_fifo, pdcp mode is= %d\n",pdcp_mode);
// generate traffic if the ue is rrc reconfigured state
// if (mac_get_rrc_status(module_id, eNB_flag, dst_id ) > 2 /*RRC_CONNECTED*/) { // not needed: this test is already done in update_otg_enb
otg_pkt = (u8*) (otg_pkt_info->otg_pkt).sdu_buffer;
pkt_size = (otg_pkt_info->otg_pkt).sdu_buffer_size;
if (otg_pkt != NULL) {
if (is_ue == 0 ) {
//rb_id = (/*NB_eNB_INST +*/ dst_id -1 ) * MAX_NUM_RB + DTCH;
LOG_D(OTG,"[eNB %d] Frame %d sending packet %d from module %d on rab id %d (src %d, dst %d) pkt size %d for pdcp mode %d\n",
eNB_index, frame, pkt_cnt++, module_id, rb_id, module_id, dst_id, pkt_size, pdcp_mode);
result = pdcp_data_req(eNB_index, UE_index, frame, eNB_flag, rb_id, RLC_MUI_UNDEFINED, RLC_SDU_CONFIRM_NO, pkt_size, otg_pkt,pdcp_mode);
AssertFatal (result == TRUE, "PDCP data request failed!\n");
}
else {
//rb_id= eNB_index * MAX_NUM_RB + DTCH;
LOG_D(OTG,"[UE %d] sending packet from module %d on rab id %d (src %d, dst %d) pkt size %d\n",
UE_index, src_id, rb_id, src_id, dst_id, pkt_size);
result = pdcp_data_req(eNB_index, UE_index, frame, eNB_flag, rb_id, RLC_MUI_UNDEFINED, RLC_SDU_CONFIRM_NO, pkt_size, otg_pkt, PDCP_DATA_PDU);
AssertFatal (result == TRUE, "PDCP data request failed!\n");
}
free(otg_pkt);
}
// } //else LOG_D(OTG,"frame %d enb %d-> ue %d link not yet established state %d \n", frame, eNB_index,dst_id - NB_eNB_INST, mac_get_rrc_status(module_id, eNB_flag, dst_id - NB_eNB_INST));
}
}
#else
if ((otg_enabled==1) && (eNB_flag == 1)) { // generate DL traffic
unsigned int ctime=0;
ctime = frame * 100;
/*if ((mac_get_rrc_status(eNB_index, eNB_flag, 0 ) > 2) &&
(mac_get_rrc_status(eNB_index, eNB_flag, 1 ) > 2)) { */
for (dst_id = 0; dst_id<NUMBER_OF_UE_MAX; dst_id++) {
if (mac_get_rrc_status(eNB_index, eNB_flag, dst_id ) > 2) {
otg_pkt=packet_gen(src_id, dst_id, 0, ctime, &pkt_size);
if (otg_pkt != NULL){
rb_id = dst_id * NB_RB_MAX + DTCH;
pdcp_data_req(eNB_index, dst_id, frame, eNB_flag, rb_id, RLC_MUI_UNDEFINED, RLC_SDU_CONFIRM_NO,pkt_size, otg_pkt, PDCP_DATA_PDU);
LOG_I(OTG,"send packet from module %d on rab id %d (src %d, dst %d) pkt size %d\n", eNB_index, rb_id, src_id, dst_id, pkt_size);
free(otg_pkt);
}
/*else {
LOG_I(OTG,"nothing generated (src %d, dst %d)\n",src_id, dst_id);
}*/
}
/*else {
LOG_I(OTG,"rrc_status (src %d, dst %d) = %d\n",src_id, dst_id, mac_get_rrc_status(src_id, eNB_flag, dst_id ));
}*/
}
}
#endif
}