Skip to content
This repository has been archived by the owner on Apr 22, 2024. It is now read-only.

Commit

Permalink
Merge pull request #651 from cemsbr/custom-speed
Browse files Browse the repository at this point in the history
Custom Interface speed
  • Loading branch information
beraldoleal committed Nov 6, 2017
2 parents 5289484 + a2ad8c9 commit 9cf8cb8
Show file tree
Hide file tree
Showing 2 changed files with 94 additions and 25 deletions.
68 changes: 53 additions & 15 deletions kytos/core/switch.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ class Interface: # pylint: disable=too-many-instance-attributes

# pylint: disable=too-many-arguments
def __init__(self, name, port_number, switch, address=None, state=None,
features=None):
features=None, speed=None):
"""Assign the parameters to instance attributes.
Args:
Expand All @@ -29,6 +29,9 @@ def __init__(self, name, port_number, switch, address=None, state=None,
state (|port_stats|): Port Stat from interface.
features (|port_features|): Port feature used to calculate link
utilization from this interface.
speed (int, float): Interface speed in bytes per second. Defaults
to what is informed by the switch. Return ``None`` if not set
and switch does not inform the speed.
"""
self.name = name
self.port_number = int(port_number)
Expand All @@ -39,6 +42,7 @@ def __init__(self, name, port_number, switch, address=None, state=None,
self.nni = False
self.endpoints = []
self.stats = None
self._custom_speed = speed

def __eq__(self, other):
"""Compare Interface class with another instance."""
Expand Down Expand Up @@ -112,7 +116,36 @@ def update_endpoint(self, endpoint):
self.delete_endpoint(endpoint)
self.add_endpoint(endpoint)

def get_speed(self):
@property
def speed(self):
"""Return the link speed in bytes per second, None otherwise.
If the switch was disconnected, we have :attr:`features` and speed is
still returned for common values between v0x01 and v0x04. For specific
v0x04 values (40 Gbps, 100 Gbps and 1 Tbps), the connection must be
active so we can make sure the protocol version is v0x04.
Returns:
int, None: Link speed in bytes per second or ``None``.
"""
if self._custom_speed is not None:
return self._custom_speed
return self.get_of_features_speed()

def set_custom_speed(self, bytes_per_second):
"""Set a speed that overrides switch OpenFlow information.
If ``None`` is given, :attr:`speed` becomes the one given by the
switch.
"""
self._custom_speed = bytes_per_second

def get_custom_speed(self):
"""Return custom speed or ``None`` if not set."""
return self._custom_speed

def get_of_features_speed(self):
"""Return the link speed in bytes per second, None otherwise.
If the switch was disconnected, we have :attr:`features` and speed is
Expand All @@ -126,18 +159,23 @@ def get_speed(self):
"""
speed = self._get_v0x01_v0x04_speed()
# Don't use switch.is_connected() because we can have the protocol
if speed is None and self.switch.is_connected() and \
self.switch.connection.protocol.version == 0x04:
if speed is None and self._is_v0x04():
speed = self._get_v0x04_speed()
if speed is None:
# Use shorter switch ID with its beginning and end
if isinstance(self.switch.id, str) and len(self.switch.id) > 20:
switch_id = self.switch.id[:3] + '...' + self.switch.id[-3:]
else:
switch_id = self.switch.id
LOG.warning("No speed port %s, sw %s, feats %s", self.port_number,
switch_id, self.features)
return speed
if speed is not None:
return speed
# Warn unknown speed
# Use shorter switch ID with its beginning and end
if isinstance(self.switch.id, str) and len(self.switch.id) > 20:
switch_id = self.switch.id[:3] + '...' + self.switch.id[-3:]
else:
switch_id = self.switch.id
LOG.warning("Couldn't get port %s speed, sw %s, feats %s",
self.port_number, switch_id, self.features)

def _is_v0x04(self):
"""Whether the switch is connected using OpenFlow 1.3."""
return self.switch.is_connected() and \
self.switch.connection.protocol.version == 0x04

def _get_v0x01_v0x04_speed(self):
"""Check against all values of v0x01. They're part of v0x04."""
Expand Down Expand Up @@ -173,7 +211,7 @@ def get_hr_speed(self):
string: String with link speed. e.g: '350 Gbps' or '350 Mbps'.
"""
speed = self.get_speed()
speed = self.speed
if speed is None:
return ''
speed *= 8
Expand Down Expand Up @@ -212,7 +250,7 @@ def as_dict(self):
'type': 'interface',
'nni': self.nni,
'uni': self.uni,
'speed': self.get_speed()}
'speed': self.speed}
if self.stats:
iface_dict['stats'] = self.stats.as_dict()
return iface_dict
Expand Down
51 changes: 41 additions & 10 deletions tests/test_core/test_interface.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,61 +15,92 @@ class TestInterface(unittest.TestCase):

def setUp(self):
"""Create interface object."""
self.iface = self._get_v0x04_iface()

@staticmethod
def _get_v0x04_iface(*args, **kwargs):
"""Create a v0x04 interface object with optional extra arguments."""
switch = Switch('dpid')
switch.connection = Mock()
switch.connection.protocol.version = 0x04
self.iface = Interface('name', 42, switch)
return Interface('name', 42, switch, *args, **kwargs)

def test_speed_feature_none(self):
"""When port's current features is None."""
self.iface.features = None
self.assertIsNone(self.iface.get_speed())
self.assertIsNone(self.iface.speed)
self.assertEqual('', self.iface.get_hr_speed())

def test_speed_feature_zero(self):
"""When port's current features is 0. E.g. port 65534."""
self.iface.features = 0
self.assertIsNone(self.iface.get_speed())
self.assertIsNone(self.iface.speed)
self.assertEqual('', self.iface.get_hr_speed())

def test_1_tera_speed(self):
"""1Tb link."""
self.iface.features = PortFeatures.OFPPF_1TB_FD
self.assertEqual(10**12 / 8, self.iface.get_speed())
self.assertEqual(10**12 / 8, self.iface.speed)
self.assertEqual('1 Tbps', self.iface.get_hr_speed())

def test_100_giga_speed(self):
"""100Gb link."""
self.iface.features = PortFeatures.OFPPF_100GB_FD
self.assertEqual(100 * 10**9 / 8, self.iface.get_speed())
self.assertEqual(100 * 10**9 / 8, self.iface.speed)
self.assertEqual('100 Gbps', self.iface.get_hr_speed())

def test_40_giga_speed(self):
"""40Gb link."""
self.iface.features = PortFeatures.OFPPF_40GB_FD
self.assertEqual(40 * 10**9 / 8, self.iface.get_speed())
self.assertEqual(40 * 10**9 / 8, self.iface.speed)
self.assertEqual('40 Gbps', self.iface.get_hr_speed())

def test_10_giga_speed(self):
"""10Gb link."""
self.iface.features = PortFeatures.OFPPF_10GB_FD
self.assertEqual(10 * 10**9 / 8, self.iface.get_speed())
self.assertEqual(10 * 10**9 / 8, self.iface.speed)
self.assertEqual('10 Gbps', self.iface.get_hr_speed())

def test_1_giga_speed(self):
"""1Gb link."""
self.iface.features = PortFeatures.OFPPF_1GB_FD
self.assertEqual(10**9 / 8, self.iface.get_speed())
self.assertEqual(10**9 / 8, self.iface.speed)
self.assertEqual('1 Gbps', self.iface.get_hr_speed())

def test_100_mega_speed(self):
"""100Mb link."""
self.iface.features = PortFeatures.OFPPF_100MB_FD
self.assertEqual(100 * 10**6 / 8, self.iface.get_speed())
self.assertEqual(100 * 10**6 / 8, self.iface.speed)
self.assertEqual('100 Mbps', self.iface.get_hr_speed())

def test_10_mega_speed(self):
"""10Mb link."""
self.iface.features = PortFeatures.OFPPF_10MB_FD
self.assertEqual(10 * 10**6 / 8, self.iface.get_speed())
self.assertEqual(10 * 10**6 / 8, self.iface.speed)
self.assertEqual('10 Mbps', self.iface.get_hr_speed())

def test_speed_setter(self):
"""Should return speed that was set and not features'."""
expected_speed = 12345
self.iface.features = PortFeatures.OFPPF_10MB_FD
self.iface.set_custom_speed(expected_speed)
actual_speed = self.iface.speed
self.assertEqual(expected_speed, actual_speed)

def test_speed_in_constructor(self):
"""Custom speed should override features'."""
expected_speed = 6789
iface = self._get_v0x04_iface(speed=expected_speed,
features=PortFeatures.OFPPF_10MB_FD)
actual_speed = iface.speed
self.assertEqual(expected_speed, actual_speed)

def test_remove_custom_speed(self):
"""Should return features' speed again when custom's becomes None."""
custom_speed = 101112
of_speed = 10 * 10**6 / 8
iface = self._get_v0x04_iface(speed=custom_speed,
features=PortFeatures.OFPPF_10MB_FD)
self.assertEqual(custom_speed, iface.speed)
iface.set_custom_speed(None)
self.assertEqual(of_speed, iface.speed)

0 comments on commit 9cf8cb8

Please sign in to comment.