core-extra/daemon/core/emane/emanemodel.py

197 lines
6.9 KiB
Python
Raw Normal View History

"""
Defines Emane Models used within CORE.
"""
from core import logger
from core.misc import utils
from core.mobility import WirelessModel
from core.xml import xmlutils
class EmaneModel(WirelessModel):
"""
EMANE models inherit from this parent class, which takes care of
handling configuration messages based on the _confmatrix list of
configurable parameters. Helper functions also live here.
"""
_prefix = {
"y": 1e-24, # yocto
"z": 1e-21, # zepto
"a": 1e-18, # atto
"f": 1e-15, # femto
"p": 1e-12, # pico
"n": 1e-9, # nano
"u": 1e-6, # micro
"m": 1e-3, # mili
"c": 1e-2, # centi
"d": 1e-1, # deci
"k": 1e3, # kilo
"M": 1e6, # mega
"G": 1e9, # giga
"T": 1e12, # tera
"P": 1e15, # peta
"E": 1e18, # exa
"Z": 1e21, # zetta
"Y": 1e24, # yotta
}
@classmethod
def configure_emane(cls, session, config_data):
"""
Handle configuration messages for setting up a model.
Pass the Emane object as the manager object.
:param core.session.Session session: session to configure emane
:param core.conf.ConfigData config_data: configuration data for carrying out a configuration
"""
return cls.configure(session.emane, config_data)
def post_startup(self, emane_manager, ifc):
"""
Logic to execute after the emane manager is finished with startup.
:param core.emane.emanemanager.EmaneManager emane_manager: emane manager for the session
:param ifc: an interface for the emane node this model is tied to
:return: nothing
"""
logger.info("%s has no post setup tasks: interface(%s)", ifc)
def buildnemxmlfiles(self, e, ifc):
"""
Build the necessary nem, mac, and phy XMLs in the given path.
"""
raise NotImplementedError
def buildplatformxmlnementry(self, doc, n, ifc):
"""
Build the NEM definition that goes into the platform.xml file.
This returns an XML element that will be added to the <platform/> element.
This default method supports per-interface config (e.g. <nem definition="n2_0_63emane_rfpipe.xml" id="1">
or per-EmaneNode config (e.g. <nem definition="n1emane_rfpipe.xml" id="1">.
This can be overriden by a model for NEM flexibility; n is the EmaneNode.
"""
nem = doc.createElement("nem")
nem.setAttribute("name", ifc.localname)
# if this netif contains a non-standard (per-interface) config,
# then we need to use a more specific xml file here
nem.setAttribute("definition", self.nemxmlname(ifc))
return nem
def buildplatformxmltransportentry(self, doc, n, ifc):
"""
Build the transport definition that goes into the platform.xml file.
This returns an XML element that will added to the nem definition.
This default method supports raw and virtual transport types, but may be
overriden by a model to support the e.g. pluggable virtual transport.
n is the EmaneNode.
"""
ttype = ifc.transport_type
if not ttype:
logger.info("warning: %s interface type unsupported!", ifc.name)
ttype = "raw"
trans = doc.createElement("transport")
trans.setAttribute("definition", n.transportxmlname(ttype))
param = doc.createElement("param")
param.setAttribute("name", "device")
if ttype == "raw":
# raw RJ45 name e.g. "eth0"
param.setAttribute("value", ifc.name)
else:
# virtual TAP name e.g. "n3.0.17"
param.setAttribute("value", ifc.localname)
param.setAttribute("value", ifc.name)
trans.appendChild(param)
return trans
def basename(self, interface=None):
"""
Return the string that other names are based on.
If a specific config is stored for a node"s interface, a unique
filename is needed; otherwise the name of the EmaneNode is used.
"""
emane = self.session.emane
name = "n%s" % self.object_id
if interface is not None:
nodenum = interface.node.objid
# Adamson change - use getifcconfig() to get proper result
# if emane.getconfig(nodenum, self._name, None)[1] is not None:
if emane.getifcconfig(nodenum, self.name, None, interface) is not None:
name = interface.localname.replace(".", "_")
return "%s%s" % (name, self.name)
def nemxmlname(self, interface=None):
"""
Return the string name for the NEM XML file, e.g. "n3rfpipenem.xml"
"""
append = ""
if interface and interface.transport_type == "raw":
append = "_raw"
return "%snem%s.xml" % (self.basename(interface), append)
def shimxmlname(self, ifc=None):
"""
Return the string name for the SHIM XML file, e.g. "commeffectshim.xml"
"""
return "%sshim.xml" % self.basename(ifc)
def macxmlname(self, ifc=None):
"""
Return the string name for the MAC XML file, e.g. "n3rfpipemac.xml"
"""
return "%smac.xml" % self.basename(ifc)
def phyxmlname(self, ifc=None):
"""
Return the string name for the PHY XML file, e.g. "n3rfpipephy.xml"
"""
return "%sphy.xml" % self.basename(ifc)
def update(self, moved, moved_netifs):
"""
invoked from MobilityModel when nodes are moved; this causes
EMANE location events to be generated for the nodes in the moved
list, making EmaneModels compatible with Ns2ScriptedMobility
"""
try:
wlan = self.session.get_object(self.object_id)
wlan.setnempositions(moved_netifs)
except KeyError:
logger.exception("error during update")
def linkconfig(self, netif, bw=None, delay=None, loss=None, duplicate=None, jitter=None, netif2=None):
"""
Invoked when a Link Message is received. Default is unimplemented.
"""
warntxt = "EMANE model %s does not support link " % self.name
warntxt += "configuration, dropping Link Message"
logger.warn(warntxt)
@staticmethod
def valuestrtoparamlist(dom, name, value):
"""
Helper to convert a parameter to a paramlist.
Returns a an XML paramlist, or None if the value does not expand to
multiple values.
"""
try:
values = utils.make_tuple_fromstr(value, str)
except SyntaxError:
logger.exception("error in value string to param list")
return None
if not hasattr(values, "__iter__"):
return None
if len(values) < 2:
return None
return xmlutils.add_param_list_to_parent(dom, parent=None, name=name, values=values)