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,40 +21,45 @@
#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;
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 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");
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;
......@@ -60,92 +67,106 @@ void bypass_init ( unsigned int (*tx_handlerP) (unsigned char,char*, unsigned in
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){
/***************************************************************************/
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 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");
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){
//LOG_T(EMU, " WAIT BYPASS_PHY...\n");
if(emul_low_mutex_var) {
pthread_cond_wait(&emul_low_cond, &emul_low_mutex);
}
if(num_bytesP==0){
//msg("[BYPASS] IDLE_WAIT\n");
//exit(0);
if(num_bytesP==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]);
} else {
#endif
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{
} 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,
#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){
switch(messg->Message_type) {
//case WAIT_SYNC_TRANSPORT:
case WAIT_PM_TRANSPORT_INFO:
if (messg->master_id==0 )
case EMU_TRANSPORT_INFO_WAIT_PM:
if (messg->master_id==0 ) {
Master_list_rx=((Master_list_rx) |(1<< messg->master_id));
}
break;
case WAIT_SM_TRANSPORT_INFO:
case EMU_TRANSPORT_INFO_WAIT_SM:
Master_list_rx=((Master_list_rx) |(1<< messg->master_id));
break;
case SYNC_TRANSPORT_INFO:
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 ){
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++ ){
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",
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++ ){
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",
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 );
......@@ -155,50 +176,57 @@ int bypass_rx_data (unsigned int frame, unsigned int last_slot, unsigned int nex
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 );
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:
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);
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 ){
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 < 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 < (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 ){
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);
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);
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);
} 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));
......@@ -206,15 +234,16 @@ int bypass_rx_data (unsigned int frame, unsigned int last_slot, unsigned int nex
emu_rx_status = SYNCED_TRANSPORT;
}
break;
case UE_TRANSPORT_INFO:
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);
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 ){
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;
......@@ -222,19 +251,21 @@ clear_UE_transport_info(oai_emulation.info.nb_ue_local+oai_emulation.info.nb_ue_
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 < 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 ++) {
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 ){
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);
UE_info = (UE_transport_info_t *)((unsigned int)UE_info + total_header+
total_tbs);
bytes_read+=total_header+total_tbs;
}
#ifdef DEBUG_EMU
......@@ -246,13 +277,14 @@ clear_UE_transport_info(oai_emulation.info.nb_ue_local+oai_emulation.info.nb_ue_
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 < 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 );
} 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));
......@@ -260,43 +292,47 @@ clear_UE_transport_info(oai_emulation.info.nb_ue_local+oai_emulation.info.nb_ue_
emu_rx_status = SYNCED_TRANSPORT;
}
break;
case RELEASE_TRANSPORT_INFO :
case EMU_TRANSPORT_INFO_RELEASE :
Master_list_rx = oai_emulation.info.master_list;
LOG_E(EMU, "RX RELEASE_TRANSPORT_INFO\n");
LOG_E(EMU, "RX EMU_TRANSPORT_INFO_RELEASE\n");
break;
default:
msg("[MAC][BYPASS] ERROR RX UNKNOWN MESSAGE\n");
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;
//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);
#endif
bypass_signal_mac_phy(frame,last_slot, next_slot, is_master);
#if !defined(ENABLE_NEW_MULTICAST)
}
#endif
//printf("leaving ...\n");
return bytes_read;
}
/******************************************************************************************************/
#ifndef USER_MODE
int bypass_rx_handler(unsigned int fifo, int rw){
/******************************************************************************************************/
// if(rw=='w'){
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);
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;
......@@ -310,59 +346,70 @@ int bypass_rx_handler(unsigned int fifo, int rw){
}
#else //USER_MODE
/******************************************************************************************************/
void bypass_rx_handler(unsigned int Num_bytes,char *Rx_buffer){
void bypass_rx_handler(unsigned int Num_bytes,char *Rx_buffer)
{
/******************************************************************************************************/
// msg("[BYPASS] BYPASS RX_HANDLER IN ...\n");
if(Num_bytes >0){
if(Num_bytes >0) {
#if !defined(ENABLE_NEW_MULTICAST)
pthread_mutex_lock(&emul_low_mutex);
while(!emul_low_mutex_var){
// msg("[BYPASS] BYPASS: WAIT MAC_LOW...\n");
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);
memcpy(rx_bufferP, Rx_buffer, Num_bytes);
#if !defined(ENABLE_NEW_MULTICAST)
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!!!!!!
/* 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
}
}
#endif //USER_MODE
/******************************************************************************************************/
void bypass_signal_mac_phy(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, uint8_t is_master)
{
/******************************************************************************************************/
// char tt=1;
if(Master_list_rx != oai_emulation.info.master_list){
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);
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;
}
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");
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],
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);
......@@ -371,103 +418,126 @@ int multicast_link_write_sock (int groupP, char *dataP, unsigned int sizeP){
#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)
{
/***************************************************************************/
unsigned int num_flows;
bypass_msg_header_t *messg;
unsigned int byte_tx_count;
// eNB_transport_info_t *eNB_info;
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)]);
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;
messg->seq_num = seq_num_tx;
byte_tx_count = sizeof (bypass_msg_header_t) + sizeof (bypass_proto2multicast_header_t);
seq_num_tx++;
if(Type==WAIT_PM_TRANSPORT){
messg->Message_type = WAIT_PM_TRANSPORT_INFO;
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 = WAIT_SM_TRANSPORT_INFO;
} 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 = SYNC_TRANSPORT_INFO;
// make sure that sync messages from the masters are received in increasing order of master id
} 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){
} else if(Type==ENB_TRANSPORT) {
LOG_D(EMU,"[TX_DATA] ENB TRANSPORT\n");
messg->Message_type = ENB_TRANSPORT_INFO;
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++) {
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 < (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;
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){
} else if (Type == UE_TRANSPORT) {
LOG_D(EMU,"[TX_DATA] UE TRANSPORT\n");
messg->Message_type = UE_TRANSPORT_INFO;
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++) {
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;
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 = RELEASE_TRANSPORT_INFO;
}else {
LOG_T(EMU,"[TX_DATA] UNKNOWN MSG \n");
} else if (Type == RELEASE_TRANSPORT) {
messg->Message_type = EMU_TRANSPORT_INFO_RELEASE;
} else {
LOG_E(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
/*********************************************************************************************************************/
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);
int bypass_tx_handler(unsigned int fifo, int rw)
{
/***************************************************************************/
if(++N_R==N_P) {
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);
}
// }
}
#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;
......@@ -114,53 +105,11 @@ typedef struct bypass_msg_header {
unsigned int nb_flow; /*! \brief */
unsigned int frame;
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;
//#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){
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);
Master_list_rx=oai_emulation.info.master_list-1; // just wait to recieve the master 0 msg
bypass_rx_data(0,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);
} 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);
bypass_rx_data(0,0,0);
if (bypass_rx_data(0,0,0,0) == -1) {
goto retry2;
}
if (emu_rx_status == SYNCED_TRANSPORT){ // i received the sync from all secondary masters
// i received the sync from all secondary masters
if (emu_rx_status == SYNCED_TRANSPORT) {
emu_tx_status = SYNCED_TRANSPORT;
}
// 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)
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);
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)
if ((frame_type == 1) && (direction == SF_S)) {
if (next_slot%2==0) {
emu_transport_DL(frame, last_slot,next_slot);
else
} else {
emu_transport_UL(frame, last_slot , next_slot);
}
//DL
}else {
} else {
if (next_slot%2 == 0 )
if ( ((frame_type == 1) && (direction == SF_DL )) || (frame_type == 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) ){
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) {
if (oai_emulation.info.is_primary_master==0){
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
if (oai_emulation.info.nb_enb_local>0) { // send in DL if
bypass_tx_data(ENB_TRANSPORT,frame, next_slot);
else
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);
bypass_rx_data(frame, last_slot, next_slot, 0);
}
else { // I am the master
} else { // I am the master
// bypass_tx_data(WAIT_TRANSPORT,last_slot);
if (oai_emulation.info.nb_enb_local>0) // send in DL if
if (oai_emulation.info.nb_enb_local>0) { // send in DL if
bypass_tx_data(ENB_TRANSPORT,frame, next_slot);
else
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);
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);
}
void emu_transport_UL(unsigned int frame, unsigned int last_slot, unsigned int next_slot) {
if (oai_emulation.info.is_primary_master==0){
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);
else
bypass_tx_data(WAIT_SM_TRANSPORT,frame, next_slot);
bypass_rx_data(frame,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 {
} else {
// bypass_tx_data(WAIT_TRANSPORT,last_slot);
if (oai_emulation.info.nb_ue_local>0)
if (oai_emulation.info.nb_ue_local>0) {
bypass_tx_data(UE_TRANSPORT,frame, next_slot);
else
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);
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);
}
void emu_transport_release(void){
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;
unsigned int emul_tx_handler(unsigned char Mode,char *Tx_buffer,
unsigned int *Nbytes,unsigned int *Nb_flows)
{
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_data(void){
unsigned int emul_rx_data(void)
{
return(0);
}
unsigned int emul_rx_handler(unsigned char Mode,char *rx_buffer, unsigned int Nbytes){
unsigned int emul_rx_handler(unsigned char Mode,char *rx_buffer,
unsigned int Nbytes)
{
unsigned short Rx_size=0;
return (Rx_size+2);
}
void clear_eNB_transport_info(u8 nb_eNB) {
void clear_eNB_transport_info(u8 nb_eNB)
{
u8 eNB_id;
for (eNB_id=0;eNB_id<nb_eNB;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;
......@@ -169,20 +192,20 @@ void clear_eNB_transport_info(u8 nb_eNB) {
// LOG_T(EMU, "EMUL clear_eNB_transport_info\n");
}
void clear_UE_transport_info(u8 nb_UE) {
void clear_UE_transport_info(u8 nb_UE)
{
u8 UE_id;
for (UE_id=0;UE_id<nb_UE;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");
}
void fill_phy_enb_vars(unsigned int enb_id, unsigned int next_slot) {
int n_dci=0, n_dci_dl;
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;
......@@ -190,13 +213,14 @@ void fill_phy_enb_vars(unsigned int enb_id, unsigned int next_slot) {
u8 nb_total_dci;
#ifdef DEBUG_EMU
LOG_D(EMU," pbch fill phy eNB %d vars for slot %d \n",enb_id, next_slot);
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
//if (next_slot == 2){
*(u32*)PHY_vars_eNB_g[enb_id]->pbch_pdu = eNB_transport_info[enb_id].cntl.pbch_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,
......@@ -211,9 +235,12 @@ void fill_phy_enb_vars(unsigned int enb_id, unsigned int next_slot) {
// 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;
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) {
......@@ -221,14 +248,12 @@ void fill_phy_enb_vars(unsigned int enb_id, unsigned int next_slot) {
&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++) {
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
//exclude ul dci
if (eNB_transport_info[enb_id].dci_alloc[n_dci_dl].format > 0) {
#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,
......@@ -237,14 +262,13 @@ void fill_phy_enb_vars(unsigned int enb_id, unsigned int next_slot) {
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]);
#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, "SI eNB_transport_info[enb_id].tbs[n_dci_dl]%d \n",
eNB_transport_info[enb_id].tbs[n_dci_dl]);
#endif
break;
case 1: //RA:
......@@ -253,32 +277,36 @@ void fill_phy_enb_vars(unsigned int enb_id, unsigned int next_slot) {
&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, "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;
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",
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]);
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;
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,
......@@ -297,8 +325,8 @@ void fill_phy_enb_vars(unsigned int enb_id, unsigned int next_slot) {
}
}
void fill_phy_ue_vars(unsigned int ue_id, unsigned int last_slot) {
void fill_phy_ue_vars(unsigned int ue_id, unsigned int last_slot)
{
int n_enb;//index
int enb_id;
// int harq_id;
......@@ -315,7 +343,9 @@ void fill_phy_ue_vars(unsigned int ue_id, unsigned int last_slot) {
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",
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,
......@@ -327,27 +357,34 @@ void fill_phy_ue_vars(unsigned int ue_id, unsigned int last_slot) {
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;
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;
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;
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;
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;
} 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;
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,"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++){
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],
......@@ -363,16 +400,22 @@ void fill_phy_ue_vars(unsigned int ue_id, unsigned int last_slot) {
//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_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;
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;
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,
......@@ -380,7 +423,8 @@ void fill_phy_ue_vars(unsigned int ue_id, unsigned int last_slot) {
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",
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);
......
/*! \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,46 +26,38 @@
#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*);
#endif
static void (*rx_handler) (unsigned int, char *);
static unsigned char multicast_group;
static char *multicast_if;
......@@ -76,9 +68,7 @@ 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. */
int reuse_addr = 1;
static struct ip_mreq command;
struct sockaddr_in sin;
// struct ifreq ifr;
......@@ -86,48 +76,65 @@ multicast_link_init ()
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 = 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);
if (setsockopt (group_list[group].socket, SOL_SOCKET, SO_REUSEADDR, &reuse_addr, sizeof (reuse_addr)) < 0) {
msg ("[MULTICAST] ERROR : setsockopt:SO_REUSEADDR, exiting ...");
/* 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) {
/* 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");
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);
}
}
socket_setnonblocking (group_list[group].socket);
//
#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) {
msg ("[MULTICAST] ERROR: %s line %d multicast_link_main_loop() IP_MULTICAST_LOOP %m", __FILE__, __LINE__);
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) {
msg ("[MULTICAST] ERROR: %s line %d NO MULTICAST", __FILE__, __LINE__);
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) {
msg ("[MULTICAST] ERROR: %s line %d IP_ADD_MEMBERSHIP %m", __FILE__, __LINE__);
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_addr.s_addr = inet_addr (
multicast_group_list[group]);
group_list[group].sock_remote_addr.sin_port = htons (group_list[group].port);
}
}
......@@ -157,48 +164,31 @@ multicast_link_build_select_list ()
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)
if (group_list[group].socket > highsock) {
highsock = group_list[group].socket;
}
}
}
}
//------------------------------------------------------------------------------
void
multicast_link_read_data (int groupP)
{
//------------------------------------------------------------------------------
#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 ((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 {
// 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);
}
} else {
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 ()
......@@ -225,72 +215,88 @@ 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__);
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 */
struct timeval timeout, *timeout_p;
int readsocks; /* Number of sockets ready for reading */
#ifdef USER_MODE
#endif //USER_MODE
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;
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();
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");
return 1;
}
return 0;
}
void* multicast_link_main_loop (void *param)
{
while (1) {
multicast_link_read_data_from_sock(0);
}
#ifdef USER_MODE
#endif //USER_MODE
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
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 ();
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);
#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
msg ("[MULTICAST LINK] Thread detached\n");
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;
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
......@@ -25,14 +25,12 @@ struct msghdr nas_msg;
#define GRAAL_NETLINK_ID 31
int netlink_init(void) {
int netlink_init(void)
{
int ret;
nas_sock_fd = socket(PF_NETLINK, SOCK_RAW,GRAAL_NETLINK_ID);
if (nas_sock_fd==-1) {
if (nas_sock_fd == -1) {
printf("[NETLINK] Error opening socket %d\n",nas_sock_fd);
return(-1);
}
......@@ -45,7 +43,7 @@ int netlink_init(void) {
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,
ret = bind(nas_sock_fd, (struct sockaddr *)&nas_src_addr,
sizeof(nas_src_addr));
printf("[NETLINK] bind returns %d\n",ret);
......@@ -69,18 +67,8 @@ int netlink_init(void) {
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);
}
......@@ -7,10 +7,16 @@
* \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