Compare commits

...

2 Commits

Author SHA1 Message Date
Cedric Roux
edb209f6e5 much better mobipass integration
with this commit I get very stable connection
over long period of time (more than 30 minutes)

I had 0 fake_rrh disconnet/reconnect messages.

I had very rarely timeouts on data from mobipass
(uplink).

Almost 0 nacks. I had some uplink nacks, which were
most certainly due to the timeouts above.

I was doing full udp DL (33Mb/s) and tcp UL (was going
around 15Mb/s) at the same time, with 1 UE.

Next step is to cleanup, remove globals, integrate properly
as a driver and put this in develop.
2017-08-11 11:10:29 +02:00
Cedric Roux
72e6e34f41 mobipass hack 2017-08-11 11:10:29 +02:00
16 changed files with 2808 additions and 21 deletions

View File

@@ -532,6 +532,14 @@ set(TPLIB_ETHERNET_SOURCE
)
add_library(oai_eth_transpro MODULE ${TPLIB_ETHERNET_SOURCE} )
include_directories("${OPENAIR_TARGETS}/ARCH/mobipass/")
set(TPLIB_MOBIPASS_SOURCE
${OPENAIR_TARGETS}/ARCH/mobipass/main.c
${OPENAIR_TARGETS}/ARCH/mobipass/mobipass.c
${OPENAIR_TARGETS}/ARCH/mobipass/queues.c
)
add_library(oai_mobipass MODULE ${TPLIB_MOBIPASS_SOURCE} )
##########################################################

View File

@@ -1,18 +1,25 @@
ID = MOBIPASS
GROUP = ALL:GENERAL:ENB
FORMAT = int,ts_high : int,ts_low
ID = SUBFRAME
GROUP = ALL:GENERAL:ENB
FORMAT = int,frame : int,subframe : string,function
#general logs
ID = ENB_MASTER_TICK
DESC = eNodeB master tick - one tick per ms, to be used as "reference clock", mostly for ticktime view
GROUP = ALL:GENERAL:ENB
FORMAT = int,eNB_ID : int,frame : int,subframe
FORMAT = int,eNB_ID : int,CC_id : int,frame : int,subframe
#PHY logs
ID = ENB_PHY_UL_TICK
DESC = eNodeB uplink tick - one tick per ms at start of uplink processing
GROUP = ALL:PHY:GRAPHIC:ENB
FORMAT = int,eNB_ID : int,frame : int,subframe
FORMAT = int,eNB_ID : int,CC_id : int,frame : int,subframe
ID = ENB_PHY_DL_TICK
DESC = eNodeB downlink tick - one tick per ms at start of downlink processing
GROUP = ALL:PHY:GRAPHIC:ENB
FORMAT = int,eNB_ID : int,frame : int,subframe
FORMAT = int,eNB_ID : int,CC_id : int,frame : int,subframe
ID = ENB_PHY_DLSCH_UE_DCI
DESC = eNodeB downlink UE specific DCI as sent by the PHY layer
GROUP = ALL:PHY:GRAPHIC:ENB
@@ -44,7 +51,7 @@ ID = ENB_PHY_ULSCH_UE_NACK
ID = ENB_PHY_INPUT_SIGNAL
DESC = eNodeB received signal in the time domain for a duration of 1ms
GROUP = ALL:PHY:GRAPHIC:HEAVY:ENB
FORMAT = int,eNB_ID : int,frame : int,subframe : int,antenna : buffer,rxdata
FORMAT = int,eNB_ID : int,CC_id : int,frame : int,subframe : int,antenna : buffer,rxdata
ID = ENB_PHY_UL_CHANNEL_ESTIMATE
DESC = eNodeB channel estimation in the time domain
GROUP = ALL:PHY:GRAPHIC:HEAVY:ENB

View File

@@ -264,14 +264,14 @@ static void enb_main_gui(enb_gui *e, gui *g, event_handler *h, void *database,
input_signal_plot = new_xy_plot(g, 256, 55, "input signal", 20);
widget_add_child(g, line, input_signal_plot, -1);
xy_plot_set_range(g, input_signal_plot, 0, 7680*10, 20, 70);
xy_plot_set_range(g, input_signal_plot, 0, 7680*10*2, 20, 70);
input_signal_log = new_framelog(h, database,
"ENB_PHY_INPUT_SIGNAL", "subframe", "rxdata");
/* a skip value of 10 means to process 1 frame over 10, that is
* more or less 10 frames per second
*/
framelog_set_skip(input_signal_log, 10);
input_signal_view = new_view_xy(7680*10, 10,
input_signal_view = new_view_xy(7680*10*2, 10,
g, input_signal_plot, new_color(g, "#0c0c72"), XY_LOOP_MODE);
logger_add_view(input_signal_log, input_signal_view);

View File

@@ -215,7 +215,7 @@ void send_IF5(PHY_VARS_eNB *eNB, openair0_timestamp proc_timestamp, int subframe
// Write the packet to the fronthaul
if ((eNB->ifdevice.trx_write_func(&eNB->ifdevice,
packet_id,
proc_timestamp + packet_id*db_fulllength,
(void**)&tx_buffer,
db_fulllength,
1,
@@ -464,6 +464,22 @@ void recv_IF5(PHY_VARS_eNB *eNB, openair0_timestamp *proc_timestamp, int subfram
db_fulllength,
1
);
//store rxdata and increase packet_id
rxp[0] = (void*)&eNB->common_vars.rxdata[0][0][(subframe*eNB->frame_parms.samples_per_tti)+packet_id*db_fulllength];
rxp128 = (__m128i *) (rxp[0]);
for (i=0; i<db_fulllength>>2; i+=2) {
r0 = _mm_loadu_si128(data_block++);
*rxp128++ =_mm_slli_epi16(_mm_srai_epi16(_mm_unpacklo_epi8(r0,r0),8),4);
*rxp128++ =_mm_slli_epi16(_mm_srai_epi16(_mm_unpackhi_epi8(r0,r0),8),4);
}
packet_id++;
#if 0
uint64_t tt = htonl(timestamp_mobipass[packet_id]);
static uint64_t oldts = 0;
T(T_MOBIPASS, T_INT(tt-oldts), T_INT(tt));
oldts = tt;
if (offset_cnt != header->seqno) printf("ERROR offset_cnt %d header->seqno %d\n", offset_cnt, header->seqno);
#ifdef DEBUG_UL_MOBIPASS
if (((proc->timestamp_tx + lower_offset) > ntohl(timestamp_mobipass[packet_id])) || ((proc->timestamp_tx + upper_offset) < ntohl(timestamp_mobipass[packet_id]))) {
//ignore the packet
@@ -499,6 +515,7 @@ void recv_IF5(PHY_VARS_eNB *eNB, openair0_timestamp *proc_timestamp, int subfram
packet_id++;
offset_cnt = (header->seqno+1)&255;
}
#endif /* #if 0 */
}//end while
*proc_timestamp = ntohl(timestamp_mobipass[0]);

View File

@@ -1899,6 +1899,7 @@ uint32_t rx_pucch(PHY_VARS_eNB *eNB,
Nprime_div_deltaPUCCH_Shift = (n1_pucch < thres) ? Ncs1_div_deltaPUCCH_Shift : (12/deltaPUCCH_Shift);
Nprime = Nprime_div_deltaPUCCH_Shift * deltaPUCCH_Shift;
LOG_I(PHY, "[eNB] PUCCH: cNcs1/deltaPUCCH_Shift %d, Nprime %d, n1_pucch %d\n",thres,Nprime,n1_pucch);
#ifdef DEBUG_PUCCH_RX
printf("[eNB] PUCCH: cNcs1/deltaPUCCH_Shift %d, Nprime %d, n1_pucch %d\n",thres,Nprime,n1_pucch);
#endif
@@ -2095,6 +2096,7 @@ uint32_t rx_pucch(PHY_VARS_eNB *eNB,
// Do cfo correction and MRC across symbols
if (fmt == pucch_format1) {
LOG_I(PHY, "Doing PUCCH detection for format 1\n");
#ifdef DEBUG_PUCCH_RX
printf("Doing PUCCH detection for format 1\n");
#endif
@@ -2159,6 +2161,7 @@ uint32_t rx_pucch(PHY_VARS_eNB *eNB,
printf("[eNB] PUCCH: stat %d, stat_max %d, phase_max %d\n", stat,stat_max,phase_max);
#endif
LOG_I(PHY,"[eNB] PUCCH fmt1: stat_max : %d, sigma2_dB %d (%d, %d), phase_max : %d\n",dB_fixed(stat_max),sigma2_dB,eNB->measurements[0].n0_subband_power_tot_dBm[6],pucch1_thres,phase_max);
#ifdef DEBUG_PUCCH_RX
LOG_I(PHY,"[eNB] PUCCH fmt1: stat_max : %d, sigma2_dB %d (%d, %d), phase_max : %d\n",dB_fixed(stat_max),sigma2_dB,eNB->measurements[0].n0_subband_power_tot_dBm[6],pucch1_thres,phase_max);
#endif
@@ -2198,6 +2201,7 @@ uint32_t rx_pucch(PHY_VARS_eNB *eNB,
}
} else if ((fmt == pucch_format1a)||(fmt == pucch_format1b)) {
stat_max = 0;
LOG_I(PHY,"Doing PUCCH detection for format 1a/1b\n");
#ifdef DEBUG_PUCCH_RX
LOG_I(PHY,"Doing PUCCH detection for format 1a/1b\n");
#endif
@@ -2266,6 +2270,7 @@ uint32_t rx_pucch(PHY_VARS_eNB *eNB,
} //re
} // aa
LOG_I(PHY,"Format 1A: phase %d : stat %d\n",phase,stat);
#ifdef DEBUG_PUCCH_RX
LOG_I(PHY,"Format 1A: phase %d : stat %d\n",phase,stat);
#endif
@@ -2402,6 +2407,8 @@ uint32_t rx_pucch(PHY_VARS_eNB *eNB,
} //re
} // aa
LOG_I(PHY,"PUCCH 1a/b: subframe %d : stat %d,%d (pos %d)\n",subframe,stat_re,stat_im,
(subframe<<10) + (eNB->pucch1ab_stats_cnt[UE_id][subframe]));
#ifdef DEBUG_PUCCH_RX
LOG_I(PHY,"PUCCH 1a/b: subframe %d : stat %d,%d (pos %d)\n",subframe,stat_re,stat_im,
(subframe<<10) + (eNB->pucch1ab_stats_cnt[UE_id][subframe]));

View File

@@ -1179,7 +1179,7 @@ void phy_procedures_eNB_TX(PHY_VARS_eNB *eNB,
VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_PHY_PROCEDURES_ENB_TX+offset,1);
if (do_meas==1) start_meas(&eNB->phy_proc_tx);
T(T_ENB_PHY_DL_TICK, T_INT(eNB->Mod_id), T_INT(frame), T_INT(subframe));
T(T_ENB_PHY_DL_TICK, T_INT(eNB->Mod_id), T_INT(eNB->CC_id), T_INT(frame), T_INT(subframe));
for (i=0; i<NUMBER_OF_UE_MAX; i++) {
// If we've dropped the UE, go back to PRACH mode for this UE
@@ -2170,7 +2170,7 @@ void pucch_procedures(PHY_VARS_eNB *eNB,eNB_rxtx_proc_t *proc,int UE_id,int harq
frame,
subframe,
PUCCH1_THRES);
LOG_D(PHY,"[eNB %d][SR %x] Frame %d subframe %d Checking SR is %d (SR n1pucch is %d)\n",
LOG_I(PHY,"[eNB %d][SR %x] Frame %d subframe %d Checking SR is %d (SR n1pucch is %d)\n",
eNB->Mod_id,
eNB->ulsch[UE_id]->rnti,
frame,
@@ -2197,7 +2197,7 @@ void pucch_procedures(PHY_VARS_eNB *eNB,eNB_rxtx_proc_t *proc,int UE_id,int harq
// if SR was detected, use the n1_pucch from SR, else use n1_pucch0
// n1_pucch0 = (SR_payload==1) ? eNB->scheduling_request_config[UE_id].sr_PUCCH_ResourceIndex:n1_pucch0;
LOG_D(PHY,"Demodulating PUCCH for ACK/NAK: n1_pucch0 %d (%d), SR_payload %d\n",n1_pucch0,eNB->scheduling_request_config[UE_id].sr_PUCCH_ResourceIndex,SR_payload);
LOG_I(PHY,"Demodulating PUCCH for ACK/NAK: n1_pucch0 %d (%d), SR_payload %d\n",n1_pucch0,eNB->scheduling_request_config[UE_id].sr_PUCCH_ResourceIndex,SR_payload);
if (eNB->abstraction_flag == 0) {
metric0 = rx_pucch(eNB,
@@ -2253,6 +2253,11 @@ void pucch_procedures(PHY_VARS_eNB *eNB,eNB_rxtx_proc_t *proc,int UE_id,int harq
#endif
}
LOG_I(PHY,"[eNB %d][PDSCH %x] Frame %d subframe %d pucch1a (FDD) payload %d (metric %d)\n",
eNB->Mod_id,
eNB->dlsch[UE_id][0]->rnti,
frame,subframe,
pucch_payload0[0],metric0);
#ifdef DEBUG_PHY_PROC
LOG_D(PHY,"[eNB %d][PDSCH %x] Frame %d subframe %d pucch1a (FDD) payload %d (metric %d)\n",
eNB->Mod_id,
@@ -2283,6 +2288,10 @@ void pucch_procedures(PHY_VARS_eNB *eNB,eNB_rxtx_proc_t *proc,int UE_id,int harq
// if SR was detected, use the n1_pucch from SR
if (SR_payload==1) {
LOG_I(PHY,"[eNB %d][PDSCH %x] Frame %d subframe %d Checking ACK/NAK (%d,%d,%d,%d) format %d with SR\n",eNB->Mod_id,
eNB->dlsch[UE_id][0]->rnti,
frame,subframe,
n1_pucch0,n1_pucch1,n1_pucch2,n1_pucch3,format);
#ifdef DEBUG_PHY_PROC
LOG_D(PHY,"[eNB %d][PDSCH %x] Frame %d subframe %d Checking ACK/NAK (%d,%d,%d,%d) format %d with SR\n",eNB->Mod_id,
eNB->dlsch[UE_id][0]->rnti,
@@ -2311,6 +2320,10 @@ void pucch_procedures(PHY_VARS_eNB *eNB,eNB_rxtx_proc_t *proc,int UE_id,int harq
#endif
}
} else { //using n1_pucch0/n1_pucch1 resources
LOG_I(PHY,"[eNB %d][PDSCH %x] Frame %d subframe %d Checking ACK/NAK (%d,%d,%d,%d) format %d\n",eNB->Mod_id,
eNB->dlsch[UE_id][0]->rnti,
frame,subframe,
n1_pucch0,n1_pucch1,n1_pucch2,n1_pucch3,format);
#ifdef DEBUG_PHY_PROC
LOG_D(PHY,"[eNB %d][PDSCH %x] Frame %d subframe %d Checking ACK/NAK (%d,%d,%d,%d) format %d\n",eNB->Mod_id,
eNB->dlsch[UE_id][0]->rnti,
@@ -2388,6 +2401,10 @@ void pucch_procedures(PHY_VARS_eNB *eNB,eNB_rxtx_proc_t *proc,int UE_id,int harq
pucch_sel = 2; // indicate that this is a bundled ACK/NAK
}
LOG_I(PHY,"[eNB %d][PDSCH %x] Frame %d subframe %d ACK/NAK metric 0 %d, metric 1 %d, sel %d, (%d,%d)\n",eNB->Mod_id,
eNB->dlsch[UE_id][0]->rnti,
frame,subframe,
metric0,metric1,pucch_sel,pucch_payload[0],pucch_payload[1]);
#ifdef DEBUG_PHY_PROC
LOG_D(PHY,"[eNB %d][PDSCH %x] Frame %d subframe %d ACK/NAK metric 0 %d, metric 1 %d, sel %d, (%d,%d)\n",eNB->Mod_id,
eNB->dlsch[UE_id][0]->rnti,
@@ -2403,6 +2420,8 @@ void pucch_procedures(PHY_VARS_eNB *eNB,eNB_rxtx_proc_t *proc,int UE_id,int harq
}
if (SR_payload == 1) {
LOG_I(PHY,"[eNB %d][SR %x] Frame %d subframe %d Got SR for PUSCH, transmitting to MAC\n",eNB->Mod_id,
eNB->ulsch[UE_id]->rnti,frame,subframe);
LOG_D(PHY,"[eNB %d][SR %x] Frame %d subframe %d Got SR for PUSCH, transmitting to MAC\n",eNB->Mod_id,
eNB->ulsch[UE_id]->rnti,frame,subframe);
eNB->UE_stats[UE_id].sr_received++;
@@ -2411,6 +2430,9 @@ void pucch_procedures(PHY_VARS_eNB *eNB,eNB_rxtx_proc_t *proc,int UE_id,int harq
eNB->first_sr[UE_id] = 0;
eNB->dlsch[UE_id][0]->harq_processes[0]->round=0;
eNB->dlsch[UE_id][0]->harq_processes[0]->status=SCH_IDLE;
LOG_I(PHY,"[eNB %d][SR %x] Frame %d subframe %d First SR\n",
eNB->Mod_id,
eNB->ulsch[UE_id]->rnti,frame,subframe);
LOG_D(PHY,"[eNB %d][SR %x] Frame %d subframe %d First SR\n",
eNB->Mod_id,
eNB->ulsch[UE_id]->rnti,frame,subframe);
@@ -2886,9 +2908,9 @@ void phy_procedures_eNB_uespec_RX(PHY_VARS_eNB *eNB,eNB_rxtx_proc_t *proc,const
uint16_t do_srs=0;
uint16_t is_srs_pos=0;
T(T_ENB_PHY_UL_TICK, T_INT(eNB->Mod_id), T_INT(frame), T_INT(subframe));
T(T_ENB_PHY_UL_TICK, T_INT(eNB->Mod_id), T_INT(eNB->CC_id), T_INT(frame), T_INT(subframe));
T(T_ENB_PHY_INPUT_SIGNAL, T_INT(eNB->Mod_id), T_INT(frame), T_INT(subframe), T_INT(0),
T(T_ENB_PHY_INPUT_SIGNAL, T_INT(eNB->Mod_id), T_INT(eNB->CC_id), T_INT(frame), T_INT(subframe), T_INT(0),
T_BUFFER(&eNB->common_vars.rxdata[0][0][subframe*eNB->frame_parms.samples_per_tti],
eNB->frame_parms.samples_per_tti * 4));

File diff suppressed because it is too large Load Diff

View File

@@ -688,7 +688,548 @@ void schedule_ulsch(module_id_t module_idP,
}
//#define BASIC_SCHED_HACK
#ifdef BASIC_SCHED_HACK
/* basic scheduler:
* - schedule only 1 UE per TTI
* - priority based: once scheduled, go to end of list
* - retransmission has absolute priority
* potential issues:
* - interactions with random access
*/
static int list[16];
static int list_size;
static void list_check(int rnti)
{
int i;
for (i = 0; i < list_size; i++)
if (list[i] == rnti) { printf("rnti %d already in list\n", rnti); abort(); }
}
static void list_insert_at_start(int rnti)
{
list_check(rnti);
if (list_size == 16) { printf("list full\n"); abort(); }
memmove(list+1, list, list_size * sizeof(int));
list[0] = rnti;
list_size++;
}
static void list_insert_at_end(int rnti)
{
list_check(rnti);
if (list_size == 16) { printf("list full\n"); abort(); }
list[list_size] = rnti;
list_size++;
}
static void list_remove(int rnti)
{
int i;
for (i = 0; i < list_size; i++) if (list[i] == rnti) break;
if (i == list_size) { printf("rnti %d not found\n", rnti); abort(); }
list_size--;
memmove(list+i, list+i+1, (list_size-i) * sizeof(int));
}
static int in_list(int rnti)
{
int i;
for (i = 0; i < list_size; i++) if (list[i] == rnti) return 1;
return 0;
}
static int look_for_ue(int wanted_rnti)
{
eNB_MAC_INST *eNB = &eNB_mac_inst[0];
UE_list_t *UE_list = &eNB->UE_list;
int i;
int rnti;
for (i = 0; i < NUMBER_OF_UE_MAX; i++) {
if (UE_list->active[i] != TRUE) continue;
rnti = UE_RNTI(0, i);
if (rnti == wanted_rnti) return i;
}
return -1;
}
static int get_ue_id(int wanted_rnti)
{
int ret = look_for_ue(wanted_rnti);
if (ret == -1) abort();
return ret;
}
static int ue_in_mac(int wanted_rnti)
{
int ret = look_for_ue(wanted_rnti);
return ret != -1;
}
static int is_rach_subframe(int frame, int subframe)
{
/* we suppose config 0 */
frame = ((frame * 10 + subframe + 4) / 10) % 1024;
subframe = (subframe + 4) % 10;
return (frame & 1) == 0 && subframe == 1;
}
static void basic_ul(int module_idP, int frameP, int subframeP, uint16_t *first_rb, int sched_subframe)
{
if (module_idP) abort();
if (is_rach_subframe(frameP, subframeP)) first_rb[0] = 8;
/* TODO: careful - only for mobipass CC 1 */
//if (is_rach_subframe(frameP, subframeP)) first_rb[1] = 8;
eNB_MAC_INST *eNB = &eNB_mac_inst[0];
UE_list_t *UE_list = &eNB->UE_list;
LTE_DL_FRAME_PARMS *frame_parms;
LTE_eNB_UE_stats *eNB_UE_stats = NULL;
int i;
int rnti;
int CC_id;
uint8_t harq_pid = 0;
uint8_t round = 0;
uint8_t aggregation = 2;
int UE_id;
UE_TEMPLATE *UE_template;
uint8_t status = 0;
uint32_t cqi_req,cshift,ndi,mcs=0,rballoc,tpc;
UE_sched_ctrl *UE_sched_ctrl;
int32_t normalized_rx_power, target_rx_power=-90;
static int32_t tpc_accumulated=0;
uint8_t rb_table_index = -1;
uint16_t TBS = 0;
void *ULSCH_dci = NULL;
DCI_PDU *DCI_pdu;
/* update list, put new UEs at head of list */
for (i = 0; i < NUMBER_OF_UE_MAX; i++) {
if (UE_list->active[i] != TRUE) continue;
rnti = UE_RNTI(0, i);
if (rnti==NOT_A_RNTI) continue;
if (!phy_stats_exist(0, rnti)) continue;
if (!in_list(rnti))
{
printf("%d.%d: UL new rnti %d\n", frameP, subframeP, rnti);
list_insert_at_start(rnti);
}
}
/* remove dead UEs */
remove:
for (i = 0; i < list_size; i++) {
if (ue_in_mac(list[i]) && phy_stats_exist(0, list[i])) continue;
printf("%d.%d: UL remove rnti %d (in_mac %d phy_stats_exist %d)\n", frameP, subframeP, list[i], ue_in_mac(list[i]), phy_stats_exist(0, list[i]));
list_remove(list[i]);
goto remove;
}
/* look for retransmission */
for (i = 0; i < list_size; i++) {
rnti = list[i];
UE_id = get_ue_id(rnti);
// don't schedule if Msg4 is not received yet
if (UE_list->UE_template[UE_PCCID(module_idP,UE_id)][UE_id].configured==FALSE) {
LOG_I(MAC,"[eNB %d] frame %d subfarme %d, UE %d: not configured, skipping UE scheduling \n",
module_idP,frameP,subframeP,UE_id);
continue;
}
CC_id = 0;
frame_parms = mac_xface->get_lte_frame_parms(module_idP,CC_id);
eNB_UE_stats = mac_xface->get_eNB_UE_stats(module_idP,CC_id,rnti);
if (eNB_UE_stats->mode != PUSCH) continue;
if (mac_xface->get_ue_active_harq_pid(module_idP,CC_id,rnti,frameP,subframeP,&harq_pid,&round,openair_harq_UL) == -1 ) {
LOG_W(MAC,"[eNB %d] Scheduler Frame %d, subframeP %d: candidate harq_pid from PHY for UE %d CC %d RNTI %x\n",
module_idP,frameP,subframeP, UE_id, CC_id, rnti);
abort();
}
if (round != 0) {
T(T_ENB_MAC_UE_UL_SCHEDULE_RETRANSMISSION, T_INT(module_idP), T_INT(CC_id), T_INT(rnti), T_INT(frameP),
T_INT(subframeP), T_INT(harq_pid), T_INT(round), T_INT(-1), T_INT(-1),
T_INT(round));
list_remove(rnti);
list_insert_at_end(rnti);
/* nothing more to do */
return;
}
}
/* first transmission */
for (i = 0; i < list_size; i++) {
rnti = list[i];
UE_id = get_ue_id(rnti);
//if (UE_id + 1 != subframeP) continue;
// don't schedule if Msg4 is not received yet
if (UE_list->UE_template[UE_PCCID(module_idP,UE_id)][UE_id].configured==FALSE) {
LOG_I(MAC,"[eNB %d] frame %d subfarme %d, UE %d: not configured, skipping UE scheduling \n",
module_idP,frameP,subframeP,UE_id);
continue;
}
CC_id = 0;
frame_parms = mac_xface->get_lte_frame_parms(module_idP,CC_id);
eNB_UE_stats = mac_xface->get_eNB_UE_stats(module_idP,CC_id,rnti);
if (eNB_UE_stats->mode != PUSCH) continue;
DCI_pdu = &eNB->common_channels[CC_id].DCI_pdu;
UE_template = &UE_list->UE_template[CC_id][UE_id];
UE_sched_ctrl = &UE_list->UE_sched_ctrl[UE_id];
if (mac_xface->get_ue_active_harq_pid(module_idP,CC_id,rnti,frameP,subframeP,&harq_pid,&round,openair_harq_UL) == -1 ) {
LOG_W(MAC,"[eNB %d] Scheduler Frame %d, subframeP %d: candidate harq_pid from PHY for UE %d CC %d RNTI %x\n",
module_idP,frameP,subframeP, UE_id, CC_id, rnti);
abort();
}
if (round != 0) abort();
aggregation=get_aggregation(get_bw_index(module_idP,CC_id),
eNB_UE_stats->DL_cqi[0],
format0);
if (CCE_allocation_infeasible(module_idP,CC_id,0,subframeP,aggregation,rnti)) {
LOG_W(MAC,"[eNB %d] frame %d subframe %d, UE %d/%x CC %d: not enough nCCE\n", module_idP,frameP,subframeP,UE_id,rnti,CC_id);
//abort();
continue;
}
if (!(UE_is_to_be_scheduled(module_idP,CC_id,UE_id)>0)) continue;
list_remove(rnti);
list_insert_at_end(rnti);
UE_list->head_ul = UE_id;
UE_list->next_ul[UE_id] = -1;
/* copy/paste from old code, with adaptation (no pre_processor) */
UE_template->ul_SR = 0;
status = mac_eNB_get_rrc_status(module_idP,rnti);
if (status < RRC_CONNECTED)
cqi_req = 0;
else if (UE_sched_ctrl->cqi_req_timer>30) {
cqi_req = 1;
UE_sched_ctrl->cqi_req_timer=0;
}
else
cqi_req = 0;
//power control
//compute the expected ULSCH RX power (for the stats)
// this is the normalized RX power and this should be constant (regardless of mcs
normalized_rx_power = eNB_UE_stats->UL_rssi[0];
target_rx_power = mac_xface->get_target_pusch_rx_power(module_idP,CC_id);
// this assumes accumulated tpc
// make sure that we are only sending a tpc update once a frame, otherwise the control loop will freak out
int32_t framex10psubframe = UE_template->pusch_tpc_tx_frame*10+UE_template->pusch_tpc_tx_subframe;
if (((framex10psubframe+10)<=(frameP*10+subframeP)) || //normal case
((framex10psubframe>(frameP*10+subframeP)) && (((10240-framex10psubframe+frameP*10+subframeP)>=10)))) //frame wrap-around
{
UE_template->pusch_tpc_tx_frame=frameP;
UE_template->pusch_tpc_tx_subframe=subframeP;
if (normalized_rx_power>(target_rx_power+1)) {
tpc = 0; //-1
tpc_accumulated--;
} else if (normalized_rx_power<(target_rx_power-1)) {
tpc = 2; //+1
tpc_accumulated++;
} else {
tpc = 1; //0
}
} else {
tpc = 1; //0
}
if (frameP == 1000)
if (tpc!=1) {
printf("[eNB %d] ULSCH scheduler: frame %d, subframe %d, harq_pid %d, tpc %d, accumulated %d, normalized/target rx power %d/%d\n",
module_idP,frameP,subframeP,harq_pid,tpc,
tpc_accumulated,normalized_rx_power,target_rx_power);
LOG_D(MAC,"[eNB %d] ULSCH scheduler: frame %d, subframe %d, harq_pid %d, tpc %d, accumulated %d, normalized/target rx power %d/%d\n",
module_idP,frameP,subframeP,harq_pid,tpc,
tpc_accumulated,normalized_rx_power,target_rx_power);
}
ndi = 1-UE_template->oldNDI_UL[harq_pid];
UE_template->oldNDI_UL[harq_pid]=ndi;
UE_list->eNB_UE_stats[CC_id][UE_id].normalized_rx_power=normalized_rx_power;
UE_list->eNB_UE_stats[CC_id][UE_id].target_rx_power=target_rx_power;
UE_list->eNB_UE_stats[CC_id][UE_id].ulsch_mcs1=UE_template->pre_assigned_mcs_ul;
mcs = UE_template->pre_assigned_mcs_ul;//cmin (UE_template->pre_assigned_mcs_ul, openair_daq_vars.target_ue_ul_mcs); // adjust, based on user-defined MCS
if (UE_template->pre_allocated_rb_table_index_ul >=0) {
rb_table_index=UE_template->pre_allocated_rb_table_index_ul;
} else {
mcs=10;//cmin (10, openair_daq_vars.target_ue_ul_mcs);
rb_table_index=5; // for PHR
}
mcs = 19;
rb_table_index = 32;
UE_list->eNB_UE_stats[CC_id][UE_id].ulsch_mcs2=mcs;
// buffer_occupancy = UE_template->ul_total_buffer;
while (((rb_table[rb_table_index]>(frame_parms->N_RB_UL-1-first_rb[CC_id])) ||
(rb_table[rb_table_index]>45)) &&
(rb_table_index>0)) {
rb_table_index--;
}
TBS = mac_xface->get_TBS_UL(mcs,rb_table[rb_table_index]);
UE_list->eNB_UE_stats[CC_id][UE_id].total_rbs_used_rx+=rb_table[rb_table_index];
UE_list->eNB_UE_stats[CC_id][UE_id].ulsch_TBS=TBS;
// buffer_occupancy -= TBS;
rballoc = mac_xface->computeRIV(frame_parms->N_RB_UL,
first_rb[CC_id],
rb_table[rb_table_index]);
T(T_ENB_MAC_UE_UL_SCHEDULE, T_INT(module_idP), T_INT(CC_id), T_INT(rnti), T_INT(frameP),
T_INT(subframeP), T_INT(harq_pid), T_INT(mcs), T_INT(first_rb[CC_id]), T_INT(rb_table[rb_table_index]),
T_INT(TBS), T_INT(ndi));
if (mac_eNB_get_rrc_status(module_idP,rnti) < RRC_CONNECTED)
LOG_I(MAC,"[eNB %d][PUSCH %d/%x] CC_id %d Frame %d subframeP %d Scheduled UE %d (mcs %d, first rb %d, nb_rb %d, rb_table_index %d, TBS %d, harq_pid %d)\n",
module_idP,harq_pid,rnti,CC_id,frameP,subframeP,UE_id,mcs,
first_rb[CC_id],rb_table[rb_table_index],
rb_table_index,TBS,harq_pid);
// bad indices : 20 (40 PRB), 21 (45 PRB), 22 (48 PRB)
// increment for next UE allocation
first_rb[CC_id]+=rb_table[rb_table_index];
//store for possible retransmission
UE_template->nb_rb_ul[harq_pid] = rb_table[rb_table_index];
UE_sched_ctrl->ul_scheduled |= (1<<harq_pid);
// adjust total UL buffer status by TBS, wait for UL sdus to do final update
LOG_D(MAC,"[eNB %d] CC_id %d UE %d/%x : adjusting ul_total_buffer, old %d, TBS %d\n", module_idP,CC_id,UE_id,rnti,UE_template->ul_total_buffer,TBS);
if (UE_template->ul_total_buffer > TBS)
UE_template->ul_total_buffer -= TBS;
else
UE_template->ul_total_buffer = 0;
LOG_D(MAC,"ul_total_buffer, new %d\n", UE_template->ul_total_buffer);
// Cyclic shift for DM RS
cshift = 0;// values from 0 to 7 can be used for mapping the cyclic shift (36.211 , Table 5.5.2.1.1-1)
if (frame_parms->frame_type == TDD) {
switch (frame_parms->N_RB_UL) {
case 6:
ULSCH_dci = UE_template->ULSCH_DCI[harq_pid];
((DCI0_1_5MHz_TDD_1_6_t *)ULSCH_dci)->type = 0;
((DCI0_1_5MHz_TDD_1_6_t *)ULSCH_dci)->hopping = 0;
((DCI0_1_5MHz_TDD_1_6_t *)ULSCH_dci)->rballoc = rballoc;
((DCI0_1_5MHz_TDD_1_6_t *)ULSCH_dci)->mcs = mcs;
((DCI0_1_5MHz_TDD_1_6_t *)ULSCH_dci)->ndi = ndi;
((DCI0_1_5MHz_TDD_1_6_t *)ULSCH_dci)->TPC = tpc;
((DCI0_1_5MHz_TDD_1_6_t *)ULSCH_dci)->cshift = cshift;
((DCI0_1_5MHz_TDD_1_6_t *)ULSCH_dci)->padding = 0;
((DCI0_1_5MHz_TDD_1_6_t *)ULSCH_dci)->dai = UE_template->DAI_ul[sched_subframe];
((DCI0_1_5MHz_TDD_1_6_t *)ULSCH_dci)->cqi_req = cqi_req;
add_ue_spec_dci(DCI_pdu,
ULSCH_dci,
rnti,
sizeof(DCI0_1_5MHz_TDD_1_6_t),
aggregation,
sizeof_DCI0_1_5MHz_TDD_1_6_t,
format0,
0);
break;
default:
case 25:
ULSCH_dci = UE_template->ULSCH_DCI[harq_pid];
((DCI0_5MHz_TDD_1_6_t *)ULSCH_dci)->type = 0;
((DCI0_5MHz_TDD_1_6_t *)ULSCH_dci)->hopping = 0;
((DCI0_5MHz_TDD_1_6_t *)ULSCH_dci)->rballoc = rballoc;
((DCI0_5MHz_TDD_1_6_t *)ULSCH_dci)->mcs = mcs;
((DCI0_5MHz_TDD_1_6_t *)ULSCH_dci)->ndi = ndi;
((DCI0_5MHz_TDD_1_6_t *)ULSCH_dci)->TPC = tpc;
((DCI0_5MHz_TDD_1_6_t *)ULSCH_dci)->cshift = cshift;
((DCI0_5MHz_TDD_1_6_t *)ULSCH_dci)->padding = 0;
((DCI0_5MHz_TDD_1_6_t *)ULSCH_dci)->dai = UE_template->DAI_ul[sched_subframe];
((DCI0_5MHz_TDD_1_6_t *)ULSCH_dci)->cqi_req = cqi_req;
add_ue_spec_dci(DCI_pdu,
ULSCH_dci,
rnti,
sizeof(DCI0_5MHz_TDD_1_6_t),
aggregation,
sizeof_DCI0_5MHz_TDD_1_6_t,
format0,
0);
break;
case 50:
ULSCH_dci = UE_template->ULSCH_DCI[harq_pid];
((DCI0_10MHz_TDD_1_6_t *)ULSCH_dci)->type = 0;
((DCI0_10MHz_TDD_1_6_t *)ULSCH_dci)->hopping = 0;
((DCI0_10MHz_TDD_1_6_t *)ULSCH_dci)->rballoc = rballoc;
((DCI0_10MHz_TDD_1_6_t *)ULSCH_dci)->mcs = mcs;
((DCI0_10MHz_TDD_1_6_t *)ULSCH_dci)->ndi = ndi;
((DCI0_10MHz_TDD_1_6_t *)ULSCH_dci)->TPC = tpc;
((DCI0_10MHz_TDD_1_6_t *)ULSCH_dci)->cshift = cshift;
((DCI0_10MHz_TDD_1_6_t *)ULSCH_dci)->padding = 0;
((DCI0_10MHz_TDD_1_6_t *)ULSCH_dci)->dai = UE_template->DAI_ul[sched_subframe];
((DCI0_10MHz_TDD_1_6_t *)ULSCH_dci)->cqi_req = cqi_req;
add_ue_spec_dci(DCI_pdu,
ULSCH_dci,
rnti,
sizeof(DCI0_10MHz_TDD_1_6_t),
aggregation,
sizeof_DCI0_10MHz_TDD_1_6_t,
format0,
0);
break;
case 100:
ULSCH_dci = UE_template->ULSCH_DCI[harq_pid];
((DCI0_20MHz_TDD_1_6_t *)ULSCH_dci)->type = 0;
((DCI0_20MHz_TDD_1_6_t *)ULSCH_dci)->hopping = 0;
((DCI0_20MHz_TDD_1_6_t *)ULSCH_dci)->rballoc = rballoc;
((DCI0_20MHz_TDD_1_6_t *)ULSCH_dci)->mcs = mcs;
((DCI0_20MHz_TDD_1_6_t *)ULSCH_dci)->ndi = ndi;
((DCI0_20MHz_TDD_1_6_t *)ULSCH_dci)->TPC = tpc;
((DCI0_20MHz_TDD_1_6_t *)ULSCH_dci)->cshift = cshift;
((DCI0_20MHz_TDD_1_6_t *)ULSCH_dci)->padding = 0;
((DCI0_20MHz_TDD_1_6_t *)ULSCH_dci)->dai = UE_template->DAI_ul[sched_subframe];
((DCI0_20MHz_TDD_1_6_t *)ULSCH_dci)->cqi_req = cqi_req;
add_ue_spec_dci(DCI_pdu,
ULSCH_dci,
rnti,
sizeof(DCI0_20MHz_TDD_1_6_t),
aggregation,
sizeof_DCI0_20MHz_TDD_1_6_t,
format0,
0);
break;
}
} // TDD
else { //FDD
switch (frame_parms->N_RB_UL) {
case 25:
default:
ULSCH_dci = UE_template->ULSCH_DCI[harq_pid];
((DCI0_5MHz_FDD_t *)ULSCH_dci)->type = 0;
((DCI0_5MHz_FDD_t *)ULSCH_dci)->hopping = 0;
((DCI0_5MHz_FDD_t *)ULSCH_dci)->rballoc = rballoc;
((DCI0_5MHz_FDD_t *)ULSCH_dci)->mcs = mcs;
((DCI0_5MHz_FDD_t *)ULSCH_dci)->ndi = ndi;
((DCI0_5MHz_FDD_t *)ULSCH_dci)->TPC = tpc;
((DCI0_5MHz_FDD_t *)ULSCH_dci)->cshift = cshift;
((DCI0_5MHz_FDD_t *)ULSCH_dci)->padding = 0;
((DCI0_5MHz_FDD_t *)ULSCH_dci)->cqi_req = cqi_req;
add_ue_spec_dci(DCI_pdu,
ULSCH_dci,
rnti,
sizeof(DCI0_5MHz_FDD_t),
aggregation,
sizeof_DCI0_5MHz_FDD_t,
format0,
0);
break;
case 6:
ULSCH_dci = UE_template->ULSCH_DCI[harq_pid];
((DCI0_1_5MHz_FDD_t *)ULSCH_dci)->type = 0;
((DCI0_1_5MHz_FDD_t *)ULSCH_dci)->hopping = 0;
((DCI0_1_5MHz_FDD_t *)ULSCH_dci)->rballoc = rballoc;
((DCI0_1_5MHz_FDD_t *)ULSCH_dci)->mcs = mcs;
((DCI0_1_5MHz_FDD_t *)ULSCH_dci)->ndi = ndi;
((DCI0_1_5MHz_FDD_t *)ULSCH_dci)->TPC = tpc;
((DCI0_1_5MHz_FDD_t *)ULSCH_dci)->cshift = cshift;
((DCI0_1_5MHz_FDD_t *)ULSCH_dci)->padding = 0;
((DCI0_1_5MHz_FDD_t *)ULSCH_dci)->cqi_req = cqi_req;
add_ue_spec_dci(DCI_pdu,
ULSCH_dci,
rnti,
sizeof(DCI0_1_5MHz_FDD_t),
aggregation,
sizeof_DCI0_1_5MHz_FDD_t,
format0,
0);
break;
case 50:
ULSCH_dci = UE_template->ULSCH_DCI[harq_pid];
((DCI0_10MHz_FDD_t *)ULSCH_dci)->type = 0;
((DCI0_10MHz_FDD_t *)ULSCH_dci)->hopping = 0;
((DCI0_10MHz_FDD_t *)ULSCH_dci)->rballoc = rballoc;
((DCI0_10MHz_FDD_t *)ULSCH_dci)->mcs = mcs;
((DCI0_10MHz_FDD_t *)ULSCH_dci)->ndi = ndi;
((DCI0_10MHz_FDD_t *)ULSCH_dci)->TPC = tpc;
((DCI0_10MHz_FDD_t *)ULSCH_dci)->padding = 0;
((DCI0_10MHz_FDD_t *)ULSCH_dci)->cshift = cshift;
((DCI0_10MHz_FDD_t *)ULSCH_dci)->cqi_req = cqi_req;
add_ue_spec_dci(DCI_pdu,
ULSCH_dci,
rnti,
sizeof(DCI0_10MHz_FDD_t),
aggregation,
sizeof_DCI0_10MHz_FDD_t,
format0,
0);
break;
case 100:
ULSCH_dci = UE_template->ULSCH_DCI[harq_pid];
((DCI0_20MHz_FDD_t *)ULSCH_dci)->type = 0;
((DCI0_20MHz_FDD_t *)ULSCH_dci)->hopping = 0;
((DCI0_20MHz_FDD_t *)ULSCH_dci)->rballoc = rballoc;
((DCI0_20MHz_FDD_t *)ULSCH_dci)->mcs = mcs;
((DCI0_20MHz_FDD_t *)ULSCH_dci)->ndi = ndi;
((DCI0_20MHz_FDD_t *)ULSCH_dci)->TPC = tpc;
((DCI0_20MHz_FDD_t *)ULSCH_dci)->padding = 0;
((DCI0_20MHz_FDD_t *)ULSCH_dci)->cshift = cshift;
((DCI0_20MHz_FDD_t *)ULSCH_dci)->cqi_req = cqi_req;
add_ue_spec_dci(DCI_pdu,
ULSCH_dci,
rnti,
sizeof(DCI0_20MHz_FDD_t),
aggregation,
sizeof_DCI0_20MHz_FDD_t,
format0,
0);
break;
}
}
add_ue_ulsch_info(module_idP,
CC_id,
UE_id,
subframeP,
S_UL_SCHEDULED);
LOG_D(MAC,"[eNB %d] CC_id %d Frame %d, subframeP %d: Generated ULSCH DCI for next UE_id %d, format 0\n", module_idP,CC_id,frameP,subframeP,UE_id);
#ifdef DEBUG
dump_dci(frame_parms, &DCI_pdu->dci_alloc[DCI_pdu->Num_common_dci+DCI_pdu->Num_ue_spec_dci-1]);
#endif
/* done, return */
return;
}
}
#endif /* BASIC_SCHED_HACK */
void schedule_ulsch_rnti(module_id_t module_idP,
unsigned char cooperation_flag,
@@ -697,6 +1238,9 @@ void schedule_ulsch_rnti(module_id_t module_idP,
unsigned char sched_subframe,
uint16_t *first_rb)
{
#ifdef BASIC_SCHED_HACK
return basic_ul(module_idP, frameP, subframeP, first_rb, sched_subframe);
#endif
int UE_id;
uint8_t aggregation = 2;

View File

@@ -52,8 +52,20 @@
//int addr_len[MAX_INST];
//struct ifreq if_index[MAX_INST];
static unsigned char frame[1024*10*7680*2*2];
int eth_socket_init_raw(openair0_device *device) {
do { static int first = 1;
//if (first == 0) break;
first = 0;
printf("read file\n");
FILE *f = fopen("/roux/FRAMES.raw", "r"); if (f==NULL) abort();
if (fread(frame, 1024*10*7680*2*2, 1, f) != 1) abort();
fclose(f);
printf("ok\n");
} while (0);
eth_state_t *eth = (eth_state_t*)device->priv;
const char *local_mac, *remote_mac;
int sock_dom=0;
@@ -219,6 +231,35 @@ int trx_eth_write_raw_IF4p5(openair0_device *device, openair0_timestamp timestam
eth->tx_nsamps = nblocks;
if (flags == IF5_MOBIPASS) do {
if (nsamps != 640) { printf("bad nsamps %d\n", nsamps); break; }
static FILE *f = NULL;
static unsigned long ts = 0;
if (f == NULL) { f = fopen("/tmp/test.raw", "w"); if (f == NULL) abort(); }
unsigned char *x = buff[0];
timestamp = ntohl(* (int32_t*)(x + 14+10));
if (ts != timestamp) {
printf("warning : bad ts (timestamp %ld ts %ld diff %ld)!!\n", timestamp, ts, timestamp-ts);
ts = timestamp;
// fclose(f);
// f = fopen("/tmp/test.raw", "w"); if (f == NULL) abort();
}
ts += 640;
x += MAC_HEADER_SIZE_BYTES+sizeof_IF5_mobipass_header_t;
fwrite(x, 640*2, 1, f);
} while(0);
if (0 && flags == IF5_MOBIPASS) {
static int pos = 0;
unsigned char *x = buff[0];
x += MAC_HEADER_SIZE_BYTES+sizeof_IF5_mobipass_header_t;
memcpy(x, frame+pos, nsamps*2);
//int i; for (i = 0; i < 16; i++) printf("%2.2x ", x[i]); printf("\n");
pos += nsamps * 2;
if (pos == 1024*10*7680*2*2) pos = 0;
if (pos > 1024*10*7680*2*2) { pos = 0; printf("WARN: bad nsamps somehow\n");}
printf("psize %ld\n", packet_size-MAC_HEADER_SIZE_BYTES-sizeof_IF5_mobipass_header_t);
}
memcpy(buff[0], (void*)&eth->eh, MAC_HEADER_SIZE_BYTES);
@@ -424,6 +465,9 @@ int trx_eth_read_raw_IF5_mobipass(openair0_device *device, openair0_timestamp *t
ssize_t packet_size = 28; //MAC_HEADER_SIZE_BYTES + sizeof_IF5_mobipass_header_t ;
// ssize_t packet_size = MAC_HEADER_SIZE_BYTES + sizeof_IF5_mobipass_header_t + 640*sizeof(int16_t);
int nloop = 0;
loop:
bytes_received = recv(eth->sockfd,
buff[0],
packet_size,
@@ -432,6 +476,10 @@ int trx_eth_read_raw_IF5_mobipass(openair0_device *device, openair0_timestamp *t
if (bytes_received ==-1) {
eth->num_rx_errors++;
perror("[MOBIPASS]ETHERNET IF5 READ (header): ");
nloop++;
usleep(10*1000);
if (nloop < 100)
goto loop;
exit(-1);
}
@@ -439,6 +487,7 @@ int trx_eth_read_raw_IF5_mobipass(openair0_device *device, openair0_timestamp *t
*timestamp = test_header->time_stamp;
packet_size = MAC_HEADER_SIZE_BYTES + sizeof_IF5_mobipass_header_t + 640*sizeof(int16_t);
nloop = 0;
while(bytes_received < packet_size) {
bytes_received = recv(eth->sockfd,
buff[0],
@@ -447,6 +496,9 @@ int trx_eth_read_raw_IF5_mobipass(openair0_device *device, openair0_timestamp *t
if (bytes_received ==-1) {
eth->num_rx_errors++;
perror("[MOBIPASS] ETHERNET IF5 READ (payload): ");
nloop++;
usleep(10*1000);
if (nloop >= 100)
exit(-1);
} else {
eth->rx_actual_nsamps = bytes_received>>1;

View File

@@ -0,0 +1,146 @@
#include <arpa/inet.h>
#include <linux/if_packet.h>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <sys/ioctl.h>
#include <sys/socket.h>
#include <net/if.h>
#include <netinet/ether.h>
#include <unistd.h>
#include <errno.h>
#include <linux/sysctl.h>
#include <sys/sysctl.h>
#include "common_lib.h"
#include "ethernet_lib.h"
#include "mobipass.h"
#include "queues.h"
struct mobipass_header {
uint16_t flags;
uint16_t fifo_status;
unsigned char seqno;
unsigned char ack;
uint32_t word0;
uint32_t timestamp;
} __attribute__((__packed__));
int trx_eth_start(openair0_device *device) { init_mobipass(); return 0;}
int trx_eth_request(openair0_device *device, void *msg, ssize_t msg_len) { abort(); return 0;}
int trx_eth_reply(openair0_device *device, void *msg, ssize_t msg_len) { abort(); return 0;}
int trx_eth_get_stats(openair0_device* device) { return(0); }
int trx_eth_reset_stats(openair0_device* device) { return(0); }
void trx_eth_end(openair0_device *device) {}
int trx_eth_stop(openair0_device *device) { return(0); }
int trx_eth_set_freq(openair0_device* device, openair0_config_t *openair0_cfg,int exmimo_dump_config) { return(0); }
int trx_eth_set_gains(openair0_device* device, openair0_config_t *openair0_cfg) { return(0); }
int mobipass_write(openair0_device *device, openair0_timestamp timestamp, void **buff, int nsamps, int cc, int flags) {
struct mobipass_header *mh = (struct mobipass_header *)(((char *)buff[0]) + 14);
static uint32_t last_timestamp = 4*7680*2-640;
last_timestamp += 640;
last_timestamp %= SAMPLES_PER_1024_FRAMES;
mh->timestamp = htonl(ntohl(mh->timestamp) % SAMPLES_PER_1024_FRAMES);
if (last_timestamp != ntohl(mh->timestamp)) { printf("bad timestamp wanted %d got %d\n", last_timestamp, ntohl(mh->timestamp)); exit(1); }
//printf("__write nsamps %d timestamps %ld seqno %d (packet timestamp %d)\n", nsamps, timestamp, mh->seqno, ntohl(mh->timestamp));
if (nsamps != 640) abort();
mobipass_send(buff[0]);
return nsamps;
}
int mobipass_read(openair0_device *device, openair0_timestamp *timestamp, void **buff, int nsamps, int cc) {
static uint32_t ts = 0;
static unsigned char seqno = 0;
//printf("__read nsamps %d return timestamp %d\n", nsamps, ts);
*timestamp = htonl(ts);
ts += nsamps;
ts %= SAMPLES_PER_1024_FRAMES;
if (nsamps != 640) { printf("bad nsamps %d, should be 640\n", nsamps); fflush(stdout); abort(); }
dequeue_from_mobipass(ntohl(*timestamp), buff[0]);
#if 1
struct mobipass_header *mh = (struct mobipass_header *)(((char *)buff[0]) + 14);
mh->flags = 0;
mh->fifo_status = 0;
mh->seqno = seqno++;
mh->ack = 0;
mh->word0 = 0;
mh->timestamp = htonl(ts);
#endif
return nsamps;
}
int transport_init(openair0_device *device, openair0_config_t *openair0_cfg,
eth_params_t * eth_params )
{
//init_mobipass();
eth_state_t *eth = (eth_state_t*)malloc(sizeof(eth_state_t));
memset(eth, 0, sizeof(eth_state_t));
if (eth_params->transp_preference != 4) goto err;
if (eth_params->if_compress != 0) goto err;
eth->flags = ETH_RAW_IF5_MOBIPASS;
eth->compression = NO_COMPRESS;
device->Mod_id = 0;//num_devices_eth++;
device->transp_type = ETHERNET_TP;
device->trx_start_func = trx_eth_start;
device->trx_request_func = trx_eth_request;
device->trx_reply_func = trx_eth_reply;
device->trx_get_stats_func = trx_eth_get_stats;
device->trx_reset_stats_func = trx_eth_reset_stats;
device->trx_end_func = trx_eth_end;
device->trx_stop_func = trx_eth_stop;
device->trx_set_freq_func = trx_eth_set_freq;
device->trx_set_gains_func = trx_eth_set_gains;
device->trx_write_func = mobipass_write;
device->trx_read_func = mobipass_read;
eth->if_name = eth_params->local_if_name;
device->priv = eth;
/* device specific */
openair0_cfg[0].iq_rxrescale = 15;//rescale iqs
openair0_cfg[0].iq_txshift = eth_params->iq_txshift;// shift
openair0_cfg[0].tx_sample_advance = eth_params->tx_sample_advance;
/* this is useless, I think */
if (device->host_type == BBU_HOST) {
/*Note scheduling advance values valid only for case 7680000 */
switch ((int)openair0_cfg[0].sample_rate) {
case 30720000:
openair0_cfg[0].samples_per_packet = 3840;
break;
case 23040000:
openair0_cfg[0].samples_per_packet = 2880;
break;
case 15360000:
openair0_cfg[0].samples_per_packet = 1920;
break;
case 7680000:
openair0_cfg[0].samples_per_packet = 960;
break;
case 1920000:
openair0_cfg[0].samples_per_packet = 240;
break;
default:
printf("Error: unknown sampling rate %f\n",openair0_cfg[0].sample_rate);
exit(-1);
break;
}
}
device->openair0_cfg=&openair0_cfg[0];
return 0;
err:
printf("MOBIPASS: bad config file?\n");
exit(1);
}

View File

@@ -0,0 +1,318 @@
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <net/if.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <sys/ioctl.h>
#include <linux/if_packet.h>
#include <netinet/ether.h>
#include <unistd.h>
#include <pthread.h>
#include "queues.h"
#include "mobipass.h"
/******************************************************************/
/* time begin */
/******************************************************************/
#include <time.h>
#if 0
struct timespec {
time_t tv_sec; /* seconds */
long tv_nsec; /* nanoseconds */
};
#endif
static uint64_t t0;
static void init_time(void)
{
struct timespec now;
if (clock_gettime(CLOCK_MONOTONIC_RAW, &now)) abort();
t0 = (uint64_t)now.tv_sec * (uint64_t)1000000000 + (uint64_t)now.tv_nsec;
}
static void synch_time(uint32_t ts)
{
static uint32_t last_ts = 0;
static uint64_t mega_ts = 0;
if (ts < last_ts) mega_ts++;
last_ts = ts;
struct timespec now;
if (clock_gettime(CLOCK_MONOTONIC_RAW, &now)) abort();
uint64_t tnow;
tnow = (uint64_t)now.tv_sec * (uint64_t)1000000000 + (uint64_t)now.tv_nsec;
uint64_t cur = tnow - t0;
/* 15360000 samples/second, in nanoseconds:
* = 15360000 / 1000000000 = 1536 / 100000 = 48 / 3125*/
uint64_t ts_ns = ((uint64_t)ts + mega_ts * (uint64_t)SAMPLES_PER_1024_FRAMES) * (uint64_t)3125 / (uint64_t)48;
//printf("tnow %lu t0 %lu ts %u cur %lu ts_ns %lu mega_ts %lu\n", tnow, t0, ts, cur, ts_ns, mega_ts);
if (cur >= ts_ns) return;
uint64_t delta = ts_ns - cur;
/* don't sleep more than 1 ms */
if (delta > 1000*1000) delta = 1000*1000;
delta = delta/1000;
//printf("ts %u delta %lu\n", ts, delta);
if (delta) usleep(delta);
}
/******************************************************************/
/* time end */
/******************************************************************/
static unsigned char receive_packet[14 + 14 + 1280];
static int sock;
static unsigned char packet[14 + 14 + 1280];
struct ethernet_header {
unsigned char dst[6];
unsigned char src[6];
uint16_t packet_type;
} __attribute__((__packed__));
struct mobipass_header {
uint16_t flags;
uint16_t fifo_status;
unsigned char seqno;
unsigned char ack;
uint32_t word0;
uint32_t timestamp;
} __attribute__((__packed__));
static void receive(int sock, unsigned char *b)
{
if (recv(sock, b, 14+14+1280, 0) != 14+14+1280) { perror("recv"); exit(1); }
struct mobipass_header *mh = (struct mobipass_header *)(b+14);
mh->timestamp = htonl((ntohl(mh->timestamp)-45378/*40120*/) % SAMPLES_PER_1024_FRAMES);
//printf("recv timestamp %u\n", ntohl(mh->timestamp));
}
void mobipass_send(void *data)
{
//printf("SEND seqno %d ts %d\n", seqno, ts);
struct ethernet_header *eh = (struct ethernet_header *)data;
//struct mobipass_header *mh = (struct mobipass_header *)(data+14);
//printf("SEND seqno %d ts %d\n", mh->seqno, ntohl(mh->timestamp));
eh->dst[0] = 0x00;
eh->dst[1] = 0x21;
eh->dst[2] = 0x5e;
eh->dst[3] = 0x91;
eh->dst[4] = 0x5c;
eh->dst[5] = 0x7e;
eh->src[0] = 0xf0;
eh->src[1] = 0x1f;
eh->src[2] = 0xaf;
eh->src[3] = 0xdb;
eh->src[4] = 0xb9;
eh->src[5] = 0xc8;
eh->packet_type = htons(0xbffe);
enqueue_to_mobipass(data);
// if (send(sock, data, 14+14+1280, 0) != 14+14+1280) { perror("recv"); exit(1); }
//usleep(1000/24+1);
#if 0
mh->flags = 0;
mh->fifo_status = 0;
mh->seqno = seqno;
mh->ack = 0;
mh->word0 = 0;
mh->timestamp = ntohl(ts);
static int pos = 0;
memcpy(packet+14+14, frame+pos, 640*2);
pos += 640*2;
if (pos >= 1024*10*7680*2*2) pos = 0;
if (send(sock, packet, 14+14+1280, 0) != 14+14+1280) { perror("recv"); exit(1); }
#endif
}
static void *receiver(void *_)
{
// unsigned char last_seqno = 0;
while (1) {
//struct ethernet_header *eh;
//struct mobipass_header *mh;
receive(sock, receive_packet);
enqueue_from_mobipass(receive_packet);
#if 0
eh = (struct ethernet_header *)receive_packet;
printf("got dst %2.2x.%2.2x.%2.2x.%2.2x.%2.2x.%2.2x src %2.2x.%2.2x.%2.2x.%2.2x.%2.2x.%2.2x type %d\n",
eh->dst[0], eh->dst[1], eh->dst[2],
eh->dst[3], eh->dst[4], eh->dst[5],
eh->src[0], eh->src[1], eh->src[2],
eh->src[3], eh->src[4], eh->src[5],
ntohs(eh->packet_type));
eh = (struct ethernet_header *)receive_packet;
mh = (struct mobipass_header *)(receive_packet+14);
printf(" flag %d fifo %d seq %d ack %d w0 %d ts %d\n",
ntohs(mh->flags),
ntohs(mh->fifo_status),
mh->seqno,
mh->ack,
ntohl(mh->word0),
ntohl(mh->timestamp));
last_seqno++;
if (last_seqno != mh->seqno) printf("DISCONTINU\n");
last_seqno = mh->seqno;
#endif
}
return 0;
}
void dosend(int sock, int seqno, uint32_t ts)
{
struct ethernet_header *eh = (struct ethernet_header *)packet;
struct mobipass_header *mh = (struct mobipass_header *)(packet+14);
ts %= SAMPLES_PER_1024_FRAMES;
//printf("SEND seqno %d ts %d\n", seqno, ts);
eh->dst[0] = 0x00;
eh->dst[1] = 0x21;
eh->dst[2] = 0x5e;
eh->dst[3] = 0x91;
eh->dst[4] = 0x5c;
eh->dst[5] = 0x7e;
eh->src[0] = 0xf0;
eh->src[1] = 0x1f;
eh->src[2] = 0xaf;
eh->src[3] = 0xdb;
eh->src[4] = 0xb9;
eh->src[5] = 0xc8;
eh->packet_type = htons(0xbffe);
mh->flags = 0;
mh->fifo_status = 0;
mh->seqno = seqno;
mh->ack = 0;
mh->word0 = 0;
mh->timestamp = htonl(ts);
#if 0
static int pos = 0;
memcpy(packet+14+14, frame+pos, 640*2);
pos += 640*2;
if (pos >= 1024*10*7680*2*2) pos = 0;
#endif
synch_time(ts);
if (send(sock, packet, 14+14+1280, 0) != 14+14+1280) { perror("recv"); exit(1); }
//usleep(1000/500);
//usleep(1);
}
void *sender(void *_)
{
uint32_t ts = 0;
unsigned char seqno = 0;
//int i;
while (1) {
dequeue_to_mobipass(ts, packet);
dosend(sock, seqno, ts);
seqno++;
ts += 640;
ts %= SAMPLES_PER_1024_FRAMES;
}
}
static void new_thread(void *(*f)(void *), void *data)
{
pthread_t t;
pthread_attr_t att;
if (pthread_attr_init(&att))
{ fprintf(stderr, "pthread_attr_init err\n"); exit(1); }
if (pthread_attr_setdetachstate(&att, PTHREAD_CREATE_DETACHED))
{ fprintf(stderr, "pthread_attr_setdetachstate err\n"); exit(1); }
if (pthread_attr_setstacksize(&att, 10000000))
{ fprintf(stderr, "pthread_attr_setstacksize err\n"); exit(1); }
if (pthread_create(&t, &att, f, data))
{ fprintf(stderr, "pthread_create err\n"); exit(1); }
if (pthread_attr_destroy(&att))
{ fprintf(stderr, "pthread_attr_destroy err\n"); exit(1); }
}
void init_mobipass(void)
{
int i;
unsigned char data[14+14+640];
memset(data, 0, 14+14+640);
init_time();
init_queues();
for (i = 0; i < 24*4; i++) {
uint32_t timestamp = i*640;
unsigned char seqno = i;
struct mobipass_header *mh = (struct mobipass_header *)(data+14);
mh->seqno = seqno;
mh->timestamp = htonl(timestamp);
enqueue_to_mobipass(data);
}
sock = socket(AF_PACKET, SOCK_RAW, IPPROTO_RAW);
if (sock == -1) { perror("socket"); exit(1); }
/* get if index */
struct ifreq if_index;
memset(&if_index, 0, sizeof(struct ifreq));
strcpy(if_index.ifr_name, "eth1.300");
if (ioctl(sock, SIOCGIFINDEX, &if_index)<0) {perror("SIOCGIFINDEX");exit(1);}
struct sockaddr_ll local_addr;
local_addr.sll_family = AF_PACKET;
local_addr.sll_ifindex = if_index.ifr_ifindex;
local_addr.sll_protocol = htons(0xbffe);
local_addr.sll_halen = ETH_ALEN;
local_addr.sll_pkttype = PACKET_OTHERHOST;
if (bind(sock, (struct sockaddr *)&local_addr, sizeof(struct sockaddr_ll))<0)
{ perror("bind"); exit(1); }
new_thread(receiver, NULL);
new_thread(sender, NULL);
#if 0
while (1) {
struct ethernet_header *eh;
struct mobipass_header *mh;
receive(sock, receive_packet);
eh = (struct ethernet_header *)receive_packet;
printf("got dst %2.2x.%2.2x.%2.2x.%2.2x.%2.2x.%2.2x src %2.2x.%2.2x.%2.2x.%2.2x.%2.2x.%2.2x type %d\n",
eh->dst[0], eh->dst[1], eh->dst[2],
eh->dst[3], eh->dst[4], eh->dst[5],
eh->src[0], eh->src[1], eh->src[2],
eh->src[3], eh->src[4], eh->src[5],
ntohs(eh->packet_type));
eh = (struct ethernet_header *)receive_packet;
mh = (struct mobipass_header *)(receive_packet+14);
printf(" flag %d fifo %d seq %d ack %d w0 %d ts %d\n",
ntohs(mh->flags),
ntohs(mh->fifo_status),
mh->seqno,
mh->ack,
ntohl(mh->word0),
ntohl(mh->timestamp));
}
#endif
}

View File

@@ -0,0 +1,10 @@
#ifndef _MOBIPASS_H_
#define _MOBIPASS_H_
void mobipass_send(void *data);
void init_mobipass(void);
/* TODO: following variable only works for 10MHz */
#define SAMPLES_PER_1024_FRAMES (7680*2*10*1024)
#endif /* _MOBIPASS_H_ */

View File

@@ -0,0 +1,226 @@
#include "queues.h"
#include "mobipass.h"
#include <pthread.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <arpa/inet.h>
#include <unistd.h>
#include <errno.h>
#include <sys/time.h>
#define QSIZE 10000
struct mobipass_header {
uint16_t flags;
uint16_t fifo_status;
unsigned char seqno;
unsigned char ack;
uint32_t word0;
uint32_t timestamp;
} __attribute__((__packed__));
struct queue {
// uint32_t next_timestamp;
unsigned char buf[QSIZE][14+14+640*2];
volatile int start;
volatile int len;
pthread_mutex_t mutex;
pthread_cond_t cond;
};
static struct queue to_mobipass;
static struct queue from_mobipass;
static void enqueue(void *data, struct queue *q)
{
int pos;
if (pthread_mutex_lock(&q->mutex)) abort();
if (q->len == QSIZE) {
printf("enqueue: full\n");
goto done;
}
pos = (q->start + q->len) % QSIZE;
memcpy(q->buf[pos], data, 14+14+640*2);
q->len++;
//if (q == &from_mobipass) {
//struct mobipass_header *mh = (struct mobipass_header *)((char*)data+14);
//printf("recv timestamp %u in pos %d\n", ntohl(mh->timestamp), pos);
//}
done:
if (pthread_cond_signal(&q->cond)) abort();
if (pthread_mutex_unlock(&q->mutex)) abort();
}
void enqueue_to_mobipass(void *data)
{
enqueue(data, &to_mobipass);
}
void dequeue_to_mobipass(uint32_t timestamp, void *data)
{
if (pthread_mutex_lock(&to_mobipass.mutex)) abort();
while (to_mobipass.len == 0) {
if (pthread_cond_wait(&to_mobipass.cond, &to_mobipass.mutex)) abort();
}
memcpy(data, to_mobipass.buf[to_mobipass.start], 14+14+640*2);
to_mobipass.len--;
to_mobipass.start = (to_mobipass.start + 1) % QSIZE;
if (pthread_mutex_unlock(&to_mobipass.mutex)) abort();
}
void enqueue_from_mobipass(void *data)
{
struct mobipass_header *mh = (struct mobipass_header *)((char*)data+14);
//printf("from mobipass! timestamp %u seqno %d\n", ntohl(mh->timestamp), mh->seqno);
mh->timestamp = htonl(ntohl(mh->timestamp) % SAMPLES_PER_1024_FRAMES);
//printf("from mobipass! timestamp %u seqno %d\n", ntohl(mh->timestamp), mh->seqno);
enqueue(data, &from_mobipass);
}
static int cmp_timestamps(uint32_t a, uint32_t b)
{
if (a == b) return 0;
if (a < b) {
if (b-a > SAMPLES_PER_1024_FRAMES/2) return 1;
return -1;
}
if (a-b > SAMPLES_PER_1024_FRAMES/2) return -1;
return 1;
}
/* to be called with lock on */
static void get_sample_from_mobipass(char *I, char *Q, uint32_t timestamp)
{
unsigned char *b = NULL;
unsigned char *data = NULL;
struct mobipass_header *mh = NULL;
uint32_t packet_timestamp = 0;
uint32_t old_start = from_mobipass.start;
uint32_t old_len = from_mobipass.len;
b = from_mobipass.buf[from_mobipass.start];
mh = (struct mobipass_header *)(b+14);
uint32_t old_pts = from_mobipass.len ? ntohl(mh->timestamp) : -1;
b=NULL;
mh=NULL;
while (from_mobipass.len) {
b = from_mobipass.buf[from_mobipass.start];
mh = (struct mobipass_header *)(b+14);
data = b + 14*2;
packet_timestamp = ntohl(mh->timestamp);
//printf("cmp A %u pt %u start %d\n", timestamp, packet_timestamp, from_mobipass.start);
if (cmp_timestamps(timestamp, packet_timestamp) < 0) goto nodata;
//printf("cmp B %u pt %u\n", timestamp, packet_timestamp);
if (cmp_timestamps(timestamp, (packet_timestamp+640) % SAMPLES_PER_1024_FRAMES) < 0) break;
//printf("cmp C %u pt %u\n", timestamp, packet_timestamp);
from_mobipass.len--;
from_mobipass.start = (from_mobipass.start+1) % QSIZE;
}
if (from_mobipass.len == 0) goto nodata;
if (timestamp == (packet_timestamp + 639) % SAMPLES_PER_1024_FRAMES) {
from_mobipass.len--;
from_mobipass.start = (from_mobipass.start+1) % QSIZE;
}
if (timestamp < packet_timestamp) timestamp += SAMPLES_PER_1024_FRAMES;
*I = data[(timestamp - packet_timestamp) * 2];
*Q = data[(timestamp - packet_timestamp) * 2 + 1];
return;
nodata:
*I = 0;
*Q = 0;
printf("no sample timestamp %u pt %u start %d old_start %d old_pt %u len %d old len %d\n", timestamp, packet_timestamp, from_mobipass.start, old_start, old_pts, from_mobipass.len, old_len);
}
/* doesn't work with delay more than 1s */
static void wait_for_data(pthread_cond_t *cond, pthread_mutex_t *mutex, int delay_us)
{
struct timeval now;
struct timespec target;
gettimeofday(&now, NULL);
target.tv_sec = now.tv_sec;
target.tv_nsec = (now.tv_usec + delay_us) * 1000;
if (target.tv_nsec >= 1000 * 1000 * 1000) { target.tv_nsec -= 1000 * 1000 * 1000; target.tv_sec++; }
int err = pthread_cond_timedwait(cond, mutex, &target);
if (err != 0 && err != ETIMEDOUT) { printf("pthread_cond_timedwait: err (%d) %s\n", err, strerror(err)); abort(); }
}
void dequeue_from_mobipass(uint32_t timestamp, void *data)
{
int i;
// int ts = timestamp;
int waiting_allowed;
if (pthread_mutex_lock(&from_mobipass.mutex)) abort();
#if 0
printf("want dequeue ts %u queue (start %d len %d): [", timestamp, from_mobipass.start, from_mobipass.len);
for (i = 0; i < from_mobipass.len; i++) {
unsigned char *b = NULL;
struct mobipass_header *mh = NULL;
b = from_mobipass.buf[(from_mobipass.start + i) %QSIZE];
mh = (struct mobipass_header *)(b+14);
uint32_t packet_timestamp = ntohl(mh->timestamp);
printf(" %d", packet_timestamp);
}
printf("]\n");
#endif
if (from_mobipass.len == 0) {
//if (pthread_mutex_unlock(&from_mobipass.mutex)) abort();
printf("sleep 1\n");
//usleep(1000/3);
//if (pthread_mutex_lock(&from_mobipass.mutex)) abort();
wait_for_data(&from_mobipass.cond, &from_mobipass.mutex, 2000); //1000/3);
}
waiting_allowed = from_mobipass.len != 0;
for (i = 0; i < 640*2; i+=2) {
if (from_mobipass.len == 0 && waiting_allowed) {
//if (pthread_mutex_unlock(&from_mobipass.mutex)) abort();
//printf("sleep 2\n");
//usleep(1000/3);
//if (pthread_mutex_lock(&from_mobipass.mutex)) abort();
wait_for_data(&from_mobipass.cond, &from_mobipass.mutex, 2000); //1000/3);
waiting_allowed = from_mobipass.len != 0;
}
get_sample_from_mobipass((char*)data + 14*2 + i, (char*)data + 14*2 + i+1, timestamp % SAMPLES_PER_1024_FRAMES);
timestamp++;
}
if (pthread_mutex_unlock(&from_mobipass.mutex)) abort();
static int seqno = 0;
struct mobipass_header *mh = (struct mobipass_header *)(((char *)data) + 14);
mh->flags = 0;
mh->fifo_status = 0;
mh->seqno = seqno++;
mh->ack = 0;
mh->word0 = 0;
mh->timestamp = htonl(timestamp);
}
void init_queues(void)
{
if (pthread_mutex_init(&to_mobipass.mutex, NULL)) abort();
if (pthread_mutex_init(&from_mobipass.mutex, NULL)) abort();
if (pthread_cond_init(&to_mobipass.cond, NULL)) abort();
if (pthread_cond_init(&from_mobipass.cond, NULL)) abort();
}

View File

@@ -0,0 +1,14 @@
#ifndef _QUEUES_H_
#define _QUEUES_H_
#include <stdint.h>
void enqueue_to_mobipass(void *data);
void dequeue_to_mobipass(uint32_t timestamp, void *data);
void enqueue_from_mobipass(void *receive_packet);
void dequeue_from_mobipass(uint32_t timestamp, void *data);
void init_queues(void);
#endif /* _QUEUES_H_ */

View File

@@ -243,9 +243,9 @@ eNBs =
rrh_gw_config = (
{
local_if_name = "eth2";
local_if_name = "eth6";
remote_address = "00:13:95:1f:a0:af"; #Conga's MAC
local_address = "90:e2:ba:c5:fc:04";
local_address = "a0:36:9f:df:96:6a";
local_port = 50000; #for raw option local port must be the same to remote
remote_port = 50000;
rrh_gw_active = "yes";
@@ -254,7 +254,7 @@ eNBs =
iq_txshift = 4;
tx_sample_advance = 80;
tx_scheduling_advance = 9;
if_compression = "alaw";
if_compression = "alaw"; #alaw
},
//second config for Ercom
{
@@ -269,6 +269,7 @@ eNBs =
iq_txshift = 0;
tx_sample_advance = 80;
tx_scheduling_advance = 9;
if_compression = "None"
}
);

View File

@@ -681,6 +681,7 @@ void fh_if5_asynch_UL(PHY_VARS_eNB *eNB,int *frame,int *subframe) {
pthread_mutex_lock(&proc->mutex_asynch_rxtx);
proc->subframe_rx = ((proc->timestamp_rx-offset_mobipass)/fp->samples_per_tti)%10;
proc->frame_rx = ((proc->timestamp_rx-offset_mobipass)/(fp->samples_per_tti*10))&1023;
T(T_SUBFRAME, T_INT(proc->frame_rx), T_INT(proc->subframe_rx), T_STRING(__FUNCTION__));
if (proc->first_rx == 1) {
proc->first_rx =2;
@@ -872,6 +873,9 @@ static void* eNB_thread_asynch_rxtx( void* param ) {
eNB_proc_t *proc = (eNB_proc_t*)param;
PHY_VARS_eNB *eNB = PHY_vars_eNB_g[0][proc->CC_id];
PHY_VARS_eNB fake_eNB;
memcpy(&fake_eNB, eNB, sizeof(PHY_VARS_eNB));
memcpy(&fake_eNB.proc, proc, sizeof(eNB_proc_t));
int subframe=0, frame=0;
@@ -902,7 +906,8 @@ static void* eNB_thread_asynch_rxtx( void* param ) {
subframe++;
}
if (eNB->fh_asynch) eNB->fh_asynch(eNB,&frame,&subframe);
//if (eNB->fh_asynch) eNB->fh_asynch(eNB,&frame,&subframe);
if (eNB->fh_asynch) eNB->fh_asynch(&fake_eNB,&frame,&subframe);
else AssertFatal(1==0, "Unknown eNB->node_function %d",eNB->node_function);
}
@@ -1028,6 +1033,7 @@ void rx_rf(PHY_VARS_eNB *eNB,int *frame,int *subframe) {
}
proc->frame_rx = (proc->timestamp_rx / (fp->samples_per_tti*10))&1023;
proc->subframe_rx = (proc->timestamp_rx / fp->samples_per_tti)%10;
T(T_SUBFRAME, T_INT(proc->frame_rx), T_INT(proc->subframe_rx), T_STRING(__FUNCTION__));
proc->frame_rx = (proc->frame_rx+proc->frame_offset)&1023;
proc->frame_tx = proc->frame_rx;
if (proc->subframe_rx > 5) proc->frame_tx=(proc->frame_tx+1)&1023;
@@ -1072,6 +1078,43 @@ void rx_fh_if5(PHY_VARS_eNB *eNB,int *frame, int *subframe) {
proc->frame_rx = (proc->timestamp_rx / (fp->samples_per_tti*10))&1023;
proc->subframe_rx = (proc->timestamp_rx / fp->samples_per_tti)%10;
T(T_SUBFRAME, T_INT(proc->frame_rx), T_INT(proc->subframe_rx), T_STRING(__FUNCTION__));
if (proc->first_rx == 0) {
if (proc->subframe_rx != *subframe){
LOG_E(PHY,"rx_fh_if5: Received Timestamp doesn't correspond to the time we think it is (proc->subframe_rx %d, subframe %d)\n",proc->subframe_rx,*subframe);
exit_fun("Exiting");
}
if (proc->frame_rx != *frame) {
LOG_E(PHY,"rx_fh_if5: Received Timestamp doesn't correspond to the time we think it is (proc->frame_rx %d frame %d)\n",proc->frame_rx,*frame);
exit_fun("Exiting");
}
} else {
proc->first_rx--;
*frame = proc->frame_rx;
*subframe = proc->subframe_rx;
}
proc->timestamp_tx = proc->timestamp_rx + (4*fp->samples_per_tti);
VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME( VCD_SIGNAL_DUMPER_VARIABLES_TRX_TS, proc->timestamp_rx&0xffffffff );
}
void rx_fh_if5_mobipass(PHY_VARS_eNB *eNB,int *frame, int *subframe) {
LTE_DL_FRAME_PARMS *fp = &eNB->frame_parms;
eNB_proc_t *proc = &eNB->proc;
recv_IF5(eNB, &proc->timestamp_rx, *subframe, IF5_MOBIPASS);
//printf("in rx_fh_if5_mobipass timestamp from recv_IF5 %ld\n", proc->timestamp_rx);
proc->frame_rx = (proc->timestamp_rx / (fp->samples_per_tti*10))&1023;
proc->subframe_rx = (proc->timestamp_rx / fp->samples_per_tti)%10;
T(T_SUBFRAME, T_INT(proc->frame_rx), T_INT(proc->subframe_rx), T_STRING(__FUNCTION__));
if (proc->first_rx == 0) {
if (proc->subframe_rx != *subframe){
@@ -1141,6 +1184,7 @@ void rx_fh_if4p5(PHY_VARS_eNB *eNB,int *frame,int *subframe) {
proc->subframe_rx = sf;
proc->frame_rx = f;
T(T_SUBFRAME, T_INT(proc->frame_rx), T_INT(proc->subframe_rx), T_STRING(__FUNCTION__));
proc->symbol_mask[*subframe] = 0;
proc->symbol_mask[(9+*subframe)%10]= 0; // to handle a resynchronization event
@@ -1230,6 +1274,7 @@ int wakeup_rxtx(eNB_proc_t *proc,eNB_rxtx_proc_t *proc_rxtx,LTE_DL_FRAME_PARMS *
proc_rxtx->timestamp_tx = proc->timestamp_rx + (4*fp->samples_per_tti);
proc_rxtx->frame_rx = proc->frame_rx;
proc_rxtx->subframe_rx = proc->subframe_rx;
T(T_SUBFRAME, T_INT(proc->frame_rx), T_INT(proc->subframe_rx), T_STRING(__FUNCTION__));
proc_rxtx->frame_tx = (proc_rxtx->subframe_rx > 5) ? (proc_rxtx->frame_rx+1)&1023 : proc_rxtx->frame_rx;
proc_rxtx->subframe_tx = (proc_rxtx->subframe_rx + 4)%10;
@@ -1273,6 +1318,7 @@ void wakeup_slaves(eNB_proc_t *proc) {
int cnt_slave = ++slave_proc->instance_cnt_FH;
slave_proc->frame_rx = proc->frame_rx;
slave_proc->subframe_rx = proc->subframe_rx;
T(T_SUBFRAME, T_INT(proc->frame_rx), T_INT(proc->subframe_rx), T_STRING(__FUNCTION__));
//slave_proc->timestamp_rx = proc->timestamp_rx;
slave_proc->timestamp_tx = proc->timestamp_tx;
@@ -1468,7 +1514,7 @@ static void* eNB_thread_FH( void* param ) {
if (eNB->rx_fh) eNB->rx_fh(eNB,&frame,&subframe);
else AssertFatal(1==0, "No fronthaul interface : eNB->node_function %d",eNB->node_function);
T(T_ENB_MASTER_TICK, T_INT(0), T_INT(proc->frame_rx), T_INT(proc->subframe_rx));
T(T_ENB_MASTER_TICK, T_INT(0), T_INT(eNB->CC_id), T_INT(proc->frame_rx), T_INT(proc->subframe_rx));
// At this point, all information for subframe has been received on FH interface
// If this proc is to provide synchronization, do so
@@ -1669,10 +1715,11 @@ static void* eNB_thread_single( void* param ) {
if (eNB->rx_fh) eNB->rx_fh(eNB,&frame,&subframe);
else AssertFatal(1==0, "No fronthaul interface : eNB->node_function %d",eNB->node_function);
T(T_ENB_MASTER_TICK, T_INT(0), T_INT(proc->frame_rx), T_INT(proc->subframe_rx));
T(T_ENB_MASTER_TICK, T_INT(0), T_INT(eNB->CC_id), T_INT(proc->frame_rx), T_INT(proc->subframe_rx));
proc_rxtx->subframe_rx = proc->subframe_rx;
proc_rxtx->frame_rx = proc->frame_rx;
T(T_SUBFRAME, T_INT(proc->frame_rx), T_INT(proc->subframe_rx), T_STRING(__FUNCTION__));
proc_rxtx->subframe_tx = (proc->subframe_rx+4)%10;
proc_rxtx->frame_tx = (proc->subframe_rx>5) ? (1+proc->frame_rx)&1023 : proc->frame_rx;
proc->frame_tx = proc_rxtx->frame_tx;
@@ -1785,7 +1832,7 @@ void init_eNB_proc(int inst) {
(eNB->node_function == NGFI_RRU_IF4p5))
pthread_create( &proc->pthread_asynch_rxtx, attr_asynch, eNB_thread_asynch_rxtx, &eNB->proc );
;// pthread_create( &proc->pthread_asynch_rxtx, attr_asynch, eNB_thread_asynch_rxtx, &eNB->proc );
char name[16];
if (eNB->single_thread_flag == 0) {
@@ -2128,8 +2175,8 @@ void init_eNB(eNB_func_t node_function[], eNB_timing_t node_timing[],int nb_inst
eNB->proc_tx = proc_tx_full;
if (eNB->node_timing == synch_to_other) {
eNB->tx_fh = tx_fh_if5_mobipass;
eNB->rx_fh = rx_fh_slave;
eNB->fh_asynch = fh_if5_asynch_UL;
eNB->rx_fh = rx_fh_if5_mobipass; //rx_fh_slave;
eNB->fh_asynch = NULL; //fh_if5_asynch_UL;
}
else {