137 lines
4.5 KiB
Python
137 lines
4.5 KiB
Python
"""
|
|
commeffect.py: EMANE CommEffect model for CORE
|
|
"""
|
|
|
|
import os
|
|
|
|
from lxml import etree
|
|
|
|
from core import logger
|
|
from core.conf import ConfigGroup
|
|
from core.emane import emanemanifest
|
|
from core.emane import emanemodel
|
|
from core.xml import emanexml
|
|
|
|
try:
|
|
from emane.events.commeffectevent import CommEffectEvent
|
|
except ImportError:
|
|
try:
|
|
from emanesh.events.commeffectevent import CommEffectEvent
|
|
except ImportError:
|
|
logger.debug("compatible emane python bindings not installed")
|
|
|
|
|
|
def convert_none(x):
|
|
"""
|
|
Helper to use 0 for None values.
|
|
"""
|
|
if type(x) is str:
|
|
x = float(x)
|
|
if x is None:
|
|
return 0
|
|
else:
|
|
return int(x)
|
|
|
|
|
|
class EmaneCommEffectModel(emanemodel.EmaneModel):
|
|
name = "emane_commeffect"
|
|
|
|
shim_library = "commeffectshim"
|
|
shim_xml = "/usr/share/emane/manifest/commeffectshim.xml"
|
|
shim_defaults = {}
|
|
config_shim = emanemanifest.parse(shim_xml, shim_defaults)
|
|
|
|
# comm effect does not need the default phy and external configurations
|
|
phy_config = ()
|
|
external_config = ()
|
|
|
|
@classmethod
|
|
def configurations(cls):
|
|
return cls.config_shim
|
|
|
|
@classmethod
|
|
def config_groups(cls):
|
|
return [
|
|
ConfigGroup("CommEffect SHIM Parameters", 1, len(cls.configurations()))
|
|
]
|
|
|
|
def build_xml_files(self, config, interface=None):
|
|
"""
|
|
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 dict config: emane model configuration for the node and interface
|
|
:param interface: interface for the emane node
|
|
:return: nothing
|
|
"""
|
|
# retrieve xml names
|
|
nem_name = emanexml.nem_file_name(self, interface)
|
|
shim_name = emanexml.shim_file_name(self, interface)
|
|
|
|
# create and write nem document
|
|
nem_element = etree.Element("nem", name="%s NEM" % self.name, type="unstructured")
|
|
transport_type = "virtual"
|
|
if interface and interface.transport_type == "raw":
|
|
transport_type = "raw"
|
|
transport_file = emanexml.transport_file_name(self.object_id, transport_type)
|
|
etree.SubElement(nem_element, "transport", definition=transport_file)
|
|
|
|
# set shim configuration
|
|
etree.SubElement(nem_element, "shim", definition=shim_name)
|
|
|
|
nem_file = os.path.join(self.session.session_dir, nem_name)
|
|
emanexml.create_file(nem_element, "nem", nem_file)
|
|
|
|
# create and write shim document
|
|
shim_element = etree.Element("shim", name="%s SHIM" % self.name, library=self.shim_library)
|
|
|
|
# append all shim options (except filterfile) to shimdoc
|
|
for configuration in self.config_shim:
|
|
name = configuration.id
|
|
if name == "filterfile":
|
|
continue
|
|
value = config[name]
|
|
emanexml.add_param(shim_element, name, value)
|
|
|
|
# empty filterfile is not allowed
|
|
ff = config["filterfile"]
|
|
if ff.strip() != "":
|
|
emanexml.add_param(shim_element, "filterfile", ff)
|
|
|
|
shim_file = os.path.join(self.session.session_dir, shim_name)
|
|
emanexml.create_file(shim_element, "shim", shim_file)
|
|
|
|
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
|
|
link parameters.
|
|
"""
|
|
service = self.session.emane.service
|
|
if service is None:
|
|
logger.warn("%s: EMANE event service unavailable", self.name)
|
|
return
|
|
|
|
if netif is None or netif2 is None:
|
|
logger.warn("%s: missing NEM information", self.name)
|
|
return
|
|
|
|
# TODO: batch these into multiple events per transmission
|
|
# TODO: may want to split out seconds portion of delay and jitter
|
|
event = CommEffectEvent()
|
|
emane_node = self.session.get_object(self.object_id)
|
|
nemid = emane_node.getnemid(netif)
|
|
nemid2 = emane_node.getnemid(netif2)
|
|
mbw = bw
|
|
logger.info("sending comm effect event")
|
|
event.append(
|
|
nemid,
|
|
latency=convert_none(delay),
|
|
jitter=convert_none(jitter),
|
|
loss=convert_none(loss),
|
|
duplicate=convert_none(duplicate),
|
|
unicast=long(convert_none(bw)),
|
|
broadcast=long(convert_none(mbw))
|
|
)
|
|
service.publish(nemid2, event)
|