consolidated EmaneNode and EmaneNet, renaming EmaneNode to EmaneNet

This commit is contained in:
bharnden 2019-09-27 22:31:56 -07:00
parent b961a8a959
commit 050297587d
11 changed files with 115 additions and 112 deletions

View file

@ -12,7 +12,7 @@ import grpc
from core import CoreError
from core.api.grpc import core_pb2, core_pb2_grpc
from core.emane.nodes import EmaneNode
from core.emane.nodes import EmaneNet
from core.emulator.data import (
ConfigData,
EventData,
@ -456,7 +456,7 @@ class CoreGrpcServer(core_pb2_grpc.CoreApiServicer):
services = [x.name for x in services]
emane_model = None
if isinstance(node, EmaneNode):
if isinstance(node, EmaneNet):
emane_model = node.model.name
node_proto = core_pb2.Node(
@ -809,7 +809,7 @@ class CoreGrpcServer(core_pb2_grpc.CoreApiServicer):
interfaces.append(interface_proto)
emane_model = None
if isinstance(node, EmaneNode):
if isinstance(node, EmaneNet):
emane_model = node.model.name
services = [x.name for x in getattr(node, "services", [])]

View file

@ -15,7 +15,7 @@ from core.emane.bypass import EmaneBypassModel
from core.emane.commeffect import EmaneCommEffectModel
from core.emane.emanemodel import EmaneModel
from core.emane.ieee80211abg import EmaneIeee80211abgModel
from core.emane.nodes import EmaneNode
from core.emane.nodes import EmaneNet
from core.emane.rfpipe import EmaneRfPipeModel
from core.emane.tdma import EmaneTdmaModel
from core.emulator.enumerations import (
@ -53,8 +53,8 @@ DEFAULT_EMANE_PREFIX = "/usr"
class EmaneManager(ModelManager):
"""
EMANE controller object. Lives in a Session instance and is used for
building EMANE config files from all of the EmaneNode objects in this
emulation, and for controlling the EMANE daemons.
building EMANE config files for all EMANE networks in this emulation, and for
controlling the EMANE daemons.
"""
name = "emane"
@ -72,7 +72,7 @@ class EmaneManager(ModelManager):
"""
super(EmaneManager, self).__init__()
self.session = session
self._emane_nodes = {}
self._emane_nets = {}
self._emane_node_lock = threading.Lock()
self._ifccounts = {}
self._ifccountslock = threading.Lock()
@ -226,38 +226,39 @@ class EmaneManager(ModelManager):
emane_model.load(emane_prefix)
self.models[emane_model.name] = emane_model
def add_node(self, emane_node):
def add_node(self, emane_net):
"""
Add a new EmaneNode object to this Emane controller object
Add EMANE network object to this manager.
:param core.emane.nodes.EmaneNode emane_node: emane node to add
:param core.emane.nodes.EmaneNet emane_net: emane node to add
:return: nothing
"""
with self._emane_node_lock:
if emane_node.id in self._emane_nodes:
if emane_net.id in self._emane_nets:
raise KeyError(
"non-unique EMANE object id %s for %s" % (emane_node.id, emane_node)
"non-unique EMANE object id %s for %s" % (emane_net.id, emane_net)
)
self._emane_nodes[emane_node.id] = emane_node
self._emane_nets[emane_net.id] = emane_net
def getnodes(self):
"""
Return a set of CoreNodes that are linked to an EmaneNode,
Return a set of CoreNodes that are linked to an EMANE network,
e.g. containers having one or more radio interfaces.
"""
# assumes self._objslock already held
nodes = set()
for emane_node in self._emane_nodes.values():
for netif in emane_node.netifs():
for emane_net in self._emane_nets.values():
for netif in emane_net.netifs():
nodes.add(netif.node)
return nodes
def setup(self):
"""
Populate self._objs with EmaneNodes; perform distributed setup;
associate models with EmaneNodes from self.config. Returns
Emane.(SUCCESS, NOT_NEEDED, NOT_READY) in order to delay session
instantiation.
Setup duties for EMANE manager.
:return: SUCCESS, NOT_NEEDED, NOT_READY in order to delay session
instantiation
:rtype: int
"""
logging.debug("emane setup")
@ -265,13 +266,13 @@ class EmaneManager(ModelManager):
with self.session._nodes_lock:
for node_id in self.session.nodes:
node = self.session.nodes[node_id]
if isinstance(node, EmaneNode):
if isinstance(node, EmaneNet):
logging.debug(
"adding emane node: id(%s) name(%s)", node.id, node.name
)
self.add_node(node)
if not self._emane_nodes:
if not self._emane_nets:
logging.debug("no emane nodes in session")
return EmaneManager.NOT_NEEDED
@ -325,9 +326,12 @@ class EmaneManager(ModelManager):
def startup(self):
"""
After all the EmaneNode objects have been added, build XML files
and start the daemons. Returns Emane.(SUCCESS, NOT_NEEDED, or
NOT_READY) which is used to delay session instantiation.
After all the EMANE networks have been added, build XML files
and start the daemons.
:return: SUCCESS, NOT_NEEDED, NOT_READY in order to delay session
instantiation
:rtype: int
"""
self.reset()
r = self.setup()
@ -346,8 +350,8 @@ class EmaneManager(ModelManager):
self.startdaemons()
self.installnetifs()
for node_id in self._emane_nodes:
emane_node = self._emane_nodes[node_id]
for node_id in self._emane_nets:
emane_node = self._emane_nets[node_id]
for netif in emane_node.netifs():
nems.append(
(netif.node.name, netif.name, emane_node.getnemid(netif))
@ -372,8 +376,8 @@ class EmaneManager(ModelManager):
return
with self._emane_node_lock:
for key in sorted(self._emane_nodes.keys()):
emane_node = self._emane_nodes[key]
for key in sorted(self._emane_nets.keys()):
emane_node = self._emane_nets[key]
logging.debug(
"post startup for emane node: %s - %s",
emane_node.id,
@ -386,11 +390,11 @@ class EmaneManager(ModelManager):
def reset(self):
"""
remove all EmaneNode objects from the dictionary,
reset port numbers and nem id counters
Remove all EMANE networks from the dictionary, reset port numbers and
nem id counters
"""
with self._emane_node_lock:
self._emane_nodes.clear()
self._emane_nets.clear()
# don't clear self._ifccounts here; NEM counts are needed for buildxml
self.platformport = self.session.options.get_config_int(
@ -408,7 +412,7 @@ class EmaneManager(ModelManager):
self._ifccounts.clear()
with self._emane_node_lock:
if not self._emane_nodes:
if not self._emane_nets:
return
logging.info("stopping EMANE daemons.")
self.deinstallnetifs()
@ -448,7 +452,7 @@ class EmaneManager(ModelManager):
master = False
with self._emane_node_lock:
if self._emane_nodes:
if self._emane_nets:
master = self.session.master
logging.info("emane check distributed as master: %s.", master)
@ -458,8 +462,8 @@ class EmaneManager(ModelManager):
nemcount = 0
with self._emane_node_lock:
for key in self._emane_nodes:
emane_node = self._emane_nodes[key]
for key in self._emane_nets:
emane_node = self._emane_nets[key]
nemcount += emane_node.numnetif()
nemid = int(self.get_config("nem_id_start"))
@ -469,7 +473,7 @@ class EmaneManager(ModelManager):
# build an ordered list of servers so platform ID is deterministic
servers = []
for key in sorted(self._emane_nodes):
for key in sorted(self._emane_nets):
for server in self.session.broker.getserversbynode(key):
if server not in servers:
servers.append(server)
@ -565,11 +569,10 @@ class EmaneManager(ModelManager):
def check_node_models(self):
"""
Associate EmaneModel classes with EmaneNode nodes. The model
configurations are stored in self.configs.
Associate EMANE model classes with EMANE network nodes.
"""
for node_id in self._emane_nodes:
emane_node = self._emane_nodes[node_id]
for node_id in self._emane_nets:
emane_node = self._emane_nets[node_id]
logging.debug("checking emane model for node: %s", node_id)
# skip nodes that already have a model set
@ -595,13 +598,13 @@ class EmaneManager(ModelManager):
def nemlookup(self, nemid):
"""
Look for the given numerical NEM ID and return the first matching
EmaneNode and NEM interface.
EMANE network and NEM interface.
"""
emane_node = None
netif = None
for node_id in self._emane_nodes:
emane_node = self._emane_nodes[node_id]
for node_id in self._emane_nets:
emane_node = self._emane_nets[node_id]
netif = emane_node.getnemnetif(nemid)
if netif is not None:
break
@ -615,8 +618,8 @@ class EmaneManager(ModelManager):
Return the number of NEMs emulated locally.
"""
count = 0
for node_id in self._emane_nodes:
emane_node = self._emane_nodes[node_id]
for node_id in self._emane_nets:
emane_node = self._emane_nets[node_id]
count += len(emane_node.netifs())
return count
@ -628,20 +631,19 @@ class EmaneManager(ModelManager):
platform_xmls = {}
# assume self._objslock is already held here
for key in sorted(self._emane_nodes.keys()):
emane_node = self._emane_nodes[key]
for key in sorted(self._emane_nets.keys()):
emane_node = self._emane_nets[key]
nemid = emanexml.build_node_platform_xml(
self, ctrlnet, emane_node, nemid, platform_xmls
)
def buildnemxml(self):
"""
Builds the xxxnem.xml, xxxmac.xml, and xxxphy.xml files which
are defined on a per-EmaneNode basis.
Builds the nem, mac, and phy xml files for each EMANE network.
"""
for key in sorted(self._emane_nodes.keys()):
emane_node = self._emane_nodes[key]
emanexml.build_xml_files(self, emane_node)
for key in sorted(self._emane_nets):
emane_net = self._emane_nets[key]
emanexml.build_xml_files(self, emane_net)
def buildtransportxml(self):
"""
@ -785,8 +787,8 @@ class EmaneManager(ModelManager):
Install TUN/TAP virtual interfaces into their proper namespaces
now that the EMANE daemons are running.
"""
for key in sorted(self._emane_nodes.keys()):
emane_node = self._emane_nodes[key]
for key in sorted(self._emane_nets.keys()):
emane_node = self._emane_nets[key]
logging.info("emane install netifs for node: %d", key)
emane_node.installnetifs()
@ -794,8 +796,8 @@ class EmaneManager(ModelManager):
"""
Uninstall TUN/TAP virtual interfaces.
"""
for key in sorted(self._emane_nodes.keys()):
emane_node = self._emane_nodes[key]
for key in sorted(self._emane_nets.keys()):
emane_node = self._emane_nets[key]
emane_node.deinstallnetifs()
def doeventmonitor(self):

View file

@ -1,6 +1,5 @@
"""
nodes.py: definition of an EmaneNode class for implementing configuration
control of an EMANE emulation. An EmaneNode has several attached NEMs that
Provides an EMANE network node class, which has several attached NEMs that
share the same MAC+PHY model.
"""
@ -19,26 +18,19 @@ except ImportError:
class EmaneNet(CoreNetworkBase):
"""
EMANE network base class.
"""
apitype = NodeTypes.EMANE.value
linktype = LinkTypes.WIRELESS.value
type = "wlan"
class EmaneNode(EmaneNet):
"""
EMANE node contains NEM configuration and causes connected nodes
to have TAP interfaces (instead of VEth). These are managed by the
Emane controller object that exists in a session.
"""
apitype = NodeTypes.EMANE.value
linktype = LinkTypes.WIRELESS.value
type = "wlan"
is_emane = True
def __init__(self, session, _id=None, name=None, start=True):
super(EmaneNode, self).__init__(session, _id, name, start)
super(EmaneNet, self).__init__(session, _id, name, start)
self.conf = ""
self.up = False
self.nemidmap = {}

View file

@ -1,4 +1,4 @@
from core.emane.nodes import EmaneNode
from core.emane.nodes import EmaneNet
from core.emulator.enumerations import LinkTypes
from core.nodes.ipaddress import Ipv4Prefix, Ipv6Prefix, MacAddress
from core.nodes.physical import PhysicalNode
@ -53,8 +53,9 @@ def link_config(network, interface, link_options, devname=None, interface_two=No
"netif2": interface_two,
}
# hacky check here, because physical and emane nodes do not conform to the same linkconfig interface
if not isinstance(network, (EmaneNode, PhysicalNode)):
# hacky check here, because physical and emane nodes do not conform to the same
# linkconfig interface
if not isinstance(network, (EmaneNet, PhysicalNode)):
config["devname"] = devname
network.linkconfig(**config)
@ -70,7 +71,8 @@ class NodeOptions(object):
Create a NodeOptions object.
:param str name: name of node, defaults to node class name postfix with its id
:param str model: defines services for default and physical nodes, defaults to "router"
:param str model: defines services for default and physical nodes, defaults to
"router"
:param str image: image to use for docker nodes
"""
self.name = name
@ -122,7 +124,8 @@ class LinkOptions(object):
"""
Create a LinkOptions object.
:param core.emulator.enumerations.LinkTypes _type: type of link, defaults to wired
:param core.emulator.enumerations.LinkTypes _type: type of link, defaults to
wired
"""
self.type = _type
self.session = None
@ -191,12 +194,13 @@ class IpPrefixes(object):
def create_interface(self, node, name=None, mac=None):
"""
Creates interface data for linking nodes, using the nodes unique id for generation, along with a random
mac address, unless provided.
Creates interface data for linking nodes, using the nodes unique id for
generation, along with a random mac address, unless provided.
:param core.nodes.base.CoreNode node: node to create interface for
:param str name: name to set for interface, default is eth{id}
:param str mac: mac address to use for this interface, default is random generation
:param str mac: mac address to use for this interface, default is random
generation
:return: new interface data for the provided node
:rtype: InterfaceData
"""

View file

@ -18,7 +18,7 @@ from core import CoreError, constants, utils
from core.api.tlv import coreapi
from core.api.tlv.broker import CoreBroker
from core.emane.emanemanager import EmaneManager
from core.emane.nodes import EmaneNet, EmaneNode
from core.emane.nodes import EmaneNet
from core.emulator.data import EventData, ExceptionData, NodeData
from core.emulator.emudata import (
IdGen,
@ -62,8 +62,8 @@ NODES = {
NodeTypes.RJ45: Rj45Node,
NodeTypes.TUNNEL: TunnelNode,
NodeTypes.KTUNNEL: None,
NodeTypes.EMANE: EmaneNode,
NodeTypes.EMANE_NET: EmaneNet,
NodeTypes.EMANE: EmaneNet,
NodeTypes.EMANE_NET: None,
NodeTypes.TAP_BRIDGE: GreTapBridge,
NodeTypes.PEER_TO_PEER: PtpNet,
NodeTypes.CONTROL_NET: CtrlNet,
@ -261,7 +261,7 @@ class Session(object):
raise CoreError("no common network found for wireless link/unlink")
for common_network, interface_one, interface_two in common_networks:
if not isinstance(common_network, (WlanNode, EmaneNode)):
if not isinstance(common_network, (WlanNode, EmaneNet)):
logging.info(
"skipping common network that is not wireless/emane: %s",
common_network,

View file

@ -8,7 +8,7 @@ import socket
from future.moves.urllib.parse import urlparse
from core import CoreError, constants
from core.emane.nodes import EmaneNode
from core.emane.nodes import EmaneNet
from core.emulator.enumerations import (
EventTypes,
LinkTlvs,
@ -365,7 +365,7 @@ class Sdt(object):
for net in nets:
all_links = net.all_link_data(flags=MessageFlags.ADD.value)
for link_data in all_links:
is_wireless = isinstance(net, (WlanNode, EmaneNode))
is_wireless = isinstance(net, (WlanNode, EmaneNet))
wireless_link = link_data.message_type == LinkTypes.WIRELESS.value
if is_wireless and link_data.node1_id == net.id:
continue
@ -493,7 +493,7 @@ class Sdt(object):
def wlancheck(self, nodenum):
"""
Helper returns True if a node number corresponds to a WlanNode or EmaneNode.
Helper returns True if a node number corresponds to a WLAN or EMANE node.
:param int nodenum: node id to check
:return: True if node is wlan or emane, False otherwise
@ -508,6 +508,6 @@ class Sdt(object):
n = self.session.get_node(nodenum)
except CoreError:
return False
if isinstance(n, (WlanNode, EmaneNode)):
if isinstance(n, (WlanNode, EmaneNet)):
return True
return False

View file

@ -1,4 +1,4 @@
from core.emane.nodes import EmaneNode
from core.emane.nodes import EmaneNet
from core.services.coreservices import CoreService
from core.xml import emanexml
@ -21,7 +21,7 @@ class EmaneTransportService(CoreService):
transport_commands = []
for interface in node.netifs(sort=True):
network_node = node.session.get_node(interface.net.id)
if isinstance(network_node, EmaneNode):
if isinstance(network_node, EmaneNet):
config = node.session.emane.get_configs(
network_node.id, network_node.model.name
)

View file

@ -3,7 +3,7 @@ quagga.py: defines routing services provided by Quagga.
"""
from core import constants
from core.emane.nodes import EmaneNode
from core.emane.nodes import EmaneNet
from core.emulator.enumerations import LinkTypes
from core.nodes import ipaddress
from core.nodes.network import PtpNet, WlanNode
@ -460,7 +460,7 @@ class Ospfv3mdr(Ospfv3):
cfg = cls.mtucheck(ifc)
# Uncomment the following line to use Address Family Translation for IPv4
cfg += " ipv6 ospf6 instance-id 65\n"
if ifc.net is not None and isinstance(ifc.net, (WlanNode, EmaneNode)):
if ifc.net is not None and isinstance(ifc.net, (WlanNode, EmaneNet)):
return (
cfg
+ """\

View file

@ -4,7 +4,7 @@ from lxml import etree
import core.nodes.base
import core.nodes.physical
from core.emane.nodes import EmaneNode
from core.emane.nodes import EmaneNet
from core.emulator.emudata import InterfaceData, LinkOptions, NodeOptions
from core.emulator.enumerations import NodeTypes
from core.nodes.base import CoreNetworkBase
@ -458,7 +458,7 @@ class CoreXmlWriter(object):
interface_name = node_interface.name
# check if emane interface
if isinstance(node_interface.net, EmaneNode):
if isinstance(node_interface.net, EmaneNet):
nem = node_interface.net.getnemid(node_interface)
add_attribute(interface, "nem", nem)

View file

@ -4,7 +4,7 @@ import socket
from lxml import etree
from core import constants, utils
from core.emane.nodes import EmaneNode
from core.emane.nodes import EmaneNet
from core.nodes import ipaddress
from core.nodes.base import CoreNodeBase
@ -144,7 +144,7 @@ class CoreXmlDeployment(object):
for netif in node.netifs():
emane_element = None
if isinstance(netif.net, EmaneNode):
if isinstance(netif.net, EmaneNet):
emane_element = add_emane_interface(host_element, netif)
parent_element = host_element

View file

@ -103,9 +103,11 @@ def build_node_platform_xml(emane_manager, control_net, node, nem_id, platform_x
"""
Create platform xml for a specific node.
:param core.emane.emanemanager.EmaneManager emane_manager: emane manager with emane configurations
:param core.nodes.network.CtrlNet control_net: control net node for this emane network
:param core.emane.nodes.EmaneNode node: node to write platform xml for
:param core.emane.emanemanager.EmaneManager emane_manager: emane manager with emane
configurations
:param core.nodes.network.CtrlNet control_net: control net node for this emane
network
:param core.emane.nodes.EmaneNet node: node to write platform xml for
:param int nem_id: nem id to use for interfaces for this node
:param dict platform_xmls: stores platform xml elements to append nem entries to
:return: the next nem id that can be used for creating platform xml files
@ -120,7 +122,7 @@ def build_node_platform_xml(emane_manager, control_net, node, nem_id, platform_x
nem_entries = {}
if node.model is None:
logging.warning("warning: EmaneNode %s has no associated model", node.name)
logging.warning("warning: EMANE network %s has no associated model", node.name)
return nem_entries
for netif in node.netifs():
@ -133,7 +135,8 @@ def build_node_platform_xml(emane_manager, control_net, node, nem_id, platform_x
"nem", id=str(nem_id), name=netif.localname, definition=nem_definition
)
# check if this is an external transport, get default config if an interface specific one does not exist
# check if this is an external transport, get default config if an interface
# specific one does not exist
config = emane_manager.getifcconfig(node.model.id, netif, node.model.name)
if is_external(config):
@ -220,8 +223,9 @@ def build_xml_files(emane_manager, node):
"""
Generate emane xml files required for node.
:param core.emane.emanemanager.EmaneManager emane_manager: emane manager with emane configurations
:param core.emane.nodes.EmaneNode node: node to write platform xml for
:param core.emane.emanemanager.EmaneManager emane_manager: emane manager with emane
configurations
:param core.emane.nodes.EmaneNet node: node to write platform xml for
:return: nothing
"""
logging.debug("building all emane xml for node(%s): %s", node, node.name)
@ -233,7 +237,7 @@ def build_xml_files(emane_manager, node):
if not config:
return
# build XML for overall network (EmaneNode) configs
# build XML for overall network EMANE configs
node.model.build_xml_files(config)
# build XML for specific interface (NEM) configs
@ -243,7 +247,7 @@ def build_xml_files(emane_manager, node):
rtype = "raw"
for netif in node.netifs():
# check for interface specific emane configuration and write xml files, if needed
# check for interface specific emane configuration and write xml files
config = emane_manager.getifcconfig(node.model.id, netif, node.model.name)
if config:
node.model.build_xml_files(config, netif)
@ -267,8 +271,9 @@ def build_transport_xml(emane_manager, node, transport_type):
"""
Build transport xml file for node and transport type.
:param core.emane.emanemanager.EmaneManager emane_manager: emane manager with emane configurations
:param core.emane.nodes.EmaneNode node: node to write platform xml for
:param core.emane.emanemanager.EmaneManager emane_manager: emane manager with emane
configurations
:param core.emane.nodes.EmaneNet node: node to write platform xml for
:param str transport_type: transport type to build xml for
:return: nothing
"""
@ -304,7 +309,7 @@ def create_phy_xml(emane_model, config, file_path):
"""
Create the phy xml document.
:param core.emane.emanemodel.EmaneModel emane_model: emane model to create phy xml for
:param core.emane.emanemodel.EmaneModel emane_model: emane model to create xml
:param dict config: all current configuration values
:param str file_path: path to write file to
:return: nothing
@ -323,7 +328,7 @@ def create_mac_xml(emane_model, config, file_path):
"""
Create the mac xml document.
:param core.emane.emanemodel.EmaneModel emane_model: emane model to create phy xml for
:param core.emane.emanemodel.EmaneModel emane_model: emane model to create xml
:param dict config: all current configuration values
:param str file_path: path to write file to
:return: nothing
@ -346,7 +351,7 @@ def create_nem_xml(
"""
Create the nem xml document.
:param core.emane.emanemodel.EmaneModel emane_model: emane model to create phy xml for
:param core.emane.emanemodel.EmaneModel emane_model: emane model to create xml
:param dict config: all current configuration values
:param str nem_file: nem file path to write
:param str transport_definition: transport file definition path
@ -422,7 +427,7 @@ def nem_file_name(emane_model, interface=None):
"""
Return the string name for the NEM XML file, e.g. "n3rfpipenem.xml"
:param core.emane.emanemodel.EmaneModel emane_model: emane model to create phy xml for
:param core.emane.emanemodel.EmaneModel emane_model: emane model to create file
:param interface: interface for this model
:return: nem xml filename
:rtype: str
@ -438,7 +443,7 @@ def shim_file_name(emane_model, interface=None):
"""
Return the string name for the SHIM XML file, e.g. "commeffectshim.xml"
:param core.emane.emanemodel.EmaneModel emane_model: emane model to create phy xml for
:param core.emane.emanemodel.EmaneModel emane_model: emane model to create file
:param interface: interface for this model
:return: shim xml filename
:rtype: str
@ -450,7 +455,7 @@ def mac_file_name(emane_model, interface=None):
"""
Return the string name for the MAC XML file, e.g. "n3rfpipemac.xml"
:param core.emane.emanemodel.EmaneModel emane_model: emane model to create phy xml for
:param core.emane.emanemodel.EmaneModel emane_model: emane model to create file
:param interface: interface for this model
:return: mac xml filename
:rtype: str
@ -462,7 +467,7 @@ def phy_file_name(emane_model, interface=None):
"""
Return the string name for the PHY XML file, e.g. "n3rfpipephy.xml"
:param core.emane.emanemodel.EmaneModel emane_model: emane model to create phy xml for
:param core.emane.emanemodel.EmaneModel emane_model: emane model to create file
:param interface: interface for this model
:return: phy xml filename
:rtype: str