added support for emane manifest parsing into core compatible information, refactoring of emane code to align with its usage

This commit is contained in:
Blake J. Harnden 2018-03-30 12:08:33 -07:00
parent 8963ef51e3
commit fd32e1cf78
7 changed files with 271 additions and 259 deletions

View file

@ -3,7 +3,7 @@ Defines Emane Models used within CORE.
"""
from core import logger
from core.enumerations import ConfigDataTypes
from core.emane import emanemanifest
from core.misc import utils
from core.mobility import WirelessModel
from core.xml import xmlutils
@ -40,98 +40,31 @@ def value_to_params(doc, name, value):
return xmlutils.add_param_list_to_parent(doc, parent=None, name=name, values=values)
class EmaneUniversalModel(object):
"""
This Univeral PHY model is meant to be imported by other models,
not instantiated.
"""
name = "emane_universal"
# universal PHY parameters
_xmlname = "universalphy"
_xmllibrary = "universalphylayer"
config_matrix = [
("bandwidth", ConfigDataTypes.UINT64.value, "1M", "", "rf bandwidth (Hz)"),
("fading.model", ConfigDataTypes.STRING.value, "none", "none,event,nakagami", "Defines fading model"),
("fading.nakagami.distance0", ConfigDataTypes.FLOAT.value, "100.0", "",
"Nakagami D0: distance lower bound in meters"),
("fading.nakagami.distance1", ConfigDataTypes.FLOAT.value, "250.0", "",
"Nakagami D1: distance upper bound in meters"),
("fading.nakagami.m0", ConfigDataTypes.FLOAT.value, "0.75", "", "Nakagami M0: shape factor for distance < D0"),
("fading.nakagami.m1", ConfigDataTypes.FLOAT.value, "1.0", "",
"Nakagami M1: shape factor for distance >= D0 < D1"),
("fading.nakagami.m2", ConfigDataTypes.FLOAT.value, "200.0", "",
"Nakagami M2: shape factor for distance >= D1"),
("fixedantennagain", ConfigDataTypes.FLOAT.value, "0.0", "", "antenna gain (dBi)"),
("fixedantennagainenable", ConfigDataTypes.BOOL.value, "1", "On,Off", "enable fixed antenna gain"),
("frequency", ConfigDataTypes.UINT64.value, "2.347G", "", "frequency (Hz)"),
("frequencyofinterest", ConfigDataTypes.UINT64.value, "2.347G", "", "frequency of interest (Hz)"),
("noisebinsize", ConfigDataTypes.UINT64.value, "20", "", "noise bin size in microseconds"),
("noisemaxclampenable", ConfigDataTypes.BOOL.value, "0", "On,Off", "Noise max clamp enable"),
("noisemaxmessagepropagation", ConfigDataTypes.UINT64.value, "200000", "",
"Noise maximum message propagation in microsecond"),
("noisemaxsegmentduration", ConfigDataTypes.UINT64.value, "1000000", "",
"Noise maximum segment duration in microseconds"),
("noisemaxsegmentoffset", ConfigDataTypes.UINT64.value, "300000", "",
"Noise maximum segment offset in microseconds"),
("noisemode", ConfigDataTypes.STRING.value, "none", "none,all,outofband", "noise processing mode"),
("propagationmodel", ConfigDataTypes.STRING.value, "2ray", "precomputed,2ray,freespace", "path loss mode"),
("subid", ConfigDataTypes.UINT16.value, "1", "", "subid"),
("systemnoisefigure", ConfigDataTypes.FLOAT.value, "4.0", "", "system noise figure (dB)"),
("timesyncthreshold", ConfigDataTypes.UINT64.value, "10000", "", "Time sync threshold"),
("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 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 = emane_model.valueof(name, values)
frequencies = value_to_params(phy_document, name, value)
if frequencies:
phy_names = list(phy_names)
phy_names.remove("frequencyofinterest")
# append all PHY options to phydoc
for name in phy_names:
value = emane_model.valueof(name, values)
param = emane_manager.xmlparam(phy_document, name, value)
phy_element.appendChild(param)
if frequencies:
phy_element.appendChild(frequencies)
return phy_document
class EmaneModel(WirelessModel):
"""
EMANE models inherit from this parent class, which takes care of
handling configuration messages based on the list of
configurable parameters. Helper functions also live here.
"""
_config_mac = []
_config_phy = EmaneUniversalModel.config_matrix
library = None
# default mac configuration settings
mac_library = None
mac_xml = None
mac_defaults = {}
config_mac = []
# default phy configuration settings, using the universal model
phy_library = None
phy_xml = "/usr/share/emane/manifest/emanephy.xml"
phy_defaults = {
"subid": "1",
"propagationmodel": "2ray",
"noisemode": "none"
}
config_phy = emanemanifest.parse(phy_xml, phy_defaults)
config_ignore = set()
config_matrix = _config_mac + _config_phy
config_groups = create_config_groups(_config_mac, config_matrix)
config_matrix = config_mac + config_phy
config_groups = create_config_groups(config_mac, config_matrix)
def __init__(self, session, object_id=None):
WirelessModel.__init__(self, session, object_id)
@ -157,16 +90,22 @@ class EmaneModel(WirelessModel):
# create mac document and write to disk
mac_name = self.mac_name(interface)
mac_document = self.create_mac_doc(emane_manager, values)
if mac_document:
emane_manager.xmlwrite(mac_document, mac_name)
emane_manager.xmlwrite(mac_document, mac_name)
# create phy document and write to disk
phy_name = self.phy_name(interface)
phy_document = self.create_phy_doc(emane_manager, values)
if phy_document:
emane_manager.xmlwrite(phy_document, phy_name)
emane_manager.xmlwrite(phy_document, phy_name)
def create_nem_doc(self, emane_manager, interface):
"""
Create the nem xml document.
:param core.emane.emanemanager.EmaneManager emane_manager: core emane manager
:param interface: interface for the emane node
:return: nem document
:rtype: xml.dom.minidom.Document
"""
mac_name = self.mac_name(interface)
phy_name = self.phy_name(interface)
@ -186,16 +125,24 @@ class EmaneModel(WirelessModel):
return nem_document
def create_mac_doc(self, emane_manager, values):
"""
Create the mac xml document.
:param core.emane.emanemanager.EmaneManager emane_manager: core emane manager
:param tuple values: all current configuration values, mac + phy
:return: nem document
:rtype: xml.dom.minidom.Document
"""
names = list(self.getnames())
mac_names = names[:len(self._config_mac)]
mac_names = names[:len(self.config_mac)]
mac_document = emane_manager.xmldoc("mac")
mac_element = mac_document.getElementsByTagName("mac").pop()
mac_element.setAttribute("name", "%s MAC" % self.name)
if not self.library:
if not self.mac_library:
raise ValueError("must define emane model library")
mac_element.setAttribute("library", self.library)
mac_element.setAttribute("library", self.mac_library)
for name in mac_names:
if name in self.config_ignore:
@ -207,9 +154,46 @@ class EmaneModel(WirelessModel):
return mac_document
def create_phy_doc(self, emane_manager, values):
"""
Create the phy xml document.
:param core.emane.emanemanager.EmaneManager emane_manager: core emane manager
:param tuple values: all current configuration values, mac + phy
:return: nem document
:rtype: xml.dom.minidom.Document
"""
names = list(self.getnames())
phy_names = names[len(self._config_mac):]
return EmaneUniversalModel.get_phy_doc(emane_manager, self, values, phy_names)
phy_names = names[len(self.config_mac):]
phy_document = emane_manager.xmldoc("phy")
phy_element = phy_document.getElementsByTagName("phy").pop()
phy_element.setAttribute("name", "%s PHY" % self.name)
if self.phy_library:
phy_element.setAttribute("library", self.phy_library)
# hack to account for config that can contain more than 1 value
frequencies = None
name = "frequencyofinterest"
try:
value = self.valueof(name, values)
frequencies = value_to_params(phy_document, name, value)
if frequencies:
phy_names = list(phy_names)
phy_names.remove("frequencyofinterest")
except ValueError:
logger.info("%s is not present in the phy names", name)
# append all PHY options to phydoc
for name in phy_names:
value = self.valueof(name, values)
param = emane_manager.xmlparam(phy_document, name, value)
phy_element.appendChild(param)
if frequencies:
phy_element.appendChild(frequencies)
return phy_document
@classmethod
def configure_emane(cls, session, config_data):