Skip to content

Commit

Permalink
Merge pull request #69 from fabric-testbed/rel1
Browse files Browse the repository at this point in the history
Adding guardrails for P2P and S2S services w.r.t. shared interfaces. …
  • Loading branch information
ibaldin authored Jul 22, 2021
2 parents 27db965 + b3782a3 commit 3b94662
Show file tree
Hide file tree
Showing 3 changed files with 37 additions and 10 deletions.
2 changes: 1 addition & 1 deletion fim/__init__.py
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
#
__VERSION__ = "1.0rc3"
__VERSION__ = "1.0"
32 changes: 29 additions & 3 deletions fim/user/network_service.py
Original file line number Diff line number Diff line change
Expand Up @@ -103,7 +103,7 @@ def __init__(self, *, name: str, node_id: str = None, topo: Any,
for interface in interfaces:
owner = topo.get_owner_node(interface)
sites.add(owner.get_property('site'))
if len(sites) > NetworkServiceSliver.ServiceConstraints[nstype].num_sites:
if len(sites) != NetworkServiceSliver.ServiceConstraints[nstype].num_sites:
raise RuntimeError(f"Service of type {nstype} cannot span {len(sites)} sites. "
f"Limit: {NetworkServiceSliver.ServiceConstraints[nstype].num_sites}.")
# set site property for services that only are in one site
Expand All @@ -123,7 +123,9 @@ def __init__(self, *, name: str, node_id: str = None, topo: Any,
self._interfaces = list()
if interfaces is not None and len(interfaces) > 0:
for i in interfaces:
self.connect_interface(interface=i)
# run through guardrails, then connect
self.__service_guardrails(sliver, i)
self.__connect_interface(interface=i)
else:
assert node_id is not None
super().__init__(name=name, node_id=node_id, topo=topo)
Expand All @@ -142,7 +144,30 @@ def __init__(self, *, name: str, node_id: str = None, topo: Any,
name_id_tuples.append((props[ABCPropertyGraph.PROP_NAME], iff))
self._interfaces = [Interface(node_id=tup[1], topo=topo, name=tup[0]) for tup in name_id_tuples]

def connect_interface(self, *, interface: Interface):
@staticmethod
def __service_guardrails(sliver: NetworkServiceSliver, interface: Interface):
"""
Checks if this interface can be added to this service for various reasons related to e.g.
service implementation constraints (that can be temporary and change from release to release).
Prints warnings or throws exceptions.
:param sliver:
:param interface:
:return:
"""
# - L2P2P service does not work for shared ports
# - L2S2S needs to warn that it may not work if the VMs with shared ports land on the same worker
if sliver.get_type() == ServiceType.L2PTP and \
interface.get_property('type') == InterfaceType.SharedPort:
raise RuntimeError(f"Unable to connect interface {interface.name} to service {sliver.get_name()}: "
f"L2P2P service currently doesn't support shared interfaces")
if sliver.get_type() == ServiceType.L2STS and \
interface.get_property('type') == InterfaceType.SharedPort:
print('WARNING: Current implementation of L2STS service does not support hairpins (connections withing the '
'same physical port), if your VMs are assigned to the same worker node, communications between them '
'over this service will not be possible! We recommend not using L2STS with shared ports unless you '
'know what you are doing.')

def __connect_interface(self, *, interface: Interface):
"""
Connect a (compute or switch) node interface to network service by transparently
creating a peer service interface and a link between them
Expand All @@ -152,6 +177,7 @@ def connect_interface(self, *, interface: Interface):
assert interface is not None
assert isinstance(interface, Interface)

# FIXME: IMPORTANT need to check number of connected interfaces here, not just in service constructor
# we can only connect interfaces connected to (compute or switch) nodes
if self.topo.get_owner_node(interface) is None:
raise RuntimeError(f'Interface {interface} is not owned by a node, as expected.')
Expand Down
13 changes: 7 additions & 6 deletions test/slice_topology_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -161,6 +161,7 @@ def testNetworkServices(self):
# component checks
n1.add_component(ctype=f.ComponentType.GPU, model='RTX6000', name='gpu1')
n1.add_component(model_type=f.ComponentModelType.SharedNIC_ConnectX_6, name='nic1')
n1.add_component(model_type=f.ComponentModelType.SmartNIC_ConnectX_6, name='nic4')
n2.add_component(ctype=f.ComponentType.SmartNIC, model='ConnectX-6', name='nic2')
n3.add_component(ctype=f.ComponentType.SharedNIC, model='ConnectX-6', name='nic3')

Expand Down Expand Up @@ -191,7 +192,7 @@ def testNetworkServices(self):
s1 = self.topo.add_network_service(name='s1', nstype=f.ServiceType.L2STS, interfaces=self.topo.interface_list)

print(f'S1 has these interfaces: {s1.interface_list}')
self.assertEqual(len(s1.interface_list), 4)
self.assertEqual(len(s1.interface_list), 6)

s1p = self.topo.network_services['s1']

Expand All @@ -200,23 +201,23 @@ def testNetworkServices(self):
s1.disconnect_interface(interface=p1)

print(f'S1 has these interfaces: {s1.interface_list}')
self.assertEqual(len(s1.interface_list), 3)
self.assertEqual(len(s1.interface_list), 5)

self.topo.remove_network_service('s1')

s2 = self.topo.add_network_service(name='s2', nstype=f.ServiceType.L2PTP,
interfaces=self.topo.interface_list[0:2])
interfaces=self.topo.interface_list[2:4])
self.assertEqual(len(s2.interface_list), 2)
print(f'S2 has these interfaces: {s2.interface_list}')

print(f'There are {self.topo.links} left in topology')
self.assertEqual(len(self.topo.links), 2)
print(f'Network services {self.topo.network_services}')
self.assertEqual(len(self.topo.network_services), 4)
self.assertEqual(len(self.topo.network_services), 5)
self.topo.remove_network_service('s2')
self.assertEqual(len(self.topo.network_services), 3)
self.assertEqual(len(self.topo.network_services), 4)
n1.remove_component('nic1')
self.assertEqual(len(self.topo.network_services), 2)
self.assertEqual(len(self.topo.network_services), 3)

#self.topo.add_link(name='l3', ltype=f.LinkType.L2Bridge, interfaces=self.topo.interface_list)

Expand Down

0 comments on commit 3b94662

Please sign in to comment.