-
-
Notifications
You must be signed in to change notification settings - Fork 569
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Added improved Patricia tree with payload implementation
- Loading branch information
1 parent
74aee5e
commit 5b960f7
Showing
1 changed file
with
175 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,175 @@ | ||
#pragma once | ||
|
||
#include "fastnetmon_networks.hpp" | ||
#include "libpatricia/patricia.hpp" | ||
#include <iostream> | ||
|
||
// This is safe wrapper for Patricia with support for storing data directly in tree leafs without doing memory | ||
// allocations We can store only types which does not exceed void* by length | ||
template <typename T> class lookup_tree_128bit_with_payload_t { | ||
public: | ||
lookup_tree_128bit_with_payload_t() { | ||
patricia_tree = New_Patricia(128); | ||
} | ||
|
||
// Loads all the elements from passed tree to our tree | ||
// using inline storage method | ||
void load_inline(const lookup_tree_128bit_with_payload_t<T>& another_tree) { | ||
|
||
patricia_process(another_tree.patricia_tree, [this](prefix_t* prefix, void* data) { | ||
subnet_ipv6_cidr_mask_t subnet; | ||
|
||
memcpy(&subnet.subnet_address, &prefix->add.sin6, sizeof(subnet.subnet_address)); | ||
subnet.cidr_prefix_length = prefix->bitlen; | ||
|
||
// Add it to tree | ||
this->add_subnet_with_payload_inline(subnet, (T)data); | ||
}); | ||
} | ||
|
||
bool add_subnet_with_payload_inline(const subnet_ipv6_cidr_mask_t& ipv6_subnet, T object_to_store) { | ||
std::string subnet_as_string = convert_ipv6_subnet_to_string(ipv6_subnet); | ||
|
||
make_and_lookup_ipv6_with_data(patricia_tree, (char*)subnet_as_string.c_str(), (void*)object_to_store); | ||
return true; | ||
} | ||
|
||
// Try to find payload for certain subnet. But we return value directly | ||
bool lookup_value_inline_for_subnet(const subnet_ipv6_cidr_mask_t& ipv6_subnet, T& target_object_ptr) { | ||
prefix_t prefix_for_check_address; | ||
|
||
prefix_for_check_address.add.sin6 = ipv6_subnet.subnet_address; | ||
prefix_for_check_address.family = AF_INET6; | ||
prefix_for_check_address.bitlen = ipv6_subnet.cidr_prefix_length; | ||
|
||
patricia_node_t* found_patrica_node = patricia_search_best2(patricia_tree, &prefix_for_check_address, 1); | ||
|
||
// Could not find anything | ||
if (found_patrica_node == NULL) { | ||
return false; | ||
} | ||
|
||
// Return value itself | ||
target_object_ptr = (T)found_patrica_node->data; | ||
return true; | ||
} | ||
|
||
// Try to find payload for certain subnet. But we return value directly | ||
// It will return data only if we have exactly this subnet with exactly this prefix | ||
bool lookup_value_inline_for_subnet_exact_match(const subnet_ipv6_cidr_mask_t& ipv6_subnet, T& target_object_ptr) { | ||
prefix_t prefix_for_check_address; | ||
|
||
prefix_for_check_address.add.sin6 = ipv6_subnet.subnet_address; | ||
prefix_for_check_address.family = AF_INET6; | ||
prefix_for_check_address.bitlen = ipv6_subnet.cidr_prefix_length; | ||
|
||
patricia_node_t* found_patrica_node = patricia_search_exact(patricia_tree, &prefix_for_check_address); | ||
|
||
// Could not find anything | ||
if (found_patrica_node == NULL) { | ||
return false; | ||
} | ||
|
||
// Return value itself | ||
target_object_ptr = (T)found_patrica_node->data; | ||
return true; | ||
} | ||
|
||
~lookup_tree_128bit_with_payload_t() { | ||
if (patricia_tree) { | ||
Destroy_Patricia(patricia_tree); | ||
} | ||
} | ||
|
||
patricia_tree_t* patricia_tree = nullptr; | ||
}; | ||
|
||
// This is safe wrapper for Patricia with support for storing data directly in tree leafs without doing memory | ||
// allocations We can store only types which does not exceed void* by length | ||
template <typename T> class lookup_tree_32bit_with_payload_t { | ||
public: | ||
lookup_tree_32bit_with_payload_t() { | ||
patricia_tree = New_Patricia(32); | ||
} | ||
|
||
// Loads all the elements from passed tree to our tree | ||
// using inline storage method | ||
void load_inline(const lookup_tree_32bit_with_payload_t<T>& another_tree) { | ||
patricia_process(another_tree.patricia_tree, [this](prefix_t* prefix, void* data) { | ||
// Construct our network from low level structure in Patricia | ||
subnet_cidr_mask_t subnet; | ||
subnet.subnet_address = prefix->add.sin.s_addr; | ||
subnet.cidr_prefix_length = prefix->bitlen; | ||
|
||
// Add it to tree | ||
add_subnet_with_payload_inline(subnet, (T)data); | ||
}); | ||
} | ||
|
||
bool add_subnet_with_payload_inline(const subnet_cidr_mask_t& subnet, T object_to_store) { | ||
std::string subnet_as_string = convert_ipv4_subnet_to_string(subnet); | ||
|
||
make_and_lookup_with_data(patricia_tree, (char*)subnet_as_string.c_str(), (void*)object_to_store); | ||
return true; | ||
} | ||
|
||
// Try to find payload for certain subnet. But we return value directly | ||
bool lookup_value_inline_for_subnet(const subnet_cidr_mask_t& subnet, T& target_object_ptr) { | ||
prefix_t prefix_for_check_address; | ||
|
||
prefix_for_check_address.add.sin.s_addr = subnet.subnet_address; | ||
prefix_for_check_address.family = AF_INET; | ||
prefix_for_check_address.bitlen = subnet.cidr_prefix_length; | ||
|
||
patricia_node_t* found_patrica_node = patricia_search_best2(patricia_tree, &prefix_for_check_address, 1); | ||
|
||
// Could not find anything | ||
if (found_patrica_node == NULL) { | ||
return false; | ||
} | ||
|
||
// Return value itself | ||
target_object_ptr = (T)found_patrica_node->data; | ||
return true; | ||
} | ||
|
||
|
||
// Try to find payload for certain subnet. But we return value directly | ||
// It will return data only if we have exactly this subnet with exactly t | ||
bool lookup_value_inline_for_subnet_exact_match(const subnet_cidr_mask_t& subnet, T& target_object_ptr) { | ||
prefix_t prefix_for_check_address; | ||
|
||
prefix_for_check_address.add.sin.s_addr = subnet.subnet_address; | ||
prefix_for_check_address.family = AF_INET; | ||
prefix_for_check_address.bitlen = subnet.cidr_prefix_length; | ||
|
||
patricia_node_t* found_patrica_node = patricia_search_exact(patricia_tree, &prefix_for_check_address); | ||
|
||
// Could not find anything | ||
if (found_patrica_node == NULL) { | ||
return false; | ||
} | ||
|
||
// Return value itself | ||
target_object_ptr = (T)found_patrica_node->data; | ||
return true; | ||
} | ||
|
||
|
||
// Try to find payload for certain IP. But we return pointer to value instead of value | ||
bool lookup_value_inline_for_ip(uint32_t ip, T& target_object_ptr) { | ||
subnet_cidr_mask_t subnet(ip, 32); | ||
|
||
return lookup_value_inline_for_subnet(subnet, target_object_ptr); | ||
} | ||
|
||
~lookup_tree_32bit_with_payload_t() { | ||
if (patricia_tree) { | ||
Destroy_Patricia(patricia_tree); | ||
|
||
patricia_tree = nullptr; | ||
} | ||
} | ||
|
||
patricia_tree_t* patricia_tree = nullptr; | ||
}; |