diff options
Diffstat (limited to 'common/src')
24 files changed, 1973 insertions, 141 deletions
diff --git a/common/src/nx_ip_address_set.c b/common/src/nx_ip_address_set.c index 71a2081a..24a0e281 100644 --- a/common/src/nx_ip_address_set.c +++ b/common/src/nx_ip_address_set.c @@ -34,7 +34,7 @@ /* FUNCTION RELEASE */ /* */ /* _nx_ip_address_set PORTABLE C */ -/* 6.1 */ +/* 6.1.8 */ /* AUTHOR */ /* */ /* Yuxin Zhou, Microsoft Corporation */ @@ -70,75 +70,13 @@ /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */ /* 09-30-2020 Yuxin Zhou Modified comment(s), */ /* resulting in version 6.1 */ +/* 08-02-2021 Yuxin Zhou Modified comment(s), */ +/* merged duplicated functions,*/ +/* resulting in version 6.1.8 */ /* */ /**************************************************************************/ UINT _nx_ip_address_set(NX_IP *ip_ptr, ULONG ip_address, ULONG network_mask) { - -#ifndef NX_DISABLE_IPV4 -TX_INTERRUPT_SAVE_AREA - -VOID (*address_change_notify)(NX_IP *, VOID *); -VOID *additional_info; -ULONG previous_ip_address; -ULONG previous_network_mask; - - - /* If trace is enabled, insert this event into the trace buffer. */ - NX_TRACE_IN_LINE_INSERT(NX_TRACE_IP_ADDRESS_SET, ip_ptr, ip_address, network_mask, 0, NX_TRACE_IP_EVENTS, 0, 0); - - /* Get mutex protection. */ - tx_mutex_get(&(ip_ptr -> nx_ip_protection), TX_WAIT_FOREVER); - - - /* Disable interrupts. */ - TX_DISABLE - - /* Save previous IP address and network mask. This service assumes the - operations on the primary interface. */ - previous_ip_address = ip_ptr -> nx_ip_interface[0].nx_interface_ip_address; - previous_network_mask = ip_ptr -> nx_ip_interface[0].nx_interface_ip_network_mask; - - /* Pickup the current notification callback and additional information pointers. */ - address_change_notify = ip_ptr -> nx_ip_address_change_notify; - additional_info = ip_ptr -> nx_ip_address_change_notify_additional_info; - - /* Setup the IP address and the network mask. */ - ip_ptr -> nx_ip_interface[0].nx_interface_ip_address = ip_address; - ip_ptr -> nx_ip_interface[0].nx_interface_ip_network_mask = network_mask; - ip_ptr -> nx_ip_interface[0].nx_interface_ip_network = ip_address & network_mask; - - /* Ensure the RARP function is disabled. */ - ip_ptr -> nx_ip_rarp_periodic_update = NX_NULL; - ip_ptr -> nx_ip_rarp_queue_process = NX_NULL; - - /* Restore interrupts. */ - TX_RESTORE - - /* Release mutex protection. */ - tx_mutex_put(&(ip_ptr -> nx_ip_protection)); - - /* Determine if the application should be notified of the IP address and/or - network mask change. */ - if ((address_change_notify) && - ((ip_address != previous_ip_address) || (network_mask != previous_network_mask))) - { - - /* Yes, call the application's IP address change notify function. */ - (address_change_notify)(ip_ptr, additional_info); - } - - /* Initialize the ARP defend timeout. */ - ip_ptr -> nx_ip_interface[0].nx_interface_arp_defend_timeout = 0; - - /* Return completion status. */ - return(NX_SUCCESS); -#else /* NX_DISABLE_IPV4 */ - NX_PARAMETER_NOT_USED(ip_ptr); - NX_PARAMETER_NOT_USED(ip_address); - NX_PARAMETER_NOT_USED(network_mask); - - return(NX_NOT_SUPPORTED); -#endif /* !NX_DISABLE_IPV4 */ + return(_nx_ip_interface_address_set(ip_ptr, 0, ip_address, network_mask)); } diff --git a/common/src/nx_ip_header_add.c b/common/src/nx_ip_header_add.c index 46758a0e..a638aac8 100644 --- a/common/src/nx_ip_header_add.c +++ b/common/src/nx_ip_header_add.c @@ -39,7 +39,7 @@ /* FUNCTION RELEASE */ /* */ /* _nx_ip_header_add PORTABLE C */ -/* 6.1 */ +/* 6.1.8 */ /* AUTHOR */ /* */ /* Yuxin Zhou, Microsoft Corporation */ @@ -52,6 +52,7 @@ /* */ /* ip_ptr Pointer to IP control block */ /* packet_ptr Pointer to packet to send */ +/* source_ip Source IP address */ /* destination_ip Destination IP address */ /* type_of_service Type of service for packet */ /* time_to_live Time to live value for packet */ @@ -79,9 +80,12 @@ /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */ /* 09-30-2020 Yuxin Zhou Modified comment(s), */ /* resulting in version 6.1 */ +/* 08-02-2021 Yuxin Zhou Modified comment(s), and */ +/* supported TCP/IP offload, */ +/* resulting in version 6.1.8 */ /* */ /**************************************************************************/ -UINT _nx_ip_header_add(NX_IP *ip_ptr, NX_PACKET *packet_ptr, ULONG destination_ip, +UINT _nx_ip_header_add(NX_IP *ip_ptr, NX_PACKET *packet_ptr, ULONG source_ip, ULONG destination_ip, ULONG type_of_service, ULONG time_to_live, ULONG protocol, ULONG fragment) { ULONG router_alert = 0; @@ -154,7 +158,7 @@ ULONG val; ip_header_ptr -> nx_ip_header_word_2 = ((time_to_live << NX_IP_TIME_TO_LIVE_SHIFT) | protocol); /* Place the source IP address in the IP header. */ - ip_header_ptr -> nx_ip_header_source_ip = packet_ptr -> nx_packet_ip_interface -> nx_interface_ip_address; + ip_header_ptr -> nx_ip_header_source_ip = source_ip; /* Place the destination IP address in the IP header. */ ip_header_ptr -> nx_ip_header_destination_ip = destination_ip; diff --git a/common/src/nx_ip_interface_attach.c b/common/src/nx_ip_interface_attach.c index 23d20e76..5c62d951 100644 --- a/common/src/nx_ip_interface_attach.c +++ b/common/src/nx_ip_interface_attach.c @@ -38,7 +38,7 @@ /* FUNCTION RELEASE */ /* */ /* _nx_ip_interface_attach PORTABLE C */ -/* 6.1 */ +/* 6.1.8 */ /* AUTHOR */ /* */ /* Yuxin Zhou, Microsoft Corporation */ @@ -88,6 +88,9 @@ /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */ /* 09-30-2020 Yuxin Zhou Modified comment(s), */ /* resulting in version 6.1 */ +/* 08-02-2021 Yuxin Zhou Modified comment(s), and */ +/* supported TCP/IP offload, */ +/* resulting in version 6.1.8 */ /* */ /**************************************************************************/ UINT _nx_ip_interface_attach(NX_IP *ip_ptr, CHAR *interface_name, ULONG ip_address, ULONG network_mask, VOID (*ip_link_driver)(struct NX_IP_DRIVER_STRUCT *)) @@ -159,12 +162,25 @@ ULONG address[4]; if (ip_ptr -> nx_ip_initialize_done == NX_TRUE) { +#ifdef NX_ENABLE_INTERFACE_CAPABILITY + /* Clear capability flag. */ + ip_ptr -> nx_ip_interface[i].nx_interface_capability_flag = 0; +#endif /* NX_ENABLE_INTERFACE_CAPABILITY */ + /* First attach the interface to the device. */ driver_request.nx_ip_driver_ptr = ip_ptr; driver_request.nx_ip_driver_command = NX_LINK_INTERFACE_ATTACH; driver_request.nx_ip_driver_interface = &(ip_ptr -> nx_ip_interface[i]); (ip_ptr -> nx_ip_interface[i].nx_interface_link_driver_entry)(&driver_request); +#ifdef NX_ENABLE_TCPIP_OFFLOAD + if (ip_ptr -> nx_ip_interface[i].nx_interface_capability_flag & NX_INTERFACE_CAPABILITY_TCPIP_OFFLOAD) + { + + /* Set checksum capability for TCP/IP offload interface. */ + ip_ptr -> nx_ip_interface[i].nx_interface_capability_flag |= NX_INTERFACE_CAPABILITY_CHECKSUM_ALL; + } +#endif /* NX_ENABLE_TCPIP_OFFLOAD */ /* Call the link driver to initialize the hardware. Among other responsibilities, the driver is required to provide the diff --git a/common/src/nx_ip_packet_receive.c b/common/src/nx_ip_packet_receive.c index b9044e56..270ca7a5 100644 --- a/common/src/nx_ip_packet_receive.c +++ b/common/src/nx_ip_packet_receive.c @@ -35,7 +35,7 @@ /* FUNCTION RELEASE */ /* */ /* _nx_ip_packet_receive PORTABLE C */ -/* 6.1 */ +/* 6.1.8 */ /* AUTHOR */ /* */ /* Yuxin Zhou, Microsoft Corporation */ @@ -74,6 +74,9 @@ /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */ /* 09-30-2020 Yuxin Zhou Modified comment(s), */ /* resulting in version 6.1 */ +/* 08-02-2021 Yuxin Zhou Modified comment(s), and */ +/* added new ip filter, */ +/* resulting in version 6.1.8 */ /* */ /**************************************************************************/ VOID _nx_ip_packet_receive(NX_IP *ip_ptr, NX_PACKET *packet_ptr) @@ -124,6 +127,20 @@ UCHAR version_byte; return; } } + + /* Check if the IP packet filter extended is set. */ + if (ip_ptr -> nx_ip_packet_filter_extended) + { + + /* Yes, call the IP packet filter extended routine. */ + if (ip_ptr -> nx_ip_packet_filter_extended(ip_ptr, packet_ptr, NX_IP_PACKET_IN) != NX_SUCCESS) + { + + /* Drop the packet. */ + _nx_packet_release(packet_ptr); + return; + } + } #endif /* NX_ENABLE_IP_PACKET_FILTER */ #ifndef NX_DISABLE_IPV4 diff --git a/common/src/nx_ip_packet_send.c b/common/src/nx_ip_packet_send.c index 7847dbcd..7b258baf 100644 --- a/common/src/nx_ip_packet_send.c +++ b/common/src/nx_ip_packet_send.c @@ -39,7 +39,7 @@ /* FUNCTION RELEASE */ /* */ /* _nx_ip_packet_send PORTABLE C */ -/* 6.1 */ +/* 6.1.8 */ /* AUTHOR */ /* */ /* Yuxin Zhou, Microsoft Corporation */ @@ -83,6 +83,10 @@ /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */ /* 09-30-2020 Yuxin Zhou Modified comment(s), */ /* resulting in version 6.1 */ +/* 08-02-2021 Yuxin Zhou Modified comment(s), and */ +/* supported TCP/IP offload, */ +/* added new ip filter, */ +/* resulting in version 6.1.8 */ /* */ /**************************************************************************/ VOID _nx_ip_packet_send(NX_IP *ip_ptr, NX_PACKET *packet_ptr, @@ -133,6 +137,24 @@ ULONG val; return; } +#ifdef NX_ENABLE_TCPIP_OFFLOAD + if (packet_ptr -> nx_packet_address.nx_packet_interface_ptr -> nx_interface_capability_flag & + NX_INTERFACE_CAPABILITY_TCPIP_OFFLOAD) + { +#ifndef NX_DISABLE_IP_INFO + + /* Increment the IP invalid packet error. */ + ip_ptr -> nx_ip_invalid_transmit_packets++; +#endif + + /* Ignore sending all packets for TCP/IP offload. Release the packet. */ + _nx_packet_transmit_release(packet_ptr); + + /* Return... nothing more can be done! */ + return; + } +#endif /* NX_ENABLE_TCPIP_OFFLOAD */ + #ifdef NX_IPSEC_ENABLE /* Check if this packet is continued after HW crypto engine. */ if (packet_ptr -> nx_packet_ipsec_sa_ptr && @@ -191,7 +213,8 @@ ULONG val; { /* Add the IP Header to the packet. */ - _nx_ip_header_add(ip_ptr, packet_ptr, destination_ip, type_of_service, time_to_live, protocol, fragment); + _nx_ip_header_add(ip_ptr, packet_ptr, packet_ptr -> nx_packet_ip_interface -> nx_interface_ip_address, + destination_ip, type_of_service, time_to_live, protocol, fragment); #ifdef NX_ENABLE_IP_PACKET_FILTER /* Check if the IP packet filter is set. */ @@ -208,6 +231,20 @@ ULONG val; return; } } + + /* Check if the IP packet filter extended is set. */ + if (ip_ptr -> nx_ip_packet_filter_extended) + { + + /* Yes, call the IP packet filter extended routine. */ + if (ip_ptr -> nx_ip_packet_filter_extended(ip_ptr, packet_ptr, NX_IP_PACKET_OUT) != NX_SUCCESS) + { + + /* Drop the packet. */ + _nx_packet_transmit_release(packet_ptr); + return; + } + } #endif /* NX_ENABLE_IP_PACKET_FILTER */ } diff --git a/common/src/nx_ip_thread_entry.c b/common/src/nx_ip_thread_entry.c index 69409683..9fab67d3 100644 --- a/common/src/nx_ip_thread_entry.c +++ b/common/src/nx_ip_thread_entry.c @@ -43,7 +43,7 @@ /* FUNCTION RELEASE */ /* */ /* _nx_ip_thread_entry PORTABLE C */ -/* 6.1 */ +/* 6.1.8 */ /* AUTHOR */ /* */ /* Yuxin Zhou, Microsoft Corporation */ @@ -114,6 +114,9 @@ /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */ /* 09-30-2020 Yuxin Zhou Modified comment(s), */ /* resulting in version 6.1 */ +/* 08-02-2021 Yuxin Zhou Modified comment(s), and */ +/* supported TCP/IP offload, */ +/* resulting in version 6.1.8 */ /* */ /**************************************************************************/ VOID _nx_ip_thread_entry(ULONG ip_ptr_value) @@ -164,6 +167,15 @@ NXD_IPV6_ADDRESS *interface_ipv6_address; driver_request.nx_ip_driver_interface = &(ip_ptr -> nx_ip_interface[i]); (ip_ptr -> nx_ip_interface[i].nx_interface_link_driver_entry)(&driver_request); +#ifdef NX_ENABLE_TCPIP_OFFLOAD + if (ip_ptr -> nx_ip_interface[i].nx_interface_capability_flag & NX_INTERFACE_CAPABILITY_TCPIP_OFFLOAD) + { + + /* Set checksum capability for TCP/IP offload interface. */ + ip_ptr -> nx_ip_interface[i].nx_interface_capability_flag |= NX_INTERFACE_CAPABILITY_CHECKSUM_ALL; + } +#endif /* NX_ENABLE_TCPIP_OFFLOAD */ + /* Call the link driver to initialize the hardware. Among other responsibilities, the driver is required to provide the Maximum Transfer Unit (MTU) for the physical layer. The MTU diff --git a/common/src/nx_ipv6_header_add.c b/common/src/nx_ipv6_header_add.c index 3dcc2693..602ec001 100644 --- a/common/src/nx_ipv6_header_add.c +++ b/common/src/nx_ipv6_header_add.c @@ -43,7 +43,7 @@ /* FUNCTION RELEASE */ /* */ /* _nx_ipv6_header_add PORTABLE C */ -/* 6.1 */ +/* 6.1.8 */ /* AUTHOR */ /* */ /* Yuxin Zhou, Microsoft Corporation */ @@ -84,6 +84,9 @@ /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */ /* 09-30-2020 Yuxin Zhou Modified comment(s), */ /* resulting in version 6.1 */ +/* 08-02-2021 Yuxin Zhou Modified comment(s), and */ +/* supported TCP/IP offload, */ +/* resulting in version 6.1.8 */ /* */ /**************************************************************************/ UINT _nx_ipv6_header_add(NX_IP *ip_ptr, NX_PACKET **packet_pptr, @@ -251,22 +254,6 @@ USHORT short_val; NX_IPV6_ADDRESS_CHANGE_ENDIAN(ip_header_ptr -> nx_ip_header_destination_ip); NX_IPV6_ADDRESS_CHANGE_ENDIAN(ip_header_ptr -> nx_ip_header_source_ip); -#ifdef NX_ENABLE_IP_PACKET_FILTER - /* Check if the IP packet filter is set. */ - if (ip_ptr -> nx_ip_packet_filter) - { - - /* Yes, call the IP packet filter routine. */ - if (ip_ptr -> nx_ip_packet_filter((VOID *)(packet_ptr -> nx_packet_prepend_ptr), - NX_IP_PACKET_OUT) != NX_SUCCESS) - { - - /* Drop the packet. */ - _nx_packet_transmit_release(packet_ptr); - return(NX_INVALID_PACKET); - } - } -#endif /* NX_ENABLE_IP_PACKET_FILTER */ #ifdef NX_IPSEC_ENABLE } else diff --git a/common/src/nx_ipv6_packet_send.c b/common/src/nx_ipv6_packet_send.c index 8d03c1a6..2c17a67b 100644 --- a/common/src/nx_ipv6_packet_send.c +++ b/common/src/nx_ipv6_packet_send.c @@ -39,7 +39,7 @@ /* FUNCTION RELEASE */ /* */ /* _nx_ipv6_packet_send PORTABLE C */ -/* 6.1 */ +/* 6.1.8 */ /* AUTHOR */ /* */ /* Yuxin Zhou, Microsoft Corporation */ @@ -93,6 +93,9 @@ /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */ /* 09-30-2020 Yuxin Zhou Modified comment(s), */ /* resulting in version 6.1 */ +/* 08-02-2021 Yuxin Zhou Modified comment(s), and */ +/* supported TCP/IP offload, */ +/* resulting in version 6.1.8 */ /* */ /**************************************************************************/ VOID _nx_ipv6_packet_send(NX_IP *ip_ptr, NX_PACKET *packet_ptr, @@ -120,6 +123,23 @@ NX_IPV6_DESTINATION_ENTRY *dest_entry_ptr; /* Interface can not be NULL. */ NX_ASSERT(if_ptr != NX_NULL); +#ifdef NX_ENABLE_TCPIP_OFFLOAD + if (if_ptr -> nx_interface_capability_flag & NX_INTERFACE_CAPABILITY_TCPIP_OFFLOAD) + { +#ifndef NX_DISABLE_IP_INFO + + /* Increment the IP invalid packet error. */ + ip_ptr -> nx_ip_invalid_transmit_packets++; +#endif + + /* Ignore sending all packets for TCP/IP offload. Release the packet. */ + _nx_packet_transmit_release(packet_ptr); + + /* Return... nothing more can be done! */ + return; + } +#endif /* NX_ENABLE_TCPIP_OFFLOAD */ + /* Add IPv6 header. */ if (_nx_ipv6_header_add(ip_ptr, &packet_ptr, protocol, payload_size, hop_limit, src_address, dest_address, &fragment) != NX_SUCCESS) @@ -129,6 +149,37 @@ NX_IPV6_DESTINATION_ENTRY *dest_entry_ptr; return; } +#ifdef NX_ENABLE_IP_PACKET_FILTER + /* Check if the IP packet filter is set. */ + if (ip_ptr -> nx_ip_packet_filter) + { + + /* Yes, call the IP packet filter routine. */ + if (ip_ptr -> nx_ip_packet_filter((VOID *)(packet_ptr -> nx_packet_prepend_ptr), + NX_IP_PACKET_OUT) != NX_SUCCESS) + { + + /* Drop the packet. */ + _nx_packet_transmit_release(packet_ptr); + return; + } + } + + /* Check if the IP packet filter extended is set. */ + if (ip_ptr -> nx_ip_packet_filter_extended) + { + + /* Yes, call the IP packet filter extended routine. */ + if (ip_ptr -> nx_ip_packet_filter_extended(ip_ptr, packet_ptr, NX_IP_PACKET_OUT) != NX_SUCCESS) + { + + /* Drop the packet. */ + _nx_packet_transmit_release(packet_ptr); + return; + } + } +#endif /* NX_ENABLE_IP_PACKET_FILTER */ + next_hop_mtu = if_ptr -> nx_interface_ip_mtu_size; packet_ptr -> nx_packet_ip_header = packet_ptr -> nx_packet_prepend_ptr; diff --git a/common/src/nx_tcp_server_socket_driver_listen.c b/common/src/nx_tcp_server_socket_driver_listen.c new file mode 100644 index 00000000..f0c68cd7 --- /dev/null +++ b/common/src/nx_tcp_server_socket_driver_listen.c @@ -0,0 +1,119 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) Microsoft Corporation. All rights reserved. */ +/* */ +/* This software is licensed under the Microsoft Software License */ +/* Terms for Microsoft Azure RTOS. Full text of the license can be */ +/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ +/* and in the root directory of this software. */ +/* */ +/**************************************************************************/ + + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** NetX Component */ +/** */ +/** Transmission Control Protocol (TCP) */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + +#define NX_SOURCE_CODE + + +/* Include necessary system files. */ + +#include "nx_api.h" +#include "nx_tcp.h" + +#ifdef NX_ENABLE_TCPIP_OFFLOAD +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _nx_tcp_server_socket_driver_listen PORTABLE C */ +/* 6.1.8 */ +/* AUTHOR */ +/* */ +/* Yuxin Zhou, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function registers a listen request to all TCP/IP offload */ +/* interfaces. */ +/* */ +/* INPUT */ +/* */ +/* ip_ptr Pointer to IP instance */ +/* port TCP port number */ +/* socket_ptr Server socket pointer */ +/* */ +/* OUTPUT */ +/* */ +/* status Completion status */ +/* */ +/* CALLS */ +/* */ +/* None */ +/* */ +/* CALLED BY */ +/* */ +/* _nx_tcp_server_socket_listen Register a listen request */ +/* _nx_tcp_server_socket_relisten Register a listen request */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 08-02-2021 Yuxin Zhou Initial Version 6.1.8 */ +/* */ +/**************************************************************************/ +UINT _nx_tcp_server_socket_driver_listen(NX_IP *ip_ptr, UINT port, NX_TCP_SOCKET *socket_ptr) +{ +UINT status; +UINT i; +NX_INTERFACE *interface_ptr; + + /* Loop all interfaces to listen to ones support TCP/IP offload. */ + for (i = 0; i < NX_MAX_IP_INTERFACES; i++) + { + + /* Use a local variable for convenience. */ + interface_ptr = &(ip_ptr -> nx_ip_interface[i]); + + /* Check for valid interfaces. */ + if ((interface_ptr -> nx_interface_valid == NX_FALSE) || + (interface_ptr -> nx_interface_link_up == NX_FALSE)) + { + + /* Skip interface not valid. */ + continue; + } + + /* Check for TCP/IP offload feature. */ + if (((interface_ptr -> nx_interface_capability_flag & NX_INTERFACE_CAPABILITY_TCPIP_OFFLOAD) == 0) || + (interface_ptr -> nx_interface_tcpip_offload_handler == NX_NULL)) + { + + /* Skip interface not support TCP/IP offload. */ + continue; + } + + /* Let TCP/IP offload interface listen to port. */ + status = interface_ptr -> nx_interface_tcpip_offload_handler(ip_ptr, interface_ptr, socket_ptr, + NX_TCPIP_OFFLOAD_TCP_SERVER_SOCKET_LISTEN, + NX_NULL, NX_NULL, NX_NULL, + port, NX_NULL, NX_NO_WAIT); + if (status) + { + + /* Return an already bound error code. */ + return(NX_TCPIP_OFFLOAD_ERROR); + } + } + + return(NX_SUCCESS); +} +#endif /* NX_ENABLE_TCPIP_OFFLOAD */
\ No newline at end of file diff --git a/common/src/nx_tcp_server_socket_listen.c b/common/src/nx_tcp_server_socket_listen.c index 3a5162c2..52b6d6f3 100644 --- a/common/src/nx_tcp_server_socket_listen.c +++ b/common/src/nx_tcp_server_socket_listen.c @@ -34,7 +34,7 @@ /* FUNCTION RELEASE */ /* */ /* _nx_tcp_server_socket_listen PORTABLE C */ -/* 6.1 */ +/* 6.1.8 */ /* AUTHOR */ /* */ /* Yuxin Zhou, Microsoft Corporation */ @@ -74,6 +74,9 @@ /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */ /* 09-30-2020 Yuxin Zhou Modified comment(s), */ /* resulting in version 6.1 */ +/* 08-02-2021 Yuxin Zhou Modified comment(s), and */ +/* supported TCP/IP offload, */ +/* resulting in version 6.1.8 */ /* */ /**************************************************************************/ UINT _nx_tcp_server_socket_listen(NX_IP *ip_ptr, UINT port, NX_TCP_SOCKET *socket_ptr, UINT listen_queue_size, @@ -232,6 +235,22 @@ UINT bound; listen_ptr -> nx_tcp_listen_next = listen_ptr; } +#ifdef NX_ENABLE_TCPIP_OFFLOAD + /* Listen to TCP/IP offload interfaces. */ + if (_nx_tcp_server_socket_driver_listen(ip_ptr, port, socket_ptr)) + { + + /* At least one of the interface fails to listen to port. */ + _nx_tcp_server_socket_unlisten(ip_ptr, port); + + /* Listen request failure, release the protection. */ + tx_mutex_put(&(ip_ptr -> nx_ip_protection)); + + /* Return an already bound error code. */ + return(NX_TCPIP_OFFLOAD_ERROR); + } +#endif /* NX_ENABLE_TCPIP_OFFLOAD */ + /* Successful listen request, release the protection. */ tx_mutex_put(&(ip_ptr -> nx_ip_protection)); diff --git a/common/src/nx_tcp_server_socket_relisten.c b/common/src/nx_tcp_server_socket_relisten.c index 5bb5896c..b868eb6d 100644 --- a/common/src/nx_tcp_server_socket_relisten.c +++ b/common/src/nx_tcp_server_socket_relisten.c @@ -38,7 +38,7 @@ /* FUNCTION RELEASE */ /* */ /* _nx_tcp_server_socket_relisten PORTABLE C */ -/* 6.1 */ +/* 6.1.8 */ /* AUTHOR */ /* */ /* Yuxin Zhou, Microsoft Corporation */ @@ -80,6 +80,9 @@ /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */ /* 09-30-2020 Yuxin Zhou Modified comment(s), */ /* resulting in version 6.1 */ +/* 08-02-2021 Yuxin Zhou Modified comment(s), and */ +/* supported TCP/IP offload, */ +/* resulting in version 6.1.8 */ /* */ /**************************************************************************/ UINT _nx_tcp_server_socket_relisten(NX_IP *ip_ptr, UINT port, NX_TCP_SOCKET *socket_ptr) @@ -150,6 +153,19 @@ VOID (*listen_callback)(NX_TCP_SOCKET *socket_ptr, UINT /* Yes, a listen request was found for this port, with an empty socket designation. */ +#ifdef NX_ENABLE_TCPIP_OFFLOAD + /* Listen to TCP/IP offload interfaces. */ + if (_nx_tcp_server_socket_driver_listen(ip_ptr, port, socket_ptr)) + { + + /* Listen request failure, release the protection. */ + tx_mutex_put(&(ip_ptr -> nx_ip_protection)); + + /* Return an already bound error code. */ + return(NX_TCPIP_OFFLOAD_ERROR); + } +#endif /* NX_ENABLE_TCPIP_OFFLOAD */ + /* Determine if there are any connection requests queued up. */ if (!listen_ptr -> nx_tcp_listen_queue_current) { diff --git a/common/src/nx_tcp_server_socket_unlisten.c b/common/src/nx_tcp_server_socket_unlisten.c index c56191e6..7b5053d2 100644 --- a/common/src/nx_tcp_server_socket_unlisten.c +++ b/common/src/nx_tcp_server_socket_unlisten.c @@ -30,12 +30,96 @@ #include "nx_packet.h" +#ifdef NX_ENABLE_TCPIP_OFFLOAD +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _nx_tcp_server_socket_driver_unlisten PORTABLE C */ +/* 6.1.8 */ +/* AUTHOR */ +/* */ +/* Yuxin Zhou, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function handles the TCP server unlisten for TCP/IP offload */ +/* interface. */ +/* */ +/* INPUT */ +/* */ +/* ip_ptr Pointer to IP instance */ +/* socket_ptr Pointer to TCP socket */ +/* port TCP port number */ +/* */ +/* OUTPUT */ +/* */ +/* status Completion status */ +/* */ +/* CALLS */ +/* */ +/* tx_mutex_get Obtain protection */ +/* tx_mutex_put Release protection */ +/* */ +/* CALLED BY */ +/* */ +/* _nx_tcp_server_socket_unlisten */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 08-02-2021 Yuxin Zhou Initial Version 6.1.8 */ +/* */ +/**************************************************************************/ +static UINT _nx_tcp_server_socket_driver_unlisten(NX_IP *ip_ptr, NX_TCP_SOCKET *socket_ptr, UINT port) +{ +UINT i; +NX_INTERFACE *interface_ptr; + + /* Loop all interfaces to unlisten to ones support TCP/IP offload. */ + for (i = 0; i < NX_MAX_IP_INTERFACES; i++) + { + + /* Use a local variable for convenience. */ + interface_ptr = &(ip_ptr -> nx_ip_interface[i]); + + /* Check for valid interfaces. */ + if (interface_ptr -> nx_interface_valid == NX_FALSE) + { + + /* Skip interface not valid. */ + continue; + } + + /* Check for TCP/IP offload feature. */ + if (((interface_ptr -> nx_interface_capability_flag & + NX_INTERFACE_CAPABILITY_TCPIP_OFFLOAD) == 0) || + (interface_ptr -> nx_interface_tcpip_offload_handler == NX_NULL)) + { + + /* Skip interface not support TCP/IP offload. */ + continue; + } + + /* Let TCP/IP offload interface unlisten to port. */ + interface_ptr -> nx_interface_tcpip_offload_handler(ip_ptr, interface_ptr, socket_ptr, + NX_TCPIP_OFFLOAD_TCP_SERVER_SOCKET_UNLISTEN, + NX_NULL, NX_NULL, NX_NULL, + port, NX_NULL, NX_NO_WAIT); + } + + return(NX_SUCCESS); +} +#endif /* NX_ENABLE_TCPIP_OFFLOAD */ + + /**************************************************************************/ /* */ /* FUNCTION RELEASE */ /* */ /* _nx_tcp_server_socket_unlisten PORTABLE C */ -/* 6.1 */ +/* 6.1.8 */ /* AUTHOR */ /* */ /* Yuxin Zhou, Microsoft Corporation */ @@ -71,6 +155,9 @@ /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */ /* 09-30-2020 Yuxin Zhou Modified comment(s), */ /* resulting in version 6.1 */ +/* 08-02-2021 Yuxin Zhou Modified comment(s), and */ +/* supported TCP/IP offload, */ +/* resulting in version 6.1.8 */ /* */ /**************************************************************************/ UINT _nx_tcp_server_socket_unlisten(NX_IP *ip_ptr, UINT port) @@ -192,6 +279,10 @@ struct NX_TCP_LISTEN_STRUCT *listen_ptr; listen_ptr -> nx_tcp_listen_next = ip_ptr -> nx_ip_tcp_available_listen_requests; ip_ptr -> nx_ip_tcp_available_listen_requests = listen_ptr; +#ifdef NX_ENABLE_TCPIP_OFFLOAD + _nx_tcp_server_socket_driver_unlisten(ip_ptr, socket_ptr, port); +#endif /* NX_ENABLE_TCPIP_OFFLOAD */ + /* Release the protection. */ tx_mutex_put(&(ip_ptr -> nx_ip_protection)); diff --git a/common/src/nx_tcp_socket_disconnect.c b/common/src/nx_tcp_socket_disconnect.c index e04f4f09..bd49d3a3 100644 --- a/common/src/nx_tcp_socket_disconnect.c +++ b/common/src/nx_tcp_socket_disconnect.c @@ -36,7 +36,7 @@ /* FUNCTION RELEASE */ /* */ /* _nx_tcp_socket_disconnect PORTABLE C */ -/* 6.1 */ +/* 6.1.8 */ /* AUTHOR */ /* */ /* Yuxin Zhou, Microsoft Corporation */ @@ -80,6 +80,9 @@ /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */ /* 09-30-2020 Yuxin Zhou Modified comment(s), */ /* resulting in version 6.1 */ +/* 08-02-2021 Yuxin Zhou Modified comment(s), and */ +/* supported TCP/IP offload, */ +/* resulting in version 6.1.8 */ /* */ /**************************************************************************/ UINT _nx_tcp_socket_disconnect(NX_TCP_SOCKET *socket_ptr, ULONG wait_option) @@ -88,6 +91,9 @@ UINT _nx_tcp_socket_disconnect(NX_TCP_SOCKET *socket_ptr, ULONG wait_option) #ifndef NX_DISABLE_RESET_DISCONNECT NX_TCP_HEADER tcp_header; #endif +#ifdef NX_ENABLE_TCPIP_OFFLOAD +NX_INTERFACE *interface_ptr; +#endif /* NX_ENABLE_TCPIP_OFFLOAD */ UINT status; NX_IP *ip_ptr; @@ -129,6 +135,25 @@ NX_IP *ip_ptr; socket_ptr -> nx_tcp_socket_keepalive_retries = 0; #endif +#ifdef NX_ENABLE_TCPIP_OFFLOAD + interface_ptr = socket_ptr -> nx_tcp_socket_connect_interface; + if (interface_ptr && + (interface_ptr -> nx_interface_capability_flag & NX_INTERFACE_CAPABILITY_TCPIP_OFFLOAD) && + (interface_ptr -> nx_interface_tcpip_offload_handler)) + { + + /* Let TCP/IP offload interface close the connection. */ + interface_ptr -> nx_interface_tcpip_offload_handler(ip_ptr, interface_ptr, socket_ptr, + NX_TCPIP_OFFLOAD_TCP_SOCKET_DISCONNECT, + NX_NULL, NX_NULL, NX_NULL, 0, NX_NULL, + wait_option); + + /* Reset socket state. */ + socket_ptr -> nx_tcp_socket_state = NX_TCP_CLOSED; + } + else +#endif /* NX_ENABLE_TCPIP_OFFLOAD */ + /* Determine if the connection wasn't fully completed. */ if ((socket_ptr -> nx_tcp_socket_state == NX_TCP_SYN_SENT) || (socket_ptr -> nx_tcp_socket_state == NX_TCP_SYN_RECEIVED)) diff --git a/common/src/nx_tcp_socket_driver_establish.c b/common/src/nx_tcp_socket_driver_establish.c new file mode 100644 index 00000000..2be2a994 --- /dev/null +++ b/common/src/nx_tcp_socket_driver_establish.c @@ -0,0 +1,243 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) Microsoft Corporation. All rights reserved. */ +/* */ +/* This software is licensed under the Microsoft Software License */ +/* Terms for Microsoft Azure RTOS. Full text of the license can be */ +/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ +/* and in the root directory of this software. */ +/* */ +/**************************************************************************/ + + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** NetX Component */ +/** */ +/** Transmission Control Protocol (TCP) */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + +#define NX_SOURCE_CODE + + +/* Include necessary system files. */ + +#include "nx_api.h" +#include "nx_tcp.h" +#include "nx_packet.h" +#include "tx_thread.h" +#include "nx_ip.h" +#ifdef FEATURE_NX_IPV6 +#include "nx_ipv6.h" +#endif /* FEATURE_NX_IPV6 */ + +#ifdef NX_ENABLE_TCPIP_OFFLOAD +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _nx_tcp_socket_driver_establish PORTABLE C */ +/* 6.1.8 */ +/* AUTHOR */ +/* */ +/* Yuxin Zhou, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function is invoked when a TCP connection is established. */ +/* */ +/* INPUT */ +/* */ +/* socket_ptr Pointer to owning socket */ +/* interface_ptr Pointer to IP interface */ +/* remote_port Pointer to remote UDP port */ +/* */ +/* OUTPUT */ +/* */ +/* Status */ +/* */ +/* CALLS */ +/* */ +/* tx_mutex_get Obtain protection mutex */ +/* tx_mutex_put Release protection mutex */ +/* _nx_ip_packet_deferred_receive Defer IP packet receive */ +/* */ +/* CALLED BY */ +/* */ +/* Driver */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 08-02-2021 Yuxin Zhou Initial Version 6.1.8 */ +/* */ +/**************************************************************************/ +UINT _nx_tcp_socket_driver_establish(NX_TCP_SOCKET *socket_ptr, NX_INTERFACE *interface_ptr, UINT remote_port) +{ +NX_IP *ip_ptr; +NXD_ADDRESS ip_address; +UINT status; +UINT index; +UINT port; +struct NX_TCP_LISTEN_STRUCT *listen_ptr; + + /* Setup the IP pointer. */ + ip_ptr = socket_ptr -> nx_tcp_socket_ip_ptr; + + /* Obtain the IP internal mutex before processing the IP event. */ + tx_mutex_get(&(ip_ptr -> nx_ip_protection), TX_WAIT_FOREVER); + + /* Check socket state first. */ + if ((socket_ptr -> nx_tcp_socket_state != NX_TCP_SYN_SENT) && + (socket_ptr -> nx_tcp_socket_state != NX_TCP_LISTEN_STATE)&& + (socket_ptr -> nx_tcp_socket_state != NX_TCP_SYN_RECEIVED)) + { + + /* Just ignore socket not in connecting state. */ + /* Release the IP internal mutex. */ + tx_mutex_put(&(ip_ptr -> nx_ip_protection)); + return(NX_NOT_SUCCESSFUL); + } + + if (socket_ptr -> nx_tcp_socket_client_type == NX_FALSE) + { + if (socket_ptr -> nx_tcp_socket_bound_next) + { + + /* TCP socket is connecting on other interface. */ + /* Release the IP internal mutex. */ + tx_mutex_put(&(ip_ptr -> nx_ip_protection)); + return(NX_NOT_SUCCESSFUL); + } + + /* For TCP server socket, the connection is not established yet. */ + port = socket_ptr -> nx_tcp_socket_port; + status = interface_ptr -> nx_interface_tcpip_offload_handler(ip_ptr, interface_ptr, socket_ptr, + NX_TCPIP_OFFLOAD_TCP_SERVER_SOCKET_ACCEPT, + NX_NULL, NX_NULL, &ip_address, port, + &remote_port, NX_NO_WAIT); + + if (status) + { + + /* This should not happen as a connection is pendding. */ + /* Release the IP internal mutex. */ + tx_mutex_put(&(ip_ptr -> nx_ip_protection)); + return(NX_TCPIP_OFFLOAD_ERROR); + } + + /* Setup connection parameters. */ + socket_ptr -> nx_tcp_socket_connect_interface = interface_ptr; + + /* Save the server port and server IP address. */ + socket_ptr -> nx_tcp_socket_connect_ip.nxd_ip_version = ip_address.nxd_ip_version; +#ifndef NX_DISABLE_IPV4 + if (ip_address.nxd_ip_version == NX_IP_VERSION_V4) + { + socket_ptr -> nx_tcp_socket_connect_ip.nxd_ip_address.v4 = ip_address.nxd_ip_address.v4; + socket_ptr -> nx_tcp_socket_mss = + (ULONG)((interface_ptr -> nx_interface_ip_mtu_size - sizeof(NX_IPV4_HEADER)) - sizeof(NX_TCP_HEADER)); + } +#endif /* !NX_DISABLE_IPV4 */ + +#ifdef FEATURE_NX_IPV6 + if (ip_address.nxd_ip_version == NX_IP_VERSION_V6) + { + COPY_IPV6_ADDRESS(ip_address.nxd_ip_address.v6, + socket_ptr -> nx_tcp_socket_connect_ip.nxd_ip_address.v6); + socket_ptr -> nx_tcp_socket_mss = + (ULONG)((interface_ptr -> nx_interface_ip_mtu_size - sizeof(NX_IPV6_HEADER)) - sizeof(NX_TCP_HEADER)); + } +#endif /* FEATURE_NX_IPV6 */ + + socket_ptr -> nx_tcp_socket_connect_port = remote_port; + + /* Find listen callback function. */ + listen_ptr = ip_ptr -> nx_ip_tcp_active_listen_requests; + if (listen_ptr) + { + do + { + if (listen_ptr -> nx_tcp_listen_port == port) + { + if (listen_ptr -> nx_tcp_listen_callback) + { + + /* Clear the server socket pointer in the listen request. If the + application wishes to honor more server connections on this port, + the application must call relisten with a new server socket + pointer. */ + listen_ptr->nx_tcp_listen_socket_ptr = NX_NULL; + + /* Call the user's listen callback function. */ + (listen_ptr ->nx_tcp_listen_callback)(socket_ptr, listen_ptr -> nx_tcp_listen_port); + break; + } + } + + /* Move to the next listen request. */ + listen_ptr = listen_ptr -> nx_tcp_listen_next; + } while (listen_ptr != ip_ptr -> nx_ip_tcp_active_listen_requests); + } + + /* Calculate the hash index in the TCP port array of the associated IP instance. */ + index = (UINT)((port + (port >> 8)) & NX_TCP_PORT_TABLE_MASK); + + /* Determine if the list is NULL. */ + if (ip_ptr -> nx_ip_tcp_port_table[index]) + { + + /* There are already sockets on this list... just add this one + to the end. */ + socket_ptr -> nx_tcp_socket_bound_next = + ip_ptr -> nx_ip_tcp_port_table[index]; + socket_ptr -> nx_tcp_socket_bound_previous = + (ip_ptr -> nx_ip_tcp_port_table[index]) -> nx_tcp_socket_bound_previous; + ((ip_ptr -> nx_ip_tcp_port_table[index]) -> nx_tcp_socket_bound_previous) -> nx_tcp_socket_bound_next = + socket_ptr; + (ip_ptr -> nx_ip_tcp_port_table[index]) -> nx_tcp_socket_bound_previous = socket_ptr; + } + else + { + + /* Nothing is on the TCP port list. Add this TCP socket to an + empty list. */ + socket_ptr -> nx_tcp_socket_bound_next = socket_ptr; + socket_ptr -> nx_tcp_socket_bound_previous = socket_ptr; + ip_ptr -> nx_ip_tcp_port_table[index] = socket_ptr; + } + } + + /* Update socket state. */ + socket_ptr -> nx_tcp_socket_state = NX_TCP_ESTABLISHED; + +#ifndef NX_DISABLE_EXTENDED_NOTIFY_SUPPORT + + /* Is a connection completion callback registered with the TCP socket? */ + if (socket_ptr -> nx_tcp_establish_notify) + { + + /* Call the application's establish callback function. */ + (socket_ptr -> nx_tcp_establish_notify)(socket_ptr); + } +#endif + + /* Determine if we need to wake a thread suspended on the connection. */ + if (socket_ptr -> nx_tcp_socket_connect_suspended_thread) + { + + /* Resume the suspended thread. */ + _nx_tcp_socket_thread_resume(&(socket_ptr -> nx_tcp_socket_connect_suspended_thread), NX_SUCCESS); + } + + /* Release the IP internal mutex. */ + tx_mutex_put(&(ip_ptr -> nx_ip_protection)); + + return(NX_SUCCESS); +} +#endif /* NX_ENABLE_TCPIP_OFFLOAD */ + diff --git a/common/src/nx_tcp_socket_driver_packet_receive.c b/common/src/nx_tcp_socket_driver_packet_receive.c new file mode 100644 index 00000000..5c800215 --- /dev/null +++ b/common/src/nx_tcp_socket_driver_packet_receive.c @@ -0,0 +1,181 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) Microsoft Corporation. All rights reserved. */ +/* */ +/* This software is licensed under the Microsoft Software License */ +/* Terms for Microsoft Azure RTOS. Full text of the license can be */ +/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ +/* and in the root directory of this software. */ +/* */ +/**************************************************************************/ + + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** NetX Component */ +/** */ +/** Transmission Control Protocol (TCP) */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + +#define NX_SOURCE_CODE + + +/* Include necessary system files. */ + +#include "nx_api.h" +#include "nx_tcp.h" +#include "nx_packet.h" +#include "tx_thread.h" +#include "nx_ip.h" +#ifdef FEATURE_NX_IPV6 +#include "nx_ipv6.h" +#endif /* FEATURE_NX_IPV6 */ + +#ifdef NX_ENABLE_TCPIP_OFFLOAD +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _nx_tcp_socket_driver_packet_receive PORTABLE C */ +/* 6.1.8 */ +/* AUTHOR */ +/* */ +/* Yuxin Zhou, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function receives a TCP packet from the TCP/IP driver and add */ +/* fake TCP/IP header. Then pass the packet to IP deferred receive */ +/* routine. */ +/* */ +/* INPUT */ +/* */ +/* socket_ptr Pointer to owning socket */ +/* packet_ptr Pointer to packet to process */ +/* */ +/* OUTPUT */ +/* */ +/* None */ +/* */ +/* CALLS */ +/* */ +/* tx_mutex_get Obtain protection mutex */ +/* tx_mutex_put Release protection mutex */ +/* _nx_ip_packet_deferred_receive Defer IP packet receive */ +/* */ +/* CALLED BY */ +/* */ +/* Driver */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 08-02-2021 Yuxin Zhou Initial Version 6.1.8 */ +/* */ +/**************************************************************************/ +VOID _nx_tcp_socket_driver_packet_receive(NX_TCP_SOCKET *socket_ptr, NX_PACKET *packet_ptr) +{ +NX_IP *ip_ptr; +NX_TCP_HEADER *header_ptr; + + /* Setup the IP pointer. */ + ip_ptr = socket_ptr -> nx_tcp_socket_ip_ptr; + + /* Obtain the IP internal mutex before processing the IP event. */ + tx_mutex_get(&(ip_ptr -> nx_ip_protection), TX_WAIT_FOREVER); + + if (packet_ptr == NX_NULL) + { + + /* Connection closed. */ + if (socket_ptr -> nx_tcp_socket_state == NX_TCP_ESTABLISHED) + { + socket_ptr -> nx_tcp_socket_state = NX_TCP_CLOSE_WAIT; + + /* Loop to release all threads suspended while trying to receive on the socket. */ + while (socket_ptr -> nx_tcp_socket_receive_suspension_list) + { + + /* Release the head of the receive suspension list. */ + _nx_tcp_receive_cleanup(socket_ptr -> nx_tcp_socket_receive_suspension_list NX_CLEANUP_ARGUMENT); + } + + /* If given, call the application's disconnect callback function + for disconnect. */ + if (socket_ptr -> nx_tcp_disconnect_callback) + { + + /* Call the application's disconnect handling function. It is + responsible for calling the socket disconnect function. */ + (socket_ptr -> nx_tcp_disconnect_callback)(socket_ptr); + } + } + + /* Release the IP internal mutex. */ + tx_mutex_put(&(ip_ptr -> nx_ip_protection)); + return; + } + + /* Fake TCP and IP header. */ + /* Prepend the TCP header to the packet. First, make room for the TCP header. */ + packet_ptr -> nx_packet_prepend_ptr = packet_ptr -> nx_packet_prepend_ptr - sizeof(NX_TCP_HEADER); + + /* Add the length of the TCP header. */ + packet_ptr -> nx_packet_length = packet_ptr -> nx_packet_length + (ULONG)sizeof(NX_TCP_HEADER); + + /* Pickup the pointer to the head of the TCP packet. */ + /*lint -e{927} -e{826} suppress cast of pointer to pointer, since it is necessary */ + header_ptr = (NX_TCP_HEADER *)packet_ptr -> nx_packet_prepend_ptr; + + /* Build the output request in the TCP header. */ + header_ptr -> nx_tcp_header_word_0 = (((ULONG)(socket_ptr -> nx_tcp_socket_connect_port)) << NX_SHIFT_BY_16) | + (ULONG)socket_ptr -> nx_tcp_socket_port; + NX_CHANGE_ULONG_ENDIAN(header_ptr -> nx_tcp_header_word_0); + header_ptr -> nx_tcp_acknowledgment_number = 0; + header_ptr -> nx_tcp_sequence_number = 0; + header_ptr -> nx_tcp_header_word_3 = NX_TCP_HEADER_SIZE | NX_TCP_ACK_BIT | NX_TCP_PSH_BIT; + NX_CHANGE_ULONG_ENDIAN(header_ptr -> nx_tcp_header_word_3); + header_ptr -> nx_tcp_header_word_4 = 0; + +#ifndef NX_DISABLE_IPV4 + if (socket_ptr -> nx_tcp_socket_connect_ip.nxd_ip_version == NX_IP_VERSION_V4) + { + _nx_ip_header_add(ip_ptr, packet_ptr, socket_ptr -> nx_tcp_socket_connect_ip.nxd_ip_address.v4, + packet_ptr -> nx_packet_ip_interface -> nx_interface_ip_address, + socket_ptr -> nx_tcp_socket_type_of_service, + socket_ptr -> nx_tcp_socket_time_to_live, + NX_IP_TCP, + socket_ptr -> nx_tcp_socket_fragment_enable); + } +#endif /* !NX_DISABLE_IPV4 */ + +#ifdef FEATURE_NX_IPV6 + if (socket_ptr -> nx_tcp_socket_connect_ip.nxd_ip_version == NX_IP_VERSION_V6) + { + if (_nx_ipv6_header_add(ip_ptr, &packet_ptr, + NX_PROTOCOL_TCP, + packet_ptr -> nx_packet_length, + ip_ptr -> nx_ipv6_hop_limit, + socket_ptr -> nx_tcp_socket_connect_ip.nxd_ip_address.v6, + socket_ptr -> nx_tcp_socket_ipv6_addr -> nxd_ipv6_address, + NX_NULL)) + { + + /* Release the IP internal mutex. */ + tx_mutex_put(&(ip_ptr -> nx_ip_protection)); + return; + } + } +#endif /* FEATURE_NX_IPV6 */ + + /* Release the IP internal mutex. */ + tx_mutex_put(&(ip_ptr -> nx_ip_protection)); + + _nx_ip_packet_deferred_receive(ip_ptr, packet_ptr); +} +#endif /* NX_ENABLE_TCPIP_OFFLOAD */ + diff --git a/common/src/nx_tcp_socket_packet_process.c b/common/src/nx_tcp_socket_packet_process.c index 085d8b47..878ff945 100644 --- a/common/src/nx_tcp_socket_packet_process.c +++ b/common/src/nx_tcp_socket_packet_process.c @@ -35,7 +35,7 @@ /* FUNCTION RELEASE */ /* */ /* _nx_tcp_socket_packet_process PORTABLE C */ -/* 6.1 */ +/* 6.1.8 */ /* AUTHOR */ /* */ /* Yuxin Zhou, Microsoft Corporation */ @@ -83,6 +83,9 @@ /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */ /* 09-30-2020 Yuxin Zhou Modified comment(s), */ /* resulting in version 6.1 */ +/* 08-02-2021 Yuxin Zhou Modified comment(s), and */ +/* supported TCP/IP offload, */ +/* resulting in version 6.1.8 */ /* */ /**************************************************************************/ VOID _nx_tcp_socket_packet_process(NX_TCP_SOCKET *socket_ptr, NX_PACKET *packet_ptr) @@ -98,6 +101,12 @@ ULONG rx_sequence; ULONG rx_window; UINT outside_of_window; ULONG mss = 0; +#ifdef NX_ENABLE_TCPIP_OFFLOAD +ULONG tcpip_offload; + + tcpip_offload = socket_ptr -> nx_tcp_socket_connect_interface -> nx_interface_capability_flag & + NX_INTERFACE_CAPABILITY_TCPIP_OFFLOAD; +#endif /* NX_ENABLE_TCPIP_OFFLOAD */ /* Add debug information. */ NX_PACKET_DEBUG(__FILE__, __LINE__, packet_ptr); @@ -112,7 +121,11 @@ ULONG mss = 0; header_length = (tcp_header_copy.nx_tcp_header_word_3 >> NX_TCP_HEADER_SHIFT) * (ULONG)sizeof(ULONG); /* Process the segment if socket state is equal or greater than NX_TCP_SYN_RECEIVED. According to RFC 793, Section 3.9, Page 69. */ - if (socket_ptr -> nx_tcp_socket_state >= NX_TCP_SYN_RECEIVED) + if ((socket_ptr -> nx_tcp_socket_state >= NX_TCP_SYN_RECEIVED) +#ifdef NX_ENABLE_TCPIP_OFFLOAD + && (!tcpip_offload) +#endif /* NX_ENABLE_TCPIP_OFFLOAD */ + ) { /* Step1: Check sequence number. According to RFC 793, Section 3.9, Page 69. */ @@ -366,12 +379,18 @@ ULONG mss = 0; /* Check for data in the current packet. */ packet_queued = _nx_tcp_socket_state_data_check(socket_ptr, packet_ptr); - /* Call the ESTABLISHED state handling function to process any state - changes caused by this new packet. */ - _nx_tcp_socket_state_established(socket_ptr); +#ifdef NX_ENABLE_TCPIP_OFFLOAD + if (!tcpip_offload) +#endif /* NX_ENABLE_TCPIP_OFFLOAD */ + { - /* Determine if any transmit suspension can be lifted. */ - _nx_tcp_socket_state_transmit_check(socket_ptr); + /* Call the ESTABLISHED state handling function to process any state + changes caused by this new packet. */ + _nx_tcp_socket_state_established(socket_ptr); + + /* Determine if any transmit suspension can be lifted. */ + _nx_tcp_socket_state_transmit_check(socket_ptr); + } /* State processing is complete. */ break; diff --git a/common/src/nx_tcp_socket_send_internal.c b/common/src/nx_tcp_socket_send_internal.c index 4d176c6f..2d466857 100644 --- a/common/src/nx_tcp_socket_send_internal.c +++ b/common/src/nx_tcp_socket_send_internal.c @@ -38,12 +38,176 @@ #endif /* NX_IPSEC_ENABLE */ +#ifdef NX_ENABLE_TCPIP_OFFLOAD +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _nx_tcp_socket_driver_send PORTABLE C */ +/* 6.1.8 */ +/* AUTHOR */ +/* */ +/* Yuxin Zhou, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function sends a TCP packet through TCP/IP offload interface. */ +/* */ +/* INPUT */ +/* */ +/* socket_ptr Pointer to socket */ +/* packet_ptr Pointer to packet to send */ +/* wait_option Suspension option */ +/* */ +/* OUTPUT */ +/* */ +/* status Completion status */ +/* */ +/* CALLS */ +/* */ +/* _nx_ip_packet_send Packet send function */ +/* _nx_ipv6_packet_send Packet send function */ +/* */ +/* CALLED BY */ +/* */ +/* _nx_tcp_socket_send_internal */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 08-02-2021 Yuxin Zhou Initial Version 6.1.8 */ +/* */ +/**************************************************************************/ +static UINT _nx_tcp_socket_driver_send(NX_TCP_SOCKET *socket_ptr, NX_PACKET *packet_ptr, ULONG wait_option) +{ +UINT status; +NX_IP *ip_ptr; +NX_INTERFACE *interface_ptr = socket_ptr -> nx_tcp_socket_connect_interface; +#ifdef NX_ENABLE_IP_PACKET_FILTER +UCHAR *original_ptr = packet_ptr -> nx_packet_prepend_ptr; +ULONG original_length = packet_ptr -> nx_packet_length; +NX_TCP_HEADER *header_ptr; +#endif /* NX_ENABLE_IP_PACKET_FILTER */ + + /* Setup the pointer to the associated IP instance. */ + ip_ptr = socket_ptr -> nx_tcp_socket_ip_ptr; + +#ifdef NX_ENABLE_IP_PACKET_FILTER + /* Check if the IP packet filter is set. */ + if (ip_ptr -> nx_ip_packet_filter || ip_ptr -> nx_ip_packet_filter_extended) + { + + /* Yes, add the TCP and IP Header to trigger filtering. */ + /* Prepend the TCP header to the packet. First, make room for the TCP header. */ + packet_ptr -> nx_packet_prepend_ptr = packet_ptr -> nx_packet_prepend_ptr - sizeof(NX_TCP_HEADER); + + /* Add the length of the TCP header. */ + packet_ptr -> nx_packet_length = packet_ptr -> nx_packet_length + (ULONG)sizeof(NX_TCP_HEADER); + + /* Pickup the pointer to the head of the TCP packet. */ + /*lint -e{927} -e{826} suppress cast of pointer to pointer, since it is necessary */ + header_ptr = (NX_TCP_HEADER *)packet_ptr -> nx_packet_prepend_ptr; + + /* Build the output request in the TCP header. */ + header_ptr -> nx_tcp_header_word_0 = (((ULONG)(socket_ptr -> nx_tcp_socket_port)) << NX_SHIFT_BY_16) | + (ULONG)socket_ptr -> nx_tcp_socket_connect_port; + header_ptr -> nx_tcp_acknowledgment_number = 0; + header_ptr -> nx_tcp_sequence_number = 0; + header_ptr -> nx_tcp_header_word_3 = NX_TCP_HEADER_SIZE | NX_TCP_ACK_BIT | NX_TCP_PSH_BIT; + header_ptr -> nx_tcp_header_word_4 = 0; + + /* Endian swapping logic. If NX_LITTLE_ENDIAN is specified, these macros will + swap the endian of the TCP header. */ + NX_CHANGE_ULONG_ENDIAN(header_ptr -> nx_tcp_header_word_0); + NX_CHANGE_ULONG_ENDIAN(header_ptr -> nx_tcp_header_word_3); + +#ifndef NX_DISABLE_IPV4 + if (socket_ptr -> nx_tcp_socket_connect_ip.nxd_ip_version == NX_IP_VERSION_V4) + { + _nx_ip_header_add(ip_ptr, packet_ptr, + socket_ptr -> nx_tcp_socket_connect_interface -> nx_interface_ip_address, + socket_ptr -> nx_tcp_socket_connect_ip.nxd_ip_address.v4, + socket_ptr -> nx_tcp_socket_type_of_service, + socket_ptr -> nx_tcp_socket_time_to_live, + NX_IP_TCP, + socket_ptr -> nx_tcp_socket_fragment_enable); + } +#endif /* !NX_DISABLE_IPV4 */ + +#ifdef FEATURE_NX_IPV6 + if (socket_ptr -> nx_tcp_socket_connect_ip.nxd_ip_version == NX_IP_VERSION_V6) + { + if (_nx_ipv6_header_add(ip_ptr, &packet_ptr, + NX_PROTOCOL_TCP, + packet_ptr -> nx_packet_length, + ip_ptr -> nx_ipv6_hop_limit, + socket_ptr -> nx_tcp_socket_ipv6_addr -> nxd_ipv6_address, + socket_ptr -> nx_tcp_socket_connect_ip.nxd_ip_address.v6, + NX_NULL)) + { + + /* Invalid interface address. Just return success. */ + return(NX_SUCCESS); + } + } +#endif /* FEATURE_NX_IPV6 */ + + if (ip_ptr -> nx_ip_packet_filter) + { + if (ip_ptr -> nx_ip_packet_filter((VOID *)(packet_ptr -> nx_packet_prepend_ptr), + NX_IP_PACKET_OUT) != NX_SUCCESS) + { + + /* Packet consumed by IP filter. Just return success. */ + _nx_packet_transmit_release(packet_ptr); + return(NX_SUCCESS); + } + } + + /* Check if the IP packet filter extended is set. */ + if (ip_ptr -> nx_ip_packet_filter_extended) + { + + /* Yes, call the IP packet filter extended routine. */ + if (ip_ptr -> nx_ip_packet_filter_extended(ip_ptr, packet_ptr, NX_IP_PACKET_OUT) != NX_SUCCESS) + { + + /* Packet consumed by IP filter. Just return success. */ + _nx_packet_transmit_release(packet_ptr); + return(NX_SUCCESS); + } + } + + /* Reset UDP and IP header. */ + packet_ptr -> nx_packet_prepend_ptr = original_ptr; + packet_ptr -> nx_packet_length = original_length; + } +#endif /* NX_ENABLE_IP_PACKET_FILTER */ + + /* Let TCP/IP offload interface send the packet. */ + status = interface_ptr -> nx_interface_tcpip_offload_handler(ip_ptr, interface_ptr, socket_ptr, + NX_TCPIP_OFFLOAD_TCP_SOCKET_SEND, + packet_ptr, NX_NULL, NX_NULL, 0, NX_NULL, + wait_option); + + if (status) + { + return(NX_TCPIP_OFFLOAD_ERROR); + } + else + { + return(NX_SUCCESS); + } +} +#endif /* NX_ENABLE_TCPIP_OFFLOAD */ + /**************************************************************************/ /* */ /* FUNCTION RELEASE */ /* */ /* _nx_tcp_socket_send_internal PORTABLE C */ -/* 6.1 */ +/* 6.1.8 */ /* AUTHOR */ /* */ /* Yuxin Zhou, Microsoft Corporation */ @@ -70,6 +234,7 @@ /* _nx_tcp_socket_thread_suspend Suspend calling thread */ /* tx_mutex_get Get protection mutex */ /* tx_mutex_put Put protection mutex */ +/* _nx_tcp_socket_driver_send TCP/IP offload send function */ /* */ /* CALLED BY */ /* */ @@ -88,6 +253,9 @@ /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */ /* 09-30-2020 Yuxin Zhou Modified comment(s), */ /* resulting in version 6.1 */ +/* 08-02-2021 Yuxin Zhou Modified comment(s), and */ +/* supported TCP/IP offload, */ +/* resulting in version 6.1.8 */ /* */ /**************************************************************************/ UINT _nx_tcp_socket_send_internal(NX_TCP_SOCKET *socket_ptr, NX_PACKET *packet_ptr, ULONG wait_option) @@ -116,6 +284,10 @@ UCHAR preempted = NX_FALSE; UCHAR adjust_packet; UINT old_threshold = 0; ULONG window_size; +#ifdef NX_ENABLE_TCPIP_OFFLOAD +UINT status; +NX_INTERFACE *interface_ptr; +#endif /* NX_ENABLE_TCPIP_OFFLOAD */ #if defined(NX_DISABLE_TCP_TX_CHECKSUM) || defined(NX_ENABLE_INTERFACE_CAPABILITY) || defined(NX_IPSEC_ENABLE) UINT compute_checksum = 1; #endif /* defined(NX_DISABLE_TCP_TX_CHECKSUM) || defined(NX_ENABLE_INTERFACE_CAPABILITY) || defined(NX_IPSEC_ENABLE) */ @@ -183,7 +355,7 @@ UINT compute_checksum = 1; /* Set the source address. */ source_ip = &socket_ptr -> nx_tcp_socket_connect_interface -> nx_interface_ip_address; - /* Set the destinatino address. */ + /* Set the destination address. */ dest_ip = &socket_ptr -> nx_tcp_socket_connect_ip.nxd_ip_address.v4; /* The outgoing interface should have been stored in the socket structure. */ @@ -210,7 +382,7 @@ UINT compute_checksum = 1; /* Set the source address. */ source_ip = socket_ptr -> nx_tcp_socket_ipv6_addr -> nxd_ipv6_address; - /* Set the destinatino address. */ + /* Set the destination address. */ dest_ip = socket_ptr -> nx_tcp_socket_connect_ip.nxd_ip_address.v6; /* The outgoing address should have been stored in the socket structure. */ @@ -221,6 +393,24 @@ UINT compute_checksum = 1; } #endif /* FEATURE_NX_IPV6 */ +#ifdef NX_ENABLE_TCPIP_OFFLOAD + interface_ptr = socket_ptr -> nx_tcp_socket_connect_interface; + if ((interface_ptr -> nx_interface_capability_flag & NX_INTERFACE_CAPABILITY_TCPIP_OFFLOAD) && + (interface_ptr -> nx_interface_tcpip_offload_handler)) + { + + /* This interface supports TCP/IP offload. */ + tx_mutex_get(&(ip_ptr -> nx_ip_protection), TX_WAIT_FOREVER); + + status = _nx_tcp_socket_driver_send(socket_ptr, packet_ptr, wait_option); + + /* Release the IP protection. */ + tx_mutex_put(&(ip_ptr -> nx_ip_protection)); + + return(status); + } +#endif /* NX_ENABLE_TCPIP_OFFLOAD */ + #ifdef NX_IPSEC_ENABLE /* Increase the data offset when IPsec is enabled. */ data_offset += socket_ptr -> nx_tcp_socket_egress_sa_data_offset; @@ -907,5 +1097,4 @@ UINT compute_checksum = 1; } } } -} - +}
\ No newline at end of file diff --git a/common/src/nx_tcp_socket_state_data_check.c b/common/src/nx_tcp_socket_state_data_check.c index 1f6475d1..d23b6c21 100644 --- a/common/src/nx_tcp_socket_state_data_check.c +++ b/common/src/nx_tcp_socket_state_data_check.c @@ -276,7 +276,7 @@ ULONG work_length; /* FUNCTION RELEASE */ /* */ /* _nx_tcp_socket_state_data_check PORTABLE C */ -/* 6.1 */ +/* 6.1.8 */ /* AUTHOR */ /* */ /* Yuxin Zhou, Microsoft Corporation */ @@ -317,6 +317,9 @@ ULONG work_length; /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */ /* 09-30-2020 Yuxin Zhou Modified comment(s), */ /* resulting in version 6.1 */ +/* 08-02-2021 Yuxin Zhou Modified comment(s), and */ +/* supported TCP/IP offload, */ +/* resulting in version 6.1.8 */ /* */ /**************************************************************************/ UINT _nx_tcp_socket_state_data_check(NX_TCP_SOCKET *socket_ptr, NX_PACKET *packet_ptr) @@ -339,6 +342,9 @@ ULONG trim_data_length; TX_THREAD *thread_ptr; ULONG acked_packets = 0; UINT need_ack = NX_FALSE; +#ifdef NX_ENABLE_TCPIP_OFFLOAD +ULONG tcpip_offload; +#endif /* NX_ENABLE_TCPIP_OFFLOAD */ #ifdef NX_ENABLE_LOW_WATERMARK UCHAR drop_packet = NX_FALSE; #endif /* NX_ENABLE_LOW_WATERMARK */ @@ -349,6 +355,10 @@ NX_IP *ip_ptr; ip_ptr = socket_ptr -> nx_tcp_socket_ip_ptr; #endif +#ifdef NX_ENABLE_TCPIP_OFFLOAD + tcpip_offload = socket_ptr -> nx_tcp_socket_connect_interface -> nx_interface_capability_flag & + NX_INTERFACE_CAPABILITY_TCPIP_OFFLOAD; +#endif /* NX_ENABLE_TCPIP_OFFLOAD */ /* Pickup the pointer to the head of the TCP packet. */ /*lint -e{927} -e{826} suppress cast of pointer to pointer, since it is necessary */ @@ -370,7 +380,11 @@ NX_IP *ip_ptr; packet_end_sequence = tcp_header_ptr -> nx_tcp_sequence_number + packet_data_length; /* Trim the data that out of the receive window, make sure all data are in receive window. */ - if (packet_data_length) + if (packet_data_length +#ifdef NX_ENABLE_TCPIP_OFFLOAD + && (!tcpip_offload) +#endif /* NX_ENABLE_TCPIP_OFFLOAD */ + ) { /* Step1. trim the data on the left side of the receive window. */ @@ -480,13 +494,17 @@ NX_IP *ip_ptr; search_end_sequence = socket_ptr -> nx_tcp_socket_rx_sequence; } -#ifdef NX_ENABLE_LOW_WATERMARK /* Does the number of queued packets exceed the maximum rx queue length, or the number of * available packets in the default packet pool reaches low watermark? */ - if ((socket_ptr -> nx_tcp_socket_receive_queue_count >= - socket_ptr -> nx_tcp_socket_receive_queue_maximum) || - (packet_ptr -> nx_packet_pool_owner -> nx_packet_pool_available < - packet_ptr -> nx_packet_pool_owner -> nx_packet_pool_low_watermark)) +#ifdef NX_ENABLE_LOW_WATERMARK + if (((socket_ptr -> nx_tcp_socket_receive_queue_count >= + socket_ptr -> nx_tcp_socket_receive_queue_maximum) || + (packet_ptr -> nx_packet_pool_owner -> nx_packet_pool_available < + packet_ptr -> nx_packet_pool_owner -> nx_packet_pool_low_watermark)) +#ifdef NX_ENABLE_TCPIP_OFFLOAD + && (!tcpip_offload) +#endif /* NX_ENABLE_TCPIP_OFFLOAD */ + ) { /* Yes it is. The last packet in queue should be dropped. */ @@ -497,8 +515,12 @@ NX_IP *ip_ptr; /* Determine if we have a simple case of TCP data coming in the correct order. This means the socket's sequence number matches the incoming packet sequence number and the last packet's data on the socket's receive queue (if any) matches the current sequence number. */ - if ((tcp_header_ptr -> nx_tcp_sequence_number == socket_ptr -> nx_tcp_socket_rx_sequence) && - (search_end_sequence == socket_ptr -> nx_tcp_socket_rx_sequence)) + if (((tcp_header_ptr -> nx_tcp_sequence_number == socket_ptr -> nx_tcp_socket_rx_sequence) && + (search_end_sequence == socket_ptr -> nx_tcp_socket_rx_sequence)) +#ifdef NX_ENABLE_TCPIP_OFFLOAD + || tcpip_offload +#endif /* NX_ENABLE_TCPIP_OFFLOAD */ + ) { /* Yes, this is the simple case of adding receive packets in sequence. */ @@ -534,7 +556,12 @@ NX_IP *ip_ptr; socket_ptr -> nx_tcp_socket_receive_queue_tail = packet_ptr; /* Setup a new delayed ACK timeout. */ - socket_ptr -> nx_tcp_socket_delayed_ack_timeout = _nx_tcp_ack_timer_rate; +#ifdef NX_ENABLE_TCPIP_OFFLOAD + if (!tcpip_offload) +#endif /* NX_ENABLE_TCPIP_OFFLOAD */ + { + socket_ptr -> nx_tcp_socket_delayed_ack_timeout = _nx_tcp_ack_timer_rate; + } } /* Increment the receive TCP packet count. */ @@ -1059,7 +1086,7 @@ NX_IP *ip_ptr; /* At this point, we can use the packet TCP header pointers since the received packet is already queued. */ - /* Any packets for receving? */ + /* Any packets for receiving? */ while (acked_packets && socket_ptr -> nx_tcp_socket_receive_suspension_list) { @@ -1134,7 +1161,11 @@ NX_IP *ip_ptr; /* If the incoming packet caused the sequence number to move forward, indicating the new piece of data is in order, in sequence, and valid for receiving. */ - if (original_rx_sequence != socket_ptr -> nx_tcp_socket_rx_sequence) + if ((original_rx_sequence != socket_ptr -> nx_tcp_socket_rx_sequence) +#ifdef NX_ENABLE_TCPIP_OFFLOAD + || tcpip_offload +#endif /* NX_ENABLE_TCPIP_OFFLOAD */ + ) { /* Determine if there is a socket receive notification function specified. */ if (socket_ptr -> nx_tcp_receive_callback) diff --git a/common/src/nx_udp_socket_bind.c b/common/src/nx_udp_socket_bind.c index 6917a2a6..c1ad243c 100644 --- a/common/src/nx_udp_socket_bind.c +++ b/common/src/nx_udp_socket_bind.c @@ -30,12 +30,117 @@ #include "tx_thread.h" +#ifdef NX_ENABLE_TCPIP_OFFLOAD +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _nx_udp_socket_driver_bind PORTABLE C */ +/* 6.1.8 */ +/* AUTHOR */ +/* */ +/* Yuxin Zhou, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function binds to a UDP port through TCP/IP offload interface. */ +/* */ +/* INPUT */ +/* */ +/* socket_ptr Pointer to UDP socket */ +/* port 16-bit UDP port number */ +/* wait_option Suspension option */ +/* */ +/* OUTPUT */ +/* */ +/* status Completion status */ +/* */ +/* CALLS */ +/* */ +/* _nx_udp_socket_unbind Unbind UDP port */ +/* tx_mutex_get Obtain protection mutex */ +/* tx_mutex_put Release protection mutex */ +/* */ +/* CALLED BY */ +/* */ +/* _nx_udp_socket_bind */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 08-02-2021 Yuxin Zhou Initial Version 6.1.8 */ +/* */ +/**************************************************************************/ +static UINT _nx_udp_socket_driver_bind(NX_UDP_SOCKET *socket_ptr, UINT port, ULONG wait_option) +{ +UINT status = NX_SUCCESS; +UINT i; +NX_INTERFACE *interface_ptr; +NX_IP *ip_ptr; + + + /* Setup the pointer to the associated IP instance. */ + ip_ptr = socket_ptr -> nx_udp_socket_ip_ptr; + + /* Obtain the IP mutex. */ + tx_mutex_get(&(ip_ptr -> nx_ip_protection), TX_WAIT_FOREVER); + + /* Loop all interfaces to bind to ones support TCP/IP offload. */ + for (i = 0; i < NX_MAX_IP_INTERFACES; i++) + { + + /* Use a local variable for convenience. */ + interface_ptr = &(ip_ptr -> nx_ip_interface[i]); + + /* Check for valid interfaces. */ + if ((interface_ptr -> nx_interface_valid == NX_FALSE) || + (interface_ptr -> nx_interface_link_up == NX_FALSE)) + { + + /* Skip interface not valid. */ + continue; + } + + /* Check for TCP/IP offload feature. */ + if (((interface_ptr -> nx_interface_capability_flag & NX_INTERFACE_CAPABILITY_TCPIP_OFFLOAD) == 0) || + (interface_ptr -> nx_interface_tcpip_offload_handler == NX_NULL)) + { + + /* Skip interface not support TCP/IP offload. */ + continue; + } + + /* Let TCP/IP offload interface bind to port. */ + status = interface_ptr -> nx_interface_tcpip_offload_handler(ip_ptr, interface_ptr, + socket_ptr, + NX_TCPIP_OFFLOAD_UDP_SOCKET_BIND, + NX_NULL, NX_NULL, NX_NULL, port, + NX_NULL, wait_option); + if (status) + { + + /* At least one of the interface fails to bind to port. */ + _nx_udp_socket_unbind(socket_ptr); + status = NX_TCPIP_OFFLOAD_ERROR; + break; + } + } + + /* Release the IP protection. */ + tx_mutex_put(&(ip_ptr -> nx_ip_protection)); + + return(status); +} +#endif /* NX_ENABLE_TCPIP_OFFLOAD */ + + /**************************************************************************/ /* */ /* FUNCTION RELEASE */ /* */ /* _nx_udp_socket_bind PORTABLE C */ -/* 6.1 */ +/* 6.1.8 */ /* AUTHOR */ /* */ /* Yuxin Zhou, Microsoft Corporation */ @@ -75,6 +180,9 @@ /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */ /* 09-30-2020 Yuxin Zhou Modified comment(s), */ /* resulting in version 6.1 */ +/* 08-02-2021 Yuxin Zhou Modified comment(s), and */ +/* supported TCP/IP offload, */ +/* resulting in version 6.1.8 */ /* */ /**************************************************************************/ UINT _nx_udp_socket_bind(NX_UDP_SOCKET *socket_ptr, UINT port, ULONG wait_option) @@ -89,6 +197,7 @@ NX_IP *ip_ptr; TX_THREAD *thread_ptr; NX_UDP_SOCKET *search_ptr; NX_UDP_SOCKET *end_ptr; +UINT status = NX_SUCCESS; /* Setup the pointer to the associated IP instance. */ @@ -222,9 +331,6 @@ NX_UDP_SOCKET *end_ptr; /* Release the mutex protection. */ tx_mutex_put(&(ip_ptr -> nx_ip_protection)); - - /* Return success to the caller. */ - return(NX_SUCCESS); } else if (wait_option) { @@ -296,7 +402,7 @@ NX_UDP_SOCKET *end_ptr; _tx_thread_system_suspend(thread_ptr); /* Return the completion status. */ - return(thread_ptr -> tx_thread_suspend_status); + status = thread_ptr -> tx_thread_suspend_status; } else { @@ -305,7 +411,19 @@ NX_UDP_SOCKET *end_ptr; tx_mutex_put(&(ip_ptr -> nx_ip_protection)); /* Return the port unavailable error. */ - return(NX_PORT_UNAVAILABLE); + status = NX_PORT_UNAVAILABLE; + } + +#ifdef NX_ENABLE_TCPIP_OFFLOAD + if (status == NX_SUCCESS) + { + + /* Bind to TCP/IP offload interface. */ + status = _nx_udp_socket_driver_bind(socket_ptr, port, wait_option); } +#endif /* NX_ENABLE_TCPIP_OFFLOAD */ + + /* Return success to the caller. */ + return(status); } diff --git a/common/src/nx_udp_socket_driver_packet_receive.c b/common/src/nx_udp_socket_driver_packet_receive.c new file mode 100644 index 00000000..cfc9897f --- /dev/null +++ b/common/src/nx_udp_socket_driver_packet_receive.c @@ -0,0 +1,158 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) Microsoft Corporation. All rights reserved. */ +/* */ +/* This software is licensed under the Microsoft Software License */ +/* Terms for Microsoft Azure RTOS. Full text of the license can be */ +/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ +/* and in the root directory of this software. */ +/* */ +/**************************************************************************/ + + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** NetX Component */ +/** */ +/** User Datagram Protocol (UDP) */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + +#define NX_SOURCE_CODE + + +/* Include necessary system files. */ + +#include "nx_api.h" +#include "tx_thread.h" +#include "nx_udp.h" +#include "nx_packet.h" +#include "nx_ip.h" +#ifdef FEATURE_NX_IPV6 +#include "nx_ipv6.h" +#endif /* FEATURE_NX_IPV6 */ + + +#ifdef NX_ENABLE_TCPIP_OFFLOAD +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _nx_udp_socket_driver_packet_receive PORTABLE C */ +/* 6.1.8 */ +/* AUTHOR */ +/* */ +/* Yuxin Zhou, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function receives a UDP packet from the TCP/IP driver and add */ +/* fake TCP/IP header. Then pass the packet to IP deferred receive */ +/* routine. */ +/* */ +/* INPUT */ +/* */ +/* socket_ptr Pointer to owning socket */ +/* packet_ptr Pointer to packet to process */ +/* local_ip Pointer to local IP address */ +/* remote_ip Pointer to remote IP address */ +/* remote_port Pointer to remote UDP port */ +/* */ +/* OUTPUT */ +/* */ +/* None */ +/* */ +/* CALLS */ +/* */ +/* tx_mutex_get Obtain protection mutex */ +/* tx_mutex_put Release protection mutex */ +/* _nx_ip_packet_deferred_receive Defer IP packet receive */ +/* */ +/* CALLED BY */ +/* */ +/* Driver */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 08-02-2021 Yuxin Zhou Initial Version 6.1.8 */ +/* */ +/**************************************************************************/ +VOID _nx_udp_socket_driver_packet_receive(NX_UDP_SOCKET *socket_ptr, NX_PACKET *packet_ptr, + NXD_ADDRESS *local_ip, NXD_ADDRESS *remote_ip, UINT remote_port) +{ + +NX_IP *ip_ptr; +NX_UDP_HEADER *udp_header_ptr; + + /* Setup the IP pointer. */ + ip_ptr = socket_ptr -> nx_udp_socket_ip_ptr; + + if (packet_ptr == NX_NULL) + { + + /* Socket error. Just ignore. */ + return; + } + + /* Fake UDP and IP header. */ + /* Prepend the UDP header to the packet. First, make room for the UDP header. */ + packet_ptr -> nx_packet_prepend_ptr = packet_ptr -> nx_packet_prepend_ptr - sizeof(NX_UDP_HEADER); + + /* Increase the packet length. */ + packet_ptr -> nx_packet_length = packet_ptr -> nx_packet_length + (ULONG)sizeof(NX_UDP_HEADER); + + /* Setup the UDP header pointer. */ + /*lint -e{927} -e{826} suppress cast of pointer to pointer, since it is necessary */ + udp_header_ptr = (NX_UDP_HEADER *)packet_ptr -> nx_packet_prepend_ptr; + + /* Build the first 32-bit word of the UDP header. */ + udp_header_ptr -> nx_udp_header_word_0 = + ((ULONG)remote_port << NX_SHIFT_BY_16) | (ULONG)socket_ptr -> nx_udp_socket_port; + + /* Build the second 32-bit word of the UDP header. */ + udp_header_ptr -> nx_udp_header_word_1 = (packet_ptr -> nx_packet_length << NX_SHIFT_BY_16); + + /* Endian swapping logic. If NX_LITTLE_ENDIAN is specified, these macros will + swap the endian of the UDP header. */ + NX_CHANGE_ULONG_ENDIAN(udp_header_ptr -> nx_udp_header_word_0); + NX_CHANGE_ULONG_ENDIAN(udp_header_ptr -> nx_udp_header_word_1); + +#ifndef NX_DISABLE_IPV4 + if (remote_ip -> nxd_ip_version == NX_IP_VERSION_V4) + { + _nx_ip_header_add(ip_ptr, packet_ptr, remote_ip -> nxd_ip_address.v4, + local_ip -> nxd_ip_address.v4, + socket_ptr -> nx_udp_socket_type_of_service, + socket_ptr -> nx_udp_socket_time_to_live, + NX_IP_UDP, + socket_ptr -> nx_udp_socket_fragment_enable); + } +#endif /* !NX_DISABLE_IPV4 */ + +#ifdef FEATURE_NX_IPV6 + if (remote_ip -> nxd_ip_version == NX_IP_VERSION_V6) + { + if (_nx_ipv6_header_add(ip_ptr, &packet_ptr, + NX_PROTOCOL_UDP, + packet_ptr -> nx_packet_length, + ip_ptr -> nx_ipv6_hop_limit, + remote_ip -> nxd_ip_address.v6, + local_ip -> nxd_ip_address.v6, + NX_NULL)) + { + + /* Release the IP internal mutex. */ + tx_mutex_put(&(ip_ptr -> nx_ip_protection)); + return; + } + } +#endif /* FEATURE_NX_IPV6 */ + + _nx_ip_packet_deferred_receive(ip_ptr, packet_ptr); +} +#endif /* NX_ENABLE_TCPIP_OFFLOAD */ + diff --git a/common/src/nx_udp_socket_unbind.c b/common/src/nx_udp_socket_unbind.c index 145e2743..05953d1e 100644 --- a/common/src/nx_udp_socket_unbind.c +++ b/common/src/nx_udp_socket_unbind.c @@ -31,12 +31,98 @@ #include "tx_thread.h" +#ifdef NX_ENABLE_TCPIP_OFFLOAD +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _nx_udp_socket_driver_unbind PORTABLE C */ +/* 6.1.8 */ +/* AUTHOR */ +/* */ +/* Yuxin Zhou, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function unbinds a UDP port through TCP/IP offload interface. */ +/* */ +/* INPUT */ +/* */ +/* socket_ptr Pointer to UDP socket */ +/* */ +/* OUTPUT */ +/* */ +/* status Completion status */ +/* */ +/* CALLS */ +/* */ +/* None */ +/* */ +/* CALLED BY */ +/* */ +/* _nx_udp_socket_bind */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 08-02-2021 Yuxin Zhou Initial Version 6.1.8 */ +/* */ +/**************************************************************************/ +static UINT _nx_udp_socket_driver_unbind(NX_UDP_SOCKET *socket_ptr) +{ +UINT i; +NX_INTERFACE *interface_ptr; +NX_IP *ip_ptr; + + + /* Setup the pointer to the associated IP instance. */ + ip_ptr = socket_ptr -> nx_udp_socket_ip_ptr; + + /* Loop all interfaces to unbind to ones support TCP/IP offload. */ + for (i = 0; i < NX_MAX_IP_INTERFACES; i++) + { + + /* Use a local variable for convenience. */ + interface_ptr = &(ip_ptr -> nx_ip_interface[i]); + + /* Check for valid interfaces. */ + if (interface_ptr -> nx_interface_valid == NX_FALSE) + { + + /* Skip interface not valid. */ + continue; + } + + /* Check for TCP/IP offload feature. */ + if (((interface_ptr -> nx_interface_capability_flag & NX_INTERFACE_CAPABILITY_TCPIP_OFFLOAD) == 0) || + (interface_ptr -> nx_interface_tcpip_offload_handler == NX_NULL)) + { + + /* Skip interface not support TCP/IP offload. */ + continue; + } + + /* Let TCP/IP offload interface unbind port. Return value is ignored. */ + interface_ptr -> nx_interface_tcpip_offload_handler(ip_ptr, interface_ptr, + socket_ptr, + NX_TCPIP_OFFLOAD_UDP_SOCKET_UNBIND, + NX_NULL, NX_NULL, NX_NULL, + socket_ptr -> nx_udp_socket_port, + NX_NULL, NX_NO_WAIT); + } + + return(NX_SUCCESS); +} +#endif /* NX_ENABLE_TCPIP_OFFLOAD */ + + /**************************************************************************/ /* */ /* FUNCTION RELEASE */ /* */ /* _nx_udp_socket_unbind PORTABLE C */ -/* 6.1 */ +/* 6.1.8 */ /* AUTHOR */ /* */ /* Yuxin Zhou, Microsoft Corporation */ @@ -74,6 +160,9 @@ /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */ /* 09-30-2020 Yuxin Zhou Modified comment(s), */ /* resulting in version 6.1 */ +/* 08-02-2021 Yuxin Zhou Modified comment(s), and */ +/* supported TCP/IP offload, */ +/* resulting in version 6.1.8 */ /* */ /**************************************************************************/ UINT _nx_udp_socket_unbind(NX_UDP_SOCKET *socket_ptr) @@ -138,6 +227,10 @@ NX_PACKET *next_packet_ptr; /* Calculate the hash index in the UDP port array of the associated IP instance. */ index = (UINT)((port + (port >> 8)) & NX_UDP_PORT_TABLE_MASK); +#ifdef NX_ENABLE_TCPIP_OFFLOAD + _nx_udp_socket_driver_unbind(socket_ptr); +#endif /* NX_ENABLE_TCPIP_OFFLOAD */ + /* Disable interrupts while we unlink the current socket. */ TX_DISABLE diff --git a/common/src/nx_utility.c b/common/src/nx_utility.c index b8d1a827..04c4bae0 100644 --- a/common/src/nx_utility.c +++ b/common/src/nx_utility.c @@ -204,6 +204,116 @@ UINT i; /* */ /* FUNCTION RELEASE */ /* */ +/* _nx_utility_uint_to_string PORTABLE C */ +/* 6.1.8 */ +/* AUTHOR */ +/* */ +/* Yuxin Zhou, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function converts the unsigned integer to string. */ +/* */ +/* INPUT */ +/* */ +/* number Input number */ +/* base Base of the conversion */ +/* 8 for OCT */ +/* 10 for DEC */ +/* 16 for HEX */ +/* string_buffer Pointer to string buffer */ +/* string_buffer_size Size of string buffer */ +/* */ +/* OUTPUT */ +/* */ +/* size The size of output string */ +/* */ +/* CALLS */ +/* */ +/* None */ +/* */ +/* CALLED BY */ +/* */ +/* Application Code */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 08-02-2021 Yuxin Zhou Initial Version 6.1.8 */ +/* */ +/**************************************************************************/ +UINT _nx_utility_uint_to_string(UINT number, UINT base, CHAR *string_buffer, UINT string_buffer_size) +{ +UINT i; +UINT digit; +UINT size; + + /* Check for invalid input pointers. */ + if ((string_buffer == NX_NULL) || (string_buffer_size == 0)) + { + return(0); + } + + /* Initialize. */ + i = 0; + size = 0; + + /* Loop to convert the number to ASCII. Minus 1 to put NULL terminal. */ + while (size < string_buffer_size - 1) + { + + /* Shift the current digits over one. */ + for (i = size; i != 0; i--) + { + + /* Move each digit over one place. */ + string_buffer[i] = string_buffer[i-1]; + } + + /* Compute the next decimal digit. */ + digit = number % base; + + /* Update the input number. */ + number = number / base; + + /* Store the new digit in ASCII form. */ + if (digit < 10) + { + string_buffer[0] = (CHAR) (digit + '0'); + } + else + { + string_buffer[0] = (CHAR) (digit + 'a' - 0xa); + } + + /* Increment the size. */ + size++; + + /* Determine if the number is now zero. */ + if (number == 0) + break; + } + + /* Determine if there is an overflow error. */ + if (number) + { + + /* Error, return bad values to user. */ + size = 0; + } + + /* Make the string NULL terminated. */ + string_buffer[size] = (CHAR) NX_NULL; + + /* Return size to caller. */ + return(size); +} + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ /* _nx_utility_base64_encode PORTABLE C */ /* 6.1.6 */ /* AUTHOR */ @@ -505,4 +615,4 @@ UINT source_size = base64name_size; *bytes_copied = j; return(NX_SUCCESS); -} +}
\ No newline at end of file diff --git a/common/src/nxd_tcp_client_socket_connect.c b/common/src/nxd_tcp_client_socket_connect.c index 9cbd88ab..a2df3662 100644 --- a/common/src/nxd_tcp_client_socket_connect.c +++ b/common/src/nxd_tcp_client_socket_connect.c @@ -32,12 +32,163 @@ #include "nx_ipv4.h" #include "nx_ip.h" + +#ifdef NX_ENABLE_TCPIP_OFFLOAD +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _nxd_tcp_client_socket_driver_connect PORTABLE C */ +/* 6.1.8 */ +/* AUTHOR */ +/* */ +/* Yuxin Zhou, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function handles the connect request for TCP/IP offload */ +/* interface. */ +/* */ +/* INPUT */ +/* */ +/* socket_ptr Pointer to TCP client socket */ +/* server_ip IP address of server */ +/* server_port Port number of server */ +/* wait_option Suspension option */ +/* */ +/* OUTPUT */ +/* */ +/* status Completion status */ +/* */ +/* CALLS */ +/* */ +/* tx_mutex_get Obtain protection */ +/* tx_mutex_put Release protection */ +/* */ +/* CALLED BY */ +/* */ +/* _nxd_tcp_client_socket_connect */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 08-02-2021 Yuxin Zhou Initial Version 6.1.8 */ +/* */ +/**************************************************************************/ +static UINT _nxd_tcp_client_socket_driver_connect(NX_TCP_SOCKET *socket_ptr, + NXD_ADDRESS *server_ip, + UINT server_port, + ULONG wait_option) +{ +UINT status; +NX_INTERFACE *interface_ptr; +NX_IP *ip_ptr; + + + /* Setup the pointer to the associated IP instance. */ + ip_ptr = socket_ptr -> nx_tcp_socket_ip_ptr; + + /* Clear the socket timeout. */ + socket_ptr -> nx_tcp_socket_timeout = 0; + + /* Let TCP/IP offload interface make the connection. */ + interface_ptr = socket_ptr -> nx_tcp_socket_connect_interface; + status = interface_ptr -> nx_interface_tcpip_offload_handler(ip_ptr, interface_ptr, socket_ptr, + NX_TCPIP_OFFLOAD_TCP_CLIENT_SOCKET_CONNECT, + NX_NULL, NX_NULL, server_ip, + socket_ptr -> nx_tcp_socket_port, + &server_port, wait_option); + if ((status == NX_SUCCESS) || (status == NX_IN_PROGRESS)) + { + + /* Set MSS. */ +#ifndef NX_DISABLE_IPV4 + if (server_ip -> nxd_ip_version == NX_IP_VERSION_V4) + { + socket_ptr -> nx_tcp_socket_mss = + (ULONG)((interface_ptr -> nx_interface_ip_mtu_size - sizeof(NX_IPV4_HEADER)) - sizeof(NX_TCP_HEADER)); + } +#endif /* !NX_DISABLE_IPV4 */ +#ifdef FEATURE_NX_IPV6 + if (server_ip -> nxd_ip_version == NX_IP_VERSION_V6) + { + socket_ptr -> nx_tcp_socket_mss = + (ULONG)((interface_ptr -> nx_interface_ip_mtu_size - sizeof(NX_IPV6_HEADER)) - sizeof(NX_TCP_HEADER)); + } +#endif /* FEATURE_NX_IPV6 */ + socket_ptr -> nx_tcp_socket_connect_mss = socket_ptr -> nx_tcp_socket_mss; + socket_ptr -> nx_tcp_socket_peer_mss = socket_ptr -> nx_tcp_socket_mss; + + if (status == NX_SUCCESS) + { + + /* Connected to server. */ + socket_ptr -> nx_tcp_socket_state = NX_TCP_ESTABLISHED; +#ifndef NX_DISABLE_EXTENDED_NOTIFY_SUPPORT + + /* Is a connection completion callback registered with the TCP socket? */ + if (socket_ptr -> nx_tcp_establish_notify) + { + + /* Call the application's establish callback function. */ + (socket_ptr -> nx_tcp_establish_notify)(socket_ptr); + } +#endif + + /* Release the IP protection. */ + tx_mutex_put(&(ip_ptr -> nx_ip_protection)); + return(NX_SUCCESS); + } + else + { + + /* Connected to server. */ + socket_ptr -> nx_tcp_socket_state = NX_TCP_SYN_SENT; + } + } + else + { + + /* Unable to connect to server. */ + +#ifndef NX_DISABLE_TCP_INFO + + /* Reduce the active connections count. */ + ip_ptr -> nx_ip_tcp_active_connections--; + + /* Reduce the TCP connections count. */ + ip_ptr -> nx_ip_tcp_connections--; +#endif + + /* Restore the socket state. */ + socket_ptr -> nx_tcp_socket_state = NX_TCP_CLOSED; + + /* Reset server port and server IP address. */ + memset(&socket_ptr -> nx_tcp_socket_connect_ip, 0, sizeof(NXD_ADDRESS)); + socket_ptr -> nx_tcp_socket_connect_port = 0; + + /* Reset the next_hop_address information. */ + socket_ptr -> nx_tcp_socket_next_hop_address = 0; + + /* Release the IP protection. */ + tx_mutex_put(&(ip_ptr -> nx_ip_protection)); + return(NX_TCPIP_OFFLOAD_ERROR); + } + + /* Release the IP protection. */ + tx_mutex_put(&(ip_ptr -> nx_ip_protection)); + return(NX_SUCCESS); +} +#endif /* NX_ENABLE_TCPIP_OFFLOAD */ + + /**************************************************************************/ /* */ /* FUNCTION RELEASE */ /* */ /* _nxd_tcp_client_socket_connect PORTABLE C */ -/* 6.1 */ +/* 6.1.8 */ /* AUTHOR */ /* */ /* Yuxin Zhou, Microsoft Corporation */ @@ -79,6 +230,9 @@ /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */ /* 09-30-2020 Yuxin Zhou Modified comment(s), */ /* resulting in version 6.1 */ +/* 08-02-2021 Yuxin Zhou Modified comment(s), and */ +/* supported TCP/IP offload, */ +/* resulting in version 6.1.8 */ /* */ /**************************************************************************/ UINT _nxd_tcp_client_socket_connect(NX_TCP_SOCKET *socket_ptr, @@ -307,8 +461,21 @@ ULONG ip_address_log = 0; socket_ptr -> nx_tcp_socket_receive_queue_head = NX_NULL; socket_ptr -> nx_tcp_socket_receive_queue_tail = NX_NULL; - /* Send the SYN message. */ - _nx_tcp_packet_send_syn(socket_ptr, (socket_ptr -> nx_tcp_socket_tx_sequence - 1)); +#ifdef NX_ENABLE_TCPIP_OFFLOAD + if ((outgoing_interface -> nx_interface_capability_flag & NX_INTERFACE_CAPABILITY_TCPIP_OFFLOAD) && + (outgoing_interface -> nx_interface_tcpip_offload_handler)) + { + + /* This interface supports TCP/IP offload. */ + return(_nxd_tcp_client_socket_driver_connect(socket_ptr, server_ip, server_port, wait_option)); + } + else +#endif /* NX_ENABLE_TCPIP_OFFLOAD */ + { + + /* Send the SYN message. */ + _nx_tcp_packet_send_syn(socket_ptr, (socket_ptr -> nx_tcp_socket_tx_sequence - 1)); + } /* Optionally suspend the thread. If timeout occurs, return a connection timeout status. If immediate response is selected, return a connection in progress status. Only on a real diff --git a/common/src/nxd_udp_socket_send.c b/common/src/nxd_udp_socket_send.c index a32c21e9..2f661756 100644 --- a/common/src/nxd_udp_socket_send.c +++ b/common/src/nxd_udp_socket_send.c @@ -28,6 +28,7 @@ #include "nx_api.h" #include "nx_udp.h" #include "nx_ip.h" +#include "nx_packet.h" #ifdef FEATURE_NX_IPV6 #include "nx_ipv6.h" #endif /* FEATURE_NX_IPV6 */ @@ -36,12 +37,177 @@ #include "nx_ipsec.h" #endif /* NX_IPSEC_ENABLE */ + +#ifdef NX_ENABLE_TCPIP_OFFLOAD +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _nx_udp_socket_driver_send PORTABLE C */ +/* 6.1.8 */ +/* AUTHOR */ +/* */ +/* Yuxin Zhou, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function sends a UDP packet through TCP/IP offload interface. */ +/* */ +/* INPUT */ +/* */ +/* socket_ptr Pointer to UDP socket */ +/* packet_ptr Pointer to UDP packet */ +/* ip_src_address Source IP address */ +/* ip_dst_address Destination IP address */ +/* port 16-bit UDP port number */ +/* */ +/* OUTPUT */ +/* */ +/* status Completion status */ +/* */ +/* CALLS */ +/* */ +/* _nx_ip_packet_send Packet send function */ +/* _nx_ipv6_packet_send Packet send function */ +/* */ +/* CALLED BY */ +/* */ +/* _nxd_udp_socket_send */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 08-02-2021 Yuxin Zhou Initial Version 6.1.8 */ +/* */ +/**************************************************************************/ +static UINT _nx_udp_socket_driver_send(NX_UDP_SOCKET *socket_ptr, + NX_PACKET *packet_ptr, + NXD_ADDRESS *ip_src_address, + NXD_ADDRESS *ip_dst_address, + UINT port) +{ +UINT status; +NX_IP *ip_ptr; +NX_INTERFACE *interface_ptr = NX_NULL; +UCHAR *original_ptr = packet_ptr -> nx_packet_prepend_ptr + sizeof(NX_UDP_HEADER); +ULONG original_length = packet_ptr -> nx_packet_length - sizeof(NX_UDP_HEADER); + + /* Set up the pointer to the associated IP instance. */ + ip_ptr = socket_ptr -> nx_udp_socket_ip_ptr; + + /* Get the outgoing interface. */ +#ifndef NX_DISABLE_IPV4 + if (ip_dst_address -> nxd_ip_version == NX_IP_VERSION_V4) + { + interface_ptr = packet_ptr -> nx_packet_address.nx_packet_interface_ptr; + } +#endif /* NX_DISABLE_IPV4 */ +#ifdef FEATURE_NX_IPV6 + if (ip_dst_address -> nxd_ip_version == NX_IP_VERSION_V6) + { + interface_ptr = packet_ptr -> nx_packet_address.nx_packet_ipv6_address_ptr -> nxd_ipv6_address_attached; + } +#endif /* FEATURE_NX_IPV6 */ + +#ifdef NX_ENABLE_IP_PACKET_FILTER + /* Check if the IP packet filter is set. */ + if (ip_ptr -> nx_ip_packet_filter || ip_ptr -> nx_ip_packet_filter_extended) + { + + /* Add the IP Header to trigger filtering. */ +#ifndef NX_DISABLE_IPV4 + if (ip_dst_address -> nxd_ip_version == NX_IP_VERSION_V4) + { + _nx_ip_header_add(ip_ptr, packet_ptr, + ip_src_address -> nxd_ip_address.v4, + ip_dst_address -> nxd_ip_address.v4, + socket_ptr -> nx_udp_socket_type_of_service, + socket_ptr -> nx_udp_socket_time_to_live, + NX_IP_UDP, socket_ptr -> nx_udp_socket_fragment_enable); + } +#endif /* !NX_DISABLE_IPV4 */ + +#ifdef FEATURE_NX_IPV6 + if (ip_dst_address -> nxd_ip_version == NX_IP_VERSION_V6) + { + if (_nx_ipv6_header_add(ip_ptr, &packet_ptr, NX_PROTOCOL_UDP, + packet_ptr -> nx_packet_length, + ip_ptr -> nx_ipv6_hop_limit, + ip_src_address -> nxd_ip_address.v6, + ip_dst_address -> nxd_ip_address.v6, NX_NULL)) + { + + /* Packet consumed by IPv6 layer. Just return success. */ + tx_mutex_put(&(ip_ptr -> nx_ip_protection)); + return(NX_SUCCESS); + } + + /* Reset IP header. */ + packet_ptr -> nx_packet_prepend_ptr = packet_ptr -> nx_packet_prepend_ptr + sizeof(NX_IPV6_HEADER); + packet_ptr -> nx_packet_length = packet_ptr -> nx_packet_length - sizeof(NX_IPV6_HEADER); + } +#endif /* FEATURE_NX_IPV6 */ + + if (ip_ptr -> nx_ip_packet_filter) + { + if (ip_ptr -> nx_ip_packet_filter((VOID *)(packet_ptr -> nx_packet_prepend_ptr), + NX_IP_PACKET_OUT) != NX_SUCCESS) + { + + /* Packet consumed by IP filter. Just return success. */ + _nx_packet_transmit_release(packet_ptr); + return(NX_SUCCESS); + } + } + + /* Check if the IP packet filter extended is set. */ + if (ip_ptr -> nx_ip_packet_filter_extended) + { + + /* Yes, call the IP packet filter extended routine. */ + if (ip_ptr -> nx_ip_packet_filter_extended(ip_ptr, packet_ptr, NX_IP_PACKET_OUT) != NX_SUCCESS) + { + + /* Packet consumed by IP filter. Just return success. */ + _nx_packet_transmit_release(packet_ptr); + return(NX_SUCCESS); + } + } + } +#endif /* NX_ENABLE_IP_PACKET_FILTER */ + + /* Reset UDP and IP header. */ + packet_ptr -> nx_packet_prepend_ptr = original_ptr; + packet_ptr -> nx_packet_length = original_length; + + /* Let TCP/IP offload interface send the packet. */ + status = interface_ptr -> nx_interface_tcpip_offload_handler(ip_ptr, interface_ptr, socket_ptr, + NX_TCPIP_OFFLOAD_UDP_SOCKET_SEND, + packet_ptr, ip_src_address, ip_dst_address, + socket_ptr -> nx_udp_socket_port, + &port, NX_NO_WAIT); + + /* Release the IP protection. */ + tx_mutex_put(&(ip_ptr -> nx_ip_protection)); + + if (status) + { + return(NX_TCPIP_OFFLOAD_ERROR); + } + else + { + return(NX_SUCCESS); + } +} +#endif /* NX_ENABLE_TCPIP_OFFLOAD */ + /**************************************************************************/ /* */ /* FUNCTION RELEASE */ /* */ /* _nxd_udp_socket_send PORTABLE C */ -/* 6.1 */ +/* 6.1.8 */ /* AUTHOR */ /* */ /* Yuxin Zhou, Microsoft Corporation */ @@ -87,6 +253,9 @@ /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */ /* 09-30-2020 Yuxin Zhou Modified comment(s), */ /* resulting in version 6.1 */ +/* 08-02-2021 Yuxin Zhou Modified comment(s), and */ +/* supported TCP/IP offload, */ +/* resulting in version 6.1.8 */ /* */ /**************************************************************************/ UINT _nxd_udp_socket_send(NX_UDP_SOCKET *socket_ptr, @@ -109,6 +278,10 @@ NX_INTERFACE *interface_ptr = NX_NULL; UINT status; #endif /* FEATURE_NX_IPV6 */ +#ifdef NX_ENABLE_TCPIP_OFFLOAD +NXD_ADDRESS ip_src_address; +#endif /* NX_ENABLE_TCPIP_OFFLOAD */ + #ifdef NX_IPSEC_ENABLE VOID *sa = NX_NULL; ULONG data_offset; @@ -199,6 +372,11 @@ UINT compute_checksum = 1; /* Fill in the IP src/dest address */ ip_dest_addr = &ip_address -> nxd_ip_address.v4; ip_src_addr = &interface_ptr -> nx_interface_ip_address; + +#ifdef NX_ENABLE_TCPIP_OFFLOAD + ip_src_address.nxd_ip_version = NX_IP_VERSION_V4; + ip_src_address.nxd_ip_address.v4 = interface_ptr -> nx_interface_ip_address; +#endif /* NX_ENABLE_TCPIP_OFFLOAD */ } #endif /* NX_DISABLE_IPV4 */ @@ -229,6 +407,11 @@ UINT compute_checksum = 1; /* Get the packet interface information. */ interface_ptr = packet_ptr -> nx_packet_address.nx_packet_ipv6_address_ptr -> nxd_ipv6_address_attached; #endif /* NX_ENABLE_INTERFACE_CAPABILITY */ + +#ifdef NX_ENABLE_TCPIP_OFFLOAD + ip_src_address.nxd_ip_version = NX_IP_VERSION_V6; + COPY_IPV6_ADDRESS(ip_src_addr, ip_src_address.nxd_ip_address.v6); +#endif /* NX_ENABLE_TCPIP_OFFLOAD */ } #endif /* FEATURE_NX_IPV6 */ @@ -281,7 +464,7 @@ UINT compute_checksum = 1; } } #endif /* NX_IPSEC_ENABLE */ - + /* Prepend the UDP header to the packet. First, make room for the UDP header. */ packet_ptr -> nx_packet_prepend_ptr = packet_ptr -> nx_packet_prepend_ptr - sizeof(NX_UDP_HEADER); @@ -320,16 +503,16 @@ UINT compute_checksum = 1; NX_TRACE_IN_LINE_INSERT(NX_TRACE_INTERNAL_UDP_SEND, ip_ptr, socket_ptr, packet_ptr, udp_header_ptr -> nx_udp_header_word_0, NX_TRACE_INTERNAL_EVENTS, 0, 0); /* Endian swapping logic. If NX_LITTLE_ENDIAN is specified, these macros will - swap the endian of the UDP header. */ + swap the endian of the UDP header. */ NX_CHANGE_ULONG_ENDIAN(udp_header_ptr -> nx_udp_header_word_0); NX_CHANGE_ULONG_ENDIAN(udp_header_ptr -> nx_udp_header_word_1); /* Determine if we need to compute the UDP checksum. - Note that with IPv6, UDP packet checksum is mandatory. However if the underly device - driver is able to compute UDP checksum in hardware, let the driver handle the checksum - computation. - */ + Note that with IPv6, UDP packet checksum is mandatory. However if the underly device + driver is able to compute UDP checksum in hardware, let the driver handle the checksum + computation. + */ if ((!socket_ptr -> nx_udp_socket_disable_checksum) || (ip_address -> nxd_ip_version == NX_IP_VERSION_V6)) @@ -343,8 +526,8 @@ UINT compute_checksum = 1; #ifdef NX_IPSEC_ENABLE /* In case this packet is going through the IPsec protected channel, the checksum would have to be computed - in software even if the hardware checksum is available at driver layer. The checksum value must be present - in order when applying IPsec process. */ + in software even if the hardware checksum is available at driver layer. The checksum value must be present + in order when applying IPsec process. */ if ((packet_ptr -> nx_packet_ipsec_sa_ptr != NX_NULL) && (((NX_IPSEC_SA *)(packet_ptr -> nx_packet_ipsec_sa_ptr)) -> nx_ipsec_sa_encryption_method != NX_CRYPTO_NONE)) { @@ -392,6 +575,14 @@ UINT compute_checksum = 1; /* Get mutex protection. */ tx_mutex_get(&(ip_ptr -> nx_ip_protection), TX_WAIT_FOREVER); +#ifdef NX_ENABLE_TCPIP_OFFLOAD + if ((interface_ptr -> nx_interface_capability_flag & NX_INTERFACE_CAPABILITY_TCPIP_OFFLOAD) && + (interface_ptr -> nx_interface_tcpip_offload_handler)) + { + return(_nx_udp_socket_driver_send(socket_ptr, packet_ptr, &ip_src_address, ip_address, port)); + } +#endif /* NX_ENABLE_TCPIP_OFFLOAD */ + #ifndef NX_DISABLE_IPV4 /* Send the UDP packet to the IPv4 component. */ if (ip_address -> nxd_ip_version == NX_IP_VERSION_V4) |
