Commit 875bdaf2 authored by frtabu's avatar frtabu

cppcheck fixes (2)

parent 227a0640
...@@ -39,586 +39,586 @@ ...@@ -39,586 +39,586 @@
#include "common/ran_context.h" #include "common/ran_context.h"
static mapping rrc_status_names[] = { static mapping rrc_status_names[] = {
{"RRC_INACTIVE", 0}, {"RRC_INACTIVE", 0},
{"RRC_IDLE", 1}, {"RRC_IDLE", 1},
{"RRC_SI_RECEIVED",2}, {"RRC_SI_RECEIVED",2},
{"RRC_CONNECTED",3}, {"RRC_CONNECTED",3},
{"RRC_RECONFIGURED",4}, {"RRC_RECONFIGURED",4},
{"RRC_HO_EXECUTION",5}, {"RRC_HO_EXECUTION",5},
{NULL, -1} {NULL, -1}
}; };
extern RAN_CONTEXT_t RC; extern RAN_CONTEXT_t RC;
int dump_eNB_l2_stats(char *buffer, int length) { int dump_eNB_l2_stats(char *buffer, int length) {
int eNB_id,UE_id,number_of_cards; int eNB_id,UE_id,number_of_cards;
int len= length; int len= length;
int CC_id=0; int CC_id=0;
int i; int i;
protocol_ctxt_t ctxt; protocol_ctxt_t ctxt;
rlc_op_status_t rlc_status; rlc_op_status_t rlc_status;
unsigned int stat_rlc_mode; unsigned int stat_rlc_mode;
unsigned int stat_tx_pdcp_sdu; unsigned int stat_tx_pdcp_sdu;
unsigned int stat_tx_pdcp_bytes; unsigned int stat_tx_pdcp_bytes;
unsigned int stat_tx_pdcp_sdu_discarded; unsigned int stat_tx_pdcp_sdu_discarded;
unsigned int stat_tx_pdcp_bytes_discarded; unsigned int stat_tx_pdcp_bytes_discarded;
unsigned int stat_tx_data_pdu; unsigned int stat_tx_data_pdu;
unsigned int stat_tx_data_bytes; unsigned int stat_tx_data_bytes;
unsigned int stat_tx_retransmit_pdu_by_status; unsigned int stat_tx_retransmit_pdu_by_status;
unsigned int stat_tx_retransmit_bytes_by_status; unsigned int stat_tx_retransmit_bytes_by_status;
unsigned int stat_tx_retransmit_pdu; unsigned int stat_tx_retransmit_pdu;
unsigned int stat_tx_retransmit_bytes; unsigned int stat_tx_retransmit_bytes;
unsigned int stat_tx_control_pdu; unsigned int stat_tx_control_pdu;
unsigned int stat_tx_control_bytes; unsigned int stat_tx_control_bytes;
unsigned int stat_rx_pdcp_sdu; unsigned int stat_rx_pdcp_sdu;
unsigned int stat_rx_pdcp_bytes; unsigned int stat_rx_pdcp_bytes;
unsigned int stat_rx_data_pdus_duplicate; unsigned int stat_rx_data_pdus_duplicate;
unsigned int stat_rx_data_bytes_duplicate; unsigned int stat_rx_data_bytes_duplicate;
unsigned int stat_rx_data_pdu; unsigned int stat_rx_data_pdu;
unsigned int stat_rx_data_bytes; unsigned int stat_rx_data_bytes;
unsigned int stat_rx_data_pdu_dropped; unsigned int stat_rx_data_pdu_dropped;
unsigned int stat_rx_data_bytes_dropped; unsigned int stat_rx_data_bytes_dropped;
unsigned int stat_rx_data_pdu_out_of_window; unsigned int stat_rx_data_pdu_out_of_window;
unsigned int stat_rx_data_bytes_out_of_window; unsigned int stat_rx_data_bytes_out_of_window;
unsigned int stat_rx_control_pdu; unsigned int stat_rx_control_pdu;
unsigned int stat_rx_control_bytes; unsigned int stat_rx_control_bytes;
unsigned int stat_timer_reordering_timed_out; unsigned int stat_timer_reordering_timed_out;
unsigned int stat_timer_poll_retransmit_timed_out; unsigned int stat_timer_poll_retransmit_timed_out;
unsigned int stat_timer_status_prohibit_timed_out; unsigned int stat_timer_status_prohibit_timed_out;
#ifdef EXMIMO #ifdef EXMIMO
number_of_cards=1; number_of_cards=1;
#else #else
number_of_cards=NB_eNB_INST; number_of_cards=NB_eNB_INST;
#endif #endif
eNB_MAC_INST *eNB; eNB_MAC_INST *eNB;
UE_list_t *UE_list; UE_list_t *UE_list;
for (eNB_id=0; eNB_id<number_of_cards; eNB_id++) { for (eNB_id=0; eNB_id<number_of_cards; eNB_id++) {
/* reset the values */ /* reset the values */
eNB = RC.mac[eNB_id]; eNB = RC.mac[eNB_id];
UE_list = &eNB->UE_list; UE_list = &eNB->UE_list;
for (CC_id=0 ; CC_id < MAX_NUM_CCs; CC_id++) { for (CC_id=0 ; CC_id < MAX_NUM_CCs; CC_id++) {
eNB->eNB_stats[CC_id].dlsch_bitrate= 0; eNB->eNB_stats[CC_id].dlsch_bitrate= 0;
len += sprintf(&buffer[len],"eNB %d CC %d Frame %d: Active UEs %d, Available PRBs %d, nCCE %d, Scheduling decisions %d, Missed Deadlines %d \n", len += sprintf(&buffer[len],"eNB %d CC %d Frame %d: Active UEs %d, Available PRBs %d, nCCE %d, Scheduling decisions %d, Missed Deadlines %d \n",
eNB_id, CC_id, eNB->frame, eNB_id, CC_id, eNB->frame,
eNB->eNB_stats[CC_id].num_dlactive_UEs, eNB->eNB_stats[CC_id].num_dlactive_UEs,
eNB->eNB_stats[CC_id].available_prbs, eNB->eNB_stats[CC_id].available_prbs,
eNB->eNB_stats[CC_id].available_ncces, eNB->eNB_stats[CC_id].available_ncces,
eNB->eNB_stats[CC_id].sched_decisions, eNB->eNB_stats[CC_id].sched_decisions,
eNB->eNB_stats[CC_id].missed_deadlines); eNB->eNB_stats[CC_id].missed_deadlines);
len += sprintf(&buffer[len],"BCCH , NB_TX_MAC = %d, transmitted bytes (TTI %d, total %d) MCS (TTI %d)\n", len += sprintf(&buffer[len],"BCCH , NB_TX_MAC = %d, transmitted bytes (TTI %d, total %d) MCS (TTI %d)\n",
eNB->eNB_stats[CC_id].total_num_bcch_pdu, eNB->eNB_stats[CC_id].total_num_bcch_pdu,
eNB->eNB_stats[CC_id].bcch_buffer, eNB->eNB_stats[CC_id].bcch_buffer,
eNB->eNB_stats[CC_id].total_bcch_buffer, eNB->eNB_stats[CC_id].total_bcch_buffer,
eNB->eNB_stats[CC_id].bcch_mcs); eNB->eNB_stats[CC_id].bcch_mcs);
len += sprintf(&buffer[len],"PCCH , NB_TX_MAC = %d, transmitted bytes (TTI %d, total %d) MCS (TTI %d)\n", len += sprintf(&buffer[len],"PCCH , NB_TX_MAC = %d, transmitted bytes (TTI %d, total %d) MCS (TTI %d)\n",
eNB->eNB_stats[CC_id].total_num_pcch_pdu, eNB->eNB_stats[CC_id].total_num_pcch_pdu,
eNB->eNB_stats[CC_id].pcch_buffer, eNB->eNB_stats[CC_id].pcch_buffer,
eNB->eNB_stats[CC_id].total_pcch_buffer, eNB->eNB_stats[CC_id].total_pcch_buffer,
eNB->eNB_stats[CC_id].pcch_mcs); eNB->eNB_stats[CC_id].pcch_mcs);
eNB->eNB_stats[CC_id].dlsch_bitrate=((eNB->eNB_stats[CC_id].dlsch_bytes_tx*8)/((eNB->frame + 1)*10)); eNB->eNB_stats[CC_id].dlsch_bitrate=((eNB->eNB_stats[CC_id].dlsch_bytes_tx*8)/((eNB->frame + 1)*10));
eNB->eNB_stats[CC_id].total_dlsch_pdus_tx+=eNB->eNB_stats[CC_id].dlsch_pdus_tx; eNB->eNB_stats[CC_id].total_dlsch_pdus_tx+=eNB->eNB_stats[CC_id].dlsch_pdus_tx;
eNB->eNB_stats[CC_id].total_dlsch_bytes_tx+=eNB->eNB_stats[CC_id].dlsch_bytes_tx; eNB->eNB_stats[CC_id].total_dlsch_bytes_tx+=eNB->eNB_stats[CC_id].dlsch_bytes_tx;
eNB->eNB_stats[CC_id].total_dlsch_bitrate=((eNB->eNB_stats[CC_id].total_dlsch_bytes_tx*8)/((eNB->frame + 1)*10)); eNB->eNB_stats[CC_id].total_dlsch_bitrate=((eNB->eNB_stats[CC_id].total_dlsch_bytes_tx*8)/((eNB->frame + 1)*10));
eNB->eNB_stats[CC_id].ulsch_bitrate=((eNB->eNB_stats[CC_id].ulsch_bytes_rx*8)/((eNB->frame + 1)*10)); eNB->eNB_stats[CC_id].ulsch_bitrate=((eNB->eNB_stats[CC_id].ulsch_bytes_rx*8)/((eNB->frame + 1)*10));
eNB->eNB_stats[CC_id].total_ulsch_bitrate=((eNB->eNB_stats[CC_id].total_ulsch_bytes_rx*8)/((eNB->frame + 1)*10)); eNB->eNB_stats[CC_id].total_ulsch_bitrate=((eNB->eNB_stats[CC_id].total_ulsch_bytes_rx*8)/((eNB->frame + 1)*10));
len += sprintf(&buffer[len],"DLSCH bitrate (TTI %u, avg %u) kbps, Transmitted bytes (TTI %u, total %u), Transmitted PDU (TTI %u, total %u) \n", len += sprintf(&buffer[len],"DLSCH bitrate (TTI %u, avg %u) kbps, Transmitted bytes (TTI %u, total %u), Transmitted PDU (TTI %u, total %u) \n",
eNB->eNB_stats[CC_id].dlsch_bitrate, eNB->eNB_stats[CC_id].dlsch_bitrate,
eNB->eNB_stats[CC_id].total_dlsch_bitrate, eNB->eNB_stats[CC_id].total_dlsch_bitrate,
eNB->eNB_stats[CC_id].dlsch_bytes_tx, eNB->eNB_stats[CC_id].dlsch_bytes_tx,
eNB->eNB_stats[CC_id].total_dlsch_bytes_tx, eNB->eNB_stats[CC_id].total_dlsch_bytes_tx,
eNB->eNB_stats[CC_id].dlsch_pdus_tx, eNB->eNB_stats[CC_id].dlsch_pdus_tx,
eNB->eNB_stats[CC_id].total_dlsch_pdus_tx); eNB->eNB_stats[CC_id].total_dlsch_pdus_tx);
len += sprintf(&buffer[len],"ULSCH bitrate (TTI %u, avg %u) kbps, Received bytes (TTI %u, total %u), Received PDU (TTI %lu, total %u) \n", len += sprintf(&buffer[len],"ULSCH bitrate (TTI %u, avg %u) kbps, Received bytes (TTI %u, total %u), Received PDU (TTI %lu, total %u) \n",
eNB->eNB_stats[CC_id].ulsch_bitrate, eNB->eNB_stats[CC_id].ulsch_bitrate,
eNB->eNB_stats[CC_id].total_ulsch_bitrate, eNB->eNB_stats[CC_id].total_ulsch_bitrate,
eNB->eNB_stats[CC_id].ulsch_bytes_rx, eNB->eNB_stats[CC_id].ulsch_bytes_rx,
eNB->eNB_stats[CC_id].total_ulsch_bytes_rx, eNB->eNB_stats[CC_id].total_ulsch_bytes_rx,
eNB->eNB_stats[CC_id].ulsch_pdus_rx, eNB->eNB_stats[CC_id].ulsch_pdus_rx,
eNB->eNB_stats[CC_id].total_ulsch_pdus_rx); eNB->eNB_stats[CC_id].total_ulsch_pdus_rx);
} }
len += sprintf(&buffer[len],"\n");
for (UE_id=UE_list->head; UE_id>=0; UE_id=UE_list->next[UE_id]) {
for (i=0; i<UE_list->numactiveCCs[UE_id]; i++) {
CC_id=UE_list->ordered_CCids[i][UE_id];
UE_list->eNB_UE_stats[CC_id][UE_id].dlsch_bitrate=((UE_list->eNB_UE_stats[CC_id][UE_id].TBS*8)/((eNB->frame + 1)*10));
UE_list->eNB_UE_stats[CC_id][UE_id].total_dlsch_bitrate= ((UE_list->eNB_UE_stats[CC_id][UE_id].total_pdu_bytes*8)/((eNB->frame + 1)*10));
UE_list->eNB_UE_stats[CC_id][UE_id].total_overhead_bytes+= UE_list->eNB_UE_stats[CC_id][UE_id].overhead_bytes;
UE_list->eNB_UE_stats[CC_id][UE_id].avg_overhead_bytes=((UE_list->eNB_UE_stats[CC_id][UE_id].total_overhead_bytes*8)/((eNB->frame + 1)*10));
UE_list->eNB_UE_stats[CC_id][UE_id].ulsch_bitrate=((UE_list->eNB_UE_stats[CC_id][UE_id].ulsch_TBS*8)/((eNB->frame + 1)*10));
UE_list->eNB_UE_stats[CC_id][UE_id].total_ulsch_bitrate= ((UE_list->eNB_UE_stats[CC_id][UE_id].total_pdu_bytes_rx*8)/((eNB->frame + 1)*10));
len += sprintf(&buffer[len],"[MAC] UE %d (DLSCH),status %s, RNTI %x : CQI %d, MCS1 %d, MCS2 %d, RB (tx %d, retx %d, total %d), ncce (tx %d, retx %d) \n",
UE_id,
map_int_to_str(rrc_status_names, UE_list->eNB_UE_stats[CC_id][UE_id].rrc_status),
UE_list->eNB_UE_stats[CC_id][UE_id].crnti,
UE_list->UE_sched_ctrl[UE_id].dl_cqi[CC_id],
UE_list->eNB_UE_stats[CC_id][UE_id].dlsch_mcs1,
UE_list->eNB_UE_stats[CC_id][UE_id].dlsch_mcs2,
UE_list->eNB_UE_stats[CC_id][UE_id].rbs_used,
UE_list->eNB_UE_stats[CC_id][UE_id].rbs_used_retx,
UE_list->eNB_UE_stats[CC_id][UE_id].total_rbs_used,
UE_list->eNB_UE_stats[CC_id][UE_id].ncce_used,
UE_list->eNB_UE_stats[CC_id][UE_id].ncce_used_retx
);
len += sprintf(&buffer[len],
"[MAC] DLSCH bitrate (TTI %d, avg %d), Transmitted bytes "
"(TTI %d, total %"PRIu64"), Total Transmitted PDU %d, Overhead "
"(TTI %"PRIu64", total %"PRIu64", avg %"PRIu64")\n",
UE_list->eNB_UE_stats[CC_id][UE_id].dlsch_bitrate,
UE_list->eNB_UE_stats[CC_id][UE_id].total_dlsch_bitrate,
UE_list->eNB_UE_stats[CC_id][UE_id].TBS,
UE_list->eNB_UE_stats[CC_id][UE_id].total_pdu_bytes,
UE_list->eNB_UE_stats[CC_id][UE_id].total_num_pdus,
UE_list->eNB_UE_stats[CC_id][UE_id].overhead_bytes,
UE_list->eNB_UE_stats[CC_id][UE_id].total_overhead_bytes,
UE_list->eNB_UE_stats[CC_id][UE_id].avg_overhead_bytes
);
len += sprintf(&buffer[len],"[MAC] UE %d (ULSCH), Status %s, Failute timer %d, RNTI %x : rx power (normalized %d, target %d), MCS (pre %d, post %d), RB (rx %d, retx %d, total %d), Current TBS %d \n",
UE_id,
map_int_to_str(rrc_status_names, UE_list->eNB_UE_stats[CC_id][UE_id].rrc_status),
UE_list->UE_sched_ctrl[UE_id].ul_failure_timer,
UE_list->eNB_UE_stats[CC_id][UE_id].crnti,
UE_list->eNB_UE_stats[CC_id][UE_id].normalized_rx_power,
UE_list->eNB_UE_stats[CC_id][UE_id].target_rx_power,
UE_list->eNB_UE_stats[CC_id][UE_id].ulsch_mcs1,
UE_list->eNB_UE_stats[CC_id][UE_id].ulsch_mcs2,
UE_list->eNB_UE_stats[CC_id][UE_id].rbs_used_rx,
UE_list->eNB_UE_stats[CC_id][UE_id].rbs_used_retx_rx,
UE_list->eNB_UE_stats[CC_id][UE_id].total_rbs_used_rx,
UE_list->eNB_UE_stats[CC_id][UE_id].ulsch_TBS
);
len += sprintf(&buffer[len],
"[MAC] ULSCH bitrate (TTI %d, avg %d), received bytes (total %"PRIu64"),"
"Total received PDU %d, Total errors %d\n",
UE_list->eNB_UE_stats[CC_id][UE_id].ulsch_bitrate,
UE_list->eNB_UE_stats[CC_id][UE_id].total_ulsch_bitrate,
UE_list->eNB_UE_stats[CC_id][UE_id].total_pdu_bytes_rx,
UE_list->eNB_UE_stats[CC_id][UE_id].total_num_pdus_rx,
UE_list->eNB_UE_stats[CC_id][UE_id].num_errors_rx);
len+= sprintf(&buffer[len],"[MAC] Received PHR PH = %d (db)\n", UE_list->UE_template[CC_id][UE_id].phr_info);
len+= sprintf(&buffer[len],"[MAC] Estimated size LCGID[0][1][2][3] = %u %u %u %u\n",
UE_list->UE_template[CC_id][UE_id].ul_buffer_info[LCGID0],
UE_list->UE_template[CC_id][UE_id].ul_buffer_info[LCGID1],
UE_list->UE_template[CC_id][UE_id].ul_buffer_info[LCGID2],
UE_list->UE_template[CC_id][UE_id].ul_buffer_info[LCGID3]
);
}
PROTOCOL_CTXT_SET_BY_MODULE_ID(&ctxt,
eNB_id,
ENB_FLAG_YES,
UE_list->eNB_UE_stats[0][UE_id].crnti,//UE_PCCID(eNB_id,UE_id)][UE_id].crnti,
eNB->frame,
eNB->subframe,
eNB_id);
rlc_status = rlc_stat_req(&ctxt,
SRB_FLAG_YES,
DCCH,
&stat_rlc_mode,
&stat_tx_pdcp_sdu,
&stat_tx_pdcp_bytes,
&stat_tx_pdcp_sdu_discarded,
&stat_tx_pdcp_bytes_discarded,
&stat_tx_data_pdu,
&stat_tx_data_bytes,
&stat_tx_retransmit_pdu_by_status,
&stat_tx_retransmit_bytes_by_status,
&stat_tx_retransmit_pdu,
&stat_tx_retransmit_bytes,
&stat_tx_control_pdu,
&stat_tx_control_bytes,
&stat_rx_pdcp_sdu,
&stat_rx_pdcp_bytes,
&stat_rx_data_pdus_duplicate,
&stat_rx_data_bytes_duplicate,
&stat_rx_data_pdu,
&stat_rx_data_bytes,
&stat_rx_data_pdu_dropped,
&stat_rx_data_bytes_dropped,
&stat_rx_data_pdu_out_of_window,
&stat_rx_data_bytes_out_of_window,
&stat_rx_control_pdu,
&stat_rx_control_bytes,
&stat_timer_reordering_timed_out,
&stat_timer_poll_retransmit_timed_out,
&stat_timer_status_prohibit_timed_out);
if (rlc_status == RLC_OP_STATUS_OK) {
len+=sprintf(&buffer[len],"[RLC] DCCH Mode %s, NB_SDU_TO_TX = %u (bytes %u)\tNB_SDU_TO_TX_DISC %u (bytes %u)\n",
(stat_rlc_mode==RLC_MODE_AM)? "AM": (stat_rlc_mode==RLC_MODE_UM)?"UM":"NONE",
stat_tx_pdcp_sdu,
stat_tx_pdcp_bytes,
stat_tx_pdcp_sdu_discarded,
stat_tx_pdcp_bytes_discarded);
len+=sprintf(&buffer[len],"[RLC] DCCH Mode %s, NB_TX_DATA = %u (bytes %u)\tNB_TX_CONTROL %u (bytes %u)\tNB_TX_RETX %u (bytes %u)\tNB_TX_RETX_BY_STATUS = %u (bytes %u)\n",
(stat_rlc_mode==RLC_MODE_AM)? "AM": (stat_rlc_mode==RLC_MODE_UM)?"UM":"NONE",
stat_tx_data_pdu,
stat_tx_data_bytes,
stat_tx_control_pdu,
stat_tx_control_bytes,
stat_tx_retransmit_pdu,
stat_tx_retransmit_bytes,
stat_tx_retransmit_pdu_by_status,
stat_tx_retransmit_bytes_by_status);
len+=sprintf(&buffer[len],"[RLC] DCCH Mode %s, NB_RX_DATA = %u (bytes %u)\tNB_RX_CONTROL %u (bytes %u)\tNB_RX_DUPL %u (bytes %u)\tNB_RX_DROP = %u (bytes %u)\tNB_RX_OUT_OF_WINDOW = %u (bytes %u)\n",
(stat_rlc_mode==RLC_MODE_AM)? "AM": (stat_rlc_mode==RLC_MODE_UM)?"UM":"NONE",
stat_rx_data_pdu,
stat_rx_data_bytes,
stat_rx_control_pdu,
stat_rx_control_bytes,
stat_rx_data_pdus_duplicate,
stat_rx_data_bytes_duplicate,
stat_rx_data_pdu_dropped,
stat_rx_data_bytes_dropped,
stat_rx_data_pdu_out_of_window,
stat_rx_data_bytes_out_of_window);
len+=sprintf(&buffer[len],"[RLC] DCCH Mode %s, RX_REODERING_TIMEOUT = %u\tRX_POLL_RET_TIMEOUT %u\tRX_PROHIBIT_TIME_OUT %u\n",
(stat_rlc_mode==RLC_MODE_AM)? "AM": (stat_rlc_mode==RLC_MODE_UM)?"UM":"NONE",
stat_timer_reordering_timed_out,
stat_timer_poll_retransmit_timed_out,
stat_timer_status_prohibit_timed_out);
len+=sprintf(&buffer[len],"[RLC] DCCH Mode %s, NB_SDU_TO_RX = %u (bytes %u)\n",
(stat_rlc_mode==RLC_MODE_AM)? "AM": (stat_rlc_mode==RLC_MODE_UM)?"UM":"NONE",
stat_rx_pdcp_sdu,
stat_rx_pdcp_bytes);
}
len += sprintf(&buffer[len],"\n"); rlc_status = rlc_stat_req(&ctxt,
SRB_FLAG_NO,
for (UE_id=UE_list->head; UE_id>=0; UE_id=UE_list->next[UE_id]) { DTCH-2, // DRB_IDENTITY
for (i=0; i<UE_list->numactiveCCs[UE_id]; i++) { &stat_rlc_mode,
CC_id=UE_list->ordered_CCids[i][UE_id]; &stat_tx_pdcp_sdu,
UE_list->eNB_UE_stats[CC_id][UE_id].dlsch_bitrate=((UE_list->eNB_UE_stats[CC_id][UE_id].TBS*8)/((eNB->frame + 1)*10)); &stat_tx_pdcp_bytes,
UE_list->eNB_UE_stats[CC_id][UE_id].total_dlsch_bitrate= ((UE_list->eNB_UE_stats[CC_id][UE_id].total_pdu_bytes*8)/((eNB->frame + 1)*10)); &stat_tx_pdcp_sdu_discarded,
UE_list->eNB_UE_stats[CC_id][UE_id].total_overhead_bytes+= UE_list->eNB_UE_stats[CC_id][UE_id].overhead_bytes; &stat_tx_pdcp_bytes_discarded,
UE_list->eNB_UE_stats[CC_id][UE_id].avg_overhead_bytes=((UE_list->eNB_UE_stats[CC_id][UE_id].total_overhead_bytes*8)/((eNB->frame + 1)*10)); &stat_tx_data_pdu,
UE_list->eNB_UE_stats[CC_id][UE_id].ulsch_bitrate=((UE_list->eNB_UE_stats[CC_id][UE_id].ulsch_TBS*8)/((eNB->frame + 1)*10)); &stat_tx_data_bytes,
UE_list->eNB_UE_stats[CC_id][UE_id].total_ulsch_bitrate= ((UE_list->eNB_UE_stats[CC_id][UE_id].total_pdu_bytes_rx*8)/((eNB->frame + 1)*10)); &stat_tx_retransmit_pdu_by_status,
len += sprintf(&buffer[len],"[MAC] UE %d (DLSCH),status %s, RNTI %x : CQI %d, MCS1 %d, MCS2 %d, RB (tx %d, retx %d, total %d), ncce (tx %d, retx %d) \n", &stat_tx_retransmit_bytes_by_status,
UE_id, &stat_tx_retransmit_pdu,
map_int_to_str(rrc_status_names, UE_list->eNB_UE_stats[CC_id][UE_id].rrc_status), &stat_tx_retransmit_bytes,
UE_list->eNB_UE_stats[CC_id][UE_id].crnti, &stat_tx_control_pdu,
UE_list->UE_sched_ctrl[UE_id].dl_cqi[CC_id], &stat_tx_control_bytes,
UE_list->eNB_UE_stats[CC_id][UE_id].dlsch_mcs1, &stat_rx_pdcp_sdu,
UE_list->eNB_UE_stats[CC_id][UE_id].dlsch_mcs2, &stat_rx_pdcp_bytes,
UE_list->eNB_UE_stats[CC_id][UE_id].rbs_used, &stat_rx_data_pdus_duplicate,
UE_list->eNB_UE_stats[CC_id][UE_id].rbs_used_retx, &stat_rx_data_bytes_duplicate,
UE_list->eNB_UE_stats[CC_id][UE_id].total_rbs_used, &stat_rx_data_pdu,
UE_list->eNB_UE_stats[CC_id][UE_id].ncce_used, &stat_rx_data_bytes,
UE_list->eNB_UE_stats[CC_id][UE_id].ncce_used_retx &stat_rx_data_pdu_dropped,
); &stat_rx_data_bytes_dropped,
len += sprintf(&buffer[len], &stat_rx_data_pdu_out_of_window,
"[MAC] DLSCH bitrate (TTI %d, avg %d), Transmitted bytes " &stat_rx_data_bytes_out_of_window,
"(TTI %d, total %"PRIu64"), Total Transmitted PDU %d, Overhead " &stat_rx_control_pdu,
"(TTI %"PRIu64", total %"PRIu64", avg %"PRIu64")\n", &stat_rx_control_bytes,
UE_list->eNB_UE_stats[CC_id][UE_id].dlsch_bitrate, &stat_timer_reordering_timed_out,
UE_list->eNB_UE_stats[CC_id][UE_id].total_dlsch_bitrate, &stat_timer_poll_retransmit_timed_out,
UE_list->eNB_UE_stats[CC_id][UE_id].TBS, &stat_timer_status_prohibit_timed_out);
UE_list->eNB_UE_stats[CC_id][UE_id].total_pdu_bytes,
UE_list->eNB_UE_stats[CC_id][UE_id].total_num_pdus, if (rlc_status == RLC_OP_STATUS_OK) {
UE_list->eNB_UE_stats[CC_id][UE_id].overhead_bytes, len+=sprintf(&buffer[len],"[RLC] DTCH Mode %s, NB_SDU_TO_TX = %u (bytes %u)\tNB_SDU_TO_TX_DISC %u (bytes %u)\n",
UE_list->eNB_UE_stats[CC_id][UE_id].total_overhead_bytes, (stat_rlc_mode==RLC_MODE_AM)? "AM": (stat_rlc_mode==RLC_MODE_UM)?"UM":"NONE",
UE_list->eNB_UE_stats[CC_id][UE_id].avg_overhead_bytes stat_tx_pdcp_sdu,
); stat_tx_pdcp_bytes,
len += sprintf(&buffer[len],"[MAC] UE %d (ULSCH), Status %s, Failute timer %d, RNTI %x : rx power (normalized %d, target %d), MCS (pre %d, post %d), RB (rx %d, retx %d, total %d), Current TBS %d \n", stat_tx_pdcp_sdu_discarded,
UE_id, stat_tx_pdcp_bytes_discarded);
map_int_to_str(rrc_status_names, UE_list->eNB_UE_stats[CC_id][UE_id].rrc_status), len+=sprintf(&buffer[len],"[RLC] DTCH Mode %s, NB_TX_DATA = %u (bytes %u)\tNB_TX_CONTROL %u (bytes %u)\tNB_TX_RETX %u (bytes %u)\tNB_TX_RETX_BY_STATUS = %u (bytes %u)\n",
UE_list->UE_sched_ctrl[UE_id].ul_failure_timer, (stat_rlc_mode==RLC_MODE_AM)? "AM": (stat_rlc_mode==RLC_MODE_UM)?"UM":"NONE",
UE_list->eNB_UE_stats[CC_id][UE_id].crnti, stat_tx_data_pdu,
UE_list->eNB_UE_stats[CC_id][UE_id].normalized_rx_power, stat_tx_data_bytes,
UE_list->eNB_UE_stats[CC_id][UE_id].target_rx_power, stat_tx_control_pdu,
UE_list->eNB_UE_stats[CC_id][UE_id].ulsch_mcs1, stat_tx_control_bytes,
UE_list->eNB_UE_stats[CC_id][UE_id].ulsch_mcs2, stat_tx_retransmit_pdu,
UE_list->eNB_UE_stats[CC_id][UE_id].rbs_used_rx, stat_tx_retransmit_bytes,
UE_list->eNB_UE_stats[CC_id][UE_id].rbs_used_retx_rx, stat_tx_retransmit_pdu_by_status,
UE_list->eNB_UE_stats[CC_id][UE_id].total_rbs_used_rx, stat_tx_retransmit_bytes_by_status);
UE_list->eNB_UE_stats[CC_id][UE_id].ulsch_TBS len+=sprintf(&buffer[len],"[RLC] DTCH Mode %s, NB_RX_DATA = %u (bytes %u)\tNB_RX_CONTROL %u (bytes %u)\tNB_RX_DUPL %u (bytes %u)\tNB_RX_DROP = %u (bytes %u)\tNB_RX_OUT_OF_WINDOW = %u (bytes %u)\n",
); (stat_rlc_mode==RLC_MODE_AM)? "AM": (stat_rlc_mode==RLC_MODE_UM)?"UM":"NONE",
len += sprintf(&buffer[len], stat_rx_data_pdu,
"[MAC] ULSCH bitrate (TTI %d, avg %d), received bytes (total %"PRIu64")," stat_rx_data_bytes,
"Total received PDU %d, Total errors %d\n", stat_rx_control_pdu,
UE_list->eNB_UE_stats[CC_id][UE_id].ulsch_bitrate, stat_rx_control_bytes,
UE_list->eNB_UE_stats[CC_id][UE_id].total_ulsch_bitrate, stat_rx_data_pdus_duplicate,
UE_list->eNB_UE_stats[CC_id][UE_id].total_pdu_bytes_rx, stat_rx_data_bytes_duplicate,
UE_list->eNB_UE_stats[CC_id][UE_id].total_num_pdus_rx, stat_rx_data_pdu_dropped,
UE_list->eNB_UE_stats[CC_id][UE_id].num_errors_rx); stat_rx_data_bytes_dropped,
len+= sprintf(&buffer[len],"[MAC] Received PHR PH = %d (db)\n", UE_list->UE_template[CC_id][UE_id].phr_info); stat_rx_data_pdu_out_of_window,
len+= sprintf(&buffer[len],"[MAC] Estimated size LCGID[0][1][2][3] = %u %u %u %u\n", stat_rx_data_bytes_out_of_window);
UE_list->UE_template[CC_id][UE_id].ul_buffer_info[LCGID0], len+=sprintf(&buffer[len],"[RLC] DTCH Mode %s, RX_REODERING_TIMEOUT = %u\tRX_POLL_RET_TIMEOUT %u\tRX_PROHIBIT_TIME_OUT %u\n",
UE_list->UE_template[CC_id][UE_id].ul_buffer_info[LCGID1], (stat_rlc_mode==RLC_MODE_AM)? "AM": (stat_rlc_mode==RLC_MODE_UM)?"UM":"NONE",
UE_list->UE_template[CC_id][UE_id].ul_buffer_info[LCGID2], stat_timer_reordering_timed_out,
UE_list->UE_template[CC_id][UE_id].ul_buffer_info[LCGID3] stat_timer_poll_retransmit_timed_out,
); stat_timer_status_prohibit_timed_out);
} len+=sprintf(&buffer[len],"[RLC] DTCH Mode %s, NB_SDU_TO_RX = %u (bytes %u)\n",
(stat_rlc_mode==RLC_MODE_AM)? "AM": (stat_rlc_mode==RLC_MODE_UM)?"UM":"NONE",
PROTOCOL_CTXT_SET_BY_MODULE_ID(&ctxt, stat_rx_pdcp_sdu,
eNB_id, stat_rx_pdcp_bytes);
ENB_FLAG_YES, }
UE_list->eNB_UE_stats[0][UE_id].crnti,//UE_PCCID(eNB_id,UE_id)][UE_id].crnti, }
eNB->frame,
eNB->subframe,
eNB_id);
rlc_status = rlc_stat_req(&ctxt,
SRB_FLAG_YES,
DCCH,
&stat_rlc_mode,
&stat_tx_pdcp_sdu,
&stat_tx_pdcp_bytes,
&stat_tx_pdcp_sdu_discarded,
&stat_tx_pdcp_bytes_discarded,
&stat_tx_data_pdu,
&stat_tx_data_bytes,
&stat_tx_retransmit_pdu_by_status,
&stat_tx_retransmit_bytes_by_status,
&stat_tx_retransmit_pdu,
&stat_tx_retransmit_bytes,
&stat_tx_control_pdu,
&stat_tx_control_bytes,
&stat_rx_pdcp_sdu,
&stat_rx_pdcp_bytes,
&stat_rx_data_pdus_duplicate,
&stat_rx_data_bytes_duplicate,
&stat_rx_data_pdu,
&stat_rx_data_bytes,
&stat_rx_data_pdu_dropped,
&stat_rx_data_bytes_dropped,
&stat_rx_data_pdu_out_of_window,
&stat_rx_data_bytes_out_of_window,
&stat_rx_control_pdu,
&stat_rx_control_bytes,
&stat_timer_reordering_timed_out,
&stat_timer_poll_retransmit_timed_out,
&stat_timer_status_prohibit_timed_out);
if (rlc_status == RLC_OP_STATUS_OK) {
len+=sprintf(&buffer[len],"[RLC] DCCH Mode %s, NB_SDU_TO_TX = %d (bytes %d)\tNB_SDU_TO_TX_DISC %d (bytes %d)\n",
(stat_rlc_mode==RLC_MODE_AM)? "AM": (stat_rlc_mode==RLC_MODE_UM)?"UM":"NONE",
stat_tx_pdcp_sdu,
stat_tx_pdcp_bytes,
stat_tx_pdcp_sdu_discarded,
stat_tx_pdcp_bytes_discarded);
len+=sprintf(&buffer[len],"[RLC] DCCH Mode %s, NB_TX_DATA = %d (bytes %d)\tNB_TX_CONTROL %d (bytes %d)\tNB_TX_RETX %d (bytes %d)\tNB_TX_RETX_BY_STATUS = %d (bytes %d)\n",
(stat_rlc_mode==RLC_MODE_AM)? "AM": (stat_rlc_mode==RLC_MODE_UM)?"UM":"NONE",
stat_tx_data_pdu,
stat_tx_data_bytes,
stat_tx_control_pdu,
stat_tx_control_bytes,
stat_tx_retransmit_pdu,
stat_tx_retransmit_bytes,
stat_tx_retransmit_pdu_by_status,
stat_tx_retransmit_bytes_by_status);
len+=sprintf(&buffer[len],"[RLC] DCCH Mode %s, NB_RX_DATA = %d (bytes %d)\tNB_RX_CONTROL %d (bytes %d)\tNB_RX_DUPL %d (bytes %d)\tNB_RX_DROP = %d (bytes %d)\tNB_RX_OUT_OF_WINDOW = %d (bytes %d)\n",
(stat_rlc_mode==RLC_MODE_AM)? "AM": (stat_rlc_mode==RLC_MODE_UM)?"UM":"NONE",
stat_rx_data_pdu,
stat_rx_data_bytes,
stat_rx_control_pdu,
stat_rx_control_bytes,
stat_rx_data_pdus_duplicate,
stat_rx_data_bytes_duplicate,
stat_rx_data_pdu_dropped,
stat_rx_data_bytes_dropped,
stat_rx_data_pdu_out_of_window,
stat_rx_data_bytes_out_of_window);
len+=sprintf(&buffer[len],"[RLC] DCCH Mode %s, RX_REODERING_TIMEOUT = %d\tRX_POLL_RET_TIMEOUT %d\tRX_PROHIBIT_TIME_OUT %d\n",
(stat_rlc_mode==RLC_MODE_AM)? "AM": (stat_rlc_mode==RLC_MODE_UM)?"UM":"NONE",
stat_timer_reordering_timed_out,
stat_timer_poll_retransmit_timed_out,
stat_timer_status_prohibit_timed_out);
len+=sprintf(&buffer[len],"[RLC] DCCH Mode %s, NB_SDU_TO_RX = %d (bytes %d)\n",
(stat_rlc_mode==RLC_MODE_AM)? "AM": (stat_rlc_mode==RLC_MODE_UM)?"UM":"NONE",
stat_rx_pdcp_sdu,
stat_rx_pdcp_bytes);
}
rlc_status = rlc_stat_req(&ctxt,
SRB_FLAG_NO,
DTCH-2, // DRB_IDENTITY
&stat_rlc_mode,
&stat_tx_pdcp_sdu,
&stat_tx_pdcp_bytes,
&stat_tx_pdcp_sdu_discarded,
&stat_tx_pdcp_bytes_discarded,
&stat_tx_data_pdu,
&stat_tx_data_bytes,
&stat_tx_retransmit_pdu_by_status,
&stat_tx_retransmit_bytes_by_status,
&stat_tx_retransmit_pdu,
&stat_tx_retransmit_bytes,
&stat_tx_control_pdu,
&stat_tx_control_bytes,
&stat_rx_pdcp_sdu,
&stat_rx_pdcp_bytes,
&stat_rx_data_pdus_duplicate,
&stat_rx_data_bytes_duplicate,
&stat_rx_data_pdu,
&stat_rx_data_bytes,
&stat_rx_data_pdu_dropped,
&stat_rx_data_bytes_dropped,
&stat_rx_data_pdu_out_of_window,
&stat_rx_data_bytes_out_of_window,
&stat_rx_control_pdu,
&stat_rx_control_bytes,
&stat_timer_reordering_timed_out,
&stat_timer_poll_retransmit_timed_out,
&stat_timer_status_prohibit_timed_out);
if (rlc_status == RLC_OP_STATUS_OK) {
len+=sprintf(&buffer[len],"[RLC] DTCH Mode %s, NB_SDU_TO_TX = %d (bytes %d)\tNB_SDU_TO_TX_DISC %d (bytes %d)\n",
(stat_rlc_mode==RLC_MODE_AM)? "AM": (stat_rlc_mode==RLC_MODE_UM)?"UM":"NONE",
stat_tx_pdcp_sdu,
stat_tx_pdcp_bytes,
stat_tx_pdcp_sdu_discarded,
stat_tx_pdcp_bytes_discarded);
len+=sprintf(&buffer[len],"[RLC] DTCH Mode %s, NB_TX_DATA = %d (bytes %d)\tNB_TX_CONTROL %d (bytes %d)\tNB_TX_RETX %d (bytes %d)\tNB_TX_RETX_BY_STATUS = %d (bytes %d)\n",
(stat_rlc_mode==RLC_MODE_AM)? "AM": (stat_rlc_mode==RLC_MODE_UM)?"UM":"NONE",
stat_tx_data_pdu,
stat_tx_data_bytes,
stat_tx_control_pdu,
stat_tx_control_bytes,
stat_tx_retransmit_pdu,
stat_tx_retransmit_bytes,
stat_tx_retransmit_pdu_by_status,
stat_tx_retransmit_bytes_by_status);
len+=sprintf(&buffer[len],"[RLC] DTCH Mode %s, NB_RX_DATA = %d (bytes %d)\tNB_RX_CONTROL %d (bytes %d)\tNB_RX_DUPL %d (bytes %d)\tNB_RX_DROP = %d (bytes %d)\tNB_RX_OUT_OF_WINDOW = %d (bytes %d)\n",
(stat_rlc_mode==RLC_MODE_AM)? "AM": (stat_rlc_mode==RLC_MODE_UM)?"UM":"NONE",
stat_rx_data_pdu,
stat_rx_data_bytes,
stat_rx_control_pdu,
stat_rx_control_bytes,
stat_rx_data_pdus_duplicate,
stat_rx_data_bytes_duplicate,
stat_rx_data_pdu_dropped,
stat_rx_data_bytes_dropped,
stat_rx_data_pdu_out_of_window,
stat_rx_data_bytes_out_of_window);
len+=sprintf(&buffer[len],"[RLC] DTCH Mode %s, RX_REODERING_TIMEOUT = %d\tRX_POLL_RET_TIMEOUT %d\tRX_PROHIBIT_TIME_OUT %d\n",
(stat_rlc_mode==RLC_MODE_AM)? "AM": (stat_rlc_mode==RLC_MODE_UM)?"UM":"NONE",
stat_timer_reordering_timed_out,
stat_timer_poll_retransmit_timed_out,
stat_timer_status_prohibit_timed_out);
len+=sprintf(&buffer[len],"[RLC] DTCH Mode %s, NB_SDU_TO_RX = %d (bytes %d)\n",
(stat_rlc_mode==RLC_MODE_AM)? "AM": (stat_rlc_mode==RLC_MODE_UM)?"UM":"NONE",
stat_rx_pdcp_sdu,
stat_rx_pdcp_bytes);
}
} }
}
return len + 1 /* SR: for trailing \0 */; return len + 1 /* SR: for trailing \0 */;
} }
#ifdef PROC #ifdef PROC
int openair2_stats_read(char *buffer, char **my_buffer, off_t off, int length) { int openair2_stats_read(char *buffer, char **my_buffer, off_t off, int length) {
int len = 0,fg,Overhead, Sign; int len = 0,fg,Overhead, Sign;
unsigned int i,j,k,kk; unsigned int i,j,k,kk;
unsigned int Mod_id = 0,CH_index; unsigned int Mod_id = 0,CH_index;
unsigned int tx_pdcp_sdu; unsigned int tx_pdcp_sdu;
unsigned int tx_pdcp_sdu_discarded; unsigned int tx_pdcp_sdu_discarded;
unsigned int tx_retransmit_pdu_unblock; unsigned int tx_retransmit_pdu_unblock;
unsigned int tx_retransmit_pdu_by_status; unsigned int tx_retransmit_pdu_by_status;
unsigned int tx_retransmit_pdu; unsigned int tx_retransmit_pdu;
unsigned int tx_data_pdu; unsigned int tx_data_pdu;
unsigned int tx_control_pdu; unsigned int tx_control_pdu;
unsigned int rx_sdu; unsigned int rx_sdu;
unsigned int rx_error_pdu; unsigned int rx_error_pdu;
unsigned int rx_data_pdu; unsigned int rx_data_pdu;
unsigned int rx_data_pdu_out_of_window; unsigned int rx_data_pdu_out_of_window;
unsigned int rx_control_pdu; unsigned int rx_control_pdu;
// if (mac_xface->is_cluster_head == 0) { // if (mac_xface->is_cluster_head == 0) {
for (k=0; k<NB_INST; k++) { for (k=0; k<NB_INST; k++) {
if (Mac_rlc_xface->Is_cluster_head[k] == 0) { if (Mac_rlc_xface->Is_cluster_head[k] == 0) {
#ifndef PHY_EMUL_ONE_MACHINE #ifndef PHY_EMUL_ONE_MACHINE
Mod_id=k-NB_CH_INST; Mod_id=k-NB_CH_INST;
len+=sprintf(&buffer[len],"UE TTI: %d\n",Mac_rlc_xface->frame); len+=sprintf(&buffer[len],"UE TTI: %d\n",Mac_rlc_xface->frame);
for (CH_index = 0; CH_index<NB_CNX_UE; CH_index++) { for (CH_index = 0; CH_index<NB_CNX_UE; CH_index++) {
if (UE_mac_inst[Mod_id].Dcch_lchan[CH_index].Active==1) { if (UE_mac_inst[Mod_id].Dcch_lchan[CH_index].Active==1) {
len+=sprintf(&buffer[len],"CH %d: Wideband SINR %d dB---\n", len+=sprintf(&buffer[len],"CH %u: Wideband SINR %d dB---\n",
CH_index,UE_mac_inst[Mod_id].Def_meas[CH_index].Wideband_sinr); CH_index,UE_mac_inst[Mod_id].Def_meas[CH_index].Wideband_sinr);
len+=sprintf(&buffer[len],"CH %d: Subband SINR (dB) :", len+=sprintf(&buffer[len],"CH %u: Subband SINR (dB) :",
CH_index); CH_index);
for (fg=0; fg<NUMBER_OF_MEASUREMENT_SUBBANDS; fg++) { for (fg=0; fg<NUMBER_OF_MEASUREMENT_SUBBANDS; fg++) {
len+=sprintf(&buffer[len],"%d ",UE_mac_inst[Mod_id].Def_meas[CH_index].Sinr_meas[0][fg]); len+=sprintf(&buffer[len],"%d ",UE_mac_inst[Mod_id].Def_meas[CH_index].Sinr_meas[0][fg]);
} }
len+=sprintf(&buffer[len],"\n"); len+=sprintf(&buffer[len],"\n");
len+=sprintf(&buffer[len],"BCCH %d, NB_RX_MAC = %d (%d errors)\n", len+=sprintf(&buffer[len],"BCCH %d, NB_RX_MAC = %d (%d errors)\n",
UE_mac_inst[Mod_id].Bcch_lchan[CH_index].Lchan_info.Lchan_id.Index, UE_mac_inst[Mod_id].Bcch_lchan[CH_index].Lchan_info.Lchan_id.Index,
UE_mac_inst[Mod_id].Bcch_lchan[CH_index].Lchan_info.NB_RX, UE_mac_inst[Mod_id].Bcch_lchan[CH_index].Lchan_info.NB_RX,
UE_mac_inst[Mod_id].Bcch_lchan[CH_index].Lchan_info.NB_RX_ERRORS); UE_mac_inst[Mod_id].Bcch_lchan[CH_index].Lchan_info.NB_RX_ERRORS);
len+=sprintf(&buffer[len],"CCCH %d, NB_RX_MAC = %d (%d errors)\n", len+=sprintf(&buffer[len],"CCCH %d, NB_RX_MAC = %d (%d errors)\n",
UE_mac_inst[Mod_id].Ccch_lchan[CH_index].Lchan_info.Lchan_id.Index, UE_mac_inst[Mod_id].Ccch_lchan[CH_index].Lchan_info.Lchan_id.Index,
UE_mac_inst[Mod_id].Ccch_lchan[CH_index].Lchan_info.NB_RX, UE_mac_inst[Mod_id].Ccch_lchan[CH_index].Lchan_info.NB_RX,
UE_mac_inst[Mod_id].Ccch_lchan[CH_index].Lchan_info.NB_RX_ERRORS); UE_mac_inst[Mod_id].Ccch_lchan[CH_index].Lchan_info.NB_RX_ERRORS);
len+=sprintf(&buffer[len],"LCHAN %d (DCCH), NB_TX_MAC = %d (%d bits/TTI, %d kbits/sec), NB_RX_MAC = %d (%d errors)\n", len+=sprintf(&buffer[len],"LCHAN %d (DCCH), NB_TX_MAC = %d (%d bits/TTI, %d kbits/sec), NB_RX_MAC = %d (%d errors)\n",
UE_mac_inst[Mod_id].Dcch_lchan[CH_index].Lchan_info.Lchan_id.Index, UE_mac_inst[Mod_id].Dcch_lchan[CH_index].Lchan_info.Lchan_id.Index,
UE_mac_inst[Mod_id].Dcch_lchan[CH_index].Lchan_info.NB_TX, UE_mac_inst[Mod_id].Dcch_lchan[CH_index].Lchan_info.NB_TX,
UE_mac_inst[Mod_id].Dcch_lchan[CH_index].Lchan_info.output_rate, UE_mac_inst[Mod_id].Dcch_lchan[CH_index].Lchan_info.output_rate,
(10*UE_mac_inst[Mod_id].Dcch_lchan[CH_index].Lchan_info.output_rate)>>5, (10*UE_mac_inst[Mod_id].Dcch_lchan[CH_index].Lchan_info.output_rate)>>5,
UE_mac_inst[Mod_id].Dcch_lchan[CH_index].Lchan_info.NB_RX, UE_mac_inst[Mod_id].Dcch_lchan[CH_index].Lchan_info.NB_RX,
UE_mac_inst[Mod_id].Dcch_lchan[CH_index].Lchan_info.NB_RX_ERRORS); UE_mac_inst[Mod_id].Dcch_lchan[CH_index].Lchan_info.NB_RX_ERRORS);
for(i=1; i<NB_RAB_MAX; i++) { for(i=1; i<NB_RAB_MAX; i++) {
if (UE_mac_inst[Mod_id].Dtch_lchan[i][CH_index].Active==1) { if (UE_mac_inst[Mod_id].Dtch_lchan[i][CH_index].Active==1) {
Overhead=UE_mac_inst[Mod_id].Dtch_lchan[i][CH_index].Lchan_info.output_rate - Pdcp_stats_tx_rate[k][CH_index][i]; Overhead=UE_mac_inst[Mod_id].Dtch_lchan[i][CH_index].Lchan_info.output_rate - Pdcp_stats_tx_rate[k][CH_index][i];
if(Overhead<0) { if(Overhead<0) {
Overhead=-Overhead; Overhead=-Overhead;
Sign=-1; Sign=-1;
} else { } else {
Sign=1; Sign=1;
} }
len+=sprintf(&buffer[len], len+=sprintf(&buffer[len],
"[PDCP]LCHAN %d: NB_TX = %d ,Tx_rate =(%d bits/TTI ,%d Kbits/s), NB_RX = %d ,Rx_rate =(%d bits/TTI ,%d Kbits/s) , LAYER2 TX OVERHEAD: %d Kbits/s\n", "[PDCP]LCHAN %d: NB_TX = %d ,Tx_rate =(%d bits/TTI ,%d Kbits/s), NB_RX = %d ,Rx_rate =(%d bits/TTI ,%d Kbits/s) , LAYER2 TX OVERHEAD: %d Kbits/s\n",
UE_mac_inst[Mod_id].Dtch_lchan[i][CH_index].Lchan_info.Lchan_id.Index, UE_mac_inst[Mod_id].Dtch_lchan[i][CH_index].Lchan_info.Lchan_id.Index,
Pdcp_stats_tx[k][CH_index][i], Pdcp_stats_tx[k][CH_index][i],
Pdcp_stats_tx_rate[k][CH_index][i], Pdcp_stats_tx_rate[k][CH_index][i],
(10*Pdcp_stats_tx_rate[k][CH_index][i])>>5, (10*Pdcp_stats_tx_rate[k][CH_index][i])>>5,
Pdcp_stats_rx[k][CH_index][i], Pdcp_stats_rx[k][CH_index][i],
Pdcp_stats_rx_rate[k][CH_index][i], Pdcp_stats_rx_rate[k][CH_index][i],
(10*Pdcp_stats_rx_rate[k][CH_index][i])>>5, (10*Pdcp_stats_rx_rate[k][CH_index][i])>>5,
Sign*(10*Overhead)>>5); Sign*(10*Overhead)>>5);
int status = rlc_stat_req (k, int status = rlc_stat_req (k,
UE_mac_inst[Mod_id].Dtch_lchan[i][CH_index].Lchan_info.Lchan_id.Index, UE_mac_inst[Mod_id].Dtch_lchan[i][CH_index].Lchan_info.Lchan_id.Index,
&tx_pdcp_sdu, &tx_pdcp_sdu,
&tx_pdcp_sdu_discarded, &tx_pdcp_sdu_discarded,
&tx_retransmit_pdu_unblock, &tx_retransmit_pdu_unblock,
&tx_retransmit_pdu_by_status, &tx_retransmit_pdu_by_status,
&tx_retransmit_pdu, &tx_retransmit_pdu,
&tx_data_pdu, &tx_data_pdu,
&tx_control_pdu, &tx_control_pdu,
&rx_sdu, &rx_sdu,
&rx_error_pdu, &rx_error_pdu,
&rx_data_pdu, &rx_data_pdu,
&rx_data_pdu_out_of_window, &rx_data_pdu_out_of_window,
&rx_control_pdu) ; &rx_control_pdu) ;
if (status == RLC_OP_STATUS_OK) { if (status == RLC_OP_STATUS_OK) {
len+=sprintf(&buffer[len],"RLC LCHAN %d, NB_SDU_TO_TX = %d\tNB_SDU_DISC %d\tNB_RX_SDU %d\n", len+=sprintf(&buffer[len],"RLC LCHAN %d, NB_SDU_TO_TX = %u\tNB_SDU_DISC %u\tNB_RX_SDU %u\n",
UE_mac_inst[Mod_id].Dtch_lchan[i][CH_index].Lchan_info.Lchan_id.Index, UE_mac_inst[Mod_id].Dtch_lchan[i][CH_index].Lchan_info.Lchan_id.Index,
tx_pdcp_sdu,
tx_pdcp_sdu_discarded,
rx_sdu);
len+=sprintf(&buffer[len],"RLC LCHAN %d, NB_TB_TX_DATA = %u\tNB_TB_TX_CONTROL %u\tNB_TX_TB_RETRANS %u",
UE_mac_inst[Mod_id].Dtch_lchan[i][CH_index].Lchan_info.Lchan_id.Index,
tx_data_pdu,
tx_control_pdu,
tx_retransmit_pdu);
len+=sprintf(&buffer[len],"\tRLC LCHAN %d, NB_TX_TB_RETRANS_BY_STATUS = %u\tNB_TX_TB_RETRANS_PADD %u\n",
UE_mac_inst[Mod_id].Dtch_lchan[i][CH_index].Lchan_info.Lchan_id.Index,
tx_retransmit_pdu_by_status,
tx_retransmit_pdu_unblock);
len+=sprintf(&buffer[len],"RLC LCHAN %d, NB_RX_DATA = %u\tNB_RX_TB_OUT_WIN %u\tNB_RX_TB_CORRUPT %u\n",
UE_mac_inst[Mod_id].Dtch_lchan[i][CH_index].Lchan_info.Lchan_id.Index,
rx_data_pdu,
rx_data_pdu_out_of_window,
rx_error_pdu);
}
len+=sprintf(&buffer[len],"[MAC]: LCHAN %d, NB_TX_MAC = %d (%d bits/TTI, %d kbits/s), NB_RX_MAC = %d (%d errors)\n",
UE_mac_inst[Mod_id].Dtch_lchan[i][CH_index].Lchan_info.Lchan_id.Index,
UE_mac_inst[Mod_id].Dtch_lchan[i][CH_index].Lchan_info.NB_TX,
UE_mac_inst[Mod_id].Dtch_lchan[i][CH_index].Lchan_info.output_rate,
(10*UE_mac_inst[Mod_id].Dtch_lchan[i][CH_index].Lchan_info.output_rate)>>5,
UE_mac_inst[Mod_id].Dtch_lchan[i][CH_index].Lchan_info.NB_RX,
UE_mac_inst[Mod_id].Dtch_lchan[i][CH_index].Lchan_info.NB_RX_ERRORS);
len+=sprintf(&buffer[len]," TX per TB: ");
for(kk=0; kk<MAX_NUMBER_TB_PER_LCHAN/2; kk++) {
len+=sprintf(&buffer[len],"%d . ",UE_mac_inst[Mod_id].Dtch_lchan[i][CH_index].Lchan_info.NB_TX_TB[kk]);
}
len+=sprintf(&buffer[len],"\n");
len+=sprintf(&buffer[len]," RXerr per TB: ");
for(kk=0; kk<MAX_NUMBER_TB_PER_LCHAN/2; kk++)
len+=sprintf(&buffer[len],"%d/%d . ",UE_mac_inst[Mod_id].Dtch_lchan[i][CH_index].Lchan_info.NB_RX_ERRORS_TB[kk],
UE_mac_inst[Mod_id].Dtch_lchan[i][CH_index].Lchan_info.NB_RX_TB[kk]);
len+=sprintf(&buffer[len],"\n");
}
}
}
}
#endif //PHY_EMUL_ONE_MACHINE
} else if(Mac_rlc_xface->Is_cluster_head[k] ==1) {
Mod_id=k;
len+=sprintf(&buffer[len],
"-------------------------------------------------------------------CH %d: TTI: %d------------------------------------------------------------------\n",
NODE_ID[Mod_id],Mac_rlc_xface->frame);
for(i=1; i<=NB_CNX_CH; i++) {
if (CH_mac_inst[Mod_id].Dcch_lchan[i].Active==1) {
len+=sprintf(&buffer[len],"\nMR index %u: DL SINR (feedback) %d dB, CQI: %s\n\n",
i,//CH_rrc_inst[Mod_id].Info.UE_list[i].L2_id[0],
CH_mac_inst[Mod_id].Def_meas[i].Wideband_sinr,
print_cqi(CH_mac_inst[Mod_id].Def_meas[i].cqi));
len+=sprintf(&buffer[len],
"[MAC] LCHAN %d (DCCH), NB_TX_MAC= %d (%d bits/TTI, %d kbits/s), NB_RX_MAC= %d (errors %d, sacch errors %d, sach errors %d, sach_missing %d)\n\n",
CH_mac_inst[Mod_id].Dcch_lchan[i].Lchan_info.Lchan_id.Index,
CH_mac_inst[Mod_id].Dcch_lchan[i].Lchan_info.NB_TX,
CH_mac_inst[Mod_id].Dcch_lchan[i].Lchan_info.output_rate,
(10*CH_mac_inst[Mod_id].Dcch_lchan[i].Lchan_info.output_rate)>>5,
CH_mac_inst[Mod_id].Dcch_lchan[i].Lchan_info.NB_RX,
CH_mac_inst[Mod_id].Dcch_lchan[i].Lchan_info.NB_RX_ERRORS,
CH_mac_inst[Mod_id].Dcch_lchan[i].Lchan_info.NB_RX_SACCH_ERRORS,
CH_mac_inst[Mod_id].Dcch_lchan[i].Lchan_info.NB_RX_SACH_ERRORS,
CH_mac_inst[Mod_id].Dcch_lchan[i].Lchan_info.NB_RX_SACH_MISSING);
for(j=0; j<NB_RAB_MAX; j++) {
if (CH_mac_inst[Mod_id].Dtch_lchan[j][i].Active==1) {
Overhead=CH_mac_inst[Mod_id].Dtch_lchan[j][i].Lchan_info.output_rate - Pdcp_stats_tx_rate[k][i][j];
if(Overhead<0) {
Overhead=-Overhead;
Sign=-1;
} else {
Sign=1;
}
len+=sprintf(&buffer[len],
"[PDCP]LCHAN %d: NB_TX = %d ,Tx_rate =(%d bits/TTI ,%d Kbits/s), NB_RX = %d ,Rx_rate =(%d bits/TTI ,%d Kbits/s), LAYER2 TX OVERHEAD= %d Kbits/s\n",
CH_mac_inst[Mod_id].Dtch_lchan[j][i].Lchan_info.Lchan_id.Index,
Pdcp_stats_tx[k][i][j],
Pdcp_stats_tx_rate[k][i][j],
(10*Pdcp_stats_tx_rate[k][i][j])>>5,
Pdcp_stats_rx[k][i][j],
Pdcp_stats_rx_rate[k][i][j],
(10*Pdcp_stats_rx_rate[k][i][j])>>5,
Sign*(10*Overhead)>>5);
int status = rlc_stat_req (k,
CH_mac_inst[Mod_id].Dtch_lchan[j][i].Lchan_info.Lchan_id.Index,
&tx_pdcp_sdu,
&tx_pdcp_sdu_discarded,
&tx_retransmit_pdu_unblock,
&tx_retransmit_pdu_by_status,
&tx_retransmit_pdu,
&tx_data_pdu,
&tx_control_pdu,
&rx_sdu,
&rx_error_pdu,
&rx_data_pdu,
&rx_data_pdu_out_of_window,
&rx_control_pdu) ;
/*
if (status == RLC_OP_STATUS_OK) {
len+=sprintf(&buffer[len],"\t[RLC] LCHAN %d, NB_SDU_TO_TX = %d\tNB_SDU_DISC %d\tNB_RX_SDU %d\n",
CH_mac_inst[Mod_id].Dtch_lchan[j][i].Lchan_info.Lchan_id.Index,
tx_pdcp_sdu, tx_pdcp_sdu,
tx_pdcp_sdu_discarded, tx_pdcp_sdu_discarded,
rx_sdu); rx_sdu);
len+=sprintf(&buffer[len],"RLC LCHAN %d, NB_TB_TX_DATA = %d\tNB_TB_TX_CONTROL %d\tNB_TX_TB_RETRANS %d", len+=sprintf(&buffer[len],"\t[RLC] LCHAN %d, NB_TB_TX_DATA = %d\tNB_TB_TX_CONTROL %d\tNB_TX_TB_RETRANS %\n",
UE_mac_inst[Mod_id].Dtch_lchan[i][CH_index].Lchan_info.Lchan_id.Index, CH_mac_inst[Mod_id].Dtch_lchan[j][i].Lchan_info.Lchan_id.Index,
tx_data_pdu, tx_data_pdu,
tx_control_pdu, tx_control_pdu,
tx_retransmit_pdu); tx_retransmit_pdu);
len+=sprintf(&buffer[len],"\tRLC LCHAN %d, NB_TX_TB_RETRANS_BY_STATUS = %d\tNB_TX_TB_RETRANS_PADD %d\n", len+=sprintf(&buffer[len],"\t[RLC] LCHAN %d, NB_TX_TB_RETRANS_BY_STATUS = %d\tNB_TX_TB_RETRANS_PADD %d\n",
UE_mac_inst[Mod_id].Dtch_lchan[i][CH_index].Lchan_info.Lchan_id.Index, CH_mac_inst[Mod_id].Dtch_lchan[j][i].Lchan_info.Lchan_id.Index,
tx_retransmit_pdu_by_status, tx_retransmit_pdu_by_status,
tx_retransmit_pdu_unblock); tx_retransmit_pdu_unblock);
len+=sprintf(&buffer[len],"RLC LCHAN %d, NB_RX_DATA = %d\tNB_RX_TB_OUT_WIN %d\tNB_RX_TB_CORRUPT %d\n", len+=sprintf(&buffer[len],"\t[RLC] LCHAN %d, NB_RX_DATA = %d\tNB_RX_TB_OUT_WIN %d\tNB_RX_TB_CORRUPT %d\n",
UE_mac_inst[Mod_id].Dtch_lchan[i][CH_index].Lchan_info.Lchan_id.Index, CH_mac_inst[Mod_id].Dtch_lchan[j][i].Lchan_info.Lchan_id.Index,
rx_data_pdu, rx_data_pdu,
rx_data_pdu_out_of_window, rx_data_pdu_out_of_window,
rx_error_pdu); rx_error_pdu);
} }
*/
len+=sprintf(&buffer[len],"[MAC]: LCHAN %d, NB_TX_MAC = %d (%d bits/TTI, %d kbits/s), NB_RX_MAC = %d (%d errors)\n", len+=sprintf(&buffer[len],
UE_mac_inst[Mod_id].Dtch_lchan[i][CH_index].Lchan_info.Lchan_id.Index, "[MAC]LCHAN %d (CNX %u,RAB %u), NB_TX_MAC= %d (%d bits/TTI, %d kbit/s), NB_RX_MAC= %d (errors %d, sacch_errors %d, sach_errors %d, sach_missing %d)\n",
UE_mac_inst[Mod_id].Dtch_lchan[i][CH_index].Lchan_info.NB_TX, CH_mac_inst[Mod_id].Dtch_lchan[j][i].Lchan_info.Lchan_id.Index,
UE_mac_inst[Mod_id].Dtch_lchan[i][CH_index].Lchan_info.output_rate, i,j,
(10*UE_mac_inst[Mod_id].Dtch_lchan[i][CH_index].Lchan_info.output_rate)>>5, CH_mac_inst[Mod_id].Dtch_lchan[j][i].Lchan_info.NB_TX,
UE_mac_inst[Mod_id].Dtch_lchan[i][CH_index].Lchan_info.NB_RX, CH_mac_inst[Mod_id].Dtch_lchan[j][i].Lchan_info.output_rate,
UE_mac_inst[Mod_id].Dtch_lchan[i][CH_index].Lchan_info.NB_RX_ERRORS); (10*CH_mac_inst[Mod_id].Dtch_lchan[j][i].Lchan_info.output_rate)>>5,
len+=sprintf(&buffer[len]," TX per TB: "); CH_mac_inst[Mod_id].Dtch_lchan[j][i].Lchan_info.NB_RX,
CH_mac_inst[Mod_id].Dtch_lchan[j][i].Lchan_info.NB_RX_ERRORS,
for(kk=0; kk<MAX_NUMBER_TB_PER_LCHAN/2; kk++) { CH_mac_inst[Mod_id].Dtch_lchan[j][i].Lchan_info.NB_RX_SACCH_ERRORS,
len+=sprintf(&buffer[len],"%d . ",UE_mac_inst[Mod_id].Dtch_lchan[i][CH_index].Lchan_info.NB_TX_TB[kk]); CH_mac_inst[Mod_id].Dtch_lchan[j][i].Lchan_info.NB_RX_SACH_ERRORS,
} CH_mac_inst[Mod_id].Dtch_lchan[j][i].Lchan_info.NB_RX_SACH_MISSING);
len+=sprintf(&buffer[len],"[MAC][SCHEDULER] TX Arrival Rate %d, TX Service Rate %d, RX Arrival rate %d, RX Service rate %d, NB_BW_REQ_RX %d\n\n",
len+=sprintf(&buffer[len],"\n"); CH_mac_inst[Mod_id].Dtch_lchan[j][i].Lchan_info.Arrival_rate,
len+=sprintf(&buffer[len]," RXerr per TB: "); CH_mac_inst[Mod_id].Dtch_lchan[j][i].Lchan_info.Tx_rate,
CH_mac_inst[Mod_id].Dtch_lchan[j][i].Lchan_info.Req_rate,
for(kk=0; kk<MAX_NUMBER_TB_PER_LCHAN/2; kk++) CH_mac_inst[Mod_id].Dtch_lchan[j][i].Lchan_info.Rx_rate,
len+=sprintf(&buffer[len],"%d/%d . ",UE_mac_inst[Mod_id].Dtch_lchan[i][CH_index].Lchan_info.NB_RX_ERRORS_TB[kk], CH_mac_inst[Mod_id].Dtch_lchan[j][i].Lchan_info.NB_BW_REQ_RX);
UE_mac_inst[Mod_id].Dtch_lchan[i][CH_index].Lchan_info.NB_RX_TB[kk]); /*
len+=sprintf(&buffer[len]," TX per TB: ");
len+=sprintf(&buffer[len],"\n"); for(kk=0;kk<MAX_NUMBER_TB_PER_LCHAN/2;kk++)
} len+=sprintf(&buffer[len],"%d.",CH_mac_inst[Mod_id].Dtch_lchan[j][i].Lchan_info.NB_TX_TB[kk]);
} len+=sprintf(&buffer[len],"\n");
} len+=sprintf(&buffer[len]," RXerr per TB: ");
} for(kk=0;kk<MAX_NUMBER_TB_PER_LCHAN/2;kk++)
len+=sprintf(&buffer[len],"%d/%d . ",CH_mac_inst[Mod_id].Dtch_lchan[j][i].Lchan_info.NB_RX_ERRORS_TB[kk],
#endif //PHY_EMUL_ONE_MACHINE CH_mac_inst[Mod_id].Dtch_lchan[j][i].Lchan_info.NB_RX_TB[kk]);
} else if(Mac_rlc_xface->Is_cluster_head[k] ==1) { len+=sprintf(&buffer[len],"\n");
Mod_id=k; */
len+=sprintf(&buffer[len], }
"-------------------------------------------------------------------CH %d: TTI: %d------------------------------------------------------------------\n", }
NODE_ID[Mod_id],Mac_rlc_xface->frame); }
for(i=1; i<=NB_CNX_CH; i++) {
if (CH_mac_inst[Mod_id].Dcch_lchan[i].Active==1) {
len+=sprintf(&buffer[len],"\nMR index %d: DL SINR (feedback) %d dB, CQI: %s\n\n",
i,//CH_rrc_inst[Mod_id].Info.UE_list[i].L2_id[0],
CH_mac_inst[Mod_id].Def_meas[i].Wideband_sinr,
print_cqi(CH_mac_inst[Mod_id].Def_meas[i].cqi));
len+=sprintf(&buffer[len],
"[MAC] LCHAN %d (DCCH), NB_TX_MAC= %d (%d bits/TTI, %d kbits/s), NB_RX_MAC= %d (errors %d, sacch errors %d, sach errors %d, sach_missing %d)\n\n",
CH_mac_inst[Mod_id].Dcch_lchan[i].Lchan_info.Lchan_id.Index,
CH_mac_inst[Mod_id].Dcch_lchan[i].Lchan_info.NB_TX,
CH_mac_inst[Mod_id].Dcch_lchan[i].Lchan_info.output_rate,
(10*CH_mac_inst[Mod_id].Dcch_lchan[i].Lchan_info.output_rate)>>5,
CH_mac_inst[Mod_id].Dcch_lchan[i].Lchan_info.NB_RX,
CH_mac_inst[Mod_id].Dcch_lchan[i].Lchan_info.NB_RX_ERRORS,
CH_mac_inst[Mod_id].Dcch_lchan[i].Lchan_info.NB_RX_SACCH_ERRORS,
CH_mac_inst[Mod_id].Dcch_lchan[i].Lchan_info.NB_RX_SACH_ERRORS,
CH_mac_inst[Mod_id].Dcch_lchan[i].Lchan_info.NB_RX_SACH_MISSING);
for(j=0; j<NB_RAB_MAX; j++) {
if (CH_mac_inst[Mod_id].Dtch_lchan[j][i].Active==1) {
Overhead=CH_mac_inst[Mod_id].Dtch_lchan[j][i].Lchan_info.output_rate - Pdcp_stats_tx_rate[k][i][j];
if(Overhead<0) {
Overhead=-Overhead;
Sign=-1;
} else {
Sign=1;
}
len+=sprintf(&buffer[len],
"[PDCP]LCHAN %d: NB_TX = %d ,Tx_rate =(%d bits/TTI ,%d Kbits/s), NB_RX = %d ,Rx_rate =(%d bits/TTI ,%d Kbits/s), LAYER2 TX OVERHEAD= %d Kbits/s\n",
CH_mac_inst[Mod_id].Dtch_lchan[j][i].Lchan_info.Lchan_id.Index,
Pdcp_stats_tx[k][i][j],
Pdcp_stats_tx_rate[k][i][j],
(10*Pdcp_stats_tx_rate[k][i][j])>>5,
Pdcp_stats_rx[k][i][j],
Pdcp_stats_rx_rate[k][i][j],
(10*Pdcp_stats_rx_rate[k][i][j])>>5,
Sign*(10*Overhead)>>5);
int status = rlc_stat_req (k,
CH_mac_inst[Mod_id].Dtch_lchan[j][i].Lchan_info.Lchan_id.Index,
&tx_pdcp_sdu,
&tx_pdcp_sdu_discarded,
&tx_retransmit_pdu_unblock,
&tx_retransmit_pdu_by_status,
&tx_retransmit_pdu,
&tx_data_pdu,
&tx_control_pdu,
&rx_sdu,
&rx_error_pdu,
&rx_data_pdu,
&rx_data_pdu_out_of_window,
&rx_control_pdu) ;
/*
if (status == RLC_OP_STATUS_OK) {
len+=sprintf(&buffer[len],"\t[RLC] LCHAN %d, NB_SDU_TO_TX = %d\tNB_SDU_DISC %d\tNB_RX_SDU %d\n",
CH_mac_inst[Mod_id].Dtch_lchan[j][i].Lchan_info.Lchan_id.Index,
tx_pdcp_sdu,
tx_pdcp_sdu_discarded,
rx_sdu);
len+=sprintf(&buffer[len],"\t[RLC] LCHAN %d, NB_TB_TX_DATA = %d\tNB_TB_TX_CONTROL %d\tNB_TX_TB_RETRANS %\n",
CH_mac_inst[Mod_id].Dtch_lchan[j][i].Lchan_info.Lchan_id.Index,
tx_data_pdu,
tx_control_pdu,
tx_retransmit_pdu);
len+=sprintf(&buffer[len],"\t[RLC] LCHAN %d, NB_TX_TB_RETRANS_BY_STATUS = %d\tNB_TX_TB_RETRANS_PADD %d\n",
CH_mac_inst[Mod_id].Dtch_lchan[j][i].Lchan_info.Lchan_id.Index,
tx_retransmit_pdu_by_status,
tx_retransmit_pdu_unblock);
len+=sprintf(&buffer[len],"\t[RLC] LCHAN %d, NB_RX_DATA = %d\tNB_RX_TB_OUT_WIN %d\tNB_RX_TB_CORRUPT %d\n",
CH_mac_inst[Mod_id].Dtch_lchan[j][i].Lchan_info.Lchan_id.Index,
rx_data_pdu,
rx_data_pdu_out_of_window,
rx_error_pdu);
}
*/
len+=sprintf(&buffer[len],
"[MAC]LCHAN %d (CNX %d,RAB %d), NB_TX_MAC= %d (%d bits/TTI, %d kbit/s), NB_RX_MAC= %d (errors %d, sacch_errors %d, sach_errors %d, sach_missing %d)\n",
CH_mac_inst[Mod_id].Dtch_lchan[j][i].Lchan_info.Lchan_id.Index,
i,j,
CH_mac_inst[Mod_id].Dtch_lchan[j][i].Lchan_info.NB_TX,
CH_mac_inst[Mod_id].Dtch_lchan[j][i].Lchan_info.output_rate,
(10*CH_mac_inst[Mod_id].Dtch_lchan[j][i].Lchan_info.output_rate)>>5,
CH_mac_inst[Mod_id].Dtch_lchan[j][i].Lchan_info.NB_RX,
CH_mac_inst[Mod_id].Dtch_lchan[j][i].Lchan_info.NB_RX_ERRORS,
CH_mac_inst[Mod_id].Dtch_lchan[j][i].Lchan_info.NB_RX_SACCH_ERRORS,
CH_mac_inst[Mod_id].Dtch_lchan[j][i].Lchan_info.NB_RX_SACH_ERRORS,
CH_mac_inst[Mod_id].Dtch_lchan[j][i].Lchan_info.NB_RX_SACH_MISSING);
len+=sprintf(&buffer[len],"[MAC][SCHEDULER] TX Arrival Rate %d, TX Service Rate %d, RX Arrival rate %d, RX Service rate %d, NB_BW_REQ_RX %d\n\n",
CH_mac_inst[Mod_id].Dtch_lchan[j][i].Lchan_info.Arrival_rate,
CH_mac_inst[Mod_id].Dtch_lchan[j][i].Lchan_info.Tx_rate,
CH_mac_inst[Mod_id].Dtch_lchan[j][i].Lchan_info.Req_rate,
CH_mac_inst[Mod_id].Dtch_lchan[j][i].Lchan_info.Rx_rate,
CH_mac_inst[Mod_id].Dtch_lchan[j][i].Lchan_info.NB_BW_REQ_RX);
/*
len+=sprintf(&buffer[len]," TX per TB: ");
for(kk=0;kk<MAX_NUMBER_TB_PER_LCHAN/2;kk++)
len+=sprintf(&buffer[len],"%d.",CH_mac_inst[Mod_id].Dtch_lchan[j][i].Lchan_info.NB_TX_TB[kk]);
len+=sprintf(&buffer[len],"\n");
len+=sprintf(&buffer[len]," RXerr per TB: ");
for(kk=0;kk<MAX_NUMBER_TB_PER_LCHAN/2;kk++)
len+=sprintf(&buffer[len],"%d/%d . ",CH_mac_inst[Mod_id].Dtch_lchan[j][i].Lchan_info.NB_RX_ERRORS_TB[kk],
CH_mac_inst[Mod_id].Dtch_lchan[j][i].Lchan_info.NB_RX_TB[kk]);
len+=sprintf(&buffer[len],"\n");
*/
} }
}
} }
}
} }
}
return len; return len;
} }
#endif #endif
...@@ -88,41 +88,41 @@ static int _at_response_encode_cgev (char* buffer, const at_response_t* data); ...@@ -88,41 +88,41 @@ static int _at_response_encode_cgev (char* buffer, const at_response_t* data);
typedef int (*_at_response_encode_function_t) (char* buffer, const at_response_t*); typedef int (*_at_response_encode_function_t) (char* buffer, const at_response_t*);
static _at_response_encode_function_t _at_response_encode_function[AT_RESPONSE_ID_MAX] = { static _at_response_encode_function_t _at_response_encode_function[AT_RESPONSE_ID_MAX] = {
NULL, NULL,
_at_response_encode_cgsn, /* CGSN */ _at_response_encode_cgsn, /* CGSN */
_at_response_encode_cgmi, /* CGMI */ _at_response_encode_cgmi, /* CGMI */
_at_response_encode_cgmm, /* CGMM */ _at_response_encode_cgmm, /* CGMM */
_at_response_encode_cgmr, /* CGMR */ _at_response_encode_cgmr, /* CGMR */
_at_response_encode_cimi, /* CIMI */ _at_response_encode_cimi, /* CIMI */
_at_response_encode_cfun, /* CFUN */ _at_response_encode_cfun, /* CFUN */
_at_response_encode_cpin, /* CPIN */ _at_response_encode_cpin, /* CPIN */
_at_response_encode_csq, /* CSQ */ _at_response_encode_csq, /* CSQ */
_at_response_encode_cesq, /* CESQ */ _at_response_encode_cesq, /* CESQ */
_at_response_encode_clac, /* CLAC */ _at_response_encode_clac, /* CLAC */
_at_response_encode_cmee, /* CMEE */ _at_response_encode_cmee, /* CMEE */
_at_response_encode_cnum, /* CNUM */ _at_response_encode_cnum, /* CNUM */
_at_response_encode_clck, /* CLCK */ _at_response_encode_clck, /* CLCK */
_at_response_encode_cops, /* COPS */ _at_response_encode_cops, /* COPS */
_at_response_encode_creg, /* CREG */ _at_response_encode_creg, /* CREG */
_at_response_encode_cgatt, /* CGATT */ _at_response_encode_cgatt, /* CGATT */
_at_response_encode_cgreg, /* CGREG */ _at_response_encode_cgreg, /* CGREG */
_at_response_encode_cereg, /* CEREG */ _at_response_encode_cereg, /* CEREG */
_at_response_encode_cgdcont, /* CGDCONT */ _at_response_encode_cgdcont, /* CGDCONT */
_at_response_encode_cgact, /* CGACT */ _at_response_encode_cgact, /* CGACT */
_at_response_encode_cgpaddr, /* CGPADDR */ _at_response_encode_cgpaddr, /* CGPADDR */
_at_response_encode_cgev, /* CGEV: unsolicited result */ _at_response_encode_cgev, /* CGEV: unsolicited result */
}; };
/* String representation of Packet Domain events (cf. network_pdn_state_t) */ /* String representation of Packet Domain events (cf. network_pdn_state_t) */
static const char* _at_response_event_str[] = { static const char* _at_response_event_str[] = {
"UNKNOWN EVENT", "UNKNOWN EVENT",
"ME PDN ACT", "ME PDN ACT",
"NW PDN DEACT", "NW PDN DEACT",
"ME PDN DEACT", "ME PDN DEACT",
"NW ACT", "NW ACT",
"ME ACT", "ME ACT",
"NW DEACT", "NW DEACT",
"ME DEACT", "ME DEACT",
}; };
/****************************************************************************/ /****************************************************************************/
...@@ -147,24 +147,24 @@ static const char* _at_response_event_str[] = { ...@@ -147,24 +147,24 @@ static const char* _at_response_event_str[] = {
***************************************************************************/ ***************************************************************************/
int at_response_encode(char* buffer, const at_response_t* at_response) int at_response_encode(char* buffer, const at_response_t* at_response)
{ {
LOG_FUNC_IN; LOG_FUNC_IN;
int bytes = RETURNerror; int bytes = RETURNerror;
_at_response_encode_function_t encode; _at_response_encode_function_t encode;
if (at_response->id < AT_RESPONSE_ID_MAX) { if (at_response->id < AT_RESPONSE_ID_MAX) {
/* Call encoding function applicable to the AT command response */ /* Call encoding function applicable to the AT command response */
encode = _at_response_encode_function[at_response->id]; encode = _at_response_encode_function[at_response->id];
if (encode != NULL) { if (encode != NULL) {
bytes = (*encode)(buffer, at_response); bytes = (*encode)(buffer, at_response);
} else { } else {
/* Generic encoding: OK, ERROR */ /* Generic encoding: OK, ERROR */
bytes = 0; bytes = 0;
}
} }
}
LOG_FUNC_RETURN (bytes); LOG_FUNC_RETURN (bytes);
} }
/****************************************************************************/ /****************************************************************************/
...@@ -188,21 +188,21 @@ int at_response_encode(char* buffer, const at_response_t* at_response) ...@@ -188,21 +188,21 @@ int at_response_encode(char* buffer, const at_response_t* at_response)
***************************************************************************/ ***************************************************************************/
static int _at_response_encode_cgsn(char* buffer, const at_response_t* data) static int _at_response_encode_cgsn(char* buffer, const at_response_t* data)
{ {
LOG_FUNC_IN; LOG_FUNC_IN;
int offset = 0; int offset = 0;
if (data->type == AT_COMMAND_ACT) { if (data->type == AT_COMMAND_ACT) {
const at_cgsn_resp_t * cgsn = &(data->response.cgsn); const at_cgsn_resp_t * cgsn = &(data->response.cgsn);
if (at_response_format_v1) { if (at_response_format_v1) {
offset += sprintf(buffer, "\r\n"); offset += sprintf(buffer, "\r\n");
} }
offset += sprintf(buffer+offset, "+CGSN: %s\r\n", cgsn->sn); offset += sprintf(buffer+offset, "+CGSN: %s\r\n", cgsn->sn);
} }
LOG_FUNC_RETURN (offset); LOG_FUNC_RETURN (offset);
} }
/**************************************************************************** /****************************************************************************
...@@ -222,21 +222,21 @@ static int _at_response_encode_cgsn(char* buffer, const at_response_t* data) ...@@ -222,21 +222,21 @@ static int _at_response_encode_cgsn(char* buffer, const at_response_t* data)
***************************************************************************/ ***************************************************************************/
static int _at_response_encode_cgmi(char* buffer, const at_response_t* data) static int _at_response_encode_cgmi(char* buffer, const at_response_t* data)
{ {
LOG_FUNC_IN; LOG_FUNC_IN;
int offset = 0; int offset = 0;
if (data->type == AT_COMMAND_ACT) { if (data->type == AT_COMMAND_ACT) {
const at_cgmi_resp_t * cgmi = &(data->response.cgmi); const at_cgmi_resp_t * cgmi = &(data->response.cgmi);
if (at_response_format_v1) { if (at_response_format_v1) {
offset += sprintf(buffer, "\r\n"); offset += sprintf(buffer, "\r\n");
} }
offset += sprintf(buffer+offset, "+CGMI: %s\r\n", cgmi->manufacturer); offset += sprintf(buffer+offset, "+CGMI: %s\r\n", cgmi->manufacturer);
} }
LOG_FUNC_RETURN (offset); LOG_FUNC_RETURN (offset);
} }
/**************************************************************************** /****************************************************************************
...@@ -256,21 +256,21 @@ static int _at_response_encode_cgmi(char* buffer, const at_response_t* data) ...@@ -256,21 +256,21 @@ static int _at_response_encode_cgmi(char* buffer, const at_response_t* data)
***************************************************************************/ ***************************************************************************/
static int _at_response_encode_cgmm(char* buffer, const at_response_t* data) static int _at_response_encode_cgmm(char* buffer, const at_response_t* data)
{ {
LOG_FUNC_IN; LOG_FUNC_IN;
int offset = 0; int offset = 0;
if (data->type == AT_COMMAND_ACT) { if (data->type == AT_COMMAND_ACT) {
const at_cgmm_resp_t * cgmm = &(data->response.cgmm); const at_cgmm_resp_t * cgmm = &(data->response.cgmm);
if (at_response_format_v1) { if (at_response_format_v1) {
offset += sprintf(buffer, "\r\n"); offset += sprintf(buffer, "\r\n");
} }
offset += sprintf(buffer+offset, "+CGMM: %s\r\n", cgmm->model); offset += sprintf(buffer+offset, "+CGMM: %s\r\n", cgmm->model);
} }
LOG_FUNC_RETURN (offset); LOG_FUNC_RETURN (offset);
} }
/**************************************************************************** /****************************************************************************
...@@ -290,21 +290,21 @@ static int _at_response_encode_cgmm(char* buffer, const at_response_t* data) ...@@ -290,21 +290,21 @@ static int _at_response_encode_cgmm(char* buffer, const at_response_t* data)
***************************************************************************/ ***************************************************************************/
static int _at_response_encode_cgmr(char* buffer, const at_response_t* data) static int _at_response_encode_cgmr(char* buffer, const at_response_t* data)
{ {
LOG_FUNC_IN; LOG_FUNC_IN;
int offset = 0; int offset = 0;
if (data->type == AT_COMMAND_ACT) { if (data->type == AT_COMMAND_ACT) {
const at_cgmr_resp_t * cgmr = &(data->response.cgmr); const at_cgmr_resp_t * cgmr = &(data->response.cgmr);
if (at_response_format_v1) { if (at_response_format_v1) {
offset += sprintf(buffer, "\r\n"); offset += sprintf(buffer, "\r\n");
} }
offset += sprintf(buffer+offset, "+CGMR: %s\r\n", cgmr->revision); offset += sprintf(buffer+offset, "+CGMR: %s\r\n", cgmr->revision);
} }
LOG_FUNC_RETURN (offset); LOG_FUNC_RETURN (offset);
} }
/**************************************************************************** /****************************************************************************
...@@ -324,21 +324,21 @@ static int _at_response_encode_cgmr(char* buffer, const at_response_t* data) ...@@ -324,21 +324,21 @@ static int _at_response_encode_cgmr(char* buffer, const at_response_t* data)
***************************************************************************/ ***************************************************************************/
static int _at_response_encode_cimi(char* buffer, const at_response_t* data) static int _at_response_encode_cimi(char* buffer, const at_response_t* data)
{ {
LOG_FUNC_IN; LOG_FUNC_IN;
int offset = 0; int offset = 0;
if (data->type == AT_COMMAND_ACT) { if (data->type == AT_COMMAND_ACT) {
const at_cimi_resp_t * cimi = &(data->response.cimi); const at_cimi_resp_t * cimi = &(data->response.cimi);
if (at_response_format_v1) { if (at_response_format_v1) {
offset += sprintf(buffer, "\r\n"); offset += sprintf(buffer, "\r\n");
} }
offset += sprintf(buffer+offset, "+CIMI: %s\r\n", cimi->IMSI); offset += sprintf(buffer+offset, "+CIMI: %s\r\n", cimi->IMSI);
} }
LOG_FUNC_RETURN (offset); LOG_FUNC_RETURN (offset);
} }
/**************************************************************************** /****************************************************************************
...@@ -358,27 +358,27 @@ static int _at_response_encode_cimi(char* buffer, const at_response_t* data) ...@@ -358,27 +358,27 @@ static int _at_response_encode_cimi(char* buffer, const at_response_t* data)
***************************************************************************/ ***************************************************************************/
static int _at_response_encode_cfun(char* buffer, const at_response_t* data) static int _at_response_encode_cfun(char* buffer, const at_response_t* data)
{ {
LOG_FUNC_IN; LOG_FUNC_IN;
const at_cfun_resp_t * cfun = &(data->response.cfun); const at_cfun_resp_t * cfun = &(data->response.cfun);
int offset = 0; int offset = 0;
if (data->type == AT_COMMAND_GET) { if (data->type == AT_COMMAND_GET) {
if (at_response_format_v1) { if (at_response_format_v1) {
offset += sprintf(buffer, "\r\n"); offset += sprintf(buffer, "\r\n");
} }
offset += sprintf(buffer+offset, "+CFUN: %d\r\n", cfun->fun); offset += sprintf(buffer+offset, "+CFUN: %d\r\n", cfun->fun);
} else if (data->type == AT_COMMAND_TST) { } else if (data->type == AT_COMMAND_TST) {
if (at_response_format_v1) { if (at_response_format_v1) {
offset += sprintf(buffer, "\r\n"); offset += sprintf(buffer, "\r\n");
} }
offset += sprintf(buffer+offset, "+CFUN: (%d-%d),(%d,%d)\r\n", offset += sprintf(buffer+offset, "+CFUN: (%d-%d),(%d,%d)\r\n",
AT_CFUN_MIN, AT_CFUN_MAX, AT_CFUN_NORST, AT_CFUN_RST); AT_CFUN_MIN, AT_CFUN_MAX, AT_CFUN_NORST, AT_CFUN_RST);
} }
LOG_FUNC_RETURN (offset); LOG_FUNC_RETURN (offset);
} }
/**************************************************************************** /****************************************************************************
...@@ -398,21 +398,21 @@ static int _at_response_encode_cfun(char* buffer, const at_response_t* data) ...@@ -398,21 +398,21 @@ static int _at_response_encode_cfun(char* buffer, const at_response_t* data)
***************************************************************************/ ***************************************************************************/
static int _at_response_encode_cpin(char* buffer, const at_response_t* data) static int _at_response_encode_cpin(char* buffer, const at_response_t* data)
{ {
LOG_FUNC_IN; LOG_FUNC_IN;
int offset = 0; int offset = 0;
if (data->type == AT_COMMAND_GET) { if (data->type == AT_COMMAND_GET) {
const at_cpin_resp_t * cpin = &(data->response.cpin); const at_cpin_resp_t * cpin = &(data->response.cpin);
if (at_response_format_v1) { if (at_response_format_v1) {
offset += sprintf(buffer, "\r\n"); offset += sprintf(buffer, "\r\n");
} }
offset += sprintf(buffer+offset, "+CPIN: %s\r\n", cpin->code); offset += sprintf(buffer+offset, "+CPIN: %s\r\n", cpin->code);
} }
LOG_FUNC_RETURN (offset); LOG_FUNC_RETURN (offset);
} }
/**************************************************************************** /****************************************************************************
...@@ -432,29 +432,29 @@ static int _at_response_encode_cpin(char* buffer, const at_response_t* data) ...@@ -432,29 +432,29 @@ static int _at_response_encode_cpin(char* buffer, const at_response_t* data)
***************************************************************************/ ***************************************************************************/
static int _at_response_encode_csq(char* buffer, const at_response_t* data) static int _at_response_encode_csq(char* buffer, const at_response_t* data)
{ {
LOG_FUNC_IN; LOG_FUNC_IN;
const at_csq_resp_t * csq = &(data->response.csq); const at_csq_resp_t * csq = &(data->response.csq);
int offset = 0; int offset = 0;
if (data->type == AT_COMMAND_ACT) { if (data->type == AT_COMMAND_ACT) {
if (at_response_format_v1) { if (at_response_format_v1) {
offset += sprintf(buffer, "\r\n"); offset += sprintf(buffer, "\r\n");
}
offset += sprintf(buffer+offset, "+CSQ: %d,%d\r\n",
csq->rssi, csq->ber);
} else if (data->type == AT_COMMAND_TST) {
if (at_response_format_v1) {
offset += sprintf(buffer, "\r\n");
}
offset += sprintf(buffer+offset, "+CSQ: (%d-%d),(%d-%d)\r\n",
AT_CSQ_RSSI_0, AT_CSQ_RSSI_31,
AT_CSQ_BER_0, AT_CSQ_BER_7);
} }
offset += sprintf(buffer+offset, "+CSQ: %d,%d\r\n", LOG_FUNC_RETURN (offset);
csq->rssi, csq->ber);
} else if (data->type == AT_COMMAND_TST) {
if (at_response_format_v1) {
offset += sprintf(buffer, "\r\n");
}
offset += sprintf(buffer+offset, "+CSQ: (%d-%d),(%d-%d)\r\n",
AT_CSQ_RSSI_0, AT_CSQ_RSSI_31,
AT_CSQ_BER_0, AT_CSQ_BER_7);
}
LOG_FUNC_RETURN (offset);
} }
/**************************************************************************** /****************************************************************************
...@@ -474,35 +474,35 @@ static int _at_response_encode_csq(char* buffer, const at_response_t* data) ...@@ -474,35 +474,35 @@ static int _at_response_encode_csq(char* buffer, const at_response_t* data)
***************************************************************************/ ***************************************************************************/
static int _at_response_encode_cesq(char* buffer, const at_response_t* data) static int _at_response_encode_cesq(char* buffer, const at_response_t* data)
{ {
LOG_FUNC_IN; LOG_FUNC_IN;
const at_cesq_resp_t * cesq = &(data->response.cesq); const at_cesq_resp_t * cesq = &(data->response.cesq);
int offset = 0; int offset = 0;
if (data->type == AT_COMMAND_ACT) { if (data->type == AT_COMMAND_ACT) {
if (at_response_format_v1) { if (at_response_format_v1) {
offset += sprintf(buffer, "\r\n"); offset += sprintf(buffer, "\r\n");
}
offset += sprintf(buffer+offset, "+CESQ: %d,%d,%d,%d,%d,%d\r\n",
cesq->rssi, cesq->ber, cesq->rscp,
cesq->ecno, cesq->rsrq, cesq->rsrp);
} else if (data->type == AT_COMMAND_TST) {
if (at_response_format_v1) {
offset += sprintf(buffer, "\r\n");
}
offset += sprintf(buffer+offset, "+CESQ: (%d-%d),(%d-%d),(%d-%d),"
"(%d-%d),(%d-%d),(%d-%d)\r\n",
AT_CESQ_RSSI_0, AT_CESQ_RSSI_31,
AT_CESQ_BER_0, AT_CESQ_BER_7,
AT_CESQ_RSCP_0, AT_CESQ_RSCP_96,
AT_CESQ_ECNO_0, AT_CESQ_ECNO_49,
AT_CESQ_RSRQ_0, AT_CESQ_RSRQ_34,
AT_CESQ_RSRP_0, AT_CESQ_RSRP_97);
} }
offset += sprintf(buffer+offset, "+CESQ: %d,%d,%d,%d,%d,%d\r\n", LOG_FUNC_RETURN (offset);
cesq->rssi, cesq->ber, cesq->rscp,
cesq->ecno, cesq->rsrq, cesq->rsrp);
} else if (data->type == AT_COMMAND_TST) {
if (at_response_format_v1) {
offset += sprintf(buffer, "\r\n");
}
offset += sprintf(buffer+offset, "+CESQ: (%d-%d),(%d-%d),(%d-%d),"
"(%d-%d),(%d-%d),(%d-%d)\r\n",
AT_CESQ_RSSI_0, AT_CESQ_RSSI_31,
AT_CESQ_BER_0, AT_CESQ_BER_7,
AT_CESQ_RSCP_0, AT_CESQ_RSCP_96,
AT_CESQ_ECNO_0, AT_CESQ_ECNO_49,
AT_CESQ_RSRQ_0, AT_CESQ_RSRQ_34,
AT_CESQ_RSRP_0, AT_CESQ_RSRP_97);
}
LOG_FUNC_RETURN (offset);
} }
/**************************************************************************** /****************************************************************************
...@@ -522,27 +522,27 @@ static int _at_response_encode_cesq(char* buffer, const at_response_t* data) ...@@ -522,27 +522,27 @@ static int _at_response_encode_cesq(char* buffer, const at_response_t* data)
***************************************************************************/ ***************************************************************************/
static int _at_response_encode_clac(char* buffer, const at_response_t* data) static int _at_response_encode_clac(char* buffer, const at_response_t* data)
{ {
LOG_FUNC_IN; LOG_FUNC_IN;
const at_clac_resp_t * clac = &(data->response.clac); const at_clac_resp_t * clac = &(data->response.clac);
int offset = 0; int offset = 0;
int i; int i;
if (data->type == AT_COMMAND_ACT) { if (data->type == AT_COMMAND_ACT) {
if (clac->n_acs > 0) { if (clac->n_acs > 0) {
if (at_response_format_v1) { if (at_response_format_v1) {
offset += sprintf(buffer, "\r\n"); offset += sprintf(buffer, "\r\n");
} }
offset += sprintf(buffer+offset, "%s", clac->ac[0]); offset += sprintf(buffer+offset, "%s", clac->ac[0]);
for (i = 1; i < clac->n_acs; i++) { for (i = 1; i < clac->n_acs; i++) {
offset += sprintf(buffer+offset, "\r\n%s", clac->ac[i]); offset += sprintf(buffer+offset, "\r\n%s", clac->ac[i]);
} }
}
} }
}
LOG_FUNC_RETURN (offset); LOG_FUNC_RETURN (offset);
} }
/**************************************************************************** /****************************************************************************
...@@ -562,22 +562,22 @@ static int _at_response_encode_clac(char* buffer, const at_response_t* data) ...@@ -562,22 +562,22 @@ static int _at_response_encode_clac(char* buffer, const at_response_t* data)
***************************************************************************/ ***************************************************************************/
static int _at_response_encode_cnum(char* buffer, const at_response_t* data) static int _at_response_encode_cnum(char* buffer, const at_response_t* data)
{ {
LOG_FUNC_IN; LOG_FUNC_IN;
int offset = 0; int offset = 0;
if (data->type == AT_COMMAND_ACT) { if (data->type == AT_COMMAND_ACT) {
const at_cnum_resp_t * cnum = &(data->response.cnum); const at_cnum_resp_t * cnum = &(data->response.cnum);
if (at_response_format_v1) { if (at_response_format_v1) {
offset += sprintf(buffer, "\r\n"); offset += sprintf(buffer, "\r\n");
} }
offset += sprintf(buffer+offset, "+CNUM: ,%s,%u\r\n", offset += sprintf(buffer+offset, "+CNUM: ,%s,%u\r\n",
cnum->number, cnum->type); cnum->number, (unsigned int)cnum->type);
} }
LOG_FUNC_RETURN (offset); LOG_FUNC_RETURN (offset);
} }
/**************************************************************************** /****************************************************************************
...@@ -597,26 +597,26 @@ static int _at_response_encode_cnum(char* buffer, const at_response_t* data) ...@@ -597,26 +597,26 @@ static int _at_response_encode_cnum(char* buffer, const at_response_t* data)
***************************************************************************/ ***************************************************************************/
static int _at_response_encode_clck(char* buffer, const at_response_t* data) static int _at_response_encode_clck(char* buffer, const at_response_t* data)
{ {
LOG_FUNC_IN; LOG_FUNC_IN;
const at_clck_resp_t * clck = &(data->response.clck); const at_clck_resp_t * clck = &(data->response.clck);
int offset = 0; int offset = 0;
if (data->type == AT_COMMAND_SET) { if (data->type == AT_COMMAND_SET) {
if (at_response_format_v1) { if (at_response_format_v1) {
offset += sprintf(buffer, "\r\n"); offset += sprintf(buffer, "\r\n");
} }
offset += sprintf(buffer+offset, "+CLCK: %d\r\n", clck->status); offset += sprintf(buffer+offset, "+CLCK: %d\r\n", clck->status);
} else if (data->type == AT_COMMAND_TST) { } else if (data->type == AT_COMMAND_TST) {
if (at_response_format_v1) { if (at_response_format_v1) {
offset += sprintf(buffer, "\r\n"); offset += sprintf(buffer, "\r\n");
} }
offset += sprintf(buffer+offset, "+CLCK: %s\r\n", AT_CLCK_SC); offset += sprintf(buffer+offset, "+CLCK: %s\r\n", AT_CLCK_SC);
} }
LOG_FUNC_RETURN (offset); LOG_FUNC_RETURN (offset);
} }
/**************************************************************************** /****************************************************************************
...@@ -636,63 +636,63 @@ static int _at_response_encode_clck(char* buffer, const at_response_t* data) ...@@ -636,63 +636,63 @@ static int _at_response_encode_clck(char* buffer, const at_response_t* data)
***************************************************************************/ ***************************************************************************/
static int _at_response_encode_cops(char* buffer, const at_response_t* data) static int _at_response_encode_cops(char* buffer, const at_response_t* data)
{ {
LOG_FUNC_IN; LOG_FUNC_IN;
int offset = 0; int offset = 0;
if (data->type == AT_COMMAND_GET) { if (data->type == AT_COMMAND_GET) {
const at_cops_get_t * cops = &(data->response.cops.get); const at_cops_get_t * cops = &(data->response.cops.get);
if (at_response_format_v1) { if (at_response_format_v1) {
offset += sprintf(buffer, "\r\n"); offset += sprintf(buffer, "\r\n");
} }
offset += sprintf(buffer+offset, "+COPS: %d", cops->mode); offset += sprintf(buffer+offset, "+COPS: %d", cops->mode);
if (data->mask & AT_COPS_RESP_OPER_MASK) { if (data->mask & AT_COPS_RESP_OPER_MASK) {
/* If <oper> is present <format> must be given */ /* If <oper> is present <format> must be given */
assert(data->mask & AT_COPS_RESP_FORMAT_MASK); assert(data->mask & AT_COPS_RESP_FORMAT_MASK);
offset += sprintf(buffer+offset, ",%d", cops->format); offset += sprintf(buffer+offset, ",%d", cops->format);
if (cops->format == AT_COPS_LONG) { if (cops->format == AT_COPS_LONG) {
offset += sprintf(buffer+offset, ",%s", offset += sprintf(buffer+offset, ",%s",
(char*)cops->plmn.id.alpha_long); (char*)cops->plmn.id.alpha_long);
} else if (cops->format == AT_COPS_SHORT) { } else if (cops->format == AT_COPS_SHORT) {
offset += sprintf(buffer+offset, ",%s", offset += sprintf(buffer+offset, ",%s",
(char*)cops->plmn.id.alpha_short); (char*)cops->plmn.id.alpha_short);
} else if (cops->format == AT_COPS_NUM) { } else if (cops->format == AT_COPS_NUM) {
offset += sprintf(buffer+offset, ",%s", offset += sprintf(buffer+offset, ",%s",
(char*)cops->plmn.id.num); (char*)cops->plmn.id.num);
} }
}
if (data->mask & AT_COPS_RESP_ACT_MASK) {
offset += sprintf(buffer+offset, ",%d", cops->AcT);
}
offset += sprintf(buffer+offset, "\r\n");
} else if (data->type == AT_COMMAND_TST) {
const at_cops_tst_t * cops = &(data->response.cops.tst);
if (at_response_format_v1) {
offset += sprintf(buffer, "\r\n");
}
offset += sprintf(buffer+offset, "+COPS: ");
/* Display the list of operators present in the network */
strncpy(buffer+offset, cops->data, cops->size);
offset += cops->size;
/* Display the list of supported network registration modes and
* supported representation formats of network operators */
//offset += sprintf(buffer+offset, ",,(%d-%d),(%d,%d,%d)",
// AT_COPS_AUTO, AT_COPS_MANAUTO,
// AT_COPS_LONG, AT_COPS_SHORT, AT_COPS_NUM);
offset += sprintf(buffer+offset, "\r\n");
} }
if (data->mask & AT_COPS_RESP_ACT_MASK) { LOG_FUNC_RETURN (offset);
offset += sprintf(buffer+offset, ",%d", cops->AcT);
}
offset += sprintf(buffer+offset, "\r\n");
} else if (data->type == AT_COMMAND_TST) {
const at_cops_tst_t * cops = &(data->response.cops.tst);
if (at_response_format_v1) {
offset += sprintf(buffer, "\r\n");
}
offset += sprintf(buffer+offset, "+COPS: ");
/* Display the list of operators present in the network */
strncpy(buffer+offset, cops->data, cops->size);
offset += cops->size;
/* Display the list of supported network registration modes and
* supported representation formats of network operators */
//offset += sprintf(buffer+offset, ",,(%d-%d),(%d,%d,%d)",
// AT_COPS_AUTO, AT_COPS_MANAUTO,
// AT_COPS_LONG, AT_COPS_SHORT, AT_COPS_NUM);
offset += sprintf(buffer+offset, "\r\n");
}
LOG_FUNC_RETURN (offset);
} }
/**************************************************************************** /****************************************************************************
...@@ -712,28 +712,28 @@ static int _at_response_encode_cops(char* buffer, const at_response_t* data) ...@@ -712,28 +712,28 @@ static int _at_response_encode_cops(char* buffer, const at_response_t* data)
***************************************************************************/ ***************************************************************************/
static int _at_response_encode_cgatt(char* buffer, const at_response_t* data) static int _at_response_encode_cgatt(char* buffer, const at_response_t* data)
{ {
LOG_FUNC_IN; LOG_FUNC_IN;
int offset = 0; int offset = 0;
if (data->type == AT_COMMAND_GET) { if (data->type == AT_COMMAND_GET) {
const at_cgatt_resp_t * cgatt = &(data->response.cgatt); const at_cgatt_resp_t * cgatt = &(data->response.cgatt);
if (at_response_format_v1) { if (at_response_format_v1) {
offset += sprintf(buffer, "\r\n"); offset += sprintf(buffer, "\r\n");
} }
offset += sprintf(buffer+offset, "+CGATT: %d\r\n", cgatt->state); offset += sprintf(buffer+offset, "+CGATT: %d\r\n", cgatt->state);
} else if (data->type == AT_COMMAND_TST) { } else if (data->type == AT_COMMAND_TST) {
if (at_response_format_v1) { if (at_response_format_v1) {
offset += sprintf(buffer, "\r\n"); offset += sprintf(buffer, "\r\n");
} }
offset += sprintf(buffer+offset, "+CGATT: (%d,%d)\r\n", offset += sprintf(buffer+offset, "+CGATT: (%d,%d)\r\n",
AT_CGATT_STATE_MIN, AT_CGATT_STATE_MAX); AT_CGATT_STATE_MIN, AT_CGATT_STATE_MAX);
} }
LOG_FUNC_RETURN (offset); LOG_FUNC_RETURN (offset);
} }
/**************************************************************************** /****************************************************************************
...@@ -753,43 +753,43 @@ static int _at_response_encode_cgatt(char* buffer, const at_response_t* data) ...@@ -753,43 +753,43 @@ static int _at_response_encode_cgatt(char* buffer, const at_response_t* data)
***************************************************************************/ ***************************************************************************/
static int _at_response_encode_creg(char* buffer, const at_response_t* data) static int _at_response_encode_creg(char* buffer, const at_response_t* data)
{ {
LOG_FUNC_IN; LOG_FUNC_IN;
int offset = 0; int offset = 0;
if (data->type == AT_COMMAND_GET) { if (data->type == AT_COMMAND_GET) {
const at_creg_resp_t * creg = &(data->response.creg); const at_creg_resp_t * creg = &(data->response.creg);
if (at_response_format_v1) { if (at_response_format_v1) {
offset += sprintf(buffer, "\r\n"); offset += sprintf(buffer, "\r\n");
} }
offset += sprintf(buffer+offset, "+CREG: %d,%d", offset += sprintf(buffer+offset, "+CREG: %d,%d",
creg->n, creg->stat); creg->n, creg->stat);
if (data->mask & AT_CREG_RESP_LAC_MASK) { if (data->mask & AT_CREG_RESP_LAC_MASK) {
offset += sprintf(buffer+offset, ",%s", creg->lac); offset += sprintf(buffer+offset, ",%s", creg->lac);
} }
if (data->mask & AT_CREG_RESP_CI_MASK) { if (data->mask & AT_CREG_RESP_CI_MASK) {
offset += sprintf(buffer+offset, ",%s", creg->ci); offset += sprintf(buffer+offset, ",%s", creg->ci);
} }
if (data->mask & AT_CREG_RESP_ACT_MASK) { if (data->mask & AT_CREG_RESP_ACT_MASK) {
offset += sprintf(buffer+offset, ",%d", creg->AcT); offset += sprintf(buffer+offset, ",%d", creg->AcT);
} }
offset += sprintf(buffer+offset, "\r\n"); offset += sprintf(buffer+offset, "\r\n");
} else if (data->type == AT_COMMAND_TST) { } else if (data->type == AT_COMMAND_TST) {
if (at_response_format_v1) { if (at_response_format_v1) {
offset += sprintf(buffer, "\r\n"); offset += sprintf(buffer, "\r\n");
} }
offset += sprintf(buffer+offset, "+CREG: (%d-%d)\r\n", offset += sprintf(buffer+offset, "+CREG: (%d-%d)\r\n",
AT_CREG_N_MIN, AT_CREG_N_MAX); AT_CREG_N_MIN, AT_CREG_N_MAX);
} }
LOG_FUNC_RETURN (offset); LOG_FUNC_RETURN (offset);
} }
/**************************************************************************** /****************************************************************************
...@@ -809,47 +809,47 @@ static int _at_response_encode_creg(char* buffer, const at_response_t* data) ...@@ -809,47 +809,47 @@ static int _at_response_encode_creg(char* buffer, const at_response_t* data)
***************************************************************************/ ***************************************************************************/
static int _at_response_encode_cgreg(char* buffer, const at_response_t* data) static int _at_response_encode_cgreg(char* buffer, const at_response_t* data)
{ {
LOG_FUNC_IN; LOG_FUNC_IN;
int offset = 0; int offset = 0;
if (data->type == AT_COMMAND_GET) { if (data->type == AT_COMMAND_GET) {
const at_cgreg_resp_t * cgreg = &(data->response.cgreg); const at_cgreg_resp_t * cgreg = &(data->response.cgreg);
if (at_response_format_v1) { if (at_response_format_v1) {
offset += sprintf(buffer, "\r\n"); offset += sprintf(buffer, "\r\n");
} }
offset += sprintf(buffer+offset, "+CGREG: %d,%d", offset += sprintf(buffer+offset, "+CGREG: %d,%d",
cgreg->n, cgreg->stat); cgreg->n, cgreg->stat);
if (data->mask & AT_CGREG_RESP_LAC_MASK) { if (data->mask & AT_CGREG_RESP_LAC_MASK) {
offset += sprintf(buffer+offset, ",%s", cgreg->lac); offset += sprintf(buffer+offset, ",%s", cgreg->lac);
} }
if (data->mask & AT_CGREG_RESP_CI_MASK) { if (data->mask & AT_CGREG_RESP_CI_MASK) {
offset += sprintf(buffer+offset, ",%s", cgreg->ci); offset += sprintf(buffer+offset, ",%s", cgreg->ci);
} }
if (data->mask & AT_CGREG_RESP_ACT_MASK) { if (data->mask & AT_CGREG_RESP_ACT_MASK) {
offset += sprintf(buffer+offset, ",%d", cgreg->AcT); offset += sprintf(buffer+offset, ",%d", cgreg->AcT);
} }
if (data->mask & AT_CGREG_RESP_RAC_MASK) { if (data->mask & AT_CGREG_RESP_RAC_MASK) {
offset += sprintf(buffer+offset, ",%s", cgreg->rac); offset += sprintf(buffer+offset, ",%s", cgreg->rac);
} }
offset += sprintf(buffer+offset, "\r\n"); offset += sprintf(buffer+offset, "\r\n");
} else if (data->type == AT_COMMAND_TST) { } else if (data->type == AT_COMMAND_TST) {
if (at_response_format_v1) { if (at_response_format_v1) {
offset += sprintf(buffer, "\r\n"); offset += sprintf(buffer, "\r\n");
} }
offset += sprintf(buffer+offset, "+CGREG: (%d-%d)\r\n", offset += sprintf(buffer+offset, "+CGREG: (%d-%d)\r\n",
AT_CGREG_N_MIN, AT_CGREG_N_MAX); AT_CGREG_N_MIN, AT_CGREG_N_MAX);
} }
LOG_FUNC_RETURN (offset); LOG_FUNC_RETURN (offset);
} }
/**************************************************************************** /****************************************************************************
...@@ -869,43 +869,43 @@ static int _at_response_encode_cgreg(char* buffer, const at_response_t* data) ...@@ -869,43 +869,43 @@ static int _at_response_encode_cgreg(char* buffer, const at_response_t* data)
***************************************************************************/ ***************************************************************************/
static int _at_response_encode_cereg(char* buffer, const at_response_t* data) static int _at_response_encode_cereg(char* buffer, const at_response_t* data)
{ {
LOG_FUNC_IN; LOG_FUNC_IN;
int offset = 0; int offset = 0;
if (data->type == AT_COMMAND_GET) { if (data->type == AT_COMMAND_GET) {
const at_cereg_resp_t * cereg = &(data->response.cereg); const at_cereg_resp_t * cereg = &(data->response.cereg);
if (at_response_format_v1) { if (at_response_format_v1) {
offset += sprintf(buffer, "\r\n"); offset += sprintf(buffer, "\r\n");
} }
offset += sprintf(buffer+offset, "+CEREG: %d,%d", offset += sprintf(buffer+offset, "+CEREG: %d,%d",
cereg->n, cereg->stat); cereg->n, cereg->stat);
if (data->mask & AT_CEREG_RESP_TAC_MASK) { if (data->mask & AT_CEREG_RESP_TAC_MASK) {
offset += sprintf(buffer+offset, ",%s", cereg->tac); offset += sprintf(buffer+offset, ",%s", cereg->tac);
} }
if (data->mask & AT_CEREG_RESP_CI_MASK) { if (data->mask & AT_CEREG_RESP_CI_MASK) {
offset += sprintf(buffer+offset, ",%s", cereg->ci); offset += sprintf(buffer+offset, ",%s", cereg->ci);
} }
if (data->mask & AT_CEREG_RESP_ACT_MASK) { if (data->mask & AT_CEREG_RESP_ACT_MASK) {
offset += sprintf(buffer+offset, ",%d", cereg->AcT); offset += sprintf(buffer+offset, ",%d", cereg->AcT);
} }
offset += sprintf(buffer+offset, "\r\n"); offset += sprintf(buffer+offset, "\r\n");
} else if (data->type == AT_COMMAND_TST) { } else if (data->type == AT_COMMAND_TST) {
if (at_response_format_v1) { if (at_response_format_v1) {
offset += sprintf(buffer, "\r\n"); offset += sprintf(buffer, "\r\n");
} }
offset += sprintf(buffer+offset, "+CEREG: (%d-%d)\r\n", offset += sprintf(buffer+offset, "+CEREG: (%d-%d)\r\n",
AT_CEREG_N_MIN, AT_CEREG_N_MAX); AT_CEREG_N_MIN, AT_CEREG_N_MAX);
} }
LOG_FUNC_RETURN (offset); LOG_FUNC_RETURN (offset);
} }
/**************************************************************************** /****************************************************************************
...@@ -925,65 +925,65 @@ static int _at_response_encode_cereg(char* buffer, const at_response_t* data) ...@@ -925,65 +925,65 @@ static int _at_response_encode_cereg(char* buffer, const at_response_t* data)
***************************************************************************/ ***************************************************************************/
static int _at_response_encode_cgdcont(char* buffer, const at_response_t* data) static int _at_response_encode_cgdcont(char* buffer, const at_response_t* data)
{ {
LOG_FUNC_IN; LOG_FUNC_IN;
int offset = 0; int offset = 0;
int i; int i;
if (data->type == AT_COMMAND_GET) { if (data->type == AT_COMMAND_GET) {
const at_cgdcont_get_t * cgdcont = &(data->response.cgdcont.get); const at_cgdcont_get_t * cgdcont = &(data->response.cgdcont.get);
if (at_response_format_v1) { if (at_response_format_v1) {
offset += sprintf(buffer, "\r\n"); offset += sprintf(buffer, "\r\n");
}
/* Display the list of defined PDN contexts */
for (i = 0; i < cgdcont->n_pdns; i++) {
offset += sprintf(buffer+offset, "+CGDCONT: %u", (unsigned int)cgdcont->cid[i]);
if (cgdcont->PDP_type[i] == NET_PDN_TYPE_IPV4) {
offset += sprintf(buffer+offset, ",IP");
} else if (cgdcont->PDP_type[i] == NET_PDN_TYPE_IPV6) {
offset += sprintf(buffer+offset, ",IPV6");
} else if (cgdcont->PDP_type[i] == NET_PDN_TYPE_IPV4V6) {
offset += sprintf(buffer+offset, ",IPV4V6");
}
offset += sprintf(buffer+offset, ",%s", cgdcont->APN[i]);
/* No data/header compression */
offset += sprintf(buffer+offset, ",%u,%u\r\n",
(unsigned int)(AT_CGDCONT_D_COMP_OFF), (unsigned int)(AT_CGDCONT_H_COMP_OFF));
}
} else if (data->type == AT_COMMAND_TST) {
const at_cgdcont_tst_t * cgdcont = &(data->response.cgdcont.tst);
if (at_response_format_v1) {
offset += sprintf(buffer, "\r\n");
}
/* IPv4 PDN type */
offset += sprintf(buffer+offset, "+CGDCONT: ");
offset += sprintf(buffer+offset, "(1-%d),IP,,,(%d-%d),(%d-%d)",
cgdcont->n_cid,
AT_CGDCONT_D_COMP_MIN, AT_CGDCONT_D_COMP_MAX,
AT_CGDCONT_H_COMP_MIN, AT_CGDCONT_H_COMP_MAX);
/* IPv6 PDN type */
offset += sprintf(buffer+offset, "\r\n+CGDCONT: ");
offset += sprintf(buffer+offset, "(1-%d),IPV6,,,(%d-%d),(%d-%d)",
cgdcont->n_cid,
AT_CGDCONT_D_COMP_MIN, AT_CGDCONT_D_COMP_MAX,
AT_CGDCONT_H_COMP_MIN, AT_CGDCONT_H_COMP_MAX);
/* IPv4v6 PDN type */
offset += sprintf(buffer+offset, "\r\n+CGDCONT: ");
offset += sprintf(buffer+offset, "(1-%d),IPV4V6,,,(%d-%d),(%d-%d)",
cgdcont->n_cid,
AT_CGDCONT_D_COMP_MIN, AT_CGDCONT_D_COMP_MAX,
AT_CGDCONT_H_COMP_MIN, AT_CGDCONT_H_COMP_MAX);
offset += sprintf(buffer+offset, "\r\n");
} }
/* Display the list of defined PDN contexts */ LOG_FUNC_RETURN (offset);
for (i = 0; i < cgdcont->n_pdns; i++) {
offset += sprintf(buffer+offset, "+CGDCONT: %u", cgdcont->cid[i]);
if (cgdcont->PDP_type[i] == NET_PDN_TYPE_IPV4) {
offset += sprintf(buffer+offset, ",IP");
} else if (cgdcont->PDP_type[i] == NET_PDN_TYPE_IPV6) {
offset += sprintf(buffer+offset, ",IPV6");
} else if (cgdcont->PDP_type[i] == NET_PDN_TYPE_IPV4V6) {
offset += sprintf(buffer+offset, ",IPV4V6");
}
offset += sprintf(buffer+offset, ",%s", cgdcont->APN[i]);
/* No data/header compression */
offset += sprintf(buffer+offset, ",%u,%u\r\n",
AT_CGDCONT_D_COMP_OFF, AT_CGDCONT_H_COMP_OFF);
}
} else if (data->type == AT_COMMAND_TST) {
const at_cgdcont_tst_t * cgdcont = &(data->response.cgdcont.tst);
if (at_response_format_v1) {
offset += sprintf(buffer, "\r\n");
}
/* IPv4 PDN type */
offset += sprintf(buffer+offset, "+CGDCONT: ");
offset += sprintf(buffer+offset, "(1-%u),IP,,,(%u-%u),(%u-%u)",
cgdcont->n_cid,
AT_CGDCONT_D_COMP_MIN, AT_CGDCONT_D_COMP_MAX,
AT_CGDCONT_H_COMP_MIN, AT_CGDCONT_H_COMP_MAX);
/* IPv6 PDN type */
offset += sprintf(buffer+offset, "\r\n+CGDCONT: ");
offset += sprintf(buffer+offset, "(1-%u),IPV6,,,(%u-%u),(%u-%u)",
cgdcont->n_cid,
AT_CGDCONT_D_COMP_MIN, AT_CGDCONT_D_COMP_MAX,
AT_CGDCONT_H_COMP_MIN, AT_CGDCONT_H_COMP_MAX);
/* IPv4v6 PDN type */
offset += sprintf(buffer+offset, "\r\n+CGDCONT: ");
offset += sprintf(buffer+offset, "(1-%u),IPV4V6,,,(%u-%u),(%u-%u)",
cgdcont->n_cid,
AT_CGDCONT_D_COMP_MIN, AT_CGDCONT_D_COMP_MAX,
AT_CGDCONT_H_COMP_MIN, AT_CGDCONT_H_COMP_MAX);
offset += sprintf(buffer+offset, "\r\n");
}
LOG_FUNC_RETURN (offset);
} }
/**************************************************************************** /****************************************************************************
...@@ -1003,33 +1003,33 @@ static int _at_response_encode_cgdcont(char* buffer, const at_response_t* data) ...@@ -1003,33 +1003,33 @@ static int _at_response_encode_cgdcont(char* buffer, const at_response_t* data)
***************************************************************************/ ***************************************************************************/
static int _at_response_encode_cgact(char* buffer, const at_response_t* data) static int _at_response_encode_cgact(char* buffer, const at_response_t* data)
{ {
LOG_FUNC_IN; LOG_FUNC_IN;
int offset = 0; int offset = 0;
int i; int i;
if (data->type == AT_COMMAND_GET) { if (data->type == AT_COMMAND_GET) {
const at_cgact_resp_t * cgact = &(data->response.cgact); const at_cgact_resp_t * cgact = &(data->response.cgact);
if (at_response_format_v1) { if (at_response_format_v1) {
offset += sprintf(buffer, "\r\n"); offset += sprintf(buffer, "\r\n");
}
/* Display the list of defined PDN status */
for (i = 0; i < cgact->n_pdns; i++) {
offset += sprintf(buffer+offset, "+CGACT: %u,%u\r\n",
(unsigned int)cgact->cid[i], (unsigned int)cgact->state[i]);
}
} else if (data->type == AT_COMMAND_TST) {
if (at_response_format_v1) {
offset += sprintf(buffer, "\r\n");
}
offset += sprintf(buffer+offset, "+CGACT: (%d,%d)\r\n",
AT_CGACT_STATE_MIN, AT_CGACT_STATE_MAX);
} }
/* Display the list of defined PDN status */ LOG_FUNC_RETURN (offset);
for (i = 0; i < cgact->n_pdns; i++) {
offset += sprintf(buffer+offset, "+CGACT: %u,%u\r\n",
cgact->cid[i], cgact->state[i]);
}
} else if (data->type == AT_COMMAND_TST) {
if (at_response_format_v1) {
offset += sprintf(buffer, "\r\n");
}
offset += sprintf(buffer+offset, "+CGACT: (%d,%d)\r\n",
AT_CGACT_STATE_MIN, AT_CGACT_STATE_MAX);
}
LOG_FUNC_RETURN (offset);
} }
/**************************************************************************** /****************************************************************************
...@@ -1049,69 +1049,72 @@ static int _at_response_encode_cgact(char* buffer, const at_response_t* data) ...@@ -1049,69 +1049,72 @@ static int _at_response_encode_cgact(char* buffer, const at_response_t* data)
***************************************************************************/ ***************************************************************************/
static int _at_response_encode_cgpaddr(char* buffer, const at_response_t* data) static int _at_response_encode_cgpaddr(char* buffer, const at_response_t* data)
{ {
LOG_FUNC_IN; LOG_FUNC_IN;
int offset = 0; int offset = 0;
const at_cgpaddr_resp_t * cgpaddr = &(data->response.cgpaddr); const at_cgpaddr_resp_t * cgpaddr = &(data->response.cgpaddr);
int i; int i;
if (data->type == AT_COMMAND_SET) { if (data->type == AT_COMMAND_SET) {
if (at_response_format_v1) { if (at_response_format_v1) {
offset += sprintf(buffer, "\r\n"); offset += sprintf(buffer, "\r\n");
} }
/* Display the list of IP addresses assigned to each defined PDN /* Display the list of IP addresses assigned to each defined PDN
* connections */ * connections */
for (i = 0; i < cgpaddr->n_pdns; i++) { for (i = 0; i < cgpaddr->n_pdns; i++) {
offset += sprintf(buffer+offset, "+CGPADDR: %u", cgpaddr->cid[i]); offset += sprintf(buffer+offset, "+CGPADDR: %u", (unsigned int)cgpaddr->cid[i]);
if (cgpaddr->PDP_addr_1[i] != NULL) { if (cgpaddr->PDP_addr_1[i] != NULL) {
/* IPv4 address */ /* IPv4 address */
offset += sprintf(buffer+offset, ",%hhu.%hhu.%hhu.%hhu", offset += sprintf(buffer+offset, ",%hhu.%hhu.%hhu.%hhu",
cgpaddr->PDP_addr_1[i][0], (unsigned int)cgpaddr->PDP_addr_1[i][0],
cgpaddr->PDP_addr_1[i][1], (unsigned int)cgpaddr->PDP_addr_1[i][1],
cgpaddr->PDP_addr_1[i][2], (unsigned int)cgpaddr->PDP_addr_1[i][2],
cgpaddr->PDP_addr_1[i][3]); (unsigned int)cgpaddr->PDP_addr_1[i][3]);
} }
if (cgpaddr->PDP_addr_2[i] != NULL) { if (cgpaddr->PDP_addr_2[i] != NULL) {
/* IPv6 Link-local address prefixe */ /* IPv6 Link-local address prefixe */
offset += sprintf(buffer+offset, offset += sprintf(buffer+offset,
",%hhu.%hhu.%hhu.%hhu.%hhu.%hhu.%hhu.%hhu", ",%hhu.%hhu.%hhu.%hhu.%hhu.%hhu.%hhu.%hhu",
0xfe, 0x80, 0, 0, 0, 0, 0, 0); (unsigned int)0xfe, (unsigned int)0x80,
/* IPv6 Link-local address */ (unsigned int)0, (unsigned int)0,
offset += sprintf(buffer+offset, (unsigned int)0, (unsigned int)0,
".%hhu.%hhu.%hhu.%hhu.%hhu.%hhu.%hhu.%hhu", (unsigned int)0, (unsigned int)0);
cgpaddr->PDP_addr_2[i][0], /* IPv6 Link-local address */
cgpaddr->PDP_addr_2[i][1], offset += sprintf(buffer+offset,
cgpaddr->PDP_addr_2[i][2], ".%hhu.%hhu.%hhu.%hhu.%hhu.%hhu.%hhu.%hhu",
cgpaddr->PDP_addr_2[i][3], (unsigned int)cgpaddr->PDP_addr_2[i][0],
cgpaddr->PDP_addr_2[i][4], (unsigned int)cgpaddr->PDP_addr_2[i][1],
cgpaddr->PDP_addr_2[i][5], (unsigned int)cgpaddr->PDP_addr_2[i][2],
cgpaddr->PDP_addr_2[i][6], (unsigned int)cgpaddr->PDP_addr_2[i][3],
cgpaddr->PDP_addr_2[i][7]); (unsigned int)cgpaddr->PDP_addr_2[i][4],
} (unsigned int)cgpaddr->PDP_addr_2[i][5],
(unsigned int)cgpaddr->PDP_addr_2[i][6],
offset += sprintf(buffer+offset, "\r\n"); (unsigned int)cgpaddr->PDP_addr_2[i][7]);
}
offset += sprintf(buffer+offset, "\r\n");
}
} else if (data->type == AT_COMMAND_TST) {
/* Display the list of defined PDN contexts */
if (cgpaddr->n_pdns > 0) {
if (at_response_format_v1) {
offset += sprintf(buffer, "\r\n");
}
offset += sprintf(buffer+offset, "+CGPADDR: %u", (unsigned int)cgpaddr->cid[0]);
for (i = 1; i < cgpaddr->n_pdns; i++) {
offset += sprintf(buffer+offset, ",%u", (unsigned int)cgpaddr->cid[i]);
}
offset += sprintf(buffer+offset, "\r\n");
}
} }
} else if (data->type == AT_COMMAND_TST) {
/* Display the list of defined PDN contexts */
if (cgpaddr->n_pdns > 0) {
if (at_response_format_v1) {
offset += sprintf(buffer, "\r\n");
}
offset += sprintf(buffer+offset, "+CGPADDR: %u", cgpaddr->cid[0]); LOG_FUNC_RETURN (offset);
for (i = 1; i < cgpaddr->n_pdns; i++) {
offset += sprintf(buffer+offset, ",%u", cgpaddr->cid[i]);
}
offset += sprintf(buffer+offset, "\r\n");
}
}
LOG_FUNC_RETURN (offset);
} }
/**************************************************************************** /****************************************************************************
...@@ -1131,28 +1134,28 @@ static int _at_response_encode_cgpaddr(char* buffer, const at_response_t* data) ...@@ -1131,28 +1134,28 @@ static int _at_response_encode_cgpaddr(char* buffer, const at_response_t* data)
***************************************************************************/ ***************************************************************************/
static int _at_response_encode_cmee(char* buffer, const at_response_t* data) static int _at_response_encode_cmee(char* buffer, const at_response_t* data)
{ {
LOG_FUNC_IN; LOG_FUNC_IN;
int offset = 0; int offset = 0;
if (data->type == AT_COMMAND_GET) { if (data->type == AT_COMMAND_GET) {
const at_cmee_resp_t * cmee = &(data->response.cmee); const at_cmee_resp_t * cmee = &(data->response.cmee);
if (at_response_format_v1) { if (at_response_format_v1) {
offset += sprintf(buffer, "\r\n"); offset += sprintf(buffer, "\r\n");
} }
offset += sprintf(buffer+offset, "+CMEE: %d\r\n", cmee->n); offset += sprintf(buffer+offset, "+CMEE: %d\r\n", cmee->n);
} else if (data->type == AT_COMMAND_TST) { } else if (data->type == AT_COMMAND_TST) {
if (at_response_format_v1) { if (at_response_format_v1) {
offset += sprintf(buffer, "\r\n"); offset += sprintf(buffer, "\r\n");
} }
offset += sprintf(buffer+offset, "+CMEE: (%d,%d)\r\n", offset += sprintf(buffer+offset, "+CMEE: (%d,%d)\r\n",
AT_CMEE_N_MIN, AT_CMEE_N_MAX); AT_CMEE_N_MIN, AT_CMEE_N_MAX);
} }
LOG_FUNC_RETURN (offset); LOG_FUNC_RETURN (offset);
} }
/**************************************************************************** /****************************************************************************
...@@ -1172,16 +1175,16 @@ static int _at_response_encode_cmee(char* buffer, const at_response_t* data) ...@@ -1172,16 +1175,16 @@ static int _at_response_encode_cmee(char* buffer, const at_response_t* data)
***************************************************************************/ ***************************************************************************/
static int _at_response_encode_cgev(char* buffer, const at_response_t* data) static int _at_response_encode_cgev(char* buffer, const at_response_t* data)
{ {
LOG_FUNC_IN; LOG_FUNC_IN;
int offset = 0; int offset = 0;
if (data->type == AT_COMMAND_GET) { if (data->type == AT_COMMAND_GET) {
const at_cgev_resp_t * cgev = &(data->response.cgev); const at_cgev_resp_t * cgev = &(data->response.cgev);
offset += sprintf(buffer+offset, "+CGEV: %s %u\r\n", offset += sprintf(buffer+offset, "+CGEV: %s %u\r\n",
_at_response_event_str[cgev->code], cgev->cid); _at_response_event_str[cgev->code], (unsigned int)cgev->cid);
} }
LOG_FUNC_RETURN (offset); LOG_FUNC_RETURN (offset);
} }
...@@ -138,119 +138,119 @@ int esm_proc_pdn_connectivity(nas_user_t *user, int cid, int is_to_define, ...@@ -138,119 +138,119 @@ int esm_proc_pdn_connectivity(nas_user_t *user, int cid, int is_to_define,
const OctetString *apn, int is_emergency, const OctetString *apn, int is_emergency,
unsigned int *pti) unsigned int *pti)
{ {
LOG_FUNC_IN; LOG_FUNC_IN;
int rc = RETURNerror; int rc = RETURNerror;
int pid = cid - 1; int pid = cid - 1;
esm_data_t *esm_data = user-> esm_data; esm_data_t *esm_data = user-> esm_data;
esm_pt_data_t *esm_pt_data = user-> esm_pt_data; esm_pt_data_t *esm_pt_data = user-> esm_pt_data;
if (!is_to_define) { if (!is_to_define) {
LOG_TRACE(INFO, "ESM-PROC - Undefine PDN connection (cid=%d)", cid); LOG_TRACE(INFO, "ESM-PROC - Undefine PDN connection (cid=%d)", cid);
/* Delete the PDN connection entry */ /* Delete the PDN connection entry */
int pti = _pdn_connectivity_delete(esm_data, pid); int pti = _pdn_connectivity_delete(esm_data, pid);
if (pti != ESM_PT_UNASSIGNED) { if (pti != ESM_PT_UNASSIGNED) {
/* Release the procedure transaction data */ /* Release the procedure transaction data */
rc = esm_pt_release(esm_pt_data, pti); rc = esm_pt_release(esm_pt_data, pti);
} }
LOG_FUNC_RETURN(rc); LOG_FUNC_RETURN(rc);
} else if (pti != NULL) { } else if (pti != NULL) {
LOG_TRACE(INFO, "ESM-PROC - Assign new procedure transaction identity " LOG_TRACE(INFO, "ESM-PROC - Assign new procedure transaction identity "
"(cid=%d)", cid); "(cid=%d)", cid);
/* Assign new procedure transaction identity */ /* Assign new procedure transaction identity */
*pti = esm_pt_assign(esm_pt_data); *pti = esm_pt_assign(esm_pt_data);
if (*pti == ESM_PT_UNASSIGNED) { if (*pti == ESM_PT_UNASSIGNED) {
LOG_TRACE(WARNING, "ESM-PROC - Failed to assign new procedure " LOG_TRACE(WARNING, "ESM-PROC - Failed to assign new procedure "
"transaction identity"); "transaction identity");
LOG_FUNC_RETURN (RETURNerror); LOG_FUNC_RETURN (RETURNerror);
} }
/* Update the PDN connection data */ /* Update the PDN connection data */
rc = _pdn_connectivity_set_pti(esm_data, pid, *pti); rc = _pdn_connectivity_set_pti(esm_data, pid, *pti);
if (rc != RETURNok) { if (rc != RETURNok) {
LOG_TRACE(WARNING, "ESM-PROC - Failed to update PDN connection"); LOG_TRACE(WARNING, "ESM-PROC - Failed to update PDN connection");
} }
LOG_FUNC_RETURN (rc); LOG_FUNC_RETURN (rc);
}
LOG_TRACE(INFO,"ESM-PROC - Define new %s PDN connection to APN %s (cid=%d)",
(pdn_type == ESM_PDN_TYPE_IPV4)? "IPv4" :
(pdn_type == ESM_PDN_TYPE_IPV6)? "IPv6" : "IPv4v6",
apn->value, cid);
if (is_emergency && esm_data->emergency) {
/* The UE shall not request additional PDN connection for
* emergency bearer services */
LOG_TRACE(WARNING, "ESM-PROC - PDN connection for emergency bearer "
"services is already active");
LOG_FUNC_RETURN (RETURNerror);
} else if (pid < ESM_DATA_PDN_MAX) {
if ((pid == esm_data->pdn[pid].pid) && (esm_data->pdn[pid].is_active)) {
/* PDN connection with the specified identifier is active */
LOG_TRACE(WARNING, "ESM-PROC - PDN connection is active");
LOG_FUNC_RETURN (RETURNerror);
} }
} else {
LOG_TRACE(WARNING, "ESM-PROC - PDN connection identifier is not valid"); LOG_TRACE(INFO,"ESM-PROC - Define new %s PDN connection to APN %s (cid=%d)",
LOG_FUNC_RETURN (RETURNerror); (pdn_type == ESM_PDN_TYPE_IPV4)? "IPv4" :
} (pdn_type == ESM_PDN_TYPE_IPV6)? "IPv6" : "IPv4v6",
(apn!=NULL)?apn->value:0, cid);
if (apn && apn->length > 0) {
/* The UE requested subsequent connectivity to additionnal PDNs */ if (is_emergency && esm_data->emergency) {
int pid = _pdn_connectivity_find_apn(esm_data, apn); /* The UE shall not request additional PDN connection for
* emergency bearer services */
if ( (pid >= 0) && esm_data->pdn[pid].is_active ) { LOG_TRACE(WARNING, "ESM-PROC - PDN connection for emergency bearer "
/* An active PDN connection to this APN already exists */ "services is already active");
if ( (esm_data->pdn[pid].data->type != ESM_PDN_TYPE_IPV4V6) && LOG_FUNC_RETURN (RETURNerror);
(esm_data->pdn[pid].data->type != pdn_type) ) { } else if (pid < ESM_DATA_PDN_MAX) {
/* The UE is requesting PDN connection for other IP version if ((pid == esm_data->pdn[pid].pid) && (esm_data->pdn[pid].is_active)) {
* than the one already activated */ /* PDN connection with the specified identifier is active */
if (!esm_data->pdn[pid].data->addr_realloc) { LOG_TRACE(WARNING, "ESM-PROC - PDN connection is active");
/* The network does not allow PDN connectivity using LOG_FUNC_RETURN (RETURNerror);
* IPv4 and IPv6 address versions to the same APN */
if (pdn_type != ESM_PDN_TYPE_IPV4V6) {
LOG_TRACE(WARNING, "ESM-PROC - %s PDN connectivity to "
"%s is not allowed by the network",
(pdn_type != ESM_PDN_TYPE_IPV4)? "IPv6" :
"IPv4", apn->value);
} else {
LOG_TRACE(WARNING, "ESM-PROC - %s PDN connection to %s "
"already exists",
(esm_data->pdn[pid].data->type !=
ESM_PDN_TYPE_IPV4)? "IPv6" : "IPv4",
apn->value);
}
LOG_FUNC_RETURN (RETURNerror);
} }
} else { } else {
/* The UE is requesting PDN connection to this APN using the LOG_TRACE(WARNING, "ESM-PROC - PDN connection identifier is not valid");
* same IP version than the one already activated */
LOG_TRACE(WARNING, "ESM-PROC - %s PDN connection to %s "
"already exists",
(esm_data->pdn[pid].data->type != ESM_PDN_TYPE_IPV4)?
(esm_data->pdn[pid].data->type != ESM_PDN_TYPE_IPV6)?
"IPv4v6" : "IPv6" : "IPv4", apn->value);
LOG_FUNC_RETURN (RETURNerror); LOG_FUNC_RETURN (RETURNerror);
}
} }
}
if (apn && apn->length > 0) {
/* /* The UE requested subsequent connectivity to additionnal PDNs */
* New PDN context has to be defined to allow connectivity to an APN: int pid = _pdn_connectivity_find_apn(esm_data, apn);
* The UE may attempt to attach to the network using the default APN,
* or request PDN connectivity to emergency bearer services. The UE if ( (pid >= 0) && esm_data->pdn[pid].is_active ) {
* may also subsequently request connectivity to additional PDNs if /* An active PDN connection to this APN already exists */
* not already established, or may have been allowed to request PDN if ( (esm_data->pdn[pid].data->type != ESM_PDN_TYPE_IPV4V6) &&
* connectivity for other IP version than the one already activated (esm_data->pdn[pid].data->type != pdn_type) ) {
*/ /* The UE is requesting PDN connection for other IP version
rc = _pdn_connectivity_create(esm_data, pid, apn, pdn_type, is_emergency); * than the one already activated */
LOG_FUNC_RETURN(rc); if (!esm_data->pdn[pid].data->addr_realloc) {
/* The network does not allow PDN connectivity using
* IPv4 and IPv6 address versions to the same APN */
if (pdn_type != ESM_PDN_TYPE_IPV4V6) {
LOG_TRACE(WARNING, "ESM-PROC - %s PDN connectivity to "
"%s is not allowed by the network",
(pdn_type != ESM_PDN_TYPE_IPV4)? "IPv6" :
"IPv4", apn->value);
} else {
LOG_TRACE(WARNING, "ESM-PROC - %s PDN connection to %s "
"already exists",
(esm_data->pdn[pid].data->type !=
ESM_PDN_TYPE_IPV4)? "IPv6" : "IPv4",
apn->value);
}
LOG_FUNC_RETURN (RETURNerror);
}
} else {
/* The UE is requesting PDN connection to this APN using the
* same IP version than the one already activated */
LOG_TRACE(WARNING, "ESM-PROC - %s PDN connection to %s "
"already exists",
(esm_data->pdn[pid].data->type != ESM_PDN_TYPE_IPV4)?
(esm_data->pdn[pid].data->type != ESM_PDN_TYPE_IPV6)?
"IPv4v6" : "IPv6" : "IPv4", apn->value);
LOG_FUNC_RETURN (RETURNerror);
}
}
}
/*
* New PDN context has to be defined to allow connectivity to an APN:
* The UE may attempt to attach to the network using the default APN,
* or request PDN connectivity to emergency bearer services. The UE
* may also subsequently request connectivity to additional PDNs if
* not already established, or may have been allowed to request PDN
* connectivity for other IP version than the one already activated
*/
rc = _pdn_connectivity_create(esm_data, pid, apn, pdn_type, is_emergency);
LOG_FUNC_RETURN(rc);
} }
/**************************************************************************** /****************************************************************************
...@@ -283,42 +283,42 @@ int esm_proc_pdn_connectivity(nas_user_t *user, int cid, int is_to_define, ...@@ -283,42 +283,42 @@ int esm_proc_pdn_connectivity(nas_user_t *user, int cid, int is_to_define,
int esm_proc_pdn_connectivity_request(nas_user_t *user, int is_standalone, int pti, int esm_proc_pdn_connectivity_request(nas_user_t *user, int is_standalone, int pti,
OctetString *msg, int sent_by_ue) OctetString *msg, int sent_by_ue)
{ {
LOG_FUNC_IN; LOG_FUNC_IN;
esm_pt_data_t *esm_pt_data = user->esm_pt_data; esm_pt_data_t *esm_pt_data = user->esm_pt_data;
int rc = RETURNok; int rc = RETURNok;
LOG_TRACE(INFO, "ESM-PROC - Initiate PDN connectivity (pti=%d)", pti); LOG_TRACE(INFO, "ESM-PROC - Initiate PDN connectivity (pti=%d)", pti);
if (is_standalone) { if (is_standalone) {
emm_sap_t emm_sap; emm_sap_t emm_sap;
emm_esm_data_t *emm_esm = &emm_sap.u.emm_esm.u.data; emm_esm_data_t *emm_esm = &emm_sap.u.emm_esm.u.data;
/* /*
* Notity EMM that ESM PDU has to be forwarded to lower layers * Notity EMM that ESM PDU has to be forwarded to lower layers
*/ */
emm_sap.primitive = EMMESM_UNITDATA_REQ; emm_sap.primitive = EMMESM_UNITDATA_REQ;
emm_sap.u.emm_esm.ueid = user->ueid; emm_sap.u.emm_esm.ueid = user->ueid;
emm_esm->msg.length = msg->length; emm_esm->msg.length = msg->length;
emm_esm->msg.value = msg->value; emm_esm->msg.value = msg->value;
rc = emm_sap_send(user, &emm_sap); rc = emm_sap_send(user, &emm_sap);
if (rc != RETURNerror) { if (rc != RETURNerror) {
/* Start T3482 retransmission timer */ /* Start T3482 retransmission timer */
rc = esm_pt_start_timer(user, pti, msg, T3482_DEFAULT_VALUE, rc = esm_pt_start_timer(user, pti, msg, T3482_DEFAULT_VALUE,
_pdn_connectivity_t3482_handler); _pdn_connectivity_t3482_handler);
}
} }
}
if (rc != RETURNerror) { if (rc != RETURNerror) {
/* Set the procedure transaction state to PENDING */ /* Set the procedure transaction state to PENDING */
rc = esm_pt_set_status(esm_pt_data, pti, ESM_PT_PENDING); rc = esm_pt_set_status(esm_pt_data, pti, ESM_PT_PENDING);
if (rc != RETURNok) { if (rc != RETURNok) {
/* The procedure transaction was already in PENDING state */ /* The procedure transaction was already in PENDING state */
LOG_TRACE(WARNING, "ESM-PROC - PTI %d was already PENDING", pti); LOG_TRACE(WARNING, "ESM-PROC - PTI %d was already PENDING", pti);
}
} }
}
LOG_FUNC_RETURN(rc); LOG_FUNC_RETURN(rc);
} }
/**************************************************************************** /****************************************************************************
...@@ -351,73 +351,73 @@ int esm_proc_pdn_connectivity_accept(nas_user_t *user, int pti, esm_proc_pdn_typ ...@@ -351,73 +351,73 @@ int esm_proc_pdn_connectivity_accept(nas_user_t *user, int pti, esm_proc_pdn_typ
const OctetString *pdn_addr, const OctetString *pdn_addr,
const OctetString *apn, int *esm_cause) const OctetString *apn, int *esm_cause)
{ {
LOG_FUNC_IN; LOG_FUNC_IN;
esm_data_t *esm_data = user->esm_data; esm_data_t *esm_data = user->esm_data;
esm_pt_data_t *esm_pt_data = user->esm_pt_data; esm_pt_data_t *esm_pt_data = user->esm_pt_data;
int rc; int rc;
int pid = RETURNerror; int pid = RETURNerror;
char apn_first_char[4]; char apn_first_char[4];
LOG_VAR(char, str[128]);
if (isprint(apn->value[0])) {
apn_first_char[0] = '\0';
} else {
sprintf (apn_first_char, "%02X", apn->value[0]);
}
LOG_TRACE(INFO, "ESM-PROC - PDN connectivity accepted by the network "
"(pti=%d) APN = %s\"%s\", IP address = %s", pti, apn_first_char, isprint(apn->value[0]) ? &apn->value[0] : &apn->value[1],
(pdn_type == ESM_PDN_TYPE_IPV4)? esm_data_get_ipv4_addr(pdn_addr, str) :
(pdn_type == ESM_PDN_TYPE_IPV6)? esm_data_get_ipv6_addr(pdn_addr, str) :
esm_data_get_ipv4v6_addr(pdn_addr, str));
/* Stop T3482 timer if running */
esm_pt_stop_timer(esm_pt_data, pti);
/* Set the procedure transaction state to INACTIVE */
rc = esm_pt_set_status(esm_pt_data, pti, ESM_PT_INACTIVE);
if (rc != RETURNok) {
/* The procedure transaction was already in INACTIVE state
* as the request may have already been accepted; consider
* this request message with same PTI as a network re-
* transmission */
LOG_TRACE(WARNING, "ESM-PROC - PTI %d network retransmission", pti);
*esm_cause = ESM_CAUSE_PTI_ALREADY_IN_USE;
} else {
/* XXX - 3GPP TS 24.301, section 6.5.1.3 and 7.3.1
* The UE should ensure that the procedure transaction identity
* (PTI) assigned to this procedure is not released immediately.
* While the PTI value is not released, the UE regards any received
* ACTIVATE DEFAULT EPS BEARER CONTEXT REQUEST message with the same
* PTI value as a network retransmission.
* The way to achieve this is implementation dependent.
*/
/* Check whether a PDN connection exists to this APN */ LOG_VAR(char, str[128]);
pid = _pdn_connectivity_find_pdn(esm_data, apn, pdn_type);
if (pid < 0) { if (isprint(apn->value[0])) {
/* No any PDN connection has been defined to establish connectivity apn_first_char[0] = '\0';
* to this APN */ } else {
LOG_TRACE(WARNING, "ESM-PROC - PDN connection entry for " sprintf (apn_first_char, "%02X", apn->value[0]);
"APN \"%s\" (type=%d) not found", apn->value, pdn_type);
*esm_cause = ESM_CAUSE_UNKNOWN_ACCESS_POINT_NAME;
LOG_FUNC_RETURN(RETURNerror);
} }
/* Update the PDN connection */ LOG_TRACE(INFO, "ESM-PROC - PDN connectivity accepted by the network "
rc = _pdn_connectivity_update(esm_data, pid, apn, pdn_type, pdn_addr, *esm_cause); "(pti=%d) APN = %s\"%s\", IP address = %s", pti, apn_first_char, isprint(apn->value[0]) ? &apn->value[0] : &apn->value[1],
(pdn_type == ESM_PDN_TYPE_IPV4)? esm_data_get_ipv4_addr(pdn_addr, str) :
(pdn_type == ESM_PDN_TYPE_IPV6)? esm_data_get_ipv6_addr(pdn_addr, str) :
esm_data_get_ipv4v6_addr(pdn_addr, str));
/* Stop T3482 timer if running */
esm_pt_stop_timer(esm_pt_data, pti);
/* Set the procedure transaction state to INACTIVE */
rc = esm_pt_set_status(esm_pt_data, pti, ESM_PT_INACTIVE);
if (rc != RETURNok) { if (rc != RETURNok) {
LOG_TRACE(WARNING, "ESM-PROC - Failed to update PDN connection " /* The procedure transaction was already in INACTIVE state
"(pid=%d)", pid); * as the request may have already been accepted; consider
*esm_cause = ESM_CAUSE_REQUEST_REJECTED_UNSPECIFIED; * this request message with same PTI as a network re-
LOG_FUNC_RETURN(RETURNerror); * transmission */
LOG_TRACE(WARNING, "ESM-PROC - PTI %d network retransmission", pti);
*esm_cause = ESM_CAUSE_PTI_ALREADY_IN_USE;
} else {
/* XXX - 3GPP TS 24.301, section 6.5.1.3 and 7.3.1
* The UE should ensure that the procedure transaction identity
* (PTI) assigned to this procedure is not released immediately.
* While the PTI value is not released, the UE regards any received
* ACTIVATE DEFAULT EPS BEARER CONTEXT REQUEST message with the same
* PTI value as a network retransmission.
* The way to achieve this is implementation dependent.
*/
/* Check whether a PDN connection exists to this APN */
pid = _pdn_connectivity_find_pdn(esm_data, apn, pdn_type);
if (pid < 0) {
/* No any PDN connection has been defined to establish connectivity
* to this APN */
LOG_TRACE(WARNING, "ESM-PROC - PDN connection entry for "
"APN \"%s\" (type=%d) not found", apn->value, pdn_type);
*esm_cause = ESM_CAUSE_UNKNOWN_ACCESS_POINT_NAME;
LOG_FUNC_RETURN(RETURNerror);
}
/* Update the PDN connection */
rc = _pdn_connectivity_update(esm_data, pid, apn, pdn_type, pdn_addr, *esm_cause);
if (rc != RETURNok) {
LOG_TRACE(WARNING, "ESM-PROC - Failed to update PDN connection "
"(pid=%d)", pid);
*esm_cause = ESM_CAUSE_REQUEST_REJECTED_UNSPECIFIED;
LOG_FUNC_RETURN(RETURNerror);
}
} }
}
LOG_FUNC_RETURN (pid); LOG_FUNC_RETURN (pid);
} }
/**************************************************************************** /****************************************************************************
...@@ -444,33 +444,33 @@ int esm_proc_pdn_connectivity_accept(nas_user_t *user, int pti, esm_proc_pdn_typ ...@@ -444,33 +444,33 @@ int esm_proc_pdn_connectivity_accept(nas_user_t *user, int pti, esm_proc_pdn_typ
***************************************************************************/ ***************************************************************************/
int esm_proc_pdn_connectivity_reject(nas_user_t *user, int pti, int *esm_cause) int esm_proc_pdn_connectivity_reject(nas_user_t *user, int pti, int *esm_cause)
{ {
LOG_FUNC_IN; LOG_FUNC_IN;
esm_pt_data_t *esm_pt_data = user->esm_pt_data; esm_pt_data_t *esm_pt_data = user->esm_pt_data;
int rc; int rc;
LOG_TRACE(WARNING, "ESM-PROC - PDN connectivity rejected by " LOG_TRACE(WARNING, "ESM-PROC - PDN connectivity rejected by "
"the network (pti=%d), ESM cause = %d", pti, *esm_cause); "the network (pti=%d), ESM cause = %d", pti, *esm_cause);
/* Stop T3482 timer if running */ /* Stop T3482 timer if running */
(void) esm_pt_stop_timer(esm_pt_data, pti); (void) esm_pt_stop_timer(esm_pt_data, pti);
/* Set the procedure transaction state to INACTIVE */ /* Set the procedure transaction state to INACTIVE */
rc = esm_pt_set_status(esm_pt_data, pti, ESM_PT_INACTIVE); rc = esm_pt_set_status(esm_pt_data, pti, ESM_PT_INACTIVE);
if (rc != RETURNok) {
/* The procedure transaction was already in INACTIVE state */
LOG_TRACE(WARNING, "ESM-PROC - PTI %d was already INACTIVE", pti);
*esm_cause = ESM_CAUSE_MESSAGE_TYPE_NOT_COMPATIBLE;
} else {
/* Release the procedure transaction identity */
rc = esm_pt_release(user->esm_pt_data, pti);
if (rc != RETURNok) { if (rc != RETURNok) {
LOG_TRACE(WARNING, "ESM-PROC - Failed to release PTI %d", pti); /* The procedure transaction was already in INACTIVE state */
*esm_cause = ESM_CAUSE_REQUEST_REJECTED_UNSPECIFIED; LOG_TRACE(WARNING, "ESM-PROC - PTI %d was already INACTIVE", pti);
*esm_cause = ESM_CAUSE_MESSAGE_TYPE_NOT_COMPATIBLE;
} else {
/* Release the procedure transaction identity */
rc = esm_pt_release(user->esm_pt_data, pti);
if (rc != RETURNok) {
LOG_TRACE(WARNING, "ESM-PROC - Failed to release PTI %d", pti);
*esm_cause = ESM_CAUSE_REQUEST_REJECTED_UNSPECIFIED;
}
} }
}
LOG_FUNC_RETURN(rc); LOG_FUNC_RETURN(rc);
} }
/**************************************************************************** /****************************************************************************
...@@ -495,22 +495,22 @@ int esm_proc_pdn_connectivity_reject(nas_user_t *user, int pti, int *esm_cause) ...@@ -495,22 +495,22 @@ int esm_proc_pdn_connectivity_reject(nas_user_t *user, int pti, int *esm_cause)
***************************************************************************/ ***************************************************************************/
int esm_proc_pdn_connectivity_complete(nas_user_t *user) int esm_proc_pdn_connectivity_complete(nas_user_t *user)
{ {
LOG_FUNC_IN; LOG_FUNC_IN;
esm_pt_data_t *esm_pt_data = user->esm_pt_data; esm_pt_data_t *esm_pt_data = user->esm_pt_data;
int rc = RETURNerror; int rc = RETURNerror;
LOG_TRACE(INFO, "ESM-PROC - PDN connectivity complete"); LOG_TRACE(INFO, "ESM-PROC - PDN connectivity complete");
/* Get the procedure transaction identity assigned to the PDN connection /* Get the procedure transaction identity assigned to the PDN connection
* entry which is still pending in the inactive state */ * entry which is still pending in the inactive state */
int pti = esm_pt_get_pending_pti(esm_pt_data, ESM_PT_INACTIVE); int pti = esm_pt_get_pending_pti(esm_pt_data, ESM_PT_INACTIVE);
if (pti != ESM_PT_UNASSIGNED) { if (pti != ESM_PT_UNASSIGNED) {
/* Release the procedure transaction identity */ /* Release the procedure transaction identity */
rc = esm_pt_release(esm_pt_data, pti); rc = esm_pt_release(esm_pt_data, pti);
} }
LOG_FUNC_RETURN(rc); LOG_FUNC_RETURN(rc);
} }
/**************************************************************************** /****************************************************************************
...@@ -536,40 +536,40 @@ int esm_proc_pdn_connectivity_complete(nas_user_t *user) ...@@ -536,40 +536,40 @@ int esm_proc_pdn_connectivity_complete(nas_user_t *user)
***************************************************************************/ ***************************************************************************/
int esm_proc_pdn_connectivity_failure(nas_user_t *user, int is_pending) int esm_proc_pdn_connectivity_failure(nas_user_t *user, int is_pending)
{ {
LOG_FUNC_IN; LOG_FUNC_IN;
esm_pt_data_t *esm_pt_data = user->esm_pt_data; esm_pt_data_t *esm_pt_data = user->esm_pt_data;
int rc; int rc;
int pti; int pti;
LOG_TRACE(WARNING, "ESM-PROC - PDN connectivity failure in state %s", LOG_TRACE(WARNING, "ESM-PROC - PDN connectivity failure in state %s",
(is_pending)? "PENDING" : "INACTIVE"); (is_pending)? "PENDING" : "INACTIVE");
if (is_pending) { if (is_pending) {
/* Get the procedure transaction identity assigned to the pending PDN /* Get the procedure transaction identity assigned to the pending PDN
* connection entry */ * connection entry */
pti = esm_pt_get_pending_pti(esm_pt_data, ESM_PT_PENDING); pti = esm_pt_get_pending_pti(esm_pt_data, ESM_PT_PENDING);
if (pti == ESM_PT_UNASSIGNED) { if (pti == ESM_PT_UNASSIGNED) {
LOG_TRACE(ERROR, "ESM-PROC - No procedure transaction is PENDING"); LOG_TRACE(ERROR, "ESM-PROC - No procedure transaction is PENDING");
return (RETURNerror); return (RETURNerror);
} }
/* Set the procedure transaction state to INACTIVE */ /* Set the procedure transaction state to INACTIVE */
(void) esm_pt_set_status(esm_pt_data, pti, ESM_PT_INACTIVE); (void) esm_pt_set_status(esm_pt_data, pti, ESM_PT_INACTIVE);
} else { } else {
/* Get the procedure transaction identity assigned to the PDN /* Get the procedure transaction identity assigned to the PDN
* connection entry which is still pending in the inactive state */ * connection entry which is still pending in the inactive state */
pti = esm_pt_get_pending_pti(esm_pt_data, ESM_PT_INACTIVE); pti = esm_pt_get_pending_pti(esm_pt_data, ESM_PT_INACTIVE);
} }
/* Release the procedure transaction identity */ /* Release the procedure transaction identity */
rc = esm_pt_release(esm_pt_data, pti); rc = esm_pt_release(esm_pt_data, pti);
if (rc != RETURNok) { if (rc != RETURNok) {
LOG_TRACE(WARNING, "ESM-PROC - Failed to release PTI %d", pti); LOG_TRACE(WARNING, "ESM-PROC - Failed to release PTI %d", pti);
} }
LOG_FUNC_RETURN(rc); LOG_FUNC_RETURN(rc);
} }
...@@ -607,62 +607,62 @@ int esm_proc_pdn_connectivity_failure(nas_user_t *user, int is_pending) ...@@ -607,62 +607,62 @@ int esm_proc_pdn_connectivity_failure(nas_user_t *user, int is_pending)
** Others: None ** ** Others: None **
** ** ** **
***************************************************************************/ ***************************************************************************/
// FIXME // FIXME
static void *_pdn_connectivity_t3482_handler(void *args) static void *_pdn_connectivity_t3482_handler(void *args)
{ {
LOG_FUNC_IN; LOG_FUNC_IN;
int rc; int rc;
/* Get retransmission timer parameters data */ /* Get retransmission timer parameters data */
esm_pt_timer_data_t *data = args; esm_pt_timer_data_t *data = args;
nas_user_t *user = data->user; nas_user_t *user = data->user;
esm_pt_data_t *esm_pt_data = user->esm_pt_data; esm_pt_data_t *esm_pt_data = user->esm_pt_data;
/* Increment the retransmission counter */ /* Increment the retransmission counter */
data->count += 1; data->count += 1;
LOG_TRACE(WARNING, "ESM-PROC - T3482 timer expired (pti=%d), " LOG_TRACE(WARNING, "ESM-PROC - T3482 timer expired (pti=%d), "
"retransmission counter = %d", data->pti, data->count); "retransmission counter = %d", data->pti, data->count);
if (data->count < ESM_PDN_CONNECTIVITY_COUNTER_MAX) { if (data->count < ESM_PDN_CONNECTIVITY_COUNTER_MAX) {
emm_sap_t emm_sap; emm_sap_t emm_sap;
emm_esm_data_t *emm_esm = &emm_sap.u.emm_esm.u.data; emm_esm_data_t *emm_esm = &emm_sap.u.emm_esm.u.data;
/* /*
* Notify EMM that the PDN connectivity request message * Notify EMM that the PDN connectivity request message
* has to be sent again * has to be sent again
*/ */
emm_sap.primitive = EMMESM_UNITDATA_REQ; emm_sap.primitive = EMMESM_UNITDATA_REQ;
emm_sap.u.emm_esm.ueid = user->ueid; emm_sap.u.emm_esm.ueid = user->ueid;
emm_esm->msg.length = data->msg.length; emm_esm->msg.length = data->msg.length;
emm_esm->msg.value = data->msg.value; emm_esm->msg.value = data->msg.value;
rc = emm_sap_send(user, &emm_sap); rc = emm_sap_send(user, &emm_sap);
if (rc != RETURNerror) { if (rc != RETURNerror) {
/* Restart the timer T3482 */ /* Restart the timer T3482 */
rc = esm_pt_start_timer(user, data->pti, &data->msg, T3482_DEFAULT_VALUE, rc = esm_pt_start_timer(user, data->pti, &data->msg, T3482_DEFAULT_VALUE,
_pdn_connectivity_t3482_handler); _pdn_connectivity_t3482_handler);
} }
} else {
/* Set the procedure transaction state to INACTIVE */
rc = esm_pt_set_status(esm_pt_data, data->pti, ESM_PT_INACTIVE);
if (rc != RETURNok) {
/* The procedure transaction was already in INACTIVE state */
LOG_TRACE(WARNING, "ESM-PROC - PTI %d was already INACTIVE",
data->pti);
} else { } else {
/* Release the transaction identity assigned to this procedure */ /* Set the procedure transaction state to INACTIVE */
rc = esm_pt_release(esm_pt_data, data->pti); rc = esm_pt_set_status(esm_pt_data, data->pti, ESM_PT_INACTIVE);
if (rc != RETURNok) { if (rc != RETURNok) {
LOG_TRACE(WARNING, "ESM-PROC - Failed to release PTI %d", /* The procedure transaction was already in INACTIVE state */
data->pti); LOG_TRACE(WARNING, "ESM-PROC - PTI %d was already INACTIVE",
} data->pti);
} else {
/* Release the transaction identity assigned to this procedure */
rc = esm_pt_release(esm_pt_data, data->pti);
if (rc != RETURNok) {
LOG_TRACE(WARNING, "ESM-PROC - Failed to release PTI %d",
data->pti);
}
}
} }
}
LOG_FUNC_RETURN(NULL); LOG_FUNC_RETURN(NULL);
} }
/* /*
...@@ -692,63 +692,63 @@ static int _pdn_connectivity_create(esm_data_t *esm_data, int pid, const OctetSt ...@@ -692,63 +692,63 @@ static int _pdn_connectivity_create(esm_data_t *esm_data, int pid, const OctetSt
esm_proc_pdn_type_t pdn_type, esm_proc_pdn_type_t pdn_type,
int is_emergency) int is_emergency)
{ {
esm_pdn_t *pdn = NULL; esm_pdn_t *pdn = NULL;
LOG_TRACE(INFO, "ESM-PROC - Create new PDN connection (pid=%d)", pid); LOG_TRACE(INFO, "ESM-PROC - Create new PDN connection (pid=%d)", pid);
if (pid >= ESM_DATA_PDN_MAX) { if (pid >= ESM_DATA_PDN_MAX) {
return (RETURNerror); return (RETURNerror);
} else if (esm_data->pdn[pid].is_active) { } else if (esm_data->pdn[pid].is_active) {
LOG_TRACE(ERROR, "ESM-PROC - PDN connection is active"); LOG_TRACE(ERROR, "ESM-PROC - PDN connection is active");
return (RETURNerror); return (RETURNerror);
}
if (esm_data->pdn[pid].data != NULL) {
/* Update existing non-active PDN connection */
pdn = esm_data->pdn[pid].data;
} else {
/* Create new PDN connection */
pdn = (esm_pdn_t *)malloc(sizeof(esm_pdn_t));
if (pdn == NULL) {
LOG_TRACE(WARNING, "ESM-PROC - "
"Failed to create new PDN connection");
return (RETURNerror);
} }
memset(pdn, 0, sizeof(esm_pdn_t)); if (esm_data->pdn[pid].data != NULL) {
/* Increment the number of PDN connections */ /* Update existing non-active PDN connection */
esm_data->n_pdns += 1; pdn = esm_data->pdn[pid].data;
/* Set the PDN connection identifier */ } else {
esm_data->pdn[pid].pid = pid; /* Create new PDN connection */
/* Reset the PDN connection active indicator */ pdn = (esm_pdn_t *)malloc(sizeof(esm_pdn_t));
esm_data->pdn[pid].is_active = FALSE;
/* Setup the PDN connection data */ if (pdn == NULL) {
esm_data->pdn[pid].data = pdn; LOG_TRACE(WARNING, "ESM-PROC - "
} "Failed to create new PDN connection");
return (RETURNerror);
/* Update the PDN connection data */ }
pdn->is_emergency = is_emergency;
memset(pdn, 0, sizeof(esm_pdn_t));
if ( apn && (apn->length > 0) ) { /* Increment the number of PDN connections */
if (pdn->apn.length > 0) { esm_data->n_pdns += 1;
free(pdn->apn.value); /* Set the PDN connection identifier */
pdn->apn.length = 0; esm_data->pdn[pid].pid = pid;
/* Reset the PDN connection active indicator */
esm_data->pdn[pid].is_active = FALSE;
/* Setup the PDN connection data */
esm_data->pdn[pid].data = pdn;
} }
pdn->apn.value = (uint8_t *)malloc(apn->length + 1); /* Update the PDN connection data */
pdn->is_emergency = is_emergency;
if ( apn && (apn->length > 0) ) {
if (pdn->apn.length > 0) {
free(pdn->apn.value);
pdn->apn.length = 0;
}
pdn->apn.value = (uint8_t *)malloc(apn->length + 1);
if (pdn->apn.value) { if (pdn->apn.value) {
pdn->apn.length = apn->length; pdn->apn.length = apn->length;
memcpy(pdn->apn.value, apn->value, apn->length); memcpy(pdn->apn.value, apn->value, apn->length);
pdn->apn.value[pdn->apn.length] = '\0'; pdn->apn.value[pdn->apn.length] = '\0';
}
} }
}
pdn->type = pdn_type; pdn->type = pdn_type;
pdn->addr_realloc = FALSE; pdn->addr_realloc = FALSE;
return (RETURNok); return (RETURNok);
} }
/**************************************************************************** /****************************************************************************
...@@ -772,75 +772,75 @@ static int _pdn_connectivity_update(esm_data_t *esm_data, int pid, const OctetSt ...@@ -772,75 +772,75 @@ static int _pdn_connectivity_update(esm_data_t *esm_data, int pid, const OctetSt
const OctetString *pdn_addr, const OctetString *pdn_addr,
int esm_cause) int esm_cause)
{ {
LOG_TRACE(INFO, "ESM-PROC - Update PDN connection (pid=%d)", pid); LOG_TRACE(INFO, "ESM-PROC - Update PDN connection (pid=%d)", pid);
if (pid >= ESM_DATA_PDN_MAX) { if (pid >= ESM_DATA_PDN_MAX) {
return (RETURNerror); return (RETURNerror);
} else if (pid != esm_data->pdn[pid].pid) { } else if (pid != esm_data->pdn[pid].pid) {
LOG_TRACE(ERROR, "ESM-PROC - PDN connection identifier is not valid"); LOG_TRACE(ERROR, "ESM-PROC - PDN connection identifier is not valid");
return (RETURNerror); return (RETURNerror);
} else if (esm_data->pdn[pid].data == NULL) { } else if (esm_data->pdn[pid].data == NULL) {
LOG_TRACE(ERROR, "ESM-PROC - PDN connection has not been allocated"); LOG_TRACE(ERROR, "ESM-PROC - PDN connection has not been allocated");
return (RETURNerror); return (RETURNerror);
} else if (esm_data->pdn[pid].is_active) { } else if (esm_data->pdn[pid].is_active) {
LOG_TRACE(WARNING, "ESM-PROC - Active %s PDN connection to %s already " LOG_TRACE(WARNING, "ESM-PROC - Active %s PDN connection to %s already "
"exists", (esm_data->pdn[pid].data->type != ESM_PDN_TYPE_IPV4)? "exists", (esm_data->pdn[pid].data->type != ESM_PDN_TYPE_IPV4)?
"IPv6" : "IPv4", esm_data->pdn[pid].data->apn.value); "IPv6" : "IPv4", esm_data->pdn[pid].data->apn.value);
return (RETURNerror); return (RETURNerror);
} }
/* Get the PDN connection */ /* Get the PDN connection */
esm_pdn_t *pdn = esm_data->pdn[pid].data; esm_pdn_t *pdn = esm_data->pdn[pid].data;
/* Setup the Access Point Name value */ /* Setup the Access Point Name value */
if ( apn && (apn->length > 0) ) { if ( apn && (apn->length > 0) ) {
if (pdn->apn.length > 0) { if (pdn->apn.length > 0) {
free(pdn->apn.value); free(pdn->apn.value);
pdn->apn.length = 0; pdn->apn.length = 0;
} }
pdn->apn.value = (uint8_t *)malloc(apn->length + 1); pdn->apn.value = (uint8_t *)malloc(apn->length + 1);
if (pdn->apn.value) { if (pdn->apn.value) {
pdn->apn.length = apn->length; pdn->apn.length = apn->length;
memcpy(pdn->apn.value, apn->value, apn->length); memcpy(pdn->apn.value, apn->value, apn->length);
pdn->apn.value[pdn->apn.length] = '\0'; pdn->apn.value[pdn->apn.length] = '\0';
}
} }
}
/* Setup the IP address allocated by the network */ /* Setup the IP address allocated by the network */
if ( pdn_addr && (pdn_addr->length > 0) ) { if ( pdn_addr && (pdn_addr->length > 0) ) {
int length = ((pdn_addr->length < ESM_DATA_IP_ADDRESS_SIZE) ? int length = ((pdn_addr->length < ESM_DATA_IP_ADDRESS_SIZE) ?
pdn_addr->length : ESM_DATA_IP_ADDRESS_SIZE); pdn_addr->length : ESM_DATA_IP_ADDRESS_SIZE);
memcpy(pdn->ip_addr, pdn_addr->value, length); memcpy(pdn->ip_addr, pdn_addr->value, length);
pdn->type = pdn_type; pdn->type = pdn_type;
} }
/* /*
* 3GPP TS 24.301, section 6.2.2 * 3GPP TS 24.301, section 6.2.2
* Update the address re-allocation indicator * Update the address re-allocation indicator
*/ */
if (esm_cause == ESM_CAUSE_SINGLE_ADDRESS_BEARERS_ONLY_ALLOWED) { if (esm_cause == ESM_CAUSE_SINGLE_ADDRESS_BEARERS_ONLY_ALLOWED) {
/* The UE requested IPv4 or IPv6 address and the network allows /* The UE requested IPv4 or IPv6 address and the network allows
* single addressing per bearer: * single addressing per bearer:
* The UE should subsequently request another PDN connection for * The UE should subsequently request another PDN connection for
* the other IP version using the UE requested PDN connectivity * the other IP version using the UE requested PDN connectivity
* procedure to the same APN with a single address PDN type * procedure to the same APN with a single address PDN type
* (IPv4 or IPv6) other than the one already activated */ * (IPv4 or IPv6) other than the one already activated */
pdn->addr_realloc = TRUE; pdn->addr_realloc = TRUE;
} else if ( (esm_cause == ESM_CAUSE_PDN_TYPE_IPV4_ONLY_ALLOWED) || } else if ( (esm_cause == ESM_CAUSE_PDN_TYPE_IPV4_ONLY_ALLOWED) ||
(esm_cause == ESM_CAUSE_PDN_TYPE_IPV6_ONLY_ALLOWED) ) { (esm_cause == ESM_CAUSE_PDN_TYPE_IPV6_ONLY_ALLOWED) ) {
/* The UE requested IPv4 or IPv6 address and the network allows /* The UE requested IPv4 or IPv6 address and the network allows
* IPv4 or IPv6 PDN address only: * IPv4 or IPv6 PDN address only:
* The UE shall not subsequently initiate another UE requested * The UE shall not subsequently initiate another UE requested
* PDN connectivity procedure to the same APN to obtain a PDN * PDN connectivity procedure to the same APN to obtain a PDN
* type different from the one allowed by the network */ * type different from the one allowed by the network */
pdn->addr_realloc = FALSE; pdn->addr_realloc = FALSE;
} else if (pdn_type != ESM_PDN_TYPE_IPV4V6) { } else if (pdn_type != ESM_PDN_TYPE_IPV4V6) {
pdn->addr_realloc = TRUE; pdn->addr_realloc = TRUE;
} }
return (RETURNok); return (RETURNok);
} }
/**************************************************************************** /****************************************************************************
...@@ -861,42 +861,42 @@ static int _pdn_connectivity_update(esm_data_t *esm_data, int pid, const OctetSt ...@@ -861,42 +861,42 @@ static int _pdn_connectivity_update(esm_data_t *esm_data, int pid, const OctetSt
***************************************************************************/ ***************************************************************************/
static int _pdn_connectivity_delete(esm_data_t *esm_data, int pid) static int _pdn_connectivity_delete(esm_data_t *esm_data, int pid)
{ {
int pti = ESM_PT_UNASSIGNED; int pti = ESM_PT_UNASSIGNED;
if (pid < ESM_DATA_PDN_MAX) { if (pid < ESM_DATA_PDN_MAX) {
if (pid != esm_data->pdn[pid].pid) { if (pid != esm_data->pdn[pid].pid) {
LOG_TRACE(ERROR, LOG_TRACE(ERROR,
"ESM-PROC - PDN connection identifier is not valid"); "ESM-PROC - PDN connection identifier is not valid");
} else if (esm_data->pdn[pid].data == NULL) { } else if (esm_data->pdn[pid].data == NULL) {
LOG_TRACE(ERROR, LOG_TRACE(ERROR,
"ESM-PROC - PDN connection has not been allocated"); "ESM-PROC - PDN connection has not been allocated");
} else if (esm_data->pdn[pid].is_active) { } else if (esm_data->pdn[pid].is_active) {
LOG_TRACE(ERROR, "ESM-PROC - PDN connection is active"); LOG_TRACE(ERROR, "ESM-PROC - PDN connection is active");
} else { } else {
/* Get the identity of the procedure transaction that created /* Get the identity of the procedure transaction that created
* the PDN connection */ * the PDN connection */
pti = esm_data->pdn[pid].data->pti; pti = esm_data->pdn[pid].data->pti;
}
} }
}
if (pti != ESM_PT_UNASSIGNED) { if (pti != ESM_PT_UNASSIGNED) {
/* Decrement the number of PDN connections */ /* Decrement the number of PDN connections */
esm_data->n_pdns -= 1; esm_data->n_pdns -= 1;
/* Set the PDN connection as available */ /* Set the PDN connection as available */
esm_data->pdn[pid].pid = -1; esm_data->pdn[pid].pid = -1;
/* Release allocated PDN connection data */
if (esm_data->pdn[pid].data->apn.length > 0) {
free(esm_data->pdn[pid].data->apn.value);
}
/* Release allocated PDN connection data */ free(esm_data->pdn[pid].data);
if (esm_data->pdn[pid].data->apn.length > 0) { esm_data->pdn[pid].data = NULL;
free(esm_data->pdn[pid].data->apn.value); LOG_TRACE(WARNING, "ESM-PROC - PDN connection %d released", pid);
} }
free(esm_data->pdn[pid].data); /* Return the procedure transaction identity */
esm_data->pdn[pid].data = NULL; return (pti);
LOG_TRACE(WARNING, "ESM-PROC - PDN connection %d released", pid);
}
/* Return the procedure transaction identity */
return (pti);
} }
/**************************************************************************** /****************************************************************************
...@@ -916,24 +916,24 @@ static int _pdn_connectivity_delete(esm_data_t *esm_data, int pid) ...@@ -916,24 +916,24 @@ static int _pdn_connectivity_delete(esm_data_t *esm_data, int pid)
***************************************************************************/ ***************************************************************************/
static int _pdn_connectivity_set_pti(esm_data_t *esm_data, int pid, int pti) static int _pdn_connectivity_set_pti(esm_data_t *esm_data, int pid, int pti)
{ {
if (pid < ESM_DATA_PDN_MAX) { if (pid < ESM_DATA_PDN_MAX) {
if (pid != esm_data->pdn[pid].pid) { if (pid != esm_data->pdn[pid].pid) {
LOG_TRACE(ERROR, LOG_TRACE(ERROR,
"ESM-PROC - PDN connection identifier is not valid"); "ESM-PROC - PDN connection identifier is not valid");
} else if (esm_data->pdn[pid].data == NULL) { } else if (esm_data->pdn[pid].data == NULL) {
LOG_TRACE(ERROR, LOG_TRACE(ERROR,
"ESM-PROC - PDN connection has not been allocated"); "ESM-PROC - PDN connection has not been allocated");
} else if (esm_data->pdn[pid].is_active) { } else if (esm_data->pdn[pid].is_active) {
LOG_TRACE(ERROR, "ESM-PROC - PDN connection is active"); LOG_TRACE(ERROR, "ESM-PROC - PDN connection is active");
} else { } else {
/* Update the identity of the procedure transaction assigned to /* Update the identity of the procedure transaction assigned to
* the PDN connection */ * the PDN connection */
esm_data->pdn[pid].data->pti = pti; esm_data->pdn[pid].data->pti = pti;
return (RETURNok); return (RETURNok);
}
} }
}
return (RETURNerror); return (RETURNerror);
} }
/**************************************************************************** /****************************************************************************
...@@ -953,26 +953,26 @@ static int _pdn_connectivity_set_pti(esm_data_t *esm_data, int pid, int pti) ...@@ -953,26 +953,26 @@ static int _pdn_connectivity_set_pti(esm_data_t *esm_data, int pid, int pti)
***************************************************************************/ ***************************************************************************/
static int _pdn_connectivity_find_apn(esm_data_t *esm_data, const OctetString *apn) static int _pdn_connectivity_find_apn(esm_data_t *esm_data, const OctetString *apn)
{ {
int i; int i;
for (i = 0; i < ESM_DATA_PDN_MAX; i++) { for (i = 0; i < ESM_DATA_PDN_MAX; i++) {
if ( (esm_data->pdn[i].pid != -1) && esm_data->pdn[i].data ) { if ( (esm_data->pdn[i].pid != -1) && esm_data->pdn[i].data ) {
if (esm_data->pdn[i].data->apn.length != apn->length) { if (esm_data->pdn[i].data->apn.length != apn->length) {
continue; continue;
} }
if (memcmp(esm_data->pdn[i].data->apn.value, if (memcmp(esm_data->pdn[i].data->apn.value,
apn->value, apn->length) != 0) { apn->value, apn->length) != 0) {
continue; continue;
} }
/* PDN entry found */ /* PDN entry found */
break; break;
}
} }
}
/* Return the identifier of the PDN connection */ /* Return the identifier of the PDN connection */
return (esm_data->pdn[i].pid); return (esm_data->pdn[i].pid);
} }
/**************************************************************************** /****************************************************************************
...@@ -994,35 +994,35 @@ static int _pdn_connectivity_find_apn(esm_data_t *esm_data, const OctetString *a ...@@ -994,35 +994,35 @@ static int _pdn_connectivity_find_apn(esm_data_t *esm_data, const OctetString *a
static int _pdn_connectivity_find_pdn(esm_data_t *esm_data, const OctetString *apn, static int _pdn_connectivity_find_pdn(esm_data_t *esm_data, const OctetString *apn,
const esm_proc_pdn_type_t pdn_type) const esm_proc_pdn_type_t pdn_type)
{ {
int i; int i;
for (i = 0; i < ESM_DATA_PDN_MAX; i++) { for (i = 0; i < ESM_DATA_PDN_MAX; i++) {
if ( (esm_data->pdn[i].pid != -1) && esm_data->pdn[i].data ) { if ( (esm_data->pdn[i].pid != -1) && esm_data->pdn[i].data ) {
/* PDN connection established during initial network attachment */ /* PDN connection established during initial network attachment */
if (esm_data->pdn[i].data->apn.length == 0) { if (esm_data->pdn[i].data->apn.length == 0) {
break; break;
} }
/* Subsequent PDN connection established for the specified APN */ /* Subsequent PDN connection established for the specified APN */
if (esm_data->pdn[i].data->apn.length != apn->length) { if (esm_data->pdn[i].data->apn.length != apn->length) {
continue; continue;
} }
if (memcmp(esm_data->pdn[i].data->apn.value, if (memcmp(esm_data->pdn[i].data->apn.value,
apn->value, apn->length) != 0) { apn->value, apn->length) != 0) {
continue; continue;
} }
if (esm_data->pdn[i].data->type == ESM_PDN_TYPE_IPV4V6) { if (esm_data->pdn[i].data->type == ESM_PDN_TYPE_IPV4V6) {
break; break;
} }
if (esm_data->pdn[i].data->type == pdn_type) { if (esm_data->pdn[i].data->type == pdn_type) {
break; break;
} }
}
} }
}
/* Return the identifier of the PDN connection */ /* Return the identifier of the PDN connection */
return (esm_data->pdn[i].pid); return (esm_data->pdn[i].pid);
} }
...@@ -90,6 +90,7 @@ extern int asn1_xer_print; ...@@ -90,6 +90,7 @@ extern int asn1_xer_print;
# define S1AP_DEBUG(x, args...) do { fprintf(stdout, "[S1AP][D]"x, ##args); } while(0) # define S1AP_DEBUG(x, args...) do { fprintf(stdout, "[S1AP][D]"x, ##args); } while(0)
#endif #endif
#define S1AP_FIND_PROTOCOLIE_BY_ID(IE_TYPE, ie, container, IE_ID, mandatory) \ #define S1AP_FIND_PROTOCOLIE_BY_ID(IE_TYPE, ie, container, IE_ID, mandatory) \
do {\ do {\
IE_TYPE **ptr; \ IE_TYPE **ptr; \
...@@ -102,15 +103,17 @@ extern int asn1_xer_print; ...@@ -102,15 +103,17 @@ extern int asn1_xer_print;
break; \ break; \
} \ } \
} \ } \
if (mandatory) DevAssert(ie != NULL); \ if (ie == NULL ) { \
S1AP_ERROR("S1AP_FIND_PROTOCOLIE_BY_ID: %s %d: ie is NULL\n",__FILE__,__LINE__);\
if (mandatory) _Assert_Exit_ \
} \
} while(0) } while(0)
/** \brief Function callback prototype. /** \brief Function callback prototype.
**/ **/
typedef int (*s1ap_message_decoded_callback)( typedef int (*s1ap_message_decoded_callback)(
uint32_t assoc_id, uint32_t assoc_id,
uint32_t stream, uint32_t stream,
S1AP_S1AP_PDU_t *pdu S1AP_S1AP_PDU_t *pdu
); );
/** \brief Handle criticality /** \brief Handle criticality
......
This source diff could not be displayed because it is too large. You can view the blob instead.
This source diff could not be displayed because it is too large. You can view the blob instead.
...@@ -47,60 +47,60 @@ int s1ap_eNB_handle_overload_start(uint32_t assoc_id, ...@@ -47,60 +47,60 @@ int s1ap_eNB_handle_overload_start(uint32_t assoc_id,
uint32_t stream, uint32_t stream,
S1AP_S1AP_PDU_t *pdu) S1AP_S1AP_PDU_t *pdu)
{ {
s1ap_eNB_mme_data_t *mme_desc_p; s1ap_eNB_mme_data_t *mme_desc_p;
S1AP_OverloadStart_t *container; S1AP_OverloadStart_t *container;
S1AP_OverloadStartIEs_t *ie; S1AP_OverloadStartIEs_t *ie;
DevAssert(pdu != NULL); DevAssert(pdu != NULL);
container = &pdu->choice.initiatingMessage.value.choice.OverloadStart; container = &pdu->choice.initiatingMessage.value.choice.OverloadStart;
S1AP_FIND_PROTOCOLIE_BY_ID(S1AP_OverloadStartIEs_t, ie, container, S1AP_FIND_PROTOCOLIE_BY_ID(S1AP_OverloadStartIEs_t, ie, container,
S1AP_ProtocolIE_ID_id_OverloadResponse, true); S1AP_ProtocolIE_ID_id_OverloadResponse, true);
if (ie != NULL) {
DevCheck(ie->value.choice.OverloadResponse.present == DevCheck(ie->value.choice.OverloadResponse.present ==
S1AP_OverloadResponse_PR_overloadAction, S1AP_OverloadResponse_PR_overloadAction,
S1AP_OverloadResponse_PR_overloadAction, 0, 0); S1AP_OverloadResponse_PR_overloadAction, 0, 0);
}
/* Non UE-associated signalling -> stream 0 */ /* Non UE-associated signalling -> stream 0 */
DevCheck(stream == 0, stream, 0, 0); DevCheck(stream == 0, stream, 0, 0);
if ((mme_desc_p = s1ap_eNB_get_MME(NULL, assoc_id, 0)) == NULL) { if ((mme_desc_p = s1ap_eNB_get_MME(NULL, assoc_id, 0)) == NULL) {
/* No MME context associated */ /* No MME context associated */
return -1; return -1;
} }
/* Mark the MME as overloaded and set the overload state according to /* Mark the MME as overloaded and set the overload state according to
* the value received. * the value received.
*/ */
mme_desc_p->state = S1AP_ENB_OVERLOAD; mme_desc_p->state = S1AP_ENB_OVERLOAD;
mme_desc_p->overload_state = mme_desc_p->overload_state =
ie->value.choice.OverloadResponse.choice.overloadAction; ie->value.choice.OverloadResponse.choice.overloadAction;
return 0; return 0;
} }
int s1ap_eNB_handle_overload_stop(uint32_t assoc_id, int s1ap_eNB_handle_overload_stop(uint32_t assoc_id,
uint32_t stream, uint32_t stream,
S1AP_S1AP_PDU_t *pdu) S1AP_S1AP_PDU_t *pdu)
{ {
/* We received Overload stop message, meaning that the MME is no more /* We received Overload stop message, meaning that the MME is no more
* overloaded. This is an empty message, with only message header and no * overloaded. This is an empty message, with only message header and no
* Information Element. * Information Element.
*/ */
DevAssert(pdu != NULL); DevAssert(pdu != NULL);
s1ap_eNB_mme_data_t *mme_desc_p; s1ap_eNB_mme_data_t *mme_desc_p;
/* Non UE-associated signalling -> stream 0 */ /* Non UE-associated signalling -> stream 0 */
DevCheck(stream == 0, stream, 0, 0); DevCheck(stream == 0, stream, 0, 0);
if ((mme_desc_p = s1ap_eNB_get_MME(NULL, assoc_id, 0)) == NULL) { if ((mme_desc_p = s1ap_eNB_get_MME(NULL, assoc_id, 0)) == NULL) {
/* No MME context associated */ /* No MME context associated */
return -1; return -1;
} }
mme_desc_p->state = S1AP_ENB_STATE_CONNECTED; mme_desc_p->state = S1AP_ENB_STATE_CONNECTED;
mme_desc_p->overload_state = S1AP_NO_OVERLOAD; mme_desc_p->overload_state = S1AP_NO_OVERLOAD;
return 0; return 0;
} }
...@@ -42,107 +42,108 @@ void s1ap_eNB_generate_trace_failure(struct s1ap_eNB_ue_context_s *ue_desc_p, ...@@ -42,107 +42,108 @@ void s1ap_eNB_generate_trace_failure(struct s1ap_eNB_ue_context_s *ue_desc_p,
S1AP_E_UTRAN_Trace_ID_t *trace_id, S1AP_E_UTRAN_Trace_ID_t *trace_id,
S1AP_Cause_t *cause_p) S1AP_Cause_t *cause_p)
{ {
S1AP_S1AP_PDU_t pdu; S1AP_S1AP_PDU_t pdu;
S1AP_TraceFailureIndication_t *out; S1AP_TraceFailureIndication_t *out;
S1AP_TraceFailureIndicationIEs_t *ie; S1AP_TraceFailureIndicationIEs_t *ie;
uint8_t *buffer = NULL; uint8_t *buffer = NULL;
uint32_t length; uint32_t length;
DevAssert(ue_desc_p != NULL); DevAssert(ue_desc_p != NULL);
DevAssert(trace_id != NULL); DevAssert(trace_id != NULL);
DevAssert(cause_p != NULL); DevAssert(cause_p != NULL);
/* Prepare the S1AP message to encode */ /* Prepare the S1AP message to encode */
memset(&pdu, 0, sizeof(pdu)); memset(&pdu, 0, sizeof(pdu));
pdu.present = S1AP_S1AP_PDU_PR_initiatingMessage; pdu.present = S1AP_S1AP_PDU_PR_initiatingMessage;
pdu.choice.initiatingMessage.procedureCode = S1AP_ProcedureCode_id_TraceFailureIndication; pdu.choice.initiatingMessage.procedureCode = S1AP_ProcedureCode_id_TraceFailureIndication;
pdu.choice.initiatingMessage.criticality = S1AP_Criticality_ignore; pdu.choice.initiatingMessage.criticality = S1AP_Criticality_ignore;
pdu.choice.initiatingMessage.value.present = S1AP_InitiatingMessage__value_PR_TraceFailureIndication; pdu.choice.initiatingMessage.value.present = S1AP_InitiatingMessage__value_PR_TraceFailureIndication;
out = &pdu.choice.initiatingMessage.value.choice.TraceFailureIndication; out = &pdu.choice.initiatingMessage.value.choice.TraceFailureIndication;
/* mandatory */ /* mandatory */
ie = (S1AP_TraceFailureIndicationIEs_t *)calloc(1, sizeof(S1AP_TraceFailureIndicationIEs_t)); ie = (S1AP_TraceFailureIndicationIEs_t *)calloc(1, sizeof(S1AP_TraceFailureIndicationIEs_t));
ie->id = S1AP_ProtocolIE_ID_id_MME_UE_S1AP_ID; ie->id = S1AP_ProtocolIE_ID_id_MME_UE_S1AP_ID;
ie->criticality = S1AP_Criticality_reject; ie->criticality = S1AP_Criticality_reject;
ie->value.present = S1AP_TraceFailureIndicationIEs__value_PR_MME_UE_S1AP_ID; ie->value.present = S1AP_TraceFailureIndicationIEs__value_PR_MME_UE_S1AP_ID;
ie->value.choice.MME_UE_S1AP_ID = ue_desc_p->mme_ue_s1ap_id; ie->value.choice.MME_UE_S1AP_ID = ue_desc_p->mme_ue_s1ap_id;
ASN_SEQUENCE_ADD(&out->protocolIEs.list, ie); ASN_SEQUENCE_ADD(&out->protocolIEs.list, ie);
/* mandatory */ /* mandatory */
ie = (S1AP_TraceFailureIndicationIEs_t *)calloc(1, sizeof(S1AP_TraceFailureIndicationIEs_t)); ie = (S1AP_TraceFailureIndicationIEs_t *)calloc(1, sizeof(S1AP_TraceFailureIndicationIEs_t));
ie->id = S1AP_ProtocolIE_ID_id_eNB_UE_S1AP_ID; ie->id = S1AP_ProtocolIE_ID_id_eNB_UE_S1AP_ID;
ie->criticality = S1AP_Criticality_reject; ie->criticality = S1AP_Criticality_reject;
ie->value.present = S1AP_TraceFailureIndicationIEs__value_PR_ENB_UE_S1AP_ID; ie->value.present = S1AP_TraceFailureIndicationIEs__value_PR_ENB_UE_S1AP_ID;
ie->value.choice.ENB_UE_S1AP_ID = ue_desc_p->eNB_ue_s1ap_id; ie->value.choice.ENB_UE_S1AP_ID = ue_desc_p->eNB_ue_s1ap_id;
ASN_SEQUENCE_ADD(&out->protocolIEs.list, ie); ASN_SEQUENCE_ADD(&out->protocolIEs.list, ie);
/* mandatory */ /* mandatory */
ie = (S1AP_TraceFailureIndicationIEs_t *)calloc(1, sizeof(S1AP_TraceFailureIndicationIEs_t)); ie = (S1AP_TraceFailureIndicationIEs_t *)calloc(1, sizeof(S1AP_TraceFailureIndicationIEs_t));
ie->id = S1AP_ProtocolIE_ID_id_E_UTRAN_Trace_ID; ie->id = S1AP_ProtocolIE_ID_id_E_UTRAN_Trace_ID;
ie->criticality = S1AP_Criticality_ignore; ie->criticality = S1AP_Criticality_ignore;
ie->value.present = S1AP_TraceFailureIndicationIEs__value_PR_E_UTRAN_Trace_ID; ie->value.present = S1AP_TraceFailureIndicationIEs__value_PR_E_UTRAN_Trace_ID;
memcpy(&ie->value.choice.E_UTRAN_Trace_ID, trace_id, sizeof(S1AP_E_UTRAN_Trace_ID_t)); memcpy(&ie->value.choice.E_UTRAN_Trace_ID, trace_id, sizeof(S1AP_E_UTRAN_Trace_ID_t));
ASN_SEQUENCE_ADD(&out->protocolIEs.list, ie); ASN_SEQUENCE_ADD(&out->protocolIEs.list, ie);
/* mandatory */ /* mandatory */
ie = (S1AP_TraceFailureIndicationIEs_t *)calloc(1, sizeof(S1AP_TraceFailureIndicationIEs_t)); ie = (S1AP_TraceFailureIndicationIEs_t *)calloc(1, sizeof(S1AP_TraceFailureIndicationIEs_t));
ie->id = S1AP_ProtocolIE_ID_id_Cause; ie->id = S1AP_ProtocolIE_ID_id_Cause;
ie->criticality = S1AP_Criticality_ignore; ie->criticality = S1AP_Criticality_ignore;
ie->value.present = S1AP_TraceFailureIndicationIEs__value_PR_Cause; ie->value.present = S1AP_TraceFailureIndicationIEs__value_PR_Cause;
memcpy(&ie->value.choice.Cause, cause_p, sizeof(S1AP_Cause_t)); memcpy(&ie->value.choice.Cause, cause_p, sizeof(S1AP_Cause_t));
ASN_SEQUENCE_ADD(&out->protocolIEs.list, ie); ASN_SEQUENCE_ADD(&out->protocolIEs.list, ie);
if (s1ap_eNB_encode_pdu(&pdu, &buffer, &length) < 0) { if (s1ap_eNB_encode_pdu(&pdu, &buffer, &length) < 0) {
return; return;
} }
s1ap_eNB_itti_send_sctp_data_req(ue_desc_p->mme_ref->s1ap_eNB_instance->instance, s1ap_eNB_itti_send_sctp_data_req(ue_desc_p->mme_ref->s1ap_eNB_instance->instance,
ue_desc_p->mme_ref->assoc_id, buffer, ue_desc_p->mme_ref->assoc_id, buffer,
length, ue_desc_p->tx_stream); length, ue_desc_p->tx_stream);
} }
int s1ap_eNB_handle_trace_start(uint32_t assoc_id, int s1ap_eNB_handle_trace_start(uint32_t assoc_id,
uint32_t stream, uint32_t stream,
S1AP_S1AP_PDU_t *pdu) S1AP_S1AP_PDU_t *pdu)
{ {
S1AP_TraceStart_t *container; S1AP_TraceStart_t *container;
S1AP_TraceStartIEs_t *ie; S1AP_TraceStartIEs_t *ie;
struct s1ap_eNB_ue_context_s *ue_desc_p; struct s1ap_eNB_ue_context_s *ue_desc_p;
struct s1ap_eNB_mme_data_s *mme_ref_p; struct s1ap_eNB_mme_data_s *mme_ref_p;
DevAssert(pdu != NULL); DevAssert(pdu != NULL);
container = &pdu->choice.initiatingMessage.value.choice.TraceStart; container = &pdu->choice.initiatingMessage.value.choice.TraceStart;
S1AP_FIND_PROTOCOLIE_BY_ID(S1AP_TraceStartIEs_t, ie, container, S1AP_FIND_PROTOCOLIE_BY_ID(S1AP_TraceStartIEs_t, ie, container,
S1AP_ProtocolIE_ID_id_eNB_UE_S1AP_ID, TRUE); S1AP_ProtocolIE_ID_id_eNB_UE_S1AP_ID, TRUE);
mme_ref_p = s1ap_eNB_get_MME(NULL, assoc_id, 0); mme_ref_p = s1ap_eNB_get_MME(NULL, assoc_id, 0);
DevAssert(mme_ref_p != NULL); DevAssert(mme_ref_p != NULL);
if ((ue_desc_p = s1ap_eNB_get_ue_context(mme_ref_p->s1ap_eNB_instance, ue_desc_p = s1ap_eNB_get_ue_context(mme_ref_p->s1ap_eNB_instance,
ie->value.choice.ENB_UE_S1AP_ID)) == NULL) { ie->value.choice.ENB_UE_S1AP_ID);
/* Could not find context associated with this eNB_ue_s1ap_id -> generate if (ue_desc_p == NULL) {
* trace failure indication. /* Could not find context associated with this eNB_ue_s1ap_id -> generate
*/ * trace failure indication.
S1AP_E_UTRAN_Trace_ID_t trace_id; */
S1AP_Cause_t cause; S1AP_E_UTRAN_Trace_ID_t trace_id;
memset(&trace_id, 0, sizeof(S1AP_E_UTRAN_Trace_ID_t)); S1AP_Cause_t cause;
memset(&cause, 0, sizeof(S1AP_Cause_t)); memset(&trace_id, 0, sizeof(S1AP_E_UTRAN_Trace_ID_t));
cause.present = S1AP_Cause_PR_radioNetwork; memset(&cause, 0, sizeof(S1AP_Cause_t));
cause.choice.radioNetwork = S1AP_CauseRadioNetwork_unknown_pair_ue_s1ap_id; cause.present = S1AP_Cause_PR_radioNetwork;
s1ap_eNB_generate_trace_failure(ue_desc_p, &trace_id, &cause); cause.choice.radioNetwork = S1AP_CauseRadioNetwork_unknown_pair_ue_s1ap_id;
} s1ap_eNB_generate_trace_failure(NULL, &trace_id, &cause);
}
return 0;
return 0;
} }
int s1ap_eNB_handle_deactivate_trace(uint32_t assoc_id, int s1ap_eNB_handle_deactivate_trace(uint32_t assoc_id,
uint32_t stream, uint32_t stream,
S1AP_S1AP_PDU_t *message_p) S1AP_S1AP_PDU_t *message_p)
{ {
// S1AP_DeactivateTraceIEs_t *deactivate_trace_p; // S1AP_DeactivateTraceIEs_t *deactivate_trace_p;
// //
// deactivate_trace_p = &message_p->msg.deactivateTraceIEs; // deactivate_trace_p = &message_p->msg.deactivateTraceIEs;
return 0; return 0;
} }
...@@ -59,33 +59,33 @@ ...@@ -59,33 +59,33 @@
enum sctp_connection_type_e { enum sctp_connection_type_e {
SCTP_TYPE_CLIENT, SCTP_TYPE_CLIENT,
SCTP_TYPE_SERVER, SCTP_TYPE_SERVER,
SCTP_TYPE_MULTI_SERVER, SCTP_TYPE_MULTI_SERVER,
SCTP_TYPE_MAX SCTP_TYPE_MAX
}; };
typedef struct sctp_cnx_list_elm_s { typedef struct sctp_cnx_list_elm_s {
STAILQ_ENTRY(sctp_cnx_list_elm_s) entries; STAILQ_ENTRY(sctp_cnx_list_elm_s) entries;
/* Type of this association /* Type of this association
*/ */
enum sctp_connection_type_e connection_type; enum sctp_connection_type_e connection_type;
int sd; ///< Socket descriptor of connection */ int sd; ///< Socket descriptor of connection */
uint16_t local_port; uint16_t local_port;
uint16_t in_streams; ///< Number of input streams negociated for this connection uint16_t in_streams; ///< Number of input streams negociated for this connection
uint16_t out_streams; ///< Number of output streams negotiated for this connection uint16_t out_streams; ///< Number of output streams negotiated for this connection
uint16_t ppid; ///< Payload protocol Identifier uint16_t ppid; ///< Payload protocol Identifier
int32_t assoc_id; ///< SCTP association id for the connection (note4debug host byte order) int32_t assoc_id; ///< SCTP association id for the connection (note4debug host byte order)
uint32_t messages_recv; ///< Number of messages received on this connection uint32_t messages_recv; ///< Number of messages received on this connection
uint32_t messages_sent; ///< Number of messages sent on this connection uint32_t messages_sent; ///< Number of messages sent on this connection
task_id_t task_id; ///< Task id of the task who asked for this connection task_id_t task_id; ///< Task id of the task who asked for this connection
instance_t instance; ///< Instance instance_t instance; ///< Instance
uint16_t cnx_id; ///< Upper layer identifier uint16_t cnx_id; ///< Upper layer identifier
struct sockaddr *peer_addresses;///< A list of peer addresses for server socket struct sockaddr *peer_addresses;///< A list of peer addresses for server socket
int nb_peer_addresses; ///< For server socket int nb_peer_addresses; ///< For server socket
} sctp_cnx_list_elm_t; } sctp_cnx_list_elm_t;
...@@ -95,962 +95,965 @@ static uint16_t sctp_nb_cnx = 0; ...@@ -95,962 +95,965 @@ static uint16_t sctp_nb_cnx = 0;
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
struct sctp_cnx_list_elm_s *sctp_get_cnx(int32_t assoc_id, int sd) struct sctp_cnx_list_elm_s *sctp_get_cnx(int32_t assoc_id, int sd)
{ {
struct sctp_cnx_list_elm_s *elm; struct sctp_cnx_list_elm_s *elm;
STAILQ_FOREACH(elm, &sctp_cnx_list, entries) { STAILQ_FOREACH(elm, &sctp_cnx_list, entries) {
if (assoc_id != -1) { if (assoc_id != -1) {
if (elm->assoc_id == assoc_id) { if (elm->assoc_id == assoc_id) {
return elm; return elm;
} }
} else { } else {
if (elm->sd == sd) { if (elm->sd == sd) {
return elm; return elm;
} }
}
} }
}
return NULL; return NULL;
} }
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
static inline static inline
void void
sctp_eNB_accept_associations_multi( sctp_eNB_accept_associations_multi(
struct sctp_cnx_list_elm_s *sctp_cnx) struct sctp_cnx_list_elm_s *sctp_cnx)
{ {
int ns; int ns;
int n; int n;
int flags = 0; int flags = 0;
socklen_t from_len; socklen_t from_len;
struct sctp_sndrcvinfo sinfo; struct sctp_sndrcvinfo sinfo;
struct sockaddr_in addr; struct sockaddr_in addr;
uint8_t buffer[SCTP_RECV_BUFFER_SIZE]; uint8_t buffer[SCTP_RECV_BUFFER_SIZE];
DevAssert(sctp_cnx != NULL); DevAssert(sctp_cnx != NULL);
memset((void *)&addr, 0, sizeof(struct sockaddr_in)); memset((void *)&addr, 0, sizeof(struct sockaddr_in));
from_len = (socklen_t)sizeof(struct sockaddr_in); from_len = (socklen_t)sizeof(struct sockaddr_in);
memset((void *)&sinfo, 0, sizeof(struct sctp_sndrcvinfo)); memset((void *)&sinfo, 0, sizeof(struct sctp_sndrcvinfo));
n = sctp_recvmsg(sctp_cnx->sd, (void *)buffer, SCTP_RECV_BUFFER_SIZE, n = sctp_recvmsg(sctp_cnx->sd, (void *)buffer, SCTP_RECV_BUFFER_SIZE,
(struct sockaddr *)&addr, &from_len, (struct sockaddr *)&addr, &from_len,
&sinfo, &flags); &sinfo, &flags);
if (n < 0) { if (n < 0) {
if (errno == ENOTCONN) { if (errno == ENOTCONN) {
SCTP_DEBUG("Received not connected for sd %d\n", sctp_cnx->sd); SCTP_DEBUG("Received not connected for sd %d\n", sctp_cnx->sd);
close(sctp_cnx->sd); close(sctp_cnx->sd);
} else { } else {
SCTP_DEBUG("An error occured during read\n"); SCTP_DEBUG("An error occured during read\n");
SCTP_ERROR("sctp_recvmsg (fd %d, len %d ): %s:%d\n", sctp_cnx->sd, n, strerror(errno), errno); SCTP_ERROR("sctp_recvmsg (fd %d, len %d ): %s:%d\n", sctp_cnx->sd, n, strerror(errno), errno);
}
return;
} }
return;
}
if (flags & MSG_NOTIFICATION) { if (flags & MSG_NOTIFICATION) {
union sctp_notification *snp; union sctp_notification *snp;
snp = (union sctp_notification *)buffer; snp = (union sctp_notification *)buffer;
SCTP_DEBUG("Received notification for sd %d, type %u\n", SCTP_DEBUG("Received notification for sd %d, type %u\n",
sctp_cnx->sd, snp->sn_header.sn_type); sctp_cnx->sd, snp->sn_header.sn_type);
/* Association has changed. */ /* Association has changed. */
if (SCTP_ASSOC_CHANGE == snp->sn_header.sn_type) { if (SCTP_ASSOC_CHANGE == snp->sn_header.sn_type) {
struct sctp_assoc_change *sctp_assoc_changed; struct sctp_assoc_change *sctp_assoc_changed;
sctp_assoc_changed = &snp->sn_assoc_change; sctp_assoc_changed = &snp->sn_assoc_change;
SCTP_DEBUG("Client association changed: %d\n", sctp_assoc_changed->sac_state); SCTP_DEBUG("Client association changed: %d\n", sctp_assoc_changed->sac_state);
/* New physical association requested by a peer */ /* New physical association requested by a peer */
switch (sctp_assoc_changed->sac_state) { switch (sctp_assoc_changed->sac_state) {
case SCTP_COMM_UP: { case SCTP_COMM_UP: {
SCTP_DEBUG("Comm up notified for sd %d, assigned assoc_id %d\n", SCTP_DEBUG("Comm up notified for sd %d, assigned assoc_id %d\n",
sctp_cnx->sd, sctp_assoc_changed->sac_assoc_id); sctp_cnx->sd, sctp_assoc_changed->sac_assoc_id);
struct sctp_cnx_list_elm_s *new_cnx; struct sctp_cnx_list_elm_s *new_cnx;
new_cnx = calloc(1, sizeof(*sctp_cnx)); new_cnx = calloc(1, sizeof(*sctp_cnx));
DevAssert(new_cnx != NULL); DevAssert(new_cnx != NULL);
new_cnx->connection_type = SCTP_TYPE_CLIENT; new_cnx->connection_type = SCTP_TYPE_CLIENT;
ns = sctp_peeloff(sctp_cnx->sd, sctp_assoc_changed->sac_assoc_id); ns = sctp_peeloff(sctp_cnx->sd, sctp_assoc_changed->sac_assoc_id);
new_cnx->sd = ns; new_cnx->sd = ns;
new_cnx->task_id = sctp_cnx->task_id; new_cnx->task_id = sctp_cnx->task_id;
new_cnx->cnx_id = 0; new_cnx->cnx_id = 0;
new_cnx->ppid = sctp_cnx->ppid; new_cnx->ppid = sctp_cnx->ppid;
new_cnx->instance = sctp_cnx->instance; new_cnx->instance = sctp_cnx->instance;
new_cnx->local_port = sctp_cnx->local_port; new_cnx->local_port = sctp_cnx->local_port;
new_cnx->assoc_id = sctp_assoc_changed->sac_assoc_id; new_cnx->assoc_id = sctp_assoc_changed->sac_assoc_id;
if (sctp_get_sockinfo(ns, &new_cnx->in_streams, &new_cnx->out_streams, if (sctp_get_sockinfo(ns, &new_cnx->in_streams, &new_cnx->out_streams,
&new_cnx->assoc_id) != 0) { &new_cnx->assoc_id) != 0) {
SCTP_ERROR("sctp_get_sockinfo failed\n"); SCTP_ERROR("sctp_get_sockinfo failed\n");
close(ns); close(ns);
free(new_cnx); free(new_cnx);
return; return;
} }
/* Insert new element at end of list */ /* Insert new element at end of list */
STAILQ_INSERT_TAIL(&sctp_cnx_list, new_cnx, entries); STAILQ_INSERT_TAIL(&sctp_cnx_list, new_cnx, entries);
sctp_nb_cnx++; sctp_nb_cnx++;
/* Add the socket to list of fd monitored by ITTI */ /* Add the socket to list of fd monitored by ITTI */
itti_subscribe_event_fd(TASK_SCTP, ns); itti_subscribe_event_fd(TASK_SCTP, ns);
sctp_itti_send_association_ind(new_cnx->task_id, new_cnx->instance, sctp_itti_send_association_ind(new_cnx->task_id, new_cnx->instance,
new_cnx->assoc_id, new_cnx->local_port, new_cnx->assoc_id, new_cnx->local_port,
new_cnx->out_streams, new_cnx->in_streams); new_cnx->out_streams, new_cnx->in_streams);
} }
break; break;
default: default:
break; break;
} }
}
} else {
SCTP_DEBUG("No notification from SCTP\n");
} }
} else {
SCTP_DEBUG("No notification from SCTP\n");
}
} }
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
void void
sctp_handle_new_association_req_multi( sctp_handle_new_association_req_multi(
const instance_t instance, const instance_t instance,
const task_id_t requestor, const task_id_t requestor,
const sctp_new_association_req_multi_t * const sctp_new_association_req_p) const sctp_new_association_req_multi_t * const sctp_new_association_req_p)
{ {
int ns; int ns;
int sd; int sd;
int32_t assoc_id = 0; int32_t assoc_id = 0;
struct sctp_cnx_list_elm_s *sctp_cnx = NULL; struct sctp_cnx_list_elm_s *sctp_cnx = NULL;
enum sctp_connection_type_e connection_type = SCTP_TYPE_CLIENT; enum sctp_connection_type_e connection_type = SCTP_TYPE_CLIENT;
/* Prepare a new SCTP association as requested by upper layer and try to connect /* Prepare a new SCTP association as requested by upper layer and try to connect
* to remote host. * to remote host.
*/ */
DevAssert(sctp_new_association_req_p != NULL); DevAssert(sctp_new_association_req_p != NULL);
sd = sctp_new_association_req_p->multi_sd; sd = sctp_new_association_req_p->multi_sd;
/* Create new socket with IPv6 affinity */ /* Create new socket with IPv6 affinity */
//#warning "SCTP may Force IPv4 only, here" //#warning "SCTP may Force IPv4 only, here"
/* Mark the socket as non-blocking */ /* Mark the socket as non-blocking */
//if (fcntl(sd, F_SETFL, O_NONBLOCK) < 0) { //if (fcntl(sd, F_SETFL, O_NONBLOCK) < 0) {
//SCTP_ERROR("fcntl F_SETFL O_NONBLOCK failed: %s\n", //SCTP_ERROR("fcntl F_SETFL O_NONBLOCK failed: %s\n",
// strerror(errno)); // strerror(errno));
//close(sd); //close(sd);
//return; //return;
//} //}
/* SOCK_STREAM socket type requires an explicit connect to the remote host
* address and port.
* Only use IPv4 for the first connection attempt
*/
if ((sctp_new_association_req_p->remote_address.ipv6 != 0) ||
(sctp_new_association_req_p->remote_address.ipv4 != 0)) {
uint8_t address_index = 0;
uint8_t used_address = sctp_new_association_req_p->remote_address.ipv6 +
sctp_new_association_req_p->remote_address.ipv4;
struct sockaddr_in addr[used_address];
memset(addr, 0, used_address * sizeof(struct sockaddr_in));
if (sctp_new_association_req_p->remote_address.ipv6 == 1) {
if (inet_pton(AF_INET6, sctp_new_association_req_p->remote_address.ipv6_address,
&addr[address_index].sin_addr.s_addr) != 1) {
SCTP_ERROR("Failed to convert ipv6 address %*s to network type\n",
(int)strlen(sctp_new_association_req_p->remote_address.ipv6_address),
sctp_new_association_req_p->remote_address.ipv6_address);
//close(sd);
//return;
exit(1);
}
SCTP_DEBUG("Converted ipv6 address %*s to network type\n",
(int)strlen(sctp_new_association_req_p->remote_address.ipv6_address),
sctp_new_association_req_p->remote_address.ipv6_address);
addr[address_index].sin_family = AF_INET6;
addr[address_index].sin_port = htons(sctp_new_association_req_p->port);
address_index++;
}
if (sctp_new_association_req_p->remote_address.ipv4 == 1) { /* SOCK_STREAM socket type requires an explicit connect to the remote host
if (inet_pton(AF_INET, sctp_new_association_req_p->remote_address.ipv4_address, * address and port.
&addr[address_index].sin_addr.s_addr) != 1) { * Only use IPv4 for the first connection attempt
SCTP_ERROR("Failed to convert ipv4 address %*s to network type\n", */
(int)strlen(sctp_new_association_req_p->remote_address.ipv4_address), if ((sctp_new_association_req_p->remote_address.ipv6 != 0) ||
sctp_new_association_req_p->remote_address.ipv4_address); (sctp_new_association_req_p->remote_address.ipv4 != 0)) {
//close(sd); uint8_t address_index = 0;
//return; uint8_t used_address = sctp_new_association_req_p->remote_address.ipv6 +
exit(1); sctp_new_association_req_p->remote_address.ipv4;
} struct sockaddr_in addr[used_address];
SCTP_DEBUG("Converted ipv4 address %*s to network type\n", memset(addr, 0, used_address * sizeof(struct sockaddr_in));
(int)strlen(sctp_new_association_req_p->remote_address.ipv4_address),
sctp_new_association_req_p->remote_address.ipv4_address); if (sctp_new_association_req_p->remote_address.ipv6 == 1) {
if (inet_pton(AF_INET6, sctp_new_association_req_p->remote_address.ipv6_address,
addr[address_index].sin_family = AF_INET; &addr[address_index].sin_addr.s_addr) != 1) {
addr[address_index].sin_port = htons(sctp_new_association_req_p->port); SCTP_ERROR("Failed to convert ipv6 address %*s to network type\n",
address_index++; (int)strlen(sctp_new_association_req_p->remote_address.ipv6_address),
} sctp_new_association_req_p->remote_address.ipv6_address);
//close(sd);
//return;
exit(1);
}
SCTP_DEBUG("Converted ipv6 address %*s to network type\n",
(int)strlen(sctp_new_association_req_p->remote_address.ipv6_address),
sctp_new_association_req_p->remote_address.ipv6_address);
addr[address_index].sin_family = AF_INET6;
addr[address_index].sin_port = htons(sctp_new_association_req_p->port);
address_index++;
}
/* Connect to remote host and port */ if (sctp_new_association_req_p->remote_address.ipv4 == 1) {
if (sctp_connectx(sd, (struct sockaddr *)addr, 1, &assoc_id) < 0) { if (inet_pton(AF_INET, sctp_new_association_req_p->remote_address.ipv4_address,
/* sctp_connectx on non-blocking socket return EINPROGRESS */ &addr[address_index].sin_addr.s_addr) != 1) {
if (errno != EINPROGRESS) { SCTP_ERROR("Failed to convert ipv4 address %*s to network type\n",
SCTP_ERROR("Connect failed: %s\n", strerror(errno)); (int)strlen(sctp_new_association_req_p->remote_address.ipv4_address),
sctp_itti_send_association_resp( sctp_new_association_req_p->remote_address.ipv4_address);
requestor, instance, -1, sctp_new_association_req_p->ulp_cnx_id, //close(sd);
SCTP_STATE_UNREACHABLE, 0, 0); //return;
/* Add the socket to list of fd monitored by ITTI */ exit(1);
//itti_unsubscribe_event_fd(TASK_SCTP, sd); }
//close(sd);
return; SCTP_DEBUG("Converted ipv4 address %*s to network type\n",
} else { (int)strlen(sctp_new_association_req_p->remote_address.ipv4_address),
SCTP_DEBUG("connectx assoc_id %d in progress..., used %d addresses\n", sctp_new_association_req_p->remote_address.ipv4_address);
assoc_id, used_address);
} addr[address_index].sin_family = AF_INET;
} else { addr[address_index].sin_port = htons(sctp_new_association_req_p->port);
SCTP_DEBUG("sctp_connectx SUCCESS, used %d addresses assoc_id %d\n", address_index++;
used_address, }
assoc_id);
/* Connect to remote host and port */
if (sctp_connectx(sd, (struct sockaddr *)addr, 1, &assoc_id) < 0) {
/* sctp_connectx on non-blocking socket return EINPROGRESS */
if (errno != EINPROGRESS) {
SCTP_ERROR("Connect failed: %s\n", strerror(errno));
sctp_itti_send_association_resp(
requestor, instance, -1, sctp_new_association_req_p->ulp_cnx_id,
SCTP_STATE_UNREACHABLE, 0, 0);
/* Add the socket to list of fd monitored by ITTI */
//itti_unsubscribe_event_fd(TASK_SCTP, sd);
//close(sd);
return;
} else {
SCTP_DEBUG("connectx assoc_id %d in progress..., used %d addresses\n",
assoc_id, used_address);
}
} else {
SCTP_DEBUG("sctp_connectx SUCCESS, used %d addresses assoc_id %d\n",
used_address,
assoc_id);
}
} }
}
ns = sctp_peeloff(sd,assoc_id); ns = sctp_peeloff(sd,assoc_id);
sctp_cnx = calloc(1, sizeof(*sctp_cnx)); sctp_cnx = calloc(1, sizeof(*sctp_cnx));
sctp_cnx->connection_type = connection_type; sctp_cnx->connection_type = connection_type;
sctp_cnx->sd = ns; sctp_cnx->sd = ns;
sctp_cnx->task_id = requestor; sctp_cnx->task_id = requestor;
sctp_cnx->cnx_id = sctp_new_association_req_p->ulp_cnx_id; sctp_cnx->cnx_id = sctp_new_association_req_p->ulp_cnx_id;
sctp_cnx->ppid = sctp_new_association_req_p->ppid; sctp_cnx->ppid = sctp_new_association_req_p->ppid;
sctp_cnx->instance = instance; sctp_cnx->instance = instance;
sctp_cnx->assoc_id = assoc_id; sctp_cnx->assoc_id = assoc_id;
/* Add the socket to list of fd monitored by ITTI */ /* Add the socket to list of fd monitored by ITTI */
itti_subscribe_event_fd(TASK_SCTP, ns); itti_subscribe_event_fd(TASK_SCTP, ns);
/* Insert new element at end of list */ /* Insert new element at end of list */
STAILQ_INSERT_TAIL(&sctp_cnx_list, sctp_cnx, entries); STAILQ_INSERT_TAIL(&sctp_cnx_list, sctp_cnx, entries);
sctp_nb_cnx++; sctp_nb_cnx++;
SCTP_DEBUG("Inserted new descriptor for sd %d in list, nb elements %u, assoc_id %d\n", SCTP_DEBUG("Inserted new descriptor for sd %d in list, nb elements %u, assoc_id %d\n",
ns, sctp_nb_cnx, assoc_id); ns, sctp_nb_cnx, assoc_id);
} }
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
void void
sctp_handle_new_association_req( sctp_handle_new_association_req(
const instance_t instance, const instance_t instance,
const task_id_t requestor, const task_id_t requestor,
const sctp_new_association_req_t * const sctp_new_association_req_p) const sctp_new_association_req_t * const sctp_new_association_req_p)
{ {
int sd = 0; int sd = 0;
int32_t assoc_id = 0; int32_t assoc_id = 0;
struct sctp_event_subscribe events; struct sctp_event_subscribe events;
struct sctp_cnx_list_elm_s *sctp_cnx = NULL; struct sctp_cnx_list_elm_s *sctp_cnx = NULL;
enum sctp_connection_type_e connection_type = SCTP_TYPE_CLIENT; enum sctp_connection_type_e connection_type = SCTP_TYPE_CLIENT;
struct ifreq ifr; struct ifreq ifr;
struct ifaddrs *ifaddr = NULL; struct ifaddrs *ifaddr = NULL;
struct ifaddrs *ifa = NULL; struct ifaddrs *ifa = NULL;
int family = 0; int family = 0;
int s = 0; int s = 0;
struct in_addr in; struct in_addr in;
struct in6_addr in6; struct in6_addr in6;
/* Prepare a new SCTP association as requested by upper layer and try to connect /* Prepare a new SCTP association as requested by upper layer and try to connect
* to remote host. * to remote host.
*/ */
DevAssert(sctp_new_association_req_p != NULL); DevAssert(sctp_new_association_req_p != NULL);
/* Create new socket with IPv6 affinity */ /* Create new socket with IPv6 affinity */
//#warning "SCTP may Force IPv4 only, here" //#warning "SCTP may Force IPv4 only, here"
#ifdef NO_VIRTUAL_MACHINE #ifdef NO_VIRTUAL_MACHINE
// in init chunk appears a list of host addresses, IPv4 and IPv4 in an arbitrary (unsorted) order // in init chunk appears a list of host addresses, IPv4 and IPv4 in an arbitrary (unsorted) order
// SCTP hearbeats starts with first ipv4 addresses then stop triyng with other ipv4 addresses // SCTP hearbeats starts with first ipv4 addresses then stop triyng with other ipv4 addresses
// if it encounters an IPv6 address in list, so we can force the building of IPv4 addresses only // if it encounters an IPv6 address in list, so we can force the building of IPv4 addresses only
// with AF_INET (the working IPv4 address can be the last in the list...) // with AF_INET (the working IPv4 address can be the last in the list...)
if ((sd = socket(AF_INET6, SOCK_STREAM, IPPROTO_SCTP)) < 0) { if ((sd = socket(AF_INET6, SOCK_STREAM, IPPROTO_SCTP)) < 0) {
#else #else
if ((sd = socket(AF_INET, SOCK_STREAM, IPPROTO_SCTP)) < 0) { if ((sd = socket(AF_INET, SOCK_STREAM, IPPROTO_SCTP)) < 0) {
#endif #endif
SCTP_ERROR("Socket creation failed: %s\n", strerror(errno)); SCTP_ERROR("Socket creation failed: %s\n", strerror(errno));
return; return;
}
/* Add the socket to list of fd monitored by ITTI */
itti_subscribe_event_fd(TASK_SCTP, sd);
if (sctp_set_init_opt(sd,
sctp_new_association_req_p->in_streams,
sctp_new_association_req_p->out_streams,
SCTP_MAX_ATTEMPTS, SCTP_TIMEOUT) != 0) {
SCTP_ERROR("Setsockopt IPPROTO_SCTP_INITMSG failed: %s\n",
strerror(errno));
itti_unsubscribe_event_fd(TASK_SCTP, sd);
close(sd);
return;
}
/* Subscribe to all events */
memset((void *)&events, 1, sizeof(struct sctp_event_subscribe));
if (setsockopt(sd, IPPROTO_SCTP, SCTP_EVENTS, &events,
sizeof(struct sctp_event_subscribe)) < 0) {
SCTP_ERROR("Setsockopt IPPROTO_SCTP_EVENTS failed: %s\n",
strerror(errno));
close(sd);
return;
}
// Bind to device ... or we could bind to address also
if (getifaddrs(&ifaddr) == -1) {
SCTP_ERROR("getifaddrs failed: %s\n", strerror(errno));
close(sd);
}
/* Walk through linked list, maintaining head pointer so we
can free list later */
for (ifa = ifaddr; ifa != NULL; ifa = ifa->ifa_next) {
if (ifa->ifa_addr == NULL)
continue;
family = ifa->ifa_addr->sa_family;
/* For an AF_INET* interface address, display the address */
if (sctp_new_association_req_p->local_address.ipv4 && family == AF_INET) {
// compare address
s = inet_aton(sctp_new_association_req_p->local_address.ipv4_address,
&in);
if (s > 0 ) {
if (((struct sockaddr_in*)ifa->ifa_addr)->sin_addr.s_addr == in.s_addr) {
struct sockaddr_in locaddr;
locaddr.sin_family = AF_INET;
locaddr.sin_port = htons(sctp_new_association_req_p->port);
locaddr.sin_addr.s_addr = in.s_addr;
if (sctp_bindx(sd, (struct sockaddr*)&locaddr, 1, SCTP_BINDX_ADD_ADDR) < 0) {
SCTP_ERROR("sctp_bindx SCTP_BINDX_ADD_ADDR failed: %s\n",
strerror(errno));
} else {
SCTP_DEBUG("sctp_bindx SCTP_BINDX_ADD_ADDR socket bound to : %s\n",
inet_ntoa(locaddr.sin_addr));
}
break;
}
}
} else if (sctp_new_association_req_p->local_address.ipv6 && family == AF_INET6) {
// compare address
s = inet_pton(AF_INET6,
sctp_new_association_req_p->local_address.ipv6_address,
&in6);
if (s == 1 ) {
if (memcmp(&((struct sockaddr_in6*)ifa->ifa_addr)->sin6_addr,
&in6, sizeof(in6)) == 0) {
memset(&ifr, 0, sizeof(ifr));
snprintf(ifr.ifr_name, sizeof(ifr.ifr_name), "%s", ifa->ifa_name);
if (setsockopt(sd, SOL_SOCKET, SO_BINDTODEVICE, (void *)&ifr, sizeof(ifr)) < 0) {
SCTP_ERROR("Setsockopt SOL_SOCKET failed: %s\n",
strerror(errno));
} else {
SCTP_DEBUG("Setsockopt SOL_SOCKET socket bound to : %s\n",
ifa->ifa_name);
}
break;
}
}
} }
}
/* Add the socket to list of fd monitored by ITTI */
freeifaddrs(ifaddr); itti_subscribe_event_fd(TASK_SCTP, sd);
/* Mark the socket as non-blocking */ if (sctp_set_init_opt(sd,
if (fcntl(sd, F_SETFL, O_NONBLOCK) < 0) { sctp_new_association_req_p->in_streams,
SCTP_ERROR("fcntl F_SETFL O_NONBLOCK failed: %s\n", sctp_new_association_req_p->out_streams,
strerror(errno)); SCTP_MAX_ATTEMPTS, SCTP_TIMEOUT) != 0) {
close(sd); SCTP_ERROR("Setsockopt IPPROTO_SCTP_INITMSG failed: %s\n",
return; strerror(errno));
} itti_unsubscribe_event_fd(TASK_SCTP, sd);
/* SOCK_STREAM socket type requires an explicit connect to the remote host
* address and port.
* Only use IPv4 for the first connection attempt
*/
if ((sctp_new_association_req_p->remote_address.ipv6 != 0) ||
(sctp_new_association_req_p->remote_address.ipv4 != 0)) {
uint8_t address_index = 0;
uint8_t used_address = sctp_new_association_req_p->remote_address.ipv6 +
sctp_new_association_req_p->remote_address.ipv4;
struct sockaddr_in addr[used_address];
memset(addr, 0, used_address * sizeof(struct sockaddr_in));
if (sctp_new_association_req_p->remote_address.ipv6 == 1) {
if (inet_pton(AF_INET6, sctp_new_association_req_p->remote_address.ipv6_address,
&addr[address_index].sin_addr.s_addr) != 1) {
SCTP_ERROR("Failed to convert ipv6 address %*s to network type\n",
(int)strlen(sctp_new_association_req_p->remote_address.ipv6_address),
sctp_new_association_req_p->remote_address.ipv6_address);
close(sd); close(sd);
return; return;
}
SCTP_DEBUG("Converted ipv6 address %*s to network type\n",
(int)strlen(sctp_new_association_req_p->remote_address.ipv6_address),
sctp_new_association_req_p->remote_address.ipv6_address);
addr[address_index].sin_family = AF_INET6;
addr[address_index].sin_port = htons(sctp_new_association_req_p->port);
address_index++;
} }
if (sctp_new_association_req_p->remote_address.ipv4 == 1) { /* Subscribe to all events */
if (inet_pton(AF_INET, sctp_new_association_req_p->remote_address.ipv4_address, memset((void *)&events, 1, sizeof(struct sctp_event_subscribe));
&addr[address_index].sin_addr.s_addr) != 1) {
SCTP_ERROR("Failed to convert ipv4 address %*s to network type\n", if (setsockopt(sd, IPPROTO_SCTP, SCTP_EVENTS, &events,
(int)strlen(sctp_new_association_req_p->remote_address.ipv4_address), sizeof(struct sctp_event_subscribe)) < 0) {
sctp_new_association_req_p->remote_address.ipv4_address); SCTP_ERROR("Setsockopt IPPROTO_SCTP_EVENTS failed: %s\n",
strerror(errno));
close(sd); close(sd);
return; return;
} }
SCTP_DEBUG("Converted ipv4 address %*s to network type\n", // Bind to device ... or we could bind to address also
(int)strlen(sctp_new_association_req_p->remote_address.ipv4_address), if (getifaddrs(&ifaddr) == -1) {
sctp_new_association_req_p->remote_address.ipv4_address); SCTP_ERROR("getifaddrs failed: %s\n", strerror(errno));
close(sd);
}
addr[address_index].sin_family = AF_INET; /* Walk through linked list, maintaining head pointer so we
addr[address_index].sin_port = htons(sctp_new_association_req_p->port); can free list later */
address_index++; for (ifa = ifaddr; ifa != NULL; ifa = ifa->ifa_next) {
if (ifa->ifa_addr == NULL)
continue;
family = ifa->ifa_addr->sa_family;
/* For an AF_INET* interface address, display the address */
if (sctp_new_association_req_p->local_address.ipv4 && family == AF_INET) {
// compare address
s = inet_aton(sctp_new_association_req_p->local_address.ipv4_address,
&in);
if (s > 0 ) {
if (((struct sockaddr_in*)ifa->ifa_addr)->sin_addr.s_addr == in.s_addr) {
struct sockaddr_in locaddr;
locaddr.sin_family = AF_INET;
locaddr.sin_port = htons(sctp_new_association_req_p->port);
locaddr.sin_addr.s_addr = in.s_addr;
if (sctp_bindx(sd, (struct sockaddr*)&locaddr, 1, SCTP_BINDX_ADD_ADDR) < 0) {
SCTP_ERROR("sctp_bindx SCTP_BINDX_ADD_ADDR failed: %s\n",
strerror(errno));
} else {
SCTP_DEBUG("sctp_bindx SCTP_BINDX_ADD_ADDR socket bound to : %s\n",
inet_ntoa(locaddr.sin_addr));
}
break;
}
}
} else if (sctp_new_association_req_p->local_address.ipv6 && family == AF_INET6) {
// compare address
s = inet_pton(AF_INET6,
sctp_new_association_req_p->local_address.ipv6_address,
&in6);
if (s == 1 ) {
if (memcmp(&((struct sockaddr_in6*)ifa->ifa_addr)->sin6_addr,
&in6, sizeof(in6)) == 0) {
memset(&ifr, 0, sizeof(ifr));
snprintf(ifr.ifr_name, sizeof(ifr.ifr_name), "%s", ifa->ifa_name);
if (setsockopt(sd, SOL_SOCKET, SO_BINDTODEVICE, (void *)&ifr, sizeof(ifr)) < 0) {
SCTP_ERROR("Setsockopt SOL_SOCKET failed: %s\n",
strerror(errno));
} else {
SCTP_DEBUG("Setsockopt SOL_SOCKET socket bound to : %s\n",
ifa->ifa_name);
}
break;
}
}
}
} }
/* Connect to remote host and port */ freeifaddrs(ifaddr);
if (sctp_connectx(sd, (struct sockaddr *)addr, 1, &assoc_id) < 0) {
/* sctp_connectx on non-blocking socket return EINPROGRESS */ /* Mark the socket as non-blocking */
if (errno != EINPROGRESS) { if (fcntl(sd, F_SETFL, O_NONBLOCK) < 0) {
SCTP_ERROR("Connect failed: %s\n", strerror(errno)); SCTP_ERROR("fcntl F_SETFL O_NONBLOCK failed: %s\n",
sctp_itti_send_association_resp( strerror(errno));
requestor, instance, -1, sctp_new_association_req_p->ulp_cnx_id,
SCTP_STATE_UNREACHABLE, 0, 0);
/* Add the socket to list of fd monitored by ITTI */
itti_unsubscribe_event_fd(TASK_SCTP, sd);
close(sd); close(sd);
return; return;
} else {
SCTP_DEBUG("connectx assoc_id %d in progress..., used %d addresses\n",
assoc_id, used_address);
}
} else {
SCTP_DEBUG("sctp_connectx SUCCESS, used %d addresses assoc_id %d\n",
used_address,
assoc_id);
} }
} else {
/* No remote address provided -> only bind the socket for now. /* SOCK_STREAM socket type requires an explicit connect to the remote host
* Connection will be accepted in the main event loop * address and port.
* Only use IPv4 for the first connection attempt
*/ */
struct sockaddr_in6 addr6; if ((sctp_new_association_req_p->remote_address.ipv6 != 0) ||
(sctp_new_association_req_p->remote_address.ipv4 != 0)) {
uint8_t address_index = 0;
uint8_t used_address = sctp_new_association_req_p->remote_address.ipv6 +
sctp_new_association_req_p->remote_address.ipv4;
struct sockaddr_in addr[used_address];
memset(addr, 0, used_address * sizeof(struct sockaddr_in));
if (sctp_new_association_req_p->remote_address.ipv6 == 1) {
if (inet_pton(AF_INET6, sctp_new_association_req_p->remote_address.ipv6_address,
&addr[address_index].sin_addr.s_addr) != 1) {
SCTP_ERROR("Failed to convert ipv6 address %*s to network type\n",
(int)strlen(sctp_new_association_req_p->remote_address.ipv6_address),
sctp_new_association_req_p->remote_address.ipv6_address);
close(sd);
return;
}
SCTP_DEBUG("Converted ipv6 address %*s to network type\n",
(int)strlen(sctp_new_association_req_p->remote_address.ipv6_address),
sctp_new_association_req_p->remote_address.ipv6_address);
addr[address_index].sin_family = AF_INET6;
addr[address_index].sin_port = htons(sctp_new_association_req_p->port);
address_index++;
}
connection_type = SCTP_TYPE_SERVER; if (sctp_new_association_req_p->remote_address.ipv4 == 1) {
if (inet_pton(AF_INET, sctp_new_association_req_p->remote_address.ipv4_address,
&addr[address_index].sin_addr.s_addr) != 1) {
SCTP_ERROR("Failed to convert ipv4 address %*s to network type\n",
(int)strlen(sctp_new_association_req_p->remote_address.ipv4_address),
sctp_new_association_req_p->remote_address.ipv4_address);
close(sd);
return;
}
SCTP_DEBUG("Converted ipv4 address %*s to network type\n",
(int)strlen(sctp_new_association_req_p->remote_address.ipv4_address),
sctp_new_association_req_p->remote_address.ipv4_address);
addr[address_index].sin_family = AF_INET;
addr[address_index].sin_port = htons(sctp_new_association_req_p->port);
address_index++;
}
/* For now bind to any interface */ /* Connect to remote host and port */
addr6.sin6_family = AF_INET6; if (sctp_connectx(sd, (struct sockaddr *)addr, 1, &assoc_id) < 0) {
addr6.sin6_addr = in6addr_any; /* sctp_connectx on non-blocking socket return EINPROGRESS */
addr6.sin6_port = htons(sctp_new_association_req_p->port); if (errno != EINPROGRESS) {
SCTP_ERROR("Connect failed: %s\n", strerror(errno));
sctp_itti_send_association_resp(
requestor, instance, -1, sctp_new_association_req_p->ulp_cnx_id,
SCTP_STATE_UNREACHABLE, 0, 0);
/* Add the socket to list of fd monitored by ITTI */
itti_unsubscribe_event_fd(TASK_SCTP, sd);
close(sd);
return;
} else {
SCTP_DEBUG("connectx assoc_id %d in progress..., used %d addresses\n",
assoc_id, used_address);
}
} else {
SCTP_DEBUG("sctp_connectx SUCCESS, used %d addresses assoc_id %d\n",
used_address,
assoc_id);
}
} else {
/* No remote address provided -> only bind the socket for now.
* Connection will be accepted in the main event loop
*/
struct sockaddr_in6 addr6;
if (bind(sd, (struct sockaddr*)&addr6, sizeof(addr6)) < 0) { connection_type = SCTP_TYPE_SERVER;
SCTP_ERROR("Failed to bind the socket to address any (v4/v6): %s\n",
strerror(errno)); /* For now bind to any interface */
close(sd); addr6.sin6_family = AF_INET6;
return; addr6.sin6_addr = in6addr_any;
addr6.sin6_port = htons(sctp_new_association_req_p->port);
if (bind(sd, (struct sockaddr*)&addr6, sizeof(addr6)) < 0) {
SCTP_ERROR("Failed to bind the socket to address any (v4/v6): %s\n",
strerror(errno));
close(sd);
return;
}
} }
}
sctp_cnx = calloc(1, sizeof(*sctp_cnx)); sctp_cnx = calloc(1, sizeof(*sctp_cnx));
sctp_cnx->connection_type = connection_type; sctp_cnx->connection_type = connection_type;
sctp_cnx->sd = sd; sctp_cnx->sd = sd;
sctp_cnx->task_id = requestor; sctp_cnx->task_id = requestor;
sctp_cnx->cnx_id = sctp_new_association_req_p->ulp_cnx_id; sctp_cnx->cnx_id = sctp_new_association_req_p->ulp_cnx_id;
sctp_cnx->ppid = sctp_new_association_req_p->ppid; sctp_cnx->ppid = sctp_new_association_req_p->ppid;
sctp_cnx->instance = instance; sctp_cnx->instance = instance;
sctp_cnx->assoc_id = assoc_id; sctp_cnx->assoc_id = assoc_id;
/* Insert new element at end of list */ /* Insert new element at end of list */
STAILQ_INSERT_TAIL(&sctp_cnx_list, sctp_cnx, entries); STAILQ_INSERT_TAIL(&sctp_cnx_list, sctp_cnx, entries);
sctp_nb_cnx++; sctp_nb_cnx++;
SCTP_DEBUG("Inserted new descriptor for sd %d in list, nb elements %u, assoc_id %d\n", SCTP_DEBUG("Inserted new descriptor for sd %d in list, nb elements %u, assoc_id %d\n",
sd, sctp_nb_cnx, assoc_id); sd, sctp_nb_cnx, assoc_id);
} }
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
void sctp_send_data( void sctp_send_data(
instance_t instance, instance_t instance,
task_id_t task_id, task_id_t task_id,
sctp_data_req_t *sctp_data_req_p) sctp_data_req_t *sctp_data_req_p)
{ {
struct sctp_cnx_list_elm_s *sctp_cnx = NULL; struct sctp_cnx_list_elm_s *sctp_cnx = NULL;
DevAssert(sctp_data_req_p != NULL); DevAssert(sctp_data_req_p != NULL);
DevAssert(sctp_data_req_p->buffer != NULL); DevAssert(sctp_data_req_p->buffer != NULL);
DevAssert(sctp_data_req_p->buffer_length > 0); DevAssert(sctp_data_req_p->buffer_length > 0);
sctp_cnx = sctp_get_cnx(sctp_data_req_p->assoc_id, 0); sctp_cnx = sctp_get_cnx(sctp_data_req_p->assoc_id, 0);
if (sctp_cnx == NULL) { if (sctp_cnx == NULL) {
SCTP_ERROR("Failed to find SCTP description for assoc_id %d\n", SCTP_ERROR("Failed to find SCTP description for assoc_id %d\n",
sctp_data_req_p->assoc_id); sctp_data_req_p->assoc_id);
/* TODO: notify upper layer */ /* TODO: notify upper layer */
return; return;
} }
if (sctp_data_req_p->stream >= sctp_cnx->out_streams) { if (sctp_data_req_p->stream >= sctp_cnx->out_streams) {
SCTP_ERROR("Requested stream (%"PRIu16") >= nb out streams (%"PRIu16")\n", SCTP_ERROR("Requested stream (%"PRIu16") >= nb out streams (%"PRIu16")\n",
sctp_data_req_p->stream, sctp_cnx->out_streams); sctp_data_req_p->stream, sctp_cnx->out_streams);
return; return;
} }
/* Send message on specified stream of the sd association /* Send message on specified stream of the sd association
* NOTE: PPID should be defined in network order * NOTE: PPID should be defined in network order
*/ */
if (sctp_sendmsg(sctp_cnx->sd, sctp_data_req_p->buffer, if (sctp_sendmsg(sctp_cnx->sd, sctp_data_req_p->buffer,
sctp_data_req_p->buffer_length, NULL, 0, sctp_data_req_p->buffer_length, NULL, 0,
htonl(sctp_cnx->ppid), 0, sctp_data_req_p->stream, 0, 0) < 0) { htonl(sctp_cnx->ppid), 0, sctp_data_req_p->stream, 0, 0) < 0) {
SCTP_ERROR("Sctp_sendmsg failed: %s\n", strerror(errno)); SCTP_ERROR("Sctp_sendmsg failed: %s\n", strerror(errno));
/* TODO: notify upper layer */ /* TODO: notify upper layer */
return; return;
} }
SCTP_DEBUG("Successfully sent %u bytes on stream %d for assoc_id %u\n", SCTP_DEBUG("Successfully sent %u bytes on stream %d for assoc_id %u\n",
sctp_data_req_p->buffer_length, sctp_data_req_p->stream, sctp_data_req_p->buffer_length, sctp_data_req_p->stream,
sctp_cnx->assoc_id); sctp_cnx->assoc_id);
} }
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
static int sctp_close_association( static int sctp_close_association(
const instance_t instance, const instance_t instance,
const task_id_t requestor, const task_id_t requestor,
sctp_close_association_t *close_association_p) sctp_close_association_t *close_association_p)
{ {
struct sctp_cnx_list_elm_s *sctp_cnx = NULL; struct sctp_cnx_list_elm_s *sctp_cnx = NULL;
DevAssert(close_association_p != NULL); DevAssert(close_association_p != NULL);
sctp_cnx = sctp_get_cnx(close_association_p->assoc_id, 0); sctp_cnx = sctp_get_cnx(close_association_p->assoc_id, 0);
if (sctp_cnx == NULL) { if (sctp_cnx == NULL) {
SCTP_ERROR("Failed to find SCTP description for assoc_id %d\n", SCTP_ERROR("Failed to find SCTP description for assoc_id %d\n",
close_association_p->assoc_id); close_association_p->assoc_id);
/* TODO: notify upper layer */ /* TODO: notify upper layer */
return -1; return -1;
} else { } else {
close(sctp_cnx->sd); close(sctp_cnx->sd);
STAILQ_REMOVE(&sctp_cnx_list, sctp_cnx, sctp_cnx_list_elm_s, entries); STAILQ_REMOVE(&sctp_cnx_list, sctp_cnx, sctp_cnx_list_elm_s, entries);
SCTP_DEBUG("Removed assoc_id %u (closed socket %u)\n", SCTP_DEBUG("Removed assoc_id %u (closed socket %u)\n",
sctp_cnx->assoc_id, sctp_cnx->sd); sctp_cnx->assoc_id, (unsigned int)sctp_cnx->sd);
} }
return 0; return 0;
} }
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
static int sctp_create_new_listener( static int sctp_create_new_listener(
const instance_t instance, const instance_t instance,
const task_id_t requestor, const task_id_t requestor,
sctp_init_t *init_p, sctp_init_t *init_p,
int server_type) int server_type)
{ {
struct sctp_event_subscribe event; struct sctp_event_subscribe event;
struct sockaddr *addr = NULL; struct sockaddr *addr = NULL;
struct sctp_cnx_list_elm_s *sctp_cnx = NULL; struct sctp_cnx_list_elm_s *sctp_cnx = NULL;
uint16_t i = 0, j = 0; uint16_t i = 0, j = 0;
int sd = 0; int sd = 0;
int used_addresses = 0; int used_addresses = 0;
DevAssert(init_p != NULL); DevAssert(init_p != NULL);
if (init_p->ipv4 == 0 && init_p->ipv6 == 0) { if (init_p->ipv4 == 0 && init_p->ipv6 == 0) {
SCTP_ERROR("Illegal IP configuration upper layer should request at" SCTP_ERROR("Illegal IP configuration upper layer should request at"
"least ipv4 and/or ipv6 config\n"); "least ipv4 and/or ipv6 config\n");
return -1; return -1;
} }
if ((used_addresses = init_p->nb_ipv4_addr + init_p->nb_ipv6_addr) == 0) { if ((used_addresses = init_p->nb_ipv4_addr + init_p->nb_ipv6_addr) == 0) {
SCTP_WARN("No address provided...\n"); SCTP_WARN("No address provided...\n");
return -1; return -1;
} }
addr = calloc(used_addresses, sizeof(struct sockaddr)); addr = calloc(used_addresses, sizeof(struct sockaddr));
SCTP_DEBUG("Creating new listen socket on port %u with\n", init_p->port); SCTP_DEBUG("Creating new listen socket on port %u with\n", init_p->port);
if (init_p->ipv4 == 1) { if (init_p->ipv4 == 1) {
struct sockaddr_in *ip4_addr; struct sockaddr_in *ip4_addr;
SCTP_DEBUG("ipv4 addresses:\n"); SCTP_DEBUG("ipv4 addresses:\n");
for (i = 0; i < init_p->nb_ipv4_addr; i++) { for (i = 0; i < init_p->nb_ipv4_addr; i++) {
SCTP_DEBUG("\t- "IPV4_ADDR"\n", SCTP_DEBUG("\t- "IPV4_ADDR"\n",
IPV4_ADDR_FORMAT(init_p->ipv4_address[i])); IPV4_ADDR_FORMAT(init_p->ipv4_address[i]));
ip4_addr = (struct sockaddr_in *)&addr[i]; ip4_addr = (struct sockaddr_in *)&addr[i];
ip4_addr->sin_family = AF_INET; ip4_addr->sin_family = AF_INET;
ip4_addr->sin_port = htons(init_p->port); ip4_addr->sin_port = htons(init_p->port);
ip4_addr->sin_addr.s_addr = init_p->ipv4_address[i]; ip4_addr->sin_addr.s_addr = init_p->ipv4_address[i];
}
} }
}
if (init_p->ipv6 == 1) { if (init_p->ipv6 == 1) {
struct sockaddr_in6 *ip6_addr; struct sockaddr_in6 *ip6_addr;
SCTP_DEBUG("ipv6 addresses:\n"); SCTP_DEBUG("ipv6 addresses:\n");
for (j = 0; j < init_p->nb_ipv6_addr; j++) { for (j = 0; j < init_p->nb_ipv6_addr; j++) {
SCTP_DEBUG("\t- %s\n", init_p->ipv6_address[j]); SCTP_DEBUG("\t- %s\n", init_p->ipv6_address[j]);
ip6_addr = (struct sockaddr_in6 *)&addr[i + j]; ip6_addr = (struct sockaddr_in6 *)&addr[i + j];
ip6_addr->sin6_family = AF_INET6; ip6_addr->sin6_family = AF_INET6;
ip6_addr->sin6_port = htons(init_p->port); ip6_addr->sin6_port = htons(init_p->port);
if (inet_pton(AF_INET6, init_p->ipv6_address[j], if (inet_pton(AF_INET6, init_p->ipv6_address[j],
ip6_addr->sin6_addr.s6_addr) <= 0) { ip6_addr->sin6_addr.s6_addr) <= 0) {
SCTP_WARN("Provided ipv6 address %s is not valid\n", SCTP_WARN("Provided ipv6 address %s is not valid\n",
init_p->ipv6_address[j]); init_p->ipv6_address[j]);
} }
}
} }
}
if (server_type) { if (server_type) {
if ((sd = socket(PF_INET, SOCK_SEQPACKET, IPPROTO_SCTP)) < 0) { if ((sd = socket(PF_INET, SOCK_SEQPACKET, IPPROTO_SCTP)) < 0) {
SCTP_ERROR("socket: %s:%d\n", strerror(errno), errno); SCTP_ERROR("socket: %s:%d\n", strerror(errno), errno);
return -1; free(addr);
return -1;
}
} }
} else {
else { if ((sd = socket(AF_INET6, SOCK_STREAM, IPPROTO_SCTP)) < 0) {
if ((sd = socket(AF_INET6, SOCK_STREAM, IPPROTO_SCTP)) < 0) { SCTP_ERROR("socket: %s:%d\n", strerror(errno), errno);
SCTP_ERROR("socket: %s:%d\n", strerror(errno), errno); free(addr);
return -1; return -1;
}
} }
}
memset((void *)&event, 1, sizeof(struct sctp_event_subscribe)); memset((void *)&event, 1, sizeof(struct sctp_event_subscribe));
if (setsockopt(sd, IPPROTO_SCTP, SCTP_EVENTS, &event, if (setsockopt(sd, IPPROTO_SCTP, SCTP_EVENTS, &event,
sizeof(struct sctp_event_subscribe)) < 0) { sizeof(struct sctp_event_subscribe)) < 0) {
SCTP_ERROR("setsockopt: %s:%d\n", strerror(errno), errno); SCTP_ERROR("setsockopt: %s:%d\n", strerror(errno), errno);
return -1; free(addr);
} return -1;
}
sctp_cnx = calloc(1, sizeof(*sctp_cnx));
if (server_type) {
sctp_cnx->connection_type = SCTP_TYPE_MULTI_SERVER;
}
else {
sctp_cnx->connection_type = SCTP_TYPE_SERVER;
}
sctp_cnx->sd = sd;
sctp_cnx->local_port = init_p->port;
sctp_cnx->in_streams = 32;
sctp_cnx->out_streams = 32;
sctp_cnx->ppid = init_p->ppid;
sctp_cnx->task_id = requestor;
sctp_cnx->instance = instance;
/* Some pre-bind socket configuration */
if (sctp_set_init_opt(sd,
sctp_cnx->in_streams,
sctp_cnx->out_streams,
0,
0) < 0) {
goto err;
}
if (sctp_bindx(sd, addr, used_addresses, SCTP_BINDX_ADD_ADDR) != 0) {
SCTP_ERROR("sctp_bindx: %s:%d\n", strerror(errno), errno);
return -1;
}
if (listen(sd, 5) < 0) { sctp_cnx = calloc(1, sizeof(*sctp_cnx));
SCTP_ERROR("listen: %s:%d\n", strerror(errno), errno);
return -1;
}
/* Insert new element at end of list */ if (server_type) {
STAILQ_INSERT_TAIL(&sctp_cnx_list, sctp_cnx, entries); sctp_cnx->connection_type = SCTP_TYPE_MULTI_SERVER;
sctp_nb_cnx++; }
else {
sctp_cnx->connection_type = SCTP_TYPE_SERVER;
}
sctp_cnx->sd = sd;
sctp_cnx->local_port = init_p->port;
sctp_cnx->in_streams = 32;
sctp_cnx->out_streams = 32;
sctp_cnx->ppid = init_p->ppid;
sctp_cnx->task_id = requestor;
sctp_cnx->instance = instance;
/* Some pre-bind socket configuration */
if (sctp_set_init_opt(sd,
sctp_cnx->in_streams,
sctp_cnx->out_streams,
0,
0) < 0) {
goto err;
}
/* Add the socket to list of fd monitored by ITTI */ if (sctp_bindx(sd, addr, used_addresses, SCTP_BINDX_ADD_ADDR) != 0) {
itti_subscribe_event_fd(TASK_SCTP, sd); SCTP_ERROR("sctp_bindx: %s:%d\n", strerror(errno), errno);
return -1;
}
if (listen(sd, 5) < 0) {
SCTP_ERROR("listen: %s:%d\n", strerror(errno), errno);
return -1;
}
/* Insert new element at end of list */
STAILQ_INSERT_TAIL(&sctp_cnx_list, sctp_cnx, entries);
sctp_nb_cnx++;
/* Add the socket to list of fd monitored by ITTI */
itti_subscribe_event_fd(TASK_SCTP, sd);
return sd; return sd;
err: err:
if (sd != -1) { if (sd != -1) {
close(sd); close(sd);
sd = -1; sd = -1;
} }
return -1; return -1;
} }
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
static inline static inline
void void
sctp_eNB_accept_associations( sctp_eNB_accept_associations(
struct sctp_cnx_list_elm_s *sctp_cnx) struct sctp_cnx_list_elm_s *sctp_cnx)
{ {
int client_sd; int client_sd;
struct sockaddr saddr; struct sockaddr saddr;
socklen_t saddr_size; socklen_t saddr_size;
DevAssert(sctp_cnx != NULL);
saddr_size = sizeof(saddr);
/* There is a new client connecting. Accept it...
*/
if ((client_sd = accept(sctp_cnx->sd, &saddr, &saddr_size)) < 0) {
SCTP_ERROR("[%d] accept failed: %s:%d\n", sctp_cnx->sd, strerror(errno), errno);
} else {
struct sctp_cnx_list_elm_s *new_cnx;
uint16_t port;
/* This is an ipv6 socket */
port = ((struct sockaddr_in6*)&saddr)->sin6_port;
/* Contrary to BSD, client socket does not inherit O_NONBLOCK option */
if (fcntl(client_sd, F_SETFL, O_NONBLOCK) < 0) {
SCTP_ERROR("fcntl F_SETFL O_NONBLOCK failed: %s\n",
strerror(errno));
close(client_sd);
return;
}
new_cnx = calloc(1, sizeof(*sctp_cnx)); DevAssert(sctp_cnx != NULL);
DevAssert(new_cnx != NULL); saddr_size = sizeof(saddr);
new_cnx->connection_type = SCTP_TYPE_CLIENT; /* There is a new client connecting. Accept it...
*/
if ((client_sd = accept(sctp_cnx->sd, &saddr, &saddr_size)) < 0) {
SCTP_ERROR("[%d] accept failed: %s:%d\n", sctp_cnx->sd, strerror(errno), errno);
} else {
struct sctp_cnx_list_elm_s *new_cnx;
uint16_t port;
new_cnx->sd = client_sd; /* This is an ipv6 socket */
new_cnx->task_id = sctp_cnx->task_id; port = ((struct sockaddr_in6*)&saddr)->sin6_port;
new_cnx->cnx_id = 0;
new_cnx->ppid = sctp_cnx->ppid;
new_cnx->instance = sctp_cnx->instance;
new_cnx->local_port = sctp_cnx->local_port;
if (sctp_get_sockinfo(client_sd, &new_cnx->in_streams, &new_cnx->out_streams, /* Contrary to BSD, client socket does not inherit O_NONBLOCK option */
&new_cnx->assoc_id) != 0) { if (fcntl(client_sd, F_SETFL, O_NONBLOCK) < 0) {
SCTP_ERROR("sctp_get_sockinfo failed\n"); SCTP_ERROR("fcntl F_SETFL O_NONBLOCK failed: %s\n",
close(client_sd); strerror(errno));
free(new_cnx); close(client_sd);
return; return;
} }
/* Insert new element at end of list */ new_cnx = calloc(1, sizeof(*sctp_cnx));
STAILQ_INSERT_TAIL(&sctp_cnx_list, new_cnx, entries);
sctp_nb_cnx++;
/* Add the socket to list of fd monitored by ITTI */ DevAssert(new_cnx != NULL);
itti_subscribe_event_fd(TASK_SCTP, client_sd);
new_cnx->connection_type = SCTP_TYPE_CLIENT;
new_cnx->sd = client_sd;
new_cnx->task_id = sctp_cnx->task_id;
new_cnx->cnx_id = 0;
new_cnx->ppid = sctp_cnx->ppid;
new_cnx->instance = sctp_cnx->instance;
new_cnx->local_port = sctp_cnx->local_port;
if (sctp_get_sockinfo(client_sd, &new_cnx->in_streams, &new_cnx->out_streams,
&new_cnx->assoc_id) != 0) {
SCTP_ERROR("sctp_get_sockinfo failed\n");
close(client_sd);
free(new_cnx);
return;
}
/* Insert new element at end of list */
STAILQ_INSERT_TAIL(&sctp_cnx_list, new_cnx, entries);
sctp_nb_cnx++;
/* Add the socket to list of fd monitored by ITTI */
itti_subscribe_event_fd(TASK_SCTP, client_sd);
sctp_itti_send_association_ind(new_cnx->task_id, new_cnx->instance, sctp_itti_send_association_ind(new_cnx->task_id, new_cnx->instance,
new_cnx->assoc_id, port, new_cnx->assoc_id, port,
new_cnx->out_streams, new_cnx->in_streams); new_cnx->out_streams, new_cnx->in_streams);
} }
} }
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
static inline static inline
void void
sctp_eNB_read_from_socket( sctp_eNB_read_from_socket(
struct sctp_cnx_list_elm_s *sctp_cnx) struct sctp_cnx_list_elm_s *sctp_cnx)
{ {
int flags = 0, n; int flags = 0, n;
socklen_t from_len; socklen_t from_len;
struct sctp_sndrcvinfo sinfo; struct sctp_sndrcvinfo sinfo;
struct sockaddr_in addr; struct sockaddr_in addr;
uint8_t buffer[SCTP_RECV_BUFFER_SIZE]; uint8_t buffer[SCTP_RECV_BUFFER_SIZE];
DevAssert(sctp_cnx != NULL); DevAssert(sctp_cnx != NULL);
memset((void *)&addr, 0, sizeof(struct sockaddr_in)); memset((void *)&addr, 0, sizeof(struct sockaddr_in));
from_len = (socklen_t)sizeof(struct sockaddr_in); from_len = (socklen_t)sizeof(struct sockaddr_in);
memset((void *)&sinfo, 0, sizeof(struct sctp_sndrcvinfo)); memset((void *)&sinfo, 0, sizeof(struct sctp_sndrcvinfo));
n = sctp_recvmsg(sctp_cnx->sd, (void *)buffer, SCTP_RECV_BUFFER_SIZE, n = sctp_recvmsg(sctp_cnx->sd, (void *)buffer, SCTP_RECV_BUFFER_SIZE,
(struct sockaddr *)&addr, &from_len, (struct sockaddr *)&addr, &from_len,
&sinfo, &flags); &sinfo, &flags);
if (n < 0) { if (n < 0) {
if (errno == ENOTCONN) { if (errno == ENOTCONN) {
itti_unsubscribe_event_fd(TASK_SCTP, sctp_cnx->sd); itti_unsubscribe_event_fd(TASK_SCTP, sctp_cnx->sd);
SCTP_DEBUG("Received not connected for sd %d\n", sctp_cnx->sd); SCTP_DEBUG("Received not connected for sd %d\n", sctp_cnx->sd);
sctp_itti_send_association_resp( sctp_itti_send_association_resp(
sctp_cnx->task_id, sctp_cnx->instance, -1, sctp_cnx->task_id, sctp_cnx->instance, -1,
sctp_cnx->cnx_id, SCTP_STATE_UNREACHABLE, 0, 0); sctp_cnx->cnx_id, SCTP_STATE_UNREACHABLE, 0, 0);
close(sctp_cnx->sd); close(sctp_cnx->sd);
STAILQ_REMOVE(&sctp_cnx_list, sctp_cnx, sctp_cnx_list_elm_s, entries); STAILQ_REMOVE(&sctp_cnx_list, sctp_cnx, sctp_cnx_list_elm_s, entries);
sctp_nb_cnx--; sctp_nb_cnx--;
free(sctp_cnx); free(sctp_cnx);
} else { } else {
SCTP_DEBUG("An error occured during read\n"); SCTP_DEBUG("An error occured during read\n");
SCTP_ERROR("sctp_recvmsg (fd %d, len %d ): %s:%d\n", sctp_cnx->sd, n, strerror(errno), errno); SCTP_ERROR("sctp_recvmsg (fd %d, len %d ): %s:%d\n", sctp_cnx->sd, n, strerror(errno), errno);
} }
return; return;
} else if (n == 0) { } else if (n == 0) {
SCTP_DEBUG("return of sctp_recvmsg is 0...\n"); SCTP_DEBUG("return of sctp_recvmsg is 0...\n");
return; return;
} }
if (flags & MSG_NOTIFICATION) { if (flags & MSG_NOTIFICATION) {
union sctp_notification *snp; union sctp_notification *snp;
snp = (union sctp_notification *)buffer; snp = (union sctp_notification *)buffer;
SCTP_DEBUG("Received notification for sd %d, type %u\n", SCTP_DEBUG("Received notification for sd %d, type %u\n",
sctp_cnx->sd, snp->sn_header.sn_type); sctp_cnx->sd, snp->sn_header.sn_type);
/* Client deconnection */ /* Client deconnection */
if (SCTP_SHUTDOWN_EVENT == snp->sn_header.sn_type) { if (SCTP_SHUTDOWN_EVENT == snp->sn_header.sn_type) {
itti_unsubscribe_event_fd(TASK_SCTP, sctp_cnx->sd); itti_unsubscribe_event_fd(TASK_SCTP, sctp_cnx->sd);
close(sctp_cnx->sd); close(sctp_cnx->sd);
sctp_itti_send_association_resp( sctp_itti_send_association_resp(
sctp_cnx->task_id, sctp_cnx->instance, sctp_cnx->assoc_id, sctp_cnx->task_id, sctp_cnx->instance, sctp_cnx->assoc_id,
sctp_cnx->cnx_id, SCTP_STATE_SHUTDOWN, sctp_cnx->cnx_id, SCTP_STATE_SHUTDOWN,
0, 0); 0, 0);
STAILQ_REMOVE(&sctp_cnx_list, sctp_cnx, sctp_cnx_list_elm_s, entries); STAILQ_REMOVE(&sctp_cnx_list, sctp_cnx, sctp_cnx_list_elm_s, entries);
sctp_nb_cnx--; sctp_nb_cnx--;
free(sctp_cnx); free(sctp_cnx);
} }
/* Association has changed. */ /* Association has changed. */
else if (SCTP_ASSOC_CHANGE == snp->sn_header.sn_type) { else if (SCTP_ASSOC_CHANGE == snp->sn_header.sn_type) {
struct sctp_assoc_change *sctp_assoc_changed; struct sctp_assoc_change *sctp_assoc_changed;
sctp_assoc_changed = &snp->sn_assoc_change; sctp_assoc_changed = &snp->sn_assoc_change;
SCTP_DEBUG("Client association changed: %d\n", sctp_assoc_changed->sac_state); SCTP_DEBUG("Client association changed: %d\n", sctp_assoc_changed->sac_state);
/* New physical association requested by a peer */ /* New physical association requested by a peer */
switch (sctp_assoc_changed->sac_state) { switch (sctp_assoc_changed->sac_state) {
case SCTP_COMM_UP: { case SCTP_COMM_UP: {
if (sctp_get_peeraddresses(sctp_cnx->sd, NULL, NULL) != 0) { if (sctp_get_peeraddresses(sctp_cnx->sd, NULL, NULL) != 0) {
/* TODO Failure -> notify upper layer */ /* TODO Failure -> notify upper layer */
} else { } else {
sctp_get_sockinfo(sctp_cnx->sd, &sctp_cnx->in_streams, sctp_get_sockinfo(sctp_cnx->sd, &sctp_cnx->in_streams,
&sctp_cnx->out_streams, &sctp_cnx->assoc_id); &sctp_cnx->out_streams, &sctp_cnx->assoc_id);
}
SCTP_DEBUG("Comm up notified for sd %d, assigned assoc_id %d\n",
sctp_cnx->sd, sctp_cnx->assoc_id);
sctp_itti_send_association_resp(
sctp_cnx->task_id, sctp_cnx->instance, sctp_cnx->assoc_id,
sctp_cnx->cnx_id, SCTP_STATE_ESTABLISHED,
sctp_cnx->out_streams, sctp_cnx->in_streams);
}
break;
default:
SCTP_WARN("unhandled: SCTP_ASSOC_CHANGE to %d\n", sctp_assoc_changed->sac_state);
break;
}
}
} else {
sctp_cnx->messages_recv++;
if (ntohl(sinfo.sinfo_ppid) != sctp_cnx->ppid) {
/* Mismatch in Payload Protocol Identifier,
* may be we received unsollicited traffic from stack other than S1AP.
*/
SCTP_ERROR("Received data from peer with unsollicited PPID %d, expecting %d\n",
ntohl(sinfo.sinfo_ppid),
sctp_cnx->ppid);
} }
SCTP_DEBUG("Comm up notified for sd %d, assigned assoc_id %d\n", SCTP_DEBUG("[%d][%d] Msg of length %d received from port %u, on stream %d, PPID %d\n",
sctp_cnx->sd, sctp_cnx->assoc_id); sinfo.sinfo_assoc_id, sctp_cnx->sd, n, ntohs(addr.sin_port),
sinfo.sinfo_stream, ntohl(sinfo.sinfo_ppid));
sctp_itti_send_association_resp(
sctp_cnx->task_id, sctp_cnx->instance, sctp_cnx->assoc_id,
sctp_cnx->cnx_id, SCTP_STATE_ESTABLISHED,
sctp_cnx->out_streams, sctp_cnx->in_streams);
}
break;
default: sctp_itti_send_new_message_ind(sctp_cnx->task_id,
SCTP_WARN("unhandled: SCTP_ASSOC_CHANGE to %d\n", sctp_assoc_changed->sac_state); sinfo.sinfo_assoc_id,
break; buffer, n, sinfo.sinfo_stream);
}
}
} else {
sctp_cnx->messages_recv++;
if (ntohl(sinfo.sinfo_ppid) != sctp_cnx->ppid) {
/* Mismatch in Payload Protocol Identifier,
* may be we received unsollicited traffic from stack other than S1AP.
*/
SCTP_ERROR("Received data from peer with unsollicited PPID %d, expecting %d\n",
ntohl(sinfo.sinfo_ppid),
sctp_cnx->ppid);
} }
SCTP_DEBUG("[%d][%d] Msg of length %d received from port %u, on stream %d, PPID %d\n",
sinfo.sinfo_assoc_id, sctp_cnx->sd, n, ntohs(addr.sin_port),
sinfo.sinfo_stream, ntohl(sinfo.sinfo_ppid));
sctp_itti_send_new_message_ind(sctp_cnx->task_id,
sinfo.sinfo_assoc_id,
buffer, n, sinfo.sinfo_stream);
}
} }
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
void void
sctp_eNB_flush_sockets( sctp_eNB_flush_sockets(
struct epoll_event *events, int nb_events) struct epoll_event *events, int nb_events)
{ {
int i; int i;
struct sctp_cnx_list_elm_s *sctp_cnx = NULL; struct sctp_cnx_list_elm_s *sctp_cnx = NULL;
if (events == NULL) { if (events == NULL) {
return; return;
} }
for (i = 0; i < nb_events; i++) { for (i = 0; i < nb_events; i++) {
sctp_cnx = sctp_get_cnx(-1, events[i].data.fd); sctp_cnx = sctp_get_cnx(-1, events[i].data.fd);
if (sctp_cnx == NULL) { if (sctp_cnx == NULL) {
continue; continue;
} }
SCTP_DEBUG("Found data for descriptor %d\n", events[i].data.fd); SCTP_DEBUG("Found data for descriptor %d\n", events[i].data.fd);
if (sctp_cnx->connection_type == SCTP_TYPE_CLIENT) { if (sctp_cnx->connection_type == SCTP_TYPE_CLIENT) {
sctp_eNB_read_from_socket(sctp_cnx); sctp_eNB_read_from_socket(sctp_cnx);
} }
else if (sctp_cnx->connection_type == SCTP_TYPE_MULTI_SERVER) { else if (sctp_cnx->connection_type == SCTP_TYPE_MULTI_SERVER) {
sctp_eNB_accept_associations_multi(sctp_cnx); sctp_eNB_accept_associations_multi(sctp_cnx);
} }
else { else {
sctp_eNB_accept_associations(sctp_cnx); sctp_eNB_accept_associations(sctp_cnx);
}
} }
}
} }
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
void sctp_eNB_init(void) void sctp_eNB_init(void)
{ {
SCTP_DEBUG("Starting SCTP layer\n"); SCTP_DEBUG("Starting SCTP layer\n");
STAILQ_INIT(&sctp_cnx_list); STAILQ_INIT(&sctp_cnx_list);
itti_mark_task_ready(TASK_SCTP); itti_mark_task_ready(TASK_SCTP);
MSC_START_USE(); MSC_START_USE();
} }
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
void *sctp_eNB_process_itti_msg(void *notUsed) void *sctp_eNB_process_itti_msg(void *notUsed)
{ {
...@@ -1058,88 +1061,88 @@ void *sctp_eNB_process_itti_msg(void *notUsed) ...@@ -1058,88 +1061,88 @@ void *sctp_eNB_process_itti_msg(void *notUsed)
struct epoll_event *events; struct epoll_event *events;
MessageDef *received_msg = NULL; MessageDef *received_msg = NULL;
int result; int result;
itti_receive_msg(TASK_SCTP, &received_msg); itti_receive_msg(TASK_SCTP, &received_msg);
/* Check if there is a packet to handle */ /* Check if there is a packet to handle */
if (received_msg != NULL) { if (received_msg != NULL) {
switch (ITTI_MSG_ID(received_msg)) { switch (ITTI_MSG_ID(received_msg)) {
case SCTP_INIT_MSG: { case SCTP_INIT_MSG: {
SCTP_DEBUG("Received SCTP_INIT_MSG\n"); SCTP_DEBUG("Received SCTP_INIT_MSG\n");
/* We received a new connection request */ /* We received a new connection request */
if (sctp_create_new_listener( if (sctp_create_new_listener(
ITTI_MESSAGE_GET_INSTANCE(received_msg), ITTI_MESSAGE_GET_INSTANCE(received_msg),
ITTI_MSG_ORIGIN_ID(received_msg), ITTI_MSG_ORIGIN_ID(received_msg),
&received_msg->ittiMsg.sctp_init,0) < 0) { &received_msg->ittiMsg.sctp_init,0) < 0) {
/* SCTP socket creation or bind failed... */ /* SCTP socket creation or bind failed... */
SCTP_ERROR("Failed to create new SCTP listener\n"); SCTP_ERROR("Failed to create new SCTP listener\n");
}
} }
} break;
break;
case SCTP_INIT_MSG_MULTI_REQ: {
case SCTP_INIT_MSG_MULTI_REQ: { int multi_sd;
int multi_sd;
SCTP_DEBUG("Received SCTP_INIT_MSG_MULTI_REQ\n");
SCTP_DEBUG("Received SCTP_INIT_MSG_MULTI_REQ\n");
multi_sd = sctp_create_new_listener(
multi_sd = sctp_create_new_listener( ITTI_MESSAGE_GET_INSTANCE(received_msg),
ITTI_MESSAGE_GET_INSTANCE(received_msg), ITTI_MSG_ORIGIN_ID(received_msg),
ITTI_MSG_ORIGIN_ID(received_msg), &received_msg->ittiMsg.sctp_init_multi,1);
&received_msg->ittiMsg.sctp_init_multi,1); /* We received a new connection request */
/* We received a new connection request */ if (multi_sd < 0) {
if (multi_sd < 0) { /* SCTP socket creation or bind failed... */
/* SCTP socket creation or bind failed... */ SCTP_ERROR("Failed to create new SCTP listener\n");
SCTP_ERROR("Failed to create new SCTP listener\n"); }
} sctp_itti_send_init_msg_multi_cnf(
sctp_itti_send_init_msg_multi_cnf(
ITTI_MSG_ORIGIN_ID(received_msg), ITTI_MSG_ORIGIN_ID(received_msg),
ITTI_MESSAGE_GET_INSTANCE(received_msg), ITTI_MESSAGE_GET_INSTANCE(received_msg),
multi_sd); multi_sd);
} }
break;
case SCTP_NEW_ASSOCIATION_REQ: {
sctp_handle_new_association_req(ITTI_MESSAGE_GET_INSTANCE(received_msg),
ITTI_MSG_ORIGIN_ID(received_msg),
&received_msg->ittiMsg.sctp_new_association_req);
}
break;
case SCTP_NEW_ASSOCIATION_REQ_MULTI: {
sctp_handle_new_association_req_multi(ITTI_MESSAGE_GET_INSTANCE(received_msg),
ITTI_MSG_ORIGIN_ID(received_msg),
&received_msg->ittiMsg.sctp_new_association_req_multi);
}
break;
case SCTP_CLOSE_ASSOCIATION:
sctp_close_association(ITTI_MESSAGE_GET_INSTANCE(received_msg),
ITTI_MSG_ORIGIN_ID(received_msg),
&received_msg->ittiMsg.sctp_close_association);
break; break;
case TERMINATE_MESSAGE: case SCTP_NEW_ASSOCIATION_REQ: {
SCTP_WARN("*** Exiting SCTP thread\n"); sctp_handle_new_association_req(ITTI_MESSAGE_GET_INSTANCE(received_msg),
itti_exit_task(); ITTI_MSG_ORIGIN_ID(received_msg),
&received_msg->ittiMsg.sctp_new_association_req);
}
break; break;
case SCTP_DATA_REQ: { case SCTP_NEW_ASSOCIATION_REQ_MULTI: {
sctp_send_data(ITTI_MESSAGE_GET_INSTANCE(received_msg), sctp_handle_new_association_req_multi(ITTI_MESSAGE_GET_INSTANCE(received_msg),
ITTI_MSG_ORIGIN_ID(received_msg), ITTI_MSG_ORIGIN_ID(received_msg),
&received_msg->ittiMsg.sctp_data_req); &received_msg->ittiMsg.sctp_new_association_req_multi);
} }
break; break;
default: case SCTP_CLOSE_ASSOCIATION:
SCTP_ERROR("Received unhandled message %d:%s\n", sctp_close_association(ITTI_MESSAGE_GET_INSTANCE(received_msg),
ITTI_MSG_ID(received_msg), ITTI_MSG_NAME(received_msg)); ITTI_MSG_ORIGIN_ID(received_msg),
&received_msg->ittiMsg.sctp_close_association);
break;
case TERMINATE_MESSAGE:
SCTP_WARN("*** Exiting SCTP thread\n");
itti_exit_task();
break;
case SCTP_DATA_REQ: {
sctp_send_data(ITTI_MESSAGE_GET_INSTANCE(received_msg),
ITTI_MSG_ORIGIN_ID(received_msg),
&received_msg->ittiMsg.sctp_data_req);
}
break; break;
}
result = itti_free(ITTI_MSG_ORIGIN_ID(received_msg), received_msg); default:
AssertFatal (result == EXIT_SUCCESS, "Failed to free memory (%d)!\n", result); SCTP_ERROR("Received unhandled message %d:%s\n",
received_msg = NULL; ITTI_MSG_ID(received_msg), ITTI_MSG_NAME(received_msg));
break;
}
result = itti_free(ITTI_MSG_ORIGIN_ID(received_msg), received_msg);
AssertFatal (result == EXIT_SUCCESS, "Failed to free memory (%d)!\n", result);
received_msg = NULL;
} }
nb_events = itti_get_events(TASK_SCTP, &events); nb_events = itti_get_events(TASK_SCTP, &events);
...@@ -1148,15 +1151,15 @@ void *sctp_eNB_process_itti_msg(void *notUsed) ...@@ -1148,15 +1151,15 @@ void *sctp_eNB_process_itti_msg(void *notUsed)
return NULL; return NULL;
} }
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
void *sctp_eNB_task(void *arg) void *sctp_eNB_task(void *arg)
{ {
sctp_eNB_init(); sctp_eNB_init();
while (1) { while (1) {
(void) sctp_eNB_process_itti_msg(NULL); (void) sctp_eNB_process_itti_msg(NULL);
} }
return NULL; return NULL;
} }
...@@ -35,18 +35,18 @@ ...@@ -35,18 +35,18 @@
* @{ * @{
*/ */
//! Number of BladeRF devices //! Number of BladeRF devices
#ifdef __SSE4_1__ #ifdef __SSE4_1__
# include <smmintrin.h> # include <smmintrin.h>
#endif #endif
#ifdef __AVX2__ #ifdef __AVX2__
# include <immintrin.h> # include <immintrin.h>
#endif #endif
int num_devices=0; int num_devices=0;
/*These items configure the underlying asynch stream used by the the sync interface. /*These items configure the underlying asynch stream used by the the sync interface.
*/ */
/*! \brief BladeRF Init function (not used at the moment) /*! \brief BladeRF Init function (not used at the moment)
...@@ -54,119 +54,119 @@ int num_devices=0; ...@@ -54,119 +54,119 @@ int num_devices=0;
* \returns 0 on success * \returns 0 on success
*/ */
int trx_brf_init(openair0_device *device) { int trx_brf_init(openair0_device *device) {
return 0; return 0;
} }
/*! \brief get current timestamp /*! \brief get current timestamp
*\param device the hardware to use *\param device the hardware to use
*\param module the bladeRf module *\param module the bladeRf module
*\returns timestamp of BladeRF *\returns timestamp of BladeRF
*/ */
openair0_timestamp trx_get_timestamp(openair0_device *device, bladerf_module module) { openair0_timestamp trx_get_timestamp(openair0_device *device, bladerf_module module) {
int status; int status;
struct bladerf_metadata meta; struct bladerf_metadata meta;
brf_state_t *brf = (brf_state_t*)device->priv; brf_state_t *brf = (brf_state_t*)device->priv;
memset(&meta, 0, sizeof(meta)); memset(&meta, 0, sizeof(meta));
if ((status=bladerf_get_timestamp(brf->dev, module, &meta.timestamp)) != 0) { if ((status=bladerf_get_timestamp(brf->dev, module, &meta.timestamp)) != 0) {
fprintf(stderr,"Failed to get current %s timestamp: %s\n",(module == BLADERF_MODULE_RX ) ? "RX" : "TX", bladerf_strerror(status)); fprintf(stderr,"Failed to get current %s timestamp: %s\n",(module == BLADERF_MODULE_RX ) ? "RX" : "TX", bladerf_strerror(status));
return -1; return -1;
} // else {printf("Current RX timestampe 0x%016"PRIx64"\n", meta.timestamp); } } // else {printf("Current RX timestampe 0x%016"PRIx64"\n", meta.timestamp); }
return meta.timestamp; return meta.timestamp;
} }
/*! \brief Start BladeRF /*! \brief Start BladeRF
* \param device the hardware to use * \param device the hardware to use
* \returns 0 on success * \returns 0 on success
*/ */
int trx_brf_start(openair0_device *device) { int trx_brf_start(openair0_device *device) {
brf_state_t *brf = (brf_state_t*)device->priv; brf_state_t *brf = (brf_state_t*)device->priv;
int status; int status;
brf->meta_tx.flags = 0; brf->meta_tx.flags = 0;
if ((status = bladerf_sync_config(brf->dev, if ((status = bladerf_sync_config(brf->dev,
BLADERF_MODULE_TX, BLADERF_MODULE_TX,
BLADERF_FORMAT_SC16_Q11_META, BLADERF_FORMAT_SC16_Q11_META,
brf->num_buffers, brf->num_buffers,
brf->buffer_size, brf->buffer_size,
brf->num_transfers, brf->num_transfers,
100/*brf->tx_timeout_ms*/)) != 0 ) { 100/*brf->tx_timeout_ms*/)) != 0 ) {
fprintf(stderr,"Failed to configure TX sync interface: %s\n", bladerf_strerror(status)); fprintf(stderr,"Failed to configure TX sync interface: %s\n", bladerf_strerror(status));
abort(); abort();
} }
if ((status = bladerf_sync_config(brf->dev, if ((status = bladerf_sync_config(brf->dev,
BLADERF_MODULE_RX, BLADERF_MODULE_RX,
BLADERF_FORMAT_SC16_Q11_META, BLADERF_FORMAT_SC16_Q11_META,
brf->num_buffers, brf->num_buffers,
brf->buffer_size, brf->buffer_size,
brf->num_transfers, brf->num_transfers,
100/*brf->rx_timeout_ms*/)) != 0 ) { 100/*brf->rx_timeout_ms*/)) != 0 ) {
fprintf(stderr,"Failed to configure RX sync interface: %s\n", bladerf_strerror(status)); fprintf(stderr,"Failed to configure RX sync interface: %s\n", bladerf_strerror(status));
abort(); abort();
} }
if ((status=bladerf_enable_module(brf->dev, BLADERF_MODULE_TX, true)) != 0) { if ((status=bladerf_enable_module(brf->dev, BLADERF_MODULE_TX, true)) != 0) {
fprintf(stderr,"Failed to enable TX module: %s\n", bladerf_strerror(status)); fprintf(stderr,"Failed to enable TX module: %s\n", bladerf_strerror(status));
abort(); abort();
} }
if ((status=bladerf_enable_module(brf->dev, BLADERF_MODULE_RX, true)) != 0) { if ((status=bladerf_enable_module(brf->dev, BLADERF_MODULE_RX, true)) != 0) {
fprintf(stderr,"Failed to enable RX module: %s\n", bladerf_strerror(status)); fprintf(stderr,"Failed to enable RX module: %s\n", bladerf_strerror(status));
abort(); abort();
} }
return 0; return 0;
} }
/*! \brief Called to send samples to the BladeRF RF target /*! \brief Called to send samples to the BladeRF RF target
\param device pointer to the device structure specific to the RF hardware target \param device pointer to the device structure specific to the RF hardware target
\param timestamp The timestamp at whicch the first sample MUST be sent \param timestamp The timestamp at whicch the first sample MUST be sent
\param buff Buffer which holds the samples \param buff Buffer which holds the samples
\param nsamps number of samples to be sent \param nsamps number of samples to be sent
\param cc index of the component carrier \param cc index of the component carrier
\param flags Ignored for the moment \param flags Ignored for the moment
\returns 0 on success \returns 0 on success
*/ */
static int trx_brf_write(openair0_device *device,openair0_timestamp ptimestamp, void **buff, int nsamps, int cc, int flags) { static int trx_brf_write(openair0_device *device,openair0_timestamp ptimestamp, void **buff, int nsamps, int cc, int flags) {
int status; int status;
brf_state_t *brf = (brf_state_t*)device->priv; brf_state_t *brf = (brf_state_t*)device->priv;
/* BRF has only 1 rx/tx chaine : is it correct? */ /* BRF has only 1 rx/tx chaine : is it correct? */
int16_t *samples = (int16_t*)buff[0]; int16_t *samples = (int16_t*)buff[0];
//memset(&brf->meta_tx, 0, sizeof(brf->meta_tx)); //memset(&brf->meta_tx, 0, sizeof(brf->meta_tx));
// When BLADERF_META_FLAG_TX_NOW is used the timestamp is not used, so one can't schedule a tx // When BLADERF_META_FLAG_TX_NOW is used the timestamp is not used, so one can't schedule a tx
if (brf->meta_tx.flags == 0 ) if (brf->meta_tx.flags == 0 )
brf->meta_tx.flags = (BLADERF_META_FLAG_TX_BURST_START);// | BLADERF_META_FLAG_TX_BURST_END);// | BLADERF_META_FLAG_TX_NOW); brf->meta_tx.flags = (BLADERF_META_FLAG_TX_BURST_START);// | BLADERF_META_FLAG_TX_BURST_END);// | BLADERF_META_FLAG_TX_NOW);
brf->meta_tx.timestamp= (uint64_t) (ptimestamp); brf->meta_tx.timestamp= (uint64_t) (ptimestamp);
status = bladerf_sync_tx(brf->dev, samples, (unsigned int) nsamps, &brf->meta_tx, 2*brf->tx_timeout_ms); status = bladerf_sync_tx(brf->dev, samples, (unsigned int) nsamps, &brf->meta_tx, 2*brf->tx_timeout_ms);
if (brf->meta_tx.flags == BLADERF_META_FLAG_TX_BURST_START) if (brf->meta_tx.flags == BLADERF_META_FLAG_TX_BURST_START)
brf->meta_tx.flags = BLADERF_META_FLAG_TX_UPDATE_TIMESTAMP; brf->meta_tx.flags = BLADERF_META_FLAG_TX_UPDATE_TIMESTAMP;
if (status != 0) { if (status != 0) {
//fprintf(stderr,"Failed to TX sample: %s\n", bladerf_strerror(status)); //fprintf(stderr,"Failed to TX sample: %s\n", bladerf_strerror(status));
brf->num_tx_errors++; brf->num_tx_errors++;
brf_error(status); brf_error(status);
} else if (brf->meta_tx.status & BLADERF_META_STATUS_UNDERRUN){ } else if (brf->meta_tx.status & BLADERF_META_STATUS_UNDERRUN) {
/* libbladeRF does not report this status. It is here for future use. */ /* libbladeRF does not report this status. It is here for future use. */
fprintf(stderr, "TX Underrun detected. %u valid samples were read.\n", brf->meta_tx.actual_count); fprintf(stderr, "TX Underrun detected. %u valid samples were read.\n", brf->meta_tx.actual_count);
brf->num_underflows++; brf->num_underflows++;
} }
//printf("Provided TX timestampe %u, meta timestame %u\n", ptimestamp,brf->meta_tx.timestamp); //printf("Provided TX timestampe %u, meta timestame %u\n", ptimestamp,brf->meta_tx.timestamp);
// printf("tx status %d \n",brf->meta_tx.status); // printf("tx status %d \n",brf->meta_tx.status);
brf->tx_current_ts=brf->meta_tx.timestamp; brf->tx_current_ts=brf->meta_tx.timestamp;
brf->tx_actual_nsamps+=brf->meta_tx.actual_count; brf->tx_actual_nsamps+=brf->meta_tx.actual_count;
brf->tx_nsamps+=nsamps; brf->tx_nsamps+=nsamps;
brf->tx_count++; brf->tx_count++;
return nsamps; //brf->meta_tx.actual_count; return nsamps; //brf->meta_tx.actual_count;
} }
/*! \brief Receive samples from hardware. /*! \brief Receive samples from hardware.
...@@ -182,90 +182,90 @@ static int trx_brf_write(openair0_device *device,openair0_timestamp ptimestamp, ...@@ -182,90 +182,90 @@ static int trx_brf_write(openair0_device *device,openair0_timestamp ptimestamp,
*/ */
static int trx_brf_read(openair0_device *device, openair0_timestamp *ptimestamp, void **buff, int nsamps, int cc) { static int trx_brf_read(openair0_device *device, openair0_timestamp *ptimestamp, void **buff, int nsamps, int cc) {
int status=0; int status=0;
brf_state_t *brf = (brf_state_t*)device->priv; brf_state_t *brf = (brf_state_t*)device->priv;
// BRF has only one rx/tx chain // BRF has only one rx/tx chain
int16_t *samples = (int16_t*)buff[0]; int16_t *samples = (int16_t*)buff[0];
brf->meta_rx.actual_count = 0; brf->meta_rx.actual_count = 0;
brf->meta_rx.flags = BLADERF_META_FLAG_RX_NOW; brf->meta_rx.flags = BLADERF_META_FLAG_RX_NOW;
status = bladerf_sync_rx(brf->dev, samples, (unsigned int) nsamps, &brf->meta_rx, 2*brf->rx_timeout_ms); status = bladerf_sync_rx(brf->dev, samples, (unsigned int) nsamps, &brf->meta_rx, 2*brf->rx_timeout_ms);
// printf("Current RX timestampe %u, nsamps %u, actual %u, cc %d\n", brf->meta_rx.timestamp, nsamps, brf->meta_rx.actual_count, cc); // printf("Current RX timestampe %u, nsamps %u, actual %u, cc %d\n", brf->meta_rx.timestamp, nsamps, brf->meta_rx.actual_count, cc);
if (status != 0) { if (status != 0) {
fprintf(stderr, "RX failed: %s\n", bladerf_strerror(status)); fprintf(stderr, "RX failed: %s\n", bladerf_strerror(status));
// printf("RX failed: %s\n", bladerf_strerror(status)); // printf("RX failed: %s\n", bladerf_strerror(status));
brf->num_rx_errors++; brf->num_rx_errors++;
} else if ( brf->meta_rx.status & BLADERF_META_STATUS_OVERRUN) { } else if ( brf->meta_rx.status & BLADERF_META_STATUS_OVERRUN) {
brf->num_overflows++; brf->num_overflows++;
printf("RX overrun (%d) is detected. t=" "%" PRIu64 "Got %u samples. nsymps %d\n", printf("RX overrun (%d) is detected. t=" "%" PRIu64 "Got %u samples. nsymps %d\n",
brf->num_overflows,brf->meta_rx.timestamp, brf->meta_rx.actual_count, nsamps); brf->num_overflows,brf->meta_rx.timestamp, brf->meta_rx.actual_count, nsamps);
} }
if (brf->meta_rx.actual_count != nsamps) { if (brf->meta_rx.actual_count != nsamps) {
printf("RX bad samples count, wanted %d, got %d\n", nsamps, brf->meta_rx.actual_count); printf("RX bad samples count, wanted %d, got %d\n", nsamps, brf->meta_rx.actual_count);
} }
//printf("Current RX timestampe %u\n", brf->meta_rx.timestamp); //printf("Current RX timestampe %u\n", brf->meta_rx.timestamp);
//printf("[BRF] (buff %p) ts=0x%"PRIu64" %s\n",samples, brf->meta_rx.timestamp,bladerf_strerror(status)); //printf("[BRF] (buff %p) ts=0x%"PRIu64" %s\n",samples, brf->meta_rx.timestamp,bladerf_strerror(status));
brf->rx_current_ts=brf->meta_rx.timestamp; brf->rx_current_ts=brf->meta_rx.timestamp;
brf->rx_actual_nsamps+=brf->meta_rx.actual_count; brf->rx_actual_nsamps+=brf->meta_rx.actual_count;
brf->rx_nsamps+=nsamps; brf->rx_nsamps+=nsamps;
brf->rx_count++; brf->rx_count++;
*ptimestamp = brf->meta_rx.timestamp; *ptimestamp = brf->meta_rx.timestamp;
return nsamps; //brf->meta_rx.actual_count; return nsamps; //brf->meta_rx.actual_count;
} }
/*! \brief Terminate operation of the BladeRF transceiver -- free all associated resources /*! \brief Terminate operation of the BladeRF transceiver -- free all associated resources
* \param device the hardware to use * \param device the hardware to use
*/ */
void trx_brf_end(openair0_device *device) { void trx_brf_end(openair0_device *device) {
int status; int status;
brf_state_t *brf = (brf_state_t*)device->priv; brf_state_t *brf = (brf_state_t*)device->priv;
// Disable RX module, shutting down our underlying RX stream // Disable RX module, shutting down our underlying RX stream
if ((status=bladerf_enable_module(brf->dev, BLADERF_MODULE_RX, false)) != 0) { if ((status=bladerf_enable_module(brf->dev, BLADERF_MODULE_RX, false)) != 0) {
fprintf(stderr, "Failed to disable RX module: %s\n", bladerf_strerror(status)); fprintf(stderr, "Failed to disable RX module: %s\n", bladerf_strerror(status));
} }
if ((status=bladerf_enable_module(brf->dev, BLADERF_MODULE_TX, false)) != 0) { if ((status=bladerf_enable_module(brf->dev, BLADERF_MODULE_TX, false)) != 0) {
fprintf(stderr, "Failed to disable TX module: %s\n", bladerf_strerror(status)); fprintf(stderr, "Failed to disable TX module: %s\n", bladerf_strerror(status));
} }
bladerf_close(brf->dev); bladerf_close(brf->dev);
exit(1); exit(1);
} }
/*! \brief print the BladeRF statistics /*! \brief print the BladeRF statistics
* \param device the hardware to use * \param device the hardware to use
* \returns 0 on success * \returns 0 on success
*/ */
int trx_brf_get_stats(openair0_device* device) { int trx_brf_get_stats(openair0_device* device) {
return(0); return(0);
} }
/*! \brief Reset the BladeRF statistics /*! \brief Reset the BladeRF statistics
* \param device the hardware to use * \param device the hardware to use
* \returns 0 on success * \returns 0 on success
*/ */
int trx_brf_reset_stats(openair0_device* device) { int trx_brf_reset_stats(openair0_device* device) {
return(0); return(0);
} }
/*! \brief Stop BladeRF /*! \brief Stop BladeRF
* \param card the hardware to use * \param card the hardware to use
* \returns 0 in success * \returns 0 in success
*/ */
int trx_brf_stop(openair0_device* device) { int trx_brf_stop(openair0_device* device) {
return(0); return(0);
} }
...@@ -273,39 +273,39 @@ int trx_brf_stop(openair0_device* device) { ...@@ -273,39 +273,39 @@ int trx_brf_stop(openair0_device* device) {
* \param device the hardware to use * \param device the hardware to use
* \param openair0_cfg1 openair0 Config structure (ignored. It is there to comply with RF common API) * \param openair0_cfg1 openair0 Config structure (ignored. It is there to comply with RF common API)
* \param exmimo_dump_config (ignored) * \param exmimo_dump_config (ignored)
* \returns 0 in success * \returns 0 in success
*/ */
int trx_brf_set_freq(openair0_device* device, openair0_config_t *openair0_cfg1,int exmimo_dump_config) { int trx_brf_set_freq(openair0_device* device, openair0_config_t *openair0_cfg1,int exmimo_dump_config) {
int status; int status;
brf_state_t *brf = (brf_state_t *)device->priv; brf_state_t *brf = (brf_state_t *)device->priv;
openair0_config_t *openair0_cfg = (openair0_config_t *)device->openair0_cfg; openair0_config_t *openair0_cfg = (openair0_config_t *)device->openair0_cfg;
if ((status=bladerf_set_frequency(brf->dev, BLADERF_MODULE_TX, (unsigned int) openair0_cfg->tx_freq[0])) != 0){ if ((status=bladerf_set_frequency(brf->dev, BLADERF_MODULE_TX, (unsigned int) openair0_cfg->tx_freq[0])) != 0) {
fprintf(stderr,"Failed to set TX frequency: %s\n",bladerf_strerror(status)); fprintf(stderr,"Failed to set TX frequency: %s\n",bladerf_strerror(status));
brf_error(status); brf_error(status);
}else } else
printf("[BRF] set TX Frequency to %u\n", (unsigned int) openair0_cfg->tx_freq[0]); printf("[BRF] set TX Frequency to %u\n", (unsigned int) openair0_cfg->tx_freq[0]);
if ((status=bladerf_set_frequency(brf->dev, BLADERF_MODULE_RX, (unsigned int) openair0_cfg->rx_freq[0])) != 0){ if ((status=bladerf_set_frequency(brf->dev, BLADERF_MODULE_RX, (unsigned int) openair0_cfg->rx_freq[0])) != 0) {
fprintf(stderr,"Failed to set RX frequency: %s\n",bladerf_strerror(status)); fprintf(stderr,"Failed to set RX frequency: %s\n",bladerf_strerror(status));
brf_error(status); brf_error(status);
} else } else
printf("[BRF] set RX frequency to %u\n",(unsigned int)openair0_cfg->rx_freq[0]); printf("[BRF] set RX frequency to %u\n",(unsigned int)openair0_cfg->rx_freq[0]);
return(0); return(0);
} }
/*! \brief Set Gains (TX/RX) /*! \brief Set Gains (TX/RX)
* \param device the hardware to use * \param device the hardware to use
* \param openair0_cfg openair0 Config structure * \param openair0_cfg openair0 Config structure
* \returns 0 in success * \returns 0 in success
*/ */
int trx_brf_set_gains(openair0_device* device, openair0_config_t *openair0_cfg) { int trx_brf_set_gains(openair0_device* device, openair0_config_t *openair0_cfg) {
return(0); return(0);
} }
...@@ -317,10 +317,11 @@ int16_t cos_3fsover8[8] = {2047, -1448, 0, 1447, -2047, 1447, 0, ...@@ -317,10 +317,11 @@ int16_t cos_3fsover8[8] = {2047, -1448, 0, 1447, -2047, 1447, 0,
/*! \brief calibration table for BladeRF */ /*! \brief calibration table for BladeRF */
rx_gain_calib_table_t calib_table_fx4[] = { rx_gain_calib_table_t calib_table_fx4[] = {
{2300000000.0,53.5}, {2300000000.0,53.5},
{1880000000.0,57.0}, {1880000000.0,57.0},
{816000000.0,73.0}, {816000000.0,73.0},
{-1,0}}; {-1,0}
};
/*! \brief set RX gain offset from calibration table /*! \brief set RX gain offset from calibration table
* \param openair0_cfg RF frontend parameters set by application * \param openair0_cfg RF frontend parameters set by application
...@@ -328,822 +329,822 @@ rx_gain_calib_table_t calib_table_fx4[] = { ...@@ -328,822 +329,822 @@ rx_gain_calib_table_t calib_table_fx4[] = {
*/ */
void set_rx_gain_offset(openair0_config_t *openair0_cfg, int chain_index) { void set_rx_gain_offset(openair0_config_t *openair0_cfg, int chain_index) {
int i=0; int i=0;
// loop through calibration table to find best adjustment factor for RX frequency // loop through calibration table to find best adjustment factor for RX frequency
double min_diff = 6e9,diff; double min_diff = 6e9,diff;
while (openair0_cfg->rx_gain_calib_table[i].freq>0) { while (openair0_cfg->rx_gain_calib_table[i].freq>0) {
diff = fabs(openair0_cfg->rx_freq[chain_index] - openair0_cfg->rx_gain_calib_table[i].freq); diff = fabs(openair0_cfg->rx_freq[chain_index] - openair0_cfg->rx_gain_calib_table[i].freq);
printf("cal %d: freq %f, offset %f, diff %f\n", printf("cal %d: freq %f, offset %f, diff %f\n",
i, i,
openair0_cfg->rx_gain_calib_table[i].freq, openair0_cfg->rx_gain_calib_table[i].freq,
openair0_cfg->rx_gain_calib_table[i].offset,diff); openair0_cfg->rx_gain_calib_table[i].offset,diff);
if (min_diff > diff) { if (min_diff > diff) {
min_diff = diff; min_diff = diff;
openair0_cfg->rx_gain_offset[chain_index] = openair0_cfg->rx_gain_calib_table[i].offset; openair0_cfg->rx_gain_offset[chain_index] = openair0_cfg->rx_gain_calib_table[i].offset;
}
i++;
} }
i++;
}
} }
/*! \brief Calibrate LMSSDR RF /*! \brief Calibrate LMSSDR RF
* \param device the hardware to use * \param device the hardware to use
*/ */
void calibrate_rf(openair0_device *device) { void calibrate_rf(openair0_device *device) {
/* TODO: this function does not seem to work. Disabled until fixed. */ /* TODO: this function does not seem to work. Disabled until fixed. */
return; return;
brf_state_t *brf = (brf_state_t *)device->priv; brf_state_t *brf = (brf_state_t *)device->priv;
openair0_timestamp ptimestamp; openair0_timestamp ptimestamp;
int16_t *calib_buffp,*calib_tx_buffp; int16_t *calib_buffp,*calib_tx_buffp;
int16_t calib_buff[2*RXDCLENGTH]; int16_t calib_buff[2*RXDCLENGTH];
int16_t calib_tx_buff[2*RXDCLENGTH]; int16_t calib_tx_buff[2*RXDCLENGTH];
int i,j,offI,offQ,offIold,offQold,offInew,offQnew,offphase,offphaseold,offphasenew,offgain,offgainold,offgainnew; int i,j,offI,offQ,offIold,offQold,offInew,offQnew,offphase,offphaseold,offphasenew,offgain,offgainold,offgainnew;
int32_t meanI,meanQ,meanIold,meanQold; int32_t meanI,meanQ,meanIold,meanQold;
int cnt=0,loop; int cnt=0,loop;
// put TX on a far-away frequency to avoid interference in RX band // put TX on a far-away frequency to avoid interference in RX band
bladerf_set_frequency(brf->dev,BLADERF_MODULE_TX, (unsigned int) device->openair0_cfg->rx_freq[0] + 200e6); bladerf_set_frequency(brf->dev,BLADERF_MODULE_TX, (unsigned int) device->openair0_cfg->rx_freq[0] + 200e6);
// Set gains to close to max // Set gains to close to max
bladerf_set_gain(brf->dev, BLADERF_MODULE_RX, 60); bladerf_set_gain(brf->dev, BLADERF_MODULE_RX, 60);
bladerf_set_gain(brf->dev, BLADERF_MODULE_TX, 60); bladerf_set_gain(brf->dev, BLADERF_MODULE_TX, 60);
// fill TX buffer with fs/8 complex sinusoid // fill TX buffer with fs/8 complex sinusoid
j=0; j=0;
for (i=0;i<RXDCLENGTH;i++) { for (i=0; i<RXDCLENGTH; i++) {
calib_tx_buff[j++] = cos_fsover8[i&7]; calib_tx_buff[j++] = cos_fsover8[i&7];
calib_tx_buff[j++] = cos_fsover8[(i+6)&7]; // sin calib_tx_buff[j++] = cos_fsover8[(i+6)&7]; // sin
}
calib_buffp = &calib_buff[0];
calib_tx_buffp = &calib_tx_buff[0];
// Calibrate RX DC offset
offIold=offQold=2048;
bladerf_set_correction(brf->dev,BLADERF_MODULE_RX,BLADERF_CORR_LMS_DCOFF_I,offIold);
bladerf_set_correction(brf->dev,BLADERF_MODULE_RX,BLADERF_CORR_LMS_DCOFF_Q,offQold);
for (i=0;i<10;i++)
trx_brf_read(device, &ptimestamp, (void **)&calib_buffp, RXDCLENGTH, 0);
for (meanIold=meanQold=i=j=0;i<RXDCLENGTH;i++) {
meanIold+=calib_buff[j++];
meanQold+=calib_buff[j++];
}
meanIold/=RXDCLENGTH;
meanQold/=RXDCLENGTH;
printf("[BRF] RX DC: (%d,%d) => (%d,%d)\n",offIold,offQold,meanIold,meanQold);
offI=offQ=-2048;
bladerf_set_correction(brf->dev,BLADERF_MODULE_RX,BLADERF_CORR_LMS_DCOFF_I,offI);
bladerf_set_correction(brf->dev,BLADERF_MODULE_RX,BLADERF_CORR_LMS_DCOFF_Q,offQ);
for (i=0;i<10;i++)
trx_brf_read(device, &ptimestamp, (void **)&calib_buffp, RXDCLENGTH, 0);
for (meanI=meanQ=i=j=0;i<RXDCLENGTH;i++) {
meanI+=calib_buff[j++];
meanQ+=calib_buff[j++];
}
meanI/=RXDCLENGTH;
meanQ/=RXDCLENGTH;
// printf("[BRF] RX DC: (%d,%d) => (%d,%d)\n",offI,offQ,meanI,meanQ);
while (cnt++ < 12) {
offInew=(offIold+offI)>>1;
offQnew=(offQold+offQ)>>1;
if (meanI*meanI < meanIold*meanIold) {
meanIold = meanI;
offIold = offI;
printf("[BRF] *** RX DC: offI %d => %d\n",offIold,meanI);
} }
if (meanQ*meanQ < meanQold*meanQold) { calib_buffp = &calib_buff[0];
meanQold = meanQ; calib_tx_buffp = &calib_tx_buff[0];
offQold = offQ; // Calibrate RX DC offset
printf("[BRF] *** RX DC: offQ %d => %d\n",offQold,meanQ);
offIold=offQold=2048;
bladerf_set_correction(brf->dev,BLADERF_MODULE_RX,BLADERF_CORR_LMS_DCOFF_I,offIold);
bladerf_set_correction(brf->dev,BLADERF_MODULE_RX,BLADERF_CORR_LMS_DCOFF_Q,offQold);
for (i=0; i<10; i++)
trx_brf_read(device, &ptimestamp, (void **)&calib_buffp, RXDCLENGTH, 0);
for (meanIold=meanQold=i=j=0; i<RXDCLENGTH; i++) {
meanIold+=calib_buff[j++];
meanQold+=calib_buff[j++];
} }
offI = offInew; meanIold/=RXDCLENGTH;
offQ = offQnew; meanQold/=RXDCLENGTH;
printf("[BRF] RX DC: (%d,%d) => (%d,%d)\n",offIold,offQold,meanIold,meanQold);
offI=offQ=-2048;
bladerf_set_correction(brf->dev,BLADERF_MODULE_RX,BLADERF_CORR_LMS_DCOFF_I,offI); bladerf_set_correction(brf->dev,BLADERF_MODULE_RX,BLADERF_CORR_LMS_DCOFF_I,offI);
bladerf_set_correction(brf->dev,BLADERF_MODULE_RX,BLADERF_CORR_LMS_DCOFF_Q,offQ); bladerf_set_correction(brf->dev,BLADERF_MODULE_RX,BLADERF_CORR_LMS_DCOFF_Q,offQ);
for (i=0; i<10; i++)
trx_brf_read(device, &ptimestamp, (void **)&calib_buffp, RXDCLENGTH, 0);
for (i=0;i<10;i++) for (meanI=meanQ=i=j=0; i<RXDCLENGTH; i++) {
trx_brf_read(device, &ptimestamp, (void **)&calib_buffp, RXDCLENGTH, 0); meanI+=calib_buff[j++];
meanQ+=calib_buff[j++];
for (meanI=meanQ=i=j=0;i<RXDCLENGTH;i++) {
meanI+=calib_buff[j++];
meanQ+=calib_buff[j++];
} }
meanI/=RXDCLENGTH; meanI/=RXDCLENGTH;
meanQ/=RXDCLENGTH; meanQ/=RXDCLENGTH;
printf("[BRF] RX DC: (%d,%d) => (%d,%d)\n",offI,offQ,meanI,meanQ); // printf("[BRF] RX DC: (%d,%d) => (%d,%d)\n",offI,offQ,meanI,meanQ);
}
while (cnt++ < 12) {
printf("[BRF] RX DC: (%d,%d) => (%d,%d)\n",offIold,offQold,meanIold,meanQold);
bladerf_set_correction(brf->dev,BLADERF_MODULE_RX,BLADERF_CORR_LMS_DCOFF_I,offIold); offInew=(offIold+offI)>>1;
bladerf_set_correction(brf->dev,BLADERF_MODULE_RX,BLADERF_CORR_LMS_DCOFF_Q,offQold); offQnew=(offQold+offQ)>>1;
// TX DC offset if (meanI*meanI < meanIold*meanIold) {
// PUT TX as f_RX + fs/4 meanIold = meanI;
// loop back BLADERF_LB_RF_LNA1 offIold = offI;
bladerf_set_frequency(brf->dev,BLADERF_MODULE_TX, (unsigned int) device->openair0_cfg->rx_freq[0] + (unsigned int) device->openair0_cfg->sample_rate/4); printf("[BRF] *** RX DC: offI %d => %d\n",offIold,meanI);
bladerf_set_loopback (brf->dev,BLADERF_LB_RF_LNA1); }
if (meanQ*meanQ < meanQold*meanQold) {
offIold=2048; meanQold = meanQ;
bladerf_set_correction(brf->dev,BLADERF_MODULE_TX,BLADERF_CORR_LMS_DCOFF_I,offIold); offQold = offQ;
for (i=0;i<10;i++) { printf("[BRF] *** RX DC: offQ %d => %d\n",offQold,meanQ);
trx_brf_read(device, &ptimestamp, (void **)&calib_buffp, RXDCLENGTH, 0); }
trx_brf_write(device,ptimestamp+5*RXDCLENGTH, (void **)&calib_tx_buffp, RXDCLENGTH, 0, 0); offI = offInew;
} offQ = offQnew;
for (meanIold=meanQold=i=j=0;i<RXDCLENGTH;i++) { bladerf_set_correction(brf->dev,BLADERF_MODULE_RX,BLADERF_CORR_LMS_DCOFF_I,offI);
switch (i&3) { bladerf_set_correction(brf->dev,BLADERF_MODULE_RX,BLADERF_CORR_LMS_DCOFF_Q,offQ);
case 0:
meanIold+=calib_buff[j++]; for (i=0; i<10; i++)
break; trx_brf_read(device, &ptimestamp, (void **)&calib_buffp, RXDCLENGTH, 0);
case 1:
meanQold+=calib_buff[j++]; for (meanI=meanQ=i=j=0; i<RXDCLENGTH; i++) {
break; meanI+=calib_buff[j++];
case 2: meanQ+=calib_buff[j++];
meanIold-=calib_buff[j++]; }
break; meanI/=RXDCLENGTH;
case 3: meanQ/=RXDCLENGTH;
meanQold-=calib_buff[j++]; printf("[BRF] RX DC: (%d,%d) => (%d,%d)\n",offI,offQ,meanI,meanQ);
break;
} }
}
// meanIold/=RXDCLENGTH; printf("[BRF] RX DC: (%d,%d) => (%d,%d)\n",offIold,offQold,meanIold,meanQold);
// meanQold/=RXDCLENGTH; bladerf_set_correction(brf->dev,BLADERF_MODULE_RX,BLADERF_CORR_LMS_DCOFF_I,offIold);
printf("[BRF] TX DC (offI): %d => (%d,%d)\n",offIold,meanIold,meanQold); bladerf_set_correction(brf->dev,BLADERF_MODULE_RX,BLADERF_CORR_LMS_DCOFF_Q,offQold);
offI=-2048; // TX DC offset
bladerf_set_correction(brf->dev,BLADERF_MODULE_TX,BLADERF_CORR_LMS_DCOFF_I,offI); // PUT TX as f_RX + fs/4
for (i=0;i<10;i++) { // loop back BLADERF_LB_RF_LNA1
trx_brf_read(device, &ptimestamp, (void **)&calib_buffp, RXDCLENGTH, 0); bladerf_set_frequency(brf->dev,BLADERF_MODULE_TX, (unsigned int) device->openair0_cfg->rx_freq[0] + (unsigned int) device->openair0_cfg->sample_rate/4);
trx_brf_write(device,ptimestamp+5*RXDCLENGTH, (void **)&calib_tx_buffp, RXDCLENGTH, 0, 0); bladerf_set_loopback (brf->dev,BLADERF_LB_RF_LNA1);
}
for (meanI=meanQ=i=j=0;i<RXDCLENGTH;i++) { offIold=2048;
switch (i&3) { bladerf_set_correction(brf->dev,BLADERF_MODULE_TX,BLADERF_CORR_LMS_DCOFF_I,offIold);
case 0: for (i=0; i<10; i++) {
meanI+=calib_buff[j++]; trx_brf_read(device, &ptimestamp, (void **)&calib_buffp, RXDCLENGTH, 0);
break; trx_brf_write(device,ptimestamp+5*RXDCLENGTH, (void **)&calib_tx_buffp, RXDCLENGTH, 0, 0);
case 1:
meanQ+=calib_buff[j++];
break;
case 2:
meanI-=calib_buff[j++];
break;
case 3:
meanQ-=calib_buff[j++];
break;
} }
} for (meanIold=meanQold=i=j=0; i<RXDCLENGTH; i++) {
// meanI/=RXDCLENGTH; switch (i&3) {
// meanQ/=RXDCLENGTH; case 0:
printf("[BRF] TX DC (offI): %d => (%d,%d)\n",offI,meanI,meanQ); meanIold+=calib_buff[j++];
cnt = 0; break;
while (cnt++ < 12) { case 1:
meanQold+=calib_buff[j++];
offInew=(offIold+offI)>>1; break;
if (meanI*meanI+meanQ*meanQ < meanIold*meanIold +meanQold*meanQold) { case 2:
printf("[BRF] TX DC (offI): ([%d,%d]) => %d : %d\n",offIold,offI,offInew,meanI*meanI+meanQ*meanQ); meanIold-=calib_buff[j++];
meanIold = meanI; break;
meanQold = meanQ; case 3:
offIold = offI; meanQold-=calib_buff[j++];
break;
}
} }
offI = offInew; // meanIold/=RXDCLENGTH;
bladerf_set_correction(brf->dev,BLADERF_MODULE_TX,BLADERF_CORR_LMS_DCOFF_I,offI); // meanQold/=RXDCLENGTH;
printf("[BRF] TX DC (offI): %d => (%d,%d)\n",offIold,meanIold,meanQold);
for (i=0;i<10;i++) { offI=-2048;
trx_brf_read(device, &ptimestamp, (void **)&calib_buffp, RXDCLENGTH, 0); bladerf_set_correction(brf->dev,BLADERF_MODULE_TX,BLADERF_CORR_LMS_DCOFF_I,offI);
trx_brf_write(device,ptimestamp+5*RXDCLENGTH, (void **)&calib_tx_buffp, RXDCLENGTH, 0, 0); for (i=0; i<10; i++) {
} trx_brf_read(device, &ptimestamp, (void **)&calib_buffp, RXDCLENGTH, 0);
for (meanI=meanQ=i=j=0;i<RXDCLENGTH;i++) { trx_brf_write(device,ptimestamp+5*RXDCLENGTH, (void **)&calib_tx_buffp, RXDCLENGTH, 0, 0);
switch (i&3) {
case 0:
meanI+=calib_buff[j++];
break;
case 1:
meanQ+=calib_buff[j++];
break;
case 2:
meanI-=calib_buff[j++];
break;
case 3:
meanQ-=calib_buff[j++];
break;
}
} }
// meanI/=RXDCLENGTH; for (meanI=meanQ=i=j=0; i<RXDCLENGTH; i++) {
// meanQ/=RXDCLENGTH; switch (i&3) {
// printf("[BRF] TX DC (offI): %d => (%d,%d)\n",offI,meanI,meanQ); case 0:
} meanI+=calib_buff[j++];
break;
bladerf_set_correction(brf->dev,BLADERF_MODULE_TX,BLADERF_CORR_LMS_DCOFF_I,offIold); case 1:
meanQ+=calib_buff[j++];
offQold=2048; break;
bladerf_set_correction(brf->dev,BLADERF_MODULE_TX,BLADERF_CORR_LMS_DCOFF_Q,offQold); case 2:
for (i=0;i<10;i++) { meanI-=calib_buff[j++];
trx_brf_read(device, &ptimestamp, (void **)&calib_buffp, RXDCLENGTH, 0); break;
trx_brf_write(device,ptimestamp+5*RXDCLENGTH, (void **)&calib_tx_buffp, RXDCLENGTH, 0, 0); case 3:
} meanQ-=calib_buff[j++];
// project on fs/4 break;
for (meanIold=meanQold=i=j=0;i<RXDCLENGTH;i++) { }
switch (i&3) {
case 0:
meanIold+=calib_buff[j++];
break;
case 1:
meanQold+=calib_buff[j++];
break;
case 2:
meanIold-=calib_buff[j++];
break;
case 3:
meanQold-=calib_buff[j++];
break;
} }
} // meanI/=RXDCLENGTH;
// meanIold/=RXDCLENGTH; // meanQ/=RXDCLENGTH;
// meanQold/=RXDCLENGTH; printf("[BRF] TX DC (offI): %d => (%d,%d)\n",offI,meanI,meanQ);
printf("[BRF] TX DC (offQ): %d => (%d,%d)\n",offQold,meanIold,meanQold); cnt = 0;
while (cnt++ < 12) {
offQ=-2048;
bladerf_set_correction(brf->dev,BLADERF_MODULE_TX,BLADERF_CORR_LMS_DCOFF_Q,offQ); offInew=(offIold+offI)>>1;
for (i=0;i<10;i++) { if (meanI*meanI+meanQ*meanQ < meanIold*meanIold +meanQold*meanQold) {
trx_brf_read(device, &ptimestamp, (void **)&calib_buffp, RXDCLENGTH, 0); printf("[BRF] TX DC (offI): ([%d,%d]) => %d : %d\n",offIold,offI,offInew,meanI*meanI+meanQ*meanQ);
trx_brf_write(device,ptimestamp+5*RXDCLENGTH, (void **)&calib_tx_buffp, RXDCLENGTH, 0, 0); meanIold = meanI;
} meanQold = meanQ;
for (meanI=meanQ=i=j=0;i<RXDCLENGTH;i++) { offIold = offI;
switch (i&3) { }
case 0: offI = offInew;
meanI+=calib_buff[j++]; bladerf_set_correction(brf->dev,BLADERF_MODULE_TX,BLADERF_CORR_LMS_DCOFF_I,offI);
break;
case 1: for (i=0; i<10; i++) {
meanQ+=calib_buff[j++]; trx_brf_read(device, &ptimestamp, (void **)&calib_buffp, RXDCLENGTH, 0);
break; trx_brf_write(device,ptimestamp+5*RXDCLENGTH, (void **)&calib_tx_buffp, RXDCLENGTH, 0, 0);
case 2: }
meanI-=calib_buff[j++]; for (meanI=meanQ=i=j=0; i<RXDCLENGTH; i++) {
break; switch (i&3) {
case 3: case 0:
meanQ-=calib_buff[j++]; meanI+=calib_buff[j++];
break; break;
case 1:
meanQ+=calib_buff[j++];
break;
case 2:
meanI-=calib_buff[j++];
break;
case 3:
meanQ-=calib_buff[j++];
break;
}
}
// meanI/=RXDCLENGTH;
// meanQ/=RXDCLENGTH;
// printf("[BRF] TX DC (offI): %d => (%d,%d)\n",offI,meanI,meanQ);
} }
}
// meanI/=RXDCLENGTH;
// meanQ/=RXDCLENGTH;
printf("[BRF] TX DC (offQ): %d => (%d,%d)\n",offQ,meanI,meanQ);
cnt=0;
while (cnt++ < 12) {
offQnew=(offQold+offQ)>>1;
if (meanI*meanI+meanQ*meanQ < meanIold*meanIold +meanQold*meanQold) {
printf("[BRF] TX DC (offQ): ([%d,%d]) => %d : %d\n",offQold,offQ,offQnew,meanI*meanI+meanQ*meanQ);
meanIold = meanI; bladerf_set_correction(brf->dev,BLADERF_MODULE_TX,BLADERF_CORR_LMS_DCOFF_I,offIold);
meanQold = meanQ;
offQold = offQ;
}
offQ = offQnew;
bladerf_set_correction(brf->dev,BLADERF_MODULE_TX,BLADERF_CORR_LMS_DCOFF_Q,offQ);
for (i=0;i<10;i++) { offQold=2048;
trx_brf_read(device, &ptimestamp, (void **)&calib_buffp, RXDCLENGTH, 0); bladerf_set_correction(brf->dev,BLADERF_MODULE_TX,BLADERF_CORR_LMS_DCOFF_Q,offQold);
trx_brf_write(device,ptimestamp+5*RXDCLENGTH, (void **)&calib_tx_buffp, RXDCLENGTH, 0, 0); for (i=0; i<10; i++) {
} trx_brf_read(device, &ptimestamp, (void **)&calib_buffp, RXDCLENGTH, 0);
for (meanI=meanQ=i=j=0;i<RXDCLENGTH;i++) { trx_brf_write(device,ptimestamp+5*RXDCLENGTH, (void **)&calib_tx_buffp, RXDCLENGTH, 0, 0);
switch (i&3) {
case 0:
meanI+=calib_buff[j++];
break;
case 1:
meanQ+=calib_buff[j++];
break;
case 2:
meanI-=calib_buff[j++];
break;
case 3:
meanQ-=calib_buff[j++];
break;
}
} }
// meanI/=RXDCLENGTH; // project on fs/4
// meanQ/=RXDCLENGTH; for (meanIold=meanQold=i=j=0; i<RXDCLENGTH; i++) {
// printf("[BRF] TX DC (offQ): %d => (%d,%d)\n",offQ,meanI,meanQ); switch (i&3) {
} case 0:
meanIold+=calib_buff[j++];
printf("[BRF] TX DC: (%d,%d) => (%d,%d)\n",offIold,offQold,meanIold,meanQold); break;
case 1:
bladerf_set_correction(brf->dev,BLADERF_MODULE_TX,BLADERF_CORR_LMS_DCOFF_Q,offQold); meanQold+=calib_buff[j++];
break;
// TX IQ imbalance case 2:
for (loop=0;loop<2;loop++) { meanIold-=calib_buff[j++];
offphaseold=4096; break;
bladerf_set_correction(brf->dev,BLADERF_MODULE_TX,BLADERF_CORR_FPGA_PHASE,offphaseold); case 3:
for (i=0;i<10;i++) { meanQold-=calib_buff[j++];
trx_brf_read(device, &ptimestamp, (void **)&calib_buffp, RXDCLENGTH, 0); break;
trx_brf_write(device,ptimestamp+5*RXDCLENGTH, (void **)&calib_tx_buffp, RXDCLENGTH, 0, 0); }
} }
// project on fs/8 (Image of TX signal in +ve frequencies) // meanIold/=RXDCLENGTH;
for (meanIold=meanQold=i=j=0;i<RXDCLENGTH;i++) { // meanQold/=RXDCLENGTH;
meanIold+= (calib_buff[j]*cos_fsover8[i&7] - calib_buff[j+1]*cos_fsover8[(i+2)&7])>>11; printf("[BRF] TX DC (offQ): %d => (%d,%d)\n",offQold,meanIold,meanQold);
meanQold+= (calib_buff[j]*cos_fsover8[(i+2)&7] + calib_buff[j+1]*cos_fsover8[i&7])>>11;
j+=2; offQ=-2048;
} bladerf_set_correction(brf->dev,BLADERF_MODULE_TX,BLADERF_CORR_LMS_DCOFF_Q,offQ);
for (i=0; i<10; i++) {
meanIold/=RXDCLENGTH; trx_brf_read(device, &ptimestamp, (void **)&calib_buffp, RXDCLENGTH, 0);
meanQold/=RXDCLENGTH; trx_brf_write(device,ptimestamp+5*RXDCLENGTH, (void **)&calib_tx_buffp, RXDCLENGTH, 0, 0);
printf("[BRF] TX IQ (offphase): %d => (%d,%d)\n",offphaseold,meanIold,meanQold);
offphase=-4096;
bladerf_set_correction(brf->dev,BLADERF_MODULE_TX,BLADERF_CORR_FPGA_PHASE,offphase);
for (i=0;i<10;i++) {
trx_brf_read(device, &ptimestamp, (void **)&calib_buffp, RXDCLENGTH, 0);
trx_brf_write(device,ptimestamp+5*RXDCLENGTH, (void **)&calib_tx_buffp, RXDCLENGTH, 0, 0);
}
// project on fs/8 (Image of TX signal in +ve frequencies)
for (meanI=meanQ=i=j=0;i<RXDCLENGTH;i++) {
meanI+= (calib_buff[j]*cos_fsover8[i&7] - calib_buff[j+1]*cos_fsover8[(i+2)&7])>>11;
meanQ+= (calib_buff[j]*cos_fsover8[(i+2)&7] + calib_buff[j+1]*cos_fsover8[i&7])>>11;
j+=2;
}
meanI/=RXDCLENGTH;
meanQ/=RXDCLENGTH;
printf("[BRF] TX IQ (offphase): %d => (%d,%d)\n",offphase,meanI,meanQ);
cnt=0;
while (cnt++ < 13) {
offphasenew=(offphaseold+offphase)>>1;
printf("[BRF] TX IQ (offphase): ([%d,%d]) => %d : %d\n",offphaseold,offphase,offphasenew,meanI*meanI+meanQ*meanQ);
if (meanI*meanI+meanQ*meanQ < meanIold*meanIold +meanQold*meanQold) {
meanIold = meanI;
meanQold = meanQ;
offphaseold = offphase;
}
offphase = offphasenew;
bladerf_set_correction(brf->dev,BLADERF_MODULE_TX,BLADERF_CORR_FPGA_PHASE,offphase);
for (i=0;i<10;i++) {
trx_brf_read(device, &ptimestamp, (void **)&calib_buffp, RXDCLENGTH, 0);
trx_brf_write(device,ptimestamp+5*RXDCLENGTH, (void **)&calib_tx_buffp, RXDCLENGTH, 0, 0);
}
// project on fs/8 (Image of TX signal in +ve frequencies)
for (meanI=meanQ=i=j=0;i<RXDCLENGTH;i++) {
meanI+= (calib_buff[j]*cos_fsover8[i&7] - calib_buff[j+1]*cos_fsover8[(i+2)&7])>>11;
meanQ+= (calib_buff[j]*cos_fsover8[(i+2)&7] + calib_buff[j+1]*cos_fsover8[i&7])>>11;
j+=2;
}
meanI/=RXDCLENGTH;
meanQ/=RXDCLENGTH;
// printf("[BRF] TX DC (offQ): %d => (%d,%d)\n",offQ,meanI,meanQ);
}
printf("[BRF] TX IQ offphase: %d => (%d,%d)\n",offphaseold,meanIold,meanQold);
bladerf_set_correction(brf->dev,BLADERF_MODULE_TX,BLADERF_CORR_FPGA_PHASE,offphaseold);
offgainold=4096;
bladerf_set_correction(brf->dev,BLADERF_MODULE_TX,BLADERF_CORR_FPGA_GAIN,offgainold);
for (i=0;i<10;i++) {
trx_brf_read(device, &ptimestamp, (void **)&calib_buffp, RXDCLENGTH, 0);
trx_brf_write(device,ptimestamp+5*RXDCLENGTH, (void **)&calib_tx_buffp, RXDCLENGTH, 0, 0);
}
// project on fs/8 (Image of TX signal in +ve frequencies)
for (meanIold=meanQold=i=j=0;i<RXDCLENGTH;i++) {
meanIold+= (calib_buff[j]*cos_fsover8[i&7] - calib_buff[j+1]*cos_fsover8[(i+2)&7])>>11;
meanQold+= (calib_buff[j]*cos_fsover8[(i+2)&7] + calib_buff[j+1]*cos_fsover8[i&7])>>11;
j+=2;
}
meanIold/=RXDCLENGTH;
meanQold/=RXDCLENGTH;
printf("[BRF] TX IQ (offgain): %d => (%d,%d)\n",offgainold,meanIold,meanQold);
offgain=-4096;
bladerf_set_correction(brf->dev,BLADERF_MODULE_TX,BLADERF_CORR_FPGA_GAIN,offgain);
for (i=0;i<10;i++) {
trx_brf_read(device, &ptimestamp, (void **)&calib_buffp, RXDCLENGTH, 0);
trx_brf_write(device,ptimestamp+5*RXDCLENGTH, (void **)&calib_tx_buffp, RXDCLENGTH, 0, 0);
}
// project on fs/8 (Image of TX signal in +ve frequencies)
for (meanI=meanQ=i=j=0;i<RXDCLENGTH;i++) {
meanI+= (calib_buff[j]*cos_fsover8[i&7] - calib_buff[j+1]*cos_fsover8[(i+2)&7])>>11;
meanQ+= (calib_buff[j]*cos_fsover8[(i+2)&7] + calib_buff[j+1]*cos_fsover8[i&7])>>11;
j+=2;
}
meanI/=RXDCLENGTH;
meanQ/=RXDCLENGTH;
printf("[BRF] TX IQ (offgain): %d => (%d,%d)\n",offgain,meanI,meanQ);
cnt=0;
while (cnt++ < 13) {
offgainnew=(offgainold+offgain)>>1;
if (meanI*meanI+meanQ*meanQ < meanIold*meanIold +meanQold*meanQold) {
printf("[BRF] TX IQ (offgain): ([%d,%d]) => %d : %d\n",offgainold,offgain,offgainnew,meanI*meanI+meanQ*meanQ);
meanIold = meanI;
meanQold = meanQ;
offgainold = offgain;
}
offgain = offgainnew;
bladerf_set_correction(brf->dev,BLADERF_MODULE_TX,BLADERF_CORR_FPGA_GAIN,offgain);
for (i=0;i<10;i++) {
trx_brf_read(device, &ptimestamp, (void **)&calib_buffp, RXDCLENGTH, 0);
trx_brf_write(device,ptimestamp+5*RXDCLENGTH, (void **)&calib_tx_buffp, RXDCLENGTH, 0, 0);
}
// project on fs/8 (Image of TX signal in +ve frequencies)
for (meanI=meanQ=i=j=0;i<RXDCLENGTH;i++) {
meanI+= (calib_buff[j]*cos_fsover8[i&7] - calib_buff[j+1]*cos_fsover8[(i+2)&7])>>11;
meanQ+= (calib_buff[j]*cos_fsover8[(i+2)&7] + calib_buff[j+1]*cos_fsover8[i&7])>>11;
j+=2;
}
meanI/=RXDCLENGTH;
meanQ/=RXDCLENGTH;
// printf("[BRF] TX DC (offQ): %d => (%d,%d)\n",offQ,meanI,meanQ);
}
printf("[BRF] TX IQ offgain: %d => (%d,%d)\n",offgainold,meanIold,meanQold);
bladerf_set_correction(brf->dev,BLADERF_MODULE_TX,BLADERF_CORR_FPGA_GAIN,offgainold);
}
// RX IQ imbalance
for (loop=0;loop<2;loop++) {
offphaseold=4096;
bladerf_set_correction(brf->dev,BLADERF_MODULE_RX,BLADERF_CORR_FPGA_PHASE,offphaseold);
for (i=0;i<10;i++) {
trx_brf_read(device, &ptimestamp, (void **)&calib_buffp, RXDCLENGTH, 0);
trx_brf_write(device,ptimestamp+5*RXDCLENGTH, (void **)&calib_tx_buffp, RXDCLENGTH, 0, 0);
}
// project on -3fs/8 (Image of TX signal in -ve frequencies)
for (meanIold=meanQold=i=j=0;i<RXDCLENGTH;i++) {
meanIold+= (calib_buff[j]*cos_3fsover8[i&7] - calib_buff[j+1]*cos_3fsover8[(i+2)&7])>>11;
meanQold+= (calib_buff[j]*cos_3fsover8[(i+2)&7] + calib_buff[j+1]*cos_3fsover8[i&7])>>11;
j+=2;
}
meanIold/=RXDCLENGTH;
meanQold/=RXDCLENGTH;
printf("[BRF] RX IQ (offphase): %d => (%d,%d)\n",offphaseold,meanIold,meanQold);
offphase=-4096;
bladerf_set_correction(brf->dev,BLADERF_MODULE_RX,BLADERF_CORR_FPGA_PHASE,offphase);
for (i=0;i<10;i++) {
trx_brf_read(device, &ptimestamp, (void **)&calib_buffp, RXDCLENGTH, 0);
trx_brf_write(device,ptimestamp+5*RXDCLENGTH, (void **)&calib_tx_buffp, RXDCLENGTH, 0, 0);
} }
// project on -3fs/8 (Image of TX signal in -ve frequencies) for (meanI=meanQ=i=j=0; i<RXDCLENGTH; i++) {
for (meanI=meanQ=i=j=0;i<RXDCLENGTH;i++) { switch (i&3) {
meanI+= (calib_buff[j]*cos_3fsover8[i&7] - calib_buff[j+1]*cos_3fsover8[(i+2)&7])>>11; case 0:
meanQ+= (calib_buff[j]*cos_3fsover8[(i+2)&7] + calib_buff[j+1]*cos_3fsover8[i&7])>>11; meanI+=calib_buff[j++];
j+=2; break;
case 1:
meanQ+=calib_buff[j++];
break;
case 2:
meanI-=calib_buff[j++];
break;
case 3:
meanQ-=calib_buff[j++];
break;
}
} }
// meanI/=RXDCLENGTH;
meanI/=RXDCLENGTH; // meanQ/=RXDCLENGTH;
meanQ/=RXDCLENGTH; printf("[BRF] TX DC (offQ): %d => (%d,%d)\n",offQ,meanI,meanQ);
printf("[BRF] RX IQ (offphase): %d => (%d,%d)\n",offphase,meanI,meanQ);
cnt=0; cnt=0;
while (cnt++ < 13) { while (cnt++ < 12) {
offphasenew=(offphaseold+offphase)>>1; offQnew=(offQold+offQ)>>1;
printf("[BRF] RX IQ (offphase): ([%d,%d]) => %d : %d\n",offphaseold,offphase,offphasenew,meanI*meanI+meanQ*meanQ); if (meanI*meanI+meanQ*meanQ < meanIold*meanIold +meanQold*meanQold) {
if (meanI*meanI+meanQ*meanQ < meanIold*meanIold +meanQold*meanQold) { printf("[BRF] TX DC (offQ): ([%d,%d]) => %d : %d\n",offQold,offQ,offQnew,meanI*meanI+meanQ*meanQ);
meanIold = meanI;
meanIold = meanI; meanQold = meanQ;
meanQold = meanQ; offQold = offQ;
offphaseold = offphase; }
} offQ = offQnew;
offphase = offphasenew; bladerf_set_correction(brf->dev,BLADERF_MODULE_TX,BLADERF_CORR_LMS_DCOFF_Q,offQ);
bladerf_set_correction(brf->dev,BLADERF_MODULE_RX,BLADERF_CORR_FPGA_PHASE,offphase);
for (i=0; i<10; i++) {
for (i=0;i<10;i++) { trx_brf_read(device, &ptimestamp, (void **)&calib_buffp, RXDCLENGTH, 0);
trx_brf_read(device, &ptimestamp, (void **)&calib_buffp, RXDCLENGTH, 0); trx_brf_write(device,ptimestamp+5*RXDCLENGTH, (void **)&calib_tx_buffp, RXDCLENGTH, 0, 0);
trx_brf_write(device,ptimestamp+5*RXDCLENGTH, (void **)&calib_tx_buffp, RXDCLENGTH, 0, 0); }
} for (meanI=meanQ=i=j=0; i<RXDCLENGTH; i++) {
// project on -3fs/8 (Image of TX signal in -ve frequencies) switch (i&3) {
for (meanI=meanQ=i=j=0;i<RXDCLENGTH;i++) { case 0:
meanI+= (calib_buff[j]*cos_3fsover8[i&7] - calib_buff[j+1]*cos_3fsover8[(i+2)&7])>>11; meanI+=calib_buff[j++];
meanQ+= (calib_buff[j]*cos_3fsover8[(i+2)&7] + calib_buff[j+1]*cos_3fsover8[i&7])>>11; break;
j+=2; case 1:
} meanQ+=calib_buff[j++];
meanI/=RXDCLENGTH; break;
meanQ/=RXDCLENGTH; case 2:
meanI-=calib_buff[j++];
// printf("[BRF] TX DC (offQ): %d => (%d,%d)\n",offQ,meanI,meanQ); break;
case 3:
meanQ-=calib_buff[j++];
break;
}
}
// meanI/=RXDCLENGTH;
// meanQ/=RXDCLENGTH;
// printf("[BRF] TX DC (offQ): %d => (%d,%d)\n",offQ,meanI,meanQ);
} }
printf("[BRF] RX IQ offphase: %d => (%d,%d)\n",offphaseold,meanIold,meanQold); printf("[BRF] TX DC: (%d,%d) => (%d,%d)\n",offIold,offQold,meanIold,meanQold);
bladerf_set_correction(brf->dev,BLADERF_MODULE_RX,BLADERF_CORR_FPGA_PHASE,offphaseold); bladerf_set_correction(brf->dev,BLADERF_MODULE_TX,BLADERF_CORR_LMS_DCOFF_Q,offQold);
offgainold=4096; // TX IQ imbalance
bladerf_set_correction(brf->dev,BLADERF_MODULE_RX,BLADERF_CORR_FPGA_GAIN,offgainold); for (loop=0; loop<2; loop++) {
for (i=0;i<10;i++) { offphaseold=4096;
trx_brf_read(device, &ptimestamp, (void **)&calib_buffp, RXDCLENGTH, 0); bladerf_set_correction(brf->dev,BLADERF_MODULE_TX,BLADERF_CORR_FPGA_PHASE,offphaseold);
trx_brf_write(device,ptimestamp+5*RXDCLENGTH, (void **)&calib_tx_buffp, RXDCLENGTH, 0,0); for (i=0; i<10; i++) {
} trx_brf_read(device, &ptimestamp, (void **)&calib_buffp, RXDCLENGTH, 0);
// project on -3fs/8 (Image of TX signal in +ve frequencies) trx_brf_write(device,ptimestamp+5*RXDCLENGTH, (void **)&calib_tx_buffp, RXDCLENGTH, 0, 0);
for (meanIold=meanQold=i=j=0;i<RXDCLENGTH;i++) { }
meanIold+= (calib_buff[j]*cos_3fsover8[i&7] - calib_buff[j+1]*cos_3fsover8[(i+2)&7])>>11; // project on fs/8 (Image of TX signal in +ve frequencies)
meanQold+= (calib_buff[j]*cos_3fsover8[(i+2)&7] + calib_buff[j+1]*cos_3fsover8[i&7])>>11; for (meanIold=meanQold=i=j=0; i<RXDCLENGTH; i++) {
j+=2; meanIold+= (calib_buff[j]*cos_fsover8[i&7] - calib_buff[j+1]*cos_fsover8[(i+2)&7])>>11;
} meanQold+= (calib_buff[j]*cos_fsover8[(i+2)&7] + calib_buff[j+1]*cos_fsover8[i&7])>>11;
j+=2;
meanIold/=RXDCLENGTH; }
meanQold/=RXDCLENGTH;
printf("[BRF] RX IQ (offgain): %d => (%d,%d)\n",offgainold,meanIold,meanQold); meanIold/=RXDCLENGTH;
meanQold/=RXDCLENGTH;
offgain=-4096; printf("[BRF] TX IQ (offphase): %d => (%d,%d)\n",offphaseold,meanIold,meanQold);
bladerf_set_correction(brf->dev,BLADERF_MODULE_RX,BLADERF_CORR_FPGA_GAIN,offgain);
for (i=0;i<10;i++) { offphase=-4096;
trx_brf_read(device, &ptimestamp, (void **)&calib_buffp, RXDCLENGTH, 0); bladerf_set_correction(brf->dev,BLADERF_MODULE_TX,BLADERF_CORR_FPGA_PHASE,offphase);
trx_brf_write(device,ptimestamp+5*RXDCLENGTH, (void **)&calib_tx_buffp, RXDCLENGTH, 0, 0); for (i=0; i<10; i++) {
} trx_brf_read(device, &ptimestamp, (void **)&calib_buffp, RXDCLENGTH, 0);
// project on 3fs/8 (Image of TX signal in -ve frequencies) trx_brf_write(device,ptimestamp+5*RXDCLENGTH, (void **)&calib_tx_buffp, RXDCLENGTH, 0, 0);
for (meanI=meanQ=i=j=0;i<RXDCLENGTH;i++) { }
meanI+= (calib_buff[j]*cos_3fsover8[i&7] - calib_buff[j+1]*cos_3fsover8[(i+2)&7])>>11; // project on fs/8 (Image of TX signal in +ve frequencies)
meanQ+= (calib_buff[j]*cos_3fsover8[(i+2)&7] + calib_buff[j+1]*cos_3fsover8[i&7])>>11; for (meanI=meanQ=i=j=0; i<RXDCLENGTH; i++) {
j+=2; meanI+= (calib_buff[j]*cos_fsover8[i&7] - calib_buff[j+1]*cos_fsover8[(i+2)&7])>>11;
meanQ+= (calib_buff[j]*cos_fsover8[(i+2)&7] + calib_buff[j+1]*cos_fsover8[i&7])>>11;
j+=2;
}
meanI/=RXDCLENGTH;
meanQ/=RXDCLENGTH;
printf("[BRF] TX IQ (offphase): %d => (%d,%d)\n",offphase,meanI,meanQ);
cnt=0;
while (cnt++ < 13) {
offphasenew=(offphaseold+offphase)>>1;
printf("[BRF] TX IQ (offphase): ([%d,%d]) => %d : %d\n",offphaseold,offphase,offphasenew,meanI*meanI+meanQ*meanQ);
if (meanI*meanI+meanQ*meanQ < meanIold*meanIold +meanQold*meanQold) {
meanIold = meanI;
meanQold = meanQ;
offphaseold = offphase;
}
offphase = offphasenew;
bladerf_set_correction(brf->dev,BLADERF_MODULE_TX,BLADERF_CORR_FPGA_PHASE,offphase);
for (i=0; i<10; i++) {
trx_brf_read(device, &ptimestamp, (void **)&calib_buffp, RXDCLENGTH, 0);
trx_brf_write(device,ptimestamp+5*RXDCLENGTH, (void **)&calib_tx_buffp, RXDCLENGTH, 0, 0);
}
// project on fs/8 (Image of TX signal in +ve frequencies)
for (meanI=meanQ=i=j=0; i<RXDCLENGTH; i++) {
meanI+= (calib_buff[j]*cos_fsover8[i&7] - calib_buff[j+1]*cos_fsover8[(i+2)&7])>>11;
meanQ+= (calib_buff[j]*cos_fsover8[(i+2)&7] + calib_buff[j+1]*cos_fsover8[i&7])>>11;
j+=2;
}
meanI/=RXDCLENGTH;
meanQ/=RXDCLENGTH;
// printf("[BRF] TX DC (offQ): %d => (%d,%d)\n",offQ,meanI,meanQ);
}
printf("[BRF] TX IQ offphase: %d => (%d,%d)\n",offphaseold,meanIold,meanQold);
bladerf_set_correction(brf->dev,BLADERF_MODULE_TX,BLADERF_CORR_FPGA_PHASE,offphaseold);
offgainold=4096;
bladerf_set_correction(brf->dev,BLADERF_MODULE_TX,BLADERF_CORR_FPGA_GAIN,offgainold);
for (i=0; i<10; i++) {
trx_brf_read(device, &ptimestamp, (void **)&calib_buffp, RXDCLENGTH, 0);
trx_brf_write(device,ptimestamp+5*RXDCLENGTH, (void **)&calib_tx_buffp, RXDCLENGTH, 0, 0);
}
// project on fs/8 (Image of TX signal in +ve frequencies)
for (meanIold=meanQold=i=j=0; i<RXDCLENGTH; i++) {
meanIold+= (calib_buff[j]*cos_fsover8[i&7] - calib_buff[j+1]*cos_fsover8[(i+2)&7])>>11;
meanQold+= (calib_buff[j]*cos_fsover8[(i+2)&7] + calib_buff[j+1]*cos_fsover8[i&7])>>11;
j+=2;
}
meanIold/=RXDCLENGTH;
meanQold/=RXDCLENGTH;
printf("[BRF] TX IQ (offgain): %d => (%d,%d)\n",offgainold,meanIold,meanQold);
offgain=-4096;
bladerf_set_correction(brf->dev,BLADERF_MODULE_TX,BLADERF_CORR_FPGA_GAIN,offgain);
for (i=0; i<10; i++) {
trx_brf_read(device, &ptimestamp, (void **)&calib_buffp, RXDCLENGTH, 0);
trx_brf_write(device,ptimestamp+5*RXDCLENGTH, (void **)&calib_tx_buffp, RXDCLENGTH, 0, 0);
}
// project on fs/8 (Image of TX signal in +ve frequencies)
for (meanI=meanQ=i=j=0; i<RXDCLENGTH; i++) {
meanI+= (calib_buff[j]*cos_fsover8[i&7] - calib_buff[j+1]*cos_fsover8[(i+2)&7])>>11;
meanQ+= (calib_buff[j]*cos_fsover8[(i+2)&7] + calib_buff[j+1]*cos_fsover8[i&7])>>11;
j+=2;
}
meanI/=RXDCLENGTH;
meanQ/=RXDCLENGTH;
printf("[BRF] TX IQ (offgain): %d => (%d,%d)\n",offgain,meanI,meanQ);
cnt=0;
while (cnt++ < 13) {
offgainnew=(offgainold+offgain)>>1;
if (meanI*meanI+meanQ*meanQ < meanIold*meanIold +meanQold*meanQold) {
printf("[BRF] TX IQ (offgain): ([%d,%d]) => %d : %d\n",offgainold,offgain,offgainnew,meanI*meanI+meanQ*meanQ);
meanIold = meanI;
meanQold = meanQ;
offgainold = offgain;
}
offgain = offgainnew;
bladerf_set_correction(brf->dev,BLADERF_MODULE_TX,BLADERF_CORR_FPGA_GAIN,offgain);
for (i=0; i<10; i++) {
trx_brf_read(device, &ptimestamp, (void **)&calib_buffp, RXDCLENGTH, 0);
trx_brf_write(device,ptimestamp+5*RXDCLENGTH, (void **)&calib_tx_buffp, RXDCLENGTH, 0, 0);
}
// project on fs/8 (Image of TX signal in +ve frequencies)
for (meanI=meanQ=i=j=0; i<RXDCLENGTH; i++) {
meanI+= (calib_buff[j]*cos_fsover8[i&7] - calib_buff[j+1]*cos_fsover8[(i+2)&7])>>11;
meanQ+= (calib_buff[j]*cos_fsover8[(i+2)&7] + calib_buff[j+1]*cos_fsover8[i&7])>>11;
j+=2;
}
meanI/=RXDCLENGTH;
meanQ/=RXDCLENGTH;
// printf("[BRF] TX DC (offQ): %d => (%d,%d)\n",offQ,meanI,meanQ);
}
printf("[BRF] TX IQ offgain: %d => (%d,%d)\n",offgainold,meanIold,meanQold);
bladerf_set_correction(brf->dev,BLADERF_MODULE_TX,BLADERF_CORR_FPGA_GAIN,offgainold);
} }
meanI/=RXDCLENGTH; // RX IQ imbalance
meanQ/=RXDCLENGTH; for (loop=0; loop<2; loop++) {
printf("[BRF] RX IQ (offgain): %d => (%d,%d)\n",offgain,meanI,meanQ); offphaseold=4096;
bladerf_set_correction(brf->dev,BLADERF_MODULE_RX,BLADERF_CORR_FPGA_PHASE,offphaseold);
cnt=0; for (i=0; i<10; i++) {
while (cnt++ < 13) { trx_brf_read(device, &ptimestamp, (void **)&calib_buffp, RXDCLENGTH, 0);
trx_brf_write(device,ptimestamp+5*RXDCLENGTH, (void **)&calib_tx_buffp, RXDCLENGTH, 0, 0);
offgainnew=(offgainold+offgain)>>1; }
if (meanI*meanI+meanQ*meanQ < meanIold*meanIold +meanQold*meanQold) { // project on -3fs/8 (Image of TX signal in -ve frequencies)
printf("[BRF] RX IQ (offgain): ([%d,%d]) => %d : %d\n",offgainold,offgain,offgainnew,meanI*meanI+meanQ*meanQ); for (meanIold=meanQold=i=j=0; i<RXDCLENGTH; i++) {
meanIold+= (calib_buff[j]*cos_3fsover8[i&7] - calib_buff[j+1]*cos_3fsover8[(i+2)&7])>>11;
meanIold = meanI; meanQold+= (calib_buff[j]*cos_3fsover8[(i+2)&7] + calib_buff[j+1]*cos_3fsover8[i&7])>>11;
meanQold = meanQ; j+=2;
offgainold = offgain; }
}
offgain = offgainnew; meanIold/=RXDCLENGTH;
bladerf_set_correction(brf->dev,BLADERF_MODULE_RX,BLADERF_CORR_FPGA_GAIN,offgain); meanQold/=RXDCLENGTH;
printf("[BRF] RX IQ (offphase): %d => (%d,%d)\n",offphaseold,meanIold,meanQold);
for (i=0;i<10;i++) {
trx_brf_read(device, &ptimestamp, (void **)&calib_buffp, RXDCLENGTH, 0); offphase=-4096;
trx_brf_write(device,ptimestamp+5*RXDCLENGTH, (void **)&calib_tx_buffp, RXDCLENGTH, 0, 0); bladerf_set_correction(brf->dev,BLADERF_MODULE_RX,BLADERF_CORR_FPGA_PHASE,offphase);
} for (i=0; i<10; i++) {
// project on -3fs/8 (Image of TX signal in -ve frequencies) trx_brf_read(device, &ptimestamp, (void **)&calib_buffp, RXDCLENGTH, 0);
for (meanI=meanQ=i=j=0;i<RXDCLENGTH;i++) { trx_brf_write(device,ptimestamp+5*RXDCLENGTH, (void **)&calib_tx_buffp, RXDCLENGTH, 0, 0);
meanI+= (calib_buff[j]*cos_3fsover8[i&7] - calib_buff[j+1]*cos_3fsover8[(i+2)&7])>>11; }
meanQ+= (calib_buff[j]*cos_3fsover8[(i+2)&7] + calib_buff[j+1]*cos_3fsover8[i&7])>>11; // project on -3fs/8 (Image of TX signal in -ve frequencies)
j+=2; for (meanI=meanQ=i=j=0; i<RXDCLENGTH; i++) {
} meanI+= (calib_buff[j]*cos_3fsover8[i&7] - calib_buff[j+1]*cos_3fsover8[(i+2)&7])>>11;
meanI/=RXDCLENGTH; meanQ+= (calib_buff[j]*cos_3fsover8[(i+2)&7] + calib_buff[j+1]*cos_3fsover8[i&7])>>11;
meanQ/=RXDCLENGTH; j+=2;
}
// printf("[BRF] TX DC (offQ): %d => (%d,%d)\n",offQ,meanI,meanQ);
meanI/=RXDCLENGTH;
meanQ/=RXDCLENGTH;
printf("[BRF] RX IQ (offphase): %d => (%d,%d)\n",offphase,meanI,meanQ);
cnt=0;
while (cnt++ < 13) {
offphasenew=(offphaseold+offphase)>>1;
printf("[BRF] RX IQ (offphase): ([%d,%d]) => %d : %d\n",offphaseold,offphase,offphasenew,meanI*meanI+meanQ*meanQ);
if (meanI*meanI+meanQ*meanQ < meanIold*meanIold +meanQold*meanQold) {
meanIold = meanI;
meanQold = meanQ;
offphaseold = offphase;
}
offphase = offphasenew;
bladerf_set_correction(brf->dev,BLADERF_MODULE_RX,BLADERF_CORR_FPGA_PHASE,offphase);
for (i=0; i<10; i++) {
trx_brf_read(device, &ptimestamp, (void **)&calib_buffp, RXDCLENGTH, 0);
trx_brf_write(device,ptimestamp+5*RXDCLENGTH, (void **)&calib_tx_buffp, RXDCLENGTH, 0, 0);
}
// project on -3fs/8 (Image of TX signal in -ve frequencies)
for (meanI=meanQ=i=j=0; i<RXDCLENGTH; i++) {
meanI+= (calib_buff[j]*cos_3fsover8[i&7] - calib_buff[j+1]*cos_3fsover8[(i+2)&7])>>11;
meanQ+= (calib_buff[j]*cos_3fsover8[(i+2)&7] + calib_buff[j+1]*cos_3fsover8[i&7])>>11;
j+=2;
}
meanI/=RXDCLENGTH;
meanQ/=RXDCLENGTH;
// printf("[BRF] TX DC (offQ): %d => (%d,%d)\n",offQ,meanI,meanQ);
}
printf("[BRF] RX IQ offphase: %d => (%d,%d)\n",offphaseold,meanIold,meanQold);
bladerf_set_correction(brf->dev,BLADERF_MODULE_RX,BLADERF_CORR_FPGA_PHASE,offphaseold);
offgainold=4096;
bladerf_set_correction(brf->dev,BLADERF_MODULE_RX,BLADERF_CORR_FPGA_GAIN,offgainold);
for (i=0; i<10; i++) {
trx_brf_read(device, &ptimestamp, (void **)&calib_buffp, RXDCLENGTH, 0);
trx_brf_write(device,ptimestamp+5*RXDCLENGTH, (void **)&calib_tx_buffp, RXDCLENGTH, 0,0);
}
// project on -3fs/8 (Image of TX signal in +ve frequencies)
for (meanIold=meanQold=i=j=0; i<RXDCLENGTH; i++) {
meanIold+= (calib_buff[j]*cos_3fsover8[i&7] - calib_buff[j+1]*cos_3fsover8[(i+2)&7])>>11;
meanQold+= (calib_buff[j]*cos_3fsover8[(i+2)&7] + calib_buff[j+1]*cos_3fsover8[i&7])>>11;
j+=2;
}
meanIold/=RXDCLENGTH;
meanQold/=RXDCLENGTH;
printf("[BRF] RX IQ (offgain): %d => (%d,%d)\n",offgainold,meanIold,meanQold);
offgain=-4096;
bladerf_set_correction(brf->dev,BLADERF_MODULE_RX,BLADERF_CORR_FPGA_GAIN,offgain);
for (i=0; i<10; i++) {
trx_brf_read(device, &ptimestamp, (void **)&calib_buffp, RXDCLENGTH, 0);
trx_brf_write(device,ptimestamp+5*RXDCLENGTH, (void **)&calib_tx_buffp, RXDCLENGTH, 0, 0);
}
// project on 3fs/8 (Image of TX signal in -ve frequencies)
for (meanI=meanQ=i=j=0; i<RXDCLENGTH; i++) {
meanI+= (calib_buff[j]*cos_3fsover8[i&7] - calib_buff[j+1]*cos_3fsover8[(i+2)&7])>>11;
meanQ+= (calib_buff[j]*cos_3fsover8[(i+2)&7] + calib_buff[j+1]*cos_3fsover8[i&7])>>11;
j+=2;
}
meanI/=RXDCLENGTH;
meanQ/=RXDCLENGTH;
printf("[BRF] RX IQ (offgain): %d => (%d,%d)\n",offgain,meanI,meanQ);
cnt=0;
while (cnt++ < 13) {
offgainnew=(offgainold+offgain)>>1;
if (meanI*meanI+meanQ*meanQ < meanIold*meanIold +meanQold*meanQold) {
printf("[BRF] RX IQ (offgain): ([%d,%d]) => %d : %d\n",offgainold,offgain,offgainnew,meanI*meanI+meanQ*meanQ);
meanIold = meanI;
meanQold = meanQ;
offgainold = offgain;
}
offgain = offgainnew;
bladerf_set_correction(brf->dev,BLADERF_MODULE_RX,BLADERF_CORR_FPGA_GAIN,offgain);
for (i=0; i<10; i++) {
trx_brf_read(device, &ptimestamp, (void **)&calib_buffp, RXDCLENGTH, 0);
trx_brf_write(device,ptimestamp+5*RXDCLENGTH, (void **)&calib_tx_buffp, RXDCLENGTH, 0, 0);
}
// project on -3fs/8 (Image of TX signal in -ve frequencies)
for (meanI=meanQ=i=j=0; i<RXDCLENGTH; i++) {
meanI+= (calib_buff[j]*cos_3fsover8[i&7] - calib_buff[j+1]*cos_3fsover8[(i+2)&7])>>11;
meanQ+= (calib_buff[j]*cos_3fsover8[(i+2)&7] + calib_buff[j+1]*cos_3fsover8[i&7])>>11;
j+=2;
}
meanI/=RXDCLENGTH;
meanQ/=RXDCLENGTH;
// printf("[BRF] TX DC (offQ): %d => (%d,%d)\n",offQ,meanI,meanQ);
}
printf("[BRF] RX IQ offgain: %d => (%d,%d)\n",offgainold,meanIold,meanQold);
bladerf_set_correction(brf->dev,BLADERF_MODULE_RX,BLADERF_CORR_FPGA_GAIN,offgainold);
} }
printf("[BRF] RX IQ offgain: %d => (%d,%d)\n",offgainold,meanIold,meanQold); bladerf_set_frequency(brf->dev,BLADERF_MODULE_TX, (unsigned int) device->openair0_cfg->tx_freq[0]);
bladerf_set_loopback(brf->dev,BLADERF_LB_NONE);
bladerf_set_correction(brf->dev,BLADERF_MODULE_RX,BLADERF_CORR_FPGA_GAIN,offgainold); bladerf_set_gain(brf->dev, BLADERF_MODULE_RX, (unsigned int) device->openair0_cfg->rx_gain[0]-device->openair0_cfg[0].rx_gain_offset[0]);
} bladerf_set_gain(brf->dev, BLADERF_MODULE_TX, (unsigned int) device->openair0_cfg->tx_gain[0]);
// LOG_M("blade_rf_test.m","rxs",calib_buff,RXDCLENGTH,1,1);
bladerf_set_frequency(brf->dev,BLADERF_MODULE_TX, (unsigned int) device->openair0_cfg->tx_freq[0]);
bladerf_set_loopback(brf->dev,BLADERF_LB_NONE);
bladerf_set_gain(brf->dev, BLADERF_MODULE_RX, (unsigned int) device->openair0_cfg->rx_gain[0]-device->openair0_cfg[0].rx_gain_offset[0]);
bladerf_set_gain(brf->dev, BLADERF_MODULE_TX, (unsigned int) device->openair0_cfg->tx_gain[0]);
// LOG_M("blade_rf_test.m","rxs",calib_buff,RXDCLENGTH,1,1);
} }
/*! \brief Initialize Openair BLADERF target. It returns 0 if OK /*! \brief Initialize Openair BLADERF target. It returns 0 if OK
* \param device the hardware to use * \param device the hardware to use
* \param openair0_cfg RF frontend parameters set by application * \param openair0_cfg RF frontend parameters set by application
* \returns 0 on success * \returns 0 on success
*/ */
int device_init(openair0_device *device, openair0_config_t *openair0_cfg) { int device_init(openair0_device *device, openair0_config_t *openair0_cfg) {
int status; int status;
brf_state_t *brf = (brf_state_t*)malloc(sizeof(brf_state_t)); brf_state_t *brf = (brf_state_t*)malloc(sizeof(brf_state_t));
memset(brf, 0, sizeof(brf_state_t)); memset(brf, 0, sizeof(brf_state_t));
/* device specific */ /* device specific */
//openair0_cfg->txlaunch_wait = 1;//manage when TX processing is triggered //openair0_cfg->txlaunch_wait = 1;//manage when TX processing is triggered
//openair0_cfg->txlaunch_wait_slotcount = 1; //manage when TX processing is triggered //openair0_cfg->txlaunch_wait_slotcount = 1; //manage when TX processing is triggered
openair0_cfg->iq_txshift = 0;// shift openair0_cfg->iq_txshift = 0;// shift
openair0_cfg->iq_rxrescale = 15;//rescale iqs openair0_cfg->iq_rxrescale = 15;//rescale iqs
// init required params // init required params
switch ((int)openair0_cfg->sample_rate) { switch ((int)openair0_cfg->sample_rate) {
case 30720000: case 30720000:
openair0_cfg->samples_per_packet = 2048; openair0_cfg->samples_per_packet = 2048;
openair0_cfg->tx_sample_advance = 0; openair0_cfg->tx_sample_advance = 0;
break; break;
case 15360000: case 15360000:
openair0_cfg->samples_per_packet = 2048; openair0_cfg->samples_per_packet = 2048;
openair0_cfg->tx_sample_advance = 0; openair0_cfg->tx_sample_advance = 0;
break; break;
case 7680000: case 7680000:
openair0_cfg->samples_per_packet = 1024; openair0_cfg->samples_per_packet = 1024;
openair0_cfg->tx_sample_advance = 0; openair0_cfg->tx_sample_advance = 0;
break; break;
case 1920000: case 1920000:
openair0_cfg->samples_per_packet = 256; openair0_cfg->samples_per_packet = 256;
openair0_cfg->tx_sample_advance = 50; openair0_cfg->tx_sample_advance = 50;
break; break;
default: default:
printf("Error: unknown sampling rate %f\n",openair0_cfg->sample_rate); printf("Error: unknown sampling rate %f\n",openair0_cfg->sample_rate);
exit(-1); exit(-1);
break; break;
} }
openair0_cfg->iq_txshift= 0; openair0_cfg->iq_txshift= 0;
openair0_cfg->iq_rxrescale = 15; /*not sure*/ openair0_cfg->iq_rxrescale = 15; /*not sure*/
openair0_cfg->rx_gain_calib_table = calib_table_fx4; openair0_cfg->rx_gain_calib_table = calib_table_fx4;
// The number of buffers to use in the underlying data stream // The number of buffers to use in the underlying data stream
brf->num_buffers = 128; brf->num_buffers = 128;
// the size of the underlying stream buffers, in samples // the size of the underlying stream buffers, in samples
brf->buffer_size = (unsigned int) openair0_cfg->samples_per_packet;//*sizeof(int32_t); // buffer size = 4096 for sample_len of 1024 brf->buffer_size = (unsigned int) openair0_cfg->samples_per_packet;//*sizeof(int32_t); // buffer size = 4096 for sample_len of 1024
brf->num_transfers = 16; brf->num_transfers = 16;
brf->rx_timeout_ms = 0; brf->rx_timeout_ms = 0;
brf->tx_timeout_ms = 0; brf->tx_timeout_ms = 0;
brf->sample_rate=(unsigned int)openair0_cfg->sample_rate; brf->sample_rate=(unsigned int)openair0_cfg->sample_rate;
memset(&brf->meta_rx, 0, sizeof(brf->meta_rx)); memset(&brf->meta_rx, 0, sizeof(brf->meta_rx));
memset(&brf->meta_tx, 0, sizeof(brf->meta_tx)); memset(&brf->meta_tx, 0, sizeof(brf->meta_tx));
printf("\n[BRF] sampling_rate %d, num_buffers %d, buffer_size %d, num transfer %d, timeout_ms (rx %d, tx %d)\n", printf("\n[BRF] sampling_rate %u, num_buffers %u, buffer_size %u, num transfer %u, timeout_ms (rx %u, tx %u)\n",
brf->sample_rate, brf->num_buffers, brf->buffer_size,brf->num_transfers, brf->rx_timeout_ms, brf->tx_timeout_ms); brf->sample_rate, brf->num_buffers, brf->buffer_size,brf->num_transfers, brf->rx_timeout_ms, brf->tx_timeout_ms);
if ((status=bladerf_open(&brf->dev, "")) != 0 ) { if ((status=bladerf_open(&brf->dev, "")) != 0 ) {
fprintf(stderr,"Failed to open brf device: %s\n",bladerf_strerror(status)); fprintf(stderr,"Failed to open brf device: %s\n",bladerf_strerror(status));
brf_error(status); brf_error(status);
} }
printf("[BRF] init dev %p\n", brf->dev); printf("[BRF] init dev %p\n", brf->dev);
switch(bladerf_device_speed(brf->dev)){ switch(bladerf_device_speed(brf->dev)) {
case BLADERF_DEVICE_SPEED_SUPER: case BLADERF_DEVICE_SPEED_SUPER:
printf("[BRF] Device operates at max speed\n"); printf("[BRF] Device operates at max speed\n");
break; break;
default: default:
printf("[BRF] Device does not operates at max speed, change the USB port\n"); printf("[BRF] Device does not operates at max speed, change the USB port\n");
brf_error(BLADERF_ERR_UNSUPPORTED); brf_error(BLADERF_ERR_UNSUPPORTED);
} }
// RX // RX
// Example of CLI output: RX Frequency: 2539999999Hz // Example of CLI output: RX Frequency: 2539999999Hz
if ((status=bladerf_set_gain_mode(brf->dev, BLADERF_MODULE_RX, BLADERF_GAIN_MGC))) { if ((status=bladerf_set_gain_mode(brf->dev, BLADERF_MODULE_RX, BLADERF_GAIN_MGC))) {
fprintf(stderr, "[BRF] Failed to disable AGC\n"); fprintf(stderr, "[BRF] Failed to disable AGC\n");
brf_error(status); brf_error(status);
} }
if ((status=bladerf_set_frequency(brf->dev, BLADERF_MODULE_RX, (unsigned int) openair0_cfg->rx_freq[0])) != 0){ if ((status=bladerf_set_frequency(brf->dev, BLADERF_MODULE_RX, (unsigned int) openair0_cfg->rx_freq[0])) != 0) {
fprintf(stderr,"Failed to set RX frequency: %s\n",bladerf_strerror(status)); fprintf(stderr,"Failed to set RX frequency: %s\n",bladerf_strerror(status));
brf_error(status); brf_error(status);
} else } else
printf("[BRF] set RX frequency to %u\n",(unsigned int)openair0_cfg->rx_freq[0]); printf("[BRF] set RX frequency to %u\n",(unsigned int)openair0_cfg->rx_freq[0]);
unsigned int actual_value=0; unsigned int actual_value=0;
if ((status=bladerf_set_sample_rate(brf->dev, BLADERF_MODULE_RX, (unsigned int) openair0_cfg->sample_rate, &actual_value)) != 0){ if ((status=bladerf_set_sample_rate(brf->dev, BLADERF_MODULE_RX, (unsigned int) openair0_cfg->sample_rate, &actual_value)) != 0) {
fprintf(stderr,"Failed to set RX sample rate: %s\n", bladerf_strerror(status)); fprintf(stderr,"Failed to set RX sample rate: %s\n", bladerf_strerror(status));
brf_error(status); brf_error(status);
}else } else
printf("[BRF] set RX sample rate to %u, %u\n", (unsigned int) openair0_cfg->sample_rate, actual_value); printf("[BRF] set RX sample rate to %u, %u\n", (unsigned int) openair0_cfg->sample_rate, actual_value);
if ((status=bladerf_set_bandwidth(brf->dev, BLADERF_MODULE_RX, (unsigned int) openair0_cfg->rx_bw*2, &actual_value)) != 0){ if ((status=bladerf_set_bandwidth(brf->dev, BLADERF_MODULE_RX, (unsigned int) openair0_cfg->rx_bw*2, &actual_value)) != 0) {
fprintf(stderr,"Failed to set RX bandwidth: %s\n", bladerf_strerror(status)); fprintf(stderr,"Failed to set RX bandwidth: %s\n", bladerf_strerror(status));
brf_error(status); brf_error(status);
}else } else
printf("[BRF] set RX bandwidth to %u, %u\n",(unsigned int)openair0_cfg->rx_bw*2, actual_value); printf("[BRF] set RX bandwidth to %u, %u\n",(unsigned int)openair0_cfg->rx_bw*2, actual_value);
set_rx_gain_offset(&openair0_cfg[0],0); set_rx_gain_offset(&openair0_cfg[0],0);
if ((status=bladerf_set_gain(brf->dev, BLADERF_MODULE_RX, (int) openair0_cfg->rx_gain[0]-openair0_cfg[0].rx_gain_offset[0])) != 0) { if ((status=bladerf_set_gain(brf->dev, BLADERF_MODULE_RX, (int) openair0_cfg->rx_gain[0]-openair0_cfg[0].rx_gain_offset[0])) != 0) {
fprintf(stderr,"Failed to set RX gain: %s\n",bladerf_strerror(status)); fprintf(stderr,"Failed to set RX gain: %s\n",bladerf_strerror(status));
brf_error(status); brf_error(status);
} else } else
printf("[BRF] set RX gain to %d (%d)\n",(int)(openair0_cfg->rx_gain[0]-openair0_cfg[0].rx_gain_offset[0]),(int)openair0_cfg[0].rx_gain_offset[0]); printf("[BRF] set RX gain to %d (%d)\n",(int)(openair0_cfg->rx_gain[0]-openair0_cfg[0].rx_gain_offset[0]),(int)openair0_cfg[0].rx_gain_offset[0]);
// TX // TX
if ((status=bladerf_set_frequency(brf->dev, BLADERF_MODULE_TX, (unsigned int) openair0_cfg->tx_freq[0])) != 0){ if ((status=bladerf_set_frequency(brf->dev, BLADERF_MODULE_TX, (unsigned int) openair0_cfg->tx_freq[0])) != 0) {
fprintf(stderr,"Failed to set TX frequency: %s\n",bladerf_strerror(status)); fprintf(stderr,"Failed to set TX frequency: %s\n",bladerf_strerror(status));
brf_error(status); brf_error(status);
}else } else
printf("[BRF] set TX Frequency to %u\n", (unsigned int) openair0_cfg->tx_freq[0]); printf("[BRF] set TX Frequency to %u\n", (unsigned int) openair0_cfg->tx_freq[0]);
if ((status=bladerf_set_sample_rate(brf->dev, BLADERF_MODULE_TX, (unsigned int) openair0_cfg->sample_rate, NULL)) != 0){ if ((status=bladerf_set_sample_rate(brf->dev, BLADERF_MODULE_TX, (unsigned int) openair0_cfg->sample_rate, NULL)) != 0) {
fprintf(stderr,"Failed to set TX sample rate: %s\n", bladerf_strerror(status)); fprintf(stderr,"Failed to set TX sample rate: %s\n", bladerf_strerror(status));
brf_error(status); brf_error(status);
}else } else
printf("[BRF] set TX sampling rate to %u \n", (unsigned int) openair0_cfg->sample_rate); printf("[BRF] set TX sampling rate to %u \n", (unsigned int) openair0_cfg->sample_rate);
if ((status=bladerf_set_bandwidth(brf->dev, BLADERF_MODULE_TX,(unsigned int)openair0_cfg->tx_bw*2, NULL)) != 0){ if ((status=bladerf_set_bandwidth(brf->dev, BLADERF_MODULE_TX,(unsigned int)openair0_cfg->tx_bw*2, NULL)) != 0) {
fprintf(stderr, "Failed to set TX bandwidth: %s\n", bladerf_strerror(status)); fprintf(stderr, "Failed to set TX bandwidth: %s\n", bladerf_strerror(status));
brf_error(status); brf_error(status);
}else } else
printf("[BRF] set TX bandwidth to %u \n", (unsigned int) openair0_cfg->tx_bw*2); printf("[BRF] set TX bandwidth to %u \n", (unsigned int) openair0_cfg->tx_bw*2);
if ((status=bladerf_set_gain(brf->dev, BLADERF_MODULE_TX, (int) openair0_cfg->tx_gain[0])) != 0) { if ((status=bladerf_set_gain(brf->dev, BLADERF_MODULE_TX, (int) openair0_cfg->tx_gain[0])) != 0) {
fprintf(stderr,"Failed to set TX gain: %s\n",bladerf_strerror(status)); fprintf(stderr,"Failed to set TX gain: %s\n",bladerf_strerror(status));
brf_error(status); brf_error(status);
}else } else
printf("[BRF] set the TX gain to %d\n", (int)openair0_cfg->tx_gain[0]); printf("[BRF] set the TX gain to %d\n", (int)openair0_cfg->tx_gain[0]);
/* Configure the device's TX module for use with the sync interface. /* Configure the device's TX module for use with the sync interface.
* SC16 Q11 samples *with* metadata are used. */ * SC16 Q11 samples *with* metadata are used. */
if ((status=bladerf_sync_config(brf->dev, BLADERF_MODULE_TX,BLADERF_FORMAT_SC16_Q11_META,brf->num_buffers,brf->buffer_size,brf->num_transfers,brf->tx_timeout_ms)) != 0 ) { if ((status=bladerf_sync_config(brf->dev, BLADERF_MODULE_TX,BLADERF_FORMAT_SC16_Q11_META,brf->num_buffers,brf->buffer_size,brf->num_transfers,brf->tx_timeout_ms)) != 0 ) {
fprintf(stderr,"Failed to configure TX sync interface: %s\n", bladerf_strerror(status)); fprintf(stderr,"Failed to configure TX sync interface: %s\n", bladerf_strerror(status));
brf_error(status); brf_error(status);
}else } else
printf("[BRF] configured TX sync interface \n"); printf("[BRF] configured TX sync interface \n");
/* Configure the device's RX module for use with the sync interface. /* Configure the device's RX module for use with the sync interface.
* SC16 Q11 samples *with* metadata are used. */ * SC16 Q11 samples *with* metadata are used. */
if ((status=bladerf_sync_config(brf->dev, BLADERF_MODULE_RX, BLADERF_FORMAT_SC16_Q11_META,brf->num_buffers,brf->buffer_size,brf->num_transfers,brf->rx_timeout_ms)) != 0 ) { if ((status=bladerf_sync_config(brf->dev, BLADERF_MODULE_RX, BLADERF_FORMAT_SC16_Q11_META,brf->num_buffers,brf->buffer_size,brf->num_transfers,brf->rx_timeout_ms)) != 0 ) {
fprintf(stderr,"Failed to configure RX sync interface: %s\n", bladerf_strerror(status)); fprintf(stderr,"Failed to configure RX sync interface: %s\n", bladerf_strerror(status));
brf_error(status); brf_error(status);
}else } else
printf("[BRF] configured Rx sync interface \n"); printf("[BRF] configured Rx sync interface \n");
/* We must always enable the TX module after calling bladerf_sync_config(), and /* We must always enable the TX module after calling bladerf_sync_config(), and
* before attempting to TX samples via bladerf_sync_tx(). */ * before attempting to TX samples via bladerf_sync_tx(). */
if ((status=bladerf_enable_module(brf->dev, BLADERF_MODULE_TX, true)) != 0) { if ((status=bladerf_enable_module(brf->dev, BLADERF_MODULE_TX, true)) != 0) {
fprintf(stderr,"Failed to enable TX module: %s\n", bladerf_strerror(status)); fprintf(stderr,"Failed to enable TX module: %s\n", bladerf_strerror(status));
brf_error(status); brf_error(status);
} else } else
printf("[BRF] TX module enabled \n"); printf("[BRF] TX module enabled \n");
/* We must always enable the RX module after calling bladerf_sync_config(), and /* We must always enable the RX module after calling bladerf_sync_config(), and
* before attempting to RX samples via bladerf_sync_rx(). */ * before attempting to RX samples via bladerf_sync_rx(). */
if ((status=bladerf_enable_module(brf->dev, BLADERF_MODULE_RX, true)) != 0) { if ((status=bladerf_enable_module(brf->dev, BLADERF_MODULE_RX, true)) != 0) {
fprintf(stderr,"Failed to enable RX module: %s\n", bladerf_strerror(status)); fprintf(stderr,"Failed to enable RX module: %s\n", bladerf_strerror(status));
brf_error(status); brf_error(status);
}else } else
printf("[BRF] RX module enabled \n"); printf("[BRF] RX module enabled \n");
// calibrate // calibrate
if ((status=bladerf_calibrate_dc(brf->dev, BLADERF_DC_CAL_LPF_TUNING)) != 0 || if ((status=bladerf_calibrate_dc(brf->dev, BLADERF_DC_CAL_LPF_TUNING)) != 0 ||
(status=bladerf_calibrate_dc(brf->dev, BLADERF_DC_CAL_TX_LPF)) != 0 || (status=bladerf_calibrate_dc(brf->dev, BLADERF_DC_CAL_TX_LPF)) != 0 ||
(status=bladerf_calibrate_dc(brf->dev, BLADERF_DC_CAL_RX_LPF)) != 0 || (status=bladerf_calibrate_dc(brf->dev, BLADERF_DC_CAL_RX_LPF)) != 0 ||
(status=bladerf_calibrate_dc(brf->dev, BLADERF_DC_CAL_RXVGA2)) != 0) { (status=bladerf_calibrate_dc(brf->dev, BLADERF_DC_CAL_RXVGA2)) != 0) {
fprintf(stderr, "[BRF] error calibrating\n"); fprintf(stderr, "[BRF] error calibrating\n");
brf_error(status); brf_error(status);
} else } else
printf("[BRF] calibration OK\n"); printf("[BRF] calibration OK\n");
bladerf_log_set_verbosity(get_brf_log_level(openair0_cfg->log_level)); bladerf_log_set_verbosity(get_brf_log_level(openair0_cfg->log_level));
printf("BLADERF: Initializing openair0_device\n"); printf("BLADERF: Initializing openair0_device\n");
device->Mod_id = num_devices++; device->Mod_id = num_devices++;
device->type = BLADERF_DEV; device->type = BLADERF_DEV;
device->trx_start_func = trx_brf_start; device->trx_start_func = trx_brf_start;
device->trx_end_func = trx_brf_end; device->trx_end_func = trx_brf_end;
device->trx_read_func = trx_brf_read; device->trx_read_func = trx_brf_read;
device->trx_write_func = trx_brf_write; device->trx_write_func = trx_brf_write;
device->trx_get_stats_func = trx_brf_get_stats; device->trx_get_stats_func = trx_brf_get_stats;
device->trx_reset_stats_func = trx_brf_reset_stats; device->trx_reset_stats_func = trx_brf_reset_stats;
device->trx_stop_func = trx_brf_stop; device->trx_stop_func = trx_brf_stop;
device->trx_set_freq_func = trx_brf_set_freq; device->trx_set_freq_func = trx_brf_set_freq;
device->trx_set_gains_func = trx_brf_set_gains; device->trx_set_gains_func = trx_brf_set_gains;
device->openair0_cfg = openair0_cfg; device->openair0_cfg = openair0_cfg;
device->priv = (void *)brf; device->priv = (void *)brf;
calibrate_rf(device); calibrate_rf(device);
// memcpy((void*)&device->openair0_cfg,(void*)&openair0_cfg[0],sizeof(openair0_config_t)); // memcpy((void*)&device->openair0_cfg,(void*)&openair0_cfg[0],sizeof(openair0_config_t));
if ((status=bladerf_enable_module(brf->dev, BLADERF_MODULE_TX, false)) != 0) { if ((status=bladerf_enable_module(brf->dev, BLADERF_MODULE_TX, false)) != 0) {
fprintf(stderr,"Failed to enable TX module: %s\n", bladerf_strerror(status)); fprintf(stderr,"Failed to enable TX module: %s\n", bladerf_strerror(status));
abort(); abort();
} }
if ((status=bladerf_enable_module(brf->dev, BLADERF_MODULE_RX, false)) != 0) { if ((status=bladerf_enable_module(brf->dev, BLADERF_MODULE_RX, false)) != 0) {
fprintf(stderr,"Failed to enable RX module: %s\n", bladerf_strerror(status)); fprintf(stderr,"Failed to enable RX module: %s\n", bladerf_strerror(status));
abort(); abort();
} }
return 0; return 0;
} }
/*! \brief bladeRF error report /*! \brief bladeRF error report
* \param status * \param status
* \returns 0 on success * \returns 0 on success
*/ */
int brf_error(int status) { int brf_error(int status) {
fprintf(stderr, "[BRF] brf_error: %s\n", bladerf_strerror(status)); fprintf(stderr, "[BRF] brf_error: %s\n", bladerf_strerror(status));
exit(-1); exit(-1);
return status; // or status error code return status; // or status error code
} }
...@@ -1153,61 +1154,61 @@ int brf_error(int status) { ...@@ -1153,61 +1154,61 @@ int brf_error(int status) {
*/ */
struct bladerf * open_bladerf_from_serial(const char *serial) { struct bladerf * open_bladerf_from_serial(const char *serial) {
int status; int status;
struct bladerf *dev; struct bladerf *dev;
struct bladerf_devinfo info; struct bladerf_devinfo info;
/* Initialize all fields to "don't care" wildcard values. /* Initialize all fields to "don't care" wildcard values.
* *
* Immediately passing this to bladerf_open_with_devinfo() would cause * Immediately passing this to bladerf_open_with_devinfo() would cause
* libbladeRF to open any device on any available backend. */ * libbladeRF to open any device on any available backend. */
bladerf_init_devinfo(&info); bladerf_init_devinfo(&info);
/* Specify the desired device's serial number, while leaving all other /* Specify the desired device's serial number, while leaving all other
* fields in the info structure wildcard values */ * fields in the info structure wildcard values */
strncpy(info.serial, serial, BLADERF_SERIAL_LENGTH - 1); strncpy(info.serial, serial, BLADERF_SERIAL_LENGTH - 1);
info.serial[BLADERF_SERIAL_LENGTH - 1] = '\0'; info.serial[BLADERF_SERIAL_LENGTH - 1] = '\0';
status = bladerf_open_with_devinfo(&dev, &info); status = bladerf_open_with_devinfo(&dev, &info);
if (status == BLADERF_ERR_NODEV) { if (status == BLADERF_ERR_NODEV) {
printf("No devices available with serial=%s\n", serial); printf("No devices available with serial=%s\n", serial);
return NULL; return NULL;
} else if (status != 0) { } else if (status != 0) {
fprintf(stderr, "Failed to open device with serial=%s (%s)\n", serial, bladerf_strerror(status)); fprintf(stderr, "Failed to open device with serial=%s (%s)\n", serial, bladerf_strerror(status));
return NULL; return NULL;
} else { } else {
return dev; return dev;
} }
} }
/*! \brief Get BladeRF log level /*! \brief Get BladeRF log level
* \param log_level log level * \param log_level log level
* \returns log level of BLADERF device * \returns log level of BLADERF device
*/ */
int get_brf_log_level(int log_level){ int get_brf_log_level(int log_level) {
int level=BLADERF_LOG_LEVEL_INFO; int level=BLADERF_LOG_LEVEL_INFO;
return BLADERF_LOG_LEVEL_INFO; return BLADERF_LOG_LEVEL_INFO;
switch(log_level) { switch(log_level) {
case LOG_DEBUG: case LOG_DEBUG:
level=BLADERF_LOG_LEVEL_DEBUG; level=BLADERF_LOG_LEVEL_DEBUG;
break; break;
case LOG_INFO: case LOG_INFO:
level= BLADERF_LOG_LEVEL_INFO; level= BLADERF_LOG_LEVEL_INFO;
break; break;
case LOG_WARNING: case LOG_WARNING:
level=BLADERF_LOG_LEVEL_WARNING; level=BLADERF_LOG_LEVEL_WARNING;
break; break;
case LOG_ERR: case LOG_ERR:
level=BLADERF_LOG_LEVEL_ERROR; level=BLADERF_LOG_LEVEL_ERROR;
break; break;
case LOG_CRIT: case LOG_CRIT:
level=BLADERF_LOG_LEVEL_CRITICAL; level=BLADERF_LOG_LEVEL_CRITICAL;
break; break;
case LOG_EMERG: case LOG_EMERG:
level = BLADERF_LOG_LEVEL_SILENT; level = BLADERF_LOG_LEVEL_SILENT;
break; break;
default: default:
break; break;
} }
return level; return level;
} }
/*@}*/ /*@}*/
...@@ -19,7 +19,7 @@ ...@@ -19,7 +19,7 @@
* contact@openairinterface.org * contact@openairinterface.org
*/ */
/*! \file ethernet_lib.c /*! \file ethernet_lib.c
* \brief API to stream I/Q samples over standard ethernet * \brief API to stream I/Q samples over standard ethernet
* \author add alcatel Katerina Trilyraki, Navid Nikaein, Pedro Dinis, Lucio Ferreira, Raymond Knopp * \author add alcatel Katerina Trilyraki, Navid Nikaein, Pedro Dinis, Lucio Ferreira, Raymond Knopp
* \date 2015 * \date 2015
...@@ -55,113 +55,113 @@ int dest_addr_len[MAX_INST]; ...@@ -55,113 +55,113 @@ int dest_addr_len[MAX_INST];
int trx_eth_start(openair0_device *device) { int trx_eth_start(openair0_device *device) {
eth_state_t *eth = (eth_state_t*)device->priv; eth_state_t *eth = (eth_state_t*)device->priv;
/* initialize socket */
if (eth->flags == ETH_RAW_MODE) {
printf("Setting ETHERNET to ETH_RAW_IF5_MODE\n");
if (eth_socket_init_raw(device)!=0) return -1;
/* RRU gets device configuration - RAU sets device configuration*/
printf("Setting Timenout to 999999 usecs\n"); /* initialize socket */
if(ethernet_tune (device,RCV_TIMEOUT,999999)!=0) return -1; if (eth->flags == ETH_RAW_MODE) {
printf("Setting ETHERNET to ETH_RAW_IF5_MODE\n");
if (eth_socket_init_raw(device)!=0) return -1;
/* RRU gets device configuration - RAU sets device configuration*/
/* printf("Setting Timenout to 999999 usecs\n");
if (device->host_type == RAU_HOST) { if(ethernet_tune (device,RCV_TIMEOUT,999999)!=0) return -1;
if(eth_set_dev_conf_raw(device)!=0) return -1;
} else {
if(eth_get_dev_conf_raw(device)!=0) return -1;
}*/
/* adjust MTU wrt number of samples per packet */ /*
if(eth->compression == ALAW_COMPRESS) { if (device->host_type == RAU_HOST) {
if(ethernet_tune (device,MTU_SIZE,RAW_PACKET_SIZE_BYTES_ALAW(device->openair0_cfg->samples_per_packet))!=0) return -1; if(eth_set_dev_conf_raw(device)!=0) return -1;
} else { } else {
if(ethernet_tune (device,MTU_SIZE,RAW_PACKET_SIZE_BYTES(device->openair0_cfg->samples_per_packet))!=0) return -1; if(eth_get_dev_conf_raw(device)!=0) return -1;
} }*/
if(ethernet_tune (device,RCV_TIMEOUT,999999)!=0) return -1;
} else if (eth->flags == ETH_RAW_IF4p5_MODE) {
printf("Setting ETHERNET to ETH_RAW_IF4p5_MODE\n"); /* adjust MTU wrt number of samples per packet */
if (eth_socket_init_raw(device)!=0) return -1; if(eth->compression == ALAW_COMPRESS) {
if(ethernet_tune (device,MTU_SIZE,RAW_PACKET_SIZE_BYTES_ALAW(device->openair0_cfg->samples_per_packet))!=0) return -1;
} else {
if(ethernet_tune (device,MTU_SIZE,RAW_PACKET_SIZE_BYTES(device->openair0_cfg->samples_per_packet))!=0) return -1;
}
if(ethernet_tune (device,RCV_TIMEOUT,999999)!=0) return -1;
} else if (eth->flags == ETH_RAW_IF4p5_MODE) {
printf("Setting Timenout to 999999 usecs\n"); printf("Setting ETHERNET to ETH_RAW_IF4p5_MODE\n");
if(ethernet_tune (device,RCV_TIMEOUT,999999)!=0) return -1; if (eth_socket_init_raw(device)!=0) return -1;
/* printf("Setting Timenout to 999999 usecs\n");
if (device->host_type == RAU_HOST) { if(ethernet_tune (device,RCV_TIMEOUT,999999)!=0) return -1;
if(eth_set_dev_conf_raw_IF4p5(device)!=0) return -1;
} else {
if(eth_get_dev_conf_raw_IF4p5(device)!=0) return -1;
}
*/
/* adjust MTU wrt number of samples per packet */ /*
if(ethernet_tune (device,MTU_SIZE,RAW_IF4p5_PRACH_SIZE_BYTES)!=0) return -1; if (device->host_type == RAU_HOST) {
if(eth_set_dev_conf_raw_IF4p5(device)!=0) return -1;
} else {
if(eth_get_dev_conf_raw_IF4p5(device)!=0) return -1;
}
*/
if(ethernet_tune (device,RCV_TIMEOUT,999999)!=0) return -1; /* adjust MTU wrt number of samples per packet */
} else if (eth->flags == ETH_UDP_IF4p5_MODE) { if(ethernet_tune (device,MTU_SIZE,RAW_IF4p5_PRACH_SIZE_BYTES)!=0) return -1;
printf("Setting ETHERNET to UDP_IF4p5_MODE\n");
if (eth_socket_init_udp(device)!=0) return -1;
printf("Setting Timeout to 999999 usecs\n"); if(ethernet_tune (device,RCV_TIMEOUT,999999)!=0) return -1;
if(ethernet_tune (device,RCV_TIMEOUT,999999)!=0) return -1; } else if (eth->flags == ETH_UDP_IF4p5_MODE) {
printf("Setting ETHERNET to UDP_IF4p5_MODE\n");
if (eth_socket_init_udp(device)!=0) return -1;
/* printf("Setting Timeout to 999999 usecs\n");
if (device->host_type == RAU_HOST) { if(ethernet_tune (device,RCV_TIMEOUT,999999)!=0) return -1;
if(eth_set_dev_conf_udp(device)!=0) return -1;
} else {
if(eth_get_dev_conf_udp(device)!=0) return -1;
}
*/
/* adjust MTU wrt number of samples per packet */ /*
if(ethernet_tune (device,MTU_SIZE,UDP_IF4p5_PRACH_SIZE_BYTES)!=0) return -1; if (device->host_type == RAU_HOST) {
if(eth_set_dev_conf_udp(device)!=0) return -1;
} else {
if(eth_get_dev_conf_udp(device)!=0) return -1;
}
*/
/* adjust MTU wrt number of samples per packet */
if(ethernet_tune (device,MTU_SIZE,UDP_IF4p5_PRACH_SIZE_BYTES)!=0) return -1;
} else if (eth->flags == ETH_RAW_IF5_MOBIPASS) {
printf("Setting ETHERNET to RAW_IF5_MODE\n");
if (eth_socket_init_raw(device)!=0) return -1;
if(ethernet_tune (device,RCV_TIMEOUT,999999)!=0) return -1;
} else {
printf("Setting ETHERNET to UDP_IF5_MODE\n");
if (eth_socket_init_udp(device)!=0) return -1;
/*
if (device->host_type == RAU_HOST) { } else if (eth->flags == ETH_RAW_IF5_MOBIPASS) {
if(eth_set_dev_conf_udp(device)!=0) return -1; printf("Setting ETHERNET to RAW_IF5_MODE\n");
if (eth_socket_init_raw(device)!=0) return -1;
if(ethernet_tune (device,RCV_TIMEOUT,999999)!=0) return -1;
} else { } else {
if(eth_get_dev_conf_udp(device)!=0) return -1; printf("Setting ETHERNET to UDP_IF5_MODE\n");
}*/ if (eth_socket_init_udp(device)!=0) return -1;
/*
if (device->host_type == RAU_HOST) {
if(eth_set_dev_conf_udp(device)!=0) return -1;
} else {
if(eth_get_dev_conf_udp(device)!=0) return -1;
}*/
/* adjust MTU wrt number of samples per packet */
if(ethernet_tune (device,MTU_SIZE,UDP_IF4p5_PRACH_SIZE_BYTES)!=0) return -1;
if(ethernet_tune (device,RCV_TIMEOUT,999999)!=0) return -1;
}
/* apply additional configuration */
if(ethernet_tune (device, SND_BUF_SIZE,2000000000)!=0) return -1;
if(ethernet_tune (device, RCV_BUF_SIZE,2000000000)!=0) return -1;
if(ethernet_tune (device, KERNEL_SND_BUF_MAX_SIZE, 200000000)!=0) return -1;
if(ethernet_tune (device, KERNEL_RCV_BUF_MAX_SIZE, 200000000)!=0) return -1;
/* adjust MTU wrt number of samples per packet */ return 0;
if(ethernet_tune (device,MTU_SIZE,UDP_IF4p5_PRACH_SIZE_BYTES)!=0) return -1;
if(ethernet_tune (device,RCV_TIMEOUT,999999)!=0) return -1;
}
/* apply additional configuration */
if(ethernet_tune (device, SND_BUF_SIZE,2000000000)!=0) return -1;
if(ethernet_tune (device, RCV_BUF_SIZE,2000000000)!=0) return -1;
if(ethernet_tune (device, KERNEL_SND_BUF_MAX_SIZE, 200000000)!=0) return -1;
if(ethernet_tune (device, KERNEL_RCV_BUF_MAX_SIZE, 200000000)!=0) return -1;
return 0;
} }
void trx_eth_end(openair0_device *device) { void trx_eth_end(openair0_device *device) {
eth_state_t *eth = (eth_state_t*)device->priv; eth_state_t *eth = (eth_state_t*)device->priv;
/* destroys socket only for the processes that call the eth_end fuction-- shutdown() for beaking the pipe */ /* destroys socket only for the processes that call the eth_end fuction-- shutdown() for beaking the pipe */
if ( close(eth->sockfdd) <0 ) { if ( close(eth->sockfdd) <0 ) {
perror("ETHERNET: Failed to close socket"); perror("ETHERNET: Failed to close socket");
exit(0); exit(0);
} else { } else {
printf("[%s] socket has been successfully closed.\n",(device->host_type == RAU_HOST)? "RAU":"RRU"); printf("[%s] socket has been successfully closed.\n",(device->host_type == RAU_HOST)? "RAU":"RRU");
} }
} }
...@@ -187,282 +187,282 @@ int trx_eth_reset_stats(openair0_device* device) { ...@@ -187,282 +187,282 @@ int trx_eth_reset_stats(openair0_device* device) {
int ethernet_tune(openair0_device *device, unsigned int option, int value) { int ethernet_tune(openair0_device *device, unsigned int option, int value) {
eth_state_t *eth = (eth_state_t*)device->priv; eth_state_t *eth = (eth_state_t*)device->priv;
struct timeval timeout; struct timeval timeout;
struct ifreq ifr; struct ifreq ifr;
char system_cmd[256]; char system_cmd[256];
int rname[] = { CTL_NET, NET_CORE, NET_CORE_RMEM_MAX }; int rname[] = { CTL_NET, NET_CORE, NET_CORE_RMEM_MAX };
int wname[] = { CTL_NET, NET_CORE, NET_CORE_WMEM_MAX }; int wname[] = { CTL_NET, NET_CORE, NET_CORE_WMEM_MAX };
int namelen=3; int namelen=3;
int newval[1]; int newval[1];
int newlen=sizeof(newval); int newlen=sizeof(newval);
int ret=0; int ret=0;
// int i=0; // int i=0;
/****************** socket level options ************************/ /****************** socket level options ************************/
switch(option) { switch(option) {
case SND_BUF_SIZE: /* transmit socket buffer size */ case SND_BUF_SIZE: /* transmit socket buffer size */
if (setsockopt(eth->sockfdd, if (setsockopt(eth->sockfdd,
SOL_SOCKET, SOL_SOCKET,
SO_SNDBUF, SO_SNDBUF,
&value,sizeof(value))) { &value,sizeof(value))) {
perror("[ETHERNET] setsockopt()"); perror("[ETHERNET] setsockopt()");
} else { } else {
printf("send buffer size= %d bytes\n",value); printf("send buffer size= %d bytes\n",value);
} }
break; break;
case RCV_BUF_SIZE: /* receive socket buffer size */ case RCV_BUF_SIZE: /* receive socket buffer size */
if (setsockopt(eth->sockfdd, if (setsockopt(eth->sockfdd,
SOL_SOCKET, SOL_SOCKET,
SO_RCVBUF, SO_RCVBUF,
&value,sizeof(value))) { &value,sizeof(value))) {
perror("[ETHERNET] setsockopt()"); perror("[ETHERNET] setsockopt()");
} else { } else {
printf("receive bufffer size= %d bytes\n",value); printf("receive bufffer size= %d bytes\n",value);
} }
break; break;
case RCV_TIMEOUT: case RCV_TIMEOUT:
timeout.tv_sec = value/1000000; timeout.tv_sec = value/1000000;
timeout.tv_usec = value%1000000;//less than rt_period? timeout.tv_usec = value%1000000;//less than rt_period?
if (setsockopt(eth->sockfdc, if (setsockopt(eth->sockfdc,
SOL_SOCKET, SOL_SOCKET,
SO_RCVTIMEO, SO_RCVTIMEO,
(char *)&timeout,sizeof(timeout))) { (char *)&timeout,sizeof(timeout))) {
perror("[ETHERNET] setsockopt()"); perror("[ETHERNET] setsockopt()");
} else { } else {
printf( "receive timeout= %u usec\n",(unsigned int)timeout.tv_usec); printf( "receive timeout= %u usec\n",(unsigned int)timeout.tv_usec);
} }
if (setsockopt(eth->sockfdd, if (setsockopt(eth->sockfdd,
SOL_SOCKET, SOL_SOCKET,
SO_RCVTIMEO, SO_RCVTIMEO,
(char *)&timeout,sizeof(timeout))) { (char *)&timeout,sizeof(timeout))) {
perror("[ETHERNET] setsockopt()"); perror("[ETHERNET] setsockopt()");
} else { } else {
printf( "receive timeout= %u usec\n",(unsigned int)timeout.tv_usec); printf( "receive timeout= %u usec\n",(unsigned int)timeout.tv_usec);
} }
break; break;
case SND_TIMEOUT: case SND_TIMEOUT:
timeout.tv_sec = value/1000000000; timeout.tv_sec = value/1000000000;
timeout.tv_usec = value%1000000000;//less than rt_period? timeout.tv_usec = value%1000000000;//less than rt_period?
if (setsockopt(eth->sockfdc, if (setsockopt(eth->sockfdc,
SOL_SOCKET, SOL_SOCKET,
SO_SNDTIMEO, SO_SNDTIMEO,
(char *)&timeout,sizeof(timeout))) { (char *)&timeout,sizeof(timeout))) {
perror("[ETHERNET] setsockopt()"); perror("[ETHERNET] setsockopt()");
} else { } else {
printf( "send timeout= %d,%d sec\n",(int)timeout.tv_sec,(int)timeout.tv_usec); printf( "send timeout= %d,%d sec\n",(int)timeout.tv_sec,(int)timeout.tv_usec);
} }
if (setsockopt(eth->sockfdd, if (setsockopt(eth->sockfdd,
SOL_SOCKET, SOL_SOCKET,
SO_SNDTIMEO, SO_SNDTIMEO,
(char *)&timeout,sizeof(timeout))) { (char *)&timeout,sizeof(timeout))) {
perror("[ETHERNET] setsockopt()"); perror("[ETHERNET] setsockopt()");
} else { } else {
printf( "send timeout= %d,%d sec\n",(int)timeout.tv_sec,(int)timeout.tv_usec); printf( "send timeout= %d,%d sec\n",(int)timeout.tv_sec,(int)timeout.tv_usec);
} }
break; break;
/******************* interface level options *************************/ /******************* interface level options *************************/
case MTU_SIZE: /* change MTU of the eth interface */ case MTU_SIZE: /* change MTU of the eth interface */
ifr.ifr_addr.sa_family = AF_INET; ifr.ifr_addr.sa_family = AF_INET;
strncpy(ifr.ifr_name,eth->if_name, sizeof(ifr.ifr_name)); strncpy(ifr.ifr_name,eth->if_name, sizeof(ifr.ifr_name));
ifr.ifr_mtu =value; ifr.ifr_mtu =value;
if (ioctl(eth->sockfdd,SIOCSIFMTU,(caddr_t)&ifr) < 0 ) if (ioctl(eth->sockfdd,SIOCSIFMTU,(caddr_t)&ifr) < 0 )
perror ("[ETHERNET] Can't set the MTU"); perror ("[ETHERNET] Can't set the MTU");
else else
printf("[ETHERNET] %s MTU size has changed to %d\n",eth->if_name,ifr.ifr_mtu); printf("[ETHERNET] %s MTU size has changed to %d\n",eth->if_name,ifr.ifr_mtu);
break; break;
case TX_Q_LEN: /* change TX queue length of eth interface */ case TX_Q_LEN: /* change TX queue length of eth interface */
ifr.ifr_addr.sa_family = AF_INET; ifr.ifr_addr.sa_family = AF_INET;
strncpy(ifr.ifr_name,eth->if_name, sizeof(ifr.ifr_name)); strncpy(ifr.ifr_name,eth->if_name, sizeof(ifr.ifr_name));
ifr.ifr_qlen =value; ifr.ifr_qlen =value;
if (ioctl(eth->sockfdd,SIOCSIFTXQLEN,(caddr_t)&ifr) < 0 ) if (ioctl(eth->sockfdd,SIOCSIFTXQLEN,(caddr_t)&ifr) < 0 )
perror ("[ETHERNET] Can't set the txqueuelen"); perror ("[ETHERNET] Can't set the txqueuelen");
else else
printf("[ETHERNET] %s txqueuelen size has changed to %d\n",eth->if_name,ifr.ifr_qlen); printf("[ETHERNET] %s txqueuelen size has changed to %d\n",eth->if_name,ifr.ifr_qlen);
break; break;
/******************* device level options *************************/ /******************* device level options *************************/
case COALESCE_PAR: case COALESCE_PAR:
ret=snprintf(system_cmd,sizeof(system_cmd),"ethtool -C %s rx-usecs %d",eth->if_name,value); ret=snprintf(system_cmd,sizeof(system_cmd),"ethtool -C %s rx-usecs %d",eth->if_name,value);
if (ret > 0) { if (ret > 0) {
ret=system(system_cmd); ret=system(system_cmd);
if (ret == -1) { if (ret == -1) {
fprintf (stderr,"[ETHERNET] Can't start shell to execute %s %s",system_cmd, strerror(errno)); fprintf (stderr,"[ETHERNET] Can't start shell to execute %s %s",system_cmd, strerror(errno));
} else { } else {
printf ("[ETHERNET] status of %s is %d\n", system_cmd, WEXITSTATUS(ret)); printf ("[ETHERNET] status of %s is %d\n", system_cmd, WEXITSTATUS(ret));
} }
printf("[ETHERNET] Coalesce parameters %s\n",system_cmd); printf("[ETHERNET] Coalesce parameters %s\n",system_cmd);
} else { } else {
perror("[ETHERNET] Can't set coalesce parameters\n"); perror("[ETHERNET] Can't set coalesce parameters\n");
}
break;
case PAUSE_PAR:
if (value==1) ret=snprintf(system_cmd,sizeof(system_cmd),"ethtool -A %s autoneg off rx off tx off",eth->if_name);
else if (value==0) ret=snprintf(system_cmd,sizeof(system_cmd),"ethtool -A %s autoneg on rx on tx on",eth->if_name);
else break;
if (ret > 0) {
ret=system(system_cmd);
if (ret == -1) {
fprintf (stderr,"[ETHERNET] Can't start shell to execute %s %s",system_cmd, strerror(errno));
} else {
printf ("[ETHERNET] status of %s is %d\n", system_cmd, WEXITSTATUS(ret));
}
printf("[ETHERNET] Pause parameters %s\n",system_cmd);
} else {
perror("[ETHERNET] Can't set pause parameters\n");
}
break;
case RING_PAR:
ret=snprintf(system_cmd,sizeof(system_cmd),"ethtool -G %s val %d",eth->if_name,value);
if (ret > 0) {
ret=system(system_cmd);
if (ret == -1) {
fprintf (stderr,"[ETHERNET] Can't start shell to execute %s %s",system_cmd, strerror(errno));
} else {
printf ("[ETHERNET] status of %s is %d\n", system_cmd, WEXITSTATUS(ret));
}
printf("[ETHERNET] Ring parameters %s\n",system_cmd);
} else {
perror("[ETHERNET] Can't set ring parameters\n");
}
break;
case KERNEL_RCV_BUF_MAX_SIZE:
newval[0] = value;
ret=sysctl(rname, namelen, NULL, 0, newval, newlen);
if (ret) {
fprintf(stderr,"[ETHERNET] Error using sysctl():%s\n",strerror(errno));
} else {
printf("[ETHERNET] Kernel network receive buffer max size is set to %u\n",(unsigned int)newval[0]);
}
break;
case KERNEL_SND_BUF_MAX_SIZE:
newval[0] = value;
ret=sysctl(wname, namelen, NULL, 0, newval, newlen);
if (ret) {
fprintf(stderr,"[ETHERNET] Error using sysctl():%s\n",strerror(errno));
} else {
printf("[ETHERNET] Kernel network send buffer max size is set to %u\n",(unsigned int)newval[0]);
}
break;
default:
break;
} }
break;
return 0;
case PAUSE_PAR: }
if (value==1) ret=snprintf(system_cmd,sizeof(system_cmd),"ethtool -A %s autoneg off rx off tx off",eth->if_name);
else if (value==0) ret=snprintf(system_cmd,sizeof(system_cmd),"ethtool -A %s autoneg on rx on tx on",eth->if_name);
else break; int transport_init(openair0_device *device, openair0_config_t *openair0_cfg, eth_params_t * eth_params ) {
if (ret > 0) {
ret=system(system_cmd); eth_state_t *eth = (eth_state_t*)malloc(sizeof(eth_state_t));
if (ret == -1) { memset(eth, 0, sizeof(eth_state_t));
fprintf (stderr,"[ETHERNET] Can't start shell to execute %s %s",system_cmd, strerror(errno));
} else { if (eth_params->transp_preference == 1) {
printf ("[ETHERNET] status of %s is %d\n", system_cmd, WEXITSTATUS(ret)); eth->flags = ETH_RAW_MODE;
} } else if (eth_params->transp_preference == 0) {
printf("[ETHERNET] Pause parameters %s\n",system_cmd); eth->flags = ETH_UDP_MODE;
} else if (eth_params->transp_preference == 3) {
eth->flags = ETH_RAW_IF4p5_MODE;
} else if (eth_params->transp_preference == 2) {
eth->flags = ETH_UDP_IF4p5_MODE;
} else if (eth_params->transp_preference == 4) {
eth->flags = ETH_RAW_IF5_MOBIPASS;
} else { } else {
perror("[ETHERNET] Can't set pause parameters\n"); printf("transport_init: Unknown transport preference %d - default to RAW", eth_params->transp_preference);
eth->flags = ETH_RAW_MODE;
} }
break;
if (eth_params->if_compress == 0) {
case RING_PAR: eth->compression = NO_COMPRESS;
ret=snprintf(system_cmd,sizeof(system_cmd),"ethtool -G %s val %d",eth->if_name,value); } else if (eth_params->if_compress == 1) {
if (ret > 0) { eth->compression = ALAW_COMPRESS;
ret=system(system_cmd);
if (ret == -1) {
fprintf (stderr,"[ETHERNET] Can't start shell to execute %s %s",system_cmd, strerror(errno));
} else {
printf ("[ETHERNET] status of %s is %d\n", system_cmd, WEXITSTATUS(ret));
}
printf("[ETHERNET] Ring parameters %s\n",system_cmd);
} else { } else {
perror("[ETHERNET] Can't set ring parameters\n"); printf("transport_init: Unknown compression scheme %d - default to ALAW", eth_params->if_compress);
} eth->compression = ALAW_COMPRESS;
break;
case KERNEL_RCV_BUF_MAX_SIZE:
newval[0] = value;
ret=sysctl(rname, namelen, NULL, 0, newval, newlen);
if (ret) {
fprintf(stderr,"[ETHERNET] Error using sysctl():%s\n",strerror(errno));
} else{
printf("[ETHERNET] Kernel network receive buffer max size is set to %u\n",newval[0]);
} }
break;
case KERNEL_SND_BUF_MAX_SIZE: printf("[ETHERNET]: Initializing openair0_device for %s ...\n", ((device->host_type == RAU_HOST) ? "RAU": "RRU"));
newval[0] = value; device->Mod_id = 0;//num_devices_eth++;
ret=sysctl(wname, namelen, NULL, 0, newval, newlen); device->transp_type = ETHERNET_TP;
if (ret) { device->trx_start_func = trx_eth_start;
fprintf(stderr,"[ETHERNET] Error using sysctl():%s\n",strerror(errno)); device->trx_get_stats_func = trx_eth_get_stats;
} else{ device->trx_reset_stats_func = trx_eth_reset_stats;
printf("[ETHERNET] Kernel network send buffer max size is set to %u\n",newval[0]); 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;
if (eth->flags == ETH_RAW_MODE) {
device->trx_write_func = trx_eth_write_raw;
device->trx_read_func = trx_eth_read_raw;
} else if (eth->flags == ETH_UDP_MODE) {
device->trx_write_func = trx_eth_write_udp;
device->trx_read_func = trx_eth_read_udp;
device->trx_ctlsend_func = trx_eth_ctlsend_udp;
device->trx_ctlrecv_func = trx_eth_ctlrecv_udp;
} else if (eth->flags == ETH_RAW_IF4p5_MODE) {
device->trx_write_func = trx_eth_write_raw_IF4p5;
device->trx_read_func = trx_eth_read_raw_IF4p5;
} else if (eth->flags == ETH_UDP_IF4p5_MODE) {
device->trx_write_func = trx_eth_write_udp_IF4p5;
device->trx_read_func = trx_eth_read_udp_IF4p5;
device->trx_ctlsend_func = trx_eth_ctlsend_udp;
device->trx_ctlrecv_func = trx_eth_ctlrecv_udp;
} else if (eth->flags == ETH_RAW_IF5_MOBIPASS) {
device->trx_write_func = trx_eth_write_raw_IF4p5;
device->trx_read_func = trx_eth_read_raw_IF5_mobipass;
} else {
//device->trx_write_func = trx_eth_write_udp_IF4p5;
//device->trx_read_func = trx_eth_read_udp_IF4p5;
} }
break;
default:
break;
}
return 0;
}
eth->if_name = eth_params->local_if_name;
device->priv = eth;
int transport_init(openair0_device *device, openair0_config_t *openair0_cfg, eth_params_t * eth_params ) { /* 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;
eth_state_t *eth = (eth_state_t*)malloc(sizeof(eth_state_t)); /* RRU does not have any information to make this configuration atm */
memset(eth, 0, sizeof(eth_state_t)); /*
if (device->host_type == RAU_HOST) {
if (eth_params->transp_preference == 1) {
eth->flags = ETH_RAW_MODE; switch ((int)openair0_cfg[0].sample_rate) {
} else if (eth_params->transp_preference == 0) { case 30720000:
eth->flags = ETH_UDP_MODE; openair0_cfg[0].samples_per_packet = 3840;
} else if (eth_params->transp_preference == 3) { break;
eth->flags = ETH_RAW_IF4p5_MODE; case 23040000:
} else if (eth_params->transp_preference == 2) { openair0_cfg[0].samples_per_packet = 2880;
eth->flags = ETH_UDP_IF4p5_MODE; break;
} else if (eth_params->transp_preference == 4) { case 15360000:
eth->flags = ETH_RAW_IF5_MOBIPASS; openair0_cfg[0].samples_per_packet = 1920;
} else { break;
printf("transport_init: Unknown transport preference %d - default to RAW", eth_params->transp_preference); case 7680000:
eth->flags = ETH_RAW_MODE; openair0_cfg[0].samples_per_packet = 960;
} break;
case 1920000:
if (eth_params->if_compress == 0) { openair0_cfg[0].samples_per_packet = 240;
eth->compression = NO_COMPRESS; break;
} else if (eth_params->if_compress == 1) { default:
eth->compression = ALAW_COMPRESS; printf("Error: unknown sampling rate %f\n",openair0_cfg[0].sample_rate);
} else { exit(-1);
printf("transport_init: Unknown compression scheme %d - default to ALAW", eth_params->if_compress); break;
eth->compression = ALAW_COMPRESS; }
} }*/
printf("[ETHERNET]: Initializing openair0_device for %s ...\n", ((device->host_type == RAU_HOST) ? "RAU": "RRU"));
device->Mod_id = 0;//num_devices_eth++;
device->transp_type = ETHERNET_TP;
device->trx_start_func = trx_eth_start;
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;
if (eth->flags == ETH_RAW_MODE) {
device->trx_write_func = trx_eth_write_raw;
device->trx_read_func = trx_eth_read_raw;
} else if (eth->flags == ETH_UDP_MODE) {
device->trx_write_func = trx_eth_write_udp;
device->trx_read_func = trx_eth_read_udp;
device->trx_ctlsend_func = trx_eth_ctlsend_udp;
device->trx_ctlrecv_func = trx_eth_ctlrecv_udp;
} else if (eth->flags == ETH_RAW_IF4p5_MODE) {
device->trx_write_func = trx_eth_write_raw_IF4p5;
device->trx_read_func = trx_eth_read_raw_IF4p5;
} else if (eth->flags == ETH_UDP_IF4p5_MODE) {
device->trx_write_func = trx_eth_write_udp_IF4p5;
device->trx_read_func = trx_eth_read_udp_IF4p5;
device->trx_ctlsend_func = trx_eth_ctlsend_udp;
device->trx_ctlrecv_func = trx_eth_ctlrecv_udp;
} else if (eth->flags == ETH_RAW_IF5_MOBIPASS) {
device->trx_write_func = trx_eth_write_raw_IF4p5;
device->trx_read_func = trx_eth_read_raw_IF5_mobipass;
} else {
//device->trx_write_func = trx_eth_write_udp_IF4p5;
//device->trx_read_func = trx_eth_read_udp_IF4p5;
}
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;
/* RRU does not have any information to make this configuration atm */
/*
if (device->host_type == RAU_HOST) {
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]; device->openair0_cfg=&openair0_cfg[0];
return 0; return 0;
} }
......
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