def search_exact(self, _prefix, head=None): if self.head is None: return None prefix = RadixPrefix(_prefix) if head is None: head = self.head node = head addr = prefix.addr bitlen = prefix.bitlen while node.bitlen < bitlen: if self._addr_test(addr, node.bitlen): node = node.right else: node = node.left if node is None: return None if node.bitlen > bitlen: return None if self._prefix_match(node.prefix, prefix, bitlen): return node return None
def search_best(self, _prefix, head=None): if self.head is None: return None prefix = RadixPrefix(_prefix) if head is None: head = self.head node = head addr = prefix.addr bitlen = prefix.bitlen stack = [] while node.bitlen < bitlen: stack.append(node) if self._addr_test(addr, node.bitlen): node = node.right else: node = node.left if node is None: break if node is not None: stack.append(node) if len(stack) <= 0: return None for node in stack[::-1]: if (self._prefix_match(node.prefix, prefix, node.bitlen)) and node.bitlen <= bitlen: return node return None
def set_attr(self, attr): self.prefix = RadixPrefix(attr["prefix"]) self.bitlen = self.prefix.bitlen self.probed = attr["probed"] self.respond = attr["respond"] self.aggregated = attr["aggregated"] self.free = False
def _common_prefix(self, node1, node2): ''' Generate common prefix of node1 and node2. Args: node1 (RadixNode) node2 (RadixNode) Returns: RadixPrefix: common prefix of node1 and node2 ''' addr1 = node1.prefix.addr addr2 = node2.prefix.addr common_addr = bytearray(16) prefixmask = [0x00, 0x80, 0xc0, 0xe0, 0xf0, 0xf8, 0xfc, 0xfe] # differ_bit: addr1とaddr2の一致するビット長 differ_bit = 0 i = 0 while i * 8 < 128: r = addr1[i] ^ addr2[i] if r == 0: differ_bit = (i + 1) * 8 common_addr[i] = addr1[i] i += 1 continue for j in range(8): if r & (0x80 >> j): common_addr[i] = addr1[i] & prefixmask[j & 7] break differ_bit = i * 8 + j break return RadixPrefix(packed=common_addr, masklen=differ_bit)
def __init__(self, prefix="::/0", maxnode=64, repair_path=None): super(AggradixTree, self).__init__() if repair_path is None: head = AggradixNode(node_id=0) head.set(RadixPrefix(prefix)) self.head = head self.maxnode = maxnode - 1 self.free_nodes = self.maxnode self.packet_count = 0 self.nodes = pylru.lrucache(self.maxnode) self.active_leaf_cache = self.nodes.head.prev self._lru_init() else: self._repair(repair_path)
def add_count(self, src_addr, dst_addr, respond=False): if self.free_nodes < 2: self.aggregate() dst_prefix = RadixPrefix(f'{dst_addr}/128') node = self.add(dst_prefix) self.nodes[node.node_id] = node # プローブを受けた回数を加算 init_or_add(node.probed, src_addr, 1) # 応答を返した回数を加算 if respond: if dst_addr not in node.respond.keys(): node.respond[dst_addr] = {} if src_addr not in node.respond[dst_addr].keys(): node.respond[dst_addr][src_addr] = 0 node.respond[dst_addr][src_addr] += 1
def search_covered(self, _prefix, head=None): if self.head is None: return None prefix = RadixPrefix(_prefix) if head is None: head = self.head # headのプレフィクス長が検索するプレフィクスのプレフィクス長より長い場合 # 同じか短くなるまで木を上に探索 while prefix.bitlen > head.prefix.bitlen: if head.parent is None: break head = head.parent results = [] node = head addr = prefix.addr bitlen = prefix.bitlen while node.bitlen < bitlen: if self._addr_test(addr, node.bitlen): node = node.right else: node = node.left if node is None: return results stack = [node] while stack: node = stack.pop() if self._prefix_match(node.prefix, prefix, prefix.bitlen): results.append(node) if node.right: stack.append(node.right) if node.left: stack.append(node.left) return results
def search_worst(self, _prefix): return super().search_worst(RadixPrefix(_prefix))