/********************************************************************* * Function: void ICMPPut(NODE_INFO *remote, * ICMP_CODE code, * BYTE *data, * BYTE len, * WORD id, * WORD seq) * * PreCondition: ICMPIsTxReady() == TRUE * * Input: remote - Remote node info * code - ICMP_ECHO_REPLY or ICMP_ECHO_REQUEST * data - Data bytes * len - Number of bytes to send * id - ICMP identifier * seq - ICMP sequence number * * Output: None * * Side Effects: None * * Note: A ICMP packet is created and put on MAC. * ********************************************************************/ void ICMPPut(NODE_INFO *remote, ICMP_CODE code, BYTE *data, BYTE len, WORD id, WORD seq) { ICMP_PACKET packet; packet.Code = 0; packet.Type = code; packet.Checksum = 0; packet.Identifier = id; packet.SequenceNumber = seq; memcpy((void*)packet.Data, (void*)data, len); SwapICMPPacket(&packet); packet.Checksum = CalcIPChecksum((BYTE*)&packet, (WORD)(ICMP_HEADER_SIZE + len)); IPPutHeader(remote, IP_PROT_ICMP, (WORD)(ICMP_HEADER_SIZE + len)); IPPutArray((BYTE*)&packet, (WORD)(ICMP_HEADER_SIZE + len)); MACFlush(); }
/** * A ICMP packet is created and put on MAC. * * @preCondition ICMPIsTxReady() == TRUE * * @param remote Remote node info * @param code ICMP_ECHO_REPLY or ICMP_ECHO_REQUEST * @param data Data bytes * @param len Number of bytes to send * @param id ICMP identifier * @param seq ICMP sequence number */ void ICMPPut(NODE_INFO *remote, ICMP_CODE code, BYTE *data, BYTE len, WORD id, WORD seq) { ICMP_PACKET packet; WORD ICMPLen; BUFFER MyTxBuffer; MyTxBuffer = MACGetTxBuffer(TRUE); // Abort if there is no where in the Ethernet controller to // store this packet. if(MyTxBuffer == INVALID_BUFFER) return; IPSetTxBuffer(MyTxBuffer, 0); ICMPLen = ICMP_HEADER_SIZE + (WORD)len; packet.Code = 0; packet.Type = code; packet.Checksum = 0; packet.Identifier = id; packet.SequenceNumber = seq; memcpy((void*)packet.Data, (void*)data, len); SwapICMPPacket(&packet); #if defined(NON_MCHP_MAC) //This is NOT a Microchip MAC packet.Checksum = CalcIPChecksum((BYTE*)&packet, ICMPLen); #endif IPPutHeader(remote, IP_PROT_ICMP, (WORD)(ICMP_HEADER_SIZE + len)); IPPutArray((BYTE*)&packet, ICMPLen); #if !defined(NON_MCHP_MAC) //This is a Microchip MAC // Calculate and write the ICMP checksum using the Microchip MAC's DMA packet.Checksum = MACCalcTxChecksum(sizeof(IP_HEADER), ICMPLen); IPSetTxBuffer(MyTxBuffer, 2); MACPutArray((BYTE*)&packet.Checksum, 2); #endif MACFlush(); }
/********************************************************************* * Function: BOOL UDPFlush(void) * * PreCondition: UDPPut() is already called and desired UDP socket * is set as an active socket by calling * UDPIsPutReady(). * * Input: None * * Output: All and any data associated with active UDP socket * buffer is marked as ready for transmission. * * Side Effects: None * * Overview: None * * Note: This function transmit all data from * an active UDP socket. ********************************************************************/ void UDPFlush(void) { UDP_HEADER h; UDP_SOCKET_INFO *p; /* * When using SLIP (USART), packet transmission takes some time * and hence before sending another packet, we must make sure * that, last packet is transmitted. * When using ethernet controller, transmission occurs very fast * and by the time next packet is transmitted, previous is * transmitted and we do not need to check for last packet. */ //while( !IPIsTxReady() ); p = &UDPSocketInfo[activeUDPSocket]; h.SourcePort = swaps(p->localPort); h.DestinationPort = swaps(p->remotePort); h.Length = (WORD)((WORD)p->TxCount + (WORD)sizeof(UDP_HEADER)); // Do not swap h.Length yet. It is needed in IPPutHeader. h.Checksum = 0x00; IPSetTxBuffer(p->TxBuffer, 0); /* * Load IP header. */ IPPutHeader( &p->remoteNode, IP_PROT_UDP, h.Length ); // Now swap h.Length. h.Length = swaps(h.Length); /* * Now load UDP header. */ IPPutArray((BYTE*)&h, sizeof(h)); /* * Update checksum. * TO BE IMPLEMENTED */ MACFlush(); p->TxBuffer = INVALID_BUFFER; p->TxCount = 0; }
/** * This function transmit all data from the active UDP socket. * * @preCondition UDPPut() is already called and desired UDP socket * is set as an active socket by calling * UDPIsPutReady(). * * @return All and any data associated with active UDP socket * buffer is marked as ready for transmission. * */ void UDPFlush(void) { UDP_HEADER h; UDP_SOCKET_INFO *p; // Wait for TX hardware to become available (finish transmitting // any previous packet) while( !IPIsTxReady(TRUE) ) FAST_USER_PROCESS(); p = &UDPSocketInfo[activeUDPSocket]; h.SourcePort.Val = swaps(p->localPort); h.DestinationPort.Val = swaps(p->remotePort); h.Length.Val = (WORD)((WORD)p->TxCount + (WORD)sizeof(UDP_HEADER)); // Do not swap h.Length yet. It is needed in IPPutHeader. h.Checksum.Val = 0x00; //Makes the given TX Buffer active, and set's the pointer to the first byte after the IP //header. This is the first byte of the UDP header. The UDP header follows the IP header. IPSetTxBuffer(p->TxBuffer, 0); //Load IP header. IPPutHeader( &p->remoteNode, IP_PROT_UDP, h.Length.Val ); //Now swap h.Length.Val h.Length.Val = swaps(h.Length.Val); //Now load UDP header. IPPutArray((BYTE*)&h, sizeof(h)); //Update checksum. !!!!!!!!!!!!!!! TO BE IMPLEMENTED !!!!!!!!!!!!!!!!!!! //Send data contained in TX Buffer via MAC MACFlush(); // The buffer was reserved with AutoFree, so we can immediately // discard it. The MAC layer will free it after transmission. p->TxBuffer = INVALID_BUFFER; p->TxCount = 0; }
/********************************************************************* * Function: BOOL UDPFlush(void) * * PreCondition: UDPPut() is already called and desired UDP socket * is set as an active socket by calling * UDPIsPutReady(). * * Input: None * * Output: All and any data associated with active UDP socket * buffer is marked as ready for transmission. * * Side Effects: None * * Overview: None * * Note: This function transmit all data from * an active UDP socket. ********************************************************************/ void UDPFlush(void) { UDP_HEADER h; UDP_SOCKET_INFO *p; // Wait for TX hardware to become available (finish transmitting // any previous packet) while( !IPIsTxReady(TRUE) ); p = &UDPSocketInfo[activeUDPSocket]; debug_udp("\r\nUDP FLUSH - Sok:%U TxC:%LU SP:%LU DP:%LU ", activeUDPSocket, p->TxCount, p->localPort, p->remotePort ); debug_udp("MAC-%X:%X:%X:%X:%X:%X", p->remoteNode.MACAddr.v[0], p->remoteNode.MACAddr.v[1], p->remoteNode.MACAddr.v[2], p->remoteNode.MACAddr.v[3], p->remoteNode.MACAddr.v[4], p->remoteNode.MACAddr.v[5] ); h.SourcePort = swaps(p->localPort); h.DestinationPort = swaps(p->remotePort); h.Length = (WORD)((WORD)p->TxCount + (WORD)sizeof(UDP_HEADER)); // Do not swap h.Length yet. It is needed in IPPutHeader. h.Checksum = 0x0000; IPSetTxBuffer(p->TxBuffer, 0); /* * Load IP header. */ IPPutHeader( &p->remoteNode, IP_PROT_UDP, h.Length ); // Now swap h.Length. h.Length = swaps(h.Length); // Now load UDP header. IPPutArray((BYTE*)&h, sizeof(h)); // Update checksum. // TO BE IMPLEMENTED MACFlush(); // The buffer was reserved with AutoFree, so we can immediately // discard it. The MAC layer will free it after transmission. p->TxBuffer = INVALID_BUFFER; p->TxCount = 0; }
/** * This function transmit all data from the active UDP socket. * * @preCondition UDPPut() is already called and desired UDP socket * is set as an active socket by calling * UDPIsPutReady(). * * @return All and any data associated with active UDP socket * buffer is marked as ready for transmission. * */ void UDPFlush(void) { UDP_HEADER h; UDP_SOCKET_INFO *p; WORD csLength; DWORD_VAL csChecksum; // Wait for TX hardware to become available (finish transmitting // any previous packet) while( !IPIsTxReady(TRUE) ) FAST_USER_PROCESS(); p = &UDPSocketInfo[activeUDPSocket]; h.SourcePort.Val = swaps(p->localPort); h.DestinationPort.Val = swaps(p->remotePort); h.Length.Val = (WORD)((WORD)p->TxCount + (WORD)sizeof(UDP_HEADER)); // Do not swap h.Length yet. It is needed in IPPutHeader. h.Checksum.Val = 0x00; //Makes the given TX Buffer active, and set's the pointer to the first byte after the IP //header. This is the first byte of the UDP header. The UDP header follows the IP header. IPSetTxBuffer(p->TxBuffer, 0); //Load IP header. IPPutHeader( &p->remoteNode, IP_PROT_UDP, h.Length.Val ); // save length before swap for checksum calculation csLength = p->TxCount; //Now swap h.Length.Val h.Length.Val = swaps(h.Length.Val); //Now load UDP header. IPPutArray((BYTE*)&h, sizeof(h)); //Update checksum. !!!!!!!!!!!!!!! TO BE IMPLEMENTED !!!!!!!!!!!!!!!!!!! // Update checksum. // start the checksum with value for UDP protocol & length from pseudo header (and in the actual packet) csChecksum.Val = (WORD)IP_PROT_UDP + (WORD)csLength + sizeof(UDP_HEADER); // add in my address and the remoteNode address csChecksum.Val += ((WORD)MY_IP_BYTE1 << 8) + MY_IP_BYTE2; csChecksum.Val += ((WORD)MY_IP_BYTE3 << 8) + MY_IP_BYTE4; csChecksum.Val += ((WORD)p->remoteNode.IPAddr.v[0] << 8) + ((WORD)p->remoteNode.IPAddr.v[1] ) + ((WORD)p->remoteNode.IPAddr.v[2] << 8) + ((WORD)p->remoteNode.IPAddr.v[3] ); // set mac pointer to the ip_addr of the source, so all of pseudo header but length is included. // length of pseudo header is already included in previous instruction. //MACSetRxBuffer( sizeof(IP_HEADER)+sizeof(UDP_HEADER) ); csChecksum.Val += (WORD)p->localPort; csChecksum.Val += (WORD)p->remotePort; csChecksum.Val += (WORD)csLength + sizeof(UDP_HEADER); //IPSetRxBuffer(BASE_TX_ADDR + sizeof(ETHER_HEADER) + sizeof(IP_HEADER) - ( sizeof(IP_ADDR) * 2 ) ); // handled in UdpPut routines csChecksum.Val += udpChecksum; // add any carry over to the last word while((DWORD)csChecksum.word.MSW) { csChecksum.Val = (DWORD)csChecksum.word.LSW + (DWORD)csChecksum.word.MSW; } // add any carry over from adding the carry over //csChecksum.Val = (DWORD)csChecksum.word.LSW + (DWORD)csChecksum.word.MSW; // invert csChecksum.Val = ~csChecksum.Val; // set write pointer to location of checksum in packet //MACSetWritePtr( sizeof(ETHER_HEADER) + sizeof(IP_HEADER) + sizeof(UDP_HEADER) - 2 ); IPSetTxBuffer(p->TxBuffer, sizeof(UDP_HEADER) - 2); // write the swapped checksum to the packet //MACPut( csChecksum.v[1] ); //MACPut( csChecksum.v[0] ); MACPut(0); MACPut(0); //Send data contained in TX Buffer via MAC MACFlush(); // The buffer was reserved with AutoFree, so we can immediately // discard it. The MAC layer will free it after transmission. p->TxBuffer = INVALID_BUFFER; p->TxCount = 0; }