daemon: added class variable type hinting to core.emane
This commit is contained in:
parent
ef3cf5697d
commit
6201875b78
11 changed files with 116 additions and 100 deletions
|
@ -1,6 +1,7 @@
|
|||
"""
|
||||
EMANE Bypass model for CORE
|
||||
"""
|
||||
from typing import List, Set
|
||||
|
||||
from core.config import Configuration
|
||||
from core.emane import emanemodel
|
||||
|
@ -8,14 +9,14 @@ from core.emulator.enumerations import ConfigDataTypes
|
|||
|
||||
|
||||
class EmaneBypassModel(emanemodel.EmaneModel):
|
||||
name = "emane_bypass"
|
||||
name: str = "emane_bypass"
|
||||
|
||||
# values to ignore, when writing xml files
|
||||
config_ignore = {"none"}
|
||||
config_ignore: Set[str] = {"none"}
|
||||
|
||||
# mac definitions
|
||||
mac_library = "bypassmaclayer"
|
||||
mac_config = [
|
||||
mac_library: str = "bypassmaclayer"
|
||||
mac_config: List[Configuration] = [
|
||||
Configuration(
|
||||
_id="none",
|
||||
_type=ConfigDataTypes.BOOL,
|
||||
|
@ -25,8 +26,8 @@ class EmaneBypassModel(emanemodel.EmaneModel):
|
|||
]
|
||||
|
||||
# phy definitions
|
||||
phy_library = "bypassphylayer"
|
||||
phy_config = []
|
||||
phy_library: str = "bypassphylayer"
|
||||
phy_config: List[Configuration] = []
|
||||
|
||||
@classmethod
|
||||
def load(cls, emane_prefix: str) -> None:
|
||||
|
|
|
@ -22,6 +22,7 @@ except ImportError:
|
|||
try:
|
||||
from emanesh.events.commeffectevent import CommEffectEvent
|
||||
except ImportError:
|
||||
CommEffectEvent = None
|
||||
logging.debug("compatible emane python bindings not installed")
|
||||
|
||||
|
||||
|
@ -38,16 +39,15 @@ def convert_none(x: float) -> int:
|
|||
|
||||
|
||||
class EmaneCommEffectModel(emanemodel.EmaneModel):
|
||||
name = "emane_commeffect"
|
||||
|
||||
shim_library = "commeffectshim"
|
||||
shim_xml = "commeffectshim.xml"
|
||||
shim_defaults = {}
|
||||
config_shim = []
|
||||
name: str = "emane_commeffect"
|
||||
shim_library: str = "commeffectshim"
|
||||
shim_xml: str = "commeffectshim.xml"
|
||||
shim_defaults: Dict[str, str] = {}
|
||||
config_shim: List[Configuration] = []
|
||||
|
||||
# comm effect does not need the default phy and external configurations
|
||||
phy_config = []
|
||||
external_config = []
|
||||
phy_config: List[Configuration] = []
|
||||
external_config: List[Configuration] = []
|
||||
|
||||
@classmethod
|
||||
def load(cls, emane_prefix: str) -> None:
|
||||
|
|
|
@ -70,11 +70,13 @@ class EmaneManager(ModelManager):
|
|||
controlling the EMANE daemons.
|
||||
"""
|
||||
|
||||
name = "emane"
|
||||
config_type = RegisterTlvs.EMULATION_SERVER
|
||||
SUCCESS, NOT_NEEDED, NOT_READY = (0, 1, 2)
|
||||
EVENTCFGVAR = "LIBEMANEEVENTSERVICECONFIG"
|
||||
DEFAULT_LOG_LEVEL = 3
|
||||
name: str = "emane"
|
||||
config_type: RegisterTlvs = RegisterTlvs.EMULATION_SERVER
|
||||
SUCCESS: int = 0
|
||||
NOT_NEEDED: int = 1
|
||||
NOT_READY: int = 2
|
||||
EVENTCFGVAR: str = "LIBEMANEEVENTSERVICECONFIG"
|
||||
DEFAULT_LOG_LEVEL: int = 3
|
||||
|
||||
def __init__(self, session: "Session") -> None:
|
||||
"""
|
||||
|
@ -84,29 +86,29 @@ class EmaneManager(ModelManager):
|
|||
:return: nothing
|
||||
"""
|
||||
super().__init__()
|
||||
self.session = session
|
||||
self._emane_nets = {}
|
||||
self._emane_node_lock = threading.Lock()
|
||||
self.session: "Session" = session
|
||||
self._emane_nets: Dict[int, EmaneNet] = {}
|
||||
self._emane_node_lock: threading.Lock = threading.Lock()
|
||||
# port numbers are allocated from these counters
|
||||
self.platformport = self.session.options.get_config_int(
|
||||
self.platformport: int = self.session.options.get_config_int(
|
||||
"emane_platform_port", 8100
|
||||
)
|
||||
self.transformport = self.session.options.get_config_int(
|
||||
self.transformport: int = self.session.options.get_config_int(
|
||||
"emane_transform_port", 8200
|
||||
)
|
||||
self.doeventloop = False
|
||||
self.eventmonthread = None
|
||||
self.doeventloop: bool = False
|
||||
self.eventmonthread: Optional[threading.Thread] = None
|
||||
|
||||
# model for global EMANE configuration options
|
||||
self.emane_config = EmaneGlobalModel(session)
|
||||
self.emane_config: EmaneGlobalModel = EmaneGlobalModel(session)
|
||||
self.set_configs(self.emane_config.default_values())
|
||||
|
||||
# link monitor
|
||||
self.link_monitor = EmaneLinkMonitor(self)
|
||||
self.link_monitor: EmaneLinkMonitor = EmaneLinkMonitor(self)
|
||||
|
||||
self.service = None
|
||||
self.eventchannel = None
|
||||
self.event_device = None
|
||||
self.service: Optional[EventService] = None
|
||||
self.eventchannel: Optional[Tuple[str, int, str]] = None
|
||||
self.event_device: Optional[str] = None
|
||||
self.emane_check()
|
||||
|
||||
def getifcconfig(
|
||||
|
@ -890,12 +892,12 @@ class EmaneGlobalModel:
|
|||
Global EMANE configuration options.
|
||||
"""
|
||||
|
||||
name = "emane"
|
||||
bitmap = None
|
||||
name: str = "emane"
|
||||
bitmap: Optional[str] = None
|
||||
|
||||
def __init__(self, session: "Session") -> None:
|
||||
self.session = session
|
||||
self.core_config = [
|
||||
self.session: "Session" = session
|
||||
self.core_config: List[Configuration] = [
|
||||
Configuration(
|
||||
_id="platform_id_start",
|
||||
_type=ConfigDataTypes.INT32,
|
||||
|
|
|
@ -11,6 +11,7 @@ except ImportError:
|
|||
try:
|
||||
from emanesh import manifest
|
||||
except ImportError:
|
||||
manifest = None
|
||||
logging.debug("compatible emane python bindings not installed")
|
||||
|
||||
|
||||
|
|
|
@ -3,7 +3,7 @@ Defines Emane Models used within CORE.
|
|||
"""
|
||||
import logging
|
||||
import os
|
||||
from typing import Dict, List
|
||||
from typing import Dict, List, Optional, Set
|
||||
|
||||
from core.config import ConfigGroup, Configuration
|
||||
from core.emane import emanemanifest
|
||||
|
@ -25,19 +25,23 @@ class EmaneModel(WirelessModel):
|
|||
"""
|
||||
|
||||
# default mac configuration settings
|
||||
mac_library = None
|
||||
mac_xml = None
|
||||
mac_defaults = {}
|
||||
mac_config = []
|
||||
mac_library: Optional[str] = None
|
||||
mac_xml: Optional[str] = None
|
||||
mac_defaults: Dict[str, str] = {}
|
||||
mac_config: List[Configuration] = []
|
||||
|
||||
# default phy configuration settings, using the universal model
|
||||
phy_library = None
|
||||
phy_xml = "emanephy.xml"
|
||||
phy_defaults = {"subid": "1", "propagationmodel": "2ray", "noisemode": "none"}
|
||||
phy_config = []
|
||||
phy_library: Optional[str] = None
|
||||
phy_xml: str = "emanephy.xml"
|
||||
phy_defaults: Dict[str, str] = {
|
||||
"subid": "1",
|
||||
"propagationmodel": "2ray",
|
||||
"noisemode": "none",
|
||||
}
|
||||
phy_config: List[Configuration] = []
|
||||
|
||||
# support for external configurations
|
||||
external_config = [
|
||||
external_config: List[Configuration] = [
|
||||
Configuration("external", ConfigDataTypes.BOOL, default="0"),
|
||||
Configuration(
|
||||
"platformendpoint", ConfigDataTypes.STRING, default="127.0.0.1:40001"
|
||||
|
@ -47,7 +51,7 @@ class EmaneModel(WirelessModel):
|
|||
),
|
||||
]
|
||||
|
||||
config_ignore = set()
|
||||
config_ignore: Set[str] = set()
|
||||
|
||||
@classmethod
|
||||
def load(cls, emane_prefix: str) -> None:
|
||||
|
|
|
@ -8,11 +8,11 @@ from core.emane import emanemodel
|
|||
|
||||
class EmaneIeee80211abgModel(emanemodel.EmaneModel):
|
||||
# model name
|
||||
name = "emane_ieee80211abg"
|
||||
name: str = "emane_ieee80211abg"
|
||||
|
||||
# mac configuration
|
||||
mac_library = "ieee80211abgmaclayer"
|
||||
mac_xml = "ieee80211abgmaclayer.xml"
|
||||
mac_library: str = "ieee80211abgmaclayer"
|
||||
mac_xml: str = "ieee80211abgmaclayer.xml"
|
||||
|
||||
@classmethod
|
||||
def load(cls, emane_prefix: str) -> None:
|
||||
|
|
|
@ -2,7 +2,7 @@ import logging
|
|||
import sched
|
||||
import threading
|
||||
import time
|
||||
from typing import TYPE_CHECKING, Dict, List, Tuple
|
||||
from typing import TYPE_CHECKING, Dict, List, Optional, Set, Tuple
|
||||
|
||||
import netaddr
|
||||
from lxml import etree
|
||||
|
@ -17,28 +17,29 @@ except ImportError:
|
|||
try:
|
||||
from emanesh import shell
|
||||
except ImportError:
|
||||
shell = None
|
||||
logging.debug("compatible emane python bindings not installed")
|
||||
|
||||
if TYPE_CHECKING:
|
||||
from core.emane.emanemanager import EmaneManager
|
||||
|
||||
DEFAULT_PORT = 47_000
|
||||
MAC_COMPONENT_INDEX = 1
|
||||
EMANE_RFPIPE = "rfpipemaclayer"
|
||||
EMANE_80211 = "ieee80211abgmaclayer"
|
||||
EMANE_TDMA = "tdmaeventschedulerradiomodel"
|
||||
SINR_TABLE = "NeighborStatusTable"
|
||||
NEM_SELF = 65535
|
||||
DEFAULT_PORT: int = 47_000
|
||||
MAC_COMPONENT_INDEX: int = 1
|
||||
EMANE_RFPIPE: str = "rfpipemaclayer"
|
||||
EMANE_80211: str = "ieee80211abgmaclayer"
|
||||
EMANE_TDMA: str = "tdmaeventschedulerradiomodel"
|
||||
SINR_TABLE: str = "NeighborStatusTable"
|
||||
NEM_SELF: int = 65535
|
||||
|
||||
|
||||
class LossTable:
|
||||
def __init__(self, losses: Dict[float, float]) -> None:
|
||||
self.losses = losses
|
||||
self.sinrs = sorted(self.losses.keys())
|
||||
self.loss_lookup = {}
|
||||
self.losses: Dict[float, float] = losses
|
||||
self.sinrs: List[float] = sorted(self.losses.keys())
|
||||
self.loss_lookup: Dict[int, float] = {}
|
||||
for index, value in enumerate(self.sinrs):
|
||||
self.loss_lookup[index] = self.losses[value]
|
||||
self.mac_id = None
|
||||
self.mac_id: Optional[str] = None
|
||||
|
||||
def get_loss(self, sinr: float) -> float:
|
||||
index = self._get_index(sinr)
|
||||
|
@ -54,11 +55,11 @@ class LossTable:
|
|||
|
||||
class EmaneLink:
|
||||
def __init__(self, from_nem: int, to_nem: int, sinr: float) -> None:
|
||||
self.from_nem = from_nem
|
||||
self.to_nem = to_nem
|
||||
self.sinr = sinr
|
||||
self.last_seen = None
|
||||
self.updated = False
|
||||
self.from_nem: int = from_nem
|
||||
self.to_nem: int = to_nem
|
||||
self.sinr: float = sinr
|
||||
self.last_seen: Optional[float] = None
|
||||
self.updated: bool = False
|
||||
self.touch()
|
||||
|
||||
def update(self, sinr: float) -> None:
|
||||
|
@ -78,9 +79,11 @@ class EmaneLink:
|
|||
|
||||
class EmaneClient:
|
||||
def __init__(self, address: str) -> None:
|
||||
self.address = address
|
||||
self.client = shell.ControlPortClient(self.address, DEFAULT_PORT)
|
||||
self.nems = {}
|
||||
self.address: str = address
|
||||
self.client: shell.ControlPortClient = shell.ControlPortClient(
|
||||
self.address, DEFAULT_PORT
|
||||
)
|
||||
self.nems: Dict[int, LossTable] = {}
|
||||
self.setup()
|
||||
|
||||
def setup(self) -> None:
|
||||
|
@ -174,15 +177,15 @@ class EmaneClient:
|
|||
|
||||
class EmaneLinkMonitor:
|
||||
def __init__(self, emane_manager: "EmaneManager") -> None:
|
||||
self.emane_manager = emane_manager
|
||||
self.clients = []
|
||||
self.links = {}
|
||||
self.complete_links = set()
|
||||
self.loss_threshold = None
|
||||
self.link_interval = None
|
||||
self.link_timeout = None
|
||||
self.scheduler = None
|
||||
self.running = False
|
||||
self.emane_manager: "EmaneManager" = emane_manager
|
||||
self.clients: List[EmaneClient] = []
|
||||
self.links: Dict[Tuple[int, int], EmaneLink] = {}
|
||||
self.complete_links: Set[Tuple[int, int]] = set()
|
||||
self.loss_threshold: Optional[int] = None
|
||||
self.link_interval: Optional[int] = None
|
||||
self.link_timeout: Optional[int] = None
|
||||
self.scheduler: Optional[sched.scheduler] = None
|
||||
self.running: bool = False
|
||||
|
||||
def start(self) -> None:
|
||||
self.loss_threshold = int(self.emane_manager.get_config("loss_threshold"))
|
||||
|
|
|
@ -16,13 +16,16 @@ from core.emulator.enumerations import (
|
|||
RegisterTlvs,
|
||||
TransportType,
|
||||
)
|
||||
from core.errors import CoreError
|
||||
from core.nodes.base import CoreNetworkBase
|
||||
from core.nodes.interface import CoreInterface
|
||||
|
||||
if TYPE_CHECKING:
|
||||
from core.emane.emanemodel import EmaneModel
|
||||
from core.emulator.session import Session
|
||||
from core.location.mobility import WirelessModel
|
||||
from core.location.mobility import WirelessModel, WayPointMobility
|
||||
|
||||
OptionalEmaneModel = Optional[EmaneModel]
|
||||
WirelessModelType = Type[WirelessModel]
|
||||
|
||||
try:
|
||||
|
@ -31,6 +34,7 @@ except ImportError:
|
|||
try:
|
||||
from emanesh.events import LocationEvent
|
||||
except ImportError:
|
||||
LocationEvent = None
|
||||
logging.debug("compatible emane python bindings not installed")
|
||||
|
||||
|
||||
|
@ -41,10 +45,10 @@ class EmaneNet(CoreNetworkBase):
|
|||
Emane controller object that exists in a session.
|
||||
"""
|
||||
|
||||
apitype = NodeTypes.EMANE
|
||||
linktype = LinkTypes.WIRED
|
||||
type = "wlan"
|
||||
is_emane = True
|
||||
apitype: NodeTypes = NodeTypes.EMANE
|
||||
linktype: LinkTypes = LinkTypes.WIRED
|
||||
type: str = "wlan"
|
||||
is_emane: bool = True
|
||||
|
||||
def __init__(
|
||||
self,
|
||||
|
@ -55,10 +59,10 @@ class EmaneNet(CoreNetworkBase):
|
|||
server: DistributedServer = None,
|
||||
) -> None:
|
||||
super().__init__(session, _id, name, start, server)
|
||||
self.conf = ""
|
||||
self.nemidmap = {}
|
||||
self.model = None
|
||||
self.mobility = None
|
||||
self.conf: str = ""
|
||||
self.nemidmap: Dict[CoreInterface, int] = {}
|
||||
self.model: "OptionalEmaneModel" = None
|
||||
self.mobility: Optional[WayPointMobility] = None
|
||||
|
||||
def linkconfig(
|
||||
self, netif: CoreInterface, options: LinkOptions, netif2: CoreInterface = None
|
||||
|
@ -84,11 +88,11 @@ class EmaneNet(CoreNetworkBase):
|
|||
|
||||
def updatemodel(self, config: Dict[str, str]) -> None:
|
||||
if not self.model:
|
||||
raise ValueError("no model set to update for node(%s)", self.id)
|
||||
raise CoreError(f"no model set to update for node({self.name})")
|
||||
logging.info(
|
||||
"node(%s) updating model(%s): %s", self.id, self.model.name, config
|
||||
)
|
||||
self.model.set_configs(config, node_id=self.id)
|
||||
self.model.update_config(config)
|
||||
|
||||
def setmodel(self, model: "WirelessModelType", config: Dict[str, str]) -> None:
|
||||
"""
|
||||
|
|
|
@ -8,11 +8,11 @@ from core.emane import emanemodel
|
|||
|
||||
class EmaneRfPipeModel(emanemodel.EmaneModel):
|
||||
# model name
|
||||
name = "emane_rfpipe"
|
||||
name: str = "emane_rfpipe"
|
||||
|
||||
# mac configuration
|
||||
mac_library = "rfpipemaclayer"
|
||||
mac_xml = "rfpipemaclayer.xml"
|
||||
mac_library: str = "rfpipemaclayer"
|
||||
mac_xml: str = "rfpipemaclayer.xml"
|
||||
|
||||
@classmethod
|
||||
def load(cls, emane_prefix: str) -> None:
|
||||
|
|
|
@ -4,6 +4,7 @@ tdma.py: EMANE TDMA model bindings for CORE
|
|||
|
||||
import logging
|
||||
import os
|
||||
from typing import Set
|
||||
|
||||
from core import constants, utils
|
||||
from core.config import Configuration
|
||||
|
@ -13,18 +14,18 @@ from core.emulator.enumerations import ConfigDataTypes
|
|||
|
||||
class EmaneTdmaModel(emanemodel.EmaneModel):
|
||||
# model name
|
||||
name = "emane_tdma"
|
||||
name: str = "emane_tdma"
|
||||
|
||||
# mac configuration
|
||||
mac_library = "tdmaeventschedulerradiomodel"
|
||||
mac_xml = "tdmaeventschedulerradiomodel.xml"
|
||||
mac_library: str = "tdmaeventschedulerradiomodel"
|
||||
mac_xml: str = "tdmaeventschedulerradiomodel.xml"
|
||||
|
||||
# add custom schedule options and ignore it when writing emane xml
|
||||
schedule_name = "schedule"
|
||||
default_schedule = os.path.join(
|
||||
schedule_name: str = "schedule"
|
||||
default_schedule: str = os.path.join(
|
||||
constants.CORE_DATA_DIR, "examples", "tdma", "schedule.xml"
|
||||
)
|
||||
config_ignore = {schedule_name}
|
||||
config_ignore: Set[str] = {schedule_name}
|
||||
|
||||
@classmethod
|
||||
def load(cls, emane_prefix: str) -> None:
|
||||
|
|
|
@ -1090,12 +1090,12 @@ class WlanNode(CoreNetwork):
|
|||
|
||||
def update_mobility(self, config: Dict[str, str]) -> None:
|
||||
if not self.mobility:
|
||||
raise ValueError(f"no mobility set to update for node({self.id})")
|
||||
raise CoreError(f"no mobility set to update for node({self.name})")
|
||||
self.mobility.update_config(config)
|
||||
|
||||
def updatemodel(self, config: Dict[str, str]) -> None:
|
||||
if not self.model:
|
||||
raise ValueError(f"no model set to update for node({self.id})")
|
||||
raise CoreError(f"no model set to update for node({self.name})")
|
||||
logging.debug(
|
||||
"node(%s) updating model(%s): %s", self.id, self.model.name, config
|
||||
)
|
||||
|
|
Loading…
Reference in a new issue