aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJordan Bracco <href@random.sh>2021-11-12 16:12:26 +0100
committerJordan Bracco <href@random.sh>2021-11-12 16:12:26 +0100
commitdf4d0399133a7ab3a40d5bde05c642875d1d4c14 (patch)
tree908c178514e08d6e8060ab69016d01d78113d01a
parentimprove rust.. (diff)
Rename to RoutingTable, improvements
-rw-r--r--README.md25
-rw-r--r--lib/routing_table.ex (renamed from lib/tree_bitmap.ex)60
-rw-r--r--lib/routing_table/tree_bitmap.ex (renamed from lib/tree_bitmap/nif.ex)4
-rw-r--r--mix.exs4
-rw-r--r--native/treebitmap_nif/src/lib.rs57
-rw-r--r--test/routing_table_test.exs40
-rw-r--r--test/tree_bitmap_test.exs134
7 files changed, 173 insertions, 151 deletions
diff --git a/README.md b/README.md
index c175b02..2a6df43 100644
--- a/README.md
+++ b/README.md
@@ -1,21 +1,14 @@
-# TreeBitmap
+# Routing Table
-**TODO: Add description**
+Efficient RIB for Elixir, implemented using a Rust NIF and [treebitmap](https://crates.io/crates/treebitmap).
-## Installation
-
-If [available in Hex](https://hex.pm/docs/publish), the package can be installed
-by adding `tree_bitmap` to your list of dependencies in `mix.exs`:
+The tables covers both IPv4 and IPv6, and values are any erlang term, stored in ets.
```elixir
-def deps do
- [
- {:tree_bitmap, "~> 0.1.0"}
- ]
-end
+table = RoutingTable.new()
+RoutingTable.add(table, {10, 69, 0, 0}, 16, :vpn)
+RoutingTable.add(table, {10, 69, 1, 0}, 24, :lan)
+:vpn = RoutingTable.longest_match(table, {10, 69, 2, 1})
+:lan = RoutingTable.longest_match(table, {10, 69, 1, 1})
+nil = RoutingTable.longest_match(table, {10, 68, 1, 1})
```
-
-Documentation can be generated with [ExDoc](https://github.com/elixir-lang/ex_doc)
-and published on [HexDocs](https://hexdocs.pm). Once published, the docs can
-be found at [https://hexdocs.pm/tree_bitmap](https://hexdocs.pm/tree_bitmap).
-
diff --git a/lib/tree_bitmap.ex b/lib/routing_table.ex
index 0da87fa..90b0160 100644
--- a/lib/tree_bitmap.ex
+++ b/lib/routing_table.ex
@@ -1,12 +1,25 @@
-defmodule TreeBitmap do
- alias TreeBitmap.NIF
+defmodule RoutingTable do
+ alias RoutingTable.TreeBitmap
defstruct [:i4, :i6, :ets]
@opaque t() :: %__MODULE__{}
@type masklen :: non_neg_integer()
+ @moduledoc """
+ Efficient routing table.
+
+ ```elixir
+ table = RoutingTable.new()
+ RoutingTable.add(table, {10, 69, 0, 0}, 16, :vpn)
+ RoutingTable.add(table, {10, 69, 1, 0}, 24, :lan)
+ :vpn = RoutingTable.longest_match(table, {10, 69, 2, 1})
+ :lan = RoutingTable.longest_match(table, {10, 69, 1, 1})
+ nil = RoutingTable.longest_match(table, {10, 68, 1, 1})
+ ```
+ """
+
def new(_opts \\ []) do
- %__MODULE__{i4: NIF.new(), i6: NIF.new(), ets: :ets.new(__MODULE__, [:public])}
+ %__MODULE__{i4: TreeBitmap.new(), i6: TreeBitmap.new(), ets: :ets.new(__MODULE__, [:public])}
end
@spec add(t(), :inet.ip_address(), masklen(), any()) :: nil | any()
@@ -78,40 +91,49 @@ defmodule TreeBitmap do
@type tree_memory() :: {nodes :: non_neg_integer(), results :: non_neg_integer()}
@spec memory(t()) :: %{inet4: tree_memory(), inet6: tree_memory(), ets: non_neg_integer()}
def memory(tree) do
- %{inet4: NIF.memory(tree.i4), inet6: NIF.memory(tree.i6), ets: :ets.info(tree.ets, :memory)}
+ %{inet4: TreeBitmap.memory(tree.i4), inet6: TreeBitmap.memory(tree.i6), ets: :ets.info(tree.ets, :memory)}
end
@spec length(t()) :: %{inet4: non_neg_integer(), inet6: non_neg_integer(), ets: non_neg_integer()}
def length(tree) do
- %{inet4: NIF.length(tree.i4), inet6: NIF.length(tree.i6), ets: :ets.info(tree.ets, :size)}
+ %{inet4: TreeBitmap.length(tree.i4), inet6: TreeBitmap.length(tree.i6), ets: :ets.info(tree.ets, :size)}
end
defp add(tree, tbm, ip, masklen, value) do
- id = :ets.update_counter(tree.ets, {__MODULE__, :counter}, 1, {{__MODULE__, :counter}, -1})
- :ets.insert(tree.ets, {id, value})
- {:ok, prev_id} = NIF.add(tbm, ip, masklen, id)
+ id = case :ets.match(tree.ets, {:'$1', :_, value}) do
+ [[id]] ->
+ :ets.update_counter(tree.ets, id, 1)
+ id
+ [] ->
+ id = :ets.update_counter(tree.ets, {__MODULE__, :counter}, 1, {{__MODULE__, :counter}, -1, 0})
+ :ets.insert(tree.ets, {id, 1, value})
+ id
+ end
+ {:ok, prev_id} = TreeBitmap.add(tbm, ip, masklen, id)
prev = if prev_id do
- [{^prev_id, value}] = :ets.lookup(tree.ets, prev_id)
- :ets.delete(tree.ets, prev_id)
+ [{^prev_id, _refc, value}] = :ets.lookup(tree.ets, prev_id)
+ refc = :ets.update_counter(tree.ets, id, -1)
+ if refc < 1, do: :ets.delete(tree.ets, prev_id)
value
end
prev
end
defp remove(tree, tbm, ip, masklen) do
- {:ok, id} = NIF.remove(tbm, ip, masklen)
+ {:ok, id} = TreeBitmap.remove(tbm, ip, masklen)
prev = if id do
- [{^id, value}] = :ets.lookup(tree.ets, id)
- :ets.delete(tree.ets, id)
+ [{^id, _refc, value}] = :ets.lookup(tree.ets, id)
+ refc = :ets.update_counter(tree.ets, id, -1)
+ if refc < 1, do: :ets.delete(tree.ets, id)
value
end
prev
end
defp longest_match(tree, tbm, ip) do
- case NIF.longest_match(tbm, ip) do
+ case TreeBitmap.longest_match(tbm, ip) do
{:ok, prefix, masklen, id} ->
- [{^id, value}] = :ets.lookup(tree.ets, id)
+ [{^id, _refc, value}] = :ets.lookup(tree.ets, id)
%{prefix: to_inet(prefix), len: masklen, value: value}
{:ok, nil} ->
nil
@@ -119,24 +141,24 @@ defmodule TreeBitmap do
end
defp longest_match?(_, tbm, ip) do
- case NIF.longest_match(tbm, ip) do
+ case TreeBitmap.longest_match(tbm, ip) do
{:ok, nil} -> false
{:ok, _, _, _} -> true
end
end
defp exact_match(tree, tbm, ip, masklen) do
- case NIF.exact_match(tbm, ip, masklen) do
+ case TreeBitmap.exact_match(tbm, ip, masklen) do
{:ok, nil} ->
nil
{:ok, id} ->
- [{^id, value}] = :ets.lookup(tree.ets, id)
+ [{^id, _refc, value}] = :ets.lookup(tree.ets, id)
value
end
end
defp exact_match?(_, tbm, ip, masklen) do
- case NIF.exact_match(tbm, ip, masklen) do
+ case TreeBitmap.exact_match(tbm, ip, masklen) do
{:ok, nil} -> false
{:ok, _} -> true
end
diff --git a/lib/tree_bitmap/nif.ex b/lib/routing_table/tree_bitmap.ex
index 7934f5a..1592bcb 100644
--- a/lib/tree_bitmap/nif.ex
+++ b/lib/routing_table/tree_bitmap.ex
@@ -1,5 +1,5 @@
-defmodule TreeBitmap.NIF do
- use Rustler, otp_app: :tree_bitmap, crate: "treebitmap_nif"
+defmodule RoutingTable.TreeBitmap do
+ use Rustler, otp_app: :routing_table, crate: "treebitmap_nif"
def new(), do: :erlang.nif_error(:nif_not_loaded)
def new_with_capacity(_), do: :erlang.nif_error(:nif_not_loaded)
diff --git a/mix.exs b/mix.exs
index a6b344d..33519c4 100644
--- a/mix.exs
+++ b/mix.exs
@@ -1,9 +1,9 @@
-defmodule TreeBitmap.MixProject do
+defmodule RoutingTable.MixProject do
use Mix.Project
def project do
[
- app: :tree_bitmap,
+ app: :routing_table,
version: "0.1.0",
elixir: "~> 1.12-rc",
start_permanent: Mix.env() == :prod,
diff --git a/native/treebitmap_nif/src/lib.rs b/native/treebitmap_nif/src/lib.rs
index 5d1821b..58859e7 100644
--- a/native/treebitmap_nif/src/lib.rs
+++ b/native/treebitmap_nif/src/lib.rs
@@ -17,34 +17,10 @@ mod atoms {
}
}
-trait Address {
+trait Maskable {
fn mask(self, masklen: u32) -> Self;
}
-#[derive(NifUntaggedEnum, Copy, Clone)]
-enum AddrTuple {
- V4(TupleV4),
- V6(TupleV6)
-}
-
-impl Address for AddrTuple {
- fn mask(self, masklen: u32) -> Self {
- match self {
- AddrTuple::V4(tuple_v4) => AddrTuple::V4(tuple_v4.mask(masklen)),
- AddrTuple::V6(tuple_v6) => AddrTuple::V6(tuple_v6.mask(masklen))
- }
- }
-}
-
-#[derive(Debug, NifRecord, Copy, Clone)]
-#[tag = "inet4"]
-struct TupleV4 {
- pub a: u8,
- pub b: u8,
- pub c: u8,
- pub d: u8
-}
-
struct NibblesV4 { pub n: [u8; 8]}
struct NibblesV6 { pub n: [u8; 32]}
@@ -71,6 +47,31 @@ impl AsRef<[u8]> for NibblesV6 {
}
}
+
+#[derive(NifUntaggedEnum, Copy, Clone)]
+enum AddrTuple {
+ V4(TupleV4),
+ V6(TupleV6)
+}
+
+impl Maskable for AddrTuple {
+ fn mask(self, masklen: u32) -> Self {
+ match self {
+ AddrTuple::V4(tuple_v4) => AddrTuple::V4(tuple_v4.mask(masklen)),
+ AddrTuple::V6(tuple_v6) => AddrTuple::V6(tuple_v6.mask(masklen))
+ }
+ }
+}
+
+#[derive(Debug, NifRecord, Copy, Clone)]
+#[tag = "inet4"]
+struct TupleV4 {
+ pub a: u8,
+ pub b: u8,
+ pub c: u8,
+ pub d: u8
+}
+
impl TupleV4 {
pub fn from(num: u32) -> Self {
TupleV4 {
@@ -86,7 +87,7 @@ impl TupleV4 {
}
}
-impl Address for TupleV4 {
+impl Maskable for TupleV4 {
fn mask(self, masklen: u32) -> Self {
debug_assert!(masklen <= 32);
let ip = u32::from(self);
@@ -186,7 +187,7 @@ impl TupleV6 {
}
-impl Address for TupleV6 {
+impl Maskable for TupleV6 {
fn mask(self, masklen: u32) -> Self {
debug_assert!(masklen <= 128);
@@ -312,7 +313,7 @@ fn memory<'a>(
make_tuple(env, &[nodes.encode(env), results.encode(env)])
}
-rustler::init!("Elixir.TreeBitmap.NIF",
+rustler::init!("Elixir.RoutingTable.TreeBitmap",
[new,
new_with_capacity,
length,
diff --git a/test/routing_table_test.exs b/test/routing_table_test.exs
new file mode 100644
index 0000000..730ed0d
--- /dev/null
+++ b/test/routing_table_test.exs
@@ -0,0 +1,40 @@
+defmodule RoutingTableTest do
+ use ExUnit.Case
+ doctest RoutingTable
+
+ test "RoutingTable" do
+ t = RoutingTable.new()
+ assert nil == RoutingTable.add(t, {192, 168, 1, 0}, 24, :lan)
+ assert nil == RoutingTable.add(t, {8193, 3512, 34211, 0, 0, 35374, 880, 1}, 64, :lan)
+
+ assert %{value: :lan} = RoutingTable.longest_match(t, {192, 168, 1, 2})
+ assert true = RoutingTable.longest_match?(t, {192, 168, 1, 2})
+ assert %{value: :lan} = RoutingTable.longest_match(t, {8193, 3512, 34211, 0, 0, 35374, 880, 29492})
+ assert true = RoutingTable.longest_match?(t, {8193, 3512, 34211, 0, 0, 35374, 880, 29492})
+
+ assert :lan = RoutingTable.exact_match(t, {192, 168, 1, 1}, 24)
+ assert true = RoutingTable.exact_match?(t, {192, 168, 1, 1}, 24)
+ assert :lan = RoutingTable.exact_match(t, {8193, 3512, 34211, 0, 0, 35374, 880, 29492}, 64)
+ assert true = RoutingTable.exact_match?(t, {8193, 3512, 34211, 0, 0, 35374, 880, 29492}, 64)
+
+ assert nil == RoutingTable.longest_match(t, {8, 8, 8, 8})
+ assert false == RoutingTable.longest_match?(t, {8, 8, 8, 8})
+ assert nil == RoutingTable.exact_match(t, {8, 8, 8, 8}, 32)
+ assert false == RoutingTable.exact_match?(t, {8, 8, 8, 8}, 32)
+
+ assert %{ets: 330, inet4: {1248, 1168}, inet6: {1344, 1168}} = RoutingTable.memory(t)
+
+ assert %{ets: 2, inet4: 1, inet6: 1} = RoutingTable.length(t)
+ assert :lan = RoutingTable.remove(t, {8193, 3512, 34211, 0, 0, 35374, 880, 1}, 64)
+ assert nil == RoutingTable.longest_match(t, {8193, 3512, 34211, 0, 0, 35374, 880, 29492})
+ assert %{ets: 2, inet4: 1, inet6: 0} = RoutingTable.length(t)
+ assert :lan == RoutingTable.remove(t, {192, 168, 1, 0}, 24)
+ assert %{ets: 1, inet4: 0, inet6: 0} = RoutingTable.length(t)
+
+ assert nil == RoutingTable.add(t, {8193, 3512, 34211, 0, 0, 35374, 880, 1}, 64, :lan)
+ assert :lan = RoutingTable.add(t, {8193, 3512, 34211, 0, 0, 35374, 880, 1}, 64, :lan2)
+ assert %{ets: 2, inet4: 0, inet6: 1} = RoutingTable.length(t)
+ end
+
+
+end
diff --git a/test/tree_bitmap_test.exs b/test/tree_bitmap_test.exs
index aedf78f..5c4f39e 100644
--- a/test/tree_bitmap_test.exs
+++ b/test/tree_bitmap_test.exs
@@ -1,126 +1,92 @@
defmodule TreeBitmapTest do
use ExUnit.Case
- doctest TreeBitmap
- alias TreeBitmap.NIF
- alias TreeBitmap
-
- test "TreeBitmap" do
- t = TreeBitmap.new()
- assert nil == TreeBitmap.add(t, {192, 168, 1, 0}, 24, :lan)
- assert nil == TreeBitmap.add(t, {8193, 3512, 34211, 0, 0, 35374, 880, 1}, 64, :lan)
-
- assert %{value: :lan} = TreeBitmap.longest_match(t, {192, 168, 1, 2})
- assert true = TreeBitmap.longest_match?(t, {192, 168, 1, 2})
- assert %{value: :lan} = TreeBitmap.longest_match(t, {8193, 3512, 34211, 0, 0, 35374, 880, 29492})
- assert true = TreeBitmap.longest_match?(t, {8193, 3512, 34211, 0, 0, 35374, 880, 29492})
-
- assert :lan = TreeBitmap.exact_match(t, {192, 168, 1, 1}, 24)
- assert true = TreeBitmap.exact_match?(t, {192, 168, 1, 1}, 24)
- assert :lan = TreeBitmap.exact_match(t, {8193, 3512, 34211, 0, 0, 35374, 880, 29492}, 64)
- assert true = TreeBitmap.exact_match?(t, {8193, 3512, 34211, 0, 0, 35374, 880, 29492}, 64)
-
- assert nil == TreeBitmap.longest_match(t, {8, 8, 8, 8})
- assert false == TreeBitmap.longest_match?(t, {8, 8, 8, 8})
- assert nil == TreeBitmap.exact_match(t, {8, 8, 8, 8}, 32)
- assert false == TreeBitmap.exact_match?(t, {8, 8, 8, 8}, 32)
-
- assert %{ets: 335, inet4: {1248, 1168}, inet6: {1344, 1168}} = TreeBitmap.memory(t)
-
- assert %{ets: 3, inet4: 1, inet6: 1} = TreeBitmap.length(t)
- assert :lan = TreeBitmap.remove(t, {8193, 3512, 34211, 0, 0, 35374, 880, 1}, 64)
- assert nil == TreeBitmap.longest_match(t, {8193, 3512, 34211, 0, 0, 35374, 880, 29492})
- assert %{ets: 2, inet4: 1, inet6: 0} = TreeBitmap.length(t)
-
- assert nil == TreeBitmap.add(t, {8193, 3512, 34211, 0, 0, 35374, 880, 1}, 64, :lan)
- assert :lan = TreeBitmap.add(t, {8193, 3512, 34211, 0, 0, 35374, 880, 1}, 64, :lan2)
- assert %{ets: 3, inet4: 1, inet6: 1} = TreeBitmap.length(t)
- end
+ alias RoutingTable.TreeBitmap
test "new/0" do
- table = NIF.new()
+ table = TreeBitmap.new()
assert is_reference(table)
end
test "memory/1" do
- table = NIF.new()
- assert {1200, 1152} == NIF.memory(table)
- {:ok, _} = NIF.add(table, {:inet4, 192, 168, 1, 0}, 24, 0)
- assert {1248, 1168} == NIF.memory(table)
+ table = TreeBitmap.new()
+ assert {1200, 1152} == TreeBitmap.memory(table)
+ {:ok, _} = TreeBitmap.add(table, {:inet4, 192, 168, 1, 0}, 24, 0)
+ assert {1248, 1168} == TreeBitmap.memory(table)
end
test "new_with_capacity/1" do
- table = NIF.new_with_capacity(1000)
+ table = TreeBitmap.new_with_capacity(1000)
assert is_reference(table)
- assert {109152, 37152} = NIF.memory(table)
+ assert {109152, 37152} = TreeBitmap.memory(table)
end
test "length/1" do
- table = NIF.new()
- assert 0 == NIF.length(table)
+ table = TreeBitmap.new()
+ assert 0 == TreeBitmap.length(table)
end
test "add/4 and longest_match/2" do
- table = NIF.new()
- assert {:ok, _} = NIF.add(table, {:inet4, 192, 168, 1, 0}, 24, 0)
- assert {:ok, _, 24, 0} = NIF.longest_match(table, {:inet4, 192, 168, 1, 1})
- assert {:ok, nil} = NIF.longest_match(table, {:inet4, 1, 1, 1, 1})
+ table = TreeBitmap.new()
+ assert {:ok, _} = TreeBitmap.add(table, {:inet4, 192, 168, 1, 0}, 24, 0)
+ assert {:ok, _, 24, 0} = TreeBitmap.longest_match(table, {:inet4, 192, 168, 1, 1})
+ assert {:ok, nil} = TreeBitmap.longest_match(table, {:inet4, 1, 1, 1, 1})
end
test "add/2 existing" do
- table = NIF.new()
- {:ok, nil} = NIF.add(table, {:inet4, 10, 69, 0, 0}, 16, 0)
- assert {:ok, 0} = NIF.add(table, {:inet4, 10, 69, 0, 0}, 16, 1)
- assert {:ok, _, _, 1} = NIF.longest_match(table, {:inet4, 10, 69, 1, 1})
+ table = TreeBitmap.new()
+ {:ok, nil} = TreeBitmap.add(table, {:inet4, 10, 69, 0, 0}, 16, 0)
+ assert {:ok, 0} = TreeBitmap.add(table, {:inet4, 10, 69, 0, 0}, 16, 1)
+ assert {:ok, _, _, 1} = TreeBitmap.longest_match(table, {:inet4, 10, 69, 1, 1})
end
test "remove/3" do
- table = NIF.new()
- {:ok, _} = NIF.add(table, {:inet4, 192, 168, 1, 0}, 24, 0)
- assert {:ok, 0} == NIF.remove(table, {:inet4, 192, 168, 1, 0}, 24)
- assert {:ok, nil} = NIF.longest_match(table, {:inet4, 192, 168, 1, 1})
+ table = TreeBitmap.new()
+ {:ok, _} = TreeBitmap.add(table, {:inet4, 192, 168, 1, 0}, 24, 0)
+ assert {:ok, 0} == TreeBitmap.remove(table, {:inet4, 192, 168, 1, 0}, 24)
+ assert {:ok, nil} = TreeBitmap.longest_match(table, {:inet4, 192, 168, 1, 1})
end
test "exact_match/3" do
- table = NIF.new()
- {:ok, _} = NIF.add(table, {:inet4, 192, 168, 1, 0}, 24, 0)
- assert {:ok, 0} = NIF.exact_match(table, {:inet4, 192, 168, 1, 0}, 24)
- assert {:ok, nil} = NIF.exact_match(table, {:inet4, 192, 168, 1, 1}, 32)
+ table = TreeBitmap.new()
+ {:ok, _} = TreeBitmap.add(table, {:inet4, 192, 168, 1, 0}, 24, 0)
+ assert {:ok, 0} = TreeBitmap.exact_match(table, {:inet4, 192, 168, 1, 0}, 24)
+ assert {:ok, nil} = TreeBitmap.exact_match(table, {:inet4, 192, 168, 1, 1}, 32)
end
test "default route" do
- table = NIF.new()
- assert {:ok, nil} == NIF.add(table, {:inet4, 0, 0, 0, 0}, 0, 0)
- assert {:ok, _, 0, 0} = NIF.longest_match(table, {:inet4, 192, 168, 1, 1})
+ table = TreeBitmap.new()
+ assert {:ok, nil} == TreeBitmap.add(table, {:inet4, 0, 0, 0, 0}, 0, 0)
+ assert {:ok, _, 0, 0} = TreeBitmap.longest_match(table, {:inet4, 192, 168, 1, 1})
end
test "more to less specific" do
- table = NIF.new()
- {:ok, _} = NIF.add(table, {:inet4, 10, 69, 1, 0}, 24, 2)
- {:ok, _} = NIF.add(table, {:inet4, 10, 69, 0, 0}, 16, 1)
- {:ok, _} = NIF.add(table, {:inet4, 0, 0, 0, 0}, 0, 0)
- assert {:ok, _, _, 0} = NIF.longest_match(table, {:inet4, 8, 8, 8, 8})
- assert {:ok, _, _, 2} = NIF.longest_match(table, {:inet4, 10, 69, 1, 2})
- assert {:ok, _, _, 1} = NIF.longest_match(table, {:inet4, 10, 69, 2, 2})
+ table = TreeBitmap.new()
+ {:ok, _} = TreeBitmap.add(table, {:inet4, 10, 69, 1, 0}, 24, 2)
+ {:ok, _} = TreeBitmap.add(table, {:inet4, 10, 69, 0, 0}, 16, 1)
+ {:ok, _} = TreeBitmap.add(table, {:inet4, 0, 0, 0, 0}, 0, 0)
+ assert {:ok, _, _, 0} = TreeBitmap.longest_match(table, {:inet4, 8, 8, 8, 8})
+ assert {:ok, _, _, 2} = TreeBitmap.longest_match(table, {:inet4, 10, 69, 1, 2})
+ assert {:ok, _, _, 1} = TreeBitmap.longest_match(table, {:inet4, 10, 69, 2, 2})
end
test "less to more specific" do
- table = NIF.new()
- {:ok, _} = NIF.add(table, {:inet4, 0, 0, 0, 0}, 0, 0)
- {:ok, _} = NIF.add(table, {:inet4, 10, 69, 0, 0}, 16, 1)
- {:ok, _} = NIF.add(table, {:inet4, 10, 69, 1, 0}, 24, 2)
- assert {:ok, _, _, 0} = NIF.longest_match(table, {:inet4, 8, 8, 8, 8})
- assert {:ok, _, _, 2} = NIF.longest_match(table, {:inet4, 10, 69, 1, 2})
- assert {:ok, _, _, 1} = NIF.longest_match(table, {:inet4, 10, 69, 2, 2})
+ table = TreeBitmap.new()
+ {:ok, _} = TreeBitmap.add(table, {:inet4, 0, 0, 0, 0}, 0, 0)
+ {:ok, _} = TreeBitmap.add(table, {:inet4, 10, 69, 0, 0}, 16, 1)
+ {:ok, _} = TreeBitmap.add(table, {:inet4, 10, 69, 1, 0}, 24, 2)
+ assert {:ok, _, _, 0} = TreeBitmap.longest_match(table, {:inet4, 8, 8, 8, 8})
+ assert {:ok, _, _, 2} = TreeBitmap.longest_match(table, {:inet4, 10, 69, 1, 2})
+ assert {:ok, _, _, 1} = TreeBitmap.longest_match(table, {:inet4, 10, 69, 2, 2})
end
test "multiple routes" do
- table = NIF.new()
- {:ok, _} = NIF.add(table, {:inet4, 8, 8, 8, 0}, 24, 8)
- {:ok, _} = NIF.add(table, {:inet4, 1, 1, 0, 0}, 16, 1)
- {:ok, _} = NIF.add(table, {:inet4, 192, 168, 1, 1}, 32, 200)
- assert {:ok, _, _, 8} = NIF.longest_match(table, {:inet4, 8, 8, 8, 8})
- assert {:ok, _, _, 1} = NIF.longest_match(table, {:inet4, 1, 1, 0, 0})
- assert {:ok, _, _, 200} = NIF.longest_match(table, {:inet4, 192, 168, 1, 1})
+ table = TreeBitmap.new()
+ {:ok, _} = TreeBitmap.add(table, {:inet4, 8, 8, 8, 0}, 24, 8)
+ {:ok, _} = TreeBitmap.add(table, {:inet4, 1, 1, 0, 0}, 16, 1)
+ {:ok, _} = TreeBitmap.add(table, {:inet4, 192, 168, 1, 1}, 32, 200)
+ assert {:ok, _, _, 8} = TreeBitmap.longest_match(table, {:inet4, 8, 8, 8, 8})
+ assert {:ok, _, _, 1} = TreeBitmap.longest_match(table, {:inet4, 1, 1, 0, 0})
+ assert {:ok, _, _, 200} = TreeBitmap.longest_match(table, {:inet4, 192, 168, 1, 1})
end
end