Example #1
0
void xilnet_icmp_echo_reply(unsigned char *buf, unsigned int len, unsigned int eth_dev_num) {
  
   unsigned char * sendbuf = (unsigned char *)eth_device[eth_dev_num].sendbuf;

   struct xilnet_icmp_hdr* icmp_req   = (struct xilnet_icmp_hdr*)(buf + IP_HDR_LEN*4);
   struct xilnet_icmp_hdr* icmp_reply = (struct xilnet_icmp_hdr*)(sendbuf+LINK_HDR_LEN+IP_HDR_LEN*4);
   unsigned char * icmp_data          = sendbuf+LINK_HDR_LEN+IP_HDR_LEN*4+ICMP_HDR_LEN;

#ifdef _DEBUG_
    xil_printf("In xilnet_imcp_echo_reply(): \n");
#endif

   // copy the icmp echo request data 
   memcpy(icmp_data, buf+IP_HDR_LEN*4 + ICMP_HDR_LEN, (len - (IP_HDR_LEN*4 +ICMP_HDR_LEN)));

   icmp_reply->type      = ICMP_ECHO_REPLY_TYPE;
   icmp_reply->code      = ICMP_ECHO_CODE;
   icmp_reply->check_sum = 0;
   icmp_reply->ident     = icmp_req->ident;
   icmp_reply->seq_no    = icmp_req->seq_no;
   icmp_reply->check_sum = Xil_Htons(xilnet_ip_calc_chksum(sendbuf + LINK_HDR_LEN+(IP_HDR_LEN*4), len - (IP_HDR_LEN*4)));
   
   // call ip
   xilnet_ip_header(sendbuf+LINK_HDR_LEN, len, IP_PROTO_ICMP, (buf+IP_SADDR_BASE), eth_dev_num );
   
   // call ethernet
   xilnet_eth_send_frame(sendbuf, len+ETH_HDR_LEN, (buf+IP_SADDR_BASE), NULL, ETH_PROTO_IP, eth_dev_num);
   
}
/**
*
* This function sends a frame of given size. This function assumes interrupt
* mode and sends the frame.
*
* @param	XEmacInstancePtr is a pointer to the XEmacLite instance to be
*		worked on.
* @param	PayloadSize is the size of the frame to create. The size only
*		reflects the payload size, it does not include the Ethernet
*		header size (14 bytes) nor the Ethernet CRC size (4 bytes).
* @param	DestAddress if the address of the remote hardware the frame is
*		to be sent to.
*
* @return	XST_SUCCESS if successful, a driver-specific return code if not.
*
* @note		None.
*
******************************************************************************/
static int EmacLiteSendFrame(XEmacLite *XEmacInstancePtr, u32 PayloadSize)
{
	u8 *FramePtr;
	int Index;
	int Status;

	/*
	 * Set the Complete flag to false.
	 */
	TransmitComplete = FALSE;

	/*
	 * Assemble the frame with a destination address and the source address.
	 */
	FramePtr = (u8 *)TxFrame;
	*FramePtr++ = LocalAddress[0];
	*FramePtr++ = LocalAddress[1];
	*FramePtr++ = LocalAddress[2];
	*FramePtr++ = LocalAddress[3];
	*FramePtr++ = LocalAddress[4];
	*FramePtr++ = LocalAddress[5];

	/*
	 * Fill in the source MAC address.
	 */
	*FramePtr++ = LocalAddress[0];
	*FramePtr++ = LocalAddress[1];
	*FramePtr++ = LocalAddress[2];
	*FramePtr++ = LocalAddress[3];
	*FramePtr++ = LocalAddress[4];
	*FramePtr++ = LocalAddress[5];

	/*
	 * Set up the type/length field - be sure its in network order.
	 */
    *((u16 *)FramePtr) = Xil_Htons(PayloadSize);
    FramePtr++;
	FramePtr++;

	/*
	 * Now fill in the data field with known values so we can verify them
	 * on receive.
	 */
	for (Index = 0; Index < PayloadSize; Index++) {
		*FramePtr++ = (u8)Index;
	}

	/*
	 * Now send the frame.
	 */
	Status = XEmacLite_Send(XEmacInstancePtr, (u8 *)TxFrame,
			    PayloadSize + XEL_HEADER_SIZE);

	return  Status;
}
Example #3
0
/**
*
* This function sends a frame of given size.
*
* @param	XEmacInstancePtr is a pointer to the XEmacLite instance.
* @param	PayloadSize is the size of the frame to create. The size only
*		reflects the payload size, it does not include the Ethernet
*		header size (14 bytes) nor the Ethernet CRC size (4 bytes).
*
* @return	XST_SUCCESS if successful, else a driver-specific return code.
*
* @note		None.
*
******************************************************************************/
int EmacLiteSendFrame(XEmacLite *InstancePtr, u32 PayloadSize)
{
	u8 *FramePtr;
	int Index;
	FramePtr = (u8 *)TxFrame;

	/*
	 * Set up the destination address as the local address for
	 * Phy Loopback.
	 */
	/*
	 * Fill in the valid Destination MAC address if
	 * the Loopback is not enabled.
	 */
	*FramePtr++ = RemoteAddress[0];
	*FramePtr++ = RemoteAddress[1];
	*FramePtr++ = RemoteAddress[2];
	*FramePtr++ = RemoteAddress[3];
	*FramePtr++ = RemoteAddress[4];
	*FramePtr++ = RemoteAddress[5];

	/*
	 * Fill in the source MAC address.
	 */
	*FramePtr++ = LocalAddress[0];
	*FramePtr++ = LocalAddress[1];
	*FramePtr++ = LocalAddress[2];
	*FramePtr++ = LocalAddress[3];
	*FramePtr++ = LocalAddress[4];
	*FramePtr++ = LocalAddress[5];

	/*
	 * Set up the type/length field - be sure its in network order.
	 */
    *((u16 *)FramePtr) = Xil_Htons(PayloadSize);
	FramePtr++;
	FramePtr++;

	/*
	 * Now fill in the data field with known values so we can verify them
	 * on receive.
	 */
	for (Index = 0; Index < PayloadSize; Index++) {
		*FramePtr++ = (u8)Index;
	}

	/*
	 * Now send the frame.
	 */
	return XEmacLite_Send(InstancePtr, (u8 *)TxFrame,
				PayloadSize + XEL_HEADER_SIZE);

}
/**
*
* This function calculates the checksum and returns a 16 bit result.
*
* @param 	RxFramePtr is a 16 bit pointer for the data to which checksum
* 		is to be calculated.
* @param	StartLoc is the starting location of the data from which the
*		checksum has to be calculated.
* @param	Length is the number of halfwords(16 bits) to which checksum is
* 		to be calculated.
*
* @return	It returns a 16 bit checksum value.
*
* @note		This can also be used for calculating checksum. The ones
* 		complement of this return value will give the final checksum.
*
******************************************************************************/
static u16 CheckSumCalculation(u16 *RxFramePtr, int StartLoc, int Length)
{
	u32 Sum = 0;
	u16 CheckSum = 0;
	int Index;

	/*
	 * Add all the 16 bit data.
	 */
	Index = StartLoc;
	while (Index < (StartLoc + Length)) {
		Sum = Sum + Xil_Htons(*(RxFramePtr + Index));
		Index++;
	}

	/*
	 * Add upper 16 bits to lower 16 bits.
	 */
	CheckSum = Sum;
	Sum = Sum>>16;
	CheckSum = Sum + CheckSum;
	return CheckSum;
}
void wlan_poll_eth() {
	XAxiDma_BdRing *rxRing_ptr;
	XAxiDma_Bd *cur_bd_ptr;
	XAxiDma_Bd *first_bd_ptr;
	u8* mpdu_start_ptr;
	u8* eth_start_ptr;
	u8* eth_mid_ptr;
	packet_bd* tx_queue;
	u32 eth_rx_len, eth_rx_buf;
	u32 mpdu_tx_len;
	packet_bd_list tx_queue_list;
	u32 i;
	u8 continue_loop;

	int bd_count;
	int status;
	int packet_is_queued;

	ethernet_header* eth_hdr;
	ipv4_header* ip_hdr;
	arp_packet* arp;
	udp_header* udp;
	dhcp_packet* dhcp;

	llc_header* llc_hdr;
	u8 eth_dest[6];
	u8 eth_src[6];

	static u32 max_bd_count = 0;

	rxRing_ptr = XAxiDma_GetRxRing(&ETH_A_DMA_Instance);

	//Check if any Rx BDs have been executed
	//TODO: process XAXIDMA_ALL_BDS instead of 1 at a time
	//bd_count = XAxiDma_BdRingFromHw(rxRing_ptr, 1, &cur_bd_ptr);
	bd_count = XAxiDma_BdRingFromHw(rxRing_ptr, XAXIDMA_ALL_BDS, &first_bd_ptr);
	cur_bd_ptr = first_bd_ptr;

	if(bd_count > max_bd_count){
		max_bd_count = bd_count;
		//xil_printf("max_bd_count = %d\n",max_bd_count);
	}

	if(bd_count == 0) {
		//No Rx BDs have been processed - no new Eth receptions waiting
		return;
	}

	for(i=0;i<bd_count;i++){

		//A packet has been received and transferred by DMA
		tx_queue = (packet_bd*)XAxiDma_BdGetId(cur_bd_ptr);

		//xil_printf("DMA has filled in packet_bd at 0x%08x\n", tx_queue);

		eth_rx_len = XAxiDma_BdGetActualLength(cur_bd_ptr, rxRing_ptr->MaxTransferLen);
		eth_rx_buf = XAxiDma_BdGetBufAddr(cur_bd_ptr);

		//After encapsulation, byte[0] of the MPDU will be at byte[0] of the queue entry frame buffer
		mpdu_start_ptr = (void*)((tx_packet_buffer*)(tx_queue->buf_ptr))->frame;

		eth_start_ptr = (u8*)eth_rx_buf;

		//Calculate actual wireless Tx len (eth payload - eth header + wireless header)
		mpdu_tx_len = eth_rx_len - sizeof(ethernet_header) + sizeof(llc_header) + sizeof(mac_header_80211);

		//Helper pointers to interpret/fill fields in the new MPDU
		eth_hdr = (ethernet_header*)eth_start_ptr;
		llc_hdr = (llc_header*)(mpdu_start_ptr + sizeof(mac_header_80211));

		//Copy the src/dest addresses from the received Eth packet to temp space
		memcpy(eth_src, eth_hdr->address_source, 6);
		memcpy(eth_dest, eth_hdr->address_destination, 6);

		//Prepare the MPDU LLC header
		llc_hdr->dsap = LLC_SNAP;
		llc_hdr->ssap = LLC_SNAP;
		llc_hdr->control_field = LLC_CNTRL_UNNUMBERED;
		bzero((void *)(llc_hdr->org_code), 3); //Org Code 0x000000: Encapsulated Ethernet

		packet_is_queued = 0;
		packet_bd_list tx_queue_list;
		packet_bd_list_init(&tx_queue_list);
		packet_bd_insertEnd(&tx_queue_list, tx_queue);

		switch(eth_encap_mode){
			case ENCAP_MODE_AP:

				switch(eth_hdr->type) {
					case ETH_TYPE_ARP:
						llc_hdr->type = LLC_TYPE_ARP;
						packet_is_queued = eth_rx_callback(&tx_queue_list, eth_dest, eth_src, mpdu_tx_len);
					break;
					case ETH_TYPE_IP:
						llc_hdr->type = LLC_TYPE_IP;
						packet_is_queued = eth_rx_callback(&tx_queue_list, eth_dest, eth_src, mpdu_tx_len);
					break;

					/* WMP_START */
					case WMP4WARP_ETHER_TYPE:
						wmp_high_util_handle_wmp_cmd_from_ethernet(eth_hdr);
					break;
					/* WMP_END */
					default:
						//Unknown/unsupported EtherType; don't process the Eth frame
					break;
				}

			break;

			case ENCAP_MODE_STA:

				//Save this ethernet src address for d
				memcpy(eth_sta_mac_addr, eth_src, 6);
				memcpy(eth_src, hw_info.hw_addr_wlan, 6);

				switch(eth_hdr->type) {
					case ETH_TYPE_ARP:
						arp = (arp_packet*)((void*)eth_hdr + sizeof(ethernet_header));

						//Here we hijack ARP messages and overwrite their source MAC address field with
						//the station's wireless MAC address.
						memcpy(arp->eth_src, hw_info.hw_addr_wlan, 6);

						llc_hdr->type = LLC_TYPE_ARP;
						packet_is_queued = eth_rx_callback(&tx_queue_list, eth_dest, eth_src, mpdu_tx_len);


					break;
					case ETH_TYPE_IP:
						llc_hdr->type = LLC_TYPE_IP;
						ip_hdr = (ipv4_header*)((void*)eth_hdr + sizeof(ethernet_header));

						if(ip_hdr->prot == IPV4_PROT_UDP){
							udp = (udp_header*)((void*)ip_hdr + 4*((u8)(ip_hdr->ver_ihl) & 0xF));
							udp->checksum = 0; //Disable the checksum since we are about to mess with the bytes in the packet

							if(Xil_Ntohs(udp->src_port) == UDP_SRC_PORT_BOOTPC || Xil_Ntohs(udp->src_port) == UDP_SRC_PORT_BOOTPS){
								//This is a DHCP Discover packet, which contains the source hardware address
								//deep inside the packet (in addition to its usual location in the Eth header).
								//For STA encapsulation, we need to overwrite this address with the MAC addr
								//of the wireless station.

								dhcp = (dhcp_packet*)((void*)udp + sizeof(udp_header));

								if(Xil_Ntohl(dhcp->magic_cookie) == DHCP_MAGIC_COOKIE){
									eth_mid_ptr = (u8*)((void*)dhcp + sizeof(dhcp_packet));

									dhcp->flags = Xil_Htons(DHCP_BOOTP_FLAGS_BROADCAST);

									//Tagged DHCP Options
									continue_loop = 1;

									while(continue_loop){
										switch(eth_mid_ptr[0]){

											case DHCP_OPTION_TAG_TYPE:
												switch(eth_mid_ptr[2]){
													case DHCP_OPTION_TYPE_DISCOVER:
													case DHCP_OPTION_TYPE_REQUEST:
														//memcpy(dhcp->chaddr,hw_info.hw_addr_wlan,6);
													break;

												}

											break;

											case DHCP_OPTION_TAG_IDENTIFIER:
												//memcpy(&(eth_mid_ptr[3]),hw_info.hw_addr_wlan,6);

											break;

											case DHCP_OPTION_END:
												continue_loop = 0;
											break;
										}
										eth_mid_ptr += (2+eth_mid_ptr[1]);
									}
								}
							}
						}
						packet_is_queued = eth_rx_callback(&tx_queue_list, eth_dest, eth_src, mpdu_tx_len);

					break;

					/* WMP_START */
					case WMP4WARP_ETHER_TYPE:{
						wmp_high_util_handle_wmp_cmd_from_ethernet(eth_hdr);
					break;}
					/* WMP_END */
					default:
						//Unknown/unsupported EtherType; don't process the Eth frame
					break;
			}

			break;

		}

		if(packet_is_queued == 0){
			//xil_printf("   ...checking in\n");
			queue_checkin(&tx_queue_list);
		}

		//TODO: Option A: We free this single BD and run the routine to checkout as many queues as we can and hook them up to BDs
		//Results: pretty good TCP performance
		//Free this bd
		status = XAxiDma_BdRingFree(rxRing_ptr, 1, cur_bd_ptr);
		if(status != XST_SUCCESS) {xil_printf("Error in XAxiDma_BdRingFree of Rx BD! Err = %d\n", status); return;}
		wlan_eth_dma_update();

		//Update cur_bd_ptr to the next BD in the chain for the next iteration
		cur_bd_ptr = XAxiDma_BdRingNext(rxRing_ptr, cur_bd_ptr);

	}
	//TODO: Option B: We free all BDs at once and run the routine to checkout as many queues as we can and hook them up to BDs
	//Results: pretty lackluster TCP performance. needs further investigation
	//Free this bd
	//status = XAxiDma_BdRingFree(rxRing_ptr, bd_count, first_bd_ptr);
	//if(status != XST_SUCCESS) {xil_printf("Error in XAxiDma_BdRingFree of Rx BD! Err = %d\n", status); return;}
	//wlan_eth_dma_update();

	return;
}
/**
*
* This function processes the received packet and generates the corresponding
* reply packets.
*
* @param	InstancePtr is a pointer to the instance of the EmacLite.
*
* @return	None.
*
* @note		This function assumes MAC does not strip padding or CRC.
*
******************************************************************************/
static void ProcessRecvFrame(XEmacLite *InstancePtr)
{
	u16 *RxFramePtr;
	u16 *TxFramePtr;
	u16 *TempPtr;
	u16 CheckSum;
	u32 NextTxBuffBaseAddr;
	int Index;
	int PacketType = 0;

	TxFramePtr = (u16 *)TxFrame;
	RxFramePtr = (u16 *)RxFrame;

	/*
	 * Determine the next expected Tx buffer address.
	 */
	NextTxBuffBaseAddr = XEmacLite_NextTransmitAddr(InstancePtr);

	/*
	 * Check the packet type.
	 */
	Index = MAC_ADDR_LEN;
	TempPtr = (u16 *)LocalMacAddr;
	while (Index--) {
		if (Xil_Ntohs((*(RxFramePtr + Index)) == BROADCAST_ADDR) &&
					(PacketType != MAC_MATCHED_PACKET)) {
			PacketType = BROADCAST_PACKET;
		} else if (Xil_Ntohs((*(RxFramePtr + Index)) == *(TempPtr + Index)) &&
					(PacketType != BROADCAST_PACKET)) {
			PacketType = MAC_MATCHED_PACKET;
		} else {
			PacketType = 0;
			break;
		}
	}

	/*
	 * Process broadcast packet.
	 */
	if (PacketType == BROADCAST_PACKET) {

		/*
		 * Check for an ARP Packet if so generate a reply.
		 */
		if (Xil_Ntohs(*(RxFramePtr + ETHER_PROTO_TYPE_LOC)) ==
				XEL_ETHER_PROTO_TYPE_ARP) {

			/*
			 * IP address of the local machine.
			 */
			TempPtr = (u16 *)LocalIpAddr;

			/*
			 * Check destination IP address of the packet with
			 * local IP address.
			 */
			if (
			((*(RxFramePtr + ARP_REQ_DEST_IP_LOC_1)) == *TempPtr++) &&
			((*(RxFramePtr + ARP_REQ_DEST_IP_LOC_2)) == *TempPtr++)) {

				/*
				 * Check ARP packet type(request/reply).
				 */
				if (Xil_Ntohs(*(RxFramePtr + ARP_REQ_STATUS_LOC)) ==
								ARP_REQUEST) {

					/*
					 * Add destination MAC address
					 * to the reply packet (i.e) source
					 * address of the received packet.
					 */
					Index = SRC_MAC_ADDR_LOC;
					while (Index < (SRC_MAC_ADDR_LOC +
							MAC_ADDR_LEN)) {
						*TxFramePtr++ =
							*(RxFramePtr + Index);
						Index++;
					}

					/*
					 * Add source (local) MAC address
					 * to the reply packet.
					 */
					Index = 0;
					TempPtr = (u16 *)LocalMacAddr;
					while (Index < MAC_ADDR_LEN) {
						*TxFramePtr++ = *TempPtr++;
						Index++;
					}

					/*
					 * Add Ethernet proto type H/W
					 * type(10/3MBps),H/W address length and
					 * protocol address len (i.e)same as in
					 * the received packet
					 */
					Index = ETHER_PROTO_TYPE_LOC;
					while (Index < (ETHER_PROTO_TYPE_LOC +
							ETHER_PROTO_TYPE_LEN +
							ARP_HW_TYPE_LEN +
							ARP_HW_ADD_LEN
							+ ARP_PROTO_ADD_LEN)) {
						*TxFramePtr++ =
							*(RxFramePtr + Index);
						Index++;
					}

					/*
					 * Add ARP reply status to the reply
					 * packet.
					 */
					*TxFramePtr++ = Xil_Htons(ARP_REPLY);

					/*
					 * Add local MAC Address
					 * to the reply packet.
					 */
					TempPtr = (u16 *)LocalMacAddr;
					Index = 0;
					while (Index < MAC_ADDR_LEN) {
						*TxFramePtr++ = *TempPtr++;
						Index++;
					}

					/*
					 * Add local IP Address
					 * to the reply packet.
					 */
					TempPtr = (u16 *)LocalIpAddr;
					Index = 0;
					while (Index < IP_ADDR_LEN) {
						*TxFramePtr++ = *TempPtr++ ;
						Index++;
					}

					/*
					 * Add Destination MAC Address
					 * to the reply packet from the received
					 * packet.
					 */
					Index = SRC_MAC_ADDR_LOC;
					while (Index < (SRC_MAC_ADDR_LOC +
							MAC_ADDR_LEN)) {
						*TxFramePtr++ =
							*(RxFramePtr + Index);
						Index++;
					}

					/*
					 * Add Destination IP Address
					 * to the reply packet.
					 */
					Index = ARP_REQ_SRC_IP_LOC;
					while (Index < (ARP_REQ_SRC_IP_LOC +
							IP_ADDR_LEN)) {
						*TxFramePtr++ =
								*(RxFramePtr + Index);
						Index++;
					}

					/*
					 * Fill zeros as per protocol.
					 */
					Index = 0;
					while (Index < ARP_ZEROS_LEN) {
						*TxFramePtr++ = 0x0000;
						Index++;
					}

					/*
					 * Transmit the Reply Packet.
					 */
					XEmacLite_Send(InstancePtr,
							(u8 *)&TxFrame,
							ARP_PACKET_SIZE);
				}
			}
		}
	}

	/*
	 * Process packets whose MAC address is matched.
	 */
 	if (PacketType == MAC_MATCHED_PACKET) {

		/*
		 * Check ICMP packet.
		 */
		if (Xil_Ntohs(*(RxFramePtr + ETHER_PROTO_TYPE_LOC)) ==
						XEL_ETHER_PROTO_TYPE_IP) {

			/*
			 * Check the IP header checksum.
			 */
			CheckSum = CheckSumCalculation(RxFramePtr,
						IP_HDR_START_LOC,
						IP_HDR_LEN);

			/*
			 * Check the Data field checksum.
			 */
			if (CheckSum == CORRECT_CKSUM_VALUE) {
				CheckSum = CheckSumCalculation(RxFramePtr,
						ICMP_DATA_START_LOC,
						ICMP_DATA_FIELD_LEN);
				if (CheckSum == CORRECT_CKSUM_VALUE) {

					/*
					 * Add destination address
					 * to the reply packet (i.e)source
					 * address of the received packet.
					 */
					Index = SRC_MAC_ADDR_LOC;
					while (Index < (SRC_MAC_ADDR_LOC +
							MAC_ADDR_LEN)) {
						*TxFramePtr++ =
							*(RxFramePtr + Index);
						Index++;
					}

					/*
					 * Add local MAC address
					 * to the reply packet.
					 */
					Index = 0;
					TempPtr = (u16 *)LocalMacAddr;
					while (Index < MAC_ADDR_LEN) {
						*TxFramePtr++ = *TempPtr++;
						Index++;
					}

					/*
					 * Add protocol type
					 * header length and, packet
					 * length(60 Bytes) to the reply packet.
					 */
					Index = ETHER_PROTO_TYPE_LOC;
					while (Index < (ETHER_PROTO_TYPE_LOC +
							ETHER_PROTO_TYPE_LEN +
							IP_VERSION_LEN +
							IP_PACKET_LEN)) {
						*TxFramePtr++ =
							*(RxFramePtr + Index);
						Index++;
					}

					/*
					 * Identification field a random number
					 * which is set to IDENT_FIELD_VALUE.
					 */
					*TxFramePtr++ = IDENT_FIELD_VALUE;

					/*
					 * Add fragment type, time to live and
					 * ICM field. It is same as in the
					 * received packet.
					 */
					Index = IP_FRAG_FIELD_LOC;
					while (Index < (IP_FRAG_FIELD_LOC +
							IP_TTL_ICM_LEN +
							IP_FRAG_FIELD_LEN)) {
						*TxFramePtr++ =
							*(RxFramePtr + Index);
						Index++;
					}

					/*
					 * Checksum first set to 0 and
					 * added in this field later.
					 */
					*TxFramePtr++ = 0x0000;

					/*
					 * Add Source IP address
					 */
					Index = 0;
					TempPtr = (u16 *)LocalIpAddr;
					while (Index < IP_ADDR_LEN) {
						*TxFramePtr++ = *TempPtr++;
						Index++;
					}

					/*
					 * Add Destination IP address.
					 */
					Index = ICMP_REQ_SRC_IP_LOC;
					while (Index < (ICMP_REQ_SRC_IP_LOC +
							IP_ADDR_LEN)) {
						*TxFramePtr++ =
							*(RxFramePtr + Index);
						Index++;
					}

					/*
					 * Calculate checksum, and
					 * add it in the appropriate field.
					 */
					CheckSum = CheckSumCalculation(
						 	(u16 *)TxFrame,
						 	IP_HDR_START_LOC,
						 	IP_HDR_LEN);
					CheckSum = ~CheckSum;
					*(TxFramePtr - IP_CSUM_LOC_BACK) =
								Xil_Htons(CheckSum);

					/*
					 * Echo reply status & checksum.
					 */
					Index = ICMP_ECHO_FIELD_LOC;
					while (Index < (ICMP_ECHO_FIELD_LOC +
							ICMP_ECHO_FIELD_LEN)) {
						*TxFramePtr++ = 0x0000;
						Index++;
					}

					/*
					 * Add data to buffer which was
					 * received from the packet.
					 */
					Index = ICMP_DATA_LOC;
					while (Index < (ICMP_DATA_LOC +
							ICMP_DATA_LEN)) {
						*TxFramePtr++ =
								(*(RxFramePtr + Index));
						Index++;
					}

					/*
					 * Generate checksum for the data and
					 * add it in the appropriate field.
					 */
					CheckSum = CheckSumCalculation(
							(u16 *)TxFrame,
							ICMP_DATA_START_LOC,
							ICMP_DATA_FIELD_LEN);
					CheckSum = ~CheckSum;
					*(TxFramePtr - ICMP_DATA_CSUM_LOC_BACK)
								= Xil_Htons(CheckSum);

					/*
					 * Transmit the frame.
					 */
					XEmacLite_Send(InstancePtr,
							(u8 *)&TxFrame,
							ICMP_PACKET_SIZE);

					/*
					 * Increment the number of
					 * Ping replies sent.
					 */
					NumOfPingReplies++;

				}
			}
		}
	}
}
/**
*
* This function will send a Echo request packet.
*
* @param	InstancePtr is a pointer to the instance of the EmacLite.
*
* @return	None.
*
* @note		None.
*
******************************************************************************/
static void SendEchoReqFrame(XEmacLite *InstancePtr)
{
	u16 *TempPtr;
	u16 *TxFramePtr;
	u16 *RxFramePtr;
	u16 CheckSum;
	u32 NextTxBuffBaseAddr;
	int Index;

	TxFramePtr = (u16 *)TxFrame;
	RxFramePtr = (u16 *)RxFrame;

	/*
	 * Determine the next expected transmit buffer base address.
	 */
	NextTxBuffBaseAddr = XEmacLite_NextTransmitAddr(InstancePtr);

	/*
	 * Add Destination MAC Address.
	 */
	Index = MAC_ADDR_LEN;
	while (Index--) {
		*(TxFramePtr + Index) = *(DestMacAddr + Index);
	}

	/*
	 * Add Source MAC Address.
	 */
	Index = MAC_ADDR_LEN;
	TempPtr = (u16 *)LocalMacAddr;
	while (Index--) {
		*(TxFramePtr + (Index + SRC_MAC_ADDR_LOC )) =
							*(TempPtr + Index);
	}

	/*
	 * Add IP header information.
	 */
	Index = IP_START_LOC;
	while (Index--) {
		*(TxFramePtr + (Index + ETHER_PROTO_TYPE_LOC )) =
				Xil_Htons(*(IpHeaderInfo + Index));
	}

	/*
	 * Add Source IP address.
	 */
	Index = IP_ADDR_LEN;
	TempPtr = (u16 *)LocalIpAddress;
	while (Index--) {
		*(TxFramePtr + (Index + IP_REQ_SRC_IP_LOC )) =
						*(TempPtr + Index);
	}

	/*
	 * Add Destination IP address.
	 */
	Index = IP_ADDR_LEN;
	TempPtr = (u16 *)DestIpAddress;
	while (Index--) {
		*(TxFramePtr + (Index + IP_REQ_DEST_IP_LOC )) =
						*(TempPtr + Index);
	}

	/*
	 * Checksum is calculated for IP field and added in the frame.
	 */
	CheckSum = CheckSumCalculation((u16 *)TxFrame, IP_START_LOC,
							IP_HEADER_LEN);
	CheckSum = ~CheckSum;
	*(TxFramePtr + IP_CHECKSUM_LOC) = Xil_Htons(CheckSum);

	/*
	 * Add echo field information.
	 */
	*(TxFramePtr + ICMP_ECHO_FIELD_LOC) = Xil_Htons(XEL_ETHER_PROTO_TYPE_IP);

	/*
	 * Checksum value is initialized to zeros.
	 */
	*(TxFramePtr + ICMP_DATA_LEN) = 0x0000;

	/*
	 * Add identifier and sequence number to the frame.
	 */
	*(TxFramePtr + ICMP_IDEN_FIELD_LOC) = (IDEN_NUM);
	*(TxFramePtr + (ICMP_IDEN_FIELD_LOC + 1)) = Xil_Htons((u16)(++SeqNum));

	/*
	 * Add known data to the frame.
	 */
	Index = ICMP_KNOWN_DATA_LEN;
	while (Index--) {
		*(TxFramePtr + (Index + ICMP_KNOWN_DATA_LOC)) =
				Xil_Htons(*(IcmpData + Index));
	}

	/*
	 * Checksum is calculated for Data Field and added in the frame.
	 */
	CheckSum = CheckSumCalculation((u16 *)TxFrame, ICMP_DATA_START_LOC,
						ICMP_DATA_FIELD_LEN );
	CheckSum = ~CheckSum;
	*(TxFramePtr + ICMP_DATA_CHECKSUM_LOC) = Xil_Htons(CheckSum);

	/*
	 * Transmit the Frame.
	 */
	XEmacLite_Send(InstancePtr, (u8 *)&TxFrame, ICMP_PKT_SIZE);
}
/**
*
* This function will send a ARP request packet.
*
* @param	InstancePtr is a pointer to the instance of the EmacLite.
*
* @return	None.
*
* @note		None.
*
******************************************************************************/
static void SendArpReqFrame(XEmacLite *InstancePtr)
{
	u16 *TempPtr;
	u16 *TxFramePtr;
	u32 NextTxBuffBaseAddr;
	int Index;

	TxFramePtr = (u16 *)TxFrame;

	/*
	 * Determine the next expected transmit buffer base address.
	 */
	NextTxBuffBaseAddr = XEmacLite_NextTransmitAddr(InstancePtr);

	/*
	 * Add broadcast address.
	 */
	Index = MAC_ADDR_LEN;
	while (Index--) {
		*TxFramePtr++ = BROADCAST_ADDR;
	}

	/*
	 * Add local MAC address.
	 */
	Index = 0;
	TempPtr = (u16 *)LocalMacAddr;
	while (Index < MAC_ADDR_LEN) {
		*TxFramePtr++ = *(TempPtr + Index);
		Index++;
	}

	/*
	 * Add
	 * 	- Ethernet proto type.
	 *	- Hardware Type
	 *	- Protocol IP Type
	 *	- IP version (IPv6/IPv4)
	 *	- ARP Request
	 */
	*TxFramePtr++ = Xil_Htons(XEL_ETHER_PROTO_TYPE_ARP);
	*TxFramePtr++ = Xil_Htons(HW_TYPE);
	*TxFramePtr++ = Xil_Htons(XEL_ETHER_PROTO_TYPE_IP);
	*TxFramePtr++ = Xil_Htons(IP_VERSION);
	*TxFramePtr++ = Xil_Htons(ARP_REQUEST);

	/*
	 * Add local MAC address.
	 */
	Index = 0;
	TempPtr = (u16 *)LocalMacAddr;
	while (Index < MAC_ADDR_LEN) {
		*TxFramePtr++ = *(TempPtr + Index);
		Index++;
	}

	/*
	 * Add local IP address.
	 */
	Index = 0;
	TempPtr = (u16 *)LocalIpAddress;
	while (Index < IP_ADDR_LEN) {
		*TxFramePtr++ = *(TempPtr + Index);
		Index++;
	}

	/*
	 * Fills 6 bytes of information with zeros as per protocol.
	 */
	Index = 0;
	while (Index < 3) {
		*TxFramePtr++ = 0x0000;
		Index++;
	}

	/*
	 * Add Destination IP address.
	 */
	Index = 0;
	TempPtr = (u16 *)DestIpAddress;
	while (Index < IP_ADDR_LEN) {
		*TxFramePtr++ = *(TempPtr + Index);
		Index++;
	}

	/*
	 * Transmit the Frame.
	 */
	XEmacLite_Send(InstancePtr, (u8 *)&TxFrame, ARP_REQ_PKT_SIZE);
}
/**
*
* This function sends a frame of given size. This function assumes interrupt
* mode and sends the frame.
*
* @param	EmacLiteInstPtr is a pointer to the EmacLite instance.
* @param	PayloadSize is the size of the frame to create. The size only
*		reflects the payload size, it does not include the Ethernet
*		header size (14 bytes) nor the Ethernet CRC size (4 bytes).
*
* @return	XST_SUCCESS if successful, else XST_FAILURE.
*
* @note		None.
*
******************************************************************************/
static int EmacLiteSendFrame(XEmacLite *EmacLiteInstPtr,  u32 PayloadSize)
{
	int Status;
	u8 *FramePtr;
	u32 Index;

	/*
	 * Set the Complete flag to false.
	 */
	TransmitComplete = FALSE;

	/*
	 * Assemble the frame with a destination address and the source address.
	 */
	FramePtr = (u8 *)TxFrame;

	/*
	 * Set up the destination address as the local address for
	 * Phy Loopback and Internal loopback.
	 */
	if (XEmacLite_IsMdioConfigured(EmacLiteInstPtr) ||
		XEmacLite_IsLoopbackConfigured(EmacLiteInstPtr)) {

		*FramePtr++ = LocalAddress[0];
		*FramePtr++ = LocalAddress[1];
		*FramePtr++ = LocalAddress[2];
		*FramePtr++ = LocalAddress[3];
		*FramePtr++ = LocalAddress[4];
		*FramePtr++ = LocalAddress[5];
	} else {
		/*
		 * Fill in the valid Destination MAC address if
		 * the Loopback is not enabled.
		 */
		*FramePtr++ = RemoteAddress[0];
		*FramePtr++ = RemoteAddress[1];
		*FramePtr++ = RemoteAddress[2];
		*FramePtr++ = RemoteAddress[3];
		*FramePtr++ = RemoteAddress[4];
		*FramePtr++ = RemoteAddress[5];
	}

	/*
	 * Fill in the source MAC address.
	 */
	*FramePtr++ = LocalAddress[0];
	*FramePtr++ = LocalAddress[1];
	*FramePtr++ = LocalAddress[2];
	*FramePtr++ = LocalAddress[3];
	*FramePtr++ = LocalAddress[4];
	*FramePtr++ = LocalAddress[5];

	/*
	 * Set up the type/length field - be sure its in network order.
	 */
    *((u16 *)FramePtr) = Xil_Htons(PayloadSize);
    FramePtr++;
	FramePtr++;

	/*
	 * Now fill in the data field with known values so we can verify them.
	 */
	for (Index = 0; Index < PayloadSize; Index++) {
		*FramePtr++ = (u8)Index;
	}

	/*
	 * Now send the frame.
	 */
	Status = XEmacLite_Send(EmacLiteInstPtr, (u8 *)TxFrame,
				PayloadSize + XEL_HEADER_SIZE);
	if (Status != XST_SUCCESS) {
		return XST_FAILURE;
	}

	return XST_SUCCESS;
}
Example #10
0
/**
 * This function is used to send a message over Ethernet
 *
 * @param   socket_index     - Index of the socket on which to send message
 * @param   to               - Pointer to socket address structure to send message
 * @param   buffers          - Array of transport buffers to send
 * @param   num_buffers      - Number of transport buffers in 'buffers' array
 *
 * @return  None
 *
 * @note    This function requires that the first transport buffer in the 'buffers'
 *          array contain the Transport header.
 *
 *****************************************************************************/
void transport_send(int socket_index, struct sockaddr * to, warp_ip_udp_buffer ** buffers, u32 num_buffers) {

    u32                      i;
    int                      status;
    transport_header       * transport_header_tx;
    u16                      buffer_length = 0;
	// interrupt_state_t     prev_interrupt_state;

    // Check that we have a valid socket to send a message on
    if (socket_index == SOCKET_INVALID_SOCKET) {
        wlan_exp_printf(WLAN_EXP_PRINT_ERROR, print_type_transport, "Invalid socket.\n");
        return;
    }

    // Initialize the header
    //     NOTE:  We require that the first warp_ip_udp_buffer always contain the wl_transport_header
    //
    transport_header_tx = (transport_header *)(buffers[0]->data);

    // Compute the length
    for (i = 0; i < num_buffers; i++) {
        buffer_length += buffers[i]->size;
    }

    //
    // NOTE:  Through performance testing, we found that it was faster to just manipulate the header
    //   in place vs creating a copy, updating the header and then restoring the copy.
    //

    // Make the outgoing transport header endian safe for sending on the network
    //     NOTE:  Set the 'length' to the computed value above
    //
    transport_header_tx->dest_id = Xil_Htons(transport_header_tx->dest_id);
    transport_header_tx->src_id  = Xil_Htons(transport_header_tx->src_id);
    transport_header_tx->length  = Xil_Htons(buffer_length + WARP_IP_UDP_DELIM_LEN);
    transport_header_tx->seq_num = Xil_Htons(transport_header_tx->seq_num);
    transport_header_tx->flags   = Xil_Htons(transport_header_tx->flags);

	// Check the interrupt status; Disable interrupts if enabled
    //     NOTE:  This is done inside the Eth send function
	// prev_interrupt_state = wlan_mac_high_interrupt_stop();

    // Send the Ethernet packet
    status = socket_sendto(socket_index, to, buffers, num_buffers);

	// Restore interrupts
    //     NOTE:  This is done inside the Eth send function
	// wlan_mac_high_interrupt_restore_state(prev_interrupt_state);

    // Restore wl_header_tx
	transport_header_tx->dest_id = Xil_Ntohs(transport_header_tx->dest_id);
	transport_header_tx->src_id  = Xil_Ntohs(transport_header_tx->src_id);
	transport_header_tx->length  = 0;
	transport_header_tx->seq_num = Xil_Ntohs(transport_header_tx->seq_num);
	transport_header_tx->flags   = Xil_Ntohs(transport_header_tx->flags);

    // Check that the packet was sent correctly
    if (status == WARP_IP_UDP_FAILURE) {
        wlan_exp_printf(WLAN_EXP_PRINT_WARNING, print_type_transport, "Issue sending packet %d to host.\n", transport_header_tx->seq_num);
    }
}
Example #11
0
/**
*
* This function sends a frame of given size. This function assumes interrupt
* mode and sends the frame.
*
* @param	EmacLiteInstPtr is a pointer to the EmacLite instance.
* @param	PayloadSize is the size of the frame to create. The size only
*		reflects the payload size, it does not include the Ethernet
*		header size (14 bytes) nor the Ethernet CRC size (4 bytes).
*
* @return	XST_SUCCESS if successful, else XST_FAILURE.
*
* @note		None.
*
******************************************************************************/
int EmacLiteSendFrame(u8 *Payload, u32 PayloadSize, MACAddr_t *DstMACAddr, short Type)
{
	int Status;
	int i;
	u8 *FramePtr;
	//u32 Index;

	/*
	 * Set the Complete flag to false.
	 */
	//TransmitComplete = FALSE;

	/*
	 * Assemble the frame with a destination address and the source address.
	 */
	FramePtr = (u8 *)TxFrame;

	/*
	 * Fill in the valid Destination MAC address if
	 * the Loopback is not enabled.
	 */
	*FramePtr++ = DstMACAddr->byte1;
	*FramePtr++ = DstMACAddr->byte2;
	*FramePtr++ = DstMACAddr->byte3;
	*FramePtr++ = DstMACAddr->byte4;
	*FramePtr++ = DstMACAddr->byte5;
	*FramePtr++ = DstMACAddr->byte6;

	/*
	 * Fill in the source MAC address.
	 */
	*FramePtr++ = LocalAddress[0];
	*FramePtr++ = LocalAddress[1];
	*FramePtr++ = LocalAddress[2];
	*FramePtr++ = LocalAddress[3];
	*FramePtr++ = LocalAddress[4];
	*FramePtr++ = LocalAddress[5];

	/*
	 * Set up the type/length field - be sure its in network order.
	 */
    *((u16 *)FramePtr) = Xil_Htons(Type);
    FramePtr++;
	FramePtr++;

	for (i = 0; i < PayloadSize; i++)
	{
		*FramePtr++ = Payload[i];
	}

	/*
	 * Now send the frame.
	 */
	Status = XEmacLite_Send(&eth_handle, (u8 *)TxFrame,
				PayloadSize + XEL_HEADER_SIZE);
	if (Status != XST_SUCCESS) {
		return XST_FAILURE;
	}

	return XST_SUCCESS;
}