Commit 25fd0fac authored by Alberts S's avatar Alberts S
Browse files

ControllerStatic use hops for best route slection

parent 7f31fb63
......@@ -3,7 +3,7 @@ import collections
import ipaddress
import logging
from datetime import datetime, timedelta
from typing import Type
from typing import List, Type
import networkx as nx
......@@ -12,26 +12,41 @@ from Router import Route, Router
class Improvement(CapybaraNetty):
def __init__(self, target, path, is_current_viable_path, is_current_best_path, optimized_ms=None):
__node_name = None
__optimized_ms = None
def __init__(self, target, node_name, path, is_current_viable_path, is_current_best_path, optimized_ms=None):
super().__init__()
optimization_history_count = self.config["controller_static_improvement_optimization_story_count"]
optimization_history_count = self.config["controller_static_improvement_optimization_history_count"]
self.target = target
self.path = path
self.discovery_time = datetime.now()
self.node_name = node_name
self.__optimized_ms = optimized_ms
self.__optimized_ms_history = collections.deque(maxlen=optimization_history_count)
self.optimized_ms = optimized_ms
self.__is_current_best_path = None
self.__last_best_time = None
self.__total_best_seconds = 0
self.__is_current_viable_path = None
self.__routes = set()
self.__stable_time = self.config["controller_static_improvement_stable_time"]
self.is_current_best_path = is_current_best_path
self.is_current_viable_path = is_current_viable_path
@property
def node_name(self):
return self.__node_name
@node_name.setter
def node_name(self, val: str):
self.__node_name = val
@property
def optimized_ms(self):
return self.__optimized_ms
......@@ -80,9 +95,21 @@ class Improvement(CapybaraNetty):
def total_best_seconds(self):
return self.__total_best_seconds
@property
def is_stable(self):
return self.total_best_seconds > self.__stable_time
@property
def is_install_candidate(self):
return self.is_current_viable_path and self.is_current_best_path
return self.is_current_viable_path and self.is_current_best_path and self.is_stable
@property
def improvement_hop(self):
self_idx = self.path.index(self.node_name)
try:
return self.path[self_idx], self.path[self_idx + 1]
except IndexError:
return None
# https://codereview.stackexchange.com/a/215329
def is_subsequence_of(self, other: "Improvement") -> bool:
......@@ -93,7 +120,7 @@ class Improvement(CapybaraNetty):
return any(haystack[i : i + len(needle)] == needle for i in range(len(haystack) - len(needle) + 1))
def __str__(self):
return f"{self.target:<16s} candidate={self.is_install_candidate:<1} viable={self.is_current_viable_path:<1}, best={self.is_current_best_path:<1} for {self.total_best_seconds:<3} seconds, {self.optimized_ms:<3}ms [{'->'.join(self.path)}] "
return f"{self.target:<16s} candidate={self.is_install_candidate:<1} viable={self.is_current_viable_path:<1}, best={self.is_current_best_path:<1} for {self.total_best_seconds:<3} seconds (stable={self.is_stable:<1}), {self.optimized_ms:<3}ms [{'->'.join(self.path)}] "
class ControllerStatic(CapybaraNetty):
......@@ -137,6 +164,7 @@ class ControllerStatic(CapybaraNetty):
is_current_best_path = True
improvement_candidate = Improvement(
node_name=node_name,
target=target,
path=path,
optimized_ms=optimized_ms,
......@@ -153,9 +181,7 @@ class ControllerStatic(CapybaraNetty):
improved_path.is_current_viable_path = is_current_viable_path
improved_path.is_current_best_path = is_current_best_path
elif improved_path.is_subsequence_of(improvement_candidate) or improvement_candidate.is_subsequence_of(
improved_path
):
elif improved_path.improvement_hop == improvement_candidate.improvement_hop:
# self.__logger.debug(
# f"{node_name:<24} subset/superset found for improvement {str(improved_path)}")
# A special case where same node has
......@@ -170,14 +196,15 @@ class ControllerStatic(CapybaraNetty):
pass
else:
# self.__logger.debug(f"{node_name:<24} SET best=0 for improvement {str(improved_path)}")
self.__logger.debug(f"{node_name:<24} SET best=0 for improvement {str(improved_path)}")
improved_path.is_current_best_path = False
if not path_is_already_known:
node_improved_path_info.append(improvement_candidate)
def is_improvement_viable_route(self, improvement: Improvement):
def is_improvement_viable_route(self, improvements: List[Improvement]):
# TODO check whether improvement is viable (e.g is stable for x... seconds)
# Or do we check it as part of Improvement obj?
pass
def find_viable_paths(self, G):
......@@ -189,7 +216,7 @@ class ControllerStatic(CapybaraNetty):
# We need G routers + single target, filter out all other targets
# otherwise the graph finds shortest path with including external targets
G_subgraph = nx.subgraph_view(G, filter_node=filter_node)
# TODO add cutoff
# TODO nonimportant - add cutoff
lengths, paths = nx.single_source_dijkstra(G_subgraph, source=target, weight="weight")
# TODO remove reversed since it was used for testing
for key, path in reversed(paths.items()):
......@@ -270,6 +297,7 @@ class ControllerStatic(CapybaraNetty):
).ip
path_obj.routes.add(
Route(
# TODO nonimportant - flexible route size
prefix=f"{path_obj.target}/32",
gateway=exit_gateway_ip,
interface=exit_interface_name,
......
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment