updates to support external transport configuration and an emane transport service to generate and run emanetransport for a configured external transport model

This commit is contained in:
Blake J. Harnden 2018-07-11 09:19:06 -07:00
parent bf222cd5b4
commit bfbee35a53
10 changed files with 108 additions and 16 deletions

View file

@ -105,7 +105,7 @@ class Configuration(object):
Represents a configuration options.
"""
def __init__(self, _id, _type, label, default="", options=None):
def __init__(self, _id, _type, label=None, default="", options=None):
"""
Creates a Configuration object.

View file

@ -41,8 +41,9 @@ class EmaneCommEffectModel(emanemodel.EmaneModel):
shim_defaults = {}
config_shim = emanemanifest.parse(shim_xml, shim_defaults)
# comm effect does not need the default phy configuration
# comm effect does not need the default phy and external configurations
phy_config = ()
external_config = ()
@classmethod
def configurations(cls):

View file

@ -128,7 +128,9 @@ class EmaneManager(ModelManager):
if not config and self.has_configs(interface.node.objid):
config = self.get_configs(node_id=interface.node.objid, config_type=model_name)
if not config and interface.transport_type == "raw":
# get non interface config, when none found
# if not config and interface.transport_type == "raw":
if not config and self.has_configs(node_id):
# with EMANE 0.9.2+, we need an extra NEM XML from
# model.buildnemxmlfiles(), so defaults are returned here
config = self.get_configs(node_id=node_id, config_type=model_name)
@ -561,11 +563,12 @@ class EmaneManager(ModelManager):
Build a platform.xml file now that all nodes are configured.
"""
nemid = int(self.get_config("nem_id_start"))
platform_xmls = {}
# assume self._objslock is already held here
for key in sorted(self._emane_nodes.keys()):
emane_node = self._emane_nodes[key]
nemid = emanexml.build_node_platform_xml(self, ctrlnet, emane_node, nemid)
nemid = emanexml.build_node_platform_xml(self, ctrlnet, emane_node, nemid, platform_xmls)
def buildnemxml(self):
"""

View file

@ -5,7 +5,9 @@ import os
from core import logger
from core.conf import ConfigGroup
from core.conf import Configuration
from core.emane import emanemanifest
from core.enumerations import ConfigDataTypes
from core.mobility import WirelessModel
from core.xml import emanexml
@ -32,19 +34,28 @@ class EmaneModel(WirelessModel):
}
phy_config = emanemanifest.parse(phy_xml, phy_defaults)
# support for external configurations
external_config = [
Configuration("external", ConfigDataTypes.BOOL, default="0"),
Configuration("platformendpoint", ConfigDataTypes.STRING, default="127.0.0.1:40001"),
Configuration("transportendpoint", ConfigDataTypes.STRING, default="127.0.0.1:50002")
]
config_ignore = set()
@classmethod
def configurations(cls):
return cls.mac_config + cls.phy_config
return cls.mac_config + cls.phy_config + cls.external_config
@classmethod
def config_groups(cls):
mac_len = len(cls.mac_config)
phy_len = len(cls.phy_config) + mac_len
config_len = len(cls.configurations())
return [
ConfigGroup("MAC Parameters", 1, mac_len),
ConfigGroup("PHY Parameters", mac_len + 1, config_len)
ConfigGroup("PHY Parameters", mac_len + 1, phy_len),
ConfigGroup("External Parameters", phy_len + 1, config_len)
]
def build_xml_files(self, config, interface=None):
@ -60,6 +71,7 @@ class EmaneModel(WirelessModel):
mac_name = emanexml.mac_file_name(self, interface)
phy_name = emanexml.phy_file_name(self, interface)
# check if this is external
transport_type = "virtual"
if interface and interface.transport_type == "raw":
transport_type = "raw"
@ -67,7 +79,7 @@ class EmaneModel(WirelessModel):
# create nem xml file
nem_file = os.path.join(self.session.session_dir, nem_name)
emanexml.create_nem_xml(self, nem_file, transport_name, mac_name, phy_name)
emanexml.create_nem_xml(self, config, nem_file, transport_name, mac_name, phy_name)
# create mac xml file
mac_file = os.path.join(self.session.session_dir, mac_name)

View file

@ -131,7 +131,7 @@ class EmaneNode(EmaneNet):
for netif in self.netifs():
if do_netns and "virtual" in netif.transport_type.lower():
netif.install()
netif.setaddrs()
# netif.setaddrs()
if not self.session.emane.genlocationevents():
netif.poshook = None
continue

View file

@ -169,6 +169,7 @@ class TunTap(PyCoreNetIf):
:return: wait for device local response
:rtype: int
"""
logger.debug("waiting for device local: %s", self.localname)
def localdevexists():
args = [constants.IP_BIN, "link", "show", self.localname]
@ -182,6 +183,7 @@ class TunTap(PyCoreNetIf):
:return: nothing
"""
logger.debug("waiting for device node: %s", self.name)
def nodedevexists():
args = [constants.IP_BIN, "link", "show", self.name]

View file

@ -0,0 +1,40 @@
from core.enumerations import NodeTypes
from core.misc import nodeutils
from core.service import CoreService
from core.xml import emanexml
class EmaneTransportService(CoreService):
name = "transportd"
executables = ("emanetransportd", "emanegentransportxml")
group = "EMANE"
dependencies = ()
dirs = ()
configs = ("emanetransport.sh",)
startup = ("sh %s" % configs[0],)
validate = ("pidof %s" % executables[0],)
validation_timer = 0.5
shutdown = ("killall %s" % executables[0],)
@classmethod
def generate_config(cls, node, filename):
if filename == cls.configs[0]:
transport_commands = []
for interface in node.netifs(sort=True):
network_node = node.session.get_object(interface.net.objid)
if nodeutils.is_node(network_node, NodeTypes.EMANE):
if not node.session.emane.has_configs(network_node.objid):
continue
all_configs = node.session.emane.get_all_configs(network_node.objid)
config = all_configs.get(network_node.model.name)
if emanexml.is_external(config):
nem_id = network_node.getnemid(interface)
command = "emanetransportd -r -l 0 -d ../transportdaemon%s.xml" % nem_id
transport_commands.append(command)
transport_commands = "\n".join(transport_commands)
return """
emanegentransportxml -o ../ ../platform%s.xml
%s
""" % (node.objid, transport_commands)
else:
raise ValueError

View file

@ -84,6 +84,11 @@ def create_emane_model_config(node_id, model, config):
value = config[phy_config.id]
add_configuration(phy_element, phy_config.id, value)
external_element = etree.SubElement(emane_element, "external")
for external_config in model.external_config:
value = config[external_config.id]
add_configuration(external_element, external_config.id, value)
return emane_element
@ -774,6 +779,12 @@ class CoreXmlReader(object):
value = config.get("value")
configs[name] = value
external_configuration = emane_configuration.find("external")
for config in external_configuration.iterchildren():
name = config.get("name")
value = config.get("value")
configs[name] = value
logger.info("reading emane configuration node(%s) model(%s)", node_id, model_name)
self.session.emane.set_model_config(node_id, model_name, configs)

View file

@ -10,6 +10,17 @@ from core.xml import corexml
_hwaddr_prefix = "02:02"
def is_external(config):
"""
Checks if the configuration is for an external transport.
:param dict config: configuration to check
:return: True if external, False otherwise
:rtype: bool
"""
return config.get("external") == "1"
def _value_to_params(value):
"""
Helper to convert a parameter to a parameter tuple.
@ -85,7 +96,7 @@ def add_configurations(xml_element, configurations, config, config_ignore):
add_param(xml_element, name, value)
def build_node_platform_xml(emane_manager, control_net, node, nem_id):
def build_node_platform_xml(emane_manager, control_net, node, nem_id, platform_xmls):
"""
Create platform xml for a specific node.
@ -93,15 +104,15 @@ def build_node_platform_xml(emane_manager, control_net, node, nem_id):
: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 = {}
platform_xmls = {}
if node.model is None:
logger.info("warning: EmaneNode %s has no associated model", node.name)
logger.warn("warning: EmaneNode %s has no associated model", node.name)
return nem_entries
for netif in node.netifs():
@ -109,6 +120,16 @@ def build_node_platform_xml(emane_manager, control_net, node, nem_id):
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])
# build transport xml
transport_type = netif.transport_type
if not transport_type:
@ -220,7 +241,6 @@ def build_xml_files(emane_manager, node):
need_raw = True
rtype = netif.transport_type
# build transport XML files depending on type of interfaces involved
if need_virtual:
build_transport_xml(emane_manager, node, vtype)
@ -270,7 +290,7 @@ def create_phy_xml(emane_model, config, file_path):
Create the phy xml document.
:param core.emane.emanemodel.EmaneModel emane_model: emane model to create phy xml for
:param dict config: all current configuration values, mac + phy
:param dict config: all current configuration values
:param str file_path: path to write file to
:return: nothing
"""
@ -287,7 +307,7 @@ def create_mac_xml(emane_model, config, file_path):
Create the mac xml document.
:param core.emane.emanemodel.EmaneModel emane_model: emane model to create phy xml for
:param dict config: all current configuration values, mac + phy
:param dict config: all current configuration values
:param str file_path: path to write file to
:return: nothing
"""
@ -299,11 +319,12 @@ def create_mac_xml(emane_model, config, file_path):
create_file(mac_element, "mac", file_path)
def create_nem_xml(emane_model, nem_file, transport_definition, mac_definition, phy_definition):
def create_nem_xml(emane_model, config, nem_file, transport_definition, mac_definition, phy_definition):
"""
Create the nem xml document.
:param core.emane.emanemodel.EmaneModel emane_model: emane model to create phy xml for
:param dict config: all current configuration values
:param str nem_file: nem file path to write
:param str transport_definition: transport file definition path
:param str mac_definition: mac file definition path
@ -311,6 +332,8 @@ def create_nem_xml(emane_model, nem_file, transport_definition, mac_definition,
:return: nothing
"""
nem_element = etree.Element("nem", name="%s NEM" % emane_model.name)
if is_external(config):
nem_element.set("type", "unstructured")
etree.SubElement(nem_element, "transport", definition=transport_definition)
etree.SubElement(nem_element, "mac", definition=mac_definition)
etree.SubElement(nem_element, "phy", definition=phy_definition)

View file

@ -14,7 +14,7 @@
}
},
"root": {
"level": "INFO",
"level": "DEBUG",
"handlers": ["console"]
}
}