diff --git a/daemon/core/emane/bypass.py b/daemon/core/emane/bypass.py index b8313e44..bb1c6f55 100644 --- a/daemon/core/emane/bypass.py +++ b/daemon/core/emane/bypass.py @@ -8,20 +8,23 @@ from core.enumerations import ConfigDataTypes class EmaneBypassModel(emanemodel.EmaneModel): name = "emane_bypass" - library = "bypassmaclayer" + # values to ignore, when writing xml files config_ignore = {"none"} - _config_mac = [ + + # mac definitions + mac_library = "bypassmaclayer" + config_mac = [ ("none", ConfigDataTypes.BOOL.value, "0", "True,False", "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_document = emane_manager.xmldoc("phy") - phy_element = phy_document.getElementsByTagName("phy").pop() - phy_element.setAttribute("name", "%s PHY" % self.name) - phy_element.setAttribute("library", "bypassphylayer") - return phy_document + # phy definitions + phy_library = "bypassphylayer" + config_phy = [] + + # defines overall config + config_matrix = config_mac + config_phy + + # gui display tabs + config_groups = "Bypass Parameters:1-1" diff --git a/daemon/core/emane/commeffect.py b/daemon/core/emane/commeffect.py index 71f3a37d..6754c353 100644 --- a/daemon/core/emane/commeffect.py +++ b/daemon/core/emane/commeffect.py @@ -3,8 +3,8 @@ commeffect.py: EMANE CommEffect model for CORE """ from core import logger +from core.emane import emanemanifest from core.emane import emanemodel -from core.enumerations import ConfigDataTypes try: from emane.events.commeffectevent import CommEffectEvent @@ -27,13 +27,11 @@ def convert_none(x): class EmaneCommEffectModel(emanemodel.EmaneModel): name = "emane_commeffect" - config_matrix = [ - ("filterfile", ConfigDataTypes.STRING.value, "", "", "filter file"), - ("groupid", ConfigDataTypes.UINT32.value, "0", "", "NEM Group ID"), - ("enablepromiscuousmode", ConfigDataTypes.BOOL.value, "0", "On,Off", "enable promiscuous mode"), - ("receivebufferperiod", ConfigDataTypes.FLOAT.value, "1.0", "", "receivebufferperiod"), - ("defaultconnectivitymode", ConfigDataTypes.BOOL.value, "1", "On,Off", "defaultconnectivity"), - ] + shim_library = "commeffectshim" + shim_xml = "/usr/share/emane/manifest/commeffectshim.xml" + shim_defaults = {} + config_shim = emanemanifest.parse(shim_xml, shim_defaults) + config_matrix = config_shim config_groups = "CommEffect SHIM Parameters:1-%d" % len(config_matrix) @@ -56,30 +54,9 @@ class EmaneCommEffectModel(emanemodel.EmaneModel): 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() - 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_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") emane_manager.appendtransporttonem(nem_document, nem_element, self.object_id, interface) @@ -87,6 +64,27 @@ class EmaneCommEffectModel(emanemodel.EmaneModel): nem_element.appendChild(shim_xml) 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): """ Generate CommEffect events when a Link Message is received having diff --git a/daemon/core/emane/emanemanifest.py b/daemon/core/emane/emanemanifest.py new file mode 100644 index 00000000..5f34ede4 --- /dev/null +++ b/daemon/core/emane/emanemanifest.py @@ -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 diff --git a/daemon/core/emane/emanemodel.py b/daemon/core/emane/emanemodel.py index ef775a93..dc1e2b38 100644 --- a/daemon/core/emane/emanemodel.py +++ b/daemon/core/emane/emanemodel.py @@ -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): diff --git a/daemon/core/emane/ieee80211abg.py b/daemon/core/emane/ieee80211abg.py index 1bb1b021..b45b19b1 100644 --- a/daemon/core/emane/ieee80211abg.py +++ b/daemon/core/emane/ieee80211abg.py @@ -2,89 +2,24 @@ ieee80211abg.py: EMANE IEEE 802.11abg model for CORE """ +from core.emane import emanemanifest from core.emane import emanemodel -from core.enumerations import ConfigDataTypes class EmaneIeee80211abgModel(emanemodel.EmaneModel): # model name name = "emane_ieee80211abg" - library = "ieee80211abgmaclayer" # mac configuration - _80211rates = "1 1 Mbps,2 2 Mbps,3 5.5 Mbps,4 11 Mbps,5 6 Mbps," + \ - "6 9 Mbps,7 12 Mbps,8 18 Mbps,9 24 Mbps,10 36 Mbps,11 48 Mbps," + \ - "12 54 Mbps" - xml_path = "/usr/share/emane/xml/models/mac/ieee80211abg" - _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"), - ("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)"), - ] + mac_library = "ieee80211abgmaclayer" + mac_xml = "/usr/share/emane/manifest/ieee80211abgmaclayer.xml" + mac_defaults = { + "pcrcurveuri": "/usr/share/emane/xml/models/mac/ieee80211abg/ieee80211pcr.xml", + } + config_mac = emanemanifest.parse(mac_xml, mac_defaults) - config_matrix = _config_mac + emanemodel.EmaneModel._config_phy - config_groups = emanemodel.create_config_groups(_config_mac, config_matrix) + # defines overall config + config_matrix = config_mac + emanemodel.EmaneModel.config_phy - def create_mac_doc(self, emane_manager, values): - names = self.getnames() - 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 + # gui display tabs + config_groups = emanemodel.create_config_groups(config_mac, config_matrix) diff --git a/daemon/core/emane/rfpipe.py b/daemon/core/emane/rfpipe.py index b104832c..0cb73812 100644 --- a/daemon/core/emane/rfpipe.py +++ b/daemon/core/emane/rfpipe.py @@ -2,31 +2,24 @@ rfpipe.py: EMANE RF-PIPE model for CORE """ +from core.emane import emanemanifest from core.emane import emanemodel -from core.enumerations import ConfigDataTypes class EmaneRfPipeModel(emanemodel.EmaneModel): # model name name = "emane_rfpipe" - library = "rfpipemaclayer" # mac configuration - xml_path = "/usr/share/emane/xml/models/mac/rfpipe" - _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"), - ("flowcontrolenable", ConfigDataTypes.BOOL.value, "0", "On,Off", "enable traffic flow control"), - ("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)"), - ] + mac_library = "rfpipemaclayer" + mac_xml = "/usr/share/emane/manifest/rfpipemaclayer.xml" + mac_defaults = { + "pcrcurveuri": "/usr/share/emane/xml/models/mac/rfpipe/rfpipepcr.xml", + } + config_mac = emanemanifest.parse(mac_xml, mac_defaults) - config_matrix = _config_mac + emanemodel.EmaneModel._config_phy - config_groups = emanemodel.create_config_groups(_config_mac, config_matrix) + # defines overall config + config_matrix = config_mac + emanemodel.EmaneModel.config_phy + + # gui display tabs + config_groups = emanemodel.create_config_groups(config_mac, config_matrix) diff --git a/daemon/core/emane/tdma.py b/daemon/core/emane/tdma.py index 86e7f90a..c54dcff0 100644 --- a/daemon/core/emane/tdma.py +++ b/daemon/core/emane/tdma.py @@ -6,6 +6,7 @@ import os from core import constants from core import logger +from core.emane import emanemanifest from core.emane import emanemodel from core.enumerations import ConfigDataTypes from core.misc import utils @@ -14,40 +15,26 @@ from core.misc import utils class EmaneTdmaModel(emanemodel.EmaneModel): # model name name = "emane_tdma" - library = "tdmaeventschedulerradiomodel" # 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" 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_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 - config_groups = emanemodel.create_config_groups(_config_mac, config_matrix) + # defines overall config + 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): """