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
|
@ -8,20 +8,23 @@ from core.enumerations import ConfigDataTypes
|
||||||
|
|
||||||
class EmaneBypassModel(emanemodel.EmaneModel):
|
class EmaneBypassModel(emanemodel.EmaneModel):
|
||||||
name = "emane_bypass"
|
name = "emane_bypass"
|
||||||
library = "bypassmaclayer"
|
|
||||||
|
|
||||||
|
# values to ignore, when writing xml files
|
||||||
config_ignore = {"none"}
|
config_ignore = {"none"}
|
||||||
_config_mac = [
|
|
||||||
|
# mac definitions
|
||||||
|
mac_library = "bypassmaclayer"
|
||||||
|
config_mac = [
|
||||||
("none", ConfigDataTypes.BOOL.value, "0", "True,False",
|
("none", ConfigDataTypes.BOOL.value, "0", "True,False",
|
||||||
"There are no parameters for the bypass model."),
|
"There are no parameters for the bypass model."),
|
||||||
]
|
]
|
||||||
_config_phy = []
|
|
||||||
config_matrix = _config_mac + _config_phy
|
|
||||||
config_groups = "Bypass Parameters:1-1"
|
|
||||||
|
|
||||||
def create_phy_doc(self, emane_manager, values):
|
# phy definitions
|
||||||
phy_document = emane_manager.xmldoc("phy")
|
phy_library = "bypassphylayer"
|
||||||
phy_element = phy_document.getElementsByTagName("phy").pop()
|
config_phy = []
|
||||||
phy_element.setAttribute("name", "%s PHY" % self.name)
|
|
||||||
phy_element.setAttribute("library", "bypassphylayer")
|
# defines overall config
|
||||||
return phy_document
|
config_matrix = config_mac + config_phy
|
||||||
|
|
||||||
|
# gui display tabs
|
||||||
|
config_groups = "Bypass Parameters:1-1"
|
||||||
|
|
|
@ -3,8 +3,8 @@ commeffect.py: EMANE CommEffect model for CORE
|
||||||
"""
|
"""
|
||||||
|
|
||||||
from core import logger
|
from core import logger
|
||||||
|
from core.emane import emanemanifest
|
||||||
from core.emane import emanemodel
|
from core.emane import emanemodel
|
||||||
from core.enumerations import ConfigDataTypes
|
|
||||||
|
|
||||||
try:
|
try:
|
||||||
from emane.events.commeffectevent import CommEffectEvent
|
from emane.events.commeffectevent import CommEffectEvent
|
||||||
|
@ -27,13 +27,11 @@ def convert_none(x):
|
||||||
class EmaneCommEffectModel(emanemodel.EmaneModel):
|
class EmaneCommEffectModel(emanemodel.EmaneModel):
|
||||||
name = "emane_commeffect"
|
name = "emane_commeffect"
|
||||||
|
|
||||||
config_matrix = [
|
shim_library = "commeffectshim"
|
||||||
("filterfile", ConfigDataTypes.STRING.value, "", "", "filter file"),
|
shim_xml = "/usr/share/emane/manifest/commeffectshim.xml"
|
||||||
("groupid", ConfigDataTypes.UINT32.value, "0", "", "NEM Group ID"),
|
shim_defaults = {}
|
||||||
("enablepromiscuousmode", ConfigDataTypes.BOOL.value, "0", "On,Off", "enable promiscuous mode"),
|
config_shim = emanemanifest.parse(shim_xml, shim_defaults)
|
||||||
("receivebufferperiod", ConfigDataTypes.FLOAT.value, "1.0", "", "receivebufferperiod"),
|
config_matrix = config_shim
|
||||||
("defaultconnectivitymode", ConfigDataTypes.BOOL.value, "1", "On,Off", "defaultconnectivity"),
|
|
||||||
]
|
|
||||||
|
|
||||||
config_groups = "CommEffect SHIM Parameters:1-%d" % len(config_matrix)
|
config_groups = "CommEffect SHIM Parameters:1-%d" % len(config_matrix)
|
||||||
|
|
||||||
|
@ -56,30 +54,9 @@ class EmaneCommEffectModel(emanemodel.EmaneModel):
|
||||||
nem_name = self.nem_name(interface)
|
nem_name = self.nem_name(interface)
|
||||||
shim_name = self.shim_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()
|
|
||||||
shim_names = list(names[:len(self.config_matrix)])
|
|
||||||
shim_names.remove("filterfile")
|
|
||||||
|
|
||||||
# append all shim options (except filterfile) to shimdoc
|
|
||||||
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(emane_manager.xmlparam(shim_document, "filterfile", ff))
|
|
||||||
emane_manager.xmlwrite(shim_document, shim_name)
|
|
||||||
|
|
||||||
nem_document = emane_manager.xmldoc("nem")
|
nem_document = emane_manager.xmldoc("nem")
|
||||||
nem_element = nem_document.getElementsByTagName("nem").pop()
|
nem_element = nem_document.getElementsByTagName("nem").pop()
|
||||||
nem_element.setAttribute("name", "commeffect NEM")
|
nem_element.setAttribute("name", "%s NEM" % self.name)
|
||||||
nem_element.setAttribute("type", "unstructured")
|
nem_element.setAttribute("type", "unstructured")
|
||||||
emane_manager.appendtransporttonem(nem_document, nem_element, self.object_id, interface)
|
emane_manager.appendtransporttonem(nem_document, nem_element, self.object_id, interface)
|
||||||
|
|
||||||
|
@ -87,6 +64,27 @@ class EmaneCommEffectModel(emanemodel.EmaneModel):
|
||||||
nem_element.appendChild(shim_xml)
|
nem_element.appendChild(shim_xml)
|
||||||
emane_manager.xmlwrite(nem_document, nem_name)
|
emane_manager.xmlwrite(nem_document, nem_name)
|
||||||
|
|
||||||
|
names = self.getnames()
|
||||||
|
shim_names = list(names)
|
||||||
|
shim_names.remove("filterfile")
|
||||||
|
|
||||||
|
shim_document = emane_manager.xmldoc("shim")
|
||||||
|
shim_element = shim_document.getElementsByTagName("shim").pop()
|
||||||
|
shim_element.setAttribute("name", "%s SHIM" % self.name)
|
||||||
|
shim_element.setAttribute("library", self.shim_library)
|
||||||
|
|
||||||
|
# append all shim options (except filterfile) to shimdoc
|
||||||
|
for name in shim_names:
|
||||||
|
value = self.valueof(name, values)
|
||||||
|
param = emane_manager.xmlparam(shim_document, name, value)
|
||||||
|
shim_element.appendChild(param)
|
||||||
|
|
||||||
|
# empty filterfile is not allowed
|
||||||
|
ff = self.valueof("filterfile", values)
|
||||||
|
if ff.strip() != "":
|
||||||
|
shim_element.appendChild(emane_manager.xmlparam(shim_document, "filterfile", ff))
|
||||||
|
emane_manager.xmlwrite(shim_document, shim_name)
|
||||||
|
|
||||||
def linkconfig(self, netif, bw=None, delay=None, loss=None, duplicate=None, jitter=None, netif2=None):
|
def linkconfig(self, netif, bw=None, delay=None, loss=None, duplicate=None, jitter=None, netif2=None):
|
||||||
"""
|
"""
|
||||||
Generate CommEffect events when a Link Message is received having
|
Generate CommEffect events when a Link Message is received having
|
||||||
|
|
112
daemon/core/emane/emanemanifest.py
Normal file
112
daemon/core/emane/emanemanifest.py
Normal file
|
@ -0,0 +1,112 @@
|
||||||
|
from core import logger
|
||||||
|
from core.enumerations import ConfigDataTypes
|
||||||
|
|
||||||
|
try:
|
||||||
|
from emane.shell import manifest
|
||||||
|
except ImportError:
|
||||||
|
logger.info("emane 1.2.1 not found")
|
||||||
|
|
||||||
|
|
||||||
|
def _type_value(config_type):
|
||||||
|
"""
|
||||||
|
Convert emane configuration type to core configuration value.
|
||||||
|
|
||||||
|
:param str config_type: emane configuration type
|
||||||
|
:return:
|
||||||
|
"""
|
||||||
|
config_type = config_type.upper()
|
||||||
|
if config_type == "DOUBLE":
|
||||||
|
config_type = "FLOAT"
|
||||||
|
return ConfigDataTypes[config_type].value
|
||||||
|
|
||||||
|
|
||||||
|
def _get_possible(config_type, config_regex):
|
||||||
|
"""
|
||||||
|
Retrieve possible config value options based on emane regexes.
|
||||||
|
|
||||||
|
:param str config_type: emane configuration type
|
||||||
|
:param str config_regex: emane configuration regex
|
||||||
|
:return: a string listing comma delimited values, if needed, empty string otherwise
|
||||||
|
:rtype: str
|
||||||
|
"""
|
||||||
|
if config_type == "bool":
|
||||||
|
return "On,Off"
|
||||||
|
|
||||||
|
if config_type == "string" and config_regex:
|
||||||
|
possible = config_regex[2:-2]
|
||||||
|
possible = possible.replace("|", ",")
|
||||||
|
return possible
|
||||||
|
|
||||||
|
return ""
|
||||||
|
|
||||||
|
|
||||||
|
def _get_default(config_type_name, config_value):
|
||||||
|
"""
|
||||||
|
Convert default configuration values to one used by core.
|
||||||
|
|
||||||
|
:param str config_type_name: emane configuration type name
|
||||||
|
:param list config_value: emane configuration value list
|
||||||
|
:return: default core config value
|
||||||
|
:rtype: str
|
||||||
|
"""
|
||||||
|
|
||||||
|
config_default = ""
|
||||||
|
|
||||||
|
if config_type_name == "bool":
|
||||||
|
if config_value and config_value[0] == "true":
|
||||||
|
config_default = "1"
|
||||||
|
else:
|
||||||
|
config_default = "0"
|
||||||
|
elif config_value:
|
||||||
|
config_default = config_value[0]
|
||||||
|
|
||||||
|
if config_default is None:
|
||||||
|
config_default = ""
|
||||||
|
return config_default
|
||||||
|
|
||||||
|
|
||||||
|
def parse(manifest_path, defaults):
|
||||||
|
"""
|
||||||
|
Parses a valid emane manifest file and converts the provided configuration values into ones used by core.
|
||||||
|
|
||||||
|
:param str manifest_path: absolute manifest file path
|
||||||
|
:param dict defaults: used to override default values for configurations
|
||||||
|
:return: list of core configuration values
|
||||||
|
:rtype: list
|
||||||
|
"""
|
||||||
|
|
||||||
|
# load configuration file
|
||||||
|
manifest_file = manifest.Manifest(manifest_path)
|
||||||
|
manifest_configurations = manifest_file.getAllConfiguration()
|
||||||
|
|
||||||
|
configurations = []
|
||||||
|
for config_name in sorted(manifest_configurations):
|
||||||
|
config_info = manifest_file.getConfigurationInfo(config_name)
|
||||||
|
|
||||||
|
# map type to internal config data type value for core
|
||||||
|
config_type = config_info.get("numeric")
|
||||||
|
if not config_type:
|
||||||
|
config_type = config_info.get("nonnumeric")
|
||||||
|
config_type_name = config_type["type"]
|
||||||
|
config_type_value = _type_value(config_type_name)
|
||||||
|
|
||||||
|
# get default values, using provided defaults
|
||||||
|
if config_name in defaults:
|
||||||
|
config_default = defaults[config_name]
|
||||||
|
else:
|
||||||
|
config_value = config_info["values"]
|
||||||
|
config_default = _get_default(config_type_name, config_value)
|
||||||
|
|
||||||
|
# map to possible values used as options within the gui
|
||||||
|
config_regex = config_info.get("regex")
|
||||||
|
possible = _get_possible(config_type_name, config_regex)
|
||||||
|
|
||||||
|
# define description and account for gui quirks
|
||||||
|
config_descriptions = config_name
|
||||||
|
if config_name.endswith("uri"):
|
||||||
|
config_descriptions = "%s file" % config_descriptions
|
||||||
|
|
||||||
|
config_tuple = (config_name, config_type_value, config_default, possible, config_descriptions)
|
||||||
|
configurations.append(config_tuple)
|
||||||
|
|
||||||
|
return configurations
|
|
@ -3,7 +3,7 @@ Defines Emane Models used within CORE.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
from core import logger
|
from core import logger
|
||||||
from core.enumerations import ConfigDataTypes
|
from core.emane import emanemanifest
|
||||||
from core.misc import utils
|
from core.misc import utils
|
||||||
from core.mobility import WirelessModel
|
from core.mobility import WirelessModel
|
||||||
from core.xml import xmlutils
|
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)
|
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):
|
class EmaneModel(WirelessModel):
|
||||||
"""
|
"""
|
||||||
EMANE models inherit from this parent class, which takes care of
|
EMANE models inherit from this parent class, which takes care of
|
||||||
handling configuration messages based on the list of
|
handling configuration messages based on the list of
|
||||||
configurable parameters. Helper functions also live here.
|
configurable parameters. Helper functions also live here.
|
||||||
"""
|
"""
|
||||||
_config_mac = []
|
# default mac configuration settings
|
||||||
_config_phy = EmaneUniversalModel.config_matrix
|
mac_library = None
|
||||||
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_ignore = set()
|
||||||
config_matrix = _config_mac + _config_phy
|
config_matrix = config_mac + config_phy
|
||||||
config_groups = create_config_groups(_config_mac, config_matrix)
|
config_groups = create_config_groups(config_mac, config_matrix)
|
||||||
|
|
||||||
def __init__(self, session, object_id=None):
|
def __init__(self, session, object_id=None):
|
||||||
WirelessModel.__init__(self, session, object_id)
|
WirelessModel.__init__(self, session, object_id)
|
||||||
|
@ -157,16 +90,22 @@ class EmaneModel(WirelessModel):
|
||||||
# create mac document and write to disk
|
# create mac document and write to disk
|
||||||
mac_name = self.mac_name(interface)
|
mac_name = self.mac_name(interface)
|
||||||
mac_document = self.create_mac_doc(emane_manager, values)
|
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
|
# create phy document and write to disk
|
||||||
phy_name = self.phy_name(interface)
|
phy_name = self.phy_name(interface)
|
||||||
phy_document = self.create_phy_doc(emane_manager, values)
|
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):
|
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)
|
mac_name = self.mac_name(interface)
|
||||||
phy_name = self.phy_name(interface)
|
phy_name = self.phy_name(interface)
|
||||||
|
|
||||||
|
@ -186,16 +125,24 @@ class EmaneModel(WirelessModel):
|
||||||
return nem_document
|
return nem_document
|
||||||
|
|
||||||
def create_mac_doc(self, emane_manager, values):
|
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())
|
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_document = emane_manager.xmldoc("mac")
|
||||||
mac_element = mac_document.getElementsByTagName("mac").pop()
|
mac_element = mac_document.getElementsByTagName("mac").pop()
|
||||||
mac_element.setAttribute("name", "%s MAC" % self.name)
|
mac_element.setAttribute("name", "%s MAC" % self.name)
|
||||||
|
|
||||||
if not self.library:
|
if not self.mac_library:
|
||||||
raise ValueError("must define emane model 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:
|
for name in mac_names:
|
||||||
if name in self.config_ignore:
|
if name in self.config_ignore:
|
||||||
|
@ -207,9 +154,46 @@ class EmaneModel(WirelessModel):
|
||||||
return mac_document
|
return mac_document
|
||||||
|
|
||||||
def create_phy_doc(self, emane_manager, values):
|
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())
|
names = list(self.getnames())
|
||||||
phy_names = names[len(self._config_mac):]
|
phy_names = names[len(self.config_mac):]
|
||||||
return EmaneUniversalModel.get_phy_doc(emane_manager, self, values, phy_names)
|
|
||||||
|
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
|
@classmethod
|
||||||
def configure_emane(cls, session, config_data):
|
def configure_emane(cls, session, config_data):
|
||||||
|
|
|
@ -2,89 +2,24 @@
|
||||||
ieee80211abg.py: EMANE IEEE 802.11abg model for CORE
|
ieee80211abg.py: EMANE IEEE 802.11abg model for CORE
|
||||||
"""
|
"""
|
||||||
|
|
||||||
|
from core.emane import emanemanifest
|
||||||
from core.emane import emanemodel
|
from core.emane import emanemodel
|
||||||
from core.enumerations import ConfigDataTypes
|
|
||||||
|
|
||||||
|
|
||||||
class EmaneIeee80211abgModel(emanemodel.EmaneModel):
|
class EmaneIeee80211abgModel(emanemodel.EmaneModel):
|
||||||
# model name
|
# model name
|
||||||
name = "emane_ieee80211abg"
|
name = "emane_ieee80211abg"
|
||||||
library = "ieee80211abgmaclayer"
|
|
||||||
|
|
||||||
# mac configuration
|
# mac configuration
|
||||||
_80211rates = "1 1 Mbps,2 2 Mbps,3 5.5 Mbps,4 11 Mbps,5 6 Mbps," + \
|
mac_library = "ieee80211abgmaclayer"
|
||||||
"6 9 Mbps,7 12 Mbps,8 18 Mbps,9 24 Mbps,10 36 Mbps,11 48 Mbps," + \
|
mac_xml = "/usr/share/emane/manifest/ieee80211abgmaclayer.xml"
|
||||||
"12 54 Mbps"
|
mac_defaults = {
|
||||||
xml_path = "/usr/share/emane/xml/models/mac/ieee80211abg"
|
"pcrcurveuri": "/usr/share/emane/xml/models/mac/ieee80211abg/ieee80211pcr.xml",
|
||||||
_config_mac = [
|
}
|
||||||
("aifs", ConfigDataTypes.STRING.value, "0:2 1:2 2:2 3:1", "", "arbitration inter frame space (0-4:aifs)"),
|
config_mac = emanemanifest.parse(mac_xml, mac_defaults)
|
||||||
("channelactivityestimationtimer", ConfigDataTypes.FLOAT.value, "0.1", "",
|
|
||||||
"Defines channel activity estimation timer in seconds"),
|
|
||||||
("cwmax", ConfigDataTypes.STRING.value, "0:1024 1:1024 2:64 3:16", "", "max contention window (0-4:maxw)"),
|
|
||||||
("cwmin", ConfigDataTypes.STRING.value, "0:32 1:32 2:16 3:8", "", "min contention window (0-4:minw)"),
|
|
||||||
("distance", ConfigDataTypes.UINT32.value, "1000", "", "max distance (m)"),
|
|
||||||
("enablepromiscuousmode", ConfigDataTypes.BOOL.value, "0", "On,Off", "enable promiscuous mode"),
|
|
||||||
("flowcontrolenable", ConfigDataTypes.BOOL.value, "0", "On,Off", "enable traffic flow control"),
|
|
||||||
("flowcontroltokens", ConfigDataTypes.UINT16.value, "10", "", "number of flow control tokens"),
|
|
||||||
("mode", ConfigDataTypes.UINT8.value, "0", "0 802.11b (DSSS only),1 802.11b (DSSS only)," +
|
|
||||||
"2 802.11a or g (OFDM),3 802.11b/g (DSSS and OFDM)", "mode"),
|
|
||||||
("multicastrate", ConfigDataTypes.UINT8.value, "1", _80211rates, "multicast rate (Mbps)"),
|
|
||||||
("msdu", ConfigDataTypes.UINT16.value, "0:65535 1:65535 2:65535 3:65535", "", "MSDU categories (0-4:size)"),
|
|
||||||
("neighbormetricdeletetime", ConfigDataTypes.FLOAT.value, "60.0", "",
|
|
||||||
"R2RI neighbor table inactivity time (sec)"),
|
|
||||||
("neighbortimeout", ConfigDataTypes.FLOAT.value, "30.0", "", "Neighbor timeout in seconds for estimation"),
|
|
||||||
("pcrcurveuri", ConfigDataTypes.STRING.value, "%s/ieee80211pcr.xml" % xml_path, "", "SINR/PCR curve file"),
|
|
||||||
("queuesize", ConfigDataTypes.STRING.value, "0:255 1:255 2:255 3:255", "", "queue size (0-4:size)"),
|
|
||||||
("radiometricenable", ConfigDataTypes.BOOL.value, "0", "On,Off", "report radio metrics via R2RI"),
|
|
||||||
("radiometricreportinterval", ConfigDataTypes.FLOAT.value, "1.0", "",
|
|
||||||
"R2RI radio metric report interval (sec)"),
|
|
||||||
("retrylimit", ConfigDataTypes.STRING.value, "0:3 1:3 2:3 3:3", "", "retry limit (0-4:numretries)"),
|
|
||||||
("rtsthreshold", ConfigDataTypes.UINT16.value, "0", "", "RTS threshold (bytes)"),
|
|
||||||
("txop", ConfigDataTypes.STRING.value, "0:0 1:0 2:0 3:0", "", "txop (0-4:usec)"),
|
|
||||||
("unicastrate", ConfigDataTypes.UINT8.value, "4", _80211rates, "unicast rate (Mbps)"),
|
|
||||||
("wmmenable", ConfigDataTypes.BOOL.value, "0", "On,Off", "WiFi Multimedia (WMM)"),
|
|
||||||
]
|
|
||||||
|
|
||||||
config_matrix = _config_mac + emanemodel.EmaneModel._config_phy
|
# defines overall config
|
||||||
config_groups = emanemodel.create_config_groups(_config_mac, config_matrix)
|
config_matrix = config_mac + emanemodel.EmaneModel.config_phy
|
||||||
|
|
||||||
def create_mac_doc(self, emane_manager, values):
|
# gui display tabs
|
||||||
names = self.getnames()
|
config_groups = emanemodel.create_config_groups(config_mac, config_matrix)
|
||||||
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)
|
|
||||||
mac_element.setAttribute("library", self.library)
|
|
||||||
for name in mac_names:
|
|
||||||
mac9xnvpairlist = self.get9xmacparamequivalent(name, values)
|
|
||||||
for nvpair in mac9xnvpairlist:
|
|
||||||
param = emane_manager.xmlparam(mac_document, nvpair[0], nvpair[1])
|
|
||||||
mac_element.appendChild(param)
|
|
||||||
return mac_document
|
|
||||||
|
|
||||||
def get9xmacparamequivalent(self, mac_name, values):
|
|
||||||
"""
|
|
||||||
This accounts for current config values labeled value0, value1, value2, etc.
|
|
||||||
|
|
||||||
Generate a list of 80211abg mac parameters in 0.9.x layout for a given mac parameter
|
|
||||||
in 8.x layout.For mac category parameters, the list returned will contain the four
|
|
||||||
equivalent 9.x parameter and value pairs. Otherwise, the list returned will only
|
|
||||||
contain a single name and value pair.
|
|
||||||
"""
|
|
||||||
nvpairlist = []
|
|
||||||
macparmval = self.valueof(mac_name, values)
|
|
||||||
|
|
||||||
if mac_name in ["queuesize", "aifs", "cwmin", "cwmax", "txop", "retrylimit", "msdu"]:
|
|
||||||
for catval in macparmval.split():
|
|
||||||
idx_and_val = catval.split(":")
|
|
||||||
idx = int(idx_and_val[0])
|
|
||||||
val = idx_and_val[1]
|
|
||||||
# aifs and tx are in microseconds. Convert to seconds.
|
|
||||||
if mac_name in ["aifs", "txop"]:
|
|
||||||
val = "%f" % (float(val) * 1e-6)
|
|
||||||
name9x = "%s%d" % (mac_name, idx)
|
|
||||||
nvpairlist.append([name9x, val])
|
|
||||||
else:
|
|
||||||
nvpairlist.append([mac_name, macparmval])
|
|
||||||
|
|
||||||
return nvpairlist
|
|
||||||
|
|
|
@ -2,31 +2,24 @@
|
||||||
rfpipe.py: EMANE RF-PIPE model for CORE
|
rfpipe.py: EMANE RF-PIPE model for CORE
|
||||||
"""
|
"""
|
||||||
|
|
||||||
|
from core.emane import emanemanifest
|
||||||
from core.emane import emanemodel
|
from core.emane import emanemodel
|
||||||
from core.enumerations import ConfigDataTypes
|
|
||||||
|
|
||||||
|
|
||||||
class EmaneRfPipeModel(emanemodel.EmaneModel):
|
class EmaneRfPipeModel(emanemodel.EmaneModel):
|
||||||
# model name
|
# model name
|
||||||
name = "emane_rfpipe"
|
name = "emane_rfpipe"
|
||||||
library = "rfpipemaclayer"
|
|
||||||
|
|
||||||
# mac configuration
|
# mac configuration
|
||||||
xml_path = "/usr/share/emane/xml/models/mac/rfpipe"
|
mac_library = "rfpipemaclayer"
|
||||||
_config_mac = [
|
mac_xml = "/usr/share/emane/manifest/rfpipemaclayer.xml"
|
||||||
("datarate", ConfigDataTypes.UINT64.value, "1M", "", "data rate (bps)"),
|
mac_defaults = {
|
||||||
("delay", ConfigDataTypes.FLOAT.value, "0.0", "", "transmission delay (sec)"),
|
"pcrcurveuri": "/usr/share/emane/xml/models/mac/rfpipe/rfpipepcr.xml",
|
||||||
("enablepromiscuousmode", ConfigDataTypes.BOOL.value, "0", "True,False", "enable promiscuous mode"),
|
}
|
||||||
("flowcontrolenable", ConfigDataTypes.BOOL.value, "0", "On,Off", "enable traffic flow control"),
|
config_mac = emanemanifest.parse(mac_xml, mac_defaults)
|
||||||
("flowcontroltokens", ConfigDataTypes.UINT16.value, "10", "", "number of flow control tokens"),
|
|
||||||
("jitter", ConfigDataTypes.FLOAT.value, "0.0", "", "transmission jitter (sec)"),
|
|
||||||
("neighbormetricdeletetime", ConfigDataTypes.FLOAT.value, "60.0", "",
|
|
||||||
"R2RI neighbor table inactivity time (sec)"),
|
|
||||||
("pcrcurveuri", ConfigDataTypes.STRING.value, "%s/rfpipepcr.xml" % xml_path, "", "SINR/PCR curve file"),
|
|
||||||
("radiometricenable", ConfigDataTypes.BOOL.value, "0", "On,Off", "report radio metrics via R2RI"),
|
|
||||||
("radiometricreportinterval", ConfigDataTypes.FLOAT.value, "1.0", "",
|
|
||||||
"R2RI radio metric report interval (sec)"),
|
|
||||||
]
|
|
||||||
|
|
||||||
config_matrix = _config_mac + emanemodel.EmaneModel._config_phy
|
# defines overall config
|
||||||
config_groups = emanemodel.create_config_groups(_config_mac, config_matrix)
|
config_matrix = config_mac + emanemodel.EmaneModel.config_phy
|
||||||
|
|
||||||
|
# gui display tabs
|
||||||
|
config_groups = emanemodel.create_config_groups(config_mac, config_matrix)
|
||||||
|
|
|
@ -6,6 +6,7 @@ import os
|
||||||
|
|
||||||
from core import constants
|
from core import constants
|
||||||
from core import logger
|
from core import logger
|
||||||
|
from core.emane import emanemanifest
|
||||||
from core.emane import emanemodel
|
from core.emane import emanemodel
|
||||||
from core.enumerations import ConfigDataTypes
|
from core.enumerations import ConfigDataTypes
|
||||||
from core.misc import utils
|
from core.misc import utils
|
||||||
|
@ -14,40 +15,26 @@ from core.misc import utils
|
||||||
class EmaneTdmaModel(emanemodel.EmaneModel):
|
class EmaneTdmaModel(emanemodel.EmaneModel):
|
||||||
# model name
|
# model name
|
||||||
name = "emane_tdma"
|
name = "emane_tdma"
|
||||||
library = "tdmaeventschedulerradiomodel"
|
|
||||||
|
|
||||||
# mac configuration
|
# mac configuration
|
||||||
xml_path = "/usr/share/emane/xml/models/mac/tdmaeventscheduler"
|
mac_library = "tdmaeventschedulerradiomodel"
|
||||||
|
mac_xml = "/usr/share/emane/manifest/tdmaeventschedulerradiomodel.xml"
|
||||||
|
mac_defaults = {
|
||||||
|
"pcrcurveuri": "/usr/share/emane/xml/models/mac/tdmaeventscheduler/tdmabasemodelpcr.xml",
|
||||||
|
}
|
||||||
|
config_mac = emanemanifest.parse(mac_xml, mac_defaults)
|
||||||
|
|
||||||
|
# add custom schedule options and ignore it when writing emane xml
|
||||||
schedule_name = "schedule"
|
schedule_name = "schedule"
|
||||||
default_schedule = os.path.join(constants.CORE_DATA_DIR, "examples", "tdma", "schedule.xml")
|
default_schedule = os.path.join(constants.CORE_DATA_DIR, "examples", "tdma", "schedule.xml")
|
||||||
|
config_mac.insert(0, (schedule_name, ConfigDataTypes.STRING.value, default_schedule, "", "TDMA schedule file"))
|
||||||
config_ignore = {schedule_name}
|
config_ignore = {schedule_name}
|
||||||
_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"),
|
|
||||||
("flowcontroltokens", ConfigDataTypes.UINT16.value, "10", "", "number of flow control tokens"),
|
|
||||||
("fragmentcheckthreshold", ConfigDataTypes.UINT16.value, "2", "",
|
|
||||||
"rate in seconds for check if fragment reassembly efforts should be abandoned"),
|
|
||||||
("fragmenttimeoutthreshold", ConfigDataTypes.UINT16.value, "5", "",
|
|
||||||
"threshold in seconds to wait for another packet fragment for reassembly"),
|
|
||||||
("neighbormetricdeletetime", ConfigDataTypes.FLOAT.value, "60.0", "",
|
|
||||||
"neighbor RF reception timeout for removal from neighbor table (sec)"),
|
|
||||||
("neighbormetricupdateinterval", ConfigDataTypes.FLOAT.value, "1.0", "",
|
|
||||||
"neighbor table update interval (sec)"),
|
|
||||||
("pcrcurveuri", ConfigDataTypes.STRING.value, "%s/tdmabasemodelpcr.xml" % xml_path, "", "SINR/PCR curve file"),
|
|
||||||
("queue.aggregationenable", ConfigDataTypes.BOOL.value, "1", "On,Off", "enable transmit packet aggregation"),
|
|
||||||
("queue.aggregationslotthreshold", ConfigDataTypes.FLOAT.value, "90.0", "",
|
|
||||||
"percentage of a slot that must be filled in order to conclude aggregation"),
|
|
||||||
("queue.depth", ConfigDataTypes.UINT16.value, "256", "",
|
|
||||||
"size of the per service class downstream packet queues (packets)"),
|
|
||||||
("queue.fragmentationenable", ConfigDataTypes.BOOL.value, "1", "On,Off",
|
|
||||||
"enable packet fragmentation (over multiple slots)"),
|
|
||||||
("queue.strictdequeueenable", ConfigDataTypes.BOOL.value, "0", "On,Off",
|
|
||||||
"enable strict dequeueing to specified queues only"),
|
|
||||||
]
|
|
||||||
|
|
||||||
config_matrix = _config_mac + emanemodel.EmaneModel._config_phy
|
# defines overall config
|
||||||
config_groups = emanemodel.create_config_groups(_config_mac, config_matrix)
|
config_matrix = config_mac + emanemodel.EmaneModel.config_phy
|
||||||
|
|
||||||
|
# gui display tabs
|
||||||
|
config_groups = emanemodel.create_config_groups(config_mac, config_matrix)
|
||||||
|
|
||||||
def post_startup(self, emane_manager):
|
def post_startup(self, emane_manager):
|
||||||
"""
|
"""
|
||||||
|
|
Loading…
Reference in a new issue