Skip to content

UDP receive packet loss with version > 2.5.0 #6218

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
6 tasks done
maciejmatczak opened this issue Jun 22, 2019 · 6 comments · Fixed by #6222
Closed
6 tasks done

UDP receive packet loss with version > 2.5.0 #6218

maciejmatczak opened this issue Jun 22, 2019 · 6 comments · Fixed by #6222

Comments

@maciejmatczak
Copy link

Basic Infos

  • This issue complies with the issue POLICY doc.
  • I have read the documentation at readthedocs and the issue is not addressed there.
  • I have tested that the issue is present in current master branch (aka latest git).
  • I have searched the issue tracker for a similar issue.
  • If there is a stack dump, I have decoded it.
  • I have filled out all fields below.

Platform

  • Hardware: ESP8266
  • Core Version: 2.5.0, 2.5.1, 2.5.2 and 2.6.0-dev
  • Development Env: Arduino IDE
  • Operating System: Manjaro

Settings in IDE

  • Module: Wemos D1 mini
  • Flash Mode: default
  • Flash Size: 4MB
  • lwip Variant: v2 Lower Memory
  • Reset Method: ?
  • Flash Frequency: ?
  • CPU Frequency: 80Mhz
  • Upload Using: SERIAL
  • Upload Speed: 115200

Problem Description

While testing most basic UDP example I run across packet loss after an update of Arduino core. Don't get me wrong, I was eventually expecting some reliability issues with UDP communication, I am trying to send 4096 bytes. But after my tests, I got reliable packet loss with core version > 2.5.0. Using Board Manager I tested following versions and got this outputs in serial monitor (after using small python client, also provided in the issue):

2.5.0

Connecting to wifi. connected
Now listening at IP 192.168.0.150, UDP port 4210
Received 1472 bytes
Received 1480 bytes
Received 1144 bytes

Sums nicely to 4096.

2.5.1

Connecting to wifi......... connected
Now listening at IP 192.168.0.150, UDP port 4210
Received 1472 bytes
Received 1144 bytes

Middle one is missing.

2.5.2

Connecting to wifi. connected
Now listening at IP 192.168.0.150, UDP port 4210
Received 1472 bytes
Received 1144 bytes

The same.

2.6.0-dev (git master)

Connecting to wifi....... connected
Now listening at IP 192.168.0.150, UDP port 4210
Received 1472 bytes
Received 1144 bytes

Also the same. This results consist only first try, I ways resending the message multiple times, this 1480 bytes packet just reliably disappears.

I have everything set up for testing this issue, so if only you have some ideas to check, I would be happy to help.

MCVE Sketch

#include <ESP8266WiFi.h>
#include <WiFiUdp.h>


const char* ssid = "***";
const char* password = "***";

WiFiUDP Udp;
unsigned int localUdpPort = 4210;  // local port to listen on
char incomingPacket[255];  // buffer for incoming packets
char  replyPacket[] = "Hi there! Got the message :-)";  // a reply string to send back

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

  Serial.printf("Connecting to wifi", ssid);
  WiFi.begin(ssid, password);
  while (WiFi.status() != WL_CONNECTED)
  {
    delay(500);
    Serial.print(".");
  }
  Serial.println(" connected");

  Udp.begin(localUdpPort);
  Serial.printf("Now listening at IP %s, UDP port %d\n", WiFi.localIP().toString().c_str(), localUdpPort);
}

void loop() {
  int packetSize = Udp.parsePacket();
  if (packetSize)
  {
    Serial.printf("Received %d bytes\n", packetSize);
  }
}

And small python sender:

#!/usr/bin/env python3

import socket


UDP_IP, UDP_PORT = '192.168.0.150', 4210


if __name__ == '__main__':
    packet = ['0x00'] * 4096
    message = b''.join(bytes.fromhex(p[2:]) for p in packet)

    print(f'Sending {len(message)} bytes...')
    with socket.socket(socket.AF_INET, socket.SOCK_DGRAM) as s:
        s.sendto(message, (UDP_IP, UDP_PORT))
@TD-er
Copy link
Contributor

TD-er commented Jun 22, 2019

What happens if you're sending ping packets to the node while testing this?
Can you also monitor the power consumption when testing this? Is there a correlation between (lower) power consumption of the ESP node and missing packets?

@d-a-v
Copy link
Collaborator

d-a-v commented Jun 22, 2019

I taggued this as a bug, because your logs seem good with core<=2.5.0.
However, tcpdump on my openwrt router says this:

23:57:56.363028 IP (tos 0x0, ttl 64, id 26455, offset 0, flags [+], proto UDP (17), length 1500)
    10.0.1.7.52656 > 10.0.1.121.4210: UDP, bad length 4096 > 1472
23:57:56.363315 IP (tos 0x0, ttl 64, id 26455, offset 1480, flags [+], proto UDP (17), length 1500)
    10.0.1.7 > 10.0.1.121: ip-proto-17
23:57:56.363508 IP (tos 0x0, ttl 64, id 26455, offset 2960, flags [none], proto UDP (17), length 1164)
    10.0.1.7 > 10.0.1.121: ip-proto-17

tcpdump on my PC (running the python script) shows exactly the same logs.
Is it allowed by standards to send an UDP packet greater than MTU ? (1500 on ESP, including ethernet (20) and UDP (8) headers)
Your sketch only monitors packet sizes, but do you really get consistent data-content with core-2.4.2 or core-2.5.0 ?

UDP receive has been rewritten between 2.5.0 and 2.5.1 because of IPv6 now in the equation and the incompatible way to retrieve source (ip,port) for every packet. That would explain why the output is different. And it currently matches what tcpdump / the router sees.

edit:
It is allowed to send more than ~MTU bytes with TCP because TCP automatically slices content on the network and rebuild consistent data on receiver.

@d-a-v d-a-v added the waiting for feedback Waiting on additional info. If it's not received, the issue may be closed. label Jun 22, 2019
@maciejmatczak
Copy link
Author

Hi Guys,

@TD-er, pinging test is fine, I didn't see any issues while doing this simultaneously. I am afraid I do not have that exact measurement equipment to pickup the differences in power consumption.

@d-a-v About data consistency - I can't swear for every bit tbh, but as I am sending frames for 64x32 display, it looked fine, no any distortions. Let me add 2.4.2 to the equation:

  • any packet with size <= 1472 comes through
  • any packet with size > 1472 gives nothing, no any packet received, total silence...

I tried though sending specific data sizes packets:

Sent Received 2.5.0 Received 2.5.2
1472 1472 1472
1473 1472, 1 1472
2952 1472, 1480 1472
2953 1472, 1480, 1 1472, 1
4432 1472, 1480, 1480 1472, 1480
4433 1472, 1480, 1480, 1 1472, 1480
5913 1472, 1480, 1480, 1480, 1 1472, 1480, 1

So it's like every second split packet gets omit.

@TD-er
Copy link
Contributor

TD-er commented Jun 23, 2019

@TD-er, pinging test is fine, I didn't see any issues while doing this simultaneously.

So if you're running a ping at the same time, all (UDP) packets are received?

@maciejmatczak
Copy link
Author

@TD-er, one terminal running ping packets, second one python sending udp packets. Tried this few times, I didn't see any dropped packets, but I wouldn't call this one a proper stress test either.

Should I setup something more? Any ideas?

@d-a-v d-a-v removed the waiting for feedback Waiting on additional info. If it's not received, the issue may be closed. label Jun 23, 2019
d-a-v added a commit to d-a-v/Arduino that referenced this issue Jun 23, 2019
fix for esp8266#5960 didn't take fragmented packets into account
fixes esp8266#6218
@d-a-v
Copy link
Collaborator

d-a-v commented Jun 23, 2019

@maciejmatczak

Thanks for finding this bug. Fragmented UDP packets were indeed mismanaged.
#6222 will fix this.

d-a-v added a commit that referenced this issue Jun 26, 2019
fix for #5960 didn't take fragmented packets into account
fixes #6218
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging a pull request may close this issue.

3 participants