Exemplo n.º 1
0
def expand(G_in):
    """ Expands out graph products. G is the source "backbone" graph. H_x is the "PoP template" graphs
    """
    graph_unwrapped = ank_utils.unwrap_graph(G_in)
    G = graph_unwrapped.copy()

    ank.set_node_default(G_in, G_in)

    template_names = set(node.pop_template for node in G_in)
    template_names.discard("None")
    template_names.discard(None)
    if not len(template_names):
        log.debug("No PoP templates set")
        return # no templates set

# Load these templates
    templates = {}
    for template in template_names:
        template_filename = os.path.join("pop_templates", "%s.graphml" % template)
        try:
            pop_graph = autonetkit.load.graphml.load_graphml(template_filename) #TODO: pass in properties eg edge type = physical
        except Exception, e:
            log.warning("Unable to load pop template %s: %s" % (template, e))
            return
        pop_graph = pop_graph.to_undirected() # Undirected for now TODO: document this
        templates[template] = pop_graph
Exemplo n.º 2
0
def expand(G_in):
    """ Expands out graph products. G is the source "backbone" graph. H_x is the "PoP template" graphs
    """
    graph_unwrapped = ank_utils.unwrap_graph(G_in)
    G = graph_unwrapped.copy()

    ank.set_node_default(G_in, G_in)

    template_names = set(node.pop_template for node in G_in)
    template_names.discard("None")
    template_names.discard(None)
    if not len(template_names):
        log.debug("No PoP templates set")
        return  # no templates set

# Load these templates
    templates = {}
    for template in template_names:
        template_filename = os.path.join("pop_templates",
                                         "%s.graphml" % template)
        try:
            pop_graph = autonetkit.load.graphml.load_graphml(
                template_filename
            )  #TODO: pass in properties eg edge type = physical
        except Exception, e:
            log.warning("Unable to load pop template %s: %s" % (template, e))
            return
        pop_graph = pop_graph.to_undirected(
        )  # Undirected for now TODO: document this
        templates[template] = pop_graph
Exemplo n.º 3
0
def expand(G_in):
    """ Expands out graph products. G is the source "backbone" graph. H_x is the "PoP template" graphs
    """
    graph_unwrapped = ank_utils.unwrap_graph(G_in)
    G = graph_unwrapped.copy()
    
    ank.set_node_default(G_in, G_in)
    
    template_names = set(node.pop_template for node in G_in)
    template_names.remove(None)
    if not len(template_names):
        return # no templates set
# Load these templates
    templates = {}
    for template in template_names:
        print "TEMplate is", template
        template_filename = os.path.join("pop_templates", "%s.graphml" % template)
        pop_graph = ank.load_graphml(template_filename) #TODO: pass in properties eg edge type = physical
        pop_graph = pop_graph.to_undirected() # Undirected for now TODO: document this
        templates[template] = pop_graph

    # construct new graph
    G_out = nx.Graph() #TODO: what about bidirectional graphs?
    G_out.add_nodes_from(expand_nodes(G, templates))

    G_out.add_edges_from(intra_pop_links(G, templates))
    G_out.add_edges_from(inter_pop_links(G, templates))

    for s, t in G_out.edges():
        G_out[s][t]['type'] = 'physical' # ensure copied across
    
    # Update properties based on co-ordinates
    for node in G_out:
        u, v = node
        template = G.node[u]['pop_template']
        u_properties = dict(G.node[u])
        v_properties = dict(templates[template].node[v]) # create copy to append with
        x = float(u_properties.get('x')) + float(v_properties.get('x'))
        y = float(u_properties.get('y')) + float(v_properties.get('y'))
        asn = u_properties['asn']
        u_properties.update(v_properties)
        u_properties['x'] = x
        u_properties['y'] = y
        u_properties['label'] = "%s_%s" % (v, u)
        u_properties['id'] = "%s_%s" % (v, u)
        u_properties['pop'] = u
        u_properties['asn'] = asn # restore, don't inherit from pop
        del u_properties['pop_template']
        G_out.node[node] = u_properties

    nx.relabel_nodes(G_out, dict( ((u, v), "%s_%s" % (v, u)) for (u, v) in G_out), copy = False)
#TODO: set edge_ids
    for s, t in G_out.edges():
        G_out[s][t]['edge_id'] = "%s_%s" % (s, t)

    G_in._replace_graph(G_out)

    return
Exemplo n.º 4
0
def igp_routes(anm, measured):
    # TODO: split up expected calculation and comparison so don't need to calculate SPF multiple times
    # TODO: allow choice of IGP - for now is just OSPF
    import networkx as nx
    g_ipv4 = anm['ipv4']
    g_ospf = anm['ospf']

    log.info("Verifying IGP routes")

    # extract source node from measured data
    try:
        src_node = measured[0][0]
    except IndexError:
        log.info("Unable to parse measured results, returning")
        return

    # calculate expected routes

    prefixes_by_router = {}
    prefix_reachability = defaultdict(list)
    for router in g_ospf:
        ipv4_node = g_ipv4.node(router)
        neighbors = ipv4_node.neighbors()
        neighbor_subnets = [n.subnet for n in neighbors]
        prefixes_by_router[router] = neighbor_subnets
        for subnet in neighbor_subnets:
            # use strings for faster matching from here on
            # (can convert back to overlay_nodes later)
            prefix_reachability[str(subnet)].append(str(router))

    # print prefixes_by_router
    # print prefix_reachability

    graph = unwrap_graph(g_ospf)

    shortest_paths = nx.shortest_path(graph, source=src_node, weight='cost')
    shortest_path_lengths = nx.shortest_path_length(
        graph, source=src_node, weight='cost')
    # pprint.pprint(shortest_path_lengths)

    optimal_prefixes = {}
    for prefix, routers in prefix_reachability.items():
        # decorate with cost
        try:
            routers_with_costs = [
                (shortest_path_lengths[r], r) for r in routers]
        except KeyError:
            continue  # no router, likely from eBGP
        min_cost = min(rwc[0] for rwc in routers_with_costs)
        shortest_routers = [rwc[1]
                            for rwc in routers_with_costs if rwc[0] == min_cost]
        optimal_prefixes[str(prefix)] = shortest_routers
    # print optimal_prefixes

    verified_prefixes = {}
    for route in measured:
        dst_cd = route[-1]
        prefix = str(g_ipv4.node(dst_cd).subnet)
        try:
            optimal_routers = optimal_prefixes[prefix]
        except KeyError:
            continue  # prefix not present
        if src_node in optimal_routers:
            continue  # target is self

        optimal_routes = [shortest_paths[r] for r in optimal_routers]
        optimal_next_hop = [p[1] for p in optimal_routes]
        actual_next_hop = route[1]

        log.info("Match: %s, %s, optimal: %s, actual: %s" % (
            actual_next_hop in optimal_next_hop, prefix, ", ".join(optimal_next_hop), actual_next_hop))

        if actual_next_hop not in optimal_next_hop:
            log.info("Unverified prefix: %s on %s. Expected: %s. Received: %s" % (prefix, dst_cd,
                                                                                  ", ".join(optimal_next_hop), actual_next_hop))

        verified_prefixes[prefix] = actual_next_hop in optimal_next_hop

    verified_count = verified_prefixes.values().count(True)
    try:
        verified_fraction = round(
            100 * verified_count / len(verified_prefixes), 2)
    except ZeroDivisionError:
        verified_fraction = 0
    log.info("%s%% verification rate" % verified_fraction)

    return verified_prefixes
Exemplo n.º 5
0
def igp_routes(anm, measured):
    #TODO: split up expected calculation and comparison so don't need to calculate SPF multiple times
    #TODO: allow choice of IGP - for now is just OSPF
    import networkx as nx
    g_ipv4 = anm['ipv4']
    g_ospf = anm['ospf']

    log.info("Verifying IGP routes")

    # extract source node from measured data
    try:
        src_node = measured[0][0]
    except IndexError:
        log.info("Unable to parse measured results, returning")
        return


    # calculate expected routes


    prefixes_by_router = {}
    prefix_reachability = defaultdict(list)
    for router in g_ospf:
        ipv4_node = g_ipv4.node(router)
        neighbors = ipv4_node.neighbors()
        neighbor_subnets = [n.subnet for n in neighbors]
        prefixes_by_router[router] = neighbor_subnets
        for subnet in neighbor_subnets:
            # use strings for faster matching from here on 
            # (can convert back to overlay_nodes later)
            prefix_reachability[str(subnet)].append(str(router))

    #print prefixes_by_router
    #print prefix_reachability

    graph = unwrap_graph(g_ospf)

    shortest_paths = nx.shortest_path(graph, source = src_node, weight = 'cost')
    shortest_path_lengths = nx.shortest_path_length(graph, source = src_node, weight = 'cost')
    #pprint.pprint(shortest_path_lengths)

    optimal_prefixes = {}
    for prefix, routers in prefix_reachability.items():
        # decorate with cost
        routers_with_costs = [(shortest_path_lengths[r], r) for r in routers]
        min_cost = min(rwc[0] for rwc in routers_with_costs)
        shortest_routers = [rwc[1] for rwc in routers_with_costs if rwc[0] == min_cost]
        optimal_prefixes[str(prefix)] = shortest_routers
    #print optimal_prefixes

    verified_prefixes = {}
    for route in measured:
        dst_cd = route[-1]
        prefix = str(g_ipv4.node(dst_cd).subnet)
        optimal_routers = optimal_prefixes[prefix]
        if src_node in optimal_routers:
            continue # target is self

        optimal_routes = [shortest_paths[r] for r in optimal_routers]
        optimal_next_hop = [p[1] for p in optimal_routes]
        actual_next_hop = route[1]

        log.debug( "Match: %s, %s, optimal: %s, actual: %s" % (
                actual_next_hop in optimal_next_hop, prefix, ", ".join(optimal_next_hop), actual_next_hop))

        if actual_next_hop not in optimal_next_hop:
            log.info("Unverified prefix: %s on %s. Expected: %s. Received: %s" % (prefix, dst_cd,
                ", ".join(optimal_next_hop), actual_next_hop))

        verified_prefixes[prefix] = actual_next_hop in optimal_next_hop


    verified_count = verified_prefixes.values().count(True) 
    verified_fraction = round(100 * verified_count/len(verified_prefixes),2)
    log.info("%s%% verification rate" % verified_fraction)
        
    return verified_prefixes