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

shell_commands: adapt ping6 to original-ping-like implementation #9523

Merged

Conversation

miri64
Copy link
Member

@miri64 miri64 commented Jul 9, 2018

Contribution description

Loosely based on the original ping and netutil's ping

New features (compared to old RIOT version):

  • Non-positional parameters
  • Configurable hop-limit
  • Better duplicate detection (addresses shell ping6 doesn't display duplicate packages #9387)
  • Better asynchronous behavior
  • Potential for future move to sock_ip
  • (Optional) DNS-support
  • Multithreading-safe (in case shell-command handler gets called
    from multiple threads)

Issues/PRs references

Resolves #9387.

@miri64 miri64 added Type: enhancement The issue suggests enhanceable parts / The PR enhances parts of the codebase / documentation Area: network Area: Networking GNRC labels Jul 9, 2018
@miri64 miri64 changed the title shell_commands: adapt ping6 to busybox-like implementation shell_commands: adapt ping6 to original-ping-like implementation Jul 9, 2018
@miri64 miri64 force-pushed the gnrc_icmpv6_echo/enh/new-shell-cmd branch from b887d79 to e36c0cd Compare July 9, 2018 15:11
@miri64
Copy link
Member Author

miri64 commented Jul 9, 2018

(I originally looked at the busybox-implementation [that's where the original title of this PR came from, because the commit had still the name ^^"], but since that is licensed under 4-clause BSD and thus incompatible to (L)GPL, I needed to dig deeper and was able to reconstruct my own version from the original ping's source [public domain; can be found on wayback machine] and inetutil's [licensed under GPLv3] and thus my version is now rather inspired by those works than the busybox one)

@miri64 miri64 force-pushed the gnrc_icmpv6_echo/enh/new-shell-cmd branch from e36c0cd to 2d73d12 Compare July 9, 2018 15:17
@miri64 miri64 requested review from jcarrano and bergzand July 9, 2018 18:25
@miri64 miri64 added the CI: ready for build If set, CI server will compile all applications for all available boards for the labeled PR label Jul 9, 2018
@miri64
Copy link
Member Author

miri64 commented Jul 9, 2018

For the record: this implementation is also more efficient than the old one. On a Cortex-M4 platform it uses ~200 byte less ROM and 56 byte less RAM than the previous implementation.

@miri64
Copy link
Member Author

miri64 commented Jul 9, 2018

(picked nucleo-f446ze to check that)

@miri64 miri64 force-pushed the gnrc_icmpv6_echo/enh/new-shell-cmd branch from a0218ec to 5dac3d3 Compare July 9, 2018 18:56
@jcarrano
Copy link
Contributor

I'm running it without arguments and it's spitting a stream of random bytes to the terminal.

@miri64
Copy link
Member Author

miri64 commented Jul 10, 2018

I'm running it without arguments and it's spitting a stream of random bytes to the terminal.

On which application and which board?

@miri64
Copy link
Member Author

miri64 commented Jul 10, 2018

With gnrc_networking on native I don't have that: sorry wrong branch....

> ping6
ping6
ping6 [<count>] <ipv6 addr>[%<interface>] [<payload_len>] [<delay in ms>] [<stats interval>]
defaults:
    count = 3
    interface = first interface if only one present, only needed for link-local addresses
    payload_len = 4
    delay = 1000
    stats interval = count

@miri64
Copy link
Member Author

miri64 commented Jul 10, 2018

mh curious, yesterday it was working...

@miri64
Copy link
Member Author

miri64 commented Jul 10, 2018

@jcarrano can you try again please?

@jcarrano
Copy link
Contributor

@miri64 Yes, it's fixed. I could run it. I can't test hoplimit because my test setup is quite simple. I'll start looking at the code.

@miri64
Copy link
Member Author

miri64 commented Jul 10, 2018

@miri64 Yes, it's fixed. I could run it. I can't test hoplimit because my test setup is quite simple. I'll start looking at the code.

https://www.iot-lab.info/ ;-)

Copy link
Contributor

@jcarrano jcarrano left a comment

Choose a reason for hiding this comment

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

I'm submitting a partial review of only the parsing code. The network part will take me more time as I'm not familiar with the apis.

sys/shell/commands/sc_gnrc_icmpv6_echo.c Show resolved Hide resolved
}
++argv;
/* parse command line arguments */
for (; argc > 0; argc--, argv++) {
Copy link
Contributor

Choose a reason for hiding this comment

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

I find this simultaneous decrementing and incrementing kind of fragile. Why not use an explicit index?

Copy link
Member Author

@miri64 miri64 Jul 10, 2018

Choose a reason for hiding this comment

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

For argc/argv I find this usually ok, but let me try with explicit index.

Copy link
Member Author

Choose a reason for hiding this comment

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

Ok, going for explicit index.

"of any responses, otherwise wait for two RTTs");
}

static int _configure(int argc, char **argv, _ping_data_t *data)
Copy link
Contributor

Choose a reason for hiding this comment

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

ping6 -c 3 without hostname fails. I have some quite lightweight code for parsing command line arguments that I wrote several years ago. If there's interest I can bring it back to life. I think there's no point in everyone hacking together their own parser.

Copy link
Member Author

Choose a reason for hiding this comment

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

Fixed.

Copy link
Member Author

Choose a reason for hiding this comment

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

I have some quite lightweight code for parsing command line arguments that I wrote several years ago. If there's interest I can bring it back to life. I think there's no point in everyone hacking together their own parser.

While I agree, but that opens a similar can of worms as the POSIX networking part, as some libc-variants already provide getopt and some don't. Since the shell is purely a debugging feature (and shell commands should also have as less dependencies as possible), I'd rather prefer every shell command to handle parsing for itself.

Copy link
Contributor

Choose a reason for hiding this comment

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

getopt posix-only, and does not support long options (getopt_long is a GNU extension).

I'd rather prefer every shell command to handle parsing for itself.

I would rephrase that as "I'd prefer every shell command to have it's own parsing bugs".

Copy link
Member Author

Choose a reason for hiding this comment

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

getopt posix-only, and does not support long options (getopt_long is a GNU extension).

At least my version of newlib supports it:

$ grep -R getopt /usr/arm-none-eabi/include/
/usr/arm-none-eabi/include/getopt.h:getopt.h - Read command line options
/usr/arm-none-eabi/include/getopt.h:The getopt() function parses the command line arguments.  Its arguments argc
/usr/arm-none-eabi/include/getopt.h:The getopt_long() function works like getopt() except that it also accepts
/usr/arm-none-eabi/include/getopt.h:The getopt() function returns the option character if the option was found
/usr/arm-none-eabi/include/getopt.h:The getopt_long() function's return value is described below.
/usr/arm-none-eabi/include/getopt.h:The function getopt_long_only() is identical to getopt_long(), except that a
/usr/arm-none-eabi/include/getopt.h:getopt() and friends to return EOF with optind != argc.
/usr/arm-none-eabi/include/getopt.h:This file and the accompanying getopt.c implementation file are hereby 
/usr/arm-none-eabi/include/getopt.h:    int *flag;			/* determines if getopt_long() returns a
/usr/arm-none-eabi/include/getopt.h:/* While getopt.h is a glibc extension, the following are newlib extensions.
/usr/arm-none-eabi/include/getopt.h: * They are optionally included via the __need_getopt_newlib flag.  */
/usr/arm-none-eabi/include/getopt.h:#ifdef __need_getopt_newlib
/usr/arm-none-eabi/include/getopt.h:     allocated variable of type struct getopt_data.  */
/usr/arm-none-eabi/include/getopt.h:  #define getopt_r		__getopt_r
/usr/arm-none-eabi/include/getopt.h:  #define getopt_long_r		__getopt_long_r
/usr/arm-none-eabi/include/getopt.h:  #define getopt_long_only_r	__getopt_long_only_r
/usr/arm-none-eabi/include/getopt.h:  /* The getopt_data structure is for reentrancy. Its members are similar to
/usr/arm-none-eabi/include/getopt.h:  typedef struct getopt_data
/usr/arm-none-eabi/include/getopt.h:  } getopt_data;
/usr/arm-none-eabi/include/getopt.h:#endif /* __need_getopt_newlib */
/usr/arm-none-eabi/include/getopt.h:  int _EXFUN (getopt,
/usr/arm-none-eabi/include/getopt.h:  int _EXFUN (getopt_long,
/usr/arm-none-eabi/include/getopt.h:  int _EXFUN (getopt_long_only,
/usr/arm-none-eabi/include/getopt.h:#ifdef __need_getopt_newlib
/usr/arm-none-eabi/include/getopt.h:  int _EXFUN (__getopt_r,
/usr/arm-none-eabi/include/getopt.h:	       struct getopt_data * __data));
/usr/arm-none-eabi/include/getopt.h:  int _EXFUN (__getopt_long_r,
/usr/arm-none-eabi/include/getopt.h:	       struct getopt_data * __data));
/usr/arm-none-eabi/include/getopt.h:  int _EXFUN (__getopt_long_only_r,
/usr/arm-none-eabi/include/getopt.h:	       struct getopt_data * __data));
/usr/arm-none-eabi/include/getopt.h:#endif /* __need_getopt_newlib */
/usr/arm-none-eabi/include/getopt.h:/* END OF FILE getopt.h */
/usr/arm-none-eabi/include/sys/unistd.h:# include <getopt.h>
/usr/arm-none-eabi/include/sys/unistd.h:extern char *optarg;			/* getopt(3) external variables */
/usr/arm-none-eabi/include/sys/unistd.h:int	 getopt(int, char * const [], const char *);
/usr/arm-none-eabi/include/sys/unistd.h:extern int optreset;			/* getopt(3) external variable */

Compare e.g. AVRlibc:

$ grep -R getopt /usr/lib/avr/include/

sys/shell/commands/sc_gnrc_icmpv6_echo.c Outdated Show resolved Hide resolved
sys/shell/commands/sc_gnrc_icmpv6_echo.c Show resolved Hide resolved
@jcarrano
Copy link
Contributor

@miri64

Your registration has been saved and submitted to validation by an administrator.

@miri64
Copy link
Member Author

miri64 commented Jul 10, 2018

@miri64

Your registration has been saved and submitted to validation by an administrator.

Maybe @aabadie can speed up that process?

@tcschmidt
Copy link
Member

@cgundogan maybe you can test this on IoTLab?

@cgundogan
Copy link
Member

@miri64

Your registration has been saved and submitted to validation by an administrator.

@jcarrano were you able to perform the tests in a multihop setup? If not, I'd help you out here.

@miri64
Copy link
Member Author

miri64 commented Aug 16, 2018

ping @jcarrano

@jcarrano
Copy link
Contributor

@miri64 I was not able to perform the test. I would have to learn how to use IOTLab and I'm lacking time ATM.

@miri64
Copy link
Member Author

miri64 commented Aug 16, 2018

@jcarrano you can also use two native nodes or two of the many IEEE 802.15.4 capable nodes on your desk ;-)

@jcarrano
Copy link
Contributor

@miri64 Sorry for leaving this PR hanging. I have since given up reviewing network-related stuff which, not being in my main area of expertise, takes me too much time while I have little to offer in terms of a valuable review.

My own reviews in this PR were mainly related to command line parsing, and they have been addressed, so I will dismiss myself if you don't mind.

@jcarrano jcarrano dismissed their stale review November 30, 2018 10:43

Comments were addressed.

@miri64
Copy link
Member Author

miri64 commented Nov 30, 2018

[…] so I will dismiss myself if you don't mind.

Sure. I understand.

@miri64 miri64 force-pushed the gnrc_icmpv6_echo/enh/new-shell-cmd branch from 5bbaa96 to 90a621b Compare December 29, 2018 17:25
@miri64
Copy link
Member Author

miri64 commented Dec 29, 2018

Rebased to current master. Also allowed for delay of 0 since I'm not sure why I disallowed that ;-).

@gschorcht
Copy link
Contributor

@miri64 I have tested the ping6 command. It is working as expected. What about option -I to define the interface as implemented on UNIX machines? It is doing the same as as the %- notation.

@miri64
Copy link
Member Author

miri64 commented Jan 5, 2019

@miri64 I have tested the ping6 command. It is working as expected. What about option -I to define the interface as implemented on UNIX machines? It is doing the same as as the %- notation.

The man page to iputils ping says:

-I interface address
    Set source address to specified interface address. Argument may be numeric IP
    address or name of device. When pinging IPv6 link-local address this option is
    required.

So I would say it's redundant in a pure IPv6 scenario.

@gschorcht
Copy link
Contributor

-I interface address
    Set source address to specified interface address. Argument may be numeric IP
    address or name of device. When pinging IPv6 link-local address this option is
    required.

So I would say it's redundant in a pure IPv6 scenario.

Yes, was just a question whether we should have it in addition to the %-notation of interface id.

@miri64
Copy link
Member Author

miri64 commented Jan 7, 2019

Yes, was just a question whether we should have it in addition to the %-notation of interface id.

I'd say no. One way to define the interface is enough IMHO (contrary to iputil's ping you can also use the % with a global address)

goto finish;
default:
/* requeue wrong packets */
msg_send(&msg, sched_active_pid);
Copy link
Member

Choose a reason for hiding this comment

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

What other messages can appear here? Shouldn't they be dropped instead of requeued? I can't see another msg_recv anywhere here that handles other types of messages, so the queue would get full with garbage ..

Copy link
Member Author

Choose a reason for hiding this comment

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

I can research that, but on first glance I would say: remember that this is the main thread. Other application specific messages might land in the queue.

Copy link
Member Author

Choose a reason for hiding this comment

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

(I did it because the current version in master does it as well:

default:
/* requeue wrong packets */
msg_send(&msg, thread_getpid());
break;
)

Copy link
Member

Choose a reason for hiding this comment

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

remember that this is the main thread. Other application specific messages might land in the queue.

yes, sounds sensible. Please research that anyway (:

Copy link
Member Author

Choose a reason for hiding this comment

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

Ok, I had in memory, that this line existed because someone asked for it, but apparently I introduced it myself in #2555. Anyway, given that this is main and that we didn't face any problems with this until now, I think the line is here correctly.

Copy link
Member

@cgundogan cgundogan left a comment

Choose a reason for hiding this comment

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

Tested on native and iotlab-m3 with unicast and multicast addresses. The output looks sensible. ACK.
We should also scan the code base and tutorials/wiki to adjust for the new syntax. e.g. here.

@cgundogan
Copy link
Member

squashing needed

@miri64
Copy link
Member Author

miri64 commented Feb 4, 2019

We should also scan the code base and tutorials/wiki to adjust for the new syntax. e.g. here.

We should this however do in a follow-up IMHO

@miri64
Copy link
Member Author

miri64 commented Feb 4, 2019

Squashed

@miri64 miri64 force-pushed the gnrc_icmpv6_echo/enh/new-shell-cmd branch from 90a621b to 1ec9591 Compare February 4, 2019 11:40
Loosely based on [the original ping] and [netutil]'s ping

New features (compared to old RIOT version):
 - non-positional parameters
 - Better duplicate detection (addresses RIOT-OS#9387)
 - Better asynchronous behavior
 - Potential for future move to `sock_ip`
 - (Optional) DNS-support
 - Multithreading-safe (in case shell-command handler gets called
   from multiple threads)

[the original ping]: http://ftp.arl.army.mil/~mike/ping.html
[netutil]: https://www.gnu.org/software/inetutils/
@miri64 miri64 force-pushed the gnrc_icmpv6_echo/enh/new-shell-cmd branch from 1ec9591 to 45ec766 Compare February 4, 2019 11:43
@miri64
Copy link
Member Author

miri64 commented Feb 4, 2019

And rebased.

@cgundogan
Copy link
Member

Alright. Murdock also agrees!

@cgundogan cgundogan merged commit e8f89b9 into RIOT-OS:master Feb 5, 2019
@miri64 miri64 deleted the gnrc_icmpv6_echo/enh/new-shell-cmd branch February 5, 2019 15:43
@miri64 miri64 added this to the Release 2019.04 milestone Feb 5, 2019
@miri64
Copy link
Member Author

miri64 commented Feb 5, 2019

Tested on native and iotlab-m3 with unicast and multicast addresses. The output looks sensible. ACK.
We should also scan the code base and tutorials/wiki to adjust for the new syntax. e.g. here.

@cgundogan the wiki page you referenced is already marked as outdated. Should we really fix it there? (all other occurrences I found, I fixed).

@miri64
Copy link
Member Author

miri64 commented Feb 5, 2019

(it even mentions fibroute)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Area: network Area: Networking CI: ready for build If set, CI server will compile all applications for all available boards for the labeled PR 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.

5 participants