refactored emane xml configurations into an isolated file, using lxml

This commit is contained in:
Blake J. Harnden 2018-07-06 11:41:32 -07:00
parent f115b1a847
commit 875a880250
4 changed files with 354 additions and 304 deletions

View file

@ -2,6 +2,8 @@
commeffect.py: EMANE CommEffect model for CORE commeffect.py: EMANE CommEffect model for CORE
""" """
import os
from lxml import etree from lxml import etree
from core import logger from core import logger
@ -64,21 +66,22 @@ class EmaneCommEffectModel(emanemodel.EmaneModel):
:return: nothing :return: nothing
""" """
# retrieve xml names # retrieve xml names
nem_name = self.nem_name(interface) nem_name = emanexml.nem_file_name(self, interface)
shim_name = self.shim_name(interface) shim_name = emanexml.shim_file_name(self, interface)
# create and write nem document # create and write nem document
nem_element = etree.Element("nem", name="%s NEM" % self.name, type="unstructured") nem_element = etree.Element("nem", name="%s NEM" % self.name, type="unstructured")
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"
transport_name = "n%strans%s.xml" % (self.object_id, transport_type) transport_file = emanexml.transport_file_name(self.object_id, transport_type)
etree.SubElement(nem_element, "transport", definition=transport_name) etree.SubElement(nem_element, "transport", definition=transport_file)
# set shim configuration # set shim configuration
etree.SubElement(nem_element, "shim", definition=shim_name) etree.SubElement(nem_element, "shim", definition=shim_name)
self.create_file(nem_element, nem_name, "nem") nem_file = os.path.join(self.session.session_dir, nem_name)
emanexml.create_file(nem_element, "nem", nem_file)
# create and write shim document # create and write shim document
shim_element = etree.Element("shim", name="%s SHIM" % self.name, library=self.shim_library) shim_element = etree.Element("shim", name="%s SHIM" % self.name, library=self.shim_library)
@ -96,7 +99,8 @@ class EmaneCommEffectModel(emanemodel.EmaneModel):
if ff.strip() != "": if ff.strip() != "":
emanexml.add_param(shim_element, "filterfile", ff) emanexml.add_param(shim_element, "filterfile", ff)
self.create_file(shim_element, shim_name, "shim") shim_file = os.path.join(self.session.session_dir, shim_name)
emanexml.create_file(shim_element, "shim", shim_file)
def linkconfig(self, netif, bw=None, delay=None, loss=None, duplicate=None, jitter=None, netif2=None): def linkconfig(self, netif, bw=None, delay=None, loss=None, duplicate=None, jitter=None, netif2=None):
""" """

View file

@ -5,8 +5,6 @@ emane.py: definition of an Emane class for implementing configuration control of
import os import os
import threading import threading
from lxml import etree
from core import CoreCommandError from core import CoreCommandError
from core import constants from core import constants
from core import logger from core import logger
@ -32,7 +30,6 @@ from core.enumerations import NodeTypes
from core.enumerations import RegisterTlvs from core.enumerations import RegisterTlvs
from core.misc import nodeutils from core.misc import nodeutils
from core.misc import utils from core.misc import utils
from core.misc.ipaddress import MacAddress
from core.xml import emanexml from core.xml import emanexml
try: try:
@ -56,159 +53,6 @@ EMANE_MODELS = [
] ]
def build_node_platform_xml(emane_manager, control_net, node, nem_id):
nem_entries = {}
platform_xmls = {}
if node.model is None:
logger.info("warning: EmaneNode %s has no associated model", node.name)
return nem_entries
for netif in node.netifs():
# build nem xml
nem_name = node.model.nem_name(netif)
nem_element = etree.Element("nem", id=str(nem_id), name=netif.localname, definition=nem_name)
# 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_name = "n%strans%s.xml" % (node.objid, transport_type.lower())
transport_element = etree.SubElement(nem_element, "transport", definition=transport_name)
# add transport parameter
emanexml.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 not platform_element:
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)
emanexml.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 = emane_manager._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)
emanexml.create_file(platform_element, doc_name, file_path)
return nem_id
def build_transport_xml(emane_manager, node, transport_type):
transport_element = etree.Element(
"transport",
name="%s Transport" % transport_type.capitalize(),
library="trans%s" % transport_type.lower()
)
# add bitrate
emanexml.add_param(transport_element, "bitrate", "0")
# get emane model cnfiguration
config = emane_manager.get_configs(node_id=node.objid, config_type=node.model.name)
flowcontrol = config.get("flowcontrolenable", "0") == "1"
if "virtual" in transport_type.lower():
device_path = "/dev/net/tun_flowctl"
if not os.path.exists(device_path):
device_path = "/dev/net/tun"
emanexml.add_param(transport_element, "devicepath", device_path)
if flowcontrol:
emanexml.add_param(transport_element, "flowcontrolenable", "on")
doc_name = "transport"
file_name = "n%strans%s.xml" % (node.objid, transport_type.lower())
file_path = os.path.join(emane_manager.session.session_dir, file_name)
emanexml.create_file(transport_element, doc_name, file_path)
def build_xml_files(emane_manager, node):
if node.model is None:
return
# get model configurations
config = emane_manager.getifcconfig(node.model.object_id, None, node.model.name)
if not config:
return
# build XML for overall network (EmaneNode) configs
node.model.build_xml_files(config)
# build XML for specific interface (NEM) configs
need_virtual = False
need_raw = False
vtype = "virtual"
rtype = "raw"
for netif in node.netifs():
# check for interface specific emane configuration and write xml files, if needed
config = emane_manager.getifcconfig(node.model.object_id, netif, node.model.name)
if config:
node.model.build_xml_files(config, netif)
# check transport type needed for interface
if "virtual" in netif.transport_type:
need_virtual = True
vtype = netif.transport_type
else:
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)
if need_raw:
build_transport_xml(emane_manager, node, rtype)
class EmaneManager(ModelManager): class EmaneManager(ModelManager):
""" """
EMANE controller object. Lives in a Session instance and is used for EMANE controller object. Lives in a Session instance and is used for
@ -217,7 +61,6 @@ class EmaneManager(ModelManager):
""" """
name = "emane" name = "emane"
config_type = RegisterTlvs.EMULATION_SERVER.value config_type = RegisterTlvs.EMULATION_SERVER.value
_hwaddr_prefix = "02:02"
SUCCESS, NOT_NEEDED, NOT_READY = (0, 1, 2) SUCCESS, NOT_NEEDED, NOT_READY = (0, 1, 2)
EVENTCFGVAR = "LIBEMANEEVENTSERVICECONFIG" EVENTCFGVAR = "LIBEMANEEVENTSERVICECONFIG"
DEFAULT_LOG_LEVEL = 3 DEFAULT_LOG_LEVEL = 3
@ -722,7 +565,7 @@ class EmaneManager(ModelManager):
# 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 = build_node_platform_xml(self, ctrlnet, emane_node, nemid) nemid = emanexml.build_node_platform_xml(self, ctrlnet, emane_node, nemid)
def buildnemxml(self): def buildnemxml(self):
""" """
@ -731,7 +574,7 @@ class EmaneManager(ModelManager):
""" """
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]
build_xml_files(self, emane_node) emanexml.build_xml_files(self, emane_node)
def buildtransportxml(self): def buildtransportxml(self):
""" """
@ -765,13 +608,7 @@ class EmaneManager(ModelManager):
dev = self.get_config("eventservicedevice") dev = self.get_config("eventservicedevice")
event_element = etree.Element("emaneeventmsgsvc") emanexml.create_event_service_xml(group, port, dev, self.session.session_dir)
for name, value in (("group", group), ("port", port), ("device", dev), ("mcloop", "1"), ("ttl", "32")):
sub_element = etree.SubElement(event_element, name)
sub_element.text = value
file_name = "libemaneeventservice.xml"
file_path = os.path.join(self.session.session_dir, file_name)
emanexml.create_file(event_element, "emaneeventmsgsvc", file_path)
def startdaemons(self): def startdaemons(self):
""" """

View file

@ -3,8 +3,6 @@ Defines Emane Models used within CORE.
""" """
import os import os
from lxml import etree
from core import logger from core import logger
from core.conf import ConfigGroup from core.conf import ConfigGroup
from core.emane import emanemanifest from core.emane import emanemanifest
@ -58,82 +56,26 @@ class EmaneModel(WirelessModel):
:param interface: interface for the emane node :param interface: interface for the emane node
:return: nothing :return: nothing
""" """
# create document and write to disk nem_name = emanexml.nem_file_name(self, interface)
self.create_nem_xml(interface) mac_name = emanexml.mac_file_name(self, interface)
phy_name = emanexml.phy_file_name(self, interface)
# create mac document and write to disk
self.create_mac_xml(interface, config)
# create phy document and write to disk
self.create_phy_xml(interface, config)
def create_nem_xml(self, interface):
"""
Create the nem xml document.
:param interface: interface for the emane node
:return: nothing
"""
nem_element = etree.Element("nem", name="%s NEM" % self.name)
# add transport
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"
transport_type = "n%strans%s.xml" % (self.object_id, transport_type) transport_name = emanexml.transport_file_name(self.object_id, transport_type)
etree.SubElement(nem_element, "transport", definition=transport_type)
# create mac # create nem xml file
mac_name = self.mac_name(interface) nem_file = os.path.join(self.session.session_dir, nem_name)
etree.SubElement(nem_element, "mac", definition=mac_name) emanexml.create_nem_xml(self, nem_file, transport_name, mac_name, phy_name)
# create phy # create mac xml file
phy_name = self.phy_name(interface) mac_file = os.path.join(self.session.session_dir, mac_name)
etree.SubElement(nem_element, "phy", definition=phy_name) emanexml.create_mac_xml(self, config, mac_file)
# write out xml # create phy xml file
nem_name = self.nem_name(interface) phy_file = os.path.join(self.session.session_dir, phy_name)
self.create_file(nem_element, nem_name, "nem") emanexml.create_phy_xml(self, config, phy_file)
def create_mac_xml(self, interface, config):
"""
Create the mac xml document.
:param interface: interface for the emane node
:param dict config: all current configuration values, mac + phy
:return: nothing
"""
if not self.mac_library:
raise ValueError("must define emane model library")
mac_element = etree.Element("mac", name="%s MAC" % self.name, library=self.mac_library)
emanexml.add_configurations(mac_element, self.mac_config, config, self.config_ignore)
# write out xml
mac_name = self.mac_name(interface)
self.create_file(mac_element, mac_name, "mac")
def create_phy_xml(self, interface, config):
"""
Create the phy xml document.
:param interface: interface for the emane node
:param dict config: all current configuration values, mac + phy
:return: nothing
"""
phy_element = etree.Element("phy", name="%s PHY" % self.name)
if self.phy_library:
phy_element.set("library", self.phy_library)
emanexml.add_configurations(phy_element, self.phy_config, config, self.config_ignore)
# write out xml
phy_name = self.phy_name(interface)
self.create_file(phy_element, phy_name, "phy")
def create_file(self, xml_element, file_name, doc_name):
file_path = os.path.join(self.session.session_dir, file_name)
emanexml.create_file(xml_element, doc_name, file_path)
def post_startup(self): def post_startup(self):
""" """
@ -143,67 +85,6 @@ class EmaneModel(WirelessModel):
""" """
logger.info("emane model(%s) has no post setup tasks", self.name) logger.info("emane model(%s) has no post setup tasks", self.name)
def _basename(self, interface=None):
"""
Create name that is leveraged for configuration file creation.
:param interface: interface for this model
:return: basename used for file creation
:rtype: str
"""
name = "n%s" % self.object_id
if interface:
node_id = interface.node.objid
if self.session.emane.getifcconfig(node_id, interface, self.name):
name = interface.localname.replace(".", "_")
return "%s%s" % (name, self.name)
def nem_name(self, interface=None):
"""
Return the string name for the NEM XML file, e.g. "n3rfpipenem.xml"
:param interface: interface for this model
:return: nem xml filename
:rtype: str
"""
basename = self._basename(interface)
append = ""
if interface and interface.transport_type == "raw":
append = "_raw"
return "%snem%s.xml" % (basename, append)
def shim_name(self, interface=None):
"""
Return the string name for the SHIM XML file, e.g. "commeffectshim.xml"
:param interface: interface for this model
:return: shim xml filename
:rtype: str
"""
return "%sshim.xml" % self._basename(interface)
def mac_name(self, interface=None):
"""
Return the string name for the MAC XML file, e.g. "n3rfpipemac.xml"
:param interface: interface for this model
:return: mac xml filename
:rtype: str
"""
return "%smac.xml" % self._basename(interface)
def phy_name(self, interface=None):
"""
Return the string name for the PHY XML file, e.g. "n3rfpipephy.xml"
:param interface: interface for this model
:return: phy xml filename
:rtype: str
"""
return "%sphy.xml" % self._basename(interface)
def update(self, moved, moved_netifs): def update(self, moved, moved_netifs):
""" """
Invoked from MobilityModel when nodes are moved; this causes Invoked from MobilityModel when nodes are moved; this causes

View file

@ -1,9 +1,14 @@
import os
from lxml import etree from lxml import etree
from core import logger from core import logger
from core.misc import utils from core.misc import utils
from core.misc.ipaddress import MacAddress
from core.xml import corexml from core.xml import corexml
_hwaddr_prefix = "02:02"
def _value_to_params(value): def _value_to_params(value):
""" """
@ -62,3 +67,326 @@ def add_configurations(xml_element, configurations, config, config_ignore):
etree.SubElement(params_element, "item", value=param) etree.SubElement(params_element, "item", value=param)
else: else:
add_param(xml_element, name, value) add_param(xml_element, name, value)
def build_node_platform_xml(emane_manager, control_net, node, nem_id):
"""
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
: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)
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)
# 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 not platform_element:
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
def build_xml_files(emane_manager, node):
"""
Generate emane xml files required for node.
:param core.emane.emanemanager.EmaneManager emane_manager: emane manager with emane configurations
:param core.emane.nodes.EmaneNode node: node to write platform xml for
:return: nothing
"""
logger.debug("building all emane xml for node(%s): %s", node, node.name)
if node.model is None:
return
# get model configurations
config = emane_manager.get_configs(node.model.object_id, node.model.name)
if not config:
return
# build XML for overall network (EmaneNode) configs
node.model.build_xml_files(config)
# build XML for specific interface (NEM) configs
need_virtual = False
need_raw = False
vtype = "virtual"
rtype = "raw"
for netif in node.netifs():
# check for interface specific emane configuration and write xml files, if needed
config = emane_manager.getifcconfig(node.model.object_id, netif, node.model.name)
if config:
node.model.build_xml_files(config, netif)
# check transport type needed for interface
if "virtual" in netif.transport_type:
need_virtual = True
vtype = netif.transport_type
else:
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)
if need_raw:
build_transport_xml(emane_manager, node, rtype)
def build_transport_xml(emane_manager, node, transport_type):
"""
Build transport xml file for node and transport type.
:param core.emane.emanemanager.EmaneManager emane_manager: emane manager with emane configurations
:param core.emane.nodes.EmaneNode node: node to write platform xml for
:param str transport_type: transport type to build xml for
:return: nothing
"""
transport_element = etree.Element(
"transport",
name="%s Transport" % transport_type.capitalize(),
library="trans%s" % transport_type.lower()
)
# add bitrate
add_param(transport_element, "bitrate", "0")
# get emane model cnfiguration
config = emane_manager.get_configs(node.objid, node.model.name)
flowcontrol = config.get("flowcontrolenable", "0") == "1"
if "virtual" in transport_type.lower():
device_path = "/dev/net/tun_flowctl"
if not os.path.exists(device_path):
device_path = "/dev/net/tun"
add_param(transport_element, "devicepath", device_path)
if flowcontrol:
add_param(transport_element, "flowcontrolenable", "on")
doc_name = "transport"
file_name = transport_file_name(node.objid, transport_type)
file_path = os.path.join(emane_manager.session.session_dir, file_name)
create_file(transport_element, doc_name, file_path)
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 str file_path: path to write file to
:return: nothing
"""
phy_element = etree.Element("phy", name="%s PHY" % emane_model.name)
if emane_model.phy_library:
phy_element.set("library", emane_model.phy_library)
add_configurations(phy_element, emane_model.phy_config, config, emane_model.config_ignore)
create_file(phy_element, "phy", file_path)
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 str file_path: path to write file to
:return: nothing
"""
if not emane_model.mac_library:
raise ValueError("must define emane model library")
mac_element = etree.Element("mac", name="%s MAC" % emane_model.name, library=emane_model.mac_library)
add_configurations(mac_element, emane_model.mac_config, config, emane_model.config_ignore)
create_file(mac_element, "mac", file_path)
def create_nem_xml(emane_model, 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 str nem_file: nem file path to write
:param str transport_definition: transport file definition path
:param str mac_definition: mac file definition path
:param str phy_definition: phy file definition path
:return: nothing
"""
nem_element = etree.Element("nem", name="%s NEM" % emane_model.name)
etree.SubElement(nem_element, "transport", definition=transport_definition)
etree.SubElement(nem_element, "mac", definition=mac_definition)
etree.SubElement(nem_element, "phy", definition=phy_definition)
create_file(nem_element, "nem", nem_file)
def create_event_service_xml(group, port, device, file_directory):
event_element = etree.Element("emaneeventmsgsvc")
for name, value in (("group", group), ("port", port), ("device", device), ("mcloop", "1"), ("ttl", "32")):
sub_element = etree.SubElement(event_element, name)
sub_element.text = value
file_name = "libemaneeventservice.xml"
file_path = os.path.join(file_directory, file_name)
create_file(event_element, "emaneeventmsgsvc", file_path)
def transport_file_name(node_id, transport_type):
"""
Create name for a transport xml file.
:param int node_id: node id to generate transport file name for
:param str transport_type: transport type to generate transport file
:return:
"""
return "n%strans%s.xml" % (node_id, transport_type)
def _basename(emane_model, interface=None):
"""
Create name that is leveraged for configuration file creation.
:param interface: interface for this model
:return: basename used for file creation
:rtype: str
"""
name = "n%s" % emane_model.object_id
if interface:
node_id = interface.node.objid
if emane_model.session.emane.getifcconfig(node_id, interface, emane_model.name):
name = interface.localname.replace(".", "_")
return "%s%s" % (name, emane_model.name)
def nem_file_name(emane_model, interface=None):
"""
Return the string name for the NEM XML file, e.g. "n3rfpipenem.xml"
:param core.emane.emanemodel.EmaneModel emane_model: emane model to create phy xml for
:param interface: interface for this model
:return: nem xml filename
:rtype: str
"""
basename = _basename(emane_model, interface)
append = ""
if interface and interface.transport_type == "raw":
append = "_raw"
return "%snem%s.xml" % (basename, append)
def shim_file_name(emane_model, interface=None):
"""
Return the string name for the SHIM XML file, e.g. "commeffectshim.xml"
:param core.emane.emanemodel.EmaneModel emane_model: emane model to create phy xml for
:param interface: interface for this model
:return: shim xml filename
:rtype: str
"""
return "%sshim.xml" % _basename(emane_model, interface)
def mac_file_name(emane_model, interface=None):
"""
Return the string name for the MAC XML file, e.g. "n3rfpipemac.xml"
:param core.emane.emanemodel.EmaneModel emane_model: emane model to create phy xml for
:param interface: interface for this model
:return: mac xml filename
:rtype: str
"""
return "%smac.xml" % _basename(emane_model, interface)
def phy_file_name(emane_model, interface=None):
"""
Return the string name for the PHY XML file, e.g. "n3rfpipephy.xml"
:param core.emane.emanemodel.EmaneModel emane_model: emane model to create phy xml for
:param interface: interface for this model
:return: phy xml filename
:rtype: str
"""
return "%sphy.xml" % _basename(emane_model, interface)