Closed nunoguedelha closed 3 years ago
The smallest ping packet possible (including the Ethernet frame header and the IP + ICMP headers, plus the minimum 32 bytes of the ICMP payload) takes 74 bytes:
Picture from http://openmaniak.com/ping.php
and the typical size is of 56 bytes, so one ICMP packet per second has a negligible impact on the network.
We shall use the "ping" unix utility which allows to chose the time interval:
man ping
...
-i wait
Wait wait seconds between sending each packet. The default is to wait
for one second between each packet. The wait time may be fractional,
but only the super-user may specify values less than 0.1 second. This
option is incompatible with the -f option.
...
We shall explicitly set it to 1s, although it is the default, for a better portability.
Since the ping packets exchange have a specific frequency, much lower than the YARP port messages, we cannot use the same synchronous scheduler (`setInterval()) used on the YARP ports data.
The setInterval()
function for scheduling a caller is not a part of JavaScript specification. But most environments have the internal scheduler and provide these methods. In particular, they are supported in all browsers and Node.js (https://javascript.info/settimeout-setinterval).
Node.js executes its main event loop in a single thread. Asynchronous tasks can be executed in other internal threads or child processes. The child_process
module creates new child processes of our main Node.js process. We can execute shell commands through those child processes 1.
exec
FunctionThe exec()
function creates a new shell and executes a given command. The output from the execution is buffered, which means kept in memory, and is available for use in a callback.
spawn
FunctionThe spawn()
function executes a command in a new child process, and streams the returned data without storing it in a buffer, but using instead a Stream API. For commands returning data continuously like the command "ping", this is a simpler and saffer choice.
var ping = spawn('ping',['-i 1','192.168.1.18']); // "ping the Yarp server host" with 1s delay between ICMPs
This function uses a Stream API, so its output of the command is made available via listeners.
ping.stdout.on('data', function (data) {...});
ping.stderr.on('data', function (data) {...});
ping.on('error', function (error) {...});
ping.on('close', function (code) {...});
The stdout object fires a data event when the command writes to that stream. Similarly, the stderr also fires a data event when the command writes to that stream.
Errors are caught by listening for them directly on the object that stores the reference for the command. You will only get an error if child_process fails to run the command.
The close event occurs when the command has finished.
Implemented in commit 09c3ab3397c85779329ee9028b57d36efeefce59 1. https://stackabuse.com/executing-shell-commands-with-node-js/, https://nodejs.org/api/child_process.html
The final intent is to enable the ON/OFF toggling of the ping through a button on the web client control console. For security reasons, system commands cannot be run directly from a browser client page. Thus we create in the telemetry server an RPC interface for triggering those system commands, using the available YarpJS bindings.
In the Software Engineering DIC Vertical meeting, @traversaro suggested the solutions proposed in the following links for running a ping from Node.js:
I was actually using the child_process
Node.js packet as expplained in this comment, but rather the spawn
method rather thanexec
.
The node-net-ping
packet seems to be quite nice too, but doesn't seem simpler than using spawn
, at least so far. On top of that, apparently it doesn't generate periodic pings. Generating a sequence of pings would require using a periodic thread to trigger them.
I actually implemented the ping in a class such that in the future we can easily switch to using node-to-ping
instead of spawn('ping')
if necessary. It is something we could try, typically if we have portability issues with the command ping.
pingON <wait-time> <host-IP-address>
pingOFF
The wait time is the time between emitted ping packets, which default is 1 second. The host target will be typically the Yarp server. The commands are processed in the onRead
RPC callback. The incoming string is parsed into the command (cmdArray[0]
) and parameters (cmdArray[1..2]
), which are processed in the local function startStopPingOnSelectedServer()
.
startStopPingOnSelectedServer()
:
Implemented in commit https://github.com/ami-iit/yarp-openmct/pull/24/commits/2427e71f45b39b64301e62e92ee4fc00e7d45547.
icubtelemetry.generateTelemetry()
with the 'ping' returned round trip time data instead of sending the data to the console log.Realtime and history samples are ready to be sent to the OpenMCT visualizer at request.
Implemented in commit https://github.com/ami-iit/yarp-openmct/pull/24/commits/852ad0b772edf805dd174172afe3314d7bd21c0c.
The steps are listed below:
Further details are added directly to the commits.
Implemented in https://github.com/ami-iit/yarp-openmct/pull/26.
Implementation completed
Moved to "done", just for the board overview during the meeting of tomorrow.
@nunoguedelha commented on Tue Jul 06 2021
@nunoguedelha commented on Thu Aug 12 2021
Ciao @S-Dafarra , how do you usually evaluate the ping performance of the network when running the walking demo for the XPrize, just doing a
ping
on the yarp server host and averaging the scores or do you use some script?@S-Dafarra commented on Thu Aug 12 2021
In the dumbest possible way. We simply run
ping 10.0.0.2
. We are interested in visually keeping track of the connection status of theicub-head
when this is connected via Wi-Fi. Because of external events, the communication may start lagging for example. With theping
we simply keep track of it. We use no scripts@nunoguedelha commented on Thu Aug 12 2021
An averaged set of 10 pings every second could be way to monitor the performance in a graph, looks fine to you? It can also be parameterizable (1: lenght of the set/batch of pings for computing the average; 2: priod between batches), and with a default value.
@S-Dafarra commented on Fri Aug 13 2021
As you find more appropriate