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 && \ 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/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 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" + } +} 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 000000000000..631b4712fa28 Binary files /dev/null and b/device/dell/x86_64-dellemc_n3248te_c3338-r0/DellEMC-N3248TE/custom_led.bin differ diff --git a/device/dell/x86_64-dellemc_n3248te_c3338-r0/DellEMC-N3248TE/hx5-n3248te-48x1G+4x10G.config.bcm b/device/dell/x86_64-dellemc_n3248te_c3338-r0/DellEMC-N3248TE/hx5-n3248te-48x1G+4x10G.config.bcm new file mode 100644 index 000000000000..69536e86e7a4 --- /dev/null +++ b/device/dell/x86_64-dellemc_n3248te_c3338-r0/DellEMC-N3248TE/hx5-n3248te-48x1G+4x10G.config.bcm @@ -0,0 +1,260 @@ +bcm_num_cos=8 +bcm_stat_interval=2000000 +bcm_tunnel_term_compatible_mode=1 +cdma_timeout_usec=3000000 +core_clock_frequency=668 +flow_init_mode=0 +ifa_enable=0 +ifp_inports_support_enable=1 +ipv6_lpm_128b_enable=0x1 +l2xmsg_mode=1 + +#Default L3 profile + +l2_mem_entries=32768 +l3_alpm_enable=2 +l3_alpm_ipv6_128b_bkt_rsvd=1 +l3_max_ecmp_mode=1 +l3_mem_entries=16348 +lpm_scaling_enable=0 +memlist_enable=1 +reglist_enable=1 +scache_filename=/tmp/brcm_bcm_scache +schan_intr_enable=0 +stable_size=0x5500000 +tdma_timeout_usec=3000000 + +pfc_deadlock_seq_control=1 + +#Port and PHY configs + +pbmp_xport_xe=0x1FFFFFFFFFFFFFFE +port_gmii_mode_33=1 +port_gmii_mode_17=1 +port_gmii_mode_1=1 +portmap_1=1:1 +portmap_2=2:1 +portmap_3=3:1 +portmap_4=4:1 +portmap_5=5:1 +portmap_6=6:1 +portmap_7=7:1 +portmap_8=8:1 +portmap_9=9:1 +portmap_10=10:1 +portmap_11=11:1 +portmap_12=12:1 +portmap_13=13:1 +portmap_14=14:1 +portmap_15=15:1 +portmap_16=16:1 +portmap_17=17:1 +portmap_18=18:1 +portmap_19=19:1 +portmap_20=20:1 +portmap_21=21:1 +portmap_22=22:1 +portmap_23=23:1 +portmap_24=24:1 +portmap_25=25:1 +portmap_26=26:1 +portmap_27=27:1 +portmap_28=28:1 +portmap_29=29:1 +portmap_30=30:1 +portmap_31=31:1 +portmap_32=32:1 +portmap_33=33:1 +portmap_34=34:1 +portmap_35=35:1 +portmap_36=36:1 +portmap_37=37:1 +portmap_38=38:1 +portmap_39=39:1 +portmap_40=40:1 +portmap_41=41:1 +portmap_42=42:1 +portmap_43=43:1 +portmap_44=44:1 +portmap_45=45:1 +portmap_46=46:1 +portmap_47=47:1 +portmap_48=48:1 +portmap_49=64:10 +portmap_50=63:10 +portmap_51=62:10 +portmap_52=61:10 +portmap_53=69:100 +portmap_57=73:100 +phy_chain_tx_lane_map_physical{33.0}=0x2301 +phy_chain_rx_lane_map_physical{33.0}=0x2301 +phy_port_primary_and_offset_1=0x0100 +phy_port_primary_and_offset_2=0x0101 +phy_port_primary_and_offset_3=0x0102 +phy_port_primary_and_offset_4=0x0103 +phy_port_primary_and_offset_5=0x0104 +phy_port_primary_and_offset_6=0x0105 +phy_port_primary_and_offset_7=0x0106 +phy_port_primary_and_offset_8=0x0107 +phy_port_primary_and_offset_9=0x0900 +phy_port_primary_and_offset_10=0x0901 +phy_port_primary_and_offset_11=0x0902 +phy_port_primary_and_offset_12=0x0903 +phy_port_primary_and_offset_13=0x0904 +phy_port_primary_and_offset_14=0x0905 +phy_port_primary_and_offset_15=0x0906 +phy_port_primary_and_offset_16=0x0907 +phy_port_primary_and_offset_17=0x1200 +phy_port_primary_and_offset_18=0x1201 +phy_port_primary_and_offset_19=0x1202 +phy_port_primary_and_offset_20=0x1203 +phy_port_primary_and_offset_21=0x1204 +phy_port_primary_and_offset_22=0x1205 +phy_port_primary_and_offset_23=0x1206 +phy_port_primary_and_offset_24=0x1207 +phy_port_primary_and_offset_25=0x2000 +phy_port_primary_and_offset_26=0x2001 +phy_port_primary_and_offset_27=0x2002 +phy_port_primary_and_offset_28=0x2003 +phy_port_primary_and_offset_29=0x2004 +phy_port_primary_and_offset_30=0x2005 +phy_port_primary_and_offset_31=0x2006 +phy_port_primary_and_offset_32=0x2007 +phy_port_primary_and_offset_33=0x2900 +phy_port_primary_and_offset_34=0x2901 +phy_port_primary_and_offset_35=0x2902 +phy_port_primary_and_offset_36=0x2903 +phy_port_primary_and_offset_37=0x2904 +phy_port_primary_and_offset_38=0x2905 +phy_port_primary_and_offset_39=0x2906 +phy_port_primary_and_offset_40=0x2907 +phy_port_primary_and_offset_41=0x3200 +phy_port_primary_and_offset_42=0x3201 +phy_port_primary_and_offset_43=0x3202 +phy_port_primary_and_offset_44=0x3203 +phy_port_primary_and_offset_45=0x3204 +phy_port_primary_and_offset_46=0x3205 +phy_port_primary_and_offset_47=0x3206 +phy_port_primary_and_offset_48=0x3207 +port_phy_addr_1=0x0 +port_phy_addr_2=0x1 +port_phy_addr_3=0x2 +port_phy_addr_4=0x3 +port_phy_addr_5=0x4 +port_phy_addr_6=0x5 +port_phy_addr_7=0x6 +port_phy_addr_8=0x7 +port_phy_addr_9=0x9 +port_phy_addr_10=0xa +port_phy_addr_11=0xb +port_phy_addr_12=0xc +port_phy_addr_13=0xd +port_phy_addr_14=0xe +port_phy_addr_15=0xf +port_phy_addr_16=0x10 +port_phy_addr_17=0x12 +port_phy_addr_18=0x13 +port_phy_addr_19=0x14 +port_phy_addr_20=0x15 +port_phy_addr_21=0x16 +port_phy_addr_22=0x17 +port_phy_addr_23=0x18 +port_phy_addr_24=0x19 +port_phy_addr_25=0x20 +port_phy_addr_26=0x21 +port_phy_addr_27=0x22 +port_phy_addr_28=0x23 +port_phy_addr_29=0x24 +port_phy_addr_30=0x25 +port_phy_addr_31=0x26 +port_phy_addr_32=0x27 +port_phy_addr_33=0x29 +port_phy_addr_34=0x2a +port_phy_addr_35=0x2b +port_phy_addr_36=0x2c +port_phy_addr_37=0x2d +port_phy_addr_38=0x2e +port_phy_addr_39=0x2f +port_phy_addr_40=0x30 +port_phy_addr_41=0x32 +port_phy_addr_42=0x33 +port_phy_addr_43=0x34 +port_phy_addr_44=0x35 +port_phy_addr_45=0x36 +port_phy_addr_46=0x37 +port_phy_addr_47=0x38 +port_phy_addr_48=0x39 +port_phy_addr_49=0x40 +phy_force_firmware_load_50=0x01 +port_phy_addr_50=0x41 +phy_force_firmware_load_51=0x01 +port_phy_addr_51=0x42 +phy_force_firmware_load_52=0x01 +port_phy_addr_52=0x43 +phy_pcs_repeater_49=0x01 +phy_pcs_repeater_50=0x01 +phy_pcs_repeater_51=0x01 +phy_pcs_repeater_52=0x01 +dport_map_port_1=1 +dport_map_port_2=2 +dport_map_port_3=3 +dport_map_port_4=4 +dport_map_port_5=5 +dport_map_port_6=6 +dport_map_port_7=7 +dport_map_port_8=8 +dport_map_port_9=9 +dport_map_port_10=10 +dport_map_port_11=11 +dport_map_port_12=12 +dport_map_port_13=13 +dport_map_port_14=14 +dport_map_port_15=15 +dport_map_port_16=16 +dport_map_port_17=17 +dport_map_port_18=18 +dport_map_port_19=19 +dport_map_port_20=20 +dport_map_port_21=21 +dport_map_port_22=22 +dport_map_port_23=23 +dport_map_port_24=24 +dport_map_port_25=25 +dport_map_port_26=26 +dport_map_port_27=27 +dport_map_port_28=28 +dport_map_port_29=29 +dport_map_port_30=30 +dport_map_port_31=31 +dport_map_port_32=32 +dport_map_port_33=33 +dport_map_port_34=34 +dport_map_port_35=35 +dport_map_port_36=36 +dport_map_port_37=37 +dport_map_port_38=38 +dport_map_port_39=39 +dport_map_port_40=40 +dport_map_port_41=41 +dport_map_port_42=42 +dport_map_port_43=43 +dport_map_port_44=44 +dport_map_port_45=45 +dport_map_port_46=46 +dport_map_port_47=47 +dport_map_port_48=48 +dport_map_port_49=49 +dport_map_port_50=50 +dport_map_port_51=51 +dport_map_port_52=52 +dport_map_port_53=53 +dport_map_port_54=54 +dport_map_port_55=55 +dport_map_port_56=56 +dport_map_port_57=57 +dport_map_port_58=58 +dport_map_port_59=59 +dport_map_port_60=60 + +sai_preinit_cmd_file=/usr/share/sonic/hwsku/sai_preinit_cmd.soc + diff --git a/device/dell/x86_64-dellemc_n3248te_c3338-r0/DellEMC-N3248TE/linkscan_led_fw.bin b/device/dell/x86_64-dellemc_n3248te_c3338-r0/DellEMC-N3248TE/linkscan_led_fw.bin new file mode 100644 index 000000000000..e86cdc1ef647 Binary files /dev/null and b/device/dell/x86_64-dellemc_n3248te_c3338-r0/DellEMC-N3248TE/linkscan_led_fw.bin differ 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/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/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"] } } } 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/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/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/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/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 \ 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/files/image_config/copp/copp-config.service b/files/image_config/copp/copp-config.service old mode 100755 new mode 100644 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 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 +} diff --git a/platform/broadcom/one-image.mk b/platform/broadcom/one-image.mk index ae7e24dc1696..1c8ffac5ce80 100644 --- a/platform/broadcom/one-image.mk +++ b/platform/broadcom/one-image.mk @@ -16,6 +16,7 @@ $(SONIC_ONE_IMAGE)_LAZY_INSTALLS += $(DELL_S6000_PLATFORM_MODULE) \ $(DELL_Z9100_PLATFORM_MODULE) \ $(DELL_S6100_PLATFORM_MODULE) \ $(DELL_N3248PXE_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 2f9c98b99431..2238c5615dc5 100644 --- a/platform/broadcom/platform-modules-dell.mk +++ b/platform/broadcom/platform-modules-dell.mk @@ -9,6 +9,7 @@ DELL_Z9332F_PLATFORM_MODULE_VERSION = 1.1 DELL_S5248F_PLATFORM_MODULE_VERSION = 1.1 DELL_S5296F_PLATFORM_MODULE_VERSION = 1.1 DELL_N3248PXE_PLATFORM_MODULE_VERSION = 1.1 +DELL_N3248TE_PLATFORM_MODULE_VERSION = 1.1 export DELL_S6000_PLATFORM_MODULE_VERSION export DELL_Z9100_PLATFORM_MODULE_VERSION @@ -19,6 +20,7 @@ export DELL_Z9332F_PLATFORM_MODULE_VERSION export DELL_S5248F_PLATFORM_MODULE_VERSION export DELL_S5296F_PLATFORM_MODULE_VERSION export DELL_N3248PXE_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 @@ -51,6 +53,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 b07e53b97f71..be2090b150c2 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 0fd5d793492b..17df6721939d 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 n3248pxe +MODULE_DIRS:= s6000 z9100 s6100 z9264f s5232f s5248f z9332f s5296f n3248pxe 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}; \ @@ -129,6 +134,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/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 eda04ae3bd8e..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 @@ -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: @@ -124,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.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): """ 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 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 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): """ 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..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): - return True + """ + 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): + """ + Gets the state of the fan drawer LED - def get_status_led(self, color): + 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/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/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 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 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 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/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" : { 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 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/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..42d7a3f86b33 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) @@ -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/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) 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" 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/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/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/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 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_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 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() + ) + + diff --git a/src/sonic-device-data/tests/permitted_list b/src/sonic-device-data/tests/permitted_list index bf67ed3fb6cc..d7b095424a7e 100644 --- a/src/sonic-device-data/tests/permitted_list +++ b/src/sonic-device-data/tests/permitted_list @@ -297,3 +297,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 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 + 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 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 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 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 diff --git a/src/sonic-sairedis b/src/sonic-sairedis index f85322e139a9..78f36138e14e 160000 --- a/src/sonic-sairedis +++ b/src/sonic-sairedis @@ -1 +1 @@ -Subproject commit f85322e139a9b10f0154b26efaed689791d135d5 +Subproject commit 78f36138e14e1ed0f0f772950f03420327ef1b1c 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 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 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."; + } + } + } + } +}