grpc: implemened initial support for streaming emane pathloss events

This commit is contained in:
Blake Harnden 2020-06-03 14:35:17 -07:00
parent 7048aa7867
commit 3b0ca1638c
6 changed files with 85 additions and 3 deletions

View file

@ -31,6 +31,8 @@ from core.api.grpc.emane_pb2 import (
EmaneLinkRequest, EmaneLinkRequest,
EmaneLinkResponse, EmaneLinkResponse,
EmaneModelConfig, EmaneModelConfig,
EmanePathlossesRequest,
EmanePathlossesResponse,
GetEmaneConfigRequest, GetEmaneConfigRequest,
GetEmaneConfigResponse, GetEmaneConfigResponse,
GetEmaneEventChannelRequest, GetEmaneEventChannelRequest,
@ -1229,6 +1231,17 @@ class CoreGrpcClient:
) )
return self.stub.WlanLink(request) return self.stub.WlanLink(request)
def emane_pathlosses(
self, pathloss_iter: Iterable[EmanePathlossesRequest]
) -> EmanePathlossesResponse:
"""
Stream EMANE pathloss events.
:param pathloss_iter: iterator for sending EMANE pathloss events
:return: EMANE pathloss response
"""
return self.stub.EmanePathlosses(pathloss_iter)
def connect(self) -> None: def connect(self) -> None:
""" """
Open connection to server, must be closed manually. Open connection to server, must be closed manually.

View file

@ -2,7 +2,9 @@ import logging
import time import time
from typing import Any, Dict, List, Tuple, Type from typing import Any, Dict, List, Tuple, Type
import grpc
import netaddr import netaddr
from grpc import ServicerContext
from core import utils from core import utils
from core.api.grpc import common_pb2, core_pb2 from core.api.grpc import common_pb2, core_pb2
@ -13,7 +15,7 @@ from core.emulator.data import LinkData
from core.emulator.emudata import InterfaceData, LinkOptions, NodeOptions from core.emulator.emudata import InterfaceData, LinkOptions, NodeOptions
from core.emulator.enumerations import LinkTypes, NodeTypes from core.emulator.enumerations import LinkTypes, NodeTypes
from core.emulator.session import Session from core.emulator.session import Session
from core.nodes.base import NodeBase from core.nodes.base import CoreNode, NodeBase
from core.nodes.interface import CoreInterface from core.nodes.interface import CoreInterface
from core.services.coreservices import CoreService from core.services.coreservices import CoreService
@ -478,3 +480,23 @@ def interface_to_proto(interface: CoreInterface) -> core_pb2.Interface:
ip6=ip6, ip6=ip6,
ip6mask=ip6mask, ip6mask=ip6mask,
) )
def get_nem_id(node: CoreNode, netif_id: int, context: ServicerContext) -> int:
"""
Get nem id for a given node and interface id.
:param node: node to get nem id for
:param netif_id: id of interface on node to get nem id for
:param context: request context
:return: nem id
"""
netif = node.netif(netif_id)
if not netif:
message = f"{node.name} missing interface {netif_id}"
context.abort(grpc.StatusCode.NOT_FOUND, message)
net = netif.net
if not isinstance(net, EmaneNet):
message = f"{node.name} interface {netif_id} is not an EMANE network"
context.abort(grpc.StatusCode.INVALID_ARGUMENT, message)
return net.getnemid(netif)

View file

@ -6,7 +6,7 @@ import tempfile
import threading import threading
import time import time
from concurrent import futures from concurrent import futures
from typing import Type from typing import Iterable, Type
import grpc import grpc
from grpc import ServicerContext from grpc import ServicerContext
@ -39,6 +39,8 @@ from core.api.grpc.core_pb2 import ExecuteScriptResponse
from core.api.grpc.emane_pb2 import ( from core.api.grpc.emane_pb2 import (
EmaneLinkRequest, EmaneLinkRequest,
EmaneLinkResponse, EmaneLinkResponse,
EmanePathlossesRequest,
EmanePathlossesResponse,
GetEmaneConfigRequest, GetEmaneConfigRequest,
GetEmaneConfigResponse, GetEmaneConfigResponse,
GetEmaneEventChannelRequest, GetEmaneEventChannelRequest,
@ -1751,3 +1753,17 @@ class CoreGrpcServer(core_pb2_grpc.CoreApiServicer):
wlan.model.sendlinkmsg(n1_netif, n2_netif, unlink=not request.linked) wlan.model.sendlinkmsg(n1_netif, n2_netif, unlink=not request.linked)
result = True result = True
return WlanLinkResponse(result=result) return WlanLinkResponse(result=result)
def EmanePathlosses(
self,
request_iterator: Iterable[EmanePathlossesRequest],
context: ServicerContext,
) -> EmanePathlossesResponse:
for request in request_iterator:
session = self.get_session(request.session_id, context)
n1 = self.get_node(session, request.node_one, context, CoreNode)
nem1 = grpcutils.get_nem_id(n1, request.interface_one_id, context)
n2 = self.get_node(session, request.node_two, context, CoreNode)
nem2 = grpcutils.get_nem_id(n2, request.interface_two_id, context)
session.emane.publish_pathloss(nem1, nem2, request.rx_one, request.rx_two)
return EmanePathlossesResponse()

View file

@ -37,7 +37,7 @@ if TYPE_CHECKING:
from core.emulator.session import Session from core.emulator.session import Session
try: try:
from emane.events import EventService from emane.events import EventService, PathlossEvent
from emane.events import LocationEvent from emane.events import LocationEvent
from emane.events.eventserviceexception import EventServiceException from emane.events.eventserviceexception import EventServiceException
except ImportError: except ImportError:
@ -48,6 +48,7 @@ except ImportError:
except ImportError: except ImportError:
EventService = None EventService = None
LocationEvent = None LocationEvent = None
PathlossEvent = None
EventServiceException = None EventServiceException = None
logging.debug("compatible emane python bindings not installed") logging.debug("compatible emane python bindings not installed")
@ -868,6 +869,21 @@ class EmaneManager(ModelManager):
result = False result = False
return result return result
def publish_pathloss(self, nem1: int, nem2: int, rx1: float, rx2: float) -> None:
"""
Publish pathloss events between provided nems, using provided rx power.
:param nem1: interface one for pathloss
:param nem2: interface two for pathloss
:param rx1: received power from nem2 to nem1
:param rx2: received power from nem1 to nem2
:return: nothing
"""
event = PathlossEvent()
event.append(nem1, forward=rx1)
event.append(nem2, forward=rx2)
self.service.publish(nem1, event)
self.service.publish(nem2, event)
class EmaneGlobalModel: class EmaneGlobalModel:
""" """

View file

@ -149,6 +149,8 @@ service CoreApi {
} }
rpc GetEmaneEventChannel (emane.GetEmaneEventChannelRequest) returns (emane.GetEmaneEventChannelResponse) { rpc GetEmaneEventChannel (emane.GetEmaneEventChannelRequest) returns (emane.GetEmaneEventChannelResponse) {
} }
rpc EmanePathlosses (stream emane.EmanePathlossesRequest) returns (emane.EmanePathlossesResponse) {
}
// xml rpc // xml rpc
rpc SaveXml (SaveXmlRequest) returns (SaveXmlResponse) { rpc SaveXml (SaveXmlRequest) returns (SaveXmlResponse) {

View file

@ -90,3 +90,16 @@ message EmaneModelConfig {
string model = 3; string model = 3;
map<string, string> config = 4; map<string, string> config = 4;
} }
message EmanePathlossesRequest {
int32 session_id = 1;
int32 node_one = 2;
float rx_one = 3;
int32 interface_one_id = 4;
int32 node_two = 5;
float rx_two = 6;
int32 interface_two_id = 7;
}
message EmanePathlossesResponse {
}