diff --git a/.github/lexicon.txt b/.github/lexicon.txt index 1304e6386..e3f4ff4ec 100755 --- a/.github/lexicon.txt +++ b/.github/lexicon.txt @@ -1345,6 +1345,7 @@ ucpeerwinscalefactor ucpreference ucprefix ucprefixlength +ucpriority ucprotocol ucprotocoladdresslength ucprotocolheadersize diff --git a/source/FreeRTOS_IP.c b/source/FreeRTOS_IP.c index de33cf1aa..7967bdc11 100644 --- a/source/FreeRTOS_IP.c +++ b/source/FreeRTOS_IP.c @@ -178,6 +178,11 @@ static eFrameProcessingResult_t prvProcessUDPPacket( NetworkBufferDescriptor_t * /** @brief The queue used to pass events into the IP-task for processing. */ QueueHandle_t xNetworkEventQueue = NULL; +#if ( ipconfigEVENT_QUEUES > 1 ) + QueueHandle_t xNetworkEventQueues[ ipconfigEVENT_QUEUES ] = { 0 }; + uint8_t xQueueMapping[ ipconfigPACKET_PRIORITIES ] = ipconfigPACKET_PRIORITY_MAPPING; +#endif + /** @brief The IP packet ID. */ uint16_t usPacketIdentifier = 0U; @@ -271,10 +276,31 @@ static void prvProcessIPEventsAndTimers( void ) /* Wait until there is something to do. If the following call exits * due to a time out rather than a message being received, set a * 'NoEvent' value. */ - if( xQueueReceive( xNetworkEventQueue, ( void * ) &xReceivedEvent, xNextIPSleep ) == pdFALSE ) - { - xReceivedEvent.eEventType = eNoEvent; - } + #if ( ipconfigEVENT_QUEUES > 1 ) + if( ulTaskNotifyTake( pdFALSE, xNextIPSleep ) == pdFALSE ) + { + xReceivedEvent.eEventType = eNoEvent; + } + else + { + BaseType_t xIndex; + BaseType_t xReturn; + + for( xIndex = ipconfigEVENT_QUEUES - 1; xIndex >= 0; xIndex-- ) + { + if( uxQueueMessagesWaiting( xNetworkEventQueues[ xIndex ] ) > 0 ) + { + xQueueReceive( xNetworkEventQueues[ xIndex ], &xReceivedEvent, 0 ); + break; + } + } + } + #else /* if ( ipconfigEVENT_QUEUES > 1 ) */ + if( xQueueReceive( xNetworkEventQueue, ( void * ) &xReceivedEvent, xNextIPSleep ) == pdFALSE ) + { + xReceivedEvent.eEventType = eNoEvent; + } + #endif /* if ( ipconfigEVENT_QUEUES > 1 ) */ #if ( ipconfigCHECK_IP_QUEUE_SPACE != 0 ) { @@ -942,6 +968,11 @@ void * FreeRTOS_GetUDPPayloadBuffer_Multi( size_t uxRequestedSizeBytes, BaseType_t FreeRTOS_IPInit_Multi( void ) { BaseType_t xReturn = pdFALSE; + BaseType_t xAllocSuccessful = pdFALSE; + + #if ( ipconfigEVENT_QUEUES > 1 ) + BaseType_t xIndex; + #endif /* There must be at least one interface and one end-point. */ configASSERT( FreeRTOS_FirstNetworkInterface() != NULL ); @@ -953,21 +984,54 @@ BaseType_t FreeRTOS_IPInit_Multi( void ) /* Attempt to create the queue used to communicate with the IP task. */ #if ( configSUPPORT_STATIC_ALLOCATION == 1 ) { - static StaticQueue_t xNetworkEventStaticQueue; - static uint8_t ucNetworkEventQueueStorageArea[ ipconfigEVENT_QUEUE_LENGTH * sizeof( IPStackEvent_t ) ]; - xNetworkEventQueue = xQueueCreateStatic( ipconfigEVENT_QUEUE_LENGTH, - sizeof( IPStackEvent_t ), - ucNetworkEventQueueStorageArea, - &xNetworkEventStaticQueue ); + #if ( ipconfigEVENT_QUEUES > 1 ) + static StaticQueue_t xPacketEventStaticQueue[ ipconfigEVENT_QUEUES ]; + static uint8_t ucPacketEventQueueStorageArea[ ipconfigEVENT_QUEUES ][ ipconfigEVENT_QUEUE_LENGTH * sizeof( IPStackEvent_t ) ]; + + xAllocSuccessful = pdTRUE; + + for( xIndex = 0; xIndex < ipconfigEVENT_QUEUES; xIndex++ ) + { + xNetworkEventQueues[ xIndex ] = xQueueCreateStatic( ipconfigEVENT_QUEUE_LENGTH, + sizeof( IPStackEvent_t ), + ucPacketEventQueueStorageArea[ xIndex ], + &xPacketEventStaticQueue[ xIndex ] ); + xAllocSuccessful &= ( xNetworkEventQueues[ xIndex ] != NULL ); + } + + xNetworkEventQueue = xNetworkEventQueues[ ipconfigEVENT_QUEUES - 1 ]; + #else /* if ( ipconfigEVENT_QUEUES > 1 ) */ + static StaticQueue_t xNetworkEventStaticQueue; + static uint8_t ucNetworkEventQueueStorageArea[ ipconfigEVENT_QUEUE_LENGTH * sizeof( IPStackEvent_t ) ]; + xNetworkEventQueue = xQueueCreateStatic( ipconfigEVENT_QUEUE_LENGTH, + sizeof( IPStackEvent_t ), + ucNetworkEventQueueStorageArea, + &xNetworkEventStaticQueue ); + xAllocSuccessful = ( xNetworkEventQueue != NULL ); + #endif /* if ( ipconfigEVENT_QUEUES > 1 ) */ } - #else + #else /* if ( configSUPPORT_STATIC_ALLOCATION == 1 ) */ { - xNetworkEventQueue = xQueueCreate( ipconfigEVENT_QUEUE_LENGTH, sizeof( IPStackEvent_t ) ); - configASSERT( xNetworkEventQueue != NULL ); + #if ( ipconfigEVENT_QUEUES > 1 ) + xAllocSuccessful = pdTRUE; + + for( xIndex = 0; xIndex < ipconfigEVENT_QUEUES; xIndex++ ) + { + xNetworkEventQueues[ xIndex ] = xQueueCreate( ipconfigEVENT_QUEUE_LENGTH, sizeof( IPStackEvent_t ) ); + configASSERT( xNetworkEventQueues[ xIndex ] != NULL ); + xAllocSuccessful &= ( xNetworkEventQueues[ xIndex ] != NULL ); + } + + xNetworkEventQueue = xNetworkEventQueues[ ipconfigEVENT_QUEUES - 1 ]; + #else /* if ( ipconfigEVENT_QUEUES > 1 ) */ + xNetworkEventQueue = xQueueCreate( ipconfigEVENT_QUEUE_LENGTH, sizeof( IPStackEvent_t ) ); + configASSERT( xNetworkEventQueue != NULL ); + xAllocSuccessful = ( xNetworkEventQueue != NULL ); + #endif /* if ( ipconfigEVENT_QUEUES > 1 ) */ } #endif /* configSUPPORT_STATIC_ALLOCATION */ - if( xNetworkEventQueue != NULL ) + if( xAllocSuccessful != pdFALSE ) { #if ( configQUEUE_REGISTRY_SIZE > 0 ) { @@ -1017,8 +1081,18 @@ BaseType_t FreeRTOS_IPInit_Multi( void ) FreeRTOS_debug_printf( ( "FreeRTOS_IPInit_Multi: xNetworkBuffersInitialise() failed\n" ) ); /* Clean up. */ - vQueueDelete( xNetworkEventQueue ); - xNetworkEventQueue = NULL; + #if ( ipconfigEVENT_QUEUES > 1 ) + for( xIndex = 0; xIndex < ipconfigEVENT_QUEUES; xIndex++ ) + { + vQueueDelete( xNetworkEventQueues[ xIndex ] ); + xNetworkEventQueues[ xIndex ] = NULL; + } + + xNetworkEventQueue = NULL; + #else + vQueueDelete( xNetworkEventQueue ); + xNetworkEventQueue = NULL; + #endif } } else @@ -1392,7 +1466,11 @@ BaseType_t xSendEventStructToIPTask( const IPStackEvent_t * pxEvent, * IP task is already awake processing other message. */ vIPSetTCPTimerExpiredState( pdTRUE ); - if( uxQueueMessagesWaiting( xNetworkEventQueue ) != 0U ) + #if ( ipconfigEVENT_QUEUES > 1 ) + if( ulTaskNotifyValueClear( xIPTaskHandle, 0 ) != 0U ) + #else + if( uxQueueMessagesWaiting( xNetworkEventQueue ) != 0U ) + #endif { /* Not actually going to send the message but this is not a * failure as the message didn't need to be sent. */ @@ -1411,7 +1489,24 @@ BaseType_t xSendEventStructToIPTask( const IPStackEvent_t * pxEvent, uxUseTimeout = ( TickType_t ) 0; } - xReturn = xQueueSendToBack( xNetworkEventQueue, pxEvent, uxUseTimeout ); + #if ( ipconfigEVENT_QUEUES > 1 ) + BaseType_t xQueue = ipconfigEVENT_QUEUES - 1; + + if( ( pxEvent->eEventType == eNetworkRxEvent ) || ( pxEvent->eEventType == eNetworkTxEvent ) || ( pxEvent->eEventType == eStackTxEvent ) ) + { + NetworkBufferDescriptor_t * pxBuffer = ( NetworkBufferDescriptor_t * ) pxEvent->pvData; + xQueue = xQueueMapping[ pxBuffer->ucPriority ]; + } + + xReturn = xQueueSendToBack( xNetworkEventQueues[ xQueue ], pxEvent, uxUseTimeout ); + + if( xReturn != pdFAIL ) + { + xTaskNotifyGive( xIPTaskHandle ); + } + #else /* if ( ipconfigEVENT_QUEUES > 1 ) */ + xReturn = xQueueSendToBack( xNetworkEventQueue, pxEvent, uxUseTimeout ); + #endif /* if ( ipconfigEVENT_QUEUES > 1 ) */ if( xReturn == pdFAIL ) { diff --git a/source/FreeRTOS_Sockets.c b/source/FreeRTOS_Sockets.c index d1bf73b09..aa3b3fe77 100644 --- a/source/FreeRTOS_Sockets.c +++ b/source/FreeRTOS_Sockets.c @@ -758,6 +758,9 @@ Socket_t FreeRTOS_socket( BaseType_t xDomain, pxSocket->xSendBlockTime = ipconfigSOCK_DEFAULT_SEND_BLOCK_TIME; pxSocket->ucSocketOptions = ( uint8_t ) FREERTOS_SO_UDPCKSUM_OUT; pxSocket->ucProtocol = ( uint8_t ) xProtocolCpy; /* protocol: UDP or TCP */ + #if ( ipconfigPACKET_PRIORITIES > 1 ) + pxSocket->ucPriority = ipconfigPACKET_PRIORITY_DEFAULT; + #endif xReturn = pxSocket; } @@ -1431,6 +1434,9 @@ static int32_t prvSendUDPPacket( const FreeRTOS_Socket_t * pxSocket, pxNetworkBuffer->xDataLength = uxTotalDataLength + uxPayloadOffset; pxNetworkBuffer->usPort = pxDestinationAddress->sin_port; pxNetworkBuffer->usBoundPort = ( uint16_t ) socketGET_SOCKET_PORT( pxSocket ); + #if ipconfigPACKET_PRIORITIES > 1 + pxNetworkBuffer->ucPriority = pxSocket->ucPriority; + #endif /* The socket options are passed to the IP layer in the * space that will eventually get used by the Ethernet header. */ @@ -2928,6 +2934,24 @@ BaseType_t FreeRTOS_setsockopt( Socket_t xSocket, xReturn = prvSetOptionStopRX( pxSocket, pvOptionValue ); break; #endif /* ipconfigUSE_TCP == 1 */ + #if ( ipconfigPACKET_PRIORITIES > 1 ) + case FREERTOS_SO_PRIORITY: + { + BaseType_t * pxValue = ( BaseType_t * ) pvOptionValue; + + if( ( pxValue == NULL ) || ( *pxValue >= ipconfigPACKET_PRIORITIES ) ) + { + xReturn = pdFREERTOS_ERRNO_EINVAL; + } + else + { + pxSocket->ucPriority = *pxValue; + xReturn = pdPASS; + } + + break; + } + #endif /* if ( ipconfigPACKET_PRIORITIES > 1 ) */ default: /* No other options are handled. */ diff --git a/source/FreeRTOS_TCP_Transmission_IPV4.c b/source/FreeRTOS_TCP_Transmission_IPV4.c index 3e5f69cd5..9c5968006 100644 --- a/source/FreeRTOS_TCP_Transmission_IPV4.c +++ b/source/FreeRTOS_TCP_Transmission_IPV4.c @@ -183,6 +183,9 @@ void prvTCPReturnPacket_IPV4( FreeRTOS_Socket_t * pxSocket, prvTCPReturn_SetSequenceNumber( pxSocket, pxNetworkBuffer, uxIPHeaderSize, ulLen ); pxIPHeader->ulDestinationIPAddress = FreeRTOS_htonl( pxSocket->u.xTCP.xRemoteIP.ulIP_IPv4 ); pxIPHeader->ulSourceIPAddress = pxNetworkBuffer->pxEndPoint->ipv4_settings.ulIPAddress; + #if ( ipconfigPACKET_PRIORITIES > 1 ) + pxNetworkBuffer->ucPriority = pxSocket->ucPriority; + #endif } else { diff --git a/source/FreeRTOS_TCP_Transmission_IPV6.c b/source/FreeRTOS_TCP_Transmission_IPV6.c index 6c7d08923..3db6fa988 100644 --- a/source/FreeRTOS_TCP_Transmission_IPV6.c +++ b/source/FreeRTOS_TCP_Transmission_IPV6.c @@ -193,6 +193,9 @@ void prvTCPReturnPacket_IPV6( FreeRTOS_Socket_t * pxSocket, prvTCPReturn_SetSequenceNumber( pxSocket, pxNetworkBuffer, uxIPHeaderSize, ulLen ); ( void ) memcpy( pxIPHeader->xDestinationAddress.ucBytes, pxSocket->u.xTCP.xRemoteIP.xIP_IPv6.ucBytes, ipSIZE_OF_IPv6_ADDRESS ); ( void ) memcpy( pxIPHeader->xSourceAddress.ucBytes, pxNetworkBuffer->pxEndPoint->ipv6_settings.xIPAddress.ucBytes, ipSIZE_OF_IPv6_ADDRESS ); + #if ( ipconfigPACKET_PRIORITIES > 1 ) + pxNetworkBuffer->ucPriority = pxSocket->ucPriority; + #endif } else { diff --git a/source/include/FreeRTOSIPConfigDefaults.h b/source/include/FreeRTOSIPConfigDefaults.h index 7cbdb9e31..b683f68c9 100644 --- a/source/include/FreeRTOSIPConfigDefaults.h +++ b/source/include/FreeRTOSIPConfigDefaults.h @@ -1161,4 +1161,32 @@ #define ipconfigRA_IP_TEST_TIME_OUT_MSEC ( 1500U ) #endif +#ifndef ipconfigEVENT_QUEUES + #define ipconfigEVENT_QUEUES 1 +#endif + +#ifndef ipconfigPACKET_PRIORITIES + #if ( ipconfigEVENT_QUEUES > 1 ) + #define ipconfigPACKET_PRIORITIES 8 + #else + #define ipconfigPACKET_PRIORITIES 1 + #endif +#endif + +#ifndef ipconfigPACKET_PRIORITY_MAPPING + #if ipconfigPACKET_PRIORITIES == 8 && ipconfigEVENT_QUEUES == 3 + #define ipconfigPACKET_PRIORITY_MAPPING { 0, 1, 1, 1, 2, 2, 2, 2, } + #elif ipconfigPACKET_PRIORITIES > 1 && ipconfigEVENT_QUEUES > 1 + #error "Please define your own ipconfigPACKET_PRIORITY_MAPPING." + #endif +#endif + +#ifndef ipconfigPACKET_PRIORITY_DEFAULT + #define ipconfigPACKET_PRIORITY_DEFAULT 1 +#endif + +#if ipconfigPACKET_PRIORITIES == 1 && ipconfigEVENT_QUEUES > 1 + #error "Network event queues need priority support." +#endif + #endif /* FREERTOS_DEFAULT_IP_CONFIG_H */ diff --git a/source/include/FreeRTOS_IP.h b/source/include/FreeRTOS_IP.h index 8500c5fc4..f7815b5cd 100644 --- a/source/include/FreeRTOS_IP.h +++ b/source/include/FreeRTOS_IP.h @@ -168,6 +168,9 @@ typedef struct xNETWORK_BUFFER #if ( ipconfigUSE_LINKED_RX_MESSAGES != 0 ) struct xNETWORK_BUFFER * pxNextBuffer; /**< Possible optimisation for expert users - requires network driver support. */ #endif + #if ( ipconfigPACKET_PRIORITIES > 1 ) + uint8_t ucPriority; /**< Priority of the buffer*/ + #endif #define ul_IPAddress xIPAddress.xIP_IPv4 #define x_IPv6Address xIPAddress.xIP_IPv6 diff --git a/source/include/FreeRTOS_IP_Private.h b/source/include/FreeRTOS_IP_Private.h index 59b47c22a..52fbabc8e 100644 --- a/source/include/FreeRTOS_IP_Private.h +++ b/source/include/FreeRTOS_IP_Private.h @@ -715,6 +715,10 @@ struct xSOCKET */ void * pvSocketID; + #if ( ipconfigPACKET_PRIORITIES > 1 ) + uint8_t ucPriority; /**< Priority of the socket */ + #endif + /* TCP/UDP specific fields: */ /* Before accessing any member of this structure, it should be confirmed */ /* that the protocol corresponds with the type of structure */ diff --git a/source/include/FreeRTOS_Sockets.h b/source/include/FreeRTOS_Sockets.h index fcfac4930..7c18ca689 100644 --- a/source/include/FreeRTOS_Sockets.h +++ b/source/include/FreeRTOS_Sockets.h @@ -148,8 +148,13 @@ #endif #if ( ipconfigUSE_TCP == 1 ) - #define FREERTOS_SO_SET_LOW_HIGH_WATER ( 18 ) + #define FREERTOS_SO_SET_LOW_HIGH_WATER ( 18 ) #endif + + #if ( ipconfigPACKET_PRIORITIES > 1 ) + #define FREERTOS_SO_PRIORITY ( 19 ) + #endif + #define FREERTOS_INADDR_ANY ( 0U ) /* The 0.0.0.0 IPv4 address. */ #if ( 0 ) /* Not Used */ diff --git a/source/portable/BufferManagement/BufferAllocation_1.c b/source/portable/BufferManagement/BufferAllocation_1.c index 546666e2b..7f2e9102f 100644 --- a/source/portable/BufferManagement/BufferAllocation_1.c +++ b/source/portable/BufferManagement/BufferAllocation_1.c @@ -292,6 +292,9 @@ NetworkBufferDescriptor_t * pxGetNetworkBufferWithDescriptor( size_t xRequestedS pxReturn->xDataLength = xRequestedSizeBytes; pxReturn->pxInterface = NULL; pxReturn->pxEndPoint = NULL; + #if ( ipconfigPACKET_PRIORITIES > 1 ) + pxReturn->ucPriority = ipconfigPACKET_PRIORITY_DEFAULT; + #endif #if ( ipconfigTCP_IP_SANITY != 0 ) { diff --git a/source/portable/BufferManagement/BufferAllocation_2.c b/source/portable/BufferManagement/BufferAllocation_2.c index 075cdf0a7..48906a2fa 100644 --- a/source/portable/BufferManagement/BufferAllocation_2.c +++ b/source/portable/BufferManagement/BufferAllocation_2.c @@ -306,6 +306,9 @@ NetworkBufferDescriptor_t * pxGetNetworkBufferWithDescriptor( size_t xRequestedS pxReturn->xDataLength = xRequestedSizeBytesCopy; pxReturn->pxInterface = NULL; pxReturn->pxEndPoint = NULL; + #if ( ipconfigPACKET_PRIORITIES > 1 ) + pxReturn->ucPriority = ipconfigPACKET_PRIORITY_DEFAULT; + #endif #if ( ipconfigUSE_LINKED_RX_MESSAGES != 0 ) {