daemon: updated core.emane to avoid using deprecated type hinting
This commit is contained in:
parent
3d722a7721
commit
4c222d1a7a
9 changed files with 73 additions and 78 deletions
|
@ -6,7 +6,7 @@ import logging
|
||||||
import os
|
import os
|
||||||
import threading
|
import threading
|
||||||
from enum import Enum
|
from enum import Enum
|
||||||
from typing import TYPE_CHECKING, Dict, List, Optional, Set, Tuple, Type, Union
|
from typing import TYPE_CHECKING, Optional, Union
|
||||||
|
|
||||||
from core import utils
|
from core import utils
|
||||||
from core.emane.emanemodel import EmaneModel
|
from core.emane.emanemodel import EmaneModel
|
||||||
|
@ -126,9 +126,9 @@ class EmaneManager:
|
||||||
"""
|
"""
|
||||||
super().__init__()
|
super().__init__()
|
||||||
self.session: "Session" = session
|
self.session: "Session" = session
|
||||||
self.nems_to_ifaces: Dict[int, CoreInterface] = {}
|
self.nems_to_ifaces: dict[int, CoreInterface] = {}
|
||||||
self.ifaces_to_nems: Dict[CoreInterface, int] = {}
|
self.ifaces_to_nems: dict[CoreInterface, int] = {}
|
||||||
self._emane_nets: Dict[int, EmaneNet] = {}
|
self._emane_nets: dict[int, EmaneNet] = {}
|
||||||
self._emane_node_lock: threading.Lock = threading.Lock()
|
self._emane_node_lock: threading.Lock = threading.Lock()
|
||||||
# port numbers are allocated from these counters
|
# port numbers are allocated from these counters
|
||||||
self.platformport: int = self.session.options.get_int(
|
self.platformport: int = self.session.options.get_int(
|
||||||
|
@ -141,14 +141,14 @@ class EmaneManager:
|
||||||
self.eventmonthread: Optional[threading.Thread] = None
|
self.eventmonthread: Optional[threading.Thread] = None
|
||||||
|
|
||||||
# model for global EMANE configuration options
|
# model for global EMANE configuration options
|
||||||
self.node_configs: Dict[int, Dict[str, Dict[str, str]]] = {}
|
self.node_configs: dict[int, dict[str, dict[str, str]]] = {}
|
||||||
self.node_models: Dict[int, str] = {}
|
self.node_models: dict[int, str] = {}
|
||||||
|
|
||||||
# link monitor
|
# link monitor
|
||||||
self.link_monitor: EmaneLinkMonitor = EmaneLinkMonitor(self)
|
self.link_monitor: EmaneLinkMonitor = EmaneLinkMonitor(self)
|
||||||
# emane event monitoring
|
# emane event monitoring
|
||||||
self.services: Dict[str, EmaneEventService] = {}
|
self.services: dict[str, EmaneEventService] = {}
|
||||||
self.nem_service: Dict[int, EmaneEventService] = {}
|
self.nem_service: dict[int, EmaneEventService] = {}
|
||||||
|
|
||||||
def next_nem_id(self, iface: CoreInterface) -> int:
|
def next_nem_id(self, iface: CoreInterface) -> int:
|
||||||
nem_id = self.session.options.get_int("nem_id_start")
|
nem_id = self.session.options.get_int("nem_id_start")
|
||||||
|
@ -161,7 +161,7 @@ class EmaneManager:
|
||||||
|
|
||||||
def get_config(
|
def get_config(
|
||||||
self, key: int, model: str, default: bool = True
|
self, key: int, model: str, default: bool = True
|
||||||
) -> Optional[Dict[str, str]]:
|
) -> Optional[dict[str, str]]:
|
||||||
"""
|
"""
|
||||||
Get the current or default configuration for an emane model.
|
Get the current or default configuration for an emane model.
|
||||||
|
|
||||||
|
@ -181,7 +181,7 @@ class EmaneManager:
|
||||||
config = model_class.default_values()
|
config = model_class.default_values()
|
||||||
return config
|
return config
|
||||||
|
|
||||||
def set_config(self, key: int, model: str, config: Dict[str, str] = None) -> None:
|
def set_config(self, key: int, model: str, config: dict[str, str] = None) -> None:
|
||||||
"""
|
"""
|
||||||
Sets and update the provided configuration against the default model
|
Sets and update the provided configuration against the default model
|
||||||
or currently set emane model configuration.
|
or currently set emane model configuration.
|
||||||
|
@ -199,7 +199,7 @@ class EmaneManager:
|
||||||
model_configs = self.node_configs.setdefault(key, {})
|
model_configs = self.node_configs.setdefault(key, {})
|
||||||
model_configs[model] = model_config
|
model_configs[model] = model_config
|
||||||
|
|
||||||
def get_model(self, model_name: str) -> Type[EmaneModel]:
|
def get_model(self, model_name: str) -> type[EmaneModel]:
|
||||||
"""
|
"""
|
||||||
Convenience method for getting globally loaded emane models.
|
Convenience method for getting globally loaded emane models.
|
||||||
|
|
||||||
|
@ -211,7 +211,7 @@ class EmaneManager:
|
||||||
|
|
||||||
def get_iface_config(
|
def get_iface_config(
|
||||||
self, emane_net: EmaneNet, iface: CoreInterface
|
self, emane_net: EmaneNet, iface: CoreInterface
|
||||||
) -> Dict[str, str]:
|
) -> dict[str, str]:
|
||||||
"""
|
"""
|
||||||
Retrieve configuration for a given interface, first checking for interface
|
Retrieve configuration for a given interface, first checking for interface
|
||||||
specific config, node specific config, network specific config, and finally
|
specific config, node specific config, network specific config, and finally
|
||||||
|
@ -260,7 +260,7 @@ class EmaneManager:
|
||||||
)
|
)
|
||||||
self._emane_nets[emane_net.id] = emane_net
|
self._emane_nets[emane_net.id] = emane_net
|
||||||
|
|
||||||
def getnodes(self) -> Set[CoreNode]:
|
def getnodes(self) -> set[CoreNode]:
|
||||||
"""
|
"""
|
||||||
Return a set of CoreNodes that are linked to an EMANE network,
|
Return a set of CoreNodes that are linked to an EMANE network,
|
||||||
e.g. containers having one or more radio interfaces.
|
e.g. containers having one or more radio interfaces.
|
||||||
|
@ -335,7 +335,7 @@ class EmaneManager:
|
||||||
self.start_daemon(iface)
|
self.start_daemon(iface)
|
||||||
self.install_iface(iface, config)
|
self.install_iface(iface, config)
|
||||||
|
|
||||||
def get_ifaces(self) -> List[Tuple[EmaneNet, TunTap]]:
|
def get_ifaces(self) -> list[tuple[EmaneNet, TunTap]]:
|
||||||
ifaces = []
|
ifaces = []
|
||||||
for emane_net in self._emane_nets.values():
|
for emane_net in self._emane_nets.values():
|
||||||
if not emane_net.wireless_model:
|
if not emane_net.wireless_model:
|
||||||
|
@ -354,7 +354,7 @@ class EmaneManager:
|
||||||
return sorted(ifaces, key=lambda x: (x[1].node.id, x[1].id))
|
return sorted(ifaces, key=lambda x: (x[1].node.id, x[1].id))
|
||||||
|
|
||||||
def setup_control_channels(
|
def setup_control_channels(
|
||||||
self, nem_id: int, iface: CoreInterface, config: Dict[str, str]
|
self, nem_id: int, iface: CoreInterface, config: dict[str, str]
|
||||||
) -> None:
|
) -> None:
|
||||||
node = iface.node
|
node = iface.node
|
||||||
# setup ota device
|
# setup ota device
|
||||||
|
@ -419,7 +419,7 @@ class EmaneManager:
|
||||||
|
|
||||||
def get_nem_position(
|
def get_nem_position(
|
||||||
self, iface: CoreInterface
|
self, iface: CoreInterface
|
||||||
) -> Optional[Tuple[int, float, float, int]]:
|
) -> Optional[tuple[int, float, float, int]]:
|
||||||
"""
|
"""
|
||||||
Retrieves nem position for a given interface.
|
Retrieves nem position for a given interface.
|
||||||
|
|
||||||
|
@ -453,7 +453,7 @@ class EmaneManager:
|
||||||
event.append(nemid, latitude=lat, longitude=lon, altitude=alt)
|
event.append(nemid, latitude=lat, longitude=lon, altitude=alt)
|
||||||
self.publish_event(nemid, event, send_all=True)
|
self.publish_event(nemid, event, send_all=True)
|
||||||
|
|
||||||
def set_nem_positions(self, moved_ifaces: List[CoreInterface]) -> None:
|
def set_nem_positions(self, moved_ifaces: list[CoreInterface]) -> None:
|
||||||
"""
|
"""
|
||||||
Several NEMs have moved, from e.g. a WaypointMobilityModel
|
Several NEMs have moved, from e.g. a WaypointMobilityModel
|
||||||
calculation. Generate an EMANE Location Event having several
|
calculation. Generate an EMANE Location Event having several
|
||||||
|
@ -480,7 +480,7 @@ class EmaneManager:
|
||||||
try:
|
try:
|
||||||
with path.open("a") as f:
|
with path.open("a") as f:
|
||||||
f.write(f"{iface.node.name} {iface.name} {nem_id}\n")
|
f.write(f"{iface.node.name} {iface.name} {nem_id}\n")
|
||||||
except IOError:
|
except OSError:
|
||||||
logger.exception("error writing to emane nem file")
|
logger.exception("error writing to emane nem file")
|
||||||
|
|
||||||
def links_enabled(self) -> bool:
|
def links_enabled(self) -> bool:
|
||||||
|
@ -624,7 +624,7 @@ class EmaneManager:
|
||||||
args = f"{emanecmd} -f {log_file} {platform_xml}"
|
args = f"{emanecmd} -f {log_file} {platform_xml}"
|
||||||
node.host_cmd(args, cwd=self.session.directory)
|
node.host_cmd(args, cwd=self.session.directory)
|
||||||
|
|
||||||
def install_iface(self, iface: TunTap, config: Dict[str, str]) -> None:
|
def install_iface(self, iface: TunTap, config: dict[str, str]) -> None:
|
||||||
external = config.get("external", "0")
|
external = config.get("external", "0")
|
||||||
if external == "0":
|
if external == "0":
|
||||||
iface.set_ips()
|
iface.set_ips()
|
||||||
|
|
|
@ -1,6 +1,5 @@
|
||||||
import logging
|
import logging
|
||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
from typing import Dict, List
|
|
||||||
|
|
||||||
from core.config import Configuration
|
from core.config import Configuration
|
||||||
from core.emulator.enumerations import ConfigDataTypes
|
from core.emulator.enumerations import ConfigDataTypes
|
||||||
|
@ -33,7 +32,7 @@ def _type_value(config_type: str) -> ConfigDataTypes:
|
||||||
return ConfigDataTypes[config_type]
|
return ConfigDataTypes[config_type]
|
||||||
|
|
||||||
|
|
||||||
def _get_possible(config_type: str, config_regex: str) -> List[str]:
|
def _get_possible(config_type: str, config_regex: str) -> list[str]:
|
||||||
"""
|
"""
|
||||||
Retrieve possible config value options based on emane regexes.
|
Retrieve possible config value options based on emane regexes.
|
||||||
|
|
||||||
|
@ -51,7 +50,7 @@ def _get_possible(config_type: str, config_regex: str) -> List[str]:
|
||||||
return []
|
return []
|
||||||
|
|
||||||
|
|
||||||
def _get_default(config_type_name: str, config_value: List[str]) -> str:
|
def _get_default(config_type_name: str, config_value: list[str]) -> str:
|
||||||
"""
|
"""
|
||||||
Convert default configuration values to one used by core.
|
Convert default configuration values to one used by core.
|
||||||
|
|
||||||
|
@ -74,7 +73,7 @@ def _get_default(config_type_name: str, config_value: List[str]) -> str:
|
||||||
return config_default
|
return config_default
|
||||||
|
|
||||||
|
|
||||||
def parse(manifest_path: Path, defaults: Dict[str, str]) -> List[Configuration]:
|
def parse(manifest_path: Path, defaults: dict[str, str]) -> list[Configuration]:
|
||||||
"""
|
"""
|
||||||
Parses a valid emane manifest file and converts the provided configuration values
|
Parses a valid emane manifest file and converts the provided configuration values
|
||||||
into ones used by core.
|
into ones used by core.
|
||||||
|
|
|
@ -3,7 +3,7 @@ Defines Emane Models used within CORE.
|
||||||
"""
|
"""
|
||||||
import logging
|
import logging
|
||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
from typing import Dict, List, Optional, Set
|
from typing import Optional
|
||||||
|
|
||||||
from core.config import ConfigBool, ConfigGroup, ConfigString, Configuration
|
from core.config import ConfigBool, ConfigGroup, ConfigString, Configuration
|
||||||
from core.emane import emanemanifest
|
from core.emane import emanemanifest
|
||||||
|
@ -28,38 +28,38 @@ class EmaneModel(WirelessModel):
|
||||||
# default platform configuration settings
|
# default platform configuration settings
|
||||||
platform_controlport: str = "controlportendpoint"
|
platform_controlport: str = "controlportendpoint"
|
||||||
platform_xml: str = "nemmanager.xml"
|
platform_xml: str = "nemmanager.xml"
|
||||||
platform_defaults: Dict[str, str] = {
|
platform_defaults: dict[str, str] = {
|
||||||
"eventservicedevice": DEFAULT_DEV,
|
"eventservicedevice": DEFAULT_DEV,
|
||||||
"eventservicegroup": "224.1.2.8:45703",
|
"eventservicegroup": "224.1.2.8:45703",
|
||||||
"otamanagerdevice": DEFAULT_DEV,
|
"otamanagerdevice": DEFAULT_DEV,
|
||||||
"otamanagergroup": "224.1.2.8:45702",
|
"otamanagergroup": "224.1.2.8:45702",
|
||||||
}
|
}
|
||||||
platform_config: List[Configuration] = []
|
platform_config: list[Configuration] = []
|
||||||
|
|
||||||
# default mac configuration settings
|
# default mac configuration settings
|
||||||
mac_library: Optional[str] = None
|
mac_library: Optional[str] = None
|
||||||
mac_xml: Optional[str] = None
|
mac_xml: Optional[str] = None
|
||||||
mac_defaults: Dict[str, str] = {}
|
mac_defaults: dict[str, str] = {}
|
||||||
mac_config: List[Configuration] = []
|
mac_config: list[Configuration] = []
|
||||||
|
|
||||||
# default phy configuration settings, using the universal model
|
# default phy configuration settings, using the universal model
|
||||||
phy_library: Optional[str] = None
|
phy_library: Optional[str] = None
|
||||||
phy_xml: str = "emanephy.xml"
|
phy_xml: str = "emanephy.xml"
|
||||||
phy_defaults: Dict[str, str] = {
|
phy_defaults: dict[str, str] = {
|
||||||
"subid": "1",
|
"subid": "1",
|
||||||
"propagationmodel": "2ray",
|
"propagationmodel": "2ray",
|
||||||
"noisemode": "none",
|
"noisemode": "none",
|
||||||
}
|
}
|
||||||
phy_config: List[Configuration] = []
|
phy_config: list[Configuration] = []
|
||||||
|
|
||||||
# support for external configurations
|
# support for external configurations
|
||||||
external_config: List[Configuration] = [
|
external_config: list[Configuration] = [
|
||||||
ConfigBool(id="external", default="0"),
|
ConfigBool(id="external", default="0"),
|
||||||
ConfigString(id="platformendpoint", default="127.0.0.1:40001"),
|
ConfigString(id="platformendpoint", default="127.0.0.1:40001"),
|
||||||
ConfigString(id="transportendpoint", default="127.0.0.1:50002"),
|
ConfigString(id="transportendpoint", default="127.0.0.1:50002"),
|
||||||
]
|
]
|
||||||
|
|
||||||
config_ignore: Set[str] = set()
|
config_ignore: set[str] = set()
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def load(cls, emane_prefix: Path) -> None:
|
def load(cls, emane_prefix: Path) -> None:
|
||||||
|
@ -94,7 +94,7 @@ class EmaneModel(WirelessModel):
|
||||||
cls.platform_config.pop(controlport_index)
|
cls.platform_config.pop(controlport_index)
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def configurations(cls) -> List[Configuration]:
|
def configurations(cls) -> list[Configuration]:
|
||||||
"""
|
"""
|
||||||
Returns the combination all all configurations (mac, phy, and external).
|
Returns the combination all all configurations (mac, phy, and external).
|
||||||
|
|
||||||
|
@ -105,7 +105,7 @@ class EmaneModel(WirelessModel):
|
||||||
)
|
)
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def config_groups(cls) -> List[ConfigGroup]:
|
def config_groups(cls) -> list[ConfigGroup]:
|
||||||
"""
|
"""
|
||||||
Returns the defined configuration groups.
|
Returns the defined configuration groups.
|
||||||
|
|
||||||
|
@ -122,7 +122,7 @@ class EmaneModel(WirelessModel):
|
||||||
ConfigGroup("External Parameters", phy_len + 1, config_len),
|
ConfigGroup("External Parameters", phy_len + 1, config_len),
|
||||||
]
|
]
|
||||||
|
|
||||||
def build_xml_files(self, config: Dict[str, str], iface: CoreInterface) -> None:
|
def build_xml_files(self, config: dict[str, str], iface: CoreInterface) -> None:
|
||||||
"""
|
"""
|
||||||
Builds xml files for this emane model. Creates a nem.xml file that points to
|
Builds xml files for this emane model. Creates a nem.xml file that points to
|
||||||
both mac.xml and phy.xml definitions.
|
both mac.xml and phy.xml definitions.
|
||||||
|
@ -146,7 +146,7 @@ class EmaneModel(WirelessModel):
|
||||||
"""
|
"""
|
||||||
logger.debug("emane model(%s) has no post setup tasks", self.name)
|
logger.debug("emane model(%s) has no post setup tasks", self.name)
|
||||||
|
|
||||||
def update(self, moved_ifaces: List[CoreInterface]) -> None:
|
def update(self, moved_ifaces: list[CoreInterface]) -> None:
|
||||||
"""
|
"""
|
||||||
Invoked from MobilityModel when nodes are moved; this causes
|
Invoked from MobilityModel when nodes are moved; this causes
|
||||||
emane location events to be generated for the nodes in the moved
|
emane location events to be generated for the nodes in the moved
|
||||||
|
|
|
@ -2,7 +2,7 @@ import logging
|
||||||
import sched
|
import sched
|
||||||
import threading
|
import threading
|
||||||
import time
|
import time
|
||||||
from typing import TYPE_CHECKING, Dict, List, Optional, Set, Tuple
|
from typing import TYPE_CHECKING, Optional
|
||||||
|
|
||||||
from lxml import etree
|
from lxml import etree
|
||||||
|
|
||||||
|
@ -34,10 +34,10 @@ NEM_SELF: int = 65535
|
||||||
|
|
||||||
|
|
||||||
class LossTable:
|
class LossTable:
|
||||||
def __init__(self, losses: Dict[float, float]) -> None:
|
def __init__(self, losses: dict[float, float]) -> None:
|
||||||
self.losses: Dict[float, float] = losses
|
self.losses: dict[float, float] = losses
|
||||||
self.sinrs: List[float] = sorted(self.losses.keys())
|
self.sinrs: list[float] = sorted(self.losses.keys())
|
||||||
self.loss_lookup: Dict[int, float] = {}
|
self.loss_lookup: dict[int, float] = {}
|
||||||
for index, value in enumerate(self.sinrs):
|
for index, value in enumerate(self.sinrs):
|
||||||
self.loss_lookup[index] = self.losses[value]
|
self.loss_lookup[index] = self.losses[value]
|
||||||
self.mac_id: Optional[str] = None
|
self.mac_id: Optional[str] = None
|
||||||
|
@ -84,7 +84,7 @@ class EmaneClient:
|
||||||
self.client: shell.ControlPortClient = shell.ControlPortClient(
|
self.client: shell.ControlPortClient = shell.ControlPortClient(
|
||||||
self.address, port
|
self.address, port
|
||||||
)
|
)
|
||||||
self.nems: Dict[int, LossTable] = {}
|
self.nems: dict[int, LossTable] = {}
|
||||||
self.setup()
|
self.setup()
|
||||||
|
|
||||||
def setup(self) -> None:
|
def setup(self) -> None:
|
||||||
|
@ -110,7 +110,7 @@ class EmaneClient:
|
||||||
self.nems[nem_id] = loss_table
|
self.nems[nem_id] = loss_table
|
||||||
|
|
||||||
def check_links(
|
def check_links(
|
||||||
self, links: Dict[Tuple[int, int], EmaneLink], loss_threshold: int
|
self, links: dict[tuple[int, int], EmaneLink], loss_threshold: int
|
||||||
) -> None:
|
) -> None:
|
||||||
for from_nem, loss_table in self.nems.items():
|
for from_nem, loss_table in self.nems.items():
|
||||||
tables = self.client.getStatisticTable(loss_table.mac_id, (SINR_TABLE,))
|
tables = self.client.getStatisticTable(loss_table.mac_id, (SINR_TABLE,))
|
||||||
|
@ -138,11 +138,11 @@ class EmaneClient:
|
||||||
link = EmaneLink(from_nem, to_nem, sinr)
|
link = EmaneLink(from_nem, to_nem, sinr)
|
||||||
links[link_key] = link
|
links[link_key] = link
|
||||||
|
|
||||||
def handle_tdma(self, config: Dict[str, Tuple]):
|
def handle_tdma(self, config: dict[str, tuple]):
|
||||||
pcr = config["pcrcurveuri"][0][0]
|
pcr = config["pcrcurveuri"][0][0]
|
||||||
logger.debug("tdma pcr: %s", pcr)
|
logger.debug("tdma pcr: %s", pcr)
|
||||||
|
|
||||||
def handle_80211(self, config: Dict[str, Tuple]) -> LossTable:
|
def handle_80211(self, config: dict[str, tuple]) -> LossTable:
|
||||||
unicastrate = config["unicastrate"][0][0]
|
unicastrate = config["unicastrate"][0][0]
|
||||||
pcr = config["pcrcurveuri"][0][0]
|
pcr = config["pcrcurveuri"][0][0]
|
||||||
logger.debug("80211 pcr: %s", pcr)
|
logger.debug("80211 pcr: %s", pcr)
|
||||||
|
@ -159,7 +159,7 @@ class EmaneClient:
|
||||||
losses[sinr] = por
|
losses[sinr] = por
|
||||||
return LossTable(losses)
|
return LossTable(losses)
|
||||||
|
|
||||||
def handle_rfpipe(self, config: Dict[str, Tuple]) -> LossTable:
|
def handle_rfpipe(self, config: dict[str, tuple]) -> LossTable:
|
||||||
pcr = config["pcrcurveuri"][0][0]
|
pcr = config["pcrcurveuri"][0][0]
|
||||||
logger.debug("rfpipe pcr: %s", pcr)
|
logger.debug("rfpipe pcr: %s", pcr)
|
||||||
tree = etree.parse(pcr)
|
tree = etree.parse(pcr)
|
||||||
|
@ -179,9 +179,9 @@ class EmaneClient:
|
||||||
class EmaneLinkMonitor:
|
class EmaneLinkMonitor:
|
||||||
def __init__(self, emane_manager: "EmaneManager") -> None:
|
def __init__(self, emane_manager: "EmaneManager") -> None:
|
||||||
self.emane_manager: "EmaneManager" = emane_manager
|
self.emane_manager: "EmaneManager" = emane_manager
|
||||||
self.clients: List[EmaneClient] = []
|
self.clients: list[EmaneClient] = []
|
||||||
self.links: Dict[Tuple[int, int], EmaneLink] = {}
|
self.links: dict[tuple[int, int], EmaneLink] = {}
|
||||||
self.complete_links: Set[Tuple[int, int]] = set()
|
self.complete_links: set[tuple[int, int]] = set()
|
||||||
self.loss_threshold: Optional[int] = None
|
self.loss_threshold: Optional[int] = None
|
||||||
self.link_interval: Optional[int] = None
|
self.link_interval: Optional[int] = None
|
||||||
self.link_timeout: Optional[int] = None
|
self.link_timeout: Optional[int] = None
|
||||||
|
@ -210,7 +210,7 @@ class EmaneLinkMonitor:
|
||||||
if client.nems:
|
if client.nems:
|
||||||
self.clients.append(client)
|
self.clients.append(client)
|
||||||
|
|
||||||
def get_addresses(self) -> List[Tuple[str, int]]:
|
def get_addresses(self) -> list[tuple[str, int]]:
|
||||||
addresses = []
|
addresses = []
|
||||||
nodes = self.emane_manager.getnodes()
|
nodes = self.emane_manager.getnodes()
|
||||||
for node in nodes:
|
for node in nodes:
|
||||||
|
@ -273,25 +273,25 @@ class EmaneLinkMonitor:
|
||||||
if self.running:
|
if self.running:
|
||||||
self.scheduler.enter(self.link_interval, 0, self.check_links)
|
self.scheduler.enter(self.link_interval, 0, self.check_links)
|
||||||
|
|
||||||
def get_complete_id(self, link_id: Tuple[int, int]) -> Tuple[int, int]:
|
def get_complete_id(self, link_id: tuple[int, int]) -> tuple[int, int]:
|
||||||
value1, value2 = link_id
|
value1, value2 = link_id
|
||||||
if value1 < value2:
|
if value1 < value2:
|
||||||
return value1, value2
|
return value1, value2
|
||||||
else:
|
else:
|
||||||
return value2, value1
|
return value2, value1
|
||||||
|
|
||||||
def is_complete_link(self, link_id: Tuple[int, int]) -> bool:
|
def is_complete_link(self, link_id: tuple[int, int]) -> bool:
|
||||||
reverse_id = link_id[1], link_id[0]
|
reverse_id = link_id[1], link_id[0]
|
||||||
return link_id in self.links and reverse_id in self.links
|
return link_id in self.links and reverse_id in self.links
|
||||||
|
|
||||||
def get_link_label(self, link_id: Tuple[int, int]) -> str:
|
def get_link_label(self, link_id: tuple[int, int]) -> str:
|
||||||
source_id = tuple(sorted(link_id))
|
source_id = tuple(sorted(link_id))
|
||||||
source_link = self.links[source_id]
|
source_link = self.links[source_id]
|
||||||
dest_id = link_id[::-1]
|
dest_id = link_id[::-1]
|
||||||
dest_link = self.links[dest_id]
|
dest_link = self.links[dest_id]
|
||||||
return f"{source_link.sinr:.1f} / {dest_link.sinr:.1f}"
|
return f"{source_link.sinr:.1f} / {dest_link.sinr:.1f}"
|
||||||
|
|
||||||
def send_link(self, message_type: MessageFlags, link_id: Tuple[int, int]) -> None:
|
def send_link(self, message_type: MessageFlags, link_id: tuple[int, int]) -> None:
|
||||||
nem1, nem2 = link_id
|
nem1, nem2 = link_id
|
||||||
link = self.emane_manager.get_nem_link(nem1, nem2, message_type)
|
link = self.emane_manager.get_nem_link(nem1, nem2, message_type)
|
||||||
if link:
|
if link:
|
||||||
|
|
|
@ -1,7 +1,6 @@
|
||||||
import logging
|
import logging
|
||||||
import pkgutil
|
import pkgutil
|
||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
from typing import Dict, List, Type
|
|
||||||
|
|
||||||
from core import utils
|
from core import utils
|
||||||
from core.emane import models as emane_models
|
from core.emane import models as emane_models
|
||||||
|
@ -12,10 +11,10 @@ logger = logging.getLogger(__name__)
|
||||||
|
|
||||||
|
|
||||||
class EmaneModelManager:
|
class EmaneModelManager:
|
||||||
models: Dict[str, Type[EmaneModel]] = {}
|
models: dict[str, type[EmaneModel]] = {}
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def load_locals(cls, emane_prefix: Path) -> List[str]:
|
def load_locals(cls, emane_prefix: Path) -> list[str]:
|
||||||
"""
|
"""
|
||||||
Load local core emane models and make them available.
|
Load local core emane models and make them available.
|
||||||
|
|
||||||
|
@ -38,7 +37,7 @@ class EmaneModelManager:
|
||||||
return errors
|
return errors
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def load(cls, path: Path, emane_prefix: Path) -> List[str]:
|
def load(cls, path: Path, emane_prefix: Path) -> list[str]:
|
||||||
"""
|
"""
|
||||||
Search and load custom emane models and make them available.
|
Search and load custom emane models and make them available.
|
||||||
|
|
||||||
|
@ -63,7 +62,7 @@ class EmaneModelManager:
|
||||||
return errors
|
return errors
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def get(cls, name: str) -> Type[EmaneModel]:
|
def get(cls, name: str) -> type[EmaneModel]:
|
||||||
model = cls.models.get(name)
|
model = cls.models.get(name)
|
||||||
if model is None:
|
if model is None:
|
||||||
raise CoreError(f"emame model does not exist {name}")
|
raise CoreError(f"emame model does not exist {name}")
|
||||||
|
|
|
@ -2,7 +2,6 @@
|
||||||
EMANE Bypass model for CORE
|
EMANE Bypass model for CORE
|
||||||
"""
|
"""
|
||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
from typing import List, Set
|
|
||||||
|
|
||||||
from core.config import ConfigBool, Configuration
|
from core.config import ConfigBool, Configuration
|
||||||
from core.emane import emanemodel
|
from core.emane import emanemodel
|
||||||
|
@ -12,11 +11,11 @@ class EmaneBypassModel(emanemodel.EmaneModel):
|
||||||
name: str = "emane_bypass"
|
name: str = "emane_bypass"
|
||||||
|
|
||||||
# values to ignore, when writing xml files
|
# values to ignore, when writing xml files
|
||||||
config_ignore: Set[str] = {"none"}
|
config_ignore: set[str] = {"none"}
|
||||||
|
|
||||||
# mac definitions
|
# mac definitions
|
||||||
mac_library: str = "bypassmaclayer"
|
mac_library: str = "bypassmaclayer"
|
||||||
mac_config: List[Configuration] = [
|
mac_config: list[Configuration] = [
|
||||||
ConfigBool(
|
ConfigBool(
|
||||||
id="none",
|
id="none",
|
||||||
default="0",
|
default="0",
|
||||||
|
@ -26,7 +25,7 @@ class EmaneBypassModel(emanemodel.EmaneModel):
|
||||||
|
|
||||||
# phy definitions
|
# phy definitions
|
||||||
phy_library: str = "bypassphylayer"
|
phy_library: str = "bypassphylayer"
|
||||||
phy_config: List[Configuration] = []
|
phy_config: list[Configuration] = []
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def load(cls, emane_prefix: Path) -> None:
|
def load(cls, emane_prefix: Path) -> None:
|
||||||
|
|
|
@ -4,7 +4,6 @@ commeffect.py: EMANE CommEffect model for CORE
|
||||||
|
|
||||||
import logging
|
import logging
|
||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
from typing import Dict, List
|
|
||||||
|
|
||||||
from lxml import etree
|
from lxml import etree
|
||||||
|
|
||||||
|
@ -42,12 +41,12 @@ class EmaneCommEffectModel(emanemodel.EmaneModel):
|
||||||
name: str = "emane_commeffect"
|
name: str = "emane_commeffect"
|
||||||
shim_library: str = "commeffectshim"
|
shim_library: str = "commeffectshim"
|
||||||
shim_xml: str = "commeffectshim.xml"
|
shim_xml: str = "commeffectshim.xml"
|
||||||
shim_defaults: Dict[str, str] = {}
|
shim_defaults: dict[str, str] = {}
|
||||||
config_shim: List[Configuration] = []
|
config_shim: list[Configuration] = []
|
||||||
|
|
||||||
# comm effect does not need the default phy and external configurations
|
# comm effect does not need the default phy and external configurations
|
||||||
phy_config: List[Configuration] = []
|
phy_config: list[Configuration] = []
|
||||||
external_config: List[Configuration] = []
|
external_config: list[Configuration] = []
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def load(cls, emane_prefix: Path) -> None:
|
def load(cls, emane_prefix: Path) -> None:
|
||||||
|
@ -56,11 +55,11 @@ class EmaneCommEffectModel(emanemodel.EmaneModel):
|
||||||
cls.config_shim = emanemanifest.parse(shim_xml_path, cls.shim_defaults)
|
cls.config_shim = emanemanifest.parse(shim_xml_path, cls.shim_defaults)
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def configurations(cls) -> List[Configuration]:
|
def configurations(cls) -> list[Configuration]:
|
||||||
return cls.platform_config + cls.config_shim
|
return cls.platform_config + cls.config_shim
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def config_groups(cls) -> List[ConfigGroup]:
|
def config_groups(cls) -> list[ConfigGroup]:
|
||||||
platform_len = len(cls.platform_config)
|
platform_len = len(cls.platform_config)
|
||||||
return [
|
return [
|
||||||
ConfigGroup("Platform Parameters", 1, platform_len),
|
ConfigGroup("Platform Parameters", 1, platform_len),
|
||||||
|
@ -71,7 +70,7 @@ class EmaneCommEffectModel(emanemodel.EmaneModel):
|
||||||
),
|
),
|
||||||
]
|
]
|
||||||
|
|
||||||
def build_xml_files(self, config: Dict[str, str], iface: CoreInterface) -> None:
|
def build_xml_files(self, config: dict[str, str], iface: CoreInterface) -> None:
|
||||||
"""
|
"""
|
||||||
Build the necessary nem and commeffect XMLs in the given path.
|
Build the necessary nem and commeffect XMLs in the given path.
|
||||||
If an individual NEM has a nonstandard config, we need to build
|
If an individual NEM has a nonstandard config, we need to build
|
||||||
|
|
|
@ -4,7 +4,6 @@ tdma.py: EMANE TDMA model bindings for CORE
|
||||||
|
|
||||||
import logging
|
import logging
|
||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
from typing import Set
|
|
||||||
|
|
||||||
from core import constants, utils
|
from core import constants, utils
|
||||||
from core.config import ConfigString
|
from core.config import ConfigString
|
||||||
|
@ -28,7 +27,7 @@ class EmaneTdmaModel(emanemodel.EmaneModel):
|
||||||
default_schedule: Path = (
|
default_schedule: Path = (
|
||||||
constants.CORE_DATA_DIR / "examples" / "tdma" / "schedule.xml"
|
constants.CORE_DATA_DIR / "examples" / "tdma" / "schedule.xml"
|
||||||
)
|
)
|
||||||
config_ignore: Set[str] = {schedule_name}
|
config_ignore: set[str] = {schedule_name}
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def load(cls, emane_prefix: Path) -> None:
|
def load(cls, emane_prefix: Path) -> None:
|
||||||
|
|
|
@ -6,7 +6,7 @@ share the same MAC+PHY model.
|
||||||
import logging
|
import logging
|
||||||
import time
|
import time
|
||||||
from dataclasses import dataclass
|
from dataclasses import dataclass
|
||||||
from typing import TYPE_CHECKING, Callable, Dict, List, Optional, Type, Union
|
from typing import TYPE_CHECKING, Callable, Optional, Union
|
||||||
|
|
||||||
from core.emulator.data import InterfaceData, LinkData, LinkOptions
|
from core.emulator.data import InterfaceData, LinkData, LinkOptions
|
||||||
from core.emulator.distributed import DistributedServer
|
from core.emulator.distributed import DistributedServer
|
||||||
|
@ -196,7 +196,7 @@ class EmaneNet(CoreNetworkBase):
|
||||||
def unlink(self, iface1: CoreInterface, iface2: CoreInterface) -> None:
|
def unlink(self, iface1: CoreInterface, iface2: CoreInterface) -> None:
|
||||||
pass
|
pass
|
||||||
|
|
||||||
def updatemodel(self, config: Dict[str, str]) -> None:
|
def updatemodel(self, config: dict[str, str]) -> None:
|
||||||
"""
|
"""
|
||||||
Update configuration for the current model.
|
Update configuration for the current model.
|
||||||
|
|
||||||
|
@ -212,8 +212,8 @@ class EmaneNet(CoreNetworkBase):
|
||||||
|
|
||||||
def setmodel(
|
def setmodel(
|
||||||
self,
|
self,
|
||||||
model: Union[Type["EmaneModel"], Type["WayPointMobility"]],
|
model: Union[type["EmaneModel"], type["WayPointMobility"]],
|
||||||
config: Dict[str, str],
|
config: dict[str, str],
|
||||||
) -> None:
|
) -> None:
|
||||||
"""
|
"""
|
||||||
set the EmaneModel associated with this node
|
set the EmaneModel associated with this node
|
||||||
|
@ -225,7 +225,7 @@ class EmaneNet(CoreNetworkBase):
|
||||||
self.mobility = model(session=self.session, _id=self.id)
|
self.mobility = model(session=self.session, _id=self.id)
|
||||||
self.mobility.update_config(config)
|
self.mobility.update_config(config)
|
||||||
|
|
||||||
def links(self, flags: MessageFlags = MessageFlags.NONE) -> List[LinkData]:
|
def links(self, flags: MessageFlags = MessageFlags.NONE) -> list[LinkData]:
|
||||||
links = []
|
links = []
|
||||||
emane_manager = self.session.emane
|
emane_manager = self.session.emane
|
||||||
# gather current emane links
|
# gather current emane links
|
||||||
|
|
Loading…
Reference in a new issue