def allocate(G_phy, G_bgp): log.info("Allocating route reflectors") graph_phy = G_phy._graph for asn, devices in G_phy.groupby("asn").items(): routers = [d for d in devices if d.is_router] router_ids = ank_utils.unwrap_nodes(routers) subgraph_phy = graph_phy.subgraph(router_ids) if len(subgraph_phy) == 1: continue # single node in graph, no ibgp betw_cen = nx.degree_centrality(subgraph_phy) ordered = sorted(subgraph_phy.nodes(), key = lambda x: betw_cen[x], reverse = True) rr_count = len(subgraph_phy)/5 # Take top 20% to be route reflectors route_reflectors = ordered[:rr_count] # most connected 20% rr_clients = ordered[rr_count:] # the other routers route_reflectors = list(ank_utils.wrap_nodes(G_bgp, route_reflectors)) rr_clients = list(ank_utils.wrap_nodes(G_bgp, rr_clients)) G_bgp.update(route_reflectors, route_reflector = True) # mark as route reflector # rr <-> rr over_links = [(rr1, rr2) for rr1 in route_reflectors for rr2 in route_reflectors if rr1 != rr2] G_bgp.add_edges_from(over_links, type = 'ibgp', direction = 'over') # client -> rr up_links = [(client, rr) for (client, rr) in itertools.product(rr_clients, route_reflectors)] G_bgp.add_edges_from(up_links, type = 'ibgp', direction = 'up') # rr -> client down_links = [(rr, client) for (client, rr) in up_links] # opposite of up G_bgp.add_edges_from(down_links, type = 'ibgp', direction = 'down') log.debug("iBGP done")
def allocate(G_phy, G_bgp): log.info("Allocating route reflectors") graph_phy = G_phy._graph for asn, devices in G_phy.groupby("asn").items(): routers = [d for d in devices if d.is_router] router_ids = list(ank_utils.unwrap_nodes(routers)) mapping_id_to_device = dict(zip( router_ids, routers)) # to reverse lookup id back to device subgraph_phy = graph_phy.subgraph(router_ids) if len(subgraph_phy) == 1: continue # single node in graph, no ibgp betw_cen = nx.degree_centrality(subgraph_phy) ordered = sorted(subgraph_phy.nodes(), key=lambda x: betw_cen[x], reverse=True) rr_count = len( subgraph_phy) / 4 or 1 # Take top 20% to be route reflectors route_reflectors = ordered[:rr_count] # most connected x% log.debug("Chose route_reflectors %s" % route_reflectors) rr_clients = ordered[rr_count:] # the other routers route_reflectors = list(ank_utils.wrap_nodes(G_bgp, route_reflectors)) rr_clients = list(ank_utils.wrap_nodes(G_bgp, rr_clients)) # distances (shortest path, physical graph) from rrs to clients path_lengths = {} for rr in route_reflectors: path = nx.single_source_shortest_path_length(subgraph_phy, rr) path_mapped = dict( (mapping_id_to_device[id], length) for (id, length) in path.items()) # ids to devices path_lengths[rr] = path_mapped G_bgp.update(route_reflectors, route_reflector=True) # mark as route reflector # rr <-> rr over_links = [(rr1, rr2) for rr1 in route_reflectors for rr2 in route_reflectors if rr1 != rr2] G_bgp.add_edges_from(over_links, type='ibgp', direction='over') for client in rr_clients: ranked_rrs = sorted(route_reflectors, key=lambda rr: path_lengths[rr][client]) parent_count = 2 # number of parents to connect to for each rr client parent_rrs = ranked_rrs[:parent_count] log.info("Route reflectors for %s are %s " % (client, parent_rrs)) for parent in parent_rrs: # client -> rr #up_links = [(client, rr) for (client, rr) in itertools.product(rr_clients, route_reflectors)] G_bgp.add_edge(client, parent, type='ibgp', direction='up') # rr -> client #down_links = [(rr, client) for (client, rr) in up_links] # opposite of up G_bgp.add_edge(parent, client, type='ibgp', direction='down') log.debug("iBGP done")
def allocate(G_phy, G_bgp): log.info("Allocating route reflectors") graph_phy = G_phy._graph for asn, devices in G_phy.groupby("asn").items(): routers = [d for d in devices if d.is_router] router_ids = list(ank_utils.unwrap_nodes(routers)) mapping_id_to_device = dict(zip(router_ids, routers)) # to reverse lookup id back to device subgraph_phy = graph_phy.subgraph(router_ids) if len(subgraph_phy) == 1: continue # single node in graph, no ibgp betw_cen = nx.degree_centrality(subgraph_phy) ordered = sorted(subgraph_phy.nodes(), key = lambda x: betw_cen[x], reverse = True) rr_count = len(subgraph_phy)/4 or 1# Take top 20% to be route reflectors route_reflectors = ordered[:rr_count] # most connected x% log.debug("Chose route_reflectors %s" % route_reflectors) rr_clients = ordered[rr_count:] # the other routers route_reflectors = list(ank_utils.wrap_nodes(G_bgp, route_reflectors)) rr_clients = list(ank_utils.wrap_nodes(G_bgp, rr_clients)) # distances (shortest path, physical graph) from rrs to clients path_lengths = {} for rr in route_reflectors: path = nx.single_source_shortest_path_length(subgraph_phy, rr) path_mapped = dict( (mapping_id_to_device[id], length) for (id, length) in path.items()) # ids to devices path_lengths[rr] = path_mapped G_bgp.update(route_reflectors, route_reflector = True) # mark as route reflector # rr <-> rr over_links = [(rr1, rr2) for rr1 in route_reflectors for rr2 in route_reflectors if rr1 != rr2] G_bgp.add_edges_from(over_links, type = 'ibgp', direction = 'over') for client in rr_clients: ranked_rrs = sorted(route_reflectors, key = lambda rr: path_lengths[rr][client]) parent_count = 2 # number of parents to connect to for each rr client parent_rrs = ranked_rrs[:parent_count] log.info("Route reflectors for %s are %s " % (client, parent_rrs)) for parent in parent_rrs: # client -> rr #up_links = [(client, rr) for (client, rr) in itertools.product(rr_clients, route_reflectors)] G_bgp.add_edge(client, parent, type = 'ibgp', direction = 'up') # rr -> client #down_links = [(rr, client) for (client, rr) in up_links] # opposite of up G_bgp.add_edge(parent, client, type = 'ibgp', direction = 'down') log.debug("iBGP done")
def boundary_nodes(G, nodes): #TODO: move to utils """ returns nodes at boundary of G TODO: check works for both directed and undirected graphs based on edge_boundary from networkx """ import autonetkit.ank as ank_utils graph = ank_utils.unwrap_graph(G) nodes = list(nodes) nbunch = list(ank_utils.unwrap_nodes(nodes)) # find boundary b_edges = nx.edge_boundary(graph, nbunch) # boundary edges internal_nodes = [s for (s, t) in b_edges] assert(all(n in nbunch for n in internal_nodes)) # check internal return ank_utils.wrap_nodes(G, internal_nodes)