I can see that there are two different problems with MTU.
They are completely independent from each other, so let's start with the
simple case first.

I am testing on an STM32F427, using Ethernet.

As previously noted, the following code will cause the running task to hang.

netlib_set_mtu(CONFIG_NETIF_DEV_NAME, 1500);

int sd = socket(AF_INET, SOCK_DGRAM, 0);

struct sockaddr_in server;
server.sin_family      = AF_INET;
server.sin_port        = 1000;
server.sin_addr.s_addr = inet_addr("192.168.1.235");

uint8_t * data = malloc(2048);
memset(data, 0xAA, 2048);

sendto(sd, data, 2048, 0, (struct sockaddr*)&server, sizeof(server));

close(sd);

As you can see, the MTU is set to 1500, and then I try to send a UDP
datagram with a larger size (2048).
Indeed `devif_send()` fails, and the aforementioned semaphore is never
posted.

(This is without buffering in UTP, in case this is important).

This draft PR, provides a solution to the issue.
https://github.com/apache/nuttx/pull/9423

If this is correct, I will also check buffered UDP, and other uses of
devif_send().

Alternatively, devif_send() may be changed to actually return an error code
(instead of returning void), so improved error handling can take place.


On Mon, May 29, 2023 at 1:41 PM Fotis Panagiotopoulos <f.j.pa...@gmail.com>
wrote:

> The failure scenario is a bit more complicated...
>
> Give me some time and I will provide a correct and reproducible example,
> with a clear explanation.
>
> On Mon, May 29, 2023, 13:27 Fotis Panagiotopoulos <f.j.pa...@gmail.com>
> wrote:
>
>> > sendfile should return an error in this case, but senfile should only be
>> > used with TCP, not UDP, since sendfile doesn't have any logic to ack or
>> > retry..
>>
>> Sorry if this wasn't clear. This last test was with plain old `send()`...
>>
>> I opened a UDP socket, and used `send()` to transmit a buffer larger than
>> the MTU.
>> Instead of getting an error, the application hangs indefinitely.
>> `devif_send()` is called periodically, but of course it always fails.
>>
>>
>>
>> On Mon, May 29, 2023 at 1:13 PM Xiang Xiao <xiaoxiang781...@gmail.com>
>> wrote:
>>
>>> On Mon, May 29, 2023 at 5:02 PM Fotis Panagiotopoulos <
>>> f.j.pa...@gmail.com>
>>> wrote:
>>>
>>> > > You need to enable IP fragmentation in this case, which is also added
>>> > > recently and disabled by default:
>>> > > https://github.com/apache/nuttx/pull/8059
>>> > <https://github.com/apache/nuttx/pull/8059>
>>> > > Otherwise, any packet bigger than MTU will be dropped silently.
>>> >
>>> > Yes, this is the expected behavior.
>>> > But, instead of dropping the packet, the system hangs because the
>>> semaphore
>>> > is never posted.
>>> > It just tries endlessly to call devif_send() which always fails.
>>> >
>>> >
>>> sendfile should return an error in this case, but senfile should only be
>>> used with TCP, not UDP, since sendfile doesn't have any logic to ack or
>>> retry..
>>>
>>>
>>> >
>>> >
>>> > On Mon, May 29, 2023 at 11:42 AM Xiang Xiao <xiaoxiang781...@gmail.com
>>> >
>>> > wrote:
>>> >
>>> > > On Sun, May 28, 2023 at 11:55 PM Fotis Panagiotopoulos <
>>> > > f.j.pa...@gmail.com>
>>> > > wrote:
>>> > >
>>> > > > While experimenting with MTU, and checking the stability of my
>>> system,
>>> > I
>>> > > > noticed the following.
>>> > > >
>>> > > > I try to send a UDP datagram that is larger than the configured
>>> MTU.
>>> > > > In this case, the offending thread seems to hang indefinitely (or
>>> at
>>> > > least
>>> > > > waiting for a very long timeout?)
>>> > > >
>>> > >
>>> > > You need to enable IP fragmentation in this case, which is also added
>>> > > recently and disabled by default:
>>> > > https://github.com/apache/nuttx/pull/8059
>>> > > Otherwise, any packet bigger than MTU will be dropped silently.
>>> > >
>>> > >
>>> > > > The problem seems to be this line:
>>> > > >
>>> > > >
>>> > >
>>> >
>>> https://github.com/apache/nuttx/blob/master/net/udp/udp_sendto_unbuffered.c#L197
>>> > > > `devif_send()` fails because the datagram is too large, but
>>> > > > `pstate->st_sem` is never posted (the code returns immediately).
>>> > > >
>>> > > > This leaves the sending task to be blocked here:
>>> > > >
>>> > > >
>>> > >
>>> >
>>> https://github.com/apache/nuttx/blob/master/net/udp/udp_sendto_unbuffered.c#L469
>>> > > >
>>> > > > Shouldn't this failure also post the semaphore?
>>> > > > And let the code proceed returning an error in `send()`?
>>> > > >
>>> > > >
>>> > > > On Sun, May 28, 2023 at 5:26 PM Fotis Panagiotopoulos <
>>> > > f.j.pa...@gmail.com
>>> > > > >
>>> > > > wrote:
>>> > > >
>>> > > > >
>>> > > > > On Sat, May 27, 2023 at 5:35 PM Xiang Xiao <
>>> > xiaoxiang781...@gmail.com>
>>> > > > > wrote:
>>> > > > >
>>> > > > >> On Sat, May 27, 2023 at 8:19 PM Fotis Panagiotopoulos <
>>> > > > >> f.j.pa...@gmail.com>
>>> > > > >> wrote:
>>> > > > >>
>>> > > > >> > Hello,
>>> > > > >> >
>>> > > > >> > I encounter some problems using sendfile().
>>> > > > >> >
>>> > > > >> > I am using sendfile to... send a file to a remote server,
>>> with my
>>> > > own
>>> > > > >> > implementation of an FTP client.
>>> > > > >> > sendfile() indeed starts to transmit chunks of the file, but
>>> as I
>>> > > see
>>> > > > in
>>> > > > >> > Wireshark, I get an ICMP response "Destination unreachable
>>> > > > >> (Fragmentation
>>> > > > >> > needed)".
>>> > > > >> > I have verified that the Ethrenet MTU is correctly set to
>>> 1500.
>>> > > > >> >
>>> > > > >> > I tried lowering the MTU a lot (1000 bytes), and the problem
>>> is
>>> > > > solved.
>>> > > > >> > Communication succeeds.
>>> > > > >> >
>>> > > > >> > This raises some questions, and indicates some potential bugs:
>>> > > > >> >
>>> > > > >> > 1. Why is there a problem with MTU in the first place?
>>> Shouldn't
>>> > MTU
>>> > > > be
>>> > > > >> > negotiated? (Is this functionality available in NuttX?)
>>> > > > >> >
>>> > > > >>
>>> > > > >> MTU isn't negotiated but a physical attribute of your
>>> > > transport(netdev).
>>> > > > >> On
>>> > > > >> the other hand, PMTU could be discovered from ICMP.
>>> > > > >>
>>> > > > >
>>> > > > > I am not very familiar with MTU negotiation, so it seems that it
>>> > > doesn't
>>> > > > > happen in the network layer that I thought...
>>> > > > >
>>> > > > >
>>> > > > >>
>>> > > > >>
>>> > > > >> > 2. Why is the ICMP response not handled? It seems that
>>> sendfile()
>>> > > just
>>> > > > >> > ignores it and continues to send chunks, nevertheless.
>>> > > > >> >
>>> > > > >>
>>> > > > >> It is handled by the recent addition here:
>>> > > > >> https://github.com/apachey/nuttx/pull/9254
>>> > > > >> <https://github.com/apache/nuttx/pull/9254>
>>> > > > >> but this feature is disabled by default, you have to enable it
>>> > > > manually..
>>> > > > >>
>>> > > > >
>>> > > > > I will definitely take a look at this. Thank you.
>>> > > > >
>>> > > > >
>>> > > > >>
>>> > > > >>
>>> > > > >
>>> > > > >> > 3. Why sendfile() sends TCP segments without receiving any
>>> ACKs
>>> > > back?
>>> > > > >> > AFAIK, depending on the configuration, TCP allows at most two
>>> > > pending
>>> > > > >> > segments on the wire. But I see dozens of them, till sendfile
>>> > > finally
>>> > > > >> > fails.
>>> > > > >> >
>>> > > > >> >
>>> > > > >> Why only two segments? TCP can send packages until the slide
>>> window
>>> > is
>>> > > > >> full.
>>> > > > >>
>>> > > > >> Disregard this. I was confused with delayed ACKs. Which is a
>>> > > receiver's
>>> > > > > functionality, not a sender's...
>>> > > > >
>>> > > > >
>>> > > > >>
>>> > > > >> > This last point is also verified in my MQTT client.
>>> > > > >> > I have seen NuttX TCP allowing sending lots of TCP segments
>>> > without
>>> > > > >> ACKing
>>> > > > >> > the previous data.
>>> > > > >> >
>>> > > > >> > So, is there any insight on the above?
>>> > > > >> > Is my configuration wrong, or is there anything wrong with
>>> TCP?
>>> > > > >> >
>>> > > > >> > Thank you.
>>> > > > >> >
>>> > > > >>
>>> > > > >
>>> > > >
>>> > >
>>> >
>>>
>>

Reply via email to