From b7327a57989102064a44b86a8733bb8992c83981 Mon Sep 17 00:00:00 2001 From: "Blake J. Harnden" Date: Wed, 28 Mar 2018 13:58:49 -0700 Subject: [PATCH] pass over emane code to cleanup methods and some documentation --- daemon/core/emane/bypass.py | 71 +++++++----- daemon/core/emane/commeffect.py | 66 ++++++----- daemon/core/emane/emanemanager.py | 13 +-- daemon/core/emane/emanemodel.py | 184 +++++++++++++++++------------- daemon/core/emane/ieee80211abg.py | 73 +++++++----- daemon/core/emane/nodes.py | 26 ++--- daemon/core/emane/rfpipe.py | 71 +++++++----- daemon/core/emane/tdma.py | 76 ++++++------ daemon/core/emane/universal.py | 43 ++++--- 9 files changed, 356 insertions(+), 267 deletions(-) diff --git a/daemon/core/emane/bypass.py b/daemon/core/emane/bypass.py index 8fad0c16..5d0192c1 100644 --- a/daemon/core/emane/bypass.py +++ b/daemon/core/emane/bypass.py @@ -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) diff --git a/daemon/core/emane/commeffect.py b/daemon/core/emane/commeffect.py index 05efefc3..ca53eb5a 100644 --- a/daemon/core/emane/commeffect.py +++ b/daemon/core/emane/commeffect.py @@ -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), diff --git a/daemon/core/emane/emanemanager.py b/daemon/core/emane/emanemanager.py index 1771b2ff..e716a548 100644 --- a/daemon/core/emane/emanemanager.py +++ b/daemon/core/emane/emanemanager.py @@ -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. """ diff --git a/daemon/core/emane/emanemodel.py b/daemon/core/emane/emanemodel.py index 080f4c3f..90a5ed5f 100644 --- a/daemon/core/emane/emanemodel.py +++ b/daemon/core/emane/emanemodel.py @@ -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. . This can be overriden by a model for NEM flexibility; n is the EmaneNode. + + + + :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. + + + + + + :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) diff --git a/daemon/core/emane/ieee80211abg.py b/daemon/core/emane/ieee80211abg.py index 86c3a705..2a2c1bf2 100644 --- a/daemon/core/emane/ieee80211abg.py +++ b/daemon/core/emane/ieee80211abg.py @@ -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 diff --git a/daemon/core/emane/nodes.py b/daemon/core/emane/nodes.py index fd7f32b6..adcc660b 100644 --- a/daemon/core/emane/nodes.py +++ b/daemon/core/emane/nodes.py @@ -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(): - # - nementry = self.model.buildplatformxmlnementry(doc, self, netif) - # - # - # - 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): """ diff --git a/daemon/core/emane/rfpipe.py b/daemon/core/emane/rfpipe.py index 08302018..55c60533 100644 --- a/daemon/core/emane/rfpipe.py +++ b/daemon/core/emane/rfpipe.py @@ -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) diff --git a/daemon/core/emane/tdma.py b/daemon/core/emane/tdma.py index a1cbeac3..34a18348 100644 --- a/daemon/core/emane/tdma.py +++ b/daemon/core/emane/tdma.py @@ -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) diff --git a/daemon/core/emane/universal.py b/daemon/core/emane/universal.py index 8b437aaa..6cf108f4 100644 --- a/daemon/core/emane/universal.py +++ b/daemon/core/emane/universal.py @@ -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