示例#1
0
    def change_qdisc(self, handle, qdisc="", **kwargs):
        """
        Change a qdisc that is already present in the device

        Parameters
        ----------
        handle : string
            Hande of the qdisc to be changed
        qdisc : string
            The new qdisc to be added to the device
        """

        for qdisc_member in self.qdisc_list:
            if qdisc_member.handle == handle:
                # In case you want to just change kwargs
                if qdisc == "":
                    qdisc = qdisc_member.qdisc
                else:
                    TopologyMap.change_qdisc(self.node_id, self.dev_id, qdisc, handle)
                    qdisc_member.qdisc = qdisc
                engine.change_qdisc(
                    self.node_id,
                    self.dev_id,
                    qdisc,
                    qdisc_member.parent,
                    handle,
                    **kwargs,
                )
示例#2
0
 def test_add_and_get_interface(self):
     self.assertEqual(
         TopologyMap.get_interface(self.ns_id1, self.int_id1)["name"],
         self.int_name1)
     self.assertEqual(
         TopologyMap.get_interface(self.ns_id1, self.int_id2)["name"],
         self.int_name2)
示例#3
0
    def add_qdisc(self, qdisc, parent="root", handle="", **kwargs):
        """
        Add a qdisc (Queueing Discipline) to this interface

        Parameters
        ----------
        qdisc : string
            The qdisc which needs to be added to the interface
        dev : Interface class
            The interface to which the qdisc is to be added
        parent : string
            id of the parent class in major:minor form(optional) (Default value = 'root')
        handle : string
            id of the filter (Default value = '')
        """
        self.qdisc_list.append(
            traffic_control.Qdisc(self.node.id, self.id, qdisc, parent, handle,
                                  **kwargs))

        # Add qdisc to TopologyMap
        TopologyMap.add_qdisc(self.node.id,
                              self.id,
                              qdisc,
                              handle,
                              parent=parent)

        return self.qdisc_list[-1]
示例#4
0
    def add_interface(self, _interface=None):
        """
        Adding interface to the network.

        Parameters
        ----------
        _interface : interface
            The interface which needs to be added to the Network.
        """
        self.interface.append(_interface)
        TopologyMap.decrement_orphan_interfaces()
示例#5
0
文件: device.py 项目: nitk-nest/NeST
    def node_id(self, node_id):
        """
        Setter for the `Node` associated
        with the device

        Parameters
        ----------
        node : str
            The id of the node where the device is to be installed
        """
        self._traffic_control_handler.node_id = node_id
        if node_id is not None:
            TopologyMap.add_interface(self.node_id, self._id, self._name)
示例#6
0
    def _add_interface(self, interface):
        """
        Add `interface` to `Node`

        Parameters
        ----------
        interface: Interface
            `Interface` to be added to `Node`
        """
        self._interfaces.append(interface)
        interface.node = self
        engine.add_int_to_ns(self.id, interface.id)
        TopologyMap.add_interface(self.id, interface.id, interface.name)
示例#7
0
文件: node.py 项目: nitk-nest/NeST
    def enable_ip_forwarding(self, ipv4=True, ipv6=True):
        """
        Enable IP forwarding in `Node`.

        After this method runs, the `Node` can be used as a router.
        """
        if not ipv4 and not ipv6:
            raise Exception(
                "IP Forwarding cannot be false for both IPv4 and IPv6 addresses"
            )

        engine.en_ip_forwarding(self.id, ipv4, ipv6)
        TopologyMap.add_router(self)
示例#8
0
    def __init__(self, network_address):
        """
        Constructor of Network.

        Parameters
        ----------
        network_address : str
            IP address of the network

        """

        self.net_address = network_address
        self.interface = []

        # Adding each network's object reference to the static list of networks in topology_map.
        TopologyMap.add_network(self)
示例#9
0
文件: run_exp.py 项目: nitk-nest/NeST
def setup_udp_flows(dependency, flow, destination_nodes):
    """
    Setup iperf3 to run udp flows

    Parameters
    ----------
    dependency: int
        whether iperf3 is installed
    flow: Flow
        Flow parameters
    destination_nodes:
        Destination nodes so far already running iperf3 server

    Returns
    -------
    dependency: int
        updated dependency in case iproute2 is not installed
    iperf3_runners: List[NetperfRunner]
        all the iperf3 udp flows generated
    workers: List[multiprocessing.Process]
        Processes to run iperf3 udp flows
    """
    iperf3_runners = []
    if not dependency:
        logger.warning("Iperf3 not found. Udp flows cannot be generated")
    else:
        # Get flow attributes
        [
            src_ns,
            dst_ns,
            dst_addr,
            start_t,
            stop_t,
            n_flows,
            options,
        ] = flow._get_props()  # pylint: disable=protected-access

        # Run iperf3 server if not already run before on given dst_node
        if dst_ns not in destination_nodes:
            Iperf3Runner.run_server(dst_ns)

        src_name = TopologyMap.get_namespace(src_ns)["name"]
        f_flow = "flow" if n_flows == 1 else "flows"
        logger.info(
            "Running %s udp %s from %s to %s...", n_flows, f_flow, src_name, dst_addr
        )

        runner_obj = Iperf3Runner(
            src_ns,
            dst_addr,
            options["target_bw"],
            n_flows,
            start_t,
            stop_t - start_t,
            dst_ns,
        )
        iperf3_runners.append(runner_obj)

    return iperf3_runners
示例#10
0
 def print_error(self, error_string_prefix):
     """
     Method to print error from `self.err`
     """
     self.err.seek(0)  # rewind to start of file
     error = self.err.read().decode()
     ns_name = TopologyMap.get_namespace(self.ns_id)["name"]
     self.logger.error("%s at %s. %s", error_string_prefix, ns_name, error)
示例#11
0
    def delete_qdisc(self, handle):
        """
        Delete qdisc (Queueing Discipline) from this interface

        Parameters
        ----------
        handle : string
            Handle of the qdisc to be deleted
        """
        # TODO: Handle this better by using the destructor in traffic-control
        counter = 0
        for qdisc in self.qdisc_list:
            if qdisc.handle == handle:
                engine.delete_qdisc(qdisc.namespace_id, qdisc.dev_id,
                                    qdisc.parent, qdisc.handle)
                TopologyMap.delete_qdisc(self.node.id, self.id, handle)
                self.qdisc_list.pop(counter)
                break
            counter += 1
示例#12
0
    def __init__(self, name):
        """
        Create a node with given `name`.

        An unique `id` is assigned to this node which is used by
        `engine` module to create the network namespace.
        This ensures that there is no naming conflict between any two
        nodes.

        Parameters
        ----------
        name: str
            The name of the node to be created
        """
        if name == "":
            raise ValueError("Node name can't be an empty string")
        if config.get_value("assign_random_names") is False and len(name) > 3:
            # We chose 3 because: 'ifb-ns1-ns2-20' is a potential IFB interface name
            # and it's already 14 character long. Note that here node names
            # are 'ns1' and 'ns2'. The `ip` utility won't accept interface names
            # longer than 15 characters
            logger.warning(
                "%s is longer than 3 characters. It's safer to use "
                "node names with atmost 3 characters with the current config.",
                name,
            )

        self._name = name
        self._id = IdGen.get_id(name)
        self._interfaces = []
        # mpls max platform label kernel parameter
        self._mpls_max_label = 0
        # Global variable disables when any new node is created
        # to ensure DAD check (if applicable)
        g_var.IS_DAD_CHECKED = False

        engine.create_ns(self.id)
        engine.set_interface_mode(self.id, "lo", "up")
        TopologyMap.add_namespace(self.id, self.name)
        TopologyMap.add_host(self)
示例#13
0
    def __init__(self,
                 protocol="static",
                 hosts=None,
                 routers=None,
                 ldp_routers=None):
        """
        Constructor for RoutingHelper

        Parameters
        ----------
        protocol: str
            routing protocol to be run. One of [ospf, rip, isis]
        hosts: List[Node]
            List of hosts in the network. If `None`, considers the entire topology.
            Use this if your topology has disjoint networks
        routers: List[Node]
            List of routers in the network. If `None`, considers the entire topology.
            Use this if your topology has disjoint networks
        ldp_routers: List[Node]
            List of Routers which are to be used with mpls.
            Only enables ldp discovery on interfaces with mpls enabled
        """
        if protocol == "static":
            raise NotImplementedError(
                "Static routing is yet to be implemented. Use rip or ospf")
        self.protocol = protocol
        self.routers = TopologyMap.get_routers(
        ) if routers is None else routers
        self.hosts = TopologyMap.get_hosts() if hosts is None else hosts
        self.ldp_routers = ldp_routers if ldp_routers is not None else []
        self.conf_dir = None
        self.log_dir = None
        module_str, class_str = RoutingHelper._module_map[self.protocol]
        module = importlib.import_module(module_str)
        self.protocol_class = getattr(module, class_str)
        self.zebra_list = []
        self.protocol_list = []
        self.ldp_list = []

        atexit.register(self._clean_up)
示例#14
0
    def run_server(ns_id):
        """
        Run iperf server in `ns_id`

        Parameters
        ----------
        ns_id : str
            namespace to run netserver on
        """
        return_code = run_iperf_server(ns_id)
        if return_code != 0:
            ns_name = TopologyMap.get_namespace(ns_id)["name"]
            logger.error("Error running iperf3 server at %s.", ns_name)
示例#15
0
文件: device.py 项目: nitk-nest/NeST
    def __init__(self, name, node_id):
        """
        Constructore for a device

        Parameters
        ----------
        name : str
            User given name for the device
        node_id : str
            This is the id of the node that the device belongs to
        """

        if config.get_value("assign_random_names") is False:
            if len(name) > MAX_CUSTOM_NAME_LEN:
                raise ValueError(
                    f"Device name {name} is too long. Device names "
                    f"should not exceed 15 characters")

        self._name = name
        self._id = IdGen.get_id(name)
        self._traffic_control_handler = TrafficControlHandler(
            node_id, self._id)
        if node_id is not None:
            TopologyMap.add_interface(self.node_id, self._id, self._name)
示例#16
0
    def get_meta_item(self):
        """
        Return the meta item for the given flow.
        This "meta" information is required by plotter.
        """
        meta_item = {
            "meta": True,
            "start_time": str(self.start_time),
            "stop_time": str(self.start_time + self.run_time),
        }

        if self.dst_ns is not None:
            meta_item["destination_node"] = TopologyMap.get_namespace(
                self.dst_ns)["name"]

        return meta_item
示例#17
0
    def setUp(self):
        # Define namespace id and names
        self.ns_id1 = "ns_id1"
        self.ns_id2 = "ns_id2"
        self.ns_name1 = "ns_name1"
        self.ns_name2 = "ns_name2"

        # Add namespaces
        TopologyMap.add_namespace(self.ns_id1, self.ns_name1)
        TopologyMap.add_namespace(self.ns_id2, self.ns_name2)

        # Define interface id and names
        self.int_id1 = "int_id1"
        self.int_id2 = "int_id2"
        self.int_name1 = "int_name1"
        self.int_name2 = "int_name2"

        # Add interfaces
        TopologyMap.add_interface(self.ns_id1, self.int_id1, self.int_name1)
        TopologyMap.add_interface(self.ns_id1, self.int_id2, self.int_name2)
示例#18
0
    def wrapper_dad_check(*args, **kwargs):
        """
        Wrapper function for DAD

        Parameters
        ----------
        *args : Non-Keyword Arguments
            passes variable number of arguments to a function
        **kwargs : Keyword Arguments
            passes keyworded, variable-length argument list to a function

        Returns
        -------
        func
            Function to be executed after wrapper is executed
        """

        if (g_var.IS_IPV6 is True
                and config.get_value("disable_dad") is not True
                and g_var.IS_DAD_CHECKED is not True):

            namespaces = TopologyMap.get_namespaces()

            # Verifies if IPv6 states are addressable or not
            while True:
                status = check_ipv6_states(namespaces)

                # IPv6 state will be both in tentative and dadfailed together
                if status["dadfailed"][0] is True:
                    raise Exception(
                        "Duplicate address found "
                        f"at interface of node {status['dadfailed'][1]}."
                        "\nExiting ....")

                # Wait if IPv6 interface is in tentative state
                if status["tentative"] is True:
                    sleep(1)
                else:
                    break
            g_var.IS_DAD_CHECKED = True
        return func(*args, **kwargs)
示例#19
0
 def test_add_same_entity_again(self):
     with self.assertRaises(ValueError):
         TopologyMap.add_namespace(self.ns_id1, self.ns_name1)
     with self.assertRaises(ValueError):
         TopologyMap.add_interface(self.ns_id1, self.int_id1,
                                   self.int_name1)
示例#20
0
    def __init__(
        self,
        protocol: str,
        hosts: List[Node] = None,
        routers: List[Node] = None,
        ldp_routers: List[Node] = None,
    ):
        """
        Constructor for RoutingHelper.
        The dynamic routing daemons will be run only on nodes with more than
        one interface. Specify `hosts` & `routers` parameters to override this.

        Parameters
        ----------
        protocol: str
            routing protocol to be run. One of [ospf, rip, isis]
        hosts: List[Node]
            List of hosts in the network. If `None`, considers the entire topology.
            Use this if your topology has disjoint networks
        routers: List[Node]
            List of routers in the network. If `None`, considers the entire topology.
            Use this if your topology has disjoint networks
        ldp_routers: List[Node]
            List of Routers which are to be used with mpls.
            Only enables ldp discovery on interfaces with mpls enabled
        """
        if protocol == "static":
            raise NotImplementedError(
                "Static routing is yet to be implemented. Use rip, ospf or isis"
            )
        if protocol not in ["rip", "ospf", "isis"]:
            raise ValueError(
                f"Supported routing protocols are rip, ospf and isis, "
                f"but got protocol {protocol}")
        self.protocol = protocol

        # Validate hosts, routers and ldp_routers
        self._is_node_list("hosts", hosts)
        self._is_node_list("routers", routers)
        self._is_node_list("ldp_routers", ldp_routers)

        self.hosts = []
        self.routers = []
        if routers is None and hosts is None:
            all_nodes = TopologyMap.get_hosts() + TopologyMap.get_routers()
            for node in all_nodes:
                num_interfaces = len(node.interfaces)
                if num_interfaces == 1:
                    self.hosts.append(node)
                elif num_interfaces > 1:
                    self.routers.append(node)
        else:
            self.hosts = hosts
            self.routers = routers

        self.ldp_routers = ldp_routers if ldp_routers is not None else []
        self.conf_dir = None
        self.log_dir = None
        module_str, class_str = RoutingHelper._module_map[self.protocol]
        module = importlib.import_module(module_str)
        self.protocol_class = getattr(module, class_str)
        self.zebra_list = []
        self.protocol_list = []
        self.ldp_list = []

        atexit.register(self._clean_up)
示例#21
0
 def tearDown(self):
     TopologyMap.delete_all_mapping()
示例#22
0
 def tearDown(self):
     delete_namespaces()
     TopologyMap.delete_all_mapping()
示例#23
0
def setup_tcp_flows(dependency, flow, ss_schedules, destination_nodes):
    """
    Setup netperf to run tcp flows
    Parameters
    ----------
    dependency: int
        whether netperf is installed
    flow: Flow
        Flow parameters
    ss_schedules:
        ss_schedules so far
    destination_nodes:
        Destination nodes so far already running netperf server

    Returns
    -------
    dependency: int
        updated dependency in case netperf is not installed
    netperf_runners: List[NetperfRunner]
        all the netperf flows generated
    workers: List[multiprocessing.Process]
        Processes to run netperf flows
    ss_schedules: dict
        updated ss_schedules
    """
    netperf_runners = []
    if not dependency:
        logger.warning("Netperf not found. Tcp flows cannot be generated")
    else:
        # Get flow attributes
        [
            src_ns,
            dst_ns,
            dst_addr,
            start_t,
            stop_t,
            n_flows,
            options,
        ] = flow._get_props()  # pylint: disable=protected-access

        # Run netserver if not already run before on given dst_node
        if dst_ns not in destination_nodes:
            NetperfRunner.run_netserver(dst_ns)

        src_name = TopologyMap.get_namespace(src_ns)["name"]

        netperf_options = {}
        netperf_options["testname"] = "TCP_STREAM"
        netperf_options["cong_algo"] = options["cong_algo"]
        f_flow = "flow" if n_flows == 1 else "flows"
        logger.info(
            "Running %s netperf %s from %s to %s...",
            n_flows,
            f_flow,
            src_name,
            dst_addr,
        )

        # Create new processes to be run simultaneously
        for _ in range(n_flows):
            runner_obj = NetperfRunner(src_ns, dst_addr, start_t,
                                       stop_t - start_t, **netperf_options)
            netperf_runners.append(runner_obj)

        # Find the start time and stop time to run ss command in `src_ns` to a `dst_addr`
        ss_schedules = _get_start_stop_time_for_ss(src_ns, dst_addr, start_t,
                                                   stop_t, ss_schedules)

    return netperf_runners, ss_schedules