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; }
/** * * 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(Ð_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; }
/** * 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); } }
/** * * 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(ð_handle, (u8 *)TxFrame, PayloadSize + XEL_HEADER_SIZE); if (Status != XST_SUCCESS) { return XST_FAILURE; } return XST_SUCCESS; }