daemon: adjustments to support global configurable mtu values for node interfaces and bridges
This commit is contained in:
parent
5ff4447528
commit
0b531d7fd8
9 changed files with 72 additions and 50 deletions
|
@ -142,6 +142,7 @@ class InterfaceData:
|
|||
ip4_mask: int = None
|
||||
ip6: str = None
|
||||
ip6_mask: int = None
|
||||
mtu: int = None
|
||||
|
||||
def get_ips(self) -> List[str]:
|
||||
"""
|
||||
|
|
|
@ -187,6 +187,7 @@ class DistributedController:
|
|||
|
||||
:return: nothing
|
||||
"""
|
||||
mtu = self.session.options.get_config_int("mtu")
|
||||
for node_id in self.session.nodes:
|
||||
node = self.session.nodes[node_id]
|
||||
if not isinstance(node, CoreNetwork):
|
||||
|
@ -195,17 +196,17 @@ class DistributedController:
|
|||
continue
|
||||
for name in self.servers:
|
||||
server = self.servers[name]
|
||||
self.create_gre_tunnel(node, server)
|
||||
self.create_gre_tunnel(node, server, mtu)
|
||||
|
||||
def create_gre_tunnel(
|
||||
self, node: CoreNetwork, server: DistributedServer
|
||||
self, node: CoreNetwork, server: DistributedServer, mtu: int
|
||||
) -> Tuple[GreTap, GreTap]:
|
||||
"""
|
||||
Create gre tunnel using a pair of gre taps between the local and remote server.
|
||||
|
||||
:param node: node to create gre tunnel for
|
||||
:param server: server to create
|
||||
tunnel for
|
||||
:param server: server to create tunnel for
|
||||
:param mtu: mtu for gre taps
|
||||
:return: local and remote gre taps created for tunnel
|
||||
"""
|
||||
host = server.host
|
||||
|
@ -215,14 +216,14 @@ class DistributedController:
|
|||
return tunnel
|
||||
# local to server
|
||||
logger.info("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 = GreTap(session=self.session, remoteip=host, key=key, mtu=mtu)
|
||||
local_tap.net_client.set_iface_master(node.brname, local_tap.localname)
|
||||
# server to local
|
||||
logger.info(
|
||||
"remote tunnel node(%s) to local(%s) key(%s)", node.name, self.address, key
|
||||
)
|
||||
remote_tap = GreTap(
|
||||
session=self.session, remoteip=self.address, key=key, server=server
|
||||
session=self.session, remoteip=self.address, key=key, server=server, mtu=mtu
|
||||
)
|
||||
remote_tap.net_client.set_iface_master(node.brname, remote_tap.localname)
|
||||
# save tunnels for shutdown
|
||||
|
|
|
@ -46,7 +46,7 @@ from core.location.geo import GeoLocation
|
|||
from core.location.mobility import BasicRangeModel, MobilityManager
|
||||
from core.nodes.base import CoreNetworkBase, CoreNode, CoreNodeBase, NodeBase
|
||||
from core.nodes.docker import DockerNode
|
||||
from core.nodes.interface import CoreInterface
|
||||
from core.nodes.interface import DEFAULT_MTU, CoreInterface
|
||||
from core.nodes.lxd import LxcNode
|
||||
from core.nodes.network import (
|
||||
CtrlNet,
|
||||
|
@ -253,7 +253,12 @@ class Session:
|
|||
node2 = self.get_node(node2_id, NodeBase)
|
||||
iface1 = None
|
||||
iface2 = None
|
||||
|
||||
# set mtu
|
||||
mtu = self.options.get_config_int("mtu") or DEFAULT_MTU
|
||||
if iface1_data:
|
||||
iface1_data.mtu = mtu
|
||||
if iface2_data:
|
||||
iface2_data.mtu = mtu
|
||||
# wireless link
|
||||
if link_type == LinkTypes.WIRELESS:
|
||||
if isinstance(node1, CoreNodeBase) and isinstance(node2, CoreNodeBase):
|
||||
|
@ -567,12 +572,18 @@ class Session:
|
|||
service_class = self.service_manager.get_service(name)
|
||||
node.add_config_service(service_class)
|
||||
|
||||
# set network mtu, if configured
|
||||
mtu = self.options.get_config_int("mtu")
|
||||
if isinstance(node, CoreNetworkBase) and mtu > 0:
|
||||
node.mtu = mtu
|
||||
|
||||
# ensure default emane configuration
|
||||
if isinstance(node, EmaneNet) and options.emane:
|
||||
model_class = self.emane.get_model(options.emane)
|
||||
node.model = model_class(self, node.id)
|
||||
if self.state == EventTypes.RUNTIME_STATE:
|
||||
self.emane.add_node(node)
|
||||
|
||||
# set default wlan config if needed
|
||||
if isinstance(node, WlanNode):
|
||||
self.mobility.set_model_config(_id, BasicRangeModel.name)
|
||||
|
|
|
@ -40,6 +40,7 @@ class SessionConfig(ConfigurableManager, ConfigurableOptions):
|
|||
id="link_interval", default="1", label="EMANE Link Check Interval (sec)"
|
||||
),
|
||||
ConfigInt(id="link_timeout", default="4", label="EMANE Link Timeout (sec)"),
|
||||
ConfigInt(id="mtu", default="0", label="MTU for All Devices"),
|
||||
]
|
||||
config_type: RegisterTlvs = RegisterTlvs.UTILITY
|
||||
|
||||
|
|
|
@ -18,7 +18,7 @@ from core.emulator.enumerations import LinkTypes, MessageFlags, NodeTypes
|
|||
from core.errors import CoreCommandError, CoreError
|
||||
from core.executables import MOUNT, TEST, VNODED
|
||||
from core.nodes.client import VnodeClient
|
||||
from core.nodes.interface import CoreInterface, TunTap, Veth
|
||||
from core.nodes.interface import DEFAULT_MTU, CoreInterface, TunTap, Veth
|
||||
from core.nodes.netclient import LinuxNetClient, get_net_client
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
@ -712,47 +712,37 @@ class CoreNode(CoreNodeBase):
|
|||
with self.lock:
|
||||
return super().next_iface_id()
|
||||
|
||||
def newveth(self, iface_id: int = None, ifname: str = None) -> int:
|
||||
def newveth(
|
||||
self, iface_id: int = None, ifname: str = None, mtu: int = DEFAULT_MTU
|
||||
) -> int:
|
||||
"""
|
||||
Create a new interface.
|
||||
|
||||
:param iface_id: id for the new interface
|
||||
:param ifname: name for the new interface
|
||||
:param mtu: mtu for interface
|
||||
:return: nothing
|
||||
"""
|
||||
with self.lock:
|
||||
if iface_id is None:
|
||||
iface_id = self.next_iface_id()
|
||||
|
||||
if ifname is None:
|
||||
ifname = f"eth{iface_id}"
|
||||
|
||||
iface_id = iface_id if iface_id is not None else self.next_iface_id()
|
||||
ifname = ifname if ifname is not None else f"eth{iface_id}"
|
||||
sessionid = self.session.short_session_id()
|
||||
|
||||
try:
|
||||
suffix = f"{self.id:x}.{iface_id}.{sessionid}"
|
||||
except TypeError:
|
||||
suffix = f"{self.id}.{iface_id}.{sessionid}"
|
||||
|
||||
localname = f"veth{suffix}"
|
||||
if len(localname) >= 16:
|
||||
raise ValueError(f"interface local name ({localname}) too long")
|
||||
|
||||
name = localname + "p"
|
||||
raise CoreError(f"interface local name ({localname}) too long")
|
||||
name = f"{localname}p"
|
||||
if len(name) >= 16:
|
||||
raise ValueError(f"interface name ({name}) too long")
|
||||
|
||||
veth = Veth(
|
||||
self.session, self, name, localname, start=self.up, server=self.server
|
||||
)
|
||||
|
||||
raise CoreError(f"interface name ({name}) too long")
|
||||
veth = Veth(self.session, self, name, localname, mtu, self.server, self.up)
|
||||
if self.up:
|
||||
self.net_client.device_ns(veth.name, str(self.pid))
|
||||
self.node_net_client.device_name(veth.name, ifname)
|
||||
self.node_net_client.checksums_off(ifname)
|
||||
|
||||
veth.name = ifname
|
||||
|
||||
if self.up:
|
||||
flow_id = self.node_net_client.get_ifindex(veth.name)
|
||||
veth.flow_id = int(flow_id)
|
||||
|
@ -760,16 +750,14 @@ class CoreNode(CoreNodeBase):
|
|||
mac = self.node_net_client.get_mac(veth.name)
|
||||
logger.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.add_iface(veth, iface_id)
|
||||
except ValueError as e:
|
||||
except CoreError as e:
|
||||
veth.shutdown()
|
||||
del veth
|
||||
raise e
|
||||
|
||||
return iface_id
|
||||
|
||||
def newtuntap(self, iface_id: int = None, ifname: str = None) -> int:
|
||||
|
@ -781,24 +769,18 @@ class CoreNode(CoreNodeBase):
|
|||
:return: interface index
|
||||
"""
|
||||
with self.lock:
|
||||
if iface_id is None:
|
||||
iface_id = self.next_iface_id()
|
||||
|
||||
if ifname is None:
|
||||
ifname = f"eth{iface_id}"
|
||||
|
||||
iface_id = iface_id if iface_id is not None else self.next_iface_id()
|
||||
ifname = ifname if ifname is not None else f"eth{iface_id}"
|
||||
sessionid = self.session.short_session_id()
|
||||
localname = f"tap{self.id}.{iface_id}.{sessionid}"
|
||||
name = ifname
|
||||
tuntap = TunTap(self.session, self, name, localname, start=self.up)
|
||||
|
||||
try:
|
||||
self.add_iface(tuntap, iface_id)
|
||||
except ValueError as e:
|
||||
except CoreError as e:
|
||||
tuntap.shutdown()
|
||||
del tuntap
|
||||
raise e
|
||||
|
||||
return iface_id
|
||||
|
||||
def set_mac(self, iface_id: int, mac: str) -> None:
|
||||
|
@ -879,7 +861,7 @@ class CoreNode(CoreNodeBase):
|
|||
raise CoreError(
|
||||
f"node({self.name}) already has interface({iface_id})"
|
||||
)
|
||||
iface_id = self.newveth(iface_id, iface_data.name)
|
||||
iface_id = self.newveth(iface_id, iface_data.name, iface_data.mtu)
|
||||
self.attachnet(iface_id, net)
|
||||
if iface_data.mac:
|
||||
self.set_mac(iface_id, iface_data.mac)
|
||||
|
@ -1001,13 +983,14 @@ class CoreNetworkBase(NodeBase):
|
|||
"""
|
||||
Create a CoreNetworkBase instance.
|
||||
|
||||
:param session: CORE session object
|
||||
:param session: session object
|
||||
:param _id: object id
|
||||
:param name: object name
|
||||
:param server: remote server node
|
||||
will run on, default is None for localhost
|
||||
"""
|
||||
super().__init__(session, _id, name, server)
|
||||
self.mtu: int = DEFAULT_MTU
|
||||
self.brname: Optional[str] = None
|
||||
self.linked: Dict[CoreInterface, Dict[CoreInterface, bool]] = {}
|
||||
self.linked_lock: threading.Lock = threading.Lock()
|
||||
|
|
|
@ -378,6 +378,9 @@ class Veth(CoreInterface):
|
|||
:raises CoreCommandError: when there is a command exception
|
||||
"""
|
||||
self.net_client.create_veth(self.localname, self.name)
|
||||
if self.mtu > 0:
|
||||
self.net_client.set_mtu(self.name, self.mtu)
|
||||
self.net_client.set_mtu(self.localname, self.mtu)
|
||||
self.net_client.device_up(self.localname)
|
||||
self.up = True
|
||||
|
||||
|
@ -455,12 +458,10 @@ class TunTap(CoreInterface):
|
|||
"""
|
||||
if not self.up:
|
||||
return
|
||||
|
||||
try:
|
||||
self.node.node_net_client.device_flush(self.name)
|
||||
except CoreCommandError:
|
||||
logger.exception("error shutting down tunnel tap")
|
||||
|
||||
self.up = False
|
||||
|
||||
def waitfor(
|
||||
|
@ -584,7 +585,7 @@ class GreTap(CoreInterface):
|
|||
node: "CoreNode" = None,
|
||||
name: str = None,
|
||||
session: "Session" = None,
|
||||
mtu: int = 1458,
|
||||
mtu: int = DEFAULT_MTU,
|
||||
remoteip: str = None,
|
||||
_id: int = None,
|
||||
localip: str = None,
|
||||
|
@ -622,6 +623,8 @@ class GreTap(CoreInterface):
|
|||
if remoteip is None:
|
||||
raise CoreError("missing remote IP required for GRE TAP device")
|
||||
self.net_client.create_gretap(self.localname, remoteip, localip, ttl, key)
|
||||
if self.mtu > 0:
|
||||
self.net_client.set_mtu(self.localname, self.mtu)
|
||||
self.net_client.device_up(self.localname)
|
||||
self.up = True
|
||||
|
||||
|
|
|
@ -296,6 +296,16 @@ class LinuxNetClient:
|
|||
"""
|
||||
self.run(f"{IP} link set {name} type bridge ageing_time {value}")
|
||||
|
||||
def set_mtu(self, name: str, value: int) -> None:
|
||||
"""
|
||||
Sets the mtu value for a device.
|
||||
|
||||
:param name: name of device to set value for
|
||||
:param value: mtu value to set
|
||||
:return: nothing
|
||||
"""
|
||||
self.run(f"{IP} link set {name} mtu {value}")
|
||||
|
||||
|
||||
class OvsNetClient(LinuxNetClient):
|
||||
"""
|
||||
|
|
|
@ -290,12 +290,14 @@ class CoreNetwork(CoreNetworkBase):
|
|||
|
||||
def startup(self) -> None:
|
||||
"""
|
||||
Linux bridge starup logic.
|
||||
Linux bridge startup logic.
|
||||
|
||||
:return: nothing
|
||||
:raises CoreCommandError: when there is a command exception
|
||||
"""
|
||||
self.net_client.create_bridge(self.brname)
|
||||
if self.mtu > 0:
|
||||
self.net_client.set_mtu(self.brname, self.mtu)
|
||||
self.has_nftables_chain = False
|
||||
self.up = True
|
||||
nft_queue.start(self)
|
||||
|
@ -584,6 +586,7 @@ class GreTapBridge(CoreNetwork):
|
|||
localip=localip,
|
||||
ttl=ttl,
|
||||
key=self.grekey,
|
||||
mtu=self.mtu,
|
||||
)
|
||||
|
||||
def startup(self) -> None:
|
||||
|
@ -619,7 +622,7 @@ class GreTapBridge(CoreNetwork):
|
|||
:return: nothing
|
||||
"""
|
||||
if self.gretap:
|
||||
raise ValueError(f"gretap already exists for {self.name}")
|
||||
raise CoreError(f"gretap already exists for {self.name}")
|
||||
remoteip = ips[0].split("/")[0]
|
||||
localip = None
|
||||
if len(ips) > 1:
|
||||
|
@ -630,6 +633,7 @@ class GreTapBridge(CoreNetwork):
|
|||
localip=localip,
|
||||
ttl=self.ttl,
|
||||
key=self.grekey,
|
||||
mtu=self.mtu,
|
||||
)
|
||||
self.attach(self.gretap)
|
||||
|
||||
|
|
|
@ -176,12 +176,20 @@ class PhysicalNode(CoreNodeBase):
|
|||
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)
|
||||
_, remote_tap = self.session.distributed.create_gre_tunnel(
|
||||
net, self.server, iface_data.mtu
|
||||
)
|
||||
self.adopt_iface(remote_tap, iface_id, iface_data.mac, ips)
|
||||
return remote_tap
|
||||
else:
|
||||
# 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,
|
||||
mtu=iface_data.mtu,
|
||||
)
|
||||
self.adopt_iface(iface, iface_id, iface_data.mac, ips)
|
||||
return iface
|
||||
|
||||
|
|
Loading…
Reference in a new issue