BlakeFoster / Arduino-Ping

ICMP ping library for the Arduino
58 stars 44 forks source link

pinging multiple targets - socket problem #9

Open dmnc-net opened 8 years ago

dmnc-net commented 8 years ago

Hi folks, thanks to @BlakeFoster for this library, good work, also thanks to @psychogenic for the async feature. I'd like to use Arduino as a watchdog for multiple targets. When I'm using this library for just one target everything is ok but with more (i.e. 8) I'm loosing too many packets - when I'm pinging Arduino itself but also (and this is bad) I'm getting false timeouts while pinging targets. With async pinging it is little bit stable but still unusable as a watchdog.

I'm doing ping in a cycle, one target by one with a delay between them and some delay after a round, I'm trying to set more retries and various timeouts but still with packet loss. Btw. in the async mode and multiple targets, Arduino is no longer responding to the icmp. I've also tried multiple sockets but in this scenario I have to turn off the async mode (not working with it) and results are still bad. I'm using MegaADK with Eth. Shield and/or Ethernet board rev. 3, both with the same results.

I know that Arduino is very limited hw and tcp/ip stack is not robust but anyway, do you please have some advice for me or do you think that this application is not able to handle it? Maybe if I should empty some buffer after a while, it can work ... In other case I'll try to port this application to the linux side of the Arduino Yun or some RPi. Thank you.

dmnc-net commented 8 years ago

I found something which is leading to the problem. I'm running tcpdump on the testing target where are all IP addresses (problem occurs even with 2 IPs), in the production it will be multiple devices with one IP on each.

I've changed the code little bit more, when problem occurs - timeout/no response I'm retrying a single ping in a for loop and I found I can do it forever because every next request for this target is not incoming to the target's iface. I have no eth. switch with port mirroring at this moment so I just count on tcpdump on the target machine.

Quick and dirty fix: I have to do 1 ping to another target, even to myself (Arduino) and then return to that suspicious one, everything is ok. I've tried to close and re-open socket directly thru W5100 object but with no success - just pinging another target helps.

At this moment I'm diving to the icmp-ping and W5100 code and trying to understand how those things works but maybe it can be affected by my approach when I'm still using just one global instance ping of the ICMPPing class: ICMPPing ping(pingSocket, 1) and just changing the target.

dmnc-net commented 8 years ago

I've did some test trials and found my project unstable. I can't mark a point of failure if it is my code or this library but probably due to memory fragmentation it starts to generate false positive even I'm using my "dirty fix". With 6 targets the 1st failure comes after avg. 101600 seconds of uptime on my MegaADK. With 5 targets after 114000 seconds of uptime. This requires a lot of time for debugging and because this projects seems to be abandoned I highly recommend to NOT use this library for multiple targets.

BlakeFoster commented 8 years ago

That's a hardware limitation, not a problem with the library. The W5100 only supports 4 sockets. If you try to open more than that (e.g. when you test the ping library against 5 or more destinations), you're exceeding the capabilites of the hardware, hence the failures. If you don't use more than four targets at once you should be fine. Keep in mind that anything else using the Ethernet shield will also occupy a socket, so you may be limited to fewer than 4 sockets for ICMP.

dmnc-net commented 7 years ago

Hi @BlakeFoster, thanks for your reply. Good to know about this limitation. Unfortunately I'm using just one socket and changing the target. Something like this:

SOCKET pingSocket = 1;                 // http is on socket 0
ICMPPing ping(pingSocket, 1);
...
for (byte targetIndex = 0; targetIndex < targetCount; targetIndex++) {
  echoReply = ping(watchdogTargets[targetIndex], 1);  
VladkoK commented 6 years ago

Hello :) Im not new in Arduino, but im still learning and explore this wonderful world when i have time... im building a device that will, beside other things, ping multiple IP addresses inside my network. Well, actual problem is that i dont get response if address is NOT available :( For now im using serial monitor to test my code, but i have no luck with NO_RESPONSE condition... SUCCESS condition works no matter where i put it (inside IF or inside ELSE IF) but NO_RESPONSE wont print nothing in serial monitor. here is that part of code:

void pinger() { ICMPEchoReply echoReply = ping(pingAddr , 4); if (echoReply.status == NO_RESPONSE) { sprintf(buffer, "fail"); }

else if (echoReply.status == SUCCESS) { sprintf(buffer, "ok");
}

Serial.println(buffer); delay(500);

}

also it would be stupid if i made separate function for each address... i dont know how to ping multiple addresses and pull out result from there... thanks for any advice :)

dmnc-net commented 6 years ago

@VladkoK I don't think your comment is related to the socket issue. Anyway you should ping different addresses by changing your pingAddr variable. For more please create the separate issue.

Anyway in case you'll have same issue like me - false positive failure (probably lost reply, maybe a request) after some time when using a lot of multiple targets thru the one socket, please write a comment here.

Btw. I'm not using Ethernet shield anymore, instead I'm running my project on Arduino Yún.