Pfx.minimize

You're seeing just the function minimize, go back to Pfx module for more information.

Specs

minimize([prefix()]) :: [prefix()]

Returns a minimized list of prefixes covering the same address space.

The list of, possibly mixed types of prefixes, is first grouped by their maxlen property, then each sublist is minimized by:

  • sorting such that, possibly, adjacent/overlapping prefixes are next to each other
  • recursively combine neighboring prefixes into their parent prefix

The prefixes can be any format understood by Pfx.new/1 or be straight up Pfx.t/0 structs, and the result mimics the format of the first prefix.

Notes:

  • to use the list as an acl, apply Enum.sort({:desc, Pfx}) afterwards
  • that uses Pfx.compare/2, so when using mixed prefix types, group_by maxlen first and sort the sub-lists

Examples

iex> acl = ["1.1.1.1", "1.1.1.2", "1.1.1.3", "1.1.1.4", "1.1.1.5", "1.1.1.6/31"]
iex> minimize(acl) |> Enum.sort({:desc, Pfx})
["1.1.1.4/30",  "1.1.1.2/31", "1.1.1.1"]

# list of 255 hosts (ip 1.1.1.128 is excluded)
iex> hosts = for ip <- hosts("1.1.1.0/24"), ip != "1.1.1.128", do: ip
iex> Enum.member?(hosts, "1.1.1.128")
false
iex> Enum.count(hosts)
255
iex> acl = minimize(hosts)
iex> Enum.sort(acl, {:desc, Pfx})
[
  "1.1.1.0/25",
  "1.1.1.192/26",
  "1.1.1.160/27",
  "1.1.1.144/28",
  "1.1.1.136/29",
  "1.1.1.132/30",
  "1.1.1.130/31",
  "1.1.1.129"
]
#
# reverse back to list of hosts
#
iex> acl_hosts = (for pfx <- acl, do: hosts(pfx)) |> List.flatten()
iex> Enum.count(acl_hosts)
255
iex> Enum.member?(acl_hosts, "1.1.1.128")
false

# minimize list of different types of prefixes
iex> list = ["1.1.0.0/24", "1.1.1.0/24", "acdc:0::/17", "acdc:8000::/17"]
iex> minimize(list)
["acdc::/16", "1.1.0.0/23"]

# mimics format of first prefix in the list
iex> minimize([{1, 2, 3, 4}, {{1, 2, 3, 0}, 25}, "1.2.3.128/26", "1.2.3.192/26"])
[{{1, 2, 3, 0}, 24}]

# mixed prefixes
iex> ["10.10.10.0/24", "10.10.11.0/24", "100.100.100.0/25", "100.100.100.128/25", "acdc::1"]
...> |> minimize()
["acdc::1", "100.100.100.0/24", "10.10.10.0/23"]

# minimize & sort mixed prefixes more to less specific (per type)
iex> ["10.10.10.0/24", "10.10.11.0/24", "100.100.100.0/25", "100.100.100.128/25", "acdc::1"]
...> |> minimize()
...> |> Enum.sort({:desc, Pfx})
["acdc::1", "10.10.10.0/23", "100.100.100.0/24"]

# to avoid excessive conversions due to mimicking, do:
iex> ["10.10.10.0/24", "10.10.11.0/24", "100.100.100.0/25", "100.100.100.128/25", "acdc::1"]
...> |> Enum.map(fn pfx -> new(pfx) end)
...> |> minimize()
...> |> Enum.sort({:desc, Pfx})
...> |> Enum.map(&format/1)
["acdc::1", "10.10.10.0/23", "100.100.100.0/24"]