示例#1
0
def initialise(input_graph):
    anm = autonetkit.anm.AbstractNetworkModel()

    input_undirected = nx.Graph(input_graph)
    g_in = anm.add_overlay("input", graph=input_undirected)
    anm.add_overlay("input_directed", graph=input_graph, directed=True)

    # set defaults
    if not g_in.data.specified_int_names:
        # if not specified then automatically assign interface names
        g_in.data.specified_int_names = False

    import autonetkit.plugins.graph_product as graph_product
    graph_product.expand(g_in)  # apply graph products if relevant

    expand_fqdn = False
    # TODO: make this set from config and also in the input file
    if expand_fqdn and len(ank_utils.unique_attr(g_in, "asn")) > 1:
        # Multiple ASNs set, use label format device.asn
        anm.set_node_label(".", ['label', 'pop', 'asn'])

    g_in.update(g_in.nodes("is_router", platform="junosphere"), syntax="junos")
    g_in.update(g_in.nodes("is_router", platform="dynagen"), syntax="ios")
    g_in.update(g_in.nodes("is_router", platform="netkit"), syntax="quagga")
    g_in.update(g_in.nodes("is_server", platform="netkit"), syntax="quagga")

    g_graphics = anm.add_overlay("graphics")  # plotting data
    g_graphics.add_nodes_from(
        g_in, retain=['x', 'y', 'device_type', 'device_subtype', 'pop', 'asn'])

    return anm
示例#2
0
def initialise(input_graph):
    anm = autonetkit.anm.AbstractNetworkModel()

    input_undirected = nx.Graph(input_graph)
    g_in = anm.add_overlay("input", graph=input_undirected)
    anm.add_overlay("input_directed", graph=input_graph, directed=True)

# set defaults
    if not g_in.data.specified_int_names:
        # if not specified then automatically assign interface names
        g_in.data.specified_int_names = False

    import autonetkit.plugins.graph_product as graph_product
    graph_product.expand(g_in)  # apply graph products if relevant

    expand_fqdn = False
    # TODO: make this set from config and also in the input file
    if expand_fqdn and len(ank_utils.unique_attr(g_in, "asn")) > 1:
        # Multiple ASNs set, use label format device.asn
        anm.set_node_label(".", ['label', 'pop', 'asn'])

    g_in.update(
        g_in.nodes("is_router", platform="junosphere"), syntax="junos")
    g_in.update(g_in.nodes("is_router", platform="dynagen"), syntax="ios")
    g_in.update(g_in.nodes("is_router", platform="netkit"), syntax="quagga")
    g_in.update(g_in.nodes("is_server", platform="netkit"), syntax="quagga")

    g_graphics = anm.add_overlay("graphics")  # plotting data
    g_graphics.add_nodes_from(g_in, retain=['x', 'y', 'device_type',
                              'device_subtype', 'pop', 'asn'])

    return anm
示例#3
0
def initialise(input_graph):
    """Initialises the input graph with from a NetworkX graph"""
    all_multigraph = input_graph.is_multigraph()
    anm = autonetkit.anm.NetworkModel(all_multigraph=all_multigraph)

    g_in = anm.initialise_input(input_graph)
    # autonetkit.update_vis(anm)

# set defaults
    if not g_in.data.specified_int_names:
        # if not specified then automatically assign interface names
        g_in.data.specified_int_names = False

    #import autonetkit.plugins.graph_product as graph_product
    # graph_product.expand(g_in)  # apply graph products if relevant

    expand_fqdn = False
    # TODO: make this set from config and also in the input file
    if expand_fqdn and len(ank_utils.unique_attr(g_in, "asn")) > 1:
        # Multiple ASNs set, use label format device.asn
        anm.set_node_label(".", ['label', 'asn'])

    g_in.update(g_in.routers(platform="junosphere"), syntax="junos")
    g_in.update(g_in.routers(platform="dynagen"), syntax="ios")
    g_in.update(g_in.routers(platform="netkit"), syntax="quagga")
    # TODO: is this used?
    g_in.update(g_in.servers(platform="netkit"), syntax="quagga")

    autonetkit.ank.set_node_default(g_in, specified_int_names=None)

    g_graphics = anm.add_overlay("graphics")  # plotting data
    g_graphics.add_nodes_from(g_in, retain=['x', 'y', 'device_type',
                                            'label', 'device_subtype', 'asn'])

    return anm
示例#4
0
def build_ip(anm):
    import autonetkit.plugins.ipv4 as ip
    G_ip = anm.add_overlay("ip")
    G_in = anm['input']
    G_graphics = anm['graphics']
    G_phy = anm['phy']

    G_ip.add_nodes_from(G_in)
    G_ip.add_edges_from(G_in.edges(type="physical"))

    ank.aggregate_nodes(G_ip, G_ip.nodes("is_switch"), retain = "edge_id")

    edges_to_split = [edge for edge in G_ip.edges() if edge.attr_both("is_l3device")]
    split_created_nodes = list(ank.split(G_ip, edges_to_split, retain='edge_id'))
    for node in split_created_nodes:
        node['graphics'].x = ank.neigh_average(G_ip, node, "x", G_graphics)
        node['graphics'].y = ank.neigh_average(G_ip, node, "y", G_graphics)

    G_ip.update(split_created_nodes, collision_domain=True)

    for node in G_ip.nodes("collision_domain"):
        graphics_node = G_graphics.node(node)
        node.host = G_phy.node(node.neighbors().next()).host # Set host to be same as one of the neighbors (arbitrary choice)
        asn = ank.neigh_most_frequent(G_ip, node, "asn", G_phy) # arbitrary choice
        node.asn = asn
        graphics_node.asn = asn
        graphics_node.x = ank.neigh_average(G_ip, node, "x", G_graphics)

        graphics_node.device_type = "collision_domain"
        cd_label = "cd_" + "_".join(sorted(ank.neigh_attr(G_ip, node, "label", G_phy)))
        node.label = cd_label 
        graphics_node.label = cd_label

    ip.allocate_ips(G_ip)
示例#5
0
def build_ebgp(anm):
    g_in = anm['input']
    g_phy = anm['phy']
    g_ebgp = anm.add_overlay("ebgp", directed=True)
    g_ebgp.add_nodes_from(g_in.nodes("is_router"))
    ebgp_edges = [e for e in g_in.edges() if not e.attr_equal("asn")]
    g_ebgp.add_edges_from(ebgp_edges, bidirectional=True, type='ebgp')

    ebgp_switches = [
        n for n in g_in.nodes("is_switch")
        if not ank_utils.neigh_equal(g_phy, n, "asn")
    ]
    g_ebgp.add_nodes_from(ebgp_switches, retain=['asn'])
    log.debug("eBGP switches are %s" % ebgp_switches)
    g_ebgp.add_edges_from(
        (e for e in g_in.edges()
         if e.src in ebgp_switches or e.dst in ebgp_switches),
        bidirectional=True,
        type='ebgp')
    ank_utils.aggregate_nodes(g_ebgp, ebgp_switches, retain="edge_id")
    ebgp_switches = list(g_ebgp.nodes(
        "is_switch"))  # need to recalculate as may have aggregated
    log.debug("aggregated eBGP switches are %s" % ebgp_switches)
    exploded_edges = ank_utils.explode_nodes(g_ebgp,
                                             ebgp_switches,
                                             retain="edge_id")
    for edge in exploded_edges:
        edge.multipoint = True
示例#6
0
def build_mpls_ldp(anm):
    """Builds MPLS LDP"""
    g_in = anm['input']
    g_vrf = anm['vrf']
    g_l3conn = anm['l3_conn']
    g_mpls_ldp = anm.add_overlay("mpls_ldp")
    nodes_to_add = [n for n in g_in.nodes("is_router")
            if n['vrf'].vrf_role in ("PE", "P")]
    g_mpls_ldp.add_nodes_from(nodes_to_add, retain=["vrf_role", "vrf"])

    # store as set for faster lookup
    pe_nodes = set(g_vrf.nodes(vrf_role = "PE"))
    p_nodes = set(g_vrf.nodes(vrf_role = "P"))

    pe_to_pe_edges = (e for e in g_l3conn.edges()
            if e.src in pe_nodes and e.dst in pe_nodes)
    g_mpls_ldp.add_edges_from(pe_to_pe_edges)

    pe_to_p_edges = (e for e in g_l3conn.edges()
            if e.src in pe_nodes and e.dst in p_nodes
            or e.src in p_nodes and e.dst in pe_nodes)
    g_mpls_ldp.add_edges_from(pe_to_p_edges)

    p_to_p_edges = (e for e in g_l3conn.edges()
            if e.src in p_nodes and e.dst in p_nodes)
    g_mpls_ldp.add_edges_from(p_to_p_edges)
示例#7
0
def initialise(input_graph):
    """Initialises the input graph with from a NetworkX graph"""
    all_multigraph = input_graph.is_multigraph()
    anm = autonetkit.anm.NetworkModel(all_multigraph=all_multigraph)

    g_in = anm.initialise_input(input_graph)
    if g_in.data.igp:
        if g_in.data.profiles:
            node_profiles = g_in.data["profiles"]
            for node in g_in:
                for prof in node_profiles:
                    if node.profile == prof["id"]:
                        if "configs" in prof and "igp" in prof["configs"]:
                            if (
                                "enabled" in prof["configs"]["igp"]
                                and prof["configs"]["igp"]["enabled"] == 1
                                and prof["configs"]["igp"]["igp_prot"]
                            ):
                                node.igp = prof["configs"]["igp"]["igp_prot"]
    else:
        g_in.data.igp = None

    if g_in.data.vxlan_global_config:
        # sharad: right now enable multicast on all nodes by default
        if "multicast" in g_in.data.vxlan_global_config:
            for node in g_in:
                node.multicast = g_in.data.vxlan_global_config["multicast"]

    # autonetkit.update_vis(anm)

    # set defaults
    if not g_in.data.specified_int_names:
        # if not specified then automatically assign interface names
        g_in.data.specified_int_names = False

    # import autonetkit.plugins.graph_product as graph_product
    # graph_product.expand(g_in)  # apply graph products if relevant

    expand_fqdn = False
    # TODO: make this set from config and also in the input file
    if expand_fqdn and len(ank_utils.unique_attr(g_in, "asn")) > 1:
        # Multiple ASNs set, use label format device.asn
        anm.set_node_label(".", ["label", "asn"])

    g_in.update(g_in.routers(platform="junosphere"), syntax="junos")
    if autonetkit.config.settings["Graphml"]["Node Defaults"]["syntax"] == "ios":
        g_in.update(g_in.routers(platform="dynagen"), syntax="ios")
    elif autonetkit.config.settings["Graphml"]["Node Defaults"]["syntax"] == "nx_os":
        g_in.update(g_in.routers(platform="dynagen"), syntax="nx_os")
    g_in.update(g_in.routers(platform="netkit"), syntax="quagga")
    # TODO: is this used?
    g_in.update(g_in.servers(platform="netkit"), syntax="quagga")

    # TODO: check this is needed
    # autonetkit.ank.set_node_default(g_in, specified_int_names=None)

    g_graphics = anm.add_overlay("graphics")  # plotting data
    g_graphics.add_nodes_from(g_in, retain=["x", "y", "device_type", "label", "device_subtype", "asn"])

    return anm
示例#8
0
def build_isis(anm):
    """Build isis overlay"""
    g_in = anm["input"]
    if not any(n.igp == "isis" for n in g_in):
        log.debug("No ISIS nodes")
        return
    g_ipv4 = anm["ipv4"]
    g_isis = anm.add_overlay("isis")
    g_isis.add_nodes_from(g_in.nodes("is_router", igp="isis"), retain=["asn"])
    g_isis.add_nodes_from(g_in.nodes("is_switch"), retain=["asn"])
    g_isis.add_edges_from(g_in.edges(), retain=["edge_id"])
    # Merge and explode switches
    ank_utils.aggregate_nodes(g_isis, g_isis.nodes("is_switch"), retain="edge_id")
    exploded_edges = ank_utils.explode_nodes(g_isis, g_isis.nodes("is_switch"), retain="edge_id")
    for edge in exploded_edges:
        edge.multipoint = True

    g_isis.remove_edges_from([link for link in g_isis.edges() if link.src.asn != link.dst.asn])

    for node in g_isis:
        ip_node = g_ipv4.node(node)
        node.net = ip_to_net_ent_title_ios(ip_node.loopback)
        node.process_id = 1  # default

    for link in g_isis.edges():
        link.metric = 1  # default
        # link.hello = 5 # for debugging, TODO: read from graph

    for edge in g_isis.edges():
        for interface in edge.interfaces():
            interface.metric = edge.metric
            interface.multipoint = edge.multipoint
def build_l3_connectivity(anm):
    """ l3_connectivity graph: switch nodes aggregated and exploded"""
    g_in = anm["input"]
    g_l3conn = anm.add_overlay("layer3")
    g_l3conn.add_nodes_from(
        g_in,
        retain=[
            "label",
            "update",
            "device_type",
            "asn",
            "specified_int_names",
            "device_subtype",
            "platform",
            "host",
            "syntax",
        ],
    )
    g_l3conn.add_nodes_from(g_in.switches(), retain=["asn"])
    g_l3conn.add_edges_from(g_in.edges())

    ank_utils.aggregate_nodes(g_l3conn, g_l3conn.switches())
    exploded_edges = ank_utils.explode_nodes(g_l3conn, g_l3conn.switches())
    for edge in exploded_edges:
        edge.multipoint = True
        edge.src_int.multipoint = True
        edge.dst_int.multipoint = True
示例#10
0
def apply_design_rules(anm):
    g_in = anm['input']

    build_phy(anm)
    g_phy = anm['phy']

    autonetkit.update_http(anm)
    build_l3_connectivity(anm)

    build_vrf(anm) # need to do before to add loopbacks before ip allocations
    build_ip(anm) # ip infrastructure topology

#TODO: set defaults at the start, rather than inline, ie set g_in.data.address_family then use later

    address_family = g_in.data.address_family or "v4" # default is v4
#TODO: can remove the infrastructure now create g_ip seperately
    if address_family in ("v4", "dual_stack"):
        build_ipv4(anm, infrastructure = True)
        g_phy.update(g_phy, use_ipv4 = True)
    else:
        build_ipv4(anm, infrastructure = False)

    #TODO: Create a collision domain overlay for ip addressing - l2 overlay?
    if address_family in ("v6", "dual_stack"):
        build_ipv6(anm)
        g_phy.update(g_phy, use_ipv6 = True)
    else:
        anm.add_overlay("ipv6") # placeholder for compiler logic

    default_igp = g_in.data.igp or "ospf" 
    non_igp_nodes = [n for n in g_in if not n.igp]
#TODO: should this be modifying g_in?
    g_in.update(non_igp_nodes, igp=default_igp) # store igp onto each node

    ank_utils.copy_attr_from(g_in, g_phy, "include_csr")

    build_ospf(anm)
    build_isis(anm)
    build_bgp(anm)
    autonetkit.update_http(anm)

# post-processing
    mark_ebgp_vrf(anm)
    build_ibgp_vpn_v4(anm) # build after bgp as is based on
    #autonetkit.update_http(anm)
    return anm
示例#11
0
def build_conn(anm):
    #TODO: see if this is still required
    G_in = anm['input']
    G_conn = anm.add_overlay("conn", directed = True)
    G_conn.add_nodes_from(G_in, retain=['label'])
    G_conn.add_edges_from(G_in.edges(type="physical"))

    return
示例#12
0
def build_conn(anm):
    """Build connectivity overlay"""
    g_in = anm["input"]
    g_conn = anm.add_overlay("conn", directed=True)
    g_conn.add_nodes_from(g_in, retain=["label"])
    g_conn.add_edges_from(g_in.edges(type="physical"))

    return
示例#13
0
def build_conn(anm):
    """Build connectivity overlay"""
    g_in = anm['input']
    g_conn = anm.add_overlay("conn", directed=True)
    g_conn.add_nodes_from(g_in, retain=['label'])
    g_conn.add_edges_from(g_in.edges(type="physical"))

    return
示例#14
0
def initialise(input_graph):
    """Initialises the input graph with from a NetworkX graph"""
    all_multigraph = input_graph.is_multigraph()
    anm = autonetkit.anm.NetworkModel(all_multigraph=all_multigraph)

    g_in = anm.initialise_input(input_graph)
    if g_in.data.igp:
        if g_in.data.profiles:
            node_profiles = g_in.data['profiles']
            for node in g_in:
                for prof in node_profiles:
                    if node.profile == prof['id']:
                        if 'configs' in prof and 'igp' in prof['configs']:
                            if ('enabled' in prof['configs']['igp'] and prof['configs']['igp']['enabled'] == 1 and
                                prof['configs']['igp']['igp_prot']):
                                node.igp = prof['configs']['igp']['igp_prot']
    else:
        g_in.data.igp = None

    if g_in.data.vxlan_global_config:
        #sharad: right now enable multicast on all nodes by default
        if 'multicast' in g_in.data.vxlan_global_config:
            for node in g_in:
                node.multicast = g_in.data.vxlan_global_config['multicast']

    # autonetkit.update_vis(anm)

# set defaults
    if not g_in.data.specified_int_names:
        # if not specified then automatically assign interface names
        g_in.data.specified_int_names = False

    #import autonetkit.plugins.graph_product as graph_product
    # graph_product.expand(g_in)  # apply graph products if relevant

    expand_fqdn = False
    # TODO: make this set from config and also in the input file
    if expand_fqdn and len(ank_utils.unique_attr(g_in, "asn")) > 1:
        # Multiple ASNs set, use label format device.asn
        anm.set_node_label(".", ['label', 'asn'])

    g_in.update(g_in.routers(platform="junosphere"), syntax="junos")
    if autonetkit.config.settings['Graphml']['Node Defaults']['syntax'] == 'ios':
        g_in.update(g_in.routers(platform="dynagen"), syntax="ios")
    elif autonetkit.config.settings['Graphml']['Node Defaults']['syntax'] == 'nx_os':
        g_in.update(g_in.routers(platform="dynagen"), syntax="nx_os")
    g_in.update(g_in.routers(platform="netkit"), syntax="quagga")
    # TODO: is this used?
    g_in.update(g_in.servers(platform="netkit"), syntax="quagga")

    #TODO: check this is needed
    #autonetkit.ank.set_node_default(g_in, specified_int_names=None)

    g_graphics = anm.add_overlay("graphics")  # plotting data
    g_graphics.add_nodes_from(g_in, retain=['x', 'y', 'device_type',
                                            'label', 'device_subtype', 'asn'])

    return anm
示例#15
0
def build_vrf(anm):
    """Build VRF Overlay"""
    g_in = anm['input']
    g_vrf = anm.add_overlay("vrf")
    g_vrf.add_nodes_from(g_in.nodes("is_router"), retain=["vrf_role", "vrf"])

    allocate_vrf_roles(g_vrf)

    vrf_pre_process(anm)

    def is_pe_ce_edge(edge):
        src_vrf_role = g_vrf.node(edge.src).vrf_role
        dst_vrf_role = g_vrf.node(edge.dst).vrf_role
        return (src_vrf_role, dst_vrf_role) in (("PE", "CE"), ("CE", "PE"))

    vrf_add_edges = (e for e in g_in.edges() if is_pe_ce_edge(e))
    #TODO: should mark as being towards PE or CE
    g_vrf.add_edges_from(vrf_add_edges, retain=['edge_id'])

    def is_pe_p_edge(edge):
        src_vrf_role = g_vrf.node(edge.src).vrf_role
        dst_vrf_role = g_vrf.node(edge.dst).vrf_role
        return (src_vrf_role, dst_vrf_role) in (("PE", "P"), ("P", "PE"))

    vrf_add_edges = (e for e in g_in.edges() if is_pe_p_edge(e))
    g_vrf.add_edges_from(vrf_add_edges, retain=['edge_id'])

    build_mpls_ldp(anm)
    # add PE to P edges

    add_vrf_loopbacks(g_vrf)
    # allocate route-targets per AS
    # This could later look at connected components for each ASN
    route_targets = {}
    for asn, devices in ank_utils.groupby("asn", g_vrf.nodes(vrf_role="PE")):
        asn_vrfs = [d.node_vrf_names for d in devices]
        # flatten list to unique set
        asn_vrfs = set(itertools.chain.from_iterable(asn_vrfs))
        route_targets[asn] = {
            vrf: "%s:%s" % (asn, index)
            for index, vrf in enumerate(sorted(asn_vrfs), 1)
        }

    g_vrf.data.route_targets = route_targets

    for node in g_vrf:
        vrf_loopbacks = node.interfaces("is_loopback", "vrf_name")
        for index, interface in enumerate(vrf_loopbacks, start=101):
            interface.index = index

    for edge in g_vrf.edges():
        # Set the vrf of the edge to be that of the CE device (either src or dst)
        edge.vrf = edge.src.vrf if edge.src.vrf_role is "CE" else edge.dst.vrf

    # map attributes to interfaces
    for edge in g_vrf.edges():
        for interface in edge.interfaces():
            interface.vrf_name = edge.vrf
示例#16
0
def build_ebgp_v6(anm):
    #TODO: remove the bgp layer and have just ibgp and ebgp
    # TODO: build from design rules, currently just builds from ibgp links in bgp layer
    g_ebgp = anm['ebgp']
    g_phy = anm['phy']
    g_ebgpv6 = anm.add_overlay("ebgp_v6", directed=True)
    ipv6_nodes = set(g_phy.nodes("is_router", "use_ipv6"))
    g_ebgpv6.add_nodes_from(n for n in g_ebgp if n in ipv6_nodes)
    g_ebgpv6.add_edges_from(g_ebgp.edges(), retain="direction")
示例#17
0
def build_ebgp_v6(anm):
    #TODO: remove the bgp layer and have just ibgp and ebgp
    # TODO: build from design rules, currently just builds from ibgp links in bgp layer
    g_ebgp = anm['ebgp']
    g_phy = anm['phy']
    g_ebgpv6 = anm.add_overlay("ebgp_v6", directed=True)
    ipv6_nodes = set(g_phy.nodes("is_router", "use_ipv6"))
    g_ebgpv6.add_nodes_from(n for n in g_ebgp if n in ipv6_nodes)
    g_ebgpv6.add_edges_from(g_ebgp.edges(), retain="direction")
示例#18
0
def build_vrf(anm):
    """Build VRF Overlay"""
    g_in = anm['input']
    g_vrf = anm.add_overlay("vrf")
    g_vrf.add_nodes_from(g_in.nodes("is_router"), retain=["vrf_role", "vrf"])

    allocate_vrf_roles(g_vrf)

    vrf_pre_process(anm)

    def is_pe_ce_edge(edge):
        src_vrf_role = g_vrf.node(edge.src).vrf_role
        dst_vrf_role = g_vrf.node(edge.dst).vrf_role
        return (src_vrf_role, dst_vrf_role) in (("PE", "CE"), ("CE", "PE"))

    vrf_add_edges = (e for e in g_in.edges()
           if is_pe_ce_edge(e))
    #TODO: should mark as being towards PE or CE
    g_vrf.add_edges_from(vrf_add_edges, retain=['edge_id'])

    def is_pe_p_edge(edge):
        src_vrf_role = g_vrf.node(edge.src).vrf_role
        dst_vrf_role = g_vrf.node(edge.dst).vrf_role
        return (src_vrf_role, dst_vrf_role) in (("PE", "P"), ("P", "PE"))
    vrf_add_edges = (e for e in g_in.edges()
            if is_pe_p_edge(e))
    g_vrf.add_edges_from(vrf_add_edges, retain=['edge_id'])

    build_mpls_ldp(anm)
    # add PE to P edges

    add_vrf_loopbacks(g_vrf)
    # allocate route-targets per AS
    # This could later look at connected components for each ASN
    route_targets = {}
    for asn, devices in ank_utils.groupby("asn", g_vrf.nodes(vrf_role = "PE")):
        asn_vrfs = [d.node_vrf_names for d in devices]
        # flatten list to unique set
        asn_vrfs = set(itertools.chain.from_iterable(asn_vrfs)) 
        route_targets[asn] = {vrf: "%s:%s" % (asn, index)
                for index, vrf in enumerate(sorted(asn_vrfs), 1)}

    g_vrf.data.route_targets = route_targets

    for node in g_vrf:
        vrf_loopbacks = node.interfaces("is_loopback", "vrf_name")
        for index, interface in enumerate(vrf_loopbacks, start = 101):
            interface.index = index 

    for edge in g_vrf.edges():
        # Set the vrf of the edge to be that of the CE device (either src or dst)
        edge.vrf = edge.src.vrf if edge.src.vrf_role is "CE" else edge.dst.vrf

    # map attributes to interfaces
    for edge in g_vrf.edges():
        for interface in edge.interfaces():
            interface.vrf_name = edge.vrf
示例#19
0
def build_ipv4(anm, infrastructure=True):
    """Builds IPv4 graph"""
    g_ipv4 = anm.add_overlay("ipv4")
    g_in = anm['input']
    g_graphics = anm['graphics']
    g_phy = anm['phy']

    g_ipv4.add_nodes_from(g_in)
    g_ipv4.add_edges_from(g_in.edges(type="physical"))

    ank_utils.aggregate_nodes(g_ipv4, g_ipv4.nodes("is_switch"),
                              retain="edge_id")

    edges_to_split = [edge for edge in g_ipv4.edges() if edge.attr_both(
        "is_l3device")]
    split_created_nodes = list(
        ank_utils.split(g_ipv4, edges_to_split, retain='edge_id'))
    for node in split_created_nodes:
        node['graphics'].x = ank_utils.neigh_average(g_ipv4, node, "x",
                                                     g_graphics) + 0.1 # temporary fix for gh-90
        node['graphics'].y = ank_utils.neigh_average(g_ipv4, node, "y",
                                                     g_graphics) + 0.1 # temporary fix for gh-90
        asn = ank_utils.neigh_most_frequent(
            g_ipv4, node, "asn", g_phy)  # arbitrary choice
        node['graphics'].asn = asn
        node.asn = asn # need to use asn in IP overlay for aggregating subnets

    switch_nodes = g_ipv4.nodes("is_switch")  # regenerate due to aggregated
    g_ipv4.update(switch_nodes, collision_domain=True)
                 # switches are part of collision domain
    g_ipv4.update(split_created_nodes, collision_domain=True)
# Assign collision domain to a host if all neighbours from same host
    for node in split_created_nodes:
        if ank_utils.neigh_equal(g_ipv4, node, "host", g_phy):
            node.host = ank_utils.neigh_attr(
                g_ipv4, node, "host", g_phy).next()  # first attribute

# set collision domain IPs
    for node in g_ipv4.nodes("collision_domain"):
        graphics_node = g_graphics.node(node)
        graphics_node.device_type = "collision_domain"
        if not node.is_switch:
            label = "_".join(
                sorted(ank_utils.neigh_attr(g_ipv4, node, "label", g_phy)))
            cd_label = "cd_%s" % label  # switches keep their names
            node.label = cd_label
            node.cd_id = cd_label
            graphics_node.label = cd_label

    #TODO: need to set allocate_ipv4 by default in the readers
    if g_in.data.allocate_ipv4 is False:
        manual_ipv4_allocation(anm)
    else:
        import autonetkit.plugins.ipv4 as ipv4
        ipv4.allocate_ips(g_ipv4, infrastructure)
        ank_utils.save(g_ipv4)
示例#20
0
def apply_design_rules(anm):
    g_in = anm['input']

    build_phy(anm)
    g_phy = anm['phy']

    build_vrf(anm)  # need to do before to add loopbacks before ip allocations
    build_ip(anm)  # ip infrastructure topology

    #TODO: set defaults at the start, rather than inline, ie set g_in.data.address_family then use later

    address_family = g_in.data.address_family or "v4"  # default is v4
    #TODO: can remove the infrastructure now create g_ip seperately
    if address_family in ("v4", "dual_stack"):
        build_ipv4(anm, infrastructure=True)
        g_phy.update(g_phy, use_ipv4=True)
    else:
        build_ipv4(anm, infrastructure=False)

    #TODO: Create a collision domain overlay for ip addressing - l2 overlay?
    if address_family in ("v6", "dual_stack"):
        build_ipv6(anm)
        g_phy.update(g_phy, use_ipv6=True)
    else:
        anm.add_overlay("ipv6")  # placeholder for compiler logic

    default_igp = g_in.data.igp or "ospf"
    non_igp_nodes = [n for n in g_in if not n.igp]
    #TODO: should this be modifying g_in?
    g_in.update(non_igp_nodes, igp=default_igp)  # store igp onto each node

    ank_utils.copy_attr_from(g_in, g_phy, "include_csr")

    build_ospf(anm)
    build_isis(anm)
    build_bgp(anm)
    autonetkit.update_http(anm)

    # post-processing
    mark_ebgp_vrf(anm)
    build_ibgp_vpn_v4(anm)  # build after bgp as is based on
    #autonetkit.update_http(anm)
    return anm
示例#21
0
def build_ip6(anm):
    """Builds IPv6 graph, using nodes and edges from IPv4 graph"""
    import autonetkit.plugins.ipv6 as ipv6
    # uses the nodes and edges from ipv4
    g_ipv6 = anm.add_overlay("ipv6")
    g_ipv4 = anm['ipv4']
    g_ipv6.add_nodes_from(
        g_ipv4, retain="collision_domain")  # retain if collision domain or not
    g_ipv6.add_edges_from(g_ipv4.edges())
    ipv6.allocate_ips(g_ipv6)
示例#22
0
def build_ibgp_v6(anm):
    #TODO: remove the bgp layer and have just ibgp and ebgp
    # TODO: build from design rules, currently just builds from ibgp links in bgp layer
    #TODO: base on generic ibgp graph, rather than bgp graph
    g_bgp = anm['bgp']
    g_phy = anm['phy']
    g_ibgpv6 = anm.add_overlay("ibgp_v6", directed=True)
    ipv6_nodes = set(g_phy.nodes("is_router", "use_ipv6"))
    g_ibgpv6.add_nodes_from((n for n in g_bgp if n in ipv6_nodes),
            retain = ["ibgp_level", "ibgp_l2_cluster", "ibgp_l3_cluster"] )
    g_ibgpv6.add_edges_from(g_bgp.edges(type="ibgp"), retain="direction")
示例#23
0
def build_ip6(anm):
    import autonetkit.plugins.ip6 as ip6
    # uses the nodes and edges from ipv4
#TODO: make the nodes/edges common for IP, and then allocate after these
#TODO: globally replace ip with ip4
    G_ip6 = anm.add_overlay("ip6")
    G_in = anm['input']
    G_ip4 = anm['ip']
    G_ip6.add_nodes_from(G_ip4, retain="collision_domain") # retain if collision domain or not
    G_ip6.add_edges_from(G_ip4.edges())
    ip6.allocate_ips(G_ip6) 
示例#24
0
def build_ip(anm):
    g_ip = anm.add_overlay("ip")
    g_in = anm['input']
    g_graphics = anm['graphics']
    g_phy = anm['phy']

    g_ip.add_nodes_from(g_in)
    g_ip.add_edges_from(g_in.edges(type="physical"))

    ank_utils.aggregate_nodes(g_ip, g_ip.nodes("is_switch"), retain="edge_id")

    edges_to_split = [
        edge for edge in g_ip.edges() if edge.attr_both("is_l3device")
    ]
    for edge in edges_to_split:
        edge.split = True  # mark as split for use in building nidb
    split_created_nodes = list(
        ank_utils.split(g_ip,
                        edges_to_split,
                        retain=['edge_id', 'split'],
                        id_prepend="cd"))
    for node in split_created_nodes:
        node['graphics'].x = ank_utils.neigh_average(
            g_ip, node, "x", g_graphics) + 0.1  # temporary fix for gh-90
        node['graphics'].y = ank_utils.neigh_average(
            g_ip, node, "y", g_graphics) + 0.1  # temporary fix for gh-90
        asn = ank_utils.neigh_most_frequent(g_ip, node, "asn",
                                            g_phy)  # arbitrary choice
        node['graphics'].asn = asn
        node.asn = asn  # need to use asn in IP overlay for aggregating subnets

    switch_nodes = g_ip.nodes("is_switch")  # regenerate due to aggregated
    g_ip.update(switch_nodes, collision_domain=True)
    # switches are part of collision domain
    g_ip.update(split_created_nodes, collision_domain=True)
    # Assign collision domain to a host if all neighbours from same host
    for node in split_created_nodes:
        if ank_utils.neigh_equal(g_ip, node, "host", g_phy):
            node.host = ank_utils.neigh_attr(g_ip, node, "host",
                                             g_phy).next()  # first attribute


# set collision domain IPs
    for node in g_ip.nodes("collision_domain"):
        graphics_node = g_graphics.node(node)
        graphics_node.device_type = "collision_domain"
        if not node.is_switch:
            # use node sorting, as accomodates for numeric/string names
            neighbors = sorted(neigh for neigh in node.neighbors())
            label = "_".join(neigh.label for neigh in neighbors)
            cd_label = "cd_%s" % label  # switches keep their names
            node.label = cd_label
            node.cd_id = cd_label
            graphics_node.label = cd_label
示例#25
0
def initialise(input_graph):
    """Initialises the input graph with from a NetworkX graph"""
    anm = autonetkit.anm.AbstractNetworkModel()

    input_undirected = nx.Graph(input_graph)
    g_in = anm.add_overlay("input", graph=input_undirected)

    # set defaults
    if not g_in.data.specified_int_names:
        # if not specified then automatically assign interface names
        g_in.data.specified_int_names = False

    #import autonetkit.plugins.graph_product as graph_product
    #graph_product.expand(g_in)  # apply graph products if relevant

    expand_fqdn = False
    # TODO: make this set from config and also in the input file
    if expand_fqdn and len(ank_utils.unique_attr(g_in, "asn")) > 1:
        # Multiple ASNs set, use label format device.asn
        anm.set_node_label(".", ['label', 'asn'])

    g_in.update(g_in.routers(platform="junosphere"), syntax="junos")
    g_in.update(g_in.routers(platform="dynagen"), syntax="ios")
    g_in.update(g_in.routers(platform="netkit"), syntax="quagga")
    #TODO: is this used?
    g_in.update(g_in.servers(platform="netkit"), syntax="quagga")

    autonetkit.ank.set_node_default(g_in, specified_int_names=None)

    g_graphics = anm.add_overlay("graphics")  # plotting data
    g_graphics.add_nodes_from(
        g_in,
        retain=['x', 'y', 'device_type', 'label', 'device_subtype', 'asn'])

    if g_in.data.Creator == "VIRL":
        #TODO: move this to other module
        # Multiple ASNs set, use label format device.asn
        #anm.set_node_label(".", ['label_full'])
        pass

    return anm
示例#26
0
def build_ibgp_v6(anm):
    #TODO: remove the bgp layer and have just ibgp and ebgp
    # TODO: build from design rules, currently just builds from ibgp links in bgp layer
    #TODO: base on generic ibgp graph, rather than bgp graph
    g_bgp = anm['bgp']
    g_phy = anm['phy']
    g_ibgpv6 = anm.add_overlay("ibgp_v6", directed=True)
    ipv6_nodes = set(g_phy.nodes("is_router", "use_ipv6"))
    g_ibgpv6.add_nodes_from(
        (n for n in g_bgp if n in ipv6_nodes),
        retain=["ibgp_level", "ibgp_l2_cluster", "ibgp_l3_cluster"])
    g_ibgpv6.add_edges_from(g_bgp.edges(type="ibgp"), retain="direction")
示例#27
0
def apply_design_rules(anm):
    """Applies appropriate design rules to ANM"""
    g_in = anm['input']

    build_phy(anm)
    g_phy = anm['phy']
    from autonetkit.design.osi_layers import (build_layer2,
        build_layer2_broadcast, build_layer3)
    build_layer2(anm)
    build_layer2_broadcast(anm)
    build_layer3(anm)

    build_l3_connectivity(anm)
    check_server_asns(anm)

    from autonetkit.design.mpls import build_vrf
    build_vrf(anm)  # do before to add loopbacks before ip allocations
    from autonetkit.design.ip import build_ip, build_ipv4, build_ipv6
    # TODO: replace this with layer2 overlay topology creation
    build_ip(anm)  # ip infrastructure topology

    address_family = g_in.data.address_family or "v4"  # default is v4
# TODO: can remove the infrastructure now create g_ip seperately
    if address_family == "None":
        log.info("IP addressing disabled, disabling routing protocol ",
                 "configuration")
        anm['phy'].data.enable_routing = False

    if address_family == "None":
        log.info("IP addressing disabled, skipping IPv4")
        anm.add_overlay("ipv4")  # create empty so rest of code follows
        g_phy.update(g_phy, use_ipv4=False)
    elif address_family in ("v4", "dual_stack"):
        build_ipv4(anm, infrastructure=True)
        g_phy.update(g_phy, use_ipv4=True)
    elif address_family == "v6":
        # Allocate v4 loopbacks for router ids
        build_ipv4(anm, infrastructure=False)
        g_phy.update(g_phy, use_ipv4=False)

    # TODO: Create collision domain overlay for ip addressing - l2 overlay?
    if address_family == "None":
        log.info("IP addressing disabled, not allocating IPv6")
        anm.add_overlay("ipv6")  # create empty so rest of code follows
        g_phy.update(g_phy, use_ipv6=False)
    elif address_family in ("v6", "dual_stack"):
        build_ipv6(anm)
        g_phy.update(g_phy, use_ipv6=True)
    else:
        anm.add_overlay("ipv6")  # placeholder for compiler logic

    default_igp = g_in.data.igp or "ospf"
    ank_utils.set_node_default(g_in,  igp=default_igp)

    ank_utils.copy_attr_from(g_in, g_phy, "include_csr")

    try:
        from autonetkit_cisco import build_network as cisco_build_network
    except ImportError, e:
        log.debug("Unable to load autonetkit_cisco %s" % e)
示例#28
0
def apply_design_rules(anm):
    """Applies appropriate design rules to ANM"""
    g_in = anm['input']

    build_phy(anm)
    g_phy = anm['phy']

    import autonetkit
    autonetkit.update_http(anm)
    build_l3_connectivity(anm)

    check_server_asns(anm)
    autonetkit.update_http(anm)

    build_vrf(anm) # need to do before to add loopbacks before ip allocations
    from autonetkit.design.ip import build_ip, build_ipv4,build_ipv6
    build_ip(anm) # ip infrastructure topology

#TODO: set defaults at the start, rather than inline, ie set g_in.data.address_family then use later

    address_family = g_in.data.address_family or "v4" # default is v4
#TODO: can remove the infrastructure now create g_ip seperately
    if address_family == "None":
        log.info("IP addressing disabled, disabling routing protocol configuration")
        anm['phy'].data.enable_routing = False

    if address_family == "None":
        log.info("IP addressing disabled, skipping IPv4")
        anm.add_overlay("ipv4") # create empty so rest of code follows through
        g_phy.update(g_phy, use_ipv4 = False)
    elif address_family in ("v4", "dual_stack"):
        build_ipv4(anm, infrastructure = True)
        g_phy.update(g_phy, use_ipv4 = True)
    elif address_family == "v6":
        # Allocate v4 loopbacks for router ids
        build_ipv4(anm, infrastructure = False)
        g_phy.update(g_phy, use_ipv4 = False)

    #TODO: Create a collision domain overlay for ip addressing - l2 overlay?
    if address_family == "None":
        log.info("IP addressing disabled, not allocating IPv6")
        anm.add_overlay("ipv6") # create empty so rest of code follows through
        g_phy.update(g_phy, use_ipv6 = False)
    elif address_family in ("v6", "dual_stack"):
        build_ipv6(anm)
        g_phy.update(g_phy, use_ipv6 = True)
    else:
        anm.add_overlay("ipv6") # placeholder for compiler logic

    default_igp = g_in.data.igp or "ospf"
    non_igp_nodes = [n for n in g_in if not n.igp]
#TODO: should this be modifying g_in?
    g_in.update(non_igp_nodes, igp=default_igp) # store igp onto each node

    ank_utils.copy_attr_from(g_in, g_phy, "include_csr")

    try:
        from autonetkit_cisco import build_network as cisco_build_network
    except ImportError, e:
        log.debug("Unable to load autonetkit_cisco %s" % e)
示例#29
0
def build_ip(anm):
    g_ip = anm.add_overlay("ip")
    g_in = anm['input']
    g_graphics = anm['graphics']
    g_phy = anm['phy']

    g_ip.add_nodes_from(g_in)
    g_ip.add_edges_from(g_in.edges(type="physical"))

    ank_utils.aggregate_nodes(g_ip, g_ip.nodes("is_switch"),
                              retain="edge_id")

    edges_to_split = [edge for edge in g_ip.edges() if edge.attr_both(
        "is_l3device")]
    for edge in edges_to_split:
        edge.split = True # mark as split for use in building nidb

    split_created_nodes = list(
        ank_utils.split(g_ip, edges_to_split, retain=['edge_id', 'split'], id_prepend = "cd"))
    for node in split_created_nodes:
        node['graphics'].x = ank_utils.neigh_average(g_ip, node, "x",
                                                     g_graphics) + 0.1 # temporary fix for gh-90
        node['graphics'].y = ank_utils.neigh_average(g_ip, node, "y",
                                                     g_graphics) + 0.1 # temporary fix for gh-90
        asn = ank_utils.neigh_most_frequent(
            g_ip, node, "asn", g_phy)  # arbitrary choice
        node['graphics'].asn = asn
        node.asn = asn # need to use asn in IP overlay for aggregating subnets

    switch_nodes = g_ip.nodes("is_switch")  # regenerate due to aggregated
    g_ip.update(switch_nodes, collision_domain=True)
                 # switches are part of collision domain
    g_ip.update(split_created_nodes, collision_domain=True)
# Assign collision domain to a host if all neighbours from same host
    for node in split_created_nodes:
        if ank_utils.neigh_equal(g_ip, node, "host", g_phy):
            node.host = ank_utils.neigh_attr(
                g_ip, node, "host", g_phy).next()  # first attribute

# set collision domain IPs
    for node in g_ip.nodes("collision_domain"):
        graphics_node = g_graphics.node(node)
        graphics_node.device_type = "collision_domain"
        if not node.is_switch:
            # use node sorting, as accomodates for numeric/string names
            neighbors = sorted(neigh for neigh in node.neighbors())
            label = "_".join(neigh.label for neigh in neighbors) 
            cd_label = "cd_%s" % label  # switches keep their names
            node.label = cd_label
            node.cd_id = cd_label
            graphics_node.label = cd_label
示例#30
0
def apply_design_rules(anm):
    """Applies appropriate design rules to ANM"""
    g_in = anm['input']

    build_phy(anm)
    g_phy = anm['phy']

    build_l3_connectivity(anm)
    check_server_asns(anm)

    from autonetkit.design.mpls import build_vrf
    build_vrf(anm)  # need to do before to add loopbacks before ip allocations
    from autonetkit.design.ip import build_ip, build_ipv4, build_ipv6
    #TODO: replace this with layer2 overlay topology creation
    build_ip(anm)  # ip infrastructure topology

    #TODO: set defaults at the start, rather than inline, ie set g_in.data.address_family then use later

    address_family = g_in.data.address_family or "v4"  # default is v4
    #TODO: can remove the infrastructure now create g_ip seperately
    if address_family == "None":
        log.info(
            "IP addressing disabled, disabling routing protocol configuration")
        anm['phy'].data.enable_routing = False

    if address_family == "None":
        log.info("IP addressing disabled, skipping IPv4")
        anm.add_overlay("ipv4")  # create empty so rest of code follows through
        g_phy.update(g_phy, use_ipv4=False)
    elif address_family in ("v4", "dual_stack"):
        build_ipv4(anm, infrastructure=True)
        g_phy.update(g_phy, use_ipv4=True)
    elif address_family == "v6":
        # Allocate v4 loopbacks for router ids
        build_ipv4(anm, infrastructure=False)
        g_phy.update(g_phy, use_ipv4=False)

    #TODO: Create a collision domain overlay for ip addressing - l2 overlay?
    if address_family == "None":
        log.info("IP addressing disabled, not allocating IPv6")
        anm.add_overlay("ipv6")  # create empty so rest of code follows through
        g_phy.update(g_phy, use_ipv6=False)
    elif address_family in ("v6", "dual_stack"):
        build_ipv6(anm)
        g_phy.update(g_phy, use_ipv6=True)
    else:
        anm.add_overlay("ipv6")  # placeholder for compiler logic

    default_igp = g_in.data.igp or "ospf"
    ank_utils.set_node_default(g_in, igp=default_igp)

    ank_utils.copy_attr_from(g_in, g_phy, "include_csr")

    try:
        from autonetkit_cisco import build_network as cisco_build_network
    except ImportError, e:
        log.debug("Unable to load autonetkit_cisco %s" % e)
示例#31
0
def build_ipv4(anm, infrastructure=True):
    """Builds IPv4 graph"""
    import autonetkit.plugins.ipv4 as ipv4
    g_ipv4 = anm.add_overlay("ipv4")
    g_ip = anm['ip']
    g_in = anm['input']
    g_ipv4.add_nodes_from(
        g_ip, retain="collision_domain")  # retain if collision domain or not
    # Copy ASN attribute chosen for collision domains (used in alloc algorithm)
    ank_utils.copy_attr_from(g_ip, g_ipv4, "asn", nbunch = g_ipv4.nodes("collision_domain"))
    g_ipv4.add_edges_from(g_ip.edges())

    # check if ip ranges have been specified on g_in
    infra_block, loopback_block, vrf_loopback_block = extract_ipv4_blocks(anm)

    # See if IP addresses specified on each interface
    l3_devices = [d for d in g_in if d.device_type in ("router", "server")]

    manual_alloc_devices = set()
    for device in l3_devices:
        physical_interfaces = list(device.physical_interfaces)
        if all(interface.ipv4_address for interface in physical_interfaces):
            manual_alloc_devices.add(device) # add as a manual allocated device

    if manual_alloc_devices == set(l3_devices):
        manual_alloc_ipv4_infrastructure = True
    else:
        manual_alloc_ipv4_infrastructure = False

    #TODO: need to set allocate_ipv4 by default in the readers
    if manual_alloc_ipv4_infrastructure:
        manual_ipv4_infrastructure_allocation(anm)
    else:
        ipv4.allocate_infra(g_ipv4, infra_block)

    if g_in.data.alloc_ipv4_loopbacks is False:
        manual_ipv4_loopback_allocation(anm)
    else:
        ipv4.allocate_loopbacks(g_ipv4, loopback_block)

    #TODO: need to also support secondary_loopbacks for IPv6
    #TODO: only call if secondaries are set
    ipv4.allocate_vrf_loopbacks(g_ipv4, vrf_loopback_block)

    #TODO: replace this with direct allocation to interfaces in ip alloc plugin
    for node in g_ipv4.nodes("is_l3device"):
        node.loopback_zero.ip_address = node.loopback
示例#32
0
def build_ipv4(anm, infrastructure=True):
    """Builds IPv4 graph"""
    g_ipv4 = anm.add_overlay("ipv4")
    g_ip = anm["ip"]
    g_in = anm["input"]
    g_ipv4.add_nodes_from(g_ip, retain="collision_domain")  # retain if collision domain or not
    # Copy ASN attribute chosen for collision domains (used in alloc algorithm)
    ank_utils.copy_attr_from(g_ip, g_ipv4, "asn", nbunch=g_ipv4.nodes("collision_domain"))
    g_ipv4.add_edges_from(g_ip.edges())
    autonetkit.update_http(anm)

    # TODO: need to set allocate_ipv4 by default in the readers
    if g_in.data.alloc_ipv4_infrastructure is False:
        manual_ipv4_infrastructure_allocation(anm)
    else:
        import autonetkit.plugins.ipv4 as ipv4

        ipv4.allocate_ips(g_ipv4, infrastructure=True, loopbacks=False)
        # ank_utils.save(g_ipv4)

    if g_in.data.alloc_ipv4_loopbacks is False:
        manual_ipv4_loopback_allocation(anm)
    else:
        import autonetkit.plugins.ipv4 as ipv4

        ipv4.allocate_ips(g_ipv4, infrastructure=False, loopbacks=True)
        # ank_utils.save(g_ipv4)

    # TODO: need to also support secondary_loopbacks for IPv6
    ipv4.allocate_ips(g_ipv4, infrastructure=False, loopbacks=False, secondary_loopbacks=True)

    autonetkit.update_http(anm)

    # TODO: replace this with direct allocation to interfaces in ip alloc plugin
    for node in g_ipv4.nodes("is_l3device"):
        node.loopback_zero.ip_address = node.loopback
        for interface in node:
            edges = list(interface.edges())
            if len(edges):
                edge = edges[0]  # first (only) edge
                interface.ip_address = edge.ip_address
                interface.subnet = edge.dst.subnet  # from collision domain

    # TODO: also map loopbacks to loopback interface 0
    autonetkit.update_http(anm)
示例#33
0
def build_l3_connectivity(anm):
    """ creates l3_connectivity graph, which is switch nodes aggregated and exploded"""
    #TODO: use this as base for ospf, ebgp, ip, etc rather than exploding in each
    g_in = anm['input']
    g_l3conn = anm.add_overlay("l3_conn")
    g_l3conn.add_nodes_from(g_in, retain=['label', 'update', 'device_type', 'asn',
        'specified_int_names',
        'device_subtype', 'platform', 'host', 'syntax'])
    g_l3conn.add_nodes_from(g_in.nodes("is_switch"), retain=['asn'])
#TODO: check if edge_id needs to be still retained
    g_l3conn.add_edges_from(g_in.edges(), retain=['edge_id'])

    ank_utils.aggregate_nodes(g_l3conn, g_l3conn.nodes("is_switch"),
                              retain="edge_id")
    exploded_edges = ank_utils.explode_nodes(g_l3conn, g_l3conn.nodes("is_switch"),
                            retain="edge_id")
    for edge in exploded_edges:
        edge.multipoint = True
示例#34
0
def build_overlays(filename):

    anm = autonetkit.anm.AbstractNetworkModel()
    input_graph = graphml.load_graphml(filename)
    G_in = anm.add_overlay("input", graph=input_graph)

    G_graphics = anm.add_overlay("graphics")  # plotting data
    G_graphics.add_nodes_from(G_in, retain=['x', 'y', 'device_type', 'asn'])

    G_phy = anm['phy']
    G_phy.add_nodes_from(
        G_in,
        retain=['label', 'device_type', 'asn', 'platform', 'host', 'syntax'])
    G_phy.add_edges_from(G_in.edges(type="physical"))
    G_phy.update(G_phy, syntax="quagga")

    routers = list(G_in.routers())
    G_ospf = anm.add_overlay("ospf", G_in.routers())
    G_ospf.add_edges_from(e for e in G_in.edges() if e.src.asn == e.dst.asn)
    G_ospf.update(area=0)  # set defaults
    G_ospf.update_edges(area=0)

    G_ebgp = anm.add_overlay("ebgp", G_in.routers(), directed=True)
    G_ebgp.add_edges_from((e for e in G_in.edges() if e.src.asn != e.dst.asn),
                          bidirectional=True)

    G_ibgp = anm.add_overlay("ibgp", G_in.routers(), directed=True)
    G_ibgp.add_edges_from(
        ((s, t) for s in routers for t in routers if s.asn == t.asn),
        bidirectional=True)

    # hierarchical
    G_ibgp = anm.add_overlay("ibgp_rr", G_in.routers(), directed=True)

    graph_phy = ank_utils.unwrap_graph(G_phy)
    centrality = nx.degree_centrality(graph_phy)
    rrs = [n for n in centrality if centrality[n] > 0.13]

    for rr in rrs:
        G_ibgp.node(rr).route_reflector = True

    rrs = set(r for r in G_ibgp if r.route_reflector)
    clients = set(G_ibgp) - rrs
    G_ibgp.add_edges_from(((s, t) for s in clients for t in rrs),
                          direction="up")
    G_ibgp.add_edges_from(((s, t) for s in rrs for t in clients),
                          direction="down")
    G_ibgp.add_edges_from(((s, t) for s in rrs for t in rrs), direction="over")

    build_ip(anm)

    return anm
示例#35
0
def build_l3_connectivity(anm):
    """ l3_connectivity graph: switch nodes aggregated and exploded"""
    g_in = anm['input']
    g_l3conn = anm.add_overlay("l3_conn")
    g_l3conn.add_nodes_from(
        g_in, retain=['label', 'update', 'device_type', 'asn',
                      'specified_int_names',
                      'device_subtype', 'platform', 'host', 'syntax'])
    g_l3conn.add_nodes_from(g_in.switches(), retain=['asn'])
    g_l3conn.add_edges_from(g_in.edges())

    ank_utils.aggregate_nodes(g_l3conn, g_l3conn.switches())
    exploded_edges = ank_utils.explode_nodes(g_l3conn,
                                             g_l3conn.switches())
    for edge in exploded_edges:
        edge.multipoint = True
        edge.src_int.multipoint = True
        edge.dst_int.multipoint = True
示例#36
0
def build_speed(anm):
    g_in = anm['input']
    g_speed = anm.add_overlay("speed")
    g_speed.add_nodes_from(g_in.nodes())
    g_speed.add_edges_from(g_in.edges(), retain=['speed'])
    for edge in g_speed.edges():
        if not edge.delay:
            delay = 0
        else:
            delay = edge.delay
        if not edge.speed:
            speed = 0
        else:
            speed = edge.speed

        edge.src_int.speed = speed 
        edge.dst_int.speed = speed 
        edge.src_int.delay = delay
        edge.dst_int.delay = delay
示例#37
0
def build_l3_connectivity(anm):
    """ l3_connectivity graph: switch nodes aggregated and exploded"""
    g_in = anm['input']
    g_l3conn = anm.add_overlay("layer3")
    g_l3conn.add_nodes_from(g_in,
                            retain=[
                                'label', 'update', 'device_type', 'asn',
                                'specified_int_names', 'device_subtype',
                                'platform', 'host', 'syntax'
                            ])
    g_l3conn.add_nodes_from(g_in.switches(), retain=['asn'])
    g_l3conn.add_edges_from(g_in.edges())

    ank_utils.aggregate_nodes(g_l3conn, g_l3conn.switches())
    exploded_edges = ank_utils.explode_nodes(g_l3conn, g_l3conn.switches())
    for edge in exploded_edges:
        edge.multipoint = True
        edge.src_int.multipoint = True
        edge.dst_int.multipoint = True
示例#38
0
def build_l3_connectivity(anm):
    """ creates l3_connectivity graph, which is switch nodes aggregated and exploded"""
    #TODO: use this as base for ospf, ebgp, ip, etc rather than exploding in each
    g_in = anm['input']
    g_l3conn = anm.add_overlay("l3_conn")
    g_l3conn.add_nodes_from(g_in,
                            retain=[
                                'label', 'update', 'device_type', 'asn',
                                'specified_int_names', 'device_subtype',
                                'platform', 'host', 'syntax'
                            ])
    g_l3conn.add_nodes_from(g_in.switches(), retain=['asn'])
    g_l3conn.add_edges_from(g_in.edges())

    ank_utils.aggregate_nodes(g_l3conn, g_l3conn.switches())
    exploded_edges = ank_utils.explode_nodes(g_l3conn, g_l3conn.switches())
    for edge in exploded_edges:
        edge.multipoint = True
        edge.src_int.multipoint = True
        edge.dst_int.multipoint = True
示例#39
0
def build_ipv4(anm, infrastructure=True):
    """Builds IPv4 graph"""
    import autonetkit.plugins.ipv4 as ipv4
    g_ipv4 = anm.add_overlay("ipv4")
    g_ip = anm['ip']
    g_in = anm['input']
    g_ipv4.add_nodes_from(
        g_ip, retain="collision_domain")  # retain if collision domain or not
    # Copy ASN attribute chosen for collision domains (used in alloc algorithm)
    ank_utils.copy_attr_from(g_ip,
                             g_ipv4,
                             "asn",
                             nbunch=g_ipv4.nodes("collision_domain"))
    g_ipv4.add_edges_from(g_ip.edges())

    # check if ip ranges have been specified on g_in
    infra_block, loopback_block, vrf_loopback_block = extract_ipv4_blocks(anm)

    #TODO: need to set allocate_ipv4 by default in the readers
    if g_in.data.alloc_ipv4_infrastructure is False:
        manual_ipv4_infrastructure_allocation(anm)
    else:
        ipv4.allocate_infra(g_ipv4, infra_block)

    if g_in.data.alloc_ipv4_loopbacks is False:
        manual_ipv4_loopback_allocation(anm)
    else:
        ipv4.allocate_loopbacks(g_ipv4, loopback_block)

    #TODO: need to also support secondary_loopbacks for IPv6
    ipv4.allocate_vrf_loopbacks(g_ipv4, vrf_loopback_block)

    #TODO: replace this with direct allocation to interfaces in ip alloc plugin
    for node in g_ipv4.nodes("is_l3device"):
        node.loopback_zero.ip_address = node.loopback
        for interface in node:
            edges = list(interface.edges())
            if len(edges):
                edge = edges[0]  # first (only) edge
                interface.ip_address = edge.ip_address
                interface.subnet = edge.dst.subnet  # from collision domain
示例#40
0
def build_ip(anm):
    import autonetkit.plugins.ipv4 as ip
    G_ip = anm.add_overlay("ip")
    G_in = anm['input']
    G_graphics = anm['graphics']
    G_phy = anm['phy']

    G_ip.add_nodes_from(G_in)
    G_ip.add_edges_from(G_in.edges(type="physical"))

    ank.aggregate_nodes(G_ip, G_ip.nodes("is_switch"), retain="edge_id")

    edges_to_split = [
        edge for edge in G_ip.edges() if edge.attr_both("is_l3device")
    ]
    split_created_nodes = list(
        ank.split(G_ip, edges_to_split, retain='edge_id'))
    for node in split_created_nodes:
        node['graphics'].x = ank.neigh_average(G_ip, node, "x", G_graphics)
        node['graphics'].y = ank.neigh_average(G_ip, node, "y", G_graphics)

    G_ip.update(split_created_nodes, collision_domain=True)

    for node in G_ip.nodes("collision_domain"):
        graphics_node = G_graphics.node(node)
        node.host = G_phy.node(
            node.neighbors().next()
        ).host  # Set host to be same as one of the neighbors (arbitrary choice)
        asn = ank.neigh_most_frequent(G_ip, node, "asn",
                                      G_phy)  # arbitrary choice
        node.asn = asn
        graphics_node.asn = asn
        graphics_node.x = ank.neigh_average(G_ip, node, "x", G_graphics)

        graphics_node.device_type = "collision_domain"
        cd_label = "cd_" + "_".join(
            sorted(ank.neigh_attr(G_ip, node, "label", G_phy)))
        node.label = cd_label
        graphics_node.label = cd_label

    ip.allocate_ips(G_ip)
示例#41
0
def build_ipv6(anm):
    """Builds IPv6 graph, using nodes and edges from IPv4 graph"""
    import autonetkit.plugins.ipv6 as ipv6
    # uses the nodes and edges from ipv4
    g_ipv6 = anm.add_overlay("ipv6")
    g_ip = anm['ip']
    g_ipv6.add_nodes_from(
        g_ip, retain="collision_domain")  # retain if collision domain or not
    g_ipv6.add_edges_from(g_ip.edges())

    ipv6.allocate_ips(g_ipv6)

    #TODO: replace this with direct allocation to interfaces in ip alloc plugin
    for node in g_ipv6.nodes("is_l3device"):
        node.loopback_zero.ip_address = node.loopback
        for interface in node:
            edges = list(interface.edges())
            if len(edges):
                edge = edges[0] # first (only) edge
                interface.ip_address = edge.ip #TODO: make this consistent
                interface.subnet = edge.dst.subnet # from collision domain
示例#42
0
def build_ebgp(anm):
    g_in = anm['input']
    g_phy = anm['phy']
    g_ebgp = anm.add_overlay("ebgp", directed=True)
    g_ebgp.add_nodes_from(g_in.nodes("is_router"))
    ebgp_edges = [e for e in g_in.edges() if not e.attr_equal("asn")]
    g_ebgp.add_edges_from(ebgp_edges, bidirectional=True, type='ebgp')

    ebgp_switches = [n for n in g_in.nodes("is_switch")
            if not ank_utils.neigh_equal(g_phy, n, "asn")]
    g_ebgp.add_nodes_from(ebgp_switches, retain=['asn'])
    log.debug("eBGP switches are %s" % ebgp_switches)
    g_ebgp.add_edges_from((e for e in g_in.edges()
            if e.src in ebgp_switches or e.dst in ebgp_switches), bidirectional=True, type='ebgp')
    ank_utils.aggregate_nodes(g_ebgp, ebgp_switches, retain="edge_id")
    ebgp_switches = list(g_ebgp.nodes("is_switch")) # need to recalculate as may have aggregated
    log.debug("aggregated eBGP switches are %s" % ebgp_switches)
    exploded_edges = ank_utils.explode_nodes(g_ebgp, ebgp_switches,
            retain="edge_id")
    for edge in exploded_edges:
        edge.multipoint = True
示例#43
0
def build_mpls_ldp(anm):
    """Builds MPLS LDP"""
    g_in = anm['input']
    g_vrf = anm['vrf']
    g_mpls_ldp = anm.add_overlay("mpls_ldp")
    nodes_to_add = [
        n for n in g_in.nodes("is_router") if n['vrf'].vrf_role in ("PE", "P")
    ]
    g_mpls_ldp.add_nodes_from(nodes_to_add, retain=["vrf_role", "vrf"])

    # store as set for faster lookup
    pe_nodes = set(g_vrf.nodes(vrf_role="PE"))
    p_nodes = set(g_vrf.nodes(vrf_role="P"))

    pe_to_pe_edges = (e for e in g_in.edges()
                      if e.src in pe_nodes and e.dst in pe_nodes)
    g_mpls_ldp.add_edges_from(pe_to_pe_edges)
    pe_to_p_edges = (e for e in g_in.edges()
                     if e.src in pe_nodes and e.dst in p_nodes
                     or e.src in p_nodes and e.dst in pe_nodes)
    g_mpls_ldp.add_edges_from(pe_to_p_edges)
示例#44
0
def build_ipv6(anm):
    """Builds IPv6 graph, using nodes and edges from IPv4 graph"""
    import autonetkit.plugins.ipv6 as ipv6
    # uses the nodes and edges from ipv4
    g_ipv6 = anm.add_overlay("ipv6")
    g_ip = anm['ip']
    g_ipv6.add_nodes_from(
        g_ip, retain="collision_domain")  # retain if collision domain or not
    g_ipv6.add_edges_from(g_ip.edges())

    ipv6.allocate_ips(g_ipv6)

    #TODO: replace this with direct allocation to interfaces in ip alloc plugin
    for node in g_ipv6.nodes("is_l3device"):
        node.loopback_zero.ip_address = node.loopback
        for interface in node:
            edges = list(interface.edges())
            if len(edges):
                edge = edges[0]  # first (only) edge
                interface.ip_address = edge.ip  #TODO: make this consistent
                interface.subnet = edge.dst.subnet  # from collision domain
示例#45
0
def build_isis(anm):
    """Build isis overlay"""
    g_in = anm['input']
    # add regardless, so allows quick check of node in anm['isis'] in compilers
    g_isis = anm.add_overlay("isis")

    if not any(n.igp == "isis" for n in g_in):
        log.debug("No ISIS nodes")
        return
    g_ipv4 = anm['ipv4']
    g_isis.add_nodes_from(g_in.nodes("is_router", igp="isis"), retain=['asn'])
    g_isis.add_nodes_from(g_in.nodes("is_switch"), retain=['asn'])
    g_isis.add_edges_from(g_in.edges(), retain=['edge_id'])
    # Merge and explode switches
    ank_utils.aggregate_nodes(g_isis,
                              g_isis.nodes("is_switch"),
                              retain="edge_id")
    exploded_edges = ank_utils.explode_nodes(g_isis,
                                             g_isis.nodes("is_switch"),
                                             retain="edge_id")
    for edge in exploded_edges:
        edge.multipoint = True

    g_isis.remove_edges_from(
        [link for link in g_isis.edges() if link.src.asn != link.dst.asn])

    for node in g_isis:
        ip_node = g_ipv4.node(node)
        node.net = ip_to_net_ent_title_ios(ip_node.loopback)
        node.process_id = 1  # default

    for link in g_isis.edges():
        link.metric = 1  # default
        # link.hello = 5 # for debugging, TODO: read from graph

    for edge in g_isis.edges():
        for interface in edge.interfaces():
            interface.metric = edge.metric
            interface.multipoint = edge.multipoint
示例#46
0
def build_isis(anm):
    G_in = anm['input']
    G_ip = anm['ip']
    G_isis = anm.add_overlay("isis")
    #G_isis.add_nodes_from(G_in.nodes("is_router", igp = "isis"), retain=['asn'])
#TODO: filter only igp=isis nodes, set the igp as a default in build_network
    G_isis.add_nodes_from(G_in.nodes("is_router"), retain=['asn'])
    G_isis.add_nodes_from(G_in.nodes("is_switch"), retain=['asn'])
    G_isis.add_edges_from(G_in.edges(), retain = ['edge_id'])
# Merge and explode switches
    ank.aggregate_nodes(G_isis, G_isis.nodes("is_switch"), retain = "edge_id")
    ank.explode_nodes(G_isis, G_isis.nodes("is_switch"), retain = "edge_id")

    G_isis.remove_edges_from([link for link in G_isis.edges() if link.src.asn != link.dst.asn])

    for node in G_isis:
        ip_node = G_ip.node(node)
        node.net = ip_to_net_ent_title_ios(ip_node.loopback)
        node.process_id = 1 # default

    for link in G_isis.edges():
        link.metric = 1 # default
示例#47
0
def build_ipv4(anm, infrastructure=True):
    """Builds IPv4 graph"""
    import autonetkit.plugins.ipv4 as ipv4
    g_ipv4 = anm.add_overlay("ipv4")
    g_ip = anm['ip']
    g_in = anm['input']
    g_ipv4.add_nodes_from(
        g_ip, retain="collision_domain")  # retain if collision domain or not
    # Copy ASN attribute chosen for collision domains (used in alloc algorithm)
    ank_utils.copy_attr_from(g_ip, g_ipv4, "asn", nbunch = g_ipv4.nodes("collision_domain"))
    g_ipv4.add_edges_from(g_ip.edges())

    # check if ip ranges have been specified on g_in
    infra_block, loopback_block, vrf_loopback_block = extract_ipv4_blocks(anm)

    #TODO: need to set allocate_ipv4 by default in the readers
    if g_in.data.alloc_ipv4_infrastructure is False:
        manual_ipv4_infrastructure_allocation(anm)
    else:
        ipv4.allocate_infra(g_ipv4, infra_block)

    if g_in.data.alloc_ipv4_loopbacks is False:
        manual_ipv4_loopback_allocation(anm)
    else:
        ipv4.allocate_loopbacks(g_ipv4, loopback_block)

    #TODO: need to also support secondary_loopbacks for IPv6
    ipv4.allocate_vrf_loopbacks(g_ipv4, vrf_loopback_block)

    #TODO: replace this with direct allocation to interfaces in ip alloc plugin
    for node in g_ipv4.nodes("is_l3device"):
        node.loopback_zero.ip_address = node.loopback
        for interface in node:
            edges = list(interface.edges())
            if len(edges):
                edge = edges[0] # first (only) edge
                interface.ip_address = edge.ip_address
                interface.subnet = edge.dst.subnet # from collision domain
示例#48
0
def build_overlays(filename):

    anm = autonetkit.anm.AbstractNetworkModel()
    input_graph = graphml.load_graphml(filename)
    G_in = anm.add_overlay("input", graph = input_graph)

    G_graphics = anm.add_overlay("graphics") # plotting data
    G_graphics.add_nodes_from(G_in, retain=['x', 'y', 'device_type', 'asn'])
    
    G_phy = anm['phy']
    G_phy.add_nodes_from(G_in, retain=['label', 'device_type', 'asn', 'platform', 'host', 'syntax'])
    G_phy.add_edges_from(G_in.edges(type="physical"))
    G_phy.update(G_phy, syntax="quagga")

    routers = list(G_in.routers())
    G_ospf = anm.add_overlay("ospf", G_in.routers())
    G_ospf.add_edges_from(e for e in G_in.edges() if e.src.asn == e.dst.asn)
    G_ospf.update(area=0) # set defaults
    G_ospf.update_edges(area=0)

    G_ebgp = anm.add_overlay("ebgp", G_in.routers(), directed = True)
    G_ebgp.add_edges_from((e for e in G_in.edges() if e.src.asn != e.dst.asn), bidirectional = True)

    G_ibgp = anm.add_overlay("ibgp", G_in.routers(), directed = True)
    G_ibgp.add_edges_from(((s, t) for s in routers for t in routers if s.asn == t.asn), bidirectional = True)

    # hierarchical
    G_ibgp = anm.add_overlay("ibgp_rr", G_in.routers(), directed = True)

    graph_phy = ank_utils.unwrap_graph(G_phy)
    centrality = nx.degree_centrality(graph_phy) 
    rrs = [n for n in centrality if centrality[n] > 0.13]

    for rr in rrs:
        G_ibgp.node(rr).route_reflector = True

    rrs = set(r for r in G_ibgp if r.route_reflector)
    clients = set(G_ibgp) - rrs
    G_ibgp.add_edges_from(((s, t) for s in clients for t in rrs), direction = "up")
    G_ibgp.add_edges_from(((s, t) for s in rrs for t in clients), direction = "down")
    G_ibgp.add_edges_from(((s, t) for s in rrs for t in rrs), direction = "over")

    build_ip(anm)

    return anm
示例#49
0
def build_isis(anm):
    """Build isis overlay"""
    g_in = anm['input']
    # add regardless, so allows quick check of node in anm['isis'] in compilers
    g_isis = anm.add_overlay("isis") 

    if not any(n.igp == "isis" for n in g_in):
        log.debug("No ISIS nodes")
        return
    g_ipv4 = anm['ipv4']
    g_isis.add_nodes_from(g_in.nodes("is_router", igp = "isis"), retain=['asn'])
    g_isis.add_nodes_from(g_in.nodes("is_server", igp = "isis"), retain=['asn'])
    g_isis.add_nodes_from(g_in.nodes("is_switch"), retain=['asn'])
    g_isis.add_edges_from(g_in.edges(), retain=['edge_id'])
# Merge and explode switches
    ank_utils.aggregate_nodes(g_isis, g_isis.nodes("is_switch"),
                              retain="edge_id")
    exploded_edges = ank_utils.explode_nodes(g_isis, g_isis.nodes("is_switch"),
                            retain="edge_id")
    for edge in exploded_edges:
        edge.multipoint = True

    g_isis.remove_edges_from(
        [link for link in g_isis.edges() if link.src.asn != link.dst.asn])

    for node in g_isis:
        ip_node = g_ipv4.node(node)
        node.net = ip_to_net_ent_title_ios(ip_node.loopback)
        node.process_id = 1  # default

    for link in g_isis.edges():
        link.metric = 1  # default

    for edge in g_isis.edges():
        for interface in edge.interfaces():
            interface.metric = edge.metric
            interface.multipoint = edge.multipoint
示例#50
0
def initialise(input_graph):
    """Initialises the input graph with from a NetworkX graph"""
    all_multigraph = input_graph.is_multigraph()
    anm = autonetkit.anm.NetworkModel(all_multigraph=all_multigraph)

    g_in = anm.initialise_input(input_graph)
    # autonetkit.update_vis(anm)

    # set defaults
    if not g_in.data.specified_int_names:
        # if not specified then automatically assign interface names
        g_in.data.specified_int_names = False

    #import autonetkit.plugins.graph_product as graph_product
    # graph_product.expand(g_in)  # apply graph products if relevant

    expand_fqdn = False
    # TODO: make this set from config and also in the input file
    if expand_fqdn and len(ank_utils.unique_attr(g_in, "asn")) > 1:
        # Multiple ASNs set, use label format device.asn
        anm.set_node_label(".", ['label', 'asn'])

    g_in.update(g_in.routers(platform="junosphere"), syntax="junos")
    g_in.update(g_in.routers(platform="dynagen"), syntax="ios")
    g_in.update(g_in.routers(platform="netkit"), syntax="quagga")
    # TODO: is this used?
    g_in.update(g_in.servers(platform="netkit"), syntax="quagga")

    #TODO: check this is needed
    #autonetkit.ank.set_node_default(g_in, specified_int_names=None)

    g_graphics = anm.add_overlay("graphics")  # plotting data
    g_graphics.add_nodes_from(
        g_in,
        retain=['x', 'y', 'device_type', 'label', 'device_subtype', 'asn'])

    return anm
示例#51
0
def build_ibgp_vpn_v4(anm):
    """Based on the ibgp_v4 hierarchy rules.
    Exceptions:
    1. Remove links to (PE, RRC) nodes

    CE nodes are excluded from RR hierarchy ibgp creation through pre-process step

    """
    #TODO: remove the bgp layer and have just ibgp and ebgp
    # TODO: build from design rules, currently just builds from ibgp links in bgp layer
    g_bgp = anm['bgp']
    g_ibgp_v4 = anm['ibgp_v4']
    g_vrf = anm['vrf']
    g_phy = anm['phy']
    g_ibgp_vpn_v4 = anm.add_overlay("ibgp_vpn_v4", directed=True)

    ibgp_v4_nodes = list(g_ibgp_v4.nodes())
    pe_nodes = set(g_vrf.nodes(vrf_role="PE"))
    pe_rrc_nodes = {
        n
        for n in ibgp_v4_nodes if n in pe_nodes and n.ibgp_role == "RRC"
    }
    ce_nodes = set(g_vrf.nodes(vrf_role="CE"))

    ibgp_vpn_v4_nodes = (n for n in ibgp_v4_nodes
                         if n not in pe_rrc_nodes and n not in ce_nodes)
    g_ibgp_vpn_v4.add_nodes_from(ibgp_vpn_v4_nodes, retain="ibgp_level")
    g_ibgp_vpn_v4.add_edges_from(g_ibgp_v4.edges(), retain="direction")

    for node in g_ibgp_vpn_v4:
        if node.ibgp_level in (2, 3):  # HRR or RR
            node.retain_route_target = True

    ce_edges = [
        e for e in g_ibgp_vpn_v4.edges()
        if e.src in ce_nodes or e.dst in ce_nodes
    ]
    """
    #TODO: do we still need this?
    g_ibgp_vpn_v4.remove_edges_from(ce_edges)

# add CE -> PE links based on physical connectivity
#Note: this could later look at 
    ce_to_pe_edges = []
    ce_phy_nodes = {g_phy.node(n) for n in ce_nodes}
    pe_phy_nodes = {g_phy.node(n) for n in g_vrf.nodes(vrf_role = "PE")}
    ce_to_pe_edges += (e for e in g_phy.edges()
            if 
            e.src.asn == e.dst.asn 
            and
            ((e.src in ce_phy_nodes and e.dst in pe_phy_nodes)
            or (e.src in pe_phy_nodes and e.dst in ce_phy_nodes)))

    g_ibgp_vpn_v4.add_edges_from(ce_to_pe_edges, type="ibgp", bidirectional = True)
    """

    # mark ibgp direction
    ce_pe_edges = []
    pe_ce_edges = []
    for edge in g_ibgp_vpn_v4.edges():
        if (edge.src.vrf_role, edge.dst.vrf_role) == ("CE", "PE"):
            edge.direction = "up"
            edge.vrf = edge.src.vrf
            ce_pe_edges.append(edge)
        elif (edge.src.vrf_role, edge.dst.vrf_role) == ("PE", "CE"):
            edge.direction = "down"
            edge.vrf = edge.dst.vrf
            pe_ce_edges.append(edge)

    #TODO: Document this
    g_ibgpv4 = anm['ibgp_v4']
    g_ibgpv6 = anm['ibgp_v6']
    g_ibgpv4.remove_edges_from(ce_edges)
    g_ibgpv6.remove_edges_from(ce_edges)
    g_ibgpv4.add_edges_from(ce_pe_edges, retain=["direction", "vrf"])
    g_ibgpv4.add_edges_from(pe_ce_edges, retain=["direction", "vrf"])
    g_ibgpv6.add_edges_from(ce_pe_edges, retain=["direction", "vrf"])
    g_ibgpv6.add_edges_from(pe_ce_edges, retain=["direction", "vrf"])
    for edge in pe_ce_edges:
        # mark as exclude so don't include in standard ibgp config stanzas
        if g_ibgpv4.has_edge(edge):
            edge['ibgp_v4'].exclude = True
        if g_ibgpv6.has_edge(edge):
            edge['ibgp_v6'].exclude = True


# legacy
    g_bgp = anm['bgp']
    g_bgp.remove_edges_from(ce_edges)
    g_bgp.add_edges_from(ce_pe_edges, retain=["direction", "vrf", "type"])
    g_bgp.add_edges_from(pe_ce_edges, retain=["direction", "vrf", "type"])
示例#52
0
def build_bgp(anm):
    """Build iBGP end eBGP overlays"""
    # eBGP
    g_in = anm['input']
    g_phy = anm['phy']

    build_ebgp(anm)
    build_ebgp_v4(anm)
    build_ebgp_v6(anm)
    """TODO: remove from here once compiler updated"""
    g_bgp = anm.add_overlay("bgp", directed=True)
    g_bgp.add_nodes_from(g_in.nodes("is_router"))
    ebgp_edges = [edge for edge in g_in.edges() if not edge.attr_equal("asn")]
    g_bgp.add_edges_from(ebgp_edges, bidirectional=True, type='ebgp')
    #TODO: why don't we include edge_id here

    ebgp_switches = [
        n for n in g_in.nodes("is_switch")
        if not ank_utils.neigh_equal(g_phy, n, "asn")
    ]
    g_bgp.add_nodes_from(ebgp_switches, retain=['asn'])
    log.debug("eBGP switches are %s" % ebgp_switches)
    g_bgp.add_edges_from((e for e in g_in.edges()
                          if e.src in ebgp_switches or e.dst in ebgp_switches),
                         bidirectional=True,
                         type='ebgp')
    ank_utils.aggregate_nodes(g_bgp, ebgp_switches, retain="edge_id")
    ebgp_switches = list(
        g_bgp.nodes("is_switch"))  # need to recalculate as may have aggregated
    log.debug("aggregated eBGP switches are %s" % ebgp_switches)
    exploded_edges = ank_utils.explode_nodes(g_bgp,
                                             ebgp_switches,
                                             retain="edge_id")
    for edge in exploded_edges:
        edge.multipoint = True
    """TODO: remove up to here once compiler updated"""

    # now iBGP
    ank_utils.copy_attr_from(g_in, g_bgp, "ibgp_level")
    ank_utils.copy_attr_from(g_in, g_bgp, "ibgp_l2_cluster")
    ank_utils.copy_attr_from(g_in, g_bgp, "ibgp_l3_cluster")
    for node in g_bgp:
        # set defaults
        if node.ibgp_level is None:
            node.ibgp_level = 1

        if node.ibgp_level == "None":  # if unicode string from yEd
            node.ibgp_level = 1

#TODO CHECK FOR IBGP NONE

        node.ibgp_level = int(node.ibgp_level)  # ensure is numeric

        if not node.ibgp_l2_cluster or node.ibgp_l2_cluster == "None":
            # ibgp_l2_cluster defaults to region
            node.ibgp_l2_cluster = node.region or "default_l2_cluster"
        if not node.ibgp_l3_cluster or node.ibgp_l3_cluster == "None":
            # ibgp_l3_cluster defaults to ASN
            node.ibgp_l3_cluster = node.asn

    for asn, devices in ank_utils.groupby("asn", g_bgp):
        # group by nodes in phy graph
        routers = list(g_bgp.node(n) for n in devices if n.is_router)
        # list of nodes from bgp graph
        ibgp_levels = {int(r.ibgp_level) for r in routers}
        max_level = max(ibgp_levels)
        # all possible edge src/dst pairs
        ibgp_routers = [r for r in routers if r.ibgp_level > 0]
        all_pairs = [(s, t) for s in ibgp_routers for t in ibgp_routers
                     if s != t]
        if max_level == 3:
            up_links, down_links, over_links = three_tier_ibgp_edges(
                ibgp_routers)

        elif max_level == 2:
            up_links, down_links, over_links = build_two_tier_ibgp(
                ibgp_routers)

        elif max_level == 1:
            up_links = []
            down_links = []
            over_links = [(s, t) for (s, t) in all_pairs
                          if s.ibgp_l3_cluster == t.ibgp_l3_cluster
                          and s.ibgp_l2_cluster == t.ibgp_l2_cluster]
        else:
            # no iBGP
            up_links = []
            down_links = []
            over_links = []

        if max_level > 0:
            g_bgp.add_edges_from(up_links, type='ibgp', direction='up')
            g_bgp.add_edges_from(down_links, type='ibgp', direction='down')
            g_bgp.add_edges_from(over_links, type='ibgp', direction='over')

        else:
            log.debug("No iBGP routers in %s" % asn)


# and set label back
    ibgp_label_to_level = {
        0: "None",  # Explicitly set role to "None" -> Not in iBGP
        3: "RR",
        1: "RRC",
        2: "HRR",
    }
    for node in g_bgp:
        node.ibgp_role = ibgp_label_to_level[node.ibgp_level]

    ebgp_nodes = [
        d for d in g_bgp if any(edge.type == 'ebgp' for edge in d.edges())
    ]
    g_bgp.update(ebgp_nodes, ebgp=True)

    for ebgp_edge in g_bgp.edges(type="ebgp"):
        for interface in ebgp_edge.interfaces():
            interface.ebgp = True

    for edge in g_bgp.edges(type='ibgp'):
        # TODO: need interface querying/selection. rather than hard-coded ids
        edge.bind_interface(edge.src, 0)

    #TODO: need to initialise interface zero to be a loopback rather than physical type
    for node in g_bgp:
        for interface in node.interfaces():
            interface.multipoint = any(e.multipoint for e in interface.edges())

    build_ibgp_v4(anm)
    build_ibgp_v6(anm)
示例#53
0
def build_ospf(anm):
    """
    Build OSPF graph.

    Allowable area combinations:
    0 -> 0
    0 -> x (x!= 0)
    x -> 0 (x!= 0)
    x -> x (x != 0)

    Not-allowed:
    x -> x (x != y != 0)

    #TODO: build check that verifies these rules
    """
    import netaddr
    g_in = anm['input']
    # add regardless, so allows quick check of node in anm['ospf'] in compilers
    g_ospf = anm.add_overlay("ospf")

    if not any(n.igp == "ospf" for n in g_in):
        log.debug("No OSPF nodes")
        return

    g_ospf.add_nodes_from(g_in.nodes("is_router", igp="ospf"), retain=['asn'])
    g_ospf.add_nodes_from(g_in.nodes("is_switch"), retain=['asn'])
    g_ospf.add_edges_from(g_in.edges(), retain=['edge_id'])

    ank_utils.copy_attr_from(g_in, g_ospf, "ospf_area", dst_attr="area")
    ank_utils.copy_edge_attr_from(g_in,
                                  g_ospf,
                                  "ospf_cost",
                                  dst_attr="cost",
                                  type=float)

    ank_utils.aggregate_nodes(g_ospf,
                              g_ospf.nodes("is_switch"),
                              retain="edge_id")
    exploded_edges = ank_utils.explode_nodes(g_ospf,
                                             g_ospf.nodes("is_switch"),
                                             retain="edge_id")
    for edge in exploded_edges:
        edge.multipoint = True

    g_ospf.remove_edges_from([
        link for link in g_ospf.edges() if link.src.asn != link.dst.asn
    ])  # remove inter-AS links

    area_zero_ip = netaddr.IPAddress("0.0.0.0")
    area_zero_int = 0
    area_zero_ids = {area_zero_ip, area_zero_int}
    default_area = area_zero_int
    if any(router.area == "0.0.0.0" for router in g_ospf):
        # string comparison as hasn't yet been cast to IPAddress
        default_area = area_zero_ip

    for router in g_ospf:
        if not router.area or router.area == "None":
            router.area = default_area
            # check if 0.0.0.0 used anywhere, if so then use 0.0.0.0 as format
        else:
            try:
                router.area = int(router.area)
            except ValueError:
                try:
                    router.area = netaddr.IPAddress(router.area)
                except netaddr.core.AddrFormatError:
                    log.warning("Invalid OSPF area %s for %s. Using default"
                                " of %s" % (router.area, router, default_area))
                    router.area = default_area

    for router in g_ospf:
        # and set area on interface
        for edge in router.edges():
            if edge.area:
                continue  # allocated (from other "direction", as undirected)
            if router.area == edge.dst.area:
                edge.area = router.area  # intra-area
                continue

            if router.area in area_zero_ids or edge.dst.area in area_zero_ids:
                # backbone to other area
                if router.area in area_zero_ids:
                    # router in backbone, use other area
                    edge.area = edge.dst.area
                else:
                    # router not in backbone, use its area
                    edge.area = router.area

    for router in g_ospf:
        areas = {edge.area for edge in router.edges()}
        router.areas = list(areas)  # edges router participates in

        if len(areas) in area_zero_ids:
            router.type = "backbone"  # no ospf edges (eg single node in AS)
        elif len(areas) == 1:
            # single area: either backbone (all 0) or internal (all nonzero)
            if len(areas & area_zero_ids):
                # intersection has at least one element -> router has area zero
                router.type = "backbone"
            else:
                router.type = "internal"

        else:
            # multiple areas
            if len(areas & area_zero_ids):
                # intersection has at least one element -> router has area zero
                router.type = "backbone ABR"
            else:
                log.warning(
                    "%s spans multiple areas but is not a member of area 0" %
                    router)
                router.type = "INVALID"

    if (any(area_zero_int in router.areas for router in g_ospf)
            and any(area_zero_ip in router.areas for router in g_ospf)):
        log.warning("Using both area 0 and area 0.0.0.0")

    for link in g_ospf.edges():
        if not link.cost:
            link.cost = 1

    # map areas and costs onto interfaces
    #TODO: later map them directly rather than with edges - this is part of the transition
    for edge in g_ospf.edges():
        for interface in edge.interfaces():
            interface.cost = edge.cost
            interface.area = edge.area
            interface.multipoint = edge.multipoint

    for router in g_ospf:
        router.loopback_zero.area = router.area
        router.loopback_zero.cost = 0
示例#54
0
    build_vrf(anm)  # do before to add loopbacks before ip allocations
    from autonetkit.design.ip import build_ip, build_ipv4, build_ipv6
    # TODO: replace this with layer2 overlay topology creation
    # log.info("Allocating IP addresses")
    build_ip(anm)  # ip infrastructure topology

    address_family = g_in.data.address_family or "v4"  # default is v4
    # TODO: can remove the infrastructure now create g_ip seperately
    if address_family == "None":
        log.info("IP addressing disabled, disabling routing protocol ",
                 "configuration")
        anm['phy'].data.enable_routing = False

    if address_family == "None":
        log.info("IP addressing disabled, skipping IPv4")
        anm.add_overlay("ipv4")  # create empty so rest of code follows
        g_phy.update(g_phy, use_ipv4=False)
    elif address_family in ("v4", "dual_stack"):
        build_ipv4(anm, infrastructure=True)
        g_phy.update(g_phy, use_ipv4=True)
    elif address_family == "v6":
        # Allocate v4 loopbacks for router ids
        build_ipv4(anm, infrastructure=False)
        g_phy.update(g_phy, use_ipv4=False)

    # TODO: Create collision domain overlay for ip addressing - l2 overlay?
    if address_family == "None":
        log.info("IP addressing disabled, not allocating IPv6")
        anm.add_overlay("ipv6")  # create empty so rest of code follows
        g_phy.update(g_phy, use_ipv6=False)
    elif address_family in ("v6", "dual_stack"):