daemon: update CoreNode.newnetif to require parameters, CoreNode.newnetif now depends on being provided InterfaceData
This commit is contained in:
parent
3691c6029f
commit
3be15a1316
5 changed files with 71 additions and 130 deletions
|
@ -1,18 +1,22 @@
|
|||
from dataclasses import dataclass, field
|
||||
from typing import List, Optional, Union
|
||||
from typing import TYPE_CHECKING, List, Optional, Union
|
||||
|
||||
import netaddr
|
||||
|
||||
from core import utils
|
||||
from core.api.grpc.core_pb2 import LinkOptions
|
||||
from core.emulator.enumerations import LinkTypes
|
||||
from core.nodes.base import CoreNetworkBase, CoreNode
|
||||
from core.nodes.interface import CoreInterface
|
||||
from core.nodes.physical import PhysicalNode
|
||||
|
||||
if TYPE_CHECKING:
|
||||
from core.nodes.base import CoreNetworkBase, CoreNode
|
||||
from core.nodes.physical import PhysicalNode
|
||||
|
||||
LinkConfigNode = Union[CoreNetworkBase, PhysicalNode]
|
||||
|
||||
|
||||
def link_config(
|
||||
node: Union[CoreNetworkBase, PhysicalNode],
|
||||
node: "LinkConfigNode",
|
||||
interface: CoreInterface,
|
||||
link_options: LinkOptions,
|
||||
interface_two: CoreInterface = None,
|
||||
|
@ -160,7 +164,7 @@ class IpPrefixes:
|
|||
if ip6_prefix:
|
||||
self.ip6 = netaddr.IPNetwork(ip6_prefix)
|
||||
|
||||
def ip4_address(self, node: CoreNode) -> str:
|
||||
def ip4_address(self, node: "CoreNode") -> str:
|
||||
"""
|
||||
Convenience method to return the IP4 address for a node.
|
||||
|
||||
|
@ -171,7 +175,7 @@ class IpPrefixes:
|
|||
raise ValueError("ip4 prefixes have not been set")
|
||||
return str(self.ip4[node.id])
|
||||
|
||||
def ip6_address(self, node: CoreNode) -> str:
|
||||
def ip6_address(self, node: "CoreNode") -> str:
|
||||
"""
|
||||
Convenience method to return the IP6 address for a node.
|
||||
|
||||
|
@ -183,7 +187,7 @@ class IpPrefixes:
|
|||
return str(self.ip6[node.id])
|
||||
|
||||
def create_interface(
|
||||
self, node: CoreNode, name: str = None, mac: str = None
|
||||
self, node: "CoreNode", name: str = None, mac: str = None
|
||||
) -> InterfaceData:
|
||||
"""
|
||||
Creates interface data for linking nodes, using the nodes unique id for
|
||||
|
@ -225,24 +229,3 @@ class IpPrefixes:
|
|||
ip6_mask=ip6_mask,
|
||||
mac=mac,
|
||||
)
|
||||
|
||||
|
||||
def create_interface(
|
||||
node: CoreNode, network: CoreNetworkBase, interface_data: InterfaceData
|
||||
):
|
||||
"""
|
||||
Create an interface for a node on a network using provided interface data.
|
||||
|
||||
:param node: node to create interface for
|
||||
:param network: network to associate interface with
|
||||
:param interface_data: interface data
|
||||
:return: created interface
|
||||
"""
|
||||
node.newnetif(
|
||||
network,
|
||||
addrlist=interface_data.get_addresses(),
|
||||
hwaddr=interface_data.mac,
|
||||
ifindex=interface_data.id,
|
||||
ifname=interface_data.name,
|
||||
)
|
||||
return node.netif(interface_data.id)
|
||||
|
|
|
@ -19,13 +19,7 @@ from core.emane.emanemanager import EmaneManager
|
|||
from core.emane.nodes import EmaneNet
|
||||
from core.emulator.data import ConfigData, EventData, ExceptionData, FileData, LinkData
|
||||
from core.emulator.distributed import DistributedController
|
||||
from core.emulator.emudata import (
|
||||
InterfaceData,
|
||||
LinkOptions,
|
||||
NodeOptions,
|
||||
create_interface,
|
||||
link_config,
|
||||
)
|
||||
from core.emulator.emudata import InterfaceData, LinkOptions, NodeOptions, link_config
|
||||
from core.emulator.enumerations import (
|
||||
EventTypes,
|
||||
ExceptionLevels,
|
||||
|
@ -360,11 +354,11 @@ class Session:
|
|||
node_one.name,
|
||||
net_one.name,
|
||||
)
|
||||
interface = create_interface(node_one, net_one, interface_one)
|
||||
node_one_interface = interface
|
||||
ifindex = node_one.newnetif(net_one, interface_one)
|
||||
node_one_interface = node_one.netif(ifindex)
|
||||
wireless_net = isinstance(net_one, (EmaneNet, WlanNode))
|
||||
if not wireless_net:
|
||||
link_config(net_one, interface, link_options)
|
||||
link_config(net_one, node_one_interface, link_options)
|
||||
|
||||
# network to node
|
||||
if node_two and net_one:
|
||||
|
@ -373,11 +367,11 @@ class Session:
|
|||
node_two.name,
|
||||
net_one.name,
|
||||
)
|
||||
interface = create_interface(node_two, net_one, interface_two)
|
||||
node_two_interface = interface
|
||||
ifindex = node_two.newnetif(net_one, interface_two)
|
||||
node_two_interface = node_two.netif(ifindex)
|
||||
wireless_net = isinstance(net_one, (EmaneNet, WlanNode))
|
||||
if not link_options.unidirectional and not wireless_net:
|
||||
link_config(net_one, interface, link_options)
|
||||
link_config(net_one, node_two_interface, link_options)
|
||||
|
||||
# network to network
|
||||
if net_one and net_two:
|
||||
|
@ -1797,35 +1791,28 @@ class Session:
|
|||
control_net = self.add_remove_control_net(net_index, remove, conf_required)
|
||||
if not control_net:
|
||||
return
|
||||
|
||||
if not node:
|
||||
return
|
||||
|
||||
# ctrl# already exists
|
||||
if node.netif(control_net.CTRLIF_IDX_BASE + net_index):
|
||||
return
|
||||
|
||||
control_ip = node.id
|
||||
|
||||
try:
|
||||
address = control_net.prefix[control_ip]
|
||||
prefix = control_net.prefix.prefixlen
|
||||
addrlist = [f"{address}/{prefix}"]
|
||||
ip4 = control_net.prefix[node.id]
|
||||
ip4_mask = control_net.prefix.prefixlen
|
||||
interface = InterfaceData(
|
||||
id=control_net.CTRLIF_IDX_BASE + net_index,
|
||||
name=f"ctrl{net_index}",
|
||||
mac=utils.random_mac(),
|
||||
ip4=ip4,
|
||||
ip4_mask=ip4_mask,
|
||||
)
|
||||
ifindex = node.newnetif(control_net, interface)
|
||||
node.netif(ifindex).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)
|
||||
return
|
||||
|
||||
interface1 = node.newnetif(
|
||||
net=control_net,
|
||||
ifindex=control_net.CTRLIF_IDX_BASE + net_index,
|
||||
ifname=f"ctrl{net_index}",
|
||||
hwaddr=utils.random_mac(),
|
||||
addrlist=addrlist,
|
||||
)
|
||||
node.netif(interface1).control = True
|
||||
|
||||
def update_control_interface_hosts(
|
||||
self, net_index: int = 0, remove: bool = False
|
||||
|
|
|
@ -15,6 +15,7 @@ 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
|
||||
from core.emulator.enumerations import LinkTypes, MessageFlags, NodeTypes
|
||||
from core.errors import CoreCommandError, CoreError
|
||||
from core.nodes.client import VnodeClient
|
||||
|
@ -845,53 +846,36 @@ class CoreNode(CoreNodeBase):
|
|||
interface_name = self.ifname(ifindex)
|
||||
self.node_net_client.device_up(interface_name)
|
||||
|
||||
def newnetif(
|
||||
self,
|
||||
net: "CoreNetworkBase" = None,
|
||||
addrlist: List[str] = None,
|
||||
hwaddr: str = None,
|
||||
ifindex: int = None,
|
||||
ifname: str = None,
|
||||
) -> int:
|
||||
def newnetif(self, net: "CoreNetworkBase", interface: InterfaceData) -> int:
|
||||
"""
|
||||
Create a new network interface.
|
||||
|
||||
:param net: network to associate with
|
||||
:param addrlist: addresses to add on the interface
|
||||
:param hwaddr: hardware address to set for interface
|
||||
:param ifindex: index of interface to create
|
||||
:param ifname: name for interface
|
||||
:param interface: interface data for new interface
|
||||
:return: interface index
|
||||
"""
|
||||
if not addrlist:
|
||||
addrlist = []
|
||||
|
||||
addresses = interface.get_addresses()
|
||||
with self.lock:
|
||||
# TODO: emane specific code
|
||||
if net is not None and net.is_emane is True:
|
||||
ifindex = self.newtuntap(ifindex, ifname)
|
||||
if net.is_emane is True:
|
||||
ifindex = self.newtuntap(interface.id, interface.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(hwaddr)
|
||||
for address in utils.make_tuple(addrlist):
|
||||
netif.sethwaddr(interface.mac)
|
||||
for address in addresses:
|
||||
netif.addaddr(address)
|
||||
return ifindex
|
||||
else:
|
||||
ifindex = self.newveth(ifindex, ifname)
|
||||
|
||||
if net is not None:
|
||||
self.attachnet(ifindex, net)
|
||||
|
||||
if hwaddr:
|
||||
self.sethwaddr(ifindex, hwaddr)
|
||||
|
||||
for address in utils.make_tuple(addrlist):
|
||||
ifindex = self.newveth(interface.id, interface.name)
|
||||
self.attachnet(ifindex, net)
|
||||
if interface.mac:
|
||||
self.sethwaddr(ifindex, interface.mac)
|
||||
for address in addresses:
|
||||
self.addaddr(ifindex, address)
|
||||
|
||||
self.ifup(ifindex)
|
||||
return ifindex
|
||||
|
||||
|
|
|
@ -10,10 +10,11 @@ from typing import IO, TYPE_CHECKING, List, Optional, Tuple
|
|||
from core import utils
|
||||
from core.constants import MOUNT_BIN, UMOUNT_BIN
|
||||
from core.emulator.distributed import DistributedServer
|
||||
from core.emulator.emudata import InterfaceData
|
||||
from core.emulator.enumerations import NodeTypes, TransportType
|
||||
from core.errors import CoreCommandError, CoreError
|
||||
from core.nodes.base import CoreNetworkBase, CoreNodeBase
|
||||
from core.nodes.interface import CoreInterface, Veth
|
||||
from core.nodes.interface import CoreInterface
|
||||
from core.nodes.network import CoreNetwork, GreTap
|
||||
|
||||
if TYPE_CHECKING:
|
||||
|
@ -168,37 +169,25 @@ class PhysicalNode(CoreNodeBase):
|
|||
self.ifindex += 1
|
||||
return ifindex
|
||||
|
||||
def newnetif(
|
||||
self,
|
||||
net: Veth = None,
|
||||
addrlist: List[str] = None,
|
||||
hwaddr: str = None,
|
||||
ifindex: int = None,
|
||||
ifname: str = None,
|
||||
) -> int:
|
||||
def newnetif(self, net: CoreNetworkBase, interface: InterfaceData) -> int:
|
||||
logging.info("creating interface")
|
||||
if not addrlist:
|
||||
addrlist = []
|
||||
|
||||
if self.up and net is None:
|
||||
raise NotImplementedError
|
||||
|
||||
addresses = interface.get_addresses()
|
||||
ifindex = interface.id
|
||||
if ifindex is None:
|
||||
ifindex = self.newifindex()
|
||||
|
||||
if ifname is None:
|
||||
ifname = f"gt{ifindex}"
|
||||
|
||||
name = interface.name
|
||||
if name is None:
|
||||
name = f"gt{ifindex}"
|
||||
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, hwaddr, addrlist)
|
||||
self.adoptnetif(remote_tap, ifindex, interface.mac, addresses)
|
||||
return ifindex
|
||||
else:
|
||||
# this is reached when configuring services (self.up=False)
|
||||
netif = GreTap(node=self, name=ifname, session=self.session, start=False)
|
||||
self.adoptnetif(netif, ifindex, hwaddr, addrlist)
|
||||
netif = GreTap(node=self, name=name, session=self.session, start=False)
|
||||
self.adoptnetif(netif, ifindex, interface.mac, addresses)
|
||||
return ifindex
|
||||
|
||||
def privatedir(self, path: str) -> None:
|
||||
|
@ -320,28 +309,19 @@ class Rj45Node(CoreNodeBase):
|
|||
self.up = False
|
||||
self.restorestate()
|
||||
|
||||
def newnetif(
|
||||
self,
|
||||
net: CoreNetworkBase = None,
|
||||
addrlist: List[str] = None,
|
||||
hwaddr: str = None,
|
||||
ifindex: int = None,
|
||||
ifname: str = None,
|
||||
) -> int:
|
||||
def newnetif(self, net: CoreNetworkBase, interface: InterfaceData) -> int:
|
||||
"""
|
||||
This is called when linking with another node. Since this node
|
||||
represents an interface, we do not create another object here,
|
||||
but attach ourselves to the given network.
|
||||
|
||||
:param net: new network instance
|
||||
:param addrlist: address list
|
||||
:param hwaddr: hardware address
|
||||
:param ifindex: interface index
|
||||
:param ifname: interface name
|
||||
:param interface: interface data for new interface
|
||||
:return: interface index
|
||||
:raises ValueError: when an interface has already been created, one max
|
||||
"""
|
||||
with self.lock:
|
||||
ifindex = interface.id
|
||||
if ifindex is None:
|
||||
ifindex = 0
|
||||
if self.interface.net is not None:
|
||||
|
@ -350,9 +330,8 @@ class Rj45Node(CoreNodeBase):
|
|||
self.ifindex = ifindex
|
||||
if net is not None:
|
||||
self.interface.attachnet(net)
|
||||
if addrlist:
|
||||
for addr in utils.make_tuple(addrlist):
|
||||
self.addaddr(addr)
|
||||
for addr in interface.get_addresses():
|
||||
self.addaddr(addr)
|
||||
return ifindex
|
||||
|
||||
def delnetif(self, ifindex: int) -> None:
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
import pytest
|
||||
|
||||
from core.emulator.emudata import NodeOptions
|
||||
from core.emulator.emudata import InterfaceData, NodeOptions
|
||||
from core.emulator.session import Session
|
||||
from core.errors import CoreError
|
||||
from core.nodes.base import CoreNode
|
||||
|
@ -52,7 +52,9 @@ class TestNodes:
|
|||
def test_node_sethwaddr(self, session: Session):
|
||||
# given
|
||||
node = session.add_node(CoreNode)
|
||||
index = node.newnetif()
|
||||
switch = session.add_node(SwitchNode)
|
||||
interface_data = InterfaceData()
|
||||
index = node.newnetif(switch, interface_data)
|
||||
interface = node.netif(index)
|
||||
mac = "aa:aa:aa:ff:ff:ff"
|
||||
|
||||
|
@ -65,7 +67,9 @@ class TestNodes:
|
|||
def test_node_sethwaddr_exception(self, session: Session):
|
||||
# given
|
||||
node = session.add_node(CoreNode)
|
||||
index = node.newnetif()
|
||||
switch = session.add_node(SwitchNode)
|
||||
interface_data = InterfaceData()
|
||||
index = node.newnetif(switch, interface_data)
|
||||
node.netif(index)
|
||||
mac = "aa:aa:aa:ff:ff:fff"
|
||||
|
||||
|
@ -76,7 +80,9 @@ class TestNodes:
|
|||
def test_node_addaddr(self, session: Session):
|
||||
# given
|
||||
node = session.add_node(CoreNode)
|
||||
index = node.newnetif()
|
||||
switch = session.add_node(SwitchNode)
|
||||
interface_data = InterfaceData()
|
||||
index = node.newnetif(switch, interface_data)
|
||||
interface = node.netif(index)
|
||||
addr = "192.168.0.1/24"
|
||||
|
||||
|
@ -89,7 +95,9 @@ class TestNodes:
|
|||
def test_node_addaddr_exception(self, session):
|
||||
# given
|
||||
node = session.add_node(CoreNode)
|
||||
index = node.newnetif()
|
||||
switch = session.add_node(SwitchNode)
|
||||
interface_data = InterfaceData()
|
||||
index = node.newnetif(switch, interface_data)
|
||||
node.netif(index)
|
||||
addr = "256.168.0.1/24"
|
||||
|
||||
|
|
Loading…
Reference in a new issue