From f899a828643ff2101d002a8370592876b286a078 Mon Sep 17 00:00:00 2001 From: Samuel Angebault Date: Thu, 9 Sep 2021 13:03:22 -0700 Subject: [PATCH 01/34] [Arista] Fix Clearwater2 phy initialization when no configuration is provided (#8271) Why I did it Fix an issue on the Clearwater2 linecard. When the linecard is started with a fresh image without configuration, phys would not be initialized. How I did it Added default_sku for Clearwater2 which prevents config-setup from failing to create a default config_db.json. Added some extra logic in the phy-credo-init script to run the phy_config.sh of the hwsku pointed by default_sku if the DEVICE_METADATA.localhost.hwsku information is not populated in CONFIG_DB. How to verify it Booting an image with this change and without configuration will lead to the phys being initialized using the phy_config.sh from default_sku. --- device/arista/x86_64-arista_7800r3_48cq2_lc/default_sku | 1 + device/arista/x86_64-arista_7800r3_48cqm2_lc/default_sku | 1 + rules/phy-credo.mk | 2 +- 3 files changed, 3 insertions(+), 1 deletion(-) create mode 100644 device/arista/x86_64-arista_7800r3_48cq2_lc/default_sku create mode 100644 device/arista/x86_64-arista_7800r3_48cqm2_lc/default_sku diff --git a/device/arista/x86_64-arista_7800r3_48cq2_lc/default_sku b/device/arista/x86_64-arista_7800r3_48cq2_lc/default_sku new file mode 100644 index 000000000000..47d37c0d9108 --- /dev/null +++ b/device/arista/x86_64-arista_7800r3_48cq2_lc/default_sku @@ -0,0 +1 @@ +Arista-7800R3-48CQ2-C48 t1 diff --git a/device/arista/x86_64-arista_7800r3_48cqm2_lc/default_sku b/device/arista/x86_64-arista_7800r3_48cqm2_lc/default_sku new file mode 100644 index 000000000000..055cc867926c --- /dev/null +++ b/device/arista/x86_64-arista_7800r3_48cqm2_lc/default_sku @@ -0,0 +1 @@ +Arista-7800R3-48CQM2-C48 t1 diff --git a/rules/phy-credo.mk b/rules/phy-credo.mk index ab6c45e0e9c5..7e9441619139 100644 --- a/rules/phy-credo.mk +++ b/rules/phy-credo.mk @@ -1,3 +1,3 @@ PHY_CREDO = phy-credo_1.0_amd64.deb -$(PHY_CREDO)_URL = "https://github.com/aristanetworks/sonic-firmware/raw/08cbc09437e942c1e3cd84a7595ca686193d311b/phy/phy-credo_1.0_amd64.deb" +$(PHY_CREDO)_URL = "https://github.com/aristanetworks/sonic-firmware/raw/0468f6c23a7219dfee6dd2819013e9f1e940c95d/phy/phy-credo_1.0_amd64.deb" SONIC_ONLINE_DEBS += $(PHY_CREDO) From f8949547d7e4c8f6cb382746ae955d2a495a0cb2 Mon Sep 17 00:00:00 2001 From: Nazarii Hnydyn Date: Fri, 10 Sep 2021 12:29:37 +0300 Subject: [PATCH 02/34] [submodule]: Advance sonic-sairedis. (#8706) Signed-off-by: Nazarii Hnydyn --- src/sonic-sairedis | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/sonic-sairedis b/src/sonic-sairedis index f85322e139a9..696ad9929db2 160000 --- a/src/sonic-sairedis +++ b/src/sonic-sairedis @@ -1 +1 @@ -Subproject commit f85322e139a9b10f0154b26efaed689791d135d5 +Subproject commit 696ad9929db26a446518dbcd22c8f742025f2b93 From f36952fea3af9cbd85424d1e3756e1b65e2560d7 Mon Sep 17 00:00:00 2001 From: Nazarii Hnydyn Date: Fri, 10 Sep 2021 17:30:00 +0300 Subject: [PATCH 03/34] [Mellanox]: Update SAI to v1.19.2 (#8618) - Why I did it Advance to Mellanox SAI ver 1.19.2 to pick up dynamic Policy Based Hashing support. For this version above the static Policy Based Hashing is no longer supported. For detailed release notes check https://github.com/Mellanox/SAI-Implementation/blob/sonic2111/release%20notes.txt - How I did it Updated SAI-Implementation submodule - How to verify it 1. make configure PLATFORM=mellanox 2. make target/sonic-mellanox.bin Run full regression as well as new dynamic PBH tests Signed-off-by: Nazarii Hnydyn --- platform/mellanox/mlnx-sai.mk | 2 +- platform/mellanox/mlnx-sai/SAI-Implementation | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/platform/mellanox/mlnx-sai.mk b/platform/mellanox/mlnx-sai.mk index 7929b8c75181..2570a2d0fefe 100644 --- a/platform/mellanox/mlnx-sai.mk +++ b/platform/mellanox/mlnx-sai.mk @@ -1,6 +1,6 @@ # Mellanox SAI -MLNX_SAI_VERSION = SAIRel1.19.1 +MLNX_SAI_VERSION = SAIRel1.19.2 export MLNX_SAI_VERSION diff --git a/platform/mellanox/mlnx-sai/SAI-Implementation b/platform/mellanox/mlnx-sai/SAI-Implementation index be35fa45f163..971a8448dadf 160000 --- a/platform/mellanox/mlnx-sai/SAI-Implementation +++ b/platform/mellanox/mlnx-sai/SAI-Implementation @@ -1 +1 @@ -Subproject commit be35fa45f163f6e1a36368f1776dc5fc745fc845 +Subproject commit 971a8448dadff061a0d8af5d79e00a20ebaf769d From b171e56e01c60e38e6e4f019132ece1c70cc1e73 Mon Sep 17 00:00:00 2001 From: Arun Saravanan Balachandran <52521751+ArunSaravananBalachandran@users.noreply.github.com> Date: Sat, 11 Sep 2021 06:05:47 +0530 Subject: [PATCH 04/34] DellEMC Z9332f: Platform API - Remove EEPROM Vendor Extension decoding (#8716) --- .../z9332f/sonic_platform/eeprom.py | 8 +------- 1 file changed, 1 insertion(+), 7 deletions(-) diff --git a/platform/broadcom/sonic-platform-modules-dell/z9332f/sonic_platform/eeprom.py b/platform/broadcom/sonic-platform-modules-dell/z9332f/sonic_platform/eeprom.py index eda04ae3bd8e..1dc66935508c 100644 --- a/platform/broadcom/sonic-platform-modules-dell/z9332f/sonic_platform/eeprom.py +++ b/platform/broadcom/sonic-platform-modules-dell/z9332f/sonic_platform/eeprom.py @@ -51,13 +51,7 @@ def __init__(self): tlv = eeprom[tlv_index:tlv_index + 2 + eeprom[tlv_index + 1]] code = "0x%02X" % tlv[0] - - if tlv[0] == self._TLV_CODE_VENDOR_EXT: - value = str((tlv[2] << 24) | (tlv[3] << 16) | - (tlv[4] << 8) | tlv[5]) - value += tlv[6:6 + tlv[1]].decode('ascii') - else: - name, value = self.decoder(None, tlv) + name, value = self.decoder(None, tlv) self.eeprom_tlv_dict[code] = value if eeprom[tlv_index] == self._TLV_CODE_CRC_32: From 1652613ad78ce5c840abf573fd81ae728e4842ee Mon Sep 17 00:00:00 2001 From: Guohan Lu Date: Fri, 10 Sep 2021 20:17:15 -0700 Subject: [PATCH 05/34] [submodule]: retreat sonic-swss submodule (#8732) Fix #8722 retreat two commits which cause warm reboot regression * eb79ca4 2021-09-01 | [pbh]: Add PBH OA (#1782) [Nazarii Hnydyn] * 3d6b1f0 2021-08-31 | [buffer orch] Bugfix: Don't query counter SAI_BUFFER_POOL_STAT_XOFF_ROOM_WATERMARK_BYTES on a pool where it is not supported (#1857) [Stephen Sun] Signed-off-by: Guohan Lu --- src/sonic-swss | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/sonic-swss b/src/sonic-swss index eb79ca4a5248..db9ca8306546 160000 --- a/src/sonic-swss +++ b/src/sonic-swss @@ -1 +1 @@ -Subproject commit eb79ca4a524899f57995abd5ae5ec5f773ec85d0 +Subproject commit db9ca8306546eec0c1b1b703be688e2a8a7ae77a From b19d42ebb7c1ddcef59144ef907894331175bbac Mon Sep 17 00:00:00 2001 From: dflynn-Nokia <60479697+dflynn-Nokia@users.noreply.github.com> Date: Sat, 11 Sep 2021 04:18:24 -0400 Subject: [PATCH 06/34] [Nokia ixs7215] Miscellaneous platform API fixes (#8707) * [Nokia ixs7215] Miscellaneous platform API fixes This commit delivers the following fixes for the Nokia ixs7215 platform - Fix bug in a fan API error path - Add support for setting the fan drawer led - Add support for getting/setting the front panel PSU status led - Add support for getting the min/max observed temperature value * [Nokia ixs7215] code review changes: temperature min/max values --- .../7215/sonic_platform/fan.py | 12 ++++------- .../7215/sonic_platform/fan_drawer.py | 2 +- .../7215/sonic_platform/psu.py | 20 +++++++++++++++++++ .../7215/sonic_platform/thermal.py | 15 ++++++++++++++ 4 files changed, 40 insertions(+), 9 deletions(-) diff --git a/platform/marvell-armhf/sonic-platform-nokia/7215/sonic_platform/fan.py b/platform/marvell-armhf/sonic-platform-nokia/7215/sonic_platform/fan.py index 14c00c763dde..b8fd335930d6 100644 --- a/platform/marvell-armhf/sonic-platform-nokia/7215/sonic_platform/fan.py +++ b/platform/marvell-armhf/sonic-platform-nokia/7215/sonic_platform/fan.py @@ -336,10 +336,10 @@ def get_status_led(self): """ if self.is_psu_fan: - return False + return None if smbus_present == 0: - return False + return None else: bus = smbus.SMBus(0) DEVICE_ADDRESS = 0x41 @@ -368,7 +368,7 @@ def get_target_speed(self): (off) to 100 (full speed) """ speed = 0 - + fan_duty = self._get_i2c_register(self.set_fan_speed_reg) if (fan_duty != 'ERR'): dutyspeed = int(fan_duty) @@ -380,9 +380,5 @@ def get_target_speed(self): speed = 50 elif dutyspeed == 255: speed = 100 - - return speed - - - + return speed diff --git a/platform/marvell-armhf/sonic-platform-nokia/7215/sonic_platform/fan_drawer.py b/platform/marvell-armhf/sonic-platform-nokia/7215/sonic_platform/fan_drawer.py index 35b663cbb786..e42d80cdbd52 100644 --- a/platform/marvell-armhf/sonic-platform-nokia/7215/sonic_platform/fan_drawer.py +++ b/platform/marvell-armhf/sonic-platform-nokia/7215/sonic_platform/fan_drawer.py @@ -54,7 +54,7 @@ def get_direction(self): return 'intake' def set_status_led(self, color): - return True + return self._fan_list[0].set_status_led(color) def get_status_led(self, color): return self._fan_list[0].get_status_led() diff --git a/platform/marvell-armhf/sonic-platform-nokia/7215/sonic_platform/psu.py b/platform/marvell-armhf/sonic-platform-nokia/7215/sonic_platform/psu.py index 6a338f5a166e..90025db7ffbf 100644 --- a/platform/marvell-armhf/sonic-platform-nokia/7215/sonic_platform/psu.py +++ b/platform/marvell-armhf/sonic-platform-nokia/7215/sonic_platform/psu.py @@ -234,3 +234,23 @@ def set_status_led(self, color): # The firmware running in the PSU controls the LED # and the PSU LED state cannot be changed from CPU. return False + + def get_status_master_led(self): + """ + Gets the state of the front panel PSU status LED + + Returns: + A string, one of the predefined STATUS_LED_COLOR_* strings. + """ + return self._psu_master_led_color + + def set_status_master_led(self, color): + """ + Sets the state of the front panel PSU status LED + + Returns: + bool: True if status LED state is set successfully, False if + not + """ + self._psu_master_led_color = color + return True diff --git a/platform/marvell-armhf/sonic-platform-nokia/7215/sonic_platform/thermal.py b/platform/marvell-armhf/sonic-platform-nokia/7215/sonic_platform/thermal.py index 528a6e49d924..20fdec61f38e 100644 --- a/platform/marvell-armhf/sonic-platform-nokia/7215/sonic_platform/thermal.py +++ b/platform/marvell-armhf/sonic-platform-nokia/7215/sonic_platform/thermal.py @@ -33,9 +33,12 @@ class Thermal(ThermalBase): "CPU Core") def __init__(self, thermal_index): + ThermalBase.__init__(self) self.index = thermal_index + 1 self.is_psu_thermal = False self.dependency = None + self._minimum = None + self._maximum = None self.thermal_high_threshold_file = None # PCB temperature sensors if self.index < 3: @@ -163,6 +166,10 @@ def get_temperature(self): self.thermal_temperature_file) if (thermal_temperature != 'ERR'): thermal_temperature = float(thermal_temperature) / 1000 + if self._minimum is None or self._minimum > thermal_temperature: + self._minimum = thermal_temperature + if self._maximum is None or self._maximum < thermal_temperature: + self._maximum = thermal_temperature else: thermal_temperature = 0 @@ -226,6 +233,14 @@ def get_high_critical_threshold(self): return float("{:.3f}".format(thermal_high_crit_threshold)) + def get_minimum_recorded(self): + self.get_temperature() + return self._minimum + + def get_maximum_recorded(self): + self.get_temperature() + return self._maximum + def get_position_in_parent(self): """ Retrieves 1-based relative physical position in parent device From d20f0cb7ea2a2cf00de6876c1f744d4431b753f8 Mon Sep 17 00:00:00 2001 From: Sudharsan Dhamal Gopalarathnam Date: Mon, 13 Sep 2021 07:22:17 -0700 Subject: [PATCH 07/34] [Mellanox] Remove 2x40G from SN3800 hwsku (#8712) - Why I did it Removed 2x40G for SN3800. This mode is not supported by hardware. - How I did it Removing it from hwsku.json and platform.json - How to verify it Load it in the device and check supported modes --- .../Mellanox-SN3800-D100C12S2/hwsku.json | 200 +++++++++--------- .../x86_64-mlnx_msn3800-r0/platform.json | 128 +++++------ 2 files changed, 164 insertions(+), 164 deletions(-) diff --git a/device/mellanox/x86_64-mlnx_msn3800-r0/Mellanox-SN3800-D100C12S2/hwsku.json b/device/mellanox/x86_64-mlnx_msn3800-r0/Mellanox-SN3800-D100C12S2/hwsku.json index 87724d4e4c00..2b1d5d322282 100644 --- a/device/mellanox/x86_64-mlnx_msn3800-r0/Mellanox-SN3800-D100C12S2/hwsku.json +++ b/device/mellanox/x86_64-mlnx_msn3800-r0/Mellanox-SN3800-D100C12S2/hwsku.json @@ -1,310 +1,310 @@ { "interfaces": { "Ethernet0": { - "default_brkout_mode": "2x50G[40G,25G,10G]" + "default_brkout_mode": "2x50G[25G,10G]" }, "Ethernet2": { - "default_brkout_mode": "2x50G[40G,25G,10G]" + "default_brkout_mode": "2x50G[25G,10G]" }, "Ethernet4": { - "default_brkout_mode": "2x50G[40G,25G,10G]" + "default_brkout_mode": "2x50G[25G,10G]" }, "Ethernet6": { - "default_brkout_mode": "2x50G[40G,25G,10G]" + "default_brkout_mode": "2x50G[25G,10G]" }, "Ethernet8": { - "default_brkout_mode": "2x50G[40G,25G,10G]" + "default_brkout_mode": "2x50G[25G,10G]" }, "Ethernet10": { - "default_brkout_mode": "2x50G[40G,25G,10G]" + "default_brkout_mode": "2x50G[25G,10G]" }, "Ethernet12": { - "default_brkout_mode": "2x50G[40G,25G,10G]" + "default_brkout_mode": "2x50G[25G,10G]" }, "Ethernet14": { - "default_brkout_mode": "2x50G[40G,25G,10G]" + "default_brkout_mode": "2x50G[25G,10G]" }, "Ethernet16": { - "default_brkout_mode": "2x50G[40G,25G,10G]" + "default_brkout_mode": "2x50G[25G,10G]" }, "Ethernet18": { - "default_brkout_mode": "2x50G[40G,25G,10G]" + "default_brkout_mode": "2x50G[25G,10G]" }, "Ethernet20": { - "default_brkout_mode": "2x50G[40G,25G,10G]" + "default_brkout_mode": "2x50G[25G,10G]" }, "Ethernet22": { - "default_brkout_mode": "2x50G[40G,25G,10G]" + "default_brkout_mode": "2x50G[25G,10G]" }, "Ethernet24": { - "default_brkout_mode": "2x50G[40G,25G,10G]" + "default_brkout_mode": "2x50G[25G,10G]" }, "Ethernet26": { - "default_brkout_mode": "2x50G[40G,25G,10G]" + "default_brkout_mode": "2x50G[25G,10G]" }, "Ethernet28": { - "default_brkout_mode": "2x50G[40G,25G,10G]" + "default_brkout_mode": "2x50G[25G,10G]" }, "Ethernet30": { - "default_brkout_mode": "2x50G[40G,25G,10G]" + "default_brkout_mode": "2x50G[25G,10G]" }, "Ethernet32": { - "default_brkout_mode": "2x50G[40G,25G,10G]" + "default_brkout_mode": "2x50G[25G,10G]" }, "Ethernet34": { - "default_brkout_mode": "2x50G[40G,25G,10G]" + "default_brkout_mode": "2x50G[25G,10G]" }, "Ethernet36": { - "default_brkout_mode": "2x50G[40G,25G,10G]" + "default_brkout_mode": "2x50G[25G,10G]" }, "Ethernet38": { - "default_brkout_mode": "2x50G[40G,25G,10G]" + "default_brkout_mode": "2x50G[25G,10G]" }, "Ethernet40": { - "default_brkout_mode": "2x50G[40G,25G,10G]" + "default_brkout_mode": "2x50G[25G,10G]" }, "Ethernet42": { - "default_brkout_mode": "2x50G[40G,25G,10G]" + "default_brkout_mode": "2x50G[25G,10G]" }, "Ethernet44": { - "default_brkout_mode": "2x50G[40G,25G,10G]" + "default_brkout_mode": "2x50G[25G,10G]" }, "Ethernet46": { - "default_brkout_mode": "2x50G[40G,25G,10G]" + "default_brkout_mode": "2x50G[25G,10G]" }, "Ethernet48": { - "default_brkout_mode": "2x50G[40G,25G,10G]" + "default_brkout_mode": "2x50G[25G,10G]" }, "Ethernet50": { - "default_brkout_mode": "2x50G[40G,25G,10G]" + "default_brkout_mode": "2x50G[25G,10G]" }, "Ethernet52": { - "default_brkout_mode": "2x50G[40G,25G,10G]" + "default_brkout_mode": "2x50G[25G,10G]" }, "Ethernet54": { - "default_brkout_mode": "2x50G[40G,25G,10G]" + "default_brkout_mode": "2x50G[25G,10G]" }, "Ethernet56": { - "default_brkout_mode": "2x50G[40G,25G,10G]" + "default_brkout_mode": "2x50G[25G,10G]" }, "Ethernet58": { - "default_brkout_mode": "2x50G[40G,25G,10G]" + "default_brkout_mode": "2x50G[25G,10G]" }, "Ethernet60": { - "default_brkout_mode": "2x50G[40G,25G,10G]" + "default_brkout_mode": "2x50G[25G,10G]" }, "Ethernet62": { - "default_brkout_mode": "2x50G[40G,25G,10G]" + "default_brkout_mode": "2x50G[25G,10G]" }, "Ethernet64": { - "default_brkout_mode": "2x50G[40G,25G,10G]" + "default_brkout_mode": "2x50G[25G,10G]" }, "Ethernet66": { - "default_brkout_mode": "2x50G[40G,25G,10G]" + "default_brkout_mode": "2x50G[25G,10G]" }, "Ethernet68": { - "default_brkout_mode": "2x50G[40G,25G,10G]" + "default_brkout_mode": "2x50G[25G,10G]" }, "Ethernet70": { - "default_brkout_mode": "2x50G[40G,25G,10G]" + "default_brkout_mode": "2x50G[25G,10G]" }, "Ethernet72": { - "default_brkout_mode": "2x50G[40G,25G,10G]" + "default_brkout_mode": "2x50G[25G,10G]" }, "Ethernet74": { - "default_brkout_mode": "2x50G[40G,25G,10G]" + "default_brkout_mode": "2x50G[25G,10G]" }, "Ethernet76": { - "default_brkout_mode": "2x50G[40G,25G,10G]" + "default_brkout_mode": "2x50G[25G,10G]" }, "Ethernet78": { - "default_brkout_mode": "2x50G[40G,25G,10G]" + "default_brkout_mode": "2x50G[25G,10G]" }, "Ethernet80": { - "default_brkout_mode": "2x50G[40G,25G,10G]" + "default_brkout_mode": "2x50G[25G,10G]" }, "Ethernet82": { - "default_brkout_mode": "2x50G[40G,25G,10G]" + "default_brkout_mode": "2x50G[25G,10G]" }, "Ethernet84": { - "default_brkout_mode": "2x50G[40G,25G,10G]" + "default_brkout_mode": "2x50G[25G,10G]" }, "Ethernet86": { - "default_brkout_mode": "2x50G[40G,25G,10G]" + "default_brkout_mode": "2x50G[25G,10G]" }, "Ethernet88": { - "default_brkout_mode": "2x50G[40G,25G,10G]" + "default_brkout_mode": "2x50G[25G,10G]" }, "Ethernet90": { - "default_brkout_mode": "2x50G[40G,25G,10G]" + "default_brkout_mode": "2x50G[25G,10G]" }, "Ethernet92": { - "default_brkout_mode": "2x50G[40G,25G,10G]" + "default_brkout_mode": "2x50G[25G,10G]" }, "Ethernet94": { - "default_brkout_mode": "2x50G[40G,25G,10G]" + "default_brkout_mode": "2x50G[25G,10G]" }, "Ethernet96": { - "default_brkout_mode": "2x50G[40G,25G,10G]" + "default_brkout_mode": "2x50G[25G,10G]" }, "Ethernet98": { - "default_brkout_mode": "2x50G[40G,25G,10G]" + "default_brkout_mode": "2x50G[25G,10G]" }, "Ethernet100": { - "default_brkout_mode": "2x50G[40G,25G,10G]" + "default_brkout_mode": "2x50G[25G,10G]" }, "Ethernet102": { - "default_brkout_mode": "2x50G[40G,25G,10G]" + "default_brkout_mode": "2x50G[25G,10G]" }, "Ethernet104": { - "default_brkout_mode": "2x50G[40G,25G,10G]" + "default_brkout_mode": "2x50G[25G,10G]" }, "Ethernet106": { - "default_brkout_mode": "2x50G[40G,25G,10G]" + "default_brkout_mode": "2x50G[25G,10G]" }, "Ethernet108": { - "default_brkout_mode": "2x50G[40G,25G,10G]" + "default_brkout_mode": "2x50G[25G,10G]" }, "Ethernet110": { - "default_brkout_mode": "2x50G[40G,25G,10G]" + "default_brkout_mode": "2x50G[25G,10G]" }, "Ethernet112": { - "default_brkout_mode": "2x50G[40G,25G,10G]" + "default_brkout_mode": "2x50G[25G,10G]" }, "Ethernet114": { - "default_brkout_mode": "2x50G[40G,25G,10G]" + "default_brkout_mode": "2x50G[25G,10G]" }, "Ethernet116": { - "default_brkout_mode": "2x50G[40G,25G,10G]" + "default_brkout_mode": "2x50G[25G,10G]" }, "Ethernet118": { - "default_brkout_mode": "2x50G[40G,25G,10G]" + "default_brkout_mode": "2x50G[25G,10G]" }, "Ethernet120": { - "default_brkout_mode": "2x50G[40G,25G,10G]" + "default_brkout_mode": "2x50G[25G,10G]" }, "Ethernet122": { - "default_brkout_mode": "2x50G[40G,25G,10G]" + "default_brkout_mode": "2x50G[25G,10G]" }, "Ethernet124": { - "default_brkout_mode": "2x50G[40G,25G,10G]" + "default_brkout_mode": "2x50G[25G,10G]" }, "Ethernet126": { - "default_brkout_mode": "2x50G[40G,25G,10G]" + "default_brkout_mode": "2x50G[25G,10G]" }, "Ethernet128": { - "default_brkout_mode": "2x50G[40G,25G,10G]" + "default_brkout_mode": "2x50G[25G,10G]" }, "Ethernet130": { - "default_brkout_mode": "2x50G[40G,25G,10G]" + "default_brkout_mode": "2x50G[25G,10G]" }, "Ethernet132": { - "default_brkout_mode": "2x50G[40G,25G,10G]" + "default_brkout_mode": "2x50G[25G,10G]" }, "Ethernet134": { - "default_brkout_mode": "2x50G[40G,25G,10G]" + "default_brkout_mode": "2x50G[25G,10G]" }, "Ethernet136": { - "default_brkout_mode": "2x50G[40G,25G,10G]" + "default_brkout_mode": "2x50G[25G,10G]" }, "Ethernet138": { - "default_brkout_mode": "2x50G[40G,25G,10G]" + "default_brkout_mode": "2x50G[25G,10G]" }, "Ethernet140": { - "default_brkout_mode": "2x50G[40G,25G,10G]" + "default_brkout_mode": "2x50G[25G,10G]" }, "Ethernet142": { - "default_brkout_mode": "2x50G[40G,25G,10G]" + "default_brkout_mode": "2x50G[25G,10G]" }, "Ethernet144": { - "default_brkout_mode": "2x50G[40G,25G,10G]" + "default_brkout_mode": "2x50G[25G,10G]" }, "Ethernet146": { - "default_brkout_mode": "2x50G[40G,25G,10G]" + "default_brkout_mode": "2x50G[25G,10G]" }, "Ethernet148": { "default_brkout_mode": "1x10G[100G,50G,40G,25G]" }, "Ethernet152": { - "default_brkout_mode": "2x50G[40G,25G,10G]" + "default_brkout_mode": "2x50G[25G,10G]" }, "Ethernet154": { - "default_brkout_mode": "2x50G[40G,25G,10G]" + "default_brkout_mode": "2x50G[25G,10G]" }, "Ethernet156": { "default_brkout_mode": "1x10G[100G,50G,40G,25G]" }, "Ethernet160": { - "default_brkout_mode": "2x50G[40G,25G,10G]" + "default_brkout_mode": "2x50G[25G,10G]" }, "Ethernet162": { - "default_brkout_mode": "2x50G[40G,25G,10G]" + "default_brkout_mode": "2x50G[25G,10G]" }, "Ethernet164": { - "default_brkout_mode": "2x50G[40G,25G,10G]" + "default_brkout_mode": "2x50G[25G,10G]" }, "Ethernet166": { - "default_brkout_mode": "2x50G[40G,25G,10G]" + "default_brkout_mode": "2x50G[25G,10G]" }, "Ethernet168": { - "default_brkout_mode": "2x50G[40G,25G,10G]" + "default_brkout_mode": "2x50G[25G,10G]" }, "Ethernet170": { - "default_brkout_mode": "2x50G[40G,25G,10G]" + "default_brkout_mode": "2x50G[25G,10G]" }, "Ethernet172": { - "default_brkout_mode": "2x50G[40G,25G,10G]" + "default_brkout_mode": "2x50G[25G,10G]" }, "Ethernet174": { - "default_brkout_mode": "2x50G[40G,25G,10G]" + "default_brkout_mode": "2x50G[25G,10G]" }, "Ethernet176": { - "default_brkout_mode": "2x50G[40G,25G,10G]" + "default_brkout_mode": "2x50G[25G,10G]" }, "Ethernet178": { - "default_brkout_mode": "2x50G[40G,25G,10G]" + "default_brkout_mode": "2x50G[25G,10G]" }, "Ethernet180": { - "default_brkout_mode": "2x50G[40G,25G,10G]" + "default_brkout_mode": "2x50G[25G,10G]" }, "Ethernet182": { - "default_brkout_mode": "2x50G[40G,25G,10G]" + "default_brkout_mode": "2x50G[25G,10G]" }, "Ethernet184": { - "default_brkout_mode": "2x50G[40G,25G,10G]" + "default_brkout_mode": "2x50G[25G,10G]" }, "Ethernet186": { - "default_brkout_mode": "2x50G[40G,25G,10G]" + "default_brkout_mode": "2x50G[25G,10G]" }, "Ethernet188": { - "default_brkout_mode": "2x50G[40G,25G,10G]" + "default_brkout_mode": "2x50G[25G,10G]" }, "Ethernet190": { - "default_brkout_mode": "2x50G[40G,25G,10G]" + "default_brkout_mode": "2x50G[25G,10G]" }, "Ethernet192": { - "default_brkout_mode": "2x50G[40G,25G,10G]" + "default_brkout_mode": "2x50G[25G,10G]" }, "Ethernet194": { - "default_brkout_mode": "2x50G[40G,25G,10G]" + "default_brkout_mode": "2x50G[25G,10G]" }, "Ethernet196": { - "default_brkout_mode": "2x50G[40G,25G,10G]" + "default_brkout_mode": "2x50G[25G,10G]" }, "Ethernet198": { - "default_brkout_mode": "2x50G[40G,25G,10G]" + "default_brkout_mode": "2x50G[25G,10G]" }, "Ethernet200": { - "default_brkout_mode": "2x50G[40G,25G,10G]" + "default_brkout_mode": "2x50G[25G,10G]" }, "Ethernet202": { - "default_brkout_mode": "2x50G[40G,25G,10G]" + "default_brkout_mode": "2x50G[25G,10G]" }, "Ethernet204": { - "default_brkout_mode": "2x50G[40G,25G,10G]" + "default_brkout_mode": "2x50G[25G,10G]" }, "Ethernet206": { - "default_brkout_mode": "2x50G[40G,25G,10G]" + "default_brkout_mode": "2x50G[25G,10G]" }, "Ethernet208": { "default_brkout_mode": "1x100G[50G,40G,25G,10G]" diff --git a/device/mellanox/x86_64-mlnx_msn3800-r0/platform.json b/device/mellanox/x86_64-mlnx_msn3800-r0/platform.json index 2cd4a13c6cfd..92865e228ee5 100644 --- a/device/mellanox/x86_64-mlnx_msn3800-r0/platform.json +++ b/device/mellanox/x86_64-mlnx_msn3800-r0/platform.json @@ -726,7 +726,7 @@ "breakout_modes": { "1x100G[50G,40G,25G,10G]": ["etp1"], "1x10G[100G,50G,40G,25G]": ["etp1"], - "2x50G[40G,25G,10G]": ["etp1a", "etp1b"] + "2x50G[25G,10G]": ["etp1a", "etp1b"] } }, "Ethernet4": { @@ -735,7 +735,7 @@ "breakout_modes": { "1x100G[50G,40G,25G,10G]": ["etp2"], "1x10G[100G,50G,40G,25G]": ["etp2"], - "2x50G[40G,25G,10G]": ["etp2a", "etp2b"] + "2x50G[25G,10G]": ["etp2a", "etp2b"] } }, "Ethernet8": { @@ -744,7 +744,7 @@ "breakout_modes": { "1x100G[50G,40G,25G,10G]": ["etp3"], "1x10G[100G,50G,40G,25G]": ["etp3"], - "2x50G[40G,25G,10G]": ["etp3a", "etp3b"] + "2x50G[25G,10G]": ["etp3a", "etp3b"] } }, "Ethernet12": { @@ -753,7 +753,7 @@ "breakout_modes": { "1x100G[50G,40G,25G,10G]": ["etp4"], "1x10G[100G,50G,40G,25G]": ["etp4"], - "2x50G[40G,25G,10G]": ["etp4a", "etp4b"] + "2x50G[25G,10G]": ["etp4a", "etp4b"] } }, "Ethernet16": { @@ -762,7 +762,7 @@ "breakout_modes": { "1x100G[50G,40G,25G,10G]": ["etp5"], "1x10G[100G,50G,40G,25G]": ["etp5"], - "2x50G[40G,25G,10G]": ["etp5a", "etp5b"] + "2x50G[25G,10G]": ["etp5a", "etp5b"] } }, "Ethernet20": { @@ -771,7 +771,7 @@ "breakout_modes": { "1x100G[50G,40G,25G,10G]": ["etp6"], "1x10G[100G,50G,40G,25G]": ["etp6"], - "2x50G[40G,25G,10G]": ["etp6a", "etp6b"] + "2x50G[25G,10G]": ["etp6a", "etp6b"] } }, "Ethernet24": { @@ -780,7 +780,7 @@ "breakout_modes": { "1x100G[50G,40G,25G,10G]": ["etp7"], "1x10G[100G,50G,40G,25G]": ["etp7"], - "2x50G[40G,25G,10G]": ["etp7a", "etp7b"] + "2x50G[25G,10G]": ["etp7a", "etp7b"] } }, "Ethernet28": { @@ -789,7 +789,7 @@ "breakout_modes": { "1x100G[50G,40G,25G,10G]": ["etp8"], "1x10G[100G,50G,40G,25G]": ["etp8"], - "2x50G[40G,25G,10G]": ["etp8a", "etp8b"] + "2x50G[25G,10G]": ["etp8a", "etp8b"] } }, "Ethernet32": { @@ -798,7 +798,7 @@ "breakout_modes": { "1x100G[50G,40G,25G,10G]": ["etp9"], "1x10G[100G,50G,40G,25G]": ["etp9"], - "2x50G[40G,25G,10G]": ["etp9a", "etp9b"] + "2x50G[25G,10G]": ["etp9a", "etp9b"] } }, "Ethernet36": { @@ -807,7 +807,7 @@ "breakout_modes": { "1x100G[50G,40G,25G,10G]": ["etp10"], "1x10G[100G,50G,40G,25G]": ["etp10"], - "2x50G[40G,25G,10G]": ["etp10a", "etp10b"] + "2x50G[25G,10G]": ["etp10a", "etp10b"] } }, "Ethernet40": { @@ -816,7 +816,7 @@ "breakout_modes": { "1x100G[50G,40G,25G,10G]": ["etp11"], "1x10G[100G,50G,40G,25G]": ["etp11"], - "2x50G[40G,25G,10G]": ["etp11a", "etp11b"] + "2x50G[25G,10G]": ["etp11a", "etp11b"] } }, "Ethernet44": { @@ -825,7 +825,7 @@ "breakout_modes": { "1x100G[50G,40G,25G,10G]": ["etp12"], "1x10G[100G,50G,40G,25G]": ["etp12"], - "2x50G[40G,25G,10G]": ["etp12a", "etp12b"] + "2x50G[25G,10G]": ["etp12a", "etp12b"] } }, "Ethernet48": { @@ -834,7 +834,7 @@ "breakout_modes": { "1x100G[50G,40G,25G,10G]": ["etp13"], "1x10G[100G,50G,40G,25G]": ["etp13"], - "2x50G[40G,25G,10G]": ["etp13a", "etp13b"] + "2x50G[25G,10G]": ["etp13a", "etp13b"] } }, "Ethernet52": { @@ -843,7 +843,7 @@ "breakout_modes": { "1x100G[50G,40G,25G,10G]": ["etp14"], "1x10G[100G,50G,40G,25G]": ["etp14"], - "2x50G[40G,25G,10G]": ["etp14a", "etp14b"] + "2x50G[25G,10G]": ["etp14a", "etp14b"] } }, "Ethernet56": { @@ -852,7 +852,7 @@ "breakout_modes": { "1x100G[50G,40G,25G,10G]": ["etp15"], "1x10G[100G,50G,40G,25G]": ["etp15"], - "2x50G[40G,25G,10G]": ["etp15a", "etp15b"] + "2x50G[25G,10G]": ["etp15a", "etp15b"] } }, "Ethernet60": { @@ -861,7 +861,7 @@ "breakout_modes": { "1x100G[50G,40G,25G,10G]": ["etp16"], "1x10G[100G,50G,40G,25G]": ["etp16"], - "2x50G[40G,25G,10G]": ["etp16a", "etp16b"] + "2x50G[25G,10G]": ["etp16a", "etp16b"] } }, "Ethernet64": { @@ -870,7 +870,7 @@ "breakout_modes": { "1x100G[50G,40G,25G,10G]": ["etp17"], "1x10G[100G,50G,40G,25G]": ["etp17"], - "2x50G[40G,25G,10G]": ["etp17a", "etp17b"] + "2x50G[25G,10G]": ["etp17a", "etp17b"] } }, "Ethernet68": { @@ -879,7 +879,7 @@ "breakout_modes": { "1x100G[50G,40G,25G,10G]": ["etp18"], "1x10G[100G,50G,40G,25G]": ["etp18"], - "2x50G[40G,25G,10G]": ["etp18a", "etp18b"] + "2x50G[25G,10G]": ["etp18a", "etp18b"] } }, "Ethernet72": { @@ -888,7 +888,7 @@ "breakout_modes": { "1x100G[50G,40G,25G,10G]": ["etp19"], "1x10G[100G,50G,40G,25G]": ["etp19"], - "2x50G[40G,25G,10G]": ["etp19a", "etp19b"] + "2x50G[25G,10G]": ["etp19a", "etp19b"] } }, "Ethernet76": { @@ -897,7 +897,7 @@ "breakout_modes": { "1x100G[50G,40G,25G,10G]": ["etp20"], "1x10G[100G,50G,40G,25G]": ["etp20"], - "2x50G[40G,25G,10G]": ["etp20a", "etp20b"] + "2x50G[25G,10G]": ["etp20a", "etp20b"] } }, "Ethernet80": { @@ -906,7 +906,7 @@ "breakout_modes": { "1x100G[50G,40G,25G,10G]": ["etp21"], "1x10G[100G,50G,40G,25G]": ["etp21"], - "2x50G[40G,25G,10G]": ["etp21a", "etp21b"] + "2x50G[25G,10G]": ["etp21a", "etp21b"] } }, "Ethernet84": { @@ -915,7 +915,7 @@ "breakout_modes": { "1x100G[50G,40G,25G,10G]": ["etp22"], "1x10G[100G,50G,40G,25G]": ["etp22"], - "2x50G[40G,25G,10G]": ["etp22a", "etp22b"] + "2x50G[25G,10G]": ["etp22a", "etp22b"] } }, "Ethernet88": { @@ -924,7 +924,7 @@ "breakout_modes": { "1x100G[50G,40G,25G,10G]": ["etp23"], "1x10G[100G,50G,40G,25G]": ["etp23"], - "2x50G[40G,25G,10G]": ["etp23a", "etp23b"] + "2x50G[25G,10G]": ["etp23a", "etp23b"] } }, "Ethernet92": { @@ -933,7 +933,7 @@ "breakout_modes": { "1x100G[50G,40G,25G,10G]": ["etp24"], "1x10G[100G,50G,40G,25G]": ["etp24"], - "2x50G[40G,25G,10G]": ["etp24a", "etp24b"] + "2x50G[25G,10G]": ["etp24a", "etp24b"] } }, "Ethernet96": { @@ -942,7 +942,7 @@ "breakout_modes": { "1x100G[50G,40G,25G,10G]": ["etp25"], "1x10G[100G,50G,40G,25G]": ["etp25"], - "2x50G[40G,25G,10G]": ["etp25a", "etp25b"] + "2x50G[25G,10G]": ["etp25a", "etp25b"] } }, "Ethernet100": { @@ -951,7 +951,7 @@ "breakout_modes": { "1x100G[50G,40G,25G,10G]": ["etp26"], "1x10G[100G,50G,40G,25G]": ["etp26"], - "2x50G[40G,25G,10G]": ["etp26a", "etp26b"] + "2x50G[25G,10G]": ["etp26a", "etp26b"] } }, "Ethernet104": { @@ -960,7 +960,7 @@ "breakout_modes": { "1x100G[50G,40G,25G,10G]": ["etp27"], "1x10G[100G,50G,40G,25G]": ["etp27"], - "2x50G[40G,25G,10G]": ["etp27a", "etp27b"] + "2x50G[25G,10G]": ["etp27a", "etp27b"] } }, "Ethernet108": { @@ -969,7 +969,7 @@ "breakout_modes": { "1x100G[50G,40G,25G,10G]": ["etp28"], "1x10G[100G,50G,40G,25G]": ["etp28"], - "2x50G[40G,25G,10G]": ["etp28a", "etp28b"] + "2x50G[25G,10G]": ["etp28a", "etp28b"] } }, "Ethernet112": { @@ -978,7 +978,7 @@ "breakout_modes": { "1x100G[50G,40G,25G,10G]": ["etp29"], "1x10G[100G,50G,40G,25G]": ["etp29"], - "2x50G[40G,25G,10G]": ["etp29a", "etp29b"] + "2x50G[25G,10G]": ["etp29a", "etp29b"] } }, "Ethernet116": { @@ -987,7 +987,7 @@ "breakout_modes": { "1x100G[50G,40G,25G,10G]": ["etp30"], "1x10G[100G,50G,40G,25G]": ["etp30"], - "2x50G[40G,25G,10G]": ["etp30a", "etp30b"] + "2x50G[25G,10G]": ["etp30a", "etp30b"] } }, "Ethernet120": { @@ -996,7 +996,7 @@ "breakout_modes": { "1x100G[50G,40G,25G,10G]": ["etp31"], "1x10G[100G,50G,40G,25G]": ["etp31"], - "2x50G[40G,25G,10G]": ["etp31a", "etp31b"] + "2x50G[25G,10G]": ["etp31a", "etp31b"] } }, "Ethernet124": { @@ -1005,7 +1005,7 @@ "breakout_modes": { "1x100G[50G,40G,25G,10G]": ["etp32"], "1x10G[100G,50G,40G,25G]": ["etp32"], - "2x50G[40G,25G,10G]": ["etp32a", "etp32b"] + "2x50G[25G,10G]": ["etp32a", "etp32b"] } }, "Ethernet128": { @@ -1014,7 +1014,7 @@ "breakout_modes": { "1x100G[50G,40G,25G,10G]": ["etp33"], "1x10G[100G,50G,40G,25G]": ["etp33"], - "2x50G[40G,25G,10G]": ["etp33a", "etp33b"] + "2x50G[25G,10G]": ["etp33a", "etp33b"] } }, "Ethernet132": { @@ -1023,7 +1023,7 @@ "breakout_modes": { "1x100G[50G,40G,25G,10G]": ["etp34"], "1x10G[100G,50G,40G,25G]": ["etp34"], - "2x50G[40G,25G,10G]": ["etp34a", "etp34b"] + "2x50G[25G,10G]": ["etp34a", "etp34b"] } }, "Ethernet136": { @@ -1032,7 +1032,7 @@ "breakout_modes": { "1x100G[50G,40G,25G,10G]": ["etp35"], "1x10G[100G,50G,40G,25G]": ["etp35"], - "2x50G[40G,25G,10G]": ["etp35a", "etp35b"] + "2x50G[25G,10G]": ["etp35a", "etp35b"] } }, "Ethernet140": { @@ -1041,7 +1041,7 @@ "breakout_modes": { "1x100G[50G,40G,25G,10G]": ["etp36"], "1x10G[100G,50G,40G,25G]": ["etp36"], - "2x50G[40G,25G,10G]": ["etp36a", "etp36b"] + "2x50G[25G,10G]": ["etp36a", "etp36b"] } }, "Ethernet144": { @@ -1050,7 +1050,7 @@ "breakout_modes": { "1x100G[50G,40G,25G,10G]": ["etp37"], "1x10G[100G,50G,40G,25G]": ["etp37"], - "2x50G[40G,25G,10G]": ["etp37a", "etp37b"] + "2x50G[25G,10G]": ["etp37a", "etp37b"] } }, "Ethernet148": { @@ -1059,7 +1059,7 @@ "breakout_modes": { "1x100G[50G,40G,25G,10G]": ["etp38"], "1x10G[100G,50G,40G,25G]": ["etp38"], - "2x50G[40G,25G,10G]": ["etp38a", "etp38b"] + "2x50G[25G,10G]": ["etp38a", "etp38b"] } }, "Ethernet152": { @@ -1068,7 +1068,7 @@ "breakout_modes": { "1x100G[50G,40G,25G,10G]": ["etp39"], "1x10G[100G,50G,40G,25G]": ["etp39"], - "2x50G[40G,25G,10G]": ["etp39a", "etp39b"] + "2x50G[25G,10G]": ["etp39a", "etp39b"] } }, "Ethernet156": { @@ -1077,7 +1077,7 @@ "breakout_modes": { "1x100G[50G,40G,25G,10G]": ["etp40"], "1x10G[100G,50G,40G,25G]": ["etp40"], - "2x50G[40G,25G,10G]": ["etp40a", "etp40b"] + "2x50G[25G,10G]": ["etp40a", "etp40b"] } }, "Ethernet160": { @@ -1086,7 +1086,7 @@ "breakout_modes": { "1x100G[50G,40G,25G,10G]": ["etp41"], "1x10G[100G,50G,40G,25G]": ["etp41"], - "2x50G[40G,25G,10G]": ["etp41a", "etp41b"] + "2x50G[25G,10G]": ["etp41a", "etp41b"] } }, "Ethernet164": { @@ -1095,7 +1095,7 @@ "breakout_modes": { "1x100G[50G,40G,25G,10G]": ["etp42"], "1x10G[100G,50G,40G,25G]": ["etp42"], - "2x50G[40G,25G,10G]": ["etp42a", "etp42b"] + "2x50G[25G,10G]": ["etp42a", "etp42b"] } }, "Ethernet168": { @@ -1104,7 +1104,7 @@ "breakout_modes": { "1x100G[50G,40G,25G,10G]": ["etp43"], "1x10G[100G,50G,40G,25G]": ["etp43"], - "2x50G[40G,25G,10G]": ["etp43a", "etp43b"] + "2x50G[25G,10G]": ["etp43a", "etp43b"] } }, "Ethernet172": { @@ -1113,7 +1113,7 @@ "breakout_modes": { "1x100G[50G,40G,25G,10G]": ["etp44"], "1x10G[100G,50G,40G,25G]": ["etp44"], - "2x50G[40G,25G,10G]": ["etp44a", "etp44b"] + "2x50G[25G,10G]": ["etp44a", "etp44b"] } }, "Ethernet176": { @@ -1122,7 +1122,7 @@ "breakout_modes": { "1x100G[50G,40G,25G,10G]": ["etp45"], "1x10G[100G,50G,40G,25G]": ["etp45"], - "2x50G[40G,25G,10G]": ["etp45a", "etp45b"] + "2x50G[25G,10G]": ["etp45a", "etp45b"] } }, "Ethernet180": { @@ -1131,7 +1131,7 @@ "breakout_modes": { "1x100G[50G,40G,25G,10G]": ["etp46"], "1x10G[100G,50G,40G,25G]": ["etp46"], - "2x50G[40G,25G,10G]": ["etp46a", "etp46b"] + "2x50G[25G,10G]": ["etp46a", "etp46b"] } }, "Ethernet184": { @@ -1140,7 +1140,7 @@ "breakout_modes": { "1x100G[50G,40G,25G,10G]": ["etp47"], "1x10G[100G,50G,40G,25G]": ["etp47"], - "2x50G[40G,25G,10G]": ["etp47a", "etp47b"] + "2x50G[25G,10G]": ["etp47a", "etp47b"] } }, "Ethernet188": { @@ -1149,7 +1149,7 @@ "breakout_modes": { "1x100G[50G,40G,25G,10G]": ["etp48"], "1x10G[100G,50G,40G,25G]": ["etp48"], - "2x50G[40G,25G,10G]": ["etp48a", "etp48b"] + "2x50G[25G,10G]": ["etp48a", "etp48b"] } }, "Ethernet192": { @@ -1158,7 +1158,7 @@ "breakout_modes": { "1x100G[50G,40G,25G,10G]": ["etp49"], "1x10G[100G,50G,40G,25G]": ["etp49"], - "2x50G[40G,25G,10G]": ["etp49a", "etp49b"] + "2x50G[25G,10G]": ["etp49a", "etp49b"] } }, "Ethernet196": { @@ -1167,7 +1167,7 @@ "breakout_modes": { "1x100G[50G,40G,25G,10G]": ["etp50"], "1x10G[100G,50G,40G,25G]": ["etp50"], - "2x50G[40G,25G,10G]": ["etp50a", "etp50b"] + "2x50G[25G,10G]": ["etp50a", "etp50b"] } }, "Ethernet200": { @@ -1176,7 +1176,7 @@ "breakout_modes": { "1x100G[50G,40G,25G,10G]": ["etp51"], "1x10G[100G,50G,40G,25G]": ["etp51"], - "2x50G[40G,25G,10G]": ["etp51a", "etp51b"] + "2x50G[25G,10G]": ["etp51a", "etp51b"] } }, "Ethernet204": { @@ -1185,7 +1185,7 @@ "breakout_modes": { "1x100G[50G,40G,25G,10G]": ["etp52"], "1x10G[100G,50G,40G,25G]": ["etp52"], - "2x50G[40G,25G,10G]": ["etp52a", "etp52b"] + "2x50G[25G,10G]": ["etp52a", "etp52b"] } }, "Ethernet208": { @@ -1194,7 +1194,7 @@ "breakout_modes": { "1x100G[50G,40G,25G,10G]": ["etp53"], "1x10G[100G,50G,40G,25G]": ["etp53"], - "2x50G[40G,25G,10G]": ["etp53a", "etp53b"] + "2x50G[25G,10G]": ["etp53a", "etp53b"] } }, "Ethernet212": { @@ -1203,7 +1203,7 @@ "breakout_modes": { "1x100G[50G,40G,25G,10G]": ["etp54"], "1x10G[100G,50G,40G,25G]": ["etp54"], - "2x50G[40G,25G,10G]": ["etp54a", "etp54b"] + "2x50G[25G,10G]": ["etp54a", "etp54b"] } }, "Ethernet216": { @@ -1212,7 +1212,7 @@ "breakout_modes": { "1x100G[50G,40G,25G,10G]": ["etp55"], "1x10G[100G,50G,40G,25G]": ["etp55"], - "2x50G[40G,25G,10G]": ["etp55a", "etp55b"] + "2x50G[25G,10G]": ["etp55a", "etp55b"] } }, "Ethernet220": { @@ -1221,7 +1221,7 @@ "breakout_modes": { "1x100G[50G,40G,25G,10G]": ["etp56"], "1x10G[100G,50G,40G,25G]": ["etp56"], - "2x50G[40G,25G,10G]": ["etp56a", "etp56b"] + "2x50G[25G,10G]": ["etp56a", "etp56b"] } }, "Ethernet224": { @@ -1230,7 +1230,7 @@ "breakout_modes": { "1x100G[50G,40G,25G,10G]": ["etp57"], "1x10G[100G,50G,40G,25G]": ["etp57"], - "2x50G[40G,25G,10G]": ["etp57a", "etp57b"] + "2x50G[25G,10G]": ["etp57a", "etp57b"] } }, "Ethernet228": { @@ -1239,7 +1239,7 @@ "breakout_modes": { "1x100G[50G,40G,25G,10G]": ["etp58"], "1x10G[100G,50G,40G,25G]": ["etp58"], - "2x50G[40G,25G,10G]": ["etp58a", "etp58b"] + "2x50G[25G,10G]": ["etp58a", "etp58b"] } }, "Ethernet232": { @@ -1248,7 +1248,7 @@ "breakout_modes": { "1x100G[50G,40G,25G,10G]": ["etp59"], "1x10G[100G,50G,40G,25G]": ["etp59"], - "2x50G[40G,25G,10G]": ["etp59a", "etp59b"] + "2x50G[25G,10G]": ["etp59a", "etp59b"] } }, "Ethernet236": { @@ -1257,7 +1257,7 @@ "breakout_modes": { "1x100G[50G,40G,25G,10G]": ["etp60"], "1x10G[100G,50G,40G,25G]": ["etp60"], - "2x50G[40G,25G,10G]": ["etp60a", "etp60b"] + "2x50G[25G,10G]": ["etp60a", "etp60b"] } }, "Ethernet240": { @@ -1266,7 +1266,7 @@ "breakout_modes": { "1x100G[50G,40G,25G,10G]": ["etp61"], "1x10G[100G,50G,40G,25G]": ["etp61"], - "2x50G[40G,25G,10G]": ["etp61a", "etp61b"] + "2x50G[25G,10G]": ["etp61a", "etp61b"] } }, "Ethernet244": { @@ -1275,7 +1275,7 @@ "breakout_modes": { "1x100G[50G,40G,25G,10G]": ["etp62"], "1x10G[100G,50G,40G,25G]": ["etp62"], - "2x50G[40G,25G,10G]": ["etp62a", "etp62b"] + "2x50G[25G,10G]": ["etp62a", "etp62b"] } }, "Ethernet248": { @@ -1284,7 +1284,7 @@ "breakout_modes": { "1x100G[50G,40G,25G,10G]": ["etp63"], "1x10G[100G,50G,40G,25G]": ["etp63"], - "2x50G[40G,25G,10G]": ["etp63a", "etp63b"] + "2x50G[25G,10G]": ["etp63a", "etp63b"] } }, "Ethernet252": { @@ -1293,7 +1293,7 @@ "breakout_modes": { "1x100G[50G,40G,25G,10G]": ["etp64"], "1x10G[100G,50G,40G,25G]": ["etp64"], - "2x50G[40G,25G,10G]": ["etp64a", "etp64b"] + "2x50G[25G,10G]": ["etp64a", "etp64b"] } } } From 41643a9729011fb41b44c1d74a4c17f0b9a7ed42 Mon Sep 17 00:00:00 2001 From: Ying Xie Date: Mon, 13 Sep 2021 07:37:46 -0700 Subject: [PATCH 08/34] [202012][fstrim] delay fstrim timer after sonic.target (#8737) Why I did it fstrim has dependency on pmon docker. How I did it start fstrim timer after sonic.target. How to verify it local test and PR test. Signed-off-by: Ying Xie ying.xie@microsoft.com --- files/image_config/fstrim/fstrim.timer | 1 + 1 file changed, 1 insertion(+) diff --git a/files/image_config/fstrim/fstrim.timer b/files/image_config/fstrim/fstrim.timer index c6142dd94826..3ffb2332b7a6 100644 --- a/files/image_config/fstrim/fstrim.timer +++ b/files/image_config/fstrim/fstrim.timer @@ -1,6 +1,7 @@ [Unit] Description=Discard unused blocks once a week Documentation=man:fstrim +After=sonic.target [Timer] OnCalendar=weekly From b423b17221fb9a747eacf36bd44ec81232bb9b3f Mon Sep 17 00:00:00 2001 From: Sudharsan Dhamal Gopalarathnam Date: Mon, 13 Sep 2021 09:01:29 -0700 Subject: [PATCH 09/34] [DPB]Removing default admin status initialization in DPB flow while loading minigraph (#8711) To Fix #8697 . The config load_minigraph initializes 'admin_status' to up when platform.json has DPB configs. This doesn't happen when using port_config.ini The update minigraph has logic to initialize only the ports whose neighbors are defined or those belonging to portchannel However, a change was introduced to have default admin status to be 'up' in portconfig.py when the minigraph was using platform.json This will lead to sanity check failure in sonic-mgmt and thus no test cases could be run --- .../sample_output/sample_new_port_config.json | 32 ----- src/sonic-config-engine/portconfig.py | 1 - .../tests/platform-sample-graph.xml | 118 ++++++++++++++++++ .../tests/sample_output/platform_output.json | 79 +----------- .../tests/test_cfggen_platformJson.py | 22 ++-- 5 files changed, 133 insertions(+), 119 deletions(-) create mode 100644 src/sonic-config-engine/tests/platform-sample-graph.xml diff --git a/platform/vs/tests/breakout/sample_output/sample_new_port_config.json b/platform/vs/tests/breakout/sample_output/sample_new_port_config.json index 7c5c190a3330..442224ea6d6e 100644 --- a/platform/vs/tests/breakout/sample_output/sample_new_port_config.json +++ b/platform/vs/tests/breakout/sample_output/sample_new_port_config.json @@ -2,14 +2,12 @@ "Ethernet0_2x50G": { "Ethernet2": { "alias": "fortyGigE0/2", - "admin_status": "up", "lanes": "27,28", "speed": "50000", "index": "0" }, "Ethernet0": { "alias": "fortyGigE0/0", - "admin_status": "up", "lanes": "25,26", "speed": "50000", "index": "0" @@ -18,21 +16,18 @@ "Ethernet12_1x50G_2x25G": { "Ethernet12": { "alias": "fortyGigE0/12", - "admin_status": "up", "lanes": "37,38", "speed": "50000", "index": "3" }, "Ethernet14": { "alias": "fortyGigE0/14", - "admin_status": "up", "lanes": "39", "speed": "25000", "index": "3" }, "Ethernet15": { "alias": "fortyGigE0/15", - "admin_status": "up", "lanes": "40", "speed": "25000", "index": "3" @@ -41,14 +36,12 @@ "Ethernet0_2x50G": { "Ethernet2": { "alias": "fortyGigE0/2", - "admin_status": "up", "lanes": "27,28", "speed": "50000", "index": "0" }, "Ethernet0": { "alias": "fortyGigE0/0", - "admin_status": "up", "lanes": "25,26", "speed": "50000", "index": "0" @@ -57,7 +50,6 @@ "Ethernet0_1x100G": { "Ethernet0": { "alias": "fortyGigE0/0", - "admin_status": "up", "lanes": "25,26,27,28", "speed": "100000", "index": "0" @@ -66,28 +58,24 @@ "Ethernet0_4x25G": { "Ethernet2": { "alias": "fortyGigE0/2", - "admin_status": "up", "lanes": "27", "speed": "25000", "index": "0" }, "Ethernet3": { "alias": "fortyGigE0/3", - "admin_status": "up", "lanes": "28", "speed": "25000", "index": "0" }, "Ethernet0": { "alias": "fortyGigE0/0", - "admin_status": "up", "lanes": "25", "speed": "25000", "index": "0" }, "Ethernet1": { "alias": "fortyGigE0/1", - "admin_status": "up", "lanes": "26", "speed": "25000", "index": "0" @@ -96,21 +84,18 @@ "Ethernet0_2x25G_1x50G": { "Ethernet2": { "alias": "fortyGigE0/2", - "admin_status": "up", "lanes": "27,28", "speed": "50000", "index": "0" }, "Ethernet0": { "alias": "fortyGigE0/0", - "admin_status": "up", "lanes": "25", "speed": "25000", "index": "0" }, "Ethernet1": { "alias": "fortyGigE0/1", - "admin_status": "up", "lanes": "26", "speed": "25000", "index": "0" @@ -119,21 +104,18 @@ "Ethernet0_1x50G_2x25G": { "Ethernet2": { "alias": "fortyGigE0/2", - "admin_status": "up", "lanes": "27", "speed": "25000", "index": "0" }, "Ethernet3": { "alias": "fortyGigE0/3", - "admin_status": "up", "lanes": "28", "speed": "25000", "index": "0" }, "Ethernet0": { "alias": "fortyGigE0/0", - "admin_status": "up", "lanes": "25,26", "speed": "50000", "index": "0" @@ -142,28 +124,24 @@ "Ethernet4_4x25G": { "Ethernet6": { "alias": "fortyGigE0/6", - "admin_status": "up", "lanes": "31", "speed": "25000", "index": "1" }, "Ethernet7": { "alias": "fortyGigE0/7", - "admin_status": "up", "lanes": "32", "speed": "25000", "index": "1" }, "Ethernet4": { "alias": "fortyGigE0/4", - "admin_status": "up", "lanes": "29", "speed": "25000", "index": "1" }, "Ethernet5": { "alias": "fortyGigE0/5", - "admin_status": "up", "lanes": "30", "speed": "25000", "index": "1" @@ -172,14 +150,12 @@ "Ethernet4_2x50G": { "Ethernet6": { "alias": "fortyGigE0/6", - "admin_status": "up", "lanes": "31,32", "speed": "50000", "index": "1" }, "Ethernet4": { "alias": "fortyGigE0/4", - "admin_status": "up", "lanes": "29,30", "speed": "50000", "index": "1" @@ -188,14 +164,12 @@ "Ethernet8_2x50G": { "Ethernet8": { "alias": "fortyGigE0/8", - "admin_status": "up", "lanes": "33,34", "speed": "50000", "index": "2" }, "Ethernet10": { "alias": "fortyGigE0/10", - "admin_status": "up", "lanes": "35,36", "speed": "50000", "index": "2" @@ -204,14 +178,12 @@ "Ethernet8_1x50G_2x25G": { "Ethernet10": { "alias": "fortyGigE0/10", - "admin_status": "up", "lanes": "35", "speed": "25000", "index": "2" }, "Ethernet11": { "alias": "fortyGigE0/11", - "admin_status": "up", "lanes": "36", "speed": "25000", "index": "2" @@ -220,21 +192,18 @@ "Ethernet8_2x25G_1x50G": { "Ethernet8": { "alias": "fortyGigE0/8", - "admin_status": "up", "lanes": "33", "speed": "25000", "index": "2" }, "Ethernet9": { "alias": "fortyGigE0/9", - "admin_status": "up", "lanes": "34", "speed": "25000", "index": "2" }, "Ethernet10": { "alias": "fortyGigE0/10", - "admin_status": "up", "lanes": "35,36", "speed": "50000", "index": "2" @@ -243,7 +212,6 @@ "Ethernet8_1x100G": { "Ethernet8": { "alias": "fortyGigE0/8", - "admin_status": "up", "lanes": "33,34,35,36", "speed": "100000", "index": "2" diff --git a/src/sonic-config-engine/portconfig.py b/src/sonic-config-engine/portconfig.py index 260632b754f9..db486b1b7d8c 100644 --- a/src/sonic-config-engine/portconfig.py +++ b/src/sonic-config-engine/portconfig.py @@ -205,7 +205,6 @@ def gen_port_config(ports, parent_intf_id, index, alias_list, lanes, k, offset) raise Exception('Regex return for speed is None...') ports[intf_name]['index'] = index.split(",")[alias_position] - ports[intf_name]['admin_status'] = "up" parent_intf_id += step alias_position += 1 diff --git a/src/sonic-config-engine/tests/platform-sample-graph.xml b/src/sonic-config-engine/tests/platform-sample-graph.xml new file mode 100644 index 000000000000..690b05073c1a --- /dev/null +++ b/src/sonic-config-engine/tests/platform-sample-graph.xml @@ -0,0 +1,118 @@ + + + + + + + + + + + + switch-t0 + + + PortChannel01 + Ethernet20 + + + + PortChannel1001 + Ethernet4;Ethernet6 + + + + + + + + + + + + + + + DeviceInterfaceLink + 100000 + ARISTA01T1 + et1 + true + switch-t0 + Ethernet0 + true + + + + + switch-t0 + Force10-S6000 + AAA00PrdStr00 + + + ARISTA01T1 + Arista + + + + + + + + DeviceInterface + + true + 1 + Ethernet0 + + false + 0 + 0 + 100000 + + + DeviceInterface + + true + 1 + Ethernet4 + + false + 0 + 0 + 50000 + + + DeviceInterface + + true + 1 + Ethernet6 + + false + 0 + 0 + 50000 + + + DeviceInterface + + true + 1 + Ethernet20 + + false + 0 + 0 + 100000 + + + true + 0 + Force10-S6000 + + + + switch-t0 + Force10-S6000 + diff --git a/src/sonic-config-engine/tests/sample_output/platform_output.json b/src/sonic-config-engine/tests/sample_output/platform_output.json index 97b49997cf43..8276b19e18a3 100644 --- a/src/sonic-config-engine/tests/sample_output/platform_output.json +++ b/src/sonic-config-engine/tests/sample_output/platform_output.json @@ -3,7 +3,6 @@ "index": "3", "lanes": "8", "description": "Eth3/1", - "admin_status": "up", "mtu": "9100", "alias": "Eth3/1", "pfc_asym": "off", @@ -14,7 +13,6 @@ "index": "3", "lanes": "9", "description": "Eth3/2", - "admin_status": "up", "mtu": "9100", "alias": "Eth3/2", "pfc_asym": "off", @@ -25,7 +23,6 @@ "index": "10", "lanes": "36,37", "description": "Eth10/1", - "admin_status": "up", "mtu": "9100", "alias": "Eth10/1", "pfc_asym": "off", @@ -36,7 +33,6 @@ "index": "25", "lanes": "98", "description": "Eth25/2", - "admin_status": "up", "mtu": "9100", "alias": "Eth25/2", "pfc_asym": "off", @@ -47,7 +43,7 @@ "index": "1", "lanes": "0,1,2,3", "fec": "rs", - "description": "Eth1", + "description": "ARISTA01T1:et1", "admin_status": "up", "mtu": "9100", "alias": "Eth1", @@ -81,7 +77,6 @@ "index": "28", "lanes": "109", "description": "Eth28/2", - "admin_status": "up", "mtu": "9100", "alias": "Eth28/2", "pfc_asym": "off", @@ -92,7 +87,6 @@ "index": "28", "lanes": "108", "description": "Eth28/1", - "admin_status": "up", "mtu": "9100", "alias": "Eth28/1", "pfc_asym": "off", @@ -103,7 +97,6 @@ "index": "5", "lanes": "18", "description": "Eth5/2", - "admin_status": "up", "mtu": "9100", "alias": "Eth5/2", "pfc_asym": "off", @@ -115,7 +108,6 @@ "lanes": "100,101,102,103", "fec": "rs", "description": "Eth26", - "admin_status": "up", "mtu": "9100", "alias": "Eth26", "pfc_asym": "off", @@ -126,7 +118,6 @@ "index": "9", "lanes": "34,35", "description": "Eth9/3", - "admin_status": "up", "mtu": "9100", "alias": "Eth9/3", "pfc_asym": "off", @@ -137,7 +128,6 @@ "index": "27", "lanes": "104,105", "description": "Eth27/1", - "admin_status": "up", "mtu": "9100", "alias": "Eth27/1", "pfc_asym": "off", @@ -148,7 +138,6 @@ "index": "27", "lanes": "106,107", "description": "Eth27/2", - "admin_status": "up", "mtu": "9100", "alias": "Eth27/2", "pfc_asym": "off", @@ -159,7 +148,6 @@ "index": "24", "lanes": "94,95", "description": "Eth24/3", - "admin_status": "up", "mtu": "9100", "alias": "Eth24/3", "pfc_asym": "off", @@ -170,7 +158,6 @@ "index": "32", "lanes": "126,127", "description": "Eth32/2", - "admin_status": "up", "mtu": "9100", "alias": "Eth32/2", "pfc_asym": "off", @@ -181,7 +168,6 @@ "index": "25", "lanes": "96,97", "description": "Eth25/1", - "admin_status": "up", "mtu": "9100", "alias": "Eth25/1", "pfc_asym": "off", @@ -192,7 +178,6 @@ "index": "32", "lanes": "124,125", "description": "Eth32/1", - "admin_status": "up", "mtu": "9100", "alias": "Eth32/1", "pfc_asym": "off", @@ -203,7 +188,6 @@ "index": "23", "lanes": "90", "description": "Eth23/3", - "admin_status": "up", "mtu": "9100", "alias": "Eth23/3", "pfc_asym": "off", @@ -214,7 +198,6 @@ "index": "23", "lanes": "91", "description": "Eth23/4", - "admin_status": "up", "mtu": "9100", "alias": "Eth23/4", "pfc_asym": "off", @@ -225,7 +208,6 @@ "index": "24", "lanes": "92", "description": "Eth24/1", - "admin_status": "up", "mtu": "9100", "alias": "Eth24/1", "pfc_asym": "off", @@ -236,7 +218,6 @@ "index": "24", "lanes": "93", "description": "Eth24/2", - "admin_status": "up", "mtu": "9100", "alias": "Eth24/2", "pfc_asym": "off", @@ -247,7 +228,6 @@ "index": "13", "lanes": "50", "description": "Eth13/3", - "admin_status": "up", "mtu": "9100", "alias": "Eth13/3", "pfc_asym": "off", @@ -258,7 +238,6 @@ "index": "13", "lanes": "51", "description": "Eth13/4", - "admin_status": "up", "mtu": "9100", "alias": "Eth13/4", "pfc_asym": "off", @@ -269,7 +248,6 @@ "index": "14", "lanes": "52", "description": "Eth14/1", - "admin_status": "up", "mtu": "9100", "alias": "Eth14/1", "pfc_asym": "off", @@ -280,7 +258,6 @@ "index": "14", "lanes": "53", "description": "Eth14/2", - "admin_status": "up", "mtu": "9100", "alias": "Eth14/2", "pfc_asym": "off", @@ -291,7 +268,6 @@ "index": "14", "lanes": "54,55", "description": "Eth14/3", - "admin_status": "up", "mtu": "9100", "alias": "Eth14/3", "pfc_asym": "off", @@ -302,7 +278,6 @@ "index": "25", "lanes": "99", "description": "Eth25/3", - "admin_status": "up", "mtu": "9100", "alias": "Eth25/3", "pfc_asym": "off", @@ -313,7 +288,6 @@ "index": "15", "lanes": "56,57", "description": "Eth15/1", - "admin_status": "up", "mtu": "9100", "alias": "Eth15/1", "pfc_asym": "off", @@ -324,7 +298,6 @@ "index": "29", "lanes": "113", "description": "Eth29/2", - "admin_status": "up", "mtu": "9100", "alias": "Eth29/2", "pfc_asym": "off", @@ -335,7 +308,6 @@ "index": "20", "lanes": "76,77", "description": "Eth20/1", - "admin_status": "up", "mtu": "9100", "alias": "Eth20/1", "pfc_asym": "off", @@ -346,7 +318,6 @@ "index": "19", "lanes": "74,75", "description": "Eth19/3", - "admin_status": "up", "mtu": "9100", "alias": "Eth19/3", "pfc_asym": "off", @@ -357,7 +328,6 @@ "index": "10", "lanes": "39", "description": "Eth10/3", - "admin_status": "up", "mtu": "9100", "alias": "Eth10/3", "pfc_asym": "off", @@ -368,7 +338,6 @@ "index": "19", "lanes": "72", "description": "Eth19/1", - "admin_status": "up", "mtu": "9100", "alias": "Eth19/1", "pfc_asym": "off", @@ -379,7 +348,6 @@ "index": "19", "lanes": "73", "description": "Eth19/2", - "admin_status": "up", "mtu": "9100", "alias": "Eth19/2", "pfc_asym": "off", @@ -390,7 +358,6 @@ "index": "18", "lanes": "70", "description": "Eth18/3", - "admin_status": "up", "mtu": "9100", "alias": "Eth18/3", "pfc_asym": "off", @@ -401,7 +368,6 @@ "index": "18", "lanes": "71", "description": "Eth18/4", - "admin_status": "up", "mtu": "9100", "alias": "Eth18/4", "pfc_asym": "off", @@ -412,7 +378,6 @@ "index": "9", "lanes": "32", "description": "Eth9/1", - "admin_status": "up", "mtu": "9100", "alias": "Eth9/1", "pfc_asym": "off", @@ -423,7 +388,6 @@ "index": "9", "lanes": "33", "description": "Eth9/2", - "admin_status": "up", "mtu": "9100", "alias": "Eth9/2", "pfc_asym": "off", @@ -434,7 +398,6 @@ "index": "5", "lanes": "16,17", "description": "Eth5/1", - "admin_status": "up", "mtu": "9100", "alias": "Eth5/1", "pfc_asym": "off", @@ -445,7 +408,6 @@ "index": "28", "lanes": "111", "description": "Eth28/4", - "admin_status": "up", "mtu": "9100", "alias": "Eth28/4", "pfc_asym": "off", @@ -456,7 +418,6 @@ "index": "3", "lanes": "10", "description": "Eth3/3", - "admin_status": "up", "mtu": "9100", "alias": "Eth3/3", "pfc_asym": "off", @@ -467,7 +428,6 @@ "index": "3", "lanes": "11", "description": "Eth3/4", - "admin_status": "up", "mtu": "9100", "alias": "Eth3/4", "pfc_asym": "off", @@ -478,7 +438,6 @@ "index": "4", "lanes": "12", "description": "Eth4/1", - "admin_status": "up", "mtu": "9100", "alias": "Eth4/1", "pfc_asym": "off", @@ -489,7 +448,6 @@ "index": "4", "lanes": "13", "description": "Eth4/2", - "admin_status": "up", "mtu": "9100", "alias": "Eth4/2", "pfc_asym": "off", @@ -500,7 +458,6 @@ "index": "15", "lanes": "58", "description": "Eth15/2", - "admin_status": "up", "mtu": "9100", "alias": "Eth15/2", "pfc_asym": "off", @@ -511,7 +468,6 @@ "index": "5", "lanes": "19", "description": "Eth5/3", - "admin_status": "up", "mtu": "9100", "alias": "Eth5/3", "pfc_asym": "off", @@ -522,7 +478,6 @@ "index": "15", "lanes": "59", "description": "Eth15/3", - "admin_status": "up", "mtu": "9100", "alias": "Eth15/3", "pfc_asym": "off", @@ -533,7 +488,6 @@ "index": "10", "lanes": "38", "description": "Eth10/2", - "admin_status": "up", "mtu": "9100", "alias": "Eth10/2", "pfc_asym": "off", @@ -544,7 +498,6 @@ "index": "20", "lanes": "78", "description": "Eth20/2", - "admin_status": "up", "mtu": "9100", "alias": "Eth20/2", "pfc_asym": "off", @@ -555,7 +508,6 @@ "index": "18", "lanes": "68", "description": "Eth18/1", - "admin_status": "up", "mtu": "9100", "alias": "Eth18/1", "pfc_asym": "off", @@ -566,7 +518,6 @@ "index": "4", "lanes": "14,15", "description": "Eth4/3", - "admin_status": "up", "mtu": "9100", "alias": "Eth4/3", "pfc_asym": "off", @@ -577,7 +528,6 @@ "index": "23", "lanes": "89", "description": "Eth23/2", - "admin_status": "up", "mtu": "9100", "alias": "Eth23/2", "pfc_asym": "off", @@ -588,7 +538,6 @@ "index": "23", "lanes": "88", "description": "Eth23/1", - "admin_status": "up", "mtu": "9100", "alias": "Eth23/1", "pfc_asym": "off", @@ -599,7 +548,6 @@ "index": "30", "lanes": "118", "description": "Eth30/2", - "admin_status": "up", "mtu": "9100", "alias": "Eth30/2", "pfc_asym": "off", @@ -610,7 +558,6 @@ "index": "30", "lanes": "119", "description": "Eth30/3", - "admin_status": "up", "mtu": "9100", "alias": "Eth30/3", "pfc_asym": "off", @@ -621,7 +568,6 @@ "index": "30", "lanes": "116,117", "description": "Eth30/1", - "admin_status": "up", "mtu": "9100", "alias": "Eth30/1", "pfc_asym": "off", @@ -632,7 +578,6 @@ "index": "29", "lanes": "114,115", "description": "Eth29/3", - "admin_status": "up", "mtu": "9100", "alias": "Eth29/3", "pfc_asym": "off", @@ -644,7 +589,6 @@ "lanes": "80,81,82,83", "fec": "rs", "description": "Eth21", - "admin_status": "up", "mtu": "9100", "alias": "Eth21", "pfc_asym": "off", @@ -655,7 +599,6 @@ "index": "29", "lanes": "112", "description": "Eth29/1", - "admin_status": "up", "mtu": "9100", "alias": "Eth29/1", "pfc_asym": "off", @@ -666,7 +609,6 @@ "index": "22", "lanes": "86,87", "description": "Eth22/2", - "admin_status": "up", "mtu": "9100", "alias": "Eth22/2", "pfc_asym": "off", @@ -677,7 +619,6 @@ "index": "28", "lanes": "110", "description": "Eth28/3", - "admin_status": "up", "mtu": "9100", "alias": "Eth28/3", "pfc_asym": "off", @@ -688,7 +629,6 @@ "index": "22", "lanes": "84,85", "description": "Eth22/1", - "admin_status": "up", "mtu": "9100", "alias": "Eth22/1", "pfc_asym": "off", @@ -699,7 +639,6 @@ "index": "8", "lanes": "31", "description": "Eth8/4", - "admin_status": "up", "mtu": "9100", "alias": "Eth8/4", "pfc_asym": "off", @@ -710,7 +649,6 @@ "index": "13", "lanes": "49", "description": "Eth13/2", - "admin_status": "up", "mtu": "9100", "alias": "Eth13/2", "pfc_asym": "off", @@ -721,7 +659,6 @@ "index": "13", "lanes": "48", "description": "Eth13/1", - "admin_status": "up", "mtu": "9100", "alias": "Eth13/1", "pfc_asym": "off", @@ -732,7 +669,6 @@ "index": "12", "lanes": "46,47", "description": "Eth12/2", - "admin_status": "up", "mtu": "9100", "alias": "Eth12/2", "pfc_asym": "off", @@ -743,7 +679,6 @@ "index": "8", "lanes": "30", "description": "Eth8/3", - "admin_status": "up", "mtu": "9100", "alias": "Eth8/3", "pfc_asym": "off", @@ -754,7 +689,6 @@ "index": "8", "lanes": "29", "description": "Eth8/2", - "admin_status": "up", "mtu": "9100", "alias": "Eth8/2", "pfc_asym": "off", @@ -766,7 +700,6 @@ "lanes": "40,41,42,43", "fec": "rs", "description": "Eth11", - "admin_status": "up", "mtu": "9100", "alias": "Eth11", "pfc_asym": "off", @@ -778,7 +711,6 @@ "lanes": "120,121,122,123", "fec": "rs", "description": "Eth31", - "admin_status": "up", "mtu": "9100", "alias": "Eth31", "pfc_asym": "off", @@ -789,7 +721,6 @@ "index": "8", "lanes": "28", "description": "Eth8/1", - "admin_status": "up", "mtu": "9100", "alias": "Eth8/1", "pfc_asym": "off", @@ -800,7 +731,6 @@ "index": "17", "lanes": "66,67", "description": "Eth17/2", - "admin_status": "up", "mtu": "9100", "alias": "Eth17/2", "pfc_asym": "off", @@ -812,7 +742,6 @@ "lanes": "60,61,62,63", "fec": "rs", "description": "Eth16", - "admin_status": "up", "mtu": "9100", "alias": "Eth16", "pfc_asym": "off", @@ -823,7 +752,6 @@ "index": "17", "lanes": "64,65", "description": "Eth17/1", - "admin_status": "up", "mtu": "9100", "alias": "Eth17/1", "pfc_asym": "off", @@ -834,7 +762,6 @@ "index": "12", "lanes": "44,45", "description": "Eth12/1", - "admin_status": "up", "mtu": "9100", "alias": "Eth12/1", "pfc_asym": "off", @@ -857,7 +784,6 @@ "index": "20", "lanes": "79", "description": "Eth20/3", - "admin_status": "up", "mtu": "9100", "alias": "Eth20/3", "pfc_asym": "off", @@ -868,7 +794,6 @@ "index": "18", "lanes": "69", "description": "Eth18/2", - "admin_status": "up", "mtu": "9100", "alias": "Eth18/2", "pfc_asym": "off", @@ -879,7 +804,6 @@ "index": "7", "lanes": "24,25", "description": "Eth7/1", - "admin_status": "up", "mtu": "9100", "alias": "Eth7/1", "pfc_asym": "off", @@ -890,7 +814,6 @@ "index": "7", "lanes": "26,27", "description": "Eth7/2", - "admin_status": "up", "mtu": "9100", "alias": "Eth7/2", "pfc_asym": "off", diff --git a/src/sonic-config-engine/tests/test_cfggen_platformJson.py b/src/sonic-config-engine/tests/test_cfggen_platformJson.py index 1765fb4f3a2c..3307c3447c0c 100644 --- a/src/sonic-config-engine/tests/test_cfggen_platformJson.py +++ b/src/sonic-config-engine/tests/test_cfggen_platformJson.py @@ -22,7 +22,7 @@ class TestCfgGenPlatformJson(TestCase): def setUp(self): self.test_dir = os.path.dirname(os.path.realpath(__file__)) self.script_file = utils.PYTHON_INTERPRETTER + ' ' + os.path.join(self.test_dir, '..', 'sonic-cfggen') - self.sample_graph_simple = os.path.join(self.test_dir, 'simple-sample-graph.xml') + self.platform_sample_graph = os.path.join(self.test_dir, 'platform-sample-graph.xml') self.platform_json = os.path.join(self.test_dir, 'sample_platform.json') self.hwsku_json = os.path.join(self.test_dir, 'sample_hwsku.json') @@ -49,13 +49,13 @@ def test_dummy_run(self): self.assertEqual(output, '') def test_print_data(self): - argument = '-m "' + self.sample_graph_simple + '" --print-data' + argument = '-m "' + self.platform_sample_graph + '" --print-data' output = self.run_script(argument) self.assertTrue(len(output.strip()) > 0) # Check whether all interfaces present or not as per platform.json def test_platform_json_interfaces_keys(self): - argument = '-m "' + self.sample_graph_simple + '" -p "' + self.platform_json + '" -S "' + self.hwsku_json + '" -v "PORT.keys()|list"' + argument = '-m "' + self.platform_sample_graph + '" -p "' + self.platform_json + '" -S "' + self.hwsku_json + '" -v "PORT.keys()|list"' output = self.run_script(argument) self.maxDiff = None expected = "['Ethernet8', 'Ethernet9', 'Ethernet36', 'Ethernet98', 'Ethernet0', 'Ethernet6', 'Ethernet4', 'Ethernet109', 'Ethernet108', 'Ethernet18', 'Ethernet100', 'Ethernet34', 'Ethernet104', 'Ethernet106', 'Ethernet94', 'Ethernet126', 'Ethernet96', 'Ethernet124', 'Ethernet90', 'Ethernet91', 'Ethernet92', 'Ethernet93', 'Ethernet50', 'Ethernet51', 'Ethernet52', 'Ethernet53', 'Ethernet54', 'Ethernet99', 'Ethernet56', 'Ethernet113', 'Ethernet76', 'Ethernet74', 'Ethernet39', 'Ethernet72', 'Ethernet73', 'Ethernet70', 'Ethernet71', 'Ethernet32', 'Ethernet33', 'Ethernet16', 'Ethernet111', 'Ethernet10', 'Ethernet11', 'Ethernet12', 'Ethernet13', 'Ethernet58', 'Ethernet19', 'Ethernet59', 'Ethernet38', 'Ethernet78', 'Ethernet68', 'Ethernet14', 'Ethernet89', 'Ethernet88', 'Ethernet118', 'Ethernet119', 'Ethernet116', 'Ethernet114', 'Ethernet80', 'Ethernet112', 'Ethernet86', 'Ethernet110', 'Ethernet84', 'Ethernet31', 'Ethernet49', 'Ethernet48', 'Ethernet46', 'Ethernet30', 'Ethernet29', 'Ethernet40', 'Ethernet120', 'Ethernet28', 'Ethernet66', 'Ethernet60', 'Ethernet64', 'Ethernet44', 'Ethernet20', 'Ethernet79', 'Ethernet69', 'Ethernet24', 'Ethernet26']" @@ -65,21 +65,27 @@ def test_platform_json_interfaces_keys(self): # Check specific Interface with it's proper configuration as per platform.json def test_platform_json_specific_ethernet_interfaces(self): - argument = '-m "' + self.sample_graph_simple + '" -p "' + self.platform_json + '" -S "' + self.hwsku_json + '" -v "PORT[\'Ethernet8\']"' + argument = '-m "' + self.platform_sample_graph + '" -p "' + self.platform_json + '" -S "' + self.hwsku_json + '" -v "PORT[\'Ethernet8\']"' output = self.run_script(argument) self.maxDiff = None - expected = "{'index': '3', 'lanes': '8', 'description': 'Eth3/1', 'admin_status': 'up', 'mtu': '9100', 'alias': 'Eth3/1', 'pfc_asym': 'off', 'speed': '25000', 'tpid': '0x8100'}" + expected = "{'index': '3', 'lanes': '8', 'description': 'Eth3/1', 'mtu': '9100', 'alias': 'Eth3/1', 'pfc_asym': 'off', 'speed': '25000', 'tpid': '0x8100'}" self.assertEqual(utils.to_dict(output.strip()), utils.to_dict(expected)) - argument = '-m "' + self.sample_graph_simple + '" -p "' + self.platform_json + '" -S "' + self.hwsku_json + '" -v "PORT[\'Ethernet112\']"' + argument = '-m "' + self.platform_sample_graph + '" -p "' + self.platform_json + '" -S "' + self.hwsku_json + '" -v "PORT[\'Ethernet112\']"' output = self.run_script(argument) self.maxDiff = None - expected = "{'index': '29', 'lanes': '112', 'description': 'Eth29/1', 'admin_status': 'up', 'mtu': '9100', 'alias': 'Eth29/1', 'pfc_asym': 'off', 'speed': '25000', 'tpid': '0x8100'}" + expected = "{'index': '29', 'lanes': '112', 'description': 'Eth29/1', 'mtu': '9100', 'alias': 'Eth29/1', 'pfc_asym': 'off', 'speed': '25000', 'tpid': '0x8100'}" self.assertEqual(utils.to_dict(output.strip()), utils.to_dict(expected)) + argument = '-m "' + self.platform_sample_graph + '" -p "' + self.platform_json + '" -S "' + self.hwsku_json + '" -v "PORT[\'Ethernet4\']"' + output = self.run_script(argument) + self.maxDiff = None + expected = "{'index': '2', 'lanes': '4,5', 'description': 'Eth2/1', 'admin_status': 'up', 'mtu': '9100', 'alias': 'Eth2/1', 'pfc_asym': 'off', 'speed': '50000', 'tpid': '0x8100'}" + print(output.strip()) + self.assertEqual(utils.to_dict(output.strip()), utils.to_dict(expected)) # Check all Interface with it's proper configuration as per platform.json def test_platform_json_all_ethernet_interfaces(self): - argument = '-m "' + self.sample_graph_simple + '" -p "' + self.platform_json + '" -S "' + self.hwsku_json + '" -v "PORT"' + argument = '-m "' + self.platform_sample_graph + '" -p "' + self.platform_json + '" -S "' + self.hwsku_json + '" -v "PORT"' output = self.run_script(argument) self.maxDiff = None From db529af20392eec9db69ce6d87de07e0f62a60cd Mon Sep 17 00:00:00 2001 From: Sudharsan Dhamal Gopalarathnam Date: Mon, 13 Sep 2021 09:10:21 -0700 Subject: [PATCH 10/34] Removing execute permission from copp config file (#8680) *Removed execute permissions from the systemd copp-config.service file. Without this we will get a warning: "Configuration file /lib/systemd/system/copp-config.service is marked executable. Please remove executable permission bits. Proceeding anyway." --- files/image_config/copp/copp-config.service | 0 1 file changed, 0 insertions(+), 0 deletions(-) mode change 100755 => 100644 files/image_config/copp/copp-config.service diff --git a/files/image_config/copp/copp-config.service b/files/image_config/copp/copp-config.service old mode 100755 new mode 100644 From 690f6ad88361bb9e9bdcbb73a5d92959701e4638 Mon Sep 17 00:00:00 2001 From: Kostiantyn Yarovyi Date: Tue, 14 Sep 2021 17:34:00 +0300 Subject: [PATCH 11/34] [show] add platform components in Newport, Montara, Mavericks for fix incomprehensible firmware Error print (#8690) What I did: add platform components How I did it: In platform_components.json add chassis and empty component How to verify it: Run show platform firmware updates --- .../x86_64-accton_as9516_32d-r0/platform_components.json | 8 ++++++++ .../platform_components.json | 8 ++++++++ .../platform_components.json | 8 ++++++++ 3 files changed, 24 insertions(+) create mode 100644 device/barefoot/x86_64-accton_as9516_32d-r0/platform_components.json create mode 100644 device/barefoot/x86_64-accton_wedge100bf_32x-r0/platform_components.json create mode 100644 device/barefoot/x86_64-accton_wedge100bf_65x-r0/platform_components.json diff --git a/device/barefoot/x86_64-accton_as9516_32d-r0/platform_components.json b/device/barefoot/x86_64-accton_as9516_32d-r0/platform_components.json new file mode 100644 index 000000000000..43874566a3ad --- /dev/null +++ b/device/barefoot/x86_64-accton_as9516_32d-r0/platform_components.json @@ -0,0 +1,8 @@ +{ + "chassis": { + "Newport": { + "component": { + } + } + } +} \ No newline at end of file diff --git a/device/barefoot/x86_64-accton_wedge100bf_32x-r0/platform_components.json b/device/barefoot/x86_64-accton_wedge100bf_32x-r0/platform_components.json new file mode 100644 index 000000000000..df77fa3e1bf9 --- /dev/null +++ b/device/barefoot/x86_64-accton_wedge100bf_32x-r0/platform_components.json @@ -0,0 +1,8 @@ +{ + "chassis": { + "Wedge100BF-32X-O-AC-F-BF": { + "component": { + } + } + } +} \ No newline at end of file diff --git a/device/barefoot/x86_64-accton_wedge100bf_65x-r0/platform_components.json b/device/barefoot/x86_64-accton_wedge100bf_65x-r0/platform_components.json new file mode 100644 index 000000000000..74e851a7c4b6 --- /dev/null +++ b/device/barefoot/x86_64-accton_wedge100bf_65x-r0/platform_components.json @@ -0,0 +1,8 @@ +{ + "chassis": { + "Wedge100BF-65X-O-AC-F-BF": { + "component": { + } + } + } +} \ No newline at end of file From 66ca6d33c7004cd97ce3a8e9b96634e725a1ae5c Mon Sep 17 00:00:00 2001 From: Ying Xie Date: Tue, 14 Sep 2021 07:57:43 -0700 Subject: [PATCH 12/34] Revert "Revert "[hostcfgd] Delay hostcfgd and aaastatsd for faster boot time (#7965)" (#8705)" (#8724) This reverts commit f4dea87cf97a78bd200a092da2193553c13a0494. --- .../debian/sonic-host-services-data.aaastatsd.service | 3 --- .../debian/sonic-host-services-data.aaastatsd.timer | 11 +++++++++++ .../debian/sonic-host-services-data.hostcfgd.service | 3 --- .../debian/sonic-host-services-data.hostcfgd.timer | 11 +++++++++++ 4 files changed, 22 insertions(+), 6 deletions(-) create mode 100644 src/sonic-host-services-data/debian/sonic-host-services-data.aaastatsd.timer create mode 100644 src/sonic-host-services-data/debian/sonic-host-services-data.hostcfgd.timer diff --git a/src/sonic-host-services-data/debian/sonic-host-services-data.aaastatsd.service b/src/sonic-host-services-data/debian/sonic-host-services-data.aaastatsd.service index b03c6a9551c0..b93fe92c04ed 100644 --- a/src/sonic-host-services-data/debian/sonic-host-services-data.aaastatsd.service +++ b/src/sonic-host-services-data/debian/sonic-host-services-data.aaastatsd.service @@ -12,6 +12,3 @@ Restart=on-failure RestartSec=10 TimeoutStopSec=3 -[Install] -WantedBy=sonic.target - diff --git a/src/sonic-host-services-data/debian/sonic-host-services-data.aaastatsd.timer b/src/sonic-host-services-data/debian/sonic-host-services-data.aaastatsd.timer new file mode 100644 index 000000000000..e0458ff326f5 --- /dev/null +++ b/src/sonic-host-services-data/debian/sonic-host-services-data.aaastatsd.timer @@ -0,0 +1,11 @@ +[Unit] +Description=Delays aaastatsd daemon until SONiC has started +PartOf=aaastatsd.service + +[Timer] +OnActiveSec=1min 30 sec +Unit=aaastatsd.service + +[Install] +WantedBy=timers.target sonic.target + diff --git a/src/sonic-host-services-data/debian/sonic-host-services-data.hostcfgd.service b/src/sonic-host-services-data/debian/sonic-host-services-data.hostcfgd.service index 4adf2aba77ad..5e2434527124 100644 --- a/src/sonic-host-services-data/debian/sonic-host-services-data.hostcfgd.service +++ b/src/sonic-host-services-data/debian/sonic-host-services-data.hostcfgd.service @@ -9,6 +9,3 @@ After=sonic.target Type=simple ExecStart=/usr/local/bin/hostcfgd -[Install] -WantedBy=sonic.target - diff --git a/src/sonic-host-services-data/debian/sonic-host-services-data.hostcfgd.timer b/src/sonic-host-services-data/debian/sonic-host-services-data.hostcfgd.timer new file mode 100644 index 000000000000..baf80f4b4cbd --- /dev/null +++ b/src/sonic-host-services-data/debian/sonic-host-services-data.hostcfgd.timer @@ -0,0 +1,11 @@ +[Unit] +Description=Delays hostcfgd daemon until SONiC has started +PartOf=hostcfgd.service + +[Timer] +OnActiveSec=1min 30 sec +Unit=hostcfgd.service + +[Install] +WantedBy=timers.target sonic.target + From 1863e1fa26649b16b03a2e47a8493cbcb99ab052 Mon Sep 17 00:00:00 2001 From: vganesan-nokia <67648637+vganesan-nokia@users.noreply.github.com> Date: Tue, 14 Sep 2021 14:04:19 -0400 Subject: [PATCH 13/34] [multi-asic][cli][chassis-db] Avoid connecting to chassis db when cli commands are executed from linecards (#8065) * [multi-asic][cli][chassis-db] Avoiding connecting to chassis db Currently, for all the cli commands, we connect to all databases mentioned in the database_config.json. The database_config.json also includes the databases from chassis redis server from supervisor card. It is unneccessary to connect to databases from chassis redis server when cli commands are executed form linecard. But we need to allow connection to chassis databases when the cli commands are executed from supervisor card. The changes in this PR fixes this problem. This PR requires that asic.conf in supervisor card includes VOQ_SUPERVISOR with value 1 to indentify the supervisor card. The connect_to_all_dbs_for_ns() is changed to skip chassis databases form the list of collected databases if the card is not supervisor card. --- .../sonic_py_common/device_info.py | 40 +++++++++++++++++++ .../sonic_py_common/multi_asic.py | 17 +++++++- 2 files changed, 55 insertions(+), 2 deletions(-) diff --git a/src/sonic-py-common/sonic_py_common/device_info.py b/src/sonic-py-common/sonic_py_common/device_info.py index 4d1df6352284..0b58a4231a65 100644 --- a/src/sonic-py-common/sonic_py_common/device_info.py +++ b/src/sonic-py-common/sonic_py_common/device_info.py @@ -29,6 +29,7 @@ NPU_NAME_PREFIX = "asic" NAMESPACE_PATH_GLOB = "/run/netns/*" ASIC_CONF_FILENAME = "asic.conf" +PLATFORM_ENV_CONF_FILENAME = "platform_env.conf" FRONTEND_ASIC_SUB_ROLE = "FrontEnd" BACKEND_ASIC_SUB_ROLE = "BackEnd" @@ -164,6 +165,29 @@ def get_asic_conf_file_path(): return None +def get_platform_env_conf_file_path(): + """ + Retrieves the path to the PLATFORM ENV conguration file on the device + + Returns: + A string containing the path to the PLATFORM ENV conguration file on success, + None on failure + """ + platform_env_conf_path_candidates = [] + + platform_env_conf_path_candidates.append(os.path.join(CONTAINER_PLATFORM_PATH, PLATFORM_ENV_CONF_FILENAME)) + + platform = get_platform() + if platform: + platform_env_conf_path_candidates.append(os.path.join(HOST_DEVICE_PATH, platform, PLATFORM_ENV_CONF_FILENAME)) + + for platform_env_conf_file_path in platform_env_conf_path_candidates: + if os.path.isfile(platform_env_conf_file_path): + return platform_env_conf_file_path + + return None + + def get_path_to_platform_dir(): """ Retreives the paths to the device's platform directory @@ -374,6 +398,22 @@ def is_multi_npu(): return (num_npus > 1) +def is_supervisor(): + platform_env_conf_file_path = get_platform_env_conf_file_path() + if platform_env_conf_file_path is None: + return False + with open(platform_env_conf_file_path) as platform_env_conf_file: + for line in platform_env_conf_file: + tokens = line.split('=') + if len(tokens) < 2: + continue + if tokens[0].lower() == 'supervisor': + val = tokens[1].strip() + if val == '1': + return True + return False + + def get_npu_id_from_name(npu_name): if npu_name.startswith(NPU_NAME_PREFIX): return npu_name[len(NPU_NAME_PREFIX):] diff --git a/src/sonic-py-common/sonic_py_common/multi_asic.py b/src/sonic-py-common/sonic_py_common/multi_asic.py index f6daba8e84a2..a5b5d48bab21 100644 --- a/src/sonic-py-common/sonic_py_common/multi_asic.py +++ b/src/sonic-py-common/sonic_py_common/multi_asic.py @@ -8,6 +8,7 @@ from .device_info import CONTAINER_PLATFORM_PATH from .device_info import HOST_DEVICE_PATH from .device_info import get_platform +from .device_info import is_supervisor ASIC_NAME_PREFIX = 'asic' NAMESPACE_PATH_GLOB = '/run/netns/*' @@ -45,7 +46,11 @@ def connect_config_db_for_ns(namespace=DEFAULT_NAMESPACE): def connect_to_all_dbs_for_ns(namespace=DEFAULT_NAMESPACE): """ The function connects to the DBs for a given namespace and - returns the handle + returns the handle + + For voq chassis systems, the db list includes databases from + supervisor card. Avoid connecting to these databases from linecards + If no namespace is provided, it will connect to the db in the default namespace. In case of multi ASIC, the default namespace is the @@ -56,7 +61,15 @@ def connect_to_all_dbs_for_ns(namespace=DEFAULT_NAMESPACE): handle to all the dbs for a namespaces """ db = swsscommon.SonicV2Connector(namespace=namespace) - for db_id in db.get_db_list(): + db_list = list(db.get_db_list()) + if not is_supervisor(): + try: + db_list.remove('CHASSIS_APP_DB') + db_list.remove('CHASSIS_STATE_DB') + except Exception: + pass + + for db_id in db_list: db.connect(db_id) return db From 2662a19eecbc1b87b2845af6b9ebcf3c38d1ffb4 Mon Sep 17 00:00:00 2001 From: Lior Avramov <73036155+liorghub@users.noreply.github.com> Date: Thu, 16 Sep 2021 00:00:43 +0300 Subject: [PATCH 14/34] [sonic-py-swsssdk]: submodule update (#8757) 2cd6236 [voq][chassis] Fix for issue in chassis redis server connection check (#110) 9da577d [port_util] Fix issue in function get_interface_oid_map (#114) 740a44c [port_util] Allow system without ports in config db run without errors (#109) d07682e Merge pull request #111 from xumia/azp-coverage 482cac2 [Ethernet-IB][index] Modifed the port_util to support the VoQ Inband Port (#113) 69eac92 Support azp diff coverage Signed-off-by: liora --- src/sonic-py-swsssdk | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/sonic-py-swsssdk b/src/sonic-py-swsssdk index 6be76f45705f..2cd6236849d1 160000 --- a/src/sonic-py-swsssdk +++ b/src/sonic-py-swsssdk @@ -1 +1 @@ -Subproject commit 6be76f45705f35ae7a8baefea801558511cd68e7 +Subproject commit 2cd6236849d194625c014d1c2c370f6d2513eb76 From 8a00ad73fd071e6e5f13319587f7f2432acd4acf Mon Sep 17 00:00:00 2001 From: Junhua Zhai Date: Thu, 16 Sep 2021 05:02:03 +0800 Subject: [PATCH 15/34] [gearbox] support gearbox feature on docker-sonic-vs (#8765) --- .../brcm_gearbox_vs/context_config.json | 8 +++++++- platform/vs/docker-sonic-vs/Dockerfile.j2 | 1 + platform/vs/docker-sonic-vs/start.sh | 5 +++++ platform/vs/docker-sonic-vs/supervisord.conf | 17 +++++++++++++++++ 4 files changed, 30 insertions(+), 1 deletion(-) diff --git a/device/virtual/x86_64-kvm_x86_64-r0/brcm_gearbox_vs/context_config.json b/device/virtual/x86_64-kvm_x86_64-r0/brcm_gearbox_vs/context_config.json index 9f9f80ba0d36..106087f7275c 100644 --- a/device/virtual/x86_64-kvm_x86_64-r0/brcm_gearbox_vs/context_config.json +++ b/device/virtual/x86_64-kvm_x86_64-r0/brcm_gearbox_vs/context_config.json @@ -7,6 +7,9 @@ "dbCounters" : "COUNTERS_DB", "dbFlex": "FLEX_COUNTER_DB", "dbState" : "STATE_DB", + "zmq_enable": false, + "zmq_endpoint": "tcp://127.0.0.1:5555", + "zmq_ntf_endpoint": "tcp://127.0.0.1:5556", "switches": [ { "index" : 0, @@ -21,10 +24,13 @@ "dbCounters" : "GB_COUNTERS_DB", "dbFlex": "GB_FLEX_COUNTER_DB", "dbState" : "STATE_DB", + "zmq_enable": false, + "zmq_endpoint": "tcp://127.0.0.1:5565", + "zmq_ntf_endpoint": "tcp://127.0.0.1:5566", "switches": [ { "index" : 1, - "hwinfo" : "" + "hwinfo": "mdio0_0_0/0" } ] } diff --git a/platform/vs/docker-sonic-vs/Dockerfile.j2 b/platform/vs/docker-sonic-vs/Dockerfile.j2 index 2e11cdaea3db..ab686d3a13de 100644 --- a/platform/vs/docker-sonic-vs/Dockerfile.j2 +++ b/platform/vs/docker-sonic-vs/Dockerfile.j2 @@ -175,6 +175,7 @@ COPY ["buffermgrd.sh", "/usr/bin/"] COPY ["platform.json", "/usr/share/sonic/device/x86_64-kvm_x86_64-r0/"] COPY ["hwsku.json", "/usr/share/sonic/device/x86_64-kvm_x86_64-r0/Force10-S6000/"] +COPY ["hwsku.json", "/usr/share/sonic/device/x86_64-kvm_x86_64-r0/brcm_gearbox_vs/"] # Workaround the tcpdump issue RUN mv /usr/sbin/tcpdump /usr/bin/tcpdump diff --git a/platform/vs/docker-sonic-vs/start.sh b/platform/vs/docker-sonic-vs/start.sh index 93c9cf479d69..047918d2e518 100755 --- a/platform/vs/docker-sonic-vs/start.sh +++ b/platform/vs/docker-sonic-vs/start.sh @@ -109,6 +109,11 @@ fi /usr/bin/configdb-load.sh +if [ "$HWSKU" = "brcm_gearbox_vs" ]; then + supervisorctl start gbsyncd + supervisorctl start gearsyncd +fi + supervisorctl start syncd supervisorctl start portsyncd diff --git a/platform/vs/docker-sonic-vs/supervisord.conf b/platform/vs/docker-sonic-vs/supervisord.conf index 977b84117e3e..96f027131520 100644 --- a/platform/vs/docker-sonic-vs/supervisord.conf +++ b/platform/vs/docker-sonic-vs/supervisord.conf @@ -43,6 +43,23 @@ autorestart=false stdout_logfile=syslog stderr_logfile=syslog +[program:gbsyncd] +command=/usr/bin/syncd -s -p /usr/share/sonic/hwsku/pai.profile -x /usr/share/sonic/hwsku/context_config.json -g 1 +priority=4 +autostart=false +autorestart=false +stdout_logfile=syslog +stderr_logfile=syslog + +[program:gearsyncd] +command=/usr/bin/gearsyncd -p /usr/share/sonic/hwsku/gearbox_config.json +startsecs=0 +priority=5 +autostart=false +autorestart=false +stdout_logfile=syslog +stderr_logfile=syslog + [program:portsyncd] command=/usr/bin/portsyncd priority=5 From 13ec43bc68416e382fe9f44ad3be94310a94a11e Mon Sep 17 00:00:00 2001 From: abdosi <58047199+abdosi@users.noreply.github.com> Date: Wed, 15 Sep 2021 23:28:27 -0700 Subject: [PATCH 16/34] [baseimage]: Logrotate for wtmp and btmp files. (#8743) Added logrotate file for wtmp and btmp to override default conf and set size cap as 100K as done in PR: #865. For buster this is control by separate file wtmp and btmp. Signed-off-by: Abhishek Dosi --- files/image_config/logrotate/logrotate.d/btmp | 7 +++++++ files/image_config/logrotate/logrotate.d/wtmp | 7 +++++++ 2 files changed, 14 insertions(+) create mode 100644 files/image_config/logrotate/logrotate.d/btmp create mode 100644 files/image_config/logrotate/logrotate.d/wtmp diff --git a/files/image_config/logrotate/logrotate.d/btmp b/files/image_config/logrotate/logrotate.d/btmp new file mode 100644 index 000000000000..e3554d3e6773 --- /dev/null +++ b/files/image_config/logrotate/logrotate.d/btmp @@ -0,0 +1,7 @@ +# no packages own btmp -- we'll rotate it here +/var/log/btmp { + missingok + size 100k + create 0660 root utmp + rotate 1 +} diff --git a/files/image_config/logrotate/logrotate.d/wtmp b/files/image_config/logrotate/logrotate.d/wtmp new file mode 100644 index 000000000000..8eb2663e6b66 --- /dev/null +++ b/files/image_config/logrotate/logrotate.d/wtmp @@ -0,0 +1,7 @@ +# no packages own wtmp -- we'll rotate it here +/var/log/wtmp { + missingok + size 100k + create 0664 root utmp + rotate 1 +} From 83e78761e615d5419eff120de9ace45455b86d48 Mon Sep 17 00:00:00 2001 From: dflynn-Nokia <60479697+dflynn-Nokia@users.noreply.github.com> Date: Thu, 16 Sep 2021 05:07:06 -0400 Subject: [PATCH 17/34] [Nokia ixs7215] Add support for SFP eeprom type_abbrv_name attribute (#8772) --- .../7215/sonic_platform/fan_drawer.py | 18 +++++- .../7215/sonic_platform/sfp.py | 55 ++++++++++++------- 2 files changed, 52 insertions(+), 21 deletions(-) diff --git a/platform/marvell-armhf/sonic-platform-nokia/7215/sonic_platform/fan_drawer.py b/platform/marvell-armhf/sonic-platform-nokia/7215/sonic_platform/fan_drawer.py index e42d80cdbd52..6c6218f0a794 100644 --- a/platform/marvell-armhf/sonic-platform-nokia/7215/sonic_platform/fan_drawer.py +++ b/platform/marvell-armhf/sonic-platform-nokia/7215/sonic_platform/fan_drawer.py @@ -54,9 +54,25 @@ def get_direction(self): return 'intake' def set_status_led(self, color): + """ + Sets the state of the fan drawer status LED + + Args: + color: A string representing the color with which to set the + fan drawer status LED + + Returns: + bool: True if status LED state is set successfully, False if not + """ return self._fan_list[0].set_status_led(color) - def get_status_led(self, color): + def get_status_led(self): + """ + Gets the state of the fan drawer LED + + Returns: + A string, one of the predefined STATUS_LED_COLOR_* strings + """ return self._fan_list[0].get_status_led() def is_replaceable(self): diff --git a/platform/marvell-armhf/sonic-platform-nokia/7215/sonic_platform/sfp.py b/platform/marvell-armhf/sonic-platform-nokia/7215/sonic_platform/sfp.py index 308e8b29a60b..244e48e1e639 100644 --- a/platform/marvell-armhf/sonic-platform-nokia/7215/sonic_platform/sfp.py +++ b/platform/marvell-armhf/sonic-platform-nokia/7215/sonic_platform/sfp.py @@ -143,7 +143,7 @@ def __init__(self, index, sfp_type, eeprom_path, port_i2c_map): 'model', 'connector', 'encoding', 'ext_identifier', 'ext_rateselect_compliance', 'cable_type', 'cable_length', 'nominal_bit_rate', 'specification_compliance', - 'vendor_date', 'vendor_oui'] + 'type_abbrv_name', 'vendor_date', 'vendor_oui'] self.dom_dict_keys = ['rx_los', 'tx_fault', 'reset_status', 'power_lpmode', 'tx_disable', 'tx_disable_channel', 'temperature', @@ -274,6 +274,7 @@ def get_transceiver_info(self): cable_length |INT |cable length in m nominal_bit_rate |INT |nominal bit rate by 100Mbs specification_compliance |1*255VCHAR |specification compliance + type_abbrv_name |1*255VCHAR |type of SFP (abbreviated) vendor_date |1*255VCHAR |vendor date vendor_oui |1*255VCHAR |vendor OUI application_advertisement |1*255VCHAR |supported applications advertisement @@ -338,33 +339,47 @@ def get_transceiver_info(self): end = start + XCVR_VENDOR_DATE_WIDTH sfp_vendor_date_data = sfpi_obj.parse_vendor_date( sfp_interface_bulk_raw[start: end], 0) - transceiver_info_dict['type'] = sfp_interface_bulk_data['data']['type']['value'] - transceiver_info_dict['manufacturer'] = sfp_vendor_name_data['data']['Vendor Name']['value'] - transceiver_info_dict['model'] = sfp_vendor_pn_data['data']['Vendor PN']['value'] - transceiver_info_dict['hardware_rev'] = sfp_vendor_rev_data['data']['Vendor Rev']['value'] - transceiver_info_dict['serial'] = sfp_vendor_sn_data['data']['Vendor SN']['value'] - transceiver_info_dict['vendor_oui'] = sfp_vendor_oui_data['data']['Vendor OUI']['value'] - transceiver_info_dict['vendor_date'] = sfp_vendor_date_data[ - 'data']['VendorDataCode(YYYY-MM-DD Lot)']['value'] - transceiver_info_dict['connector'] = sfp_interface_bulk_data['data']['Connector']['value'] - transceiver_info_dict['encoding'] = sfp_interface_bulk_data['data']['EncodingCodes']['value'] - transceiver_info_dict['ext_identifier'] = sfp_interface_bulk_data['data']['Extended Identifier']['value'] - transceiver_info_dict['ext_rateselect_compliance'] = sfp_interface_bulk_data['data']['RateIdentifier']['value'] + + transceiver_info_dict['type'] = sfp_interface_bulk_data \ + ['data']['type']['value'] + transceiver_info_dict['manufacturer'] = sfp_vendor_name_data \ + ['data']['Vendor Name']['value'] + transceiver_info_dict['model'] = sfp_vendor_pn_data \ + ['data']['Vendor PN']['value'] + transceiver_info_dict['hardware_rev'] = sfp_vendor_rev_data \ + ['data']['Vendor Rev']['value'] + transceiver_info_dict['serial'] = sfp_vendor_sn_data \ + ['data']['Vendor SN']['value'] + transceiver_info_dict['vendor_oui'] = sfp_vendor_oui_data \ + ['data']['Vendor OUI']['value'] + transceiver_info_dict['vendor_date'] = sfp_vendor_date_data \ + ['data']['VendorDataCode(YYYY-MM-DD Lot)']['value'] + transceiver_info_dict['connector'] = sfp_interface_bulk_data \ + ['data']['Connector']['value'] + transceiver_info_dict['encoding'] = sfp_interface_bulk_data \ + ['data']['EncodingCodes']['value'] + transceiver_info_dict['ext_identifier'] = sfp_interface_bulk_data \ + ['data']['Extended Identifier']['value'] + transceiver_info_dict['ext_rateselect_compliance'] = sfp_interface_bulk_data \ + ['data']['RateIdentifier']['value'] + transceiver_info_dict['type_abbrv_name'] = sfp_interface_bulk_data \ + ['data']['type_abbrv_name']['value'] for key in sfp_cable_length_tup: if key in sfp_interface_bulk_data['data']: transceiver_info_dict['cable_type'] = key - transceiver_info_dict['cable_length'] = str( - sfp_interface_bulk_data['data'][key]['value']) + transceiver_info_dict['cable_length'] = \ + str(sfp_interface_bulk_data['data'][key]['value']) for key in sfp_compliance_code_tup: if key in sfp_interface_bulk_data['data']['Specification compliance']['value']: - compliance_code_dict[key] = sfp_interface_bulk_data['data']['Specification compliance']['value'][key]['value'] - transceiver_info_dict['specification_compliance'] = str( - compliance_code_dict) + compliance_code_dict[key] = sfp_interface_bulk_data \ + ['data']['Specification compliance']['value'][key]['value'] - transceiver_info_dict['nominal_bit_rate'] = str( - sfp_interface_bulk_data['data']['NominalSignallingRate(UnitsOf100Mbd)']['value']) + transceiver_info_dict['specification_compliance'] = \ + str(compliance_code_dict) + transceiver_info_dict['nominal_bit_rate'] = \ + str(sfp_interface_bulk_data['data']['NominalSignallingRate(UnitsOf100Mbd)']['value']) transceiver_info_dict['application_advertisement'] = 'N/A' return transceiver_info_dict From 5c2d4dd15c863289f755261e7e765ed43095d426 Mon Sep 17 00:00:00 2001 From: Aravind Mani <53524901+aravindmani-1@users.noreply.github.com> Date: Thu, 16 Sep 2021 07:25:43 -0700 Subject: [PATCH 18/34] DellEMC: Z9332f fix platform bugs (#8777) * DellEMC: Z9332f fix platform bugs * update sfp.py --- .../buffers_defaults_t0.j2 | 12 +++++------ .../buffers_defaults_t1.j2 | 12 +++++------ .../sai_postinit_cmd.soc | 7 +++---- .../z9332f/sonic_platform/sfp.py | 21 ++++++++++--------- 4 files changed, 26 insertions(+), 26 deletions(-) diff --git a/device/dell/x86_64-dellemc_z9332f_d1508-r0/DellEMC-Z9332f-M-O16C64/buffers_defaults_t0.j2 b/device/dell/x86_64-dellemc_z9332f_d1508-r0/DellEMC-Z9332f-M-O16C64/buffers_defaults_t0.j2 index 5ecbe788e3ab..33aaea75935d 100644 --- a/device/dell/x86_64-dellemc_z9332f_d1508-r0/DellEMC-Z9332f-M-O16C64/buffers_defaults_t0.j2 +++ b/device/dell/x86_64-dellemc_z9332f_d1508-r0/DellEMC-Z9332f-M-O16C64/buffers_defaults_t0.j2 @@ -4,18 +4,18 @@ {# Generate list of ports #} {%- for port_idx in range(0,12) %} {%- if PORT_ALL.append("Ethernet%d" % (port_idx * 8)) %}{%- endif %} - {%- if PORT_ALL.append("Ethernet%d" % (port_idx * 2) + 2) %}{%- endif %} - {%- if PORT_ALL.append("Ethernet%d" % (port_idx * 2) + 4) %}{%- endif %} - {%- if PORT_ALL.append("Ethernet%d" % (port_idx * 2) + 6) %}{%- endif %} + {%- if PORT_ALL.append("Ethernet%d" % (port_idx * 8) + 2) %}{%- endif %} + {%- if PORT_ALL.append("Ethernet%d" % (port_idx * 8) + 4) %}{%- endif %} + {%- if PORT_ALL.append("Ethernet%d" % (port_idx * 8) + 6) %}{%- endif %} {%- endfor %} {%- for port_idx in range(12,16) %} {%- if PORT_ALL.append("Ethernet%d" % (port_idx * 8)) %}{%- endif %} {%- endfor %} {%- for port_idx in range(16,20) %} {%- if PORT_ALL.append("Ethernet%d" % (port_idx * 8)) %}{%- endif %} - {%- if PORT_ALL.append("Ethernet%d" % (port_idx * 2) + 2) %}{%- endif %} - {%- if PORT_ALL.append("Ethernet%d" % (port_idx * 2) + 4) %}{%- endif %} - {%- if PORT_ALL.append("Ethernet%d" % (port_idx * 2) + 6) %}{%- endif %} + {%- if PORT_ALL.append("Ethernet%d" % (port_idx * 8) + 2) %}{%- endif %} + {%- if PORT_ALL.append("Ethernet%d" % (port_idx * 8) + 4) %}{%- endif %} + {%- if PORT_ALL.append("Ethernet%d" % (port_idx * 8) + 6) %}{%- endif %} {%- endfor %} {%- for port_idx in range(20,32) %} {%- if PORT_ALL.append("Ethernet%d" % (port_idx * 8)) %}{%- endif %} diff --git a/device/dell/x86_64-dellemc_z9332f_d1508-r0/DellEMC-Z9332f-M-O16C64/buffers_defaults_t1.j2 b/device/dell/x86_64-dellemc_z9332f_d1508-r0/DellEMC-Z9332f-M-O16C64/buffers_defaults_t1.j2 index 5ecbe788e3ab..33aaea75935d 100644 --- a/device/dell/x86_64-dellemc_z9332f_d1508-r0/DellEMC-Z9332f-M-O16C64/buffers_defaults_t1.j2 +++ b/device/dell/x86_64-dellemc_z9332f_d1508-r0/DellEMC-Z9332f-M-O16C64/buffers_defaults_t1.j2 @@ -4,18 +4,18 @@ {# Generate list of ports #} {%- for port_idx in range(0,12) %} {%- if PORT_ALL.append("Ethernet%d" % (port_idx * 8)) %}{%- endif %} - {%- if PORT_ALL.append("Ethernet%d" % (port_idx * 2) + 2) %}{%- endif %} - {%- if PORT_ALL.append("Ethernet%d" % (port_idx * 2) + 4) %}{%- endif %} - {%- if PORT_ALL.append("Ethernet%d" % (port_idx * 2) + 6) %}{%- endif %} + {%- if PORT_ALL.append("Ethernet%d" % (port_idx * 8) + 2) %}{%- endif %} + {%- if PORT_ALL.append("Ethernet%d" % (port_idx * 8) + 4) %}{%- endif %} + {%- if PORT_ALL.append("Ethernet%d" % (port_idx * 8) + 6) %}{%- endif %} {%- endfor %} {%- for port_idx in range(12,16) %} {%- if PORT_ALL.append("Ethernet%d" % (port_idx * 8)) %}{%- endif %} {%- endfor %} {%- for port_idx in range(16,20) %} {%- if PORT_ALL.append("Ethernet%d" % (port_idx * 8)) %}{%- endif %} - {%- if PORT_ALL.append("Ethernet%d" % (port_idx * 2) + 2) %}{%- endif %} - {%- if PORT_ALL.append("Ethernet%d" % (port_idx * 2) + 4) %}{%- endif %} - {%- if PORT_ALL.append("Ethernet%d" % (port_idx * 2) + 6) %}{%- endif %} + {%- if PORT_ALL.append("Ethernet%d" % (port_idx * 8) + 2) %}{%- endif %} + {%- if PORT_ALL.append("Ethernet%d" % (port_idx * 8) + 4) %}{%- endif %} + {%- if PORT_ALL.append("Ethernet%d" % (port_idx * 8) + 6) %}{%- endif %} {%- endfor %} {%- for port_idx in range(20,32) %} {%- if PORT_ALL.append("Ethernet%d" % (port_idx * 8)) %}{%- endif %} diff --git a/device/dell/x86_64-dellemc_z9332f_d1508-r0/DellEMC-Z9332f-M-O16C64/sai_postinit_cmd.soc b/device/dell/x86_64-dellemc_z9332f_d1508-r0/DellEMC-Z9332f-M-O16C64/sai_postinit_cmd.soc index 4a5b5ffcad9a..3222a4906bdf 100644 --- a/device/dell/x86_64-dellemc_z9332f_d1508-r0/DellEMC-Z9332f-M-O16C64/sai_postinit_cmd.soc +++ b/device/dell/x86_64-dellemc_z9332f_d1508-r0/DellEMC-Z9332f-M-O16C64/sai_postinit_cmd.soc @@ -373,6 +373,7 @@ phy $port TXFIR_TAP_CTL4r.3 TXFIR_TAP4_COEFF=0 phy $port TXFIR_TAP_CTL5r.3 TXFIR_TAP5_COEFF=0 phy $port TXFIR_TAP_CTL0r.3 TXFIR_TAP_LOAD=0x1 +local port ce18 #*** lane 4 *** phy $port TXFIR_TAP_CTL0r.4 TXFIR_TAP0_COEFF=0 phy $port TXFIR_TAP_CTL1r.4 TXFIR_TAP1_COEFF=0x1E8 @@ -382,8 +383,6 @@ phy $port TXFIR_TAP_CTL4r.4 TXFIR_TAP4_COEFF=0 phy $port TXFIR_TAP_CTL5r.4 TXFIR_TAP5_COEFF=0 phy $port TXFIR_TAP_CTL0r.4 TXFIR_TAP_LOAD=0x1 - -local port ce18 #*** lane 5 *** phy $port TXFIR_TAP_CTL0r.5 TXFIR_TAP0_COEFF=0 phy $port TXFIR_TAP_CTL1r.5 TXFIR_TAP1_COEFF=0x1E8 @@ -393,6 +392,7 @@ phy $port TXFIR_TAP_CTL4r.5 TXFIR_TAP4_COEFF=0 phy $port TXFIR_TAP_CTL5r.5 TXFIR_TAP5_COEFF=0 phy $port TXFIR_TAP_CTL0r.5 TXFIR_TAP_LOAD=0x1 +local port ce19 #*** lane 6 *** phy $port TXFIR_TAP_CTL0r.6 TXFIR_TAP0_COEFF=0 phy $port TXFIR_TAP_CTL1r.6 TXFIR_TAP1_COEFF=0x1E8 @@ -402,7 +402,6 @@ phy $port TXFIR_TAP_CTL4r.6 TXFIR_TAP4_COEFF=0 phy $port TXFIR_TAP_CTL5r.6 TXFIR_TAP5_COEFF=0 phy $port TXFIR_TAP_CTL0r.6 TXFIR_TAP_LOAD=0x1 -local port ce19 #*** lane 7 *** phy $port TXFIR_TAP_CTL0r.7 TXFIR_TAP0_COEFF=4 phy $port TXFIR_TAP_CTL1r.7 TXFIR_TAP1_COEFF=0x1E4 @@ -974,6 +973,7 @@ phy $port TXFIR_TAP_CTL4r.5 TXFIR_TAP4_COEFF=0 phy $port TXFIR_TAP_CTL5r.5 TXFIR_TAP5_COEFF=0 phy $port TXFIR_TAP_CTL0r.5 TXFIR_TAP_LOAD=0x1 +local port ce47 #*** lane 6 *** phy $port TXFIR_TAP_CTL0r.6 TXFIR_TAP0_COEFF=0 phy $port TXFIR_TAP_CTL1r.6 TXFIR_TAP1_COEFF=0x1E8 @@ -983,7 +983,6 @@ phy $port TXFIR_TAP_CTL4r.6 TXFIR_TAP4_COEFF=0 phy $port TXFIR_TAP_CTL5r.6 TXFIR_TAP5_COEFF=0 phy $port TXFIR_TAP_CTL0r.6 TXFIR_TAP_LOAD=0x1 -local port ce47 #*** lane 7 *** phy $port TXFIR_TAP_CTL0r.7 TXFIR_TAP0_COEFF=4 phy $port TXFIR_TAP_CTL1r.7 TXFIR_TAP1_COEFF=0x1E4 diff --git a/platform/broadcom/sonic-platform-modules-dell/z9332f/sonic_platform/sfp.py b/platform/broadcom/sonic-platform-modules-dell/z9332f/sonic_platform/sfp.py index 4fe4b261cad0..744f47236208 100644 --- a/platform/broadcom/sonic-platform-modules-dell/z9332f/sonic_platform/sfp.py +++ b/platform/broadcom/sonic-platform-modules-dell/z9332f/sonic_platform/sfp.py @@ -713,6 +713,7 @@ def get_transceiver_bulk_status(self): Retrieves transceiver bulk status of this SFP """ tx_bias_list = [] + tx_power_list = [] rx_power_list = [] transceiver_dom_dict = {} transceiver_dom_dict = dict.fromkeys(dom_dict_keys, 'N/A') @@ -751,7 +752,7 @@ def get_transceiver_bulk_status(self): rx_power_list = self.get_rx_power() if self.sfp_type == 'QSFP_DD': - if tx_bias_list is not None: + if tx_bias_list: transceiver_dom_dict['tx1bias'] = tx_bias_list[0] transceiver_dom_dict['tx2bias'] = tx_bias_list[1] transceiver_dom_dict['tx3bias'] = tx_bias_list[2] @@ -762,17 +763,17 @@ def get_transceiver_bulk_status(self): transceiver_dom_dict['tx8bias'] = tx_bias_list[7] elif self.sfp_type == 'QSFP': - if tx_bias_list is not None: + if tx_bias_list: transceiver_dom_dict['tx1bias'] = tx_bias_list[0] transceiver_dom_dict['tx2bias'] = tx_bias_list[1] transceiver_dom_dict['tx3bias'] = tx_bias_list[2] transceiver_dom_dict['tx4bias'] = tx_bias_list[3] else: - if tx_bias_list is not None: + if tx_bias_list: transceiver_dom_dict['tx1bias'] = tx_bias_list[0] if self.sfp_type == 'QSFP_DD': - if rx_power_list is not None: + if rx_power_list: transceiver_dom_dict['rx1power'] = rx_power_list[0] transceiver_dom_dict['rx2power'] = rx_power_list[1] transceiver_dom_dict['rx3power'] = rx_power_list[2] @@ -783,17 +784,17 @@ def get_transceiver_bulk_status(self): transceiver_dom_dict['rx8power'] = rx_power_list[7] elif self.sfp_type == 'QSFP': - if rx_power_list is not None: + if rx_power_list: transceiver_dom_dict['rx1power'] = rx_power_list[0] transceiver_dom_dict['rx2power'] = rx_power_list[1] transceiver_dom_dict['rx3power'] = rx_power_list[2] transceiver_dom_dict['rx4power'] = rx_power_list[3] else: - if rx_power_list is not None: + if rx_power_list: transceiver_dom_dict['rx1power'] = rx_power_list[0] if self.sfp_type == 'QSFP_DD': - if tx_power_list is not None: + if tx_power_list: transceiver_dom_dict['tx1power'] = tx_power_list[0] transceiver_dom_dict['tx2power'] = tx_power_list[1] transceiver_dom_dict['tx3power'] = tx_power_list[2] @@ -803,14 +804,14 @@ def get_transceiver_bulk_status(self): transceiver_dom_dict['tx7power'] = tx_power_list[6] transceiver_dom_dict['tx8power'] = tx_power_list[7] elif self.sfp_type == 'QSFP': - if tx_power_list is not None: + if tx_power_list: transceiver_dom_dict['tx1power'] = tx_power_list[0] transceiver_dom_dict['tx2power'] = tx_power_list[1] transceiver_dom_dict['tx3power'] = tx_power_list[2] transceiver_dom_dict['tx4power'] = tx_power_list[3] else: - if tx_power_list is not None: - transceiver_dom_dict['tx1power'] = tx_power_list[0] + if tx_power_list: + transceiver_dom_dict['tx1power'] = tx_power_list[0] transceiver_dom_dict['rx_los'] = rx_los transceiver_dom_dict['tx_fault'] = tx_fault transceiver_dom_dict['reset_status'] = reset_state From 508b6497a1108c38b89bd6f9fadce95a2241d511 Mon Sep 17 00:00:00 2001 From: Sudharsan Dhamal Gopalarathnam Date: Thu, 16 Sep 2021 11:04:46 -0700 Subject: [PATCH 19/34] Advancing sonic-sairedis submodule pointer (#8775) --- src/sonic-sairedis | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/sonic-sairedis b/src/sonic-sairedis index 696ad9929db2..78f36138e14e 160000 --- a/src/sonic-sairedis +++ b/src/sonic-sairedis @@ -1 +1 @@ -Subproject commit 696ad9929db26a446518dbcd22c8f742025f2b93 +Subproject commit 78f36138e14e1ed0f0f772950f03420327ef1b1c From f6ec932b3cb1a78f79bf0af9c72c1f9ae060332c Mon Sep 17 00:00:00 2001 From: Arun Saravanan Balachandran <52521751+ArunSaravananBalachandran@users.noreply.github.com> Date: Fri, 17 Sep 2021 06:25:50 +0530 Subject: [PATCH 20/34] DellEMC Z9332f: Platform API - Update maximum fan speed (#8766) --- .../z9332f/sonic_platform/fan.py | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/platform/broadcom/sonic-platform-modules-dell/z9332f/sonic_platform/fan.py b/platform/broadcom/sonic-platform-modules-dell/z9332f/sonic_platform/fan.py index 6ffadb2a1e5f..4fce691c02f1 100755 --- a/platform/broadcom/sonic-platform-modules-dell/z9332f/sonic_platform/fan.py +++ b/platform/broadcom/sonic-platform-modules-dell/z9332f/sonic_platform/fan.py @@ -48,6 +48,10 @@ def __init__(self, fantray_index=1, fan_index=1, psu_fan=False, dependency=None) is_discrete=True) self.speed_sensor = IpmiSensor(self.FAN_SENSOR_MAPPING[self.index]["Speed"]) self.fan_dir_raw_cmd = "0x3a 0x0a {}".format(fantray_index) + if self.fanindex == 1: + self.max_speed = 24700 + else: + self.max_speed = 29700 else: self.dependency = dependency self.fanindex = fan_index @@ -55,7 +59,7 @@ def __init__(self, fantray_index=1, fan_index=1, psu_fan=False, dependency=None) is_discrete=True) self.speed_sensor = IpmiSensor(self.PSU_FAN_SENSOR_MAPPING[self.fanindex]["Speed"]) self.fan_dir_raw_cmd = "0x3a 0x0a {}".format(7+(fan_index-1)) - self.max_speed = 23500 + self.max_speed = 26500 def get_name(self): """ From 1a2e85248309faf3c4b7d3decb34ec4377df0284 Mon Sep 17 00:00:00 2001 From: dflynn-Nokia <60479697+dflynn-Nokia@users.noreply.github.com> Date: Fri, 17 Sep 2021 00:01:12 -0400 Subject: [PATCH 21/34] [Nokia ixs7215] Support show system-health (#8771) * [Nokia ixs7215] Support show system-health * [Nokia ixs7215] Fix LGTM alert --- .../system_health_monitoring_config.json | 14 +++++ .../7215/sonic_platform/chassis.py | 51 +++++++++++-------- 2 files changed, 44 insertions(+), 21 deletions(-) create mode 100644 device/nokia/armhf-nokia_ixs7215_52x-r0/system_health_monitoring_config.json diff --git a/device/nokia/armhf-nokia_ixs7215_52x-r0/system_health_monitoring_config.json b/device/nokia/armhf-nokia_ixs7215_52x-r0/system_health_monitoring_config.json new file mode 100644 index 000000000000..fb16658c840c --- /dev/null +++ b/device/nokia/armhf-nokia_ixs7215_52x-r0/system_health_monitoring_config.json @@ -0,0 +1,14 @@ +{ + "services_to_ignore": [], + "devices_to_ignore": [ + "asic", + "psu" + ], + "user_defined_checkers": [], + "polling_interval": 60, + "led_color": { + "fault": "amber", + "normal": "green", + "booting": "blinking green" + } +} diff --git a/platform/marvell-armhf/sonic-platform-nokia/7215/sonic_platform/chassis.py b/platform/marvell-armhf/sonic-platform-nokia/7215/sonic_platform/chassis.py index a01aca24b684..cf67a7bb30ac 100755 --- a/platform/marvell-armhf/sonic-platform-nokia/7215/sonic_platform/chassis.py +++ b/platform/marvell-armhf/sonic-platform-nokia/7215/sonic_platform/chassis.py @@ -27,6 +27,11 @@ except ImportError as e: smbus_present = 0 +if sys.version_info[0] < 3: + import commands as cmd +else: + import subprocess as cmd + MAX_SELECT_DELAY = 3600 COPPER_PORT_START = 1 COPPER_PORT_END = 48 @@ -278,6 +283,9 @@ def get_thermal_manager(self): from .thermal_manager import ThermalManager return ThermalManager + def initizalize_system_led(self): + return True + def set_status_led(self, color): """ Sets the state of the system LED @@ -306,17 +314,18 @@ def set_status_led(self, color): return False # Write sys led - if smbus_present == 0: - sonic_logger.log_warning("PMON LED SET -> smbus present = 0") + if smbus_present == 0: # called from host (e.g. 'show system-health') + cmdstatus, value = cmd.getstatusoutput('sudo i2cset -y 0 0x41 0x7 %d' % value) + if cmdstatus: + sonic_logger.log_warning(" System LED set %s failed" % value) + return False else: bus = smbus.SMBus(0) DEVICE_ADDRESS = 0x41 DEVICEREG = 0x7 bus.write_byte_data(DEVICE_ADDRESS, DEVICEREG, value) - sonic_logger.log_info(" System LED set O.K. ") - return True - return False + return True def get_status_led(self): """ @@ -327,29 +336,29 @@ def get_status_led(self): specified. """ # Read sys led - if smbus_present == 0: - sonic_logger.log_warning("PMON LED GET -> smbus present = 0") - return False + if smbus_present == 0: # called from host + cmdstatus, value = cmd.getstatusoutput('sudo i2cget -y 0 0x41 0x7') + value = int(value, 16) else: bus = smbus.SMBus(0) DEVICE_ADDRESS = 0x41 DEVICE_REG = 0x7 value = bus.read_byte_data(DEVICE_ADDRESS, DEVICE_REG) - if value == 0x00: - color = 'off' - elif value == 0x01: - color = 'amber' - elif value == 0x02: - color = 'green' - elif value == 0x03: - color = 'amber_blink' - elif value == 0x04: - color = 'green_blink' - else: - return False + if value == 0x00: + color = 'off' + elif value == 0x01: + color = 'amber' + elif value == 0x02: + color = 'green' + elif value == 0x03: + color = 'amber_blink' + elif value == 0x04: + color = 'green_blink' + else: + return None - return color + return color def get_watchdog(self): """ From e6699a0132c141b000af99521eab1fabf6942921 Mon Sep 17 00:00:00 2001 From: Shilong Liu Date: Fri, 17 Sep 2021 16:18:36 +0800 Subject: [PATCH 22/34] Add pipeline to build vhdx image. (#8665) * Add pipeline to build vhdx image --- .azure-pipelines/azure-pipelines-build.yml | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/.azure-pipelines/azure-pipelines-build.yml b/.azure-pipelines/azure-pipelines-build.yml index eb3c3aa21bb8..2b90f6bf3cd4 100644 --- a/.azure-pipelines/azure-pipelines-build.yml +++ b/.azure-pipelines/azure-pipelines-build.yml @@ -104,6 +104,11 @@ jobs: make $BUILD_OPTIONS INSTALL_DEBUG_TOOLS=y target/sonic-vs.img.gz && mv target/sonic-vs.img.gz target/sonic-vs-dbg.img.gz fi make $BUILD_OPTIONS target/docker-sonic-vs.gz target/sonic-vs.img.gz target/docker-ptf.gz + if [ $(Build.Reason) != 'PullRequest' ];then + gzip -kd target/sonic-vs.img.gz + SONIC_RUN_CMDS="qemu-img convert target/sonic-vs.img -O vhdx -o subformat=dynamic target/sonic-vs.vhdx" make sonic-slave-run + rm target/sonic-vs.img + fi else if [ $(dbg_image) == yes ]; then make $BUILD_OPTIONS INSTALL_DEBUG_TOOLS=y target/sonic-$(GROUP_NAME).bin && \ From f1dac178f05a635bb597cbd2f4bbc47f91ee243a Mon Sep 17 00:00:00 2001 From: Prince George <45705344+prgeor@users.noreply.github.com> Date: Sat, 18 Sep 2021 12:31:05 +0530 Subject: [PATCH 23/34] Update sonic-platform-daemon submodule (#8788) Signed-off-by: Prince George --- src/sonic-platform-daemons | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/sonic-platform-daemons b/src/sonic-platform-daemons index e038bc2997ab..84386e6a1c46 160000 --- a/src/sonic-platform-daemons +++ b/src/sonic-platform-daemons @@ -1 +1 @@ -Subproject commit e038bc2997ab7504b544c087bb88bb01b3bd620c +Subproject commit 84386e6a1c46e96bacb6c449c7611904227f58fb From e46dd633d85ae57ce34c7130854dbfe048b8a51c Mon Sep 17 00:00:00 2001 From: yozhao101 <56170650+yozhao101@users.noreply.github.com> Date: Sat, 18 Sep 2021 10:31:36 -0700 Subject: [PATCH 24/34] [healthd] Add system health configuration for platform Celestica E1031 (#8783) This PR aims to fix the healthd crash issue by adding system health monitoring configuration file for platform Celestica E1031 by adding a new configuration file under the path device/celestica/x86_64-cel_e1031-r0/. How to verify it I manually restart the system-health.service and confirmed that healthd is running. Signed-off-by: Yong Zhao --- .../system_health_monitoring_config.json | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) create mode 100644 device/celestica/x86_64-cel_e1031-r0/system_health_monitoring_config.json diff --git a/device/celestica/x86_64-cel_e1031-r0/system_health_monitoring_config.json b/device/celestica/x86_64-cel_e1031-r0/system_health_monitoring_config.json new file mode 100644 index 000000000000..1733fcffdba3 --- /dev/null +++ b/device/celestica/x86_64-cel_e1031-r0/system_health_monitoring_config.json @@ -0,0 +1,16 @@ +{ + "services_to_ignore": [], + "devices_to_ignore": [ + "asic", + "psu.temperature", + "PSU2 Fan", + "PSU1 Fan" + ], + "user_defined_checkers": [], + "polling_interval": 60, + "led_color": { + "fault": "orange", + "normal": "green", + "booting": "orange_blink" + } +} From d588b3bc8c417fd89ec77caaf595830022897701 Mon Sep 17 00:00:00 2001 From: Arun Saravanan Balachandran <52521751+ArunSaravananBalachandran@users.noreply.github.com> Date: Mon, 20 Sep 2021 00:45:22 +0530 Subject: [PATCH 25/34] DellEMC: Z9332f - Platform API implementation (#8787) --- .../z9332f/sonic_platform/chassis.py | 9 +++++++ .../z9332f/sonic_platform/eeprom.py | 2 +- .../z9332f/sonic_platform/fan_drawer.py | 10 +++++++ .../z9332f/sonic_platform/psu.py | 27 +++++++++++++++++++ 4 files changed, 47 insertions(+), 1 deletion(-) diff --git a/platform/broadcom/sonic-platform-modules-dell/z9332f/sonic_platform/chassis.py b/platform/broadcom/sonic-platform-modules-dell/z9332f/sonic_platform/chassis.py index aba6160d1938..fac058f45207 100755 --- a/platform/broadcom/sonic-platform-modules-dell/z9332f/sonic_platform/chassis.py +++ b/platform/broadcom/sonic-platform-modules-dell/z9332f/sonic_platform/chassis.py @@ -270,6 +270,15 @@ def get_serial_number(self): """ return self._eeprom.serial_number_str() + def get_revision(self): + """ + Retrieves the hardware revision of the device + + Returns: + string: Revision value of device + """ + return self._eeprom.revision_str() + def get_system_eeprom_info(self): """ Retrieves the full content of system EEPROM information for the chassis diff --git a/platform/broadcom/sonic-platform-modules-dell/z9332f/sonic_platform/eeprom.py b/platform/broadcom/sonic-platform-modules-dell/z9332f/sonic_platform/eeprom.py index 1dc66935508c..fe7da80d012f 100644 --- a/platform/broadcom/sonic-platform-modules-dell/z9332f/sonic_platform/eeprom.py +++ b/platform/broadcom/sonic-platform-modules-dell/z9332f/sonic_platform/eeprom.py @@ -118,7 +118,7 @@ def revision_str(self): Returns the device revision """ (is_valid, results) = self.get_tlv_field( - self.eeprom_data, self._TLV_CODE_DEVICE_VERSION) + self.eeprom_data, self._TLV_CODE_LABEL_REVISION) if not is_valid: return "N/A" diff --git a/platform/broadcom/sonic-platform-modules-dell/z9332f/sonic_platform/fan_drawer.py b/platform/broadcom/sonic-platform-modules-dell/z9332f/sonic_platform/fan_drawer.py index f7ea8a4cbf6c..98d9f95c53fb 100644 --- a/platform/broadcom/sonic-platform-modules-dell/z9332f/sonic_platform/fan_drawer.py +++ b/platform/broadcom/sonic-platform-modules-dell/z9332f/sonic_platform/fan_drawer.py @@ -103,3 +103,13 @@ def set_status_led(self, color): # Fan tray status LED controlled by BMC # Return True to avoid thermalctld alarm return True + + def get_maximum_consumed_power(self): + """ + Retrives the maximum power drawn by Fan Drawer + + Returns: + A float, with value of the maximum consumable power of the + component. + """ + return 36.0 diff --git a/platform/broadcom/sonic-platform-modules-dell/z9332f/sonic_platform/psu.py b/platform/broadcom/sonic-platform-modules-dell/z9332f/sonic_platform/psu.py index 28d62aa0152b..5aeebd4144b2 100644 --- a/platform/broadcom/sonic-platform-modules-dell/z9332f/sonic_platform/psu.py +++ b/platform/broadcom/sonic-platform-modules-dell/z9332f/sonic_platform/psu.py @@ -87,6 +87,19 @@ def get_serial(self): """ return self.fru.get_board_serial() + def get_revision(self): + """ + Retrieves the hardware revision of the device + + Returns: + string: Revision value of device + """ + serial = self.fru.get_board_serial() + if serial != "NA" and len(serial) == 23: + return serial[-3:] + else: + return "NA" + def get_status(self): """ Retrieves the operational status of the PSU @@ -193,6 +206,20 @@ def get_power(self): return float(power) + def get_maximum_supplied_power(self): + """ + Retrieves the maximum supplied power by PSU + + Returns: + A float number, the maximum power output in Watts. + e.g. 1200.1 + """ + is_valid, power = self.power_sensor.get_threshold("UpperCritical") + if not is_valid: + return None + + return float(power) + def get_powergood_status(self): """ Retrieves the powergood status of PSU From 40490675341ce4dd5bdb916ef34cb1c6fd6e5685 Mon Sep 17 00:00:00 2001 From: AmitKaushik7 <52193450+AmitKaushik7@users.noreply.github.com> Date: Tue, 21 Sep 2021 03:28:30 +0530 Subject: [PATCH 26/34] [yang]: Adding yang model for PFC watch dog parameters (#7839) Added sonic-pfcwd.yang file that defines the yang model for PFC watch dog parameters sonic-pfcwd.yang is required for configuring action, detection_time, restoration time of PFC watchdog on the interface port. --- src/sonic-yang-models/setup.py | 1 + .../tests/files/sample_config_db.json | 15 +- .../tests/yang_model_tests/tests/pfc.json | 42 ++++ .../yang_model_tests/tests_config/pfc.json | 199 ++++++++++++++++++ .../yang-models/sonic-pfcwd.yang | 79 +++++++ 5 files changed, 333 insertions(+), 3 deletions(-) create mode 100644 src/sonic-yang-models/tests/yang_model_tests/tests/pfc.json create mode 100644 src/sonic-yang-models/tests/yang_model_tests/tests_config/pfc.json create mode 100644 src/sonic-yang-models/yang-models/sonic-pfcwd.yang diff --git a/src/sonic-yang-models/setup.py b/src/sonic-yang-models/setup.py index 13ce554d022c..8c19b719e34d 100644 --- a/src/sonic-yang-models/setup.py +++ b/src/sonic-yang-models/setup.py @@ -62,6 +62,7 @@ './yang-models/sonic-nat.yang', './yang-models/sonic-port.yang', './yang-models/sonic-portchannel.yang', + './yang-models/sonic-pfcwd.yang', './yang-models/sonic-route-common.yang', './yang-models/sonic-route-map.yang', './yang-models/sonic-routing-policy-sets.yang', diff --git a/src/sonic-yang-models/tests/files/sample_config_db.json b/src/sonic-yang-models/tests/files/sample_config_db.json index 5d8009afbc04..0778a7a87ad6 100644 --- a/src/sonic-yang-models/tests/files/sample_config_db.json +++ b/src/sonic-yang-models/tests/files/sample_config_db.json @@ -879,7 +879,18 @@ "polling_interval": "0" } }, - + "PFC_WD": { + "Ethernet9": { + "action": "drop", + "detection_time": "100", + "restoration_time": "400" + } + }, + "PFC_WD": { + "GLOBAL": { + "POLL_INTERVAL": "100" + } + }, "SFLOW_COLLECTOR": { "collector1": { "collector_ip": "10.100.12.13", @@ -908,7 +919,6 @@ "agent_id": "Ethernet0" } }, - "AAA": { "authentication": { "login": "local" @@ -925,7 +935,6 @@ "timeout": "10" } }, - "NAT_BINDINGS": { "bind1": { "nat_pool": "pool1", diff --git a/src/sonic-yang-models/tests/yang_model_tests/tests/pfc.json b/src/sonic-yang-models/tests/yang_model_tests/tests/pfc.json new file mode 100644 index 000000000000..4405075aeefc --- /dev/null +++ b/src/sonic-yang-models/tests/yang_model_tests/tests/pfc.json @@ -0,0 +1,42 @@ +{ + "PFC_WDOG_WITH_CORRECT_ACTION_DROP_VALUE": { + "desc": "PFC_WDOG_WITH_CORRECT_ACTION_DROP_VALUE no failure." + }, + "PFC_WDOG_WITH_CORRECT_ACTION_FORWARD_VALUE": { + "desc": "PFC_WDOG_WITH_CORRECT_ACTION_FORWARD_VALUE no failure." + }, + "PFC_WDOG_WITH_CORRECT_ACTION_ALERT_VALUE": { + "desc": "PFC_WDOG_WITH_CORRECT_ACTION_ALERT_VALUE no failure." + }, + "PFC_WDOG_WITH_WRONG_ACTION_VALUE": { + "desc": "PFC_WDOG_WITH_WRONG_ACTION_VALUE must contain a valid action", + "eStr": [ "wrong" ] + }, + "PFC_WDOG_WITH_CORRECT_POLL_INTERVAL_VALUE": { + "desc": "PFC_WDOG_WITH_CORRECT_POLL_INTERVAL_VALUE no failure" + }, + "PFC_WDOG_WITH_WRONG_POLL_INTERVAL_LOW_VALUE": { + "desc": "PFC_WDOG_WITH_WRONG_POLL_INTERVAL_LOW_VALUE", + "eStr": "range" + }, + "PFC_WDOG_WITH_WRONG_POLL_INTERVAL_HIGH_VALUE": { + "desc": "PFC_WDOG_WITH_WRONG_POLL_INTERVAL_HIGH_VALUE", + "eStr": "range" + }, + "PFC_WDOG_WITH_WRONG_DETECTION_TIME_LOW_VALUE": { + "desc": "PFC_WDOG_WITH_WRONG_DETECTION_TIME_LOW_VALUE", + "eStr": "range" + }, + "PFC_WDOG_WITH_WRONG_DETECTION_TIME_HIGH_VALUE": { + "desc": "PFC_WDOG_WITH_WRONG_DETECTION_TIME_HIGH_VALUE", + "eStr": "range" + }, + "PFC_WDOG_WITH_WRONG_RESTORATION_TIME_LOW_VALUE": { + "desc": "PFC_WDOG_WITH_WRONG_RESTORATION_TIME_LOW_VALUE", + "eStr": "range" + }, + "PFC_WDOG_WITH_WRONG_RESTORATION_TIME_HIGH_VALUE": { + "desc": "PFC_WDOG_WITH_WRONG_RESTORATION_TIME_HIGH_VALUE", + "eStr": "range" + } +} diff --git a/src/sonic-yang-models/tests/yang_model_tests/tests_config/pfc.json b/src/sonic-yang-models/tests/yang_model_tests/tests_config/pfc.json new file mode 100644 index 000000000000..8c31d6dd98ed --- /dev/null +++ b/src/sonic-yang-models/tests/yang_model_tests/tests_config/pfc.json @@ -0,0 +1,199 @@ +{ + "PFC_WDOG_WITH_CORRECT_ACTION_DROP_VALUE": { + "sonic-port:sonic-port": { + "sonic-port:PORT": { + "PORT_LIST": [ + { + "admin_status": "up", + "alias": "eth0", + "description": "Ethernet4", + "lanes": "65", + "mtu": "9000", + "name": "Ethernet4", + "tpid": "0x8100", + "speed": "25000" + } + ] + } + }, + "sonic-pfcwd:sonic-pfcwd": { + "sonic-pfcwd:PFC_WD": { + "PFC_WD_LIST": [ + { + "ifname": "Ethernet4", + "action": "drop", + "detection_time": 300, + "restoration_time": 3000 + } + ] + } + } + }, + "PFC_WDOG_WITH_CORRECT_ACTION_FORWARD_VALUE": { + "sonic-port:sonic-port": { + "sonic-port:PORT": { + "PORT_LIST": [ + { + "admin_status": "up", + "alias": "eth0", + "description": "Ethernet4", + "lanes": "65", + "mtu": "9000", + "name": "Ethernet4", + "tpid": "0x8100", + "speed": "25000" + } + ] + } + }, + "sonic-pfcwd:sonic-pfcwd": { + "sonic-pfcwd:PFC_WD": { + "PFC_WD_LIST": [ + { + "ifname": "Ethernet4", + "action": "forward", + "detection_time": 300, + "restoration_time": 3000 + } + ] + } + } + }, + "PFC_WDOG_WITH_CORRECT_ACTION_ALERT_VALUE": { + "sonic-port:sonic-port": { + "sonic-port:PORT": { + "PORT_LIST": [ + { + "admin_status": "up", + "alias": "eth0", + "description": "Ethernet4", + "lanes": "65", + "mtu": "9000", + "name": "Ethernet4", + "tpid": "0x8100", + "speed": "25000" + } + ] + } + }, + + "sonic-pfcwd:sonic-pfcwd": { + "sonic-pfcwd:PFC_WD": { + "PFC_WD_LIST": [ + { + "ifname": "Ethernet4", + "action": "alert", + "detection_time": 300, + "restoration_time": 3000 + } + ] + } + } + }, + "PFC_WDOG_WITH_WRONG_ACTION_VALUE": { + "sonic-pfcwd:sonic-pfcwd": { + "sonic-pfcwd:PFC_WD": { + "PFC_WD_LIST": [ + { + "ifname": "Ethernet4", + "action": "wrong", + "detection_time": 300, + "restoration_time": 3000 + } + ] + } + } + }, + "PFC_WDOG_WITH_CORRECT_POLL_INTERVAL_VALUE": { + "sonic-pfcwd:sonic-pfcwd": { + "sonic-pfcwd:PFC_WD": { + "PFC_WD_LIST": [ + { + "ifname": "GLOBAL", + "POLL_INTERVAL": 101 + } + ] + } + } + }, + "PFC_WDOG_WITH_WRONG_POLL_INTERVAL_LOW_VALUE": { + "sonic-pfcwd:sonic-pfcwd": { + "sonic-pfcwd:PFC_WD": { + "PFC_WD_LIST": [ + { + "ifname": "GLOBAL", + "POLL_INTERVAL":99 + } + ] + } + } + }, + "PFC_WDOG_WITH_WRONG_POLL_INTERVAL_HIGH_VALUE": { + "sonic-pfcwd:sonic-pfcwd": { + "sonic-pfcwd:PFC_WD": { + "PFC_WD_LIST": [ + { + "ifname": "GLOBAL", + "POLL_INTERVAL": 3001 + } + ] + } + } + }, + "PFC_WDOG_WITH_WRONG_DETECTION_TIME_LOW_VALUE": { + "sonic-pfcwd:sonic-pfcwd": { + "sonic-pfcwd:PFC_WD": { + "PFC_WD_LIST": [ + { + "ifname": "Ethernet4", + "action": "drop", + "detection_time": 99, + "restoration_time": 3000 + } + ] + } + } + }, + "PFC_WDOG_WITH_WRONG_DETECTION_TIME_HIGH_VALUE": { + "sonic-pfcwd:sonic-pfcwd": { + "sonic-pfcwd:PFC_WD": { + "PFC_WD_LIST": [ + { + "ifname": "Ethernet4", + "action": "wrong", + "detection_time": 5001, + "restoration_time": 3000 + } + ] + } + } + }, + "PFC_WDOG_WITH_WRONG_RESTORATION_TIME_LOW_VALUE": { + "sonic-pfcwd:sonic-pfcwd": { + "sonic-pfcwd:PFC_WD": { + "PFC_WD_LIST": [ + { + "ifname": "Ethernet4", + "action": "drop", + "detection_time": 99, + "restoration_time": 3000 + } + ] + } + } + }, + "PFC_WDOG_WITH_WRONG_RESTORATION_TIME_HIGH_VALUE": { + "sonic-pfcwd:sonic-pfcwd": { + "sonic-pfcwd:PFC_WD": { + "PFC_WD_LIST": [ + { + "ifname": "Ethernet4", + "action": "wrong", + "detection_time": 60001, + "restoration_time": 3000 + } + ] + } + } + } +} diff --git a/src/sonic-yang-models/yang-models/sonic-pfcwd.yang b/src/sonic-yang-models/yang-models/sonic-pfcwd.yang new file mode 100644 index 000000000000..beebf51965df --- /dev/null +++ b/src/sonic-yang-models/yang-models/sonic-pfcwd.yang @@ -0,0 +1,79 @@ +module sonic-pfcwd { + namespace "http://github.com/Azure/sonic-pfcwd"; + prefix sonic-pfcwd; + + yang-version 1.1; + + import sonic-port { + prefix port; + } + + organization + "SONiC"; + + contact + "SONiC"; + + description + "SONIC PFC Watchdog parameters"; + + revision 2021-07-01 { + description + "Initial revision."; + } + + container sonic-pfcwd { + container PFC_WD { + list PFC_WD_LIST { + key "ifname"; + leaf ifname { + type union { + type leafref { + path "/port:sonic-port/port:PORT/port:PORT_LIST/port:name"; + } + type string { + pattern "GLOBAL" { + error-message "Invalid interface name"; + error-app-tag interface-name-invalid; + } + } + } + } + leaf action { + must "../ifname != 'GLOBAL'"; + type enumeration { + enum drop; + enum forward; + enum alert; + } + description + "PFC watchdog action when entering storm state."; + } + leaf detection_time { + must "../ifname != 'GLOBAL'"; + type uint32 { + range 100..5000; + } + description + "Detection interval for pause storm in msec."; + } + leaf restoration_time { + must "../ifname != 'GLOBAL'"; + type uint32 { + range 100..60000; + } + description + "Time delay before resuming normal PFC operation in msec."; + } + leaf POLL_INTERVAL { + must "../ifname = 'GLOBAL'"; + type uint32 { + range 100..3000; + } + description + "PFC watchdog global polling interval in msec."; + } + } + } + } +} From 34dddb8ce429ca4abb37641c8934138725df2da6 Mon Sep 17 00:00:00 2001 From: Sumukha Tumkur Vani Date: Tue, 21 Sep 2021 10:13:48 -0700 Subject: [PATCH 27/34] [RESTAPI] Update submodule Commits included: 1. Update API description for default vrf and ecmp routes fad87fa20f6b15e28c90e02a131c44d236d6a751 2. Fix WS-2018-0594 potential non-random UUIDs security issue 8d4fd4a56b637d3b7403c321aef36b8dff58cd62 3. Add BFD config to subinterface and neighbor d3e8b8e4aee278fa11d7d86acabdab3fffc70d5a 4. Default Vrf static route support 6cfc8fe110c46a1ee5a8430e02a440b5a7b4006d 5. Added flag to make go/pkg/ folder writable (removable) ee887c785c10d8b4f70db90ca50cc398327c5d73 --- src/sonic-restapi | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/sonic-restapi b/src/sonic-restapi index 8d09602a9e3c..ee887c785c10 160000 --- a/src/sonic-restapi +++ b/src/sonic-restapi @@ -1 +1 @@ -Subproject commit 8d09602a9e3c762f86992d8eaf642e7115c5318b +Subproject commit ee887c785c10d8b4f70db90ca50cc398327c5d73 From 4da623c3f2ec0acfaaf7a760a72fab3e1d8657d1 Mon Sep 17 00:00:00 2001 From: Junhua Zhai Date: Wed, 22 Sep 2021 10:50:08 +0800 Subject: [PATCH 28/34] [docker-sonic-vs] always use separator ':' for GB_ASIC_DB, like ASIC_DB (#8806) --- platform/vs/docker-sonic-vs/database_config.json | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/platform/vs/docker-sonic-vs/database_config.json b/platform/vs/docker-sonic-vs/database_config.json index 953c23f22710..fb15299e9002 100644 --- a/platform/vs/docker-sonic-vs/database_config.json +++ b/platform/vs/docker-sonic-vs/database_config.json @@ -60,17 +60,17 @@ }, "GB_ASIC_DB" : { "id" : 8, - "separator": "|", + "separator": ":", "instance" : "redis" }, "GB_COUNTERS_DB" : { "id" : 9, - "separator": "|", + "separator": ":", "instance" : "redis" }, "GB_FLEX_COUNTER_DB" : { "id" : 10, - "separator": "|", + "separator": ":", "instance" : "redis" }, "CHASSIS_APP_DB" : { From bc06c6fcb5c7af4638ba767d862a1f953591f6cf Mon Sep 17 00:00:00 2001 From: kellyyeh <42761586+kellyyeh@users.noreply.github.com> Date: Wed, 22 Sep 2021 16:05:03 -0700 Subject: [PATCH 29/34] Incorporate DHCPv6 Relay Agent into dhcp-relay docker (#8321) --- dockers/docker-dhcp-relay/critical_processes | 2 +- .../docker-dhcp-relay/dhcp-relay.programs.j2 | 4 +- .../docker-dhcp-relay/dhcpv6-relay.agents.j2 | 19 +------ .../dhcpv6-relay.monitors.j2 | 2 +- rules/dhcp6relay.dep | 9 ++++ rules/dhcp6relay.mk | 10 ++++ rules/docker-dhcp-relay.mk | 2 +- src/dhcp6relay/src/configInterface.cpp | 16 +++--- src/dhcp6relay/src/configInterface.h | 8 +-- src/dhcp6relay/src/main.cpp | 2 +- src/dhcp6relay/src/relay.cpp | 51 +++++++++++-------- src/dhcp6relay/src/relay.h | 9 ++-- .../py2/docker-dhcp-relay.supervisord.conf | 11 ++-- .../py3/docker-dhcp-relay.supervisord.conf | 11 ++-- 14 files changed, 83 insertions(+), 73 deletions(-) create mode 100644 rules/dhcp6relay.dep create mode 100644 rules/dhcp6relay.mk diff --git a/dockers/docker-dhcp-relay/critical_processes b/dockers/docker-dhcp-relay/critical_processes index 855851bf2d68..43bf6af2794f 100644 --- a/dockers/docker-dhcp-relay/critical_processes +++ b/dockers/docker-dhcp-relay/critical_processes @@ -1 +1 @@ -group:isc-dhcp-relay +group:dhcp-relay diff --git a/dockers/docker-dhcp-relay/dhcp-relay.programs.j2 b/dockers/docker-dhcp-relay/dhcp-relay.programs.j2 index d6c0d805a4cc..9cb0c03876d6 100644 --- a/dockers/docker-dhcp-relay/dhcp-relay.programs.j2 +++ b/dockers/docker-dhcp-relay/dhcp-relay.programs.j2 @@ -1,4 +1,4 @@ -[group:isc-dhcp-relay] +[group:dhcp-relay] programs= {%- set add_preceding_comma = { 'flag': False } %} {% for vlan_name in VLAN_INTERFACE %} @@ -12,6 +12,6 @@ isc-dhcpv4-relay-{{ vlan_name }} {% if VLAN and vlan_name in VLAN and 'dhcpv6_servers' in VLAN[vlan_name] and VLAN[vlan_name]['dhcpv6_servers']|length > 0 %} {% if add_preceding_comma.flag %},{% endif %} {% set _dummy = add_preceding_comma.update({'flag': True}) %} -isc-dhcpv6-relay-{{ vlan_name }} +dhcp6relay {%- endif %} {% endfor %} diff --git a/dockers/docker-dhcp-relay/dhcpv6-relay.agents.j2 b/dockers/docker-dhcp-relay/dhcpv6-relay.agents.j2 index 2d95b383c093..218c95320edc 100644 --- a/dockers/docker-dhcp-relay/dhcpv6-relay.agents.j2 +++ b/dockers/docker-dhcp-relay/dhcpv6-relay.agents.j2 @@ -7,23 +7,8 @@ {% endfor %} {% if relay_for_ipv6.flag %} {% set _dummy = relay_for_ipv6.update({'flag': False}) %} -[program:isc-dhcpv6-relay-{{ vlan_name }}] -{# We treat this VLAN as a downstream interface (-l), as we only want to listen for requests #} -command=/usr/sbin/dhcrelay -d -6 --name-alias-map-file /tmp/port-name-alias-map.txt -l {{ vlan_name }} -{#- We treat all other interfaces as upstream interfaces (-u), as we only want to listen for replies #} -{%- for dhcpv6_server in VLAN[vlan_name]['dhcpv6_servers'] %} -{%- if dhcpv6_server | ipv6 %} -{%- for (name, prefix) in VLAN_INTERFACE|pfx_filter %} -{%- if prefix | ipv6 and name != vlan_name %} -u {{ dhcpv6_server }}%%{{ name }} {% endif -%} -{% endfor %} -{% for (name, prefix) in INTERFACE|pfx_filter %} -{% if prefix | ipv6 %} -u {{ dhcpv6_server }}%%{{ name }} {% endif -%} -{% endfor %} -{% for (name, prefix) in PORTCHANNEL_INTERFACE|pfx_filter %} -{% if prefix | ipv6 %} -u {{ dhcpv6_server }}%%{{ name }} {% endif -%} -{% endfor %} -{% endif -%} -{% endfor %} +[program:dhcp6relay] +command=/usr/sbin/dhcp6relay priority=3 autostart=false diff --git a/dockers/docker-dhcp-relay/dhcpv6-relay.monitors.j2 b/dockers/docker-dhcp-relay/dhcpv6-relay.monitors.j2 index 8bb9e5ad8136..9f2d0f01b59f 100644 --- a/dockers/docker-dhcp-relay/dhcpv6-relay.monitors.j2 +++ b/dockers/docker-dhcp-relay/dhcpv6-relay.monitors.j2 @@ -70,7 +70,7 @@ stderr_logfile=syslog dependent_startup=true dependent_startup_wait_for= {%- if relay_for_ipv4.flag %}isc-dhcpv4-relay-{{ vlan_name }}:running {% endif %} -{% if relay_for_ipv6.flag %}isc-dhcpv6-relay-{{ vlan_name }}:running{% endif %} +{% if relay_for_ipv6.flag %}dhcp6relay:running{% endif %} {% set _dummy = relay_for_ipv4.update({'flag': False}) %} diff --git a/rules/dhcp6relay.dep b/rules/dhcp6relay.dep new file mode 100644 index 000000000000..be82d326fe21 --- /dev/null +++ b/rules/dhcp6relay.dep @@ -0,0 +1,9 @@ + +SPATH := $($(SONIC_DHCP6RELAY)_SRC_PATH) +DEP_FILES := $(SONIC_COMMON_FILES_LIST) rules/dhcp6relay.mk rules/dhcp6relay.dep +DEP_FILES += $(SONIC_COMMON_BASE_FILES_LIST) +DEP_FILES += $(shell git ls-files $(SPATH)) + +$(SONIC_DHCP6RELAY)_CACHE_MODE := GIT_CONTENT_SHA +$(SONIC_DHCP6RELAY)_DEP_FLAGS := $(SONIC_COMMON_FLAGS_LIST) +$(SONIC_DHCP6RELAY)_DEP_FILES := $(DEP_FILES) diff --git a/rules/dhcp6relay.mk b/rules/dhcp6relay.mk new file mode 100644 index 000000000000..d9ff506d8a27 --- /dev/null +++ b/rules/dhcp6relay.mk @@ -0,0 +1,10 @@ +# SONiC DHCPV6 RELAY Package + +SONIC_DHCP6RELAY_VERSION = 1.0.0-0 +SONIC_DHCP6RELAY_PKG_NAME = dhcp6relay + +SONIC_DHCP6RELAY = sonic-$(SONIC_DHCP6RELAY_PKG_NAME)_$(SONIC_DHCP6RELAY_VERSION)_$(CONFIGURED_ARCH).deb +$(SONIC_DHCP6RELAY)_DEPENDS = $(LIBSWSSCOMMON) $(LIBHIREDIS) $(LIBSWSSCOMMON_DEV) $(LIBHIREDIS_DEV) +$(DOCKER_DHCP_RELAY)_INSTALL_DEBS = $(LIBSWSSCOMMON) $(LIBHIREDIS) $(LIBSWSSCOMMON_DEV) $(LIBHIREDIS_DEV) +$(SONIC_DHCP6RELAY)_SRC_PATH = $(SRC_PATH)/$(SONIC_DHCP6RELAY_PKG_NAME) +SONIC_DPKG_DEBS += $(SONIC_DHCP6RELAY) diff --git a/rules/docker-dhcp-relay.mk b/rules/docker-dhcp-relay.mk index a8b33c5bc74c..c3232e6da27a 100644 --- a/rules/docker-dhcp-relay.mk +++ b/rules/docker-dhcp-relay.mk @@ -6,7 +6,7 @@ DOCKER_DHCP_RELAY_DBG = $(DOCKER_DHCP_RELAY_STEM)-$(DBG_IMAGE_MARK).gz $(DOCKER_DHCP_RELAY)_PATH = $(DOCKERS_PATH)/$(DOCKER_DHCP_RELAY_STEM) -$(DOCKER_DHCP_RELAY)_DEPENDS += $(ISC_DHCP_RELAY) $(SONIC_DHCPMON) +$(DOCKER_DHCP_RELAY)_DEPENDS += $(ISC_DHCP_RELAY) $(SONIC_DHCPMON) $(SONIC_DHCP6RELAY) $(LIBSWSSCOMMON) $(DOCKER_DHCP_RELAY)_DBG_DEPENDS = $($(DOCKER_CONFIG_ENGINE_BUSTER)_DBG_DEPENDS) $(DOCKER_DHCP_RELAY)_DBG_DEPENDS += $(ISC_DHCP_RELAY_DBG) diff --git a/src/dhcp6relay/src/configInterface.cpp b/src/dhcp6relay/src/configInterface.cpp index db2c67656a76..0af4f49a285f 100644 --- a/src/dhcp6relay/src/configInterface.cpp +++ b/src/dhcp6relay/src/configInterface.cpp @@ -13,13 +13,13 @@ swss::SubscriberStateTable ipHelpersTable(configDbPtr.get(), "DHCP_RELAY"); swss::Select swssSelect; /** - * @code void deinitialize_swss() + * @code void initialize_swss() * * @brief initialize DB tables and start SWSS listening thread * * @return none */ -void initialize_swss(std::vector *vlans, swss::DBConnector *db) +void initialize_swss(std::vector *vlans) { try { swssSelect.addSelectable(&ipHelpersTable); @@ -85,7 +85,7 @@ void handleSwssNotification(std::vector *vlans) * @brief handles DHCPv6 relay configuration change notification * * @param ipHelpersTable DHCP table - * @param context list of vlans/argument config that contains strings of server and option + * @param vlans list of vlans/argument config that contains strings of server and option * * @return none */ @@ -103,7 +103,7 @@ void handleRelayNotification(swss::SubscriberStateTable &ipHelpersTable, std::ve * @brief process DHCPv6 relay servers and options configuration change notification * * @param entries queue of std::tuple> entries in DHCP table - * @param context list of vlans/argument config that contains strings of server and option + * @param vlans list of vlans/argument config that contains strings of server and option * * @return none */ @@ -117,6 +117,7 @@ void processRelayNotification(std::deque &entries, std::vector fieldValues = kfvFieldsValues(entry); relay_config intf; + intf.is_option_79 = true; intf.interface = vlan; for (auto &fieldValue: fieldValues) { std::string f = fvField(fieldValue); @@ -130,11 +131,8 @@ void processRelayNotification(std::deque &entries, } syslog(LOG_DEBUG, "key: %s, Operation: %s, f: %s, v: %s", vlan.c_str(), operation.c_str(), f.c_str(), v.c_str()); } - if(f == "dhcpv6_option|rfc6939_support") { - if(v == "true") - intf.is_option_79 = true; - else if(v == "false") - intf.is_option_79 = false; + if(f == "dhcpv6_option|rfc6939_support" && v == "false") { + intf.is_option_79 = false; } } vlans->push_back(intf); diff --git a/src/dhcp6relay/src/configInterface.h b/src/dhcp6relay/src/configInterface.h index dfd5eb668e0e..20b0912c5cef 100644 --- a/src/dhcp6relay/src/configInterface.h +++ b/src/dhcp6relay/src/configInterface.h @@ -4,13 +4,13 @@ #include "relay.h" /** - * @code void deinitialize_swss() + * @code void initialize_swss() * * @brief initialize DB tables and start SWSS listening thread * * @return none */ -void initialize_swss(std::vector *vlans, swss::DBConnector *db); +void initialize_swss(std::vector *vlans); /** * @code void deinitialize_swss() @@ -35,7 +35,7 @@ void get_dhcp(std::vector *vlans); * * @brief main thread for handling SWSS notification * - * @param context list of vlans/argument config that contains strings of server and option + * @param vlans list of vlans/argument config that contains strings of server and option * * @return none */ @@ -47,7 +47,7 @@ void handleSwssNotification(std::vector *vlans); * @brief handles DHCPv6 relay configuration change notification * * @param ipHelpersTable DHCP table - * @param context list of vlans/argument config that contains strings of server and option + * @param vlans list of vlans/argument config that contains strings of server and option * * @return none */ diff --git a/src/dhcp6relay/src/main.cpp b/src/dhcp6relay/src/main.cpp index 860e4d1346d8..9f5bc74bcfa0 100644 --- a/src/dhcp6relay/src/main.cpp +++ b/src/dhcp6relay/src/main.cpp @@ -6,7 +6,7 @@ int main(int argc, char *argv[]) { try { std::vector vlans; swss::DBConnector state_db("STATE_DB", 0); - initialize_swss(&vlans, &state_db); + initialize_swss(&vlans); loop_relay(&vlans, &state_db); } catch (std::exception &e) diff --git a/src/dhcp6relay/src/relay.cpp b/src/dhcp6relay/src/relay.cpp index d9c7114a7937..e2eb8e4fac12 100644 --- a/src/dhcp6relay/src/relay.cpp +++ b/src/dhcp6relay/src/relay.cpp @@ -18,6 +18,7 @@ struct event *server_listen_event; struct event_base *base; struct event *ev_sigint; struct event *ev_sigterm; +static std::string counter_table = "DHCPv6_COUNTER_TABLE|"; /* DHCPv6 filter */ /* sudo tcpdump -dd "ip6 dst ff02::1:2 && udp dst port 547" */ @@ -325,12 +326,12 @@ int sock_open(int ifindex, const struct sock_fprog *fprog) * * @return none */ -void prepare_relay_config(relay_config *interface_config, int local_sock, int filter) { +void prepare_relay_config(relay_config *interface_config, int *local_sock, int filter) { struct ifaddrs *ifa, *ifa_tmp; sockaddr_in6 non_link_local; sockaddr_in6 link_local; - interface_config->local_sock = local_sock; + interface_config->local_sock = *local_sock; interface_config->filter = filter; for(auto server: interface_config->servers) { @@ -376,22 +377,20 @@ void prepare_relay_config(relay_config *interface_config, int local_sock, int fi } /** - * @code prepare_socket(int *local_sock, relay_config *config); + * @code prepare_socket(int *local_sock); * * @brief prepare L3 socket for sending * * @param local_sock pointer to socket to be prepared - * @param config relay config that contains strings of server and interface addresses * * @return none */ -void prepare_socket(int *local_sock, relay_config *config, int index) { +void prepare_socket(int *local_sock) { int flag = 1; sockaddr_in6 addr; memset(&addr, 0, sizeof(addr)); addr.sin6_family = AF_INET6; addr.sin6_addr = in6addr_any; - addr.sin6_scope_id = index; addr.sin6_port = htons(RELAY_PORT); if ((*local_sock = socket(AF_INET6, SOCK_DGRAM, 0)) == -1) { @@ -434,11 +433,6 @@ void relay_client(int sock, const uint8_t *msg, int32_t len, const ip6_hdr *ip_h memcpy(current_buffer_position, &new_message, sizeof(dhcpv6_relay_msg)); current_buffer_position += sizeof(dhcpv6_relay_msg); - - auto dhcp_message_length = len; - relay_forward(current_buffer_position, parse_dhcpv6_hdr(msg), dhcp_message_length); - current_buffer_position += dhcp_message_length + sizeof(dhcpv6_option); - if(config->is_option_79) { linklayer_addr_option option79; option79.link_layer_type = htons(1); @@ -447,10 +441,14 @@ void relay_client(int sock, const uint8_t *msg, int32_t len, const ip6_hdr *ip_h memcpy(current_buffer_position, &option79, sizeof(linklayer_addr_option)); current_buffer_position += sizeof(linklayer_addr_option); + + memcpy(current_buffer_position, ðer_hdr->ether_shost, sizeof(ether_hdr->ether_shost)); + current_buffer_position += sizeof(ether_hdr->ether_shost); } - memcpy(current_buffer_position, ðer_hdr->ether_shost, sizeof(ether_hdr->ether_shost)); - current_buffer_position += sizeof(ether_hdr->ether_shost); + auto dhcp_message_length = len; + relay_forward(current_buffer_position, parse_dhcpv6_hdr(msg), dhcp_message_length); + current_buffer_position += dhcp_message_length + sizeof(dhcpv6_option); for(auto server: config->servers_sock) { send_udp(sock, buffer, server, current_buffer_position - buffer); @@ -546,11 +544,23 @@ void callback(evutil_socket_t fd, short event, void *arg) { auto msg = parse_dhcpv6_hdr(current_position); counters[msg->msg_type]++; - update_counter(config->db, config->counterVlan, msg->msg_type); + std::string counterVlan = counter_table; + update_counter(config->db, counterVlan.append(config->interface), msg->msg_type); relay_client(config->local_sock, current_position, ntohs(udp_header->len) - sizeof(udphdr), ip_header, ether_header, config); } +/** + * @code void server_callback(evutil_socket_t fd, short event, void *arg); + * + * @brief callback for libevent that is called everytime data is received at the server socket + * + * @param fd filter socket + * @param event libevent triggered event + * @param arg callback argument provided by user + * + * @return none + */ void server_callback(evutil_socket_t fd, short event, void *arg) { struct relay_config *config = (struct relay_config *)arg; sockaddr_in6 from; @@ -563,9 +573,9 @@ void server_callback(evutil_socket_t fd, short event, void *arg) { } auto msg = parse_dhcpv6_hdr(message_buffer); - counters[msg->msg_type]++; - update_counter(config->db, config->counterVlan, msg->msg_type); + std::string counterVlan = counter_table; + update_counter(config->db, counterVlan.append(config->interface), msg->msg_type); if (msg->msg_type == DHCPv6_MESSAGE_TYPE_RELAY_REPL) { relay_relay_reply(config->local_sock, message_buffer, data, config); } @@ -673,17 +683,16 @@ void loop_relay(std::vector *vlans, swss::DBConnector *db) { int index = if_nametoindex(ifname); config.db = db; - config.counterVlan = "DHCPv6_COUNTER_TABLE|"; - config.counterVlan.append(ifname); - initialize_counter(config.db, config.counterVlan); + std::string counterVlan = counter_table; + initialize_counter(config.db, counterVlan.append(config.interface)); filter = sock_open(index, ðer_relay_fprog); - prepare_socket(&local_sock, &config, index); + prepare_socket(&local_sock); sockets.push_back(filter); sockets.push_back(local_sock); - prepare_relay_config(&config, local_sock, filter); + prepare_relay_config(&config, &local_sock, filter); evutil_make_listen_socket_reuseable(filter); evutil_make_socket_nonblocking(filter); diff --git a/src/dhcp6relay/src/relay.h b/src/dhcp6relay/src/relay.h index eb97f06cd690..ddd63559c66b 100644 --- a/src/dhcp6relay/src/relay.h +++ b/src/dhcp6relay/src/relay.h @@ -49,7 +49,6 @@ struct relay_config { std::vector servers; std::vector servers_sock; bool is_option_79; - std::string counterVlan; }; @@ -91,17 +90,15 @@ struct linklayer_addr_option { int sock_open(int ifindex, const struct sock_fprog *fprog); /** - * @code prepare_socket(int *local_sock, arg_config *config); + * @code prepare_socket(int *local_sock); * * @brief prepare L3 socket for sending * * @param local_sock pointer to socket to be prepared - * @param config argument config that contains strings of server and interface addresses - * @param index interface id * * @return none */ -void prepare_socket(int *local_sock, relay_config *config, int index); +void prepare_socket(int *local_sock); /** * @code prepare_relay_config(relay_config *interface_config, int local_sock, int filter); @@ -114,7 +111,7 @@ void prepare_socket(int *local_sock, relay_config *config, int index); * * @return none */ -void prepare_relay_config(relay_config *interface_config, int local_sock, int filter); +void prepare_relay_config(relay_config *interface_config, int *local_sock, int filter); /** * @code relay_forward(uint8_t *buffer, const struct dhcpv6_msg *msg, uint16_t msg_length); diff --git a/src/sonic-config-engine/tests/sample_output/py2/docker-dhcp-relay.supervisord.conf b/src/sonic-config-engine/tests/sample_output/py2/docker-dhcp-relay.supervisord.conf index 35dfe5ea4b5d..a9004e2b00f5 100644 --- a/src/sonic-config-engine/tests/sample_output/py2/docker-dhcp-relay.supervisord.conf +++ b/src/sonic-config-engine/tests/sample_output/py2/docker-dhcp-relay.supervisord.conf @@ -39,8 +39,8 @@ stderr_logfile=syslog dependent_startup=true dependent_startup_wait_for=rsyslogd:running -[group:isc-dhcp-relay] -programs=isc-dhcpv4-relay-Vlan1000,isc-dhcpv6-relay-Vlan1000 +[group:dhcp-relay] +programs=isc-dhcpv4-relay-Vlan1000,dhcp6relay [program:isc-dhcpv4-relay-Vlan1000] command=/usr/sbin/dhcrelay -d -m discard -a %%h:%%p %%P --name-alias-map-file /tmp/port-name-alias-map.txt -id Vlan1000 -iu Vlan2000 -iu PortChannel02 -iu PortChannel03 -iu PortChannel04 -iu PortChannel01 192.0.0.1 192.0.0.2 @@ -52,8 +52,9 @@ stderr_logfile=syslog dependent_startup=true dependent_startup_wait_for=start:exited -[program:isc-dhcpv6-relay-Vlan1000] -command=/usr/sbin/dhcrelay -d -6 --name-alias-map-file /tmp/port-name-alias-map.txt -l Vlan1000 -u fc02:2000::1%%PortChannel04 -u fc02:2000::1%%PortChannel03 -u fc02:2000::1%%PortChannel01 -u fc02:2000::1%%PortChannel02 -u fc02:2000::2%%PortChannel04 -u fc02:2000::2%%PortChannel03 -u fc02:2000::2%%PortChannel01 -u fc02:2000::2%%PortChannel02 +[program:dhcp6relay] +command=/usr/sbin/dhcp6relay + priority=3 autostart=false autorestart=false @@ -74,6 +75,6 @@ autorestart=false stdout_logfile=syslog stderr_logfile=syslog dependent_startup=true -dependent_startup_wait_for=isc-dhcpv4-relay-Vlan1000:running isc-dhcpv6-relay-Vlan1000:running +dependent_startup_wait_for=isc-dhcpv4-relay-Vlan1000:running dhcp6relay:running diff --git a/src/sonic-config-engine/tests/sample_output/py3/docker-dhcp-relay.supervisord.conf b/src/sonic-config-engine/tests/sample_output/py3/docker-dhcp-relay.supervisord.conf index bc24433a14cf..521899b939f4 100644 --- a/src/sonic-config-engine/tests/sample_output/py3/docker-dhcp-relay.supervisord.conf +++ b/src/sonic-config-engine/tests/sample_output/py3/docker-dhcp-relay.supervisord.conf @@ -39,8 +39,8 @@ stderr_logfile=syslog dependent_startup=true dependent_startup_wait_for=rsyslogd:running -[group:isc-dhcp-relay] -programs=isc-dhcpv4-relay-Vlan1000,isc-dhcpv6-relay-Vlan1000 +[group:dhcp-relay] +programs=isc-dhcpv4-relay-Vlan1000,dhcp6relay [program:isc-dhcpv4-relay-Vlan1000] command=/usr/sbin/dhcrelay -d -m discard -a %%h:%%p %%P --name-alias-map-file /tmp/port-name-alias-map.txt -id Vlan1000 -iu Vlan2000 -iu PortChannel01 -iu PortChannel02 -iu PortChannel03 -iu PortChannel04 192.0.0.1 192.0.0.2 @@ -52,8 +52,9 @@ stderr_logfile=syslog dependent_startup=true dependent_startup_wait_for=start:exited -[program:isc-dhcpv6-relay-Vlan1000] -command=/usr/sbin/dhcrelay -d -6 --name-alias-map-file /tmp/port-name-alias-map.txt -l Vlan1000 -u fc02:2000::1%%PortChannel01 -u fc02:2000::1%%PortChannel02 -u fc02:2000::1%%PortChannel03 -u fc02:2000::1%%PortChannel04 -u fc02:2000::2%%PortChannel01 -u fc02:2000::2%%PortChannel02 -u fc02:2000::2%%PortChannel03 -u fc02:2000::2%%PortChannel04 +[program:dhcp6relay] +command=/usr/sbin/dhcp6relay + priority=3 autostart=false autorestart=false @@ -74,6 +75,6 @@ autorestart=false stdout_logfile=syslog stderr_logfile=syslog dependent_startup=true -dependent_startup_wait_for=isc-dhcpv4-relay-Vlan1000:running isc-dhcpv6-relay-Vlan1000:running +dependent_startup_wait_for=isc-dhcpv4-relay-Vlan1000:running dhcp6relay:running From 1d7e82b96d084485e4f95f40608bc6d4abd93930 Mon Sep 17 00:00:00 2001 From: bingwang-ms <66248323+bingwang-ms@users.noreply.github.com> Date: Thu, 23 Sep 2021 01:18:56 -0700 Subject: [PATCH 30/34] Update minigraph parser to support type MIRROR_DSCP (#8819) * Update minigraph parser to support MIRROR_DSCP Signed-off-by: bingwang --- src/sonic-config-engine/minigraph.py | 13 +++++++++---- .../tests/simple-sample-graph-case.xml | 5 +++++ .../tests/test_minigraph_case.py | 14 ++++++++++++++ 3 files changed, 28 insertions(+), 4 deletions(-) diff --git a/src/sonic-config-engine/minigraph.py b/src/sonic-config-engine/minigraph.py index 756743f85e67..1963c3716851 100644 --- a/src/sonic-config-engine/minigraph.py +++ b/src/sonic-config-engine/minigraph.py @@ -596,6 +596,7 @@ def parse_dpg(dpg, hname): acl_intfs = [] is_mirror = False is_mirror_v6 = False + is_mirror_dscp = False # TODO: Ensure that acl_intfs will only ever contain front-panel interfaces (e.g., # maybe we should explicity ignore management and loopback interfaces?) because we @@ -618,8 +619,10 @@ def parse_dpg(dpg, hname): # Give a warning if trying to attach ACL to a LAG member interface, correct way is to attach ACL to the LAG interface if port_alias_map[member] in intfs_inpc: print("Warning: ACL " + aclname + " is attached to a LAG member interface " + port_alias_map[member] + ", instead of LAG interface", file=sys.stderr) - elif member.lower().startswith('erspan') or member.lower().startswith('egress_erspan'): - if member.lower().startswith('erspanv6') or member.lower().startswith('egress_erspanv6'): + elif member.lower().startswith('erspan') or member.lower().startswith('egress_erspan') or member.lower().startswith('erspan_dscp'): + if 'dscp' in member.lower(): + is_mirror_dscp = True + elif member.lower().startswith('erspanv6') or member.lower().startswith('egress_erspanv6'): is_mirror_v6 = True else: is_mirror = True @@ -639,7 +642,7 @@ def parse_dpg(dpg, hname): # are binded then do not classify as Control plane. # For multi-asic platforms it's possible there is no # interface are binded to everflow in host namespace. - if acl_intfs or is_mirror_v6 or is_mirror: + if acl_intfs or is_mirror_v6 or is_mirror or is_mirror_dscp: # Remove duplications dedup_intfs = [] for intf in acl_intfs: @@ -653,6 +656,8 @@ def parse_dpg(dpg, hname): acls[aclname]['type'] = 'MIRROR' elif is_mirror_v6: acls[aclname]['type'] = 'MIRRORV6' + elif is_mirror_dscp: + acls[aclname]['type'] = 'MIRROR_DSCP' else: acls[aclname]['type'] = 'L3V6' if 'v6' in aclname.lower() else 'L3' else: @@ -1088,7 +1093,7 @@ def filter_acl_table_bindings(acls, neighbors, port_channels, sub_role): # Control Plane ACL has no Interface associated and # Data Plane ACL Interface are attached via minigraph # AclInterface. - if group_type != 'MIRROR' and group_type != 'MIRRORV6': + if group_type != 'MIRROR' and group_type != 'MIRRORV6' and group_type != 'MIRROR_DSCP': continue # Filters out back-panel ports from the binding list for Everflow (Mirror) diff --git a/src/sonic-config-engine/tests/simple-sample-graph-case.xml b/src/sonic-config-engine/tests/simple-sample-graph-case.xml index 78e81bd6df78..acaab2c4c7e3 100644 --- a/src/sonic-config-engine/tests/simple-sample-graph-case.xml +++ b/src/sonic-config-engine/tests/simple-sample-graph-case.xml @@ -189,6 +189,11 @@ SNMP_ACL SNMP + + ERSPAN_DSCP + Everflow_dscp + Everflow_dscp + diff --git a/src/sonic-config-engine/tests/test_minigraph_case.py b/src/sonic-config-engine/tests/test_minigraph_case.py index 0f736998ddeb..4ebff7f78c6c 100644 --- a/src/sonic-config-engine/tests/test_minigraph_case.py +++ b/src/sonic-config-engine/tests/test_minigraph_case.py @@ -381,5 +381,19 @@ def test_dhcp_table(self): utils.to_dict(output.strip()), expected ) + + def test_minigraph_mirror_dscp(self): + result = minigraph.parse_xml(self.sample_graph, port_config_file=self.port_config) + self.assertTrue('EVERFLOW_DSCP' in result['ACL_TABLE']) + everflow_dscp_entry = result['ACL_TABLE']['EVERFLOW_DSCP'] + self.assertEqual(everflow_dscp_entry['type'], 'MIRROR_DSCP') + self.assertEqual(everflow_dscp_entry['stage'], 'ingress') + expected_ports = ['PortChannel01', 'Ethernet12', 'Ethernet8', 'Ethernet0'] + self.assertEqual( + everflow_dscp_entry['ports'].sort(), + expected_ports.sort() + ) + + From 31a647a72d0426d64e9694fdc8320531bd2a2f0b Mon Sep 17 00:00:00 2001 From: DINESH KUMAR SELLAPPAN <40899231+selldinesh@users.noreply.github.com> Date: Thu, 23 Sep 2021 02:12:12 -0700 Subject: [PATCH 31/34] [docker-sonic-mgmt]: Snappi version to 0.5.11 (#8790) --- dockers/docker-sonic-mgmt/Dockerfile.j2 | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) mode change 100644 => 100755 dockers/docker-sonic-mgmt/Dockerfile.j2 diff --git a/dockers/docker-sonic-mgmt/Dockerfile.j2 b/dockers/docker-sonic-mgmt/Dockerfile.j2 old mode 100644 new mode 100755 index 543e4df1f075..ccdcc168bef8 --- a/dockers/docker-sonic-mgmt/Dockerfile.j2 +++ b/dockers/docker-sonic-mgmt/Dockerfile.j2 @@ -42,7 +42,7 @@ RUN pip install cffi==1.10.0 \ ipython==5.4.1 \ ixnetwork-restpy==1.0.64 \ ixnetwork-open-traffic-generator==0.0.79 \ - snappi[ixnetwork]==0.3.13 \ + snappi[ixnetwork,convergence]==0.5.11 \ jinja2==2.7.2 \ jsonpatch \ lxml \ From 27aef5305417c4eb072174cbd27c5d6adcecccaf Mon Sep 17 00:00:00 2001 From: Junhua Zhai Date: Fri, 24 Sep 2021 10:25:27 +0800 Subject: [PATCH 32/34] [submodule] update sonic-swss-common to latest (#8828) The following fixes are included: b502743 [gearbox] Since ASIC_DB, as well its COUNTER_DB, FLEX_COUNTER_DB use separator ':', GB_ASIC_DB should use same ((Azure/sonic-swss-common#532) 81182ec Added support for setting TTL on a Table managed entry. ((Azure/sonic-swss-common#526) --- src/sonic-swss-common | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/sonic-swss-common b/src/sonic-swss-common index 4253aa6c20ea..b5027436c267 160000 --- a/src/sonic-swss-common +++ b/src/sonic-swss-common @@ -1 +1 @@ -Subproject commit 4253aa6c20ea2dbf03fd705d601a5ef789ab20e4 +Subproject commit b5027436c267638709d4f9a1be4b5a2d07c94893 From 8325500560db6cdde2d63646c10e1f2644f94101 Mon Sep 17 00:00:00 2001 From: arunlk-dell <83708154+arunlk-dell@users.noreply.github.com> Date: Fri, 24 Sep 2021 09:17:32 +0530 Subject: [PATCH 33/34] DellEMC: N3248TE Initial platform commit (#8809) Why I did it Added support for the device N3248TE How I did it Implemented the support for the platform N3248TE Switch Vendor: DellEMC Switch SKU: N3248TE ASIC Vendor: Broadcom SONiC Image: sonic-broadcom.bin How to verify it Verified the show platform commands --- .../DellEMC-N3248TE/buffers.json.j2 | 2 + .../DellEMC-N3248TE/buffers_defaults_t0.j2 | 41 + .../DellEMC-N3248TE/buffers_defaults_t1.j2 | 41 + .../copp_capabilities_config.j2 | 3 + .../DellEMC-N3248TE/copp_platform_config.j2 | 145 ++ .../DellEMC-N3248TE/custom_led.bin | Bin 0 -> 606 bytes .../hx5-n3248te-48x1G+4x10G.config.bcm | 260 ++++ .../DellEMC-N3248TE/linkscan_led_fw.bin | Bin 0 -> 6100 bytes .../DellEMC-N3248TE/pg_profile_lookup.ini | 17 + .../DellEMC-N3248TE/port_config.ini | 55 + .../DellEMC-N3248TE/qos.json.j2 | 1 + .../DellEMC-N3248TE/qos_config_t1.j2 | 175 +++ .../DellEMC-N3248TE/sai.profile | 1 + .../DellEMC-N3248TE/sai_preinit_cmd.soc | 2 + .../default_sku | 1 + .../init_cfg.json | 13 + .../installer.conf | 3 + .../led_proc_init.soc | 7 + .../plugins/eeprom.py | 22 + .../plugins/fanutil.py | 72 + .../plugins/pcie.yaml | 16 + .../plugins/psuutil.py | 191 +++ .../plugins/sfputil.py | 172 +++ .../pmon_daemon_control.json | 3 + .../sensors.conf | 58 + platform/broadcom/one-image.mk | 1 + platform/broadcom/platform-modules-dell.mk | 6 + .../debian/control | 5 + .../debian/platform-modules-n3248te.init | 39 + .../debian/platform-modules-n3248te.install | 12 + .../debian/platform-modules-n3248te.postinst | 7 + .../sonic-platform-modules-dell/debian/rules | 12 +- .../n3248te/cfg/n3248te-modules.conf | 14 + .../n3248te/modules/Makefile | 2 + .../n3248te/modules/dell_n3248te_platform.c | 1236 +++++++++++++++++ .../n3248te/modules/emc2305.c | 877 ++++++++++++ .../n3248te/modules/pmbus.h | 425 ++++++ .../n3248te/scripts/fancontrol.sh | 78 ++ .../n3248te/scripts/n3248te_platform.sh | 143 ++ .../n3248te/scripts/platform_sensors.py | 136 ++ .../n3248te/scripts/portiocfg.py | 105 ++ .../n3248te/scripts/ports_xcvrd_notify.py | 107 ++ .../n3248te/scripts/sensors | 8 + .../n3248te/setup.py | 1 + .../n3248te/sonic_platform/__init__.py | 8 + .../n3248te/sonic_platform/chassis.py | 350 +++++ .../n3248te/sonic_platform/component.py | 82 ++ .../n3248te/sonic_platform/eeprom.py | 134 ++ .../n3248te/sonic_platform/fan.py | 169 +++ .../n3248te/sonic_platform/fan_drawer.py | 37 + .../n3248te/sonic_platform/platform.py | 24 + .../n3248te/sonic_platform/psu.py | 207 +++ .../n3248te/sonic_platform/sfp.py | 783 +++++++++++ .../n3248te/sonic_platform/thermal.py | 146 ++ .../n3248te/sonic_platform/watchdog.py | 210 +++ .../systemd/platform-modules-n3248te.service | 14 + src/sonic-device-data/tests/permitted_list | 4 + 57 files changed, 6682 insertions(+), 1 deletion(-) create mode 100644 device/dell/x86_64-dellemc_n3248te_c3338-r0/DellEMC-N3248TE/buffers.json.j2 create mode 100644 device/dell/x86_64-dellemc_n3248te_c3338-r0/DellEMC-N3248TE/buffers_defaults_t0.j2 create mode 100644 device/dell/x86_64-dellemc_n3248te_c3338-r0/DellEMC-N3248TE/buffers_defaults_t1.j2 create mode 100644 device/dell/x86_64-dellemc_n3248te_c3338-r0/DellEMC-N3248TE/copp_capabilities_config.j2 create mode 100644 device/dell/x86_64-dellemc_n3248te_c3338-r0/DellEMC-N3248TE/copp_platform_config.j2 create mode 100644 device/dell/x86_64-dellemc_n3248te_c3338-r0/DellEMC-N3248TE/custom_led.bin create mode 100644 device/dell/x86_64-dellemc_n3248te_c3338-r0/DellEMC-N3248TE/hx5-n3248te-48x1G+4x10G.config.bcm create mode 100644 device/dell/x86_64-dellemc_n3248te_c3338-r0/DellEMC-N3248TE/linkscan_led_fw.bin create mode 100644 device/dell/x86_64-dellemc_n3248te_c3338-r0/DellEMC-N3248TE/pg_profile_lookup.ini create mode 100644 device/dell/x86_64-dellemc_n3248te_c3338-r0/DellEMC-N3248TE/port_config.ini create mode 100644 device/dell/x86_64-dellemc_n3248te_c3338-r0/DellEMC-N3248TE/qos.json.j2 create mode 100644 device/dell/x86_64-dellemc_n3248te_c3338-r0/DellEMC-N3248TE/qos_config_t1.j2 create mode 100644 device/dell/x86_64-dellemc_n3248te_c3338-r0/DellEMC-N3248TE/sai.profile create mode 100644 device/dell/x86_64-dellemc_n3248te_c3338-r0/DellEMC-N3248TE/sai_preinit_cmd.soc create mode 100644 device/dell/x86_64-dellemc_n3248te_c3338-r0/default_sku create mode 100644 device/dell/x86_64-dellemc_n3248te_c3338-r0/init_cfg.json create mode 100644 device/dell/x86_64-dellemc_n3248te_c3338-r0/installer.conf create mode 100644 device/dell/x86_64-dellemc_n3248te_c3338-r0/led_proc_init.soc create mode 100644 device/dell/x86_64-dellemc_n3248te_c3338-r0/plugins/eeprom.py create mode 100644 device/dell/x86_64-dellemc_n3248te_c3338-r0/plugins/fanutil.py create mode 100644 device/dell/x86_64-dellemc_n3248te_c3338-r0/plugins/pcie.yaml create mode 100644 device/dell/x86_64-dellemc_n3248te_c3338-r0/plugins/psuutil.py create mode 100644 device/dell/x86_64-dellemc_n3248te_c3338-r0/plugins/sfputil.py create mode 100644 device/dell/x86_64-dellemc_n3248te_c3338-r0/pmon_daemon_control.json create mode 100644 device/dell/x86_64-dellemc_n3248te_c3338-r0/sensors.conf create mode 100755 platform/broadcom/sonic-platform-modules-dell/debian/platform-modules-n3248te.init create mode 100644 platform/broadcom/sonic-platform-modules-dell/debian/platform-modules-n3248te.install create mode 100644 platform/broadcom/sonic-platform-modules-dell/debian/platform-modules-n3248te.postinst create mode 100644 platform/broadcom/sonic-platform-modules-dell/n3248te/cfg/n3248te-modules.conf create mode 100644 platform/broadcom/sonic-platform-modules-dell/n3248te/modules/Makefile create mode 100644 platform/broadcom/sonic-platform-modules-dell/n3248te/modules/dell_n3248te_platform.c create mode 100644 platform/broadcom/sonic-platform-modules-dell/n3248te/modules/emc2305.c create mode 100644 platform/broadcom/sonic-platform-modules-dell/n3248te/modules/pmbus.h create mode 100755 platform/broadcom/sonic-platform-modules-dell/n3248te/scripts/fancontrol.sh create mode 100755 platform/broadcom/sonic-platform-modules-dell/n3248te/scripts/n3248te_platform.sh create mode 100755 platform/broadcom/sonic-platform-modules-dell/n3248te/scripts/platform_sensors.py create mode 100755 platform/broadcom/sonic-platform-modules-dell/n3248te/scripts/portiocfg.py create mode 100755 platform/broadcom/sonic-platform-modules-dell/n3248te/scripts/ports_xcvrd_notify.py create mode 100755 platform/broadcom/sonic-platform-modules-dell/n3248te/scripts/sensors create mode 120000 platform/broadcom/sonic-platform-modules-dell/n3248te/setup.py create mode 100644 platform/broadcom/sonic-platform-modules-dell/n3248te/sonic_platform/__init__.py create mode 100644 platform/broadcom/sonic-platform-modules-dell/n3248te/sonic_platform/chassis.py create mode 100644 platform/broadcom/sonic-platform-modules-dell/n3248te/sonic_platform/component.py create mode 100644 platform/broadcom/sonic-platform-modules-dell/n3248te/sonic_platform/eeprom.py create mode 100644 platform/broadcom/sonic-platform-modules-dell/n3248te/sonic_platform/fan.py create mode 100644 platform/broadcom/sonic-platform-modules-dell/n3248te/sonic_platform/fan_drawer.py create mode 100644 platform/broadcom/sonic-platform-modules-dell/n3248te/sonic_platform/platform.py create mode 100644 platform/broadcom/sonic-platform-modules-dell/n3248te/sonic_platform/psu.py create mode 100644 platform/broadcom/sonic-platform-modules-dell/n3248te/sonic_platform/sfp.py create mode 100644 platform/broadcom/sonic-platform-modules-dell/n3248te/sonic_platform/thermal.py create mode 100644 platform/broadcom/sonic-platform-modules-dell/n3248te/sonic_platform/watchdog.py create mode 100644 platform/broadcom/sonic-platform-modules-dell/n3248te/systemd/platform-modules-n3248te.service diff --git a/device/dell/x86_64-dellemc_n3248te_c3338-r0/DellEMC-N3248TE/buffers.json.j2 b/device/dell/x86_64-dellemc_n3248te_c3338-r0/DellEMC-N3248TE/buffers.json.j2 new file mode 100644 index 000000000000..1083a6210fc9 --- /dev/null +++ b/device/dell/x86_64-dellemc_n3248te_c3338-r0/DellEMC-N3248TE/buffers.json.j2 @@ -0,0 +1,2 @@ +{%- set default_topo = 't0' %} +{%- include 'buffers_config.j2' %} diff --git a/device/dell/x86_64-dellemc_n3248te_c3338-r0/DellEMC-N3248TE/buffers_defaults_t0.j2 b/device/dell/x86_64-dellemc_n3248te_c3338-r0/DellEMC-N3248TE/buffers_defaults_t0.j2 new file mode 100644 index 000000000000..bfd81d10049f --- /dev/null +++ b/device/dell/x86_64-dellemc_n3248te_c3338-r0/DellEMC-N3248TE/buffers_defaults_t0.j2 @@ -0,0 +1,41 @@ +{%- set default_cable = '5m' %} + +{%- macro generate_port_lists(PORT_ALL) %} + {# Generate list of ports #} + {% for port_idx in range(0,32) %} + {% if PORT_ALL.append("Ethernet%d" % (port_idx * 4)) %}{% endif %} + {% endfor %} +{%- endmacro %} + +{%- macro generate_buffer_pool_and_profiles() %} + "BUFFER_POOL": { + "ingress_lossless_pool": { + "size": "8192000", + "type": "ingress", + "mode": "dynamic", + "xoff": "196608" + }, + "egress_lossless_pool": { + "size": "8388608", + "type": "egress", + "mode": "static" + } + }, + "BUFFER_PROFILE": { + "ingress_lossy_profile": { + "pool":"[BUFFER_POOL|ingress_lossless_pool]", + "size":"0", + "dynamic_th":"3" + }, + "egress_lossless_profile": { + "pool":"[BUFFER_POOL|egress_lossless_pool]", + "size":"0", + "static_th":"8388608" + }, + "egress_lossy_profile": { + "pool":"[BUFFER_POOL|egress_lossless_pool]", + "size":"1518", + "dynamic_th":"3" + } + }, +{%- endmacro %} diff --git a/device/dell/x86_64-dellemc_n3248te_c3338-r0/DellEMC-N3248TE/buffers_defaults_t1.j2 b/device/dell/x86_64-dellemc_n3248te_c3338-r0/DellEMC-N3248TE/buffers_defaults_t1.j2 new file mode 100644 index 000000000000..3b9cd1f104d6 --- /dev/null +++ b/device/dell/x86_64-dellemc_n3248te_c3338-r0/DellEMC-N3248TE/buffers_defaults_t1.j2 @@ -0,0 +1,41 @@ +{%- set default_cable = '300m' %} + +{%- macro generate_port_lists(PORT_ALL) %} + {# Generate list of ports #} + {% for port_idx in range(0,32) %} + {% if PORT_ALL.append("Ethernet%d" % (port_idx * 4)) %}{% endif %} + {% endfor %} +{%- endmacro %} + +{%- macro generate_buffer_pool_and_profiles() %} + "BUFFER_POOL": { + "ingress_lossless_pool": { + "size": "8192000", + "type": "ingress", + "mode": "dynamic", + "xoff": "196608" + }, + "egress_lossless_pool": { + "size": "8388608", + "type": "egress", + "mode": "static" + } + }, + "BUFFER_PROFILE": { + "ingress_lossy_profile": { + "pool":"[BUFFER_POOL|ingress_lossless_pool]", + "size":"0", + "dynamic_th":"3" + }, + "egress_lossless_profile": { + "pool":"[BUFFER_POOL|egress_lossless_pool]", + "size":"0", + "static_th":"8388608" + }, + "egress_lossy_profile": { + "pool":"[BUFFER_POOL|egress_lossless_pool]", + "size":"1518", + "dynamic_th":"3" + } + }, +{%- endmacro %} diff --git a/device/dell/x86_64-dellemc_n3248te_c3338-r0/DellEMC-N3248TE/copp_capabilities_config.j2 b/device/dell/x86_64-dellemc_n3248te_c3338-r0/DellEMC-N3248TE/copp_capabilities_config.j2 new file mode 100644 index 000000000000..ba28f2410393 --- /dev/null +++ b/device/dell/x86_64-dellemc_n3248te_c3338-r0/DellEMC-N3248TE/copp_capabilities_config.j2 @@ -0,0 +1,3 @@ +{ + "copp_rx_rate":15000 +} diff --git a/device/dell/x86_64-dellemc_n3248te_c3338-r0/DellEMC-N3248TE/copp_platform_config.j2 b/device/dell/x86_64-dellemc_n3248te_c3338-r0/DellEMC-N3248TE/copp_platform_config.j2 new file mode 100644 index 000000000000..35c0066dc59e --- /dev/null +++ b/device/dell/x86_64-dellemc_n3248te_c3338-r0/DellEMC-N3248TE/copp_platform_config.j2 @@ -0,0 +1,145 @@ +{ + "COPP_GROUP": { + "copp-system-lacp": { + "cir":"250", + "cbs":"250" + }, + "copp-system-udld": { + "cir":"250", + "cbs":"250" + }, + "copp-system-stp": { + "cir":"8000", + "cbs":"8000" + }, + "copp-system-bfd": { + "cir":"750", + "cbs":"750" + }, + "copp-system-lldp": { + "cir":"250", + "cbs":"250" + }, + "copp-system-vrrp": { + "cir":"250", + "cbs":"250" + }, + "copp-system-iccp": { + "cir":"2500", + "cbs":"2500" + }, + "copp-system-ospf": { + "cir":"2500", + "cbs":"2500" + }, + "copp-system-bgp": { + "cir":"5000", + "cbs":"5000" + }, + "copp-system-pim": { + "cir":"2500", + "cbs":"2500" + }, + "copp-system-igmp": { + "cir":"1000", + "cbs":"1000" + }, + "copp-system-suppress": { + "cir":"1500", + "cbs":"1500" + }, + "copp-system-arp": { + "cir":"1500", + "cbs":"1500" + }, + "copp-system-dhcp": { + "cir":"150", + "cbs":"150" + }, + "copp-system-icmp": { + "cir":"500", + "cbs":"500" + }, + "copp-system-ip2me": { + "cir":"3000", + "cbs":"3000" + }, + "copp-system-subnet": { + "cir":"1000", + "cbs":"1000" + }, + "copp-system-mtu": { + "cir":"250", + "cbs":"250" + }, + "copp-system-sflow": { + "cir":"4000", + "cbs":"4000" + } + }, + "SCHEDULER": { + "copp-scheduler-policy@23": { + "pir": "250" + }, + "copp-scheduler-policy@22": { + "pir": "250" + }, + "copp-scheduler-policy@21": { + "pir": "8000" + }, + "copp-scheduler-policy@20": { + "pir": "750" + }, + "copp-scheduler-policy@19": { + "pir": "2500" + }, + "copp-scheduler-policy@18": { + "pir": "250" + }, + "copp-scheduler-policy@17": { + "pir": "250" + }, + "copp-scheduler-policy@16": { + "pir": "2500" + }, + "copp-scheduler-policy@15": { + "pir": "2500" + }, + "copp-scheduler-policy@14": { + "pir": "5000" + }, + "copp-scheduler-policy@13": { + "pir": "2500" + }, + "copp-scheduler-policy@12": { + "pir": "1000" + }, + "copp-scheduler-policy@11": { + "pir": "1500" + }, + "copp-scheduler-policy@10": { + "pir": "1500" + }, + "copp-scheduler-policy@9": { + "pir": "150" + }, + "copp-scheduler-policy@8": { + "pir": "500" + }, + "copp-scheduler-policy@7": { + "pir": "3000" + }, + "copp-scheduler-policy@6": { + "pir": "1000" + }, + "copp-scheduler-policy@4": { + "pir": "250" + }, + "copp-scheduler-policy@3": { + "pir": "4000" + }, + "copp-scheduler-policy@1": { + "pir": "100" + } + } +} diff --git a/device/dell/x86_64-dellemc_n3248te_c3338-r0/DellEMC-N3248TE/custom_led.bin b/device/dell/x86_64-dellemc_n3248te_c3338-r0/DellEMC-N3248TE/custom_led.bin new file mode 100644 index 0000000000000000000000000000000000000000..631b4712fa28c7bfb63dc04864b96e88166f1939 GIT binary patch literal 606 zcmW-cy>C)s6vm(TUJ#Jd+9I~dEiJqSELU2~hiK6X7kU~(8WTx0K%=E5=B6_PBZkCi zyZEtybTZw#)J8jLV&dp>S#|MGVAjQhXFkvK`#q!2Pv{|SQ;9~Ox~CHw-XQ#_+=;2O zM~c+)$0X!?@@TEh;aub8;Q961hNI)rIAZ;k;?5t_L+sgJHJJ(ta#_u_EH7U#u`6!?JVS@wYzaZkn~KNFSdm zNoRaGL}c-PCpxD2^KPwX)Cv{jh;mvh)hAusPyMM^g98Y&R)?H4JXY82kx>%s-nJ{Z zW9$^9CQ=6uVeOGOAJ_JiWjd&f^|u(HU{)U}8E4|xP{{AQkZLn4i%pyCHr3NRUtUw6 zKF|q`zJ84dihT8@P*2Y@v+G7>QfR;wCakBZVZ^_-mEF6P(gH zz055!Zi{fMBeODy2<0Fzf$^h#+H!Z9Oa7pZm{+83*C3Lx_rGposIGZS^|;VI$*X#V66@wioj7W&gBOLZDL3;78z)R zak*uPkNLrIC0>|F2z5fg%XBW`AKuTfUln@!MnC1-=x_FI6yD{VdA~sM9;=^!PJr1^XAn;d zP<7B%K0M?b;L8&zkqbn(`A+!K$T>di9T@xf4BP7i2^c> zoE8qcJ|6}q5Cs=|4(T)u;*_s<@4CIPTvi3o%C*DKZve{evkP3z0sl$XJN{9ZXOS(OZ>K z^Reg6sZsNgjwqw%<0!d+eVP~7Wz%;BTAUFR(cqk-w0OA_*PurFv;-^6Q}nY6eRb56 zQ=?2oZ?``~rC!T|gBFd5w>fG;ea#qScyJVmELsgPQu+x=YLc340^Q`sx;aWIBex2> zT=Y4aE6~CUtOW!!_6A!1vYl31Q?~;kY7lr0O9U|vQDz7=qP42c2iH`YLo=#X>--zm z{_TUl4cH6DQ@dQM;jpFOr5)BKz`vq=hb36q>!L=kY9kQQ*fX9I8mhhA5{sANIfrFv zE!647=5^Xr`&??VcOBGGVr*T1OSjeBaAEX#3`qi@h5$hre27uDDd z^e1jAWzT+!NZ%u=$!B~u?tO(s5gvxveqFFw;LQ%|BQqoL3D6?KZ8*wVA*EX+zX1EF z)Y*)d0AowMs^3jCHS{5|Z4T|{{?+2OfxVf#&oYfTY9Hp-dH=c0Z&}9EPwwJR@(+>% zA5`t~6|8>W*J*8Ay^zrLpO3OuIMna@{fO*6-t6&qs^$o4L@!pNM&9;NKCms}n|(NQ zu7>}Iq&f00t)0R?7d@g@G^4SX&|dD<);>hV%}uv-p&!$tM(G1PRqbHBoW;^F(>6N9ET9b>`7M${eO)P1Q`gi`&r#_L#+6wSr?UeckVLn@ONW9vf)M zufMl7Xz|*YWAD|LN3OLvoPm~1q)4%Oe-1)0r&x3ny;DcN^i!#o8CQjkI8a09bLgk2 z-x!xs){%)eVbp5H{$r$yU>p;SiN|3Ld3(in_~Y`qe%9)-ZgWALX7;%*jqpO9KZq7c zk3cFZ^;>x!!jugJJqL&MXw{kM<;eCy4d}&-{`o>cc+926SP|n4gDGXUv81Nfj~1al z_$(al+6t$=^*BSf^;vm_>R-DqkI>;Dlsc)@{Tcls)Gu!kOYO*!Iw9%9^kGWSFdvqg z5;V#@ll;GAIB}J+vivF!;wqiIHXKc6BBewJ1`!VGNg*PW^F!(bsks6eQ$j{L6TRcQ zwe-RBUH=G|y#2T)2-gWgX!OeaOGm2O`v!}N2Fzj;O1bDqtW(cRu8Kwl-v-22tKh4- zwr2=K>X5`%Kqw%*Mdl&ORLGdvg(#1AZHJNNHz_D@RZxZ}54pY`*(jW})cNx}xCM6* z;Hj|s$siOZ09LU8CM*+o18^#U{^+SjbtBUy&KAx z%UFA?effC~%lZW7g=8S22A!De$hqs#K1`E{dYnqg5uuKZq35fxMI|z*gYNM_w7Zfw z1VM8C#3`j$PRdc^@L+iu9Jh$64yfKhOt0`1Yn9Sxq-UU~tJ_MmpSzt-w#&@XY{2_> zUQ@%xQK%6pnEfJHLYA;R_HAjwiXKw3qJT_iY4(7N7Ts(ww_y1u>%6%aM$5zNt<-YU zoKHr9nTeRHP*-Eg6h`ztgKh>=9!Udth;<|h;ZC9st3lwv+yiC_nv8n!>5vV=_&1KH6(nd&~%ynB$4Od3r zKx_ab<!p8-mo%To9ZN`Xkv6FDHSapVKHS-lMD-s(%TovQiwk zDMvroZS7xfYWN1xD0;CMclD4m#%ZUYD<6Q=yj;->z?8q-3wz3b)HUbfPW=U4J;z#C zdJ7zX9ziSa+P2iAFGE}Ih1FfG^+(D|d)uMLIbTpTm(EdS0OobAw;EZy*EHwyHGNSb zO3~MU;)tKPf86SH!itg=D%6@0wWbyWt<9`+UO#76H22x)I`{0C>UK=#${?!7&1Mtw%tXVkTW)3 z^gP%cNWD2;6prZ@$4&Tc7UdCg|KPakFpcXs?N=+Kj*ScCMvN!d=OC+=05o81abUSV z_n43*$%$=JT9+#ff#b&blBJ71Tfw>DRM$6MJ!H76ke$ZvaZw^weF^Q~0cm?*-WZC zVpo#=(VWp@jIgBXTgnNhhH=E(V2DyqlWAmaly>y}c?t^C?$5bA|fWx)lk z_21S&$mvLb1l4QYRF%!rLwJm99D zkkUsngEoxb=MMG&)m)7Jtz(OuSt_)Vrx+)nLt8`7s?}nwWi2-lQ%IL^qJ8#fzyTsv zYYK0&4!XWM4>x}gPaHkjh3I;$qSsWH9aUF(JRV#{FV4{XdpRqXBc^QKe&oJgv{TEi z=6OFS&O{ShfSk*@D{ppa&fVJD4?#N8`Z`o@BaZKdH9Iy z?eoCAk!*_Ku0^)e-p(4dBIPI*g8*fCy9+f%0Z$DJu23yfNKHqIiYKs#wqYb-w22$s z_*)^5rEE0j!y6Fgrl`(i6rdhu+51?xK+B#mbw@I(rkNSEg}2Z)pc!$a%?+>(XrPP!eZw=TDF8J>WRW8%2}HfH&0wCChI1scg->ls=GQFiZZcIDt8d&IDk^{oYi7 z`^C(GLL_V5fffS;D$H9M7QY1w4G}4QQQDz4nAnwgd&62%sku5KYIVcrKufttACSK> zok2J)bmDmtE2g>Ae4yn9*=Bwk)5VGdEhV0q)*$TkcN#jWSP{+b#M^wKyBqUTcw8PK zYtU0U9uKtWl-A&1v|?OCe{I4wFUFFJ9B7?Yb3)kPcA)(w%{~Fo@dCuLs-FeQU zp1#lO{U43F5%$8poAUDLt8^Y6tndRSSq9K*fLc{UR%8CP(oV zW{2hd2N_2O^Bg!NrEkn?fL1I$7p2e-@dYERA}M}uD`sX`b7j?N+jUBmw`JwiU{Dwm z7H~tj7H2@d&&s}4)gh&ab2Hn)VMhOyX?(57mAieyK#K)^i<0=wQu;%sRZDnW139R_qY?v{SKIhTL<~|Z zvrU9XWQU|2WR?eO7%I5Dn|0KzI zlgwF!ycWz)XJ=(Tz&8W7viIm6IJ=adod!B7n=KA;5%v|t z_1HHfu@Fbsh<9QO9WTI^qC^8}R8V;*lgFzL@xr@9m`XsHw!7~6DyhQSSW=DObW)4o zKPPqg{W@vD@5Q7Mzh7Xc3O3m1$DM7+sG<0bYBoH5g@ZW;(Sf_znZb)(>cxykTX5sF znGDF;YyQ4&l;j*kzPZoAx0RA9da;zjY(#EdDP5kT1nFXOzH&SHImYHp)Qxtx7|VbU z;HL!OGn}G&Op=cMha_dHDG=V1q|`Y{;vddQu}c$@Gg3fg&tmXB#E>W?XW6G+nvn|f z1nZeugI~7n2GUsxbG|Seg@l;RuChz4g=5lGx?J>b#|f4S=9DyE!@L&KFg&SHZK zwoDoNrlL0MM%)RbmOgy}+z8L6zursm>XR zM}WF)9O{kYbm6h`r(Ehd2o{T(HxoMHtI9dc62bW!{hg5Dgy}pTQzz&OGv+^E#?i*{ zZM13X1uhlUwrbsGUfWtyKCB;x#W9L$;y+Awp?rA`wHGjO0MH5jNz}m*)Q{l_C%?;5 r32LZh7SzipUVi`b`|m0o-h^13!6LsQJYocJBmG@}mEYC*|LFT~Y{;3K literal 0 HcmV?d00001 diff --git a/device/dell/x86_64-dellemc_n3248te_c3338-r0/DellEMC-N3248TE/pg_profile_lookup.ini b/device/dell/x86_64-dellemc_n3248te_c3338-r0/DellEMC-N3248TE/pg_profile_lookup.ini new file mode 100644 index 000000000000..6d91d03ae684 --- /dev/null +++ b/device/dell/x86_64-dellemc_n3248te_c3338-r0/DellEMC-N3248TE/pg_profile_lookup.ini @@ -0,0 +1,17 @@ +# PG lossless profiles. +# speed cable size xon xoff threshold xon_offset + 10000 5m 9427 0 50176 1 3584 + 25000 5m 9427 0 50176 1 3584 + 40000 5m 9427 0 50176 1 3584 + 50000 5m 9427 0 50176 1 3584 + 100000 5m 9427 0 50176 1 3584 + 10000 40m 9427 0 50176 1 3584 + 25000 40m 9427 0 50176 1 3584 + 40000 40m 9427 0 50176 1 3584 + 50000 40m 9427 0 50176 1 3584 + 100000 40m 9427 0 50176 1 3584 + 10000 300m 9427 0 50176 1 3584 + 25000 300m 9427 0 50176 1 3584 + 40000 300m 9427 0 50176 1 3584 + 50000 300m 9427 0 50176 1 3584 + 100000 300m 9427 0 50176 1 3584 diff --git a/device/dell/x86_64-dellemc_n3248te_c3338-r0/DellEMC-N3248TE/port_config.ini b/device/dell/x86_64-dellemc_n3248te_c3338-r0/DellEMC-N3248TE/port_config.ini new file mode 100644 index 000000000000..fd37efc9332e --- /dev/null +++ b/device/dell/x86_64-dellemc_n3248te_c3338-r0/DellEMC-N3248TE/port_config.ini @@ -0,0 +1,55 @@ +# name lanes alias index speed autoneg +Ethernet0 1 oneGigE1/1 1 1000 1 +Ethernet1 2 oneGigE1/2 2 1000 1 +Ethernet2 3 oneGigE1/3 3 1000 1 +Ethernet3 4 oneGigE1/4 4 1000 1 +Ethernet4 5 oneGigE1/5 5 1000 1 +Ethernet5 6 oneGigE1/6 6 1000 1 +Ethernet6 7 oneGigE1/7 7 1000 1 +Ethernet7 8 oneGigE1/8 8 1000 1 +Ethernet8 9 oneGigE1/9 9 1000 1 +Ethernet9 10 oneGigE1/10 10 1000 1 +Ethernet10 11 oneGigE1/11 11 1000 1 +Ethernet11 12 oneGigE1/12 12 1000 1 +Ethernet12 13 oneGigE1/13 13 1000 1 +Ethernet13 14 oneGigE1/14 14 1000 1 +Ethernet14 15 oneGigE1/15 15 1000 1 +Ethernet15 16 oneGigE1/16 16 1000 1 +Ethernet16 17 oneGigE1/17 17 1000 1 +Ethernet17 18 oneGigE1/18 18 1000 1 +Ethernet18 19 oneGigE1/19 19 1000 1 +Ethernet19 20 oneGigE1/20 20 1000 1 +Ethernet20 21 oneGigE1/21 21 1000 1 +Ethernet21 22 oneGigE1/22 22 1000 1 +Ethernet22 23 oneGigE1/23 23 1000 1 +Ethernet23 24 oneGigE1/24 24 1000 1 +Ethernet24 25 oneGigE1/25 25 1000 1 +Ethernet25 26 oneGigE1/26 26 1000 1 +Ethernet26 27 oneGigE1/27 27 1000 1 +Ethernet27 28 oneGigE1/28 28 1000 1 +Ethernet28 29 oneGigE1/29 29 1000 1 +Ethernet29 30 oneGigE1/30 30 1000 1 +Ethernet30 31 oneGigE1/31 31 1000 1 +Ethernet31 32 oneGigE1/32 32 1000 1 +Ethernet32 33 oneGigE1/33 33 1000 1 +Ethernet33 34 oneGigE1/34 34 1000 1 +Ethernet34 35 oneGigE1/35 35 1000 1 +Ethernet35 36 oneGigE1/36 36 1000 1 +Ethernet36 37 oneGigE1/37 37 1000 1 +Ethernet37 38 oneGigE1/38 38 1000 1 +Ethernet38 39 oneGigE1/39 39 1000 1 +Ethernet39 40 oneGigE1/40 40 1000 1 +Ethernet40 41 oneGigE1/41 41 1000 1 +Ethernet41 42 oneGigE1/42 42 1000 1 +Ethernet42 43 oneGigE1/43 43 1000 1 +Ethernet43 44 oneGigE1/44 44 1000 1 +Ethernet44 45 oneGigE1/45 45 1000 1 +Ethernet45 46 oneGigE1/46 46 1000 1 +Ethernet46 47 oneGigE1/47 47 1000 1 +Ethernet47 48 oneGigE1/48 48 1000 1 +Ethernet48 64 tenGigE1/49 49 10000 0 +Ethernet49 63 tenGigE1/50 50 10000 0 +Ethernet50 62 tenGigE1/51 51 10000 0 +Ethernet51 61 tenGigE1/52 52 10000 0 +Ethernet52 69,70,71,72 hundredGigE1/53 53 100000 0 +Ethernet56 73,74,75,76 hundredGigE1/54 54 100000 0 diff --git a/device/dell/x86_64-dellemc_n3248te_c3338-r0/DellEMC-N3248TE/qos.json.j2 b/device/dell/x86_64-dellemc_n3248te_c3338-r0/DellEMC-N3248TE/qos.json.j2 new file mode 100644 index 000000000000..ee67c6e26221 --- /dev/null +++ b/device/dell/x86_64-dellemc_n3248te_c3338-r0/DellEMC-N3248TE/qos.json.j2 @@ -0,0 +1 @@ +{%- include 'qos_config_t1.j2' %} diff --git a/device/dell/x86_64-dellemc_n3248te_c3338-r0/DellEMC-N3248TE/qos_config_t1.j2 b/device/dell/x86_64-dellemc_n3248te_c3338-r0/DellEMC-N3248TE/qos_config_t1.j2 new file mode 100644 index 000000000000..5fe5324a85c1 --- /dev/null +++ b/device/dell/x86_64-dellemc_n3248te_c3338-r0/DellEMC-N3248TE/qos_config_t1.j2 @@ -0,0 +1,175 @@ +{%- set PORT_ALL = [] %} +{%- for port in PORT %} + {%- if PORT_ALL.append(port) %}{% endif %} +{%- endfor %} +{%- if PORT_ALL | sort_by_port_index %}{% endif %} + +{%- set port_names_list_all = [] %} +{%- for port in PORT_ALL %} + {%- if port_names_list_all.append(port) %}{% endif %} +{%- endfor %} +{%- set port_names_all = port_names_list_all | join(',') -%} + + +{%- set PORT_ACTIVE = [] %} +{%- if DEVICE_NEIGHBOR is not defined %} + {%- set PORT_ACTIVE = PORT_ALL %} +{%- else %} + {%- for port in DEVICE_NEIGHBOR.keys() %} + {%- if PORT_ACTIVE.append(port) %}{%- endif %} + {%- endfor %} +{%- endif %} +{%- if PORT_ACTIVE | sort_by_port_index %}{% endif %} + +{%- set port_names_list_active = [] %} +{%- for port in PORT_ACTIVE %} + {%- if port_names_list_active.append(port) %}{%- endif %} +{%- endfor %} +{%- set port_names_active = port_names_list_active | join(',') -%} + + +{%- set pfc_to_pg_map_supported_asics = ['mellanox', 'barefoot', 'marvell'] -%} + + +{ +{% if generate_tc_to_pg_map is defined %} + {{- generate_tc_to_pg_map() }} +{% else %} + "TC_TO_PRIORITY_GROUP_MAP": { + "AZURE": { + "0": "0", + "1": "0", + "2": "0", + "3": "3", + "4": "4", + "5": "0", + "6": "0", + "7": "7" + } + }, +{% endif %} + "MAP_PFC_PRIORITY_TO_QUEUE": { + "AZURE": { + "0": "0", + "1": "1", + "2": "2", + "3": "3", + "4": "4", + "5": "5", + "6": "6", + "7": "7" + } + }, + "TC_TO_QUEUE_MAP": { + "AZURE": { + "0": "0", + "1": "1", + "2": "2", + "3": "3", + "4": "4", + "5": "5", + "6": "6", + "7": "7" + } + }, + "DSCP_TO_TC_MAP": { + "AZURE": { + "0" : "1", + "1" : "1", + "2" : "1", + "3" : "3", + "4" : "4", + "5" : "2", + "6" : "1", + "7" : "1", + "8" : "0", + "9" : "1", + "10": "1", + "11": "1", + "12": "1", + "13": "1", + "14": "1", + "15": "1", + "16": "1", + "17": "1", + "18": "1", + "19": "1", + "20": "1", + "21": "1", + "22": "1", + "23": "1", + "24": "1", + "25": "1", + "26": "1", + "27": "1", + "28": "1", + "29": "1", + "30": "1", + "31": "1", + "32": "1", + "33": "1", + "34": "1", + "35": "1", + "36": "1", + "37": "1", + "38": "1", + "39": "1", + "40": "1", + "41": "1", + "42": "1", + "43": "1", + "44": "1", + "45": "1", + "46": "5", + "47": "1", + "48": "6", + "49": "1", + "50": "1", + "51": "1", + "52": "1", + "53": "1", + "54": "1", + "55": "1", + "56": "1", + "57": "1", + "58": "1", + "59": "1", + "60": "1", + "61": "1", + "62": "1", + "63": "1" + } + }, + "SCHEDULER": { + "scheduler.0": { + "type" : "DWRR", + "weight": "14" + }, + "scheduler.1": { + "type" : "DWRR", + "weight": "15" + } + }, +{% if asic_type in pfc_to_pg_map_supported_asics %} + "PFC_PRIORITY_TO_PRIORITY_GROUP_MAP": { + "AZURE": { + "3": "3", + "4": "4" + } + }, +{% endif %} + "PORT_QOS_MAP": { +{% for port in PORT_ACTIVE %} + "{{ port }}": { + "dscp_to_tc_map" : "[DSCP_TO_TC_MAP|AZURE]", + "tc_to_queue_map" : "[TC_TO_QUEUE_MAP|AZURE]", + "tc_to_pg_map" : "[TC_TO_PRIORITY_GROUP_MAP|AZURE]", + "pfc_to_queue_map": "[MAP_PFC_PRIORITY_TO_QUEUE|AZURE]", +{% if asic_type in pfc_to_pg_map_supported_asics %} + "pfc_to_pg_map" : "[PFC_PRIORITY_TO_PRIORITY_GROUP_MAP|AZURE]", +{% endif %} + "pfc_enable" : "3,4" + }{% if not loop.last %},{% endif %} +{% endfor %} + } +} diff --git a/device/dell/x86_64-dellemc_n3248te_c3338-r0/DellEMC-N3248TE/sai.profile b/device/dell/x86_64-dellemc_n3248te_c3338-r0/DellEMC-N3248TE/sai.profile new file mode 100644 index 000000000000..8acb22ae32f2 --- /dev/null +++ b/device/dell/x86_64-dellemc_n3248te_c3338-r0/DellEMC-N3248TE/sai.profile @@ -0,0 +1 @@ +SAI_INIT_CONFIG_FILE=/usr/share/sonic/hwsku/hx5-n3248te-48x1G+4x10G.config.bcm diff --git a/device/dell/x86_64-dellemc_n3248te_c3338-r0/DellEMC-N3248TE/sai_preinit_cmd.soc b/device/dell/x86_64-dellemc_n3248te_c3338-r0/DellEMC-N3248TE/sai_preinit_cmd.soc new file mode 100644 index 000000000000..4d62900f898f --- /dev/null +++ b/device/dell/x86_64-dellemc_n3248te_c3338-r0/DellEMC-N3248TE/sai_preinit_cmd.soc @@ -0,0 +1,2 @@ +m0 load 0 0x0 /usr/share/sonic/hwsku/linkscan_led_fw.bin +m0 load 0 0x3800 /usr/share/sonic/hwsku/custom_led.bin diff --git a/device/dell/x86_64-dellemc_n3248te_c3338-r0/default_sku b/device/dell/x86_64-dellemc_n3248te_c3338-r0/default_sku new file mode 100644 index 000000000000..59ca9b54544a --- /dev/null +++ b/device/dell/x86_64-dellemc_n3248te_c3338-r0/default_sku @@ -0,0 +1 @@ +DellEMC-N3248TE t1 diff --git a/device/dell/x86_64-dellemc_n3248te_c3338-r0/init_cfg.json b/device/dell/x86_64-dellemc_n3248te_c3338-r0/init_cfg.json new file mode 100644 index 000000000000..dc933239006c --- /dev/null +++ b/device/dell/x86_64-dellemc_n3248te_c3338-r0/init_cfg.json @@ -0,0 +1,13 @@ +{ + "FEATURE": { + "tam": { + "state": "disabled" + }, + "telemetry": { + "state": "disabled" + }, + "nat": { + "state": "disabled" + } + } +} diff --git a/device/dell/x86_64-dellemc_n3248te_c3338-r0/installer.conf b/device/dell/x86_64-dellemc_n3248te_c3338-r0/installer.conf new file mode 100644 index 000000000000..8e3add013c31 --- /dev/null +++ b/device/dell/x86_64-dellemc_n3248te_c3338-r0/installer.conf @@ -0,0 +1,3 @@ +CONSOLE_PORT=0x3f8 +CONSOLE_DEV=0 +VAR_LOG_SIZE=512 diff --git a/device/dell/x86_64-dellemc_n3248te_c3338-r0/led_proc_init.soc b/device/dell/x86_64-dellemc_n3248te_c3338-r0/led_proc_init.soc new file mode 100644 index 000000000000..c909fe5e9fe5 --- /dev/null +++ b/device/dell/x86_64-dellemc_n3248te_c3338-r0/led_proc_init.soc @@ -0,0 +1,7 @@ +# LED microprocessor initialization for Dell N3248TE +# +# +#Led0 +#led auto on +m0 load 0 0x3800 /usr/share/sonic/hwsku/custom_led.bin +led start diff --git a/device/dell/x86_64-dellemc_n3248te_c3338-r0/plugins/eeprom.py b/device/dell/x86_64-dellemc_n3248te_c3338-r0/plugins/eeprom.py new file mode 100644 index 000000000000..bf4703f05d9f --- /dev/null +++ b/device/dell/x86_64-dellemc_n3248te_c3338-r0/plugins/eeprom.py @@ -0,0 +1,22 @@ +#!/usr/bin/python3 + +############################################################################# +# Dell S3000 +# +# Platform and model specific eeprom subclass, inherits from the base class, +# and provides the followings: +# - the eeprom format definition +# - specific encoder/decoder if there is special need +############################################################################# + +try: + from sonic_eeprom import eeprom_tlvinfo +except ImportError as e: + raise ImportError (str(e) + "- required module not found") + + +class board(eeprom_tlvinfo.TlvInfoDecoder): + + def __init__(self, name, path, cpld_root, ro): + self.eeprom_path = "/sys/class/i2c-adapter/i2c-2/2-0050/eeprom" + super(board, self).__init__(self.eeprom_path, 0, '', True) diff --git a/device/dell/x86_64-dellemc_n3248te_c3338-r0/plugins/fanutil.py b/device/dell/x86_64-dellemc_n3248te_c3338-r0/plugins/fanutil.py new file mode 100644 index 000000000000..47979b5d7ab5 --- /dev/null +++ b/device/dell/x86_64-dellemc_n3248te_c3338-r0/plugins/fanutil.py @@ -0,0 +1,72 @@ +# +# fanutil.py +# Platform-specific FAN status interface for SONiC +# + +import subprocess +import sys + +SENSORS_CMD = "docker exec -i pmon /usr/bin/sensors" +DOCKER_SENSORS_CMD = "/usr/bin/sensors" + + +try: + from sonic_fan.fan_base import FanBase +except ImportError as e: + raise ImportError(str(e) + "- required module not found") + + +class FanUtil(FanBase): + """Platform-specific FanUtil class""" + _fan_mapping = { + 1 : '0', + 2 : '1', + 3 : '2' + } + + def __init__(self): + FanBase.__init__(self) + + def isDockerEnv(self): + num_docker = open('/proc/self/cgroup', 'r').read().count(":/docker") + if num_docker > 0: + return True + + def get_num_fans(self): + N3248TE_MAX_FANTRAYS = 3 + return N3248TE_MAX_FANTRAYS + + def get_presence(self, idx): + sysfs_path = "/sys/devices/platform/dell-n3248te-cpld.0/fan" + self._fan_mapping[idx] + "_prs" + return int(open(sysfs_path).read(), 16) + + def get_direction(self, idx): + sysfs_path = "/sys/devices/platform/dell-n3248te-cpld.0/fan" + self._fan_mapping[idx] + "_dir" + return open(sysfs_path).read() + + def get_speed(self, idx): + dockerenv = self.isDockerEnv() + if not dockerenv: + status, cmd_output = subprocess.getstatusoutput(SENSORS_CMD) + else : + status, cmd_output = subprocess.getstatusoutput(DOCKER_SENSORS_CMD) + + if status: + print('Failed to execute sensors command') + sys.exit(0) + fan_id = 'Fan ' + str(idx) + found = False + for line in cmd_output.splitlines(): + if line.startswith('emc2305-i2c-7-2c'): + found = True + if found and line.startswith(fan_id): + return line.split()[3] + return 0.0 + + def get_status(self, idx): + sysfs_path = "/sys/devices/platform/dell-n3248te-cpld.0/fan" + self._fan_mapping[idx] + "_prs" + return int(open(sysfs_path).read(), 16) + + + def set_speed(self, idx): + return False diff --git a/device/dell/x86_64-dellemc_n3248te_c3338-r0/plugins/pcie.yaml b/device/dell/x86_64-dellemc_n3248te_c3338-r0/plugins/pcie.yaml new file mode 100644 index 000000000000..dd8049268567 --- /dev/null +++ b/device/dell/x86_64-dellemc_n3248te_c3338-r0/plugins/pcie.yaml @@ -0,0 +1,16 @@ +- bus: '02' + dev: '00' + fn: '0' + id: '1533' + name: 'Ethernet controller: Intel Corporation I210 Gigabit Network Connection (rev + 03)' +- bus: '01' + dev: '00' + fn: '0' + id: b371 + name: 'Ethernet controller: Broadcom Limited BCM56371 Switch ASIC (rev 02)' +- bus: '00' + dev: '14' + fn: '0' + id: 19c2 + name: 'SATA controller: Intel Corporation DNV SATA Controller 1 (rev 11)' diff --git a/device/dell/x86_64-dellemc_n3248te_c3338-r0/plugins/psuutil.py b/device/dell/x86_64-dellemc_n3248te_c3338-r0/plugins/psuutil.py new file mode 100644 index 000000000000..13e95ed2549d --- /dev/null +++ b/device/dell/x86_64-dellemc_n3248te_c3338-r0/plugins/psuutil.py @@ -0,0 +1,191 @@ +# +# psuutil.py +# Platform-specific PSU status interface for SONiC +# + +import commands +import os +import sys + +SENSORS_CMD = "docker exec -i pmon /usr/bin/sensors" +DOCKER_SENSORS_CMD = "/usr/bin/sensors" + +try: + from sonic_psu.psu_base import PsuBase +except ImportError as e: + raise ImportError(str(e) + "- required module not found") + + +class PsuUtil(PsuBase): + """Platform-specific PSUutil class""" + _psu_mapping = { + 1 : '0', + 2 : '1' + } + + def __init__(self): + PsuBase.__init__(self) + + def isDockerEnv(self): + num_docker = open('/proc/self/cgroup', 'r').read().count(":/docker") + if num_docker > 0: + return True + else: + return False + + def remove_nonnumeric(self, text): + digits='0123456789.' + return ''.join(c for c in text if c in digits) + + def get_cpld_register(self, reg_name): + cpld_dir = "/sys/devices/platform/dell-n3248te-cpld.0/" + retval = 'ERR' + reg_file = cpld_dir +'/' + reg_name + if (not os.path.isfile(reg_file)): + return retval + + try: + with open(reg_file, 'r') as fd: + retval = fd.read() + except Exception as error: + print("Unable to open ", reg_file, "file !") + + retval = retval.rstrip('\r\n') + return retval + + def get_num_psus(self): + """ + Retrieves the number of PSUs available on the device + :return: An integer, the number of PSUs available on the device + """ + N3248TE_MAX_PSUS = 2 + return N3248TE_MAX_PSUS + + def get_psu_status(self, index): + """ + Retrieves the oprational status of power supply unit (PSU) defined + by index + :param index: An integer, index of the PSU of which to query status + :return: Boolean, True if PSU is operating properly, False if PSU is\ + faulty + """ + status = 0 + psu_status = self.get_cpld_register('psu'+self._psu_mapping[index]+'_status') + if (psu_status != 'ERR'): + status = int(psu_status, 10) + + presence = self.get_psu_presence(index) + + return (status & presence) + + def get_psu_presence(self, index): + """ + Retrieves the presence status of power supply unit (PSU) defined + by index + :param index: An integer, index of the PSU of which to query status + :return: Boolean, True if PSU is plugged, False if not + """ + status = 0 + psu_presence = self.get_cpld_register('psu'+self._psu_mapping[index]+'_prs') + if (psu_presence != 'ERR'): + status = int(psu_presence, 10) + + return status + + def get_sensor(self): + dockerenv = self.isDockerEnv() + if not dockerenv: + status, cmd_output = commands.getstatusoutput(SENSORS_CMD) + else : + status, cmd_output = commands.getstatusoutput(DOCKER_SENSORS_CMD) + + if status: + print('Failed to execute sensors command') + sys.exit(0) + return cmd_output + + def get_output_current(self, index): + cmd_output= self.get_sensor() + sensor_name = 'dps460-i2c-10' if index == 1 else 'dps460-i2c-11' + found = False + for line in cmd_output.splitlines(): + if line.startswith(sensor_name): + found = True + if found: + if 'Output Current' in line : + return float(self.remove_nonnumeric(line.split()[2])) + return 0.0 + + def get_output_voltage(self, index): + cmd_output= self.get_sensor() + sensor_name = 'dps460-i2c-10' if index == 1 else 'dps460-i2c-11' + found = False + for line in cmd_output.splitlines(): + if line.startswith(sensor_name): + found = True + if found: + if 'Output Voltage' in line : + return float(self.remove_nonnumeric(line.split()[2])) + return 0.0 + + def get_fan_rpm(self, index, fan_index): + if fan_index > 1 : return 0.0 + cmd_output= self.get_sensor() + sensor_name = 'dps460-i2c-10' if index == 1 else 'dps460-i2c-11' + found = False + for line in cmd_output.splitlines(): + if line.startswith(sensor_name): + found = True + if found: + if 'Fan RPM' in line : + return self.remove_nonnumeric(line.split()[2]) + return 0.0 + + def get_output_power(self, index): + cmd_output= self.get_sensor() + sensor_name = 'dps460-i2c-10' if index == 1 else 'dps460-i2c-11' + found = False + for line in cmd_output.splitlines(): + if line.startswith(sensor_name): + found = True + if found: + if 'Output Power' in line : + return float(self.remove_nonnumeric(line.split()[2])) + return 0.0 + + def get_direction(self, index): + psuid = '0' if index == 1 else '1' + sysfs_path = '/sys/devices/platform/dell-n3248te-cpld.0/psu' + psuid + '_prs' + found_psu = int(open(sysfs_path).read()) + if not found_psu : return '' + bus_no = '10' if index == 1 else '11' + sysfs_path = "/sys/bus/i2c/devices/" + bus_no + "-0056/eeprom" + val = (open(sysfs_path, "rb").read())[0xe1:0xe8] + dir = 'F2B' if 'FORWARD' == val else 'B2F' + return dir + + def get_serial(self, index): + psuid = '0' if index == 1 else '1' + sysfs_path = '/sys/devices/platform/dell-n3248te-cpld.0/psu' + psuid + '_prs' + found_psu = int(open(sysfs_path).read()) + if not found_psu : return '' + bus_no = '10' if index == 1 else '11' + sysfs_path = "/sys/bus/i2c/devices/" + bus_no + "-0056/eeprom" + val = (open(sysfs_path, "rb").read())[0xc4:0xd9] + return val + + def get_model(self, index): + psuid = '0' if index == 1 else '1' + sysfs_path = '/sys/devices/platform/dell-n3248te-cpld.0/psu' + psuid + '_prs' + found_psu = int(open(sysfs_path).read()) + if not found_psu : return '' + bus_no = '10' if index == 1 else '11' + sysfs_path = "/sys/bus/i2c/devices/" + bus_no + "-0056/eeprom" + val = (open(sysfs_path, "rb").read())[0x50:0x62] + return val + + def get_mfr_id(self, index): + psuid = '0' if index == 1 else '1' + sysfs_path = '/sys/devices/platform/dell-n3248te-cpld.0/psu' + psuid + '_prs' + found_psu = int(open(sysfs_path).read()) + return 'DELTA' if found_psu else '' diff --git a/device/dell/x86_64-dellemc_n3248te_c3338-r0/plugins/sfputil.py b/device/dell/x86_64-dellemc_n3248te_c3338-r0/plugins/sfputil.py new file mode 100644 index 000000000000..1c974ca6fd00 --- /dev/null +++ b/device/dell/x86_64-dellemc_n3248te_c3338-r0/plugins/sfputil.py @@ -0,0 +1,172 @@ +# sfputil.py +# +# Platform-specific SFP transceiver interface for SONiC +# + +try: + import time + from socket import * + from select import * + from sonic_sfp.sfputilbase import SfpUtilBase +except ImportError as e: + raise ImportError("%s - required module not found" % str(e)) + +class SfpUtil(SfpUtilBase): + """Platform-specific SfpUtil class""" + + PORT_START = 1 + PORT_END = 52 + PORTS_IN_BLOCK = 52 + SFP_PORT_START = 49 + SFP_PORT_END = 52 + + EEPROM_OFFSET = 14 + + _port_to_eeprom_mapping = {} + _sfpp_port_i2c_mapping = { + 49 : 20, + 50 : 21, + 51 : 22, + 52 : 23 + } + port_dict = {} + + @property + def port_start(self): + return self.PORT_START + + @property + def port_end(self): + return self.PORT_END + + @property + def qsfp_ports(self) : + return range(self.SFP_PORT_END+1, self.SFP_PORT_END+1) + + @property + def port_to_eeprom_mapping(self): + return self._port_to_eeprom_mapping + + @property + def get_transceiver_status(self): + + try: + sfp_modprs_path = "/sys/devices/platform/dell-n3248te-cpld.0/sfp_modprs" + reg_file = open(sfp_modprs_path) + + except IOError as e: + print ("Error: unable to open file: %s" % str(e)) + return False + + content = reg_file.readline().rstrip() + + reg_file.close() + + return int(content, 16) + + + def __init__(self): + + sfpplus_eeprom_path = "/sys/class/i2c-adapter/i2c-{0}/{0}-0050/eeprom" + + for x in range(self.SFP_PORT_START, self.SFP_PORT_END + 1): + self.port_to_eeprom_mapping[x] = sfpplus_eeprom_path.format(self._sfpp_port_i2c_mapping[x]) + # Get Transceiver status + self.modprs_register = self.get_transceiver_status + + SfpUtilBase.__init__(self) + + def get_presence(self, port_num): + # Check for invalid port_num + if port_num < self.port_start or port_num > self.port_end: + return False + + if port_num < self.SFP_PORT_START : + return False + port_num -= self.SFP_PORT_START + try: + sfp_modprs_path = "/sys/devices/platform/dell-n3248te-cpld.0/sfp_modprs" + reg_file = open(sfp_modprs_path) + except IOError as e: + print ("Error: unable to open file: %s" % str(e)) + return False + + content = reg_file.readline().rstrip() + + # content is a string containing the hex representation of the register + reg_value = int(content, 16) + + # Mask off the bit corresponding to our port + mask = (1 << port_num) + + # ModPrsL is active low + if (reg_value & mask) == 0: + return True + + return False + + def get_low_power_mode(self, port_num): + return False + + def set_low_power_mode(self, port_num, lpmode): + return False + + def reset(self, port_num): + return False + + def get_transceiver_change_event(self, timeout=0): + + start_time = time.time() + port = self.SFP_PORT_START + forever = False + + if timeout == 0: + forever = True + elif timeout > 0: + timeout = timeout / float(1000) # Convert to secs + else: + print ('get_transceiver_change_event:Invalid timeout value', timeout) + return False, {} + + end_time = start_time + timeout + if start_time > end_time: + print ('get_transceiver_change_event:' \ + 'time wrap / invalid timeout value', timeout) + + return False, {} # Time wrap or possibly incorrect timeout + + while timeout >= 0: + # Check for OIR events and return updated port_dict + reg_value = self.get_transceiver_status + if reg_value != self.modprs_register: + changed_ports = self.modprs_register ^ reg_value + while port >= self.SFP_PORT_START and port <= self.SFP_PORT_END: + + # Mask off the bit corresponding to our port + mask = (1 << (port - self.SFP_PORT_START)) + + if changed_ports & mask: + # ModPrsL is active low + if reg_value & mask == 0: + self.port_dict[port] = '1' + else: + self.port_dict[port] = '0' + + port += 1 + + # Update reg value + self.modprs_register = reg_value + return True, self.port_dict + + if forever: + time.sleep(1) + else: + timeout = end_time - time.time() + if timeout >= 1: + time.sleep(1) # We poll at 1 second granularity + else: + if timeout > 0: + time.sleep(timeout) + return True, {} + print ("get_transceiver_change_event: Should not reach here.") + return False, {} diff --git a/device/dell/x86_64-dellemc_n3248te_c3338-r0/pmon_daemon_control.json b/device/dell/x86_64-dellemc_n3248te_c3338-r0/pmon_daemon_control.json new file mode 100644 index 000000000000..4f701c3b3400 --- /dev/null +++ b/device/dell/x86_64-dellemc_n3248te_c3338-r0/pmon_daemon_control.json @@ -0,0 +1,3 @@ +{ + "skip_ledd": true +} diff --git a/device/dell/x86_64-dellemc_n3248te_c3338-r0/sensors.conf b/device/dell/x86_64-dellemc_n3248te_c3338-r0/sensors.conf new file mode 100644 index 000000000000..987b4ad73984 --- /dev/null +++ b/device/dell/x86_64-dellemc_n3248te_c3338-r0/sensors.conf @@ -0,0 +1,58 @@ +# libsensors configuration file for Dell N3248TE +# The i2c bus portion is omit because adapter name +# changes every time when system boot up. + +bus "i2c-7" "i2c-0-mux (chan_id 5)" +bus "i2c-5" "i2c-0-mux (chan_id 3)" +bus "i2c-10" "i2c-5-mux (chan_id 0)" +bus "i2c-11" "i2c-5-mux (chan_id 1)" + +chip "tmp75-i2c-7-49" + label temp1 "Switch Near Temperature" +chip "tmp75-i2c-7-4a" + label temp1 "Switch Rear Temperature" +chip "tmp75-i2c-7-4b" + label temp1 "Front Panel PHY Temperature" +chip "tmp75-i2c-7-4c" + label temp1 "Near Front Panel Temperature" +chip "tmp75-i2c-7-4f" + label temp1 "Middle Fan Tray Temperature" + + +chip "emc2305-i2c-7-2c" + ignore fan4 + ignore fan5 + label fan1 "Fan 1 " + label fan2 "Fan 2 " + label fan3 "Fan 3 " + +chip "dps460-i2c-10-5e" + label power1 "Input Power" + label power2 "Output Power" + label curr1 "Input Current" + label curr2 "Output Current" + label in1 "Input Voltage" + ignore in2 + label in3 "Output Voltage" + label fan1 "Fan RPM" + ignore fan2 + ignore fan3 + ignore temp1 + label temp2 "FAN Airflow Temperature" + label temp3 "FAN Normal Temperature" + + +chip "dps460-i2c-11-5e" + label power1 "Input Power" + label power2 "Output Power" + label curr1 "Input Current" + label curr2 "Output Current" + label in1 "Input Voltage" + ignore in2 + label in3 "Output Voltage" + label fan1 "Fan RPM" + ignore fan2 + ignore fan3 + ignore temp1 + label temp2 "FAN Airflow Temperature" + label temp3 "FAN Normal Temperature" diff --git a/platform/broadcom/one-image.mk b/platform/broadcom/one-image.mk index 7f9a46b5c166..ad9a4398c884 100644 --- a/platform/broadcom/one-image.mk +++ b/platform/broadcom/one-image.mk @@ -15,6 +15,7 @@ $(SONIC_ONE_IMAGE)_LAZY_INSTALLS += $(DELL_S6000_PLATFORM_MODULE) \ $(DELL_S5296F_PLATFORM_MODULE) \ $(DELL_Z9100_PLATFORM_MODULE) \ $(DELL_S6100_PLATFORM_MODULE) \ + $(DELL_N3248TE_PLATFORM_MODULE) \ $(INGRASYS_S8900_54XC_PLATFORM_MODULE) \ $(INGRASYS_S8900_64XC_PLATFORM_MODULE) \ $(INGRASYS_S9100_PLATFORM_MODULE) \ diff --git a/platform/broadcom/platform-modules-dell.mk b/platform/broadcom/platform-modules-dell.mk index 90eb4fc20b5a..4e0363772a6a 100644 --- a/platform/broadcom/platform-modules-dell.mk +++ b/platform/broadcom/platform-modules-dell.mk @@ -8,6 +8,7 @@ DELL_S5232F_PLATFORM_MODULE_VERSION = 1.1 DELL_Z9332F_PLATFORM_MODULE_VERSION = 1.1 DELL_S5248F_PLATFORM_MODULE_VERSION = 1.1 DELL_S5296F_PLATFORM_MODULE_VERSION = 1.1 +DELL_N3248TE_PLATFORM_MODULE_VERSION = 1.1 export DELL_S6000_PLATFORM_MODULE_VERSION export DELL_Z9100_PLATFORM_MODULE_VERSION @@ -17,6 +18,7 @@ export DELL_S5232F_PLATFORM_MODULE_VERSION export DELL_Z9332F_PLATFORM_MODULE_VERSION export DELL_S5248F_PLATFORM_MODULE_VERSION export DELL_S5296F_PLATFORM_MODULE_VERSION +export DELL_N3248TE_PLATFORM_MODULE_VERSION DELL_Z9100_PLATFORM_MODULE = platform-modules-z9100_$(DELL_Z9100_PLATFORM_MODULE_VERSION)_amd64.deb $(DELL_Z9100_PLATFORM_MODULE)_SRC_PATH = $(PLATFORM_PATH)/sonic-platform-modules-dell @@ -49,6 +51,10 @@ DELL_S5248F_PLATFORM_MODULE = platform-modules-s5248f_$(DELL_S5248F_PLATFORM_MOD $(DELL_S5248F_PLATFORM_MODULE)_PLATFORM = x86_64-dellemc_s5248f_c3538-r0 $(eval $(call add_extra_package,$(DELL_Z9100_PLATFORM_MODULE),$(DELL_S5248F_PLATFORM_MODULE))) +DELL_N3248TE_PLATFORM_MODULE = platform-modules-n3248te_$(DELL_N3248TE_PLATFORM_MODULE_VERSION)_amd64.deb +$(DELL_N3248TE_PLATFORM_MODULE)_PLATFORM = x86_64-dellemc_n3248te_c3338-r0 +$(eval $(call add_extra_package,$(DELL_Z9100_PLATFORM_MODULE),$(DELL_N3248TE_PLATFORM_MODULE))) + DELL_S5296F_PLATFORM_MODULE = platform-modules-s5296f_$(DELL_S5296F_PLATFORM_MODULE_VERSION)_amd64.deb $(DELL_S5296F_PLATFORM_MODULE)_PLATFORM = x86_64-dellemc_s5296f_c3538-r0 $(eval $(call add_extra_package,$(DELL_Z9100_PLATFORM_MODULE),$(DELL_S5296F_PLATFORM_MODULE))) diff --git a/platform/broadcom/sonic-platform-modules-dell/debian/control b/platform/broadcom/sonic-platform-modules-dell/debian/control index 2920602fcd60..85585a5cf122 100644 --- a/platform/broadcom/sonic-platform-modules-dell/debian/control +++ b/platform/broadcom/sonic-platform-modules-dell/debian/control @@ -35,6 +35,11 @@ Architecture: amd64 Depends: linux-image-4.19.0-12-2-amd64-unsigned Description: kernel modules for platform devices such as fan, led, sfp +Package: platform-modules-n3248te +Architecture: amd64 +Depends: linux-image-4.19.0-12-2-amd64-unsigned +Description: kernel modules for platform devices such as fan, led, sfp + Package: platform-modules-z9332f Architecture: amd64 Depends: linux-image-4.19.0-12-2-amd64-unsigned diff --git a/platform/broadcom/sonic-platform-modules-dell/debian/platform-modules-n3248te.init b/platform/broadcom/sonic-platform-modules-dell/debian/platform-modules-n3248te.init new file mode 100755 index 000000000000..823e0708e8f8 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-dell/debian/platform-modules-n3248te.init @@ -0,0 +1,39 @@ +#!/bin/bash + +### BEGIN INIT INFO +# Provides: setup-board +# Required-Start: +# Required-Stop: +# Should-Start: +# Should-Stop: +# Default-Start: S +# Default-Stop: 0 6 +# Short-Description: Setup S3000 board. +### END INIT INFO + +case "$1" in +start) + echo -n "Setting up board... " + + /usr/local/bin/n3248te_platform.sh init + + echo "done." + ;; + +stop) + /usr/local/bin/n3248te_platform.sh deinit + echo "done." + + ;; + +force-reload|restart) + echo "Not supported" + ;; + +*) + echo "Usage: /etc/init.d/platform-modules-n3248te.init {start|stop}" + exit 1 + ;; +esac + +exit 0 diff --git a/platform/broadcom/sonic-platform-modules-dell/debian/platform-modules-n3248te.install b/platform/broadcom/sonic-platform-modules-dell/debian/platform-modules-n3248te.install new file mode 100644 index 000000000000..04fe8c5a337e --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-dell/debian/platform-modules-n3248te.install @@ -0,0 +1,12 @@ +n3248te/scripts/n3248te_platform.sh usr/local/bin +n3248te/scripts/platform_sensors.py usr/local/bin +n3248te/scripts/sensors usr/bin +n3248te/scripts//portiocfg.py usr/local/bin +n3248te/scripts//ports_xcvrd_notify.py usr/local/bin +n3248te/systemd/platform-modules-n3248te.service etc/systemd/system +n3248te/cfg/n3248te-modules.conf etc/modules-load.d +common/dell_i2c_utils.sh usr/local/bin +n3248te/modules/sonic_platform-1.0-py3-none-any.whl usr/share/sonic/device/x86_64-dellemc_n3248te_c3338-r0 +common/platform_reboot usr/share/sonic/device/x86_64-dellemc_n3248te_c3338-r0 +common/fw-updater /usr/local/bin +common/onie_mode_set usr/local/bin diff --git a/platform/broadcom/sonic-platform-modules-dell/debian/platform-modules-n3248te.postinst b/platform/broadcom/sonic-platform-modules-dell/debian/platform-modules-n3248te.postinst new file mode 100644 index 000000000000..7f787c2a328c --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-dell/debian/platform-modules-n3248te.postinst @@ -0,0 +1,7 @@ +# postinst script for N3248TE + +# Enable Dell-N3248TE-platform-service +depmod -a +systemctl enable platform-modules-n3248te.service +systemctl start platform-modules-n3248te.service +#DEBHELPER# diff --git a/platform/broadcom/sonic-platform-modules-dell/debian/rules b/platform/broadcom/sonic-platform-modules-dell/debian/rules index 520331ed16d3..5bc62aba0891 100755 --- a/platform/broadcom/sonic-platform-modules-dell/debian/rules +++ b/platform/broadcom/sonic-platform-modules-dell/debian/rules @@ -5,7 +5,7 @@ export INSTALL_MOD_DIR:=extra KVERSION ?= $(shell uname -r) KERNEL_SRC := /lib/modules/$(KVERSION) MOD_SRC_DIR:= $(shell pwd) -MODULE_DIRS:= s6000 z9100 s6100 z9264f s5232f s5248f z9332f s5296f +MODULE_DIRS:= s6000 z9100 s6100 z9264f s5232f s5248f z9332f s5296f n3248te COMMON_DIR := common %: @@ -50,6 +50,11 @@ override_dh_auto_build: cd $(MOD_SRC_DIR)/$${mod}; \ python3 setup.py bdist_wheel -d $(MOD_SRC_DIR)/$${mod}/modules; \ cd $(MOD_SRC_DIR); \ + elif [ $$mod = "n3248te" ]; then \ + cp $(COMMON_DIR)/ipmihelper.py $(MOD_SRC_DIR)/$${mod}/sonic_platform/ipmihelper.py; \ + cd $(MOD_SRC_DIR)/$${mod}; \ + python3 setup.py bdist_wheel -d $(MOD_SRC_DIR)/$${mod}/modules; \ + cd $(MOD_SRC_DIR); \ elif [ $$mod = "z9332f" ]; then \ cp $(COMMON_DIR)/ipmihelper.py $(MOD_SRC_DIR)/$${mod}/sonic_platform/ipmihelper.py; \ cd $(MOD_SRC_DIR)/$${mod}; \ @@ -118,6 +123,11 @@ override_dh_clean: rm -f $(MOD_SRC_DIR)/$${mod}/modules/*.whl; \ rm -rf $(MOD_SRC_DIR)/$${mod}/build; \ rm -rf $(MOD_SRC_DIR)/$${mod}/build/*.egg-info; \ + elif [ $$mod = "n3248te" ]; then \ + rm -f $(MOD_SRC_DIR)/$${mod}/sonic_platform/ipmihelper.py; \ + rm -f $(MOD_SRC_DIR)/$${mod}/modules/*.whl; \ + rm -rf $(MOD_SRC_DIR)/$${mod}/build; \ + rm -rf $(MOD_SRC_DIR)/$${mod}/build/*.egg-info; \ fi; \ make -C $(KERNEL_SRC)/build M=$(MOD_SRC_DIR)/$${mod}/modules clean; \ done); \ diff --git a/platform/broadcom/sonic-platform-modules-dell/n3248te/cfg/n3248te-modules.conf b/platform/broadcom/sonic-platform-modules-dell/n3248te/cfg/n3248te-modules.conf new file mode 100644 index 000000000000..923b364b375e --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-dell/n3248te/cfg/n3248te-modules.conf @@ -0,0 +1,14 @@ +# /etc/modules: kernel modules to load at boot time. +# +# This file contains the names of kernel modules that should be loaded +# at boot time, one per line. Lines beginning with "#" are ignored. + +i2c-isch +i2c-ismt +i2c-dev +i2c-mux +i2c-smbus + +i2c-mux-pca954x +dell_n3248te_platform + diff --git a/platform/broadcom/sonic-platform-modules-dell/n3248te/modules/Makefile b/platform/broadcom/sonic-platform-modules-dell/n3248te/modules/Makefile new file mode 100644 index 000000000000..2ce4d5b5e963 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-dell/n3248te/modules/Makefile @@ -0,0 +1,2 @@ +obj-m := dell_n3248te_platform.o emc2305.o + diff --git a/platform/broadcom/sonic-platform-modules-dell/n3248te/modules/dell_n3248te_platform.c b/platform/broadcom/sonic-platform-modules-dell/n3248te/modules/dell_n3248te_platform.c new file mode 100644 index 000000000000..aa6a6672b552 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-dell/n3248te/modules/dell_n3248te_platform.c @@ -0,0 +1,1236 @@ +/* Copyright (c) 2020 Dell Inc. + * dell_n3248te_platform.c - Driver for N3248TE switches + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ + #include + #include + #include + #include + #include + #include + #include + #include + #include + #include + #include + + #define PSU_MODULE_BASE_NR 10 + #define FANTRAY_MODULE_BASE_NR 15 + #define SFP_MODULE_BASE_NR 20 + #define SFP_MUX_BASE_NR 8 + #define FANTRAY_MUX_BASE_NR 4 + #define PSU_MUX_BASE_NR 5 + + #define PHY_RESET_REG 0x40 + #define RESET_ALL_PHY 0x7F + #define SYS_CTRL_REG 0x15 + #define POWER_CYCLE_SYS 0x1 + #define CPLD_DEVICE_NUM 2 + #define PF_MUX_DEVICES 3 + + #define FAN_0 0 + #define FAN_1 1 + #define FAN_2 2 + + static void device_release(struct device *dev) + { + return; + } + + /* + * N3248TE CPLD + */ + + enum cpld_type { + cpu_cpld, + sys_cpld, + }; + + struct cpld_platform_data { + int reg_addr; + struct i2c_client *client; + }; + + static struct cpld_platform_data n3248te_cpld_platform_data[] = { + [cpu_cpld] = { + .reg_addr = 0x31, + }, + + [sys_cpld] = { + .reg_addr = 0x32, + }, + }; + + static struct platform_device n3248te_cpld = { + .name = "dell-n3248te-cpld", + .id = 0, + .dev = { + .platform_data = n3248te_cpld_platform_data, + .release = device_release + }, + }; + + /* + * N3248TE MUX + */ + + struct mux_platform_data { + int parent; + int base_nr; + int reg_addr; + struct i2c_client *cpld; + int no_of_buses; + int mux_offset; + }; + + struct pf_mux { + struct mux_platform_data data; + }; + + static struct mux_platform_data n3248te_mux_platform_data[] = { + { + .parent = SFP_MUX_BASE_NR, + .base_nr = SFP_MODULE_BASE_NR, + .cpld = NULL, + .reg_addr = 0x11, + .no_of_buses = 6, + .mux_offset = 1, + }, + { + .parent = FANTRAY_MUX_BASE_NR, + .base_nr = FANTRAY_MODULE_BASE_NR, + .cpld = NULL, + .reg_addr = 0x13, + .no_of_buses = 3, + .mux_offset = 1, + }, + { + .parent = PSU_MUX_BASE_NR, + .base_nr = PSU_MODULE_BASE_NR, + .cpld = NULL, + .reg_addr = 0x12, + .no_of_buses = 2, + .mux_offset = 1, + }, + }; + + static struct platform_device n3248te_mux[] = { + { + .name = "dell-n3248te-mux", + .id = 0, + .dev = { + .platform_data = &n3248te_mux_platform_data[0], + .release = device_release, + }, + }, + { + .name = "dell-n3248te-mux", + .id = 1, + .dev = { + .platform_data = &n3248te_mux_platform_data[1], + .release = device_release, + }, + }, + { + .name = "dell-n3248te-mux", + .id = 2, + .dev = { + .platform_data = &n3248te_mux_platform_data[2], + .release = device_release, + }, + }, + }; + + static int cpld_reg_write_byte(struct i2c_client *client, u8 regaddr, u8 val) + { + union i2c_smbus_data data; + + data.byte = val; + return client->adapter->algo->smbus_xfer(client->adapter, client->addr, + client->flags, + I2C_SMBUS_WRITE, + regaddr, I2C_SMBUS_BYTE_DATA, &data); + } + + static int mux_select(struct i2c_mux_core *muxc, u32 chan) + { + struct pf_mux *mux = i2c_mux_priv(muxc); + u8 chan_data = chan + mux->data.mux_offset; + + return cpld_reg_write_byte(mux->data.cpld, mux->data.reg_addr, chan_data); + } + + static int __init mux_probe(struct platform_device *pdev) + { + struct i2c_mux_core *muxc; + struct pf_mux *mux; + struct mux_platform_data *pdata; + struct i2c_adapter *parent; + int i, ret; + + pdata = pdev->dev.platform_data; + if (!pdata) { + dev_err(&pdev->dev, "Missing platform data\n"); + return -ENODEV; + } + + mux = devm_kzalloc(&pdev->dev, sizeof(*mux), GFP_KERNEL); + if (!mux) { + return -ENOMEM; + } + + mux->data = *pdata; + + parent = i2c_get_adapter(pdata->parent); + if (!parent) { + dev_err(&pdev->dev, "Parent adapter (%d) not found\n", + pdata->parent); + return -EPROBE_DEFER; + } + + muxc = i2c_mux_alloc(parent, &pdev->dev, pdata->no_of_buses, 0, 0, + mux_select, NULL); + if (!muxc) { + ret = -ENOMEM; + goto alloc_failed; + } + muxc->priv = mux; + + platform_set_drvdata(pdev, muxc); + + for (i = 0; i < pdata->no_of_buses; i++) { + int nr = pdata->base_nr + i; + unsigned int class = 0; + + ret = i2c_mux_add_adapter(muxc, nr, i, class); + if (ret) { + dev_err(&pdev->dev, "Failed to add adapter %d\n", i); + goto add_adapter_failed; + } + } + + return 0; + + add_adapter_failed: + i2c_mux_del_adapters(muxc); + alloc_failed: + i2c_put_adapter(parent); + + return ret; + } + + static int mux_remove(struct platform_device *pdev) + { + struct i2c_mux_core *muxc = platform_get_drvdata(pdev); + + i2c_mux_del_adapters(muxc); + + i2c_put_adapter(muxc->parent); + + return 0; + } + + static struct platform_driver mux_driver = { + .probe = mux_probe, + .remove = mux_remove, + .driver = { + .owner = THIS_MODULE, + .name = "dell-n3248te-mux", + }, + }; + + static ssize_t sfp_txdis_show (struct device *dev, struct device_attribute *devattr, char *buf) + { + s32 ret = 0; + struct cpld_platform_data *pdata = dev->platform_data; + + ret = i2c_smbus_read_byte_data(pdata[sys_cpld].client, 0x31); + if (ret < 0) + return sprintf(buf, "read error"); + + return sprintf(buf, "0x%x\n", (u8)ret); + } + + static ssize_t sfp_txdis_store (struct device *dev, struct device_attribute *devattr, const char *buf, size_t size) + { + long value; + struct cpld_platform_data *pdata = dev->platform_data; + s32 ret; + u8 data; + ssize_t status; + + status = kstrtol(buf, 0, &value); + if (status == 0) { + ret = i2c_smbus_read_byte_data(pdata[sys_cpld].client, 0x31); + if (ret < 0) + return ret; + data = (u8)ret & ~(0x0F); + data = data | (value & 0x0F); + + ret = i2c_smbus_write_byte_data(pdata[sys_cpld].client, 0x31, data); + if (ret < 0) + return ret; + + status = size; + } + + return status; + } + + static ssize_t sfp_rxlos_show (struct device *dev, struct device_attribute *devattr, char *buf) + { + s32 ret = 0; + struct cpld_platform_data *pdata = dev->platform_data; + + ret = i2c_smbus_read_byte_data(pdata[sys_cpld].client, 0x32); + if (ret < 0) + return sprintf(buf, "read error"); + + return sprintf(buf, "0x%x\n", (u8)ret); + } + + static ssize_t sfp_txfault_show (struct device *dev, struct device_attribute *devattr, char *buf) + { + s32 ret = 0; + struct cpld_platform_data *pdata = dev->platform_data; + + ret = i2c_smbus_read_byte_data(pdata[sys_cpld].client, 0x33); + if (ret < 0) + return sprintf(buf, "read error"); + + return sprintf(buf, "0x%x\n", (u8)ret); + } + + static ssize_t sfp_modprs_show (struct device *dev, struct device_attribute *devattr, char *buf) + { + s32 ret = 0; + struct cpld_platform_data *pdata = dev->platform_data; + + ret = i2c_smbus_read_byte_data(pdata[sys_cpld].client, 0x30); + if (ret < 0) + return sprintf(buf, "read error"); + + return sprintf(buf, "0x%x\n", (u8)ret); + } + + static ssize_t qsfp_modprs_show (struct device *dev, struct device_attribute *devattr, char *buf) + { + s32 ret = 0; + struct cpld_platform_data *pdata = dev->platform_data; + + ret = i2c_smbus_read_byte_data(pdata[sys_cpld].client, 0x20); + if (ret < 0) + return sprintf(buf, "read error"); + + return sprintf(buf, "0x%x\n", (u8)ret); + } + + static ssize_t qsfp_rst_show (struct device *dev, struct device_attribute *devattr, char *buf) + { + s32 ret = 0; + struct cpld_platform_data *pdata = dev->platform_data; + + ret = i2c_smbus_read_byte_data(pdata[sys_cpld].client, 0x21); + if (ret < 0) + return sprintf(buf, "read error"); + + return sprintf(buf, "0x%x\n", (u8)ret); + } + + static ssize_t reboot_cause_show (struct device *dev, struct device_attribute *devattr, char *buf) + { + s32 ret = 0; + u8 data; + struct cpld_platform_data *pdata = dev->platform_data; + + ret = i2c_smbus_read_byte_data(pdata[sys_cpld].client, 0x10); + if (ret < 0) + return sprintf(buf, "read error"); + + data = (u8)ret; + return sprintf(buf, "0x%x\n", data); + } + + + static ssize_t power_reset_store(struct device *dev, struct device_attribute *devattr, const char *buf, size_t count) + { + unsigned long data; + s32 err; + struct cpld_platform_data *pdata = dev->platform_data; + + err = kstrtoul(buf, 10, &data); + if (err) + return err; + + if (data) + { + i2c_smbus_write_byte_data(pdata[sys_cpld].client, SYS_CTRL_REG, (u8)(POWER_CYCLE_SYS)); + } + + return count; + } + + static ssize_t power_reset_show(struct device *dev, struct device_attribute *devattr, char *buf) + { + s32 ret = 0; + struct cpld_platform_data *pdata = dev->platform_data; + + ret = i2c_smbus_read_byte_data(pdata[sys_cpld].client, SYS_CTRL_REG); + if (ret < 0) + return sprintf(buf, "read error"); + + return sprintf(buf, "0x%x\n", ret); + } + + static ssize_t fan_dir_show(struct device *dev, struct device_attribute *devattr, char *buf) + { + s32 ret; + u8 data = 0; + struct cpld_platform_data *pdata = dev->platform_data; + struct sensor_device_attribute *sa = to_sensor_dev_attr(devattr); + int index = sa->index; + u8 mask = 1 << (index+4); + + ret = i2c_smbus_read_byte_data(pdata[sys_cpld].client, 0xA); + if (ret < 0) + return sprintf(buf, "read error"); + data = (u8)((ret & mask) >> (index+4)); + + return sprintf(buf, "%s\n", data? "B2F" : "F2B"); +} + +static ssize_t fan_prs_show(struct device *dev, struct device_attribute *devattr, char *buf) +{ + s32 ret; + u8 data = 0; + struct cpld_platform_data *pdata = dev->platform_data; + struct sensor_device_attribute *sa = to_sensor_dev_attr(devattr); + int index = sa->index; + uint8_t mask = 1 << index; + + ret = i2c_smbus_read_byte_data(pdata[sys_cpld].client, 0xA); + if (ret < 0) + return sprintf(buf, "read error"); + data = (u32)((ret & mask) >> index); + + data = ~data & 0x1; + + return sprintf(buf, "0x%x\n", data); +} + +static ssize_t psu0_prs_show(struct device *dev, struct device_attribute *devattr, char *buf) +{ + s32 ret; + u8 data = 0; + struct cpld_platform_data *pdata = dev->platform_data; + + ret = i2c_smbus_read_byte_data(pdata[sys_cpld].client, 0xC); + if (ret < 0) + return sprintf(buf, "read error"); + + if (!(ret & 0x80)) + data = 1; + + return sprintf(buf, "%d\n", data); +} + +static ssize_t psu1_prs_show(struct device *dev, struct device_attribute *devattr, char *buf) +{ + s32 ret; + u8 data = 0; + struct cpld_platform_data *pdata = dev->platform_data; + + ret = i2c_smbus_read_byte_data(pdata[sys_cpld].client, 0xC); + if (ret < 0) + return sprintf(buf, "read error"); + + if (!(ret & 0x08)) + data = 1; + + return sprintf(buf, "%d\n", data); +} + +static ssize_t psu0_status_show(struct device *dev, struct device_attribute *devattr, char *buf) +{ + s32 ret; + u8 data = 0; + struct cpld_platform_data *pdata = dev->platform_data; + + ret = i2c_smbus_read_byte_data(pdata[sys_cpld].client, 0xC); + if (ret < 0) + return sprintf(buf, "read error"); + + if ((ret & 0x40)) + data = 1; + + return sprintf(buf, "%d\n", data); +} + +static ssize_t psu1_status_show(struct device *dev, struct device_attribute *devattr, char *buf) +{ + s32 ret; + u8 data = 0; + struct cpld_platform_data *pdata = dev->platform_data; + + ret = i2c_smbus_read_byte_data(pdata[sys_cpld].client, 0xC); + if (ret < 0) + return sprintf(buf, "read error"); + + if ((ret & 0x04)) + data = 1; + + return sprintf(buf, "%d\n", data); +} + +static ssize_t fani_led_show(struct device *dev, struct device_attribute *devattr, char *buf) +{ + s32 ret; + u8 data = 0; + struct cpld_platform_data *pdata = dev->platform_data; + struct sensor_device_attribute *sa = to_sensor_dev_attr(devattr); + int index = sa->index; + uint8_t mask = 3 << (index*2); + + ret = i2c_smbus_read_byte_data(pdata[sys_cpld].client, 0x9); + if (ret < 0) + return sprintf(buf, "read error"); + + data = (u32)(ret & mask) >> (index*2); + + switch (data) + { + case 0: + ret = sprintf(buf, "off\n"); + break; + case 1: + ret = sprintf(buf, "green\n"); + break; + case 2: + ret = sprintf(buf, "yellow\n"); + break; + default: + ret = sprintf(buf, "unknown\n"); + } + + return ret; +} + +static ssize_t fani_led_store(struct device *dev, struct device_attribute *devattr, const char *buf, size_t count) +{ + s32 ret; + u8 mask, data = 0; + struct cpld_platform_data *pdata = dev->platform_data; + struct sensor_device_attribute *sa = to_sensor_dev_attr(devattr); + int index = sa->index; + + if (!strncmp(buf, "off", 3)) + { + data = 0; + } + else if (!strncmp(buf, "yellow", 6)) + { + data = 2; + } + else if (!strncmp(buf, "green", 5)) + { + data = 1; + } + else + { + return -1; + } + + + mask = ~((uint8_t)(3 << (index*2))); + ret = i2c_smbus_read_byte_data(pdata[sys_cpld].client, 0x9); + if (ret < 0) + return ret; + + ret = i2c_smbus_write_byte_data(pdata[sys_cpld].client, 0x9, (u8)((ret & mask) | (data << (index * 2)))); + if (ret < 0) + return ret; + + return count; +} + +static ssize_t system_led_show(struct device *dev, struct device_attribute *devattr, char *buf) +{ + s32 ret; + u8 data = 0; + struct cpld_platform_data *pdata = dev->platform_data; + + ret = i2c_smbus_read_byte_data(pdata[sys_cpld].client, 0x7); + if (ret < 0) + return sprintf(buf, "read error"); + + data = (u8)(ret & 0x30) >> 5; + + switch (data) + { + case 0: + ret = sprintf(buf, "blink_green\n"); + break; + case 1: + ret = sprintf(buf, "green\n"); + break; + case 2: + ret = sprintf(buf, "yellow\n"); + break; + default: + ret = sprintf(buf, "blink_yellow\n"); + } + + return ret; +} + +static ssize_t system_led_store(struct device *dev, struct device_attribute *devattr, const char *buf, size_t count) +{ + s32 ret; + u8 data = 0; + struct cpld_platform_data *pdata = dev->platform_data; + + if (!strncmp(buf, "blink_green", 11)) + { + data = 0; + } + else if (!strncmp(buf, "green", 5)) + { + data = 1; + } + else if (!strncmp(buf, "yellow", 6)) + { + data = 2; + } + else if (!strncmp(buf, "blink_yellow", 12)) + { + data = 3; + } + else + { + return -1; + } + + ret = i2c_smbus_read_byte_data(pdata[sys_cpld].client, 0x7); + if (ret < 0) + return ret; + + ret = i2c_smbus_write_byte_data(pdata[sys_cpld].client, 0x7, (u8)((ret & 0xCF) | (data << 4))); + if (ret < 0) + return ret; + + return count; +} + +static ssize_t locator_led_show(struct device *dev, struct device_attribute *devattr, char *buf) +{ + s32 ret; + u8 data = 0; + struct cpld_platform_data *pdata = dev->platform_data; + + ret = i2c_smbus_read_byte_data(pdata[sys_cpld].client, 0x7); + if (ret < 0) + return sprintf(buf, "read error"); + + data = (u32)(ret & 0x08) >> 3; + + switch (data) + { + case 0: + ret = sprintf(buf, "off\n"); + break; + case 1: + ret = sprintf(buf, "blink_blue\n"); + break; + default: + ret = sprintf(buf, "invalid\n"); + } + + return ret; +} + +static ssize_t locator_led_store(struct device *dev, struct device_attribute *devattr, const char *buf, size_t count) +{ + s32 ret; + u8 data = 0; + struct cpld_platform_data *pdata = dev->platform_data; + + if (!strncmp(buf, "off", 3)) + { + data = 0; + } + else if (!strncmp(buf, "blink_blue", 10)) + { + data = 1; + } + else + { + return -1; + } + + ret = i2c_smbus_read_byte_data(pdata[sys_cpld].client, 0x7); + if (ret < 0) + return ret; + + ret = i2c_smbus_write_byte_data(pdata[sys_cpld].client, 0x7, (u8)((ret & 0xF7) | (data << 3))); + if (ret < 0) + return ret; + + return count; +} + +static ssize_t power_led_show(struct device *dev, struct device_attribute *devattr, char *buf) +{ + s32 ret; + u8 data = 0; + struct cpld_platform_data *pdata = dev->platform_data; + + ret = i2c_smbus_read_byte_data(pdata[sys_cpld].client, 0x7); + if (ret < 0) + return sprintf(buf, "read error"); + + data = (u32)(ret & 0x06) >> 1; + + switch (data) + { + case 0: + ret = sprintf(buf, "off\n"); + break; + case 1: + ret = sprintf(buf, "yellow\n"); + break; + case 2: + ret = sprintf(buf, "green\n"); + break; + default: + ret = sprintf(buf, "blink_yellow\n"); + } + + return ret; +} + +static ssize_t power_led_store(struct device *dev, struct device_attribute *devattr, const char *buf, size_t count) +{ + s32 ret; + u8 data = 0; + struct cpld_platform_data *pdata = dev->platform_data; + + if (!strncmp(buf, "off", 3)) + { + data = 0; + } + else if (!strncmp(buf, "yellow", 6)) + { + data = 1; + } + else if (!strncmp(buf, "green", 5)) + { + data = 2; + } + else if (!strncmp(buf, "blink_yellow", 12)) + { + data = 3; + } + else + { + return -1; + } + + ret = i2c_smbus_read_byte_data(pdata[sys_cpld].client, 0x7); + if (ret < 0) + return ret; + + ret = i2c_smbus_write_byte_data(pdata[sys_cpld].client, 0x7, (u8)((ret & 0xF9) | (data << 1))); + if (ret < 0) + return ret; + + return count; +} + +static ssize_t master_led_show(struct device *dev, struct device_attribute *devattr, char *buf) +{ + s32 ret; + u8 data = 0; + struct cpld_platform_data *pdata = dev->platform_data; + + ret = i2c_smbus_read_byte_data(pdata[sys_cpld].client, 0x7); + if (ret < 0) + return sprintf(buf, "read error"); + + data = (u32)(ret & 0x1); + + switch (data) + { + case 0: + ret = sprintf(buf, "green\n"); + break; + default: + ret = sprintf(buf, "off\n"); + break; + } + + return ret; +} + +static ssize_t master_led_store(struct device *dev, struct device_attribute *devattr, const char *buf, size_t count) +{ + s32 ret; + u8 data = 0; + struct cpld_platform_data *pdata = dev->platform_data; + + if (!strncmp(buf, "green", 5)) + { + data = 0; + } + else if (!strncmp(buf, "off", 3)) + { + data = 1; + } + else + { + return -1; + } + + ret = i2c_smbus_read_byte_data(pdata[sys_cpld].client, 0x7); + if (ret < 0) + return ret; + + ret = i2c_smbus_write_byte_data(pdata[sys_cpld].client, 0x7, (u8)((ret & 0xFE) | data)); + if (ret < 0) + return ret; + + return count; +} + +static ssize_t fan_led_show(struct device *dev, struct device_attribute *devattr, char *buf) +{ + s32 ret; + u8 data = 0; + struct cpld_platform_data *pdata = dev->platform_data; + + ret = i2c_smbus_read_byte_data(pdata[sys_cpld].client, 0x7); + if (ret < 0) + return sprintf(buf, "read error"); + + data = (u8)(ret & 0xC0) >> 6; + + switch (data) + { + case 0: + ret = sprintf(buf, "off\n"); + break; + case 1: + ret = sprintf(buf, "yellow\n"); + break; + case 2: + ret = sprintf(buf, "green\n"); + break; + default: + ret = sprintf(buf, "blink_yellow\n"); + } + + return ret; +} + +static ssize_t fan_led_store(struct device *dev, struct device_attribute *devattr, const char *buf, size_t count) +{ + s32 ret; + u8 data = 0; + struct cpld_platform_data *pdata = dev->platform_data; + + if (!strncmp(buf, "off", 3)) + { + data = 0; + } + else if (!strncmp(buf, "yellow", 6)) + { + data = 1; + } + else if (!strncmp(buf, "green", 5)) + { + data = 2; + } + else if (!strncmp(buf, "blink_yellow", 12)) + { + data = 3; + } + else + { + return -1; + } + + ret = i2c_smbus_read_byte_data(pdata[sys_cpld].client, 0x7); + if (ret < 0) + return ret; + + ret = i2c_smbus_write_byte_data(pdata[sys_cpld].client, 0x7, (u8)((ret & 0x3F) | (data << 6))); + if (ret < 0) + return ret; + + return count; +} + + +static ssize_t power_good_show(struct device *dev, + struct device_attribute *devattr, char *buf) +{ + s32 ret; + u8 pwr_good1 = 0; + u8 pwr_good2 = 0; + struct cpld_platform_data *pdata = dev->platform_data; + + ret = i2c_smbus_read_byte_data(pdata[cpu_cpld].client, 0xc); + if (ret < 0) + return sprintf(buf, "read error"); + pwr_good1 = ret; + + ret = i2c_smbus_read_byte_data(pdata[cpu_cpld].client, 0xd); + if (ret < 0) + return sprintf(buf, "read error"); + pwr_good2 = ret; + + return sprintf(buf, "0x%x\n", (pwr_good1 == 0xFF && (pwr_good2 & 0x1F) == 0x1F)); +} + +static ssize_t sys_cpld_mjr_ver_show(struct device *dev, + struct device_attribute *devattr, char *buf) +{ + s32 ret; + u8 data = 0; + struct cpld_platform_data *pdata = dev->platform_data; + + ret = i2c_smbus_read_byte_data(pdata[sys_cpld].client, 0x1); + if (ret < 0) + return sprintf(buf, "read error"); + data = ret; + + return sprintf(buf, "0x%x\n", data); +} + +static ssize_t sys_cpld_mnr_ver_show(struct device *dev, + struct device_attribute *devattr, char *buf) +{ + s32 ret; + u8 data = 0; + struct cpld_platform_data *pdata = dev->platform_data; + + ret = i2c_smbus_read_byte_data(pdata[sys_cpld].client, 0x0); + if (ret < 0) + return sprintf(buf, "read error"); + data = ret; + + return sprintf(buf, "0x%x\n", data); +} + +static ssize_t cpu_cpld_mjr_ver_show(struct device *dev, + struct device_attribute *devattr, char *buf) +{ + s32 ret; + u8 data = 0; + struct cpld_platform_data *pdata = dev->platform_data; + + ret = i2c_smbus_read_byte_data(pdata[cpu_cpld].client, 0x1); + if (ret < 0) + return sprintf(buf, "read error"); + data = ret; + + return sprintf(buf, "0x%x\n", data); +} + +static ssize_t cpu_cpld_mnr_ver_show(struct device *dev, + struct device_attribute *devattr, char *buf) +{ + s32 ret; + u8 data = 0; + struct cpld_platform_data *pdata = dev->platform_data; + + ret = i2c_smbus_read_byte_data(pdata[cpu_cpld].client, 0x0); + if (ret < 0) + return sprintf(buf, "read error"); + data = ret; + + return sprintf(buf, "0x%x\n", data); +} + + +static DEVICE_ATTR_RO(sfp_txfault); +static DEVICE_ATTR_RO(sfp_modprs); +static DEVICE_ATTR_RO(qsfp_modprs); +static DEVICE_ATTR_RO(qsfp_rst); +static DEVICE_ATTR_RO(sfp_rxlos); +static DEVICE_ATTR_RW(sfp_txdis); +static DEVICE_ATTR_RO(reboot_cause); +static DEVICE_ATTR_RW(power_reset); +static DEVICE_ATTR_RO(psu0_prs); +static DEVICE_ATTR_RO(psu1_prs); +static DEVICE_ATTR_RO(psu0_status); +static DEVICE_ATTR_RO(psu1_status); +static DEVICE_ATTR_RW(system_led); +static DEVICE_ATTR_RW(locator_led); +static DEVICE_ATTR_RW(power_led); +static DEVICE_ATTR_RW(master_led); +static DEVICE_ATTR_RW(fan_led); +static DEVICE_ATTR_RO(power_good); +static DEVICE_ATTR_RO(sys_cpld_mjr_ver); +static DEVICE_ATTR_RO(sys_cpld_mnr_ver); +static DEVICE_ATTR_RO(cpu_cpld_mjr_ver); +static DEVICE_ATTR_RO(cpu_cpld_mnr_ver); + +static SENSOR_DEVICE_ATTR(fan0_dir, S_IRUGO, fan_dir_show, NULL, FAN_0); +static SENSOR_DEVICE_ATTR(fan1_dir, S_IRUGO, fan_dir_show, NULL, FAN_1); +static SENSOR_DEVICE_ATTR(fan2_dir, S_IRUGO, fan_dir_show, NULL, FAN_2); +static SENSOR_DEVICE_ATTR(fan0_prs, S_IRUGO, fan_prs_show, NULL, FAN_0); +static SENSOR_DEVICE_ATTR(fan1_prs, S_IRUGO, fan_prs_show, NULL, FAN_1); +static SENSOR_DEVICE_ATTR(fan2_prs, S_IRUGO, fan_prs_show, NULL, FAN_2); +static SENSOR_DEVICE_ATTR(fan0_led, S_IRUGO, fani_led_show, fani_led_store, FAN_0); +static SENSOR_DEVICE_ATTR(fan1_led, S_IRUGO, fani_led_show, fani_led_store, FAN_1); +static SENSOR_DEVICE_ATTR(fan2_led, S_IRUGO, fani_led_show, fani_led_store, FAN_2); + +static struct attribute *n3248te_cpld_attrs[] = { + &dev_attr_sfp_txdis.attr, + &dev_attr_sfp_rxlos.attr, + &dev_attr_sfp_txfault.attr, + &dev_attr_sfp_modprs.attr, + &dev_attr_qsfp_modprs.attr, + &dev_attr_qsfp_rst.attr, + &dev_attr_reboot_cause.attr, + &dev_attr_power_reset.attr, + &sensor_dev_attr_fan0_dir.dev_attr.attr, + &sensor_dev_attr_fan1_dir.dev_attr.attr, + &sensor_dev_attr_fan2_dir.dev_attr.attr, + &sensor_dev_attr_fan0_prs.dev_attr.attr, + &sensor_dev_attr_fan1_prs.dev_attr.attr, + &sensor_dev_attr_fan2_prs.dev_attr.attr, + &sensor_dev_attr_fan0_led.dev_attr.attr, + &sensor_dev_attr_fan1_led.dev_attr.attr, + &sensor_dev_attr_fan2_led.dev_attr.attr, + &dev_attr_psu0_prs.attr, + &dev_attr_psu1_prs.attr, + &dev_attr_psu0_status.attr, + &dev_attr_psu1_status.attr, + &dev_attr_system_led.attr, + &dev_attr_locator_led.attr, + &dev_attr_power_led.attr, + &dev_attr_master_led.attr, + &dev_attr_fan_led.attr, + &dev_attr_power_good.attr, + &dev_attr_sys_cpld_mjr_ver.attr, + &dev_attr_sys_cpld_mnr_ver.attr, + &dev_attr_cpu_cpld_mjr_ver.attr, + &dev_attr_cpu_cpld_mnr_ver.attr, + NULL, +}; + +static struct attribute_group n3248te_cpld_attr_grp = { + .attrs = n3248te_cpld_attrs, +}; + +static int get_ismt_base_nr(void) +{ + struct i2c_adapter *ismt_adap; + static int ismt_base_nr = -1; + + if (ismt_base_nr != -1) { + return ismt_base_nr; + } + for (ismt_base_nr = 0; ismt_base_nr < 2; ismt_base_nr++) { + ismt_adap = i2c_get_adapter(ismt_base_nr); + if (!ismt_adap) { + printk(KERN_WARNING "iSMT adapter (%d) not found\n", ismt_base_nr); + return -ENODEV; + } + if (!strstr(ismt_adap->name, "iSMT adapter")) { + i2c_put_adapter(ismt_adap); + printk("I2C %d adapter is %s\n", ismt_base_nr, ismt_adap->name); + } else { + i2c_put_adapter(ismt_adap); + return ismt_base_nr; + } + } + return -ENODEV; +} + +static int __init cpld_probe(struct platform_device *pdev) +{ + struct cpld_platform_data *pdata; + struct i2c_adapter *parent; + int i, cpld_bus; + int ret; + + pdata = pdev->dev.platform_data; + if (!pdata) { + dev_err(&pdev->dev, "Missing platform data\n"); + return -ENODEV; + } + + cpld_bus = get_ismt_base_nr(); + if (cpld_bus < 0) { + return -ENODEV; + } + parent = i2c_get_adapter(cpld_bus); + if (!parent) { + printk(KERN_WARNING "Parent adapter (%d) not found\n", cpld_bus); + return -ENODEV; + } + for (i = 0; i < CPLD_DEVICE_NUM; i++) { + pdata[i].client = i2c_new_dummy(parent, pdata[i].reg_addr); + if (!pdata[i].client) { + printk(KERN_WARNING "Fail to create dummy i2c client for addr %d\n", pdata[i].reg_addr); + goto error; + } + } + + ret = sysfs_create_group(&pdev->dev.kobj, &n3248te_cpld_attr_grp); + if (ret) + goto error; + + return 0; + +error: + i--; + for (; i >= 0; i--) { + if (pdata[i].client) { + i2c_unregister_device(pdata[i].client); + } + } + + i2c_put_adapter(parent); + + return -ENODEV; +} + +static int __exit cpld_remove(struct platform_device *pdev) +{ + int i; + struct i2c_adapter *parent = NULL; + struct cpld_platform_data *pdata = pdev->dev.platform_data; + + sysfs_remove_group(&pdev->dev.kobj, &n3248te_cpld_attr_grp); + + if (!pdata) { + dev_err(&pdev->dev, "Missing platform data\n"); + } else { + for (i = 0; i < CPLD_DEVICE_NUM; i++) { + if (pdata[i].client) { + if (!parent) { + parent = (pdata[i].client)->adapter; + } + i2c_unregister_device(pdata[i].client); + } + } + } + + i2c_put_adapter(parent); + + return 0; +} + +static struct platform_driver cpld_driver = { + .probe = cpld_probe, + .remove = __exit_p(cpld_remove), + .driver = { + .owner = THIS_MODULE, + .name = "dell-n3248te-cpld", + }, +}; + +static struct i2c_board_info sys_board_mux[] = { + { + I2C_BOARD_INFO("pca9548", 0x71) + } +}; + +static int __init dell_n3248te_platform_init(void) +{ + int ret = 0; + struct i2c_adapter *sys_i2c_adap; + struct i2c_client *mux_i2c_cli; + struct cpld_platform_data *cpld_pdata; + struct mux_platform_data *pdata; + int i, sys_i2c_bus; + + printk("dell_n3248te_platform module initialization\n"); + sys_i2c_bus = get_ismt_base_nr(); + if (sys_i2c_bus < 0) { + return -ENODEV; + } + + sys_i2c_adap = i2c_get_adapter(sys_i2c_bus); + mux_i2c_cli = i2c_new_device(sys_i2c_adap, sys_board_mux); + if (!mux_i2c_cli) + return PTR_ERR_OR_ZERO(mux_i2c_cli); + + ret = platform_driver_register(&cpld_driver); + if (ret) { + printk(KERN_WARNING "Fail to register cpld driver\n"); + goto error_cpld_driver; + } + + ret = platform_driver_register(&mux_driver); + if (ret) { + printk(KERN_WARNING "Fail to register mux driver\n"); + goto error_mux_driver; + } + + ret = platform_device_register(&n3248te_cpld); + if (ret) { + printk(KERN_WARNING "Fail to create cpld device\n"); + goto error_cpld; + } + + cpld_pdata = n3248te_cpld.dev.platform_data; + + for (i = 0; i < PF_MUX_DEVICES; i++) { + pdata = n3248te_mux[i].dev.platform_data; + pdata->cpld = cpld_pdata[sys_cpld].client; + ret = platform_device_register(&n3248te_mux[i]); + if (ret) { + printk(KERN_WARNING "fail to create mux %d\n", i); + goto error_mux; + } + } + ret = i2c_smbus_write_byte_data(cpld_pdata[sys_cpld].client, PHY_RESET_REG, RESET_ALL_PHY); + if (ret) + goto error_mux; + + return 0; + +error_mux: + i--; + for (; i >= 0; i--) { + platform_device_unregister(&n3248te_mux[i]); + } + platform_device_unregister(&n3248te_cpld); +error_cpld: + platform_driver_unregister(&mux_driver); +error_mux_driver: + platform_driver_unregister(&cpld_driver); +error_cpld_driver: + return ret; +} + +static void __exit dell_n3248te_platform_exit(void) +{ + int i; + + for (i = 0; i < PF_MUX_DEVICES; i++) + platform_device_unregister(&n3248te_mux[i]); + platform_device_unregister(&n3248te_cpld); + platform_driver_unregister(&cpld_driver); + platform_driver_unregister(&mux_driver); +} + +module_init(dell_n3248te_platform_init); +module_exit(dell_n3248te_platform_exit); + +MODULE_DESCRIPTION("DELL N3248TE Platform Support"); +MODULE_AUTHOR("Dhanakumar Subramanian "); +MODULE_LICENSE("GPL"); diff --git a/platform/broadcom/sonic-platform-modules-dell/n3248te/modules/emc2305.c b/platform/broadcom/sonic-platform-modules-dell/n3248te/modules/emc2305.c new file mode 100644 index 000000000000..f08033e080ce --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-dell/n3248te/modules/emc2305.c @@ -0,0 +1,877 @@ +/* + * emc2305.c - hwmon driver for SMSC EMC2305 fan controller + * (C) Copyright 2013 + * Reinhard Pfau, Guntermann & Drunck GmbH + * + * Based on emc2103 driver by SMSC. + * + * Datasheet available at: + * http://www.smsc.com/Downloads/SMSC/Downloads_Public/Data_Sheets/2305.pdf + * + * Also supports the EMC2303 fan controller which has the same functionality + * and register layout as EMC2305, but supports only up to 3 fans instead of 5. + * + * Also supports EMC2302 (up to 2 fans) and EMC2301 (1 fan) fan controller. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +/* + * TODO / IDEAS: + * - expose more of the configuration and features + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/* + * Addresses scanned. + * Listed in the same order as they appear in the EMC2305, EMC2303 data sheets. + * + * Note: these are the I2C adresses which are possible for EMC2305 and EMC2303 + * chips. + * The EMC2302 supports only 0x2e (EMC2302-1) and 0x2f (EMC2302-2). + * The EMC2301 supports only 0x2f. + */ +static const unsigned short i2c_adresses[] = { + 0x2E, + 0x2F, + 0x2C, + 0x2D, + 0x4C, + 0x4D, + I2C_CLIENT_END +}; + +/* + * global registers + */ +enum { + REG_CONFIGURATION = 0x20, + REG_FAN_STATUS = 0x24, + REG_FAN_STALL_STATUS = 0x25, + REG_FAN_SPIN_STATUS = 0x26, + REG_DRIVE_FAIL_STATUS = 0x27, + REG_FAN_INTERRUPT_ENABLE = 0x29, + REG_PWM_POLARITY_CONFIG = 0x2a, + REG_PWM_OUTPUT_CONFIG = 0x2b, + REG_PWM_BASE_FREQ_1 = 0x2c, + REG_PWM_BASE_FREQ_2 = 0x2d, + REG_SOFTWARE_LOCK = 0xef, + REG_PRODUCT_FEATURES = 0xfc, + REG_PRODUCT_ID = 0xfd, + REG_MANUFACTURER_ID = 0xfe, + REG_REVISION = 0xff +}; + +/* + * fan specific registers + */ +enum { + REG_FAN_SETTING = 0x30, + REG_PWM_DIVIDE = 0x31, + REG_FAN_CONFIGURATION_1 = 0x32, + REG_FAN_CONFIGURATION_2 = 0x33, + REG_GAIN = 0x35, + REG_FAN_SPIN_UP_CONFIG = 0x36, + REG_FAN_MAX_STEP = 0x37, + REG_FAN_MINIMUM_DRIVE = 0x38, + REG_FAN_VALID_TACH_COUNT = 0x39, + REG_FAN_DRIVE_FAIL_BAND_LOW = 0x3a, + REG_FAN_DRIVE_FAIL_BAND_HIGH = 0x3b, + REG_TACH_TARGET_LOW = 0x3c, + REG_TACH_TARGET_HIGH = 0x3d, + REG_TACH_READ_HIGH = 0x3e, + REG_TACH_READ_LOW = 0x3f, +}; + +#define SEL_FAN(fan, reg) (reg + fan * 0x10) + +/* + * Factor by equations [2] and [3] from data sheet; valid for fans where the + * number of edges equals (poles * 2 + 1). + */ +#define FAN_RPM_FACTOR 3932160 + + +struct emc2305_fan_data { + bool enabled; + bool valid; + unsigned long last_updated; + bool rpm_control; + u8 multiplier; + u8 poles; + u16 target; + u16 tach; + u16 rpm_factor; + u8 pwm; +}; + +struct emc2305_data { + struct device *hwmon_dev; + struct mutex update_lock; + int fans; + struct emc2305_fan_data fan[5]; +}; + +static int read_u8_from_i2c(struct i2c_client *client, u8 i2c_reg, u8 *output) +{ + int status = i2c_smbus_read_byte_data(client, i2c_reg); + if (status < 0) { + dev_warn(&client->dev, "reg 0x%02x, err %d\n", + i2c_reg, status); + } else { + *output = status; + } + return status; +} + +static void read_fan_from_i2c(struct i2c_client *client, u16 *output, + u8 hi_addr, u8 lo_addr) +{ + u8 high_byte, lo_byte; + + if (read_u8_from_i2c(client, hi_addr, &high_byte) < 0) + return; + + if (read_u8_from_i2c(client, lo_addr, &lo_byte) < 0) + return; + + *output = ((u16)high_byte << 5) | (lo_byte >> 3); +} + +static void write_fan_target_to_i2c(struct i2c_client *client, int fan, + u16 new_target) +{ + const u8 lo_reg = SEL_FAN(fan, REG_TACH_TARGET_LOW); + const u8 hi_reg = SEL_FAN(fan, REG_TACH_TARGET_HIGH); + u8 high_byte = (new_target & 0x1fe0) >> 5; + u8 low_byte = (new_target & 0x001f) << 3; + i2c_smbus_write_byte_data(client, lo_reg, low_byte); + i2c_smbus_write_byte_data(client, hi_reg, high_byte); +} + +static void read_fan_config_from_i2c(struct i2c_client *client, int fan) + +{ + struct emc2305_data *data = i2c_get_clientdata(client); + u8 conf1; + + if (read_u8_from_i2c(client, SEL_FAN(fan, REG_FAN_CONFIGURATION_1), + &conf1) < 0) + return; + + data->fan[fan].rpm_control = (conf1 & 0x80) != 0; + data->fan[fan].multiplier = 1 << ((conf1 & 0x60) >> 5); + data->fan[fan].poles = ((conf1 & 0x18) >> 3) + 1; +} + +static void read_fan_setting(struct i2c_client *client, int fan) +{ + struct emc2305_data *data = i2c_get_clientdata(client); + u8 setting; + + if (read_u8_from_i2c(client, SEL_FAN(fan, REG_FAN_SETTING), + &setting) < 0) + return; + + data->fan[fan].pwm = setting; +} + +static void read_fan_data(struct i2c_client *client, int fan_idx) +{ + struct emc2305_data *data = i2c_get_clientdata(client); + + read_fan_from_i2c(client, &data->fan[fan_idx].target, + SEL_FAN(fan_idx, REG_TACH_TARGET_HIGH), + SEL_FAN(fan_idx, REG_TACH_TARGET_LOW)); + read_fan_from_i2c(client, &data->fan[fan_idx].tach, + SEL_FAN(fan_idx, REG_TACH_READ_HIGH), + SEL_FAN(fan_idx, REG_TACH_READ_LOW)); +} + +static struct emc2305_fan_data * +emc2305_update_fan(struct i2c_client *client, int fan_idx) +{ + struct emc2305_data *data = i2c_get_clientdata(client); + struct emc2305_fan_data *fan_data = &data->fan[fan_idx]; + + mutex_lock(&data->update_lock); + + if (time_after(jiffies, fan_data->last_updated + HZ + HZ / 2) + || !fan_data->valid) { + read_fan_config_from_i2c(client, fan_idx); + read_fan_data(client, fan_idx); + read_fan_setting(client, fan_idx); + fan_data->valid = true; + fan_data->last_updated = jiffies; + } + + mutex_unlock(&data->update_lock); + return fan_data; +} + +static struct emc2305_fan_data * +emc2305_update_device_fan(struct device *dev, struct device_attribute *da) +{ + struct i2c_client *client = to_i2c_client(dev); + int fan_idx = to_sensor_dev_attr(da)->index; + + return emc2305_update_fan(client, fan_idx); +} + +/* + * set/ config functions + */ + +/* + * Note: we also update the fan target here, because its value is + * determined in part by the fan clock divider. This follows the principle + * of least surprise; the user doesn't expect the fan target to change just + * because the divider changed. + */ +static int +emc2305_set_fan_div(struct i2c_client *client, int fan_idx, long new_div) +{ + struct emc2305_data *data = i2c_get_clientdata(client); + struct emc2305_fan_data *fan = emc2305_update_fan(client, fan_idx); + const u8 reg_conf1 = SEL_FAN(fan_idx, REG_FAN_CONFIGURATION_1); + int new_range_bits, old_div = 8 / fan->multiplier; + int status = 0; + + if (new_div == old_div) /* No change */ + return 0; + + switch (new_div) { + case 1: + new_range_bits = 3; + break; + case 2: + new_range_bits = 2; + break; + case 4: + new_range_bits = 1; + break; + case 8: + new_range_bits = 0; + break; + default: + return -EINVAL; + } + + mutex_lock(&data->update_lock); + + status = i2c_smbus_read_byte_data(client, reg_conf1); + if (status < 0) { + dev_dbg(&client->dev, "reg 0x%02x, err %d\n", + reg_conf1, status); + status = -EIO; + goto exit_unlock; + } + status &= 0x9F; + status |= (new_range_bits << 5); + status = i2c_smbus_write_byte_data(client, reg_conf1, status); + if (status < 0) { + status = -EIO; + goto exit_invalidate; + } + + fan->multiplier = 8 / new_div; + + /* update fan target if high byte is not disabled */ + if ((fan->target & 0x1fe0) != 0x1fe0) { + u16 new_target = (fan->target * old_div) / new_div; + fan->target = min_t(u16, new_target, 0x1fff); + write_fan_target_to_i2c(client, fan_idx, fan->target); + } + +exit_invalidate: + /* invalidate fan data to force re-read from hardware */ + fan->valid = false; +exit_unlock: + mutex_unlock(&data->update_lock); + return status; +} + +static int +emc2305_set_fan_target(struct i2c_client *client, int fan_idx, long rpm_target) +{ + struct emc2305_data *data = i2c_get_clientdata(client); + struct emc2305_fan_data *fan = emc2305_update_fan(client, fan_idx); + + /* + * Datasheet states 16000 as maximum RPM target + * (table 2.2 and section 4.3) + */ + if ((rpm_target < 0) || (rpm_target > 16000)) + return -EINVAL; + + mutex_lock(&data->update_lock); + + if (rpm_target == 0) + fan->target = 0x1fff; + else + fan->target = clamp_val( + (FAN_RPM_FACTOR * fan->multiplier) / rpm_target, + 0, 0x1fff); + + write_fan_target_to_i2c(client, fan_idx, fan->target); + + mutex_unlock(&data->update_lock); + return 0; +} + +static int +emc2305_set_pwm_enable(struct i2c_client *client, int fan_idx, long enable) +{ + struct emc2305_data *data = i2c_get_clientdata(client); + struct emc2305_fan_data *fan = emc2305_update_fan(client, fan_idx); + const u8 reg_fan_conf1 = SEL_FAN(fan_idx, REG_FAN_CONFIGURATION_1); + int status = 0; + u8 conf_reg; + + mutex_lock(&data->update_lock); + switch (enable) { + case 0: + fan->rpm_control = false; + break; + case 3: + fan->rpm_control = true; + break; + default: + status = -EINVAL; + goto exit_unlock; + } + + status = read_u8_from_i2c(client, reg_fan_conf1, &conf_reg); + if (status < 0) { + status = -EIO; + goto exit_unlock; + } + + if (fan->rpm_control) + conf_reg |= 0x80; + else + conf_reg &= ~0x80; + + status = i2c_smbus_write_byte_data(client, reg_fan_conf1, conf_reg); + if (status < 0) + status = -EIO; + +exit_unlock: + mutex_unlock(&data->update_lock); + return status; +} + +static int +emc2305_set_pwm(struct i2c_client *client, int fan_idx, long pwm) +{ + struct emc2305_data *data = i2c_get_clientdata(client); + struct emc2305_fan_data *fan = emc2305_update_fan(client, fan_idx); + const u8 reg_fan_setting = SEL_FAN(fan_idx, REG_FAN_SETTING); + int status = 0; + + /* + * Datasheet states 255 as maximum PWM + * (section 5.7) + */ + if ((pwm < 0) || (pwm > 255)) + return -EINVAL; + + fan->pwm = pwm; + + mutex_lock(&data->update_lock); + + status = i2c_smbus_write_byte_data(client, reg_fan_setting, fan->pwm); + + mutex_unlock(&data->update_lock); + return status; +} +/* + * sysfs callback functions + * + * Note: + * Naming of the funcs is modelled after the naming scheme described in + * Documentation/hwmon/sysfs-interface: + * + * For a sysfs file _ the functions are named like this: + * the show function: show__ + * the store function: set__ + * For read only (RO) attributes of course only the show func is required. + * + * This convention allows us to define the sysfs attributes by using macros. + */ + +static ssize_t +show_fan_input(struct device *dev, struct device_attribute *da, char *buf) +{ + struct emc2305_fan_data *fan = emc2305_update_device_fan(dev, da); + int rpm = 0; + if (fan->tach != 0) + rpm = (FAN_RPM_FACTOR * fan->multiplier) / fan->tach; + return sprintf(buf, "%d\n", rpm); +} + +static ssize_t +show_fan_fault(struct device *dev, struct device_attribute *da, char *buf) +{ + struct emc2305_fan_data *fan = emc2305_update_device_fan(dev, da); + bool fault = ((fan->tach & 0x1fe0) == 0x1fe0); + return sprintf(buf, "%d\n", fault ? 1 : 0); +} + +static ssize_t +show_fan_div(struct device *dev, struct device_attribute *da, char *buf) +{ + struct emc2305_fan_data *fan = emc2305_update_device_fan(dev, da); + int fan_div = 8 / fan->multiplier; + return sprintf(buf, "%d\n", fan_div); +} + +static ssize_t +set_fan_div(struct device *dev, struct device_attribute *da, + const char *buf, size_t count) +{ + struct i2c_client *client = to_i2c_client(dev); + int fan_idx = to_sensor_dev_attr(da)->index; + long new_div; + int status; + + status = kstrtol(buf, 10, &new_div); + if (status < 0) + return -EINVAL; + + status = emc2305_set_fan_div(client, fan_idx, new_div); + if (status < 0) + return status; + + return count; +} + +static ssize_t +show_fan_target(struct device *dev, struct device_attribute *da, char *buf) +{ + struct emc2305_fan_data *fan = emc2305_update_device_fan(dev, da); + int rpm = 0; + + /* high byte of 0xff indicates disabled so return 0 */ + if ((fan->target != 0) && ((fan->target & 0x1fe0) != 0x1fe0)) + rpm = (FAN_RPM_FACTOR * fan->multiplier) + / fan->target; + + return sprintf(buf, "%d\n", rpm); +} + +static ssize_t set_fan_target(struct device *dev, struct device_attribute *da, + const char *buf, size_t count) +{ + struct i2c_client *client = to_i2c_client(dev); + int fan_idx = to_sensor_dev_attr(da)->index; + long rpm_target; + int status; + + status = kstrtol(buf, 10, &rpm_target); + if (status < 0) + return -EINVAL; + + status = emc2305_set_fan_target(client, fan_idx, rpm_target); + if (status < 0) + return status; + + return count; +} + +static ssize_t +show_pwm_enable(struct device *dev, struct device_attribute *da, char *buf) +{ + struct emc2305_fan_data *fan = emc2305_update_device_fan(dev, da); + return sprintf(buf, "%d\n", fan->rpm_control ? 3 : 0); +} + +static ssize_t set_pwm_enable(struct device *dev, struct device_attribute *da, + const char *buf, size_t count) +{ + struct i2c_client *client = to_i2c_client(dev); + int fan_idx = to_sensor_dev_attr(da)->index; + long new_value; + int status; + + status = kstrtol(buf, 10, &new_value); + if (status < 0) + return -EINVAL; + status = emc2305_set_pwm_enable(client, fan_idx, new_value); + return count; +} + +static ssize_t show_pwm(struct device *dev, struct device_attribute *da, + char *buf) +{ + struct emc2305_fan_data *fan = emc2305_update_device_fan(dev, da); + return sprintf(buf, "%d\n", fan->pwm); +} + +static ssize_t set_pwm(struct device *dev, struct device_attribute *da, + const char *buf, size_t count) +{ + struct i2c_client *client = to_i2c_client(dev); + int fan_idx = to_sensor_dev_attr(da)->index; + unsigned long val; + int ret; + int status; + + ret = kstrtoul(buf, 10, &val); + if (ret) + return ret; + if (val > 255) + return -EINVAL; + + status = emc2305_set_pwm(client, fan_idx, val); + return count; +} + +/* define a read only attribute */ +#define EMC2305_ATTR_RO(_type, _item, _num) \ + SENSOR_ATTR(_type ## _num ## _ ## _item, S_IRUGO, \ + show_## _type ## _ ## _item, NULL, _num - 1) + +/* define a read/write attribute */ +#define EMC2305_ATTR_RW(_type, _item, _num) \ + SENSOR_ATTR(_type ## _num ## _ ## _item, S_IRUGO | S_IWUSR, \ + show_## _type ##_ ## _item, \ + set_## _type ## _ ## _item, _num - 1) + +/* + * TODO: Ugly hack, but temporary as this whole logic needs + * to be rewritten as per standard HWMON sysfs registration + */ + +/* define a read/write attribute */ +#define EMC2305_ATTR_RW2(_type, _num) \ + SENSOR_ATTR(_type ## _num, S_IRUGO | S_IWUSR, \ + show_## _type, set_## _type, _num - 1) + +/* defines the attributes for a single fan */ +#define EMC2305_DEFINE_FAN_ATTRS(_num) \ + static const \ + struct sensor_device_attribute emc2305_attr_fan ## _num[] = { \ + EMC2305_ATTR_RO(fan, input, _num), \ + EMC2305_ATTR_RO(fan, fault, _num), \ + EMC2305_ATTR_RW(fan, div, _num), \ + EMC2305_ATTR_RW(fan, target, _num), \ + EMC2305_ATTR_RW(pwm, enable, _num), \ + EMC2305_ATTR_RW2(pwm, _num) \ + } + +#define EMC2305_NUM_FAN_ATTRS ARRAY_SIZE(emc2305_attr_fan1) + +/* common attributes for EMC2303 and EMC2305 */ +static const struct sensor_device_attribute emc2305_attr_common[] = { +}; + +/* fan attributes for the single fans */ +EMC2305_DEFINE_FAN_ATTRS(1); +EMC2305_DEFINE_FAN_ATTRS(2); +EMC2305_DEFINE_FAN_ATTRS(3); +EMC2305_DEFINE_FAN_ATTRS(4); +EMC2305_DEFINE_FAN_ATTRS(5); +EMC2305_DEFINE_FAN_ATTRS(6); + +/* fan attributes */ +static const struct sensor_device_attribute *emc2305_fan_attrs[] = { + emc2305_attr_fan1, + emc2305_attr_fan2, + emc2305_attr_fan3, + emc2305_attr_fan4, + emc2305_attr_fan5, +}; + +/* + * driver interface + */ + +static int emc2305_remove(struct i2c_client *client) +{ + struct emc2305_data *data = i2c_get_clientdata(client); + int fan_idx, i; + + hwmon_device_unregister(data->hwmon_dev); + + for (fan_idx = 0; fan_idx < data->fans; ++fan_idx) + for (i = 0; i < EMC2305_NUM_FAN_ATTRS; ++i) + device_remove_file( + &client->dev, + &emc2305_fan_attrs[fan_idx][i].dev_attr); + + for (i = 0; i < ARRAY_SIZE(emc2305_attr_common); ++i) + device_remove_file(&client->dev, + &emc2305_attr_common[i].dev_attr); + + kfree(data); + return 0; +} + + +#ifdef CONFIG_OF +/* + * device tree support + */ + +struct of_fan_attribute { + const char *name; + int (*set)(struct i2c_client*, int, long); +}; + +struct of_fan_attribute of_fan_attributes[] = { + {"fan-div", emc2305_set_fan_div}, + {"fan-target", emc2305_set_fan_target}, + {"pwm-enable", emc2305_set_pwm_enable}, + {NULL, NULL} +}; + +static int emc2305_config_of(struct i2c_client *client) +{ + struct emc2305_data *data = i2c_get_clientdata(client); + struct device_node *node; + unsigned int fan_idx; + + if (!client->dev.of_node) + return -EINVAL; + if (!of_get_next_child(client->dev.of_node, NULL)) + return 0; + + for (fan_idx = 0; fan_idx < data->fans; ++fan_idx) + data->fan[fan_idx].enabled = false; + + for_each_child_of_node(client->dev.of_node, node) { + const __be32 *property; + int len; + struct of_fan_attribute *attr; + + property = of_get_property(node, "reg", &len); + if (!property || len != sizeof(int)) { + dev_err(&client->dev, "invalid reg on %s\n", + node->full_name); + continue; + } + + fan_idx = be32_to_cpup(property); + if (fan_idx >= data->fans) { + dev_err(&client->dev, + "invalid fan index %d on %s\n", + fan_idx, node->full_name); + continue; + } + + data->fan[fan_idx].enabled = true; + + for (attr = of_fan_attributes; attr->name; ++attr) { + int status = 0; + long value; + property = of_get_property(node, attr->name, &len); + if (!property) + continue; + if (len != sizeof(int)) { + dev_err(&client->dev, "invalid %s on %s\n", + attr->name, node->full_name); + continue; + } + value = be32_to_cpup(property); + status = attr->set(client, fan_idx, value); + if (status == -EINVAL) { + dev_err(&client->dev, + "invalid value for %s on %s\n", + attr->name, node->full_name); + } + } + } + + return 0; +} + +#endif + +static void emc2305_get_config(struct i2c_client *client) +{ + int i; + struct emc2305_data *data = i2c_get_clientdata(client); + + for (i = 0; i < data->fans; ++i) { + data->fan[i].enabled = true; + emc2305_update_fan(client, i); + } + +#ifdef CONFIG_OF + emc2305_config_of(client); +#endif + +} + +static int +emc2305_probe(struct i2c_client *client, const struct i2c_device_id *id) +{ + struct emc2305_data *data; + int status; + int i; + int fan_idx; + + if (!i2c_check_functionality(client->adapter, I2C_FUNC_SMBUS_BYTE_DATA)) + return -EIO; + + data = kzalloc(sizeof(struct emc2305_data), GFP_KERNEL); + if (!data) + return -ENOMEM; + + i2c_set_clientdata(client, data); + mutex_init(&data->update_lock); + + status = i2c_smbus_read_byte_data(client, REG_PRODUCT_ID); + switch (status) { + case 0x34: /* EMC2305 */ + data->fans = 5; + break; + case 0x35: /* EMC2303 */ + data->fans = 3; + break; + case 0x36: /* EMC2302 */ + data->fans = 2; + break; + case 0x37: /* EMC2301 */ + data->fans = 1; + break; + default: + if (status >= 0) + status = -EINVAL; + goto exit_free; + } + + emc2305_get_config(client); + + for (i = 0; i < ARRAY_SIZE(emc2305_attr_common); ++i) { + status = device_create_file(&client->dev, + &emc2305_attr_common[i].dev_attr); + if (status) + goto exit_remove; + } + for (fan_idx = 0; fan_idx < data->fans; ++fan_idx) + for (i = 0; i < EMC2305_NUM_FAN_ATTRS; ++i) { + if (!data->fan[fan_idx].enabled) + continue; + status = device_create_file( + &client->dev, + &emc2305_fan_attrs[fan_idx][i].dev_attr); + if (status) + goto exit_remove_fans; + } + + data->hwmon_dev = hwmon_device_register(&client->dev); + if (IS_ERR(data->hwmon_dev)) { + status = PTR_ERR(data->hwmon_dev); + goto exit_remove_fans; + } + + dev_info(&client->dev, "%s: sensor '%s'\n", + dev_name(data->hwmon_dev), client->name); + + return 0; + +exit_remove_fans: + for (fan_idx = 0; fan_idx < data->fans; ++fan_idx) + for (i = 0; i < EMC2305_NUM_FAN_ATTRS; ++i) + device_remove_file( + &client->dev, + &emc2305_fan_attrs[fan_idx][i].dev_attr); + +exit_remove: + for (i = 0; i < ARRAY_SIZE(emc2305_attr_common); ++i) + device_remove_file(&client->dev, + &emc2305_attr_common[i].dev_attr); +exit_free: + kfree(data); + return status; +} + +static const struct i2c_device_id emc2305_id[] = { + { "emc2305", 0 }, + { "emc2303", 0 }, + { "emc2302", 0 }, + { "emc2301", 0 }, + { } +}; +MODULE_DEVICE_TABLE(i2c, emc2305_id); + +/* Return 0 if detection is successful, -ENODEV otherwise */ +static int +emc2305_detect(struct i2c_client *new_client, struct i2c_board_info *info) +{ + struct i2c_adapter *adapter = new_client->adapter; + int manufacturer, product; + + if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA)) + return -ENODEV; + + manufacturer = + i2c_smbus_read_byte_data(new_client, REG_MANUFACTURER_ID); + if (manufacturer != 0x5D) + return -ENODEV; + + product = i2c_smbus_read_byte_data(new_client, REG_PRODUCT_ID); + + switch (product) { + case 0x34: + strlcpy(info->type, "emc2305", I2C_NAME_SIZE); + break; + case 0x35: + strlcpy(info->type, "emc2303", I2C_NAME_SIZE); + break; + case 0x36: + strlcpy(info->type, "emc2302", I2C_NAME_SIZE); + break; + case 0x37: + strlcpy(info->type, "emc2301", I2C_NAME_SIZE); + break; + default: + return -ENODEV; + } + + return 0; +} + +static struct i2c_driver emc2305_driver = { + .class = I2C_CLASS_HWMON, + .driver = { + .name = "emc2305", + }, + .probe = emc2305_probe, + .remove = emc2305_remove, + .id_table = emc2305_id, +/* + .detect = emc2305_detect, + .address_list = i2c_adresses, +*/ +}; + +module_i2c_driver(emc2305_driver); + +MODULE_AUTHOR("Reinhard Pfau "); +MODULE_DESCRIPTION("SMSC EMC2305 hwmon driver"); +MODULE_LICENSE("GPL"); diff --git a/platform/broadcom/sonic-platform-modules-dell/n3248te/modules/pmbus.h b/platform/broadcom/sonic-platform-modules-dell/n3248te/modules/pmbus.h new file mode 100644 index 000000000000..521baf6da49a --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-dell/n3248te/modules/pmbus.h @@ -0,0 +1,425 @@ +/* + * pmbus.h - Common defines and structures for PMBus devices + * + * Copyright (c) 2010, 2011 Ericsson AB. + * Copyright (c) 2012 Guenter Roeck + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#ifndef PMBUS_H +#define PMBUS_H + +#include +#include + +/* + * Registers + */ +enum pmbus_regs { + PMBUS_PAGE = 0x00, + PMBUS_OPERATION = 0x01, + PMBUS_ON_OFF_CONFIG = 0x02, + PMBUS_CLEAR_FAULTS = 0x03, + PMBUS_PHASE = 0x04, + + PMBUS_CAPABILITY = 0x19, + PMBUS_QUERY = 0x1A, + + PMBUS_VOUT_MODE = 0x20, + PMBUS_VOUT_COMMAND = 0x21, + PMBUS_VOUT_TRIM = 0x22, + PMBUS_VOUT_CAL_OFFSET = 0x23, + PMBUS_VOUT_MAX = 0x24, + PMBUS_VOUT_MARGIN_HIGH = 0x25, + PMBUS_VOUT_MARGIN_LOW = 0x26, + PMBUS_VOUT_TRANSITION_RATE = 0x27, + PMBUS_VOUT_DROOP = 0x28, + PMBUS_VOUT_SCALE_LOOP = 0x29, + PMBUS_VOUT_SCALE_MONITOR = 0x2A, + + PMBUS_COEFFICIENTS = 0x30, + PMBUS_POUT_MAX = 0x31, + + PMBUS_FAN_CONFIG_12 = 0x3A, + PMBUS_FAN_COMMAND_1 = 0x3B, + PMBUS_FAN_COMMAND_2 = 0x3C, + PMBUS_FAN_CONFIG_34 = 0x3D, + PMBUS_FAN_COMMAND_3 = 0x3E, + PMBUS_FAN_COMMAND_4 = 0x3F, + + PMBUS_VOUT_OV_FAULT_LIMIT = 0x40, + PMBUS_VOUT_OV_FAULT_RESPONSE = 0x41, + PMBUS_VOUT_OV_WARN_LIMIT = 0x42, + PMBUS_VOUT_UV_WARN_LIMIT = 0x43, + PMBUS_VOUT_UV_FAULT_LIMIT = 0x44, + PMBUS_VOUT_UV_FAULT_RESPONSE = 0x45, + PMBUS_IOUT_OC_FAULT_LIMIT = 0x46, + PMBUS_IOUT_OC_FAULT_RESPONSE = 0x47, + PMBUS_IOUT_OC_LV_FAULT_LIMIT = 0x48, + PMBUS_IOUT_OC_LV_FAULT_RESPONSE = 0x49, + PMBUS_IOUT_OC_WARN_LIMIT = 0x4A, + PMBUS_IOUT_UC_FAULT_LIMIT = 0x4B, + PMBUS_IOUT_UC_FAULT_RESPONSE = 0x4C, + + PMBUS_OT_FAULT_LIMIT = 0x4F, + PMBUS_OT_FAULT_RESPONSE = 0x50, + PMBUS_OT_WARN_LIMIT = 0x51, + PMBUS_UT_WARN_LIMIT = 0x52, + PMBUS_UT_FAULT_LIMIT = 0x53, + PMBUS_UT_FAULT_RESPONSE = 0x54, + PMBUS_VIN_OV_FAULT_LIMIT = 0x55, + PMBUS_VIN_OV_FAULT_RESPONSE = 0x56, + PMBUS_VIN_OV_WARN_LIMIT = 0x57, + PMBUS_VIN_UV_WARN_LIMIT = 0x58, + PMBUS_VIN_UV_FAULT_LIMIT = 0x59, + + PMBUS_IIN_OC_FAULT_LIMIT = 0x5B, + PMBUS_IIN_OC_WARN_LIMIT = 0x5D, + + PMBUS_POUT_OP_FAULT_LIMIT = 0x68, + PMBUS_POUT_OP_WARN_LIMIT = 0x6A, + PMBUS_PIN_OP_WARN_LIMIT = 0x6B, + + PMBUS_STATUS_BYTE = 0x78, + PMBUS_STATUS_WORD = 0x79, + PMBUS_STATUS_VOUT = 0x7A, + PMBUS_STATUS_IOUT = 0x7B, + PMBUS_STATUS_INPUT = 0x7C, + PMBUS_STATUS_TEMPERATURE = 0x7D, + PMBUS_STATUS_CML = 0x7E, + PMBUS_STATUS_OTHER = 0x7F, + PMBUS_STATUS_MFR_SPECIFIC = 0x80, + PMBUS_STATUS_FAN_12 = 0x81, + PMBUS_STATUS_FAN_34 = 0x82, + + PMBUS_READ_VIN = 0x88, + PMBUS_READ_IIN = 0x89, + PMBUS_READ_VCAP = 0x8A, + PMBUS_READ_VOUT = 0x8B, + PMBUS_READ_IOUT = 0x8C, + PMBUS_READ_TEMPERATURE_1 = 0x8D, + PMBUS_READ_TEMPERATURE_2 = 0x8E, + PMBUS_READ_TEMPERATURE_3 = 0x8F, + PMBUS_READ_FAN_SPEED_1 = 0x90, + PMBUS_READ_FAN_SPEED_2 = 0x91, + PMBUS_READ_FAN_SPEED_3 = 0x92, + PMBUS_READ_FAN_SPEED_4 = 0x93, + PMBUS_READ_DUTY_CYCLE = 0x94, + PMBUS_READ_FREQUENCY = 0x95, + PMBUS_READ_POUT = 0x96, + PMBUS_READ_PIN = 0x97, + + PMBUS_REVISION = 0x98, + PMBUS_MFR_ID = 0x99, + PMBUS_MFR_MODEL = 0x9A, + PMBUS_MFR_REVISION = 0x9B, + PMBUS_MFR_LOCATION = 0x9C, + PMBUS_MFR_DATE = 0x9D, + PMBUS_MFR_SERIAL = 0x9E, + +/* + * Virtual registers. + * Useful to support attributes which are not supported by standard PMBus + * registers but exist as manufacturer specific registers on individual chips. + * Must be mapped to real registers in device specific code. + * + * Semantics: + * Virtual registers are all word size. + * READ registers are read-only; writes are either ignored or return an error. + * RESET registers are read/write. Reading reset registers returns zero + * (used for detection), writing any value causes the associated history to be + * reset. + * Virtual registers have to be handled in device specific driver code. Chip + * driver code returns non-negative register values if a virtual register is + * supported, or a negative error code if not. The chip driver may return + * -ENODATA or any other error code in this case, though an error code other + * than -ENODATA is handled more efficiently and thus preferred. Either case, + * the calling PMBus core code will abort if the chip driver returns an error + * code when reading or writing virtual registers. + */ + PMBUS_VIRT_BASE = 0x100, + PMBUS_VIRT_READ_TEMP_AVG, + PMBUS_VIRT_READ_TEMP_MIN, + PMBUS_VIRT_READ_TEMP_MAX, + PMBUS_VIRT_RESET_TEMP_HISTORY, + PMBUS_VIRT_READ_VIN_AVG, + PMBUS_VIRT_READ_VIN_MIN, + PMBUS_VIRT_READ_VIN_MAX, + PMBUS_VIRT_RESET_VIN_HISTORY, + PMBUS_VIRT_READ_IIN_AVG, + PMBUS_VIRT_READ_IIN_MIN, + PMBUS_VIRT_READ_IIN_MAX, + PMBUS_VIRT_RESET_IIN_HISTORY, + PMBUS_VIRT_READ_PIN_AVG, + PMBUS_VIRT_READ_PIN_MIN, + PMBUS_VIRT_READ_PIN_MAX, + PMBUS_VIRT_RESET_PIN_HISTORY, + PMBUS_VIRT_READ_POUT_AVG, + PMBUS_VIRT_READ_POUT_MIN, + PMBUS_VIRT_READ_POUT_MAX, + PMBUS_VIRT_RESET_POUT_HISTORY, + PMBUS_VIRT_READ_VOUT_AVG, + PMBUS_VIRT_READ_VOUT_MIN, + PMBUS_VIRT_READ_VOUT_MAX, + PMBUS_VIRT_RESET_VOUT_HISTORY, + PMBUS_VIRT_READ_IOUT_AVG, + PMBUS_VIRT_READ_IOUT_MIN, + PMBUS_VIRT_READ_IOUT_MAX, + PMBUS_VIRT_RESET_IOUT_HISTORY, + PMBUS_VIRT_READ_TEMP2_AVG, + PMBUS_VIRT_READ_TEMP2_MIN, + PMBUS_VIRT_READ_TEMP2_MAX, + PMBUS_VIRT_RESET_TEMP2_HISTORY, + + PMBUS_VIRT_READ_VMON, + PMBUS_VIRT_VMON_UV_WARN_LIMIT, + PMBUS_VIRT_VMON_OV_WARN_LIMIT, + PMBUS_VIRT_VMON_UV_FAULT_LIMIT, + PMBUS_VIRT_VMON_OV_FAULT_LIMIT, + PMBUS_VIRT_STATUS_VMON, +}; + +/* + * OPERATION + */ +#define PB_OPERATION_CONTROL_ON BIT(7) + +/* + * CAPABILITY + */ +#define PB_CAPABILITY_SMBALERT BIT(4) +#define PB_CAPABILITY_ERROR_CHECK BIT(7) + +/* + * VOUT_MODE + */ +#define PB_VOUT_MODE_MODE_MASK 0xe0 +#define PB_VOUT_MODE_PARAM_MASK 0x1f + +#define PB_VOUT_MODE_LINEAR 0x00 +#define PB_VOUT_MODE_VID 0x20 +#define PB_VOUT_MODE_DIRECT 0x40 + +/* + * Fan configuration + */ +#define PB_FAN_2_PULSE_MASK (BIT(0) | BIT(1)) +#define PB_FAN_2_RPM BIT(2) +#define PB_FAN_2_INSTALLED BIT(3) +#define PB_FAN_1_PULSE_MASK (BIT(4) | BIT(5)) +#define PB_FAN_1_RPM BIT(6) +#define PB_FAN_1_INSTALLED BIT(7) + +/* + * STATUS_BYTE, STATUS_WORD (lower) + */ +#define PB_STATUS_NONE_ABOVE BIT(0) +#define PB_STATUS_CML BIT(1) +#define PB_STATUS_TEMPERATURE BIT(2) +#define PB_STATUS_VIN_UV BIT(3) +#define PB_STATUS_IOUT_OC BIT(4) +#define PB_STATUS_VOUT_OV BIT(5) +#define PB_STATUS_OFF BIT(6) +#define PB_STATUS_BUSY BIT(7) + +/* + * STATUS_WORD (upper) + */ +#define PB_STATUS_UNKNOWN BIT(8) +#define PB_STATUS_OTHER BIT(9) +#define PB_STATUS_FANS BIT(10) +#define PB_STATUS_POWER_GOOD_N BIT(11) +#define PB_STATUS_WORD_MFR BIT(12) +#define PB_STATUS_INPUT BIT(13) +#define PB_STATUS_IOUT_POUT BIT(14) +#define PB_STATUS_VOUT BIT(15) + +/* + * STATUS_IOUT + */ +#define PB_POUT_OP_WARNING BIT(0) +#define PB_POUT_OP_FAULT BIT(1) +#define PB_POWER_LIMITING BIT(2) +#define PB_CURRENT_SHARE_FAULT BIT(3) +#define PB_IOUT_UC_FAULT BIT(4) +#define PB_IOUT_OC_WARNING BIT(5) +#define PB_IOUT_OC_LV_FAULT BIT(6) +#define PB_IOUT_OC_FAULT BIT(7) + +/* + * STATUS_VOUT, STATUS_INPUT + */ +#define PB_VOLTAGE_UV_FAULT BIT(4) +#define PB_VOLTAGE_UV_WARNING BIT(5) +#define PB_VOLTAGE_OV_WARNING BIT(6) +#define PB_VOLTAGE_OV_FAULT BIT(7) + +/* + * STATUS_INPUT + */ +#define PB_PIN_OP_WARNING BIT(0) +#define PB_IIN_OC_WARNING BIT(1) +#define PB_IIN_OC_FAULT BIT(2) + +/* + * STATUS_TEMPERATURE + */ +#define PB_TEMP_UT_FAULT BIT(4) +#define PB_TEMP_UT_WARNING BIT(5) +#define PB_TEMP_OT_WARNING BIT(6) +#define PB_TEMP_OT_FAULT BIT(7) + +/* + * STATUS_FAN + */ +#define PB_FAN_AIRFLOW_WARNING BIT(0) +#define PB_FAN_AIRFLOW_FAULT BIT(1) +#define PB_FAN_FAN2_SPEED_OVERRIDE BIT(2) +#define PB_FAN_FAN1_SPEED_OVERRIDE BIT(3) +#define PB_FAN_FAN2_WARNING BIT(4) +#define PB_FAN_FAN1_WARNING BIT(5) +#define PB_FAN_FAN2_FAULT BIT(6) +#define PB_FAN_FAN1_FAULT BIT(7) + +/* + * CML_FAULT_STATUS + */ +#define PB_CML_FAULT_OTHER_MEM_LOGIC BIT(0) +#define PB_CML_FAULT_OTHER_COMM BIT(1) +#define PB_CML_FAULT_PROCESSOR BIT(3) +#define PB_CML_FAULT_MEMORY BIT(4) +#define PB_CML_FAULT_PACKET_ERROR BIT(5) +#define PB_CML_FAULT_INVALID_DATA BIT(6) +#define PB_CML_FAULT_INVALID_COMMAND BIT(7) + +enum pmbus_sensor_classes { + PSC_VOLTAGE_IN = 0, + PSC_VOLTAGE_OUT, + PSC_CURRENT_IN, + PSC_CURRENT_OUT, + PSC_POWER, + PSC_TEMPERATURE, + PSC_FAN, + PSC_NUM_CLASSES /* Number of power sensor classes */ +}; + +#define PMBUS_PAGES 32 /* Per PMBus specification */ + +/* Functionality bit mask */ +#define PMBUS_HAVE_VIN BIT(0) +#define PMBUS_HAVE_VCAP BIT(1) +#define PMBUS_HAVE_VOUT BIT(2) +#define PMBUS_HAVE_IIN BIT(3) +#define PMBUS_HAVE_IOUT BIT(4) +#define PMBUS_HAVE_PIN BIT(5) +#define PMBUS_HAVE_POUT BIT(6) +#define PMBUS_HAVE_FAN12 BIT(7) +#define PMBUS_HAVE_FAN34 BIT(8) +#define PMBUS_HAVE_TEMP BIT(9) +#define PMBUS_HAVE_TEMP2 BIT(10) +#define PMBUS_HAVE_TEMP3 BIT(11) +#define PMBUS_HAVE_STATUS_VOUT BIT(12) +#define PMBUS_HAVE_STATUS_IOUT BIT(13) +#define PMBUS_HAVE_STATUS_INPUT BIT(14) +#define PMBUS_HAVE_STATUS_TEMP BIT(15) +#define PMBUS_HAVE_STATUS_FAN12 BIT(16) +#define PMBUS_HAVE_STATUS_FAN34 BIT(17) +#define PMBUS_HAVE_VMON BIT(18) +#define PMBUS_HAVE_STATUS_VMON BIT(19) + +enum pmbus_data_format { linear = 0, direct, vid }; +enum vrm_version { vr11 = 0, vr12 }; + +struct pmbus_driver_info { + int pages; /* Total number of pages */ + enum pmbus_data_format format[PSC_NUM_CLASSES]; + enum vrm_version vrm_version; + /* + * Support one set of coefficients for each sensor type + * Used for chips providing data in direct mode. + */ + int m[PSC_NUM_CLASSES]; /* mantissa for direct data format */ + int b[PSC_NUM_CLASSES]; /* offset */ + int R[PSC_NUM_CLASSES]; /* exponent */ + + u32 func[PMBUS_PAGES]; /* Functionality, per page */ + /* + * The following functions map manufacturing specific register values + * to PMBus standard register values. Specify only if mapping is + * necessary. + * Functions return the register value (read) or zero (write) if + * successful. A return value of -ENODATA indicates that there is no + * manufacturer specific register, but that a standard PMBus register + * may exist. Any other negative return value indicates that the + * register does not exist, and that no attempt should be made to read + * the standard register. + */ + int (*read_byte_data)(struct i2c_client *client, int page, int reg); + int (*read_word_data)(struct i2c_client *client, int page, int reg); + int (*write_word_data)(struct i2c_client *client, int page, int reg, + u16 word); + int (*write_byte)(struct i2c_client *client, int page, u8 value); + /* + * The identify function determines supported PMBus functionality. + * This function is only necessary if a chip driver supports multiple + * chips, and the chip functionality is not pre-determined. + */ + int (*identify)(struct i2c_client *client, + struct pmbus_driver_info *info); + + /* Regulator functionality, if supported by this chip driver. */ + int num_regulators; + const struct regulator_desc *reg_desc; +}; + +/* Regulator ops */ + +extern const struct regulator_ops pmbus_regulator_ops; + +/* Macro for filling in array of struct regulator_desc */ +#define PMBUS_REGULATOR(_name, _id) \ + [_id] = { \ + .name = (_name # _id), \ + .id = (_id), \ + .of_match = of_match_ptr(_name # _id), \ + .regulators_node = of_match_ptr("regulators"), \ + .ops = &pmbus_regulator_ops, \ + .type = REGULATOR_VOLTAGE, \ + .owner = THIS_MODULE, \ + } + +/* Function declarations */ + +void pmbus_clear_cache(struct i2c_client *client); +int pmbus_set_page(struct i2c_client *client, u8 page); +int pmbus_read_word_data(struct i2c_client *client, u8 page, u8 reg); +int pmbus_write_word_data(struct i2c_client *client, u8 page, u8 reg, u16 word); +int pmbus_read_byte_data(struct i2c_client *client, int page, u8 reg); +int pmbus_write_byte(struct i2c_client *client, int page, u8 value); +int pmbus_write_byte_data(struct i2c_client *client, int page, u8 reg, + u8 value); +int pmbus_update_byte_data(struct i2c_client *client, int page, u8 reg, + u8 mask, u8 value); +void pmbus_clear_faults(struct i2c_client *client); +bool pmbus_check_byte_register(struct i2c_client *client, int page, int reg); +bool pmbus_check_word_register(struct i2c_client *client, int page, int reg); +int pmbus_do_probe(struct i2c_client *client, const struct i2c_device_id *id, + struct pmbus_driver_info *info); +int pmbus_do_remove(struct i2c_client *client); +const struct pmbus_driver_info *pmbus_get_driver_info(struct i2c_client + *client); + +#endif /* PMBUS_H */ \ No newline at end of file diff --git a/platform/broadcom/sonic-platform-modules-dell/n3248te/scripts/fancontrol.sh b/platform/broadcom/sonic-platform-modules-dell/n3248te/scripts/fancontrol.sh new file mode 100755 index 000000000000..448ec5acb38c --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-dell/n3248te/scripts/fancontrol.sh @@ -0,0 +1,78 @@ +#! /bin/sh + +### BEGIN INIT INFO +# Provides: fancontrol +# Required-Start: $remote_fs +# Required-Stop: $remote_fs +# Default-Start: 2 3 4 5 +# Default-Stop: +# Short-Description: fancontrol +# Description: fan speed regulator +### END INIT INFO + +. /lib/lsb/init-functions + +[ -f /etc/default/rcS ] && . /etc/default/rcS +PATH=/bin:/usr/bin:/sbin:/usr/sbin:/usr/local/bin +DAEMON=/usr/local/bin/fancontrol +DESC="fan speed regulator" +NAME="fancontrol" +PIDFILE=/var/run/fancontrol.pid +PLATFORMPATH=/sys/devices/platform/LPC +MAIN_CONF=/usr/share/sonic/device/x86_64-dell_s3000_c2338-r0/fancontrol +DEVPATH=/sys/devices/pci0000:00/0000:00:13.0/i2c-0/i2c-8/i2c-23/23-004d + +test -x $DAEMON || exit 0 + +for i in 1 2 3 +do + j=$i + [ $i -eq 3 ] && j=4 + FANFAULT=$(cat ${DEVPATH}/fan${j}_fault) + [ $FANFAULT = 1 ] && continue + FANDIR=$(cat ${PLATFORMPATH}/fan${i}_dir) +done +CONF=${MAIN_CONF}-${FANDIR} + +case "$1" in + start) + if [ -f $CONF ] ; then + if $DAEMON --check $CONF 1>/dev/null 2>/dev/null ; then + log_daemon_msg "Starting $DESC" "$NAME\n" + start-stop-daemon --start --quiet --pidfile $PIDFILE --startas $DAEMON $CONF + log_end_msg $? + else + log_failure_msg "Not starting fancontrol, broken configuration file; please re-run pwmconfig." + fi + else + if [ "$VERBOSE" != no ]; then + log_warning_msg "Not starting fancontrol; run pwmconfig first." + fi + fi + ;; + stop) + log_daemon_msg "Stopping $DESC" "$NAME" + start-stop-daemon --stop --quiet --pidfile $PIDFILE --oknodo --startas $DAEMON $CONF + rm -f $PIDFILE + log_end_msg $? + ;; + restart) + $0 stop + sleep 3 + $0 start + ;; + force-reload) + if start-stop-daemon --stop --test --quiet --pidfile $PIDFILE --startas $DAEMON $CONF ; then + $0 restart + fi + ;; + status) + status_of_proc $DAEMON $NAME $CONF && exit 0 || exit $? + ;; + *) + log_success_msg "Usage: /etc/init.d/fancontrol {start|stop|restart|force-reload|status}" + exit 1 + ;; +esac + +exit 0 diff --git a/platform/broadcom/sonic-platform-modules-dell/n3248te/scripts/n3248te_platform.sh b/platform/broadcom/sonic-platform-modules-dell/n3248te/scripts/n3248te_platform.sh new file mode 100755 index 000000000000..e4c0734b1fd9 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-dell/n3248te/scripts/n3248te_platform.sh @@ -0,0 +1,143 @@ +#!/bin/bash + +#platform init script for Dell N3248TE + +source dell_i2c_utils.sh + +#Attach/Detach the system devices +sys_devices() { + case $1 in + "new_device") #syseeprom + i2c_config "echo 24c02 0x50 > /sys/bus/i2c/devices/i2c-2/$1" + #Attach Fan Controller + i2c_config "echo emc2305 0x2c > /sys/bus/i2c/devices/i2c-7/$1" + #Attach temperature monitor + i2c_config "echo tmp75 0x49 > /sys/bus/i2c/devices/i2c-7/$1" + i2c_config "echo tmp75 0x4a > /sys/bus/i2c/devices/i2c-7/$1" + i2c_config "echo tmp75 0x4b > /sys/bus/i2c/devices/i2c-7/$1" + i2c_config "echo tmp75 0x4c > /sys/bus/i2c/devices/i2c-7/$1" + i2c_config "echo tmp75 0x4f > /sys/bus/i2c/devices/i2c-7/$1" + #Attach PSU Controller + i2c_config "echo dps460 0x5e > /sys/bus/i2c/devices/i2c-10/$1" + i2c_config "echo dps460 0x5e > /sys/bus/i2c/devices/i2c-11/$1" + #Attach PSU EEPROM + i2c_config "echo 24c02 0x56 > /sys/bus/i2c/devices/i2c-10/$1" + i2c_config "echo 24c02 0x56 > /sys/bus/i2c/devices/i2c-11/$1" + #Attach Fan EEPROM + i2c_config "echo 24c02 0x50 > /sys/bus/i2c/devices/i2c-15/$1" + i2c_config "echo 24c02 0x50 > /sys/bus/i2c/devices/i2c-16/$1" + i2c_config "echo 24c02 0x50 > /sys/bus/i2c/devices/i2c-17/$1" + ;; + "delete_device") i2c_config "echo 0x50 > /sys/bus/i2c/devices/i2c-2/$1" + i2c_config "echo 0x2c > /sys/bus/i2c/devices/i2c-7/$1" + i2c_config "echo 0x49 > /sys/bus/i2c/devices/i2c-7/$1" + i2c_config "echo 0x4a > /sys/bus/i2c/devices/i2c-7/$1" + i2c_config "echo 0x4b > /sys/bus/i2c/devices/i2c-7/$1" + i2c_config "echo 0x4c > /sys/bus/i2c/devices/i2c-7/$1" + i2c_config "echo 0x4f > /sys/bus/i2c/devices/i2c-7/$1" + i2c_config "echo 0x5e > /sys/bus/i2c/devices/i2c-10/$1" + i2c_config "echo 0x5e > /sys/bus/i2c/devices/i2c-11/$1" + i2c_config "echo 0x56 > /sys/bus/i2c/devices/i2c-10/$1" + i2c_config "echo 0x56 > /sys/bus/i2c/devices/i2c-11/$1" + i2c_config "echo 0x50 > /sys/bus/i2c/devices/i2c-15/$1" + i2c_config "echo 0x50 > /sys/bus/i2c/devices/i2c-16/$1" + i2c_config "echo 0x50 > /sys/bus/i2c/devices/i2c-17/$1" + ;; + *) echo "n3248te_platform: main_board_mux : invalid command !" + ;; + esac +} + +#Attach/Detach the SFP modules on PCA9548_2 +switch_board_sfp() { + case $1 in + "new_device") i2c_config "echo optoe2 0x50 > /sys/bus/i2c/devices/i2c-20/$1" + i2c_config "echo optoe2 0x50 > /sys/bus/i2c/devices/i2c-21/$1" + i2c_config "echo optoe2 0x50 > /sys/bus/i2c/devices/i2c-22/$1" + i2c_config "echo optoe2 0x50 > /sys/bus/i2c/devices/i2c-23/$1" + i2c_config "echo optoe1 0x50 > /sys/bus/i2c/devices/i2c-24/$1" + i2c_config "echo optoe1 0x50 > /sys/bus/i2c/devices/i2c-25/$1" + ;; + "delete_device") i2c_config "echo 0x50 > /sys/bus/i2c/devices/i2c-20/$1" + i2c_config "echo 0x50 > /sys/bus/i2c/devices/i2c-21/$1" + i2c_config "echo 0x50 > /sys/bus/i2c/devices/i2c-22/$1" + i2c_config "echo 0x50 > /sys/bus/i2c/devices/i2c-23/$1" + i2c_config "echo 0x50 > /sys/bus/i2c/devices/i2c-24/$1" + i2c_config "echo 0x50 > /sys/bus/i2c/devices/i2c-25/$1" + ;; + *) echo "n3248te_platform: switch_board_sfp: invalid command !" + ;; + esac +} + +#Forcibly bring quad-port phy out of reset for 48-1G port functionality + +platform_firmware_versions() { + +FIRMWARE_VERSION_FILE=/var/log/firmware_versions +rm -rf ${FIRMWARE_VERSION_FILE} +# Get BIOS version +echo "BIOS: `dmidecode -s system-version `" > $FIRMWARE_VERSION_FILE +# Get CPU CPLD version +echo "CPU CPLD: $((`cat /sys/devices/platform/dell-n3248te-cpld.0/cpu_cpld_mjr_ver`)).$((`cat /sys/devices/platform/dell-n3248te-cpld.0/cpu_cpld_mnr_ver`))" >> $FIRMWARE_VERSION_FILE +# Get SYS CPLD version +echo "SYS CPLD: $((`cat /sys/devices/platform/dell-n3248te-cpld.0/sys_cpld_mjr_ver`)).$((`cat /sys/devices/platform/dell-n3248te-cpld.0/sys_cpld_mnr_ver`))" >> $FIRMWARE_VERSION_FILE + +} + +install_python_api_package() { + device="/usr/share/sonic/device" + platform=$(/usr/local/bin/sonic-cfggen -H -v DEVICE_METADATA.localhost.platform) + + pip3 install $device/$platform/sonic_platform-1.0-py3-none-any.whl +} + +remove_python_api_package() { + rv=$(pip3 show sonic-platform > /dev/null 2>/dev/null) + if [ $? -eq 0 ]; then + rv=$(pip3 uninstall -y sonic-platform > /dev/null 2>/dev/null) + fi +} + +get_reboot_cause() { + REBOOT_REASON_FILE="/host/reboot-cause/platform/reboot_reason" + mkdir -p $(dirname $REBOOT_REASON_FILE) + + # Handle First Boot into software version with reboot cause determination support + if [[ ! -e $REBOOT_REASON_FILE ]]; then + echo "0x0" > $REBOOT_REASON_FILE + else + cat /sys/devices/platform/dell-n3248te-cpld.0/reboot_cause > $REBOOT_REASON_FILE + fi +} + + +if [[ "$1" == "init" ]]; then + modprobe i2c-dev + modprobe i2c-mux-pca954x force_deselect_on_exit=1 + modprobe pmbus + modprobe emc2305 + modprobe dps200 + modprobe dell_n3248te_platform + + sys_devices "new_device" + get_reboot_cause + switch_board_sfp "new_device" + echo 0xf0 > /sys/devices/platform/dell-n3248te-cpld.0/sfp_txdis + install_python_api_package + platform_firmware_versions +elif [[ "$1" == "deinit" ]]; then + switch_board_sfp "delete_device" + sysdevices "delete_device" + + modprobe -r dell_n3248te_platform + + modprobe -r dps200 + modprobe -r emc2305 + modprobe -r pmbus + modprobe -r i2c-mux-pca954x + modprobe -r i2c-dev + remove_python_api_package +else + echo "n3248te_platform : Invalid option !" +fi diff --git a/platform/broadcom/sonic-platform-modules-dell/n3248te/scripts/platform_sensors.py b/platform/broadcom/sonic-platform-modules-dell/n3248te/scripts/platform_sensors.py new file mode 100755 index 000000000000..02aa59595417 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-dell/n3248te/scripts/platform_sensors.py @@ -0,0 +1,136 @@ +#!/usr/bin/python +# This provies support for the following objects: +# * Onboard temperature sensors +# * FAN trays +# * PSU + + +import subprocess + +output = "" +try: + rc = 0 + output = subprocess.check_output('/usr/bin/sensors').splitlines() + + valid = False + for line in output: + if line.startswith('acpitz') or line.startswith('coretemp'): + valid = True + if valid: + print line + if line == '': valid = False + + print "Onboard Temperature Sensors:" + idx = 0 + for line in output: + if line.startswith('tmp75'): + print '\t' + output[idx+2].split('(')[0] + idx += 1 + + print "\nFanTrays:" + idx = 0 + found_emc = False + for line in output: + if line.startswith('emc'): + found_emc = True + with open('/sys/devices/platform/dell-n3248te-cpld.0/fan0_prs') as f: + line = f.readline() + present = int(line, 0) + if present : + print '\t' + 'FanTray1:' + print '\t\t' + 'Fan Speed:' + (output[idx+2].split('(')[0]).split(':')[1] + with open('/sys/devices/platform/dell-n3248te-cpld.0/fan0_dir') as f: + line = f.readline() + dir = 'Intake' if line[:-1] == 'B2F' else 'Exhaust' + print '\t\t' + 'Airflow:\t' + dir + else : print '\t' + 'FanTray1:\tNot Present' + + with open('/sys/devices/platform/dell-n3248te-cpld.0/fan1_prs') as f: + line = f.readline() + present = int(line, 0) + if present : + print '\t' + 'FanTray2:' + print '\t\t' + 'Fan Speed:' + (output[idx+3].split('(')[0]).split(':')[1] + with open('/sys/devices/platform/dell-n3248te-cpld.0/fan1_dir') as f: + line = f.readline() + dir = 'Intake' if line[:-1] == 'B2F' else 'Exhaust' + print '\t\t' + 'Airflow:\t' + dir + else : print '\t' + 'FanTray2:\tNot Present' + + with open('/sys/devices/platform/dell-n3248te-cpld.0/fan2_prs') as f: + line = f.readline() + present = int(line, 0) + if present : + print '\t' + 'FanTray3:' + print '\t\t' + 'Fan Speed:' + (output[idx+4].split('(')[0]).split(':')[1] + with open('/sys/devices/platform/dell-n3248te-cpld.0/fan2_dir') as f: + line = f.readline() + dir = 'Intake' if line[:-1] == 'B2F' else 'Exhaust' + print '\t\t' + 'Airflow:\t' + dir + else : print '\t' + 'FanTray3:\tNot Present' + idx += 1 + if not found_emc : + print '\t' + 'FanTray1:\tNot Present' + print '\t' + 'FanTray2:\tNot Present' + print '\t' + 'FanTray3:\tNot Present' + + print '\nPSUs:' + idx = 0 + with open('/sys/devices/platform/dell-n3248te-cpld.0/psu0_prs') as f: + line = f.readline() + found_psu1 = int(line, 0) + if not found_psu1 : + print '\tPSU1:\tNot Present' + with open('/sys/devices/platform/dell-n3248te-cpld.0/psu1_prs') as f: + line = f.readline() + found_psu2 = int(line, 0) + for line in output: + if line.startswith('dps460-i2c-10'): + with open('/sys/devices/platform/dell-n3248te-cpld.0/psu0_status') as f: + line = f.readline() + status = int(line, 0) + if not status : + print '\tPSU1:\tNot OK' + break + with open('/sys/bus/i2c/devices/10-0056/eeprom') as f: + line = f.readline() + dir = 'Exhaust' if 'FORWARD' in line else 'Intake' + print '\tPSU1:' + print '\t\t' + output[idx+2].split('(')[0] + print '\t\t' + output[idx+4].split('(')[0] + print '\t\t' + output[idx+6].split('(')[0] + print '\t\t' + output[idx+7].split('(')[0] + print '\t\t' + output[idx+9].split('(')[0] + print '\t\t' + output[idx+11].split('(')[0] + print '\t\t' + output[idx+12].split('(')[0] + print '\t\t' + output[idx+14].split('(')[0] + print '\t\t' + output[idx+15].split('(')[0] + print '\t\t' + 'Airflow:\t\t ' + dir + if line.startswith('dps460-i2c-11'): + with open('/sys/devices/platform/dell-n3248te-cpld.0/psu1_status') as f: + line = f.readline() + status = int(line, 0) + if not status : + print '\tPSU2:\tNot OK' + break + print '\tPSU2:' + with open('/sys/bus/i2c/devices/11-0056/eeprom') as f: + line = f.readline() + dir = 'Exhaust' if 'FORWARD' in line else 'Intake' + print '\t\t' + output[idx+2].split('(')[0] + print '\t\t' + output[idx+4].split('(')[0] + print '\t\t' + output[idx+6].split('(')[0] + print '\t\t' + output[idx+7].split('(')[0] + print '\t\t' + output[idx+9].split('(')[0] + print '\t\t' + output[idx+11].split('(')[0] + print '\t\t' + output[idx+12].split('(')[0] + print '\t\t' + output[idx+14].split('(')[0] + print '\t\t' + output[idx+15].split('(')[0] + print '\t\t' + 'Airflow:\t\t ' + dir + idx += 1 + if not found_psu2 : + print '\tPSU2:\tNot Present' + +except subprocess.CalledProcessError as err: + print ("Exception when calling get_sonic_error -> %s\n" %(err)) + rc = err.returncode diff --git a/platform/broadcom/sonic-platform-modules-dell/n3248te/scripts/portiocfg.py b/platform/broadcom/sonic-platform-modules-dell/n3248te/scripts/portiocfg.py new file mode 100755 index 000000000000..e81f8afa4470 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-dell/n3248te/scripts/portiocfg.py @@ -0,0 +1,105 @@ +#!/usr/bin/python +# Copyright (c) 2015 Dell Inc. +# +# Licensed under the Apache License, Version 2.0 (the "License"); you may +# not use this file except in compliance with the License. You may obtain +# a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 +# +# THIS CODE IS PROVIDED ON AN *AS IS* BASIS, WITHOUT WARRANTIES OR +# CONDITIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING WITHOUT +# LIMITATION ANY IMPLIED WARRANTIES OR CONDITIONS OF TITLE, FITNESS +# FOR A PARTICULAR PURPOSE, MERCHANTABLITY OR NON-INFRINGEMENT. +# +# See the Apache Version 2.0 License for specific language governing +# permissions and limitations under the License. +#Script to read/write the portio based registers + +import sys +import os +import getopt +import struct + +resource='/dev/port' + +def usage(): + ''' This is the Usage Method ''' + + print '\t\t portiocfg.py --default' + print '\t\t portiocfg.py --get --offset ' + print '\t\t portiocfg.py --set --val --offset ' + sys.exit(1) + +def portio_reg_read(resource,offset): + fd=os.open(resource, os.O_RDONLY) + if(fd<0): + print 'file open failed %s"%resource' + return + if(os.lseek(fd, offset, os.SEEK_SET) != offset): + print 'lseek failed on %s'%resource + return + buf=os.read(fd,1) + reg_val1=ord(buf) + print 'reg value %x'%reg_val1 + os.close(fd) + +def portio_reg_write(resource,offset,val): + fd=os.open(resource,os.O_RDWR) + if(fd<0): + print 'file open failed %s"%resource' + return + if(os.lseek(fd, offset, os.SEEK_SET) != offset): + print 'lseek failed on %s'%resource + return + ret=os.write(fd,struct.pack('B',val)) + if(ret != 1): + print 'write failed %d'%ret + return + os.close(fd) + +def main(argv): + + ''' The main function will read the user input from the + command line argument and process the request ''' + + opts = '' + val = '' + choice = '' + offset = '' + + try: + opts, args = getopt.getopt(argv, "hgs:" , \ + ["val=","offset=","help", "get", "set"]) + + except getopt.GetoptError: + usage() + + for opt,arg in opts: + + if opt in ('-h','--help'): + choice = 'help' + + elif opt in ('-g', '--get'): + choice = 'get' + + elif opt in ('-s', '--set'): + choice = 'set' + + elif opt == '--offset': + offset = int(arg,16) + + elif opt == '--val': + val = int(arg,16) + + if choice == 'get' and offset != '': + portio_reg_read(resource,offset) + + elif choice == 'set' and offset != '' and val != '': + portio_reg_write(resource,offset,val) + + else: + usage() + +#Calling the main method +if __name__ == "__main__": + main(sys.argv[1:]) + diff --git a/platform/broadcom/sonic-platform-modules-dell/n3248te/scripts/ports_xcvrd_notify.py b/platform/broadcom/sonic-platform-modules-dell/n3248te/scripts/ports_xcvrd_notify.py new file mode 100755 index 000000000000..c791590fb576 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-dell/n3248te/scripts/ports_xcvrd_notify.py @@ -0,0 +1,107 @@ +#!/usr/bin/env python3 + +""" + port_notify + port notify status change for SONiC +""" + +try: + from datetime import datetime + from swsscommon import swsscommon + from sonic_py_common import daemon_base, logger +except ImportError as e: + raise ImportError (str(e) + " - required module not found") + +# +# Constants ==================================================================== +# + +SYSLOG_IDENTIFIER = "port_notify" + + +STATE_PORT_TABLE = 'PORT_TABLE' + + +RJ45_PORT_START = 0; +RJ45_PORT_END = 47; + +# Global logger class instance +helper_logger = logger.Logger(SYSLOG_IDENTIFIER) + +XCVR_STATE_EMPTY = 0 +XCVR_STATE_ERROR = 1 +XCVR_STATE_INCOMP = 2 +XCVR_STATE_CONFIG = 3 +XCVR_STATE_READY = 4 +XCVR_STATE_TIMEOUT = 5 + +xcvr_state_tbl = { + XCVR_STATE_EMPTY: { "xcvr_state": "N/A", "xcvr_app_status": "down" }, + XCVR_STATE_ERROR: { "xcvr_state": "Error", "xcvr_app_status": "down" }, + XCVR_STATE_INCOMP: { "xcvr_state": "Incompatible", "xcvr_app_status": "up" }, + XCVR_STATE_CONFIG: { "xcvr_state": "Config", "xcvr_app_status": "down" }, + XCVR_STATE_TIMEOUT: { "xcvr_state": "Timeout", "xcvr_app_status": "up" }, + XCVR_STATE_READY: { "xcvr_state": "Ready", "xcvr_app_status": "up" } +} + +# Wait for port init is done +def wait_for_port_init_done(): + # Connect to APPL_DB and subscribe to PORT table notifications + appl_db = daemon_base.db_connect("APPL_DB") + + sel = swsscommon.Select() + sst = swsscommon.SubscriberStateTable(appl_db, swsscommon.APP_PORT_TABLE_NAME) + sel.addSelectable(sst) + + # Make sure this daemon started after all port configured + while True: + (state, c) = sel.select(1000) + if state == swsscommon.Select.TIMEOUT: + continue + if state != swsscommon.Select.OBJECT: + helper_logger.log_warning("sel.select() did not return swsscommon.Select.OBJECT") + continue + + (key, op, fvp) = sst.pop() + + # Wait until PortInitDone + if key in ["PortInitDone"]: + break + +def notify_port_xcvr_status(port_name, app_status_port_tbl, state_port_tbl, flag): + + fvs = swsscommon.FieldValuePairs([("xcvr_status", xcvr_state_tbl[flag]["xcvr_app_status"])]) + tm = datetime.now().strftime("%Y-%m-%d %H:%M:%S") + state_fvs = swsscommon.FieldValuePairs([("xcvr_status", xcvr_state_tbl[flag]["xcvr_state"]), ("xcvr_time", tm)]) + + state_port_tbl.set(port_name, state_fvs) + + app_status_port_tbl.set(port_name, fvs) + + helper_logger.log_notice("Port {} xcvr_app_status change to {}".format(port_name, xcvr_state_tbl[flag]["xcvr_app_status"])) + return True + + +def main(): + helper_logger.log_notice("Start port_notify") + # Connect to APP_DB and create transceiver dom info table + appl_db = daemon_base.db_connect("APPL_DB") + + app_status_port_tbl = swsscommon.ProducerStateTable(appl_db, + swsscommon.APP_PORT_APP_STATUS_TABLE_NAME) + + state_db = daemon_base.db_connect("STATE_DB") + state_port_tbl = swsscommon.Table(state_db, STATE_PORT_TABLE) + + # Wait for PortInitDone + wait_for_port_init_done() + + for port in range(RJ45_PORT_START, RJ45_PORT_END+1): + #print("Ethernet{}".format(port)) + notify_port_xcvr_status("Ethernet{}".format(port), app_status_port_tbl, state_port_tbl, XCVR_STATE_READY) + + helper_logger.log_notice("End port_notify") + + +if __name__ == '__main__': + main() diff --git a/platform/broadcom/sonic-platform-modules-dell/n3248te/scripts/sensors b/platform/broadcom/sonic-platform-modules-dell/n3248te/scripts/sensors new file mode 100755 index 000000000000..572b9d45e9e3 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-dell/n3248te/scripts/sensors @@ -0,0 +1,8 @@ +#!/bin/bash +#docker exec -i pmon sensors "$@" +docker exec -i pmon /usr/bin/platform_sensors.py "$@" + +#To probe sensors not part of lm-sensors +#if [ -r /usr/local/bin/platform_sensors.py ]; then +# python /usr/local/bin/platform_sensors.py +#fi diff --git a/platform/broadcom/sonic-platform-modules-dell/n3248te/setup.py b/platform/broadcom/sonic-platform-modules-dell/n3248te/setup.py new file mode 120000 index 000000000000..4f6de9941d96 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-dell/n3248te/setup.py @@ -0,0 +1 @@ +../s6100/setup.py \ No newline at end of file diff --git a/platform/broadcom/sonic-platform-modules-dell/n3248te/sonic_platform/__init__.py b/platform/broadcom/sonic-platform-modules-dell/n3248te/sonic_platform/__init__.py new file mode 100644 index 000000000000..3e1260e6b854 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-dell/n3248te/sonic_platform/__init__.py @@ -0,0 +1,8 @@ +""" +Module sonic_platform provides the platform dependent population of +platform.py, chassis.py, component.py, sfp.py, thermal.py, psu.py, +fan.py and watchdog.py +""" +__all__ = ["platform", "chassis", "sfp", "eeprom", "component", "thermal", "psu", "fan", "fan_drawer", "watchdog"] +from sonic_platform import * + diff --git a/platform/broadcom/sonic-platform-modules-dell/n3248te/sonic_platform/chassis.py b/platform/broadcom/sonic-platform-modules-dell/n3248te/sonic_platform/chassis.py new file mode 100644 index 000000000000..9686892f6f2a --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-dell/n3248te/sonic_platform/chassis.py @@ -0,0 +1,350 @@ +#!/usr/bin/env python + +############################################################################# +# DELLEMC N3248TE +# +# Module contains an implementation of SONiC Platform Base API and +# provides the platform information +# +############################################################################# + +try: + import os + import sys + import time + from sonic_platform_base.chassis_base import ChassisBase + from sonic_platform.sfp import Sfp + from sonic_platform.eeprom import Eeprom + from sonic_platform.component import Component + from sonic_platform.psu import Psu + from sonic_platform.thermal import Thermal + from sonic_platform.watchdog import Watchdog + from sonic_platform.fan import Fan + from sonic_platform.fan_drawer import FanDrawer +except ImportError as e: + raise ImportError(str(e) + "- required module not found") + + +MAX_N3248TE_FANTRAY = 3 +MAX_N3248TE_FAN = 1 +MAX_N3248TE_PSU = 2 +MAX_N3248TE_THERMAL = 5 +MAX_N3248TE_COMPONENT = 3 # BIOS, CPU CPLD and SYS CPLD + +media_part_num_list = set([ \ +"8T47V","XTY28","MHVPK","GF76J","J6FGD","F1KMV","9DN5J","H4DHD","6MCNV","0WRX0","X7F70","5R2PT","WTRD1","WTRD1","WTRD1","WTRD1","5250G","WTRD1","C5RNH","C5RNH","FTLX8571D3BCL-FC", +"C5RNH","5250G","N8TDR","7D64H","7D64H","RN84N","RN84N","HMTNW","6K3Y6","6K3Y6","TY5FM","50M0R","PGYJT","WP2PP","85Y13","1HCGH","FP9R1","FYD0M","C6Y7M","C6Y7M","V250M","V250M", +"5CWK6","5CWK6","53HVN","53HVN","358VV","358VV","MV799","MV799","YJF03","P9GND","T1KCN","1DXKP","MT7R2","K0T7R","W5G04","7TCDN","7TCDN","7TCDN","7TCDN","7TCDN","V3XJK","0MV31", +"5FVP7","N6KM9","C41MF","77KC3","XW7J0","V4NJV","2XJHY","H93DH","H93DH","F8CG0","F8CG0","F8CG0","119N6","WFMF5","794RX","288F6","1M31V","1M31V","5NP8R","5NP8R","4TC09","4TC09", +"FC6KV","FC6KV","J90VN","J90VN","05RH0","05RH0","YDN52","0C2YV","YDN52","0C2YV","9JT65","D7M6H","6GW14","FYVFW","0VF5H","P4YPY","P4YPY","TCPM2","TCPM2","JNPF8","JNPF8","27GG5", +"27GG5","P8T4W","P8T4W","JR54Y","M6N0J","XJYD0","K44H9","035KG","P7C7N","76V43","3CC35","FN4FC","26FN3","YFNDD","YFNDD","7R9N9","035KG","P7C7N","76V43","3CC35","PLRXPLSCS43811", +"FN4FC","26FN3","YFNDD","YFNDD","7R9N9","G86YJ","V407F","V407F","9KH6T","G86YJ","V407F","9KH6T","2JVDD","D0R73","VXFJY","9X8JP","2JVDD","D0R73","VXFJY","9X8JP","2JVDD","D0R73","VXFJY", +"9X8JP","GMFC5","GMFC5","GMFC5","D7P80","3MFXG","3MFXG","0GWXJ","THPF3","THPF3","THPF3","THPF3","THPF3","PJ62G","3XCX1","JJYKG","RRRTK","16K56","86JM2","K5R6C","7MG2C","WTPPN","9HTT2", +"NKM4F","VXGGG","JC9W6","6MR8M","RP3GV","M5PPJ","XKY55","TKCXT","05J8P","5WGKD","XFDRT","NW8DM","YPKH3","5WGKD","XFDRT","NW8DM","YPKH3","71XXK","MVCX6","0XYP6","HPPVW","3GHRT","71XXK", +"MVCX6","0XYP6","HPPVW","3GHRT","2X5T6","135V2","KD5MV","2X5T6","KD5MV","HHFK0","3YWG7","5CMT2","RCVP5","X5DH4","HHFK0","3YWG7","5CMT2","RCVP5","X5DH4","3YWG7","5CMT2","RCVP5","X5DH4", +"4WJ41","4WJ41","14NV5","14NV5","14NV5","4WGYD","YKMH7","X7CCC","X7CCC","0X9CT","0CY8V","P7D7R","W4GPP","W4GPP","W4GPP","HHHCHC","07RN7","07RN7","0YR96","0YR96","JCYM9","FTLX8571D3BCL", +"DDW0X","VPFDJ","229KM","9FC7D","DDW0X","VPFDJ","6FMR5","J7K20","N3K9W","6FMR5","8R4VM","7VN5T","D9YM8","8R4VM","VYXPW","87TPX","WY6FK","VYXPW","87TPX","WY6FK","WG8C4","N8K82","2DV6Y", +"77C3C","RC0HM","77C3C","RC0HM","JHXTN","3P3PG","92YVM","4VX5M","4VX5M","6RRGD","W4JWV","22V6R","XR11M","9GMDY","JMCWK","TP2F0","6MGDY","78RHK", "C0TP5","0WDNV","FCLF8522P2BTL"\ +]) +class Chassis(ChassisBase): + """ + DELLEMC Platform-specific Chassis class + """ + CPLD_DIR = '/sys/devices/platform/dell-n3248te-cpld.0/' + + _global_port_pres_dict = {} + + _sfpp_port_to_i2c_mapping = { + 49: 20, + 50: 21, + 51: 22, + 52: 23, + 53: 24, + 54: 25, + } + + def __init__(self): + ChassisBase.__init__(self) + # sfp.py will read eeprom contents and retrive the eeprom data. + # We pass the eeprom path from chassis.py + self.PORT_START = 1 + self.PORT_END = 54 + self.PORTS_IN_BLOCK = (self.PORT_END + 1) + self.SFP_PORT_START = 49 + self._sfp_port = range(self.SFP_PORT_START, self.PORTS_IN_BLOCK) + eeprom_base = "/sys/class/i2c-adapter/i2c-{0}/{0}-0050/eeprom" + for index in range(self.PORT_START, self.PORTS_IN_BLOCK): + eeprom_path = '' + if index in self._sfp_port: + eeprom_path = eeprom_base.format(self._sfpp_port_to_i2c_mapping[index]) + if(index < 53): + port_type = 'SFP' + else: + port_type = 'QSFP' + + sfp_node = Sfp(index, port_type, eeprom_path) + self._sfp_list.append(sfp_node) + + self._eeprom = Eeprom() + self._watchdog = Watchdog() + self._num_sfps = 54 + self._num_fans = MAX_N3248TE_FANTRAY * MAX_N3248TE_FAN + self._fan_list = [Fan(i, j) for i in range(MAX_N3248TE_FANTRAY) \ + for j in range(MAX_N3248TE_FAN)] + for k in range(MAX_N3248TE_FANTRAY): + fandrawer = FanDrawer(k) + self._fan_drawer_list.append(fandrawer) + self._fan_list.extend(fandrawer._fan_list) + + self._psu_list = [Psu(i) for i in range(MAX_N3248TE_PSU)] + self._thermal_list = [Thermal(i) for i in range(MAX_N3248TE_THERMAL)] + self._component_list = [Component(i) for i in range(MAX_N3248TE_COMPONENT)] + for port_num in self._sfp_port: + # sfp get uses zero-indexing, but port numbers start from 1 + presence = self.get_sfp(port_num-1).get_presence() + self._global_port_pres_dict[port_num] = '1' if presence else '0' + + self._watchdog = Watchdog() + self.locator_led_reg = "locator_led" + self.LOCATOR_LED_ON = "blink_blue" + self.LOCATOR_LED_OFF = self.STATUS_LED_COLOR_OFF + + def _get_cpld_register(self, reg_name): + # On successful read, returns the value read from given + # reg name and on failure rethrns 'ERR' + cpld_reg_file = self.CPLD_DIR + '/' + reg_name + try: + rv = open(cpld_reg_file, 'r').read() + except IOError : return 'ERR' + return rv.strip('\r\n').lstrip(' ') + + def _set_cpld_register(self, reg_name, value): + # On successful write, returns the value will be written on + # reg_name and on failure returns 'ERR' + rv = 'ERR' + cpld_reg_file = self.CPLD_DIR + '/' + reg_name + + if (not os.path.isfile(cpld_reg_file)): + #print "open error" + return rv + + try: + with open(cpld_reg_file, 'w') as fd: + rv = fd.write(str(value)) + except Exception: + rv = 'ERR' + + return rv + +# check for this event change for sfp / do we need to handle timeout/sleep + + def get_change_event(self, timeout=0): + """ + Returns a nested dictionary containing all devices which have + experienced a change at chassis level + """ + port_dict = {} + change_dict = {} + change_dict['sfp'] = port_dict + while True: + for port_num in self._sfp_port: + # sfp get uses zero-indexing, but port numbers start from 1 + presence = self.get_sfp(port_num-1).get_presence() + if(presence and self._global_port_pres_dict[port_num] == '0'): + self._global_port_pres_dict[port_num] = '1' + port_dict[port_num] = '1' + elif(not presence and self._global_port_pres_dict[port_num] == '1'): + self._global_port_pres_dict[port_num] = '0' + port_dict[port_num] = '0' + + if(len(port_dict) > 0): + return True, change_dict + + time.sleep(0.5) + + + + def get_sfp(self, index): + """ + Retrieves sfp represented by (0-based) index + + Args: + index: An integer, the index (0-based) of the sfp to retrieve. + The index should be the sequence of a physical port in a chassis, + starting from 0. + For example, 0 for Ethernet0, 1 for Ethernet4 and so on. + + Returns: + An object dervied from SfpBase representing the specified sfp + """ + sfp = None + + try: + # The index will start from 0 + sfp = self._sfp_list[index-1] + except IndexError: + sys.stderr.write("SFP index {} out of range (1-{})\n".format( + index, len(self._sfp_list))) + return sfp + + def get_name(self): + """ + Retrieves the name of the chassis + Returns: + string: The name of the chassis + """ + return self._eeprom.modelstr().decode() + + def get_presence(self): + """ + Retrieves the presence of the chassis + Returns: + bool: True if chassis is present, False if not + """ + return True + + def get_model(self): + """ + Retrieves the model number (or part number) of the chassis + Returns: + string: Model/part number of chassis + """ + return self._eeprom.part_number_str() + + def get_serial(self): + """ + Retrieves the serial number of the chassis (Service tag) + Returns: + string: Serial number of chassis + """ + return self._eeprom.serial_str() + + def get_status(self): + """ + Retrieves the operational status of the chassis + Returns: + bool: A boolean value, True if chassis is operating properly + False if not + """ + return True + + def get_base_mac(self): + """ + Retrieves the base MAC address for the chassis + Returns: + A string containing the MAC address in the format + 'XX:XX:XX:XX:XX:XX' + """ + return self._eeprom.base_mac_addr('') + + def get_serial_number(self): + """ + Retrieves the hardware serial number for the chassis + Returns: + A string containing the hardware serial number for this chassis. + """ + return self._eeprom.serial_number_str() + + def get_system_eeprom_info(self): + """ + Retrieves the full content of system EEPROM information for the chassis + Returns: + A dictionary where keys are the type code defined in + OCP ONIE TlvInfo EEPROM format and values are their corresponding + values. + """ + return self._eeprom.system_eeprom_info() + + def get_reboot_cause(self): + """ + Retrieves the cause of the previous reboot + Returns: + A tuple (string, string) where the first element is a string + containing the cause of the previous reboot. This string must be + one of the predefined strings in this class. If the first string + is "REBOOT_CAUSE_HARDWARE_OTHER", the second string can be used + to pass a description of the reboot cause. + """ + + reset_reason = int(self._get_cpld_register('reboot_cause'), 16) + + if (reset_reason & 0x02) : + return (ChassisBase.REBOOT_CAUSE_NON_HARDWARE, 'Shutdown by CPU') + elif (reset_reason & 0x04) : + return (ChassisBase.REBOOT_CAUSE_NON_HARDWARE, "Failed to boot from configured boot device") + elif (reset_reason & 0x8) : + return (ChassisBase.REBOOT_CAUSE_NON_HARDWARE, "Booted from Backup BIOS") + elif (reset_reason & 0x10) : + return(ChassisBase.REBOOT_CAUSE_WATCHDOG, None) + elif (reset_reason & 0x20): + return(ChassisBase.REBOOT_CAUSE_THERMAL_OVERLOAD_CPU) + elif (reset_reason & 0x40) : + return (ChassisBase.REBOOT_CAUSE_NON_HARDWARE, 'Warm Reset') + elif (reset_reason & 0x80) : + return (ChassisBase.REBOOT_CAUSE_NON_HARDWARE, 'Cold Reset') + elif (reset_reason & 0x01) : + return (ChassisBase.REBOOT_CAUSE_POWER_LOSS, None) + + def get_eeprom(self): + """ + Retrieves the Sys Eeprom instance for the chassis. + Returns : + The instance of the Sys Eeprom + """ + return self._eeprom + + def get_num_fans(self): + """ + Retrives the number of Fans on the chassis. + Returns : + An integer represents the number of Fans on the chassis. + """ + return self._num_fans + + def get_num_sfps(self): + """ + Retrives the numnber of Media on the chassis. + Returns: + An integer represences the number of SFPs on the chassis. + """ + return self._num_sfps + + def get_qualified_media_list(self): + return media_part_num_list + + def set_locator_led(self, color): + """ + Sets the state of the Chassis Locator LED + + Args: + color: A string representing the color with which to set the Chassis Locator LED + + Returns: + bool: True if the Chassis Locator LED state is set successfully, False if not + + """ + if color == self.LOCATOR_LED_ON or color == self.LOCATOR_LED_OFF: + rv = self._set_cpld_register(self.locator_led_reg, color) + if (rv != 'ERR'): + return True + else: + return False + + def get_locator_led(self): + """ + Gets the state of the Chassis Locator LED + + Returns: + LOCATOR_LED_ON or LOCATOR_LED_OFF + """ + loc_led = self._get_cpld_register(self.locator_led_reg) + if (loc_led != 'ERR'): + # Actually driver returns the color code 'blink_blue' + # Returning "blue_blink" to make it common to all platforms output + if (loc_led == self.LOCATOR_LED_ON): + self.LOCATOR_LED_ON = self.STATUS_LED_COLOR_BLUE_BLINK + return self.LOCATOR_LED_ON + else: + return self.LOCATOR_LED_OFF + else: + return self.LOCATOR_LED_OFF diff --git a/platform/broadcom/sonic-platform-modules-dell/n3248te/sonic_platform/component.py b/platform/broadcom/sonic-platform-modules-dell/n3248te/sonic_platform/component.py new file mode 100644 index 000000000000..ec0dba2ab5b9 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-dell/n3248te/sonic_platform/component.py @@ -0,0 +1,82 @@ +#!/usr/bin/env python + +######################################################################## +# DELLEMC N3248TE +# +# Module contains an implementation of SONiC Platform Base API and +# provides the Components' (e.g., BIOS, CPLD, FPGA, BMC etc.) available in +# the platform +# +######################################################################## + +try: + import subprocess + from sonic_platform_base.component_base import ComponentBase + +except ImportError as e: + raise ImportError(str(e) + "- required module not found") +def get_bios_version(): + return subprocess.check_output(['dmidecode', '-s', 'system-version']).strip().decode() + +def get_cpld_version(cpld): + mjr_ver=subprocess.check_output('cat /sys/devices/platform/dell-n3248te-cpld.0/' + cpld + '_mjr_ver', shell=True).strip()[2:].decode() + mnr_ver=subprocess.check_output('cat /sys/devices/platform/dell-n3248te-cpld.0/' + cpld + '_mnr_ver', shell=True).strip()[2:].decode() + return (str(mjr_ver) + '.' + str(mnr_ver)) + +class Component(ComponentBase): + """DellEMC Platform-specific Component class""" + + CHASSIS_COMPONENTS = [ + ['BIOS', + 'Performs initialization of hardware components during booting', + get_bios_version() + ], + ['CPU CPLD', + 'Used for managing the CPU power sequence and CPU states', + get_cpld_version('cpu_cpld') + ], + ['SYS CPLD', + 'Used for managing FAN, PSU, SFP modules (1-48) SFP Plus modules (49-62)', + get_cpld_version('sys_cpld') + ] + ] + + def __init__(self, component_index=0): + self.index = component_index + self.name = self.CHASSIS_COMPONENTS[self.index][0] + self.description = self.CHASSIS_COMPONENTS[self.index][1] + self.version = self.CHASSIS_COMPONENTS[self.index][2] + + def get_name(self): + """ + Retrieves the name of the component + Returns: + A string containing the name of the component + """ + return self.name + + def get_description(self): + """ + Retrieves the description of the component + Returns: + A string containing the description of the component + """ + return self.description + + def get_firmware_version(self): + """ + Retrieves the firmware version of the component + Returns: + A string containing the firmware version of the component + """ + return self.version + + def install_firmware(self, image_path): + """ + Installs firmware to the component + Args: + image_path: A string, path to firmware image + Returns: + A boolean, True if install was successful, False if not + """ + return False diff --git a/platform/broadcom/sonic-platform-modules-dell/n3248te/sonic_platform/eeprom.py b/platform/broadcom/sonic-platform-modules-dell/n3248te/sonic_platform/eeprom.py new file mode 100644 index 000000000000..75584cbc80b0 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-dell/n3248te/sonic_platform/eeprom.py @@ -0,0 +1,134 @@ +#!/usr/bin/env python + +############################################################################# +# DellEmc Z9332F +# +# Platform and model specific eeprom subclass, inherits from the base class, +# and provides the followings: +# - the eeprom format definition +# - specific encoder/decoder if there is special need +############################################################################# +try: + import os.path + from sonic_eeprom import eeprom_tlvinfo + import binascii +except ImportError as e: + raise ImportError(str(e) + "- required module not found") + + +class Eeprom(eeprom_tlvinfo.TlvInfoDecoder): + + def __init__(self): + self.eeprom_path = None + f = '/sys/class/i2c-adapter/i2c-2/2-0050/eeprom' + if not os.path.exists(f): + return + self.eeprom_path = f + super(Eeprom, self).__init__(self.eeprom_path, 0, '', True) + self.eeprom_tlv_dict = dict() + try: + self.eeprom_data = self.read_eeprom() + except Exception: + self.eeprom_data = "N/A" + raise RuntimeError("Eeprom is not Programmed") + + eeprom = self.eeprom_data + + if not self.is_valid_tlvinfo_header(eeprom): + return + + total_length = ((eeprom[9]) << 8) | (eeprom[10]) + tlv_index = self._TLV_INFO_HDR_LEN + tlv_end = self._TLV_INFO_HDR_LEN + total_length + + while (tlv_index + 2) < len(eeprom) and tlv_index < tlv_end: + if not self.is_valid_tlv(eeprom[tlv_index:]): + break + + tlv = eeprom[tlv_index:tlv_index + 2 + + (eeprom[tlv_index + 1])] + code = "0x%02X" % ((tlv[0])) + + + name, value = self.decoder(None, tlv) + + self.eeprom_tlv_dict[code] = value + if (eeprom[tlv_index]) == self._TLV_CODE_CRC_32: + break + + tlv_index += (eeprom[tlv_index+1]) + 2 + + def serial_number_str(self): + """ + Returns the serial number + """ + (is_valid, results) = self.get_tlv_field( + self.eeprom_data, self._TLV_CODE_SERIAL_NUMBER) + if not is_valid: + return "N/A" + return results[2].decode('ascii') + + def base_mac_addr(self, e): + """ + Returns the base mac address found in the system EEPROM + """ + (is_valid, t) = self.get_tlv_field( + self.eeprom_data, self._TLV_CODE_MAC_BASE) + if not is_valid or t[1] != 6: + return super(eeprom_tlvinfo.TlvInfoDecoder, self).switchaddrstr(t) + + return ":".join([binascii.b2a_hex(T) for T in t[2]]) + + def modelstr(self): + """ + Returns the Model name + """ + (is_valid, results) = self.get_tlv_field( + self.eeprom_data, self._TLV_CODE_PRODUCT_NAME) + if not is_valid: + return "N/A" + + return results[2] + + def part_number_str(self): + """ + Returns the part number + """ + (is_valid, results) = self.get_tlv_field( + self.eeprom_data, self._TLV_CODE_PART_NUMBER) + if not is_valid: + return "N/A" + + return results[2] + + def serial_str(self): + """ + Returns the servicetag number + """ + (is_valid, results) = self.get_tlv_field( + self.eeprom_data, self._TLV_CODE_SERVICE_TAG) + if not is_valid: + return "N/A" + + return results[2] + + def revision_str(self): + """ + Returns the device revision + """ + (is_valid, results) = self.get_tlv_field( + self.eeprom_data, self._TLV_CODE_DEVICE_VERSION) + if not is_valid: + return "N/A" + + return results[2] + + def system_eeprom_info(self): + """ + Returns a dictionary, where keys are the type code defined in + ONIE EEPROM format and values are their corresponding values + found in the system EEPROM. + """ + return self.eeprom_tlv_dict + + diff --git a/platform/broadcom/sonic-platform-modules-dell/n3248te/sonic_platform/fan.py b/platform/broadcom/sonic-platform-modules-dell/n3248te/sonic_platform/fan.py new file mode 100644 index 000000000000..873ae4163a84 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-dell/n3248te/sonic_platform/fan.py @@ -0,0 +1,169 @@ +#!/usr/bin/env python + +######################################################################## +# DellEMC Z9332F +# +# Module contains an implementation of SONiC Platform Base API and +# provides the Fans' information which are available in the platform. +# +######################################################################## +try: + import os + from sonic_platform_base.fan_base import FanBase +except ImportError as e: + raise ImportError(str(e) + "- required module not found") + + +class Fan(FanBase): + """DellEMC Platform-specific Fan class""" + + def __init__(self, fantray_index=0, fan_index=0, psu_fan=False, dependency=None): + self.is_psu_fan = psu_fan + + if not self.is_psu_fan: + # API index is starting from 0, DellEMC platform index is + # starting from 1 + self.presence_reg = "fan{}_prs".format(fantray_index) + self.dir_reg = "fan{}_dir".format(fantray_index) + self.rpm_file = "/sys/bus/i2c/devices/7-002c/fan{}_input".format(fantray_index+1) + self.eeprom = "/sys/bus/i2c/devices/{}-0050/eeprom".format(15 + fantray_index) + self.fantray_index = fantray_index + else: + self.presence_reg = "psu{}_prs".format(fantray_index) + self.psu_index = fantray_index + self.dependancy = dependency + self.dir_reg = "" + self.dps_hwmon = "/sys/bus/i2c/devices/{}-005e/hwmon/".format(fantray_index+10) + self.eeprom = "/sys/bus/i2c/devices/{}-0056/eeprom".format(10 + fantray_index) + self.max_speed = 0 + + def _get_cpld_register(self, reg_name): + # On successful read, returns the value read from given + # reg name and on failure rethrns 'ERR' + cpld_dir = "/sys/devices/platform/dell-n3248te-cpld.0/" + cpld_reg_file = cpld_dir + '/' + reg_name + try: + buf = open(cpld_reg_file, 'r').read() + except (IOError, AttributeError): + return 'ERR' + return buf.strip('\r\n').lstrip(' ') + + def get_name(self): + """ + Retrieves the name of the device + Returns: + String: The name of the device + """ + if self.is_psu_fan: + return "PSU{} Fan".format(self.psu_index) + else: + return "Fan{}".format(self.fantray_index+1) + + def get_model(self): + """ + Retrieves the part number of the FAN + Returns: + String: Part number of FAN + """ + try: + val = open(self.eeprom, "rb").read()[13:19] + except Exception: + val = None + return val.decode() + + def get_serial(self): + """ + Retrieves the serial number of the FAN + Returns: + String: Serial number of FAN + """ + try: + val = open(self.eeprom, "rb").read()[21:41] + except Exception: + val = None + return val.decode() + + def get_presence(self): + """ + Retrieves the presence of the FAN + Returns: + bool: True if fan is present, False if not + """ + + presence = self._get_cpld_register(self.presence_reg) + if presence == 'ERR': + return False + if int(presence,0) == 1: + return True + + def get_status(self): + """ + Retrieves the operational status of the FAN + Returns: + bool: True if FAN is operating properly, False if not + """ + return True + + def get_direction(self): + """ + Retrieves the fan airfow direction + Returns: + A string, either FAN_DIRECTION_INTAKE or FAN_DIRECTION_EXHAUST + depending on fan direction + + Notes: + In DellEMC platforms, + - Forward/Exhaust : Air flows from Port side to Fan side. + - Reverse/Intake : Air flows from Fan side to Port side. + """ + if not self.is_psu_fan: + val = self._get_cpld_register(self.dir_reg) + direction = 'Exhaust' if val == 'F2B' else 'Intake' + if direction == 'ERR': + return None + else: + try: + val = open(self.eeprom, "rb").read()[0xe1:0xe8] + except Exception: + return None + direction = 'Exhaust' if val == 'FORWARD' else 'Intake' + return direction + + def get_speed(self): + """ + Retrieves the speed of the fan + Returns: + int: percentage of the max fan speed + """ + if self.max_speed == 0: + self.max_speed = 23500 + fan_speed = 0 + try: + if not self.is_psu_fan: + rpm_file = self.rpm_file + else: + dps_dir = self.dps_hwmon + '/' + os.listdir(self.dps_hwmon)[0] + rpm_file = dps_dir + '/' + 'fan1_input' + fan_speed = int(open(rpm_file, "rb").read()) + except Exception: + return None + speed = (100 * fan_speed)//self.max_speed + return speed + + def get_speed_rpm(self): + """ + Retrieves the speed of the fan + Returns: + int: percentage of the max fan speed + """ + fan_speed = 0 + try: + if not self.is_psu_fan: + rpm_file = self.rpm_file + else: + dps_dir = self.dps_hwmon + '/' + os.listdir(self.dps_hwmon)[0] + rpm_file = dps_dir + '/' + 'fan1_input' + fan_speed = int(open(rpm_file, "rb").read()) + except Exception: + return None + return fan_speed diff --git a/platform/broadcom/sonic-platform-modules-dell/n3248te/sonic_platform/fan_drawer.py b/platform/broadcom/sonic-platform-modules-dell/n3248te/sonic_platform/fan_drawer.py new file mode 100644 index 000000000000..5142827554db --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-dell/n3248te/sonic_platform/fan_drawer.py @@ -0,0 +1,37 @@ +#!/usr/bin/env python + +######################################################################## +# DellEMC N3248TE +# +# Module contains an implementation of SONiC Platform Base API and +# provides the Fan-Drawers' information available in the platform. +# +######################################################################## + +try: + from sonic_platform_base.fan_drawer_base import FanDrawerBase + from sonic_platform.fan import Fan +except ImportError as e: + raise ImportError(str(e) + "- required module not found") + +N3248TE_FANS_PER_FANTRAY = 2 + + +class FanDrawer(FanDrawerBase): + """DellEMC Platform-specific Fan class""" + + def __init__(self, fantray_index): + + FanDrawerBase.__init__(self) + # FanTray is 1-based in DellEMC platforms + self.fantrayindex = fantray_index + 1 + for i in range(N3248TE_FANS_PER_FANTRAY): + self._fan_list.append(Fan(fantray_index, i)) + + def get_name(self): + """ + Retrieves the fan drawer name + Returns: + string: The name of the device + """ + return "FanTray{}".format(self.fantrayindex) diff --git a/platform/broadcom/sonic-platform-modules-dell/n3248te/sonic_platform/platform.py b/platform/broadcom/sonic-platform-modules-dell/n3248te/sonic_platform/platform.py new file mode 100644 index 000000000000..996d94cf5a6e --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-dell/n3248te/sonic_platform/platform.py @@ -0,0 +1,24 @@ +#!/usr/bin/env python + +############################################################################# +# +# Module contains an implementation of SONiC Platform Base API and +# provides the platform information +# +############################################################################# + +try: + from sonic_platform_base.platform_base import PlatformBase + from sonic_platform.chassis import Chassis +except ImportError as e: + raise ImportError(str(e) + "- required module not found") + + +class Platform(PlatformBase): + """ + DELLEMC Platform-specific class + """ + + def __init__(self): + PlatformBase.__init__(self) + self._chassis = Chassis() diff --git a/platform/broadcom/sonic-platform-modules-dell/n3248te/sonic_platform/psu.py b/platform/broadcom/sonic-platform-modules-dell/n3248te/sonic_platform/psu.py new file mode 100644 index 000000000000..30d4f2bd6c2a --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-dell/n3248te/sonic_platform/psu.py @@ -0,0 +1,207 @@ +#!/usr/bin/env python + +######################################################################## +# DellEMC Z9332F +# +# Module contains an implementation of SONiC Platform Base API and +# provides the PSUs' information which are available in the platform +# +######################################################################## + +try: + import os + from sonic_platform_base.psu_base import PsuBase + from sonic_platform.fan import Fan +except ImportError as e: + raise ImportError(str(e) + "- required module not found") + + +class Psu(PsuBase): + """DellEMC Platform-specific PSU class""" + + def __init__(self, psu_index): + PsuBase.__init__(self) + self.index = psu_index + 1 # PSU is 1-based in DellEMC platforms + self.psu_presence_reg = "psu{}_prs".format(psu_index) + self.psu_status = "psu{}_status".format(psu_index) + self.eeprom = "/sys/bus/i2c/devices/{}-0056/eeprom".format(10+psu_index) + self.psu_voltage_reg = 'in3_input' + self.psu_current_reg = 'curr2_input' + self.psu_power_reg = 'power2_input' + self.dps_hwmon = "/sys/bus/i2c/devices/{}-005e/hwmon/".format(10 + psu_index) + self.dps_hwmon_exist = os.path.exists(self.dps_hwmon) + self._fan_list.append(Fan(fan_index=self.index, psu_fan=True, dependency=self)) + + def _get_cpld_register(self, reg_name): + # On successful read, returns the value read from given + # reg name and on failure rethrns 'ERR' + cpld_dir = "/sys/devices/platform/dell-n3248te-cpld.0/" + cpld_reg_file = cpld_dir + '/' + reg_name + try: + rv = open(cpld_reg_file, 'r').read() + except IOError : return 'ERR' + return rv.strip('\r\n').lstrip(' ') + + def _get_dps_register(self, reg_name): + try : + dps_dir = self.dps_hwmon + '/' + os.listdir(self.dps_hwmon)[0] + dps_reg_file = dps_dir + '/' + reg_name + rv = open(dps_reg_file, 'r').read() + except (IOError, OSError) : return 'ERR' + return rv + + def get_name(self): + """ + Retrieves the name of the device + + Returns: + string: The name of the device + """ + return "PSU{}".format(self.index) + + def _reload_dps_module(self): + try: + del_cmd = "echo 0x56 > /sys/bus/i2c/devices/i2c-{}/delete_device".format(10 + self.index - 1) + os.system(del_cmd) + except (IOError, OSError): + pass + try: + del_cmd = "echo 0x5e > /sys/bus/i2c/devices/i2c-{}/delete_device".format(10 + self.index - 1) + os.system(del_cmd) + except (IOError, OSError): + pass + try: + ins_cmd = "echo '24c02 0x56' > /sys/bus/i2c/devices/i2c-{}/new_device".format(10 + self.index - 1) + os.system(ins_cmd) + ins_cmd = "echo 'dps460 0x5e' > /sys/bus/i2c/devices/i2c-{}/new_device".format(10 + self.index - 1) + os.system(ins_cmd) + except (IOError, OSError): + pass + + def get_presence(self): + """ + Retrieves the presence of the Power Supply Unit (PSU) + + Returns: + bool: True if PSU is present, False if not + """ + presence = self._get_cpld_register(self.psu_presence_reg).strip() + if presence == 'ERR' : return False + if not self.dps_hwmon_exist and int(presence, 0): + self.dps_hwmon_exist = os.path.exists(self.dps_hwmon) + if not self.dps_hwmon_exist: + self._reload_dps_module() + return int(presence, 0) + + def get_model(self): + """ + Retrieves the part number of the PSU + + Returns: + string: Part number of PSU + """ + try: val = open(self.eeprom, "rb").read()[0x50:0x62] + except Exception: + val = None + return val.decode() + + def get_serial(self): + """ + Retrieves the serial number of the PSU + + Returns: + string: Serial number of PSU + """ + try: val = open(self.eeprom, "rb").read()[0xc4:0xd9] + except Exception: + val = None + return val.decode() + + def get_status(self): + """ + Retrieves the operational status of the PSU + + Returns: + bool: True if PSU is operating properly, False if not + """ + status = self._get_cpld_register(self.psu_status).strip() + if status == 'ERR' : return False + return int(status, 0) + + def get_voltage(self): + """ + Retrieves current PSU voltage output + + Returns: + A float number, the output voltage in volts, + e.g. 12.1 + """ + volt_reading = self._get_dps_register(self.psu_voltage_reg) + try: + voltage = int(volt_reading)/1000 + except Exception: + return None + return "{:.1f}".format(voltage) + + def get_current(self): + """ + Retrieves present electric current supplied by PSU + + Returns: + A float number, electric current in amperes, + e.g. 15.4 + """ + curr_reading = self._get_dps_register(self.psu_current_reg) + try: + current = int(curr_reading)/1000 + except Exception: + return None + return "{:.1f}".format(current) + + def get_power(self): + """ + Retrieves current energy supplied by PSU + + Returns: + A float number, the power in watts, + e.g. 302.6 + """ + power_reading = self._get_dps_register(self.psu_power_reg) + try: + power = int(power_reading)/1000 + except Exception: + return None + return "{:.1f}".format(power) + + def get_powergood_status(self): + """ + Retrieves the powergood status of PSU + + Returns: + A boolean, True if PSU has stablized its output voltages and + passed all its internal self-tests, False if not. + """ + power_good = self._get_cpld_register(self.psu_status).strip() + if power_good == 'ERR' : return False + return int(power_good, 0) + + def get_mfr_id(self): + """ + Retrives the Manufacturer Id of PSU + + Returns: + A string, the manunfacturer id. + """ + return 'DELTA' + + def get_type(self): + """ + Retrives the Power Type of PSU + + Returns : + A string, PSU power type + """ + try: val = open(self.eeprom, "rb").read()[0xe8:0xea] + except Exception: + return None + return val diff --git a/platform/broadcom/sonic-platform-modules-dell/n3248te/sonic_platform/sfp.py b/platform/broadcom/sonic-platform-modules-dell/n3248te/sonic_platform/sfp.py new file mode 100644 index 000000000000..be10fd7d35b0 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-dell/n3248te/sonic_platform/sfp.py @@ -0,0 +1,783 @@ +#!/usr/bin/env python + +############################################################################# +# DELLEMC S5248F +# +# Module contains an implementation of SONiC Platform Base API and +# provides the platform information +# +############################################################################# + +try: + import os + import struct + import mmap + from sonic_platform_base.sfp_base import SfpBase + from sonic_platform_base.sonic_sfp.sff8436 import sff8436InterfaceId + from sonic_platform_base.sonic_sfp.sff8436 import sff8436Dom + from sonic_platform_base.sonic_sfp.sff8472 import sff8472InterfaceId + from sonic_platform_base.sonic_sfp.sff8472 import sff8472Dom + +except ImportError as e: + raise ImportError(str(e) + "- required module not found") + +PAGE_OFFSET = 0 +KEY_OFFSET = 1 +KEY_WIDTH = 2 +FUNC_NAME = 3 + +QSFP_INFO_OFFSET = 128 +QSFP_DOM_OFFSET = 0 +QSFP_DOM_OFFSET1 = 384 + +SFP_PORT_START = 49 +SFP_PORT_END = 54 + +SFP_INFO_OFFSET = 0 +SFP_DOM_OFFSET = 256 + +SFP_STATUS_CONTROL_OFFSET = 110 +SFP_STATUS_CONTROL_WIDTH = 7 +SFP_TX_DISABLE_HARD_BIT = 7 +SFP_TX_DISABLE_SOFT_BIT = 6 + +qsfp_cable_length_tup = ('Length(km)', 'Length OM3(2m)', 'Length OM2(m)', + 'Length OM1(m)', 'Length Cable Assembly(m)') + +qsfp_compliance_code_tup = ( + '10/40G Ethernet Compliance Code', + 'SONET Compliance codes', + 'SAS/SATA compliance codes', + 'Gigabit Ethernet Compliant codes', + 'Fibre Channel link length/Transmitter Technology', + 'Fibre Channel transmission media', + 'Fibre Channel Speed') + +sfp_cable_length_tup = ('LengthSMFkm-UnitsOfKm', 'LengthSMF(UnitsOf100m)', + 'Length50um(UnitsOf10m)', 'Length62.5um(UnitsOfm)', + 'LengthOM3(UnitsOf10m)', 'LengthCable(UnitsOfm)') + +sfp_compliance_code_tup = ('10GEthernetComplianceCode', 'InfinibandComplianceCode', + 'ESCONComplianceCodes', 'SONETComplianceCodes', + 'EthernetComplianceCodes', 'FibreChannelLinkLength', + 'FibreChannelTechnology', 'SFP+CableTechnology', + 'FibreChannelTransmissionMedia', 'FibreChannelSpeed') + +info_dict_keys = ['type', 'hardware_rev', 'serial', + 'manufacturer', 'model', 'connector', + 'encoding', 'ext_identifier', 'ext_rateselect_compliance', + 'cable_type', 'cable_length', 'nominal_bit_rate', + 'specification_compliance', 'type_abbrv_name','vendor_date', 'vendor_oui'] + +dom_dict_keys = ['rx_los', 'tx_fault', 'reset_status', + 'power_lpmode', 'tx_disable', 'tx_disable_channel', + 'temperature', 'voltage', 'rx1power', + 'rx2power', 'rx3power', 'rx4power', + 'tx1bias', 'tx2bias', 'tx3bias', + 'tx4bias', 'tx1power', 'tx2power', + 'tx3power', 'tx4power'] + +threshold_dict_keys = ['temphighalarm', 'temphighwarning', + 'templowalarm', 'templowwarning', + 'vcchighalarm', 'vcchighwarning', + 'vcclowalarm', 'vcclowwarning', + 'rxpowerhighalarm', 'rxpowerhighwarning', + 'rxpowerlowalarm', 'rxpowerlowwarning', + 'txpowerhighalarm', 'txpowerhighwarning', + 'txpowerlowalarm', 'txpowerlowwarning', + 'txbiashighalarm', 'txbiashighwarning', + 'txbiaslowalarm', 'txbiaslowwarning'] + +sff8436_parser = { + 'reset_status': [QSFP_DOM_OFFSET, 2, 1, 'parse_dom_status_indicator'], + 'rx_los': [QSFP_DOM_OFFSET, 3, 1, 'parse_dom_tx_rx_los'], + 'tx_fault': [QSFP_DOM_OFFSET, 4, 1, 'parse_dom_tx_fault'], + 'tx_disable': [QSFP_DOM_OFFSET, 86, 1, 'parse_dom_tx_disable'], + 'power_lpmode': [QSFP_DOM_OFFSET, 93, 1, 'parse_dom_power_control'], + 'power_override': [QSFP_DOM_OFFSET, 93, 1, 'parse_dom_power_control'], + 'Temperature': [QSFP_DOM_OFFSET, 22, 2, 'parse_temperature'], + 'Voltage': [QSFP_DOM_OFFSET, 26, 2, 'parse_voltage'], + 'ChannelMonitor': [QSFP_DOM_OFFSET, 34, 16, 'parse_channel_monitor_params'], + 'ChannelMonitor_TxPower': + [QSFP_DOM_OFFSET, 34, 24, 'parse_channel_monitor_params_with_tx_power'], + + 'cable_type': [QSFP_INFO_OFFSET, -1, -1, 'parse_sfp_info_bulk'], + 'cable_length': [QSFP_INFO_OFFSET, -1, -1, 'parse_sfp_info_bulk'], + 'connector': [QSFP_INFO_OFFSET, 0, 20, 'parse_sfp_info_bulk'], + 'type': [QSFP_INFO_OFFSET, 0, 20, 'parse_sfp_info_bulk'], + 'encoding': [QSFP_INFO_OFFSET, 0, 20, 'parse_sfp_info_bulk'], + 'ext_identifier': [QSFP_INFO_OFFSET, 0, 20, 'parse_sfp_info_bulk'], + 'ext_rateselect_compliance': + [QSFP_INFO_OFFSET, 0, 20, 'parse_sfp_info_bulk'], + 'nominal_bit_rate': [QSFP_INFO_OFFSET, 0, 20, 'parse_sfp_info_bulk'], + 'specification_compliance': + [QSFP_INFO_OFFSET, 0, 20, 'parse_sfp_info_bulk'], + 'type_abbrv_name': [QSFP_INFO_OFFSET, 0, 20, 'parse_sfp_info_bulk'], + 'manufacturer': [QSFP_INFO_OFFSET, 20, 16, 'parse_vendor_name'], + 'vendor_oui': [QSFP_INFO_OFFSET, 37, 3, 'parse_vendor_oui'], + 'model': [QSFP_INFO_OFFSET, 40, 16, 'parse_vendor_pn'], + 'hardware_rev': [QSFP_INFO_OFFSET, 56, 2, 'parse_vendor_rev'], + 'serial': [QSFP_INFO_OFFSET, 68, 16, 'parse_vendor_sn'], + 'vendor_date': [QSFP_INFO_OFFSET, 84, 8, 'parse_vendor_date'], + 'dom_capability': [QSFP_INFO_OFFSET, 92, 1, 'parse_qsfp_dom_capability'], + 'dom_rev': [QSFP_DOM_OFFSET, 1, 1, 'parse_sfp_dom_rev'], + 'ModuleThreshold': [QSFP_DOM_OFFSET1, 128, 24, 'parse_module_threshold_values'], + 'ChannelThreshold': [QSFP_DOM_OFFSET1, 176, 16, 'parse_channel_threshold_values'], +} + +sff8472_parser = { + 'Temperature': [SFP_DOM_OFFSET, 96, 2, 'parse_temperature'], + 'Voltage': [SFP_DOM_OFFSET, 98, 2, 'parse_voltage'], + 'ChannelMonitor': [SFP_DOM_OFFSET, 100, 6, 'parse_channel_monitor_params'], + + 'cable_type': [SFP_INFO_OFFSET, -1, -1, 'parse_sfp_info_bulk'], + 'cable_length': [SFP_INFO_OFFSET, -1, -1, 'parse_sfp_info_bulk'], + 'connector': [SFP_INFO_OFFSET, 0, 21, 'parse_sfp_info_bulk'], + 'type': [SFP_INFO_OFFSET, 0, 21, 'parse_sfp_info_bulk'], + 'encoding': [SFP_INFO_OFFSET, 0, 21, 'parse_sfp_info_bulk'], + 'ext_identifier': [SFP_INFO_OFFSET, 0, 21, 'parse_sfp_info_bulk'], + 'ext_rateselect_compliance': + [SFP_INFO_OFFSET, 0, 21, 'parse_sfp_info_bulk'], + 'nominal_bit_rate': [SFP_INFO_OFFSET, 0, 21, 'parse_sfp_info_bulk'], + 'specification_compliance': + [SFP_INFO_OFFSET, 0, 21, 'parse_sfp_info_bulk'], + 'type_abbrv_name': [SFP_INFO_OFFSET, 0, 21, 'parse_sfp_info_bulk'], + 'manufacturer': [SFP_INFO_OFFSET, 20, 16, 'parse_vendor_name'], + 'vendor_oui': [SFP_INFO_OFFSET, 37, 3, 'parse_vendor_oui'], + 'model': [SFP_INFO_OFFSET, 40, 16, 'parse_vendor_pn'], + 'hardware_rev': [SFP_INFO_OFFSET, 56, 4, 'parse_vendor_rev'], + 'serial': [SFP_INFO_OFFSET, 68, 16, 'parse_vendor_sn'], + 'vendor_date': [SFP_INFO_OFFSET, 84, 8, 'parse_vendor_date'], + 'ModuleThreshold': [SFP_DOM_OFFSET, 0, 56, 'parse_alarm_warning_threshold'], +} + + +class Sfp(SfpBase): + """ + DELLEMC Platform-specific Sfp class + """ + + def __init__(self, index, sfp_type, eeprom_path): + SfpBase.__init__(self) + self.sfp_type = sfp_type + self.index = index + self.eeprom_path = eeprom_path + self.qsfpInfo = sff8436InterfaceId() + self.qsfpDomInfo = sff8436Dom() + self.sfpInfo = sff8472InterfaceId() + self.sfpDomInfo = sff8472Dom(None,1) + + def get_eeprom_sysfs_path(self): + return self.eeprom_path + + def pci_mem_read(self, mm, offset): + mm.seek(offset) + read_data_stream = mm.read(4) + reg_val = struct.unpack('I', read_data_stream) + mem_val = str(reg_val)[1:-2] + # print "reg_val read:%x"%reg_val + return mem_val + + def pci_mem_write(self, mm, offset, data): + mm.seek(offset) + # print "data to write:%x"%data + mm.write(struct.pack('I', data)) + + def pci_set_value(self, resource, val, offset): + fd = os.open(resource, os.O_RDWR) + mm = mmap.mmap(fd, 0) + val = self.pci_mem_write(mm, offset, val) + mm.close() + os.close(fd) + return val + + def pci_get_value(self, resource, offset): + fd = os.open(resource, os.O_RDWR) + mm = mmap.mmap(fd, 0) + val = self.pci_mem_read(mm, offset) + mm.close() + os.close(fd) + return val + + def _read_eeprom_bytes(self, eeprom_path, offset, num_bytes): + eeprom_raw = [] + try: + eeprom = open(eeprom_path, mode="rb", buffering=0) + except IOError: + return None + + for i in range(0, num_bytes): + eeprom_raw.append("0x00") + + try: + eeprom.seek(offset) + raw = eeprom.read(num_bytes) + except IOError: + eeprom.close() + return None + + raw = bytearray(raw) + + try: + for n in range(0, num_bytes): + eeprom_raw[n] = hex((raw[n]))[2:].zfill(2) + except BaseException: + eeprom.close() + return None + + eeprom.close() + return eeprom_raw + + def _get_eeprom_data(self, eeprom_key): + eeprom_data = None + page_offset = None + + if(self.sfp_type == 'QSFP'): + page_offset = sff8436_parser[eeprom_key][PAGE_OFFSET] + eeprom_data_raw = self._read_eeprom_bytes( + self.eeprom_path, + (sff8436_parser[eeprom_key][PAGE_OFFSET] + + sff8436_parser[eeprom_key][KEY_OFFSET]), + sff8436_parser[eeprom_key][KEY_WIDTH]) + if (eeprom_data_raw is not None): + # Offset 128 is used to retrieve sff8436InterfaceId Info + # Offset 0 is used to retrieve sff8436Dom Info + if (page_offset == 128): + if ( self.qsfpInfo is None): + return None + eeprom_data = getattr( + self.qsfpInfo, sff8436_parser[eeprom_key][FUNC_NAME])( + eeprom_data_raw, 0) + else: + if ( self.qsfpDomInfo is None): + return None + eeprom_data = getattr( + self.qsfpDomInfo, sff8436_parser[eeprom_key][FUNC_NAME])( + eeprom_data_raw, 0) + else: + page_offset = sff8472_parser[eeprom_key][PAGE_OFFSET] + eeprom_data_raw = self._read_eeprom_bytes( + self.eeprom_path, + (sff8472_parser[eeprom_key][PAGE_OFFSET] + + sff8472_parser[eeprom_key][KEY_OFFSET]), + sff8472_parser[eeprom_key][KEY_WIDTH]) + if (eeprom_data_raw is not None): + # Offset 0 is used to retrieve sff8472InterfaceId Info + # Offset 256 is used to retrieve sff8472Dom Info + if (page_offset == 0): + if ( self.sfpInfo is None): + return None + eeprom_data = getattr( + self.sfpInfo, sff8472_parser[eeprom_key][FUNC_NAME])( + eeprom_data_raw, 0) + else: + if ( self.sfpDomInfo is None): + return None + eeprom_data = getattr( + self.sfpDomInfo, sff8472_parser[eeprom_key][FUNC_NAME])( + eeprom_data_raw, 0) + + return eeprom_data + + def get_transceiver_info(self): + """ + Retrieves transceiver info of this SFP + """ + transceiver_info_dict = {} + compliance_code_dict = {} + transceiver_info_dict = dict.fromkeys(info_dict_keys, 'N/A') + # BaseInformation + try: + iface_data = self._get_eeprom_data('type') + connector = iface_data['data']['Connector']['value'] + encoding = iface_data['data']['EncodingCodes']['value'] + ext_id = iface_data['data']['Extended Identifier']['value'] + rate_identifier = iface_data['data']['RateIdentifier']['value'] + identifier = iface_data['data']['type']['value'] + type_abbrv_name=iface_data['data']['type_abbrv_name']['value'] + if(self.sfp_type == 'QSFP'): + bit_rate = str( + iface_data['data']['Nominal Bit Rate(100Mbs)']['value']) + for key in qsfp_compliance_code_tup: + if key in iface_data['data']['Specification compliance']['value']: + compliance_code_dict[key] = iface_data['data']['Specification compliance']['value'][key]['value'] + for key in qsfp_cable_length_tup: + if key in iface_data['data']: + cable_type = key + cable_length = str(iface_data['data'][key]['value']) + else: + bit_rate = str( + iface_data['data']['NominalSignallingRate(UnitsOf100Mbd)']['value']) + for key in sfp_compliance_code_tup: + if key in iface_data['data']['Specification compliance']['value']: + compliance_code_dict[key] = iface_data['data']['Specification compliance']['value'][key]['value'] + for key in sfp_cable_length_tup: + if key in iface_data['data']: + cable_type = key + cable_length = str(iface_data['data'][key]['value']) + + transceiver_info_dict['type_abbrv_name']=type_abbrv_name + transceiver_info_dict['type'] = identifier + transceiver_info_dict['connector'] = connector + transceiver_info_dict['encoding'] = encoding + transceiver_info_dict['ext_identifier'] = ext_id + transceiver_info_dict['ext_rateselect_compliance'] = rate_identifier + transceiver_info_dict['cable_type'] = cable_type + transceiver_info_dict['cable_length'] = cable_length + transceiver_info_dict['nominal_bit_rate'] = bit_rate + transceiver_info_dict['specification_compliance'] = str(compliance_code_dict) + except (ValueError, TypeError) : pass + + # Vendor Date + try: + vendor_date_data = self._get_eeprom_data('vendor_date') + vendor_date = vendor_date_data['data']['VendorDataCode(YYYY-MM-DD Lot)']['value'] + transceiver_info_dict['vendor_date'] = vendor_date + except (ValueError, TypeError) : pass + + # Vendor Name + try: + vendor_name_data = self._get_eeprom_data('manufacturer') + vendor_name = vendor_name_data['data']['Vendor Name']['value'] + transceiver_info_dict['manufacturer'] = vendor_name + except (ValueError, TypeError) : pass + + # Vendor OUI + try: + vendor_oui_data = self._get_eeprom_data('vendor_oui') + vendor_oui = vendor_oui_data['data']['Vendor OUI']['value'] + transceiver_info_dict['vendor_oui'] = vendor_oui + except (ValueError, TypeError) : pass + + # Vendor PN + try: + vendor_pn_data = self._get_eeprom_data('model') + vendor_pn = vendor_pn_data['data']['Vendor PN']['value'] + transceiver_info_dict['model'] = vendor_pn + except (ValueError, TypeError) : pass + + # Vendor Revision + try: + vendor_rev_data = self._get_eeprom_data('hardware_rev') + vendor_rev = vendor_rev_data['data']['Vendor Rev']['value'] + transceiver_info_dict['hardware_rev'] = vendor_rev + except (ValueError, TypeError) : pass + + # Vendor Serial Number + try: + vendor_sn_data = self._get_eeprom_data('serial') + vendor_sn = vendor_sn_data['data']['Vendor SN']['value'] + transceiver_info_dict['serial'] = vendor_sn + except (ValueError, TypeError) : pass + + return transceiver_info_dict + + def get_transceiver_threshold_info(self): + """ + Retrieves transceiver threshold info of this SFP + """ + transceiver_dom_threshold_dict = {} + transceiver_dom_threshold_dict = dict.fromkeys( + threshold_dict_keys, 'N/A') + + try: + # Module Threshold + module_threshold_data = self._get_eeprom_data('ModuleThreshold') + if (self.sfp_type == 'QSFP'): + transceiver_dom_threshold_dict['temphighalarm'] = module_threshold_data['data']['TempHighAlarm']['value'] + transceiver_dom_threshold_dict['temphighwarning'] = module_threshold_data['data']['TempHighWarning']['value'] + transceiver_dom_threshold_dict['templowalarm'] = module_threshold_data['data']['TempLowAlarm']['value'] + transceiver_dom_threshold_dict['templowwarning'] = module_threshold_data['data']['TempLowWarning']['value'] + transceiver_dom_threshold_dict['vcchighalarm'] = module_threshold_data['data']['VccHighAlarm']['value'] + transceiver_dom_threshold_dict['vcchighwarning'] = module_threshold_data['data']['VccHighWarning']['value'] + transceiver_dom_threshold_dict['vcclowalarm'] = module_threshold_data['data']['VccLowAlarm']['value'] + transceiver_dom_threshold_dict['vcclowwarning'] = module_threshold_data['data']['VccLowWarning']['value'] + else: #SFP + transceiver_dom_threshold_dict['temphighalarm'] = module_threshold_data['data']['TempHighAlarm']['value'] + transceiver_dom_threshold_dict['templowalarm'] = module_threshold_data['data']['TempLowAlarm']['value'] + transceiver_dom_threshold_dict['temphighwarning'] = module_threshold_data['data']['TempHighWarning']['value'] + transceiver_dom_threshold_dict['templowwarning'] = module_threshold_data['data']['TempLowWarning']['value'] + transceiver_dom_threshold_dict['vcchighalarm'] = module_threshold_data['data']['VoltageHighAlarm']['value'] + transceiver_dom_threshold_dict['vcclowalarm'] = module_threshold_data['data']['VoltageLowAlarm']['value'] + transceiver_dom_threshold_dict['vcchighwarning'] = module_threshold_data['data']['VoltageHighWarning']['value'] + transceiver_dom_threshold_dict['vcclowwarning'] = module_threshold_data['data']['VoltageLowWarning']['value'] + transceiver_dom_threshold_dict['txbiashighalarm'] = module_threshold_data['data']['BiasHighAlarm']['value'] + transceiver_dom_threshold_dict['txbiaslowalarm'] = module_threshold_data['data']['BiasLowAlarm']['value'] + transceiver_dom_threshold_dict['txbiashighwarning'] = module_threshold_data['data']['BiasHighWarning']['value'] + transceiver_dom_threshold_dict['txbiaslowwarning'] = module_threshold_data['data']['BiasLowWarning']['value'] + transceiver_dom_threshold_dict['txpowerhighalarm'] = module_threshold_data['data']['TXPowerHighAlarm']['value'] + transceiver_dom_threshold_dict['txpowerlowalarm'] = module_threshold_data['data']['TXPowerLowAlarm']['value'] + transceiver_dom_threshold_dict['txpowerhighwarning'] = module_threshold_data['data']['TXPowerHighWarning']['value'] + transceiver_dom_threshold_dict['txpowerlowwarning'] = module_threshold_data['data']['TXPowerLowWarning']['value'] + transceiver_dom_threshold_dict['rxpowerhighalarm'] = module_threshold_data['data']['RXPowerHighAlarm']['value'] + transceiver_dom_threshold_dict['rxpowerlowalarm'] = module_threshold_data['data']['RXPowerLowAlarm']['value'] + transceiver_dom_threshold_dict['rxpowerhighwarning'] = module_threshold_data['data']['RXPowerHighWarning']['value'] + transceiver_dom_threshold_dict['rxpowerlowwarning'] = module_threshold_data['data']['RXPowerLowWarning']['value'] + except (ValueError, TypeError) : pass + + try: + if (self.sfp_type == 'QSFP'): + channel_threshold_data = self._get_eeprom_data('ChannelThreshold') + transceiver_dom_threshold_dict['rxpowerhighalarm'] = channel_threshold_data['data']['RxPowerHighAlarm']['value'] + transceiver_dom_threshold_dict['rxpowerhighwarning'] = channel_threshold_data['data']['RxPowerHighWarning']['value'] + transceiver_dom_threshold_dict['rxpowerlowalarm'] = channel_threshold_data['data']['RxPowerLowAlarm']['value'] + transceiver_dom_threshold_dict['rxpowerlowwarning'] = channel_threshold_data['data']['RxPowerLowWarning']['value'] + transceiver_dom_threshold_dict['txbiashighalarm'] = channel_threshold_data['data']['TxBiasHighAlarm']['value'] + transceiver_dom_threshold_dict['txbiashighwarning'] = channel_threshold_data['data']['TxBiasHighWarning']['value'] + transceiver_dom_threshold_dict['txbiaslowalarm'] = channel_threshold_data['data']['TxBiasLowAlarm']['value'] + transceiver_dom_threshold_dict['txbiaslowwarning'] = channel_threshold_data['data']['TxBiasLowWarning']['value'] + + except (ValueError, TypeError) : pass + return transceiver_dom_threshold_dict + + def get_transceiver_bulk_status(self): + """ + Retrieves transceiver bulk status of this SFP + """ + tx_bias_list = [] + rx_power_list = [] + transceiver_dom_dict = {} + transceiver_dom_dict = dict.fromkeys(dom_dict_keys, 'N/A') + + # RxLos + rx_los = self.get_rx_los() + + # TxFault + tx_fault = self.get_tx_fault() + + # ResetStatus + reset_state = self.get_reset_status() + + # LowPower Mode + lp_mode = self.get_lpmode() + + # TxDisable + tx_disable = self.get_tx_disable() + + # TxDisable Channel + tx_disable_channel = self.get_tx_disable_channel() + + # Temperature + temperature = self.get_temperature() + + # Voltage + voltage = self.get_voltage() + + # Channel Monitor + tx_power_list = self.get_tx_power() + + # tx bias + tx_bias_list = self.get_tx_bias() + + # rx power + rx_power_list = self.get_rx_power() + + if tx_bias_list is not None: + transceiver_dom_dict['tx1bias'] = tx_bias_list[0] + transceiver_dom_dict['tx2bias'] = tx_bias_list[1] + transceiver_dom_dict['tx3bias'] = tx_bias_list[2] + transceiver_dom_dict['tx4bias'] = tx_bias_list[3] + + if rx_power_list is not None: + transceiver_dom_dict['rx1power'] = rx_power_list[0] + transceiver_dom_dict['rx2power'] = rx_power_list[1] + transceiver_dom_dict['rx3power'] = rx_power_list[2] + transceiver_dom_dict['rx4power'] = rx_power_list[3] + + if tx_power_list is not None: + transceiver_dom_dict['tx1power'] = tx_power_list[0] + transceiver_dom_dict['tx2power'] = tx_power_list[1] + transceiver_dom_dict['tx3power'] = tx_power_list[2] + transceiver_dom_dict['tx4power'] = tx_power_list[3] + + transceiver_dom_dict['rx_los'] = rx_los + transceiver_dom_dict['tx_fault'] = tx_fault + transceiver_dom_dict['reset_status'] = reset_state + transceiver_dom_dict['power_lpmode'] = lp_mode + transceiver_dom_dict['tx_disable'] = tx_disable + transceiver_dom_dict['tx_disable_channel'] = tx_disable_channel + transceiver_dom_dict['temperature'] = temperature + transceiver_dom_dict['voltage'] = voltage + + return transceiver_dom_dict + + def get_name(self): + """ + Retrieves the name of the sfp + Returns : QSFP or QSFP+ or QSFP28 + """ + try: + iface_data = self._get_eeprom_data('type') + identifier = iface_data['data']['type']['value'] + except (TypeError, ValueError): + return 'N/A' + return identifier + + def _get_cpld_register(self, reg): + reg_file = '/sys/devices/platform/dell-n3248te-cpld.0/' + reg + try: + rv = open(reg_file, 'r').read() + except IOError : return 'ERR' + return rv.strip('\r\n').lstrip(' ') + + def get_presence(self): + """ + Retrieves the presence of the sfp + Returns : True if sfp is present and false if it is absent + """ + # Check for invalid port_num + presence = False + if not (self.index >= SFP_PORT_START and self.index <= SFP_PORT_END): return presence + bit_mask = 1 << (self.index - SFP_PORT_START) + try: + sfp_mod_prs = self._get_cpld_register('sfp_modprs') + if sfp_mod_prs == 'ERR' : return presence + presence = ((int(sfp_mod_prs, 16) & bit_mask) == 0) + except Exception: + pass + return presence + + def get_model(self): + """ + Retrieves the model number (or part number) of the sfp + """ + try: + vendor_pn_data = self._get_eeprom_data('model') + vendor_pn = vendor_pn_data['data']['Vendor PN']['value'] + except (TypeError, ValueError): + return 'N/A' + + return vendor_pn + + def get_serial(self): + """ + Retrieves the serial number of the sfp + """ + try: + vendor_sn_data = self._get_eeprom_data('serial') + vendor_sn = vendor_sn_data['data']['Vendor SN']['value'] + except (TypeError, ValueError): + return 'N/A' + + return vendor_sn + + def get_reset_status(self): + """ + Retrives the reset status of SFP + """ + reset_status = False + return reset_status + + def get_rx_los(self): + """ + Retrieves the RX LOS (lost-of-signal) status of SFP + """ + rx_los = False + if not (self.index >= SFP_PORT_START and self.index <= SFP_PORT_END): return rx_los + bit_mask = 1 << (self.index - SFP_PORT_START) + try: + sfp_rxlos = self._get_cpld_register('sfp_rxlos') + if sfp_rxlos == 'ERR' : return rx_los + rx_los = ((int(sfp_rxlos, 16) & bit_mask) != 0) + except Exception: + pass + return rx_los + + def get_tx_fault(self): + """ + Retrieves the TX fault status of SFP + """ + tx_fault = False + if not (self.index >= SFP_PORT_START and self.index <= SFP_PORT_END): return tx_fault + bit_mask = 1 << (self.index - SFP_PORT_START) + try: + sfp_txfault = self._get_cpld_register('sfp_txfault') + if sfp_txfault == 'ERR' : return tx_fault + tx_fault = ((int(sfp_txfault, 16) & bit_mask) != 0) + except Exception: + pass + return tx_fault + + def get_tx_disable(self): + """ + Retrieves the tx_disable status of this SFP + """ + tx_disable = False + if not (self.index >= SFP_PORT_START and self.index <= SFP_PORT_END): return tx_disable + bit_mask = 1 << (self.index - SFP_PORT_START) + try: + sfp_txdisable = self._get_cpld_register('sfp_txdis') + if sfp_txdisable == 'ERR' : return tx_disable + tx_disable = ((int(sfp_txdisable, 16) & bit_mask) != 0) + except Exception: + pass + return tx_disable + + def get_tx_disable_channel(self): + """ + Retrieves the TX disabled channels in this SFP + """ + tx_disable_channel = 0 + try: + if (self.sfp_type == 'QSFP'): + tx_disable_data = self._get_eeprom_data('tx_disable') + for tx_disable_id in ('Tx1Disable', 'Tx2Disable', 'Tx3Disable', 'Tx4Disable'): + tx_disable_channel <<= 1 + tx_disable_channel |= (tx_disable_data['data']['Tx1Disable']['value'] is 'On') + except (TypeError, ValueError): + return 'N/A' + return tx_disable_channel + + def get_lpmode(self): + """ + Retrieves the lpmode(low power mode) of this SFP + """ + lpmode_state = False + return lpmode_state + + def get_power_override(self): + """ + Retrieves the power-override status of this SFP + """ + power_override_state = False + + try: + if (self.sfp_type == 'QSFP'): + power_override_data = self._get_eeprom_data('power_override') + power_override = power_override_data['data']['PowerOverRide']['value'] + power_override_state = (power_override is 'On') + except (TypeError, ValueError): pass + return power_override_state + + def get_temperature(self): + """ + Retrieves the temperature of this SFP + """ + try : + temperature_data = self._get_eeprom_data('Temperature') + temperature = temperature_data['data']['Temperature']['value'] + except (TypeError, ValueError): + return 'N/A' + return temperature + + def get_voltage(self): + """ + Retrieves the supply voltage of this SFP + """ + try: + voltage_data = self._get_eeprom_data('Voltage') + voltage = voltage_data['data']['Vcc']['value'] + except (TypeError, ValueError): + return 'N/A' + return voltage + + def get_tx_bias(self): + """ + Retrieves the TX bias current of this SFP + """ + tx_bias_list = [] + try: + tx_bias_data = self._get_eeprom_data('ChannelMonitor') + if (self.sfp_type == 'QSFP'): + for tx_bias_id in ('TX1Bias', 'TX2Bias', 'TX3Bias', 'TX4Bias') : + tx_bias = tx_bias_data['data'][tx_bias_id]['value'] + tx_bias_list.append(tx_bias) + else: + tx1_bias = tx_bias_data['data']['TXBias']['value'] + tx_bias_list = [tx1_bias, "N/A", "N/A", "N/A"] + except (TypeError, ValueError): + return None + return tx_bias_list + + def get_rx_power(self): + """ + Retrieves the received optical power for this SFP + """ + rx_power_list = [] + try: + rx_power_data = self._get_eeprom_data('ChannelMonitor') + if (self.sfp_type == 'QSFP'): + for rx_power_id in ('RX1Power', 'RX2Power', 'RX3Power', 'RX4Power'): + rx_power = rx_power_data['data'][rx_power_id]['value'] + rx_power_list.append(rx_power) + else: + rx1_pw = rx_power_data['data']['RXPower']['value'] + rx_power_list = [rx1_pw, "N/A", "N/A", "N/A"] + except (TypeError, ValueError): + return None + return rx_power_list + + def get_tx_power(self): + """ + Retrieves the TX power of this SFP + """ + tx_power_list = [] + try: + if(self.sfp_type == 'QSFP'): + # QSFP capability byte parse, through this byte can know whether it support tx_power or not. + # TODO: in the future when decided to migrate to support SFF-8636 instead of SFF-8436, + # need to add more code for determining the capability and version compliance + # in SFF-8636 dom capability definitions evolving with the versions. + qspf_dom_capability_data = self._get_eeprom_data('dom_capability') + qsfp_dom_rev_data = self._get_eeprom_data('dom_rev') + qsfp_dom_rev = qsfp_dom_rev_data['data']['dom_rev']['value'] + qsfp_tx_power_support = qspf_dom_capability_data['data']['Tx_power_support']['value'] + + # The tx_power monitoring is only available on QSFP which compliant with SFF-8636 + # and claimed that it support tx_power with one indicator bit. + if (qsfp_dom_rev[0:8] != 'SFF-8636' or (qsfp_dom_rev[0:8] == 'SFF-8636' and qsfp_tx_power_support != 'on')): + return None + channel_monitor_data = self._get_eeprom_data('ChannelMonitor_TxPower') + for tx_power_id in ('TX1Power', 'TX2Power', 'TX3Power', 'TX4Power'): + tx_pw = channel_monitor_data['data'][tx_power_id]['value'] + tx_power_list.append(tx_pw) + else: + channel_monitor_data = self._get_eeprom_data('ChannelMonitor') + tx1_pw = channel_monitor_data['data']['TXPower']['value'] + tx_power_list = [tx1_pw, 'N/A', 'N/A', 'N/A'] + except (TypeError, ValueError): + return None + return tx_power_list + + def reset(self): + """ + Reset the SFP and returns all user settings to their default state + """ + return True + + def set_lpmode(self, lpmode): + """ + Sets the lpmode(low power mode) of this SFP + """ + return True + + def tx_disable(self, tx_disable): + """ + Disable SFP TX for all channels + """ + return False + + def tx_disable_channel(self, channel, disable): + """ + Sets the tx_disable for specified SFP channels + """ + return False + + def set_power_override(self, power_override, power_set): + """ + Sets SFP power level using power_override and power_set + """ + return False + + def get_status(self): + """ + Retrieves the operational status of the device + """ + reset = self.get_reset_status() + return (not reset) + + def get_max_port_power(self): + """ + Retrieves the maximumum power allowed on the port in watts + """ + return 2.5 diff --git a/platform/broadcom/sonic-platform-modules-dell/n3248te/sonic_platform/thermal.py b/platform/broadcom/sonic-platform-modules-dell/n3248te/sonic_platform/thermal.py new file mode 100644 index 000000000000..96edda7c14d4 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-dell/n3248te/sonic_platform/thermal.py @@ -0,0 +1,146 @@ +#!/usr/bin/env python + +######################################################################## +# DellEMC Z9332F +# +# Module contains an implementation of SONiC Platform Base API and +# provides the Thermals' information which are available in the platform +# +######################################################################## + + +try: + import os + from sonic_platform_base.thermal_base import ThermalBase +except ImportError as e: + raise ImportError(str(e) + "- required module not found") + + +class Thermal(ThermalBase): + """DellEMC Platform-specific Thermal class""" + + # [ Sensor-Name, Sensor-ID ] + SENSOR_MAPPING = [ + ['Switch Near Temperature', '7-0049'], + ['Switch Rear Temperature', '7-004a'], + ['Front Panel PHY Temperature', '7-004b'], + ['Near Front Panel Temperature', '7-004c'], + ['Middle Fan Tray Temperature', '7-004f'], + ] + + def __init__(self, thermal_index): + ThermalBase.__init__(self) + self.index = thermal_index + 1 + temp_hwmon = '/sys/bus/i2c/devices/' + self.SENSOR_MAPPING[thermal_index][1] + '/hwmon' + self.temp_file = temp_hwmon + '/' + os.listdir(temp_hwmon)[0] + '/' + 'temp1_input' + + def get_name(self): + """ + Retrieves the name of the thermal + + Returns: + string: The name of the thermal + """ + return self.SENSOR_MAPPING[self.index - 1][0] + + def get_presence(self): + """ + Retrieves the presence of the thermal + + Returns: + bool: True if thermal is present, False if not + """ + return True + + def get_model(self): + """ + Retrieves the model number (or part number) of the Thermal + + Returns: + string: Model/part number of Thermal + """ + return 'NA' + + def get_serial(self): + """ + Retrieves the serial number of the Thermal + + Returns: + string: Serial number of Thermal + """ + return 'NA' + + def get_status(self): + """ + Retrieves the operational status of the thermal + + Returns: + A boolean value, True if thermal is operating properly, + False if not + """ + return True + + def get_temperature(self): + """ + Retrieves current temperature reading from thermal + + Returns: + A float number of current temperature in Celsius up to + nearest thousandth of one degree Celsius, e.g. 30.125 + """ + temperature = 0.0 + try : + temperature = float(open(self.temp_file).read()) / 1000.0 + except Exception: + pass + return float(temperature) + + def get_high_threshold(self): + """ + Retrieves the high threshold temperature of thermal + + Returns: + A float number, the high threshold temperature of thermal in + Celsius up to nearest thousandth of one degree Celsius, + e.g. 30.125 + """ + return 75.0 + + def get_low_threshold(self): + """ + Retrieves the low threshold temperature of thermal + + Returns: + A float number, the low threshold temperature of thermal in + Celsius up to nearest thousandth of one degree Celsius, + e.g. 30.125 + """ + return 0.0 + + def set_high_threshold(self, temperature): + """ + Sets the high threshold temperature of thermal + + Args : + temperature: A float number up to nearest thousandth of one + degree Celsius, e.g. 30.125 + Returns: + A boolean, True if threshold is set successfully, False if + not + """ + # Thermal threshold values are pre-defined based on HW. + return False + + def set_low_threshold(self, temperature): + """ + Sets the low threshold temperature of thermal + + Args : + temperature: A float number up to nearest thousandth of one + degree Celsius, e.g. 30.125 + Returns: + A boolean, True if threshold is set successfully, False if + not + """ + # Thermal threshold values are pre-defined based on HW. + return False diff --git a/platform/broadcom/sonic-platform-modules-dell/n3248te/sonic_platform/watchdog.py b/platform/broadcom/sonic-platform-modules-dell/n3248te/sonic_platform/watchdog.py new file mode 100644 index 000000000000..ebd4706b4215 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-dell/n3248te/sonic_platform/watchdog.py @@ -0,0 +1,210 @@ +#!/usr/bin/env python + +######################################################################## +# +# DELLEMC N3248TE +# +# Abstract base class for implementing a platform-specific class with +# which to interact with a hardware watchdog module in SONiC +# +######################################################################## + +try: + import ctypes + import subprocess + from sonic_platform_base.watchdog_base import WatchdogBase +except ImportError as e: + raise ImportError(str(e) + "- required module not found") + + +class _timespec(ctypes.Structure): + _fields_ = [ + ('tv_sec', ctypes.c_long), + ('tv_nsec', ctypes.c_long) + ] + + +class Watchdog(WatchdogBase): + """ + Abstract base class for interfacing with a hardware watchdog module + """ + + TIMERS = [15,20,30,40,50,60,65,70] + + armed_time = 0 + timeout = 0 + CLOCK_MONOTONIC = 1 + + def __init__(self): + self._librt = ctypes.CDLL('librt.so.1', use_errno=True) + self._clock_gettime = self._librt.clock_gettime + self._clock_gettime.argtypes=[ctypes.c_int, ctypes.POINTER(_timespec)] + + def _get_command_result(self, cmdline): + try: + proc = subprocess.Popen(cmdline.split(), stdout=subprocess.PIPE, + stderr=subprocess.STDOUT) + stdout = proc.communicate()[0] + proc.wait() + result = stdout.rstrip('\n') + except OSError: + result = None + + return result + + def _get_reg_val(self): + # 0x31 = CPLD I2C Base Address + # 0x07 = Watchdog Function Register + value = self._get_command_result("/usr/sbin/i2cget -y 601 0x31 0x07") + if not value: + return None + else: + return int(value, 16) + + def _set_reg_val(self,val): + # 0x31 = CPLD I2C Base Address + # 0x07 = Watchdog Function Register + value = self._get_command_result("/usr/sbin/i2cset -y 601 0x31 0x07 %s" + % (val)) + return value + + def _get_time(self): + """ + To get clock monotonic time + """ + ts = _timespec() + if self._clock_gettime(self.CLOCK_MONOTONIC, ctypes.pointer(ts)) != 0: + self._errno = ctypes.get_errno() + return 0 + return ts.tv_sec + ts.tv_nsec * 1e-9 + + def arm(self, seconds): + """ + Arm the hardware watchdog with a timeout of seconds. + If the watchdog is currently armed, calling this function will + simply reset the timer to the provided value. If the underlying + hardware does not support the value provided in , this + method should arm the watchdog with the *next greater* + available value. + + Returns: + An integer specifying the *actual* number of seconds the + watchdog was armed with. On failure returns -1. + """ + timer_offset = -1 + for key,timer_seconds in enumerate(self.TIMERS): + if seconds <= timer_seconds: + timer_offset = key + seconds = timer_seconds + break + + if timer_offset == -1: + return -1 + + # Extracting 5th to 7th bits for WD timer values + # 000 - 15 sec + # 001 - 20 sec + # 010 - 30 sec + # 011 - 40 sec + # 100 - 50 sec + # 101 - 60 sec + # 110 - 65 sec + # 111 - 70 sec + reg_val = self._get_reg_val() + wd_timer_offset = (reg_val >> 4) & 0x7 + + if wd_timer_offset != timer_offset: + # Setting 5th to 7th bits + # value from timer_offset + self.disarm() + self._set_reg_val(reg_val | (timer_offset << 4)) + + if self.is_armed(): + # Setting last bit to WD Timer punch + # Last bit = WD Timer punch + self._set_reg_val(reg_val & 0xFE) + + self.armed_time = self._get_time() + self.timeout = seconds + return seconds + else: + # Setting 4th bit to enable WD + # 4th bit = Enable WD + reg_val = self._get_reg_val() + self._set_reg_val(reg_val | 0x8) + + self.armed_time = self._get_time() + self.timeout = seconds + return seconds + + def disarm(self): + """ + Disarm the hardware watchdog + + Returns: + A boolean, True if watchdog is disarmed successfully, False + if not + """ + if self.is_armed(): + # Setting 4th bit to disable WD + # 4th bit = Disable WD + reg_val = self._get_reg_val() + self._set_reg_val(reg_val & 0xF7) + + self.armed_time = 0 + self.timeout = 0 + return True + + return False + + def is_armed(self): + """ + Retrieves the armed state of the hardware watchdog. + + Returns: + A boolean, True if watchdog is armed, False if not + """ + + # Extracting 4th bit to get WD Enable/Disable status + # 0 - Disabled WD + # 1 - Enabled WD + reg_val = self._get_reg_val() + wd_offset = (reg_val >> 3) & 1 + + return bool(wd_offset) + + def get_remaining_time(self): + """ + If the watchdog is armed, retrieve the number of seconds + remaining on the watchdog timer + + Returns: + An integer specifying the number of seconds remaining on + their watchdog timer. If the watchdog is not armed, returns + -1. + + S5232 doesnot have hardware support to show remaining time. + Due to this limitation, this API is implemented in software. + This API would return correct software time difference if it + is called from the process which armed the watchdog timer. + If this API called from any other process, it would return + 0. If the watchdog is not armed, this API would return -1. + """ + if not self.is_armed(): + return -1 + + if self.armed_time > 0 and self.timeout != 0: + cur_time = self._get_time() + + if cur_time <= 0: + return 0 + + diff_time = int(cur_time - self.armed_time) + + if diff_time > self.timeout: + return self.timeout + else: + return self.timeout - diff_time + + return 0 + diff --git a/platform/broadcom/sonic-platform-modules-dell/n3248te/systemd/platform-modules-n3248te.service b/platform/broadcom/sonic-platform-modules-dell/n3248te/systemd/platform-modules-n3248te.service new file mode 100644 index 000000000000..403945f8c7f3 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-dell/n3248te/systemd/platform-modules-n3248te.service @@ -0,0 +1,14 @@ +[Unit] +Description=Dell N3248TE Platform modules +Before=pmon.service +After=platform-init.service +DefaultDependencies=no + +[Service] +Type=oneshot +ExecStart=/usr/local/bin/n3248te_platform.sh init +ExecStop=/usr/local/bin/n3248te_platform.sh deinit +RemainAfterExit=yes + +[Install] +WantedBy=multi-user.target diff --git a/src/sonic-device-data/tests/permitted_list b/src/sonic-device-data/tests/permitted_list index 46a82cce9248..506fffe7e5f2 100644 --- a/src/sonic-device-data/tests/permitted_list +++ b/src/sonic-device-data/tests/permitted_list @@ -286,3 +286,7 @@ lb_port_pipe1_int ing_origin_id_device_id_mask egr_origin_id_device_id_mask port_count_in_pb_stream +ifa_enable +port_gmii_mode +phy_force_firmware_load +phy_pcs_repeater \ No newline at end of file From 62a1f5eb19dd8994d2dfaf66b31829fa622d0b2a Mon Sep 17 00:00:00 2001 From: kellyyeh <42761586+kellyyeh@users.noreply.github.com> Date: Thu, 23 Sep 2021 22:01:26 -0700 Subject: [PATCH 34/34] Add CLI Support for IPv6 Helpers and DHCPv6 Relay Counters (#8593) --- .../cli-plugin-tests/mock_config.py | 18 +++ .../test_show_dhcp6relay_counters.py | 43 +++++++ .../test_show_dhcpv6_helper.py | 40 +++++++ .../clear/plugins/clear_dhcp6relay_counter.py | 32 +++++ .../cli/show/plugins/show_dhcp_relay.py | 113 +++++++++++++++++- files/build_templates/manifest.json.j2 | 3 +- rules/docker-dhcp-relay.mk | 1 + rules/functions | 1 + sonic-slave-buster/Dockerfile.j2 | 4 + sonic-slave-stretch/Dockerfile.j2 | 4 + 10 files changed, 257 insertions(+), 2 deletions(-) create mode 100644 dockers/docker-dhcp-relay/cli-plugin-tests/mock_config.py create mode 100644 dockers/docker-dhcp-relay/cli-plugin-tests/test_show_dhcp6relay_counters.py create mode 100644 dockers/docker-dhcp-relay/cli-plugin-tests/test_show_dhcpv6_helper.py create mode 100644 dockers/docker-dhcp-relay/cli/clear/plugins/clear_dhcp6relay_counter.py diff --git a/dockers/docker-dhcp-relay/cli-plugin-tests/mock_config.py b/dockers/docker-dhcp-relay/cli-plugin-tests/mock_config.py new file mode 100644 index 000000000000..ed04367fbba7 --- /dev/null +++ b/dockers/docker-dhcp-relay/cli-plugin-tests/mock_config.py @@ -0,0 +1,18 @@ +TEST_DATA = [ + [ + "DHCPv6_Helpers", + { + "config_db": { + "DHCP_RELAY": { + "Vlan1000": { + "dhcpv6_servers": [ + "fc02:2000::1", + "fc02:2000::2" + ], + "dhcpv6_option|rfc6939_support": "true" + } + } + }, + }, + ], +] diff --git a/dockers/docker-dhcp-relay/cli-plugin-tests/test_show_dhcp6relay_counters.py b/dockers/docker-dhcp-relay/cli-plugin-tests/test_show_dhcp6relay_counters.py new file mode 100644 index 000000000000..f640ef1de6ce --- /dev/null +++ b/dockers/docker-dhcp-relay/cli-plugin-tests/test_show_dhcp6relay_counters.py @@ -0,0 +1,43 @@ +import sys +import os +from unittest import mock +sys.path.append('../cli/show/plugins/') +import show_dhcp_relay as show + +from click.testing import CliRunner + +try: + modules_path = os.path.join(os.path.dirname(__file__), "../../../src/sonic-utilities") + test_path = os.path.join(modules_path, "tests") + mock_table_path = os.path.join(test_path, "mock_tables") + sys.path.insert(0, modules_path) + sys.path.insert(0, test_path) + sys.path.insert(0, mock_table_path) + import dbconnector +except KeyError: + pass + +expected_counts = """\ + Message Type Vlan1000 +-------------- ----------- + Solicit + Advertise + Request + Confirm + Renew + Rebind + Reply + Release + Decline + Relay-Forward + Relay-Reply + +""" + +class TestDhcp6RelayCounters(object): + + def test_show_counts(self): + runner = CliRunner() + result = runner.invoke(show.dhcp6relay_counters.commands["counts"], ["-i Vlan1000"]) + assert result.output == expected_counts + diff --git a/dockers/docker-dhcp-relay/cli-plugin-tests/test_show_dhcpv6_helper.py b/dockers/docker-dhcp-relay/cli-plugin-tests/test_show_dhcpv6_helper.py new file mode 100644 index 000000000000..1f079c5ac965 --- /dev/null +++ b/dockers/docker-dhcp-relay/cli-plugin-tests/test_show_dhcpv6_helper.py @@ -0,0 +1,40 @@ +import pytest +import sys +import os +sys.path.append('../cli/show/plugins/') +import show_dhcp_relay as show +from click.testing import CliRunner +from swsscommon import swsscommon +from mock_config import TEST_DATA +from parameterized import parameterized +from pyfakefs.fake_filesystem_unittest import patchfs + +try: + sys.path.insert(0, '../../../src/sonic-host-services/tests/common') + from mock_configdb import MockConfigDb + swsscommon.ConfigDBConnector = MockConfigDb +except KeyError: + pass + +expected_table = """\ +-------- ------------ +Vlan1000 fc02:2000::1 + fc02:2000::2 +-------- ------------ +""" + +DBCONFIG_PATH = '/var/run/redis/sonic-db/database_config.json' + +class TestDhcpRelayHelper(object): + + @parameterized.expand(TEST_DATA) + @patchfs + def test_show_dhcpv6_helper(self, test_name, test_data, fs): + if not os.path.exists(DBCONFIG_PATH): + fs.create_file(DBCONFIG_PATH) + MockConfigDb.set_config_db(test_data["config_db"]) + runner = CliRunner() + table = MockConfigDb.get_table(self, "DHCP_RELAY") + result = show.get_data(table, "Vlan1000") + assert result == expected_table + diff --git a/dockers/docker-dhcp-relay/cli/clear/plugins/clear_dhcp6relay_counter.py b/dockers/docker-dhcp-relay/cli/clear/plugins/clear_dhcp6relay_counter.py new file mode 100644 index 000000000000..7b0d5097d2ec --- /dev/null +++ b/dockers/docker-dhcp-relay/cli/clear/plugins/clear_dhcp6relay_counter.py @@ -0,0 +1,32 @@ +import sys +import click +sys.path.insert(0, '../../show/plugins/') +from show_dhcp6relay_counters import DHCPv6_Counter + +import utilities_common.cli as clicommon + + +# sonic-clear dhcp6relay_counters +@click.group(cls=clicommon.AliasedGroup) +def dhcp6relay_clear(): + pass + +@dhcp6relay_clear.command('dhcp6relay_counters') +@click.option('-i', '--interface', required=False) +def dhcp6relay_clear_counters(interface): + """ Clear dhcp6relay message counts """ + + counter = DHCPv6_Counter() + counter_intf = counter.get_interface() + + if interface: + counter.clear_table(interface) + else: + for intf in counter_intf: + counter.clear_table(intf) + +def register(cli): + cli.add_command(dhcp6relay_clear_counters) + +if __name__ == '__main__': + dhcp6relay_clear_counters() diff --git a/dockers/docker-dhcp-relay/cli/show/plugins/show_dhcp_relay.py b/dockers/docker-dhcp-relay/cli/show/plugins/show_dhcp_relay.py index 95698f276463..bad1de7d52bd 100644 --- a/dockers/docker-dhcp-relay/cli/show/plugins/show_dhcp_relay.py +++ b/dockers/docker-dhcp-relay/cli/show/plugins/show_dhcp_relay.py @@ -1,5 +1,22 @@ +import click from natsort import natsorted +from tabulate import tabulate import show.vlan as vlan +import utilities_common.cli as clicommon + +from swsscommon.swsscommon import ConfigDBConnector +from swsscommon.swsscommon import SonicV2Connector + + +# STATE_DB Table +DHCPv6_COUNTER_TABLE = 'DHCPv6_COUNTER_TABLE' + +# DHCPv6 Counter Messages +messages = ["Solicit", "Advertise", "Request", "Confirm", "Renew", "Rebind", "Reply", "Release", "Decline", "Relay-Forward", "Relay-Reply"] + +# DHCP_RELAY Config Table +DHCP_RELAY = 'DHCP_RELAY' +config_db = ConfigDBConnector() def get_dhcp_helper_address(ctx, vlan): cfg, _ = ctx @@ -17,5 +34,99 @@ def get_dhcp_helper_address(ctx, vlan): vlan.VlanBrief.register_column('DHCP Helper Address', get_dhcp_helper_address) -def register(cli): +class DHCPv6_Counter(object): + def __init__(self): + self.db = SonicV2Connector(use_unix_socket_path=False) + self.db.connect(self.db.STATE_DB) + self.table_name = DHCPv6_COUNTER_TABLE + self.db.get_db_separator(self.db.STATE_DB) + + + def get_interface(self): + """ Get all names of all interfaces in DHCPv6_COUNTER_TABLE """ + vlans = [] + for key in self.db.keys(self.db.STATE_DB): + if DHCPv6_COUNTER_TABLE in key: + vlans.append(key[21:]) + return vlans + + + def get_dhcp6relay_msg_count(self, interface, msg): + """ Get count of a dhcp6relay message """ + count = self.db.get(self.db.STATE_DB, self.table_name + str(interface), str(msg)) + data = [str(msg), count] + return data + + + def clear_table(self, interface): + """ Reset all message counts to 0 """ + for msg in messages: + self.db.set(self.db.STATE_DB, self.table_name + str(interface), str(msg), '0') + +def print_count(counter, intf): + """Print count of each message""" + data = [] + for i in messages: + data.append(counter.get_dhcp6relay_msg_count(intf, i)) + print(tabulate(data, headers = ["Message Type", intf], tablefmt='simple', stralign='right') + "\n") + + +# +# 'dhcp6relay_counters' group ### +# + + +@click.group(cls=clicommon.AliasedGroup, name="dhcp6relay_counters") +def dhcp6relay_counters(): + """Show DHCPv6 counter""" pass + + +# 'counts' subcommand ("show dhcp6relay_counters counts") +@dhcp6relay_counters.command('counts') +@click.option('-i', '--interface', required=False) +@click.option('--verbose', is_flag=True, help="Enable verbose output") +def counts(interface, verbose): + """Show dhcp6relay message counts""" + + counter = DHCPv6_Counter() + counter_intf = counter.get_interface() + + if interface: + print_count(counter, interface) + else: + for intf in counter_intf: + print_count(counter, intf) + + + +@click.group(cls=clicommon.AliasedGroup, name="dhcprelay_helper") +def dhcp_relay_helper(): + """Show DHCP_Relay helper information""" + pass + +@dhcp_relay_helper.command('ipv6') +def get_dhcpv6_helper_address(): + """Parse through DHCP_RELAY table for each interface in config_db.json and print dhcpv6 helpers in table format""" + if config_db is not None: + config_db.connect() + table_data = config_db.get_table(DHCP_RELAY) + if table_data is not None: + vlans = config_db.get_keys(DHCP_RELAY) + for vlan in vlans: + output = get_data(table_data, vlan) + print(output) + + +def get_data(table_data, vlan): + vlan_data = table_data.get(vlan) + helpers_data = vlan_data.get('dhcpv6_servers') + if helpers_data is not None: + addr = {vlan:[]} + for ip in helpers_data: + addr[vlan].append(ip) + output = tabulate({'Interface':[vlan], vlan:addr.get(vlan)}, tablefmt='simple', stralign='right') + '\n' + return output + +def register(cli): + cli.add_command(dhcp6relay_counters) + cli.add_command(dhcp_relay_helper) diff --git a/files/build_templates/manifest.json.j2 b/files/build_templates/manifest.json.j2 index 9f3e872d2e65..431b2dd22432 100644 --- a/files/build_templates/manifest.json.j2 +++ b/files/build_templates/manifest.json.j2 @@ -29,6 +29,7 @@ }, "cli": { "config": "{{ config_cli_plugin|default('') }}", - "show": "{{ show_cli_plugin|default('') }}" + "show": "{{ show_cli_plugin|default('') }}", + "clear": "{{ clear_cli_plugin|default('') }}" } } diff --git a/rules/docker-dhcp-relay.mk b/rules/docker-dhcp-relay.mk index c3232e6da27a..42d7a3f86b33 100644 --- a/rules/docker-dhcp-relay.mk +++ b/rules/docker-dhcp-relay.mk @@ -53,5 +53,6 @@ $(DOCKER_DHCP_RELAY)_CONTAINER_TMPFS += /var/tmp/ $(DOCKER_DHCP_RELAY)_CLI_CONFIG_PLUGIN = /cli/config/plugins/dhcp_relay.py $(DOCKER_DHCP_RELAY)_CLI_SHOW_PLUGIN = /cli/show/plugins/show_dhcp_relay.py +$(DOCKER_DHCP_RELAY)_CLI_CLEAR_PLUGIN = /cli/clear/plugins/clear_dhcp6relay_counter.py $(DOCKER_DHCP_RELAY)_FILES += $(SUPERVISOR_PROC_EXIT_LISTENER_SCRIPT) diff --git a/rules/functions b/rules/functions index 5873b2db1b87..6f62b87797c8 100644 --- a/rules/functions +++ b/rules/functions @@ -196,6 +196,7 @@ define generate_manifest $(eval export tmpfs=$($(1).gz_CONTAINER_TMPFS)) $(eval export config_cli_plugin=$($(1).gz_CLI_CONFIG_PLUGIN)) $(eval export show_cli_plugin=$($(1).gz_CLI_SHOW_PLUGIN)) + $(eval export clear_cli_plugin=$($(1).gz_CLI_CLEAR_PLUGIN)) j2 $($*.gz_PATH)/Dockerfile$(2).j2 > $($(1).gz_PATH)/Dockerfile$(2) j2 --customize scripts/j2cli/json_filter.py files/build_templates/manifest.json.j2 > $($(1).gz_PATH)/manifest.common.json if [ -f $($*.gz_PATH)/manifest.part.json.j2 ]; then diff --git a/sonic-slave-buster/Dockerfile.j2 b/sonic-slave-buster/Dockerfile.j2 index bbd68a31396e..f23c1aeb8c17 100644 --- a/sonic-slave-buster/Dockerfile.j2 +++ b/sonic-slave-buster/Dockerfile.j2 @@ -486,6 +486,10 @@ EXPOSE 22 RUN git clone https://chromium.googlesource.com/chromium/tools/depot_tools.git /usr/share/depot_tools ENV PATH /usr/share/depot_tools:$PATH +# Install dependencies for dhcp relay test +RUN pip3 install parameterized==0.8.1 +RUN pip3 install pyfakefs + # Install docker engine 17.03.2~ce-0 inside docker and enable experimental feature RUN apt-get update RUN apt-get install -y \ diff --git a/sonic-slave-stretch/Dockerfile.j2 b/sonic-slave-stretch/Dockerfile.j2 index cc45afbc6f82..e077c69e01b3 100644 --- a/sonic-slave-stretch/Dockerfile.j2 +++ b/sonic-slave-stretch/Dockerfile.j2 @@ -291,6 +291,10 @@ RUN apt-get update && apt-get install -y \ python-lxml \ libexpat1-dev +# Install dependencies for dhcp relay test +RUN pip3 install parameterized==0.8.1 +RUN pip3 install pyfakefs + ## Config dpkg ## install the configuration file if it’s currently missing RUN sudo augtool --autosave "set /files/etc/dpkg/dpkg.cfg/force-confmiss"