Skip to content
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

sys/shell/commands/gnrc_icmpv6_echo: test for ICMPv6 reply corruption #15622

Merged
merged 2 commits into from Aug 11, 2021

Conversation

benpicco
Copy link
Contributor

Contribution description

The Linux ping utility has the nice feature that fills the ICMPv6 request payload with a pattern payload_index & 0xFF.
Then the ICMPv6 response payload is checked to verify that the pattern is still intact.

This way corrupted messages can be detected.
In the past that revealed some 6lo-fragmentation bugs in Linux when corrupted replies arrived.

This feature is also useful for RIOT, so implement it in RIOTs ping command.

Testing procedure

ping should still work with varying lengths.
If packet corruption happened on the data path, this should now be reported.

Issues/PRs references

@benpicco benpicco added Area: network Area: Networking Type: enhancement The issue suggests enhanceable parts / The PR enhances parts of the codebase / documentation labels Dec 13, 2020
@benpicco benpicco force-pushed the gnrc_icmpv6_echo-corruption branch 2 times, most recently from edd74fa to 2178ecc Compare December 13, 2020 16:30
@benpicco benpicco added the CI: ready for build If set, CI server will compile all applications for all available boards for the labeled PR label Dec 13, 2020
@maribu maribu added Reviewed: 2-code-design The code design of the PR was reviewed according to the maintainer guidelines Reviewed: 4-code-style The adherence to coding conventions by the PR were reviewed according to the maintainer guidelines Reviewed: 5-documentation The documentation details of the PR were reviewed according to the maintainer guidelines labels Dec 13, 2020
@miri64
Copy link
Member

miri64 commented Dec 14, 2020

Mh, is that feature optional on Linux? Because, as documented,

* This implementation oriented itself on the [version by Mike
* Muuss](http://ftp.arl.army.mil/~mike/ping.html) which was published under
* public domain. The state-handling and duplicate detection was inspired by the
* ping version of [inetutils](://www.gnu.org/software/inetutils/), which was
* published under GPLv3

the implementation is partly based on the Linux implementation.

@miri64
Copy link
Member

miri64 commented Dec 14, 2020

(So my actual question is: should we make this optional using a command-line flag?)

@miri64
Copy link
Member

miri64 commented Dec 14, 2020

At any rate this most likely will need an adaptation of the corresponding ShellInteraction

class GNRCICMPv6Echo(ShellInteraction):
@ShellInteraction.check_term
def ping6(self, hostname, count=3, interval=1000, packet_size=4,
hop_limit=None, timeout=1000, async_=False):
cmd = "ping6 {hostname} -c {count} -i {interval} " \
"-s {packet_size} -W {timeout}" \
.format(hostname=hostname, count=count, interval=interval,
packet_size=packet_size, timeout=timeout)
if hop_limit is not None:
cmd += " -h {hop_limit}".format(hop_limit=hop_limit)
# wait a second longer than all pings
cmd_timeout = ((timeout / 1000) * count) + 1
return self.cmd(cmd, timeout=cmd_timeout, async_=async_)

And its corresponding parser

res = {}
for line in cmd_output.splitlines():
if "stats" not in res: # If final stats were not found yet
m = self.c_reply.match(line)
if m is not None:
self._add_reply(res, m.groupdict())
continue
m = self.c_stats.match(line)
if m is not None:
self._set_stats(res, m.groupdict())
continue
else:
m = self.c_rtts.match(line)
if m is not None:
self._set_rtts(res, m.groupdict())
return res

To deal with the new behavior.

@benpicco
Copy link
Contributor Author

What would we gain by making this optional? The Linux ping utility will always do the corruption check.
For ShellInteraction, would I just add reply["corrupt"] = 1 in case the error line is printed?

@miri64
Copy link
Member

miri64 commented Jan 12, 2021

What would we gain by making this optional? The Linux ping utility will always do the corruption check.

You wouldn't need to adapt the riotctrl stuff and not break the tests ;-).

For ShellInteraction, would I just add reply["corrupt"] = 1 in case the error line is printed?

The ShellInteraction itself probably doesn't need any adoption, since as far as I can see you don't change the command parameters. The parser, however, needs adoption. Since you provide offset information and stuff like that, I would prefer, if that information would be provided in the reply dictionary as well. E.g.

reply["corrupt"] = {"bytes": bytes, "offset": offset}

@benpicco
Copy link
Contributor Author

benpicco commented Feb 2, 2021

I did a thing.
I don't know how to test this though, so it's untested.

(the reply can either be truncated or corrupted. A truncated reply is not checked for corruption as it's already damaged)

dist/pythonlibs/riotctrl_shell/gnrc.py Outdated Show resolved Hide resolved
@benpicco benpicco force-pushed the gnrc_icmpv6_echo-corruption branch 2 times, most recently from 66df92a to aaf8cba Compare February 2, 2021 19:34
@benpicco benpicco added this to Backlog / Proposals in RIOT Sprint Day via automation Feb 16, 2021
@benpicco benpicco removed this from Backlog / Proposals in RIOT Sprint Day Feb 16, 2021
@benpicco benpicco force-pushed the gnrc_icmpv6_echo-corruption branch 2 times, most recently from 158b4e1 to 464686b Compare February 16, 2021 10:21
dist/pythonlibs/riotctrl_shell/gnrc.py Outdated Show resolved Hide resolved
@MrKevinWeiss MrKevinWeiss added this to the Release 2021.07 milestone Jun 21, 2021
@MrKevinWeiss MrKevinWeiss removed this from the Release 2021.07 milestone Jul 15, 2021
@benpicco
Copy link
Contributor Author

How can I test riotctrl_shell/gnrc.py?

@miri64
Copy link
Member

miri64 commented Jul 27, 2021

Type tox when you are in the dist/pythonlibs/riotctrl_shell/ directory (you might need to install tox first).

@miri64
Copy link
Member

miri64 commented Jul 27, 2021

(see also the tools-test / python-tests Github Actions Workflow).

@benpicco benpicco removed the CI: ready for build If set, CI server will compile all applications for all available boards for the labeled PR label Aug 6, 2021
@github-actions github-actions bot added Area: sys Area: System Area: tests Area: tests and testing framework and removed Area: network Area: Networking labels Aug 6, 2021
@benpicco benpicco force-pushed the gnrc_icmpv6_echo-corruption branch from 278c6f9 to 8245b12 Compare August 6, 2021 20:49
@benpicco
Copy link
Contributor Author

benpicco commented Aug 6, 2021

Thank you for the hint with tox! Now I figured out what's going on here.
I re-wrote the error output to be in-line so there is only a single line of output / reply for easier parsing.

@miri64
Copy link
Member

miri64 commented Aug 7, 2021

Thank you for the hint with tox! Now I figured out what's going on here.
I re-wrote the error output to be in-line so there is only a single line of output / reply for easier parsing.

Now only the flake8 linter is complaining :-).

@benpicco
Copy link
Contributor Author

benpicco commented Aug 7, 2021

Heh, I thought we bumped the limit to 100 characters, but only for C code it seems.

@miri64
Copy link
Member

miri64 commented Aug 9, 2021

Heh, I thought we bumped the limit to 100 characters, but only for C code it seems.

For C code the coding conventions also still say 80 chars as soft target.

@miri64
Copy link
Member

miri64 commented Aug 9, 2021

(but we actually aim for PEP8 compliance in the pythonlibs (not in the test scripts though))

const uint8_t *data = buf;

if (len >= sizeof(uint32_t)) {
*triptime = xtimer_now_usec() - unaligned_get_u32(buf);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

now is now much later fetched. Can this be a problem? Ideally this should come directly after the receive and maybe provided as a parameter to _check_payload().

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I moved the time capture to the _handle_reply() call so we get the time right after msg_receive() returned.

@miri64
Copy link
Member

miri64 commented Aug 11, 2021

Using ping6 -c 100 -i 100 ... I get similar results for both

master
--- fe80::dc1a:a8ff:fe09:45b3 PING statistics ---
100 packets transmitted, 100 packets received, 0% packet loss
round-trip min/avg/max = 0.158/0.438/0.781 ms
This PR
--- fe80::dc1a:a8ff:fe09:45b3 PING statistics ---
100 packets transmitted, 100 packets received, 0% packet loss
round-trip min/avg/max = 0.135/0.449/1.470 ms

Tox for dist/pythonlibs/riotctrl_shell still passes. Did not bother to test the output for corrupted and truncated replies. Maybe something with scapy can be done there.

Copy link
Member

@miri64 miri64 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ACK

@miri64 miri64 added Reviewed: 1-fundamentals The fundamentals of the PR were reviewed according to the maintainer guidelines Reviewed: 3-testing The PR was tested according to the maintainer guidelines CI: ready for build If set, CI server will compile all applications for all available boards for the labeled PR labels Aug 11, 2021
The Linux ping utility has the nice feature that fills the ICMPv6 echo
request payload with a pattern `payload_index & 0xFF`.
Then the ICMPv6 echo response payload is checked to verify that the pattern
is still intact.

This way corrupted messages can be detected.
In the past that revealed some 6lo-fragmentation bugs in Linux when
corrupted replies arrived.

This feature is also useful for RIOT, so implement it in RIOTs `ping`
command.
@miri64
Copy link
Member

miri64 commented Aug 11, 2021

Just to be absolutely sure there is not a problem introduced with riotctrl_shell, I also started a release-test Github Action release-tests Github Action (edit: link changed to build correct commit) that uses that python library. If it succeeds (or fails with unrelated errors) we are good to go, I think.

@miri64
Copy link
Member

miri64 commented Aug 11, 2021

Just to be absolutely sure there is not a problem introduced with riotctrl_shell, I also started a release-test Github Action release-tests Github Action (edit: link changed to build correct commit) that uses that python library. If it succeeds (or fails with unrelated errors) we are good to go, I think.

Only the usual suspects (LoRaWAN and a test where the nodes are picked way to far apart) fail. So gooo!

@miri64 miri64 merged commit 67b4acd into RIOT-OS:master Aug 11, 2021
@benpicco benpicco deleted the gnrc_icmpv6_echo-corruption branch August 11, 2021 13:54
@benpicco benpicco added this to the Release 2021.10 milestone Oct 20, 2021
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Area: sys Area: System Area: tests Area: tests and testing framework CI: ready for build If set, CI server will compile all applications for all available boards for the labeled PR Reviewed: 1-fundamentals The fundamentals of the PR were reviewed according to the maintainer guidelines Reviewed: 2-code-design The code design of the PR was reviewed according to the maintainer guidelines Reviewed: 3-testing The PR was tested according to the maintainer guidelines Reviewed: 4-code-style The adherence to coding conventions by the PR were reviewed according to the maintainer guidelines Reviewed: 5-documentation The documentation details of the PR were reviewed according to the maintainer guidelines Type: enhancement The issue suggests enhanceable parts / The PR enhances parts of the codebase / documentation
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

4 participants