daemon: changes to support providing emane wireless links in all_link_data, which makes it accessible over grpc

This commit is contained in:
Blake Harnden 2020-05-29 11:48:00 -07:00
parent 4ab415e37d
commit 183ffda570
3 changed files with 68 additions and 24 deletions

View file

@ -6,7 +6,7 @@ import logging
import os import os
import threading import threading
from collections import OrderedDict from collections import OrderedDict
from typing import TYPE_CHECKING, Dict, List, Set, Tuple, Type from typing import TYPE_CHECKING, Dict, List, Optional, Set, Tuple, Type
from core import utils from core import utils
from core.config import ConfigGroup, Configuration, ModelManager from core.config import ConfigGroup, Configuration, ModelManager
@ -19,7 +19,13 @@ from core.emane.linkmonitor import EmaneLinkMonitor
from core.emane.nodes import EmaneNet from core.emane.nodes import EmaneNet
from core.emane.rfpipe import EmaneRfPipeModel from core.emane.rfpipe import EmaneRfPipeModel
from core.emane.tdma import EmaneTdmaModel from core.emane.tdma import EmaneTdmaModel
from core.emulator.enumerations import ConfigDataTypes, RegisterTlvs from core.emulator.data import LinkData
from core.emulator.enumerations import (
ConfigDataTypes,
LinkTypes,
MessageFlags,
RegisterTlvs,
)
from core.errors import CoreCommandError, CoreError from core.errors import CoreCommandError, CoreError
from core.nodes.base import CoreNode, NodeBase from core.nodes.base import CoreNode, NodeBase
from core.nodes.interface import CoreInterface from core.nodes.interface import CoreInterface
@ -458,7 +464,7 @@ class EmaneManager(ModelManager):
model_class = self.models[model_name] model_class = self.models[model_name]
emane_node.setmodel(model_class, config) emane_node.setmodel(model_class, config)
def nemlookup(self, nemid) -> Tuple[EmaneNet, CoreInterface]: def nemlookup(self, nemid) -> Tuple[Optional[EmaneNet], Optional[CoreInterface]]:
""" """
Look for the given numerical NEM ID and return the first matching Look for the given numerical NEM ID and return the first matching
EMANE network and NEM interface. EMANE network and NEM interface.
@ -476,6 +482,29 @@ class EmaneManager(ModelManager):
return emane_node, netif return emane_node, netif
def get_nem_link(
self, nem1: int, nem2: int, flags: MessageFlags = MessageFlags.NONE
) -> Optional[LinkData]:
emane1, netif = self.nemlookup(nem1)
if not emane1 or not netif:
logging.error("invalid nem: %s", nem1)
return None
node1 = netif.node
emane2, netif = self.nemlookup(nem2)
if not emane2 or not netif:
logging.error("invalid nem: %s", nem2)
return None
node2 = netif.node
color = self.session.get_link_color(emane1.id)
return LinkData(
message_type=flags,
node1_id=node1.id,
node2_id=node2.id,
network_id=emane1.id,
link_type=LinkTypes.WIRELESS,
color=color,
)
def numnems(self) -> int: def numnems(self) -> int:
""" """
Return the number of NEMs emulated locally. Return the number of NEMs emulated locally.

View file

@ -285,26 +285,11 @@ class EmaneLinkMonitor:
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:
nem_one, nem_two = link_id nem_one, nem_two = link_id
emane_one, netif = self.emane_manager.nemlookup(nem_one) link = self.emane_manager.get_nem_link(nem_one, nem_two, message_type)
if not emane_one or not netif: if link:
logging.error("invalid nem: %s", nem_one) label = self.get_link_label(link_id)
return link.label = label
node_one = netif.node self.emane_manager.session.broadcast_link(link)
emane_two, netif = self.emane_manager.nemlookup(nem_two)
if not emane_two or not netif:
logging.error("invalid nem: %s", nem_two)
return
node_two = netif.node
logging.debug(
"%s emane link from %s(%s) to %s(%s)",
message_type.name,
node_one.name,
nem_one,
node_two.name,
nem_two,
)
label = self.get_link_label(link_id)
self.send_message(message_type, label, node_one.id, node_two.id, emane_one.id)
def send_message( def send_message(
self, self,

View file

@ -6,8 +6,9 @@ share the same MAC+PHY model.
import logging import logging
from typing import TYPE_CHECKING, Dict, List, Optional, Tuple, Type from typing import TYPE_CHECKING, Dict, List, Optional, Tuple, Type
from core.emulator.data import LinkData
from core.emulator.distributed import DistributedServer from core.emulator.distributed import DistributedServer
from core.emulator.enumerations import LinkTypes, NodeTypes, RegisterTlvs from core.emulator.enumerations import LinkTypes, MessageFlags, NodeTypes, RegisterTlvs
from core.nodes.base import CoreNetworkBase from core.nodes.base import CoreNetworkBase
from core.nodes.interface import CoreInterface from core.nodes.interface import CoreInterface
@ -236,3 +237,32 @@ class EmaneNet(CoreNetworkBase):
nemid, lon, lat, alt = position nemid, lon, lat, alt = position
event.append(nemid, latitude=lat, longitude=lon, altitude=alt) event.append(nemid, latitude=lat, longitude=lon, altitude=alt)
self.session.emane.service.publish(0, event) self.session.emane.service.publish(0, event)
def all_link_data(self, flags: MessageFlags = MessageFlags.NONE) -> List[LinkData]:
logging.info("gathering emane links: %s", self.id)
links = super().all_link_data(flags)
# gather current emane links
nem_ids = set(self.nemidmap.values())
logging.info("known nems: %s", nem_ids)
emane_manager = self.session.emane
emane_links = emane_manager.link_monitor.links
considered = set()
for link_key in emane_links:
considered_key = tuple(sorted(link_key))
if considered_key in considered:
continue
considered.add(considered_key)
logging.info("considering emane link: %s", considered_key)
nem1, nem2 = considered_key
# ignore links not related to this node
if nem1 not in nem_ids and nem2 not in nem_ids:
logging.info("ignore emane link not within network: %s", (nem1, nem2))
continue
# ignore incomplete links
if (nem2, nem1) not in emane_links:
logging.info("ignore emane link not complete: %s", (nem1, nem2))
continue
link = emane_manager.get_nem_link(nem1, nem2)
if link:
links.append(link)
return links