Commit d44ccd24 authored by Cedric Roux's avatar Cedric Roux

- Update multicast:

	* Remove recv thread
	* Update logs to LOG api
	* Retransmit Initial message if master not ready
	* Assert if packets lost -> break the execution if there is a drift in slots

git-svn-id: http://svn.eurecom.fr/openair4G/trunk@4006 818b1a75-f10b-46b9-bf7c-635c3b92a50f
parent b62ae47b
/*! \file bypass_session_layer.h
* \brief implementation of emultor tx and rx
* \author Navid Nikaein and Raymond Knopp
* \date 2011
* \version 1.0
* \company Eurecom
* \email: navid.nikaein@eurecom.fr
*/
* \brief implementation of emultor tx and rx
* \author Navid Nikaein and Raymond Knopp
* \date 2011
* \version 1.0
* \company Eurecom
* \email: navid.nikaein@eurecom.fr
*/
#include "PHY/defs.h"
#include "defs.h"
#include "proto.h"
#include "extern.h"
//#include "mac_extern.h"
#include "UTIL/assertions.h"
#include "UTIL/OCG/OCG.h"
#include "UTIL/OCG/OCG_extern.h"
#include "UTIL/LOG/log.h"
......@@ -19,455 +21,523 @@
#include "multicast_link.h"
#endif
/***************************************************************************/
char rx_bufferP[BYPASS_RX_BUFFER_SIZE];
static unsigned int num_bytesP=0;
int N_P=0,N_R=0;
char bypass_tx_buffer[BYPASS_TX_BUFFER_SIZE];
unsigned int Master_list_rx, Seq_nb;
/***************************************************************************/
static unsigned int num_bytesP = 0;
int N_P = 0, N_R = 0;
char bypass_tx_buffer[BYPASS_TX_BUFFER_SIZE];
static unsigned int byte_tx_count;
unsigned int Master_list_rx;
static uint64_t seq_num_tx = 0;
mapping transport_names[] = {
{"WAIT PM TRANSPORT INFO", WAIT_PM_TRANSPORT_INFO},
{"WAIT SM TRANSPORT INFO", WAIT_SM_TRANSPORT_INFO},
{"SYNC TRANSPORT INFO", SYNC_TRANSPORT_INFO},
{"ENB_TRANSPORT INFO", ENB_TRANSPORT_INFO},
{"UE TRANSPORT INFO", UE_TRANSPORT_INFO},
{"RELEASE TRANSPORT INFO", RELEASE_TRANSPORT_INFO},
{"WAIT PM TRANSPORT INFO", EMU_TRANSPORT_INFO_WAIT_PM},
{"WAIT SM TRANSPORT INFO", EMU_TRANSPORT_INFO_WAIT_SM},
{"SYNC TRANSPORT INFO", EMU_TRANSPORT_INFO_SYNC},
{"ENB_TRANSPORT INFO", EMU_TRANSPORT_INFO_ENB},
{"UE TRANSPORT INFO", EMU_TRANSPORT_INFO_UE},
{"RELEASE TRANSPORT INFO", EMU_TRANSPORT_INFO_RELEASE},
{NULL, -1}
};
void init_bypass (void){
msg ("[PHYSIM] INIT BYPASS\n");
pthread_mutex_init (&Tx_mutex, NULL);
pthread_cond_init (&Tx_cond, NULL);
Tx_mutex_var = 1;
pthread_mutex_init (&emul_low_mutex, NULL);
pthread_cond_init (&emul_low_cond, NULL);
emul_low_mutex_var = 1;
bypass_init (emul_tx_handler, emul_rx_handler);
void init_bypass (void)
{
LOG_I(EMU, "[PHYSIM] INIT BYPASS\n");
#if !defined(ENABLE_NEW_MULTICAST)
pthread_mutex_init (&Tx_mutex, NULL);
pthread_cond_init (&Tx_cond, NULL);
Tx_mutex_var = 1;
pthread_mutex_init (&emul_low_mutex, NULL);
pthread_cond_init (&emul_low_cond, NULL);
emul_low_mutex_var = 1;
#endif
bypass_init (emul_tx_handler, emul_rx_handler);
}
/***************************************************************************/
void bypass_init ( unsigned int (*tx_handlerP) (unsigned char,char*, unsigned int*, unsigned int*),unsigned int (*rx_handlerP) (unsigned char,char*,unsigned int)){
void bypass_init (tx_handler_t tx_handlerP, rx_handler_t rx_handlerP)
{
/***************************************************************************/
#ifdef USER_MODE
multicast_link_start (bypass_rx_handler, oai_emulation.info.multicast_group, oai_emulation.info.multicast_ifname);
#if defined(USER_MODE)
multicast_link_start (bypass_rx_handler, oai_emulation.info.multicast_group,
oai_emulation.info.multicast_ifname);
#endif //USER_MODE
tx_handler = tx_handlerP;
rx_handler = rx_handlerP;
Master_list_rx=0;
emu_tx_status = WAIT_SYNC_TRANSPORT;
emu_rx_status = WAIT_SYNC_TRANSPORT;
tx_handler = tx_handlerP;
rx_handler = rx_handlerP;
Master_list_rx=0;
emu_tx_status = WAIT_SYNC_TRANSPORT;
emu_rx_status = WAIT_SYNC_TRANSPORT;
}
/***************************************************************************/
int bypass_rx_data (unsigned int frame, unsigned int last_slot, unsigned int next_slot){
/***************************************************************************/
bypass_msg_header_t *messg;
bypass_proto2multicast_header_t *bypass_read_header;
eNB_transport_info_t *eNB_info;
UE_transport_info_t *UE_info;
int ue_info_ix, enb_info_ix;
// int tmp_byte_count;
int bytes_read = 0;
int bytes_data_to_read;
// int num_flows;
// int current_flow;
int m_id, n_enb, n_ue, n_dci, total_tbs=0, total_header=0;
// printf("in bypass_rx_data ...\n");
pthread_mutex_lock(&emul_low_mutex);
if(emul_low_mutex_var){
//LOG_T(EMU, " WAIT BYPASS_PHY...\n");
pthread_cond_wait(&emul_low_cond, &emul_low_mutex);
}
if(num_bytesP==0){
//msg("[BYPASS] IDLE_WAIT\n");
//exit(0);
pthread_mutex_unlock(&emul_low_mutex);
}
else{
//LOG_T(EMU,"BYPASS_RX_DATA: IN, Num_bytesp=%d...\n",num_bytesP);
bypass_read_header = (bypass_proto2multicast_header_t *) (&rx_bufferP[bytes_read]);
bytes_read += sizeof (bypass_proto2multicast_header_t);
bytes_data_to_read = bypass_read_header->size;
if(num_bytesP!=bytes_read+bytes_data_to_read) {
LOG_W(EMU, "WARNINIG BYTES2READ # DELIVERED BYTES!!!\n");
int bypass_rx_data(unsigned int frame, unsigned int last_slot,
unsigned int next_slot, uint8_t is_master)
{
bypass_msg_header_t *messg;
bypass_proto2multicast_header_t *bypass_read_header;
eNB_transport_info_t *eNB_info;
UE_transport_info_t *UE_info;
int ue_info_ix, enb_info_ix;
int bytes_read = 0;
int bytes_data_to_read;
int m_id, n_enb, n_ue, n_dci, total_tbs = 0, total_header = 0;
LOG_D(EMU, "Entering bypass_rx for frame %d next_slot %d is_master %u\n",
frame, next_slot, is_master);
#if defined(ENABLE_NEW_MULTICAST)
if (multicast_link_read_data_from_sock(is_master) == 1) {
/* We got a timeout */
return -1;
}
#else
pthread_mutex_lock(&emul_low_mutex);
if(emul_low_mutex_var) {
pthread_cond_wait(&emul_low_cond, &emul_low_mutex);
}
else{
messg = (bypass_msg_header_t *) (&rx_bufferP[bytes_read]);
bytes_read += sizeof (bypass_msg_header_t);
if ( (messg->frame != frame) || (messg->subframe != next_slot>>1) )
LOG_W(EMU, "Received %s from master %d for (frame %d,subframe %d) currently (frame %d,subframe %d)\n",
map_int_to_str(transport_names,messg->Message_type), messg->master_id,
messg->frame, messg->subframe,
frame, next_slot>>1);
//chek if MASTER in my List
// switch(Emulation_status){
switch(messg->Message_type){
//case WAIT_SYNC_TRANSPORT:
case WAIT_PM_TRANSPORT_INFO:
if (messg->master_id==0 )
Master_list_rx=((Master_list_rx) |(1<< messg->master_id));
break;
case WAIT_SM_TRANSPORT_INFO:
Master_list_rx=((Master_list_rx) |(1<< messg->master_id));
break;
case SYNC_TRANSPORT_INFO:
// determite the total number of remote enb & ue
oai_emulation.info.nb_enb_remote += messg->nb_enb;
oai_emulation.info.nb_ue_remote += messg->nb_ue;
// determine the index of local enb and ue wrt the remote ones
if ( messg->master_id < oai_emulation.info.master_id ){
oai_emulation.info.first_enb_local +=messg->nb_enb;
oai_emulation.info.first_ue_local +=messg->nb_ue;
}
// store param for enb per master
if ((oai_emulation.info.master[messg->master_id].nb_enb = messg->nb_enb) > 0 ){
for (m_id=0;m_id < messg->master_id; m_id++ ){
oai_emulation.info.master[messg->master_id].first_enb+=oai_emulation.info.master[m_id].nb_enb;
}
LOG_I(EMU, "[ENB] WAIT_SYNC_TRANSPORT state: for master %d (first enb %d, totan enb %d)\n",
messg->master_id,
oai_emulation.info.master[messg->master_id].first_enb,
oai_emulation.info.master[messg->master_id].nb_enb);
}
// store param for ue per master
if ((oai_emulation.info.master[messg->master_id].nb_ue = messg->nb_ue) > 0){
for (m_id=0;m_id < messg->master_id; m_id++ ){
oai_emulation.info.master[messg->master_id].first_ue+=oai_emulation.info.master[m_id].nb_ue;
}
LOG_I(EMU, "[UE]WAIT_SYNC_TRANSPORT state: for master %d (first ue %d, total ue%d)\n",
messg->master_id,
oai_emulation.info.master[messg->master_id].first_ue,
oai_emulation.info.master[messg->master_id].nb_ue );
}
Master_list_rx=((Master_list_rx) |(1<< messg->master_id));
if (Master_list_rx == oai_emulation.info.master_list) {
emu_rx_status = SYNCED_TRANSPORT;
}
LOG_I(EMU,"WAIT_SYNC_TRANSPORT state: m_id %d total enb remote %d total ue remote %d \n",
messg->master_id,oai_emulation.info.nb_enb_remote, oai_emulation.info.nb_ue_remote );
break;
//case WAIT_ENB_TRANSPORT:
case ENB_TRANSPORT_INFO:
#ifdef DEBUG_EMU
LOG_D(EMU," RX ENB_TRANSPORT INFO from master %d \n",messg->master_id);
if(num_bytesP==0) {
pthread_mutex_unlock(&emul_low_mutex);
} else {
#endif
clear_eNB_transport_info(oai_emulation.info.nb_enb_local+oai_emulation.info.nb_enb_remote);
if (oai_emulation.info.master[messg->master_id].nb_enb > 0 ){
enb_info_ix =0;
total_header=0;
total_header += sizeof(eNB_transport_info_t)-MAX_TRANSPORT_BLOCKS_BUFFER_SIZE;
eNB_info = (eNB_transport_info_t *) (&rx_bufferP[bytes_read]);
for (n_enb = oai_emulation.info.master[messg->master_id].first_enb;
n_enb < oai_emulation.info.master[messg->master_id].first_enb+oai_emulation.info.master[messg->master_id].nb_enb ;
n_enb ++) {
total_tbs=0;
for (n_dci = 0 ;
n_dci < (eNB_info[enb_info_ix].num_ue_spec_dci+eNB_info[enb_info_ix].num_common_dci);
n_dci ++) {
total_tbs+=eNB_info[enb_info_ix].tbs[n_dci];
}
enb_info_ix++;
if ( (total_tbs + total_header) > MAX_TRANSPORT_BLOCKS_BUFFER_SIZE ){
LOG_W(EMU,"RX eNB Transport buffer total size %d (header%d,tbs %d) \n",
total_header+total_tbs, total_header,total_tbs);
}
memcpy (&eNB_transport_info[n_enb],eNB_info, total_header+total_tbs);
eNB_info = (eNB_transport_info_t *)((unsigned int)eNB_info + total_header+total_tbs);
bytes_read+=total_header+total_tbs;
}
for (n_enb = oai_emulation.info.master[messg->master_id].first_enb;
n_enb < oai_emulation.info.master[messg->master_id].first_enb+oai_emulation.info.master[messg->master_id].nb_enb ;
n_enb ++)
fill_phy_enb_vars(n_enb,next_slot);
}
else{
LOG_T(EMU,"WAIT_ENB_TRANSPORT state: no enb transport info from master %d \n", messg->master_id);
}
Master_list_rx=((Master_list_rx) |(1<< messg->master_id));
if (Master_list_rx == oai_emulation.info.master_list) {
emu_rx_status = SYNCED_TRANSPORT;
}
break;
case UE_TRANSPORT_INFO:
bypass_read_header = (bypass_proto2multicast_header_t *) (
&rx_bufferP[bytes_read]);
bytes_read += sizeof (bypass_proto2multicast_header_t);
bytes_data_to_read = bypass_read_header->size;
if(num_bytesP!=bytes_read+bytes_data_to_read) {
LOG_W(EMU, "WARNINIG BYTES2READ # DELIVERED BYTES!!!\n");
} else {
messg = (bypass_msg_header_t *) (&rx_bufferP[bytes_read]);
bytes_read += sizeof (bypass_msg_header_t);
#if defined(ENABLE_NEW_MULTICAST)
LOG_D(EMU, "Received %d bytes [%s] from master_id %d with seq %"PRIuMAX"\n",
num_bytesP, map_int_to_str(transport_names, messg->Message_type),
messg->master_id,
messg->seq_num);
DevCheck4((messg->frame == frame) && (messg->subframe == (next_slot>>1)),
messg->frame, frame, messg->subframe, next_slot>>1);
#else
if ((messg->frame != frame) || (messg->subframe != next_slot>>1))
LOG_W(EMU,
"Received %s from master %d for (frame %d,subframe %d) "
"currently (frame %d,subframe %d)\n",
map_int_to_str(transport_names,messg->Message_type),
messg->master_id,
messg->frame, messg->subframe,
frame, next_slot>>1);
#endif
//chek if MASTER in my List
// switch(Emulation_status){
switch(messg->Message_type) {
//case WAIT_SYNC_TRANSPORT:
case EMU_TRANSPORT_INFO_WAIT_PM:
if (messg->master_id==0 ) {
Master_list_rx=((Master_list_rx) |(1<< messg->master_id));
}
break;
case EMU_TRANSPORT_INFO_WAIT_SM:
Master_list_rx=((Master_list_rx) |(1<< messg->master_id));
break;
case EMU_TRANSPORT_INFO_SYNC:
// determite the total number of remote enb & ue
oai_emulation.info.nb_enb_remote += messg->nb_enb;
oai_emulation.info.nb_ue_remote += messg->nb_ue;
// determine the index of local enb and ue wrt the remote ones
if ( messg->master_id < oai_emulation.info.master_id ) {
oai_emulation.info.first_enb_local +=messg->nb_enb;
oai_emulation.info.first_ue_local +=messg->nb_ue;
}
// store param for enb per master
if ((oai_emulation.info.master[messg->master_id].nb_enb = messg->nb_enb) > 0 ) {
for (m_id=0; m_id < messg->master_id; m_id++ ) {
oai_emulation.info.master[messg->master_id].first_enb+=oai_emulation.info.master[m_id].nb_enb;
}
LOG_I(EMU,
"[ENB] WAIT_SYNC_TRANSPORT state: for master %d (first enb %d, totan enb %d)\n",
messg->master_id,
oai_emulation.info.master[messg->master_id].first_enb,
oai_emulation.info.master[messg->master_id].nb_enb);
}
// store param for ue per master
if ((oai_emulation.info.master[messg->master_id].nb_ue = messg->nb_ue) > 0) {
for (m_id=0; m_id < messg->master_id; m_id++ ) {
oai_emulation.info.master[messg->master_id].first_ue+=oai_emulation.info.master[m_id].nb_ue;
}
LOG_I(EMU,
"[UE]WAIT_SYNC_TRANSPORT state: for master %d (first ue %d, total ue%d)\n",
messg->master_id,
oai_emulation.info.master[messg->master_id].first_ue,
oai_emulation.info.master[messg->master_id].nb_ue );
}
Master_list_rx=((Master_list_rx) |(1<< messg->master_id));
if (Master_list_rx == oai_emulation.info.master_list) {
emu_rx_status = SYNCED_TRANSPORT;
}
LOG_I(EMU,
"WAIT_SYNC_TRANSPORT state: m_id %d total enb remote %d total ue remote %d \n",
messg->master_id,oai_emulation.info.nb_enb_remote,
oai_emulation.info.nb_ue_remote );
break;
//case WAIT_ENB_TRANSPORT:
case EMU_TRANSPORT_INFO_ENB:
#ifdef DEBUG_EMU
LOG_D(EMU," RX ENB_TRANSPORT INFO from master %d \n",messg->master_id);
#endif
clear_eNB_transport_info(oai_emulation.info.nb_enb_local+
oai_emulation.info.nb_enb_remote);
if (oai_emulation.info.master[messg->master_id].nb_enb > 0 ) {
enb_info_ix =0;
total_header=0;
total_header += sizeof(eNB_transport_info_t)-MAX_TRANSPORT_BLOCKS_BUFFER_SIZE;
eNB_info = (eNB_transport_info_t *) (&rx_bufferP[bytes_read]);
for (n_enb = oai_emulation.info.master[messg->master_id].first_enb;
n_enb < oai_emulation.info.master[messg->master_id].first_enb+
oai_emulation.info.master[messg->master_id].nb_enb ;
n_enb ++) {
total_tbs=0;
for (n_dci = 0 ;
n_dci < (eNB_info[enb_info_ix].num_ue_spec_dci+
eNB_info[enb_info_ix].num_common_dci);
n_dci ++) {
total_tbs+=eNB_info[enb_info_ix].tbs[n_dci];
}
enb_info_ix++;
if ( (total_tbs + total_header) > MAX_TRANSPORT_BLOCKS_BUFFER_SIZE ) {
LOG_W(EMU,"RX eNB Transport buffer total size %d (header%d,tbs %d) \n",
total_header+total_tbs, total_header,total_tbs);
}
memcpy (&eNB_transport_info[n_enb],eNB_info, total_header+total_tbs);
eNB_info = (eNB_transport_info_t *)((unsigned int)eNB_info + total_header+
total_tbs);
bytes_read+=total_header+total_tbs;
}
for (n_enb = oai_emulation.info.master[messg->master_id].first_enb;
n_enb < oai_emulation.info.master[messg->master_id].first_enb+
oai_emulation.info.master[messg->master_id].nb_enb ;
n_enb ++) {
fill_phy_enb_vars(n_enb, next_slot);
}
} else {
LOG_T(EMU,"WAIT_ENB_TRANSPORT state: no enb transport info from master %d \n",
messg->master_id);
}
Master_list_rx=((Master_list_rx) |(1<< messg->master_id));
if (Master_list_rx == oai_emulation.info.master_list) {
emu_rx_status = SYNCED_TRANSPORT;
}
break;
case EMU_TRANSPORT_INFO_UE:
#ifdef DEBUG_EMU
LOG_D(EMU," RX UE TRANSPORT INFO from master %d\n",messg->master_id);
#endif
clear_UE_transport_info(oai_emulation.info.nb_ue_local+oai_emulation.info.nb_ue_remote);
if (oai_emulation.info.master[messg->master_id].nb_ue > 0 ){ //&& oai_emulation.info.nb_enb_local >0 ){
// get the header first
ue_info_ix =0;
total_header=0;
total_header += sizeof(UE_transport_info_t)-MAX_TRANSPORT_BLOCKS_BUFFER_SIZE;
UE_info = (UE_transport_info_t *) (&rx_bufferP[bytes_read]);
// get the total size of the transport blocks
for (n_ue = oai_emulation.info.master[messg->master_id].first_ue;
n_ue < oai_emulation.info.master[messg->master_id].first_ue+oai_emulation.info.master[messg->master_id].nb_ue ;
n_ue ++) {
total_tbs=0;
for (n_enb = 0;n_enb < UE_info[ue_info_ix].num_eNB; n_enb ++) {
total_tbs+=UE_info[ue_info_ix].tbs[n_enb];
}
ue_info_ix++;
if (total_tbs + total_header > MAX_TRANSPORT_BLOCKS_BUFFER_SIZE ){
LOG_W(EMU,"RX [UE %d] Total size of buffer is %d (header%d,tbs %d) \n",
n_ue, total_header+total_tbs,total_header,total_tbs);
}
memcpy (&UE_transport_info[n_ue], UE_info, total_header+total_tbs);
UE_info = (UE_transport_info_t *)((unsigned int)UE_info + total_header+total_tbs);
bytes_read+=total_header+total_tbs;
}
LOG_D(EMU," RX UE TRANSPORT INFO from master %d\n",messg->master_id);
#endif
clear_UE_transport_info(oai_emulation.info.nb_ue_local+
oai_emulation.info.nb_ue_remote);
if (oai_emulation.info.master[messg->master_id].nb_ue >
0 ) { //&& oai_emulation.info.nb_enb_local >0 ){
// get the header first
ue_info_ix =0;
total_header=0;
total_header += sizeof(UE_transport_info_t)-MAX_TRANSPORT_BLOCKS_BUFFER_SIZE;
UE_info = (UE_transport_info_t *) (&rx_bufferP[bytes_read]);
// get the total size of the transport blocks
for (n_ue = oai_emulation.info.master[messg->master_id].first_ue;
n_ue < oai_emulation.info.master[messg->master_id].first_ue+
oai_emulation.info.master[messg->master_id].nb_ue ;
n_ue ++) {
total_tbs=0;
for (n_enb = 0; n_enb < UE_info[ue_info_ix].num_eNB; n_enb ++) {
total_tbs+=UE_info[ue_info_ix].tbs[n_enb];
}
ue_info_ix++;
if (total_tbs + total_header > MAX_TRANSPORT_BLOCKS_BUFFER_SIZE ) {
LOG_W(EMU,"RX [UE %d] Total size of buffer is %d (header%d,tbs %d) \n",
n_ue, total_header+total_tbs,total_header,total_tbs);
}
memcpy (&UE_transport_info[n_ue], UE_info, total_header+total_tbs);
UE_info = (UE_transport_info_t *)((unsigned int)UE_info + total_header+
total_tbs);
bytes_read+=total_header+total_tbs;
}
#ifdef DEBUG_EMU
for (n_enb=0; n_enb < UE_info[0].num_eNB; n_enb ++ )
LOG_T(EMU,"dump ue transport info rnti %x enb_id %d, harq_id %d tbs %d\n",
UE_transport_info[0].rnti[n_enb],
UE_transport_info[0].eNB_id[n_enb],
UE_transport_info[0].harq_pid[n_enb],
UE_transport_info[0].tbs[n_enb]);
#endif
for (n_ue = oai_emulation.info.master[messg->master_id].first_ue;
n_ue < oai_emulation.info.master[messg->master_id].first_ue + oai_emulation.info.master[messg->master_id].nb_ue ;
n_ue ++) {
fill_phy_ue_vars(n_ue,last_slot);
}
}
else{
LOG_T(EMU,"WAIT_UE_TRANSPORT state: no UE transport info from master %d\n", messg->master_id );
}
Master_list_rx=((Master_list_rx) |(1<< messg->master_id));
if (Master_list_rx == oai_emulation.info.master_list) {
emu_rx_status = SYNCED_TRANSPORT;
}
break;
case RELEASE_TRANSPORT_INFO :
Master_list_rx = oai_emulation.info.master_list;
LOG_E(EMU, "RX RELEASE_TRANSPORT_INFO\n");
break;
default:
msg("[MAC][BYPASS] ERROR RX UNKNOWN MESSAGE\n");
//mac_xface->macphy_exit("");
break;
}
}
num_bytesP=0;
emul_low_mutex_var=1;
//msg("[BYPASS] CALLING_SIGNAL_HIGH_MAC\n");
pthread_cond_signal(&emul_low_cond);
pthread_mutex_unlock(&emul_low_mutex);
bypass_signal_mac_phy(frame,last_slot, next_slot);
for (n_enb=0; n_enb < UE_info[0].num_eNB; n_enb ++ )
LOG_T(EMU,"dump ue transport info rnti %x enb_id %d, harq_id %d tbs %d\n",
UE_transport_info[0].rnti[n_enb],
UE_transport_info[0].eNB_id[n_enb],
UE_transport_info[0].harq_pid[n_enb],
UE_transport_info[0].tbs[n_enb]);
#endif
for (n_ue = oai_emulation.info.master[messg->master_id].first_ue;
n_ue < oai_emulation.info.master[messg->master_id].first_ue +
oai_emulation.info.master[messg->master_id].nb_ue ;
n_ue ++) {
fill_phy_ue_vars(n_ue,last_slot);
}
} else {
LOG_T(EMU,"WAIT_UE_TRANSPORT state: no UE transport info from master %d\n",
messg->master_id);
}
Master_list_rx=((Master_list_rx) |(1<< messg->master_id));
if (Master_list_rx == oai_emulation.info.master_list) {
emu_rx_status = SYNCED_TRANSPORT;
}
break;
case EMU_TRANSPORT_INFO_RELEASE :
Master_list_rx = oai_emulation.info.master_list;
LOG_E(EMU, "RX EMU_TRANSPORT_INFO_RELEASE\n");
break;
default:
LOG_E(EMU, "[MAC][BYPASS] ERROR RX UNKNOWN MESSAGE\n");
//mac_xface->macphy_exit("");
break;
}
}
num_bytesP=0;
}
#if !defined(ENABLE_NEW_MULTICAST)
emul_low_mutex_var=1;
pthread_cond_signal(&emul_low_cond);
pthread_mutex_unlock(&emul_low_mutex);
#endif
bypass_signal_mac_phy(frame,last_slot, next_slot, is_master);
#if !defined(ENABLE_NEW_MULTICAST)
}
#endif
//printf("leaving ...\n");
return bytes_read;
return bytes_read;
}
/******************************************************************************************************/
#ifndef USER_MODE
int bypass_rx_handler(unsigned int fifo, int rw){
/******************************************************************************************************/
// if(rw=='w'){
int bytes_read;
int bytes_processed=0;
int header_bytes; //, elapsed_time;
/******************************************************************************************************/
#ifndef USER_MODE
int bypass_rx_handler(unsigned int fifo, int rw)
{
/******************************************************************************************************/
int bytes_read;
int bytes_processed=0;
int header_bytes; //, elapsed_time;
//printk("[BYPASS] BYPASS_RX_HANDLER IN...\n");
header_bytes= rtf_get(fifo_bypass_phy_user2kern, rx_bufferP,sizeof(bypass_proto2multicast_header_t) );
header_bytes= rtf_get(fifo_bypass_phy_user2kern, rx_bufferP,
sizeof(bypass_proto2multicast_header_t) );
if (header_bytes> 0) {
bytes_read = rtf_get(fifo_bypass_phy_user2kern, &rx_bufferP[header_bytes],((bypass_proto2multicast_header_t *) (&rx_bufferP[0]))->size);
// printk("BYTES_READ=%d\n",bytes_read);
if (bytes_read > 0) {
num_bytesP=header_bytes+bytes_read;
emul_low_mutex_var=0;
//printk("BYPASS_PHY SIGNAL MAC_LOW...\n");
pthread_cond_signal(&emul_low_cond);
}
bytes_read = rtf_get(fifo_bypass_phy_user2kern, &rx_bufferP[header_bytes],
((bypass_proto2multicast_header_t *) (&rx_bufferP[0]))->size);
// printk("BYTES_READ=%d\n",bytes_read);
if (bytes_read > 0) {
num_bytesP=header_bytes+bytes_read;
emul_low_mutex_var=0;
//printk("BYPASS_PHY SIGNAL MAC_LOW...\n");
pthread_cond_signal(&emul_low_cond);
}
}
// }
return 0;
return 0;
}
#else //USER_MODE
/******************************************************************************************************/
void bypass_rx_handler(unsigned int Num_bytes,char *Rx_buffer){
/******************************************************************************************************/
// msg("[BYPASS] BYPASS RX_HANDLER IN ...\n");
if(Num_bytes >0){
pthread_mutex_lock(&emul_low_mutex);
while(!emul_low_mutex_var){
// msg("[BYPASS] BYPASS: WAIT MAC_LOW...\n");
pthread_cond_wait(&emul_low_cond, &emul_low_mutex);
/******************************************************************************************************/
void bypass_rx_handler(unsigned int Num_bytes,char *Rx_buffer)
{
/******************************************************************************************************/
if(Num_bytes >0) {
#if !defined(ENABLE_NEW_MULTICAST)
pthread_mutex_lock(&emul_low_mutex);
while(!emul_low_mutex_var) {
pthread_cond_wait(&emul_low_cond, &emul_low_mutex);
}
#endif
num_bytesP=Num_bytes;
memcpy(rx_bufferP, Rx_buffer, Num_bytes);
#if !defined(ENABLE_NEW_MULTICAST)
emul_low_mutex_var=0;
/* on ne peut que signaler depuis un context linux
* (rtf_handler); pas de wait, jamais!!!!!!
*/
pthread_cond_signal(&emul_low_cond);
pthread_mutex_unlock(&emul_low_mutex);
#endif
}
num_bytesP=Num_bytes;
memcpy(rx_bufferP,Rx_buffer,Num_bytes);
emul_low_mutex_var=0;
//msg("[BYPASS] RX_HANDLER SIGNAL MAC_LOW\n");
pthread_cond_signal(&emul_low_cond); //on ne peut que signaler depuis un context linux (rtf_handler); pas de wait, jamais!!!!!!
pthread_mutex_unlock(&emul_low_mutex);
}
}
#endif //USER_MODE
/******************************************************************************************************/
void bypass_signal_mac_phy(unsigned int frame, unsigned int last_slot, unsigned int next_slot){
/******************************************************************************************************/
// char tt=1;
if(Master_list_rx != oai_emulation.info.master_list){
/******************************************************************************************************/
void bypass_signal_mac_phy(unsigned int frame, unsigned int last_slot,
unsigned int next_slot, uint8_t is_master)
{
/******************************************************************************************************/
if(Master_list_rx != oai_emulation.info.master_list) {
#ifndef USER_MODE
rtf_put(fifo_mac_bypass,&tt,1); // the Rx window is still opened (Re)signal bypass_phy (emulate MAC signal)
#endif //USER_MODE
bypass_rx_data(frame,last_slot, next_slot);
}
else Master_list_rx=0;
rtf_put(fifo_mac_bypass, &tt, 1);
/* the Rx window is still opened (Re)signal bypass_phy (emulate MAC signal) */
#endif
bypass_rx_data(frame, last_slot, next_slot, is_master);
} else {
Master_list_rx=0;
}
}
#ifndef USER_MODE
/***************************************************************************/
int multicast_link_write_sock (int groupP, char *dataP, unsigned int sizeP){
int multicast_link_write_sock (int groupP, char *dataP, unsigned int sizeP)
{
/***************************************************************************/
int tx_bytes=0;
pthread_mutex_lock(&Tx_mutex);
while(!Tx_mutex_var){
//msg("[BYPASS]RG WAIT USER_SPACE FIFO SIGNAL..\n");
pthread_cond_wait(&Tx_cond,&Tx_mutex);
}
Tx_mutex_var=0;
N_P=(int)((sizeP-sizeof (bypass_proto2multicast_header_t))/1000)+2;
tx_bytes += rtf_put (fifo_bypass_phy_kern2user, &dataP[tx_bytes],sizeof (bypass_proto2multicast_header_t));
while(tx_bytes<sizeP){
if(sizeP-tx_bytes<=1000)
tx_bytes += rtf_put (fifo_bypass_phy_kern2user, &dataP[tx_bytes],sizeP-tx_bytes);
else
tx_bytes += rtf_put (fifo_bypass_phy_kern2user, &dataP[tx_bytes],1000);
}
//RG_tx_mutex_var=0;
pthread_mutex_unlock(&Tx_mutex);
return tx_bytes;
int tx_bytes=0;
pthread_mutex_lock(&Tx_mutex);
while(!Tx_mutex_var) {
pthread_cond_wait(&Tx_cond,&Tx_mutex);
}
Tx_mutex_var=0;
N_P=(int)((sizeP-sizeof (bypass_proto2multicast_header_t))/1000)+2;
tx_bytes += rtf_put (fifo_bypass_phy_kern2user, &dataP[tx_bytes],
sizeof (bypass_proto2multicast_header_t));
while(tx_bytes<sizeP) {
if(sizeP-tx_bytes<=1000) {
tx_bytes += rtf_put (fifo_bypass_phy_kern2user, &dataP[tx_bytes],
sizeP-tx_bytes);
} else {
tx_bytes += rtf_put (fifo_bypass_phy_kern2user, &dataP[tx_bytes],1000);
}
}
//RG_tx_mutex_var=0;
pthread_mutex_unlock(&Tx_mutex);
return tx_bytes;
}
#endif
/***************************************************************************/
void bypass_tx_data(char Type, unsigned int frame, unsigned int next_slot){
/***************************************************************************/
unsigned int num_flows;
bypass_msg_header_t *messg;
unsigned int byte_tx_count;
// eNB_transport_info_t *eNB_info;
int n_enb,n_ue, n_dci,total_tbs=0,total_size=0;
messg = (bypass_msg_header_t *) (&bypass_tx_buffer[sizeof (bypass_proto2multicast_header_t)]);
num_flows = 0;
messg->master_id = oai_emulation.info.master_id; //Master_id;
// messg->nb_master = oai_emulation.info.nb_master;
messg->nb_enb = oai_emulation.info.nb_enb_local; //Master_id;
messg->nb_ue = oai_emulation.info.nb_ue_local; //Master_id;
messg->nb_flow = num_flows;
messg->frame = frame;
messg->subframe = next_slot>>1;
byte_tx_count = sizeof (bypass_msg_header_t) + sizeof (bypass_proto2multicast_header_t);
if(Type==WAIT_PM_TRANSPORT){
messg->Message_type = WAIT_PM_TRANSPORT_INFO;
LOG_T(EMU,"[TX_DATA] WAIT SYNC PM TRANSPORT\n");
}
else if(Type==WAIT_SM_TRANSPORT){
messg->Message_type = WAIT_SM_TRANSPORT_INFO;
LOG_T(EMU,"[TX_DATA] WAIT SYNC SM TRANSPORT\n");
}
else if(Type==SYNC_TRANSPORT){
messg->Message_type = SYNC_TRANSPORT_INFO;
// make sure that sync messages from the masters are received in increasing order of master id
sleep(oai_emulation.info.master_id+1);
LOG_T(EMU,"[TX_DATA] SYNC TRANSPORT\n");
}
else if(Type==ENB_TRANSPORT){
LOG_D(EMU,"[TX_DATA] ENB TRANSPORT\n");
messg->Message_type = ENB_TRANSPORT_INFO;
total_size=0;
total_tbs=0;
for (n_enb=oai_emulation.info.first_enb_local;n_enb<(oai_emulation.info.first_enb_local+oai_emulation.info.nb_enb_local);n_enb++) {
total_tbs=0;
for (n_dci =0 ;
n_dci < (eNB_transport_info[n_enb].num_ue_spec_dci+ eNB_transport_info[n_enb].num_common_dci);
n_dci++) {
total_tbs +=eNB_transport_info[n_enb].tbs[n_dci];
}
if (total_tbs <= MAX_TRANSPORT_BLOCKS_BUFFER_SIZE)
total_size = sizeof(eNB_transport_info_t)+total_tbs-MAX_TRANSPORT_BLOCKS_BUFFER_SIZE;
else
LOG_E(EMU,"[eNB]running out of memory for the eNB emulation transport buffer of size %d\n", MAX_TRANSPORT_BLOCKS_BUFFER_SIZE);
memcpy(&bypass_tx_buffer[byte_tx_count], (char*)&eNB_transport_info[n_enb], total_size);
byte_tx_count +=total_size;
}
}
else if (Type == UE_TRANSPORT){
LOG_D(EMU,"[TX_DATA] UE TRANSPORT\n");
messg->Message_type = UE_TRANSPORT_INFO;
total_size=0;
total_tbs=0; // compute the actual size of transport_blocks
for (n_ue = oai_emulation.info.first_ue_local; n_ue < (oai_emulation.info.first_ue_local+oai_emulation.info.nb_ue_local);n_ue++){
for (n_enb=0;n_enb<UE_transport_info[n_ue].num_eNB;n_enb++) {
total_tbs+=UE_transport_info[n_ue].tbs[n_enb];
}
if (total_tbs <= MAX_TRANSPORT_BLOCKS_BUFFER_SIZE)
total_size = sizeof(UE_transport_info_t)+total_tbs-MAX_TRANSPORT_BLOCKS_BUFFER_SIZE;
else
LOG_E(EMU,"[UE]running out of memory for the UE emulation transport buffer of size %d\n", MAX_TRANSPORT_BLOCKS_BUFFER_SIZE);
memcpy(&bypass_tx_buffer[byte_tx_count], (char*)&UE_transport_info[n_ue], total_size);
byte_tx_count +=total_size;
void bypass_tx_data(emu_transport_info_t Type, unsigned int frame, unsigned int next_slot)
{
/***************************************************************************/
unsigned int num_flows;
bypass_msg_header_t *messg;
LOG_D(EMU, "Entering bypass_tx [%s] for frame %d next_slot %d\n",
map_int_to_str(transport_names, Type), frame, next_slot);
int n_enb,n_ue, n_dci,total_tbs=0,total_size=0;
messg = (bypass_msg_header_t *) (
&bypass_tx_buffer[sizeof (bypass_proto2multicast_header_t)]);
num_flows = 0;
messg->master_id = oai_emulation.info.master_id; //Master_id;
messg->nb_enb = oai_emulation.info.nb_enb_local; //Master_id;
messg->nb_ue = oai_emulation.info.nb_ue_local; //Master_id;
messg->nb_flow = num_flows;
messg->frame = frame;
messg->subframe = next_slot>>1;
messg->seq_num = seq_num_tx;
seq_num_tx++;
byte_tx_count = sizeof (bypass_msg_header_t) + sizeof (
bypass_proto2multicast_header_t);
if (Type == WAIT_PM_TRANSPORT) {
messg->Message_type = EMU_TRANSPORT_INFO_WAIT_PM;
LOG_T(EMU,"[TX_DATA] WAIT SYNC PM TRANSPORT\n");
} else if (Type == WAIT_SM_TRANSPORT) {
messg->Message_type = EMU_TRANSPORT_INFO_WAIT_SM;
LOG_T(EMU,"[TX_DATA] WAIT SYNC SM TRANSPORT\n");
} else if (Type == SYNC_TRANSPORT) {
messg->Message_type = EMU_TRANSPORT_INFO_SYNC;
/* make sure that sync messages from the masters are received in
* increasing order of master id
*/
sleep(oai_emulation.info.master_id+1);
LOG_T(EMU,"[TX_DATA] SYNC TRANSPORT\n");
} else if(Type==ENB_TRANSPORT) {
LOG_D(EMU,"[TX_DATA] ENB TRANSPORT\n");
messg->Message_type = EMU_TRANSPORT_INFO_ENB;
total_size=0;
total_tbs=0;
for (n_enb=oai_emulation.info.first_enb_local;
n_enb<(oai_emulation.info.first_enb_local+oai_emulation.info.nb_enb_local);
n_enb++) {
total_tbs=0;
for (n_dci =0 ;
n_dci < (eNB_transport_info[n_enb].num_ue_spec_dci+
eNB_transport_info[n_enb].num_common_dci);
n_dci++) {
total_tbs +=eNB_transport_info[n_enb].tbs[n_dci];
}
if (total_tbs <= MAX_TRANSPORT_BLOCKS_BUFFER_SIZE) {
total_size = sizeof(eNB_transport_info_t)+total_tbs-
MAX_TRANSPORT_BLOCKS_BUFFER_SIZE;
} else {
LOG_E(EMU,
"[eNB]running out of memory for the eNB emulation transport buffer of size %d\n",
MAX_TRANSPORT_BLOCKS_BUFFER_SIZE);
}
memcpy(&bypass_tx_buffer[byte_tx_count], (char *)&eNB_transport_info[n_enb],
total_size);
byte_tx_count +=total_size;
}
} else if (Type == UE_TRANSPORT) {
LOG_D(EMU,"[TX_DATA] UE TRANSPORT\n");
messg->Message_type = EMU_TRANSPORT_INFO_UE;
total_size=0;
total_tbs=0; // compute the actual size of transport_blocks
for (n_ue = oai_emulation.info.first_ue_local;
n_ue < (oai_emulation.info.first_ue_local+oai_emulation.info.nb_ue_local);
n_ue++) {
for (n_enb=0; n_enb<UE_transport_info[n_ue].num_eNB; n_enb++) {
total_tbs+=UE_transport_info[n_ue].tbs[n_enb];
}
if (total_tbs <= MAX_TRANSPORT_BLOCKS_BUFFER_SIZE) {
total_size = sizeof(UE_transport_info_t)+total_tbs-
MAX_TRANSPORT_BLOCKS_BUFFER_SIZE;
} else {
LOG_E(EMU,
"[UE]running out of memory for the UE emulation transport buffer of size %d\n",
MAX_TRANSPORT_BLOCKS_BUFFER_SIZE);
}
memcpy(&bypass_tx_buffer[byte_tx_count], (char *)&UE_transport_info[n_ue],
total_size);
byte_tx_count +=total_size;
}
} else if (Type == RELEASE_TRANSPORT) {
messg->Message_type = EMU_TRANSPORT_INFO_RELEASE;
} else {
LOG_E(EMU,"[TX_DATA] UNKNOWN MSG \n");
}
}
else if (Type == RELEASE_TRANSPORT){
messg->Message_type = RELEASE_TRANSPORT_INFO;
}else {
LOG_T(EMU,"[TX_DATA] UNKNOWN MSG \n");
}
((bypass_proto2multicast_header_t *) bypass_tx_buffer)->size = byte_tx_count - sizeof (bypass_proto2multicast_header_t);
//if(mac_xface->frame%1000==0)
multicast_link_write_sock (oai_emulation.info.multicast_group, bypass_tx_buffer, byte_tx_count);
((bypass_proto2multicast_header_t *) bypass_tx_buffer)->size = byte_tx_count -
sizeof (bypass_proto2multicast_header_t);
multicast_link_write_sock (oai_emulation.info.multicast_group,
bypass_tx_buffer, byte_tx_count);
LOG_D(EMU, "Sent %d bytes [%s] with master_id %d and seq %"PRIuMAX"\n",
byte_tx_count, map_int_to_str(transport_names, Type),
messg->master_id, messg->seq_num);
}
#ifndef USER_MODE
#ifndef USER_MODE
/*********************************************************************************************************************/
int bypass_tx_handler(unsigned int fifo, int rw){
/***************************************************************************/
// if(rw=='r'){
if(++N_R==N_P){
//msg("[OPENAIR][RG_BYPASS] TX_handler..\n");
// pthread_mutex_lock(&RG_tx_mutex);
rtf_reset(fifo_bypass_phy_kern2user);
// pthread_mutex_lock(&RG_tx_mutex);
Tx_mutex_var=1;
N_R=0;
// pthread_mutex_unlock(&RG_tx_mutex);
pthread_cond_signal(&Tx_cond);
int bypass_tx_handler(unsigned int fifo, int rw)
{
/***************************************************************************/
if(++N_R==N_P) {
rtf_reset(fifo_bypass_phy_kern2user);
Tx_mutex_var=1;
N_R=0;
pthread_cond_signal(&Tx_cond);
}
// }
}
#endif
/*! \file phy_emulation.h
* \brief specifies the data structure and variable for phy emulation
* \author Navid Nikaein, Raymomd Knopp and Hicham Anouar
* \date 2011
* \version 1.0
* \company Eurecom
* \email: navid.nikaein@eurecom.fr
*/
//#include "SCHED/defs.h"
#include "proto.h"
//#include "UTIL/OCG/OCG.h"
* \brief specifies the data structure and variable for phy emulation
* \author Navid Nikaein, Raymomd Knopp and Hicham Anouar
* \date 2011
* \version 1.1
* \company Eurecom
* \email: navid.nikaein@eurecom.fr
*/
#ifndef __BYPASS_SESSION_LAYER_DEFS_H__
# define __BYPASS_SESSION_LAYER_DEFS_H__
//-----------------------------------------------------------------------------
//#include "openair_defs.h"
#define WAIT_PM_TRANSPORT_INFO 0x1
#define WAIT_SM_TRANSPORT_INFO 0x2
#define SYNC_TRANSPORT_INFO 0x3
#define ENB_TRANSPORT_INFO 0X4
#define UE_TRANSPORT_INFO 0X5
#define RELEASE_TRANSPORT_INFO 0x6
typedef enum {
EMU_TRANSPORT_INFO_ERROR = 0x0,
EMU_TRANSPORT_INFO_WAIT_PM,
EMU_TRANSPORT_INFO_WAIT_SM,
EMU_TRANSPORT_INFO_SYNC,
EMU_TRANSPORT_INFO_ENB,
EMU_TRANSPORT_INFO_UE,
EMU_TRANSPORT_INFO_RELEASE
} emu_transport_info_t;
#define WAIT_PM_TRANSPORT 1
#define WAIT_SM_TRANSPORT 2
......@@ -41,10 +38,11 @@
#define BYPASS_RX_BUFFER_SIZE 64000
#define BYPASS_TX_BUFFER_SIZE 64000
typedef unsigned int (*tx_handler_t) (unsigned char, char*, unsigned int*, unsigned int*);
typedef unsigned int (*rx_handler_t) (unsigned char, char*, unsigned int);
/*************************************************************/
typedef struct {
u32 pbch_flag:1;
u32 pss:2;
......@@ -71,8 +69,10 @@ typedef struct {
u8 prach_flag:1; // 0=none,1=active
u8 prach_id:6; // this is the PHY preamble index for the prach
} UE_cntl;
#define MAX_TRANSPORT_BLOCKS_BUFFER_SIZE 16384
#define MAX_NUM_DCI 5
typedef struct {
eNB_cntl cntl;
u8 num_common_dci;
......@@ -85,15 +85,6 @@ typedef struct {
u8 transport_blocks[MAX_TRANSPORT_BLOCKS_BUFFER_SIZE];
} __attribute__ ((__packed__)) eNB_transport_info_t ;
/*typedef struct {
eNB_cntl cntl;
u8 num_common_dci;
u8 num_ue_spec_dci;
DCI_ALLOC_t dci_alloc;
u8 dlsch_info[6*MAX_NUM_DCI + MAX_TRANSPORT_BLOCKS_BUFFER_SIZE];
} eNB_transport_info_rx_t ;
*/
typedef struct {
UE_cntl cntl;
u8 num_eNB;
......@@ -113,54 +104,12 @@ typedef struct bypass_msg_header {
unsigned int nb_ue; /*! \brief */
unsigned int nb_flow; /*! \brief */
unsigned int frame;
unsigned int subframe;
unsigned int subframe;
uint64_t seq_num;
}__attribute__ ((__packed__)) bypass_msg_header_t;
typedef struct bypass_proto2multicast_header_t {
unsigned int size;
} bypass_proto2multicast_header_t;
/* // replaced to OCG.h
#define NUMBER_OF_MASTER_MAX 20
//#define NUMBER_OF_UE_MAX 32
typedef struct {
unsigned char nb_ue;
unsigned char first_ue;
unsigned char nb_enb;
unsigned char first_enb;
}master_info_t;
typedef struct {
master_info_t master[NUMBER_OF_MASTER_MAX];
unsigned char nb_ue_local;
unsigned char nb_ue_remote;
unsigned char nb_enb_local;
unsigned char nb_enb_remote;
unsigned char first_enb_local;
unsigned char first_ue_local;
unsigned short master_id;
unsigned char nb_master;
unsigned int master_list;
unsigned int is_primary_master;
unsigned int ethernet_flag;
char local_server[128]; // for the oaisim -c option : 0 = EURECOM web portal; -1 = local; 1 - N or filename = running a specific XML configuration file
unsigned int offset_ue_inst;
unsigned char multicast_group;
unsigned char ocg_enabled;
unsigned char opt_enabled;
unsigned char otg_enabled;
unsigned char omg_model_enb;
unsigned char omg_model_ue;
unsigned int seed;
double time;
}emu_info_t;
*/
#endif //
#endif /* __BYPASS_SESSION_LAYER_DEFS_H__ */
/*! \file phy_emulation.c
* \brief implements the underlying protocol for emulated data exchange over Ethernet using IP multicast
* \author Navid Nikaein
* \date 2011
* \version 1.0
* \company Eurecom
* \email: navid.nikaein@eurecom.fr
*/
* \brief implements the underlying protocol for emulated data exchange over Ethernet using IP multicast
* \author Navid Nikaein
* \date 2011
* \version 1.1
* \company Eurecom
* \email: navid.nikaein@eurecom.fr
*/
#include "PHY/defs.h"
#include "PHY/extern.h"
#include "defs.h"
#include "extern.h"
#include "proto.h"
#include "UTIL/OCG/OCG.h"
#include "UTIL/OCG/OCG_extern.h"
#include "UTIL/LOG/log.h"
#include "UTIL/LOG/vcd_signal_dumper.h"
extern unsigned int Master_list_rx;
//extern unsigned short NODE_ID[1];
extern unsigned char NB_INST;
extern unsigned int Master_list_rx;
extern unsigned char NB_INST;
//#define DEBUG_CONTROL 1
//#define DEBUG_EMU 1
/*
char is_node_local_neighbor(unsigned short Node_id){
int i;
for(i=0;i<NB_INST;i++)
if(NODE_ID[i]==Node_id) return 1;
return 0;
}
*/
void emu_transport_sync(void){
if (oai_emulation.info.is_primary_master==0){
bypass_tx_data(WAIT_SM_TRANSPORT,0,0);
Master_list_rx=oai_emulation.info.master_list-1; // just wait to recieve the master 0 msg
bypass_rx_data(0,0,0);
}
else {
bypass_rx_data(0,0,0);
bypass_tx_data(WAIT_PM_TRANSPORT,0,0);
}
void emu_transport_sync(void)
{
LOG_D(EMU, "Entering EMU transport SYNC is primary master %d\n",
oai_emulation.info.is_primary_master);
if (oai_emulation.info.is_primary_master == 0) {
retry:
bypass_tx_data(WAIT_SM_TRANSPORT,0,0);
// just wait to recieve the master 0 msg
Master_list_rx = oai_emulation.info.master_list - 1;
if (bypass_rx_data(0,0,0,1) == -1) {
/* In case the master is not ready at time we send the first message */
sleep(1);
goto retry;
}
} else {
bypass_rx_data(0,0,0,0);
bypass_tx_data(WAIT_PM_TRANSPORT,0,0);
}
if (oai_emulation.info.master_list!=0){
if (oai_emulation.info.master_list!=0) {
retry2:
bypass_tx_data(SYNC_TRANSPORT,0,0);
if (bypass_rx_data(0,0,0,0) == -1) {
goto retry2;
}
bypass_tx_data(SYNC_TRANSPORT,0,0);
bypass_rx_data(0,0,0);
// i received the sync from all secondary masters
if (emu_rx_status == SYNCED_TRANSPORT) {
emu_tx_status = SYNCED_TRANSPORT;
}
if (emu_rx_status == SYNCED_TRANSPORT){ // i received the sync from all secondary masters
emu_tx_status = SYNCED_TRANSPORT;
LOG_D(EMU,"TX secondary master SYNC_TRANSPORT state \n");
}
// else emu_transport_sync(last_slot);
LOG_D(EMU,"TX secondary master SYNC_TRANSPORT state \n");
}
LOG_D(EMU, "Leaving EMU transport SYNC is primary master %d\n",
oai_emulation.info.is_primary_master);
}
void emu_transport(unsigned int frame, unsigned int last_slot, unsigned int next_slot,lte_subframe_t direction, unsigned char frame_type, int ethernet_flag ){
if (ethernet_flag == 0)
return;
vcd_signal_dumper_dump_function_by_name(VCD_SIGNAL_DUMPER_FUNCTIONS_EMU_TRANSPORT, VCD_FUNCTION_IN);
if ((frame_type == 1) && (direction == SF_S)){
if (next_slot%2==0)
emu_transport_DL(frame, last_slot,next_slot);
else
emu_transport_UL(frame, last_slot , next_slot);
//DL
}else {
if (next_slot%2 == 0 )
if ( ((frame_type == 1) && (direction == SF_DL )) || (frame_type == 0) ){
emu_transport_DL(frame, last_slot,next_slot);
void emu_transport(unsigned int frame, unsigned int last_slot,
unsigned int next_slot,lte_subframe_t direction,
unsigned char frame_type,
int ethernet_flag )
{
if (ethernet_flag == 0) {
return;
}
// UL
if ( ((frame_type == 1) && (direction == SF_UL)) || (frame_type == 0) ){
emu_transport_UL(frame, last_slot , next_slot);
vcd_signal_dumper_dump_function_by_name(
VCD_SIGNAL_DUMPER_FUNCTIONS_EMU_TRANSPORT, VCD_FUNCTION_IN);
if ((frame_type == 1) && (direction == SF_S)) {
if (next_slot%2==0) {
emu_transport_DL(frame, last_slot,next_slot);
} else {
emu_transport_UL(frame, last_slot , next_slot);
}
//DL
} else {
if (next_slot%2 == 0 )
if ( ((frame_type == 1) && (direction == SF_DL )) || (frame_type == 0) ) {
emu_transport_DL(frame, last_slot,next_slot);
}
// UL
if ( ((frame_type == 1) && (direction == SF_UL)) || (frame_type == 0) ) {
emu_transport_UL(frame, last_slot , next_slot);
}
}
}
vcd_signal_dumper_dump_function_by_name(VCD_SIGNAL_DUMPER_FUNCTIONS_EMU_TRANSPORT, VCD_FUNCTION_OUT);
vcd_signal_dumper_dump_function_by_name(
VCD_SIGNAL_DUMPER_FUNCTIONS_EMU_TRANSPORT, VCD_FUNCTION_OUT);
}
void emu_transport_DL(unsigned int frame, unsigned int last_slot, unsigned int next_slot) {
void emu_transport_DL(unsigned int frame, unsigned int last_slot,
unsigned int next_slot)
{
LOG_D(EMU, "Entering EMU transport DL, is primary master %d\n",
oai_emulation.info.is_primary_master);
if (oai_emulation.info.is_primary_master==0) {
// bypass_rx_data(last_slot);
if (oai_emulation.info.nb_enb_local>0) { // send in DL if
bypass_tx_data(ENB_TRANSPORT,frame, next_slot);
bypass_rx_data(frame, last_slot, next_slot, 1);
} else {
bypass_tx_data(WAIT_SM_TRANSPORT,frame,next_slot);
bypass_rx_data(frame, last_slot, next_slot, 0);
}
} else { // I am the master
// bypass_tx_data(WAIT_TRANSPORT,last_slot);
if (oai_emulation.info.nb_enb_local>0) { // send in DL if
bypass_tx_data(ENB_TRANSPORT,frame, next_slot);
bypass_rx_data(frame,last_slot, next_slot, 1);
} else {
bypass_tx_data(WAIT_SM_TRANSPORT,frame, next_slot);
bypass_rx_data(frame,last_slot, next_slot, 0);
}
}
LOG_D(EMU, "Leaving EMU transport DL, is primary master %d\n",
oai_emulation.info.is_primary_master);
}
if (oai_emulation.info.is_primary_master==0){
// bypass_rx_data(last_slot);
if (oai_emulation.info.nb_enb_local>0) // send in DL if
bypass_tx_data(ENB_TRANSPORT,frame, next_slot);
else
bypass_tx_data(WAIT_SM_TRANSPORT,frame,next_slot);
void emu_transport_UL(unsigned int frame, unsigned int last_slot,
unsigned int next_slot)
{
LOG_D(EMU, "Entering EMU transport UL, is primary master %d\n",
oai_emulation.info.is_primary_master);
if (oai_emulation.info.is_primary_master==0) {
// bypass_rx_data(last_slot, next_slot);
if (oai_emulation.info.nb_ue_local>0) {
bypass_tx_data(UE_TRANSPORT, frame, next_slot);
bypass_rx_data(frame,last_slot, next_slot, 1);
} else {
bypass_tx_data(WAIT_SM_TRANSPORT, frame, next_slot);
bypass_rx_data(frame,last_slot, next_slot, 0);
}
} else {
// bypass_tx_data(WAIT_TRANSPORT,last_slot);
if (oai_emulation.info.nb_ue_local>0) {
bypass_tx_data(UE_TRANSPORT,frame, next_slot);
bypass_rx_data(frame,last_slot, next_slot, 1);
} else {
bypass_tx_data(WAIT_SM_TRANSPORT,frame, next_slot);
bypass_rx_data(frame,last_slot, next_slot, 0);
}
}
LOG_D(EMU, "Leaving EMU transport UL, is primary master %d\n",
oai_emulation.info.is_primary_master);
}
bypass_rx_data(frame, last_slot, next_slot);
}
else { // I am the master
// bypass_tx_data(WAIT_TRANSPORT,last_slot);
if (oai_emulation.info.nb_enb_local>0) // send in DL if
bypass_tx_data(ENB_TRANSPORT,frame, next_slot);
else
bypass_tx_data(WAIT_SM_TRANSPORT,frame, next_slot);
void emu_transport_release(void)
{
bypass_tx_data(RELEASE_TRANSPORT,0,0);
LOG_E(EMU," tx RELEASE_TRANSPORT \n");
}
bypass_rx_data(frame,last_slot, next_slot);
}
unsigned int emul_tx_handler(unsigned char Mode,char *Tx_buffer,
unsigned int *Nbytes,unsigned int *Nb_flows)
{
return *Nbytes;
}
void emu_transport_UL(unsigned int frame, unsigned int last_slot, unsigned int next_slot) {
if (oai_emulation.info.is_primary_master==0){
// bypass_rx_data(last_slot, next_slot);
if (oai_emulation.info.nb_ue_local>0)
bypass_tx_data(UE_TRANSPORT,frame, next_slot);
else
bypass_tx_data(WAIT_SM_TRANSPORT,frame, next_slot);
bypass_rx_data(frame,last_slot, next_slot);
}
else {
// bypass_tx_data(WAIT_TRANSPORT,last_slot);
if (oai_emulation.info.nb_ue_local>0)
bypass_tx_data(UE_TRANSPORT,frame, next_slot);
else
bypass_tx_data(WAIT_SM_TRANSPORT,frame, next_slot);
bypass_rx_data(frame,last_slot, next_slot);
}
unsigned int emul_rx_data(void)
{
return(0);
}
void emu_transport_release(void){
bypass_tx_data(RELEASE_TRANSPORT,0,0);
LOG_E(EMU," tx RELEASE_TRANSPORT \n");
}
unsigned int emul_tx_handler(unsigned char Mode,char *Tx_buffer,unsigned int* Nbytes,unsigned int *Nb_flows){
unsigned short k,Mod_id;
for(k=0;k<NB_INST;k++){//Nb_out_src[Mode];k++){
Mod_id=k;//Out_list[Mode][k];
}
return *Nbytes;
unsigned int emul_rx_handler(unsigned char Mode,char *rx_buffer,
unsigned int Nbytes)
{
unsigned short Rx_size=0;
return (Rx_size+2);
}
unsigned int emul_rx_data(void){
return(0);
}
void clear_eNB_transport_info(u8 nb_eNB)
{
u8 eNB_id;
unsigned int emul_rx_handler(unsigned char Mode,char *rx_buffer, unsigned int Nbytes){
unsigned short Rx_size=0;
return (Rx_size+2);
for (eNB_id=0; eNB_id<nb_eNB; eNB_id++) {
eNB_transport_info_TB_index[eNB_id]=0;
memset((void *)&eNB_transport_info[eNB_id].cntl,0,sizeof(eNB_cntl));
eNB_transport_info[eNB_id].num_common_dci=0;
eNB_transport_info[eNB_id].num_ue_spec_dci=0;
}
// LOG_T(EMU, "EMUL clear_eNB_transport_info\n");
}
void clear_eNB_transport_info(u8 nb_eNB) {
u8 eNB_id;
for (eNB_id=0;eNB_id<nb_eNB;eNB_id++) {
eNB_transport_info_TB_index[eNB_id]=0;
memset((void *)&eNB_transport_info[eNB_id].cntl,0,sizeof(eNB_cntl));
eNB_transport_info[eNB_id].num_common_dci=0;
eNB_transport_info[eNB_id].num_ue_spec_dci=0;
}
// LOG_T(EMU, "EMUL clear_eNB_transport_info\n");
}
void clear_UE_transport_info(u8 nb_UE)
{
u8 UE_id;
void clear_UE_transport_info(u8 nb_UE) {
u8 UE_id;
for (UE_id=0;UE_id<nb_UE;UE_id++) {
UE_transport_info_TB_index[UE_id]=0;
memset((void *)&UE_transport_info[UE_id].cntl,0,sizeof(UE_cntl));
}
// LOG_T(EMU, "EMUL clear_UE_transport_info\n");
for (UE_id=0; UE_id<nb_UE; UE_id++) {
UE_transport_info_TB_index[UE_id]=0;
memset((void *)&UE_transport_info[UE_id].cntl,0,sizeof(UE_cntl));
}
// LOG_T(EMU, "EMUL clear_UE_transport_info\n");
}
void fill_phy_enb_vars(unsigned int enb_id, unsigned int next_slot)
{
int n_dci = 0, n_dci_dl;
int payload_offset = 0;
unsigned int harq_pid;
LTE_eNB_DLSCH_t *dlsch_eNB;
unsigned short ue_id;
u8 nb_total_dci;
void fill_phy_enb_vars(unsigned int enb_id, unsigned int next_slot) {
int n_dci=0, n_dci_dl;
int payload_offset = 0;
unsigned int harq_pid;
LTE_eNB_DLSCH_t *dlsch_eNB;
unsigned short ue_id;
u8 nb_total_dci;
#ifdef DEBUG_EMU
LOG_D(EMU," pbch fill phy eNB %d vars for slot %d \n",enb_id, next_slot);
#endif
// eNB
// PBCH : copy payload
//if (next_slot == 2){
*(u32*)PHY_vars_eNB_g[enb_id]->pbch_pdu = eNB_transport_info[enb_id].cntl.pbch_payload;
/* LOG_I(EMU," RX slot %d ENB TRANSPORT pbch payload %d pdu[0] %d pdu[0] %d \n",
next_slot ,
eNB_transport_info[enb_id].cntl.pbch_payload,
((u8*)PHY_vars_eNB_g[enb_id]->pbch_pdu)[0],
((u8*)PHY_vars_eNB_g[enb_id]->pbch_pdu)[1]);
LOG_D(EMU, " pbch fill phy eNB %d vars for slot %d fault %d\n",
enb_id, next_slot, network_fault);
#endif
// eNB
// PBCH : copy payload
*(u32 *)PHY_vars_eNB_g[enb_id]->pbch_pdu =
eNB_transport_info[enb_id].cntl.pbch_payload;
/* LOG_I(EMU," RX slot %d ENB TRANSPORT pbch payload %d pdu[0] %d pdu[0] %d \n",
next_slot ,
eNB_transport_info[enb_id].cntl.pbch_payload,
((u8*)PHY_vars_eNB_g[enb_id]->pbch_pdu)[0],
((u8*)PHY_vars_eNB_g[enb_id]->pbch_pdu)[1]);
*/
// }
//CFI
// not needed yet
//PHICH
// to be added later
//DCI
nb_total_dci= eNB_transport_info[enb_id].num_ue_spec_dci+ eNB_transport_info[enb_id].num_common_dci;
PHY_vars_eNB_g[enb_id]->num_ue_spec_dci[(next_slot>>1)&1] = eNB_transport_info[enb_id].num_ue_spec_dci;
PHY_vars_eNB_g[enb_id]->num_common_dci[(next_slot>>1)&1] = eNB_transport_info[enb_id].num_common_dci;
if (nb_total_dci >0) {
memcpy(PHY_vars_eNB_g[enb_id]->dci_alloc[(next_slot>>1)&1],
&eNB_transport_info[enb_id].dci_alloc,
(nb_total_dci)* sizeof(DCI_ALLOC_t));
n_dci_dl=0;
// fill dlsch_eNB structure from DCI
for (n_dci =0 ;
n_dci < nb_total_dci;
n_dci++) {
if (eNB_transport_info[enb_id].dci_alloc[n_dci_dl].format > 0){ //exclude ul dci
#ifdef DEBUG_EMU
LOG_D(EMU, "dci spec %d common %d tbs is %d payload offset %d\n",
eNB_transport_info[enb_id].num_ue_spec_dci,
eNB_transport_info[enb_id].num_common_dci,
eNB_transport_info[enb_id].tbs[n_dci_dl],
payload_offset);
#endif
switch (eNB_transport_info[enb_id].dlsch_type[n_dci_dl]) {
case 0: //SI:
memcpy(PHY_vars_eNB_g[enb_id]->dlsch_eNB_SI->harq_processes[0]->b,
&eNB_transport_info[enb_id].transport_blocks[payload_offset],
eNB_transport_info[enb_id].tbs[n_dci_dl]);
//CFI
// not needed yet
//PHICH
// to be added later
//DCI
nb_total_dci= eNB_transport_info[enb_id].num_ue_spec_dci+
eNB_transport_info[enb_id].num_common_dci;
PHY_vars_eNB_g[enb_id]->num_ue_spec_dci[(next_slot>>1)&1] =
eNB_transport_info[enb_id].num_ue_spec_dci;
PHY_vars_eNB_g[enb_id]->num_common_dci[(next_slot>>1)&1] =
eNB_transport_info[enb_id].num_common_dci;
if (nb_total_dci >0) {
memcpy(PHY_vars_eNB_g[enb_id]->dci_alloc[(next_slot>>1)&1],
&eNB_transport_info[enb_id].dci_alloc,
(nb_total_dci)* sizeof(DCI_ALLOC_t));
n_dci_dl=0;
// fill dlsch_eNB structure from DCI
for (n_dci = 0; n_dci < nb_total_dci; n_dci++) {
//exclude ul dci
if (eNB_transport_info[enb_id].dci_alloc[n_dci_dl].format > 0) {
#ifdef DEBUG_EMU
LOG_D(EMU, "SI eNB_transport_info[enb_id].tbs[n_dci_dl]%d \n", eNB_transport_info[enb_id].tbs[n_dci_dl]);
LOG_D(EMU, "dci spec %d common %d tbs is %d payload offset %d\n",
eNB_transport_info[enb_id].num_ue_spec_dci,
eNB_transport_info[enb_id].num_common_dci,
eNB_transport_info[enb_id].tbs[n_dci_dl],
payload_offset);
#endif
break;
case 1: //RA:
memcpy(PHY_vars_eNB_g[enb_id]->dlsch_eNB_ra->harq_processes[0]->b,
&eNB_transport_info[enb_id].transport_blocks[payload_offset],
eNB_transport_info[enb_id].tbs[n_dci_dl]);
switch (eNB_transport_info[enb_id].dlsch_type[n_dci_dl]) {
case 0: //SI:
memcpy(PHY_vars_eNB_g[enb_id]->dlsch_eNB_SI->harq_processes[0]->b,
&eNB_transport_info[enb_id].transport_blocks[payload_offset],
eNB_transport_info[enb_id].tbs[n_dci_dl]);
#ifdef DEBUG_EMU
LOG_D(EMU, "RA eNB_transport_info[enb_id].tbs[n_dci_dl]%d \n", eNB_transport_info[enb_id].tbs[n_dci_dl]);
LOG_D(EMU, "SI eNB_transport_info[enb_id].tbs[n_dci_dl]%d \n",
eNB_transport_info[enb_id].tbs[n_dci_dl]);
#endif
break;
case 2://TB0:
harq_pid = eNB_transport_info[enb_id].harq_pid[n_dci_dl];
ue_id = eNB_transport_info[enb_id].ue_id[n_dci_dl];
PHY_vars_eNB_g[enb_id]->dlsch_eNB[ue_id][0]->rnti= eNB_transport_info[enb_id].dci_alloc[n_dci_dl].rnti;
dlsch_eNB = PHY_vars_eNB_g[enb_id]->dlsch_eNB[ue_id][0];
break;
case 1: //RA:
memcpy(PHY_vars_eNB_g[enb_id]->dlsch_eNB_ra->harq_processes[0]->b,
&eNB_transport_info[enb_id].transport_blocks[payload_offset],
eNB_transport_info[enb_id].tbs[n_dci_dl]);
#ifdef DEBUG_EMU
LOG_D(EMU, " enb_id %d ue id is %d rnti is %x dci index %d, harq_pid %d tbs %d \n",
enb_id, ue_id, eNB_transport_info[enb_id].dci_alloc[n_dci_dl].rnti,
n_dci_dl, harq_pid, eNB_transport_info[enb_id].tbs[n_dci_dl]);
int i;
for (i=0;i<eNB_transport_info[enb_id].tbs[n_dci_dl];i++)
msg("%x.",(unsigned char) eNB_transport_info[enb_id].transport_blocks[payload_offset+i]);
#endif
memcpy(dlsch_eNB->harq_processes[harq_pid]->b,
&eNB_transport_info[enb_id].transport_blocks[payload_offset],
eNB_transport_info[enb_id].tbs[n_dci_dl]);
break;
case 3://TB1:
harq_pid = eNB_transport_info[enb_id].harq_pid[n_dci_dl];
ue_id = eNB_transport_info[enb_id].ue_id[n_dci_dl];
PHY_vars_eNB_g[enb_id]->dlsch_eNB[ue_id][1]->rnti= eNB_transport_info[enb_id].dci_alloc[n_dci_dl].rnti;
dlsch_eNB = PHY_vars_eNB_g[enb_id]->dlsch_eNB[ue_id][1];
memcpy(dlsch_eNB->harq_processes[harq_pid]->b,
&eNB_transport_info[enb_id].transport_blocks[payload_offset],
eNB_transport_info[enb_id].tbs[n_dci_dl]);
break;
}
payload_offset += eNB_transport_info[enb_id].tbs[n_dci_dl];
}
n_dci_dl++;
}
LOG_D(EMU, "RA eNB_transport_info[enb_id].tbs[n_dci_dl]%d \n",
eNB_transport_info[enb_id].tbs[n_dci_dl]);
#endif
break;
case 2://TB0:
harq_pid = eNB_transport_info[enb_id].harq_pid[n_dci_dl];
ue_id = eNB_transport_info[enb_id].ue_id[n_dci_dl];
PHY_vars_eNB_g[enb_id]->dlsch_eNB[ue_id][0]->rnti=
eNB_transport_info[enb_id].dci_alloc[n_dci_dl].rnti;
dlsch_eNB = PHY_vars_eNB_g[enb_id]->dlsch_eNB[ue_id][0];
#ifdef DEBUG_EMU
LOG_D(EMU,
" enb_id %d ue id is %d rnti is %x dci index %d, harq_pid %d tbs %d \n",
enb_id, ue_id, eNB_transport_info[enb_id].dci_alloc[n_dci_dl].rnti,
n_dci_dl, harq_pid, eNB_transport_info[enb_id].tbs[n_dci_dl]);
int i;
for (i=0; i<eNB_transport_info[enb_id].tbs[n_dci_dl]; i++) {
LOG_T(EMU, "%x.",
(unsigned char) eNB_transport_info[enb_id].transport_blocks[payload_offset+i]);
}
#endif
memcpy(dlsch_eNB->harq_processes[harq_pid]->b,
&eNB_transport_info[enb_id].transport_blocks[payload_offset],
eNB_transport_info[enb_id].tbs[n_dci_dl]);
break;
case 3://TB1:
harq_pid = eNB_transport_info[enb_id].harq_pid[n_dci_dl];
ue_id = eNB_transport_info[enb_id].ue_id[n_dci_dl];
PHY_vars_eNB_g[enb_id]->dlsch_eNB[ue_id][1]->rnti=
eNB_transport_info[enb_id].dci_alloc[n_dci_dl].rnti;
dlsch_eNB = PHY_vars_eNB_g[enb_id]->dlsch_eNB[ue_id][1];
memcpy(dlsch_eNB->harq_processes[harq_pid]->b,
&eNB_transport_info[enb_id].transport_blocks[payload_offset],
eNB_transport_info[enb_id].tbs[n_dci_dl]);
break;
}
payload_offset += eNB_transport_info[enb_id].tbs[n_dci_dl];
}
n_dci_dl++;
}
#ifdef DEBUG_EMU
LOG_D(EMU, "Fill phy eNB vars done next slot %d !\n", next_slot);
#endif
}
LOG_D(EMU, "Fill phy eNB vars done next slot %d !\n", next_slot);
#endif
}
}
void fill_phy_ue_vars(unsigned int ue_id, unsigned int last_slot) {
int n_enb;//index
int enb_id;
// int harq_id;
// int payload_offset = 0;
unsigned short rnti;
unsigned int harq_pid;
LTE_UE_ULSCH_t *ulsch;
PUCCH_FMT_t pucch_format;
// u8 ue_transport_info_index[NUMBER_OF_eNB_MAX];
u8 subframe = (last_slot+1)>>1;
memcpy (&ue_cntl_delay[ue_id][(last_slot+1)%2],
&UE_transport_info[ue_id].cntl,
sizeof(UE_cntl));
void fill_phy_ue_vars(unsigned int ue_id, unsigned int last_slot)
{
int n_enb;//index
int enb_id;
// int harq_id;
// int payload_offset = 0;
unsigned short rnti;
unsigned int harq_pid;
LTE_UE_ULSCH_t *ulsch;
PUCCH_FMT_t pucch_format;
// u8 ue_transport_info_index[NUMBER_OF_eNB_MAX];
u8 subframe = (last_slot+1)>>1;
memcpy (&ue_cntl_delay[ue_id][(last_slot+1)%2],
&UE_transport_info[ue_id].cntl,
sizeof(UE_cntl));
#ifdef DEBUG_EMU
LOG_D(EMU, "Last slot %d subframe %d Fill phy UE %d vars PRACH is (%d,%d) preamble (%d,%d) SR (%d,%d), pucch_sel (%d, %d)\n",
last_slot,subframe,ue_id,
UE_transport_info[ue_id].cntl.prach_flag,
ue_cntl_delay[ue_id][last_slot%2].prach_flag,
UE_transport_info[ue_id].cntl.prach_id,
ue_cntl_delay[ue_id][last_slot%2].prach_id,
UE_transport_info[ue_id].cntl.sr,
ue_cntl_delay[ue_id][last_slot%2].sr,
UE_transport_info[ue_id].cntl.pucch_sel,
ue_cntl_delay[ue_id][last_slot%2].pucch_sel );
#endif
//ue_cntl_delay[subframe%2].prach_flag ;
PHY_vars_UE_g[ue_id]->generate_prach = ue_cntl_delay[ue_id][last_slot%2].prach_flag;//UE_transport_info[ue_id].cntl.prach_flag;
if (PHY_vars_UE_g[ue_id]->generate_prach == 1) {
// if (PHY_vars_UE_g[ue_id]->prach_resources[enb_id] == NULL)
// PHY_vars_UE_g[ue_id]->prach_resources[enb_id] = malloc(sizeof(PRACH_RESOURCES_t));
//ue_cntl_delay[subframe%2].prach_id;
PHY_vars_UE_g[ue_id]->prach_PreambleIndex = ue_cntl_delay[ue_id][last_slot%2].prach_id;
}
pucch_format= ue_cntl_delay[ue_id][last_slot%2].pucch_flag;// UE_transport_info[ue_id].cntl.pucch_flag;
if ((last_slot+1) % 2 == 0 ) {
if (pucch_format == pucch_format1) // UE_transport_info[ue_id].cntl.sr;
PHY_vars_UE_g[ue_id]->sr[subframe] = ue_cntl_delay[ue_id][last_slot%2].sr;
else if ((pucch_format == pucch_format1a) || (pucch_format == pucch_format1b )){
PHY_vars_UE_g[ue_id]->pucch_payload[0] = ue_cntl_delay[ue_id][last_slot%2].pucch_payload;//UE_transport_info[ue_id].cntl.pucch_payload;
}
PHY_vars_UE_g[ue_id]->pucch_sel[subframe] = ue_cntl_delay[ue_id][last_slot%2].pucch_sel;
}
#ifdef DEBUG_EMU
LOG_D(EMU,"subframe %d trying to copy the payload from num eNB %d to UE %d \n",subframe, UE_transport_info[ue_id].num_eNB, ue_id);
LOG_D(EMU,
"Last slot %d subframe %d Fill phy UE %d vars PRACH is (%d,%d) preamble (%d,%d) SR (%d,%d), pucch_sel (%d, %d)\n",
last_slot,subframe,ue_id,
UE_transport_info[ue_id].cntl.prach_flag,
ue_cntl_delay[ue_id][last_slot%2].prach_flag,
UE_transport_info[ue_id].cntl.prach_id,
ue_cntl_delay[ue_id][last_slot%2].prach_id,
UE_transport_info[ue_id].cntl.sr,
ue_cntl_delay[ue_id][last_slot%2].sr,
UE_transport_info[ue_id].cntl.pucch_sel,
ue_cntl_delay[ue_id][last_slot%2].pucch_sel );
#endif
for (n_enb=0; n_enb < UE_transport_info[ue_id].num_eNB; n_enb++){
#ifdef DEBUG_EMU
/* LOG_D(EMU,"Setting ulsch vars for ue %d rnti %x harq pid is %d \n",
ue_id, UE_transport_info[ue_id].rnti[n_enb],
PHY_vars_UE_g[ue_id]->ulsch_ue[enb_id]);
*/
//ue_cntl_delay[subframe%2].prach_flag ;
PHY_vars_UE_g[ue_id]->generate_prach =
ue_cntl_delay[ue_id][last_slot%2].prach_flag;//UE_transport_info[ue_id].cntl.prach_flag;
if (PHY_vars_UE_g[ue_id]->generate_prach == 1) {
// if (PHY_vars_UE_g[ue_id]->prach_resources[enb_id] == NULL)
// PHY_vars_UE_g[ue_id]->prach_resources[enb_id] = malloc(sizeof(PRACH_RESOURCES_t));
//ue_cntl_delay[subframe%2].prach_id;
PHY_vars_UE_g[ue_id]->prach_PreambleIndex =
ue_cntl_delay[ue_id][last_slot%2].prach_id;
}
pucch_format=
ue_cntl_delay[ue_id][last_slot%2].pucch_flag;// UE_transport_info[ue_id].cntl.pucch_flag;
if ((last_slot+1) % 2 == 0 ) {
if (pucch_format == pucch_format1) { // UE_transport_info[ue_id].cntl.sr;
PHY_vars_UE_g[ue_id]->sr[subframe] = ue_cntl_delay[ue_id][last_slot%2].sr;
} else if ((pucch_format == pucch_format1a)
|| (pucch_format == pucch_format1b )) {
PHY_vars_UE_g[ue_id]->pucch_payload[0] =
ue_cntl_delay[ue_id][last_slot%2].pucch_payload;//UE_transport_info[ue_id].cntl.pucch_payload;
}
PHY_vars_UE_g[ue_id]->pucch_sel[subframe] =
ue_cntl_delay[ue_id][last_slot%2].pucch_sel;
}
#ifdef DEBUG_EMU
LOG_D(EMU,"subframe %d trying to copy the payload from num eNB %d to UE %d \n",
subframe, UE_transport_info[ue_id].num_eNB, ue_id);
#endif
for (n_enb=0; n_enb < UE_transport_info[ue_id].num_eNB; n_enb++) {
#ifdef DEBUG_EMU
/* LOG_D(EMU,"Setting ulsch vars for ue %d rnti %x harq pid is %d \n",
ue_id, UE_transport_info[ue_id].rnti[n_enb],
PHY_vars_UE_g[ue_id]->ulsch_ue[enb_id]);
*/
#endif
rnti = UE_transport_info[ue_id].rnti[n_enb];
enb_id = UE_transport_info[ue_id].eNB_id[n_enb];
PHY_vars_UE_g[ue_id]->lte_ue_pdcch_vars[enb_id]->crnti=rnti;
harq_pid = UE_transport_info[ue_id].harq_pid[n_enb];
//ulsch = PHY_vars_UE_g[ue_id]->ulsch_ue[enb_id];
PHY_vars_UE_g[ue_id]->ulsch_ue[enb_id]->o_RI[0] = ue_cntl_delay[ue_id][last_slot%2].pusch_ri & 0x1;
PHY_vars_UE_g[ue_id]->ulsch_ue[enb_id]->o_RI[1] = (ue_cntl_delay[ue_id][last_slot%2].pusch_ri>>1) & 0x1;
PHY_vars_UE_g[ue_id]->ulsch_ue[enb_id]->o_ACK[0]= ue_cntl_delay[ue_id][last_slot%2].pusch_ack & 0x1;
PHY_vars_UE_g[ue_id]->ulsch_ue[enb_id]->o_ACK[1]= (ue_cntl_delay[ue_id][last_slot%2].pusch_ack>>1) & 0x1;
//*(u32 *)ulsch->o = ue_cntl_delay[ue_id][last_slot%2].pusch_uci;
if (last_slot%2 == 1 ) {
PHY_vars_UE_g[ue_id]->ulsch_ue[enb_id]->O = ue_cntl_delay[ue_id][last_slot%2].length_uci;
PHY_vars_UE_g[ue_id]->ulsch_ue[enb_id]->uci_format = ue_cntl_delay[ue_id][last_slot%2].uci_format;
memcpy(PHY_vars_UE_g[ue_id]->ulsch_ue[enb_id]->o,
ue_cntl_delay[ue_id][last_slot%2].pusch_uci,
MAX_CQI_BYTES);
ulsch = PHY_vars_UE_g[ue_id]->ulsch_ue[enb_id];
// if (((HLC_subband_cqi_rank1_2A_5MHz *)ulsch->o)->cqi1)
LOG_D(EMU,"[UE %d] subframe %d last slot %d copy the payload from eNB %d to UE %d with harq id %d cqi (val %d, length %d) \n",
ue_id, subframe, last_slot, enb_id, ue_id, harq_pid,
((HLC_subband_cqi_rank1_2A_5MHz *)ulsch->o)->cqi1,
PHY_vars_UE_g[ue_id]->ulsch_ue[enb_id]->O);
}
memcpy(PHY_vars_UE_g[ue_id]->ulsch_ue[enb_id]->harq_processes[harq_pid]->b,
UE_transport_info[ue_id].transport_blocks,
UE_transport_info[ue_id].tbs[enb_id]);
//ue_transport_info_index[enb_id]+=UE_transport_info[ue_id].tbs[enb_id];
//UE_transport_info[ue_id].transport_blocks+=ue_transport_info_index[enb_id];
//LOG_T(EMU,"ulsch tbs is %d\n", UE_transport_info[ue_id].tbs[enb_id]);
}
rnti = UE_transport_info[ue_id].rnti[n_enb];
enb_id = UE_transport_info[ue_id].eNB_id[n_enb];
PHY_vars_UE_g[ue_id]->lte_ue_pdcch_vars[enb_id]->crnti=rnti;
harq_pid = UE_transport_info[ue_id].harq_pid[n_enb];
//ulsch = PHY_vars_UE_g[ue_id]->ulsch_ue[enb_id];
PHY_vars_UE_g[ue_id]->ulsch_ue[enb_id]->o_RI[0] =
ue_cntl_delay[ue_id][last_slot%2].pusch_ri & 0x1;
PHY_vars_UE_g[ue_id]->ulsch_ue[enb_id]->o_RI[1] =
(ue_cntl_delay[ue_id][last_slot%2].pusch_ri>>1) & 0x1;
PHY_vars_UE_g[ue_id]->ulsch_ue[enb_id]->o_ACK[0]=
ue_cntl_delay[ue_id][last_slot%2].pusch_ack & 0x1;
PHY_vars_UE_g[ue_id]->ulsch_ue[enb_id]->o_ACK[1]=
(ue_cntl_delay[ue_id][last_slot%2].pusch_ack>>1) & 0x1;
//*(u32 *)ulsch->o = ue_cntl_delay[ue_id][last_slot%2].pusch_uci;
if (last_slot%2 == 1 ) {
PHY_vars_UE_g[ue_id]->ulsch_ue[enb_id]->O =
ue_cntl_delay[ue_id][last_slot%2].length_uci;
PHY_vars_UE_g[ue_id]->ulsch_ue[enb_id]->uci_format =
ue_cntl_delay[ue_id][last_slot%2].uci_format;
memcpy(PHY_vars_UE_g[ue_id]->ulsch_ue[enb_id]->o,
ue_cntl_delay[ue_id][last_slot%2].pusch_uci,
MAX_CQI_BYTES);
ulsch = PHY_vars_UE_g[ue_id]->ulsch_ue[enb_id];
// if (((HLC_subband_cqi_rank1_2A_5MHz *)ulsch->o)->cqi1)
LOG_D(EMU,
"[UE %d] subframe %d last slot %d copy the payload from eNB %d to UE %d with harq id %d cqi (val %d, length %d) \n",
ue_id, subframe, last_slot, enb_id, ue_id, harq_pid,
((HLC_subband_cqi_rank1_2A_5MHz *)ulsch->o)->cqi1,
PHY_vars_UE_g[ue_id]->ulsch_ue[enb_id]->O);
}
memcpy(PHY_vars_UE_g[ue_id]->ulsch_ue[enb_id]->harq_processes[harq_pid]->b,
UE_transport_info[ue_id].transport_blocks,
UE_transport_info[ue_id].tbs[enb_id]);
//ue_transport_info_index[enb_id]+=UE_transport_info[ue_id].tbs[enb_id];
//UE_transport_info[ue_id].transport_blocks+=ue_transport_info_index[enb_id];
//LOG_T(EMU,"ulsch tbs is %d\n", UE_transport_info[ue_id].tbs[enb_id]);
}
}
/*! \file extern.h
* \brief specifies the extern variables for phy emulation
* \author Navid Nikaein and Raymomd Knopp and Hicham Anouar
* \date 2011
* \version 1.0
* \company Eurecom
* \email: navid.nikaein@eurecom.fr
*/
* \brief specifies the extern variables for phy emulation
* \author Navid Nikaein and Raymomd Knopp and Hicham Anouar
* \date 2011
* \version 1.1
* \company Eurecom
* \email: navid.nikaein@eurecom.fr
*/
#ifndef __BYPASS_SESSION_LAYER_EXTERN_H__
# define __BYPASS_SESSION_LAYER_EXTERN_H__
......@@ -23,16 +23,17 @@ extern unsigned char emu_rx_status;
//extern unsigned short Master_id;
//extern unsigned int Is_primary_master;
#if !defined(ENABLE_NEW_MULTICAST)
extern pthread_mutex_t emul_low_mutex;
extern pthread_cond_t emul_low_cond;
extern char emul_low_mutex_var;
extern pthread_mutex_t Tx_mutex;
extern pthread_cond_t Tx_cond;
extern char Tx_mutex_var;
#endif
extern int (*rx_handler) (unsigned char,char*,int);
extern int (*tx_handler) (unsigned char,char*, unsigned int*, unsigned int*);
extern rx_handler_t rx_handler;
extern tx_handler_t tx_handler;
extern eNB_transport_info_t eNB_transport_info[NUMBER_OF_eNB_MAX];
extern u16 eNB_transport_info_TB_index[NUMBER_OF_eNB_MAX];
......
/*! \file multicast.h
* \brief
* \author Lionel Gauthier and Navid Nikaein
* \date 2011
* \version 1.0
* \company Eurecom
* \email: navid.nikaein@eurecom.fr
*/
* \brief
* \author Lionel Gauthier and Navid Nikaein
* \date 2011
* \version 1.1
* \company Eurecom
* \email: navid.nikaein@eurecom.fr
*/
#include <pthread.h>
#include <stdio.h>
......@@ -26,110 +26,117 @@
#include <sys/socket.h>
#include <sys/select.h>
//#include "openair_defs.h"
//#include <sys/socket.h>
#include <netinet/in.h>
//#include "openair_defs.h"
#define MULTICAST_LINK_C
#include "socket.h"
#include "multicast_link.h"
#ifndef USER_MODE
#ifdef NODE_RG
//#include "mac_rg_bypass.h"
#endif
#ifdef NODE_MT
//#include "mac_ue_bypass.h"
#endif
#endif //USER_MODE
#ifdef USER_MODE
//#include <rtai.h>
# define msg printf
# include "UTIL/LOG/log.h"
#endif //USER_MODE
//#include "extern.h"
extern unsigned short Master_id;
#define MULTICAST_LINK_NUM_GROUPS 4
char *multicast_group_list[MULTICAST_LINK_NUM_GROUPS] = {
"239.0.0.161\0",
"239.0.0.162\0",
"239.0.0.163\0",
"239.0.0.164\0"
"239.0.0.161",
"239.0.0.162",
"239.0.0.163",
"239.0.0.164"
};
static multicast_group_t group_list[MULTICAST_LINK_NUM_GROUPS];
static fd_set socks; /* Socket file descriptors we want to wake up for, using select() */
static int highsock; /* Highest #'d file descriptor, needed for select() */
/* Socket file descriptors we want to wake up for, using select() */
static fd_set socks;
/* Highest #'d file descriptor, needed for select() */
static int highsock;
#if ! defined(ENABLE_NEW_MULTICAST)
static pthread_t main_loop_thread;
static void (*rx_handler) (unsigned int, char*);
static unsigned char multicast_group;
static char *multicast_if;
#endif
static void (*rx_handler) (unsigned int, char *);
static unsigned char multicast_group;
static char *multicast_if;
//------------------------------------------------------------------------------
void
multicast_link_init ()
{
//------------------------------------------------------------------------------
int group;
int multicast_loop;
int reuse_addr = 1; /* Used so we can re-bind to our port
while a previous connection is still
in TIME_WAIT state. */
static struct ip_mreq command;
struct sockaddr_in sin;
// struct ifreq ifr;
for (group = 0; group < MULTICAST_LINK_NUM_GROUPS; group++) {
strcpy (group_list[group].host_addr, multicast_group_list[group]);
group_list[group].port = 46014 + group;
group_list[group].socket = make_socket_inet (SOCK_DGRAM, &group_list[group].port, &sin);
msg("multicast_link_init(): Created socket %d for group %d, port %d\n",
group_list[group].socket,group,group_list[group].port);
if (setsockopt (group_list[group].socket, SOL_SOCKET, SO_REUSEADDR, &reuse_addr, sizeof (reuse_addr)) < 0) {
msg ("[MULTICAST] ERROR : setsockopt:SO_REUSEADDR, exiting ...");
exit (EXIT_FAILURE);
}
if (multicast_if != NULL) {
/* memset(&ifr, 0, sizeof(struct ifreq));
snprintf(ifr.ifr_name, sizeof(ifr.ifr_name), multicast_if);
ioctl(group_list[group].socket, SIOCGIFINDEX, &ifr);
if (setsockopt (group_list[group].socket, SOL_SOCKET,SO_BINDTODEVICE,(void*)&ifr, sizeof(struct ifreq)) < 0) { */
if (setsockopt (group_list[group].socket, SOL_SOCKET,SO_BINDTODEVICE,multicast_if, 4) < 0) {
msg ("[MULTICAST] ERROR : setsockopt:SO_BINDTODEVICE on interface %s, exiting ...\n", multicast_if);
msg ("[MULTICAST] make sure that you have a root privilage or run with sudo -E \n");
exit (EXIT_FAILURE);
}
}
socket_setnonblocking (group_list[group].socket);
int group;
int multicast_loop;
int reuse_addr = 1;
static struct ip_mreq command;
struct sockaddr_in sin;
// struct ifreq ifr;
//
multicast_loop = 0;
if (setsockopt (group_list[group].socket, IPPROTO_IP, IP_MULTICAST_LOOP, &multicast_loop, sizeof (multicast_loop)) < 0) {
msg ("[MULTICAST] ERROR: %s line %d multicast_link_main_loop() IP_MULTICAST_LOOP %m", __FILE__, __LINE__);
exit (EXIT_FAILURE);
}
// Join the broadcast group:
command.imr_multiaddr.s_addr = inet_addr (group_list[group].host_addr);
command.imr_interface.s_addr = htonl (INADDR_ANY);
if (command.imr_multiaddr.s_addr == -1) {
msg ("[MULTICAST] ERROR: %s line %d NO MULTICAST", __FILE__, __LINE__);
exit (EXIT_FAILURE);
}
if (setsockopt (group_list[group].socket, IPPROTO_IP, IP_ADD_MEMBERSHIP, &command, sizeof (command)) < 0) {
msg ("[MULTICAST] ERROR: %s line %d IP_ADD_MEMBERSHIP %m", __FILE__, __LINE__);
exit (EXIT_FAILURE);
}
for (group = 0; group < MULTICAST_LINK_NUM_GROUPS; group++) {
strcpy (group_list[group].host_addr, multicast_group_list[group]);
group_list[group].port = 46014 + group;
group_list[group].socket = make_socket_inet(
SOCK_DGRAM,
&group_list[group].port, &sin);
LOG_D(EMU, "multicast_link_init(): Created socket %d for group %d, port %d\n",
group_list[group].socket,group,group_list[group].port);
/* Used so we can re-bind to our port while a previous connection is still
* in TIME_WAIT state.
*/
if (setsockopt(group_list[group].socket, SOL_SOCKET, SO_REUSEADDR,
&reuse_addr, sizeof (reuse_addr)) < 0) {
LOG_E(EMU, "[MULTICAST] ERROR : setsockopt:SO_REUSEADDR, exiting ...");
exit (EXIT_FAILURE);
}
if (multicast_if != NULL) {
if (setsockopt(group_list[group].socket, SOL_SOCKET,SO_BINDTODEVICE,
multicast_if, 4) < 0) {
LOG_E(EMU,
"[MULTICAST] ERROR : setsockopt:SO_BINDTODEVICE on interface %s, exiting ...\n",
multicast_if);
LOG_E(EMU,
"[MULTICAST] make sure that you have a root privilage or run with sudo -E \n");
exit (EXIT_FAILURE);
}
}
memset (&group_list[group].sock_remote_addr, 0, sizeof (struct sockaddr_in));
group_list[group].sock_remote_addr.sin_family = AF_INET;
group_list[group].sock_remote_addr.sin_addr.s_addr = inet_addr (multicast_group_list[group]);
group_list[group].sock_remote_addr.sin_port = htons (group_list[group].port);
}
#if !defined(ENABLE_TCP_MULTICAST)
/* Make the socket blocking */
socket_setnonblocking(group_list[group].socket);
#endif
multicast_loop = 0;
if (setsockopt (group_list[group].socket, IPPROTO_IP, IP_MULTICAST_LOOP,
&multicast_loop, sizeof (multicast_loop)) < 0) {
LOG_E(EMU,
"[MULTICAST] ERROR: %s line %d multicast_link_main_loop() IP_MULTICAST_LOOP %m",
__FILE__, __LINE__);
exit (EXIT_FAILURE);
}
// Join the broadcast group:
command.imr_multiaddr.s_addr = inet_addr (group_list[group].host_addr);
command.imr_interface.s_addr = htonl (INADDR_ANY);
if (command.imr_multiaddr.s_addr == -1) {
LOG_E(EMU, "[MULTICAST] ERROR: %s line %d NO MULTICAST", __FILE__, __LINE__);
exit (EXIT_FAILURE);
}
if (setsockopt (group_list[group].socket, IPPROTO_IP, IP_ADD_MEMBERSHIP,
&command, sizeof (command)) < 0) {
LOG_E(EMU, "[MULTICAST] ERROR: %s line %d IP_ADD_MEMBERSHIP %m", __FILE__,
__LINE__);
exit (EXIT_FAILURE);
}
memset (&group_list[group].sock_remote_addr, 0, sizeof (struct sockaddr_in));
group_list[group].sock_remote_addr.sin_family = AF_INET;
group_list[group].sock_remote_addr.sin_addr.s_addr = inet_addr (
multicast_group_list[group]);
group_list[group].sock_remote_addr.sin_port = htons (group_list[group].port);
}
}
//------------------------------------------------------------------------------
......@@ -137,86 +144,69 @@ void
multicast_link_build_select_list ()
{
//------------------------------------------------------------------------------
int group;
int group;
/* First put together fd_set for select(), which will
consist of the sock veriable in case a new connection
is coming in, plus all the sockets we have already
accepted. */
/* First put together fd_set for select(), which will
consist of the sock veriable in case a new connection
is coming in, plus all the sockets we have already
accepted. */
/* FD_ZERO() clears out the fd_set called socks, so that
it doesn't contain any file descriptors. */
/* FD_ZERO() clears out the fd_set called socks, so that
it doesn't contain any file descriptors. */
FD_ZERO (&socks);
FD_ZERO (&socks);
/* Loops through all the possible connections and adds
those sockets to the fd_set */
/* Loops through all the possible connections and adds
those sockets to the fd_set */
for (group = 0; group < MULTICAST_LINK_NUM_GROUPS; group++) {
if (group_list[group].socket != 0) {
FD_SET (group_list[group].socket, &socks);
if (group_list[group].socket > highsock)
highsock = group_list[group].socket;
for (group = 0; group < MULTICAST_LINK_NUM_GROUPS; group++) {
if (group_list[group].socket != 0) {
FD_SET (group_list[group].socket, &socks);
if (group_list[group].socket > highsock) {
highsock = group_list[group].socket;
}
}
}
}
}
//------------------------------------------------------------------------------
void
multicast_link_read_data (int groupP)
{
//------------------------------------------------------------------------------
int num_bytes;
#ifdef BYPASS_PHY
//pthread_mutex_lock(&Bypass_phy_wr_mutex);
// while(Bypass_phy_wr){
// msg("[Multicast read] BYPASS_PHY_NOT_YET READY, Waiting for signal\n");
// pthread_cond_wait(&Bypass_phy_wr_cond,&Bypass_phy_wr_mutex);
// }
//msg("[Multicast read] BYPASS_PHY TX Signal\n");
//pthread_mutex_unlock(&Bypass_phy_wr_mutex);
//pthread_mutex_lock(&Bypass_phy_wr_mutex);
// Bypass_phy_wr=1;
// pthread_mutex_unlock(&Bypass_phy_wr_mutex);
#endif //BYPASS_PHY
int num_bytes;
//msg("multicast link read INNNNNNNNNNNNNNNNNN\n");
// msg("multicast_link_read_data: groupP=%d,rx_buffer = %p\n",groupP,group_list[groupP].rx_buffer );
if ((groupP <= MULTICAST_LINK_NUM_GROUPS) && (groupP >= 0)) {
if ((num_bytes = recvfrom (group_list[groupP].socket, group_list[groupP].rx_buffer, 40000, 0, 0, 0)) < 0) {
fprintf (stderr, "ERROR: %s line %d multicast_link_read_data()/recvfrom() %m", __FILE__, __LINE__);
if ((groupP <= MULTICAST_LINK_NUM_GROUPS) && (groupP >= 0)) {
if ((num_bytes = recvfrom (group_list[groupP].socket,
group_list[groupP].rx_buffer, 40000, 0, 0, 0)) < 0) {
LOG_E(EMU, "[MULTICAST] recvfrom has failed (%d:%s)\n (%s:%d)\n",
errno, strerror(errno), __FILE__, __LINE__);
} else {
rx_handler(num_bytes,group_list[groupP].rx_buffer);
}
} else {
// msg("multicast_link_read_data: groupP=%d,rx_buffer = %p,NUm_bytes=%d\n",groupP,group_list[groupP].rx_buffer,num_bytes );
//msg("MULTICAST calling rx_handler\n");
rx_handler(num_bytes,group_list[groupP].rx_buffer);
LOG_E(EMU, "[MULTICAST] ERROR: groupP out of bounds %d\n", groupP);
}
}
else {
fprintf(stderr,"ERROR: groupP out of bounds %d\n",groupP);
}
//msg("ENNNNND multicast_link_read_data: groupP=%d,rx_buffer = %p, num_bytes=%d\n",groupP,group_list[groupP].rx_buffer,num_bytes );
}
//------------------------------------------------------------------------------
void
multicast_link_read ()
{
//------------------------------------------------------------------------------
int group; /* Current item in connectlist for for loops */
int group; /* Current item in connectlist for for loops */
/* Now check connectlist for available data */
/* Now check connectlist for available data */
/* Run through our sockets and check to see if anything
happened with them, if so 'service' them. */
for (group = multicast_group; group < MULTICAST_LINK_NUM_GROUPS ; group++) {
if (FD_ISSET (group_list[group].socket, &socks)) {
multicast_link_read_data (group);
break;
}
} /* for (all entries in queue) */
/* Run through our sockets and check to see if anything
happened with them, if so 'service' them. */
for (group = multicast_group; group < MULTICAST_LINK_NUM_GROUPS ; group++) {
if (FD_ISSET (group_list[group].socket, &socks)) {
multicast_link_read_data (group);
break;
}
} /* for (all entries in queue) */
}
//------------------------------------------------------------------------------
......@@ -224,73 +214,89 @@ int
multicast_link_write_sock (int groupP, char *dataP, uint32_t sizeP)
{
//------------------------------------------------------------------------------
int num;
if ((num = sendto (group_list[groupP].socket, dataP, sizeP, 0, (struct sockaddr *) &group_list[groupP].sock_remote_addr, sizeof (group_list[groupP].sock_remote_addr))) < 0) {
fprintf (stderr, "ERROR: %s line %d multicast_link_write_sock()/sendto() %m", __FILE__, __LINE__);
}
return num;
int num;
if ((num = sendto (group_list[groupP].socket, dataP, sizeP, 0,
(struct sockaddr *) &group_list[groupP].sock_remote_addr,
sizeof (group_list[groupP].sock_remote_addr))) < 0) {
LOG_E(EMU, "[MULTICAST] sendto has failed (%d:%s)\n (%s:%d)\n",
errno, strerror(errno),
__FILE__, __LINE__);
}
return num;
}
//------------------------------------------------------------------------------
void *
multicast_link_main_loop (void *param)
int multicast_link_read_data_from_sock(uint8_t is_master)
{
//------------------------------------------------------------------------------
struct timeval timeout; /* Timeout for select */
int readsocks; /* Number of sockets ready for reading */
#ifdef USER_MODE
struct timeval timeout, *timeout_p;
int readsocks; /* Number of sockets ready for reading */
timeout.tv_sec = 0;
timeout.tv_usec = 3000;
if (is_master == 0) {
/* UE will block indefinetely if no data is sent from eNB
* NOTE: a NULL timeout for select will block indefinetely
*/
timeout_p = NULL;
} else {
/* In case of eNB set the timeout to 500 usecs after which we consider
* the packets as dropped.
*/
timeout_p = &timeout;
}
highsock = -1;
#endif //USER_MODE
highsock = -1;
while (1) {
multicast_link_build_select_list ();
/* [24/06/13] SR: Set the timeout to one second ->
* avoid infinite loop if no data to read.
*/
timeout.tv_sec = 1;
timeout.tv_usec = 0;
readsocks = select (highsock + 1, &socks, (fd_set *) 0, (fd_set *) 0, &timeout);
LOG_D(EMU, "Stuck on select with timeout %s\n",
timeout_p == NULL ? "infinite" : "1000 usecs");
readsocks = select(highsock + 1, &socks, (fd_set *) 0, (fd_set *) 0, timeout_p);
if (readsocks < 0) {
LOG_E(EMU, "Multicast select failed (%d:%s)\n", errno, strerror(errno));
// exit();
LOG_E(EMU, "Multicast select failed (%d:%s)\n", errno, strerror(errno));
exit(EXIT_FAILURE);
} else if (readsocks > 0) {
//msg("calling multicast link read\n");
multicast_link_read ();
// usleep(1);
LOG_D(EMU, "Multicast Normal read\n");
multicast_link_read();
} else {
/* Timeout */
LOG_I(EMU, "Multicast select time-out\n");
/* Timeout */
LOG_I(EMU, "Multicast select time-out\n");
return 1;
}
}
#ifdef USER_MODE
return 0;
}
#endif //USER_MODE
void* multicast_link_main_loop (void *param)
{
while (1) {
multicast_link_read_data_from_sock(0);
}
return NULL;
}
//-----------------------------------------------------------------------------
void
multicast_link_start ( void (*rx_handlerP) (unsigned int, char*), unsigned char multicast_group, char * multicast_ifname)
void multicast_link_start(void (*rx_handlerP) (unsigned int, char *),
unsigned char multicast_group, char *multicast_ifname)
{
//-----------------------------------------------------------------------------
rx_handler = rx_handlerP;
multicast_group = multicast_group;
multicast_if = multicast_ifname;
msg("[MULTICAST] LINK START on interface=%s for group=%d: handler=%p\n",
(multicast_if == NULL) ? "not specified" : multicast_if, multicast_group, rx_handler);
#ifdef BYPASS_PHY
// pthread_mutex_init(&Bypass_phy_wr_mutex,NULL);
//pthread_cond_init(&Bypass_phy_wr_cond,NULL);
//Bypass_phy_wr=0;
#endif //BYPASS_PHY
multicast_link_init ();
msg("[MULTICAST] multicast link start thread\n");
if (pthread_create (&main_loop_thread, NULL, multicast_link_main_loop, NULL) != 0) {
msg ("[MULTICAST LINK] Thread started\n");
exit (-2);
} else {
pthread_detach (main_loop_thread); // disassociate from parent
msg ("[MULTICAST LINK] Thread detached\n");
}
rx_handler = rx_handlerP;
multicast_group = multicast_group;
multicast_if = multicast_ifname;
LOG_I(EMU, "[MULTICAST] LINK START on interface=%s for group=%d: handler=%p\n",
(multicast_if == NULL) ? "not specified" : multicast_if, multicast_group,
rx_handler);
multicast_link_init ();
#if ! defined(ENABLE_NEW_MULTICAST)
LOG_D(EMU, "[MULTICAST] multicast link start thread\n");
if (pthread_create (&main_loop_thread, NULL, multicast_link_main_loop,
NULL) != 0) {
LOG_E(EMU, "[MULTICAST LINK] Error in pthread_create (%d:%s)\n",
errno, strerror(errno));
exit(EXIT_FAILURE);
} else {
pthread_detach(main_loop_thread); // disassociate from parent
LOG_I(EMU, "[MULTICAST LINK] Thread detached\n");
}
#endif
}
/*! \file multicast.h
* \brief
* \author Lionel Gauthier and Navid Nikaein
* \date 2011
* \version 1.0
* \company Eurecom
* \email: navid.nikaein@eurecom.fr
*/
* \brief
* \author Lionel Gauthier and Navid Nikaein
* \date 2011
* \version 1.1
* \company Eurecom
* \email: navid.nikaein@eurecom.fr
*/
#ifndef __MULTICAST_LINK_H__
# define __MULTICAST_LINK_H__
......@@ -18,27 +18,24 @@
# endif
# include "stdint.h"
private_multicast_link (typedef struct multicast_group_t {
int socket;
struct sockaddr_in sock_remote_addr;
char host_addr[16];
uint16_t port;
struct sockaddr_in sock_remote_addr;
uint16_t port;
char rx_buffer[40000];
} multicast_group_t;)
private_multicast_link(void multicast_link_init ());
private_multicast_link(void multicast_link_read_data (int groupP));
private_multicast_link(void multicast_link_read ());
private_multicast_link(void *multicast_link_main_loop (void *param));
public_multicast_link(int multicast_link_write_sock (int groupP, char *dataP, uint32_t sizeP));
public_multicast_link( void multicast_link_start ( void (*rx_handlerP) (unsigned int, char*), unsigned char multicast_group, char * multicast_ifname));
#ifdef BYPASS_PHY
public_multicast_link( pthread_mutex_t Bypass_phy_wr_mutex);
public_multicast_link( pthread_cond_t Bypass_phy_wr_cond);
public_multicast_link( char Bypass_phy_wr);
#endif //BYPASS_PHY
public_multicast_link(void multicast_link_start ( void (*rx_handlerP) (unsigned int, char*), unsigned char multicast_group, char * multicast_ifname));
# ifdef BYPASS_PHY
public_multicast_link(pthread_mutex_t Bypass_phy_wr_mutex);
public_multicast_link(pthread_cond_t Bypass_phy_wr_cond);
public_multicast_link(char Bypass_phy_wr);
# endif //BYPASS_PHY
#endif
/*! \file netlink_init.c
* \brief initiate the netlink socket for communication with nas dirver
* \brief initiate the netlink socket for communication with nas dirver
* \author Navid Nikaein and Raymomd Knopp
* \date 2011
* \version 1.0
* \version 1.0
* \company Eurecom
* \email: navid.nikaein@eurecom.fr
*/
*/
#include <sys/socket.h>
#include <linux/netlink.h>
......@@ -25,62 +25,50 @@ struct msghdr nas_msg;
#define GRAAL_NETLINK_ID 31
int netlink_init(void) {
int ret;
nas_sock_fd = socket(PF_NETLINK, SOCK_RAW,GRAAL_NETLINK_ID);
if (nas_sock_fd==-1) {
printf("[NETLINK] Error opening socket %d\n",nas_sock_fd);
return(-1);
}
printf("[NETLINK]Opened socket with fd %d\n",nas_sock_fd);
ret = fcntl(nas_sock_fd,F_SETFL,O_NONBLOCK);
printf("[NETLINK] fcntl returns %d\n",ret);
memset(&nas_src_addr, 0, sizeof(nas_src_addr));
nas_src_addr.nl_family = AF_NETLINK;
nas_src_addr.nl_pid = 1;//getpid(); /* self pid */
nas_src_addr.nl_groups = 0; /* not in mcast groups */
ret = bind(nas_sock_fd, (struct sockaddr*)&nas_src_addr,
sizeof(nas_src_addr));
printf("[NETLINK] bind returns %d\n",ret);
memset(&nas_dest_addr, 0, sizeof(nas_dest_addr));
nas_dest_addr.nl_family = AF_NETLINK;
nas_dest_addr.nl_pid = 0; /* For Linux Kernel */
nas_dest_addr.nl_groups = 0; /* unicast */
nas_nlh=(struct nlmsghdr *)malloc(NLMSG_SPACE(MAX_PAYLOAD));
/* Fill the netlink message header */
nas_nlh->nlmsg_len = NLMSG_SPACE(MAX_PAYLOAD);
nas_nlh->nlmsg_pid = 1;//getpid(); /* self pid */
nas_nlh->nlmsg_flags = 0;
nas_iov.iov_base = (void *)nas_nlh;
nas_iov.iov_len = nas_nlh->nlmsg_len;
memset(&nas_msg,0,sizeof(nas_msg));
nas_msg.msg_name = (void *)&nas_dest_addr;
nas_msg.msg_namelen = sizeof(nas_dest_addr);
nas_msg.msg_iov = &nas_iov;
nas_msg.msg_iovlen = 1;
/* Read message from kernel */
memset(nas_nlh, 0, NLMSG_SPACE(MAX_PAYLOAD));
return(nas_sock_fd);
int netlink_init(void)
{
int ret;
nas_sock_fd = socket(PF_NETLINK, SOCK_RAW,GRAAL_NETLINK_ID);
if (nas_sock_fd == -1) {
printf("[NETLINK] Error opening socket %d\n",nas_sock_fd);
return(-1);
}
printf("[NETLINK]Opened socket with fd %d\n",nas_sock_fd);
ret = fcntl(nas_sock_fd,F_SETFL,O_NONBLOCK);
printf("[NETLINK] fcntl returns %d\n",ret);
memset(&nas_src_addr, 0, sizeof(nas_src_addr));
nas_src_addr.nl_family = AF_NETLINK;
nas_src_addr.nl_pid = 1;//getpid(); /* self pid */
nas_src_addr.nl_groups = 0; /* not in mcast groups */
ret = bind(nas_sock_fd, (struct sockaddr *)&nas_src_addr,
sizeof(nas_src_addr));
printf("[NETLINK] bind returns %d\n",ret);
memset(&nas_dest_addr, 0, sizeof(nas_dest_addr));
nas_dest_addr.nl_family = AF_NETLINK;
nas_dest_addr.nl_pid = 0; /* For Linux Kernel */
nas_dest_addr.nl_groups = 0; /* unicast */
nas_nlh=(struct nlmsghdr *)malloc(NLMSG_SPACE(MAX_PAYLOAD));
/* Fill the netlink message header */
nas_nlh->nlmsg_len = NLMSG_SPACE(MAX_PAYLOAD);
nas_nlh->nlmsg_pid = 1;//getpid(); /* self pid */
nas_nlh->nlmsg_flags = 0;
nas_iov.iov_base = (void *)nas_nlh;
nas_iov.iov_len = nas_nlh->nlmsg_len;
memset(&nas_msg,0,sizeof(nas_msg));
nas_msg.msg_name = (void *)&nas_dest_addr;
nas_msg.msg_namelen = sizeof(nas_dest_addr);
nas_msg.msg_iov = &nas_iov;
nas_msg.msg_iovlen = 1;
/* Read message from kernel */
memset(nas_nlh, 0, NLMSG_SPACE(MAX_PAYLOAD));
return(nas_sock_fd);
}
......@@ -5,12 +5,18 @@
* \version 1.0
* \company Eurecom
* \email: navid.nikaein@eurecom.fr
*/
*/
#include "SIMULATION/ETH_TRANSPORT/defs.h"
#ifndef EMU_PROTO_H_
#define EMU_PROTO_H_
void init_bypass (void);
void bypass_init ( unsigned int (*tx_handlerP) (unsigned char,char*, unsigned int*, unsigned int*),unsigned int (*rx_handlerP) (unsigned char,char*,unsigned int));
int bypass_rx_data (unsigned int frame, unsigned int last_slot, unsigned int next_slot);
void bypass_signal_mac_phy(unsigned int frame, unsigned int last_slot, unsigned int next_slot);
int bypass_rx_data (unsigned int frame, unsigned int last_slot, unsigned int next_slot, uint8_t is_master);
void bypass_signal_mac_phy(unsigned int frame, unsigned int last_slot,
unsigned int next_slot, uint8_t is_master);
#ifndef USER_MODE
int multicast_link_write_sock (int groupP, char *dataP, unsigned int sizeP);
int bypass_tx_handler(unsigned int fifo, int rw);
......@@ -19,7 +25,7 @@ int bypass_rx_handler(unsigned int fifo, int rw);
void bypass_rx_handler(unsigned int Num_bytes,char *Rx_buffer);
#endif
void bypass_tx_data (char Type, unsigned int frame, unsigned int next_slot);
void bypass_tx_data (emu_transport_info_t Type, unsigned int frame, unsigned int next_slot);
void emulation_tx_rx(void);
......@@ -37,7 +43,10 @@ void emu_transport_DL(unsigned int frame, unsigned int last_slot,unsigned int ne
void emu_transport_UL(unsigned int frame, unsigned int last_slot,unsigned int next_slot);
void emu_transport_release(void);
int multicast_link_read_data_from_sock(uint8_t eNB_flag);
void clear_eNB_transport_info(u8);
void clear_UE_transport_info(u8);
int netlink_init(void);
#endif /* EMU_PROTO_H_ */
......@@ -24,15 +24,18 @@ unsigned char emu_rx_status;
//unsigned short Master_id;
//unsigned int Is_primary_master;
#if !defined(ENABLE_NEW_MULTICAST)
pthread_mutex_t emul_low_mutex;
pthread_cond_t emul_low_cond;
char emul_low_mutex_var;
pthread_mutex_t Tx_mutex;
pthread_cond_t Tx_cond;
char Tx_mutex_var;
#endif
int (*rx_handler) (unsigned char,char*,int);
int (*tx_handler) (unsigned char,char*, unsigned int*, unsigned int*);
/* Handlers for RX and TX */
rx_handler_t rx_handler;
tx_handler_t tx_handler;
eNB_transport_info_t eNB_transport_info[NUMBER_OF_eNB_MAX];
u16 eNB_transport_info_TB_index[NUMBER_OF_eNB_MAX];
......
/*******************************************************************************
Eurecom OpenAirInterface
Copyright(c) 1999 - 2012 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.fr/openairinterface
Address : EURECOM, Campus SophiaTech, 450 Route des Chappes
06410 Biot FRANCE
*******************************************************************************/
#include <stdio.h>
#ifndef ASSERTIONS_H_
#define ASSERTIONS_H_
#define DevCheck(cOND, vALUE1, vALUE2, vALUE3) \
do { \
if (!(cOND)) { \
fprintf(stderr, "%s:%d:%s Assertion `"#cOND"` failed.\n", \
__FILE__, __LINE__, __FUNCTION__); \
fprintf(stderr, #vALUE1": %d\n"#vALUE2": %d\n"#vALUE3": %d\n", \
(int)vALUE1, (int)vALUE2, (int)vALUE3); \
abort(); \
} \
} while(0)
#define DevCheck4(cOND, vALUE1, vALUE2, vALUE3, vALUE4) \
do { \
if (!(cOND)) { \
fprintf(stderr, "%s:%d:%s Assertion `"#cOND"` failed.\n", \
__FILE__, __LINE__, __FUNCTION__); \
fprintf(stderr, #vALUE1": %d\n"#vALUE2": %d\n"#vALUE3": %d\n" \
#vALUE4": %d\n", \
(int)vALUE1, (int)vALUE2, (int)vALUE3, (int)vALUE4); \
exit(EXIT_FAILURE); \
} \
} while(0)
#define DevParam(vALUE1, vALUE2, vALUE3) \
DevCheck(0 == 1, vALUE1, vALUE2, vALUE3)
#define DevAssert(cOND) \
do { \
if (!(cOND)) { \
fprintf(stderr, "%s:%d:%s Assertion `"#cOND"` failed.\n", \
__FILE__, __LINE__, __FUNCTION__); \
abort(); \
} \
} while(0)
#define DevMessage(mESSAGE) \
do { \
fprintf(stderr, "%s:%d:%s Execution interrupted: `"#mESSAGE"`.\n", \
__FILE__, __LINE__, __FUNCTION__); \
abort(); \
} while(0)
#endif /* ASSERTIONS_H_ */
......@@ -218,6 +218,7 @@ CFLAGS +=-DPROC
endif
CFLAGS += -DENABLE_VCD_FIFO
CFLAGS += -DENABLE_NEW_MULTICAST
# CFLAGS += -DENABLE_LOG_FIFO
OBJ = $(PHY_OBJS) $(SIMULATION_OBJS) $(ETHERNET_TRANSPORT_OBJS) $(TOOLS_OBJS) $(SCHED_OBJS) $(STATS_OBJS) $(OAISIM_OBJS) $(NAS_OBJS) $(INT_OBJS) $(UTIL_OBJ)
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment