/** * * This function will process the received packet. This function sends * the echo request packet based on the ARP reply packet. * * @param InstancePtr is a pointer to the instance of the EmacLite. * * @return XST_SUCCESS is returned when an echo reply is received. * Otherwise, XST_FAILURE is returned. * * @note This assumes MAC does not strip padding or CRC. * ******************************************************************************/ static int ProcessRecvFrame(XEmacLite *InstancePtr) { u16 *RxFramePtr; u16 *TempPtr; u16 CheckSum; int Index; int Match = 0; int DataWrong = 0; RxFramePtr = (u16 *)RxFrame; TempPtr = (u16 *)LocalMacAddr; /* * Check Dest Mac address of the packet with the LocalMac address. */ Match = CompareData(RxFramePtr, TempPtr, 0, 0, MAC_ADDR_LEN); if (Match == XST_SUCCESS) { /* * Check ARP type. */ if (Xil_Ntohs(*(RxFramePtr + ETHER_PROTO_TYPE_LOC)) == XEL_ETHER_PROTO_TYPE_ARP ) { /* * Check ARP status. */ if (Xil_Ntohs(*(RxFramePtr + ARP_REQ_STATUS_LOC)) == ARP_REPLY) { /* * Check destination IP address with * packet's source IP address. */ TempPtr = (u16 *)DestIpAddress; Match = CompareData(RxFramePtr, TempPtr, ARP_REQ_SRC_IP_LOC, 0, IP_ADDR_LEN); if (Match == XST_SUCCESS) { /* * Copy src Mac address of the received * packet. */ Index = MAC_ADDR_LEN; TempPtr = (u16 *)DestMacAddr; while (Index--) { *(TempPtr + Index) = *(RxFramePtr + (SRC_MAC_ADDR_LOC + Index)); } /* * Send Echo request packet. */ SendEchoReqFrame(InstancePtr); } } } /* * Check for IP type. */ else if (Xil_Ntohs(*(RxFramePtr + ETHER_PROTO_TYPE_LOC)) == XEL_ETHER_PROTO_TYPE_IP) { /* * Calculate checksum. */ CheckSum = CheckSumCalculation(RxFramePtr, ICMP_DATA_START_LOC, ICMP_DATA_FIELD_LEN); /* * Verify checksum, echo reply, identifier number and * sequence number of the received packet. */ if ((CheckSum == CORRECT_CHECKSUM_VALUE) && (Xil_Ntohs(*(RxFramePtr + ICMP_ECHO_FIELD_LOC)) == ECHO_REPLY) && (Xil_Ntohs(*(RxFramePtr + ICMP_IDEN_FIELD_LOC)) == IDEN_NUM) && (Xil_Ntohs(*(RxFramePtr + (ICMP_SEQ_NO_LOC))) == SeqNum)) { /* * Verify data in the received packet with known * data. */ TempPtr = IcmpData; Match = CompareData(RxFramePtr, TempPtr, ICMP_KNOWN_DATA_LOC, 0, ICMP_KNOWN_DATA_LEN); if (Match == XST_FAILURE) { DataWrong = 1; } } if (DataWrong != 1) { xil_printf("Packet No: %d ", NUM_OF_PING_REQ_PKTS - NumOfPingReqPkts); xil_printf("Seq NO %d Echo Packet received\r\n", SeqNum); return XST_SUCCESS; } } } return XST_FAILURE; }
/** * * 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); }