Author image Karl Gaissmaier
and 1 contributors


Net::IPAM::Tree - A CIDR/Block tree library for fast IP lookup with longest-prefix-match.


A module for fast IP-routing-table lookups and IP-ACLs (Access Control Lists).

It is NOT a standard patricia-trie implementation. This isn't possible for general blocks not represented by bitmasks. Every tree item is a Net::IPAM::Block or a subclass of it.


  use Net::IPAM::Tree;

  my ($t, $dups) = Net::IPAM::Tree->new(@blocks);
  if (@$dups) {
    warn("items are duplicate: " . join("\n", @$dups));

  my $block = $t->lookup($ip_or_block)
    && printf( "longest-prefix-match in tree for %s is %s\n", $ip_or_block, $block );

  my $superset = $t->superset($ip_or_block)
    && printf( "superset in tree for ip or block %s is %s\n", $ip_or_block, $superset );

  say $t->to_string;

  ├─ ::/8
  ├─ 100::/8
  ├─ 2000::/3
  │  ├─ 2000::/4
  │  └─ 3000::/4
  ├─ 4000::/3



Create Net::IPAM::Tree object.

  my ($t, $dups) = Net::IPAM::Tree->new(@blocks);

In scalar context just returns the tree object, duplicate items produce a warning.

In list context returns the tree object and the arrayref of duplicate items, if any.


Returns the outermost block if the given $thing (Net::IPAM::IP or Net::IPAM::Block) is contained in the tree or undef.


Returns Net::IPAM::Block with longest prefix match for $thing (Net::IPAM::IP or Net::IPAM::Block) in the tree, undef if not found.

This can be used for ACL or fast routing table lookups.

  # make blocks
  my @priv = map { Net::IPAM::Block->new($_) } qw( fc00::/7);

  # make tree
  my $priv = Net::IPAM::Tree->new(@priv);

  my $b = Net::IPAM::Block->new('fdcd:aa59:8bce::/48') or die;

  my $lpm = $priv->lookup($b)
    && say "longest-prefix-match for $b is $lpm";


Returns the tree as ordered graph or undef on empty trees.


The optional callback is called on every block. Returns the decorated string for block.

  $t->to_string( sub { my $block = shift; return decorate($block) } );

example (without callback):

  ├─ ::/8
  ├─ 100::/8
  ├─ 2000::/3
  │  ├─ 2000::/4
  │  └─ 3000::/4
  ├─ 6000::/3

possible example (with callback):

  ├─ ::/8.................   "Reserved by IETF     [RFC3513][RFC4291]"
  ├─ 100::/8..............   "Reserved by IETF     [RFC3513][RFC4291]"
  ├─ 2000::/3.............   "Global Unicast       [RFC3513][RFC4291]"
  │  ├─ 2000::/4.............  "Test"
  │  └─ 3000::/4.............  "FREE"
  ├─ 6000::/3.............   "Reserved by IETF     [RFC3513][RFC4291]"


Walks the ordered tree, see to_string().

  my $err_string = $t->walk($walk_func);

For every item the walk_func function is called with the following hash-ref:

    my $err = $walk_func->(
        depth  => $i,           # starts at 0
        item   => $item,        # current block
        parent => $parent,      # parent block, undef for root items
        childs => [@childs],    # child blocks, empty for leaf items

The current depth is counting from 0.

On error, the walk is stopped and the error is returned to the caller. The walk_func MUST return undef if there is no error!


Returns the number of blocks in the tree.


Karl Gaissmaier, <karl.gaissmaier(at)>


You can find documentation for this module with the perldoc command.

    perldoc Net::IPAM::Tree

You can also look for information at:

  • on github



Net::IPAM::IP Net::IPAM::Block


This software is copyright (c) 2020-2022 by Karl Gaissmaier.

This is free software; you can redistribute it and/or modify it under the same terms as the Perl 5 programming language system itself.