daemon: add linked method to session and grpc support leveraging new linking semantics, update add_link validation check

This commit is contained in:
Blake Harnden 2022-03-21 15:42:14 -07:00
parent e5e14ad67b
commit 7ed007496c
4 changed files with 106 additions and 3 deletions

View file

@ -16,7 +16,7 @@ from core.api.grpc.configservices_pb2 import (
GetConfigServiceDefaultsRequest, GetConfigServiceDefaultsRequest,
GetNodeConfigServiceRequest, GetNodeConfigServiceRequest,
) )
from core.api.grpc.core_pb2 import ExecuteScriptRequest, GetConfigRequest from core.api.grpc.core_pb2 import ExecuteScriptRequest, GetConfigRequest, LinkedRequest
from core.api.grpc.emane_pb2 import ( from core.api.grpc.emane_pb2 import (
EmaneLinkRequest, EmaneLinkRequest,
GetEmaneEventChannelRequest, GetEmaneEventChannelRequest,
@ -1049,6 +1049,36 @@ class CoreGrpcClient:
""" """
self.stub.EmanePathlosses(streamer.iter()) self.stub.EmanePathlosses(streamer.iter())
def linked(
self,
session_id: int,
node1_id: int,
node2_id: int,
iface1_id: int,
iface2_id: int,
linked: bool,
) -> None:
"""
Link or unlink an existing core wired link.
:param session_id: session containing the link
:param node1_id: first node in link
:param node2_id: second node in link
:param iface1_id: node1 interface
:param iface2_id: node2 interface
:param linked: True to connect link, False to disconnect
:return: nothing
"""
request = LinkedRequest(
session_id=session_id,
node1_id=node1_id,
node2_id=node2_id,
iface1_id=iface1_id,
iface2_id=iface2_id,
linked=linked,
)
self.stub.Linked(request)
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

@ -26,7 +26,7 @@ from core.api.grpc.configservices_pb2 import (
GetNodeConfigServiceRequest, GetNodeConfigServiceRequest,
GetNodeConfigServiceResponse, GetNodeConfigServiceResponse,
) )
from core.api.grpc.core_pb2 import ExecuteScriptResponse from core.api.grpc.core_pb2 import ExecuteScriptResponse, LinkedRequest, LinkedResponse
from core.api.grpc.emane_pb2 import ( from core.api.grpc.emane_pb2 import (
EmaneLinkRequest, EmaneLinkRequest,
EmaneLinkResponse, EmaneLinkResponse,
@ -1315,3 +1315,16 @@ class CoreGrpcServer(core_pb2_grpc.CoreApiServicer):
nem2 = grpcutils.get_nem_id(session, 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) session.emane.publish_pathloss(nem1, nem2, request.rx1, request.rx2)
return EmanePathlossesResponse() return EmanePathlossesResponse()
def Linked(
self, request: LinkedRequest, context: ServicerContext
) -> LinkedResponse:
session = self.get_session(request.session_id, context)
session.linked(
request.node1_id,
request.node2_id,
request.iface1_id,
request.iface2_id,
request.linked,
)
return LinkedResponse()

View file

@ -192,6 +192,45 @@ class Session:
def use_ovs(self) -> bool: def use_ovs(self) -> bool:
return self.options.get_config("ovs") == "1" return self.options.get_config("ovs") == "1"
def linked(
self, node1_id: int, node2_id: int, iface1_id: int, iface2_id: int, linked: bool
) -> None:
"""
Links or unlinks wired core link interfaces from being connected to the same
bridge.
:param node1_id: first node in link
:param node2_id: second node in link
:param iface1_id: node1 interface
:param iface2_id: node2 interface
:param linked: True if interfaces should be connected, False for disconnected
:return: nothing
"""
node1 = self.get_node(node1_id, NodeBase)
node2 = self.get_node(node2_id, NodeBase)
logger.info(
"link node(%s):interface(%s) node(%s):interface(%s) linked(%s)",
node1.name,
iface1_id,
node2.name,
iface2_id,
linked,
)
iface1 = node1.get_iface(iface1_id)
iface2 = node2.get_iface(iface2_id)
core_link = self.link_manager.get_link(node1, iface1, node2, iface2)
if not core_link:
raise CoreError(
f"there is no link for node({node1.name}):interface({iface1_id}) "
f"node({node2.name}):interface({iface2_id})"
)
if linked:
core_link.ptp.attach(iface1)
core_link.ptp.attach(iface2)
else:
core_link.ptp.detach(iface1)
core_link.ptp.detach(iface2)
def add_link( def add_link(
self, self,
node1_id: int, node1_id: int,
@ -223,7 +262,14 @@ class Session:
node1 = self.get_node(node1_id, NodeBase) node1 = self.get_node(node1_id, NodeBase)
node2 = self.get_node(node2_id, NodeBase) node2 = self.get_node(node2_id, NodeBase)
# check for invalid linking # check for invalid linking
if isinstance(node1, WIRELESS_TYPE) and isinstance(node2, WIRELESS_TYPE): if (
isinstance(node1, WIRELESS_TYPE)
and isinstance(node2, WIRELESS_TYPE)
or isinstance(node1, WIRELESS_TYPE)
and not isinstance(node2, CoreNodeBase)
or not isinstance(node1, CoreNodeBase)
and isinstance(node2, WIRELESS_TYPE)
):
raise CoreError(f"cannot link node({type(node1)}) node({type(node2)})") raise CoreError(f"cannot link node({type(node1)}) node({type(node2)})")
# custom links # custom links
iface1 = None iface1 = None

View file

@ -61,6 +61,8 @@ service CoreApi {
} }
rpc DeleteLink (DeleteLinkRequest) returns (DeleteLinkResponse) { rpc DeleteLink (DeleteLinkRequest) returns (DeleteLinkResponse) {
} }
rpc Linked (LinkedRequest) returns (LinkedResponse) {
}
// mobility rpc // mobility rpc
rpc GetMobilityConfig (mobility.GetMobilityConfigRequest) returns (mobility.GetMobilityConfigResponse) { rpc GetMobilityConfig (mobility.GetMobilityConfigRequest) returns (mobility.GetMobilityConfigResponse) {
@ -684,3 +686,15 @@ message Server {
string name = 1; string name = 1;
string host = 2; string host = 2;
} }
message LinkedRequest {
int32 session_id = 1;
int32 node1_id = 2;
int32 node2_id = 3;
int32 iface1_id = 4;
int32 iface2_id = 5;
bool linked = 6;
}
message LinkedResponse {
}