NativeEthernet socket size bug

If you don't set the size, you get a default recv buffer size, which in my case isn't big enough. I don't want to send many small packets and worry about reassembling them when the actual transport will let me send a whole frame worth of data in a single packet (in my case 1620*3 bytes). If the recv buffer is not big enough, it silently fails to receive the large packets. If you follow the link above you can see my explanation of the error...
 
Where this might matter is the TCP MSS and window size, but it looks like you’re using UDP. Anything above 1472 bytes (for transports having a 1500-byte MTU) will be fragmented anyway, but at the IP layer. While there’s a settable limit, I believe QNEthernet should be able to handle IP reassembly of 1620*3 UDP payload bytes out of the box. I have to test this…
 
Last edited:
Yeah, I am not a low level transport expert, so my comment on the repo was just to set to MAX_MTU or whatever, but.. my experience with it was that if I did not set the size equal or greater to my big packet size, I got no large packets. As soon as I set it to my packet size (or larger) I got all of them. When I set to less than, I could still get my smaller packets (synch packets), but no pixel data packets, and performance went into the crapper, like 10x-100x slower. Just observations, and without better or deeper knowledge, I can't explain the behavior... Thanks for chiming in, and I def will check out QNEthernet :)
 
What are you using to send larger-than-the-MTU UDP packets (i.e. requiring fragmentation)? For example, a C++ program on a desktop? I just wrote a quickie Java app in Processing that attempts to send 1620*3-byte packets and I’m getting IOExceptions complaining the packets are too large. I checked my send buffer size and it’s set to 65507 bytes. I’ll explore this more; I’m trying to test my statement that my Ethernet library can properly reassemble fragmented UDP packets.

In any case, let me know if the library works for you, however you managed to send those large packets. I haven't figured it out yet. Perhaps I need to configure the OS somehow to allow this. Are you having to jump through some hoops just to send these larger-than-MTU UDP packets?

Update: In theory, the Mac can send 9216-byte UDP packets (see `sysctl -a |grep dgram`). Maybe I just have to write a non-Java program...
 
Last edited:
I figured it out. At least on my setup, you can send fragmented packets to a unicast address but not to a broadcast address. I tested with 1620*3-byte packets and the UDP reassembly appears to work fine. It correctly shows packets of size 4860 being received.

Instructions:
1. Run the Teensy code first to get its IP address.
2. Replace ADDR in the Processing code with that address.
3. Run the Processing code.

Here's the Processing code:
Code:
import java.io.IOException;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.InetAddress;

// Your Teensy address. Doesn't appear to work if a broadcast address.
static final String ADDR = "192.168.1.100";
static final int PORT = 5000;

DatagramSocket socket;
DatagramPacket packet;
InetAddress addr;
byte[] data = new byte[1620*3];

int packetCount = 0;

void setup() {
  // Initialize with some data
  for (int i = 0; i < data.length; i++) {
    data[i] = (byte) ((i % 10) + '0');
  }

  try {
    socket = new DatagramSocket();
    packet = new DatagramPacket(data, data.length,
                                InetAddress.getByName(ADDR), PORT);
    println("Starting...");
  } catch (IOException ex) {
    println(ex);
  }
}

void draw() {
  try {
    socket.send(packet);
    println("Sent " + (++packetCount));
  } catch (IOException ex) {
    println(ex);
  }

  delay(2000);  // Every 2 seconds
}

Here's the Teensy code:
Code:
#include <QNEthernet.h>

using namespace qindesign::network;

constexpr uint32_t kDHCPTimeout = 10000;
constexpr uint16_t kPort = 5000;

EthernetUDP udp;

// Program setup.
void setup() {
  Serial.begin(115200);
  while (!Serial && millis() < 4000) {
    // Wait for Serial to initialize
  }
  stdPrint = &Serial;  // Make printf work (a QNEthernet feature)
  printf("Starting...\n");

  uint8_t mac[6];
  Ethernet.macAddress(mac);
  printf("MAC = %02x:%02x:%02x:%02x:%02x:%02x\n",
         mac[0], mac[1], mac[2], mac[3], mac[4], mac[5]);

  printf("Starting Ethernet with DHCP...\n");
  if (!Ethernet.begin()) {
    printf("Failed to start Ethernet\n");
    return;
  }
  if (!Ethernet.waitForLocalIP(kDHCPTimeout)) {
    printf("Failed to get IP address from DHCP\n");
    return;
  }

  IPAddress ip = Ethernet.localIP();
  printf("    Local IP    = %u.%u.%u.%u\n", ip[0], ip[1], ip[2], ip[3]);
  ip = Ethernet.subnetMask();
  printf("    Subnet mask = %u.%u.%u.%u\n", ip[0], ip[1], ip[2], ip[3]);
  ip = Ethernet.gatewayIP();
  printf("    Gateway     = %u.%u.%u.%u\n", ip[0], ip[1], ip[2], ip[3]);
  ip = Ethernet.dnsServerIP();
  printf("    DNS         = %u.%u.%u.%u\n", ip[0], ip[1], ip[2], ip[3]);

  udp.begin(kPort);
  printf("Receiving UDP packets on port %u...\n", kPort);
}

// Main program loop.
void loop() {
  static int counter = 0;
  int size = udp.parsePacket();
  if (size > 0) {
    printf("%d: size=%d\n", (++counter), size);
  }
}
 
Last edited:
Hi Shawn,

I am using Go on a RasPi and yes, unicast. Static addresses for all parties. Cool that QNEthernet doesn't have the recv buffer size issue.. just works :) At this point, packet bandwidth is no longer an issue, it's down to SPI speed, MUXing and signal integrity. Y'know the easy stuff ;>
 
Back
Top