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:
ahrenholz 2014-09-23 20:24:19 +00:00
parent e825b94e13
commit 4ee92d1711
6 changed files with 96 additions and 33 deletions

View file

@ -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)

View file

@ -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))

View file

@ -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'

View file

@ -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)

View file

@ -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)

View file

@ -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'):