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

Please allow -g at least for smaller IPv6 ranges #59

Open
xtaran opened this issue Mar 19, 2014 · 10 comments
Open

Please allow -g at least for smaller IPv6 ranges #59

xtaran opened this issue Mar 19, 2014 · 10 comments

Comments

@xtaran
Copy link
Contributor

xtaran commented Mar 19, 2014

fping6 -g surely does not make sense in SLAAC environments or with other larger ranges at the size of /64.

But for DHCPv6 managed IPv6 ranges (like the /115 and /118 ranges we use at ETH) there is likely some use.

I have no idea where to make the cut for refusing or at least warning the user about pinging a too big range.

@poige
Copy link

poige commented Aug 8, 2017

I have no idea where to make the cut for refusing or at least warning the user about pinging a too big range.

Well, if to refer to fping's error message it's clearly seen that even /1 was okay for IPv4:

netmask must be between 1 and 30 (is: 124)

;-)

@auerswal
Copy link
Collaborator

I have started looking into this, and found a bit of an inconsistency regarding limiting the number of hosts to ping:

  • fping -g 127.0.0.1 127.1.255.254 results in the error message fping: -g parameter generates too many addresses and an exit with status code 1;
  • the equivalent fping -g 127.0.0.0/15 results in generating all 131,070 addresses and pinging all of them (takes a good 20 minutes on my laptop);
  • the equivalent net2ips 127.0.0.0/15 | fping results in reading all 131,070 addresses and pinging all of them, too (net2ips is a script of mine that prints the individual ip addresses of the given CIDR range).

This happens because only the add_range() function checks if the requested range is bigger than MAX_GENERATE (currently defined to be 100,000), but neither add_cidr() nor the file reading loop in lines 1075-1082 of src/fping.c do.

Before implementing IPv6 support for -g I would like to combine the common code of add_cidr() and add_range() so that I would only need to add IPv6 support to one code path. But that would apply the same MAX_GENERATE limit for both variants (CIDR or range), or would remove the MAX_GENERATE limit.

IPv6 support for the -g, --generate option would most likely require a limit to avoid out-of-memory problems for systems with memory over-commit (e.g., Linux). Even generating all IPv6 addresses for a SLAAC enabled subnet would be on the order of 2^64 addresses of 16B each and thus require more memory than addressable on 64-bit systems, and thus would need to be prevented.

On the positive side, this moves the generator problem into the realm of uint64_t arithmetic.

The limit for the number of targets should be similar for IPv4 and IPv6. I do not think it is necessary to account for the different address sizes, and then there is the constant overhead for per host statistics, at least with options like -Q.

The examples of /115 and /118 given in this feature request correspond to 8,192 (2^13) and 1,024 (2^10) addresses, and a /112 (65,536 addresses) would still be below 100,000.

Thus I would like to add the MAX_GENERATE to all generator variants, including the new IPv6 ones. Would that be OK?

To impose a general limit on the number of targets, including reading targets from a file, the limiter would probably need to be added to add_addr(). I'd say that is a different topic than extending generator support to IPv6.

@xtaran
Copy link
Contributor Author

xtaran commented Mar 25, 2022

Thanks for looking into this!

net2ips is a script of mine that prints the individual ip addresses of the given CIDR range.

JFYI: You might want to have a look at prips (for "print IPs") which seems to do exactly the same. It is also available packaged in at least the Debian universe (including Ubuntu).

@auerswal
Copy link
Collaborator

JFYI: You might want to have a look at prips (for "print IPs") which seems to do exactly the same. It is also available packaged in at least the Debian universe (including Ubuntu).

Thanks for adding this information. For people trying to reproduce the above, prips would be a good alternative to my script.

A difference between fping -g 192.0.2.0/30 respectively net2ips 192.0.2.0/30 | fping and prips 192.0.2.0/30 | fping is that the latter does not exclude the network and broadcast addresses. This may or may not be wanted, depending on use case. The CIDR range may not even correspond to an actual IP network configured on a link, so there may be no network and broadcast addresses.

I do not plan to handle the first and last address of an IPv6 CIDR range differently from the rest, because the lowest address is the so called Subnet-Router anycast address, and there is no broadcast address in IPv6, so there is no reason to exclude them even for networks using the provided CIDR range for a link (e.g., /126 point-to-point links, sometimes used for $reasons).

(I already knew of prips, but I found it only after I had written my net2ips script (on a SPARC Solaris system that I did not administrate, without a C compiler). Since it works for me I have kept it around and still use it. Thus I used it for the test above and needed to provide a short description.)

@auerswal
Copy link
Collaborator

auerswal commented Apr 2, 2022

To document what I have found out so far:

Some C compilers support a 128-bit integer type for some platforms, e.g., a not too old GCC supports it for 64-bit platforms, see, e.g., the GCC online documentation. It seems this can be tested for via the __SIZEOF_INT128__ definition, see, e.g., Is there a 128 bit integer in gcc?.

In tests with GCC 7.5 on x86_64 I could use unsigned __int128 and __uint128_t.

Thus it may be possible to implement an IPv6 generator similarly to the IPv4 generator by using __uint128_t, if supported, and fail with an error message if this is not available.

A different way would be to use two unsigned 64 bit integers (uint64_t) and handle overflow manually (e.g., for the two addresses in the inclusive range from 2001:db8::ffff:ffff:ffff:ffff to 2001:db8:0:1::). I would expect that to be slower than compiler support for 128-bit integers. I do not expect this to be too slow, even when written in straight-forward C. I would expect this to be sufficiently portable, because fping already uses int64_t.

The portable uint64_t based version could be implemented first, and then optimized by replacing it with a __uint128_t based version, if supported by the C compiler. This optimization could be guarded by #ifdef __SIZEOF_INT128__.

@hmh
Copy link
Contributor

hmh commented Apr 5, 2022

__uint128_t is non-standard and has ABI issues between gcc and clang, so whatever you do, don't use it in a dynamic object (lib, etc).

@auerswal
Copy link
Collaborator

auerswal commented Apr 5, 2022

If I should use unsigned __int128 guarded by #ifdef __SIZEOF_INT128__, that would be inside fping.c, so not for a library. I could make all functions exposing it as parameter or return type static, just in case anyone wants to use fping as a dynamic library anyway.

I have a first implementation of IPv6 support for -g, --generate using uint64_t locally. I want to add more tests and clean it up a bit, then possibly abstract the currently open-coded 128-bit arithmetic to prepare for an optional unsigned __int128 version, and then look into unsigned __int128 use.

After all that I want to split everything into a few nice commits and create a pull request. That will take some time.

@auerswal
Copy link
Collaborator

auerswal commented May 1, 2022

I have just created pull request #254 for open-coded IPv6 generator support.

@auerswal
Copy link
Collaborator

auerswal commented Jun 8, 2023

I have close pull request #254 since there has not been any feedback. It seems as if there is no real interest in this work, despite the help wanted tag on this issue.

I would suggest everyone looking for some IPv6 generator like functionality to use an external program and pipe the output from that into fping. Possible IPv6 generators are my Python scripts net2ips.py (supports only CIDR notation) and ipenum.py (supports CIDR notation flexible range specifications). Both are released as free software under GPL version 3 or later.

@xtaran
Copy link
Contributor Author

xtaran commented Jun 20, 2023

I have close pull request #254 since there has not been any feedback.

That's not nice! No feedback for a year does not necessarily mean no interest but can e.g. also mean just not enough time besides maintenance.

BTW, I just ran into this again today:

fping: -g works only with IPv4 addresses

Workaround:

perl -E 'foreach my $i (0 .. $end) { printf("$prefix::%x\n", $i); }' | xargs fping -a -q

(Replace $end and $prefix with according values.)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

5 participants