daemon: adjustments to support global configurable mtu values for node interfaces and bridges

This commit is contained in:
Blake Harnden 2021-12-21 08:59:48 -08:00
parent 5ff4447528
commit 0b531d7fd8
9 changed files with 72 additions and 50 deletions

View file

@ -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()

View file

@ -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

View file

@ -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):
"""

View file

@ -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)

View file

@ -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