Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix VDM freeze and unfreeze needed for PM stats collection #402

Merged
merged 4 commits into from
Nov 29, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
46 changes: 37 additions & 9 deletions sonic_platform_base/sonic_xcvr/api/public/c_cmis.py
Original file line number Diff line number Diff line change
Expand Up @@ -147,6 +147,43 @@ def set_tx_power(self, tx_power):
time.sleep(1)
return status

def freeze_vdm_stats(self):
'''
This function freeze all the vdm statistics reporting registers.
When raised by the host, causes the module to freeze and hold all
reported statistics reporting registers (minimum, maximum and
average values)in Pages 24h-27h.

Returns True if the provision succeeds and False incase of failure.
'''
return self.xcvr_eeprom.write(consts.VDM_CONTROL, VDM_FREEZE)

def get_vdm_freeze_status(self):
'''
This function reads and returns the vdm Freeze done status.

Returns True if the vdm stats freeze is successful and False if not freeze.
'''
return self.xcvr_eeprom.read(consts.VDM_FREEZE_DONE)

def unfreeze_vdm_stats(self):
'''
This function unfreeze all the vdm statistics reporting registers.
When freeze is ceased by the host, releases the freeze request, allowing the
reported minimum, maximum and average values to update again.

Returns True if the provision succeeds and False incase of failure.
'''
return self.xcvr_eeprom.write(consts.VDM_CONTROL, VDM_UNFREEZE)

def get_vdm_unfreeze_status(self):
'''
This function reads and returns the vdm unfreeze status.

Returns True if the vdm stats unfreeze is successful and False if not unfreeze.
'''
return self.xcvr_eeprom.read(consts.VDM_UNFREEZE_DONE)

def get_pm_all(self):
'''
This function returns the PMs reported in Page 34h and 35h in OIF C-CMIS document
Expand All @@ -163,14 +200,6 @@ def get_pm_all(self):
SOPROC: unit in krad/s
MER: unit in dB
'''
# When raised by the host, causes the module to freeze and hold all
jaganbal-a marked this conversation as resolved.
Show resolved Hide resolved
# reported statistics reporting registers (minimum, maximum and
# average values)in Pages 24h-27h.
# When ceased by the host, releases the freeze request, allowing the
# reported minimum, maximum and average values to update again.
self.xcvr_eeprom.write(consts.VDM_CONTROL, VDM_FREEZE)
time.sleep(1)
self.xcvr_eeprom.write(consts.VDM_CONTROL, VDM_UNFREEZE)
PM_dict = dict()

rx_bits_pm = self.xcvr_eeprom.read(consts.RX_BITS_PM)
Expand Down Expand Up @@ -256,7 +285,6 @@ def get_pm_all(self):
PM_dict['rx_mer_max'] = self.xcvr_eeprom.read(consts.RX_MAX_MER_PM)
return PM_dict


def get_transceiver_info(self):
"""
Retrieves transceiver info of this SFP
Expand Down
8 changes: 0 additions & 8 deletions sonic_platform_base/sonic_xcvr/api/public/cmisVDM.py
Original file line number Diff line number Diff line change
Expand Up @@ -170,14 +170,6 @@ def get_vdm_allpage(self):
return None
VDM_START_PAGE = 0x20
vdm = dict()
# When raised by the host, causes the module to freeze and hold all
# reported statistics reporting registers (minimum, maximum and
# average values)in Pages 24h-27h.
# When ceased by the host, releases the freeze request, allowing the
# reported minimum, maximum and average values to update again.
self.xcvr_eeprom.write(consts.VDM_CONTROL, VDM_FREEZE)
time.sleep(1)
self.xcvr_eeprom.write(consts.VDM_CONTROL, VDM_UNFREEZE)
vdm_flag_page = self.xcvr_eeprom.read_raw(VDM_FLAG_PAGE * PAGE_SIZE + PAGE_OFFSET, PAGE_SIZE)
for page in range(VDM_START_PAGE, VDM_START_PAGE + vdm_page_supported_raw + 1):
vdm_current_page = self.get_vdm_page(page, vdm_flag_page)
Expand Down
4 changes: 4 additions & 0 deletions sonic_platform_base/sonic_xcvr/fields/consts.py
Original file line number Diff line number Diff line change
Expand Up @@ -413,6 +413,10 @@
VDM_SUPPORTED = "VdmSupported"
VDM_SUPPORTED_PAGE = "VdmSupportedPage"
VDM_CONTROL = "VdmControl"
VDM_STATUS = "VdmStatus"
VDM_FREEZE_DONE = "VdmFreezeDone"
VDM_UNFREEZE_DONE = "VdmUnfreezeDone"

MEDIA_LANE_FEC_PM = "Media Lane FEC Performance Monitoring"
MEDIA_LANE_LINK_PM = "Media Lane Link Performance Monitoring"
RX_BITS_PM = "rxBitsPm"
Expand Down
4 changes: 4 additions & 0 deletions sonic_platform_base/sonic_xcvr/mem_maps/public/cmis.py
Original file line number Diff line number Diff line change
Expand Up @@ -449,6 +449,10 @@ def __init__(self, codes):
*(RegBitField("Bit%d" % (bit), bit) for bit in range (0, 2))
),
NumberRegField(consts.VDM_CONTROL, self.getaddr(0x2f, 144), size=1, ro=False),
NumberRegField(consts.VDM_STATUS, self.getaddr(0x2f, 145),
RegBitField(consts.VDM_UNFREEZE_DONE, 6),
RegBitField(consts.VDM_FREEZE_DONE, 7),
),
)

self.TRANS_CONFIG = RegGroupField(consts.TRANS_CONFIG_FIELD,
Expand Down
55 changes: 55 additions & 0 deletions sonic_platform_base/sonic_xcvr/sfp_optoe_base.py
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,61 @@ def get_transceiver_pm(self):
api = self.get_xcvr_api()
return api.get_transceiver_pm() if api is not None else None

def freeze_vdm_stats(self):
'''
This function freeze all the vdm statistics reporting registers.
When raised by the host, causes the module to freeze and hold all
reported statistics reporting registers (minimum, maximum and
average values)in Pages 24h-27h.

Returns True if the provision succeeds and False incase of failure.
'''
api = self.get_xcvr_api()
jaganbal-a marked this conversation as resolved.
Show resolved Hide resolved
try:
return api.freeze_vdm_stats() if api is not None else False
except (NotImplementedError, AttributeError):
return False

def unfreeze_vdm_stats(self):
'''
This function unfreeze all the vdm statistics reporting registers.
When freeze is ceased by the host, releases the freeze request, allowing the
reported minimum, maximum and average values to update again.

Returns True if the provision succeeds and False incase of failure.
'''
api = self.get_xcvr_api()
try:
return api.unfreeze_vdm_stats() if api is not None else False
except (NotImplementedError, AttributeError):
return False


def get_vdm_freeze_status(self):
'''
This function reads and returns the vdm Freeze done status.

Returns True if the vdm stats freeze is successful and False if not freeze.
'''
api = self.get_xcvr_api()
try:
return api.get_vdm_freeze_status() if api is not None else False
except (NotImplementedError, AttributeError):
return False

def get_vdm_unfreeze_status(self):
'''
This function reads and returns the vdm unfreeze status.

Returns True if the vdm stats unfreeze is successful and False if not unfreeze.
'''
api = self.get_xcvr_api()
try:
return api.get_vdm_unfreeze_status() if api is not None else False
except (NotImplementedError, AttributeError):
return False


def get_rx_los(self):
api = self.get_xcvr_api()
if api is not None:
Expand Down
41 changes: 41 additions & 0 deletions tests/sonic_xcvr/test_ccmis.py
Original file line number Diff line number Diff line change
Expand Up @@ -624,3 +624,44 @@ def test_get_transceiver_pm(self, mock_response, expected):
self.api.get_pm_all.return_value = mock_response
result = self.api.get_transceiver_pm()
assert result == expected

@pytest.mark.parametrize("mock_response, expected", [
(0, 0),
(1, 1),
])
def test_get_vdm_freeze_status(self, mock_response, expected):
self.api.xcvr_eeprom.read = MagicMock()
self.api.xcvr_eeprom.read.return_value = mock_response
result = self.api.get_vdm_freeze_status()
assert result == expected

@pytest.mark.parametrize("mock_response, expected", [
(0, 0),
(1, 1),
])
def test_get_vdm_unfreeze_status(self, mock_response, expected):
self.api.xcvr_eeprom.read = MagicMock()
self.api.xcvr_eeprom.read.return_value = mock_response
result = self.api.get_vdm_unfreeze_status()
assert result == expected

@pytest.mark.parametrize("mock_response, expected", [
(0, 0),
(1, 1),
])
def test_freeze_vdm_stats(self, mock_response, expected):
self.api.xcvr_eeprom.write = MagicMock()
self.api.xcvr_eeprom.write.return_value = mock_response
result = self.api.freeze_vdm_stats()
assert result == expected

@pytest.mark.parametrize("mock_response, expected", [
(0, 0),
(1, 1),
])
def test_unfreeze_vdm_stats(self, mock_response, expected):
self.api.xcvr_eeprom.write = MagicMock()
self.api.xcvr_eeprom.write.return_value = mock_response
result = self.api.unfreeze_vdm_stats()
assert result == expected

81 changes: 81 additions & 0 deletions tests/sonic_xcvr/test_sfp_optoe_base.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,81 @@
from mock import MagicMock
from mock import patch
import pytest
from sonic_platform_base.sonic_xcvr.sfp_optoe_base import SfpOptoeBase
from sonic_platform_base.sonic_xcvr.api.public.c_cmis import CCmisApi
from sonic_platform_base.sonic_xcvr.api.public.cmis import CmisApi
from sonic_platform_base.sonic_xcvr.mem_maps.public.c_cmis import CCmisMemMap
from sonic_platform_base.sonic_xcvr.xcvr_eeprom import XcvrEeprom
from sonic_platform_base.sonic_xcvr.codes.public.cmis import CmisCodes

class TestSfpOptoeBase(object):

codes = CmisCodes
mem_map = CCmisMemMap(codes)
reader = MagicMock(return_value=None)
writer = MagicMock()
eeprom = XcvrEeprom(reader, writer, mem_map)
sfp_optoe_api = SfpOptoeBase()
ccmis_api = CCmisApi(eeprom)
cmis_api = CmisApi(eeprom)

@pytest.mark.parametrize("mock_response1, mock_response2, expected", [
(0, ccmis_api, 0),
(1, ccmis_api, 1),
(None, None, False),
(None, cmis_api, False),
])
def test_freeze_vdm_stats(self, mock_response1, mock_response2, expected):
self.sfp_optoe_api.get_xcvr_api = MagicMock()
self.sfp_optoe_api.get_xcvr_api.return_value = mock_response2
self.ccmis_api.freeze_vdm_stats = MagicMock()
self.ccmis_api.freeze_vdm_stats.return_value = mock_response1

result = self.sfp_optoe_api.freeze_vdm_stats()
assert result == expected

@pytest.mark.parametrize("mock_response1, mock_response2, expected", [
(0, ccmis_api, 0),
(1, ccmis_api, 1),
(None, None, False),
(None, cmis_api, False),
])
def test_unfreeze_vdm_stats(self, mock_response1, mock_response2, expected):
self.sfp_optoe_api.get_xcvr_api = MagicMock()
self.sfp_optoe_api.get_xcvr_api.return_value = mock_response2
self.ccmis_api.unfreeze_vdm_stats = MagicMock()
self.ccmis_api.unfreeze_vdm_stats.return_value = mock_response1

result = self.sfp_optoe_api.unfreeze_vdm_stats()
assert result == expected

@pytest.mark.parametrize("mock_response1, mock_response2, expected", [
(0, ccmis_api, 0),
(1, ccmis_api, 1),
(None, None, False),
(None, cmis_api, False),
])
def test_get_vdm_freeze_status(self, mock_response1, mock_response2, expected):
self.sfp_optoe_api.get_xcvr_api = MagicMock()
self.sfp_optoe_api.get_xcvr_api.return_value = mock_response2
self.ccmis_api.get_vdm_freeze_status = MagicMock()
self.ccmis_api.get_vdm_freeze_status.return_value = mock_response1

result = self.sfp_optoe_api.get_vdm_freeze_status()
assert result == expected

@pytest.mark.parametrize("mock_response1, mock_response2, expected", [
(0, ccmis_api, 0),
(1, ccmis_api, 1),
(None, None, False),
(None, cmis_api, False),
])
def test_get_vdm_unfreeze_status(self, mock_response1, mock_response2, expected):
self.sfp_optoe_api.get_xcvr_api = MagicMock()
self.sfp_optoe_api.get_xcvr_api.return_value = mock_response2
self.ccmis_api.get_vdm_unfreeze_status = MagicMock()
self.ccmis_api.get_vdm_unfreeze_status.return_value = mock_response1

result = self.sfp_optoe_api.get_vdm_unfreeze_status()
assert result == expected

Loading