From: Christos Sfakianakis csfakian@redhat.com
Hi,
this patch includes ports for simple_macsec and short_lived_connections of phase 3. Note that, due to current issue with iperf, ShortLivedConnectionsRecipe cannot be tested yet. In terms of SimpleMacsecRecipe, ip commands were chosen for the creation of the devices, as pyroute2 seems to have issue handling IFLA_MACSEC_ENCRYPT.
Christos
Christos Sfakianakis (5): lnst.RecipeCommon.Perf.Measurements.BaseFlowMeasurement: add Flow msg_size setter lnst.Controller.Host: allow device removal lnst.Devices: add MacsecDevice lnst.Recipes.ENRT: add ShortLivedConnectionsRecipe lnst.Recipes.ENRT: add SimpleMacsecRecipe
lnst/Controller/Host.py | 6 + lnst/Devices/MacsecDevice.py | 67 +++++ lnst/Devices/__init__.py | 4 +- .../Perf/Measurements/BaseFlowMeasurement.py | 4 + .../ENRT/ShortLivedConnectionsRecipe.py | 74 +++++ lnst/Recipes/ENRT/SimpleMacsecRecipe.py | 270 ++++++++++++++++++ 6 files changed, 424 insertions(+), 1 deletion(-) create mode 100644 lnst/Devices/MacsecDevice.py create mode 100644 lnst/Recipes/ENRT/ShortLivedConnectionsRecipe.py create mode 100644 lnst/Recipes/ENRT/SimpleMacsecRecipe.py
From: Christos Sfakianakis csfakian@redhat.com
Allow 'msg_size' property of a Flow object to be set (to be used with ShortLivedConnectionsRecipe).
Signed-off-by: Christos Sfakianakis csfakian@redhat.com --- lnst/RecipeCommon/Perf/Measurements/BaseFlowMeasurement.py | 4 ++++ 1 file changed, 4 insertions(+)
diff --git a/lnst/RecipeCommon/Perf/Measurements/BaseFlowMeasurement.py b/lnst/RecipeCommon/Perf/Measurements/BaseFlowMeasurement.py index c4448b7..81cd02c 100644 --- a/lnst/RecipeCommon/Perf/Measurements/BaseFlowMeasurement.py +++ b/lnst/RecipeCommon/Perf/Measurements/BaseFlowMeasurement.py @@ -46,6 +46,10 @@ class Flow(object): def msg_size(self): return self._msg_size
+ @msg_size.setter + def msg_size(self, value): + self._msg_size = value + @property def duration(self): return self._duration
On Fri, May 24, 2019 at 07:26:47PM +0200, csfakian@redhat.com wrote:
From: Christos Sfakianakis csfakian@redhat.com
Allow 'msg_size' property of a Flow object to be set (to be used with ShortLivedConnectionsRecipe).
Signed-off-by: Christos Sfakianakis csfakian@redhat.com
lnst/RecipeCommon/Perf/Measurements/BaseFlowMeasurement.py | 4 ++++ 1 file changed, 4 insertions(+)
diff --git a/lnst/RecipeCommon/Perf/Measurements/BaseFlowMeasurement.py b/lnst/RecipeCommon/Perf/Measurements/BaseFlowMeasurement.py index c4448b7..81cd02c 100644 --- a/lnst/RecipeCommon/Perf/Measurements/BaseFlowMeasurement.py +++ b/lnst/RecipeCommon/Perf/Measurements/BaseFlowMeasurement.py @@ -46,6 +46,10 @@ class Flow(object): def msg_size(self): return self._msg_size
- @msg_size.setter
- def msg_size(self, value):
self._msg_size = value
- @property def duration(self): return self._duration
-- 2.17.1 _______________________________________________ LNST-developers mailing list -- lnst-developers@lists.fedorahosted.org To unsubscribe send an email to lnst-developers-leave@lists.fedorahosted.org Fedora Code of Conduct: https://getfedora.org/code-of-conduct.html List Guidelines: https://fedoraproject.org/wiki/Mailing_list_guidelines List Archives: https://lists.fedorahosted.org/archives/list/lnst-developers@lists.fedorahos...
Also not sure about this... I imagined that Flow instances shouldn't really be changed once they're created. I'll take a look at the use case but I think it's probably a better idea to not reuse Flow instances and just create a new one when needed.
-Ondrej
From: Christos Sfakianakis csfakian@redhat.com
Allow device removal. Destroy the device, remove it from the database and log a relevant message. This is useful when a new device with the same name identifier needs to be created.
Signed-off-by: Christos Sfakianakis csfakian@redhat.com --- lnst/Controller/Host.py | 6 ++++++ 1 file changed, 6 insertions(+)
diff --git a/lnst/Controller/Host.py b/lnst/Controller/Host.py index ee36803..70fece5 100644 --- a/lnst/Controller/Host.py +++ b/lnst/Controller/Host.py @@ -15,6 +15,7 @@ from lnst.Common.Parameters import Parameters from lnst.Controller.Common import ControllerError from lnst.Controller.Namespace import Namespace from lnst.Controller.NetNamespace import NetNamespace +import logging
class Hosts(object): """Container object for Host class instances @@ -82,3 +83,8 @@ class Host(Namespace): self._machine.send_class(cls)
return self._machine.init_remote_class(cls, *args, **kwargs) + + def remove_dev(self, dev): + logging.debug("Device %s is being removed intentionally." % dev.name) + dev.destroy() + self._unset(dev)
On Fri, May 24, 2019 at 07:26:48PM +0200, csfakian@redhat.com wrote:
From: Christos Sfakianakis csfakian@redhat.com
Allow device removal. Destroy the device, remove it from the database and log a relevant message. This is useful when a new device with the same name identifier needs to be created.
Signed-off-by: Christos Sfakianakis csfakian@redhat.com
lnst/Controller/Host.py | 6 ++++++ 1 file changed, 6 insertions(+)
diff --git a/lnst/Controller/Host.py b/lnst/Controller/Host.py index ee36803..70fece5 100644 --- a/lnst/Controller/Host.py +++ b/lnst/Controller/Host.py @@ -15,6 +15,7 @@ from lnst.Common.Parameters import Parameters from lnst.Controller.Common import ControllerError from lnst.Controller.Namespace import Namespace from lnst.Controller.NetNamespace import NetNamespace +import logging
class Hosts(object): """Container object for Host class instances @@ -82,3 +83,8 @@ class Host(Namespace): self._machine.send_class(cls)
return self._machine.init_remote_class(cls, *args, **kwargs)
- def remove_dev(self, dev):
logging.debug("Device %s is being removed intentionally." % dev.name)
dev.destroy()
self._unset(dev)
-- 2.17.1 _______________________________________________ LNST-developers mailing list -- lnst-developers@lists.fedorahosted.org To unsubscribe send an email to lnst-developers-leave@lists.fedorahosted.org Fedora Code of Conduct: https://getfedora.org/code-of-conduct.html List Guidelines: https://fedoraproject.org/wiki/Mailing_list_guidelines List Archives: https://lists.fedorahosted.org/archives/list/lnst-developers@lists.fedorahos...
I'm not sure about this, this is introducing a new tester facing api call that might need more consideration before commiting to something like this...
I think explicitly doing the following in a Recipe might be best for now: h.my_device.destroy() del h.my_device
...
h.my_device = MyDevice()
-Ondrej
From: Christos Sfakianakis csfakian@redhat.com
Add a class to account for the creation of link of type macsec. For now, use only the master device and possibly the encryption setting for creating it. Provide methods that map to corresponding 'ip macsec' commands.
Signed-off-by: Christos Sfakianakis csfakian@redhat.com --- lnst/Devices/MacsecDevice.py | 67 ++++++++++++++++++++++++++++++++++++ lnst/Devices/__init__.py | 4 ++- 2 files changed, 70 insertions(+), 1 deletion(-) create mode 100644 lnst/Devices/MacsecDevice.py
diff --git a/lnst/Devices/MacsecDevice.py b/lnst/Devices/MacsecDevice.py new file mode 100644 index 0000000..799ea9e --- /dev/null +++ b/lnst/Devices/MacsecDevice.py @@ -0,0 +1,67 @@ +import pyroute2 +from lnst.Common.ExecCmd import exec_cmd +from lnst.Common.DeviceError import DeviceConfigError +from lnst.Devices.Device import Device +from lnst.Devices.SoftDevice import SoftDevice + +class MacsecDevice(SoftDevice): + _name_template = "t_macsec" + _cmd = '' + + def __init__(self, ifmanager, *args, **kwargs): + super(MacsecDevice, self).__init__(ifmanager) + self._kwargs = kwargs + + def _create(self): + realdev = self._kwargs.pop("realdev") + encrypt = self._kwargs.pop("encrypt", None) + cmd = "ip link add link %s %s type macsec" % (realdev.name, self.name) + if encrypt: + cmd += " encrypt %s" % encrypt + exec_cmd(cmd) + + def destroy(self): + exec_cmd("ip link delete %s" % self.name) + + def rx(self, op, **kwargs): + self._sci(op, kwargs) + if op != 'del': + try: + self._cmd += "%s" % kwargs.pop('enable') + except KeyError: + pass + self._chk_exec(op, kwargs) + + def rx_sa(self, op, **kwargs): + self._sci(op, kwargs) + self._sa_pn_key(op, kwargs) + + def tx_sa(self, op, **kwargs): + self._cmd = "ip macsec %s %s tx " % (op, self.name) + self._sa_pn_key(op, kwargs) + + def _sci(self, op, kwargs): + self._cmd = "ip macsec %s %s rx " % (op, self.name) + try: + self._cmd += "sci %s " % kwargs.pop('sci') + except KeyError: + self._cmd += "port %s address %s " % (kwargs.pop('port'), + kwargs.pop('address')) + + def _sa_pn_key(self, op, kwargs): + self._cmd += "sa %s " % kwargs.pop('sa') + if op != 'del': + try: + self._cmd += "pn %s " % kwargs.pop('pn') + self._cmd += "%s " % kwargs.pop('enable') + except KeyError: + pass + if op == 'add': + self._cmd += "key %s " % kwargs.pop('id') + self._cmd += "%s" % kwargs.pop('key') + self._chk_exec(op, kwargs) + + def _chk_exec(self, op, kwargs): + if kwargs: + raise DeviceConfigError("Unexpected options with %s: %s" % (op, kwargs)) + exec_cmd(self._cmd) diff --git a/lnst/Devices/__init__.py b/lnst/Devices/__init__.py index 675db3c..b38d1b6 100644 --- a/lnst/Devices/__init__.py +++ b/lnst/Devices/__init__.py @@ -10,6 +10,7 @@ from lnst.Devices.VxlanDevice import VxlanDevice from lnst.Devices.VtiDevice import VtiDevice, Vti6Device from lnst.Devices.VethDevice import VethDevice, PairedVethDevice from lnst.Devices.VethPair import VethPair +from lnst.Devices.MacsecDevice import MacsecDevice from lnst.Devices.RemoteDevice import RemoteDevice, remotedev_decorator
device_classes = [ @@ -24,7 +25,8 @@ device_classes = [ ("VtiDevice", VtiDevice), ("Vti6Device", Vti6Device), ("BondDevice", BondDevice), - ("TeamDevice", TeamDevice)] + ("TeamDevice", TeamDevice), + ("MacsecDevice", MacsecDevice)]
for name, cls in device_classes: globals()[name] = remotedev_decorator(cls)
On Fri, May 24, 2019 at 07:26:49PM +0200, csfakian@redhat.com wrote:
From: Christos Sfakianakis csfakian@redhat.com
Add a class to account for the creation of link of type macsec. For now, use only the master device and possibly the encryption setting for creating it. Provide methods that map to corresponding 'ip macsec' commands.
Signed-off-by: Christos Sfakianakis csfakian@redhat.com
lnst/Devices/MacsecDevice.py | 67 ++++++++++++++++++++++++++++++++++++ lnst/Devices/__init__.py | 4 ++- 2 files changed, 70 insertions(+), 1 deletion(-) create mode 100644 lnst/Devices/MacsecDevice.py
diff --git a/lnst/Devices/MacsecDevice.py b/lnst/Devices/MacsecDevice.py new file mode 100644 index 0000000..799ea9e --- /dev/null +++ b/lnst/Devices/MacsecDevice.py @@ -0,0 +1,67 @@ +import pyroute2 +from lnst.Common.ExecCmd import exec_cmd +from lnst.Common.DeviceError import DeviceConfigError +from lnst.Devices.Device import Device +from lnst.Devices.SoftDevice import SoftDevice
+class MacsecDevice(SoftDevice):
- _name_template = "t_macsec"
- _cmd = ''
- def __init__(self, ifmanager, *args, **kwargs):
super(MacsecDevice, self).__init__(ifmanager)
self._kwargs = kwargs
since *args isn't used it shouldn't be allowed in the method parameters, this way you can do this:
MacsecDevice(some_manager, 1,2,3,4,5,5,"aaa",whatever, name="some name")
and all the parameters between "some_manager" and "name=" will just silently get ignored.
- def _create(self):
realdev = self._kwargs.pop("realdev")
encrypt = self._kwargs.pop("encrypt", None)
cmd = "ip link add link %s %s type macsec" % (realdev.name, self.name)
if encrypt:
cmd += " encrypt %s" % encrypt
exec_cmd(cmd)
- def destroy(self):
exec_cmd("ip link delete %s" % self.name)
- def rx(self, op, **kwargs):
self._sci(op, kwargs)
if op != 'del':
try:
self._cmd += "%s" % kwargs.pop('enable')
except KeyError:
pass
self._chk_exec(op, kwargs)
- def rx_sa(self, op, **kwargs):
self._sci(op, kwargs)
self._sa_pn_key(op, kwargs)
- def tx_sa(self, op, **kwargs):
self._cmd = "ip macsec %s %s tx " % (op, self.name)
self._sa_pn_key(op, kwargs)
- def _sci(self, op, kwargs):
self._cmd = "ip macsec %s %s rx " % (op, self.name)
try:
self._cmd += "sci %s " % kwargs.pop('sci')
except KeyError:
self._cmd += "port %s address %s " % (kwargs.pop('port'),
kwargs.pop('address'))
- def _sa_pn_key(self, op, kwargs):
self._cmd += "sa %s " % kwargs.pop('sa')
if op != 'del':
try:
self._cmd += "pn %s " % kwargs.pop('pn')
self._cmd += "%s " % kwargs.pop('enable')
except KeyError:
pass
if op == 'add':
self._cmd += "key %s " % kwargs.pop('id')
self._cmd += "%s" % kwargs.pop('key')
self._chk_exec(op, kwargs)
- def _chk_exec(self, op, kwargs):
if kwargs:
raise DeviceConfigError("Unexpected options with %s: %s" % (op, kwargs))
exec_cmd(self._cmd)
diff --git a/lnst/Devices/__init__.py b/lnst/Devices/__init__.py index 675db3c..b38d1b6 100644 --- a/lnst/Devices/__init__.py +++ b/lnst/Devices/__init__.py @@ -10,6 +10,7 @@ from lnst.Devices.VxlanDevice import VxlanDevice from lnst.Devices.VtiDevice import VtiDevice, Vti6Device from lnst.Devices.VethDevice import VethDevice, PairedVethDevice from lnst.Devices.VethPair import VethPair +from lnst.Devices.MacsecDevice import MacsecDevice from lnst.Devices.RemoteDevice import RemoteDevice, remotedev_decorator
device_classes = [ @@ -24,7 +25,8 @@ device_classes = [ ("VtiDevice", VtiDevice), ("Vti6Device", Vti6Device), ("BondDevice", BondDevice),
("TeamDevice", TeamDevice)]
("TeamDevice", TeamDevice),
("MacsecDevice", MacsecDevice)]
for name, cls in device_classes: globals()[name] = remotedev_decorator(cls) -- 2.17.1 _______________________________________________ LNST-developers mailing list -- lnst-developers@lists.fedorahosted.org To unsubscribe send an email to lnst-developers-leave@lists.fedorahosted.org Fedora Code of Conduct: https://getfedora.org/code-of-conduct.html List Guidelines: https://fedoraproject.org/wiki/Mailing_list_guidelines List Archives: https://lists.fedorahosted.org/archives/list/lnst-developers@lists.fedorahos...
Fri, May 24, 2019 at 07:26:49PM CEST, csfakian@redhat.com wrote:
From: Christos Sfakianakis csfakian@redhat.com
Add a class to account for the creation of link of type macsec. For now, use only the master device and possibly the encryption setting for creating it. Provide methods that map to corresponding 'ip macsec' commands.
Signed-off-by: Christos Sfakianakis csfakian@redhat.com
lnst/Devices/MacsecDevice.py | 67 ++++++++++++++++++++++++++++++++++++ lnst/Devices/__init__.py | 4 ++- 2 files changed, 70 insertions(+), 1 deletion(-) create mode 100644 lnst/Devices/MacsecDevice.py
diff --git a/lnst/Devices/MacsecDevice.py b/lnst/Devices/MacsecDevice.py new file mode 100644 index 0000000..799ea9e --- /dev/null +++ b/lnst/Devices/MacsecDevice.py @@ -0,0 +1,67 @@ +import pyroute2 +from lnst.Common.ExecCmd import exec_cmd +from lnst.Common.DeviceError import DeviceConfigError +from lnst.Devices.Device import Device +from lnst.Devices.SoftDevice import SoftDevice
+class MacsecDevice(SoftDevice):
- _name_template = "t_macsec"
- _cmd = ''
- def __init__(self, ifmanager, *args, **kwargs):
super(MacsecDevice, self).__init__(ifmanager)
self._kwargs = kwargs
- def _create(self):
realdev = self._kwargs.pop("realdev")
encrypt = self._kwargs.pop("encrypt", None)
cmd = "ip link add link %s %s type macsec" % (realdev.name, self.name)
if encrypt:
cmd += " encrypt %s" % encrypt
exec_cmd(cmd)
I've checked the 'ip link' man page and it's not clear what is the default value for encrypt parameter if not specified. It would be better if this is explicit in LNST code, either on or off. Is this device parameter mandatory (in LNST code)?
-Jan
- def destroy(self):
exec_cmd("ip link delete %s" % self.name)
- def rx(self, op, **kwargs):
self._sci(op, kwargs)
if op != 'del':
try:
self._cmd += "%s" % kwargs.pop('enable')
except KeyError:
pass
self._chk_exec(op, kwargs)
- def rx_sa(self, op, **kwargs):
self._sci(op, kwargs)
self._sa_pn_key(op, kwargs)
- def tx_sa(self, op, **kwargs):
self._cmd = "ip macsec %s %s tx " % (op, self.name)
self._sa_pn_key(op, kwargs)
- def _sci(self, op, kwargs):
self._cmd = "ip macsec %s %s rx " % (op, self.name)
try:
self._cmd += "sci %s " % kwargs.pop('sci')
except KeyError:
self._cmd += "port %s address %s " % (kwargs.pop('port'),
kwargs.pop('address'))
- def _sa_pn_key(self, op, kwargs):
self._cmd += "sa %s " % kwargs.pop('sa')
if op != 'del':
try:
self._cmd += "pn %s " % kwargs.pop('pn')
self._cmd += "%s " % kwargs.pop('enable')
except KeyError:
pass
if op == 'add':
self._cmd += "key %s " % kwargs.pop('id')
self._cmd += "%s" % kwargs.pop('key')
self._chk_exec(op, kwargs)
- def _chk_exec(self, op, kwargs):
if kwargs:
raise DeviceConfigError("Unexpected options with %s: %s" % (op, kwargs))
exec_cmd(self._cmd)
diff --git a/lnst/Devices/__init__.py b/lnst/Devices/__init__.py index 675db3c..b38d1b6 100644 --- a/lnst/Devices/__init__.py +++ b/lnst/Devices/__init__.py @@ -10,6 +10,7 @@ from lnst.Devices.VxlanDevice import VxlanDevice from lnst.Devices.VtiDevice import VtiDevice, Vti6Device from lnst.Devices.VethDevice import VethDevice, PairedVethDevice from lnst.Devices.VethPair import VethPair +from lnst.Devices.MacsecDevice import MacsecDevice from lnst.Devices.RemoteDevice import RemoteDevice, remotedev_decorator
device_classes = [ @@ -24,7 +25,8 @@ device_classes = [ ("VtiDevice", VtiDevice), ("Vti6Device", Vti6Device), ("BondDevice", BondDevice),
("TeamDevice", TeamDevice)]
("TeamDevice", TeamDevice),
("MacsecDevice", MacsecDevice)]
for name, cls in device_classes: globals()[name] = remotedev_decorator(cls) -- 2.17.1 _______________________________________________ LNST-developers mailing list -- lnst-developers@lists.fedorahosted.org To unsubscribe send an email to lnst-developers-leave@lists.fedorahosted.org Fedora Code of Conduct: https://getfedora.org/code-of-conduct.html List Guidelines: https://fedoraproject.org/wiki/Mailing_list_guidelines List Archives: https://lists.fedorahosted.org/archives/list/lnst-developers@lists.fedorahos...
----- Original Message -----
From: "Jan Tluka" jtluka@redhat.com To: csfakian@redhat.com Cc: lnst-developers@lists.fedorahosted.org Sent: Monday, May 27, 2019 12:19:05 PM Subject: Re: [PATCH-next 3/5] lnst.Devices: add MacsecDevice
Fri, May 24, 2019 at 07:26:49PM CEST, csfakian@redhat.com wrote:
From: Christos Sfakianakis csfakian@redhat.com
Add a class to account for the creation of link of type macsec. For now, use only the master device and possibly the encryption setting for creating it. Provide methods that map to corresponding 'ip macsec' commands.
Signed-off-by: Christos Sfakianakis csfakian@redhat.com
lnst/Devices/MacsecDevice.py | 67 ++++++++++++++++++++++++++++++++++++ lnst/Devices/__init__.py | 4 ++- 2 files changed, 70 insertions(+), 1 deletion(-) create mode 100644 lnst/Devices/MacsecDevice.py
diff --git a/lnst/Devices/MacsecDevice.py b/lnst/Devices/MacsecDevice.py new file mode 100644 index 0000000..799ea9e --- /dev/null +++ b/lnst/Devices/MacsecDevice.py @@ -0,0 +1,67 @@ +import pyroute2 +from lnst.Common.ExecCmd import exec_cmd +from lnst.Common.DeviceError import DeviceConfigError +from lnst.Devices.Device import Device +from lnst.Devices.SoftDevice import SoftDevice
+class MacsecDevice(SoftDevice):
- _name_template = "t_macsec"
- _cmd = ''
- def __init__(self, ifmanager, *args, **kwargs):
super(MacsecDevice, self).__init__(ifmanager)
self._kwargs = kwargs
- def _create(self):
realdev = self._kwargs.pop("realdev")
encrypt = self._kwargs.pop("encrypt", None)
cmd = "ip link add link %s %s type macsec" % (realdev.name,
self.name)
if encrypt:
cmd += " encrypt %s" % encrypt
exec_cmd(cmd)
I've checked the 'ip link' man page and it's not clear what is the default value for encrypt parameter if not specified. It would be better if this is explicit in LNST code, either on or off. Is this device parameter mandatory (in LNST code)?
Ok, I will set this option as mandatory together with the 'realdev' option.
-Jan
- def destroy(self):
exec_cmd("ip link delete %s" % self.name)
- def rx(self, op, **kwargs):
self._sci(op, kwargs)
if op != 'del':
try:
self._cmd += "%s" % kwargs.pop('enable')
except KeyError:
pass
self._chk_exec(op, kwargs)
- def rx_sa(self, op, **kwargs):
self._sci(op, kwargs)
self._sa_pn_key(op, kwargs)
- def tx_sa(self, op, **kwargs):
self._cmd = "ip macsec %s %s tx " % (op, self.name)
self._sa_pn_key(op, kwargs)
- def _sci(self, op, kwargs):
self._cmd = "ip macsec %s %s rx " % (op, self.name)
try:
self._cmd += "sci %s " % kwargs.pop('sci')
except KeyError:
self._cmd += "port %s address %s " % (kwargs.pop('port'),
kwargs.pop('address'))
- def _sa_pn_key(self, op, kwargs):
self._cmd += "sa %s " % kwargs.pop('sa')
if op != 'del':
try:
self._cmd += "pn %s " % kwargs.pop('pn')
self._cmd += "%s " % kwargs.pop('enable')
except KeyError:
pass
if op == 'add':
self._cmd += "key %s " % kwargs.pop('id')
self._cmd += "%s" % kwargs.pop('key')
self._chk_exec(op, kwargs)
- def _chk_exec(self, op, kwargs):
if kwargs:
raise DeviceConfigError("Unexpected options with %s: %s" % (op,
kwargs))
exec_cmd(self._cmd)
diff --git a/lnst/Devices/__init__.py b/lnst/Devices/__init__.py index 675db3c..b38d1b6 100644 --- a/lnst/Devices/__init__.py +++ b/lnst/Devices/__init__.py @@ -10,6 +10,7 @@ from lnst.Devices.VxlanDevice import VxlanDevice from lnst.Devices.VtiDevice import VtiDevice, Vti6Device from lnst.Devices.VethDevice import VethDevice, PairedVethDevice from lnst.Devices.VethPair import VethPair +from lnst.Devices.MacsecDevice import MacsecDevice from lnst.Devices.RemoteDevice import RemoteDevice, remotedev_decorator
device_classes = [ @@ -24,7 +25,8 @@ device_classes = [ ("VtiDevice", VtiDevice), ("Vti6Device", Vti6Device), ("BondDevice", BondDevice),
("TeamDevice", TeamDevice)]
("TeamDevice", TeamDevice),
("MacsecDevice", MacsecDevice)]
for name, cls in device_classes: globals()[name] = remotedev_decorator(cls) -- 2.17.1 _______________________________________________ LNST-developers mailing list -- lnst-developers@lists.fedorahosted.org To unsubscribe send an email to lnst-developers-leave@lists.fedorahosted.org Fedora Code of Conduct: https://getfedora.org/code-of-conduct.html List Guidelines: https://fedoraproject.org/wiki/Mailing_list_guidelines List Archives: https://lists.fedorahosted.org/archives/list/lnst-developers@lists.fedorahos...
Mon, May 27, 2019 at 01:40:09PM CEST, csfakian@redhat.com wrote:
----- Original Message -----
From: "Jan Tluka" jtluka@redhat.com To: csfakian@redhat.com Cc: lnst-developers@lists.fedorahosted.org Sent: Monday, May 27, 2019 12:19:05 PM Subject: Re: [PATCH-next 3/5] lnst.Devices: add MacsecDevice
I've checked the 'ip link' man page and it's not clear what is the default value for encrypt parameter if not specified. It would be better if this is explicit in LNST code, either on or off. Is this device parameter mandatory (in LNST code)?
Ok, I will set this option as mandatory together with the 'realdev' option.
And remove the condition completely. Simply exec with encrypt + whatever is passed as the device param.
Thanks, Jan
----- Original Message -----
From: "Jan Tluka" jtluka@redhat.com To: "Christos Sfakianakis" csfakian@redhat.com Cc: lnst-developers@lists.fedorahosted.org Sent: Monday, May 27, 2019 1:48:42 PM Subject: Re: [PATCH-next 3/5] lnst.Devices: add MacsecDevice
Mon, May 27, 2019 at 01:40:09PM CEST, csfakian@redhat.com wrote:
----- Original Message -----
From: "Jan Tluka" jtluka@redhat.com To: csfakian@redhat.com Cc: lnst-developers@lists.fedorahosted.org Sent: Monday, May 27, 2019 12:19:05 PM Subject: Re: [PATCH-next 3/5] lnst.Devices: add MacsecDevice
I've checked the 'ip link' man page and it's not clear what is the default value for encrypt parameter if not specified. It would be better if this is explicit in LNST code, either on or off. Is this device parameter mandatory (in LNST code)?
Ok, I will set this option as mandatory together with the 'realdev' option.
And remove the condition completely. Simply exec with encrypt + whatever is passed as the device param.
S. Dubroca informed me that the kernel policy has a default value of 'off' for 'encrypt' (so it is expected to stay so forever); I am therefore leaving the code as is for now (after our talk).
Thanks, Jan _______________________________________________ LNST-developers mailing list -- lnst-developers@lists.fedorahosted.org To unsubscribe send an email to lnst-developers-leave@lists.fedorahosted.org Fedora Code of Conduct: https://getfedora.org/code-of-conduct.html List Guidelines: https://fedoraproject.org/wiki/Mailing_list_guidelines List Archives: https://lists.fedorahosted.org/archives/list/lnst-developers@lists.fedorahos...
From: Christos Sfakianakis csfakian@redhat.com
Add ShortLivedConnectionsRecipe, which accounts for short_lived_connections of old phase 3.
Signed-off-by: Christos Sfakianakis csfakian@redhat.com --- .../ENRT/ShortLivedConnectionsRecipe.py | 74 +++++++++++++++++++ 1 file changed, 74 insertions(+) create mode 100644 lnst/Recipes/ENRT/ShortLivedConnectionsRecipe.py
diff --git a/lnst/Recipes/ENRT/ShortLivedConnectionsRecipe.py b/lnst/Recipes/ENRT/ShortLivedConnectionsRecipe.py new file mode 100644 index 0000000..e311fa2 --- /dev/null +++ b/lnst/Recipes/ENRT/ShortLivedConnectionsRecipe.py @@ -0,0 +1,74 @@ +""" +Implements scenario similar to regression_tests/phase3/ +(short_lived_connections.xml + short_lived_connections.py) +""" +from lnst.Common.IpAddress import ipaddress +from lnst.Controller import HostReq, DeviceReq, RecipeParam +from lnst.Recipes.ENRT.BaseEnrtRecipe import BaseEnrtRecipe, EnrtConfiguration +from lnst.Common.Parameters import Param, IntParam, ListParam + +class ShortLivedConnectionsRecipe(BaseEnrtRecipe): + host1 = HostReq() + host1.eth0 = DeviceReq(label="to_switch", driver=RecipeParam("driver")) + + host2 = HostReq() + host2.eth0 = DeviceReq(label="to_switch", driver=RecipeParam("driver")) + + perf_tests = Param(default=("TCP_RR", "TCP_CRR")) + ip_versions = Param(default=("ipv4",)) + perf_parallel_streams = IntParam(default=2) + perf_msg_size = ListParam(default=[1000, 5000, 7000, 10000, 12000]) + + def generate_ping_configurations(self, main_config, sub_config): + return [] + + def generate_flow_combinations(self, main_config, sub_config): + for size in self.params.perf_msg_size: + for flow in super(ShortLivedConnectionsRecipe, self).generate_flow_combinations( + main_config, sub_config): + flow[0].msg_size = size + yield flow + + def test_wide_configuration(self): + host1, host2 = self.matched.host1, self.matched.host2 + + for host in [host1, host2]: + host.eth0.down() + + net_addr = "192.168.101" + + for i, host in enumerate([host1, host2], 10): + host.eth0.ip_add(ipaddress(net_addr + "." + str(i) + "/24")) + + #Due to limitations in the current EnrtConfiguration + #class, a single vlan test pair is chosen + configuration = EnrtConfiguration() + configuration.endpoint1 = host1.eth0 + configuration.endpoint2 = host2.eth0 + + if "mtu" in self.params: + for host in [host1, host2]: + host.eth0.mtu = self.params.mtu + + for host in [host1, host2]: + host.eth0.up() + + #TODO better service handling through HostAPI + if "dev_intr_cpu" in self.params: + for host in [host1, host2]: + host.run("service irqbalance stop") + self._pin_dev_interrupts(host.eth0, self.params.dev_intr_cpu) + + if self.params.perf_parallel_streams > 1: + for host in [host1, host2]: + host.run("tc qdisc replace dev %s root mq" % host.eth0.name) + + return configuration + + def test_wide_deconfiguration(self, config): + host1, host2 = self.matched.host1, self.matched.host2 + + #TODO better service handling through HostAPI + if "dev_intr_cpu" in self.params: + for host in [host1, host2]: + host.run("service irqbalance start")
On Fri, May 24, 2019 at 07:26:50PM +0200, csfakian@redhat.com wrote:
From: Christos Sfakianakis csfakian@redhat.com
Add ShortLivedConnectionsRecipe, which accounts for short_lived_connections of old phase 3.
Signed-off-by: Christos Sfakianakis csfakian@redhat.com
.../ENRT/ShortLivedConnectionsRecipe.py | 74 +++++++++++++++++++ 1 file changed, 74 insertions(+) create mode 100644 lnst/Recipes/ENRT/ShortLivedConnectionsRecipe.py
diff --git a/lnst/Recipes/ENRT/ShortLivedConnectionsRecipe.py b/lnst/Recipes/ENRT/ShortLivedConnectionsRecipe.py new file mode 100644 index 0000000..e311fa2 --- /dev/null +++ b/lnst/Recipes/ENRT/ShortLivedConnectionsRecipe.py @@ -0,0 +1,74 @@ +""" +Implements scenario similar to regression_tests/phase3/ +(short_lived_connections.xml + short_lived_connections.py) +""" +from lnst.Common.IpAddress import ipaddress +from lnst.Controller import HostReq, DeviceReq, RecipeParam +from lnst.Recipes.ENRT.BaseEnrtRecipe import BaseEnrtRecipe, EnrtConfiguration +from lnst.Common.Parameters import Param, IntParam, ListParam
+class ShortLivedConnectionsRecipe(BaseEnrtRecipe):
- host1 = HostReq()
- host1.eth0 = DeviceReq(label="to_switch", driver=RecipeParam("driver"))
- host2 = HostReq()
- host2.eth0 = DeviceReq(label="to_switch", driver=RecipeParam("driver"))
- perf_tests = Param(default=("TCP_RR", "TCP_CRR"))
- ip_versions = Param(default=("ipv4",))
- perf_parallel_streams = IntParam(default=2)
- perf_msg_size = ListParam(default=[1000, 5000, 7000, 10000, 12000])
- def generate_ping_configurations(self, main_config, sub_config):
return []
- def generate_flow_combinations(self, main_config, sub_config):
for size in self.params.perf_msg_size:
for flow in super(ShortLivedConnectionsRecipe, self).generate_flow_combinations(
main_config, sub_config):
flow[0].msg_size = size
yield flow
So the interface method of "generate_flow_combinations" from BaseEnrtRecipe returns a list of flows that should be tested in parallel. Changing the message size of only the first stream is therefore incorrect.
I understand that we don't actually have a different parallel streams use case at the moment, but it's good to think of that option for the future.
Wrt. changing the msg_size of a flow, that's only required since you changed the type of the parameter. I think eventually we might want to change the type of the parameter to a List for all of our recipes so this should be taken care of in the BaseEnrtRecipe generate_flow_combinations method instead.
And in that case you don't need the msg_size setter for the Flow either since you just create the correct flow instance from the start.
I think you can do this perf_msg_size parameter change in the base recipe and skip the method override here. Maybe even rename the parameter to "perf_msg_sizes" to indicate that it's a list.
- def test_wide_configuration(self):
host1, host2 = self.matched.host1, self.matched.host2
for host in [host1, host2]:
host.eth0.down()
net_addr = "192.168.101"
for i, host in enumerate([host1, host2], 10):
host.eth0.ip_add(ipaddress(net_addr + "." + str(i) + "/24"))
#Due to limitations in the current EnrtConfiguration
#class, a single vlan test pair is chosen
configuration = EnrtConfiguration()
configuration.endpoint1 = host1.eth0
configuration.endpoint2 = host2.eth0
if "mtu" in self.params:
for host in [host1, host2]:
host.eth0.mtu = self.params.mtu
for host in [host1, host2]:
host.eth0.up()
#TODO better service handling through HostAPI
if "dev_intr_cpu" in self.params:
for host in [host1, host2]:
host.run("service irqbalance stop")
self._pin_dev_interrupts(host.eth0, self.params.dev_intr_cpu)
if self.params.perf_parallel_streams > 1:
for host in [host1, host2]:
host.run("tc qdisc replace dev %s root mq" % host.eth0.name)
return configuration
- def test_wide_deconfiguration(self, config):
host1, host2 = self.matched.host1, self.matched.host2
#TODO better service handling through HostAPI
if "dev_intr_cpu" in self.params:
for host in [host1, host2]:
host.run("service irqbalance start")
-- 2.17.1 _______________________________________________ LNST-developers mailing list -- lnst-developers@lists.fedorahosted.org To unsubscribe send an email to lnst-developers-leave@lists.fedorahosted.org Fedora Code of Conduct: https://getfedora.org/code-of-conduct.html List Guidelines: https://fedoraproject.org/wiki/Mailing_list_guidelines List Archives: https://lists.fedorahosted.org/archives/list/lnst-developers@lists.fedorahos...
Fri, May 24, 2019 at 07:26:50PM CEST, csfakian@redhat.com wrote:
From: Christos Sfakianakis csfakian@redhat.com
Add ShortLivedConnectionsRecipe, which accounts for short_lived_connections of old phase 3.
If the test currently cannot run (since we want to use iperf that does not implement the test instead of netperf) the commit message or the code should include a note about this (instead of having a note in the cover letter).
Another comment few lines below.
Signed-off-by: Christos Sfakianakis csfakian@redhat.com
.../ENRT/ShortLivedConnectionsRecipe.py | 74 +++++++++++++++++++ 1 file changed, 74 insertions(+) create mode 100644 lnst/Recipes/ENRT/ShortLivedConnectionsRecipe.py
diff --git a/lnst/Recipes/ENRT/ShortLivedConnectionsRecipe.py b/lnst/Recipes/ENRT/ShortLivedConnectionsRecipe.py new file mode 100644 index 0000000..e311fa2 --- /dev/null +++ b/lnst/Recipes/ENRT/ShortLivedConnectionsRecipe.py @@ -0,0 +1,74 @@ +""" +Implements scenario similar to regression_tests/phase3/ +(short_lived_connections.xml + short_lived_connections.py) +""" +from lnst.Common.IpAddress import ipaddress +from lnst.Controller import HostReq, DeviceReq, RecipeParam +from lnst.Recipes.ENRT.BaseEnrtRecipe import BaseEnrtRecipe, EnrtConfiguration +from lnst.Common.Parameters import Param, IntParam, ListParam
+class ShortLivedConnectionsRecipe(BaseEnrtRecipe):
- host1 = HostReq()
- host1.eth0 = DeviceReq(label="to_switch", driver=RecipeParam("driver"))
- host2 = HostReq()
- host2.eth0 = DeviceReq(label="to_switch", driver=RecipeParam("driver"))
- perf_tests = Param(default=("TCP_RR", "TCP_CRR"))
- ip_versions = Param(default=("ipv4",))
- perf_parallel_streams = IntParam(default=2)
- perf_msg_size = ListParam(default=[1000, 5000, 7000, 10000, 12000])
- def generate_ping_configurations(self, main_config, sub_config):
return []
- def generate_flow_combinations(self, main_config, sub_config):
for size in self.params.perf_msg_size:
for flow in super(ShortLivedConnectionsRecipe, self).generate_flow_combinations(
main_config, sub_config):
flow[0].msg_size = size
yield flow
- def test_wide_configuration(self):
host1, host2 = self.matched.host1, self.matched.host2
for host in [host1, host2]:
host.eth0.down()
net_addr = "192.168.101"
for i, host in enumerate([host1, host2], 10):
host.eth0.ip_add(ipaddress(net_addr + "." + str(i) + "/24"))
#Due to limitations in the current EnrtConfiguration
#class, a single vlan test pair is chosen
There are no vlans in this test - the comment is likely a copy-paste issue.
-Jan
configuration = EnrtConfiguration()
configuration.endpoint1 = host1.eth0
configuration.endpoint2 = host2.eth0
if "mtu" in self.params:
for host in [host1, host2]:
host.eth0.mtu = self.params.mtu
for host in [host1, host2]:
host.eth0.up()
#TODO better service handling through HostAPI
if "dev_intr_cpu" in self.params:
for host in [host1, host2]:
host.run("service irqbalance stop")
self._pin_dev_interrupts(host.eth0, self.params.dev_intr_cpu)
if self.params.perf_parallel_streams > 1:
for host in [host1, host2]:
host.run("tc qdisc replace dev %s root mq" % host.eth0.name)
return configuration
- def test_wide_deconfiguration(self, config):
host1, host2 = self.matched.host1, self.matched.host2
#TODO better service handling through HostAPI
if "dev_intr_cpu" in self.params:
for host in [host1, host2]:
host.run("service irqbalance start")
-- 2.17.1 _______________________________________________ LNST-developers mailing list -- lnst-developers@lists.fedorahosted.org To unsubscribe send an email to lnst-developers-leave@lists.fedorahosted.org Fedora Code of Conduct: https://getfedora.org/code-of-conduct.html List Guidelines: https://fedoraproject.org/wiki/Mailing_list_guidelines List Archives: https://lists.fedorahosted.org/archives/list/lnst-developers@lists.fedorahos...
From: Christos Sfakianakis csfakian@redhat.com
Add SimpleMacsecRecipe, corresponding to old simple_macsec recipe of phase 3.
Signed-off-by: Christos Sfakianakis csfakian@redhat.com --- lnst/Recipes/ENRT/SimpleMacsecRecipe.py | 270 ++++++++++++++++++++++++ 1 file changed, 270 insertions(+) create mode 100644 lnst/Recipes/ENRT/SimpleMacsecRecipe.py
diff --git a/lnst/Recipes/ENRT/SimpleMacsecRecipe.py b/lnst/Recipes/ENRT/SimpleMacsecRecipe.py new file mode 100644 index 0000000..ffa772e --- /dev/null +++ b/lnst/Recipes/ENRT/SimpleMacsecRecipe.py @@ -0,0 +1,270 @@ +""" +Implements scenario similar to regression_tests/phase3/ +(simple_macsec.xml + simple_macsec.py) +""" +import logging +from lnst.Common.IpAddress import ipaddress +from lnst.Common.IpAddress import AF_INET, AF_INET6 +from lnst.Common.LnstError import LnstError +from lnst.Controller import HostReq, DeviceReq, RecipeParam +from lnst.Devices import MacsecDevice +from lnst.Recipes.ENRT.BaseEnrtRecipe import BaseEnrtRecipe, EnrtConfiguration, EnrtSubConfiguration +from lnst.RecipeCommon.Perf.Recipe import RecipeConf as PerfRecipeConf +from lnst.RecipeCommon.Perf.Measurements import Flow as PerfFlow +from lnst.RecipeCommon.Ping import PingConf + +class MacsecEnrtConfiguration(EnrtConfiguration): + def __init__(self): + super(MacsecEnrtConfiguration, self).__init__() + self._host1 = None + self._host2 = None + + @property + def host1(self): + return self._host1 + + @host1.setter + def host1(self, value): + self._host1 = value + + @property + def host2(self): + return self._host2 + + @host2.setter + def host2(self, value): + self._host2 = value + +class MacsecEnrtSubConfiguration(EnrtSubConfiguration): + def __init__(self): + super(MacsecEnrtSubConfiguration, self).__init__() + self._ip_vers = ('ipv4',) + self._encrypt = None + + @property + def encrypt(self): + return self._encrypt + + @encrypt.setter + def encrypt(self, value): + self._encrypt = value + + @property + def ip_vers(self): + return self._ip_vers + + @ip_vers.setter + def ip_vers(self, value): + self._ip_vers = value + +class SimpleMacsecRecipe(BaseEnrtRecipe): + host1 = HostReq() + host1.eth0 = DeviceReq(label="to_switch", driver=RecipeParam("driver")) + + host2 = HostReq() + host2.eth0 = DeviceReq(label="to_switch", driver=RecipeParam("driver")) + + macsec_settings = [None, 'on', 'off'] + ids = ['00', '01'] + keys = ["7a16780284000775d4f0a3c0f0e092c0", "3212ef5c4cc5d0e4210b17208e88779e"] + + def generate_sub_configurations(self, main_config): + for encryption in self.macsec_settings: + sub_config = MacsecEnrtSubConfiguration() + sub_config.encrypt = encryption + if encryption: + sub_config.ip_vers = self.params.ip_versions + yield sub_config + + def apply_sub_configuration(self, main_config, sub_config): + if not sub_config.encrypt: + main_config.endpoint1.up() + main_config.endpoint2.up() + else: + net_addr = "192.168.100" + net_addr6 = "fc00:0:0:0" + host1, host2 = main_config.host1, main_config.host2 + k_ids = zip(self.ids, self.keys) + hosts_and_keys = [(host1, host2, k_ids), (host2, host1, k_ids[::-1])] + for host_a, host_b, k_ids in hosts_and_keys: + host_a.msec0 = MacsecDevice(realdev=host_a.eth0, encrypt=sub_config.encrypt) + rx_kwargs = dict(port=1, address=host_b.eth0.hwaddr) + tx_sa_kwargs = dict(sa=0, pn=1, enable='on', id=k_ids[0][0], key=k_ids[0][1]) + rx_sa_kwargs = rx_kwargs.copy() + rx_sa_kwargs.update(tx_sa_kwargs) + rx_sa_kwargs['id'] = k_ids[1][0] + rx_sa_kwargs['key'] = k_ids[1][1] + host_a.msec0.rx('add', **rx_kwargs) + host_a.msec0.tx_sa('add', **tx_sa_kwargs) + host_a.msec0.rx_sa('add', **rx_sa_kwargs) + for i, host in enumerate([host1, host2]): + host.msec0.ip_add(ipaddress(net_addr + "." + str(i+1) + "/24")) + host.msec0.ip_add(ipaddress(net_addr6 + "::" + str(i+1) + "/64")) + host.eth0.up() + host.msec0.up() + + def remove_sub_configuration(self, main_config, sub_config): + if sub_config.encrypt: + host1, host2 = main_config.host1, main_config.host2 + for host in (host1, host2): + host.msec0.netns.remove_dev(host.msec0) + main_config.endpoint1.down() + main_config.endpoint2.down() + + def generate_ping_configurations(self, main_config, sub_config): + if not sub_config.encrypt: + client_nic = main_config.endpoint1 + server_nic = main_config.endpoint2 + ip_vers = ('ipv4',) + else: + client_nic = main_config.host1.msec0 + server_nic = main_config.host2.msec0 + ip_vers = self.params.ip_versions + + count = self.params.ping_count + interval = self.params.ping_interval + size = self.params.ping_psize + common_args = {'count' : count, 'interval' : interval, 'size' : size} + + for ipv in ip_vers: + kwargs = {} + if ipv == "ipv4": + kwargs.update(family = AF_INET) + elif ipv == "ipv6": + kwargs.update(family = AF_INET6) + kwargs.update(link_local = False) + + client_ips = client_nic.ips_filter(**kwargs) + server_ips = server_nic.ips_filter(**kwargs) + if ipv == "ipv6": + client_ips = client_ips[::-1] + server_ips = server_ips[::-1] + + if len(client_ips) != len(server_ips) or len(client_ips) * len(server_ips) == 0: + raise LnstError("Source/destination ip lists are of different size or empty.") + + for src_addr, dst_addr in zip(client_ips, server_ips): + pconf = PingConf(client = client_nic.netns, + client_bind = src_addr, + destination = server_nic.netns, + destination_address = dst_addr, + **common_args) + + yield [pconf] + + def generate_perf_configurations(self, main_config, sub_config): + if sub_config.encrypt: + client_nic = main_config.host1.msec0 + server_nic = main_config.host2.msec0 + client_netns = client_nic.netns + server_netns = server_nic.netns + + flow_combinations = self.generate_flow_combinations( + main_config, sub_config + ) + + for flows in flow_combinations: + perf_recipe_conf=dict( + main_config=main_config, + sub_config=sub_config, + flows=flows, + ) + + flows_measurement = self.params.net_perf_tool( + flows, + perf_recipe_conf + ) + + cpu_measurement = self.params.cpu_perf_tool( + [client_netns, server_netns], + perf_recipe_conf, + ) + + perf_conf = PerfRecipeConf( + measurements=[cpu_measurement, flows_measurement], + iterations=self.params.perf_iterations, + ) + + perf_conf.register_evaluators( + cpu_measurement, self.cpu_perf_evaluators + ) + perf_conf.register_evaluators( + flows_measurement, self.net_perf_evaluators + ) + + yield perf_conf + + def generate_flow_combinations(self, main_config, sub_config): + client_nic = main_config.host1.msec0 + server_nic = main_config.host2.msec0 + client_netns = client_nic.netns + server_netns = server_nic.netns + + for ipv in self.params.ip_versions: + if ipv == "ipv4": + family = AF_INET + elif ipv == "ipv6": + family = AF_INET6 + + client_bind = client_nic.ips_filter(family=family)[0] + server_bind = server_nic.ips_filter(family=family)[0] + + for perf_test in self.params.perf_tests: + flow = PerfFlow( + type = perf_test, + generator = client_netns, + generator_bind = client_bind, + receiver = server_netns, + receiver_bind = server_bind, + msg_size = self.params.perf_msg_size, + duration = self.params.perf_duration, + parallel_streams = self.params.perf_parallel_streams, + cpupin = self.params.perf_tool_cpu if "perf_tool_cpu" in self.params else None + ) + yield [flow] + + def test_wide_configuration(self): + host1, host2 = self.matched.host1, self.matched.host2 + + for host in [host1, host2]: + host.eth0.down() + + net_addr = "192.168.0" + + for i, host in enumerate([host1, host2]): + host.eth0.ip_add(ipaddress(net_addr + '.' + str(i+1) + "/24")) + + #Due to limitations in the current EnrtConfiguration + #class, a single vlan test pair is chosen + configuration = EnrtConfiguration() + configuration.endpoint1 = host1.eth0 + configuration.endpoint2 = host2.eth0 + configuration.host1 = host1 + configuration.host2 = host2 + + cond = (self.params.ping_parallel or self.params.ping_bidirect or + self.params.perf_reverse) + if cond: + logging.debug("Parallelism in pings or reverse perf tests are " + "not supported for this recipe, ping_parallel/bidirect " + " or perf_reverse will be ignored.") + + if "mtu" in self.params: + for host in [host1, host2]: + host.eth0.mtu = self.params.mtu + + #TODO better service handling through HostAPI + if "dev_intr_cpu" in self.params: + for host in [host1, host2]: + host.run("service irqbalance stop") + self._pin_dev_interrupts(host.eth0, self.params.dev_intr_cpu) + + return configuration + + def test_wide_deconfiguration(self, config): + host1, host2 = self.matched.host1, self.matched.host2 + + #TODO better service handling through HostAPI + if "dev_intr_cpu" in self.params: + for host in [host1, host2]: + host.run("service irqbalance start")
On Fri, May 24, 2019 at 07:26:51PM +0200, csfakian@redhat.com wrote:
From: Christos Sfakianakis csfakian@redhat.com
Add SimpleMacsecRecipe, corresponding to old simple_macsec recipe of phase 3.
Signed-off-by: Christos Sfakianakis csfakian@redhat.com
lnst/Recipes/ENRT/SimpleMacsecRecipe.py | 270 ++++++++++++++++++++++++ 1 file changed, 270 insertions(+) create mode 100644 lnst/Recipes/ENRT/SimpleMacsecRecipe.py
diff --git a/lnst/Recipes/ENRT/SimpleMacsecRecipe.py b/lnst/Recipes/ENRT/SimpleMacsecRecipe.py new file mode 100644 index 0000000..ffa772e --- /dev/null +++ b/lnst/Recipes/ENRT/SimpleMacsecRecipe.py @@ -0,0 +1,270 @@ +""" +Implements scenario similar to regression_tests/phase3/ +(simple_macsec.xml + simple_macsec.py) +""" +import logging +from lnst.Common.IpAddress import ipaddress +from lnst.Common.IpAddress import AF_INET, AF_INET6 +from lnst.Common.LnstError import LnstError +from lnst.Controller import HostReq, DeviceReq, RecipeParam +from lnst.Devices import MacsecDevice +from lnst.Recipes.ENRT.BaseEnrtRecipe import BaseEnrtRecipe, EnrtConfiguration, EnrtSubConfiguration +from lnst.RecipeCommon.Perf.Recipe import RecipeConf as PerfRecipeConf +from lnst.RecipeCommon.Perf.Measurements import Flow as PerfFlow +from lnst.RecipeCommon.Ping import PingConf
+class MacsecEnrtConfiguration(EnrtConfiguration):
- def __init__(self):
super(MacsecEnrtConfiguration, self).__init__()
self._host1 = None
self._host2 = None
- @property
- def host1(self):
return self._host1
- @host1.setter
- def host1(self, value):
self._host1 = value
- @property
- def host2(self):
return self._host2
- @host2.setter
- def host2(self, value):
self._host2 = value
+class MacsecEnrtSubConfiguration(EnrtSubConfiguration):
- def __init__(self):
super(MacsecEnrtSubConfiguration, self).__init__()
self._ip_vers = ('ipv4',)
self._encrypt = None
- @property
- def encrypt(self):
return self._encrypt
- @encrypt.setter
- def encrypt(self, value):
self._encrypt = value
- @property
- def ip_vers(self):
return self._ip_vers
- @ip_vers.setter
- def ip_vers(self, value):
self._ip_vers = value
+class SimpleMacsecRecipe(BaseEnrtRecipe):
- host1 = HostReq()
- host1.eth0 = DeviceReq(label="to_switch", driver=RecipeParam("driver"))
- host2 = HostReq()
- host2.eth0 = DeviceReq(label="to_switch", driver=RecipeParam("driver"))
- macsec_settings = [None, 'on', 'off']
- ids = ['00', '01']
- keys = ["7a16780284000775d4f0a3c0f0e092c0", "3212ef5c4cc5d0e4210b17208e88779e"]
- def generate_sub_configurations(self, main_config):
for encryption in self.macsec_settings:
sub_config = MacsecEnrtSubConfiguration()
sub_config.encrypt = encryption
if encryption:
I think it might be a little more understandable if these conditions explicitly check for the "None" value - "if encryption is not None"
since the "on", "off" can kind of be mistaken for True/False and just the short version of "if encryption" would only get called for True.
Checking for None makes it a little bit more explicit that there's also a third option.
sub_config.ip_vers = self.params.ip_versions
yield sub_config
- def apply_sub_configuration(self, main_config, sub_config):
if not sub_config.encrypt:
main_config.endpoint1.up()
main_config.endpoint2.up()
else:
net_addr = "192.168.100"
net_addr6 = "fc00:0:0:0"
host1, host2 = main_config.host1, main_config.host2
k_ids = zip(self.ids, self.keys)
hosts_and_keys = [(host1, host2, k_ids), (host2, host1, k_ids[::-1])]
for host_a, host_b, k_ids in hosts_and_keys:
host_a.msec0 = MacsecDevice(realdev=host_a.eth0, encrypt=sub_config.encrypt)
rx_kwargs = dict(port=1, address=host_b.eth0.hwaddr)
tx_sa_kwargs = dict(sa=0, pn=1, enable='on', id=k_ids[0][0], key=k_ids[0][1])
rx_sa_kwargs = rx_kwargs.copy()
rx_sa_kwargs.update(tx_sa_kwargs)
rx_sa_kwargs['id'] = k_ids[1][0]
rx_sa_kwargs['key'] = k_ids[1][1]
host_a.msec0.rx('add', **rx_kwargs)
host_a.msec0.tx_sa('add', **tx_sa_kwargs)
host_a.msec0.rx_sa('add', **rx_sa_kwargs)
for i, host in enumerate([host1, host2]):
host.msec0.ip_add(ipaddress(net_addr + "." + str(i+1) + "/24"))
host.msec0.ip_add(ipaddress(net_addr6 + "::" + str(i+1) + "/64"))
host.eth0.up()
host.msec0.up()
- def remove_sub_configuration(self, main_config, sub_config):
if sub_config.encrypt:
host1, host2 = main_config.host1, main_config.host2
for host in (host1, host2):
host.msec0.netns.remove_dev(host.msec0)
main_config.endpoint1.down()
main_config.endpoint2.down()
- def generate_ping_configurations(self, main_config, sub_config):
if not sub_config.encrypt:
client_nic = main_config.endpoint1
server_nic = main_config.endpoint2
ip_vers = ('ipv4',)
else:
client_nic = main_config.host1.msec0
server_nic = main_config.host2.msec0
ip_vers = self.params.ip_versions
count = self.params.ping_count
interval = self.params.ping_interval
size = self.params.ping_psize
common_args = {'count' : count, 'interval' : interval, 'size' : size}
for ipv in ip_vers:
kwargs = {}
if ipv == "ipv4":
kwargs.update(family = AF_INET)
elif ipv == "ipv6":
kwargs.update(family = AF_INET6)
kwargs.update(link_local = False)
client_ips = client_nic.ips_filter(**kwargs)
server_ips = server_nic.ips_filter(**kwargs)
if ipv == "ipv6":
client_ips = client_ips[::-1]
server_ips = server_ips[::-1]
if len(client_ips) != len(server_ips) or len(client_ips) * len(server_ips) == 0:
raise LnstError("Source/destination ip lists are of different size or empty.")
for src_addr, dst_addr in zip(client_ips, server_ips):
pconf = PingConf(client = client_nic.netns,
client_bind = src_addr,
destination = server_nic.netns,
destination_address = dst_addr,
**common_args)
yield [pconf]
- def generate_perf_configurations(self, main_config, sub_config):
if sub_config.encrypt:
client_nic = main_config.host1.msec0
server_nic = main_config.host2.msec0
client_netns = client_nic.netns
server_netns = server_nic.netns
flow_combinations = self.generate_flow_combinations(
main_config, sub_config
)
for flows in flow_combinations:
perf_recipe_conf=dict(
main_config=main_config,
sub_config=sub_config,
flows=flows,
)
flows_measurement = self.params.net_perf_tool(
flows,
perf_recipe_conf
)
cpu_measurement = self.params.cpu_perf_tool(
[client_netns, server_netns],
perf_recipe_conf,
)
perf_conf = PerfRecipeConf(
measurements=[cpu_measurement, flows_measurement],
iterations=self.params.perf_iterations,
)
perf_conf.register_evaluators(
cpu_measurement, self.cpu_perf_evaluators
)
perf_conf.register_evaluators(
flows_measurement, self.net_perf_evaluators
)
yield perf_conf
- def generate_flow_combinations(self, main_config, sub_config):
client_nic = main_config.host1.msec0
server_nic = main_config.host2.msec0
client_netns = client_nic.netns
server_netns = server_nic.netns
for ipv in self.params.ip_versions:
if ipv == "ipv4":
family = AF_INET
elif ipv == "ipv6":
family = AF_INET6
client_bind = client_nic.ips_filter(family=family)[0]
server_bind = server_nic.ips_filter(family=family)[0]
for perf_test in self.params.perf_tests:
flow = PerfFlow(
type = perf_test,
generator = client_netns,
generator_bind = client_bind,
receiver = server_netns,
receiver_bind = server_bind,
msg_size = self.params.perf_msg_size,
duration = self.params.perf_duration,
parallel_streams = self.params.perf_parallel_streams,
cpupin = self.params.perf_tool_cpu if "perf_tool_cpu" in self.params else None
)
yield [flow]
- def test_wide_configuration(self):
host1, host2 = self.matched.host1, self.matched.host2
for host in [host1, host2]:
host.eth0.down()
net_addr = "192.168.0"
for i, host in enumerate([host1, host2]):
host.eth0.ip_add(ipaddress(net_addr + '.' + str(i+1) + "/24"))
#Due to limitations in the current EnrtConfiguration
#class, a single vlan test pair is chosen
configuration = EnrtConfiguration()
configuration.endpoint1 = host1.eth0
configuration.endpoint2 = host2.eth0
configuration.host1 = host1
configuration.host2 = host2
cond = (self.params.ping_parallel or self.params.ping_bidirect or
self.params.perf_reverse)
if cond:
What's the point of writing the condition like this if its result isn't reused? just write it the same way directly in the if statement.
logging.debug("Parallelism in pings or reverse perf tests are "
"not supported for this recipe, ping_parallel/bidirect "
" or perf_reverse will be ignored.")
if "mtu" in self.params:
for host in [host1, host2]:
host.eth0.mtu = self.params.mtu
#TODO better service handling through HostAPI
if "dev_intr_cpu" in self.params:
for host in [host1, host2]:
host.run("service irqbalance stop")
self._pin_dev_interrupts(host.eth0, self.params.dev_intr_cpu)
return configuration
- def test_wide_deconfiguration(self, config):
host1, host2 = self.matched.host1, self.matched.host2
#TODO better service handling through HostAPI
if "dev_intr_cpu" in self.params:
for host in [host1, host2]:
host.run("service irqbalance start")
-- 2.17.1 _______________________________________________ LNST-developers mailing list -- lnst-developers@lists.fedorahosted.org To unsubscribe send an email to lnst-developers-leave@lists.fedorahosted.org Fedora Code of Conduct: https://getfedora.org/code-of-conduct.html List Guidelines: https://fedoraproject.org/wiki/Mailing_list_guidelines List Archives: https://lists.fedorahosted.org/archives/list/lnst-developers@lists.fedorahos...
The ordering of your methods is upside down. There's a reason why I wrote the BaseEnrtRecipe the way I did - to make the flow of reading the code easier.
If method A calls method B then A should be before B. So that I don't first read B when I don't have the context of it's use. I first read A, see that it uses a "smaller" "helper" method B that will be defined later and I continue reading method A, then I get to method B and that clears out the specifics of it's implementation, but it's public api (it's parameters and return value) should be relatively obvious from it's use from the method A.
-Ondrej
lnst-developers@lists.fedorahosted.org