pass over emane code to cleanup methods and some documentation

This commit is contained in:
Blake J. Harnden 2018-03-28 13:58:49 -07:00
parent ef48052d41
commit b7327a5798
9 changed files with 356 additions and 267 deletions

View file

@ -1,5 +1,5 @@
"""
bypass.py: EMANE Bypass model for CORE
EMANE Bypass model for CORE
"""
from core.emane.emanemodel import EmaneModel
@ -9,8 +9,8 @@ from core.enumerations import ConfigDataTypes
class EmaneBypassModel(EmaneModel):
name = "emane_bypass"
config_matrix = [
("none", ConfigDataTypes.BOOL.value, "0",
"True,False", "There are no parameters for the bypass model."),
("none", ConfigDataTypes.BOOL.value, "0", "True,False",
"There are no parameters for the bypass model."),
]
# value groupings
@ -19,36 +19,55 @@ class EmaneBypassModel(EmaneModel):
def __init__(self, session, object_id=None):
EmaneModel.__init__(self, session, object_id)
def buildnemxmlfiles(self, e, ifc):
def build_xml_files(self, emane_manager, interface):
"""
Build the necessary nem, mac, and phy XMLs in the given path.
If an individual NEM has a nonstandard config, we need to build
that file also. Otherwise the WLAN-wide nXXemane_bypassnem.xml,
nXXemane_bypassmac.xml, nXXemane_bypassphy.xml are used.
:param core.emane.emanemanager.EmaneManager emane_manager: core emane manager
:param interface: interface for the emane node
:return: nothing
"""
values = e.getifcconfig(self.object_id, self.name, self.getdefaultvalues(), ifc)
values = emane_manager.getifcconfig(self.object_id, self.name, self.getdefaultvalues(), interface)
if values is None:
return
nemdoc = e.xmldoc("nem")
nem = nemdoc.getElementsByTagName("nem").pop()
nem.setAttribute("name", "BYPASS NEM")
e.appendtransporttonem(nemdoc, nem, self.object_id, ifc)
mactag = nemdoc.createElement("mac")
mactag.setAttribute("definition", self.macxmlname(ifc))
nem.appendChild(mactag)
phytag = nemdoc.createElement("phy")
phytag.setAttribute("definition", self.phyxmlname(ifc))
nem.appendChild(phytag)
e.xmlwrite(nemdoc, self.nemxmlname(ifc))
macdoc = e.xmldoc("mac")
mac = macdoc.getElementsByTagName("mac").pop()
mac.setAttribute("name", "BYPASS MAC")
mac.setAttribute("library", "bypassmaclayer")
e.xmlwrite(macdoc, self.macxmlname(ifc))
# retrieve xml names
nem_name = self.nem_name(interface)
mac_name = self.mac_name(interface)
phy_name = self.phy_name(interface)
phydoc = e.xmldoc("phy")
phy = phydoc.getElementsByTagName("phy").pop()
phy.setAttribute("name", "BYPASS PHY")
phy.setAttribute("library", "bypassphylayer")
e.xmlwrite(phydoc, self.phyxmlname(ifc))
# create nem document
nem_document = emane_manager.xmldoc("nem")
nem_element = nem_document.getElementsByTagName("nem").pop()
nem_element.setAttribute("name", "BYPASS NEM")
emane_manager.appendtransporttonem(nem_document, nem_element, self.object_id, interface)
# create link to mac definition
mac_element = nem_document.createElement("mac")
mac_element.setAttribute("definition", mac_name)
nem_element.appendChild(mac_element)
# create link to phy definition
phy_element = nem_document.createElement("phy")
phy_element.setAttribute("definition", phy_name)
nem_element.appendChild(phy_element)
# write nem document
emane_manager.xmlwrite(nem_document, nem_name)
# create and write mac document
mac_document = emane_manager.xmldoc("mac")
mac_element = mac_document.getElementsByTagName("mac").pop()
mac_element.setAttribute("name", "BYPASS MAC")
mac_element.setAttribute("library", "bypassmaclayer")
emane_manager.xmlwrite(mac_document, mac_name)
# create and write phy document
phy_document = emane_manager.xmldoc("phy")
phy_element = phy_document.getElementsByTagName("phy").pop()
phy_element.setAttribute("name", "BYPASS PHY")
phy_element.setAttribute("library", "bypassphylayer")
emane_manager.xmlwrite(phy_document, phy_name)

View file

@ -9,10 +9,7 @@ from core.enumerations import ConfigDataTypes
try:
from emanesh.events.commeffectevent import CommEffectEvent
except ImportError:
try:
from emane.events.commeffectevent import CommEffectEvent
except ImportError:
logger.info("emane 0.9.1+ not found")
logger.info("emane 1.2.1 not found")
def convert_none(x):
@ -28,10 +25,9 @@ def convert_none(x):
class EmaneCommEffectModel(EmaneModel):
# model name
name = "emane_commeffect"
# CommEffect parameters
_confmatrix_shim_base = [
config_matrix = [
("filterfile", ConfigDataTypes.STRING.value, "",
"", "filter file"),
("groupid", ConfigDataTypes.UINT32.value, "0",
@ -40,54 +36,64 @@ class EmaneCommEffectModel(EmaneModel):
"On,Off", "enable promiscuous mode"),
("receivebufferperiod", ConfigDataTypes.FLOAT.value, "1.0",
"", "receivebufferperiod"),
]
_confmatrix_shim_091 = [
("defaultconnectivitymode", ConfigDataTypes.BOOL.value, "1",
"On,Off", "defaultconnectivity"),
]
_confmatrix_shim = _confmatrix_shim_base + _confmatrix_shim_091
config_matrix = _confmatrix_shim
# value groupings
config_groups = "CommEffect SHIM Parameters:1-%d" % len(_confmatrix_shim)
config_groups = "CommEffect SHIM Parameters:1-%d" % len(config_matrix)
def __init__(self, session, object_id=None):
EmaneModel.__init__(self, session, object_id)
def buildnemxmlfiles(self, e, ifc):
def build_xml_files(self, emane_manager, interface):
"""
Build the necessary nem and commeffect XMLs in the given path.
If an individual NEM has a nonstandard config, we need to build
that file also. Otherwise the WLAN-wide
nXXemane_commeffectnem.xml, nXXemane_commeffectshim.xml are used.
:param core.emane.emanemanager.EmaneManager emane_manager: core emane manager
:param interface: interface for the emane node
:return: nothing
"""
values = e.getifcconfig(self.object_id, self.name, self.getdefaultvalues(), ifc)
values = emane_manager.getifcconfig(self.object_id, self.name, self.getdefaultvalues(), interface)
if values is None:
return
shimdoc = e.xmldoc("shim")
shim = shimdoc.getElementsByTagName("shim").pop()
# retrieve xml names
nem_name = self.nem_name(interface)
shim_name = self.shim_name(interface)
shim_document = emane_manager.xmldoc("shim")
shim = shim_document.getElementsByTagName("shim").pop()
shim.setAttribute("name", "commeffect SHIM")
shim.setAttribute("library", "commeffectshim")
names = self.getnames()
shimnames = list(names[:len(self._confmatrix_shim)])
shimnames.remove("filterfile")
shim_names = list(names[:len(self.config_matrix)])
shim_names.remove("filterfile")
# append all shim options (except filterfile) to shimdoc
map(lambda n: shim.appendChild(e.xmlparam(shimdoc, n, self.valueof(n, values))), shimnames)
for name in shim_names:
value = self.valueof(name, values)
param = emane_manager.xmlparam(shim_document, name, value)
shim.appendChild(param)
# empty filterfile is not allowed
ff = self.valueof("filterfile", values)
if ff.strip() != "":
shim.appendChild(e.xmlparam(shimdoc, "filterfile", ff))
e.xmlwrite(shimdoc, self.shimxmlname(ifc))
shim.appendChild(emane_manager.xmlparam(shim_document, "filterfile", ff))
emane_manager.xmlwrite(shim_document, shim_name)
nemdoc = e.xmldoc("nem")
nem = nemdoc.getElementsByTagName("nem").pop()
nem.setAttribute("name", "commeffect NEM")
nem.setAttribute("type", "unstructured")
e.appendtransporttonem(nemdoc, nem, self.object_id, ifc)
nem.appendChild(e.xmlshimdefinition(nemdoc, self.shimxmlname(ifc)))
e.xmlwrite(nemdoc, self.nemxmlname(ifc))
nem_document = emane_manager.xmldoc("nem")
nem_element = nem_document.getElementsByTagName("nem").pop()
nem_element.setAttribute("name", "commeffect NEM")
nem_element.setAttribute("type", "unstructured")
emane_manager.appendtransporttonem(nem_document, nem_element, self.object_id, interface)
shim_xml = emane_manager.xmlshimdefinition(nem_document, shim_name)
nem_element.appendChild(shim_xml)
emane_manager.xmlwrite(nem_document, nem_name)
def linkconfig(self, netif, bw=None, delay=None, loss=None, duplicate=None, jitter=None, netif2=None):
"""
@ -110,7 +116,7 @@ class EmaneCommEffectModel(EmaneModel):
nemid = emane_node.getnemid(netif)
nemid2 = emane_node.getnemid(netif2)
mbw = bw
logger.info("sending comm effect event")
logger.info("sending comm effect event")
event.append(
nemid,
latency=convert_none(delay),

View file

@ -33,12 +33,7 @@ try:
from emane.events import LocationEvent
from emane.events.eventserviceexception import EventServiceException
except ImportError:
try:
from emanesh.events import EventService
from emanesh.events import LocationEvent
from emanesh.events.eventserviceexception import EventServiceException
except ImportError:
logger.info("emane 0.9.1+ not found")
logger.info("emane 1.2.1 not found")
EMANE_MODELS = [
EmaneRfPipeModel,
@ -341,7 +336,7 @@ class EmaneManager(ConfigurableManager):
with self._emane_node_lock:
for key in sorted(self._emane_nodes.keys()):
emane_node = self._emane_nodes[key]
logger.debug("post startup for emane node: %s - %s", emane_node.objid, emane_node.name)
logger.debug("post startup for emane node: %s - %s", emane_node.objid, emane_node.name)
emane_node.model.post_startup(self)
for netif in emane_node.netifs():
x, y, z = netif.node.position.get()
@ -680,7 +675,7 @@ class EmaneManager(ConfigurableManager):
"""
for key in sorted(self._emane_nodes.keys()):
emane_node = self._emane_nodes[key]
emane_node.buildnemxmlfiles(self)
emane_node.build_xml_files(self)
def appendtransporttonem(self, doc, nem, nodenum, ifc=None):
"""
@ -1061,7 +1056,7 @@ class EmaneGlobalModel(EmaneModel):
def __init__(self, session, object_id=None):
EmaneModel.__init__(self, session, object_id)
def buildnemxmlfiles(self, e, ifc):
def build_xml_files(self, emane_manager, interface):
"""
Build the necessary nem, mac, and phy XMLs in the given path.
"""

View file

@ -11,35 +11,14 @@ from core.xml import xmlutils
class EmaneModel(WirelessModel):
"""
EMANE models inherit from this parent class, which takes care of
handling configuration messages based on the _confmatrix list of
handling configuration messages based on the list of
configurable parameters. Helper functions also live here.
"""
_prefix = {
"y": 1e-24, # yocto
"z": 1e-21, # zepto
"a": 1e-18, # atto
"f": 1e-15, # femto
"p": 1e-12, # pico
"n": 1e-9, # nano
"u": 1e-6, # micro
"m": 1e-3, # mili
"c": 1e-2, # centi
"d": 1e-1, # deci
"k": 1e3, # kilo
"M": 1e6, # mega
"G": 1e9, # giga
"T": 1e12, # tera
"P": 1e15, # peta
"E": 1e18, # exa
"Z": 1e21, # zetta
"Y": 1e24, # yotta
}
@classmethod
def configure_emane(cls, session, config_data):
"""
Handle configuration messages for setting up a model.
Pass the Emane object as the manager object.
Handle configuration messages for configuring an emane model.
:param core.session.Session session: session to configure emane
:param core.conf.ConfigData config_data: configuration data for carrying out a configuration
@ -55,13 +34,17 @@ class EmaneModel(WirelessModel):
"""
logger.info("emane model(%s) has no post setup tasks", self.name)
def buildnemxmlfiles(self, e, ifc):
def build_xml_files(self, emane_manager, interface):
"""
Build the necessary nem, mac, and phy XMLs in the given path.
:param core.emane.emanemanager.EmaneManager emane_manager: core emane manager
:param interface: interface for the emane node
:return: nothing
"""
raise NotImplementedError
def buildplatformxmlnementry(self, doc, n, ifc):
def build_nem_xml(self, doc, emane_node, interface):
"""
Build the NEM definition that goes into the platform.xml file.
@ -71,93 +54,125 @@ class EmaneModel(WirelessModel):
or per-EmaneNode config (e.g. <nem definition="n1emane_rfpipe.xml" id="1">.
This can be overriden by a model for NEM flexibility; n is the EmaneNode.
<nem name="NODE-001" definition="rfpipenem.xml">
:param xml.dom.minidom.Document doc: xml document
:param core.emane.nodes.EmaneNode emane_node: emane node to get information from
:param interface: interface for the emane node
:return: created platform xml
"""
nem = doc.createElement("nem")
nem.setAttribute("name", ifc.localname)
# if this netif contains a non-standard (per-interface) config,
# then we need to use a more specific xml file here
nem.setAttribute("definition", self.nemxmlname(ifc))
nem_name = self.nem_name(interface)
nem = doc.createElement("nem")
nem.setAttribute("name", interface.localname)
nem.setAttribute("definition", nem_name)
return nem
def buildplatformxmltransportentry(self, doc, n, ifc):
def build_transport_xml(self, doc, emane_node, interface):
"""
Build the transport definition that goes into the platform.xml file.
This returns an XML element that will added to the nem definition.
This returns an XML element that will be added to the nem definition.
This default method supports raw and virtual transport types, but may be
overriden by a model to support the e.g. pluggable virtual transport.
n is the EmaneNode.
"""
ttype = ifc.transport_type
if not ttype:
logger.info("warning: %s interface type unsupported!", ifc.name)
ttype = "raw"
overridden by a model to support the e.g. pluggable virtual transport.
<transport definition="transvirtual.xml" group="1">
<param name="device" value="n1.0.158" />
</transport>
:param xml.dom.minidom.Document doc: xml document
:param core.emane.nodes.EmaneNode emane_node: emane node to get information from
:param interface: interface for the emane node
:return: created transport xml
"""
transport_type = interface.transport_type
if not transport_type:
logger.info("warning: %s interface type unsupported!", interface.name)
transport_type = "raw"
transport_name = emane_node.transportxmlname(transport_type)
transport = doc.createElement("transport")
transport.setAttribute("definition", transport_name)
trans = doc.createElement("transport")
trans.setAttribute("definition", n.transportxmlname(ttype))
param = doc.createElement("param")
param.setAttribute("name", "device")
param.setAttribute("value", interface.name)
if ttype == "raw":
# raw RJ45 name e.g. "eth0"
param.setAttribute("value", ifc.name)
else:
# virtual TAP name e.g. "n3.0.17"
param.setAttribute("value", ifc.localname)
param.setAttribute("value", ifc.name)
transport.appendChild(param)
return transport
trans.appendChild(param)
return trans
def basename(self, interface=None):
def _basename(self, interface=None):
"""
Return the string that other names are based on.
If a specific config is stored for a node"s interface, a unique
filename is needed; otherwise the name of the EmaneNode is used.
Create name that is leveraged for configuration file creation.
:param interface: interface for this model
:return: basename used for file creation
:rtype: str
"""
emane = self.session.emane
name = "n%s" % self.object_id
emane_manager = self.session.emane
if interface is not None:
nodenum = interface.node.objid
# Adamson change - use getifcconfig() to get proper result
# if emane.getconfig(nodenum, self._name, None)[1] is not None:
if emane.getifcconfig(nodenum, self.name, None, interface) is not None:
if interface:
node_id = interface.node.objid
if emane_manager.getifcconfig(node_id, self.name, None, interface) is not None:
name = interface.localname.replace(".", "_")
return "%s%s" % (name, self.name)
def nemxmlname(self, interface=None):
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" % (self.basename(interface), append)
return "%snem%s.xml" % (basename, append)
def shimxmlname(self, ifc=None):
def shim_name(self, interface=None):
"""
Return the string name for the SHIM XML file, e.g. "commeffectshim.xml"
"""
return "%sshim.xml" % self.basename(ifc)
def macxmlname(self, ifc=None):
: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"
"""
return "%smac.xml" % self.basename(ifc)
def phyxmlname(self, ifc=None):
: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(ifc)
return "%sphy.xml" % self._basename(interface)
def update(self, moved, moved_netifs):
"""
invoked from MobilityModel when nodes are moved; this causes
EMANE location events to be generated for the nodes in the moved
list, making EmaneModels compatible with Ns2ScriptedMobility
Invoked from MobilityModel when nodes are moved; this causes
emane location events to be generated for the nodes in the moved
list, making EmaneModels compatible with Ns2ScriptedMobility.
:param bool moved: were nodes moved
:param list moved_netifs: interfaces that were moved
:return:
"""
try:
wlan = self.session.get_object(self.object_id)
@ -168,17 +183,28 @@ class EmaneModel(WirelessModel):
def linkconfig(self, netif, bw=None, delay=None, loss=None, duplicate=None, jitter=None, netif2=None):
"""
Invoked when a Link Message is received. Default is unimplemented.
:param core.netns.vif.Veth netif: interface one
:param bw: bandwidth to set to
:param delay: packet delay to set to
:param loss: packet loss to set to
:param duplicate: duplicate percentage to set to
:param jitter: jitter to set to
:param core.netns.vif.Veth netif2: interface two
:return: nothing
"""
warntxt = "EMANE model %s does not support link " % self.name
warntxt += "configuration, dropping Link Message"
logger.warn(warntxt)
logger.warn("emane model(%s) does not support link configuration", self.name)
@staticmethod
def valuestrtoparamlist(dom, name, value):
def value_to_params(doc, name, value):
"""
Helper to convert a parameter to a paramlist.
Returns a an XML paramlist, or None if the value does not expand to
Helper to convert a parameter to a paramlist. Returns an XML paramlist, or None if the value does not expand to
multiple values.
:param xml.dom.minidom.Document doc: xml document
:param name: name of element for params
:param str value: value string to convert to tuple
:return: xml document with added params or None, when an invalid value has been provided
"""
try:
values = utils.make_tuple_fromstr(value, str)
@ -192,4 +218,4 @@ class EmaneModel(WirelessModel):
if len(values) < 2:
return None
return xmlutils.add_param_list_to_parent(dom, parent=None, name=name, values=values)
return xmlutils.add_param_list_to_parent(doc, parent=None, name=name, values=values)

View file

@ -16,7 +16,7 @@ class EmaneIeee80211abgModel(EmaneModel):
xml_path = "/usr/share/emane/xml/models/mac/ieee80211abg"
# MAC parameters
_confmatrix_mac = [
_config_mac = [
("aifs", ConfigDataTypes.STRING.value, "0:2 1:2 2:2 3:1", "", "arbitration inter frame space (0-4:aifs)"),
("channelactivityestimationtimer", ConfigDataTypes.FLOAT.value, "0.1", "",
"Defines channel activity estimation timer in seconds"),
@ -46,58 +46,69 @@ class EmaneIeee80211abgModel(EmaneModel):
]
# PHY parameters from Universal PHY
_confmatrix_phy = EmaneUniversalModel.config_matrix
_config_phy = EmaneUniversalModel.config_matrix
config_matrix = _confmatrix_mac + _confmatrix_phy
config_matrix = _config_mac + _config_phy
# value groupings
config_groups = "802.11 MAC Parameters:1-%d|Universal PHY Parameters:%d-%d" % (
len(_confmatrix_mac), len(_confmatrix_mac) + 1, len(config_matrix))
len(_config_mac), len(_config_mac) + 1, len(config_matrix))
def __init__(self, session, object_id=None):
EmaneModel.__init__(self, session, object_id)
def buildnemxmlfiles(self, e, ifc):
def build_xml_files(self, emane_manager, interface):
"""
Build the necessary nem, mac, and phy XMLs in the given path.
If an individual NEM has a nonstandard config, we need to build
that file also. Otherwise the WLAN-wide
nXXemane_ieee80211abgnem.xml, nXXemane_ieee80211abgemac.xml,
nXXemane_ieee80211abgphy.xml are used.
:param core.emane.emanemanager.EmaneManager emane_manager: core emane manager
:param interface: interface for the emane node
:return: nothing
"""
values = e.getifcconfig(self.object_id, self.name, self.getdefaultvalues(), ifc)
values = emane_manager.getifcconfig(self.object_id, self.name, self.getdefaultvalues(), interface)
if values is None:
return
nemdoc = e.xmldoc("nem")
nem = nemdoc.getElementsByTagName("nem").pop()
nem.setAttribute("name", "ieee80211abg NEM")
e.appendtransporttonem(nemdoc, nem, self.object_id, ifc)
mactag = nemdoc.createElement("mac")
mactag.setAttribute("definition", self.macxmlname(ifc))
nem.appendChild(mactag)
phytag = nemdoc.createElement("phy")
phytag.setAttribute("definition", self.phyxmlname(ifc))
nem.appendChild(phytag)
e.xmlwrite(nemdoc, self.nemxmlname(ifc))
macdoc = e.xmldoc("mac")
mac = macdoc.getElementsByTagName("mac").pop()
mac.setAttribute("name", "ieee80211abg MAC")
mac.setAttribute("library", "ieee80211abgmaclayer")
# retrieve xml names
nem_name = self.nem_name(interface)
mac_name = self.mac_name(interface)
phy_name = self.phy_name(interface)
nem_document = emane_manager.xmldoc("nem")
nem_element = nem_document.getElementsByTagName("nem").pop()
nem_element.setAttribute("name", "ieee80211abg NEM")
emane_manager.appendtransporttonem(nem_document, nem_element, self.object_id, interface)
mac_element = nem_document.createElement("mac")
mac_element.setAttribute("definition", mac_name)
nem_element.appendChild(mac_element)
phy_element = nem_document.createElement("phy")
phy_element.setAttribute("definition", phy_name)
nem_element.appendChild(phy_element)
emane_manager.xmlwrite(nem_document, nem_name)
names = self.getnames()
macnames = names[:len(self._confmatrix_mac)]
phynames = names[len(self._confmatrix_mac):]
mac_names = names[:len(self._config_mac)]
phy_names = names[len(self._config_mac):]
# append all MAC options to macdoc
for macname in macnames:
mac9xnvpairlist = self.get9xmacparamequivalent(macname, values)
mac_document = emane_manager.xmldoc("mac")
mac_element = mac_document.getElementsByTagName("mac").pop()
mac_element.setAttribute("name", "ieee80211abg MAC")
mac_element.setAttribute("library", "ieee80211abgmaclayer")
for name in mac_names:
mac9xnvpairlist = self.get9xmacparamequivalent(name, values)
for nvpair in mac9xnvpairlist:
mac.appendChild(e.xmlparam(macdoc, nvpair[0], nvpair[1]))
param = emane_manager.xmlparam(mac_document, nvpair[0], nvpair[1])
mac_element.appendChild(param)
emane_manager.xmlwrite(mac_document, mac_name)
e.xmlwrite(macdoc, self.macxmlname(ifc))
phydoc = EmaneUniversalModel.getphydoc(e, self, values, phynames)
e.xmlwrite(phydoc, self.phyxmlname(ifc))
phy_document = EmaneUniversalModel.get_phy_doc(emane_manager, self, values, phy_names)
emane_manager.xmlwrite(phy_document, phy_name)
#
# TEMP HACK: Account for parameter convention change in EMANE 9.x

View file

@ -15,10 +15,7 @@ from core.enumerations import RegisterTlvs
try:
from emane.events import LocationEvent
except ImportError:
try:
from emanesh.events import LocationEvent
except ImportError:
logger.info("emane 0.9.1+ not found")
logger.info("emane 1.2.1 not found")
class EmaneNet(PyCoreNet):
@ -122,26 +119,25 @@ class EmaneNode(EmaneNet):
return ret
for netif in self.netifs():
# <nem name="NODE-001" definition="rfpipenem.xml">
nementry = self.model.buildplatformxmlnementry(doc, self, netif)
# <transport definition="transvirtual.xml" group="1">
# <param name="device" value="n1.0.158" />
# </transport>
trans = self.model.buildplatformxmltransportentry(doc, self, netif)
nementry = self.model.build_nem_xml(doc, self, netif)
trans = self.model.build_transport_xml(doc, self, netif)
nementry.appendChild(trans)
ret[netif] = nementry
return ret
def buildnemxmlfiles(self, emane):
def build_xml_files(self, emane_manager):
"""
Let the configured model build the necessary nem, mac, and phy XMLs.
:param core.emane.emanemanager.EmaneManager emane_manager: core emane manager
:return: nothing
"""
if self.model is None:
return
# build XML for overall network (EmaneNode) configs
self.model.buildnemxmlfiles(emane, ifc=None)
self.model.build_xml_files(emane_manager, interface=None)
# build XML for specific interface (NEM) configs
need_virtual = False
@ -150,7 +146,7 @@ class EmaneNode(EmaneNet):
rtype = "raw"
for netif in self.netifs():
self.model.buildnemxmlfiles(emane, netif)
self.model.build_xml_files(emane_manager, netif)
if "virtual" in netif.transport_type:
need_virtual = True
vtype = netif.transport_type
@ -160,10 +156,10 @@ class EmaneNode(EmaneNet):
# build transport XML files depending on type of interfaces involved
if need_virtual:
self.buildtransportxml(emane, vtype)
self.buildtransportxml(emane_manager, vtype)
if need_raw:
self.buildtransportxml(emane, rtype)
self.buildtransportxml(emane_manager, rtype)
def buildtransportxml(self, emane, transport_type):
"""

View file

@ -15,7 +15,7 @@ class EmaneRfPipeModel(EmaneModel):
# configuration parameters are
# ( "name", "type", "default", "possible-value-list", "caption")
# MAC parameters
_confmatrix_mac = [
_config_mac = [
("datarate", ConfigDataTypes.UINT64.value, "1M", "", "data rate (bps)"),
("delay", ConfigDataTypes.FLOAT.value, "0.0", "", "transmission delay (sec)"),
("enablepromiscuousmode", ConfigDataTypes.BOOL.value, "0", "True,False", "enable promiscuous mode"),
@ -31,52 +31,65 @@ class EmaneRfPipeModel(EmaneModel):
]
# PHY parameters from Universal PHY
_confmatrix_phy = EmaneUniversalModel.config_matrix
_config_phy = EmaneUniversalModel.config_matrix
config_matrix = _confmatrix_mac + _confmatrix_phy
config_matrix = _config_mac + _config_phy
# value groupings
config_groups = "RF-PIPE MAC Parameters:1-%d|Universal PHY Parameters:%d-%d" % (
len(_confmatrix_mac), len(_confmatrix_mac) + 1, len(config_matrix))
len(_config_mac), len(_config_mac) + 1, len(config_matrix))
def __init__(self, session, object_id=None):
EmaneModel.__init__(self, session, object_id)
def buildnemxmlfiles(self, e, ifc):
def build_xml_files(self, emane_manager, interface):
"""
Build the necessary nem, mac, and phy XMLs in the given path.
If an individual NEM has a nonstandard config, we need to build
that file also. Otherwise the WLAN-wide nXXemane_rfpipenem.xml,
nXXemane_rfpipemac.xml, nXXemane_rfpipephy.xml are used.
:param core.emane.emanemanager.EmaneManager emane_manager: core emane manager
:param interface: interface for the emane node
:return: nothing
"""
values = e.getifcconfig(self.object_id, self.name, self.getdefaultvalues(), ifc)
values = emane_manager.getifcconfig(self.object_id, self.name, self.getdefaultvalues(), interface)
if values is None:
return
nemdoc = e.xmldoc("nem")
nem = nemdoc.getElementsByTagName("nem").pop()
nem.setAttribute("name", "RF-PIPE NEM")
e.appendtransporttonem(nemdoc, nem, self.object_id, ifc)
mactag = nemdoc.createElement("mac")
mactag.setAttribute("definition", self.macxmlname(ifc))
nem.appendChild(mactag)
phytag = nemdoc.createElement("phy")
phytag.setAttribute("definition", self.phyxmlname(ifc))
nem.appendChild(phytag)
e.xmlwrite(nemdoc, self.nemxmlname(ifc))
# retrieve xml names
nem_name = self.nem_name(interface)
mac_name = self.mac_name(interface)
phy_name = self.phy_name(interface)
nem_document = emane_manager.xmldoc("nem")
nem_element = nem_document.getElementsByTagName("nem").pop()
nem_element.setAttribute("name", "RF-PIPE NEM")
emane_manager.appendtransporttonem(nem_document, nem_element, self.object_id, interface)
mac_element = nem_document.createElement("mac")
mac_element.setAttribute("definition", mac_name)
nem_element.appendChild(mac_element)
phy_element = nem_document.createElement("phy")
phy_element.setAttribute("definition", phy_name)
nem_element.appendChild(phy_element)
emane_manager.xmlwrite(nem_document, nem_name)
names = list(self.getnames())
macnames = names[:len(self._confmatrix_mac)]
phynames = names[len(self._confmatrix_mac):]
mac_name = names[:len(self._config_mac)]
phy_names = names[len(self._config_mac):]
macdoc = e.xmldoc("mac")
mac = macdoc.getElementsByTagName("mac").pop()
mac.setAttribute("name", "RF-PIPE MAC")
mac.setAttribute("library", "rfpipemaclayer")
mac_document = emane_manager.xmldoc("mac")
mac_element = mac_document.getElementsByTagName("mac").pop()
mac_element.setAttribute("name", "RF-PIPE MAC")
mac_element.setAttribute("library", "rfpipemaclayer")
for name in mac_name:
value = self.valueof(name, values)
param = emane_manager.xmlparam(mac_document, name, value)
mac_element.appendChild(param)
emane_manager.xmlwrite(mac_document, mac_name)
# append MAC options to macdoc
map(lambda n: mac.appendChild(e.xmlparam(macdoc, n, self.valueof(n, values))), macnames)
e.xmlwrite(macdoc, self.macxmlname(ifc))
phydoc = EmaneUniversalModel.getphydoc(e, self, values, phynames)
e.xmlwrite(phydoc, self.phyxmlname(ifc))
phy_document = EmaneUniversalModel.get_phy_doc(emane_manager, self, values, phy_names)
emane_manager.xmlwrite(phy_document, phy_name)

View file

@ -20,7 +20,7 @@ class EmaneTdmaModel(EmaneModel):
default_schedule = os.path.join(constants.CORE_DATA_DIR, "examples", "tdma", "schedule.xml")
# MAC parameters
_confmatrix_mac = [
_config_mac = [
(schedule_name, ConfigDataTypes.STRING.value, default_schedule, "", "TDMA schedule file"),
("enablepromiscuousmode", ConfigDataTypes.BOOL.value, "0", "True,False", "enable promiscuous mode"),
("flowcontrolenable", ConfigDataTypes.BOOL.value, "0", "On,Off", "enable traffic flow control"),
@ -46,13 +46,13 @@ class EmaneTdmaModel(EmaneModel):
]
# PHY parameters from Universal PHY
_confmatrix_phy = EmaneUniversalModel.config_matrix
_config_phy = EmaneUniversalModel.config_matrix
config_matrix = _confmatrix_mac + _confmatrix_phy
config_matrix = _config_mac + _config_phy
# value groupings
config_groups = "TDMA MAC Parameters:1-%d|Universal PHY Parameters:%d-%d" % (
len(_confmatrix_mac), len(_confmatrix_mac) + 1, len(config_matrix))
len(_config_mac), len(_config_mac) + 1, len(config_matrix))
def __init__(self, session, object_id=None):
EmaneModel.__init__(self, session, object_id)
@ -69,54 +69,64 @@ class EmaneTdmaModel(EmaneModel):
if values is None:
return
schedule = self.valueof(EmaneTdmaModel.schedule_name, values)
event_device = emane_manager.event_device
# initiate tdma schedule
logger.info("setting up tdma schedule: schedule(%s) device(%s)", schedule, event_device)
utils.check_cmd(["emaneevent-tdmaschedule", "-i", event_device, schedule])
def buildnemxmlfiles(self, e, ifc):
def build_xml_files(self, emane_manager, interface):
"""
Build the necessary nem, mac, and phy XMLs in the given path.
If an individual NEM has a nonstandard config, we need to build
that file also. Otherwise the WLAN-wide nXXemane_tdmanem.xml,
nXXemane_tdmamac.xml, nXXemane_tdmaphy.xml are used.
:param core.emane.emanemanager.EmaneManager emane_manager: core emane manager
:param interface: interface for the emane node
:return: nothing
"""
values = e.getifcconfig(self.object_id, self.name, self.getdefaultvalues(), ifc)
values = emane_manager.getifcconfig(self.object_id, self.name, self.getdefaultvalues(), interface)
if values is None:
return
nemdoc = e.xmldoc("nem")
nem = nemdoc.getElementsByTagName("nem").pop()
nem.setAttribute("name", "TDMA NEM")
e.appendtransporttonem(nemdoc, nem, self.object_id, ifc)
mactag = nemdoc.createElement("mac")
mactag.setAttribute("definition", self.macxmlname(ifc))
nem.appendChild(mactag)
phytag = nemdoc.createElement("phy")
phytag.setAttribute("definition", self.phyxmlname(ifc))
nem.appendChild(phytag)
e.xmlwrite(nemdoc, self.nemxmlname(ifc))
# retrieve xml names
nem_name = self.nem_name(interface)
mac_name = self.mac_name(interface)
phy_name = self.phy_name(interface)
nem_document = emane_manager.xmldoc("nem")
nem_element = nem_document.getElementsByTagName("nem").pop()
nem_element.setAttribute("name", "TDMA NEM")
emane_manager.appendtransporttonem(nem_document, nem_element, self.object_id, interface)
mac_element = nem_document.createElement("mac")
mac_element.setAttribute("definition", mac_name)
nem_element.appendChild(mac_element)
phy_element = nem_document.createElement("phy")
phy_element.setAttribute("definition", phy_name)
nem_element.appendChild(phy_element)
emane_manager.xmlwrite(nem_document, nem_name)
names = list(self.getnames())
macnames = names[:len(self._confmatrix_mac)]
phynames = names[len(self._confmatrix_mac):]
mac_names = names[:len(self._config_mac)]
phy_names = names[len(self._config_mac):]
# make any changes to the mac/phy names here to e.g. exclude them from the XML output
macnames.remove(EmaneTdmaModel.schedule_name)
mac_names.remove(EmaneTdmaModel.schedule_name)
macdoc = e.xmldoc("mac")
mac = macdoc.getElementsByTagName("mac").pop()
mac.setAttribute("name", "TDMA MAC")
mac.setAttribute("library", "tdmaeventschedulerradiomodel")
# append MAC options to macdoc
for name in macnames:
mac_document = emane_manager.xmldoc("mac")
mac_element = mac_document.getElementsByTagName("mac").pop()
mac_element.setAttribute("name", "TDMA MAC")
mac_element.setAttribute("library", "tdmaeventschedulerradiomodel")
for name in mac_names:
value = self.valueof(name, values)
param = e.xmlparam(macdoc, name, value)
mac.appendChild(param)
param = emane_manager.xmlparam(mac_document, name, value)
mac_element.appendChild(param)
emane_manager.xmlwrite(mac_document, mac_name)
e.xmlwrite(macdoc, self.macxmlname(ifc))
phydoc = EmaneUniversalModel.getphydoc(e, self, values, phynames)
e.xmlwrite(phydoc, self.phyxmlname(ifc))
phydoc = EmaneUniversalModel.get_phy_doc(emane_manager, self, values, phy_names)
emane_manager.xmlwrite(phydoc, phy_name)

View file

@ -13,9 +13,6 @@ class EmaneUniversalModel(EmaneModel):
not instantiated.
"""
def __init__(self, session, object_id=None):
raise NotImplemented("Cannot use this class directly")
name = "emane_universal"
_xmlname = "universalphy"
_xmllibrary = "universalphylayer"
@ -53,22 +50,38 @@ class EmaneUniversalModel(EmaneModel):
("txpower", ConfigDataTypes.FLOAT.value, "0.0", "", "transmit power (dBm)"),
]
def __init__(self, session, object_id=None):
raise NotImplemented("Cannot use this class directly")
@classmethod
def getphydoc(cls, e, mac, values, phynames):
phydoc = e.xmldoc("phy")
phy = phydoc.getElementsByTagName("phy").pop()
phy.setAttribute("name", cls._xmlname)
def get_phy_doc(cls, emane_manager, emane_model, values, phy_names):
"""
Create a phy doc for a model based on the universal model.
:param core.emane.emanemanager.EmaneManager emane_manager: core emane manager
:param core.emane.emanemodel.EmaneModel emane_model: model to create phy doc for
:param tuple values: emane model configuration values
:param phy_names: names for phy configuration values
:return:
"""
phy_document = emane_manager.xmldoc("phy")
phy_element = phy_document.getElementsByTagName("phy").pop()
phy_element.setAttribute("name", cls._xmlname)
name = "frequencyofinterest"
value = mac.valueof(name, values)
frequencies = cls.valuestrtoparamlist(phydoc, name, value)
value = emane_model.valueof(name, values)
frequencies = cls.value_to_params(phy_document, name, value)
if frequencies:
phynames = list(phynames)
phynames.remove("frequencyofinterest")
phy_names = list(phy_names)
phy_names.remove("frequencyofinterest")
# append all PHY options to phydoc
map(lambda n: phy.appendChild(e.xmlparam(phydoc, n, mac.valueof(n, values))), phynames)
if frequencies:
phy.appendChild(frequencies)
for name in phy_names:
value = emane_model.valueof(name, values)
param = emane_manager.xmlparam(phy_document, name, value)
phy_element.appendChild(param)
return phydoc
if frequencies:
phy_element.appendChild(frequencies)
return phy_document