Anonymous Monk has asked for the wisdom of the Perl Monks concerning the following question:

Hello all, I'm trying to calculate and print out all subnets of prefix length x from a subnet with a prefix length y \. For example: I want to split a /40, say 2001:0DB8::/40 into /56 subnets. I thought about using NetAddr::IP , for example:

use NetAddr::IP; my $sub6 = new NetAddr::IP '2001:db8::/40'; my $i=1; while ($sub6 < $sub6->broadcast) { # should've been <= but it does no +t seem to work if ($i==4722366482869645213696) { # that many addresses in a / +56 print "ip = $sub6\n"; $i=1; } $sub6 ++; $i++; } print "ip = $sub6\n"; # need to print last address

the above probably works but seems so inefficient and terribly slow. Any ideas would be greatly welcomed!

Replies are listed 'Best First'.
Re: efficient IPv6 subnetting
by BrowserUk (Patriarch) on Nov 25, 2015 at 15:46 UTC

    Incrementing an address 4.7 octillion times (4.7e21) in order to add 4.7e21 to it (and then repeat the exercise 256 times!) is a crazy way of doing things.

    NetAddr::IP does allow you to add an arbitrary number (not just 1); but how you deal with additions of numbers greater than the native integer is not explained.

    Overall, it just seems easier to use a package that knows how to deal with 128bit integers.

    Try this:

    #! perl -slw use strict; use Data::Dump qw[ pp ]; use Math::Int128 qw[ uint128 ]; sub IPv6toUint128 { my $n = uint128( 0 ); my $ip = shift; my @bits = split ':', $ip, 8; my $missing = 9 - @bits; @bits = map { length() ? hex( '0x' . $_ ) : ( (0) x $missing ) } @ +bits; $#bits = 7; $n = $n * 65536 + $_ for @bits; return $n } sub Uint128toIPv6 { my $mask = uint128( 0xffff ); my $n = shift; my @bits = map { my $bits = ( $n & $mask ) >> ( $_ * 16 ); $mask <<= 16; $bits; } 0 .. 7; @bits = map{ sprintf '%04x', $_ } reverse @bits; return join ':', @bits; } my $n = IPv6toUint128( '2001:db8::' ); # my $step = uint128( '4722366482869645213696' ); my $step = uint128( 1 ); $step <<= 72; # 128 - 56 print Uint128toIPv6( $n += $step ) for 1 .. 256; __END__ C:\test>1148545 2001:0db8:0000:0100:0000:0000:0000:0000 2001:0db8:0000:0200:0000:0000:0000:0000 2001:0db8:0000:0300:0000:0000:0000:0000 2001:0db8:0000:0400:0000:0000:0000:0000 2001:0db8:0000:0500:0000:0000:0000:0000 ... 2001:0db8:0000:fc00:0000:0000:0000:0000 2001:0db8:0000:fd00:0000:0000:0000:0000 2001:0db8:0000:fe00:0000:0000:0000:0000 2001:0db8:0000:ff00:0000:0000:0000:0000 2001:0db8:0001:0000:0000:0000:0000:0000

    My conversion routines could stand a bit of cleaning up; but they suffice for the purposes of this post.

    Of course, if you need the addresses in compact form (why would you; any software should also accept the long form), then you can input the strings produced above to NetAddr::IP and have it compact them for you.


    With the rise and rise of 'Social' network sites: 'Computers are making people easier to use everyday'
    Examine what is said, not who speaks -- Silence betokens consent -- Love the truth but pardon error.
    "Science is about questioning the status quo. Questioning authority". I knew I was on the right track :)
    In the absence of evidence, opinion is indistinguishable from prejudice.
Re: efficient IPv6 subnetting
by stevieb (Canon) on Nov 25, 2015 at 00:37 UTC

    I apologize. The code I wrote while with the ISP in the early days of IPv6 is protected by IP rights (before I forced an agreement that what code I wrote I could open-source), so I can't share it (it's much more efficient than what you're doing here, but it is still pretty clunky).

    I don't have the time to play around right now, so what I can recommend is sipcalc command line utility. eg:

    sipcalc -a 2001:db8::/40 -S /56

    You can dump the output of that to a file, then write Perl code to read and manipulate it afterwards.

      I have got -- only a few times in my time here, and that's because I spoke before I tested. Please speak up if you have a better suggestion. This isn't SO... I'd like to know what's bad about my post so I can improve what I do here.

Re: efficient IPv6 subnetting
by stevieb (Canon) on Nov 24, 2015 at 21:38 UTC
    If nobody can provide a response by the time I'm home tonight, I'll dig up some of my past code and see of it helps. I was the senior network engineer at an ISP for many years, and had to write code to carve up my /32 into efficient chunks that I could document and test with.