daemon: abstracted out iface specific configuration generation and parsing to common utilities, to avoid duplicate logic and potential differences that may arise

This commit is contained in:
Blake Harnden 2020-09-02 09:44:45 -07:00
parent e775ad4c5d
commit a80fda11f5
7 changed files with 54 additions and 63 deletions

View file

@ -306,35 +306,6 @@ def get_links(node: NodeBase):
return links return links
def get_emane_model_id(node_id: int, iface_id: int) -> int:
"""
Get EMANE model id
:param node_id: node id
:param iface_id: interface id
:return: EMANE model id
"""
if iface_id >= 0:
return node_id * 1000 + iface_id
else:
return node_id
def parse_emane_model_id(_id: int) -> Tuple[int, int]:
"""
Parses EMANE model id to get true node id and interface id.
:param _id: id to parse
:return: node id and interface id
"""
iface_id = -1
node_id = _id
if _id >= 1000:
iface_id = _id % 1000
node_id = int(_id / 1000)
return node_id, iface_id
def convert_iface(iface_data: InterfaceData) -> core_pb2.Interface: def convert_iface(iface_data: InterfaceData) -> core_pb2.Interface:
return core_pb2.Interface( return core_pb2.Interface(
id=iface_data.id, id=iface_data.id,
@ -559,7 +530,8 @@ def get_emane_model_configs(session: Session) -> List[GetEmaneModelConfig]:
model = session.emane.models[model_name] model = session.emane.models[model_name]
current_config = session.emane.get_model_config(_id, model_name) current_config = session.emane.get_model_config(_id, model_name)
config = get_config_options(current_config, model) config = get_config_options(current_config, model)
node_id, iface_id = parse_emane_model_id(_id) node_id, iface_id = utils.parse_iface_config_id(_id)
iface_id = iface_id if iface_id is not None else -1
model_config = GetEmaneModelConfig( model_config = GetEmaneModelConfig(
node_id=node_id, model=model_name, iface_id=iface_id, config=config node_id=node_id, model=model_name, iface_id=iface_id, config=config
) )

View file

@ -56,12 +56,7 @@ from core.api.grpc.emane_pb2 import (
SetEmaneModelConfigResponse, SetEmaneModelConfigResponse,
) )
from core.api.grpc.events import EventStreamer from core.api.grpc.events import EventStreamer
from core.api.grpc.grpcutils import ( from core.api.grpc.grpcutils import get_config_options, get_links, get_net_stats
get_config_options,
get_emane_model_id,
get_links,
get_net_stats,
)
from core.api.grpc.mobility_pb2 import ( from core.api.grpc.mobility_pb2 import (
GetMobilityConfigRequest, GetMobilityConfigRequest,
GetMobilityConfigResponse, GetMobilityConfigResponse,
@ -249,7 +244,7 @@ class CoreGrpcServer(core_pb2_grpc.CoreApiServicer):
config = session.emane.get_configs() config = session.emane.get_configs()
config.update(request.emane_config) config.update(request.emane_config)
for config in request.emane_model_configs: for config in request.emane_model_configs:
_id = get_emane_model_id(config.node_id, config.iface_id) _id = utils.iface_config_id(config.node_id, config.iface_id)
session.emane.set_model_config(_id, config.model, config.config) session.emane.set_model_config(_id, config.model, config.config)
# wlan configs # wlan configs
@ -1441,7 +1436,7 @@ class CoreGrpcServer(core_pb2_grpc.CoreApiServicer):
model = session.emane.models.get(request.model) model = session.emane.models.get(request.model)
if not model: if not model:
raise CoreError(f"invalid emane model: {request.model}") raise CoreError(f"invalid emane model: {request.model}")
_id = get_emane_model_id(request.node_id, request.iface_id) _id = utils.iface_config_id(request.node_id, request.iface_id)
current_config = session.emane.get_model_config(_id, request.model) current_config = session.emane.get_model_config(_id, request.model)
config = get_config_options(current_config, model) config = get_config_options(current_config, model)
return GetEmaneModelConfigResponse(config=config) return GetEmaneModelConfigResponse(config=config)
@ -1460,7 +1455,7 @@ class CoreGrpcServer(core_pb2_grpc.CoreApiServicer):
logging.debug("set emane model config: %s", request) logging.debug("set emane model config: %s", request)
session = self.get_session(request.session_id, context) session = self.get_session(request.session_id, context)
model_config = request.emane_model_config model_config = request.emane_model_config
_id = get_emane_model_id(model_config.node_id, model_config.iface_id) _id = utils.iface_config_id(model_config.node_id, model_config.iface_id)
session.emane.set_model_config(_id, model_config.model, model_config.config) session.emane.set_model_config(_id, model_config.model, model_config.config)
return SetEmaneModelConfigResponse(result=True) return SetEmaneModelConfigResponse(result=True)

View file

@ -1331,9 +1331,7 @@ class CoreHandler(socketserver.BaseRequestHandler):
iface_id = config_data.iface_id iface_id = config_data.iface_id
values_str = config_data.data_values values_str = config_data.data_values
if iface_id is not None: node_id = utils.iface_config_id(node_id, iface_id)
node_id = node_id * 1000 + iface_id
logging.debug( logging.debug(
"received configure message for %s nodenum: %s", object_name, node_id "received configure message for %s nodenum: %s", object_name, node_id
) )
@ -1381,9 +1379,7 @@ class CoreHandler(socketserver.BaseRequestHandler):
iface_id = config_data.iface_id iface_id = config_data.iface_id
values_str = config_data.data_values values_str = config_data.data_values
if iface_id is not None: node_id = utils.iface_config_id(node_id, iface_id)
node_id = node_id * 1000 + iface_id
logging.debug( logging.debug(
"received configure message for %s nodenum: %s", object_name, node_id "received configure message for %s nodenum: %s", object_name, node_id
) )
@ -1413,9 +1409,7 @@ class CoreHandler(socketserver.BaseRequestHandler):
iface_id = config_data.iface_id iface_id = config_data.iface_id
values_str = config_data.data_values values_str = config_data.data_values
if iface_id is not None: node_id = utils.iface_config_id(node_id, iface_id)
node_id = node_id * 1000 + iface_id
logging.debug( logging.debug(
"received configure message for %s nodenum: %s", object_name, node_id "received configure message for %s nodenum: %s", object_name, node_id
) )

View file

@ -140,12 +140,12 @@ class EmaneManager(ModelManager):
# Adamson change: first check for iface config keyed by "node:iface.name" # Adamson change: first check for iface config keyed by "node:iface.name"
# (so that nodes w/ multiple interfaces of same conftype can have # (so that nodes w/ multiple interfaces of same conftype can have
# different configs for each separate interface) # different configs for each separate interface)
key = 1000 * iface.node.id config = None
# try to retrieve interface specific configuration
if iface.node_id is not None: if iface.node_id is not None:
key += iface.node_id key = utils.iface_config_id(iface.node.id, iface.node_id)
# try retrieve interface specific configuration, avoid getting defaults config = self.get_configs(node_id=key, config_type=model_name)
config = self.get_configs(node_id=key, config_type=model_name) # attempt to retrieve node specific config, when iface config is not present
# attempt to retrieve node specific conifg, when iface config is not present
if not config: if not config:
config = self.get_configs(node_id=iface.node.id, config_type=model_name) config = self.get_configs(node_id=iface.node.id, config_type=model_name)
# attempt to get emane net specific config, when node config is not present # attempt to get emane net specific config, when node config is not present

View file

@ -41,6 +41,7 @@ if TYPE_CHECKING:
T = TypeVar("T") T = TypeVar("T")
DEVNULL = open(os.devnull, "wb") DEVNULL = open(os.devnull, "wb")
IFACE_CONFIG_FACTOR: int = 1000
def execute_file( def execute_file(
@ -430,3 +431,34 @@ def random_mac() -> str:
value |= 0x00163E << 24 value |= 0x00163E << 24
mac = netaddr.EUI(value, dialect=netaddr.mac_unix_expanded) mac = netaddr.EUI(value, dialect=netaddr.mac_unix_expanded)
return str(mac) return str(mac)
def iface_config_id(node_id: int, iface_id: int = None) -> int:
"""
Common utility to generate a configuration id, in case an interface is being
targeted.
:param node_id: node for config id
:param iface_id: interface for config id
:return: generated config id when interface is present, node id otherwise
"""
if iface_id is not None and iface_id >= 0:
return node_id * IFACE_CONFIG_FACTOR + iface_id
else:
return node_id
def parse_iface_config_id(config_id: int) -> Tuple[int, Optional[int]]:
"""
Parses configuration id, that may be potentially derived from an interface for a
node.
:param config_id: configuration id to parse
:return:
"""
iface_id = None
node_id = config_id
if config_id >= IFACE_CONFIG_FACTOR:
iface_id = config_id % IFACE_CONFIG_FACTOR
node_id = config_id // IFACE_CONFIG_FACTOR
return node_id, iface_id

View file

@ -5,6 +5,7 @@ from lxml import etree
import core.nodes.base import core.nodes.base
import core.nodes.physical import core.nodes.physical
from core import utils
from core.emane.nodes import EmaneNet from core.emane.nodes import EmaneNet
from core.emulator.data import InterfaceData, LinkData, LinkOptions, NodeOptions from core.emulator.data import InterfaceData, LinkData, LinkOptions, NodeOptions
from core.emulator.enumerations import EventTypes, NodeTypes from core.emulator.enumerations import EventTypes, NodeTypes
@ -382,10 +383,7 @@ class CoreXmlWriter:
all_configs = self.session.emane.get_all_configs(node_id) all_configs = self.session.emane.get_all_configs(node_id)
if not all_configs: if not all_configs:
continue continue
iface_id = None node_id, iface_id = utils.parse_iface_config_id(node_id)
if node_id >= 1000:
iface_id = node_id % 1000
node_id = node_id // 1000
for model_name in all_configs: for model_name in all_configs:
config = all_configs[model_name] config = all_configs[model_name]
logging.debug( logging.debug(
@ -796,10 +794,8 @@ class CoreXmlReader:
logging.info( logging.info(
"reading emane configuration node(%s) model(%s)", node_id, model_name "reading emane configuration node(%s) model(%s)", node_id, model_name
) )
key = node_id node_id = utils.iface_config_id(node_id, iface_id)
if iface_id is not None: self.session.emane.set_model_config(node_id, model_name, configs)
key = node_id * 1000 + iface_id
self.session.emane.set_model_config(key, model_name, configs)
def read_mobility_configs(self) -> None: def read_mobility_configs(self) -> None:
mobility_configurations = self.scenario.find("mobility_configurations") mobility_configurations = self.scenario.find("mobility_configurations")

View file

@ -8,6 +8,7 @@ from xml.etree import ElementTree
import pytest import pytest
from core import utils
from core.emane.bypass import EmaneBypassModel from core.emane.bypass import EmaneBypassModel
from core.emane.commeffect import EmaneCommEffectModel from core.emane.commeffect import EmaneCommEffectModel
from core.emane.emanemodel import EmaneModel from core.emane.emanemodel import EmaneModel
@ -244,8 +245,9 @@ class TestEmane:
# set node specific conifg # set node specific conifg
datarate = "101" datarate = "101"
config_id = utils.iface_config_id(node1.id, iface1_data.id)
session.emane.set_model_config( session.emane.set_model_config(
node1.id * 1000, EmaneRfPipeModel.name, {"datarate": datarate} config_id, EmaneRfPipeModel.name, {"datarate": datarate}
) )
# instantiate session # instantiate session
@ -283,5 +285,5 @@ class TestEmane:
node = session.nodes[node_id] node = session.nodes[node_id]
links += node.links() links += node.links()
assert len(links) == 2 assert len(links) == 2
config = session.emane.get_model_config(node1.id * 1000, EmaneRfPipeModel.name) config = session.emane.get_model_config(config_id, EmaneRfPipeModel.name)
assert config["datarate"] == datarate assert config["datarate"] == datarate