66
77try :
88 import math
9+ import time
910 import struct
1011 from ctypes import c_int8
1112
4849OFFSET_TOR1_CURSOR_VALUES = 681
4950OFFSET_TOR2_CURSOR_VALUES = 701
5051OFFSET_NIC_LANE_ACTIVE = 721
52+ OFFSET_INTERNAL_TEMPERATURE = 22
53+ OFFSET_INTERNAL_VOLTAGE = 26
54+ OFFSET_NIC_TEMPERATURE = 727
55+ OFFSET_NIC_VOLTAGE = 729
5156
5257# definitions of targets for getting the cursor
5358# equalization parameters from the register spec
7580SWITCH_COUNT_MANUAL = "manual"
7681SWITCH_COUNT_AUTO = "auto"
7782
83+ FIRMWARE_INFO_PAYLOAD_SIZE = 48
84+ NUM_MCU_SIDE = 3
85+
86+ EEPROM_READ_DATA_INVALID = - 1
87+ EEPROM_ERROR = - 1
88+ EEPROM_TIMEOUT_ERROR = - 1
89+
90+ BER_TIMEOUT_SECS = 1
91+ EYE_TIMEOUT_SECS = 1
92+
93+ MAX_NUM_LANES = 4
94+
7895SYSLOG_IDENTIFIER = "sonic_y_cable"
7996
8097# Global logger instance for helper functions and classes to log
@@ -97,15 +114,15 @@ def y_cable_validate_read_data(result, size, physical_port, message):
97114 if len (result ) != size :
98115 LOG_MESSAGE_TEMPLATE = "Error: for checking mux_cable {}, eeprom read returned a size {} not equal to 1 for port {}"
99116 helper_logger .log_error (LOG_MESSAGE_TEMPLATE .format (message , len (result ), physical_port ))
100- return - 1
117+ return EEPROM_READ_DATA_INVALID
101118 else :
102119 LOG_MESSAGE_TEMPLATE = "Error: for checking mux_cable {}, eeprom read returned an instance value of type {} which is not a bytearray for port {}"
103120 helper_logger .log_error (LOG_MESSAGE_TEMPLATE .format (message , type (result ), physical_port ))
104- return - 1
121+ return EEPROM_READ_DATA_INVALID
105122 else :
106123 LOG_MESSAGE_TEMPLATE = "Error: for checking mux_cable {}, eeprom read returned a None value for port {} which is not expected"
107124 helper_logger .log_error (LOG_MESSAGE_TEMPLATE .format (message , physical_port ))
108- return - 1
125+ return EEPROM_READ_DATA_INVALID
109126
110127
111128def hook_y_cable_simulator (target ):
@@ -573,7 +590,6 @@ def check_if_link_is_active_for_torB(physical_port):
573590 return False
574591
575592
576- @hook_y_cable_simulator
577593def enable_prbs_mode (physical_port , target , mode_value , lane_map ):
578594 """
579595 This API specifically configures and enables the PRBS mode/type depending upon the mode_value the user provides.
@@ -646,7 +662,6 @@ def enable_prbs_mode(physical_port, target, mode_value, lane_map):
646662 return result
647663
648664
649- @hook_y_cable_simulator
650665def disable_prbs_mode (physical_port , target ):
651666 """
652667 This API specifically disables the PRBS mode on the physcial port.
@@ -697,7 +712,6 @@ def disable_prbs_mode(physical_port, target):
697712 return result
698713
699714
700- @hook_y_cable_simulator
701715def enable_loopback_mode (physical_port , target , lane_map ):
702716 """
703717 This API specifically configures and enables the Loopback mode on the port user provides.
@@ -755,7 +769,6 @@ def enable_loopback_mode(physical_port, target, lane_map):
755769 return result
756770
757771
758- @hook_y_cable_simulator
759772def disable_loopback_mode (physical_port , target ):
760773 """
761774 This API specifically disables the Loopback mode on the port user provides.
@@ -809,7 +822,6 @@ def disable_loopback_mode(physical_port, target):
809822 return result
810823
811824
812- @hook_y_cable_simulator
813825def get_ber_info (physical_port , target ):
814826 """
815827 This API specifically returns the BER (Bit error rate) value for a specfic port.
@@ -856,20 +868,27 @@ def get_ber_info(physical_port, target):
856868 physical_port ).write_eeprom (curr_offset , 1 , buffer )
857869 if result is False :
858870 return result
871+ time_start = time .time ()
859872 while (True ):
860873 done = platform_chassis .get_sfp (physical_port ).read_eeprom (curr_offset , 1 )
861- y_cable_validate_read_data (done , 1 , physical_port , "BER data ready to read" )
874+ if y_cable_validate_read_data (done , 1 , physical_port , "BER data ready to read" ) == EEPROM_READ_DATA_INVALID :
875+ return EEPROM_ERROR
876+ time_now = time .time ()
877+ time_diff = time_now - time_start
862878 if done [0 ] == 1 :
863879 break
880+ elif time_diff >= BER_TIMEOUT_SECS :
881+ return EEPROM_TIMEOUT_ERROR
864882
865883 idx = 0
866- maxLane = 2
867884 curr_offset = OFFSET_LANE_1_BER_RESULT
868- for lane in range (maxLane ):
885+ for lane in range (MAX_NUM_LANES ):
869886 msb_result = platform_chassis .get_sfp (physical_port ).read_eeprom (curr_offset + idx , 1 )
870- y_cable_validate_read_data (msb_result , 1 , physical_port , "BER data msb result" )
887+ if y_cable_validate_read_data (msb_result , 1 , physical_port , "BER data msb result" ) == EEPROM_READ_DATA_INVALID :
888+ return EEPROM_ERROR
871889 lsb_result = platform_chassis .get_sfp (physical_port ).read_eeprom (curr_offset + 1 + idx , 1 )
872- y_cable_validate_read_data (lsb_result , 1 , physical_port , "BER data lsb result" )
890+ if y_cable_validate_read_data (lsb_result , 1 , physical_port , "BER data lsb result" ) == EEPROM_READ_DATA_INVALID :
891+ return EEPROM_ERROR
873892 lane_result = msb_result [0 ] * math .pow (10 , (lsb_result [0 ]- 24 ))
874893 ber_result .append (lane_result )
875894 idx += 2
@@ -881,7 +900,6 @@ def get_ber_info(physical_port, target):
881900 return ber_result
882901
883902
884- @hook_y_cable_simulator
885903def get_eye_info (physical_port , target ):
886904 """
887905 This API specifically returns the EYE height value for a specfic port.
@@ -927,20 +945,27 @@ def get_eye_info(physical_port, target):
927945 if result is False :
928946 return result
929947
948+ time_start = time .time ()
930949 while (True ):
931950 done = platform_chassis .get_sfp (physical_port ).read_eeprom (curr_offset , 1 )
932- y_cable_validate_read_data (done , 1 , physical_port , "EYE data ready to read" )
951+ if y_cable_validate_read_data (done , 1 , physical_port , "EYE data ready to read" ) == EEPROM_READ_DATA_INVALID :
952+ return EEPROM_ERROR
953+ time_now = time .time ()
954+ time_diff = time_now - time_start
933955 if done [0 ] == 1 :
934956 break
957+ elif time_diff >= EYE_TIMEOUT_SECS :
958+ return EEPROM_TIMEOUT_ERROR
935959
936960 idx = 0
937- maxLane = 2
938- for lane in range (maxLane ):
961+ for lane in range (MAX_NUM_LANES ):
939962 curr_offset = OFFSET_LANE_1_EYE_RESULT
940963 msb_result = platform_chassis .get_sfp (physical_port ).read_eeprom (curr_offset + idx , 1 )
941- y_cable_validate_read_data (msb_result , 1 , physical_port , "EYE data msb result" )
964+ if y_cable_validate_read_data (msb_result , 1 , physical_port , "EYE data msb result" ) == EEPROM_READ_DATA_INVALID :
965+ return EEPROM_ERROR
942966 lsb_result = platform_chassis .get_sfp (physical_port ).read_eeprom (curr_offset + 1 + idx , 1 )
943- y_cable_validate_read_data (lsb_result , 1 , physical_port , "EYE data lsb result" )
967+ if y_cable_validate_read_data (lsb_result , 1 , physical_port , "EYE data lsb result" ) == EEPROM_READ_DATA_INVALID :
968+ return EEPROM_ERROR
944969 lane_result = (msb_result [0 ] << 8 | lsb_result [0 ])
945970 eye_result .append (lane_result )
946971 idx += 2
@@ -952,7 +977,6 @@ def get_eye_info(physical_port, target):
952977 return eye_result
953978
954979
955- @hook_y_cable_simulator
956980def get_pn_number_and_vendor_name (physical_port ):
957981 """
958982 This API specifically returns the pn number and vendor name for a specfic port.
@@ -968,10 +992,12 @@ def get_pn_number_and_vendor_name(physical_port):
968992
969993 if platform_chassis is not None :
970994 pn_result = platform_chassis .get_sfp (physical_port ).read_eeprom (curr_offset , 15 )
971- y_cable_validate_read_data (pn_result , 1 , physical_port , "PN number" )
995+ if y_cable_validate_read_data (pn_result , 15 , physical_port , "PN number" ) == EEPROM_READ_DATA_INVALID :
996+ return EEPROM_ERROR
972997 curr_offset = OFFSET_VENDOR_NAME
973998 vendor_name = platform_chassis .get_sfp (physical_port ).read_eeprom (curr_offset , 15 )
974- y_cable_validate_read_data (vendor_name , 15 , physical_port , "vendor name" )
999+ if y_cable_validate_read_data (vendor_name , 15 , physical_port , "vendor name" ) == EEPROM_READ_DATA_INVALID :
1000+ return EEPROM_ERROR
9751001
9761002 else :
9771003 helper_logger .log_error ("platform_chassis is not loaded, failed to get pin results" )
@@ -980,7 +1006,6 @@ def get_pn_number_and_vendor_name(physical_port):
9801006 return pn_result , vendor_name
9811007
9821008
983- @hook_y_cable_simulator
9841009def get_switch_count (physical_port , count_type ):
9851010 """
9861011 This API specifically returns the switch count to change the Active TOR which has
@@ -1009,13 +1034,17 @@ def get_switch_count(physical_port, count_type):
10091034
10101035 if platform_chassis is not None :
10111036 msb_result = platform_chassis .get_sfp (physical_port ).read_eeprom (curr_offset , 1 )
1012- y_cable_validate_read_data (msb_result , 1 , physical_port , "{} switch count msb result" .format (count_type ))
1037+ if y_cable_validate_read_data (msb_result , 1 , physical_port , "{} switch count msb result" .format (count_type )) == EEPROM_READ_DATA_INVALID :
1038+ return EEPROM_ERROR
10131039 msb_result_1 = platform_chassis .get_sfp (physical_port ).read_eeprom (curr_offset + 1 , 1 )
1014- y_cable_validate_read_data (msb_result_1 , 1 , physical_port , "{} switch count msb result 1" .format (count_type ))
1040+ if y_cable_validate_read_data (msb_result_1 , 1 , physical_port , "{} switch count msb result 1" .format (count_type )) == EEPROM_READ_DATA_INVALID :
1041+ return EEPROM_ERROR
10151042 msb_result_2 = platform_chassis .get_sfp (physical_port ).read_eeprom (curr_offset + 2 , 1 )
1016- y_cable_validate_read_data (msb_result_2 , 1 , physical_port , "{} switch count msb result 2" .format (count_type ))
1043+ if y_cable_validate_read_data (msb_result_2 , 1 , physical_port , "{} switch count msb result 2" .format (count_type )) == EEPROM_READ_DATA_INVALID :
1044+ return EEPROM_ERROR
10171045 lsb_result = platform_chassis .get_sfp (physical_port ).read_eeprom (curr_offset + 3 , 1 )
1018- y_cable_validate_read_data (lsb_result , 1 , physical_port , "{} switch count lsb result" .format (count_type ))
1046+ if y_cable_validate_read_data (lsb_result , 1 , physical_port , "{} switch count lsb result" .format (count_type )) == EEPROM_READ_DATA_INVALID :
1047+ return EEPROM_ERROR
10191048 count = (msb_result [0 ] << 24 | msb_result_1 [0 ] << 16 | msb_result_2 [0 ] << 8 | lsb_result [0 ])
10201049
10211050 else :
@@ -1025,7 +1054,6 @@ def get_switch_count(physical_port, count_type):
10251054 return count
10261055
10271056
1028- @hook_y_cable_simulator
10291057def get_target_cursor_values (physical_port , lane , target ):
10301058 """
10311059 This API specifically returns the cursor equalization parameters for a target(NIC, TOR1, TOR2).
@@ -1055,19 +1083,24 @@ def get_target_cursor_values(physical_port, lane, target):
10551083
10561084 if platform_chassis is not None :
10571085 pre1 = platform_chassis .get_sfp (physical_port ).read_eeprom (curr_offset + (target )* 20 + (lane - 1 )* 5 , 1 )
1058- y_cable_validate_read_data (pre1 , 1 , physical_port , "target cursor result" )
1086+ if y_cable_validate_read_data (pre1 , 1 , physical_port , "target cursor result" ) == EEPROM_READ_DATA_INVALID :
1087+ return EEPROM_ERROR
10591088 result .append (c_int8 (pre1 [0 ]).value )
10601089 pre2 = platform_chassis .get_sfp (physical_port ).read_eeprom (curr_offset + (target )* 20 + (lane - 1 )* 5 + 1 , 1 )
1061- y_cable_validate_read_data (pre2 , 1 , physical_port , "target cursor result" )
1090+ if y_cable_validate_read_data (pre2 , 1 , physical_port , "target cursor result" ) == EEPROM_READ_DATA_INVALID :
1091+ return EEPROM_ERROR
10621092 result .append (c_int8 (pre2 [0 ]).value )
10631093 main = platform_chassis .get_sfp (physical_port ).read_eeprom (curr_offset + (target )* 20 + (lane - 1 )* 5 + 2 , 1 )
1064- y_cable_validate_read_data (main , 1 , physical_port , "target cursor result" )
1094+ if y_cable_validate_read_data (main , 1 , physical_port , "target cursor result" ) == EEPROM_READ_DATA_INVALID :
1095+ return EEPROM_ERROR
10651096 result .append (c_int8 (main [0 ]).value )
10661097 post1 = platform_chassis .get_sfp (physical_port ).read_eeprom (curr_offset + (target )* 20 + (lane - 1 )* 5 + 3 , 1 )
1067- y_cable_validate_read_data (post1 , 1 , physical_port , "target cursor result" )
1098+ if y_cable_validate_read_data (post1 , 1 , physical_port , "target cursor result" ) == EEPROM_READ_DATA_INVALID :
1099+ return EEPROM_ERROR
10681100 result .append (c_int8 (post1 [0 ]).value )
10691101 post2 = platform_chassis .get_sfp (physical_port ).read_eeprom (curr_offset + (target )* 20 + (lane - 1 )* 5 + 4 , 1 )
1070- y_cable_validate_read_data (post2 , 1 , physical_port , "target cursor result" )
1102+ if y_cable_validate_read_data (post2 , 1 , physical_port , "target cursor result" ) == EEPROM_READ_DATA_INVALID :
1103+ return EEPROM_ERROR
10711104 result .append (c_int8 (post2 [0 ]).value )
10721105
10731106 else :
@@ -1077,7 +1110,6 @@ def get_target_cursor_values(physical_port, lane, target):
10771110 return result
10781111
10791112
1080- @hook_y_cable_simulator
10811113def check_if_nic_lanes_active (physical_port ):
10821114 """
10831115 This API specifically returns the byte value which denotes which nic lanes
@@ -1097,11 +1129,111 @@ def check_if_nic_lanes_active(physical_port):
10971129
10981130 if platform_chassis is not None :
10991131 res = platform_chassis .get_sfp (physical_port ).read_eeprom (curr_offset , 1 )
1100- y_cable_validate_read_data (res , 1 , physical_port , "nic lanes active" )
1132+ if y_cable_validate_read_data (res , 1 , physical_port , "nic lanes active" ) == EEPROM_READ_DATA_INVALID :
1133+ return EEPROM_ERROR
11011134 result = res [0 ]
11021135
11031136 else :
11041137 helper_logger .log_error ("platform_chassis is not loaded, failed to get NIC lanes active" )
11051138 return - 1
11061139
11071140 return result
1141+
1142+
1143+ def get_firmware_version (physical_port , target ):
1144+
1145+ data = bytearray (FIRMWARE_INFO_PAYLOAD_SIZE )
1146+
1147+ if platform_chassis is not None :
1148+ for byte_idx in range (0 , FIRMWARE_INFO_PAYLOAD_SIZE ):
1149+ curr_offset = 0xfc * 128 + 128 + byte_idx
1150+ read_out = platform_chassis .get_sfp (physical_port ).read_eeprom (curr_offset , 1 )
1151+ if y_cable_validate_read_data (read_out , 1 , physical_port , "firmware info" ) == EEPROM_READ_DATA_INVALID :
1152+ return EEPROM_ERROR
1153+ data [byte_idx ] = read_out [0 ]
1154+ else :
1155+ helper_logger .log_error ("platform_chassis is not loaded, failed to get NIC lanes active" )
1156+ return - 1
1157+
1158+ result = {}
1159+ NUM_MCU_SIDE = 3
1160+
1161+ base_addr = int (target * (FIRMWARE_INFO_PAYLOAD_SIZE / NUM_MCU_SIDE ))
1162+ rev_major_slot1 = struct .unpack_from ('<B' , data [(0 + base_addr ):(1 + base_addr )])[0 ]
1163+ rev_minor_slot1 = struct .unpack_from ('<B' , data [(2 + base_addr ):(3 + base_addr )])[0 ]
1164+ rev_build_lsb_slot1 = struct .unpack_from ('<B' , data [(4 + base_addr ):(5 + base_addr )])[0 ]
1165+ rev_build_msb_slot1 = struct .unpack_from ('<B' , data [(5 + base_addr ):(6 + base_addr )])[0 ]
1166+ rev_major_slot2 = struct .unpack_from ('<B' , data [(1 + base_addr ):(2 + base_addr )])[0 ]
1167+ rev_minor_slot2 = struct .unpack_from ('<B' , data [(3 + base_addr ):(4 + base_addr )])[0 ]
1168+ rev_build_lsb_slot2 = struct .unpack_from ('<B' , data [(6 + base_addr ):(7 + base_addr )])[0 ]
1169+ rev_build_msb_slot2 = struct .unpack_from ('<B' , data [(7 + base_addr ):(8 + base_addr )])[0 ]
1170+ slot_status = struct .unpack_from ('<B' , data [(8 + base_addr ):(9 + base_addr )])[0 ]
1171+
1172+ if (rev_major_slot1 == 0 and rev_minor_slot1 == 0 and rev_build_lsb_slot1 == 0 and rev_build_msb_slot1 == 0 and rev_major_slot2 == 0 and rev_minor_slot2 == 0 and rev_build_lsb_slot2 == 0 and rev_build_msb_slot2 == 0 ):
1173+ return None
1174+ else :
1175+ build_slot1 = chr (rev_build_lsb_slot1 ) + chr (rev_build_msb_slot1 )
1176+ version_slot1 = str (rev_major_slot1 ) + "." + str (rev_minor_slot1 )
1177+ build_slot2 = chr (rev_build_lsb_slot2 ) + chr (rev_build_msb_slot2 )
1178+ version_slot2 = str (rev_major_slot2 ) + "." + str (rev_minor_slot2 )
1179+
1180+ result ["build_slot1" ] = build_slot1
1181+ result ["version_slot1" ] = version_slot1
1182+ result ["build_slot2" ] = build_slot2
1183+ result ["version_slot2" ] = version_slot2
1184+ result ["run_slot1" ] = True if slot_status & 0x01 else False
1185+ result ["run_slot2" ] = True if slot_status & 0x10 else False
1186+ result ["commit_slot1" ] = True if slot_status & 0x02 else False
1187+ result ["commit_slot2" ] = True if slot_status & 0x20 else False
1188+ result ["empty_slot1" ] = True if slot_status & 0x04 else False
1189+ result ["empty_slot2" ] = True if slot_status & 0x40 else False
1190+
1191+ return result
1192+
1193+
1194+ def get_internal_voltage_temp (physical_port ):
1195+
1196+ curr_offset = OFFSET_INTERNAL_TEMPERATURE
1197+ if platform_chassis is not None :
1198+ result = platform_chassis .get_sfp (physical_port ).read_eeprom (curr_offset , 1 )
1199+ if y_cable_validate_read_data (result , 1 , physical_port , "internal voltage" ) == EEPROM_READ_DATA_INVALID :
1200+ return EEPROM_ERROR
1201+ curr_offset = OFFSET_INTERNAL_VOLTAGE
1202+ msb_result = platform_chassis .get_sfp (physical_port ).read_eeprom (curr_offset , 1 )
1203+ if y_cable_validate_read_data (msb_result , 1 , physical_port , "internal temperature msb" ) == EEPROM_READ_DATA_INVALID :
1204+ return EEPROM_ERROR
1205+ lsb_result = platform_chassis .get_sfp (physical_port ).read_eeprom (curr_offset + 1 , 1 )
1206+ if y_cable_validate_read_data (lsb_result , 1 , physical_port , "internal temperature lsb" ) == EEPROM_READ_DATA_INVALID :
1207+ return EEPROM_ERROR
1208+
1209+ temp = result [0 ]
1210+ voltage = (((msb_result [0 ] << 8 ) | lsb_result [0 ]) * 0.0001 )
1211+ else :
1212+ helper_logger .log_error ("platform_chassis is not loaded, failed to get internal voltage and temp" )
1213+ return - 1
1214+
1215+ return temp , voltage
1216+
1217+
1218+ def get_nic_voltage_temp (physical_port ):
1219+
1220+ curr_offset = OFFSET_NIC_TEMPERATURE
1221+ if platform_chassis is not None :
1222+ result = platform_chassis .get_sfp (physical_port ).read_eeprom (curr_offset , 1 )
1223+ if y_cable_validate_read_data (result , 1 , physical_port , "internal voltage" ) == EEPROM_READ_DATA_INVALID :
1224+ return EEPROM_ERROR
1225+ curr_offset = OFFSET_NIC_VOLTAGE
1226+ msb_result = platform_chassis .get_sfp (physical_port ).read_eeprom (curr_offset , 1 )
1227+ if y_cable_validate_read_data (msb_result , 1 , physical_port , "internal temperature msb" ) == EEPROM_READ_DATA_INVALID :
1228+ return EEPROM_ERROR
1229+ lsb_result = platform_chassis .get_sfp (physical_port ).read_eeprom (curr_offset + 1 , 1 )
1230+ if y_cable_validate_read_data (lsb_result , 1 , physical_port , "internal temperature lsb" ) == EEPROM_READ_DATA_INVALID :
1231+ return EEPROM_ERROR
1232+
1233+ temp = result [0 ]
1234+ voltage = (((msb_result [0 ] << 8 ) | lsb_result [0 ]) * 0.0001 )
1235+ else :
1236+ helper_logger .log_error ("platform_chassis is not loaded, failed to get NIC voltage and temp" )
1237+ return - 1
1238+
1239+ return temp , voltage
0 commit comments