STM32 + Lwip, MCU load due to broadcast packet - stm32

Due to the wrong network configuration,
It is assumed that broadcast packet looping has occurred.
STM32 MCU continuously receives broadcast packets.
As a result, the MCU load increases.
Tested on the STM32F746G-DISCOVERY board,
MCU load increased to 70 ~ 80%.
In this case, the polling period is broken and
Our products do not work properly.
Except for using the Serial to Ethernet Controller with TCP / IP Protocol stack,
Is there a way to avoid this problem?

If you detect flooding of broadcast packets, you could in theory temporary disable receiving broadcast packets in the MAC configuration (the ethernet hardware inside the STM32). STM32 MCU can filter packets by broadcast, multicast, receive-all, hash of either sender or received hardward adress.

Related

Ethernet network: Accteptance and discarding of messages based on their destniation addresses

In Ethernet networks, the MAC layer is the first layer to detect the destination address of the received message.
my questions: is that means that the transceiver shall take a copy of each message on the bus and forward it to the MAC layer who will decide to accept that message or discard it? If so, this means that the MAC layer must have a very large buffers to save all that intended and non intended message. am I correct ?
The MAC layer does not typically have much buffering. It may not even be able to store a full packet. Packets instead stream through the MAC.
Packets enter and exit the MAC one flit at a time. It may take hundreds of cycles for a full packet to pass into a MAC depending on the size of the packet and the width of the interface. For example, a MAC with an 8-byte interface (8-byte flit size) will take 1000 cycles to receive an 8kB packet.
The MAC may only have 800 bytes of buffering. In that case, the packet will start coming out the other end after 100 cycles when only 10% of the packet has entered. In fact, many MACs have a latency well below 100 cycles.
Packets which are rejected on the basis of destination address stream in one side but nothing comes out the other side. The frames are simply forgotten/dropped as they arrive.

UDP Packet loss simulation & probability

I am currently creating a server software that communicates with multiple arduino boards. Due to the hardware, I am using the UDP Protocol. I have a pretty simple mechanism that will resend packages in most of the cases when they get lost. I have two questions now:
How probable is it that UDP Packets get lost in a Network with no Internet access and about 20 arduinos and one computer? Is it even neccessary to have a resend method?
Is there a way I can simulate UDP Packet loss in this network to check if the resend mechanisms are working?
How probable is it that UDP Packets get lost in a Network with no
Internet access and about 20 arduinos and one computer?
The probability is 100% that sooner or later a packet will be dropped.
If you want a more detailed statistic, like the probability of a packet being dropped within any particular period of time, the only real way to know is to try it and found out (using e.g. sequence numbers in the packets so that the receiver(s) can detect when a packet has been dropped by noting the skipped sequence-number). The probability will depend very much on the size of the packets, the speed at which the packets are being sent, the CPU speed of the receivers, what other tasks the receivers are spending CPU time on, the quality of your Ethernet switch, the quality of your Ethernet cables, the phase of the moon, etc etc.
Is it even neccessary to have a resend method?
That depends on what the consequences would be to having a packet dropped. For some applications (e.g. streaming audio or video, or audio-metering data), dropping a packet is no big deal; you just ignore the fact that some data was lost, and continue on with the next packet as usual. For other applications (e.g. file transmit/receive), the loss of a packet means the loss of data that the receiver needs, so you'll want to have some way to recover from that loss, e.g. by detecting it and triggering a resend, or else the entire transfer will fail (or at least the receiver will end up with only a partial file).
Is there a way I can simulate UDP Packet loss in this network to check
if the resend mechanisms are working?
Sure, just put some logic into the receivers so that they occasionally pretend to not have received a packet:
int numBytesReceived = recv(...);
if ((rand()%100) == 0) // Simulate a 1% packet loss rate
{
printf("Pretending to have dropped a packet!\n");
}
else
{
// handle the incoming packet as usual
}

How to find the right sending speed with UDP?

I want to transfer a large number of messages. The messages do not need to be reliable. UDP comes to mind as a protocol choice.
Latency is important as well. I do not want to suffer from TCP head-of-line blocking.
I'm concerned I might overload the network when I just start sending messages at maximum speed (e.g. while (messagesRemaining != 0) Send(...);). If I send more than some middle-box can relay then, I think, large numbers of messages might be dropped. Some messages being dropped is fine but most of them should arrive.
How can I address this issue? How can I find out how fast I can send? I want to maintain reasonable packet loss (a few percent) and otherwise maximize bandwidth.
Whether you will overload the network or not depends on what is between the sender and the receiver hosts. The iperf utility has a UDP option that could help you determine the max rate you could send for a certain level of acceptable packet loss.
That said, from personal experience:
If it's local Gigabit network and client/server on same subnet, I highly doubt you would lose any packets. I've done tests before with iperf in this type of environment and never lost any packets; iperf is going to be one of the fastest and most efficient ways to put UDP packets on to the wire from a PC and we still never lost packets. We were even running the packets through an intel Atom-based Linux host with bridged ports setup while doing tcpdump at the same time and still never lost packets (note that even cheapo switches would perform as good or better than a bridge setup in a PC). The only way we were ever able to get packets to be lost was when we used FPGA/ASIC test devices that could put packets onto the wire at true line-speed for long periods of time. Even at that, the test setup was only losing packets when the packets were less than around 500 bytes.
If you aren't on a local network though (i.e. going over internet or routers) you will just need to do some testing with iperf to see what is acceptable for your environment. Problem is though that what rate can be sustained one day isn't guaranteed to be the same the next day. UDP doesn't have any sort of congestion/flow control algorithms like TCP does so you will have to figure out on your own how fast you can send.

how to receive large number of UDP packets continously in vc++

I am writing an GUI application which receives UDP packets from a FPGA board of 4Gb data continuously (application is a data retrieval system).
I created my own class inherited from CAyncSocket and on receive message I am reading packets through ReceiveFrom API and writing data to file.
As packets are sent continuously from FPGA (about 400k packets of 1KB data) my application is missing the packets. I am receiving only 200k packets. but when I am monitoring with Wireshark all packets are received.
Can anyone suggest any technique or algorithm to solve this problem, so that I can receive large number of UDP packets without loss.
The first thing to understand and accept is that you cannot guarantee that no UDP packets will be dropped. It is part of the nature of the UDP transport layer that any step in the transmission is allowed to drop a UDP packet for any reason, and that this is something that will happen from time to time. In your case, it sounds like the Windows networking stack is dropping the incoming UDP packets after receiving them from the network card, probably because the incoming-UDP-packets buffer associated with your socket is too full and does not have room to store them. This could happen for example if your write-to-disk calls occasionally take a number of milliseconds to return, during which time your app is unable to read more data from the UDP socket.
That said, there are a few things you can do to make the dropping of packets somewhat less likely.
The first (and easiest) thing to do is to increase the size of your socket's incoming-packets-buffer, using setsockopt(SO_RCVBUF). This helps because the larger the buffer is, the more time your program will have to read packets out of the buffer before the networking stack fills the buffer up entirely and starts dropping packets because it has no place to put them.
If that isn't sufficient for your purposes, the other thing you can do is spawn a separate thread that does nothing but receive incoming UDP packets and add them to a queue (for another thread to process later). Because this thread does nothing else besides receive UDP packets, it will be able to respond quickly when new packets have arrived, and thus the incoming-sockets-buffer will be less likely to ever fill up and overflow. You'll probably want to run this thread at a high priority if possible, so that there is less chance of it being held off of the CPU in the case where other threads or programs are competing for CPU time.
If you've implemented both of the above and the rate of packet loss still isn't acceptable, then you may have to step back and re-evaluate your approach. This might include switching from UDP protocol to TCP, or rewriting your code as an in-kernel driver, or switching to a real-time OS that can make better guarantees about response times.

What is the difference between "Interrupt coalescing" and the "Nagle algorithm"?

Is the main difference that?
Interrupt coalescing (ethtool -C eth1 rx-usecs 0) - coalesce the received packets from different connections, i.e. increase bandwitdh, but increase the latency of the receive
Nagle algorithm (socket options = TCP_NODELAY) - coalesce the sent packets from the same connection, i.e. increase bandwitdh, but increasethe the latency of the send
Interrupt coalescing concerns the network driver: the idea is to avoid invoking the interrupt handler anew every time a network packet shows up. Instead, after receiving a packet, the NIC waits until M packets are received or until N microseconds have passed before generating an interrupt. Then the driver can process many packets at once. (Otherwise, with modern gigabit and 10-gigabit adapters, the processor would need to field hundreds of thousands or millions of interrupts per second, which can prevent the system from being able to accomplish much else.) As your link points out, there is (or at least may be) a cost of additional latency since the OS doesn't start processing a received packet at the earliest possible instant.
Nagle's algorithm is focused on reducing the number of packets sent by coalescing payload data from multiple packets into one. The classic example is a telnet session. Without Nagle, every time you press a key, the system has to create an entire new packet (min 64 bytes on Ethernet) to send one byte.
So the intent of interrupt coalescing is to support greater bandwidth utilization, while the intent of Nagle's algorithm is actually to produce lower bandwidth (by sending fewer packets).