From 887e510198a6fec0beeb22d61df9ebb9b994a6e6 Mon Sep 17 00:00:00 2001 From: Anoop Kamath <115578705+AnoopKamath@users.noreply.github.com> Date: Wed, 5 Jul 2023 15:59:01 -0700 Subject: [PATCH 01/32] Optics SI settings changes for platform daemon --- sonic-xcvrd/xcvrd/xcvrd.py | 177 +++++++++++++++++++++++++++++++++++-- 1 file changed, 170 insertions(+), 7 deletions(-) diff --git a/sonic-xcvrd/xcvrd/xcvrd.py b/sonic-xcvrd/xcvrd/xcvrd.py index f59cf6433..400c6aa53 100644 --- a/sonic-xcvrd/xcvrd/xcvrd.py +++ b/sonic-xcvrd/xcvrd/xcvrd.py @@ -88,6 +88,7 @@ BIAS_UNIT = 'mA' g_dict = {} +g_optics_si_dict = {} # Global platform specific sfputil class instance platform_sfputil = None # Global chassis object based on new platform api @@ -791,6 +792,135 @@ def notify_media_setting(logical_port_name, transceiver_dict, app_port_tbl.set(port_name, fvs) +def get_optics_si_settings_value(physical_port, lane_speed, key): + GLOBAL_MEDIA_SETTINGS_KEY = 'GLOBAL_MEDIA_SETTINGS' + PORT_MEDIA_SETTINGS_KEY = 'PORT_MEDIA_SETTINGS' + DEFAULT_KEY = 'Default' + SPEED_KEY = lane_speed + 'G_SPEED' + RANGE_SEPARATOR = '-' + COMMA_SEPARATOR = ',' + default_dict = {} + + # Keys under global media settings can be a list or range or list of ranges + # of physical port numbers. Below are some examples + # 1-32 + # 1,2,3,4,5 + # 1-4,9-12 + + RANGE_SEPARATOR = '-' + COMMA_SEPARATOR = ',' + default_dict = {} + optics_si_dict = {} + + # Keys under global media settings can be a list or range or list of ranges + # of physical port numbers. Below are some examples + # 1-32 + # 1,2,3,4,5 + # 1-4,9-12 + + if GLOBAL_MEDIA_SETTINGS_KEY in g_optics_si_dict: + for keys in g_optics_si_dict[GLOBAL_MEDIA_SETTINGS_KEY]: + if COMMA_SEPARATOR in keys: + port_list = keys.split(COMMA_SEPARATOR) + for port in port_list: + if RANGE_SEPARATOR in port: + if check_port_in_range(port, physical_port): + optics_si_dict = g_optics_si_dict[GLOBAL_MEDIA_SETTINGS_KEY][keys] + break + elif str(physical_port) == port: + optics_si_dict = g_optics_si_dict[GLOBAL_MEDIA_SETTINGS_KEY][keys] + break + + elif RANGE_SEPARATOR in keys: + if check_port_in_range(keys, physical_port): + optics_si_dict = g_optics_si_dict[GLOBAL_MEDIA_SETTINGS_KEY][keys] + + key_dict = {} + if SPEED_KEY in optics_si_dict: + if key in optics_si_dict[SPEED_KEY]: + key_dict = optics_si_dict[SPEED_KEY] + return key_dict[key] + if DEFAULT_KEY in optics_si_dict[SPEED_KEY]: + key_dict = optics_si_dict[SPEED_KEY] + default_dict = key_dict[DEFAULT_KEY] + + optics_si_dict = {} + key_dict = {} + + if PORT_MEDIA_SETTINGS_KEY in g_optics_si_dict: + for keys in g_optics_si_dict[PORT_MEDIA_SETTINGS_KEY]: + if int(keys) == physical_port: + optics_si_dict = g_optics_si_dict[PORT_MEDIA_SETTINGS_KEY][keys] + break + + if len(optics_si_dict) == 0: + if len(default_dict) != 0: + return default_dict + else: + helper_logger.log_error("Error: No values for physical port '{}'".format(physical_port)) + return {} + + if SPEED_KEY in optics_si_dict: + if key in optics_si_dict[SPEED_KEY]: + key_dict = optics_si_dict[SPEED_KEY] + return key_dict[key] + if DEFAULT_KEY in optics_si_dict[SPEED_KEY]: + key_dict = optics_si_dict[SPEED_KEY] + default_dict = key_dict[DEFAULT_KEY] + elif len(default_dict) != 0: + return default_dict + else: + if len(default_dict) != 0: + return default_dict + + return {} + +def get_optics_si_settings_key(physical_port, transceiver_dict): + vendor_name_str = transceiver_dict['manufacturer'] + vendor_pn_str = transceiver_dict['model'] + vendor_key = vendor_name_str.upper().strip() + '-' + vendor_pn_str.strip() + + return vendor_key + +def notify_optics_si_setting(logical_port_name, lane_speed, port_mapping): + + if not g_optics_si_dict: + return + + transceiver_dict = {} + ganged_port = False + ganged_member_num = 1 + optics_si = {} + + physical_port_list = port_mapping.logical_port_name_to_physical_port_list(logical_port_name) + if physical_port_list is None: + helper_logger.log_error("Error: No physical ports found for logical port '{}'".format(logical_port_name)) + return PHYSICAL_PORT_NOT_EXIST + + if len(physical_port_list) > 1: + ganged_port = True + + for physical_port in physical_port_list: + logical_port_list = port_mapping.get_physical_to_logical(physical_port) + num_logical_ports = len(logical_port_list) + logical_idx = logical_port_list.index(logical_port_name) + if not _wrapper_get_presence(physical_port): + helper_logger.log_info("Module {} presence not detected during notify".format(physical_port)) + continue + port_info_dict = _wrapper_get_transceiver_info(physical_port) + if port_info_dict is not None: + transceiver_dict[physical_port] = port_info_dict + if physical_port not in transceiver_dict: + helper_logger.log_error("Module {} eeprom not populated in transceiver dict".format(physical_port)) + continue + + port_name = get_physical_port_name(logical_port_name, + ganged_member_num, ganged_port) + ganged_member_num += 1 + key = get_optics_si_settings_key(physical_port, transceiver_dict[physical_port]) + optics_si = get_optics_si_settings_value(physical_port, lane_speed, key) + + return optics_si def waiting_time_compensation_with_sleep(time_start, time_to_wait): time_now = time.time() @@ -1398,6 +1528,9 @@ def task_worker(self): if 'admin_status' not in self.port_dict[lport]: self.port_dict[lport]['admin_status'] = self.get_port_admin_status(lport) + if 'optics_si_validated' not in self.port_dict[lport]: + self.port_dict[lport]['optics_si_validated'] = False + pport = int(info.get('index', "-1")) speed = int(info.get('speed', "0")) lanes = info.get('lanes', "").strip() @@ -1614,12 +1747,29 @@ def task_worker(self): self.log_notice("{} waiting for host tx ready...".format(lport)) continue - # D.1.3 Software Configuration and Initialization - api.set_datapath_init(host_lanes_mask) - dpInitDuration = self.get_cmis_dp_init_duration_secs(api) - self.log_notice("{}: DpInit duration {} secs".format(lport, dpInitDuration)) - self.port_dict[lport]['cmis_expired'] = now + datetime.timedelta(seconds=dpInitDuration) - self.port_dict[lport]['cmis_state'] = self.CMIS_STATE_DP_TXON + optics_si_dict = {} + if not self.port_dict[lport]['optics_si_validated'] and g_optics_si_dict: + # Apply module SI settings if applicable + lane_speed = int(speed/1000)//host_lane_count + optics_si_dict = notify_optics_si_setting(lport, lane_speed, self.port_mapping) + + if optics_si_dict: + self.log_notice("{}: Optics SI found. Apply".format(lport)) + if not api.set_module_si_settings(host_lanes_mask, appl, optics_si_dict): + self.log_notice("{}: unable to apply SI settings and set application".format(lport)) + self.force_cmis_reinit(lport, retries + 1) + continue + else: + # Recheck config errors + self.port_dict[lport]['optics_si_validated'] = True + self.port_dict[lport]['cmis_state'] = self.CMIS_STATE_DP_INIT + else: + # D.1.3 Software Configuration and Initialization + api.set_datapath_init(host_lanes_mask) + dpInitDuration = self.get_cmis_dp_init_duration_secs(api) + self.log_notice("{}: DpInit duration {} secs".format(lport, dpInitDuration)) + self.port_dict[lport]['cmis_expired'] = now + datetime.timedelta(seconds=dpInitDuration) + self.port_dict[lport]['cmis_state'] = self.CMIS_STATE_DP_TXON elif state == self.CMIS_STATE_DP_TXON: if not self.check_datapath_state(api, host_lanes_mask, ['DataPathInitialized']): if (expired is not None) and (expired <= now): @@ -2378,6 +2528,18 @@ def load_media_settings(self): with open(media_settings_file_path, "r") as media_file: g_dict = json.load(media_file) + def load_optics_si_settings(self): + global g_optics_si_dict + (platform_path, _) = device_info.get_paths_to_platform_and_hwsku_dirs() + + optics_si_settings_file_path = os.path.join(platform_path, "optics_si_settings.json") + if not os.path.isfile(optics_si_settings_file_path): + self.log_info("xcvrd: No optics SI file exists") + return {} + + with open(optics_si_settings_file_path, "r") as optics_si_file: + g_optics_si_dict = json.load(optics_si_file) + # Initialize daemon def init(self): global platform_sfputil @@ -2419,9 +2581,10 @@ def init(self): self.xcvr_table_helper = XcvrTableHelper(self.namespaces) if is_fast_reboot_enabled(): - self.log_info("Skip loading media_settings.json in case of fast-reboot") + self.log_info("Skip loading media_settings.json and optics_si_settings.json in case of fast-reboot") else: self.load_media_settings() + self.load_optics_si_settings() # Make sure this daemon started after all port configured self.log_notice("XCVRD INIT: Wait for port config is done") From 6a8991bc3ca699e9b059bd90e831db62858354c0 Mon Sep 17 00:00:00 2001 From: Anoop Kamath <115578705+AnoopKamath@users.noreply.github.com> Date: Thu, 6 Jul 2023 11:12:06 -0700 Subject: [PATCH 02/32] Remove repeated lines --- sonic-xcvrd/xcvrd/xcvrd.py | 13 +------------ 1 file changed, 1 insertion(+), 12 deletions(-) diff --git a/sonic-xcvrd/xcvrd/xcvrd.py b/sonic-xcvrd/xcvrd/xcvrd.py index 400c6aa53..f079ed4a6 100644 --- a/sonic-xcvrd/xcvrd/xcvrd.py +++ b/sonic-xcvrd/xcvrd/xcvrd.py @@ -806,18 +806,7 @@ def get_optics_si_settings_value(physical_port, lane_speed, key): # 1-32 # 1,2,3,4,5 # 1-4,9-12 - - RANGE_SEPARATOR = '-' - COMMA_SEPARATOR = ',' - default_dict = {} - optics_si_dict = {} - - # Keys under global media settings can be a list or range or list of ranges - # of physical port numbers. Below are some examples - # 1-32 - # 1,2,3,4,5 - # 1-4,9-12 - + if GLOBAL_MEDIA_SETTINGS_KEY in g_optics_si_dict: for keys in g_optics_si_dict[GLOBAL_MEDIA_SETTINGS_KEY]: if COMMA_SEPARATOR in keys: From e806c439c78d0ab0084dab0e0244d85f1a39df6f Mon Sep 17 00:00:00 2001 From: Anoop Kamath <115578705+AnoopKamath@users.noreply.github.com> Date: Fri, 7 Jul 2023 15:03:56 -0700 Subject: [PATCH 03/32] Address review comments: --- sonic-xcvrd/xcvrd/xcvrd.py | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/sonic-xcvrd/xcvrd/xcvrd.py b/sonic-xcvrd/xcvrd/xcvrd.py index f079ed4a6..5ed96e80f 100644 --- a/sonic-xcvrd/xcvrd/xcvrd.py +++ b/sonic-xcvrd/xcvrd/xcvrd.py @@ -796,7 +796,7 @@ def get_optics_si_settings_value(physical_port, lane_speed, key): GLOBAL_MEDIA_SETTINGS_KEY = 'GLOBAL_MEDIA_SETTINGS' PORT_MEDIA_SETTINGS_KEY = 'PORT_MEDIA_SETTINGS' DEFAULT_KEY = 'Default' - SPEED_KEY = lane_speed + 'G_SPEED' + SPEED_KEY = str(lane_speed) + 'G_SPEED' RANGE_SEPARATOR = '-' COMMA_SEPARATOR = ',' default_dict = {} @@ -871,7 +871,7 @@ def get_optics_si_settings_key(physical_port, transceiver_dict): return vendor_key -def notify_optics_si_setting(logical_port_name, lane_speed, port_mapping): +def fetch_optics_si_setting(logical_port_name, lane_speed, port_mapping): if not g_optics_si_dict: return @@ -1662,6 +1662,7 @@ def task_worker(self): self.port_dict[lport]['cmis_state'] = self.CMIS_STATE_READY continue self.log_notice("{}: force Datapath reinit".format(lport)) + self.port_dict[lport]['optics_si_validated'] = False self.port_dict[lport]['cmis_state'] = self.CMIS_STATE_DP_DEINIT elif state == self.CMIS_STATE_DP_DEINIT: # D.2.2 Software Deinitialization @@ -1740,7 +1741,7 @@ def task_worker(self): if not self.port_dict[lport]['optics_si_validated'] and g_optics_si_dict: # Apply module SI settings if applicable lane_speed = int(speed/1000)//host_lane_count - optics_si_dict = notify_optics_si_setting(lport, lane_speed, self.port_mapping) + optics_si_dict = fetch_optics_si_setting(lport, lane_speed, self.port_mapping) if optics_si_dict: self.log_notice("{}: Optics SI found. Apply".format(lport)) From df3c8e637b487e82779906226be306cf68d87e40 Mon Sep 17 00:00:00 2001 From: Anoop Kamath <115578705+AnoopKamath@users.noreply.github.com> Date: Mon, 10 Jul 2023 01:51:24 -0700 Subject: [PATCH 04/32] Fix UT issues --- sonic-xcvrd/xcvrd/xcvrd.py | 31 +++++++++++++++++-------------- 1 file changed, 17 insertions(+), 14 deletions(-) diff --git a/sonic-xcvrd/xcvrd/xcvrd.py b/sonic-xcvrd/xcvrd/xcvrd.py index 5ed96e80f..c892b860b 100644 --- a/sonic-xcvrd/xcvrd/xcvrd.py +++ b/sonic-xcvrd/xcvrd/xcvrd.py @@ -792,7 +792,7 @@ def notify_media_setting(logical_port_name, transceiver_dict, app_port_tbl.set(port_name, fvs) -def get_optics_si_settings_value(physical_port, lane_speed, key): +def get_optics_si_settings_value(physical_port, lane_speed, transceiver_dict): GLOBAL_MEDIA_SETTINGS_KEY = 'GLOBAL_MEDIA_SETTINGS' PORT_MEDIA_SETTINGS_KEY = 'PORT_MEDIA_SETTINGS' DEFAULT_KEY = 'Default' @@ -800,6 +800,11 @@ def get_optics_si_settings_value(physical_port, lane_speed, key): RANGE_SEPARATOR = '-' COMMA_SEPARATOR = ',' default_dict = {} + optics_si_dict = {} + + vendor_name_str = transceiver_dict['manufacturer'].upper().strip() + vendor_pn_str = transceiver_dict['model'].upper().strip() + key = vendor_name_str + '-' + vendor_pn_str # Keys under global media settings can be a list or range or list of ranges # of physical port numbers. Below are some examples @@ -829,13 +834,15 @@ def get_optics_si_settings_value(physical_port, lane_speed, key): if key in optics_si_dict[SPEED_KEY]: key_dict = optics_si_dict[SPEED_KEY] return key_dict[key] - if DEFAULT_KEY in optics_si_dict[SPEED_KEY]: + elif vendor_name_str in optics_si_dict[SPEED_KEY]: + key_dict = optics_si_dict[SPEED_KEY] + return key_dict[vendor_name_str] + elif DEFAULT_KEY in optics_si_dict[SPEED_KEY]: key_dict = optics_si_dict[SPEED_KEY] default_dict = key_dict[DEFAULT_KEY] optics_si_dict = {} - key_dict = {} - + if PORT_MEDIA_SETTINGS_KEY in g_optics_si_dict: for keys in g_optics_si_dict[PORT_MEDIA_SETTINGS_KEY]: if int(keys) == physical_port: @@ -849,11 +856,15 @@ def get_optics_si_settings_value(physical_port, lane_speed, key): helper_logger.log_error("Error: No values for physical port '{}'".format(physical_port)) return {} + key_dict = {} if SPEED_KEY in optics_si_dict: if key in optics_si_dict[SPEED_KEY]: key_dict = optics_si_dict[SPEED_KEY] return key_dict[key] - if DEFAULT_KEY in optics_si_dict[SPEED_KEY]: + elif vendor_name_str in optics_si_dict[SPEED_KEY]: + key_dict = optics_si_dict[SPEED_KEY] + return key_dict[vendor_name_str] + elif DEFAULT_KEY in optics_si_dict[SPEED_KEY]: key_dict = optics_si_dict[SPEED_KEY] default_dict = key_dict[DEFAULT_KEY] elif len(default_dict) != 0: @@ -864,13 +875,6 @@ def get_optics_si_settings_value(physical_port, lane_speed, key): return {} -def get_optics_si_settings_key(physical_port, transceiver_dict): - vendor_name_str = transceiver_dict['manufacturer'] - vendor_pn_str = transceiver_dict['model'] - vendor_key = vendor_name_str.upper().strip() + '-' + vendor_pn_str.strip() - - return vendor_key - def fetch_optics_si_setting(logical_port_name, lane_speed, port_mapping): if not g_optics_si_dict: @@ -906,8 +910,7 @@ def fetch_optics_si_setting(logical_port_name, lane_speed, port_mapping): port_name = get_physical_port_name(logical_port_name, ganged_member_num, ganged_port) ganged_member_num += 1 - key = get_optics_si_settings_key(physical_port, transceiver_dict[physical_port]) - optics_si = get_optics_si_settings_value(physical_port, lane_speed, key) + optics_si = get_optics_si_settings_value(physical_port, lane_speed, transceiver_dict[physical_port]) return optics_si From dc8cf53ec33cec68066a34ccc16b45c24af99112 Mon Sep 17 00:00:00 2001 From: Anoop Kamath <115578705+AnoopKamath@users.noreply.github.com> Date: Mon, 10 Jul 2023 14:51:43 -0700 Subject: [PATCH 05/32] Fix UT issues --- sonic-xcvrd/xcvrd/xcvrd.py | 13 +++++-------- 1 file changed, 5 insertions(+), 8 deletions(-) diff --git a/sonic-xcvrd/xcvrd/xcvrd.py b/sonic-xcvrd/xcvrd/xcvrd.py index c892b860b..89277fd87 100644 --- a/sonic-xcvrd/xcvrd/xcvrd.py +++ b/sonic-xcvrd/xcvrd/xcvrd.py @@ -869,11 +869,8 @@ def get_optics_si_settings_value(physical_port, lane_speed, transceiver_dict): default_dict = key_dict[DEFAULT_KEY] elif len(default_dict) != 0: return default_dict - else: - if len(default_dict) != 0: - return default_dict - return {} + return default_dict def fetch_optics_si_setting(logical_port_name, lane_speed, port_mapping): @@ -1752,10 +1749,10 @@ def task_worker(self): self.log_notice("{}: unable to apply SI settings and set application".format(lport)) self.force_cmis_reinit(lport, retries + 1) continue - else: - # Recheck config errors - self.port_dict[lport]['optics_si_validated'] = True - self.port_dict[lport]['cmis_state'] = self.CMIS_STATE_DP_INIT + + # Recheck config errors + self.port_dict[lport]['optics_si_validated'] = True + self.port_dict[lport]['cmis_state'] = self.CMIS_STATE_DP_INIT else: # D.1.3 Software Configuration and Initialization api.set_datapath_init(host_lanes_mask) From b36377a6534942d287481bc099b069159a86ee26 Mon Sep 17 00:00:00 2001 From: Anoop Kamath <115578705+AnoopKamath@users.noreply.github.com> Date: Mon, 17 Jul 2023 01:16:54 -0700 Subject: [PATCH 06/32] Removed unused code --- sonic-xcvrd/xcvrd/xcvrd.py | 12 ------------ 1 file changed, 12 deletions(-) diff --git a/sonic-xcvrd/xcvrd/xcvrd.py b/sonic-xcvrd/xcvrd/xcvrd.py index 89277fd87..0dbd9f73d 100644 --- a/sonic-xcvrd/xcvrd/xcvrd.py +++ b/sonic-xcvrd/xcvrd/xcvrd.py @@ -873,13 +873,10 @@ def get_optics_si_settings_value(physical_port, lane_speed, transceiver_dict): return default_dict def fetch_optics_si_setting(logical_port_name, lane_speed, port_mapping): - if not g_optics_si_dict: return transceiver_dict = {} - ganged_port = False - ganged_member_num = 1 optics_si = {} physical_port_list = port_mapping.logical_port_name_to_physical_port_list(logical_port_name) @@ -887,13 +884,7 @@ def fetch_optics_si_setting(logical_port_name, lane_speed, port_mapping): helper_logger.log_error("Error: No physical ports found for logical port '{}'".format(logical_port_name)) return PHYSICAL_PORT_NOT_EXIST - if len(physical_port_list) > 1: - ganged_port = True - for physical_port in physical_port_list: - logical_port_list = port_mapping.get_physical_to_logical(physical_port) - num_logical_ports = len(logical_port_list) - logical_idx = logical_port_list.index(logical_port_name) if not _wrapper_get_presence(physical_port): helper_logger.log_info("Module {} presence not detected during notify".format(physical_port)) continue @@ -904,9 +895,6 @@ def fetch_optics_si_setting(logical_port_name, lane_speed, port_mapping): helper_logger.log_error("Module {} eeprom not populated in transceiver dict".format(physical_port)) continue - port_name = get_physical_port_name(logical_port_name, - ganged_member_num, ganged_port) - ganged_member_num += 1 optics_si = get_optics_si_settings_value(physical_port, lane_speed, transceiver_dict[physical_port]) return optics_si From dd388904aef2dc1ba51aa21580db1b2d884a1b53 Mon Sep 17 00:00:00 2001 From: Anoop Kamath <115578705+AnoopKamath@users.noreply.github.com> Date: Mon, 17 Jul 2023 12:39:30 -0700 Subject: [PATCH 07/32] Add xcvrd test cases --- sonic-xcvrd/tests/test_xcvrd.py | 37 +++++++++++++++++++++++++++++++++ 1 file changed, 37 insertions(+) diff --git a/sonic-xcvrd/tests/test_xcvrd.py b/sonic-xcvrd/tests/test_xcvrd.py index 2581c7a0d..cc2052309 100644 --- a/sonic-xcvrd/tests/test_xcvrd.py +++ b/sonic-xcvrd/tests/test_xcvrd.py @@ -41,6 +41,14 @@ global_media_settings = media_settings_with_comma_dict['GLOBAL_MEDIA_SETTINGS'].pop('1-32') media_settings_with_comma_dict['GLOBAL_MEDIA_SETTINGS']['1-5,6,7-20,21-32'] = global_media_settings +with open(os.path.join(test_path, 'optics_si_settings.json'), 'r') as fn: + optics_si_settings_dict = json.load(fn) +port_optics_si_settings = {} +optics_si_settings_with_comma_dict = copy.deepcopy(optics_si_settings_dict) +global_optics_si_settings = optics_si_settings_with_comma_dict['GLOBAL_MEDIA_SETTINGS'].pop('0-31') +port_optics_si_settings['PORT_MEDIA_SETTINGS'] = optics_si_settings_with_comma_dict.pop('PORT_MEDIA_SETTINGS') +optics_si_settings_with_comma_dict['GLOBAL_MEDIA_SETTINGS']['0-5,6,7-20,21-31'] = global_optics_si_settings + class TestXcvrdThreadException(object): @patch('xcvrd.xcvrd.platform_chassis', MagicMock()) @@ -470,6 +478,35 @@ def _check_notify_media_setting(self, index): port_mapping.handle_port_change_event(port_change_event) notify_media_setting(logical_port_name, xcvr_info_dict, app_port_tbl, port_mapping) + @patch('xcvrd.xcvrd.g_optics_si_dict', optics_si_settings_dict) + @patch('xcvrd.xcvrd._wrapper_get_presence', MagicMock(return_value=True)) + def test_fetch_optics_si_setting(self): + self._check_fetch_optics_si_setting(1) + + @patch('xcvrd.xcvrd.g_optics_si_dict', optics_si_settings_with_comma_dict) + @patch('xcvrd.xcvrd._wrapper_get_presence', MagicMock(return_value=True)) + def test_fetch_optics_si_setting_with_comma(self): + self._check_fetch_optics_si_setting(1) + self._check_fetch_optics_si_setting(6) + + @patch('xcvrd.xcvrd.g_optics_si_dict', port_optics_si_settings) + @patch('xcvrd.xcvrd._wrapper_get_presence', MagicMock(return_value=True)) + def test_fetch_optics_si_setting_with_port(self): + self._check_fetch_optics_si_setting(1) + + @patch('xcvrd.xcvrd_utilities.port_mapping.PortMapping.logical_port_name_to_physical_port_list', MagicMock(return_value=[0])) + @patch('xcvrd.xcvrd._wrapper_get_presence', MagicMock(return_value=True)) + @patch('xcvrd.xcvrd._wrapper_get_transceiver_info', MagicMock(return_value={'type': 'QSFP-DD Double Density 8X Pluggable Transceiver', + 'vendor_rev': '0.5', + 'serial': '0.7', + 'manufacturer': 'Credo', + 'model': 'CAC82X321M2MC0HW'})) + def _check_fetch_optics_si_setting(self, index): + logical_port_name = 'Ethernet0' + port_mapping = PortMapping() + lane_speed = 100 + fetch_optics_si_setting(logical_port_name, lane_speed, port_mapping) + def test_detect_port_in_error_status(self): class MockTable: def get(self, key): From 025133584610d2e5dc54b98bacd4d10293741188 Mon Sep 17 00:00:00 2001 From: Anoop Kamath <115578705+AnoopKamath@users.noreply.github.com> Date: Mon, 17 Jul 2023 12:44:29 -0700 Subject: [PATCH 08/32] Create optics_si_settings.json --- sonic-xcvrd/tests/optics_si_settings.json | 222 ++++++++++++++++++++++ 1 file changed, 222 insertions(+) create mode 100644 sonic-xcvrd/tests/optics_si_settings.json diff --git a/sonic-xcvrd/tests/optics_si_settings.json b/sonic-xcvrd/tests/optics_si_settings.json new file mode 100644 index 000000000..2b9defc81 --- /dev/null +++ b/sonic-xcvrd/tests/optics_si_settings.json @@ -0,0 +1,222 @@ +{ + "GLOBAL_MEDIA_SETTINGS":{ + "0-31":{ + "100G_SPEED":{ + "CREDO-CAC82X321M2MC0HW":{ + "OutputEqPreCursorTargetRx":{ + "OutputEqPreCursorTargetRx1":3, + "OutputEqPreCursorTargetRx2":3, + "OutputEqPreCursorTargetRx3":3, + "OutputEqPreCursorTargetRx4":3, + "OutputEqPreCursorTargetRx5":3, + "OutputEqPreCursorTargetRx6":3, + "OutputEqPreCursorTargetRx7":3, + "OutputEqPreCursorTargetRx8":3 + }, + "OutputEqPostCursorTargetRx":{ + "OutputEqPostCursorTargetRx1":0, + "OutputEqPostCursorTargetRx2":0, + "OutputEqPostCursorTargetRx3":0, + "OutputEqPostCursorTargetRx4":0, + "OutputEqPostCursorTargetRx5":0, + "OutputEqPostCursorTargetRx6":0, + "OutputEqPostCursorTargetRx7":0, + "OutputEqPostCursorTargetRx8":0 + }, + "OutputAmplitudeTargetRx":{ + "OutputAmplitudeTargetRx1":0, + "OutputAmplitudeTargetRx2":0, + "OutputAmplitudeTargetRx3":0, + "OutputAmplitudeTargetRx4":0, + "OutputAmplitudeTargetRx5":0, + "OutputAmplitudeTargetRx6":0, + "OutputAmplitudeTargetRx7":0, + "OutputAmplitudeTargetRx8":0 + } + } + } + } + }, + "PORT_MEDIA_SETTINGS":{ + "0":{ + "100G_SPEED":{ + "CREDO-CAC82X321M2MC0HW":{ + "OutputEqPreCursorTargetRx":{ + "OutputEqPreCursorTargetRx1":3, + "OutputEqPreCursorTargetRx2":3, + "OutputEqPreCursorTargetRx3":3, + "OutputEqPreCursorTargetRx4":3, + "OutputEqPreCursorTargetRx5":3, + "OutputEqPreCursorTargetRx6":3, + "OutputEqPreCursorTargetRx7":3, + "OutputEqPreCursorTargetRx8":3 + }, + "OutputEqPostCursorTargetRx":{ + "OutputEqPostCursorTargetRx1":0, + "OutputEqPostCursorTargetRx2":0, + "OutputEqPostCursorTargetRx3":0, + "OutputEqPostCursorTargetRx4":0, + "OutputEqPostCursorTargetRx5":0, + "OutputEqPostCursorTargetRx6":0, + "OutputEqPostCursorTargetRx7":0, + "OutputEqPostCursorTargetRx8":0 + }, + "OutputAmplitudeTargetRx":{ + "OutputAmplitudeTargetRx1":0, + "OutputAmplitudeTargetRx2":0, + "OutputAmplitudeTargetRx3":0, + "OutputAmplitudeTargetRx4":0, + "OutputAmplitudeTargetRx5":0, + "OutputAmplitudeTargetRx6":0, + "OutputAmplitudeTargetRx7":0, + "OutputAmplitudeTargetRx8":0 + } + } + } + }, + "1":{ + "100G_SPEED":{ + "Default":{ + "OutputEqPreCursorTargetRx":{ + "OutputEqPreCursorTargetRx1":3, + "OutputEqPreCursorTargetRx2":3, + "OutputEqPreCursorTargetRx3":3, + "OutputEqPreCursorTargetRx4":3, + "OutputEqPreCursorTargetRx5":3, + "OutputEqPreCursorTargetRx6":3, + "OutputEqPreCursorTargetRx7":3, + "OutputEqPreCursorTargetRx8":3 + }, + "OutputEqPostCursorTargetRx":{ + "OutputEqPostCursorTargetRx1":0, + "OutputEqPostCursorTargetRx2":0, + "OutputEqPostCursorTargetRx3":0, + "OutputEqPostCursorTargetRx4":0, + "OutputEqPostCursorTargetRx5":0, + "OutputEqPostCursorTargetRx6":0, + "OutputEqPostCursorTargetRx7":0, + "OutputEqPostCursorTargetRx8":0 + }, + "OutputAmplitudeTargetRx":{ + "OutputAmplitudeTargetRx1":1, + "OutputAmplitudeTargetRx2":1, + "OutputAmplitudeTargetRx3":1, + "OutputAmplitudeTargetRx4":1, + "OutputAmplitudeTargetRx5":1, + "OutputAmplitudeTargetRx6":1, + "OutputAmplitudeTargetRx7":1, + "OutputAmplitudeTargetRx8":1 + } + } + } + }, + "10":{ + "100G_SPEED":{ + "Default":{ + "OutputEqPreCursorTargetRx":{ + "OutputEqPreCursorTargetRx1":3, + "OutputEqPreCursorTargetRx2":3, + "OutputEqPreCursorTargetRx3":3, + "OutputEqPreCursorTargetRx4":3, + "OutputEqPreCursorTargetRx5":3, + "OutputEqPreCursorTargetRx6":3, + "OutputEqPreCursorTargetRx7":3, + "OutputEqPreCursorTargetRx8":3 + }, + "OutputEqPostCursorTargetRx":{ + "OutputEqPostCursorTargetRx1":0, + "OutputEqPostCursorTargetRx2":0, + "OutputEqPostCursorTargetRx3":0, + "OutputEqPostCursorTargetRx4":0, + "OutputEqPostCursorTargetRx5":0, + "OutputEqPostCursorTargetRx6":0, + "OutputEqPostCursorTargetRx7":0, + "OutputEqPostCursorTargetRx8":0 + }, + "OutputAmplitudeTargetRx":{ + "OutputAmplitudeTargetRx1":1, + "OutputAmplitudeTargetRx2":1, + "OutputAmplitudeTargetRx3":1, + "OutputAmplitudeTargetRx4":1, + "OutputAmplitudeTargetRx5":1, + "OutputAmplitudeTargetRx6":1, + "OutputAmplitudeTargetRx7":1, + "OutputAmplitudeTargetRx8":1 + } + } + } + }, + "11":{ + "100G_SPEED":{ + "Default":{ + "OutputEqPreCursorTargetRx":{ + "OutputEqPreCursorTargetRx1":3, + "OutputEqPreCursorTargetRx2":3, + "OutputEqPreCursorTargetRx3":3, + "OutputEqPreCursorTargetRx4":3, + "OutputEqPreCursorTargetRx5":3, + "OutputEqPreCursorTargetRx6":3, + "OutputEqPreCursorTargetRx7":3, + "OutputEqPreCursorTargetRx8":3 + }, + "OutputEqPostCursorTargetRx":{ + "OutputEqPostCursorTargetRx1":0, + "OutputEqPostCursorTargetRx2":0, + "OutputEqPostCursorTargetRx3":0, + "OutputEqPostCursorTargetRx4":0, + "OutputEqPostCursorTargetRx5":0, + "OutputEqPostCursorTargetRx6":0, + "OutputEqPostCursorTargetRx7":0, + "OutputEqPostCursorTargetRx8":0 + }, + "OutputAmplitudeTargetRx":{ + "OutputAmplitudeTargetRx1":1, + "OutputAmplitudeTargetRx2":1, + "OutputAmplitudeTargetRx3":1, + "OutputAmplitudeTargetRx4":1, + "OutputAmplitudeTargetRx5":1, + "OutputAmplitudeTargetRx6":1, + "OutputAmplitudeTargetRx7":1, + "OutputAmplitudeTargetRx8":1 + } + } + } + }, + "12":{ + "100G_SPEED":{ + "Default":{ + "OutputEqPreCursorTargetRx":{ + "OutputEqPreCursorTargetRx1":3, + "OutputEqPreCursorTargetRx2":3, + "OutputEqPreCursorTargetRx3":3, + "OutputEqPreCursorTargetRx4":3, + "OutputEqPreCursorTargetRx5":3, + "OutputEqPreCursorTargetRx6":3, + "OutputEqPreCursorTargetRx7":3, + "OutputEqPreCursorTargetRx8":3 + }, + "OutputEqPostCursorTargetRx":{ + "OutputEqPostCursorTargetRx1":0, + "OutputEqPostCursorTargetRx2":0, + "OutputEqPostCursorTargetRx3":0, + "OutputEqPostCursorTargetRx4":0, + "OutputEqPostCursorTargetRx5":0, + "OutputEqPostCursorTargetRx6":0, + "OutputEqPostCursorTargetRx7":0, + "OutputEqPostCursorTargetRx8":0 + }, + "OutputAmplitudeTargetRx":{ + "OutputAmplitudeTargetRx1":1, + "OutputAmplitudeTargetRx2":1, + "OutputAmplitudeTargetRx3":1, + "OutputAmplitudeTargetRx4":1, + "OutputAmplitudeTargetRx5":1, + "OutputAmplitudeTargetRx6":1, + "OutputAmplitudeTargetRx7":1, + "OutputAmplitudeTargetRx8":1 + } + } + } + } + } +} From 4d179563c6851721073a8d757093b770f78ba76c Mon Sep 17 00:00:00 2001 From: Anoop Kamath <115578705+AnoopKamath@users.noreply.github.com> Date: Mon, 17 Jul 2023 18:07:08 -0700 Subject: [PATCH 09/32] Fix build fail --- sonic-xcvrd/xcvrd/xcvrd.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sonic-xcvrd/xcvrd/xcvrd.py b/sonic-xcvrd/xcvrd/xcvrd.py index 0dbd9f73d..eb562adc9 100644 --- a/sonic-xcvrd/xcvrd/xcvrd.py +++ b/sonic-xcvrd/xcvrd/xcvrd.py @@ -834,7 +834,7 @@ def get_optics_si_settings_value(physical_port, lane_speed, transceiver_dict): if key in optics_si_dict[SPEED_KEY]: key_dict = optics_si_dict[SPEED_KEY] return key_dict[key] - elif vendor_name_str in optics_si_dict[SPEED_KEY]: + elif vendor_name_str in optics_si_dict[SPEED_KEY]: key_dict = optics_si_dict[SPEED_KEY] return key_dict[vendor_name_str] elif DEFAULT_KEY in optics_si_dict[SPEED_KEY]: From 5a2bfbfec70b595bcb4ea11628fb732ab698d266 Mon Sep 17 00:00:00 2001 From: Anoop Kamath <115578705+AnoopKamath@users.noreply.github.com> Date: Mon, 17 Jul 2023 18:21:08 -0700 Subject: [PATCH 10/32] Fix build failures --- sonic-xcvrd/xcvrd/xcvrd.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/sonic-xcvrd/xcvrd/xcvrd.py b/sonic-xcvrd/xcvrd/xcvrd.py index eb562adc9..0fe30bba4 100644 --- a/sonic-xcvrd/xcvrd/xcvrd.py +++ b/sonic-xcvrd/xcvrd/xcvrd.py @@ -856,12 +856,12 @@ def get_optics_si_settings_value(physical_port, lane_speed, transceiver_dict): helper_logger.log_error("Error: No values for physical port '{}'".format(physical_port)) return {} - key_dict = {} + key_dict = {} if SPEED_KEY in optics_si_dict: if key in optics_si_dict[SPEED_KEY]: key_dict = optics_si_dict[SPEED_KEY] return key_dict[key] - elif vendor_name_str in optics_si_dict[SPEED_KEY]: + elif vendor_name_str in optics_si_dict[SPEED_KEY]: key_dict = optics_si_dict[SPEED_KEY] return key_dict[vendor_name_str] elif DEFAULT_KEY in optics_si_dict[SPEED_KEY]: From 51ff947cc2bca066ca10640fe02f508f1a96bafd Mon Sep 17 00:00:00 2001 From: Anoop Kamath <115578705+AnoopKamath@users.noreply.github.com> Date: Mon, 17 Jul 2023 23:24:30 -0700 Subject: [PATCH 11/32] fix build failures --- sonic-xcvrd/xcvrd/xcvrd.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/sonic-xcvrd/xcvrd/xcvrd.py b/sonic-xcvrd/xcvrd/xcvrd.py index 0fe30bba4..41736559c 100644 --- a/sonic-xcvrd/xcvrd/xcvrd.py +++ b/sonic-xcvrd/xcvrd/xcvrd.py @@ -1650,7 +1650,7 @@ def task_worker(self): self.port_dict[lport]['cmis_state'] = self.CMIS_STATE_READY continue self.log_notice("{}: force Datapath reinit".format(lport)) - self.port_dict[lport]['optics_si_validated'] = False + self.port_dict[lport]['optics_si_validated'] = False self.port_dict[lport]['cmis_state'] = self.CMIS_STATE_DP_DEINIT elif state == self.CMIS_STATE_DP_DEINIT: # D.2.2 Software Deinitialization @@ -1725,7 +1725,7 @@ def task_worker(self): self.log_notice("{} waiting for host tx ready...".format(lport)) continue - optics_si_dict = {} + optics_si_dict = {} if not self.port_dict[lport]['optics_si_validated'] and g_optics_si_dict: # Apply module SI settings if applicable lane_speed = int(speed/1000)//host_lane_count From c52c86689caf3ef29a25c0391d18499ee9981307 Mon Sep 17 00:00:00 2001 From: Anoop Kamath <115578705+AnoopKamath@users.noreply.github.com> Date: Mon, 17 Jul 2023 23:45:22 -0700 Subject: [PATCH 12/32] fix build failures --- sonic-xcvrd/xcvrd/xcvrd.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sonic-xcvrd/xcvrd/xcvrd.py b/sonic-xcvrd/xcvrd/xcvrd.py index 41736559c..2b8401780 100644 --- a/sonic-xcvrd/xcvrd/xcvrd.py +++ b/sonic-xcvrd/xcvrd/xcvrd.py @@ -1505,7 +1505,7 @@ def task_worker(self): if 'admin_status' not in self.port_dict[lport]: self.port_dict[lport]['admin_status'] = self.get_port_admin_status(lport) - if 'optics_si_validated' not in self.port_dict[lport]: + if 'optics_si_validated' not in self.port_dict[lport]: self.port_dict[lport]['optics_si_validated'] = False pport = int(info.get('index', "-1")) From 47d5a6175f2075071850f55e8c32020a30e4f211 Mon Sep 17 00:00:00 2001 From: Anoop Kamath <115578705+AnoopKamath@users.noreply.github.com> Date: Tue, 18 Jul 2023 00:02:36 -0700 Subject: [PATCH 13/32] Fix build failures --- sonic-xcvrd/xcvrd/xcvrd.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/sonic-xcvrd/xcvrd/xcvrd.py b/sonic-xcvrd/xcvrd/xcvrd.py index 2b8401780..8b3dfdea1 100644 --- a/sonic-xcvrd/xcvrd/xcvrd.py +++ b/sonic-xcvrd/xcvrd/xcvrd.py @@ -2515,7 +2515,7 @@ def load_optics_si_settings(self): self.log_info("xcvrd: No optics SI file exists") return {} - with open(optics_si_settings_file_path, "r") as optics_si_file: + with open(optics_si_settings_file_path, "r") as optics_si_file: g_optics_si_dict = json.load(optics_si_file) # Initialize daemon @@ -2562,7 +2562,7 @@ def init(self): self.log_info("Skip loading media_settings.json and optics_si_settings.json in case of fast-reboot") else: self.load_media_settings() - self.load_optics_si_settings() + self.load_optics_si_settings() # Make sure this daemon started after all port configured self.log_notice("XCVRD INIT: Wait for port config is done") From 813b62f1296a7e500052d8b6ed352db7b4798e32 Mon Sep 17 00:00:00 2001 From: Anoop Kamath <115578705+AnoopKamath@users.noreply.github.com> Date: Tue, 25 Jul 2023 04:47:59 -0700 Subject: [PATCH 14/32] Update xcvrd.py --- sonic-xcvrd/xcvrd/xcvrd.py | 91 ++++++++++++++++++++++---------------- 1 file changed, 53 insertions(+), 38 deletions(-) diff --git a/sonic-xcvrd/xcvrd/xcvrd.py b/sonic-xcvrd/xcvrd/xcvrd.py index 00ff40276..662608e99 100644 --- a/sonic-xcvrd/xcvrd/xcvrd.py +++ b/sonic-xcvrd/xcvrd/xcvrd.py @@ -792,7 +792,7 @@ def notify_media_setting(logical_port_name, transceiver_dict, app_port_tbl.set(port_name, fvs) -def get_optics_si_settings_value(physical_port, lane_speed, transceiver_dict): +def get_optics_si_settings_value(physical_port, lane_speed, key, vendor_name_str): GLOBAL_MEDIA_SETTINGS_KEY = 'GLOBAL_MEDIA_SETTINGS' PORT_MEDIA_SETTINGS_KEY = 'PORT_MEDIA_SETTINGS' DEFAULT_KEY = 'Default' @@ -802,10 +802,6 @@ def get_optics_si_settings_value(physical_port, lane_speed, transceiver_dict): default_dict = {} optics_si_dict = {} - vendor_name_str = transceiver_dict['manufacturer'].upper().strip() - vendor_pn_str = transceiver_dict['model'].upper().strip() - key = vendor_name_str + '-' + vendor_pn_str - # Keys under global media settings can be a list or range or list of ranges # of physical port numbers. Below are some examples # 1-32 @@ -872,11 +868,33 @@ def get_optics_si_settings_value(physical_port, lane_speed, transceiver_dict): return default_dict +def get_module_vendor_key(physical_port): + sfp = platform_chassis.get_sfp(physical_port) + if not sfp.get_presence(): + helper_logger.log_info("Module {} presence not detected during notify".format(physical_port)) + return None + + api = sfp.get_xcvr_api() + if api is None: + helper_logger.log_info("Module {} xcvrd api not found".format(physical_port)) + return None + + vendor_name = api.get_manufacturer() + if vendor_name is None: + helper_logger.log_info("Module {} vendor name not found".format(physical_port)) + return None + + vendor_sn = api.get_model() + if vendor_sn is None: + helper_logger.log_info("Module {} vendor serial number not found".format(physical_port)) + return None + + return vendor_name.upper().strip() + '-' + vendor_sn.upper().strip(), vendor_name.upper().strip() + def fetch_optics_si_setting(logical_port_name, lane_speed, port_mapping): if not g_optics_si_dict: return - transceiver_dict = {} optics_si = {} physical_port_list = port_mapping.logical_port_name_to_physical_port_list(logical_port_name) @@ -888,14 +906,13 @@ def fetch_optics_si_setting(logical_port_name, lane_speed, port_mapping): if not _wrapper_get_presence(physical_port): helper_logger.log_info("Module {} presence not detected during notify".format(physical_port)) continue - port_info_dict = _wrapper_get_transceiver_info(physical_port) - if port_info_dict is not None: - transceiver_dict[physical_port] = port_info_dict - if physical_port not in transceiver_dict: - helper_logger.log_error("Module {} eeprom not populated in transceiver dict".format(physical_port)) + + vendor_key, vendor_name = get_module_vendor_key(physical_port) + if vendor_key is None: + helper_logger.log_error("Error: No Vendor Key found for port '{}'".format(logical_port_name)) continue - optics_si = get_optics_si_settings_value(physical_port, lane_speed, transceiver_dict[physical_port]) + optics_si = get_optics_si_settings_value(physical_port, lane_speed, vendor_key, vendor_name) return optics_si @@ -1702,6 +1719,7 @@ def task_worker(self): self.port_dict[lport]['cmis_expired'] = now + datetime.timedelta(seconds = max(modulePwrUpDuration, dpDeinitDuration)) elif state == self.CMIS_STATE_AP_CONF: + ec = 0 # TODO: Use fine grained time when the CMIS memory map is available if not self.check_module_state(api, ['ModuleReady']): if (expired is not None) and (expired <= now): @@ -1724,9 +1742,23 @@ def task_worker(self): else: self.log_notice("{} configured laser frequency {} GHz".format(lport, freq)) + # Stage custom SI settings + optics_si_dict = {} + if g_optics_si_dict: + # Apply module SI settings if applicable + lane_speed = int(speed/1000)//host_lane_count + optics_si_dict = fetch_optics_si_setting(lport, lane_speed, self.port_mapping) + + if optics_si_dict: + self.log_notice("{}: Optics SI found. Apply".format(lport)) + api.stage_custom_si_settings(host_lanes_mask, optics_si_dict) + #Set Explicit control bit to apply Custom Host SI settings + ec = 1 + # D.1.3 Software Configuration and Initialization - if not api.set_application(host_lanes_mask, appl): - self.log_notice("{}: unable to set application".format(lport)) + api.set_application(host_lanes_mask, appl, ec) + if not api.stage_datapath_init(host_lanes_mask): + self.log_notice("{}: unable to set application and stage DP init".format(lport)) self.force_cmis_reinit(lport, retries + 1) continue @@ -1755,29 +1787,12 @@ def task_worker(self): self.log_notice("{} waiting for host tx ready...".format(lport)) continue - optics_si_dict = {} - if not self.port_dict[lport]['optics_si_validated'] and g_optics_si_dict: - # Apply module SI settings if applicable - lane_speed = int(speed/1000)//host_lane_count - optics_si_dict = fetch_optics_si_setting(lport, lane_speed, self.port_mapping) - - if optics_si_dict: - self.log_notice("{}: Optics SI found. Apply".format(lport)) - if not api.set_module_si_settings(host_lanes_mask, appl, optics_si_dict): - self.log_notice("{}: unable to apply SI settings and set application".format(lport)) - self.force_cmis_reinit(lport, retries + 1) - continue - - # Recheck config errors - self.port_dict[lport]['optics_si_validated'] = True - self.port_dict[lport]['cmis_state'] = self.CMIS_STATE_DP_INIT - else: - # D.1.3 Software Configuration and Initialization - api.set_datapath_init(host_lanes_mask) - dpInitDuration = self.get_cmis_dp_init_duration_secs(api) - self.log_notice("{}: DpInit duration {} secs".format(lport, dpInitDuration)) - self.port_dict[lport]['cmis_expired'] = now + datetime.timedelta(seconds=dpInitDuration) - self.port_dict[lport]['cmis_state'] = self.CMIS_STATE_DP_TXON + # D.1.3 Software Configuration and Initialization + api.set_datapath_init(host_lanes_mask) + dpInitDuration = self.get_cmis_dp_init_duration_secs(api) + self.log_notice("{}: DpInit duration {} secs".format(lport, dpInitDuration)) + self.port_dict[lport]['cmis_expired'] = now + datetime.timedelta(seconds=dpInitDuration) + self.port_dict[lport]['cmis_state'] = self.CMIS_STATE_DP_TXON elif state == self.CMIS_STATE_DP_TXON: if not self.check_datapath_state(api, host_lanes_mask, ['DataPathInitialized']): if (expired is not None) and (expired <= now): @@ -2543,7 +2558,7 @@ def load_optics_si_settings(self): optics_si_settings_file_path = os.path.join(platform_path, "optics_si_settings.json") if not os.path.isfile(optics_si_settings_file_path): - self.log_info("xcvrd: No optics SI file exists") + self.log_info("No optics SI file exists") return {} with open(optics_si_settings_file_path, "r") as optics_si_file: From 925a91ed631a8d1c1f879c68fcdac21e20ed05fb Mon Sep 17 00:00:00 2001 From: Anoop Kamath <115578705+AnoopKamath@users.noreply.github.com> Date: Tue, 25 Jul 2023 04:51:14 -0700 Subject: [PATCH 15/32] Update xcvrd.py --- sonic-xcvrd/xcvrd/xcvrd.py | 4 ---- 1 file changed, 4 deletions(-) diff --git a/sonic-xcvrd/xcvrd/xcvrd.py b/sonic-xcvrd/xcvrd/xcvrd.py index 662608e99..915174431 100644 --- a/sonic-xcvrd/xcvrd/xcvrd.py +++ b/sonic-xcvrd/xcvrd/xcvrd.py @@ -1552,9 +1552,6 @@ def task_worker(self): if 'admin_status' not in self.port_dict[lport]: self.port_dict[lport]['admin_status'] = self.get_port_admin_status(lport) - if 'optics_si_validated' not in self.port_dict[lport]: - self.port_dict[lport]['optics_si_validated'] = False - pport = int(info.get('index', "-1")) speed = int(info.get('speed', "0")) lanes = info.get('lanes', "").strip() @@ -1697,7 +1694,6 @@ def task_worker(self): self.port_dict[lport]['cmis_state'] = self.CMIS_STATE_READY continue self.log_notice("{}: force Datapath reinit".format(lport)) - self.port_dict[lport]['optics_si_validated'] = False self.port_dict[lport]['cmis_state'] = self.CMIS_STATE_DP_DEINIT elif state == self.CMIS_STATE_DP_DEINIT: # D.2.2 Software Deinitialization From 860933adf468e544d778c712d3b4a3cbb8e717e9 Mon Sep 17 00:00:00 2001 From: Anoop Kamath <115578705+AnoopKamath@users.noreply.github.com> Date: Tue, 25 Jul 2023 04:59:17 -0700 Subject: [PATCH 16/32] Update xcvrd.py --- sonic-xcvrd/xcvrd/xcvrd.py | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/sonic-xcvrd/xcvrd/xcvrd.py b/sonic-xcvrd/xcvrd/xcvrd.py index 915174431..3aa66e54e 100644 --- a/sonic-xcvrd/xcvrd/xcvrd.py +++ b/sonic-xcvrd/xcvrd/xcvrd.py @@ -1747,7 +1747,11 @@ def task_worker(self): if optics_si_dict: self.log_notice("{}: Optics SI found. Apply".format(lport)) - api.stage_custom_si_settings(host_lanes_mask, optics_si_dict) + if not api.stage_custom_si_settings(host_lanes_mask, optics_si_dict): + self.log_notice("{}: unable to stage custom SI settings ".format(lport)) + self.force_cmis_reinit(lport, retries + 1) + continue + #Set Explicit control bit to apply Custom Host SI settings ec = 1 From 0005bc05dcf072f884a784e0a5c5c7c4c5cdf402 Mon Sep 17 00:00:00 2001 From: Anoop Kamath <115578705+AnoopKamath@users.noreply.github.com> Date: Tue, 25 Jul 2023 10:17:24 -0700 Subject: [PATCH 17/32] Update xcvrd.py --- sonic-xcvrd/xcvrd/xcvrd.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sonic-xcvrd/xcvrd/xcvrd.py b/sonic-xcvrd/xcvrd/xcvrd.py index 3aa66e54e..7f5204584 100644 --- a/sonic-xcvrd/xcvrd/xcvrd.py +++ b/sonic-xcvrd/xcvrd/xcvrd.py @@ -907,7 +907,7 @@ def fetch_optics_si_setting(logical_port_name, lane_speed, port_mapping): helper_logger.log_info("Module {} presence not detected during notify".format(physical_port)) continue - vendor_key, vendor_name = get_module_vendor_key(physical_port) + vendor_key, vendor_name = get_module_vendor_key(physical_port) if vendor_key is None: helper_logger.log_error("Error: No Vendor Key found for port '{}'".format(logical_port_name)) continue From cce60bf61ce6968cc12cfe0b853fac7c62306b06 Mon Sep 17 00:00:00 2001 From: Anoop Kamath <115578705+AnoopKamath@users.noreply.github.com> Date: Tue, 25 Jul 2023 15:17:13 -0700 Subject: [PATCH 18/32] Update test_xcvrd.py --- sonic-xcvrd/tests/test_xcvrd.py | 18 +++++++++++++----- 1 file changed, 13 insertions(+), 5 deletions(-) diff --git a/sonic-xcvrd/tests/test_xcvrd.py b/sonic-xcvrd/tests/test_xcvrd.py index e5734e7c8..364cc4934 100644 --- a/sonic-xcvrd/tests/test_xcvrd.py +++ b/sonic-xcvrd/tests/test_xcvrd.py @@ -496,17 +496,25 @@ def test_fetch_optics_si_setting_with_port(self): @patch('xcvrd.xcvrd_utilities.port_mapping.PortMapping.logical_port_name_to_physical_port_list', MagicMock(return_value=[0])) @patch('xcvrd.xcvrd._wrapper_get_presence', MagicMock(return_value=True)) - @patch('xcvrd.xcvrd._wrapper_get_transceiver_info', MagicMock(return_value={'type': 'QSFP-DD Double Density 8X Pluggable Transceiver', - 'vendor_rev': '0.5', - 'serial': '0.7', - 'manufacturer': 'Credo', - 'model': 'CAC82X321M2MC0HW'})) + @patch('xcvrd.xcvrd.get_module_vendor_key', MagicMock(return_value=('CREDO-CAC82X321M','CREDO'))) def _check_fetch_optics_si_setting(self, index): logical_port_name = 'Ethernet0' port_mapping = PortMapping() lane_speed = 100 fetch_optics_si_setting(logical_port_name, lane_speed, port_mapping) + @patch('xcvrd.xcvrd.platform_chassis') + def test_get_module_vendor_key(self, mock_chassis): + mock_sfp = MagicMock() + mock_xcvr_api = MagicMock() + mock_sfp.get_presence = MagicMock(return_value=True) + mock_sfp.get_xcvr_api = MagicMock(return_value=mock_xcvr_api) + mock_chassis.get_sfp = MagicMock(return_value=mock_sfp) + mock_xcvr_api.get_manufacturer = MagicMock(return_value='Credo ') + mock_xcvr_api.get_model = MagicMock(return_value='CAC82X321HW') + result = get_module_vendor_key(1) + assert result == ('CREDO-CAC82X321HW','CREDO') + def test_detect_port_in_error_status(self): class MockTable: def get(self, key): From 6eb7da03d4ea047bb1379343cbd2b0c4284894f9 Mon Sep 17 00:00:00 2001 From: Anoop Kamath <115578705+AnoopKamath@users.noreply.github.com> Date: Tue, 25 Jul 2023 23:35:47 -0700 Subject: [PATCH 19/32] Address review comments: Pass pport instead of lport --- sonic-xcvrd/xcvrd/xcvrd.py | 29 ++++++++++------------------- 1 file changed, 10 insertions(+), 19 deletions(-) diff --git a/sonic-xcvrd/xcvrd/xcvrd.py b/sonic-xcvrd/xcvrd/xcvrd.py index 7f5204584..53842ef46 100644 --- a/sonic-xcvrd/xcvrd/xcvrd.py +++ b/sonic-xcvrd/xcvrd/xcvrd.py @@ -891,30 +891,21 @@ def get_module_vendor_key(physical_port): return vendor_name.upper().strip() + '-' + vendor_sn.upper().strip(), vendor_name.upper().strip() -def fetch_optics_si_setting(logical_port_name, lane_speed, port_mapping): +def fetch_optics_si_setting(physical_port, lane_speed): if not g_optics_si_dict: return optics_si = {} - physical_port_list = port_mapping.logical_port_name_to_physical_port_list(logical_port_name) - if physical_port_list is None: - helper_logger.log_error("Error: No physical ports found for logical port '{}'".format(logical_port_name)) - return PHYSICAL_PORT_NOT_EXIST - - for physical_port in physical_port_list: - if not _wrapper_get_presence(physical_port): - helper_logger.log_info("Module {} presence not detected during notify".format(physical_port)) - continue - - vendor_key, vendor_name = get_module_vendor_key(physical_port) - if vendor_key is None: - helper_logger.log_error("Error: No Vendor Key found for port '{}'".format(logical_port_name)) - continue - - optics_si = get_optics_si_settings_value(physical_port, lane_speed, vendor_key, vendor_name) - + if not _wrapper_get_presence(physical_port): + helper_logger.log_info("Module {} presence not detected during notify".format(physical_port)) + return optics_si + vendor_key, vendor_name = get_module_vendor_key(physical_port) + if vendor_key is None: + helper_logger.log_error("Error: No Vendor Key found for port '{}'".format(logical_port_name)) return optics_si + optics_si = get_optics_si_settings_value(physical_port, lane_speed, vendor_key, vendor_name) + return optics_si def waiting_time_compensation_with_sleep(time_start, time_to_wait): time_now = time.time() @@ -1743,7 +1734,7 @@ def task_worker(self): if g_optics_si_dict: # Apply module SI settings if applicable lane_speed = int(speed/1000)//host_lane_count - optics_si_dict = fetch_optics_si_setting(lport, lane_speed, self.port_mapping) + optics_si_dict = fetch_optics_si_setting(pport, lane_speed) if optics_si_dict: self.log_notice("{}: Optics SI found. Apply".format(lport)) From 140d7c1efd3c5c0232e19a4f420c27ebdb2de497 Mon Sep 17 00:00:00 2001 From: Anoop Kamath <115578705+AnoopKamath@users.noreply.github.com> Date: Tue, 25 Jul 2023 23:42:27 -0700 Subject: [PATCH 20/32] Update test_xcvrd.py --- sonic-xcvrd/tests/test_xcvrd.py | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/sonic-xcvrd/tests/test_xcvrd.py b/sonic-xcvrd/tests/test_xcvrd.py index 364cc4934..a2f89995a 100644 --- a/sonic-xcvrd/tests/test_xcvrd.py +++ b/sonic-xcvrd/tests/test_xcvrd.py @@ -494,14 +494,12 @@ def test_fetch_optics_si_setting_with_comma(self): def test_fetch_optics_si_setting_with_port(self): self._check_fetch_optics_si_setting(1) - @patch('xcvrd.xcvrd_utilities.port_mapping.PortMapping.logical_port_name_to_physical_port_list', MagicMock(return_value=[0])) @patch('xcvrd.xcvrd._wrapper_get_presence', MagicMock(return_value=True)) @patch('xcvrd.xcvrd.get_module_vendor_key', MagicMock(return_value=('CREDO-CAC82X321M','CREDO'))) def _check_fetch_optics_si_setting(self, index): - logical_port_name = 'Ethernet0' - port_mapping = PortMapping() + port = 1 lane_speed = 100 - fetch_optics_si_setting(logical_port_name, lane_speed, port_mapping) + fetch_optics_si_setting(port, lane_speed) @patch('xcvrd.xcvrd.platform_chassis') def test_get_module_vendor_key(self, mock_chassis): From 9f8bca9baa8a833c0aa90c4b915f8988397a2f51 Mon Sep 17 00:00:00 2001 From: Anoop Kamath <115578705+AnoopKamath@users.noreply.github.com> Date: Wed, 26 Jul 2023 00:48:54 -0700 Subject: [PATCH 21/32] remove whitespaces --- sonic-xcvrd/xcvrd/xcvrd.py | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/sonic-xcvrd/xcvrd/xcvrd.py b/sonic-xcvrd/xcvrd/xcvrd.py index 53842ef46..4080f48cd 100644 --- a/sonic-xcvrd/xcvrd/xcvrd.py +++ b/sonic-xcvrd/xcvrd/xcvrd.py @@ -807,7 +807,7 @@ def get_optics_si_settings_value(physical_port, lane_speed, key, vendor_name_str # 1-32 # 1,2,3,4,5 # 1-4,9-12 - + if GLOBAL_MEDIA_SETTINGS_KEY in g_optics_si_dict: for keys in g_optics_si_dict[GLOBAL_MEDIA_SETTINGS_KEY]: if COMMA_SEPARATOR in keys: @@ -838,7 +838,7 @@ def get_optics_si_settings_value(physical_port, lane_speed, key, vendor_name_str default_dict = key_dict[DEFAULT_KEY] optics_si_dict = {} - + if PORT_MEDIA_SETTINGS_KEY in g_optics_si_dict: for keys in g_optics_si_dict[PORT_MEDIA_SETTINGS_KEY]: if int(keys) == physical_port: @@ -1745,9 +1745,9 @@ def task_worker(self): #Set Explicit control bit to apply Custom Host SI settings ec = 1 - + # D.1.3 Software Configuration and Initialization - api.set_application(host_lanes_mask, appl, ec) + api.set_application(host_lanes_mask, appl, ec) if not api.stage_datapath_init(host_lanes_mask): self.log_notice("{}: unable to set application and stage DP init".format(lport)) self.force_cmis_reinit(lport, retries + 1) @@ -2554,7 +2554,7 @@ def load_optics_si_settings(self): with open(optics_si_settings_file_path, "r") as optics_si_file: g_optics_si_dict = json.load(optics_si_file) - + # Initialize daemon def init(self): global platform_sfputil From ae8900e3488861a794cfe4377a3fc3ad6ce00c95 Mon Sep 17 00:00:00 2001 From: Anoop Kamath <115578705+AnoopKamath@users.noreply.github.com> Date: Fri, 11 Aug 2023 12:25:28 -0700 Subject: [PATCH 22/32] Update xcvrd.py --- sonic-xcvrd/xcvrd/xcvrd.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sonic-xcvrd/xcvrd/xcvrd.py b/sonic-xcvrd/xcvrd/xcvrd.py index 4080f48cd..5e40f8292 100644 --- a/sonic-xcvrd/xcvrd/xcvrd.py +++ b/sonic-xcvrd/xcvrd/xcvrd.py @@ -1748,7 +1748,7 @@ def task_worker(self): # D.1.3 Software Configuration and Initialization api.set_application(host_lanes_mask, appl, ec) - if not api.stage_datapath_init(host_lanes_mask): + if not api.scs_apply_datapath_init(host_lanes_mask): self.log_notice("{}: unable to set application and stage DP init".format(lport)) self.force_cmis_reinit(lport, retries + 1) continue From ee32e2e5c0c5aca902d3e8f595d76d4972b77aca Mon Sep 17 00:00:00 2001 From: Anoop Kamath <115578705+AnoopKamath@users.noreply.github.com> Date: Mon, 14 Aug 2023 17:31:56 -0700 Subject: [PATCH 23/32] Create optics_si_parser file --- sonic-xcvrd/xcvrd/xcvrd.py | 134 ++----------------------------------- 1 file changed, 4 insertions(+), 130 deletions(-) diff --git a/sonic-xcvrd/xcvrd/xcvrd.py b/sonic-xcvrd/xcvrd/xcvrd.py index 5e40f8292..aa1483426 100644 --- a/sonic-xcvrd/xcvrd/xcvrd.py +++ b/sonic-xcvrd/xcvrd/xcvrd.py @@ -792,121 +792,6 @@ def notify_media_setting(logical_port_name, transceiver_dict, app_port_tbl.set(port_name, fvs) -def get_optics_si_settings_value(physical_port, lane_speed, key, vendor_name_str): - GLOBAL_MEDIA_SETTINGS_KEY = 'GLOBAL_MEDIA_SETTINGS' - PORT_MEDIA_SETTINGS_KEY = 'PORT_MEDIA_SETTINGS' - DEFAULT_KEY = 'Default' - SPEED_KEY = str(lane_speed) + 'G_SPEED' - RANGE_SEPARATOR = '-' - COMMA_SEPARATOR = ',' - default_dict = {} - optics_si_dict = {} - - # Keys under global media settings can be a list or range or list of ranges - # of physical port numbers. Below are some examples - # 1-32 - # 1,2,3,4,5 - # 1-4,9-12 - - if GLOBAL_MEDIA_SETTINGS_KEY in g_optics_si_dict: - for keys in g_optics_si_dict[GLOBAL_MEDIA_SETTINGS_KEY]: - if COMMA_SEPARATOR in keys: - port_list = keys.split(COMMA_SEPARATOR) - for port in port_list: - if RANGE_SEPARATOR in port: - if check_port_in_range(port, physical_port): - optics_si_dict = g_optics_si_dict[GLOBAL_MEDIA_SETTINGS_KEY][keys] - break - elif str(physical_port) == port: - optics_si_dict = g_optics_si_dict[GLOBAL_MEDIA_SETTINGS_KEY][keys] - break - - elif RANGE_SEPARATOR in keys: - if check_port_in_range(keys, physical_port): - optics_si_dict = g_optics_si_dict[GLOBAL_MEDIA_SETTINGS_KEY][keys] - - key_dict = {} - if SPEED_KEY in optics_si_dict: - if key in optics_si_dict[SPEED_KEY]: - key_dict = optics_si_dict[SPEED_KEY] - return key_dict[key] - elif vendor_name_str in optics_si_dict[SPEED_KEY]: - key_dict = optics_si_dict[SPEED_KEY] - return key_dict[vendor_name_str] - elif DEFAULT_KEY in optics_si_dict[SPEED_KEY]: - key_dict = optics_si_dict[SPEED_KEY] - default_dict = key_dict[DEFAULT_KEY] - - optics_si_dict = {} - - if PORT_MEDIA_SETTINGS_KEY in g_optics_si_dict: - for keys in g_optics_si_dict[PORT_MEDIA_SETTINGS_KEY]: - if int(keys) == physical_port: - optics_si_dict = g_optics_si_dict[PORT_MEDIA_SETTINGS_KEY][keys] - break - - if len(optics_si_dict) == 0: - if len(default_dict) != 0: - return default_dict - else: - helper_logger.log_error("Error: No values for physical port '{}'".format(physical_port)) - return {} - - key_dict = {} - if SPEED_KEY in optics_si_dict: - if key in optics_si_dict[SPEED_KEY]: - key_dict = optics_si_dict[SPEED_KEY] - return key_dict[key] - elif vendor_name_str in optics_si_dict[SPEED_KEY]: - key_dict = optics_si_dict[SPEED_KEY] - return key_dict[vendor_name_str] - elif DEFAULT_KEY in optics_si_dict[SPEED_KEY]: - key_dict = optics_si_dict[SPEED_KEY] - default_dict = key_dict[DEFAULT_KEY] - elif len(default_dict) != 0: - return default_dict - - return default_dict - -def get_module_vendor_key(physical_port): - sfp = platform_chassis.get_sfp(physical_port) - if not sfp.get_presence(): - helper_logger.log_info("Module {} presence not detected during notify".format(physical_port)) - return None - - api = sfp.get_xcvr_api() - if api is None: - helper_logger.log_info("Module {} xcvrd api not found".format(physical_port)) - return None - - vendor_name = api.get_manufacturer() - if vendor_name is None: - helper_logger.log_info("Module {} vendor name not found".format(physical_port)) - return None - - vendor_sn = api.get_model() - if vendor_sn is None: - helper_logger.log_info("Module {} vendor serial number not found".format(physical_port)) - return None - - return vendor_name.upper().strip() + '-' + vendor_sn.upper().strip(), vendor_name.upper().strip() - -def fetch_optics_si_setting(physical_port, lane_speed): - if not g_optics_si_dict: - return - - optics_si = {} - - if not _wrapper_get_presence(physical_port): - helper_logger.log_info("Module {} presence not detected during notify".format(physical_port)) - return optics_si - vendor_key, vendor_name = get_module_vendor_key(physical_port) - if vendor_key is None: - helper_logger.log_error("Error: No Vendor Key found for port '{}'".format(logical_port_name)) - return optics_si - optics_si = get_optics_si_settings_value(physical_port, lane_speed, vendor_key, vendor_name) - return optics_si - def waiting_time_compensation_with_sleep(time_start, time_to_wait): time_now = time.time() time_diff = time_now - time_start @@ -1706,6 +1591,7 @@ def task_worker(self): self.port_dict[lport]['cmis_expired'] = now + datetime.timedelta(seconds = max(modulePwrUpDuration, dpDeinitDuration)) elif state == self.CMIS_STATE_AP_CONF: + # Explicit control bit to apply custom Host SI settings ec = 0 # TODO: Use fine grained time when the CMIS memory map is available if not self.check_module_state(api, ['ModuleReady']): @@ -1731,10 +1617,10 @@ def task_worker(self): # Stage custom SI settings optics_si_dict = {} - if g_optics_si_dict: + if optics_si_parser.optics_si_present(): # Apply module SI settings if applicable lane_speed = int(speed/1000)//host_lane_count - optics_si_dict = fetch_optics_si_setting(pport, lane_speed) + optics_si_dict = optics_si_parser.fetch_optics_si_setting(pport, lane_speed) if optics_si_dict: self.log_notice("{}: Optics SI found. Apply".format(lport)) @@ -1743,7 +1629,7 @@ def task_worker(self): self.force_cmis_reinit(lport, retries + 1) continue - #Set Explicit control bit to apply Custom Host SI settings + # Set Explicit control bit to apply Custom Host SI settings ec = 1 # D.1.3 Software Configuration and Initialization @@ -2543,18 +2429,6 @@ def load_media_settings(self): with open(media_settings_file_path, "r") as media_file: g_dict = json.load(media_file) - def load_optics_si_settings(self): - global g_optics_si_dict - (platform_path, _) = device_info.get_paths_to_platform_and_hwsku_dirs() - - optics_si_settings_file_path = os.path.join(platform_path, "optics_si_settings.json") - if not os.path.isfile(optics_si_settings_file_path): - self.log_info("No optics SI file exists") - return {} - - with open(optics_si_settings_file_path, "r") as optics_si_file: - g_optics_si_dict = json.load(optics_si_file) - # Initialize daemon def init(self): global platform_sfputil From 814cc4dc54510c2cbd6438de8c9893970f62a40a Mon Sep 17 00:00:00 2001 From: Anoop Kamath <115578705+AnoopKamath@users.noreply.github.com> Date: Mon, 14 Aug 2023 17:40:06 -0700 Subject: [PATCH 24/32] Create optics_si_parser.py --- .../xcvrd/xcvrd_utilities/optics_si_parser.py | 149 ++++++++++++++++++ 1 file changed, 149 insertions(+) create mode 100644 sonic-xcvrd/xcvrd/xcvrd_utilities/optics_si_parser.py diff --git a/sonic-xcvrd/xcvrd/xcvrd_utilities/optics_si_parser.py b/sonic-xcvrd/xcvrd/xcvrd_utilities/optics_si_parser.py new file mode 100644 index 000000000..4d6d5d8ad --- /dev/null +++ b/sonic-xcvrd/xcvrd/xcvrd_utilities/optics_si_parser.py @@ -0,0 +1,149 @@ +import json +import os +import sonic_platform.platform +import sonic_platform_base.sonic_sfp.sfputilhelper +platform_chassis = sonic_platform.platform.Platform().get_chassis() + +from sonic_py_common import daemon_base, device_info, logger +from xcvrd.xcvrd_utilities import sfp_status_helper +from xcvrd.xcvrd_utilities import port_mapping +from xcvrd import xcvrd + +g_optics_si_dict = {} + +SYSLOG_IDENTIFIER = "xcvrd" +helper_logger = logger.Logger(SYSLOG_IDENTIFIER) + +def get_optics_si_settings_value(physical_port, lane_speed, key, vendor_name_str): + GLOBAL_MEDIA_SETTINGS_KEY = 'GLOBAL_MEDIA_SETTINGS' + PORT_MEDIA_SETTINGS_KEY = 'PORT_MEDIA_SETTINGS' + DEFAULT_KEY = 'Default' + SPEED_KEY = str(lane_speed) + 'G_SPEED' + RANGE_SEPARATOR = '-' + COMMA_SEPARATOR = ',' + default_dict = {} + optics_si_dict = {} + + # Keys under global media settings can be a list or range or list of ranges + # of physical port numbers. Below are some examples + # 1-32 + # 1,2,3,4,5 + # 1-4,9-12 + + if GLOBAL_MEDIA_SETTINGS_KEY in g_optics_si_dict: + for keys in g_optics_si_dict[GLOBAL_MEDIA_SETTINGS_KEY]: + if COMMA_SEPARATOR in keys: + port_list = keys.split(COMMA_SEPARATOR) + for port in port_list: + if RANGE_SEPARATOR in port: + if xcvrd.check_port_in_range(port, physical_port): + optics_si_dict = g_optics_si_dict[GLOBAL_MEDIA_SETTINGS_KEY][keys] + break + elif str(physical_port) == port: + optics_si_dict = g_optics_si_dict[GLOBAL_MEDIA_SETTINGS_KEY][keys] + break + + elif RANGE_SEPARATOR in keys: + if xcvrd.check_port_in_range(keys, physical_port): + optics_si_dict = g_optics_si_dict[GLOBAL_MEDIA_SETTINGS_KEY][keys] + + key_dict = {} + if SPEED_KEY in optics_si_dict: + if key in optics_si_dict[SPEED_KEY]: + key_dict = optics_si_dict[SPEED_KEY] + return key_dict[key] + elif vendor_name_str in optics_si_dict[SPEED_KEY]: + key_dict = optics_si_dict[SPEED_KEY] + return key_dict[vendor_name_str] + elif DEFAULT_KEY in optics_si_dict[SPEED_KEY]: + key_dict = optics_si_dict[SPEED_KEY] + default_dict = key_dict[DEFAULT_KEY] + + optics_si_dict = {} + + if PORT_MEDIA_SETTINGS_KEY in g_optics_si_dict: + for keys in g_optics_si_dict[PORT_MEDIA_SETTINGS_KEY]: + if int(keys) == physical_port: + optics_si_dict = g_optics_si_dict[PORT_MEDIA_SETTINGS_KEY][keys] + break + if len(optics_si_dict) == 0: + if len(default_dict) != 0: + return default_dict + else: + helper_logger.log_error("Error: No values for physical port '{}'".format(physical_port)) + return {} + + key_dict = {} + if SPEED_KEY in optics_si_dict: + if key in optics_si_dict[SPEED_KEY]: + key_dict = optics_si_dict[SPEED_KEY] + return key_dict[key] + elif vendor_name_str in optics_si_dict[SPEED_KEY]: + key_dict = optics_si_dict[SPEED_KEY] + return key_dict[vendor_name_str] + elif DEFAULT_KEY in optics_si_dict[SPEED_KEY]: + key_dict = optics_si_dict[SPEED_KEY] + default_dict = key_dict[DEFAULT_KEY] + elif len(default_dict) != 0: + return default_dict + + return default_dict + +def get_module_vendor_key(physical_port): + sfp = platform_chassis.get_sfp(physical_port) + if not sfp.get_presence(): + helper_logger.log_info("Module {} presence not detected during notify".format(physical_port)) + return None + + api = sfp.get_xcvr_api() + if api is None: + helper_logger.log_info("Module {} xcvrd api not found".format(physical_port)) + return None + + vendor_name = api.get_manufacturer() + if vendor_name is None: + helper_logger.log_info("Module {} vendor name not found".format(physical_port)) + return None + + vendor_sn = api.get_model() + if vendor_sn is None: + helper_logger.log_info("Module {} vendor serial number not found".format(physical_port)) + return None + + return vendor_name.upper().strip() + '-' + vendor_sn.upper().strip(), vendor_name.upper().strip() + +def fetch_optics_si_setting(physical_port, lane_speed): + if not g_optics_si_dict: + return + + optics_si = {} + + if not xcvrd._wrapper_get_presence(physical_port): + helper_logger.log_info("Module {} presence not detected during notify".format(physical_port)) + return optics_si + vendor_key, vendor_name = get_module_vendor_key(physical_port) + if vendor_key is None: + helper_logger.log_error("Error: No Vendor Key found for port '{}'".format(logical_port_name)) + return optics_si + optics_si = get_optics_si_settings_value(physical_port, lane_speed, vendor_key, vendor_name) + return optics_si + +def load_optics_si_settings(): + global g_optics_si_dict + (platform_path, _) = device_info.get_paths_to_platform_and_hwsku_dirs() + + helper_logger.log_error("ANOOP parse optics json file {}".format(platform_path)) + optics_si_settings_file_path = os.path.join(platform_path, "optics_si_settings.json") + if not os.path.isfile(optics_si_settings_file_path): + helper_logger.log_error("No optics SI file exists") + return {} + + with open(optics_si_settings_file_path, "r") as optics_si_file: + g_optics_si_dict = json.load(optics_si_file) + helper_logger.log_error("ANOOP parsed optics json file {}".format(g_optics_si_dict)) + +def optics_si_present(): + if g_optics_si_dict: + return True + return False + From 1268f44403ed7bc2f366860a66692d0e6b3ec4d6 Mon Sep 17 00:00:00 2001 From: Anoop Kamath <115578705+AnoopKamath@users.noreply.github.com> Date: Mon, 14 Aug 2023 17:45:33 -0700 Subject: [PATCH 25/32] Update xcvrd.py --- sonic-xcvrd/xcvrd/xcvrd.py | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/sonic-xcvrd/xcvrd/xcvrd.py b/sonic-xcvrd/xcvrd/xcvrd.py index aa1483426..0448d3e9d 100644 --- a/sonic-xcvrd/xcvrd/xcvrd.py +++ b/sonic-xcvrd/xcvrd/xcvrd.py @@ -88,7 +88,6 @@ BIAS_UNIT = 'mA' g_dict = {} -g_optics_si_dict = {} # Global platform specific sfputil class instance platform_sfputil = None # Global chassis object based on new platform api @@ -792,6 +791,7 @@ def notify_media_setting(logical_port_name, transceiver_dict, app_port_tbl.set(port_name, fvs) + def waiting_time_compensation_with_sleep(time_start, time_to_wait): time_now = time.time() time_diff = time_now - time_start @@ -1591,8 +1591,11 @@ def task_worker(self): self.port_dict[lport]['cmis_expired'] = now + datetime.timedelta(seconds = max(modulePwrUpDuration, dpDeinitDuration)) elif state == self.CMIS_STATE_AP_CONF: - # Explicit control bit to apply custom Host SI settings + # Explicit control bit to apply custom Host SI settings. + # It will set to 1 and applied via set_application if + # custom SI settings is applicable ec = 0 + # TODO: Use fine grained time when the CMIS memory map is available if not self.check_module_state(api, ['ModuleReady']): if (expired is not None) and (expired <= now): From 3f4c26d4f97820fbb03695e0be4c623724c1f3b5 Mon Sep 17 00:00:00 2001 From: Anoop Kamath <115578705+AnoopKamath@users.noreply.github.com> Date: Mon, 14 Aug 2023 20:17:15 -0700 Subject: [PATCH 26/32] Update test_xcvrd.py --- sonic-xcvrd/tests/test_xcvrd.py | 19 +++++++++---------- 1 file changed, 9 insertions(+), 10 deletions(-) diff --git a/sonic-xcvrd/tests/test_xcvrd.py b/sonic-xcvrd/tests/test_xcvrd.py index a2f89995a..a3adf5823 100644 --- a/sonic-xcvrd/tests/test_xcvrd.py +++ b/sonic-xcvrd/tests/test_xcvrd.py @@ -1,6 +1,7 @@ #from unittest.mock import DEFAULT from xcvrd.xcvrd_utilities.port_mapping import * from xcvrd.xcvrd_utilities.sfp_status_helper import * +from xcvrd.xcvrd_utilities.optics_si_parser import * from xcvrd.xcvrd import * import pytest import copy @@ -478,39 +479,37 @@ def _check_notify_media_setting(self, index): port_mapping.handle_port_change_event(port_change_event) notify_media_setting(logical_port_name, xcvr_info_dict, app_port_tbl, port_mapping) - @patch('xcvrd.xcvrd.g_optics_si_dict', optics_si_settings_dict) + @patch('xcvrd.xcvrd_utilities.optics_si_parser.g_optics_si_dict', optics_si_settings_dict) @patch('xcvrd.xcvrd._wrapper_get_presence', MagicMock(return_value=True)) def test_fetch_optics_si_setting(self): self._check_fetch_optics_si_setting(1) - @patch('xcvrd.xcvrd.g_optics_si_dict', optics_si_settings_with_comma_dict) + @patch('xcvrd.xcvrd_utilities.optics_si_parser.g_optics_si_dict', optics_si_settings_with_comma_dict) @patch('xcvrd.xcvrd._wrapper_get_presence', MagicMock(return_value=True)) def test_fetch_optics_si_setting_with_comma(self): self._check_fetch_optics_si_setting(1) self._check_fetch_optics_si_setting(6) - @patch('xcvrd.xcvrd.g_optics_si_dict', port_optics_si_settings) + @patch('xcvrd.xcvrd_utilities.optics_si_parser.g_optics_si_dict', port_optics_si_settings) @patch('xcvrd.xcvrd._wrapper_get_presence', MagicMock(return_value=True)) def test_fetch_optics_si_setting_with_port(self): self._check_fetch_optics_si_setting(1) @patch('xcvrd.xcvrd._wrapper_get_presence', MagicMock(return_value=True)) - @patch('xcvrd.xcvrd.get_module_vendor_key', MagicMock(return_value=('CREDO-CAC82X321M','CREDO'))) + @patch('xcvrd.xcvrd_utilities.optics_si_parser.get_module_vendor_key', MagicMock(return_value=('CREDO-CAC82X321M','CREDO'))) def _check_fetch_optics_si_setting(self, index): port = 1 lane_speed = 100 - fetch_optics_si_setting(port, lane_speed) + mock_sfp = MagicMock() + optics_si_parser.fetch_optics_si_setting(port, lane_speed, mock_sfp) - @patch('xcvrd.xcvrd.platform_chassis') - def test_get_module_vendor_key(self, mock_chassis): + def test_get_module_vendor_key(self): mock_sfp = MagicMock() mock_xcvr_api = MagicMock() - mock_sfp.get_presence = MagicMock(return_value=True) mock_sfp.get_xcvr_api = MagicMock(return_value=mock_xcvr_api) - mock_chassis.get_sfp = MagicMock(return_value=mock_sfp) mock_xcvr_api.get_manufacturer = MagicMock(return_value='Credo ') mock_xcvr_api.get_model = MagicMock(return_value='CAC82X321HW') - result = get_module_vendor_key(1) + result = get_module_vendor_key(1, mock_sfp) assert result == ('CREDO-CAC82X321HW','CREDO') def test_detect_port_in_error_status(self): From 31cfa6e7a6b228f0aab931a17ef45cd787f7f1b3 Mon Sep 17 00:00:00 2001 From: Anoop Kamath <115578705+AnoopKamath@users.noreply.github.com> Date: Mon, 14 Aug 2023 20:19:26 -0700 Subject: [PATCH 27/32] Update xcvrd.py --- sonic-xcvrd/xcvrd/xcvrd.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/sonic-xcvrd/xcvrd/xcvrd.py b/sonic-xcvrd/xcvrd/xcvrd.py index 0448d3e9d..be37cc346 100644 --- a/sonic-xcvrd/xcvrd/xcvrd.py +++ b/sonic-xcvrd/xcvrd/xcvrd.py @@ -27,6 +27,7 @@ from .xcvrd_utilities import sfp_status_helper from .xcvrd_utilities import port_mapping + from .xcvrd_utilities import optics_si_parser except ImportError as e: raise ImportError(str(e) + " - required module not found") @@ -1623,7 +1624,7 @@ def task_worker(self): if optics_si_parser.optics_si_present(): # Apply module SI settings if applicable lane_speed = int(speed/1000)//host_lane_count - optics_si_dict = optics_si_parser.fetch_optics_si_setting(pport, lane_speed) + optics_si_dict = optics_si_parser.fetch_optics_si_setting(pport, lane_speed, sfp) if optics_si_dict: self.log_notice("{}: Optics SI found. Apply".format(lport)) From 160a2f9b1b49e14de4f57680804c7c56ebd10c0d Mon Sep 17 00:00:00 2001 From: Anoop Kamath <115578705+AnoopKamath@users.noreply.github.com> Date: Mon, 14 Aug 2023 20:21:22 -0700 Subject: [PATCH 28/32] Update optics_si_parser.py --- .../xcvrd/xcvrd_utilities/optics_si_parser.py | 16 +++------------- 1 file changed, 3 insertions(+), 13 deletions(-) diff --git a/sonic-xcvrd/xcvrd/xcvrd_utilities/optics_si_parser.py b/sonic-xcvrd/xcvrd/xcvrd_utilities/optics_si_parser.py index 4d6d5d8ad..7f479dc02 100644 --- a/sonic-xcvrd/xcvrd/xcvrd_utilities/optics_si_parser.py +++ b/sonic-xcvrd/xcvrd/xcvrd_utilities/optics_si_parser.py @@ -1,8 +1,5 @@ import json import os -import sonic_platform.platform -import sonic_platform_base.sonic_sfp.sfputilhelper -platform_chassis = sonic_platform.platform.Platform().get_chassis() from sonic_py_common import daemon_base, device_info, logger from xcvrd.xcvrd_utilities import sfp_status_helper @@ -89,12 +86,7 @@ def get_optics_si_settings_value(physical_port, lane_speed, key, vendor_name_str return default_dict -def get_module_vendor_key(physical_port): - sfp = platform_chassis.get_sfp(physical_port) - if not sfp.get_presence(): - helper_logger.log_info("Module {} presence not detected during notify".format(physical_port)) - return None - +def get_module_vendor_key(physical_port, sfp): api = sfp.get_xcvr_api() if api is None: helper_logger.log_info("Module {} xcvrd api not found".format(physical_port)) @@ -112,7 +104,7 @@ def get_module_vendor_key(physical_port): return vendor_name.upper().strip() + '-' + vendor_sn.upper().strip(), vendor_name.upper().strip() -def fetch_optics_si_setting(physical_port, lane_speed): +def fetch_optics_si_setting(physical_port, lane_speed, sfp): if not g_optics_si_dict: return @@ -121,7 +113,7 @@ def fetch_optics_si_setting(physical_port, lane_speed): if not xcvrd._wrapper_get_presence(physical_port): helper_logger.log_info("Module {} presence not detected during notify".format(physical_port)) return optics_si - vendor_key, vendor_name = get_module_vendor_key(physical_port) + vendor_key, vendor_name = get_module_vendor_key(physical_port, sfp) if vendor_key is None: helper_logger.log_error("Error: No Vendor Key found for port '{}'".format(logical_port_name)) return optics_si @@ -132,7 +124,6 @@ def load_optics_si_settings(): global g_optics_si_dict (platform_path, _) = device_info.get_paths_to_platform_and_hwsku_dirs() - helper_logger.log_error("ANOOP parse optics json file {}".format(platform_path)) optics_si_settings_file_path = os.path.join(platform_path, "optics_si_settings.json") if not os.path.isfile(optics_si_settings_file_path): helper_logger.log_error("No optics SI file exists") @@ -140,7 +131,6 @@ def load_optics_si_settings(): with open(optics_si_settings_file_path, "r") as optics_si_file: g_optics_si_dict = json.load(optics_si_file) - helper_logger.log_error("ANOOP parsed optics json file {}".format(g_optics_si_dict)) def optics_si_present(): if g_optics_si_dict: From a859f55a98482fc947d792edcbb3b7ddbb5af2b2 Mon Sep 17 00:00:00 2001 From: Anoop Kamath <115578705+AnoopKamath@users.noreply.github.com> Date: Tue, 15 Aug 2023 00:21:48 -0700 Subject: [PATCH 29/32] Update xcvrd.py --- sonic-xcvrd/xcvrd/xcvrd.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/sonic-xcvrd/xcvrd/xcvrd.py b/sonic-xcvrd/xcvrd/xcvrd.py index be37cc346..cae44707d 100644 --- a/sonic-xcvrd/xcvrd/xcvrd.py +++ b/sonic-xcvrd/xcvrd/xcvrd.py @@ -1593,7 +1593,7 @@ def task_worker(self): elif state == self.CMIS_STATE_AP_CONF: # Explicit control bit to apply custom Host SI settings. - # It will set to 1 and applied via set_application if + # It will be set to 1 and applied via set_application if # custom SI settings is applicable ec = 0 @@ -1620,8 +1620,8 @@ def task_worker(self): self.log_notice("{} configured laser frequency {} GHz".format(lport, freq)) # Stage custom SI settings - optics_si_dict = {} if optics_si_parser.optics_si_present(): + optics_si_dict = {} # Apply module SI settings if applicable lane_speed = int(speed/1000)//host_lane_count optics_si_dict = optics_si_parser.fetch_optics_si_setting(pport, lane_speed, sfp) @@ -2477,7 +2477,7 @@ def init(self): self.log_info("Skip loading media_settings.json and optics_si_settings.json in case of fast-reboot") else: self.load_media_settings() - self.load_optics_si_settings() + optics_si_parser.load_optics_si_settings() # Make sure this daemon started after all port configured self.log_notice("XCVRD INIT: Wait for port config is done") From 14a57615cd93068b15620d28373e25a45e4574da Mon Sep 17 00:00:00 2001 From: Anoop Kamath <115578705+AnoopKamath@users.noreply.github.com> Date: Tue, 15 Aug 2023 00:30:11 -0700 Subject: [PATCH 30/32] Update optics_si_parser.py --- sonic-xcvrd/xcvrd/xcvrd_utilities/optics_si_parser.py | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/sonic-xcvrd/xcvrd/xcvrd_utilities/optics_si_parser.py b/sonic-xcvrd/xcvrd/xcvrd_utilities/optics_si_parser.py index 7f479dc02..428ac3273 100644 --- a/sonic-xcvrd/xcvrd/xcvrd_utilities/optics_si_parser.py +++ b/sonic-xcvrd/xcvrd/xcvrd_utilities/optics_si_parser.py @@ -1,9 +1,7 @@ import json import os -from sonic_py_common import daemon_base, device_info, logger -from xcvrd.xcvrd_utilities import sfp_status_helper -from xcvrd.xcvrd_utilities import port_mapping +from sonic_py_common import device_info, logger from xcvrd import xcvrd g_optics_si_dict = {} @@ -114,7 +112,7 @@ def fetch_optics_si_setting(physical_port, lane_speed, sfp): helper_logger.log_info("Module {} presence not detected during notify".format(physical_port)) return optics_si vendor_key, vendor_name = get_module_vendor_key(physical_port, sfp) - if vendor_key is None: + if vendor_key is None or vendor_name is None: helper_logger.log_error("Error: No Vendor Key found for port '{}'".format(logical_port_name)) return optics_si optics_si = get_optics_si_settings_value(physical_port, lane_speed, vendor_key, vendor_name) From bbee1520fbed20f0aa5f23fc47294830d743cf9c Mon Sep 17 00:00:00 2001 From: Anoop Kamath <115578705+AnoopKamath@users.noreply.github.com> Date: Tue, 15 Aug 2023 17:17:07 -0700 Subject: [PATCH 31/32] Add Vendor key to XCVRD log --- sonic-xcvrd/xcvrd/xcvrd.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/sonic-xcvrd/xcvrd/xcvrd.py b/sonic-xcvrd/xcvrd/xcvrd.py index cae44707d..ab06b9ab1 100644 --- a/sonic-xcvrd/xcvrd/xcvrd.py +++ b/sonic-xcvrd/xcvrd/xcvrd.py @@ -1627,7 +1627,8 @@ def task_worker(self): optics_si_dict = optics_si_parser.fetch_optics_si_setting(pport, lane_speed, sfp) if optics_si_dict: - self.log_notice("{}: Optics SI found. Apply".format(lport)) + self.log_notice("{}: Apply Optics SI found for Vendor: {} PN: {} lane speed: {}G". + format(lport, api.get_manufacturer(), api.get_model(), lane_speed)) if not api.stage_custom_si_settings(host_lanes_mask, optics_si_dict): self.log_notice("{}: unable to stage custom SI settings ".format(lport)) self.force_cmis_reinit(lport, retries + 1) From 1d2262ca126f5c6f6a4bb62fe71c6274d57b2ed9 Mon Sep 17 00:00:00 2001 From: Anoop Kamath <115578705+AnoopKamath@users.noreply.github.com> Date: Tue, 15 Aug 2023 17:18:55 -0700 Subject: [PATCH 32/32] Change logging level --- sonic-xcvrd/xcvrd/xcvrd_utilities/optics_si_parser.py | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/sonic-xcvrd/xcvrd/xcvrd_utilities/optics_si_parser.py b/sonic-xcvrd/xcvrd/xcvrd_utilities/optics_si_parser.py index 428ac3273..fff418563 100644 --- a/sonic-xcvrd/xcvrd/xcvrd_utilities/optics_si_parser.py +++ b/sonic-xcvrd/xcvrd/xcvrd_utilities/optics_si_parser.py @@ -95,12 +95,12 @@ def get_module_vendor_key(physical_port, sfp): helper_logger.log_info("Module {} vendor name not found".format(physical_port)) return None - vendor_sn = api.get_model() - if vendor_sn is None: - helper_logger.log_info("Module {} vendor serial number not found".format(physical_port)) + vendor_pn = api.get_model() + if vendor_pn is None: + helper_logger.log_info("Module {} vendor part number not found".format(physical_port)) return None - return vendor_name.upper().strip() + '-' + vendor_sn.upper().strip(), vendor_name.upper().strip() + return vendor_name.upper().strip() + '-' + vendor_pn.upper().strip(), vendor_name.upper().strip() def fetch_optics_si_setting(physical_port, lane_speed, sfp): if not g_optics_si_dict: @@ -124,7 +124,7 @@ def load_optics_si_settings(): optics_si_settings_file_path = os.path.join(platform_path, "optics_si_settings.json") if not os.path.isfile(optics_si_settings_file_path): - helper_logger.log_error("No optics SI file exists") + helper_logger.log_info("No optics SI file exists") return {} with open(optics_si_settings_file_path, "r") as optics_si_file: