Beispiel #1
0
 def __init__(self, list_id, access, as_paths):
     assert isinstance(list_id, int)
     assert isinstance(as_paths, Iterable)
     assert isinstance(access, Access)
     if not is_empty(as_paths):
         for as_path in as_paths:
             assert is_empty(as_path) or isinstance(as_path, int)
     self._list_id = list_id
     self._access = access
     self._as_paths = as_paths
Beispiel #2
0
 def __init__(self, prefix, peer, origin,
              as_path, as_path_len, next_hop, local_pref, med, communities,
              permitted, prev_announcement=None):
     """
     :param prefix: the prefix that's being announced
     :param peer: the peer from whom that prefix has been received
                 (this is not technically in the BGP attributes set)
     :param origin: See BGP_ATTRS_ORIGIN
     :param as_path: List of AS numbers
     :param as_path_len: int
     :param next_hop:
         1. If the BGP Peers are in different AS then the next_hop IP address
            that will be sent in the update message will be the IP address of
            the advertising router.
         2. If the BGP peers are in the same AS (IBGP Peers),
             and the destination network being advertised in the update message
             is also in the same AS, then the next_hop IP address that will be sent
             in the update message will be the IP address of the advertising router
         3. If the BGP peers are in the same AS (IBGP Peers),
             and the destination network being advertised in the update message
             is in an external AS, then the next_hop IP address that will be
             sent in the update message will be the IP address of the external
             peer router which sent the advertisement to this AS.
     :param local_pref: is only used in updates sent to the IBGP Peers,
             It is not passed on to the BGP peers in other autonomous systems.
     :param med: MED value, int
     :param communities: dict Community values: Community->True/False
     :param permitted: Access.permit or Access.deny
     :param prev_announcement: keep track of the announcement that generated this one
     """
     #if isinstance(as_path, list):
     #    if not is_symbolic(as_path_len) and not is_empty(as_path_len):
     #        assert len(as_path) == as_path_len
     if prev_announcement:
         assert isinstance(prev_announcement, Announcement)
     assert is_symbolic or not is_empty(as_path)
     if not is_symbolic(as_path):
         for asnum in as_path:
             assert not is_empty(asnum)
     self.prefix = prefix
     self.peer = peer
     self.origin = origin
     self.as_path = as_path
     self.as_path_len = as_path_len
     self.next_hop = next_hop
     self.local_pref = local_pref
     self.med = med
     self.communities = communities
     self.permitted = permitted
     self.prev_announcement = prev_announcement
     self.__setattr__ = self._disable_mutations
Beispiel #3
0
 def gen_route_map(self, node, routemap):
     assert isinstance(routemap, RouteMap)
     config = ''
     name = routemap.name
     for line in routemap.lines:
         if is_empty(line.lineno) or is_empty(line.access):
             continue
         no = line.lineno
         access = line.access.value if hasattr(line.access, 'value') else Access.permit
         config += "route-map %s %s %s\n" % (name, access, no)
         for match in line.matches:
             config += " %s\n" % self.gen_route_map_match(node, match)
         for action in line.actions:
             config += " %s\n" % self.gen_route_map_action(action)
     return config
Beispiel #4
0
 def set_bgp_router_id(self, node, router_id):
     """Sets the BGP router ID of a given router"""
     assert self.is_bgp_enabled(node)
     if not is_empty(router_id) and not is_symbolic(router_id):
         assert isinstance(router_id, (int, ipaddress.IPv4Address))
         if isinstance(router_id, int):
             assert router_id > 0
     self.get_bgp_attrs(node)['router_id'] = router_id
Beispiel #5
0
    def synthesize_connection(self, src, dst):
        """Synthesize connection between two routers"""
        err = "Routers (%s, %s) are not directly connected" % (src, dst)
        assert self.network_graph.has_edge(src, dst), err
        iface1 = self.network_graph.get_edge_iface(src, dst)
        iface2 = self.network_graph.get_edge_iface(dst, src)
        # Make sure interfaces are up
        if self.full and self.network_graph.is_iface_shutdown(src, iface1):
            raise InterfaceIsDownError(src, iface1)
        if self.full and self.network_graph.is_iface_shutdown(dst, iface2):
            raise InterfaceIsDownError(src, iface2)
        addr1 = self.network_graph.get_iface_addr(src, iface1)
        addr2 = self.network_graph.get_iface_addr(dst, iface2)
        err1 = "Address not set and not a hole for iface: %s-%s" % (src, iface1)
        err2 = "Address not set and not a hole for iface: %s-%s" % (dst, iface2)
        assert addr1, err1
        assert addr2, err2

        # Get the subnet for both ends of the line
        if is_empty(addr1) and is_empty(addr2):
            # No initial config is given
            # Then synthesize completely new subnet
            net1 = self._next_net
            self._next_net = self.get_next_net(net1)
            net2 = net1
        elif is_empty(addr1) or is_empty(addr2):
            # Only one side is concrete
            net = addr1.network if not is_empty(addr1) else addr2.network
            net1 = net
            net2 = net
        else:
            # Both sides are concrete
            net1 = addr1.network
            net2 = addr2.network

        # The two interfaces must have the same network
        if net1 != net2:
            raise NotValidSubnetsError(src, iface1, net1, dst, iface2, net2)

        # Assign IP addresses to the first interface (if needed)
        if is_empty(addr1):
            for host in net1.hosts():
                addr = ip_interface(u"%s/%d" % (host, net1.prefixlen))
                if addr == addr2:
                    continue
                addr1 = addr
                self.network_graph.set_iface_addr(src, iface1, addr)
                break
        # Assign IP addresses to the second interface (if needed)
        if is_empty(addr2):
            for host in net2.hosts():
                addr = ip_interface(u"%s/%d" % (host, net2.prefixlen))
                if addr != addr1:
                    addr2 = addr
                    self.network_graph.set_iface_addr(dst, iface2, addr)
                    break
        # The interfaces must have unique IP addresses
        if addr1 == addr2:
            raise DuplicateAddressError(src, iface1, addr1, dst, iface2, addr2)
        assert iface1
Beispiel #6
0
 def __init__(self, communities, additive=True):
     """
     Set a list of communities to a route
     :param communities: list of Community
     :param additive:
     """
     assert isinstance(communities, Iterable)
     for community in communities:
         assert is_empty(community) or isinstance(community, Community)
     self._communities = communities
     self._additive = additive
Beispiel #7
0
 def _check_announce_prefix(self, node, prefix, protocol):
     if protocol == Protocols.OSPF:
         if is_empty(prefix):
             self.log.warn("Using unknown prefix to node %s", node)
             return True
         if not self.topo.is_ospf_enabled(node):
             return False
         if prefix not in self.topo.get_ospf_networks(node):
             return False
     else:
         raise ValueError("Unknown protocol value {}".format(protocol))
     return True
Beispiel #8
0
 def compute_bgp_peerings(self):
     for node in self.network_graph.routers_iter():
         if not self.network_graph.get_bgp_asnum(node):
             # BGP is not configured on this router
             continue
         neighbors = self.network_graph.get_bgp_neighbors(node)
         for neighbor in neighbors:
             iface = self.network_graph.get_bgp_neighbor_iface(node, neighbor)
             if is_empty(iface):
                 iface = self.synthesize_next_hop(node, neighbor)
             self.network_graph.set_bgp_neighbor_iface(node, neighbor, iface)
             assert iface, "Synthesize connected first"
Beispiel #9
0
 def add_static_route(self, node, prefix, next_hop):
     """
     Set a static route
     :param node: Router
     :param prefix: Prefixed to be routed
     :param next_hop: Router
     :return:
     """
     attrs = self.get_static_routes(node)
     if is_empty(attrs):
         self.node[node]['static'] = {}
     self.node[node]['static'][prefix] = next_hop
Beispiel #10
0
 def set_loopback_addr(self, node, loopback, addr):
     """
     Assigns an IP address to a loopback interface
     :param node: name of the router
     :param loopback: name of loopback interface. e.graph., lo0, lo1, etc..
     :param addr: an instance of ipaddress.IPv4Interface or ipaddress.IPv6Interface
     :return: None
     """
     assert is_valid_add(addr)
     loopbacks = self.get_loopback_interfaces(node)
     if loopback not in loopbacks:
         loopbacks[loopback] = {}
     assert is_empty(loopbacks[loopback].get('addr', None)), loopbacks[loopback].get('addr', None)
     loopbacks[loopback]['addr'] = addr
Beispiel #11
0
 def assign_loop_back_addresses(self):
     for node in sorted(self.network_graph.routers_iter()):
         loopbacks = self.network_graph.get_loopback_interfaces(node)
         for loopback in loopbacks:
             if not is_empty(self.network_graph.get_loopback_addr(node, loopback)):
                 continue
             net = self._next_lo_net
             self._next_lo_net = self.get_next_net(net)
             ipaddr = None
             for ipaddr in net.hosts():
                 break
             if not ipaddr:
                 ipaddr = net.network_address
             addr = ip_interface(ipaddr)
             self.network_graph.set_loopback_addr(node, loopback, addr)
Beispiel #12
0
 def gen_route_map_match(self, node, match):
     config = ''
     if isinstance(match, MatchCommunitiesList):
         if match.match.list_id in self._empty_community_lists.get(
                 node, []):
             err = "Community list id {} is used in a match but it's empty".format(
                 match.match.list_id)
             assert False, err
         config += 'match community %d' % match.match.list_id
     elif isinstance(match, MatchIpPrefixListList):
         name = match.match.name
         ips = self.g.get_ip_preflix_lists(node)
         err = "IP list '%s' is not registered at Node '%s': %s" % (
             name, node, ips)
         assert name in ips, err
         if not all([is_empty(p) for p in ips[match.match.name].networks]):
             config += 'match ip address prefix-list %s' % match.match.name
     elif isinstance(match, MatchAsPath):
         list_no = None
         for tmp in self.g.get_as_path_list(node).values():
             if tmp.as_paths == match.match:
                 list_no = tmp.list_id
         if not list_no:
             list_no = next(self._next_as_paths[node])
             as_path = ASPathList(list_id=list_no,
                                  access=Access.permit,
                                  as_paths=match.match)
             self.g.add_as_path_list(node, as_path)
         config += 'match as-path %s' % list_no
     elif isinstance(match, MatchNextHop):
         next_hop = match.match
         parsed = None
         if isinstance(next_hop, basestring):
             if '_DASH_' in next_hop:
                 parsed = next_hop.split('_DASH_')
             else:
                 parsed = next_hop.split('-')
         if parsed and self.g.has_node(parsed[0]):
             router = parsed[0]
             iface = '/'.join(parsed[1:])
             next_hop = self.g.get_interface_loop_addr(router, iface)
             self.prefix_map[match.match] = next_hop
         if hasattr(next_hop, 'ip'):
             next_hop = next_hop.ip
         config += 'match ip next-hop %s' % next_hop
     else:
         raise ValueError('Unknown match type %s' % match)
     return config
Beispiel #13
0
 def gen_static_routes(self, node):
     config = ""
     static_routes = self.g.get_static_routes(node)
     if not static_routes or is_empty(static_routes):
         return config
     for prefix, next_hop in static_routes.iteritems():
         net = self.prefix_lookup(prefix)
         if self.g.is_router(next_hop):
             iface = self.g.get_edge_iface(next_hop, node)
             addr = self.g.get_iface_addr(next_hop, iface)
             nhop_addr = addr.ip
         else:
             nhop_addr = next_hop
         config += "ip route %s %s %s\n" % (net.network_address, net.netmask, nhop_addr)
     config += "!\n"
     return config
Beispiel #14
0
    def __init__(self, matches, actions, access, lineno=None):
        if matches is None:
            matches = []
        if actions is None:
            actions = []
        assert isinstance(matches, Iterable)
        assert isinstance(actions, Iterable)
        for match in matches:
            assert isinstance(match, Match), "Expected a match but found %s" % match
        for action in actions:
            assert isinstance(action, Action)
        assert is_empty(access) or isinstance(access, Access)

        self._matches = matches
        self._actions = actions
        self._access = access
        self._lineno = lineno
Beispiel #15
0
 def gen_acl(self, node):
     config = ""
     acl_lists = self.g.get_acls(node)
     # print("acl lists", acl_lists)
     if not acl_lists or is_empty(acl_lists):
         return config
     for inface in acl_lists:
         for acl_num in acl_lists[inface]:
             acl_content = acl_lists[inface][acl_num]
             for item in acl_content[1:]:
                 # could be extended later for more acl formats
                 if len(item) == 5:
                     #item = (state, src_ip, src_mask, dst_ip, src_mask)
                     config += "access-list " + str(acl_num) + " " + str(item[0]) + " ip " + str(item[1]) + " " + str(item[2]) \
                               + " " + str(item[3]) + " " + str(item[4]) + "\n"
             config += "access-list " + str(acl_num) + " permit any\n"
     return config
Beispiel #16
0
 def gen_community_list(self, node, community_list):
     """
     Generate config lines for community list
     :param community_list:
     :return: configs string
     """
     assert isinstance(community_list, CommunityList)
     config = ''
     list_id = community_list.list_id
     access = community_list.access.value
     communities = [c.value for c in community_list.communities if not is_empty(c)]
     if communities:
         config += "ip community-list %d %s %s\n" % (list_id, access, ' '.join(communities))
     else:
         if node not in self._empty_community_lists:
             self._empty_community_lists[node] = []
         self._empty_community_lists[node].append(list_id)
     return config
Beispiel #17
0
 def add_acl(self, node, interface, inout, acl_number=None):
     """
     add Access_List
     :param node: Router
     :param interface: interface name
     :param inout: 'in' or 'out'
     """
     attrs = self.get_acls(node)
     if is_empty(attrs):
         self.node[node]['acls'] = {}
     if interface not in self.node[node]['acls']:
         self.node[node]['acls'][interface] = {}
     if not acl_number:
         if not self.node[node]['acls'][interface]:
             acl_number = random.randint(0, 20)
         else:
             max_num = max(self.node[node]['acls'][interface],
                           key=self.node[node]['acls'][interface].get)
             acl_number = max_num + 1
     self.node[node]['acls'][interface][acl_number] = [inout]
     return acl_number
Beispiel #18
0
    def test_one_side_concrete(self):
        # Arrange
        graph = self.get_two_nodes()
        addr1 = ip_interface(u"192.168.0.1/24")
        # Set Iface for R1 to R2
        iface = 'Fa0/0'
        graph.add_iface('R1', iface, is_shutdown=False)
        graph.set_iface_addr('R1', iface, addr1)
        graph.set_edge_iface('R1', 'R2', iface)
        graph.set_iface_description('R1', iface, '' "To {}" ''.format('R2'))

        # Set Iface for R2 to R1
        iface = 'Fa0/0'
        graph.add_iface('R2', iface, is_shutdown=False)
        graph.set_iface_addr('R2', iface, VALUENOTSET)
        graph.set_edge_iface('R2', 'R1', iface)
        graph.set_iface_description('R2', iface, '' "To {}" ''.format('R1'))
        # Act
        syn = ConnectedSyn(graph, full=True)
        syn.synthesize()
        # Assert
        self.assertFalse(is_empty(graph.get_iface_addr('R2', iface)))
Beispiel #19
0
 def gen_ip_prefix_list(self, node, prefix_list):
     """
     Generate config lines for ip prefix-list
     :param prefix_list:
     :return: configs string
     """
     assert isinstance(prefix_list, IpPrefixList)
     config = ''
     access = prefix_list.access.value
     networks = prefix_list.networks
     name = prefix_list.name
     for i, network in enumerate(networks):
         if is_empty(network):
             continue
         network = self.prefix_lookup(network)
         lineno = (i + 1) * 10
         network = ip_network(str(network))
         addr = str(getattr(network, 'network_address', network))
         prefixlen = getattr(network, 'prefixlen', 32)
         config += "ip prefix-list %s seq %d %s %s/%d\n" % (
             name, lineno, access, addr, prefixlen)
     return config
Beispiel #20
0
 def _check_ospf_announced(self, router, iface):
     """Return True if the address is announced over OSPF"""
     addr = self.topo.get_interface_loop_addr(router, iface)
     assert not is_empty(addr)
     routers = [(router, iface)]
     # Maybe the neighbor is announcing it
     for neighbor in self.topo.neighbors(router):
         if not self.topo.is_router(neighbor):
             continue
         if iface != self.topo.get_edge_iface(router, neighbor):
             continue
         routers.append(
             (neighbor, self.topo.get_edge_iface(neighbor, router)))
     for router, iface in routers:
         if not self.topo.is_ospf_enabled(router):
             continue
         for network in self.topo.get_ospf_networks(router):
             if not isinstance(network, (IPv4Network, IPv6Network)):
                 if iface == network:
                     return True
             elif addr in network:
                 return True
     return False
Beispiel #21
0
    def gen_all_interface_configs(self, node):
        """
        Iterate over all interfaces (including loopbacks) to generate their configs
        :param node: router name
        :return: string configs
        """
        config = ''
        for neighbor in self.g.neighbors(node):
            iface = self.g.get_edge_iface(node, neighbor)

            acl_declare = None
            acl_lists = self.g.get_acls(node)
            if acl_lists and not is_empty(acl_lists):
                if iface in acl_lists:
                    acl_declare = []
                    for acl_num in acl_lists[iface]:
                        print("acl_num", acl_num)
                        acl_content = acl_lists[iface][acl_num]
                        acl_declare.append((str(acl_num), acl_content[0]))

            #addr = self.graph.get_edge_addr(node, neighbor)
            addr = self.g.get_iface_addr(node, iface)
            desc = self.g.get_iface_description(node, iface)
            if self.g.is_ospf_enabled(node) and self.g.is_ospf_enabled(
                    neighbor):
                ospf_cost = self.g.get_edge_ospf_cost(node, neighbor)
            else:
                ospf_cost = None
            config += self.gen_iface_config(node, iface, addr, desc, False,
                                            ospf_cost, acl_declare)

        # Loop back interface
        for lo in sorted(self.g.get_loopback_interfaces(node)):
            addr = self.g.get_loopback_addr(node, lo)
            desc = self.g.get_loopback_description(node, lo)
            config += self.gen_iface_config(node, lo, addr, desc, True, None)
        return config
Beispiel #22
0
 def __init__(self, as_path):
     assert is_empty(as_path) or isinstance(as_path, Iterable)
     self._value = as_path
Beispiel #23
0
 def __init__(self, next_hop):
     assert is_empty(next_hop) or isinstance(next_hop, basestring)
     self._value = next_hop
Beispiel #24
0
 def __init__(self, prefix):
     assert is_empty(prefix) or isinstance(prefix, basestring)
     self._value = prefix
Beispiel #25
0
 def access(self, value):
     """Set to drop to allow (see Access)"""
     if not is_empty(self._access):
         raise ValueError("Access already set to %s" % self._access)
     assert isinstance(value, Access)
     self._access = value
Beispiel #26
0
 def __init__(self, as_path_len):
     assert is_empty(as_path_len) or isinstance(as_path_len, int)
     self._value = as_path_len
Beispiel #27
0
 def __eq__(self, other):
     if is_empty(self._value):
         return False
     return self.value == getattr(other, 'value', None)
Beispiel #28
0
 def value(self, value):
     if not is_empty(self._value):
         raise ValueError("Value already set to %s" % str(self._value))
     self._value = value
Beispiel #29
0
 def __init__(self, med):
     assert is_empty(med) or isinstance(med, int)
     self._value = med
Beispiel #30
0
 def __init__(self, peer):
     assert is_empty(peer) or isinstance(peer, basestring)
     self._value = peer