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:
parent
bf222cd5b4
commit
bfbee35a53
10 changed files with 108 additions and 16 deletions
|
@ -105,7 +105,7 @@ class Configuration(object):
|
||||||
Represents a configuration options.
|
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.
|
Creates a Configuration object.
|
||||||
|
|
||||||
|
|
|
@ -41,8 +41,9 @@ class EmaneCommEffectModel(emanemodel.EmaneModel):
|
||||||
shim_defaults = {}
|
shim_defaults = {}
|
||||||
config_shim = emanemanifest.parse(shim_xml, 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 = ()
|
phy_config = ()
|
||||||
|
external_config = ()
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def configurations(cls):
|
def configurations(cls):
|
||||||
|
|
|
@ -128,7 +128,9 @@ class EmaneManager(ModelManager):
|
||||||
if not config and self.has_configs(interface.node.objid):
|
if not config and self.has_configs(interface.node.objid):
|
||||||
config = self.get_configs(node_id=interface.node.objid, config_type=model_name)
|
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
|
# with EMANE 0.9.2+, we need an extra NEM XML from
|
||||||
# model.buildnemxmlfiles(), so defaults are returned here
|
# model.buildnemxmlfiles(), so defaults are returned here
|
||||||
config = self.get_configs(node_id=node_id, config_type=model_name)
|
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.
|
Build a platform.xml file now that all nodes are configured.
|
||||||
"""
|
"""
|
||||||
nemid = int(self.get_config("nem_id_start"))
|
nemid = int(self.get_config("nem_id_start"))
|
||||||
|
platform_xmls = {}
|
||||||
|
|
||||||
# assume self._objslock is already held here
|
# assume self._objslock is already held here
|
||||||
for key in sorted(self._emane_nodes.keys()):
|
for key in sorted(self._emane_nodes.keys()):
|
||||||
emane_node = self._emane_nodes[key]
|
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):
|
def buildnemxml(self):
|
||||||
"""
|
"""
|
||||||
|
|
|
@ -5,7 +5,9 @@ import os
|
||||||
|
|
||||||
from core import logger
|
from core import logger
|
||||||
from core.conf import ConfigGroup
|
from core.conf import ConfigGroup
|
||||||
|
from core.conf import Configuration
|
||||||
from core.emane import emanemanifest
|
from core.emane import emanemanifest
|
||||||
|
from core.enumerations import ConfigDataTypes
|
||||||
from core.mobility import WirelessModel
|
from core.mobility import WirelessModel
|
||||||
from core.xml import emanexml
|
from core.xml import emanexml
|
||||||
|
|
||||||
|
@ -32,19 +34,28 @@ class EmaneModel(WirelessModel):
|
||||||
}
|
}
|
||||||
phy_config = emanemanifest.parse(phy_xml, phy_defaults)
|
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()
|
config_ignore = set()
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def configurations(cls):
|
def configurations(cls):
|
||||||
return cls.mac_config + cls.phy_config
|
return cls.mac_config + cls.phy_config + cls.external_config
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def config_groups(cls):
|
def config_groups(cls):
|
||||||
mac_len = len(cls.mac_config)
|
mac_len = len(cls.mac_config)
|
||||||
|
phy_len = len(cls.phy_config) + mac_len
|
||||||
config_len = len(cls.configurations())
|
config_len = len(cls.configurations())
|
||||||
return [
|
return [
|
||||||
ConfigGroup("MAC Parameters", 1, mac_len),
|
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):
|
def build_xml_files(self, config, interface=None):
|
||||||
|
@ -60,6 +71,7 @@ class EmaneModel(WirelessModel):
|
||||||
mac_name = emanexml.mac_file_name(self, interface)
|
mac_name = emanexml.mac_file_name(self, interface)
|
||||||
phy_name = emanexml.phy_file_name(self, interface)
|
phy_name = emanexml.phy_file_name(self, interface)
|
||||||
|
|
||||||
|
# check if this is external
|
||||||
transport_type = "virtual"
|
transport_type = "virtual"
|
||||||
if interface and interface.transport_type == "raw":
|
if interface and interface.transport_type == "raw":
|
||||||
transport_type = "raw"
|
transport_type = "raw"
|
||||||
|
@ -67,7 +79,7 @@ class EmaneModel(WirelessModel):
|
||||||
|
|
||||||
# create nem xml file
|
# create nem xml file
|
||||||
nem_file = os.path.join(self.session.session_dir, nem_name)
|
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
|
# create mac xml file
|
||||||
mac_file = os.path.join(self.session.session_dir, mac_name)
|
mac_file = os.path.join(self.session.session_dir, mac_name)
|
||||||
|
|
|
@ -131,7 +131,7 @@ class EmaneNode(EmaneNet):
|
||||||
for netif in self.netifs():
|
for netif in self.netifs():
|
||||||
if do_netns and "virtual" in netif.transport_type.lower():
|
if do_netns and "virtual" in netif.transport_type.lower():
|
||||||
netif.install()
|
netif.install()
|
||||||
netif.setaddrs()
|
# netif.setaddrs()
|
||||||
if not self.session.emane.genlocationevents():
|
if not self.session.emane.genlocationevents():
|
||||||
netif.poshook = None
|
netif.poshook = None
|
||||||
continue
|
continue
|
||||||
|
|
|
@ -169,6 +169,7 @@ class TunTap(PyCoreNetIf):
|
||||||
:return: wait for device local response
|
:return: wait for device local response
|
||||||
:rtype: int
|
:rtype: int
|
||||||
"""
|
"""
|
||||||
|
logger.debug("waiting for device local: %s", self.localname)
|
||||||
|
|
||||||
def localdevexists():
|
def localdevexists():
|
||||||
args = [constants.IP_BIN, "link", "show", self.localname]
|
args = [constants.IP_BIN, "link", "show", self.localname]
|
||||||
|
@ -182,6 +183,7 @@ class TunTap(PyCoreNetIf):
|
||||||
|
|
||||||
:return: nothing
|
:return: nothing
|
||||||
"""
|
"""
|
||||||
|
logger.debug("waiting for device node: %s", self.name)
|
||||||
|
|
||||||
def nodedevexists():
|
def nodedevexists():
|
||||||
args = [constants.IP_BIN, "link", "show", self.name]
|
args = [constants.IP_BIN, "link", "show", self.name]
|
||||||
|
|
40
daemon/core/services/emaneservices.py
Normal file
40
daemon/core/services/emaneservices.py
Normal 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
|
|
@ -84,6 +84,11 @@ def create_emane_model_config(node_id, model, config):
|
||||||
value = config[phy_config.id]
|
value = config[phy_config.id]
|
||||||
add_configuration(phy_element, phy_config.id, value)
|
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
|
return emane_element
|
||||||
|
|
||||||
|
|
||||||
|
@ -774,6 +779,12 @@ class CoreXmlReader(object):
|
||||||
value = config.get("value")
|
value = config.get("value")
|
||||||
configs[name] = 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)
|
logger.info("reading emane configuration node(%s) model(%s)", node_id, model_name)
|
||||||
self.session.emane.set_model_config(node_id, model_name, configs)
|
self.session.emane.set_model_config(node_id, model_name, configs)
|
||||||
|
|
||||||
|
|
|
@ -10,6 +10,17 @@ from core.xml import corexml
|
||||||
_hwaddr_prefix = "02:02"
|
_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):
|
def _value_to_params(value):
|
||||||
"""
|
"""
|
||||||
Helper to convert a parameter to a parameter tuple.
|
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)
|
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.
|
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.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 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 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
|
:return: the next nem id that can be used for creating platform xml files
|
||||||
:rtype: int
|
:rtype: int
|
||||||
"""
|
"""
|
||||||
logger.debug("building emane platform xml for node(%s): %s", node, node.name)
|
logger.debug("building emane platform xml for node(%s): %s", node, node.name)
|
||||||
nem_entries = {}
|
nem_entries = {}
|
||||||
platform_xmls = {}
|
|
||||||
|
|
||||||
if node.model is None:
|
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
|
return nem_entries
|
||||||
|
|
||||||
for netif in node.netifs():
|
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_definition = nem_file_name(node.model, netif)
|
||||||
nem_element = etree.Element("nem", id=str(nem_id), name=netif.localname, definition=nem_definition)
|
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
|
# build transport xml
|
||||||
transport_type = netif.transport_type
|
transport_type = netif.transport_type
|
||||||
if not transport_type:
|
if not transport_type:
|
||||||
|
@ -220,7 +241,6 @@ def build_xml_files(emane_manager, node):
|
||||||
need_raw = True
|
need_raw = True
|
||||||
rtype = netif.transport_type
|
rtype = netif.transport_type
|
||||||
|
|
||||||
# build transport XML files depending on type of interfaces involved
|
|
||||||
if need_virtual:
|
if need_virtual:
|
||||||
build_transport_xml(emane_manager, node, vtype)
|
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.
|
Create the phy xml document.
|
||||||
|
|
||||||
:param core.emane.emanemodel.EmaneModel emane_model: emane model to create phy xml for
|
: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
|
:param str file_path: path to write file to
|
||||||
:return: nothing
|
:return: nothing
|
||||||
"""
|
"""
|
||||||
|
@ -287,7 +307,7 @@ def create_mac_xml(emane_model, config, file_path):
|
||||||
Create the mac xml document.
|
Create the mac xml document.
|
||||||
|
|
||||||
:param core.emane.emanemodel.EmaneModel emane_model: emane model to create phy xml for
|
: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
|
:param str file_path: path to write file to
|
||||||
:return: nothing
|
:return: nothing
|
||||||
"""
|
"""
|
||||||
|
@ -299,11 +319,12 @@ def create_mac_xml(emane_model, config, file_path):
|
||||||
create_file(mac_element, "mac", 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.
|
Create the nem xml document.
|
||||||
|
|
||||||
:param core.emane.emanemodel.EmaneModel emane_model: emane model to create phy xml for
|
: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 nem_file: nem file path to write
|
||||||
:param str transport_definition: transport file definition path
|
:param str transport_definition: transport file definition path
|
||||||
:param str mac_definition: mac 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
|
:return: nothing
|
||||||
"""
|
"""
|
||||||
nem_element = etree.Element("nem", name="%s NEM" % emane_model.name)
|
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, "transport", definition=transport_definition)
|
||||||
etree.SubElement(nem_element, "mac", definition=mac_definition)
|
etree.SubElement(nem_element, "mac", definition=mac_definition)
|
||||||
etree.SubElement(nem_element, "phy", definition=phy_definition)
|
etree.SubElement(nem_element, "phy", definition=phy_definition)
|
||||||
|
|
|
@ -14,7 +14,7 @@
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"root": {
|
"root": {
|
||||||
"level": "INFO",
|
"level": "DEBUG",
|
||||||
"handlers": ["console"]
|
"handlers": ["console"]
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Reference in a new issue