support linking RJ45 with EMANE 0.9.2 using Raw transport;
build extra XML and launch emane process on host for the raw devices (Boeing r1882)
This commit is contained in:
parent
e825b94e13
commit
4ee92d1711
6 changed files with 96 additions and 33 deletions
|
@ -42,7 +42,7 @@ class EmaneBypassModel(EmaneModel):
|
||||||
nemdoc = e.xmldoc("nem")
|
nemdoc = e.xmldoc("nem")
|
||||||
nem = nemdoc.getElementsByTagName("nem").pop()
|
nem = nemdoc.getElementsByTagName("nem").pop()
|
||||||
nem.setAttribute("name", "BYPASS NEM")
|
nem.setAttribute("name", "BYPASS NEM")
|
||||||
e.appendtransporttonem(nemdoc, nem, self.objid)
|
e.appendtransporttonem(nemdoc, nem, self.objid, ifc)
|
||||||
mactag = nemdoc.createElement("mac")
|
mactag = nemdoc.createElement("mac")
|
||||||
mactag.setAttribute("definition", self.macxmlname(ifc))
|
mactag.setAttribute("definition", self.macxmlname(ifc))
|
||||||
nem.appendChild(mactag)
|
nem.appendChild(mactag)
|
||||||
|
|
|
@ -95,7 +95,7 @@ class EmaneCommEffectModel(EmaneModel):
|
||||||
nem = nemdoc.getElementsByTagName("nem").pop()
|
nem = nemdoc.getElementsByTagName("nem").pop()
|
||||||
nem.setAttribute("name", "commeffect NEM")
|
nem.setAttribute("name", "commeffect NEM")
|
||||||
nem.setAttribute("type", "unstructured")
|
nem.setAttribute("type", "unstructured")
|
||||||
e.appendtransporttonem(nemdoc, nem, self.objid)
|
e.appendtransporttonem(nemdoc, nem, self.objid, ifc)
|
||||||
nem.appendChild(e.xmlshimdefinition(nemdoc, self.shimxmlname(ifc)))
|
nem.appendChild(e.xmlshimdefinition(nemdoc, self.shimxmlname(ifc)))
|
||||||
e.xmlwrite(nemdoc, self.nemxmlname(ifc))
|
e.xmlwrite(nemdoc, self.nemxmlname(ifc))
|
||||||
|
|
||||||
|
|
|
@ -224,7 +224,14 @@ class Emane(ConfigurableManager):
|
||||||
# don't use default values when interface config is the same as net
|
# don't use default values when interface config is the same as net
|
||||||
# note here that using ifc.node.objid as key allows for only one type
|
# note here that using ifc.node.objid as key allows for only one type
|
||||||
# of each model per node; TODO: use both node and interface as key
|
# of each model per node; TODO: use both node and interface as key
|
||||||
return self.getconfig(ifc.node.objid, conftype, None)[1]
|
values = self.getconfig(ifc.node.objid, conftype, None)[1]
|
||||||
|
if not values and self.version > self.EMANE091:
|
||||||
|
# with EMANE 0.9.2+, we need an extra NEM XML from
|
||||||
|
# model.buildnemxmlfiles(), so defaults are returned here
|
||||||
|
if ifc.transport_type == "raw":
|
||||||
|
values = self.getconfig(nodenum, conftype, defaultvalues)[1]
|
||||||
|
return values
|
||||||
|
|
||||||
|
|
||||||
def setup(self):
|
def setup(self):
|
||||||
''' Populate self._objs with EmaneNodes; perform distributed setup;
|
''' Populate self._objs with EmaneNodes; perform distributed setup;
|
||||||
|
@ -416,12 +423,12 @@ class Emane(ConfigurableManager):
|
||||||
NEMs run inside containers using the control network for passing
|
NEMs run inside containers using the control network for passing
|
||||||
events and data.
|
events and data.
|
||||||
'''
|
'''
|
||||||
# control network bridge needs to exist when eventservice binds to it
|
|
||||||
self.session.addremovectrlif(node=None, remove=False, conf_reqd=False)
|
|
||||||
# assume self._objslock is already held here
|
# assume self._objslock is already held here
|
||||||
if self.verbose:
|
if self.verbose:
|
||||||
self.info("Emane.buildxml2()")
|
self.info("Emane.buildxml2()")
|
||||||
self.buildplatformxml2()
|
# control network bridge needs to exist when eventservice binds to it
|
||||||
|
ctrlnet = self.session.addremovectrlnet(remove=False, conf_reqd=False)
|
||||||
|
self.buildplatformxml2(ctrlnet)
|
||||||
self.buildnemxml()
|
self.buildnemxml()
|
||||||
self.buildeventservicexml()
|
self.buildeventservicexml()
|
||||||
|
|
||||||
|
@ -567,18 +574,30 @@ class Emane(ConfigurableManager):
|
||||||
self.transformport += 1
|
self.transformport += 1
|
||||||
self.xmlwrite(doc, "platform.xml")
|
self.xmlwrite(doc, "platform.xml")
|
||||||
|
|
||||||
def newplatformxmldoc(self, values):
|
def newplatformxmldoc(self, values, otadev=None, eventdev=None):
|
||||||
|
''' Start a new platform XML file. Use global EMANE config values
|
||||||
|
as keys. Override OTA manager and event service devices if
|
||||||
|
specified (in order to support Raw Transport).
|
||||||
|
'''
|
||||||
doc = self.xmldoc("platform")
|
doc = self.xmldoc("platform")
|
||||||
plat = doc.getElementsByTagName("platform").pop()
|
plat = doc.getElementsByTagName("platform").pop()
|
||||||
names = list(self.emane_config.getnames())
|
names = list(self.emane_config.getnames())
|
||||||
platform_names = names[:len(self.emane_config._confmatrix_platform)]
|
platform_names = names[:len(self.emane_config._confmatrix_platform)]
|
||||||
platform_names.remove('platform_id_start')
|
platform_names.remove('platform_id_start')
|
||||||
|
platform_values = list(values)
|
||||||
|
if otadev:
|
||||||
|
i = platform_names.index('otamanagerdevice')
|
||||||
|
platform_values[i] = otadev
|
||||||
|
if eventdev:
|
||||||
|
i = platform_names.index('eventservicedevice')
|
||||||
|
platform_values[i] = eventdev
|
||||||
# append all platform options (except starting id) to doc
|
# append all platform options (except starting id) to doc
|
||||||
map( lambda n: plat.appendChild(self.xmlparam(doc, n, \
|
map( lambda n: plat.appendChild(self.xmlparam(doc, n, \
|
||||||
self.emane_config.valueof(n, values))), platform_names)
|
self.emane_config.valueof(n, platform_values))), \
|
||||||
|
platform_names)
|
||||||
return doc
|
return doc
|
||||||
|
|
||||||
def buildplatformxml2(self):
|
def buildplatformxml2(self, ctrlnet):
|
||||||
''' Build a platform.xml file now that all nodes are configured.
|
''' Build a platform.xml file now that all nodes are configured.
|
||||||
'''
|
'''
|
||||||
values = self.getconfig(None, "emane",
|
values = self.getconfig(None, "emane",
|
||||||
|
@ -591,13 +610,20 @@ class Emane(ConfigurableManager):
|
||||||
emanenode = self._objs[n]
|
emanenode = self._objs[n]
|
||||||
nems = emanenode.buildplatformxmlentry(self.xmldoc("platform"))
|
nems = emanenode.buildplatformxmlentry(self.xmldoc("platform"))
|
||||||
for netif in sorted(nems, key=lambda n: n.node.objid):
|
for netif in sorted(nems, key=lambda n: n.node.objid):
|
||||||
# set ID, endpoints here
|
|
||||||
nementry = nems[netif]
|
nementry = nems[netif]
|
||||||
nementry.setAttribute("id", "%d" % nemid)
|
nementry.setAttribute("id", "%d" % nemid)
|
||||||
nodenum = netif.node.objid
|
k = netif.node.objid
|
||||||
if nodenum not in platformxmls:
|
if netif.transport_type == "raw":
|
||||||
platformxmls[nodenum] = self.newplatformxmldoc(values)
|
k = 'host'
|
||||||
doc = platformxmls[nodenum]
|
otadev = ctrlnet.brname
|
||||||
|
eventdev = ctrlnet.brname
|
||||||
|
else:
|
||||||
|
otadev = None
|
||||||
|
eventdev = None
|
||||||
|
if k not in platformxmls:
|
||||||
|
platformxmls[k] = self.newplatformxmldoc(values, otadev,
|
||||||
|
eventdev)
|
||||||
|
doc = platformxmls[k]
|
||||||
plat = doc.getElementsByTagName("platform").pop()
|
plat = doc.getElementsByTagName("platform").pop()
|
||||||
plat.appendChild(nementry)
|
plat.appendChild(nementry)
|
||||||
emanenode.setnemid(netif, nemid)
|
emanenode.setnemid(netif, nemid)
|
||||||
|
@ -605,8 +631,11 @@ class Emane(ConfigurableManager):
|
||||||
macstr += "%02X:%02X" % ((nemid >> 8) & 0xFF, nemid & 0xFF)
|
macstr += "%02X:%02X" % ((nemid >> 8) & 0xFF, nemid & 0xFF)
|
||||||
netif.sethwaddr(MacAddr.fromstring(macstr))
|
netif.sethwaddr(MacAddr.fromstring(macstr))
|
||||||
nemid += 1
|
nemid += 1
|
||||||
for nodenum in sorted(platformxmls.keys()):
|
for k in sorted(platformxmls.keys()):
|
||||||
self.xmlwrite(platformxmls[nodenum], "platform%d.xml" % nodenum)
|
if k == 'host':
|
||||||
|
self.xmlwrite(platformxmls['host'], "platform.xml")
|
||||||
|
continue
|
||||||
|
self.xmlwrite(platformxmls[k], "platform%d.xml" % k)
|
||||||
|
|
||||||
def buildnemxml(self):
|
def buildnemxml(self):
|
||||||
''' Builds the xxxnem.xml, xxxmac.xml, and xxxphy.xml files which
|
''' Builds the xxxnem.xml, xxxmac.xml, and xxxphy.xml files which
|
||||||
|
@ -616,7 +645,7 @@ class Emane(ConfigurableManager):
|
||||||
emanenode = self._objs[n]
|
emanenode = self._objs[n]
|
||||||
nems = emanenode.buildnemxmlfiles(self)
|
nems = emanenode.buildnemxmlfiles(self)
|
||||||
|
|
||||||
def appendtransporttonem(self, doc, nem, nodenum):
|
def appendtransporttonem(self, doc, nem, nodenum, ifc=None):
|
||||||
''' Given a nem XML node and EMANE WLAN node number, append
|
''' Given a nem XML node and EMANE WLAN node number, append
|
||||||
a <transport/> tag to the NEM definition, required for using
|
a <transport/> tag to the NEM definition, required for using
|
||||||
EMANE's internal transport.
|
EMANE's internal transport.
|
||||||
|
@ -625,8 +654,11 @@ class Emane(ConfigurableManager):
|
||||||
return
|
return
|
||||||
emanenode = self._objs[nodenum]
|
emanenode = self._objs[nodenum]
|
||||||
transtag = doc.createElement("transport")
|
transtag = doc.createElement("transport")
|
||||||
|
transtypestr = "virtual"
|
||||||
|
if ifc and ifc.transport_type == "raw":
|
||||||
|
transtypestr = "raw"
|
||||||
transtag.setAttribute("definition",
|
transtag.setAttribute("definition",
|
||||||
emanenode.transportxmlname("virtual"))
|
emanenode.transportxmlname(transtypestr))
|
||||||
nem.appendChild(transtag)
|
nem.appendChild(transtag)
|
||||||
|
|
||||||
def buildtransportxml(self):
|
def buildtransportxml(self):
|
||||||
|
@ -746,7 +778,12 @@ class Emane(ConfigurableManager):
|
||||||
values).split(':')
|
values).split(':')
|
||||||
otadev = self.emane_config.valueof('otamanagerdevice', values)
|
otadev = self.emane_config.valueof('otamanagerdevice', values)
|
||||||
|
|
||||||
|
run_emane_on_host = False
|
||||||
for node in self.getnodes():
|
for node in self.getnodes():
|
||||||
|
if hasattr(node, 'transport_type') and \
|
||||||
|
node.transport_type == "raw":
|
||||||
|
run_emane_on_host = True
|
||||||
|
continue
|
||||||
path = self.session.sessiondir
|
path = self.session.sessiondir
|
||||||
n = node.objid
|
n = node.objid
|
||||||
# control network not yet started here
|
# control network not yet started here
|
||||||
|
@ -760,7 +797,7 @@ class Emane(ConfigurableManager):
|
||||||
cmd = emanecmd + ["-f", os.path.join(path, "emane%d.log" % n),
|
cmd = emanecmd + ["-f", os.path.join(path, "emane%d.log" % n),
|
||||||
os.path.join(path, "platform%d.xml" % n)]
|
os.path.join(path, "platform%d.xml" % n)]
|
||||||
if self.verbose:
|
if self.verbose:
|
||||||
self.info("Emane.startdaemons() running %s" % str(cmd))
|
self.info("Emane.startdaemons2() running %s" % str(cmd))
|
||||||
#node.cmd(cmd, cwd=path, wait=True)
|
#node.cmd(cmd, cwd=path, wait=True)
|
||||||
#status, result = node.cmdresult(cmd, cwd=path, wait=True)
|
#status, result = node.cmdresult(cmd, cwd=path, wait=True)
|
||||||
status = node.cmd(cmd, wait=True)
|
status = node.cmd(cmd, wait=True)
|
||||||
|
@ -771,6 +808,20 @@ class Emane(ConfigurableManager):
|
||||||
self.session.exception(coreapi.CORE_EXCP_LEVEL_FATAL, "emane",
|
self.session.exception(coreapi.CORE_EXCP_LEVEL_FATAL, "emane",
|
||||||
n, errmsg)
|
n, errmsg)
|
||||||
self.info(errmsg)
|
self.info(errmsg)
|
||||||
|
if not run_emane_on_host:
|
||||||
|
return
|
||||||
|
path = self.session.sessiondir
|
||||||
|
try:
|
||||||
|
emanecmd += ["-f", os.path.join(path, "emane.log")]
|
||||||
|
cmd = emanecmd + [os.path.join(path, "platform.xml")]
|
||||||
|
if self.verbose:
|
||||||
|
self.info("Emane.startdaemons2() running %s" % str(cmd))
|
||||||
|
subprocess.check_call(cmd, cwd=path)
|
||||||
|
except Exception, e:
|
||||||
|
errmsg = "error starting emane: %s" % e
|
||||||
|
self.session.exception(coreapi.CORE_EXCP_LEVEL_FATAL, "emane",
|
||||||
|
None, errmsg)
|
||||||
|
self.info(errmsg)
|
||||||
|
|
||||||
def stopdaemons(self):
|
def stopdaemons(self):
|
||||||
''' Kill the appropriate EMANE daemons.
|
''' Kill the appropriate EMANE daemons.
|
||||||
|
@ -778,12 +829,19 @@ class Emane(ConfigurableManager):
|
||||||
# TODO: we may want to improve this if we had the PIDs from the
|
# TODO: we may want to improve this if we had the PIDs from the
|
||||||
# specific EMANE daemons that we've started
|
# specific EMANE daemons that we've started
|
||||||
cmd = ["killall", "-q", "emane"]
|
cmd = ["killall", "-q", "emane"]
|
||||||
|
stop_emane_on_host = False
|
||||||
if self.version > self.EMANE091:
|
if self.version > self.EMANE091:
|
||||||
for node in self.getnodes():
|
for node in self.getnodes():
|
||||||
|
if hasattr(node, 'transport_type') and \
|
||||||
|
node.transport_type == "raw":
|
||||||
|
stop_emane_on_host = True
|
||||||
|
continue
|
||||||
if node.up:
|
if node.up:
|
||||||
node.cmd(cmd, wait=False)
|
node.cmd(cmd, wait=False)
|
||||||
# TODO: RJ45 node
|
# TODO: RJ45 node
|
||||||
else:
|
else:
|
||||||
|
stop_emane_on_host = True
|
||||||
|
if stop_emane_on_host:
|
||||||
subprocess.call(cmd)
|
subprocess.call(cmd)
|
||||||
subprocess.call(["killall", "-q", "emanetransportd"])
|
subprocess.call(["killall", "-q", "emanetransportd"])
|
||||||
|
|
||||||
|
@ -792,10 +850,10 @@ class Emane(ConfigurableManager):
|
||||||
now that the EMANE daemons are running.
|
now that the EMANE daemons are running.
|
||||||
'''
|
'''
|
||||||
for n in sorted(self._objs.keys()):
|
for n in sorted(self._objs.keys()):
|
||||||
emanenode = self._objs[n]
|
emanenode = self._objs[n]
|
||||||
if self.verbose:
|
if self.verbose:
|
||||||
self.info("Emane.installnetifs() for node %d" % n)
|
self.info("Emane.installnetifs() for node %d" % n)
|
||||||
emanenode.installnetifs(do_netns)
|
emanenode.installnetifs(do_netns)
|
||||||
|
|
||||||
def deinstallnetifs(self):
|
def deinstallnetifs(self):
|
||||||
''' Uninstall TUN/TAP virtual interfaces.
|
''' Uninstall TUN/TAP virtual interfaces.
|
||||||
|
@ -1042,17 +1100,17 @@ class EmaneModel(WirelessModel):
|
||||||
overriden by a model to support the e.g. pluggable virtual transport.
|
overriden by a model to support the e.g. pluggable virtual transport.
|
||||||
n is the EmaneNode.
|
n is the EmaneNode.
|
||||||
'''
|
'''
|
||||||
type = ifc.transport_type
|
ttype = ifc.transport_type
|
||||||
if not type:
|
if not ttype:
|
||||||
e.info("warning: %s interface type unsupported!" % ifc.name)
|
self.session.info("warning: %s interface type unsupported!" % ifc.name)
|
||||||
type = "raw"
|
ttype = "raw"
|
||||||
trans = doc.createElement("transport")
|
trans = doc.createElement("transport")
|
||||||
trans.setAttribute("definition", n.transportxmlname(type))
|
trans.setAttribute("definition", n.transportxmlname(ttype))
|
||||||
if self.session.emane.version < self.session.emane.EMANE092:
|
if self.session.emane.version < self.session.emane.EMANE092:
|
||||||
trans.setAttribute("group", "1")
|
trans.setAttribute("group", "1")
|
||||||
param = doc.createElement("param")
|
param = doc.createElement("param")
|
||||||
param.setAttribute("name", "device")
|
param.setAttribute("name", "device")
|
||||||
if type == "raw":
|
if ttype == "raw":
|
||||||
# raw RJ45 name e.g. 'eth0'
|
# raw RJ45 name e.g. 'eth0'
|
||||||
param.setAttribute("value", ifc.name)
|
param.setAttribute("value", ifc.name)
|
||||||
else:
|
else:
|
||||||
|
@ -1080,7 +1138,11 @@ class EmaneModel(WirelessModel):
|
||||||
def nemxmlname(self, ifc = None):
|
def nemxmlname(self, ifc = None):
|
||||||
''' Return the string name for the NEM XML file, e.g. 'n3rfpipenem.xml'
|
''' Return the string name for the NEM XML file, e.g. 'n3rfpipenem.xml'
|
||||||
'''
|
'''
|
||||||
return "%snem.xml" % self.basename(ifc)
|
append = ""
|
||||||
|
if self.session.emane.version > self.session.emane.EMANE091:
|
||||||
|
if ifc and ifc.transport_type == "raw":
|
||||||
|
append = "_raw"
|
||||||
|
return "%snem%s.xml" % (self.basename(ifc), append)
|
||||||
|
|
||||||
def shimxmlname(self, ifc = None):
|
def shimxmlname(self, ifc = None):
|
||||||
''' Return the string name for the SHIM XML file, e.g. 'commeffectshim.xml'
|
''' Return the string name for the SHIM XML file, e.g. 'commeffectshim.xml'
|
||||||
|
|
|
@ -100,7 +100,7 @@ class EmaneIeee80211abgModel(EmaneModel):
|
||||||
nemdoc = e.xmldoc("nem")
|
nemdoc = e.xmldoc("nem")
|
||||||
nem = nemdoc.getElementsByTagName("nem").pop()
|
nem = nemdoc.getElementsByTagName("nem").pop()
|
||||||
nem.setAttribute("name", "ieee80211abg NEM")
|
nem.setAttribute("name", "ieee80211abg NEM")
|
||||||
e.appendtransporttonem(nemdoc, nem, self.objid)
|
e.appendtransporttonem(nemdoc, nem, self.objid, ifc)
|
||||||
mactag = nemdoc.createElement("mac")
|
mactag = nemdoc.createElement("mac")
|
||||||
mactag.setAttribute("definition", self.macxmlname(ifc))
|
mactag.setAttribute("definition", self.macxmlname(ifc))
|
||||||
nem.appendChild(mactag)
|
nem.appendChild(mactag)
|
||||||
|
|
|
@ -86,7 +86,7 @@ class EmaneRfPipeModel(EmaneModel):
|
||||||
nemdoc = e.xmldoc("nem")
|
nemdoc = e.xmldoc("nem")
|
||||||
nem = nemdoc.getElementsByTagName("nem").pop()
|
nem = nemdoc.getElementsByTagName("nem").pop()
|
||||||
nem.setAttribute("name", "RF-PIPE NEM")
|
nem.setAttribute("name", "RF-PIPE NEM")
|
||||||
e.appendtransporttonem(nemdoc, nem, self.objid)
|
e.appendtransporttonem(nemdoc, nem, self.objid, ifc)
|
||||||
mactag = nemdoc.createElement("mac")
|
mactag = nemdoc.createElement("mac")
|
||||||
mactag.setAttribute("definition", self.macxmlname(ifc))
|
mactag.setAttribute("definition", self.macxmlname(ifc))
|
||||||
nem.appendChild(mactag)
|
nem.appendChild(mactag)
|
||||||
|
|
|
@ -739,7 +739,8 @@ class Session(object):
|
||||||
def addremovectrlnet(self, remove=False, conf_reqd=True):
|
def addremovectrlnet(self, remove=False, conf_reqd=True):
|
||||||
''' Create a control network bridge as necessary.
|
''' Create a control network bridge as necessary.
|
||||||
When the remove flag is True, remove the bridge that connects control
|
When the remove flag is True, remove the bridge that connects control
|
||||||
interfaces.
|
interfaces. The conf_reqd flag, when False, causes a control network
|
||||||
|
bridge to be added even if one has not been configured.
|
||||||
'''
|
'''
|
||||||
prefix = self.cfg.get('controlnet')
|
prefix = self.cfg.get('controlnet')
|
||||||
if hasattr(self.options, 'controlnet'):
|
if hasattr(self.options, 'controlnet'):
|
||||||
|
|
Loading…
Add table
Reference in a new issue