Ejemplo n.º 1
0
    def add_link(self,
                 node,
                 voisin,
                 config_node,
                 config_voisin,
                 link_type='share',
                 **kwargs):
        """
            Add a physical link between 2 devices (routers, hosts, anycast servers). 
            Arguments :
                - node / voisin : name of devices to link. 
                - config_node   : config of node for the link. 
                - config_voisin : config of voisin for the link. 
                - link_type     : used if as of node and voisin are not the same. 
            
            Note : if AS of the 2 devices are not the same, add an eBGP connection. 
        """
        as_1, as_2 = self.get_as_of(node), self.get_as_of(voisin)
        node, voisin = self.get(node), self.get(voisin)

        config_node = config_node.copy()

        ip1, ip2 = config_node.pop('ip', None), config_voisin.pop('ip', None)

        if 'subnet' in config_voisin:
            subnet = config_voisin.pop('subnet')
            if isinstance(subnet, dict):
                subnet = format_address(subnet, self.__prefixes)
            ip1, ip2 = subnet
        elif self.infer_ip_link:
            generated_ips = self.generate_ip(node, 2, 1)
            if generated_ips:
                ip1, ip2 = generated_ips

        kwargs = {**config_node, **config_voisin}
        if ip1 is not None:
            kwargs.setdefault('params1', {})
            kwargs['params1']['ip'] = ip1
        if ip2 is not None:
            kwargs.setdefault('params2', {})
            kwargs['params2']['ip'] = ip2

        if self.debug:
            print("Adding link between {} and {} with config : {}".format(
                node, voisin, kwargs))

        link = self.addLink(node, voisin, **kwargs)

        if as_1 != as_2:
            self.add_ebgp_session(node, voisin, as_1, as_2, link_type)

        return link
Ejemplo n.º 2
0
    def _build_anycast_servers(self, as_name, anycast, as_routers):
        rr_levels = []
        for r_name, r_config in as_routers.items():
            rr_levels.append(
                r_config.get('niveau', 1)
                if 'clients' in r_config or 'peers' in r_config else 0)
        anycast_rr_level = max(rr_levels) + 1

        for anycast_config in anycast:
            anycast_address = anycast_config['addresses']
            anycast_address = tuple(
                format_address(anycast_address, self.__prefixes))

            self.__anycast.setdefault(anycast_address, [])

            if self.debug:
                print("Adding anycast address : {}".format(anycast_address))

            for node in anycast_config.get('nodes', []):
                server_name = 'server_{}'.format(
                    len(self.__anycast_servers) + 1)
                self.__as[as_name]['anycast_servers'][
                    server_name] = anycast_address
                self.__anycast[anycast_address].append((node, server_name))

                s_config = {'lo_addresses': anycast_address}

                if self.debug:
                    print("Adding server {} to this anycast address".format(
                        server_name))

                server = self.addRouter(server_name,
                                        config=RouterConfig,
                                        **s_config)
                self.add_daemons(server,
                                 {'bgp': anycast_config.get('bgp_config', {})},
                                 {})

                self.__anycast_servers[server_name] = server

                self.add_new_link(server_name, node)

                # Add the node to the clients of the router
                if 'clients' not in as_routers[
                        node] and 'peers' not in as_routers[node]:
                    as_routers[node].setdefault('niveau', anycast_rr_level)
                as_routers[node].setdefault('clients', [])
                as_routers[node]['clients'].append(server_name)

                subnet = self.get_subnet_of(node)
                if subnet is not None:
                    self.__subnets[subnet]['nodes'].append(server_name)
Ejemplo n.º 3
0
    def _build_routers(self, as_name, routers, **default_config):
        default_daemons = default_config.pop('daemons', [])

        for r_name, r_config in routers.items():
            self.__as[as_name]['routers'].append(r_name)

            r_config = {**default_config, **r_config}
            if 'lo_addresses' in r_config:
                # option lo_addresses = [IPV6_ADDRESS, IPV4_ADDRESS] to set the loopback address of the router
                # see https://ipmininet.readthedocs.io/en/latest/addressing.html
                r_config['lo_addresses'] = format_address(
                    r_config['lo_addresses'], self.__prefixes)
            elif self.infer_ip_lo:
                lo_addr = self.generate_ip(r_name, ipv4=True, ipv6=True)
                if lo_addr is not None:
                    r_config['lo_addresses'] = lo_addr

            r_kwargs = {
                k: v
                for k, v in r_config.items() if k in ('lo_addresses', )
            }

            if self.debug:
                print("Adding router {} to AS {} with config {}".format(
                    r_name, as_name, r_kwargs))

            router = self.addRouter(r_name, config=RouterConfig, **r_kwargs)
            self.add_daemons(router, r_config.get('daemons', []),
                             default_daemons)

            self.__routers[r_name] = router

            if 'clients' in r_config or 'peers' in r_config:
                niv = r_config.get('niveau', 1)
                rr_config = {'niveau': niv}
                if 'clients' in r_config:
                    rr_config['clients'] = r_config['clients']
                if 'peers' in r_config: rr_config['peers'] = r_config['peers']

                self.__as[as_name]['rr'].setdefault(niv, {})
                self.__as[as_name]['rr'][niv][r_name] = rr_config

            if 'hosts' in r_config:
                self.add_host_to_router(r_name, r_config['hosts'])

            if self.add_hosts:
                self.add_fictif_host(as_name, r_name)

        self._build_rr(as_name)
Ejemplo n.º 4
0
    def add_link(self,
                 node,
                 voisin,
                 config_node,
                 config_voisin,
                 link_type='share',
                 **kwargs):
        as_1, as_2 = self.get_as_of(node), self.get_as_of(voisin)
        node, voisin = self.get(node), self.get(voisin)

        config_node = config_node.copy()

        ip1, ip2 = config_node.pop('ip', None), config_voisin.pop('ip', None)

        if self.infer_ip_link and ip1 is None and 'subnet' not in config_voisin:
            ip1 = self.generate_ip(node)

        if self.infer_ip_link and ip2 is None and 'subnet' not in config_voisin:
            ip2 = self.generate_ip(voisin)

        if 'subnet' in config_voisin:
            subnet = config_voisin.pop('subnet')
            if isinstance(subnet, dict):
                subnet = format_address(subnet, self.__prefixes)
            ip1, ip2 = subnet

        kwargs = {**config_node, **config_voisin}
        if ip1 is not None:
            kwargs.setdefault('params1', {})
            kwargs['params1']['ip'] = ip1
        if ip2 is not None:
            kwargs.setdefault('params2', {})
            kwargs['params2']['ip'] = ip2

        if self.debug:
            print("Adding link between {} and {} with config : {}".format(
                node, voisin, kwargs))

        link = self.addLink(node, voisin, **kwargs)

        if as_1 != as_2:
            self.add_ebgp_session(node, voisin, as_1, as_2, link_type)

        return link
Ejemplo n.º 5
0
        def add_addr_to_subnet(net, first_addr, host_bits, is_ipv6):
            sep = '.' if not is_ipv6 else ':'
            new_mask = 32 - host_bits if not is_ipv6 else 128 - host_bits

            ip_subnet = format_address(net, self.__prefixes, is_ipv6=is_ipv6)

            last_bits = ip_subnet.split('/')[0].split(sep)[-1]
            if is_ipv6:
                last_bits = 0 if last_bits == '' else int(last_bits, 16)
            else:
                last_bits = int(last_bits)
            last_bits += first_addr

            new_ip = ip_subnet.split('/')[0].split(sep)
            new_ip[-1] = str(last_bits)

            new_ip = sep.join(new_ip) + '/' + str(new_mask)

            return new_ip
Ejemplo n.º 6
0
    def _build_subnets(self):
        for subnet_name, subnet_config in self.__subnets.items():
            if self.debug:
                print(
                    "Creating subnet {} with prefix :\n- IPv4 : {}\n- IPv6 : {}"
                    .format(subnet_name, subnet_config.get('ipv4', None),
                            subnet_config.get('ipv6', None)))

            addresses = format_address(subnet_config, self.__prefixes)

            nodes = [
                self.get(node_name)
                for node_name in subnet_config.get('nodes', [])
            ]

            if len(nodes) > 0:
                if self.debug:
                    print("Adding nodes {} to subnet".format(nodes))
                self.addSubnet(nodes, subnets=addresses)
            elif self.debug:
                print("No node attached to this subnet")
Ejemplo n.º 7
0
    def add_daemons(self, router, daemons, default_daemons=[]):
        """
            Add daemon to router. 
            Arguments : 
                - router    : the router class to which add daemons. 
                - daemons   : daemons specific for this router. 
                - default_daemons   : daemons by default. 
            
            daemons and default_daemons can be : 
                - list  : name of daemons (will be added without specific config). 
                - dict  : {daemon_name : dict (config)}
        """
        if isinstance(default_daemons, list):
            default_daemons = {d: {} for d in default_daemons}
        if isinstance(daemons, list): daemons = {d: {} for d in daemons}

        daemons = deep_merge(default_daemons, daemons)
        for d, d_config in daemons.items():
            if self.debug:
                print("Adding daemon {} with config {}".format(d, d_config))
            if d == 'ospf':
                router.addDaemon(OSPF)
            elif d == 'ospf6':
                router.addDaemon(OSPF6)
            elif d == 'bgp':
                if 'networks' in d_config:
                    d_config['networks'] = format_address(
                        d_config['networks'], self.__prefixes)
                if 'communities' in d_config:
                    self.__communities[router] = d_config["communities"]

                families = (AF_INET(redistribute=('connected', )),
                            AF_INET6(redistribute=('connected', )))
                router.addDaemon(BGP, address_families=families)
            else:
                raise NotImplementedError(
                    "Daemon {} is not supported yet !".format(d))

        return True
Ejemplo n.º 8
0
    def add_daemons(self, router, daemons, default_daemons=[]):
        if isinstance(default_daemons, list):
            default_daemons = {d: {} for d in default_daemons}
        if isinstance(daemons, list): daemons = {d: {} for d in daemons}

        daemons = {**default_daemons, **daemons}
        for d, d_config in daemons.items():
            if self.debug:
                print("Adding daemon {} with config {}".format(d, d_config))
            if d == 'ospf':
                router.addDaemon(OSPF)
            elif d == 'ospf6':
                router.addDaemon(OSPF6)
            elif d == 'bgp':
                if 'networks' in d_config:
                    d_config['networks'] = format_address(
                        d_config['networks'], self.__prefixes)

                families = (AF_INET(redistribute=('connected', )),
                            AF_INET6(redistribute=('connected', )))
                router.addDaemon(BGP, address_families=families)

        return True