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.routers()) 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.switches() if not ank_utils.neigh_equal(g_phy, n, "asn")] g_ebgp.add_nodes_from(ebgp_switches, retain=['asn']) g_ebgp.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) # need to recalculate as may have aggregated ebgp_switches = list(g_ebgp.switches()) g_ebgp.log.debug("aggregated eBGP switches are %s" % ebgp_switches) exploded_edges = ank_utils.explode_nodes(g_ebgp, ebgp_switches) same_asn_edges = [] for edge in exploded_edges: if edge.src.asn == edge.dst.asn: same_asn_edges.append(edge) else: edge.multipoint = True """TODO: remove up to here once compiler updated""" g_ebgp.remove_edges_from(same_asn_edges)
def build_layer3(anm): """ l3_connectivity graph: switch nodes aggregated and exploded""" g_in = anm['input'] gl2_conn = anm['layer2_conn'] g_l3 = anm.add_overlay("layer3") g_l3.add_nodes_from(gl2_conn, retain=['label']) g_l3.add_nodes_from(g_in.switches(), retain=['asn']) g_l3.add_edges_from(gl2_conn.edges()) switches = g_l3.switches() ank_utils.aggregate_nodes(g_l3, switches) exploded_edges = ank_utils.explode_nodes(g_l3, switches) # also explode virtual switches vswitches = [ n for n in g_l3.nodes() if n['layer2'].device_type == "switch" and n['layer2'].device_subtype == "virtual" ] # explode each seperately? for edge in exploded_edges: edge.multipoint = True edge.src_int.multipoint = True edge.dst_int.multipoint = True
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
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") # need to recalculate as may have aggregated ebgp_switches = list(g_ebgp.nodes("is_switch")) log.debug("aggregated eBGP switches are %s" % ebgp_switches) exploded_edges = ank_utils.explode_nodes(g_ebgp, ebgp_switches, retain="edge_id") same_asn_edges = [] for edge in exploded_edges: if edge.src.asn == edge.dst.asn: same_asn_edges.append(edge) else: edge.multipoint = True """TODO: remove up to here once compiler updated""" g_ebgp.remove_edges_from(same_asn_edges)
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
def build_layer3(anm): """ l3_connectivity graph: switch nodes aggregated and exploded""" g_in = anm['input'] g_l2 = anm['layer2'] g_l3 = anm.add_overlay("layer3") g_l3.add_nodes_from(g_l2, retain=['label']) g_l3.add_nodes_from(g_in.switches(), retain=['asn']) g_l3.add_edges_from(g_l2.edges()) switches = g_l3.switches() ank_utils.aggregate_nodes(g_l3, switches) exploded_edges = ank_utils.explode_nodes(g_l3, switches) # also explode virtual switches vswitches = [n for n in g_l3.nodes() if n['layer2'].device_type == "switch" and n['layer2'].device_subtype == "virtual"] # explode each seperately? for edge in exploded_edges: edge.multipoint = True edge.src_int.multipoint = True edge.dst_int.multipoint = True
def build_layer3(anm): """ l3_connectivity graph: switch nodes aggregated and exploded""" g_in = anm['input'] gl2_conn = anm['layer2_conn'] g_l3 = anm.add_overlay("layer3") g_l3.add_nodes_from(gl2_conn, retain=['label', 'devsubtype']) ank_utils.copy_attr_from(g_in, g_l3, "multicast") g_l3.add_nodes_from(g_in.switches(), retain=['asn']) g_l3.add_edges_from(gl2_conn.edges(), retain=['link_type']) edges_to_remove = [ edge for edge in gl2_conn.edges() if edge.link_type == 'is_not_l3' ] g_l3.remove_edges_from(edges_to_remove) edges_to_remove = [] switches = g_l3.switches() ank_utils.aggregate_nodes(g_l3, switches) exploded_edges = ank_utils.explode_nodes(g_l3, switches, retain=['link_type']) # also explode virtual switches vswitches = [ n for n in g_l3.nodes() if n['layer2'].device_type == "switch" and n['layer2'].device_subtype == "virtual" ] # explode each seperately? for edge in exploded_edges: edge.multipoint = True edge.src_int.multipoint = True edge.dst_int.multipoint = True
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_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
def build_layer1_conn(anm): g_l1 = anm['layer1'] g_l1_conn = anm.add_overlay('layer1_conn') g_l1_conn.add_nodes_from(g_l1, retain="collision_domain") g_l1_conn.add_edges_from(g_l1.edges()) collision_domains = g_l1_conn.nodes(collision_domain=True) exploded_edges = ank_utils.explode_nodes(g_l1_conn, collision_domains) # explode each seperately? for edge in exploded_edges: edge.multipoint = True edge.src_int.multipoint = True edge.dst_int.multipoint = True
def build_layer1_conn(anm): g_l1 = anm['layer1'] g_l1_conn = anm.add_overlay('layer1_conn') g_l1_conn.add_nodes_from(g_l1, retain="collision_domain") g_l1_conn.add_edges_from(g_l1.edges(), retain=['link_type']) collision_domains = g_l1_conn.nodes(collision_domain=True) exploded_edges = ank_utils.explode_nodes(g_l1_conn, collision_domains, retain=['link_type']) # explode each seperately? for edge in exploded_edges: edge.multipoint = True edge.src_int.multipoint = True edge.dst_int.multipoint = True
def build_layer2_conn(anm): g_l2 = anm['layer2'] g_l2_conn = anm.add_overlay('layer2_conn') g_l2_conn.add_nodes_from(g_l2, retain="broadcast_domain") g_l2_conn.add_edges_from(g_l2.edges()) broadcast_domains = g_l2_conn.nodes(broadcast_domain=True) exploded_edges = ank_utils.explode_nodes(g_l2_conn, broadcast_domains) # explode each seperately? for edge in exploded_edges: edge.multipoint = True edge.src_int.multipoint = True edge.dst_int.multipoint = True
def build_layer2_conn(anm): g_l2 = anm['layer2'] g_l2_conn = anm.add_overlay('layer2_conn') g_l2_conn.add_nodes_from(g_l2, retain=["broadcast_domain", "devsubtype"]) g_l2_conn.add_edges_from(g_l2.edges(), retain=['link_type']) broadcast_domains = g_l2_conn.nodes(broadcast_domain=True) exploded_edges = ank_utils.explode_nodes(g_l2_conn, broadcast_domains, retain=['link_type']) # explode each seperately? for edge in exploded_edges: edge.multipoint = True edge.src_int.multipoint = True edge.dst_int.multipoint = True
def build_isis(anm): """Build isis overlay""" g_in = anm['input'] 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") ank_utils.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_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
def build_layer3(anm): """ l3_connectivity graph: switch nodes aggregated and exploded""" g_in = anm['input'] g_l2 = anm['layer2'] g_l3 = anm.add_overlay("layer3") g_l3.add_nodes_from(g_l2, retain=['label']) g_l3.add_nodes_from(g_in.switches(), retain=['asn']) g_l3.add_edges_from(g_in.edges()) ank_utils.aggregate_nodes(g_l3, g_l3.switches()) exploded_edges = ank_utils.explode_nodes(g_l3, g_l3.switches()) for edge in exploded_edges: edge.multipoint = True edge.src_int.multipoint = True edge.dst_int.multipoint = True
def build_layer3(anm): """ l3_connectivity graph: switch nodes aggregated and exploded""" g_in = anm['input'] g_l2 = anm['layer2'] g_l3 = anm.add_overlay("layer3") g_l3.add_nodes_from(g_l2 , retain=['label']) g_l3.add_nodes_from(g_in.switches(), retain=['asn']) g_l3.add_edges_from(g_in.edges()) ank_utils.aggregate_nodes(g_l3, g_l3.switches()) exploded_edges = ank_utils.explode_nodes(g_l3, g_l3.switches()) for edge in exploded_edges: edge.multipoint = True edge.src_int.multipoint = True edge.dst_int.multipoint = True
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
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
def build_eigrp(anm): """Build eigrp overlay""" g_in = anm['input'] # add regardless, so allows quick check of node in anm['isis'] in compilers g_eigrp = anm.add_overlay("eigrp") if not anm['phy'].data.enable_routing: log.info("Routing disabled, not configuring EIGRP") return if not any(n.igp == "eigrp" for n in g_in): log.debug("No EIGRP nodes") return g_ipv4 = anm['ipv4'] g_eigrp.add_nodes_from(g_in.nodes("is_router", igp = "eigrp"), retain=['asn']) g_eigrp.add_nodes_from(g_in.nodes("is_server", igp = "eigrp"), retain=['asn']) g_eigrp.add_nodes_from(g_in.nodes("is_switch"), retain=['asn']) g_eigrp.add_edges_from(g_in.edges(), retain=['edge_id']) # Merge and explode switches ank_utils.aggregate_nodes(g_eigrp, g_eigrp.nodes("is_switch"), retain="edge_id") exploded_edges = ank_utils.explode_nodes(g_eigrp, g_eigrp.nodes("is_switch"), retain="edge_id") for edge in exploded_edges: edge.multipoint = True g_eigrp.remove_edges_from( [link for link in g_eigrp.edges() if link.src.asn != link.dst.asn]) for node in g_eigrp: ip_node = g_ipv4.node(node) node.net = ip_to_net_ent_title_ios(ip_node.loopback) node.name = "one" # default for link in g_eigrp.edges(): link.metric = 1 # default for edge in g_eigrp.edges(): for interface in edge.interfaces(): interface.metric = edge.metric interface.multipoint = edge.multipoint
def build_eigrp(anm): """Build eigrp overlay""" g_in = anm['input'] # add regardless, so allows quick check of node in anm['isis'] in compilers g_l3 = anm['layer3'] g_eigrp = anm.add_overlay("eigrp") g_phy = anm['phy'] if not anm['phy'].data.enable_routing: g_eigrp.log.info("Routing disabled, not configuring EIGRP") return if not any(n.igp == "eigrp" for n in g_phy): log.debug("No EIGRP nodes") return eigrp_nodes = [n for n in g_l3 if n['phy'].igp == "eigrp"] g_eigrp.add_nodes_from(eigrp_nodes) g_eigrp.add_edges_from(g_l3.edges(), warn=False) ank_utils.copy_int_attr_from(g_l3, g_eigrp, "multipoint") ank_utils.copy_attr_from(g_in, g_eigrp, "custom_config_eigrp", dst_attr="custom_config") # Merge and explode switches ank_utils.aggregate_nodes(g_eigrp, g_eigrp.switches()) exploded_edges = ank_utils.explode_nodes(g_eigrp, g_eigrp.switches()) for edge in exploded_edges: edge.multipoint = True g_eigrp.remove_edges_from( [link for link in g_eigrp.edges() if link.src.asn != link.dst.asn]) for node in g_eigrp: node.process_id = node.asn for link in g_eigrp.edges(): link.metric = 1 # default for edge in g_eigrp.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
def build_eigrp(anm): """Build eigrp overlay""" g_in = anm['input'] # add regardless, so allows quick check of node in anm['isis'] in compilers g_l3 = anm['layer3'] g_eigrp = anm.add_overlay("eigrp") g_phy = anm['phy'] if not anm['phy'].data.enable_routing: g_eigrp.log.info("Routing disabled, not configuring EIGRP") return if not any(n.igp == "eigrp" for n in g_phy): log.debug("No EIGRP nodes") return eigrp_nodes = [n for n in g_l3 if n['phy'].igp == "eigrp"] g_eigrp.add_nodes_from(eigrp_nodes) g_eigrp.add_edges_from(g_l3.edges(), warn=False) ank_utils.copy_int_attr_from(g_l3, g_eigrp, "multipoint") ank_utils.copy_attr_from( g_in, g_eigrp, "custom_config_eigrp", dst_attr="custom_config") # Merge and explode switches ank_utils.aggregate_nodes(g_eigrp, g_eigrp.switches()) exploded_edges = ank_utils.explode_nodes(g_eigrp, g_eigrp.switches()) for edge in exploded_edges: edge.multipoint = True g_eigrp.remove_edges_from( [link for link in g_eigrp.edges() if link.src.asn != link.dst.asn]) for node in g_eigrp: node.process_id = node.asn for link in g_eigrp.edges(): link.metric = 1 # default for edge in g_eigrp.edges(): for interface in edge.interfaces(): interface.metric = edge.metric interface.multipoint = edge.multipoint
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
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
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
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 anm['phy'].data.enable_routing: g_isis.log.info("Routing disabled, not configuring ISIS") return if not any(n.igp == "isis" for n in g_in): g_isis.log.debug("No ISIS nodes") return g_ipv4 = anm['ipv4'] g_isis.add_nodes_from(g_in.l3devices(igp="isis"), retain=['asn']) g_isis.add_nodes_from(g_in.switches(), retain=['asn']) g_isis.add_edges_from(g_in.edges()) # Merge and explode switches ank_utils.aggregate_nodes(g_isis, g_isis.switches()) exploded_edges = ank_utils.explode_nodes(g_isis, g_isis.switches()) 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.routers(): 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
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 anm['phy'].data.enable_routing: g_isis.log.info("Routing disabled, not configuring ISIS") return if not any(n.igp == "isis" for n in g_in): g_isis.log.debug("No ISIS nodes") return g_ipv4 = anm['ipv4'] g_isis.add_nodes_from(g_in.l3devices(igp = "isis"), retain=['asn']) g_isis.add_nodes_from(g_in.switches(), retain=['asn']) g_isis.add_edges_from(g_in.edges()) # Merge and explode switches ank_utils.aggregate_nodes(g_isis, g_isis.switches()) exploded_edges = ank_utils.explode_nodes(g_isis, g_isis.switches()) 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.routers(): 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
def build_bgp(anm): """Build iBGP end eBGP overlays""" # eBGP g_in = anm['input'] g_phy = anm['phy'] if not anm['phy'].data.enable_routing: log.info("Routing disabled, not configuring BGP") return 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") same_asn_edges = [] for edge in exploded_edges: if edge.src.asn == edge.dst.asn: same_asn_edges.append(edge) else: edge.multipoint = True """TODO: remove up to here once compiler updated""" g_bgp.remove_edges_from(same_asn_edges) # 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: #TODO: check when this is reached - as RR is not HRR.... due to naming/levels mapping 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)
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
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)
def build_bgp(anm): """Build iBGP end eBGP overlays""" # eBGP g_in = anm['input'] g_phy = anm['phy'] if not anm['phy'].data.enable_routing: log.info("Routing disabled, not configuring BGP") return 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.routers()) 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') ebgp_switches = [n for n in g_in.switches() 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) ebgp_switches = list(g_bgp.switches()) # 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) same_asn_edges = [] for edge in exploded_edges: if edge.src.asn == edge.dst.asn: same_asn_edges.append(edge) else: edge.multipoint = True """TODO: remove up to here once compiler updated""" g_bgp.remove_edges_from(same_asn_edges) build_ibgp(anm) 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)
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_server", 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 #TODO: use interfaces throughout, rather than edges 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
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) """ import netaddr G_in = anm['input'] G_ospf = anm.add_overlay("ospf") G_ospf.add_nodes_from(G_in.nodes("is_router"), 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.copy_attr_from(G_in, G_ospf, "ospf_area", dst_attr = "area") #TODO: move this into graphml (and later gml) reader ank.aggregate_nodes(G_ospf, G_ospf.nodes("is_switch"), retain = "edge_id") ank.explode_nodes(G_ospf, G_ospf.nodes("is_switch"), retain= "edge_id") 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 = set([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": #TODO: tidy up this default of None being a string router.area = default_area #TODO: could check if 0.0.0.0 used anywhere, if so then use 0.0.0.0 as base 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 # already allocated (from other "direction", as undirected) if router.area == edge.dst.area: edge.area = router.area # intra-area else: 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: edge.area = edge.dst.area # router in backbone, use other area else: edge.area = router.area # router not in backbone, use its area for router in G_ospf: areas = set(edge.area for edge in router.edges()) router.areas = list(areas) # store all the edges a router participates in if len(areas) in area_zero_ids: router.type = "backbone" # no ospf edges (such as 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") #TODO: do we want to allocate non-symmetric OSPF costs? do we need a directed OSPF graph? # (note this will all change once have proper interface nodes) for link in G_ospf.edges(): link.cost = 1
def build_bgp(anm): """Build iBGP end eBGP overlays""" # eBGP g_in = anm['input'] g_phy = anm['phy'] if not anm['phy'].data.enable_routing: log.info("Routing disabled, not configuring BGP") return 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.routers()) ebgp_edges = [edge for edge in g_in.edges() if edge.src.asn != edge.dst.asn] g_bgp.add_edges_from(ebgp_edges, bidirectional=True, type='ebgp') ebgp_switches = [n for n in g_in.switches() 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) ebgp_switches = list(g_bgp.switches()) # 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) same_asn_edges = [] for edge in exploded_edges: if edge.src.asn == edge.dst.asn: same_asn_edges.append(edge) else: edge.multipoint = True """TODO: remove up to here once compiler updated""" ank_utils.copy_attr_from(g_in, g_bgp, "custom_config_bgp", dst_attr="custom_config") g_bgp.remove_edges_from(same_asn_edges) build_ibgp(anm) 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)
def build_bgp(anm): """Build iBGP end eBGP overlays""" # eBGP g_in = anm["input"] g_phy = anm["phy"] 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 # 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", 3: "RR", 1: "RRC", 2: "HRR"} # Explicitly set role to "None" -> Not in iBGP 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())