added type hinting to core.emane functions
This commit is contained in:
parent
49f09a25cc
commit
fa095431fb
9 changed files with 147 additions and 108 deletions
|
@ -1,6 +1,8 @@
|
|||
"""
|
||||
EMANE Bypass model for CORE
|
||||
"""
|
||||
from typing import List
|
||||
|
||||
from core.config import ConfigGroup, Configuration
|
||||
from core.emane import emanemodel
|
||||
from core.emulator.enumerations import ConfigDataTypes
|
||||
|
@ -29,11 +31,11 @@ class EmaneBypassModel(emanemodel.EmaneModel):
|
|||
phy_config = []
|
||||
|
||||
@classmethod
|
||||
def load(cls, emane_prefix):
|
||||
def load(cls, emane_prefix: str) -> None:
|
||||
# ignore default logic
|
||||
pass
|
||||
|
||||
# override config groups
|
||||
@classmethod
|
||||
def config_groups(cls):
|
||||
def config_groups(cls) -> List[ConfigGroup]:
|
||||
return [ConfigGroup("Bypass Parameters", 1, 1)]
|
||||
|
|
|
@ -4,11 +4,13 @@ commeffect.py: EMANE CommEffect model for CORE
|
|||
|
||||
import logging
|
||||
import os
|
||||
from typing import Dict, List
|
||||
|
||||
from lxml import etree
|
||||
|
||||
from core.config import ConfigGroup
|
||||
from core.config import ConfigGroup, Configuration
|
||||
from core.emane import emanemanifest, emanemodel
|
||||
from core.nodes.interface import CoreInterface
|
||||
from core.xml import emanexml
|
||||
|
||||
try:
|
||||
|
@ -20,7 +22,7 @@ except ImportError:
|
|||
logging.debug("compatible emane python bindings not installed")
|
||||
|
||||
|
||||
def convert_none(x):
|
||||
def convert_none(x: float) -> int:
|
||||
"""
|
||||
Helper to use 0 for None values.
|
||||
"""
|
||||
|
@ -45,19 +47,21 @@ class EmaneCommEffectModel(emanemodel.EmaneModel):
|
|||
external_config = []
|
||||
|
||||
@classmethod
|
||||
def load(cls, emane_prefix):
|
||||
def load(cls, emane_prefix: str) -> None:
|
||||
shim_xml_path = os.path.join(emane_prefix, "share/emane/manifest", cls.shim_xml)
|
||||
cls.config_shim = emanemanifest.parse(shim_xml_path, cls.shim_defaults)
|
||||
|
||||
@classmethod
|
||||
def configurations(cls):
|
||||
def configurations(cls) -> List[Configuration]:
|
||||
return cls.config_shim
|
||||
|
||||
@classmethod
|
||||
def config_groups(cls):
|
||||
def config_groups(cls) -> List[ConfigGroup]:
|
||||
return [ConfigGroup("CommEffect SHIM Parameters", 1, len(cls.configurations()))]
|
||||
|
||||
def build_xml_files(self, config, interface=None):
|
||||
def build_xml_files(
|
||||
self, config: Dict[str, str], interface: CoreInterface = None
|
||||
) -> None:
|
||||
"""
|
||||
Build the necessary nem and commeffect XMLs in the given path.
|
||||
If an individual NEM has a nonstandard config, we need to build
|
||||
|
@ -109,14 +113,14 @@ class EmaneCommEffectModel(emanemodel.EmaneModel):
|
|||
|
||||
def linkconfig(
|
||||
self,
|
||||
netif,
|
||||
bw=None,
|
||||
delay=None,
|
||||
loss=None,
|
||||
duplicate=None,
|
||||
jitter=None,
|
||||
netif2=None,
|
||||
):
|
||||
netif: CoreInterface,
|
||||
bw: float = None,
|
||||
delay: float = None,
|
||||
loss: float = None,
|
||||
duplicate: float = None,
|
||||
jitter: float = None,
|
||||
netif2: CoreInterface = None,
|
||||
) -> None:
|
||||
"""
|
||||
Generate CommEffect events when a Link Message is received having
|
||||
link parameters.
|
||||
|
|
|
@ -6,6 +6,7 @@ import logging
|
|||
import os
|
||||
import threading
|
||||
from collections import OrderedDict
|
||||
from typing import TYPE_CHECKING, Dict, List, Set, Tuple, Type
|
||||
|
||||
from core import utils
|
||||
from core.config import ConfigGroup, Configuration, ModelManager
|
||||
|
@ -19,8 +20,15 @@ from core.emane.rfpipe import EmaneRfPipeModel
|
|||
from core.emane.tdma import EmaneTdmaModel
|
||||
from core.emulator.enumerations import ConfigDataTypes, RegisterTlvs
|
||||
from core.errors import CoreCommandError, CoreError
|
||||
from core.nodes.base import CoreNode
|
||||
from core.nodes.interface import CoreInterface
|
||||
from core.nodes.network import CtrlNet
|
||||
from core.xml import emanexml
|
||||
|
||||
if TYPE_CHECKING:
|
||||
from core.emulator.session import Session
|
||||
|
||||
|
||||
try:
|
||||
from emane.events import EventService
|
||||
from emane.events import LocationEvent
|
||||
|
@ -57,7 +65,7 @@ class EmaneManager(ModelManager):
|
|||
EVENTCFGVAR = "LIBEMANEEVENTSERVICECONFIG"
|
||||
DEFAULT_LOG_LEVEL = 3
|
||||
|
||||
def __init__(self, session):
|
||||
def __init__(self, session: "Session") -> None:
|
||||
"""
|
||||
Creates a Emane instance.
|
||||
|
||||
|
@ -86,7 +94,9 @@ class EmaneManager(ModelManager):
|
|||
self.event_device = None
|
||||
self.emane_check()
|
||||
|
||||
def getifcconfig(self, node_id, interface, model_name):
|
||||
def getifcconfig(
|
||||
self, node_id: int, interface: CoreInterface, model_name: str
|
||||
) -> Dict[str, str]:
|
||||
"""
|
||||
Retrieve interface configuration or node configuration if not provided.
|
||||
|
||||
|
@ -129,11 +139,11 @@ class EmaneManager(ModelManager):
|
|||
|
||||
return config
|
||||
|
||||
def config_reset(self, node_id=None):
|
||||
def config_reset(self, node_id: int = None) -> None:
|
||||
super().config_reset(node_id)
|
||||
self.set_configs(self.emane_config.default_values())
|
||||
|
||||
def emane_check(self):
|
||||
def emane_check(self) -> None:
|
||||
"""
|
||||
Check if emane is installed and load models.
|
||||
|
||||
|
@ -157,7 +167,7 @@ class EmaneManager(ModelManager):
|
|||
except CoreCommandError:
|
||||
logging.info("emane is not installed")
|
||||
|
||||
def deleteeventservice(self):
|
||||
def deleteeventservice(self) -> None:
|
||||
if self.service:
|
||||
for fd in self.service._readFd, self.service._writeFd:
|
||||
if fd >= 0:
|
||||
|
@ -168,7 +178,7 @@ class EmaneManager(ModelManager):
|
|||
self.service = None
|
||||
self.event_device = None
|
||||
|
||||
def initeventservice(self, filename=None, shutdown=False):
|
||||
def initeventservice(self, filename: str = None, shutdown: bool = False) -> None:
|
||||
"""
|
||||
Re-initialize the EMANE Event service.
|
||||
The multicast group and/or port may be configured.
|
||||
|
@ -186,7 +196,7 @@ class EmaneManager(ModelManager):
|
|||
logging.error(
|
||||
"invalid emane event service device provided: %s", self.event_device
|
||||
)
|
||||
return False
|
||||
return
|
||||
|
||||
# make sure the event control network is in place
|
||||
eventnet = self.session.add_remove_control_net(
|
||||
|
@ -205,9 +215,7 @@ class EmaneManager(ModelManager):
|
|||
except EventServiceException:
|
||||
logging.exception("error instantiating emane EventService")
|
||||
|
||||
return True
|
||||
|
||||
def load_models(self, emane_models):
|
||||
def load_models(self, emane_models: List[Type[EmaneModel]]) -> None:
|
||||
"""
|
||||
Load EMANE models and make them available.
|
||||
"""
|
||||
|
@ -219,7 +227,7 @@ class EmaneManager(ModelManager):
|
|||
emane_model.load(emane_prefix)
|
||||
self.models[emane_model.name] = emane_model
|
||||
|
||||
def add_node(self, emane_net):
|
||||
def add_node(self, emane_net: EmaneNet) -> None:
|
||||
"""
|
||||
Add EMANE network object to this manager.
|
||||
|
||||
|
@ -233,7 +241,7 @@ class EmaneManager(ModelManager):
|
|||
)
|
||||
self._emane_nets[emane_net.id] = emane_net
|
||||
|
||||
def getnodes(self):
|
||||
def getnodes(self) -> Set[CoreNode]:
|
||||
"""
|
||||
Return a set of CoreNodes that are linked to an EMANE network,
|
||||
e.g. containers having one or more radio interfaces.
|
||||
|
@ -245,7 +253,7 @@ class EmaneManager(ModelManager):
|
|||
nodes.add(netif.node)
|
||||
return nodes
|
||||
|
||||
def setup(self):
|
||||
def setup(self) -> int:
|
||||
"""
|
||||
Setup duties for EMANE manager.
|
||||
|
||||
|
@ -303,7 +311,7 @@ class EmaneManager(ModelManager):
|
|||
self.check_node_models()
|
||||
return EmaneManager.SUCCESS
|
||||
|
||||
def startup(self):
|
||||
def startup(self) -> int:
|
||||
"""
|
||||
After all the EMANE networks have been added, build XML files
|
||||
and start the daemons.
|
||||
|
@ -347,7 +355,7 @@ class EmaneManager(ModelManager):
|
|||
|
||||
return EmaneManager.SUCCESS
|
||||
|
||||
def poststartup(self):
|
||||
def poststartup(self) -> None:
|
||||
"""
|
||||
Retransmit location events now that all NEMs are active.
|
||||
"""
|
||||
|
@ -367,7 +375,7 @@ class EmaneManager(ModelManager):
|
|||
x, y, z = netif.node.position.get()
|
||||
emane_node.setnemposition(netif, x, y, z)
|
||||
|
||||
def reset(self):
|
||||
def reset(self) -> None:
|
||||
"""
|
||||
Remove all EMANE networks from the dictionary, reset port numbers and
|
||||
nem id counters
|
||||
|
@ -382,7 +390,7 @@ class EmaneManager(ModelManager):
|
|||
"emane_transform_port", 8200
|
||||
)
|
||||
|
||||
def shutdown(self):
|
||||
def shutdown(self) -> None:
|
||||
"""
|
||||
stop all EMANE daemons
|
||||
"""
|
||||
|
@ -394,7 +402,7 @@ class EmaneManager(ModelManager):
|
|||
self.stopdaemons()
|
||||
self.stopeventmonitor()
|
||||
|
||||
def buildxml(self):
|
||||
def buildxml(self) -> None:
|
||||
"""
|
||||
Build XML files required to run EMANE on each node.
|
||||
NEMs run inside containers using the control network for passing
|
||||
|
@ -410,7 +418,7 @@ class EmaneManager(ModelManager):
|
|||
self.buildnemxml()
|
||||
self.buildeventservicexml()
|
||||
|
||||
def check_node_models(self):
|
||||
def check_node_models(self) -> None:
|
||||
"""
|
||||
Associate EMANE model classes with EMANE network nodes.
|
||||
"""
|
||||
|
@ -438,7 +446,7 @@ class EmaneManager(ModelManager):
|
|||
model_class = self.models[model_name]
|
||||
emane_node.setmodel(model_class, config)
|
||||
|
||||
def nemlookup(self, nemid):
|
||||
def nemlookup(self, nemid) -> Tuple[EmaneNet, CoreInterface]:
|
||||
"""
|
||||
Look for the given numerical NEM ID and return the first matching
|
||||
EMANE network and NEM interface.
|
||||
|
@ -456,7 +464,7 @@ class EmaneManager(ModelManager):
|
|||
|
||||
return emane_node, netif
|
||||
|
||||
def numnems(self):
|
||||
def numnems(self) -> int:
|
||||
"""
|
||||
Return the number of NEMs emulated locally.
|
||||
"""
|
||||
|
@ -466,7 +474,7 @@ class EmaneManager(ModelManager):
|
|||
count += len(emane_node.netifs())
|
||||
return count
|
||||
|
||||
def buildplatformxml(self, ctrlnet):
|
||||
def buildplatformxml(self, ctrlnet: CtrlNet) -> None:
|
||||
"""
|
||||
Build a platform.xml file now that all nodes are configured.
|
||||
"""
|
||||
|
@ -480,7 +488,7 @@ class EmaneManager(ModelManager):
|
|||
self, ctrlnet, emane_node, nemid, platform_xmls
|
||||
)
|
||||
|
||||
def buildnemxml(self):
|
||||
def buildnemxml(self) -> None:
|
||||
"""
|
||||
Builds the nem, mac, and phy xml files for each EMANE network.
|
||||
"""
|
||||
|
@ -488,7 +496,7 @@ class EmaneManager(ModelManager):
|
|||
emane_net = self._emane_nets[key]
|
||||
emanexml.build_xml_files(self, emane_net)
|
||||
|
||||
def buildeventservicexml(self):
|
||||
def buildeventservicexml(self) -> None:
|
||||
"""
|
||||
Build the libemaneeventservice.xml file if event service options
|
||||
were changed in the global config.
|
||||
|
@ -520,7 +528,7 @@ class EmaneManager(ModelManager):
|
|||
)
|
||||
)
|
||||
|
||||
def startdaemons(self):
|
||||
def startdaemons(self) -> None:
|
||||
"""
|
||||
Start one EMANE daemon per node having a radio.
|
||||
Add a control network even if the user has not configured one.
|
||||
|
@ -596,7 +604,7 @@ class EmaneManager(ModelManager):
|
|||
self.session.distributed.execute(lambda x: x.remote_cmd(emanecmd, cwd=path))
|
||||
logging.info("host emane daemon running: %s", emanecmd)
|
||||
|
||||
def stopdaemons(self):
|
||||
def stopdaemons(self) -> None:
|
||||
"""
|
||||
Kill the appropriate EMANE daemons.
|
||||
"""
|
||||
|
@ -623,7 +631,7 @@ class EmaneManager(ModelManager):
|
|||
except CoreCommandError:
|
||||
logging.exception("error shutting down emane daemons")
|
||||
|
||||
def installnetifs(self):
|
||||
def installnetifs(self) -> None:
|
||||
"""
|
||||
Install TUN/TAP virtual interfaces into their proper namespaces
|
||||
now that the EMANE daemons are running.
|
||||
|
@ -633,7 +641,7 @@ class EmaneManager(ModelManager):
|
|||
logging.info("emane install netifs for node: %d", key)
|
||||
emane_node.installnetifs()
|
||||
|
||||
def deinstallnetifs(self):
|
||||
def deinstallnetifs(self) -> None:
|
||||
"""
|
||||
Uninstall TUN/TAP virtual interfaces.
|
||||
"""
|
||||
|
@ -641,7 +649,7 @@ class EmaneManager(ModelManager):
|
|||
emane_node = self._emane_nets[key]
|
||||
emane_node.deinstallnetifs()
|
||||
|
||||
def doeventmonitor(self):
|
||||
def doeventmonitor(self) -> bool:
|
||||
"""
|
||||
Returns boolean whether or not EMANE events will be monitored.
|
||||
"""
|
||||
|
@ -649,7 +657,7 @@ class EmaneManager(ModelManager):
|
|||
# generate the EMANE events when nodes are moved
|
||||
return self.session.options.get_config_bool("emane_event_monitor")
|
||||
|
||||
def genlocationevents(self):
|
||||
def genlocationevents(self) -> bool:
|
||||
"""
|
||||
Returns boolean whether or not EMANE events will be generated.
|
||||
"""
|
||||
|
@ -660,7 +668,7 @@ class EmaneManager(ModelManager):
|
|||
tmp = not self.doeventmonitor()
|
||||
return tmp
|
||||
|
||||
def starteventmonitor(self):
|
||||
def starteventmonitor(self) -> None:
|
||||
"""
|
||||
Start monitoring EMANE location events if configured to do so.
|
||||
"""
|
||||
|
@ -681,7 +689,7 @@ class EmaneManager(ModelManager):
|
|||
self.eventmonthread.daemon = True
|
||||
self.eventmonthread.start()
|
||||
|
||||
def stopeventmonitor(self):
|
||||
def stopeventmonitor(self) -> None:
|
||||
"""
|
||||
Stop monitoring EMANE location events.
|
||||
"""
|
||||
|
@ -697,7 +705,7 @@ class EmaneManager(ModelManager):
|
|||
self.eventmonthread.join()
|
||||
self.eventmonthread = None
|
||||
|
||||
def eventmonitorloop(self):
|
||||
def eventmonitorloop(self) -> None:
|
||||
"""
|
||||
Thread target that monitors EMANE location events.
|
||||
"""
|
||||
|
@ -724,7 +732,7 @@ class EmaneManager(ModelManager):
|
|||
threading.currentThread().getName(),
|
||||
)
|
||||
|
||||
def handlelocationevent(self, rxnemid, eid, data):
|
||||
def handlelocationevent(self, rxnemid: int, eid: int, data: str) -> None:
|
||||
"""
|
||||
Handle an EMANE location event.
|
||||
"""
|
||||
|
@ -747,7 +755,9 @@ class EmaneManager(ModelManager):
|
|||
logging.debug("emane location event: %s,%s,%s", lat, lon, alt)
|
||||
self.handlelocationeventtoxyz(txnemid, lat, lon, alt)
|
||||
|
||||
def handlelocationeventtoxyz(self, nemid, lat, lon, alt):
|
||||
def handlelocationeventtoxyz(
|
||||
self, nemid: int, lat: float, lon: float, alt: float
|
||||
) -> bool:
|
||||
"""
|
||||
Convert the (NEM ID, lat, long, alt) from a received location event
|
||||
into a node and x,y,z coordinate values, sending a Node Message.
|
||||
|
@ -800,11 +810,11 @@ class EmaneManager(ModelManager):
|
|||
|
||||
# don"t use node.setposition(x,y,z) which generates an event
|
||||
node.position.set(x, y, z)
|
||||
node_data = node.data(message_type=0, lat=str(lat), lon=str(lon), alt=str(alt))
|
||||
node_data = node.data(message_type=0, lat=lat, lon=lon, alt=alt)
|
||||
self.session.broadcast_node(node_data)
|
||||
return True
|
||||
|
||||
def emanerunning(self, node):
|
||||
def emanerunning(self, node: CoreNode) -> bool:
|
||||
"""
|
||||
Return True if an EMANE process associated with the given node is running,
|
||||
False otherwise.
|
||||
|
@ -827,7 +837,7 @@ class EmaneGlobalModel:
|
|||
name = "emane"
|
||||
bitmap = None
|
||||
|
||||
def __init__(self, session):
|
||||
def __init__(self, session: "Session") -> None:
|
||||
self.session = session
|
||||
self.nem_config = [
|
||||
Configuration(
|
||||
|
@ -840,7 +850,7 @@ class EmaneGlobalModel:
|
|||
self.emulator_config = None
|
||||
self.parse_config()
|
||||
|
||||
def parse_config(self):
|
||||
def parse_config(self) -> None:
|
||||
emane_prefix = self.session.options.get_config(
|
||||
"emane_prefix", default=DEFAULT_EMANE_PREFIX
|
||||
)
|
||||
|
@ -862,10 +872,10 @@ class EmaneGlobalModel:
|
|||
),
|
||||
)
|
||||
|
||||
def configurations(self):
|
||||
def configurations(self) -> List[Configuration]:
|
||||
return self.emulator_config + self.nem_config
|
||||
|
||||
def config_groups(self):
|
||||
def config_groups(self) -> List[ConfigGroup]:
|
||||
emulator_len = len(self.emulator_config)
|
||||
config_len = len(self.configurations())
|
||||
return [
|
||||
|
@ -873,7 +883,7 @@ class EmaneGlobalModel:
|
|||
ConfigGroup("NEM Parameters", emulator_len + 1, config_len),
|
||||
]
|
||||
|
||||
def default_values(self):
|
||||
def default_values(self) -> Dict[str, str]:
|
||||
return OrderedDict(
|
||||
[(config.id, config.default) for config in self.configurations()]
|
||||
)
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
import logging
|
||||
from typing import Dict, List
|
||||
|
||||
from core.config import Configuration
|
||||
from core.emulator.enumerations import ConfigDataTypes
|
||||
|
@ -13,12 +14,12 @@ except ImportError:
|
|||
logging.debug("compatible emane python bindings not installed")
|
||||
|
||||
|
||||
def _type_value(config_type):
|
||||
def _type_value(config_type: str) -> ConfigDataTypes:
|
||||
"""
|
||||
Convert emane configuration type to core configuration value.
|
||||
|
||||
:param str config_type: emane configuration type
|
||||
:return:
|
||||
:return: core config type
|
||||
"""
|
||||
config_type = config_type.upper()
|
||||
if config_type == "DOUBLE":
|
||||
|
@ -28,7 +29,7 @@ def _type_value(config_type):
|
|||
return ConfigDataTypes[config_type]
|
||||
|
||||
|
||||
def _get_possible(config_type, config_regex):
|
||||
def _get_possible(config_type: str, config_regex: str) -> List[str]:
|
||||
"""
|
||||
Retrieve possible config value options based on emane regexes.
|
||||
|
||||
|
@ -47,7 +48,7 @@ def _get_possible(config_type, config_regex):
|
|||
return []
|
||||
|
||||
|
||||
def _get_default(config_type_name, config_value):
|
||||
def _get_default(config_type_name: str, config_value: List[str]) -> str:
|
||||
"""
|
||||
Convert default configuration values to one used by core.
|
||||
|
||||
|
@ -72,7 +73,7 @@ def _get_default(config_type_name, config_value):
|
|||
return config_default
|
||||
|
||||
|
||||
def parse(manifest_path, defaults):
|
||||
def parse(manifest_path: str, defaults: Dict[str, str]) -> List[Configuration]:
|
||||
"""
|
||||
Parses a valid emane manifest file and converts the provided configuration values into ones used by core.
|
||||
|
||||
|
|
|
@ -3,12 +3,14 @@ Defines Emane Models used within CORE.
|
|||
"""
|
||||
import logging
|
||||
import os
|
||||
from typing import Dict, List
|
||||
|
||||
from core.config import ConfigGroup, Configuration
|
||||
from core.emane import emanemanifest
|
||||
from core.emulator.enumerations import ConfigDataTypes
|
||||
from core.errors import CoreError
|
||||
from core.location.mobility import WirelessModel
|
||||
from core.nodes.interface import CoreInterface
|
||||
from core.xml import emanexml
|
||||
|
||||
|
||||
|
@ -45,7 +47,7 @@ class EmaneModel(WirelessModel):
|
|||
config_ignore = set()
|
||||
|
||||
@classmethod
|
||||
def load(cls, emane_prefix):
|
||||
def load(cls, emane_prefix: str) -> None:
|
||||
"""
|
||||
Called after being loaded within the EmaneManager. Provides configured emane_prefix for
|
||||
parsing xml files.
|
||||
|
@ -63,7 +65,7 @@ class EmaneModel(WirelessModel):
|
|||
cls.phy_config = emanemanifest.parse(phy_xml_path, cls.phy_defaults)
|
||||
|
||||
@classmethod
|
||||
def configurations(cls):
|
||||
def configurations(cls) -> List[Configuration]:
|
||||
"""
|
||||
Returns the combination all all configurations (mac, phy, and external).
|
||||
|
||||
|
@ -73,7 +75,7 @@ class EmaneModel(WirelessModel):
|
|||
return cls.mac_config + cls.phy_config + cls.external_config
|
||||
|
||||
@classmethod
|
||||
def config_groups(cls):
|
||||
def config_groups(cls) -> List[ConfigGroup]:
|
||||
"""
|
||||
Returns the defined configuration groups.
|
||||
|
||||
|
@ -89,10 +91,12 @@ class EmaneModel(WirelessModel):
|
|||
ConfigGroup("External Parameters", phy_len + 1, config_len),
|
||||
]
|
||||
|
||||
def build_xml_files(self, config, interface=None):
|
||||
def build_xml_files(
|
||||
self, config: Dict[str, str], interface: CoreInterface = None
|
||||
) -> None:
|
||||
"""
|
||||
Builds xml files for this emane model. Creates a nem.xml file that points to both mac.xml and phy.xml
|
||||
definitions.
|
||||
Builds xml files for this emane model. Creates a nem.xml file that points to
|
||||
both mac.xml and phy.xml definitions.
|
||||
|
||||
:param dict config: emane model configuration for the node and interface
|
||||
:param interface: interface for the emane node
|
||||
|
@ -127,7 +131,7 @@ class EmaneModel(WirelessModel):
|
|||
phy_file = os.path.join(self.session.session_dir, phy_name)
|
||||
emanexml.create_phy_xml(self, config, phy_file, server)
|
||||
|
||||
def post_startup(self):
|
||||
def post_startup(self) -> None:
|
||||
"""
|
||||
Logic to execute after the emane manager is finished with startup.
|
||||
|
||||
|
@ -135,7 +139,7 @@ class EmaneModel(WirelessModel):
|
|||
"""
|
||||
logging.debug("emane model(%s) has no post setup tasks", self.name)
|
||||
|
||||
def update(self, moved, moved_netifs):
|
||||
def update(self, moved: bool, moved_netifs: List[CoreInterface]) -> None:
|
||||
"""
|
||||
Invoked from MobilityModel when nodes are moved; this causes
|
||||
emane location events to be generated for the nodes in the moved
|
||||
|
@ -143,7 +147,7 @@ class EmaneModel(WirelessModel):
|
|||
|
||||
:param bool moved: were nodes moved
|
||||
:param list moved_netifs: interfaces that were moved
|
||||
:return:
|
||||
:return: nothing
|
||||
"""
|
||||
try:
|
||||
wlan = self.session.get_node(self.id)
|
||||
|
@ -153,14 +157,14 @@ class EmaneModel(WirelessModel):
|
|||
|
||||
def linkconfig(
|
||||
self,
|
||||
netif,
|
||||
bw=None,
|
||||
delay=None,
|
||||
loss=None,
|
||||
duplicate=None,
|
||||
jitter=None,
|
||||
netif2=None,
|
||||
):
|
||||
netif: CoreInterface,
|
||||
bw: float = None,
|
||||
delay: float = None,
|
||||
loss: float = None,
|
||||
duplicate: float = None,
|
||||
jitter: float = None,
|
||||
netif2: CoreInterface = None,
|
||||
) -> None:
|
||||
"""
|
||||
Invoked when a Link Message is received. Default is unimplemented.
|
||||
|
||||
|
|
|
@ -15,7 +15,7 @@ class EmaneIeee80211abgModel(emanemodel.EmaneModel):
|
|||
mac_xml = "ieee80211abgmaclayer.xml"
|
||||
|
||||
@classmethod
|
||||
def load(cls, emane_prefix):
|
||||
def load(cls, emane_prefix: str) -> None:
|
||||
cls.mac_defaults["pcrcurveuri"] = os.path.join(
|
||||
emane_prefix, "share/emane/xml/models/mac/ieee80211abg/ieee80211pcr.xml"
|
||||
)
|
||||
|
|
|
@ -4,9 +4,18 @@ share the same MAC+PHY model.
|
|||
"""
|
||||
|
||||
import logging
|
||||
from typing import TYPE_CHECKING, Dict, List, Optional, Type
|
||||
|
||||
from core.emulator.distributed import DistributedServer
|
||||
from core.emulator.enumerations import LinkTypes, NodeTypes, RegisterTlvs
|
||||
from core.nodes.base import CoreNetworkBase
|
||||
from core.nodes.interface import CoreInterface
|
||||
|
||||
if TYPE_CHECKING:
|
||||
from core.emulator.session import Session
|
||||
from core.location.mobility import WirelessModel
|
||||
|
||||
WirelessModelType = Type[WirelessModel]
|
||||
|
||||
try:
|
||||
from emane.events import LocationEvent
|
||||
|
@ -29,7 +38,14 @@ class EmaneNet(CoreNetworkBase):
|
|||
type = "wlan"
|
||||
is_emane = True
|
||||
|
||||
def __init__(self, session, _id=None, name=None, start=True, server=None):
|
||||
def __init__(
|
||||
self,
|
||||
session: "Session",
|
||||
_id: int = None,
|
||||
name: str = None,
|
||||
start: bool = True,
|
||||
server: DistributedServer = None,
|
||||
) -> None:
|
||||
super().__init__(session, _id, name, start, server)
|
||||
self.conf = ""
|
||||
self.up = False
|
||||
|
@ -39,20 +55,20 @@ class EmaneNet(CoreNetworkBase):
|
|||
|
||||
def linkconfig(
|
||||
self,
|
||||
netif,
|
||||
bw=None,
|
||||
delay=None,
|
||||
loss=None,
|
||||
duplicate=None,
|
||||
jitter=None,
|
||||
netif2=None,
|
||||
):
|
||||
netif: CoreInterface,
|
||||
bw: float = None,
|
||||
delay: float = None,
|
||||
loss: float = None,
|
||||
duplicate: float = None,
|
||||
jitter: float = None,
|
||||
netif2: CoreInterface = None,
|
||||
) -> None:
|
||||
"""
|
||||
The CommEffect model supports link configuration.
|
||||
"""
|
||||
if not self.model:
|
||||
return
|
||||
return self.model.linkconfig(
|
||||
self.model.linkconfig(
|
||||
netif=netif,
|
||||
bw=bw,
|
||||
delay=delay,
|
||||
|
@ -62,19 +78,19 @@ class EmaneNet(CoreNetworkBase):
|
|||
netif2=netif2,
|
||||
)
|
||||
|
||||
def config(self, conf):
|
||||
def config(self, conf: str) -> None:
|
||||
self.conf = conf
|
||||
|
||||
def shutdown(self):
|
||||
def shutdown(self) -> None:
|
||||
pass
|
||||
|
||||
def link(self, netif1, netif2):
|
||||
def link(self, netif1: CoreInterface, netif2: CoreInterface) -> None:
|
||||
pass
|
||||
|
||||
def unlink(self, netif1, netif2):
|
||||
def unlink(self, netif1: CoreInterface, netif2: CoreInterface) -> None:
|
||||
pass
|
||||
|
||||
def updatemodel(self, config):
|
||||
def updatemodel(self, config: Dict[str, str]) -> None:
|
||||
if not self.model:
|
||||
raise ValueError("no model set to update for node(%s)", self.id)
|
||||
logging.info(
|
||||
|
@ -82,7 +98,7 @@ class EmaneNet(CoreNetworkBase):
|
|||
)
|
||||
self.model.set_configs(config, node_id=self.id)
|
||||
|
||||
def setmodel(self, model, config):
|
||||
def setmodel(self, model: "WirelessModelType", config: Dict[str, str]) -> None:
|
||||
"""
|
||||
set the EmaneModel associated with this node
|
||||
"""
|
||||
|
@ -96,14 +112,14 @@ class EmaneNet(CoreNetworkBase):
|
|||
self.mobility = model(session=self.session, _id=self.id)
|
||||
self.mobility.update_config(config)
|
||||
|
||||
def setnemid(self, netif, nemid):
|
||||
def setnemid(self, netif: CoreInterface, nemid: int) -> None:
|
||||
"""
|
||||
Record an interface to numerical ID mapping. The Emane controller
|
||||
object manages and assigns these IDs for all NEMs.
|
||||
"""
|
||||
self.nemidmap[netif] = nemid
|
||||
|
||||
def getnemid(self, netif):
|
||||
def getnemid(self, netif: CoreInterface) -> Optional[int]:
|
||||
"""
|
||||
Given an interface, return its numerical ID.
|
||||
"""
|
||||
|
@ -112,7 +128,7 @@ class EmaneNet(CoreNetworkBase):
|
|||
else:
|
||||
return self.nemidmap[netif]
|
||||
|
||||
def getnemnetif(self, nemid):
|
||||
def getnemnetif(self, nemid: int) -> Optional[CoreInterface]:
|
||||
"""
|
||||
Given a numerical NEM ID, return its interface. This returns the
|
||||
first interface that matches the given NEM ID.
|
||||
|
@ -122,13 +138,13 @@ class EmaneNet(CoreNetworkBase):
|
|||
return netif
|
||||
return None
|
||||
|
||||
def netifs(self, sort=True):
|
||||
def netifs(self, sort: bool = True) -> List[CoreInterface]:
|
||||
"""
|
||||
Retrieve list of linked interfaces sorted by node number.
|
||||
"""
|
||||
return sorted(self._netif.values(), key=lambda ifc: ifc.node.id)
|
||||
|
||||
def installnetifs(self):
|
||||
def installnetifs(self) -> None:
|
||||
"""
|
||||
Install TAP devices into their namespaces. This is done after
|
||||
EMANE daemons have been started, because that is their only chance
|
||||
|
@ -159,7 +175,7 @@ class EmaneNet(CoreNetworkBase):
|
|||
x, y, z = netif.node.position.get()
|
||||
self.setnemposition(netif, x, y, z)
|
||||
|
||||
def deinstallnetifs(self):
|
||||
def deinstallnetifs(self) -> None:
|
||||
"""
|
||||
Uninstall TAP devices. This invokes their shutdown method for
|
||||
any required cleanup; the device may be actually removed when
|
||||
|
@ -170,7 +186,9 @@ class EmaneNet(CoreNetworkBase):
|
|||
netif.shutdown()
|
||||
netif.poshook = None
|
||||
|
||||
def setnemposition(self, netif, x, y, z):
|
||||
def setnemposition(
|
||||
self, netif: CoreInterface, x: float, y: float, z: float
|
||||
) -> None:
|
||||
"""
|
||||
Publish a NEM location change event using the EMANE event service.
|
||||
"""
|
||||
|
@ -191,7 +209,7 @@ class EmaneNet(CoreNetworkBase):
|
|||
event.append(nemid, latitude=lat, longitude=lon, altitude=alt)
|
||||
self.session.emane.service.publish(0, event)
|
||||
|
||||
def setnempositions(self, moved_netifs):
|
||||
def setnempositions(self, moved_netifs: List[CoreInterface]) -> None:
|
||||
"""
|
||||
Several NEMs have moved, from e.g. a WaypointMobilityModel
|
||||
calculation. Generate an EMANE Location Event having several
|
||||
|
|
|
@ -15,7 +15,7 @@ class EmaneRfPipeModel(emanemodel.EmaneModel):
|
|||
mac_xml = "rfpipemaclayer.xml"
|
||||
|
||||
@classmethod
|
||||
def load(cls, emane_prefix):
|
||||
def load(cls, emane_prefix: str) -> None:
|
||||
cls.mac_defaults["pcrcurveuri"] = os.path.join(
|
||||
emane_prefix, "share/emane/xml/models/mac/rfpipe/rfpipepcr.xml"
|
||||
)
|
||||
|
|
|
@ -27,7 +27,7 @@ class EmaneTdmaModel(emanemodel.EmaneModel):
|
|||
config_ignore = {schedule_name}
|
||||
|
||||
@classmethod
|
||||
def load(cls, emane_prefix):
|
||||
def load(cls, emane_prefix: str) -> None:
|
||||
cls.mac_defaults["pcrcurveuri"] = os.path.join(
|
||||
emane_prefix,
|
||||
"share/emane/xml/models/mac/tdmaeventscheduler/tdmabasemodelpcr.xml",
|
||||
|
@ -43,7 +43,7 @@ class EmaneTdmaModel(emanemodel.EmaneModel):
|
|||
),
|
||||
)
|
||||
|
||||
def post_startup(self):
|
||||
def post_startup(self) -> None:
|
||||
"""
|
||||
Logic to execute after the emane manager is finished with startup.
|
||||
|
||||
|
|
Loading…
Reference in a new issue