diff --git a/download.py b/download.py index 3efa6dd..4f14383 100755 --- a/download.py +++ b/download.py @@ -171,12 +171,8 @@ def list_ip(c_list: list = []): # добавляем IPv4 подсети for ip_int, mask in sorted(ipv4_list, key=lambda x: x[0]): Root.insert(net_tree.Net(ip_int, mask, 4)) - # считаем статистику - Root.finalize() - # сжатие по CIDR, если ключ сжимать - if compress: Root.collapse() - # получаем результат - ipv4_list = Root.export('route {addr}/{masklen} blackhole;') + # сжатие по CIDR, если ключ сжимать, иначе убираем только родителей, покрываемых детьми + ipv4_list = Root.export_compress('route {addr}/{masklen} blackhole;') if compress else Root.export('route {addr}/{masklen} blackhole;') else: ipv4_list:bool=False @@ -187,12 +183,8 @@ def list_ip(c_list: list = []): # добавляем IPv6 подсети for ip_int, mask in sorted(ipv6_list, key=lambda x: x[0]): Root.insert(net_tree.Net(ip_int, mask, 6)) - # считаем статистику - Root.finalize() - # сжатие по CIDR, если ключ сжимать - if compress: Root.collapse() - # получаем результат - ipv6_list = Root.export('route {addr}/{masklen} blackhole;') + # сжатие по CIDR, если ключ сжимать, иначе убираем только родителей, покрываемых детьми + ipv6_list = Root.export_compress('route {addr}/{masklen} blackhole;') if compress else Root.export('route {addr}/{masklen} blackhole;') else: ipv6_list:bool=False # возвращаем 2 списка маршрутов diff --git a/include/net_tree.py b/include/net_tree.py index bec3d14..246d7f7 100644 --- a/include/net_tree.py +++ b/include/net_tree.py @@ -238,13 +238,17 @@ class Node: self.__recalc() return delta, fake - def export(self, fmt='{addr}/{masklen}'): + def export_compress(self, fmt='{addr}/{masklen}'): + # считаем статистику + self.finalize() + # сжимаем + self.collapse() result = [] def walk(node): if node is None: return - # если суперсеть реальная – дети не нужны + # если суперсеть реальная –> дети не нужны if node.is_real: result.append(node.net.getAsString(fmt)) return @@ -253,3 +257,35 @@ class Node: walk(self) return "\n".join(result) + + + def export(self, fmt='{addr}/{masklen}'): + # считаем статистику + self.finalize() + result = [] + + def walk(node): + if node is None: + return + + if node.is_real: + # дети полностью покрывают диапазон родителя? + child_real_vol = 0 + for ch in (node.child0, node.child1): + if ch: + child_real_vol += ch.real_volume + + # если дети полностью покрывают родителя -> родители не нужны + if child_real_vol >= node.net.volume: + walk(node.child0) + walk(node.child1) + return + + # иначе выводим родителя и детей + result.append(node.net.getAsString(fmt)) + + walk(node.child0) + walk(node.child1) + + walk(self) + return "\n".join(result) \ No newline at end of file