daemon: removed nem map from individual emane networks, all nems are stored and generated from the emane manager

This commit is contained in:
Blake Harnden 2020-07-05 21:29:03 -07:00
parent fcda1f9f14
commit 5cc4d92760
9 changed files with 64 additions and 89 deletions

View file

@ -491,10 +491,13 @@ def iface_to_proto(node_id: int, iface: CoreInterface) -> core_pb2.Interface:
)
def get_nem_id(node: CoreNode, iface_id: int, context: ServicerContext) -> int:
def get_nem_id(
session: Session, node: CoreNode, iface_id: int, context: ServicerContext
) -> int:
"""
Get nem id for a given node and interface id.
:param session: session node belongs to
:param node: node to get nem id for
:param iface_id: id of interface on node to get nem id for
:param context: request context
@ -508,7 +511,7 @@ def get_nem_id(node: CoreNode, iface_id: int, context: ServicerContext) -> int:
if not isinstance(net, EmaneNet):
message = f"{node.name} interface {iface_id} is not an EMANE network"
context.abort(grpc.StatusCode.INVALID_ARGUMENT, message)
nem_id = net.getnemid(iface)
nem_id = session.emane.get_nem_id(iface)
if nem_id is None:
message = f"{node.name} interface {iface_id} nem id does not exist"
context.abort(grpc.StatusCode.INVALID_ARGUMENT, message)

View file

@ -1551,29 +1551,29 @@ class CoreGrpcServer(core_pb2_grpc.CoreApiServicer):
logging.debug("emane link: %s", request)
session = self.get_session(request.session_id, context)
nem1 = request.nem1
emane1, iface = session.emane.nemlookup(nem1)
if not emane1 or not iface:
iface1 = session.emane.get_iface(nem1)
if not iface1:
context.abort(grpc.StatusCode.NOT_FOUND, f"nem one {nem1} not found")
node1 = iface.node
node1 = iface1.node
nem2 = request.nem2
emane2, iface = session.emane.nemlookup(nem2)
if not emane2 or not iface:
iface2 = session.emane.get_iface(nem2)
if not iface2:
context.abort(grpc.StatusCode.NOT_FOUND, f"nem two {nem2} not found")
node2 = iface.node
node2 = iface2.node
if emane1.id == emane2.id:
if iface1.net == iface2.net:
if request.linked:
flag = MessageFlags.ADD
else:
flag = MessageFlags.DELETE
color = session.get_link_color(emane1.id)
color = session.get_link_color(iface1.net.id)
link = LinkData(
message_type=flag,
type=LinkTypes.WIRELESS,
node1_id=node1.id,
node2_id=node2.id,
network_id=emane1.id,
network_id=iface1.net.id,
color=color,
)
session.broadcast_link(link)
@ -1796,8 +1796,8 @@ class CoreGrpcServer(core_pb2_grpc.CoreApiServicer):
for request in request_iterator:
session = self.get_session(request.session_id, context)
node1 = self.get_node(session, request.node1_id, context, CoreNode)
nem1 = grpcutils.get_nem_id(node1, request.iface1_id, context)
nem1 = grpcutils.get_nem_id(session, node1, request.iface1_id, context)
node2 = self.get_node(session, request.node2_id, context, CoreNode)
nem2 = grpcutils.get_nem_id(node2, request.iface2_id, context)
nem2 = grpcutils.get_nem_id(session, node2, request.iface2_id, context)
session.emane.publish_pathloss(nem1, nem2, request.rx1, request.rx2)
return EmanePathlossesResponse()

View file

@ -10,7 +10,6 @@ from lxml import etree
from core.config import ConfigGroup, Configuration
from core.emane import emanemanifest, emanemodel
from core.emane.nodes import EmaneNet
from core.emulator.data import LinkOptions
from core.nodes.interface import CoreInterface
from core.xml import emanexml
@ -124,12 +123,11 @@ class EmaneCommEffectModel(emanemodel.EmaneModel):
# TODO: batch these into multiple events per transmission
# TODO: may want to split out seconds portion of delay and jitter
event = CommEffectEvent()
emane_node = self.session.get_node(self.id, EmaneNet)
nemid = emane_node.getnemid(iface)
nemid2 = emane_node.getnemid(iface2)
nem1 = self.session.emane.get_nem_id(iface)
nem2 = self.session.emane.get_nem_id(iface2)
logging.info("sending comm effect event")
event.append(
nemid,
nem1,
latency=convert_none(options.delay),
jitter=convert_none(options.jitter),
loss=convert_none(options.loss),
@ -137,4 +135,4 @@ class EmaneCommEffectModel(emanemodel.EmaneModel):
unicast=int(convert_none(options.bandwidth)),
broadcast=int(convert_none(options.bandwidth)),
)
service.publish(nemid2, event)
service.publish(nem2, event)

View file

@ -90,7 +90,8 @@ class EmaneManager(ModelManager):
"""
super().__init__()
self.session: "Session" = session
self.nems: Dict[int, CoreInterface] = {}
self.nems_to_ifaces: Dict[int, CoreInterface] = {}
self.ifaces_to_nems: Dict[CoreInterface, int] = {}
self._emane_nets: Dict[int, EmaneNet] = {}
self._emane_node_lock: threading.Lock = threading.Lock()
# port numbers are allocated from these counters
@ -117,7 +118,7 @@ class EmaneManager(ModelManager):
def next_nem_id(self) -> int:
nem_id = int(self.get_config("nem_id_start"))
while nem_id in self.nems:
while nem_id in self.nems_to_ifaces:
nem_id += 1
return nem_id
@ -363,7 +364,7 @@ class EmaneManager(ModelManager):
0, remove=False, conf_required=False
)
nem_id = self.next_nem_id()
self.nems[nem_id] = iface
self.set_nem(nem_id, iface)
self.write_nem(iface, nem_id)
emanexml.build_platform_xml(self, control_net, emane_net, iface, nem_id)
config = self.get_iface_config(emane_net, iface)
@ -371,6 +372,18 @@ class EmaneManager(ModelManager):
self.start_daemon(iface)
self.install_iface(emane_net, iface)
def set_nem(self, nem_id: int, iface: CoreInterface) -> None:
if nem_id in self.nems_to_ifaces:
raise CoreError(f"adding duplicate nem: {nem_id}")
self.nems_to_ifaces[nem_id] = iface
self.ifaces_to_nems[iface] = nem_id
def get_iface(self, nem_id: int) -> Optional[CoreInterface]:
return self.nems_to_ifaces.get(nem_id)
def get_nem_id(self, iface: CoreInterface) -> Optional[int]:
return self.ifaces_to_nems.get(iface)
def write_nem(self, iface: CoreInterface, nem_id: int) -> None:
path = os.path.join(self.session.session_dir, "emane_nems")
try:
@ -405,7 +418,8 @@ class EmaneManager(ModelManager):
"""
with self._emane_node_lock:
self._emane_nets.clear()
self.nems.clear()
self.nems_to_ifaces.clear()
self.ifaces_to_nems.clear()
def shutdown(self) -> None:
"""
@ -448,42 +462,29 @@ class EmaneManager(ModelManager):
model_class = self.models[model_name]
emane_net.setmodel(model_class, config)
def nemlookup(self, nemid) -> Tuple[Optional[EmaneNet], Optional[CoreInterface]]:
"""
Look for the given numerical NEM ID and return the first matching
EMANE network and NEM interface.
"""
emane_node = None
iface = None
for node_id in self._emane_nets:
emane_node = self._emane_nets[node_id]
iface = emane_node.get_nem_iface(nemid)
if iface is not None:
break
else:
emane_node = None
return emane_node, iface
def get_nem_link(
self, nem1: int, nem2: int, flags: MessageFlags = MessageFlags.NONE
) -> Optional[LinkData]:
emane1, iface = self.nemlookup(nem1)
if not emane1 or not iface:
iface1 = self.get_iface(nem1)
if not iface1:
logging.error("invalid nem: %s", nem1)
return None
node1 = iface.node
emane2, iface = self.nemlookup(nem2)
if not emane2 or not iface:
node1 = iface1.node
iface2 = self.get_iface(nem2)
if not iface2:
logging.error("invalid nem: %s", nem2)
return None
node2 = iface.node
color = self.session.get_link_color(emane1.id)
node2 = iface2.node
if iface1.net != iface2.net:
return None
emane_net = iface1.net
color = self.session.get_link_color(emane_net.id)
return LinkData(
message_type=flags,
type=LinkTypes.WIRELESS,
node1_id=node1.id,
node2_id=node2.id,
network_id=emane1.id,
network_id=emane_net.id,
color=color,
)
@ -728,7 +729,7 @@ class EmaneManager(ModelManager):
Returns True if successfully parsed and a Node Message was sent.
"""
# convert nemid to node number
_emanenode, iface = self.nemlookup(nemid)
iface = self.get_iface(nemid)
if iface is None:
logging.info("location event for unknown NEM %s", nemid)
return False

View file

@ -52,7 +52,6 @@ class EmaneNet(CoreNetworkBase):
) -> None:
super().__init__(session, _id, name, server)
self.conf: str = ""
self.nemidmap: Dict[CoreInterface, int] = {}
self.model: "OptionalEmaneModel" = None
self.mobility: Optional[WayPointMobility] = None
@ -105,32 +104,6 @@ class EmaneNet(CoreNetworkBase):
self.mobility = model(session=self.session, _id=self.id)
self.mobility.update_config(config)
def setnemid(self, iface: 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[iface] = nemid
def getnemid(self, iface: CoreInterface) -> Optional[int]:
"""
Given an interface, return its numerical ID.
"""
if iface not in self.nemidmap:
return None
else:
return self.nemidmap[iface]
def get_nem_iface(self, nemid: int) -> Optional[CoreInterface]:
"""
Given a numerical NEM ID, return its interface. This returns the
first interface that matches the given NEM ID.
"""
for iface in self.nemidmap:
if self.nemidmap[iface] == nemid:
return iface
return None
def _nem_position(
self, iface: CoreInterface
) -> Optional[Tuple[int, float, float, float]]:
@ -140,9 +113,9 @@ class EmaneNet(CoreNetworkBase):
:param iface: interface to get nem emane position for
:return: nem position tuple, None otherwise
"""
nemid = self.getnemid(iface)
nem_id = self.session.emane.get_nem_id(iface)
ifname = iface.localname
if nemid is None:
if nem_id is None:
logging.info("nemid for %s is unknown", ifname)
return
node = iface.node
@ -153,7 +126,7 @@ class EmaneNet(CoreNetworkBase):
node.position.set_geo(lon, lat, alt)
# altitude must be an integer or warning is printed
alt = int(round(alt))
return nemid, lon, lat, alt
return nem_id, lon, lat, alt
def setnemposition(self, iface: CoreInterface) -> None:
"""
@ -164,7 +137,6 @@ class EmaneNet(CoreNetworkBase):
if self.session.emane.service is None:
logging.info("position service not available")
return
position = self._nem_position(iface)
if position:
nemid, lon, lat, alt = position
@ -195,9 +167,12 @@ class EmaneNet(CoreNetworkBase):
def links(self, flags: MessageFlags = MessageFlags.NONE) -> List[LinkData]:
links = super().links(flags)
# gather current emane links
nem_ids = set(self.nemidmap.values())
emane_manager = self.session.emane
# gather current emane links
nem_ids = set()
for iface in self.get_ifaces():
nem_id = emane_manager.get_nem_id(iface)
nem_ids.add(nem_id)
emane_links = emane_manager.link_monitor.links
considered = set()
for link_key in emane_links:

View file

@ -28,7 +28,7 @@ class EmaneTransportService(CoreService):
emane_net = iface.net
config = emane_manager.get_iface_config(emane_net, iface)
if emanexml.is_external(config):
nem_id = emane_net.getnemid(iface)
nem_id = emane_manager.get_nem_id(iface)
cfg += f"emanegentransportxml {iface.name}-platform.xml\n"
cfg += f"emanetransportd -r -l 0 -d transportdaemon{nem_id}.xml\n"
return cfg

View file

@ -501,8 +501,8 @@ class CoreXmlWriter:
iface = node.get_iface(iface_data.id)
# check if emane interface
if isinstance(iface.net, EmaneNet):
nem = iface.net.getnemid(iface)
add_attribute(iface_element, "nem", nem)
nem_id = self.session.emane.get_nem_id(iface)
add_attribute(iface_element, "nem", nem_id)
add_attribute(iface_element, "id", iface_data.id)
add_attribute(iface_element, "name", iface_data.name)
add_attribute(iface_element, "mac", iface_data.mac)

View file

@ -9,7 +9,6 @@ from core import utils
from core.emane.nodes import EmaneNet
from core.executables import IP
from core.nodes.base import CoreNodeBase, NodeBase
from core.nodes.interface import CoreInterface
if TYPE_CHECKING:
from core.emulator.session import Session
@ -38,11 +37,10 @@ def add_mapping(parent_element: etree.Element, maptype: str, mapref: str) -> Non
def add_emane_iface(
host_element: etree.Element,
iface: CoreInterface,
nem_id: int,
platform_name: str = "p1",
transport_name: str = "t1",
) -> etree.Element:
nem_id = iface.net.nemidmap[iface]
host_id = host_element.get("id")
# platform data
@ -158,7 +156,8 @@ class CoreXmlDeployment:
for iface in node.get_ifaces():
emane_element = None
if isinstance(iface.net, EmaneNet):
emane_element = add_emane_iface(host_element, iface)
nem_id = self.session.emane.get_nem_id(iface)
emane_element = add_emane_iface(host_element, nem_id)
parent_element = host_element
if emane_element is not None:

View file

@ -193,7 +193,6 @@ def build_platform_xml(
value = emane_manager.get_config(name)
add_param(platform_element, name, value)
platform_element.append(nem_element)
emane_net.setnemid(iface, nem_id)
mac = _MAC_PREFIX + ":00:00:"
mac += f"{(nem_id >> 8) & 0xFF:02X}:{nem_id & 0xFF:02X}"
iface.set_mac(mac)