def __init__(self): self.private_address_network = ip_network(CFG.get(DEFAULTSECT, 'private_net')) try: with open(CFG.get(DEFAULTSECT, 'private_ips'), 'r') as f: self.private_address_binding = json.load(f) self.router_private_address = {} for subnets in self.private_address_binding.itervalues(): for rid, ip in subnets.iteritems(): try: iplist = self.router_private_address[rid] except KeyError: iplist = self.router_private_address[rid] = [] iplist.append(ip) except Exception as e: log.error('Incorrect private IP addresses binding file') log.error(str(e)) self.private_address_binding = {} self.router_private_address = {} self.last_line = '' self.transaction = None self.graph = DiGraph() self.routers = {} # router-id : lsa self.networks = {} # DR IP : lsa self.ext_networks = {} # (router-id, dest) : lsa self.controllers = defaultdict(list) # controller nr : ip_list self.listener = {} self.keep_running = True self.queue = Queue() self.processing_thread = Thread(target=self.process_lsa, name="lsa_processing_thread") self.processing_thread.start()
def __init__(self, instance_number): """ :param instance_number: the controller instance number :param net: the subnet allocated for the fibbing nodes """ self.leader = False self.instance = instance_number self.name = 'c%s' % instance_number self.nodes = {} self.bridge = Bridge('br0', self.name) self.root = None net = ip_network(CFG.get(DEFAULTSECT, 'base_net')) controller_prefix = CFG.getint(DEFAULTSECT, 'controller_prefixlen') host_prefix = net.max_prefixlen - controller_prefix controller_base = (int(net.network_address) + (instance_number << host_prefix)) controller_net = ip_address(controller_base) self.net = ip_network('%s/%s' % (controller_net, controller_prefix)) self.graph_thread = Thread(target=self.infer_graph, name="Graph inference thread") self.json_proxy = SJMPServer(hostname=CFG.get(DEFAULTSECT, 'json_hostname'), port=CFG.getint(DEFAULTSECT, 'json_port'), invoke=self.proxy_connected, target=FakeNodeProxyImplem(self)) self.json_thread = Thread(target=self.json_proxy.communicate) # Used to assign unique router-id to each node self.next_id = 1 self.links = [] # The fibbing routes self.routes = {} self.route_mappings = {}
def __init__(self, instance_number): """ :param instance_number: the controller instance number :param net: the subnet allocated for the fibbing nodes """ self.leader = False self.instance = instance_number self.name = 'c%s' % instance_number self.nodes = {} self.bridge = Bridge('br0', self.name) self.root = None net = ip_network(CFG.get(DEFAULTSECT, 'base_net')) controller_prefix = CFG.getint(DEFAULTSECT, 'controller_prefixlen') host_prefix = net.max_prefixlen - controller_prefix controller_base = (int(net.network_address) + (instance_number << host_prefix)) controller_net = ip_address(controller_base) self.net = ip_network('%s/%s' % (controller_net, controller_prefix)) self.graph_thread = daemon_thread(target=self.infer_graph, name="Graph inference thread") self.json_proxy = SJMPServer(hostname=CFG.get(DEFAULTSECT, 'json_hostname'), port=CFG.getint(DEFAULTSECT, 'json_port'), invoke=self.proxy_connected, target=FakeNodeProxyImplem(self)) self.json_thread = daemon_thread(target=self.json_proxy.communicate, name="JSON proxy thread") # Used to assign unique router-id to each node self.next_id = 1 self.links = [] # The fibbing routes self.routes = {} self.route_mappings = {}
def __init__(self, node, port_name, port_ip): """ :param node: The node owning this link :param port_name: The name of the only port visible on this link :param port_ip: The IPV4Address of that link """ section = port_name if CFG.has_section(port_name) else 'physical' self.src = Port(node, self, port_name, hello_int=CFG.get(section, 'hello_interval'), dead_int=CFG.get(section, 'dead_interval'), area=CFG.get(section, 'area'), cost=CFG.get(section, 'cost')) self.src.move_in_namespace() self.src.set_ip(port_ip)
def __init__(self, node, port_name, port_ip): """ :param node: The node owning this link :param port_name: The name of the only port visible on this link :param port_ip: The IPV4Address of that link """ section = port_name if CFG.has_section(port_name) else 'physical' self.src = Port(node, self, port_name, hello_int=CFG.get(section, 'hello_interval'), dead_int=CFG.get(section, 'dead_interval'), area=CFG.get(section, 'area'), cost=CFG.get(section, 'cost')) self.src.move_in_namespace() self.src.set_ip(port_ip) self.node = node self.name = port_name
def update_graph(self, new_graph): self.leader_watchdog.check_leader(self.get_leader()) added_edges = new_graph.difference(self.graph) removed_edges = self.graph.difference(new_graph) node_prop_diff = {n: data for n, data in new_graph.nodes_iter(data=True) if n not in self.graph or (data.viewitems() - self.graph.node[n].viewitems())} # Propagate differences if added_edges or removed_edges or node_prop_diff: log.debug('Pushing changes') for u, v in added_edges: self.for_all_listeners('add_edge', u, v, new_graph.export_edge_data(u, v)) for u, v in removed_edges: self.for_all_listeners('remove_edge', u, v) if node_prop_diff: self.for_all_listeners('update_node_properties', **node_prop_diff) if CFG.getboolean(DEFAULTSECT, 'draw_graph'): new_graph.draw(CFG.get(DEFAULTSECT, 'graph_loc')) self.graph = new_graph log.info('LSA update yielded +%d -%d edges changes, ' '%d node property changes', len(added_edges), len(removed_edges), len(node_prop_diff)) self.for_all_listeners('commit')
def gen_physical_ports(port_list): """ Find all enabled physical interfaces of this :param port_list: The list of all physical ports that should be analyzed :return: A list of Tuple (interface name, ip address) for each active physical interface """ ports = [] for port_name in port_list: try: ip = ip_interface(CFG.get(port_name, 'ip')) ports.append((port_name, ip)) except ConfigError: try: out = subprocess.check_output(['ip', 'a', 'show', port_name]) for line in out.splitlines(): if 'inet ' in line: line = line.strip(' \t\n') port_addr = ip_interface(line.split(' ')[1]) log.debug('Added physical port %s@%s', port_name, port_addr) ports.append((port_name, port_addr)) break # TODO support multiple IP/interface? except subprocess.CalledProcessError as e: log.exception(e) return ports
def build_graph(self): new_graph = DiGraph() # Rebuild the graph from the LSDB for lsa in chain(self.routers.values(), self.networks.values(), self.ext_networks.values()): lsa.apply(new_graph, self) # Contract all IPs to their respective router-id for lsa in self.routers.values(): lsa.contract_graph(new_graph, self.router_private_address.get( lsa.routerid, [])) # Figure out the controllers layout base_net = ip_network(CFG.get(DEFAULTSECT, 'base_net')) controller_prefix = CFG.getint(DEFAULTSECT, 'controller_prefixlen') # Group by controller and log them for ip in new_graph.nodes_iter(): addr = ip_address(ip) if addr in base_net: """1. Compute address diff to remove base_net 2. Right shift to remove host bits 3. Mask with controller mask """ id = (((int(addr) - int(base_net.network_address)) >> base_net.max_prefixlen - controller_prefix) & ((1 << controller_prefix) - 1)) self.controllers[id].append(ip) # Contract them on the graph for id, ips in self.controllers.iteritems(): contract_graph(new_graph, ips, 'C_%s' % id) # Remove generated self loops new_graph.remove_edges_from(new_graph.selfloop_edges()) self.apply_secondary_addresses(new_graph) return new_graph
def __init__(self, node, link, id=None, cost=CFG.get('fake', 'cost'), dead_int=CFG.get('fake', 'dead_interval'), hello_int=CFG.get('fake', 'hello_interval'), area=CFG.get('fake', 'area')): """ :param node: The node owning this port :param link: The link in which this port belongs :param id: The id of this port, otherwise infer it from the node next available port number :param cost: The OSPF cost of that interface :param dead_int: The OSPF dead interval for that interface :param hello_int: The OSPF Hello interval """ self.node = node self.link = link self.id = '%s-eth%s' % (node.id, node.get_next_port()) if not id else id self.ip_interface = None self.ospf_area = area self.ospf_cost = cost self.ospf_dead_int = dead_int self.ospf_hello_int = hello_int
def __init__(self): self.BASE_NET = ip_network(CFG.get(DEFAULTSECT, 'base_net')) self.private_addresses = PrivateAddressStore(CFG.get(DEFAULTSECT, 'private_ips')) self.last_line = '' self.leader_watchdog = None self.transaction = False self.uncommitted_changes = 0 self.graph = IGPGraph() self._lsdb = {NetworkLSA.TYPE: {}, RouterLSA.TYPE: {}, ASExtLSA.TYPE: {}} self.controllers = defaultdict(list) # controller nr : ip_list self.listener = {} self.keep_running = True self.queue = Queue() self.processing_thread = start_daemon_thread( target=self.process_lsa, name='lsa processing thread')
def __init__(self, node, link, id=None, cost=CFG.get('fake', 'cost'), dead_int=CFG.get('fake', 'dead_interval'), hello_int=CFG.get('fake', 'hello_interval'), area=CFG.get('fake', 'area')): """ :param node: The node owning this port :param link: The link in which this port belongs :param id: The id of this port, otherwise infer it from the node next available port number :param cost: The OSPF cost of that interface :param dead_int: The OSPF dead interval for that interface :param hello_int: The OSPF Hello interval """ self.node = node self.link = link self.id = '%s-eth%s' % (node.id, node.get_next_port()) if not id else id self.ip_interface = None self.ospf_area = area self.ospf_cost = cost self.ospf_dead_int = dead_int self.ospf_hello_int = hello_int
def __init__(self, *args, **kwargs): super(SouthboundListener, self).__init__(*args, **kwargs) self.igp_graph = IGPGraph() self.dirty = False self.json_proxy = SJMPClient(hostname=CFG.get(DEFAULTSECT, 'json_hostname'), port=CFG.getint(DEFAULTSECT, 'json_port'), target=self) self.quagga_manager = ProxyCloner(FakeNodeProxy, self.json_proxy)
def __init__(self, *args, **kwargs): super(SouthboundListener, self).__init__(*args, **kwargs) self.igp_graph = IGPGraph() self.dirty = False self.json_proxy = SJMPClient(hostname=CFG.get(DEFAULTSECT, 'json_hostname'), port=CFG.getint(DEFAULTSECT, 'json_port'), target=self) self.quagga_manager = ProxyCloner(FakeNodeProxy, self.json_proxy)
def __init__(self): self.BASE_NET = ip_network(CFG.get(DEFAULTSECT, 'base_net')) self.private_addresses = PrivateAddressStore( CFG.get(DEFAULTSECT, 'private_ips')) self.last_line = '' self.leader_watchdog = None self.transaction = None self.graph = IGPGraph() self.routers = {} # router-id : lsa self.networks = {} # DR IP : lsa self.ext_networks = {} # (router-id, dest) : lsa self.controllers = defaultdict(list) # controller nr : ip_list self.listener = {} self.keep_running = True self.queue = Queue() self.processing_thread = Thread(target=self.process_lsa, name="lsa_processing_thread") self.processing_thread.setDaemon(True) self.processing_thread.start()
def __init__(self): self.BASE_NET = ip_network(CFG.get(DEFAULTSECT, 'base_net')) self.private_addresses = PrivateAddressStore(CFG.get(DEFAULTSECT, 'private_ips')) self.last_line = '' self.leader_watchdog = None self.transaction = None self.graph = IGPGraph() self.routers = {} # router-id : lsa self.networks = {} # DR IP : lsa self.ext_networks = {} # (router-id, dest) : lsa self.controllers = defaultdict(list) # controller nr : ip_list self.listener = {} self.keep_running = True self.queue = Queue() self.processing_thread = Thread(target=self.process_lsa, name="lsa_processing_thread") self.processing_thread.setDaemon(True) self.processing_thread.start()
def __init__(self, router, *args, **kwargs): super(MininetRouterConfig, self).__init__(router, *args, **kwargs) self.ospf.redistribute.connected = 1000 self.ospf.redistribute.static = 1000 self.ospf.router_id = router.id # Parse LSA throttling parameters delay = CFG.get("DEFAULT", 'delay') initial_holdtime = CFG.get("DEFAULT", 'initial_holdtime') max_holdtime = CFG.get("DEFAULT", 'max_holdtime') # Parse minimum LS intervals min_ls_interval = CFG.get("DEFAULT", 'min_ls_interval') min_ls_arrival = CFG.get("DEFAULT", 'min_ls_arrival') self.ospf.throttling = ConfigDict(spf=ConfigDict(delay=delay, initial_holdtime=initial_holdtime, max_holdtime=max_holdtime), lsa_all=ConfigDict(min_ls_interval=min_ls_interval)) self.ospf.lsa = ConfigDict(min_ls_arrival=min_ls_arrival)
def __init__(self, fwd_dags, optimizer, additional_routes=None): self.igp_graph = nx.DiGraph() self.dirty = False self.additional_routes = additional_routes self.optimizer = optimizer self.fwd_dags = fwd_dags self.current_lsas = set([]) self.json_proxy = SJMPClient(hostname=CFG.get(DEFAULTSECT, 'json_hostname'), port=CFG.getint(DEFAULTSECT, 'json_port'), target=self) self.quagga_manager = ProxyCloner(FakeNodeProxy, self.json_proxy)
def __init__(self, address, metric, node): """ :param address: The forwarding address to specify for this attraction point :param metric: The metric of this attraction point :param node: The node advertizing this :return: """ self._address = address self.metric = metric self.node = node self.advertized = False self.ttl = CFG.get(DEFAULTSECT, 'fake_lsa_ttl')
def draw_graph(graph): try: layout = spring_layout(graph) metrics = { (src, dst): data['metric'] for src, dst, data in graph.edges_iter(data=True) } draw_networkx_edge_labels(graph, layout, edge_labels=metrics) draw(graph, layout, node_size=20) draw_networkx_labels(graph, layout, labels={n: n for n in graph}) output = CFG.get(DEFAULTSECT, 'graph_loc') if os.path.exists(output): os.unlink(output) plt.savefig(output) plt.close() log.debug('Graph of %d nodes saved in %s', len(graph), output) except: pass