Merge pull request #472 from coreemu/cleanup/interfaces-to-iface

interface and related functions renaming
This commit is contained in:
bharnden 2020-06-18 10:23:37 -07:00 committed by GitHub
commit 250bc6e1f5
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
96 changed files with 2388 additions and 2758 deletions

View file

@ -92,7 +92,7 @@ from core.api.grpc.wlan_pb2 import (
WlanLinkRequest,
WlanLinkResponse,
)
from core.emulator.emudata import IpPrefixes
from core.emulator.data import IpPrefixes
class InterfaceHelper:
@ -110,27 +110,27 @@ class InterfaceHelper:
"""
self.prefixes: IpPrefixes = IpPrefixes(ip4_prefix, ip6_prefix)
def create_interface(
self, node_id: int, interface_id: int, name: str = None, mac: str = None
def create_iface(
self, node_id: int, iface_id: int, name: str = None, mac: str = None
) -> core_pb2.Interface:
"""
Create an interface protobuf object.
:param node_id: node id to create interface for
:param interface_id: interface id
:param iface_id: interface id
:param name: name of interface
:param mac: mac address for interface
:return: interface protobuf
"""
interface_data = self.prefixes.gen_interface(node_id, name, mac)
iface_data = self.prefixes.gen_iface(node_id, name, mac)
return core_pb2.Interface(
id=interface_id,
name=interface_data.name,
ip4=interface_data.ip4,
ip4mask=interface_data.ip4_mask,
ip6=interface_data.ip6,
ip6mask=interface_data.ip6_mask,
mac=interface_data.mac,
id=iface_id,
name=iface_data.name,
ip4=iface_data.ip4,
ip4_mask=iface_data.ip4_mask,
ip6=iface_data.ip6,
ip6_mask=iface_data.ip6_mask,
mac=iface_data.mac,
)
@ -611,8 +611,8 @@ class CoreGrpcClient:
session_id: int,
node1_id: int,
node2_id: int,
interface1: core_pb2.Interface = None,
interface2: core_pb2.Interface = None,
iface1: core_pb2.Interface = None,
iface2: core_pb2.Interface = None,
options: core_pb2.LinkOptions = None,
) -> core_pb2.AddLinkResponse:
"""
@ -621,8 +621,8 @@ class CoreGrpcClient:
:param session_id: session id
:param node1_id: node one id
:param node2_id: node two id
:param interface1: node one interface data
:param interface2: node two interface data
:param iface1: node one interface data
:param iface2: node two interface data
:param options: options for link (jitter, bandwidth, etc)
:return: response with result of success or failure
:raises grpc.RpcError: when session or one of the nodes don't exist
@ -631,8 +631,8 @@ class CoreGrpcClient:
node1_id=node1_id,
node2_id=node2_id,
type=core_pb2.LinkType.WIRED,
interface1=interface1,
interface2=interface2,
iface1=iface1,
iface2=iface2,
options=options,
)
request = core_pb2.AddLinkRequest(session_id=session_id, link=link)
@ -644,8 +644,8 @@ class CoreGrpcClient:
node1_id: int,
node2_id: int,
options: core_pb2.LinkOptions,
interface1_id: int = None,
interface2_id: int = None,
iface1_id: int = None,
iface2_id: int = None,
) -> core_pb2.EditLinkResponse:
"""
Edit a link between nodes.
@ -654,8 +654,8 @@ class CoreGrpcClient:
:param node1_id: node one id
:param node2_id: node two id
:param options: options for link (jitter, bandwidth, etc)
:param interface1_id: node one interface id
:param interface2_id: node two interface id
:param iface1_id: node one interface id
:param iface2_id: node two interface id
:return: response with result of success or failure
:raises grpc.RpcError: when session or one of the nodes don't exist
"""
@ -664,8 +664,8 @@ class CoreGrpcClient:
node1_id=node1_id,
node2_id=node2_id,
options=options,
interface1_id=interface1_id,
interface2_id=interface2_id,
iface1_id=iface1_id,
iface2_id=iface2_id,
)
return self.stub.EditLink(request)
@ -674,8 +674,8 @@ class CoreGrpcClient:
session_id: int,
node1_id: int,
node2_id: int,
interface1_id: int = None,
interface2_id: int = None,
iface1_id: int = None,
iface2_id: int = None,
) -> core_pb2.DeleteLinkResponse:
"""
Delete a link between nodes.
@ -683,8 +683,8 @@ class CoreGrpcClient:
:param session_id: session id
:param node1_id: node one id
:param node2_id: node two id
:param interface1_id: node one interface id
:param interface2_id: node two interface id
:param iface1_id: node one interface id
:param iface2_id: node two interface id
:return: response with result of success or failure
:raises grpc.RpcError: when session doesn't exist
"""
@ -692,8 +692,8 @@ class CoreGrpcClient:
session_id=session_id,
node1_id=node1_id,
node2_id=node2_id,
interface1_id=interface1_id,
interface2_id=interface2_id,
iface1_id=iface1_id,
iface2_id=iface2_id,
)
return self.stub.DeleteLink(request)
@ -1028,7 +1028,7 @@ class CoreGrpcClient:
return self.stub.GetEmaneModels(request)
def get_emane_model_config(
self, session_id: int, node_id: int, model: str, interface_id: int = -1
self, session_id: int, node_id: int, model: str, iface_id: int = -1
) -> GetEmaneModelConfigResponse:
"""
Get emane model configuration for a node or a node's interface.
@ -1036,12 +1036,12 @@ class CoreGrpcClient:
:param session_id: session id
:param node_id: node id
:param model: emane model name
:param interface_id: node interface id
:param iface_id: node interface id
:return: response with a list of configuration groups
:raises grpc.RpcError: when session doesn't exist
"""
request = GetEmaneModelConfigRequest(
session_id=session_id, node_id=node_id, model=model, interface=interface_id
session_id=session_id, node_id=node_id, model=model, iface_id=iface_id
)
return self.stub.GetEmaneModelConfig(request)
@ -1051,7 +1051,7 @@ class CoreGrpcClient:
node_id: int,
model: str,
config: Dict[str, str] = None,
interface_id: int = -1,
iface_id: int = -1,
) -> SetEmaneModelConfigResponse:
"""
Set emane model configuration for a node or a node's interface.
@ -1060,12 +1060,12 @@ class CoreGrpcClient:
:param node_id: node id
:param model: emane model name
:param config: emane model configuration
:param interface_id: node interface id
:param iface_id: node interface id
:return: response with result of success or failure
:raises grpc.RpcError: when session doesn't exist
"""
model_config = EmaneModelConfig(
node_id=node_id, model=model, config=config, interface_id=interface_id
node_id=node_id, model=model, config=config, iface_id=iface_id
)
request = SetEmaneModelConfigRequest(
session_id=session_id, emane_model_config=model_config
@ -1128,7 +1128,7 @@ class CoreGrpcClient:
)
return self.stub.EmaneLink(request)
def get_interfaces(self) -> core_pb2.GetInterfacesResponse:
def get_ifaces(self) -> core_pb2.GetInterfacesResponse:
"""
Retrieves a list of interfaces available on the host machine that are not
a part of a CORE session.

View file

@ -15,24 +15,28 @@ from core.emulator.data import (
from core.emulator.session import Session
def handle_node_event(event: NodeData) -> core_pb2.NodeEvent:
def handle_node_event(node_data: NodeData) -> core_pb2.NodeEvent:
"""
Handle node event when there is a node event
:param event: node data
:param node_data: node data
:return: node event that contains node id, name, model, position, and services
"""
position = core_pb2.Position(x=event.x_position, y=event.y_position)
geo = core_pb2.Geo(lat=event.latitude, lon=event.longitude, alt=event.altitude)
node = node_data.node
x, y, _ = node.position.get()
position = core_pb2.Position(x=x, y=y)
lon, lat, alt = node.position.get_geo()
geo = core_pb2.Geo(lon=lon, lat=lat, alt=alt)
services = [x.name for x in node.services]
node_proto = core_pb2.Node(
id=event.id,
name=event.name,
model=event.model,
id=node.id,
name=node.name,
model=node.type,
position=position,
geo=geo,
services=event.services,
services=services,
)
return core_pb2.NodeEvent(node=node_proto, source=event.source)
return core_pb2.NodeEvent(node=node_proto, source=node_data.source)
def handle_link_event(event: LinkData) -> core_pb2.LinkEvent:
@ -82,7 +86,7 @@ def handle_config_event(event: ConfigData) -> core_pb2.ConfigEvent:
data_values=event.data_values,
possible_values=event.possible_values,
groups=event.groups,
interface=event.interface_number,
iface_id=event.iface_id,
network_id=event.network_id,
opaque=event.opaque,
data_types=event.data_types,

View file

@ -11,8 +11,7 @@ from core.api.grpc import common_pb2, core_pb2
from core.api.grpc.services_pb2 import NodeServiceData, ServiceConfig
from core.config import ConfigurableOptions
from core.emane.nodes import EmaneNet
from core.emulator.data import LinkData
from core.emulator.emudata import InterfaceData, LinkOptions, NodeOptions
from core.emulator.data import InterfaceData, LinkData, LinkOptions, NodeOptions
from core.emulator.enumerations import LinkTypes, NodeTypes
from core.emulator.session import Session
from core.nodes.base import CoreNode, NodeBase
@ -35,7 +34,6 @@ def add_node_data(node_proto: core_pb2.Node) -> Tuple[NodeTypes, int, NodeOption
name=node_proto.name,
model=node_proto.model,
icon=node_proto.icon,
opaque=node_proto.opaque,
image=node_proto.image,
services=node_proto.services,
config_services=node_proto.config_services,
@ -52,58 +50,57 @@ def add_node_data(node_proto: core_pb2.Node) -> Tuple[NodeTypes, int, NodeOption
return _type, _id, options
def link_interface(interface_proto: core_pb2.Interface) -> InterfaceData:
def link_iface(iface_proto: core_pb2.Interface) -> InterfaceData:
"""
Create interface data from interface proto.
:param interface_proto: interface proto
:param iface_proto: interface proto
:return: interface data
"""
interface_data = None
if interface_proto:
name = interface_proto.name if interface_proto.name else None
mac = interface_proto.mac if interface_proto.mac else None
ip4 = interface_proto.ip4 if interface_proto.ip4 else None
ip6 = interface_proto.ip6 if interface_proto.ip6 else None
interface_data = InterfaceData(
id=interface_proto.id,
iface_data = None
if iface_proto:
name = iface_proto.name if iface_proto.name else None
mac = iface_proto.mac if iface_proto.mac else None
ip4 = iface_proto.ip4 if iface_proto.ip4 else None
ip6 = iface_proto.ip6 if iface_proto.ip6 else None
iface_data = InterfaceData(
id=iface_proto.id,
name=name,
mac=mac,
ip4=ip4,
ip4_mask=interface_proto.ip4mask,
ip4_mask=iface_proto.ip4_mask,
ip6=ip6,
ip6_mask=interface_proto.ip6mask,
ip6_mask=iface_proto.ip6_mask,
)
return interface_data
return iface_data
def add_link_data(
link_proto: core_pb2.Link
) -> Tuple[InterfaceData, InterfaceData, LinkOptions]:
) -> Tuple[InterfaceData, InterfaceData, LinkOptions, LinkTypes]:
"""
Convert link proto to link interfaces and options data.
:param link_proto: link proto
:return: link interfaces and options
"""
interface1_data = link_interface(link_proto.interface1)
interface2_data = link_interface(link_proto.interface2)
iface1_data = link_iface(link_proto.iface1)
iface2_data = link_iface(link_proto.iface2)
link_type = LinkTypes(link_proto.type)
options = LinkOptions(type=link_type)
options_data = link_proto.options
if options_data:
options.delay = options_data.delay
options.bandwidth = options_data.bandwidth
options.loss = options_data.loss
options.dup = options_data.dup
options.jitter = options_data.jitter
options.mer = options_data.mer
options.burst = options_data.burst
options.mburst = options_data.mburst
options.unidirectional = options_data.unidirectional
options.key = options_data.key
options.opaque = options_data.opaque
return interface1_data, interface2_data, options
options = LinkOptions()
options_proto = link_proto.options
if options_proto:
options.delay = options_proto.delay
options.bandwidth = options_proto.bandwidth
options.loss = options_proto.loss
options.dup = options_proto.dup
options.jitter = options_proto.jitter
options.mer = options_proto.mer
options.burst = options_proto.burst
options.mburst = options_proto.mburst
options.unidirectional = options_proto.unidirectional
options.key = options_proto.key
return iface1_data, iface2_data, options, link_type
def create_nodes(
@ -143,8 +140,8 @@ def create_links(
for link_proto in link_protos:
node1_id = link_proto.node1_id
node2_id = link_proto.node2_id
interface1, interface2, options = add_link_data(link_proto)
args = (node1_id, node2_id, interface1, interface2, options)
iface1, iface2, options, link_type = add_link_data(link_proto)
args = (node1_id, node2_id, iface1, iface2, options, link_type)
funcs.append((session.add_link, args, {}))
start = time.monotonic()
results, exceptions = utils.threadpool(funcs)
@ -167,8 +164,8 @@ def edit_links(
for link_proto in link_protos:
node1_id = link_proto.node1_id
node2_id = link_proto.node2_id
interface1, interface2, options = add_link_data(link_proto)
args = (node1_id, node2_id, interface1.id, interface2.id, options)
iface1, iface2, options, link_type = add_link_data(link_proto)
args = (node1_id, node2_id, iface1.id, iface2.id, options, link_type)
funcs.append((session.update_link, args, {}))
start = time.monotonic()
results, exceptions = utils.threadpool(funcs)
@ -279,16 +276,16 @@ def get_links(node: NodeBase):
return links
def get_emane_model_id(node_id: int, interface_id: int) -> int:
def get_emane_model_id(node_id: int, iface_id: int) -> int:
"""
Get EMANE model id
:param node_id: node id
:param interface_id: interface id
:param iface_id: interface id
:return: EMANE model id
"""
if interface_id >= 0:
return node_id * 1000 + interface_id
if iface_id >= 0:
return node_id * 1000 + iface_id
else:
return node_id
@ -300,12 +297,39 @@ def parse_emane_model_id(_id: int) -> Tuple[int, int]:
:param _id: id to parse
:return: node id and interface id
"""
interface = -1
iface_id = -1
node_id = _id
if _id >= 1000:
interface = _id % 1000
iface_id = _id % 1000
node_id = int(_id / 1000)
return node_id, interface
return node_id, iface_id
def convert_iface(iface_data: InterfaceData) -> core_pb2.Interface:
return core_pb2.Interface(
id=iface_data.id,
name=iface_data.name,
mac=iface_data.mac,
ip4=iface_data.ip4,
ip4_mask=iface_data.ip4_mask,
ip6=iface_data.ip6,
ip6_mask=iface_data.ip6_mask,
)
def convert_link_options(options_data: LinkOptions) -> core_pb2.LinkOptions:
return core_pb2.LinkOptions(
jitter=options_data.jitter,
key=options_data.key,
mburst=options_data.mburst,
mer=options_data.mer,
loss=options_data.loss,
bandwidth=options_data.bandwidth,
burst=options_data.burst,
delay=options_data.delay,
dup=options_data.dup,
unidirectional=options_data.unidirectional,
)
def convert_link(link_data: LinkData) -> core_pb2.Link:
@ -315,47 +339,19 @@ def convert_link(link_data: LinkData) -> core_pb2.Link:
:param link_data: link to convert
:return: core protobuf Link
"""
interface1 = None
if link_data.interface1_id is not None:
interface1 = core_pb2.Interface(
id=link_data.interface1_id,
name=link_data.interface1_name,
mac=convert_value(link_data.interface1_mac),
ip4=convert_value(link_data.interface1_ip4),
ip4mask=link_data.interface1_ip4_mask,
ip6=convert_value(link_data.interface1_ip6),
ip6mask=link_data.interface1_ip6_mask,
)
interface2 = None
if link_data.interface2_id is not None:
interface2 = core_pb2.Interface(
id=link_data.interface2_id,
name=link_data.interface2_name,
mac=convert_value(link_data.interface2_mac),
ip4=convert_value(link_data.interface2_ip4),
ip4mask=link_data.interface2_ip4_mask,
ip6=convert_value(link_data.interface2_ip6),
ip6mask=link_data.interface2_ip6_mask,
)
options = core_pb2.LinkOptions(
opaque=link_data.opaque,
jitter=link_data.jitter,
key=link_data.key,
mburst=link_data.mburst,
mer=link_data.mer,
loss=link_data.loss,
bandwidth=link_data.bandwidth,
burst=link_data.burst,
delay=link_data.delay,
dup=link_data.dup,
unidirectional=link_data.unidirectional,
)
iface1 = None
if link_data.iface1 is not None:
iface1 = convert_iface(link_data.iface1)
iface2 = None
if link_data.iface2 is not None:
iface2 = convert_iface(link_data.iface2)
options = convert_link_options(link_data.options)
return core_pb2.Link(
type=link_data.link_type.value,
type=link_data.type.value,
node1_id=link_data.node1_id,
node2_id=link_data.node2_id,
interface1=interface1,
interface2=interface2,
iface1=iface1,
iface2=iface2,
options=options,
network_id=link_data.network_id,
label=link_data.label,
@ -440,58 +436,58 @@ def get_service_configuration(service: CoreService) -> NodeServiceData:
)
def interface_to_proto(interface: CoreInterface) -> core_pb2.Interface:
def iface_to_proto(iface: CoreInterface) -> core_pb2.Interface:
"""
Convenience for converting a core interface to the protobuf representation.
:param interface: interface to convert
:param iface: interface to convert
:return: interface proto
"""
net_id = None
if interface.net:
net_id = interface.net.id
if iface.net:
net_id = iface.net.id
ip4 = None
ip4mask = None
ip4_mask = None
ip6 = None
ip6mask = None
for addr in interface.addrlist:
ip6_mask = None
for addr in iface.addrlist:
network = netaddr.IPNetwork(addr)
mask = network.prefixlen
ip = str(network.ip)
if netaddr.valid_ipv4(ip) and not ip4:
ip4 = ip
ip4mask = mask
ip4_mask = mask
elif netaddr.valid_ipv6(ip) and not ip6:
ip6 = ip
ip6mask = mask
ip6_mask = mask
return core_pb2.Interface(
id=interface.netindex,
netid=net_id,
name=interface.name,
mac=str(interface.hwaddr),
mtu=interface.mtu,
flowid=interface.flow_id,
id=iface.node_id,
net_id=net_id,
name=iface.name,
mac=iface.mac,
mtu=iface.mtu,
flow_id=iface.flow_id,
ip4=ip4,
ip4mask=ip4mask,
ip4_mask=ip4_mask,
ip6=ip6,
ip6mask=ip6mask,
ip6_mask=ip6_mask,
)
def get_nem_id(node: CoreNode, netif_id: int, context: ServicerContext) -> int:
def get_nem_id(node: CoreNode, iface_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 iface_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}"
iface = node.ifaces.get(iface_id)
if not iface:
message = f"{node.name} missing interface {iface_id}"
context.abort(grpc.StatusCode.NOT_FOUND, message)
net = netif.net
net = iface.net
if not isinstance(net, EmaneNet):
message = f"{node.name} interface {netif_id} is not an EMANE network"
message = f"{node.name} interface {iface_id} is not an EMANE network"
context.abort(grpc.StatusCode.INVALID_ARGUMENT, message)
return net.getnemid(netif)
return net.getnemid(iface)

View file

@ -108,8 +108,7 @@ from core.api.grpc.wlan_pb2 import (
WlanLinkResponse,
)
from core.emulator.coreemu import CoreEmu
from core.emulator.data import LinkData
from core.emulator.emudata import LinkOptions, NodeOptions
from core.emulator.data import LinkData, LinkOptions, NodeOptions
from core.emulator.enumerations import EventTypes, LinkTypes, MessageFlags
from core.emulator.session import NT, Session
from core.errors import CoreCommandError, CoreError
@ -246,7 +245,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.interface_id)
_id = get_emane_model_id(config.node_id, config.iface_id)
session.emane.set_model_config(_id, config.model, config.config)
# wlan configs
@ -625,16 +624,14 @@ class CoreGrpcServer(core_pb2_grpc.CoreApiServicer):
key = key.split(".")
node_id = _INTERFACE_REGEX.search(key[0]).group("node")
node_id = int(node_id, base=16)
interface_id = int(key[1], base=16)
iface_id = int(key[1], base=16)
session_id = int(key[2], base=16)
if session.id != session_id:
continue
interface_throughput = (
throughputs_event.interface_throughputs.add()
)
interface_throughput.node_id = node_id
interface_throughput.interface_id = interface_id
interface_throughput.throughput = throughput
iface_throughput = throughputs_event.iface_throughputs.add()
iface_throughput.node_id = node_id
iface_throughput.iface_id = iface_id
iface_throughput.throughput = throughput
elif key.startswith("b."):
try:
key = key.split(".")
@ -686,13 +683,13 @@ class CoreGrpcServer(core_pb2_grpc.CoreApiServicer):
logging.debug("get node: %s", request)
session = self.get_session(request.session_id, context)
node = self.get_node(session, request.node_id, context, NodeBase)
interfaces = []
for interface_id in node._netif:
interface = node._netif[interface_id]
interface_proto = grpcutils.interface_to_proto(interface)
interfaces.append(interface_proto)
ifaces = []
for iface_id in node.ifaces:
iface = node.ifaces[iface_id]
iface_proto = grpcutils.iface_to_proto(iface)
ifaces.append(iface_proto)
node_proto = grpcutils.get_node_proto(session, node)
return core_pb2.GetNodeResponse(node=node_proto, interfaces=interfaces)
return core_pb2.GetNodeResponse(node=node_proto, ifaces=ifaces)
def MoveNodes(
self,
@ -850,18 +847,20 @@ class CoreGrpcServer(core_pb2_grpc.CoreApiServicer):
node2_id = request.link.node2_id
self.get_node(session, node1_id, context, NodeBase)
self.get_node(session, node2_id, context, NodeBase)
interface1, interface2, options = grpcutils.add_link_data(request.link)
node1_interface, node2_interface = session.add_link(
node1_id, node2_id, interface1, interface2, options=options
iface1_data, iface2_data, options, link_type = grpcutils.add_link_data(
request.link
)
interface1_proto = None
interface2_proto = None
if node1_interface:
interface1_proto = grpcutils.interface_to_proto(node1_interface)
if node2_interface:
interface2_proto = grpcutils.interface_to_proto(node2_interface)
node1_iface, node2_iface = session.add_link(
node1_id, node2_id, iface1_data, iface2_data, options, link_type
)
iface1_proto = None
iface2_proto = None
if node1_iface:
iface1_proto = grpcutils.iface_to_proto(node1_iface)
if node2_iface:
iface2_proto = grpcutils.iface_to_proto(node2_iface)
return core_pb2.AddLinkResponse(
result=True, interface1=interface1_proto, interface2=interface2_proto
result=True, iface1=iface1_proto, iface2=iface2_proto
)
def EditLink(
@ -878,23 +877,22 @@ class CoreGrpcServer(core_pb2_grpc.CoreApiServicer):
session = self.get_session(request.session_id, context)
node1_id = request.node1_id
node2_id = request.node2_id
interface1_id = request.interface1_id
interface2_id = request.interface2_id
options_data = request.options
iface1_id = request.iface1_id
iface2_id = request.iface2_id
options_proto = request.options
options = LinkOptions(
delay=options_data.delay,
bandwidth=options_data.bandwidth,
loss=options_data.loss,
dup=options_data.dup,
jitter=options_data.jitter,
mer=options_data.mer,
burst=options_data.burst,
mburst=options_data.mburst,
unidirectional=options_data.unidirectional,
key=options_data.key,
opaque=options_data.opaque,
delay=options_proto.delay,
bandwidth=options_proto.bandwidth,
loss=options_proto.loss,
dup=options_proto.dup,
jitter=options_proto.jitter,
mer=options_proto.mer,
burst=options_proto.burst,
mburst=options_proto.mburst,
unidirectional=options_proto.unidirectional,
key=options_proto.key,
)
session.update_link(node1_id, node2_id, interface1_id, interface2_id, options)
session.update_link(node1_id, node2_id, iface1_id, iface2_id, options)
return core_pb2.EditLinkResponse(result=True)
def DeleteLink(
@ -911,9 +909,9 @@ class CoreGrpcServer(core_pb2_grpc.CoreApiServicer):
session = self.get_session(request.session_id, context)
node1_id = request.node1_id
node2_id = request.node2_id
interface1_id = request.interface1_id
interface2_id = request.interface2_id
session.delete_link(node1_id, node2_id, interface1_id, interface2_id)
iface1_id = request.iface1_id
iface2_id = request.iface2_id
session.delete_link(node1_id, node2_id, iface1_id, iface2_id)
return core_pb2.DeleteLinkResponse(result=True)
def GetHooks(
@ -1371,7 +1369,7 @@ class CoreGrpcServer(core_pb2_grpc.CoreApiServicer):
logging.debug("get emane model config: %s", request)
session = self.get_session(request.session_id, context)
model = session.emane.models[request.model]
_id = get_emane_model_id(request.node_id, request.interface)
_id = get_emane_model_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)
@ -1390,7 +1388,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.interface_id)
_id = get_emane_model_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)
@ -1419,12 +1417,9 @@ class CoreGrpcServer(core_pb2_grpc.CoreApiServicer):
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, interface = grpcutils.parse_emane_model_id(_id)
node_id, iface_id = grpcutils.parse_emane_model_id(_id)
model_config = GetEmaneModelConfigsResponse.ModelConfig(
node_id=node_id,
model=model_name,
interface=interface,
config=config,
node_id=node_id, model=model_name, iface_id=iface_id, config=config
)
configs.append(model_config)
return GetEmaneModelConfigsResponse(configs=configs)
@ -1489,16 +1484,12 @@ class CoreGrpcServer(core_pb2_grpc.CoreApiServicer):
:param context: context object
:return: get-interfaces response that has all the system's interfaces
"""
interfaces = []
for interface in os.listdir("/sys/class/net"):
if (
interface.startswith("b.")
or interface.startswith("veth")
or interface == "lo"
):
ifaces = []
for iface in os.listdir("/sys/class/net"):
if iface.startswith("b.") or iface.startswith("veth") or iface == "lo":
continue
interfaces.append(interface)
return core_pb2.GetInterfacesResponse(interfaces=interfaces)
ifaces.append(iface)
return core_pb2.GetInterfacesResponse(ifaces=ifaces)
def EmaneLink(
self, request: EmaneLinkRequest, context: ServicerContext
@ -1513,16 +1504,16 @@ class CoreGrpcServer(core_pb2_grpc.CoreApiServicer):
logging.debug("emane link: %s", request)
session = self.get_session(request.session_id, context)
nem1 = request.nem1
emane1, netif = session.emane.nemlookup(nem1)
if not emane1 or not netif:
emane1, iface = session.emane.nemlookup(nem1)
if not emane1 or not iface:
context.abort(grpc.StatusCode.NOT_FOUND, f"nem one {nem1} not found")
node1 = netif.node
node1 = iface.node
nem2 = request.nem2
emane2, netif = session.emane.nemlookup(nem2)
if not emane2 or not netif:
emane2, iface = session.emane.nemlookup(nem2)
if not emane2 or not iface:
context.abort(grpc.StatusCode.NOT_FOUND, f"nem two {nem2} not found")
node2 = netif.node
node2 = iface.node
if emane1.id == emane2.id:
if request.linked:
@ -1532,7 +1523,7 @@ class CoreGrpcServer(core_pb2_grpc.CoreApiServicer):
color = session.get_link_color(emane1.id)
link = LinkData(
message_type=flag,
link_type=LinkTypes.WIRELESS,
type=LinkTypes.WIRELESS,
node1_id=node1.id,
node2_id=node2.id,
network_id=emane1.id,
@ -1734,21 +1725,19 @@ class CoreGrpcServer(core_pb2_grpc.CoreApiServicer):
)
node1 = self.get_node(session, request.node1_id, context, CoreNode)
node2 = self.get_node(session, request.node2_id, context, CoreNode)
node1_interface, node2_interface = None, None
for net, interface1, interface2 in node1.commonnets(node2):
node1_iface, node2_iface = None, None
for net, iface1, iface2 in node1.commonnets(node2):
if net == wlan:
node1_interface = interface1
node2_interface = interface2
node1_iface = iface1
node2_iface = iface2
break
result = False
if node1_interface and node2_interface:
if node1_iface and node2_iface:
if request.linked:
wlan.link(node1_interface, node2_interface)
wlan.link(node1_iface, node2_iface)
else:
wlan.unlink(node1_interface, node2_interface)
wlan.model.sendlinkmsg(
node1_interface, node2_interface, unlink=not request.linked
)
wlan.unlink(node1_iface, node2_iface)
wlan.model.sendlinkmsg(node1_iface, node2_iface, unlink=not request.linked)
result = True
return WlanLinkResponse(result=result)
@ -1760,8 +1749,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.interface1_id, context)
nem1 = grpcutils.get_nem_id(node1, request.iface1_id, context)
node2 = self.get_node(session, request.node2_id, context, CoreNode)
nem2 = grpcutils.get_nem_id(node2, request.interface2_id, context)
nem2 = grpcutils.get_nem_id(node2, request.iface2_id, context)
session.emane.publish_pathloss(nem1, nem2, request.rx1, request.rx2)
return EmanePathlossesResponse()

View file

@ -508,18 +508,18 @@ class CoreLinkTlv(CoreTlv):
LinkTlvs.EMULATION_ID.value: CoreTlvDataUint32,
LinkTlvs.NETWORK_ID.value: CoreTlvDataUint32,
LinkTlvs.KEY.value: CoreTlvDataUint32,
LinkTlvs.INTERFACE1_NUMBER.value: CoreTlvDataUint16,
LinkTlvs.INTERFACE1_IP4.value: CoreTlvDataIpv4Addr,
LinkTlvs.INTERFACE1_IP4_MASK.value: CoreTlvDataUint16,
LinkTlvs.INTERFACE1_MAC.value: CoreTlvDataMacAddr,
LinkTlvs.INTERFACE1_IP6.value: CoreTlvDataIPv6Addr,
LinkTlvs.INTERFACE1_IP6_MASK.value: CoreTlvDataUint16,
LinkTlvs.INTERFACE2_NUMBER.value: CoreTlvDataUint16,
LinkTlvs.INTERFACE2_IP4.value: CoreTlvDataIpv4Addr,
LinkTlvs.INTERFACE2_IP4_MASK.value: CoreTlvDataUint16,
LinkTlvs.INTERFACE2_MAC.value: CoreTlvDataMacAddr,
LinkTlvs.INTERFACE2_IP6.value: CoreTlvDataIPv6Addr,
LinkTlvs.INTERFACE2_IP6_MASK.value: CoreTlvDataUint16,
LinkTlvs.IFACE1_NUMBER.value: CoreTlvDataUint16,
LinkTlvs.IFACE1_IP4.value: CoreTlvDataIpv4Addr,
LinkTlvs.IFACE1_IP4_MASK.value: CoreTlvDataUint16,
LinkTlvs.IFACE1_MAC.value: CoreTlvDataMacAddr,
LinkTlvs.IFACE1_IP6.value: CoreTlvDataIPv6Addr,
LinkTlvs.IFACE1_IP6_MASK.value: CoreTlvDataUint16,
LinkTlvs.IFACE2_NUMBER.value: CoreTlvDataUint16,
LinkTlvs.IFACE2_IP4.value: CoreTlvDataIpv4Addr,
LinkTlvs.IFACE2_IP4_MASK.value: CoreTlvDataUint16,
LinkTlvs.IFACE2_MAC.value: CoreTlvDataMacAddr,
LinkTlvs.IFACE2_IP6.value: CoreTlvDataIPv6Addr,
LinkTlvs.IFACE2_IP6_MASK.value: CoreTlvDataUint16,
LinkTlvs.INTERFACE1_NAME.value: CoreTlvDataString,
LinkTlvs.INTERFACE2_NAME.value: CoreTlvDataString,
LinkTlvs.OPAQUE.value: CoreTlvDataString,
@ -577,7 +577,7 @@ class CoreConfigTlv(CoreTlv):
ConfigTlvs.POSSIBLE_VALUES.value: CoreTlvDataString,
ConfigTlvs.GROUPS.value: CoreTlvDataString,
ConfigTlvs.SESSION.value: CoreTlvDataString,
ConfigTlvs.INTERFACE_NUMBER.value: CoreTlvDataUint16,
ConfigTlvs.IFACE_ID.value: CoreTlvDataUint16,
ConfigTlvs.NETWORK_ID.value: CoreTlvDataUint32,
ConfigTlvs.OPAQUE.value: CoreTlvDataString,
}

View file

@ -29,8 +29,15 @@ from core.api.tlv.enumerations import (
NodeTlvs,
SessionTlvs,
)
from core.emulator.data import ConfigData, EventData, ExceptionData, FileData
from core.emulator.emudata import InterfaceData, LinkOptions, NodeOptions
from core.emulator.data import (
ConfigData,
EventData,
ExceptionData,
FileData,
InterfaceData,
LinkOptions,
NodeOptions,
)
from core.emulator.enumerations import (
ConfigDataTypes,
EventTypes,
@ -71,7 +78,7 @@ class CoreHandler(socketserver.BaseRequestHandler):
MessageTypes.REGISTER.value: self.handle_register_message,
MessageTypes.CONFIG.value: self.handle_config_message,
MessageTypes.FILE.value: self.handle_file_message,
MessageTypes.INTERFACE.value: self.handle_interface_message,
MessageTypes.INTERFACE.value: self.handle_iface_message,
MessageTypes.EVENT.value: self.handle_event_message,
MessageTypes.SESSION.value: self.handle_session_message,
}
@ -322,7 +329,6 @@ class CoreHandler(socketserver.BaseRequestHandler):
"""
logging.debug("handling broadcast node: %s", node_data)
message = dataconversion.convert_node(node_data)
try:
self.sendall(message)
except IOError:
@ -336,46 +342,49 @@ class CoreHandler(socketserver.BaseRequestHandler):
:return: nothing
"""
logging.debug("handling broadcast link: %s", link_data)
options_data = link_data.options
loss = ""
if link_data.loss is not None:
loss = str(link_data.loss)
if options_data.loss is not None:
loss = str(options_data.loss)
dup = ""
if link_data.dup is not None:
dup = str(link_data.dup)
if options_data.dup is not None:
dup = str(options_data.dup)
iface1 = link_data.iface1
if iface1 is None:
iface1 = InterfaceData()
iface2 = link_data.iface2
if iface2 is None:
iface2 = InterfaceData()
tlv_data = structutils.pack_values(
coreapi.CoreLinkTlv,
[
(LinkTlvs.N1_NUMBER, link_data.node1_id),
(LinkTlvs.N2_NUMBER, link_data.node2_id),
(LinkTlvs.DELAY, link_data.delay),
(LinkTlvs.BANDWIDTH, link_data.bandwidth),
(LinkTlvs.DELAY, options_data.delay),
(LinkTlvs.BANDWIDTH, options_data.bandwidth),
(LinkTlvs.LOSS, loss),
(LinkTlvs.DUP, dup),
(LinkTlvs.JITTER, link_data.jitter),
(LinkTlvs.MER, link_data.mer),
(LinkTlvs.BURST, link_data.burst),
(LinkTlvs.SESSION, link_data.session),
(LinkTlvs.MBURST, link_data.mburst),
(LinkTlvs.TYPE, link_data.link_type.value),
(LinkTlvs.GUI_ATTRIBUTES, link_data.gui_attributes),
(LinkTlvs.UNIDIRECTIONAL, link_data.unidirectional),
(LinkTlvs.EMULATION_ID, link_data.emulation_id),
(LinkTlvs.JITTER, options_data.jitter),
(LinkTlvs.MER, options_data.mer),
(LinkTlvs.BURST, options_data.burst),
(LinkTlvs.MBURST, options_data.mburst),
(LinkTlvs.TYPE, link_data.type.value),
(LinkTlvs.UNIDIRECTIONAL, options_data.unidirectional),
(LinkTlvs.NETWORK_ID, link_data.network_id),
(LinkTlvs.KEY, link_data.key),
(LinkTlvs.INTERFACE1_NUMBER, link_data.interface1_id),
(LinkTlvs.INTERFACE1_IP4, link_data.interface1_ip4),
(LinkTlvs.INTERFACE1_IP4_MASK, link_data.interface1_ip4_mask),
(LinkTlvs.INTERFACE1_MAC, link_data.interface1_mac),
(LinkTlvs.INTERFACE1_IP6, link_data.interface1_ip6),
(LinkTlvs.INTERFACE1_IP6_MASK, link_data.interface1_ip6_mask),
(LinkTlvs.INTERFACE2_NUMBER, link_data.interface2_id),
(LinkTlvs.INTERFACE2_IP4, link_data.interface2_ip4),
(LinkTlvs.INTERFACE2_IP4_MASK, link_data.interface2_ip4_mask),
(LinkTlvs.INTERFACE2_MAC, link_data.interface2_mac),
(LinkTlvs.INTERFACE2_IP6, link_data.interface2_ip6),
(LinkTlvs.INTERFACE2_IP6_MASK, link_data.interface2_ip6_mask),
(LinkTlvs.OPAQUE, link_data.opaque),
(LinkTlvs.KEY, options_data.key),
(LinkTlvs.IFACE1_NUMBER, iface1.id),
(LinkTlvs.IFACE1_IP4, iface1.ip4),
(LinkTlvs.IFACE1_IP4_MASK, iface1.ip4_mask),
(LinkTlvs.IFACE1_MAC, iface1.mac),
(LinkTlvs.IFACE1_IP6, iface1.ip6),
(LinkTlvs.IFACE1_IP6_MASK, iface1.ip6_mask),
(LinkTlvs.IFACE2_NUMBER, iface2.id),
(LinkTlvs.IFACE2_IP4, iface2.ip4),
(LinkTlvs.IFACE2_IP4_MASK, iface2.ip4_mask),
(LinkTlvs.IFACE2_MAC, iface2.mac),
(LinkTlvs.IFACE2_IP6, iface2.ip6),
(LinkTlvs.IFACE2_IP6_MASK, iface2.ip6_mask),
],
)
@ -709,7 +718,6 @@ class CoreHandler(socketserver.BaseRequestHandler):
options.icon = message.get_tlv(NodeTlvs.ICON.value)
options.canvas = message.get_tlv(NodeTlvs.CANVAS.value)
options.opaque = message.get_tlv(NodeTlvs.OPAQUE.value)
options.server = message.get_tlv(NodeTlvs.EMULATION_SERVER.value)
services = message.get_tlv(NodeTlvs.SERVICES.value)
@ -749,56 +757,51 @@ class CoreHandler(socketserver.BaseRequestHandler):
"""
node1_id = message.get_tlv(LinkTlvs.N1_NUMBER.value)
node2_id = message.get_tlv(LinkTlvs.N2_NUMBER.value)
interface1_data = InterfaceData(
id=message.get_tlv(LinkTlvs.INTERFACE1_NUMBER.value),
iface1_data = InterfaceData(
id=message.get_tlv(LinkTlvs.IFACE1_NUMBER.value),
name=message.get_tlv(LinkTlvs.INTERFACE1_NAME.value),
mac=message.get_tlv(LinkTlvs.INTERFACE1_MAC.value),
ip4=message.get_tlv(LinkTlvs.INTERFACE1_IP4.value),
ip4_mask=message.get_tlv(LinkTlvs.INTERFACE1_IP4_MASK.value),
ip6=message.get_tlv(LinkTlvs.INTERFACE1_IP6.value),
ip6_mask=message.get_tlv(LinkTlvs.INTERFACE1_IP6_MASK.value),
mac=message.get_tlv(LinkTlvs.IFACE1_MAC.value),
ip4=message.get_tlv(LinkTlvs.IFACE1_IP4.value),
ip4_mask=message.get_tlv(LinkTlvs.IFACE1_IP4_MASK.value),
ip6=message.get_tlv(LinkTlvs.IFACE1_IP6.value),
ip6_mask=message.get_tlv(LinkTlvs.IFACE1_IP6_MASK.value),
)
interface2_data = InterfaceData(
id=message.get_tlv(LinkTlvs.INTERFACE2_NUMBER.value),
iface2_data = InterfaceData(
id=message.get_tlv(LinkTlvs.IFACE2_NUMBER.value),
name=message.get_tlv(LinkTlvs.INTERFACE2_NAME.value),
mac=message.get_tlv(LinkTlvs.INTERFACE2_MAC.value),
ip4=message.get_tlv(LinkTlvs.INTERFACE2_IP4.value),
ip4_mask=message.get_tlv(LinkTlvs.INTERFACE2_IP4_MASK.value),
ip6=message.get_tlv(LinkTlvs.INTERFACE2_IP6.value),
ip6_mask=message.get_tlv(LinkTlvs.INTERFACE2_IP6_MASK.value),
mac=message.get_tlv(LinkTlvs.IFACE2_MAC.value),
ip4=message.get_tlv(LinkTlvs.IFACE2_IP4.value),
ip4_mask=message.get_tlv(LinkTlvs.IFACE2_IP4_MASK.value),
ip6=message.get_tlv(LinkTlvs.IFACE2_IP6.value),
ip6_mask=message.get_tlv(LinkTlvs.IFACE2_IP6_MASK.value),
)
link_type = LinkTypes.WIRED
link_type_value = message.get_tlv(LinkTlvs.TYPE.value)
if link_type_value is not None:
link_type = LinkTypes(link_type_value)
options = LinkOptions(type=link_type)
options = LinkOptions()
options.delay = message.get_tlv(LinkTlvs.DELAY.value)
options.bandwidth = message.get_tlv(LinkTlvs.BANDWIDTH.value)
options.session = message.get_tlv(LinkTlvs.SESSION.value)
options.loss = message.get_tlv(LinkTlvs.LOSS.value)
options.dup = message.get_tlv(LinkTlvs.DUP.value)
options.jitter = message.get_tlv(LinkTlvs.JITTER.value)
options.mer = message.get_tlv(LinkTlvs.MER.value)
options.burst = message.get_tlv(LinkTlvs.BURST.value)
options.mburst = message.get_tlv(LinkTlvs.MBURST.value)
options.gui_attributes = message.get_tlv(LinkTlvs.GUI_ATTRIBUTES.value)
options.unidirectional = message.get_tlv(LinkTlvs.UNIDIRECTIONAL.value)
options.emulation_id = message.get_tlv(LinkTlvs.EMULATION_ID.value)
options.network_id = message.get_tlv(LinkTlvs.NETWORK_ID.value)
options.key = message.get_tlv(LinkTlvs.KEY.value)
options.opaque = message.get_tlv(LinkTlvs.OPAQUE.value)
if message.flags & MessageFlags.ADD.value:
self.session.add_link(
node1_id, node2_id, interface1_data, interface2_data, options
node1_id, node2_id, iface1_data, iface2_data, options, link_type
)
elif message.flags & MessageFlags.DELETE.value:
self.session.delete_link(
node1_id, node2_id, interface1_data.id, interface2_data.id
node1_id, node2_id, iface1_data.id, iface2_data.id, link_type
)
else:
self.session.update_link(
node1_id, node2_id, interface1_data.id, interface2_data.id, options
node1_id, node2_id, iface1_data.id, iface2_data.id, options, link_type
)
return ()
@ -1008,7 +1011,7 @@ class CoreHandler(socketserver.BaseRequestHandler):
possible_values=message.get_tlv(ConfigTlvs.POSSIBLE_VALUES.value),
groups=message.get_tlv(ConfigTlvs.GROUPS.value),
session=message.get_tlv(ConfigTlvs.SESSION.value),
interface_number=message.get_tlv(ConfigTlvs.INTERFACE_NUMBER.value),
iface_id=message.get_tlv(ConfigTlvs.IFACE_ID.value),
network_id=message.get_tlv(ConfigTlvs.NETWORK_ID.value),
opaque=message.get_tlv(ConfigTlvs.OPAQUE.value),
)
@ -1325,11 +1328,11 @@ class CoreHandler(socketserver.BaseRequestHandler):
replies = []
node_id = config_data.node
object_name = config_data.object
interface_id = config_data.interface_number
iface_id = config_data.iface_id
values_str = config_data.data_values
if interface_id is not None:
node_id = node_id * 1000 + interface_id
if iface_id is not None:
node_id = node_id * 1000 + iface_id
logging.debug(
"received configure message for %s nodenum: %s", object_name, node_id
@ -1375,11 +1378,11 @@ class CoreHandler(socketserver.BaseRequestHandler):
replies = []
node_id = config_data.node
object_name = config_data.object
interface_id = config_data.interface_number
iface_id = config_data.iface_id
values_str = config_data.data_values
if interface_id is not None:
node_id = node_id * 1000 + interface_id
if iface_id is not None:
node_id = node_id * 1000 + iface_id
logging.debug(
"received configure message for %s nodenum: %s", object_name, node_id
@ -1407,11 +1410,11 @@ class CoreHandler(socketserver.BaseRequestHandler):
replies = []
node_id = config_data.node
object_name = config_data.object
interface_id = config_data.interface_number
iface_id = config_data.iface_id
values_str = config_data.data_values
if interface_id is not None:
node_id = node_id * 1000 + interface_id
if iface_id is not None:
node_id = node_id * 1000 + iface_id
logging.debug(
"received configure message for %s nodenum: %s", object_name, node_id
@ -1505,7 +1508,7 @@ class CoreHandler(socketserver.BaseRequestHandler):
return ()
def handle_interface_message(self, message):
def handle_iface_message(self, message):
"""
Interface Message handler.
@ -1950,7 +1953,7 @@ class CoreUdpHandler(CoreHandler):
MessageTypes.REGISTER.value: self.handle_register_message,
MessageTypes.CONFIG.value: self.handle_config_message,
MessageTypes.FILE.value: self.handle_file_message,
MessageTypes.INTERFACE.value: self.handle_interface_message,
MessageTypes.INTERFACE.value: self.handle_iface_message,
MessageTypes.EVENT.value: self.handle_event_message,
MessageTypes.SESSION.value: self.handle_session_message,
}

View file

@ -8,45 +8,39 @@ from typing import Dict, List
from core.api.tlv import coreapi, structutils
from core.api.tlv.enumerations import ConfigTlvs, NodeTlvs
from core.config import ConfigGroup, ConfigurableOptions
from core.emulator.data import ConfigData
from core.emulator.data import ConfigData, NodeData
def convert_node(node_data):
def convert_node(node_data: NodeData):
"""
Convenience method for converting NodeData to a packed TLV message.
:param core.emulator.data.NodeData node_data: node data to convert
:return: packed node message
"""
session = None
if node_data.session is not None:
session = str(node_data.session)
node = node_data.node
services = None
if node_data.services is not None:
services = "|".join([x for x in node_data.services])
if node.services is not None:
services = "|".join([x.name for x in node.services])
server = None
if node.server is not None:
server = node.server.name
tlv_data = structutils.pack_values(
coreapi.CoreNodeTlv,
[
(NodeTlvs.NUMBER, node_data.id),
(NodeTlvs.TYPE, node_data.node_type.value),
(NodeTlvs.NAME, node_data.name),
(NodeTlvs.IP_ADDRESS, node_data.ip_address),
(NodeTlvs.MAC_ADDRESS, node_data.mac_address),
(NodeTlvs.IP6_ADDRESS, node_data.ip6_address),
(NodeTlvs.MODEL, node_data.model),
(NodeTlvs.EMULATION_ID, node_data.emulation_id),
(NodeTlvs.EMULATION_SERVER, node_data.server),
(NodeTlvs.SESSION, session),
(NodeTlvs.X_POSITION, int(node_data.x_position)),
(NodeTlvs.Y_POSITION, int(node_data.y_position)),
(NodeTlvs.CANVAS, node_data.canvas),
(NodeTlvs.NETWORK_ID, node_data.network_id),
(NodeTlvs.NUMBER, node.id),
(NodeTlvs.TYPE, node.apitype.value),
(NodeTlvs.NAME, node.name),
(NodeTlvs.MODEL, node.type),
(NodeTlvs.EMULATION_SERVER, server),
(NodeTlvs.X_POSITION, int(node.position.x)),
(NodeTlvs.Y_POSITION, int(node.position.y)),
(NodeTlvs.CANVAS, node.canvas),
(NodeTlvs.SERVICES, services),
(NodeTlvs.LATITUDE, str(node_data.latitude)),
(NodeTlvs.LONGITUDE, str(node_data.longitude)),
(NodeTlvs.ALTITUDE, str(node_data.altitude)),
(NodeTlvs.ICON, node_data.icon),
(NodeTlvs.OPAQUE, node_data.opaque),
(NodeTlvs.LATITUDE, str(node.position.lat)),
(NodeTlvs.LONGITUDE, str(node.position.lon)),
(NodeTlvs.ALTITUDE, str(node.position.alt)),
(NodeTlvs.ICON, node.icon),
],
)
return coreapi.CoreNodeMessage.pack(node_data.message_type.value, tlv_data)
@ -75,7 +69,7 @@ def convert_config(config_data):
(ConfigTlvs.POSSIBLE_VALUES, config_data.possible_values),
(ConfigTlvs.GROUPS, config_data.groups),
(ConfigTlvs.SESSION, session),
(ConfigTlvs.INTERFACE_NUMBER, config_data.interface_number),
(ConfigTlvs.IFACE_ID, config_data.iface_id),
(ConfigTlvs.NETWORK_ID, config_data.network_id),
(ConfigTlvs.OPAQUE, config_data.opaque),
],

View file

@ -72,18 +72,18 @@ class LinkTlvs(Enum):
EMULATION_ID = 0x23
NETWORK_ID = 0x24
KEY = 0x25
INTERFACE1_NUMBER = 0x30
INTERFACE1_IP4 = 0x31
INTERFACE1_IP4_MASK = 0x32
INTERFACE1_MAC = 0x33
INTERFACE1_IP6 = 0x34
INTERFACE1_IP6_MASK = 0x35
INTERFACE2_NUMBER = 0x36
INTERFACE2_IP4 = 0x37
INTERFACE2_IP4_MASK = 0x38
INTERFACE2_MAC = 0x39
INTERFACE2_IP6 = 0x40
INTERFACE2_IP6_MASK = 0x41
IFACE1_NUMBER = 0x30
IFACE1_IP4 = 0x31
IFACE1_IP4_MASK = 0x32
IFACE1_MAC = 0x33
IFACE1_IP6 = 0x34
IFACE1_IP6_MASK = 0x35
IFACE2_NUMBER = 0x36
IFACE2_IP4 = 0x37
IFACE2_IP4_MASK = 0x38
IFACE2_MAC = 0x39
IFACE2_IP6 = 0x40
IFACE2_IP6_MASK = 0x41
INTERFACE1_NAME = 0x42
INTERFACE2_NAME = 0x43
OPAQUE = 0x50
@ -118,7 +118,7 @@ class ConfigTlvs(Enum):
POSSIBLE_VALUES = 0x08
GROUPS = 0x09
SESSION = 0x0A
INTERFACE_NUMBER = 0x0B
IFACE_ID = 0x0B
NETWORK_ID = 0x24
OPAQUE = 0x50

View file

@ -13,33 +13,33 @@ from core.nodes.network import WlanNode
GROUP = "FRR"
def has_mtu_mismatch(ifc: CoreInterface) -> bool:
def has_mtu_mismatch(iface: CoreInterface) -> bool:
"""
Helper to detect MTU mismatch and add the appropriate FRR
mtu-ignore command. This is needed when e.g. a node is linked via a
GreTap device.
"""
if ifc.mtu != 1500:
if iface.mtu != 1500:
return True
if not ifc.net:
if not iface.net:
return False
for i in ifc.net.netifs():
if i.mtu != ifc.mtu:
for iface in iface.net.get_ifaces():
if iface.mtu != iface.mtu:
return True
return False
def get_min_mtu(ifc):
def get_min_mtu(iface):
"""
Helper to discover the minimum MTU of interfaces linked with the
given interface.
"""
mtu = ifc.mtu
if not ifc.net:
mtu = iface.mtu
if not iface.net:
return mtu
for i in ifc.net.netifs():
if i.mtu < mtu:
mtu = i.mtu
for iface in iface.net.get_ifaces():
if iface.mtu < mtu:
mtu = iface.mtu
return mtu
@ -47,10 +47,8 @@ def get_router_id(node: CoreNodeBase) -> str:
"""
Helper to return the first IPv4 address of a node as its router ID.
"""
for ifc in node.netifs():
if getattr(ifc, "control", False):
continue
for a in ifc.addrlist:
for iface in node.get_ifaces(control=False):
for a in iface.addrlist:
a = a.split("/")[0]
if netaddr.valid_ipv4(a):
return a
@ -97,25 +95,25 @@ class FRRZebra(ConfigService):
want_ip6 = True
services.append(service)
interfaces = []
for ifc in self.node.netifs():
ifaces = []
for iface in self.node.get_ifaces():
ip4s = []
ip6s = []
for x in ifc.addrlist:
for x in iface.addrlist:
addr = x.split("/")[0]
if netaddr.valid_ipv4(addr):
ip4s.append(x)
else:
ip6s.append(x)
is_control = getattr(ifc, "control", False)
interfaces.append((ifc, ip4s, ip6s, is_control))
is_control = getattr(iface, "control", False)
ifaces.append((iface, ip4s, ip6s, is_control))
return dict(
frr_conf=frr_conf,
frr_sbin_search=frr_sbin_search,
frr_bin_search=frr_bin_search,
frr_state_dir=constants.FRR_STATE_DIR,
interfaces=interfaces,
ifaces=ifaces,
want_ip4=want_ip4,
want_ip6=want_ip6,
services=services,
@ -138,7 +136,7 @@ class FrrService(abc.ABC):
ipv6_routing = False
@abc.abstractmethod
def frr_interface_config(self, ifc: CoreInterface) -> str:
def frr_iface_config(self, iface: CoreInterface) -> str:
raise NotImplementedError
@abc.abstractmethod
@ -162,10 +160,8 @@ class FRROspfv2(FrrService, ConfigService):
def frr_config(self) -> str:
router_id = get_router_id(self.node)
addresses = []
for ifc in self.node.netifs():
if getattr(ifc, "control", False):
continue
for a in ifc.addrlist:
for iface in self.node.get_ifaces(control=False):
for a in iface.addrlist:
addr = a.split("/")[0]
if netaddr.valid_ipv4(addr):
addresses.append(a)
@ -180,8 +176,8 @@ class FRROspfv2(FrrService, ConfigService):
"""
return self.render_text(text, data)
def frr_interface_config(self, ifc: CoreInterface) -> str:
if has_mtu_mismatch(ifc):
def frr_iface_config(self, iface: CoreInterface) -> str:
if has_mtu_mismatch(iface):
return "ip ospf mtu-ignore"
else:
return ""
@ -203,10 +199,8 @@ class FRROspfv3(FrrService, ConfigService):
def frr_config(self) -> str:
router_id = get_router_id(self.node)
ifnames = []
for ifc in self.node.netifs():
if getattr(ifc, "control", False):
continue
ifnames.append(ifc.name)
for iface in self.node.get_ifaces(control=False):
ifnames.append(iface.name)
data = dict(router_id=router_id, ifnames=ifnames)
text = """
router ospf6
@ -218,9 +212,9 @@ class FRROspfv3(FrrService, ConfigService):
"""
return self.render_text(text, data)
def frr_interface_config(self, ifc: CoreInterface) -> str:
mtu = get_min_mtu(ifc)
if mtu < ifc.mtu:
def frr_iface_config(self, iface: CoreInterface) -> str:
mtu = get_min_mtu(iface)
if mtu < iface.mtu:
return f"ipv6 ospf6 ifmtu {mtu}"
else:
return ""
@ -254,7 +248,7 @@ class FRRBgp(FrrService, ConfigService):
"""
return self.clean_text(text)
def frr_interface_config(self, ifc: CoreInterface) -> str:
def frr_iface_config(self, iface: CoreInterface) -> str:
return ""
@ -279,7 +273,7 @@ class FRRRip(FrrService, ConfigService):
"""
return self.clean_text(text)
def frr_interface_config(self, ifc: CoreInterface) -> str:
def frr_iface_config(self, iface: CoreInterface) -> str:
return ""
@ -304,7 +298,7 @@ class FRRRipng(FrrService, ConfigService):
"""
return self.clean_text(text)
def frr_interface_config(self, ifc: CoreInterface) -> str:
def frr_iface_config(self, iface: CoreInterface) -> str:
return ""
@ -321,10 +315,8 @@ class FRRBabel(FrrService, ConfigService):
def frr_config(self) -> str:
ifnames = []
for ifc in self.node.netifs():
if getattr(ifc, "control", False):
continue
ifnames.append(ifc.name)
for iface in self.node.get_ifaces(control=False):
ifnames.append(iface.name)
text = """
router babel
% for ifname in ifnames:
@ -337,8 +329,8 @@ class FRRBabel(FrrService, ConfigService):
data = dict(ifnames=ifnames)
return self.render_text(text, data)
def frr_interface_config(self, ifc: CoreInterface) -> str:
if isinstance(ifc.net, (WlanNode, EmaneNet)):
def frr_iface_config(self, iface: CoreInterface) -> str:
if isinstance(iface.net, (WlanNode, EmaneNet)):
text = """
babel wireless
no babel split-horizon
@ -363,9 +355,9 @@ class FRRpimd(FrrService, ConfigService):
def frr_config(self) -> str:
ifname = "eth0"
for ifc in self.node.netifs():
if ifc.name != "lo":
ifname = ifc.name
for iface in self.node.get_ifaces():
if iface.name != "lo":
ifname = iface.name
break
text = f"""
@ -382,7 +374,7 @@ class FRRpimd(FrrService, ConfigService):
"""
return self.clean_text(text)
def frr_interface_config(self, ifc: CoreInterface) -> str:
def frr_iface_config(self, iface: CoreInterface) -> str:
text = """
ip mfea
ip igmp

View file

@ -1,5 +1,5 @@
% for ifc, ip4s, ip6s, is_control in interfaces:
interface ${ifc.name}
% for iface, ip4s, ip6s, is_control in ifaces:
interface ${iface.name}
% if want_ip4:
% for addr in ip4s:
ip address ${addr}
@ -12,7 +12,7 @@ interface ${ifc.name}
% endif
% if not is_control:
% for service in services:
% for line in service.frr_interface_config(ifc).split("\n"):
% for line in service.frr_iface_config(iface).split("\n"):
${line}
% endfor
% endfor

View file

@ -98,8 +98,8 @@ confcheck
bootfrr
# reset interfaces
% for ifc, _, _ , _ in interfaces:
ip link set dev ${ifc.name} down
% for iface, _, _ , _ in ifaces:
ip link set dev ${iface.name} down
sleep 1
ip link set dev ${ifc.name} up
ip link set dev ${iface.name} up
% endfor

View file

@ -24,8 +24,8 @@ class MgenSinkService(ConfigService):
def data(self) -> Dict[str, Any]:
ifnames = []
for ifc in self.node.netifs():
name = utils.sysctl_devname(ifc.name)
for iface in self.node.get_ifaces():
name = utils.sysctl_devname(iface.name)
ifnames.append(name)
return dict(ifnames=ifnames)
@ -47,10 +47,8 @@ class NrlNhdp(ConfigService):
def data(self) -> Dict[str, Any]:
has_smf = "SMF" in self.node.config_services
ifnames = []
for ifc in self.node.netifs():
if getattr(ifc, "control", False):
continue
ifnames.append(ifc.name)
for iface in self.node.get_ifaces(control=False):
ifnames.append(iface.name)
return dict(has_smf=has_smf, ifnames=ifnames)
@ -74,13 +72,11 @@ class NrlSmf(ConfigService):
has_olsr = "OLSR" in self.node.config_services
ifnames = []
ip4_prefix = None
for ifc in self.node.netifs():
if getattr(ifc, "control", False):
continue
ifnames.append(ifc.name)
for iface in self.node.get_ifaces(control=False):
ifnames.append(iface.name)
if ip4_prefix:
continue
for a in ifc.addrlist:
for a in iface.addrlist:
a = a.split("/")[0]
if netaddr.valid_ipv4(a):
ip4_prefix = f"{a}/{24}"
@ -112,10 +108,8 @@ class NrlOlsr(ConfigService):
has_smf = "SMF" in self.node.config_services
has_zebra = "zebra" in self.node.config_services
ifname = None
for ifc in self.node.netifs():
if getattr(ifc, "control", False):
continue
ifname = ifc.name
for iface in self.node.get_ifaces(control=False):
ifname = iface.name
break
return dict(has_smf=has_smf, has_zebra=has_zebra, ifname=ifname)
@ -137,10 +131,8 @@ class NrlOlsrv2(ConfigService):
def data(self) -> Dict[str, Any]:
has_smf = "SMF" in self.node.config_services
ifnames = []
for ifc in self.node.netifs():
if getattr(ifc, "control", False):
continue
ifnames.append(ifc.name)
for iface in self.node.get_ifaces(control=False):
ifnames.append(iface.name)
return dict(has_smf=has_smf, ifnames=ifnames)
@ -161,10 +153,8 @@ class OlsrOrg(ConfigService):
def data(self) -> Dict[str, Any]:
has_smf = "SMF" in self.node.config_services
ifnames = []
for ifc in self.node.netifs():
if getattr(ifc, "control", False):
continue
ifnames.append(ifc.name)
for iface in self.node.get_ifaces(control=False):
ifnames.append(iface.name)
return dict(has_smf=has_smf, ifnames=ifnames)
@ -199,12 +189,10 @@ class Arouted(ConfigService):
def data(self) -> Dict[str, Any]:
ip4_prefix = None
for ifc in self.node.netifs():
if getattr(ifc, "control", False):
continue
for iface in self.node.get_ifaces(control=False):
if ip4_prefix:
continue
for a in ifc.addrlist:
for a in iface.addrlist:
a = a.split("/")[0]
if netaddr.valid_ipv4(a):
ip4_prefix = f"{a}/{24}"

View file

@ -1,7 +1,7 @@
<%
interfaces = "-i " + " -i ".join(ifnames)
ifaces = "-i " + " -i ".join(ifnames)
smf = ""
if has_smf:
smf = "-flooding ecds -smfClient %s_smf" % node.name
%>
nrlnhdp -l /var/log/nrlnhdp.log -rpipe ${node.name}_nhdp ${smf} ${interfaces}
nrlnhdp -l /var/log/nrlnhdp.log -rpipe ${node.name}_nhdp ${smf} ${ifaces}

View file

@ -1,7 +1,7 @@
<%
interfaces = "-i " + " -i ".join(ifnames)
ifaces = "-i " + " -i ".join(ifnames)
smf = ""
if has_smf:
smf = "-flooding ecds -smfClient %s_smf" % node.name
%>
nrlolsrv2 -l /var/log/nrlolsrv2.log -rpipe ${node.name}_olsrv2 -p olsr ${smf} ${interfaces}
nrlolsrv2 -l /var/log/nrlolsrv2.log -rpipe ${node.name}_olsrv2 -p olsr ${smf} ${ifaces}

View file

@ -1,4 +1,4 @@
<%
interfaces = "-i " + " -i ".join(ifnames)
ifaces = "-i " + " -i ".join(ifnames)
%>
olsrd ${interfaces}
olsrd ${ifaces}

View file

@ -1,5 +1,5 @@
<%
interfaces = ",".join(ifnames)
ifaces = ",".join(ifnames)
arouted = ""
if has_arouted:
arouted = "tap %s_tap unicast %s push lo,%s resequence on" % (node.name, ip4_prefix, ifnames[0])
@ -12,4 +12,4 @@
%>
#!/bin/sh
# auto-generated by NrlSmf service
nrlsmf instance ${node.name}_smf ${interfaces} ${arouted} ${flood} hash MD5 log /var/log/nrlsmf.log < /dev/null > /dev/null 2>&1 &
nrlsmf instance ${node.name}_smf ${ifaces} ${arouted} ${flood} hash MD5 log /var/log/nrlsmf.log < /dev/null > /dev/null 2>&1 &

View file

@ -14,33 +14,33 @@ from core.nodes.network import WlanNode
GROUP = "Quagga"
def has_mtu_mismatch(ifc: CoreInterface) -> bool:
def has_mtu_mismatch(iface: CoreInterface) -> bool:
"""
Helper to detect MTU mismatch and add the appropriate OSPF
mtu-ignore command. This is needed when e.g. a node is linked via a
GreTap device.
"""
if ifc.mtu != 1500:
if iface.mtu != 1500:
return True
if not ifc.net:
if not iface.net:
return False
for i in ifc.net.netifs():
if i.mtu != ifc.mtu:
for iface in iface.net.get_ifaces():
if iface.mtu != iface.mtu:
return True
return False
def get_min_mtu(ifc):
def get_min_mtu(iface: CoreInterface):
"""
Helper to discover the minimum MTU of interfaces linked with the
given interface.
"""
mtu = ifc.mtu
if not ifc.net:
mtu = iface.mtu
if not iface.net:
return mtu
for i in ifc.net.netifs():
if i.mtu < mtu:
mtu = i.mtu
for iface in iface.net.get_ifaces():
if iface.mtu < mtu:
mtu = iface.mtu
return mtu
@ -48,10 +48,8 @@ def get_router_id(node: CoreNodeBase) -> str:
"""
Helper to return the first IPv4 address of a node as its router ID.
"""
for ifc in node.netifs():
if getattr(ifc, "control", False):
continue
for a in ifc.addrlist:
for iface in node.get_ifaces(control=False):
for a in iface.addrlist:
a = a.split("/")[0]
if netaddr.valid_ipv4(a):
return a
@ -98,25 +96,25 @@ class Zebra(ConfigService):
want_ip6 = True
services.append(service)
interfaces = []
for ifc in self.node.netifs():
ifaces = []
for iface in self.node.get_ifaces():
ip4s = []
ip6s = []
for x in ifc.addrlist:
for x in iface.addrlist:
addr = x.split("/")[0]
if netaddr.valid_ipv4(addr):
ip4s.append(x)
else:
ip6s.append(x)
is_control = getattr(ifc, "control", False)
interfaces.append((ifc, ip4s, ip6s, is_control))
is_control = getattr(iface, "control", False)
ifaces.append((iface, ip4s, ip6s, is_control))
return dict(
quagga_bin_search=quagga_bin_search,
quagga_sbin_search=quagga_sbin_search,
quagga_state_dir=quagga_state_dir,
quagga_conf=quagga_conf,
interfaces=interfaces,
ifaces=ifaces,
want_ip4=want_ip4,
want_ip6=want_ip6,
services=services,
@ -139,7 +137,7 @@ class QuaggaService(abc.ABC):
ipv6_routing = False
@abc.abstractmethod
def quagga_interface_config(self, ifc: CoreInterface) -> str:
def quagga_iface_config(self, iface: CoreInterface) -> str:
raise NotImplementedError
@abc.abstractmethod
@ -159,8 +157,8 @@ class Ospfv2(QuaggaService, ConfigService):
shutdown = ["killall ospfd"]
ipv4_routing = True
def quagga_interface_config(self, ifc: CoreInterface) -> str:
if has_mtu_mismatch(ifc):
def quagga_iface_config(self, iface: CoreInterface) -> str:
if has_mtu_mismatch(iface):
return "ip ospf mtu-ignore"
else:
return ""
@ -168,10 +166,8 @@ class Ospfv2(QuaggaService, ConfigService):
def quagga_config(self) -> str:
router_id = get_router_id(self.node)
addresses = []
for ifc in self.node.netifs():
if getattr(ifc, "control", False):
continue
for a in ifc.addrlist:
for iface in self.node.get_ifaces(control=False):
for a in iface.addrlist:
addr = a.split("/")[0]
if netaddr.valid_ipv4(addr):
addresses.append(a)
@ -200,9 +196,9 @@ class Ospfv3(QuaggaService, ConfigService):
ipv4_routing = True
ipv6_routing = True
def quagga_interface_config(self, ifc: CoreInterface) -> str:
mtu = get_min_mtu(ifc)
if mtu < ifc.mtu:
def quagga_iface_config(self, iface: CoreInterface) -> str:
mtu = get_min_mtu(iface)
if mtu < iface.mtu:
return f"ipv6 ospf6 ifmtu {mtu}"
else:
return ""
@ -210,10 +206,8 @@ class Ospfv3(QuaggaService, ConfigService):
def quagga_config(self) -> str:
router_id = get_router_id(self.node)
ifnames = []
for ifc in self.node.netifs():
if getattr(ifc, "control", False):
continue
ifnames.append(ifc.name)
for iface in self.node.get_ifaces(control=False):
ifnames.append(iface.name)
data = dict(router_id=router_id, ifnames=ifnames)
text = """
router ospf6
@ -238,14 +232,14 @@ class Ospfv3mdr(Ospfv3):
name = "OSPFv3MDR"
def data(self) -> Dict[str, Any]:
for ifc in self.node.netifs():
is_wireless = isinstance(ifc.net, (WlanNode, EmaneNet))
for iface in self.node.get_ifaces():
is_wireless = isinstance(iface.net, (WlanNode, EmaneNet))
logging.info("MDR wireless: %s", is_wireless)
return dict()
def quagga_interface_config(self, ifc: CoreInterface) -> str:
config = super().quagga_interface_config(ifc)
if isinstance(ifc.net, (WlanNode, EmaneNet)):
def quagga_iface_config(self, iface: CoreInterface) -> str:
config = super().quagga_iface_config(iface)
if isinstance(iface.net, (WlanNode, EmaneNet)):
config = self.clean_text(
f"""
{config}
@ -277,7 +271,7 @@ class Bgp(QuaggaService, ConfigService):
def quagga_config(self) -> str:
return ""
def quagga_interface_config(self, ifc: CoreInterface) -> str:
def quagga_iface_config(self, iface: CoreInterface) -> str:
router_id = get_router_id(self.node)
text = f"""
! BGP configuration
@ -313,7 +307,7 @@ class Rip(QuaggaService, ConfigService):
"""
return self.clean_text(text)
def quagga_interface_config(self, ifc: CoreInterface) -> str:
def quagga_iface_config(self, iface: CoreInterface) -> str:
return ""
@ -338,7 +332,7 @@ class Ripng(QuaggaService, ConfigService):
"""
return self.clean_text(text)
def quagga_interface_config(self, ifc: CoreInterface) -> str:
def quagga_iface_config(self, iface: CoreInterface) -> str:
return ""
@ -355,10 +349,8 @@ class Babel(QuaggaService, ConfigService):
def quagga_config(self) -> str:
ifnames = []
for ifc in self.node.netifs():
if getattr(ifc, "control", False):
continue
ifnames.append(ifc.name)
for iface in self.node.get_ifaces(control=False):
ifnames.append(iface.name)
text = """
router babel
% for ifname in ifnames:
@ -371,8 +363,8 @@ class Babel(QuaggaService, ConfigService):
data = dict(ifnames=ifnames)
return self.render_text(text, data)
def quagga_interface_config(self, ifc: CoreInterface) -> str:
if isinstance(ifc.net, (WlanNode, EmaneNet)):
def quagga_iface_config(self, iface: CoreInterface) -> str:
if isinstance(iface.net, (WlanNode, EmaneNet)):
text = """
babel wireless
no babel split-horizon
@ -397,9 +389,9 @@ class Xpimd(QuaggaService, ConfigService):
def quagga_config(self) -> str:
ifname = "eth0"
for ifc in self.node.netifs():
if ifc.name != "lo":
ifname = ifc.name
for iface in self.node.get_ifaces():
if iface.name != "lo":
ifname = iface.name
break
text = f"""
@ -416,7 +408,7 @@ class Xpimd(QuaggaService, ConfigService):
"""
return self.clean_text(text)
def quagga_interface_config(self, ifc: CoreInterface) -> str:
def quagga_iface_config(self, iface: CoreInterface) -> str:
text = """
ip mfea
ip pim

View file

@ -1,5 +1,5 @@
% for ifc, ip4s, ip6s, is_control in interfaces:
interface ${ifc.name}
% for iface, ip4s, ip6s, is_control in ifaces:
interface ${iface.name}
% if want_ip4:
% for addr in ip4s:
ip address ${addr}
@ -12,7 +12,7 @@ interface ${ifc.name}
% endif
% if not is_control:
% for service in services:
% for line in service.quagga_interface_config(ifc).split("\n"):
% for line in service.quagga_iface_config(iface).split("\n"):
${line}
% endfor
% endfor

View file

@ -78,10 +78,8 @@ class VpnServer(ConfigService):
def data(self) -> Dict[str, Any]:
address = None
for ifc in self.node.netifs():
if getattr(ifc, "control", False):
continue
for x in ifc.addrlist:
for iface in self.node.get_ifaces(control=False):
for x in iface.addrlist:
addr = x.split("/")[0]
if netaddr.valid_ipv4(addr):
address = addr
@ -134,8 +132,6 @@ class Nat(ConfigService):
def data(self) -> Dict[str, Any]:
ifnames = []
for ifc in self.node.netifs():
if getattr(ifc, "control", False):
continue
ifnames.append(ifc.name)
for iface in self.node.get_ifaces(control=False):
ifnames.append(iface.name)
return dict(ifnames=ifnames)

View file

@ -25,10 +25,10 @@ class DefaultRouteService(ConfigService):
def data(self) -> Dict[str, Any]:
# only add default routes for linked routing nodes
routes = []
netifs = self.node.netifs(sort=True)
if netifs:
netif = netifs[0]
for x in netif.addrlist:
ifaces = self.node.get_ifaces()
if ifaces:
iface = ifaces[0]
for x in iface.addrlist:
net = netaddr.IPNetwork(x).cidr
if net.size > 1:
router = net[1]
@ -52,10 +52,8 @@ class DefaultMulticastRouteService(ConfigService):
def data(self) -> Dict[str, Any]:
ifname = None
for ifc in self.node.netifs():
if getattr(ifc, "control", False):
continue
ifname = ifc.name
for iface in self.node.get_ifaces(control=False):
ifname = iface.name
break
return dict(ifname=ifname)
@ -76,10 +74,8 @@ class StaticRouteService(ConfigService):
def data(self) -> Dict[str, Any]:
routes = []
for ifc in self.node.netifs():
if getattr(ifc, "control", False):
continue
for x in ifc.addrlist:
for iface in self.node.get_ifaces(control=False):
for x in iface.addrlist:
addr = x.split("/")[0]
if netaddr.valid_ipv6(addr):
dst = "3ffe:4::/64"
@ -107,8 +103,8 @@ class IpForwardService(ConfigService):
def data(self) -> Dict[str, Any]:
devnames = []
for ifc in self.node.netifs():
devname = utils.sysctl_devname(ifc.name)
for iface in self.node.get_ifaces():
devname = utils.sysctl_devname(iface.name)
devnames.append(devname)
return dict(devnames=devnames)
@ -151,10 +147,8 @@ class DhcpService(ConfigService):
def data(self) -> Dict[str, Any]:
subnets = []
for ifc in self.node.netifs():
if getattr(ifc, "control", False):
continue
for x in ifc.addrlist:
for iface in self.node.get_ifaces(control=False):
for x in iface.addrlist:
addr = x.split("/")[0]
if netaddr.valid_ipv4(addr):
net = netaddr.IPNetwork(x)
@ -182,10 +176,8 @@ class DhcpClientService(ConfigService):
def data(self) -> Dict[str, Any]:
ifnames = []
for ifc in self.node.netifs():
if getattr(ifc, "control", False):
continue
ifnames.append(ifc.name)
for iface in self.node.get_ifaces(control=False):
ifnames.append(iface.name)
return dict(ifnames=ifnames)
@ -220,10 +212,8 @@ class PcapService(ConfigService):
def data(self) -> Dict[str, Any]:
ifnames = []
for ifc in self.node.netifs():
if getattr(ifc, "control", False):
continue
ifnames.append(ifc.name)
for iface in self.node.get_ifaces(control=False):
ifnames.append(iface.name)
return dict()
@ -242,19 +232,17 @@ class RadvdService(ConfigService):
modes = {}
def data(self) -> Dict[str, Any]:
interfaces = []
for ifc in self.node.netifs():
if getattr(ifc, "control", False):
continue
ifaces = []
for iface in self.node.get_ifaces(control=False):
prefixes = []
for x in ifc.addrlist:
for x in iface.addrlist:
addr = x.split("/")[0]
if netaddr.valid_ipv6(addr):
prefixes.append(x)
if not prefixes:
continue
interfaces.append((ifc.name, prefixes))
return dict(interfaces=interfaces)
ifaces.append((iface.name, prefixes))
return dict(ifaces=ifaces)
class AtdService(ConfigService):
@ -294,9 +282,7 @@ class HttpService(ConfigService):
modes = {}
def data(self) -> Dict[str, Any]:
interfaces = []
for ifc in self.node.netifs():
if getattr(ifc, "control", False):
continue
interfaces.append(ifc)
return dict(interfaces=interfaces)
ifaces = []
for iface in self.node.get_ifaces(control=False):
ifaces.append(iface)
return dict(ifaces=ifaces)

View file

@ -5,8 +5,8 @@
<p>This is the default web page for this server.</p>
<p>The web server software is running but no content has been added, yet.</p>
<ul>
% for ifc in interfaces:
<li>${ifc.name} - ${ifc.addrlist}</li>
% for iface in ifaces:
<li>${iface.name} - ${iface.addrlist}</li>
% endfor
</ul>
</body>

View file

@ -11,7 +11,7 @@ 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.emudata import LinkOptions
from core.emulator.data import LinkOptions
from core.emulator.enumerations import TransportType
from core.nodes.interface import CoreInterface
from core.xml import emanexml
@ -63,7 +63,7 @@ class EmaneCommEffectModel(emanemodel.EmaneModel):
return [ConfigGroup("CommEffect SHIM Parameters", 1, len(cls.configurations()))]
def build_xml_files(
self, config: Dict[str, str], interface: CoreInterface = None
self, config: Dict[str, str], iface: CoreInterface = None
) -> None:
"""
Build the necessary nem and commeffect XMLs in the given path.
@ -72,17 +72,17 @@ class EmaneCommEffectModel(emanemodel.EmaneModel):
nXXemane_commeffectnem.xml, nXXemane_commeffectshim.xml are used.
:param config: emane model configuration for the node and interface
:param interface: interface for the emane node
:param iface: interface for the emane node
:return: nothing
"""
# retrieve xml names
nem_name = emanexml.nem_file_name(self, interface)
shim_name = emanexml.shim_file_name(self, interface)
nem_name = emanexml.nem_file_name(self, iface)
shim_name = emanexml.shim_file_name(self, iface)
# create and write nem document
nem_element = etree.Element("nem", name=f"{self.name} NEM", type="unstructured")
transport_type = TransportType.VIRTUAL
if interface and interface.transport_type == TransportType.RAW:
if iface and iface.transport_type == TransportType.RAW:
transport_type = TransportType.RAW
transport_file = emanexml.transport_file_name(self.id, transport_type)
etree.SubElement(nem_element, "transport", definition=transport_file)
@ -115,7 +115,7 @@ class EmaneCommEffectModel(emanemodel.EmaneModel):
emanexml.create_file(shim_element, "shim", shim_file)
def linkconfig(
self, netif: CoreInterface, options: LinkOptions, netif2: CoreInterface = None
self, iface: CoreInterface, options: LinkOptions, iface2: CoreInterface = None
) -> None:
"""
Generate CommEffect events when a Link Message is received having
@ -126,7 +126,7 @@ class EmaneCommEffectModel(emanemodel.EmaneModel):
logging.warning("%s: EMANE event service unavailable", self.name)
return
if netif is None or netif2 is None:
if iface is None or iface2 is None:
logging.warning("%s: missing NEM information", self.name)
return
@ -134,8 +134,8 @@ class EmaneCommEffectModel(emanemodel.EmaneModel):
# 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(netif)
nemid2 = emane_node.getnemid(netif2)
nemid = emane_node.getnemid(iface)
nemid2 = emane_node.getnemid(iface2)
logging.info("sending comm effect event")
event.append(
nemid,

View file

@ -111,41 +111,39 @@ class EmaneManager(ModelManager):
self.event_device: Optional[str] = None
self.emane_check()
def getifcconfig(
self, node_id: int, interface: CoreInterface, model_name: str
def get_iface_config(
self, node_id: int, iface: CoreInterface, model_name: str
) -> Dict[str, str]:
"""
Retrieve interface configuration or node configuration if not provided.
:param node_id: node id
:param interface: node interface
:param iface: node interface
:param model_name: model to get configuration for
:return: node/interface model configuration
"""
# use the network-wide config values or interface(NEM)-specific values?
if interface is None:
if iface is None:
return self.get_configs(node_id=node_id, config_type=model_name)
else:
# don"t use default values when interface config is the same as net
# note here that using ifc.node.id as key allows for only one type
# note here that using iface.node.id as key allows for only one type
# of each model per node;
# TODO: use both node and interface as key
# Adamson change: first check for iface config keyed by "node:ifc.name"
# 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 * interface.node.id
if interface.netindex is not None:
key += interface.netindex
key = 1000 * iface.node.id
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)
# otherwise retrieve the interfaces node configuration, avoid using defaults
if not config:
config = self.get_configs(
node_id=interface.node.id, config_type=model_name
)
config = self.get_configs(node_id=iface.node.id, config_type=model_name)
# get non interface config, when none found
if not config:
@ -265,8 +263,8 @@ class EmaneManager(ModelManager):
# assumes self._objslock already held
nodes = set()
for emane_net in self._emane_nets.values():
for netif in emane_net.netifs():
nodes.add(netif.node)
for iface in emane_net.get_ifaces():
nodes.add(iface.node)
return nodes
def setup(self) -> int:
@ -352,13 +350,13 @@ class EmaneManager(ModelManager):
if self.numnems() > 0:
self.startdaemons()
self.installnetifs()
self.install_ifaces()
for node_id in self._emane_nets:
emane_node = self._emane_nets[node_id]
for netif in emane_node.netifs():
for iface in emane_node.get_ifaces():
nems.append(
(netif.node.name, netif.name, emane_node.getnemid(netif))
(iface.node.name, iface.name, emane_node.getnemid(iface))
)
if nems:
@ -392,8 +390,8 @@ class EmaneManager(ModelManager):
emane_node.name,
)
emane_node.model.post_startup()
for netif in emane_node.netifs():
netif.setposition()
for iface in emane_node.get_ifaces():
iface.setposition()
def reset(self) -> None:
"""
@ -420,7 +418,7 @@ class EmaneManager(ModelManager):
logging.info("stopping EMANE daemons")
if self.links_enabled():
self.link_monitor.stop()
self.deinstallnetifs()
self.deinstall_ifaces()
self.stopdaemons()
self.stopeventmonitor()
@ -474,38 +472,38 @@ class EmaneManager(ModelManager):
EMANE network and NEM interface.
"""
emane_node = None
netif = None
iface = None
for node_id in self._emane_nets:
emane_node = self._emane_nets[node_id]
netif = emane_node.getnemnetif(nemid)
if netif is not None:
iface = emane_node.get_nem_iface(nemid)
if iface is not None:
break
else:
emane_node = None
return emane_node, netif
return emane_node, iface
def get_nem_link(
self, nem1: int, nem2: int, flags: MessageFlags = MessageFlags.NONE
) -> Optional[LinkData]:
emane1, netif = self.nemlookup(nem1)
if not emane1 or not netif:
emane1, iface = self.nemlookup(nem1)
if not emane1 or not iface:
logging.error("invalid nem: %s", nem1)
return None
node1 = netif.node
emane2, netif = self.nemlookup(nem2)
if not emane2 or not netif:
node1 = iface.node
emane2, iface = self.nemlookup(nem2)
if not emane2 or not iface:
logging.error("invalid nem: %s", nem2)
return None
node2 = netif.node
node2 = iface.node
color = self.session.get_link_color(emane1.id)
return LinkData(
message_type=flags,
type=LinkTypes.WIRELESS,
node1_id=node1.id,
node2_id=node2.id,
network_id=emane1.id,
link_type=LinkTypes.WIRELESS,
color=color,
)
@ -516,7 +514,7 @@ class EmaneManager(ModelManager):
count = 0
for node_id in self._emane_nets:
emane_node = self._emane_nets[node_id]
count += len(emane_node.netifs())
count += len(emane_node.ifaces)
return count
def buildplatformxml(self, ctrlnet: CtrlNet) -> None:
@ -607,19 +605,19 @@ class EmaneManager(ModelManager):
n = node.id
# control network not yet started here
self.session.add_remove_control_interface(
self.session.add_remove_control_iface(
node, 0, remove=False, conf_required=False
)
if otanetidx > 0:
logging.info("adding ota device ctrl%d", otanetidx)
self.session.add_remove_control_interface(
self.session.add_remove_control_iface(
node, otanetidx, remove=False, conf_required=False
)
if eventservicenetidx >= 0:
logging.info("adding event service device ctrl%d", eventservicenetidx)
self.session.add_remove_control_interface(
self.session.add_remove_control_iface(
node, eventservicenetidx, remove=False, conf_required=False
)
@ -676,23 +674,23 @@ class EmaneManager(ModelManager):
except CoreCommandError:
logging.exception("error shutting down emane daemons")
def installnetifs(self) -> None:
def install_ifaces(self) -> None:
"""
Install TUN/TAP virtual interfaces into their proper namespaces
now that the EMANE daemons are running.
"""
for key in sorted(self._emane_nets.keys()):
emane_node = self._emane_nets[key]
logging.info("emane install netifs for node: %d", key)
emane_node.installnetifs()
node = self._emane_nets[key]
logging.info("emane install interface for node(%s): %d", node.name, key)
node.install_ifaces()
def deinstallnetifs(self) -> None:
def deinstall_ifaces(self) -> None:
"""
Uninstall TUN/TAP virtual interfaces.
"""
for key in sorted(self._emane_nets.keys()):
emane_node = self._emane_nets[key]
emane_node.deinstallnetifs()
emane_node.deinstall_ifaces()
def doeventmonitor(self) -> bool:
"""
@ -808,12 +806,12 @@ class EmaneManager(ModelManager):
Returns True if successfully parsed and a Node Message was sent.
"""
# convert nemid to node number
_emanenode, netif = self.nemlookup(nemid)
if netif is None:
_emanenode, iface = self.nemlookup(nemid)
if iface is None:
logging.info("location event for unknown NEM %s", nemid)
return False
n = netif.node.id
n = iface.node.id
# convert from lat/long/alt to x,y,z coordinates
x, y, z = self.session.location.getxyz(lat, lon, alt)
x = int(x)

View file

@ -8,7 +8,7 @@ from typing import Dict, List, Optional, Set
from core.config import ConfigGroup, Configuration
from core.emane import emanemanifest
from core.emane.nodes import EmaneNet
from core.emulator.emudata import LinkOptions
from core.emulator.data import LinkOptions
from core.emulator.enumerations import ConfigDataTypes, TransportType
from core.errors import CoreError
from core.location.mobility import WirelessModel
@ -97,28 +97,28 @@ class EmaneModel(WirelessModel):
]
def build_xml_files(
self, config: Dict[str, str], interface: CoreInterface = None
self, config: Dict[str, str], iface: CoreInterface = None
) -> None:
"""
Builds xml files for this emane model. Creates a nem.xml file that points to
both mac.xml and phy.xml definitions.
:param config: emane model configuration for the node and interface
:param interface: interface for the emane node
:param iface: interface for the emane node
:return: nothing
"""
nem_name = emanexml.nem_file_name(self, interface)
mac_name = emanexml.mac_file_name(self, interface)
phy_name = emanexml.phy_file_name(self, interface)
nem_name = emanexml.nem_file_name(self, iface)
mac_name = emanexml.mac_file_name(self, iface)
phy_name = emanexml.phy_file_name(self, iface)
# remote server for file
server = None
if interface is not None:
server = interface.node.server
if iface is not None:
server = iface.node.server
# check if this is external
transport_type = TransportType.VIRTUAL
if interface and interface.transport_type == TransportType.RAW:
if iface and iface.transport_type == TransportType.RAW:
transport_type = TransportType.RAW
transport_name = emanexml.transport_file_name(self.id, transport_type)
@ -144,31 +144,31 @@ class EmaneModel(WirelessModel):
"""
logging.debug("emane model(%s) has no post setup tasks", self.name)
def update(self, moved: List[CoreNode], moved_netifs: List[CoreInterface]) -> None:
def update(self, moved: List[CoreNode], moved_ifaces: List[CoreInterface]) -> None:
"""
Invoked from MobilityModel when nodes are moved; this causes
emane location events to be generated for the nodes in the moved
list, making EmaneModels compatible with Ns2ScriptedMobility.
:param moved: moved nodes
:param moved_netifs: interfaces that were moved
:param moved_ifaces: interfaces that were moved
:return: nothing
"""
try:
wlan = self.session.get_node(self.id, EmaneNet)
wlan.setnempositions(moved_netifs)
wlan.setnempositions(moved_ifaces)
except CoreError:
logging.exception("error during update")
def linkconfig(
self, netif: CoreInterface, options: LinkOptions, netif2: CoreInterface = None
self, iface: CoreInterface, options: LinkOptions, iface2: CoreInterface = None
) -> None:
"""
Invoked when a Link Message is received. Default is unimplemented.
:param netif: interface one
:param iface: interface one
:param options: options for configuring link
:param netif2: interface two
:param iface2: interface two
:return: nothing
"""
logging.warning("emane model(%s) does not support link config", self.name)

View file

@ -212,10 +212,10 @@ class EmaneLinkMonitor:
addresses = []
nodes = self.emane_manager.getnodes()
for node in nodes:
for netif in node.netifs():
if isinstance(netif.net, CtrlNet):
for iface in node.get_ifaces():
if isinstance(iface.net, CtrlNet):
ip4 = None
for x in netif.addrlist:
for x in iface.addrlist:
address, prefix = x.split("/")
if netaddr.valid_ipv4(address):
ip4 = address
@ -305,11 +305,11 @@ class EmaneLinkMonitor:
color = self.emane_manager.session.get_link_color(emane_id)
link_data = LinkData(
message_type=message_type,
type=LinkTypes.WIRELESS,
label=label,
node1_id=node1,
node2_id=node2,
network_id=emane_id,
link_type=LinkTypes.WIRELESS,
color=color,
)
self.emane_manager.session.broadcast_link(link_data)

View file

@ -6,9 +6,8 @@ share the same MAC+PHY model.
import logging
from typing import TYPE_CHECKING, Dict, List, Optional, Tuple, Type
from core.emulator.data import LinkData
from core.emulator.data import LinkData, LinkOptions
from core.emulator.distributed import DistributedServer
from core.emulator.emudata import LinkOptions
from core.emulator.enumerations import (
LinkTypes,
MessageFlags,
@ -64,14 +63,14 @@ class EmaneNet(CoreNetworkBase):
self.mobility: Optional[WayPointMobility] = None
def linkconfig(
self, netif: CoreInterface, options: LinkOptions, netif2: CoreInterface = None
self, iface: CoreInterface, options: LinkOptions, iface2: CoreInterface = None
) -> None:
"""
The CommEffect model supports link configuration.
"""
if not self.model:
return
self.model.linkconfig(netif, options, netif2)
self.model.linkconfig(iface, options, iface2)
def config(self, conf: str) -> None:
self.conf = conf
@ -82,10 +81,10 @@ class EmaneNet(CoreNetworkBase):
def shutdown(self) -> None:
pass
def link(self, netif1: CoreInterface, netif2: CoreInterface) -> None:
def link(self, iface1: CoreInterface, iface2: CoreInterface) -> None:
pass
def unlink(self, netif1: CoreInterface, netif2: CoreInterface) -> None:
def unlink(self, iface1: CoreInterface, iface2: CoreInterface) -> None:
pass
def linknet(self, net: "CoreNetworkBase") -> CoreInterface:
@ -113,39 +112,33 @@ class EmaneNet(CoreNetworkBase):
self.mobility = model(session=self.session, _id=self.id)
self.mobility.update_config(config)
def setnemid(self, netif: CoreInterface, nemid: int) -> None:
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[netif] = nemid
self.nemidmap[iface] = nemid
def getnemid(self, netif: CoreInterface) -> Optional[int]:
def getnemid(self, iface: CoreInterface) -> Optional[int]:
"""
Given an interface, return its numerical ID.
"""
if netif not in self.nemidmap:
if iface not in self.nemidmap:
return None
else:
return self.nemidmap[netif]
return self.nemidmap[iface]
def getnemnetif(self, nemid: int) -> Optional[CoreInterface]:
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 netif in self.nemidmap:
if self.nemidmap[netif] == nemid:
return netif
for iface in self.nemidmap:
if self.nemidmap[iface] == nemid:
return iface
return None
def netifs(self, sort: bool = True) -> List[CoreInterface]:
"""
Retrieve list of linked interfaces sorted by node number.
"""
return sorted(self._netif.values(), key=lambda ifc: ifc.node.id)
def installnetifs(self) -> None:
def install_ifaces(self) -> None:
"""
Install TAP devices into their namespaces. This is done after
EMANE daemons have been started, because that is their only chance
@ -159,48 +152,48 @@ class EmaneNet(CoreNetworkBase):
warntxt += "Python bindings failed to load"
logging.error(warntxt)
for netif in self.netifs():
for iface in self.get_ifaces():
external = self.session.emane.get_config(
"external", self.id, self.model.name
)
if external == "0":
netif.setaddrs()
iface.setaddrs()
if not self.session.emane.genlocationevents():
netif.poshook = None
iface.poshook = None
continue
# at this point we register location handlers for generating
# EMANE location events
netif.poshook = self.setnemposition
netif.setposition()
iface.poshook = self.setnemposition
iface.setposition()
def deinstallnetifs(self) -> None:
def deinstall_ifaces(self) -> None:
"""
Uninstall TAP devices. This invokes their shutdown method for
any required cleanup; the device may be actually removed when
emanetransportd terminates.
"""
for netif in self.netifs():
if netif.transport_type == TransportType.VIRTUAL:
netif.shutdown()
netif.poshook = None
for iface in self.get_ifaces():
if iface.transport_type == TransportType.VIRTUAL:
iface.shutdown()
iface.poshook = None
def _nem_position(
self, netif: CoreInterface
self, iface: CoreInterface
) -> Optional[Tuple[int, float, float, float]]:
"""
Creates nem position for emane event for a given interface.
:param netif: interface to get nem emane position for
:param iface: interface to get nem emane position for
:return: nem position tuple, None otherwise
"""
nemid = self.getnemid(netif)
ifname = netif.localname
nemid = self.getnemid(iface)
ifname = iface.localname
if nemid is None:
logging.info("nemid for %s is unknown", ifname)
return
node = netif.node
node = iface.node
x, y, z = node.getposition()
lat, lon, alt = self.session.location.getgeo(x, y, z)
if node.position.alt is not None:
@ -210,30 +203,30 @@ class EmaneNet(CoreNetworkBase):
alt = int(round(alt))
return nemid, lon, lat, alt
def setnemposition(self, netif: CoreInterface) -> None:
def setnemposition(self, iface: CoreInterface) -> None:
"""
Publish a NEM location change event using the EMANE event service.
:param netif: interface to set nem position for
:param iface: interface to set nem position for
"""
if self.session.emane.service is None:
logging.info("position service not available")
return
position = self._nem_position(netif)
position = self._nem_position(iface)
if position:
nemid, lon, lat, alt = position
event = LocationEvent()
event.append(nemid, latitude=lat, longitude=lon, altitude=alt)
self.session.emane.service.publish(0, event)
def setnempositions(self, moved_netifs: List[CoreInterface]) -> None:
def setnempositions(self, moved_ifaces: List[CoreInterface]) -> None:
"""
Several NEMs have moved, from e.g. a WaypointMobilityModel
calculation. Generate an EMANE Location Event having several
entries for each netif that has moved.
entries for each interface that has moved.
"""
if len(moved_netifs) == 0:
if len(moved_ifaces) == 0:
return
if self.session.emane.service is None:
@ -241,8 +234,8 @@ class EmaneNet(CoreNetworkBase):
return
event = LocationEvent()
for netif in moved_netifs:
position = self._nem_position(netif)
for iface in moved_ifaces:
position = self._nem_position(iface)
if position:
nemid, lon, lat, alt = position
event.append(nemid, latitude=lat, longitude=lon, altitude=alt)

View file

@ -1,18 +1,22 @@
"""
CORE data objects.
"""
from dataclasses import dataclass, field
from typing import TYPE_CHECKING, List, Optional, Tuple
from dataclasses import dataclass
from typing import List, Tuple
import netaddr
from core import utils
from core.emulator.enumerations import (
EventTypes,
ExceptionLevels,
LinkTypes,
MessageFlags,
NodeTypes,
)
if TYPE_CHECKING:
from core.nodes.base import CoreNode, NodeBase
@dataclass
class ConfigData:
@ -27,7 +31,7 @@ class ConfigData:
possible_values: str = None
groups: str = None
session: int = None
interface_number: int = None
iface_id: int = None
network_id: int = None
opaque: str = None
@ -68,65 +72,217 @@ class FileData:
@dataclass
class NodeData:
message_type: MessageFlags = None
id: int = None
node_type: NodeTypes = None
class NodeOptions:
"""
Options for creating and updating nodes within core.
"""
name: str = None
ip_address: str = None
mac_address: str = None
ip6_address: str = None
model: str = None
emulation_id: int = None
server: str = None
session: int = None
x_position: float = None
y_position: float = None
model: Optional[str] = "PC"
canvas: int = None
network_id: int = None
services: List[str] = None
latitude: float = None
longitude: float = None
altitude: float = None
icon: str = None
opaque: str = None
services: List[str] = field(default_factory=list)
config_services: List[str] = field(default_factory=list)
x: float = None
y: float = None
lat: float = None
lon: float = None
alt: float = None
server: str = None
image: str = None
emane: str = None
def set_position(self, x: float, y: float) -> None:
"""
Convenience method for setting position.
:param x: x position
:param y: y position
:return: nothing
"""
self.x = x
self.y = y
def set_location(self, lat: float, lon: float, alt: float) -> None:
"""
Convenience method for setting location.
:param lat: latitude
:param lon: longitude
:param alt: altitude
:return: nothing
"""
self.lat = lat
self.lon = lon
self.alt = alt
@dataclass
class NodeData:
"""
Node to broadcast.
"""
node: "NodeBase"
message_type: MessageFlags = None
source: str = None
@dataclass
class InterfaceData:
"""
Convenience class for storing interface data.
"""
id: int = None
name: str = None
mac: str = None
ip4: str = None
ip4_mask: int = None
ip6: str = None
ip6_mask: int = None
def get_addresses(self) -> List[str]:
"""
Returns a list of ip4 and ip6 addresses when present.
:return: list of addresses
"""
addresses = []
if self.ip4 and self.ip4_mask:
addresses.append(f"{self.ip4}/{self.ip4_mask}")
if self.ip6 and self.ip6_mask:
addresses.append(f"{self.ip6}/{self.ip6_mask}")
return addresses
@dataclass
class LinkOptions:
"""
Options for creating and updating links within core.
"""
delay: int = None
bandwidth: int = None
loss: float = None
dup: int = None
jitter: int = None
mer: int = None
burst: int = None
mburst: int = None
unidirectional: int = None
key: int = None
@dataclass
class LinkData:
"""
Represents all data associated with a link.
"""
message_type: MessageFlags = None
type: LinkTypes = LinkTypes.WIRED
label: str = None
node1_id: int = None
node2_id: int = None
delay: float = None
bandwidth: float = None
loss: float = None
dup: float = None
jitter: float = None
mer: float = None
burst: float = None
session: int = None
mburst: float = None
link_type: LinkTypes = None
gui_attributes: str = None
unidirectional: int = None
emulation_id: int = None
network_id: int = None
key: int = None
interface1_id: int = None
interface1_name: str = None
interface1_ip4: str = None
interface1_ip4_mask: int = None
interface1_mac: str = None
interface1_ip6: str = None
interface1_ip6_mask: int = None
interface2_id: int = None
interface2_name: str = None
interface2_ip4: str = None
interface2_ip4_mask: int = None
interface2_mac: str = None
interface2_ip6: str = None
interface2_ip6_mask: int = None
opaque: str = None
iface1: InterfaceData = None
iface2: InterfaceData = None
options: LinkOptions = LinkOptions()
color: str = None
class IpPrefixes:
"""
Convenience class to help generate IP4 and IP6 addresses for nodes within CORE.
"""
def __init__(self, ip4_prefix: str = None, ip6_prefix: str = None) -> None:
"""
Creates an IpPrefixes object.
:param ip4_prefix: ip4 prefix to use for generation
:param ip6_prefix: ip6 prefix to use for generation
:raises ValueError: when both ip4 and ip6 prefixes have not been provided
"""
if not ip4_prefix and not ip6_prefix:
raise ValueError("ip4 or ip6 must be provided")
self.ip4 = None
if ip4_prefix:
self.ip4 = netaddr.IPNetwork(ip4_prefix)
self.ip6 = None
if ip6_prefix:
self.ip6 = netaddr.IPNetwork(ip6_prefix)
def ip4_address(self, node_id: int) -> str:
"""
Convenience method to return the IP4 address for a node.
:param node_id: node id to get IP4 address for
:return: IP4 address or None
"""
if not self.ip4:
raise ValueError("ip4 prefixes have not been set")
return str(self.ip4[node_id])
def ip6_address(self, node_id: int) -> str:
"""
Convenience method to return the IP6 address for a node.
:param node_id: node id to get IP6 address for
:return: IP4 address or None
"""
if not self.ip6:
raise ValueError("ip6 prefixes have not been set")
return str(self.ip6[node_id])
def gen_iface(self, node_id: int, name: str = None, mac: str = None):
"""
Creates interface data for linking nodes, using the nodes unique id for
generation, along with a random mac address, unless provided.
:param node_id: node id to create an interface for
:param name: name to set for interface, default is eth{id}
:param mac: mac address to use for this interface, default is random
generation
:return: new interface data for the provided node
"""
# generate ip4 data
ip4 = None
ip4_mask = None
if self.ip4:
ip4 = self.ip4_address(node_id)
ip4_mask = self.ip4.prefixlen
# generate ip6 data
ip6 = None
ip6_mask = None
if self.ip6:
ip6 = self.ip6_address(node_id)
ip6_mask = self.ip6.prefixlen
# random mac
if not mac:
mac = utils.random_mac()
return InterfaceData(
name=name, ip4=ip4, ip4_mask=ip4_mask, ip6=ip6, ip6_mask=ip6_mask, mac=mac
)
def create_iface(
self, node: "CoreNode", name: str = None, mac: str = None
) -> InterfaceData:
"""
Creates interface data for linking nodes, using the nodes unique id for
generation, along with a random mac address, unless provided.
:param node: node to create interface for
:param name: name to set for interface, default is eth{id}
:param mac: mac address to use for this interface, default is random
generation
:return: new interface data for the provided node
"""
iface_data = self.gen_iface(node.id, name, mac)
iface_data.id = node.next_iface_id()
return iface_data

View file

@ -208,7 +208,7 @@ class DistributedController:
"local tunnel node(%s) to remote(%s) key(%s)", node.name, host, key
)
local_tap = GreTap(session=self.session, remoteip=host, key=key)
local_tap.net_client.set_interface_master(node.brname, local_tap.localname)
local_tap.net_client.set_iface_master(node.brname, local_tap.localname)
# server to local
logging.info(
@ -217,7 +217,7 @@ class DistributedController:
remote_tap = GreTap(
session=self.session, remoteip=self.address, key=key, server=server
)
remote_tap.net_client.set_interface_master(node.brname, remote_tap.localname)
remote_tap.net_client.set_iface_master(node.brname, remote_tap.localname)
# save tunnels for shutdown
tunnel = (local_tap, remote_tap)

View file

@ -1,206 +0,0 @@
from dataclasses import dataclass, field
from typing import TYPE_CHECKING, List, Optional
import netaddr
from core import utils
from core.emulator.enumerations import LinkTypes
if TYPE_CHECKING:
from core.nodes.base import CoreNode
@dataclass
class NodeOptions:
"""
Options for creating and updating nodes within core.
"""
name: str = None
model: Optional[str] = "PC"
canvas: int = None
icon: str = None
opaque: str = None
services: List[str] = field(default_factory=list)
config_services: List[str] = field(default_factory=list)
x: float = None
y: float = None
lat: float = None
lon: float = None
alt: float = None
emulation_id: int = None
server: str = None
image: str = None
emane: str = None
def set_position(self, x: float, y: float) -> None:
"""
Convenience method for setting position.
:param x: x position
:param y: y position
:return: nothing
"""
self.x = x
self.y = y
def set_location(self, lat: float, lon: float, alt: float) -> None:
"""
Convenience method for setting location.
:param lat: latitude
:param lon: longitude
:param alt: altitude
:return: nothing
"""
self.lat = lat
self.lon = lon
self.alt = alt
@dataclass
class LinkOptions:
"""
Options for creating and updating links within core.
"""
type: LinkTypes = LinkTypes.WIRED
session: int = None
delay: int = None
bandwidth: int = None
loss: float = None
dup: int = None
jitter: int = None
mer: int = None
burst: int = None
mburst: int = None
gui_attributes: str = None
unidirectional: bool = None
emulation_id: int = None
network_id: int = None
key: int = None
opaque: str = None
@dataclass
class InterfaceData:
"""
Convenience class for storing interface data.
"""
id: int = None
name: str = None
mac: str = None
ip4: str = None
ip4_mask: int = None
ip6: str = None
ip6_mask: int = None
def get_addresses(self) -> List[str]:
"""
Returns a list of ip4 and ip6 addresses when present.
:return: list of addresses
"""
addresses = []
if self.ip4 and self.ip4_mask:
addresses.append(f"{self.ip4}/{self.ip4_mask}")
if self.ip6 and self.ip6_mask:
addresses.append(f"{self.ip6}/{self.ip6_mask}")
return addresses
class IpPrefixes:
"""
Convenience class to help generate IP4 and IP6 addresses for nodes within CORE.
"""
def __init__(self, ip4_prefix: str = None, ip6_prefix: str = None) -> None:
"""
Creates an IpPrefixes object.
:param ip4_prefix: ip4 prefix to use for generation
:param ip6_prefix: ip6 prefix to use for generation
:raises ValueError: when both ip4 and ip6 prefixes have not been provided
"""
if not ip4_prefix and not ip6_prefix:
raise ValueError("ip4 or ip6 must be provided")
self.ip4 = None
if ip4_prefix:
self.ip4 = netaddr.IPNetwork(ip4_prefix)
self.ip6 = None
if ip6_prefix:
self.ip6 = netaddr.IPNetwork(ip6_prefix)
def ip4_address(self, node_id: int) -> str:
"""
Convenience method to return the IP4 address for a node.
:param node_id: node id to get IP4 address for
:return: IP4 address or None
"""
if not self.ip4:
raise ValueError("ip4 prefixes have not been set")
return str(self.ip4[node_id])
def ip6_address(self, node_id: int) -> str:
"""
Convenience method to return the IP6 address for a node.
:param node_id: node id to get IP6 address for
:return: IP4 address or None
"""
if not self.ip6:
raise ValueError("ip6 prefixes have not been set")
return str(self.ip6[node_id])
def gen_interface(self, node_id: int, name: str = None, mac: str = None):
"""
Creates interface data for linking nodes, using the nodes unique id for
generation, along with a random mac address, unless provided.
:param node_id: node id to create an interface for
:param name: name to set for interface, default is eth{id}
:param mac: mac address to use for this interface, default is random
generation
:return: new interface data for the provided node
"""
# generate ip4 data
ip4 = None
ip4_mask = None
if self.ip4:
ip4 = self.ip4_address(node_id)
ip4_mask = self.ip4.prefixlen
# generate ip6 data
ip6 = None
ip6_mask = None
if self.ip6:
ip6 = self.ip6_address(node_id)
ip6_mask = self.ip6.prefixlen
# random mac
if not mac:
mac = utils.random_mac()
return InterfaceData(
name=name, ip4=ip4, ip4_mask=ip4_mask, ip6=ip6, ip6_mask=ip6_mask, mac=mac
)
def create_interface(
self, node: "CoreNode", name: str = None, mac: str = None
) -> InterfaceData:
"""
Creates interface data for linking nodes, using the nodes unique id for
generation, along with a random mac address, unless provided.
:param node: node to create interface for
:param name: name to set for interface, default is eth{id}
:param mac: mac address to use for this interface, default is random
generation
:return: new interface data for the provided node
"""
interface_data = self.gen_interface(node.id, name, mac)
interface_data.id = node.newifindex()
return interface_data

View file

@ -22,11 +22,13 @@ from core.emulator.data import (
EventData,
ExceptionData,
FileData,
InterfaceData,
LinkData,
LinkOptions,
NodeData,
NodeOptions,
)
from core.emulator.distributed import DistributedController
from core.emulator.emudata import InterfaceData, LinkOptions, NodeOptions
from core.emulator.enumerations import (
EventTypes,
ExceptionLevels,
@ -203,7 +205,7 @@ class Session:
common_networks = node1.commonnets(node1)
if not common_networks:
raise CoreError("no common network found for wireless link/unlink")
for common_network, interface1, interface2 in common_networks:
for common_network, iface1, iface2 in common_networks:
if not isinstance(common_network, (WlanNode, EmaneNet)):
logging.info(
"skipping common network that is not wireless/emane: %s",
@ -211,40 +213,42 @@ class Session:
)
continue
if connect:
common_network.link(interface1, interface2)
common_network.link(iface1, iface2)
else:
common_network.unlink(interface1, interface2)
common_network.unlink(iface1, iface2)
def add_link(
self,
node1_id: int,
node2_id: int,
interface1_data: InterfaceData = None,
interface2_data: InterfaceData = None,
iface1_data: InterfaceData = None,
iface2_data: InterfaceData = None,
options: LinkOptions = None,
link_type: LinkTypes = LinkTypes.WIRED,
) -> Tuple[CoreInterface, CoreInterface]:
"""
Add a link between nodes.
:param node1_id: node one id
:param node2_id: node two id
:param interface1_data: node one interface
:param iface1_data: node one interface
data, defaults to none
:param interface2_data: node two interface
:param iface2_data: node two interface
data, defaults to none
:param options: data for creating link,
defaults to no options
:param link_type: type of link to add
:return: tuple of created core interfaces, depending on link
"""
if not options:
options = LinkOptions()
node1 = self.get_node(node1_id, NodeBase)
node2 = self.get_node(node2_id, NodeBase)
interface1 = None
interface2 = None
iface1 = None
iface2 = None
# wireless link
if options.type == LinkTypes.WIRELESS:
if link_type == LinkTypes.WIRELESS:
if isinstance(node1, CoreNodeBase) and isinstance(node2, CoreNodeBase):
self._link_wireless(node1, node2, connect=True)
else:
@ -258,22 +262,22 @@ class Session:
logging.info("linking ptp: %s - %s", node1.name, node2.name)
start = self.state.should_start()
ptp = self.create_node(PtpNet, start)
interface1 = node1.newnetif(ptp, interface1_data)
interface2 = node2.newnetif(ptp, interface2_data)
ptp.linkconfig(interface1, options)
iface1 = node1.new_iface(ptp, iface1_data)
iface2 = node2.new_iface(ptp, iface2_data)
ptp.linkconfig(iface1, options)
if not options.unidirectional:
ptp.linkconfig(interface2, options)
ptp.linkconfig(iface2, options)
# link node to net
elif isinstance(node1, CoreNodeBase) and isinstance(node2, CoreNetworkBase):
interface1 = node1.newnetif(node2, interface1_data)
iface1 = node1.new_iface(node2, iface1_data)
if not isinstance(node2, (EmaneNet, WlanNode)):
node2.linkconfig(interface1, options)
node2.linkconfig(iface1, options)
# link net to node
elif isinstance(node2, CoreNodeBase) and isinstance(node1, CoreNetworkBase):
interface2 = node2.newnetif(node1, interface2_data)
iface2 = node2.new_iface(node1, iface2_data)
wireless_net = isinstance(node1, (EmaneNet, WlanNode))
if not options.unidirectional and not wireless_net:
node1.linkconfig(interface2, options)
node1.linkconfig(iface2, options)
# network to network
elif isinstance(node1, CoreNetworkBase) and isinstance(
node2, CoreNetworkBase
@ -281,12 +285,12 @@ class Session:
logging.info(
"linking network to network: %s - %s", node1.name, node2.name
)
interface1 = node1.linknet(node2)
node1.linkconfig(interface1, options)
iface1 = node1.linknet(node2)
node1.linkconfig(iface1, options)
if not options.unidirectional:
interface1.swapparams("_params_up")
node2.linkconfig(interface1, options)
interface1.swapparams("_params_up")
iface1.swapparams("_params_up")
node2.linkconfig(iface1, options)
iface1.swapparams("_params_up")
else:
raise CoreError(
f"cannot link node1({type(node1)}) node2({type(node2)})"
@ -296,19 +300,19 @@ class Session:
key = options.key
if isinstance(node1, TunnelNode):
logging.info("setting tunnel key for: %s", node1.name)
node1.setkey(key, interface1_data)
node1.setkey(key, iface1_data)
if isinstance(node2, TunnelNode):
logging.info("setting tunnel key for: %s", node2.name)
node2.setkey(key, interface2_data)
node2.setkey(key, iface2_data)
self.sdt.add_link(node1_id, node2_id)
return interface1, interface2
return iface1, iface2
def delete_link(
self,
node1_id: int,
node2_id: int,
interface1_id: int = None,
interface2_id: int = None,
iface1_id: int = None,
iface2_id: int = None,
link_type: LinkTypes = LinkTypes.WIRED,
) -> None:
"""
@ -316,8 +320,8 @@ class Session:
:param node1_id: node one id
:param node2_id: node two id
:param interface1_id: interface id for node one
:param interface2_id: interface id for node two
:param iface1_id: interface id for node one
:param iface2_id: interface id for node two
:param link_type: link type to delete
:return: nothing
:raises core.CoreError: when no common network is found for link being deleted
@ -328,9 +332,9 @@ class Session:
"deleting link(%s) node(%s):interface(%s) node(%s):interface(%s)",
link_type.name,
node1.name,
interface1_id,
iface1_id,
node2.name,
interface2_id,
iface2_id,
)
# wireless link
@ -345,47 +349,41 @@ class Session:
# wired link
else:
if isinstance(node1, CoreNodeBase) and isinstance(node2, CoreNodeBase):
interface1 = node1.netif(interface1_id)
interface2 = node2.netif(interface2_id)
if not interface1:
raise CoreError(
f"node({node1.name}) missing interface({interface1_id})"
)
if not interface2:
raise CoreError(
f"node({node2.name}) missing interface({interface2_id})"
)
if interface1.net != interface2.net:
iface1 = node1.get_iface(iface1_id)
iface2 = node2.get_iface(iface2_id)
if iface1.net != iface2.net:
raise CoreError(
f"node1({node1.name}) node2({node2.name}) "
"not connected to same net"
)
ptp = interface1.net
node1.delnetif(interface1_id)
node2.delnetif(interface2_id)
ptp = iface1.net
node1.delete_iface(iface1_id)
node2.delete_iface(iface2_id)
self.delete_node(ptp.id)
elif isinstance(node1, CoreNodeBase) and isinstance(node2, CoreNetworkBase):
node1.delnetif(interface1_id)
node1.delete_iface(iface1_id)
elif isinstance(node2, CoreNodeBase) and isinstance(node1, CoreNetworkBase):
node2.delnetif(interface2_id)
node2.delete_iface(iface2_id)
self.sdt.delete_link(node1_id, node2_id)
def update_link(
self,
node1_id: int,
node2_id: int,
interface1_id: int = None,
interface2_id: int = None,
iface1_id: int = None,
iface2_id: int = None,
options: LinkOptions = None,
link_type: LinkTypes = LinkTypes.WIRED,
) -> None:
"""
Update link information between nodes.
:param node1_id: node one id
:param node2_id: node two id
:param interface1_id: interface id for node one
:param interface2_id: interface id for node two
:param iface1_id: interface id for node one
:param iface2_id: interface id for node two
:param options: data to update link with
:param link_type: type of link to update
:return: nothing
:raises core.CoreError: when updating a wireless type link, when there is a
unknown link between networks
@ -396,66 +394,66 @@ class Session:
node2 = self.get_node(node2_id, NodeBase)
logging.info(
"update link(%s) node(%s):interface(%s) node(%s):interface(%s)",
options.type.name,
link_type.name,
node1.name,
interface1_id,
iface1_id,
node2.name,
interface2_id,
iface2_id,
)
# wireless link
if options.type == LinkTypes.WIRELESS:
if link_type == LinkTypes.WIRELESS:
raise CoreError("cannot update wireless link")
else:
if isinstance(node1, CoreNodeBase) and isinstance(node2, CoreNodeBase):
interface1 = node1.netif(interface1_id)
interface2 = node2.netif(interface2_id)
if not interface1:
iface1 = node1.ifaces.get(iface1_id)
iface2 = node2.ifaces.get(iface2_id)
if not iface1:
raise CoreError(
f"node({node1.name}) missing interface({interface1_id})"
f"node({node1.name}) missing interface({iface1_id})"
)
if not interface2:
if not iface2:
raise CoreError(
f"node({node2.name}) missing interface({interface2_id})"
f"node({node2.name}) missing interface({iface2_id})"
)
if interface1.net != interface2.net:
if iface1.net != iface2.net:
raise CoreError(
f"node1({node1.name}) node2({node2.name}) "
"not connected to same net"
)
ptp = interface1.net
ptp.linkconfig(interface1, options, interface2)
ptp = iface1.net
ptp.linkconfig(iface1, options, iface2)
if not options.unidirectional:
ptp.linkconfig(interface2, options, interface1)
ptp.linkconfig(iface2, options, iface1)
elif isinstance(node1, CoreNodeBase) and isinstance(node2, CoreNetworkBase):
interface = node1.netif(interface1_id)
node2.linkconfig(interface, options)
iface = node1.get_iface(iface1_id)
node2.linkconfig(iface, options)
elif isinstance(node2, CoreNodeBase) and isinstance(node1, CoreNetworkBase):
interface = node2.netif(interface2_id)
node1.linkconfig(interface, options)
iface = node2.get_iface(iface2_id)
node1.linkconfig(iface, options)
elif isinstance(node1, CoreNetworkBase) and isinstance(
node2, CoreNetworkBase
):
interface = node1.getlinknetif(node2)
iface = node1.get_linked_iface(node2)
upstream = False
if not interface:
if not iface:
upstream = True
interface = node2.getlinknetif(node1)
if not interface:
iface = node2.get_linked_iface(node1)
if not iface:
raise CoreError("modify unknown link between nets")
if upstream:
interface.swapparams("_params_up")
node1.linkconfig(interface, options)
interface.swapparams("_params_up")
iface.swapparams("_params_up")
node1.linkconfig(iface, options)
iface.swapparams("_params_up")
else:
node1.linkconfig(interface, options)
node1.linkconfig(iface, options)
if not options.unidirectional:
if upstream:
node2.linkconfig(interface, options)
node2.linkconfig(iface, options)
else:
interface.swapparams("_params_up")
node2.linkconfig(interface, options)
interface.swapparams("_params_up")
iface.swapparams("_params_up")
node2.linkconfig(iface, options)
iface.swapparams("_params_up")
else:
raise CoreError(
f"cannot update link node1({type(node1)}) node2({type(node2)})"
@ -525,7 +523,6 @@ class Session:
# set node attributes
node.icon = options.icon
node.canvas = options.canvas
node.opaque = options.opaque
# set node position and broadcast it
self.set_node_position(node, options)
@ -553,7 +550,7 @@ class Session:
is_boot_node = isinstance(node, CoreNodeBase) and not isinstance(node, Rj45Node)
if self.state == EventTypes.RUNTIME_STATE and is_boot_node:
self.write_nodes()
self.add_remove_control_interface(node=node, remove=False)
self.add_remove_control_iface(node=node, remove=False)
self.services.boot_services(node)
self.sdt.add_node(node)
@ -810,9 +807,9 @@ class Session:
:param source: source of broadcast, None by default
:return: nothing
"""
node_data = node.data(message_type, source)
if not node_data:
if not node.apitype:
return
node_data = NodeData(node=node, message_type=message_type, source=source)
for handler in self.node_handlers:
handler(node_data)
@ -1268,7 +1265,7 @@ class Session:
self.emane.shutdown()
# update control interface hosts
self.update_control_interface_hosts(remove=True)
self.update_control_iface_hosts(remove=True)
# remove all four possible control networks
self.add_remove_control_net(0, remove=True)
@ -1314,7 +1311,7 @@ class Session:
:return: nothing
"""
logging.info("booting node(%s): %s", node.name, [x.name for x in node.services])
self.add_remove_control_interface(node=node, remove=False)
self.add_remove_control_iface(node=node, remove=False)
self.services.boot_services(node)
node.start_config_services()
@ -1338,7 +1335,7 @@ class Session:
total = time.monotonic() - start
logging.debug("boot run time: %s", total)
if not exceptions:
self.update_control_interface_hosts()
self.update_control_iface_hosts()
return exceptions
def get_control_net_prefixes(self) -> List[str]:
@ -1356,7 +1353,7 @@ class Session:
p0 = p
return [p0, p1, p2, p3]
def get_control_net_server_interfaces(self) -> List[str]:
def get_control_net_server_ifaces(self) -> List[str]:
"""
Retrieve control net server interfaces.
@ -1424,7 +1421,7 @@ class Session:
else:
prefix_spec = CtrlNet.DEFAULT_PREFIX_LIST[net_index]
logging.debug("prefix spec: %s", prefix_spec)
server_interface = self.get_control_net_server_interfaces()[net_index]
server_iface = self.get_control_net_server_ifaces()[net_index]
# return any existing controlnet bridge
try:
@ -1465,7 +1462,7 @@ class Session:
_id,
prefix,
updown_script,
server_interface,
server_iface,
)
control_net = self.create_node(
CtrlNet,
@ -1473,11 +1470,11 @@ class Session:
prefix,
_id=_id,
updown_script=updown_script,
serverintf=server_interface,
serverintf=server_iface,
)
return control_net
def add_remove_control_interface(
def add_remove_control_iface(
self,
node: CoreNode,
net_index: int = 0,
@ -1503,27 +1500,27 @@ class Session:
if not node:
return
# ctrl# already exists
if node.netif(control_net.CTRLIF_IDX_BASE + net_index):
if node.ifaces.get(control_net.CTRLIF_IDX_BASE + net_index):
return
try:
ip4 = control_net.prefix[node.id]
ip4_mask = control_net.prefix.prefixlen
interface_data = InterfaceData(
iface_data = InterfaceData(
id=control_net.CTRLIF_IDX_BASE + net_index,
name=f"ctrl{net_index}",
mac=utils.random_mac(),
ip4=ip4,
ip4_mask=ip4_mask,
)
interface = node.newnetif(control_net, interface_data)
interface.control = True
iface = node.new_iface(control_net, iface_data)
iface.control = True
except ValueError:
msg = f"Control interface not added to node {node.id}. "
msg += f"Invalid control network prefix ({control_net.prefix}). "
msg += "A longer prefix length may be required for this many nodes."
logging.exception(msg)
def update_control_interface_hosts(
def update_control_iface_hosts(
self, net_index: int = 0, remove: bool = False
) -> None:
"""
@ -1549,9 +1546,9 @@ class Session:
return
entries = []
for interface in control_net.netifs():
name = interface.node.name
for address in interface.addrlist:
for iface in control_net.get_ifaces():
name = iface.node.name
for address in iface.addrlist:
address = address.split("/")[0]
entries.append(f"{address} {name}")

View file

@ -57,8 +57,8 @@ class CoreClient:
self.read_config()
# helpers
self.interface_to_edge = {}
self.interfaces_manager = InterfaceManager(self.app)
self.iface_to_edge = {}
self.ifaces_manager = InterfaceManager(self.app)
# session data
self.state = None
@ -91,8 +91,8 @@ class CoreClient:
def reset(self):
# helpers
self.interfaces_manager.reset()
self.interface_to_edge.clear()
self.ifaces_manager.reset()
self.iface_to_edge.clear()
# session data
self.canvas_nodes.clear()
self.links.clear()
@ -263,7 +263,7 @@ class CoreClient:
self.emane_config = response.config
# update interface manager
self.interfaces_manager.joined(session.links)
self.ifaces_manager.joined(session.links)
# draw session
self.app.canvas.reset_and_redraw(session)
@ -278,11 +278,11 @@ class CoreClient:
# get emane model config
response = self.client.get_emane_model_configs(self.session_id)
for config in response.configs:
interface = None
if config.interface != -1:
interface = config.interface
iface_id = None
if config.iface_id != -1:
iface_id = config.iface_id
canvas_node = self.canvas_nodes[config.node_id]
canvas_node.emane_model_configs[(config.model, interface)] = dict(
canvas_node.emane_model_configs[(config.model, iface_id)] = dict(
config.config
)
@ -460,16 +460,16 @@ class CoreClient:
self.app.show_grpc_exception("Edit Node Error", e)
def start_session(self) -> core_pb2.StartSessionResponse:
self.interfaces_manager.reset_mac()
self.ifaces_manager.reset_mac()
nodes = [x.core_node for x in self.canvas_nodes.values()]
links = []
for edge in self.links.values():
link = core_pb2.Link()
link.CopyFrom(edge.link)
if link.HasField("interface1") and not link.interface1.mac:
link.interface1.mac = self.interfaces_manager.next_mac()
if link.HasField("interface2") and not link.interface2.mac:
link.interface2.mac = self.interfaces_manager.next_mac()
if link.HasField("iface1") and not link.iface1.mac:
link.iface1.mac = self.ifaces_manager.next_mac()
if link.HasField("iface2") and not link.iface2.mac:
link.iface2.mac = self.ifaces_manager.next_mac()
links.append(link)
wlan_configs = self.get_wlan_configs_proto()
mobility_configs = self.get_mobility_configs_proto()
@ -689,8 +689,8 @@ class CoreClient:
self.session_id,
link_proto.node1_id,
link_proto.node2_id,
link_proto.interface1,
link_proto.interface2,
link_proto.iface1,
link_proto.iface2,
link_proto.options,
)
logging.debug("create link: %s", response)
@ -733,7 +733,7 @@ class CoreClient:
config_proto.node_id,
config_proto.model,
config_proto.config,
config_proto.interface_id,
config_proto.iface_id,
)
if self.emane_config:
config = {x: self.emane_config[x].value for x in self.emane_config}
@ -824,31 +824,31 @@ class CoreClient:
for edge in edges:
del self.links[edge.token]
links.append(edge.link)
self.interfaces_manager.removed(links)
self.ifaces_manager.removed(links)
def create_interface(self, canvas_node: CanvasNode) -> core_pb2.Interface:
def create_iface(self, canvas_node: CanvasNode) -> core_pb2.Interface:
node = canvas_node.core_node
ip4, ip6 = self.interfaces_manager.get_ips(node)
ip4_mask = self.interfaces_manager.ip4_mask
ip6_mask = self.interfaces_manager.ip6_mask
interface_id = canvas_node.next_interface_id()
name = f"eth{interface_id}"
interface = core_pb2.Interface(
id=interface_id,
ip4, ip6 = self.ifaces_manager.get_ips(node)
ip4_mask = self.ifaces_manager.ip4_mask
ip6_mask = self.ifaces_manager.ip6_mask
iface_id = canvas_node.next_iface_id()
name = f"eth{iface_id}"
iface = core_pb2.Interface(
id=iface_id,
name=name,
ip4=ip4,
ip4mask=ip4_mask,
ip4_mask=ip4_mask,
ip6=ip6,
ip6mask=ip6_mask,
ip6_mask=ip6_mask,
)
logging.info(
"create node(%s) interface(%s) IPv4(%s) IPv6(%s)",
node.name,
interface.name,
interface.ip4,
interface.ip6,
iface.name,
iface.ip4,
iface.ip6,
)
return interface
return iface
def create_link(
self, edge: CanvasEdge, canvas_src_node: CanvasNode, canvas_dst_node: CanvasNode
@ -861,34 +861,34 @@ class CoreClient:
dst_node = canvas_dst_node.core_node
# determine subnet
self.interfaces_manager.determine_subnets(canvas_src_node, canvas_dst_node)
self.ifaces_manager.determine_subnets(canvas_src_node, canvas_dst_node)
src_interface = None
src_iface = None
if NodeUtils.is_container_node(src_node.type):
src_interface = self.create_interface(canvas_src_node)
self.interface_to_edge[(src_node.id, src_interface.id)] = edge.token
src_iface = self.create_iface(canvas_src_node)
self.iface_to_edge[(src_node.id, src_iface.id)] = edge.token
dst_interface = None
dst_iface = None
if NodeUtils.is_container_node(dst_node.type):
dst_interface = self.create_interface(canvas_dst_node)
self.interface_to_edge[(dst_node.id, dst_interface.id)] = edge.token
dst_iface = self.create_iface(canvas_dst_node)
self.iface_to_edge[(dst_node.id, dst_iface.id)] = edge.token
link = core_pb2.Link(
type=core_pb2.LinkType.WIRED,
node1_id=src_node.id,
node2_id=dst_node.id,
interface1=src_interface,
interface2=dst_interface,
iface1=src_iface,
iface2=dst_iface,
)
# assign after creating link proto, since interfaces are copied
if src_interface:
interface1 = link.interface1
edge.src_interface = interface1
canvas_src_node.interfaces[interface1.id] = interface1
if dst_interface:
interface2 = link.interface2
edge.dst_interface = interface2
canvas_dst_node.interfaces[interface2.id] = interface2
if src_iface:
iface1 = link.iface1
edge.src_iface = iface1
canvas_src_node.ifaces[iface1.id] = iface1
if dst_iface:
iface2 = link.iface2
edge.dst_iface = iface2
canvas_dst_node.ifaces[iface2.id] = iface2
edge.set_link(link)
self.links[edge.token] = edge
logging.info("Add link between %s and %s", src_node.name, dst_node.name)
@ -928,12 +928,12 @@ class CoreClient:
continue
node_id = canvas_node.core_node.id
for key, config in canvas_node.emane_model_configs.items():
model, interface = key
model, iface_id = key
config = {x: config[x].value for x in config}
if interface is None:
interface = -1
if iface_id is None:
iface_id = -1
config_proto = EmaneModelConfig(
node_id=node_id, interface_id=interface, model=model, config=config
node_id=node_id, iface_id=iface_id, model=model, config=config
)
configs.append(config_proto)
return configs
@ -1021,19 +1021,19 @@ class CoreClient:
return dict(config)
def get_emane_model_config(
self, node_id: int, model: str, interface: int = None
self, node_id: int, model: str, iface_id: int = None
) -> Dict[str, common_pb2.ConfigOption]:
if interface is None:
interface = -1
if iface_id is None:
iface_id = -1
response = self.client.get_emane_model_config(
self.session_id, node_id, model, interface
self.session_id, node_id, model, iface_id
)
config = response.config
logging.debug(
"get emane model config: node id: %s, EMANE model: %s, interface: %s, config: %s",
node_id,
model,
interface,
iface_id,
config,
)
return dict(config)

View file

@ -56,7 +56,7 @@ class EmaneModelDialog(Dialog):
app: "Application",
canvas_node: "CanvasNode",
model: str,
interface: int = None,
iface_id: int = None,
):
super().__init__(
app, f"{canvas_node.core_node.name} {model} Configuration", master=master
@ -64,16 +64,16 @@ class EmaneModelDialog(Dialog):
self.canvas_node = canvas_node
self.node = canvas_node.core_node
self.model = f"emane_{model}"
self.interface = interface
self.iface_id = iface_id
self.config_frame = None
self.has_error = False
try:
self.config = self.canvas_node.emane_model_configs.get(
(self.model, self.interface)
(self.model, self.iface_id)
)
if not self.config:
self.config = self.app.core.get_emane_model_config(
self.node.id, self.model, self.interface
self.node.id, self.model, self.iface_id
)
self.draw()
except grpc.RpcError as e:
@ -103,7 +103,7 @@ class EmaneModelDialog(Dialog):
def click_apply(self):
self.config_frame.parse_config()
key = (self.model, self.interface)
key = (self.model, self.iface_id)
self.canvas_node.emane_model_configs[key] = self.config
self.destroy()

View file

@ -146,6 +146,6 @@ class IpConfigDialog(Dialog):
ip_config.ip6 = self.ip6
ip_config.ip4s = ip4s
ip_config.ip6s = ip6s
self.app.core.interfaces_manager.update_ips(self.ip4, self.ip6)
self.app.core.ifaces_manager.update_ips(self.ip4, self.ip6)
self.app.save_config()
self.destroy()

View file

@ -227,21 +227,21 @@ class LinkConfigurationDialog(Dialog):
)
link.options.CopyFrom(options)
interface1_id = None
if link.HasField("interface1"):
interface1_id = link.interface1.id
interface2_id = None
if link.HasField("interface2"):
interface2_id = link.interface2.id
iface1_id = None
if link.HasField("iface1"):
iface1_id = link.iface1.id
iface2_id = None
if link.HasField("iface2"):
iface2_id = link.iface2.id
if not self.is_symmetric:
link.options.unidirectional = True
asym_interface1 = None
if interface1_id:
asym_interface1 = core_pb2.Interface(id=interface1_id)
asym_interface2 = None
if interface2_id:
asym_interface2 = core_pb2.Interface(id=interface2_id)
asym_iface1 = None
if iface1_id:
asym_iface1 = core_pb2.Interface(id=iface1_id)
asym_iface2 = None
if iface2_id:
asym_iface2 = core_pb2.Interface(id=iface2_id)
down_bandwidth = get_int(self.down_bandwidth)
down_jitter = get_int(self.down_jitter)
down_delay = get_int(self.down_delay)
@ -258,8 +258,8 @@ class LinkConfigurationDialog(Dialog):
self.edge.asymmetric_link = core_pb2.Link(
node1_id=link.node2_id,
node2_id=link.node1_id,
interface1=asym_interface1,
interface2=asym_interface2,
iface1=asym_iface1,
iface2=asym_iface2,
options=options,
)
else:
@ -273,8 +273,8 @@ class LinkConfigurationDialog(Dialog):
link.node1_id,
link.node2_id,
link.options,
interface1_id,
interface2_id,
iface1_id,
iface2_id,
)
if self.edge.asymmetric_link:
self.app.core.client.edit_link(
@ -282,8 +282,8 @@ class LinkConfigurationDialog(Dialog):
link.node2_id,
link.node1_id,
self.edge.asymmetric_link.options,
interface1_id,
interface2_id,
iface1_id,
iface2_id,
)
self.destroy()

View file

@ -55,7 +55,7 @@ class MacConfigDialog(Dialog):
if not netaddr.valid_mac(mac):
messagebox.showerror("MAC Error", f"{mac} is an invalid mac")
else:
self.app.core.interfaces_manager.mac = netaddr.EUI(mac)
self.app.core.ifaces_manager.mac = netaddr.EUI(mac)
self.app.guiconfig.mac = mac
self.app.save_config()
self.destroy()

View file

@ -111,7 +111,7 @@ class NodeConfigDialog(Dialog):
if self.node.server:
server = self.node.server
self.server = tk.StringVar(value=server)
self.interfaces = {}
self.ifaces = {}
self.draw()
def draw(self):
@ -183,53 +183,53 @@ class NodeConfigDialog(Dialog):
row += 1
if NodeUtils.is_rj45_node(self.node.type):
response = self.app.core.client.get_interfaces()
response = self.app.core.client.get_ifaces()
logging.debug("host machine available interfaces: %s", response)
interfaces = ListboxScroll(frame)
interfaces.listbox.config(state=state)
interfaces.grid(
ifaces = ListboxScroll(frame)
ifaces.listbox.config(state=state)
ifaces.grid(
row=row, column=0, columnspan=2, sticky="ew", padx=PADX, pady=PADY
)
for inf in sorted(response.interfaces[:]):
interfaces.listbox.insert(tk.END, inf)
for inf in sorted(response.ifaces[:]):
ifaces.listbox.insert(tk.END, inf)
row += 1
interfaces.listbox.bind("<<ListboxSelect>>", self.interface_select)
ifaces.listbox.bind("<<ListboxSelect>>", self.iface_select)
# interfaces
if self.canvas_node.interfaces:
self.draw_interfaces()
if self.canvas_node.ifaces:
self.draw_ifaces()
self.draw_spacer()
self.draw_buttons()
def draw_interfaces(self):
def draw_ifaces(self):
notebook = ttk.Notebook(self.top)
notebook.grid(sticky="nsew", pady=PADY)
self.top.rowconfigure(notebook.grid_info()["row"], weight=1)
state = tk.DISABLED if self.app.core.is_runtime() else tk.NORMAL
for interface_id in sorted(self.canvas_node.interfaces):
interface = self.canvas_node.interfaces[interface_id]
for iface_id in sorted(self.canvas_node.ifaces):
iface = self.canvas_node.ifaces[iface_id]
tab = ttk.Frame(notebook, padding=FRAME_PAD)
tab.grid(sticky="nsew", pady=PADY)
tab.columnconfigure(1, weight=1)
tab.columnconfigure(2, weight=1)
notebook.add(tab, text=interface.name)
notebook.add(tab, text=iface.name)
row = 0
emane_node = self.canvas_node.has_emane_link(interface.id)
emane_node = self.canvas_node.has_emane_link(iface.id)
if emane_node:
emane_model = emane_node.emane.split("_")[1]
button = ttk.Button(
tab,
text=f"Configure EMANE {emane_model}",
command=lambda: self.click_emane_config(emane_model, interface.id),
command=lambda: self.click_emane_config(emane_model, iface.id),
)
button.grid(row=row, sticky="ew", columnspan=3, pady=PADY)
row += 1
label = ttk.Label(tab, text="MAC")
label.grid(row=row, column=0, padx=PADX, pady=PADY)
auto_set = not interface.mac
auto_set = not iface.mac
mac_state = tk.DISABLED if auto_set else tk.NORMAL
is_auto = tk.BooleanVar(value=auto_set)
checkbutton = ttk.Checkbutton(
@ -237,7 +237,7 @@ class NodeConfigDialog(Dialog):
)
checkbutton.var = is_auto
checkbutton.grid(row=row, column=1, padx=PADX)
mac = tk.StringVar(value=interface.mac)
mac = tk.StringVar(value=iface.mac)
entry = ttk.Entry(tab, textvariable=mac, state=mac_state)
entry.grid(row=row, column=2, sticky="ew")
func = partial(mac_auto, is_auto, entry, mac)
@ -247,8 +247,8 @@ class NodeConfigDialog(Dialog):
label = ttk.Label(tab, text="IPv4")
label.grid(row=row, column=0, padx=PADX, pady=PADY)
ip4_net = ""
if interface.ip4:
ip4_net = f"{interface.ip4}/{interface.ip4mask}"
if iface.ip4:
ip4_net = f"{iface.ip4}/{iface.ip4_mask}"
ip4 = tk.StringVar(value=ip4_net)
entry = ttk.Entry(tab, textvariable=ip4, state=state)
entry.grid(row=row, column=1, columnspan=2, sticky="ew")
@ -257,13 +257,13 @@ class NodeConfigDialog(Dialog):
label = ttk.Label(tab, text="IPv6")
label.grid(row=row, column=0, padx=PADX, pady=PADY)
ip6_net = ""
if interface.ip6:
ip6_net = f"{interface.ip6}/{interface.ip6mask}"
if iface.ip6:
ip6_net = f"{iface.ip6}/{iface.ip6_mask}"
ip6 = tk.StringVar(value=ip6_net)
entry = ttk.Entry(tab, textvariable=ip6, state=state)
entry.grid(row=row, column=1, columnspan=2, sticky="ew")
self.interfaces[interface.id] = InterfaceData(is_auto, mac, ip4, ip6)
self.ifaces[iface.id] = InterfaceData(is_auto, mac, ip4, ip6)
def draw_buttons(self):
frame = ttk.Frame(self.top)
@ -277,9 +277,9 @@ class NodeConfigDialog(Dialog):
button = ttk.Button(frame, text="Cancel", command=self.destroy)
button.grid(row=0, column=1, sticky="ew")
def click_emane_config(self, emane_model: str, interface_id: int):
def click_emane_config(self, emane_model: str, iface_id: int):
dialog = EmaneModelDialog(
self, self.app, self.canvas_node, emane_model, interface_id
self, self.app, self.canvas_node, emane_model, iface_id
)
dialog.show()
@ -309,54 +309,54 @@ class NodeConfigDialog(Dialog):
self.canvas_node.image = self.image
# update node interface data
for interface in self.canvas_node.interfaces.values():
data = self.interfaces[interface.id]
for iface in self.canvas_node.ifaces.values():
data = self.ifaces[iface.id]
# validate ip4
ip4_net = data.ip4.get()
if not check_ip4(self, interface.name, ip4_net):
if not check_ip4(self, iface.name, ip4_net):
error = True
break
if ip4_net:
ip4, ip4mask = ip4_net.split("/")
ip4mask = int(ip4mask)
ip4, ip4_mask = ip4_net.split("/")
ip4_mask = int(ip4_mask)
else:
ip4, ip4mask = "", 0
interface.ip4 = ip4
interface.ip4mask = ip4mask
ip4, ip4_mask = "", 0
iface.ip4 = ip4
iface.ip4_mask = ip4_mask
# validate ip6
ip6_net = data.ip6.get()
if not check_ip6(self, interface.name, ip6_net):
if not check_ip6(self, iface.name, ip6_net):
error = True
break
if ip6_net:
ip6, ip6mask = ip6_net.split("/")
ip6mask = int(ip6mask)
ip6, ip6_mask = ip6_net.split("/")
ip6_mask = int(ip6_mask)
else:
ip6, ip6mask = "", 0
interface.ip6 = ip6
interface.ip6mask = ip6mask
ip6, ip6_mask = "", 0
iface.ip6 = ip6
iface.ip6_mask = ip6_mask
mac = data.mac.get()
auto_mac = data.is_auto.get()
if not auto_mac and not netaddr.valid_mac(mac):
title = f"MAC Error for {interface.name}"
title = f"MAC Error for {iface.name}"
messagebox.showerror(title, "Invalid MAC Address")
error = True
break
elif not auto_mac:
mac = netaddr.EUI(mac, dialect=netaddr.mac_unix_expanded)
interface.mac = str(mac)
iface.mac = str(mac)
# redraw
if not error:
self.canvas_node.redraw()
self.destroy()
def interface_select(self, event: tk.Event):
def iface_select(self, event: tk.Event):
listbox = event.widget
cur = listbox.curselection()
if cur:
interface = listbox.get(cur[0])
self.name.set(interface)
iface = listbox.get(cur[0])
self.name.set(iface)

View file

@ -259,8 +259,8 @@ class CanvasEdge(Edge):
Create an instance of canvas edge object
"""
super().__init__(canvas, src)
self.src_interface = None
self.dst_interface = None
self.src_iface = None
self.dst_iface = None
self.text_src = None
self.text_dst = None
self.link = None
@ -283,25 +283,25 @@ class CanvasEdge(Edge):
self.link = link
self.draw_labels()
def interface_label(self, interface: core_pb2.Interface) -> str:
def iface_label(self, iface: core_pb2.Interface) -> str:
label = ""
if interface.name and self.canvas.show_interface_names.get():
label = f"{interface.name}"
if interface.ip4 and self.canvas.show_ip4s.get():
if iface.name and self.canvas.show_iface_names.get():
label = f"{iface.name}"
if iface.ip4 and self.canvas.show_ip4s.get():
label = f"{label}\n" if label else ""
label += f"{interface.ip4}/{interface.ip4mask}"
if interface.ip6 and self.canvas.show_ip6s.get():
label += f"{iface.ip4}/{iface.ip4_mask}"
if iface.ip6 and self.canvas.show_ip6s.get():
label = f"{label}\n" if label else ""
label += f"{interface.ip6}/{interface.ip6mask}"
label += f"{iface.ip6}/{iface.ip6_mask}"
return label
def create_node_labels(self) -> Tuple[str, str]:
label1 = None
if self.link.HasField("interface1"):
label1 = self.interface_label(self.link.interface1)
if self.link.HasField("iface1"):
label1 = self.iface_label(self.link.iface1)
label2 = None
if self.link.HasField("interface2"):
label2 = self.interface_label(self.link.interface2)
if self.link.HasField("iface2"):
label2 = self.iface_label(self.link.iface2)
return label1, label2
def draw_labels(self) -> None:

View file

@ -97,7 +97,7 @@ class CanvasGraph(tk.Canvas):
self.show_link_labels = ShowVar(self, tags.LINK_LABEL, value=True)
self.show_grid = ShowVar(self, tags.GRIDLINE, value=True)
self.show_annotations = ShowVar(self, tags.ANNOTATION, value=True)
self.show_interface_names = BooleanVar(value=False)
self.show_iface_names = BooleanVar(value=False)
self.show_ip4s = BooleanVar(value=True)
self.show_ip6s = BooleanVar(value=True)
@ -136,7 +136,7 @@ class CanvasGraph(tk.Canvas):
self.show_link_labels.set(True)
self.show_grid.set(True)
self.show_annotations.set(True)
self.show_interface_names.set(False)
self.show_iface_names.set(False)
self.show_ip4s.set(True)
self.show_ip6s.set(True)
@ -195,19 +195,19 @@ class CanvasGraph(tk.Canvas):
return valid_topleft and valid_bottomright
def set_throughputs(self, throughputs_event: core_pb2.ThroughputsEvent):
for interface_throughput in throughputs_event.interface_throughputs:
node_id = interface_throughput.node_id
interface_id = interface_throughput.interface_id
throughput = interface_throughput.throughput
interface_to_edge_id = (node_id, interface_id)
token = self.core.interface_to_edge.get(interface_to_edge_id)
for iface_throughput in throughputs_event.iface_throughputs:
node_id = iface_throughput.node_id
iface_id = iface_throughput.iface_id
throughput = iface_throughput.throughput
iface_to_edge_id = (node_id, iface_id)
token = self.core.iface_to_edge.get(iface_to_edge_id)
if not token:
continue
edge = self.edges.get(token)
if edge:
edge.set_throughput(throughput)
else:
del self.core.interface_to_edge[interface_to_edge_id]
del self.core.iface_to_edge[iface_to_edge_id]
def draw_grid(self):
"""
@ -321,18 +321,16 @@ class CanvasGraph(tk.Canvas):
canvas_node2.edges.add(edge)
self.edges[edge.token] = edge
self.core.links[edge.token] = edge
if link.HasField("interface1"):
interface1 = link.interface1
self.core.interface_to_edge[(node1.id, interface1.id)] = token
canvas_node1.interfaces[interface1.id] = interface1
edge.src_interface = interface1
if link.HasField("interface2"):
interface2 = link.interface2
self.core.interface_to_edge[
(node2.id, interface2.id)
] = edge.token
canvas_node2.interfaces[interface2.id] = interface2
edge.dst_interface = interface2
if link.HasField("iface1"):
iface1 = link.iface1
self.core.iface_to_edge[(node1.id, iface1.id)] = token
canvas_node1.ifaces[iface1.id] = iface1
edge.src_iface = iface1
if link.HasField("iface2"):
iface2 = link.iface2
self.core.iface_to_edge[(node2.id, iface2.id)] = edge.token
canvas_node2.ifaces[iface2.id] = iface2
edge.dst_iface = iface2
elif link.options.unidirectional:
edge = self.edges[token]
edge.asymmetric_link = link
@ -513,14 +511,14 @@ class CanvasGraph(tk.Canvas):
edge.delete()
# update node connected to edge being deleted
other_id = edge.src
other_interface = edge.src_interface
other_iface = edge.src_iface
if edge.src == object_id:
other_id = edge.dst
other_interface = edge.dst_interface
other_iface = edge.dst_iface
other_node = self.nodes[other_id]
other_node.edges.remove(edge)
if other_interface:
del other_node.interfaces[other_interface.id]
if other_iface:
del other_node.ifaces[other_iface.id]
if is_wireless:
other_node.delete_antenna()
@ -538,12 +536,12 @@ class CanvasGraph(tk.Canvas):
del self.edges[edge.token]
src_node = self.nodes[edge.src]
src_node.edges.discard(edge)
if edge.src_interface:
del src_node.interfaces[edge.src_interface.id]
if edge.src_iface:
del src_node.ifaces[edge.src_iface.id]
dst_node = self.nodes[edge.dst]
dst_node.edges.discard(edge)
if edge.dst_interface:
del dst_node.interfaces[edge.dst_interface.id]
if edge.dst_iface:
del dst_node.ifaces[edge.dst_iface.id]
src_wireless = NodeUtils.is_wireless_node(src_node.core_node.type)
if src_wireless:
dst_node.delete_antenna()
@ -963,26 +961,26 @@ class CanvasGraph(tk.Canvas):
copy_link = copy_edge.link
options = edge.link.options
copy_link.options.CopyFrom(options)
interface1_id = None
if copy_link.HasField("interface1"):
interface1_id = copy_link.interface1.id
interface2_id = None
if copy_link.HasField("interface2"):
interface2_id = copy_link.interface2.id
iface1_id = None
if copy_link.HasField("iface1"):
iface1_id = copy_link.iface1.id
iface2_id = None
if copy_link.HasField("iface2"):
iface2_id = copy_link.iface2.id
if not options.unidirectional:
copy_edge.asymmetric_link = None
else:
asym_interface1 = None
if interface1_id:
asym_interface1 = core_pb2.Interface(id=interface1_id)
asym_interface2 = None
if interface2_id:
asym_interface2 = core_pb2.Interface(id=interface2_id)
asym_iface1 = None
if iface1_id:
asym_iface1 = core_pb2.Interface(id=iface1_id)
asym_iface2 = None
if iface2_id:
asym_iface2 = core_pb2.Interface(id=iface2_id)
copy_edge.asymmetric_link = core_pb2.Link(
node1_id=copy_link.node2_id,
node2_id=copy_link.node1_id,
interface1=asym_interface1,
interface2=asym_interface2,
iface1=asym_iface1,
iface2=asym_iface2,
options=edge.asymmetric_link.options,
)
self.itemconfig(

View file

@ -55,7 +55,7 @@ class CanvasNode:
)
self.tooltip = CanvasTooltip(self.canvas)
self.edges = set()
self.interfaces = {}
self.ifaces = {}
self.wireless_edges = set()
self.antennas = []
self.antenna_images = {}
@ -70,9 +70,9 @@ class CanvasNode:
self.context = tk.Menu(self.canvas)
themes.style_menu(self.context)
def next_interface_id(self) -> int:
def next_iface_id(self) -> int:
i = 0
while i in self.interfaces:
while i in self.ifaces:
i += 1
return i
@ -300,16 +300,16 @@ class CanvasNode:
dialog = NodeConfigServiceDialog(self.app, self)
dialog.show()
def has_emane_link(self, interface_id: int) -> core_pb2.Node:
def has_emane_link(self, iface_id: int) -> core_pb2.Node:
result = None
for edge in self.edges:
if self.id == edge.src:
other_id = edge.dst
edge_interface_id = edge.src_interface.id
edge_iface_id = edge.src_iface.id
else:
other_id = edge.src
edge_interface_id = edge.dst_interface.id
if edge_interface_id != interface_id:
edge_iface_id = edge.dst_iface.id
if edge_iface_id != iface_id:
continue
other_node = self.canvas.nodes[other_id]
if other_node.core_node.type == NodeType.EMANE:

View file

@ -12,10 +12,10 @@ if TYPE_CHECKING:
from core.gui.graph.node import CanvasNode
def get_index(interface: "core_pb2.Interface") -> Optional[int]:
if not interface.ip4:
def get_index(iface: "core_pb2.Interface") -> Optional[int]:
if not iface.ip4:
return None
net = netaddr.IPNetwork(f"{interface.ip4}/{interface.ip4mask}")
net = netaddr.IPNetwork(f"{iface.ip4}/{iface.ip4_mask}")
ip_value = net.value
cidr_value = net.cidr.value
return ip_value - cidr_value
@ -89,43 +89,43 @@ class InterfaceManager:
remaining_subnets = set()
for edge in self.app.core.links.values():
link = edge.link
if link.HasField("interface1"):
subnets = self.get_subnets(link.interface1)
if link.HasField("iface1"):
subnets = self.get_subnets(link.iface1)
remaining_subnets.add(subnets)
if link.HasField("interface2"):
subnets = self.get_subnets(link.interface2)
if link.HasField("iface2"):
subnets = self.get_subnets(link.iface2)
remaining_subnets.add(subnets)
# remove all subnets from used subnets when no longer present
# or remove used indexes from subnet
interfaces = []
ifaces = []
for link in links:
if link.HasField("interface1"):
interfaces.append(link.interface1)
if link.HasField("interface2"):
interfaces.append(link.interface2)
for interface in interfaces:
subnets = self.get_subnets(interface)
if link.HasField("iface1"):
ifaces.append(link.iface1)
if link.HasField("iface2"):
ifaces.append(link.iface2)
for iface in ifaces:
subnets = self.get_subnets(iface)
if subnets not in remaining_subnets:
self.used_subnets.pop(subnets.key(), None)
else:
index = get_index(interface)
index = get_index(iface)
if index is not None:
subnets.used_indexes.discard(index)
self.current_subnets = None
def joined(self, links: List["core_pb2.Link"]) -> None:
interfaces = []
ifaces = []
for link in links:
if link.HasField("interface1"):
interfaces.append(link.interface1)
if link.HasField("interface2"):
interfaces.append(link.interface2)
if link.HasField("iface1"):
ifaces.append(link.iface1)
if link.HasField("iface2"):
ifaces.append(link.iface2)
# add to used subnets and mark used indexes
for interface in interfaces:
subnets = self.get_subnets(interface)
index = get_index(interface)
for iface in ifaces:
subnets = self.get_subnets(iface)
index = get_index(iface)
if index is None:
continue
subnets.used_indexes.add(index)
@ -150,13 +150,13 @@ class InterfaceManager:
ip6 = self.current_subnets.ip6[index]
return str(ip4), str(ip6)
def get_subnets(self, interface: "core_pb2.Interface") -> Subnets:
def get_subnets(self, iface: "core_pb2.Interface") -> Subnets:
ip4_subnet = self.ip4_subnets
if interface.ip4:
ip4_subnet = IPNetwork(f"{interface.ip4}/{interface.ip4mask}").cidr
if iface.ip4:
ip4_subnet = IPNetwork(f"{iface.ip4}/{iface.ip4_mask}").cidr
ip6_subnet = self.ip6_subnets
if interface.ip6:
ip6_subnet = IPNetwork(f"{interface.ip6}/{interface.ip6mask}").cidr
if iface.ip6:
ip6_subnet = IPNetwork(f"{iface.ip6}/{iface.ip6_mask}").cidr
subnets = Subnets(ip4_subnet, ip6_subnet)
return self.used_subnets.get(subnets.key(), subnets)
@ -196,16 +196,16 @@ class InterfaceManager:
for edge in canvas_node.edges:
src_node = canvas.nodes[edge.src]
dst_node = canvas.nodes[edge.dst]
interface = edge.src_interface
iface = edge.src_iface
check_node = src_node
if src_node == canvas_node:
interface = edge.dst_interface
iface = edge.dst_iface
check_node = dst_node
if check_node.core_node.id in visited:
continue
visited.add(check_node.core_node.id)
if interface:
subnets = self.get_subnets(interface)
if iface:
subnets = self.get_subnets(iface)
else:
subnets = self.find_subnets(check_node, visited)
if subnets:

View file

@ -139,7 +139,7 @@ class Menubar(tk.Menu):
menu.add_checkbutton(
label="Interface Names",
command=self.click_edge_label_change,
variable=self.canvas.show_interface_names,
variable=self.canvas.show_iface_names,
)
menu.add_checkbutton(
label="IPv4 Addresses",

View file

@ -13,8 +13,7 @@ from typing import TYPE_CHECKING, Callable, Dict, List, Optional, Tuple
from core import utils
from core.config import ConfigGroup, ConfigurableOptions, Configuration, ModelManager
from core.emulator.data import EventData, LinkData
from core.emulator.emudata import LinkOptions
from core.emulator.data import EventData, LinkData, LinkOptions
from core.emulator.enumerations import (
ConfigDataTypes,
EventTypes,
@ -178,7 +177,7 @@ class MobilityManager(ModelManager):
self.session.broadcast_event(event_data)
def updatewlans(
self, moved: List[CoreNode], moved_netifs: List[CoreInterface]
self, moved: List[CoreNode], moved_ifaces: List[CoreInterface]
) -> None:
"""
A mobility script has caused nodes in the 'moved' list to move.
@ -186,7 +185,7 @@ class MobilityManager(ModelManager):
were to recalculate for each individual node movement.
:param moved: moved nodes
:param moved_netifs: moved network interfaces
:param moved_ifaces: moved network interfaces
:return: nothing
"""
for node_id in self.nodes():
@ -195,7 +194,7 @@ class MobilityManager(ModelManager):
except CoreError:
continue
if node.model:
node.model.update(moved, moved_netifs)
node.model.update(moved, moved_ifaces)
class WirelessModel(ConfigurableOptions):
@ -228,12 +227,12 @@ class WirelessModel(ConfigurableOptions):
"""
return []
def update(self, moved: List[CoreNode], moved_netifs: List[CoreInterface]) -> None:
def update(self, moved: List[CoreNode], moved_ifaces: List[CoreInterface]) -> None:
"""
Update this wireless model.
:param moved: moved nodes
:param moved_netifs: moved network interfaces
:param moved_ifaces: moved network interfaces
:return: nothing
"""
raise NotImplementedError
@ -301,8 +300,8 @@ class BasicRangeModel(WirelessModel):
super().__init__(session, _id)
self.session: "Session" = session
self.wlan: WlanNode = session.get_node(_id, WlanNode)
self._netifs: Dict[CoreInterface, Tuple[float, float, float]] = {}
self._netifslock: threading.Lock = threading.Lock()
self.iface_to_pos: Dict[CoreInterface, Tuple[float, float, float]] = {}
self.iface_lock: threading.Lock = threading.Lock()
self.range: int = 0
self.bw: Optional[int] = None
self.delay: Optional[int] = None
@ -333,48 +332,48 @@ class BasicRangeModel(WirelessModel):
Apply link parameters to all interfaces. This is invoked from
WlanNode.setmodel() after the position callback has been set.
"""
with self._netifslock:
for netif in self._netifs:
with self.iface_lock:
for iface in self.iface_to_pos:
options = LinkOptions(
bandwidth=self.bw,
delay=self.delay,
loss=self.loss,
jitter=self.jitter,
)
self.wlan.linkconfig(netif, options)
self.wlan.linkconfig(iface, options)
def get_position(self, netif: CoreInterface) -> Tuple[float, float, float]:
def get_position(self, iface: CoreInterface) -> Tuple[float, float, float]:
"""
Retrieve network interface position.
:param netif: network interface position to retrieve
:param iface: network interface position to retrieve
:return: network interface position
"""
with self._netifslock:
return self._netifs[netif]
with self.iface_lock:
return self.iface_to_pos[iface]
def set_position(self, netif: CoreInterface) -> None:
def set_position(self, iface: CoreInterface) -> None:
"""
A node has moved; given an interface, a new (x,y,z) position has
been set; calculate the new distance between other nodes and link or
unlink node pairs based on the configured range.
:param netif: network interface to set position for
:param iface: network interface to set position for
:return: nothing
"""
x, y, z = netif.node.position.get()
self._netifslock.acquire()
self._netifs[netif] = (x, y, z)
x, y, z = iface.node.position.get()
self.iface_lock.acquire()
self.iface_to_pos[iface] = (x, y, z)
if x is None or y is None:
self._netifslock.release()
self.iface_lock.release()
return
for netif2 in self._netifs:
self.calclink(netif, netif2)
self._netifslock.release()
for iface2 in self.iface_to_pos:
self.calclink(iface, iface2)
self.iface_lock.release()
position_callback = set_position
def update(self, moved: List[CoreNode], moved_netifs: List[CoreInterface]) -> None:
def update(self, moved: List[CoreNode], moved_ifaces: List[CoreInterface]) -> None:
"""
Node positions have changed without recalc. Update positions from
node.position, then re-calculate links for those that have moved.
@ -382,37 +381,37 @@ class BasicRangeModel(WirelessModel):
one of the nodes has moved.
:param moved: moved nodes
:param moved_netifs: moved network interfaces
:param moved_ifaces: moved network interfaces
:return: nothing
"""
with self._netifslock:
while len(moved_netifs):
netif = moved_netifs.pop()
nx, ny, nz = netif.node.getposition()
if netif in self._netifs:
self._netifs[netif] = (nx, ny, nz)
for netif2 in self._netifs:
if netif2 in moved_netifs:
with self.iface_lock:
while len(moved_ifaces):
iface = moved_ifaces.pop()
nx, ny, nz = iface.node.getposition()
if iface in self.iface_to_pos:
self.iface_to_pos[iface] = (nx, ny, nz)
for iface2 in self.iface_to_pos:
if iface2 in moved_ifaces:
continue
self.calclink(netif, netif2)
self.calclink(iface, iface2)
def calclink(self, netif: CoreInterface, netif2: CoreInterface) -> None:
def calclink(self, iface: CoreInterface, iface2: CoreInterface) -> None:
"""
Helper used by set_position() and update() to
calculate distance between two interfaces and perform
linking/unlinking. Sends link/unlink messages and updates the
WlanNode's linked dict.
:param netif: interface one
:param netif2: interface two
:param iface: interface one
:param iface2: interface two
:return: nothing
"""
if netif == netif2:
if iface == iface2:
return
try:
x, y, z = self._netifs[netif]
x2, y2, z2 = self._netifs[netif2]
x, y, z = self.iface_to_pos[iface]
x2, y2, z2 = self.iface_to_pos[iface2]
if x2 is None or y2 is None:
return
@ -420,8 +419,8 @@ class BasicRangeModel(WirelessModel):
d = self.calcdistance((x, y, z), (x2, y2, z2))
# ordering is important, to keep the wlan._linked dict organized
a = min(netif, netif2)
b = max(netif, netif2)
a = min(iface, iface2)
b = max(iface, iface2)
with self.wlan._linked_lock:
linked = self.wlan.linked(a, b)
@ -475,42 +474,39 @@ class BasicRangeModel(WirelessModel):
self.setlinkparams()
def create_link_data(
self,
interface1: CoreInterface,
interface2: CoreInterface,
message_type: MessageFlags,
self, iface1: CoreInterface, iface2: CoreInterface, message_type: MessageFlags
) -> LinkData:
"""
Create a wireless link/unlink data message.
:param interface1: interface one
:param interface2: interface two
:param iface1: interface one
:param iface2: interface two
:param message_type: link message type
:return: link data
"""
color = self.session.get_link_color(self.wlan.id)
return LinkData(
message_type=message_type,
node1_id=interface1.node.id,
node2_id=interface2.node.id,
type=LinkTypes.WIRELESS,
node1_id=iface1.node.id,
node2_id=iface2.node.id,
network_id=self.wlan.id,
link_type=LinkTypes.WIRELESS,
color=color,
)
def sendlinkmsg(
self, netif: CoreInterface, netif2: CoreInterface, unlink: bool = False
self, iface: CoreInterface, iface2: CoreInterface, unlink: bool = False
) -> None:
"""
Send a wireless link/unlink API message to the GUI.
:param netif: interface one
:param netif2: interface two
:param iface: interface one
:param iface2: interface two
:param unlink: unlink or not
:return: nothing
"""
message_type = MessageFlags.DELETE if unlink else MessageFlags.ADD
link_data = self.create_link_data(netif, netif2, message_type)
link_data = self.create_link_data(iface, iface2, message_type)
self.session.broadcast_link(link_data)
def all_link_data(self, flags: MessageFlags = MessageFlags.NONE) -> List[LinkData]:
@ -643,17 +639,17 @@ class WayPointMobility(WirelessModel):
return
return self.run()
# only move netifs attached to self.wlan, or all nodenum in script?
# only move interfaces attached to self.wlan, or all nodenum in script?
moved = []
moved_netifs = []
for netif in self.wlan.netifs():
node = netif.node
moved_ifaces = []
for iface in self.wlan.get_ifaces():
node = iface.node
if self.movenode(node, dt):
moved.append(node)
moved_netifs.append(netif)
moved_ifaces.append(iface)
# calculate all ranges after moving nodes; this saves calculations
self.session.mobility.updatewlans(moved, moved_netifs)
self.session.mobility.updatewlans(moved, moved_ifaces)
# TODO: check session state
self.session.event_loop.add_event(0.001 * self.refresh_ms, self.runround)
@ -725,16 +721,16 @@ class WayPointMobility(WirelessModel):
:return: nothing
"""
moved = []
moved_netifs = []
for netif in self.wlan.netifs():
node = netif.node
moved_ifaces = []
for iface in self.wlan.get_ifaces():
node = iface.node
if node.id not in self.initial:
continue
x, y, z = self.initial[node.id].coords
self.setnodeposition(node, x, y, z)
moved.append(node)
moved_netifs.append(netif)
self.session.mobility.updatewlans(moved, moved_netifs)
moved_ifaces.append(iface)
self.session.mobility.updatewlans(moved, moved_ifaces)
def addwaypoint(
self,

View file

@ -14,8 +14,7 @@ import netaddr
from core import utils
from core.configservice.dependencies import ConfigServiceDependencies
from core.constants import MOUNT_BIN, VNODED_BIN
from core.emulator.data import LinkData, NodeData
from core.emulator.emudata import InterfaceData, LinkOptions
from core.emulator.data import InterfaceData, LinkData, LinkOptions
from core.emulator.enumerations import LinkTypes, MessageFlags, NodeTypes
from core.errors import CoreCommandError, CoreError
from core.nodes.client import VnodeClient
@ -68,11 +67,10 @@ class NodeBase(abc.ABC):
self.server: "DistributedServer" = server
self.type: Optional[str] = None
self.services: CoreServices = []
self._netif: Dict[int, CoreInterface] = {}
self.ifindex: int = 0
self.ifaces: Dict[int, CoreInterface] = {}
self.iface_id: int = 0
self.canvas: Optional[int] = None
self.icon: Optional[str] = None
self.opaque: Optional[str] = None
self.position: Position = Position()
self.up: bool = False
use_ovs = session.options.get_config("ovs") == "True"
@ -139,103 +137,54 @@ class NodeBase(abc.ABC):
"""
return self.position.get()
def ifname(self, ifindex: int) -> str:
"""
Retrieve interface name for index.
def get_iface(self, iface_id: int) -> CoreInterface:
if iface_id not in self.ifaces:
raise CoreError(f"node({self.name}) does not have interface({iface_id})")
return self.ifaces[iface_id]
:param ifindex: interface index
:return: interface name
def get_ifaces(self, control: bool = True) -> List[CoreInterface]:
"""
return self._netif[ifindex].name
Retrieve sorted list of interfaces, optionally do not include control
interfaces.
def netifs(self, sort: bool = False) -> List[CoreInterface]:
:param control: False to exclude control interfaces, included otherwise
:return: list of interfaces
"""
Retrieve network interfaces, sorted if desired.
ifaces = []
for iface_id in sorted(self.ifaces):
iface = self.ifaces[iface_id]
if not control and getattr(iface, "control", False):
continue
ifaces.append(iface)
return ifaces
:param sort: boolean used to determine if interfaces should be sorted
:return: network interfaces
def get_iface_id(self, iface: CoreInterface) -> int:
"""
if sort:
return [self._netif[x] for x in sorted(self._netif)]
else:
return list(self._netif.values())
Retrieve id for an interface.
def numnetif(self) -> int:
"""
Return the attached interface count.
:return: number of network interfaces
"""
return len(self._netif)
def getifindex(self, netif: CoreInterface) -> int:
"""
Retrieve index for an interface.
:param netif: interface to get index for
:param iface: interface to get id for
:return: interface index if found, -1 otherwise
"""
for ifindex in self._netif:
if self._netif[ifindex] is netif:
return ifindex
return -1
for iface_id, local_iface in self.ifaces.items():
if local_iface is iface:
return iface_id
raise CoreError(f"node({self.name}) does not have interface({iface.name})")
def newifindex(self) -> int:
def next_iface_id(self) -> int:
"""
Create a new interface index.
:return: interface index
"""
while self.ifindex in self._netif:
self.ifindex += 1
ifindex = self.ifindex
self.ifindex += 1
return ifindex
def data(
self, message_type: MessageFlags = MessageFlags.NONE, source: str = None
) -> Optional[NodeData]:
"""
Build a data object for this node.
:param message_type: purpose for the data object we are creating
:param source: source of node data
:return: node data object
"""
if self.apitype is None:
return None
x, y, _ = self.getposition()
model = self.type
server = None
if self.server is not None:
server = self.server.name
services = [service.name for service in self.services]
return NodeData(
message_type=message_type,
id=self.id,
node_type=self.apitype,
name=self.name,
emulation_id=self.id,
canvas=self.canvas,
icon=self.icon,
opaque=self.opaque,
x_position=x,
y_position=y,
latitude=self.position.lat,
longitude=self.position.lon,
altitude=self.position.alt,
model=model,
server=server,
services=services,
source=source,
)
while self.iface_id in self.ifaces:
self.iface_id += 1
iface_id = self.iface_id
self.iface_id += 1
return iface_id
def all_link_data(self, flags: MessageFlags = MessageFlags.NONE) -> List[LinkData]:
"""
Build CORE Link data for this object. There is no default
method for PyCoreObjs as PyCoreNodes do not implement this but
PyCoreNets do.
Build link data for this node.
:param flags: message flags
:return: list of link data
@ -325,14 +274,14 @@ class CoreNodeBase(NodeBase):
raise NotImplementedError
@abc.abstractmethod
def newnetif(
self, net: "CoreNetworkBase", interface_data: InterfaceData
def new_iface(
self, net: "CoreNetworkBase", iface_data: InterfaceData
) -> CoreInterface:
"""
Create a new network interface.
Create a new interface.
:param net: network to associate with
:param interface_data: interface data for new interface
:param iface_data: interface data for new interface
:return: interface index
"""
raise NotImplementedError
@ -399,67 +348,53 @@ class CoreNodeBase(NodeBase):
if self.tmpnodedir:
self.host_cmd(f"rm -rf {self.nodedir}")
def addnetif(self, netif: CoreInterface, ifindex: int) -> None:
def add_iface(self, iface: CoreInterface, iface_id: int) -> None:
"""
Add network interface to node and set the network interface index if successful.
:param netif: network interface to add
:param ifindex: interface index
:param iface: network interface to add
:param iface_id: interface id
:return: nothing
"""
if ifindex in self._netif:
raise ValueError(f"ifindex {ifindex} already exists")
self._netif[ifindex] = netif
netif.netindex = ifindex
if iface_id in self.ifaces:
raise CoreError(f"interface({iface_id}) already exists")
self.ifaces[iface_id] = iface
iface.node_id = iface_id
def delnetif(self, ifindex: int) -> None:
def delete_iface(self, iface_id: int) -> None:
"""
Delete a network interface
:param ifindex: interface index to delete
:param iface_id: interface index to delete
:return: nothing
"""
if ifindex not in self._netif:
raise CoreError(f"node({self.name}) ifindex({ifindex}) does not exist")
netif = self._netif.pop(ifindex)
logging.info("node(%s) removing interface(%s)", self.name, netif.name)
netif.detachnet()
netif.shutdown()
if iface_id not in self.ifaces:
raise CoreError(f"node({self.name}) interface({iface_id}) does not exist")
iface = self.ifaces.pop(iface_id)
logging.info("node(%s) removing interface(%s)", self.name, iface.name)
iface.detachnet()
iface.shutdown()
def netif(self, ifindex: int) -> Optional[CoreInterface]:
"""
Retrieve network interface.
:param ifindex: index of interface to retrieve
:return: network interface, or None if not found
"""
if ifindex in self._netif:
return self._netif[ifindex]
else:
return None
def attachnet(self, ifindex: int, net: "CoreNetworkBase") -> None:
def attachnet(self, iface_id: int, net: "CoreNetworkBase") -> None:
"""
Attach a network.
:param ifindex: interface of index to attach
:param iface_id: interface of index to attach
:param net: network to attach
:return: nothing
"""
if ifindex not in self._netif:
raise ValueError(f"ifindex {ifindex} does not exist")
self._netif[ifindex].attachnet(net)
iface = self.get_iface(iface_id)
iface.attachnet(net)
def detachnet(self, ifindex: int) -> None:
def detachnet(self, iface_id: int) -> None:
"""
Detach network interface.
:param ifindex: interface index to detach
:param iface_id: interface id to detach
:return: nothing
"""
if ifindex not in self._netif:
raise ValueError(f"ifindex {ifindex} does not exist")
self._netif[ifindex].detachnet()
iface = self.get_iface(iface_id)
iface.detachnet()
def setposition(self, x: float = None, y: float = None, z: float = None) -> None:
"""
@ -472,8 +407,8 @@ class CoreNodeBase(NodeBase):
"""
changed = super().setposition(x, y, z)
if changed:
for netif in self.netifs(sort=True):
netif.setposition()
for iface in self.get_ifaces():
iface.setposition()
def commonnets(
self, node: "CoreNodeBase", want_ctrl: bool = False
@ -488,12 +423,10 @@ class CoreNodeBase(NodeBase):
:return: tuples of common networks
"""
common = []
for netif1 in self.netifs():
if not want_ctrl and hasattr(netif1, "control"):
continue
for netif2 in node.netifs():
if netif1.net == netif2.net:
common.append((netif1.net, netif1, netif2))
for iface1 in self.get_ifaces(control=want_ctrl):
for iface2 in node.get_ifaces():
if iface1.net == iface2.net:
common.append((iface1.net, iface1, iface2))
return common
@ -620,8 +553,8 @@ class CoreNode(CoreNodeBase):
self._mounts = []
# shutdown all interfaces
for netif in self.netifs():
netif.shutdown()
for iface in self.get_ifaces():
iface.shutdown()
# kill node process if present
try:
@ -636,7 +569,7 @@ class CoreNode(CoreNodeBase):
logging.exception("error removing node directory")
# clear interface data, close client, and mark self and not up
self._netif.clear()
self.ifaces.clear()
self.client.close()
self.up = False
except OSError:
@ -704,36 +637,36 @@ class CoreNode(CoreNodeBase):
self.cmd(f"{MOUNT_BIN} -n --bind {source} {target}")
self._mounts.append((source, target))
def newifindex(self) -> int:
def next_iface_id(self) -> int:
"""
Retrieve a new interface index.
:return: new interface index
"""
with self.lock:
return super().newifindex()
return super().next_iface_id()
def newveth(self, ifindex: int = None, ifname: str = None) -> int:
def newveth(self, iface_id: int = None, ifname: str = None) -> int:
"""
Create a new interface.
:param ifindex: index for the new interface
:param iface_id: id for the new interface
:param ifname: name for the new interface
:return: nothing
"""
with self.lock:
if ifindex is None:
ifindex = self.newifindex()
if iface_id is None:
iface_id = self.next_iface_id()
if ifname is None:
ifname = f"eth{ifindex}"
ifname = f"eth{iface_id}"
sessionid = self.session.short_session_id()
try:
suffix = f"{self.id:x}.{ifindex}.{sessionid}"
suffix = f"{self.id:x}.{iface_id}.{sessionid}"
except TypeError:
suffix = f"{self.id}.{ifindex}.{sessionid}"
suffix = f"{self.id}.{iface_id}.{sessionid}"
localname = f"veth{suffix}"
if len(localname) >= 16:
@ -758,147 +691,145 @@ class CoreNode(CoreNodeBase):
flow_id = self.node_net_client.get_ifindex(veth.name)
veth.flow_id = int(flow_id)
logging.debug("interface flow index: %s - %s", veth.name, veth.flow_id)
hwaddr = self.node_net_client.get_mac(veth.name)
logging.debug("interface mac: %s - %s", veth.name, hwaddr)
veth.sethwaddr(hwaddr)
mac = self.node_net_client.get_mac(veth.name)
logging.debug("interface mac: %s - %s", veth.name, mac)
veth.set_mac(mac)
try:
# add network interface to the node. If unsuccessful, destroy the
# network interface and raise exception.
self.addnetif(veth, ifindex)
self.add_iface(veth, iface_id)
except ValueError as e:
veth.shutdown()
del veth
raise e
return ifindex
return iface_id
def newtuntap(self, ifindex: int = None, ifname: str = None) -> int:
def newtuntap(self, iface_id: int = None, ifname: str = None) -> int:
"""
Create a new tunnel tap.
:param ifindex: interface index
:param iface_id: interface id
:param ifname: interface name
:return: interface index
"""
with self.lock:
if ifindex is None:
ifindex = self.newifindex()
if iface_id is None:
iface_id = self.next_iface_id()
if ifname is None:
ifname = f"eth{ifindex}"
ifname = f"eth{iface_id}"
sessionid = self.session.short_session_id()
localname = f"tap{self.id}.{ifindex}.{sessionid}"
localname = f"tap{self.id}.{iface_id}.{sessionid}"
name = ifname
tuntap = TunTap(self.session, self, name, localname, start=self.up)
try:
self.addnetif(tuntap, ifindex)
self.add_iface(tuntap, iface_id)
except ValueError as e:
tuntap.shutdown()
del tuntap
raise e
return ifindex
return iface_id
def sethwaddr(self, ifindex: int, addr: str) -> None:
def set_mac(self, iface_id: int, mac: str) -> None:
"""
Set hardware addres for an interface.
Set hardware address for an interface.
:param ifindex: index of interface to set hardware address for
:param addr: hardware address to set
:param iface_id: id of interface to set hardware address for
:param mac: mac address to set
:return: nothing
:raises CoreCommandError: when a non-zero exit status occurs
"""
addr = utils.validate_mac(addr)
interface = self._netif[ifindex]
interface.sethwaddr(addr)
mac = utils.validate_mac(mac)
iface = self.get_iface(iface_id)
iface.set_mac(mac)
if self.up:
self.node_net_client.device_mac(interface.name, addr)
self.node_net_client.device_mac(iface.name, mac)
def addaddr(self, ifindex: int, addr: str) -> None:
def addaddr(self, iface_id: int, addr: str) -> None:
"""
Add interface address.
:param ifindex: index of interface to add address to
:param iface_id: id of interface to add address to
:param addr: address to add to interface
:return: nothing
"""
addr = utils.validate_ip(addr)
interface = self._netif[ifindex]
interface.addaddr(addr)
iface = self.get_iface(iface_id)
iface.addaddr(addr)
if self.up:
# ipv4 check
broadcast = None
if netaddr.valid_ipv4(addr):
broadcast = "+"
self.node_net_client.create_address(interface.name, addr, broadcast)
self.node_net_client.create_address(iface.name, addr, broadcast)
def deladdr(self, ifindex: int, addr: str) -> None:
def deladdr(self, iface_id: int, addr: str) -> None:
"""
Delete address from an interface.
:param ifindex: index of interface to delete address from
:param iface_id: id of interface to delete address from
:param addr: address to delete from interface
:return: nothing
:raises CoreCommandError: when a non-zero exit status occurs
"""
interface = self._netif[ifindex]
iface = self.get_iface(iface_id)
try:
interface.deladdr(addr)
iface.deladdr(addr)
except ValueError:
logging.exception("trying to delete unknown address: %s", addr)
if self.up:
self.node_net_client.delete_address(interface.name, addr)
self.node_net_client.delete_address(iface.name, addr)
def ifup(self, ifindex: int) -> None:
def ifup(self, iface_id: int) -> None:
"""
Bring an interface up.
:param ifindex: index of interface to bring up
:param iface_id: index of interface to bring up
:return: nothing
"""
if self.up:
interface_name = self.ifname(ifindex)
self.node_net_client.device_up(interface_name)
iface = self.get_iface(iface_id)
self.node_net_client.device_up(iface.name)
def newnetif(
self, net: "CoreNetworkBase", interface_data: InterfaceData
def new_iface(
self, net: "CoreNetworkBase", iface_data: InterfaceData
) -> CoreInterface:
"""
Create a new network interface.
:param net: network to associate with
:param interface_data: interface data for new interface
:param iface_data: interface data for new interface
:return: interface index
"""
addresses = interface_data.get_addresses()
addresses = iface_data.get_addresses()
with self.lock:
# TODO: emane specific code
if net.is_emane is True:
ifindex = self.newtuntap(interface_data.id, interface_data.name)
iface_id = self.newtuntap(iface_data.id, iface_data.name)
# TUN/TAP is not ready for addressing yet; the device may
# take some time to appear, and installing it into a
# namespace after it has been bound removes addressing;
# save addresses with the interface now
self.attachnet(ifindex, net)
netif = self.netif(ifindex)
netif.sethwaddr(interface_data.mac)
self.attachnet(iface_id, net)
iface = self.get_iface(iface_id)
iface.set_mac(iface_data.mac)
for address in addresses:
netif.addaddr(address)
iface.addaddr(address)
else:
ifindex = self.newveth(interface_data.id, interface_data.name)
self.attachnet(ifindex, net)
if interface_data.mac:
self.sethwaddr(ifindex, interface_data.mac)
iface_id = self.newveth(iface_data.id, iface_data.name)
self.attachnet(iface_id, net)
if iface_data.mac:
self.set_mac(iface_id, iface_data.mac)
for address in addresses:
self.addaddr(ifindex, address)
self.ifup(ifindex)
netif = self.netif(ifindex)
return netif
self.addaddr(iface_id, address)
self.ifup(iface_id)
iface = self.get_iface(iface_id)
return iface
def addfile(self, srcname: str, filename: str) -> None:
"""
@ -1041,54 +972,54 @@ class CoreNetworkBase(NodeBase):
@abc.abstractmethod
def linkconfig(
self, netif: CoreInterface, options: LinkOptions, netif2: CoreInterface = None
self, iface: CoreInterface, options: LinkOptions, iface2: CoreInterface = None
) -> None:
"""
Configure link parameters by applying tc queuing disciplines on the interface.
:param netif: interface one
:param iface: interface one
:param options: options for configuring link
:param netif2: interface two
:param iface2: interface two
:return: nothing
"""
raise NotImplementedError
def getlinknetif(self, net: "CoreNetworkBase") -> Optional[CoreInterface]:
def get_linked_iface(self, net: "CoreNetworkBase") -> Optional[CoreInterface]:
"""
Return the interface of that links this net with another net.
Return the interface that links this net with another net.
:param net: interface to get link for
:return: interface the provided network is linked to
"""
for netif in self.netifs():
if netif.othernet == net:
return netif
for iface in self.get_ifaces():
if iface.othernet == net:
return iface
return None
def attach(self, netif: CoreInterface) -> None:
def attach(self, iface: CoreInterface) -> None:
"""
Attach network interface.
:param netif: network interface to attach
:param iface: network interface to attach
:return: nothing
"""
i = self.newifindex()
self._netif[i] = netif
netif.netifi = i
i = self.next_iface_id()
self.ifaces[i] = iface
iface.net_id = i
with self._linked_lock:
self._linked[netif] = {}
self._linked[iface] = {}
def detach(self, netif: CoreInterface) -> None:
def detach(self, iface: CoreInterface) -> None:
"""
Detach network interface.
:param netif: network interface to detach
:param iface: network interface to detach
:return: nothing
"""
del self._netif[netif.netifi]
netif.netifi = None
del self.ifaces[iface.net_id]
iface.net_id = None
with self._linked_lock:
del self._linked[netif]
del self._linked[iface]
def all_link_data(self, flags: MessageFlags = MessageFlags.NONE) -> List[LinkData]:
"""
@ -1102,84 +1033,63 @@ class CoreNetworkBase(NodeBase):
# build a link message from this network node to each node having a
# connected interface
for netif in self.netifs(sort=True):
if not hasattr(netif, "node"):
continue
for iface in self.get_ifaces():
uni = False
linked_node = netif.node
linked_node = iface.node
if linked_node is None:
# two layer-2 switches/hubs linked together via linknet()
if not netif.othernet:
if not iface.othernet:
continue
linked_node = netif.othernet
linked_node = iface.othernet
if linked_node.id == self.id:
continue
netif.swapparams("_params_up")
upstream_params = netif.getparams()
netif.swapparams("_params_up")
if netif.getparams() != upstream_params:
iface.swapparams("_params_up")
upstream_params = iface.getparams()
iface.swapparams("_params_up")
if iface.getparams() != upstream_params:
uni = True
unidirectional = 0
if uni:
unidirectional = 1
interface2_ip4 = None
interface2_ip4_mask = None
interface2_ip6 = None
interface2_ip6_mask = None
for address in netif.addrlist:
iface2 = InterfaceData(
id=linked_node.get_iface_id(iface), name=iface.name, mac=iface.mac
)
for address in iface.addrlist:
ip, _sep, mask = address.partition("/")
mask = int(mask)
if netaddr.valid_ipv4(ip):
interface2_ip4 = ip
interface2_ip4_mask = mask
iface2.ip4 = ip
iface2.ip4_mask = mask
else:
interface2_ip6 = ip
interface2_ip6_mask = mask
iface2.ip6 = ip
iface2.ip6_mask = mask
options_data = iface.get_link_options(unidirectional)
link_data = LinkData(
message_type=flags,
type=self.linktype,
node1_id=self.id,
node2_id=linked_node.id,
link_type=self.linktype,
unidirectional=unidirectional,
interface2_id=linked_node.getifindex(netif),
interface2_name=netif.name,
interface2_mac=netif.hwaddr,
interface2_ip4=interface2_ip4,
interface2_ip4_mask=interface2_ip4_mask,
interface2_ip6=interface2_ip6,
interface2_ip6_mask=interface2_ip6_mask,
delay=netif.getparam("delay"),
bandwidth=netif.getparam("bw"),
dup=netif.getparam("duplicate"),
jitter=netif.getparam("jitter"),
loss=netif.getparam("loss"),
iface2=iface2,
options=options_data,
)
all_links.append(link_data)
if not uni:
continue
netif.swapparams("_params_up")
iface.swapparams("_params_up")
options_data = iface.get_link_options(unidirectional)
link_data = LinkData(
message_type=MessageFlags.NONE,
type=self.linktype,
node1_id=linked_node.id,
node2_id=self.id,
link_type=self.linktype,
unidirectional=1,
delay=netif.getparam("delay"),
bandwidth=netif.getparam("bw"),
dup=netif.getparam("duplicate"),
jitter=netif.getparam("jitter"),
loss=netif.getparam("loss"),
options=options_data,
)
netif.swapparams("_params_up")
iface.swapparams("_params_up")
all_links.append(link_data)
return all_links

View file

@ -141,7 +141,7 @@ class DockerNode(CoreNode):
return
with self.lock:
self._netif.clear()
self.ifaces.clear()
self.client.stop_container()
self.up = False

View file

@ -7,8 +7,9 @@ import time
from typing import TYPE_CHECKING, Callable, Dict, List, Optional, Tuple
from core import utils
from core.emulator.enumerations import MessageFlags, TransportType
from core.errors import CoreCommandError
from core.emulator.data import LinkOptions
from core.emulator.enumerations import TransportType
from core.errors import CoreCommandError, CoreError
from core.nodes.netclient import LinuxNetClient, get_net_client
if TYPE_CHECKING:
@ -52,16 +53,16 @@ class CoreInterface:
self.othernet: Optional[CoreNetworkBase] = None
self._params: Dict[str, float] = {}
self.addrlist: List[str] = []
self.hwaddr: Optional[str] = None
self.mac: Optional[str] = None
# placeholder position hook
self.poshook: Callable[[CoreInterface], None] = lambda x: None
# used with EMANE
self.transport_type: Optional[TransportType] = None
# node interface index
self.netindex: Optional[int] = None
# net interface index
self.netifi: Optional[int] = None
# index used to find flow data
# id of interface for node
self.node_id: Optional[int] = None
# id of interface for network
self.net_id: Optional[int] = None
# id used to find flow data
self.flow_id: Optional[int] = None
self.server: Optional["DistributedServer"] = server
use_ovs = session.options.get_config("ovs") == "True"
@ -149,16 +150,16 @@ class CoreInterface:
"""
self.addrlist.remove(addr)
def sethwaddr(self, addr: str) -> None:
def set_mac(self, mac: str) -> None:
"""
Set hardware address.
Set mac address.
:param addr: hardware address to set to.
:param mac: mac address to set
:return: nothing
"""
if addr is not None:
addr = utils.validate_mac(addr)
self.hwaddr = addr
if mac is not None:
mac = utils.validate_mac(mac)
self.mac = mac
def getparam(self, key: str) -> float:
"""
@ -169,6 +170,34 @@ class CoreInterface:
"""
return self._params.get(key)
def get_link_options(self, unidirectional: int) -> LinkOptions:
"""
Get currently set params as link options.
:param unidirectional: unidirectional setting
:return: link options
"""
delay = self.getparam("delay")
if delay is not None:
delay = int(delay)
bandwidth = self.getparam("bw")
if bandwidth is not None:
bandwidth = int(bandwidth)
dup = self.getparam("duplicate")
if dup is not None:
dup = int(dup)
jitter = self.getparam("jitter")
if jitter is not None:
jitter = int(jitter)
return LinkOptions(
delay=delay,
bandwidth=bandwidth,
dup=dup,
jitter=jitter,
loss=self.getparam("loss"),
unidirectional=unidirectional,
)
def getparams(self) -> List[Tuple[str, float]]:
"""
Return (key, value) pairs for parameters.
@ -284,19 +313,16 @@ class Veth(CoreInterface):
"""
if not self.up:
return
if self.node:
try:
self.node.node_net_client.device_flush(self.name)
except CoreCommandError:
logging.exception("error shutting down interface")
if self.localname:
try:
self.net_client.delete_device(self.localname)
except CoreCommandError:
logging.info("link already removed: %s", self.localname)
self.up = False
@ -518,7 +544,7 @@ class GreTap(CoreInterface):
if not start:
return
if remoteip is None:
raise ValueError("missing remote IP required for GRE TAP device")
raise CoreError("missing remote IP required for GRE TAP device")
self.net_client.create_gretap(self.localname, remoteip, localip, ttl, key)
self.net_client.device_up(self.localname)
self.up = True
@ -535,23 +561,4 @@ class GreTap(CoreInterface):
self.net_client.delete_device(self.localname)
except CoreCommandError:
logging.exception("error during shutdown")
self.localname = None
def data(self, message_type: int) -> None:
"""
Data for a gre tap.
:param message_type: message type for data
:return: None
"""
return None
def all_link_data(self, flags: MessageFlags = MessageFlags.NONE) -> List:
"""
Retrieve link data.
:param flags: link flags
:return: link data
"""
return []

View file

@ -126,7 +126,7 @@ class LxcNode(CoreNode):
return
with self.lock:
self._netif.clear()
self.ifaces.clear()
self.client.stop_container()
self.up = False
@ -215,7 +215,7 @@ class LxcNode(CoreNode):
self.client.copy_file(source, filename)
self.cmd(f"chmod {mode:o} {filename}")
def addnetif(self, netif: CoreInterface, ifindex: int) -> None:
super().addnetif(netif, ifindex)
def add_iface(self, iface: CoreInterface, iface_id: int) -> None:
super().add_iface(iface, iface_id)
# adding small delay to allow time for adding addresses to work correctly
time.sleep(0.5)

View file

@ -155,14 +155,14 @@ class LinuxNetClient:
"""
self.run(f"{TC_BIN} qdisc delete dev {device} root")
def checksums_off(self, interface_name: str) -> None:
def checksums_off(self, iface_name: str) -> None:
"""
Turns interface checksums off.
:param interface_name: interface to update
:param iface_name: interface to update
:return: nothing
"""
self.run(f"{ETHTOOL_BIN} -K {interface_name} rx off tx off")
self.run(f"{ETHTOOL_BIN} -K {iface_name} rx off tx off")
def create_address(self, device: str, address: str, broadcast: str = None) -> None:
"""
@ -250,26 +250,26 @@ class LinuxNetClient:
self.device_down(name)
self.run(f"{IP_BIN} link delete {name} type bridge")
def set_interface_master(self, bridge_name: str, interface_name: str) -> None:
def set_iface_master(self, bridge_name: str, iface_name: str) -> None:
"""
Assign interface master to a Linux bridge.
:param bridge_name: bridge name
:param interface_name: interface name
:param iface_name: interface name
:return: nothing
"""
self.run(f"{IP_BIN} link set dev {interface_name} master {bridge_name}")
self.device_up(interface_name)
self.run(f"{IP_BIN} link set dev {iface_name} master {bridge_name}")
self.device_up(iface_name)
def delete_interface(self, bridge_name: str, interface_name: str) -> None:
def delete_iface(self, bridge_name: str, iface_name: str) -> None:
"""
Delete an interface associated with a Linux bridge.
:param bridge_name: bridge name
:param interface_name: interface name
:param iface_name: interface name
:return: nothing
"""
self.run(f"{IP_BIN} link set dev {interface_name} nomaster")
self.run(f"{IP_BIN} link set dev {iface_name} nomaster")
def existing_bridges(self, _id: int) -> bool:
"""
@ -330,26 +330,26 @@ class OvsNetClient(LinuxNetClient):
self.device_down(name)
self.run(f"{OVS_BIN} del-br {name}")
def set_interface_master(self, bridge_name: str, interface_name: str) -> None:
def set_iface_master(self, bridge_name: str, iface_name: str) -> None:
"""
Create an interface associated with a network bridge.
:param bridge_name: bridge name
:param interface_name: interface name
:param iface_name: interface name
:return: nothing
"""
self.run(f"{OVS_BIN} add-port {bridge_name} {interface_name}")
self.device_up(interface_name)
self.run(f"{OVS_BIN} add-port {bridge_name} {iface_name}")
self.device_up(iface_name)
def delete_interface(self, bridge_name: str, interface_name: str) -> None:
def delete_iface(self, bridge_name: str, iface_name: str) -> None:
"""
Delete an interface associated with a OVS bridge.
:param bridge_name: bridge name
:param interface_name: interface name
:param iface_name: interface name
:return: nothing
"""
self.run(f"{OVS_BIN} del-port {bridge_name} {interface_name}")
self.run(f"{OVS_BIN} del-port {bridge_name} {iface_name}")
def existing_bridges(self, _id: int) -> bool:
"""

View file

@ -11,8 +11,7 @@ import netaddr
from core import utils
from core.constants import EBTABLES_BIN, TC_BIN
from core.emulator.data import LinkData, NodeData
from core.emulator.emudata import InterfaceData, LinkOptions
from core.emulator.data import InterfaceData, LinkData, LinkOptions
from core.emulator.enumerations import (
LinkTypes,
MessageFlags,
@ -216,20 +215,20 @@ class EbtablesQueue:
]
)
# rebuild the chain
for netif1, v in wlan._linked.items():
for netif2, linked in v.items():
for iface1, v in wlan._linked.items():
for oface2, linked in v.items():
if wlan.policy == NetworkPolicy.DROP and linked:
self.cmds.extend(
[
f"-A {wlan.brname} -i {netif1.localname} -o {netif2.localname} -j ACCEPT",
f"-A {wlan.brname} -o {netif1.localname} -i {netif2.localname} -j ACCEPT",
f"-A {wlan.brname} -i {iface1.localname} -o {oface2.localname} -j ACCEPT",
f"-A {wlan.brname} -o {iface1.localname} -i {oface2.localname} -j ACCEPT",
]
)
elif wlan.policy == NetworkPolicy.ACCEPT and not linked:
self.cmds.extend(
[
f"-A {wlan.brname} -i {netif1.localname} -o {netif2.localname} -j DROP",
f"-A {wlan.brname} -o {netif1.localname} -i {netif2.localname} -j DROP",
f"-A {wlan.brname} -i {iface1.localname} -o {oface2.localname} -j DROP",
f"-A {wlan.brname} -o {iface1.localname} -i {oface2.localname} -j DROP",
]
)
@ -347,53 +346,53 @@ class CoreNetwork(CoreNetworkBase):
logging.exception("error during shutdown")
# removes veth pairs used for bridge-to-bridge connections
for netif in self.netifs():
netif.shutdown()
for iface in self.get_ifaces():
iface.shutdown()
self._netif.clear()
self.ifaces.clear()
self._linked.clear()
del self.session
self.up = False
def attach(self, netif: CoreInterface) -> None:
def attach(self, iface: CoreInterface) -> None:
"""
Attach a network interface.
:param netif: network interface to attach
:param iface: network interface to attach
:return: nothing
"""
if self.up:
netif.net_client.set_interface_master(self.brname, netif.localname)
super().attach(netif)
iface.net_client.set_iface_master(self.brname, iface.localname)
super().attach(iface)
def detach(self, netif: CoreInterface) -> None:
def detach(self, iface: CoreInterface) -> None:
"""
Detach a network interface.
:param netif: network interface to detach
:param iface: network interface to detach
:return: nothing
"""
if self.up:
netif.net_client.delete_interface(self.brname, netif.localname)
super().detach(netif)
iface.net_client.delete_iface(self.brname, iface.localname)
super().detach(iface)
def linked(self, netif1: CoreInterface, netif2: CoreInterface) -> bool:
def linked(self, iface1: CoreInterface, iface2: CoreInterface) -> bool:
"""
Determine if the provided network interfaces are linked.
:param netif1: interface one
:param netif2: interface two
:param iface1: interface one
:param iface2: interface two
:return: True if interfaces are linked, False otherwise
"""
# check if the network interfaces are attached to this network
if self._netif[netif1.netifi] != netif1:
raise ValueError(f"inconsistency for netif {netif1.name}")
if self.ifaces[iface1.net_id] != iface1:
raise ValueError(f"inconsistency for interface {iface1.name}")
if self._netif[netif2.netifi] != netif2:
raise ValueError(f"inconsistency for netif {netif2.name}")
if self.ifaces[iface2.net_id] != iface2:
raise ValueError(f"inconsistency for interface {iface2.name}")
try:
linked = self._linked[netif1][netif2]
linked = self._linked[iface1][iface2]
except KeyError:
if self.policy == NetworkPolicy.ACCEPT:
linked = True
@ -401,93 +400,93 @@ class CoreNetwork(CoreNetworkBase):
linked = False
else:
raise Exception(f"unknown policy: {self.policy.value}")
self._linked[netif1][netif2] = linked
self._linked[iface1][iface2] = linked
return linked
def unlink(self, netif1: CoreInterface, netif2: CoreInterface) -> None:
def unlink(self, iface1: CoreInterface, iface2: CoreInterface) -> None:
"""
Unlink two interfaces, resulting in adding or removing ebtables
filtering rules.
:param netif1: interface one
:param netif2: interface two
:param iface1: interface one
:param iface2: interface two
:return: nothing
"""
with self._linked_lock:
if not self.linked(netif1, netif2):
if not self.linked(iface1, iface2):
return
self._linked[netif1][netif2] = False
self._linked[iface1][iface2] = False
ebq.ebchange(self)
def link(self, netif1: CoreInterface, netif2: CoreInterface) -> None:
def link(self, iface1: CoreInterface, iface2: CoreInterface) -> None:
"""
Link two interfaces together, resulting in adding or removing
ebtables filtering rules.
:param netif1: interface one
:param netif2: interface two
:param iface1: interface one
:param iface2: interface two
:return: nothing
"""
with self._linked_lock:
if self.linked(netif1, netif2):
if self.linked(iface1, iface2):
return
self._linked[netif1][netif2] = True
self._linked[iface1][iface2] = True
ebq.ebchange(self)
def linkconfig(
self, netif: CoreInterface, options: LinkOptions, netif2: CoreInterface = None
self, iface: CoreInterface, options: LinkOptions, iface2: CoreInterface = None
) -> None:
"""
Configure link parameters by applying tc queuing disciplines on the interface.
:param netif: interface one
:param iface: interface one
:param options: options for configuring link
:param netif2: interface two
:param iface2: interface two
:return: nothing
"""
devname = netif.localname
devname = iface.localname
tc = f"{TC_BIN} qdisc replace dev {devname}"
parent = "root"
changed = False
bw = options.bandwidth
if netif.setparam("bw", bw):
if iface.setparam("bw", bw):
# from tc-tbf(8): minimum value for burst is rate / kernel_hz
burst = max(2 * netif.mtu, int(bw / 1000))
burst = max(2 * iface.mtu, int(bw / 1000))
# max IP payload
limit = 0xFFFF
tbf = f"tbf rate {bw} burst {burst} limit {limit}"
if bw > 0:
if self.up:
cmd = f"{tc} {parent} handle 1: {tbf}"
netif.host_cmd(cmd)
netif.setparam("has_tbf", True)
iface.host_cmd(cmd)
iface.setparam("has_tbf", True)
changed = True
elif netif.getparam("has_tbf") and bw <= 0:
elif iface.getparam("has_tbf") and bw <= 0:
if self.up:
cmd = f"{TC_BIN} qdisc delete dev {devname} {parent}"
netif.host_cmd(cmd)
netif.setparam("has_tbf", False)
iface.host_cmd(cmd)
iface.setparam("has_tbf", False)
# removing the parent removes the child
netif.setparam("has_netem", False)
iface.setparam("has_netem", False)
changed = True
if netif.getparam("has_tbf"):
if iface.getparam("has_tbf"):
parent = "parent 1:1"
netem = "netem"
delay = options.delay
changed = max(changed, netif.setparam("delay", delay))
changed = max(changed, iface.setparam("delay", delay))
loss = options.loss
if loss is not None:
loss = float(loss)
changed = max(changed, netif.setparam("loss", loss))
changed = max(changed, iface.setparam("loss", loss))
duplicate = options.dup
if duplicate is not None:
duplicate = int(duplicate)
changed = max(changed, netif.setparam("duplicate", duplicate))
changed = max(changed, iface.setparam("duplicate", duplicate))
jitter = options.jitter
changed = max(changed, netif.setparam("jitter", jitter))
changed = max(changed, iface.setparam("jitter", jitter))
if not changed:
return
# jitter and delay use the same delay statement
@ -510,19 +509,19 @@ class CoreNetwork(CoreNetworkBase):
duplicate_check = duplicate is None or duplicate <= 0
if all([delay_check, jitter_check, loss_check, duplicate_check]):
# possibly remove netem if it exists and parent queue wasn't removed
if not netif.getparam("has_netem"):
if not iface.getparam("has_netem"):
return
if self.up:
cmd = f"{TC_BIN} qdisc delete dev {devname} {parent} handle 10:"
netif.host_cmd(cmd)
netif.setparam("has_netem", False)
iface.host_cmd(cmd)
iface.setparam("has_netem", False)
elif len(netem) > 1:
if self.up:
cmd = (
f"{TC_BIN} qdisc replace dev {devname} {parent} handle 10: {netem}"
)
netif.host_cmd(cmd)
netif.setparam("has_netem", True)
iface.host_cmd(cmd)
iface.setparam("has_netem", True)
def linknet(self, net: CoreNetworkBase) -> CoreInterface:
"""
@ -551,19 +550,19 @@ class CoreNetwork(CoreNetworkBase):
if len(name) >= 16:
raise ValueError(f"interface name {name} too long")
netif = Veth(self.session, None, name, localname, start=self.up)
self.attach(netif)
iface = Veth(self.session, None, name, localname, start=self.up)
self.attach(iface)
if net.up and net.brname:
netif.net_client.set_interface_master(net.brname, netif.name)
i = net.newifindex()
net._netif[i] = netif
iface.net_client.set_iface_master(net.brname, iface.name)
i = net.next_iface_id()
net.ifaces[i] = iface
with net._linked_lock:
net._linked[netif] = {}
netif.net = self
netif.othernet = net
return netif
net._linked[iface] = {}
iface.net = self
iface.othernet = net
return iface
def getlinknetif(self, net: CoreNetworkBase) -> Optional[CoreInterface]:
def get_linked_iface(self, net: CoreNetworkBase) -> Optional[CoreInterface]:
"""
Return the interface of that links this net with another net
(that were linked using linknet()).
@ -571,9 +570,9 @@ class CoreNetwork(CoreNetworkBase):
:param net: interface to get link for
:return: interface the provided network is linked to
"""
for netif in self.netifs():
if netif.othernet == net:
return netif
for iface in self.get_ifaces():
if iface.othernet == net:
return iface
return None
def addrconfig(self, addrlist: List[str]) -> None:
@ -619,7 +618,6 @@ class GreTapBridge(CoreNetwork):
:param localip: local address
:param ttl: ttl value
:param key: gre tap key
:param start: start flag
:param server: remote server node
will run on, default is None for localhost
"""
@ -690,17 +688,17 @@ class GreTapBridge(CoreNetwork):
)
self.attach(self.gretap)
def setkey(self, key: int, interface_data: InterfaceData) -> None:
def setkey(self, key: int, iface_data: InterfaceData) -> None:
"""
Set the GRE key used for the GreTap device. This needs to be set
prior to instantiating the GreTap device (before addrconfig).
:param key: gre key
:param interface_data: interface data for setting up tunnel key
:param iface_data: interface data for setting up tunnel key
:return: nothing
"""
self.grekey = key
addresses = interface_data.get_addresses()
addresses = iface_data.get_addresses()
if addresses:
self.addrconfig(addresses)
@ -802,7 +800,7 @@ class CtrlNet(CoreNetwork):
self.host_cmd(f"{self.updown_script} {self.brname} startup")
if self.serverintf:
self.net_client.set_interface_master(self.brname, self.serverintf)
self.net_client.set_iface_master(self.brname, self.serverintf)
def shutdown(self) -> None:
"""
@ -812,7 +810,7 @@ class CtrlNet(CoreNetwork):
"""
if self.serverintf is not None:
try:
self.net_client.delete_interface(self.brname, self.serverintf)
self.net_client.delete_iface(self.brname, self.serverintf)
except CoreCommandError:
logging.exception(
"error deleting server interface %s from bridge %s",
@ -850,31 +848,16 @@ class PtpNet(CoreNetwork):
policy: NetworkPolicy = NetworkPolicy.ACCEPT
def attach(self, netif: CoreInterface) -> None:
def attach(self, iface: CoreInterface) -> None:
"""
Attach a network interface, but limit attachment to two interfaces.
:param netif: network interface
:param iface: network interface
:return: nothing
"""
if len(self._netif) >= 2:
raise ValueError(
"Point-to-point links support at most 2 network interfaces"
)
super().attach(netif)
def data(
self, message_type: MessageFlags = MessageFlags.NONE, source: str = None
) -> Optional[NodeData]:
"""
Do not generate a Node Message for point-to-point links. They are
built using a link message instead.
:param message_type: purpose for the data object we are creating
:param source: source of node data
:return: node data object
"""
return None
if len(self.ifaces) >= 2:
raise CoreError("ptp links support at most 2 network interfaces")
super().attach(iface)
def all_link_data(self, flags: MessageFlags = MessageFlags.NONE) -> List[LinkData]:
"""
@ -885,87 +868,68 @@ class PtpNet(CoreNetwork):
:return: list of link data
"""
all_links = []
if len(self._netif) != 2:
if len(self.ifaces) != 2:
return all_links
interface1, interface2 = self._netif.values()
ifaces = self.get_ifaces()
iface1 = ifaces[0]
iface2 = ifaces[1]
unidirectional = 0
if interface1.getparams() != interface2.getparams():
if iface1.getparams() != iface2.getparams():
unidirectional = 1
interface1_ip4 = None
interface1_ip4_mask = None
interface1_ip6 = None
interface1_ip6_mask = None
for address in interface1.addrlist:
iface1_data = InterfaceData(
id=iface1.node.get_iface_id(iface1), name=iface1.name, mac=iface1.mac
)
for address in iface1.addrlist:
ip, _sep, mask = address.partition("/")
mask = int(mask)
if netaddr.valid_ipv4(ip):
interface1_ip4 = ip
interface1_ip4_mask = mask
iface1.ip4 = ip
iface1.ip4_mask = mask
else:
interface1_ip6 = ip
interface1_ip6_mask = mask
iface1.ip6 = ip
iface1.ip6_mask = mask
interface2_ip4 = None
interface2_ip4_mask = None
interface2_ip6 = None
interface2_ip6_mask = None
for address in interface2.addrlist:
iface2_data = InterfaceData(
id=iface2.node.get_iface_id(iface2), name=iface2.name, mac=iface2.mac
)
for address in iface2.addrlist:
ip, _sep, mask = address.partition("/")
mask = int(mask)
if netaddr.valid_ipv4(ip):
interface2_ip4 = ip
interface2_ip4_mask = mask
iface2.ip4 = ip
iface2.ip4_mask = mask
else:
interface2_ip6 = ip
interface2_ip6_mask = mask
iface2.ip6 = ip
iface2.ip6_mask = mask
options_data = iface1.get_link_options(unidirectional)
link_data = LinkData(
message_type=flags,
node1_id=interface1.node.id,
node2_id=interface2.node.id,
link_type=self.linktype,
unidirectional=unidirectional,
delay=interface1.getparam("delay"),
bandwidth=interface1.getparam("bw"),
loss=interface1.getparam("loss"),
dup=interface1.getparam("duplicate"),
jitter=interface1.getparam("jitter"),
interface1_id=interface1.node.getifindex(interface1),
interface1_name=interface1.name,
interface1_mac=interface1.hwaddr,
interface1_ip4=interface1_ip4,
interface1_ip4_mask=interface1_ip4_mask,
interface1_ip6=interface1_ip6,
interface1_ip6_mask=interface1_ip6_mask,
interface2_id=interface2.node.getifindex(interface2),
interface2_name=interface2.name,
interface2_mac=interface2.hwaddr,
interface2_ip4=interface2_ip4,
interface2_ip4_mask=interface2_ip4_mask,
interface2_ip6=interface2_ip6,
interface2_ip6_mask=interface2_ip6_mask,
type=self.linktype,
node1_id=iface1.node.id,
node2_id=iface2.node.id,
iface1=iface1_data,
iface2=iface2_data,
options=options_data,
)
all_links.append(link_data)
# build a 2nd link message for the upstream link parameters
# (swap if1 and if2)
if unidirectional:
iface1_data = InterfaceData(id=iface2.node.get_iface_id(iface2))
iface2_data = InterfaceData(id=iface1.node.get_iface_id(iface1))
options_data = iface2.get_link_options(unidirectional)
link_data = LinkData(
message_type=MessageFlags.NONE,
link_type=self.linktype,
node1_id=interface2.node.id,
node2_id=interface1.node.id,
delay=interface2.getparam("delay"),
bandwidth=interface2.getparam("bw"),
loss=interface2.getparam("loss"),
dup=interface2.getparam("duplicate"),
jitter=interface2.getparam("jitter"),
unidirectional=1,
interface1_id=interface2.node.getifindex(interface2),
interface2_id=interface1.node.getifindex(interface1),
type=self.linktype,
node1_id=iface2.node.id,
node2_id=iface1.node.id,
iface1=iface1_data,
iface2=iface2_data,
options=options_data,
)
all_links.append(link_data)
return all_links
@ -1025,7 +989,6 @@ class WlanNode(CoreNetwork):
:param session: core session instance
:param _id: node id
:param name: node name
:param start: start flag
:param server: remote server node
will run on, default is None for localhost
:param policy: wlan policy
@ -1045,17 +1008,17 @@ class WlanNode(CoreNetwork):
self.net_client.disable_mac_learning(self.brname)
ebq.ebchange(self)
def attach(self, netif: CoreInterface) -> None:
def attach(self, iface: CoreInterface) -> None:
"""
Attach a network interface.
:param netif: network interface
:param iface: network interface
:return: nothing
"""
super().attach(netif)
super().attach(iface)
if self.model:
netif.poshook = self.model.position_callback
netif.setposition()
iface.poshook = self.model.position_callback
iface.setposition()
def setmodel(self, model: "WirelessModelType", config: Dict[str, str]):
"""
@ -1068,9 +1031,9 @@ class WlanNode(CoreNetwork):
logging.debug("node(%s) setting model: %s", self.name, model.name)
if model.config_type == RegisterTlvs.WIRELESS:
self.model = model(session=self.session, _id=self.id)
for netif in self.netifs():
netif.poshook = self.model.position_callback
netif.setposition()
for iface in self.get_ifaces():
iface.poshook = self.model.position_callback
iface.setposition()
self.updatemodel(config)
elif model.config_type == RegisterTlvs.MOBILITY:
self.mobility = model(session=self.session, _id=self.id)
@ -1088,8 +1051,8 @@ class WlanNode(CoreNetwork):
"node(%s) updating model(%s): %s", self.id, self.model.name, config
)
self.model.update_config(config)
for netif in self.netifs():
netif.setposition()
for iface in self.get_ifaces():
iface.setposition()
def all_link_data(self, flags: MessageFlags = MessageFlags.NONE) -> List[LinkData]:
"""

View file

@ -9,8 +9,8 @@ from typing import IO, TYPE_CHECKING, List, Optional, Tuple
from core import utils
from core.constants import MOUNT_BIN, UMOUNT_BIN
from core.emulator.data import InterfaceData, LinkOptions
from core.emulator.distributed import DistributedServer
from core.emulator.emudata import InterfaceData, LinkOptions
from core.emulator.enumerations import NodeTypes, TransportType
from core.errors import CoreCommandError, CoreError
from core.nodes.base import CoreNetworkBase, CoreNodeBase
@ -51,8 +51,8 @@ class PhysicalNode(CoreNodeBase):
_source, target = self._mounts.pop(-1)
self.umount(target)
for netif in self.netifs():
netif.shutdown()
for iface in self.get_ifaces():
iface.shutdown()
self.rmnodedir()
@ -65,117 +65,115 @@ class PhysicalNode(CoreNodeBase):
"""
return sh
def sethwaddr(self, ifindex: int, addr: str) -> None:
def set_mac(self, iface_id: int, mac: str) -> None:
"""
Set hardware address for an interface.
Set mac address for an interface.
:param ifindex: index of interface to set hardware address for
:param addr: hardware address to set
:param iface_id: index of interface to set hardware address for
:param mac: mac address to set
:return: nothing
:raises CoreCommandError: when a non-zero exit status occurs
"""
addr = utils.validate_mac(addr)
interface = self._netif[ifindex]
interface.sethwaddr(addr)
mac = utils.validate_mac(mac)
iface = self.ifaces[iface_id]
iface.set_mac(mac)
if self.up:
self.net_client.device_mac(interface.name, addr)
self.net_client.device_mac(iface.name, mac)
def addaddr(self, ifindex: int, addr: str) -> None:
def addaddr(self, iface_id: int, addr: str) -> None:
"""
Add an address to an interface.
:param ifindex: index of interface to add address to
:param iface_id: index of interface to add address to
:param addr: address to add
:return: nothing
"""
addr = utils.validate_ip(addr)
interface = self._netif[ifindex]
iface = self.get_iface(iface_id)
if self.up:
self.net_client.create_address(interface.name, addr)
interface.addaddr(addr)
self.net_client.create_address(iface.name, addr)
iface.addaddr(addr)
def deladdr(self, ifindex: int, addr: str) -> None:
def deladdr(self, iface_id: int, addr: str) -> None:
"""
Delete an address from an interface.
:param ifindex: index of interface to delete
:param iface_id: index of interface to delete
:param addr: address to delete
:return: nothing
"""
interface = self._netif[ifindex]
iface = self.ifaces[iface_id]
try:
interface.deladdr(addr)
iface.deladdr(addr)
except ValueError:
logging.exception("trying to delete unknown address: %s", addr)
if self.up:
self.net_client.delete_address(interface.name, addr)
self.net_client.delete_address(iface.name, addr)
def adoptnetif(
self, netif: CoreInterface, ifindex: int, hwaddr: str, addrlist: List[str]
def adopt_iface(
self, iface: CoreInterface, iface_id: int, mac: str, addrlist: List[str]
) -> None:
"""
When a link message is received linking this node to another part of
the emulation, no new interface is created; instead, adopt the
GreTap netif as the node interface.
GreTap interface as the node interface.
"""
netif.name = f"gt{ifindex}"
netif.node = self
self.addnetif(netif, ifindex)
iface.name = f"gt{iface_id}"
iface.node = self
self.add_iface(iface, iface_id)
# use a more reasonable name, e.g. "gt0" instead of "gt.56286.150"
if self.up:
self.net_client.device_down(netif.localname)
self.net_client.device_name(netif.localname, netif.name)
netif.localname = netif.name
if hwaddr:
self.sethwaddr(ifindex, hwaddr)
self.net_client.device_down(iface.localname)
self.net_client.device_name(iface.localname, iface.name)
iface.localname = iface.name
if mac:
self.set_mac(iface_id, mac)
for addr in addrlist:
self.addaddr(ifindex, addr)
self.addaddr(iface_id, addr)
if self.up:
self.net_client.device_up(netif.localname)
self.net_client.device_up(iface.localname)
def linkconfig(
self, netif: CoreInterface, options: LinkOptions, netif2: CoreInterface = None
self, iface: CoreInterface, options: LinkOptions, iface2: CoreInterface = None
) -> None:
"""
Apply tc queing disciplines using linkconfig.
"""
linux_bridge = CoreNetwork(self.session)
linux_bridge.up = True
linux_bridge.linkconfig(netif, options, netif2)
linux_bridge.linkconfig(iface, options, iface2)
del linux_bridge
def newifindex(self) -> int:
def next_iface_id(self) -> int:
with self.lock:
while self.ifindex in self._netif:
self.ifindex += 1
ifindex = self.ifindex
self.ifindex += 1
return ifindex
while self.iface_id in self.ifaces:
self.iface_id += 1
iface_id = self.iface_id
self.iface_id += 1
return iface_id
def newnetif(
self, net: CoreNetworkBase, interface_data: InterfaceData
def new_iface(
self, net: CoreNetworkBase, iface_data: InterfaceData
) -> CoreInterface:
logging.info("creating interface")
addresses = interface_data.get_addresses()
ifindex = interface_data.id
if ifindex is None:
ifindex = self.newifindex()
name = interface_data.name
addresses = iface_data.get_addresses()
iface_id = iface_data.id
if iface_id is None:
iface_id = self.next_iface_id()
name = iface_data.name
if name is None:
name = f"gt{ifindex}"
name = f"gt{iface_id}"
if self.up:
# this is reached when this node is linked to a network node
# tunnel to net not built yet, so build it now and adopt it
_, remote_tap = self.session.distributed.create_gre_tunnel(net, self.server)
self.adoptnetif(remote_tap, ifindex, interface_data.mac, addresses)
self.adopt_iface(remote_tap, iface_id, iface_data.mac, addresses)
return remote_tap
else:
# this is reached when configuring services (self.up=False)
netif = GreTap(node=self, name=name, session=self.session, start=False)
self.adoptnetif(netif, ifindex, interface_data.mac, addresses)
return netif
iface = GreTap(node=self, name=name, session=self.session, start=False)
self.adopt_iface(iface, iface_id, iface_data.mac, addresses)
return iface
def privatedir(self, path: str) -> None:
if path[0] != "/":
@ -257,10 +255,10 @@ class Rj45Node(CoreNodeBase):
will run on, default is None for localhost
"""
super().__init__(session, _id, name, server)
self.interface = CoreInterface(session, self, name, name, mtu, server)
self.interface.transport_type = TransportType.RAW
self.iface = CoreInterface(session, self, name, name, mtu, server)
self.iface.transport_type = TransportType.RAW
self.lock: threading.RLock = threading.RLock()
self.ifindex: Optional[int] = None
self.iface_id: Optional[int] = None
self.old_up: bool = False
self.old_addrs: List[Tuple[str, Optional[str]]] = []
@ -273,7 +271,7 @@ class Rj45Node(CoreNodeBase):
"""
# interface will also be marked up during net.attach()
self.savestate()
self.net_client.device_up(self.interface.localname)
self.net_client.device_up(self.iface.localname)
self.up = True
def shutdown(self) -> None:
@ -285,7 +283,7 @@ class Rj45Node(CoreNodeBase):
"""
if not self.up:
return
localname = self.interface.localname
localname = self.iface.localname
self.net_client.device_down(localname)
self.net_client.device_flush(localname)
try:
@ -295,8 +293,8 @@ class Rj45Node(CoreNodeBase):
self.up = False
self.restorestate()
def newnetif(
self, net: CoreNetworkBase, interface_data: InterfaceData
def new_iface(
self, net: CoreNetworkBase, iface_data: InterfaceData
) -> CoreInterface:
"""
This is called when linking with another node. Since this node
@ -304,70 +302,51 @@ class Rj45Node(CoreNodeBase):
but attach ourselves to the given network.
:param net: new network instance
:param interface_data: interface data for new interface
:param iface_data: interface data for new interface
:return: interface index
:raises ValueError: when an interface has already been created, one max
"""
with self.lock:
ifindex = interface_data.id
if ifindex is None:
ifindex = 0
if self.interface.net is not None:
raise ValueError("RJ45 nodes support at most 1 network interface")
self._netif[ifindex] = self.interface
self.ifindex = ifindex
iface_id = iface_data.id
if iface_id is None:
iface_id = 0
if self.iface.net is not None:
raise CoreError("RJ45 nodes support at most 1 network interface")
self.ifaces[iface_id] = self.iface
self.iface_id = iface_id
if net is not None:
self.interface.attachnet(net)
for addr in interface_data.get_addresses():
self.iface.attachnet(net)
for addr in iface_data.get_addresses():
self.addaddr(addr)
return self.interface
return self.iface
def delnetif(self, ifindex: int) -> None:
def delete_iface(self, iface_id: int) -> None:
"""
Delete a network interface.
:param ifindex: interface index to delete
:param iface_id: interface index to delete
:return: nothing
"""
if ifindex is None:
ifindex = 0
self._netif.pop(ifindex)
if ifindex == self.ifindex:
self.shutdown()
else:
raise ValueError(f"ifindex {ifindex} does not exist")
self.get_iface(iface_id)
self.ifaces.pop(iface_id)
self.shutdown()
def netif(
self, ifindex: int, net: CoreNetworkBase = None
) -> Optional[CoreInterface]:
"""
This object is considered the network interface, so we only
return self here. This keeps the RJ45Node compatible with
real nodes.
def get_iface(self, iface_id: int) -> CoreInterface:
if iface_id != self.iface_id or iface_id not in self.ifaces:
raise CoreError(f"node({self.name}) interface({iface_id}) does not exist")
return self.iface
:param ifindex: interface index to retrieve
:param net: network to retrieve
:return: a network interface
"""
if net is not None and net == self.interface.net:
return self.interface
if ifindex is None:
ifindex = 0
if ifindex == self.ifindex:
return self.interface
return None
def getifindex(self, netif: CoreInterface) -> Optional[int]:
def get_iface_id(self, iface: CoreInterface) -> Optional[int]:
"""
Retrieve network interface index.
:param netif: network interface to retrieve
:param iface: network interface to retrieve
index for
:return: interface index, None otherwise
"""
if netif != self.interface:
return None
return self.ifindex
if iface is not self.iface:
raise CoreError(f"node({self.name}) does not have interface({iface.name})")
return self.iface_id
def addaddr(self, addr: str) -> None:
"""
@ -380,7 +359,7 @@ class Rj45Node(CoreNodeBase):
addr = utils.validate_ip(addr)
if self.up:
self.net_client.create_address(self.name, addr)
self.interface.addaddr(addr)
self.iface.addaddr(addr)
def deladdr(self, addr: str) -> None:
"""
@ -392,7 +371,7 @@ class Rj45Node(CoreNodeBase):
"""
if self.up:
self.net_client.delete_address(self.name, addr)
self.interface.deladdr(addr)
self.iface.deladdr(addr)
def savestate(self) -> None:
"""
@ -404,7 +383,7 @@ class Rj45Node(CoreNodeBase):
"""
self.old_up = False
self.old_addrs: List[Tuple[str, Optional[str]]] = []
localname = self.interface.localname
localname = self.iface.localname
output = self.net_client.address_show(localname)
for line in output.split("\n"):
items = line.split()
@ -429,7 +408,7 @@ class Rj45Node(CoreNodeBase):
:return: nothing
:raises CoreCommandError: when there is a command exception
"""
localname = self.interface.localname
localname = self.iface.localname
logging.info("restoring rj45 state: %s", localname)
for addr in self.old_addrs:
self.net_client.create_address(localname, addr[0], addr[1])
@ -446,7 +425,7 @@ class Rj45Node(CoreNodeBase):
:return: True if position changed, False otherwise
"""
super().setposition(x, y, z)
self.interface.setposition()
self.iface.setposition()
def termcmdstring(self, sh: str) -> str:
raise CoreError("rj45 does not support terminal commands")

View file

@ -314,26 +314,22 @@ class Sdt:
:param node_data: node data being updated
:return: nothing
"""
logging.debug("sdt handle node update: %s - %s", node_data.id, node_data.name)
if not self.connect():
return
# delete node
node = node_data.node
logging.debug("sdt handle node update: %s - %s", node.id, node.name)
if node_data.message_type == MessageFlags.DELETE:
self.cmd(f"delete node,{node_data.id}")
self.cmd(f"delete node,{node.id}")
else:
x = node_data.x_position
y = node_data.y_position
lat = node_data.latitude
lon = node_data.longitude
alt = node_data.altitude
x, y, _ = node.position.get()
lon, lat, alt = node.position.get_geo()
if all([lat is not None, lon is not None, alt is not None]):
pos = f"pos {lon:.6f},{lat:.6f},{alt:.6f}"
self.cmd(f"node {node_data.id} {pos}")
self.cmd(f"node {node.id} {pos}")
elif node_data.message_type == 0:
lat, lon, alt = self.session.location.getgeo(x, y, 0)
pos = f"pos {lon:.6f},{lat:.6f},{alt:.6f}"
self.cmd(f"node {node_data.id} {pos}")
self.cmd(f"node {node.id} {pos}")
def wireless_net_check(self, node_id: int) -> bool:
"""

View file

@ -35,10 +35,8 @@ class Bird(CoreService):
"""
Helper to return the first IPv4 address of a node as its router ID.
"""
for ifc in node.netifs():
if hasattr(ifc, "control") and ifc.control is True:
continue
for a in ifc.addrlist:
for iface in node.get_ifaces(control=False):
for a in iface.addrlist:
a = a.split("/")[0]
if netaddr.valid_ipv4(a):
return a
@ -84,7 +82,7 @@ protocol device {
for s in node.services:
if cls.name not in s.dependencies:
continue
cfg += s.generatebirdconfig(node)
cfg += s.generate_bird_config(node)
return cfg
@ -106,11 +104,11 @@ class BirdService(CoreService):
meta = "The config file for this service can be found in the bird service."
@classmethod
def generatebirdconfig(cls, node):
def generate_bird_config(cls, node):
return ""
@classmethod
def generatebirdifcconfig(cls, node):
def generate_bird_iface_config(cls, node):
"""
Use only bare interfaces descriptions in generated protocol
configurations. This has the slight advantage of being the same
@ -118,10 +116,8 @@ class BirdService(CoreService):
"""
cfg = ""
for ifc in node.netifs():
if hasattr(ifc, "control") and ifc.control is True:
continue
cfg += ' interface "%s";\n' % ifc.name
for iface in node.get_ifaces(control=False):
cfg += ' interface "%s";\n' % iface.name
return cfg
@ -135,7 +131,7 @@ class BirdBgp(BirdService):
custom_needed = True
@classmethod
def generatebirdconfig(cls, node):
def generate_bird_config(cls, node):
return """
/* This is a sample config that should be customized with appropriate AS numbers
* and peers; add one section like this for each neighbor */
@ -165,7 +161,7 @@ class BirdOspf(BirdService):
name = "BIRD_OSPFv2"
@classmethod
def generatebirdconfig(cls, node):
def generate_bird_config(cls, node):
cfg = "protocol ospf {\n"
cfg += " export filter {\n"
cfg += " if source = RTS_BGP then {\n"
@ -175,7 +171,7 @@ class BirdOspf(BirdService):
cfg += " accept;\n"
cfg += " };\n"
cfg += " area 0.0.0.0 {\n"
cfg += cls.generatebirdifcconfig(node)
cfg += cls.generate_bird_iface_config(node)
cfg += " };\n"
cfg += "}\n\n"
@ -190,12 +186,12 @@ class BirdRadv(BirdService):
name = "BIRD_RADV"
@classmethod
def generatebirdconfig(cls, node):
def generate_bird_config(cls, node):
cfg = "/* This is a sample config that must be customized */\n"
cfg += "protocol radv {\n"
cfg += " # auto configuration on all interfaces\n"
cfg += cls.generatebirdifcconfig(node)
cfg += cls.generate_bird_iface_config(node)
cfg += " # Advertise DNS\n"
cfg += " rdnss {\n"
cfg += "# lifetime mult 10;\n"
@ -218,11 +214,11 @@ class BirdRip(BirdService):
name = "BIRD_RIP"
@classmethod
def generatebirdconfig(cls, node):
def generate_bird_config(cls, node):
cfg = "protocol rip {\n"
cfg += " period 10;\n"
cfg += " garbage time 60;\n"
cfg += cls.generatebirdifcconfig(node)
cfg += cls.generate_bird_iface_config(node)
cfg += " honor neighbor;\n"
cfg += " authentication none;\n"
cfg += " import all;\n"
@ -241,7 +237,7 @@ class BirdStatic(BirdService):
custom_needed = True
@classmethod
def generatebirdconfig(cls, node):
def generate_bird_config(cls, node):
cfg = "/* This is a sample config that must be customized */\n"
cfg += "protocol static {\n"
cfg += "# route 0.0.0.0/0 via 198.51.100.130; # Default route. Do NOT advertise on BGP !\n"

View file

@ -20,14 +20,14 @@ class EmaneTransportService(CoreService):
def generate_config(cls, node, filename):
if filename == cls.configs[0]:
transport_commands = []
for interface in node.netifs(sort=True):
for iface in node.get_ifaces():
try:
network_node = node.session.get_node(interface.net.id, EmaneNet)
network_node = node.session.get_node(iface.net.id, EmaneNet)
config = node.session.emane.get_configs(
network_node.id, network_node.model.name
)
if config and emanexml.is_external(config):
nem_id = network_node.getnemid(interface)
nem_id = network_node.getnemid(iface)
command = (
"emanetransportd -r -l 0 -d ../transportdaemon%s.xml"
% nem_id

View file

@ -59,12 +59,12 @@ class FRRZebra(CoreService):
"""
# we could verify here that filename == frr.conf
cfg = ""
for ifc in node.netifs():
cfg += "interface %s\n" % ifc.name
for iface in node.get_ifaces():
cfg += "interface %s\n" % iface.name
# include control interfaces in addressing but not routing daemons
if hasattr(ifc, "control") and ifc.control is True:
if hasattr(iface, "control") and iface.control is True:
cfg += " "
cfg += "\n ".join(map(cls.addrstr, ifc.addrlist))
cfg += "\n ".join(map(cls.addrstr, iface.addrlist))
cfg += "\n"
continue
cfgv4 = ""
@ -74,18 +74,18 @@ class FRRZebra(CoreService):
for s in node.services:
if cls.name not in s.dependencies:
continue
ifccfg = s.generatefrrifcconfig(node, ifc)
iface_config = s.generate_frr_iface_config(node, iface)
if s.ipv4_routing:
want_ipv4 = True
if s.ipv6_routing:
want_ipv6 = True
cfgv6 += ifccfg
cfgv6 += iface_config
else:
cfgv4 += ifccfg
cfgv4 += iface_config
if want_ipv4:
ipv4list = filter(
lambda x: netaddr.valid_ipv4(x.split("/")[0]), ifc.addrlist
lambda x: netaddr.valid_ipv4(x.split("/")[0]), iface.addrlist
)
cfg += " "
cfg += "\n ".join(map(cls.addrstr, ipv4list))
@ -93,7 +93,7 @@ class FRRZebra(CoreService):
cfg += cfgv4
if want_ipv6:
ipv6list = filter(
lambda x: netaddr.valid_ipv6(x.split("/")[0]), ifc.addrlist
lambda x: netaddr.valid_ipv6(x.split("/")[0]), iface.addrlist
)
cfg += " "
cfg += "\n ".join(map(cls.addrstr, ipv6list))
@ -104,7 +104,7 @@ class FRRZebra(CoreService):
for s in node.services:
if cls.name not in s.dependencies:
continue
cfg += s.generatefrrconfig(node)
cfg += s.generate_frr_config(node)
return cfg
@staticmethod
@ -237,10 +237,10 @@ bootfrr
frr_bin_search,
constants.FRR_STATE_DIR,
)
for ifc in node.netifs():
cfg += f"ip link set dev {ifc.name} down\n"
for iface in node.get_ifaces():
cfg += f"ip link set dev {iface.name} down\n"
cfg += "sleep 1\n"
cfg += f"ip link set dev {ifc.name} up\n"
cfg += f"ip link set dev {iface.name} up\n"
return cfg
@classmethod
@ -334,10 +334,8 @@ class FrrService(CoreService):
"""
Helper to return the first IPv4 address of a node as its router ID.
"""
for ifc in node.netifs():
if hasattr(ifc, "control") and ifc.control is True:
continue
for a in ifc.addrlist:
for iface in node.get_ifaces(control=False):
for a in iface.addrlist:
a = a.split("/")[0]
if netaddr.valid_ipv4(a):
return a
@ -345,16 +343,16 @@ class FrrService(CoreService):
return "0.0.0.0"
@staticmethod
def rj45check(ifc):
def rj45check(iface):
"""
Helper to detect whether interface is connected an external RJ45
link.
"""
if ifc.net:
for peerifc in ifc.net.netifs():
if peerifc == ifc:
if iface.net:
for peer_iface in iface.net.get_ifaces():
if peer_iface == iface:
continue
if isinstance(peerifc.node, Rj45Node):
if isinstance(peer_iface.node, Rj45Node):
return True
return False
@ -363,11 +361,11 @@ class FrrService(CoreService):
return ""
@classmethod
def generatefrrifcconfig(cls, node, ifc):
def generate_frr_iface_config(cls, node, iface):
return ""
@classmethod
def generatefrrconfig(cls, node):
def generate_frr_config(cls, node):
return ""
@ -385,43 +383,41 @@ class FRROspfv2(FrrService):
ipv4_routing = True
@staticmethod
def mtucheck(ifc):
def mtucheck(iface):
"""
Helper to detect MTU mismatch and add the appropriate OSPF
mtu-ignore command. This is needed when e.g. a node is linked via a
GreTap device.
"""
if ifc.mtu != 1500:
if iface.mtu != 1500:
# a workaround for PhysicalNode GreTap, which has no knowledge of
# the other nodes/nets
return " ip ospf mtu-ignore\n"
if not ifc.net:
if not iface.net:
return ""
for i in ifc.net.netifs():
if i.mtu != ifc.mtu:
for iface in iface.net.get_ifaces():
if iface.mtu != iface.mtu:
return " ip ospf mtu-ignore\n"
return ""
@staticmethod
def ptpcheck(ifc):
def ptpcheck(iface):
"""
Helper to detect whether interface is connected to a notional
point-to-point link.
"""
if isinstance(ifc.net, PtpNet):
if isinstance(iface.net, PtpNet):
return " ip ospf network point-to-point\n"
return ""
@classmethod
def generatefrrconfig(cls, node):
def generate_frr_config(cls, node):
cfg = "router ospf\n"
rtrid = cls.routerid(node)
cfg += " router-id %s\n" % rtrid
# network 10.0.0.0/24 area 0
for ifc in node.netifs():
if hasattr(ifc, "control") and ifc.control is True:
continue
for a in ifc.addrlist:
for iface in node.get_ifaces(control=False):
for a in iface.addrlist:
addr = a.split("/")[0]
if not netaddr.valid_ipv4(addr):
continue
@ -430,8 +426,8 @@ class FRROspfv2(FrrService):
return cfg
@classmethod
def generatefrrifcconfig(cls, node, ifc):
return cls.mtucheck(ifc)
def generate_frr_iface_config(cls, node, iface):
return cls.mtucheck(iface)
class FRROspfv3(FrrService):
@ -449,57 +445,55 @@ class FRROspfv3(FrrService):
ipv6_routing = True
@staticmethod
def minmtu(ifc):
def minmtu(iface):
"""
Helper to discover the minimum MTU of interfaces linked with the
given interface.
"""
mtu = ifc.mtu
if not ifc.net:
mtu = iface.mtu
if not iface.net:
return mtu
for i in ifc.net.netifs():
if i.mtu < mtu:
mtu = i.mtu
for iface in iface.net.get_ifaces():
if iface.mtu < mtu:
mtu = iface.mtu
return mtu
@classmethod
def mtucheck(cls, ifc):
def mtucheck(cls, iface):
"""
Helper to detect MTU mismatch and add the appropriate OSPFv3
ifmtu command. This is needed when e.g. a node is linked via a
GreTap device.
"""
minmtu = cls.minmtu(ifc)
if minmtu < ifc.mtu:
minmtu = cls.minmtu(iface)
if minmtu < iface.mtu:
return " ipv6 ospf6 ifmtu %d\n" % minmtu
else:
return ""
@staticmethod
def ptpcheck(ifc):
def ptpcheck(iface):
"""
Helper to detect whether interface is connected to a notional
point-to-point link.
"""
if isinstance(ifc.net, PtpNet):
if isinstance(iface.net, PtpNet):
return " ipv6 ospf6 network point-to-point\n"
return ""
@classmethod
def generatefrrconfig(cls, node):
def generate_frr_config(cls, node):
cfg = "router ospf6\n"
rtrid = cls.routerid(node)
cfg += " router-id %s\n" % rtrid
for ifc in node.netifs():
if hasattr(ifc, "control") and ifc.control is True:
continue
cfg += " interface %s area 0.0.0.0\n" % ifc.name
for iface in node.get_ifaces(control=False):
cfg += " interface %s area 0.0.0.0\n" % iface.name
cfg += "!\n"
return cfg
@classmethod
def generatefrrifcconfig(cls, node, ifc):
return cls.mtucheck(ifc)
def generate_frr_iface_config(cls, node, iface):
return cls.mtucheck(iface)
# cfg = cls.mtucheck(ifc)
# external RJ45 connections will use default OSPF timers
# if cls.rj45check(ifc):
@ -531,7 +525,7 @@ class FRRBgp(FrrService):
ipv6_routing = True
@classmethod
def generatefrrconfig(cls, node):
def generate_frr_config(cls, node):
cfg = "!\n! BGP configuration\n!\n"
cfg += "! You should configure the AS number below,\n"
cfg += "! along with this router's peers.\n!\n"
@ -555,7 +549,7 @@ class FRRRip(FrrService):
ipv4_routing = True
@classmethod
def generatefrrconfig(cls, node):
def generate_frr_config(cls, node):
cfg = """\
router rip
redistribute static
@ -579,7 +573,7 @@ class FRRRipng(FrrService):
ipv6_routing = True
@classmethod
def generatefrrconfig(cls, node):
def generate_frr_config(cls, node):
cfg = """\
router ripng
redistribute static
@ -604,18 +598,16 @@ class FRRBabel(FrrService):
ipv6_routing = True
@classmethod
def generatefrrconfig(cls, node):
def generate_frr_config(cls, node):
cfg = "router babel\n"
for ifc in node.netifs():
if hasattr(ifc, "control") and ifc.control is True:
continue
cfg += " network %s\n" % ifc.name
for iface in node.get_ifaces(control=False):
cfg += " network %s\n" % iface.name
cfg += " redistribute static\n redistribute ipv4 connected\n"
return cfg
@classmethod
def generatefrrifcconfig(cls, node, ifc):
if ifc.net and isinstance(ifc.net, (EmaneNet, WlanNode)):
def generate_frr_iface_config(cls, node, iface):
if iface.net and isinstance(iface.net, (EmaneNet, WlanNode)):
return " babel wireless\n no babel split-horizon\n"
else:
return " babel wired\n babel split-horizon\n"
@ -633,11 +625,11 @@ class FRRpimd(FrrService):
ipv4_routing = True
@classmethod
def generatefrrconfig(cls, node):
def generate_frr_config(cls, node):
ifname = "eth0"
for ifc in node.netifs():
if ifc.name != "lo":
ifname = ifc.name
for iface in node.get_ifaces():
if iface.name != "lo":
ifname = iface.name
break
cfg = "router mfea\n!\n"
cfg += "router igmp\n!\n"
@ -649,7 +641,7 @@ class FRRpimd(FrrService):
return cfg
@classmethod
def generatefrrifcconfig(cls, node, ifc):
def generate_frr_iface_config(cls, node, iface):
return " ip mfea\n ip igmp\n ip pim\n"
@ -668,17 +660,17 @@ class FRRIsis(FrrService):
ipv6_routing = True
@staticmethod
def ptpcheck(ifc):
def ptpcheck(iface):
"""
Helper to detect whether interface is connected to a notional
point-to-point link.
"""
if isinstance(ifc.net, PtpNet):
if isinstance(iface.net, PtpNet):
return " isis network point-to-point\n"
return ""
@classmethod
def generatefrrconfig(cls, node):
def generate_frr_config(cls, node):
cfg = "router isis DEFAULT\n"
cfg += " net 47.0001.0000.1900.%04x.00\n" % node.id
cfg += " metric-style wide\n"
@ -687,9 +679,9 @@ class FRRIsis(FrrService):
return cfg
@classmethod
def generatefrrifcconfig(cls, node, ifc):
def generate_frr_iface_config(cls, node, iface):
cfg = " ip router isis DEFAULT\n"
cfg += " ipv6 router isis DEFAULT\n"
cfg += " isis circuit-type level-2-only\n"
cfg += cls.ptpcheck(ifc)
cfg += cls.ptpcheck(iface)
return cfg

View file

@ -32,10 +32,8 @@ class NrlService(CoreService):
prefix of a node, using the supplied prefix length. This ignores the
interface's prefix length, so e.g. '/32' can turn into '/24'.
"""
for ifc in node.netifs():
if hasattr(ifc, "control") and ifc.control is True:
continue
for a in ifc.addrlist:
for iface in node.get_ifaces(control=False):
for a in iface.addrlist:
a = a.split("/")[0]
if netaddr.valid_ipv4(a):
return f"{a}/{prefixlen}"
@ -54,8 +52,8 @@ class MgenSinkService(NrlService):
@classmethod
def generate_config(cls, node, filename):
cfg = "0.0 LISTEN UDP 5000\n"
for ifc in node.netifs():
name = utils.sysctl_devname(ifc.name)
for iface in node.get_ifaces():
name = utils.sysctl_devname(iface.name)
cfg += "0.0 Join 224.225.1.2 INTERFACE %s\n" % name
return cfg
@ -91,11 +89,11 @@ class NrlNhdp(NrlService):
cmd += " -flooding ecds"
cmd += " -smfClient %s_smf" % node.name
netifs = list(filter(lambda x: not getattr(x, "control", False), node.netifs()))
if len(netifs) > 0:
interfacenames = map(lambda x: x.name, netifs)
ifaces = node.get_ifaces(control=False)
if len(ifaces) > 0:
iface_names = map(lambda x: x.name, ifaces)
cmd += " -i "
cmd += " -i ".join(interfacenames)
cmd += " -i ".join(iface_names)
return (cmd,)
@ -125,16 +123,16 @@ class NrlSmf(NrlService):
cmd = "nrlsmf instance %s_smf" % node.name
servicenames = map(lambda x: x.name, node.services)
netifs = list(filter(lambda x: not getattr(x, "control", False), node.netifs()))
if len(netifs) == 0:
ifaces = node.get_ifaces(control=False)
if len(ifaces) == 0:
return ""
if "arouted" in servicenames:
comments += "# arouted service is enabled\n"
cmd += " tap %s_tap" % (node.name,)
cmd += " unicast %s" % cls.firstipv4prefix(node, 24)
cmd += " push lo,%s resequence on" % netifs[0].name
if len(netifs) > 0:
cmd += " push lo,%s resequence on" % ifaces[0].name
if len(ifaces) > 0:
if "NHDP" in servicenames:
comments += "# NHDP service is enabled\n"
cmd += " ecds "
@ -143,8 +141,8 @@ class NrlSmf(NrlService):
cmd += " smpr "
else:
cmd += " cf "
interfacenames = map(lambda x: x.name, netifs)
cmd += ",".join(interfacenames)
iface_names = map(lambda x: x.name, ifaces)
cmd += ",".join(iface_names)
cmd += " hash MD5"
cmd += " log /var/log/nrlsmf.log"
@ -171,10 +169,10 @@ class NrlOlsr(NrlService):
"""
cmd = cls.startup[0]
# are multiple interfaces supported? No.
netifs = list(node.netifs())
if len(netifs) > 0:
ifc = netifs[0]
cmd += " -i %s" % ifc.name
ifaces = node.get_ifaces()
if len(ifaces) > 0:
iface = ifaces[0]
cmd += " -i %s" % iface.name
cmd += " -l /var/log/nrlolsrd.log"
cmd += " -rpipe %s_olsr" % node.name
@ -215,11 +213,11 @@ class NrlOlsrv2(NrlService):
cmd += " -p olsr"
netifs = list(filter(lambda x: not getattr(x, "control", False), node.netifs()))
if len(netifs) > 0:
interfacenames = map(lambda x: x.name, netifs)
ifaces = node.get_ifaces(control=False)
if len(ifaces) > 0:
iface_names = map(lambda x: x.name, ifaces)
cmd += " -i "
cmd += " -i ".join(interfacenames)
cmd += " -i ".join(iface_names)
return (cmd,)
@ -243,11 +241,11 @@ class OlsrOrg(NrlService):
Generate the appropriate command-line based on node interfaces.
"""
cmd = cls.startup[0]
netifs = list(filter(lambda x: not getattr(x, "control", False), node.netifs()))
if len(netifs) > 0:
interfacenames = map(lambda x: x.name, netifs)
ifaces = node.get_ifaces(control=False)
if len(ifaces) > 0:
iface_names = map(lambda x: x.name, ifaces)
cmd += " -i "
cmd += " -i ".join(interfacenames)
cmd += " -i ".join(iface_names)
return (cmd,)
@ -607,8 +605,8 @@ class MgenActor(NrlService):
comments = ""
cmd = "mgenBasicActor.py -n %s -a 0.0.0.0" % node.name
netifs = [x for x in node.netifs() if not getattr(x, "control", False)]
if len(netifs) == 0:
ifaces = node.get_ifaces(control=False)
if len(ifaces) == 0:
return ""
cfg += comments + cmd + " < /dev/null > /dev/null 2>&1 &\n\n"

View file

@ -56,12 +56,12 @@ class Zebra(CoreService):
"""
# we could verify here that filename == Quagga.conf
cfg = ""
for ifc in node.netifs():
cfg += "interface %s\n" % ifc.name
for iface in node.get_ifaces():
cfg += "interface %s\n" % iface.name
# include control interfaces in addressing but not routing daemons
if hasattr(ifc, "control") and ifc.control is True:
if hasattr(iface, "control") and iface.control is True:
cfg += " "
cfg += "\n ".join(map(cls.addrstr, ifc.addrlist))
cfg += "\n ".join(map(cls.addrstr, iface.addrlist))
cfg += "\n"
continue
cfgv4 = ""
@ -71,18 +71,18 @@ class Zebra(CoreService):
for s in node.services:
if cls.name not in s.dependencies:
continue
ifccfg = s.generatequaggaifcconfig(node, ifc)
iface_config = s.generate_quagga_iface_config(node, iface)
if s.ipv4_routing:
want_ipv4 = True
if s.ipv6_routing:
want_ipv6 = True
cfgv6 += ifccfg
cfgv6 += iface_config
else:
cfgv4 += ifccfg
cfgv4 += iface_config
if want_ipv4:
ipv4list = filter(
lambda x: netaddr.valid_ipv4(x.split("/")[0]), ifc.addrlist
lambda x: netaddr.valid_ipv4(x.split("/")[0]), iface.addrlist
)
cfg += " "
cfg += "\n ".join(map(cls.addrstr, ipv4list))
@ -90,7 +90,7 @@ class Zebra(CoreService):
cfg += cfgv4
if want_ipv6:
ipv6list = filter(
lambda x: netaddr.valid_ipv6(x.split("/")[0]), ifc.addrlist
lambda x: netaddr.valid_ipv6(x.split("/")[0]), iface.addrlist
)
cfg += " "
cfg += "\n ".join(map(cls.addrstr, ipv6list))
@ -101,7 +101,7 @@ class Zebra(CoreService):
for s in node.services:
if cls.name not in s.dependencies:
continue
cfg += s.generatequaggaconfig(node)
cfg += s.generate_quagga_config(node)
return cfg
@staticmethod
@ -252,10 +252,8 @@ class QuaggaService(CoreService):
"""
Helper to return the first IPv4 address of a node as its router ID.
"""
for ifc in node.netifs():
if hasattr(ifc, "control") and ifc.control is True:
continue
for a in ifc.addrlist:
for iface in node.get_ifaces(control=False):
for a in iface.addrlist:
a = a.split("/")[0]
if netaddr.valid_ipv4(a):
return a
@ -263,16 +261,16 @@ class QuaggaService(CoreService):
return "0.0.0.%d" % node.id
@staticmethod
def rj45check(ifc):
def rj45check(iface):
"""
Helper to detect whether interface is connected an external RJ45
link.
"""
if ifc.net:
for peerifc in ifc.net.netifs():
if peerifc == ifc:
if iface.net:
for peer_iface in iface.net.get_ifaces():
if peer_iface == iface:
continue
if isinstance(peerifc.node, Rj45Node):
if isinstance(peer_iface.node, Rj45Node):
return True
return False
@ -281,11 +279,11 @@ class QuaggaService(CoreService):
return ""
@classmethod
def generatequaggaifcconfig(cls, node, ifc):
def generate_quagga_iface_config(cls, node, iface):
return ""
@classmethod
def generatequaggaconfig(cls, node):
def generate_quagga_config(cls, node):
return ""
@ -303,43 +301,41 @@ class Ospfv2(QuaggaService):
ipv4_routing = True
@staticmethod
def mtucheck(ifc):
def mtucheck(iface):
"""
Helper to detect MTU mismatch and add the appropriate OSPF
mtu-ignore command. This is needed when e.g. a node is linked via a
GreTap device.
"""
if ifc.mtu != 1500:
if iface.mtu != 1500:
# a workaround for PhysicalNode GreTap, which has no knowledge of
# the other nodes/nets
return " ip ospf mtu-ignore\n"
if not ifc.net:
if not iface.net:
return ""
for i in ifc.net.netifs():
if i.mtu != ifc.mtu:
for iface in iface.net.get_ifaces():
if iface.mtu != iface.mtu:
return " ip ospf mtu-ignore\n"
return ""
@staticmethod
def ptpcheck(ifc):
def ptpcheck(iface):
"""
Helper to detect whether interface is connected to a notional
point-to-point link.
"""
if isinstance(ifc.net, PtpNet):
if isinstance(iface.net, PtpNet):
return " ip ospf network point-to-point\n"
return ""
@classmethod
def generatequaggaconfig(cls, node):
def generate_quagga_config(cls, node):
cfg = "router ospf\n"
rtrid = cls.routerid(node)
cfg += " router-id %s\n" % rtrid
# network 10.0.0.0/24 area 0
for ifc in node.netifs():
if hasattr(ifc, "control") and ifc.control is True:
continue
for a in ifc.addrlist:
for iface in node.get_ifaces(control=False):
for a in iface.addrlist:
addr = a.split("/")[0]
if netaddr.valid_ipv4(addr):
cfg += " network %s area 0\n" % a
@ -347,12 +343,12 @@ class Ospfv2(QuaggaService):
return cfg
@classmethod
def generatequaggaifcconfig(cls, node, ifc):
cfg = cls.mtucheck(ifc)
def generate_quagga_iface_config(cls, node, iface):
cfg = cls.mtucheck(iface)
# external RJ45 connections will use default OSPF timers
if cls.rj45check(ifc):
if cls.rj45check(iface):
return cfg
cfg += cls.ptpcheck(ifc)
cfg += cls.ptpcheck(iface)
return (
cfg
+ """\
@ -378,58 +374,56 @@ class Ospfv3(QuaggaService):
ipv6_routing = True
@staticmethod
def minmtu(ifc):
def minmtu(iface):
"""
Helper to discover the minimum MTU of interfaces linked with the
given interface.
"""
mtu = ifc.mtu
if not ifc.net:
mtu = iface.mtu
if not iface.net:
return mtu
for i in ifc.net.netifs():
if i.mtu < mtu:
mtu = i.mtu
for iface in iface.net.get_ifaces():
if iface.mtu < mtu:
mtu = iface.mtu
return mtu
@classmethod
def mtucheck(cls, ifc):
def mtucheck(cls, iface):
"""
Helper to detect MTU mismatch and add the appropriate OSPFv3
ifmtu command. This is needed when e.g. a node is linked via a
GreTap device.
"""
minmtu = cls.minmtu(ifc)
if minmtu < ifc.mtu:
minmtu = cls.minmtu(iface)
if minmtu < iface.mtu:
return " ipv6 ospf6 ifmtu %d\n" % minmtu
else:
return ""
@staticmethod
def ptpcheck(ifc):
def ptpcheck(iface):
"""
Helper to detect whether interface is connected to a notional
point-to-point link.
"""
if isinstance(ifc.net, PtpNet):
if isinstance(iface.net, PtpNet):
return " ipv6 ospf6 network point-to-point\n"
return ""
@classmethod
def generatequaggaconfig(cls, node):
def generate_quagga_config(cls, node):
cfg = "router ospf6\n"
rtrid = cls.routerid(node)
cfg += " instance-id 65\n"
cfg += " router-id %s\n" % rtrid
for ifc in node.netifs():
if hasattr(ifc, "control") and ifc.control is True:
continue
cfg += " interface %s area 0.0.0.0\n" % ifc.name
for iface in node.get_ifaces(control=False):
cfg += " interface %s area 0.0.0.0\n" % iface.name
cfg += "!\n"
return cfg
@classmethod
def generatequaggaifcconfig(cls, node, ifc):
return cls.mtucheck(ifc)
def generate_quagga_iface_config(cls, node, iface):
return cls.mtucheck(iface)
class Ospfv3mdr(Ospfv3):
@ -444,9 +438,9 @@ class Ospfv3mdr(Ospfv3):
ipv4_routing = True
@classmethod
def generatequaggaifcconfig(cls, node, ifc):
cfg = cls.mtucheck(ifc)
if ifc.net is not None and isinstance(ifc.net, (WlanNode, EmaneNet)):
def generate_quagga_iface_config(cls, node, iface):
cfg = cls.mtucheck(iface)
if iface.net is not None and isinstance(iface.net, (WlanNode, EmaneNet)):
return (
cfg
+ """\
@ -479,7 +473,7 @@ class Bgp(QuaggaService):
ipv6_routing = True
@classmethod
def generatequaggaconfig(cls, node):
def generate_quagga_config(cls, node):
cfg = "!\n! BGP configuration\n!\n"
cfg += "! You should configure the AS number below,\n"
cfg += "! along with this router's peers.\n!\n"
@ -503,7 +497,7 @@ class Rip(QuaggaService):
ipv4_routing = True
@classmethod
def generatequaggaconfig(cls, node):
def generate_quagga_config(cls, node):
cfg = """\
router rip
redistribute static
@ -527,7 +521,7 @@ class Ripng(QuaggaService):
ipv6_routing = True
@classmethod
def generatequaggaconfig(cls, node):
def generate_quagga_config(cls, node):
cfg = """\
router ripng
redistribute static
@ -552,18 +546,16 @@ class Babel(QuaggaService):
ipv6_routing = True
@classmethod
def generatequaggaconfig(cls, node):
def generate_quagga_config(cls, node):
cfg = "router babel\n"
for ifc in node.netifs():
if hasattr(ifc, "control") and ifc.control is True:
continue
cfg += " network %s\n" % ifc.name
for iface in node.get_ifaces(control=False):
cfg += " network %s\n" % iface.name
cfg += " redistribute static\n redistribute connected\n"
return cfg
@classmethod
def generatequaggaifcconfig(cls, node, ifc):
if ifc.net and ifc.net.linktype == LinkTypes.WIRELESS:
def generate_quagga_iface_config(cls, node, iface):
if iface.net and iface.net.linktype == LinkTypes.WIRELESS:
return " babel wireless\n no babel split-horizon\n"
else:
return " babel wired\n babel split-horizon\n"
@ -581,11 +573,11 @@ class Xpimd(QuaggaService):
ipv4_routing = True
@classmethod
def generatequaggaconfig(cls, node):
def generate_quagga_config(cls, node):
ifname = "eth0"
for ifc in node.netifs():
if ifc.name != "lo":
ifname = ifc.name
for iface in node.get_ifaces():
if iface.name != "lo":
ifname = iface.name
break
cfg = "router mfea\n!\n"
cfg += "router igmp\n!\n"
@ -597,5 +589,5 @@ class Xpimd(QuaggaService):
return cfg
@classmethod
def generatequaggaifcconfig(cls, node, ifc):
def generate_quagga_iface_config(cls, node, iface):
return " ip mfea\n ip igmp\n ip pim\n"

View file

@ -49,10 +49,8 @@ class OvsService(SdnService):
cfg += "\n## Now add all our interfaces as ports to the switch\n"
portnum = 1
for ifc in node.netifs():
if hasattr(ifc, "control") and ifc.control is True:
continue
ifnumstr = re.findall(r"\d+", ifc.name)
for iface in node.get_ifaces(control=False):
ifnumstr = re.findall(r"\d+", iface.name)
ifnum = ifnumstr[0]
# create virtual interfaces
@ -61,18 +59,18 @@ class OvsService(SdnService):
# remove ip address of eths because quagga/zebra will assign same IPs to rtr interfaces
# or assign them manually to rtr interfaces if zebra is not running
for ifcaddr in ifc.addrlist:
addr = ifcaddr.split("/")[0]
for addr in iface.addrlist:
addr = addr.split("/")[0]
if netaddr.valid_ipv4(addr):
cfg += "ip addr del %s dev %s\n" % (ifcaddr, ifc.name)
cfg += "ip addr del %s dev %s\n" % (addr, iface.name)
if has_zebra == 0:
cfg += "ip addr add %s dev rtr%s\n" % (ifcaddr, ifnum)
cfg += "ip addr add %s dev rtr%s\n" % (addr, ifnum)
elif netaddr.valid_ipv6(addr):
cfg += "ip -6 addr del %s dev %s\n" % (ifcaddr, ifc.name)
cfg += "ip -6 addr del %s dev %s\n" % (addr, iface.name)
if has_zebra == 0:
cfg += "ip -6 addr add %s dev rtr%s\n" % (ifcaddr, ifnum)
cfg += "ip -6 addr add %s dev rtr%s\n" % (addr, ifnum)
else:
raise ValueError("invalid address: %s" % ifcaddr)
raise ValueError("invalid address: %s" % addr)
# add interfaces to bridge
# Make port numbers explicit so they're easier to follow in reading the script
@ -102,9 +100,7 @@ class OvsService(SdnService):
cfg += "## if the above controller will be present then you probably want to delete them\n"
# Setup default flows
portnum = 1
for ifc in node.netifs():
if hasattr(ifc, "control") and ifc.control is True:
continue
for iface in node.get_ifaces(control=False):
cfg += "## Take the data from the CORE interface and put it on the veth and vice versa\n"
cfg += (
"ovs-ofctl add-flow ovsbr0 priority=1000,in_port=%d,action=output:%d\n"

View file

@ -131,18 +131,18 @@ class Nat(CoreService):
custom_needed = False
@classmethod
def generateifcnatrule(cls, ifc, line_prefix=""):
def generate_iface_nat_rule(cls, iface, line_prefix=""):
"""
Generate a NAT line for one interface.
"""
cfg = line_prefix + "iptables -t nat -A POSTROUTING -o "
cfg += ifc.name + " -j MASQUERADE\n"
cfg += iface.name + " -j MASQUERADE\n"
cfg += line_prefix + "iptables -A FORWARD -i " + ifc.name
cfg += line_prefix + "iptables -A FORWARD -i " + iface.name
cfg += " -m state --state RELATED,ESTABLISHED -j ACCEPT\n"
cfg += line_prefix + "iptables -A FORWARD -i "
cfg += ifc.name + " -j DROP\n"
cfg += iface.name + " -j DROP\n"
return cfg
@classmethod
@ -154,14 +154,12 @@ class Nat(CoreService):
cfg += "# generated by security.py\n"
cfg += "# NAT out the first interface by default\n"
have_nat = False
for ifc in node.netifs():
if hasattr(ifc, "control") and ifc.control is True:
continue
for iface in node.get_ifaces(control=False):
if have_nat:
cfg += cls.generateifcnatrule(ifc, line_prefix="#")
cfg += cls.generate_iface_nat_rule(iface, line_prefix="#")
else:
have_nat = True
cfg += "# NAT out the " + ifc.name + " interface\n"
cfg += cls.generateifcnatrule(ifc)
cfg += "# NAT out the " + iface.name + " interface\n"
cfg += cls.generate_iface_nat_rule(iface)
cfg += "\n"
return cfg

View file

@ -55,8 +55,8 @@ class IPForwardService(UtilService):
""" % {
"sysctl": constants.SYSCTL_BIN
}
for ifc in node.netifs():
name = utils.sysctl_devname(ifc.name)
for iface in node.get_ifaces():
name = utils.sysctl_devname(iface.name)
cfg += "%s -w net.ipv4.conf.%s.forwarding=1\n" % (
constants.SYSCTL_BIN,
name,
@ -77,10 +77,10 @@ class DefaultRouteService(UtilService):
@classmethod
def generate_config(cls, node, filename):
routes = []
netifs = node.netifs(sort=True)
if netifs:
netif = netifs[0]
for x in netif.addrlist:
ifaces = node.get_ifaces()
if ifaces:
iface = ifaces[0]
for x in iface.addrlist:
net = netaddr.IPNetwork(x).cidr
if net.size > 1:
router = net[1]
@ -104,14 +104,12 @@ class DefaultMulticastRouteService(UtilService):
cfg += "# the first interface is chosen below; please change it "
cfg += "as needed\n"
for ifc in node.netifs():
if hasattr(ifc, "control") and ifc.control is True:
continue
for iface in node.get_ifaces(control=False):
if os.uname()[0] == "Linux":
rtcmd = "ip route add 224.0.0.0/4 dev"
else:
raise Exception("unknown platform")
cfg += "%s %s\n" % (rtcmd, ifc.name)
cfg += "%s %s\n" % (rtcmd, iface.name)
cfg += "\n"
break
return cfg
@ -129,10 +127,8 @@ class StaticRouteService(UtilService):
cfg += "# auto-generated by StaticRoute service (utility.py)\n#\n"
cfg += "# NOTE: this service must be customized to be of any use\n"
cfg += "# Below are samples that you can uncomment and edit.\n#\n"
for ifc in node.netifs():
if hasattr(ifc, "control") and ifc.control is True:
continue
cfg += "\n".join(map(cls.routestr, ifc.addrlist))
for iface in node.get_ifaces(control=False):
cfg += "\n".join(map(cls.routestr, iface.addrlist))
cfg += "\n"
return cfg
@ -259,10 +255,8 @@ max-lease-time 7200;
ddns-update-style none;
"""
for ifc in node.netifs():
if hasattr(ifc, "control") and ifc.control is True:
continue
cfg += "\n".join(map(cls.subnetentry, ifc.addrlist))
for iface in node.get_ifaces(control=False):
cfg += "\n".join(map(cls.subnetentry, iface.addrlist))
cfg += "\n"
return cfg
@ -320,13 +314,11 @@ class DhcpClientService(UtilService):
cfg += "side DNS\n# resolution based on the DHCP server response.\n"
cfg += "#mkdir -p /var/run/resolvconf/interface\n"
for ifc in node.netifs():
if hasattr(ifc, "control") and ifc.control is True:
continue
cfg += "#ln -s /var/run/resolvconf/interface/%s.dhclient" % ifc.name
for iface in node.get_ifaces(control=False):
cfg += "#ln -s /var/run/resolvconf/interface/%s.dhclient" % iface.name
cfg += " /var/run/resolvconf/resolv.conf\n"
cfg += "/sbin/dhclient -nw -pf /var/run/dhclient-%s.pid" % ifc.name
cfg += " -lf /var/run/dhclient-%s.lease %s\n" % (ifc.name, ifc.name)
cfg += "/sbin/dhclient -nw -pf /var/run/dhclient-%s.pid" % iface.name
cfg += " -lf /var/run/dhclient-%s.lease %s\n" % (iface.name, iface.name)
return cfg
@ -585,10 +577,8 @@ export LANG
"""
% node.name
)
for ifc in node.netifs():
if hasattr(ifc, "control") and ifc.control is True:
continue
body += "<li>%s - %s</li>\n" % (ifc.name, ifc.addrlist)
for iface in node.get_ifaces(control=False):
body += "<li>%s - %s</li>\n" % (iface.name, iface.addrlist)
return "<html><body>%s</body></html>" % body
@ -619,14 +609,14 @@ DUMPOPTS="-s 12288 -C 10 -n"
if [ "x$1" = "xstart" ]; then
"""
for ifc in node.netifs():
if hasattr(ifc, "control") and ifc.control is True:
for iface in node.get_ifaces():
if hasattr(iface, "control") and iface.control is True:
cfg += "# "
redir = "< /dev/null"
cfg += "tcpdump ${DUMPOPTS} -w %s.%s.pcap -i %s %s &\n" % (
node.name,
ifc.name,
ifc.name,
iface.name,
iface.name,
redir,
)
cfg += """
@ -654,10 +644,8 @@ class RadvdService(UtilService):
using the network address of each interface.
"""
cfg = "# auto-generated by RADVD service (utility.py)\n"
for ifc in node.netifs():
if hasattr(ifc, "control") and ifc.control is True:
continue
prefixes = list(map(cls.subnetentry, ifc.addrlist))
for iface in node.get_ifaces(control=False):
prefixes = list(map(cls.subnetentry, iface.addrlist))
if len(prefixes) < 1:
continue
cfg += (
@ -670,7 +658,7 @@ interface %s
AdvDefaultPreference low;
AdvHomeAgentFlag off;
"""
% ifc.name
% iface.name
)
for prefix in prefixes:
if prefix == "":

View file

@ -35,11 +35,11 @@ class XorpRtrmgr(CoreService):
invoked here. Filename currently ignored.
"""
cfg = "interfaces {\n"
for ifc in node.netifs():
cfg += " interface %s {\n" % ifc.name
cfg += "\tvif %s {\n" % ifc.name
cfg += "".join(map(cls.addrstr, ifc.addrlist))
cfg += cls.lladdrstr(ifc)
for iface in node.get_ifaces():
cfg += " interface %s {\n" % iface.name
cfg += "\tvif %s {\n" % iface.name
cfg += "".join(map(cls.addrstr, iface.addrlist))
cfg += cls.lladdrstr(iface)
cfg += "\t}\n"
cfg += " }\n"
cfg += "}\n\n"
@ -65,11 +65,11 @@ class XorpRtrmgr(CoreService):
return cfg
@staticmethod
def lladdrstr(ifc):
def lladdrstr(iface):
"""
helper for adding link-local address entries (required by OSPFv3)
"""
cfg = "\t address %s {\n" % ifc.hwaddr.tolinklocal()
cfg = "\t address %s {\n" % netaddr.EUI(iface.mac).eui64()
cfg += "\t\tprefix-length: 64\n"
cfg += "\t }\n"
return cfg
@ -104,15 +104,15 @@ class XorpService(CoreService):
return cfg
@staticmethod
def mfea(forwarding, ifcs):
def mfea(forwarding, ifaces):
"""
Helper to add a multicast forwarding engine entry to the config file.
"""
names = []
for ifc in ifcs:
if hasattr(ifc, "control") and ifc.control is True:
for iface in ifaces:
if hasattr(iface, "control") and iface.control is True:
continue
names.append(ifc.name)
names.append(iface.name)
names.append("register_vif")
cfg = "plumbing {\n"
@ -148,10 +148,8 @@ class XorpService(CoreService):
"""
Helper to return the first IPv4 address of a node as its router ID.
"""
for ifc in node.netifs():
if hasattr(ifc, "control") and ifc.control is True:
continue
for a in ifc.addrlist:
for iface in node.get_ifaces(control=False):
for a in iface.addrlist:
a = a.split("/")[0]
if netaddr.valid_ipv4(a):
return a
@ -184,12 +182,10 @@ class XorpOspfv2(XorpService):
cfg += " ospf4 {\n"
cfg += "\trouter-id: %s\n" % rtrid
cfg += "\tarea 0.0.0.0 {\n"
for ifc in node.netifs():
if hasattr(ifc, "control") and ifc.control is True:
continue
cfg += "\t interface %s {\n" % ifc.name
cfg += "\t\tvif %s {\n" % ifc.name
for a in ifc.addrlist:
for iface in node.get_ifaces(control=False):
cfg += "\t interface %s {\n" % iface.name
cfg += "\t\tvif %s {\n" % iface.name
for a in iface.addrlist:
addr = a.split("/")[0]
if not netaddr.valid_ipv4(addr):
continue
@ -220,11 +216,9 @@ class XorpOspfv3(XorpService):
cfg += " ospf6 0 { /* Instance ID 0 */\n"
cfg += "\trouter-id: %s\n" % rtrid
cfg += "\tarea 0.0.0.0 {\n"
for ifc in node.netifs():
if hasattr(ifc, "control") and ifc.control is True:
continue
cfg += "\t interface %s {\n" % ifc.name
cfg += "\t\tvif %s {\n" % ifc.name
for iface in node.get_ifaces(control=False):
cfg += "\t interface %s {\n" % iface.name
cfg += "\t\tvif %s {\n" % iface.name
cfg += "\t\t}\n"
cfg += "\t }\n"
cfg += "\t}\n"
@ -277,12 +271,10 @@ class XorpRip(XorpService):
cfg += "\nprotocols {\n"
cfg += " rip {\n"
cfg += '\texport: "export-connected"\n'
for ifc in node.netifs():
if hasattr(ifc, "control") and ifc.control is True:
continue
cfg += "\tinterface %s {\n" % ifc.name
cfg += "\t vif %s {\n" % ifc.name
for a in ifc.addrlist:
for iface in node.get_ifaces(control=False):
cfg += "\tinterface %s {\n" % iface.name
cfg += "\t vif %s {\n" % iface.name
for a in iface.addrlist:
addr = a.split("/")[0]
if not netaddr.valid_ipv4(addr):
continue
@ -310,12 +302,10 @@ class XorpRipng(XorpService):
cfg += "\nprotocols {\n"
cfg += " ripng {\n"
cfg += '\texport: "export-connected"\n'
for ifc in node.netifs():
if hasattr(ifc, "control") and ifc.control is True:
continue
cfg += "\tinterface %s {\n" % ifc.name
cfg += "\t vif %s {\n" % ifc.name
cfg += "\t\taddress %s {\n" % ifc.hwaddr.tolinklocal()
for iface in node.get_ifaces(control=False):
cfg += "\tinterface %s {\n" % iface.name
cfg += "\t vif %s {\n" % iface.name
cfg += "\t\taddress %s {\n" % netaddr.EUI(iface.mac).eui64()
cfg += "\t\t disable: false\n"
cfg += "\t\t}\n"
cfg += "\t }\n"
@ -334,17 +324,15 @@ class XorpPimSm4(XorpService):
@classmethod
def generatexorpconfig(cls, node):
cfg = cls.mfea("mfea4", node.netifs())
cfg = cls.mfea("mfea4", node.get_ifaces())
cfg += "\nprotocols {\n"
cfg += " igmp {\n"
names = []
for ifc in node.netifs():
if hasattr(ifc, "control") and ifc.control is True:
continue
names.append(ifc.name)
cfg += "\tinterface %s {\n" % ifc.name
cfg += "\t vif %s {\n" % ifc.name
for iface in node.get_ifaces(control=False):
names.append(iface.name)
cfg += "\tinterface %s {\n" % iface.name
cfg += "\t vif %s {\n" % iface.name
cfg += "\t\tdisable: false\n"
cfg += "\t }\n"
cfg += "\t}\n"
@ -394,17 +382,15 @@ class XorpPimSm6(XorpService):
@classmethod
def generatexorpconfig(cls, node):
cfg = cls.mfea("mfea6", node.netifs())
cfg = cls.mfea("mfea6", node.get_ifaces())
cfg += "\nprotocols {\n"
cfg += " mld {\n"
names = []
for ifc in node.netifs():
if hasattr(ifc, "control") and ifc.control is True:
continue
names.append(ifc.name)
cfg += "\tinterface %s {\n" % ifc.name
cfg += "\t vif %s {\n" % ifc.name
for iface in node.get_ifaces(control=False):
names.append(iface.name)
cfg += "\tinterface %s {\n" % iface.name
cfg += "\t vif %s {\n" % iface.name
cfg += "\t\tdisable: false\n"
cfg += "\t }\n"
cfg += "\t}\n"
@ -459,12 +445,10 @@ class XorpOlsr(XorpService):
cfg += "\nprotocols {\n"
cfg += " olsr4 {\n"
cfg += "\tmain-address: %s\n" % rtrid
for ifc in node.netifs():
if hasattr(ifc, "control") and ifc.control is True:
continue
cfg += "\tinterface %s {\n" % ifc.name
cfg += "\t vif %s {\n" % ifc.name
for a in ifc.addrlist:
for iface in node.get_ifaces(control=False):
cfg += "\tinterface %s {\n" % iface.name
cfg += "\t vif %s {\n" % iface.name
for a in iface.addrlist:
addr = a.split("/")[0]
if not netaddr.valid_ipv4(addr):
continue

View file

@ -6,8 +6,7 @@ from lxml import etree
import core.nodes.base
import core.nodes.physical
from core.emane.nodes import EmaneNet
from core.emulator.data import LinkData
from core.emulator.emudata import InterfaceData, LinkOptions, NodeOptions
from core.emulator.data import InterfaceData, LinkData, LinkOptions, NodeOptions
from core.emulator.enumerations import EventTypes, NodeTypes
from core.errors import CoreXmlError
from core.nodes.base import CoreNodeBase, NodeBase
@ -58,16 +57,16 @@ def add_attribute(element: etree.Element, name: str, value: Any) -> None:
element.set(name, str(value))
def create_interface_data(interface_element: etree.Element) -> InterfaceData:
interface_id = int(interface_element.get("id"))
name = interface_element.get("name")
mac = interface_element.get("mac")
ip4 = interface_element.get("ip4")
ip4_mask = get_int(interface_element, "ip4_mask")
ip6 = interface_element.get("ip6")
ip6_mask = get_int(interface_element, "ip6_mask")
def create_iface_data(iface_element: etree.Element) -> InterfaceData:
iface_id = int(iface_element.get("id"))
name = iface_element.get("name")
mac = iface_element.get("mac")
ip4 = iface_element.get("ip4")
ip4_mask = get_int(iface_element, "ip4_mask")
ip6 = iface_element.get("ip6")
ip6_mask = get_int(iface_element, "ip6_mask")
return InterfaceData(
id=interface_id,
id=iface_id,
name=name,
mac=mac,
ip4=ip4,
@ -482,12 +481,10 @@ class CoreXmlWriter:
# add link data
for link_data in links:
# skip basic range links
if link_data.interface1_id is None and link_data.interface2_id is None:
if link_data.iface1 is None and link_data.iface2 is None:
continue
link_element = self.create_link_element(link_data)
link_elements.append(link_element)
if link_elements.getchildren():
self.scenario.append(link_elements)
@ -495,37 +492,25 @@ class CoreXmlWriter:
device = DeviceElement(self.session, node)
self.devices.append(device.element)
def create_interface_element(
self,
element_name: str,
node_id: int,
interface_id: int,
mac: str,
ip4: str,
ip4_mask: int,
ip6: str,
ip6_mask: int,
def create_iface_element(
self, element_name: str, node_id: int, iface_data: InterfaceData
) -> etree.Element:
interface = etree.Element(element_name)
iface_element = etree.Element(element_name)
node = self.session.get_node(node_id, NodeBase)
interface_name = None
if isinstance(node, CoreNodeBase):
node_interface = node.netif(interface_id)
interface_name = node_interface.name
iface = node.get_iface(iface_data.id)
# check if emane interface
if isinstance(node_interface.net, EmaneNet):
nem = node_interface.net.getnemid(node_interface)
add_attribute(interface, "nem", nem)
add_attribute(interface, "id", interface_id)
add_attribute(interface, "name", interface_name)
add_attribute(interface, "mac", mac)
add_attribute(interface, "ip4", ip4)
add_attribute(interface, "ip4_mask", ip4_mask)
add_attribute(interface, "ip6", ip6)
add_attribute(interface, "ip6_mask", ip6_mask)
return interface
if isinstance(iface.net, EmaneNet):
nem = iface.net.getnemid(iface)
add_attribute(iface_element, "nem", nem)
add_attribute(iface_element, "id", iface_data.id)
add_attribute(iface_element, "name", iface_data.name)
add_attribute(iface_element, "mac", iface_data.mac)
add_attribute(iface_element, "ip4", iface_data.ip4)
add_attribute(iface_element, "ip4_mask", iface_data.ip4_mask)
add_attribute(iface_element, "ip6", iface_data.ip6)
add_attribute(iface_element, "ip6_mask", iface_data.ip6_mask)
return iface_element
def create_link_element(self, link_data: LinkData) -> etree.Element:
link_element = etree.Element("link")
@ -533,32 +518,18 @@ class CoreXmlWriter:
add_attribute(link_element, "node2", link_data.node2_id)
# check for interface one
if link_data.interface1_id is not None:
interface1 = self.create_interface_element(
"interface1",
link_data.node1_id,
link_data.interface1_id,
link_data.interface1_mac,
link_data.interface1_ip4,
link_data.interface1_ip4_mask,
link_data.interface1_ip6,
link_data.interface1_ip6_mask,
if link_data.iface1 is not None:
iface1 = self.create_iface_element(
"interface1", link_data.node1_id, link_data.iface1
)
link_element.append(interface1)
link_element.append(iface1)
# check for interface two
if link_data.interface2_id is not None:
interface2 = self.create_interface_element(
"interface2",
link_data.node2_id,
link_data.interface2_id,
link_data.interface2_mac,
link_data.interface2_ip4,
link_data.interface2_ip4_mask,
link_data.interface2_ip6,
link_data.interface2_ip6_mask,
if link_data.iface2 is not None:
iface2 = self.create_iface_element(
"interface2", link_data.node2_id, link_data.iface2
)
link_element.append(interface2)
link_element.append(iface2)
# check for options, don't write for emane/wlan links
node1 = self.session.get_node(link_data.node1_id, NodeBase)
@ -566,23 +537,19 @@ class CoreXmlWriter:
is_node1_wireless = isinstance(node1, (WlanNode, EmaneNet))
is_node2_wireless = isinstance(node2, (WlanNode, EmaneNet))
if not any([is_node1_wireless, is_node2_wireless]):
options_data = link_data.options
options = etree.Element("options")
add_attribute(options, "delay", link_data.delay)
add_attribute(options, "bandwidth", link_data.bandwidth)
add_attribute(options, "loss", link_data.loss)
add_attribute(options, "dup", link_data.dup)
add_attribute(options, "jitter", link_data.jitter)
add_attribute(options, "mer", link_data.mer)
add_attribute(options, "burst", link_data.burst)
add_attribute(options, "mburst", link_data.mburst)
add_attribute(options, "type", link_data.link_type)
add_attribute(options, "gui_attributes", link_data.gui_attributes)
add_attribute(options, "unidirectional", link_data.unidirectional)
add_attribute(options, "emulation_id", link_data.emulation_id)
add_attribute(options, "delay", options_data.delay)
add_attribute(options, "bandwidth", options_data.bandwidth)
add_attribute(options, "loss", options_data.loss)
add_attribute(options, "dup", options_data.dup)
add_attribute(options, "jitter", options_data.jitter)
add_attribute(options, "mer", options_data.mer)
add_attribute(options, "burst", options_data.burst)
add_attribute(options, "mburst", options_data.mburst)
add_attribute(options, "unidirectional", options_data.unidirectional)
add_attribute(options, "network_id", link_data.network_id)
add_attribute(options, "key", link_data.key)
add_attribute(options, "opaque", link_data.opaque)
add_attribute(options, "session", link_data.session)
add_attribute(options, "key", options_data.key)
if options.items():
link_element.append(options)
@ -940,19 +907,19 @@ class CoreXmlReader:
node2_id = get_int(link_element, "node_two")
node_set = frozenset((node1_id, node2_id))
interface1_element = link_element.find("interface1")
if interface1_element is None:
interface1_element = link_element.find("interface_one")
interface1_data = None
if interface1_element is not None:
interface1_data = create_interface_data(interface1_element)
iface1_element = link_element.find("interface1")
if iface1_element is None:
iface1_element = link_element.find("interface_one")
iface1_data = None
if iface1_element is not None:
iface1_data = create_iface_data(iface1_element)
interface2_element = link_element.find("interface2")
if interface2_element is None:
interface2_element = link_element.find("interface_two")
interface2_data = None
if interface2_element is not None:
interface2_data = create_interface_data(interface2_element)
iface2_element = link_element.find("interface2")
if iface2_element is None:
iface2_element = link_element.find("interface_two")
iface2_data = None
if iface2_element is not None:
iface2_data = create_iface_data(iface2_element)
options_element = link_element.find("options")
options = LinkOptions()
@ -969,21 +936,16 @@ class CoreXmlReader:
if options.loss is None:
options.loss = get_float(options_element, "per")
options.unidirectional = get_int(options_element, "unidirectional")
options.session = options_element.get("session")
options.emulation_id = get_int(options_element, "emulation_id")
options.network_id = get_int(options_element, "network_id")
options.opaque = options_element.get("opaque")
options.gui_attributes = options_element.get("gui_attributes")
if options.unidirectional == 1 and node_set in node_sets:
logging.info("updating link node1(%s) node2(%s)", node1_id, node2_id)
self.session.update_link(
node1_id, node2_id, interface1_data.id, interface2_data.id, options
node1_id, node2_id, iface1_data.id, iface2_data.id, options
)
else:
logging.info("adding link node1(%s) node2(%s)", node1_id, node2_id)
self.session.add_link(
node1_id, node2_id, interface1_data, interface2_data, options
node1_id, node2_id, iface1_data, iface2_data, options
)
node_sets.add(node_set)

View file

@ -24,25 +24,25 @@ def add_address(
parent_element: etree.Element,
address_type: str,
address: str,
interface_name: str = None,
iface_name: str = None,
) -> None:
address_element = etree.SubElement(parent_element, "address", type=address_type)
address_element.text = address
if interface_name is not None:
address_element.set("iface", interface_name)
if iface_name is not None:
address_element.set("iface", iface_name)
def add_mapping(parent_element: etree.Element, maptype: str, mapref: str) -> None:
etree.SubElement(parent_element, "mapping", type=maptype, ref=mapref)
def add_emane_interface(
def add_emane_iface(
host_element: etree.Element,
netif: CoreInterface,
iface: CoreInterface,
platform_name: str = "p1",
transport_name: str = "t1",
) -> etree.Element:
nem_id = netif.net.nemidmap[netif]
nem_id = iface.net.nemidmap[iface]
host_id = host_element.get("id")
# platform data
@ -89,10 +89,10 @@ def get_ipv4_addresses(hostname: str) -> List[Tuple[str, str]]:
split = line.split()
if not split:
continue
interface_name = split[1]
iface_name = split[1]
address = split[3]
if not address.startswith("127."):
addresses.append((interface_name, address))
addresses.append((iface_name, address))
return addresses
else:
# TODO: handle other hosts
@ -112,11 +112,11 @@ class CoreXmlDeployment:
device = self.scenario.find(f"devices/device[@name='{name}']")
return device
def find_interface(self, device: NodeBase, name: str) -> etree.Element:
interface = self.scenario.find(
def find_iface(self, device: NodeBase, name: str) -> etree.Element:
iface = self.scenario.find(
f"devices/device[@name='{device.name}']/interfaces/interface[@name='{name}']"
)
return interface
return iface
def add_deployment(self) -> None:
physical_host = self.add_physical_host(socket.gethostname())
@ -136,8 +136,8 @@ class CoreXmlDeployment:
add_type(host_element, "physical")
# add ipv4 addresses
for interface_name, address in get_ipv4_addresses("localhost"):
add_address(host_element, "IPv4", address, interface_name)
for iface_name, address in get_ipv4_addresses("localhost"):
add_address(host_element, "IPv4", address, iface_name)
return host_element
@ -155,15 +155,15 @@ class CoreXmlDeployment:
# add host type
add_type(host_element, "virtual")
for netif in node.netifs():
for iface in node.get_ifaces():
emane_element = None
if isinstance(netif.net, EmaneNet):
emane_element = add_emane_interface(host_element, netif)
if isinstance(iface.net, EmaneNet):
emane_element = add_emane_iface(host_element, iface)
parent_element = host_element
if emane_element is not None:
parent_element = emane_element
for address in netif.addrlist:
for address in iface.addrlist:
address_type = get_address_type(address)
add_address(parent_element, address_type, address, netif.name)
add_address(parent_element, address_type, address, iface.name)

View file

@ -18,7 +18,7 @@ if TYPE_CHECKING:
from core.emane.emanemanager import EmaneManager
from core.emane.emanemodel import EmaneModel
_hwaddr_prefix = "02:02"
_MAC_PREFIX = "02:02"
def is_external(config: Dict[str, str]) -> bool:
@ -158,19 +158,19 @@ def build_node_platform_xml(
logging.warning("warning: EMANE network %s has no associated model", node.name)
return nem_id
for netif in node.netifs():
for iface in node.get_ifaces():
logging.debug(
"building platform xml for interface(%s) nem_id(%s)", netif.name, nem_id
"building platform xml for interface(%s) nem_id(%s)", iface.name, nem_id
)
# build nem xml
nem_definition = nem_file_name(node.model, netif)
nem_definition = nem_file_name(node.model, iface)
nem_element = etree.Element(
"nem", id=str(nem_id), name=netif.localname, definition=nem_definition
"nem", id=str(nem_id), name=iface.localname, definition=nem_definition
)
# check if this is an external transport, get default config if an interface
# specific one does not exist
config = emane_manager.getifcconfig(node.model.id, netif, node.model.name)
config = emane_manager.get_iface_config(node.model.id, iface, node.model.name)
if is_external(config):
nem_element.set("transport", "external")
@ -180,9 +180,9 @@ def build_node_platform_xml(
add_param(nem_element, transport_endpoint, config[transport_endpoint])
else:
# build transport xml
transport_type = netif.transport_type
transport_type = iface.transport_type
if not transport_type:
logging.info("warning: %s interface type unsupported!", netif.name)
logging.info("warning: %s interface type unsupported!", iface.name)
transport_type = TransportType.RAW
transport_file = transport_file_name(node.id, transport_type)
transport_element = etree.SubElement(
@ -190,14 +190,14 @@ def build_node_platform_xml(
)
# add transport parameter
add_param(transport_element, "device", netif.name)
add_param(transport_element, "device", iface.name)
# add nem entry
nem_entries[netif] = nem_element
nem_entries[iface] = nem_element
# merging code
key = netif.node.id
if netif.transport_type == TransportType.RAW:
key = iface.node.id
if iface.transport_type == TransportType.RAW:
key = "host"
otadev = control_net.brname
eventdev = control_net.brname
@ -229,10 +229,10 @@ def build_node_platform_xml(
platform_element.append(nem_element)
node.setnemid(netif, nem_id)
macstr = _hwaddr_prefix + ":00:00:"
node.setnemid(iface, nem_id)
macstr = _MAC_PREFIX + ":00:00:"
macstr += f"{(nem_id >> 8) & 0xFF:02X}:{nem_id & 0xFF:02X}"
netif.sethwaddr(macstr)
iface.set_mac(macstr)
# increment nem id
nem_id += 1
@ -280,19 +280,19 @@ def build_xml_files(emane_manager: "EmaneManager", node: EmaneNet) -> None:
vtype = TransportType.VIRTUAL
rtype = TransportType.RAW
for netif in node.netifs():
for iface in node.get_ifaces():
# check for interface specific emane configuration and write xml files
config = emane_manager.getifcconfig(node.model.id, netif, node.model.name)
config = emane_manager.get_iface_config(node.model.id, iface, node.model.name)
if config:
node.model.build_xml_files(config, netif)
node.model.build_xml_files(config, iface)
# check transport type needed for interface
if netif.transport_type == TransportType.VIRTUAL:
if iface.transport_type == TransportType.VIRTUAL:
need_virtual = True
vtype = netif.transport_type
vtype = iface.transport_type
else:
need_raw = True
rtype = netif.transport_type
rtype = iface.transport_type
if need_virtual:
build_transport_xml(emane_manager, node, vtype)
@ -494,70 +494,70 @@ def transport_file_name(node_id: int, transport_type: TransportType) -> str:
return f"n{node_id}trans{transport_type.value}.xml"
def _basename(emane_model: "EmaneModel", interface: CoreInterface = None) -> str:
def _basename(emane_model: "EmaneModel", iface: CoreInterface = None) -> str:
"""
Create name that is leveraged for configuration file creation.
:param emane_model: emane model to create name for
:param interface: interface for this model
:param iface: interface for this model
:return: basename used for file creation
"""
name = f"n{emane_model.id}"
if interface:
node_id = interface.node.id
if emane_model.session.emane.getifcconfig(node_id, interface, emane_model.name):
name = interface.localname.replace(".", "_")
if iface:
node_id = iface.node.id
if emane_model.session.emane.get_iface_config(node_id, iface, emane_model.name):
name = iface.localname.replace(".", "_")
return f"{name}{emane_model.name}"
def nem_file_name(emane_model: "EmaneModel", interface: CoreInterface = None) -> str:
def nem_file_name(emane_model: "EmaneModel", iface: CoreInterface = None) -> str:
"""
Return the string name for the NEM XML file, e.g. "n3rfpipenem.xml"
:param emane_model: emane model to create file
:param interface: interface for this model
:param iface: interface for this model
:return: nem xml filename
"""
basename = _basename(emane_model, interface)
basename = _basename(emane_model, iface)
append = ""
if interface and interface.transport_type == TransportType.RAW:
if iface and iface.transport_type == TransportType.RAW:
append = "_raw"
return f"{basename}nem{append}.xml"
def shim_file_name(emane_model: "EmaneModel", interface: CoreInterface = None) -> str:
def shim_file_name(emane_model: "EmaneModel", iface: CoreInterface = None) -> str:
"""
Return the string name for the SHIM XML file, e.g. "commeffectshim.xml"
:param emane_model: emane model to create file
:param interface: interface for this model
:param iface: interface for this model
:return: shim xml filename
"""
name = _basename(emane_model, interface)
name = _basename(emane_model, iface)
return f"{name}shim.xml"
def mac_file_name(emane_model: "EmaneModel", interface: CoreInterface = None) -> str:
def mac_file_name(emane_model: "EmaneModel", iface: CoreInterface = None) -> str:
"""
Return the string name for the MAC XML file, e.g. "n3rfpipemac.xml"
:param emane_model: emane model to create file
:param interface: interface for this model
:param iface: interface for this model
:return: mac xml filename
"""
name = _basename(emane_model, interface)
name = _basename(emane_model, iface)
return f"{name}mac.xml"
def phy_file_name(emane_model: "EmaneModel", interface: CoreInterface = None) -> str:
def phy_file_name(emane_model: "EmaneModel", iface: CoreInterface = None) -> str:
"""
Return the string name for the PHY XML file, e.g. "n3rfpipephy.xml"
:param emane_model: emane model to create file
:param interface: interface for this model
:param iface: interface for this model
:return: phy xml filename
"""
name = _basename(emane_model, interface)
name = _basename(emane_model, iface)
return f"{name}phy.xml"

View file

@ -1,7 +1,7 @@
import logging
from core.emulator.coreemu import CoreEmu
from core.emulator.emudata import IpPrefixes, NodeOptions
from core.emulator.data import IpPrefixes, NodeOptions
from core.emulator.enumerations import EventTypes
from core.nodes.base import CoreNode
from core.nodes.network import SwitchNode
@ -20,13 +20,13 @@ if __name__ == "__main__":
# node one
options.config_services = ["DefaultRoute", "IPForward"]
node1 = session.add_node(CoreNode, options=options)
interface = prefixes.create_interface(node1)
session.add_link(node1.id, switch.id, interface1_data=interface)
interface = prefixes.create_iface(node1)
session.add_link(node1.id, switch.id, iface1_data=interface)
# node two
node2 = session.add_node(CoreNode, options=options)
interface = prefixes.create_interface(node2)
session.add_link(node2.id, switch.id, interface1_data=interface)
interface = prefixes.create_iface(node2)
session.add_link(node2.id, switch.id, iface1_data=interface)
# start session and run services
session.instantiate()

View file

@ -1,7 +1,7 @@
import logging
from core.emulator.coreemu import CoreEmu
from core.emulator.emudata import IpPrefixes, NodeOptions
from core.emulator.data import IpPrefixes, NodeOptions
from core.emulator.enumerations import EventTypes
from core.nodes.base import CoreNode
from core.nodes.docker import DockerNode
@ -18,11 +18,11 @@ if __name__ == "__main__":
# create node one
node1 = session.add_node(DockerNode, options=options)
interface1_data = prefixes.create_interface(node1)
interface1_data = prefixes.create_iface(node1)
# create node two
node2 = session.add_node(CoreNode)
interface2_data = prefixes.create_interface(node2)
interface2_data = prefixes.create_iface(node2)
# add link
session.add_link(node1.id, node2.id, interface1_data, interface2_data)

View file

@ -1,7 +1,7 @@
import logging
from core.emulator.coreemu import CoreEmu
from core.emulator.emudata import IpPrefixes, NodeOptions
from core.emulator.data import IpPrefixes, NodeOptions
from core.emulator.enumerations import EventTypes
from core.nodes.docker import DockerNode
@ -19,11 +19,11 @@ if __name__ == "__main__":
# create node one
node1 = session.add_node(DockerNode, options=options)
interface1_data = prefixes.create_interface(node1)
interface1_data = prefixes.create_iface(node1)
# create node two
node2 = session.add_node(DockerNode, options=options)
interface2_data = prefixes.create_interface(node2)
interface2_data = prefixes.create_iface(node2)
# add link
session.add_link(node1.id, node2.id, interface1_data, interface2_data)

View file

@ -1,7 +1,7 @@
import logging
from core.emulator.coreemu import CoreEmu
from core.emulator.emudata import IpPrefixes, NodeOptions
from core.emulator.data import IpPrefixes, NodeOptions
from core.emulator.enumerations import EventTypes
from core.nodes.base import CoreNode
from core.nodes.docker import DockerNode
@ -23,15 +23,15 @@ if __name__ == "__main__":
# node one
node1 = session.add_node(DockerNode, options=options)
interface1_data = prefixes.create_interface(node1)
interface1_data = prefixes.create_iface(node1)
# node two
node2 = session.add_node(DockerNode, options=options)
interface2_data = prefixes.create_interface(node2)
interface2_data = prefixes.create_iface(node2)
# node three
node_three = session.add_node(CoreNode)
interface_three = prefixes.create_interface(node_three)
interface_three = prefixes.create_iface(node_three)
# add links
session.add_link(node1.id, switch.id, interface1_data)

View file

@ -47,7 +47,7 @@ def main(args):
node1_id = response.node_id
# create link
interface1 = interface_helper.create_interface(node1_id, 0)
interface1 = interface_helper.create_iface(node1_id, 0)
response = core.add_link(session_id, node1_id, switch_id, interface1)
logging.info("created link from node one to switch: %s", response)
@ -59,7 +59,7 @@ def main(args):
node2_id = response.node_id
# create link
interface1 = interface_helper.create_interface(node2_id, 0)
interface1 = interface_helper.create_iface(node2_id, 0)
response = core.add_link(session_id, node2_id, switch_id, interface1)
logging.info("created link from node two to switch: %s", response)

View file

@ -57,10 +57,10 @@ def main():
node2_id = response.node_id
# links nodes to switch
interface1 = interface_helper.create_interface(node1_id, 0)
interface1 = interface_helper.create_iface(node1_id, 0)
response = core.add_link(session_id, node1_id, emane_id, interface1)
logging.info("created link: %s", response)
interface1 = interface_helper.create_interface(node2_id, 0)
interface1 = interface_helper.create_iface(node2_id, 0)
response = core.add_link(session_id, node2_id, emane_id, interface1)
logging.info("created link: %s", response)

View file

@ -53,10 +53,10 @@ def main():
node2_id = response.node_id
# links nodes to switch
interface1 = interface_helper.create_interface(node1_id, 0)
interface1 = interface_helper.create_iface(node1_id, 0)
response = core.add_link(session_id, node1_id, switch_id, interface1)
logging.info("created link: %s", response)
interface1 = interface_helper.create_interface(node2_id, 0)
interface1 = interface_helper.create_iface(node2_id, 0)
response = core.add_link(session_id, node2_id, switch_id, interface1)
logging.info("created link: %s", response)

View file

@ -65,10 +65,10 @@ def main():
node2_id = response.node_id
# links nodes to switch
interface1 = interface_helper.create_interface(node1_id, 0)
interface1 = interface_helper.create_iface(node1_id, 0)
response = core.add_link(session_id, node1_id, wlan_id, interface1)
logging.info("created link: %s", response)
interface1 = interface_helper.create_interface(node2_id, 0)
interface1 = interface_helper.create_iface(node2_id, 0)
response = core.add_link(session_id, node2_id, wlan_id, interface1)
logging.info("created link: %s", response)

View file

@ -1,7 +1,7 @@
import logging
from core.emulator.coreemu import CoreEmu
from core.emulator.emudata import IpPrefixes, NodeOptions
from core.emulator.data import IpPrefixes, NodeOptions
from core.emulator.enumerations import EventTypes
from core.nodes.base import CoreNode
from core.nodes.lxd import LxcNode
@ -18,11 +18,11 @@ if __name__ == "__main__":
# create node one
node1 = session.add_node(LxcNode, options=options)
interface1_data = prefixes.create_interface(node1)
interface1_data = prefixes.create_iface(node1)
# create node two
node2 = session.add_node(CoreNode)
interface2_data = prefixes.create_interface(node2)
interface2_data = prefixes.create_iface(node2)
# add link
session.add_link(node1.id, node2.id, interface1_data, interface2_data)

View file

@ -1,7 +1,7 @@
import logging
from core.emulator.coreemu import CoreEmu
from core.emulator.emudata import IpPrefixes, NodeOptions
from core.emulator.data import IpPrefixes, NodeOptions
from core.emulator.enumerations import EventTypes
from core.nodes.lxd import LxcNode
@ -19,11 +19,11 @@ if __name__ == "__main__":
# create node one
node1 = session.add_node(LxcNode, options=options)
interface1_data = prefixes.create_interface(node1)
interface1_data = prefixes.create_iface(node1)
# create node two
node2 = session.add_node(LxcNode, options=options)
interface2_data = prefixes.create_interface(node2)
interface2_data = prefixes.create_iface(node2)
# add link
session.add_link(node1.id, node2.id, interface1_data, interface2_data)

View file

@ -1,7 +1,7 @@
import logging
from core.emulator.coreemu import CoreEmu
from core.emulator.emudata import IpPrefixes, NodeOptions
from core.emulator.data import IpPrefixes, NodeOptions
from core.emulator.enumerations import EventTypes
from core.nodes.base import CoreNode
from core.nodes.lxd import LxcNode
@ -23,15 +23,15 @@ if __name__ == "__main__":
# node one
node1 = session.add_node(LxcNode, options=options)
interface1_data = prefixes.create_interface(node1)
interface1_data = prefixes.create_iface(node1)
# node two
node2 = session.add_node(LxcNode, options=options)
interface2_data = prefixes.create_interface(node2)
interface2_data = prefixes.create_iface(node2)
# node three
node3 = session.add_node(CoreNode)
interface3_data = prefixes.create_interface(node3)
interface3_data = prefixes.create_iface(node3)
# add links
session.add_link(node1.id, switch.id, interface1_data)

View file

@ -80,8 +80,8 @@ class MyService(CoreService):
if filename == cls.configs[0]:
cfg += "# auto-generated by MyService (sample.py)\n"
for ifc in node.netifs():
cfg += f'echo "Node {node.name} has interface {ifc.name}"\n'
for iface in node.get_ifaces():
cfg += f'echo "Node {node.name} has interface {iface.name}"\n'
elif filename == cls.configs[1]:
cfg += "echo hello"

View file

@ -9,7 +9,7 @@ import logging
from core.emane.ieee80211abg import EmaneIeee80211abgModel
from core.emane.nodes import EmaneNet
from core.emulator.coreemu import CoreEmu
from core.emulator.emudata import IpPrefixes, NodeOptions
from core.emulator.data import IpPrefixes, NodeOptions
from core.emulator.enumerations import EventTypes
from core.nodes.base import CoreNode
@ -59,10 +59,10 @@ def main(args):
node2 = session.add_node(CoreNode, options=options)
# create node interfaces and link
interface1_data = prefixes.create_interface(node1)
interface2_data = prefixes.create_interface(node2)
session.add_link(node1.id, emane_net.id, interface1_data=interface1_data)
session.add_link(node2.id, emane_net.id, interface1_data=interface2_data)
interface1_data = prefixes.create_iface(node1)
interface2_data = prefixes.create_iface(node2)
session.add_link(node1.id, emane_net.id, iface1_data=interface1_data)
session.add_link(node2.id, emane_net.id, iface1_data=interface2_data)
# instantiate session
session.instantiate()

View file

@ -7,7 +7,7 @@ import argparse
import logging
from core.emulator.coreemu import CoreEmu
from core.emulator.emudata import IpPrefixes, NodeOptions
from core.emulator.data import IpPrefixes, NodeOptions
from core.emulator.enumerations import EventTypes
from core.nodes.lxd import LxcNode
@ -48,8 +48,8 @@ def main(args):
node2 = session.add_node(LxcNode, options=options)
# create node interfaces and link
interface1_data = prefixes.create_interface(node1)
interface2_data = prefixes.create_interface(node2)
interface1_data = prefixes.create_iface(node1)
interface2_data = prefixes.create_iface(node2)
session.add_link(node1.id, node2.id, interface1_data, interface2_data)
# instantiate session

View file

@ -7,7 +7,7 @@ import argparse
import logging
from core.emulator.coreemu import CoreEmu
from core.emulator.emudata import IpPrefixes, NodeOptions
from core.emulator.data import IpPrefixes, NodeOptions
from core.emulator.enumerations import EventTypes
from core.nodes.base import CoreNode
@ -48,8 +48,8 @@ def main(args):
node2 = session.add_node(CoreNode, options=options)
# create node interfaces and link
interface1_data = prefixes.create_interface(node1)
interface2_data = prefixes.create_interface(node2)
interface1_data = prefixes.create_iface(node1)
interface2_data = prefixes.create_iface(node2)
session.add_link(node1.id, node2.id, interface1_data, interface2_data)
# instantiate session

View file

@ -7,7 +7,7 @@ import argparse
import logging
from core.emulator.coreemu import CoreEmu
from core.emulator.emudata import IpPrefixes, NodeOptions
from core.emulator.data import IpPrefixes, NodeOptions
from core.emulator.enumerations import EventTypes
from core.nodes.base import CoreNode
from core.nodes.network import SwitchNode
@ -52,10 +52,10 @@ def main(args):
node2 = session.add_node(CoreNode, options=options)
# create node interfaces and link
interface1_data = prefixes.create_interface(node1)
interface2_data = prefixes.create_interface(node2)
session.add_link(node1.id, switch.id, interface1_data=interface1_data)
session.add_link(node2.id, switch.id, interface1_data=interface2_data)
interface1_data = prefixes.create_iface(node1)
interface2_data = prefixes.create_iface(node2)
session.add_link(node1.id, switch.id, iface1_data=interface1_data)
session.add_link(node2.id, switch.id, iface1_data=interface2_data)
# instantiate session
session.instantiate()

View file

@ -10,7 +10,7 @@ import time
from core.emane.ieee80211abg import EmaneIeee80211abgModel
from core.emane.nodes import EmaneNet
from core.emulator.coreemu import CoreEmu
from core.emulator.emudata import IpPrefixes, NodeOptions
from core.emulator.data import IpPrefixes, NodeOptions
from core.emulator.enumerations import EventTypes
from core.nodes.base import CoreNode
@ -42,8 +42,8 @@ def main():
for i in range(NODES):
node = session.add_node(CoreNode, options=options)
node.setposition(x=150 * (i + 1), y=150)
interface = prefixes.create_interface(node)
session.add_link(node.id, emane_network.id, interface1_data=interface)
interface = prefixes.create_iface(node)
session.add_link(node.id, emane_network.id, iface1_data=interface)
# instantiate session
session.instantiate()

View file

@ -6,7 +6,7 @@ interact with the GUI.
import logging
from core.emulator.coreemu import CoreEmu
from core.emulator.emudata import IpPrefixes
from core.emulator.data import IpPrefixes
from core.emulator.enumerations import EventTypes
from core.nodes.base import CoreNode
from core.nodes.network import SwitchNode
@ -31,8 +31,8 @@ def main():
# create nodes
for _ in range(NODES):
node = session.add_node(CoreNode)
interface = prefixes.create_interface(node)
session.add_link(node.id, switch.id, interface1_data=interface)
interface = prefixes.create_iface(node)
session.add_link(node.id, switch.id, iface1_data=interface)
# instantiate session
session.instantiate()

View file

@ -8,7 +8,7 @@ same CoreEmu instance the GUI is using.
import logging
from core.emulator.coreemu import CoreEmu
from core.emulator.emudata import IpPrefixes
from core.emulator.data import IpPrefixes
from core.emulator.enumerations import EventTypes
from core.nodes.base import CoreNode
from core.nodes.network import SwitchNode
@ -33,8 +33,8 @@ def main():
# create nodes
for _ in range(NODES):
node = session.add_node(CoreNode)
interface = prefixes.create_interface(node)
session.add_link(node.id, switch.id, interface1_data=interface)
interface = prefixes.create_iface(node)
session.add_link(node.id, switch.id, iface1_data=interface)
# instantiate session
session.instantiate()

View file

@ -6,7 +6,7 @@ interact with the GUI.
import logging
from core.emulator.coreemu import CoreEmu
from core.emulator.emudata import IpPrefixes, NodeOptions
from core.emulator.data import IpPrefixes, NodeOptions
from core.emulator.enumerations import EventTypes
from core.location.mobility import BasicRangeModel
from core.nodes.base import CoreNode
@ -35,8 +35,8 @@ def main():
options.set_position(0, 0)
for _ in range(NODES):
node = session.add_node(CoreNode, options=options)
interface = prefixes.create_interface(node)
session.add_link(node.id, wlan.id, interface1_data=interface)
interface = prefixes.create_iface(node)
session.add_link(node.id, wlan.id, iface1_data=interface)
# instantiate session
session.instantiate()

View file

@ -319,12 +319,12 @@ message ThroughputsRequest {
message ThroughputsEvent {
int32 session_id = 1;
repeated BridgeThroughput bridge_throughputs = 2;
repeated InterfaceThroughput interface_throughputs = 3;
repeated InterfaceThroughput iface_throughputs = 3;
}
message InterfaceThroughput {
int32 node_id = 1;
int32 interface_id = 2;
int32 iface_id = 2;
double throughput = 3;
}
@ -374,7 +374,7 @@ message ConfigEvent {
string bitmap = 8;
string possible_values = 9;
string groups = 10;
int32 interface = 11;
int32 iface_id = 11;
int32 network_id = 12;
string opaque = 13;
}
@ -416,7 +416,7 @@ message GetNodeRequest {
message GetNodeResponse {
Node node = 1;
repeated Interface interfaces = 2;
repeated Interface ifaces = 2;
}
message EditNodeRequest {
@ -492,16 +492,16 @@ message AddLinkRequest {
message AddLinkResponse {
bool result = 1;
Interface interface1 = 2;
Interface interface2 = 3;
Interface iface1 = 2;
Interface iface2 = 3;
}
message EditLinkRequest {
int32 session_id = 1;
int32 node1_id = 2;
int32 node2_id = 3;
int32 interface1_id = 4;
int32 interface2_id = 5;
int32 iface1_id = 4;
int32 iface2_id = 5;
LinkOptions options = 6;
}
@ -513,8 +513,8 @@ message DeleteLinkRequest {
int32 session_id = 1;
int32 node1_id = 2;
int32 node2_id = 3;
int32 interface1_id = 4;
int32 interface2_id = 5;
int32 iface1_id = 4;
int32 iface2_id = 5;
}
message DeleteLinkResponse {
@ -561,7 +561,7 @@ message GetInterfacesRequest {
}
message GetInterfacesResponse {
repeated string interfaces = 1;
repeated string ifaces = 1;
}
message ExecuteScriptRequest {
@ -692,21 +692,20 @@ message Node {
repeated string services = 6;
string emane = 7;
string icon = 8;
string opaque = 9;
string image = 10;
string server = 11;
repeated string config_services = 12;
Geo geo = 13;
string dir = 14;
string channel = 15;
string image = 9;
string server = 10;
repeated string config_services = 11;
Geo geo = 12;
string dir = 13;
string channel = 14;
}
message Link {
int32 node1_id = 1;
int32 node2_id = 2;
LinkType.Enum type = 3;
Interface interface1 = 4;
Interface interface2 = 5;
Interface iface1 = 4;
Interface iface2 = 5;
LinkOptions options = 6;
int32 network_id = 7;
string label = 8;
@ -732,11 +731,11 @@ message Interface {
string name = 2;
string mac = 3;
string ip4 = 4;
int32 ip4mask = 5;
int32 ip4_mask = 5;
string ip6 = 6;
int32 ip6mask = 7;
int32 netid = 8;
int32 flowid = 9;
int32 ip6_mask = 7;
int32 net_id = 8;
int32 flow_id = 9;
int32 mtu = 10;
}

View file

@ -32,7 +32,7 @@ message GetEmaneModelsResponse {
message GetEmaneModelConfigRequest {
int32 session_id = 1;
int32 node_id = 2;
int32 interface = 3;
int32 iface_id = 3;
string model = 4;
}
@ -57,7 +57,7 @@ message GetEmaneModelConfigsResponse {
message ModelConfig {
int32 node_id = 1;
string model = 2;
int32 interface = 3;
int32 iface_id = 3;
map<string, common.ConfigOption> config = 4;
}
repeated ModelConfig configs = 1;
@ -86,7 +86,7 @@ message EmaneLinkResponse {
message EmaneModelConfig {
int32 node_id = 1;
int32 interface_id = 2;
int32 iface_id = 2;
string model = 3;
map<string, string> config = 4;
}
@ -95,10 +95,10 @@ message EmanePathlossesRequest {
int32 session_id = 1;
int32 node1_id = 2;
float rx1 = 3;
int32 interface1_id = 4;
int32 iface1_id = 4;
int32 node2_id = 5;
float rx2 = 6;
int32 interface2_id = 7;
int32 iface2_id = 7;
}
message EmanePathlossesResponse {

View file

@ -101,8 +101,8 @@ class RouterMonitor:
node_map[node.id] = node.channel
if self.src_id is None:
response = self.core.get_node(self.session, node.id)
for netif in response.interfaces:
if self.src == netif.ip4:
for iface in response.ifaces:
if self.src == iface.ip4:
self.src_id = node.id
break
except grpc.RpcError:

View file

@ -14,8 +14,8 @@ from core.api.grpc.server import CoreGrpcServer
from core.api.tlv.corehandlers import CoreHandler
from core.emane.emanemanager import EmaneManager
from core.emulator.coreemu import CoreEmu
from core.emulator.data import IpPrefixes
from core.emulator.distributed import DistributedServer
from core.emulator.emudata import IpPrefixes
from core.emulator.enumerations import EventTypes
from core.emulator.session import Session
from core.nodes.base import CoreNode
@ -89,7 +89,7 @@ def ip_prefixes():
@pytest.fixture(scope="session")
def interface_helper():
def iface_helper():
return InterfaceHelper(ip4_prefix="10.83.0.0/16")

View file

@ -15,7 +15,7 @@ from core.emane.ieee80211abg import EmaneIeee80211abgModel
from core.emane.nodes import EmaneNet
from core.emane.rfpipe import EmaneRfPipeModel
from core.emane.tdma import EmaneTdmaModel
from core.emulator.emudata import IpPrefixes, NodeOptions
from core.emulator.data import IpPrefixes, NodeOptions
from core.emulator.session import Session
from core.errors import CoreCommandError, CoreError
from core.nodes.base import CoreNode
@ -79,8 +79,8 @@ class TestEmane:
for i, node in enumerate([node1, node2]):
node.setposition(x=150 * (i + 1), y=150)
interface = ip_prefixes.create_interface(node)
session.add_link(node.id, emane_network.id, interface1_data=interface)
iface_data = ip_prefixes.create_iface(node)
session.add_link(node.id, emane_network.id, iface1_data=iface_data)
# instantiate session
session.instantiate()
@ -119,8 +119,8 @@ class TestEmane:
for i, node in enumerate([node1, node2]):
node.setposition(x=150 * (i + 1), y=150)
interface = ip_prefixes.create_interface(node)
session.add_link(node.id, emane_network.id, interface1_data=interface)
iface_data = ip_prefixes.create_iface(node)
session.add_link(node.id, emane_network.id, iface1_data=iface_data)
# instantiate session
session.instantiate()

View file

@ -8,7 +8,7 @@ from typing import Type
import pytest
from core.emulator.emudata import IpPrefixes, NodeOptions
from core.emulator.data import IpPrefixes, NodeOptions
from core.emulator.enumerations import MessageFlags
from core.emulator.session import Session
from core.errors import CoreCommandError
@ -53,8 +53,8 @@ class TestCore:
# link nodes to net node
for node in [node1, node2]:
interface = ip_prefixes.create_interface(node)
session.add_link(node.id, net_node.id, interface1_data=interface)
iface_data = ip_prefixes.create_iface(node)
session.add_link(node.id, net_node.id, iface1_data=iface_data)
# instantiate session
session.instantiate()
@ -80,8 +80,8 @@ class TestCore:
# link nodes to ptp net
for node in [node1, node2]:
interface = ip_prefixes.create_interface(node)
session.add_link(node.id, ptp_node.id, interface1_data=interface)
iface_data = ip_prefixes.create_iface(node)
session.add_link(node.id, ptp_node.id, iface1_data=iface_data)
# get node client for testing
client = node1.client
@ -96,9 +96,9 @@ class TestCore:
if not request.config.getoption("mock"):
assert client.check_cmd("echo hello") == "hello"
def test_netif(self, session: Session, ip_prefixes: IpPrefixes):
def test_iface(self, session: Session, ip_prefixes: IpPrefixes):
"""
Test netif methods.
Test interface methods.
:param session: session for test
:param ip_prefixes: generates ip addresses for nodes
@ -113,8 +113,8 @@ class TestCore:
# link nodes to ptp net
for node in [node1, node2]:
interface = ip_prefixes.create_interface(node)
session.add_link(node.id, ptp_node.id, interface1_data=interface)
iface = ip_prefixes.create_iface(node)
session.add_link(node.id, ptp_node.id, iface1_data=iface)
# instantiate session
session.instantiate()
@ -126,19 +126,19 @@ class TestCore:
assert node1.commonnets(node2)
assert node2.commonnets(node1)
# check we can retrieve netif index
assert node1.ifname(0)
assert node2.ifname(0)
# check we can retrieve interface id
assert 0 in node1.ifaces
assert 0 in node2.ifaces
# check interface parameters
interface = node1.netif(0)
interface.setparam("test", 1)
assert interface.getparam("test") == 1
assert interface.getparams()
iface = node1.get_iface(0)
iface.setparam("test", 1)
assert iface.getparam("test") == 1
assert iface.getparams()
# delete netif and test that if no longer exists
node1.delnetif(0)
assert not node1.netif(0)
# delete interface and test that if no longer exists
node1.delete_iface(0)
assert 0 not in node1.ifaces
def test_wlan_ping(self, session: Session, ip_prefixes: IpPrefixes):
"""
@ -160,8 +160,8 @@ class TestCore:
# link nodes
for node in [node1, node2]:
interface = ip_prefixes.create_interface(node)
session.add_link(node.id, wlan_node.id, interface1_data=interface)
iface_id = ip_prefixes.create_iface(node)
session.add_link(node.id, wlan_node.id, iface1_data=iface_id)
# instantiate session
session.instantiate()
@ -190,8 +190,8 @@ class TestCore:
# link nodes
for node in [node1, node2]:
interface = ip_prefixes.create_interface(node)
session.add_link(node.id, wlan_node.id, interface1_data=interface)
iface_id = ip_prefixes.create_iface(node)
session.add_link(node.id, wlan_node.id, iface1_data=iface_id)
# configure mobility script for session
config = {

View file

@ -1,4 +1,4 @@
from core.emulator.emudata import NodeOptions
from core.emulator.data import NodeOptions
from core.emulator.session import Session
from core.nodes.base import CoreNode
from core.nodes.network import HubNode

View file

@ -18,8 +18,7 @@ from core.api.tlv.dataconversion import ConfigShim
from core.api.tlv.enumerations import ConfigFlags
from core.emane.ieee80211abg import EmaneIeee80211abgModel
from core.emane.nodes import EmaneNet
from core.emulator.data import EventData, NodeData
from core.emulator.emudata import IpPrefixes, NodeOptions
from core.emulator.data import EventData, IpPrefixes, NodeData, NodeOptions
from core.emulator.enumerations import EventTypes, ExceptionLevels, NodeTypes
from core.errors import CoreError
from core.location.mobility import BasicRangeModel, Ns2ScriptedMobility
@ -42,15 +41,17 @@ class TestGrpc:
id=3, type=NodeTypes.WIRELESS_LAN.value, position=position
)
nodes = [node1, node2, wlan_node]
interface_helper = InterfaceHelper(ip4_prefix="10.83.0.0/16")
interface1 = interface_helper.create_interface(node1.id, 0)
interface2 = interface_helper.create_interface(node2.id, 0)
iface_helper = InterfaceHelper(ip4_prefix="10.83.0.0/16")
iface1_id = 0
iface1 = iface_helper.create_iface(node1.id, iface1_id)
iface2_id = 0
iface2 = iface_helper.create_iface(node2.id, iface2_id)
link = core_pb2.Link(
type=core_pb2.LinkType.WIRED,
node1_id=node1.id,
node2_id=node2.id,
interface1=interface1,
interface2=interface2,
iface1=iface1,
iface2=iface2,
)
links = [link]
hook = core_pb2.Hook(
@ -81,7 +82,7 @@ class TestGrpc:
model_config_value = "500000"
model_config = EmaneModelConfig(
node_id=model_node_id,
interface_id=-1,
iface_id=-1,
model=EmaneIeee80211abgModel.name,
config={model_config_key: model_config_value},
)
@ -131,8 +132,8 @@ class TestGrpc:
assert node1.id in session.nodes
assert node2.id in session.nodes
assert wlan_node.id in session.nodes
assert session.nodes[node1.id].netif(0) is not None
assert session.nodes[node2.id].netif(0) is not None
assert iface1_id in session.nodes[node1.id].ifaces
assert iface2_id in session.nodes[node2.id].ifaces
hook_file, hook_data = session.hooks[EventTypes.RUNTIME_STATE][0]
assert hook_file == hook.file
assert hook_data == hook.data
@ -522,8 +523,8 @@ class TestGrpc:
session = grpc_server.coreemu.create_session()
switch = session.add_node(SwitchNode)
node = session.add_node(CoreNode)
interface = ip_prefixes.create_interface(node)
session.add_link(node.id, switch.id, interface)
iface_data = ip_prefixes.create_iface(node)
session.add_link(node.id, switch.id, iface_data)
# then
with client.context_connect():
@ -540,17 +541,15 @@ class TestGrpc:
session = grpc_server.coreemu.create_session()
switch = session.add_node(SwitchNode)
node = session.add_node(CoreNode)
interface = ip_prefixes.create_interface(node)
session.add_link(node.id, switch.id, interface)
iface_data = ip_prefixes.create_iface(node)
session.add_link(node.id, switch.id, iface_data)
# then
with pytest.raises(grpc.RpcError):
with client.context_connect():
client.get_node_links(session.id, 3)
def test_add_link(
self, grpc_server: CoreGrpcServer, interface_helper: InterfaceHelper
):
def test_add_link(self, grpc_server: CoreGrpcServer, iface_helper: InterfaceHelper):
# given
client = CoreGrpcClient()
session = grpc_server.coreemu.create_session()
@ -559,16 +558,16 @@ class TestGrpc:
assert len(switch.all_link_data()) == 0
# then
interface = interface_helper.create_interface(node.id, 0)
iface = iface_helper.create_iface(node.id, 0)
with client.context_connect():
response = client.add_link(session.id, node.id, switch.id, interface)
response = client.add_link(session.id, node.id, switch.id, iface)
# then
assert response.result is True
assert len(switch.all_link_data()) == 1
def test_add_link_exception(
self, grpc_server: CoreGrpcServer, interface_helper: InterfaceHelper
self, grpc_server: CoreGrpcServer, iface_helper: InterfaceHelper
):
# given
client = CoreGrpcClient()
@ -576,10 +575,10 @@ class TestGrpc:
node = session.add_node(CoreNode)
# then
interface = interface_helper.create_interface(node.id, 0)
iface = iface_helper.create_iface(node.id, 0)
with pytest.raises(grpc.RpcError):
with client.context_connect():
client.add_link(session.id, 1, 3, interface)
client.add_link(session.id, 1, 3, iface)
def test_edit_link(self, grpc_server: CoreGrpcServer, ip_prefixes: IpPrefixes):
# given
@ -587,32 +586,32 @@ class TestGrpc:
session = grpc_server.coreemu.create_session()
switch = session.add_node(SwitchNode)
node = session.add_node(CoreNode)
interface = ip_prefixes.create_interface(node)
session.add_link(node.id, switch.id, interface)
iface = ip_prefixes.create_iface(node)
session.add_link(node.id, switch.id, iface)
options = core_pb2.LinkOptions(bandwidth=30000)
link = switch.all_link_data()[0]
assert options.bandwidth != link.bandwidth
assert options.bandwidth != link.options.bandwidth
# then
with client.context_connect():
response = client.edit_link(
session.id, node.id, switch.id, options, interface1_id=interface.id
session.id, node.id, switch.id, options, iface1_id=iface.id
)
# then
assert response.result is True
link = switch.all_link_data()[0]
assert options.bandwidth == link.bandwidth
assert options.bandwidth == link.options.bandwidth
def test_delete_link(self, grpc_server: CoreGrpcServer, ip_prefixes: IpPrefixes):
# given
client = CoreGrpcClient()
session = grpc_server.coreemu.create_session()
node1 = session.add_node(CoreNode)
interface1 = ip_prefixes.create_interface(node1)
iface1 = ip_prefixes.create_iface(node1)
node2 = session.add_node(CoreNode)
interface2 = ip_prefixes.create_interface(node2)
session.add_link(node1.id, node2.id, interface1, interface2)
iface2 = ip_prefixes.create_iface(node2)
session.add_link(node1.id, node2.id, iface1, iface2)
link_node = None
for node_id in session.nodes:
node = session.nodes[node_id]
@ -624,7 +623,7 @@ class TestGrpc:
# then
with client.context_connect():
response = client.delete_link(
session.id, node1.id, node2.id, interface1.id, interface2.id
session.id, node1.id, node2.id, iface1.id, iface2.id
)
# then
@ -729,7 +728,7 @@ class TestGrpc:
assert emane_network.id == model_config.node_id
assert model_config.model == EmaneIeee80211abgModel.name
assert len(model_config.config) > 0
assert model_config.interface == -1
assert model_config.iface_id == -1
def test_set_emane_model_config(self, grpc_server: CoreGrpcServer):
# given
@ -1028,8 +1027,8 @@ class TestGrpc:
session = grpc_server.coreemu.create_session()
wlan = session.add_node(WlanNode)
node = session.add_node(CoreNode)
interface = ip_prefixes.create_interface(node)
session.add_link(node.id, wlan.id, interface)
iface = ip_prefixes.create_iface(node)
session.add_link(node.id, wlan.id, iface)
link_data = wlan.all_link_data()[0]
queue = Queue()
@ -1199,9 +1198,10 @@ class TestGrpc:
queue = Queue()
def node_handler(node_data: NodeData):
assert node_data.longitude == lon
assert node_data.latitude == lat
assert node_data.altitude == alt
n = node_data.node
assert n.position.lon == lon
assert n.position.lat == lat
assert n.position.alt == alt
queue.put(node_data)
session.node_handlers.append(node_handler)

View file

@ -107,15 +107,15 @@ class TestGui:
switch_id = 2
coretlv.session.add_node(SwitchNode, _id=switch_id)
ip_prefix = netaddr.IPNetwork("10.0.0.0/24")
interface1_ip4 = str(ip_prefix[node1_id])
iface1_ip4 = str(ip_prefix[node1_id])
message = coreapi.CoreLinkMessage.create(
MessageFlags.ADD.value,
[
(LinkTlvs.N1_NUMBER, node1_id),
(LinkTlvs.N2_NUMBER, switch_id),
(LinkTlvs.INTERFACE1_NUMBER, 0),
(LinkTlvs.INTERFACE1_IP4, interface1_ip4),
(LinkTlvs.INTERFACE1_IP4_MASK, 24),
(LinkTlvs.IFACE1_NUMBER, 0),
(LinkTlvs.IFACE1_IP4, iface1_ip4),
(LinkTlvs.IFACE1_IP4_MASK, 24),
],
)
@ -131,15 +131,15 @@ class TestGui:
switch_id = 2
coretlv.session.add_node(SwitchNode, _id=switch_id)
ip_prefix = netaddr.IPNetwork("10.0.0.0/24")
interface2_ip4 = str(ip_prefix[node1_id])
iface2_ip4 = str(ip_prefix[node1_id])
message = coreapi.CoreLinkMessage.create(
MessageFlags.ADD.value,
[
(LinkTlvs.N1_NUMBER, switch_id),
(LinkTlvs.N2_NUMBER, node1_id),
(LinkTlvs.INTERFACE2_NUMBER, 0),
(LinkTlvs.INTERFACE2_IP4, interface2_ip4),
(LinkTlvs.INTERFACE2_IP4_MASK, 24),
(LinkTlvs.IFACE2_NUMBER, 0),
(LinkTlvs.IFACE2_IP4, iface2_ip4),
(LinkTlvs.IFACE2_IP4_MASK, 24),
],
)
@ -155,19 +155,19 @@ class TestGui:
node2_id = 2
coretlv.session.add_node(CoreNode, _id=node2_id)
ip_prefix = netaddr.IPNetwork("10.0.0.0/24")
interface1_ip4 = str(ip_prefix[node1_id])
interface2_ip4 = str(ip_prefix[node2_id])
iface1_ip4 = str(ip_prefix[node1_id])
iface2_ip4 = str(ip_prefix[node2_id])
message = coreapi.CoreLinkMessage.create(
MessageFlags.ADD.value,
[
(LinkTlvs.N1_NUMBER, node1_id),
(LinkTlvs.N2_NUMBER, node2_id),
(LinkTlvs.INTERFACE1_NUMBER, 0),
(LinkTlvs.INTERFACE1_IP4, interface1_ip4),
(LinkTlvs.INTERFACE1_IP4_MASK, 24),
(LinkTlvs.INTERFACE2_NUMBER, 0),
(LinkTlvs.INTERFACE2_IP4, interface2_ip4),
(LinkTlvs.INTERFACE2_IP4_MASK, 24),
(LinkTlvs.IFACE1_NUMBER, 0),
(LinkTlvs.IFACE1_IP4, iface1_ip4),
(LinkTlvs.IFACE1_IP4_MASK, 24),
(LinkTlvs.IFACE2_NUMBER, 0),
(LinkTlvs.IFACE2_IP4, iface2_ip4),
(LinkTlvs.IFACE2_IP4_MASK, 24),
],
)
@ -185,15 +185,15 @@ class TestGui:
switch_id = 2
coretlv.session.add_node(SwitchNode, _id=switch_id)
ip_prefix = netaddr.IPNetwork("10.0.0.0/24")
interface1_ip4 = str(ip_prefix[node1_id])
iface1_ip4 = str(ip_prefix[node1_id])
message = coreapi.CoreLinkMessage.create(
MessageFlags.ADD.value,
[
(LinkTlvs.N1_NUMBER, node1_id),
(LinkTlvs.N2_NUMBER, switch_id),
(LinkTlvs.INTERFACE1_NUMBER, 0),
(LinkTlvs.INTERFACE1_IP4, interface1_ip4),
(LinkTlvs.INTERFACE1_IP4_MASK, 24),
(LinkTlvs.IFACE1_NUMBER, 0),
(LinkTlvs.IFACE1_IP4, iface1_ip4),
(LinkTlvs.IFACE1_IP4_MASK, 24),
],
)
coretlv.handle_message(message)
@ -201,7 +201,7 @@ class TestGui:
all_links = switch_node.all_link_data()
assert len(all_links) == 1
link = all_links[0]
assert link.bandwidth is None
assert link.options.bandwidth is None
bandwidth = 50000
message = coreapi.CoreLinkMessage.create(
@ -209,7 +209,7 @@ class TestGui:
[
(LinkTlvs.N1_NUMBER, node1_id),
(LinkTlvs.N2_NUMBER, switch_id),
(LinkTlvs.INTERFACE1_NUMBER, 0),
(LinkTlvs.IFACE1_NUMBER, 0),
(LinkTlvs.BANDWIDTH, bandwidth),
],
)
@ -219,7 +219,7 @@ class TestGui:
all_links = switch_node.all_link_data()
assert len(all_links) == 1
link = all_links[0]
assert link.bandwidth == bandwidth
assert link.options.bandwidth == bandwidth
def test_link_delete_node_to_node(self, coretlv: CoreHandler):
node1_id = 1
@ -227,18 +227,18 @@ class TestGui:
node2_id = 2
coretlv.session.add_node(CoreNode, _id=node2_id)
ip_prefix = netaddr.IPNetwork("10.0.0.0/24")
interface1_ip4 = str(ip_prefix[node1_id])
interface2_ip4 = str(ip_prefix[node2_id])
iface1_ip4 = str(ip_prefix[node1_id])
iface2_ip4 = str(ip_prefix[node2_id])
message = coreapi.CoreLinkMessage.create(
MessageFlags.ADD.value,
[
(LinkTlvs.N1_NUMBER, node1_id),
(LinkTlvs.N2_NUMBER, node2_id),
(LinkTlvs.INTERFACE1_NUMBER, 0),
(LinkTlvs.INTERFACE1_IP4, interface1_ip4),
(LinkTlvs.INTERFACE1_IP4_MASK, 24),
(LinkTlvs.INTERFACE2_IP4, interface2_ip4),
(LinkTlvs.INTERFACE2_IP4_MASK, 24),
(LinkTlvs.IFACE1_NUMBER, 0),
(LinkTlvs.IFACE1_IP4, iface1_ip4),
(LinkTlvs.IFACE1_IP4_MASK, 24),
(LinkTlvs.IFACE2_IP4, iface2_ip4),
(LinkTlvs.IFACE2_IP4_MASK, 24),
],
)
coretlv.handle_message(message)
@ -253,8 +253,8 @@ class TestGui:
[
(LinkTlvs.N1_NUMBER, node1_id),
(LinkTlvs.N2_NUMBER, node2_id),
(LinkTlvs.INTERFACE1_NUMBER, 0),
(LinkTlvs.INTERFACE2_NUMBER, 0),
(LinkTlvs.IFACE1_NUMBER, 0),
(LinkTlvs.IFACE2_NUMBER, 0),
],
)
coretlv.handle_message(message)
@ -271,15 +271,15 @@ class TestGui:
switch_id = 2
coretlv.session.add_node(SwitchNode, _id=switch_id)
ip_prefix = netaddr.IPNetwork("10.0.0.0/24")
interface1_ip4 = str(ip_prefix[node1_id])
iface1_ip4 = str(ip_prefix[node1_id])
message = coreapi.CoreLinkMessage.create(
MessageFlags.ADD.value,
[
(LinkTlvs.N1_NUMBER, node1_id),
(LinkTlvs.N2_NUMBER, switch_id),
(LinkTlvs.INTERFACE1_NUMBER, 0),
(LinkTlvs.INTERFACE1_IP4, interface1_ip4),
(LinkTlvs.INTERFACE1_IP4_MASK, 24),
(LinkTlvs.IFACE1_NUMBER, 0),
(LinkTlvs.IFACE1_IP4, iface1_ip4),
(LinkTlvs.IFACE1_IP4_MASK, 24),
],
)
coretlv.handle_message(message)
@ -292,7 +292,7 @@ class TestGui:
[
(LinkTlvs.N1_NUMBER, node1_id),
(LinkTlvs.N2_NUMBER, switch_id),
(LinkTlvs.INTERFACE1_NUMBER, 0),
(LinkTlvs.IFACE1_NUMBER, 0),
],
)
coretlv.handle_message(message)
@ -307,15 +307,15 @@ class TestGui:
switch_id = 2
coretlv.session.add_node(SwitchNode, _id=switch_id)
ip_prefix = netaddr.IPNetwork("10.0.0.0/24")
interface1_ip4 = str(ip_prefix[node1_id])
iface1_ip4 = str(ip_prefix[node1_id])
message = coreapi.CoreLinkMessage.create(
MessageFlags.ADD.value,
[
(LinkTlvs.N1_NUMBER, node1_id),
(LinkTlvs.N2_NUMBER, switch_id),
(LinkTlvs.INTERFACE1_NUMBER, 0),
(LinkTlvs.INTERFACE1_IP4, interface1_ip4),
(LinkTlvs.INTERFACE1_IP4_MASK, 24),
(LinkTlvs.IFACE1_NUMBER, 0),
(LinkTlvs.IFACE1_IP4, iface1_ip4),
(LinkTlvs.IFACE1_IP4_MASK, 24),
],
)
coretlv.handle_message(message)
@ -328,7 +328,7 @@ class TestGui:
[
(LinkTlvs.N1_NUMBER, switch_id),
(LinkTlvs.N2_NUMBER, node1_id),
(LinkTlvs.INTERFACE2_NUMBER, 0),
(LinkTlvs.IFACE2_NUMBER, 0),
],
)
coretlv.handle_message(message)

View file

@ -1,6 +1,6 @@
from typing import Tuple
from core.emulator.emudata import IpPrefixes, LinkOptions
from core.emulator.data import IpPrefixes, LinkOptions
from core.emulator.session import Session
from core.nodes.base import CoreNode
from core.nodes.network import SwitchNode
@ -14,9 +14,9 @@ def create_ptp_network(
node2 = session.add_node(CoreNode)
# link nodes to net node
interface1_data = ip_prefixes.create_interface(node1)
interface2_data = ip_prefixes.create_interface(node2)
session.add_link(node1.id, node2.id, interface1_data, interface2_data)
iface1_data = ip_prefixes.create_iface(node1)
iface2_data = ip_prefixes.create_iface(node2)
session.add_link(node1.id, node2.id, iface1_data, iface2_data)
# instantiate session
session.instantiate()
@ -29,41 +29,41 @@ class TestLinks:
# given
node1 = session.add_node(CoreNode)
node2 = session.add_node(CoreNode)
interface1_data = ip_prefixes.create_interface(node1)
interface2_data = ip_prefixes.create_interface(node2)
iface1_data = ip_prefixes.create_iface(node1)
iface2_data = ip_prefixes.create_iface(node2)
# when
session.add_link(node1.id, node2.id, interface1_data, interface2_data)
session.add_link(node1.id, node2.id, iface1_data, iface2_data)
# then
assert node1.netif(interface1_data.id)
assert node2.netif(interface2_data.id)
assert node1.get_iface(iface1_data.id)
assert node2.get_iface(iface2_data.id)
def test_add_node_to_net(self, session: Session, ip_prefixes: IpPrefixes):
# given
node1 = session.add_node(CoreNode)
node2 = session.add_node(SwitchNode)
interface1_data = ip_prefixes.create_interface(node1)
iface1_data = ip_prefixes.create_iface(node1)
# when
session.add_link(node1.id, node2.id, interface1_data=interface1_data)
session.add_link(node1.id, node2.id, iface1_data=iface1_data)
# then
assert node2.all_link_data()
assert node1.netif(interface1_data.id)
assert node1.get_iface(iface1_data.id)
def test_add_net_to_node(self, session: Session, ip_prefixes: IpPrefixes):
# given
node1 = session.add_node(SwitchNode)
node2 = session.add_node(CoreNode)
interface2_data = ip_prefixes.create_interface(node2)
iface2_data = ip_prefixes.create_iface(node2)
# when
session.add_link(node1.id, node2.id, interface2_data=interface2_data)
session.add_link(node1.id, node2.id, iface2_data=iface2_data)
# then
assert node1.all_link_data()
assert node2.netif(interface2_data.id)
assert node2.get_iface(iface2_data.id)
def test_add_net_to_net(self, session):
# given
@ -85,29 +85,29 @@ class TestLinks:
jitter = 10
node1 = session.add_node(CoreNode)
node2 = session.add_node(SwitchNode)
interface1_data = ip_prefixes.create_interface(node1)
session.add_link(node1.id, node2.id, interface1_data)
interface1 = node1.netif(interface1_data.id)
assert interface1.getparam("delay") != delay
assert interface1.getparam("bw") != bandwidth
assert interface1.getparam("loss") != loss
assert interface1.getparam("duplicate") != dup
assert interface1.getparam("jitter") != jitter
iface1_data = ip_prefixes.create_iface(node1)
session.add_link(node1.id, node2.id, iface1_data)
iface1 = node1.get_iface(iface1_data.id)
assert iface1.getparam("delay") != delay
assert iface1.getparam("bw") != bandwidth
assert iface1.getparam("loss") != loss
assert iface1.getparam("duplicate") != dup
assert iface1.getparam("jitter") != jitter
# when
options = LinkOptions(
delay=delay, bandwidth=bandwidth, loss=loss, dup=dup, jitter=jitter
)
session.update_link(
node1.id, node2.id, interface1_id=interface1_data.id, options=options
node1.id, node2.id, iface1_id=iface1_data.id, options=options
)
# then
assert interface1.getparam("delay") == delay
assert interface1.getparam("bw") == bandwidth
assert interface1.getparam("loss") == loss
assert interface1.getparam("duplicate") == dup
assert interface1.getparam("jitter") == jitter
assert iface1.getparam("delay") == delay
assert iface1.getparam("bw") == bandwidth
assert iface1.getparam("loss") == loss
assert iface1.getparam("duplicate") == dup
assert iface1.getparam("jitter") == jitter
def test_update_net_to_node(self, session: Session, ip_prefixes: IpPrefixes):
# given
@ -118,29 +118,29 @@ class TestLinks:
jitter = 10
node1 = session.add_node(SwitchNode)
node2 = session.add_node(CoreNode)
interface2_data = ip_prefixes.create_interface(node2)
session.add_link(node1.id, node2.id, interface2_data=interface2_data)
interface2 = node2.netif(interface2_data.id)
assert interface2.getparam("delay") != delay
assert interface2.getparam("bw") != bandwidth
assert interface2.getparam("loss") != loss
assert interface2.getparam("duplicate") != dup
assert interface2.getparam("jitter") != jitter
iface2_data = ip_prefixes.create_iface(node2)
session.add_link(node1.id, node2.id, iface2_data=iface2_data)
iface2 = node2.get_iface(iface2_data.id)
assert iface2.getparam("delay") != delay
assert iface2.getparam("bw") != bandwidth
assert iface2.getparam("loss") != loss
assert iface2.getparam("duplicate") != dup
assert iface2.getparam("jitter") != jitter
# when
options = LinkOptions(
delay=delay, bandwidth=bandwidth, loss=loss, dup=dup, jitter=jitter
)
session.update_link(
node1.id, node2.id, interface2_id=interface2_data.id, options=options
node1.id, node2.id, iface2_id=iface2_data.id, options=options
)
# then
assert interface2.getparam("delay") == delay
assert interface2.getparam("bw") == bandwidth
assert interface2.getparam("loss") == loss
assert interface2.getparam("duplicate") == dup
assert interface2.getparam("jitter") == jitter
assert iface2.getparam("delay") == delay
assert iface2.getparam("bw") == bandwidth
assert iface2.getparam("loss") == loss
assert iface2.getparam("duplicate") == dup
assert iface2.getparam("jitter") == jitter
def test_update_ptp(self, session: Session, ip_prefixes: IpPrefixes):
# given
@ -151,83 +151,81 @@ class TestLinks:
jitter = 10
node1 = session.add_node(CoreNode)
node2 = session.add_node(CoreNode)
interface1_data = ip_prefixes.create_interface(node1)
interface2_data = ip_prefixes.create_interface(node2)
session.add_link(node1.id, node2.id, interface1_data, interface2_data)
interface1 = node1.netif(interface1_data.id)
interface2 = node2.netif(interface2_data.id)
assert interface1.getparam("delay") != delay
assert interface1.getparam("bw") != bandwidth
assert interface1.getparam("loss") != loss
assert interface1.getparam("duplicate") != dup
assert interface1.getparam("jitter") != jitter
assert interface2.getparam("delay") != delay
assert interface2.getparam("bw") != bandwidth
assert interface2.getparam("loss") != loss
assert interface2.getparam("duplicate") != dup
assert interface2.getparam("jitter") != jitter
iface1_data = ip_prefixes.create_iface(node1)
iface2_data = ip_prefixes.create_iface(node2)
session.add_link(node1.id, node2.id, iface1_data, iface2_data)
iface1 = node1.get_iface(iface1_data.id)
iface2 = node2.get_iface(iface2_data.id)
assert iface1.getparam("delay") != delay
assert iface1.getparam("bw") != bandwidth
assert iface1.getparam("loss") != loss
assert iface1.getparam("duplicate") != dup
assert iface1.getparam("jitter") != jitter
assert iface2.getparam("delay") != delay
assert iface2.getparam("bw") != bandwidth
assert iface2.getparam("loss") != loss
assert iface2.getparam("duplicate") != dup
assert iface2.getparam("jitter") != jitter
# when
options = LinkOptions(
delay=delay, bandwidth=bandwidth, loss=loss, dup=dup, jitter=jitter
)
session.update_link(
node1.id, node2.id, interface1_data.id, interface2_data.id, options
)
session.update_link(node1.id, node2.id, iface1_data.id, iface2_data.id, options)
# then
assert interface1.getparam("delay") == delay
assert interface1.getparam("bw") == bandwidth
assert interface1.getparam("loss") == loss
assert interface1.getparam("duplicate") == dup
assert interface1.getparam("jitter") == jitter
assert interface2.getparam("delay") == delay
assert interface2.getparam("bw") == bandwidth
assert interface2.getparam("loss") == loss
assert interface2.getparam("duplicate") == dup
assert interface2.getparam("jitter") == jitter
assert iface1.getparam("delay") == delay
assert iface1.getparam("bw") == bandwidth
assert iface1.getparam("loss") == loss
assert iface1.getparam("duplicate") == dup
assert iface1.getparam("jitter") == jitter
assert iface2.getparam("delay") == delay
assert iface2.getparam("bw") == bandwidth
assert iface2.getparam("loss") == loss
assert iface2.getparam("duplicate") == dup
assert iface2.getparam("jitter") == jitter
def test_delete_ptp(self, session: Session, ip_prefixes: IpPrefixes):
# given
node1 = session.add_node(CoreNode)
node2 = session.add_node(CoreNode)
interface1_data = ip_prefixes.create_interface(node1)
interface2_data = ip_prefixes.create_interface(node2)
session.add_link(node1.id, node2.id, interface1_data, interface2_data)
assert node1.netif(interface1_data.id)
assert node2.netif(interface2_data.id)
iface1_data = ip_prefixes.create_iface(node1)
iface2_data = ip_prefixes.create_iface(node2)
session.add_link(node1.id, node2.id, iface1_data, iface2_data)
assert node1.get_iface(iface1_data.id)
assert node2.get_iface(iface2_data.id)
# when
session.delete_link(node1.id, node2.id, interface1_data.id, interface2_data.id)
session.delete_link(node1.id, node2.id, iface1_data.id, iface2_data.id)
# then
assert not node1.netif(interface1_data.id)
assert not node2.netif(interface2_data.id)
assert iface1_data.id not in node1.ifaces
assert iface2_data.id not in node2.ifaces
def test_delete_node_to_net(self, session: Session, ip_prefixes: IpPrefixes):
# given
node1 = session.add_node(CoreNode)
node2 = session.add_node(SwitchNode)
interface1_data = ip_prefixes.create_interface(node1)
session.add_link(node1.id, node2.id, interface1_data)
assert node1.netif(interface1_data.id)
iface1_data = ip_prefixes.create_iface(node1)
session.add_link(node1.id, node2.id, iface1_data)
assert node1.get_iface(iface1_data.id)
# when
session.delete_link(node1.id, node2.id, interface1_id=interface1_data.id)
session.delete_link(node1.id, node2.id, iface1_id=iface1_data.id)
# then
assert not node1.netif(interface1_data.id)
assert iface1_data.id not in node1.ifaces
def test_delete_net_to_node(self, session: Session, ip_prefixes: IpPrefixes):
# given
node1 = session.add_node(SwitchNode)
node2 = session.add_node(CoreNode)
interface2_data = ip_prefixes.create_interface(node2)
session.add_link(node1.id, node2.id, interface2_data=interface2_data)
assert node2.netif(interface2_data.id)
iface2_data = ip_prefixes.create_iface(node2)
session.add_link(node1.id, node2.id, iface2_data=iface2_data)
assert node2.get_iface(iface2_data.id)
# when
session.delete_link(node1.id, node2.id, interface2_id=interface2_data.id)
session.delete_link(node1.id, node2.id, iface2_id=iface2_data.id)
# then
assert not node2.netif(interface2_data.id)
assert iface2_data.id not in node2.ifaces

View file

@ -1,6 +1,6 @@
import pytest
from core.emulator.emudata import InterfaceData, NodeOptions
from core.emulator.data import InterfaceData, NodeOptions
from core.emulator.session import Session
from core.errors import CoreError
from core.nodes.base import CoreNode
@ -49,57 +49,57 @@ class TestNodes:
with pytest.raises(CoreError):
session.get_node(node.id, CoreNode)
def test_node_sethwaddr(self, session: Session):
def test_node_set_mac(self, session: Session):
# given
node = session.add_node(CoreNode)
switch = session.add_node(SwitchNode)
interface_data = InterfaceData()
interface = node.newnetif(switch, interface_data)
iface_data = InterfaceData()
iface = node.new_iface(switch, iface_data)
mac = "aa:aa:aa:ff:ff:ff"
# when
node.sethwaddr(interface.netindex, mac)
node.set_mac(iface.node_id, mac)
# then
assert interface.hwaddr == mac
assert iface.mac == mac
def test_node_sethwaddr_exception(self, session: Session):
def test_node_set_mac_exception(self, session: Session):
# given
node = session.add_node(CoreNode)
switch = session.add_node(SwitchNode)
interface_data = InterfaceData()
interface = node.newnetif(switch, interface_data)
iface_data = InterfaceData()
iface = node.new_iface(switch, iface_data)
mac = "aa:aa:aa:ff:ff:fff"
# when
with pytest.raises(CoreError):
node.sethwaddr(interface.netindex, mac)
node.set_mac(iface.node_id, mac)
def test_node_addaddr(self, session: Session):
# given
node = session.add_node(CoreNode)
switch = session.add_node(SwitchNode)
interface_data = InterfaceData()
interface = node.newnetif(switch, interface_data)
iface_data = InterfaceData()
iface = node.new_iface(switch, iface_data)
addr = "192.168.0.1/24"
# when
node.addaddr(interface.netindex, addr)
node.addaddr(iface.node_id, addr)
# then
assert interface.addrlist[0] == addr
assert iface.addrlist[0] == addr
def test_node_addaddr_exception(self, session):
# given
node = session.add_node(CoreNode)
switch = session.add_node(SwitchNode)
interface_data = InterfaceData()
interface = node.newnetif(switch, interface_data)
iface_data = InterfaceData()
iface = node.new_iface(switch, iface_data)
addr = "256.168.0.1/24"
# when
with pytest.raises(CoreError):
node.addaddr(interface.netindex, addr)
node.addaddr(iface.node_id, addr)
@pytest.mark.parametrize("net_type", NET_TYPES)
def test_net(self, session, net_type):

View file

@ -3,7 +3,7 @@ from xml.etree import ElementTree
import pytest
from core.emulator.emudata import IpPrefixes, LinkOptions, NodeOptions
from core.emulator.data import IpPrefixes, LinkOptions, NodeOptions
from core.emulator.enumerations import EventTypes
from core.emulator.session import Session
from core.errors import CoreError
@ -73,8 +73,8 @@ class TestXml:
# link nodes to ptp net
for node in [node1, node2]:
interface = ip_prefixes.create_interface(node)
session.add_link(node.id, ptp_node.id, interface1_data=interface)
iface_data = ip_prefixes.create_iface(node)
session.add_link(node.id, ptp_node.id, iface1_data=iface_data)
# instantiate session
session.instantiate()
@ -128,8 +128,8 @@ class TestXml:
# link nodes to ptp net
for node in [node1, node2]:
interface = ip_prefixes.create_interface(node)
session.add_link(node.id, ptp_node.id, interface1_data=interface)
iface_data = ip_prefixes.create_iface(node)
session.add_link(node.id, ptp_node.id, iface1_data=iface_data)
# set custom values for node service
session.services.set_service(node1.id, SshService.name)
@ -197,8 +197,8 @@ class TestXml:
# link nodes
for node in [node1, node2]:
interface = ip_prefixes.create_interface(node)
session.add_link(node.id, wlan_node.id, interface1_data=interface)
iface_data = ip_prefixes.create_iface(node)
session.add_link(node.id, wlan_node.id, iface1_data=iface_data)
# instantiate session
session.instantiate()
@ -299,7 +299,7 @@ class TestXml:
"""
# create nodes
node1 = session.add_node(CoreNode)
interface1_data = ip_prefixes.create_interface(node1)
iface1_data = ip_prefixes.create_iface(node1)
switch = session.add_node(SwitchNode)
# create link
@ -309,7 +309,7 @@ class TestXml:
options.jitter = 10
options.delay = 30
options.dup = 5
session.add_link(node1.id, switch.id, interface1_data, options=options)
session.add_link(node1.id, switch.id, iface1_data, options=options)
# instantiate session
session.instantiate()
@ -347,11 +347,11 @@ class TestXml:
node = session.nodes[node_id]
links += node.all_link_data()
link = links[0]
assert options.loss == link.loss
assert options.bandwidth == link.bandwidth
assert options.jitter == link.jitter
assert options.delay == link.delay
assert options.dup == link.dup
assert options.loss == link.options.loss
assert options.bandwidth == link.options.bandwidth
assert options.jitter == link.options.jitter
assert options.delay == link.options.delay
assert options.dup == link.options.dup
def test_link_options_ptp(
self, session: Session, tmpdir: TemporaryFile, ip_prefixes: IpPrefixes
@ -365,9 +365,9 @@ class TestXml:
"""
# create nodes
node1 = session.add_node(CoreNode)
interface1_data = ip_prefixes.create_interface(node1)
iface1_data = ip_prefixes.create_iface(node1)
node2 = session.add_node(CoreNode)
interface2_data = ip_prefixes.create_interface(node2)
iface2_data = ip_prefixes.create_iface(node2)
# create link
options = LinkOptions()
@ -376,7 +376,7 @@ class TestXml:
options.jitter = 10
options.delay = 30
options.dup = 5
session.add_link(node1.id, node2.id, interface1_data, interface2_data, options)
session.add_link(node1.id, node2.id, iface1_data, iface2_data, options)
# instantiate session
session.instantiate()
@ -414,11 +414,11 @@ class TestXml:
node = session.nodes[node_id]
links += node.all_link_data()
link = links[0]
assert options.loss == link.loss
assert options.bandwidth == link.bandwidth
assert options.jitter == link.jitter
assert options.delay == link.delay
assert options.dup == link.dup
assert options.loss == link.options.loss
assert options.bandwidth == link.options.bandwidth
assert options.jitter == link.options.jitter
assert options.delay == link.options.delay
assert options.dup == link.options.dup
def test_link_options_bidirectional(
self, session: Session, tmpdir: TemporaryFile, ip_prefixes: IpPrefixes
@ -432,9 +432,9 @@ class TestXml:
"""
# create nodes
node1 = session.add_node(CoreNode)
interface1_data = ip_prefixes.create_interface(node1)
iface1_data = ip_prefixes.create_iface(node1)
node2 = session.add_node(CoreNode)
interface2_data = ip_prefixes.create_interface(node2)
iface2_data = ip_prefixes.create_iface(node2)
# create link
options1 = LinkOptions()
@ -444,7 +444,7 @@ class TestXml:
options1.loss = 10.5
options1.dup = 5
options1.jitter = 5
session.add_link(node1.id, node2.id, interface1_data, interface2_data, options1)
session.add_link(node1.id, node2.id, iface1_data, iface2_data, options1)
options2 = LinkOptions()
options2.unidirectional = 1
options2.bandwidth = 10000
@ -453,7 +453,7 @@ class TestXml:
options2.dup = 10
options2.jitter = 10
session.update_link(
node2.id, node1.id, interface2_data.id, interface1_data.id, options2
node2.id, node1.id, iface2_data.id, iface1_data.id, options2
)
# instantiate session
@ -494,13 +494,13 @@ class TestXml:
assert len(links) == 2
link1 = links[0]
link2 = links[1]
assert options1.bandwidth == link1.bandwidth
assert options1.delay == link1.delay
assert options1.loss == link1.loss
assert options1.dup == link1.dup
assert options1.jitter == link1.jitter
assert options2.bandwidth == link2.bandwidth
assert options2.delay == link2.delay
assert options2.loss == link2.loss
assert options2.dup == link2.dup
assert options2.jitter == link2.jitter
assert options1.bandwidth == link1.options.bandwidth
assert options1.delay == link1.options.delay
assert options1.loss == link1.options.loss
assert options1.dup == link1.options.dup
assert options1.jitter == link1.options.jitter
assert options2.bandwidth == link2.options.bandwidth
assert options2.delay == link2.options.delay
assert options2.loss == link2.options.loss
assert options2.dup == link2.options.dup
assert options2.jitter == link2.options.jitter

View file

@ -36,7 +36,7 @@ interact with the GUI.
import logging
from core.emulator.coreemu import CoreEmu
from core.emulator.emudata import IpPrefixes
from core.emulator.data import IpPrefixes
from core.emulator.enumerations import EventTypes
from core.nodes.base import CoreNode
from core.nodes.network import SwitchNode
@ -61,8 +61,8 @@ def main():
# create nodes
for _ in range(NODES):
node = session.add_node(CoreNode)
interface = prefixes.create_interface(node)
session.add_link(node.id, switch.id, interface1_data=interface)
interface = prefixes.create_iface(node)
session.add_link(node.id, switch.id, iface1_data=interface)
# instantiate session
session.instantiate()

View file

@ -263,7 +263,7 @@ class MyService(CoreService):
if filename == cls.configs[0]:
cfg += "# auto-generated by MyService (sample.py)\n"
for ifc in node.netifs():
for ifc in node.get_ifaces():
cfg += f'echo "Node {node.name} has interface {ifc.name}"\n'
elif filename == cls.configs[1]:
cfg += "echo hello"