Пример #1
0
def link_message(n1,
                 n2,
                 intf_one=None,
                 address_one=None,
                 intf_two=None,
                 address_two=None,
                 key=None):
    """
    Convenience method for creating link TLV messages.

    :param int n1: node one id
    :param int n2: node two id
    :param int intf_one: node one interface id
    :param core.misc.ipaddress.IpAddress address_one: node one ip4 address
    :param int intf_two: node two interface id
    :param core.misc.ipaddress.IpAddress address_two: node two ip4 address
    :param int key: tunnel key for link if needed
    :return: tlv mesage
    :rtype: core.api.coreapi.CoreLinkMessage
    """
    mac_one, mac_two = None, None
    if address_one:
        mac_one = MacAddress.random()
    if address_two:
        mac_two = MacAddress.random()

    values = [
        (LinkTlvs.N1_NUMBER, n1),
        (LinkTlvs.N2_NUMBER, n2),
        (LinkTlvs.DELAY, 0),
        (LinkTlvs.BANDWIDTH, 0),
        (LinkTlvs.PER, "0"),
        (LinkTlvs.DUP, "0"),
        (LinkTlvs.JITTER, 0),
        (LinkTlvs.TYPE, LinkTypes.WIRED.value),
        (LinkTlvs.INTERFACE1_NUMBER, intf_one),
        (LinkTlvs.INTERFACE1_IP4, address_one),
        (LinkTlvs.INTERFACE1_IP4_MASK, 24),
        (LinkTlvs.INTERFACE1_MAC, mac_one),
        (LinkTlvs.INTERFACE2_NUMBER, intf_two),
        (LinkTlvs.INTERFACE2_IP4, address_two),
        (LinkTlvs.INTERFACE2_IP4_MASK, 24),
        (LinkTlvs.INTERFACE2_MAC, mac_two),
    ]

    if key:
        values.append((LinkTlvs.KEY, key))

    return CoreLinkMessage.create(MessageFlags.ADD.value, values)
Пример #2
0
 def parse_interface(self, node, device_id, interface):
     """
     Each interface can have multiple 'address' elements.
     """
     if_name = interface.getAttribute('name')
     network = self.find_interface_network_object(interface)
     if not network:
         msg = 'skipping node \'%s\' interface \'%s\': ' \
               'unknown network' % (node.name, if_name)
         logger.warn(msg)
         assert False  # XXX for testing
     mac, ipv4, ipv6, hostname = self.parse_addresses(interface)
     if mac:
         hwaddr = MacAddress.from_string(mac[0])
     else:
         hwaddr = None
     ifindex = node.newnetif(network,
                             addrlist=ipv4 + ipv6,
                             hwaddr=hwaddr,
                             ifindex=None,
                             ifname=if_name)
     # TODO: 'hostname' addresses are unused
     msg = 'node \'%s\' interface \'%s\' connected ' \
           'to network \'%s\'' % (node.name, if_name, network.name)
     logger.info(msg)
     # set link parameters for wired links
     if nodeutils.is_node(
             network,
         (NodeTypes.HUB, NodeTypes.PEER_TO_PEER, NodeTypes.SWITCH)):
         netif = node.netif(ifindex)
         self.set_wired_link_parameters(network, netif, device_id)
Пример #3
0
 def parse_interface(self, node, device_id, interface):
     """
     Each interface can have multiple 'address' elements.
     """
     if_name = interface.getAttribute('name')
     network = self.find_interface_network_object(interface)
     if not network:
         msg = 'skipping node \'%s\' interface \'%s\': ' \
               'unknown network' % (node.name, if_name)
         logger.warn(msg)
         assert False  # XXX for testing
     mac, ipv4, ipv6, hostname = self.parse_addresses(interface)
     if mac:
         hwaddr = MacAddress.from_string(mac[0])
     else:
         hwaddr = None
     ifindex = node.newnetif(network, addrlist=ipv4 + ipv6, hwaddr=hwaddr, ifindex=None, ifname=if_name)
     # TODO: 'hostname' addresses are unused
     msg = 'node \'%s\' interface \'%s\' connected ' \
           'to network \'%s\'' % (node.name, if_name, network.name)
     logger.info(msg)
     # set link parameters for wired links
     if nodeutils.is_node(network, (NodeTypes.HUB, NodeTypes.PEER_TO_PEER, NodeTypes.SWITCH)):
         netif = node.netif(ifindex)
         self.set_wired_link_parameters(network, netif, device_id)
Пример #4
0
    def newveth(self, ifindex=None, ifname=None, net=None):
        """
        Create a new interface.

        :param int ifindex: index for the new interface
        :param str ifname: name for the new interface
        :param net: network to associate interface with
        :return: nothing
        """
        with self.lock:
            if ifindex is None:
                ifindex = self.newifindex()

            if ifname is None:
                ifname = "eth%d" % ifindex

            sessionid = self.session.short_session_id()

            try:
                suffix = "%x.%s.%s" % (self.objid, ifindex, sessionid)
            except TypeError:
                suffix = "%s.%s.%s" % (self.objid, ifindex, sessionid)

            localname = "veth" + suffix
            if len(localname) >= 16:
                raise ValueError("interface local name (%s) too long" % localname)

            name = localname + "p"
            if len(name) >= 16:
                raise ValueError("interface name (%s) too long" % name)

            veth = VEth(node=self, name=name, localname=localname, net=net, start=self.up)

            if self.up:
                utils.check_cmd([constants.IP_BIN, "link", "set", veth.name, "netns", str(self.pid)])
                self.check_cmd([constants.IP_BIN, "link", "set", veth.name, "name", ifname])

            veth.name = ifname

            if self.up:
                # TODO: potentially find better way to query interface ID
                # retrieve interface information
                output = self.check_cmd(["ip", "link", "show", veth.name])
                logger.debug("interface command output: %s", output)
                output = output.split("\n")
                veth.flow_id = int(output[0].strip().split(":")[0]) + 1
                logger.debug("interface flow index: %s - %s", veth.name, veth.flow_id)
                veth.hwaddr = MacAddress.from_string(output[1].strip().split()[1])
                logger.debug("interface mac: %s - %s", veth.name, veth.hwaddr)

            try:
                self.addnetif(veth, ifindex)
            except ValueError as e:
                veth.shutdown()
                del veth
                raise e

            return ifindex
Пример #5
0
    def new_obj(value):
        """
        Retrieve mac address from a string representation.

        :param str value: value to get Ipv4 address from
        :return: Ipv4 address
        :rtype: core.misc.ipaddress.MacAddress
        """
        # only use 48 bits
        return MacAddress(address=value[2:])
Пример #6
0
def link_message(n1, n2, intf_one=None, address_one=None, intf_two=None, address_two=None, key=None):
    """
    Convenience method for creating link TLV messages.

    :param int n1: node one id
    :param int n2: node two id
    :param int intf_one: node one interface id
    :param core.misc.ipaddress.IpAddress address_one: node one ip4 address
    :param int intf_two: node two interface id
    :param core.misc.ipaddress.IpAddress address_two: node two ip4 address
    :param int key: tunnel key for link if needed
    :return: tlv mesage
    :rtype: core.api.coreapi.CoreLinkMessage
    """
    mac_one, mac_two = None, None
    if address_one:
        mac_one = MacAddress.random()
    if address_two:
        mac_two = MacAddress.random()

    values = [
        (LinkTlvs.N1_NUMBER, n1),
        (LinkTlvs.N2_NUMBER, n2),
        (LinkTlvs.DELAY, 0),
        (LinkTlvs.BANDWIDTH, 0),
        (LinkTlvs.PER, "0"),
        (LinkTlvs.DUP, "0"),
        (LinkTlvs.JITTER, 0),
        (LinkTlvs.TYPE, LinkTypes.WIRED.value),
        (LinkTlvs.INTERFACE1_NUMBER, intf_one),
        (LinkTlvs.INTERFACE1_IP4, address_one),
        (LinkTlvs.INTERFACE1_IP4_MASK, 24),
        (LinkTlvs.INTERFACE1_MAC, mac_one),
        (LinkTlvs.INTERFACE2_NUMBER, intf_two),
        (LinkTlvs.INTERFACE2_IP4, address_two),
        (LinkTlvs.INTERFACE2_IP4_MASK, 24),
        (LinkTlvs.INTERFACE2_MAC, mac_two),
    ]

    if key:
        values.append((LinkTlvs.KEY, key))

    return CoreLinkMessage.create(MessageFlags.ADD.value, values)
Пример #7
0
def create_interface_data(interface_element):
    interface_id = int(interface_element.get("id"))
    name = interface_element.get("name")
    mac = interface_element.get("mac")
    if mac:
        mac = MacAddress.from_string(mac)
    ip4 = interface_element.get("ip4")
    ip4_mask = get_int(interface_element, "ip4_mask")
    ip6 = interface_element.get("ip6")
    ip6_mask = get_int(interface_element, "ip6_mask")
    return InterfaceData(interface_id, name, mac, ip4, ip4_mask, ip6, ip6_mask)
Пример #8
0
def create_interface_data(interface_element):
    interface_id = int(interface_element.get("id"))
    name = interface_element.get("name")
    mac = interface_element.get("mac")
    if mac:
        mac = MacAddress.from_string(mac)
    ip4 = interface_element.get("ip4")
    ip4_mask = get_int(interface_element, "ip4_mask")
    ip6 = interface_element.get("ip6")
    ip6_mask = get_int(interface_element, "ip6_mask")
    return InterfaceData(interface_id, name, mac, ip4, ip4_mask, ip6, ip6_mask)
Пример #9
0
    def add_remove_control_interface(self,
                                     node,
                                     net_index=0,
                                     remove=False,
                                     conf_required=True):
        """
        Add a control interface to a node when a 'controlnet' prefix is
        listed in the config file or session options. Uses
        addremovectrlnet() to build or remove the control bridge.
        If conf_reqd is False, the control network may be built even
        when the user has not configured one (e.g. for EMANE.)

        :param core.netns.nodes.CoreNode node: node to add or remove control interface
        :param int net_index: network index
        :param bool remove: flag to check if it should be removed
        :param bool conf_required: flag to check if conf is required
        :return: nothing
        """
        control_net = self.add_remove_control_net(net_index, remove,
                                                  conf_required)
        if not control_net:
            return

        if not node:
            return

        # ctrl# already exists
        if node.netif(control_net.CTRLIF_IDX_BASE + net_index):
            return

        control_ip = node.objid

        try:
            addrlist = [
                "%s/%s" % (control_net.prefix.addr(control_ip),
                           control_net.prefix.prefixlen)
            ]
        except ValueError:
            msg = "Control interface not added to node %s. " % node.objid
            msg += "Invalid control network prefix (%s). " % control_net.prefix
            msg += "A longer prefix length may be required for this many nodes."
            logger.exception(msg)
            return

        interface1 = node.newnetif(net=control_net,
                                   ifindex=control_net.CTRLIF_IDX_BASE +
                                   net_index,
                                   ifname="ctrl%d" % net_index,
                                   hwaddr=MacAddress.random(),
                                   addrlist=addrlist)
        node.netif(interface1).control = True
Пример #10
0
    def buildplatformxml(self, ctrlnet):
        """
        Build a platform.xml file now that all nodes are configured.
        """
        values = self.getconfig(None, "emane",
                                self.emane_config.getdefaultvalues())[1]
        nemid = int(self.emane_config.valueof("nem_id_start", values))
        platformxmls = {}

        # assume self._objslock is already held here
        for key in sorted(self._emane_nodes.keys()):
            emane_node = self._emane_nodes[key]
            nems = emane_node.buildplatformxmlentry(self.xmldoc("platform"))
            for netif in sorted(nems, key=lambda x: x.node.objid):
                nementry = nems[netif]
                nementry.setAttribute("id", "%d" % nemid)
                key = netif.node.objid
                if netif.transport_type == "raw":
                    key = "host"
                    otadev = ctrlnet.brname
                    eventdev = ctrlnet.brname
                else:
                    otadev = None
                    eventdev = None

                if key not in platformxmls:
                    platformxmls[key] = self.newplatformxmldoc(
                        values, otadev, eventdev)

                doc = platformxmls[key]
                plat = doc.getElementsByTagName("platform").pop()
                plat.appendChild(nementry)
                emane_node.setnemid(netif, nemid)
                macstr = self._hwaddr_prefix + ":00:00:"
                macstr += "%02X:%02X" % ((nemid >> 8) & 0xFF, nemid & 0xFF)
                netif.sethwaddr(MacAddress.from_string(macstr))
                nemid += 1

        for key in sorted(platformxmls.keys()):
            if key == "host":
                self.xmlwrite(platformxmls["host"], "platform.xml")
                continue
            self.xmlwrite(platformxmls[key], "platform%d.xml" % key)
Пример #11
0
    def create_interface(self, node, name=None, mac=None):
        """
        Creates interface data for linking nodes, using the nodes unique id for generation, along with a random
        mac address, unless provided.

        :param core.coreobj.PyCoreNode node: node to create interface for
        :param str name: name to set for interface, default is eth{id}
        :param str mac: mac address to use for this interface, default is random generation
        :return: new interface data for the provided node
        :rtype: InterfaceData
        """
        # interface id
        inteface_id = node.newifindex()

        # generate ip4 data
        ip4 = None
        ip4_mask = None
        if self.ip4:
            ip4 = str(self.ip4.addr(node.objid))
            ip4_mask = self.ip4.prefixlen

        # generate ip6 data
        ip6 = None
        ip6_mask = None
        if self.ip6:
            ip6 = str(self.ip6.addr(node.objid))
            ip6_mask = self.ip6.prefixlen

        # random mac
        if not mac:
            mac = MacAddress.random()

        return InterfaceData(
            _id=inteface_id,
            name=name,
            ip4=ip4,
            ip4_mask=ip4_mask,
            ip6=ip6,
            ip6_mask=ip6_mask,
            mac=mac
        )
Пример #12
0
    def add_remove_control_interface(self, node, net_index=0, remove=False, conf_required=True):
        """
        Add a control interface to a node when a 'controlnet' prefix is
        listed in the config file or session options. Uses
        addremovectrlnet() to build or remove the control bridge.
        If conf_reqd is False, the control network may be built even
        when the user has not configured one (e.g. for EMANE.)

        :param core.netns.nodes.CoreNode node: node to add or remove control interface
        :param int net_index: network index
        :param bool remove: flag to check if it should be removed
        :param bool conf_required: flag to check if conf is required
        :return: nothing
        """
        control_net = self.add_remove_control_net(net_index, remove, conf_required)
        if not control_net:
            return

        if not node:
            return

        # ctrl# already exists
        if node.netif(control_net.CTRLIF_IDX_BASE + net_index):
            return

        control_ip = node.objid

        try:
            addrlist = ["%s/%s" % (control_net.prefix.addr(control_ip), control_net.prefix.prefixlen)]
        except ValueError:
            msg = "Control interface not added to node %s. " % node.objid
            msg += "Invalid control network prefix (%s). " % control_net.prefix
            msg += "A longer prefix length may be required for this many nodes."
            logger.exception(msg)
            return

        interface1 = node.newnetif(net=control_net,
                                   ifindex=control_net.CTRLIF_IDX_BASE + net_index,
                                   ifname="ctrl%d" % net_index, hwaddr=MacAddress.random(),
                                   addrlist=addrlist)
        node.netif(interface1).control = True
Пример #13
0
def build_node_platform_xml(emane_manager, control_net, node, nem_id,
                            platform_xmls):
    """
    Create platform xml for a specific node.

    :param core.emane.emanemanager.EmaneManager emane_manager: emane manager with emane configurations
    :param core.netns.nodes.CtrlNet control_net: control net node for this emane network
    :param core.emane.nodes.EmaneNode node: node to write platform xml for
    :param int nem_id: nem id to use for interfaces for this node
    :param dict platform_xmls: stores platform xml elements to append nem entries to
    :return: the next nem id that can be used for creating platform xml files
    :rtype: int
    """
    logging.debug("building emane platform xml for node(%s): %s", node,
                  node.name)
    nem_entries = {}

    if node.model is None:
        logging.warn("warning: EmaneNode %s has no associated model",
                     node.name)
        return nem_entries

    for netif in node.netifs():
        # build nem xml
        nem_definition = nem_file_name(node.model, netif)
        nem_element = etree.Element("nem",
                                    id=str(nem_id),
                                    name=netif.localname,
                                    definition=nem_definition)

        # check if this is an external transport, get default config if an interface specific one does not exist
        config = emane_manager.getifcconfig(node.model.object_id, netif,
                                            node.model.name)

        if is_external(config):
            nem_element.set("transport", "external")
            platform_endpoint = "platformendpoint"
            add_param(nem_element, platform_endpoint,
                      config[platform_endpoint])
            transport_endpoint = "transportendpoint"
            add_param(nem_element, transport_endpoint,
                      config[transport_endpoint])
        else:
            # build transport xml
            transport_type = netif.transport_type
            if not transport_type:
                logging.info("warning: %s interface type unsupported!",
                             netif.name)
                transport_type = "raw"
            transport_file = transport_file_name(node.objid, transport_type)
            transport_element = etree.SubElement(nem_element,
                                                 "transport",
                                                 definition=transport_file)

            # add transport parameter
            add_param(transport_element, "device", netif.name)

        # add nem entry
        nem_entries[netif] = nem_element

        # merging code
        key = netif.node.objid
        if netif.transport_type == "raw":
            key = "host"
            otadev = control_net.brname
            eventdev = control_net.brname
        else:
            otadev = None
            eventdev = None

        platform_element = platform_xmls.get(key)
        if platform_element is None:
            platform_element = etree.Element("platform")

            if otadev:
                emane_manager.set_config("otamanagerdevice", otadev)

            if eventdev:
                emane_manager.set_config("eventservicedevice", eventdev)

            # append all platform options (except starting id) to doc
            for configuration in emane_manager.emane_config.emulator_config:
                name = configuration.id
                if name == "platform_id_start":
                    continue

                value = emane_manager.get_config(name)
                add_param(platform_element, name, value)

            # add platform xml
            platform_xmls[key] = platform_element

        platform_element.append(nem_element)

        node.setnemid(netif, nem_id)
        macstr = _hwaddr_prefix + ":00:00:"
        macstr += "%02X:%02X" % ((nem_id >> 8) & 0xFF, nem_id & 0xFF)
        netif.sethwaddr(MacAddress.from_string(macstr))

        # increment nem id
        nem_id += 1

    for key in sorted(platform_xmls.keys()):
        if key == "host":
            file_name = "platform.xml"
        else:
            file_name = "platform%d.xml" % key

        platform_element = platform_xmls[key]

        doc_name = "platform"
        file_path = os.path.join(emane_manager.session.session_dir, file_name)
        create_file(platform_element, doc_name, file_path)

    return nem_id
Пример #14
0
def build_node_platform_xml(emane_manager, control_net, node, nem_id, platform_xmls):
    """
    Create platform xml for a specific node.

    :param core.emane.emanemanager.EmaneManager emane_manager: emane manager with emane configurations
    :param core.netns.nodes.CtrlNet control_net: control net node for this emane network
    :param core.emane.nodes.EmaneNode node: node to write platform xml for
    :param int nem_id: nem id to use for interfaces for this node
    :param dict platform_xmls: stores platform xml elements to append nem entries to
    :return: the next nem id that can be used for creating platform xml files
    :rtype: int
    """
    logger.debug("building emane platform xml for node(%s): %s", node, node.name)
    nem_entries = {}

    if node.model is None:
        logger.warn("warning: EmaneNode %s has no associated model", node.name)
        return nem_entries

    for netif in node.netifs():
        # build nem xml
        nem_definition = nem_file_name(node.model, netif)
        nem_element = etree.Element("nem", id=str(nem_id), name=netif.localname, definition=nem_definition)

        # check if this is an external transport, get default config if an interface specific one does not exist
        config = emane_manager.getifcconfig(node.model.object_id, netif, node.model.name)

        if is_external(config):
            nem_element.set("transport", "external")
            platform_endpoint = "platformendpoint"
            add_param(nem_element, platform_endpoint, config[platform_endpoint])
            transport_endpoint = "transportendpoint"
            add_param(nem_element, transport_endpoint, config[transport_endpoint])
        else:
            # build transport xml
            transport_type = netif.transport_type
            if not transport_type:
                logger.info("warning: %s interface type unsupported!", netif.name)
                transport_type = "raw"
            transport_file = transport_file_name(node.objid, transport_type)
            transport_element = etree.SubElement(nem_element, "transport", definition=transport_file)

            # add transport parameter
            add_param(transport_element, "device", netif.name)

        # add nem entry
        nem_entries[netif] = nem_element

        # merging code
        key = netif.node.objid
        if netif.transport_type == "raw":
            key = "host"
            otadev = control_net.brname
            eventdev = control_net.brname
        else:
            otadev = None
            eventdev = None

        platform_element = platform_xmls.get(key)
        if platform_element is None:
            platform_element = etree.Element("platform")

            if otadev:
                emane_manager.set_config("otamanagerdevice", otadev)

            if eventdev:
                emane_manager.set_config("eventservicedevice", eventdev)

            # append all platform options (except starting id) to doc
            for configuration in emane_manager.emane_config.emulator_config:
                name = configuration.id
                if name == "platform_id_start":
                    continue

                value = emane_manager.get_config(name)
                add_param(platform_element, name, value)

            # add platform xml
            platform_xmls[key] = platform_element

        platform_element.append(nem_element)

        node.setnemid(netif, nem_id)
        macstr = _hwaddr_prefix + ":00:00:"
        macstr += "%02X:%02X" % ((nem_id >> 8) & 0xFF, nem_id & 0xFF)
        netif.sethwaddr(MacAddress.from_string(macstr))

        # increment nem id
        nem_id += 1

    for key in sorted(platform_xmls.keys()):
        if key == "host":
            file_name = "platform.xml"
        else:
            file_name = "platform%d.xml" % key

        platform_element = platform_xmls[key]

        doc_name = "platform"
        file_path = os.path.join(emane_manager.session.session_dir, file_name)
        create_file(platform_element, doc_name, file_path)

    return nem_id