Closed simonqhughes closed 8 years ago
ARM Internal Ref: IOTSFW-1788
@niklas-arm, I believe you've seen something similar to this. Did you have a fix in mind?
Hi A further observation is that if the udp socket create(), bind(), connect() idiom is used then after the connect the socket is not bound correctly to the interface, but rather the local address is still reported as INADDR_ANY, as shown in the following console trace:
MBED: remote udp server:10.2.203.21:49659
MBED: udp local after bind():0.0.0.0:49153
MBED: udp local after connect():0.0.0.0:49153
MBED: udp_ec_tx_rx_from_test:289 ret!=0 [FAIL]
HOST: Received 32 bytes of data
HOST: Sent 32 bytes of data
MBED: [FAIL] connect() failed as connected local address (0.0.0.0) doesnt match ethernet i/f ip address 10.2.203.161)
How to reproduce this problem:
Best Simon
Fixed in #48
recv_from() returns incorrect remote {ipaddr, port} tuple for udp rx packet data
Problem:
Target received 2 IP packets but lwip layer doesnt reassemble the 2 ip packets into the udp msg but instead delivers 2 udp msg fragments via 2 calls to recv_from(). The first recv_from() correctly recovers the ipaddr:port of the remote host pc transmitter. However the second recv_from() call fails to report the correct ipaddr:port tuple, as shown in the following trace:
first line reports remote ipaddr:port as 15cb020a:49192, which is correct sixth line reports remote ipaddr:port as 80805c8:2562, which is incorrect
This behaviour is a BUG (BUG01).
The following describes behaviour of the lwip stack which developers will find confusing. UDP implementation "normally" preserve msg boundaries or discard large UDP datagrams if a component IP fragment is lost, for example. However, lwip appears to have a different UDP behaviour.
The target received 2 IP packets but lwip doesnt reassemble the 2 ip packets into the udp msg. Instead lwip delivers 2 udp msg fragments via 2 calls to recv_from(). UDP implementations normally preserve message boundaries (see Comparison of Transport protocols here: https://en.wikipedia.org/wiki/Transport_layer# Comparison_of_transport_layer_protocols) but this is not a requirement of rfc1122, for example. Udp message boundaries will be preserved and the sockets layer will present the whole datagram in one recv_from() call, provided the received data buffer is less than the maximum datagram size for the system (see rfc 1122 Sec 4 and 3.4, GET_MAXSIZES()), where the minimum value of GET_MAXSIZES() is the min size of IP packets (576 bytes) less the size of the IP/UDP packet headers. i.e. However, rfc1122 does not state that UDP message boundaries will be preserved always, but rather says:
"Therefore, an application program running over UDP must deal directly with end-to-end communication problems that a connection-oriented protocol would have handled -- e.g., retransmission for reliable delivery, packetization and reassembly, flow control, congestion avoidance, etc., when these are required. The fairly complex coupling between IP and TCP will be mirrored in the coupling between UDP and many applications using UDP."
This is possibly one of those cases where e.g. the BSD reference implementations have become the defacto standard.
The following describes the callback handler API which developers may find unsatisfactory.
The provided udp_echo_client_orig.cpp/socket_abstract_test.cpp provide samples give an example of whats outlined below.
The problem is that the handler had no context argument (better to be void* ctx rather than void), so ctx can be cast to a type to access variable shared between the callback and the mainline code. The disadvantages of this are:
Reproducing BUG01 Problem:
Traces similar to the following will be captured:
defect_report.txt iotsfw_num_tbd_console_trace.txt
iotsfw_num_tbd_sal_stack_lwip_recv_from_returns_incorrect_sockaddr_info_for_remote ipaddr_port_tupl_20160113_pcapng.txt iotsfw_num_tbd__20160113_pcapng.txt
sal_test_api_h.txt sal_udpserver_py.txt socket_abstract_test_cpp.txt udp_echo_client_orig_cpp.txt