Merge pull request #472 from coreemu/cleanup/interfaces-to-iface
interface and related functions renaming
This commit is contained in:
commit
250bc6e1f5
96 changed files with 2388 additions and 2758 deletions
daemon
core
api
grpc
tlv
configservices
frrservices
nrlservices
quaggaservices
sercurityservices
utilservices
emane
emulator
gui
location
nodes
plugins
services
xml
examples
configservices
docker
grpc
lxd
myservices
python
proto/core/api/grpc
scripts
tests
docs
|
@ -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.
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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()
|
||||
|
|
|
@ -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,
|
||||
}
|
||||
|
|
|
@ -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,
|
||||
}
|
||||
|
|
|
@ -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),
|
||||
],
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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}"
|
||||
|
|
|
@ -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}
|
||||
|
|
|
@ -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}
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
<%
|
||||
interfaces = "-i " + " -i ".join(ifnames)
|
||||
ifaces = "-i " + " -i ".join(ifnames)
|
||||
%>
|
||||
olsrd ${interfaces}
|
||||
olsrd ${ifaces}
|
||||
|
|
|
@ -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 &
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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>
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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
|
|
@ -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}")
|
||||
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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()
|
||||
|
||||
|
|
|
@ -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()
|
||||
|
|
|
@ -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()
|
||||
|
|
|
@ -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()
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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:
|
||||
|
|
|
@ -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(
|
||||
|
|
|
@ -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:
|
||||
|
|
|
@ -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:
|
||||
|
|
|
@ -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",
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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
|
||||
|
||||
|
||||
|
|
|
@ -141,7 +141,7 @@ class DockerNode(CoreNode):
|
|||
return
|
||||
|
||||
with self.lock:
|
||||
self._netif.clear()
|
||||
self.ifaces.clear()
|
||||
self.client.stop_container()
|
||||
self.up = False
|
||||
|
||||
|
|
|
@ -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 []
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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:
|
||||
"""
|
||||
|
|
|
@ -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]:
|
||||
"""
|
||||
|
|
|
@ -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")
|
||||
|
|
|
@ -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:
|
||||
"""
|
||||
|
|
|
@ -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"
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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"
|
||||
|
|
|
@ -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"
|
||||
|
|
|
@ -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"
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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 == "":
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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"
|
||||
|
|
|
@ -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()
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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)
|
||||
|
||||
|
|
|
@ -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)
|
||||
|
||||
|
|
|
@ -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)
|
||||
|
||||
|
|
|
@ -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)
|
||||
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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"
|
||||
|
||||
|
|
|
@ -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()
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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()
|
||||
|
|
|
@ -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()
|
||||
|
|
|
@ -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()
|
||||
|
|
|
@ -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()
|
||||
|
|
|
@ -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()
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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 {
|
||||
|
|
|
@ -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:
|
||||
|
|
|
@ -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")
|
||||
|
||||
|
||||
|
|
|
@ -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()
|
||||
|
|
|
@ -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 = {
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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):
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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()
|
||||
|
|
|
@ -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"
|
||||
|
|
Loading…
Add table
Reference in a new issue