From ca9fe243684253858d2b4c478fe0da8bde6442a1 Mon Sep 17 00:00:00 2001 From: Leonard Yu Date: Tue, 24 Oct 2023 17:32:19 +0200 Subject: [PATCH 1/5] Add support for two new modules Odin-10G-6S-6P[a] and Loki-100G-3S-1P-B[b] --- xoa_driver/__init__.py | 2 +- .../hli_v1/modules/modules_l23/family_f.py | 15 +++++++++++++++ .../hli_v1/modules/modules_l23/family_g.py | 16 +++++++++++++++- .../internals/hli_v1/ports/port_l23/family_f.py | 9 +++++++++ .../internals/hli_v1/ports/port_l23/family_g.py | 5 +++++ .../hli_v2/modules/modules_l23/family_f.py | 14 ++++++++++++++ .../hli_v2/modules/modules_l23/family_g.py | 14 ++++++++++++++ .../internals/hli_v2/ports/port_l23/family_f.py | 9 +++++++++ .../internals/hli_v2/ports/port_l23/family_g.py | 5 +++++ xoa_driver/modules.py | 3 +++ xoa_driver/ports.py | 6 ++++++ xoa_driver/v2/modules.py | 3 +++ xoa_driver/v2/ports.py | 6 ++++++ 13 files changed, 105 insertions(+), 2 deletions(-) diff --git a/xoa_driver/__init__.py b/xoa_driver/__init__.py index 2227104d..454327a4 100644 --- a/xoa_driver/__init__.py +++ b/xoa_driver/__init__.py @@ -1,2 +1,2 @@ -__version__ = "2.1.5" +__version__ = "2.1.6" __short_version__ = "2.0" diff --git a/xoa_driver/internals/hli_v1/modules/modules_l23/family_f.py b/xoa_driver/internals/hli_v1/modules/modules_l23/family_f.py index 8a866411..8ffebd44 100644 --- a/xoa_driver/internals/hli_v1/modules/modules_l23/family_f.py +++ b/xoa_driver/internals/hli_v1/modules/modules_l23/family_f.py @@ -128,3 +128,18 @@ def __init__(self, conn: "itf.IConnection", init_data: "m_itf.ModuleInitData") - ports_count=self.ports_count ) """Port Index Manager Odin-10G-1S-12P""" + + +@typing.final +@revisions.register_valkyrie_module(rev="Odin-10G-6S-6P[a]") +class MOdin10G6S6P_a(ModuleL23): + """Test module Odin-10G-6S-6P[a]""" + def __init__(self, conn: "itf.IConnection", init_data: "m_itf.ModuleInitData") -> None: + super().__init__(conn, init_data) + self.ports: pm.PortsManager[ports.POdin10G6S6P_a] = pm.PortsManager( + conn=conn, + ports_type=ports.POdin10G6S6P_a, + module_id=self.module_id, + ports_count=self.ports_count + ) + """Port Index Manager Odin-10G-6S-6P[a]""" \ No newline at end of file diff --git a/xoa_driver/internals/hli_v1/modules/modules_l23/family_g.py b/xoa_driver/internals/hli_v1/modules/modules_l23/family_g.py index f4346706..97e6cf59 100644 --- a/xoa_driver/internals/hli_v1/modules/modules_l23/family_g.py +++ b/xoa_driver/internals/hli_v1/modules/modules_l23/family_g.py @@ -67,4 +67,18 @@ def __init__(self, conn: "itf.IConnection", init_data: "m_itf.ModuleInitData") - module_id=self.module_id, ports_count=self.ports_count ) - """Port index manager of Loki-100G-3S-1P-B""" \ No newline at end of file + """Port index manager of Loki-100G-3S-1P-B""" + +@typing.final +@revisions.register_valkyrie_module(rev="Loki-100G-3S-1P-B[b]") +class MLoki100G3S1PB_b(ModuleL23): + """Test module Loki-100G-3S-1P-B[b]""" + def __init__(self, conn: "itf.IConnection", init_data: "m_itf.ModuleInitData") -> None: + super().__init__(conn, init_data) + self.ports: pm.PortsManager[ports.PLoki100G3S1PB_b] = pm.PortsManager( + conn=conn, + ports_type=ports.PLoki100G3S1PB_b, + module_id=self.module_id, + ports_count=self.ports_count + ) + """Port index manager of Loki-100G-3S-1P-B[b]""" \ No newline at end of file diff --git a/xoa_driver/internals/hli_v1/ports/port_l23/family_f.py b/xoa_driver/internals/hli_v1/ports/port_l23/family_f.py index 9ec7a1e0..4654f05a 100644 --- a/xoa_driver/internals/hli_v1/ports/port_l23/family_f.py +++ b/xoa_driver/internals/hli_v1/ports/port_l23/family_f.py @@ -93,6 +93,15 @@ def __init__(self, conn: "itf.IConnection", module_id: int, port_id: int) -> Non self.preamble = Preamble(conn, module_id, port_id) """Preamble settiNgs.""" +class POdin10G6S6P_a(FamilyF): + def __init__(self, conn: "itf.IConnection", module_id: int, port_id: int) -> None: + super().__init__(conn, module_id, port_id) + self.runt = Runt(conn, module_id, port_id) + """Runt settings.""" + + self.preamble = Preamble(conn, module_id, port_id) + """Preamble settiNgs.""" + class POdin10G1S2PT(FamilyF): """L23 port on Odin-10G-1S-2P-T module. diff --git a/xoa_driver/internals/hli_v1/ports/port_l23/family_g.py b/xoa_driver/internals/hli_v1/ports/port_l23/family_g.py index 5cfe14aa..584453b7 100644 --- a/xoa_driver/internals/hli_v1/ports/port_l23/family_g.py +++ b/xoa_driver/internals/hli_v1/ports/port_l23/family_g.py @@ -70,3 +70,8 @@ class PLoki100G3S1PB(FamilyG): """L23 port on Loki-100G-3S-1P-B module. """ ... + +class PLoki100G3S1PB_b(FamilyG): + """L23 port on Loki-100G-3S-1P-B[b] module. + """ + ... \ No newline at end of file diff --git a/xoa_driver/internals/hli_v2/modules/modules_l23/family_f.py b/xoa_driver/internals/hli_v2/modules/modules_l23/family_f.py index 10583e75..561e7ed6 100644 --- a/xoa_driver/internals/hli_v2/modules/modules_l23/family_f.py +++ b/xoa_driver/internals/hli_v2/modules/modules_l23/family_f.py @@ -128,3 +128,17 @@ def __init__(self, conn: "itf.IConnection", init_data: "m_itf.ModuleInitData") - ports_count=self.ports_count ) """Port index manager Odin-10G-1S-12P""" + +@typing.final +@revisions.register_valkyrie_module(rev="Odin-10G-6S-6P[a]") +class MOdin10G6S6P_a(ModuleL23): + """Test module Odin-10G-6S-6P[a]""" + def __init__(self, conn: "itf.IConnection", init_data: "m_itf.ModuleInitData") -> None: + super().__init__(conn, init_data) + self.ports: pm.PortsManager[ports.POdin10G6S6P_a] = pm.PortsManager( + conn=conn, + ports_type=ports.POdin10G6S6P_a, + module_id=self.module_id, + ports_count=self.ports_count + ) + """Port Index Manager Odin-10G-6S-6P[a]""" diff --git a/xoa_driver/internals/hli_v2/modules/modules_l23/family_g.py b/xoa_driver/internals/hli_v2/modules/modules_l23/family_g.py index 5baf9b4a..aed1e279 100644 --- a/xoa_driver/internals/hli_v2/modules/modules_l23/family_g.py +++ b/xoa_driver/internals/hli_v2/modules/modules_l23/family_g.py @@ -68,3 +68,17 @@ def __init__(self, conn: "itf.IConnection", init_data: "m_itf.ModuleInitData") - ports_count=self.ports_count ) """Port index manager of Loki-100G-3S-1P-B""" + +@typing.final +@revisions.register_valkyrie_module(rev="Loki-100G-3S-1P-B[b]") +class MLoki100G3S1PB_b(ModuleL23): + """Test module Loki-100G-3S-1P-B[b]""" + def __init__(self, conn: "itf.IConnection", init_data: "m_itf.ModuleInitData") -> None: + super().__init__(conn, init_data) + self.ports: pm.PortsManager[ports.PLoki100G3S1PB_b] = pm.PortsManager( + conn=conn, + ports_type=ports.PLoki100G3S1PB_b, + module_id=self.module_id, + ports_count=self.ports_count + ) + """Port index manager of Loki-100G-3S-1P-B[b]""" diff --git a/xoa_driver/internals/hli_v2/ports/port_l23/family_f.py b/xoa_driver/internals/hli_v2/ports/port_l23/family_f.py index 2f04d572..a961a464 100644 --- a/xoa_driver/internals/hli_v2/ports/port_l23/family_f.py +++ b/xoa_driver/internals/hli_v2/ports/port_l23/family_f.py @@ -88,6 +88,15 @@ def __init__(self, conn: "itf.IConnection", module_id: int, port_id: int) -> Non self.preamble = Preamble(conn, module_id, port_id) """Preamble settiNgs.""" +class POdin10G6S6P_a(FamilyF): + def __init__(self, conn: "itf.IConnection", module_id: int, port_id: int) -> None: + super().__init__(conn, module_id, port_id) + self.runt = Runt(conn, module_id, port_id) + """Runt settings.""" + + self.preamble = Preamble(conn, module_id, port_id) + """Preamble settiNgs.""" + class POdin10G1S2PT(FamilyF): """L23 port on Odin-10G-1S-2P-T module. diff --git a/xoa_driver/internals/hli_v2/ports/port_l23/family_g.py b/xoa_driver/internals/hli_v2/ports/port_l23/family_g.py index 5cfe14aa..9b198e65 100644 --- a/xoa_driver/internals/hli_v2/ports/port_l23/family_g.py +++ b/xoa_driver/internals/hli_v2/ports/port_l23/family_g.py @@ -70,3 +70,8 @@ class PLoki100G3S1PB(FamilyG): """L23 port on Loki-100G-3S-1P-B module. """ ... + +class PLoki100G3S1PB_b(FamilyG): + """L23 port on Loki-100G-3S-1P-B[b] module. + """ + ... diff --git a/xoa_driver/modules.py b/xoa_driver/modules.py index c1c54a6b..bf531052 100644 --- a/xoa_driver/modules.py +++ b/xoa_driver/modules.py @@ -27,6 +27,7 @@ MOdin10G1S6P, MOdin10G1S6P_b, MOdin10G1S12P, + MOdin10G6S6P_a, ) from .internals.hli_v1.modules.modules_l23.family_g import ( MLoki100G3S1P, @@ -135,6 +136,7 @@ "MOdin1G3S6PT1RJ45", "MOdin10G4S2PCombi", "MOdin10G4S2PCombi_b", + "MOdin10G6S6P_a", ] GenericAnyModule = typing.Union[ @@ -200,6 +202,7 @@ "MOdin1G3S6PT1RJ45", "MOdin10G4S2PCombi", "MOdin10G4S2PCombi_b", + "MOdin10G6S6P_a", "ModuleL23VE", "ModuleChimera", "MChi100G5S2P", diff --git a/xoa_driver/ports.py b/xoa_driver/ports.py index 1c3f42bd..15cc3190 100644 --- a/xoa_driver/ports.py +++ b/xoa_driver/ports.py @@ -50,6 +50,7 @@ POdin10G1S12P, POdin40G2S2P, POdin40G2S2PB, + POdin10G6S6P_a, ) from xoa_driver.internals.hli_v1.ports.port_l23.family_g import ( @@ -57,6 +58,7 @@ PLoki100G3S1P_b, PLoki100G3S1PSE, PLoki100G3S1PB, + PLoki100G3S1PB_b, ) from xoa_driver.internals.hli_v1.ports.port_l23.family_h import ( @@ -145,6 +147,8 @@ "POdin1G4S4PCombi_b", "POdin10G4S2PCombi", "POdin10G4S2PCombi_b", + "POdin10G6S6P_a", + "PLoki100G3S1PB_b", ] GenericAnyPort = typing.Union[ @@ -210,6 +214,8 @@ "POdin1G4S4PCombi_b", "POdin10G4S2PCombi", "POdin10G4S2PCombi_b", + "POdin10G6S6P_a", + "PLoki100G3S1PB_b", "PortL47", "PortL23VE", "PortChimera", diff --git a/xoa_driver/v2/modules.py b/xoa_driver/v2/modules.py index fe1c802c..c0308635 100644 --- a/xoa_driver/v2/modules.py +++ b/xoa_driver/v2/modules.py @@ -23,6 +23,7 @@ MOdin10G1S6P, MOdin10G1S6P_b, MOdin10G1S12P, + MOdin10G6S6P_a, ) from xoa_driver.internals.hli_v2.modules.modules_l23.family_g import ( MLoki100G3S1P, @@ -131,6 +132,7 @@ "MOdin1G3S6PT1RJ45", "MOdin10G4S2PCombi", "MOdin10G4S2PCombi_b", + "MOdin10G6S6P_a", ] GenericAnyModule = typing.Union[ @@ -196,6 +198,7 @@ "MOdin1G3S6PT1RJ45", "MOdin10G4S2PCombi", "MOdin10G4S2PCombi_b", + "MOdin10G6S6P_a", "ModuleL23VE", "ModuleChimera", "MChi100G5S2P", diff --git a/xoa_driver/v2/ports.py b/xoa_driver/v2/ports.py index 82ee3e36..be1f02ee 100644 --- a/xoa_driver/v2/ports.py +++ b/xoa_driver/v2/ports.py @@ -47,6 +47,7 @@ POdin10G1S12P, POdin40G2S2P, POdin40G2S2PB, + POdin10G6S6P_a, ) from xoa_driver.internals.hli_v2.ports.port_l23.family_g import ( @@ -54,6 +55,7 @@ PLoki100G3S1P_b, PLoki100G3S1PSE, PLoki100G3S1PB, + PLoki100G3S1PB_b, ) from xoa_driver.internals.hli_v2.ports.port_l23.family_h import ( @@ -142,6 +144,8 @@ "POdin1G4S4PCombi_b", "POdin10G4S2PCombi", "POdin10G4S2PCombi_b", + "POdin10G6S6P_a", + "PLoki100G3S1PB_b", ] GenericAnyPort = typing.Union[ @@ -207,6 +211,8 @@ "POdin1G4S4PCombi_b", "POdin10G4S2PCombi", "POdin10G4S2PCombi_b", + "POdin10G6S6P_a", + "PLoki100G3S1PB_b", "PortL47", "PortL23VE", "PortChimera", From 51bfb128fd790b4f694a37c7bf0786532fcc5735 Mon Sep 17 00:00:00 2001 From: Leonard Yu Date: Tue, 24 Oct 2023 21:57:31 +0200 Subject: [PATCH 2/5] Add more param to p_capabilities --- xoa_driver/internals/commands/enums.py | 105 ++++++++++++++ xoa_driver/internals/commands/p_commands.py | 149 ++++++++++++++++++++ 2 files changed, 254 insertions(+) diff --git a/xoa_driver/internals/commands/enums.py b/xoa_driver/internals/commands/enums.py index 58033896..869e62f5 100644 --- a/xoa_driver/internals/commands/enums.py +++ b/xoa_driver/internals/commands/enums.py @@ -2490,6 +2490,111 @@ class RxEqExtCap(IntEnum): CTLE_HIGH = 1 """CTLE high frequency.""" + AGC = 2 + """Automatic Gain Control""" + + OC = 3 + """Offset Cancellation""" + + CDR = 4 + """Clock and Data Recovery""" + + PRE_FFE_1 = 5 + """Pre Feed-Forward Equalizer #1""" + + PRE_FFE_2 = 6 + """Pre Feed-Forward Equalizer #2""" + + PRE_FFE_3 = 7 + """Pre Feed-Forward Equalizer #3""" + + PRE_FFE_4 = 8 + """Pre Feed-Forward Equalizer #4""" + + PRE_FFE_5 = 9 + """Pre Feed-Forward Equalizer #5""" + + PRE_FFE_6 = 10 + """Pre Feed-Forward Equalizer #6""" + + PRE_FFE_7 = 11 + """Pre Feed-Forward Equalizer #7""" + + PRE_FFE_8 = 12 + """Pre Feed-Forward Equalizer #8""" + + DFE = 13 + """Decision Feedback Equalization""" + + POST_FFE_1 = 14 + """Post Feed-Forward Equalizer #1""" + + POST_FFE_2 = 15 + """Post Feed-Forward Equalizer #2""" + + POST_FFE_3 = 16 + """Post Feed-Forward Equalizer #3""" + + POST_FFE_4 = 17 + """Post Feed-Forward Equalizer #4""" + + POST_FFE_5 = 18 + """Post Feed-Forward Equalizer #5""" + + POST_FFE_6 = 19 + """Post Feed-Forward Equalizer #6""" + + POST_FFE_7 = 20 + """Post Feed-Forward Equalizer #7""" + + POST_FFE_8 = 21 + """Post Feed-Forward Equalizer #8""" + + POST_FFE_9 = 22 + """Post Feed-Forward Equalizer #9""" + + POST_FFE_10 = 23 + """Post Feed-Forward Equalizer #10""" + + POST_FFE_11 = 24 + """Post Feed-Forward Equalizer #11""" + + POST_FFE_12 = 25 + """Post Feed-Forward Equalizer #12""" + + POST_FFE_13 = 26 + """Post Feed-Forward Equalizer #13""" + + POST_FFE_14 = 27 + """Post Feed-Forward Equalizer #14""" + + POST_FFE_15 = 28 + """Post Feed-Forward Equalizer #15""" + + POST_FFE_16 = 29 + """Post Feed-Forward Equalizer #16""" + + POST_FFE_17 = 30 + """Post Feed-Forward Equalizer #17""" + + POST_FFE_18 = 31 + """Post Feed-Forward Equalizer #18""" + + POST_FFE_19 = 32 + """Post Feed-Forward Equalizer #19""" + + POST_FFE_20 = 33 + """Post Feed-Forward Equalizer #20""" + + POST_FFE_21 = 34 + """Post Feed-Forward Equalizer #21""" + + POST_FFE_22 = 35 + """Post Feed-Forward Equalizer #22""" + + POST_FFE_23 = 36 + """Post Feed-Forward Equalizer #23""" + class RxEqExtCapMode(IntEnum): """Status for Rx Equalizer Advanced Capability.""" diff --git a/xoa_driver/internals/commands/p_commands.py b/xoa_driver/internals/commands/p_commands.py index d46a7b0a..cd6c9aa7 100644 --- a/xoa_driver/internals/commands/p_commands.py +++ b/xoa_driver/internals/commands/p_commands.py @@ -370,6 +370,155 @@ class GetDataAttr(ResponseBodyStruct): """integer, max match term position in bytes""" stream_misc: int = field(XmpInt(), min_version=457) """integer, bit pattern, what streams on this port can do. [0]: Whether the port supports streams with DEC8/INC16/DEC16 payload. [1]: Whether the port supports INCPLDFROM0 stream option (refer to the PS_OPTIONS command).""" + rxeq_cap_ctle_low_min: int = field(XmpInt(), min_version=457) + """min value of CTLE LOW.""" + rxeq_cap_ctle_high_min: int = field(XmpInt(), min_version=457) + """min value of CTLE HIGH.""" + rxeq_cap_agc_min: int = field(XmpInt(), min_version=457) + """min value of Automatic Gain Control.""" + rxeq_cap_oc_min: int = field(XmpInt(), min_version=457) + """min value of Offset Cancellation.""" + rxeq_cap_ffe_pre1_min: int = field(XmpInt(), min_version=457) + """min value of FFE Pre 1.""" + rxeq_cap_ffe_pre2_min: int = field(XmpInt(), min_version=457) + """min value of FFE Pre 2.""" + rxeq_cap_ffe_pre3_min: int = field(XmpInt(), min_version=457) + """min value of FFE Pre 3.""" + rxeq_cap_ffe_pre4_min: int = field(XmpInt(), min_version=457) + """min value of FFE Pre 4.""" + rxeq_cap_ffe_pre5_min: int = field(XmpInt(), min_version=457) + """min value of FFE Pre 5.""" + rxeq_cap_ffe_pre6_min: int = field(XmpInt(), min_version=457) + """min value of FFE Pre 6.""" + rxeq_cap_ffe_pre7_min: int = field(XmpInt(), min_version=457) + """min value of FFE Pre 7.""" + rxeq_cap_ffe_pre8_min: int = field(XmpInt(), min_version=457) + """min value of FFE Pre 8.""" + rxeq_cap_ffe_post1_min: int = field(XmpInt(), min_version=457) + """min value of FFE Post 1.""" + rxeq_cap_ffe_post2_min: int = field(XmpInt(), min_version=457) + """min value of FFE Post 2.""" + rxeq_cap_ffe_post3_min: int = field(XmpInt(), min_version=457) + """min value of FFE Post 3.""" + rxeq_cap_ffe_post4_min: int = field(XmpInt(), min_version=457) + """min value of FFE Post 4.""" + rxeq_cap_ffe_post5_min: int = field(XmpInt(), min_version=457) + """min value of FFE Post 5.""" + rxeq_cap_ffe_post6_min: int = field(XmpInt(), min_version=457) + """min value of FFE Post 6.""" + rxeq_cap_ffe_post7_min: int = field(XmpInt(), min_version=457) + """min value of FFE Post 7.""" + rxeq_cap_ffe_post8_min: int = field(XmpInt(), min_version=457) + """min value of FFE Post 8.""" + rxeq_cap_ffe_post9_min: int = field(XmpInt(), min_version=457) + """min value of FFE Post 9.""" + rxeq_cap_ffe_post10_min: int = field(XmpInt(), min_version=457) + """min value of FFE Post 10.""" + rxeq_cap_ffe_post11_min: int = field(XmpInt(), min_version=457) + """min value of FFE Post 11.""" + rxeq_cap_ffe_post12_min: int = field(XmpInt(), min_version=457) + """min value of FFE Post 12.""" + rxeq_cap_ffe_post13_min: int = field(XmpInt(), min_version=457) + """min value of FFE Post 13.""" + rxeq_cap_ffe_post14_min: int = field(XmpInt(), min_version=457) + """min value of FFE Post 14.""" + rxeq_cap_ffe_post15_min: int = field(XmpInt(), min_version=457) + """min value of FFE Post 15.""" + rxeq_cap_ffe_post16_min: int = field(XmpInt(), min_version=457) + """min value of FFE Post 16.""" + rxeq_cap_ffe_post17_min: int = field(XmpInt(), min_version=457) + """min value of FFE Post 17.""" + rxeq_cap_ffe_post18_min: int = field(XmpInt(), min_version=457) + """min value of FFE Post 18.""" + rxeq_cap_ffe_post19_min: int = field(XmpInt(), min_version=457) + """min value of FFE Post 19.""" + rxeq_cap_ffe_post20_min: int = field(XmpInt(), min_version=457) + """min value of FFE Post 20.""" + rxeq_cap_ffe_post21_min: int = field(XmpInt(), min_version=457) + """min value of FFE Post 21.""" + rxeq_cap_ffe_post22_min: int = field(XmpInt(), min_version=457) + """min value of FFE Post 22.""" + rxeq_cap_ffe_post23_min: int = field(XmpInt(), min_version=457) + """min value of FFE Post 23.""" + rxeq_cap_ctle_low_max: int = field(XmpInt(), min_version=457) + """max value of CTLE LOW.""" + rxeq_cap_ctle_high_max: int = field(XmpInt(), min_version=457) + """max value of CTLE HIGH.""" + rxeq_cap_agc_max: int = field(XmpInt(), min_version=457) + """max value of Automatic Gain Control.""" + rxeq_cap_oc_max: int = field(XmpInt(), min_version=457) + """max value of Offset Cancellation.""" + rxeq_cap_ffe_pre1_max: int = field(XmpInt(), min_version=457) + """max value of FFE Pre 1.""" + rxeq_cap_ffe_pre2_max: int = field(XmpInt(), min_version=457) + """max value of FFE Pre 2.""" + rxeq_cap_ffe_pre3_max: int = field(XmpInt(), min_version=457) + """max value of FFE Pre 3.""" + rxeq_cap_ffe_pre4_max: int = field(XmpInt(), min_version=457) + """max value of FFE Pre 4.""" + rxeq_cap_ffe_pre5_max: int = field(XmpInt(), min_version=457) + """max value of FFE Pre 5.""" + rxeq_cap_ffe_pre6_max: int = field(XmpInt(), min_version=457) + """max value of FFE Pre 6.""" + rxeq_cap_ffe_pre7_max: int = field(XmpInt(), min_version=457) + """max value of FFE Pre 7.""" + rxeq_cap_ffe_pre8_max: int = field(XmpInt(), min_version=457) + """max value of FFE Pre 8.""" + rxeq_cap_ffe_post1_max: int = field(XmpInt(), min_version=457) + """max value of FFE Post 1.""" + rxeq_cap_ffe_post2_max: int = field(XmpInt(), min_version=457) + """max value of FFE Post 2.""" + rxeq_cap_ffe_post3_max: int = field(XmpInt(), min_version=457) + """max value of FFE Post 3.""" + rxeq_cap_ffe_post4_max: int = field(XmpInt(), min_version=457) + """max value of FFE Post 4.""" + rxeq_cap_ffe_post5_max: int = field(XmpInt(), min_version=457) + """max value of FFE Post 5.""" + rxeq_cap_ffe_post6_max: int = field(XmpInt(), min_version=457) + """max value of FFE Post 6.""" + rxeq_cap_ffe_post7_max: int = field(XmpInt(), min_version=457) + """max value of FFE Post 7.""" + rxeq_cap_ffe_post8_max: int = field(XmpInt(), min_version=457) + """max value of FFE Post 8.""" + rxeq_cap_ffe_post9_max: int = field(XmpInt(), min_version=457) + """max value of FFE Post 9.""" + rxeq_cap_ffe_post10_max: int = field(XmpInt(), min_version=457) + """max value of FFE Post 10.""" + rxeq_cap_ffe_post11_max: int = field(XmpInt(), min_version=457) + """max value of FFE Post 11.""" + rxeq_cap_ffe_post12_max: int = field(XmpInt(), min_version=457) + """max value of FFE Post 12.""" + rxeq_cap_ffe_post13_max: int = field(XmpInt(), min_version=457) + """max value of FFE Post 13.""" + rxeq_cap_ffe_post14_max: int = field(XmpInt(), min_version=457) + """max value of FFE Post 14.""" + rxeq_cap_ffe_post15_max: int = field(XmpInt(), min_version=457) + """max value of FFE Post 15.""" + rxeq_cap_ffe_post16_max: int = field(XmpInt(), min_version=457) + """max value of FFE Post 16.""" + rxeq_cap_ffe_post17_max: int = field(XmpInt(), min_version=457) + """max value of FFE Post 17.""" + rxeq_cap_ffe_post18_max: int = field(XmpInt(), min_version=457) + """max value of FFE Post 18.""" + rxeq_cap_ffe_post19_max: int = field(XmpInt(), min_version=457) + """max value of FFE Post 19.""" + rxeq_cap_ffe_post20_max: int = field(XmpInt(), min_version=457) + """max value of FFE Post 20.""" + rxeq_cap_ffe_post21_max: int = field(XmpInt(), min_version=457) + """max value of FFE Post 21.""" + rxeq_cap_ffe_post22_max: int = field(XmpInt(), min_version=457) + """max value of FFE Post 22.""" + rxeq_cap_ffe_post23_max: int = field(XmpInt(), min_version=457) + """max value of FFE Post 23.""" + length_histogram_step_max: int = field(XmpInt(), min_version=457) + """minimum step size for length histograms.""" + length_histogram_step_max: int = field(XmpInt(), min_version=457) + """maximum step size for length histograms.""" + latency_histogram_step_max: int = field(XmpInt(), min_version=457) + """minimum step size for latency histograms.""" + latency_histogram_step_max: int = field(XmpInt(), min_version=457) + """maximum step size for latency histograms.""" + def get(self) -> Token[GetDataAttr]: """Get the internal limits, aka. capabilities, of the port. From 2240a4453af10ad60829a12569cc5e061c153b3a Mon Sep 17 00:00:00 2001 From: Leonard Yu Date: Tue, 24 Oct 2023 21:58:02 +0200 Subject: [PATCH 3/5] Add PP_PHYRXEQSTATUS_EXT and PP_PRECODINGSTATUS --- xoa_driver/internals/commands/pp_commands.py | 85 +++++++++++++++++--- 1 file changed, 75 insertions(+), 10 deletions(-) diff --git a/xoa_driver/internals/commands/pp_commands.py b/xoa_driver/internals/commands/pp_commands.py index 4be34408..bc064308 100644 --- a/xoa_driver/internals/commands/pp_commands.py +++ b/xoa_driver/internals/commands/pp_commands.py @@ -1908,6 +1908,40 @@ def set(self, mode: RxEqExtCapMode, value: int) -> Token[None]: return Token(self._connection, build_set_request(self, module=self._module, port=self._port, indices=[self._serdes_xindex, self._capability_type], mode=mode, value=value)) +@register_command +@dataclass +class PP_PHYRXEQSTATUS_EXT: + """ + Get RX EQ advanced parameter values. (Only for Freya modules) + """ + + code: typing.ClassVar[int] = 398 + pushed: typing.ClassVar[bool] = True + + _connection: 'interfaces.IConnection' + _module: int + _port: int + _serdes_xindex: int + _capability_type: RxEqExtCap + + class GetDataAttr(ResponseBodyStruct): + value1: int = field(XmpInt()) + """the 1st value for the capability""" + value2: int = field(XmpInt()) + """the 2nd value for the capability""" + + + def get(self) -> Token[GetDataAttr]: + """Get RX EQ Advanced parameters. + + :return: mode Auto/Manual/Freeze, value. + :rtype: PP_PHYRXEQ_EXT.GetDataAttr + """ + + return Token(self._connection, build_get_request(self, module=self._module, port=self._port, indices=[self._serdes_xindex, self._capability_type])) + + + @register_command @dataclass class PP_AUTONEG: @@ -2030,8 +2064,7 @@ def get(self) -> Token[GetDataAttr]: @dataclass class PP_LINKTRAIN: """ - Link training settings - for Thor-400G-7S-1P rev.B. The PP_LINKTRAIN command is - per port. + Link training settings - for Thor-400G-7S-1P and Freya modules """ code: typing.ClassVar[int] = 383 @@ -2115,8 +2148,7 @@ def set( @dataclass class PP_LINKTRAINSTATUS: """ - Per lane Link training status - for Thor-400G-7S-1P rev.B. The PP_LINKTRAINSTATUS command - is per lane. + Per lane Link training status - for Thor-400G-7S-1P and Freya modules """ code: typing.ClassVar[int] = 384 @@ -2148,7 +2180,7 @@ def get(self) -> Token[GetDataAttr]: @dataclass class PP_PRECODING: """ - GET/SET Pre-Coding Configurations. + GET/SET Pre-Coding Configurations. (only for Freya) """ code: typing.ClassVar[int] = 420 @@ -2201,14 +2233,13 @@ def set(self, rx_mode: PreCodingMode, rx_endianness: Endianness, tx_mode: PreCod :type endianness: Endianness """ - return Token(self._connection, build_set_request(self, module=self._module, port=self._port, indices=[self._serdes_xindex], - rx_mode=rx_mode, rx_endianness=rx_endianness, tx_mode=tx_mode, tx_endianness=tx_endianness)) + return Token(self._connection, build_set_request(self, module=self._module, port=self._port, indices=[self._serdes_xindex], rx_mode=rx_mode, rx_endianness=rx_endianness, tx_mode=tx_mode, tx_endianness=tx_endianness)) @register_command @dataclass class PP_GRAYCODING: """ - GET/SET Gray-Coding Configurations. + GET/SET Gray-Coding Configurations. (only for Freya) """ code: typing.ClassVar[int] = 421 @@ -2261,5 +2292,39 @@ def set(self, rx_mode: GrayCodingMode, rx_endianness: Endianness, tx_mode: GrayC :type endianness: Endianness """ - return Token(self._connection, build_set_request(self, module=self._module, port=self._port, indices=[self._serdes_xindex], - rx_mode=rx_mode, rx_endianness=rx_endianness, tx_mode=tx_mode, tx_endianness=tx_endianness)) + return Token(self._connection, build_set_request(self, module=self._module, port=self._port, indices=[self._serdes_xindex], rx_mode=rx_mode, rx_endianness=rx_endianness, tx_mode=tx_mode, tx_endianness=tx_endianness)) + + +@register_command +@dataclass +class PP_PRECODINGSTATUS: + """ + GET Pre-Coding status (only for Freya) + """ + + code: typing.ClassVar[int] = 422 + pushed: typing.ClassVar[bool] = True + + _connection: 'interfaces.IConnection' + _module: int + _port: int + _serdes_xindex: int + + class GetDataAttr(ResponseBodyStruct): + rx_mode: OnOff = field(XmpInt()) + """RX Mode Off/On""" + rx_endianness: Endianness = field(XmpInt()) + """RX Endianness Normal/Reverted(BigEndian/LittleEndian)) """ + tx_mode: OnOff = field(XmpInt()) + """TX Mode Off/On""" + tx_endianness: Endianness = field(XmpInt()) + """TX Endianness Normal/Reverted(BigEndian/LittleEndian)) """ + + def get(self) -> Token[GetDataAttr]: + """Get the Pre-Coding Configurations. + + :return: Pre-Coding configurations including rx_mode, rx_endianness, tx_mode, and tx_endianness. + :rtype: PP_PRECODING.GetDataAttr + """ + + return Token(self._connection, build_get_request(self, module=self._module, port=self._port, indices=[self._serdes_xindex])) From dbdd70845a0ef7e51fa5eeeb0c21caf34697e526 Mon Sep 17 00:00:00 2001 From: Leonard Yu Date: Wed, 25 Oct 2023 15:10:48 +0200 Subject: [PATCH 4/5] Move code example to script lib repo --- docs/source/code_example/boilerplate.py | 9 - docs/source/code_example/cli_conversion.rst | 22 -- .../code_example/cli_conversion/cli_script.py | 147 ------------ .../code_example/cli_conversion/config.txt | 5 - .../code_example/cli_conversion/xoa_script.py | 210 ------------------ docs/source/code_example/cli_integration.rst | 8 - .../cli_integration/xoa_script.py | 76 ------- docs/source/code_example/hlapiv1.rst | 200 ----------------- .../hlapiv1/01_create_tester_from_type.py | 15 -- .../hlapiv1/02_create_tester_context.py | 15 -- .../hlapiv1/03_create_multi_testers.py | 24 -- .../hlapiv1/04_obtain_one_module.py | 21 -- .../hlapiv1/05_obtain_multiple_modules.py | 22 -- .../hlapiv1/06_obtain_all_modules.py | 20 -- .../hlapiv1/07_obtain_one_port.py | 25 --- .../hlapiv1/08_obtain_multiple_ports.py | 20 -- .../hlapiv1/09_obtain_all_ports.py | 23 -- .../hlapiv1/10_query_parameters.py | 32 --- .../hlapiv1/11_setting_parameters.py | 50 ----- .../source/code_example/hlapiv1/12_streams.py | 80 ------- .../code_example/hlapiv1/13_modifiers.py | 91 -------- .../code_example/hlapiv1/14_traffic_stats.py | 156 ------------- .../hlapiv1/15_traffic_impairment.py | 119 ---------- .../hlapiv1/16_transceiver_reg.py | 61 ----- .../hlapiv2/traffic_impairment.py | 164 -------------- docs/source/code_example/index.rst | 28 ++- docs/source/code_example/llapi.rst | 73 ------ .../llapi/create_conn_to_tester.py | 26 --- .../llapi/create_multiple_conns.py | 39 ---- .../llapi/obtain_multiple_modules.py | 30 --- .../code_example/llapi/obtain_one_module.py | 28 --- .../code_example/llapi/query_parameters.py | 29 --- .../code_example/llapi/setting_parameters.py | 34 --- .../code_example/llapi/stats_collection.py | 34 --- docs/source/code_example/xpc_integration.rst | 16 -- .../xpc_integration/port_config.xpc | 77 ------- .../xpc_integration/port_config_hlapi.py | 44 ---- .../understand_xoa_python/hlapi_guide.rst | 11 - 38 files changed, 19 insertions(+), 2065 deletions(-) delete mode 100644 docs/source/code_example/boilerplate.py delete mode 100644 docs/source/code_example/cli_conversion.rst delete mode 100644 docs/source/code_example/cli_conversion/cli_script.py delete mode 100644 docs/source/code_example/cli_conversion/config.txt delete mode 100644 docs/source/code_example/cli_conversion/xoa_script.py delete mode 100644 docs/source/code_example/cli_integration.rst delete mode 100644 docs/source/code_example/cli_integration/xoa_script.py delete mode 100644 docs/source/code_example/hlapiv1.rst delete mode 100644 docs/source/code_example/hlapiv1/01_create_tester_from_type.py delete mode 100644 docs/source/code_example/hlapiv1/02_create_tester_context.py delete mode 100644 docs/source/code_example/hlapiv1/03_create_multi_testers.py delete mode 100644 docs/source/code_example/hlapiv1/04_obtain_one_module.py delete mode 100644 docs/source/code_example/hlapiv1/05_obtain_multiple_modules.py delete mode 100644 docs/source/code_example/hlapiv1/06_obtain_all_modules.py delete mode 100644 docs/source/code_example/hlapiv1/07_obtain_one_port.py delete mode 100644 docs/source/code_example/hlapiv1/08_obtain_multiple_ports.py delete mode 100644 docs/source/code_example/hlapiv1/09_obtain_all_ports.py delete mode 100644 docs/source/code_example/hlapiv1/10_query_parameters.py delete mode 100644 docs/source/code_example/hlapiv1/11_setting_parameters.py delete mode 100644 docs/source/code_example/hlapiv1/12_streams.py delete mode 100644 docs/source/code_example/hlapiv1/13_modifiers.py delete mode 100644 docs/source/code_example/hlapiv1/14_traffic_stats.py delete mode 100644 docs/source/code_example/hlapiv1/15_traffic_impairment.py delete mode 100644 docs/source/code_example/hlapiv1/16_transceiver_reg.py delete mode 100644 docs/source/code_example/hlapiv2/traffic_impairment.py delete mode 100644 docs/source/code_example/llapi.rst delete mode 100644 docs/source/code_example/llapi/create_conn_to_tester.py delete mode 100644 docs/source/code_example/llapi/create_multiple_conns.py delete mode 100644 docs/source/code_example/llapi/obtain_multiple_modules.py delete mode 100644 docs/source/code_example/llapi/obtain_one_module.py delete mode 100644 docs/source/code_example/llapi/query_parameters.py delete mode 100644 docs/source/code_example/llapi/setting_parameters.py delete mode 100644 docs/source/code_example/llapi/stats_collection.py delete mode 100644 docs/source/code_example/xpc_integration.rst delete mode 100644 docs/source/code_example/xpc_integration/port_config.xpc delete mode 100644 docs/source/code_example/xpc_integration/port_config_hlapi.py diff --git a/docs/source/code_example/boilerplate.py b/docs/source/code_example/boilerplate.py deleted file mode 100644 index 08ed4fef..00000000 --- a/docs/source/code_example/boilerplate.py +++ /dev/null @@ -1,9 +0,0 @@ -import asyncio - -async def main(): - # your code goes here... - ... - await asyncio.Event().wait() - -if __name__ == "__main__": - asyncio.run(main()) \ No newline at end of file diff --git a/docs/source/code_example/cli_conversion.rst b/docs/source/code_example/cli_conversion.rst deleted file mode 100644 index 64d5bf25..00000000 --- a/docs/source/code_example/cli_conversion.rst +++ /dev/null @@ -1,22 +0,0 @@ -Conversion from CLI -=================================== - -If you are already familiar with :term:`XOA CLI`, the comparison below will help you understand the differences between a :term:`XOA HL-API` script and a CLI script. Both scripts do the same thing and generate the same port/stream configuration. - -Both scripts are using the configuration text file below: - -.. literalinclude:: cli_conversion/config.txt - :caption: Configuration for Both - - -.. tab:: CLI - - .. literalinclude:: cli_conversion/cli_script.py - :caption: In XOA CLI - - -.. tab:: HL-API - - .. literalinclude:: cli_conversion/xoa_script.py - :caption: In XOA HL Python API - diff --git a/docs/source/code_example/cli_conversion/cli_script.py b/docs/source/code_example/cli_conversion/cli_script.py deleted file mode 100644 index 7986280c..00000000 --- a/docs/source/code_example/cli_conversion/cli_script.py +++ /dev/null @@ -1,147 +0,0 @@ -# coding=UTF-8 -import time, json, random, queue, types, sys, socket, math, os -from binascii import hexlify -from TestUtilsL23 import XenaScriptTools # Download from https://github.com/xenadevel/xenascriptlibs/tree/master/layer23/python3/testutils - -def runtest(xm, ports, rate, size, duration): - print("Start the scripting...") - ##RELEASE THE ports, relinquish other users. - xm.Send(ports[0] + ' P_RESERVATION RELEASE') - xm.Send(ports[0] + ' P_RESERVATION relinquish') - xm.Send(ports[1] + ' P_RESERVATION RELEASE') - xm.Send(ports[1] + ' P_RESERVATION relinquish') - - - ##Release the port and then Reserve the ports - print ("Resever the port...") - xm.Send(ports[0] + ' P_RESERVATION RESERVE') - xm.Send(ports[1] + ' P_RESERVATION RESERVE') - ##RESET PORTS - xm.Send(ports[0] + ' P_RESET') - xm.Send(ports[1] + ' P_RESET') - time.sleep(3) - - - MAC1= '000000000002' - MAC2= '000000000001' - IP1 = '192.168.100.100' - IP2 = '192.168.100.101' - IP1 = hexlify(socket.inet_aton(IP1)).decode() - IP2 = hexlify(socket.inet_aton(IP2)).decode() - hearder1 = '0x' + str(MAC2) + str(MAC1) + '08004500002E000000007FFFF0B6' + str(IP1) + str(IP2) - hearder2 = '0x' + str(MAC1) + str(MAC2) + '08004500002E000000007FFFF0B6' + str(IP2) + str(IP1) - - print("Start to configure the streams...") - ##Create the streams in port 0 - ##Create the SID index of stream - xm.SendExpectOK(ports[0] + " PS_CREATE [0]") - ##Create the TPLD index of stream - xm.SendExpectOK(ports[0] + " PS_TPLDID [0] 0") - ##Configure the packet size - xm.SendExpectOK(ports[0] + " PS_PACKETLENGTH [0]" + size) - ##Configure the packet type - xm.SendExpectOK(ports[0] + " PS_HEADERPROTOCOL [0] ETHERNET IP") - ##Configure the packet header - xm.SendExpectOK(ports[0] + " PS_PACKETHEADER [0] "+ str(hearder1)) - ##Enable streams - xm.SendExpectOK(ports[0] + " PS_ENABLE [0] on") - ##Configure the stream rate - xm.SendExpectOK(ports[0] + " PS_RATEFRACTION [0] " + str(int(rate)*10000)) - - ##Create the streams in port 1 - xm.SendExpectOK(ports[1] + " PS_CREATE [1]") - xm.SendExpectOK(ports[1] + " PS_TPLDID [1] 1") - xm.SendExpectOK(ports[1] + " PS_PACKETLENGTH [1]" + size) - xm.SendExpectOK(ports[1] + " PS_HEADERPROTOCOL [1] ETHERNET IP") - xm.SendExpectOK(ports[1] + " PS_PACKETHEADER [1] "+ str(hearder2)) - xm.SendExpectOK(ports[1] + " PS_ENABLE [1] on") - xm.SendExpectOK(ports[1] + " PS_RATEFRACTION [1] " + str(int(rate)*10000)) - - print("Start the traffic...") - #####START TRAFFIC - xm.SendExpectOK(ports[0] + ' P_TRAFFIC ON') - xm.SendExpectOK(ports[1] + ' P_TRAFFIC ON') - time.sleep(2) - xm.SendExpectOK(ports[0] + ' P_TRAFFIC OFF') - xm.SendExpectOK(ports[1] + ' P_TRAFFIC OFF') - xm.SendExpectOK(ports[0] + ' PT_CLEAR') - xm.SendExpectOK(ports[1] + ' PT_CLEAR') - xm.SendExpectOK(ports[0] + ' PR_CLEAR') - xm.SendExpectOK(ports[1] + ' PR_CLEAR') - time.sleep(1) - - xm.SendExpectOK(ports[0] + ' P_TRAFFIC ON') - xm.SendExpectOK(ports[1] + ' P_TRAFFIC ON') - time.sleep(int(duration)) - xm.SendExpectOK(ports[0] + ' P_TRAFFIC OFF') - xm.SendExpectOK(ports[1] + ' P_TRAFFIC OFF') - print("Stop the traffic and collect the result...") - xm.Send(ports[0] + ' P_RESERVATION RELEASE') - xm.Send(ports[1] + ' P_RESERVATION RELEASE') - time.sleep(2) - - ####Get traffic result - ##Get the TX and RX result - TX1 = (filter(xm, ports[0] + ' PT_STREAM [0] ?'))[3] - TX2 = (filter(xm, ports[1] + ' PT_STREAM [1] ?'))[3] - RX1 = (filter(xm, ports[1] + ' PR_TPLDTRAFFIC [0] ?'))[3] - RX2 = (filter(xm, ports[0] + ' PR_TPLDTRAFFIC [1] ?'))[3] - print('TX1: %s, TX2: %s, RX1: %s, RX2: %s,'%(TX1, TX2, RX1, RX2)) - - ##Get the latency - latency1 = (filter(xm, ports[1] + ' PR_TPLDLATENCY [0] ?'))[1] - latency2 = (filter(xm, ports[0] + ' PR_TPLDLATENCY [1] ?'))[1] - - ##Get the error - error1 = filter(xm, ports[1] + ' PR_TPLDERRORS[1] ?') - error2 = filter(xm, ports[0] + ' PR_TPLDERRORS[0] ?') - - ##Get the FCS - FCS1 = (filter(xm, ports[0] + ' PR_EXTRA ?'))[0] - FCS2 = (filter(xm, ports[1] + ' PR_EXTRA ?'))[0] - - ##Caculate the lost - Lost1 = int(TX1) - int(RX1) - Lost2 = int(TX2) - int(RX2) - - ##print the result - print() - print ('----------------------------------------------------------------------------------------------------') - print ('Stream1 | TX: ' + str(TX1) + ' | RX: ' + str(RX1) + ' | Lost :' + str(Lost1) + ' | FCS: ' + str(FCS2) + ' | Misoder Error: ' + error1[2] + ' | Payload Errors: ' + error1[3]) - print ('----------------------------------------------------------------------------------------------------') - print ('Stream2 | TX: ' + str(TX2) + ' | RX: ' + str(RX2) + ' | Lost :' + str(Lost2) + ' | FCS: ' + str(FCS1) + ' | Misoder Error: ' + error2[2] + ' | Payload Errors: ' + error2[3]) - print ('----------------------------------------------------------------------------------------------------') - print ('Ending.......') - - -def filter(xm, cmd): - getvalue = xm.Send(cmd) - getvalue1 = getvalue.split(' ')[-1] - getvalue2 = getvalue1.split(' ') - return getvalue2 - -def main(argv): - with open('config.txt','r+') as f: - configs = f.readlines() - config_dict = {} - for conf in configs: - parsed = conf.strip('\n').split(':') - if len(parsed) > 1: - config_dict[parsed[0]] = parsed[1] - - ip_address = config_dict.get('ip_address') - print(ip_address) - ports = config_dict.get('ports').split(' ') - print(ports) - rate = config_dict.get('rate') - size = config_dict.get('size') - duration = config_dict.get('duration') - xm = XenaScriptTools(ip_address) - print('Start to connect to the chassis...') - xm.LogonSetOwner("xena", "python_test_1") - print('Logon successful...') - runtest(xm, ports, rate, size, duration) - - -if __name__ == '__main__': - sys.exit(main(sys.argv)) \ No newline at end of file diff --git a/docs/source/code_example/cli_conversion/config.txt b/docs/source/code_example/cli_conversion/config.txt deleted file mode 100644 index c5e13a88..00000000 --- a/docs/source/code_example/cli_conversion/config.txt +++ /dev/null @@ -1,5 +0,0 @@ -ip_address:192.168.1.198 -ports:2/4 2/5 -rate:100 -size:FIXED 64 1518 -duration:10 \ No newline at end of file diff --git a/docs/source/code_example/cli_conversion/xoa_script.py b/docs/source/code_example/cli_conversion/xoa_script.py deleted file mode 100644 index 738d9794..00000000 --- a/docs/source/code_example/cli_conversion/xoa_script.py +++ /dev/null @@ -1,210 +0,0 @@ -import asyncio -import socket -import typing -import dataclasses -from binascii import hexlify -from xoa_driver import testers -from xoa_driver import ports -from xoa_driver import utils -from xoa_driver import enums - -class ResultError(typing.NamedTuple): - dummy: int - non_incre_seq_event_count: int - swapped_seq_misorder_event_count: int - non_incre_payload_packet_count: int - -class Results(typing.NamedTuple): - tx: int - rx: int - latency: int - error: ResultError - fcs: int - - @classmethod - def from_data(cls, data): - tx, rx, latency, error, fcs = data - return cls( - tx.packet_count_since_cleared, - rx.packet_count_since_cleared, - latency.avg_val, - ResultError(*dataclasses.astuple(error)), - fcs.fcs_error_count - ) - -async def prepare_port(port: "ports.GenericL23Port") -> None: - if port.is_reserved_by_me(): - await port.reservation.set_release() - elif not port.is_released(): - await port.reservation.set_relinquish() - await utils.apply( - port.reservation.set_reserve(), - port.reset.set() - ) - -class PortInfo(typing.NamedTuple): - module_id: int - port_id: int - - def __repr__(self): - return f"{self.module_id}/{self.port_id}" - -class PacketLength(typing.NamedTuple): - length_type: enums.LengthType - min_val: int - max_val: int - - @classmethod - def from_string(cls, data: str): - length_type, min_val, max_val = data.split() - return cls( - enums.LengthType[length_type], - int(min_val), - int(max_val) - ) - -class Config(typing.NamedTuple): - ip_address: str - ports: typing.List[PortInfo] - rate: int - size: PacketLength - duration: int - -def read_config(path: str) -> "Config": - config_dict = {} - with open(path,'r+') as f: - for conf in f: - parsed = conf.strip('\n').split(':') - if len(parsed) <= 1: - continue - config_dict[parsed[0]] = parsed[1] - return Config( - ip_address=config_dict["ip_address"], - ports=[ - PortInfo(*map(int, port.split('/'))) - for port in config_dict['ports'].split(' ') - ], - rate=int(config_dict["rate"]), - size=PacketLength.from_string(config_dict["size"]), - duration=int(config_dict["duration"]) - ) - -async def set_stream(port: "ports.GenericL23Port", size: tuple, header: str, rate: int) -> None: - stream = await port.streams.create() # Create one stream at the port - header_protocol = [ enums.ProtocolOption.ETHERNET, enums.ProtocolOption.IP] - await utils.apply( - stream.tpld_id.set(0), # Create the TPLD index of stream - stream.packet.length.set(*size), # Configure the packet size - stream.packet.header.protocol.set(header_protocol), # Configure the packet type - stream.packet.header.data.set(header), # Configure the packet header - stream.enable.set_on(), # Enable streams - stream.rate.fraction.set(rate*10000) # Configure the stream rate - ) - -async def clear_statistics(port: "ports.GenericL23Port") -> None: - await utils.apply( - port.statistics.tx.clear.set(), - port.statistics.rx.clear.set() - ) - -async def start_traffic(ports: typing.List["ports.GenericL23Port"]) -> None: - await utils.apply(*[p.traffic.state.set_start() for p in ports]) - -async def stop_traffic(ports: typing.List["ports.GenericL23Port"]) -> None: - await utils.apply(*[p.traffic.state.set_stop() for p in ports]) - - -async def fetch_result(port: "ports.GenericL23Port") -> "Results": - stream = port.streams.obtain(0) # Retrieve stream which we created for port - tpld = port.statistics.rx.access_tpld(0) # before was port.reception_statistics.access_tpld(0) - return Results.from_data( - await utils.apply( - port.statistics.tx.obtain_from_stream(stream).get(), - tpld.traffic.get(), - tpld.latency.get(), - tpld.errors.get(), - port.statistics.rx.extra.get() - ) - ) - - -async def run_test(test_ports: typing.List["ports.GenericL23Port"], config: "Config") -> None: - print("Start the scripting...") - - print ("Reserve the port...") - await asyncio.gather(*[ prepare_port(p) for p in test_ports ]) - await asyncio.sleep(3) - - MAC1= '000000000002' - MAC2= '000000000001' - IP1 = '192.168.100.100' - IP2 = '192.168.100.101' - IP1 = hexlify(socket.inet_aton(IP1)).decode() - IP2 = hexlify(socket.inet_aton(IP2)).decode() - header1 = f'0x{MAC2}{MAC1}08004500002E000000007FFFF0B6{IP1}{IP2}' - header2 = f'0x{MAC1}{MAC2}08004500002E000000007FFFF0B6{IP2}{IP1}' - - print("Start to configure the streams...") - await asyncio.gather( - set_stream(test_ports[0], config.size, header1, config.rate), - set_stream(test_ports[1], config.size, header2, config.rate) - ) - - print("Start the traffic...") - await start_traffic(test_ports) - await asyncio.sleep(2) - - await stop_traffic(test_ports) - await asyncio.gather(*[clear_statistics(p) for p in test_ports]) # Sort of clear ports in parallel - await asyncio.sleep(1) - - await start_traffic(test_ports) - await asyncio.sleep(config.duration) - - await stop_traffic(test_ports) - await utils.apply(*[p.reservation.set_release() for p in test_ports]) - - await asyncio.sleep(2) - - ports_results = list(await asyncio.gather(*[ fetch_result(p) for p in test_ports ])) - TX1 = ports_results[0].tx - TX2 = ports_results[1].tx - RX1 = ports_results[1].rx - RX2 = ports_results[0].rx - - print('TX1: %s, TX2: %s, RX1: %s, RX2: %s,'%(TX1, TX2, RX1, RX2)) - - Lost1 = TX1 - RX1 - Lost2 = TX2 - RX2 - - output = ( - "----------------------------------------------------------------------------------------------------", - f"Stream1 | TX: {TX1} | RX: {RX1} | Lost : {Lost1} | FCS: {ports_results[1].fcs} | Misoder Error: { ports_results[1].error.swapped_seq_misorder_event_count} | Payload Errors: {ports_results[1].error.non_incre_payload_packet_count}", - "----------------------------------------------------------------------------------------------------", - f"Stream2 | TX: {TX2} | RX: {RX2} | Lost : {Lost2} | FCS: {ports_results[0].fcs} | Misoder Error: { ports_results[0].error.swapped_seq_misorder_event_count} | Payload Errors: {ports_results[0].error.non_incre_payload_packet_count}", - "----------------------------------------------------------------------------------------------------", - "Ending......." - ) - print("\n".join(output)) - - - -async def start() -> None: - config = read_config("./config.txt") - print(config.ip_address) - print(config.ports) - print('Start to connect to the chassis...') - async with testers.L23Tester(config.ip_address, "python_test_1", debug=True) as tester: - test_ports = [ tester.modules.obtain(p.module_id).ports.obtain(p.port_id) for p in config.ports ] - if any(isinstance(p, ports.PortChimera) for p in test_ports): - raise ValueError("Please select other port. Chimera Ports can't be used in this test.") - await run_test(test_ports, config) # type: ignore - -def main(): - try: - asyncio.run(start()) - except KeyboardInterrupt: - pass - -if __name__ == "__main__": - main() \ No newline at end of file diff --git a/docs/source/code_example/cli_integration.rst b/docs/source/code_example/cli_integration.rst deleted file mode 100644 index 16a7b5ad..00000000 --- a/docs/source/code_example/cli_integration.rst +++ /dev/null @@ -1,8 +0,0 @@ -Integration with CLI -=================================== - -The XOA Python API seamlessly integrates with the XOA CLI, enabling users to work with CLI commands effortlessly within their Python scripts. - -.. literalinclude:: cli_integration/xoa_script.py - :caption: Integration with CLI - diff --git a/docs/source/code_example/cli_integration/xoa_script.py b/docs/source/code_example/cli_integration/xoa_script.py deleted file mode 100644 index 1d4de3eb..00000000 --- a/docs/source/code_example/cli_integration/xoa_script.py +++ /dev/null @@ -1,76 +0,0 @@ -import asyncio - -from xoa_driver import testers -from xoa_driver import modules -from xoa_driver import ports -from xoa_driver import enums -from xoa_driver import utils -from xoa_driver.hlfuncs import mgmt, cli - -async def my_awesome_func(stop_event: asyncio.Event): - # create tester instance and establish connection - async with testers.L23Tester("10.10.10.10", "xoa") as tester: - - # access module 0 on the tester - module = tester.modules.obtain(0) - if isinstance(module, modules.ModuleChimera): - return None - - # access port 0 on the module - port = module.ports.obtain(0) - - # reserve the port - await mgmt.reserve_port(port=port) - - # configure port with .xpc file generated by ValkyrieManager - await cli.port_config_from_file(port=port, path="port_config.xpc") - - # configure port with CLI commands - await cli.port_config_from_string( - port=port, - long_str=""" - P_RESET - P_COMMENT \"this is a comment\" - P_MACADDRESS 0xAAAAAABBBB99 - P_IPADDRESS 1.1.1.1 0.0.0.0 0.0.0.0 0.0.0.0 - """) - - # reserve the module - await mgmt.reserve_module(module=module) - - # configure module by file - await cli.module_config_from_file(module=module, path="module_config.txt") - - # configure module with CLI commands - await cli.module_config_from_string( - module=module, - long_str=""" - M_COMMENT \"this is a comment\" - M_MEDIA QSFP_DD_NRZ - M_CFPCONFIGEXT 2 100000 100000 - """) - - # reserve the tester - await mgmt.reserve_tester(tester=tester) - - # configure module by file - await cli.tester_config_from_file(tester=tester, path="tester_config.txt") - - # configure module with CLI commands - await cli.tester_config_from_string( - tester=tester, - long_str=""" - C_COMMENT \"this is a comment\" - C_NAME \"this is a name\" - """) - -async def main(): - stop_event = asyncio.Event() - try: - await my_awesome_func(stop_event) - except KeyboardInterrupt: - stop_event.set() - - -if __name__ == "__main__": - asyncio.run(main()) \ No newline at end of file diff --git a/docs/source/code_example/hlapiv1.rst b/docs/source/code_example/hlapiv1.rst deleted file mode 100644 index 6e521f54..00000000 --- a/docs/source/code_example/hlapiv1.rst +++ /dev/null @@ -1,200 +0,0 @@ -High-Level API -=================================== - -.. note:: - - For more examples, please go to `XOA Scripting Library `_. - -The boilerplate code that is used to run the examples in this section: - -.. literalinclude:: boilerplate.py - :language: python - - -Testers --------------------------------- - -To connect to a tester, create a tester object and the driver will automatically handle the connection. Each tester class is represented as an `awaitable object `_. When awaited, it establishes a TCP connection to the tester. - -A tester instance also can be created without awaiting the connection establishment for more flexible manipulation of instances in user code. - -Available tester types are `L23Tester`, `L23VeTester`, `L47Tester`, and `L47VeTester`. - -.. literalinclude:: hlapiv1/01_create_tester_from_type.py - :language: python - :caption: Create tester instance - - -You can also create a tester instance using Python Context Manager - -.. seealso:: - - Read more about `Python Context Manager `_ - - -.. literalinclude:: hlapiv1/02_create_tester_context.py - :language: python - :caption: Create tester instance using Python Context Manager - - -To create multiple tester instances, you can do: - -.. literalinclude:: hlapiv1/03_create_multi_testers.py - :caption: Create multiple tester instances - :language: python - -.. seealso:: - - `Learn more about await asyncio.gather `_. - - -Module & Port -------------- - -Access Module -^^^^^^^^^^^^^ - -The examples below help you gain access to a test module on a tester. - -.. literalinclude:: hlapiv1/04_obtain_one_module.py - :caption: Access a single module on a tester - :language: python - - -The examples below help you gain access to several test modules on a tester. - -.. literalinclude:: hlapiv1/05_obtain_multiple_modules.py - :caption: Access multiple modules on a tester - :language: python - - -The examples below help you gain access to several test modules on a tester. - -.. literalinclude:: hlapiv1/06_obtain_all_modules.py - :caption: Access all modules on a tester - :language: python - - -Access Port -^^^^^^^^^^^ - -The examples below help you gain access to a test port on a module. - -.. literalinclude:: hlapiv1/07_obtain_one_port.py - :caption: Access a single port on a module - :language: python - - -The examples below help you gain access to several test ports on a module. - -The interface of obtaining multiple ports is equivalent to obtaining multiple modules with the following exceptions: - -* All ports are of the same type -* All ports are aligned from index ``0`` to ``max_port_count-1`` - -.. literalinclude:: hlapiv1/08_obtain_multiple_ports.py - :caption: Access multiple ports on a module - :language: python - - -The examples below help you gain access to all test ports on a module. - -.. literalinclude:: hlapiv1/09_obtain_all_ports.py - :caption: Access all ports on a module - :language: python - - -Read Module and Port -^^^^^^^^^^^^^^^^^^^^ - -.. note:: - - Resource reservation is not required to query information from the tester. - -.. literalinclude:: hlapiv1/10_query_parameters.py - :caption: Query module and port - :language: python - - -Write Module and Port -^^^^^^^^^^^^^^^^^^^^^ - -.. note:: - - Reservation is required to do ``set`` to: `Testers`, `Modules`, and `Ports`. - -.. literalinclude:: hlapiv1/11_setting_parameters.py - :caption: Configure module and port - :language: python - - -Streams --------------------------------- - -To generate L23 stateless traffic, stream configuration is necessary. The example below shows how to create/delete streams on a L23 port. - -.. note:: - - Reservation is required to do :terms: `CRUD`` operations streams on `Ports`. - -.. literalinclude:: hlapiv1/12_streams.py - :caption: Configure streams on a port - :language: python - - -Modifiers --------------------------------- - -To simulate traffic from many address, or when you want certain fields of a packet to change dynamically on a per packet basis, you can use modifiers. A modifier changes the field value per packet based on how you configure it. The example below shows how to create/delete modifiers on a stream. - -.. note:: - - Port reservation is required to create modifiers on streams. - -.. note:: - - The mechanism of creating and deleting modifiers is different from streams. In order to change the modifiers on a stream packet header, you need to re-configure all the modifiers again. An abstraction will be added to the HL Python API to provide users with the same API syntax, i.e. ``create()``. ``delete()``, and ``remove()`` in a future release of XOA Python API. - -.. note:: - - An easy way to configure the packet header content will be added to the HL Python API in a future release. - - -.. literalinclude:: hlapiv1/13_modifiers.py - :caption: Create and delete modifiers on a stream - :language: python - - -Traffic & Statistics ------------------------------------------- - -Statistics collection, such as latency and jitter, TX/RX rate, frame count, etc., should be done by Python standard library ``asyncio``. In case you are new to ``asyncio``, the example below may help you understand how to use ``asyncio`` to query counters. - -To show how to query statistics on-the-fly, the function ``my_awesome_func`` is slightly modified. - -.. literalinclude:: hlapiv1/14_traffic_stats.py - :caption: Traffic and statistics - :language: python - - -Transceiver --------------------------------------------- - -The example demonstrates how to read/write transceiver register of different types in different ways, as well as reading transceiver temperature. - -.. literalinclude:: hlapiv1/16_transceiver_reg.py - :caption: Read/write transceiver values - :language: python - - -Impairment (Chimera) ------------------------------------------------------ - -.. note:: - - Only applicable to a Chimera module. This is not meant to generate any traffic. - - -.. literalinclude:: hlapiv1/15_traffic_impairment.py - :caption: Traffic drop and latency/jitter impairment - :language: python \ No newline at end of file diff --git a/docs/source/code_example/hlapiv1/01_create_tester_from_type.py b/docs/source/code_example/hlapiv1/01_create_tester_from_type.py deleted file mode 100644 index 28a34a75..00000000 --- a/docs/source/code_example/hlapiv1/01_create_tester_from_type.py +++ /dev/null @@ -1,15 +0,0 @@ -import asyncio -from xoa_driver import testers - -CHASSIS_IP = "demo.xenanetworks.com" -USERNAME = "xoa" - -async def main(): - # create tester instance and establish connection using username "xoa". - my_tester = await testers.L23Tester(CHASSIS_IP, USERNAME) - - # gracefully close connection - await my_tester.session.logoff() - -if __name__ == "__main__": - asyncio.run(main()) \ No newline at end of file diff --git a/docs/source/code_example/hlapiv1/02_create_tester_context.py b/docs/source/code_example/hlapiv1/02_create_tester_context.py deleted file mode 100644 index 1ed9e197..00000000 --- a/docs/source/code_example/hlapiv1/02_create_tester_context.py +++ /dev/null @@ -1,15 +0,0 @@ -import asyncio -from xoa_driver import testers - -CHASSIS_IP = "demo.xenanetworks.com" -USERNAME = "xoa" - -async def main(): - # create tester instance and establish connection - async with testers.L23Tester(CHASSIS_IP, USERNAME) as my_tester: - print(my_tester.session.is_online) - # when leaving this block, the TCP connection will be closed. - - -if __name__ == "__main__": - asyncio.run(main()) \ No newline at end of file diff --git a/docs/source/code_example/hlapiv1/03_create_multi_testers.py b/docs/source/code_example/hlapiv1/03_create_multi_testers.py deleted file mode 100644 index 1cbb12cd..00000000 --- a/docs/source/code_example/hlapiv1/03_create_multi_testers.py +++ /dev/null @@ -1,24 +0,0 @@ -import asyncio -import typing -from xoa_driver import testers - -def create_testers(hosts: typing.List[str], username: str) -> typing.List["testers.GenericAnyTester"]: - return [ testers.L23Tester(host, username) for host in hosts ] - -async def main(): - known_hosts = [ - "192.168.1.200", - "192.168.1.201" - ] - - my_tester_pool = create_testers( known_hosts, "xoa") - # now we can do ``await testers_pool[0]`` which establishes the connection - - # we also can use asyncio.gather for await all testers at once in concurrent mode - await asyncio.gather(*my_tester_pool) - print(my_tester_pool[0].session.is_online) - print(my_tester_pool[0].session.owner_name) - - -if __name__ == "__main__": - asyncio.run(main()) \ No newline at end of file diff --git a/docs/source/code_example/hlapiv1/04_obtain_one_module.py b/docs/source/code_example/hlapiv1/04_obtain_one_module.py deleted file mode 100644 index 4942a157..00000000 --- a/docs/source/code_example/hlapiv1/04_obtain_one_module.py +++ /dev/null @@ -1,21 +0,0 @@ -import asyncio -from xoa_driver import testers -from xoa_driver import modules - -CHASSIS_IP = "demo.xenanetworks.com" -USERNAME = "xoa" -MODULE_ID = 0 - -async def main(): - # create tester instance and establish connection - my_tester = await testers.L23Tester(CHASSIS_IP, USERNAME) - - # get access to instance of module under slot 0 - my_module = my_tester.modules.obtain(MODULE_ID) - - # check if module is of types which we are suspecting - if not isinstance(my_module, modules.ModuleChimera): - print(my_module.info.media_info_list) - -if __name__ == "__main__": - asyncio.run(main()) \ No newline at end of file diff --git a/docs/source/code_example/hlapiv1/05_obtain_multiple_modules.py b/docs/source/code_example/hlapiv1/05_obtain_multiple_modules.py deleted file mode 100644 index 4a50e5a7..00000000 --- a/docs/source/code_example/hlapiv1/05_obtain_multiple_modules.py +++ /dev/null @@ -1,22 +0,0 @@ -import asyncio -from xoa_driver import testers -from xoa_driver import modules - -CHASSIS_IP = "demo.xenanetworks.com" -USERNAME = "xoa" -MODULE_IDS = [0,1] - -async def main(): - # create tester instance and establish connection - my_tester = await testers.L23Tester(CHASSIS_IP, USERNAME) - - # get reference to instance of module under slot 0 and 1 - my_modules = my_tester.modules.obtain_multiple(*MODULE_IDS) - - for module in my_modules: - # check if module is of types which we are suspecting - if not isinstance(module, modules.ModuleChimera): - print(module.info.media_info_list) - -if __name__ == "__main__": - asyncio.run(main()) \ No newline at end of file diff --git a/docs/source/code_example/hlapiv1/06_obtain_all_modules.py b/docs/source/code_example/hlapiv1/06_obtain_all_modules.py deleted file mode 100644 index 8e1826f5..00000000 --- a/docs/source/code_example/hlapiv1/06_obtain_all_modules.py +++ /dev/null @@ -1,20 +0,0 @@ -import asyncio -from xoa_driver import testers -from xoa_driver import modules - -CHASSIS_IP = "demo.xenanetworks.com" -USERNAME = "xoa" - -async def main(): - # create tester instance and establish connection - my_tester = await testers.L23Tester(CHASSIS_IP, USERNAME) - - for module in my_tester.modules: - # check if module is of types which we are suspecting - if not isinstance(module, modules.ModuleChimera): - print(module.info.media_info_list) - else: - print("Is chimera module") - -if __name__ == "__main__": - asyncio.run(main()) \ No newline at end of file diff --git a/docs/source/code_example/hlapiv1/07_obtain_one_port.py b/docs/source/code_example/hlapiv1/07_obtain_one_port.py deleted file mode 100644 index 7c5f3a70..00000000 --- a/docs/source/code_example/hlapiv1/07_obtain_one_port.py +++ /dev/null @@ -1,25 +0,0 @@ -import asyncio - -from xoa_driver import testers -from xoa_driver import modules - -CHASSIS_IP = "demo.xenanetworks.com" -USERNAME = "xoa" -MODULE_ID = 0 -PORT_ID = 0 - -async def main(): - # create tester instance and establish connection - my_tester = await testers.L23Tester(CHASSIS_IP, USERNAME) - my_module = my_tester.modules.obtain(MODULE_ID) - - # check if module is of types which we are suspecting - if not isinstance(my_module, modules.ModuleChimera): - print(my_module.info.media_info_list) - - # get access to instance of port 0 - my_port = my_module.ports.obtain(PORT_ID) - print(my_port.comment.get()) - -if __name__ == "__main__": - asyncio.run(main()) \ No newline at end of file diff --git a/docs/source/code_example/hlapiv1/08_obtain_multiple_ports.py b/docs/source/code_example/hlapiv1/08_obtain_multiple_ports.py deleted file mode 100644 index 83125df8..00000000 --- a/docs/source/code_example/hlapiv1/08_obtain_multiple_ports.py +++ /dev/null @@ -1,20 +0,0 @@ -import asyncio - -from xoa_driver import testers -from xoa_driver import modules - -CHASSIS_IP = "demo.xenanetworks.com" -USERNAME = "xoa" -MODULE_ID = 0 -PORT_IDS =[0,1] - -async def main(): - # create tester instance and establish connection - my_tester = await testers.L23Tester(CHASSIS_IP, USERNAME) - my_module = my_tester.modules.obtain(MODULE_ID) - - # get access to port 0 and 1 - ( tx_port, rx_port ) = resources = my_module.ports.obtain_multiple(*PORT_IDS) - -if __name__ == "__main__": - asyncio.run(main()) \ No newline at end of file diff --git a/docs/source/code_example/hlapiv1/09_obtain_all_ports.py b/docs/source/code_example/hlapiv1/09_obtain_all_ports.py deleted file mode 100644 index aa1ed755..00000000 --- a/docs/source/code_example/hlapiv1/09_obtain_all_ports.py +++ /dev/null @@ -1,23 +0,0 @@ -import asyncio - -from xoa_driver import testers -from xoa_driver import modules, enums - -CHASSIS_IP = "demo.xenanetworks.com" -USERNAME = "xoa" -MODULE_ID = 0 - -async def main(): - # create tester instance and establish connection - my_tester = await testers.L23Tester(CHASSIS_IP, USERNAME) - my_module = my_tester.modules.obtain(MODULE_ID) - - for port in my_module.ports: - # check if module is of types which we are suspecting - if not isinstance(my_module, modules.ModuleChimera): - print(my_module.info.media_info_list) - else: - print(port.comment.get()) - -if __name__ == "__main__": - asyncio.run(main()) \ No newline at end of file diff --git a/docs/source/code_example/hlapiv1/10_query_parameters.py b/docs/source/code_example/hlapiv1/10_query_parameters.py deleted file mode 100644 index 7a6d4988..00000000 --- a/docs/source/code_example/hlapiv1/10_query_parameters.py +++ /dev/null @@ -1,32 +0,0 @@ -import asyncio - -from xoa_driver import testers -from xoa_driver import modules - -CHASSIS_IP = "demo.xenanetworks.com" -USERNAME = "xoa" -MODULE_ID = 0 -PORT_IDS = [0,1] - -async def main(): - # create tester instance and establish connection - my_tester = await testers.L23Tester(CHASSIS_IP, USERNAME) - my_module = my_tester.modules.obtain(MODULE_ID) - - # commands which used in this example are not supported by Chimera Module - if isinstance(my_module, modules.ModuleChimera): - return None - - # Querying module current media configuration - print(await my_module.media.get()) - - ( tx_port, rx_port ) = resources = my_module.ports.obtain_multiple(*PORT_IDS) - - for port in resources: - # Querying port supported speed modes - print(await port.speed.mode.supported.get()) - # Querying port current speed mode - print(await port.speed.mode.selection.get()) - -if __name__ == "__main__": - asyncio.run(main()) \ No newline at end of file diff --git a/docs/source/code_example/hlapiv1/11_setting_parameters.py b/docs/source/code_example/hlapiv1/11_setting_parameters.py deleted file mode 100644 index 434bebfe..00000000 --- a/docs/source/code_example/hlapiv1/11_setting_parameters.py +++ /dev/null @@ -1,50 +0,0 @@ -import asyncio - -from xoa_driver import testers -from xoa_driver import modules -from xoa_driver import utils, enums -from xoa_driver.hlfuncs import mgmt - -CHASSIS_IP = "demo.xenanetworks.com" -USERNAME = "xoa" -MODULE_ID = 0 -PORT_IDS = [0,1] - -async def main(): - # create tester instance and establish connection - my_tester = await testers.L23Tester(CHASSIS_IP, USERNAME) - - # access module 0 on the tester - my_module = my_tester.modules.obtain(MODULE_ID) - - # commands which used in this example are not supported by Chimera Module - if isinstance(my_module, modules.ModuleChimera): - return None - - await mgmt.reserve_module(my_module) - - # set module config - await my_module.media.set(media_config=enums.MediaConfigurationType.QSFP56_PAM4) - - ( tx_port, rx_port ) = resources = my_module.ports.obtain_multiple(*PORT_IDS) - - # use high-level func to reserve the port - for port in resources: - await mgmt.reserve_port(port) - - await utils.apply( - # set latency mode of the Tx port - tx_port.latency_config.mode.set(mode = enums.LatencyMode.LAST2LAST), - # set an comment of the Tx port - tx_port.comment.set("My Tx port") - ) - - await utils.apply( - # set latency mode of the Rx port - rx_port.latency_config.mode.set(mode = enums.LatencyMode.LAST2LAST), - # set an comment of the Rx port - rx_port.comment.set("My Rx port") - ) - -if __name__ == "__main__": - asyncio.run(main()) \ No newline at end of file diff --git a/docs/source/code_example/hlapiv1/12_streams.py b/docs/source/code_example/hlapiv1/12_streams.py deleted file mode 100644 index a4bd28ef..00000000 --- a/docs/source/code_example/hlapiv1/12_streams.py +++ /dev/null @@ -1,80 +0,0 @@ -import asyncio - -from xoa_driver import testers -from xoa_driver import modules -from xoa_driver import utils, enums -from xoa_driver.hlfuncs import mgmt - -CHASSIS_IP = "demo.xenanetworks.com" -USERNAME = "xoa" -MODULE_ID = 0 -PORT_ID = 0 - -DESTINATION_MAC = "AAAAAAAAAAAA" -SOURCE_MAC = "BBBBBBBBBBBB" -ETHERNET_TYPE = "8100" -VLAN = "0000FFFF" - -DESTINATION_MAC2 = "BBBBBBBBBBBB" -SOURCE_MAC2 = "AAAAAAAAAAAA" -ETHERNET_TYPE2 = "8100" -VLAN2 = "0010FFFF" - -async def main(): - # create tester instance and establish connection - my_tester = await testers.L23Tester(CHASSIS_IP, USERNAME) - - # access module 0 on the tester - my_module = my_tester.modules.obtain(MODULE_ID) - - # commands which used in this example are not supported by Chimera Module - if isinstance(my_module, modules.ModuleChimera): - return None - - # access port 0 on the module as the TX port - tx_port = my_module.ports.obtain(PORT_ID) - - # use high-level func to reserve the port - await mgmt.reserve_port(tx_port) - - # reset the port - await mgmt.reset_port(tx_port) - - # create one stream on the port - my_stream1 = await tx_port.streams.create() - # create one stream on the port - my_stream2 = await tx_port.streams.create() - - header_data1 = f'0x{DESTINATION_MAC}{SOURCE_MAC}{ETHERNET_TYPE}{VLAN}' - header_data2 = f'0x{DESTINATION_MAC2}{SOURCE_MAC2}{ETHERNET_TYPE2}{VLAN2}' - - await utils.apply( - # Create the TPLD index of stream - my_stream1.tpld_id.set(0), - # Configure the packet size - my_stream1.packet.length.set(length_type=enums.LengthType.FIXED, min_val=1000, max_val=1000), - # Enable streams - my_stream1.enable.set_on(), - # Configure the stream rate - my_stream1.rate.fraction.set(stream_rate_ppm=500000), - # Configure the stream packet header protocol - my_stream1.packet.header.protocol.set(segments=[enums.ProtocolOption.ETHERNET, enums.ProtocolOption.VLAN]), - # Configure the stream packet header value - my_stream1.packet.header.data.set(hex_data=header_data1), - - # Configure TPLD ID - my_stream2.tpld_id.set(1), - # Configure the packet size - my_stream2.packet.length.set(length_type=enums.LengthType.INCREMENTING, min_val=100, max_val=1000), - # Enable streams - my_stream2.enable.set_on(), - # Configure the stream rate - my_stream2.rate.fraction.set(stream_rate_ppm=500000), - # Configure the stream packet header protocol - my_stream2.packet.header.protocol.set(segments=[enums.ProtocolOption.ETHERNET, enums.ProtocolOption.VLAN]), - # Configure the stream packet header value - my_stream2.packet.header.data.set(hex_data=header_data2) - ) - -if __name__ == "__main__": - asyncio.run(main()) \ No newline at end of file diff --git a/docs/source/code_example/hlapiv1/13_modifiers.py b/docs/source/code_example/hlapiv1/13_modifiers.py deleted file mode 100644 index b26fc475..00000000 --- a/docs/source/code_example/hlapiv1/13_modifiers.py +++ /dev/null @@ -1,91 +0,0 @@ -import asyncio - -from xoa_driver import testers -from xoa_driver import modules -from xoa_driver import utils, enums -from xoa_driver.hlfuncs import mgmt - -CHASSIS_IP = "demo.xenanetworks.com" -USERNAME = "xoa" -MODULE_ID = 0 -PORT_ID = 0 - -SMAC = '000000000001' -DMAC = '000000000002' -ETHERTYPE = '0800' - -async def main(): - # create tester instance and establish connection - my_tester = await testers.L23Tester(CHASSIS_IP, USERNAME) - - # access module 0 on the tester - my_module = my_tester.modules.obtain(MODULE_ID) - - if isinstance(my_module, modules.ModuleChimera): - return None # commands which used in this example are not supported by Chimera Module - - # access port 0 on the module as the TX port - tx_port = my_module.ports.obtain(PORT_ID) - - # use high-level func to reserve the port - await mgmt.reserve_port(tx_port) - - # reset the port - await tx_port.reset.set() - - # create one stream on the port - my_stream = await tx_port.streams.create() - - header_data = f'0x{DMAC}{SMAC}{ETHERTYPE}' - - await utils.apply( - # Create the TPLD index of stream - my_stream.tpld_id.set(0), - # Configure the packet size - my_stream.packet.length.set(length_type=enums.LengthType.FIXED, min_val=1000, max_val=1000), - # Enable stream - my_stream.enable.set_on(), - # Configure the stream rate - my_stream.rate.fraction.set(stream_rate_ppm=500000), - - # Configure the packet type - my_stream.packet.header.protocol.set(segments=[enums.ProtocolOption.ETHERNET, enums.ProtocolOption.IP]), - # Configure the packet header data - my_stream.packet.header.data.set(hex_data = header_data) - ) - - # create one modifier and configure - await my_stream.packet.header.modifiers.configure(1) - # access the created modifier - my_modifier = my_stream.packet.header.modifiers.obtain(0) - # configure the modifier - # place the modifier on header position 0 - await my_modifier.specification.set(position=0, mask="0xFFFF", action=enums.ModifierAction.INC, repetition=1) - await my_modifier.range.set(min_val=0, step=1, max_val=65535) - - # to create another modifier, you need to re-configure all modifiers again - await my_stream.packet.header.modifiers.configure(2) - - my_modifier = my_stream.packet.header.modifiers.obtain(0) - # place the first modifier on header position 0 - await my_modifier.specification.set(position=0, mask="0xFFFF", action=enums.ModifierAction.INC, repetition=1) - await my_modifier.range.set(min_val=0, step=1, max_val=65535) - - my_modifier_2 = my_stream.packet.header.modifiers.obtain(1) - # place the second modifier on header position 6 - await my_modifier_2.specification.set(position=6, mask="0xFFFF", action=enums.ModifierAction.INC, repetition=1) - await my_modifier_2.range.set(min_val=0, step=1, max_val=65535) - - # to delete the first modifier, you need to re-configure all modifiers again - await my_stream.packet.header.modifiers.configure(1) - - my_modifier = my_stream.packet.header.modifiers.obtain(0) - # place the modifier on header position 0 - await my_modifier.specification.set(position=6, mask="0xFFFF", action=enums.ModifierAction.INC, repetition=1) - await my_modifier.range.set(min_val=0, step=1, max_val=65535) - - # to delete all modifiers - await my_stream.packet.header.modifiers.configure(0) - -if __name__ == "__main__": - asyncio.run(main()) \ No newline at end of file diff --git a/docs/source/code_example/hlapiv1/14_traffic_stats.py b/docs/source/code_example/hlapiv1/14_traffic_stats.py deleted file mode 100644 index 3c09ac3c..00000000 --- a/docs/source/code_example/hlapiv1/14_traffic_stats.py +++ /dev/null @@ -1,156 +0,0 @@ -import asyncio -from xoa_driver import testers -from xoa_driver import modules -from xoa_driver.enums import * -from xoa_driver.hlfuncs import mgmt - -CHASSIS_IP = "demo.xenanetworks.com" -USERNAME = "xoa" -MODULE_ID = 0 -PORT1_ID = 1 -PORT2_ID = 3 - -TRAFFIC_DURATION = 180 # Three minutes - -DESTINATION_MAC = "AAAAAAAAAAAA" -SOURCE_MAC = "BBBBBBBBBBBB" -ETHERNET_TYPE = "8100" -VLAN = "0000FFFF" - -DESTINATION_MAC2 = "BBBBBBBBBBBB" -SOURCE_MAC2 = "AAAAAAAAAAAA" -ETHERNET_TYPE2 = "8100" -VLAN2 = "0010FFFF" - -async def main(): - # create tester instance and establish connection - print(f"Connecting to chassis: {CHASSIS_IP}, username: {USERNAME}") - my_tester = await testers.L23Tester(CHASSIS_IP, USERNAME) - - - my_module = my_tester.modules.obtain(MODULE_ID) - - # commands which used in this example are not supported by Chimera Module - if isinstance(my_module, modules.ModuleChimera): - return None - - ( port1, port2 ) = resources = my_module.ports.obtain_multiple(PORT1_ID, PORT2_ID) - - print(f"Reserve and reset port {MODULE_ID}/{PORT1_ID}") - print(f"Reserve and reset port {MODULE_ID}/{PORT2_ID}") - for port in resources: - await mgmt.reserve_port(port) - await mgmt.reset_port(port) - - - # Create one stream on the port - print(f"Creating a stream on port {MODULE_ID}/{PORT1_ID}") - my_stream1 = await port1.streams.create() - # Create one stream on the port - print(f"Creating a stream on port {MODULE_ID}/{PORT2_ID}") - my_stream2 = await port2.streams.create() - - - print(f"Configuring streams..") - - header_data1 = f'0x{DESTINATION_MAC}{SOURCE_MAC}{ETHERNET_TYPE}{VLAN}' - header_data2 = f'0x{DESTINATION_MAC2}{SOURCE_MAC2}{ETHERNET_TYPE2}{VLAN2}' - - await asyncio.gather( - # Create the TPLD index of stream - my_stream1.tpld_id.set(0), - # Configure the packet size - my_stream1.packet.length.set(length_type=LengthType.FIXED, min_val=1000, max_val=1000), - my_stream1.packet.header.protocol.set(segments=[ - ProtocolOption.ETHERNET, - ProtocolOption.VLAN - ]), - # Enable streams - my_stream1.enable.set_on(), - # Configure the stream rate - # my_stream1.rate.fraction.set(stream_rate_ppm=100000), - # my_stream1.rate.l2bps.set(l2_bps=1e9), - my_stream1.rate.pps.set(stream_rate_pps=1000), - # my_stream.packet.limit.set(packet_count=10000), - my_stream1.packet.header.data.set(hex_data=header_data1), - - my_stream2.tpld_id.set(1), - # Configure the packet size - my_stream2.packet.length.set(length_type=LengthType.INCREMENTING, min_val=100, max_val=1000), - my_stream2.packet.header.protocol.set(segments=[ - ProtocolOption.ETHERNET, - ProtocolOption.VLAN - ]), - # Enable streams - my_stream2.enable.set_on(), - # Configure the stream rate - # my_stream2.rate.fraction.set(stream_rate_ppm=100000), - # my_stream2.rate.l2bps.set(l2_bps=1e9), - my_stream2.rate.pps.set(stream_rate_pps=1000), - # my_stream2.packet.limit.set(packet_count=10000), - my_stream2.packet.header.data.set(hex_data=header_data2), - ) - - # clear port statistics - print(f"Clearing statistics") - await asyncio.gather( - port1.statistics.tx.clear.set(), - port1.statistics.rx.clear.set(), - port2.statistics.tx.clear.set(), - port2.statistics.rx.clear.set() - ) - - # start traffic on the ports - print(f"Starting traffic") - await asyncio.gather( - port1.traffic.state.set_start(), - port2.traffic.state.set_start() - ) - - # # let traffic runs for 10 seconds - print(f"Wait for {TRAFFIC_DURATION} seconds...") - await asyncio.sleep(TRAFFIC_DURATION) - - # # stop traffic on the Tx port - print(f"Stopping traffic..") - await asyncio.gather( - port1.traffic.state.set_stop(), - port2.traffic.state.set_stop() - ) - await asyncio.sleep(2) - - # collect statistics - print(f"Collecting statistics..") - - (p1_tx, p1_rx, p2_tx, p2_rx) = await asyncio.gather( - port1.statistics.tx.obtain_from_stream(0).get(), - port1.statistics.rx.access_tpld(1).traffic.get(), - port2.statistics.tx.obtain_from_stream(0).get(), - port2.statistics.rx.access_tpld(0).traffic.get(), - ) - print(f"Port 1") - print(f" TX(tid=0).Byte_Count: {p1_tx.byte_count_since_cleared}") - print(f" TX(tid=0).Packet_Count: {p1_tx.packet_count_since_cleared}") - print(f" RX(tid=1).Byte_Count: {p1_rx.byte_count_since_cleared}") - print(f" RX(tid=1).Packet_Count: {p1_rx.packet_count_since_cleared}") - - print(f"Port 2") - print(f" TX(tid=1).Byte_Count: {p2_tx.byte_count_since_cleared}") - print(f" TX(tid=1).Packet_Count: {p2_tx.packet_count_since_cleared}") - print(f" RX(tid=0).Byte_Count: {p2_rx.byte_count_since_cleared}") - print(f" RX(tid=0).Packet_Count: {p2_rx.packet_count_since_cleared}") - - print(f"Frame Loss (TX-RX)") - print(f" Port 1->Port 2 (tid=0): {p1_tx.packet_count_since_cleared - p2_rx.packet_count_since_cleared}") - print(f" Port 2->Port 1 (tid=1): {p2_tx.packet_count_since_cleared - p1_rx.packet_count_since_cleared}") - - # free ports - print(f"Free ports") - for port in resources: - await mgmt.free_port(port) - - # done - print(f"Test done") - -if __name__ == "__main__": - asyncio.run(main()) \ No newline at end of file diff --git a/docs/source/code_example/hlapiv1/15_traffic_impairment.py b/docs/source/code_example/hlapiv1/15_traffic_impairment.py deleted file mode 100644 index 839e07b5..00000000 --- a/docs/source/code_example/hlapiv1/15_traffic_impairment.py +++ /dev/null @@ -1,119 +0,0 @@ -import asyncio -from xoa_driver import testers -from xoa_driver import modules -from xoa_driver import utils -from xoa_driver import misc -from xoa_driver.enums import * -from xoa_driver.hlfuncs import mgmt - -CHASSIS_IP = "87.61.110.118" -USERNAME = "xoa" -MODULE_ID = 10 -PORT_ID = 0 - -# --------------------------------------------------------------------------------------# -# function name: collect_statistics # -# This function collect Chimera's statistics on-the-fly. # -# # -# --------------------------------------------------------------------------------------# - -async def collect_statistics(flow: misc.ImpairmentFlow, stop_event: asyncio.Event) -> None: - print(f"Start collecting statistics by Chimera...") - count = 0 - while not stop_event.is_set(): - (rx, total_drop) = await utils.apply( - flow.statistics.rx.total.get(), - flow.statistics.total.drop_packets.get() - ) - print(f"{count}\t\t\tChimera total received frames: {rx.packet_count},\t\ttotal dropped: {total_drop.pkt_drop_count_total}") - count+=1 - await asyncio.sleep(1.0) - - -async def my_awesome_func(stop_event: asyncio.Event) -> None: - - # Access to the chassis that has a Chimera module in - async with testers.L23Tester(CHASSIS_IP, USERNAME) as tester: - # Access the module #10 - my_module = tester.modules.obtain(MODULE_ID) - - # Check whether the module is a Chimera module - if not isinstance(my_module, modules.ModuleChimera): - print("Selected not a Chimera module.", "Exiting.") - return None - - # Use port #0 - my_port = my_module.ports.obtain(PORT_ID) - - # use high-level func to reserve the port - await mgmt.reserve_port(my_port) - - # Enable impairment on the port. If you don't do this, the port won't impair the incoming traffic. - await my_port.emulate.set_on() - - # Use Flow #1 on this port. We will define a filter and configure impairment functions on it. - flow_1 = my_port.emulation.flows[1] - - # Initializing the shadow copy of the filter. (If you don't know how Chimera impairment works, please read the Chimera's user manual) - await flow_1.shadow_filter.initiating.set() - # Enable the filter - await flow_1.shadow_filter.enable.set_on() - # Basic mode - await flow_1.shadow_filter.use_basic_mode() - # Description of the flow - await flow_1.comment.set("On VLAN 20") - - # Query the mode of the filter (either basic or extended) - filter = await flow_1.shadow_filter.get_mode() - - # Set up the filter to impair frames with VLAN Tag = 20 (using command grouping) - if isinstance(filter, misc.BasicImpairmentFlowFilter): - await utils.apply( - # filter.ethernet.settings.set(use=FilterUse.OFF, action=InfoAction.INCLUDE), - # filter.ethernet.src_address.set(use=OnOff.OFF, value="0x000000000000", mask="0xFFFFFFFFFFFF"), - # filter.ethernet.dest_address.set(use=OnOff.OFF, value="0x000000000000", mask="0xFFFFFFFFFFFF"), - filter.l2plus_use.set(use=L2PlusPresent.VLAN1), - filter.vlan.settings.set(use=FilterUse.AND, action=InfoAction.INCLUDE), - filter.vlan.inner.tag.set(use=OnOff.ON, value=20, mask="0x0FFF"), - filter.vlan.inner.pcp.set(use=OnOff.OFF, value=0, mask="0x07"), - # filter.vlan.outer.tag.set(use=OnOff.OFF, value=20, mask="0x0FFF"), - # filter.vlan.outer.pcp.set(use=OnOff.OFF, value=0, mask="0x07"), - ) - - # Apply the filter so the configuration data in the shadow copy is committed to the working copy automatically. - await flow_1.shadow_filter.apply.set() - - # Start configuring the impairment for the filter. (using command grouping) - await utils.apply( - # Latency/Jitter impairment (distribution: constant) - flow_1.impairment_distribution.latency_jitter_type_config.constant_delay.set(20000), # 20,000 ns, must be multiples of 100 - flow_1.impairment_distribution.latency_jitter_type_config.schedule.set(1, 0), # continuously increase the latency - - # Drop impairment (distribution: fixed burst) - flow_1.impairment_distribution.drop_type_config.fixed_burst.set(burst_size=5), # drop a fixed burst size 5 frames - flow_1.impairment_distribution.drop_type_config.schedule.set(1, 5), # drop is on for 10ms and pause for 40ms (total=50ms) (100 drops per second) - ) - - await asyncio.sleep(1) - - # start latency & jitter impairment - await flow_1.impairment_distribution.latency_jitter_type_config.enable.set_on() - - # start frame drop impairment - # await flow_1.impairment_distribution.drop_type_config.enable.set(action=OnOff.ON) - - asyncio.create_task(collect_statistics(flow_1, stop_event)) - await stop_event.wait() - await asyncio.sleep(1) - - -async def main(): - stop_event = asyncio.Event() - try: - await my_awesome_func(stop_event) - except KeyboardInterrupt: - stop_event.set() - - -if __name__ == "__main__": - asyncio.run(main()) \ No newline at end of file diff --git a/docs/source/code_example/hlapiv1/16_transceiver_reg.py b/docs/source/code_example/hlapiv1/16_transceiver_reg.py deleted file mode 100644 index 816e4407..00000000 --- a/docs/source/code_example/hlapiv1/16_transceiver_reg.py +++ /dev/null @@ -1,61 +0,0 @@ -import asyncio - -from xoa_driver import testers -from xoa_driver import modules -from xoa_driver.hlfuncs import mgmt - -CHASSIS_IP = "demo.xenanetworks.com" -USERNAME = "xoa" -MODULE_ID = 2 -PORT_ID = 2 - -async def main(): - # Establish connection to a Valkyrie tester - async with testers.L23Tester(CHASSIS_IP, USERNAME) as my_tester: - my_module = my_tester.modules.obtain(MODULE_ID) - - # commands which used in this example are not supported by Chimera Module - if isinstance(my_module, modules.ModuleChimera): - return None - - # Get the port 2/2 (module 2) - my_port = my_module.ports.obtain(PORT_ID) - - # use high-level func to reserve the port - await mgmt.reserve_port(my_port) - - # Reset the port - await my_port.reset.set() - - await asyncio.sleep(10) - - # Read transceiver's temperature - temperature = await my_port.transceiver.access_temperature.get() - print(f"Transceiver temperature: {temperature.integral_part + temperature.fractional_part/256} degrees Celsius.") - - # Read transceiver's register value (single read) - rx_power_lsb = await my_port.transceiver.access_rw(page_address=0xA2, register_address=0x69).get() - print(rx_power_lsb) - - # Write transceiver's register value (single write) - await my_port.transceiver.access_rw(page_address=0xA2, register_address=0x69).set("0xFFFF") - - # Read MII transceiver's register value (single operation) - rx_power_lsb = await my_port.transceiver.access_mii(register_address=0x69).get() - print(rx_power_lsb) - - # Write MII transceiver's register value (single operation) - await my_port.transceiver.access_mii(register_address=0x69).set("0xFFFF") - - # Read transceiver's register value (sequential read) - i2c_read = await my_port.transceiver.access_rw_seq(page_address=0xA2, register_address=0x69, byte_count=16).get() - print(i2c_read) - - # Write transceiver's register value (sequential write) - await my_port.transceiver.access_rw_seq(page_address=0xA2, register_address=0x69, byte_count=16).set("0xFFFF") - - # Release the port - await my_port.reservation.set_release() - -if __name__ == "__main__": - asyncio.run(main()) diff --git a/docs/source/code_example/hlapiv2/traffic_impairment.py b/docs/source/code_example/hlapiv2/traffic_impairment.py deleted file mode 100644 index 8ac65eba..00000000 --- a/docs/source/code_example/hlapiv2/traffic_impairment.py +++ /dev/null @@ -1,164 +0,0 @@ -import asyncio -from contextlib import asynccontextmanager -from typing import AsyncGenerator, Tuple, TypeVar -from xoa_driver.v2 import testers -from xoa_driver.v2 import modules -from xoa_driver.v2 import ports -from xoa_driver import utils -from xoa_driver.v2 import misc -from xoa_driver.enums import * - -# region high-level functions - -# --------------------------------------------------------------------------------------# -# function name: reserve_ports # -# This function takes care of port reservation procedure to simplify the user code. # -# # -# This high-level function will be included in XOA HL Python # -# --------------------------------------------------------------------------------------# -async def reserve_ports(*used_ports: ports.GenericAnyPort) -> None: - async def relinquish(port: ports.GenericAnyPort): - if port.info.reservation is ReservedStatus.RESERVED_BY_OTHER: - await port.reservation.set_relinquish() - while port.info.reservation is not ReservedStatus.RELEASED: - await asyncio.sleep(0.01) - await asyncio.gather(*[ relinquish(port) for port in used_ports ]) - await asyncio.gather( - *[ - utils.apply( - port.reservation.set_reserve(), - port.reset.set() - ) - for port in used_ports - ] - ) - -# --------------------------------------------------------------------------------------# -# function name: release_ports # -# This function resets and releases the ports # -# # -# This high-level function will be included in XOA HL Python # -# --------------------------------------------------------------------------------------# -async def release_ports(*used_ports: ports.GenericAnyPort) -> None: - coros = [ - utils.apply( - port.reset.set(), - port.reservation.set_release(), - ) - for port in used_ports - ] - await asyncio.gather(*coros) - -# endregion - - -# --------------------------------------------------------------------------------------# -# function name: safe_ports_usage # -# This function automatically reserve the ports you want to use, # -# and makes them into clean states after the use. # -# # -# This high-level function will be included in XOA HL Python # -# --------------------------------------------------------------------------------------# -PT = TypeVar("PT", bound=ports.GenericAnyPort) - -@asynccontextmanager -async def safe_ports_usage(*used_ports: PT) -> AsyncGenerator[Tuple[PT, ...], None]: - await reserve_ports(*used_ports) - try: - yield used_ports - finally: - await release_ports(*used_ports) - -async def flow_statistic_fetcher(flow: misc.ImpairmentFlow, stop_event: asyncio.Event) -> None: - print(f"Start collecting statistics by Chimera...") - count = 0 - while not stop_event.is_set(): - (rx, total_drop) = await utils.apply( - flow.statistics.rx.total.get(), - flow.statistics.total.dropped.get() - ) - print(f"{count}\t\t\tChimera total received frames: {rx.packet_count},\t\ttotal dropped: {total_drop.pkt_drop_count_total}") - count+=1 - await asyncio.sleep(1.0) - - -async def impairment_config(stop_event: asyncio.Event) -> None: - - # Access to the chassis that has a Chimera module in - async with testers.L23Tester("192.168.1.201", "xena") as tester: - # Access the module #10 - chimera_module = tester.modules.obtain(0) - - # Check whether the module is a Chimera module - if not isinstance(chimera_module, modules.ModuleChimera): - print("Selected not a Chimera module.", "Exiting.") - return None - - # Auto reserving and cleaning the Chimera ports. - async with safe_ports_usage(*chimera_module.ports) as reserved_chimera_ports: - # Use port #0 - port_0 = reserved_chimera_ports[0] - - # Enable impairment on the port. If you don't do this, the port won't impair the incoming traffic. - await port_0.emulate.set_on() - - # Use Flow #1 on this port. We will define a filter and configure impairment functions on it. - flow_1 = port_0.emulation.flow[1] - - # Initializing the shadow copy of the filter. (If you don't know how Chimera impairment works, please read the Chimera's user manual) - await flow_1.shadow_filter.initiating.set() - # Basic mode - await flow_1.shadow_filter.use_basic_mode() - # Description of the flow - await flow_1.comment.set("On VLAN 20") - - # Query the mode of the filter (either basic or extended) - filter = await flow_1.shadow_filter.get_mode() - - # Set up the filter to impair frames with VLAN Tag = 20 (using command grouping) - if isinstance(filter, misc.BasicImpairmentFlowFilter): - await utils.apply( - filter.ethernet.settings.set(use=FilterUse.OFF, action=InfoAction.INCLUDE), - filter.ethernet.src_address.set(use=OnOff.OFF, value="0x000000000000", mask="0xFFFFFFFFFFFF"), - filter.ethernet.dest_address.set(use=OnOff.OFF, value="0x000000000000", mask="0xFFFFFFFFFFFF"), - filter.l2plus_use.set(use=L2PlusPresent.VLAN1), - filter.vlan.settings.set(use=FilterUse.AND, action=InfoAction.INCLUDE), - filter.vlan.inner.tag.set(use=OnOff.ON, value=20, mask="0x0FFF"), - filter.vlan.inner.pcp.set(use=OnOff.OFF, value=0, mask="0x07"), - filter.vlan.outer.tag.set(use=OnOff.OFF, value=20, mask="0x0FFF"), - filter.vlan.outer.pcp.set(use=OnOff.OFF, value=0, mask="0x07"), - ) - - # Enable the filter - await flow_1.shadow_filter.enable.set_on() - # Apply the filter so the configuration data in the shadow copy is committed to the working copy automatically. - await flow_1.shadow_filter.apply.set() - - # Start configuring the impairment for the filter. (using command grouping) - await utils.apply( - # Latency/Jitter impairment (distribution: constant) - flow_1.latency_jitter.distribution.constant_delay.set(10000), # 10,000 ns, must be multiples of 100 - flow_1.latency_jitter.schedule.set(1, 0), # continuously increase the latency - flow_1.latency_jitter.enable.set_on(), # start this impairment - - # Drop impairment (distribution: fixed burst) - flow_1.drop.distribution.fixed_burst.set(burst_size=5), # drop a fixed burst size 5 frames - flow_1.drop.schedule.set(1, 5), # drop is on for 10ms and pause for 40ms (total=50ms) (100 drops per second) - flow_1.drop.enable.set_on(), # start this impairment - ) - - asyncio.create_task(flow_statistic_fetcher(flow_1, stop_event)) - await stop_event.wait() - await asyncio.sleep(1) - - -async def main(): - stop_event = asyncio.Event() - try: - await impairment_config(stop_event) - except KeyboardInterrupt: - stop_event.set() - - -if __name__ == "__main__": - asyncio.run(main()) \ No newline at end of file diff --git a/docs/source/code_example/index.rst b/docs/source/code_example/index.rst index bbb19153..6bcfe661 100644 --- a/docs/source/code_example/index.rst +++ b/docs/source/code_example/index.rst @@ -1,14 +1,24 @@ Code Examples =================== -.. note:: - - For more examples, please go to `XOA Scripting Library `_. +You can find various code examples in `XOA Scripting Library `_. -.. toctree:: +We recommend you start from `Quick Start `_. Some highlighted examples that you may find helpful: - hlapiv1 - xpc_integration - cli_integration - cli_conversion - llapi \ No newline at end of file +1. `XenaAsyncWrapper `_: The APIs provided by xoa-driver are **async** functions. This means any function that uses the xoa-driver must be declared as **async**. This might be a problem for you if your existing framework doesn't support async functions. To solve this "incompatibility" issue, we have made an async wrapper class **XenaAsyncWrapper** for you to wrap xoa-driver's async function inside and use it as a regular Python function. + +2. `Use XOA Python API to load port configuration file `_ as you do on ValkyrieManager. + +3. `Send CLI via XOA Python API `_ demonstrates how to load ``.xpc`` file or send CLI commands via XOA Python API. + +4. `Low-Level API `_ demonstrates how to use xoa-driver's low-level API if you are familiar with XOA CLI. + +5. `Network Emulation `_ demonstrates how to automate Chimera for network emulation. + +6. `PPM Sweep and ANLT on Thor `_ demonstrates how to change media configuration, perform PPM sweep and AN< on Thor modules. + +7. `IP ARP/NDP Table `_ demonstrates how to generate ARP/NDP table on a port for IP streams. + +8. `Packet Capture `_ demonstrates how to capture packets and read their content. + +**More code examples can be found in** `XOA Scripting Library `_. \ No newline at end of file diff --git a/docs/source/code_example/llapi.rst b/docs/source/code_example/llapi.rst deleted file mode 100644 index 9cd8cf58..00000000 --- a/docs/source/code_example/llapi.rst +++ /dev/null @@ -1,73 +0,0 @@ -Low-Level API -=================================== - -The boilerplate code that is used to run all of the examples. - -.. literalinclude:: boilerplate.py - - -Connect to Tester --------------------------------- - -Each tester class is represented as an `awaitable object `_. When awaited, it establishes a TCP connection to the tester. - -A tester instance also can be created without awaiting the connection establishment for more flexible manipulation of instances in user code. - -.. literalinclude:: llapi/create_conn_to_tester.py - :caption: Create connection to a tester - - -.. literalinclude:: llapi/create_multiple_conns.py - :caption: Create multiple connections to testers - - - -Access Modules --------------------------------- - -The examples below help you gain access to the test modules on a tester. - -.. literalinclude:: llapi/obtain_one_module.py - :caption: Access a single module on a tester - - -.. literalinclude:: llapi/obtain_multiple_modules.py - :caption: Access multiple modules on a tester - - - -Querying & Setting --------------------------------- - -Querying -^^^^^^^^^^^ - -.. note:: - - Resource reservation is not required to query information from the tester. - -.. literalinclude:: llapi/query_parameters.py - :caption: Query port - - -Setting -^^^^^^^^^^^^^ - -.. note:: - - Reservation is required to do ``set`` to: `Testers`, `Modules`, and `Ports`. - -.. literalinclude:: llapi/setting_parameters.py - :caption: Configure port - - -Statistics Collection --------------------------------- - -Statistics collection, such as latency and jitter, TX/RX rate, frame count, etc., can be done by Python standard library ``asyncio``. In case you are new to ``asyncio``, the example below may help you understand how to use ``asyncio`` to query counters. - -.. literalinclude:: llapi/stats_collection.py - :caption: Collect statistics - - - diff --git a/docs/source/code_example/llapi/create_conn_to_tester.py b/docs/source/code_example/llapi/create_conn_to_tester.py deleted file mode 100644 index e5cf3ff6..00000000 --- a/docs/source/code_example/llapi/create_conn_to_tester.py +++ /dev/null @@ -1,26 +0,0 @@ -import asyncio -from xoa_driver import utils -from xoa_driver.lli import commands as cmd -from xoa_driver.lli import TransportationHandler -from xoa_driver.lli import establish_connection - -async def my_awesome_func(): - handler = TransportationHandler(debug=False) - await establish_connection(handler, "192.168.1.198") - await utils.apply( - cmd.C_LOGON(handler).set("xena"), - cmd.C_OWNER(handler).set("xoa"), - ) # establish connection using username "xoa". - - # other code ... - -def main(): - try: - loop = asyncio.get_event_loop() - loop.create_task(my_awesome_func()) - loop.run_forever() - except KeyboardInterrupt: - pass - -if __name__ == "__main__": - main() \ No newline at end of file diff --git a/docs/source/code_example/llapi/create_multiple_conns.py b/docs/source/code_example/llapi/create_multiple_conns.py deleted file mode 100644 index 14214973..00000000 --- a/docs/source/code_example/llapi/create_multiple_conns.py +++ /dev/null @@ -1,39 +0,0 @@ -import asyncio -from xoa_driver import utils -from xoa_driver.lli import commands as cmd -from xoa_driver.lli import TransportationHandler -from xoa_driver.lli import establish_connection - -async def my_awesome_func(): - handler1 = TransportationHandler(debug=False) - await establish_connection(handler1, "192.168.1.198") - - await utils.apply( - cmd.C_LOGON(handler1).set("xena"), - cmd.C_OWNER(handler1).set("xoa"), - ) # establish connection using username "xoa". - - handler2 = TransportationHandler(debug=False) - await establish_connection(handler2, "192.168.1.198") - await utils.apply( - cmd.C_LOGON(handler2).set("xena"), - cmd.C_OWNER(handler2).set("Alice"), - ) # establish connection using username "Alice". - - handler3 = TransportationHandler(debug=False) - await establish_connection(handler3, "192.168.1.198") - await utils.apply( - cmd.C_LOGON(handler3).set("xena"), - cmd.C_OWNER(handler3).set("Bob"), - ) # establish connection using username "Bob". - -def main(): - try: - loop = asyncio.get_event_loop() - loop.create_task(my_awesome_func()) - loop.run_forever() - except KeyboardInterrupt: - pass - -if __name__ == "__main__": - main() \ No newline at end of file diff --git a/docs/source/code_example/llapi/obtain_multiple_modules.py b/docs/source/code_example/llapi/obtain_multiple_modules.py deleted file mode 100644 index 36d3acd6..00000000 --- a/docs/source/code_example/llapi/obtain_multiple_modules.py +++ /dev/null @@ -1,30 +0,0 @@ -import asyncio -from xoa_driver import utils -from xoa_driver.lli import commands as cmd -from xoa_driver.lli import TransportationHandler -from xoa_driver.lli import establish_connection - -async def my_awesome_func(): - handler = TransportationHandler(debug=False) - await establish_connection(handler, "192.168.1.198") - await utils.apply( - cmd.C_LOGON(handler).set("xena"), - cmd.C_OWNER(handler).set("xoa"), - ) # establish connection using username "xoa". - - print(await cmd.M_PORTCOUNT(handler, 0).get()) # get test module 0 port count - print(await cmd.M_PORTCOUNT(handler, 1).get()) # get test module 1 port count - print(await cmd.M_PORTCOUNT(handler, 2).get()) # get test module 2 port count - - # other code ... - -def main(): - try: - loop = asyncio.get_event_loop() - loop.create_task(my_awesome_func()) - loop.run_forever() - except KeyboardInterrupt: - pass - -if __name__ == "__main__": - main() \ No newline at end of file diff --git a/docs/source/code_example/llapi/obtain_one_module.py b/docs/source/code_example/llapi/obtain_one_module.py deleted file mode 100644 index b1eb838d..00000000 --- a/docs/source/code_example/llapi/obtain_one_module.py +++ /dev/null @@ -1,28 +0,0 @@ -import asyncio -from xoa_driver import utils -from xoa_driver.lli import commands as cmd -from xoa_driver.lli import TransportationHandler -from xoa_driver.lli import establish_connection - -async def my_awesome_func(): - handler = TransportationHandler(debug=False) - await establish_connection(handler, "192.168.1.198") - await utils.apply( - cmd.C_LOGON(handler).set("xena"), - cmd.C_OWNER(handler).set("xoa"), - ) # establish connection using username "xoa". - - print(await cmd.M_PORTCOUNT(handler, 0).get()) # get test module 0 port count - - # other code ... - -def main(): - try: - loop = asyncio.get_event_loop() - loop.create_task(my_awesome_func()) - loop.run_forever() - except KeyboardInterrupt: - pass - -if __name__ == "__main__": - main() \ No newline at end of file diff --git a/docs/source/code_example/llapi/query_parameters.py b/docs/source/code_example/llapi/query_parameters.py deleted file mode 100644 index 6c10c3ca..00000000 --- a/docs/source/code_example/llapi/query_parameters.py +++ /dev/null @@ -1,29 +0,0 @@ -import asyncio -from xoa_driver import utils -from xoa_driver.lli import commands as cmd -from xoa_driver.lli import TransportationHandler -from xoa_driver.lli import establish_connection - -async def my_awesome_func(): - handler = TransportationHandler(debug=False) - await establish_connection(handler, "192.168.1.198") - await utils.apply( - cmd.C_LOGON(handler).set("xena"), - cmd.C_OWNER(handler).set("xoa"), - ) # establish connection using username "xoa". - - print(await cmd.P_SPEEDS_SUPPORTED(handler, 0, 0).get()) # get speeds supported of port 0/0 - print(await cmd.P_SPEEDS_SUPPORTED(handler, 0, 1).get())# get speeds supported of port 0/1 - - # other code ... - -def main(): - try: - loop = asyncio.get_event_loop() - loop.create_task(my_awesome_func()) - loop.run_forever() - except KeyboardInterrupt: - pass - -if __name__ == "__main__": - main() \ No newline at end of file diff --git a/docs/source/code_example/llapi/setting_parameters.py b/docs/source/code_example/llapi/setting_parameters.py deleted file mode 100644 index d949109c..00000000 --- a/docs/source/code_example/llapi/setting_parameters.py +++ /dev/null @@ -1,34 +0,0 @@ -import asyncio -from xoa_driver import utils -from xoa_driver import enums -from xoa_driver.lli import commands as cmd -from xoa_driver.lli import TransportationHandler -from xoa_driver.lli import establish_connection - -async def my_awesome_func(): - handler = TransportationHandler(debug=False) - await establish_connection(handler, "192.168.1.198") - await utils.apply( - cmd.C_LOGON(handler).set("xena"), - cmd.C_OWNER(handler).set("xoa"), - ) # establish connection using username "xoa". - - reservation = await cmd.P_RESERVATION(handler, 0, 0).get() # port 0/0 - if not reservation == enums.ReservedStatus.RELEASED: - await cmd.P_RESERVATION(handler, 0, 0).set(enums.ReservedAction.RELINQUISH) - await cmd.P_RESERVATION(handler, 0, 0).set(enums.ReservedAction.RESERVE) - - await cmd.P_COMMENT(handler, 0, 0).set(comment="My Port") - - # other code ... - -def main(): - try: - loop = asyncio.get_event_loop() - loop.create_task(my_awesome_func()) - loop.run_forever() - except KeyboardInterrupt: - pass - -if __name__ == "__main__": - main() \ No newline at end of file diff --git a/docs/source/code_example/llapi/stats_collection.py b/docs/source/code_example/llapi/stats_collection.py deleted file mode 100644 index b5123e34..00000000 --- a/docs/source/code_example/llapi/stats_collection.py +++ /dev/null @@ -1,34 +0,0 @@ -import asyncio -from xoa_driver import utils -from xoa_driver.lli import commands as cmd -from xoa_driver.lli import TransportationHandler -from xoa_driver.lli import establish_connection - -async def background_task(handler: TransportationHandler): - while True: - print(await cmd.PT_STREAM(handler, 0, 0, 0).get()) # port 0/0, stream[0] - print(await cmd.PR_TPLDTRAFFIC(handler, 0, 1, 0).get()) # # port 0/1, stream [0] - await asyncio.sleep(1) - -async def my_awesome_func(): - # my code ... - handler = TransportationHandler(debug=False) - await establish_connection(handler, "192.168.1.198") - await utils.apply( - cmd.C_LOGON(handler).set("xena"), - cmd.C_OWNER(handler).set("xoa"), - ) # establish connection using username "xoa". - - asyncio.create_task(background_task(handler)) # put function to work in the background - print("Task working in background") - -def main(): - try: - loop = asyncio.get_event_loop() - loop.create_task(my_awesome_func()) - loop.run_forever() - except KeyboardInterrupt: - pass - -if __name__ == "__main__": - main() \ No newline at end of file diff --git a/docs/source/code_example/xpc_integration.rst b/docs/source/code_example/xpc_integration.rst deleted file mode 100644 index 50c90919..00000000 --- a/docs/source/code_example/xpc_integration.rst +++ /dev/null @@ -1,16 +0,0 @@ -Integration with Port Config -================================================ - -In ValkyrieManager, port configurations are saved into files with extension ``.xpc`` in the same command format as used by `XOA CLI `_. This makes it very easy to go back and forth between a ValkyrieManager environment and a XOA CLI environment. For example, exporting a port configuration from ValkyrieCLIManager generates a configuration file in a simple text format that can be edited using a text editing tool such as Microsoft Notepad. It can then be imported back into ValkyrieManager. - -.. tab:: XPC - - .. literalinclude:: xpc_integration/port_config.xpc - :caption: Port Configuration File (.xpc) - - -.. tab:: HL-API - - .. literalinclude:: xpc_integration/port_config_hlapi.py - :caption: Port Configuration Script in XOA Python API - diff --git a/docs/source/code_example/xpc_integration/port_config.xpc b/docs/source/code_example/xpc_integration/port_config.xpc deleted file mode 100644 index ee5e1a64..00000000 --- a/docs/source/code_example/xpc_integration/port_config.xpc +++ /dev/null @@ -1,77 +0,0 @@ -;XENAPORT -;FormatVersion: 2 -;Savedby: ValkyrieManager (v1.80.8196.2) -;Testbed: Default testbed -;Chassis: New chassis S.454, D.40) -;ChassisSerial: xxxxxxxx -;ModuleModel: M6RJ45N[b] -;Port: 0/0 -;ModuleSerial: xxxxxx -;ModuleVersion: 312 -;Global: S+C+T+R+ -P_RESET -P_SPEEDSELECTION AUTO -P_COMMENT "Port number 0" -P_TXENABLE ON -P_INTERFRAMEGAP 20 -P_FLASH OFF -P_AUTONEGSELECTION ON -P_SPEEDREDUCTION -1 -P_MACADDRESS 0x04F4BCA53E60 -P_IPADDRESS 0.0.0.0 0.0.0.0 0.0.0.0 0.0.0.0 -P_MULTICAST 0.0.0.0 OFF 25 -P_MULTICASTEXT 0.0.0.0 OFF 25 IGMPV2 -P_MULTICASTHDR 0 NOHDR 0 0 DEI_OFF -P_MCSRCLIST 0.0.0.0 -P_ARPREPLY OFF -P_PINGREPLY OFF -P_IPV6ADDRESS 0x00000000000000000000000000000000 0x00000000000000000000000000000000 128 128 -P_ARPV6REPLY OFF -P_PINGV6REPLY OFF -P_ARPRXTABLE -P_NDPRXTABLE -P_PAUSE OFF -P_PFCENABLE OFF OFF OFF OFF OFF OFF OFF OFF -P_RANDOMSEED 0 -P_LATENCYOFFSET 0 -P_LATENCYMODE LAST2LAST -P_TXTIMELIMIT 0 -P_TXBURSTPERIOD 0 -P_TXPACKETLIMIT 0 -P_TXMODE NORMAL -P_MAXHEADERLENGTH 128 -P_AUTOTRAIN 0 -P_LOOPBACK NONE -P_CHECKSUM OFF -P_GAPMONITOR 0 0 -P_MIXWEIGHTS 0 0 0 0 57 3 5 1 2 5 1 4 4 18 0 0 -P_TXDELAY 0 -P_TPLDMODE NORMAL -P_DYNAMIC OFF -P_PAYLOADMODE NORMAL -P_LPENABLE OFF -P_LPTXMODE OFF -PEC_INDICES -PS_INDICES 0 -PS_ENABLE [0] ON -PS_PACKETLIMIT [0] -1 -PS_COMMENT [0] "Stream number 0" -PS_RATEFRACTION [0] 500000 -PS_BURST [0] -1 100 -PS_BURSTGAP [0] 0 0 -PS_HEADERPROTOCOL [0] ETHERNET -PS_PACKETHEADER [0] 0x00000000000004F4BCA53E60FFFF -PS_MODIFIERCOUNT [0] 0 -PS_PACKETLENGTH [0] FIXED 64 1518 -PS_PAYLOAD [0] INCREMENTING 0x00 -PS_TPLDID [0] 0 -PS_INSERTFCS [0] ON -PS_IPV4GATEWAY [0] 0.0.0.0 -PS_IPV6GATEWAY [0] 0x00000000000000000000000000000000 -PS_PFCPRIORITY [0] VLAN_PCP -PM_INDICES -PL_INDICES -PF_INDICES -PC_TRIGGER ON 0 FULL 0 -PC_KEEP ALL 0 -1 -PD_INDICES diff --git a/docs/source/code_example/xpc_integration/port_config_hlapi.py b/docs/source/code_example/xpc_integration/port_config_hlapi.py deleted file mode 100644 index 199570f9..00000000 --- a/docs/source/code_example/xpc_integration/port_config_hlapi.py +++ /dev/null @@ -1,44 +0,0 @@ -import asyncio -from contextlib import suppress -import ipaddress - -from xoa_driver import testers -from xoa_driver import modules -from xoa_driver import ports -from xoa_driver import enums -from xoa_driver import utils -from xoa_driver import exceptions -from xoa_driver.hlfuncs import mgmt, cli - -CHASSIS_IP = "demo.xenanetworks.com" -USERNAME = "xoa" -MODULE_ID = 0 -PORT_ID = 0 - -async def main(): - # create tester instance and establish connection - async with testers.L23Tester(CHASSIS_IP, USERNAME) as tester: - - # access module 0 on the tester - module = tester.modules.obtain(MODULE_ID) - - if isinstance(module, modules.ModuleChimera): - return None # commands which used in this example are not supported by Chimera Module - - # access port 0 on the module as the TX port - port = module.ports.obtain(PORT_ID) - - #--------------------------- - # Port reservation - #--------------------------- - # use high-level func to reserve the port - await mgmt.reserve_port(port) - - await cli.port_config_from_file(port, "port_config.xpc") - - # use high-level func to reserve the port - await mgmt.free_port(port) - - -if __name__ == "__main__": - asyncio.run(main()) \ No newline at end of file diff --git a/docs/source/understand_xoa_python/hlapi_guide.rst b/docs/source/understand_xoa_python/hlapi_guide.rst index 9eb92da4..72b3a599 100644 --- a/docs/source/understand_xoa_python/hlapi_guide.rst +++ b/docs/source/understand_xoa_python/hlapi_guide.rst @@ -233,11 +233,6 @@ Methods to gain access to a module or a port from a :term:`resource manager`: obtain( | ) -**Example**: - -.. literalinclude:: /code_example/hlapiv1/04_obtain_one_module.py - :caption: Access a single module on a tester - Gain Access to Multiple Objects @@ -251,12 +246,6 @@ Methods to gain access to multiple resources from a :term:`resource manager`: obtain_multiple( | , ...) -**Example**: - -.. literalinclude:: /code_example/hlapiv1/05_obtain_multiple_modules.py - :caption: Access multiple modules on a tester - - Index Managers ^^^^^^^^^^^^^^^^^^^^ From 54a2f2ad96d1f24ad719213dc5bd987d2a69431e Mon Sep 17 00:00:00 2001 From: Leonard Yu Date: Wed, 25 Oct 2023 15:12:55 +0200 Subject: [PATCH 5/5] Update version to 2.2.0 --- xoa_driver/__init__.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/xoa_driver/__init__.py b/xoa_driver/__init__.py index 454327a4..920c59d2 100644 --- a/xoa_driver/__init__.py +++ b/xoa_driver/__init__.py @@ -1,2 +1,2 @@ -__version__ = "2.1.6" +__version__ = "2.2.0" __short_version__ = "2.0"