diff --git a/.gitignore b/.gitignore index 316cf974e6c1..e763b1d26a79 100644 --- a/.gitignore +++ b/.gitignore @@ -162,3 +162,16 @@ src/**/debian/stamp-autotools-files # .o files src/**/*.o + +# platform +platform/**/*.egg-info +platform/**/*-none-any.whl +platform/**/.pybuild +platform/**/debian/* +platform/**/build +platform/broadcom/sonic-platform-modules-dell/s5232f/sonic_platform/ipmihelper.py +platform/broadcom/sonic-platform-modules-dell/s6100/modules/dell_ich.c +platform/broadcom/sonic-platform-modules-dell/s6100/modules/dell_s6100_lpc.c +platform/broadcom/sonic-platform-modules-dell/z9100/modules/dell_ich.c +platform/broadcom/sonic-platform-modules-dell/z9100/modules/dell_mailbox.c +platform/broadcom/sonic-platform-modules-dell/z9264f/sonic_platform/ipmihelper.py diff --git a/Makefile.work b/Makefile.work index e4e31a134555..14c433e4f5d8 100644 --- a/Makefile.work +++ b/Makefile.work @@ -169,7 +169,7 @@ SONIC_BUILD_INSTRUCTION := make \ INSTALL_KUBERNETES=$(INSTALL_KUBERNETES) \ KUBERNETES_VERSION=$(KUBERNETES_VERSION) \ K8s_GCR_IO_PAUSE_VERSION=$(K8s_GCR_IO_PAUSE_VERSION) \ - K8s_CNI_CALICO_VERSION=$(K8s_CNI_CALICO_VERSION) \ + K8s_CNI_FLANNEL_VERSION=$(K8s_CNI_FLANNEL_VERSION) \ SONIC_ENABLE_PFCWD_ON_START=$(ENABLE_PFCWD_ON_START) \ SONIC_ENABLE_SYNCD_RPC=$(ENABLE_SYNCD_RPC) \ SONIC_INSTALL_DEBUG_TOOLS=$(INSTALL_DEBUG_TOOLS) \ @@ -252,8 +252,8 @@ reset : fi git clean -xfdf; git reset --hard; - git submodule foreach --recursive git clean -xfdf; - git submodule foreach --recursive git reset --hard; + git submodule foreach --recursive 'git clean -xfdf || true'; + git submodule foreach --recursive 'git reset --hard || true'; git submodule update --init --recursive; echo "Reset complete!"; else diff --git a/build_debian.sh b/build_debian.sh index f63edfe9a134..be953f51b096 100755 --- a/build_debian.sh +++ b/build_debian.sh @@ -165,6 +165,10 @@ sudo chmod +x $FILESYSTEM_ROOT/etc/initramfs-tools/scripts/init-premount/arista- sudo cp files/initramfs-tools/resize-rootfs $FILESYSTEM_ROOT/etc/initramfs-tools/scripts/init-premount/resize-rootfs sudo chmod +x $FILESYSTEM_ROOT/etc/initramfs-tools/scripts/init-premount/resize-rootfs +# Hook into initramfs: run fsck to repair a non-clean filesystem prior to be mounted +sudo cp files/initramfs-tools/fsck-rootfs $FILESYSTEM_ROOT/etc/initramfs-tools/scripts/init-premount/fsck-rootfs +sudo chmod +x $FILESYSTEM_ROOT/etc/initramfs-tools/scripts/init-premount/fsck-rootfs + ## Hook into initramfs: after partition mount and loop file mount ## 1. Prepare layered file system ## 2. Bind-mount docker working directory (docker overlay storage cannot work over overlay rootfs) @@ -213,6 +217,14 @@ then ## Check out the sources list update matches current Debian version sudo cp files/image_config/kubernetes/kubernetes.list $FILESYSTEM_ROOT/etc/apt/sources.list.d/ sudo LANG=C chroot $FILESYSTEM_ROOT apt-get update + if [[ $KUBERNETES_VERSION == 1.18.0 ]]; then + # kubeadm 1.18.0 package auto install has some dependency error so install + # those package explicitly. + sudo LANG=C chroot $FILESYSTEM_ROOT apt-get -y install kubernetes-cni=0.7.5-00 + sudo LANG=C chroot $FILESYSTEM_ROOT apt-get -y install kubelet=1.18.3-00 + sudo LANG=C chroot $FILESYSTEM_ROOT apt-get -y install kubectl=1.18.3-00 + fi + # else kubeadm package auto install kubelet & kubectl sudo LANG=C chroot $FILESYSTEM_ROOT apt-get -y install kubeadm=${KUBERNETES_VERSION}-00 # kubeadm package auto install kubelet & kubectl else @@ -362,59 +374,27 @@ EOF sudo sed -i 's/^ListenAddress ::/#ListenAddress ::/' $FILESYSTEM_ROOT/etc/ssh/sshd_config sudo sed -i 's/^#ListenAddress 0.0.0.0/ListenAddress 0.0.0.0/' $FILESYSTEM_ROOT/etc/ssh/sshd_config -## Config sysctl sudo mkdir -p $FILESYSTEM_ROOT/var/core + +# Config sysctl sudo augtool --autosave " set /files/etc/sysctl.conf/kernel.core_pattern '|/usr/bin/coredump-compress %e %t %p' - set /files/etc/sysctl.conf/kernel.softlockup_panic 1 set /files/etc/sysctl.conf/kernel.panic 10 set /files/etc/sysctl.conf/vm.panic_on_oom 2 set /files/etc/sysctl.conf/fs.suid_dumpable 2 - -set /files/etc/sysctl.conf/net.ipv4.conf.default.forwarding 1 -set /files/etc/sysctl.conf/net.ipv4.conf.all.forwarding 1 -set /files/etc/sysctl.conf/net.ipv4.conf.eth0.forwarding 0 - -set /files/etc/sysctl.conf/net.ipv4.conf.default.arp_accept 0 -set /files/etc/sysctl.conf/net.ipv4.conf.default.arp_announce 0 -set /files/etc/sysctl.conf/net.ipv4.conf.default.arp_filter 0 -set /files/etc/sysctl.conf/net.ipv4.conf.default.arp_notify 0 -set /files/etc/sysctl.conf/net.ipv4.conf.default.arp_ignore 0 -set /files/etc/sysctl.conf/net.ipv4.conf.all.arp_accept 0 -set /files/etc/sysctl.conf/net.ipv4.conf.all.arp_announce 1 -set /files/etc/sysctl.conf/net.ipv4.conf.all.arp_filter 0 -set /files/etc/sysctl.conf/net.ipv4.conf.all.arp_notify 1 -set /files/etc/sysctl.conf/net.ipv4.conf.all.arp_ignore 2 - -set /files/etc/sysctl.conf/net.ipv4.neigh.default.base_reachable_time_ms 1800000 -set /files/etc/sysctl.conf/net.ipv6.neigh.default.base_reachable_time_ms 1800000 -set /files/etc/sysctl.conf/net.ipv4.neigh.default.gc_thresh1 1024 -set /files/etc/sysctl.conf/net.ipv6.neigh.default.gc_thresh1 1024 -set /files/etc/sysctl.conf/net.ipv4.neigh.default.gc_thresh2 2048 -set /files/etc/sysctl.conf/net.ipv6.neigh.default.gc_thresh2 2048 -set /files/etc/sysctl.conf/net.ipv4.neigh.default.gc_thresh3 4096 -set /files/etc/sysctl.conf/net.ipv6.neigh.default.gc_thresh3 4096 - -set /files/etc/sysctl.conf/net.ipv6.conf.default.forwarding 1 -set /files/etc/sysctl.conf/net.ipv6.conf.all.forwarding 1 -set /files/etc/sysctl.conf/net.ipv6.conf.eth0.forwarding 0 - -set /files/etc/sysctl.conf/net.ipv6.conf.default.accept_dad 0 -set /files/etc/sysctl.conf/net.ipv6.conf.all.accept_dad 0 -set /files/etc/sysctl.conf/net.ipv6.conf.eth0.accept_dad 0 - -set /files/etc/sysctl.conf/net.ipv6.conf.default.keep_addr_on_down 1 -set /files/etc/sysctl.conf/net.ipv6.conf.all.keep_addr_on_down 1 -set /files/etc/sysctl.conf/net.ipv6.conf.eth0.keep_addr_on_down 1 - -set /files/etc/sysctl.conf/net.ipv4.tcp_l3mdev_accept 1 -set /files/etc/sysctl.conf/net.ipv4.udp_l3mdev_accept 1 - -set /files/etc/sysctl.conf/net.core.rmem_max 2097152 -set /files/etc/sysctl.conf/net.core.wmem_max 2097152 " -r $FILESYSTEM_ROOT +sysctl_net_cmd_string="" +while read line; do + [[ "$line" =~ ^#.*$ ]] && continue + sysctl_net_conf_key=`echo $line | awk -F '=' '{print $1}'` + sysctl_net_conf_value=`echo $line | awk -F '=' '{print $2}'` + sysctl_net_cmd_string=$sysctl_net_cmd_string"set /files/etc/sysctl.conf/$sysctl_net_conf_key $sysctl_net_conf_value"$'\n' +done < files/image_config/sysctl/sysctl-net.conf + +sudo augtool --autosave "$sysctl_net_cmd_string" -r $FILESYSTEM_ROOT + if [[ $CONFIGURED_ARCH == amd64 ]]; then # Configure mcelog to log machine checks to syslog sudo sed -i 's/^#syslog = yes/syslog = yes/' $FILESYSTEM_ROOT/etc/mcelog/mcelog.conf diff --git a/device/arista/x86_64-arista_7050_qx32/pmon_daemon_control.json b/device/arista/x86_64-arista_7050_qx32/pmon_daemon_control.json new file mode 120000 index 000000000000..2322ef7a22d8 --- /dev/null +++ b/device/arista/x86_64-arista_7050_qx32/pmon_daemon_control.json @@ -0,0 +1 @@ +../x86_64-arista_common/pmon_daemon_control_skip_thermalctld.json \ No newline at end of file diff --git a/device/arista/x86_64-arista_7050_qx32s/pmon_daemon_control.json b/device/arista/x86_64-arista_7050_qx32s/pmon_daemon_control.json new file mode 120000 index 000000000000..2322ef7a22d8 --- /dev/null +++ b/device/arista/x86_64-arista_7050_qx32s/pmon_daemon_control.json @@ -0,0 +1 @@ +../x86_64-arista_common/pmon_daemon_control_skip_thermalctld.json \ No newline at end of file diff --git a/device/arista/x86_64-arista_7050cx3_32s/pmon_daemon_control.json b/device/arista/x86_64-arista_7050cx3_32s/pmon_daemon_control.json new file mode 120000 index 000000000000..2322ef7a22d8 --- /dev/null +++ b/device/arista/x86_64-arista_7050cx3_32s/pmon_daemon_control.json @@ -0,0 +1 @@ +../x86_64-arista_common/pmon_daemon_control_skip_thermalctld.json \ No newline at end of file diff --git a/device/arista/x86_64-arista_7060_cx32s/pmon_daemon_control.json b/device/arista/x86_64-arista_7060_cx32s/pmon_daemon_control.json new file mode 120000 index 000000000000..2322ef7a22d8 --- /dev/null +++ b/device/arista/x86_64-arista_7060_cx32s/pmon_daemon_control.json @@ -0,0 +1 @@ +../x86_64-arista_common/pmon_daemon_control_skip_thermalctld.json \ No newline at end of file diff --git a/device/arista/x86_64-arista_7060cx2_32s/pmon_daemon_control.json b/device/arista/x86_64-arista_7060cx2_32s/pmon_daemon_control.json new file mode 120000 index 000000000000..2322ef7a22d8 --- /dev/null +++ b/device/arista/x86_64-arista_7060cx2_32s/pmon_daemon_control.json @@ -0,0 +1 @@ +../x86_64-arista_common/pmon_daemon_control_skip_thermalctld.json \ No newline at end of file diff --git a/device/arista/x86_64-arista_7060px4_32/pmon_daemon_control.json b/device/arista/x86_64-arista_7060px4_32/pmon_daemon_control.json new file mode 120000 index 000000000000..2322ef7a22d8 --- /dev/null +++ b/device/arista/x86_64-arista_7060px4_32/pmon_daemon_control.json @@ -0,0 +1 @@ +../x86_64-arista_common/pmon_daemon_control_skip_thermalctld.json \ No newline at end of file diff --git a/device/arista/x86_64-arista_7170_32c/pmon_daemon_control.json b/device/arista/x86_64-arista_7170_32c/pmon_daemon_control.json new file mode 120000 index 000000000000..2322ef7a22d8 --- /dev/null +++ b/device/arista/x86_64-arista_7170_32c/pmon_daemon_control.json @@ -0,0 +1 @@ +../x86_64-arista_common/pmon_daemon_control_skip_thermalctld.json \ No newline at end of file diff --git a/device/arista/x86_64-arista_7170_32cd/pmon_daemon_control.json b/device/arista/x86_64-arista_7170_32cd/pmon_daemon_control.json new file mode 120000 index 000000000000..2322ef7a22d8 --- /dev/null +++ b/device/arista/x86_64-arista_7170_32cd/pmon_daemon_control.json @@ -0,0 +1 @@ +../x86_64-arista_common/pmon_daemon_control_skip_thermalctld.json \ No newline at end of file diff --git a/device/arista/x86_64-arista_7170_64c/pmon_daemon_control.json b/device/arista/x86_64-arista_7170_64c/pmon_daemon_control.json new file mode 120000 index 000000000000..2322ef7a22d8 --- /dev/null +++ b/device/arista/x86_64-arista_7170_64c/pmon_daemon_control.json @@ -0,0 +1 @@ +../x86_64-arista_common/pmon_daemon_control_skip_thermalctld.json \ No newline at end of file diff --git a/device/arista/x86_64-arista_7260cx3_64/pmon_daemon_control.json b/device/arista/x86_64-arista_7260cx3_64/pmon_daemon_control.json new file mode 120000 index 000000000000..2322ef7a22d8 --- /dev/null +++ b/device/arista/x86_64-arista_7260cx3_64/pmon_daemon_control.json @@ -0,0 +1 @@ +../x86_64-arista_common/pmon_daemon_control_skip_thermalctld.json \ No newline at end of file diff --git a/device/arista/x86_64-arista_7280cr3_32p4/pmon_daemon_control.json b/device/arista/x86_64-arista_7280cr3_32p4/pmon_daemon_control.json new file mode 120000 index 000000000000..2322ef7a22d8 --- /dev/null +++ b/device/arista/x86_64-arista_7280cr3_32p4/pmon_daemon_control.json @@ -0,0 +1 @@ +../x86_64-arista_common/pmon_daemon_control_skip_thermalctld.json \ No newline at end of file diff --git a/device/arista/x86_64-arista_common/pmon_daemon_control_skip_thermalctld.json b/device/arista/x86_64-arista_common/pmon_daemon_control_skip_thermalctld.json new file mode 100644 index 000000000000..75db6d97558a --- /dev/null +++ b/device/arista/x86_64-arista_common/pmon_daemon_control_skip_thermalctld.json @@ -0,0 +1,4 @@ +{ + "skip_thermalctld": true +} + diff --git a/device/barefoot/x86_64-accton_as9516bf_32d-r0/pmon_daemon_control.json b/device/barefoot/x86_64-accton_as9516bf_32d-r0/pmon_daemon_control.json index 3a76f2fdd0e4..c182e0f23548 100644 --- a/device/barefoot/x86_64-accton_as9516bf_32d-r0/pmon_daemon_control.json +++ b/device/barefoot/x86_64-accton_as9516bf_32d-r0/pmon_daemon_control.json @@ -1,6 +1,8 @@ { + "skip_thermalctld": true, + "skip_fancontrol": true, "skip_ledd": true, "skip_xcvrd": false, "skip_psud": false, - "skip_syseepromd": false + "skip_syseepromd": false } diff --git a/device/barefoot/x86_64-accton_wedge100bf_32x-r0/pmon_daemon_control.json b/device/barefoot/x86_64-accton_wedge100bf_32x-r0/pmon_daemon_control.json index ea20aeb1f83b..c182e0f23548 100644 --- a/device/barefoot/x86_64-accton_wedge100bf_32x-r0/pmon_daemon_control.json +++ b/device/barefoot/x86_64-accton_wedge100bf_32x-r0/pmon_daemon_control.json @@ -1,4 +1,5 @@ { + "skip_thermalctld": true, "skip_fancontrol": true, "skip_ledd": true, "skip_xcvrd": false, diff --git a/device/barefoot/x86_64-accton_wedge100bf_65x-r0/pmon_daemon_control.json b/device/barefoot/x86_64-accton_wedge100bf_65x-r0/pmon_daemon_control.json index ea20aeb1f83b..c182e0f23548 100644 --- a/device/barefoot/x86_64-accton_wedge100bf_65x-r0/pmon_daemon_control.json +++ b/device/barefoot/x86_64-accton_wedge100bf_65x-r0/pmon_daemon_control.json @@ -1,4 +1,5 @@ { + "skip_thermalctld": true, "skip_fancontrol": true, "skip_ledd": true, "skip_xcvrd": false, diff --git a/device/celestica/x86_64-cel_seastone-r0/fancontrol b/device/celestica/x86_64-cel_seastone-r0/fancontrol deleted file mode 100644 index 8d5cbccb9d00..000000000000 --- a/device/celestica/x86_64-cel_seastone-r0/fancontrol +++ /dev/null @@ -1,12 +0,0 @@ -# Configuration file generated by pwmconfig, changes will be lost -INTERVAL=10 -DEVPATH=hwmon6=devices/pci0000:00/0000:00:13.0/i2c-1/i2c-13/13-002e hwmon7=devices/pci0000:00/0000:00:13.0/i2c-1/i2c-13/13-004d -DEVNAME=hwmon6=emc2305 hwmon7=emc2305 -FCTEMPS=hwmon6/device/pwm1=/sys/devices/pci0000:00/0000:00:13.0/i2c-1/i2c-5/5-0048/hwmon/hwmon1/temp1_input hwmon6/device/pwm2=/sys/devices/pci0000:00/0000:00:13.0/i2c-1/i2c-5/5-0048/hwmon/hwmon1/temp1_input hwmon6/device/pwm3=/sys/devices/pci0000:00/0000:00:13.0/i2c-1/i2c-5/5-0048/hwmon/hwmon1/temp1_input hwmon6/device/pwm4=/sys/devices/pci0000:00/0000:00:13.0/i2c-1/i2c-5/5-0048/hwmon/hwmon1/temp1_input hwmon6/device/pwm5=/sys/devices/pci0000:00/0000:00:13.0/i2c-1/i2c-5/5-0048/hwmon/hwmon1/temp1_input hwmon7/device/pwm1=/sys/devices/pci0000:00/0000:00:13.0/i2c-1/i2c-5/5-0048/hwmon/hwmon1/temp1_input hwmon7/device/pwm2=/sys/devices/pci0000:00/0000:00:13.0/i2c-1/i2c-5/5-0048/hwmon/hwmon1/temp1_input hwmon7/device/pwm3=/sys/devices/pci0000:00/0000:00:13.0/i2c-1/i2c-5/5-0048/hwmon/hwmon1/temp1_input hwmon7/device/pwm4=/sys/devices/pci0000:00/0000:00:13.0/i2c-1/i2c-5/5-0048/hwmon/hwmon1/temp1_input hwmon7/device/pwm5=/sys/devices/pci0000:00/0000:00:13.0/i2c-1/i2c-5/5-0048/hwmon/hwmon1/temp1_input -FCFANS=hwmon7/device/pwm5=/sys/devices/pci0000:00/0000:00:13.0/i2c-1/i2c-13/13-004d/pwm5 hwmon7/device/pwm4=/sys/devices/pci0000:00/0000:00:13.0/i2c-1/i2c-13/13-004d/pwm4 hwmon7/device/pwm3=/sys/devices/pci0000:00/0000:00:13.0/i2c-1/i2c-13/13-004d/pwm3 hwmon7/device/pwm2=/sys/devices/pci0000:00/0000:00:13.0/i2c-1/i2c-13/13-004d/pwm2 hwmon7/device/pwm1=/sys/devices/pci0000:00/0000:00:13.0/i2c-1/i2c-13/13-004d/pwm1 hwmon6/device/pwm5=/sys/devices/pci0000:00/0000:00:13.0/i2c-1/i2c-13/13-002e/pwm5 hwmon6/device/pwm4=/sys/devices/pci0000:00/0000:00:13.0/i2c-1/i2c-13/13-002e/pwm4 hwmon6/device/pwm3=/sys/devices/pci0000:00/0000:00:13.0/i2c-1/i2c-13/13-002e/pwm3 hwmon6/device/pwm2=/sys/devices/pci0000:00/0000:00:13.0/i2c-1/i2c-13/13-002e/pwm2 hwmon6/device/pwm1=/sys/devices/pci0000:00/0000:00:13.0/i2c-1/i2c-13/13-002e/pwm1 -MINTEMP=hwmon6/device/pwm1=26 hwmon6/device/pwm2=26 hwmon6/device/pwm3=26 hwmon6/device/pwm4=26 hwmon6/device/pwm5=26 hwmon7/device/pwm1=26 hwmon7/device/pwm2=26 hwmon7/device/pwm3=26 hwmon7/device/pwm4=26 hwmon7/device/pwm5=26 -MAXTEMP=hwmon6/device/pwm1=45 hwmon6/device/pwm2=45 hwmon6/device/pwm3=45 hwmon6/device/pwm4=45 hwmon6/device/pwm5=45 hwmon7/device/pwm1=45 hwmon7/device/pwm2=45 hwmon7/device/pwm3=45 hwmon7/device/pwm4=45 hwmon7/device/pwm5=45 -MINSTART=hwmon6/device/pwm1=89 hwmon6/device/pwm2=89 hwmon6/device/pwm3=89 hwmon6/device/pwm4=89 hwmon6/device/pwm5=89 hwmon7/device/pwm1=89 hwmon7/device/pwm2=89 hwmon7/device/pwm3=89 hwmon7/device/pwm4=89 hwmon7/device/pwm5=89 -MINSTOP=hwmon6/device/pwm1=89 hwmon6/device/pwm2=89 hwmon6/device/pwm3=89 hwmon6/device/pwm4=89 hwmon6/device/pwm5=89 hwmon7/device/pwm1=89 hwmon7/device/pwm2=89 hwmon7/device/pwm3=89 hwmon7/device/pwm4=89 hwmon7/device/pwm5=89 -MINPWM=hwmon6/device/pwm1=89 hwmon6/device/pwm2=89 hwmon6/device/pwm3=89 hwmon6/device/pwm4=89 hwmon6/device/pwm5=89 hwmon7/device/pwm1=89 hwmon7/device/pwm2=89 hwmon7/device/pwm3=89 hwmon7/device/pwm4=89 hwmon7/device/pwm5=89 -MAXPWM=hwmon6/device/pwm1=255 hwmon6/device/pwm2=255 hwmon6/device/pwm3=255 hwmon6/device/pwm4=255 hwmon6/device/pwm5=255 hwmon7/device/pwm1=255 hwmon7/device/pwm2=255 hwmon7/device/pwm3=255 hwmon7/device/pwm4=255 hwmon7/device/pwm5=255 diff --git a/device/celestica/x86_64-cel_seastone-r0/fancontrol-B2F b/device/celestica/x86_64-cel_seastone-r0/fancontrol-B2F new file mode 100644 index 000000000000..c2132d7f2806 --- /dev/null +++ b/device/celestica/x86_64-cel_seastone-r0/fancontrol-B2F @@ -0,0 +1,11 @@ +# Configuration file generated by pwmconfig, changes will be lost +INTERVAL=2 +FCTEMPS=13-002e/pwm1=/sys/bus/i2c/devices/15-004e/hwmon/hwmon*/temp1_input 13-002e/pwm2=/sys/bus/i2c/devices/15-004e/hwmon/hwmon*/temp1_input 13-002e/pwm3=/sys/bus/i2c/devices/15-004e/hwmon/hwmon*/temp1_input 13-002e/pwm4=/sys/bus/i2c/devices/15-004e/hwmon/hwmon*/temp1_input 13-002e/pwm5=/sys/bus/i2c/devices/15-004e/hwmon/hwmon*/temp1_input 13-004d/pwm1=/sys/bus/i2c/devices/15-004e/hwmon/hwmon*/temp1_input 13-004d/pwm2=/sys/bus/i2c/devices/15-004e/hwmon/hwmon*/temp1_input 13-004d/pwm3=/sys/bus/i2c/devices/15-004e/hwmon/hwmon*/temp1_input 13-004d/pwm4=/sys/bus/i2c/devices/15-004e/hwmon/hwmon*/temp1_input 13-004d/pwm5=/sys/bus/i2c/devices/15-004e/hwmon/hwmon*/temp1_input +FCFANS=13-004d/pwm5=13-004d/fan5_input 13-004d/pwm4=13-004d/fan4_input 13-004d/pwm3=13-004d/fan3_input 13-004d/pwm2=13-004d/fan2_input 13-004d/pwm1=13-004d/fan1_input 13-002e/pwm5=13-002e/fan5_input 13-002e/pwm4=13-002e/fan4_input 13-002e/pwm3=13-002e/fan3_input 13-002e/pwm2=13-002e/fan2_input 13-002e/pwm1=13-002e/fan1_input +MINTEMP=13-002e/pwm1=27 13-002e/pwm2=27 13-002e/pwm3=27 13-002e/pwm4=27 13-002e/pwm5=27 13-004d/pwm1=27 13-004d/pwm2=27 13-004d/pwm3=27 13-004d/pwm4=27 13-004d/pwm5=27 +MAXTEMP=13-002e/pwm1=46 13-002e/pwm2=46 13-002e/pwm3=46 13-002e/pwm4=46 13-002e/pwm5=46 13-004d/pwm1=46 13-004d/pwm2=46 13-004d/pwm3=46 13-004d/pwm4=46 13-004d/pwm5=46 +MINSTART=13-002e/pwm1=89 13-002e/pwm2=89 13-002e/pwm3=89 13-002e/pwm4=89 13-002e/pwm5=89 13-004d/pwm1=89 13-004d/pwm2=89 13-004d/pwm3=89 13-004d/pwm4=89 13-004d/pwm5=89 +MINSTOP=13-002e/pwm1=89 13-002e/pwm2=89 13-002e/pwm3=89 13-002e/pwm4=89 13-002e/pwm5=89 13-004d/pwm1=89 13-004d/pwm2=89 13-004d/pwm3=89 13-004d/pwm4=89 13-004d/pwm5=89 +MINPWM=13-002e/pwm1=89 13-002e/pwm2=89 13-002e/pwm3=89 13-002e/pwm4=89 13-002e/pwm5=89 13-004d/pwm1=89 13-004d/pwm2=89 13-004d/pwm3=89 13-004d/pwm4=89 13-004d/pwm5=89 +MAXPWM=13-002e/pwm1=255 13-002e/pwm2=255 13-002e/pwm3=255 13-002e/pwm4=255 13-002e/pwm5=255 13-004d/pwm1=255 13-004d/pwm2=255 13-004d/pwm3=255 13-004d/pwm4=255 13-004d/pwm5=255 +THYST=13-002e/pwm1=3 13-002e/pwm2=3 13-002e/pwm3=3 13-002e/pwm4=3 13-002e/pwm5=3 13-004d/pwm1=3 13-004d/pwm2=3 13-004d/pwm3=3 13-004d/pwm4=3 13-004d/pwm5=3 \ No newline at end of file diff --git a/device/celestica/x86_64-cel_seastone-r0/fancontrol-F2B b/device/celestica/x86_64-cel_seastone-r0/fancontrol-F2B new file mode 100644 index 000000000000..dc67e2623cc2 --- /dev/null +++ b/device/celestica/x86_64-cel_seastone-r0/fancontrol-F2B @@ -0,0 +1,12 @@ +# Configuration file generated by pwmconfig, changes will be lost +INTERVAL=2 +FCTEMPS=13-002e/pwm1=/sys/bus/i2c/devices/5-0048/hwmon/hwmon*/temp1_input 13-002e/pwm2=/sys/bus/i2c/devices/5-0048/hwmon/hwmon*/temp1_input 13-002e/pwm3=/sys/bus/i2c/devices/5-0048/hwmon/hwmon*/temp1_input 13-002e/pwm4=/sys/bus/i2c/devices/5-0048/hwmon/hwmon*/temp1_input 13-002e/pwm5=/sys/bus/i2c/devices/5-0048/hwmon/hwmon*/temp1_input 13-004d/pwm1=/sys/bus/i2c/devices/5-0048/hwmon/hwmon*/temp1_input 13-004d/pwm2=/sys/bus/i2c/devices/5-0048/hwmon/hwmon*/temp1_input 13-004d/pwm3=/sys/bus/i2c/devices/5-0048/hwmon/hwmon*/temp1_input 13-004d/pwm4=/sys/bus/i2c/devices/5-0048/hwmon/hwmon*/temp1_input 13-004d/pwm5=/sys/bus/i2c/devices/5-0048/hwmon/hwmon*/temp1_input +FCFANS=13-004d/pwm5=13-004d/fan5_input 13-004d/pwm4=13-004d/fan4_input 13-004d/pwm3=13-004d/fan3_input 13-004d/pwm2=13-004d/fan2_input 13-004d/pwm1=13-004d/fan1_input 13-002e/pwm5=13-002e/fan5_input 13-002e/pwm4=13-002e/fan4_input 13-002e/pwm3=13-002e/fan3_input 13-002e/pwm2=13-002e/fan2_input 13-002e/pwm1=13-002e/fan1_input +MINTEMP=13-002e/pwm1=26 13-002e/pwm2=26 13-002e/pwm3=26 13-002e/pwm4=26 13-002e/pwm5=26 13-004d/pwm1=26 13-004d/pwm2=26 13-004d/pwm3=26 13-004d/pwm4=26 13-004d/pwm5=26 +MAXTEMP=13-002e/pwm1=45 13-002e/pwm2=45 13-002e/pwm3=45 13-002e/pwm4=45 13-002e/pwm5=45 13-004d/pwm1=45 13-004d/pwm2=45 13-004d/pwm3=45 13-004d/pwm4=45 13-004d/pwm5=45 +MINSTART=13-002e/pwm1=89 13-002e/pwm2=89 13-002e/pwm3=89 13-002e/pwm4=89 13-002e/pwm5=89 13-004d/pwm1=89 13-004d/pwm2=89 13-004d/pwm3=89 13-004d/pwm4=89 13-004d/pwm5=89 +MINSTOP=13-002e/pwm1=89 13-002e/pwm2=89 13-002e/pwm3=89 13-002e/pwm4=89 13-002e/pwm5=89 13-004d/pwm1=89 13-004d/pwm2=89 13-004d/pwm3=89 13-004d/pwm4=89 13-004d/pwm5=89 +MINPWM=13-002e/pwm1=89 13-002e/pwm2=89 13-002e/pwm3=89 13-002e/pwm4=89 13-002e/pwm5=89 13-004d/pwm1=89 13-004d/pwm2=89 13-004d/pwm3=89 13-004d/pwm4=89 13-004d/pwm5=89 +MAXPWM=13-002e/pwm1=255 13-002e/pwm2=255 13-002e/pwm3=255 13-002e/pwm4=255 13-002e/pwm5=255 13-004d/pwm1=255 13-004d/pwm2=255 13-004d/pwm3=255 13-004d/pwm4=255 13-004d/pwm5=255 +THYST=13-002e/pwm1=3 13-002e/pwm2=3 13-002e/pwm3=3 13-002e/pwm4=3 13-002e/pwm5=3 13-004d/pwm1=3 13-004d/pwm2=3 13-004d/pwm3=3 13-004d/pwm4=3 13-004d/pwm5=3 + diff --git a/device/dell/x86_64-dell_s6000_s1220-r0/plugins/eeprom.py b/device/dell/x86_64-dell_s6000_s1220-r0/plugins/eeprom.py index b326d24f6d44..10364c2c9f8e 100644 --- a/device/dell/x86_64-dell_s6000_s1220-r0/plugins/eeprom.py +++ b/device/dell/x86_64-dell_s6000_s1220-r0/plugins/eeprom.py @@ -10,13 +10,21 @@ ############################################################################# try: - from sonic_eeprom import eeprom_tlvinfo -except ImportError, e: - raise ImportError (str(e) + "- required module not found") + from sonic_eeprom.eeprom_tlvinfo import TlvInfoDecoder + from sonic_platform.eeprom import EepromS6000 +except ImportError as e: + raise ImportError(str(e) + "- required module not found") -class board(eeprom_tlvinfo.TlvInfoDecoder): +class board(object): - def __init__(self, name, path, cpld_root, ro): - self.eeprom_path = "/sys/class/i2c-adapter/i2c-10/10-0053/eeprom" - super(board, self).__init__(self.eeprom_path, 0, '', True) + def __new__(cls, name, path, cpld_root, ro): + eeprom_path = "/sys/class/i2c-adapter/i2c-10/10-0053/eeprom" + + with open("/sys/class/dmi/id/product_name", "r") as fd: + board_type = fd.read() + + if 'S6000-ON' in board_type: + return TlvInfoDecoder(eeprom_path, 0, '', True) + else: + return EepromS6000(is_plugin=True) diff --git a/device/dell/x86_64-dell_s6000_s1220-r0/pmon_daemon_control.json b/device/dell/x86_64-dell_s6000_s1220-r0/pmon_daemon_control.json index 94592fa8cebc..44871c057e82 100644 --- a/device/dell/x86_64-dell_s6000_s1220-r0/pmon_daemon_control.json +++ b/device/dell/x86_64-dell_s6000_s1220-r0/pmon_daemon_control.json @@ -1,3 +1,4 @@ { - "skip_ledd": true + "skip_ledd": true, + "skip_thermalctld": true } diff --git a/device/dell/x86_64-dell_s6100_c2538-r0/pmon_daemon_control.json b/device/dell/x86_64-dell_s6100_c2538-r0/pmon_daemon_control.json index 94592fa8cebc..44871c057e82 100644 --- a/device/dell/x86_64-dell_s6100_c2538-r0/pmon_daemon_control.json +++ b/device/dell/x86_64-dell_s6100_c2538-r0/pmon_daemon_control.json @@ -1,3 +1,4 @@ { - "skip_ledd": true + "skip_ledd": true, + "skip_thermalctld": true } diff --git a/device/dell/x86_64-dell_z9100_c2538-r0/pmon_daemon_control.json b/device/dell/x86_64-dell_z9100_c2538-r0/pmon_daemon_control.json index 94592fa8cebc..44871c057e82 100644 --- a/device/dell/x86_64-dell_z9100_c2538-r0/pmon_daemon_control.json +++ b/device/dell/x86_64-dell_z9100_c2538-r0/pmon_daemon_control.json @@ -1,3 +1,4 @@ { - "skip_ledd": true + "skip_ledd": true, + "skip_thermalctld": true } diff --git a/device/dell/x86_64-dellemc_s5232f_c3538-r0/DellEMC-S5232f-C8D48/port_config.ini b/device/dell/x86_64-dellemc_s5232f_c3538-r0/DellEMC-S5232f-C8D48/port_config.ini index b7a336827ffe..3fc2ef699913 100644 --- a/device/dell/x86_64-dellemc_s5232f_c3538-r0/DellEMC-S5232f-C8D48/port_config.ini +++ b/device/dell/x86_64-dellemc_s5232f_c3538-r0/DellEMC-S5232f-C8D48/port_config.ini @@ -39,18 +39,18 @@ Ethernet80 81,82 fiftyGigE1/21/1 21 50000 Ethernet82 83,84 fiftyGigE1/21/2 21 50000 Ethernet84 85,86 fiftyGigE1/22/1 22 50000 Ethernet86 87,88 fiftyGigE1/22/2 22 50000 -Ethernet88 89,90 fiftyGigE1/23/1 23 50000 -Ethernet90 91,92 fiftyGigE1/23/2 23 50000 -Ethernet92 93,94 fiftyGigE1/24/1 24 50000 -Ethernet94 95,96 fiftyGigE1/24/2 24 50000 -Ethernet96 97,98 fiftyGigE1/25/1 25 50000 -Ethernet98 99,100 fiftyGigE1/25/2 25 50000 -Ethernet100 101,102 fiftyGigE1/26/1 26 50000 -Ethernet102 103,104 fiftyGigE1/26/2 26 50000 -Ethernet104 105,106,107,108 hundredGigE1/27 27 100000 -Ethernet108 109,110,111,112 hundredGigE1/28 28 100000 -Ethernet112 113,114,115,116 hundredGigE1/29 29 100000 -Ethernet116 117,118,119,120 hundredGigE1/30 30 100000 +Ethernet88 89,90,91,92 hundredGigE1/23 23 100000 +Ethernet92 93,94,95,96 hundredGigE1/24 24 100000 +Ethernet96 97,98,99,100 hundredGigE1/25 25 100000 +Ethernet100 101,102,103,104 hundredGigE1/26 26 100000 +Ethernet104 105,106 fiftyGigE1/27/1 27 50000 +Ethernet106 107,108 fiftyGigE1/27/2 27 50000 +Ethernet108 109,110 fiftyGigE1/28/1 28 50000 +Ethernet110 111,112 fiftyGigE1/28/2 28 50000 +Ethernet112 113,114 fiftyGigE1/29/1 29 50000 +Ethernet114 115,116 fiftyGigE1/29/2 29 50000 +Ethernet116 117,118 fiftyGigE1/30/1 30 50000 +Ethernet118 119,120 fiftyGigE1/30/2 30 50000 Ethernet120 121,122 fiftyGigE1/31/1 31 50000 Ethernet122 123,124 fiftyGigE1/31/2 31 50000 Ethernet124 125,126 fiftyGigE1/32/1 32 50000 diff --git a/device/dell/x86_64-dellemc_s5232f_c3538-r0/DellEMC-S5232f-C8D48/td3-s5232f-8x100G+48x50G.config.bcm b/device/dell/x86_64-dellemc_s5232f_c3538-r0/DellEMC-S5232f-C8D48/td3-s5232f-8x100G+48x50G.config.bcm index cf0bfd043ee0..b9762a712d94 100644 --- a/device/dell/x86_64-dellemc_s5232f_c3538-r0/DellEMC-S5232f-C8D48/td3-s5232f-8x100G+48x50G.config.bcm +++ b/device/dell/x86_64-dellemc_s5232f_c3538-r0/DellEMC-S5232f-C8D48/td3-s5232f-8x100G+48x50G.config.bcm @@ -85,18 +85,18 @@ portmap_83.0=81:50:2 portmap_85.0=83:50:2 portmap_87.0=85:50:2 portmap_89.0=87:50:2 -portmap_91.0=89:50:2 -portmap_93.0=91:50:2 -portmap_95.0=93:50:2 -portmap_97.0=95:50:2 -portmap_99.0=97:50:2 -portmap_101.0=99:50:2 -portmap_103.0=101:50:2 -portmap_105.0=103:50:2 -portmap_107.0=105:100 -portmap_111.0=109:100 -portmap_115.0=113:100 -portmap_119.0=117:100 +portmap_91.0=89:100 +portmap_95.0=93:100 +portmap_99.0=97:100 +portmap_103.0=101:100 +portmap_107.0=105:50:2 +portmap_109.0=107:50:2 +portmap_111.0=109:50:2 +portmap_113.0=111:50:2 +portmap_115.0=113:50:2 +portmap_117.0=115:50:2 +portmap_119.0=117:50:2 +portmap_121.0=119:50:2 portmap_123.0=121:50:2 portmap_125.0=123:50:2 portmap_127.0=125:50:2 diff --git a/device/dell/x86_64-dellemc_s5232f_c3538-r0/plugins/sfputil.py b/device/dell/x86_64-dellemc_s5232f_c3538-r0/plugins/sfputil.py index 62dc5cb9c34b..c50dfb752484 100644 --- a/device/dell/x86_64-dellemc_s5232f_c3538-r0/plugins/sfputil.py +++ b/device/dell/x86_64-dellemc_s5232f_c3538-r0/plugins/sfputil.py @@ -192,7 +192,7 @@ def set_low_power_mode(self, port_num, lpmode): if (reg_value == "" ): return False - # Mask off 4th bit for presence + # Mask off 6th bit for lpmode mask = (1 << 6) # LPMode is active high; set or clear the bit accordingly @@ -223,7 +223,7 @@ def reset(self, port_num): return False # Mask off 4th bit for presence - mask = (1 << 6) + mask = (1 << 4) # ResetL is active low reg_value = reg_value & ~mask diff --git a/device/dell/x86_64-dellemc_s5248f_c3538-r0/plugins/sfputil.py b/device/dell/x86_64-dellemc_s5248f_c3538-r0/plugins/sfputil.py index e6680dc8d919..d12e52996da7 100644 --- a/device/dell/x86_64-dellemc_s5248f_c3538-r0/plugins/sfputil.py +++ b/device/dell/x86_64-dellemc_s5248f_c3538-r0/plugins/sfputil.py @@ -221,7 +221,7 @@ def set_low_power_mode(self, port_num, lpmode): if (reg_value == "" ): return False - # Mask off 4th bit for presence + # Mask off 6th bit for lpmode mask = (1 << 6) # LPMode is active high; set or clear the bit accordingly @@ -252,7 +252,7 @@ def reset(self, port_num): return False # Mask off 4th bit for presence - mask = (1 << 6) + mask = (1 << 4) # ResetL is active low reg_value = reg_value & ~mask diff --git a/device/dell/x86_64-dellemc_z9264f_c3538-r0/pmon_daemon_control.json b/device/dell/x86_64-dellemc_z9264f_c3538-r0/pmon_daemon_control.json index 94592fa8cebc..44871c057e82 100644 --- a/device/dell/x86_64-dellemc_z9264f_c3538-r0/pmon_daemon_control.json +++ b/device/dell/x86_64-dellemc_z9264f_c3538-r0/pmon_daemon_control.json @@ -1,3 +1,4 @@ { - "skip_ledd": true + "skip_ledd": true, + "skip_thermalctld": true } diff --git a/device/mellanox/x86_64-mlnx_lssn2700-r0/thermal_policy.json b/device/mellanox/x86_64-mlnx_lssn2700-r0/thermal_policy.json new file mode 120000 index 000000000000..5a25cd87f70c --- /dev/null +++ b/device/mellanox/x86_64-mlnx_lssn2700-r0/thermal_policy.json @@ -0,0 +1 @@ +../x86_64-mlnx_msn2700-r0/thermal_policy.json \ No newline at end of file diff --git a/device/mellanox/x86_64-mlnx_msn2010-r0/ACS-MSN2010/port_config.ini b/device/mellanox/x86_64-mlnx_msn2010-r0/ACS-MSN2010/port_config.ini index 2bd7aef02e1f..f9fa81669a13 100644 --- a/device/mellanox/x86_64-mlnx_msn2010-r0/ACS-MSN2010/port_config.ini +++ b/device/mellanox/x86_64-mlnx_msn2010-r0/ACS-MSN2010/port_config.ini @@ -1,23 +1,23 @@ # name lanes index -Ethernet0 0 0 -Ethernet4 4 1 -Ethernet8 8 2 -Ethernet12 12 3 -Ethernet16 16 4 -Ethernet20 20 5 -Ethernet24 24 6 -Ethernet28 28 7 -Ethernet32 32 8 -Ethernet36 36 9 -Ethernet40 40 10 -Ethernet44 44 11 -Ethernet48 48 12 -Ethernet52 52 13 -Ethernet56 56 14 -Ethernet60 60 15 -Ethernet64 64 16 -Ethernet68 68 17 -Ethernet72 72,73,74,75 18 -Ethernet76 76,77,78,79 19 -Ethernet80 80,81,82,83 20 -Ethernet84 84,85,86,87 21 +Ethernet0 0 1 +Ethernet4 4 2 +Ethernet8 8 3 +Ethernet12 12 4 +Ethernet16 16 5 +Ethernet20 20 6 +Ethernet24 24 7 +Ethernet28 28 8 +Ethernet32 32 9 +Ethernet36 36 10 +Ethernet40 40 11 +Ethernet44 44 12 +Ethernet48 48 13 +Ethernet52 52 14 +Ethernet56 56 15 +Ethernet60 60 16 +Ethernet64 64 17 +Ethernet68 68 18 +Ethernet72 72,73,74,75 19 +Ethernet76 76,77,78,79 20 +Ethernet80 80,81,82,83 21 +Ethernet84 84,85,86,87 22 diff --git a/device/mellanox/x86_64-mlnx_msn2010-r0/thermal_policy.json b/device/mellanox/x86_64-mlnx_msn2010-r0/thermal_policy.json new file mode 120000 index 000000000000..5a25cd87f70c --- /dev/null +++ b/device/mellanox/x86_64-mlnx_msn2010-r0/thermal_policy.json @@ -0,0 +1 @@ +../x86_64-mlnx_msn2700-r0/thermal_policy.json \ No newline at end of file diff --git a/device/mellanox/x86_64-mlnx_msn2100-r0/ACS-MSN2100/port_config.ini b/device/mellanox/x86_64-mlnx_msn2100-r0/ACS-MSN2100/port_config.ini index c792a4114b9c..c7ea79bbdbee 100644 --- a/device/mellanox/x86_64-mlnx_msn2100-r0/ACS-MSN2100/port_config.ini +++ b/device/mellanox/x86_64-mlnx_msn2100-r0/ACS-MSN2100/port_config.ini @@ -1,17 +1,17 @@ -# name lanes -Ethernet0 0,1,2,3 -Ethernet4 4,5,6,7 -Ethernet8 8,9,10,11 -Ethernet12 12,13,14,15 -Ethernet16 16,17,18,19 -Ethernet20 20,21,22,23 -Ethernet24 24,25,26,27 -Ethernet28 28,29,30,31 -Ethernet32 32,33,34,35 -Ethernet36 36,37,38,39 -Ethernet40 40,41,42,43 -Ethernet44 44,45,46,47 -Ethernet48 48,49,50,51 -Ethernet52 52,53,54,55 -Ethernet56 56,57,58,59 -Ethernet60 60,61,62,63 +# name lanes index +Ethernet0 0,1,2,3 1 +Ethernet4 4,5,6,7 2 +Ethernet8 8,9,10,11 3 +Ethernet12 12,13,14,15 4 +Ethernet16 16,17,18,19 5 +Ethernet20 20,21,22,23 6 +Ethernet24 24,25,26,27 7 +Ethernet28 28,29,30,31 8 +Ethernet32 32,33,34,35 9 +Ethernet36 36,37,38,39 10 +Ethernet40 40,41,42,43 11 +Ethernet44 44,45,46,47 12 +Ethernet48 48,49,50,51 13 +Ethernet52 52,53,54,55 14 +Ethernet56 56,57,58,59 15 +Ethernet60 60,61,62,63 16 diff --git a/device/mellanox/x86_64-mlnx_msn2100-r0/thermal_policy.json b/device/mellanox/x86_64-mlnx_msn2100-r0/thermal_policy.json new file mode 120000 index 000000000000..5a25cd87f70c --- /dev/null +++ b/device/mellanox/x86_64-mlnx_msn2100-r0/thermal_policy.json @@ -0,0 +1 @@ +../x86_64-mlnx_msn2700-r0/thermal_policy.json \ No newline at end of file diff --git a/device/mellanox/x86_64-mlnx_msn2410-r0/ACS-MSN2410/port_config.ini b/device/mellanox/x86_64-mlnx_msn2410-r0/ACS-MSN2410/port_config.ini index c7db66b02274..782949e5706a 100644 --- a/device/mellanox/x86_64-mlnx_msn2410-r0/ACS-MSN2410/port_config.ini +++ b/device/mellanox/x86_64-mlnx_msn2410-r0/ACS-MSN2410/port_config.ini @@ -1,57 +1,57 @@ -# name lanes -Ethernet0 0 -Ethernet4 4 -Ethernet8 8 -Ethernet12 12 -Ethernet16 16 -Ethernet20 20 -Ethernet24 24 -Ethernet28 28 -Ethernet32 32 -Ethernet36 36 -Ethernet40 40 -Ethernet44 44 -Ethernet48 48 -Ethernet52 52 -Ethernet56 56 -Ethernet60 60 -Ethernet64 64 -Ethernet68 68 -Ethernet72 72 -Ethernet76 76 -Ethernet80 80 -Ethernet84 84 -Ethernet88 88 -Ethernet92 92 -Ethernet96 96 -Ethernet100 100 -Ethernet104 104 -Ethernet108 108 -Ethernet112 112 -Ethernet116 116 -Ethernet120 120 -Ethernet124 124 -Ethernet128 128 -Ethernet132 132 -Ethernet136 136 -Ethernet140 140 -Ethernet144 144 -Ethernet148 148 -Ethernet152 152 -Ethernet156 156 -Ethernet160 160 -Ethernet164 164 -Ethernet168 168 -Ethernet172 172 -Ethernet176 176 -Ethernet180 180 -Ethernet184 184 -Ethernet188 188 -Ethernet192 192,193,194,195 -Ethernet196 196,197,198,199 -Ethernet200 200,201,202,203 -Ethernet204 204,205,206,207 -Ethernet208 208,209,210,211 -Ethernet212 212,213,214,215 -Ethernet216 216,217,218,219 -Ethernet220 220,221,222,223 +# name lanes index +Ethernet0 0 1 +Ethernet4 4 2 +Ethernet8 8 3 +Ethernet12 12 4 +Ethernet16 16 5 +Ethernet20 20 6 +Ethernet24 24 7 +Ethernet28 28 8 +Ethernet32 32 9 +Ethernet36 36 10 +Ethernet40 40 11 +Ethernet44 44 12 +Ethernet48 48 13 +Ethernet52 52 14 +Ethernet56 56 15 +Ethernet60 60 16 +Ethernet64 64 17 +Ethernet68 68 18 +Ethernet72 72 19 +Ethernet76 76 20 +Ethernet80 80 21 +Ethernet84 84 22 +Ethernet88 88 23 +Ethernet92 92 24 +Ethernet96 96 25 +Ethernet100 100 26 +Ethernet104 104 27 +Ethernet108 108 28 +Ethernet112 112 29 +Ethernet116 116 30 +Ethernet120 120 31 +Ethernet124 124 32 +Ethernet128 128 33 +Ethernet132 132 34 +Ethernet136 136 35 +Ethernet140 140 36 +Ethernet144 144 37 +Ethernet148 148 38 +Ethernet152 152 39 +Ethernet156 156 40 +Ethernet160 160 41 +Ethernet164 164 42 +Ethernet168 168 43 +Ethernet172 172 44 +Ethernet176 176 45 +Ethernet180 180 46 +Ethernet184 184 47 +Ethernet188 188 48 +Ethernet192 192,193,194,195 49 +Ethernet196 196,197,198,199 50 +Ethernet200 200,201,202,203 51 +Ethernet204 204,205,206,207 52 +Ethernet208 208,209,210,211 53 +Ethernet212 212,213,214,215 54 +Ethernet216 216,217,218,219 55 +Ethernet220 220,221,222,223 56 diff --git a/device/mellanox/x86_64-mlnx_msn2410-r0/thermal_policy.json b/device/mellanox/x86_64-mlnx_msn2410-r0/thermal_policy.json new file mode 120000 index 000000000000..5a25cd87f70c --- /dev/null +++ b/device/mellanox/x86_64-mlnx_msn2410-r0/thermal_policy.json @@ -0,0 +1 @@ +../x86_64-mlnx_msn2700-r0/thermal_policy.json \ No newline at end of file diff --git a/device/mellanox/x86_64-mlnx_msn2700-r0/ACS-MSN2700/port_config.ini b/device/mellanox/x86_64-mlnx_msn2700-r0/ACS-MSN2700/port_config.ini index 1e1906ff0ef5..c1e59909c0fb 100644 --- a/device/mellanox/x86_64-mlnx_msn2700-r0/ACS-MSN2700/port_config.ini +++ b/device/mellanox/x86_64-mlnx_msn2700-r0/ACS-MSN2700/port_config.ini @@ -1,33 +1,33 @@ -# name lanes alias -Ethernet0 0,1,2,3 etp1 -Ethernet4 4,5,6,7 etp2 -Ethernet8 8,9,10,11 etp3 -Ethernet12 12,13,14,15 etp4 -Ethernet16 16,17,18,19 etp5 -Ethernet20 20,21,22,23 etp6 -Ethernet24 24,25,26,27 etp7 -Ethernet28 28,29,30,31 etp8 -Ethernet32 32,33,34,35 etp9 -Ethernet36 36,37,38,39 etp10 -Ethernet40 40,41,42,43 etp11 -Ethernet44 44,45,46,47 etp12 -Ethernet48 48,49,50,51 etp13 -Ethernet52 52,53,54,55 etp14 -Ethernet56 56,57,58,59 etp15 -Ethernet60 60,61,62,63 etp16 -Ethernet64 64,65,66,67 etp17 -Ethernet68 68,69,70,71 etp18 -Ethernet72 72,73,74,75 etp19 -Ethernet76 76,77,78,79 etp20 -Ethernet80 80,81,82,83 etp21 -Ethernet84 84,85,86,87 etp22 -Ethernet88 88,89,90,91 etp23 -Ethernet92 92,93,94,95 etp24 -Ethernet96 96,97,98,99 etp25 -Ethernet100 100,101,102,103 etp26 -Ethernet104 104,105,106,107 etp27 -Ethernet108 108,109,110,111 etp28 -Ethernet112 112,113,114,115 etp29 -Ethernet116 116,117,118,119 etp30 -Ethernet120 120,121,122,123 etp31 -Ethernet124 124,125,126,127 etp32 +# name lanes alias index +Ethernet0 0,1,2,3 etp1 1 +Ethernet4 4,5,6,7 etp2 2 +Ethernet8 8,9,10,11 etp3 3 +Ethernet12 12,13,14,15 etp4 4 +Ethernet16 16,17,18,19 etp5 5 +Ethernet20 20,21,22,23 etp6 6 +Ethernet24 24,25,26,27 etp7 7 +Ethernet28 28,29,30,31 etp8 8 +Ethernet32 32,33,34,35 etp9 9 +Ethernet36 36,37,38,39 etp10 10 +Ethernet40 40,41,42,43 etp11 11 +Ethernet44 44,45,46,47 etp12 12 +Ethernet48 48,49,50,51 etp13 13 +Ethernet52 52,53,54,55 etp14 14 +Ethernet56 56,57,58,59 etp15 15 +Ethernet60 60,61,62,63 etp16 16 +Ethernet64 64,65,66,67 etp17 17 +Ethernet68 68,69,70,71 etp18 18 +Ethernet72 72,73,74,75 etp19 19 +Ethernet76 76,77,78,79 etp20 20 +Ethernet80 80,81,82,83 etp21 21 +Ethernet84 84,85,86,87 etp22 22 +Ethernet88 88,89,90,91 etp23 23 +Ethernet92 92,93,94,95 etp24 24 +Ethernet96 96,97,98,99 etp25 25 +Ethernet100 100,101,102,103 etp26 26 +Ethernet104 104,105,106,107 etp27 27 +Ethernet108 108,109,110,111 etp28 28 +Ethernet112 112,113,114,115 etp29 29 +Ethernet116 116,117,118,119 etp30 30 +Ethernet120 120,121,122,123 etp31 31 +Ethernet124 124,125,126,127 etp32 32 diff --git a/device/mellanox/x86_64-mlnx_msn2700-r0/Mellanox-SN2700-C28D8/port_config.ini b/device/mellanox/x86_64-mlnx_msn2700-r0/Mellanox-SN2700-C28D8/port_config.ini index 8bc48269d163..653a61ecc23c 100644 --- a/device/mellanox/x86_64-mlnx_msn2700-r0/Mellanox-SN2700-C28D8/port_config.ini +++ b/device/mellanox/x86_64-mlnx_msn2700-r0/Mellanox-SN2700-C28D8/port_config.ini @@ -1,37 +1,37 @@ # name lanes alias index speed -Ethernet0 0,1,2,3 etp1 0 100000 -Ethernet4 4,5,6,7 etp2 1 100000 -Ethernet8 8,9,10,11 etp3 2 100000 -Ethernet12 12,13,14,15 etp4 3 100000 -Ethernet16 16,17,18,19 etp5 4 100000 -Ethernet20 20,21,22,23 etp6 5 100000 -Ethernet24 24,25,26,27 etp7 6 100000 -Ethernet28 28,29,30,31 etp8 7 100000 -Ethernet32 32,33,34,35 etp9 8 100000 -Ethernet36 36,37,38,39 etp10 9 100000 -Ethernet40 40,41,42,43 etp11 10 100000 -Ethernet44 44,45,46,47 etp12 11 100000 -Ethernet48 48,49,50,51 etp13 12 100000 -Ethernet52 52,53,54,55 etp14 13 100000 -Ethernet56 56,57,58,59 etp15 14 100000 -Ethernet60 60,61,62,63 etp16 15 100000 -Ethernet64 64,65,66,67 etp17 16 100000 -Ethernet68 68,69,70,71 etp18 17 100000 -Ethernet72 72,73,74,75 etp19 18 100000 -Ethernet76 76,77,78,79 etp20 19 100000 -Ethernet80 80,81,82,83 etp21 20 100000 -Ethernet84 84,85,86,87 etp22 21 100000 -Ethernet88 88,89,90,91 etp23 22 100000 -Ethernet92 92,93,94,95 etp24 23 100000 -Ethernet96 96,97,98,99 etp25 24 100000 -Ethernet100 100,101,102,103 etp26 25 100000 -Ethernet104 104,105,106,107 etp27 26 100000 -Ethernet108 108,109,110,111 etp28 27 100000 -Ethernet112 112,113 etp29a 28 50000 -Ethernet114 114,115 etp29b 28 50000 -Ethernet116 116,117 etp30a 29 50000 -Ethernet118 118,119 etp30b 29 50000 -Ethernet120 120,121 etp31a 30 50000 -Ethernet122 122,123 etp31b 30 50000 -Ethernet124 124,125 etp32a 31 50000 -Ethernet126 126,127 etp32b 31 50000 +Ethernet0 0,1,2,3 etp1 1 100000 +Ethernet4 4,5,6,7 etp2 2 100000 +Ethernet8 8,9,10,11 etp3 3 100000 +Ethernet12 12,13,14,15 etp4 4 100000 +Ethernet16 16,17,18,19 etp5 5 100000 +Ethernet20 20,21,22,23 etp6 6 100000 +Ethernet24 24,25,26,27 etp7 7 100000 +Ethernet28 28,29,30,31 etp8 8 100000 +Ethernet32 32,33,34,35 etp9 9 100000 +Ethernet36 36,37,38,39 etp10 10 100000 +Ethernet40 40,41,42,43 etp11 11 100000 +Ethernet44 44,45,46,47 etp12 12 100000 +Ethernet48 48,49,50,51 etp13 13 100000 +Ethernet52 52,53,54,55 etp14 14 100000 +Ethernet56 56,57,58,59 etp15 15 100000 +Ethernet60 60,61,62,63 etp16 16 100000 +Ethernet64 64,65,66,67 etp17 17 100000 +Ethernet68 68,69,70,71 etp18 18 100000 +Ethernet72 72,73,74,75 etp19 19 100000 +Ethernet76 76,77,78,79 etp20 20 100000 +Ethernet80 80,81,82,83 etp21 21 100000 +Ethernet84 84,85,86,87 etp22 22 100000 +Ethernet88 88,89,90,91 etp23 23 100000 +Ethernet92 92,93,94,95 etp24 24 100000 +Ethernet96 96,97,98,99 etp25 25 100000 +Ethernet100 100,101,102,103 etp26 26 100000 +Ethernet104 104,105,106,107 etp27 27 100000 +Ethernet108 108,109,110,111 etp28 28 100000 +Ethernet112 112,113 etp29a 29 50000 +Ethernet114 114,115 etp29b 29 50000 +Ethernet116 116,117 etp30a 30 50000 +Ethernet118 118,119 etp30b 30 50000 +Ethernet120 120,121 etp31a 31 50000 +Ethernet122 122,123 etp31b 31 50000 +Ethernet124 124,125 etp32a 32 50000 +Ethernet126 126,127 etp32b 32 50000 diff --git a/device/mellanox/x86_64-mlnx_msn2700-r0/Mellanox-SN2700-D48C8/port_config.ini b/device/mellanox/x86_64-mlnx_msn2700-r0/Mellanox-SN2700-D48C8/port_config.ini index f9f465f1a3ea..830f558fb383 100644 --- a/device/mellanox/x86_64-mlnx_msn2700-r0/Mellanox-SN2700-D48C8/port_config.ini +++ b/device/mellanox/x86_64-mlnx_msn2700-r0/Mellanox-SN2700-D48C8/port_config.ini @@ -1,57 +1,57 @@ # name lanes alias index speed -Ethernet0 0,1 etp1a 0 50000 -Ethernet2 2,3 etp1b 0 50000 -Ethernet4 4,5 etp2a 1 50000 -Ethernet6 6,7 etp2b 1 50000 -Ethernet8 8,9 etp3a 2 50000 -Ethernet10 10,11 etp3b 2 50000 -Ethernet12 12,13 etp4a 3 50000 -Ethernet14 14,15 etp4b 3 50000 -Ethernet16 16,17 etp5a 4 50000 -Ethernet18 18,19 etp5b 4 50000 -Ethernet20 20,21 etp6a 5 50000 -Ethernet22 22,23 etp6b 5 50000 -Ethernet24 24,25,26,27 etp7 6 100000 -Ethernet28 28,29,30,31 etp8 7 100000 -Ethernet32 32,33,34,35 etp9 8 100000 -Ethernet36 36,37,38,39 etp10 9 100000 -Ethernet40 40,41 etp11a 10 50000 -Ethernet42 42,43 etp11b 10 50000 -Ethernet44 44,45 etp12a 11 50000 -Ethernet46 46,47 etp12b 11 50000 -Ethernet48 48,49 etp13a 12 50000 -Ethernet50 50,51 etp13b 12 50000 -Ethernet52 52,53 etp14a 13 50000 -Ethernet54 54,55 etp14b 13 50000 -Ethernet56 56,57 etp15a 14 50000 -Ethernet58 58,59 etp15b 14 50000 -Ethernet60 60,61 etp16a 15 50000 -Ethernet62 62,63 etp16b 15 50000 -Ethernet64 64,65 etp17a 16 50000 -Ethernet66 66,67 etp17b 16 50000 -Ethernet68 68,69 etp18a 17 50000 -Ethernet70 70,71 etp18b 17 50000 -Ethernet72 72,73 etp19a 18 50000 -Ethernet74 74,75 etp19b 18 50000 -Ethernet76 76,77 etp20a 19 50000 -Ethernet78 78,79 etp20b 19 50000 -Ethernet80 80,81 etp21a 20 50000 -Ethernet82 82,83 etp21b 20 50000 -Ethernet84 84,85 etp22a 21 50000 -Ethernet86 86,87 etp22b 21 50000 -Ethernet88 88,89,90,91 etp23 22 100000 -Ethernet92 92,93,94,95 etp24 23 100000 -Ethernet96 96,97,98,99 etp25 24 100000 -Ethernet100 100,101,102,103 etp26 25 100000 -Ethernet104 104,105 etp27a 26 50000 -Ethernet106 106,107 etp27b 26 50000 -Ethernet108 108,109 etp28a 27 50000 -Ethernet110 110,111 etp28b 27 50000 -Ethernet112 112,113 etp29a 28 50000 -Ethernet114 114,115 etp29b 28 50000 -Ethernet116 116,117 etp30a 29 50000 -Ethernet118 118,119 etp30b 29 50000 -Ethernet120 120,121 etp31a 30 50000 -Ethernet122 122,123 etp31b 30 50000 -Ethernet124 124,125 etp32a 31 50000 -Ethernet126 126,127 etp32b 31 50000 +Ethernet0 0,1 etp1a 1 50000 +Ethernet2 2,3 etp1b 1 50000 +Ethernet4 4,5 etp2a 2 50000 +Ethernet6 6,7 etp2b 2 50000 +Ethernet8 8,9 etp3a 3 50000 +Ethernet10 10,11 etp3b 3 50000 +Ethernet12 12,13 etp4a 4 50000 +Ethernet14 14,15 etp4b 4 50000 +Ethernet16 16,17 etp5a 5 50000 +Ethernet18 18,19 etp5b 5 50000 +Ethernet20 20,21 etp6a 6 50000 +Ethernet22 22,23 etp6b 6 50000 +Ethernet24 24,25,26,27 etp7 7 100000 +Ethernet28 28,29,30,31 etp8 8 100000 +Ethernet32 32,33,34,35 etp9 9 100000 +Ethernet36 36,37,38,39 etp10 10 100000 +Ethernet40 40,41 etp11a 11 50000 +Ethernet42 42,43 etp11b 11 50000 +Ethernet44 44,45 etp12a 12 50000 +Ethernet46 46,47 etp12b 12 50000 +Ethernet48 48,49 etp13a 13 50000 +Ethernet50 50,51 etp13b 13 50000 +Ethernet52 52,53 etp14a 14 50000 +Ethernet54 54,55 etp14b 14 50000 +Ethernet56 56,57 etp15a 15 50000 +Ethernet58 58,59 etp15b 15 50000 +Ethernet60 60,61 etp16a 16 50000 +Ethernet62 62,63 etp16b 16 50000 +Ethernet64 64,65 etp17a 17 50000 +Ethernet66 66,67 etp17b 17 50000 +Ethernet68 68,69 etp18a 18 50000 +Ethernet70 70,71 etp18b 18 50000 +Ethernet72 72,73 etp19a 19 50000 +Ethernet74 74,75 etp19b 19 50000 +Ethernet76 76,77 etp20a 20 50000 +Ethernet78 78,79 etp20b 20 50000 +Ethernet80 80,81 etp21a 21 50000 +Ethernet82 82,83 etp21b 21 50000 +Ethernet84 84,85 etp22a 22 50000 +Ethernet86 86,87 etp22b 22 50000 +Ethernet88 88,89,90,91 etp23 23 100000 +Ethernet92 92,93,94,95 etp24 24 100000 +Ethernet96 96,97,98,99 etp25 25 100000 +Ethernet100 100,101,102,103 etp26 26 100000 +Ethernet104 104,105 etp27a 27 50000 +Ethernet106 106,107 etp27b 27 50000 +Ethernet108 108,109 etp28a 28 50000 +Ethernet110 110,111 etp28b 28 50000 +Ethernet112 112,113 etp29a 29 50000 +Ethernet114 114,115 etp29b 29 50000 +Ethernet116 116,117 etp30a 30 50000 +Ethernet118 118,119 etp30b 30 50000 +Ethernet120 120,121 etp31a 31 50000 +Ethernet122 122,123 etp31b 31 50000 +Ethernet124 124,125 etp32a 32 50000 +Ethernet126 126,127 etp32b 32 50000 diff --git a/device/mellanox/x86_64-mlnx_msn2700-r0/plugins/sfplpmget.py b/device/mellanox/x86_64-mlnx_msn2700-r0/plugins/sfplpmget.py index 170766e9bce4..a4a53fb099f1 100644 --- a/device/mellanox/x86_64-mlnx_msn2700-r0/plugins/sfplpmget.py +++ b/device/mellanox/x86_64-mlnx_msn2700-r0/plugins/sfplpmget.py @@ -24,7 +24,7 @@ sys.exit(errno.EACCES) # Get SFP module number -sfp_module = int(sys.argv[1]) +sfp_module = int(sys.argv[1]) - 1 # Get MCION mcion = ku_mcion_reg() diff --git a/device/mellanox/x86_64-mlnx_msn2700-r0/plugins/sfplpmset.py b/device/mellanox/x86_64-mlnx_msn2700-r0/plugins/sfplpmset.py index f9b35b8e74e7..9fafaa951404 100644 --- a/device/mellanox/x86_64-mlnx_msn2700-r0/plugins/sfplpmset.py +++ b/device/mellanox/x86_64-mlnx_msn2700-r0/plugins/sfplpmset.py @@ -146,7 +146,7 @@ def set_sfp_lpmode(sfp_module, lpm_enable): sys.exit(errno.EACCES); # Get SFP module -sfp_module = int(sys.argv[1]) +sfp_module = int(sys.argv[1]) - 1 # Get all ports at admin up status that related to the SFP module log_port_list = get_log_ports(handle, sfp_module) diff --git a/device/mellanox/x86_64-mlnx_msn2700-r0/plugins/sfpreset.py b/device/mellanox/x86_64-mlnx_msn2700-r0/plugins/sfpreset.py index 69fa2be614c2..2ba6c6d7bc78 100644 --- a/device/mellanox/x86_64-mlnx_msn2700-r0/plugins/sfpreset.py +++ b/device/mellanox/x86_64-mlnx_msn2700-r0/plugins/sfpreset.py @@ -24,7 +24,7 @@ sys.exit(errno.EACCES) # Get SFP module number -sfp_module = int(sys.argv[1]) +sfp_module = int(sys.argv[1]) - 1 # Get PMAOS pmaos = ku_pmaos_reg() diff --git a/device/mellanox/x86_64-mlnx_msn2700-r0/plugins/sfputil.py b/device/mellanox/x86_64-mlnx_msn2700-r0/plugins/sfputil.py index 647d967f84a1..71d8945afdad 100644 --- a/device/mellanox/x86_64-mlnx_msn2700-r0/plugins/sfputil.py +++ b/device/mellanox/x86_64-mlnx_msn2700-r0/plugins/sfputil.py @@ -33,15 +33,15 @@ SYSTEM_READY = 'system_become_ready' SYSTEM_FAIL = 'system_fail' -GET_HWSKU_CMD = "sonic-cfggen -d -v DEVICE_METADATA.localhost.hwsku" +GET_PLATFORM_CMD = "sonic-cfggen -d -v DEVICE_METADATA.localhost.platform" # Ethernet <=> sfp -SFP_PORT_NAME_OFFSET = 1 +SFP_PORT_NAME_OFFSET = 0 SFP_PORT_NAME_CONVENTION = "sfp{}" -# magic code defnition for port number, qsfp port position of each hwsku +# magic code defnition for port number, qsfp port position of each Platform # port_position_tuple = (PORT_START, QSFP_PORT_START, PORT_END, PORT_IN_BLOCK, EEPROM_OFFSET) -hwsku_dict = {'ACS-MSN2700': 0, 'Mellanox-SN2700': 0, 'Mellanox-SN2700-D48C8': 0, 'LS-SN2700':0, 'ACS-MSN2740': 0, 'ACS-MSN2100': 1, 'ACS-MSN2410': 2, 'ACS-MSN2010': 3, 'ACS-MSN3700': 0, 'ACS-MSN3700C': 0, 'ACS-MSN3800': 4, 'Mellanox-SN3800-D112C8': 4, 'ACS-MSN4700': 0, 'ACS-MSN3420': 5, 'ACS-MSN4600C': 4} +platform_dict = {'x86_64-mlnx_msn2700-r0': 0, 'x86_64-mlnx_msn2740-r0': 0, 'x86_64-mlnx_msn2100-r0': 1, 'x86_64-mlnx_msn2410-r0': 2, 'x86_64-mlnx_msn2010-r0': 3, 'x86_64-mlnx_msn3420-r0':5, 'x86_64-mlnx_msn3700-r0': 0, 'x86_64-mlnx_msn3700c-r0': 0, 'x86_64-mlnx_msn3800-r0': 4, 'x86_64-mlnx_msn4600c':4, 'x86_64-mlnx_msn4700-r0': 0} port_position_tuple_list = [(0, 0, 31, 32, 1), (0, 0, 15, 16, 1), (0, 48, 55, 56, 1), (0, 18, 21, 22, 1), (0, 0, 63, 64, 1), (0, 48, 59, 60, 1)] def log_info(msg, also_print_to_console=False): @@ -86,17 +86,17 @@ def port_to_eeprom_mapping(self): print "dependency on sysfs has been removed" raise Exception() - def get_port_position_tuple_by_sku_name(self): - p = subprocess.Popen(GET_HWSKU_CMD, shell=True, stdout=subprocess.PIPE) + def get_port_position_tuple_by_platform_name(self): + p = subprocess.Popen(GET_PLATFORM_CMD, shell=True, stdout=subprocess.PIPE) out, err = p.communicate() - position_tuple = port_position_tuple_list[hwsku_dict[out.rstrip('\n')]] + position_tuple = port_position_tuple_list[platform_dict[out.rstrip('\n')]] return position_tuple def __init__(self): - port_position_tuple = self.get_port_position_tuple_by_sku_name() - self.PORT_START = port_position_tuple[0] - self.QSFP_PORT_START = port_position_tuple[1] - self.PORT_END = port_position_tuple[2] + port_position_tuple = self.get_port_position_tuple_by_platform_name() + self.PORT_START = port_position_tuple[0] + 1 + self.QSFP_PORT_START = port_position_tuple[1] + 1 + self.PORT_END = port_position_tuple[2] + 1 self.PORTS_IN_BLOCK = port_position_tuple[3] self.EEPROM_OFFSET = port_position_tuple[4] self.mlnx_sfpd_started = False diff --git a/device/mellanox/x86_64-mlnx_msn2700-r0/thermal_policy.json b/device/mellanox/x86_64-mlnx_msn2700-r0/thermal_policy.json new file mode 100644 index 000000000000..1e23d6c8b2bd --- /dev/null +++ b/device/mellanox/x86_64-mlnx_msn2700-r0/thermal_policy.json @@ -0,0 +1,80 @@ +{ + "thermal_control_algorithm": { + "run_at_boot_up": "true", + "fan_speed_when_suspend": "60" + }, + "info_types": [ + { + "type": "fan_info" + }, + { + "type": "psu_info" + }, + { + "type": "chassis_info" + } + ], + "policies": [ + { + "name": "any fan absence", + "conditions": [ + { + "type": "fan.any.absence" + } + ], + "actions": [ + { + "type": "fan.all.set_speed", + "speed": "100" + } + ] + }, + { + "name": "any psu absence", + "conditions": [ + { + "type": "psu.any.absence" + } + ], + "actions": [ + { + "type": "fan.all.set_speed", + "speed": "100" + } + ] + }, + { + "name": "any fan broken", + "conditions": [ + { + "type": "fan.any.fault" + } + ], + "actions": [ + { + "type": "fan.all.set_speed", + "speed": "100" + } + ] + }, + { + "name": "all fan and psu presence", + "conditions": [ + { + "type": "fan.all.presence" + }, + { + "type": "psu.all.presence" + }, + { + "type": "fan.all.good" + } + ], + "actions": [ + { + "type": "thermal.recover" + } + ] + } + ] +} \ No newline at end of file diff --git a/device/mellanox/x86_64-mlnx_msn2700_simx-r0/thermal_policy.json b/device/mellanox/x86_64-mlnx_msn2700_simx-r0/thermal_policy.json new file mode 120000 index 000000000000..5a25cd87f70c --- /dev/null +++ b/device/mellanox/x86_64-mlnx_msn2700_simx-r0/thermal_policy.json @@ -0,0 +1 @@ +../x86_64-mlnx_msn2700-r0/thermal_policy.json \ No newline at end of file diff --git a/device/mellanox/x86_64-mlnx_msn2740-r0/ACS-MSN2740/port_config.ini b/device/mellanox/x86_64-mlnx_msn2740-r0/ACS-MSN2740/port_config.ini index 816bb0e94a70..2ef052c68d52 100644 --- a/device/mellanox/x86_64-mlnx_msn2740-r0/ACS-MSN2740/port_config.ini +++ b/device/mellanox/x86_64-mlnx_msn2740-r0/ACS-MSN2740/port_config.ini @@ -1,33 +1,33 @@ -# name lanes -Ethernet0 0,1,2,3 -Ethernet4 4,5,6,7 -Ethernet8 8,9,10,11 -Ethernet12 12,13,14,15 -Ethernet16 16,17,18,19 -Ethernet20 20,21,22,23 -Ethernet24 24,25,26,27 -Ethernet28 28,29,30,31 -Ethernet32 32,33,34,35 -Ethernet36 36,37,38,39 -Ethernet40 40,41,42,43 -Ethernet44 44,45,46,47 -Ethernet48 48,49,50,51 -Ethernet52 52,53,54,55 -Ethernet56 56,57,58,59 -Ethernet60 60,61,62,63 -Ethernet64 64,65,66,67 -Ethernet68 68,69,70,71 -Ethernet72 72,73,74,75 -Ethernet76 76,77,78,79 -Ethernet80 80,81,82,83 -Ethernet84 84,85,86,87 -Ethernet88 88,89,90,91 -Ethernet92 92,93,94,95 -Ethernet96 96,97,98,99 -Ethernet100 100,101,102,103 -Ethernet104 104,105,106,107 -Ethernet108 108,109,110,111 -Ethernet112 112,113,114,115 -Ethernet116 116,117,118,119 -Ethernet120 120,121,122,123 -Ethernet124 124,125,126,127 +# name lanes index +Ethernet0 0,1,2,3 1 +Ethernet4 4,5,6,7 2 +Ethernet8 8,9,10,11 3 +Ethernet12 12,13,14,15 4 +Ethernet16 16,17,18,19 5 +Ethernet20 20,21,22,23 6 +Ethernet24 24,25,26,27 7 +Ethernet28 28,29,30,31 8 +Ethernet32 32,33,34,35 9 +Ethernet36 36,37,38,39 10 +Ethernet40 40,41,42,43 11 +Ethernet44 44,45,46,47 12 +Ethernet48 48,49,50,51 13 +Ethernet52 52,53,54,55 14 +Ethernet56 56,57,58,59 15 +Ethernet60 60,61,62,63 16 +Ethernet64 64,65,66,67 17 +Ethernet68 68,69,70,71 18 +Ethernet72 72,73,74,75 19 +Ethernet76 76,77,78,79 20 +Ethernet80 80,81,82,83 21 +Ethernet84 84,85,86,87 22 +Ethernet88 88,89,90,91 23 +Ethernet92 92,93,94,95 24 +Ethernet96 96,97,98,99 25 +Ethernet100 100,101,102,103 26 +Ethernet104 104,105,106,107 27 +Ethernet108 108,109,110,111 28 +Ethernet112 112,113,114,115 29 +Ethernet116 116,117,118,119 30 +Ethernet120 120,121,122,123 31 +Ethernet124 124,125,126,127 32 diff --git a/device/mellanox/x86_64-mlnx_msn2740-r0/thermal_policy.json b/device/mellanox/x86_64-mlnx_msn2740-r0/thermal_policy.json new file mode 120000 index 000000000000..5a25cd87f70c --- /dev/null +++ b/device/mellanox/x86_64-mlnx_msn2740-r0/thermal_policy.json @@ -0,0 +1 @@ +../x86_64-mlnx_msn2700-r0/thermal_policy.json \ No newline at end of file diff --git a/device/mellanox/x86_64-mlnx_msn3420-r0/ACS-MSN3420/port_config.ini b/device/mellanox/x86_64-mlnx_msn3420-r0/ACS-MSN3420/port_config.ini index df63cbe39ac3..38441f21f003 100644 --- a/device/mellanox/x86_64-mlnx_msn3420-r0/ACS-MSN3420/port_config.ini +++ b/device/mellanox/x86_64-mlnx_msn3420-r0/ACS-MSN3420/port_config.ini @@ -1,61 +1,61 @@ # name lanes alias index -Ethernet0 0 etp1 0 -Ethernet4 4 etp2 1 -Ethernet8 8 etp3 2 -Ethernet12 12 etp4 3 -Ethernet16 16 etp5 4 -Ethernet20 20 etp6 5 -Ethernet24 24 etp7 6 -Ethernet28 28 etp8 7 -Ethernet32 32 etp9 8 -Ethernet36 36 etp10 9 -Ethernet40 40 etp11 10 -Ethernet44 44 etp12 11 -Ethernet48 48 etp13 12 -Ethernet52 52 etp14 13 -Ethernet56 56 etp15 14 -Ethernet60 60 etp16 15 -Ethernet64 64 etp17 16 -Ethernet68 68 etp18 17 -Ethernet72 72 etp19 18 -Ethernet76 76 etp20 19 -Ethernet80 80 etp21 20 -Ethernet84 84 etp22 21 -Ethernet88 88 etp23 22 -Ethernet92 92 etp24 23 -Ethernet96 96 etp25 24 -Ethernet100 100 etp26 25 -Ethernet104 104 etp27 26 -Ethernet108 108 etp28 27 -Ethernet112 112 etp29 28 -Ethernet116 116 etp30 29 -Ethernet120 120 etp31 30 -Ethernet124 124 etp32 31 -Ethernet128 128 etp33 32 -Ethernet132 132 etp34 33 -Ethernet136 136 etp35 34 -Ethernet140 140 etp36 35 -Ethernet144 144 etp37 36 -Ethernet148 148 etp38 37 -Ethernet152 152 etp39 38 -Ethernet156 156 etp40 39 -Ethernet160 160 etp41 40 -Ethernet164 164 etp42 41 -Ethernet168 168 etp43 42 -Ethernet172 172 etp44 43 -Ethernet176 176 etp45 44 -Ethernet180 180 etp46 45 -Ethernet184 184 etp47 46 -Ethernet188 188 etp48 47 -Ethernet192 192,193,194,195 etp49 48 -Ethernet196 196,197,198,199 etp50 49 -Ethernet200 200,201,202,203 etp51 50 -Ethernet204 204,205,206,207 etp52 51 -Ethernet208 208,209,210,211 etp53 52 -Ethernet212 212,213,214,215 etp54 53 -Ethernet216 216,217,218,219 etp55 54 -Ethernet220 220,221,222,223 etp56 55 -Ethernet224 224,225,226,227 etp57 56 -Ethernet228 228,229,230,231 etp58 57 -Ethernet232 232,233,234,235 etp59 58 -Ethernet236 236,237,238,239 etp60 59 +Ethernet0 0 etp1 1 +Ethernet4 4 etp2 2 +Ethernet8 8 etp3 3 +Ethernet12 12 etp4 4 +Ethernet16 16 etp5 5 +Ethernet20 20 etp6 6 +Ethernet24 24 etp7 7 +Ethernet28 28 etp8 8 +Ethernet32 32 etp9 9 +Ethernet36 36 etp10 10 +Ethernet40 40 etp11 11 +Ethernet44 44 etp12 12 +Ethernet48 48 etp13 13 +Ethernet52 52 etp14 14 +Ethernet56 56 etp15 15 +Ethernet60 60 etp16 16 +Ethernet64 64 etp17 17 +Ethernet68 68 etp18 18 +Ethernet72 72 etp19 19 +Ethernet76 76 etp20 20 +Ethernet80 80 etp21 21 +Ethernet84 84 etp22 22 +Ethernet88 88 etp23 23 +Ethernet92 92 etp24 24 +Ethernet96 96 etp25 25 +Ethernet100 100 etp26 26 +Ethernet104 104 etp27 27 +Ethernet108 108 etp28 28 +Ethernet112 112 etp29 29 +Ethernet116 116 etp30 30 +Ethernet120 120 etp31 31 +Ethernet124 124 etp32 32 +Ethernet128 128 etp33 33 +Ethernet132 132 etp34 34 +Ethernet136 136 etp35 35 +Ethernet140 140 etp36 36 +Ethernet144 144 etp37 37 +Ethernet148 148 etp38 38 +Ethernet152 152 etp39 39 +Ethernet156 156 etp40 40 +Ethernet160 160 etp41 41 +Ethernet164 164 etp42 42 +Ethernet168 168 etp43 43 +Ethernet172 172 etp44 44 +Ethernet176 176 etp45 45 +Ethernet180 180 etp46 46 +Ethernet184 184 etp47 47 +Ethernet188 188 etp48 48 +Ethernet192 192,193,194,195 etp49 49 +Ethernet196 196,197,198,199 etp50 50 +Ethernet200 200,201,202,203 etp51 51 +Ethernet204 204,205,206,207 etp52 52 +Ethernet208 208,209,210,211 etp53 53 +Ethernet212 212,213,214,215 etp54 54 +Ethernet216 216,217,218,219 etp55 55 +Ethernet220 220,221,222,223 etp56 56 +Ethernet224 224,225,226,227 etp57 57 +Ethernet228 228,229,230,231 etp58 58 +Ethernet232 232,233,234,235 etp59 59 +Ethernet236 236,237,238,239 etp60 60 diff --git a/device/mellanox/x86_64-mlnx_msn3420-r0/thermal_policy.json b/device/mellanox/x86_64-mlnx_msn3420-r0/thermal_policy.json new file mode 120000 index 000000000000..5a25cd87f70c --- /dev/null +++ b/device/mellanox/x86_64-mlnx_msn3420-r0/thermal_policy.json @@ -0,0 +1 @@ +../x86_64-mlnx_msn2700-r0/thermal_policy.json \ No newline at end of file diff --git a/device/mellanox/x86_64-mlnx_msn3700-r0/thermal_policy.json b/device/mellanox/x86_64-mlnx_msn3700-r0/thermal_policy.json new file mode 120000 index 000000000000..5a25cd87f70c --- /dev/null +++ b/device/mellanox/x86_64-mlnx_msn3700-r0/thermal_policy.json @@ -0,0 +1 @@ +../x86_64-mlnx_msn2700-r0/thermal_policy.json \ No newline at end of file diff --git a/device/mellanox/x86_64-mlnx_msn3700_simx-r0/thermal_policy.json b/device/mellanox/x86_64-mlnx_msn3700_simx-r0/thermal_policy.json new file mode 120000 index 000000000000..5a25cd87f70c --- /dev/null +++ b/device/mellanox/x86_64-mlnx_msn3700_simx-r0/thermal_policy.json @@ -0,0 +1 @@ +../x86_64-mlnx_msn2700-r0/thermal_policy.json \ No newline at end of file diff --git a/device/mellanox/x86_64-mlnx_msn3700c-r0/thermal_policy.json b/device/mellanox/x86_64-mlnx_msn3700c-r0/thermal_policy.json new file mode 120000 index 000000000000..5a25cd87f70c --- /dev/null +++ b/device/mellanox/x86_64-mlnx_msn3700c-r0/thermal_policy.json @@ -0,0 +1 @@ +../x86_64-mlnx_msn2700-r0/thermal_policy.json \ No newline at end of file diff --git a/device/mellanox/x86_64-mlnx_msn3800-r0/ACS-MSN3800/port_config.ini b/device/mellanox/x86_64-mlnx_msn3800-r0/ACS-MSN3800/port_config.ini index db5216ccf24f..d43b11a22eb6 100644 --- a/device/mellanox/x86_64-mlnx_msn3800-r0/ACS-MSN3800/port_config.ini +++ b/device/mellanox/x86_64-mlnx_msn3800-r0/ACS-MSN3800/port_config.ini @@ -1,65 +1,65 @@ -# name lanes alias -Ethernet0 0,1,2,3 etp1 -Ethernet4 4,5,6,7 etp2 -Ethernet8 8,9,10,11 etp3 -Ethernet12 12,13,14,15 etp4 -Ethernet16 16,17,18,19 etp5 -Ethernet20 20,21,22,23 etp6 -Ethernet24 24,25,26,27 etp7 -Ethernet28 28,29,30,31 etp8 -Ethernet32 32,33,34,35 etp9 -Ethernet36 36,37,38,39 etp10 -Ethernet40 40,41,42,43 etp11 -Ethernet44 44,45,46,47 etp12 -Ethernet48 48,49,50,51 etp13 -Ethernet52 52,53,54,55 etp14 -Ethernet56 56,57,58,59 etp15 -Ethernet60 60,61,62,63 etp16 -Ethernet64 64,65,66,67 etp17 -Ethernet68 68,69,70,71 etp18 -Ethernet72 72,73,74,75 etp19 -Ethernet76 76,77,78,79 etp20 -Ethernet80 80,81,82,83 etp21 -Ethernet84 84,85,86,87 etp22 -Ethernet88 88,89,90,91 etp23 -Ethernet92 92,93,94,95 etp24 -Ethernet96 96,97,98,99 etp25 -Ethernet100 100,101,102,103 etp26 -Ethernet104 104,105,106,107 etp27 -Ethernet108 108,109,110,111 etp28 -Ethernet112 112,113,114,115 etp29 -Ethernet116 116,117,118,119 etp30 -Ethernet120 120,121,122,123 etp31 -Ethernet124 124,125,126,127 etp32 -Ethernet128 128,129,130,131 etp33 -Ethernet132 132,133,134,135 etp34 -Ethernet136 136,137,138,139 etp35 -Ethernet140 140,141,142,143 etp36 -Ethernet144 144,145,146,147 etp37 -Ethernet148 148,149,150,151 etp38 -Ethernet152 152,153,154,155 etp39 -Ethernet156 156,157,158,159 etp40 -Ethernet160 160,161,162,163 etp41 -Ethernet164 164,165,166,167 etp42 -Ethernet168 168,169,170,171 etp43 -Ethernet172 172,173,174,175 etp44 -Ethernet176 176,177,178,179 etp45 -Ethernet180 180,181,182,183 etp46 -Ethernet184 184,185,186,187 etp47 -Ethernet188 188,189,190,191 etp48 -Ethernet192 192,193,194,195 etp49 -Ethernet196 196,197,198,199 etp50 -Ethernet200 200,201,202,203 etp51 -Ethernet204 204,205,206,207 etp52 -Ethernet208 208,209,210,211 etp53 -Ethernet212 212,213,214,215 etp54 -Ethernet216 216,217,218,219 etp55 -Ethernet220 220,221,222,223 etp56 -Ethernet224 224,225,226,227 etp57 -Ethernet228 228,229,230,231 etp58 -Ethernet232 232,233,234,235 etp59 -Ethernet236 236,237,238,239 etp60 -Ethernet240 240,241,242,243 etp61 -Ethernet244 244,245,246,247 etp62 -Ethernet248 248,249,250,251 etp63 -Ethernet252 252,253,254,255 etp64 +# name lanes alias index +Ethernet0 0,1,2,3 etp1 1 +Ethernet4 4,5,6,7 etp2 2 +Ethernet8 8,9,10,11 etp3 3 +Ethernet12 12,13,14,15 etp4 4 +Ethernet16 16,17,18,19 etp5 5 +Ethernet20 20,21,22,23 etp6 6 +Ethernet24 24,25,26,27 etp7 7 +Ethernet28 28,29,30,31 etp8 8 +Ethernet32 32,33,34,35 etp9 9 +Ethernet36 36,37,38,39 etp10 10 +Ethernet40 40,41,42,43 etp11 11 +Ethernet44 44,45,46,47 etp12 12 +Ethernet48 48,49,50,51 etp13 13 +Ethernet52 52,53,54,55 etp14 14 +Ethernet56 56,57,58,59 etp15 15 +Ethernet60 60,61,62,63 etp16 16 +Ethernet64 64,65,66,67 etp17 17 +Ethernet68 68,69,70,71 etp18 18 +Ethernet72 72,73,74,75 etp19 19 +Ethernet76 76,77,78,79 etp20 20 +Ethernet80 80,81,82,83 etp21 21 +Ethernet84 84,85,86,87 etp22 22 +Ethernet88 88,89,90,91 etp23 23 +Ethernet92 92,93,94,95 etp24 24 +Ethernet96 96,97,98,99 etp25 25 +Ethernet100 100,101,102,103 etp26 26 +Ethernet104 104,105,106,107 etp27 27 +Ethernet108 108,109,110,111 etp28 28 +Ethernet112 112,113,114,115 etp29 29 +Ethernet116 116,117,118,119 etp30 30 +Ethernet120 120,121,122,123 etp31 31 +Ethernet124 124,125,126,127 etp32 32 +Ethernet128 128,129,130,131 etp33 33 +Ethernet132 132,133,134,135 etp34 34 +Ethernet136 136,137,138,139 etp35 35 +Ethernet140 140,141,142,143 etp36 36 +Ethernet144 144,145,146,147 etp37 37 +Ethernet148 148,149,150,151 etp38 38 +Ethernet152 152,153,154,155 etp39 39 +Ethernet156 156,157,158,159 etp40 40 +Ethernet160 160,161,162,163 etp41 41 +Ethernet164 164,165,166,167 etp42 42 +Ethernet168 168,169,170,171 etp43 43 +Ethernet172 172,173,174,175 etp44 44 +Ethernet176 176,177,178,179 etp45 45 +Ethernet180 180,181,182,183 etp46 46 +Ethernet184 184,185,186,187 etp47 47 +Ethernet188 188,189,190,191 etp48 48 +Ethernet192 192,193,194,195 etp49 49 +Ethernet196 196,197,198,199 etp50 50 +Ethernet200 200,201,202,203 etp51 51 +Ethernet204 204,205,206,207 etp52 52 +Ethernet208 208,209,210,211 etp53 53 +Ethernet212 212,213,214,215 etp54 54 +Ethernet216 216,217,218,219 etp55 55 +Ethernet220 220,221,222,223 etp56 56 +Ethernet224 224,225,226,227 etp57 57 +Ethernet228 228,229,230,231 etp58 58 +Ethernet232 232,233,234,235 etp59 59 +Ethernet236 236,237,238,239 etp60 60 +Ethernet240 240,241,242,243 etp61 61 +Ethernet244 244,245,246,247 etp62 62 +Ethernet248 248,249,250,251 etp63 63 +Ethernet252 252,253,254,255 etp64 64 diff --git a/device/mellanox/x86_64-mlnx_msn3800-r0/Mellanox-SN3800-C64 b/device/mellanox/x86_64-mlnx_msn3800-r0/Mellanox-SN3800-C64 new file mode 120000 index 000000000000..65b8f3c8ec9d --- /dev/null +++ b/device/mellanox/x86_64-mlnx_msn3800-r0/Mellanox-SN3800-C64 @@ -0,0 +1 @@ +ACS-MSN3800/ \ No newline at end of file diff --git a/device/mellanox/x86_64-mlnx_msn3800-r0/Mellanox-SN3800-D112C8/port_config.ini b/device/mellanox/x86_64-mlnx_msn3800-r0/Mellanox-SN3800-D112C8/port_config.ini index 9559119c7e38..8e40d6bd41ec 100644 --- a/device/mellanox/x86_64-mlnx_msn3800-r0/Mellanox-SN3800-D112C8/port_config.ini +++ b/device/mellanox/x86_64-mlnx_msn3800-r0/Mellanox-SN3800-D112C8/port_config.ini @@ -1,105 +1,121 @@ -# name lanes alias index speed fec -Ethernet0 0,1 etp1a 0 50000 none -Ethernet2 2,3 etp1b 0 50000 none -Ethernet4 4,5 etp2a 1 50000 none -Ethernet6 6,7 etp2b 1 50000 none -Ethernet8 8,9 etp3a 2 50000 none -Ethernet10 10,11 etp3b 2 50000 none -Ethernet12 12,13,14,15 etp4 3 50000 none -Ethernet16 16,17 etp5a 4 50000 none -Ethernet18 18,19 etp5b 4 50000 none -Ethernet20 20,21 etp6a 5 50000 none -Ethernet22 22,23 etp6b 5 50000 none -Ethernet24 24,25 etp7a 6 50000 none -Ethernet26 26,27 etp7b 6 50000 none -Ethernet28 28,29,30,31 etp8 7 50000 none -Ethernet32 32,33 etp9a 8 50000 none -Ethernet34 34,35 etp9b 8 50000 none -Ethernet36 36,37 etp10a 9 50000 none -Ethernet38 38,39 etp10b 9 50000 none -Ethernet40 40,41 etp11a 10 50000 none -Ethernet42 42,43 etp11b 10 50000 none -Ethernet44 44,45,46,47 etp12 11 50000 none -Ethernet48 48,49 etp13a 12 50000 none -Ethernet50 50,51 etp13b 12 50000 none -Ethernet52 52,53 etp14a 13 50000 none -Ethernet54 54,55 etp14b 13 50000 none -Ethernet56 56,57 etp15a 14 50000 none -Ethernet58 58,59 etp15b 14 50000 none -Ethernet60 60,61,62,63 etp16 15 50000 none -Ethernet64 64,65 etp17a 16 50000 none -Ethernet66 66,67 etp17b 16 50000 none -Ethernet68 68,69 etp18a 17 50000 none -Ethernet70 70,71 etp18b 17 50000 none -Ethernet72 72,73 etp19a 18 50000 none -Ethernet74 74,75 etp19b 18 50000 none -Ethernet76 76,77,78,79 etp20 19 50000 none -Ethernet80 80,81 etp21a 20 50000 none -Ethernet82 82,83 etp21b 20 50000 none -Ethernet84 84,85 etp22a 21 50000 none -Ethernet86 86,87 etp22b 21 50000 none -Ethernet88 88,89 etp23a 22 50000 none -Ethernet90 90,91 etp23b 22 50000 none -Ethernet92 92,93,94,95 etp24 23 50000 none -Ethernet96 96,97,98,99 etp25 24 100000 rs -Ethernet100 100,101,102,103 etp26 25 100000 rs -Ethernet104 104,105 etp27a 26 50000 none -Ethernet106 106,107 etp27b 26 50000 none -Ethernet108 108,109,110,111 etp28 27 50000 none -Ethernet112 112,113,114,115 etp29 28 100000 rs -Ethernet116 116,117,118,119 etp30 29 100000 rs -Ethernet120 120,121 etp31a 30 50000 none -Ethernet122 122,123 etp31b 30 50000 none -Ethernet124 124,125,126,127 etp32 31 50000 none -Ethernet128 128,129,130,131 etp33 32 100000 rs -Ethernet132 132,133,134,135 etp34 33 100000 rs -Ethernet136 136,137 etp35a 34 50000 none -Ethernet138 138,139 etp35b 34 50000 none -Ethernet140 140,141,142,143 etp36 35 50000 none -Ethernet144 144,145,146,147 etp37 36 100000 rs -Ethernet148 148,149,150,151 etp38 37 100000 rs -Ethernet152 152,153 etp39a 38 50000 none -Ethernet154 154,155 etp39b 38 50000 none -Ethernet156 156,157,158,159 etp40 39 50000 none -Ethernet160 160,161 etp41a 40 50000 none -Ethernet162 162,163 etp41b 40 50000 none -Ethernet164 164,165 etp42a 41 50000 none -Ethernet166 166,167 etp42b 41 50000 none -Ethernet168 168,169 etp43a 42 50000 none -Ethernet170 170,171 etp43b 42 50000 none -Ethernet172 172,173,174,175 etp44 43 50000 none -Ethernet176 176,177 etp45a 44 50000 none -Ethernet178 178,179 etp45b 44 50000 none -Ethernet180 180,181 etp46a 45 50000 none -Ethernet182 182,183 etp46b 45 50000 none -Ethernet184 184,185 etp47a 46 50000 none -Ethernet186 186,187 etp47b 46 50000 none -Ethernet188 188,189,190,191 etp48 47 50000 none -Ethernet192 192,193 etp49a 48 50000 none -Ethernet194 194,195 etp49b 48 50000 none -Ethernet196 196,197 etp50a 49 50000 none -Ethernet198 198,199 etp50b 49 50000 none -Ethernet200 200,201 etp51a 50 50000 none -Ethernet202 202,203 etp51b 50 50000 none -Ethernet204 204,205,206,207 etp52 51 50000 none -Ethernet208 208,209 etp53a 52 50000 none -Ethernet210 210,211 etp53b 52 50000 none -Ethernet212 212,213 etp54a 53 50000 none -Ethernet214 214,215 etp54b 53 50000 none -Ethernet216 216,217 etp55a 54 50000 none -Ethernet218 218,219 etp55b 54 50000 none -Ethernet220 220,221,222,223 etp56 55 50000 none -Ethernet224 224,225 etp57a 56 50000 none -Ethernet226 226,227 etp57b 56 50000 none -Ethernet228 228,229 etp58a 57 50000 none -Ethernet230 230,231 etp58b 57 50000 none -Ethernet232 232,233 etp59a 58 50000 none -Ethernet234 234,235 etp59b 58 50000 none -Ethernet236 236,237,238,239 etp60 59 50000 none -Ethernet240 240,241 etp61a 60 50000 none -Ethernet242 242,243 etp61b 60 50000 none -Ethernet244 244,245 etp62a 61 50000 none -Ethernet246 246,247 etp62b 61 50000 none -Ethernet248 248,249 etp63a 62 50000 none -Ethernet250 250,251 etp63b 62 50000 none -Ethernet252 252,253,254,255 etp64 63 50000 none +# name lanes alias index speed +Ethernet0 0,1 etp1a 1 50000 +Ethernet2 2,3 etp1b 1 50000 +Ethernet4 4,5 etp2a 2 50000 +Ethernet6 6,7 etp2b 2 50000 +Ethernet8 8,9 etp3a 3 50000 +Ethernet10 10,11 etp3b 3 50000 +Ethernet12 12,13 etp4a 4 50000 +Ethernet14 14,15 etp4b 4 50000 +Ethernet16 16,17 etp5a 5 50000 +Ethernet18 18,19 etp5b 5 50000 +Ethernet20 20,21 etp6a 6 50000 +Ethernet22 22,23 etp6b 6 50000 +Ethernet24 24,25 etp7a 7 50000 +Ethernet26 26,27 etp7b 7 50000 +Ethernet28 28,29 etp8a 8 50000 +Ethernet30 30,31 etp8b 8 50000 +Ethernet32 32,33 etp9a 9 50000 +Ethernet34 34,35 etp9b 9 50000 +Ethernet36 36,37 etp10a 10 50000 +Ethernet38 38,39 etp10b 10 50000 +Ethernet40 40,41 etp11a 11 50000 +Ethernet42 42,43 etp11b 11 50000 +Ethernet44 44,45 etp12a 12 50000 +Ethernet46 46,47 etp12b 12 50000 +Ethernet48 48,49 etp13a 13 50000 +Ethernet50 50,51 etp13b 13 50000 +Ethernet52 52,53 etp14a 14 50000 +Ethernet54 54,55 etp14b 14 50000 +Ethernet56 56,57 etp15a 15 50000 +Ethernet58 58,59 etp15b 15 50000 +Ethernet60 60,61 etp16a 16 50000 +Ethernet62 62,63 etp16b 16 50000 +Ethernet64 64,65 etp17a 17 50000 +Ethernet66 66,67 etp17b 17 50000 +Ethernet68 68,69 etp18a 18 50000 +Ethernet70 70,71 etp18b 18 50000 +Ethernet72 72,73 etp19a 19 50000 +Ethernet74 74,75 etp19b 19 50000 +Ethernet76 76,77 etp20a 20 50000 +Ethernet78 78,79 etp20b 20 50000 +Ethernet80 80,81 etp21a 21 50000 +Ethernet82 82,83 etp21b 21 50000 +Ethernet84 84,85 etp22a 22 50000 +Ethernet86 86,87 etp22b 22 50000 +Ethernet88 88,89 etp23a 23 50000 +Ethernet90 90,91 etp23b 23 50000 +Ethernet92 92,93 etp24a 24 50000 +Ethernet94 94,95 etp24b 24 50000 +Ethernet96 96,97,98,99 etp25 25 100000 +Ethernet100 100,101,102,103 etp26 26 100000 +Ethernet104 104,105 etp27a 27 50000 +Ethernet106 106,107 etp27b 27 50000 +Ethernet108 108,109 etp28a 28 50000 +Ethernet110 110,111 etp28b 28 50000 +Ethernet112 112,113,114,115 etp29 29 100000 +Ethernet116 116,117,118,119 etp30 30 100000 +Ethernet120 120,121 etp31a 31 50000 +Ethernet122 122,123 etp31b 31 50000 +Ethernet124 124,125 etp32a 32 50000 +Ethernet126 126,127 etp32b 32 50000 +Ethernet128 128,129,130,131 etp33 33 100000 +Ethernet132 132,133,134,135 etp34 34 100000 +Ethernet136 136,137 etp35a 35 50000 +Ethernet138 138,139 etp35b 35 50000 +Ethernet140 140,141 etp36a 36 50000 +Ethernet142 142,143 etp36b 36 50000 +Ethernet144 144,145,146,147 etp37 37 100000 +Ethernet148 148,149,150,151 etp38 38 100000 +Ethernet152 152,153 etp39a 39 50000 +Ethernet154 154,155 etp39b 39 50000 +Ethernet156 156,157 etp40a 40 50000 +Ethernet158 158,159 etp40b 40 50000 +Ethernet160 160,161 etp41a 41 50000 +Ethernet162 162,163 etp41b 41 50000 +Ethernet164 164,165 etp42a 42 50000 +Ethernet166 166,167 etp42b 42 50000 +Ethernet168 168,169 etp43a 43 50000 +Ethernet170 170,171 etp43b 43 50000 +Ethernet172 172,173 etp44a 44 50000 +Ethernet174 174,175 etp44b 44 50000 +Ethernet176 176,177 etp45a 45 50000 +Ethernet178 178,179 etp45b 45 50000 +Ethernet180 180,181 etp46a 46 50000 +Ethernet182 182,183 etp46b 46 50000 +Ethernet184 184,185 etp47a 47 50000 +Ethernet186 186,187 etp47b 47 50000 +Ethernet188 188,189 etp48a 48 50000 +Ethernet190 190,191 etp48b 48 50000 +Ethernet192 192,193 etp49a 49 50000 +Ethernet194 194,195 etp49b 49 50000 +Ethernet196 196,197 etp50a 50 50000 +Ethernet198 198,199 etp50b 50 50000 +Ethernet200 200,201 etp51a 51 50000 +Ethernet202 202,203 etp51b 51 50000 +Ethernet204 204,205 etp52a 52 50000 +Ethernet206 206,207 etp52b 52 50000 +Ethernet208 208,209 etp53a 53 50000 +Ethernet210 210,211 etp53b 53 50000 +Ethernet212 212,213 etp54a 54 50000 +Ethernet214 214,215 etp54b 54 50000 +Ethernet216 216,217 etp55a 55 50000 +Ethernet218 218,219 etp55b 55 50000 +Ethernet220 220,221 etp56a 56 50000 +Ethernet222 222,223 etp56b 56 50000 +Ethernet224 224,225 etp57a 57 50000 +Ethernet226 226,227 etp57b 57 50000 +Ethernet228 228,229 etp58a 58 50000 +Ethernet230 230,231 etp58b 58 50000 +Ethernet232 232,233 etp59a 59 50000 +Ethernet234 234,235 etp59b 59 50000 +Ethernet236 236,237 etp60a 60 50000 +Ethernet238 238,239 etp60b 60 50000 +Ethernet240 240,241 etp61a 61 50000 +Ethernet242 242,243 etp61b 61 50000 +Ethernet244 244,245 etp62a 62 50000 +Ethernet246 246,247 etp62b 62 50000 +Ethernet248 248,249 etp63a 63 50000 +Ethernet250 250,251 etp63b 63 50000 +Ethernet252 252,253 etp64a 64 50000 +Ethernet254 254,255 etp64b 64 50000 diff --git a/device/mellanox/x86_64-mlnx_msn3800-r0/Mellanox-SN3800-D24C52/buffers.json.j2 b/device/mellanox/x86_64-mlnx_msn3800-r0/Mellanox-SN3800-D24C52/buffers.json.j2 new file mode 120000 index 000000000000..dc17caa0aa32 --- /dev/null +++ b/device/mellanox/x86_64-mlnx_msn3800-r0/Mellanox-SN3800-D24C52/buffers.json.j2 @@ -0,0 +1 @@ +../ACS-MSN3800/buffers.json.j2 \ No newline at end of file diff --git a/device/mellanox/x86_64-mlnx_msn3800-r0/Mellanox-SN3800-D24C52/buffers_defaults_t0.j2 b/device/mellanox/x86_64-mlnx_msn3800-r0/Mellanox-SN3800-D24C52/buffers_defaults_t0.j2 new file mode 120000 index 000000000000..0987f6724863 --- /dev/null +++ b/device/mellanox/x86_64-mlnx_msn3800-r0/Mellanox-SN3800-D24C52/buffers_defaults_t0.j2 @@ -0,0 +1 @@ +../ACS-MSN3800/buffers_defaults_t0.j2 \ No newline at end of file diff --git a/device/mellanox/x86_64-mlnx_msn3800-r0/Mellanox-SN3800-D24C52/buffers_defaults_t1.j2 b/device/mellanox/x86_64-mlnx_msn3800-r0/Mellanox-SN3800-D24C52/buffers_defaults_t1.j2 new file mode 120000 index 000000000000..119460bfa556 --- /dev/null +++ b/device/mellanox/x86_64-mlnx_msn3800-r0/Mellanox-SN3800-D24C52/buffers_defaults_t1.j2 @@ -0,0 +1 @@ +../ACS-MSN3800/buffers_defaults_t1.j2 \ No newline at end of file diff --git a/device/mellanox/x86_64-mlnx_msn3800-r0/Mellanox-SN3800-D24C52/pg_profile_lookup.ini b/device/mellanox/x86_64-mlnx_msn3800-r0/Mellanox-SN3800-D24C52/pg_profile_lookup.ini new file mode 120000 index 000000000000..db2f74508aad --- /dev/null +++ b/device/mellanox/x86_64-mlnx_msn3800-r0/Mellanox-SN3800-D24C52/pg_profile_lookup.ini @@ -0,0 +1 @@ +../ACS-MSN3800/pg_profile_lookup.ini \ No newline at end of file diff --git a/device/mellanox/x86_64-mlnx_msn3800-r0/Mellanox-SN3800-D24C52/port_config.ini b/device/mellanox/x86_64-mlnx_msn3800-r0/Mellanox-SN3800-D24C52/port_config.ini new file mode 100644 index 000000000000..87d4485963f7 --- /dev/null +++ b/device/mellanox/x86_64-mlnx_msn3800-r0/Mellanox-SN3800-D24C52/port_config.ini @@ -0,0 +1,77 @@ +# name lanes alias index speed +Ethernet0 0,1,2,3 etp1 1 100000 +Ethernet4 4,5,6,7 etp2 2 100000 +Ethernet8 8,9,10,11 etp3 3 100000 +Ethernet12 12,13,14,15 etp4 4 100000 +Ethernet16 16,17,18,19 etp5 5 100000 +Ethernet20 20,21,22,23 etp6 6 100000 +Ethernet24 24,25,26,27 etp7 7 100000 +Ethernet28 28,29,30,31 etp8 8 100000 +Ethernet32 32,33 etp9a 9 50000 +Ethernet34 34,35 etp9b 9 50000 +Ethernet36 36,37 etp10a 10 50000 +Ethernet38 38,39 etp10b 10 50000 +Ethernet40 40,41 etp11a 11 50000 +Ethernet42 42,43 etp11b 11 50000 +Ethernet44 44,45 etp12a 12 50000 +Ethernet46 46,47 etp12b 12 50000 +Ethernet48 48,49,50,51 etp13 13 100000 +Ethernet52 52,53,54,55 etp14 14 100000 +Ethernet56 56,57,58,59 etp15 15 100000 +Ethernet60 60,61,62,63 etp16 16 100000 +Ethernet64 64,65,66,67 etp17 17 100000 +Ethernet68 68,69,70,71 etp18 18 100000 +Ethernet72 72,73,74,75 etp19 19 100000 +Ethernet76 76,77,78,79 etp20 20 100000 +Ethernet80 80,81,82,83 etp21 21 100000 +Ethernet84 84,85,86,87 etp22 22 100000 +Ethernet88 88,89,90,91 etp23 23 100000 +Ethernet92 92,93,94,95 etp24 24 100000 +Ethernet96 96,97,98,99 etp25 25 100000 +Ethernet100 100,101,102,103 etp26 26 100000 +Ethernet104 104,105 etp27a 27 50000 +Ethernet106 106,107 etp27b 27 50000 +Ethernet108 108,109 etp28a 28 50000 +Ethernet110 110,111 etp28b 28 50000 +Ethernet112 112,113,114,115 etp29 29 100000 +Ethernet116 116,117,118,119 etp30 30 100000 +Ethernet120 120,121,122,123 etp31 31 100000 +Ethernet124 124,125,126,127 etp32 32 100000 +Ethernet128 128,129,130,131 etp33 33 100000 +Ethernet132 132,133,134,135 etp34 34 100000 +Ethernet136 136,137,138,139 etp35 35 100000 +Ethernet140 140,141,142,143 etp36 36 100000 +Ethernet144 144,145,146,147 etp37 37 100000 +Ethernet148 148,149,150,151 etp38 38 100000 +Ethernet152 152,153,154,155 etp39 39 100000 +Ethernet156 156,157,158,159 etp40 40 100000 +Ethernet160 160,161,162,163 etp41 41 100000 +Ethernet164 164,165,166,167 etp42 42 100000 +Ethernet168 168,169,170,171 etp43 43 100000 +Ethernet172 172,173,174,175 etp44 44 100000 +Ethernet176 176,177 etp45a 45 50000 +Ethernet178 178,179 etp45b 45 50000 +Ethernet180 180,181 etp46a 46 50000 +Ethernet182 182,183 etp46b 46 50000 +Ethernet184 184,185 etp47a 47 50000 +Ethernet186 186,187 etp47b 47 50000 +Ethernet188 188,189 etp48a 48 50000 +Ethernet190 190,191 etp48b 48 50000 +Ethernet192 192,193,194,195 etp49 49 100000 +Ethernet196 196,197,198,199 etp50 50 100000 +Ethernet200 200,201,202,203 etp51 51 100000 +Ethernet204 204,205,206,207 etp52 52 100000 +Ethernet208 208,209,210,211 etp53 53 100000 +Ethernet212 212,213,214,215 etp54 54 100000 +Ethernet216 216,217,218,219 etp55 55 100000 +Ethernet220 220,221,222,223 etp56 56 100000 +Ethernet224 224,225,226,227 etp57 57 100000 +Ethernet228 228,229,230,231 etp58 58 100000 +Ethernet232 232,233,234,235 etp59 59 100000 +Ethernet236 236,237,238,239 etp60 60 100000 +Ethernet240 240,241 etp61a 61 50000 +Ethernet242 242,243 etp61b 61 50000 +Ethernet244 244,245 etp62a 62 50000 +Ethernet246 246,247 etp62b 62 50000 +Ethernet248 248,249,250,251 etp63 63 100000 +Ethernet252 252,253,254,255 etp64 64 100000 \ No newline at end of file diff --git a/device/mellanox/x86_64-mlnx_msn3800-r0/Mellanox-SN3800-D24C52/qos.json.j2 b/device/mellanox/x86_64-mlnx_msn3800-r0/Mellanox-SN3800-D24C52/qos.json.j2 new file mode 120000 index 000000000000..26b0dac51846 --- /dev/null +++ b/device/mellanox/x86_64-mlnx_msn3800-r0/Mellanox-SN3800-D24C52/qos.json.j2 @@ -0,0 +1 @@ +../ACS-MSN3800/qos.json.j2 \ No newline at end of file diff --git a/device/mellanox/x86_64-mlnx_msn3800-r0/Mellanox-SN3800-D24C52/sai.profile b/device/mellanox/x86_64-mlnx_msn3800-r0/Mellanox-SN3800-D24C52/sai.profile new file mode 100644 index 000000000000..7c632389b58c --- /dev/null +++ b/device/mellanox/x86_64-mlnx_msn3800-r0/Mellanox-SN3800-D24C52/sai.profile @@ -0,0 +1 @@ +SAI_INIT_CONFIG_FILE=/usr/share/sonic/hwsku/sai_3800_24x50g_52x100g.xml diff --git a/device/mellanox/x86_64-mlnx_msn3800-r0/Mellanox-SN3800-D24C52/sai_3800_24x50g_52x100g.xml b/device/mellanox/x86_64-mlnx_msn3800-r0/Mellanox-SN3800-D24C52/sai_3800_24x50g_52x100g.xml new file mode 100644 index 000000000000..1b3c77ce381c --- /dev/null +++ b/device/mellanox/x86_64-mlnx_msn3800-r0/Mellanox-SN3800-D24C52/sai_3800_24x50g_52x100g.xml @@ -0,0 +1,470 @@ + + + + + + 00:02:03:04:05:00 + + + 1 + + + 64 + + + + + 1 + 4 + 48 + + + 3 + + + 1536 + + + 3 + 4 + 49 + 3 + 1536 + + + 5 + 4 + 50 + 3 + 1536 + + + 7 + 4 + 51 + 3 + 1536 + + + 9 + 4 + 52 + 3 + 1536 + + + 11 + 4 + 53 + 3 + 1536 + + + 13 + 4 + 54 + 3 + 1536 + + + 15 + 4 + 55 + 3 + 1536 + + + 17 + 4 + 56 + 3 + 1536 + + + 19 + 4 + 57 + 3 + 1536 + + + 21 + 4 + 58 + 3 + 1536 + + + 23 + 4 + 59 + 3 + 1536 + + + 25 + 4 + 60 + 3 + 1536 + + + 27 + 4 + 61 + 3 + 1536 + + + 29 + 4 + 62 + 3 + 1536 + + + 31 + 4 + 63 + 3 + 1536 + + + 33 + 4 + 12 + 3 + 1536 + + + 35 + 4 + 13 + 3 + 1536 + + + 37 + 4 + 14 + 3 + 1536 + + + 39 + 4 + 15 + 3 + 1536 + + + 41 + 4 + 8 + 3 + 1536 + + + 43 + 4 + 9 + 3 + 1536 + + + 45 + 4 + 10 + 3 + 1536 + + + 47 + 4 + 11 + 3 + 1536 + + + 49 + 4 + 4 + 3 + 1536 + + + 51 + 4 + 5 + 3 + 1536 + + + 53 + 4 + 6 + 3 + 1536 + + + 55 + 4 + 7 + 3 + 1536 + + + 57 + 4 + 0 + 3 + 1536 + + + 59 + 4 + 1 + 3 + 1536 + + + 61 + 4 + 2 + 3 + 1536 + + + 63 + 4 + 3 + 3 + 1536 + + + 65 + 4 + 44 + 3 + 1536 + + + 67 + 4 + 45 + 3 + 1536 + + + 69 + 4 + 46 + 3 + 1536 + + + 71 + 4 + 47 + 3 + 1536 + + + 73 + 4 + 40 + 3 + 1536 + + + 75 + 4 + 41 + 3 + 1536 + + + 77 + 4 + 42 + 3 + 1536 + + + 79 + 4 + 43 + 3 + 1536 + + + 81 + 4 + 36 + 3 + 1536 + + + 83 + 4 + 37 + 3 + 1536 + + + 85 + 4 + 38 + 3 + 1536 + + + 87 + 4 + 39 + 3 + 1536 + + + 89 + 4 + 32 + 3 + 1536 + + + 91 + 4 + 33 + 3 + 1536 + + + 93 + 4 + 34 + 3 + 1536 + + + 95 + 4 + 35 + 3 + 1536 + + + 97 + 4 + 16 + 3 + 1536 + + + 99 + 4 + 17 + 3 + 1536 + + + 101 + 4 + 18 + 3 + 1536 + + + 103 + 4 + 19 + 3 + 1536 + + + 105 + 4 + 20 + 3 + 1536 + + + 107 + 4 + 21 + 3 + 1536 + + + 109 + 4 + 22 + 3 + 1536 + + + 111 + 4 + 23 + 3 + 1536 + + + 113 + 4 + 24 + 3 + 1536 + + + 115 + 4 + 25 + 3 + 1536 + + + 117 + 4 + 26 + 3 + 1536 + + + 119 + 4 + 27 + 3 + 1536 + + + 121 + 4 + 28 + 3 + 1536 + + + 123 + 4 + 29 + 3 + 1536 + + + 125 + 4 + 30 + 3 + 1536 + + + 127 + 4 + 31 + 3 + 1536 + + + + diff --git a/device/mellanox/x86_64-mlnx_msn3800-r0/Mellanox-SN3800-D28C50/buffers.json.j2 b/device/mellanox/x86_64-mlnx_msn3800-r0/Mellanox-SN3800-D28C50/buffers.json.j2 new file mode 120000 index 000000000000..dc17caa0aa32 --- /dev/null +++ b/device/mellanox/x86_64-mlnx_msn3800-r0/Mellanox-SN3800-D28C50/buffers.json.j2 @@ -0,0 +1 @@ +../ACS-MSN3800/buffers.json.j2 \ No newline at end of file diff --git a/device/mellanox/x86_64-mlnx_msn3800-r0/Mellanox-SN3800-D28C50/buffers_defaults_t0.j2 b/device/mellanox/x86_64-mlnx_msn3800-r0/Mellanox-SN3800-D28C50/buffers_defaults_t0.j2 new file mode 120000 index 000000000000..0987f6724863 --- /dev/null +++ b/device/mellanox/x86_64-mlnx_msn3800-r0/Mellanox-SN3800-D28C50/buffers_defaults_t0.j2 @@ -0,0 +1 @@ +../ACS-MSN3800/buffers_defaults_t0.j2 \ No newline at end of file diff --git a/device/mellanox/x86_64-mlnx_msn3800-r0/Mellanox-SN3800-D28C50/buffers_defaults_t1.j2 b/device/mellanox/x86_64-mlnx_msn3800-r0/Mellanox-SN3800-D28C50/buffers_defaults_t1.j2 new file mode 120000 index 000000000000..119460bfa556 --- /dev/null +++ b/device/mellanox/x86_64-mlnx_msn3800-r0/Mellanox-SN3800-D28C50/buffers_defaults_t1.j2 @@ -0,0 +1 @@ +../ACS-MSN3800/buffers_defaults_t1.j2 \ No newline at end of file diff --git a/device/mellanox/x86_64-mlnx_msn3800-r0/Mellanox-SN3800-D28C50/pg_profile_lookup.ini b/device/mellanox/x86_64-mlnx_msn3800-r0/Mellanox-SN3800-D28C50/pg_profile_lookup.ini new file mode 120000 index 000000000000..db2f74508aad --- /dev/null +++ b/device/mellanox/x86_64-mlnx_msn3800-r0/Mellanox-SN3800-D28C50/pg_profile_lookup.ini @@ -0,0 +1 @@ +../ACS-MSN3800/pg_profile_lookup.ini \ No newline at end of file diff --git a/device/mellanox/x86_64-mlnx_msn3800-r0/Mellanox-SN3800-D28C50/port_config.ini b/device/mellanox/x86_64-mlnx_msn3800-r0/Mellanox-SN3800-D28C50/port_config.ini new file mode 100644 index 000000000000..4c169a5fb48f --- /dev/null +++ b/device/mellanox/x86_64-mlnx_msn3800-r0/Mellanox-SN3800-D28C50/port_config.ini @@ -0,0 +1,79 @@ +# name lanes alias index speed +Ethernet0 0,1,2,3 etp1 1 100000 +Ethernet4 4,5,6,7 etp2 2 100000 +Ethernet8 8,9,10,11 etp3 3 100000 +Ethernet12 12,13,14,15 etp4 4 100000 +Ethernet16 16,17,18,19 etp5 5 100000 +Ethernet20 20,21,22,23 etp6 6 100000 +Ethernet24 24,25,26,27 etp7 7 100000 +Ethernet28 28,29,30,31 etp8 8 100000 +Ethernet32 32,33 etp9a 9 50000 +Ethernet34 34,35 etp9b 9 50000 +Ethernet36 36,37 etp10a 10 50000 +Ethernet38 38,39 etp10b 10 50000 +Ethernet40 40,41 etp11a 11 50000 +Ethernet42 42,43 etp11b 11 50000 +Ethernet44 44,45 etp12a 12 50000 +Ethernet46 46,47 etp12b 12 50000 +Ethernet48 48,49,50,51 etp13 13 100000 +Ethernet52 52,53,54,55 etp14 14 100000 +Ethernet56 56,57,58,59 etp15 15 100000 +Ethernet60 60,61,62,63 etp16 16 100000 +Ethernet64 64,65,66,67 etp17 17 100000 +Ethernet68 68,69,70,71 etp18 18 100000 +Ethernet72 72,73,74,75 etp19 19 100000 +Ethernet76 76,77,78,79 etp20 20 100000 +Ethernet80 80,81,82,83 etp21 21 100000 +Ethernet84 84,85,86,87 etp22 22 100000 +Ethernet88 88,89,90,91 etp23 23 100000 +Ethernet92 92,93,94,95 etp24 24 100000 +Ethernet96 96,97,98,99 etp25 25 100000 +Ethernet100 100,101,102,103 etp26 26 100000 +Ethernet104 104,105 etp27a 27 50000 +Ethernet106 106,107 etp27b 27 50000 +Ethernet108 108,109 etp28a 28 50000 +Ethernet110 110,111 etp28b 28 50000 +Ethernet112 112,113,114,115 etp29 29 100000 +Ethernet116 116,117,118,119 etp30 30 100000 +Ethernet120 120,121,122,123 etp31 31 100000 +Ethernet124 124,125,126,127 etp32 32 100000 +Ethernet128 128,129,130,131 etp33 33 100000 +Ethernet132 132,133,134,135 etp34 34 100000 +Ethernet136 136,137,138,139 etp35 35 100000 +Ethernet140 140,141,142,143 etp36 36 100000 +Ethernet144 144,145,146,147 etp37 37 100000 +Ethernet148 148,149,150,151 etp38 38 100000 +Ethernet152 152,153,154,155 etp39 38 100000 +Ethernet156 156,157,158,159 etp40 40 100000 +Ethernet160 160,161,162,163 etp41 41 100000 +Ethernet164 164,165,166,167 etp42 42 100000 +Ethernet168 168,169,170,171 etp43 43 100000 +Ethernet172 172,173,174,175 etp44 44 100000 +Ethernet176 176,177 etp45a 45 50000 +Ethernet178 178,179 etp45b 45 50000 +Ethernet180 180,181 etp46a 46 50000 +Ethernet182 182,183 etp46b 46 50000 +Ethernet184 184,185 etp47a 47 50000 +Ethernet186 186,187 etp47b 47 50000 +Ethernet188 188,189 etp48a 48 50000 +Ethernet190 190,191 etp48b 48 50000 +Ethernet192 192,193,194,195 etp49 49 100000 +Ethernet196 196,197,198,199 etp50 50 100000 +Ethernet200 200,201,202,203 etp51 51 100000 +Ethernet204 204,205,206,207 etp52 52 100000 +Ethernet208 208,209,210,211 etp53 53 100000 +Ethernet212 212,213,214,215 etp54 54 100000 +Ethernet216 216,217,218,219 etp55 55 100000 +Ethernet220 220,221,222,223 etp56 56 100000 +Ethernet224 224,225,226,227 etp57 57 100000 +Ethernet228 228,229,230,231 etp58 58 100000 +Ethernet232 232,233,234,235 etp59 59 100000 +Ethernet236 236,237,238,239 etp60 60 100000 +Ethernet240 240,241 etp61a 61 50000 +Ethernet242 242,243 etp61b 61 50000 +Ethernet244 244,245 etp62a 62 50000 +Ethernet246 246,247 etp62b 62 50000 +Ethernet248 248,249 etp63a 63 50000 +Ethernet250 250,251 etp63b 63 50000 +Ethernet252 252,253 etp64a 64 50000 +Ethernet254 254,255 etp64b 64 50000 \ No newline at end of file diff --git a/device/mellanox/x86_64-mlnx_msn3800-r0/Mellanox-SN3800-D28C50/qos.json.j2 b/device/mellanox/x86_64-mlnx_msn3800-r0/Mellanox-SN3800-D28C50/qos.json.j2 new file mode 120000 index 000000000000..26b0dac51846 --- /dev/null +++ b/device/mellanox/x86_64-mlnx_msn3800-r0/Mellanox-SN3800-D28C50/qos.json.j2 @@ -0,0 +1 @@ +../ACS-MSN3800/qos.json.j2 \ No newline at end of file diff --git a/device/mellanox/x86_64-mlnx_msn3800-r0/Mellanox-SN3800-D28C50/sai.profile b/device/mellanox/x86_64-mlnx_msn3800-r0/Mellanox-SN3800-D28C50/sai.profile new file mode 100644 index 000000000000..aa37fb30dbd0 --- /dev/null +++ b/device/mellanox/x86_64-mlnx_msn3800-r0/Mellanox-SN3800-D28C50/sai.profile @@ -0,0 +1 @@ +SAI_INIT_CONFIG_FILE=/usr/share/sonic/hwsku/sai_3800_28x50g_52x100g.xml diff --git a/device/mellanox/x86_64-mlnx_msn3800-r0/Mellanox-SN3800-D28C50/sai_3800_28x50g_52x100g.xml b/device/mellanox/x86_64-mlnx_msn3800-r0/Mellanox-SN3800-D28C50/sai_3800_28x50g_52x100g.xml new file mode 100644 index 000000000000..1b3c77ce381c --- /dev/null +++ b/device/mellanox/x86_64-mlnx_msn3800-r0/Mellanox-SN3800-D28C50/sai_3800_28x50g_52x100g.xml @@ -0,0 +1,470 @@ + + + + + + 00:02:03:04:05:00 + + + 1 + + + 64 + + + + + 1 + 4 + 48 + + + 3 + + + 1536 + + + 3 + 4 + 49 + 3 + 1536 + + + 5 + 4 + 50 + 3 + 1536 + + + 7 + 4 + 51 + 3 + 1536 + + + 9 + 4 + 52 + 3 + 1536 + + + 11 + 4 + 53 + 3 + 1536 + + + 13 + 4 + 54 + 3 + 1536 + + + 15 + 4 + 55 + 3 + 1536 + + + 17 + 4 + 56 + 3 + 1536 + + + 19 + 4 + 57 + 3 + 1536 + + + 21 + 4 + 58 + 3 + 1536 + + + 23 + 4 + 59 + 3 + 1536 + + + 25 + 4 + 60 + 3 + 1536 + + + 27 + 4 + 61 + 3 + 1536 + + + 29 + 4 + 62 + 3 + 1536 + + + 31 + 4 + 63 + 3 + 1536 + + + 33 + 4 + 12 + 3 + 1536 + + + 35 + 4 + 13 + 3 + 1536 + + + 37 + 4 + 14 + 3 + 1536 + + + 39 + 4 + 15 + 3 + 1536 + + + 41 + 4 + 8 + 3 + 1536 + + + 43 + 4 + 9 + 3 + 1536 + + + 45 + 4 + 10 + 3 + 1536 + + + 47 + 4 + 11 + 3 + 1536 + + + 49 + 4 + 4 + 3 + 1536 + + + 51 + 4 + 5 + 3 + 1536 + + + 53 + 4 + 6 + 3 + 1536 + + + 55 + 4 + 7 + 3 + 1536 + + + 57 + 4 + 0 + 3 + 1536 + + + 59 + 4 + 1 + 3 + 1536 + + + 61 + 4 + 2 + 3 + 1536 + + + 63 + 4 + 3 + 3 + 1536 + + + 65 + 4 + 44 + 3 + 1536 + + + 67 + 4 + 45 + 3 + 1536 + + + 69 + 4 + 46 + 3 + 1536 + + + 71 + 4 + 47 + 3 + 1536 + + + 73 + 4 + 40 + 3 + 1536 + + + 75 + 4 + 41 + 3 + 1536 + + + 77 + 4 + 42 + 3 + 1536 + + + 79 + 4 + 43 + 3 + 1536 + + + 81 + 4 + 36 + 3 + 1536 + + + 83 + 4 + 37 + 3 + 1536 + + + 85 + 4 + 38 + 3 + 1536 + + + 87 + 4 + 39 + 3 + 1536 + + + 89 + 4 + 32 + 3 + 1536 + + + 91 + 4 + 33 + 3 + 1536 + + + 93 + 4 + 34 + 3 + 1536 + + + 95 + 4 + 35 + 3 + 1536 + + + 97 + 4 + 16 + 3 + 1536 + + + 99 + 4 + 17 + 3 + 1536 + + + 101 + 4 + 18 + 3 + 1536 + + + 103 + 4 + 19 + 3 + 1536 + + + 105 + 4 + 20 + 3 + 1536 + + + 107 + 4 + 21 + 3 + 1536 + + + 109 + 4 + 22 + 3 + 1536 + + + 111 + 4 + 23 + 3 + 1536 + + + 113 + 4 + 24 + 3 + 1536 + + + 115 + 4 + 25 + 3 + 1536 + + + 117 + 4 + 26 + 3 + 1536 + + + 119 + 4 + 27 + 3 + 1536 + + + 121 + 4 + 28 + 3 + 1536 + + + 123 + 4 + 29 + 3 + 1536 + + + 125 + 4 + 30 + 3 + 1536 + + + 127 + 4 + 31 + 3 + 1536 + + + + diff --git a/device/mellanox/x86_64-mlnx_msn3800-r0/thermal_policy.json b/device/mellanox/x86_64-mlnx_msn3800-r0/thermal_policy.json new file mode 120000 index 000000000000..5a25cd87f70c --- /dev/null +++ b/device/mellanox/x86_64-mlnx_msn3800-r0/thermal_policy.json @@ -0,0 +1 @@ +../x86_64-mlnx_msn2700-r0/thermal_policy.json \ No newline at end of file diff --git a/device/mellanox/x86_64-mlnx_msn4600c-r0/ACS-MSN4600C/port_config.ini b/device/mellanox/x86_64-mlnx_msn4600c-r0/ACS-MSN4600C/port_config.ini index 7ccff5a8da4b..a1ecf9aa3266 100644 --- a/device/mellanox/x86_64-mlnx_msn4600c-r0/ACS-MSN4600C/port_config.ini +++ b/device/mellanox/x86_64-mlnx_msn4600c-r0/ACS-MSN4600C/port_config.ini @@ -1,65 +1,65 @@ # name lanes alias index -Ethernet0 0,1,2,3 etp1 0 -Ethernet8 8,9,10,11 etp2 1 -Ethernet16 16,17,18,19 etp3 2 -Ethernet24 24,25,26,27 etp4 3 -Ethernet32 32,33,34,35 etp5 4 -Ethernet40 40,41,42,43 etp6 5 -Ethernet48 48,49,50,51 etp7 6 -Ethernet56 56,57,58,59 etp8 7 -Ethernet64 64,65,66,67 etp9 8 -Ethernet72 72,73,74,75 etp10 9 -Ethernet80 80,81,82,83 etp11 10 -Ethernet88 88,89,90,91 etp12 11 -Ethernet96 96,97,98,99 etp13 12 -Ethernet104 104,105,106,107 etp14 13 -Ethernet112 112,113,114,115 etp15 14 -Ethernet120 120,121,122,123 etp16 15 -Ethernet128 128,129,130,131 etp17 16 -Ethernet136 136,137,138,139 etp18 17 -Ethernet144 144,145,146,147 etp19 18 -Ethernet152 152,153,154,155 etp20 19 -Ethernet160 160,161,162,163 etp21 20 -Ethernet168 168,169,170,171 etp22 21 -Ethernet176 176,177,178,179 etp23 22 -Ethernet184 184,185,186,187 etp24 23 -Ethernet192 192,193,194,195 etp25 24 -Ethernet200 200,201,202,203 etp26 25 -Ethernet208 208,209,210,211 etp27 26 -Ethernet216 216,217,218,219 etp28 27 -Ethernet224 224,225,226,227 etp29 28 -Ethernet232 232,233,234,235 etp30 29 -Ethernet240 240,241,242,243 etp31 30 -Ethernet248 248,249,250,251 etp32 31 -Ethernet256 256,257,258,259 etp33 32 -Ethernet264 264,265,266,267 etp34 33 -Ethernet272 272,273,274,275 etp35 34 -Ethernet280 280,281,282,283 etp36 35 -Ethernet288 288,289,290,291 etp37 36 -Ethernet296 296,297,298,299 etp38 37 -Ethernet304 304,305,306,307 etp39 38 -Ethernet312 312,313,314,315 etp40 39 -Ethernet320 320,321,322,323 etp41 40 -Ethernet328 328,329,330,331 etp42 41 -Ethernet336 336,337,338,339 etp43 42 -Ethernet344 344,345,346,347 etp44 43 -Ethernet352 352,353,354,355 etp45 44 -Ethernet360 360,361,362,363 etp46 45 -Ethernet368 368,369,370,371 etp47 46 -Ethernet376 376,377,378,379 etp48 47 -Ethernet384 384,385,386,387 etp49 48 -Ethernet392 392,393,394,395 etp50 49 -Ethernet400 400,401,402,403 etp51 50 -Ethernet408 408,409,410,411 etp52 51 -Ethernet416 416,417,418,419 etp53 52 -Ethernet424 424,425,426,427 etp54 53 -Ethernet432 432,433,434,435 etp55 54 -Ethernet440 440,441,442,443 etp56 55 -Ethernet448 448,449,450,451 etp57 56 -Ethernet456 456,457,458,459 etp58 57 -Ethernet464 464,465,466,467 etp59 58 -Ethernet472 472,473,474,475 etp60 59 -Ethernet480 480,481,482,483 etp61 60 -Ethernet488 488,489,490,491 etp62 61 -Ethernet496 496,497,498,499 etp63 62 -Ethernet504 504,505,506,507 etp64 63 +Ethernet0 0,1,2,3 etp1 1 +Ethernet8 8,9,10,11 etp2 2 +Ethernet16 16,17,18,19 etp3 3 +Ethernet24 24,25,26,27 etp4 4 +Ethernet32 32,33,34,35 etp5 5 +Ethernet40 40,41,42,43 etp6 6 +Ethernet48 48,49,50,51 etp7 7 +Ethernet56 56,57,58,59 etp8 8 +Ethernet64 64,65,66,67 etp9 9 +Ethernet72 72,73,74,75 etp10 10 +Ethernet80 80,81,82,83 etp11 11 +Ethernet88 88,89,90,91 etp12 12 +Ethernet96 96,97,98,99 etp13 13 +Ethernet104 104,105,106,107 etp14 14 +Ethernet112 112,113,114,115 etp15 15 +Ethernet120 120,121,122,123 etp16 16 +Ethernet128 128,129,130,131 etp17 17 +Ethernet136 136,137,138,139 etp18 18 +Ethernet144 144,145,146,147 etp19 19 +Ethernet152 152,153,154,155 etp20 20 +Ethernet160 160,161,162,163 etp21 21 +Ethernet168 168,169,170,171 etp22 22 +Ethernet176 176,177,178,179 etp23 23 +Ethernet184 184,185,186,187 etp24 24 +Ethernet192 192,193,194,195 etp25 25 +Ethernet200 200,201,202,203 etp26 26 +Ethernet208 208,209,210,211 etp27 27 +Ethernet216 216,217,218,219 etp28 28 +Ethernet224 224,225,226,227 etp29 29 +Ethernet232 232,233,234,235 etp30 30 +Ethernet240 240,241,242,243 etp31 31 +Ethernet248 248,249,250,251 etp32 32 +Ethernet256 256,257,258,259 etp33 33 +Ethernet264 264,265,266,267 etp34 34 +Ethernet272 272,273,274,275 etp35 35 +Ethernet280 280,281,282,283 etp36 36 +Ethernet288 288,289,290,291 etp37 37 +Ethernet296 296,297,298,299 etp38 38 +Ethernet304 304,305,306,307 etp39 39 +Ethernet312 312,313,314,315 etp40 40 +Ethernet320 320,321,322,323 etp41 41 +Ethernet328 328,329,330,331 etp42 42 +Ethernet336 336,337,338,339 etp43 43 +Ethernet344 344,345,346,347 etp44 44 +Ethernet352 352,353,354,355 etp45 45 +Ethernet360 360,361,362,363 etp46 46 +Ethernet368 368,369,370,371 etp47 47 +Ethernet376 376,377,378,379 etp48 48 +Ethernet384 384,385,386,387 etp49 49 +Ethernet392 392,393,394,395 etp50 50 +Ethernet400 400,401,402,403 etp51 51 +Ethernet408 408,409,410,411 etp52 52 +Ethernet416 416,417,418,419 etp53 53 +Ethernet424 424,425,426,427 etp54 54 +Ethernet432 432,433,434,435 etp55 55 +Ethernet440 440,441,442,443 etp56 56 +Ethernet448 448,449,450,451 etp57 57 +Ethernet456 456,457,458,459 etp58 58 +Ethernet464 464,465,466,467 etp59 59 +Ethernet472 472,473,474,475 etp60 60 +Ethernet480 480,481,482,483 etp61 61 +Ethernet488 488,489,490,491 etp62 62 +Ethernet496 496,497,498,499 etp63 63 +Ethernet504 504,505,506,507 etp64 64 diff --git a/device/mellanox/x86_64-mlnx_msn4600c-r0/sensors.conf b/device/mellanox/x86_64-mlnx_msn4600c-r0/sensors.conf index b2f942ffa5f8..9c80350e19ad 100644 --- a/device/mellanox/x86_64-mlnx_msn4600c-r0/sensors.conf +++ b/device/mellanox/x86_64-mlnx_msn4600c-r0/sensors.conf @@ -23,114 +23,114 @@ bus "i2c-15" "i2c-1-mux (chan_id 6)" bus "i2c-5" "i2c-1-mux (chan_id 4)" chip "xdpe12284-i2c-*-62" label in1 "PMIC-1 PSU 12V Rail (in)" - label in2 "PMIC-1 PSU 12V Rail (in)" + ignore in2 label in3 "PMIC-1 ASIC 0.8V VCORE_MAIN Rail (out)" ignore in4 label temp1 "PMIC-1 Temp 1" label temp2 "PMIC-1 Temp 2" label power1 "PMIC-1 ASIC 12V VCORE_MAIN Rail Pwr (in)" ignore power2 - label power3 "PMIC-1 ASIC 12V VCORE_MAIN Rail Pwr (out)" + label power3 "PMIC-1 ASIC 0.8V VCORE_MAIN Rail Pwr (out)" ignore power4 - label curr1 "PMIC-1 ASIC 0.8V VCORE_MAIN Rail Curr (in)" + label curr1 "PMIC-1 ASIC 12V VCORE_MAIN Rail Curr (in)" ignore curr2 label curr3 "PMIC-1 ASIC 0.8V VCORE_MAIN Rail Curr (out)" ignore curr4 chip "xdpe12284-i2c-*-64" - label in1 "PMIC-2 PSU 12V Rail (in)" - label in2 "PMIC-2 PSU 12V Rail (in)" - label in3 "PMIC-2 ASIC 1.8V MAIN Rail (out)" - label in4 "PMIC-2 ASIC 1.2V MAIN Rail (out)" + label in1 "PMIC-2 PSU 12V Rail_1 (in)" + label in2 "PMIC-2 PSU 12V Rail_2 (in)" + label in3 "PMIC-2 ASIC 1.8V Rail_1 (out)" + label in4 "PMIC-2 ASIC 1.2V Rail_2 (out)" label temp1 "PMIC-2 Temp 1" label temp2 "PMIC-2 Temp 2" - label power1 "PMIC-2 ASIC 1.8V MAIN Rail Pwr (in)" - label power2 "PMIC-2 ASIC 1.2V MAIN Rail Pwr (in)" - label power3 "PMIC-2 ASIC 1.8V MAIN Rail Pwr (out)" - label power4 "PMIC-2 ASIC 1.2V MAIN Rail Pwr (out)" - label curr1 "PMIC-2 ASIC 1.8V MAIN Rail Curr (in)" - label curr2 "PMIC-2 ASIC 1.2V MAIN Rail Curr (in)" - label curr3 "PMIC-2 ASIC 1.8V MAIN Rail Curr (out)" - label curr4 "PMIC-2 ASIC 1.2V MAIN Rail Curr (out)" + label power1 "PMIC-2 ASIC 12V Rail_1 Pwr (in)" + label power2 "PMIC-2 ASIC 12V Rail_2 Pwr (in)" + label power3 "PMIC-2 ASIC 1.8V Rail_1 Pwr (out)" + label power4 "PMIC-2 ASIC 1.2V Rail_2 Pwr (out)" + label curr1 "PMIC-2 ASIC 12V Rail_1 Curr (in)" + label curr2 "PMIC-2 ASIC 12V Rail_2 Curr (in)" + label curr3 "PMIC-2 ASIC 1.8V Rail_1 Curr (out)" + label curr4 "PMIC-2 ASIC 1.2V Rail_2 Curr (out)" chip "xdpe12284-i2c-*-66" - label in1 "PMIC-3 PSU 12V Rail (in)" - label in2 "PMIC-3 PSU 12V Rail (in)" - label in3 "PMIC-3 ASIC 0.85V MAIN Rail (out)" - label in4 "PMIC-3 ASIC 1.8V MAIN Rail (out)" + label in1 "PMIC-3 PSU 12V Rail_1 (in)" + label in2 "PMIC-3 PSU 12V Rail_2 (in)" + label in3 "PMIC-3 ASIC 0.85V Rail_1 T0_1 (out)" + label in4 "PMIC-3 ASIC 1.8V Rail_2 T0_1 (out)" label temp1 "PMIC-3 Temp 1" label temp2 "PMIC-3 Temp 2" - label power1 "PMIC-3 ASIC 12V MAIN Rail Pwr (in)" - label power2 "PMIC-3 ASIC 12V MAIN Rail Pwr (in)" - label power3 "PMIC-3 ASIC 0.85V MAIN Rail Pwr (out)" - label power4 "PMIC-3 ASIC 1.8V MAIN Rail Pwr (out)" - label curr1 "PMIC-3 ASIC 12V MAIN Rail Curr (in)" - label curr2 "PMIC-3 ASIC 12V MAIN Rail Curr (in)" - label curr3 "PMIC-3 ASIC 0.85V MAIN Rail Curr (out)" - label curr4 "PMIC-3 ASIC 1.8V MAIN Rail Curr (out)" + label power1 "PMIC-3 ASIC 12V Rail_1 Pwr (in)" + label power2 "PMIC-3 ASIC 12V Rail_2 Pwr (in)" + label power3 "PMIC-3 ASIC 0.85V Rail_1 T0_1 Pwr (out)" + label power4 "PMIC-3 ASIC 1.8V Rail_2 T0_1 Pwr (out)" + label curr1 "PMIC-3 ASIC 12V Rail_1 Curr (in)" + label curr2 "PMIC-3 ASIC 12V Rail_2 Curr (in)" + label curr3 "PMIC-3 ASIC 0.85V Rail_1 T0_1 Curr (out)" + label curr4 "PMIC-3 ASIC 1.8V Rail_2 T0_1 Curr (out)" chip "xdpe12284-i2c-*-68" - label in1 "PMIC-4 PSU 12V Rail (in)" - label in2 "PMIC-4 PSU 12V Rail (in)" - label in3 "PMIC-4 ASIC 0.85V VCORE_T6_7 Rail (out)" - label in4 "PMIC-4 ASIC 1.8V T6_7 Rail (out)" + label in1 "PMIC-4 PSU 12V Rail_1 (in)" + label in2 "PMIC-4 PSU 12V Rail_2 (in)" + label in3 "PMIC-4 ASIC 0.85V Rail_1 T2_3 (out)" + label in4 "PMIC-4 ASIC 1.8V Rail_2 T2_3 (out)" label temp1 "PMIC-4 Temp 1" label temp2 "PMIC-4 Temp 2" - label power1 "PMIC-4 ASIC 0.85V VCORE_T6_7 Rail Pwr (in)" - label power2 "PMIC-4 ASIC 1.8V T6_7 Rail Pwr (in)" - label power3 "PMIC-4 ASIC 0.85V VCORE_T6_7 Rail Pwr (out)" - label power4 "PMIC-4 ASIC 1.8V T6_7 Rail Pwr (out)" - label curr1 "PMIC-4 ASIC 0.85V VCORE_T6_7 Rail Curr (in)" - label curr2 "PMIC-4 ASIC 1.8V T6_7 Rail Curr (in)" - label curr3 "PMIC-4 ASIC 0.85V VCORE_T6_7 Rail Curr (out)" - label curr4 "PMIC-4 ASIC 1.8V T6_7 Rail Curr (out)" + label power1 "PMIC-4 ASIC 12V Rail_1 Pwr (in)" + label power2 "PMIC-4 ASIC 12V Rail_2 Pwr (in)" + label power3 "PMIC-4 ASIC 0.85V Rail_1 T2_3 Pwr (out)" + label power4 "PMIC-4 ASIC 1.8V Rail_2 T2_3 Pwr (out)" + label curr1 "PMIC-4 ASIC 12V Rail_1 Curr (in)" + label curr2 "PMIC-4 ASIC 12V Rail_2 Curr (in)" + label curr3 "PMIC-4 ASIC 0.85V Rail_1 T2_3 Curr (out)" + label curr4 "PMIC-4 ASIC 1.8V Rail_2 T2_3 Curr (out)" chip "xdpe12284-i2c-*-6a" - label in1 "PMIC-5 PSU 12V Rail (in)" - label in2 "PMIC-5 PSU 12V Rail (in)" - label in3 "PMIC-5 ASIC 0.85V VCORE_T6_7 Rail (out)" - label in4 "PMIC-5 ASIC 1.8V T6_7 Rail (out)" + label in1 "PMIC-5 PSU 12V Rail_1 (in)" + label in2 "PMIC-5 PSU 12V Rail_2 (in)" + label in3 "PMIC-5 ASIC 0.85V Rail_1 T4_5 (out)" + label in4 "PMIC-5 ASIC 1.8V Rail_2 T4_5 (out)" label temp1 "PMIC-5 Temp 1" label temp2 "PMIC-5 Temp 2" - label power1 "PMIC-5 ASIC 0.85V VCORE_T6_7 Rail Pwr (in)" - label power2 "PMIC-5 ASIC 1.8V T6_7 Rail Pwr (in)" - label power3 "PMIC-5 ASIC 0.85V VCORE_T6_7 Rail Pwr (out)" - label power4 "PMIC-5 ASIC 1.8V T6_7 Rail Pwr (out)" - label curr1 "PMIC-5 ASIC 0.85V VCORE_T6_7 Rail Curr (in)" - label curr2 "PMIC-5 ASIC 1.8V T6_7 Rail Curr (in)" - label curr3 "PMIC-5 ASIC 0.85V VCORE_T6_7 Rail Curr (out)" - label curr4 "PMIC-5 ASIC 1.8V T6_7 Rail Curr (out)" + label power1 "PMIC-5 ASIC 12V Rail_1 Pwr (in)" + label power2 "PMIC-5 ASIC 12V Rail_2 Pwr (in)" + label power3 "PMIC-5 ASIC 0.85V Rail_1 T4_5 Pwr (out)" + label power4 "PMIC-5 ASIC 1.8V Rail_2 T4_5 Pwr (out)" + label curr1 "PMIC-5 ASIC 12V Rail_1 Curr (in)" + label curr2 "PMIC-5 ASIC 12V Rail_2 Curr (in)" + label curr3 "PMIC-5 ASIC 0.85V Rail_1 T4_5 Curr (out)" + label curr4 "PMIC-5 ASIC 1.8V Rail_2 T4_5 Curr (out)" chip "xdpe12284-i2c-*-6c" - label in1 "PMIC-6 PSU 12V Rail (in)" - label in2 "PMIC-6 PSU 12V Rail (in)" - label in3 "PMIC-6 ASIC 0.85V VCORE_T6_7 Rail (out)" - label in4 "PMIC-6 ASIC 1.8V T6_7 Rail (out)" + label in1 "PMIC-6 PSU 12V Rail_1 (in)" + label in2 "PMIC-6 PSU 12V Rail_2 (in)" + label in3 "PMIC-6 ASIC 0.85V Rail_1 T6_7 (out)" + label in4 "PMIC-6 ASIC 1.8V Rail_2 T6_7 (out)" label temp1 "PMIC-6 Temp 1" label temp2 "PMIC-6 Temp 2" - label power1 "PMIC-6 ASIC 0.85V VCORE_T6_7 Rail Pwr (in)" - label power2 "PMIC-6 ASIC 1.8V T6_7 Rail Pwr (in)" - label power3 "PMIC-6 ASIC 0.85V VCORE_T6_7 Rail Pwr (out)" - label power4 "PMIC-6 ASIC 1.8V T6_7 Rail Pwr (out)" - label curr1 "PMIC-6 ASIC 0.85V VCORE_T6_7 Rail Curr (in)" - label curr2 "PMIC-6 ASIC 1.8V T6_7 Rail Curr (in)" - label curr3 "PMIC-6 ASIC 0.85V VCORE_T6_7 Rail Curr (out)" - label curr4 "PMIC-6 ASIC 1.8V T6_7 Rail Curr (out)" + label power1 "PMIC-6 ASIC 12V Rail_1 Pwr (in)" + label power2 "PMIC-6 ASIC 12V Rail_2 Pwr (in)" + label power3 "PMIC-6 ASIC 0.85V Rail_1 T6_7 Pwr (out)" + label power4 "PMIC-6 ASIC 1.8V Rail_2 T6_7 Pwr (out)" + label curr1 "PMIC-6 ASIC 12V Rail_1 Curr (in)" + label curr2 "PMIC-6 ASIC 12V Rail_2 Curr (in)" + label curr3 "PMIC-6 ASIC 0.85V Rail_1 T6_7 Curr (out)" + label curr4 "PMIC-6 ASIC 1.8V Rail_2 T6_7 Curr (out)" chip "xdpe12284-i2c-*-6e" - label in1 "PMIC-7 PSU 12V Rail (in)" - label in2 "PMIC-7 PSU 12V Rail (in)" - label in3 "PMIC-7 ASIC 1.2V VCORE_T6_7 Rail (out)" - label in4 "PMIC-7 ASIC 1.2V T6_7 Rail (out)" + label in1 "PMIC-7 PSU 12V Rail_1 (in)" + label in2 "PMIC-7 PSU 12V Rail_2 (in)" + label in3 "PMIC-7 ASIC 1.2V Rail_1 T0_3 (out)" + label in4 "PMIC-7 ASIC 1.2V Rail_2 T4_7 (out)" label temp1 "PMIC-7 Temp 1" label temp2 "PMIC-7 Temp 2" - label power1 "PMIC-7 ASIC 0.85V VCORE_T6_7 Rail Pwr (in)" - label power2 "PMIC-7 ASIC 1.8V T6_7 Rail Pwr (in)" - label power3 "PMIC-7 ASIC 0.85V VCORE_T6_7 Rail Pwr (out)" - label power4 "PMIC-7 ASIC 1.8V T6_7 Rail Pwr (out)" - label curr1 "PMIC-7 ASIC 0.85V VCORE_T6_7 Rail Curr (in)" - label curr2 "PMIC-7 ASIC 1.8V T6_7 Rail Curr (in)" - label curr3 "PMIC-7 ASIC 0.85V VCORE_T6_7 Rail Curr (out)" - label curr4 "PMIC-7 ASIC 1.8V T6_7 Rail Curr (out)" + label power1 "PMIC-7 ASIC 12V Rail_1 Pwr (in)" + label power2 "PMIC-7 ASIC 12V Rail_2 Pwr (in)" + label power3 "PMIC-7 ASIC 1.2V Rail_1 T0_3 Pwr (out)" + label power4 "PMIC-7 ASIC 1.2V Rail_2 T4_7 Pwr (out)" + label curr1 "PMIC-7 ASIC 12V Rail_1 Curr (in)" + label curr2 "PMIC-7 ASIC 12V Rail_2 Curr (in)" + label curr3 "PMIC-7 ASIC 1.2V Rail_1 T0_3 Curr (out)" + label curr4 "PMIC-7 ASIC 1.2V Rail_2 T4_7 Curr (out)" bus "i2c-15" "i2c-1-mux (chan_id 6)" chip "tps53679-i2c-*-58" - label in1 "PMIC-8 PSU 12V Rail (in)" - label in2 "PMIC-8 PSU 12V Rail (in)" + label in1 "PMIC-8 PSU 12V Rail (in1)" + label in2 "PMIC-8 PSU 12V Rail (in2)" label in3 "PMIC-8 COMEX 1.8V Rail (out)" label in4 "PMIC-8 COMEX 1.05V Rail (out)" label temp1 "PMIC-8 Temp 1" @@ -140,8 +140,8 @@ bus "i2c-15" "i2c-1-mux (chan_id 6)" label curr1 "PMIC-8 COMEX 1.8V Rail Curr (out)" label curr2 "PMIC-8 COMEX 1.05V Rail Curr (out)" chip "tps53679-i2c-*-61" - label in1 "PMIC-9 PSU 12V Rail (in)" - label in2 "PMIC-9 PSU 12V Rail (in)" + label in1 "PMIC-9 PSU 12V Rail (in1)" + label in2 "PMIC-9 PSU 12V Rail (in2)" label in3 "PMIC-9 COMEX 1.2V Rail (out)" ignore in4 label temp1 "PMIC-9 Temp 1" @@ -154,22 +154,8 @@ bus "i2c-15" "i2c-1-mux (chan_id 6)" # Power supplies bus "i2c-4" "i2c-1-mux (chan_id 3)" chip "dps460-i2c-*-58" - label in1 "PSU-2(R) 220V Rail (in)" - label in2 "PSU-2(R) 220V Rail (in)" - label in3 "PSU-2(R) 12V Rail (out)" - label fan1 "PSU-2(R) Fan 1" - ignore fan2 - ignore fan3 - label temp1 "PSU-2(R) Temp 1" - label temp2 "PSU-2(R) Temp 2" - label temp3 "PSU-2(R) Temp 3" - label power1 "PSU-2(R) 220V Rail Pwr (in)" - label power2 "PSU-2(R) 12V Rail Pwr (out)" - label curr1 "PSU-2(R) 220V Rail Curr (in)" - label curr2 "PSU-2(R) 12V Rail Curr (out)" - chip "dps460-i2c-*-59" label in1 "PSU-1(L) 220V Rail (in)" - label in2 "PSU-1(L) 220V Rail (in)" + ignore in2 label in3 "PSU-1(L) 12V Rail (out)" label fan1 "PSU-1(L) Fan 1" ignore fan2 @@ -181,13 +167,23 @@ bus "i2c-4" "i2c-1-mux (chan_id 3)" label power2 "PSU-1(L) 12V Rail Pwr (out)" label curr1 "PSU-1(L) 220V Rail Curr (in)" label curr2 "PSU-1(L) 12V Rail Curr (out)" + chip "dps460-i2c-*-59" + label in1 "PSU-2(R) 220V Rail (in)" + ignore in2 + label in3 "PSU-2(R) 12V Rail (out)" + label fan1 "PSU-2(R) Fan 1" + ignore fan2 + ignore fan3 + label temp1 "PSU-2(R) Temp 1" + label temp2 "PSU-2(R) Temp 2" + label temp3 "PSU-2(R) Temp 3" + label power1 "PSU-2(R) 220V Rail Pwr (in)" + label power2 "PSU-2(R) 12V Rail Pwr (out)" + label curr1 "PSU-2(R) 220V Rail Curr (in)" + label curr2 "PSU-2(R) 12V Rail Curr (out)" # Chassis fans chip "mlxreg_fan-isa-*" label fan1 "Chassis Fan Drawer-1" label fan2 "Chassis Fan Drawer-2" label fan3 "Chassis Fan Drawer-3" - -# Miscellaneous -chip "*-virtual-*" - ignore temp1 diff --git a/device/mellanox/x86_64-mlnx_msn4600c-r0/thermal_policy.json b/device/mellanox/x86_64-mlnx_msn4600c-r0/thermal_policy.json new file mode 120000 index 000000000000..5a25cd87f70c --- /dev/null +++ b/device/mellanox/x86_64-mlnx_msn4600c-r0/thermal_policy.json @@ -0,0 +1 @@ +../x86_64-mlnx_msn2700-r0/thermal_policy.json \ No newline at end of file diff --git a/device/mellanox/x86_64-mlnx_msn4700-r0/ACS-MSN4700/port_config.ini b/device/mellanox/x86_64-mlnx_msn4700-r0/ACS-MSN4700/port_config.ini index 2a14b4a79eb6..ea7219932624 100644 --- a/device/mellanox/x86_64-mlnx_msn4700-r0/ACS-MSN4700/port_config.ini +++ b/device/mellanox/x86_64-mlnx_msn4700-r0/ACS-MSN4700/port_config.ini @@ -1,33 +1,33 @@ # name lanes alias index -Ethernet0 0,1,2,3,4,5,6,7 etp1 0 -Ethernet8 8,9,10,11,12,13,14,15 etp2 1 -Ethernet16 16,17,18,19,20,21,22,23 etp3 2 -Ethernet24 24,25,26,27,28,29,30,31 etp4 3 -Ethernet32 32,33,34,35,36,37,38,39 etp5 4 -Ethernet40 40,41,42,43,44,45,46,47 etp6 5 -Ethernet48 48,49,50,51,52,53,54,55 etp7 6 -Ethernet56 56,57,58,59,60,61,62,63 etp8 7 -Ethernet64 64,65,66,67,68,69,70,71 etp9 8 -Ethernet72 72,73,74,75,76,77,78,79 etp10 9 -Ethernet80 80,81,82,83,84,85,86,87 etp11 10 -Ethernet88 88,89,90,91,92,93,94,95 etp12 11 -Ethernet96 96,97,98,99,100,101,102,103 etp13 12 -Ethernet104 104,105,106,107,108,109,110,111 etp14 13 -Ethernet112 112,113,114,115,116,117,118,119 etp15 14 -Ethernet120 120,121,122,123,124,125,126,127 etp16 15 -Ethernet128 128,129,130,131,132,133,134,135 etp17 16 -Ethernet136 136,137,138,139,140,141,142,143 etp18 17 -Ethernet144 144,145,146,147,148,149,150,151 etp19 18 -Ethernet152 152,153,154,155,156,157,158,159 etp20 19 -Ethernet160 160,161,162,163,164,165,166,167 etp21 20 -Ethernet168 168,169,170,171,172,173,174,175 etp22 21 -Ethernet176 176,177,178,179,180,181,182,183 etp23 22 -Ethernet184 184,185,186,187,188,189,190,191 etp24 23 -Ethernet192 192,193,194,195,196,197,198,199 etp25 24 -Ethernet200 200,201,202,203,204,205,206,207 etp26 25 -Ethernet208 208,209,210,211,212,213,214,215 etp27 26 -Ethernet216 216,217,218,219,220,221,222,223 etp28 27 -Ethernet224 224,225,226,227,228,229,230,231 etp29 28 -Ethernet232 232,233,234,235,236,237,238,239 etp30 29 -Ethernet240 240,241,242,243,244,245,246,247 etp31 30 -Ethernet248 248,249,250,251,252,253,254,255 etp32 31 +Ethernet0 0,1,2,3,4,5,6,7 etp1 1 +Ethernet8 8,9,10,11,12,13,14,15 etp2 2 +Ethernet16 16,17,18,19,20,21,22,23 etp3 3 +Ethernet24 24,25,26,27,28,29,30,31 etp4 4 +Ethernet32 32,33,34,35,36,37,38,39 etp5 5 +Ethernet40 40,41,42,43,44,45,46,47 etp6 6 +Ethernet48 48,49,50,51,52,53,54,55 etp7 7 +Ethernet56 56,57,58,59,60,61,62,63 etp8 8 +Ethernet64 64,65,66,67,68,69,70,71 etp9 9 +Ethernet72 72,73,74,75,76,77,78,79 etp10 10 +Ethernet80 80,81,82,83,84,85,86,87 etp11 11 +Ethernet88 88,89,90,91,92,93,94,95 etp12 12 +Ethernet96 96,97,98,99,100,101,102,103 etp13 13 +Ethernet104 104,105,106,107,108,109,110,111 etp14 14 +Ethernet112 112,113,114,115,116,117,118,119 etp15 15 +Ethernet120 120,121,122,123,124,125,126,127 etp16 16 +Ethernet128 128,129,130,131,132,133,134,135 etp17 17 +Ethernet136 136,137,138,139,140,141,142,143 etp18 18 +Ethernet144 144,145,146,147,148,149,150,151 etp19 19 +Ethernet152 152,153,154,155,156,157,158,159 etp20 20 +Ethernet160 160,161,162,163,164,165,166,167 etp21 21 +Ethernet168 168,169,170,171,172,173,174,175 etp22 22 +Ethernet176 176,177,178,179,180,181,182,183 etp23 23 +Ethernet184 184,185,186,187,188,189,190,191 etp24 24 +Ethernet192 192,193,194,195,196,197,198,199 etp25 25 +Ethernet200 200,201,202,203,204,205,206,207 etp26 26 +Ethernet208 208,209,210,211,212,213,214,215 etp27 27 +Ethernet216 216,217,218,219,220,221,222,223 etp28 28 +Ethernet224 224,225,226,227,228,229,230,231 etp29 29 +Ethernet232 232,233,234,235,236,237,238,239 etp30 30 +Ethernet240 240,241,242,243,244,245,246,247 etp31 31 +Ethernet248 248,249,250,251,252,253,254,255 etp32 32 diff --git a/device/mellanox/x86_64-mlnx_msn4700-r0/sensors.conf b/device/mellanox/x86_64-mlnx_msn4700-r0/sensors.conf index b4eaf76f2ec0..39fa9a5f93d3 100644 --- a/device/mellanox/x86_64-mlnx_msn4700-r0/sensors.conf +++ b/device/mellanox/x86_64-mlnx_msn4700-r0/sensors.conf @@ -21,83 +21,118 @@ bus "i2c-15" "i2c-1-mux (chan_id 6)" # Power controllers bus "i2c-5" "i2c-1-mux (chan_id 4)" - chip "tps53679-i2c-*-62" - label in1 "PMIC-1 PSU 12V Rail (in)" - label in2 "PMIC-1 ASIC 0.8V VCORE_MAIN Rail (out)" - ignore in3 + chip "xdpe12284-i2c-*-62" + label in1 "PMIC-1 PSU 12V Rail (in1)" + label in2 "PMIC-1 PSU 12V Rail (in2)" + label in3 "PMIC-1 ASIC 0.85V VCORE_T6_7 Rail (out)" + label in4 "PMIC-1 ASIC 1.8V T6_7 Rail (out)" label temp1 "PMIC-1 Temp 1" label temp2 "PMIC-1 Temp 2" - label power1 "PMIC-1 ASIC 0.8V VCORE_MAIN Rail Pwr (out)" - ignore power2 - label curr1 "PMIC-1 ASIC 0.8V VCORE_MAIN Rail Curr (out)" - ignore curr2 - chip "tps53679-i2c-*-64" - label in1 "PMIC-2 PSU 12V Rail (in)" - label in2 "PMIC-2 ASIC 1.8V MAIN Rail (out)" - compute in2 (1.5)*@, @/(1.5) - label in3 "PMIC-2 ASIC 1.2V MAIN Rail (out)" + label power1 "PMIC-1 ASIC 0.85V VCORE_T6_7 Rail Pwr (in)" + label power2 "PMIC-1 ASIC 1.8V T6_7 Rail Pwr (in)" + label power3 "PMIC-1 ASIC 0.85V VCORE_T6_7 Rail Pwr (out)" + label power4 "PMIC-1 ASIC 1.8V T6_7 Rail Pwr (out)" + label curr1 "PMIC-1 ASIC 0.85V VCORE_T6_7 Rail Curr (in)" + label curr2 "PMIC-1 ASIC 1.8V T6_7 Rail Curr (in)" + label curr3 "PMIC-1 ASIC 0.85V VCORE_T6_7 Rail Curr (out)" + label curr4 "PMIC-1 ASIC 1.8V T6_7 Rail Curr (out)" + chip "xdpe12284-i2c-*-64" + label in1 "PMIC-2 PSU 12V Rail (in1)" + label in2 "PMIC-2 PSU 12V Rail (in2)" + label in3 "PMIC-2 ASIC 0.85V VCORE_T6_7 Rail (out)" + label in4 "PMIC-2 ASIC 1.8V T6_7 Rail (out)" label temp1 "PMIC-2 Temp 1" label temp2 "PMIC-2 Temp 2" - label power1 "PMIC-2 ASIC 1.8V MAIN Rail Pwr (out)" - label power2 "PMIC-2 ASIC 1.2V MAIN Rail Pwr (out)" - label curr1 "PMIC-2 ASIC 1.8V MAIN Rail Curr (out)" - label curr2 "PMIC-2 ASIC 1.2V MAIN Rail Curr (out)" - chip "tps53679-i2c-*-66" - label in1 "PMIC-3 PSU 12V Rail (in)" - label in2 "PMIC-3 ASIC 0.85V VCORE_T0_1 Rail (out)" - label in3 "PMIC-3 ASIC 1.8V T0_1 Rail (out)" + label power1 "PMIC-2 ASIC 0.85V VCORE_T6_7 Rail Pwr (in)" + label power2 "PMIC-2 ASIC 1.8V T6_7 Rail Pwr (in)" + label power3 "PMIC-2 ASIC 0.85V VCORE_T6_7 Rail Pwr (out)" + label power4 "PMIC-2 ASIC 1.8V T6_7 Rail Pwr (out)" + label curr1 "PMIC-2 ASIC 0.85V VCORE_T6_7 Rail Curr (in)" + label curr2 "PMIC-2 ASIC 1.8V T6_7 Rail Curr (in)" + label curr3 "PMIC-2 ASIC 0.85V VCORE_T6_7 Rail Curr (out)" + label curr4 "PMIC-2 ASIC 1.8V T6_7 Rail Curr (out)" + chip "xdpe12284-i2c-*-66" + label in1 "PMIC-3 PSU 12V Rail (in1)" + label in2 "PMIC-3 PSU 12V Rail (in2)" + label in3 "PMIC-3 ASIC 0.85V VCORE_T6_7 Rail (out)" + label in4 "PMIC-3 ASIC 1.8V T6_7 Rail (out)" label temp1 "PMIC-3 Temp 1" label temp2 "PMIC-3 Temp 2" - label power1 "PMIC-3 ASIC 0.85V VCORE_T0_1 Rail Pwr (out)" - label power2 "PMIC-3 ASIC 1.8V T0_1 Rail Pwr (out)" - label curr1 "PMIC-3 ASIC 0.85V VCORE_T0_1 Rail Curr (out)" - label curr2 "PMIC-3 ASIC 1.8V T0_1 Rail Curr (out)" - chip "tps53679-i2c-*-68" - label in1 "PMIC-4 PSU 12V Rail (in)" - label in2 "PMIC-4 ASIC 0.85V VCORE_T2_3 Rail (out)" - label in3 "PMIC-4 ASIC 1.8V T2_3 Rail (out)" + label power1 "PMIC-3 ASIC 0.85V VCORE_T6_7 Rail Pwr (in)" + label power2 "PMIC-3 ASIC 1.8V T6_7 Rail Pwr (in)" + label power3 "PMIC-3 ASIC 0.85V VCORE_T6_7 Rail Pwr (out)" + label power4 "PMIC-3 ASIC 1.8V T6_7 Rail Pwr (out)" + label curr1 "PMIC-3 ASIC 0.85V VCORE_T6_7 Rail Curr (in)" + label curr2 "PMIC-3 ASIC 1.8V T6_7 Rail Curr (in)" + label curr3 "PMIC-3 ASIC 0.85V VCORE_T6_7 Rail Curr (out)" + label curr4 "PMIC-3 ASIC 1.8V T6_7 Rail Curr (out)" + chip "xdpe12284-i2c-*-68" + label in1 "PMIC-4 PSU 12V Rail (in1)" + label in2 "PMIC-4 PSU 12V Rail (in2)" + label in3 "PMIC-4 ASIC 0.85V VCORE_T6_7 Rail (out)" + label in4 "PMIC-4 ASIC 1.8V T6_7 Rail (out)" label temp1 "PMIC-4 Temp 1" label temp2 "PMIC-4 Temp 2" - label power1 "PMIC-4 ASIC 0.85V VCORE_T2_3 Rail Pwr (out)" - label power2 "PMIC-4 ASIC 1.8V T2_3 Rail Pwr (out)" - label curr1 "PMIC-4 ASIC 0.85V VCORE_T2_3 Rail Curr (out)" - label curr2 "PMIC-4 ASIC 1.8V T2_3 Rail Curr (out)" - chip "tps53679-i2c-*-6a" - label in1 "PMIC-5 PSU 12V Rail (in)" - label in2 "PMIC-5 ASIC 0.85V VCORE_T4_5 Rail (out)" - label in3 "PMIC-5 ASIC 1.8V T4_5 Rail (out)" + label power1 "PMIC-4 ASIC 0.85V VCORE_T6_7 Rail Pwr (in)" + label power2 "PMIC-4 ASIC 1.8V T6_7 Rail Pwr (in)" + label power3 "PMIC-4 ASIC 0.85V VCORE_T6_7 Rail Pwr (out)" + label power4 "PMIC-4 ASIC 1.8V T6_7 Rail Pwr (out)" + label curr1 "PMIC-4 ASIC 0.85V VCORE_T6_7 Rail Curr (in)" + label curr2 "PMIC-4 ASIC 1.8V T6_7 Rail Curr (in)" + label curr3 "PMIC-4 ASIC 0.85V VCORE_T6_7 Rail Curr (out)" + label curr4 "PMIC-4 ASIC 1.8V T6_7 Rail Curr (out)" + chip "xdpe12284-i2c-*-6a" + label in1 "PMIC-5 PSU 12V Rail (in1)" + label in2 "PMIC-5 PSU 12V Rail (in2)" + label in3 "PMIC-5 ASIC 0.85V VCORE_T6_7 Rail (out)" + label in4 "PMIC-5 ASIC 1.8V T6_7 Rail (out)" label temp1 "PMIC-5 Temp 1" label temp2 "PMIC-5 Temp 2" - label power1 "PMIC-5 ASIC 0.85V VCORE_T4_5 Rail Pwr (out)" - label power2 "PMIC-5 ASIC 1.8V T4_5 Rail Pwr (out)" - label curr1 "PMIC-5 ASIC 0.85V VCORE_T4_5 Rail Curr (out)" - label curr2 "PMIC-5 ASIC 1.8V T4_5 Rail Curr (out)" - chip "tps53679-i2c-*-6c" - label in1 "PMIC-6 PSU 12V Rail (in)" - label in2 "PMIC-6 ASIC 0.85V VCORE_T6_7 Rail (out)" - label in3 "PMIC-6 ASIC 1.8V T6_7 Rail (out)" + label power1 "PMIC-5 ASIC 0.85V VCORE_T6_7 Rail Pwr (in)" + label power2 "PMIC-5 ASIC 1.8V T6_7 Rail Pwr (in)" + label power3 "PMIC-5 ASIC 0.85V VCORE_T6_7 Rail Pwr (out)" + label power4 "PMIC-5 ASIC 1.8V T6_7 Rail Pwr (out)" + label curr1 "PMIC-5 ASIC 0.85V VCORE_T6_7 Rail Curr (in)" + label curr2 "PMIC-5 ASIC 1.8V T6_7 Rail Curr (in)" + label curr3 "PMIC-5 ASIC 0.85V VCORE_T6_7 Rail Curr (out)" + label curr4 "PMIC-5 ASIC 1.8V T6_7 Rail Curr (out)" + chip "xdpe12284-i2c-*-6c" + label in1 "PMIC-6 PSU 12V Rail (in1)" + label in2 "PMIC-6 PSU 12V Rail (in2)" + label in3 "PMIC-6 ASIC 0.85V VCORE_T6_7 Rail (out)" + label in4 "PMIC-6 ASIC 1.8V T6_7 Rail (out)" label temp1 "PMIC-6 Temp 1" label temp2 "PMIC-6 Temp 2" - label power1 "PMIC-6 ASIC 0.85V VCORE_T6_7 Rail Pwr (out)" - label power2 "PMIC-6 ASIC 1.8V T6_7 Rail Pwr (out)" - label curr1 "PMIC-6 ASIC 0.85V VCORE_T6_7 Rail Curr (out)" - label curr2 "PMIC-6 ASIC 1.8V T6_7 Rail Curr (out)" - chip "tps53679-i2c-*-6e" - label in1 "PMIC-7 PSU 12V Rail (in)" - label in2 "PMIC-7 ASIC 1.2V T0_3 Rail (out)" - label in3 "PMIC-7 ASIC 1.2V T4_7 Rail (out)" + label power1 "PMIC-6 ASIC 0.85V VCORE_T6_7 Rail Pwr (in)" + label power2 "PMIC-6 ASIC 1.8V T6_7 Rail Pwr (in)" + label power3 "PMIC-6 ASIC 0.85V VCORE_T6_7 Rail Pwr (out)" + label power4 "PMIC-6 ASIC 1.8V T6_7 Rail Pwr (out)" + label curr1 "PMIC-6 ASIC 0.85V VCORE_T6_7 Rail Curr (in)" + label curr2 "PMIC-6 ASIC 1.8V T6_7 Rail Curr (in)" + label curr3 "PMIC-6 ASIC 0.85V VCORE_T6_7 Rail Curr (out)" + label curr4 "PMIC-6 ASIC 1.8V T6_7 Rail Curr (out)" + chip "xdpe12284-i2c-*-6e" + label in1 "PMIC-7 PSU 12V Rail (in1)" + label in2 "PMIC-7 PSU 12V Rail (in2)" + label in3 "PMIC-7 ASIC 0.85V VCORE_T6_7 Rail (out)" + label in4 "PMIC-7 ASIC 1.8V T6_7 Rail (out)" label temp1 "PMIC-7 Temp 1" label temp2 "PMIC-7 Temp 2" - label power1 "PMIC-7 ASIC 1.2V T0_3 Rail Pwr (out)" - label power2 "PMIC-7 ASIC 1.2V T4_7 Rail Pwr (out)" - label curr1 "PMIC-7 ASIC 1.2V T0_3 Rail Curr (out)" - label curr2 "PMIC-7 ASIC 1.2V T4_7 Rail Curr (out)" + label power1 "PMIC-7 ASIC 0.85V VCORE_T6_7 Rail Pwr (in)" + label power2 "PMIC-7 ASIC 1.8V T6_7 Rail Pwr (in)" + label power3 "PMIC-7 ASIC 0.85V VCORE_T6_7 Rail Pwr (out)" + label power4 "PMIC-7 ASIC 1.8V T6_7 Rail Pwr (out)" + label curr1 "PMIC-7 ASIC 0.85V VCORE_T6_7 Rail Curr (in)" + label curr2 "PMIC-7 ASIC 1.8V T6_7 Rail Curr (in)" + label curr3 "PMIC-7 ASIC 0.85V VCORE_T6_7 Rail Curr (out)" + label curr4 "PMIC-7 ASIC 1.8V T6_7 Rail Curr (out)" bus "i2c-15" "i2c-1-mux (chan_id 6)" chip "tps53679-i2c-*-58" - label in1 "PMIC-8 PSU 12V Rail (in)" - label in2 "PMIC-8 COMEX 1.8V Rail (out)" - label in3 "PMIC-8 COMEX 1.05V Rail (out)" + label in1 "PMIC-8 PSU 12V Rail (in1)" + label in2 "PMIC-8 PSU 12V Rail (in2)" + label in3 "PMIC-8 COMEX 1.8V Rail (out)" + label in4 "PMIC-8 COMEX 1.05V Rail (out)" label temp1 "PMIC-8 Temp 1" label temp2 "PMIC-8 Temp 2" label power1 "PMIC-8 COMEX 1.8V Rail Pwr (out)" @@ -105,15 +140,16 @@ bus "i2c-15" "i2c-1-mux (chan_id 6)" label curr1 "PMIC-8 COMEX 1.8V Rail Curr (out)" label curr2 "PMIC-8 COMEX 1.05V Rail Curr (out)" chip "tps53679-i2c-*-61" - label in1 "PMIC-9 PSU 12V Rail (in)" - label in2 "PMIC-9 COMEX 1.2V Rail (out)" - ignore in3 + label in1 "PMIC-9 PSU 12V Rail (in1)" + label in2 "PMIC-9 PSU 12V Rail (in2)" + label in3 "PMIC-9 COMEX 1.2V Rail (out)" + ignore in4 label temp1 "PMIC-9 Temp 1" label temp2 "PMIC-9 Temp 2" label power1 "PMIC-9 COMEX 1.2V Rail Pwr (out)" - ignore power2 + ignore power2 label curr1 "PMIC-9 COMEX 1.2V Rail Curr (out)" - ignore curr2 + ignore curr2 # Power supplies bus "i2c-4" "i2c-1-mux (chan_id 3)" diff --git a/device/mellanox/x86_64-mlnx_msn4700-r0/thermal_policy.json b/device/mellanox/x86_64-mlnx_msn4700-r0/thermal_policy.json new file mode 120000 index 000000000000..5a25cd87f70c --- /dev/null +++ b/device/mellanox/x86_64-mlnx_msn4700-r0/thermal_policy.json @@ -0,0 +1 @@ +../x86_64-mlnx_msn2700-r0/thermal_policy.json \ No newline at end of file diff --git a/dockers/docker-database/Dockerfile.j2 b/dockers/docker-database/Dockerfile.j2 index bea4f17f2afc..d666d4a21997 100644 --- a/dockers/docker-database/Dockerfile.j2 +++ b/dockers/docker-database/Dockerfile.j2 @@ -37,6 +37,7 @@ COPY ["docker-database-init.sh", "/usr/local/bin/"] COPY ["database_config.json.j2", "/usr/share/sonic/templates/"] COPY ["database_global.json.j2", "/usr/share/sonic/templates/"] COPY ["files/supervisor-proc-exit-listener", "/usr/bin"] +COPY ["files/sysctl-net.conf", "/etc/sysctl.d/"] COPY ["critical_processes", "/etc/supervisor"] ENTRYPOINT ["/usr/local/bin/docker-database-init.sh"] diff --git a/dockers/docker-database/critical_processes b/dockers/docker-database/critical_processes index 7800f0fad3ff..53a45931dfc9 100644 --- a/dockers/docker-database/critical_processes +++ b/dockers/docker-database/critical_processes @@ -1 +1 @@ -redis +program:redis diff --git a/dockers/docker-database/database_config.json.j2 b/dockers/docker-database/database_config.json.j2 index 3383ec161144..6d116b5e1ae0 100644 --- a/dockers/docker-database/database_config.json.j2 +++ b/dockers/docker-database/database_config.json.j2 @@ -1,7 +1,7 @@ { "INSTANCES": { "redis":{ - "hostname" : "127.0.0.1", + "hostname" : "{{HOST_IP}}", "port" : 6379, "unix_socket_path" : "/var/run/redis{{NAMESPACE_ID}}/redis.sock", "persistence_for_warm_boot" : "yes" diff --git a/dockers/docker-database/docker-database-init.sh b/dockers/docker-database/docker-database-init.sh index 5dae34d8f616..645a7d99272a 100755 --- a/dockers/docker-database/docker-database-init.sh +++ b/dockers/docker-database/docker-database-init.sh @@ -1,12 +1,29 @@ #!/usr/bin/env bash +# For linux host namespace, in both single and multi ASIC platform use the loopback interface +# For other namespaces, use eth0 interface which is connected to the docker0 bridge in the host. +if [[ $NAMESPACE_ID == "" ]] +then + INTFC=lo +else + INTFC=eth0 +fi + +# Get the ip address of the interface +# if the ip address was not retrieved correctly, put localhost(127.0.0.1) as the default. +host_ip=$(ip -4 -o addr show $INTFC | awk '{print $4}' | cut -d'/' -f1 | head -1) +if [[ $host_ip == "" ]] +then + host_ip=127.0.0.1 +fi + REDIS_DIR=/var/run/redis$NAMESPACE_ID mkdir -p $REDIS_DIR/sonic-db if [ -f /etc/sonic/database_config$NAMESPACE_ID.json ]; then cp /etc/sonic/database_config$NAMESPACE_ID.json $REDIS_DIR/sonic-db/database_config.json else - j2 /usr/share/sonic/templates/database_config.json.j2 > $REDIS_DIR/sonic-db/database_config.json + HOST_IP=$host_ip j2 /usr/share/sonic/templates/database_config.json.j2 > $REDIS_DIR/sonic-db/database_config.json fi mkdir -p /etc/supervisor/conf.d/ diff --git a/dockers/docker-database/supervisord.conf.j2 b/dockers/docker-database/supervisord.conf.j2 index 9e855527edba..efeedd0439c6 100644 --- a/dockers/docker-database/supervisord.conf.j2 +++ b/dockers/docker-database/supervisord.conf.j2 @@ -20,7 +20,12 @@ stderr_logfile=syslog {% if INSTANCES %} {% for redis_inst, redis_items in INSTANCES.iteritems() %} [program: {{ redis_inst }}] -command=/bin/bash -c "{ [[ -s /var/lib/{{ redis_inst }}/dump.rdb ]] || rm -f /var/lib/{{ redis_inst }}/dump.rdb; } && mkdir -p /var/lib/{{ redis_inst }} && exec /usr/bin/redis-server /etc/redis/redis.conf --port {{ redis_items['port'] }} --unixsocket {{ redis_items['unix_socket_path'] }} --pidfile /var/run/redis/{{ redis_inst }}.pid --dir /var/lib/{{ redis_inst }}" +{% if redis_items['hostname'] != '127.0.0.1' %} +{%- set LOOPBACK_IP = '127.0.0.1' -%} +{%- else -%} +{%- set LOOPBACK_IP = '' -%} +{%- endif -%} +command=/bin/bash -c "{ [[ -s /var/lib/{{ redis_inst }}/dump.rdb ]] || rm -f /var/lib/{{ redis_inst }}/dump.rdb; } && mkdir -p /var/lib/{{ redis_inst }} && exec /usr/bin/redis-server /etc/redis/redis.conf --bind {{ LOOPBACK_IP }} {{ redis_items['hostname'] }} --port {{ redis_items['port'] }} --unixsocket {{ redis_items['unix_socket_path'] }} --pidfile /var/run/redis/{{ redis_inst }}.pid --dir /var/lib/{{ redis_inst }}" priority=2 autostart=true autorestart=false diff --git a/dockers/docker-dhcp-relay/critical_processes b/dockers/docker-dhcp-relay/critical_processes index ddb183963a67..855851bf2d68 100644 --- a/dockers/docker-dhcp-relay/critical_processes +++ b/dockers/docker-dhcp-relay/critical_processes @@ -1 +1 @@ -isc-dhcp-relay +group:isc-dhcp-relay diff --git a/dockers/docker-fpm-frr/Dockerfile.j2 b/dockers/docker-fpm-frr/Dockerfile.j2 index ea8fdea5b5da..04f3e4416787 100644 --- a/dockers/docker-fpm-frr/Dockerfile.j2 +++ b/dockers/docker-fpm-frr/Dockerfile.j2 @@ -35,16 +35,24 @@ RUN useradd -u ${frr_user_uid} -g ${frr_user_gid} -M -s /bin/false frr {{ install_debian_packages(docker_fpm_frr_debs.split(' ')) }} {%- endif %} +{% if docker_fpm_frr_whls.strip() %} +# Copy locally-built Python wheel dependencies +{{ copy_files("python-wheels/", docker_fpm_frr_whls.split(' '), "/python-wheels/") }} + +# Install locally-built Python wheel dependencies +{{ install_python_wheels(docker_fpm_frr_whls.split(' ')) }} +{% endif %} + RUN chown -R ${frr_user_uid}:${frr_user_gid} /etc/frr/ # Clean up RUN apt-get clean -y && \ apt-get autoclean -y && \ apt-get autoremove -y && \ - rm -rf /debs ~/.cache + rm -rf /debs ~/.cache /python-wheels COPY ["frr", "/usr/share/sonic/templates"] -COPY ["bgpcfgd", "start.sh", "/usr/bin/"] +COPY ["start.sh", "/usr/bin/"] COPY ["supervisord.conf", "/etc/supervisor/conf.d/"] COPY ["snmp.conf", "/etc/snmp/frr.conf"] COPY ["TSA", "/usr/bin/TSA"] diff --git a/dockers/docker-fpm-frr/base_image_files/monit_bgp b/dockers/docker-fpm-frr/base_image_files/monit_bgp index 5b943ea7c0bb..5dbb794c346b 100644 --- a/dockers/docker-fpm-frr/base_image_files/monit_bgp +++ b/dockers/docker-fpm-frr/base_image_files/monit_bgp @@ -19,5 +19,5 @@ check process bgpd matching "/usr/lib/frr/bgpd" check process staticd matching "/usr/lib/frr/staticd" if does not exist for 5 times within 5 cycles then alert -check process bgpcfgd matching "python /usr/bin/bgpcfgd" +check process bgpcfgd matching "python /usr/local/bin/bgpcfgd" if does not exist for 5 times within 5 cycles then alert diff --git a/dockers/docker-fpm-frr/critical_processes b/dockers/docker-fpm-frr/critical_processes index 8ea09e1bb538..2631fee15e66 100644 --- a/dockers/docker-fpm-frr/critical_processes +++ b/dockers/docker-fpm-frr/critical_processes @@ -1,5 +1,5 @@ -zebra -staticd -bgpd -fpmsyncd -bgpcfgd +program:zebra +program:staticd +program:bgpd +program:fpmsyncd +program:bgpcfgd diff --git a/dockers/docker-fpm-frr/frr/bgpd/bgpd.main.conf.j2 b/dockers/docker-fpm-frr/frr/bgpd/bgpd.main.conf.j2 index 503c37e9be14..ef98dcf9f16a 100644 --- a/dockers/docker-fpm-frr/frr/bgpd/bgpd.main.conf.j2 +++ b/dockers/docker-fpm-frr/frr/bgpd/bgpd.main.conf.j2 @@ -1,3 +1,4 @@ +{% from "common/functions.conf.j2" import get_ipv4_loopback_address, get_ipv6_loopback_address %} ! ! template: bgpd/bgpd.main.conf.j2 ! @@ -63,7 +64,12 @@ router bgp {{ DEVICE_METADATA['localhost']['bgp_asn'] }} ! ! {% if DEVICE_METADATA['localhost']['sub_role'] == 'FrontEnd' %} - redistribute connected route-map HIDE_INTERNAL + address-family ipv4 + redistribute connected route-map HIDE_INTERNAL + exit-address-family + address-family ipv6 + redistribute connected route-map HIDE_INTERNAL + exit-address-family {% endif %} ! {% if constants.bgp.maximum_paths.enabled is defined and constants.bgp.maximum_paths.enabled %} diff --git a/dockers/docker-fpm-frr/frr/bgpd/templates/dynamic/instance.conf.j2 b/dockers/docker-fpm-frr/frr/bgpd/templates/dynamic/instance.conf.j2 index efb1546dac4b..5082b75005c2 100644 --- a/dockers/docker-fpm-frr/frr/bgpd/templates/dynamic/instance.conf.j2 +++ b/dockers/docker-fpm-frr/frr/bgpd/templates/dynamic/instance.conf.j2 @@ -34,5 +34,5 @@ neighbor {{ bgp_session['name'] }} activate exit-address-family ! -! end of template: bgpd/templates/BGP_SPEAKER/instance.conf.j2 +! end of template: bgpd/templates/dynamic/instance.conf.j2 ! diff --git a/dockers/docker-fpm-frr/frr/bgpd/templates/general/instance.conf.j2 b/dockers/docker-fpm-frr/frr/bgpd/templates/general/instance.conf.j2 index aed32d291c76..e4422a771664 100644 --- a/dockers/docker-fpm-frr/frr/bgpd/templates/general/instance.conf.j2 +++ b/dockers/docker-fpm-frr/frr/bgpd/templates/general/instance.conf.j2 @@ -6,7 +6,7 @@ {# set the bgp neighbor timers if they have not default values #} {% if (bgp_session['keepalive'] is defined and bgp_session['keepalive'] | int != 60) or (bgp_session['holdtime'] is defined and bgp_session['holdtime'] | int != 180) %} - neighbor {{ neighbor_addr }} timers {{ bgp_session['keepalive'] }} {{ bgp_session['holdtime'] }} + neighbor {{ neighbor_addr }} timers {{ bgp_session['keepalive'] | default("60") }} {{ bgp_session['holdtime'] | default("180") }} {% endif %} ! {% if bgp_session.has_key('admin_status') and bgp_session['admin_status'] == 'down' or not bgp_session.has_key('admin_status') and CONFIG_DB__DEVICE_METADATA['localhost'].has_key('default_bgp_status') and CONFIG_DB__DEVICE_METADATA['localhost']['default_bgp_status'] == 'down' %} @@ -15,36 +15,43 @@ ! {% if neighbor_addr | ipv4 %} address-family ipv4 -{% if 'ASIC' in bgp_session['name'] %} +{% if 'ASIC' in bgp_session['name'] %} neighbor {{ neighbor_addr }} peer-group PEER_V4_INT -{% else %} +{% else %} neighbor {{ neighbor_addr }} peer-group PEER_V4 {% endif %} +! {% if CONFIG_DB__DEVICE_METADATA['localhost']['sub_role'] == 'BackEnd' %} neighbor {{ neighbor_addr }} route-map FROM_BGP_PEER_V4_INT in {% endif %} +! {% elif neighbor_addr | ipv6 %} address-family ipv6 -{% if 'ASIC' in bgp_session['name'] %} +{% if 'ASIC' in bgp_session['name'] %} neighbor {{ neighbor_addr }} peer-group PEER_V6_INT -{% else %} +{% else %} neighbor {{ neighbor_addr }} peer-group PEER_V6 {% endif %} +! {% if CONFIG_DB__DEVICE_METADATA['localhost']['sub_role'] == 'BackEnd' %} neighbor {{ neighbor_addr }} route-map FROM_BGP_PEER_V6_INT in {% endif %} {% endif %} ! -{% if bgp_session['rrclient'] | int != 0 %} +{% if bgp_session.has_key('rrclient') and bgp_session['rrclient'] | int != 0 %} neighbor {{ neighbor_addr }} route-reflector-client -{% endif %} +{% endif %} ! -{% if bgp_session['nhopself'] | int != 0 %} +{% if bgp_session.has_key('nhopself') and bgp_session['nhopself'] | int != 0 %} neighbor {{ neighbor_addr }} next-hop-self -{% endif %} -{% if 'ASIC' in bgp_session['name'] %} +{% endif %} +! +{% if 'ASIC' in bgp_session['name'] %} neighbor {{ neighbor_addr }} next-hop-self force -{% endif %} +{% endif %} +! + neighbor {{ neighbor_addr }} activate + exit-address-family ! {% if bgp_session["asn"] == bgp_asn and CONFIG_DB__DEVICE_METADATA['localhost']['type'] == "SpineChassisFrontendRouter" %} address-family l2vpn evpn @@ -52,8 +59,6 @@ advertise-all-vni exit-address-family {% endif %} - neighbor {{ neighbor_addr }} activate - exit-address-family ! ! end of template: bgpd/templates/general/instance.conf.j2 ! diff --git a/dockers/docker-fpm-frr/start.sh b/dockers/docker-fpm-frr/start.sh index aa72b36e5ce3..ab56cb42b2f1 100755 --- a/dockers/docker-fpm-frr/start.sh +++ b/dockers/docker-fpm-frr/start.sh @@ -4,6 +4,29 @@ mkdir -p /etc/frr CONFIG_TYPE=`sonic-cfggen -d -v 'DEVICE_METADATA["localhost"]["docker_routing_config_mode"]'` +if [[ ! -z "$NAMESPACE_ID" ]]; then + # FRR is not running in host namespace so we need to delete + # default gw kernel route added by docker network via eth0 and add it back + # with higher administrative distance so that default route learnt + # by FRR becomes best route if/when available + GATEWAY_IP=$(ip route show 0.0.0.0/0 dev eth0 | awk '{print $3}') + #Check if docker default route is there + if [[ ! -z "$GATEWAY_IP" ]]; then + ip route del 0.0.0.0/0 dev eth0 + #Make sure route is deleted + CHECK_GATEWAY_IP=$(ip route show 0.0.0.0/0 dev eth0 | awk '{print $3}') + if [[ -z "$CHECK_GATEWAY_IP" ]]; then + # Ref: http://docs.frrouting.org/en/latest/zebra.html#zebra-vrf + # Zebra does treat Kernel routes as special case for the purposes of Admin Distance. \ + # Upon learning about a route that is not originated by FRR we read the metric value as a uint32_t. + # The top byte of the value is interpreted as the Administrative Distance and + # the low three bytes are read in as the metric. + # so here we are programming administrative distance of 210 (210 << 24) > 200 (for routes learnt via IBGP) + ip route add 0.0.0.0/0 via $GATEWAY_IP dev eth0 metric 3523215360 + fi + fi +fi + if [ -z "$CONFIG_TYPE" ] || [ "$CONFIG_TYPE" == "separated" ]; then sonic-cfggen -d -t /usr/share/sonic/templates/bgpd/bgpd.conf.j2 -y /etc/sonic/constants.yml > /etc/frr/bgpd.conf sonic-cfggen -d -t /usr/share/sonic/templates/zebra/zebra.conf.j2 > /etc/frr/zebra.conf diff --git a/dockers/docker-fpm-frr/supervisord.conf b/dockers/docker-fpm-frr/supervisord.conf index 3e544b64b296..316662cdd0be 100644 --- a/dockers/docker-fpm-frr/supervisord.conf +++ b/dockers/docker-fpm-frr/supervisord.conf @@ -64,8 +64,8 @@ startsecs=0 stdout_logfile=syslog stderr_logfile=syslog -[program:vtysh_b] -command=/usr/bin/vtysh -b +[program:fpmsyncd] +command=fpmsyncd priority=6 autostart=false autorestart=false @@ -73,8 +73,17 @@ startsecs=0 stdout_logfile=syslog stderr_logfile=syslog -[program:fpmsyncd] -command=fpmsyncd +[program:bgpcfgd] +command=/usr/local/bin/bgpcfgd +priority=6 +autostart=false +autorestart=false +startsecs=0 +stdout_logfile=syslog +stderr_logfile=syslog + +[program:vtysh_b] +command=/usr/bin/vtysh -b priority=6 autostart=false autorestart=false diff --git a/dockers/docker-fpm-gobgp/critical_processes b/dockers/docker-fpm-gobgp/critical_processes index 2a9e47831e0d..789f4685244a 100644 --- a/dockers/docker-fpm-gobgp/critical_processes +++ b/dockers/docker-fpm-gobgp/critical_processes @@ -1,2 +1,2 @@ -gobgpd -fpmsyncd +program:gobgpd +program:fpmsyncd diff --git a/dockers/docker-fpm-quagga/critical_processes b/dockers/docker-fpm-quagga/critical_processes index f151af9c4bdd..2dceb501e3e5 100644 --- a/dockers/docker-fpm-quagga/critical_processes +++ b/dockers/docker-fpm-quagga/critical_processes @@ -1,4 +1,4 @@ -zebra -bgpd -fpmsyncd -bgpcfgd +program:zebra +program:bgpd +program:fpmsyncd +program:bgpcfgd diff --git a/dockers/docker-lldp-sv2/critical_processes b/dockers/docker-lldp-sv2/critical_processes index b845b70bb3f7..90586536a4f5 100644 --- a/dockers/docker-lldp-sv2/critical_processes +++ b/dockers/docker-lldp-sv2/critical_processes @@ -1,3 +1,3 @@ -lldpd -lldp-syncd -lldpmgrd +program:lldpd +program:lldp-syncd +program:lldpmgrd diff --git a/dockers/docker-nat/critical_processes b/dockers/docker-nat/critical_processes index d442976143f1..5edc5eedc3d5 100644 --- a/dockers/docker-nat/critical_processes +++ b/dockers/docker-nat/critical_processes @@ -1,2 +1,2 @@ -natmgrd -natsyncd +program:natmgrd +program:natsyncd diff --git a/dockers/docker-orchagent/critical_processes b/dockers/docker-orchagent/critical_processes index 7fd8a516520c..99f501e2cc03 100644 --- a/dockers/docker-orchagent/critical_processes +++ b/dockers/docker-orchagent/critical_processes @@ -1,10 +1,10 @@ -orchagent -portsyncd -neighsyncd -vlanmgrd -intfmgrd -portmgrd -buffermgrd -vrfmgrd -nbrmgrd -vxlanmgrd +program:orchagent +program:portsyncd +program:neighsyncd +program:vlanmgrd +program:intfmgrd +program:portmgrd +program:buffermgrd +program:vrfmgrd +program:nbrmgrd +program:vxlanmgrd diff --git a/dockers/docker-orchagent/swssconfig.sh b/dockers/docker-orchagent/swssconfig.sh index 856b3bcd0e41..0743d95f8eb6 100755 --- a/dockers/docker-orchagent/swssconfig.sh +++ b/dockers/docker-orchagent/swssconfig.sh @@ -8,19 +8,19 @@ function fast_reboot { if [[ -f /fdb.json ]]; then swssconfig /fdb.json - rm -f /fdb.json + mv -f /fdb.json /fdb.json.1 fi if [[ -f /arp.json ]]; then swssconfig /arp.json - rm -f /arp.json + mv -f /arp.json /arp.json.1 fi if [[ -f /default_routes.json ]]; then swssconfig /default_routes.json - rm -f /default_routes.json + mv -f /default_routes.json /default_routes.json.1 fi ;; diff --git a/dockers/docker-platform-monitor/Dockerfile.j2 b/dockers/docker-platform-monitor/Dockerfile.j2 index 61374af7d544..2ce609fff178 100755 --- a/dockers/docker-platform-monitor/Dockerfile.j2 +++ b/dockers/docker-platform-monitor/Dockerfile.j2 @@ -18,7 +18,8 @@ RUN apt-get update && \ rrdtool \ python-smbus \ ethtool \ - dmidecode && \ + dmidecode \ + i2c-tools && \ pip install enum34 {% if docker_platform_monitor_debs.strip() -%} diff --git a/dockers/docker-platform-monitor/critical_processes b/dockers/docker-platform-monitor/critical_processes index 9798dffc4c27..3165d13ecdbc 100644 --- a/dockers/docker-platform-monitor/critical_processes +++ b/dockers/docker-platform-monitor/critical_processes @@ -1,3 +1,3 @@ -ledd -xcvrd -psud +program:ledd +program:xcvrd +program:psud diff --git a/dockers/docker-platform-monitor/docker-pmon.supervisord.conf.j2 b/dockers/docker-platform-monitor/docker-pmon.supervisord.conf.j2 index 5d848776f2a7..d33b4e7c3fe7 100644 --- a/dockers/docker-platform-monitor/docker-pmon.supervisord.conf.j2 +++ b/dockers/docker-platform-monitor/docker-pmon.supervisord.conf.j2 @@ -91,3 +91,14 @@ stdout_logfile=syslog stderr_logfile=syslog startsecs=10 {% endif %} + +{% if not skip_thermalctld %} +[program:thermalctld] +command=/usr/bin/thermalctld +priority=9 +autostart=false +autorestart=true +stdout_logfile=syslog +stderr_logfile=syslog +startsecs=0 +{% endif %} diff --git a/dockers/docker-platform-monitor/start.sh.j2 b/dockers/docker-platform-monitor/start.sh.j2 index 5b4fe4588819..03e0b49b8c4d 100644 --- a/dockers/docker-platform-monitor/start.sh.j2 +++ b/dockers/docker-platform-monitor/start.sh.j2 @@ -75,3 +75,7 @@ supervisorctl start psud supervisorctl start syseepromd {% endif %} +{% if not skip_thermalctld %} +supervisorctl start thermalctld +{% endif %} + diff --git a/dockers/docker-router-advertiser/critical_processes b/dockers/docker-router-advertiser/critical_processes index 238a0346ac9f..a343765f78e0 100644 --- a/dockers/docker-router-advertiser/critical_processes +++ b/dockers/docker-router-advertiser/critical_processes @@ -1 +1 @@ -radvd +program:radvd diff --git a/dockers/docker-sflow/critical_processes b/dockers/docker-sflow/critical_processes index 5b24e2d8e1da..8180f8ad1c37 100644 --- a/dockers/docker-sflow/critical_processes +++ b/dockers/docker-sflow/critical_processes @@ -1 +1 @@ -sflowmgrd +program:sflowmgrd diff --git a/dockers/docker-snmp-sv2/critical_processes b/dockers/docker-snmp-sv2/critical_processes index e6039c5b9840..cff479d7fa11 100644 --- a/dockers/docker-snmp-sv2/critical_processes +++ b/dockers/docker-snmp-sv2/critical_processes @@ -1,2 +1,2 @@ -snmpd -snmp-subagent +program:snmpd +program:snmp-subagent diff --git a/dockers/docker-sonic-mgmt/Dockerfile.j2 b/dockers/docker-sonic-mgmt/Dockerfile.j2 index d24df1ca5d77..3c2bbff2504e 100644 --- a/dockers/docker-sonic-mgmt/Dockerfile.j2 +++ b/dockers/docker-sonic-mgmt/Dockerfile.j2 @@ -2,56 +2,69 @@ FROM ubuntu:16.04 ENV DEBIAN_FRONTEND=noninteractive -RUN apt-get update -RUN apt-get install -y \ - openssh-server \ - gcc \ - vim \ - make \ - git \ - sudo \ - python \ - python-dev \ - python-cffi \ - libffi-dev \ - libssl-dev \ - sshpass \ - libxml2 \ - libxslt1-dev \ - python-setuptools \ - build-essential \ - curl \ - cmake \ - tcpdump \ - python-dev \ - python-scapy - -# For JNLP launcher -RUN apt-get install -y default-jre - -# For syslog test -RUN apt-get install -y rsyslog psmisc - -# Remove cffi 1.5.2, will install 1.10.0 by pip later -RUN apt-get purge -y python-cffi python-cffi-backend -# Remove pycparser 2.14, will install >=2.17 by pip later -RUN apt-get purge -y python-ply python-pycparser - -RUN easy_install pip - -RUN pip install ipaddr \ +RUN apt-get update && apt-get install -y build-essential \ + cmake \ + curl \ + default-jre \ + gcc \ + git \ + inetutils-ping \ + libffi-dev \ + libssl-dev \ + libxml2 \ + libxslt1-dev \ + make \ + openssh-server \ + psmisc \ + python \ + python-dev \ + python-scapy \ + python-setuptools \ + rsyslog \ + snmp \ + sshpass \ + sudo \ + tcpdump \ + telnet \ + vim + +RUN easy_install pip==20.1.1 + +RUN pip install cffi==1.10.0 \ + "cryptography>=2.5" \ + "future>=0.16.0" \ + gitpython \ + ipaddr \ + ipython==5.4.1 \ + ixnetwork-restpy==1.0.52 \ + jinja2==2.7.2 \ + jsonpatch \ lxml \ - netaddr \ natsort \ - six \ + netaddr \ + netmiko==2.4.2 \ + paramiko==2.7.1 \ + passlib \ pexpect \ + prettytable \ + psutil \ pyasn1==0.1.9 \ + pycryptodome \ + pyfiglet \ + pylint==1.8.1 \ + pyro4 \ pysnmp==4.2.5 \ - jinja2==2.7.2 \ - cffi==1.10.0 \ - paramiko==2.1.2 \ - passlib \ - ipython==5.4.1 \ + pytest-repeat \ + pytest-html \ + pytest-xdist==1.28.0 \ + pytest==4.6.5 \ + redis \ + requests \ + rpyc \ + six \ + tabulate \ + textfsm \ + virtualenv \ && git clone https://github.com/p4lang/scapy-vxlan.git \ && cd scapy-vxlan \ && python setup.py install \ @@ -71,12 +84,24 @@ RUN pip install ipaddr \ && pip install nnpy \ && pip install dpkt +# Install docker-ce-cli +RUN apt-get update \ + && apt-get install -y \ + apt-transport-https \ + ca-certificates \ + curl \ + gnupg-agent \ + software-properties-common \ + && curl -fsSL https://download.docker.com/linux/ubuntu/gpg | apt-key add - \ + && add-apt-repository "deb [arch=amd64] https://download.docker.com/linux/ubuntu $(lsb_release -cs) stable" \ + && apt-get update \ + && apt-get install -y docker-ce-cli + # Install Microsoft Azure Kusto Library for Python RUN pip install azure-kusto-data==0.0.13 \ azure-kusto-ingest==0.0.13 -# Install pytest-ansible module -RUN pip install pytest-ansible==2.2.2 +RUN pip install wheel==0.33.6 ## Copy and install sonic-mgmt docker dependencies COPY \ @@ -90,7 +115,17 @@ RUN dpkg -i \ debs/{{ deb }}{{' '}} {%- endfor %} -RUN pip install ansible==2.8.7 +RUN pip install ansible==2.8.12 + +RUN pip install pysubnettree + +# Install pytest-ansible module with 'become', 'become_user' parameters support +RUN git clone https://github.com/ansible/pytest-ansible.git \ + && cd pytest-ansible \ + && git checkout d33c025f070a9c870220a157cc5a999fda68de44 \ + && python setup.py install \ + && cd .. \ + && rm -fr pytest-ansible RUN mkdir /var/run/sshd EXPOSE 22 @@ -103,6 +138,7 @@ ARG hostname ENV BUILD_HOSTNAME $hostname ENV USER $user +ENV CC=gcc CPP=cpp CXX=c++ LDSHARED="gcc -pthread -shared" PYMSSQL_BUILD_WITH_BUNDLED_FREETDS=1 RUN groupadd -f -r -g $guid g$user @@ -130,4 +166,6 @@ RUN azure-cli_bundle_*/installer # TODO: if azure-cli contains newer version azure-keyvault, remove this RUN ~/lib/azure-cli/bin/python -m pip install azure-keyvault==0.3.7 -U -RUN git clone https://github.com/Azure/sonic-mgmt +# Install Virtual Environment +RUN python -m virtualenv --system-site-packages env-201811 +RUN env-201811/bin/pip install ansible==2.0.0.2 diff --git a/dockers/docker-sonic-restapi/critical_processes b/dockers/docker-sonic-restapi/critical_processes index 3106eaa9410a..455b7fb2fa46 100644 --- a/dockers/docker-sonic-restapi/critical_processes +++ b/dockers/docker-sonic-restapi/critical_processes @@ -1 +1 @@ -restapi +program:restapi diff --git a/dockers/docker-sonic-telemetry/critical_processes b/dockers/docker-sonic-telemetry/critical_processes index d6953dd0c883..612a94d9edac 100644 --- a/dockers/docker-sonic-telemetry/critical_processes +++ b/dockers/docker-sonic-telemetry/critical_processes @@ -1,2 +1,2 @@ -telemetry -dialout +program:telemetry +program:dialout diff --git a/dockers/docker-teamd/critical_processes b/dockers/docker-teamd/critical_processes index b5c543df050d..286d6aef4c7a 100644 --- a/dockers/docker-teamd/critical_processes +++ b/dockers/docker-teamd/critical_processes @@ -1,2 +1,2 @@ -teammgrd -teamsyncd +program:teammgrd +program:teamsyncd diff --git a/files/build_scripts/mask_disabled_services.py b/files/build_scripts/mask_disabled_services.py new file mode 100755 index 000000000000..e2597ac686f1 --- /dev/null +++ b/files/build_scripts/mask_disabled_services.py @@ -0,0 +1,13 @@ +#!/usr/bin/env python3 + +import json +import subprocess + +INIT_CFG_FILE_PATH = '/etc/sonic/init_cfg.json' + +with open(INIT_CFG_FILE_PATH) as init_cfg_file: + init_cfg = json.load(init_cfg_file) + if 'FEATURE' in init_cfg: + for feature_name, feature_props in init_cfg['FEATURE'].items(): + if 'status' in feature_props and feature_props['status'] == 'disabled': + subprocess.run(['systemctl', 'mask', '{}.service'.format(feature_name)]) diff --git a/files/build_templates/docker_image_ctl.j2 b/files/build_templates/docker_image_ctl.j2 index 3d4cb30569b8..e8cc666779d8 100644 --- a/files/build_templates/docker_image_ctl.j2 +++ b/files/build_templates/docker_image_ctl.j2 @@ -27,6 +27,22 @@ link_namespace() { } {%- endif %} +function updateSyslogConf() +{ + # On multiNPU platforms, change the syslog target ip to docker0 ip to allow logs from containers + # running on the namespace to reach the rsyslog service running on the host + # Also update the container name + if [[ ($NUM_ASIC -gt 1) ]]; then + TARGET_IP=$(docker network inspect bridge --format={{ "'{{(index .IPAM.Config 0).Gateway}}'" }}) + CONTAINER_NAME="{{docker_container_name}}$DEV" + TMP_FILE="/tmp/rsyslog.$CONTAINER_NAME.conf" + + sonic-cfggen -t /usr/share/sonic/templates/rsyslog-container.conf.j2 -a "{\"target_ip\": \"$TARGET_IP\", \"container_name\": \"$CONTAINER_NAME\" }" > $TMP_FILE + docker cp $TMP_FILE {{docker_container_name}}$DEV:/etc/rsyslog.conf + rm -rf $TMP_FILE + fi +} + function getMountPoint() { echo $1 | python -c "import sys, json, os; mnts = [x for x in json.load(sys.stdin)[0]['Mounts'] if x['Destination'] == '/usr/share/sonic/hwsku']; print '' if len(mnts) == 0 else os.path.basename(mnts[0]['Source'])" 2>/dev/null @@ -68,13 +84,14 @@ function preStartAction() {%- else %} : # nothing {%- endif %} + updateSyslogConf } function postStartAction() { {%- if docker_container_name == "database" %} if [ "$DEV" ]; then - docker exec -i database$DEV sysctl -w net.ipv6.conf.all.disable_ipv6=0 + docker exec -i database$DEV sysctl --system -e link_namespace $DEV fi @@ -295,11 +312,9 @@ start() { --tmpfs /tmp \ {%- endif %} --tmpfs /var/tmp \ -{%- if docker_container_name == "database" %} --env "NAMESPACE_ID"="$DEV" \ --env "NAMESPACE_PREFIX"="$NAMESPACE_PREFIX" \ --env "NAMESPACE_COUNT"=$NUM_ASIC \ -{%- endif %} --name={{docker_container_name}}$DEV {{docker_image_name}}:latest || { echo "Failed to docker run" >&1 exit 4 diff --git a/files/build_templates/init_cfg.json.j2 b/files/build_templates/init_cfg.json.j2 index c187e02762b8..7a0a8d15880d 100644 --- a/files/build_templates/init_cfg.json.j2 +++ b/files/build_templates/init_cfg.json.j2 @@ -18,9 +18,9 @@ } }, "FEATURE": { -{%- for feature in ["sflow", "telemetry"] %} +{%- for feature, status in [("sflow", "disabled"), ("telemetry", "enabled")] %} "{{feature}}": { - "status": "disabled" + "status": "{{status}}" }{% if not loop.last %},{% endif -%} {% endfor %} }, diff --git a/files/build_templates/sonic_debian_extension.j2 b/files/build_templates/sonic_debian_extension.j2 index 00ab059cf3ef..fb6f104ca856 100644 --- a/files/build_templates/sonic_debian_extension.j2 +++ b/files/build_templates/sonic_debian_extension.j2 @@ -27,12 +27,14 @@ set -x -e CONFIGURED_ARCH=$([ -f .arch ] && cat .arch || echo amd64) . functions.sh +BUILD_SCRIPTS_DIR=files/build_scripts BUILD_TEMPLATES=files/build_templates IMAGE_CONFIGS=files/image_config SCRIPTS_DIR=files/scripts # Define target fold macro FILESYSTEM_ROOT_USR="$FILESYSTEM_ROOT/usr" +FILESYSTEM_ROOT_USR_LIB_SYSTEMD_SYSTEM="$FILESYSTEM_ROOT/usr/lib/systemd/system" FILESYSTEM_ROOT_USR_SHARE="$FILESYSTEM_ROOT_USR/share" FILESYSTEM_ROOT_USR_SHARE_SONIC="$FILESYSTEM_ROOT_USR_SHARE/sonic" FILESYSTEM_ROOT_USR_SHARE_SONIC_TEMPLATES="$FILESYSTEM_ROOT_USR_SHARE_SONIC/templates" @@ -76,6 +78,9 @@ sudo mkdir -p $FILESYSTEM_ROOT/etc/sonic/ sudo mkdir -p $FILESYSTEM_ROOT/etc/modprobe.d/ sudo mkdir -p $FILESYSTEM_ROOT/var/cache/sonic/ sudo mkdir -p $FILESYSTEM_ROOT_USR_SHARE_SONIC_TEMPLATES/ +# This is needed for Stretch and might not be needed for Buster where Linux create this directory by default. +# Keeping it generic. It should not harm anyways. +sudo mkdir -p $FILESYSTEM_ROOT_USR_LIB_SYSTEMD_SYSTEM # Install a more recent version of ifupdown2 (and its dependencies via 'apt-get -y install -f') sudo dpkg --root=$FILESYSTEM_ROOT -i $debs_path/ifupdown2_*.deb || \ @@ -190,20 +195,21 @@ sudo chmod 600 $FILESYSTEM_ROOT/etc/monit/conf.d/* sudo cp -f $IMAGE_CONFIGS/cron.d/* $FILESYSTEM_ROOT/etc/cron.d/ # Copy NTP configuration files and templates -sudo cp $IMAGE_CONFIGS/ntp/ntp-config.service $FILESYSTEM_ROOT/etc/systemd/system/ +sudo cp $IMAGE_CONFIGS/ntp/ntp-config.service $FILESYSTEM_ROOT_USR_LIB_SYSTEMD_SYSTEM echo "ntp-config.service" | sudo tee -a $GENERATED_SERVICE_FILE sudo cp $IMAGE_CONFIGS/ntp/ntp-config.sh $FILESYSTEM_ROOT/usr/bin/ sudo cp $IMAGE_CONFIGS/ntp/ntp.conf.j2 $FILESYSTEM_ROOT_USR_SHARE_SONIC_TEMPLATES/ # Copy warmboot-finalizer files sudo LANG=C cp $IMAGE_CONFIGS/warmboot-finalizer/finalize-warmboot.sh $FILESYSTEM_ROOT/usr/local/bin/finalize-warmboot.sh -sudo LANG=C cp $IMAGE_CONFIGS/warmboot-finalizer/warmboot-finalizer.service $FILESYSTEM_ROOT/etc/systemd/system/ +sudo LANG=C cp $IMAGE_CONFIGS/warmboot-finalizer/warmboot-finalizer.service $FILESYSTEM_ROOT_USR_LIB_SYSTEMD_SYSTEM echo "warmboot-finalizer.service" | sudo tee -a $GENERATED_SERVICE_FILE # Copy rsyslog configuration files and templates -sudo cp $IMAGE_CONFIGS/rsyslog/rsyslog-config.service $FILESYSTEM_ROOT/etc/systemd/system/ +sudo cp $IMAGE_CONFIGS/rsyslog/rsyslog-config.service $FILESYSTEM_ROOT_USR_LIB_SYSTEMD_SYSTEM sudo cp $IMAGE_CONFIGS/rsyslog/rsyslog-config.sh $FILESYSTEM_ROOT/usr/bin/ sudo cp $IMAGE_CONFIGS/rsyslog/rsyslog.conf.j2 $FILESYSTEM_ROOT_USR_SHARE_SONIC_TEMPLATES/ +sudo cp $IMAGE_CONFIGS/rsyslog/rsyslog-container.conf.j2 $FILESYSTEM_ROOT_USR_SHARE_SONIC_TEMPLATES/ sudo cp $IMAGE_CONFIGS/rsyslog/rsyslog.d/* $FILESYSTEM_ROOT/etc/rsyslog.d/ echo "rsyslog-config.service" | sudo tee -a $GENERATED_SERVICE_FILE @@ -214,7 +220,7 @@ sudo cp -f $IMAGE_CONFIGS/logrotate/logrotate.d/* $FILESYSTEM_ROOT/etc/logrotate sudo cp -f $IMAGE_CONFIGS/systemd/journald.conf $FILESYSTEM_ROOT/etc/systemd/ # Copy interfaces configuration files and templates -sudo cp $IMAGE_CONFIGS/interfaces/interfaces-config.service $FILESYSTEM_ROOT/etc/systemd/system/ +sudo cp $IMAGE_CONFIGS/interfaces/interfaces-config.service $FILESYSTEM_ROOT_USR_LIB_SYSTEMD_SYSTEM sudo cp $IMAGE_CONFIGS/interfaces/interfaces-config.sh $FILESYSTEM_ROOT/usr/bin/ sudo cp $IMAGE_CONFIGS/interfaces/*.j2 $FILESYSTEM_ROOT_USR_SHARE_SONIC_TEMPLATES/ echo "interfaces-config.service" | sudo tee -a $GENERATED_SERVICE_FILE @@ -230,13 +236,13 @@ sudo cp $IMAGE_CONFIGS/interfaces/init_interfaces $FILESYSTEM_ROOT/etc/network/i sudo mkdir -p $FILESYSTEM_ROOT/etc/network/interfaces.d # Copy hostcfgd files -sudo cp $IMAGE_CONFIGS/hostcfgd/hostcfgd.service $FILESYSTEM_ROOT/etc/systemd/system/ +sudo cp $IMAGE_CONFIGS/hostcfgd/hostcfgd.service $FILESYSTEM_ROOT_USR_LIB_SYSTEMD_SYSTEM echo "hostcfgd.service" | sudo tee -a $GENERATED_SERVICE_FILE sudo cp $IMAGE_CONFIGS/hostcfgd/hostcfgd $FILESYSTEM_ROOT/usr/bin/ sudo cp $IMAGE_CONFIGS/hostcfgd/*.j2 $FILESYSTEM_ROOT_USR_SHARE_SONIC_TEMPLATES/ # copy core file uploader files -sudo cp $IMAGE_CONFIGS/corefile_uploader/core_uploader.service $FILESYSTEM_ROOT/etc/systemd/system/ +sudo cp $IMAGE_CONFIGS/corefile_uploader/core_uploader.service $FILESYSTEM_ROOT_USR_LIB_SYSTEMD_SYSTEM sudo LANG=C chroot $FILESYSTEM_ROOT systemctl disable core_uploader.service sudo cp $IMAGE_CONFIGS/corefile_uploader/core_uploader.py $FILESYSTEM_ROOT/usr/bin/ sudo cp $IMAGE_CONFIGS/corefile_uploader/core_analyzer.rc.json $FILESYSTEM_ROOT_ETC_SONIC/ @@ -259,7 +265,7 @@ sudo cp $BUILD_TEMPLATES/buffers_config.j2 $FILESYSTEM_ROOT_USR_SHARE_SONIC_TEMP sudo cp $BUILD_TEMPLATES/qos_config.j2 $FILESYSTEM_ROOT_USR_SHARE_SONIC_TEMPLATES/ # Copy hostname configuration scripts -sudo cp $IMAGE_CONFIGS/hostname/hostname-config.service $FILESYSTEM_ROOT/etc/systemd/system/ +sudo cp $IMAGE_CONFIGS/hostname/hostname-config.service $FILESYSTEM_ROOT_USR_LIB_SYSTEMD_SYSTEM echo "hostname-config.service" | sudo tee -a $GENERATED_SERVICE_FILE sudo cp $IMAGE_CONFIGS/hostname/hostname-config.sh $FILESYSTEM_ROOT/usr/bin/ @@ -268,13 +274,13 @@ sudo cp $IMAGE_CONFIGS/misc/docker-wait-any $FILESYSTEM_ROOT/usr/bin/ # Copy internal topology configuration scripts {%- if sonic_asic_platform == "vs" %} -sudo cp $IMAGE_CONFIGS/topology/topology.service $FILESYSTEM_ROOT/etc/systemd/system/ +sudo cp $IMAGE_CONFIGS/topology/topology.service $FILESYSTEM_ROOT_USR_LIB_SYSTEMD_SYSTEM echo "topology.service" | sudo tee -a $GENERATED_SERVICE_FILE sudo cp $IMAGE_CONFIGS/topology/topology.sh $FILESYSTEM_ROOT/usr/bin {%- endif %} # Copy updategraph script and service file -j2 files/build_templates/updategraph.service.j2 | sudo tee $FILESYSTEM_ROOT/etc/systemd/system/updategraph.service +j2 files/build_templates/updategraph.service.j2 | sudo tee $FILESYSTEM_ROOT_USR_LIB_SYSTEMD_SYSTEM/updategraph.service sudo cp $IMAGE_CONFIGS/updategraph/updategraph $FILESYSTEM_ROOT/usr/bin/ echo "updategraph.service" | sudo tee -a $GENERATED_SERVICE_FILE {% if enable_dhcp_graph_service == "y" %} @@ -289,7 +295,7 @@ sudo bash -c "echo enabled=false > $FILESYSTEM_ROOT/etc/sonic/updategraph.conf" j2 files/build_templates/init_cfg.json.j2 | sudo tee $FILESYSTEM_ROOT/etc/sonic/init_cfg.json # Copy config-setup script and service file -j2 files/build_templates/config-setup.service.j2 | sudo tee $FILESYSTEM_ROOT/etc/systemd/system/config-setup.service +j2 files/build_templates/config-setup.service.j2 | sudo tee $FILESYSTEM_ROOT_USR_LIB_SYSTEMD_SYSTEM/config-setup.service sudo cp $IMAGE_CONFIGS/config-setup/config-setup $FILESYSTEM_ROOT/usr/bin/config-setup echo "config-setup.service" | sudo tee -a $GENERATED_SERVICE_FILE sudo LANG=C chroot $FILESYSTEM_ROOT systemctl enable config-setup.service @@ -305,22 +311,22 @@ sudo cp $IMAGE_CONFIGS/sudoers/sudoers $FILESYSTEM_ROOT/etc/ sudo cp $IMAGE_CONFIGS/sudoers/sudoers.lecture $FILESYSTEM_ROOT/etc/ # Copy control plane ACL management daemon files -sudo cp $IMAGE_CONFIGS/caclmgrd/caclmgrd.service $FILESYSTEM_ROOT/etc/systemd/system/ +sudo cp $IMAGE_CONFIGS/caclmgrd/caclmgrd.service $FILESYSTEM_ROOT_USR_LIB_SYSTEMD_SYSTEM echo "caclmgrd.service" | sudo tee -a $GENERATED_SERVICE_FILE sudo cp $IMAGE_CONFIGS/caclmgrd/caclmgrd $FILESYSTEM_ROOT/usr/bin/ # Copy process/docker cpu/memory utilization data export daemon -sudo cp $IMAGE_CONFIGS/procdockerstatsd/procdockerstatsd.service $FILESYSTEM_ROOT/etc/systemd/system/ +sudo cp $IMAGE_CONFIGS/procdockerstatsd/procdockerstatsd.service $FILESYSTEM_ROOT_USR_LIB_SYSTEMD_SYSTEM echo "procdockerstatsd.service" | sudo tee -a $GENERATED_SERVICE_FILE sudo cp $IMAGE_CONFIGS/procdockerstatsd/procdockerstatsd $FILESYSTEM_ROOT/usr/bin/ # Copy systemd timer configuration # It implements delayed start of services -sudo cp $BUILD_TEMPLATES/process-reboot-cause.timer $FILESYSTEM_ROOT/etc/systemd/system/ +sudo cp $BUILD_TEMPLATES/process-reboot-cause.timer $FILESYSTEM_ROOT_USR_LIB_SYSTEMD_SYSTEM sudo LANG=C chroot $FILESYSTEM_ROOT systemctl enable process-reboot-cause.timer # Copy process-reboot-cause service files -sudo cp $IMAGE_CONFIGS/process-reboot-cause/process-reboot-cause.service $FILESYSTEM_ROOT/etc/systemd/system/ +sudo cp $IMAGE_CONFIGS/process-reboot-cause/process-reboot-cause.service $FILESYSTEM_ROOT_USR_LIB_SYSTEMD_SYSTEM echo "process-reboot-cause.service" | sudo tee -a $GENERATED_SERVICE_FILE sudo cp $IMAGE_CONFIGS/process-reboot-cause/process-reboot-cause $FILESYSTEM_ROOT/usr/bin/ @@ -370,7 +376,7 @@ sudo dpkg --root=$FILESYSTEM_ROOT -P {{ debname }} sudo rm -f $FILESYSTEM_ROOT/usr/sbin/policy-rc.d # Copy fstrim service and timer file, enable fstrim timer -sudo cp $IMAGE_CONFIGS/fstrim/* $FILESYSTEM_ROOT/etc/systemd/system/ +sudo cp $IMAGE_CONFIGS/fstrim/* $FILESYSTEM_ROOT_USR_LIB_SYSTEMD_SYSTEM sudo LANG=C chroot $FILESYSTEM_ROOT systemctl enable fstrim.timer ## copy platform rc.local @@ -410,11 +416,10 @@ sudo LANG=C chroot $FILESYSTEM_ROOT docker $SONIC_NATIVE_DOCKERD_FOR_DOCKERFS ta {% if install_kubernetes == "y" %} ## Pull in kubernetes docker images echo "pulling universal k8s images ..." +FLANNEL_ARCH=$([ "${CONFIGURED_ARCH}" == "armhf" ] && echo "arm64" || echo "${CONFIGURED_ARCH}") sudo https_proxy=$https_proxy LANG=C chroot $FILESYSTEM_ROOT docker pull k8s.gcr.io/pause:${K8s_GCR_IO_PAUSE_VERSION} sudo https_proxy=$https_proxy LANG=C chroot $FILESYSTEM_ROOT docker pull k8s.gcr.io/kube-proxy:v${KUBERNETES_VERSION} -sudo https_proxy=$https_proxy LANG=C chroot $FILESYSTEM_ROOT docker pull calico/node:v${K8s_CNI_CALICO_VERSION} -sudo https_proxy=$https_proxy LANG=C chroot $FILESYSTEM_ROOT docker pull calico/pod2daemon-flexvol:v${K8s_CNI_CALICO_VERSION} -sudo https_proxy=$https_proxy LANG=C chroot $FILESYSTEM_ROOT docker pull calico/cni:v${K8s_CNI_CALICO_VERSION} +sudo https_proxy=$https_proxy LANG=C chroot $FILESYSTEM_ROOT docker pull quay.io/coreos/flannel:${K8s_CNI_FLANNEL_VERSION}-${FLANNEL_ARCH} echo "docker images pull complete" {% endif %} @@ -431,12 +436,12 @@ sudo cp {{script}} $FILESYSTEM_ROOT/usr/bin/ {% endfor %} {% for service in installer_services.split(' ') -%} if [ -f {{service}} ]; then - sudo cp {{service}} $FILESYSTEM_ROOT/etc/systemd/system/ + sudo cp {{service}} $FILESYSTEM_ROOT_USR_LIB_SYSTEMD_SYSTEM {% if "@" in service %} MULTI_INSTANCE="{{service}}" SINGLE_INSTANCE=${MULTI_INSTANCE/"@"} - sudo cp $SINGLE_INSTANCE $FILESYSTEM_ROOT/etc/systemd/system/ + sudo cp $SINGLE_INSTANCE $FILESYSTEM_ROOT_USR_LIB_SYSTEMD_SYSTEM {% endif %} echo "{{service}}" | sudo tee -a $GENERATED_SERVICE_FILE @@ -455,11 +460,11 @@ sudo LANG=C cp $SCRIPTS_DIR/sonic-netns-exec $FILESYSTEM_ROOT/usr/bin/sonic-netn # Copy systemd timer configuration # It implements delayed start of services -sudo cp $BUILD_TEMPLATES/snmp.timer $FILESYSTEM_ROOT/etc/systemd/system/ -sudo LANG=C chroot $FILESYSTEM_ROOT systemctl enable snmp.timer +sudo cp $BUILD_TEMPLATES/snmp.timer $FILESYSTEM_ROOT_USR_LIB_SYSTEMD_SYSTEM +echo "snmp.timer" | sudo tee -a $GENERATED_SERVICE_FILE {% if enable_system_telemetry == 'y' %} -sudo cp $BUILD_TEMPLATES/telemetry.timer $FILESYSTEM_ROOT/etc/systemd/system/ -sudo LANG=C chroot $FILESYSTEM_ROOT systemctl enable telemetry.timer +sudo cp $BUILD_TEMPLATES/telemetry.timer $FILESYSTEM_ROOT_USR_LIB_SYSTEMD_SYSTEM +echo "telemetry.timer" | sudo tee -a $GENERATED_SERVICE_FILE {% endif %} sudo LANG=C DEBIAN_FRONTEND=noninteractive chroot $FILESYSTEM_ROOT apt-get purge -y python-dev @@ -501,3 +506,9 @@ sudo chown -R $FRR_USER_UID:$FRR_USER_GID $FILESYSTEM_ROOT/etc/sonic/frr sudo chmod -R 640 $FILESYSTEM_ROOT/etc/sonic/frr/ sudo chmod 750 $FILESYSTEM_ROOT/etc/sonic/frr {%- endif %} + +# Mask services which are disabled by default +sudo cp $BUILD_SCRIPTS_DIR/mask_disabled_services.py $FILESYSTEM_ROOT/tmp/ +sudo chmod a+x $FILESYSTEM_ROOT/tmp/mask_disabled_services.py +sudo LANG=C chroot $FILESYSTEM_ROOT /tmp/mask_disabled_services.py +sudo rm -rf $FILESYSTEM_ROOT/tmp/mask_disabled_services.py diff --git a/files/image_config/caclmgrd/caclmgrd b/files/image_config/caclmgrd/caclmgrd index e5744c7ca65b..37a86418967e 100755 --- a/files/image_config/caclmgrd/caclmgrd +++ b/files/image_config/caclmgrd/caclmgrd @@ -11,7 +11,7 @@ # try: - import ipaddr as ipaddress + import ipaddress import os import subprocess import sys @@ -44,6 +44,15 @@ def log_error(msg): syslog.syslog(syslog.LOG_ERR, msg) syslog.closelog() +# ========================== Helper Functions ========================= + +def _ip_prefix_in_key(key): + """ + Function to check if IP prefix is present in a Redis database key. + If it is present, then the key will be a tuple. Otherwise, the + key will be a string. + """ + return (isinstance(key, tuple)) # ============================== Classes ============================== @@ -61,12 +70,21 @@ class ControlPlaneAclManager(object): ACL_TABLE_TYPE_CTRLPLANE = "CTRLPLANE" - # To specify a port range, use iptables format: separate start and end - # ports with a colon, e.g., "1000:2000" + # To specify a port range instead of a single port, use iptables format: + # separate start and end ports with a colon, e.g., "1000:2000" ACL_SERVICES = { - "NTP": {"ip_protocols": ["udp"], "dst_ports": ["123"]}, - "SNMP": {"ip_protocols": ["tcp", "udp"], "dst_ports": ["161"]}, - "SSH": {"ip_protocols": ["tcp"], "dst_ports": ["22"]} + "NTP": { + "ip_protocols": ["udp"], + "dst_ports": ["123"] + }, + "SNMP": { + "ip_protocols": ["tcp", "udp"], + "dst_ports": ["161"] + }, + "SSH": { + "ip_protocols": ["tcp"], + "dst_ports": ["22"] + } } def __init__(self): @@ -115,6 +133,94 @@ class ControlPlaneAclManager(object): tcp_flags_str = tcp_flags_str[:-1] return tcp_flags_str + def generate_block_ip2me_traffic_iptables_commands(self): + LOOPBACK_INTERFACE_TABLE_NAME = "LOOPBACK_INTERFACE" + MGMT_INTERFACE_TABLE_NAME = "MGMT_INTERFACE" + VLAN_INTERFACE_TABLE_NAME = "VLAN_INTERFACE" + PORTCHANNEL_INTERFACE_TABLE_NAME = "PORTCHANNEL_INTERFACE" + INTERFACE_TABLE_NAME = "INTERFACE" + + block_ip2me_cmds = [] + + # Add iptables rules to drop all packets destined for loopback interface IP addresses + loopback_iface_table = self.config_db.get_table(LOOPBACK_INTERFACE_TABLE_NAME) + if loopback_iface_table: + for key, _ in loopback_iface_table.iteritems(): + if not _ip_prefix_in_key(key): + continue + iface_name, iface_cidr = key + ip_ntwrk = ipaddress.ip_network(iface_cidr, strict=False) + if isinstance(ip_ntwrk, ipaddress.IPv4Network): + block_ip2me_cmds.append("iptables -A INPUT -d {}/{} -j DROP".format(ip_ntwrk.network_address, ip_ntwrk.max_prefixlen)) + elif isinstance(ip_ntwrk, ipaddress.IPv6Network): + block_ip2me_cmds.append("ip6tables -A INPUT -d {}/{} -j DROP".format(ip_ntwrk.network_address, ip_ntwrk.max_prefixlen)) + else: + log_warning("Unrecognized IP address type on interface '{}': {}".format(iface_name, ip_ntwrk)) + + # Add iptables rules to drop all packets destined for management interface IP addresses + mgmt_iface_table = self.config_db.get_table(MGMT_INTERFACE_TABLE_NAME) + if mgmt_iface_table: + for key, _ in mgmt_iface_table.iteritems(): + if not _ip_prefix_in_key(key): + continue + iface_name, iface_cidr = key + ip_ntwrk = ipaddress.ip_network(iface_cidr, strict=False) + if isinstance(ip_ntwrk, ipaddress.IPv4Network): + block_ip2me_cmds.append("iptables -A INPUT -d {}/{} -j DROP".format(ip_ntwrk.network_address, ip_ntwrk.max_prefixlen)) + elif isinstance(ip_ntwrk, ipaddress.IPv6Network): + block_ip2me_cmds.append("ip6tables -A INPUT -d {}/{} -j DROP".format(ip_ntwrk.network_address, ip_ntwrk.max_prefixlen)) + else: + log_warning("Unrecognized IP address type on interface '{}': {}".format(iface_name, ip_ntwrk)) + + # Add iptables rules to drop all packets destined for our VLAN interface gateway IP addresses + vlan_iface_table = self.config_db.get_table(VLAN_INTERFACE_TABLE_NAME) + if vlan_iface_table: + for key, _ in vlan_iface_table.iteritems(): + if not _ip_prefix_in_key(key): + continue + iface_name, iface_cidr = key + ip_ntwrk = ipaddress.ip_network(iface_cidr, strict=False) + first_host = next(ip_ntwrk.hosts()) + if isinstance(ip_ntwrk, ipaddress.IPv4Network): + block_ip2me_cmds.append("iptables -A INPUT -d {}/{} -j DROP".format(first_host, ip_ntwrk.max_prefixlen)) + elif isinstance(ip_ntwrk, ipaddress.IPv6Network): + block_ip2me_cmds.append("ip6tables -A INPUT -d {}/{} -j DROP".format(first_host, ip_ntwrk.max_prefixlen)) + else: + log_warning("Unrecognized IP address type on interface '{}': {}".format(iface_name, ip_ntwrk)) + + # Add iptables rules to drop all packets destined for point-to-point interface IP addresses + # (All portchannel interfaces and configured front-panel interfaces) + portchannel_iface_table = self.config_db.get_table(PORTCHANNEL_INTERFACE_TABLE_NAME) + if portchannel_iface_table: + for key, _ in portchannel_iface_table.iteritems(): + if not _ip_prefix_in_key(key): + continue + iface_name, iface_cidr = key + ip_ntwrk = ipaddress.ip_network(iface_cidr, strict=False) + if isinstance(ip_ntwrk, ipaddress.IPv4Network): + block_ip2me_cmds.append("iptables -A INPUT -d {}/{} -j DROP".format(ip_ntwrk.network_address, ip_ntwrk.max_prefixlen)) + elif isinstance(ip_ntwrk, ipaddress.IPv6Network): + block_ip2me_cmds.append("ip6tables -A INPUT -d {}/{} -j DROP".format(ip_ntwrk.network_address, ip_ntwrk.max_prefixlen)) + else: + log_warning("Unrecognized IP address type on interface '{}': {}".format(iface_name, ip_ntwrk)) + + iface_table = self.config_db.get_table(INTERFACE_TABLE_NAME) + if iface_table: + for key, _ in iface_table.iteritems(): + if not _ip_prefix_in_key(key): + continue + iface_name, iface_cidr = key + ip_ntwrk = ipaddress.ip_network(iface_cidr, strict=False) + if isinstance(ip_ntwrk, ipaddress.IPv4Network): + block_ip2me_cmds.append("iptables -A INPUT -d {}/{} -j DROP".format(ip_ntwrk.network_address, ip_ntwrk.max_prefixlen)) + elif isinstance(ip_ntwrk, ipaddress.IPv6Network): + block_ip2me_cmds.append("ip6tables -A INPUT -d {}/{} -j DROP".format(ip_ntwrk.network_address, ip_ntwrk.max_prefixlen)) + else: + log_warning("Unrecognized IP address type on interface '{}': {}".format(iface_name, ip_ntwrk)) + + return block_ip2me_cmds + + def get_acl_rules_and_translate_to_iptables_commands(self): """ Retrieves current ACL tables and rules from Config DB, translates @@ -147,14 +253,58 @@ class ControlPlaneAclManager(object): iptables_cmds.append("ip6tables -F") iptables_cmds.append("ip6tables -X") - # Add iptables commands to allow all IPv4 and IPv6 traffic from localhost + # Add iptables/ip6tables commands to allow all traffic from localhost iptables_cmds.append("iptables -A INPUT -s 127.0.0.1 -i lo -j ACCEPT") iptables_cmds.append("ip6tables -A INPUT -s ::1 -i lo -j ACCEPT") + # Add iptables/ip6tables commands to allow all incoming packets from established + # connections or new connections which are related to established connections + iptables_cmds.append("iptables -A INPUT -m conntrack --ctstate ESTABLISHED,RELATED -j ACCEPT") + iptables_cmds.append("ip6tables -A INPUT -m conntrack --ctstate ESTABLISHED,RELATED -j ACCEPT") + + # Add iptables/ip6tables commands to allow bidirectional ICMPv4 ping and traceroute + # TODO: Support processing ICMPv4 service ACL rules, and remove this blanket acceptance + iptables_cmds.append("iptables -A INPUT -p icmp --icmp-type echo-request -j ACCEPT") + iptables_cmds.append("iptables -A INPUT -p icmp --icmp-type echo-reply -j ACCEPT") + iptables_cmds.append("iptables -A INPUT -p icmp --icmp-type destination-unreachable -j ACCEPT") + iptables_cmds.append("iptables -A INPUT -p icmp --icmp-type time-exceeded -j ACCEPT") + + # Add iptables/ip6tables commands to allow bidirectional ICMPv6 ping and traceroute + # TODO: Support processing ICMPv6 service ACL rules, and remove this blanket acceptance + iptables_cmds.append("ip6tables -A INPUT -p icmpv6 --icmpv6-type echo-request -j ACCEPT") + iptables_cmds.append("ip6tables -A INPUT -p icmpv6 --icmpv6-type echo-reply -j ACCEPT") + iptables_cmds.append("ip6tables -A INPUT -p icmpv6 --icmpv6-type destination-unreachable -j ACCEPT") + iptables_cmds.append("ip6tables -A INPUT -p icmpv6 --icmpv6-type time-exceeded -j ACCEPT") + + # Add iptables/ip6tables commands to allow all incoming Neighbor Discovery Protocol (NDP) NS/NA/RS/RA messages + # TODO: Support processing NDP service ACL rules, and remove this blanket acceptance + iptables_cmds.append("ip6tables -A INPUT -p icmpv6 --icmpv6-type neighbor-solicitation -j ACCEPT") + iptables_cmds.append("ip6tables -A INPUT -p icmpv6 --icmpv6-type neighbor-advertisement -j ACCEPT") + iptables_cmds.append("ip6tables -A INPUT -p icmpv6 --icmpv6-type router-solicitation -j ACCEPT") + iptables_cmds.append("ip6tables -A INPUT -p icmpv6 --icmpv6-type router-advertisement -j ACCEPT") + + # Add iptables/ip6tables commands to allow all incoming IPv4 DHCP packets + iptables_cmds.append("iptables -A INPUT -p udp --dport 67:68 --sport 67:68 -j ACCEPT") + iptables_cmds.append("ip6tables -A INPUT -p udp --dport 67:68 --sport 67:68 -j ACCEPT") + + # Add iptables/ip6tables commands to allow all incoming IPv6 DHCP packets + iptables_cmds.append("iptables -A INPUT -p udp --dport 546:547 --sport 546:547 -j ACCEPT") + iptables_cmds.append("ip6tables -A INPUT -p udp --dport 546:547 --sport 546:547 -j ACCEPT") + + # Add iptables/ip6tables commands to allow all incoming BGP traffic + # TODO: Determine BGP ACLs based on configured device sessions, and remove this blanket acceptance + iptables_cmds.append("iptables -A INPUT -p tcp --dport 179 -j ACCEPT") + iptables_cmds.append("iptables -A INPUT -p tcp --sport 179 -j ACCEPT") + iptables_cmds.append("ip6tables -A INPUT -p tcp --dport 179 -j ACCEPT") + iptables_cmds.append("ip6tables -A INPUT -p tcp --sport 179 -j ACCEPT") + + # Get current ACL tables and rules from Config DB self._tables_db_info = self.config_db.get_table(self.ACL_TABLE) self._rules_db_info = self.config_db.get_table(self.ACL_RULE) + num_ctrl_plane_acl_rules = 0 + # Walk the ACL tables for (table_name, table_data) in self._tables_db_info.iteritems(): @@ -246,6 +396,23 @@ class ControlPlaneAclManager(object): rule_cmd += " -j {}".format(rule_props["PACKET_ACTION"]) iptables_cmds.append(rule_cmd) + num_ctrl_plane_acl_rules += 1 + + # Add iptables commands to block ip2me traffic + iptables_cmds += self.generate_block_ip2me_traffic_iptables_commands() + + # Add iptables/ip6tables commands to allow all incoming packets with TTL of 0 or 1 + # This allows the device to respond to tools like tcptraceroute + iptables_cmds.append("iptables -A INPUT -m ttl --ttl-lt 2 -j ACCEPT") + iptables_cmds.append("ip6tables -A INPUT -p tcp -m hl --hl-lt 2 -j ACCEPT") + + # Finally, if the device has control plane ACLs configured, + # add iptables/ip6tables commands to drop all other incoming packets + if num_ctrl_plane_acl_rules > 0: + iptables_cmds.append("iptables -A INPUT -j DROP") + iptables_cmds.append("iptables -A FORWARD -j DROP") + iptables_cmds.append("ip6tables -A INPUT -j DROP") + iptables_cmds.append("ip6tables -A FORWARD -j DROP") return iptables_cmds diff --git a/files/image_config/hostcfgd/hostcfgd b/files/image_config/hostcfgd/hostcfgd index 4ac3be83d06e..8a3dbd15b622 100755 --- a/files/image_config/hostcfgd/hostcfgd +++ b/files/image_config/hostcfgd/hostcfgd @@ -40,6 +40,40 @@ def obfuscate(data): else: return data + +def update_feature_status(feature_name, status): + if status == "enabled": + start_cmds = [] + start_cmds.append("sudo systemctl unmask {}.service".format(feature_name)) + start_cmds.append("sudo systemctl enable {}.service".format(feature_name)) + start_cmds.append("sudo systemctl start {}.service".format(feature_name)) + for cmd in start_cmds: + syslog.syslog(syslog.LOG_INFO, "Running cmd: '{}'".format(cmd)) + try: + subprocess.check_call(cmd, shell=True) + except subprocess.CalledProcessError as err: + syslog.syslog(syslog.LOG_ERR, "'{}' failed. RC: {}, output: {}" + .format(err.cmd, err.returncode, err.output)) + continue + syslog.syslog(syslog.LOG_INFO, "Feature '{}' is enabled and started".format(feature_name)) + elif status == "disabled": + stop_cmds = [] + stop_cmds.append("sudo systemctl stop {}.service".format(feature_name)) + stop_cmds.append("sudo systemctl disable {}.service".format(feature_name)) + stop_cmds.append("sudo systemctl mask {}.service".format(feature_name)) + for cmd in stop_cmds: + syslog.syslog(syslog.LOG_INFO, "Running cmd: '{}'".format(cmd)) + try: + subprocess.check_call(cmd, shell=True) + except subprocess.CalledProcessError as err: + syslog.syslog(syslog.LOG_ERR, "'{}' failed. RC: {}, output: {}" + .format(err.cmd, err.returncode, err.output)) + continue + syslog.syslog(syslog.LOG_INFO, "Feature '{}' is stopped and disabled".format(feature_name)) + else: + syslog.syslog(syslog.LOG_ERR, "Unexpected status value '{}' for feature '{}'".format(status, feature_name)) + + class Iptables(object): def __init__(self): ''' @@ -114,7 +148,7 @@ class Iptables(object): try: subprocess.check_call(cmd, shell=True) except subprocess.CalledProcessError as err: - syslog.syslog(syslog.LOG_ERR, "{} - failed: return code - {}, output:\n{}" + syslog.syslog(syslog.LOG_ERR, "'{}' failed. RC: {}, output: {}" .format(err.cmd, err.returncode, err.output)) class AaaCfg(object): @@ -234,26 +268,40 @@ class HostConfigDaemon: self.iptables = Iptables() self.iptables.load(lpbk_table) + def update_all_feature_statuses(self): + feature_table = self.config_db.get_table('FEATURE') + for feature_name in feature_table.keys(): + if not feature_name: + syslog.syslog(syslog.LOG_WARNING, "Feature is None") + continue + + status = feature_table[feature_name]['status'] + if not status: + syslog.syslog(syslog.LOG_WARNING, "Status of feature '{}' is None".format(feature_name)) + continue + + update_feature_status(feature_name, status) + def aaa_handler(self, key, data): self.aaacfg.aaa_update(key, data) def tacacs_server_handler(self, key, data): self.aaacfg.tacacs_server_update(key, data) log_data = copy.deepcopy(data) - if log_data.has_key('passkey'): + if 'passkey' in log_data: log_data['passkey'] = obfuscate(log_data['passkey']) syslog.syslog(syslog.LOG_INFO, 'value of {} changed to {}'.format(key, log_data)) def tacacs_global_handler(self, key, data): self.aaacfg.tacacs_global_update(key, data) log_data = copy.deepcopy(data) - if log_data.has_key('passkey'): + if 'passkey' in log_data: log_data['passkey'] = obfuscate(log_data['passkey']) syslog.syslog(syslog.LOG_INFO, 'value of {} changed to {}'.format(key, log_data)) def lpbk_handler(self, key, data): key = ConfigDBConnector.deserialize_key(key) - #Check if delete operation by fetch existing keys + # Check if delete operation by fetch existing keys keys = self.config_db.get_keys('LOOPBACK_INTERFACE') if key in keys: add = True @@ -263,45 +311,23 @@ class HostConfigDaemon: self.iptables.iptables_handler(key, data, add) def feature_status_handler(self, key, data): - status_data = self.config_db.get_table('FEATURE') - for key in status_data.keys(): - if not key: - syslog.syslog(syslog.LOG_WARNING, "FEATURE key is missing") - return - status = status_data[key]['status'] + feature_name = key + feature_table = self.config_db.get_table('FEATURE') + if feature_name not in feature_table.keys(): + syslog.syslog(syslog.LOG_WARNING, "Feature '{}' not in FEATURE table".format(feature_name)) + return + + status = feature_table[feature_name]['status'] if not status: - syslog.syslog(syslog.LOG_WARNING, "status is missing for {}".format(key)) + syslog.syslog(syslog.LOG_WARNING, "Status of feature '{}' is None".format(feature_name)) return - if status == "enabled": - start_cmds=[] - start_cmds.append("sudo systemctl enable {}".format(key)) - start_cmds.append("sudo systemctl start {}".format(key)) - for cmd in start_cmds: - syslog.syslog(syslog.LOG_INFO, "Running cmd - {}".format(cmd)) - try: - subprocess.check_call(cmd, shell=True) - except subprocess.CalledProcessError as err: - syslog.syslog(syslog.LOG_ERR, "{} - failed: return code - {}, output:\n{}" - .format(err.cmd, err.returncode, err.output)) - return - syslog.syslog(syslog.LOG_INFO, "Feature '{}' is enabled and started".format(key)) - elif status == "disabled": - stop_cmds=[] - stop_cmds.append("sudo systemctl stop {}".format(key)) - stop_cmds.append("sudo systemctl disable {}".format(key)) - for cmd in stop_cmds: - syslog.syslog(syslog.LOG_INFO, "Running cmd - {}".format(cmd)) - try: - subprocess.check_call(cmd, shell=True) - except subprocess.CalledProcessError as err: - syslog.syslog(syslog.LOG_ERR, "{} - failed: return code - {}, output:\n{}" - .format(err.cmd, err.returncode, err.output)) - return - syslog.syslog(syslog.LOG_INFO, "Feature '{}' is stopped and disabled".format(key)) - else: - syslog.syslog(syslog.LOG_ERR, "Unexpected status value '{}' for '{}'".format(status, key)) + + update_feature_status(feature_name, status) def start(self): + # Update all feature statuses once upon starting + self.update_all_feature_statuses() + self.config_db.subscribe('AAA', lambda table, key, data: self.aaa_handler(key, data)) self.config_db.subscribe('TACPLUS_SERVER', lambda table, key, data: self.tacacs_server_handler(key, data)) self.config_db.subscribe('TACPLUS', lambda table, key, data: self.tacacs_global_handler(key, data)) diff --git a/files/image_config/ntp/ntp-config.sh b/files/image_config/ntp/ntp-config.sh index 7ab84174dcaa..0cec0f7af2db 100755 --- a/files/image_config/ntp/ntp-config.sh +++ b/files/image_config/ntp/ntp-config.sh @@ -26,12 +26,7 @@ function modify_ntp_default sonic-cfggen -d -t /usr/share/sonic/templates/ntp.conf.j2 >/etc/ntp.conf get_database_reboot_type -if [[ x"${reboot_type}" == x"cold" ]]; then - echo "Enabling NTP long jump for reboot type ${reboot_type} ..." - modify_ntp_default "s/NTPD_OPTS='-x'/NTPD_OPTS='-g'/" -else - echo "Disabling NTP long jump for reboot type ${reboot_type} ..." - modify_ntp_default "s/NTPD_OPTS='-g'/NTPD_OPTS='-x'/" -fi +echo "Disabling NTP long jump for reboot type ${reboot_type} ..." +modify_ntp_default "s/NTPD_OPTS='-g'/NTPD_OPTS='-x'/" systemctl restart ntp diff --git a/files/image_config/platform/rc.local b/files/image_config/platform/rc.local index 2884270b7870..2beec7500cfd 100755 --- a/files/image_config/platform/rc.local +++ b/files/image_config/platform/rc.local @@ -82,10 +82,6 @@ update_mgmt_interface_macaddr() { log_migration "eth0 mac in EEPROM after update:" ethtool -e eth0 offset $ethtool_offset length 6 >> /host/migration/migration.log - - # Update the 70-persistent-net.rules with the new mac for eth0 - log_migration "/etc/udev/rules.d/70-persistent-net.rules : replacing $old_mac with $new_mac for eth0" - sed -i "/eth0/ s/ATTR{address}==\"$old_mac\"/ATTR{address}==\"$new_mac\"/g" /etc/udev/rules.d/70-persistent-net.rules } firsttime_exit() { @@ -340,4 +336,10 @@ if [ -f $FIRST_BOOT_FILE ]; then firsttime_exit fi +# Copy the fsck log into syslog +if [ -f /var/log/fsck.log.gz ]; then + gunzip -d -c /var/log/fsck.log.gz | logger -t "FSCK" + rm -f /var/log/fsck.log.gz +fi + exit 0 diff --git a/files/image_config/rsyslog/rsyslog-config.sh b/files/image_config/rsyslog/rsyslog-config.sh index c8ba7b99453c..26767d84fbe0 100755 --- a/files/image_config/rsyslog/rsyslog-config.sh +++ b/files/image_config/rsyslog/rsyslog-config.sh @@ -1,4 +1,23 @@ #!/bin/bash -sonic-cfggen -d -t /usr/share/sonic/templates/rsyslog.conf.j2 >/etc/rsyslog.conf +PLATFORM=`sonic-cfggen -H -v DEVICE_METADATA.localhost.platform` + +# Parse the device specific asic conf file, if it exists +ASIC_CONF=/usr/share/sonic/device/$PLATFORM/asic.conf +if [ -f "$ASIC_CONF" ]; then + source $ASIC_CONF +fi + +# On Multi NPU platforms we need to start the rsyslog server on the docker0 ip address +# for the syslogs from the containers in the namespaces to work. +# on Single NPU platforms we continue to use loopback adddres + +if [[ ($NUM_ASIC -gt 1) ]]; then + udp_server_ip=$(ip -o -4 addr list docker0 | awk '{print $4}' | cut -d/ -f1) +else + udp_server_ip=$(ip -o -4 addr list lo scope host | awk '{print $4}' | cut -d/ -f1) +fi + +sonic-cfggen -d -t /usr/share/sonic/templates/rsyslog.conf.j2 -a "{\"udp_server_ip\": \"$udp_server_ip\"}" >/etc/rsyslog.conf + systemctl restart rsyslog diff --git a/files/image_config/rsyslog/rsyslog-container.conf.j2 b/files/image_config/rsyslog/rsyslog-container.conf.j2 new file mode 100644 index 000000000000..d17fbb6767ba --- /dev/null +++ b/files/image_config/rsyslog/rsyslog-container.conf.j2 @@ -0,0 +1,76 @@ +# +# /etc/rsyslog.conf Configuration file for rsyslog. +# +# For more information see +# /usr/share/doc/rsyslog-doc/html/rsyslog_conf.html + + +################# +#### MODULES #### +################# + +$ModLoad imuxsock # provides support for local system logging + +# +# Set a rate limit on messages from the container +# +$SystemLogRateLimitInterval 300 +$SystemLogRateLimitBurst 20000 + +#$ModLoad imklog # provides kernel logging support +#$ModLoad immark # provides --MARK-- message capability + +# provides UDP syslog reception +#$ModLoad imudp +#$UDPServerRun 514 + +# provides TCP syslog reception +#$ModLoad imtcp +#$InputTCPServerRun 514 + + +########################### +#### GLOBAL DIRECTIVES #### +########################### + +# Set remote syslog server +template (name="ForwardFormatInContainer" type="string" string="<%PRI%>%TIMESTAMP:::date-rfc3339% %HOSTNAME% {{container_name}}#%syslogtag%%msg:::sp-if-no-1st-sp%%msg%") +*.* action(type="omfwd" target="{{target_ip}}" port="514" protocol="udp" Template="ForwardFormatInContainer") + +# +# Use traditional timestamp format. +# To enable high precision timestamps, comment out the following line. +# +#$ActionFileDefaultTemplate RSYSLOG_TraditionalFileFormat + +# Define a custom template +$template SONiCFileFormat,"%TIMESTAMP%.%timestamp:::date-subseconds% %HOSTNAME% %syslogseverity-text:::uppercase% {{container_name}}#%syslogtag%%msg:::sp-if-no-1st-sp%%msg:::drop-last-lf%\n" +$ActionFileDefaultTemplate SONiCFileFormat + +# +# Set the default permissions for all log files. +# +$FileOwner root +$FileGroup adm +$FileCreateMode 0640 +$DirCreateMode 0755 +$Umask 0022 + +# +# Where to place spool and state files +# +$WorkDirectory /var/spool/rsyslog + +# +# Include all config files in /etc/rsyslog.d/ +# +$IncludeConfig /etc/rsyslog.d/*.conf + +# +# Suppress duplicate messages and report "message repeated n times" +# +$RepeatedMsgReduction on + +############### +#### RULES #### +############### diff --git a/files/image_config/rsyslog/rsyslog.conf.j2 b/files/image_config/rsyslog/rsyslog.conf.j2 index fbf8bf20160a..37410293a45f 100644 --- a/files/image_config/rsyslog/rsyslog.conf.j2 +++ b/files/image_config/rsyslog/rsyslog.conf.j2 @@ -19,7 +19,7 @@ $ModLoad imklog # provides kernel logging support # provides UDP syslog reception $ModLoad imudp -$UDPServerAddress 127.0.0.1 # bind to localhost before udp server run +$UDPServerAddress {{udp_server_ip}} #bind to localhost before udp server run $UDPServerRun 514 # provides TCP syslog reception diff --git a/files/image_config/sysctl/sysctl-net.conf b/files/image_config/sysctl/sysctl-net.conf new file mode 100644 index 000000000000..62fda3a8ca91 --- /dev/null +++ b/files/image_config/sysctl/sysctl-net.conf @@ -0,0 +1,39 @@ +# All the sysctl for ipv4/ipv6 network. +# Same will be used in host or docker namespace +# It should be provided as key=value format for parsing +net.ipv6.conf.all.disable_ipv6=0 +net.ipv4.conf.default.forwarding=1 +net.ipv4.conf.all.forwarding=1 +net.ipv4.conf.eth0.forwarding=0 +net.ipv4.conf.default.arp_accept=0 +net.ipv4.conf.default.arp_announce=0 +net.ipv4.conf.default.arp_filter=0 +net.ipv4.conf.default.arp_notify=0 +net.ipv4.conf.default.arp_ignore=0 +net.ipv4.conf.all.arp_accept=0 +net.ipv4.conf.all.arp_announce=1 +net.ipv4.conf.all.arp_filter=0 +net.ipv4.conf.all.arp_notify=1 +net.ipv4.conf.all.arp_ignore=2 +net.ipv4.neigh.default.base_reachable_time_ms=1800000 +net.ipv6.neigh.default.base_reachable_time_ms=1800000 +net.ipv4.neigh.default.gc_thresh1=1024 +net.ipv6.neigh.default.gc_thresh1=1024 +net.ipv4.neigh.default.gc_thresh2=2048 +net.ipv6.neigh.default.gc_thresh2=2048 +net.ipv4.neigh.default.gc_thresh3=4096 +net.ipv6.neigh.default.gc_thresh3=4096 +net.ipv6.conf.default.forwarding=1 +net.ipv6.conf.all.forwarding=1 +net.ipv6.conf.eth0.forwarding=0 +net.ipv6.conf.default.accept_dad=0 +net.ipv6.conf.all.accept_dad=0 +net.ipv6.conf.eth0.accept_dad=0 +net.ipv6.conf.default.keep_addr_on_down=1 +net.ipv6.conf.all.keep_addr_on_down=1 +net.ipv6.conf.eth0.keep_addr_on_down=1 +net.ipv4.tcp_l3mdev_accept=1 +net.ipv4.udp_l3mdev_accept=1 +net.core.rmem_max=2097152 +net.core.wmem_max=2097152 +net.core.somaxconn=512 diff --git a/files/initramfs-tools/fsck-rootfs b/files/initramfs-tools/fsck-rootfs new file mode 100644 index 000000000000..25b1c096aa5b --- /dev/null +++ b/files/initramfs-tools/fsck-rootfs @@ -0,0 +1,34 @@ +#!/bin/sh + +case $1 in + prereqs) + exit 0 + ;; +esac + +# Extract kernel parameters +root_val="" +set -- $(cat /proc/cmdline) +for x in "$@"; do + case "$x" in + root=*) + root_val="${x#root=}" + ;; + esac +done + +# Check the filesystem we are using +if [ ! -z $root_val ]; then + fstype=$(blkid -o value -s TYPE $root_val) + case "$fstype" in + ext4) + cmd="fsck.ext4 -v -p" + ;; + ext3) + cmd="fsck.ext3 -v -p" + ;; + esac + if [ ! -z "$cmd" ]; then + $cmd $root_val 2>&1 | gzip -c > /tmp/fsck.log.gz + fi +fi diff --git a/files/initramfs-tools/union-mount.j2 b/files/initramfs-tools/union-mount.j2 index 39a514b0669e..f5e77da1e14f 100644 --- a/files/initramfs-tools/union-mount.j2 +++ b/files/initramfs-tools/union-mount.j2 @@ -65,7 +65,10 @@ mount --bind ${rootmnt}/host/$image_dir/boot ${rootmnt}/boot ## Mount loop device or tmpfs for /var/log onie_platform="" aboot_platform="" -. ${rootmnt}/host/machine.conf +if [ -f ${rootmnt}/host/machine.conf ]; then + . ${rootmnt}/host/machine.conf +fi + if [ X"$aboot_platform" = X"x86_64-arista_7050_qx32" ] || [ X"$aboot_platform" = X"x86_64-arista_7050_qx32s" ] || [ X"$aboot_platform" = X"x86_64-arista_7060_cx32s" ] @@ -74,5 +77,12 @@ then mount -t tmpfs -o rw,nosuid,nodev,size=${varlogsize}M tmpfs ${rootmnt}/var/log [ -f ${rootmnt}/host/disk-img/var-log.ext4 ] && rm -rf ${rootmnt}/host/disk-img/var-log.ext4 else + [ -f ${rootmnt}/host/disk-img/var-log.ext4 ] && fsck.ext4 -v -p ${rootmnt}/host/disk-img/var-log.ext4 2>&1 \ + | gzip -c >> /tmp/fsck.log.gz [ -f ${rootmnt}/host/disk-img/var-log.ext4 ] && mount -t ext4 -o loop,rw ${rootmnt}/host/disk-img/var-log.ext4 ${rootmnt}/var/log fi + +## fscklog file: /tmp will be lost when overlayfs is mounted +if [ -f /tmp/fsck.log.gz ]; then + mv /tmp/fsck.log.gz ${rootmnt}/var/log +fi diff --git a/files/scripts/supervisor-proc-exit-listener b/files/scripts/supervisor-proc-exit-listener index cf154b3a5c10..04a2a5001371 100755 --- a/files/scripts/supervisor-proc-exit-listener +++ b/files/scripts/supervisor-proc-exit-listener @@ -10,14 +10,42 @@ import swsssdk from supervisor import childutils -# Contents of file should be the names of critical processes (as defined in -# supervisor.conf file), one per line +# Each line of this file should specify either one critical process or one +# critical process group, (as defined in supervisord.conf file), in the +# following format: +# +# program: +# group: CRITICAL_PROCESSES_FILE = '/etc/supervisor/critical_processes' # This table in databse contains the features for container and each # feature for a row will be configured a state or number. CONTAINER_FEATURE_TABLE_NAME = 'CONTAINER_FEATURE' +# Read the critical processes/group names from CRITICAL_PROCESSES_FILE +def get_critical_group_and_process_list(): + critical_group_list = [] + critical_process_list = [] + + with open(CRITICAL_PROCESSES_FILE, 'r') as file: + for line in file: + line_info = line.strip(' \n').split(':') + if len(line_info) != 2: + syslog.syslog(syslog.LOG_ERR, "Syntax of the line {} in critical_processes file is incorrect. Exiting...".format(line)) + sys.exit(5) + + identifier_key = line_info[0].strip() + identifier_value = line_info[1].strip() + if identifier_key == "group" and identifier_value: + critical_group_list.append(identifier_value) + elif identifier_key == "program" and identifier_value: + critical_process_list.append(identifier_value) + else: + syslog.syslog(syslog.LOG_ERR, "Syntax of the line {} in critical_processes file is incorrect. Exiting...".format(line)) + sys.exit(6) + + return critical_group_list, critical_process_list + def main(argv): container_name = None opts, args = getopt.getopt(argv, "c:", ["container-name="]) @@ -29,9 +57,7 @@ def main(argv): syslog.syslog(syslog.LOG_ERR, "Container name not specified. Exiting...") sys.exit(1) - # Read the list of critical processes from a file - with open(CRITICAL_PROCESSES_FILE, 'r') as f: - critical_processes = [line.rstrip('\n') for line in f] + critical_group_list, critical_process_list = get_critical_group_and_process_list() while True: # Transition from ACKNOWLEDGED to READY @@ -73,7 +99,7 @@ def main(argv): # If container is database or auto-restart feature is enabled and at the same time # a critical process exited unexpectedly, terminate supervisor if ((container_name == 'database' or restart_feature == 'enabled') and expected == 0 and - (processname in critical_processes or groupname in critical_processes)): + (processname in critical_process_list or groupname in critical_group_list)): MSG_FORMAT_STR = "Process {} exited unxepectedly. Terminating supervisor..." msg = MSG_FORMAT_STR.format(payload_headers['processname']) syslog.syslog(syslog.LOG_INFO, msg) diff --git a/files/scripts/syncd.sh b/files/scripts/syncd.sh index 4ebc35d379ed..797aaec21990 100755 --- a/files/scripts/syncd.sh +++ b/files/scripts/syncd.sh @@ -113,7 +113,7 @@ start() { /usr/bin/hw-management.sh chipupdis fi - /usr/bin/mst start + /usr/bin/mst start --with_i2cdev /usr/bin/mlnx-fw-upgrade.sh /etc/init.d/sxdkernel start fi @@ -163,11 +163,21 @@ stop() { debug "${TYPE} shutdown syncd process ..." /usr/bin/docker exec -i syncd$DEV /usr/bin/syncd_request_shutdown --${TYPE} - # wait until syncd quits gracefully - while docker top syncd$DEV | grep -q /usr/bin/syncd; do + # wait until syncd quits gracefully or force syncd to exit after + # waiting for 20 seconds + start_in_secs=${SECONDS} + end_in_secs=${SECONDS} + timer_threshold=20 + while docker top syncd$DEV | grep -q /usr/bin/syncd \ + && [[ $((end_in_secs - start_in_secs)) -le $timer_threshold ]]; do sleep 0.1 + end_in_secs=${SECONDS} done + if [[ $((end_in_secs - start_in_secs)) -gt $timer_threshold ]]; then + debug "syncd process in container syncd$DEV did not exit gracefully" + fi + /usr/bin/docker exec -i syncd$DEV /bin/sync debug "Finished ${TYPE} shutdown syncd process ..." fi diff --git a/onie-image.conf b/onie-image.conf index 2ca0a68484e2..3889244f9adf 100644 --- a/onie-image.conf +++ b/onie-image.conf @@ -25,7 +25,7 @@ FILESYSTEM_DOCKERFS=dockerfs.tar.gz DOCKERFS_DIR=docker ## docker ramfs disk space -DOCKER_RAMFS_SIZE=900M +DOCKER_RAMFS_SIZE=1300M ## Output file name for onie installer OUTPUT_ONIE_IMAGE=target/sonic-$TARGET_MACHINE.bin diff --git a/platform/barefoot/docker-syncd-bfn/base_image_files/monit_syncd b/platform/barefoot/docker-syncd-bfn/base_image_files/monit_syncd index 3079618990ed..75391f90ac32 100644 --- a/platform/barefoot/docker-syncd-bfn/base_image_files/monit_syncd +++ b/platform/barefoot/docker-syncd-bfn/base_image_files/monit_syncd @@ -3,5 +3,5 @@ ## process list: ## syncd ############################################################################### -check process syncd matching "/usr/bin/syncd" +check process syncd matching "/usr/bin/syncd\s" if does not exist for 5 times within 5 cycles then alert diff --git a/platform/barefoot/docker-syncd-bfn/critical_processes b/platform/barefoot/docker-syncd-bfn/critical_processes index 6082f242b872..bdd6903c5690 100644 --- a/platform/barefoot/docker-syncd-bfn/critical_processes +++ b/platform/barefoot/docker-syncd-bfn/critical_processes @@ -1 +1 @@ -syncd +program:syncd diff --git a/platform/broadcom/docker-syncd-brcm/base_image_files/monit_syncd b/platform/broadcom/docker-syncd-brcm/base_image_files/monit_syncd index 0b9ec741cd57..81c0b6ef6bc6 100644 --- a/platform/broadcom/docker-syncd-brcm/base_image_files/monit_syncd +++ b/platform/broadcom/docker-syncd-brcm/base_image_files/monit_syncd @@ -4,7 +4,7 @@ ## syncd ## dsserve ############################################################################### -check process syncd matching "/usr/bin/syncd" +check process syncd matching "/usr/bin/syncd\s" if does not exist for 5 times within 5 cycles then alert check process dsserve matching "/usr/bin/dsserve /usr/bin/syncd" diff --git a/platform/broadcom/docker-syncd-brcm/critical_processes b/platform/broadcom/docker-syncd-brcm/critical_processes index 489668a89e08..d1163a9c3046 100644 --- a/platform/broadcom/docker-syncd-brcm/critical_processes +++ b/platform/broadcom/docker-syncd-brcm/critical_processes @@ -1,2 +1,2 @@ -dsserve -syncd +program:dsserve +program:syncd diff --git a/platform/broadcom/sai-modules.mk b/platform/broadcom/sai-modules.mk index 93132c2287bd..c11cf8a94e8b 100644 --- a/platform/broadcom/sai-modules.mk +++ b/platform/broadcom/sai-modules.mk @@ -1,7 +1,7 @@ # Broadcom SAI modules KVERSION = 4.9.0-11-2-amd64 -BRCM_OPENNSL_KERNEL_VERSION = 3.7.3.3-1 +BRCM_OPENNSL_KERNEL_VERSION = 3.7.5.1 BRCM_OPENNSL_KERNEL = opennsl-modules_$(BRCM_OPENNSL_KERNEL_VERSION)_amd64.deb $(BRCM_OPENNSL_KERNEL)_SRC_PATH = $(PLATFORM_PATH)/saibcm-modules diff --git a/platform/broadcom/sai.mk b/platform/broadcom/sai.mk index e6e40039caf0..d92305d4240a 100644 --- a/platform/broadcom/sai.mk +++ b/platform/broadcom/sai.mk @@ -1,8 +1,8 @@ -BRCM_SAI = libsaibcm_3.7.3.3-4_amd64.deb -$(BRCM_SAI)_URL = "https://sonicstorage.blob.core.windows.net/packages/bcmsai/3.7/libsaibcm_3.7.3.3-4_amd64.deb?sv=2015-04-05&sr=b&sig=9z7vLhweD%2B%2FZylkr9XsDAJ3DdE5NJlcPTslFYyBuAXU%3D&se=2033-12-25T14%3A52%3A25Z&sp=r" -BRCM_SAI_DEV = libsaibcm-dev_3.7.3.3-4_amd64.deb +BRCM_SAI = libsaibcm_3.7.5.1-1_amd64.deb +$(BRCM_SAI)_URL = "https://sonicstorage.blob.core.windows.net/packages/bcmsai/3.7/libsaibcm_3.7.5.1-1_amd64.deb?sv=2015-04-05&sr=b&sig=cxmXsJ%2BjcnR9ckFRbMigIbkzOncYkiV04weL%2FVPKBmk%3D&se=2034-03-06T00%3A30%3A30Z&sp=r" +BRCM_SAI_DEV = libsaibcm-dev_3.7.5.1-1_amd64.deb $(eval $(call add_derived_package,$(BRCM_SAI),$(BRCM_SAI_DEV))) -$(BRCM_SAI_DEV)_URL = "https://sonicstorage.blob.core.windows.net/packages/bcmsai/3.7/libsaibcm-dev_3.7.3.3-4_amd64.deb?sv=2015-04-05&sr=b&sig=SAOoGh2zdljiPuKeDoa%2B1lSJzZ8uXh2Irl2RZX1uAiA%3D&se=2033-12-25T14%3A53%3A44Z&sp=r" +$(BRCM_SAI_DEV)_URL = "https://sonicstorage.blob.core.windows.net/packages/bcmsai/3.7/libsaibcm-dev_3.7.5.1-1_amd64.deb?sv=2015-04-05&sr=b&sig=LVgghAv75VG4idW6xfpId%2FlrvPBja7uBQeTbjZsR3CA%3D&se=2034-03-06T00%3A31%3A30Z&sp=r" SONIC_ONLINE_DEBS += $(BRCM_SAI) $(BRCM_SAI_DEV)_DEPENDS += $(BRCM_SAI) diff --git a/platform/broadcom/saibcm-modules/debian/changelog b/platform/broadcom/saibcm-modules/debian/changelog index 2be513ed0435..6197f9e38c9a 100644 --- a/platform/broadcom/saibcm-modules/debian/changelog +++ b/platform/broadcom/saibcm-modules/debian/changelog @@ -1,3 +1,10 @@ +opennsl (3.7.5.1) unstable; urgency=medium + + * Port Broadcom SAI 3.7.5.1 + * Cherry-pick change from master branch, 3.7.5.1 + + -- Judy Joseph Fri, 25 MAY 2020 15:32:47 +0000 + opennsl (3.7.3.3-1) unstable; urgency=medium * Port Broadcom SAI 3.7.3.3 diff --git a/platform/broadcom/saibcm-modules/systems/linux/kernel/modules/knet-cb/psample-cb.c b/platform/broadcom/saibcm-modules/systems/linux/kernel/modules/knet-cb/psample-cb.c index ef6fc102ce78..8b1d3b236a39 100644 --- a/platform/broadcom/saibcm-modules/systems/linux/kernel/modules/knet-cb/psample-cb.c +++ b/platform/broadcom/saibcm-modules/systems/linux/kernel/modules/knet-cb/psample-cb.c @@ -64,6 +64,7 @@ extern int debug; #define SOC_HIGIG_SRCPORT(x) ((x[1] >> 16) & 0x1f) #define SOC_HIGIG2_SOP (0xfb) //0xfc - TODO: how can we differentiate between Higig and higig2? #define SOC_HIGIG2_START(x) ((x[0] >> 24) & 0xff) +#define SOC_HIGIG2_IS_MC(x) ((x[0] >> 20) & 0x1) #define SOC_HIGIG2_DSTPORT(x) ((x[0] >> 0) & 0xff) #define SOC_HIGIG2_SRCPORT(x) ((x[1] >> 16) & 0xff) #define SOC_DCB32_HG_OFFSET (6) @@ -213,7 +214,14 @@ psample_meta_dstport_get(uint8_t *pkt, void *pkt_meta) if (SOC_HIGIG2_START(metadata) == SOC_HIGIG2_SOP) { - dstport = SOC_HIGIG2_DSTPORT(metadata); + if (SOC_HIGIG2_IS_MC(metadata)) + { + dstport = 0; + } + else + { + dstport = SOC_HIGIG2_DSTPORT(metadata); + } } else if (SOC_HIGIG_START(metadata) == SOC_HIGIG_SOP) { @@ -427,7 +435,7 @@ psample_netif_create_cb(int unit, kcom_netif_t *netif, struct net_device *dev) psample_netif_t *psample_netif, *lpsample_netif; unsigned long flags; - if ((psample_netif = kmalloc(sizeof(psample_netif_t), GFP_KERNEL)) == NULL) { + if ((psample_netif = kmalloc(sizeof(psample_netif_t), GFP_ATOMIC)) == NULL) { gprintk("%s: failed to alloc psample mem for netif '%s'\n", __func__, dev->name); return (-1); diff --git a/platform/broadcom/saibcm-modules/systems/linux/kernel/modules/psample/psample.c b/platform/broadcom/saibcm-modules/systems/linux/kernel/modules/psample/psample.c index e1d4e2353b09..99317cbf30cc 100644 --- a/platform/broadcom/saibcm-modules/systems/linux/kernel/modules/psample/psample.c +++ b/platform/broadcom/saibcm-modules/systems/linux/kernel/modules/psample/psample.c @@ -35,7 +35,7 @@ static const struct genl_multicast_group psample_nl_mcgrps[] = { [PSAMPLE_NL_MCGRP_SAMPLE] = { .name = PSAMPLE_NL_MCGRP_SAMPLE_NAME }, }; -static struct genl_family psample_nl_family __ro_after_init; +static struct genl_family psample_nl_family; static int psample_group_nl_fill(struct sk_buff *msg, struct psample_group *group, @@ -106,7 +106,7 @@ static const struct genl_ops psample_nl_ops[] = { } }; -static struct genl_family psample_nl_family __ro_after_init = { +static struct genl_family psample_nl_family = { .name = PSAMPLE_GENL_NAME, .version = PSAMPLE_GENL_VERSION, .maxattr = PSAMPLE_ATTR_MAX, @@ -224,7 +224,7 @@ void psample_sample_packet(struct psample_group *group, struct sk_buff *skb, data_len = PSAMPLE_MAX_PACKET_SIZE - meta_len - NLA_HDRLEN - NLA_ALIGNTO; - nl_skb = genlmsg_new(meta_len + data_len, GFP_ATOMIC); + nl_skb = genlmsg_new(meta_len + nla_total_size(data_len), GFP_ATOMIC); if (unlikely(!nl_skb)) return; diff --git a/platform/broadcom/sonic-platform-modules-cel/debian/platform-modules-dx010.install b/platform/broadcom/sonic-platform-modules-cel/debian/platform-modules-dx010.install index 8570fa1eae84..9b456a7c9112 100644 --- a/platform/broadcom/sonic-platform-modules-cel/debian/platform-modules-dx010.install +++ b/platform/broadcom/sonic-platform-modules-cel/debian/platform-modules-dx010.install @@ -1,5 +1,8 @@ dx010/scripts/dx010_check_qsfp.sh usr/local/bin dx010/cfg/dx010-modules.conf etc/modules-load.d dx010/systemd/platform-modules-dx010.service lib/systemd/system +dx010/scripts/fancontrol.sh etc/init.d +services/fancontrol/fancontrol.service lib/systemd/system +services/fancontrol/fancontrol usr/local/bin dx010/modules/sonic_platform-1.0-py2-none-any.whl usr/share/sonic/device/x86_64-cel_seastone-r0 services/platform_api/platform_api_mgnt.sh usr/local/bin diff --git a/platform/broadcom/sonic-platform-modules-cel/debian/platform-modules-dx010.postinst b/platform/broadcom/sonic-platform-modules-cel/debian/platform-modules-dx010.postinst index 15243c935ca3..8dbf0ece6676 100644 --- a/platform/broadcom/sonic-platform-modules-cel/debian/platform-modules-dx010.postinst +++ b/platform/broadcom/sonic-platform-modules-cel/debian/platform-modules-dx010.postinst @@ -1,6 +1,9 @@ depmod -a systemctl enable platform-modules-dx010.service +systemctl enable fancontrol.service + systemctl start platform-modules-dx010.service +systemctl start fancontrol.service /usr/local/bin/platform_api_mgnt.sh install diff --git a/platform/broadcom/sonic-platform-modules-cel/dx010/scripts/fancontrol.sh b/platform/broadcom/sonic-platform-modules-cel/dx010/scripts/fancontrol.sh new file mode 100644 index 000000000000..75ad6c65b37f --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-cel/dx010/scripts/fancontrol.sh @@ -0,0 +1,81 @@ +#! /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 +MAIN_CONF=/usr/share/sonic/device/x86_64-cel_seastone-r0/fancontrol +DEVPATH=/sys/devices/pci0000:00/0000:00:13.0/i2c-*/i2c-13/13-002e +GPIO_DIR=/sys/class/gpio +BASE_GPIO=$(find $GPIO_DIR | grep gpiochip | grep -o '[[:digit:]]*') +DIRGPIO_START=15 + +test -x $DAEMON || exit 0 + +for i in 1 2 3 4 5 +do + FANFAULT=$(cat ${DEVPATH}/fan${i}_fault) + [ $FANFAULT = 1 ] && continue + FANDIR_GPIO_NUMBER=$((DIRGPIO_START + BASE_GPIO)) + FANDIR_VALUE=$(cat ${GPIO_DIR}/gpio${FANDIR_GPIO_NUMBER}/value) + DIRGPIO_START=$((DIRGPIO_START+1)) + FANDIR=$([ $FANDIR_VALUE = 1 ] && echo "B2F" || echo "F2B") +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-cel/services/fancontrol/fancontrol b/platform/broadcom/sonic-platform-modules-cel/services/fancontrol/fancontrol index 9155d8a66998..eb15598b0efa 100755 --- a/platform/broadcom/sonic-platform-modules-cel/services/fancontrol/fancontrol +++ b/platform/broadcom/sonic-platform-modules-cel/services/fancontrol/fancontrol @@ -322,11 +322,12 @@ fi cd $DIR # Check for configuration change -if [ "$DIR" != "/" ] && [ -z "$DEVPATH" -o -z "$DEVNAME" ] -then - echo "Configuration is too old, please run pwmconfig again" >&2 - exit 1 -fi +# if [ "$DIR" != "/" ] && [ -z "$DEVPATH" -o -z "$DEVNAME" ] +# then +# echo "Configuration is too old, please run pwmconfig again" >&2 +# exit 1 +# fi + if [ "$DIR" = "/" -a -n "$DEVPATH" ] then echo "Unneeded DEVPATH with absolute device paths" >&2 diff --git a/platform/broadcom/sonic-platform-modules-dell/s6000/sonic_platform/chassis.py b/platform/broadcom/sonic-platform-modules-dell/s6000/sonic_platform/chassis.py index 8bb95cac1d63..06fb6c2ff0e9 100755 --- a/platform/broadcom/sonic-platform-modules-dell/s6000/sonic_platform/chassis.py +++ b/platform/broadcom/sonic-platform-modules-dell/s6000/sonic_platform/chassis.py @@ -15,7 +15,7 @@ import subprocess from sonic_platform_base.chassis_base import ChassisBase from sonic_platform.sfp import Sfp - from sonic_platform.eeprom import Eeprom + from sonic_platform.eeprom import Eeprom, EepromS6000 from sonic_platform.fan import Fan from sonic_platform.psu import Psu from sonic_platform.thermal import Thermal @@ -68,7 +68,14 @@ def __init__(self): # Get Transceiver status self.modprs_register = self._get_transceiver_status() - self._eeprom = Eeprom() + with open("/sys/class/dmi/id/product_name", "r") as fd: + board_type = fd.read() + + if 'S6000-ON' in board_type: + self._eeprom = Eeprom() + else: + self._eeprom = EepromS6000() + for i in range(MAX_S6000_FAN): fan = Fan(i) self._fan_list.append(fan) @@ -138,7 +145,7 @@ def get_name(self): Returns: string: The name of the chassis """ - return self._eeprom.modelstr() + return self._eeprom.get_model() def get_presence(self): """ @@ -154,7 +161,7 @@ def get_model(self): Returns: string: Model/part number of chassis """ - return self._eeprom.part_number_str() + return self._eeprom.get_part_number() def get_serial(self): """ @@ -162,7 +169,7 @@ def get_serial(self): Returns: string: Serial number of chassis """ - return self._eeprom.serial_str() + return self._eeprom.get_serial() def get_status(self): """ @@ -181,7 +188,7 @@ def get_base_mac(self): A string containing the MAC address in the format 'XX:XX:XX:XX:XX:XX' """ - return self._eeprom.base_mac_addr() + return self._eeprom.get_base_mac() def get_serial_number(self): """ @@ -191,7 +198,7 @@ def get_serial_number(self): A string containing the hardware serial number for this chassis. """ - return self._eeprom.serial_number_str() + return self._eeprom.get_serial_number() def get_system_eeprom_info(self): """ @@ -237,13 +244,32 @@ def _get_transceiver_status(self): return int(content, 16) - def get_transceiver_change_event(self, timeout=0): + def get_change_event(self, timeout=0): """ - Returns a dictionary containing sfp changes which have + Returns a nested dictionary containing all devices which have experienced a change at chassis level + + Args: + timeout: Timeout in milliseconds (optional). If timeout == 0, + this method will block until a change is detected. + + Returns: + (bool, dict): + - True if call successful, False if not; + - A nested dictionary where key is a device type, + value is a dictionary with key:value pairs in the + format of {'device_id':'device_event'}, + where device_id is the device ID for this device and + device_event, + status='1' represents device inserted, + status='0' represents device removed. + Ex. {'fan':{'0':'0', '2':'1'}, 'sfp':{'11':'0'}} + indicates that fan 0 has been removed, fan 2 + has been inserted and sfp 11 has been removed. """ start_time = time.time() port_dict = {} + ret_dict = {"sfp": port_dict} port = self.PORT_START forever = False @@ -256,7 +282,7 @@ def get_transceiver_change_event(self, timeout=0): end_time = start_time + timeout if (start_time > end_time): - return False, {} # Time wrap or possibly incorrect timeout + return False, ret_dict # Time wrap or possibly incorrect timeout while (timeout >= 0): # Check for OIR events and return updated port_dict @@ -276,7 +302,7 @@ def get_transceiver_change_event(self, timeout=0): # Update reg value self.modprs_register = reg_value - return True, port_dict + return True, ret_dict if forever: time.sleep(1) @@ -287,7 +313,7 @@ def get_transceiver_change_event(self, timeout=0): else: if timeout > 0: time.sleep(timeout) - return True, {} - return False, {} + return True, ret_dict + return False, ret_dict diff --git a/platform/broadcom/sonic-platform-modules-dell/s6000/sonic_platform/eeprom.py b/platform/broadcom/sonic-platform-modules-dell/s6000/sonic_platform/eeprom.py index a82fd6a70201..1a8a3a84b601 100644 --- a/platform/broadcom/sonic-platform-modules-dell/s6000/sonic_platform/eeprom.py +++ b/platform/broadcom/sonic-platform-modules-dell/s6000/sonic_platform/eeprom.py @@ -17,12 +17,17 @@ try: + import binascii import os + import redis + import struct + from collections import OrderedDict from sonic_platform_base.sonic_eeprom.eeprom_base import EepromDecoder from sonic_platform_base.sonic_eeprom.eeprom_tlvinfo import TlvInfoDecoder except ImportError as e: raise ImportError(str(e) + "- required module not found") +STATE_DB_INDEX = 6 # PSU eeprom fields in format required by EepromDecoder psu_eeprom_format = [ @@ -200,13 +205,13 @@ def _get_eeprom_field(self, field_name): return (False, None) - def serial_number_str(self): + def get_serial_number(self): """ Returns the serial number. """ return self.serial_number - def part_number_str(self): + def get_part_number(self): """ Returns the part number. """ @@ -222,19 +227,19 @@ def airflow_fan_type(self): return int(self.fan_type.encode('hex'), 16) # System EEPROM specific methods - def base_mac_addr(self): + def get_base_mac(self): """ Returns the base MAC address found in the system EEPROM. """ return self.base_mac - def modelstr(self): + def get_model(self): """ Returns the Model name. """ return self.model_str - def serial_str(self): + def get_serial(self): """ Returns the servicetag number. """ @@ -247,3 +252,252 @@ def system_eeprom_info(self): found in the system EEPROM. """ return self.eeprom_tlv_dict + + +class EepromS6000(EepromDecoder): + + _EEPROM_MAX_LEN = 128 + + _BLK_HDR_LEN = 6 + _BLK_HDR_MAGIC = '\x3a\x29' + _BLK_HDR_REVID = 1 + + _BLK_CODE_MFG = 0x20 + _BLK_CODE_SW = 0x1F + _BLK_CODE_MAC = 0x21 + + _BLK_MFG_FORMAT = [ + ("PPID", 20), ("DPN Rev", 3), ("Service Tag", 7), ("Part Number", 10), + ("Part Number Rev", 3), ("Mfg Test Results", 2) + ] + + _BLK_SW_FORMAT = [("Card ID", 4), ("Module ID", 2)] + _BLK_MAC_FORMAT = [("Base MAC address", 6)] + + _BLK_INFO = OrderedDict([ + (_BLK_CODE_MFG, {"name": "MFG BLOCK", "size": 64, + "offset": 0x0, "format": _BLK_MFG_FORMAT}), + (_BLK_CODE_SW, {"name": "SW BLOCK", "size": 48, + "offset": 0x40, "format": _BLK_SW_FORMAT}), + (_BLK_CODE_MAC, {"name": "MAC BLOCK", "size": 16, + "offset": 0x70, "format": _BLK_MAC_FORMAT}) + ]) + + def __init__(self, is_plugin=False): + self.eeprom_path = "/sys/bus/i2c/devices/i2c-10/10-0053/eeprom" + super(EepromS6000, self).__init__(self.eeprom_path, None, 0, '', True) + + if not is_plugin: + self.eeprom_data = self.read_eeprom() + + def _is_valid_block_checksum(self, e): + crc = self.compute_dell_crc(e[:-2]) + return crc == struct.unpack('3d} {:3d} {: /sys/bus/pci/devices/0000:02:00.0/remove + [ -d $pericom ] && echo 1 > $pericom/remove + # Disable Watchdog Timer if [[ -e /usr/local/bin/platform_watchdog_disable.sh ]]; then /usr/local/bin/platform_watchdog_disable.sh diff --git a/platform/broadcom/sonic-platform-modules-dell/s6100/sonic_platform/chassis.py b/platform/broadcom/sonic-platform-modules-dell/s6100/sonic_platform/chassis.py index a1c7692b5f6e..3284e671bfe0 100755 --- a/platform/broadcom/sonic-platform-modules-dell/s6100/sonic_platform/chassis.py +++ b/platform/broadcom/sonic-platform-modules-dell/s6100/sonic_platform/chassis.py @@ -39,6 +39,7 @@ class Chassis(ChassisBase): HWMON_DIR = "/sys/devices/platform/SMF.512/hwmon/" HWMON_NODE = os.listdir(HWMON_DIR)[0] MAILBOX_DIR = HWMON_DIR + HWMON_NODE + POLL_INTERVAL = 1 # Poll interval in seconds reset_reason_dict = {} reset_reason_dict[11] = ChassisBase.REBOOT_CAUSE_POWER_LOSS @@ -81,6 +82,7 @@ def __init__(self): self._component_list.append(component) self._watchdog = Watchdog() + self._transceiver_presence = self._get_transceiver_presence() def _get_reboot_reason_smf_register(self): # In S6100, mb_poweron_reason register will @@ -111,6 +113,24 @@ def _get_pmc_register(self, reg_name): rv = rv.lstrip(" ") return rv + def _get_register(self, reg_file): + # On successful read, returns the value read from given + # reg_name and on failure returns 'ERR' + rv = 'ERR' + + if (not os.path.isfile(reg_file)): + return rv + + try: + with open(reg_file, 'r') as fd: + rv = fd.read() + except Exception as error: + rv = 'ERR' + + rv = rv.rstrip('\r\n') + rv = rv.lstrip(" ") + return rv + def get_name(self): """ Retrieves the name of the chassis @@ -215,3 +235,103 @@ def get_reboot_cause(self): return (ChassisBase.REBOOT_CAUSE_NON_HARDWARE, None) return (ChassisBase.REBOOT_CAUSE_HARDWARE_OTHER, "Invalid Reason") + + def _get_transceiver_presence(self): + + cpld2_modprs = self._get_register( + "/sys/class/i2c-adapter/i2c-14/14-003e/qsfp_modprs") + cpld3_modprs = self._get_register( + "/sys/class/i2c-adapter/i2c-15/15-003e/qsfp_modprs") + cpld4_modprs = self._get_register( + "/sys/class/i2c-adapter/i2c-16/16-003e/qsfp_modprs") + cpld5_modprs = self._get_register( + "/sys/class/i2c-adapter/i2c-17/17-003e/qsfp_modprs") + + # If IOM is not present, register read will fail. + # Handle the scenario gracefully + if (cpld2_modprs == 'read error') or (cpld2_modprs == 'ERR'): + cpld2_modprs = '0x0' + if (cpld3_modprs == 'read error') or (cpld3_modprs == 'ERR'): + cpld3_modprs = '0x0' + if (cpld4_modprs == 'read error') or (cpld4_modprs == 'ERR'): + cpld4_modprs = '0x0' + if (cpld5_modprs == 'read error') or (cpld5_modprs == 'ERR'): + cpld5_modprs = '0x0' + + # Make it contiguous + transceiver_presence = (int(cpld2_modprs, 16) & 0xffff) |\ + ((int(cpld4_modprs, 16) & 0xffff) << 16) |\ + ((int(cpld3_modprs, 16) & 0xffff) << 32) |\ + ((int(cpld5_modprs, 16) & 0xffff) << 48) + + return transceiver_presence + + def get_change_event(self, timeout=0): + """ + Returns a nested dictionary containing all devices which have + experienced a change at chassis level + + Args: + timeout: Timeout in milliseconds (optional). If timeout == 0, + this method will block until a change is detected. + + Returns: + (bool, dict): + - True if call successful, False if not; + - A nested dictionary where key is a device type, + value is a dictionary with key:value pairs in the + format of {'device_id':'device_event'}, + where device_id is the device ID for this device and + device_event, + status='1' represents device inserted, + status='0' represents device removed. + Ex. {'fan':{'0':'0', '2':'1'}, 'sfp':{'11':'0'}} + indicates that fan 0 has been removed, fan 2 + has been inserted and sfp 11 has been removed. + """ + port_dict = {} + ret_dict = {'sfp': port_dict} + forever = False + + if timeout == 0: + forever = True + elif timeout > 0: + timeout = timeout / float(1000) # Convert to secs + else: + return False, ret_dict # Incorrect timeout + + while True: + if forever: + timer = self.POLL_INTERVAL + else: + timer = min(timeout, self.POLL_INTERVAL) + start_time = time.time() + + time.sleep(timer) + cur_presence = self._get_transceiver_presence() + + # Update dict only if a change has been detected + if cur_presence != self._transceiver_presence: + changed_ports = self._transceiver_presence ^ cur_presence + for port in range(self.get_num_sfps()): + # Mask off the bit corresponding to particular port + mask = 1 << port + if changed_ports & mask: + # qsfp_modprs 1 => optics is removed + if cur_presence & mask: + port_dict[port] = '0' + # qsfp_modprs 0 => optics is inserted + else: + port_dict[port] = '1' + + # Update current presence + self._transceiver_presence = cur_presence + break + + if not forever: + elapsed_time = time.time() - start_time + timeout = round(timeout - elapsed_time, 3) + if timeout <= 0: + break + + return True, ret_dict diff --git a/platform/broadcom/sonic-platform-modules-dell/s6100/sonic_platform/thermal.py b/platform/broadcom/sonic-platform-modules-dell/s6100/sonic_platform/thermal.py index 3947f4c84957..c6f6314dcb6d 100644 --- a/platform/broadcom/sonic-platform-modules-dell/s6100/sonic_platform/thermal.py +++ b/platform/broadcom/sonic-platform-modules-dell/s6100/sonic_platform/thermal.py @@ -138,11 +138,11 @@ def get_temperature(self): thermal_temperature = self._read_sysfs_file( self.thermal_temperature_file) if (thermal_temperature != 'ERR'): - thermal_temperature = float(thermal_temperature) / 1000 + thermal_temperature = float(thermal_temperature) else: thermal_temperature = 0 - return "{:.3f}".format(thermal_temperature) + return thermal_temperature / 1000.0 def get_high_threshold(self): """ @@ -156,11 +156,11 @@ def get_high_threshold(self): thermal_high_threshold = self._read_sysfs_file( self.thermal_high_threshold_file) if (thermal_high_threshold != 'ERR'): - thermal_high_threshold = float(thermal_high_threshold) / 1000 + thermal_high_threshold = float(thermal_high_threshold) else: thermal_high_threshold = 0 - return "{:.3f}".format(thermal_high_threshold) + return thermal_high_threshold / 1000.0 def get_low_threshold(self): """ @@ -174,11 +174,11 @@ def get_low_threshold(self): thermal_low_threshold = self._read_sysfs_file( self.thermal_low_threshold_file) if (thermal_low_threshold != 'ERR'): - thermal_low_threshold = float(thermal_low_threshold) / 1000 + thermal_low_threshold = float(thermal_low_threshold) else: thermal_low_threshold = 0 - return "{:.3f}".format(thermal_low_threshold) + return thermal_low_threshold / 1000.0 def set_high_threshold(self, temperature): """ diff --git a/platform/broadcom/sonic-platform-modules-dell/z9100/sonic_platform/chassis.py b/platform/broadcom/sonic-platform-modules-dell/z9100/sonic_platform/chassis.py index 3e070d54004e..3f03f9671f91 100755 --- a/platform/broadcom/sonic-platform-modules-dell/z9100/sonic_platform/chassis.py +++ b/platform/broadcom/sonic-platform-modules-dell/z9100/sonic_platform/chassis.py @@ -10,8 +10,8 @@ try: import os - import subprocess - import re + import select + import sys from sonic_platform_base.chassis_base import ChassisBase from sonic_platform.sfp import Sfp from sonic_platform.fan import Fan @@ -60,6 +60,8 @@ class Chassis(ChassisBase): 28: [16, 6], 29: [16, 7], 30: [16, 8], 31: [16, 9] } + OIR_FD_PATH = "/sys/devices/platform/dell_ich.0/sci_int_gpio_sus6" + reset_reason_dict = {} reset_reason_dict[11] = ChassisBase.REBOOT_CAUSE_POWER_LOSS reset_reason_dict[33] = ChassisBase.REBOOT_CAUSE_WATCHDOG @@ -74,6 +76,8 @@ class Chassis(ChassisBase): def __init__(self): ChassisBase.__init__(self) + self.oir_fd = -1 + self.epoll = -1 PORT_START = 0 PORT_END = 31 PORTS_IN_BLOCK = (PORT_END + 1) @@ -112,6 +116,12 @@ def __init__(self): component = Component(i) self._component_list.append(component) + def __del__(self): + if self.oir_fd != -1: + self.epoll.unregister(self.oir_fd.fileno()) + self.epoll.close() + self.oir_fd.close() + def _get_pmc_register(self, reg_name): # On successful read, returns the value read from given # reg_name and on failure returns 'ERR' @@ -131,6 +141,24 @@ def _get_pmc_register(self, reg_name): rv = rv.lstrip(" ") return rv + def _get_register(self, reg_file): + # On successful read, returns the value read from given + # reg_name and on failure returns 'ERR' + rv = 'ERR' + + if (not os.path.isfile(reg_file)): + return rv + + try: + with open(reg_file, 'r') as fd: + rv = fd.read() + except Exception as error: + rv = 'ERR' + + rv = rv.rstrip('\r\n') + rv = rv.lstrip(" ") + return rv + def get_name(self): """ Retrieves the name of the chassis @@ -162,7 +190,7 @@ def get_serial(self): string: Serial number of chassis """ return self._eeprom.serial_str() - + def get_sfp(self, index): """ Retrieves sfp represented by (1-based) index @@ -252,3 +280,132 @@ def get_reboot_cause(self): return (self.reset_reason_dict[reset_reason], None) return (ChassisBase.REBOOT_CAUSE_HARDWARE_OTHER, "Invalid Reason") + + def _check_interrupts(self, port_dict): + is_port_dict_updated = False + + cpld2_abs_int = self._get_register( + "/sys/class/i2c-adapter/i2c-14/14-003e/qsfp_abs_int") + cpld2_abs_sta = self._get_register( + "/sys/class/i2c-adapter/i2c-14/14-003e/qsfp_abs_sta") + cpld3_abs_int = self._get_register( + "/sys/class/i2c-adapter/i2c-15/15-003e/qsfp_abs_int") + cpld3_abs_sta = self._get_register( + "/sys/class/i2c-adapter/i2c-15/15-003e/qsfp_abs_sta") + cpld4_abs_int = self._get_register( + "/sys/class/i2c-adapter/i2c-16/16-003e/qsfp_abs_int") + cpld4_abs_sta = self._get_register( + "/sys/class/i2c-adapter/i2c-16/16-003e/qsfp_abs_sta") + + if (cpld2_abs_int == 'ERR' or cpld2_abs_sta == 'ERR' or + cpld3_abs_int == 'ERR' or cpld3_abs_sta == 'ERR' or + cpld4_abs_int == 'ERR' or cpld4_abs_sta == 'ERR'): + return False, is_port_dict_updated + + cpld2_abs_int = int(cpld2_abs_int, 16) + cpld2_abs_sta = int(cpld2_abs_sta, 16) + cpld3_abs_int = int(cpld3_abs_int, 16) + cpld3_abs_sta = int(cpld3_abs_sta, 16) + cpld4_abs_int = int(cpld4_abs_int, 16) + cpld4_abs_sta = int(cpld4_abs_sta, 16) + + # Make it contiguous (discard reserved bits) + interrupt_reg = (cpld2_abs_int & 0xfff) |\ + ((cpld3_abs_int & 0x3ff) << 12) |\ + ((cpld4_abs_int & 0x3ff) << 22) + status_reg = (cpld2_abs_sta & 0xfff) |\ + ((cpld3_abs_sta & 0x3ff) << 12) |\ + ((cpld4_abs_sta & 0x3ff) << 22) + + for port in range(self.get_num_sfps()): + if interrupt_reg & (1 << port): + # update only if atleast one port has generated + # interrupt + is_port_dict_updated = True + if status_reg & (1 << port): + # status reg 1 => optics is removed + port_dict[port+1] = '0' + else: + # status reg 0 => optics is inserted + port_dict[port+1] = '1' + + return True, is_port_dict_updated + + def get_change_event(self, timeout=0): + """ + Returns a nested dictionary containing all devices which have + experienced a change at chassis level + + Args: + timeout: Timeout in milliseconds (optional). If timeout == 0, + this method will block until a change is detected. + + Returns: + (bool, dict): + - True if call successful, False if not; + - A nested dictionary where key is a device type, + value is a dictionary with key:value pairs in the + format of {'device_id':'device_event'}, + where device_id is the device ID for this device and + device_event, + status='1' represents device inserted, + status='0' represents device removed. + Ex. {'fan':{'0':'0', '2':'1'}, 'sfp':{'11':'0'}} + indicates that fan 0 has been removed, fan 2 + has been inserted and sfp 11 has been removed. + """ + port_dict = {} + ret_dict = {'sfp': port_dict} + if timeout != 0: + timeout = timeout / 1000 + try: + # We get notified when there is an SCI interrupt from GPIO SUS6 + # Open the sysfs file and register the epoll object + self.oir_fd = open(self.OIR_FD_PATH, "r") + if self.oir_fd != -1: + # Do a dummy read before epoll register + self.oir_fd.read() + self.epoll = select.epoll() + self.epoll.register(self.oir_fd.fileno(), + select.EPOLLIN & select.EPOLLET) + else: + return False, ret_dict + + # Check for missed interrupts by invoking self.check_interrupts + # which will update the port_dict. + while True: + interrupt_count_start = self._get_register(self.OIR_FD_PATH) + + retval, is_port_dict_updated = \ + self._check_interrupts(port_dict) + if (retval is True) and (is_port_dict_updated is True): + return True, ret_dict + + interrupt_count_end = self._get_register(self.OIR_FD_PATH) + + if (interrupt_count_start == 'ERR' or + interrupt_count_end == 'ERR'): + break + + # check_interrupts() itself may take upto 100s of msecs. + # We detect a missed interrupt based on the count + if interrupt_count_start == interrupt_count_end: + break + + # Block until an xcvr is inserted or removed with timeout = -1 + events = self.epoll.poll(timeout=timeout if timeout != 0 else -1) + if events: + # check interrupts and return the port_dict + retval, is_port_dict_updated = \ + self._check_interrupts(port_dict) + + return retval, ret_dict + except Exception: + return False, ret_dict + finally: + if self.oir_fd != -1: + self.epoll.unregister(self.oir_fd.fileno()) + self.epoll.close() + self.oir_fd.close() + self.oir_fd = -1 + self.epoll = -1 diff --git a/platform/broadcom/sonic-platform-modules-dell/z9100/sonic_platform/thermal.py b/platform/broadcom/sonic-platform-modules-dell/z9100/sonic_platform/thermal.py index 05d012b114c0..e781a545e8ea 100644 --- a/platform/broadcom/sonic-platform-modules-dell/z9100/sonic_platform/thermal.py +++ b/platform/broadcom/sonic-platform-modules-dell/z9100/sonic_platform/thermal.py @@ -134,11 +134,11 @@ def get_temperature(self): thermal_temperature = self._read_sysfs_file( self.thermal_temperature_file) if (thermal_temperature != 'ERR'): - thermal_temperature = float(thermal_temperature) / 1000 + thermal_temperature = float(thermal_temperature) else: thermal_temperature = 0 - return "{:.3f}".format(thermal_temperature) + return thermal_temperature / 1000.0 def get_high_threshold(self): """ @@ -152,11 +152,11 @@ def get_high_threshold(self): thermal_high_threshold = self._read_sysfs_file( self.thermal_high_threshold_file) if (thermal_high_threshold != 'ERR'): - thermal_high_threshold = float(thermal_high_threshold) / 1000 + thermal_high_threshold = float(thermal_high_threshold) else: thermal_high_threshold = 0 - return "{:.3f}".format(thermal_high_threshold) + return thermal_high_threshold / 1000.0 def get_low_threshold(self): """ @@ -170,11 +170,11 @@ def get_low_threshold(self): thermal_low_threshold = self._read_sysfs_file( self.thermal_low_threshold_file) if (thermal_low_threshold != 'ERR'): - thermal_low_threshold = float(thermal_low_threshold) / 1000 + thermal_low_threshold = float(thermal_low_threshold) else: thermal_low_threshold = 0 - return "{:.3f}".format(thermal_low_threshold) + return thermal_low_threshold / 1000.0 def set_high_threshold(self, temperature): """ diff --git a/platform/cavium/docker-syncd-cavm/base_image_files/monit_syncd b/platform/cavium/docker-syncd-cavm/base_image_files/monit_syncd index 3079618990ed..75391f90ac32 100644 --- a/platform/cavium/docker-syncd-cavm/base_image_files/monit_syncd +++ b/platform/cavium/docker-syncd-cavm/base_image_files/monit_syncd @@ -3,5 +3,5 @@ ## process list: ## syncd ############################################################################### -check process syncd matching "/usr/bin/syncd" +check process syncd matching "/usr/bin/syncd\s" if does not exist for 5 times within 5 cycles then alert diff --git a/platform/cavium/docker-syncd-cavm/critical_processes b/platform/cavium/docker-syncd-cavm/critical_processes index 6082f242b872..bdd6903c5690 100644 --- a/platform/cavium/docker-syncd-cavm/critical_processes +++ b/platform/cavium/docker-syncd-cavm/critical_processes @@ -1 +1 @@ -syncd +program:syncd diff --git a/platform/centec/docker-syncd-centec/base_image_files/monit_syncd b/platform/centec/docker-syncd-centec/base_image_files/monit_syncd index 3079618990ed..75391f90ac32 100644 --- a/platform/centec/docker-syncd-centec/base_image_files/monit_syncd +++ b/platform/centec/docker-syncd-centec/base_image_files/monit_syncd @@ -3,5 +3,5 @@ ## process list: ## syncd ############################################################################### -check process syncd matching "/usr/bin/syncd" +check process syncd matching "/usr/bin/syncd\s" if does not exist for 5 times within 5 cycles then alert diff --git a/platform/centec/docker-syncd-centec/critical_processes b/platform/centec/docker-syncd-centec/critical_processes index 6082f242b872..bdd6903c5690 100644 --- a/platform/centec/docker-syncd-centec/critical_processes +++ b/platform/centec/docker-syncd-centec/critical_processes @@ -1 +1 @@ -syncd +program:syncd diff --git a/platform/marvell-arm64/docker-syncd-mrvl/base_image_files/monit_syncd b/platform/marvell-arm64/docker-syncd-mrvl/base_image_files/monit_syncd index 3079618990ed..75391f90ac32 100644 --- a/platform/marvell-arm64/docker-syncd-mrvl/base_image_files/monit_syncd +++ b/platform/marvell-arm64/docker-syncd-mrvl/base_image_files/monit_syncd @@ -3,5 +3,5 @@ ## process list: ## syncd ############################################################################### -check process syncd matching "/usr/bin/syncd" +check process syncd matching "/usr/bin/syncd\s" if does not exist for 5 times within 5 cycles then alert diff --git a/platform/marvell-arm64/docker-syncd-mrvl/critical_processes b/platform/marvell-arm64/docker-syncd-mrvl/critical_processes index 6082f242b872..bdd6903c5690 100644 --- a/platform/marvell-arm64/docker-syncd-mrvl/critical_processes +++ b/platform/marvell-arm64/docker-syncd-mrvl/critical_processes @@ -1 +1 @@ -syncd +program:syncd diff --git a/platform/marvell-armhf/docker-syncd-mrvl/base_image_files/monit_syncd b/platform/marvell-armhf/docker-syncd-mrvl/base_image_files/monit_syncd index 3079618990ed..75391f90ac32 100644 --- a/platform/marvell-armhf/docker-syncd-mrvl/base_image_files/monit_syncd +++ b/platform/marvell-armhf/docker-syncd-mrvl/base_image_files/monit_syncd @@ -3,5 +3,5 @@ ## process list: ## syncd ############################################################################### -check process syncd matching "/usr/bin/syncd" +check process syncd matching "/usr/bin/syncd\s" if does not exist for 5 times within 5 cycles then alert diff --git a/platform/marvell-armhf/docker-syncd-mrvl/critical_processes b/platform/marvell-armhf/docker-syncd-mrvl/critical_processes index 6082f242b872..bdd6903c5690 100644 --- a/platform/marvell-armhf/docker-syncd-mrvl/critical_processes +++ b/platform/marvell-armhf/docker-syncd-mrvl/critical_processes @@ -1 +1 @@ -syncd +program:syncd diff --git a/platform/marvell/docker-syncd-mrvl/base_image_files/monit_syncd b/platform/marvell/docker-syncd-mrvl/base_image_files/monit_syncd index 3079618990ed..75391f90ac32 100644 --- a/platform/marvell/docker-syncd-mrvl/base_image_files/monit_syncd +++ b/platform/marvell/docker-syncd-mrvl/base_image_files/monit_syncd @@ -3,5 +3,5 @@ ## process list: ## syncd ############################################################################### -check process syncd matching "/usr/bin/syncd" +check process syncd matching "/usr/bin/syncd\s" if does not exist for 5 times within 5 cycles then alert diff --git a/platform/marvell/docker-syncd-mrvl/critical_processes b/platform/marvell/docker-syncd-mrvl/critical_processes index 6082f242b872..bdd6903c5690 100644 --- a/platform/marvell/docker-syncd-mrvl/critical_processes +++ b/platform/marvell/docker-syncd-mrvl/critical_processes @@ -1 +1 @@ -syncd +program:syncd diff --git a/platform/mellanox/docker-syncd-mlnx/base_image_files/monit_syncd b/platform/mellanox/docker-syncd-mlnx/base_image_files/monit_syncd index 3079618990ed..75391f90ac32 100644 --- a/platform/mellanox/docker-syncd-mlnx/base_image_files/monit_syncd +++ b/platform/mellanox/docker-syncd-mlnx/base_image_files/monit_syncd @@ -3,5 +3,5 @@ ## process list: ## syncd ############################################################################### -check process syncd matching "/usr/bin/syncd" +check process syncd matching "/usr/bin/syncd\s" if does not exist for 5 times within 5 cycles then alert diff --git a/platform/mellanox/docker-syncd-mlnx/critical_processes b/platform/mellanox/docker-syncd-mlnx/critical_processes index 6082f242b872..bdd6903c5690 100644 --- a/platform/mellanox/docker-syncd-mlnx/critical_processes +++ b/platform/mellanox/docker-syncd-mlnx/critical_processes @@ -1 +1 @@ -syncd +program:syncd diff --git a/platform/mellanox/fw.mk b/platform/mellanox/fw.mk index 57cf8d6ecd06..35265337fe21 100644 --- a/platform/mellanox/fw.mk +++ b/platform/mellanox/fw.mk @@ -11,17 +11,17 @@ else FW_FROM_URL = n endif -MLNX_SPC_FW_VERSION = 13.2007.1140 +MLNX_SPC_FW_VERSION = 13.2007.1280 MLNX_SPC_FW_FILE = fw-SPC-rel-$(subst .,_,$(MLNX_SPC_FW_VERSION))-EVB.mfa $(MLNX_SPC_FW_FILE)_PATH = $(MLNX_FW_BASE_PATH) $(MLNX_SPC_FW_FILE)_URL = $(MLNX_FW_BASE_URL)/$(MLNX_SPC_FW_FILE) -MLNX_SPC2_FW_VERSION = 29.2007.1140 +MLNX_SPC2_FW_VERSION = 29.2007.1280 MLNX_SPC2_FW_FILE = fw-SPC2-rel-$(subst .,_,$(MLNX_SPC2_FW_VERSION))-EVB.mfa $(MLNX_SPC2_FW_FILE)_PATH = $(MLNX_FW_BASE_PATH) $(MLNX_SPC2_FW_FILE)_URL = $(MLNX_FW_BASE_URL)/$(MLNX_SPC2_FW_FILE) -MLNX_SPC3_FW_VERSION = 30.2007.1140 +MLNX_SPC3_FW_VERSION = 30.2007.1280 MLNX_SPC3_FW_FILE = fw-SPC3-rel-$(subst .,_,$(MLNX_SPC3_FW_VERSION))-EVB.mfa $(MLNX_SPC3_FW_FILE)_PATH = $(MLNX_FW_BASE_PATH) $(MLNX_SPC3_FW_FILE)_URL = $(MLNX_FW_BASE_URL)/$(MLNX_SPC3_FW_FILE) diff --git a/platform/mellanox/hw-management.mk b/platform/mellanox/hw-management.mk index 4f08fe363a8a..1acb806c828d 100644 --- a/platform/mellanox/hw-management.mk +++ b/platform/mellanox/hw-management.mk @@ -1,6 +1,6 @@ # Mellanox HW Management -MLNX_HW_MANAGEMENT_VERSION = 7.0000.3034 +MLNX_HW_MANAGEMENT_VERSION = 7.0010.1000 export MLNX_HW_MANAGEMENT_VERSION diff --git a/platform/mellanox/hw-management/0001-Make-hw-mgmt-SimX-compatiable.patch b/platform/mellanox/hw-management/0001-Make-hw-mgmt-SimX-compatiable.patch deleted file mode 100644 index a72c94473e88..000000000000 --- a/platform/mellanox/hw-management/0001-Make-hw-mgmt-SimX-compatiable.patch +++ /dev/null @@ -1,53 +0,0 @@ -From ebb17bd1f6996f73cb67313846a63c789e74c4f4 Mon Sep 17 00:00:00 2001 -From: Mykola Faryma -Date: Fri, 21 Feb 2020 12:28:54 +0200 -Subject: [PATCH 1/1] Make hw-mgmt SimX compatiable - -Signed-off-by: Mykola Faryma ---- - usr/usr/bin/hw-management.sh | 29 +++++++++++++++++++++++++++++ - 1 file changed, 29 insertions(+) - -diff --git a/usr/usr/bin/hw-management.sh b/usr/usr/bin/hw-management.sh -index 1b5b18a..3dfd4b1 100755 ---- a/usr/usr/bin/hw-management.sh -+++ b/usr/usr/bin/hw-management.sh -@@ -943,6 +943,35 @@ do_chip_down() - /usr/bin/hw-management-thermal-events.sh change hotplug_asic down %S %p - } - -+handle_simx() -+{ -+ local -r onie_platform="$(cat /host/machine.conf | grep onie_platform | cut -d= -f2)" -+ -+ local -r syseeprom_cache_path="/var/cache/sonic/decode-syseeprom/syseeprom_cache" -+ local -r syseeprom_hex_path="/usr/share/sonic/device/${onie_platform}/syseeprom.hex" -+ local -r syseeprom_vpd_path="/var/run/hw-management/eeprom/vpd_info" -+ -+ case $ACTION in -+ start) -+ /bin/bash -c "/bin/rm -f ${syseeprom_cache_path}" -+ /bin/bash -c "/bin/mkdir -p ${eeprom_path}" -+ /bin/bash -c "/usr/bin/xxd -r -p ${syseeprom_hex_path} ${syseeprom_vpd_path}" -+ ;; -+ stop) -+ /bin/bash -c "/bin/rm -fr ${hw_management_path}" -+ ;; -+ *) -+ echo "Usage: `basename $0` {start|stop}" -+ exit 1 -+ ;; -+ esac -+} -+ -+if [[ "$(cat /sys/devices/virtual/dmi/id/sys_vendor)" = "QEMU" ]]; then -+ handle_simx -+ exit 0 -+fi -+ - case $ACTION in - start) - if [ -d /var/run/hw-management ]; then --- -1.9.1 - diff --git a/platform/mellanox/hw-management/0001-hw-management.sh-Disable-thermal-policy-running-in-h.patch b/platform/mellanox/hw-management/0001-hw-management.sh-Disable-thermal-policy-running-in-h.patch new file mode 100644 index 000000000000..2bdadebcd0c2 --- /dev/null +++ b/platform/mellanox/hw-management/0001-hw-management.sh-Disable-thermal-policy-running-in-h.patch @@ -0,0 +1,27 @@ +From 3512488c981eb81d51ce92cb3573721e36861f56 Mon Sep 17 00:00:00 2001 +From: Junchao Chen +Date: Fri, 29 May 2020 10:38:53 +0300 +Subject: [PATCH] Disable hw-management thermal control service + +--- + usr/usr/bin/hw-management.sh | 4 +++- + 1 file changed, 3 insertions(+), 1 deletion(-) + +diff --git a/usr/usr/bin/hw-management.sh b/usr/usr/bin/hw-management.sh +index 65e5d39..0d1c4a1 100755 +--- a/usr/usr/bin/hw-management.sh ++++ b/usr/usr/bin/hw-management.sh +@@ -832,7 +832,9 @@ do_start() + if [ -f $config_path/max_tachos ]; then + max_tachos=$(<$config_path/max_tachos) + fi +- $THERMAL_CONTROL $thermal_type $max_tachos $max_psus& ++ # Disable hw-management thermal control because ++ # SONiC already implement it ++ #$THERMAL_CONTROL $thermal_type $max_tachos $max_psus& + } + + do_stop() +-- +1.9.1 + diff --git a/platform/mellanox/hw-management/hw-mgmt b/platform/mellanox/hw-management/hw-mgmt index 39f66b8e1997..cdacf1e932f9 160000 --- a/platform/mellanox/hw-management/hw-mgmt +++ b/platform/mellanox/hw-management/hw-mgmt @@ -1 +1 @@ -Subproject commit 39f66b8e1997868bbec297d7ae38f4e4ccc9009d +Subproject commit cdacf1e932f929c8dedde6c7e14759a2083aac66 diff --git a/platform/mellanox/mft.mk b/platform/mellanox/mft.mk index 229ba86b4a7b..95e9f84e84a0 100644 --- a/platform/mellanox/mft.mk +++ b/platform/mellanox/mft.mk @@ -1,7 +1,7 @@ # Mellanox SAI -MFT_VERSION = 4.14.0 -MFT_REVISION = 500 +MFT_VERSION = 4.14.5 +MFT_REVISION = 2 export MFT_VERSION MFT_REVISION diff --git a/platform/mellanox/mlnx-onie-fw-update.sh b/platform/mellanox/mlnx-onie-fw-update.sh index 314f4ed70268..5a62e74b647b 100755 --- a/platform/mellanox/mlnx-onie-fw-update.sh +++ b/platform/mellanox/mlnx-onie-fw-update.sh @@ -1,120 +1,205 @@ -#!/bin/sh +#!/bin/bash # Copyright (C) 2019 Mellanox Technologies Ltd. # Copyright (C) 2019 Michael Shych # # SPDX-License-Identifier: GPL-2.0 -this_script=${ONIE_FWPKG_PROGRAM_NAME:-$(basename $(realpath $0))} +this_script="$(basename $(realpath ${0}))" +lock_file="/var/run/${this_script%.*}.lock" onie_mount=/mnt/onie-boot +onie_lib=/lib/onie os_boot=/host -onie_partition= -export ONIE_FWPKG_PROGRAM_NAME=$(basename $(realpath $0)) - -usage() -{ +print_help() { cat <${lock_file} + /usr/bin/flock -x ${lock_fd} + register_unlock_handler ${lock_fd} +} + +# Multiprocessing synchronization +lock_script_state_change + # Process command arguments -cmd=$1 -# optional argument -name="$2" +cmd="${1}" + +# Optional argument +arg="${2}" -if [ -z "$cmd" ] ; then - # Default to 'show' if no command is specified. - cmd="show" +if [[ -z "${cmd}" ]]; then + # Default to 'show' if no command is specified. + cmd="show" fi -case "$cmd" in - add | remove) - [ -z "$name" ] && { - echo "ERROR: This command requires a firmware update file name." - echo "Run '$this_script help' for complete details." - exit 1 - } - ;; - update) - enable_onie_access - show_pending - rc=$? - if [ $rc -ne 0 ]; then - change_grub_boot_order - rc=$? - clean_onie_access - exit $rc - else - echo "ERROR: NO FW images for update." - echo "Run: $this_script add before update." - clean_onie_access - exit 1 - fi - ;; - purge | show | show-results | show-log | show-pending | help) - ;; - *) - echo "Unknown command: $cmd" - exit 1 - ;; +case "${cmd}" in + add|remove) + if [[ -z "${arg}" ]]; then + echo "ERROR: This command requires a firmware update file name" + echo "Run: '${this_script} help' for complete details" + exit 1 + fi + ;; + update) + enable_onie_access + show_pending + rc=$? + if [[ ${rc} -ne 0 ]]; then + enable_onie_fw_update_mode + rc=$? + disable_onie_access + if [[ ${rc} -eq 0 ]]; then + system_reboot + else + echo "ERROR: failed to enable ONIE firmware update mode" + exit ${rc} + fi + else + echo "ERROR: No firmware images for update" + echo "Run: '${this_script} add ' before update" + disable_onie_access + exit 1 + fi + ;; + purge|show-pending|show-results|show|show-log|help) + ;; + *) + echo "ERROR: Unknown command: ${cmd}" + exit 1 + ;; esac enable_onie_access -$onie_mount/onie/tools/bin/onie-fwpkg "$@" +${onie_mount}/onie/tools/bin/onie-fwpkg "$@" rc=$? -if [ $cmd = "help" ]; then - usage +if [[ "${cmd}" = "help" ]]; then + print_help fi -clean_onie_access +disable_onie_access -exit $rc +exit ${rc} diff --git a/platform/mellanox/mlnx-platform-api.mk b/platform/mellanox/mlnx-platform-api.mk index 4b70e59debc1..7bbbc3c70b0e 100644 --- a/platform/mellanox/mlnx-platform-api.mk +++ b/platform/mellanox/mlnx-platform-api.mk @@ -3,6 +3,7 @@ SONIC_PLATFORM_API_PY2 = mlnx_platform_api-1.0-py2-none-any.whl $(SONIC_PLATFORM_API_PY2)_SRC_PATH = $(PLATFORM_PATH)/mlnx-platform-api $(SONIC_PLATFORM_API_PY2)_PYTHON_VERSION = 2 +$(SONIC_PLATFORM_API_PY2)_DEPENDS = $(SONIC_PLATFORM_COMMON_PY2) $(SONIC_DAEMON_BASE_PY2) $(SONIC_CONFIG_ENGINE) SONIC_PYTHON_WHEELS += $(SONIC_PLATFORM_API_PY2) export mlnx_platform_api_py2_wheel_path="$(addprefix $(PYTHON_WHEELS_PATH)/,$(SONIC_PLATFORM_API_PY2))" diff --git a/platform/mellanox/mlnx-platform-api/.gitignore b/platform/mellanox/mlnx-platform-api/.gitignore new file mode 100644 index 000000000000..07f8a98e1f4a --- /dev/null +++ b/platform/mellanox/mlnx-platform-api/.gitignore @@ -0,0 +1,2 @@ +*.pyc +.cache/ diff --git a/platform/mellanox/mlnx-platform-api/pytest.ini b/platform/mellanox/mlnx-platform-api/pytest.ini new file mode 100644 index 000000000000..c24fe5bb9e65 --- /dev/null +++ b/platform/mellanox/mlnx-platform-api/pytest.ini @@ -0,0 +1,3 @@ +[pytest] +filterwarnings = + ignore::DeprecationWarning diff --git a/platform/mellanox/mlnx-platform-api/setup.cfg b/platform/mellanox/mlnx-platform-api/setup.cfg new file mode 100644 index 000000000000..b7e478982ccf --- /dev/null +++ b/platform/mellanox/mlnx-platform-api/setup.cfg @@ -0,0 +1,2 @@ +[aliases] +test=pytest diff --git a/platform/mellanox/mlnx-platform-api/setup.py b/platform/mellanox/mlnx-platform-api/setup.py index 12809c4085ed..f10f84924d2c 100644 --- a/platform/mellanox/mlnx-platform-api/setup.py +++ b/platform/mellanox/mlnx-platform-api/setup.py @@ -12,6 +12,14 @@ maintainer_email='kevinw@mellanox.com', packages=[ 'sonic_platform', + 'tests' + ], + setup_requires= [ + 'pytest-runner' + ], + tests_require = [ + 'pytest', + 'mock>=2.0.0' ], classifiers=[ 'Development Status :: 3 - Alpha', @@ -26,5 +34,6 @@ 'Topic :: Utilities', ], keywords='sonic SONiC platform PLATFORM', + test_suite='setup.get_test_suite' ) diff --git a/platform/mellanox/mlnx-platform-api/sonic_platform/__init__.py b/platform/mellanox/mlnx-platform-api/sonic_platform/__init__.py index d94d4c9ec820..d82f3749319c 100644 --- a/platform/mellanox/mlnx-platform-api/sonic_platform/__init__.py +++ b/platform/mellanox/mlnx-platform-api/sonic_platform/__init__.py @@ -1,2 +1,2 @@ __all__ = ["platform", "chassis"] -from sonic_platform import * \ No newline at end of file +from sonic_platform import * diff --git a/platform/mellanox/mlnx-platform-api/sonic_platform/chassis.py b/platform/mellanox/mlnx-platform-api/sonic_platform/chassis.py index c693b93462de..61b4273974c4 100644 --- a/platform/mellanox/mlnx-platform-api/sonic_platform/chassis.py +++ b/platform/mellanox/mlnx-platform-api/sonic_platform/chassis.py @@ -15,6 +15,7 @@ from sonic_daemon_base.daemon_base import Logger from os import listdir from os.path import isfile, join + from glob import glob import sys import io import re @@ -28,12 +29,17 @@ MLNX_NUM_PSU = 2 GET_HWSKU_CMD = "sonic-cfggen -d -v DEVICE_METADATA.localhost.hwsku" +GET_PLATFORM_CMD = "sonic-cfggen -d -v DEVICE_METADATA.localhost.platform" EEPROM_CACHE_ROOT = '/var/cache/sonic/decode-syseeprom' EEPROM_CACHE_FILE = 'syseeprom_cache' HWMGMT_SYSTEM_ROOT = '/var/run/hw-management/system/' +MST_DEVICE_NAME_PATTERN = '/dev/mst/mt[0-9]*_pciconf0' +MST_DEVICE_RE_PATTERN = '/dev/mst/mt([0-9]*)_pciconf0' +SPECTRUM1_CHIP_ID = '52100' + #reboot cause related definitions REBOOT_CAUSE_ROOT = HWMGMT_SYSTEM_ROOT @@ -42,9 +48,13 @@ # Global logger class instance logger = Logger() -# magic code defnition for port number, qsfp port position of each hwsku +# System LED system fs definitions for 201911 branch only +SYSTEM_STATUS_LED_GREEN_FILE = '/run/hw-management/led/led_status_green' +LED_ON = '1' + +# magic code defnition for port number, qsfp port position of each Platform # port_position_tuple = (PORT_START, QSFP_PORT_START, PORT_END, PORT_IN_BLOCK, EEPROM_OFFSET) -hwsku_dict_port = {'ACS-MSN2010': 3, 'ACS-MSN2100': 1, 'ACS-MSN2410': 2, 'ACS-MSN2700': 0, 'Mellanox-SN2700': 0, 'Mellanox-SN2700-D48C8': 0, 'LS-SN2700':0, 'ACS-MSN2740': 0, 'ACS-MSN3700': 0, 'ACS-MSN3700C': 0, 'ACS-MSN3800': 4, 'Mellanox-SN3800-D112C8': 4, 'ACS-MSN4700': 0, 'ACS-MSN3420': 5, 'ACS-MSN4600C': 4} +platform_dict_port = {'x86_64-mlnx_msn2010-r0': 3, 'x86_64-mlnx_msn2100-r0': 1, 'x86_64-mlnx_msn2410-r0': 2, 'x86_64-mlnx_msn2700-r0': 0, 'x86_64-mlnx_lssn2700':0, 'x86_64-mlnx_msn2740-r0': 0, 'x86_64-mlnx_msn3420-r0':5, 'x86_64-mlnx_msn3700-r0': 0, 'x86_64-mlnx_msn3700C-r0': 0, 'x86_64-mlnx_msn3800-r0': 4, 'x86_64-mlnx_msn4600c-r0':4, 'x86_64-mlnx_msn4700-r0': 0} port_position_tuple_list = [(0, 0, 31, 32, 1), (0, 0, 15, 16, 1), (0, 48, 55, 56, 1), (0, 18, 21, 22, 1), (0, 0, 63, 64, 1), (0, 48, 59, 60, 1)] class Chassis(ChassisBase): @@ -53,8 +63,9 @@ class Chassis(ChassisBase): def __init__(self): super(Chassis, self).__init__() - # Initialize SKU name + # Initialize SKU name and Platform name self.sku_name = self._get_sku_name() + self.platform_name = self._get_platform_name() mi = get_machine_info() if mi is not None: self.name = mi['onie_platform'] @@ -66,6 +77,7 @@ def __init__(self): self.sfp_module_initialized = False self.sfp_event_initialized = False self.reboot_cause_initialized = False + self.initialize_system_led() logger.log_info("Chassis loaded successfully") @@ -79,7 +91,7 @@ def initialize_psu(self): # Initialize PSU list self.psu_module = Psu for index in range(MLNX_NUM_PSU): - psu = Psu(index, self.sku_name) + psu = Psu(index, self.platform_name) self._psu_list.append(psu) @@ -93,11 +105,21 @@ def initialize_fan(self): num_of_fan, num_of_drawer = self._extract_num_of_fans_and_fan_drawers() multi_rotor_in_drawer = num_of_fan > num_of_drawer + # Fan's direction isn't supported on spectrum 1 devices for now + mst_dev_list = glob(MST_DEVICE_NAME_PATTERN) + if not mst_dev_list: + raise RuntimeError("Can't get chip type due to {} not found".format(MST_DEVICE_NAME_PATTERN)) + m = re.search(MST_DEVICE_RE_PATTERN, mst_dev_list[0]) + if m.group(1) == SPECTRUM1_CHIP_ID: + has_fan_dir = False + else: + has_fan_dir = True + for index in range(num_of_fan): if multi_rotor_in_drawer: - fan = Fan(index, index/2) + fan = Fan(has_fan_dir, index, index/2, False, self.platform_name) else: - fan = Fan(index, index) + fan = Fan(has_fan_dir, index, index, False, self.platform_name) self._fan_list.append(fan) @@ -107,7 +129,7 @@ def initialize_sfp(self): self.sfp_module = SFP # Initialize SFP list - port_position_tuple = self._get_port_position_tuple_by_sku_name() + port_position_tuple = self._get_port_position_tuple_by_platform_name() self.PORT_START = port_position_tuple[0] self.QSFP_PORT_START = port_position_tuple[1] self.PORT_END = port_position_tuple[2] @@ -126,7 +148,7 @@ def initialize_sfp(self): def initialize_thermals(self): from sonic_platform.thermal import initialize_thermals # Initialize thermals - initialize_thermals(self.sku_name, self._thermal_list, self._psu_list) + initialize_thermals(self.platform_name, self._thermal_list, self._psu_list) def initialize_eeprom(self): @@ -137,7 +159,9 @@ def initialize_eeprom(self): def initialize_components(self): # Initialize component list - from sonic_platform.component import ComponentBIOS, ComponentCPLD + from sonic_platform.component import ComponentONIE, ComponentSSD, ComponentBIOS, ComponentCPLD + self._component_list.append(ComponentONIE()) + self._component_list.append(ComponentSSD()) self._component_list.append(ComponentBIOS()) self._component_list.extend(ComponentCPLD.get_component_list()) @@ -182,13 +206,13 @@ def get_all_sfps(self): def get_sfp(self, index): """ - Retrieves sfp represented by (0-based) index + Retrieves sfp represented by (1-based) index Args: - index: An integer, the index (0-based) of the sfp to retrieve. + index: An integer, the index (1-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. + starting from 1. + For example, 1 for Ethernet0, 2 for Ethernet4 and so on. Returns: An object dervied from SfpBase representing the specified sfp @@ -197,7 +221,7 @@ def get_sfp(self, index): self.initialize_sfp() sfp = None - + index -= 1 try: sfp = self._sfp_list[index] except IndexError: @@ -230,8 +254,14 @@ def _get_sku_name(self): return out.rstrip('\n') - def _get_port_position_tuple_by_sku_name(self): - position_tuple = port_position_tuple_list[hwsku_dict_port[self.sku_name]] + def _get_platform_name(self): + p = subprocess.Popen(GET_PLATFORM_CMD, shell=True, stdout=subprocess.PIPE) + out, err = p.communicate() + return out.rstrip('\n') + + + def _get_port_position_tuple_by_platform_name(self): + position_tuple = port_position_tuple_list[platform_dict_port[self.platform_name]] return position_tuple @@ -442,3 +472,19 @@ def get_change_event(self, timeout=0): return True, {'sfp':port_dict} else: return True, {'sfp':{}} + + def get_thermal_manager(self): + from .thermal_manager import ThermalManager + return ThermalManager + + def initialize_system_led(self): + """ + Init system LED color to green. + This is for 201911 branch only + """ + try: + with open(SYSTEM_STATUS_LED_GREEN_FILE, 'w') as f: + f.write(LED_ON) + except: + pass + diff --git a/platform/mellanox/mlnx-platform-api/sonic_platform/component.py b/platform/mellanox/mlnx-platform-api/sonic_platform/component.py index d5937b63286d..d38bb30029ed 100644 --- a/platform/mellanox/mlnx-platform-api/sonic_platform/component.py +++ b/platform/mellanox/mlnx-platform-api/sonic_platform/component.py @@ -6,19 +6,308 @@ # implementation of new platform api ############################################################################# from __future__ import print_function + + try: - from sonic_platform_base.component_base import ComponentBase - from sonic_device_util import get_machine_info - from glob import glob - import subprocess - import io import os + import io import re + import glob + import tempfile + import subprocess + import ConfigParser + + from sonic_platform_base.component_base import ComponentBase except ImportError as e: raise ImportError(str(e) + "- required module not found") -ZERO = '0' -NEWLINE = '\n' + +class MPFAManager(object): + MPFA_EXTENSION = '.mpfa' + + MPFA_EXTRACT_COMMAND = 'tar xzf {} -C {}' + MPFA_CLEANUP_COMMAND = 'rm -rf {}' + + def __init__(self, mpfa_path): + self.__mpfa_path = mpfa_path + self.__contents_path = None + self.__metadata = None + + def __enter__(self): + self.extract() + return self + + def __exit__(self, exc_type, exc_value, traceback): + self.cleanup() + + def __validate_path(self, mpfa_path): + if not os.path.isfile(mpfa_path): + raise RuntimeError("MPFA doesn't exist: path={}".format(mpfa_path)) + + name, ext = os.path.splitext(mpfa_path) + if ext != self.MPFA_EXTENSION: + raise RuntimeError("MPFA doesn't have valid extension: path={}".format(mpfa_path)) + + def __extract_contents(self, mpfa_path): + contents_path = tempfile.mkdtemp(prefix='mpfa-') + + cmd = self.MPFA_EXTRACT_COMMAND.format(mpfa_path, contents_path) + subprocess.check_call(cmd.split()) + + self.__contents_path = contents_path + + def __parse_metadata(self, contents_path): + metadata_path = os.path.join(contents_path, 'metadata.ini') + + if not os.path.isfile(metadata_path): + raise RuntimeError("MPFA metadata doesn't exist: path={}".format(metadata_path)) + + cp = ConfigParser.ConfigParser() + with io.open(metadata_path, 'r') as metadata_ini: + cp.readfp(metadata_ini) + + self.__metadata = cp + + def extract(self): + if self.is_extracted(): + return + + self.__validate_path(self.__mpfa_path) + self.__extract_contents(self.__mpfa_path) + self.__parse_metadata(self.__contents_path) + + def cleanup(self): + if os.path.exists(self.__contents_path): + cmd = self.MPFA_CLEANUP_COMMAND.format(self.__contents_path) + subprocess.check_call(cmd.split()) + + self.__contents_path = None + self.__metadata = None + + def get_path(self): + return self.__contents_path + + def get_metadata(self): + return self.__metadata + + def is_extracted(self): + return self.__contents_path is not None and os.path.exists(self.__contents_path) + + +class ONIEUpdater(object): + ONIE_FW_UPDATE_CMD_ADD = '/usr/bin/mlnx-onie-fw-update.sh add {}' + ONIE_FW_UPDATE_CMD_REMOVE = '/usr/bin/mlnx-onie-fw-update.sh remove {}' + ONIE_FW_UPDATE_CMD_UPDATE = '/usr/bin/mlnx-onie-fw-update.sh update' + ONIE_FW_UPDATE_CMD_SHOW_PENDING = '/usr/bin/mlnx-onie-fw-update.sh show-pending' + + ONIE_VERSION_PARSE_PATTERN = '([0-9]{4})\.([0-9]{2})-([0-9]+)\.([0-9]+)\.([0-9]+)-([0-9]+)' + ONIE_VERSION_BASE_PARSE_PATTERN = '([0-9]+)\.([0-9]+)\.([0-9]+)' + ONIE_VERSION_REQUIRED = '5.2.0016' + + ONIE_VERSION_ATTR = 'onie_version' + ONIE_NO_PENDING_UPDATES_ATTR = 'No pending firmware updates present' + + ONIE_IMAGE_INFO_COMMAND = '/bin/bash {} -q -i' + + def __mount_onie_fs(self): + fs_mountpoint = '/mnt/onie-fs' + onie_path = '/lib/onie' + + if os.path.lexists(onie_path) or os.path.exists(fs_mountpoint): + self.__umount_onie_fs() + + cmd = "fdisk -l | grep 'ONIE boot' | awk '{print $1}'" + fs_path = subprocess.check_output(cmd, stderr=subprocess.STDOUT, shell=True).rstrip('\n') + + os.mkdir(fs_mountpoint) + cmd = "mount -n -r -t ext4 {} {}".format(fs_path, fs_mountpoint) + subprocess.check_call(cmd, shell=True) + + fs_onie_path = os.path.join(fs_mountpoint, 'onie/tools/lib/onie') + os.symlink(fs_onie_path, onie_path) + + return fs_mountpoint + + def __umount_onie_fs(self): + fs_mountpoint = '/mnt/onie-fs' + onie_path = '/lib/onie' + + if os.path.islink(onie_path): + os.unlink(onie_path) + + if os.path.ismount(fs_mountpoint): + cmd = "umount -rf {}".format(fs_mountpoint) + subprocess.check_call(cmd, shell=True) + + if os.path.exists(fs_mountpoint): + os.rmdir(fs_mountpoint) + + def __stage_update(self, image_path): + cmd = self.ONIE_FW_UPDATE_CMD_ADD.format(image_path) + + try: + subprocess.check_call(cmd.split()) + except subprocess.CalledProcessError as e: + raise RuntimeError("Failed to stage firmware update: {}".format(str(e))) + + def __unstage_update(self, image_path): + cmd = self.ONIE_FW_UPDATE_CMD_REMOVE.format(os.path.basename(image_path)) + + try: + subprocess.check_call(cmd.split()) + except subprocess.CalledProcessError as e: + raise RuntimeError("Failed to unstage firmware update: {}".format(str(e))) + + def __trigger_update(self): + cmd = self.ONIE_FW_UPDATE_CMD_UPDATE + + try: + subprocess.check_call(cmd.split()) + except subprocess.CalledProcessError as e: + raise RuntimeError("Failed to trigger firmware update: {}".format(str(e))) + + def __is_update_staged(self, image_path): + cmd = self.ONIE_FW_UPDATE_CMD_SHOW_PENDING + + try: + output = subprocess.check_output(cmd.split(), stderr=subprocess.STDOUT).rstrip('\n') + except subprocess.CalledProcessError as e: + raise RuntimeError("Failed to get pending firmware updates: {}".format(str(e))) + + basename = os.path.basename(image_path) + + for line in output.splitlines(): + if line.startswith(basename): + return True + + return False + + def parse_onie_version(self, version, is_base=False): + onie_year = None + onie_month = None + onie_major = None + onie_minor = None + onie_release = None + onie_baudrate = None + + if is_base: + pattern = self.ONIE_VERSION_BASE_PARSE_PATTERN + + m = re.search(pattern, version) + if not m: + raise RuntimeError("Failed to parse ONIE version: pattern={}, version={}".format(pattern, version)) + + onie_major = m.group(1) + onie_minor = m.group(2) + onie_release = m.group(3) + + return onie_year, onie_month, onie_major, onie_minor, onie_release, onie_baudrate + + pattern = self.ONIE_VERSION_PARSE_PATTERN + + m = re.search(pattern, version) + if not m: + raise RuntimeError("Failed to parse ONIE version: pattern={}, version={}".format(pattern, version)) + + onie_year = m.group(1) + onie_month = m.group(2) + onie_major = m.group(3) + onie_minor = m.group(4) + onie_release = m.group(5) + onie_baudrate = m.group(6) + + return onie_year, onie_month, onie_major, onie_minor, onie_release, onie_baudrate + + def get_onie_required_version(self): + return self.ONIE_VERSION_REQUIRED + + def get_onie_version(self): + version = None + + try: + fs_mountpoint = self.__mount_onie_fs() + machine_conf_path = os.path.join(fs_mountpoint, 'onie/grub/grub-machine.cfg') + + with open(machine_conf_path, 'r') as machine_conf: + for line in machine_conf: + if line.startswith(self.ONIE_VERSION_ATTR): + items = line.rstrip('\n').split('=') + + if len(items) != 2: + raise RuntimeError("Failed to parse ONIE info: line={}".format(line)) + + version = items[1] + break + + if version is None: + raise RuntimeError("Failed to parse ONIE version") + finally: + self.__umount_onie_fs() + + return version + + def get_onie_firmware_info(self, image_path): + firmware_info = { } + + try: + self.__mount_onie_fs() + + cmd = self.ONIE_IMAGE_INFO_COMMAND.format(image_path) + + try: + output = subprocess.check_output(cmd.split(), stderr=subprocess.STDOUT).rstrip('\n') + except subprocess.CalledProcessError as e: + raise RuntimeError("Failed to get ONIE firmware info: {}".format(str(e))) + + for line in output.splitlines(): + items = line.split('=') + + if len(items) != 2: + raise RuntimeError("Failed to parse ONIE firmware info: line={}".format(line)) + + firmware_info[items[0]] = items[1] + finally: + self.__umount_onie_fs() + + return firmware_info + + def update_firmware(self, image_path): + cmd = self.ONIE_FW_UPDATE_CMD_SHOW_PENDING + + try: + output = subprocess.check_output(cmd.split(), stderr=subprocess.STDOUT).rstrip('\n') + except subprocess.CalledProcessError as e: + raise RuntimeError("Failed to get pending firmware updates: {}".format(str(e))) + + no_pending_updates = False + + for line in output.splitlines(): + if line.startswith(self.ONIE_NO_PENDING_UPDATES_ATTR): + no_pending_updates = True + break + + if not no_pending_updates: + raise RuntimeError("Failed to complete firmware update: pending updates are present") + + try: + self.__stage_update(image_path) + self.__trigger_update() + except: + if self.__is_update_staged(image_path): + self.__unstage_update(image_path) + raise + + def is_non_onie_firmware_update_supported(self): + current_version = self.get_onie_version() + _, _, major1, minor1, release1, _ = self.parse_onie_version(current_version) + version1 = int("{}{}{}".format(major1, minor1, release1)) + + required_version = self.get_onie_required_version() + _, _, major2, minor2, release2, _ = self.parse_onie_version(required_version, True) + version2 = int("{}{}{}".format(major2, minor2, release2)) + + return version1 >= version2 + class Component(ComponentBase): def __init__(self): @@ -26,27 +315,12 @@ def __init__(self): self.description = None self.image_ext_name = None - 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 - @staticmethod def _read_generic_file(filename, len, ignore_errors=False): """ @@ -63,7 +337,6 @@ def _read_generic_file(filename, len, ignore_errors=False): return result - @staticmethod def _get_command_result(cmdline): try: @@ -79,149 +352,252 @@ def _get_command_result(cmdline): return result - def _check_file_validity(self, image_path): - # check whether the image file exists if not os.path.isfile(image_path): print("ERROR: File {} doesn't exist or is not a file".format(image_path)) return False + name_list = os.path.splitext(image_path) if self.image_ext_name is not None: - name_list = os.path.splitext(image_path) if name_list[1] != self.image_ext_name: print("ERROR: Extend name of file {} is wrong. Image for {} should have extend name {}".format(image_path, self.name, self.image_ext_name)) return False + else: + if name_list[1]: + print("ERROR: Extend name of file {} is wrong. Image for {} shouldn't have extension".format(image_path, self.name)) + return False return True +class ComponentONIE(Component): + COMPONENT_NAME = 'ONIE' + COMPONENT_DESCRIPTION = 'ONIE - Open Network Install Environment' -class ComponentBIOS(Component): - COMPONENT_NAME = 'BIOS' - COMPONENT_DESCRIPTION = 'BIOS - Basic Input/Output System' - COMPONENT_FIRMWARE_EXTENSION = '.rom' + ONIE_IMAGE_VERSION_ATTR = 'image_version' - # To update BIOS requires the ONIE with version 5.2.0016 or upper - ONIE_VERSION_PARSE_PATTERN = '[0-9]{4}\.[0-9]{2}-([0-9]+)\.([0-9]+)\.([0-9]+)' - ONIE_VERSION_MAJOR_OFFSET = 1 - ONIE_VERSION_MINOR_OFFSET = 2 - ONIE_VERSION_RELEASE_OFFSET = 3 - ONIE_REQUIRED_MAJOR = '5' - ONIE_REQUIRED_MINOR = '2' - ONIE_REQUIRED_RELEASE = '0016' + def __init__(self): + super(ComponentONIE, self).__init__() - BIOS_VERSION_PARSE_PATTERN = 'OEM[\s]*Strings\n[\s]*String[\s]*1:[\s]*([0-9a-zA-Z_\.]*)' - BIOS_PENDING_UPDATE_PATTERN = '([0-9A-Za-z_]*.rom)[\s]*\|[\s]*bios_update' + self.name = self.COMPONENT_NAME + self.description = self.COMPONENT_DESCRIPTION + self.onie_updater = ONIEUpdater() - ONIE_FW_UPDATE_CMD_ADD = '/usr/bin/mlnx-onie-fw-update.sh add {}' - ONIE_FW_UPDATE_CMD_REMOVE = '/usr/bin/mlnx-onie-fw-update.sh remove {}' - ONIE_FW_UPDATE_CMD_UPDATE = '/usr/bin/mlnx-onie-fw-update.sh update' - ONIE_FW_UPDATE_CMD_SHOW = '/usr/bin/mlnx-onie-fw-update.sh show-pending' + def __install_firmware(self, image_path): + if not self._check_file_validity(image_path): + return False + + try: + print("INFO: Staging {} firmware update with ONIE updater".format(self.name)) + self.onie_updater.update_firmware(image_path) + except Exception as e: + print("ERROR: Failed to update {} firmware: {}".format(self.name, str(e))) + return False - BIOS_QUERY_VERSION_COMMAND = 'dmidecode -t 11' + return True + + def get_firmware_version(self): + return self.onie_updater.get_onie_version() + + def get_available_firmware_version(self, image_path): + firmware_info = self.onie_updater.get_onie_firmware_info(image_path) + if self.ONIE_IMAGE_VERSION_ATTR not in firmware_info: + raise RuntimeError("Failed to get {} available firmware version".format(self.name)) + + return firmware_info[self.ONIE_IMAGE_VERSION_ATTR] + + def get_firmware_update_notification(self, image_path): + return "Immediate cold reboot is required to complete {} firmware update".format(self.name) + + def install_firmware(self, image_path): + return self.__install_firmware(image_path) + + def update_firmware(self, image_path): + self.__install_firmware(image_path) + + +class ComponentSSD(Component): + COMPONENT_NAME = 'SSD' + COMPONENT_DESCRIPTION = 'SSD - Solid-State Drive' + COMPONENT_FIRMWARE_EXTENSION = '.pkg' + + FIRMWARE_VERSION_ATTR = 'Firmware Version' + AVAILABLE_FIRMWARE_VERSION_ATTR = 'Available Firmware Version' + POWER_CYCLE_REQUIRED_ATTR = 'Power Cycle Required' + UPGRADE_REQUIRED_ATTR = 'Upgrade Required' + + SSD_INFO_COMMAND = "/usr/bin/mlnx-ssd-fw-update.sh -q" + SSD_FIRMWARE_INFO_COMMAND = "/usr/bin/mlnx-ssd-fw-update.sh -q -i {}" + SSD_FIRMWARE_UPDATE_COMMAND = "/usr/bin/mlnx-ssd-fw-update.sh -y -u -i {}" def __init__(self): + super(ComponentSSD, self).__init__() + self.name = self.COMPONENT_NAME self.description = self.COMPONENT_DESCRIPTION self.image_ext_name = self.COMPONENT_FIRMWARE_EXTENSION + def __install_firmware(self, image_path): + if not self._check_file_validity(image_path): + return False + + cmd = self.SSD_FIRMWARE_UPDATE_COMMAND.format(image_path) + + try: + print("INFO: Installing {} firmware update".format(self.name)) + subprocess.check_call(cmd.split()) + except subprocess.CalledProcessError as e: + print("ERROR: Failed to update {} firmware: {}".format(self.name, str(e))) + return False + + return True def get_firmware_version(self): - """ - Retrieves the firmware version of the component + cmd = self.SSD_INFO_COMMAND - Returns: - A string containing the firmware version of the component + try: + output = subprocess.check_output(cmd.split(), stderr=subprocess.STDOUT).rstrip('\n') + except subprocess.CalledProcessError as e: + raise RuntimeError("Failed to get {} info: {}".format(self.name, str(e))) - BIOS version is retrieved via command 'dmidecode -t 11' - which should return result in the following convention - # dmidecode 3.0 - Getting SMBIOS data from sysfs. - SMBIOS 2.7 present. + for line in output.splitlines(): + if line.startswith(self.FIRMWARE_VERSION_ATTR): + return line.split(':')[1].lstrip(' \t') - Handle 0x0022, DMI type 11, 5 bytes - OEM Strings - String 1:*0ABZS017_02.02.002* - String 2: To Be Filled By O.E.M. + raise RuntimeError("Failed to parse {} version".format(self.name)) + + def get_available_firmware_version(self, image_path): + cmd = self.SSD_FIRMWARE_INFO_COMMAND.format(image_path) - By using regular expression 'OEM[\s]*Strings\n[\s]*String[\s]*1:[\s]*([0-9a-zA-Z_\.]*)' - we can extrace the version string which is marked with * in the above context - """ try: - bios_ver_str = self._get_command_result(self.BIOS_QUERY_VERSION_COMMAND) - m = re.search(self.BIOS_VERSION_PARSE_PATTERN, bios_ver_str) - result = m.group(1) - except (AttributeError, RuntimeError) as e: - raise RuntimeError("Failed to parse BIOS version due to {}".format(repr(e))) + output = subprocess.check_output(cmd.split(), stderr=subprocess.STDOUT).rstrip('\n') + except subprocess.CalledProcessError as e: + raise RuntimeError("Failed to get {} firmware info: {}".format(self.name, str(e))) - return result + current_firmware_version = None + available_firmware_version = None + upgrade_required = None + + for line in output.splitlines(): + if line.startswith(self.FIRMWARE_VERSION_ATTR): + current_firmware_version = line.split(':')[1].lstrip(' \t') + if line.startswith(self.AVAILABLE_FIRMWARE_VERSION_ATTR): + available_firmware_version = line.split(':')[1].lstrip(' \t') + if line.startswith(self.UPGRADE_REQUIRED_ATTR): + upgrade_required = line.split(':')[1].lstrip(' \t') + + if upgrade_required is None or upgrade_required not in ['yes', 'no']: + raise RuntimeError("Failed to parse {} firmware upgrade status".format(self.name)) + if upgrade_required == 'no': + if current_firmware_version is None: + raise RuntimeError("Failed to parse {} current firmware version".format(self.name)) + return current_firmware_version + + if available_firmware_version is None: + raise RuntimeError("Failed to parse {} available firmware version".format(self.name)) + + return available_firmware_version + + def get_firmware_update_notification(self, image_path): + cmd = self.SSD_FIRMWARE_INFO_COMMAND.format(image_path) - def _check_onie_version(self): - # check ONIE version. To update ONIE requires version 5.2.0016 or later. try: - machine_info = get_machine_info() - onie_version_string = machine_info['onie_version'] - m = re.search(self.ONIE_VERSION_PARSE_PATTERN, onie_version_string) - onie_major = m.group(self.ONIE_VERSION_MAJOR_OFFSET) - onie_minor = m.group(self.ONIE_VERSION_MINOR_OFFSET) - onie_release = m.group(self.ONIE_VERSION_RELEASE_OFFSET) - except AttributeError as e: - print("ERROR: Failed to parse ONIE version by {} from {} due to {}".format( - self.ONIE_VERSION_PARSE_PATTERN, machine_conf, repr(e))) - return False + output = subprocess.check_output(cmd.split(), stderr=subprocess.STDOUT).rstrip('\n') + except subprocess.CalledProcessError as e: + raise RuntimeError("Failed to get {} firmware info: {}".format(self.name, str(e))) - if onie_major < self.ONIE_REQUIRED_MAJOR or onie_minor < self.ONIE_REQUIRED_MINOR or onie_release < self.ONIE_REQUIRED_RELEASE: - print("ERROR: ONIE {}.{}.{} or later is required".format(self.ONIE_REQUIRED_MAJOR, self.ONIE_REQUIRED_MINOR, self.ONIE_REQUIRED_RELEASE)) - return False + power_cycle_required = None + upgrade_required = None - return True + for line in output.splitlines(): + if line.startswith(self.POWER_CYCLE_REQUIRED_ATTR): + power_cycle_required = line.split(':')[1].lstrip(' \t') + if line.startswith(self.UPGRADE_REQUIRED_ATTR): + upgrade_required = line.split(':')[1].lstrip(' \t') + if upgrade_required is None or upgrade_required not in ['yes', 'no']: + raise RuntimeError("Failed to parse {} firmware upgrade status".format(self.name)) + + if upgrade_required == 'no': + return None + + if power_cycle_required is None or power_cycle_required not in ['yes', 'no']: + raise RuntimeError("Failed to parse {} firmware power policy".format(self.name)) + + notification = None + + if power_cycle_required == 'yes': + notification = "Immediate power cycle is required to complete {} firmware update".format(self.name) + + return notification def install_firmware(self, image_path): - """ - Installs firmware to the component + return self.__install_firmware(image_path) - Args: - image_path: A string, path to firmware image + def update_firmware(self, image_path): + self.__install_firmware(image_path) - Returns: - A boolean, True if install was successful, False if not - """ - # check ONIE version requirement - if not self._check_onie_version(): + +class ComponentBIOS(Component): + COMPONENT_NAME = 'BIOS' + COMPONENT_DESCRIPTION = 'BIOS - Basic Input/Output System' + COMPONENT_FIRMWARE_EXTENSION = '.rom' + + BIOS_VERSION_ATTR = 'String 1' + + BIOS_VERSION_COMMAND = 'dmidecode -q -t 11' + + def __init__(self): + super(ComponentBIOS, self).__init__() + + self.name = self.COMPONENT_NAME + self.description = self.COMPONENT_DESCRIPTION + self.image_ext_name = self.COMPONENT_FIRMWARE_EXTENSION + self.onie_updater = ONIEUpdater() + + def __install_firmware(self, image_path): + if not self.onie_updater.is_non_onie_firmware_update_supported(): + print("ERROR: ONIE {} or later is required".format(self.onie_updater.get_onie_required_version())) return False - # check whether the file exists if not self._check_file_validity(image_path): return False - # do the real work try: - # check whether there has already been some images pending - # if yes, remove them - result = self._get_command_result(self.ONIE_FW_UPDATE_CMD_SHOW) - pending_list = result.split("\n") - for pending in pending_list: - m = re.match(self.BIOS_PENDING_UPDATE_PATTERN, pending) - if m is not None: - pending_image = m.group(1) - self._get_command_result(self.ONIE_FW_UPDATE_CMD_REMOVE.format(pending_image)) - print("WARNING: Image {} which is already pending to upgrade has been removed".format(pending_image)) - - result = subprocess.check_call(self.ONIE_FW_UPDATE_CMD_ADD.format(image_path).split()) - if result: - return False - result = subprocess.check_call(self.ONIE_FW_UPDATE_CMD_UPDATE.split()) - if result: - return False + print("INFO: Staging {} firmware update with ONIE updater".format(self.name)) + self.onie_updater.update_firmware(image_path) except Exception as e: - print("ERROR: Installing BIOS failed due to {}".format(repr(e))) + print("ERROR: Failed to update {} firmware: {}".format(self.name, str(e))) return False - print("INFO: Reboot is required to finish BIOS installation") return True + def get_firmware_version(self): + cmd = self.BIOS_VERSION_COMMAND + + try: + output = subprocess.check_output(cmd.split(), stderr=subprocess.STDOUT).rstrip('\n') + except subprocess.CalledProcessError as e: + raise RuntimeError("Failed to get {} version: {}".format(self.name, str(e))) + + for line in output.splitlines(): + if line.lstrip(' \t').startswith(self.BIOS_VERSION_ATTR): + return line.split(':')[1].lstrip(' \t') + + raise RuntimeError("Failed to parse {} version".format(self.name)) + + def get_available_firmware_version(self, image_path): + raise NotImplementedError("{} component doesn't support firmware version query".format(self.name)) + + def get_firmware_update_notification(self, image_path): + return "Immediate cold reboot is required to complete {} firmware update".format(self.name) + + def install_firmware(self, image_path): + return self.__install_firmware(image_path) + + def update_firmware(self, image_path): + self.__install_firmware(image_path) class ComponentCPLD(Component): @@ -229,6 +605,9 @@ class ComponentCPLD(Component): COMPONENT_DESCRIPTION = 'CPLD - Complex Programmable Logic Device' COMPONENT_FIRMWARE_EXTENSION = '.vme' + MST_DEVICE_PATH = '/dev/mst' + MST_DEVICE_PATTERN = 'mt[0-9]*_pci_cr0' + CPLD_NUMBER_FILE = '/var/run/hw-management/config/cpld_num' CPLD_PART_NUMBER_FILE = '/var/run/hw-management/system/cpld{}_pn' CPLD_VERSION_FILE = '/var/run/hw-management/system/cpld{}_version' @@ -239,28 +618,54 @@ class ComponentCPLD(Component): CPLD_VERSION_MAX_LENGTH = 2 CPLD_VERSION_MINOR_MAX_LENGTH = 2 - CPLD_PART_NUMBER_DEFAULT = ZERO - CPLD_VERSION_MINOR_DEFAULT = ZERO - - CPLD_UPDATE_COMMAND = 'cpldupdate --dev {} --print-progress {}' + CPLD_PART_NUMBER_DEFAULT = '0' + CPLD_VERSION_MINOR_DEFAULT = '0' - MST_DEVICE_PATTERN = '/dev/mst/mt[0-9]*_pci_cr0' + CPLD_FIRMWARE_UPDATE_COMMAND = 'cpldupdate --dev {} --print-progress {}' def __init__(self, idx): + super(ComponentCPLD, self).__init__() + self.idx = idx self.name = self.COMPONENT_NAME.format(self.idx) self.description = self.COMPONENT_DESCRIPTION self.image_ext_name = self.COMPONENT_FIRMWARE_EXTENSION + def __get_mst_device(self): + if not os.path.exists(self.MST_DEVICE_PATH): + print("ERROR: mst driver is not loaded") + return None - def get_firmware_version(self): - """ - Retrieves the firmware version of the component + pattern = os.path.join(self.MST_DEVICE_PATH, self.MST_DEVICE_PATTERN) - Returns: - A string containing the firmware version of the component - """ + mst_dev_list = glob.glob(pattern) + if not mst_dev_list or len(mst_dev_list) != 1: + devices = str(os.listdir(self.MST_DEVICE_PATH)) + print("ERROR: Failed to get mst device: pattern={}, devices={}".format(pattern, devices)) + return None + + return mst_dev_list[0] + + def __install_firmware(self, image_path): + if not self._check_file_validity(image_path): + return False + + mst_dev = self.__get_mst_device() + if mst_dev is None: + return False + + cmd = self.CPLD_FIRMWARE_UPDATE_COMMAND.format(mst_dev, image_path) + + try: + print("INFO: Installing {} firmware update: path={}".format(self.name, image_path)) + subprocess.check_call(cmd.split()) + except subprocess.CalledProcessError as e: + print("ERROR: Failed to update {} firmware: {}".format(self.name, str(e))) + return False + + return True + def get_firmware_version(self): part_number_file = self.CPLD_PART_NUMBER_FILE.format(self.idx) version_file = self.CPLD_VERSION_FILE.format(self.idx) version_minor_file = self.CPLD_VERSION_MINOR_FILE.format(self.idx) @@ -275,75 +680,52 @@ def get_firmware_version(self): if version_minor is None: version_minor = self.CPLD_VERSION_MINOR_DEFAULT - part_number = part_number.rstrip(NEWLINE).zfill(self.CPLD_PART_NUMBER_MAX_LENGTH) - version = version.rstrip(NEWLINE).zfill(self.CPLD_VERSION_MAX_LENGTH) - version_minor = version_minor.rstrip(NEWLINE).zfill(self.CPLD_VERSION_MINOR_MAX_LENGTH) + part_number = part_number.rstrip('\n').zfill(self.CPLD_PART_NUMBER_MAX_LENGTH) + version = version.rstrip('\n').zfill(self.CPLD_VERSION_MAX_LENGTH) + version_minor = version_minor.rstrip('\n').zfill(self.CPLD_VERSION_MINOR_MAX_LENGTH) return "CPLD{}_REV{}{}".format(part_number, version, version_minor) + def get_available_firmware_version(self, image_path): + with MPFAManager(image_path) as mpfa: + if not mpfa.get_metadata().has_option('version', self.name): + raise RuntimeError("Failed to get {} available firmware version".format(self.name)) - def _get_mst_device(self): - mst_dev_list = glob(self.MST_DEVICE_PATTERN) - if mst_dev_list is None or len(mst_dev_list) != 1: - return None - return mst_dev_list + return mpfa.get_metadata().get('version', self.name) + def get_firmware_update_notification(self, image_path): + name, ext = os.path.splitext(os.path.basename(image_path)) + if ext == self.COMPONENT_FIRMWARE_EXTENSION: + return "Power cycle (with 30 sec delay) or refresh image is required to complete {} firmware update".format(self.name) - 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 - - Details: - The command "cpldupdate" is provided to install CPLD. There are two ways to do it: - 1. To burn CPLD via gpio, which is faster but only supported on new systems, like SN3700, ... - 2. To install CPLD via firmware, which is slower but supported on older systems. - This also requires the mst device designated. - "cpldupdate --dev " has the logic of testing whether to update via gpio is supported, - and if so then go this way, otherwise tries updating software via fw. So we take advantage of it to update the CPLD. - By doing so we don't have to mind whether to update via gpio supported, which belongs to hardware details. - - So the procedure should be: - 1. Test whether the file exists - 2. Fetch the mst device name - 3. Update CPLD via executing "cpldupdate --dev " - 4. Check the result - """ - # check whether the image file exists - if not self._check_file_validity(image_path): - return False - - mst_dev_list = self._get_mst_device() - if mst_dev_list is None: - print("ERROR: Failed to get mst device which is required for CPLD updating or multiple device files matched") - return False + return "Immediate power cycle is required to complete {} firmware update".format(self.name) - cmdline = self.CPLD_UPDATE_COMMAND.format(mst_dev_list[0], image_path) - success_flag = False + def install_firmware(self, image_path): + return self.__install_firmware(image_path) - try: - subprocess.check_call(cmdline, stderr=subprocess.STDOUT, shell=True) - success_flag = True - except subprocess.CalledProcessError as e: - print("ERROR: Failed to upgrade CPLD: rc={}".format(e.returncode)) + def update_firmware(self, image_path): + with MPFAManager(image_path) as mpfa: + if not mpfa.get_metadata().has_option('firmware', 'burn'): + raise RuntimeError("Failed to get {} burn firmware".format(self.name)) + if not mpfa.get_metadata().has_option('firmware', 'refresh'): + raise RuntimeError("Failed to get {} refresh firmware".format(self.name)) - if success_flag: - print("INFO: Refresh or power cycle is required to finish CPLD installation") + burn_firmware = mpfa.get_metadata().get('firmware', 'burn') + refresh_firmware = mpfa.get_metadata().get('firmware', 'refresh') - return success_flag + print("INFO: Processing {} burn file: firmware install".format(self.name)) + if not self.__install_firmware(os.path.join(mpfa.get_path(), burn_firmware)): + return + print("INFO: Processing {} refresh file: firmware update".format(self.name)) + self.__install_firmware(os.path.join(mpfa.get_path(), refresh_firmware)) @classmethod def get_component_list(cls): component_list = [ ] cpld_number = cls._read_generic_file(cls.CPLD_NUMBER_FILE, cls.CPLD_NUMBER_MAX_LENGTH) - cpld_number = cpld_number.rstrip(NEWLINE) + cpld_number = cpld_number.rstrip('\n') for cpld_idx in xrange(1, int(cpld_number) + 1): component_list.append(cls(cpld_idx)) diff --git a/platform/mellanox/mlnx-platform-api/sonic_platform/device_data.py b/platform/mellanox/mlnx-platform-api/sonic_platform/device_data.py new file mode 100644 index 000000000000..bbf7f36c9256 --- /dev/null +++ b/platform/mellanox/mlnx-platform-api/sonic_platform/device_data.py @@ -0,0 +1,90 @@ +DEVICE_DATA = { + 'x86_64-mlnx_msn2700-r0': { + 'thermal': { + 'minimum_table': { + "unk_trust": {"-127:30":13, "31:40":14 , "41:120":15}, + "unk_untrust": {"-127:25":13, "26:30":14 , "31:35":15, "36:120":16} + } + } + }, + 'x86_64-mlnx_msn2740-r0': { + 'thermal': { + 'minimum_table': { + "unk_trust": {"-127:120":13}, + "unk_untrust": {"-127:15":13, "16:25":14 , "26:30":15, "31:120":17}, + } + } + }, + 'x86_64-mlnx_msn2100-r0': { + 'thermal': { + 'minimum_table': { + "unk_trust": {"-127:40":12, "41:120":13}, + "unk_untrust": {"-127:15":12, "16:25":13, "26:30":14, "31:35":15, "36:120":16} + } + } + }, + 'x86_64-mlnx_msn2410-r0': { + 'thermal': { + 'minimum_table': { + "unk_trust": {"-127:30":13, "31:40":14 , "41:120":15}, + "unk_untrust": {"-127:25":13, "26:30":14 , "31:35":15, "36:120":16} + } + } + }, + 'x86_64-mlnx_msn2010-r0': { + 'thermal': { + 'minimum_table': { + "unk_trust": {"-127:120":12}, + "unk_untrust": {"-127:15":12, "16:20":13 , "21:30":14, "31:35":15, "36:120":16} + } + } + }, + 'x86_64-mlnx_msn3700-r0': { + 'thermal': { + 'minimum_table': { + "unk_trust": {"-127:25":12, "26:40":13 , "41:120":14}, + "unk_untrust": {"-127:15":12, "16:30":13 , "31:35":14, "36:40":15, "41:120":16}, + } + } + }, + 'x86_64-mlnx_msn3700c-r0': { + 'thermal': { + 'minimum_table': { + "unk_trust": {"-127:40":12, "41:120":13}, + "unk_untrust": {"-127:10":12, "11:20":13 , "21:30":14, "31:35":15, "36:120":16}, + } + } + }, + 'x86_64-mlnx_msn3800-r0': { + 'thermal': { + 'minimum_table': { + "unk_trust": {"-127:30":12, "31:40":13 , "41:120":14}, + "unk_untrust": {"-127:0":12, "1:10":13 , "11:15":14, "16:20":15, "21:35":16, "36:120":17}, + } + } + }, + 'x86_64-mlnx_msn4700-r0': { + 'thermal': { + 'minimum_table': { + "unk_trust": {"-127:120":16}, + "unk_untrust": {"-127:120":16}, + } + } + }, + 'x86_64-mlnx_msn3420-r0': { + 'thermal': { + 'minimum_table': { + "unk_trust": {"-127:120":16}, + "unk_untrust": {"-127:120":16}, + } + } + }, + 'x86_64-mlnx_msn4600c-r0': { + 'thermal': { + 'minimum_table': { + "unk_trust": {"-127:120":16}, + "unk_untrust": {"-127:120":16}, + } + } + } +} \ No newline at end of file diff --git a/platform/mellanox/mlnx-platform-api/sonic_platform/fan.py b/platform/mellanox/mlnx-platform-api/sonic_platform/fan.py index 8b057e4123a2..d0114dedaee7 100644 --- a/platform/mellanox/mlnx-platform-api/sonic_platform/fan.py +++ b/platform/mellanox/mlnx-platform-api/sonic_platform/fan.py @@ -9,6 +9,7 @@ ############################################################################# import os.path +import subprocess try: from sonic_platform_base.fan_base import FanBase @@ -22,32 +23,99 @@ FAN_PATH = "/var/run/hw-management/thermal/" LED_PATH = "/var/run/hw-management/led/" +CONFIG_PATH = "/var/run/hw-management/config" +# fan_dir isn't supported on Spectrum 1. It is supported on Spectrum 2 and later switches +FAN_DIR = "/var/run/hw-management/system/fan_dir" +COOLING_STATE_PATH = "/var/run/hw-management/thermal/cooling_cur_state" + +# Platforms with unplugable FANs: +# 1. don't have fanX_status and should be treated as always present +platform_with_unplugable_fan = ['x86_64-mlnx_msn2010-r0', 'x86_64-mlnx_msn2100-r0'] + class Fan(FanBase): """Platform-specific Fan class""" - def __init__(self, fan_index, drawer_index = 1, psu_fan = False): + + STATUS_LED_COLOR_ORANGE = "orange" + min_cooling_level = 2 + MIN_VALID_COOLING_LEVEL = 1 + MAX_VALID_COOLING_LEVEL = 10 + # PSU fan speed vector + PSU_FAN_SPEED = ['0x3c', '0x3c', '0x3c', '0x3c', '0x3c', + '0x3c', '0x3c', '0x46', '0x50', '0x5a', '0x64'] + + def __init__(self, has_fan_dir, fan_index, drawer_index = 1, psu_fan = False, platform = None): # API index is starting from 0, Mellanox platform index is starting from 1 self.index = fan_index + 1 self.drawer_index = drawer_index + 1 self.is_psu_fan = psu_fan - + self.always_presence = False if platform not in platform_with_unplugable_fan else True + self.fan_min_speed_path = "fan{}_min".format(self.index) if not self.is_psu_fan: self.fan_speed_get_path = "fan{}_speed_get".format(self.index) self.fan_speed_set_path = "fan{}_speed_set".format(self.index) self.fan_presence_path = "fan{}_status".format(self.drawer_index) self.fan_max_speed_path = "fan{}_max".format(self.index) + self._name = "fan{}".format(fan_index + 1) else: self.fan_speed_get_path = "psu{}_fan1_speed_get".format(self.index) self.fan_presence_path = "psu{}_fan1_speed_get".format(self.index) - self.fan_max_speed_path = "psu{}_max".format(self.index) + self._name = 'psu_{}_fan_{}'.format(self.index, 1) + self.fan_max_speed_path = None + self.psu_i2c_bus_path = os.path.join(CONFIG_PATH, 'psu{0}_i2c_bus'.format(self.index)) + self.psu_i2c_addr_path = os.path.join(CONFIG_PATH, 'psu{0}_i2c_addr'.format(self.index)) + self.psu_i2c_command_path = os.path.join(CONFIG_PATH, 'fan_command') + self.fan_status_path = "fan{}_fault".format(self.index) self.fan_green_led_path = "led_fan{}_green".format(self.drawer_index) self.fan_red_led_path = "led_fan{}_red".format(self.drawer_index) self.fan_orange_led_path = "led_fan{}_orange".format(self.drawer_index) self.fan_pwm_path = "pwm1" self.fan_led_cap_path = "led_fan{}_capability".format(self.drawer_index) + if has_fan_dir: + self.fan_dir = FAN_DIR + else: + self.fan_dir = None + + + def get_direction(self): + """ + Retrieves the fan's direction + + Returns: + A string, either FAN_DIRECTION_INTAKE or FAN_DIRECTION_EXHAUST + depending on fan direction + + Notes: + What Mellanox calls forward: + Air flows from fans side to QSFP side, for example: MSN2700-CS2F + which means intake in community + What Mellanox calls reverse: + Air flow from QSFP side to fans side, for example: MSN2700-CS2R + which means exhaust in community + According to hw-mgmt: + 1 stands for forward, in other words intake + 0 stands for reverse, in other words exhaust + """ + if not self.fan_dir or self.is_psu_fan or not self.get_presence(): + return self.FAN_DIRECTION_NOT_APPLICABLE + + try: + with open(os.path.join(self.fan_dir), 'r') as fan_dir: + fan_dir_bits = int(fan_dir.read().strip()) + fan_mask = 1 << self.drawer_index - 1 + if fan_dir_bits & fan_mask: + return self.FAN_DIRECTION_INTAKE + else: + return self.FAN_DIRECTION_EXHAUST + except (ValueError, IOError) as e: + raise RuntimeError("Failed to read fan direction status to {}".format(repr(e))) + + + def get_name(self): + return self._name def get_status(self): """ @@ -58,15 +126,15 @@ def get_status(self): """ status = 0 if self.is_psu_fan: - status = 1 + status = 0 else: try: with open(os.path.join(FAN_PATH, self.fan_status_path), 'r') as fault_status: - status = int(fault_status.read()) + status = int(fault_status.read().strip()) except (ValueError, IOError): - status = 0 + status = 1 - return status == 1 + return status == 0 def get_presence(self): """ @@ -82,11 +150,14 @@ def get_presence(self): else: status = 0 else: - try: - with open(os.path.join(FAN_PATH, self.fan_presence_path), 'r') as presence_status: - status = int(presence_status.read()) - except (ValueError, IOError): - status = 0 + if self.always_presence: + status = 1 + else: + try: + with open(os.path.join(FAN_PATH, self.fan_presence_path), 'r') as presence_status: + status = int(presence_status.read().strip()) + except (ValueError, IOError): + status = 0 return status == 1 @@ -104,7 +175,7 @@ def _get_max_speed_in_rpm(self): speed = 0 try: with open(os.path.join(FAN_PATH, self.fan_max_speed_path), 'r') as max_fan_speed: - speed = int(max_fan_speed.read()) + speed = int(max_fan_speed.read().strip()) except (ValueError, IOError): speed = 0 @@ -120,12 +191,18 @@ def get_speed(self): speed = 0 try: with open(os.path.join(FAN_PATH, self.fan_speed_get_path), 'r') as fan_curr_speed: - speed_in_rpm = int(fan_curr_speed.read()) + speed_in_rpm = int(fan_curr_speed.read().strip()) except (ValueError, IOError): speed_in_rpm = 0 - + + if self.fan_max_speed_path is None: + # in case of max speed unsupported, we just return speed in unit of RPM. + return speed_in_rpm + max_speed_in_rpm = self._get_max_speed_in_rpm() speed = 100*speed_in_rpm/max_speed_in_rpm + if speed > 100: + speed = 100 return speed @@ -136,14 +213,13 @@ def get_target_speed(self): Returns: int: percentage of the max fan speed """ - speed = 0 - if self.is_psu_fan: # Not like system fan, psu fan speed can not be modified, so target speed is N/A - return speed + return self.get_speed() + try: with open(os.path.join(FAN_PATH, self.fan_speed_set_path), 'r') as fan_pwm: - pwm = int(fan_pwm.read()) + pwm = int(fan_pwm.read().strip()) except (ValueError, IOError): pwm = 0 @@ -163,13 +239,36 @@ def set_speed(self, speed): bool: True if set success, False if fail. """ status = True - pwm = int(round(PWM_MAX*speed/100.0)) if self.is_psu_fan: - #PSU fan speed is not setable. - return False - + if not self.get_presence(): + return False + from .thermal import logger + try: + with open(self.psu_i2c_bus_path, 'r') as f: + bus = f.read().strip() + with open(self.psu_i2c_addr_path, 'r') as f: + addr = f.read().strip() + with open(self.psu_i2c_command_path, 'r') as f: + command = f.read().strip() + speed = Fan.PSU_FAN_SPEED[int(speed / 10)] + command = "i2cset -f -y {0} {1} {2} {3} wp".format(bus, addr, command, speed) + subprocess.check_call(command, shell = True) + return True + except subprocess.CalledProcessError as ce: + logger.log_error('Failed to call command {}, return code={}, command output={}'.format(ce.cmd, ce.returncode, ce.output)) + return False + except Exception as e: + logger.log_error('Failed to set PSU FAN speed - {}'.format(e)) + return False + try: + cooling_level = int(speed / 10) + if cooling_level < self.min_cooling_level: + cooling_level = self.min_cooling_level + speed = self.min_cooling_level * 10 + self.set_cooling_level(cooling_level, cooling_level) + pwm = int(round(PWM_MAX*speed/100.0)) with open(os.path.join(FAN_PATH, self.fan_speed_set_path), 'w') as fan_pwm: fan_pwm.write(str(pwm)) except (ValueError, IOError): @@ -243,4 +342,43 @@ def get_speed_tolerance(self): considered tolerable """ # The tolerance value is fixed as 20% for all the Mellanox platform - return 20 \ No newline at end of file + return 20 + + @classmethod + def set_cooling_level(cls, level, cur_state): + """ + Change cooling level. The input level should be an integer value [1, 10]. + 1 means 10%, 2 means 20%, 10 means 100%. + """ + if not isinstance(level, int): + raise RuntimeError("Failed to set cooling level, input parameter must be integer") + + if level < cls.MIN_VALID_COOLING_LEVEL or level > cls.MAX_VALID_COOLING_LEVEL: + raise RuntimeError("Failed to set cooling level, level value must be in range [{}, {}], got {}".format( + cls.MIN_VALID_COOLING_LEVEL, + cls.MAX_VALID_COOLING_LEVEL, + level + )) + + try: + # Reset FAN cooling level vector. According to low level team, + # if we need set cooling level to X, we need first write a (10+X) + # to cooling_cur_state file to reset the cooling level vector. + with open(COOLING_STATE_PATH, 'w') as cooling_state: + cooling_state.write(str(level + 10)) + + # We need set cooling level after resetting the cooling level vector + with open(COOLING_STATE_PATH, 'w') as cooling_state: + cooling_state.write(str(cur_state)) + except (ValueError, IOError) as e: + raise RuntimeError("Failed to set cooling level - {}".format(e)) + + @classmethod + def get_cooling_level(cls): + try: + with open(COOLING_STATE_PATH, 'r') as cooling_state: + cooling_level = int(cooling_state.read().strip()) + return cooling_level + except (ValueError, IOError) as e: + raise RuntimeError("Failed to get cooling level - {}".format(e)) + diff --git a/platform/mellanox/mlnx-platform-api/sonic_platform/platform.py b/platform/mellanox/mlnx-platform-api/sonic_platform/platform.py index 25461986f37a..6d81ca3e7b51 100644 --- a/platform/mellanox/mlnx-platform-api/sonic_platform/platform.py +++ b/platform/mellanox/mlnx-platform-api/sonic_platform/platform.py @@ -24,6 +24,7 @@ def __init__(self): self._chassis.initialize_psu() self._chassis.initialize_fan() self._chassis.initialize_eeprom() + self._chassis.initialize_thermals() def _is_host(self): """ diff --git a/platform/mellanox/mlnx-platform-api/sonic_platform/psu.py b/platform/mellanox/mlnx-platform-api/sonic_platform/psu.py index f403678a6698..9652fcab627f 100644 --- a/platform/mellanox/mlnx-platform-api/sonic_platform/psu.py +++ b/platform/mellanox/mlnx-platform-api/sonic_platform/psu.py @@ -28,11 +28,11 @@ # SKUs with unplugable PSUs: # 1. don't have psuX_status and should be treated as always present # 2. don't have voltage, current and power values -hwsku_dict_with_unplugable_psu = ['ACS-MSN2010', 'ACS-MSN2100'] +platform_dict_with_unplugable_psu = ['x86_64-mlnx_msn2010-r0', 'x86_64-mlnx_msn2100-r0'] # in most SKUs the file psuX_curr, psuX_volt and psuX_power contain current, voltage and power data respectively. # but there are exceptions which will be handled by the following dictionary -hwsku_dict_psu = {'ACS-MSN3700': 1, 'ACS-MSN3700C': 1, 'ACS-MSN3800': 1, 'Mellanox-SN3800-D112C8': 1, 'ACS-MSN4700': 1, 'ACS-MSN3420': 1, 'ACS-MSN4600C': 1} +platform_dict_psu = {'x86_64-mlnx_msn3420-r0':1, 'x86_64-mlnx_msn3700-r0': 1, 'x86_64-mlnx_msn3700c-r0': 1, 'x86_64-mlnx_msn3800-r0': 1, 'x86_64-mlnx_msn4600c-r0':1, 'x86_64-mlnx_msn4700-r0': 1} psu_profile_list = [ # default filename convention { @@ -40,7 +40,7 @@ PSU_VOLTAGE : "power/psu{}_volt", PSU_POWER : "power/psu{}_power" }, - # for 3420, 3700, 3700c, 3800, 4700 + # for 3420, 3700, 3700c, 3800, 4600c, 4700 { PSU_CURRENT : "power/psu{}_curr", PSU_VOLTAGE : "power/psu{}_volt_out2", @@ -50,7 +50,7 @@ class Psu(PsuBase): """Platform-specific Psu class""" - def __init__(self, psu_index, sku): + def __init__(self, psu_index, platform): global psu_list PsuBase.__init__(self) # PSU is 1-based on Mellanox platform @@ -60,13 +60,14 @@ def __init__(self, psu_index, sku): psu_oper_status = "thermal/psu{}_pwr_status".format(self.index) #psu_oper_status should always be present for all SKUs self.psu_oper_status = os.path.join(self.psu_path, psu_oper_status) + self._name = "PSU{}".format(psu_index + 1) - if sku in hwsku_dict_psu: - filemap = psu_profile_list[hwsku_dict_psu[sku]] + if platform in platform_dict_psu: + filemap = psu_profile_list[platform_dict_psu[platform]] else: filemap = psu_profile_list[0] - if sku in hwsku_dict_with_unplugable_psu: + if platform in platform_dict_with_unplugable_psu: self.always_presence = True self.psu_voltage = None self.psu_current = None @@ -90,9 +91,20 @@ def __init__(self, psu_index, sku): psu_presence = os.path.join(self.psu_path, psu_presence) self.psu_presence = psu_presence - fan = Fan(psu_index, psu_index, True) - if fan.get_presence(): - self._fan = fan + # unplugable PSU has no FAN + if platform not in platform_dict_with_unplugable_psu: + fan = Fan(False, psu_index, psu_index, True) + self._fan_list.append(fan) + + self.psu_green_led_path = "led_psu_green" + self.psu_red_led_path = "led_psu_red" + self.psu_orange_led_path = "led_psu_orange" + self.psu_led_cap_path = "led_psu_capability" + + + def get_name(self): + return self._name + def _read_generic_file(self, filename, len): """ @@ -100,8 +112,10 @@ def _read_generic_file(self, filename, len): """ result = 0 try: + if not os.path.exists(filename): + return result with open(filename, 'r') as fileobj: - result = int(fileobj.read()) + result = int(fileobj.read().strip()) except Exception as e: logger.log_info("Fail to read file {} due to {}".format(filename, repr(e))) return result @@ -169,3 +183,117 @@ def get_power(self): return float(power) / 1000000 else: return None + + + def _get_led_capability(self): + cap_list = None + try: + with open(os.path.join(LED_PATH, self.psu_led_cap_path), 'r') as psu_led_cap: + caps = psu_led_cap.read() + cap_list = caps.split() + except (ValueError, IOError): + pass + + return cap_list + + + def set_status_led(self, color): + """ + Sets the state of the PSU status LED + + Args: + color: A string representing the color with which to set the + PSU status LED + + Returns: + bool: True if status LED state is set successfully, False if not + + Notes: + Only one led for all PSUs. + """ + led_cap_list = self._get_led_capability() + if led_cap_list is None: + return False + + status = False + try: + if color == self.STATUS_LED_COLOR_GREEN: + with open(os.path.join(LED_PATH, self.psu_green_led_path), 'w') as psu_led: + psu_led.write(LED_ON) + status = True + elif color == self.STATUS_LED_COLOR_RED: + # Some fan don't support red led but support orange led, in this case we set led to orange + if self.STATUS_LED_COLOR_RED in led_cap_list: + led_path = os.path.join(LED_PATH, self.psu_red_led_path) + elif self.STATUS_LED_COLOR_ORANGE in led_cap_list: + led_path = os.path.join(LED_PATH, self.psu_orange_led_path) + else: + return False + with open(led_path, 'w') as psu_led: + psu_led.write(LED_ON) + status = True + elif color == self.STATUS_LED_COLOR_OFF: + if self.STATUS_LED_COLOR_GREEN in led_cap_list: + with open(os.path.join(LED_PATH, self.psu_green_led_path), 'w') as psu_led: + psu_led.write(str(LED_OFF)) + if self.STATUS_LED_COLOR_RED in led_cap_list: + with open(os.path.join(LED_PATH, self.psu_red_led_path), 'w') as psu_led: + psu_led.write(str(LED_OFF)) + if self.STATUS_LED_COLOR_ORANGE in led_cap_list: + with open(os.path.join(LED_PATH, self.psu_orange_led_path), 'w') as psu_led: + psu_led.write(str(LED_OFF)) + + status = True + else: + status = False + except (ValueError, IOError): + status = False + + return status + + + def get_status_led(self): + """ + Gets the state of the PSU status LED + + Returns: + A string, one of the predefined STATUS_LED_COLOR_* strings above + """ + led_cap_list = self._get_led_capability() + if led_cap_list is None: + return self.STATUS_LED_COLOR_OFF + + try: + with open(os.path.join(LED_PATH, self.psu_green_led_path), 'r') as psu_led: + if LED_OFF != psu_led.read().rstrip('\n'): + return self.STATUS_LED_COLOR_GREEN + if self.STATUS_LED_COLOR_RED in led_cap_list: + with open(os.path.join(LED_PATH, self.psu_red_led_path), 'r') as psu_led: + if LED_OFF != psu_led.read().rstrip('\n'): + return self.STATUS_LED_COLOR_RED + if self.STATUS_LED_COLOR_ORANGE in led_cap_list: + with open(os.path.join(LED_PATH, self.psu_orange_led_path), 'r') as psu_led: + if LED_OFF != psu_led.read().rstrip('\n'): + return self.STATUS_LED_COLOR_RED + except (ValueError, IOError) as e: + raise RuntimeError("Failed to read led status for psu due to {}".format(repr(e))) + + return self.STATUS_LED_COLOR_OFF + + + def get_power_available_status(self): + """ + Gets the power available status + + Returns: + True if power is present and power on. + False and "absence of PSU" if power is not present. + False and "absence of power" if power is present but not power on. + """ + if not self.get_presence(): + return False, "absence of PSU" + elif not self.get_powergood_status(): + return False, "absence of power" + else: + return True, "" + diff --git a/platform/mellanox/mlnx-platform-api/sonic_platform/sfp_event.py b/platform/mellanox/mlnx-platform-api/sonic_platform/sfp_event.py index 0ed75c26c63a..859e411fb00a 100644 --- a/platform/mellanox/mlnx-platform-api/sonic_platform/sfp_event.py +++ b/platform/mellanox/mlnx-platform-api/sonic_platform/sfp_event.py @@ -259,7 +259,7 @@ def check_sfp_status(self, port_change, timeout): for port in port_list: logger.log_info("SFP on port {} state {}".format(port, sfp_state)) - port_change[port] = sfp_state + port_change[port+1] = sfp_state found += 1 return found != 0 diff --git a/platform/mellanox/mlnx-platform-api/sonic_platform/thermal.py b/platform/mellanox/mlnx-platform-api/sonic_platform/thermal.py index 1d03016af4ef..f1ad5d86e3c9 100644 --- a/platform/mellanox/mlnx-platform-api/sonic_platform/thermal.py +++ b/platform/mellanox/mlnx-platform-api/sonic_platform/thermal.py @@ -36,28 +36,46 @@ THERMAL_API_GET_TEMPERATURE = "get_temperature" THERMAL_API_GET_HIGH_THRESHOLD = "get_high_threshold" +THERMAL_API_GET_HIGH_CRITICAL_THRESHOLD = "get_high_critical_threshold" + +THERMAL_API_INVALID_HIGH_THRESHOLD = 0.0 HW_MGMT_THERMAL_ROOT = "/var/run/hw-management/thermal/" +THERMAL_ZONE_ASIC_PATH = "/var/run/hw-management/thermal/mlxsw/" +THERMAL_ZONE_MODULE_PATH = "/var/run/hw-management/thermal/mlxsw-module{}/" +THERMAL_ZONE_GEARBOX_PATH = "/var/run/hw-management/thermal/mlxsw-gearbox{}/" +THERMAL_ZONE_MODE = "thermal_zone_mode" +THERMAL_ZONE_POLICY = "thermal_zone_policy" +THERMAL_ZONE_TEMPERATURE = "thermal_zone_temp" +THERMAL_ZONE_NORMAL_TEMPERATURE = "temp_trip_norm" + +MODULE_TEMPERATURE_FAULT_PATH = "/var/run/hw-management/thermal/module{}_temp_fault" + thermal_api_handler_cpu_core = { THERMAL_API_GET_TEMPERATURE:"cpu_core{}", - THERMAL_API_GET_HIGH_THRESHOLD:"cpu_core{}_max" + THERMAL_API_GET_HIGH_THRESHOLD:"cpu_core{}_max", + THERMAL_API_GET_HIGH_CRITICAL_THRESHOLD:"cpu_core{}_crit" } thermal_api_handler_cpu_pack = { THERMAL_API_GET_TEMPERATURE:"cpu_pack", - THERMAL_API_GET_HIGH_THRESHOLD:"cpu_pack_max" + THERMAL_API_GET_HIGH_THRESHOLD:"cpu_pack_max", + THERMAL_API_GET_HIGH_CRITICAL_THRESHOLD:"cpu_pack_crit" } thermal_api_handler_module = { THERMAL_API_GET_TEMPERATURE:"module{}_temp_input", - THERMAL_API_GET_HIGH_THRESHOLD:"module{}_temp_crit" + THERMAL_API_GET_HIGH_THRESHOLD:"module{}_temp_crit", + THERMAL_API_GET_HIGH_CRITICAL_THRESHOLD:"module{}_temp_emergency" } thermal_api_handler_psu = { THERMAL_API_GET_TEMPERATURE:"psu{}_temp", - THERMAL_API_GET_HIGH_THRESHOLD:"psu{}_temp_max" + THERMAL_API_GET_HIGH_THRESHOLD:"psu{}_temp_max", + THERMAL_API_GET_HIGH_CRITICAL_THRESHOLD:None } thermal_api_handler_gearbox = { - THERMAL_API_GET_TEMPERATURE:"temp_input_gearbox{}", - THERMAL_API_GET_HIGH_THRESHOLD:None + THERMAL_API_GET_TEMPERATURE:"gearbox{}_temp_input", + THERMAL_API_GET_HIGH_THRESHOLD:None, + THERMAL_API_GET_HIGH_CRITICAL_THRESHOLD:None } thermal_ambient_apis = { THERMAL_DEV_ASIC_AMBIENT : "asic", @@ -106,7 +124,7 @@ THERMAL_API_GET_HIGH_THRESHOLD ] -hwsku_dict_thermal = {'ACS-MSN2700': 0, 'LS-SN2700':0, 'ACS-MSN2740': 3, 'ACS-MSN2100': 1, 'ACS-MSN2410': 2, 'ACS-MSN2010': 4, 'ACS-MSN3700': 5, 'ACS-MSN3700C': 6, 'Mellanox-SN2700': 0, 'Mellanox-SN2700-D48C8': 0, 'ACS-MSN3800': 7, 'Mellanox-SN3800-D112C8': 7, 'ACS-MSN4700': 8, 'ACS-MSN3420': 9, 'ACS-MSN4600C': 9} +platform_dict_thermal = {'x86_64-mlnx_msn2700-r0': 0, 'x86_64-mlnx_lssn2700-r0':0, 'x86_64-mlnx_msn2740-r0': 3, 'x86_64-mlnx_msn2100-r0': 1, 'x86_64-mlnx_msn2410-r0': 2, 'x86_64-mlnx_msn2010-r0': 4, 'x86_64-mlnx_msn3420-r0':9, 'x86_64-mlnx_msn3700-r0': 5, 'x86_64-mlnx_msn3700c-r0': 6, 'x86_64-mlnx_msn3800-r0': 7, 'x86_64-mlnx_msn4600c-r0':9, 'x86_64-mlnx_msn4700-r0': 8} thermal_profile_list = [ # 2700 { @@ -281,10 +299,12 @@ } ] -def initialize_thermals(sku, thermal_list, psu_list): + +def initialize_thermals(platform, thermal_list, psu_list): # create thermal objects for all categories of sensors - tp_index = hwsku_dict_thermal[sku] + tp_index = platform_dict_thermal[platform] thermal_profile = thermal_profile_list[tp_index] + Thermal.thermal_profile = thermal_profile for category in thermal_device_categories_all: if category == THERMAL_DEV_CATEGORY_AMBIENT: count, ambient_list = thermal_profile[category] @@ -303,15 +323,20 @@ def initialize_thermals(sku, thermal_list, psu_list): else: if category == THERMAL_DEV_CATEGORY_PSU: for index in range(count): - thermal = Thermal(category, start + index, True, psu_list[index].get_powergood_status, "power off") + thermal = Thermal(category, start + index, True, psu_list[index].get_power_available_status) thermal_list.append(thermal) else: for index in range(count): thermal = Thermal(category, start + index, True) thermal_list.append(thermal) + + class Thermal(ThermalBase): - def __init__(self, category, index, has_index, dependency = None, hint = None): + thermal_profile = None + thermal_algorithm_status = False + + def __init__(self, category, index, has_index, dependency = None): """ index should be a string for category ambient and int for other categories """ @@ -328,8 +353,9 @@ def __init__(self, category, index, has_index, dependency = None, hint = None): self.category = category self.temperature = self._get_file_from_api(THERMAL_API_GET_TEMPERATURE) self.high_threshold = self._get_file_from_api(THERMAL_API_GET_HIGH_THRESHOLD) + self.high_critical_threshold = self._get_file_from_api(THERMAL_API_GET_HIGH_CRITICAL_THRESHOLD) self.dependency = dependency - self.dependent_hint = hint + def get_name(self): """ @@ -340,18 +366,21 @@ def get_name(self): """ return self.name - def _read_generic_file(self, filename, len): + + @classmethod + def _read_generic_file(cls, filename, len): """ Read a generic file, returns the contents of the file """ result = None try: with open(filename, 'r') as fileobj: - result = fileobj.read() + result = fileobj.read().strip() except Exception as e: logger.log_info("Fail to read file {} due to {}".format(filename, repr(e))) return result + def _get_file_from_api(self, api_name): if self.category == THERMAL_DEV_CATEGORY_AMBIENT: if api_name == THERMAL_API_GET_TEMPERATURE: @@ -363,9 +392,13 @@ def _get_file_from_api(self, api_name): if self.category in thermal_device_categories_singleton: filename = handler else: - filename = handler.format(self.index) + if handler: + filename = handler.format(self.index) + else: + return None return join(HW_MGMT_THERMAL_ROOT, filename) + def get_temperature(self): """ Retrieves current temperature reading from thermal @@ -374,19 +407,20 @@ def get_temperature(self): A float number of current temperature in Celsius up to nearest thousandth of one degree Celsius, e.g. 30.125 """ - if self.dependency and not self.dependency(): - if self.dependent_hint: - hint = self.dependent_hint - else: - hint = "unknown reason" - logger.log_info("get_temperature for {} failed due to {}".format(self.name, hint)) - return None + if self.dependency: + status, hint = self.dependency() + if not status: + logger.log_debug("get_temperature for {} failed due to {}".format(self.name, hint)) + return None value_str = self._read_generic_file(self.temperature, 0) if value_str is None: return None value_float = float(value_str) + if self.category == THERMAL_DEV_CATEGORY_MODULE and value_float == THERMAL_API_INVALID_HIGH_THRESHOLD: + return None return value_float / 1000.0 + def get_high_threshold(self): """ Retrieves the high threshold temperature of thermal @@ -397,8 +431,167 @@ def get_high_threshold(self): """ if self.high_threshold is None: return None + if self.dependency: + status, hint = self.dependency() + if not status: + logger.log_debug("get_high_threshold for {} failed due to {}".format(self.name, hint)) + return None value_str = self._read_generic_file(self.high_threshold, 0) if value_str is None: return None value_float = float(value_str) + if self.category == THERMAL_DEV_CATEGORY_MODULE and value_float == THERMAL_API_INVALID_HIGH_THRESHOLD: + return None + return value_float / 1000.0 + + + def get_high_critical_threshold(self): + """ + Retrieves the high critical threshold temperature of thermal + + Returns: + A float number, the high critical threshold temperature of thermal in Celsius + up to nearest thousandth of one degree Celsius, e.g. 30.125 + """ + if self.high_critical_threshold is None: + return None + if self.dependency: + status, hint = self.dependency() + if not status: + logger.log_debug("get_high_critical_threshold for {} failed due to {}".format(self.name, hint)) + return None + value_str = self._read_generic_file(self.high_critical_threshold, 0) + if value_str is None: + return None + value_float = float(value_str) + if self.category == THERMAL_DEV_CATEGORY_MODULE and value_float == THERMAL_API_INVALID_HIGH_THRESHOLD: + return None return value_float / 1000.0 + + + @classmethod + def _write_generic_file(cls, filename, content): + """ + Generic functions to write content to a specified file path if + the content has changed. + """ + try: + with open(filename, 'w+') as file_obj: + origin_content = file_obj.read() + if origin_content != content: + file_obj.write(content) + except Exception as e: + logger.log_info("Fail to write file {} due to {}".format(filename, repr(e))) + + @classmethod + def set_thermal_algorithm_status(cls, status, force=True): + """ + Enable/disable kernel thermal algorithm. + When enable kernel thermal algorithm, kernel will adjust fan speed + according to thermal zones temperature. Please note that kernel will + only adjust fan speed when temperature across some "edge", e.g temperature + changes to exceed high threshold. + When disable kernel thermal algorithm, kernel no longer adjust fan speed. + We usually disable the algorithm when we want to set a fix speed. E.g, when + a fan unit is removed from system, we will set fan speed to 100% and disable + the algorithm to avoid it adjust the speed. + + Returns: + True if thermal algorithm status changed. + """ + if not cls.thermal_profile: + raise Exception("Fail to get thermal profile for this switch") + + if not force and cls.thermal_algorithm_status == status: + return False + + cls.thermal_algorithm_status = status + content = "enabled" if status else "disabled" + policy = "step_wise" if status else "user_space" + cls._write_generic_file(join(THERMAL_ZONE_ASIC_PATH, THERMAL_ZONE_MODE), content) + cls._write_generic_file(join(THERMAL_ZONE_ASIC_PATH, THERMAL_ZONE_POLICY), policy) + + if THERMAL_DEV_CATEGORY_MODULE in cls.thermal_profile: + start, count = cls.thermal_profile[THERMAL_DEV_CATEGORY_MODULE] + if count != 0: + for index in range(count): + cls._write_generic_file(join(THERMAL_ZONE_MODULE_PATH.format(start + index), THERMAL_ZONE_MODE), content) + cls._write_generic_file(join(THERMAL_ZONE_MODULE_PATH.format(start + index), THERMAL_ZONE_POLICY), policy) + + if THERMAL_DEV_CATEGORY_GEARBOX in cls.thermal_profile: + start, count = cls.thermal_profile[THERMAL_DEV_CATEGORY_GEARBOX] + if count != 0: + for index in range(count): + cls._write_generic_file(join(THERMAL_ZONE_GEARBOX_PATH.format(start + index), THERMAL_ZONE_MODE), content) + cls._write_generic_file(join(THERMAL_ZONE_GEARBOX_PATH.format(start + index), THERMAL_ZONE_POLICY), policy) + return True + + @classmethod + def check_thermal_zone_temperature(cls): + """ + Check thermal zone current temperature with normal temperature + + Returns: + True if all thermal zones current temperature less or equal than normal temperature + """ + if not cls.thermal_profile: + raise Exception("Fail to get thermal profile for this switch") + + if not cls._check_thermal_zone_temperature(THERMAL_ZONE_ASIC_PATH): + return False + + if THERMAL_DEV_CATEGORY_MODULE in cls.thermal_profile: + start, count = cls.thermal_profile[THERMAL_DEV_CATEGORY_MODULE] + if count != 0: + for index in range(count): + if not cls._check_thermal_zone_temperature(THERMAL_ZONE_MODULE_PATH.format(start + index)): + return False + + if THERMAL_DEV_CATEGORY_GEARBOX in cls.thermal_profile: + start, count = cls.thermal_profile[THERMAL_DEV_CATEGORY_GEARBOX] + if count != 0: + for index in range(count): + if not cls._check_thermal_zone_temperature(THERMAL_ZONE_GEARBOX_PATH.format(start + index)): + return False + + return True + + @classmethod + def _check_thermal_zone_temperature(cls, thermal_zone_path): + normal_temp_path = join(thermal_zone_path, THERMAL_ZONE_NORMAL_TEMPERATURE) + current_temp_path = join(thermal_zone_path, THERMAL_ZONE_TEMPERATURE) + normal = None + current = None + try: + with open(normal_temp_path, 'r') as file_obj: + normal = float(file_obj.read()) + + with open(current_temp_path, 'r') as file_obj: + current = float(file_obj.read()) + + return current <= normal + except Exception as e: + logger.log_info("Fail to check thermal zone temperature for file {} due to {}".format(thermal_zone_path, repr(e))) + + @classmethod + def check_module_temperature_trustable(cls): + if not cls.thermal_profile: + raise Exception("Fail to get thermal profile for this switch") + + start, count = cls.thermal_profile[THERMAL_DEV_CATEGORY_MODULE] + for index in range(count): + fault_file_path = MODULE_TEMPERATURE_FAULT_PATH.format(index + start) + fault = cls._read_generic_file(fault_file_path, 0) + if fault.strip() != '0': + return 'untrust' + return 'trust' + + @classmethod + def get_min_amb_temperature(cls): + fan_ambient_path = join(HW_MGMT_THERMAL_ROOT, THERMAL_DEV_FAN_AMBIENT) + port_ambient_path = join(HW_MGMT_THERMAL_ROOT, THERMAL_DEV_PORT_AMBIENT) + + # if there is any exception, let it raise + fan_ambient_temp = int(cls._read_generic_file(fan_ambient_path, 0)) + port_ambient_temp = int(cls._read_generic_file(port_ambient_path, 0)) + return fan_ambient_temp if fan_ambient_temp < port_ambient_temp else port_ambient_temp diff --git a/platform/mellanox/mlnx-platform-api/sonic_platform/thermal_actions.py b/platform/mellanox/mlnx-platform-api/sonic_platform/thermal_actions.py new file mode 100644 index 000000000000..e7436bd0a5b7 --- /dev/null +++ b/platform/mellanox/mlnx-platform-api/sonic_platform/thermal_actions.py @@ -0,0 +1,209 @@ +from sonic_platform_base.sonic_thermal_control.thermal_action_base import ThermalPolicyActionBase +from sonic_platform_base.sonic_thermal_control.thermal_json_object import thermal_json_object +from .thermal import logger + + +class SetFanSpeedAction(ThermalPolicyActionBase): + """ + Base thermal action class to set speed for fans + """ + # JSON field definition + JSON_FIELD_SPEED = 'speed' + + def __init__(self): + """ + Constructor of SetFanSpeedAction which actually do nothing. + """ + self.speed = None + + def load_from_json(self, json_obj): + """ + Construct SetFanSpeedAction via JSON. JSON example: + { + "type": "fan.all.set_speed" + "speed": "100" + } + :param json_obj: A JSON object representing a SetFanSpeedAction action. + :return: + """ + if SetFanSpeedAction.JSON_FIELD_SPEED in json_obj: + speed = float(json_obj[SetFanSpeedAction.JSON_FIELD_SPEED]) + if speed < 0 or speed > 100: + raise ValueError('SetFanSpeedAction invalid speed value {} in JSON policy file, valid value should be [0, 100]'. + format(speed)) + self.speed = float(json_obj[SetFanSpeedAction.JSON_FIELD_SPEED]) + else: + raise ValueError('SetFanSpeedAction missing mandatory field {} in JSON policy file'. + format(SetFanSpeedAction.JSON_FIELD_SPEED)) + + +@thermal_json_object('fan.all.set_speed') +class SetAllFanSpeedAction(SetFanSpeedAction): + """ + Action to set speed for all fans + """ + def execute(self, thermal_info_dict): + """ + Set speed for all fans + :param thermal_info_dict: A dictionary stores all thermal information. + :return: + """ + from .thermal_infos import FanInfo + if FanInfo.INFO_NAME in thermal_info_dict and isinstance(thermal_info_dict[FanInfo.INFO_NAME], FanInfo): + fan_info_obj = thermal_info_dict[FanInfo.INFO_NAME] + for fan in fan_info_obj.get_presence_fans(): + fan.set_speed(self.speed) + logger.log_info('Set all system FAN speed to {}'.format(self.speed)) + + SetAllFanSpeedAction.set_psu_fan_speed(thermal_info_dict, self.speed) + + @classmethod + def set_psu_fan_speed(cls, thermal_info_dict, speed): + from .thermal_infos import ChassisInfo + if ChassisInfo.INFO_NAME in thermal_info_dict and isinstance(thermal_info_dict[ChassisInfo.INFO_NAME], ChassisInfo): + chassis = thermal_info_dict[ChassisInfo.INFO_NAME].get_chassis() + for psu in chassis.get_all_psus(): + for psu_fan in psu.get_all_fans(): + psu_fan.set_speed(speed) + + +@thermal_json_object('fan.all.check_and_set_speed') +class CheckAndSetAllFanSpeedAction(SetAllFanSpeedAction): + """ + Action to check thermal zone temperature and recover speed for all fans + """ + def execute(self, thermal_info_dict): + """ + Check thermal zone and set speed for all fans + :param thermal_info_dict: A dictionary stores all thermal information. + :return: + """ + from .thermal import Thermal + if Thermal.check_thermal_zone_temperature(): + SetAllFanSpeedAction.execute(self, thermal_info_dict) + + +@thermal_json_object('thermal_control.control') +class ControlThermalAlgoAction(ThermalPolicyActionBase): + """ + Action to control the thermal control algorithm + """ + # JSON field definition + JSON_FIELD_STATUS = 'status' + + def __init__(self): + self.status = True + + def load_from_json(self, json_obj): + """ + Construct ControlThermalAlgoAction via JSON. JSON example: + { + "type": "thermal_control.control" + "status": "true" + } + :param json_obj: A JSON object representing a ControlThermalAlgoAction action. + :return: + """ + if ControlThermalAlgoAction.JSON_FIELD_STATUS in json_obj: + status_str = json_obj[ControlThermalAlgoAction.JSON_FIELD_STATUS].lower() + if status_str == 'true': + self.status = True + elif status_str == 'false': + self.status = False + else: + raise ValueError('Invalid {} field value, please specify true of false'. + format(ControlThermalAlgoAction.JSON_FIELD_STATUS)) + else: + raise ValueError('ControlThermalAlgoAction ' + 'missing mandatory field {} in JSON policy file'. + format(ControlThermalAlgoAction.JSON_FIELD_STATUS)) + + def execute(self, thermal_info_dict): + """ + Disable thermal control algorithm + :param thermal_info_dict: A dictionary stores all thermal information. + :return: + """ + from .thermal_infos import FanInfo + from .thermal import Thermal + from .thermal_conditions import UpdateCoolingLevelToMinCondition + from .fan import Fan + status_changed = Thermal.set_thermal_algorithm_status(self.status, False) + + # Only update cooling level if thermal algorithm status changed + if status_changed: + if self.status: + # Check thermal zone temperature, if all thermal zone temperature + # back to normal, set it to minimum allowed speed to + # save power + UpdateCoolingLevelToMinAction.update_cooling_level_to_minimum(thermal_info_dict) + + logger.log_info('Changed thermal algorithm status to {}'.format(self.status)) + + +@thermal_json_object('thermal.recover') +class ThermalRecoverAction(ThermalPolicyActionBase): + def execute(self, thermal_info_dict): + UpdateCoolingLevelToMinAction.update_cooling_level_to_minimum(thermal_info_dict) + + +class ChangeMinCoolingLevelAction(ThermalPolicyActionBase): + UNKNOWN_SKU_COOLING_LEVEL = 6 + def execute(self, thermal_info_dict): + from .device_data import DEVICE_DATA + from .fan import Fan + from .thermal_infos import ChassisInfo + from .thermal_conditions import MinCoolingLevelChangeCondition + from .thermal_conditions import UpdateCoolingLevelToMinCondition + + chassis = thermal_info_dict[ChassisInfo.INFO_NAME].get_chassis() + if chassis.platform_name not in DEVICE_DATA or 'thermal' not in DEVICE_DATA[chassis.platform_name] or 'minimum_table' not in DEVICE_DATA[chassis.platform_name]['thermal']: + Fan.min_cooling_level = ChangeMinCoolingLevelAction.UNKNOWN_SKU_COOLING_LEVEL + else: + trust_state = MinCoolingLevelChangeCondition.trust_state + temperature = MinCoolingLevelChangeCondition.temperature + minimum_table = DEVICE_DATA[chassis.platform_name]['thermal']['minimum_table']['unk_{}'.format(trust_state)] + + for key, cooling_level in minimum_table.items(): + temp_range = key.split(':') + temp_min = int(temp_range[0].strip()) + temp_max = int(temp_range[1].strip()) + if temp_min <= temperature <= temp_max: + Fan.min_cooling_level = cooling_level - 10 + break + + current_cooling_level = Fan.get_cooling_level() + if current_cooling_level < Fan.min_cooling_level: + Fan.set_cooling_level(Fan.min_cooling_level, Fan.min_cooling_level) + SetAllFanSpeedAction.set_psu_fan_speed(thermal_info_dict, Fan.min_cooling_level * 10) + else: + Fan.set_cooling_level(Fan.min_cooling_level, current_cooling_level) + UpdateCoolingLevelToMinAction.update_cooling_level_to_minimum(thermal_info_dict) + + +class UpdatePsuFanSpeedAction(ThermalPolicyActionBase): + def execute(self, thermal_info_dict): + from .thermal_conditions import CoolingLevelChangeCondition + SetAllFanSpeedAction.set_psu_fan_speed(thermal_info_dict, CoolingLevelChangeCondition.cooling_level * 10) + + +class UpdateCoolingLevelToMinAction(ThermalPolicyActionBase): + def execute(self, thermal_info_dict): + self.update_cooling_level_to_minimum(thermal_info_dict) + + @classmethod + def update_cooling_level_to_minimum(cls, thermal_info_dict): + from .fan import Fan + from .thermal import Thermal + from .thermal_conditions import UpdateCoolingLevelToMinCondition + from .thermal_infos import FanInfo + if Thermal.check_thermal_zone_temperature(): + fan_info_obj = thermal_info_dict[FanInfo.INFO_NAME] + speed = Fan.min_cooling_level * 10 + for fan in fan_info_obj.get_presence_fans(): + fan.set_speed(speed) + SetAllFanSpeedAction.set_psu_fan_speed(thermal_info_dict, speed) + UpdateCoolingLevelToMinCondition.enable = False + else: + UpdateCoolingLevelToMinCondition.enable = True + diff --git a/platform/mellanox/mlnx-platform-api/sonic_platform/thermal_conditions.py b/platform/mellanox/mlnx-platform-api/sonic_platform/thermal_conditions.py new file mode 100644 index 000000000000..94e18a2e00b0 --- /dev/null +++ b/platform/mellanox/mlnx-platform-api/sonic_platform/thermal_conditions.py @@ -0,0 +1,126 @@ +from sonic_platform_base.sonic_thermal_control.thermal_condition_base import ThermalPolicyConditionBase +from sonic_platform_base.sonic_thermal_control.thermal_json_object import thermal_json_object + + +class FanCondition(ThermalPolicyConditionBase): + def get_fan_info(self, thermal_info_dict): + from .thermal_infos import FanInfo + if FanInfo.INFO_NAME in thermal_info_dict and isinstance(thermal_info_dict[FanInfo.INFO_NAME], FanInfo): + return thermal_info_dict[FanInfo.INFO_NAME] + else: + return None + + +@thermal_json_object('fan.any.absence') +class AnyFanAbsenceCondition(FanCondition): + def is_match(self, thermal_info_dict): + fan_info_obj = self.get_fan_info(thermal_info_dict) + return len(fan_info_obj.get_absence_fans()) > 0 if fan_info_obj else False + + +@thermal_json_object('fan.all.absence') +class AllFanAbsenceCondition(FanCondition): + def is_match(self, thermal_info_dict): + fan_info_obj = self.get_fan_info(thermal_info_dict) + return len(fan_info_obj.get_presence_fans()) == 0 if fan_info_obj else False + + +@thermal_json_object('fan.all.presence') +class AllFanPresenceCondition(FanCondition): + def is_match(self, thermal_info_dict): + fan_info_obj = self.get_fan_info(thermal_info_dict) + return len(fan_info_obj.get_absence_fans()) == 0 if fan_info_obj else False + + +@thermal_json_object('fan.any.fault') +class AnyFanFaultCondition(FanCondition): + def is_match(self, thermal_info_dict): + fan_info_obj = self.get_fan_info(thermal_info_dict) + return len(fan_info_obj.get_fault_fans()) > 0 if fan_info_obj else False + + +@thermal_json_object('fan.all.good') +class AllFanGoodCondition(FanCondition): + def is_match(self, thermal_info_dict): + fan_info_obj = self.get_fan_info(thermal_info_dict) + return len(fan_info_obj.get_fault_fans()) == 0 if fan_info_obj else False + + +class PsuCondition(ThermalPolicyConditionBase): + def get_psu_info(self, thermal_info_dict): + from .thermal_infos import PsuInfo + if PsuInfo.INFO_NAME in thermal_info_dict and isinstance(thermal_info_dict[PsuInfo.INFO_NAME], PsuInfo): + return thermal_info_dict[PsuInfo.INFO_NAME] + else: + return None + + +@thermal_json_object('psu.any.absence') +class AnyPsuAbsenceCondition(PsuCondition): + def is_match(self, thermal_info_dict): + psu_info_obj = self.get_psu_info(thermal_info_dict) + return len(psu_info_obj.get_absence_psus()) > 0 if psu_info_obj else False + + +@thermal_json_object('psu.all.absence') +class AllPsuAbsenceCondition(PsuCondition): + def is_match(self, thermal_info_dict): + psu_info_obj = self.get_psu_info(thermal_info_dict) + return len(psu_info_obj.get_presence_psus()) == 0 if psu_info_obj else False + + +@thermal_json_object('psu.all.presence') +class AllPsuPresenceCondition(PsuCondition): + def is_match(self, thermal_info_dict): + psu_info_obj = self.get_psu_info(thermal_info_dict) + return len(psu_info_obj.get_absence_psus()) == 0 if psu_info_obj else False + + +class MinCoolingLevelChangeCondition(ThermalPolicyConditionBase): + trust_state = None + temperature = None + + def is_match(self, thermal_info_dict): + from .thermal import Thermal + + trust_state = Thermal.check_module_temperature_trustable() + temperature = Thermal.get_min_amb_temperature() + temperature = temperature / 1000 + + change_cooling_level = False + if trust_state != MinCoolingLevelChangeCondition.trust_state: + MinCoolingLevelChangeCondition.trust_state = trust_state + change_cooling_level = True + + if temperature != MinCoolingLevelChangeCondition.temperature: + MinCoolingLevelChangeCondition.temperature = temperature + change_cooling_level = True + + return change_cooling_level + + +class CoolingLevelChangeCondition(ThermalPolicyConditionBase): + cooling_level = None + + def is_match(self, thermal_info_dict): + from .fan import Fan + current_cooling_level = Fan.get_cooling_level() + if current_cooling_level != CoolingLevelChangeCondition.cooling_level: + CoolingLevelChangeCondition.cooling_level = current_cooling_level + return True + else: + return False + + +class UpdateCoolingLevelToMinCondition(ThermalPolicyConditionBase): + enable = False + def is_match(self, thermal_info_dict): + if not UpdateCoolingLevelToMinCondition.enable: + return False + + from .fan import Fan + current_cooling_level = Fan.get_cooling_level() + if current_cooling_level == Fan.min_cooling_level: + UpdateCoolingLevelToMinCondition.enable = False + return False + return True diff --git a/platform/mellanox/mlnx-platform-api/sonic_platform/thermal_infos.py b/platform/mellanox/mlnx-platform-api/sonic_platform/thermal_infos.py new file mode 100644 index 000000000000..e810a5646456 --- /dev/null +++ b/platform/mellanox/mlnx-platform-api/sonic_platform/thermal_infos.py @@ -0,0 +1,154 @@ +from sonic_platform_base.sonic_thermal_control.thermal_info_base import ThermalPolicyInfoBase +from sonic_platform_base.sonic_thermal_control.thermal_json_object import thermal_json_object + + +@thermal_json_object('fan_info') +class FanInfo(ThermalPolicyInfoBase): + """ + Fan information needed by thermal policy + """ + + # Fan information name + INFO_NAME = 'fan_info' + + def __init__(self): + self._absence_fans = set() + self._presence_fans = set() + self._fault_fans = set() + self._status_changed = False + + def collect(self, chassis): + """ + Collect absence and presence fans. + :param chassis: The chassis object + :return: + """ + self._status_changed = False + for fan in chassis.get_all_fans(): + presence = fan.get_presence() + status = fan.get_status() + if presence and fan not in self._presence_fans: + self._presence_fans.add(fan) + self._status_changed = True + if fan in self._absence_fans: + self._absence_fans.remove(fan) + elif not presence and fan not in self._absence_fans: + self._absence_fans.add(fan) + self._status_changed = True + if fan in self._presence_fans: + self._presence_fans.remove(fan) + + if not status and fan not in self._fault_fans: + self._fault_fans.add(fan) + self._status_changed = True + elif status and fan in self._fault_fans: + self._fault_fans.remove(fan) + self._status_changed = True + + + def get_absence_fans(self): + """ + Retrieves absence fans + :return: A set of absence fans + """ + return self._absence_fans + + def get_presence_fans(self): + """ + Retrieves presence fans + :return: A set of presence fans + """ + return self._presence_fans + + def get_fault_fans(self): + """ + Retrieves fault fans + :return: A set of fault fans + """ + return self._fault_fans + + def is_status_changed(self): + """ + Retrieves if the status of fan information changed + :return: True if status changed else False + """ + return self._status_changed + + +@thermal_json_object('psu_info') +class PsuInfo(ThermalPolicyInfoBase): + """ + PSU information needed by thermal policy + """ + INFO_NAME = 'psu_info' + + def __init__(self): + self._absence_psus = set() + self._presence_psus = set() + self._status_changed = False + + def collect(self, chassis): + """ + Collect absence and presence PSUs. + :param chassis: The chassis object + :return: + """ + self._status_changed = False + for psu in chassis.get_all_psus(): + if psu.get_presence() and psu.get_powergood_status() and psu not in self._presence_psus: + self._presence_psus.add(psu) + self._status_changed = True + if psu in self._absence_psus: + self._absence_psus.remove(psu) + elif (not psu.get_presence() or not psu.get_powergood_status()) and psu not in self._absence_psus: + self._absence_psus.add(psu) + self._status_changed = True + if psu in self._presence_psus: + self._presence_psus.remove(psu) + + def get_absence_psus(self): + """ + Retrieves presence PSUs + :return: A set of absence PSUs + """ + return self._absence_psus + + def get_presence_psus(self): + """ + Retrieves presence PSUs + :return: A set of presence fans + """ + return self._presence_psus + + def is_status_changed(self): + """ + Retrieves if the status of PSU information changed + :return: True if status changed else False + """ + return self._status_changed + + +@thermal_json_object('chassis_info') +class ChassisInfo(ThermalPolicyInfoBase): + """ + Chassis information needed by thermal policy + """ + INFO_NAME = 'chassis_info' + + def __init__(self): + self._chassis = None + + def collect(self, chassis): + """ + Collect platform chassis. + :param chassis: The chassis object + :return: + """ + self._chassis = chassis + + def get_chassis(self): + """ + Retrieves platform chassis object + :return: A platform chassis object. + """ + return self._chassis diff --git a/platform/mellanox/mlnx-platform-api/sonic_platform/thermal_manager.py b/platform/mellanox/mlnx-platform-api/sonic_platform/thermal_manager.py new file mode 100644 index 000000000000..c0eae332e435 --- /dev/null +++ b/platform/mellanox/mlnx-platform-api/sonic_platform/thermal_manager.py @@ -0,0 +1,64 @@ +from sonic_platform_base.sonic_thermal_control.thermal_manager_base import ThermalManagerBase +from sonic_platform_base.sonic_thermal_control.thermal_policy import ThermalPolicy +from .thermal_actions import * # lgtm [py/polluting-import] +from .thermal_conditions import * # lgtm [py/polluting-import] +from .thermal_infos import * # lgtm [py/polluting-import] + + +class ThermalManager(ThermalManagerBase): + @classmethod + def initialize(cls): + """ + Initialize thermal manager, including register thermal condition types and thermal action types + and any other vendor specific initialization. + :return: + """ + cls._add_private_thermal_policy() + + @classmethod + def deinitialize(cls): + """ + Destroy thermal manager, including any vendor specific cleanup. The default behavior of this function + is a no-op. + :return: + """ + cls.start_thermal_control_algorithm() + + @classmethod + def start_thermal_control_algorithm(cls): + """ + Start thermal control algorithm + + Returns: + bool: True if set success, False if fail. + """ + from .thermal import Thermal + Thermal.set_thermal_algorithm_status(True) + + @classmethod + def stop_thermal_control_algorithm(cls): + """ + Stop thermal control algorithm + + Returns: + bool: True if set success, False if fail. + """ + from .thermal import Thermal + Thermal.set_thermal_algorithm_status(False) + + @classmethod + def _add_private_thermal_policy(cls): + dynamic_min_speed_policy = ThermalPolicy() + dynamic_min_speed_policy.conditions[MinCoolingLevelChangeCondition] = MinCoolingLevelChangeCondition() + dynamic_min_speed_policy.actions[ChangeMinCoolingLevelAction] = ChangeMinCoolingLevelAction() + cls._policy_dict['DynamicMinCoolingLevelPolicy'] = dynamic_min_speed_policy + + update_psu_fan_speed_policy = ThermalPolicy() + update_psu_fan_speed_policy.conditions[CoolingLevelChangeCondition] = CoolingLevelChangeCondition() + update_psu_fan_speed_policy.actions[UpdatePsuFanSpeedAction] = UpdatePsuFanSpeedAction() + cls._policy_dict['UpdatePsuFanSpeedPolicy'] = update_psu_fan_speed_policy + + update_cooling_level_policy = ThermalPolicy() + update_cooling_level_policy.conditions[UpdateCoolingLevelToMinCondition] = UpdateCoolingLevelToMinCondition() + update_cooling_level_policy.actions[UpdateCoolingLevelToMinAction] = UpdateCoolingLevelToMinAction() + cls._policy_dict['UpdateCoolingLevelPolicy'] = update_cooling_level_policy diff --git a/platform/mellanox/mlnx-platform-api/tests/__init__.py b/platform/mellanox/mlnx-platform-api/tests/__init__.py new file mode 100644 index 000000000000..e69de29bb2d1 diff --git a/platform/mellanox/mlnx-platform-api/tests/duplicate_action.json b/platform/mellanox/mlnx-platform-api/tests/duplicate_action.json new file mode 100644 index 000000000000..c19787aa26e0 --- /dev/null +++ b/platform/mellanox/mlnx-platform-api/tests/duplicate_action.json @@ -0,0 +1,18 @@ +{ + "name": "any fan absence", + "conditions": [ + { + "type": "fan.any.absence" + } + ], + "actions": [ + { + "type": "fan.all.set_speed", + "speed": "100" + }, + { + "type": "fan.all.set_speed", + "speed": "100" + } + ] +} diff --git a/platform/mellanox/mlnx-platform-api/tests/duplicate_condition.json b/platform/mellanox/mlnx-platform-api/tests/duplicate_condition.json new file mode 100644 index 000000000000..c25d84762e2a --- /dev/null +++ b/platform/mellanox/mlnx-platform-api/tests/duplicate_condition.json @@ -0,0 +1,17 @@ +{ + "name": "any fan absence", + "conditions": [ + { + "type": "fan.any.absence" + }, + { + "type": "fan.any.absence" + } + ], + "actions": [ + { + "type": "fan.all.set_speed", + "speed": "100" + } + ] +} diff --git a/platform/mellanox/mlnx-platform-api/tests/empty_action.json b/platform/mellanox/mlnx-platform-api/tests/empty_action.json new file mode 100644 index 000000000000..b1051b5a6f60 --- /dev/null +++ b/platform/mellanox/mlnx-platform-api/tests/empty_action.json @@ -0,0 +1,10 @@ +{ + "name": "any fan absence", + "conditions": [ + { + "type": "fan.any.absence" + } + ], + "actions": [ + ] +} \ No newline at end of file diff --git a/platform/mellanox/mlnx-platform-api/tests/empty_condition.json b/platform/mellanox/mlnx-platform-api/tests/empty_condition.json new file mode 100644 index 000000000000..e7a588459246 --- /dev/null +++ b/platform/mellanox/mlnx-platform-api/tests/empty_condition.json @@ -0,0 +1,11 @@ +{ + "name": "any fan absence", + "conditions": [ + ], + "actions": [ + { + "type": "fan.all.set_speed", + "speed": "100" + } + ] +} \ No newline at end of file diff --git a/platform/mellanox/mlnx-platform-api/tests/mock_platform.py b/platform/mellanox/mlnx-platform-api/tests/mock_platform.py new file mode 100644 index 000000000000..c53480584889 --- /dev/null +++ b/platform/mellanox/mlnx-platform-api/tests/mock_platform.py @@ -0,0 +1,58 @@ +class MockFan: + speed = 60 + def __init__(self): + self.presence = True + self.status = True + + def get_presence(self): + return self.presence + + def set_speed(self, speed): + MockFan.speed = speed + + def get_status(self): + return self.status + + def get_target_speed(self): + return MockFan.speed + + +class MockPsu: + def __init__(self): + self.presence = True + self.powergood = True + + def get_presence(self): + return self.presence + + def get_powergood_status(self): + return self.powergood + + def get_all_fans(self): + return [] + + +class MockChassis: + def __init__(self): + self.fan_list = [] + self.psu_list = [] + + def get_all_psus(self): + return self.psu_list + + def get_all_fans(self): + return self.fan_list + + def get_thermal_manager(self): + from sonic_platform.thermal_manager import ThermalManager + return ThermalManager + + def make_fan_absence(self): + fan = MockFan() + fan.presence = False + self.fan_list.append(fan) + + def make_psu_absence(self): + psu = MockPsu() + psu.presence = False + self.psu_list.append(psu) diff --git a/platform/mellanox/mlnx-platform-api/tests/policy_with_same_conditions.json b/platform/mellanox/mlnx-platform-api/tests/policy_with_same_conditions.json new file mode 100644 index 000000000000..ace291be1c55 --- /dev/null +++ b/platform/mellanox/mlnx-platform-api/tests/policy_with_same_conditions.json @@ -0,0 +1,75 @@ +{ + "thermal_control_algorithm": { + "run_at_boot_up": "false", + "fan_speed_when_suspend": "60" + }, + "info_types": [ + { + "type": "fan_info" + }, + { + "type": "psu_info" + }, + { + "type": "chassis_info" + } + ], + "policies": [ + { + "name": "all fan and psu presence", + "conditions": [ + { + "type": "fan.all.presence" + }, + { + "type": "psu.all.presence" + } + ], + "actions": [ + { + "type": "thermal_control.control", + "status": "false" + }, + { + "type": "fan.all.set_speed", + "speed": "100" + } + ] + }, + { + "name": "any psu absence", + "conditions": [ + { + "type": "psu.any.absence" + } + ], + "actions": [ + { + "type": "thermal_control.control", + "status": "false" + }, + { + "type": "fan.all.set_speed", + "speed": "100" + } + ] + }, + { + "name": "all fan and psu presence 1", + "conditions": [ + { + "type": "fan.all.presence" + }, + { + "type": "psu.all.presence" + } + ], + "actions": [ + { + "type": "thermal_control.control", + "status": "true" + } + ] + } + ] +} \ No newline at end of file diff --git a/platform/mellanox/mlnx-platform-api/tests/test_fan_api.py b/platform/mellanox/mlnx-platform-api/tests/test_fan_api.py new file mode 100644 index 000000000000..381260163c0f --- /dev/null +++ b/platform/mellanox/mlnx-platform-api/tests/test_fan_api.py @@ -0,0 +1,17 @@ +import os +import sys +from mock import MagicMock + +test_path = os.path.dirname(os.path.abspath(__file__)) +modules_path = os.path.dirname(test_path) +sys.path.insert(0, modules_path) + +from sonic_platform.fan import Fan + + +def test_get_absence_fan_direction(): + fan = Fan(True, 0, 0) + fan.get_presence = MagicMock(return_value=False) + assert fan.fan_dir is not None + assert not fan.is_psu_fan + assert fan.get_direction() == Fan.FAN_DIRECTION_NOT_APPLICABLE diff --git a/platform/mellanox/mlnx-platform-api/tests/test_thermal_policy.py b/platform/mellanox/mlnx-platform-api/tests/test_thermal_policy.py new file mode 100644 index 000000000000..f25b6421ed85 --- /dev/null +++ b/platform/mellanox/mlnx-platform-api/tests/test_thermal_policy.py @@ -0,0 +1,496 @@ +import os +import sys +import pytest +import json +from mock import MagicMock +from .mock_platform import MockChassis, MockFan, MockPsu + +test_path = os.path.dirname(os.path.abspath(__file__)) +modules_path = os.path.dirname(test_path) +sys.path.insert(0, modules_path) + +from sonic_platform.thermal_manager import ThermalManager +from sonic_platform.thermal_infos import FanInfo, PsuInfo +from sonic_platform.thermal import Thermal + +Thermal.check_thermal_zone_temperature = MagicMock() +Thermal.set_thermal_algorithm_status = MagicMock() + + +@pytest.fixture(scope='session', autouse=True) +def thermal_manager(): + policy_file = os.path.join(test_path, 'thermal_policy.json') + ThermalManager.load(policy_file) + return ThermalManager + + +def test_load_policy(thermal_manager): + assert 'psu_info' in thermal_manager._thermal_info_dict + assert 'fan_info' in thermal_manager._thermal_info_dict + assert 'chassis_info' in thermal_manager._thermal_info_dict + + assert 'any fan absence' in thermal_manager._policy_dict + assert 'any psu absence' in thermal_manager._policy_dict + assert 'any fan broken' in thermal_manager._policy_dict + assert 'all fan and psu presence' in thermal_manager._policy_dict + + assert thermal_manager._fan_speed_when_suspend == 60 + assert thermal_manager._run_thermal_algorithm_at_boot_up == False + + +def test_fan_info(): + chassis = MockChassis() + chassis.make_fan_absence() + fan_info = FanInfo() + fan_info.collect(chassis) + assert len(fan_info.get_absence_fans()) == 1 + assert len(fan_info.get_presence_fans()) == 0 + assert len(fan_info.get_fault_fans()) == 0 + assert fan_info.is_status_changed() + + fan_list = chassis.get_all_fans() + fan_list[0].presence = True + fan_info.collect(chassis) + assert len(fan_info.get_absence_fans()) == 0 + assert len(fan_info.get_presence_fans()) == 1 + assert len(fan_info.get_fault_fans()) == 0 + assert fan_info.is_status_changed() + + fan_list[0].status = False + fan_info.collect(chassis) + assert len(fan_info.get_absence_fans()) == 0 + assert len(fan_info.get_presence_fans()) == 1 + assert len(fan_info.get_fault_fans()) == 1 + assert fan_info.is_status_changed() + +def test_psu_info(): + chassis = MockChassis() + chassis.make_psu_absence() + psu_info = PsuInfo() + psu_info.collect(chassis) + assert len(psu_info.get_absence_psus()) == 1 + assert len(psu_info.get_presence_psus()) == 0 + assert psu_info.is_status_changed() + + psu_list = chassis.get_all_psus() + psu_list[0].presence = True + psu_info.collect(chassis) + assert len(psu_info.get_absence_psus()) == 0 + assert len(psu_info.get_presence_psus()) == 1 + assert psu_info.is_status_changed() + + psu_list[0].powergood = False + psu_info.collect(chassis) + assert len(psu_info.get_absence_psus()) == 1 + assert len(psu_info.get_presence_psus()) == 0 + assert psu_info.is_status_changed() + + +def test_fan_policy(thermal_manager): + chassis = MockChassis() + chassis.make_fan_absence() + chassis.fan_list.append(MockFan()) + thermal_manager.run_policy(chassis) + + fan_list = chassis.get_all_fans() + assert fan_list[1].speed == 100 + Thermal.set_thermal_algorithm_status.assert_called_with(False, False) + + fan_list[0].presence = True + Thermal.check_thermal_zone_temperature = MagicMock(return_value=True) + thermal_manager.run_policy(chassis) + Thermal.set_thermal_algorithm_status.assert_called_with(True, False) + assert Thermal.check_thermal_zone_temperature.call_count == 2 + assert fan_list[0].speed == 60 + assert fan_list[1].speed == 60 + + fan_list[0].status = False + thermal_manager.run_policy(chassis) + Thermal.set_thermal_algorithm_status.assert_called_with(False, False) + + fan_list[0].status = True + Thermal.check_thermal_zone_temperature = MagicMock(return_value=False) + thermal_manager.run_policy(chassis) + Thermal.set_thermal_algorithm_status.assert_called_with(True, False) + assert Thermal.check_thermal_zone_temperature.call_count == 2 + assert fan_list[0].speed == 100 + assert fan_list[1].speed == 100 + + +def test_psu_policy(thermal_manager): + chassis = MockChassis() + chassis.make_psu_absence() + chassis.fan_list.append(MockFan()) + thermal_manager.run_policy(chassis) + + fan_list = chassis.get_all_fans() + assert fan_list[0].speed == 100 + Thermal.set_thermal_algorithm_status.assert_called_with(False, False) + + psu_list = chassis.get_all_psus() + psu_list[0].presence = True + thermal_manager.run_policy(chassis) + Thermal.set_thermal_algorithm_status.assert_called_with(True, False) + + +def test_any_fan_absence_condition(): + chassis = MockChassis() + chassis.make_fan_absence() + fan_info = FanInfo() + fan_info.collect(chassis) + + from sonic_platform.thermal_conditions import AnyFanAbsenceCondition + condition = AnyFanAbsenceCondition() + assert condition.is_match({'fan_info': fan_info}) + + fan = chassis.get_all_fans()[0] + fan.presence = True + fan_info.collect(chassis) + assert not condition.is_match({'fan_info': fan_info}) + + +def test_all_fan_absence_condition(): + chassis = MockChassis() + chassis.make_fan_absence() + fan = MockFan() + fan_list = chassis.get_all_fans() + fan_list.append(fan) + fan_info = FanInfo() + fan_info.collect(chassis) + + from sonic_platform.thermal_conditions import AllFanAbsenceCondition + condition = AllFanAbsenceCondition() + assert not condition.is_match({'fan_info': fan_info}) + + fan.presence = False + fan_info.collect(chassis) + assert condition.is_match({'fan_info': fan_info}) + + +def test_any_fan_fault_condition(): + chassis = MockChassis() + fan = MockFan() + fan_list = chassis.get_all_fans() + fan_list.append(fan) + fault_fan = MockFan() + fault_fan.status = False + fan_list.append(fault_fan) + fan_info = FanInfo() + fan_info.collect(chassis) + + from sonic_platform.thermal_conditions import AnyFanFaultCondition + condition = AnyFanFaultCondition() + assert condition.is_match({'fan_info': fan_info}) + + fault_fan.status = True + fan_info.collect(chassis) + assert not condition.is_match({'fan_info': fan_info}) + +def test_all_fan_good_condition(): + chassis = MockChassis() + fan = MockFan() + fan_list = chassis.get_all_fans() + fan_list.append(fan) + fault_fan = MockFan() + fault_fan.status = False + fan_list.append(fault_fan) + fan_info = FanInfo() + fan_info.collect(chassis) + + from sonic_platform.thermal_conditions import AllFanGoodCondition + condition = AllFanGoodCondition() + assert not condition.is_match({'fan_info': fan_info}) + + fault_fan.status = True + fan_info.collect(chassis) + assert condition.is_match({'fan_info': fan_info}) + + +def test_any_psu_absence_condition(): + chassis = MockChassis() + chassis.make_psu_absence() + psu_info = PsuInfo() + psu_info.collect(chassis) + + from sonic_platform.thermal_conditions import AnyPsuAbsenceCondition + condition = AnyPsuAbsenceCondition() + assert condition.is_match({'psu_info': psu_info}) + + psu = chassis.get_all_psus()[0] + psu.presence = True + psu_info.collect(chassis) + assert not condition.is_match({'psu_info': psu_info}) + + +def test_all_psu_absence_condition(): + chassis = MockChassis() + chassis.make_psu_absence() + psu = MockPsu() + psu_list = chassis.get_all_psus() + psu_list.append(psu) + psu_info = PsuInfo() + psu_info.collect(chassis) + + from sonic_platform.thermal_conditions import AllPsuAbsenceCondition + condition = AllPsuAbsenceCondition() + assert not condition.is_match({'psu_info': psu_info}) + + psu.presence = False + psu_info.collect(chassis) + assert condition.is_match({'psu_info': psu_info}) + + +def test_all_fan_presence_condition(): + chassis = MockChassis() + chassis.make_psu_absence() + psu = MockPsu() + psu_list = chassis.get_all_psus() + psu_list.append(psu) + psu_info = PsuInfo() + psu_info.collect(chassis) + + from sonic_platform.thermal_conditions import AllPsuPresenceCondition + condition = AllPsuPresenceCondition() + assert not condition.is_match({'psu_info': psu_info}) + + psu_list[0].presence = True + psu_info.collect(chassis) + assert condition.is_match({'psu_info': psu_info}) + + +def test_load_set_fan_speed_action(): + from sonic_platform.thermal_actions import SetAllFanSpeedAction + action = SetAllFanSpeedAction() + json_str = '{\"speed\": \"50\"}' + json_obj = json.loads(json_str) + action.load_from_json(json_obj) + assert action.speed == 50 + + json_str = '{\"speed\": \"-1\"}' + json_obj = json.loads(json_str) + with pytest.raises(ValueError): + action.load_from_json(json_obj) + + json_str = '{\"speed\": \"101\"}' + json_obj = json.loads(json_str) + with pytest.raises(ValueError): + action.load_from_json(json_obj) + + json_str = '{\"invalid\": \"101\"}' + json_obj = json.loads(json_str) + with pytest.raises(ValueError): + action.load_from_json(json_obj) + + +def test_execute_set_fan_speed_action(): + chassis = MockChassis() + fan_list = chassis.get_all_fans() + fan_list.append(MockFan()) + fan_list.append(MockFan()) + fan_info = FanInfo() + fan_info.collect(chassis) + + from sonic_platform.thermal_actions import SetAllFanSpeedAction + action = SetAllFanSpeedAction() + action.speed = 99 + action.execute({'fan_info': fan_info}) + assert fan_list[0].speed == 99 + assert fan_list[1].speed == 99 + + +def test_load_control_thermal_algo_action(): + from sonic_platform.thermal_actions import ControlThermalAlgoAction + action = ControlThermalAlgoAction() + json_str = '{\"status\": \"false\"}' + json_obj = json.loads(json_str) + action.load_from_json(json_obj) + assert not action.status + + json_str = '{\"status\": \"true\"}' + json_obj = json.loads(json_str) + action.load_from_json(json_obj) + assert action.status + + json_str = '{\"status\": \"invalid\"}' + json_obj = json.loads(json_str) + with pytest.raises(ValueError): + action.load_from_json(json_obj) + + json_str = '{\"invalid\": \"true\"}' + json_obj = json.loads(json_str) + with pytest.raises(ValueError): + action.load_from_json(json_obj) + +def test_load_check_and_set_speed_action(): + from sonic_platform.thermal_actions import CheckAndSetAllFanSpeedAction + action = CheckAndSetAllFanSpeedAction() + json_str = '{\"speed\": \"40\"}' + json_obj = json.loads(json_str) + action.load_from_json(json_obj) + assert action.speed == 40 + + json_str = '{\"speed\": \"-1\"}' + json_obj = json.loads(json_str) + with pytest.raises(ValueError): + action.load_from_json(json_obj) + + json_str = '{\"speed\": \"101\"}' + json_obj = json.loads(json_str) + with pytest.raises(ValueError): + action.load_from_json(json_obj) + + json_str = '{\"invalid\": \"60\"}' + json_obj = json.loads(json_str) + with pytest.raises(ValueError): + action.load_from_json(json_obj) + +def test_execute_check_and_set_fan_speed_action(): + chassis = MockChassis() + fan_list = chassis.get_all_fans() + fan_list.append(MockFan()) + fan_list.append(MockFan()) + fan_info = FanInfo() + fan_info.collect(chassis) + Thermal.check_thermal_zone_temperature = MagicMock(return_value=True) + + from sonic_platform.thermal_actions import CheckAndSetAllFanSpeedAction + action = CheckAndSetAllFanSpeedAction() + action.speed = 99 + action.execute({'fan_info': fan_info}) + assert fan_list[0].speed == 99 + assert fan_list[1].speed == 99 + + Thermal.check_thermal_zone_temperature = MagicMock(return_value=False) + fan_list[0].speed = 100 + fan_list[1].speed = 100 + action.speed = 60 + action.execute({'fan_info': fan_info}) + assert fan_list[0].speed == 100 + assert fan_list[1].speed == 100 + +def test_load_duplicate_condition(): + from sonic_platform_base.sonic_thermal_control.thermal_policy import ThermalPolicy + with open(os.path.join(test_path, 'duplicate_condition.json')) as f: + json_obj = json.load(f) + policy = ThermalPolicy() + with pytest.raises(Exception): + policy.load_from_json(json_obj) + +def test_load_duplicate_action(): + from sonic_platform_base.sonic_thermal_control.thermal_policy import ThermalPolicy + with open(os.path.join(test_path, 'duplicate_action.json')) as f: + json_obj = json.load(f) + policy = ThermalPolicy() + with pytest.raises(Exception): + policy.load_from_json(json_obj) + +def test_load_empty_condition(): + from sonic_platform_base.sonic_thermal_control.thermal_policy import ThermalPolicy + with open(os.path.join(test_path, 'empty_condition.json')) as f: + json_obj = json.load(f) + policy = ThermalPolicy() + with pytest.raises(Exception): + policy.load_from_json(json_obj) + +def test_load_empty_action(): + from sonic_platform_base.sonic_thermal_control.thermal_policy import ThermalPolicy + with open(os.path.join(test_path, 'empty_action.json')) as f: + json_obj = json.load(f) + policy = ThermalPolicy() + with pytest.raises(Exception): + policy.load_from_json(json_obj) + +def test_load_policy_with_same_conditions(): + from sonic_platform_base.sonic_thermal_control.thermal_manager_base import ThermalManagerBase + class MockThermalManager(ThermalManagerBase): + pass + + with pytest.raises(Exception): + MockThermalManager.load(os.path.join(test_path, 'policy_with_same_conditions.json')) + +def test_dynamic_minimum_table_data(): + from sonic_platform.device_data import DEVICE_DATA + for platform, platform_data in DEVICE_DATA.items(): + if 'thermal' in platform_data and 'minimum_table' in platform_data['thermal']: + minimum_table = platform_data['thermal']['minimum_table'] + check_minimum_table_data(platform, minimum_table) + +def check_minimum_table_data(platform, minimum_table): + valid_dir = ['p2c', 'c2p', 'unk'] + valid_trust_state = ['trust', 'untrust'] + + for category, data in minimum_table.items(): + key_data = category.split('_') + assert key_data[0] in valid_dir + assert key_data[1] in valid_trust_state + + data_list = [(value, key) for key, value in data.items()] + data_list.sort(key=lambda x : x[0]) + + previous_edge = None + previous_cooling_level = None + for item in data_list: + cooling_level = item[0] + range_str = item[1] + + ranges = range_str.split(':') + low = int(ranges[0]) + high = int(ranges[1]) + assert low < high + + if previous_edge is None: + assert low == -127 + else: + assert low - previous_edge == 1, '{}-{}-{} error, item={}'.format(platform, key_data[0], key_data[1], item) + previous_edge = high + + assert 10 <= cooling_level <= 20 + if previous_cooling_level is not None: + assert cooling_level > previous_cooling_level + previous_cooling_level = cooling_level + +def test_dynamic_minimum_policy(thermal_manager): + from sonic_platform.thermal_conditions import MinCoolingLevelChangeCondition + from sonic_platform.thermal_actions import ChangeMinCoolingLevelAction + from sonic_platform.thermal_infos import ChassisInfo + from sonic_platform.thermal import Thermal + from sonic_platform.fan import Fan + ThermalManager.initialize() + assert 'DynamicMinCoolingLevelPolicy' in thermal_manager._policy_dict + policy = thermal_manager._policy_dict['DynamicMinCoolingLevelPolicy'] + assert MinCoolingLevelChangeCondition in policy.conditions + assert ChangeMinCoolingLevelAction in policy.actions + + condition = policy.conditions[MinCoolingLevelChangeCondition] + action = policy.actions[ChangeMinCoolingLevelAction] + Thermal.check_module_temperature_trustable = MagicMock(return_value='trust') + Thermal.get_min_amb_temperature = MagicMock(return_value=35000) + assert condition.is_match(None) + assert MinCoolingLevelChangeCondition.trust_state == 'trust' + assert MinCoolingLevelChangeCondition.temperature == 35 + assert not condition.is_match(None) + + Thermal.check_module_temperature_trustable = MagicMock(return_value='untrust') + assert condition.is_match(None) + assert MinCoolingLevelChangeCondition.trust_state == 'untrust' + + Thermal.get_min_amb_temperature = MagicMock(return_value=25000) + assert condition.is_match(None) + assert MinCoolingLevelChangeCondition.temperature == 25 + + chassis = MockChassis() + chassis.platform_name = 'invalid' + info = ChassisInfo() + info._chassis = chassis + thermal_info_dict = {ChassisInfo.INFO_NAME: info} + Fan.get_cooling_level = MagicMock(return_value=5) + Fan.set_cooling_level = MagicMock() + action.execute(thermal_info_dict) + assert Fan.min_cooling_level == 6 + Fan.set_cooling_level.assert_called_with(6, 6) + Fan.set_cooling_level.call_count = 0 + + chassis.platform_name = 'x86_64-mlnx_msn2700-r0' + action.execute(thermal_info_dict) + assert Fan.min_cooling_level == 3 + Fan.set_cooling_level.assert_called_with(3, 5) diff --git a/platform/mellanox/mlnx-platform-api/tests/thermal_policy.json b/platform/mellanox/mlnx-platform-api/tests/thermal_policy.json new file mode 100644 index 000000000000..413211b21220 --- /dev/null +++ b/platform/mellanox/mlnx-platform-api/tests/thermal_policy.json @@ -0,0 +1,97 @@ +{ + "thermal_control_algorithm": { + "run_at_boot_up": "false", + "fan_speed_when_suspend": "60" + }, + "info_types": [ + { + "type": "fan_info" + }, + { + "type": "psu_info" + }, + { + "type": "chassis_info" + } + ], + "policies": [ + { + "name": "any fan absence", + "conditions": [ + { + "type": "fan.any.absence" + } + ], + "actions": [ + { + "type": "thermal_control.control", + "status": "false" + }, + { + "type": "fan.all.set_speed", + "speed": "100" + } + ] + }, + { + "name": "any psu absence", + "conditions": [ + { + "type": "psu.any.absence" + } + ], + "actions": [ + { + "type": "thermal_control.control", + "status": "false" + }, + { + "type": "fan.all.set_speed", + "speed": "100" + } + ] + }, + { + "name": "any fan broken", + "conditions": [ + { + "type": "fan.any.fault" + } + ], + "actions": [ + { + "type": "thermal_control.control", + "status": "false" + }, + { + "type": "fan.all.set_speed", + "speed": "100" + } + ] + }, + { + "name": "all fan and psu presence", + "conditions": [ + { + "type": "fan.all.presence" + }, + { + "type": "psu.all.presence" + }, + { + "type": "fan.all.good" + } + ], + "actions": [ + { + "type": "thermal_control.control", + "status": "true" + }, + { + "type": "fan.all.check_and_set_speed", + "speed": "60" + } + ] + } + ] +} \ No newline at end of file diff --git a/platform/mellanox/mlnx-sai/SAI-Implementation b/platform/mellanox/mlnx-sai/SAI-Implementation index 8cbb3aaaa2d3..830de815159b 160000 --- a/platform/mellanox/mlnx-sai/SAI-Implementation +++ b/platform/mellanox/mlnx-sai/SAI-Implementation @@ -1 +1 @@ -Subproject commit 8cbb3aaaa2d3ff3d5770d5d2452a0ebe32149206 +Subproject commit 830de815159b4133a3f6d1d86218f8a16e62f590 diff --git a/platform/mellanox/mlnx-ssd-fw-update.sh b/platform/mellanox/mlnx-ssd-fw-update.sh index 5163c8e7f8f7..4a2204adacf8 100755 --- a/platform/mellanox/mlnx-ssd-fw-update.sh +++ b/platform/mellanox/mlnx-ssd-fw-update.sh @@ -35,7 +35,7 @@ #= Global variable # #= #===== -VERSION="1.3" +VERSION="1.5" #===== SWITCH_SSD_DEV="/dev/sda" UTIL_TITLE="This is MLNX SSD firmware update utility to read and write SSD FW. Version ${VERSION}" @@ -79,6 +79,8 @@ function init_script() { else LOGGER_UTIL=$FALSE fi + export LC_ALL= + export LANG="en_US.UTF-8" } #==============================================================================# @@ -415,7 +417,7 @@ function check_package_signing() { LOG_MSG "checksum_signed_file: ${checksum_signed_file}" ${DEBUG_MSG} LOG_MSG "checksum_unsigned_file: ${checksum_unsigned_file}" ${DEBUG_MSG} - gpg --keyring "$public_cert_file" --verify "$checksum_signed_file" "$checksum_unsigned_file" > /dev/null 2>&1 + gpg --ignore-time-conflict --keyring "$public_cert_file" --verify "$checksum_signed_file" "$checksum_unsigned_file" > /dev/null 2>&1 [ $? -ne 0 ] && LOG_MSG_AND_EXIT "Error: fault package signing." LOG_MSG "cd into: ${package_path}" ${DEBUG_MSG} @@ -559,7 +561,7 @@ function print_ssd_info() { LOG_MSG "Device Model\t : $SSD_DEVICE_MODEL" LOG_MSG "Serial Number\t : $SSD_SERIAL" LOG_MSG "User Capacity\t : $SSD_SIZE GB" - LOG_MSG "Firmware Version : $SSD_FW_VER" + LOG_MSG "Firmware Version : $SSD_FW_VER" fi } @@ -695,7 +697,7 @@ elif [ $ARG_UPDATE_FLAG == $TRUE ]; then else LOG_MSG "SSD FW update completed successfully." - if [ $ARG_POWER_CYCLE_FLAG == $TRUE ]; then + if [[ "yes" == "$power_policy" || $ARG_POWER_CYCLE_FLAG == $TRUE ]]; then LOG_MSG "Execute power cycle..." sleep 1 sync @@ -715,7 +717,7 @@ elif [ $ARG_UPDATE_FLAG == $TRUE ]; then fi done if [ $UPDATE_DONE == $FALSE ]; then - LOG_MSG "SSD FW upgrade not require, based on given package latest version is in used." + LOG_MSG "SSD FW upgrade is not required, latest version based on given package is in use." print_ssd_info "no" fi diff --git a/platform/mellanox/sdk-src/sx-kernel/Switch-SDK-drivers b/platform/mellanox/sdk-src/sx-kernel/Switch-SDK-drivers index 0115fcd6b6de..bb4c9c1c9856 160000 --- a/platform/mellanox/sdk-src/sx-kernel/Switch-SDK-drivers +++ b/platform/mellanox/sdk-src/sx-kernel/Switch-SDK-drivers @@ -1 +1 @@ -Subproject commit 0115fcd6b6dea3dd9faf957389885a7ed40b671d +Subproject commit bb4c9c1c98563c3177dc8e086b8ddfe41b9695a2 diff --git a/platform/mellanox/sdk.mk b/platform/mellanox/sdk.mk index 166e66657476..791c34c3f2fd 100644 --- a/platform/mellanox/sdk.mk +++ b/platform/mellanox/sdk.mk @@ -1,5 +1,5 @@ MLNX_SDK_BASE_PATH = $(PLATFORM_PATH)/sdk-src/sx-kernel/Switch-SDK-drivers/bin/ -MLNX_SDK_VERSION = 4.4.0918 +MLNX_SDK_VERSION = 4.4.0952 MLNX_SDK_ISSU_VERSION = 101 MLNX_SDK_DEB_VERSION = $(subst _,.,$(MLNX_SDK_VERSION)) diff --git a/platform/nephos/docker-syncd-nephos/base_image_files/monit_syncd b/platform/nephos/docker-syncd-nephos/base_image_files/monit_syncd index 0b9ec741cd57..81c0b6ef6bc6 100644 --- a/platform/nephos/docker-syncd-nephos/base_image_files/monit_syncd +++ b/platform/nephos/docker-syncd-nephos/base_image_files/monit_syncd @@ -4,7 +4,7 @@ ## syncd ## dsserve ############################################################################### -check process syncd matching "/usr/bin/syncd" +check process syncd matching "/usr/bin/syncd\s" if does not exist for 5 times within 5 cycles then alert check process dsserve matching "/usr/bin/dsserve /usr/bin/syncd" diff --git a/platform/nephos/docker-syncd-nephos/critical_processes b/platform/nephos/docker-syncd-nephos/critical_processes index 489668a89e08..d1163a9c3046 100644 --- a/platform/nephos/docker-syncd-nephos/critical_processes +++ b/platform/nephos/docker-syncd-nephos/critical_processes @@ -1,2 +1,2 @@ -dsserve -syncd +program:dsserve +program:syncd diff --git a/platform/vs/docker-syncd-vs/critical_processes b/platform/vs/docker-syncd-vs/critical_processes new file mode 100644 index 000000000000..bdd6903c5690 --- /dev/null +++ b/platform/vs/docker-syncd-vs/critical_processes @@ -0,0 +1 @@ +program:syncd diff --git a/rules/config b/rules/config index 0c2f07cd2648..8dfaf59fd571 100644 --- a/rules/config +++ b/rules/config @@ -117,11 +117,11 @@ INSTALL_KUBERNETES = n # KUBERNETES_VERSION - Set to the required version. # K8s_GCR_IO_PAUSE_VERSION - Version of k8s universal pause container image -# K8s_CNI_CALICO_VERSION - Calico used as CNI; Appropriate version for this Kubernetes version +# K8s_CNI_FLANNEL_VERSION - Flannel used as CNI; Appropriate version for this Kubernetes version # These are Used *only* when INSTALL_KUBERNETES=y # NOTE: As a worker node it has to run version compatible to kubernetes master. # KUBERNETES_VERSION = 1.18.0 K8s_GCR_IO_PAUSE_VERSION = 3.2 -K8s_CNI_CALICO_VERSION = 3.12.1 +K8s_CNI_FLANNEL_VERSION = v0.12.0 diff --git a/rules/docker-database.mk b/rules/docker-database.mk index 7e372048afab..4112204eea3f 100644 --- a/rules/docker-database.mk +++ b/rules/docker-database.mk @@ -28,4 +28,4 @@ $(DOCKER_DATABASE)_RUN_OPT += -v /etc/sonic:/etc/sonic:ro $(DOCKER_DATABASE)_BASE_IMAGE_FILES += redis-cli:/usr/bin/redis-cli $(DOCKER_DATABASE)_BASE_IMAGE_FILES += monit_database:/etc/monit/conf.d -$(DOCKER_DATABASE)_FILES += $(SUPERVISOR_PROC_EXIT_LISTENER_SCRIPT) +$(DOCKER_DATABASE)_FILES += $(SYSCTL_NET_CONFIG) $(SUPERVISOR_PROC_EXIT_LISTENER_SCRIPT) diff --git a/rules/docker-fpm-frr.mk b/rules/docker-fpm-frr.mk index 45a755a9289f..ad6613a685c6 100644 --- a/rules/docker-fpm-frr.mk +++ b/rules/docker-fpm-frr.mk @@ -5,6 +5,7 @@ DOCKER_FPM_FRR = $(DOCKER_FPM_FRR_STEM).gz DOCKER_FPM_FRR_DBG = $(DOCKER_FPM_FRR_STEM)-$(DBG_IMAGE_MARK).gz $(DOCKER_FPM_FRR)_PATH = $(DOCKERS_PATH)/$(DOCKER_FPM_FRR_STEM) +$(DOCKER_FPM_FRR)_PYTHON_WHEELS += $(SONIC_BGPCFGD) $(DOCKER_FPM_FRR)_DEPENDS += $(FRR) $(FRR_SNMP) $(SWSS) $(LIBYANG) $(DOCKER_FPM_FRR)_DBG_DEPENDS = $($(DOCKER_CONFIG_ENGINE_STRETCH)_DBG_DEPENDS) diff --git a/rules/docker-platform-monitor.mk b/rules/docker-platform-monitor.mk index a37f4d2e9ee7..db1c8c5a0289 100644 --- a/rules/docker-platform-monitor.mk +++ b/rules/docker-platform-monitor.mk @@ -10,7 +10,7 @@ $(DOCKER_PLATFORM_MONITOR)_DEPENDS += $(LIBSENSORS) $(LM_SENSORS) $(FANCONTROL) ifeq ($(CONFIGURED_PLATFORM),barefoot) $(DOCKER_PLATFORM_MONITOR)_DEPENDS += $(PYTHON_THRIFT) endif -$(DOCKER_PLATFORM_MONITOR)_PYTHON_DEBS += $(SONIC_LEDD) $(SONIC_XCVRD) $(SONIC_PSUD) $(SONIC_SYSEEPROMD) +$(DOCKER_PLATFORM_MONITOR)_PYTHON_DEBS += $(SONIC_LEDD) $(SONIC_XCVRD) $(SONIC_PSUD) $(SONIC_SYSEEPROMD) $(SONIC_THERMALCTLD) $(DOCKER_PLATFORM_MONITOR)_PYTHON_WHEELS += $(SONIC_PLATFORM_COMMON_PY2) $(DOCKER_PLATFORM_MONITOR)_PYTHON_WHEELS += $(SWSSSDK_PY2) $(DOCKER_PLATFORM_MONITOR)_PYTHON_WHEELS += $(SONIC_PLATFORM_API_PY2) diff --git a/rules/scripts.mk b/rules/scripts.mk index 8c6d0324fc0e..b3ed0cab95f8 100644 --- a/rules/scripts.mk +++ b/rules/scripts.mk @@ -14,10 +14,12 @@ $(QOS_CONFIG_TEMPLATE)_PATH = files/build_templates SUPERVISOR_PROC_EXIT_LISTENER_SCRIPT = supervisor-proc-exit-listener $(SUPERVISOR_PROC_EXIT_LISTENER_SCRIPT)_PATH = files/scripts +SYSCTL_NET_CONFIG = sysctl-net.conf +$(SYSCTL_NET_CONFIG)_PATH = files/image_config/sysctl + SONIC_COPY_FILES += $(CONFIGDB_LOAD_SCRIPT) \ $(ARP_UPDATE_SCRIPT) \ $(BUFFERS_CONFIG_TEMPLATE) \ $(QOS_CONFIG_TEMPLATE) \ - $(SUPERVISOR_PROC_EXIT_LISTENER_SCRIPT) - - + $(SUPERVISOR_PROC_EXIT_LISTENER_SCRIPT) \ + $(SYSCTL_NET_CONFIG) diff --git a/rules/sonic-thermalctld.mk b/rules/sonic-thermalctld.mk new file mode 100644 index 000000000000..775082e7bbce --- /dev/null +++ b/rules/sonic-thermalctld.mk @@ -0,0 +1,6 @@ +# sonic-thermalctld (SONiC Thermal control daemon) Debian package + +SONIC_THERMALCTLD = python-sonic-thermalctld_1.0-1_all.deb +$(SONIC_THERMALCTLD)_SRC_PATH = $(SRC_PATH)/sonic-platform-daemons/sonic-thermalctld +$(SONIC_THERMALCTLD)_WHEEL_DEPENDS = $(SONIC_DAEMON_BASE_PY2) +SONIC_PYTHON_STDEB_DEBS += $(SONIC_THERMALCTLD) diff --git a/rules/sonic_bgpcfgd.dep b/rules/sonic_bgpcfgd.dep new file mode 100644 index 000000000000..abd51062b8bb --- /dev/null +++ b/rules/sonic_bgpcfgd.dep @@ -0,0 +1,10 @@ + +SPATH := $($(SONIC_BGPCFGD)_SRC_PATH) +DEP_FILES := $(SONIC_COMMON_FILES_LIST) rules/sonic_bgpcfgd.mk rules/sonic_bgpcfgd.dep +DEP_FILES += $(SONIC_COMMON_BASE_FILES_LIST) +DEP_FILES += $(shell git ls-files $(SPATH)) + +$(SONIC_BGPCFGD)_CACHE_MODE := GIT_CONTENT_SHA +$(SONIC_BGPCFGD)_DEP_FLAGS := $(SONIC_COMMON_FLAGS_LIST) +$(SONIC_BGPCFGD)_DEP_FILES := $(DEP_FILES) + diff --git a/rules/sonic_bgpcfgd.mk b/rules/sonic_bgpcfgd.mk new file mode 100644 index 000000000000..650874b619c9 --- /dev/null +++ b/rules/sonic_bgpcfgd.mk @@ -0,0 +1,7 @@ +# sonic-bgpcfgd package + +SONIC_BGPCFGD = sonic_bgpcfgd-1.0-py2-none-any.whl +$(SONIC_BGPCFGD)_SRC_PATH = $(SRC_PATH)/sonic-bgpcfgd +$(SONIC_BGPCFGD)_DEPENDS += $(SWSSSDK_PY2) +$(SONIC_BGPCFGD)_PYTHON_VERSION = 2 +SONIC_PYTHON_WHEELS += $(SONIC_BGPCFGD) diff --git a/sonic-slave-jessie/Dockerfile.j2 b/sonic-slave-jessie/Dockerfile.j2 index 23186d175620..05558fa45457 100644 --- a/sonic-slave-jessie/Dockerfile.j2 +++ b/sonic-slave-jessie/Dockerfile.j2 @@ -322,6 +322,9 @@ RUN pip install mockredispy==2.9.3 RUN pip install pytest-runner==4.4 RUN pip install setuptools==40.8.0 +# For sonic-swss-common testing +RUN pip install Pympler==0.8 + # Install dependencies for isc-dhcp-relay build RUN apt-get -y build-dep isc-dhcp diff --git a/sonic-slave-stretch/Dockerfile.j2 b/sonic-slave-stretch/Dockerfile.j2 index a3936539bc77..69329cd53ec2 100644 --- a/sonic-slave-stretch/Dockerfile.j2 +++ b/sonic-slave-stretch/Dockerfile.j2 @@ -295,7 +295,9 @@ RUN apt-get update && apt-get install -y \ libnetfilter-conntrack-dev \ libnftnl-dev \ # For SAI3.7 + protobuf-compiler \ libprotobuf-dev \ + xxd \ # For DHCP Monitor tool libexplain-dev \ libevent-dev @@ -367,6 +369,9 @@ RUN pip install mockredispy==2.9.3 RUN pip install pytest-runner==4.4 RUN pip install setuptools==40.8.0 +# For sonic-swss-common testing +RUN pip install Pympler==0.8 + # For mgmt-framework build RUN pip install mmh3 diff --git a/src/sonic-bgpcfgd/.gitignore b/src/sonic-bgpcfgd/.gitignore new file mode 100644 index 000000000000..bb1ba531d1d6 --- /dev/null +++ b/src/sonic-bgpcfgd/.gitignore @@ -0,0 +1,8 @@ +.eggs/ +build/ +dist/ +*.egg-info/ +app/*.pyc +tests/*.pyc +tests/__pycache__/ +.idea diff --git a/src/sonic-bgpcfgd/app/__init__.py b/src/sonic-bgpcfgd/app/__init__.py new file mode 100644 index 000000000000..e69de29bb2d1 diff --git a/src/sonic-bgpcfgd/app/config.py b/src/sonic-bgpcfgd/app/config.py new file mode 100644 index 000000000000..26639fe75e89 --- /dev/null +++ b/src/sonic-bgpcfgd/app/config.py @@ -0,0 +1,103 @@ +import os +import tempfile + +from .vars import g_debug +from .log import log_crit, log_err +from .util import run_command + + +class ConfigMgr(object): + """ The class represents frr configuration """ + def __init__(self): + self.current_config = None + + def reset(self): + """ Reset stored config """ + self.current_config = None + + def update(self): + """ Read current config from FRR """ + self.current_config = None + ret_code, out, err = run_command(["vtysh", "-c", "show running-config"]) + if ret_code != 0: + log_crit("can't update running config: rc=%d out='%s' err='%s'" % (ret_code, out, err)) + return + self.current_config = self.to_canonical(out) + + def push(self, cmd): + """ + Push new changes to FRR + :param cmd: configuration change for FRR. Type: String + :return: True if change was applied successfully, False otherwise + """ + return self.write(cmd) + + def write(self, cmd): + """ + Write configuration change to FRR. + :param cmd: new configuration to write into FRR. Type: String + :return: True if change was applied successfully, False otherwise + """ + fd, tmp_filename = tempfile.mkstemp(dir='/tmp') + os.close(fd) + with open(tmp_filename, 'w') as fp: + fp.write("%s\n" % cmd) + command = ["vtysh", "-f", tmp_filename] + ret_code, out, err = run_command(command) + if not g_debug: + os.remove(tmp_filename) + if ret_code != 0: + err_tuple = str(cmd), ret_code, out, err + log_err("ConfigMgr::push(): can't push configuration '%s', rc='%d', stdout='%s', stderr='%s'" % err_tuple) + if ret_code == 0: + self.current_config = None # invalidate config + return ret_code == 0 + + @staticmethod + def to_canonical(raw_config): + """ + Convert FRR config into canonical format + :param raw_config: config in frr format + :return: frr config in canonical format + """ + parsed_config = [] + lines_with_comments = raw_config.split("\n") + lines = [line for line in lines_with_comments + if not line.strip().startswith('!') and line.strip() != ''] + if len(lines) == 0: + return [] + cur_path = [lines[0]] + cur_offset = ConfigMgr.count_spaces(lines[0]) + for line in lines: + n_spaces = ConfigMgr.count_spaces(line) + s_line = line.strip() +# assert(n_spaces == cur_offset or (n_spaces + 1) == cur_offset or (n_spaces - 1) == cur_offset) + if n_spaces == cur_offset: + cur_path[-1] = s_line + elif n_spaces > cur_offset: + cur_path.append(s_line) + elif n_spaces < cur_offset: + cur_path = cur_path[:-2] + cur_path.append(s_line) + parsed_config.append(cur_path[:]) + cur_offset = n_spaces + return parsed_config + + @staticmethod + def count_spaces(line): + """ Count leading spaces in the line """ + return len(line) - len(line.lstrip()) + + @staticmethod + def from_canonical(canonical_config): + """ + Convert config from canonical format into FRR raw format + :param canonical_config: config in a canonical format + :return: config in the FRR raw format + """ + out = "" + for lines in canonical_config: + spaces = len(lines) - 1 + out += " " * spaces + lines[-1] + "\n" + + return out \ No newline at end of file diff --git a/src/sonic-bgpcfgd/app/log.py b/src/sonic-bgpcfgd/app/log.py new file mode 100644 index 000000000000..4083b13aa6ad --- /dev/null +++ b/src/sonic-bgpcfgd/app/log.py @@ -0,0 +1,33 @@ +import syslog + +from .vars import g_debug + +def log_debug(msg): + """ Send a message msg to the syslog as DEBUG """ + if g_debug: + syslog.syslog(syslog.LOG_DEBUG, msg) + + +def log_notice(msg): + """ Send a message msg to the syslog as NOTICE """ + syslog.syslog(syslog.LOG_NOTICE, msg) + + +def log_info(msg): + """ Send a message msg to the syslog as INFO """ + syslog.syslog(syslog.LOG_INFO, msg) + + +def log_warn(msg): + """ Send a message msg to the syslog as WARNING """ + syslog.syslog(syslog.LOG_WARNING, msg) + + +def log_err(msg): + """ Send a message msg to the syslog as ERR """ + syslog.syslog(syslog.LOG_ERR, msg) + + +def log_crit(msg): + """ Send a message msg to the syslog as CRIT """ + syslog.syslog(syslog.LOG_CRIT, msg) \ No newline at end of file diff --git a/src/sonic-bgpcfgd/app/template.py b/src/sonic-bgpcfgd/app/template.py new file mode 100644 index 000000000000..a9251545a33a --- /dev/null +++ b/src/sonic-bgpcfgd/app/template.py @@ -0,0 +1,108 @@ +from collections import OrderedDict +from functools import partial + +import jinja2 +import netaddr + +from .log import log_err + +class TemplateFabric(object): + """ Fabric for rendering jinja2 templates """ + def __init__(self, template_path = '/usr/share/sonic/templates'): + j2_template_paths = [template_path] + j2_loader = jinja2.FileSystemLoader(j2_template_paths) + j2_env = jinja2.Environment(loader=j2_loader, trim_blocks=False) + j2_env.filters['ipv4'] = self.is_ipv4 + j2_env.filters['ipv6'] = self.is_ipv6 + j2_env.filters['pfx_filter'] = self.pfx_filter + for attr in ['ip', 'network', 'prefixlen', 'netmask']: + j2_env.filters[attr] = partial(self.prefix_attr, attr) + self.env = j2_env + + def from_file(self, filename): + """ + Read a template from a file + :param filename: filename of the file. Type String + :return: Jinja2 template object + """ + return self.env.get_template(filename) + + def from_string(self, tmpl): + """ + Read a template from a string + :param tmpl: Text representation of Jinja2 template + :return: Jinja2 template object + """ + return self.env.from_string(tmpl) + + @staticmethod + def is_ipv4(value): + """ Return True if the value is an ipv4 address """ + if not value: + return False + if isinstance(value, netaddr.IPNetwork): + addr = value + else: + try: + addr = netaddr.IPNetwork(str(value)) + except (netaddr.NotRegisteredError, netaddr.AddrFormatError, netaddr.AddrConversionError): + return False + return addr.version == 4 + + @staticmethod + def is_ipv6(value): + """ Return True if the value is an ipv6 address """ + if not value: + return False + if isinstance(value, netaddr.IPNetwork): + addr = value + else: + try: + addr = netaddr.IPNetwork(str(value)) + except (netaddr.NotRegisteredError, netaddr.AddrFormatError, netaddr.AddrConversionError): + return False + return addr.version == 6 + + @staticmethod + def prefix_attr(attr, value): + """ + Extract attribute from IPNetwork object + :param attr: attribute to extract + :param value: the string representation of ip prefix which will be converted to IPNetwork. + :return: the value of the extracted attribute + """ + if not value: + return None + else: + try: + prefix = netaddr.IPNetwork(str(value)) + except (netaddr.NotRegisteredError, netaddr.AddrFormatError, netaddr.AddrConversionError): + return None + return str(getattr(prefix, attr)) + + @staticmethod + def pfx_filter(value): + """INTERFACE Table can have keys in one of the two formats: + string or tuple - This filter skips the string keys and only + take into account the tuple. + For eg - VLAN_INTERFACE|Vlan1000 vs VLAN_INTERFACE|Vlan1000|192.168.0.1/21 + """ + table = OrderedDict() + + if not value: + return table + + for key, val in value.items(): + if not isinstance(key, tuple): + continue + intf, ip_address = key + if '/' not in ip_address: + if TemplateFabric.is_ipv4(ip_address): + table[(intf, "%s/32" % ip_address)] = val + elif TemplateFabric.is_ipv6(ip_address): + table[(intf, "%s/128" % ip_address)] = val + else: + log_err("'%s' is invalid ip address" % ip_address) + else: + table[key] = val + return table diff --git a/src/sonic-bgpcfgd/app/util.py b/src/sonic-bgpcfgd/app/util.py new file mode 100644 index 000000000000..b25e651f1ec6 --- /dev/null +++ b/src/sonic-bgpcfgd/app/util.py @@ -0,0 +1,22 @@ +import subprocess + +from .log import log_debug, log_err + + +def run_command(command, shell=False, hide_errors=False): + """ + Run a linux command. The command is defined as a list. See subprocess.Popen documentation on format + :param command: command to execute. Type: List of strings + :param shell: execute the command through shell when True. Type: Boolean + :param hide_errors: don't report errors to syslog when True. Type: Boolean + :return: Tuple: integer exit code from the command, stdout as a string, stderr as a string + """ + log_debug("execute command '%s'." % str(command)) + p = subprocess.Popen(command, shell=shell, stdout=subprocess.PIPE, stderr=subprocess.PIPE) + stdout, stderr = p.communicate() + if p.returncode != 0: + if not hide_errors: + print_tuple = p.returncode, str(command), stdout, stderr + log_err("command execution returned %d. Command: '%s', stdout: '%s', stderr: '%s'" % print_tuple) + + return p.returncode, stdout, stderr \ No newline at end of file diff --git a/src/sonic-bgpcfgd/app/vars.py b/src/sonic-bgpcfgd/app/vars.py new file mode 100644 index 000000000000..11377fc87f93 --- /dev/null +++ b/src/sonic-bgpcfgd/app/vars.py @@ -0,0 +1 @@ +g_debug = False diff --git a/dockers/docker-fpm-frr/bgpcfgd b/src/sonic-bgpcfgd/bgpcfgd similarity index 80% rename from dockers/docker-fpm-frr/bgpcfgd rename to src/sonic-bgpcfgd/bgpcfgd index adc142c109d2..0fbe44602a22 100755 --- a/dockers/docker-fpm-frr/bgpcfgd +++ b/src/sonic-bgpcfgd/bgpcfgd @@ -1,260 +1,27 @@ #!/usr/bin/env python import sys -import subprocess import datetime import time import syslog import signal import traceback import os -import tempfile import json -from collections import defaultdict, OrderedDict -from pprint import pprint -from functools import partial +from collections import defaultdict import yaml import jinja2 import netaddr from swsscommon import swsscommon +from app.vars import g_debug +from app.log import log_debug, log_notice, log_info, log_warn, log_err, log_crit +from app.template import TemplateFabric +from app.config import ConfigMgr +from app.util import run_command g_run = True -g_debug = False - - -def log_debug(msg): - """ Send a message msg to the syslog as DEBUG """ - if g_debug: - syslog.syslog(syslog.LOG_DEBUG, msg) - -def log_notice(msg): - """ Send a message msg to the syslog as NOTICE """ - syslog.syslog(syslog.LOG_NOTICE, msg) - -def log_info(msg): - """ Send a message msg to the syslog as INFO """ - syslog.syslog(syslog.LOG_INFO, msg) - -def log_warn(msg): - """ Send a message msg to the syslog as WARNING """ - syslog.syslog(syslog.LOG_WARNING, msg) - -def log_err(msg): - """ Send a message msg to the syslog as ERR """ - syslog.syslog(syslog.LOG_ERR, msg) - -def log_crit(msg): - """ Send a message msg to the syslog as CRIT """ - syslog.syslog(syslog.LOG_CRIT, msg) - - -def run_command(command, shell=False, hide_errors=False): - """ - Run a linux command. The command is defined as a list. See subprocess.Popen documentation on format - :param command: command to execute. Type: List of strings - :param shell: execute the command through shell when True. Type: Boolean - :param hide_errors: don't report errors to syslog when True. Type: Boolean - :return: Tuple: integer exit code from the command, stdout as a string, stderr as a string - """ - log_debug("execute command '%s'." % str(command)) - p = subprocess.Popen(command, shell=shell, stdout=subprocess.PIPE, stderr=subprocess.PIPE) - stdout, stderr = p.communicate() - if p.returncode != 0: - if not hide_errors: - print_tuple = p.returncode, str(command), stdout, stderr - log_err("command execution returned %d. Command: '%s', stdout: '%s', stderr: '%s'" % print_tuple) - - return p.returncode, stdout, stderr - - -class ConfigMgr(object): - """ The class represents frr configuration """ - def __init__(self): - self.current_config = None - - def reset(self): - """ Reset stored config """ - self.current_config = None - - def update(self): - """ Read current config from FRR """ - self.current_config = None - ret_code, out, err = run_command(["vtysh", "-c", "show running-config"]) - if ret_code != 0: - log_crit("can't update running config: rc=%d out='%s' err='%s'" % (ret_code, out, err)) - return - self.current_config = self.to_canonical(out) - - def push(self, cmd): - """ - Push new changes to FRR - :param cmd: configuration change for FRR. Type: String - :return: True if change was applied successfully, False otherwise - """ - return self.write(cmd) - - def write(self, cmd): - """ - Write configuration change to FRR. - :param cmd: new configuration to write into FRR. Type: String - :return: True if change was applied successfully, False otherwise - """ - fd, tmp_filename = tempfile.mkstemp(dir='/tmp') - os.close(fd) - with open(tmp_filename, 'w') as fp: - fp.write("%s\n" % cmd) - command = ["vtysh", "-f", tmp_filename] - ret_code, out, err = run_command(command) - if not g_debug: - os.remove(tmp_filename) - if ret_code != 0: - err_tuple = str(cmd), ret_code, out, err - log_err("ConfigMgr::push(): can't push configuration '%s', rc='%d', stdout='%s', stderr='%s'" % err_tuple) - if ret_code == 0: - self.current_config = None # invalidate config - return ret_code == 0 - - @staticmethod - def to_canonical(raw_config): - """ - Convert FRR config into canonical format - :param raw_config: config in frr format - :return: frr config in canonical format - """ - parsed_config = [] - cur_offset = 0 - lines = raw_config.split("\n") - cur_path = [lines[0]] - for line in lines: - if line.strip().startswith('!') or line.strip() == '': - continue - n_spaces = ConfigMgr.count_spaces(line) - s_line = line.strip() - assert(n_spaces == cur_offset or (n_spaces + 1) == cur_offset or (n_spaces - 1) == cur_offset) - if n_spaces == cur_offset: - cur_path[-1] = s_line - elif n_spaces > cur_offset: - cur_path.append(s_line) - elif n_spaces < cur_offset: - cur_path = cur_path[:-2] - cur_path.append(s_line) - parsed_config.append(cur_path[:]) - cur_offset = n_spaces - return parsed_config - - @staticmethod - def count_spaces(line): - """ Count leading spaces in the line """ - return len(line) - len(line.lstrip()) - - @staticmethod - def from_canonical(canonical_config): - """ - Convert config from canonical format into FRR raw format - :param canonical_config: config in a canonical format - :return: config in the FRR raw format - """ - out = "" - for lines in canonical_config: - spaces = len(lines) - 1 - out += " " * spaces + lines[-1] + "\n" - - return out - - -class TemplateFabric(object): - """ Fabric for rendering jinja2 templates """ - def __init__(self): - j2_template_paths = ['/usr/share/sonic/templates'] - j2_loader = jinja2.FileSystemLoader(j2_template_paths) - j2_env = jinja2.Environment(loader=j2_loader, trim_blocks=False) - j2_env.filters['ipv4'] = self.is_ipv4 - j2_env.filters['ipv6'] = self.is_ipv6 - j2_env.filters['pfx_filter'] = self.pfx_filter - for attr in ['ip', 'network', 'prefixlen', 'netmask']: - j2_env.filters[attr] = partial(self.prefix_attr, attr) - self.env = j2_env - - def from_file(self, filename): - """ - Read a template from a file - :param filename: filename of the file. Type String - :return: Jinja2 template object - """ - return self.env.get_template(filename) - - def from_string(self, tmpl): - """ - Read a template from a string - :param tmpl: Text representation of Jinja2 template - :return: Jinja2 template object - """ - return self.env.from_string(tmpl) - - @staticmethod - def is_ipv4(value): - """ Return True if the value is an ipv4 address """ - if not value: - return False - if isinstance(value, netaddr.IPNetwork): - addr = value - else: - try: - addr = netaddr.IPNetwork(str(value)) - except (netaddr.NotRegisteredError, netaddr.AddrFormatError, netaddr.AddrConversionError): - return False - return addr.version == 4 - - @staticmethod - def is_ipv6(value): - """ Return True if the value is an ipv6 address """ - if not value: - return False - if isinstance(value, netaddr.IPNetwork): - addr = value - else: - try: - addr = netaddr.IPNetwork(str(value)) - except (netaddr.NotRegisteredError, netaddr.AddrFormatError, netaddr.AddrConversionError): - return False - return addr.version == 6 - - @staticmethod - def prefix_attr(attr, value): - """ - Extract attribute from IPNetwork object - :param attr: attribute to extract - :param value: the string representation of ip prefix which will be converted to IPNetwork. - :return: the value of the extracted attribute - """ - if not value: - return None - else: - try: - prefix = netaddr.IPNetwork(str(value)) - except (netaddr.NotRegisteredError, netaddr.AddrFormatError, netaddr.AddrConversionError): - return None - return str(getattr(prefix, attr)) - - @staticmethod - def pfx_filter(value): - """INTERFACE Table can have keys in one of the two formats: - string or tuple - This filter skips the string keys and only - take into account the tuple. - For eg - VLAN_INTERFACE|Vlan1000 vs VLAN_INTERFACE|Vlan1000|192.168.0.1/21 - """ - table = OrderedDict() - - if not value: - return table - - for key, val in value.items(): - if not isinstance(key, tuple): - continue - table[key] = val - return table class Directory(object): diff --git a/src/sonic-bgpcfgd/setup.cfg b/src/sonic-bgpcfgd/setup.cfg new file mode 100644 index 000000000000..00ed5efbcbad --- /dev/null +++ b/src/sonic-bgpcfgd/setup.cfg @@ -0,0 +1,5 @@ +[aliases] +test=pytest +[tool:pytest] +addopts = --verbose +python_files = tests/*.py diff --git a/src/sonic-bgpcfgd/setup.py b/src/sonic-bgpcfgd/setup.py new file mode 100755 index 000000000000..fae1c313850e --- /dev/null +++ b/src/sonic-bgpcfgd/setup.py @@ -0,0 +1,15 @@ +#!/usr/bin/env python + +import setuptools + +setuptools.setup(name='sonic-bgpcfgd', + version='1.0', + description='Utility to dynamically generate BGP configuration for FRR', + author='Pavel Shirshov', + author_email='pavelsh@microsoft.com', + url='https://github.com/Azure/sonic-buildimage', + packages=setuptools.find_packages(), + scripts=['bgpcfgd'], + install_requires=['jinja2>=2.10', 'netaddr', 'pyyaml'], + setup_requires=['pytest-runner', 'pytest'], +) diff --git a/src/sonic-bgpcfgd/tests/__init__.py b/src/sonic-bgpcfgd/tests/__init__.py new file mode 100644 index 000000000000..e69de29bb2d1 diff --git a/src/sonic-bgpcfgd/tests/data/dynamic/instance.conf/param_all.json b/src/sonic-bgpcfgd/tests/data/dynamic/instance.conf/param_all.json new file mode 100644 index 000000000000..c4134ff29806 --- /dev/null +++ b/src/sonic-bgpcfgd/tests/data/dynamic/instance.conf/param_all.json @@ -0,0 +1,21 @@ +{ + "CONFIG_DB__DEVICE_METADATA": { + "localhost": { + "deployment_id": "5" + } + }, + "CONFIG_DB__LOOPBACK_INTERFACE": { + "Loopback1|55.55.55.55/32": {} + }, + "bgp_session": { + "ip_range": "10.10.20.0/24,20.20.20.0/24", + "name": "dyn_name", + "peer_asn": "11111", + "src_address": "1.1.1.1" + }, + "constants": { + "deployment_id_asn_map": { + "5": "51111" + } + } +} diff --git a/src/sonic-bgpcfgd/tests/data/dynamic/instance.conf/param_base.json b/src/sonic-bgpcfgd/tests/data/dynamic/instance.conf/param_base.json new file mode 100644 index 000000000000..04fd24fa0819 --- /dev/null +++ b/src/sonic-bgpcfgd/tests/data/dynamic/instance.conf/param_base.json @@ -0,0 +1,19 @@ +{ + "CONFIG_DB__DEVICE_METADATA": { + "localhost": { + "deployment_id": "5" + } + }, + "CONFIG_DB__LOOPBACK_INTERFACE": { + "Loopback1|55.55.55.55/32": {} + }, + "bgp_session": { + "ip_range": "10.10.20.0/24,20.20.20.0/24", + "name": "dyn_name" + }, + "constants": { + "deployment_id_asn_map": { + "5": "51111" + } + } +} diff --git a/src/sonic-bgpcfgd/tests/data/dynamic/instance.conf/result_all.conf b/src/sonic-bgpcfgd/tests/data/dynamic/instance.conf/result_all.conf new file mode 100644 index 000000000000..1ffc3d34343e --- /dev/null +++ b/src/sonic-bgpcfgd/tests/data/dynamic/instance.conf/result_all.conf @@ -0,0 +1,22 @@ +! +! template: bgpd/templates/dynamic/instance.conf.j2 +! + neighbor dyn_name peer-group + neighbor dyn_name passive + neighbor dyn_name ebgp-multihop 255 + neighbor dyn_name soft-reconfiguration inbound + neighbor dyn_name route-map FROM_BGP_SPEAKER in + neighbor dyn_name route-map TO_BGP_SPEAKER out + neighbor dyn_name remote-as 11111 + bgp listen range 10.10.20.0/24 peer-group dyn_name + bgp listen range 20.20.20.0/24 peer-group dyn_name + neighbor dyn_name update-source 1.1.1.1 + address-family ipv4 + neighbor dyn_name activate + exit-address-family + address-family ipv6 + neighbor dyn_name activate + exit-address-family +! +! end of template: bgpd/templates/dynamic/instance.conf.j2 +! diff --git a/src/sonic-bgpcfgd/tests/data/dynamic/instance.conf/result_base.conf b/src/sonic-bgpcfgd/tests/data/dynamic/instance.conf/result_base.conf new file mode 100644 index 000000000000..ac2a4f3e18d7 --- /dev/null +++ b/src/sonic-bgpcfgd/tests/data/dynamic/instance.conf/result_base.conf @@ -0,0 +1,22 @@ +! +! template: bgpd/templates/dynamic/instance.conf.j2 +! + neighbor dyn_name peer-group + neighbor dyn_name passive + neighbor dyn_name ebgp-multihop 255 + neighbor dyn_name soft-reconfiguration inbound + neighbor dyn_name route-map FROM_BGP_SPEAKER in + neighbor dyn_name route-map TO_BGP_SPEAKER out + neighbor dyn_name remote-as 51111 + bgp listen range 10.10.20.0/24 peer-group dyn_name + bgp listen range 20.20.20.0/24 peer-group dyn_name + neighbor dyn_name update-source 55.55.55.55 + address-family ipv4 + neighbor dyn_name activate + exit-address-family + address-family ipv6 + neighbor dyn_name activate + exit-address-family +! +! end of template: bgpd/templates/dynamic/instance.conf.j2 +! diff --git a/src/sonic-bgpcfgd/tests/data/dynamic/peer-group.conf/param_all.json b/src/sonic-bgpcfgd/tests/data/dynamic/peer-group.conf/param_all.json new file mode 100644 index 000000000000..0967ef424bce --- /dev/null +++ b/src/sonic-bgpcfgd/tests/data/dynamic/peer-group.conf/param_all.json @@ -0,0 +1 @@ +{} diff --git a/src/sonic-bgpcfgd/tests/data/dynamic/peer-group.conf/result_all.conf b/src/sonic-bgpcfgd/tests/data/dynamic/peer-group.conf/result_all.conf new file mode 100644 index 000000000000..86d5c0297227 --- /dev/null +++ b/src/sonic-bgpcfgd/tests/data/dynamic/peer-group.conf/result_all.conf @@ -0,0 +1,7 @@ +! +! template: bgpd/templates/BGP_SPEAKER/peer-group.conf.j2 +! +! nothing is here +! +! end of template: bgpd/templates/BGP_SPEAKER/peer-group.conf.j2 +! diff --git a/src/sonic-bgpcfgd/tests/data/dynamic/policies.conf/param_all.json b/src/sonic-bgpcfgd/tests/data/dynamic/policies.conf/param_all.json new file mode 100644 index 000000000000..0967ef424bce --- /dev/null +++ b/src/sonic-bgpcfgd/tests/data/dynamic/policies.conf/param_all.json @@ -0,0 +1 @@ +{} diff --git a/src/sonic-bgpcfgd/tests/data/dynamic/policies.conf/result_all.conf b/src/sonic-bgpcfgd/tests/data/dynamic/policies.conf/result_all.conf new file mode 100644 index 000000000000..17ca09ec2a36 --- /dev/null +++ b/src/sonic-bgpcfgd/tests/data/dynamic/policies.conf/result_all.conf @@ -0,0 +1,9 @@ +! +! template: bgpd/templates/BGP_SPEAKER/policies.conf.j2 +! +route-map FROM_BGP_SPEAKER permit 10 +! +route-map TO_BGP_SPEAKER deny 1 +! +! end of template: bgpd/templates/BGP_SPEAKER/policies.conf.j2 +! diff --git a/src/sonic-bgpcfgd/tests/data/general/instance.conf/param_ASIC_v4.json b/src/sonic-bgpcfgd/tests/data/general/instance.conf/param_ASIC_v4.json new file mode 100644 index 000000000000..1691732b39b4 --- /dev/null +++ b/src/sonic-bgpcfgd/tests/data/general/instance.conf/param_ASIC_v4.json @@ -0,0 +1,15 @@ +{ + "CONFIG_DB__DEVICE_METADATA": { + "localhost": {} + }, + "neighbor_addr": "10.10.10.10", + "bgp_session": { + "asn": "555", + "name": "_ASIC_" + }, + "constants": { + "deployment_id_asn_map": { + "5": "51111" + } + } +} diff --git a/src/sonic-bgpcfgd/tests/data/general/instance.conf/param_ASIC_v6.json b/src/sonic-bgpcfgd/tests/data/general/instance.conf/param_ASIC_v6.json new file mode 100644 index 000000000000..89a4117fdac2 --- /dev/null +++ b/src/sonic-bgpcfgd/tests/data/general/instance.conf/param_ASIC_v6.json @@ -0,0 +1,15 @@ +{ + "CONFIG_DB__DEVICE_METADATA": { + "localhost": {} + }, + "neighbor_addr": "FC00::", + "bgp_session": { + "asn": "555", + "name": "_ASIC_" + }, + "constants": { + "deployment_id_asn_map": { + "5": "51111" + } + } +} diff --git a/src/sonic-bgpcfgd/tests/data/general/instance.conf/param_all_v4.json b/src/sonic-bgpcfgd/tests/data/general/instance.conf/param_all_v4.json new file mode 100644 index 000000000000..c2391674a56e --- /dev/null +++ b/src/sonic-bgpcfgd/tests/data/general/instance.conf/param_all_v4.json @@ -0,0 +1,23 @@ +{ + "CONFIG_DB__DEVICE_METADATA": { + "localhost": { + "sub_role": "BackEnd" + } + }, + "neighbor_addr": "10.10.10.10", + "bgp_session": { + "asn": "555", + "name": "remote_peer", + "keepalive": "5", + "holdtime": "30", + "admin_status": "down", + "ASIC": "something", + "rrclient": "1", + "nhopself": "1" + }, + "constants": { + "deployment_id_asn_map": { + "5": "51111" + } + } +} diff --git a/src/sonic-bgpcfgd/tests/data/general/instance.conf/param_all_v6.json b/src/sonic-bgpcfgd/tests/data/general/instance.conf/param_all_v6.json new file mode 100644 index 000000000000..d19139a75a88 --- /dev/null +++ b/src/sonic-bgpcfgd/tests/data/general/instance.conf/param_all_v6.json @@ -0,0 +1,23 @@ +{ + "CONFIG_DB__DEVICE_METADATA": { + "localhost": { + "sub_role": "BackEnd" + } + }, + "neighbor_addr": "fc::10", + "bgp_session": { + "asn": "555", + "name": "remote_peer", + "keepalive": "5", + "holdtime": "30", + "admin_status": "down", + "ASIC": "something", + "rrclient": "1", + "nhopself": "1" + }, + "constants": { + "deployment_id_asn_map": { + "5": "51111" + } + } +} diff --git a/src/sonic-bgpcfgd/tests/data/general/instance.conf/param_base_v4.json b/src/sonic-bgpcfgd/tests/data/general/instance.conf/param_base_v4.json new file mode 100644 index 000000000000..e2e59575cbb3 --- /dev/null +++ b/src/sonic-bgpcfgd/tests/data/general/instance.conf/param_base_v4.json @@ -0,0 +1,15 @@ +{ + "CONFIG_DB__DEVICE_METADATA": { + "localhost": {} + }, + "neighbor_addr": "10.10.10.10", + "bgp_session": { + "asn": "555", + "name": "remote_peer" + }, + "constants": { + "deployment_id_asn_map": { + "5": "51111" + } + } +} diff --git a/src/sonic-bgpcfgd/tests/data/general/instance.conf/param_base_v6.json b/src/sonic-bgpcfgd/tests/data/general/instance.conf/param_base_v6.json new file mode 100644 index 000000000000..5e79378e3e00 --- /dev/null +++ b/src/sonic-bgpcfgd/tests/data/general/instance.conf/param_base_v6.json @@ -0,0 +1,15 @@ +{ + "CONFIG_DB__DEVICE_METADATA": { + "localhost": {} + }, + "neighbor_addr": "fc00::2", + "bgp_session": { + "asn": "555", + "name": "remote_peer" + }, + "constants": { + "deployment_id_asn_map": { + "5": "51111" + } + } +} diff --git a/src/sonic-bgpcfgd/tests/data/general/instance.conf/param_l2vpn.json b/src/sonic-bgpcfgd/tests/data/general/instance.conf/param_l2vpn.json new file mode 100644 index 000000000000..e679bff08435 --- /dev/null +++ b/src/sonic-bgpcfgd/tests/data/general/instance.conf/param_l2vpn.json @@ -0,0 +1,18 @@ +{ + "CONFIG_DB__DEVICE_METADATA": { + "localhost": { + "type": "SpineChassisFrontendRouter" + } + }, + "neighbor_addr": "10.10.10.10", + "bgp_session": { + "asn": "555", + "name": "remote_peer" + }, + "constants": { + "deployment_id_asn_map": { + "5": "51111" + } + }, + "bgp_asn": "555" +} diff --git a/src/sonic-bgpcfgd/tests/data/general/instance.conf/param_shutdown_1.json b/src/sonic-bgpcfgd/tests/data/general/instance.conf/param_shutdown_1.json new file mode 100644 index 000000000000..b7c1e2075f02 --- /dev/null +++ b/src/sonic-bgpcfgd/tests/data/general/instance.conf/param_shutdown_1.json @@ -0,0 +1,17 @@ +{ + "CONFIG_DB__DEVICE_METADATA": { + "localhost": { + "default_bgp_status": "down" + } + }, + "neighbor_addr": "10.10.10.10", + "bgp_session": { + "asn": "555", + "name": "remote_peer" + }, + "constants": { + "deployment_id_asn_map": { + "5": "51111" + } + } +} diff --git a/src/sonic-bgpcfgd/tests/data/general/instance.conf/param_shutdown_2.json b/src/sonic-bgpcfgd/tests/data/general/instance.conf/param_shutdown_2.json new file mode 100644 index 000000000000..610254a2b2ba --- /dev/null +++ b/src/sonic-bgpcfgd/tests/data/general/instance.conf/param_shutdown_2.json @@ -0,0 +1,17 @@ +{ + "CONFIG_DB__DEVICE_METADATA": { + "localhost": { + "default_bgp_status": "up" + } + }, + "neighbor_addr": "10.10.10.10", + "bgp_session": { + "asn": "555", + "name": "remote_peer" + }, + "constants": { + "deployment_id_asn_map": { + "5": "51111" + } + } +} diff --git a/src/sonic-bgpcfgd/tests/data/general/instance.conf/param_timers_1.json b/src/sonic-bgpcfgd/tests/data/general/instance.conf/param_timers_1.json new file mode 100644 index 000000000000..88d2b6defb2a --- /dev/null +++ b/src/sonic-bgpcfgd/tests/data/general/instance.conf/param_timers_1.json @@ -0,0 +1,16 @@ +{ + "CONFIG_DB__DEVICE_METADATA": { + "localhost": {} + }, + "neighbor_addr": "10.10.10.10", + "bgp_session": { + "asn": "555", + "name": "remote_peer", + "keepalive": "5" + }, + "constants": { + "deployment_id_asn_map": { + "5": "51111" + } + } +} diff --git a/src/sonic-bgpcfgd/tests/data/general/instance.conf/param_timers_2.json b/src/sonic-bgpcfgd/tests/data/general/instance.conf/param_timers_2.json new file mode 100644 index 000000000000..4b5c2bec220b --- /dev/null +++ b/src/sonic-bgpcfgd/tests/data/general/instance.conf/param_timers_2.json @@ -0,0 +1,16 @@ +{ + "CONFIG_DB__DEVICE_METADATA": { + "localhost": {} + }, + "neighbor_addr": "10.10.10.10", + "bgp_session": { + "asn": "555", + "name": "remote_peer", + "holdtime": "240" + }, + "constants": { + "deployment_id_asn_map": { + "5": "51111" + } + } +} diff --git a/src/sonic-bgpcfgd/tests/data/general/instance.conf/result_ASIC_v4.conf b/src/sonic-bgpcfgd/tests/data/general/instance.conf/result_ASIC_v4.conf new file mode 100644 index 000000000000..1e89f822457a --- /dev/null +++ b/src/sonic-bgpcfgd/tests/data/general/instance.conf/result_ASIC_v4.conf @@ -0,0 +1,13 @@ +! +! template: bgpd/templates/general/instance.conf.j2 +! + neighbor 10.10.10.10 remote-as 555 + neighbor 10.10.10.10 description _ASIC_ + address-family ipv4 + neighbor 10.10.10.10 peer-group PEER_V4_INT + neighbor 10.10.10.10 next-hop-self force + neighbor 10.10.10.10 activate + exit-address-family +! +! end of template: bgpd/templates/general/instance.conf.j2 +! diff --git a/src/sonic-bgpcfgd/tests/data/general/instance.conf/result_ASIC_v6.conf b/src/sonic-bgpcfgd/tests/data/general/instance.conf/result_ASIC_v6.conf new file mode 100644 index 000000000000..64d14dcd4fa5 --- /dev/null +++ b/src/sonic-bgpcfgd/tests/data/general/instance.conf/result_ASIC_v6.conf @@ -0,0 +1,13 @@ +! +! template: bgpd/templates/general/instance.conf.j2 +! + neighbor FC00:: remote-as 555 + neighbor FC00:: description _ASIC_ + address-family ipv6 + neighbor FC00:: peer-group PEER_V6_INT + neighbor FC00:: next-hop-self force + neighbor FC00:: activate + exit-address-family +! +! end of template: bgpd/templates/general/instance.conf.j2 +! diff --git a/src/sonic-bgpcfgd/tests/data/general/instance.conf/result_all_v4.conf b/src/sonic-bgpcfgd/tests/data/general/instance.conf/result_all_v4.conf new file mode 100644 index 000000000000..2241bbf34146 --- /dev/null +++ b/src/sonic-bgpcfgd/tests/data/general/instance.conf/result_all_v4.conf @@ -0,0 +1,17 @@ +! +! template: bgpd/templates/general/instance.conf.j2 +! + neighbor 10.10.10.10 remote-as 555 + neighbor 10.10.10.10 description remote_peer + neighbor 10.10.10.10 timers 5 30 + neighbor 10.10.10.10 shutdown + address-family ipv4 + neighbor 10.10.10.10 peer-group PEER_V4 + neighbor 10.10.10.10 route-map FROM_BGP_PEER_V4_INT in + neighbor 10.10.10.10 route-reflector-client + neighbor 10.10.10.10 next-hop-self + neighbor 10.10.10.10 activate + exit-address-family +! +! end of template: bgpd/templates/general/instance.conf.j2 +! diff --git a/src/sonic-bgpcfgd/tests/data/general/instance.conf/result_all_v6.conf b/src/sonic-bgpcfgd/tests/data/general/instance.conf/result_all_v6.conf new file mode 100644 index 000000000000..7194b0916620 --- /dev/null +++ b/src/sonic-bgpcfgd/tests/data/general/instance.conf/result_all_v6.conf @@ -0,0 +1,17 @@ +! +! template: bgpd/templates/general/instance.conf.j2 +! + neighbor fc::10 remote-as 555 + neighbor fc::10 description remote_peer + neighbor fc::10 timers 5 30 + neighbor fc::10 shutdown + address-family ipv6 + neighbor fc::10 peer-group PEER_V6 + neighbor fc::10 route-map FROM_BGP_PEER_V6_INT in + neighbor fc::10 route-reflector-client + neighbor fc::10 next-hop-self + neighbor fc::10 activate + exit-address-family +! +! end of template: bgpd/templates/general/instance.conf.j2 +! diff --git a/src/sonic-bgpcfgd/tests/data/general/instance.conf/result_base_v4.conf b/src/sonic-bgpcfgd/tests/data/general/instance.conf/result_base_v4.conf new file mode 100644 index 000000000000..2990d5aef7c7 --- /dev/null +++ b/src/sonic-bgpcfgd/tests/data/general/instance.conf/result_base_v4.conf @@ -0,0 +1,12 @@ +! +! template: bgpd/templates/general/instance.conf.j2 +! + neighbor 10.10.10.10 remote-as 555 + neighbor 10.10.10.10 description remote_peer + address-family ipv4 + neighbor 10.10.10.10 peer-group PEER_V4 + neighbor 10.10.10.10 activate + exit-address-family +! +! end of template: bgpd/templates/general/instance.conf.j2 +! diff --git a/src/sonic-bgpcfgd/tests/data/general/instance.conf/result_base_v6.conf b/src/sonic-bgpcfgd/tests/data/general/instance.conf/result_base_v6.conf new file mode 100644 index 000000000000..38ec714894ae --- /dev/null +++ b/src/sonic-bgpcfgd/tests/data/general/instance.conf/result_base_v6.conf @@ -0,0 +1,12 @@ +! +! template: bgpd/templates/general/instance.conf.j2 +! + neighbor fc00::2 remote-as 555 + neighbor fc00::2 description remote_peer + address-family ipv6 + neighbor fc00::2 peer-group PEER_V6 + neighbor fc00::2 activate + exit-address-family +! +! end of template: bgpd/templates/general/instance.conf.j2 +! diff --git a/src/sonic-bgpcfgd/tests/data/general/instance.conf/result_l2vpn.conf b/src/sonic-bgpcfgd/tests/data/general/instance.conf/result_l2vpn.conf new file mode 100644 index 000000000000..b30eaaa62a35 --- /dev/null +++ b/src/sonic-bgpcfgd/tests/data/general/instance.conf/result_l2vpn.conf @@ -0,0 +1,16 @@ +! +! template: bgpd/templates/general/instance.conf.j2 +! + neighbor 10.10.10.10 remote-as 555 + neighbor 10.10.10.10 description remote_peer + address-family ipv4 + neighbor 10.10.10.10 peer-group PEER_V4 + neighbor 10.10.10.10 activate + exit-address-family + address-family l2vpn evpn + neighbor 10.10.10.10 activate + advertise-all-vni + exit-address-family +! +! end of template: bgpd/templates/general/instance.conf.j2 +! diff --git a/src/sonic-bgpcfgd/tests/data/general/instance.conf/result_shutdown_1.conf b/src/sonic-bgpcfgd/tests/data/general/instance.conf/result_shutdown_1.conf new file mode 100644 index 000000000000..9303e3b9ab7f --- /dev/null +++ b/src/sonic-bgpcfgd/tests/data/general/instance.conf/result_shutdown_1.conf @@ -0,0 +1,13 @@ +! +! template: bgpd/templates/general/instance.conf.j2 +! + neighbor 10.10.10.10 remote-as 555 + neighbor 10.10.10.10 description remote_peer + neighbor 10.10.10.10 shutdown + address-family ipv4 + neighbor 10.10.10.10 peer-group PEER_V4 + neighbor 10.10.10.10 activate + exit-address-family +! +! end of template: bgpd/templates/general/instance.conf.j2 +! diff --git a/src/sonic-bgpcfgd/tests/data/general/instance.conf/result_shutdown_2.conf b/src/sonic-bgpcfgd/tests/data/general/instance.conf/result_shutdown_2.conf new file mode 100644 index 000000000000..2990d5aef7c7 --- /dev/null +++ b/src/sonic-bgpcfgd/tests/data/general/instance.conf/result_shutdown_2.conf @@ -0,0 +1,12 @@ +! +! template: bgpd/templates/general/instance.conf.j2 +! + neighbor 10.10.10.10 remote-as 555 + neighbor 10.10.10.10 description remote_peer + address-family ipv4 + neighbor 10.10.10.10 peer-group PEER_V4 + neighbor 10.10.10.10 activate + exit-address-family +! +! end of template: bgpd/templates/general/instance.conf.j2 +! diff --git a/src/sonic-bgpcfgd/tests/data/general/instance.conf/result_timers_1.conf b/src/sonic-bgpcfgd/tests/data/general/instance.conf/result_timers_1.conf new file mode 100644 index 000000000000..ffca0e6b69e6 --- /dev/null +++ b/src/sonic-bgpcfgd/tests/data/general/instance.conf/result_timers_1.conf @@ -0,0 +1,13 @@ +! +! template: bgpd/templates/general/instance.conf.j2 +! + neighbor 10.10.10.10 remote-as 555 + neighbor 10.10.10.10 description remote_peer + neighbor 10.10.10.10 timers 5 180 + address-family ipv4 + neighbor 10.10.10.10 peer-group PEER_V4 + neighbor 10.10.10.10 activate + exit-address-family +! +! end of template: bgpd/templates/general/instance.conf.j2 +! diff --git a/src/sonic-bgpcfgd/tests/data/general/instance.conf/result_timers_2.conf b/src/sonic-bgpcfgd/tests/data/general/instance.conf/result_timers_2.conf new file mode 100644 index 000000000000..3a8ac3d90e3f --- /dev/null +++ b/src/sonic-bgpcfgd/tests/data/general/instance.conf/result_timers_2.conf @@ -0,0 +1,13 @@ +! +! template: bgpd/templates/general/instance.conf.j2 +! + neighbor 10.10.10.10 remote-as 555 + neighbor 10.10.10.10 description remote_peer + neighbor 10.10.10.10 timers 60 240 + address-family ipv4 + neighbor 10.10.10.10 peer-group PEER_V4 + neighbor 10.10.10.10 activate + exit-address-family +! +! end of template: bgpd/templates/general/instance.conf.j2 +! diff --git a/src/sonic-bgpcfgd/tests/data/general/peer-group.conf/param_all.json b/src/sonic-bgpcfgd/tests/data/general/peer-group.conf/param_all.json new file mode 100644 index 000000000000..293ccc7990dc --- /dev/null +++ b/src/sonic-bgpcfgd/tests/data/general/peer-group.conf/param_all.json @@ -0,0 +1,7 @@ +{ + "CONFIG_DB__DEVICE_METADATA": { + "localhost": { + "type": "ToRRouter" + } + } +} \ No newline at end of file diff --git a/src/sonic-bgpcfgd/tests/data/general/peer-group.conf/param_base.json b/src/sonic-bgpcfgd/tests/data/general/peer-group.conf/param_base.json new file mode 100644 index 000000000000..046ffb1a6417 --- /dev/null +++ b/src/sonic-bgpcfgd/tests/data/general/peer-group.conf/param_base.json @@ -0,0 +1,8 @@ +{ + "CONFIG_DB__DEVICE_METADATA": { + "localhost": { + "type": "LeafRouter", + "sub_role": "BackEnd" + } + } +} \ No newline at end of file diff --git a/src/sonic-bgpcfgd/tests/data/general/peer-group.conf/result_all.conf b/src/sonic-bgpcfgd/tests/data/general/peer-group.conf/result_all.conf new file mode 100644 index 000000000000..63211ded8796 --- /dev/null +++ b/src/sonic-bgpcfgd/tests/data/general/peer-group.conf/result_all.conf @@ -0,0 +1,30 @@ +! +! template: bgpd/templates/general/peer-group.conf.j2 +! + neighbor PEER_V4 peer-group + neighbor PEER_V4_INT peer-group + neighbor PEER_V6 peer-group + neighbor PEER_V6_INT peer-group + address-family ipv4 + neighbor PEER_V4 allowas-in 1 + neighbor PEER_V4_INT allowas-in 1 + neighbor PEER_V4 soft-reconfiguration inbound + neighbor PEER_V4 route-map FROM_BGP_PEER_V4 in + neighbor PEER_V4 route-map TO_BGP_PEER_V4 out + neighbor PEER_V4_INT soft-reconfiguration inbound + neighbor PEER_V4_INT route-map FROM_BGP_PEER_V4 in + neighbor PEER_V4_INT route-map TO_BGP_PEER_V4 out + exit-address-family + address-family ipv6 + neighbor PEER_V6 allowas-in 1 + neighbor PEER_V6_INT allowas-in 1 + neighbor PEER_V6 soft-reconfiguration inbound + neighbor PEER_V6 route-map FROM_BGP_PEER_V6 in + neighbor PEER_V6 route-map TO_BGP_PEER_V6 out + neighbor PEER_V6_INT soft-reconfiguration inbound + neighbor PEER_V6_INT route-map FROM_BGP_PEER_V6 in + neighbor PEER_V6_INT route-map TO_BGP_PEER_V6 out + exit-address-family +! +! end of template: bgpd/templates/general/peer-group.conf.j2 +! diff --git a/src/sonic-bgpcfgd/tests/data/general/peer-group.conf/result_base.conf b/src/sonic-bgpcfgd/tests/data/general/peer-group.conf/result_base.conf new file mode 100644 index 000000000000..a681e7f08083 --- /dev/null +++ b/src/sonic-bgpcfgd/tests/data/general/peer-group.conf/result_base.conf @@ -0,0 +1,28 @@ +! +! template: bgpd/templates/general/peer-group.conf.j2 +! + neighbor PEER_V4 peer-group + neighbor PEER_V4_INT peer-group + neighbor PEER_V6 peer-group + neighbor PEER_V6_INT peer-group + address-family ipv4 + neighbor PEER_V4_INT route-reflector-client + neighbor PEER_V4 soft-reconfiguration inbound + neighbor PEER_V4 route-map FROM_BGP_PEER_V4 in + neighbor PEER_V4 route-map TO_BGP_PEER_V4 out + neighbor PEER_V4_INT soft-reconfiguration inbound + neighbor PEER_V4_INT route-map FROM_BGP_PEER_V4 in + neighbor PEER_V4_INT route-map TO_BGP_PEER_V4 out + exit-address-family + address-family ipv6 + neighbor PEER_V6_INT route-reflector-client + neighbor PEER_V6 soft-reconfiguration inbound + neighbor PEER_V6 route-map FROM_BGP_PEER_V6 in + neighbor PEER_V6 route-map TO_BGP_PEER_V6 out + neighbor PEER_V6_INT soft-reconfiguration inbound + neighbor PEER_V6_INT route-map FROM_BGP_PEER_V6 in + neighbor PEER_V6_INT route-map TO_BGP_PEER_V6 out + exit-address-family +! +! end of template: bgpd/templates/general/peer-group.conf.j2 +! diff --git a/src/sonic-bgpcfgd/tests/data/general/policies.conf/param_all.json b/src/sonic-bgpcfgd/tests/data/general/policies.conf/param_all.json new file mode 100644 index 000000000000..148456fe960f --- /dev/null +++ b/src/sonic-bgpcfgd/tests/data/general/policies.conf/param_all.json @@ -0,0 +1,8 @@ +{ + "CONFIG_DB__DEVICE_METADATA": { + "localhost": { + "sub_role": "BackEnd" + } + }, + "loopback0_ipv4": "10.10.10.10/32" +} \ No newline at end of file diff --git a/src/sonic-bgpcfgd/tests/data/general/policies.conf/param_base.json b/src/sonic-bgpcfgd/tests/data/general/policies.conf/param_base.json new file mode 100644 index 000000000000..53bf5572eff3 --- /dev/null +++ b/src/sonic-bgpcfgd/tests/data/general/policies.conf/param_base.json @@ -0,0 +1,8 @@ +{ + "CONFIG_DB__DEVICE_METADATA": { + "localhost": { + "sub_role": "NotBackEnd" + } + }, + "loopback0_ipv4": "10.10.10.10/32" +} \ No newline at end of file diff --git a/src/sonic-bgpcfgd/tests/data/general/policies.conf/result_all.conf b/src/sonic-bgpcfgd/tests/data/general/policies.conf/result_all.conf new file mode 100644 index 000000000000..1e3288b9a7da --- /dev/null +++ b/src/sonic-bgpcfgd/tests/data/general/policies.conf/result_all.conf @@ -0,0 +1,25 @@ +! +! template: bgpd/templates/general/policies.conf.j2 +! +route-map FROM_BGP_PEER_V4 permit 100 +! +route-map TO_BGP_PEER_V4 permit 100 +! +route-map FROM_BGP_PEER_V6 permit 1 + set ipv6 next-hop prefer-global +! +route-map FROM_BGP_PEER_V6 permit 100 +! +route-map TO_BGP_PEER_V6 permit 100 +! +route-map FROM_BGP_PEER_V4_INT permit 2 + set originator-id 10.10.10.10 +! +route-map FROM_BGP_PEER_V6_INT permit 1 + set ipv6 next-hop prefer-global +! +route-map FROM_BGP_PEER_V6_INT permit 2 + set originator-id 10.10.10.10 +! +! end of template: bgpd/templates/general/policies.conf.j2 +! diff --git a/src/sonic-bgpcfgd/tests/data/general/policies.conf/result_base.conf b/src/sonic-bgpcfgd/tests/data/general/policies.conf/result_base.conf new file mode 100644 index 000000000000..957264352209 --- /dev/null +++ b/src/sonic-bgpcfgd/tests/data/general/policies.conf/result_base.conf @@ -0,0 +1,16 @@ +! +! template: bgpd/templates/general/policies.conf.j2 +! +route-map FROM_BGP_PEER_V4 permit 100 +! +route-map TO_BGP_PEER_V4 permit 100 +! +route-map FROM_BGP_PEER_V6 permit 1 + set ipv6 next-hop prefer-global +! +route-map FROM_BGP_PEER_V6 permit 100 +! +route-map TO_BGP_PEER_V6 permit 100 +! +! end of template: bgpd/templates/general/policies.conf.j2 +! diff --git a/src/sonic-bgpcfgd/tests/data/monitors/instance.conf/param_all.json b/src/sonic-bgpcfgd/tests/data/monitors/instance.conf/param_all.json new file mode 100644 index 000000000000..9ac3ceda978a --- /dev/null +++ b/src/sonic-bgpcfgd/tests/data/monitors/instance.conf/param_all.json @@ -0,0 +1,12 @@ +{ + "bgp_asn": "555", + "neighbor_addr": "10.20.30.40", + "bgp_session": { + "name": "monitor" + }, + "constants": { + "deployment_id_asn_map": { + "5": "51111" + } + } +} diff --git a/src/sonic-bgpcfgd/tests/data/monitors/instance.conf/result_all.conf b/src/sonic-bgpcfgd/tests/data/monitors/instance.conf/result_all.conf new file mode 100644 index 000000000000..c8faaa895bd7 --- /dev/null +++ b/src/sonic-bgpcfgd/tests/data/monitors/instance.conf/result_all.conf @@ -0,0 +1,13 @@ +! +! template: bgpd/templates/monitors/instance.conf.j2 +! + neighbor 10.20.30.40 remote-as 555 + neighbor 10.20.30.40 peer-group BGPMON + neighbor 10.20.30.40 description monitor + neighbor 10.20.30.40 activate + address-family ipv6 + neighbor 10.20.30.40 activate + exit-address-family +! +! end of template: bgpd/templates/BGPMON/instance.conf.j2 +! diff --git a/src/sonic-bgpcfgd/tests/data/monitors/peer-group.conf/param_all.json b/src/sonic-bgpcfgd/tests/data/monitors/peer-group.conf/param_all.json new file mode 100644 index 000000000000..4f45f8a0f3f4 --- /dev/null +++ b/src/sonic-bgpcfgd/tests/data/monitors/peer-group.conf/param_all.json @@ -0,0 +1,3 @@ +{ + "loopback0_ipv4": "1.1.1.1/32" +} \ No newline at end of file diff --git a/src/sonic-bgpcfgd/tests/data/monitors/peer-group.conf/result_all.conf b/src/sonic-bgpcfgd/tests/data/monitors/peer-group.conf/result_all.conf new file mode 100644 index 000000000000..d5e9624ff1a5 --- /dev/null +++ b/src/sonic-bgpcfgd/tests/data/monitors/peer-group.conf/result_all.conf @@ -0,0 +1,12 @@ +! +! template: bgpd/templates/BGPMON/peer-group.conf.j2 +! + neighbor BGPMON peer-group + neighbor BGPMON update-source 1.1.1.1 + neighbor BGPMON route-map FROM_BGPMON in + neighbor BGPMON route-map TO_BGPMON out + neighbor BGPMON send-community + neighbor BGPMON maximum-prefix 1 +! +! end of template: bgpd/templates/BGPMON/peer-group.conf.j2 +! diff --git a/src/sonic-bgpcfgd/tests/data/monitors/policies.conf/param_all.json b/src/sonic-bgpcfgd/tests/data/monitors/policies.conf/param_all.json new file mode 100644 index 000000000000..9e26dfeeb6e6 --- /dev/null +++ b/src/sonic-bgpcfgd/tests/data/monitors/policies.conf/param_all.json @@ -0,0 +1 @@ +{} \ No newline at end of file diff --git a/src/sonic-bgpcfgd/tests/data/monitors/policies.conf/result_all.conf b/src/sonic-bgpcfgd/tests/data/monitors/policies.conf/result_all.conf new file mode 100644 index 000000000000..8d53991064de --- /dev/null +++ b/src/sonic-bgpcfgd/tests/data/monitors/policies.conf/result_all.conf @@ -0,0 +1,9 @@ +! +! template: bgpd/templates/BGPMON/policies.conf.j2 +! +route-map FROM_BGPMON deny 10 +! +route-map TO_BGPMON permit 10 +! +! end of template: bgpd/templates/BGPMON/policies.conf.j2 +! diff --git a/src/sonic-bgpcfgd/tests/data/sonic-cfggen/bgpd.conf.j2/all.conf b/src/sonic-bgpcfgd/tests/data/sonic-cfggen/bgpd.conf.j2/all.conf new file mode 100644 index 000000000000..166a5c64752c --- /dev/null +++ b/src/sonic-bgpcfgd/tests/data/sonic-cfggen/bgpd.conf.j2/all.conf @@ -0,0 +1,76 @@ +! +! template: bgpd/bgpd.conf.j2 +! +! =========== Managed by sonic-cfggen DO NOT edit manually! ==================== +! generated by templates/quagga/bgpd.conf.j2 with config DB data +! file: bgpd.conf +! +! template: common/daemons.common.conf.j2 +! +hostname new_hostname +password zebra +enable password zebra +! +log syslog informational +log facility local4 +! +! end of template: common/daemons.common.conf.j2! +agentx +! +! template: bgpd/bgpd.main.conf.j2 +! +! bgp multiple-instance +! +! BGP configuration +! +! TSA configuration +! +ip prefix-list PL_LoopbackV4 permit 55.55.55.55/32 +! +ipv6 prefix-list PL_LoopbackV6 permit fc00::/64 +! +route-map HIDE_INTERNAL permit 10 + set community local-AS +! +router bgp 55555 +! + bgp log-neighbor-changes + no bgp default ipv4-unicast +! + bgp bestpath as-path multipath-relax +! + bgp graceful-restart restart-time 480 + bgp graceful-restart + bgp graceful-restart preserve-fw-state +! + bgp router-id 55.55.55.55 +! + network 55.55.55.55/32 +! + address-family ipv6 + network fc00::1/64 + exit-address-family +! + network 10.10.10.1/24 + address-family ipv6 + network fc01::1/64 + exit-address-family +! + address-family ipv4 + redistribute connected route-map HIDE_INTERNAL + exit-address-family + address-family ipv6 + redistribute connected route-map HIDE_INTERNAL + exit-address-family +! + address-family ipv4 + maximum-paths 32 + exit-address-family + address-family ipv6 + maximum-paths 32 + exit-address-family +! +! end of template: bgpd/bgpd.main.conf.j2 +!! +! end of template: bgpd/bgpd.conf.j2 +! diff --git a/src/sonic-bgpcfgd/tests/data/sonic-cfggen/bgpd.conf.j2/all.json b/src/sonic-bgpcfgd/tests/data/sonic-cfggen/bgpd.conf.j2/all.json new file mode 100644 index 000000000000..17e32589d84c --- /dev/null +++ b/src/sonic-bgpcfgd/tests/data/sonic-cfggen/bgpd.conf.j2/all.json @@ -0,0 +1,33 @@ +{ + "DEVICE_METADATA": { + "localhost": { + "hostname": "new_hostname", + "bgp_asn": "55555", + "sub_role": "FrontEnd" + } + }, + "LOOPBACK_INTERFACE": { + "Loopback0|55.55.55.55/32": {}, + "Loopback0|fc00::1/128": {} + }, + "VLAN_INTERFACE": { + "Vlan10|10.10.10.1/24": {}, + "Vlan10|fc01::1/64": {} + }, + "constants": { + "bgp": { + "multipath_relax": { + "enabled": true + }, + "graceful_restart": { + "enabled": true, + "restart_time": 480 + }, + "maximum_paths": { + "enabled": true, + "ipv4": 32, + "ipv6": 32 + } + } + } +} diff --git a/src/sonic-bgpcfgd/tests/data/sonic-cfggen/bgpd.main.conf.j2/all.conf b/src/sonic-bgpcfgd/tests/data/sonic-cfggen/bgpd.main.conf.j2/all.conf new file mode 100644 index 000000000000..8edbdb60a613 --- /dev/null +++ b/src/sonic-bgpcfgd/tests/data/sonic-cfggen/bgpd.main.conf.j2/all.conf @@ -0,0 +1,56 @@ +! +! template: bgpd/bgpd.main.conf.j2 +! +! bgp multiple-instance +! +! BGP configuration +! +! TSA configuration +! +ip prefix-list PL_LoopbackV4 permit 55.55.55.55/32 +! +ipv6 prefix-list PL_LoopbackV6 permit fc00::/64 +! +route-map HIDE_INTERNAL permit 10 + set community local-AS +! +router bgp 55555 +! + bgp log-neighbor-changes + no bgp default ipv4-unicast +! + bgp bestpath as-path multipath-relax +! + bgp graceful-restart restart-time 480 + bgp graceful-restart + bgp graceful-restart preserve-fw-state +! + bgp router-id 55.55.55.55 +! + network 55.55.55.55/32 +! + address-family ipv6 + network fc00::1/64 + exit-address-family +! + network 10.10.10.1/24 + address-family ipv6 + network fc01::1/64 + exit-address-family +! + address-family ipv4 + redistribute connected route-map HIDE_INTERNAL + exit-address-family + address-family ipv6 + redistribute connected route-map HIDE_INTERNAL + exit-address-family +! + address-family ipv4 + maximum-paths 32 + exit-address-family + address-family ipv6 + maximum-paths 32 + exit-address-family +! +! end of template: bgpd/bgpd.main.conf.j2 +! diff --git a/src/sonic-bgpcfgd/tests/data/sonic-cfggen/bgpd.main.conf.j2/all.json b/src/sonic-bgpcfgd/tests/data/sonic-cfggen/bgpd.main.conf.j2/all.json new file mode 100644 index 000000000000..36099674ac4e --- /dev/null +++ b/src/sonic-bgpcfgd/tests/data/sonic-cfggen/bgpd.main.conf.j2/all.json @@ -0,0 +1,32 @@ +{ + "DEVICE_METADATA": { + "localhost": { + "bgp_asn": "55555", + "sub_role": "FrontEnd" + } + }, + "LOOPBACK_INTERFACE": { + "Loopback0|55.55.55.55/32": {}, + "Loopback0|fc00::1/128": {} + }, + "VLAN_INTERFACE": { + "Vlan10|10.10.10.1/24": {}, + "Vlan10|fc01::1/64": {} + }, + "constants": { + "bgp": { + "multipath_relax": { + "enabled": true + }, + "graceful_restart": { + "enabled": true, + "restart_time": 480 + }, + "maximum_paths": { + "enabled": true, + "ipv4": 32, + "ipv6": 32 + } + } + } +} diff --git a/src/sonic-bgpcfgd/tests/data/sonic-cfggen/bgpd.main.conf.j2/base.conf b/src/sonic-bgpcfgd/tests/data/sonic-cfggen/bgpd.main.conf.j2/base.conf new file mode 100644 index 000000000000..97159456b6f9 --- /dev/null +++ b/src/sonic-bgpcfgd/tests/data/sonic-cfggen/bgpd.main.conf.j2/base.conf @@ -0,0 +1,22 @@ +! +! template: bgpd/bgpd.main.conf.j2 +! +! bgp multiple-instance +! +! BGP configuration +! +! TSA configuration +! +ip prefix-list PL_LoopbackV4 permit 55.55.55.55/32 +! +router bgp 55555 +! + bgp log-neighbor-changes + no bgp default ipv4-unicast +! + bgp router-id 55.55.55.55 +! + network 55.55.55.55/32 +! +! end of template: bgpd/bgpd.main.conf.j2 +! diff --git a/src/sonic-bgpcfgd/tests/data/sonic-cfggen/bgpd.main.conf.j2/base.json b/src/sonic-bgpcfgd/tests/data/sonic-cfggen/bgpd.main.conf.j2/base.json new file mode 100644 index 000000000000..692d4c78f0b9 --- /dev/null +++ b/src/sonic-bgpcfgd/tests/data/sonic-cfggen/bgpd.main.conf.j2/base.json @@ -0,0 +1,19 @@ +{ + "DEVICE_METADATA": { + "localhost": { + "bgp_asn": "55555", + "sub_role": "" + } + }, + "LOOPBACK_INTERFACE": { + "Loopback0|55.55.55.55/32": {}, + "Loopback1|fc00::1/128": {} + }, + "constants": { + "bgp": { + "multipath_relax": {}, + "graceful_restart": {}, + "maximum_paths": {} + } + } +} diff --git a/src/sonic-bgpcfgd/tests/data/sonic-cfggen/bgpd.main.conf.j2/defaults.conf b/src/sonic-bgpcfgd/tests/data/sonic-cfggen/bgpd.main.conf.j2/defaults.conf new file mode 100644 index 000000000000..b444fcd7e559 --- /dev/null +++ b/src/sonic-bgpcfgd/tests/data/sonic-cfggen/bgpd.main.conf.j2/defaults.conf @@ -0,0 +1,56 @@ +! +! template: bgpd/bgpd.main.conf.j2 +! +! bgp multiple-instance +! +! BGP configuration +! +! TSA configuration +! +ip prefix-list PL_LoopbackV4 permit 55.55.55.55/32 +! +ipv6 prefix-list PL_LoopbackV6 permit fc00::/64 +! +route-map HIDE_INTERNAL permit 10 + set community local-AS +! +router bgp 55555 +! + bgp log-neighbor-changes + no bgp default ipv4-unicast +! + bgp bestpath as-path multipath-relax +! + bgp graceful-restart restart-time 240 + bgp graceful-restart + bgp graceful-restart preserve-fw-state +! + bgp router-id 55.55.55.55 +! + network 55.55.55.55/32 +! + address-family ipv6 + network fc00::1/64 + exit-address-family +! + network 10.10.10.1/24 + address-family ipv6 + network fc01::1/64 + exit-address-family +! + address-family ipv4 + redistribute connected route-map HIDE_INTERNAL + exit-address-family + address-family ipv6 + redistribute connected route-map HIDE_INTERNAL + exit-address-family +! + address-family ipv4 + maximum-paths 64 + exit-address-family + address-family ipv6 + maximum-paths 64 + exit-address-family +! +! end of template: bgpd/bgpd.main.conf.j2 +! diff --git a/src/sonic-bgpcfgd/tests/data/sonic-cfggen/bgpd.main.conf.j2/defaults.json b/src/sonic-bgpcfgd/tests/data/sonic-cfggen/bgpd.main.conf.j2/defaults.json new file mode 100644 index 000000000000..2db9bd771c84 --- /dev/null +++ b/src/sonic-bgpcfgd/tests/data/sonic-cfggen/bgpd.main.conf.j2/defaults.json @@ -0,0 +1,29 @@ +{ + "DEVICE_METADATA": { + "localhost": { + "bgp_asn": "55555", + "sub_role": "FrontEnd" + } + }, + "LOOPBACK_INTERFACE": { + "Loopback0|55.55.55.55/32": {}, + "Loopback0|fc00::1/128": {} + }, + "VLAN_INTERFACE": { + "Vlan10|10.10.10.1/24": {}, + "Vlan10|fc01::1/64": {} + }, + "constants": { + "bgp": { + "multipath_relax": { + "enabled": true + }, + "graceful_restart": { + "enabled": true + }, + "maximum_paths": { + "enabled": true + } + } + } +} diff --git a/src/sonic-bgpcfgd/tests/data/sonic-cfggen/bgpd.spine_chassis_frontend_router.conf.j2/base.conf b/src/sonic-bgpcfgd/tests/data/sonic-cfggen/bgpd.spine_chassis_frontend_router.conf.j2/base.conf new file mode 100644 index 000000000000..581eb107ec23 --- /dev/null +++ b/src/sonic-bgpcfgd/tests/data/sonic-cfggen/bgpd.spine_chassis_frontend_router.conf.j2/base.conf @@ -0,0 +1,39 @@ +! +! Vnet BGP instance +router bgp 555 vrf First + no bgp default ipv4-unicast + bgp log-neighbor-changes + bgp bestpath as-path multipath-relax + no bgp default ipv4-unicast + bgp graceful-restart restart-time 240 + bgp graceful-restart + bgp router-id 10.20.30.40 + neighbor 10.10.10.1 remote-as 10 + neighbor 10.10.10.1 description session1 + address-family ipv4 unicast + neighbor 10.10.10.1 activate + neighbor 10.10.10.1 soft-reconfiguration inbound + maximum-paths 64 + exit-address-family + address-family l2vpn evpn + advertise ipv4 unicast + exit-address-family +router bgp 555 vrf Second + no bgp default ipv4-unicast + bgp log-neighbor-changes + bgp bestpath as-path multipath-relax + no bgp default ipv4-unicast + bgp graceful-restart restart-time 240 + bgp graceful-restart + bgp router-id 10.20.30.40 + neighbor 20.20.20.1 remote-as 20 + neighbor 20.20.20.1 description session2 + address-family ipv4 unicast + neighbor 20.20.20.1 activate + neighbor 20.20.20.1 soft-reconfiguration inbound + maximum-paths 64 + exit-address-family + address-family l2vpn evpn + advertise ipv4 unicast + exit-address-family +! diff --git a/src/sonic-bgpcfgd/tests/data/sonic-cfggen/bgpd.spine_chassis_frontend_router.conf.j2/base.json b/src/sonic-bgpcfgd/tests/data/sonic-cfggen/bgpd.spine_chassis_frontend_router.conf.j2/base.json new file mode 100644 index 000000000000..d6f09fb1139e --- /dev/null +++ b/src/sonic-bgpcfgd/tests/data/sonic-cfggen/bgpd.spine_chassis_frontend_router.conf.j2/base.json @@ -0,0 +1,42 @@ +{ + "DEVICE_METADATA": { + "localhost": { + "bgp_asn": "555" + } + }, + "LOOPBACK_INTERFACE": { + "Loopback0|10.20.30.40/32": {} + }, + "VNET": { + "First": { + "vni": 10 + }, + "Second": { + "vni": 20 + } + }, + "INTERFACE": { + "Ethernet0": { + "vnet_name": "First" + }, + "Ethernet0|10.10.10.10/24": {}, + "Ethernet8": { + "vnet_name": "Second" + }, + "Ethernet8|20.20.20.20/24": {}, + "Ethernet10": {}, + "Ethernet10|20.20.20.20/24": {} + }, + "BGP_NEIGHBOR": { + "10.10.10.1": { + "asn": "10", + "name": "session1", + "local_addr": "10.10.10.10" + }, + "20.20.20.1": { + "asn": "20", + "name": "session2", + "local_addr": "20.20.20.20" + } + } +} \ No newline at end of file diff --git a/src/sonic-bgpcfgd/tests/data/sonic-cfggen/common/daemons.common.conf b/src/sonic-bgpcfgd/tests/data/sonic-cfggen/common/daemons.common.conf new file mode 100644 index 000000000000..14d7b99d07ed --- /dev/null +++ b/src/sonic-bgpcfgd/tests/data/sonic-cfggen/common/daemons.common.conf @@ -0,0 +1,10 @@ +! template: common/daemons.common.conf.j2 +! +hostname test_hostname +password zebra +enable password zebra +! +log syslog informational +log facility local4 +! +! end of template: common/daemons.common.conf.j2 diff --git a/src/sonic-bgpcfgd/tests/data/sonic-cfggen/common/daemons.common.conf.json b/src/sonic-bgpcfgd/tests/data/sonic-cfggen/common/daemons.common.conf.json new file mode 100644 index 000000000000..8ef3e43694a7 --- /dev/null +++ b/src/sonic-bgpcfgd/tests/data/sonic-cfggen/common/daemons.common.conf.json @@ -0,0 +1,7 @@ +{ + "DEVICE_METADATA": { + "localhost": { + "hostname": "test_hostname" + } + } +} diff --git a/src/sonic-bgpcfgd/tests/data/sonic-cfggen/common/functions.conf b/src/sonic-bgpcfgd/tests/data/sonic-cfggen/common/functions.conf new file mode 100644 index 000000000000..8b137891791f --- /dev/null +++ b/src/sonic-bgpcfgd/tests/data/sonic-cfggen/common/functions.conf @@ -0,0 +1 @@ + diff --git a/src/sonic-bgpcfgd/tests/data/sonic-cfggen/common/functions.conf.json b/src/sonic-bgpcfgd/tests/data/sonic-cfggen/common/functions.conf.json new file mode 100644 index 000000000000..9e26dfeeb6e6 --- /dev/null +++ b/src/sonic-bgpcfgd/tests/data/sonic-cfggen/common/functions.conf.json @@ -0,0 +1 @@ +{} \ No newline at end of file diff --git a/src/sonic-bgpcfgd/tests/data/sonic-cfggen/frr.conf.j2/all.conf b/src/sonic-bgpcfgd/tests/data/sonic-cfggen/frr.conf.j2/all.conf new file mode 100644 index 000000000000..4c5e81f4f90d --- /dev/null +++ b/src/sonic-bgpcfgd/tests/data/sonic-cfggen/frr.conf.j2/all.conf @@ -0,0 +1,91 @@ +! +! =========== Managed by sonic-cfggen DO NOT edit manually! ==================== +! generated by templates/frr.conf.j2 with config DB data +! file: frr.conf +! +! template: common/daemons.common.conf.j2 +! +hostname test_hostname +password zebra +enable password zebra +! +log syslog informational +log facility local4 +! +! end of template: common/daemons.common.conf.j2! +agentx +! +! Enable link-detect (default disabled) +interface Ethernet0 +link-detect +! +interface Ethernet4 +link-detect +! +interface PortChannel10 +link-detect +! +interface PortChannel20 +link-detect +! +!! +! +! set static default route to mgmt gateway as a backup to learned default +ip route 0.0.0.0/0 10.10.10.1 200 +!! +! +! template: bgpd/bgpd.main.conf.j2 +! +! bgp multiple-instance +! +! BGP configuration +! +! TSA configuration +! +ip prefix-list PL_LoopbackV4 permit 55.55.55.55/32 +! +ipv6 prefix-list PL_LoopbackV6 permit fc00::/64 +! +route-map HIDE_INTERNAL permit 10 + set community local-AS +! +router bgp 55555 +! + bgp log-neighbor-changes + no bgp default ipv4-unicast +! + bgp bestpath as-path multipath-relax +! + bgp graceful-restart restart-time 480 + bgp graceful-restart + bgp graceful-restart preserve-fw-state +! + bgp router-id 55.55.55.55 +! + network 55.55.55.55/32 +! + address-family ipv6 + network fc00::1/64 + exit-address-family +! + network 10.10.10.1/24 + address-family ipv6 + network fc01::1/64 + exit-address-family +! + address-family ipv4 + redistribute connected route-map HIDE_INTERNAL + exit-address-family + address-family ipv6 + redistribute connected route-map HIDE_INTERNAL + exit-address-family +! + address-family ipv4 + maximum-paths 32 + exit-address-family + address-family ipv6 + maximum-paths 32 + exit-address-family +! +! end of template: bgpd/bgpd.main.conf.j2 +!! diff --git a/src/sonic-bgpcfgd/tests/data/sonic-cfggen/frr.conf.j2/all.json b/src/sonic-bgpcfgd/tests/data/sonic-cfggen/frr.conf.j2/all.json new file mode 100644 index 000000000000..d81eba2b0fe6 --- /dev/null +++ b/src/sonic-bgpcfgd/tests/data/sonic-cfggen/frr.conf.j2/all.json @@ -0,0 +1,46 @@ +{ + "DEVICE_METADATA": { + "localhost": { + "bgp_asn": "55555", + "hostname": "test_hostname", + "sub_role": "FrontEnd" + } + }, + "INTERFACE": { + "Ethernet0|10.20.30.40/24": {}, + "Ethernet4|20.20.30.40/24": {} + }, + "PORTCHANNEL": { + "PortChannel10": {}, + "PortChannel20": {} + }, + "MGMT_INTERFACE": { + "eth0|10.10.10.10/24": { + "gwaddr": "10.10.10.1" + } + }, + "LOOPBACK_INTERFACE": { + "Loopback0|55.55.55.55/32": {}, + "Loopback0|fc00::1/128": {} + }, + "VLAN_INTERFACE": { + "Vlan10|10.10.10.1/24": {}, + "Vlan10|fc01::1/64": {} + }, + "constants": { + "bgp": { + "multipath_relax": { + "enabled": true + }, + "graceful_restart": { + "enabled": true, + "restart_time": 480 + }, + "maximum_paths": { + "enabled": true, + "ipv4": 32, + "ipv6": 32 + } + } + } +} \ No newline at end of file diff --git a/src/sonic-bgpcfgd/tests/data/sonic-cfggen/isolate/isolate b/src/sonic-bgpcfgd/tests/data/sonic-cfggen/isolate/isolate new file mode 100644 index 000000000000..74f107495298 --- /dev/null +++ b/src/sonic-bgpcfgd/tests/data/sonic-cfggen/isolate/isolate @@ -0,0 +1,17 @@ +#!/bin/bash +## vtysh only accepts script in stdin, so cannot be directly used in shebang +## Cut the tail of this script and feed vtysh stdin +sed -n -e '9,$p' < "$0" | vtysh "$@" +## Exit with vtysh return code +exit $? +## vtysh script start from next line, which line number MUST equal in 'sed' command above +configure terminal + router bgp 12345 + neighbor 10.20.30.40 route-map ISOLATE out + address-family ipv6 + neighbor fc00::1 route-map ISOLATE out + exit-address-family + exit +exit +clear ip bgp 10.20.30.40 soft out +clear ip bgp fc00::1 soft out diff --git a/src/sonic-bgpcfgd/tests/data/sonic-cfggen/isolate/isolate.json b/src/sonic-bgpcfgd/tests/data/sonic-cfggen/isolate/isolate.json new file mode 100644 index 000000000000..012b69ef3036 --- /dev/null +++ b/src/sonic-bgpcfgd/tests/data/sonic-cfggen/isolate/isolate.json @@ -0,0 +1,11 @@ +{ + "DEVICE_METADATA": { + "localhost": { + "bgp_asn": "12345" + } + }, + "BGP_NEIGHBOR": { + "10.20.30.40": {}, + "fc00::1": {} + } +} diff --git a/src/sonic-bgpcfgd/tests/data/sonic-cfggen/isolate/unisolate b/src/sonic-bgpcfgd/tests/data/sonic-cfggen/isolate/unisolate new file mode 100644 index 000000000000..b9476d0b7107 --- /dev/null +++ b/src/sonic-bgpcfgd/tests/data/sonic-cfggen/isolate/unisolate @@ -0,0 +1,17 @@ +#!/bin/bash +## vtysh only accepts script in stdin, so cannot be directly used in shebang +## Cut the tail of this script and feed vtysh stdin +sed -n -e '9,$p' < "$0" | vtysh "$@" +## Exit with vtysh return code +exit $? +## vtysh script start from next line, which line number MUST equal in 'sed' command above +configure terminal + router bgp 12345 + no neighbor 10.20.30.40 route-map ISOLATE out + address-family ipv6 + no neighbor fc00::1 route-map ISOLATE out + exit-address-family + exit +exit +clear ip bgp 10.20.30.40 soft out +clear ip bgp fc00::1 soft out diff --git a/src/sonic-bgpcfgd/tests/data/sonic-cfggen/isolate/unisolate.json b/src/sonic-bgpcfgd/tests/data/sonic-cfggen/isolate/unisolate.json new file mode 100644 index 000000000000..012b69ef3036 --- /dev/null +++ b/src/sonic-bgpcfgd/tests/data/sonic-cfggen/isolate/unisolate.json @@ -0,0 +1,11 @@ +{ + "DEVICE_METADATA": { + "localhost": { + "bgp_asn": "12345" + } + }, + "BGP_NEIGHBOR": { + "10.20.30.40": {}, + "fc00::1": {} + } +} diff --git a/src/sonic-bgpcfgd/tests/data/sonic-cfggen/staticd/staticd.conf b/src/sonic-bgpcfgd/tests/data/sonic-cfggen/staticd/staticd.conf new file mode 100644 index 000000000000..522c0d36f296 --- /dev/null +++ b/src/sonic-bgpcfgd/tests/data/sonic-cfggen/staticd/staticd.conf @@ -0,0 +1,19 @@ +! +! =========== Managed by sonic-cfggen DO NOT edit manually! ==================== +! generated by templates/frr/staticd.conf.j2 using config DB data +! file: staticd.conf +! +! template: common/daemons.common.conf.j2 +! +hostname new_hostname +password zebra +enable password zebra +! +log syslog informational +log facility local4 +! +! end of template: common/daemons.common.conf.j2! +! +! set static default route to mgmt gateway as a backup to learned default +ip route 0.0.0.0/0 10.10.10.1 200 +!! diff --git a/src/sonic-bgpcfgd/tests/data/sonic-cfggen/staticd/staticd.conf.json b/src/sonic-bgpcfgd/tests/data/sonic-cfggen/staticd/staticd.conf.json new file mode 100644 index 000000000000..37f660d101d6 --- /dev/null +++ b/src/sonic-bgpcfgd/tests/data/sonic-cfggen/staticd/staticd.conf.json @@ -0,0 +1,12 @@ +{ + "DEVICE_METADATA": { + "localhost": { + "hostname": "new_hostname" + } + }, + "MGMT_INTERFACE": { + "eth0|10.10.10.10/24": { + "gwaddr": "10.10.10.1" + } + } +} diff --git a/src/sonic-bgpcfgd/tests/data/sonic-cfggen/staticd/staticd.default_route.conf b/src/sonic-bgpcfgd/tests/data/sonic-cfggen/staticd/staticd.default_route.conf new file mode 100644 index 000000000000..11adb98ebc3c --- /dev/null +++ b/src/sonic-bgpcfgd/tests/data/sonic-cfggen/staticd/staticd.default_route.conf @@ -0,0 +1,4 @@ +! +! set static default route to mgmt gateway as a backup to learned default +ip route 0.0.0.0/0 10.10.10.1 200 +! diff --git a/src/sonic-bgpcfgd/tests/data/sonic-cfggen/staticd/staticd.default_route.conf.json b/src/sonic-bgpcfgd/tests/data/sonic-cfggen/staticd/staticd.default_route.conf.json new file mode 100644 index 000000000000..80cd218a790e --- /dev/null +++ b/src/sonic-bgpcfgd/tests/data/sonic-cfggen/staticd/staticd.default_route.conf.json @@ -0,0 +1,7 @@ +{ + "MGMT_INTERFACE": { + "eth0|10.10.10.10/24": { + "gwaddr": "10.10.10.1" + } + } +} diff --git a/src/sonic-bgpcfgd/tests/data/sonic-cfggen/tsa/isolate.conf b/src/sonic-bgpcfgd/tests/data/sonic-cfggen/tsa/isolate.conf new file mode 100644 index 000000000000..7bd155fcdb64 --- /dev/null +++ b/src/sonic-bgpcfgd/tests/data/sonic-cfggen/tsa/isolate.conf @@ -0,0 +1,5 @@ +route-map test_rm_name permit 2 + match ip address prefix-list PL_LoopbackV4 + set community 12345:555 +route-map test_rm_name deny 3 +! diff --git a/src/sonic-bgpcfgd/tests/data/sonic-cfggen/tsa/isolate.json b/src/sonic-bgpcfgd/tests/data/sonic-cfggen/tsa/isolate.json new file mode 100644 index 000000000000..708e4013f131 --- /dev/null +++ b/src/sonic-bgpcfgd/tests/data/sonic-cfggen/tsa/isolate.json @@ -0,0 +1,9 @@ +{ + "constants": { + "bgp": { + "traffic_shift_community": "12345:555" + } + }, + "route_map_name": "test_rm_name", + "ip_version": "V4" +} \ No newline at end of file diff --git a/src/sonic-bgpcfgd/tests/data/sonic-cfggen/tsa/unisolate.conf b/src/sonic-bgpcfgd/tests/data/sonic-cfggen/tsa/unisolate.conf new file mode 100644 index 000000000000..db53a69e7ec4 --- /dev/null +++ b/src/sonic-bgpcfgd/tests/data/sonic-cfggen/tsa/unisolate.conf @@ -0,0 +1,3 @@ +no route-map test_rm permit 2 +no route-map test_rm deny 3 +! diff --git a/src/sonic-bgpcfgd/tests/data/sonic-cfggen/tsa/unisolate.json b/src/sonic-bgpcfgd/tests/data/sonic-cfggen/tsa/unisolate.json new file mode 100644 index 000000000000..da070431493d --- /dev/null +++ b/src/sonic-bgpcfgd/tests/data/sonic-cfggen/tsa/unisolate.json @@ -0,0 +1,3 @@ +{ + "route_map_name": "test_rm" +} \ No newline at end of file diff --git a/src/sonic-bgpcfgd/tests/data/sonic-cfggen/zebra/interfaces.conf b/src/sonic-bgpcfgd/tests/data/sonic-cfggen/zebra/interfaces.conf new file mode 100644 index 000000000000..919c35085b5c --- /dev/null +++ b/src/sonic-bgpcfgd/tests/data/sonic-cfggen/zebra/interfaces.conf @@ -0,0 +1,14 @@ +! +! Enable link-detect (default disabled) +interface Ethernet0 +link-detect +! +interface Ethernet4 +link-detect +! +interface PortChannel10 +link-detect +! +interface PortChannel20 +link-detect +! diff --git a/src/sonic-bgpcfgd/tests/data/sonic-cfggen/zebra/interfaces.json b/src/sonic-bgpcfgd/tests/data/sonic-cfggen/zebra/interfaces.json new file mode 100644 index 000000000000..e9c1bcba418d --- /dev/null +++ b/src/sonic-bgpcfgd/tests/data/sonic-cfggen/zebra/interfaces.json @@ -0,0 +1,10 @@ +{ + "INTERFACE": { + "Ethernet0|10.20.30.40/24": {}, + "Ethernet4|20.20.30.40/24": {} + }, + "PORTCHANNEL": { + "PortChannel10": {}, + "PortChannel20": {} + } +} \ No newline at end of file diff --git a/src/sonic-bgpcfgd/tests/data/sonic-cfggen/zebra/set_src.conf b/src/sonic-bgpcfgd/tests/data/sonic-cfggen/zebra/set_src.conf new file mode 100644 index 000000000000..b543d24e0023 --- /dev/null +++ b/src/sonic-bgpcfgd/tests/data/sonic-cfggen/zebra/set_src.conf @@ -0,0 +1,8 @@ +! +! Set ip source to loopback for bgp learned routes +! +route-map new_rm_name permit 10 + set src 10.20.30.40 +! +ipv4 protocol bgp route-map new_rm_name +! diff --git a/src/sonic-bgpcfgd/tests/data/sonic-cfggen/zebra/set_src.json b/src/sonic-bgpcfgd/tests/data/sonic-cfggen/zebra/set_src.json new file mode 100644 index 000000000000..2e76d46fd106 --- /dev/null +++ b/src/sonic-bgpcfgd/tests/data/sonic-cfggen/zebra/set_src.json @@ -0,0 +1,5 @@ +{ + "rm_name": "new_rm_name", + "lo_ip": "10.20.30.40", + "ip_proto": "v4" +} \ No newline at end of file diff --git a/src/sonic-bgpcfgd/tests/data/sonic-cfggen/zebra/zebra.conf b/src/sonic-bgpcfgd/tests/data/sonic-cfggen/zebra/zebra.conf new file mode 100644 index 000000000000..f7b30f214d4d --- /dev/null +++ b/src/sonic-bgpcfgd/tests/data/sonic-cfggen/zebra/zebra.conf @@ -0,0 +1,36 @@ +! +! =========== Managed by sonic-cfggen DO NOT edit manually! ==================== +! generated by templates/zebra/zebra.conf.j2 using config DB data +! file: zebra.conf +! +! template: common/daemons.common.conf.j2 +! +hostname new_hostname +password zebra +enable password zebra +! +log syslog informational +log facility local4 +! +! end of template: common/daemons.common.conf.j2! +! +vrf First +vni 10 +! +vrf Second +vni 20 +! +! Enable link-detect (default disabled) +interface Ethernet0 +link-detect +! +interface Ethernet4 +link-detect +! +interface PortChannel10 +link-detect +! +interface PortChannel20 +link-detect +! +!! diff --git a/src/sonic-bgpcfgd/tests/data/sonic-cfggen/zebra/zebra.conf.json b/src/sonic-bgpcfgd/tests/data/sonic-cfggen/zebra/zebra.conf.json new file mode 100644 index 000000000000..9b63ff526fb9 --- /dev/null +++ b/src/sonic-bgpcfgd/tests/data/sonic-cfggen/zebra/zebra.conf.json @@ -0,0 +1,23 @@ +{ + "DEVICE_METADATA": { + "localhost": { + "hostname": "new_hostname" + } + }, + "VNET": { + "First": { + "vni": 10 + }, + "Second": { + "vni": 20 + } + }, + "INTERFACE": { + "Ethernet0|10.20.30.40/24": {}, + "Ethernet4|20.20.30.40/24": {} + }, + "PORTCHANNEL": { + "PortChannel10": {}, + "PortChannel20": {} + } +} \ No newline at end of file diff --git a/src/sonic-bgpcfgd/tests/test_ipv6_nexthop_global.py b/src/sonic-bgpcfgd/tests/test_ipv6_nexthop_global.py new file mode 100644 index 000000000000..bc6d01cdb536 --- /dev/null +++ b/src/sonic-bgpcfgd/tests/test_ipv6_nexthop_global.py @@ -0,0 +1,114 @@ +import os +import re + +from app.template import TemplateFabric +from .util import load_constants + +TEMPLATE_PATH = os.path.abspath('../../dockers/docker-fpm-frr/frr') + + +def parse_instance_conf(filename): + activate_re = re.compile(r'^neighbor\s+(\S+)\s+activate$') + with open(filename) as fp: + lines = [line.strip() for line in fp if not line.strip().startswith('!') and line.strip() != ''] + # Search all v6 neighbors + neighbors = {} + for line in lines: + if activate_re.match(line): + neighbor = activate_re.match(line).group(1) + if TemplateFabric.is_ipv6(neighbor): + neighbors[neighbor] = {} + # Extract peer-groups and route-maps + for neighbor, neighbor_data in neighbors.iteritems(): + route_map_in_re = re.compile(r'^neighbor\s+%s\s+route-map\s+(\S+) in$' % neighbor) + peer_group_re = re.compile(r'^neighbor\s+%s\s+peer-group\s+(\S+)$' % neighbor) + for line in lines: + if route_map_in_re.match(line): + assert "route-map" not in neighbor_data + neighbor_data["route-map"] = route_map_in_re.match(line).group(1) + if peer_group_re.match(line): + assert "peer-group" not in neighbor_data + neighbor_data["peer-group"] = peer_group_re.match(line).group(1) + # Ensure that every ivp6 neighbor has either route-map or peer-group + for neighbor, neighbor_data in neighbors.iteritems(): + assert "route-map" in neighbor_data or "peer-group" in neighbor_data,\ + "IPv6 neighbor '%s' must have either route-map in or peer-group %s" % (neighbor, neighbor_data) + return neighbors + +def load_results(path, dir_name): + result_files = [] + for fname in os.listdir(os.path.join(path, dir_name)): + if not fname.startswith("result_"): + continue + full_fname = os.path.join(path, dir_name, fname) + if not os.path.isfile(full_fname): + continue + result_files.append(full_fname) + return result_files + +def process_instances(path): + result_files = load_results(path, "instance.conf") + # search for ipv6 neighbors + neighbors_list = [] + for fname in result_files: + neighbors = parse_instance_conf(fname) + if neighbors: + neighbors_list.append(neighbors) + return neighbors_list + +def parse_peer_group_conf(filename, pg_name): + route_map_re = re.compile(r'^neighbor\s+%s\s+route-map\s+(\S+)\s+in$' % pg_name) + with open(filename) as fp: + lines = [line.strip() for line in fp if not line.strip().startswith('!') and line.strip() != ''] + route_maps = set() + for line in lines: + if route_map_re.match(line): + route_map = route_map_re.match(line).group(1) + route_maps.add(route_map) + return route_maps + +def extract_rm_from_peer_group(path, peer_group_name): + result_files = load_results(path, "peer-group.conf") + rm_set = set() + for fname in result_files: + route_maps = parse_peer_group_conf(fname, peer_group_name) + if route_maps: + rm_set |= route_maps + return list(rm_set) + +def check_routemap_in_file(filename, route_map_name): + route_map_re = re.compile(r'^route-map\s+%s\s+(\S+)' % route_map_name) + set_re = re.compile(r'set ipv6 next-hop prefer-global') + with open(filename) as fp: + lines = [line.strip() for line in fp if not line.strip().startswith('!') and line.strip() != ''] + found_first_entry = False + for line in lines: + err_msg = "route-map %s doesn't have mandatory 'set ipv6 next-hop prefer-global' entry as the first rule" % route_map_name + assert not (found_first_entry and line.startswith("route-map")), err_msg + if found_first_entry and set_re.match(line): + break # We're good + if route_map_re.match(line): + err_msg = "route-map %s doesn't have mandatory permit entry for 'set ipv6 next-hop prefer-global" % route_map_name + assert route_map_re.match(line).group(1) == 'permit', err_msg + found_first_entry = True + return found_first_entry + +def check_routemap(path, route_map_name): + result_files = load_results(path, "policies.conf") + checked = False + for fname in result_files: + checked = checked or check_routemap_in_file(fname, route_map_name) + assert checked, "route-map %s wasn't found" % route_map_name + +def test_v6_next_hop_global(): + paths = ["tests/data/%s" % value for value in load_constants().values()] + for path in paths: + test_cases = process_instances(path) + for test_case in test_cases: + for neighbor_value in test_case.values(): + if 'route-map' in neighbor_value: + check_routemap(path, neighbor_value['route-map']) + elif 'peer-group' in neighbor_value: + route_map_in_list = extract_rm_from_peer_group(path, neighbor_value['peer-group']) + for route_map_in in route_map_in_list: + check_routemap(path, route_map_in) diff --git a/src/sonic-bgpcfgd/tests/test_pfx_filter.py b/src/sonic-bgpcfgd/tests/test_pfx_filter.py new file mode 100644 index 000000000000..3eebd3951f7b --- /dev/null +++ b/src/sonic-bgpcfgd/tests/test_pfx_filter.py @@ -0,0 +1,139 @@ +from app.template import TemplateFabric +from collections import OrderedDict +import pytest + + +def test_pfx_filter_none(): + res = TemplateFabric.pfx_filter(None) + assert isinstance(res, OrderedDict) and len(res) == 0 + +def test_pfx_filter_empty_tuple(): + res = TemplateFabric.pfx_filter(()) + assert isinstance(res, OrderedDict) and len(res) == 0 + +def test_pfx_filter_empty_list(): + res = TemplateFabric.pfx_filter([]) + assert isinstance(res, OrderedDict) and len(res) == 0 + +def test_pfx_filter_empty_dict(): + res = TemplateFabric.pfx_filter({}) + assert isinstance(res, OrderedDict) and len(res) == 0 + +def test_pfx_filter_strings(): + src = { + 'Loopback0': {}, + 'Loopback1': {}, + } + expected = OrderedDict([]) + res = TemplateFabric.pfx_filter(src) + assert res == expected + +def test_pfx_filter_mixed_keys(): + src = { + 'Loopback0': {}, + ('Loopback0', '11.11.11.11/32'): {}, + 'Loopback1': {}, + ('Loopback1', '55.55.55.55/32'): {}, + } + expected = OrderedDict( + [ + (('Loopback1', '55.55.55.55/32'), {}), + (('Loopback0', '11.11.11.11/32'), {}), + ] + ) + res = TemplateFabric.pfx_filter(src) + assert res == expected + + +def test_pfx_filter_pfx_v4_w_mask(): + src = { + ('Loopback0', '11.11.11.11/32'): {}, + ('Loopback1', '55.55.55.55/32'): {}, + } + expected = OrderedDict( + [ + (('Loopback1', '55.55.55.55/32'), {}), + (('Loopback0', '11.11.11.11/32'), {}), + ] + ) + res = TemplateFabric.pfx_filter(src) + assert res == expected + +def test_pfx_filter_pfx_v6_w_mask(): + src = { + ('Loopback0', 'fc00::/128'): {}, + ('Loopback1', 'fc00::1/128'): {}, + } + expected = OrderedDict( + [ + (('Loopback0', 'fc00::/128'), {}), + (('Loopback1', 'fc00::1/128'), {}), + ] + ) + res = TemplateFabric.pfx_filter(src) + assert res == expected + +def test_pfx_filter_pfx_v4_no_mask(): + src = { + ('Loopback0', '11.11.11.11'): {}, + ('Loopback1', '55.55.55.55'): {}, + } + expected = OrderedDict( + [ + (('Loopback1', '55.55.55.55/32'), {}), + (('Loopback0', '11.11.11.11/32'), {}), + ] + ) + res = TemplateFabric.pfx_filter(src) + assert res == expected + +def test_pfx_filter_pfx_v6_no_mask(): + src = { + ('Loopback0', 'fc00::'): {}, + ('Loopback1', 'fc00::1'): {}, + } + expected = OrderedDict( + [ + (('Loopback0', 'fc00::/128'), {}), + (('Loopback1', 'fc00::1/128'), {}), + ] + ) + res = TemplateFabric.pfx_filter(src) + assert res == expected + + +def test_pfx_filter_pfx_comprehensive(): + src = { + 'Loopback0': {}, + ('Loopback0', 'fc00::'): {}, + 'Loopback1': {}, + ('Loopback1', 'fc00::1/128'): {}, + ('Loopback2', '11.11.11.11/32'): {}, + ('Loopback3', '55.55.55.55'): {}, + 'Loopback2': {}, + 'Loopback3': {}, + ('Loopback5', '22.22.22.1/24'): {}, + ('Loopback6', 'fc00::55/64'): {}, + } + expected = OrderedDict( + [ + (('Loopback1', 'fc00::1/128'), {}), + (('Loopback3', '55.55.55.55/32'), {}), + (('Loopback6', 'fc00::55/64'), {}), + (('Loopback2', '11.11.11.11/32'), {}), + (('Loopback0', 'fc00::/128'), {}), + (('Loopback5', '22.22.22.1/24'), {}), + ] + ) + res = TemplateFabric.pfx_filter(src) + assert res == expected + +@pytest.fixture +def test_pfx_filter_wrong_ip(caplog): + src = { + ('Loopback0', 'wrong_ip'): {}, + } + res = TemplateFabric.pfx_filter(src) + assert "'wrong_ip' is invalid ip address" in caplog.text + assert isinstance(res, OrderedDict) and len(res) == 0 + diff --git a/src/sonic-bgpcfgd/tests/test_sonic-cfggen.py b/src/sonic-bgpcfgd/tests/test_sonic-cfggen.py new file mode 100644 index 000000000000..065ecb815ccb --- /dev/null +++ b/src/sonic-bgpcfgd/tests/test_sonic-cfggen.py @@ -0,0 +1,133 @@ +import os +import subprocess + + +from app.config import ConfigMgr +from .test_templates import compress_comments, write_result + + +TEMPLATE_PATH = os.path.abspath('../../dockers/docker-fpm-frr/frr') +DATA_PATH = "tests/data/sonic-cfggen/" +CONSTANTS_PATH = os.path.abspath('../../files/image_config/constants/constants.yml') + + +def run_test(name, template_path, json_path, match_path): + template_path = os.path.join(TEMPLATE_PATH, template_path) + json_path = os.path.join(DATA_PATH, json_path) + cfggen = os.path.abspath("../sonic-config-engine/sonic-cfggen") + command = [cfggen, "-T", TEMPLATE_PATH, "-t", template_path, "-y", json_path] + p = subprocess.Popen(command, shell=False, stdout=subprocess.PIPE, stderr=subprocess.PIPE) + stdout, stderr = p.communicate() + assert p.returncode == 0, "sonic-cfggen for %s test returned %d code. stderr='%s'" % (name, p.returncode, stderr) + raw_generated_result = stdout + assert "None" not in raw_generated_result, "Test %s" % name + canonical_generated_result = ConfigMgr.to_canonical(raw_generated_result) + match_path = os.path.join(DATA_PATH, match_path) + # only for development write_result(match_path, raw_generated_result) + with open(match_path) as result_fp: + raw_saved_result = result_fp.read() + canonical_saved_result = ConfigMgr.to_canonical(raw_saved_result) + assert canonical_saved_result == canonical_generated_result, "Test %s" % name + + +def test_bgpd_main_conf_base(): + run_test("Base bgpd.main.conf.j2", + "bgpd/bgpd.main.conf.j2", + "bgpd.main.conf.j2/base.json", + "bgpd.main.conf.j2/base.conf") + +def test_bgpd_main_conf_comprehensive(): + run_test("Comprehensive bgpd.main.conf.j2", + "bgpd/bgpd.main.conf.j2", + "bgpd.main.conf.j2/all.json", + "bgpd.main.conf.j2/all.conf") + +def test_bgpd_main_conf_defaults(): + run_test("Defaults bgpd.main.conf.j2", + "bgpd/bgpd.main.conf.j2", + "bgpd.main.conf.j2/defaults.json", + "bgpd.main.conf.j2/defaults.conf") + +def test_tsa_isolate(): + run_test("tsa/bgpd.tsa.isolate.conf.j2", + "bgpd/tsa/bgpd.tsa.isolate.conf.j2", + "tsa/isolate.json", + "tsa/isolate.conf") + +def test_tsa_unisolate(): + run_test("tsa/bgpd.tsa.unisolate.conf.j2", + "bgpd/tsa/bgpd.tsa.unisolate.conf.j2", + "tsa/unisolate.json", + "tsa/unisolate.conf") + +def test_common_daemons(): + run_test("daemons.common.conf.j2", + "common/daemons.common.conf.j2", + "common/daemons.common.conf.json", + "common/daemons.common.conf") + +def test_common_functions(): + run_test("functions.conf.j2", + "common/functions.conf.j2", + "common/functions.conf.json", + "common/functions.conf") + +def test_staticd_default_route(): + run_test("staticd.default_route.conf.j2", + "staticd/staticd.default_route.conf.j2", + "staticd/staticd.default_route.conf.json", + "staticd/staticd.default_route.conf") + +def test_staticd(): + run_test("staticd.conf.j2", + "staticd/staticd.conf.j2", + "staticd/staticd.conf.json", + "staticd/staticd.conf") + +def test_zebra_interfaces(): + run_test("zebra.interfaces.conf.j2", + "zebra/zebra.interfaces.conf.j2", + "zebra/interfaces.json", + "zebra/interfaces.conf") + +def test_zebra_set_src(): + run_test("zebra.set_src.conf.j2", + "zebra/zebra.set_src.conf.j2", + "zebra/set_src.json", + "zebra/set_src.conf") + +def test_zebra(): + run_test("zebra.conf.j2", + "zebra/zebra.conf.j2", + "zebra/zebra.conf.json", + "zebra/zebra.conf") + +def test_isolate(): + run_test("isolate.j2", + "isolate.j2", + "isolate/isolate.json", + "isolate/isolate") + +def test_unisolate(): + run_test("unisolate.j2", + "unisolate.j2", + "isolate/unisolate.json", + "isolate/unisolate") + +def test_frr_conf(): + run_test("frr.conf.j2", + "frr.conf.j2", + "frr.conf.j2/all.json", + "frr.conf.j2/all.conf") + +def test_l3vpn_base(): + run_test("bgpd spine_chassis_frontend_router.conf.j2", + "bgpd/bgpd.spine_chassis_frontend_router.conf.j2", + "bgpd.spine_chassis_frontend_router.conf.j2/base.json", + "bgpd.spine_chassis_frontend_router.conf.j2/base.conf") + +def test_bgp_conf_all(): + run_test("bgpd/bgpd.conf", + "bgpd/bgpd.conf.j2", + "bgpd.conf.j2/all.json", + "bgpd.conf.j2/all.conf") diff --git a/src/sonic-bgpcfgd/tests/test_templates.py b/src/sonic-bgpcfgd/tests/test_templates.py new file mode 100644 index 000000000000..bd0bf9dbb484 --- /dev/null +++ b/src/sonic-bgpcfgd/tests/test_templates.py @@ -0,0 +1,129 @@ +import os +import json + + +from app.template import TemplateFabric +from app.config import ConfigMgr +from .util import load_constants + +TEMPLATE_PATH = os.path.abspath('../../dockers/docker-fpm-frr/frr') + + +def load_tests(peer_type, template_name): + constants = load_constants() + path = "tests/data/%s/%s" % (constants[peer_type], template_name) + param_files = [name for name in os.listdir(path) + if os.path.isfile(os.path.join(path, name)) and name.startswith("param_")] + tests = [] + for param_fname in param_files: + casename = param_fname.replace("param_", "").replace(".json", "") + result_fname = "result_%s.conf" % casename + full_param_fname = os.path.join(path, param_fname) + full_result_fname = os.path.join(path, result_fname) + tests.append((casename, full_param_fname, full_result_fname)) + tmpl_path = os.path.join("bgpd", "templates", constants[peer_type], "%s.j2" % template_name) + return tmpl_path, tests + +def load_json(fname): + with open(fname) as param_fp: + raw_params = json.load(param_fp) + params = {} + for table_key, table_entries in raw_params.items(): + if table_key.startswith("CONFIG_DB__"): + # convert CONFIG_DB__* entries keys into tuple if needed + new_table_entries = {} + for entry_key, entry_value in table_entries.items(): + if '|' in entry_key: + new_key = tuple(entry_key.split('|')) + else: + new_key = entry_key + new_table_entries[new_key] = entry_value + params[table_key] = new_table_entries + else: + params[table_key] = table_entries + return params + +def compress_comments(raw_config): + comment_counter = 0 + output = [] + for line in raw_config.split('\n'): + stripped_line = line.strip() + # Skip empty lines + if stripped_line == '': + pass + # Write lines without comments + elif not stripped_line.startswith('!'): + if comment_counter > 0: + output.append("!") + comment_counter = 0 + output.append(line) + # Write non-empty comments + elif stripped_line.startswith('!') and len(stripped_line) > 1: + if comment_counter > 0: + output.append("!") + comment_counter = 0 + output.append(line) + # Count empty comments + else: # stripped_line == '!' + comment_counter += 1 + # Flush last comment if we have one + if comment_counter > 0: + output.append("!") + return "\n".join(output) + "\n" + +def write_result(fname, raw_result): + with open(fname, 'w') as fp: + raw_result_w_commpressed_comments = compress_comments(raw_result) + fp.write(raw_result_w_commpressed_comments) + +def run_tests(test_name, template_fname, tests): + tf = TemplateFabric(TEMPLATE_PATH) + template = tf.from_file(template_fname) + for case_name, param_fname, result_fname in tests: + params = load_json(param_fname) + raw_generated_result = str(template.render(params)) + assert "None" not in raw_generated_result, "Test %s.%s" % (test_name, case_name) + # this is used only for initial generation write_result(result_fname, raw_generated_result) + canonical_generated_result = ConfigMgr.to_canonical(raw_generated_result) + with open(result_fname) as result_fp: + raw_saved_result = result_fp.read() + canonical_saved_result = ConfigMgr.to_canonical(raw_saved_result) + assert canonical_saved_result == canonical_generated_result, "Test %s.%s" % (test_name, case_name) + +# Tests + +def test_general_policies(): + test_data = load_tests("general", "policies.conf") + run_tests("general_policies", *test_data) + +def test_general_pg(): + test_data = load_tests("general", "peer-group.conf") + run_tests("general_pg", *test_data) + +def test_general_instance(): + test_data = load_tests("general", "instance.conf") + run_tests("general_instance", *test_data) + +def test_dynamic_policies(): + test_data = load_tests("dynamic", "policies.conf") + run_tests("dynamic_policies", *test_data) + +def test_dynamic_pg(): + test_data = load_tests("dynamic", "peer-group.conf") + run_tests("dynamic_pg", *test_data) + +def test_dynamic_instance(): + test_data = load_tests("dynamic", "instance.conf") + run_tests("dynamic_instance", *test_data) + +def test_monitors_policies(): + test_data = load_tests("monitors", "policies.conf") + run_tests("monitors_policies", *test_data) + +def test_monitors_pg(): + test_data = load_tests("monitors", "peer-group.conf") + run_tests("monitors_pg", *test_data) + +def test_monitors_instance(): + test_data = load_tests("monitors", "instance.conf") + run_tests("monitors_instance", *test_data) diff --git a/src/sonic-bgpcfgd/tests/util.py b/src/sonic-bgpcfgd/tests/util.py new file mode 100644 index 000000000000..0bc12b060aec --- /dev/null +++ b/src/sonic-bgpcfgd/tests/util.py @@ -0,0 +1,16 @@ +import os +import yaml + +CONSTANTS_PATH = os.path.abspath('../../files/image_config/constants/constants.yml') + +def load_constants(): + with open(CONSTANTS_PATH) as f: + data = yaml.load(f) + result = {} + assert "constants" in data, "'constants' key not found in constants.yml" + assert "bgp" in data["constants"], "'bgp' key not found in constants.yml" + assert "peers" in data["constants"]["bgp"], "'peers' key not found in constants.yml" + for name, value in data["constants"]["bgp"]["peers"].items(): + assert "template_dir" in value, "'template_dir' key not found for peer '%s'" % name + result[name] = value["template_dir"] + return result \ No newline at end of file diff --git a/src/sonic-config-engine/minigraph.py b/src/sonic-config-engine/minigraph.py index 94ac39dbabde..2c079f1b472b 100644 --- a/src/sonic-config-engine/minigraph.py +++ b/src/sonic-config-engine/minigraph.py @@ -528,6 +528,7 @@ def parse_meta(meta, hname): erspan_dst = [] deployment_id = None region = None + cloudtype = None device_metas = meta.find(str(QName(ns, "Devices"))) for device in device_metas.findall(str(QName(ns1, "DeviceMetadata"))): if device.find(str(QName(ns1, "Name"))).text.lower() == hname.lower(): @@ -552,7 +553,9 @@ def parse_meta(meta, hname): deployment_id = value elif name == "Region": region = value - return syslog_servers, dhcp_servers, ntp_servers, tacacs_servers, mgmt_routes, erspan_dst, deployment_id, region + elif name == "CloudType": + cloudtype = value + return syslog_servers, dhcp_servers, ntp_servers, tacacs_servers, mgmt_routes, erspan_dst, deployment_id, region, cloudtype def parse_linkmeta(meta, hname): @@ -812,6 +815,7 @@ def parse_xml(filename, platform=None, port_config_file=None, asic_name=None): bgp_peers_with_range = None deployment_id = None region = None + cloudtype = None hostname = None linkmetas = {} @@ -847,7 +851,7 @@ def parse_xml(filename, platform=None, port_config_file=None, asic_name=None): elif child.tag == str(QName(ns, "UngDec")): (u_neighbors, u_devices, _, _, _, _, _, _) = parse_png(child, hostname) elif child.tag == str(QName(ns, "MetadataDeclaration")): - (syslog_servers, dhcp_servers, ntp_servers, tacacs_servers, mgmt_routes, erspan_dst, deployment_id, region) = parse_meta(child, hostname) + (syslog_servers, dhcp_servers, ntp_servers, tacacs_servers, mgmt_routes, erspan_dst, deployment_id, region, cloudtype) = parse_meta(child, hostname) elif child.tag == str(QName(ns, "LinkMetadataDeclaration")): linkmetas = parse_linkmeta(child, hostname) elif child.tag == str(QName(ns, "DeviceInfos")): @@ -879,6 +883,7 @@ def parse_xml(filename, platform=None, port_config_file=None, asic_name=None): 'bgp_asn': bgp_asn, 'deployment_id': deployment_id, 'region': region, + 'cloudtype': cloudtype, 'docker_routing_config_mode': docker_routing_config_mode, 'hostname': hostname, 'hwsku': hwsku, @@ -961,10 +966,7 @@ def parse_xml(filename, platform=None, port_config_file=None, asic_name=None): for port_name, port in ports.items(): # get port alias from port_config.ini - if port_config_file: - alias = port.get('alias') - else: - alias = port_name + alias = port.get('alias', port_name) # generate default 100G FEC # Note: FECDisabled only be effective on 100G port right now if port.get('speed') == '100000' and linkmetas.get(alias, {}).get('FECDisabled', '').lower() != 'true': diff --git a/src/sonic-config-engine/sonic-cfggen b/src/sonic-config-engine/sonic-cfggen index 2e0ad43d5899..c449bb1d17b4 100755 --- a/src/sonic-config-engine/sonic-cfggen +++ b/src/sonic-config-engine/sonic-cfggen @@ -16,6 +16,8 @@ See usage string for detail description for arguments. """ from __future__ import print_function +import sys +sys.path.insert(0, "/usr/local/lib/python2.7/dist-packages") # monkey patch re.compile to do lazy regular expression compilation. # This is done to improve import time of jinja2, yaml, natsort modules, because they @@ -43,6 +45,7 @@ from sonic_device_util import get_machine_info from sonic_device_util import get_platform_info from sonic_device_util import get_system_mac from sonic_device_util import get_npu_id_from_name +from sonic_device_util import get_npu_device_id from config_samples import generate_sample_config from config_samples import get_available_config from swsssdk import SonicV2Connector, ConfigDBConnector, SonicDBConfig @@ -113,7 +116,17 @@ def pfx_filter(value): for key,val in value.items(): if not isinstance(key, tuple): continue - table[key] = val + intf, ip_address = key + if '/' not in ip_address: + if is_ipv4(ip_address): + new_ip_address = "%s/32" % ip_address + elif is_ipv6(ip_address): + new_ip_address = "%s/128" % ip_address + else: + raise ValueError("'%s' is invalid ip address" % ip_address) + table[(intf, new_ip_address)] = val + else: + table[key] = val return table def ip_network(value): @@ -304,7 +317,12 @@ def main(): }}} # The ID needs to be passed to the SAI to identify the asic. if asic_name is not None: - hardware_data['DEVICE_METADATA']['localhost'].update(asic_id=asic_id) + device_id = get_npu_device_id(asic_id) + # if the device_id obtained is None, exit with error + if device_id is None: + print('Failed to get device ID for', asic_name, file=sys.stderr) + sys.exit(1) + hardware_data['DEVICE_METADATA']['localhost'].update(asic_id=device_id) deep_update(data, hardware_data) if args.template is not None: diff --git a/src/sonic-config-engine/sonic_device_util.py b/src/sonic-config-engine/sonic_device_util.py index cf1edfd59bfb..1bdf33162dac 100644 --- a/src/sonic-config-engine/sonic_device_util.py +++ b/src/sonic-config-engine/sonic_device_util.py @@ -44,6 +44,32 @@ def get_npu_id_from_name(npu_name): else: return None +def get_npu_device_id(npu_id): + platform = get_platform_info(get_machine_info()) + if not platform: + return None + + asic_conf_file_path = os.path.join(SONIC_DEVICE_PATH, platform, ASIC_CONF_FILENAME) + if not os.path.isfile(asic_conf_file_path): + return None + + # In a multi-npu device we need to have the file "asic.conf" updated with the asic instance + # and the corresponding device id which could be pci_id. Below is an eg: for a 2 ASIC platform/sku. + # DEV_ID_ASIC_0=03:00.0 + # DEV_ID_ASIC_1=04:00.0 + device_str = "DEV_ID_ASIC_{}".format(npu_id) + + with open(asic_conf_file_path) as asic_conf_file: + for line in asic_conf_file: + tokens = line.split('=') + if len(tokens) < 2: + continue + if tokens[0] == device_str: + device_id = tokens[1].strip() + return device_id + + return None + def get_num_npus(): platform = get_platform_info(get_machine_info()) if not platform: diff --git a/src/sonic-config-engine/tests/data/pfx_filter/param_1.json b/src/sonic-config-engine/tests/data/pfx_filter/param_1.json new file mode 100644 index 000000000000..ce6cd21886a2 --- /dev/null +++ b/src/sonic-config-engine/tests/data/pfx_filter/param_1.json @@ -0,0 +1,12 @@ +{ + "VLAN_INTERFACE": { + "Vlan1": {}, + "Vlan1|1.1.1.1/32": {}, + "Vlan2": {}, + "Vlan2|2.2.2.2": {}, + "Vlan3": {}, + "Vlan3|fc00::1": {}, + "Vlan4": {}, + "Vlan4|fc00::2/64": {} + } +} diff --git a/src/sonic-config-engine/tests/data/pfx_filter/result_1.txt b/src/sonic-config-engine/tests/data/pfx_filter/result_1.txt new file mode 100644 index 000000000000..d8ea7d304222 --- /dev/null +++ b/src/sonic-config-engine/tests/data/pfx_filter/result_1.txt @@ -0,0 +1,5 @@ +"Vlan1"="1.1.1.1/32" +"Vlan2"="2.2.2.2/32" +"Vlan3"="fc00::1/128" +"Vlan4"="fc00::2/64" + diff --git a/src/sonic-config-engine/tests/data/pfx_filter/tmpl_1.txt.j2 b/src/sonic-config-engine/tests/data/pfx_filter/tmpl_1.txt.j2 new file mode 100644 index 000000000000..2612fe4a2936 --- /dev/null +++ b/src/sonic-config-engine/tests/data/pfx_filter/tmpl_1.txt.j2 @@ -0,0 +1,3 @@ +{% for intf, addr in VLAN_INTERFACE|pfx_filter %} +"{{ intf }}"="{{ addr }}" +{% endfor %} diff --git a/src/sonic-config-engine/tests/simple-sample-graph-metadata.xml b/src/sonic-config-engine/tests/simple-sample-graph-metadata.xml index db103e13480d..4bde42cdda3a 100644 --- a/src/sonic-config-engine/tests/simple-sample-graph-metadata.xml +++ b/src/sonic-config-engine/tests/simple-sample-graph-metadata.xml @@ -220,6 +220,11 @@ usfoo + + CloudType + + Public + ErspanDestinationIpv4 diff --git a/src/sonic-config-engine/tests/test_cfggen.py b/src/sonic-config-engine/tests/test_cfggen.py index 816575f84171..66ca26f3250e 100644 --- a/src/sonic-config-engine/tests/test_cfggen.py +++ b/src/sonic-config-engine/tests/test_cfggen.py @@ -58,6 +58,11 @@ def test_minigraph_region(self): output = self.run_script(argument) self.assertEqual(output.strip(), 'usfoo') + def test_minigraph_cloudtype(self): + argument = '-v "DEVICE_METADATA[\'localhost\'][\'cloudtype\']" -m "' + self.sample_graph_metadata + '"' + output = self.run_script(argument) + self.assertEqual(output.strip(), 'Public') + def test_print_data(self): argument = '-m "' + self.sample_graph + '" --print-data' output = self.run_script(argument) diff --git a/src/sonic-config-engine/tests/test_cfggen_pfx_filter.py b/src/sonic-config-engine/tests/test_cfggen_pfx_filter.py new file mode 100644 index 000000000000..8ffd72907b21 --- /dev/null +++ b/src/sonic-config-engine/tests/test_cfggen_pfx_filter.py @@ -0,0 +1,15 @@ +from unittest import TestCase +import subprocess + +class TestPfxFilter(TestCase): + def test_comprehensive(self): + # Generate output + data_dir = "tests/data/pfx_filter" + cmd = "./sonic-cfggen -j %s/param_1.json -t %s/tmpl_1.txt.j2 > /tmp/result_1.txt" % (data_dir, data_dir) + subprocess.check_output(cmd, shell=True) + # Compare outputs + cmd = "diff -u tests/data/pfx_filter/result_1.txt /tmp/result_1.txt" + try: + res = subprocess.check_output(cmd, shell=True) + except subprocess.CalledProcessError as e: + assert False, "Wrong output. return code: %d, Diff: %s" % (e.returncode, e.output) diff --git a/src/sonic-daemon-base/sonic_daemon_base/daemon_base.py b/src/sonic-daemon-base/sonic_daemon_base/daemon_base.py index d3807bf91524..205bc9e57f40 100644 --- a/src/sonic-daemon-base/sonic_daemon_base/daemon_base.py +++ b/src/sonic-daemon-base/sonic_daemon_base/daemon_base.py @@ -13,6 +13,7 @@ # # Constants ==================================================================== # +REDIS_TIMEOUT_MSECS = 0 # Redis DB information REDIS_HOSTNAME = 'localhost' diff --git a/src/sonic-daemon-base/sonic_daemon_base/task_base.py b/src/sonic-daemon-base/sonic_daemon_base/task_base.py new file mode 100644 index 000000000000..e1738ffba213 --- /dev/null +++ b/src/sonic-daemon-base/sonic_daemon_base/task_base.py @@ -0,0 +1,50 @@ +import multiprocessing +import os +import signal +import threading + + +# +# ProcessTaskBase ===================================================================== +# +class ProcessTaskBase(object): # TODO: put this class to swss-platform-common + def __init__(self): + self.task_process = None + self.task_stopping_event = multiprocessing.Event() + + def task_worker(self): + pass + + def task_run(self): + if self.task_stopping_event.is_set(): + return + + self.task_process = multiprocessing.Process(target=self.task_worker) + self.task_process.start() + + def task_stop(self): + self.task_stopping_event.set() + os.kill(self.task_process.pid, signal.SIGKILL) + + +# +# ThreadTaskBase ===================================================================== +# +class ThreadTaskBase(object): # TODO: put this class to swss-platform-common; + def __init__(self): + self.task_thread = None + self.task_stopping_event = threading.Event() + + def task_worker(self): + pass + + def task_run(self): + if self.task_stopping_event.is_set(): + return + + self.task_thread = threading.Thread(target=self.task_worker) + self.task_thread.start() + + def task_stop(self): + self.task_stopping_event.set() + self.task_thread.join() diff --git a/src/sonic-dbsyncd b/src/sonic-dbsyncd index ffb3bad2f355..399ac217c6d0 160000 --- a/src/sonic-dbsyncd +++ b/src/sonic-dbsyncd @@ -1 +1 @@ -Subproject commit ffb3bad2f355c28be201d5f27ac4564c46047593 +Subproject commit 399ac217c6d0c6e2397cb690e6d30b7c56aa52d3 diff --git a/src/sonic-frr/patch/0005-nexthops-compare-vrf-only-if-ip-type.patch b/src/sonic-frr/patch/0005-nexthops-compare-vrf-only-if-ip-type.patch new file mode 100644 index 000000000000..343f1b3262d9 --- /dev/null +++ b/src/sonic-frr/patch/0005-nexthops-compare-vrf-only-if-ip-type.patch @@ -0,0 +1,73 @@ +From 2f0b5aef66316b47d2cc8ac18453600621a6a317 Mon Sep 17 00:00:00 2001 +From: Tyler Li +Date: Thu, 14 Nov 2019 23:46:52 -0800 +Subject: [PATCH] nexthops compare vrf only if ip type + +--- + lib/nexthop.c | 12 ++++++------ + lib/zclient.c | 12 ++++++------ + 2 files changed, 12 insertions(+), 12 deletions(-) + +diff --git a/lib/nexthop.c b/lib/nexthop.c +index cf5bed3d6..7d9f646c9 100644 +--- a/lib/nexthop.c ++++ b/lib/nexthop.c +@@ -105,12 +105,6 @@ static int _nexthop_cmp_no_labels(const struct nexthop *next1, + { + int ret = 0; + +- if (next1->vrf_id < next2->vrf_id) +- return -1; +- +- if (next1->vrf_id > next2->vrf_id) +- return 1; +- + if (next1->type < next2->type) + return -1; + +@@ -120,6 +114,12 @@ static int _nexthop_cmp_no_labels(const struct nexthop *next1, + switch (next1->type) { + case NEXTHOP_TYPE_IPV4: + case NEXTHOP_TYPE_IPV6: ++ if (next1->vrf_id < next2->vrf_id) ++ return -1; ++ ++ if (next1->vrf_id > next2->vrf_id) ++ return 1; ++ + ret = _nexthop_gateway_cmp(next1, next2); + if (ret != 0) + return ret; +diff --git a/lib/zclient.c b/lib/zclient.c +index c739af043..0d37c46d1 100644 +--- a/lib/zclient.c ++++ b/lib/zclient.c +@@ -783,12 +783,6 @@ static int zapi_nexthop_cmp_no_labels(const struct zapi_nexthop *next1, + { + int ret = 0; + +- if (next1->vrf_id < next2->vrf_id) +- return -1; +- +- if (next1->vrf_id > next2->vrf_id) +- return 1; +- + if (next1->type < next2->type) + return -1; + +@@ -798,6 +792,12 @@ static int zapi_nexthop_cmp_no_labels(const struct zapi_nexthop *next1, + switch (next1->type) { + case NEXTHOP_TYPE_IPV4: + case NEXTHOP_TYPE_IPV6: ++ if (next1->vrf_id < next2->vrf_id) ++ return -1; ++ ++ if (next1->vrf_id > next2->vrf_id) ++ return 1; ++ + ret = nexthop_g_addr_cmp(next1->type, &next1->gate, + &next2->gate); + if (ret != 0) +-- +2.11.0 + diff --git a/src/sonic-frr/patch/series b/src/sonic-frr/patch/series index 233021ace50b..13619c87ff65 100644 --- a/src/sonic-frr/patch/series +++ b/src/sonic-frr/patch/series @@ -2,4 +2,5 @@ 0002-Reduce-severity-of-Vty-connected-from-message.patch 0003-Use-vrf_id-for-vrf-not-tabled_id.patch 0004-Allow-BGP-attr-NEXT_HOP-to-be-0.0.0.0-due-to-allevia.patch +0005-nexthops-compare-vrf-only-if-ip-type.patch 0006-changes-for-making-snmp-socket-non-blocking.patch diff --git a/src/sonic-linux-kernel b/src/sonic-linux-kernel index ea9e81d95c26..5117d43d49d3 160000 --- a/src/sonic-linux-kernel +++ b/src/sonic-linux-kernel @@ -1 +1 @@ -Subproject commit ea9e81d95c269799e991e22cb5797e6da421a3ce +Subproject commit 5117d43d49d3d9526eed97002281cfee23049d80 diff --git a/src/sonic-platform-common b/src/sonic-platform-common index 3fe07066892a..5d7e8aad7e4c 160000 --- a/src/sonic-platform-common +++ b/src/sonic-platform-common @@ -1 +1 @@ -Subproject commit 3fe07066892aba5ae3e8f5f0ffd5163ffc578b31 +Subproject commit 5d7e8aad7e4c5220206613c0fda04070502628d5 diff --git a/src/sonic-platform-daemons b/src/sonic-platform-daemons index 364ae4254ba4..74ffbd6c115c 160000 --- a/src/sonic-platform-daemons +++ b/src/sonic-platform-daemons @@ -1 +1 @@ -Subproject commit 364ae4254ba4d770fffa1286e2219841571c78b5 +Subproject commit 74ffbd6c115c345d59909189604e3c02fb72edf3 diff --git a/src/sonic-restapi b/src/sonic-restapi index 95e6bf8dcbf9..ed640ac1f917 160000 --- a/src/sonic-restapi +++ b/src/sonic-restapi @@ -1 +1 @@ -Subproject commit 95e6bf8dcbf9a3052c01cb8264f0a750eda91625 +Subproject commit ed640ac1f917f52c2298c0b799fb6a6cfbecccb4 diff --git a/src/sonic-sairedis b/src/sonic-sairedis index 0305b7fb531b..b3f4f984be87 160000 --- a/src/sonic-sairedis +++ b/src/sonic-sairedis @@ -1 +1 @@ -Subproject commit 0305b7fb531b60fafc42c16aecfed9a6701be870 +Subproject commit b3f4f984be874ec4b70ee0782b9d96bbab0e2384 diff --git a/src/sonic-swss b/src/sonic-swss index 62d4af4f1e0b..a153622725d4 160000 --- a/src/sonic-swss +++ b/src/sonic-swss @@ -1 +1 @@ -Subproject commit 62d4af4f1e0bd4115ba139a215847294c9f3a90a +Subproject commit a153622725d4518155a24d2807c31dbcdc85d317 diff --git a/src/sonic-swss-common b/src/sonic-swss-common index e81e661cea0d..9a1e2b727cf2 160000 --- a/src/sonic-swss-common +++ b/src/sonic-swss-common @@ -1 +1 @@ -Subproject commit e81e661cea0dbf441f9576013b9e9485de0e4c45 +Subproject commit 9a1e2b727cf208c70fa96562757b41aee433f797 diff --git a/src/sonic-utilities b/src/sonic-utilities index 3d77d5a9c49d..1149792b054d 160000 --- a/src/sonic-utilities +++ b/src/sonic-utilities @@ -1 +1 @@ -Subproject commit 3d77d5a9c49d764f9d7c479ec8446a2b8aec4925 +Subproject commit 1149792b054d3cf37f0fb034473db7f1b59c8380 diff --git a/src/sonic-ztp b/src/sonic-ztp index 374c9e804a9f..c93fb6d33250 160000 --- a/src/sonic-ztp +++ b/src/sonic-ztp @@ -1 +1 @@ -Subproject commit 374c9e804a9f434cdb58fa7afe0c3f6201bfe56f +Subproject commit c93fb6d332505562dbba351fedc638f187b32dde diff --git a/src/systemd-sonic-generator/systemd-sonic-generator.c b/src/systemd-sonic-generator/systemd-sonic-generator.c index 566d37ff0a4c..e801fcb229d2 100644 --- a/src/systemd-sonic-generator/systemd-sonic-generator.c +++ b/src/systemd-sonic-generator/systemd-sonic-generator.c @@ -14,7 +14,7 @@ #define MAX_NUM_UNITS 128 #define MAX_BUF_SIZE 512 -static const char* UNIT_FILE_PREFIX = "/etc/systemd/system/"; +static const char* UNIT_FILE_PREFIX = "/usr/lib/systemd/system/"; static const char* CONFIG_FILE = "/etc/sonic/generated_services.conf"; static const char* MACHINE_CONF_FILE = "/host/machine.conf"; static int num_asics; @@ -147,12 +147,16 @@ static void replace_multi_inst_dep(char *src) { char *line_copy; char *service_name; char *type; + char *save_ptr1 = NULL; + char *save_ptr2 = NULL; ssize_t nread; bool section_done = false; char tmp_file_path[PATH_MAX]; - /* assumes that the service files has 3 sections, + /* Assumes that the service files has 3 sections, * in the order: Unit, Service and Install. + * Assumes that the timer file has 3 sectiosn, + * in the order: Unit, Timer and Install. * Read service dependency from Unit and Install * sections, replace if dependent on multi instance * service. @@ -162,30 +166,31 @@ static void replace_multi_inst_dep(char *src) { fp_tmp = fopen(tmp_file_path, "w"); while ((nread = getline(&line, &len, fp_src)) != -1 ) { - if (strstr(line, "[Service]") != NULL) { + if ((strstr(line, "[Service]") != NULL) || + (strstr(line, "[Timer]") != NULL)) { section_done = true; fputs(line,fp_tmp); - } else if (strstr(line, "[Install]") != NULL) { + } else if (strstr(line, "[Install]") != NULL) { section_done = false; fputs(line,fp_tmp); } else if ((strstr(line, "[Unit]") != NULL) || (strstr(line, "Description") != NULL) || - (section_done == true)){ + (section_done == true)) { fputs(line,fp_tmp); } else { line_copy = strdup(line); - token = strtok(line_copy, "="); - while ((word = strtok(NULL, " "))){ + token = strtok_r(line_copy, "=", &save_ptr1); + while ((word = strtok_r(NULL, " ", &save_ptr1))) { if((strchr(word, '.') == NULL) || (strchr(word, '@') != NULL)) { snprintf(buf, MAX_BUF_SIZE,"%s=%s\n",token, word); fputs(buf,fp_tmp); } else { service_name = strdup(word); - service_name = strtok(service_name, "."); - type = strtok(NULL, " "); + service_name = strtok_r(service_name, ".", &save_ptr2); + type = strtok_r(NULL, " ", &save_ptr2); if (is_multi_instance_service(word)) { - for(i = 0; i < num_asics; i++){ + for(i = 0; i < num_asics; i++) { snprintf(buf, MAX_BUF_SIZE, "%s=%s@%d.%s\n", token, service_name, i, type); fputs(buf,fp_tmp); @@ -513,7 +518,7 @@ static int get_num_of_asic() { while ((nread = getline(&line, &len, fp)) != -1) { if ((strstr(line, "onie_platform") != NULL) || - (strstr(line, "aboot_platform") != NULL)) { + (strstr(line, "aboot_platform") != NULL)) { token = strtok(line, "="); platform = strtok(NULL, "="); strip_trailing_newline(platform); @@ -580,7 +585,7 @@ int main(int argc, char **argv) { // For each unit file, get the installation targets and install the unit for (int i = 0; i < num_unit_files; i++) { - unit_instance = strdup(unit_files[i]); + unit_instance = strdup(unit_files[i]); if ((num_asics == 1) && strstr(unit_instance, "@") != NULL) { prefix = strtok(unit_instance, "@"); suffix = strtok(NULL, "@");