daemon: initial changes to rework logic to start emane for a given interface

This commit is contained in:
Blake Harnden 2020-07-02 15:37:51 -07:00
parent da9c0d0660
commit bd48e14348
6 changed files with 262 additions and 496 deletions

View file

@ -10,6 +10,7 @@ from core.config import Configuration
from core.emane.nodes import EmaneNet
from core.emulator.distributed import DistributedServer
from core.emulator.enumerations import TransportType
from core.errors import CoreError
from core.nodes.interface import CoreInterface
from core.nodes.network import CtrlNet
from core.xml import corexml
@ -40,15 +41,11 @@ def _value_to_params(value: str) -> Optional[Tuple[str]]:
"""
try:
values = utils.make_tuple_fromstr(value, str)
if not hasattr(values, "__iter__"):
return None
if len(values) < 2:
return None
return values
except SyntaxError:
logging.exception("error in value string to param list")
return None
@ -127,13 +124,13 @@ def add_configurations(
add_param(xml_element, name, value)
def build_node_platform_xml(
def build_platform_xml(
emane_manager: "EmaneManager",
control_net: CtrlNet,
node: EmaneNet,
emane_net: EmaneNet,
iface: CoreInterface,
nem_id: int,
platform_xmls: Dict[str, etree.Element],
) -> int:
) -> None:
"""
Create platform xml for a specific node.
@ -141,175 +138,121 @@ def build_node_platform_xml(
configurations
:param control_net: control net node for this emane
network
:param node: node to write platform xml for
:param nem_id: nem id to use for interfaces for this node
:param platform_xmls: stores platform xml elements to append nem entries to
:param emane_net: emane network associated with interface
:param iface: interface running emane
:param nem_id: nem id to use for this interface
:return: the next nem id that can be used for creating platform xml files
"""
logging.debug(
"building emane platform xml for node(%s) nem_id(%s): %s",
node,
nem_id,
node.name,
# build nem xml
nem_definition = nem_file_name(iface)
nem_element = etree.Element(
"nem", id=str(nem_id), name=iface.localname, definition=nem_definition
)
nem_entries = {}
if node.model is None:
logging.warning("warning: EMANE network %s has no associated model", node.name)
return nem_id
for iface in node.get_ifaces():
logging.debug(
"building platform xml for interface(%s) nem_id(%s)", iface.name, nem_id
)
# build nem xml
nem_definition = nem_file_name(node.model, iface)
nem_element = etree.Element(
"nem", id=str(nem_id), name=iface.localname, definition=nem_definition
# check if this is an external transport, get default config if an interface
# specific one does not exist
config = emane_manager.get_iface_config(emane_net, iface)
if is_external(config):
nem_element.set("transport", "external")
platform_endpoint = "platformendpoint"
add_param(nem_element, platform_endpoint, config[platform_endpoint])
transport_endpoint = "transportendpoint"
add_param(nem_element, transport_endpoint, config[transport_endpoint])
else:
# build transport xml
transport_type = iface.transport_type
if not transport_type:
logging.info("warning: %s interface type unsupported!", iface.name)
transport_type = TransportType.RAW
transport_file = transport_file_name(iface, transport_type)
transport_element = etree.SubElement(
nem_element, "transport", definition=transport_file
)
add_param(transport_element, "device", iface.name)
# check if this is an external transport, get default config if an interface
# specific one does not exist
config = emane_manager.get_iface_config(node.model.id, iface, node.model.name)
if is_external(config):
nem_element.set("transport", "external")
platform_endpoint = "platformendpoint"
add_param(nem_element, platform_endpoint, config[platform_endpoint])
transport_endpoint = "transportendpoint"
add_param(nem_element, transport_endpoint, config[transport_endpoint])
else:
# build transport xml
transport_type = iface.transport_type
if not transport_type:
logging.info("warning: %s interface type unsupported!", iface.name)
transport_type = TransportType.RAW
transport_file = transport_file_name(node.id, transport_type)
transport_element = etree.SubElement(
nem_element, "transport", definition=transport_file
)
# add transport parameter
add_param(transport_element, "device", iface.name)
# add nem entry
nem_entries[iface] = nem_element
# merging code
key = iface.node.id
if iface.transport_type == TransportType.RAW:
key = "host"
otadev = control_net.brname
eventdev = control_net.brname
else:
otadev = None
eventdev = None
platform_element = platform_xmls.get(key)
if platform_element is None:
platform_element = etree.Element("platform")
if otadev:
emane_manager.set_config("otamanagerdevice", otadev)
if eventdev:
emane_manager.set_config("eventservicedevice", eventdev)
# append all platform options (except starting id) to doc
for configuration in emane_manager.emane_config.emulator_config:
name = configuration.id
if name == "platform_id_start":
continue
value = emane_manager.get_config(name)
add_param(platform_element, name, value)
# add platform xml
platform_xmls[key] = platform_element
platform_element.append(nem_element)
node.setnemid(iface, nem_id)
mac = _MAC_PREFIX + ":00:00:"
mac += f"{(nem_id >> 8) & 0xFF:02X}:{nem_id & 0xFF:02X}"
iface.set_mac(mac)
# increment nem id
nem_id += 1
# determine platform element to add xml to
key = iface.node.id
if iface.transport_type == TransportType.RAW:
key = "host"
otadev = control_net.brname
eventdev = control_net.brname
else:
otadev = None
eventdev = None
platform_element = etree.Element("platform")
if otadev:
emane_manager.set_config("otamanagerdevice", otadev)
if eventdev:
emane_manager.set_config("eventservicedevice", eventdev)
for configuration in emane_manager.emane_config.emulator_config:
name = configuration.id
value = emane_manager.get_config(name)
add_param(platform_element, name, value)
platform_element.append(nem_element)
emane_net.setnemid(iface, nem_id)
mac = _MAC_PREFIX + ":00:00:"
mac += f"{(nem_id >> 8) & 0xFF:02X}:{nem_id & 0xFF:02X}"
iface.set_mac(mac)
doc_name = "platform"
for key in sorted(platform_xmls.keys()):
platform_element = platform_xmls[key]
if key == "host":
file_name = "platform.xml"
file_path = os.path.join(emane_manager.session.session_dir, file_name)
create_file(platform_element, doc_name, file_path)
else:
file_name = f"platform{key}.xml"
file_path = os.path.join(emane_manager.session.session_dir, file_name)
linked_node = emane_manager.session.nodes[key]
create_file(platform_element, doc_name, file_path, linked_node.server)
return nem_id
server = None
if key == "host":
file_name = "platform.xml"
file_path = os.path.join(emane_manager.session.session_dir, file_name)
else:
node = iface.node
file_name = f"{iface.name}-platform.xml"
file_path = os.path.join(node.nodedir, file_name)
server = node.server
create_file(platform_element, doc_name, file_path, server)
def build_xml_files(emane_manager: "EmaneManager", node: EmaneNet) -> None:
def build_model_xmls(
manager: "EmaneManager", emane_net: EmaneNet, iface: CoreInterface
) -> None:
"""
Generate emane xml files required for node.
:param emane_manager: emane manager with emane
:param manager: emane manager with emane
configurations
:param node: node to write platform xml for
:param emane_net: emane network associated with interface
:param iface: interface to create emane xml for
:return: nothing
"""
logging.debug("building all emane xml for node(%s): %s", node, node.name)
if node.model is None:
return
# get model configurations
config = emane_manager.get_configs(node.model.id, node.model.name)
if not config:
return
# build XML for overall network EMANE configs
node.model.build_xml_files(config)
# build XML for specific interface (NEM) configs
# check for interface specific emane configuration and write xml files
config = manager.get_iface_config(emane_net, iface)
emane_net.model.build_xml_files(config, iface)
# check transport type needed for interface
need_virtual = False
need_raw = False
vtype = TransportType.VIRTUAL
rtype = TransportType.RAW
for iface in node.get_ifaces():
# check for interface specific emane configuration and write xml files
config = emane_manager.get_iface_config(node.model.id, iface, node.model.name)
if config:
node.model.build_xml_files(config, iface)
# check transport type needed for interface
if iface.transport_type == TransportType.VIRTUAL:
need_virtual = True
vtype = iface.transport_type
else:
need_raw = True
rtype = iface.transport_type
if iface.transport_type == TransportType.VIRTUAL:
need_virtual = True
vtype = iface.transport_type
else:
need_raw = True
rtype = iface.transport_type
if need_virtual:
build_transport_xml(emane_manager, node, vtype)
build_transport_xml(manager, emane_net, iface, vtype)
if need_raw:
build_transport_xml(emane_manager, node, rtype)
build_transport_xml(manager, emane_net, iface, rtype)
def build_transport_xml(
emane_manager: "EmaneManager", node: EmaneNet, transport_type: TransportType
manager: "EmaneManager",
emane_net: EmaneNet,
iface: CoreInterface,
transport_type: TransportType,
) -> None:
"""
Build transport xml file for node and transport type.
:param emane_manager: emane manager with emane
configurations
:param node: node to write platform xml for
:param manager: emane manager with emane configurations
:param emane_net: emane network associated with interface
:param iface: interface to build transport xml for
:param transport_type: transport type to build xml for
:return: nothing
"""
@ -318,28 +261,24 @@ def build_transport_xml(
name=f"{transport_type.value.capitalize()} Transport",
library=f"trans{transport_type.value.lower()}",
)
# add bitrate
add_param(transport_element, "bitrate", "0")
# get emane model cnfiguration
config = emane_manager.get_configs(node.id, node.model.name)
config = manager.get_iface_config(emane_net, iface)
flowcontrol = config.get("flowcontrolenable", "0") == "1"
if transport_type == TransportType.VIRTUAL:
device_path = "/dev/net/tun_flowctl"
if not os.path.exists(device_path):
device_path = "/dev/net/tun"
add_param(transport_element, "devicepath", device_path)
if flowcontrol:
add_param(transport_element, "flowcontrolenable", "on")
doc_name = "transport"
file_name = transport_file_name(node.id, transport_type)
file_path = os.path.join(emane_manager.session.session_dir, file_name)
node = iface.node
file_name = transport_file_name(iface, transport_type)
file_path = os.path.join(node.nodedir, file_name)
create_file(transport_element, doc_name, file_path)
emane_manager.session.distributed.execute(
manager.session.distributed.execute(
lambda x: create_file(transport_element, doc_name, file_path, x)
)
@ -348,7 +287,7 @@ def create_phy_xml(
emane_model: "EmaneModel",
config: Dict[str, str],
file_path: str,
server: DistributedServer,
server: Optional[DistributedServer],
) -> None:
"""
Create the phy xml document.
@ -363,25 +302,17 @@ def create_phy_xml(
phy_element = etree.Element("phy", name=f"{emane_model.name} PHY")
if emane_model.phy_library:
phy_element.set("library", emane_model.phy_library)
add_configurations(
phy_element, emane_model.phy_config, config, emane_model.config_ignore
)
create_file(phy_element, "phy", file_path)
if server is not None:
create_file(phy_element, "phy", file_path, server)
else:
create_file(phy_element, "phy", file_path)
emane_model.session.distributed.execute(
lambda x: create_file(phy_element, "phy", file_path, x)
)
create_file(phy_element, "phy", file_path, server)
def create_mac_xml(
emane_model: "EmaneModel",
config: Dict[str, str],
file_path: str,
server: DistributedServer,
server: Optional[DistributedServer],
) -> None:
"""
Create the mac xml document.
@ -394,22 +325,14 @@ def create_mac_xml(
:return: nothing
"""
if not emane_model.mac_library:
raise ValueError("must define emane model library")
raise CoreError("must define emane model library")
mac_element = etree.Element(
"mac", name=f"{emane_model.name} MAC", library=emane_model.mac_library
)
add_configurations(
mac_element, emane_model.mac_config, config, emane_model.config_ignore
)
create_file(mac_element, "mac", file_path)
if server is not None:
create_file(mac_element, "mac", file_path, server)
else:
create_file(mac_element, "mac", file_path)
emane_model.session.distributed.execute(
lambda x: create_file(mac_element, "mac", file_path, x)
)
create_file(mac_element, "mac", file_path, server)
def create_nem_xml(
@ -419,7 +342,7 @@ def create_nem_xml(
transport_definition: str,
mac_definition: str,
phy_definition: str,
server: DistributedServer,
server: Optional[DistributedServer],
) -> None:
"""
Create the nem xml document.
@ -441,13 +364,7 @@ def create_nem_xml(
etree.SubElement(nem_element, "transport", definition=transport_definition)
etree.SubElement(nem_element, "mac", definition=mac_definition)
etree.SubElement(nem_element, "phy", definition=phy_definition)
if server is not None:
create_file(nem_element, "nem", nem_file, server)
else:
create_file(nem_element, "nem", nem_file)
emane_model.session.distributed.execute(
lambda x: create_file(nem_element, "nem", nem_file, x)
)
create_file(nem_element, "nem", nem_file, server)
def create_event_service_xml(
@ -483,81 +400,55 @@ def create_event_service_xml(
create_file(event_element, "emaneeventmsgsvc", file_path, server)
def transport_file_name(node_id: int, transport_type: TransportType) -> str:
def transport_file_name(iface: CoreInterface, transport_type: TransportType) -> str:
"""
Create name for a transport xml file.
:param node_id: node id to generate transport file name for
:param iface: interface running emane
:param transport_type: transport type to generate transport file
:return:
:return: transport xml file name
"""
return f"n{node_id}trans{transport_type.value}.xml"
return f"{iface.name}-trans-{transport_type.value}.xml"
def _basename(emane_model: "EmaneModel", iface: CoreInterface = None) -> str:
def nem_file_name(iface: CoreInterface) -> str:
"""
Create name that is leveraged for configuration file creation.
Return the string name for the NEM XML file, e.g. "eth0-nem.xml"
:param emane_model: emane model to create name for
:param iface: interface for this model
:return: basename used for file creation
:param iface: interface running emane
:return: nem xm file name
"""
name = f"n{emane_model.id}"
if iface:
node_id = iface.node.id
if emane_model.session.emane.get_iface_config(node_id, iface, emane_model.name):
name = iface.localname.replace(".", "_")
return f"{name}{emane_model.name}"
def nem_file_name(emane_model: "EmaneModel", iface: CoreInterface = None) -> str:
"""
Return the string name for the NEM XML file, e.g. "n3rfpipenem.xml"
:param emane_model: emane model to create file
:param iface: interface for this model
:return: nem xml filename
"""
basename = _basename(emane_model, iface)
append = ""
if iface and iface.transport_type == TransportType.RAW:
append = "_raw"
return f"{basename}nem{append}.xml"
append = "-raw"
return f"{iface.name}-nem{append}.xml"
def shim_file_name(emane_model: "EmaneModel", iface: CoreInterface = None) -> str:
def shim_file_name(iface: CoreInterface = None) -> str:
"""
Return the string name for the SHIM XML file, e.g. "commeffectshim.xml"
Return the string name for the SHIM XML file, e.g. "eth0-shim.xml"
:param emane_model: emane model to create file
:param iface: interface for this model
:return: shim xml filename
:param iface: interface running emane
:return: shim xml file name
"""
name = _basename(emane_model, iface)
return f"{name}shim.xml"
return f"{iface.name}-shim.xml"
def mac_file_name(emane_model: "EmaneModel", iface: CoreInterface = None) -> str:
def mac_file_name(iface: CoreInterface) -> str:
"""
Return the string name for the MAC XML file, e.g. "n3rfpipemac.xml"
Return the string name for the MAC XML file, e.g. "eth0-mac.xml"
:param emane_model: emane model to create file
:param iface: interface for this model
:return: mac xml filename
:param iface: interface running emane
:return: mac xml file name
"""
name = _basename(emane_model, iface)
return f"{name}mac.xml"
return f"{iface.name}-mac.xml"
def phy_file_name(emane_model: "EmaneModel", iface: CoreInterface = None) -> str:
def phy_file_name(iface: CoreInterface) -> str:
"""
Return the string name for the PHY XML file, e.g. "n3rfpipephy.xml"
Return the string name for the PHY XML file, e.g. "eth0-phy.xml"
:param emane_model: emane model to create file
:param iface: interface for this model
:return: phy xml filename
:param iface: interface running emane
:return: phy xml file name
"""
name = _basename(emane_model, iface)
return f"{name}phy.xml"
return f"{iface.name}-phy.xml"