Search code examples
rubycidr

NetAddr::Tree take list of CIDR and merge them?


I’m using the Ruby NetAddr::Tree class to hold a bunch of CIDR objects, but I need a way to compress the CIDR objects into larger subnets.

I want a way to take IPs like:

12.26.8.0/21
12.26.16.0/21
12.26.24.0/21
12.26.32.0/21
12.26.40.0/21
12.27.152.0/21

and merge the relevant address ranges in the tree so the output would be like:

12.26.8.0/21
12.26.16.0/20
12.26.32.0/20
12.27.152.0/21

I looked through the documentation but can’t find any way to do this. I’m happy to move away from using NEtAddr::Tree if needed, all that’s important is it take a list of IP/netmask strings, merge them and output them line by line.


Solution

  • Have you taken a look at NetAddr::merge?

    From the docs:

    Given a list of CIDR addresses or NetAddr::CIDR objects, merge (summarize) them in the most efficient way possible. Summarization will only occur when the newly created supernets will not result in the ‘creation’ of new IP space. For example the following blocks (192.168.0.0/24, 192.168.1.0/24, and 192.168.2.0/24) would be summarized into 192.168.0.0/23 and 192.168.2.0/24 rather than into 192.168.0.0/22

    require 'netaddr'
    require 'pp'
    
    pp NetAddr.merge(
      %w[
        12.26.8.0/21
        12.26.16.0/21
        12.26.24.0/21
        12.26.32.0/21
        12.26.40.0/21
        12.27.152.0/21
      ].map{ |ip| NetAddr::CIDR.create(ip) }
    )
    
    => ["12.26.8.0/21", "12.26.16.0/20", "12.26.32.0/20", "12.27.152.0/21"]