daemon: added class variable type hinting to core.emane

This commit is contained in:
Blake Harnden 2020-06-12 09:52:01 -07:00
parent ef3cf5697d
commit 6201875b78
11 changed files with 116 additions and 100 deletions

View file

@ -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:

View file

@ -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:

View file

@ -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,

View file

@ -11,6 +11,7 @@ except ImportError:
try:
from emanesh import manifest
except ImportError:
manifest = None
logging.debug("compatible emane python bindings not installed")

View file

@ -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:

View file

@ -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:

View file

@ -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"))

View file

@ -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:
"""

View file

@ -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:

View file

@ -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:

View file

@ -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
)