⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 wlan_mac_tmac_nav_rpm_31jan06_ver2.function block

📁 opnet无线网络编程
💻 FUNCTION BLOCK
📖 第 1 页 / 共 5 页
字号:

			/* Prepare beacon frame to be transmitted */
			wlan_prepare_frame_to_send (WlanC_Beac);

			/* Break the routine once beacon prepared to transmit */
			FOUT;
		}

		/* Send a CTS frame if it is the type of frame we need to send a		*/
		/* response of.															*/
		else if (fresp_to_send == WlanC_Cts)
		{
			wlan_prepare_frame_to_send (fresp_to_send);
			/* Break the routine if Cts or Ack is already prepared to transmit.	*/
			FOUT;
		}

		/* If it is a retransmission then check which type of frame needs to be	*/
		/* retransmitted and then prepare and transmit that frame.				*/
		else if (short_retry_count + long_retry_count > 0)
		{
			/* If the last frame unsuccessfully transmitted was an RTS  or a 	*/
			/* CTS-to-self then transmit it again.								*/
			if ((last_frametx_type == WlanC_Rts || last_frametx_type == WlanC_Cts) && 
				wlan_flags->rts_sent == OPC_FALSE &&  wlan_flags->polled == OPC_FALSE)
			{
				wlan_prepare_frame_to_send (last_frametx_type);
			}

			/* If our last transmission was a data packet, then it means it was	*/
			/* not acknowledged. Restart the transmission process. Do the same	*/
			/* if we are resuming our retransmission after sending a beacon		*/
			/* frame or a management frame reporting end of CFP.				*/
			else if ((last_frametx_type == WlanC_Data   || last_frametx_type == WlanC_Beac ||
				last_frametx_type == WlanC_Cf_End || last_frametx_type == WlanC_Cf_End_A) && wlan_flags->polled == OPC_FALSE)
			{
				/* Check whether we need to start the retransmission with an	*/
				/* RTS message.													*/
				if (wlan_flags->frame_size_req_rts == OPC_TRUE && wlan_flags->rts_sent == OPC_FALSE)
				{
					/* Retransmit the RTS frame to again contend for the data .	*/
					wlan_prepare_frame_to_send (WlanC_Rts);		
				}


				/* Just retransmit the data packet if no protection is needed.	*/
				else
				{
					wlan_prepare_frame_to_send (WlanC_Data);
				
				}
			}
			else
			{
				/* We continue with the retransmission process. Either we have	*/
				/* received the expected CTS for our last RTS before and now we	*/
				/* can retransmit our data frame, or we moved from DCF period	*/
				/* into PCF period and have been polled by the AP for			*/
				/* transmission. In case of PCF, also check whether we have an	*/
				/* ACK to append to our data packet.							*/
				wlan_prepare_frame_to_send (WlanC_Data);
				
			}

			FOUT;
		}

		/* If higher layer queue is not empty then dequeue a packet	*/
		/* from the higher layer and insert it into fragmentation 	*/
		/* buffer check whether fragmentation and RTS-CTS exchange 	*/
		/* is needed  based on thresholds							*/
		/* Check if fragmentation buffer is empty. If it is empty   */
		/* then dequeue a packet from the higher layer queue.		*/ 
		else if ((op_prg_list_size (hld_list_ptr) != 0) && (op_sar_buf_size (fragmentation_buffer_ptr) == 0))
		{	
			/* If rts is already sent then transmit data otherwise	*/
			/* check if rts needs to be sent or not.				*/
			if (wlan_flags->rts_sent == OPC_FALSE)
			{

				/* Remove packet from higher layer queue. */
				hld_ptr = (WlanT_Hld_List_Elem *) op_prg_list_remove (hld_list_ptr, 0);

				/* Update the higher layer queue size statistic.				*/
				if (active_pc)
					op_stat_write (hl_packets_rcvd, (double) (op_prg_list_size (hld_list_ptr) + op_prg_list_size (cfpd_list_ptr)));
				else
					op_stat_write (hl_packets_rcvd, (double) op_prg_list_size (hld_list_ptr));

				/* Determine packet size to determine later whether fragmentation	*/
				/* and/or rts-cts exchange is needed.								*/
				packet_size_dcf = op_pk_total_size_get (hld_ptr->pkptr);

				/* Updating the total packet size of the higher layer buffer.	*/
				total_hlpk_size = total_hlpk_size - packet_size_dcf;

				/* Setting destination address state variable	*/				
				destination_addr = hld_ptr->destination_address;

				/* Packet seq number modulo 4096 counter.	*/
				packet_seq_number = (packet_seq_number + 1) % 4096;  

				/* Packet fragment number is initialized.	*/
				packet_frag_number = 0;				

				/* Packet needs to be fragmented if it is more than			*/
				/* fragmentation threshold, provided fragmentation is		*/
				/* enabled. Broadcast packets are not fragmented regardless	*/
				/* of their sizes.											*/
				if (frag_threshold != -1 && destination_addr >= 0 && packet_size_dcf > (frag_threshold * 8))
				{
					/* Determine number of fragments for the packet	*/
					/* and the size of the last fragment			*/							
					num_fragments =  (int) (packet_size_dcf / (frag_threshold * 8));
					remainder_size = packet_size_dcf - (num_fragments * frag_threshold * 8);

					/* If the remainder size is non zero it means that the	*/
					/* last fragment is fractional but since the number 	*/
					/* of fragments is a whole number we need to transmit	*/
					/* one additional fragment to ensure that all of the	*/
					/* data bits will be transmitted						*/
					if (remainder_size != 0)
						num_fragments = num_fragments + 1;									 
					else
						/* Special case: data size is a multiple of the		*/
						/* fragment size, so all the fragments will be the	*/
						/* same size. To be consistent with other cases,	*/
						/* set remainder_size to the size of the last		*/
						/* fragment.										*/
						remainder_size = frag_threshold * 8;
				}
				else
				{			
					/* If no fragments needed then number of	*/
					/* packets to be transmitted is set to 1	*/								
					num_fragments = 1;
					remainder_size = packet_size_dcf;
				}

				/* Storing Data packet id for debugging purposes.	*/			
				pkt_in_service = op_pk_id (hld_ptr->pkptr);		

				/* Insert packet to fragmentation buffer	*/					
				op_sar_segbuf_pk_insert (fragmentation_buffer_ptr, hld_ptr->pkptr, 0);

				/* Computing packet duration in the queue in seconds	*/
				/* and reporting it to the statistics					*/
				pkt_tx_time = (current_time - hld_ptr->time_rcvd);

				/* Printing out information to ODB.	*/
				if (wlan_trace_active == OPC_TRUE)
				{
					sprintf (msg_string, "Data packet " OPC_PACKET_ID_FMT " is removed from higher layer buffer", pkt_in_service);
					sprintf	(msg_string1, "The queueing delay for data packet " OPC_PACKET_ID_FMT " is %fs", 	
						pkt_in_service, pkt_tx_time);	
					op_prg_odb_print_major (msg_string, msg_string1, OPC_NIL);
				}

				/* Store the arrival time of the packet.	*/
				receive_time_dcf = hld_ptr->time_rcvd;

				/* Free up allocated memory for the data packet removed from the higher		*/
				/* layer queue.																*/
				op_prg_mem_free (hld_ptr);


				/* Send RTS if RTS is enabled and packet size is more than RTS threshold.	*/
				/* No RTS message is sent for broadcast packets regradless of their sizes.	*/
				if (rts_threshold != -1 && destination_addr >= 0 && 
					(packet_size_dcf + WLANC_MSDU_HEADER_SIZE) > (rts_threshold * 8) &&
					wlan_flags->polled == OPC_FALSE)			
				{
					/* Set the flag indicating that an RTS is needed for the current frame	*/
					/* due to its size.														*/
					wlan_flags->frame_size_req_rts = OPC_TRUE;

					/* Prepare RTS frame for transmission.									*/
					wlan_prepare_frame_to_send (WlanC_Rts);
					/* Break the routine as RTS is already prepared.						*/
					FOUT;
				}

				else
				{
					/* Reset the flag indicating an RTS was not necessary due to current	*/
					/* frame size.															*/
					wlan_flags->frame_size_req_rts = OPC_FALSE;

				}
			}
		}

		/* This is a normal DCF transmission. Prepare the frame for		*/
		/* for transmission.											*/
		wlan_prepare_frame_to_send (WlanC_Data);
		
	FOUT;
}



static void 
wlan_prepare_frame_to_send (WlanT_Mac_Frame_Type frame_type)
{
	Packet*							seg_pkptr;
	OpT_Packet_Size					tx_datapacket_size;
	WlanT_Mac_Frame_Type			type;
	//int								i;
	double							tx_data_rate;
	double							duration, mac_delay;
	double							total_pk_size;
	double							tx_end_time;
	double							total_plcp_overhead;
	WlanT_Data_Header_Fields*		pk_dhstruct_ptr;
	WlanT_Control_Header_Fields*	pk_chstruct_ptr;
	WlanT_Beacon_Body_Fields*		pk_bbstruct_ptr;
	Packet*							wlan_transmit_frame_ptr;
	char							msg_string [120];
	char							frame_type_str [32];

	/** Prepare frames to transmit by setting appropriate fields in the 	**/
	/** packet format for Data,Cts,Rts or Ack.  If data or Rts packet needs **/
	/** to be retransmitted then the copy of the packet is resent.          **/
	FIN (wlan_prepare_frame_to_send (frame_type));

	rcvd_frame_drate  = wsn_data_rate;
	
	/* First initialize the transmission data rate to the lowest supported	*/
	/* data rate, which is the data rate used for control frames.			*/
	tx_data_rate = control_data_rate;

	/* It this is a CP period and the frame to be transmitted is a data/ACK.*/
	if ((wlan_flags->pcf_active == OPC_FALSE) && 
		((frame_type == WlanC_Data) || (frame_type == WlanC_Data_Ack)))
	{
		/* Adjust the transmission data rate based on the operational speed.*/
		tx_data_rate = wsn_data_rate;

		/* Set the variable which keeps track of the last transmitted frame.	*/
		last_frametx_type = frame_type;

		/* If it is a retransmission of a packet. Obtain the frame from the 	*/
		/* the copy pointer which was stored during the previous transmission	*/
		if ((short_retry_count + long_retry_count > 0) && (wlan_transmit_frame_copy_ptr != OPC_NIL))
		{
			/* If it is a retransmission then just transmit the previous frame	*/			
			wlan_transmit_frame_ptr = op_pk_copy (wlan_transmit_frame_copy_ptr);

			/* Reset header type in case Ack status has changed for frame */
			op_pk_nfd_set_int32 (wlan_transmit_frame_ptr, "Type", frame_type);

			/* If retry count is non-zero means that the frame is a */
			/* retransmission of the last transmitted frame			*/
			op_pk_nfd_access (wlan_transmit_frame_ptr, "Wlan Header", &pk_dhstruct_ptr);
			pk_dhstruct_ptr->retry = 1;

			/* Reset more_data bit in case queue status has changed since last transmission			*/
			/* If this STA has been polled, and there are additional packets remaining				*/
			if ((wlan_flags->polled == OPC_TRUE) && (op_prg_list_size (hld_list_ptr) != 0))
			{
				/* Set more data bit to tell AP that STA has more packets */
				pk_dhstruct_ptr->more_data = 1;
			}

			/* Printing out information to ODB.	*/
			if (wlan_trace_active == OPC_TRUE)
			{
				sprintf (msg_string, "Data fragment %d for packet " OPC_PACKET_ID_FMT " is retransmitted",
					pk_dhstruct_ptr->fragment_number, pkt_in_service);							
				op_prg_odb_print_major (msg_string, OPC_NIL);
			}					

			/* Calculate NAV duration till the channel will be occupied by 	*/
			/* station. The duration is SIFS time plus the ACK frame time,	*/
			/* which the station needs in response to the data frame (note:	*/
			/* no need to check for broadcast packets, since for broadcast	*/
			/* packets the encapsulating if condition will be never true).	*/
			duration = sifs_time + TXTIME_CTRL (WLANC_ACK_LENGTH);		

			/* Since the number of fragments for the last transmitted frame is	*/
			/* already decremented, there will be more fragments to transmit  	*/
			/* if number of fragments is more than zero.					  	*/
			if (num_fragments != 1)	
			{
				/* If more fragments need to be transmitted then the station 	*/
				/* need to compute the duration until the receipt of the       	*/
				/* the acknowledgement for the next fragment. 224 bits (header	*/
				/* size) is the length of the control fields in the data  		*/
				/* frame and needs to be accounted in the duration calculation.	*/
				if (num_fragments == 2)
					tx_datapacket_size = remainder_size + WLANC_MSDU_HEADER_SIZE;
				else
					tx_datapacket_size = (frag_threshold * 8) + WLANC_MSDU_HEADER_SIZE;
				duration = 2 * duration + sifs_time + TXTIME_DATA (tx_datapacket_size);
			}

			/* Set the type of the expected response to "ACK".	*/			
			expected_frame_type = WlanC_Ack;

			/* Station update its own nav_duration during CP   	*/
			/* NAV should be updated only during the CP period 	*/
			/* During CFP NAV duration is updated only during	*/
			/* the transmission of the beacon frames			*/
	

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -