diff --git a/source/include/FreeRTOS_IPv4_Private.h b/source/include/FreeRTOS_IPv4_Private.h index 0a57f5abf2..fcdd4d8afa 100644 --- a/source/include/FreeRTOS_IPv4_Private.h +++ b/source/include/FreeRTOS_IPv4_Private.h @@ -24,7 +24,7 @@ * https://www.FreeRTOS.org * https://github.com/FreeRTOS */ - + #ifndef FREERTOS_IPV4_PRIVATE_H #define FREERTOS_IPV4_PRIVATE_H /* *INDENT-OFF* */ diff --git a/source/include/NetworkInterface.h b/source/include/NetworkInterface.h index 719a4e082c..9bfe88a025 100644 --- a/source/include/NetworkInterface.h +++ b/source/include/NetworkInterface.h @@ -35,15 +35,19 @@ /* *INDENT-ON* */ /* INTERNAL API FUNCTIONS. */ -BaseType_t xNetworkInterfaceInitialise( void ); -BaseType_t xNetworkInterfaceOutput( NetworkBufferDescriptor_t * const pxNetworkBuffer, - BaseType_t xReleaseAfterSend ); -/* The following function is defined only when BufferAllocation_1.c is linked in the project. */ -void vNetworkInterfaceAllocateRAMToBuffers( NetworkBufferDescriptor_t pxNetworkBuffers[ ipconfigNUM_NETWORK_BUFFER_DESCRIPTORS ] ); +/* Since there are multiple interfaces, there are multiple versions + * of the following functions. + * These are now declared static in NetworkInterface.c and their addresses + * are stored in a struct NetworkInterfaceDescriptor_t. + * + * BaseType_t xNetworkInterfaceInitialise( struct xNetworkInterface *pxInterface ); + * BaseType_t xNetworkInterfaceOutput( struct xNetworkInterface *pxInterface, NetworkBufferDescriptor_t * const pxNetworkBuffer, BaseType_t xReleaseAfterSend ); + * BaseType_t xGetPhyLinkStatus( struct xNetworkInterface *pxInterface ); + */ /* The following function is defined only when BufferAllocation_1.c is linked in the project. */ -BaseType_t xGetPhyLinkStatus( void ); +void vNetworkInterfaceAllocateRAMToBuffers( NetworkBufferDescriptor_t pxNetworkBuffers[ ipconfigNUM_NETWORK_BUFFER_DESCRIPTORS ] ); /* *INDENT-OFF* */ #ifdef __cplusplus diff --git a/source/portable/NetworkInterface/STM32Fxx/NetworkInterface.c b/source/portable/NetworkInterface/STM32Fxx/NetworkInterface.c index 9ab6a0d793..0380cca0cc 100644 --- a/source/portable/NetworkInterface/STM32Fxx/NetworkInterface.c +++ b/source/portable/NetworkInterface/STM32Fxx/NetworkInterface.c @@ -50,6 +50,7 @@ #include "NetworkBufferManagement.h" #include "NetworkInterface.h" #include "phyHandling.h" +#include "FreeRTOS_Routing.h" #include "stm32fxx_hal_eth.h" @@ -181,7 +182,7 @@ static void prvEthernetUpdateConfig( BaseType_t xForce ); */ static BaseType_t prvNetworkInterfaceInput( void ); -#if ( ipconfigUSE_LLMNR != 0 ) || ( ipconfigUSE_MDNS != 0 ) +#if ( ipconfigUSE_LLMNR != 0 ) || ( ipconfigUSE_MDNS != 0 ) || ( ipconfigUSE_IPv6 != 0 ) /* * For LLMNR, an extra MAC-address must be configured to @@ -192,6 +193,27 @@ static BaseType_t prvNetworkInterfaceInput( void ); uint8_t * Addr ); #endif +/* FreeRTOS+TCP/multi : + * Each network device has 3 access functions: + * - Initialise the device + * - Output a network packet + * - Return the PHY Link-Status (LS) + * They can be defined as static because the function addresses + * will be stored in struct NetworkInterface_t. The latter will be done in + * the function pxFillInterfaceDescriptor(). */ + +static BaseType_t xNetworkInterfaceInitialise( NetworkInterface_t * pxInterface ); + +static BaseType_t xNetworkInterfaceOutput( NetworkInterface_t * pxInterface, + NetworkBufferDescriptor_t * const pxBuffer, + BaseType_t bReleaseAfterSend ); + +static BaseType_t xGetPhyLinkStatus( NetworkInterface_t * pxInterface ); + +NetworkInterface_t * pxFillInterfaceDescriptor( BaseType_t xEMACIndex, + NetworkInterface_t * pxInterface ); + + /* * Check if a given packet should be accepted. */ @@ -216,7 +238,9 @@ static void vClearTXBuffers( void ); #if ( ipconfigUSE_LLMNR == 1 ) static const uint8_t xLLMNR_MACAddress[] = { 0x01, 0x00, 0x5E, 0x00, 0x00, 0xFC }; #endif - +#if ( ipconfigUSE_MDNS == 1 ) + static const uint8_t xMDNS_MACAddressIPv4[] = { 0x01, 0x00, 0x5e, 0x00, 0x00, 0xfb }; +#endif static EthernetPhy_t xPhyObject; /* Ethernet handle. */ @@ -274,6 +298,8 @@ ETH_DMADescTypeDef DMATxDscrTab[ ETH_TXBUFNB ]; * that must be cleared by vClearTXBuffers(). */ static __IO ETH_DMADescTypeDef * DMATxDescToClear; +static NetworkInterface_t * pxMyInterface = NULL; + /* Holds the handle of the task used as a deferred interrupt processor. The * handle is used so direct notifications can be sent to the task for all EMAC/DMA * related interrupts. */ @@ -388,10 +414,11 @@ static void vClearTXBuffers() } /*-----------------------------------------------------------*/ -BaseType_t xNetworkInterfaceInitialise( void ) +static BaseType_t xNetworkInterfaceInitialise( NetworkInterface_t * pxInterface ) { HAL_StatusTypeDef hal_eth_init_status; - BaseType_t xResult; + BaseType_t xResult = pdPASS; + Network_EndPoint_t * pxEndPoint; #if ( ipconfigUSE_LLMNR != 0 ) || ( ipconfigUSE_MDNS != 0 ) BaseType_t xMACEntry = ETH_MAC_ADDRESS1; /* ETH_MAC_ADDRESS0 reserved for the primary MAC-address. */ @@ -408,6 +435,9 @@ BaseType_t xNetworkInterfaceInitialise( void ) else { /* Initialise ETH */ + pxMyInterface = pxInterface; + pxEndPoint = FreeRTOS_FirstEndPoint( pxInterface ); + configASSERT( pxEndPoint != NULL ); xETH.Instance = ETH; xETH.Init.AutoNegotiation = ETH_AUTONEGOTIATION_ENABLE; @@ -416,7 +446,7 @@ BaseType_t xNetworkInterfaceInitialise( void ) /* Value of PhyAddress doesn't matter, will be probed for. */ xETH.Init.PhyAddress = 0; - xETH.Init.MACAddr = ( uint8_t * ) FreeRTOS_GetMACAddress(); + xETH.Init.MACAddr = ( uint8_t * ) pxEndPoint->xMACAddress.ucBytes; xETH.Init.RxMode = ETH_RXINTERRUPT_MODE; #if ( ipconfigDRIVER_INCLUDED_TX_IP_CHECKSUM != 0 ) @@ -471,6 +501,12 @@ BaseType_t xNetworkInterfaceInitialise( void ) xMACEntry += 8; } #endif + #if ( ( ipconfigUSE_MDNS == 1 ) && ( ipconfigUSE_IPv6 != 0 ) ) + { + prvMACAddressConfig( &xETH, xMACEntry, ( uint8_t * ) xMDNS_MACAdressIPv6.ucBytes ); + xMACEntry += 8; + } + #endif #if ( ipconfigUSE_LLMNR == 1 ) { /* Program the LLMNR address. */ @@ -478,6 +514,59 @@ BaseType_t xNetworkInterfaceInitialise( void ) xMACEntry += 8; } #endif + #if ( ( ipconfigUSE_LLMNR == 1 ) && ( ipconfigUSE_IPv6 != 0 ) ) + { + prvMACAddressConfig( &xETH, xMACEntry, ( uint8_t * ) xLLMNR_MacAdressIPv6.ucBytes ); + xMACEntry += 8; + } + #endif + + { + /* The EMAC address of the first end-point has been registered in HAL_ETH_Init(). */ + for( ; + pxEndPoint != NULL; + pxEndPoint = FreeRTOS_NextEndPoint( pxMyInterface, pxEndPoint ) ) + { + #if ( ipconfigUSE_IPv6 != 0 ) + if( pxEndPoint->bits.bIPv6 != pdFALSE_UNSIGNED ) + { + uint8_t ucMACAddress[ 6 ] = { 0x33, 0x33, 0xff, 0, 0, 0 }; + + ucMACAddress[ 3 ] = pxEndPoint->ipv6_settings.xIPAddress.ucBytes[ 13 ]; + ucMACAddress[ 4 ] = pxEndPoint->ipv6_settings.xIPAddress.ucBytes[ 14 ]; + ucMACAddress[ 5 ] = pxEndPoint->ipv6_settings.xIPAddress.ucBytes[ 15 ]; + prvMACAddressConfig( &xETH, xMACEntry, ucMACAddress ); + xMACEntry += 8; + } + else + #else /* if ( ipconfigUSE_IPv6 != 0 ) */ + { + if( xETH.Init.MACAddr != ( uint8_t * ) pxEndPoint->xMACAddress.ucBytes ) + { + prvMACAddressConfig( &xETH, xMACEntry, pxEndPoint->xMACAddress.ucBytes ); + xMACEntry += 8; + } + } + #endif /* if ( ipconfigUSE_IPv6 != 0 ) */ + if( xMACEntry > ( BaseType_t ) ETH_MAC_ADDRESS3 ) + { + /* No more locations available. */ + break; + } + } + } + #if ( ipconfigUSE_IPv6 != 0 ) + { + if( xMACEntry <= ( BaseType_t ) ETH_MAC_ADDRESS3 ) + { + /* 33:33:00:00:00:01 */ + uint8_t ucMACAddress[ 6 ] = { 0x33, 0x33, 0, 0, 0, 0x01 }; + + prvMACAddressConfig( &xETH, xMACEntry, ucMACAddress ); + xMACEntry += 8; + } + } + #endif /* ( ipconfigUSE_IPv6 != 0 ) */ /* Force a negotiation with the Switch or Router and wait for LS. */ prvEthernetUpdateConfig( pdTRUE ); @@ -660,8 +749,9 @@ static void prvDMARxDescListInit() #endif /* if ( ipconfigUSE_LLMNR != 0 ) || ( ipconfigUSE_MDNS != 0 ) */ /*-----------------------------------------------------------*/ -BaseType_t xNetworkInterfaceOutput( NetworkBufferDescriptor_t * const pxDescriptor, - BaseType_t bReleaseAfterSend ) +static BaseType_t xNetworkInterfaceOutput( NetworkInterface_t * pxInterface, + NetworkBufferDescriptor_t * const pxDescriptor, + BaseType_t bReleaseAfterSend ) { BaseType_t xReturn = pdFAIL; uint32_t ulTransmitSize = 0; @@ -669,20 +759,53 @@ BaseType_t xNetworkInterfaceOutput( NetworkBufferDescriptor_t * const pxDescript /* Do not wait too long for a free TX DMA buffer. */ const TickType_t xBlockTimeTicks = pdMS_TO_TICKS( 50u ); + /* As there is only a single instance of the EMAC, there is only one pxInterface object. */ + ( void ) pxInterface; + /* Open a do {} while ( 0 ) loop to be able to call break. */ do { + if( xCheckLoopback( pxDescriptor, bReleaseAfterSend ) != 0 ) + { + /* The packet has been sent back to the IP-task. + * The IP-task will further handle it. + * Do not release the descriptor. */ + bReleaseAfterSend = pdFALSE; + break; + } + #if ( ipconfigDRIVER_INCLUDED_TX_IP_CHECKSUM != 0 ) { - ProtocolPacket_t * pxPacket; + const IPPacket_t * pxIPPacket; + + pxIPPacket = ipPOINTER_CAST( const IPPacket_t *, pxDescriptor->pucEthernetBuffer ); + #if ( ipconfigUSE_IPv6 != 0 ) + if( pxIPPacket->xEthernetHeader.usFrameType == ipIPv6_FRAME_TYPE ) + { + const IPHeader_IPv6_t * pxIPPacket_IPv6; + + pxIPPacket_IPv6 = ipPOINTER_CAST( const IPHeader_IPv6_t *, &( pxDescriptor->pucEthernetBuffer[ ipSIZE_OF_ETH_HEADER ] ) ); - /* If the peripheral must calculate the checksum, it wants - * the protocol checksum to have a value of zero. */ - pxPacket = ( ProtocolPacket_t * ) ( pxDescriptor->pucEthernetBuffer ); + if( pxIPPacket_IPv6->ucNextHeader == ( uint8_t ) ipPROTOCOL_ICMP_IPv6 ) + { + ICMPHeader_IPv6_t * pxICMPHeader_IPv6; - if( pxPacket->xICMPPacket.xIPHeader.ucProtocol == ( uint8_t ) ipPROTOCOL_ICMP ) + pxICMPHeader_IPv6 = ipPOINTER_CAST( ICMPHeader_IPv6_t *, &( pxDescriptor->pucEthernetBuffer[ ipSIZE_OF_ETH_HEADER + ipSIZE_OF_IPv6_HEADER ] ) ); + pxICMPHeader_IPv6->usChecksum = 0U; + } + } + else + #endif /* if ( ipconfigUSE_IPv6 != 0 ) */ + + if( pxIPPacket->xEthernetHeader.usFrameType == ipIPv4_FRAME_TYPE ) { - pxPacket->xICMPPacket.xICMPHeader.usChecksum = ( uint16_t ) 0u; + if( pxIPPacket->xIPHeader.ucProtocol == ( uint8_t ) ipPROTOCOL_ICMP ) + { + ICMPHeader_t * pxICMPHeader; + + pxICMPHeader = ipPOINTER_CAST( ICMPHeader_t *, &( pxDescriptor->pucEthernetBuffer[ ipSIZE_OF_ETH_HEADER + ipSIZE_OF_IPv4_HEADER ] ) ); + pxICMPHeader->usChecksum = ( uint16_t ) 0U; + } } } #endif /* ipconfigDRIVER_INCLUDED_TX_IP_CHECKSUM */ @@ -796,6 +919,10 @@ static BaseType_t xMayAcceptPacket( uint8_t * pucEthernetBuffer ) /* Check it later. */ return pdTRUE; + case ipIPv6_FRAME_TYPE: + /* Check it later. */ + return pdTRUE; + case ipIPv4_FRAME_TYPE: /* Check it here. */ break; @@ -977,6 +1104,7 @@ static BaseType_t prvNetworkInterfaceInput( void ) /* Find out which Network Buffer was originally passed to the descriptor. */ pxCurDescriptor = pxPacketBuffer_to_NetworkBuffer( pucBuffer ); configASSERT( pxCurDescriptor != NULL ); + configASSERT( pxCurDescriptor->pucEthernetBuffer != NULL ); } #else { @@ -995,6 +1123,9 @@ static BaseType_t prvNetworkInterfaceInput( void ) if( xAccepted != pdFALSE ) { pxCurDescriptor->xDataLength = xReceivedLength; + pxCurDescriptor->pxInterface = pxMyInterface; + pxCurDescriptor->pxEndPoint = FreeRTOS_MatchingEndpoint( pxMyInterface, pxCurDescriptor->pucEthernetBuffer ); + #if ( ipconfigUSE_LINKED_RX_MESSAGES != 0 ) { pxCurDescriptor->pxNextBuffer = NULL; @@ -1196,6 +1327,11 @@ static void prvEthernetUpdateConfig( BaseType_t xForce ) /* ETHERNET MAC Re-Configuration */ HAL_ETH_ConfigMAC( &xETH, ( ETH_MACInitTypeDef * ) NULL ); + /* Optionally, pass all mutlicast */ + #if 0 + xETH.Instance->MACFFR |= ETH_MACFFR_PAM; + #endif + /* Restart MAC interface */ HAL_ETH_Start( &xETH ); } @@ -1207,10 +1343,12 @@ static void prvEthernetUpdateConfig( BaseType_t xForce ) } /*-----------------------------------------------------------*/ -BaseType_t xGetPhyLinkStatus( void ) +static BaseType_t xGetPhyLinkStatus( NetworkInterface_t * pxInterface ) { BaseType_t xReturn; + ( void ) pxInterface; + if( xPhyObject.ulLinkStatusMask != 0 ) { xReturn = pdPASS; @@ -1243,6 +1381,31 @@ void vNetworkInterfaceAllocateRAMToBuffers( NetworkBufferDescriptor_t pxNetworkB ucRAMBuffer += ETH_MAX_PACKET_SIZE; } } + +/*-----------------------------------------------------------*/ + +NetworkInterface_t * pxFillInterfaceDescriptor( BaseType_t xEMACIndex, + NetworkInterface_t * pxInterface ) +{ + static char pcName[ 17 ]; + +/* This function pxFillInterfaceDescriptor() adds a network-interface. + * Make sure that the object pointed to by 'pxInterface' + * is declared static or global, and that it will remain to exist. */ + + snprintf( pcName, sizeof( pcName ), "eth%u", ( unsigned ) xEMACIndex ); + + memset( pxInterface, '\0', sizeof( *pxInterface ) ); + pxInterface->pcName = pcName; /* Just for logging, debugging. */ + pxInterface->pvArgument = ( void * ) xEMACIndex; /* Has only meaning for the driver functions. */ + pxInterface->pfInitialise = xNetworkInterfaceInitialise; + pxInterface->pfOutput = xNetworkInterfaceOutput; + pxInterface->pfGetPhyLinkStatus = xGetPhyLinkStatus; + + FreeRTOS_AddNetworkInterface( pxInterface ); + + return pxInterface; +} /*-----------------------------------------------------------*/ static void prvEMACHandlerTask( void * pvParameters ) diff --git a/source/portable/NetworkInterface/STM32Hxx/NetworkInterface.c b/source/portable/NetworkInterface/STM32Hxx/NetworkInterface.c index 926effa1d8..68634469eb 100644 --- a/source/portable/NetworkInterface/STM32Hxx/NetworkInterface.c +++ b/source/portable/NetworkInterface/STM32Hxx/NetworkInterface.c @@ -43,6 +43,7 @@ #include "FreeRTOS_Sockets.h" #include "FreeRTOS_IP_Private.h" #include "FreeRTOS_DNS.h" +#include "FreeRTOS_Routing.h" #include "NetworkBufferManagement.h" #include "NetworkInterface.h" @@ -107,6 +108,8 @@ static SemaphoreHandle_t xTransmissionMutex; static ETH_HandleTypeDef xEthHandle; static ETH_TxPacketConfig xTxConfig; +static NetworkInterface_t * pxMyInterface = NULL; + /* * About the section ".ethernet_data" : the DMA wants the descriptors and buffers allocated in the * RAM3 memory, which can be added to the .LD file as follows:: @@ -172,6 +175,25 @@ static void vClearOptionBit( volatile uint32_t * pulValue, static size_t uxGetOwnCount( ETH_HandleTypeDef * heth ); +/* FreeRTOS+TCP/multi : + * Each network device has 3 access functions: + * - Initialise the device + * - Output a network packet + * - Return the PHY Link-Status (LS) + * They can be defined as static because the function addresses + * addresses will be stored in struct NetworkInterface_t. */ + +static BaseType_t xNetworkInterfaceInitialise( NetworkInterface_t * pxInterface ); + +static BaseType_t xNetworkInterfaceOutput( NetworkInterface_t * pxInterface, + NetworkBufferDescriptor_t * const pxBuffer, + BaseType_t xReleaseAfterSend ); + +static BaseType_t xGetPhyLinkStatus( NetworkInterface_t * pxInterface ); + +NetworkInterface_t * pxFillInterfaceDescriptor( BaseType_t xEMACIndex, + NetworkInterface_t * pxInterface ); + /*-----------------------------------------------------------*/ static EthernetPhy_t xPhyObject; @@ -207,21 +229,26 @@ static uint8_t * pucGetRXBuffer( size_t uxSize ) } /*-----------------------------------------------------------*/ -BaseType_t xNetworkInterfaceInitialise( void ) +static BaseType_t xNetworkInterfaceInitialise( NetworkInterface_t * pxInterface ) { BaseType_t xResult = pdFAIL; + NetworkEndPoint_t * pxEndPoint; HAL_StatusTypeDef xHalEthInitStatus; size_t uxIndex = 0; if( xMacInitStatus == eMACInit ) { + pxMyInterface = pxInterface; + pxEndPoint = FreeRTOS_FirstEndPoint( pxInterface ); + configASSERT( pxEndPoint != NULL ); + /* * Initialize ETH Handler * It assumes that Ethernet GPIO and clock configuration * are already done in the ETH_MspInit() */ xEthHandle.Instance = ETH; - xEthHandle.Init.MACAddr = ( uint8_t * ) FreeRTOS_GetMACAddress(); + xEthHandle.Init.MACAddr = ( uint8_t * ) pxEndPoint->xMACAddress.ucBytes; xEthHandle.Init.MediaInterface = HAL_ETH_RMII_MODE; xEthHandle.Init.TxDesc = DMATxDscrTab; xEthHandle.Init.RxDesc = DMARxDscrTab; @@ -318,16 +345,21 @@ BaseType_t xNetworkInterfaceInitialise( void ) { /* For now pdFAIL will be returned. But prvEMACHandlerTask() is running * and it will keep on checking the PHY and set 'ulLinkStatusMask' when necessary. */ + xResult = pdFAIL; } } + else + { + xResult = pdFAIL; + } return xResult; } /*-----------------------------------------------------------*/ -BaseType_t xGetPhyLinkStatus( void ) +static BaseType_t xGetPhyLinkStatus( NetworkInterface_t * pxInterface ) { - BaseType_t xReturn; + BaseType_t xReturn = pdFAIL; if( xPhyObject.ulLinkStatusMask != 0U ) { @@ -342,8 +374,33 @@ BaseType_t xGetPhyLinkStatus( void ) } /*-----------------------------------------------------------*/ -BaseType_t xNetworkInterfaceOutput( NetworkBufferDescriptor_t * const pxDescriptor, - BaseType_t xReleaseAfterSend ) +NetworkInterface_t * pxFillInterfaceDescriptor( BaseType_t xEMACIndex, + NetworkInterface_t * pxInterface ) +{ + static char pcName[ 17 ]; + +/* This function pxFillInterfaceDescriptor() adds a network-interface. + * Make sure that the object pointed to by 'pxInterface' + * is declared static or global, and that it will remain to exist. */ + + snprintf( pcName, sizeof( pcName ), "eth%u", ( unsigned ) xEMACIndex ); + + memset( pxInterface, '\0', sizeof( *pxInterface ) ); + pxInterface->pcName = pcName; /* Just for logging, debugging. */ + pxInterface->pvArgument = ( void * ) xEMACIndex; /* Has only meaning for the driver functions. */ + pxInterface->pfInitialise = xNetworkInterfaceInitialise; + pxInterface->pfOutput = xNetworkInterfaceOutput; + pxInterface->pfGetPhyLinkStatus = xGetPhyLinkStatus; + + FreeRTOS_AddNetworkInterface( pxInterface ); + + return pxInterface; +} +/*-----------------------------------------------------------*/ + +static BaseType_t xNetworkInterfaceOutput( NetworkInterface_t * pxInterface, + NetworkBufferDescriptor_t * const pxDescriptor, + BaseType_t xReleaseAfterSend ) { BaseType_t xResult = pdFAIL; TickType_t xBlockTimeTicks = pdMS_TO_TICKS( 100U ); @@ -641,6 +698,9 @@ static BaseType_t prvNetworkInterfaceInput( void ) .pvData = ( void * ) pxReceivedBuffer }; + pxReceivedBuffer->pxInterface = pxMyInterface; + pxReceivedBuffer->pxEndPoint = FreeRTOS_MatchingEndpoint( pxMyInterface, pxReceivedBuffer->pucEthernetBuffer ); + /* Send the data to the TCP/IP stack. */ if( xSendEventStructToIPTask( &( xRxEvent ), 0 ) != pdFALSE ) { diff --git a/source/portable/NetworkInterface/WinPCap/NetworkInterface.c b/source/portable/NetworkInterface/WinPCap/NetworkInterface.c index 737a5ce835..e2e8d0824e 100644 --- a/source/portable/NetworkInterface/WinPCap/NetworkInterface.c +++ b/source/portable/NetworkInterface/WinPCap/NetworkInterface.c @@ -40,12 +40,14 @@ #include "FreeRTOS_IP.h" #include "FreeRTOS_IP_Private.h" #include "NetworkBufferManagement.h" +#include "FreeRTOS_Routing.h" /* Thread-safe circular buffers are being used to pass data to and from the PCAP * access functions. */ #include "Win32-Extensions.h" #include "FreeRTOS_Stream_Buffer.h" + /* Sizes of the thread safe circular buffers used to pass data to and from the * WinPCAP Windows threads. */ #define xSEND_BUFFER_SIZE 32768 @@ -72,6 +74,12 @@ DWORD WINAPI prvWinPcapRecvThread( void * pvParam ); DWORD WINAPI prvWinPcapSendThread( void * pvParam ); +/* + * A pointer to the network interface is needed later when receiving packets. + */ +static NetworkInterface_t * pxMyInterface; + + /* * Print out a numbered list of network interfaces that are available on the * host computer. @@ -110,6 +118,13 @@ static const char * prvRemoveSpaces( char * pcBuffer, int aBuflen, const char * pcMessage ); +/* + * This function will return pdTRUE if the packet is targeted at + * the MAC address of this device, in other words when is was bounced- + * back by the WinPCap interface. + */ +static BaseType_t xPacketBouncedBack( const uint8_t * pucBuffer ); + /*-----------------------------------------------------------*/ /* Required by the WinPCap library. */ @@ -139,11 +154,26 @@ static volatile uint32_t ulWinPCAPSendFailures = 0; /*-----------------------------------------------------------*/ -BaseType_t xNetworkInterfaceInitialise( void ) +static BaseType_t xNetworkInterfaceInitialise( NetworkInterface_t * pxInterface ); +static BaseType_t xNetworkInterfaceOutput( NetworkInterface_t * pxInterface, + NetworkBufferDescriptor_t * const pxNetworkBuffer, + BaseType_t bReleaseAfterSend ); +static BaseType_t xGetPhyLinkStatus( NetworkInterface_t * pxInterface ); + +NetworkInterface_t * pxFillInterfaceDescriptor( BaseType_t xEMACIndex, + NetworkInterface_t * pxInterface ); + +/*-----------------------------------------------------------*/ + +/*-----------------------------------------------------------*/ + +static BaseType_t xNetworkInterfaceInitialise( NetworkInterface_t * pxInterface ) { BaseType_t xReturn = pdFALSE; pcap_if_t * pxAllNetworkInterfaces; + ( void ) pxInterface; + /* Query the computer the simulation is being executed on to find the * network interfaces it has installed. */ pxAllNetworkInterfaces = prvPrintAvailableNetworkInterfaces(); @@ -191,11 +221,14 @@ static void prvCreateThreadSafeBuffers( void ) } /*-----------------------------------------------------------*/ -BaseType_t xNetworkInterfaceOutput( NetworkBufferDescriptor_t * const pxNetworkBuffer, - BaseType_t bReleaseAfterSend ) +static BaseType_t xNetworkInterfaceOutput( NetworkInterface_t * pxInterface, + NetworkBufferDescriptor_t * const pxNetworkBuffer, + BaseType_t bReleaseAfterSend ) { size_t xSpace; + ( void ) pxInterface; + iptraceNETWORK_INTERFACE_TRANSMIT(); configASSERT( xIsCallingFromIPTask() == pdTRUE ); @@ -232,6 +265,50 @@ BaseType_t xNetworkInterfaceOutput( NetworkBufferDescriptor_t * const pxNetworkB } /*-----------------------------------------------------------*/ +static BaseType_t xGetPhyLinkStatus( NetworkInterface_t * pxInterface ) +{ + BaseType_t xResult = pdFALSE; + + ( void ) pxInterface; + + if( pxOpenedInterfaceHandle != NULL ) + { + xResult = pdTRUE; + } + + return xResult; +} + +/*-----------------------------------------------------------*/ + + +NetworkInterface_t * pxFillInterfaceDescriptor( BaseType_t xEMACIndex, + NetworkInterface_t * pxInterface ) +{ + static char pcName[ 17 ]; + +/* This function pxFillInterfaceDescriptor() adds a network-interface. + * Make sure that the object pointed to by 'pxInterface' + * is declared static or global, and that it will remain to exist. */ + + pxMyInterface = pxInterface; + + snprintf( pcName, sizeof( pcName ), "eth%ld", xEMACIndex ); + + memset( pxInterface, '\0', sizeof( *pxInterface ) ); + pxInterface->pcName = pcName; /* Just for logging, debugging. */ + pxInterface->pvArgument = ( void * ) xEMACIndex; /* Has only meaning for the driver functions. */ + pxInterface->pfInitialise = xNetworkInterfaceInitialise; + pxInterface->pfOutput = xNetworkInterfaceOutput; + pxInterface->pfGetPhyLinkStatus = xGetPhyLinkStatus; + + FreeRTOS_AddNetworkInterface( pxInterface ); + + return pxInterface; +} + +/*-----------------------------------------------------------*/ + static pcap_if_t * prvPrintAvailableNetworkInterfaces( void ) { pcap_if_t * pxAllNetworkInterfaces = NULL, * xInterface; @@ -520,20 +597,36 @@ DWORD WINAPI prvWinPcapSendThread( void * pvParam ) static BaseType_t xPacketBouncedBack( const uint8_t * pucBuffer ) { + static BaseType_t xHasWarned = pdFALSE; EthernetHeader_t * pxEtherHeader; - BaseType_t xResult; + NetworkEndPoint_t * pxEndPoint; + BaseType_t xResult = pdFALSE; pxEtherHeader = ( EthernetHeader_t * ) pucBuffer; /* Sometimes, packets are bounced back by the driver and we need not process them. Check * whether this packet is one such packet. */ - if( memcmp( ipLOCAL_MAC_ADDRESS, pxEtherHeader->xSourceAddress.ucBytes, ipMAC_ADDRESS_LENGTH_BYTES ) == 0 ) - { - xResult = pdTRUE; - } - else + for( pxEndPoint = FreeRTOS_FirstEndPoint( NULL ); + pxEndPoint != NULL; + pxEndPoint = FreeRTOS_NextEndPoint( NULL, pxEndPoint ) ) { - xResult = pdFALSE; + if( memcmp( pxEndPoint->xMACAddress.ucBytes, pxEtherHeader->xSourceAddress.ucBytes, ipMAC_ADDRESS_LENGTH_BYTES ) == 0 ) + { + if( xHasWarned == pdFALSE ) + { + xHasWarned = pdTRUE; + FreeRTOS_printf( ( "Bounced back by WinPCAP interface: %02x:%02x:%02x:%02x:%02x:%02x\n", + pxEndPoint->xMACAddress.ucBytes[ 0 ], + pxEndPoint->xMACAddress.ucBytes[ 1 ], + pxEndPoint->xMACAddress.ucBytes[ 2 ], + pxEndPoint->xMACAddress.ucBytes[ 3 ], + pxEndPoint->xMACAddress.ucBytes[ 4 ], + pxEndPoint->xMACAddress.ucBytes[ 5 ] ) ); + } + + xResult = pdTRUE; + break; + } } return xResult; @@ -611,6 +704,9 @@ static void prvInterruptSimulatorTask( void * pvParameters ) { xRxEvent.pvData = ( void * ) pxNetworkBuffer; + pxNetworkBuffer->pxInterface = pxMyInterface; + pxNetworkBuffer->pxEndPoint = FreeRTOS_MatchingEndpoint( pxMyInterface, pxNetworkBuffer->pucEthernetBuffer ); + /* Data was received and stored. Send a message to * the IP task to let it know. */ if( xSendEventStructToIPTask( &xRxEvent, ( TickType_t ) 0 ) == pdFAIL ) diff --git a/test/Coverity/Portable.c b/test/Coverity/Portable.c index 08b5547346..0a526159ae 100644 --- a/test/Coverity/Portable.c +++ b/test/Coverity/Portable.c @@ -211,7 +211,7 @@ BaseType_t FreeRTOS_SendPingRequest( uint32_t ulIPAddress, /*-----------------------------------------------------------*/ eDHCPCallbackAnswer_t xApplicationDHCPHook( eDHCPCallbackPhase_t eDHCPPhase, - uint32_t ulIPAddress ) + uint32_t ulIPAddress ) { /* Provide a stub for this function. */ return eDHCPContinue; diff --git a/test/unit-test/ConfigFiles/FreeRTOSIPConfig.h b/test/unit-test/ConfigFiles/FreeRTOSIPConfig.h index 4ac57b3a97..debc4163d8 100644 --- a/test/unit-test/ConfigFiles/FreeRTOSIPConfig.h +++ b/test/unit-test/ConfigFiles/FreeRTOSIPConfig.h @@ -34,7 +34,7 @@ #define TEST 1 -#define ipconfigUSE_IPV4 ( 1 ) +#define ipconfigUSE_IPV4 ( 1 ) /* Set to 1 to print out debug messages. If ipconfigHAS_DEBUG_PRINTF is set to * 1 then FreeRTOS_debug_printf should be defined to the function used to print diff --git a/test/unit-test/FreeRTOS_Sockets/FreeRTOS_Sockets_privates_utest.c b/test/unit-test/FreeRTOS_Sockets/FreeRTOS_Sockets_privates_utest.c index 96b28bd57e..1ad1d9a363 100644 --- a/test/unit-test/FreeRTOS_Sockets/FreeRTOS_Sockets_privates_utest.c +++ b/test/unit-test/FreeRTOS_Sockets/FreeRTOS_Sockets_privates_utest.c @@ -2463,6 +2463,7 @@ void test_pxTCPSocketLookup_FoundAMatch( void ) uint32_t ulLocalIP = 0xAABBCCDD; UBaseType_t uxLocalPort = 0x1234; IP_Address_t ulRemoteIP; + ulRemoteIP.xIP_IPv4 = 0xBCBCDCDC; UBaseType_t uxRemotePort = 0x4567; ListItem_t xLocalListItem; @@ -2496,6 +2497,7 @@ void test_pxTCPSocketLookup_NoMatch( void ) uint32_t ulLocalIP = 0xAABBCCDD; UBaseType_t uxLocalPort = 0x1234; IP_Address_t ulRemoteIP; + ulRemoteIP.xIP_IPv4 = 0xBCBCDCDC; UBaseType_t uxRemotePort = 0x4567; ListItem_t xLocalListItem; @@ -2532,6 +2534,7 @@ void test_pxTCPSocketLookup_NoMatch2( void ) uint32_t ulLocalIP = 0xAABBCCDD; UBaseType_t uxLocalPort = 0x1234; IP_Address_t ulRemoteIP; + ulRemoteIP.xIP_IPv4 = 0xBCBCDCDC; UBaseType_t uxRemotePort = 0x4567; ListItem_t xLocalListItem; @@ -2568,6 +2571,7 @@ void test_pxTCPSocketLookup_FoundAPartialMatch( void ) uint32_t ulLocalIP = 0xAABBCCDD; UBaseType_t uxLocalPort = 0x1234; IP_Address_t ulRemoteIP; + ulRemoteIP.xIP_IPv4 = 0xBCBCDCDC; UBaseType_t uxRemotePort = 0x4567; ListItem_t xLocalListItem;