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
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:
return core_pb2.Interface(
id=iface_data.id,
@ -559,7 +530,8 @@ def get_emane_model_configs(session: Session) -> List[GetEmaneModelConfig]:
model = session.emane.models[model_name]
current_config = session.emane.get_model_config(_id, model_name)
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(
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,
)
from core.api.grpc.events import EventStreamer
from core.api.grpc.grpcutils import (
get_config_options,
get_emane_model_id,
get_links,
get_net_stats,
)
from core.api.grpc.grpcutils import get_config_options, get_links, get_net_stats
from core.api.grpc.mobility_pb2 import (
GetMobilityConfigRequest,
GetMobilityConfigResponse,
@ -249,7 +244,7 @@ class CoreGrpcServer(core_pb2_grpc.CoreApiServicer):
config = session.emane.get_configs()
config.update(request.emane_config)
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)
# wlan configs
@ -1441,7 +1436,7 @@ class CoreGrpcServer(core_pb2_grpc.CoreApiServicer):
model = session.emane.models.get(request.model)
if not 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)
config = get_config_options(current_config, model)
return GetEmaneModelConfigResponse(config=config)
@ -1460,7 +1455,7 @@ class CoreGrpcServer(core_pb2_grpc.CoreApiServicer):
logging.debug("set emane model config: %s", request)
session = self.get_session(request.session_id, context)
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)
return SetEmaneModelConfigResponse(result=True)

View file

@ -1331,9 +1331,7 @@ class CoreHandler(socketserver.BaseRequestHandler):
iface_id = config_data.iface_id
values_str = config_data.data_values
if iface_id is not None:
node_id = node_id * 1000 + iface_id
node_id = utils.iface_config_id(node_id, iface_id)
logging.debug(
"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
values_str = config_data.data_values
if iface_id is not None:
node_id = node_id * 1000 + iface_id
node_id = utils.iface_config_id(node_id, iface_id)
logging.debug(
"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
values_str = config_data.data_values
if iface_id is not None:
node_id = node_id * 1000 + iface_id
node_id = utils.iface_config_id(node_id, iface_id)
logging.debug(
"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"
# (so that nodes w/ multiple interfaces of same conftype can have
# 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:
key += iface.node_id
# try retrieve interface specific configuration, avoid getting defaults
config = self.get_configs(node_id=key, config_type=model_name)
# attempt to retrieve node specific conifg, when iface config is not present
key = utils.iface_config_id(iface.node.id, iface.node_id)
config = self.get_configs(node_id=key, config_type=model_name)
# attempt to retrieve node specific config, when iface config is not present
if not config:
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

View file

@ -41,6 +41,7 @@ if TYPE_CHECKING:
T = TypeVar("T")
DEVNULL = open(os.devnull, "wb")
IFACE_CONFIG_FACTOR: int = 1000
def execute_file(
@ -430,3 +431,34 @@ def random_mac() -> str:
value |= 0x00163E << 24
mac = netaddr.EUI(value, dialect=netaddr.mac_unix_expanded)
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.physical
from core import utils
from core.emane.nodes import EmaneNet
from core.emulator.data import InterfaceData, LinkData, LinkOptions, NodeOptions
from core.emulator.enumerations import EventTypes, NodeTypes
@ -382,10 +383,7 @@ class CoreXmlWriter:
all_configs = self.session.emane.get_all_configs(node_id)
if not all_configs:
continue
iface_id = None
if node_id >= 1000:
iface_id = node_id % 1000
node_id = node_id // 1000
node_id, iface_id = utils.parse_iface_config_id(node_id)
for model_name in all_configs:
config = all_configs[model_name]
logging.debug(
@ -796,10 +794,8 @@ class CoreXmlReader:
logging.info(
"reading emane configuration node(%s) model(%s)", node_id, model_name
)
key = node_id
if iface_id is not None:
key = node_id * 1000 + iface_id
self.session.emane.set_model_config(key, model_name, configs)
node_id = utils.iface_config_id(node_id, iface_id)
self.session.emane.set_model_config(node_id, model_name, configs)
def read_mobility_configs(self) -> None:
mobility_configurations = self.scenario.find("mobility_configurations")

View file

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