arduino-libraries / Ethernet

Ethernet Library for Arduino
http://arduino.cc/
259 stars 264 forks source link

udp multicast, receiving bytes stops after a while #132

Open lathoub opened 4 years ago

lathoub commented 4 years ago

Hi, I wrote a library for Arduino to send/receive ipMIDI (IDE 1.8.10). All works fine, but after a while, the Arduino stops receiving input (sending bytes continues to work).

The failure does not happen after a fixed number of reads or parsepackets, it varies between 10 and 1000 iterations in the example. Failure happens on both W5100 and W5500 shields and on both Arduino Ethernet (W5100) and MKR1000 with Ethernet shield (W5500). Failure does not happen on ESP32.

Below the (compacted) source code for an Arduino Ethernet (using 38% program storage space, 25% of dynamic memory). Packet Sender on a Mac (10.15.4) sends 3 bytes (MIDI note on) to multicast address 225.0.0.37, port 21928 (udp) every 500ms.

#include <EthernetUdp.h>
byte mac[] = { 0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xED };
byte packetBuffer[UDP_TX_PACKET_MAX_SIZE];  // buffer to hold incoming packet,

EthernetUDP Udp;
int loopCounter = 0;

void setup() {
  Serial.begin(115200);

  Ethernet.begin(mac);
  Udp.beginMulticast({ 225, 0, 0, 37 }, 21928);
}

void loop() {
  auto packetSize = Udp.parsePacket();
  if (packetSize > 0) {
    Serial.print("packetSize: ");
    Serial.println(packetSize);

    auto readLen = Udp.read(packetBuffer, sizeof(packetBuffer));
    for (auto i = 0; i < packetSize; i++) {
      Serial.print ("0x");
      Serial.print (packetBuffer[i], HEX);
      Serial.print (" ");
    }
    Serial.println(loopCounter++);
  }

  Ethernet.maintain();
}
lathoub commented 4 years ago

sample output:

...
11:22:22.527 -> 0x90 0x4C 0x40 589
11:22:22.948 -> packetSize: 3
11:22:22.948 -> 0x90 0x4C 0x40 590
11:22:23.398 -> packetSize: 3
11:22:23.398 -> 0x90 0x4C 0x40 591
11:22:23.830 -> packetSize: 3
11:22:23.830 -> 0x90 0x4C 0x40 592
11:22:24.283 -> packetSize: 3
11:22:24.283 -> 0x90 0x4C 0x40 593
11:22:24.704 -> packetSize: 3
11:22:24.704 -> 0x90 0x4C 0x40 594

in this case, receiving stops after 594 packets - that number varies

Rotzbua commented 4 years ago

@lathoub Did you checked for a memory leak?

lathoub commented 4 years ago

@Rotzbua no memory is dynamically allocated in the above example. Only static memory is used in packetBuffer. (I don't know what happens in the Ethernet library)

Rotzbua commented 4 years ago

@lathoub My suggestion is a memory leak in the library, because it stops after "some packets". I suggest to print the free ram of the arduino in every loop, if it becomes less there is a memory leak otherwise there is a other problem. https://github.com/mpflaga/Arduino-MemoryFree

Maybe check your hardware (clone?) for faulty design. Those clones cost me a lot of time in the past #117 .

lathoub commented 4 years ago

@Rotzbua thanks - I installed the suggested MemoryFree library and printed the freeMemory(). No memory leak, stable at 2292 bytes (all using genuine Arduino hardware)

17:40:52.886 -> packetSize: 3
17:40:52.886 -> 0x90 0x4C 0x40 248 2292
17:40:53.876 -> packetSize: 3
17:40:53.876 -> 0x90 0x4C 0x40 249 2292
17:40:54.834 -> packetSize: 3
17:40:54.834 -> 0x90 0x4C 0x40 250 2292
17:40:55.811 -> packetSize: 3
17:40:55.811 -> 0x90 0x4C 0x40 251 2292
17:40:56.772 -> packetSize: 3
17:40:56.772 -> 0x90 0x4C 0x40 252 2292
Rotzbua commented 4 years ago

The last thing is a code part which depends on ram of the target. Printing MAX_SOCK_NUM should give you 8 on the mkr1000 and 4 on Uno.

https://github.com/arduino-libraries/Ethernet/blob/6e9dffa64f6b0eb89607dbb5293dc33be82cc39e/src/Ethernet.h#L32-L40

lathoub commented 4 years ago

W5100 (Arduino Ethernet) reports 4, W5500 shield (on MKRZERO) reports 8.