📄 radio_link_agent.cpp
字号:
fprintf(stderr,"!!error in module %s: SDU buffer overflow\n",ModuleName);
exit(-1);
}
upper_layer_status = Upper_Layer_Agent->get_PDU(simulation_time,&(SDU_Buffer[SDU_buffer_write_position].upper_layer_PDU));
switch (upper_layer_status)
{
case 0:
// succeeded
SDU_Buffer[SDU_buffer_write_position].unsent_bytes = SDU_Buffer[SDU_buffer_write_position].upper_layer_PDU.size;
SDU_Buffer[SDU_buffer_write_position].received_bytes_counter = 0;
SDU_Buffer[SDU_buffer_write_position].correct_bytes_counter = 0;
SDU_buffer_write_position++;
if ( SDU_buffer_write_position == PACKET_BUFFER_SIZE )
{
SDU_buffer_write_position = 0; // wrap around circular SDU buffer
}
SDU_buffer_total_length++;
SDU_buffer_unsent_length++;
break;
case 1:
// failed: input file still contains data, but the timestamp is younger than the current simulation time
// send dummy frames to simulate idle periods
fprintf(LogFile_ptr,"%s: not enough data available for transmission at the moment - sending dummy frame at time %d\n",ModuleName,simulation_time);
if ( ((*outgoing_frame) = (RADIO_LINK_FRAME *) malloc(sizeof(RADIO_LINK_FRAME))) == NULL )
{
fprintf(stderr,"!!error in module %s: cannot allocate enough memory for new radio link frame\n",ModuleName);
exit(-1);
}
(*outgoing_frame)->sequence_number = send_sequence_number;
send_sequence_number++;
(*outgoing_frame)->size = frame_size;
(*outgoing_frame)->frame_type = DUMMY;
(*outgoing_frame)->number_of_contained_SDUs = 0;
(*outgoing_frame)->number_of_retransmissions = 0;
total_frames_counter++;
total_dummy_frames_counter++;
simulation_time += transmission_time_interval;
return TRUE;
case 2:
// failed: end of input file already reached
if ( Retransmit_buffer_length > 0 )
{
// no new data available, but retransmission buffer still contains unsent frames - send dummy frames
fprintf(LogFile_ptr,"%s: no more data available for transmission - but retransmission buffer still full\n",ModuleName);
if ( ((*outgoing_frame) = (RADIO_LINK_FRAME *) malloc(sizeof(RADIO_LINK_FRAME))) == NULL )
{
fprintf(stderr,"!!error in module %s: cannot allocate enough memory for new radio link frame\n",ModuleName);
exit(-1);
}
(*outgoing_frame)->sequence_number = send_sequence_number;
send_sequence_number++;
(*outgoing_frame)->size = frame_size;
(*outgoing_frame)->frame_type = DUMMY;
(*outgoing_frame)->number_of_contained_SDUs = 0;
(*outgoing_frame)->number_of_retransmissions = 0;
total_frames_counter++;
total_dummy_frames_counter++;
simulation_time += transmission_time_interval;
return TRUE;
}
else
{
fprintf(LogFile_ptr,"%s: no more data available for transmission - termination initiated\n",ModuleName);
return FALSE;
}
default:
// unexpected return value
fprintf(stderr,"!!error in module %s: unexpected return value for <get_SDU>\n",ModuleName);
exit(-1);
}
}
// enough data available in SDU buffer
// prepare outgoing radio link frame for transmission
if ( ((*outgoing_frame) = (RADIO_LINK_FRAME *) malloc(sizeof(RADIO_LINK_FRAME))) == NULL )
{
fprintf(stderr,"!!error in module %s: cannot allocate enough memory for new radio link frame\n",ModuleName);
exit(-1);
}
(*outgoing_frame)->sequence_number = send_sequence_number;
send_sequence_number++;
(*outgoing_frame)->size = 0;
(*outgoing_frame)->frame_type = DATA;
(*outgoing_frame)->number_of_contained_SDUs = 0;
(*outgoing_frame)->number_of_retransmissions = 0;
// (virtually) add header fields to outgoing radio link frame
(*outgoing_frame)->size += agent_header_size*8;
// (virtually) map data from SDU buffer to the outgoing radio link frame, until the latter is full or the SDU buffer is empty
while ( (*outgoing_frame)->size < frame_size )
{
if ( SDU_Buffer[SDU_buffer_read_position].unsent_bytes <= (frame_size - (*outgoing_frame)->size)/8 )
{
// unsent bytes in current SDU do no exceed the space still left in the radio link frame
(*outgoing_frame)->size += SDU_Buffer[SDU_buffer_read_position].unsent_bytes*8;
(*outgoing_frame)->contained_SDU[(*outgoing_frame)->number_of_contained_SDUs].identifier = SDU_buffer_read_position;
(*outgoing_frame)->contained_SDU[(*outgoing_frame)->number_of_contained_SDUs].size = SDU_Buffer[SDU_buffer_read_position].unsent_bytes;
(*outgoing_frame)->number_of_contained_SDUs++;
SDU_Buffer[SDU_buffer_read_position].unsent_bytes = 0;
SDU_buffer_unsent_length--;
SDU_buffer_read_position++;
if ( SDU_buffer_read_position == PACKET_BUFFER_SIZE )
{
SDU_buffer_read_position = 0; // wrap around circular SDU buffer
}
}
else
{
// unsent bytes in current SDU exceed the space still left in the radio link frame - take only a fraction of them
mapped_data_size = (frame_size - (*outgoing_frame)->size)/8;
(*outgoing_frame)->size = frame_size;
(*outgoing_frame)->contained_SDU[(*outgoing_frame)->number_of_contained_SDUs].identifier = SDU_buffer_read_position;
(*outgoing_frame)->contained_SDU[(*outgoing_frame)->number_of_contained_SDUs].size = mapped_data_size;
(*outgoing_frame)->number_of_contained_SDUs++;
SDU_Buffer[SDU_buffer_read_position].unsent_bytes -= mapped_data_size;
}
// check, if SDU buffer still contains unsent data parts and the radio link frame is not completely filled yet
if ( (SDU_buffer_unsent_length == 0) && ((*outgoing_frame)->size < frame_size) )
{
// we need to request a new SDU from the upper layer agent
//check for buffer overflow first
if ( SDU_buffer_total_length == PACKET_BUFFER_SIZE )
{
fprintf(stderr,"!!error in module %s: SDU buffer overflow\n",ModuleName);
exit(-1);
}
upper_layer_status = Upper_Layer_Agent->get_PDU(simulation_time,&(SDU_Buffer[SDU_buffer_write_position].upper_layer_PDU));
switch (upper_layer_status)
{
case 0:
// succeeded
SDU_Buffer[SDU_buffer_write_position].unsent_bytes = SDU_Buffer[SDU_buffer_write_position].upper_layer_PDU.size;
SDU_Buffer[SDU_buffer_write_position].received_bytes_counter = 0;
SDU_Buffer[SDU_buffer_write_position].correct_bytes_counter = 0;
SDU_buffer_write_position++;
if ( SDU_buffer_write_position == PACKET_BUFFER_SIZE )
{
SDU_buffer_write_position = 0; // wrap around circular SDU buffer
}
SDU_buffer_total_length++;
SDU_buffer_unsent_length++;
break;
case 1:
// failed: input file still contains data, but the timestamp is younger than the current simulation time
// perform (virtual) stuffing for the rest of the radio link frame
fprintf(LogFile_ptr,"%s: not enough data available for transmission at the moment - perform (virtual) stuffing on frame at time %d\n",ModuleName,simulation_time);
(*outgoing_frame)->size = frame_size;
break;
case 2:
// failed: end of input file already reached
// also perform (virtual) stuffing for the rest of the radio link frame
fprintf(LogFile_ptr,"%s: no more data available for transmission - perform (virtual) stuffing on frame at time %d\n",ModuleName,simulation_time);
(*outgoing_frame)->size = frame_size;
break;
default:
// unexpected return value
fprintf(stderr,"!!error in module %s: unexpected return value for <get_SDU>\n",ModuleName);
exit(-1);
}
}
}
// finish generation of new radio link frame
total_frames_counter++;
simulation_time += transmission_time_interval;
return TRUE;
}
// invoke reception procedure for radio link frames depending on radio link operation mode
void RADIO_LINK_AGENT::receive_frame(RADIO_LINK_FRAME *incoming_frame, Boolean frame_error_indicator)
{
if ( ACK_mode )
{
// acknowledged mode
AM_receive_frame(incoming_frame, frame_error_indicator);
}
else
{
//unacknowledged mode
UM_receive_frame(incoming_frame, frame_error_indicator);
}
}
void RADIO_LINK_AGENT::write_statistics(FILE *StatisticsFile_ptr)
{
//calculate statistics first
total_bitrate = (double)(total_frames_counter*frame_size)/(double)simulation_time;
total_net_bitrate = (double)(total_frames_counter*(frame_size-agent_header_size*8))/(double)simulation_time;
effective_net_bitrate = (double)total_correct_payload_bits_counter/(double)simulation_time;
// write statistics to file
fprintf(StatisticsFile_ptr,"----------------------------------------------------------------------------\n");
fprintf(StatisticsFile_ptr,"%s: Statistics:\n\n",ModuleName);
fprintf(StatisticsFile_ptr,"total number of radio link frames transmitted: %10d\n",total_frames_counter);
fprintf(StatisticsFile_ptr,"number of retransmissions: %10d\n",total_retransmitted_frames_counter);
fprintf(StatisticsFile_ptr,"number of dummy frames: %10d\n\n",total_dummy_frames_counter);
fprintf(StatisticsFile_ptr,"total bitrate (including radio link header): %f kbit/s\n",total_bitrate);
fprintf(StatisticsFile_ptr,"total net bitrate (excluding radio link header): %f kbit/s\n",total_net_bitrate);
fprintf(StatisticsFile_ptr,"effective net bitrate (including only correct data bits): %f kbit/s\n",effective_net_bitrate);
fprintf(StatisticsFile_ptr,"----------------------------------------------------------------------------\n");
fprintf(StatisticsFile_ptr,"total simulation time: %d ms\n",simulation_time);
fprintf(StatisticsFile_ptr,"----------------------------------------------------------------------------\n");
}
// reception procedure for acknowledged mode operation
void RADIO_LINK_AGENT::AM_receive_frame(RADIO_LINK_FRAME *incoming_frame, Boolean frame_error_indicator)
{
int32 i, identifier;
// determine the type of the received frame
switch ( incoming_frame->frame_type )
{
case DATA:
// check for frame sequence reordering
if ( incoming_frame->sequence_number != receive_sequence_number )
{
fprintf(stderr,"!!error in module %s: frame reordering in acknowledged mode has occurred\n",ModuleName);
}
receive_sequence_number++;
// check frame error status
if ( frame_error_indicator )
{
// retransmission is allowed at least once per frame in acknowledged mode
incoming_frame->frame_type = RETRANSMIT;
incoming_frame->number_of_retransmissions = 0;
// check for retransmission buffer overflow
if ( Retransmit_buffer_length == FRAME_BUFFER_SIZE )
{
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -