added support for emane manifest parsing into core compatible information, refactoring of emane code to align with its usage
This commit is contained in:
parent
8963ef51e3
commit
fd32e1cf78
7 changed files with 271 additions and 259 deletions
|
@ -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):
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue