Merge pull request #475 from coreemu/cleanup/interface-addresses
Cleanup/interface addresses
This commit is contained in:
commit
3638b05cd1
22 changed files with 328 additions and 363 deletions
|
@ -3,7 +3,6 @@ import time
|
||||||
from typing import Any, Dict, List, Tuple, Type, Union
|
from typing import Any, Dict, List, Tuple, Type, Union
|
||||||
|
|
||||||
import grpc
|
import grpc
|
||||||
import netaddr
|
|
||||||
from grpc import ServicerContext
|
from grpc import ServicerContext
|
||||||
|
|
||||||
from core import utils
|
from core import utils
|
||||||
|
@ -447,18 +446,16 @@ def iface_to_proto(iface: CoreInterface) -> core_pb2.Interface:
|
||||||
net_id = iface.net.id
|
net_id = iface.net.id
|
||||||
ip4 = None
|
ip4 = None
|
||||||
ip4_mask = None
|
ip4_mask = None
|
||||||
|
ip4_net = iface.get_ip4()
|
||||||
|
if ip4_net:
|
||||||
|
ip4 = str(ip4_net.ip)
|
||||||
|
ip4_mask = ip4_net.prefixlen
|
||||||
ip6 = None
|
ip6 = None
|
||||||
ip6_mask = None
|
ip6_mask = None
|
||||||
for addr in iface.addrlist:
|
ip6_net = iface.get_ip6()
|
||||||
network = netaddr.IPNetwork(addr)
|
if ip6_net:
|
||||||
mask = network.prefixlen
|
ip6 = str(ip6_net.ip)
|
||||||
ip = str(network.ip)
|
ip6_mask = ip6_net.prefixlen
|
||||||
if netaddr.valid_ipv4(ip) and not ip4:
|
|
||||||
ip4 = ip
|
|
||||||
ip4_mask = mask
|
|
||||||
elif netaddr.valid_ipv6(ip) and not ip6:
|
|
||||||
ip6 = ip
|
|
||||||
ip6_mask = mask
|
|
||||||
return core_pb2.Interface(
|
return core_pb2.Interface(
|
||||||
id=iface.node_id,
|
id=iface.node_id,
|
||||||
net_id=net_id,
|
net_id=net_id,
|
||||||
|
|
|
@ -1,8 +1,6 @@
|
||||||
import abc
|
import abc
|
||||||
from typing import Any, Dict, List
|
from typing import Any, Dict, List
|
||||||
|
|
||||||
import netaddr
|
|
||||||
|
|
||||||
from core import constants
|
from core import constants
|
||||||
from core.config import Configuration
|
from core.config import Configuration
|
||||||
from core.configservice.base import ConfigService, ConfigServiceMode
|
from core.configservice.base import ConfigService, ConfigServiceMode
|
||||||
|
@ -49,10 +47,9 @@ def get_router_id(node: CoreNodeBase) -> str:
|
||||||
Helper to return the first IPv4 address of a node as its router ID.
|
Helper to return the first IPv4 address of a node as its router ID.
|
||||||
"""
|
"""
|
||||||
for iface in node.get_ifaces(control=False):
|
for iface in node.get_ifaces(control=False):
|
||||||
for a in iface.addrlist:
|
ip4 = iface.get_ip4()
|
||||||
a = a.split("/")[0]
|
if ip4:
|
||||||
if netaddr.valid_ipv4(a):
|
return str(ip4.ip)
|
||||||
return a
|
|
||||||
return "0.0.0.0"
|
return "0.0.0.0"
|
||||||
|
|
||||||
|
|
||||||
|
@ -102,12 +99,10 @@ class FRRZebra(ConfigService):
|
||||||
for iface in self.node.get_ifaces():
|
for iface in self.node.get_ifaces():
|
||||||
ip4s = []
|
ip4s = []
|
||||||
ip6s = []
|
ip6s = []
|
||||||
for x in iface.addrlist:
|
for ip4 in iface.ip4s:
|
||||||
addr = x.split("/")[0]
|
ip4s.append(str(ip4.ip))
|
||||||
if netaddr.valid_ipv4(addr):
|
for ip6 in iface.ip6s:
|
||||||
ip4s.append(x)
|
ip6s.append(str(ip6.ip))
|
||||||
else:
|
|
||||||
ip6s.append(x)
|
|
||||||
is_control = getattr(iface, "control", False)
|
is_control = getattr(iface, "control", False)
|
||||||
ifaces.append((iface, ip4s, ip6s, is_control))
|
ifaces.append((iface, ip4s, ip6s, is_control))
|
||||||
|
|
||||||
|
@ -163,10 +158,8 @@ class FRROspfv2(FrrService, ConfigService):
|
||||||
router_id = get_router_id(self.node)
|
router_id = get_router_id(self.node)
|
||||||
addresses = []
|
addresses = []
|
||||||
for iface in self.node.get_ifaces(control=False):
|
for iface in self.node.get_ifaces(control=False):
|
||||||
for a in iface.addrlist:
|
for ip4 in iface.ip4s:
|
||||||
addr = a.split("/")[0]
|
addresses.append(str(ip4.ip))
|
||||||
if netaddr.valid_ipv4(addr):
|
|
||||||
addresses.append(a)
|
|
||||||
data = dict(router_id=router_id, addresses=addresses)
|
data = dict(router_id=router_id, addresses=addresses)
|
||||||
text = """
|
text = """
|
||||||
router ospf
|
router ospf
|
||||||
|
|
|
@ -1,7 +1,5 @@
|
||||||
from typing import Any, Dict, List
|
from typing import Any, Dict, List
|
||||||
|
|
||||||
import netaddr
|
|
||||||
|
|
||||||
from core import utils
|
from core import utils
|
||||||
from core.config import Configuration
|
from core.config import Configuration
|
||||||
from core.configservice.base import ConfigService, ConfigServiceMode
|
from core.configservice.base import ConfigService, ConfigServiceMode
|
||||||
|
@ -75,13 +73,10 @@ class NrlSmf(ConfigService):
|
||||||
ip4_prefix = None
|
ip4_prefix = None
|
||||||
for iface in self.node.get_ifaces(control=False):
|
for iface in self.node.get_ifaces(control=False):
|
||||||
ifnames.append(iface.name)
|
ifnames.append(iface.name)
|
||||||
if ip4_prefix:
|
ip4 = iface.get_ip4()
|
||||||
continue
|
if ip4:
|
||||||
for a in iface.addrlist:
|
ip4_prefix = f"{ip4.ip}/{24}"
|
||||||
a = a.split("/")[0]
|
break
|
||||||
if netaddr.valid_ipv4(a):
|
|
||||||
ip4_prefix = f"{a}/{24}"
|
|
||||||
break
|
|
||||||
return dict(
|
return dict(
|
||||||
has_arouted=has_arouted,
|
has_arouted=has_arouted,
|
||||||
has_nhdp=has_nhdp,
|
has_nhdp=has_nhdp,
|
||||||
|
@ -191,11 +186,8 @@ class Arouted(ConfigService):
|
||||||
def data(self) -> Dict[str, Any]:
|
def data(self) -> Dict[str, Any]:
|
||||||
ip4_prefix = None
|
ip4_prefix = None
|
||||||
for iface in self.node.get_ifaces(control=False):
|
for iface in self.node.get_ifaces(control=False):
|
||||||
if ip4_prefix:
|
ip4 = iface.get_ip4()
|
||||||
continue
|
if ip4:
|
||||||
for a in iface.addrlist:
|
ip4_prefix = f"{ip4.ip}/{24}"
|
||||||
a = a.split("/")[0]
|
break
|
||||||
if netaddr.valid_ipv4(a):
|
|
||||||
ip4_prefix = f"{a}/{24}"
|
|
||||||
break
|
|
||||||
return dict(ip4_prefix=ip4_prefix)
|
return dict(ip4_prefix=ip4_prefix)
|
||||||
|
|
|
@ -2,8 +2,6 @@ import abc
|
||||||
import logging
|
import logging
|
||||||
from typing import Any, Dict, List
|
from typing import Any, Dict, List
|
||||||
|
|
||||||
import netaddr
|
|
||||||
|
|
||||||
from core import constants
|
from core import constants
|
||||||
from core.config import Configuration
|
from core.config import Configuration
|
||||||
from core.configservice.base import ConfigService, ConfigServiceMode
|
from core.configservice.base import ConfigService, ConfigServiceMode
|
||||||
|
@ -50,10 +48,9 @@ def get_router_id(node: CoreNodeBase) -> str:
|
||||||
Helper to return the first IPv4 address of a node as its router ID.
|
Helper to return the first IPv4 address of a node as its router ID.
|
||||||
"""
|
"""
|
||||||
for iface in node.get_ifaces(control=False):
|
for iface in node.get_ifaces(control=False):
|
||||||
for a in iface.addrlist:
|
ip4 = iface.get_ip4()
|
||||||
a = a.split("/")[0]
|
if ip4:
|
||||||
if netaddr.valid_ipv4(a):
|
return str(ip4.ip)
|
||||||
return a
|
|
||||||
return "0.0.0.0"
|
return "0.0.0.0"
|
||||||
|
|
||||||
|
|
||||||
|
@ -103,12 +100,10 @@ class Zebra(ConfigService):
|
||||||
for iface in self.node.get_ifaces():
|
for iface in self.node.get_ifaces():
|
||||||
ip4s = []
|
ip4s = []
|
||||||
ip6s = []
|
ip6s = []
|
||||||
for x in iface.addrlist:
|
for ip4 in iface.ip4s:
|
||||||
addr = x.split("/")[0]
|
ip4s.append(str(ip4.ip))
|
||||||
if netaddr.valid_ipv4(addr):
|
for ip6 in iface.ip6s:
|
||||||
ip4s.append(x)
|
ip6s.append(str(ip6.ip))
|
||||||
else:
|
|
||||||
ip6s.append(x)
|
|
||||||
is_control = getattr(iface, "control", False)
|
is_control = getattr(iface, "control", False)
|
||||||
ifaces.append((iface, ip4s, ip6s, is_control))
|
ifaces.append((iface, ip4s, ip6s, is_control))
|
||||||
|
|
||||||
|
@ -170,10 +165,8 @@ class Ospfv2(QuaggaService, ConfigService):
|
||||||
router_id = get_router_id(self.node)
|
router_id = get_router_id(self.node)
|
||||||
addresses = []
|
addresses = []
|
||||||
for iface in self.node.get_ifaces(control=False):
|
for iface in self.node.get_ifaces(control=False):
|
||||||
for a in iface.addrlist:
|
for ip4 in iface.ip4s:
|
||||||
addr = a.split("/")[0]
|
addresses.append(str(ip4.ip))
|
||||||
if netaddr.valid_ipv4(addr):
|
|
||||||
addresses.append(a)
|
|
||||||
data = dict(router_id=router_id, addresses=addresses)
|
data = dict(router_id=router_id, addresses=addresses)
|
||||||
text = """
|
text = """
|
||||||
router ospf
|
router ospf
|
||||||
|
|
|
@ -1,7 +1,5 @@
|
||||||
from typing import Any, Dict, List
|
from typing import Any, Dict, List
|
||||||
|
|
||||||
import netaddr
|
|
||||||
|
|
||||||
from core.config import Configuration
|
from core.config import Configuration
|
||||||
from core.configservice.base import ConfigService, ConfigServiceMode
|
from core.configservice.base import ConfigService, ConfigServiceMode
|
||||||
from core.emulator.enumerations import ConfigDataTypes
|
from core.emulator.enumerations import ConfigDataTypes
|
||||||
|
@ -79,10 +77,10 @@ class VpnServer(ConfigService):
|
||||||
def data(self) -> Dict[str, Any]:
|
def data(self) -> Dict[str, Any]:
|
||||||
address = None
|
address = None
|
||||||
for iface in self.node.get_ifaces(control=False):
|
for iface in self.node.get_ifaces(control=False):
|
||||||
for x in iface.addrlist:
|
ip4 = iface.get_ip4()
|
||||||
addr = x.split("/")[0]
|
if ip4:
|
||||||
if netaddr.valid_ipv4(addr):
|
address = str(ip4.ip)
|
||||||
address = addr
|
break
|
||||||
return dict(address=address)
|
return dict(address=address)
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -29,8 +29,8 @@ class DefaultRouteService(ConfigService):
|
||||||
ifaces = self.node.get_ifaces()
|
ifaces = self.node.get_ifaces()
|
||||||
if ifaces:
|
if ifaces:
|
||||||
iface = ifaces[0]
|
iface = ifaces[0]
|
||||||
for x in iface.addrlist:
|
for ip in iface.ips():
|
||||||
net = netaddr.IPNetwork(x).cidr
|
net = ip.cidr
|
||||||
if net.size > 1:
|
if net.size > 1:
|
||||||
router = net[1]
|
router = net[1]
|
||||||
routes.append(str(router))
|
routes.append(str(router))
|
||||||
|
@ -76,15 +76,14 @@ class StaticRouteService(ConfigService):
|
||||||
def data(self) -> Dict[str, Any]:
|
def data(self) -> Dict[str, Any]:
|
||||||
routes = []
|
routes = []
|
||||||
for iface in self.node.get_ifaces(control=False):
|
for iface in self.node.get_ifaces(control=False):
|
||||||
for x in iface.addrlist:
|
for ip in iface.ips():
|
||||||
addr = x.split("/")[0]
|
address = str(ip.ip)
|
||||||
if netaddr.valid_ipv6(addr):
|
if netaddr.valid_ipv6(address):
|
||||||
dst = "3ffe:4::/64"
|
dst = "3ffe:4::/64"
|
||||||
else:
|
else:
|
||||||
dst = "10.9.8.0/24"
|
dst = "10.9.8.0/24"
|
||||||
net = netaddr.IPNetwork(x)
|
if ip[-2] != ip[1]:
|
||||||
if net[-2] != net[1]:
|
routes.append((dst, ip[1]))
|
||||||
routes.append((dst, net[1]))
|
|
||||||
return dict(routes=routes)
|
return dict(routes=routes)
|
||||||
|
|
||||||
|
|
||||||
|
@ -149,15 +148,12 @@ class DhcpService(ConfigService):
|
||||||
def data(self) -> Dict[str, Any]:
|
def data(self) -> Dict[str, Any]:
|
||||||
subnets = []
|
subnets = []
|
||||||
for iface in self.node.get_ifaces(control=False):
|
for iface in self.node.get_ifaces(control=False):
|
||||||
for x in iface.addrlist:
|
for ip4 in iface.ip4s:
|
||||||
addr = x.split("/")[0]
|
# divide the address space in half
|
||||||
if netaddr.valid_ipv4(addr):
|
index = (ip4.size - 2) / 2
|
||||||
net = netaddr.IPNetwork(x)
|
rangelow = ip4[index]
|
||||||
# divide the address space in half
|
rangehigh = ip4[-2]
|
||||||
index = (net.size - 2) / 2
|
subnets.append((ip4.ip, ip4.netmask, rangelow, rangehigh, str(ip4.ip)))
|
||||||
rangelow = net[index]
|
|
||||||
rangehigh = net[-2]
|
|
||||||
subnets.append((net.ip, net.netmask, rangelow, rangehigh, addr))
|
|
||||||
return dict(subnets=subnets)
|
return dict(subnets=subnets)
|
||||||
|
|
||||||
|
|
||||||
|
@ -238,10 +234,8 @@ class RadvdService(ConfigService):
|
||||||
ifaces = []
|
ifaces = []
|
||||||
for iface in self.node.get_ifaces(control=False):
|
for iface in self.node.get_ifaces(control=False):
|
||||||
prefixes = []
|
prefixes = []
|
||||||
for x in iface.addrlist:
|
for ip6 in iface.ip6s:
|
||||||
addr = x.split("/")[0]
|
prefixes.append(str(ip6))
|
||||||
if netaddr.valid_ipv6(addr):
|
|
||||||
prefixes.append(x)
|
|
||||||
if not prefixes:
|
if not prefixes:
|
||||||
continue
|
continue
|
||||||
ifaces.append((iface.name, prefixes))
|
ifaces.append((iface.name, prefixes))
|
||||||
|
|
|
@ -4,7 +4,6 @@ import threading
|
||||||
import time
|
import time
|
||||||
from typing import TYPE_CHECKING, Dict, List, Optional, Set, Tuple
|
from typing import TYPE_CHECKING, Dict, List, Optional, Set, Tuple
|
||||||
|
|
||||||
import netaddr
|
|
||||||
from lxml import etree
|
from lxml import etree
|
||||||
|
|
||||||
from core.emulator.data import LinkData
|
from core.emulator.data import LinkData
|
||||||
|
@ -214,13 +213,10 @@ class EmaneLinkMonitor:
|
||||||
for node in nodes:
|
for node in nodes:
|
||||||
for iface in node.get_ifaces():
|
for iface in node.get_ifaces():
|
||||||
if isinstance(iface.net, CtrlNet):
|
if isinstance(iface.net, CtrlNet):
|
||||||
ip4 = None
|
ip4 = iface.get_ip4()
|
||||||
for x in iface.addrlist:
|
|
||||||
address, prefix = x.split("/")
|
|
||||||
if netaddr.valid_ipv4(address):
|
|
||||||
ip4 = address
|
|
||||||
if ip4:
|
if ip4:
|
||||||
addresses.append(ip4)
|
address = str(ip4.ip)
|
||||||
|
addresses.append(address)
|
||||||
break
|
break
|
||||||
return addresses
|
return addresses
|
||||||
|
|
||||||
|
|
|
@ -142,18 +142,18 @@ class InterfaceData:
|
||||||
ip6: str = None
|
ip6: str = None
|
||||||
ip6_mask: int = None
|
ip6_mask: int = None
|
||||||
|
|
||||||
def get_addresses(self) -> List[str]:
|
def get_ips(self) -> List[str]:
|
||||||
"""
|
"""
|
||||||
Returns a list of ip4 and ip6 addresses when present.
|
Returns a list of ip4 and ip6 addresses when present.
|
||||||
|
|
||||||
:return: list of addresses
|
:return: list of ip addresses
|
||||||
"""
|
"""
|
||||||
addresses = []
|
ips = []
|
||||||
if self.ip4 and self.ip4_mask:
|
if self.ip4 and self.ip4_mask:
|
||||||
addresses.append(f"{self.ip4}/{self.ip4_mask}")
|
ips.append(f"{self.ip4}/{self.ip4_mask}")
|
||||||
if self.ip6 and self.ip6_mask:
|
if self.ip6 and self.ip6_mask:
|
||||||
addresses.append(f"{self.ip6}/{self.ip6_mask}")
|
ips.append(f"{self.ip6}/{self.ip6_mask}")
|
||||||
return addresses
|
return ips
|
||||||
|
|
||||||
|
|
||||||
@dataclass
|
@dataclass
|
||||||
|
|
|
@ -1548,9 +1548,8 @@ class Session:
|
||||||
entries = []
|
entries = []
|
||||||
for iface in control_net.get_ifaces():
|
for iface in control_net.get_ifaces():
|
||||||
name = iface.node.name
|
name = iface.node.name
|
||||||
for address in iface.addrlist:
|
for ip in iface.ips():
|
||||||
address = address.split("/")[0]
|
entries.append(f"{ip.ip} {name}")
|
||||||
entries.append(f"{address} {name}")
|
|
||||||
|
|
||||||
logging.info("Adding %d /etc/hosts file entries.", len(entries))
|
logging.info("Adding %d /etc/hosts file entries.", len(entries))
|
||||||
utils.file_munge("/etc/hosts", header, "\n".join(entries) + "\n")
|
utils.file_munge("/etc/hosts", header, "\n".join(entries) + "\n")
|
||||||
|
|
|
@ -7,7 +7,7 @@ import os
|
||||||
import shutil
|
import shutil
|
||||||
import threading
|
import threading
|
||||||
from threading import RLock
|
from threading import RLock
|
||||||
from typing import TYPE_CHECKING, Dict, List, Optional, Set, Tuple, Type, Union
|
from typing import TYPE_CHECKING, Dict, List, Optional, Tuple, Type, Union
|
||||||
|
|
||||||
import netaddr
|
import netaddr
|
||||||
|
|
||||||
|
@ -138,6 +138,13 @@ class NodeBase(abc.ABC):
|
||||||
return self.position.get()
|
return self.position.get()
|
||||||
|
|
||||||
def get_iface(self, iface_id: int) -> CoreInterface:
|
def get_iface(self, iface_id: int) -> CoreInterface:
|
||||||
|
"""
|
||||||
|
Retrieve interface based on id.
|
||||||
|
|
||||||
|
:param iface_id: id of interface to retrieve
|
||||||
|
:return: interface
|
||||||
|
:raises CoreError: when interface does not exist
|
||||||
|
"""
|
||||||
if iface_id not in self.ifaces:
|
if iface_id not in self.ifaces:
|
||||||
raise CoreError(f"node({self.name}) does not have interface({iface_id})")
|
raise CoreError(f"node({self.name}) does not have interface({iface_id})")
|
||||||
return self.ifaces[iface_id]
|
return self.ifaces[iface_id]
|
||||||
|
@ -436,7 +443,6 @@ class CoreNode(CoreNodeBase):
|
||||||
"""
|
"""
|
||||||
|
|
||||||
apitype: NodeTypes = NodeTypes.DEFAULT
|
apitype: NodeTypes = NodeTypes.DEFAULT
|
||||||
valid_address_types: Set[str] = {"inet", "inet6", "inet6link"}
|
|
||||||
|
|
||||||
def __init__(
|
def __init__(
|
||||||
self,
|
self,
|
||||||
|
@ -750,40 +756,39 @@ class CoreNode(CoreNodeBase):
|
||||||
if self.up:
|
if self.up:
|
||||||
self.node_net_client.device_mac(iface.name, mac)
|
self.node_net_client.device_mac(iface.name, mac)
|
||||||
|
|
||||||
def addaddr(self, iface_id: int, addr: str) -> None:
|
def add_ip(self, iface_id: int, ip: str) -> None:
|
||||||
"""
|
"""
|
||||||
Add interface address.
|
Add an ip address to an interface in the format "10.0.0.1/24".
|
||||||
|
|
||||||
:param iface_id: id of interface to add address to
|
:param iface_id: id of interface to add address to
|
||||||
:param addr: address to add to interface
|
:param ip: address to add to interface
|
||||||
:return: nothing
|
|
||||||
"""
|
|
||||||
addr = utils.validate_ip(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(iface.name, addr, broadcast)
|
|
||||||
|
|
||||||
def deladdr(self, iface_id: int, addr: str) -> None:
|
|
||||||
"""
|
|
||||||
Delete address from an interface.
|
|
||||||
|
|
||||||
:param iface_id: id of interface to delete address from
|
|
||||||
:param addr: address to delete from interface
|
|
||||||
:return: nothing
|
:return: nothing
|
||||||
|
:raises CoreError: when ip address provided is invalid
|
||||||
:raises CoreCommandError: when a non-zero exit status occurs
|
:raises CoreCommandError: when a non-zero exit status occurs
|
||||||
"""
|
"""
|
||||||
iface = self.get_iface(iface_id)
|
iface = self.get_iface(iface_id)
|
||||||
try:
|
iface.add_ip(ip)
|
||||||
iface.deladdr(addr)
|
|
||||||
except ValueError:
|
|
||||||
logging.exception("trying to delete unknown address: %s", addr)
|
|
||||||
if self.up:
|
if self.up:
|
||||||
self.node_net_client.delete_address(iface.name, addr)
|
# ipv4 check
|
||||||
|
broadcast = None
|
||||||
|
if netaddr.valid_ipv4(ip):
|
||||||
|
broadcast = "+"
|
||||||
|
self.node_net_client.create_address(iface.name, ip, broadcast)
|
||||||
|
|
||||||
|
def remove_ip(self, iface_id: int, ip: str) -> None:
|
||||||
|
"""
|
||||||
|
Remove an ip address from an interface in the format "10.0.0.1/24".
|
||||||
|
|
||||||
|
:param iface_id: id of interface to delete address from
|
||||||
|
:param ip: ip address to remove from interface
|
||||||
|
:return: nothing
|
||||||
|
:raises CoreError: when ip address provided is invalid
|
||||||
|
:raises CoreCommandError: when a non-zero exit status occurs
|
||||||
|
"""
|
||||||
|
iface = self.get_iface(iface_id)
|
||||||
|
iface.remove_ip(ip)
|
||||||
|
if self.up:
|
||||||
|
self.node_net_client.delete_address(iface.name, ip)
|
||||||
|
|
||||||
def ifup(self, iface_id: int) -> None:
|
def ifup(self, iface_id: int) -> None:
|
||||||
"""
|
"""
|
||||||
|
@ -806,7 +811,7 @@ class CoreNode(CoreNodeBase):
|
||||||
:param iface_data: interface data for new interface
|
:param iface_data: interface data for new interface
|
||||||
:return: interface index
|
:return: interface index
|
||||||
"""
|
"""
|
||||||
addresses = iface_data.get_addresses()
|
ips = iface_data.get_ips()
|
||||||
with self.lock:
|
with self.lock:
|
||||||
# TODO: emane specific code
|
# TODO: emane specific code
|
||||||
if net.is_emane is True:
|
if net.is_emane is True:
|
||||||
|
@ -818,15 +823,15 @@ class CoreNode(CoreNodeBase):
|
||||||
self.attachnet(iface_id, net)
|
self.attachnet(iface_id, net)
|
||||||
iface = self.get_iface(iface_id)
|
iface = self.get_iface(iface_id)
|
||||||
iface.set_mac(iface_data.mac)
|
iface.set_mac(iface_data.mac)
|
||||||
for address in addresses:
|
for ip in ips:
|
||||||
iface.addaddr(address)
|
iface.add_ip(ip)
|
||||||
else:
|
else:
|
||||||
iface_id = self.newveth(iface_data.id, iface_data.name)
|
iface_id = self.newveth(iface_data.id, iface_data.name)
|
||||||
self.attachnet(iface_id, net)
|
self.attachnet(iface_id, net)
|
||||||
if iface_data.mac:
|
if iface_data.mac:
|
||||||
self.set_mac(iface_id, iface_data.mac)
|
self.set_mac(iface_id, iface_data.mac)
|
||||||
for address in addresses:
|
for ip in ips:
|
||||||
self.addaddr(iface_id, address)
|
self.add_ip(iface_id, ip)
|
||||||
self.ifup(iface_id)
|
self.ifup(iface_id)
|
||||||
iface = self.get_iface(iface_id)
|
iface = self.get_iface(iface_id)
|
||||||
return iface
|
return iface
|
||||||
|
@ -1053,18 +1058,17 @@ class CoreNetworkBase(NodeBase):
|
||||||
if uni:
|
if uni:
|
||||||
unidirectional = 1
|
unidirectional = 1
|
||||||
|
|
||||||
iface2 = InterfaceData(
|
iface2_data = InterfaceData(
|
||||||
id=linked_node.get_iface_id(iface), name=iface.name, mac=iface.mac
|
id=linked_node.get_iface_id(iface), name=iface.name, mac=iface.mac
|
||||||
)
|
)
|
||||||
for address in iface.addrlist:
|
ip4 = iface.get_ip4()
|
||||||
ip, _sep, mask = address.partition("/")
|
if ip4:
|
||||||
mask = int(mask)
|
iface2_data.ip4 = str(ip4.ip)
|
||||||
if netaddr.valid_ipv4(ip):
|
iface2_data.ip4_mask = ip4.prefixlen
|
||||||
iface2.ip4 = ip
|
ip6 = iface.get_ip6()
|
||||||
iface2.ip4_mask = mask
|
if ip6:
|
||||||
else:
|
iface2_data.ip6 = str(ip6.ip)
|
||||||
iface2.ip6 = ip
|
iface2_data.ip6_mask = ip6.prefixlen
|
||||||
iface2.ip6_mask = mask
|
|
||||||
|
|
||||||
options_data = iface.get_link_options(unidirectional)
|
options_data = iface.get_link_options(unidirectional)
|
||||||
link_data = LinkData(
|
link_data = LinkData(
|
||||||
|
@ -1072,7 +1076,7 @@ class CoreNetworkBase(NodeBase):
|
||||||
type=self.linktype,
|
type=self.linktype,
|
||||||
node1_id=self.id,
|
node1_id=self.id,
|
||||||
node2_id=linked_node.id,
|
node2_id=linked_node.id,
|
||||||
iface2=iface2,
|
iface2=iface2_data,
|
||||||
options=options_data,
|
options=options_data,
|
||||||
)
|
)
|
||||||
all_links.append(link_data)
|
all_links.append(link_data)
|
||||||
|
|
|
@ -6,6 +6,8 @@ import logging
|
||||||
import time
|
import time
|
||||||
from typing import TYPE_CHECKING, Callable, Dict, List, Optional, Tuple
|
from typing import TYPE_CHECKING, Callable, Dict, List, Optional, Tuple
|
||||||
|
|
||||||
|
import netaddr
|
||||||
|
|
||||||
from core import utils
|
from core import utils
|
||||||
from core.emulator.data import LinkOptions
|
from core.emulator.data import LinkOptions
|
||||||
from core.emulator.enumerations import TransportType
|
from core.emulator.enumerations import TransportType
|
||||||
|
@ -52,7 +54,8 @@ class CoreInterface:
|
||||||
self.net: Optional[CoreNetworkBase] = None
|
self.net: Optional[CoreNetworkBase] = None
|
||||||
self.othernet: Optional[CoreNetworkBase] = None
|
self.othernet: Optional[CoreNetworkBase] = None
|
||||||
self._params: Dict[str, float] = {}
|
self._params: Dict[str, float] = {}
|
||||||
self.addrlist: List[str] = []
|
self.ip4s: List[netaddr.IPNetwork] = []
|
||||||
|
self.ip6s: List[netaddr.IPNetwork] = []
|
||||||
self.mac: Optional[str] = None
|
self.mac: Optional[str] = None
|
||||||
# placeholder position hook
|
# placeholder position hook
|
||||||
self.poshook: Callable[[CoreInterface], None] = lambda x: None
|
self.poshook: Callable[[CoreInterface], None] = lambda x: None
|
||||||
|
@ -131,24 +134,65 @@ class CoreInterface:
|
||||||
if self.net is not None:
|
if self.net is not None:
|
||||||
self.net.detach(self)
|
self.net.detach(self)
|
||||||
|
|
||||||
def addaddr(self, addr: str) -> None:
|
def add_ip(self, ip: str) -> None:
|
||||||
"""
|
"""
|
||||||
Add address.
|
Add ip address in the format "10.0.0.1/24".
|
||||||
|
|
||||||
:param addr: address to add
|
:param ip: ip address to add
|
||||||
:return: nothing
|
:return: nothing
|
||||||
|
:raises CoreError: when ip address provided is invalid
|
||||||
"""
|
"""
|
||||||
addr = utils.validate_ip(addr)
|
try:
|
||||||
self.addrlist.append(addr)
|
ip = netaddr.IPNetwork(ip)
|
||||||
|
address = str(ip.ip)
|
||||||
|
if netaddr.valid_ipv4(address):
|
||||||
|
self.ip4s.append(ip)
|
||||||
|
else:
|
||||||
|
self.ip6s.append(ip)
|
||||||
|
except netaddr.AddrFormatError:
|
||||||
|
raise CoreError(f"adding invalid address {ip}")
|
||||||
|
|
||||||
def deladdr(self, addr: str) -> None:
|
def remove_ip(self, ip: str) -> None:
|
||||||
"""
|
"""
|
||||||
Delete address.
|
Remove ip address in the format "10.0.0.1/24".
|
||||||
|
|
||||||
:param addr: address to delete
|
:param ip: ip address to delete
|
||||||
:return: nothing
|
:return: nothing
|
||||||
|
:raises CoreError: when ip address provided is invalid
|
||||||
"""
|
"""
|
||||||
self.addrlist.remove(addr)
|
try:
|
||||||
|
ip = netaddr.IPNetwork(ip)
|
||||||
|
address = str(ip.ip)
|
||||||
|
if netaddr.valid_ipv4(address):
|
||||||
|
self.ip4s.remove(ip)
|
||||||
|
else:
|
||||||
|
self.ip6s.remove(ip)
|
||||||
|
except (netaddr.AddrFormatError, ValueError):
|
||||||
|
raise CoreError(f"deleting invalid address {ip}")
|
||||||
|
|
||||||
|
def get_ip4(self) -> Optional[netaddr.IPNetwork]:
|
||||||
|
"""
|
||||||
|
Looks for the first ip4 address.
|
||||||
|
|
||||||
|
:return: ip4 address, None otherwise
|
||||||
|
"""
|
||||||
|
return next(iter(self.ip4s), None)
|
||||||
|
|
||||||
|
def get_ip6(self) -> Optional[netaddr.IPNetwork]:
|
||||||
|
"""
|
||||||
|
Looks for the first ip6 address.
|
||||||
|
|
||||||
|
:return: ip6 address, None otherwise
|
||||||
|
"""
|
||||||
|
return next(iter(self.ip6s), None)
|
||||||
|
|
||||||
|
def ips(self) -> List[netaddr.IPNetwork]:
|
||||||
|
"""
|
||||||
|
Retrieve a list of all ip4 and ip6 addresses combined.
|
||||||
|
|
||||||
|
:return: ip4 and ip6 addresses
|
||||||
|
"""
|
||||||
|
return self.ip4s + self.ip6s
|
||||||
|
|
||||||
def set_mac(self, mac: str) -> None:
|
def set_mac(self, mac: str) -> None:
|
||||||
"""
|
"""
|
||||||
|
@ -487,13 +531,13 @@ class TunTap(CoreInterface):
|
||||||
|
|
||||||
def setaddrs(self) -> None:
|
def setaddrs(self) -> None:
|
||||||
"""
|
"""
|
||||||
Set interface addresses based on self.addrlist.
|
Set interface addresses.
|
||||||
|
|
||||||
:return: nothing
|
:return: nothing
|
||||||
"""
|
"""
|
||||||
self.waitfordevicenode()
|
self.waitfordevicenode()
|
||||||
for addr in self.addrlist:
|
for ip in self.ips():
|
||||||
self.node.node_net_client.create_address(self.name, str(addr))
|
self.node.node_net_client.create_address(self.name, str(ip))
|
||||||
|
|
||||||
|
|
||||||
class GreTap(CoreInterface):
|
class GreTap(CoreInterface):
|
||||||
|
|
|
@ -575,18 +575,17 @@ class CoreNetwork(CoreNetworkBase):
|
||||||
return iface
|
return iface
|
||||||
return None
|
return None
|
||||||
|
|
||||||
def addrconfig(self, addrlist: List[str]) -> None:
|
def add_ips(self, ips: List[str]) -> None:
|
||||||
"""
|
"""
|
||||||
Set addresses on the bridge.
|
Add ip addresses on the bridge in the format "10.0.0.1/24".
|
||||||
|
|
||||||
:param addrlist: address list
|
:param ips: ip address to add
|
||||||
:return: nothing
|
:return: nothing
|
||||||
"""
|
"""
|
||||||
if not self.up:
|
if not self.up:
|
||||||
return
|
return
|
||||||
|
for ip in ips:
|
||||||
for addr in addrlist:
|
self.net_client.create_address(self.brname, ip)
|
||||||
self.net_client.create_address(self.brname, str(addr))
|
|
||||||
|
|
||||||
|
|
||||||
class GreTapBridge(CoreNetwork):
|
class GreTapBridge(CoreNetwork):
|
||||||
|
@ -663,22 +662,22 @@ class GreTapBridge(CoreNetwork):
|
||||||
self.gretap = None
|
self.gretap = None
|
||||||
super().shutdown()
|
super().shutdown()
|
||||||
|
|
||||||
def addrconfig(self, addrlist: List[str]) -> None:
|
def add_ips(self, ips: List[str]) -> None:
|
||||||
"""
|
"""
|
||||||
Set the remote tunnel endpoint. This is a one-time method for
|
Set the remote tunnel endpoint. This is a one-time method for
|
||||||
creating the GreTap device, which requires the remoteip at startup.
|
creating the GreTap device, which requires the remoteip at startup.
|
||||||
The 1st address in the provided list is remoteip, 2nd optionally
|
The 1st address in the provided list is remoteip, 2nd optionally
|
||||||
specifies localip.
|
specifies localip.
|
||||||
|
|
||||||
:param addrlist: address list
|
:param ips: address list
|
||||||
:return: nothing
|
:return: nothing
|
||||||
"""
|
"""
|
||||||
if self.gretap:
|
if self.gretap:
|
||||||
raise ValueError(f"gretap already exists for {self.name}")
|
raise ValueError(f"gretap already exists for {self.name}")
|
||||||
remoteip = addrlist[0].split("/")[0]
|
remoteip = ips[0].split("/")[0]
|
||||||
localip = None
|
localip = None
|
||||||
if len(addrlist) > 1:
|
if len(ips) > 1:
|
||||||
localip = addrlist[1].split("/")[0]
|
localip = ips[1].split("/")[0]
|
||||||
self.gretap = GreTap(
|
self.gretap = GreTap(
|
||||||
session=self.session,
|
session=self.session,
|
||||||
remoteip=remoteip,
|
remoteip=remoteip,
|
||||||
|
@ -698,9 +697,9 @@ class GreTapBridge(CoreNetwork):
|
||||||
:return: nothing
|
:return: nothing
|
||||||
"""
|
"""
|
||||||
self.grekey = key
|
self.grekey = key
|
||||||
addresses = iface_data.get_addresses()
|
ips = iface_data.get_ips()
|
||||||
if addresses:
|
if ips:
|
||||||
self.addrconfig(addresses)
|
self.add_ips(ips)
|
||||||
|
|
||||||
|
|
||||||
class CtrlNet(CoreNetwork):
|
class CtrlNet(CoreNetwork):
|
||||||
|
@ -881,28 +880,26 @@ class PtpNet(CoreNetwork):
|
||||||
iface1_data = InterfaceData(
|
iface1_data = InterfaceData(
|
||||||
id=iface1.node.get_iface_id(iface1), name=iface1.name, mac=iface1.mac
|
id=iface1.node.get_iface_id(iface1), name=iface1.name, mac=iface1.mac
|
||||||
)
|
)
|
||||||
for address in iface1.addrlist:
|
ip4 = iface1.get_ip4()
|
||||||
ip, _sep, mask = address.partition("/")
|
if ip4:
|
||||||
mask = int(mask)
|
iface1_data.ip4 = str(ip4.ip)
|
||||||
if netaddr.valid_ipv4(ip):
|
iface1_data.ip4_mask = ip4.prefixlen
|
||||||
iface1.ip4 = ip
|
ip6 = iface1.get_ip6()
|
||||||
iface1.ip4_mask = mask
|
if ip6:
|
||||||
else:
|
iface1_data.ip6 = str(ip6.ip)
|
||||||
iface1.ip6 = ip
|
iface1_data.ip6_mask = ip6.prefixlen
|
||||||
iface1.ip6_mask = mask
|
|
||||||
|
|
||||||
iface2_data = InterfaceData(
|
iface2_data = InterfaceData(
|
||||||
id=iface2.node.get_iface_id(iface2), name=iface2.name, mac=iface2.mac
|
id=iface2.node.get_iface_id(iface2), name=iface2.name, mac=iface2.mac
|
||||||
)
|
)
|
||||||
for address in iface2.addrlist:
|
ip4 = iface2.get_ip4()
|
||||||
ip, _sep, mask = address.partition("/")
|
if ip4:
|
||||||
mask = int(mask)
|
iface2_data.ip4 = str(ip4.ip)
|
||||||
if netaddr.valid_ipv4(ip):
|
iface2_data.ip4_mask = ip4.prefixlen
|
||||||
iface2.ip4 = ip
|
ip6 = iface2.get_ip6()
|
||||||
iface2.ip4_mask = mask
|
if ip6:
|
||||||
else:
|
iface2_data.ip6 = str(ip6.ip)
|
||||||
iface2.ip6 = ip
|
iface2_data.ip6_mask = ip6.prefixlen
|
||||||
iface2.ip6_mask = mask
|
|
||||||
|
|
||||||
options_data = iface1.get_link_options(unidirectional)
|
options_data = iface1.get_link_options(unidirectional)
|
||||||
link_data = LinkData(
|
link_data = LinkData(
|
||||||
|
|
|
@ -75,43 +75,43 @@ class PhysicalNode(CoreNodeBase):
|
||||||
:raises CoreCommandError: when a non-zero exit status occurs
|
:raises CoreCommandError: when a non-zero exit status occurs
|
||||||
"""
|
"""
|
||||||
mac = utils.validate_mac(mac)
|
mac = utils.validate_mac(mac)
|
||||||
iface = self.ifaces[iface_id]
|
iface = self.get_iface(iface_id)
|
||||||
iface.set_mac(mac)
|
iface.set_mac(mac)
|
||||||
if self.up:
|
if self.up:
|
||||||
self.net_client.device_mac(iface.name, mac)
|
self.net_client.device_mac(iface.name, mac)
|
||||||
|
|
||||||
def addaddr(self, iface_id: int, addr: str) -> None:
|
def add_ip(self, iface_id: int, ip: str) -> None:
|
||||||
"""
|
"""
|
||||||
Add an address to an interface.
|
Add an ip address to an interface in the format "10.0.0.1/24".
|
||||||
|
|
||||||
:param iface_id: index of interface to add address to
|
:param iface_id: id of interface to add address to
|
||||||
:param addr: address to add
|
:param ip: address to add to interface
|
||||||
:return: nothing
|
:return: nothing
|
||||||
|
:raises CoreError: when ip address provided is invalid
|
||||||
|
:raises CoreCommandError: when a non-zero exit status occurs
|
||||||
"""
|
"""
|
||||||
addr = utils.validate_ip(addr)
|
|
||||||
iface = self.get_iface(iface_id)
|
iface = self.get_iface(iface_id)
|
||||||
|
iface.add_ip(ip)
|
||||||
if self.up:
|
if self.up:
|
||||||
self.net_client.create_address(iface.name, addr)
|
self.net_client.create_address(iface.name, ip)
|
||||||
iface.addaddr(addr)
|
|
||||||
|
|
||||||
def deladdr(self, iface_id: int, addr: str) -> None:
|
def remove_ip(self, iface_id: int, ip: str) -> None:
|
||||||
"""
|
"""
|
||||||
Delete an address from an interface.
|
Remove an ip address from an interface in the format "10.0.0.1/24".
|
||||||
|
|
||||||
:param iface_id: index of interface to delete
|
:param iface_id: id of interface to delete address from
|
||||||
:param addr: address to delete
|
:param ip: ip address to remove from interface
|
||||||
:return: nothing
|
:return: nothing
|
||||||
|
:raises CoreError: when ip address provided is invalid
|
||||||
|
:raises CoreCommandError: when a non-zero exit status occurs
|
||||||
"""
|
"""
|
||||||
iface = self.ifaces[iface_id]
|
iface = self.get_iface(iface_id)
|
||||||
try:
|
iface.remove_ip(ip)
|
||||||
iface.deladdr(addr)
|
|
||||||
except ValueError:
|
|
||||||
logging.exception("trying to delete unknown address: %s", addr)
|
|
||||||
if self.up:
|
if self.up:
|
||||||
self.net_client.delete_address(iface.name, addr)
|
self.net_client.delete_address(iface.name, ip)
|
||||||
|
|
||||||
def adopt_iface(
|
def adopt_iface(
|
||||||
self, iface: CoreInterface, iface_id: int, mac: str, addrlist: List[str]
|
self, iface: CoreInterface, iface_id: int, mac: str, ips: List[str]
|
||||||
) -> None:
|
) -> None:
|
||||||
"""
|
"""
|
||||||
When a link message is received linking this node to another part of
|
When a link message is received linking this node to another part of
|
||||||
|
@ -128,8 +128,8 @@ class PhysicalNode(CoreNodeBase):
|
||||||
iface.localname = iface.name
|
iface.localname = iface.name
|
||||||
if mac:
|
if mac:
|
||||||
self.set_mac(iface_id, mac)
|
self.set_mac(iface_id, mac)
|
||||||
for addr in addrlist:
|
for ip in ips:
|
||||||
self.addaddr(iface_id, addr)
|
self.add_ip(iface_id, ip)
|
||||||
if self.up:
|
if self.up:
|
||||||
self.net_client.device_up(iface.localname)
|
self.net_client.device_up(iface.localname)
|
||||||
|
|
||||||
|
@ -156,7 +156,7 @@ class PhysicalNode(CoreNodeBase):
|
||||||
self, net: CoreNetworkBase, iface_data: InterfaceData
|
self, net: CoreNetworkBase, iface_data: InterfaceData
|
||||||
) -> CoreInterface:
|
) -> CoreInterface:
|
||||||
logging.info("creating interface")
|
logging.info("creating interface")
|
||||||
addresses = iface_data.get_addresses()
|
ips = iface_data.get_ips()
|
||||||
iface_id = iface_data.id
|
iface_id = iface_data.id
|
||||||
if iface_id is None:
|
if iface_id is None:
|
||||||
iface_id = self.next_iface_id()
|
iface_id = self.next_iface_id()
|
||||||
|
@ -167,12 +167,12 @@ class PhysicalNode(CoreNodeBase):
|
||||||
# this is reached when this node is linked to a network node
|
# 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
|
# tunnel to net not built yet, so build it now and adopt it
|
||||||
_, remote_tap = self.session.distributed.create_gre_tunnel(net, self.server)
|
_, remote_tap = self.session.distributed.create_gre_tunnel(net, self.server)
|
||||||
self.adopt_iface(remote_tap, iface_id, iface_data.mac, addresses)
|
self.adopt_iface(remote_tap, iface_id, iface_data.mac, ips)
|
||||||
return remote_tap
|
return remote_tap
|
||||||
else:
|
else:
|
||||||
# this is reached when configuring services (self.up=False)
|
# this is reached when configuring services (self.up=False)
|
||||||
iface = GreTap(node=self, name=name, session=self.session, start=False)
|
iface = GreTap(node=self, name=name, session=self.session, start=False)
|
||||||
self.adopt_iface(iface, iface_id, iface_data.mac, addresses)
|
self.adopt_iface(iface, iface_id, iface_data.mac, ips)
|
||||||
return iface
|
return iface
|
||||||
|
|
||||||
def privatedir(self, path: str) -> None:
|
def privatedir(self, path: str) -> None:
|
||||||
|
@ -316,8 +316,8 @@ class Rj45Node(CoreNodeBase):
|
||||||
self.iface_id = iface_id
|
self.iface_id = iface_id
|
||||||
if net is not None:
|
if net is not None:
|
||||||
self.iface.attachnet(net)
|
self.iface.attachnet(net)
|
||||||
for addr in iface_data.get_addresses():
|
for ip in iface_data.get_ips():
|
||||||
self.addaddr(addr)
|
self.add_ip(ip)
|
||||||
return self.iface
|
return self.iface
|
||||||
|
|
||||||
def delete_iface(self, iface_id: int) -> None:
|
def delete_iface(self, iface_id: int) -> None:
|
||||||
|
@ -348,30 +348,31 @@ class Rj45Node(CoreNodeBase):
|
||||||
raise CoreError(f"node({self.name}) does not have interface({iface.name})")
|
raise CoreError(f"node({self.name}) does not have interface({iface.name})")
|
||||||
return self.iface_id
|
return self.iface_id
|
||||||
|
|
||||||
def addaddr(self, addr: str) -> None:
|
def add_ip(self, ip: str) -> None:
|
||||||
"""
|
"""
|
||||||
Add address to to network interface.
|
Add an ip address to an interface in the format "10.0.0.1/24".
|
||||||
|
|
||||||
:param addr: address to add
|
:param ip: address to add to interface
|
||||||
:return: nothing
|
:return: nothing
|
||||||
:raises CoreCommandError: when there is a command exception
|
:raises CoreError: when ip address provided is invalid
|
||||||
|
:raises CoreCommandError: when a non-zero exit status occurs
|
||||||
"""
|
"""
|
||||||
addr = utils.validate_ip(addr)
|
self.iface.add_ip(ip)
|
||||||
if self.up:
|
if self.up:
|
||||||
self.net_client.create_address(self.name, addr)
|
self.net_client.create_address(self.name, ip)
|
||||||
self.iface.addaddr(addr)
|
|
||||||
|
|
||||||
def deladdr(self, addr: str) -> None:
|
def remove_ip(self, ip: str) -> None:
|
||||||
"""
|
"""
|
||||||
Delete address from network interface.
|
Remove an ip address from an interface in the format "10.0.0.1/24".
|
||||||
|
|
||||||
:param addr: address to delete
|
:param ip: ip address to remove from interface
|
||||||
:return: nothing
|
:return: nothing
|
||||||
:raises CoreCommandError: when there is a command exception
|
:raises CoreError: when ip address provided is invalid
|
||||||
|
:raises CoreCommandError: when a non-zero exit status occurs
|
||||||
"""
|
"""
|
||||||
|
self.iface.remove_ip(ip)
|
||||||
if self.up:
|
if self.up:
|
||||||
self.net_client.delete_address(self.name, addr)
|
self.net_client.delete_address(self.name, ip)
|
||||||
self.iface.deladdr(addr)
|
|
||||||
|
|
||||||
def savestate(self) -> None:
|
def savestate(self) -> None:
|
||||||
"""
|
"""
|
||||||
|
|
|
@ -3,8 +3,6 @@ bird.py: defines routing services provided by the BIRD Internet Routing Daemon.
|
||||||
"""
|
"""
|
||||||
from typing import Optional, Tuple
|
from typing import Optional, Tuple
|
||||||
|
|
||||||
import netaddr
|
|
||||||
|
|
||||||
from core.nodes.base import CoreNode
|
from core.nodes.base import CoreNode
|
||||||
from core.services.coreservices import CoreService
|
from core.services.coreservices import CoreService
|
||||||
|
|
||||||
|
@ -39,10 +37,9 @@ class Bird(CoreService):
|
||||||
Helper to return the first IPv4 address of a node as its router ID.
|
Helper to return the first IPv4 address of a node as its router ID.
|
||||||
"""
|
"""
|
||||||
for iface in node.get_ifaces(control=False):
|
for iface in node.get_ifaces(control=False):
|
||||||
for a in iface.addrlist:
|
ip4 = iface.get_ip4()
|
||||||
a = a.split("/")[0]
|
if ip4:
|
||||||
if netaddr.valid_ipv4(a):
|
return str(ip4.ip)
|
||||||
return a
|
|
||||||
return "0.0.0.0"
|
return "0.0.0.0"
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
|
|
|
@ -67,7 +67,7 @@ class FRRZebra(CoreService):
|
||||||
# include control interfaces in addressing but not routing daemons
|
# include control interfaces in addressing but not routing daemons
|
||||||
if hasattr(iface, "control") and iface.control is True:
|
if hasattr(iface, "control") and iface.control is True:
|
||||||
cfg += " "
|
cfg += " "
|
||||||
cfg += "\n ".join(map(cls.addrstr, iface.addrlist))
|
cfg += "\n ".join(map(cls.addrstr, iface.ips()))
|
||||||
cfg += "\n"
|
cfg += "\n"
|
||||||
continue
|
continue
|
||||||
cfgv4 = ""
|
cfgv4 = ""
|
||||||
|
@ -87,19 +87,13 @@ class FRRZebra(CoreService):
|
||||||
cfgv4 += iface_config
|
cfgv4 += iface_config
|
||||||
|
|
||||||
if want_ipv4:
|
if want_ipv4:
|
||||||
ipv4list = filter(
|
|
||||||
lambda x: netaddr.valid_ipv4(x.split("/")[0]), iface.addrlist
|
|
||||||
)
|
|
||||||
cfg += " "
|
cfg += " "
|
||||||
cfg += "\n ".join(map(cls.addrstr, ipv4list))
|
cfg += "\n ".join(map(cls.addrstr, iface.ip4s))
|
||||||
cfg += "\n"
|
cfg += "\n"
|
||||||
cfg += cfgv4
|
cfg += cfgv4
|
||||||
if want_ipv6:
|
if want_ipv6:
|
||||||
ipv6list = filter(
|
|
||||||
lambda x: netaddr.valid_ipv6(x.split("/")[0]), iface.addrlist
|
|
||||||
)
|
|
||||||
cfg += " "
|
cfg += " "
|
||||||
cfg += "\n ".join(map(cls.addrstr, ipv6list))
|
cfg += "\n ".join(map(cls.addrstr, iface.ip6s))
|
||||||
cfg += "\n"
|
cfg += "\n"
|
||||||
cfg += cfgv6
|
cfg += cfgv6
|
||||||
cfg += "!\n"
|
cfg += "!\n"
|
||||||
|
@ -111,17 +105,17 @@ class FRRZebra(CoreService):
|
||||||
return cfg
|
return cfg
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def addrstr(x: str) -> str:
|
def addrstr(ip: netaddr.IPNetwork) -> str:
|
||||||
"""
|
"""
|
||||||
helper for mapping IP addresses to zebra config statements
|
helper for mapping IP addresses to zebra config statements
|
||||||
"""
|
"""
|
||||||
addr = x.split("/")[0]
|
address = str(ip.ip)
|
||||||
if netaddr.valid_ipv4(addr):
|
if netaddr.valid_ipv4(address):
|
||||||
return "ip address %s" % x
|
return "ip address %s" % ip
|
||||||
elif netaddr.valid_ipv6(addr):
|
elif netaddr.valid_ipv6(address):
|
||||||
return "ipv6 address %s" % x
|
return "ipv6 address %s" % ip
|
||||||
else:
|
else:
|
||||||
raise ValueError("invalid address: %s", x)
|
raise ValueError("invalid address: %s", ip)
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def generate_frr_boot(cls, node: CoreNode) -> str:
|
def generate_frr_boot(cls, node: CoreNode) -> str:
|
||||||
|
@ -333,10 +327,9 @@ class FrrService(CoreService):
|
||||||
Helper to return the first IPv4 address of a node as its router ID.
|
Helper to return the first IPv4 address of a node as its router ID.
|
||||||
"""
|
"""
|
||||||
for iface in node.get_ifaces(control=False):
|
for iface in node.get_ifaces(control=False):
|
||||||
for a in iface.addrlist:
|
ip4 = iface.get_ip4()
|
||||||
a = a.split("/")[0]
|
if ip4:
|
||||||
if netaddr.valid_ipv4(a):
|
return str(ip4.ip)
|
||||||
return a
|
|
||||||
return "0.0.0.0"
|
return "0.0.0.0"
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
|
@ -413,11 +406,8 @@ class FRROspfv2(FrrService):
|
||||||
cfg += " router-id %s\n" % rtrid
|
cfg += " router-id %s\n" % rtrid
|
||||||
# network 10.0.0.0/24 area 0
|
# network 10.0.0.0/24 area 0
|
||||||
for iface in node.get_ifaces(control=False):
|
for iface in node.get_ifaces(control=False):
|
||||||
for a in iface.addrlist:
|
for ip4 in iface.ip4s:
|
||||||
addr = a.split("/")[0]
|
cfg += f" network {ip4} area 0\n"
|
||||||
if not netaddr.valid_ipv4(addr):
|
|
||||||
continue
|
|
||||||
cfg += " network %s area 0\n" % a
|
|
||||||
cfg += "!\n"
|
cfg += "!\n"
|
||||||
return cfg
|
return cfg
|
||||||
|
|
||||||
|
|
|
@ -4,8 +4,6 @@ nrl.py: defines services provided by NRL protolib tools hosted here:
|
||||||
"""
|
"""
|
||||||
from typing import Optional, Tuple
|
from typing import Optional, Tuple
|
||||||
|
|
||||||
import netaddr
|
|
||||||
|
|
||||||
from core import utils
|
from core import utils
|
||||||
from core.nodes.base import CoreNode
|
from core.nodes.base import CoreNode
|
||||||
from core.services.coreservices import CoreService
|
from core.services.coreservices import CoreService
|
||||||
|
@ -32,10 +30,9 @@ class NrlService(CoreService):
|
||||||
interface's prefix length, so e.g. '/32' can turn into '/24'.
|
interface's prefix length, so e.g. '/32' can turn into '/24'.
|
||||||
"""
|
"""
|
||||||
for iface in node.get_ifaces(control=False):
|
for iface in node.get_ifaces(control=False):
|
||||||
for a in iface.addrlist:
|
ip4 = iface.get_ip4()
|
||||||
a = a.split("/")[0]
|
if ip4:
|
||||||
if netaddr.valid_ipv4(a):
|
return f"{ip4.ip}/{prefixlen}"
|
||||||
return f"{a}/{prefixlen}"
|
|
||||||
return "0.0.0.0/%s" % prefixlen
|
return "0.0.0.0/%s" % prefixlen
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -64,7 +64,7 @@ class Zebra(CoreService):
|
||||||
# include control interfaces in addressing but not routing daemons
|
# include control interfaces in addressing but not routing daemons
|
||||||
if getattr(iface, "control", False):
|
if getattr(iface, "control", False):
|
||||||
cfg += " "
|
cfg += " "
|
||||||
cfg += "\n ".join(map(cls.addrstr, iface.addrlist))
|
cfg += "\n ".join(map(cls.addrstr, iface.ips()))
|
||||||
cfg += "\n"
|
cfg += "\n"
|
||||||
continue
|
continue
|
||||||
cfgv4 = ""
|
cfgv4 = ""
|
||||||
|
@ -86,19 +86,13 @@ class Zebra(CoreService):
|
||||||
cfgv4 += iface_config
|
cfgv4 += iface_config
|
||||||
|
|
||||||
if want_ipv4:
|
if want_ipv4:
|
||||||
ipv4list = filter(
|
|
||||||
lambda x: netaddr.valid_ipv4(x.split("/")[0]), iface.addrlist
|
|
||||||
)
|
|
||||||
cfg += " "
|
cfg += " "
|
||||||
cfg += "\n ".join(map(cls.addrstr, ipv4list))
|
cfg += "\n ".join(map(cls.addrstr, iface.ip4s))
|
||||||
cfg += "\n"
|
cfg += "\n"
|
||||||
cfg += cfgv4
|
cfg += cfgv4
|
||||||
if want_ipv6:
|
if want_ipv6:
|
||||||
ipv6list = filter(
|
|
||||||
lambda x: netaddr.valid_ipv6(x.split("/")[0]), iface.addrlist
|
|
||||||
)
|
|
||||||
cfg += " "
|
cfg += " "
|
||||||
cfg += "\n ".join(map(cls.addrstr, ipv6list))
|
cfg += "\n ".join(map(cls.addrstr, iface.ip6s))
|
||||||
cfg += "\n"
|
cfg += "\n"
|
||||||
cfg += cfgv6
|
cfg += cfgv6
|
||||||
cfg += "!\n"
|
cfg += "!\n"
|
||||||
|
@ -112,17 +106,17 @@ class Zebra(CoreService):
|
||||||
return cfg
|
return cfg
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def addrstr(x: str) -> str:
|
def addrstr(ip: netaddr.IPNetwork) -> str:
|
||||||
"""
|
"""
|
||||||
helper for mapping IP addresses to zebra config statements
|
helper for mapping IP addresses to zebra config statements
|
||||||
"""
|
"""
|
||||||
addr = x.split("/")[0]
|
address = str(ip.ip)
|
||||||
if netaddr.valid_ipv4(addr):
|
if netaddr.valid_ipv4(address):
|
||||||
return "ip address %s" % x
|
return "ip address %s" % ip
|
||||||
elif netaddr.valid_ipv6(addr):
|
elif netaddr.valid_ipv6(address):
|
||||||
return "ipv6 address %s" % x
|
return "ipv6 address %s" % ip
|
||||||
else:
|
else:
|
||||||
raise ValueError("invalid address: %s", x)
|
raise ValueError("invalid address: %s", ip)
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def generate_quagga_boot(cls, node: CoreNode) -> str:
|
def generate_quagga_boot(cls, node: CoreNode) -> str:
|
||||||
|
@ -255,10 +249,9 @@ class QuaggaService(CoreService):
|
||||||
Helper to return the first IPv4 address of a node as its router ID.
|
Helper to return the first IPv4 address of a node as its router ID.
|
||||||
"""
|
"""
|
||||||
for iface in node.get_ifaces(control=False):
|
for iface in node.get_ifaces(control=False):
|
||||||
for a in iface.addrlist:
|
ip4 = iface.get_ip4()
|
||||||
a = a.split("/")[0]
|
if ip4:
|
||||||
if netaddr.valid_ipv4(a):
|
return str(ip4.ip)
|
||||||
return a
|
|
||||||
return f"0.0.0.{node.id:d}"
|
return f"0.0.0.{node.id:d}"
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
|
@ -335,10 +328,8 @@ class Ospfv2(QuaggaService):
|
||||||
cfg += " router-id %s\n" % rtrid
|
cfg += " router-id %s\n" % rtrid
|
||||||
# network 10.0.0.0/24 area 0
|
# network 10.0.0.0/24 area 0
|
||||||
for iface in node.get_ifaces(control=False):
|
for iface in node.get_ifaces(control=False):
|
||||||
for a in iface.addrlist:
|
for ip4 in iface.ip4s:
|
||||||
addr = a.split("/")[0]
|
cfg += f" network {ip4} area 0\n"
|
||||||
if netaddr.valid_ipv4(addr):
|
|
||||||
cfg += " network %s area 0\n" % a
|
|
||||||
cfg += "!\n"
|
cfg += "!\n"
|
||||||
return cfg
|
return cfg
|
||||||
|
|
||||||
|
|
|
@ -5,8 +5,6 @@ sdn.py defines services to start Open vSwitch and the Ryu SDN Controller.
|
||||||
import re
|
import re
|
||||||
from typing import Tuple
|
from typing import Tuple
|
||||||
|
|
||||||
import netaddr
|
|
||||||
|
|
||||||
from core.nodes.base import CoreNode
|
from core.nodes.base import CoreNode
|
||||||
from core.services.coreservices import CoreService
|
from core.services.coreservices import CoreService
|
||||||
|
|
||||||
|
@ -65,18 +63,14 @@ class OvsService(SdnService):
|
||||||
|
|
||||||
# remove ip address of eths because quagga/zebra will assign same IPs to rtr interfaces
|
# 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
|
# or assign them manually to rtr interfaces if zebra is not running
|
||||||
for addr in iface.addrlist:
|
for ip4 in iface.ip4s:
|
||||||
addr = addr.split("/")[0]
|
cfg += "ip addr del %s dev %s\n" % (ip4.ip, iface.name)
|
||||||
if netaddr.valid_ipv4(addr):
|
if has_zebra == 0:
|
||||||
cfg += "ip addr del %s dev %s\n" % (addr, iface.name)
|
cfg += "ip addr add %s dev rtr%s\n" % (ip4.ip, ifnum)
|
||||||
if has_zebra == 0:
|
for ip6 in iface.ip6s:
|
||||||
cfg += "ip addr add %s dev rtr%s\n" % (addr, ifnum)
|
cfg += "ip -6 addr del %s dev %s\n" % (ip6.ip, iface.name)
|
||||||
elif netaddr.valid_ipv6(addr):
|
if has_zebra == 0:
|
||||||
cfg += "ip -6 addr del %s dev %s\n" % (addr, iface.name)
|
cfg += "ip -6 addr add %s dev rtr%s\n" % (ip6.ip, ifnum)
|
||||||
if has_zebra == 0:
|
|
||||||
cfg += "ip -6 addr add %s dev rtr%s\n" % (addr, ifnum)
|
|
||||||
else:
|
|
||||||
raise ValueError("invalid address: %s" % addr)
|
|
||||||
|
|
||||||
# add interfaces to bridge
|
# add interfaces to bridge
|
||||||
# Make port numbers explicit so they're easier to follow in reading the script
|
# Make port numbers explicit so they're easier to follow in reading the script
|
||||||
|
|
|
@ -74,8 +74,8 @@ class DefaultRouteService(UtilService):
|
||||||
ifaces = node.get_ifaces()
|
ifaces = node.get_ifaces()
|
||||||
if ifaces:
|
if ifaces:
|
||||||
iface = ifaces[0]
|
iface = ifaces[0]
|
||||||
for x in iface.addrlist:
|
for ip in iface.ips():
|
||||||
net = netaddr.IPNetwork(x).cidr
|
net = ip.cidr
|
||||||
if net.size > 1:
|
if net.size > 1:
|
||||||
router = net[1]
|
router = net[1]
|
||||||
routes.append(str(router))
|
routes.append(str(router))
|
||||||
|
@ -118,23 +118,22 @@ class StaticRouteService(UtilService):
|
||||||
cfg += "# NOTE: this service must be customized to be of any use\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"
|
cfg += "# Below are samples that you can uncomment and edit.\n#\n"
|
||||||
for iface in node.get_ifaces(control=False):
|
for iface in node.get_ifaces(control=False):
|
||||||
cfg += "\n".join(map(cls.routestr, iface.addrlist))
|
cfg += "\n".join(map(cls.routestr, iface.ips()))
|
||||||
cfg += "\n"
|
cfg += "\n"
|
||||||
return cfg
|
return cfg
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def routestr(x: str) -> str:
|
def routestr(ip: netaddr.IPNetwork) -> str:
|
||||||
addr = x.split("/")[0]
|
address = str(ip.ip)
|
||||||
if netaddr.valid_ipv6(addr):
|
if netaddr.valid_ipv6(address):
|
||||||
dst = "3ffe:4::/64"
|
dst = "3ffe:4::/64"
|
||||||
else:
|
else:
|
||||||
dst = "10.9.8.0/24"
|
dst = "10.9.8.0/24"
|
||||||
net = netaddr.IPNetwork(x)
|
if ip[-2] == ip[1]:
|
||||||
if net[-2] == net[1]:
|
|
||||||
return ""
|
return ""
|
||||||
else:
|
else:
|
||||||
rtcmd = "#/sbin/ip route add %s via" % dst
|
rtcmd = "#/sbin/ip route add %s via" % dst
|
||||||
return "%s %s" % (rtcmd, net[1])
|
return "%s %s" % (rtcmd, ip[1])
|
||||||
|
|
||||||
|
|
||||||
class SshService(UtilService):
|
class SshService(UtilService):
|
||||||
|
@ -242,25 +241,24 @@ max-lease-time 7200;
|
||||||
ddns-update-style none;
|
ddns-update-style none;
|
||||||
"""
|
"""
|
||||||
for iface in node.get_ifaces(control=False):
|
for iface in node.get_ifaces(control=False):
|
||||||
cfg += "\n".join(map(cls.subnetentry, iface.addrlist))
|
cfg += "\n".join(map(cls.subnetentry, iface.ips()))
|
||||||
cfg += "\n"
|
cfg += "\n"
|
||||||
return cfg
|
return cfg
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def subnetentry(x: str) -> str:
|
def subnetentry(ip: netaddr.IPNetwork) -> str:
|
||||||
"""
|
"""
|
||||||
Generate a subnet declaration block given an IPv4 prefix string
|
Generate a subnet declaration block given an IPv4 prefix string
|
||||||
for inclusion in the dhcpd3 config file.
|
for inclusion in the dhcpd3 config file.
|
||||||
"""
|
"""
|
||||||
addr = x.split("/")[0]
|
address = str(ip.ip)
|
||||||
if netaddr.valid_ipv6(addr):
|
if netaddr.valid_ipv6(address):
|
||||||
return ""
|
return ""
|
||||||
else:
|
else:
|
||||||
net = netaddr.IPNetwork(x)
|
|
||||||
# divide the address space in half
|
# divide the address space in half
|
||||||
index = (net.size - 2) / 2
|
index = (ip.size - 2) / 2
|
||||||
rangelow = net[index]
|
rangelow = ip[index]
|
||||||
rangehigh = net[-2]
|
rangehigh = ip[-2]
|
||||||
return """
|
return """
|
||||||
subnet %s netmask %s {
|
subnet %s netmask %s {
|
||||||
pool {
|
pool {
|
||||||
|
@ -270,11 +268,11 @@ subnet %s netmask %s {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
""" % (
|
""" % (
|
||||||
net.ip,
|
ip.ip,
|
||||||
net.netmask,
|
ip.netmask,
|
||||||
rangelow,
|
rangelow,
|
||||||
rangehigh,
|
rangehigh,
|
||||||
addr,
|
address,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
|
@ -557,7 +555,7 @@ export LANG
|
||||||
% node.name
|
% node.name
|
||||||
)
|
)
|
||||||
for iface in node.get_ifaces(control=False):
|
for iface in node.get_ifaces(control=False):
|
||||||
body += "<li>%s - %s</li>\n" % (iface.name, iface.addrlist)
|
body += "<li>%s - %s</li>\n" % (iface.name, [str(x) for x in iface.ips()])
|
||||||
return "<html><body>%s</body></html>" % body
|
return "<html><body>%s</body></html>" % body
|
||||||
|
|
||||||
|
|
||||||
|
@ -625,7 +623,7 @@ class RadvdService(UtilService):
|
||||||
"""
|
"""
|
||||||
cfg = "# auto-generated by RADVD service (utility.py)\n"
|
cfg = "# auto-generated by RADVD service (utility.py)\n"
|
||||||
for iface in node.get_ifaces(control=False):
|
for iface in node.get_ifaces(control=False):
|
||||||
prefixes = list(map(cls.subnetentry, iface.addrlist))
|
prefixes = list(map(cls.subnetentry, iface.ips()))
|
||||||
if len(prefixes) < 1:
|
if len(prefixes) < 1:
|
||||||
continue
|
continue
|
||||||
cfg += (
|
cfg += (
|
||||||
|
@ -658,14 +656,14 @@ interface %s
|
||||||
return cfg
|
return cfg
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def subnetentry(x: str) -> str:
|
def subnetentry(ip: netaddr.IPNetwork) -> str:
|
||||||
"""
|
"""
|
||||||
Generate a subnet declaration block given an IPv6 prefix string
|
Generate a subnet declaration block given an IPv6 prefix string
|
||||||
for inclusion in the RADVD config file.
|
for inclusion in the RADVD config file.
|
||||||
"""
|
"""
|
||||||
addr = x.split("/")[0]
|
address = str(ip.ip)
|
||||||
if netaddr.valid_ipv6(addr):
|
if netaddr.valid_ipv6(address):
|
||||||
return x
|
return str(ip)
|
||||||
else:
|
else:
|
||||||
return ""
|
return ""
|
||||||
|
|
||||||
|
|
|
@ -40,7 +40,7 @@ class XorpRtrmgr(CoreService):
|
||||||
for iface in node.get_ifaces():
|
for iface in node.get_ifaces():
|
||||||
cfg += " interface %s {\n" % iface.name
|
cfg += " interface %s {\n" % iface.name
|
||||||
cfg += "\tvif %s {\n" % iface.name
|
cfg += "\tvif %s {\n" % iface.name
|
||||||
cfg += "".join(map(cls.addrstr, iface.addrlist))
|
cfg += "".join(map(cls.addrstr, iface.ips()))
|
||||||
cfg += cls.lladdrstr(iface)
|
cfg += cls.lladdrstr(iface)
|
||||||
cfg += "\t}\n"
|
cfg += "\t}\n"
|
||||||
cfg += " }\n"
|
cfg += " }\n"
|
||||||
|
@ -55,13 +55,12 @@ class XorpRtrmgr(CoreService):
|
||||||
return cfg
|
return cfg
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def addrstr(x: str) -> str:
|
def addrstr(ip: netaddr.IPNetwork) -> str:
|
||||||
"""
|
"""
|
||||||
helper for mapping IP addresses to XORP config statements
|
helper for mapping IP addresses to XORP config statements
|
||||||
"""
|
"""
|
||||||
addr, plen = x.split("/")
|
cfg = "\t address %s {\n" % ip.ip
|
||||||
cfg = "\t address %s {\n" % addr
|
cfg += "\t\tprefix-length: %s\n" % ip.prefixlen
|
||||||
cfg += "\t\tprefix-length: %s\n" % plen
|
|
||||||
cfg += "\t }\n"
|
cfg += "\t }\n"
|
||||||
return cfg
|
return cfg
|
||||||
|
|
||||||
|
@ -145,10 +144,9 @@ class XorpService(CoreService):
|
||||||
Helper to return the first IPv4 address of a node as its router ID.
|
Helper to return the first IPv4 address of a node as its router ID.
|
||||||
"""
|
"""
|
||||||
for iface in node.get_ifaces(control=False):
|
for iface in node.get_ifaces(control=False):
|
||||||
for a in iface.addrlist:
|
ip4 = iface.get_ip4()
|
||||||
a = a.split("/")[0]
|
if ip4:
|
||||||
if netaddr.valid_ipv4(a):
|
return str(ip4.ip)
|
||||||
return a
|
|
||||||
return "0.0.0.0"
|
return "0.0.0.0"
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
|
@ -180,11 +178,8 @@ class XorpOspfv2(XorpService):
|
||||||
for iface in node.get_ifaces(control=False):
|
for iface in node.get_ifaces(control=False):
|
||||||
cfg += "\t interface %s {\n" % iface.name
|
cfg += "\t interface %s {\n" % iface.name
|
||||||
cfg += "\t\tvif %s {\n" % iface.name
|
cfg += "\t\tvif %s {\n" % iface.name
|
||||||
for a in iface.addrlist:
|
for ip4 in iface.ip4s:
|
||||||
addr = a.split("/")[0]
|
cfg += "\t\t address %s {\n" % ip4.ip
|
||||||
if not netaddr.valid_ipv4(addr):
|
|
||||||
continue
|
|
||||||
cfg += "\t\t address %s {\n" % addr
|
|
||||||
cfg += "\t\t }\n"
|
cfg += "\t\t }\n"
|
||||||
cfg += "\t\t}\n"
|
cfg += "\t\t}\n"
|
||||||
cfg += "\t }\n"
|
cfg += "\t }\n"
|
||||||
|
@ -269,11 +264,8 @@ class XorpRip(XorpService):
|
||||||
for iface in node.get_ifaces(control=False):
|
for iface in node.get_ifaces(control=False):
|
||||||
cfg += "\tinterface %s {\n" % iface.name
|
cfg += "\tinterface %s {\n" % iface.name
|
||||||
cfg += "\t vif %s {\n" % iface.name
|
cfg += "\t vif %s {\n" % iface.name
|
||||||
for a in iface.addrlist:
|
for ip4 in iface.ip4s:
|
||||||
addr = a.split("/")[0]
|
cfg += "\t\taddress %s {\n" % ip4.ip
|
||||||
if not netaddr.valid_ipv4(addr):
|
|
||||||
continue
|
|
||||||
cfg += "\t\taddress %s {\n" % addr
|
|
||||||
cfg += "\t\t disable: false\n"
|
cfg += "\t\t disable: false\n"
|
||||||
cfg += "\t\t}\n"
|
cfg += "\t\t}\n"
|
||||||
cfg += "\t }\n"
|
cfg += "\t }\n"
|
||||||
|
@ -435,11 +427,8 @@ class XorpOlsr(XorpService):
|
||||||
for iface in node.get_ifaces(control=False):
|
for iface in node.get_ifaces(control=False):
|
||||||
cfg += "\tinterface %s {\n" % iface.name
|
cfg += "\tinterface %s {\n" % iface.name
|
||||||
cfg += "\t vif %s {\n" % iface.name
|
cfg += "\t vif %s {\n" % iface.name
|
||||||
for a in iface.addrlist:
|
for ip4 in iface.ip4s:
|
||||||
addr = a.split("/")[0]
|
cfg += "\t\taddress %s {\n" % ip4.ip
|
||||||
if not netaddr.valid_ipv4(addr):
|
|
||||||
continue
|
|
||||||
cfg += "\t\taddress %s {\n" % addr
|
|
||||||
cfg += "\t\t}\n"
|
cfg += "\t\t}\n"
|
||||||
cfg += "\t }\n"
|
cfg += "\t }\n"
|
||||||
cfg += "\t}\n"
|
cfg += "\t}\n"
|
||||||
|
|
|
@ -164,6 +164,7 @@ class CoreXmlDeployment:
|
||||||
if emane_element is not None:
|
if emane_element is not None:
|
||||||
parent_element = emane_element
|
parent_element = emane_element
|
||||||
|
|
||||||
for address in iface.addrlist:
|
for ip in iface.ips():
|
||||||
|
address = str(ip.ip)
|
||||||
address_type = get_address_type(address)
|
address_type = get_address_type(address)
|
||||||
add_address(parent_element, address_type, address, iface.name)
|
add_address(parent_element, address_type, address, iface.name)
|
||||||
|
|
|
@ -75,31 +75,31 @@ class TestNodes:
|
||||||
with pytest.raises(CoreError):
|
with pytest.raises(CoreError):
|
||||||
node.set_mac(iface.node_id, mac)
|
node.set_mac(iface.node_id, mac)
|
||||||
|
|
||||||
def test_node_addaddr(self, session: Session):
|
def test_node_add_ip(self, session: Session):
|
||||||
# given
|
# given
|
||||||
node = session.add_node(CoreNode)
|
node = session.add_node(CoreNode)
|
||||||
switch = session.add_node(SwitchNode)
|
switch = session.add_node(SwitchNode)
|
||||||
iface_data = InterfaceData()
|
iface_data = InterfaceData()
|
||||||
iface = node.new_iface(switch, iface_data)
|
iface = node.new_iface(switch, iface_data)
|
||||||
addr = "192.168.0.1/24"
|
ip = "192.168.0.1/24"
|
||||||
|
|
||||||
# when
|
# when
|
||||||
node.addaddr(iface.node_id, addr)
|
node.add_ip(iface.node_id, ip)
|
||||||
|
|
||||||
# then
|
# then
|
||||||
assert iface.addrlist[0] == addr
|
assert str(iface.get_ip4()) == ip
|
||||||
|
|
||||||
def test_node_addaddr_exception(self, session):
|
def test_node_add_ip_exception(self, session):
|
||||||
# given
|
# given
|
||||||
node = session.add_node(CoreNode)
|
node = session.add_node(CoreNode)
|
||||||
switch = session.add_node(SwitchNode)
|
switch = session.add_node(SwitchNode)
|
||||||
iface_data = InterfaceData()
|
iface_data = InterfaceData()
|
||||||
iface = node.new_iface(switch, iface_data)
|
iface = node.new_iface(switch, iface_data)
|
||||||
addr = "256.168.0.1/24"
|
ip = "256.168.0.1/24"
|
||||||
|
|
||||||
# when
|
# when
|
||||||
with pytest.raises(CoreError):
|
with pytest.raises(CoreError):
|
||||||
node.addaddr(iface.node_id, addr)
|
node.add_ip(iface.node_id, ip)
|
||||||
|
|
||||||
@pytest.mark.parametrize("net_type", NET_TYPES)
|
@pytest.mark.parametrize("net_type", NET_TYPES)
|
||||||
def test_net(self, session, net_type):
|
def test_net(self, session, net_type):
|
||||||
|
|
Loading…
Add table
Reference in a new issue