diff --git a/.gitmodules b/.gitmodules index dcc3740421ae..52e4e9f8042c 100644 --- a/.gitmodules +++ b/.gitmodules @@ -35,7 +35,7 @@ url = https://github.com/p4lang/ptf.git [submodule "src/sonic-utilities"] path = src/sonic-utilities - url = https://github.com/sonic-net/sonic-utilities + url = https://github.com/Azure/sonic-utilities.msft branch = 202205 [submodule "platform/broadcom/sonic-platform-modules-arista"] path = platform/broadcom/sonic-platform-modules-arista diff --git a/Makefile.work b/Makefile.work index 93c8546753ca..f090a49274bc 100644 --- a/Makefile.work +++ b/Makefile.work @@ -230,6 +230,23 @@ ifdef SONIC_BUILD_QUIETER DOCKER_RUN += -e "SONIC_BUILD_QUIETER=$(SONIC_BUILD_QUIETER)" endif +# Mount the Signing key and Certificate in the slave container +ifneq ($(SECURE_UPGRADE_DEV_SIGNING_KEY),) + DOCKER_RUN += -v $(SECURE_UPGRADE_DEV_SIGNING_KEY):$(SECURE_UPGRADE_DEV_SIGNING_KEY):ro +endif + +ifneq ($(SECURE_UPGRADE_DEV_SIGNING_CERT),) + DOCKER_RUN += -v $(SECURE_UPGRADE_DEV_SIGNING_CERT):$(SECURE_UPGRADE_DEV_SIGNING_CERT):ro +endif + +# Mount the Signing prod tool in the slave container +$(info "SECURE_UPGRADE_PROD_SIGNING_TOOL": "$(SECURE_UPGRADE_PROD_SIGNING_TOOL)") +ifneq ($(SECURE_UPGRADE_PROD_SIGNING_TOOL),) + SECURE_UPGRADE_PROD_SIGNING_TOOL_DST = /sonic/scripts/$(shell basename -- $(SECURE_UPGRADE_PROD_SIGNING_TOOL)) + DOCKER_RUN += -v $(SECURE_UPGRADE_PROD_SIGNING_TOOL):$(SECURE_UPGRADE_PROD_SIGNING_TOOL_DST):ro + SECURE_UPGRADE_PROD_SIGNING_TOOL := $(SECURE_UPGRADE_PROD_SIGNING_TOOL_DST) +endif + ifneq ($(SONIC_DPKG_CACHE_SOURCE),) DOCKER_RUN += -v "$(SONIC_DPKG_CACHE_SOURCE):/dpkg_cache:rw" endif @@ -392,6 +409,10 @@ SONIC_BUILD_INSTRUCTION := make \ BUILD_LOG_TIMESTAMP=$(BUILD_LOG_TIMESTAMP) \ SONIC_ENABLE_IMAGE_SIGNATURE=$(ENABLE_IMAGE_SIGNATURE) \ SONIC_ENABLE_SECUREBOOT_SIGNATURE=$(SONIC_ENABLE_SECUREBOOT_SIGNATURE) \ + SECURE_UPGRADE_MODE=$(SECURE_UPGRADE_MODE) \ + SECURE_UPGRADE_DEV_SIGNING_KEY=$(SECURE_UPGRADE_DEV_SIGNING_KEY) \ + SECURE_UPGRADE_DEV_SIGNING_CERT=$(SECURE_UPGRADE_DEV_SIGNING_CERT) \ + SECURE_UPGRADE_PROD_SIGNING_TOOL=$(SECURE_UPGRADE_PROD_SIGNING_TOOL) \ SONIC_DEFAULT_CONTAINER_REGISTRY=$(DEFAULT_CONTAINER_REGISTRY) \ ENABLE_HOST_SERVICE_ON_START=$(ENABLE_HOST_SERVICE_ON_START) \ SLAVE_DIR=$(SLAVE_DIR) \ diff --git a/build_debian.sh b/build_debian.sh index bac02a88a6ce..606a5df5f86a 100755 --- a/build_debian.sh +++ b/build_debian.sh @@ -154,7 +154,8 @@ if [[ $CONFIGURED_ARCH == amd64 ]]; then fi ## Sign the Linux kernel -if [ "$SONIC_ENABLE_SECUREBOOT_SIGNATURE" = "y" ]; then +# note: when flag SONIC_ENABLE_SECUREBOOT_SIGNATURE is enabled the Secure Upgrade flags should be disabled (no_sign) to avoid conflict between the features. +if [ "$SONIC_ENABLE_SECUREBOOT_SIGNATURE" = "y" ] && [ "$SECURE_UPGRADE_MODE" != 'dev' ] && [ "$SECURE_UPGRADE_MODE" != "prod" ]; then if [ ! -f $SIGNING_KEY ]; then echo "Error: SONiC linux kernel signing key missing" exit 1 @@ -629,6 +630,56 @@ then fi +# ################# +# secure boot +# ################# +if [[ $SECURE_UPGRADE_MODE == 'dev' || $SECURE_UPGRADE_MODE == "prod" && $SONIC_ENABLE_SECUREBOOT_SIGNATURE != 'y' ]]; then + # note: SONIC_ENABLE_SECUREBOOT_SIGNATURE is a feature that signing just kernel, + # SECURE_UPGRADE_MODE is signing all the boot component including kernel. + # its required to do not enable both features together to avoid conflicts. + echo "Secure Boot support build stage: Starting .." + + # debian secure boot dependecies + sudo LANG=C DEBIAN_FRONTEND=noninteractive chroot $FILESYSTEM_ROOT apt-get -y install \ + shim-unsigned \ + grub-efi + + if [ ! -f $SECURE_UPGRADE_DEV_SIGNING_CERT ]; then + echo "Error: SONiC SECURE_UPGRADE_DEV_SIGNING_CERT=$SECURE_UPGRADE_DEV_SIGNING_CERT key missing" + exit 1 + fi + + if [[ $SECURE_UPGRADE_MODE == 'dev' ]]; then + # development signing & verification + + if [ ! -f $SECURE_UPGRADE_DEV_SIGNING_KEY ]; then + echo "Error: SONiC SECURE_UPGRADE_DEV_SIGNING_KEY=$SECURE_UPGRADE_DEV_SIGNING_KEY key missing" + exit 1 + fi + + sudo ./scripts/signing_secure_boot_dev.sh -a $CONFIGURED_ARCH \ + -r $FILESYSTEM_ROOT \ + -l $LINUX_KERNEL_VERSION \ + -c $SECURE_UPGRADE_DEV_SIGNING_CERT \ + -p $SECURE_UPGRADE_DEV_SIGNING_KEY + elif [[ $SECURE_UPGRADE_MODE == "prod" ]]; then + # Here Vendor signing should be implemented + OUTPUT_SEC_BOOT_DIR=$FILESYSTEM_ROOT/boot + sudo $SECURE_UPGRADE_PROD_SIGNING_TOOL $CONFIGURED_ARCH $FILESYSTEM_ROOT $LINUX_KERNEL_VERSION $OUTPUT_SEC_BOOT_DIR + + # verifying all EFI files and kernel modules in $OUTPUT_SEC_BOOT_DIR + sudo ./scripts/secure_boot_signature_verification.sh -e $OUTPUT_SEC_BOOT_DIR \ + -c $SECURE_UPGRADE_DEV_SIGNING_CERT \ + -k $FILESYSTEM_ROOT + + # verifying vmlinuz file. + sudo ./scripts/secure_boot_signature_verification.sh -e $FILESYSTEM_ROOT/boot/vmlinuz-${LINUX_KERNEL_VERSION}-${CONFIGURED_ARCH} \ + -c $SECURE_UPGRADE_DEV_SIGNING_CERT \ + -k $FILESYSTEM_ROOT + fi + echo "Secure Boot support build stage: END." +fi + ## Update initramfs sudo chroot $FILESYSTEM_ROOT update-initramfs -u ## Convert initrd image to u-boot format diff --git a/device/arista/x86_64-arista_7800_sup/Arista-7804R3-FM/fabric_monitor_config.json b/device/arista/x86_64-arista_7800_sup/Arista-7804R3-FM/fabric_monitor_config.json new file mode 100644 index 000000000000..653b25d1e276 --- /dev/null +++ b/device/arista/x86_64-arista_7800_sup/Arista-7804R3-FM/fabric_monitor_config.json @@ -0,0 +1,8 @@ +{ + "FABRIC_MONITOR_DATA": { + "monErrThreshCrcCells": 1, + "monErrThreshRxCells": 61035156, + "monPollThreshRecovery": 8, + "monPollThreshIsolation": 1 + } +} diff --git a/device/arista/x86_64-arista_7800_sup/Arista-7804R3-FM/fabric_port_config.ini b/device/arista/x86_64-arista_7800_sup/Arista-7804R3-FM/fabric_port_config.ini new file mode 100644 index 000000000000..f9a60d04e5ea --- /dev/null +++ b/device/arista/x86_64-arista_7800_sup/Arista-7804R3-FM/fabric_port_config.ini @@ -0,0 +1,193 @@ +# name lanes isolateStatus +Fabric0 0 False +Fabric1 1 False +Fabric2 2 False +Fabric3 3 False +Fabric4 4 False +Fabric5 5 False +Fabric6 6 False +Fabric7 7 False +Fabric8 8 False +Fabric9 9 False +Fabric10 10 False +Fabric11 11 False +Fabric12 12 False +Fabric13 13 False +Fabric14 14 False +Fabric15 15 False +Fabric16 16 False +Fabric17 17 False +Fabric18 18 False +Fabric19 19 False +Fabric20 20 False +Fabric21 21 False +Fabric22 22 False +Fabric23 23 False +Fabric24 24 False +Fabric25 25 False +Fabric26 26 False +Fabric27 27 False +Fabric28 28 False +Fabric29 29 False +Fabric30 30 False +Fabric31 31 False +Fabric32 32 False +Fabric33 33 False +Fabric34 34 False +Fabric35 35 False +Fabric36 36 False +Fabric37 37 False +Fabric38 38 False +Fabric39 39 False +Fabric40 40 False +Fabric41 41 False +Fabric42 42 False +Fabric43 43 False +Fabric44 44 False +Fabric45 45 False +Fabric46 46 False +Fabric47 47 False +Fabric48 48 False +Fabric49 49 False +Fabric50 50 False +Fabric51 51 False +Fabric52 52 False +Fabric53 53 False +Fabric54 54 False +Fabric55 55 False +Fabric56 56 False +Fabric57 57 False +Fabric58 58 False +Fabric59 59 False +Fabric60 60 False +Fabric61 61 False +Fabric62 62 False +Fabric63 63 False +Fabric64 64 False +Fabric65 65 False +Fabric66 66 False +Fabric67 67 False +Fabric68 68 False +Fabric69 69 False +Fabric70 70 False +Fabric71 71 False +Fabric72 72 False +Fabric73 73 False +Fabric74 74 False +Fabric75 75 False +Fabric76 76 False +Fabric77 77 False +Fabric78 78 False +Fabric79 79 False +Fabric80 80 False +Fabric81 81 False +Fabric82 82 False +Fabric83 83 False +Fabric84 84 False +Fabric85 85 False +Fabric86 86 False +Fabric87 87 False +Fabric88 88 False +Fabric89 89 False +Fabric90 90 False +Fabric91 91 False +Fabric92 92 False +Fabric93 93 False +Fabric94 94 False +Fabric95 95 False +Fabric96 96 False +Fabric97 97 False +Fabric98 98 False +Fabric99 99 False +Fabric100 100 False +Fabric101 101 False +Fabric102 102 False +Fabric103 103 False +Fabric104 104 False +Fabric105 105 False +Fabric106 106 False +Fabric107 107 False +Fabric108 108 False +Fabric109 109 False +Fabric110 110 False +Fabric111 111 False +Fabric112 112 False +Fabric113 113 False +Fabric114 114 False +Fabric115 115 False +Fabric116 116 False +Fabric117 117 False +Fabric118 118 False +Fabric119 119 False +Fabric120 120 False +Fabric121 121 False +Fabric122 122 False +Fabric123 123 False +Fabric124 124 False +Fabric125 125 False +Fabric126 126 False +Fabric127 127 False +Fabric128 128 False +Fabric129 129 False +Fabric130 130 False +Fabric131 131 False +Fabric132 132 False +Fabric133 133 False +Fabric134 134 False +Fabric135 135 False +Fabric136 136 False +Fabric137 137 False +Fabric138 138 False +Fabric139 139 False +Fabric140 140 False +Fabric141 141 False +Fabric142 142 False +Fabric143 143 False +Fabric144 144 False +Fabric145 145 False +Fabric146 146 False +Fabric147 147 False +Fabric148 148 False +Fabric149 149 False +Fabric150 150 False +Fabric151 151 False +Fabric152 152 False +Fabric153 153 False +Fabric154 154 False +Fabric155 155 False +Fabric156 156 False +Fabric157 157 False +Fabric158 158 False +Fabric159 159 False +Fabric160 160 False +Fabric161 161 False +Fabric162 162 False +Fabric163 163 False +Fabric164 164 False +Fabric165 165 False +Fabric166 166 False +Fabric167 167 False +Fabric168 168 False +Fabric169 169 False +Fabric170 170 False +Fabric171 171 False +Fabric172 172 False +Fabric173 173 False +Fabric174 174 False +Fabric175 175 False +Fabric176 176 False +Fabric177 177 False +Fabric178 178 False +Fabric179 179 False +Fabric180 180 False +Fabric181 181 False +Fabric182 182 False +Fabric183 183 False +Fabric184 184 False +Fabric185 185 False +Fabric186 186 False +Fabric187 187 False +Fabric188 188 False +Fabric189 189 False +Fabric190 190 False +Fabric191 191 False diff --git a/device/arista/x86_64-arista_7800_sup/Arista-7808R3-FM/fabric_monitor_config.json b/device/arista/x86_64-arista_7800_sup/Arista-7808R3-FM/fabric_monitor_config.json new file mode 100644 index 000000000000..653b25d1e276 --- /dev/null +++ b/device/arista/x86_64-arista_7800_sup/Arista-7808R3-FM/fabric_monitor_config.json @@ -0,0 +1,8 @@ +{ + "FABRIC_MONITOR_DATA": { + "monErrThreshCrcCells": 1, + "monErrThreshRxCells": 61035156, + "monPollThreshRecovery": 8, + "monPollThreshIsolation": 1 + } +} diff --git a/device/arista/x86_64-arista_7800_sup/Arista-7808R3-FM/fabric_port_config.ini b/device/arista/x86_64-arista_7800_sup/Arista-7808R3-FM/fabric_port_config.ini new file mode 100644 index 000000000000..f9a60d04e5ea --- /dev/null +++ b/device/arista/x86_64-arista_7800_sup/Arista-7808R3-FM/fabric_port_config.ini @@ -0,0 +1,193 @@ +# name lanes isolateStatus +Fabric0 0 False +Fabric1 1 False +Fabric2 2 False +Fabric3 3 False +Fabric4 4 False +Fabric5 5 False +Fabric6 6 False +Fabric7 7 False +Fabric8 8 False +Fabric9 9 False +Fabric10 10 False +Fabric11 11 False +Fabric12 12 False +Fabric13 13 False +Fabric14 14 False +Fabric15 15 False +Fabric16 16 False +Fabric17 17 False +Fabric18 18 False +Fabric19 19 False +Fabric20 20 False +Fabric21 21 False +Fabric22 22 False +Fabric23 23 False +Fabric24 24 False +Fabric25 25 False +Fabric26 26 False +Fabric27 27 False +Fabric28 28 False +Fabric29 29 False +Fabric30 30 False +Fabric31 31 False +Fabric32 32 False +Fabric33 33 False +Fabric34 34 False +Fabric35 35 False +Fabric36 36 False +Fabric37 37 False +Fabric38 38 False +Fabric39 39 False +Fabric40 40 False +Fabric41 41 False +Fabric42 42 False +Fabric43 43 False +Fabric44 44 False +Fabric45 45 False +Fabric46 46 False +Fabric47 47 False +Fabric48 48 False +Fabric49 49 False +Fabric50 50 False +Fabric51 51 False +Fabric52 52 False +Fabric53 53 False +Fabric54 54 False +Fabric55 55 False +Fabric56 56 False +Fabric57 57 False +Fabric58 58 False +Fabric59 59 False +Fabric60 60 False +Fabric61 61 False +Fabric62 62 False +Fabric63 63 False +Fabric64 64 False +Fabric65 65 False +Fabric66 66 False +Fabric67 67 False +Fabric68 68 False +Fabric69 69 False +Fabric70 70 False +Fabric71 71 False +Fabric72 72 False +Fabric73 73 False +Fabric74 74 False +Fabric75 75 False +Fabric76 76 False +Fabric77 77 False +Fabric78 78 False +Fabric79 79 False +Fabric80 80 False +Fabric81 81 False +Fabric82 82 False +Fabric83 83 False +Fabric84 84 False +Fabric85 85 False +Fabric86 86 False +Fabric87 87 False +Fabric88 88 False +Fabric89 89 False +Fabric90 90 False +Fabric91 91 False +Fabric92 92 False +Fabric93 93 False +Fabric94 94 False +Fabric95 95 False +Fabric96 96 False +Fabric97 97 False +Fabric98 98 False +Fabric99 99 False +Fabric100 100 False +Fabric101 101 False +Fabric102 102 False +Fabric103 103 False +Fabric104 104 False +Fabric105 105 False +Fabric106 106 False +Fabric107 107 False +Fabric108 108 False +Fabric109 109 False +Fabric110 110 False +Fabric111 111 False +Fabric112 112 False +Fabric113 113 False +Fabric114 114 False +Fabric115 115 False +Fabric116 116 False +Fabric117 117 False +Fabric118 118 False +Fabric119 119 False +Fabric120 120 False +Fabric121 121 False +Fabric122 122 False +Fabric123 123 False +Fabric124 124 False +Fabric125 125 False +Fabric126 126 False +Fabric127 127 False +Fabric128 128 False +Fabric129 129 False +Fabric130 130 False +Fabric131 131 False +Fabric132 132 False +Fabric133 133 False +Fabric134 134 False +Fabric135 135 False +Fabric136 136 False +Fabric137 137 False +Fabric138 138 False +Fabric139 139 False +Fabric140 140 False +Fabric141 141 False +Fabric142 142 False +Fabric143 143 False +Fabric144 144 False +Fabric145 145 False +Fabric146 146 False +Fabric147 147 False +Fabric148 148 False +Fabric149 149 False +Fabric150 150 False +Fabric151 151 False +Fabric152 152 False +Fabric153 153 False +Fabric154 154 False +Fabric155 155 False +Fabric156 156 False +Fabric157 157 False +Fabric158 158 False +Fabric159 159 False +Fabric160 160 False +Fabric161 161 False +Fabric162 162 False +Fabric163 163 False +Fabric164 164 False +Fabric165 165 False +Fabric166 166 False +Fabric167 167 False +Fabric168 168 False +Fabric169 169 False +Fabric170 170 False +Fabric171 171 False +Fabric172 172 False +Fabric173 173 False +Fabric174 174 False +Fabric175 175 False +Fabric176 176 False +Fabric177 177 False +Fabric178 178 False +Fabric179 179 False +Fabric180 180 False +Fabric181 181 False +Fabric182 182 False +Fabric183 183 False +Fabric184 184 False +Fabric185 185 False +Fabric186 186 False +Fabric187 187 False +Fabric188 188 False +Fabric189 189 False +Fabric190 190 False +Fabric191 191 False diff --git a/device/arista/x86_64-arista_7800_sup/Arista-7808R3A-FM/fabric_monitor_config.json b/device/arista/x86_64-arista_7800_sup/Arista-7808R3A-FM/fabric_monitor_config.json new file mode 100644 index 000000000000..653b25d1e276 --- /dev/null +++ b/device/arista/x86_64-arista_7800_sup/Arista-7808R3A-FM/fabric_monitor_config.json @@ -0,0 +1,8 @@ +{ + "FABRIC_MONITOR_DATA": { + "monErrThreshCrcCells": 1, + "monErrThreshRxCells": 61035156, + "monPollThreshRecovery": 8, + "monPollThreshIsolation": 1 + } +} diff --git a/device/arista/x86_64-arista_7800_sup/Arista-7808R3A-FM/fabric_port_config.ini b/device/arista/x86_64-arista_7800_sup/Arista-7808R3A-FM/fabric_port_config.ini new file mode 100644 index 000000000000..f9a60d04e5ea --- /dev/null +++ b/device/arista/x86_64-arista_7800_sup/Arista-7808R3A-FM/fabric_port_config.ini @@ -0,0 +1,193 @@ +# name lanes isolateStatus +Fabric0 0 False +Fabric1 1 False +Fabric2 2 False +Fabric3 3 False +Fabric4 4 False +Fabric5 5 False +Fabric6 6 False +Fabric7 7 False +Fabric8 8 False +Fabric9 9 False +Fabric10 10 False +Fabric11 11 False +Fabric12 12 False +Fabric13 13 False +Fabric14 14 False +Fabric15 15 False +Fabric16 16 False +Fabric17 17 False +Fabric18 18 False +Fabric19 19 False +Fabric20 20 False +Fabric21 21 False +Fabric22 22 False +Fabric23 23 False +Fabric24 24 False +Fabric25 25 False +Fabric26 26 False +Fabric27 27 False +Fabric28 28 False +Fabric29 29 False +Fabric30 30 False +Fabric31 31 False +Fabric32 32 False +Fabric33 33 False +Fabric34 34 False +Fabric35 35 False +Fabric36 36 False +Fabric37 37 False +Fabric38 38 False +Fabric39 39 False +Fabric40 40 False +Fabric41 41 False +Fabric42 42 False +Fabric43 43 False +Fabric44 44 False +Fabric45 45 False +Fabric46 46 False +Fabric47 47 False +Fabric48 48 False +Fabric49 49 False +Fabric50 50 False +Fabric51 51 False +Fabric52 52 False +Fabric53 53 False +Fabric54 54 False +Fabric55 55 False +Fabric56 56 False +Fabric57 57 False +Fabric58 58 False +Fabric59 59 False +Fabric60 60 False +Fabric61 61 False +Fabric62 62 False +Fabric63 63 False +Fabric64 64 False +Fabric65 65 False +Fabric66 66 False +Fabric67 67 False +Fabric68 68 False +Fabric69 69 False +Fabric70 70 False +Fabric71 71 False +Fabric72 72 False +Fabric73 73 False +Fabric74 74 False +Fabric75 75 False +Fabric76 76 False +Fabric77 77 False +Fabric78 78 False +Fabric79 79 False +Fabric80 80 False +Fabric81 81 False +Fabric82 82 False +Fabric83 83 False +Fabric84 84 False +Fabric85 85 False +Fabric86 86 False +Fabric87 87 False +Fabric88 88 False +Fabric89 89 False +Fabric90 90 False +Fabric91 91 False +Fabric92 92 False +Fabric93 93 False +Fabric94 94 False +Fabric95 95 False +Fabric96 96 False +Fabric97 97 False +Fabric98 98 False +Fabric99 99 False +Fabric100 100 False +Fabric101 101 False +Fabric102 102 False +Fabric103 103 False +Fabric104 104 False +Fabric105 105 False +Fabric106 106 False +Fabric107 107 False +Fabric108 108 False +Fabric109 109 False +Fabric110 110 False +Fabric111 111 False +Fabric112 112 False +Fabric113 113 False +Fabric114 114 False +Fabric115 115 False +Fabric116 116 False +Fabric117 117 False +Fabric118 118 False +Fabric119 119 False +Fabric120 120 False +Fabric121 121 False +Fabric122 122 False +Fabric123 123 False +Fabric124 124 False +Fabric125 125 False +Fabric126 126 False +Fabric127 127 False +Fabric128 128 False +Fabric129 129 False +Fabric130 130 False +Fabric131 131 False +Fabric132 132 False +Fabric133 133 False +Fabric134 134 False +Fabric135 135 False +Fabric136 136 False +Fabric137 137 False +Fabric138 138 False +Fabric139 139 False +Fabric140 140 False +Fabric141 141 False +Fabric142 142 False +Fabric143 143 False +Fabric144 144 False +Fabric145 145 False +Fabric146 146 False +Fabric147 147 False +Fabric148 148 False +Fabric149 149 False +Fabric150 150 False +Fabric151 151 False +Fabric152 152 False +Fabric153 153 False +Fabric154 154 False +Fabric155 155 False +Fabric156 156 False +Fabric157 157 False +Fabric158 158 False +Fabric159 159 False +Fabric160 160 False +Fabric161 161 False +Fabric162 162 False +Fabric163 163 False +Fabric164 164 False +Fabric165 165 False +Fabric166 166 False +Fabric167 167 False +Fabric168 168 False +Fabric169 169 False +Fabric170 170 False +Fabric171 171 False +Fabric172 172 False +Fabric173 173 False +Fabric174 174 False +Fabric175 175 False +Fabric176 176 False +Fabric177 177 False +Fabric178 178 False +Fabric179 179 False +Fabric180 180 False +Fabric181 181 False +Fabric182 182 False +Fabric183 183 False +Fabric184 184 False +Fabric185 185 False +Fabric186 186 False +Fabric187 187 False +Fabric188 188 False +Fabric189 189 False +Fabric190 190 False +Fabric191 191 False diff --git a/device/arista/x86_64-arista_7800r3_48cq2_lc/Arista-7800R3-48CQ2-C48/fabric_monitor_config.json b/device/arista/x86_64-arista_7800r3_48cq2_lc/Arista-7800R3-48CQ2-C48/fabric_monitor_config.json new file mode 100644 index 000000000000..653b25d1e276 --- /dev/null +++ b/device/arista/x86_64-arista_7800r3_48cq2_lc/Arista-7800R3-48CQ2-C48/fabric_monitor_config.json @@ -0,0 +1,8 @@ +{ + "FABRIC_MONITOR_DATA": { + "monErrThreshCrcCells": 1, + "monErrThreshRxCells": 61035156, + "monPollThreshRecovery": 8, + "monPollThreshIsolation": 1 + } +} diff --git a/device/arista/x86_64-arista_7800r3_48cq2_lc/Arista-7800R3-48CQ2-C48/fabric_port_config.ini b/device/arista/x86_64-arista_7800r3_48cq2_lc/Arista-7800R3-48CQ2-C48/fabric_port_config.ini new file mode 100644 index 000000000000..e07e256dc169 --- /dev/null +++ b/device/arista/x86_64-arista_7800r3_48cq2_lc/Arista-7800R3-48CQ2-C48/fabric_port_config.ini @@ -0,0 +1,113 @@ +# name lanes isolateStatus +Fabric0 0 False +Fabric1 1 False +Fabric2 2 False +Fabric3 3 False +Fabric4 4 False +Fabric5 5 False +Fabric6 6 False +Fabric7 7 False +Fabric8 8 False +Fabric9 9 False +Fabric10 10 False +Fabric11 11 False +Fabric12 12 False +Fabric13 13 False +Fabric14 14 False +Fabric15 15 False +Fabric16 16 False +Fabric17 17 False +Fabric18 18 False +Fabric19 19 False +Fabric20 20 False +Fabric21 21 False +Fabric22 22 False +Fabric23 23 False +Fabric24 24 False +Fabric25 25 False +Fabric26 26 False +Fabric27 27 False +Fabric28 28 False +Fabric29 29 False +Fabric30 30 False +Fabric31 31 False +Fabric32 32 False +Fabric33 33 False +Fabric34 34 False +Fabric35 35 False +Fabric36 36 False +Fabric37 37 False +Fabric38 38 False +Fabric39 39 False +Fabric40 40 False +Fabric41 41 False +Fabric42 42 False +Fabric43 43 False +Fabric44 44 False +Fabric45 45 False +Fabric46 46 False +Fabric47 47 False +Fabric48 48 False +Fabric49 49 False +Fabric50 50 False +Fabric51 51 False +Fabric52 52 False +Fabric53 53 False +Fabric54 54 False +Fabric55 55 False +Fabric56 56 False +Fabric57 57 False +Fabric58 58 False +Fabric59 59 False +Fabric60 60 False +Fabric61 61 False +Fabric62 62 False +Fabric63 63 False +Fabric64 64 False +Fabric65 65 False +Fabric66 66 False +Fabric67 67 False +Fabric68 68 False +Fabric69 69 False +Fabric70 70 False +Fabric71 71 False +Fabric72 72 False +Fabric73 73 False +Fabric74 74 False +Fabric75 75 False +Fabric76 76 False +Fabric77 77 False +Fabric78 78 False +Fabric79 79 False +Fabric80 80 False +Fabric81 81 False +Fabric82 82 False +Fabric83 83 False +Fabric84 84 False +Fabric85 85 False +Fabric86 86 False +Fabric87 87 False +Fabric88 88 False +Fabric89 89 False +Fabric90 90 False +Fabric91 91 False +Fabric92 92 False +Fabric93 93 False +Fabric94 94 False +Fabric95 95 False +Fabric96 96 False +Fabric97 97 False +Fabric98 98 False +Fabric99 99 False +Fabric100 100 False +Fabric101 101 False +Fabric102 102 False +Fabric103 103 False +Fabric104 104 False +Fabric105 105 False +Fabric106 106 False +Fabric107 107 False +Fabric108 108 False +Fabric109 109 False +Fabric110 110 False +Fabric111 111 False diff --git a/device/arista/x86_64-arista_7800r3_48cq2_lc/Arista-7800R3-48CQ2-C48/port_config.ini b/device/arista/x86_64-arista_7800r3_48cq2_lc/Arista-7800R3-48CQ2-C48/port_config.ini index 07a78421dd4b..3f5543738aa6 100644 --- a/device/arista/x86_64-arista_7800r3_48cq2_lc/Arista-7800R3-48CQ2-C48/port_config.ini +++ b/device/arista/x86_64-arista_7800r3_48cq2_lc/Arista-7800R3-48CQ2-C48/port_config.ini @@ -1,4 +1,4 @@ -# name lanes alias index role speed asic_port_name coreId corePortId numVoq +# name lanes alias index role speed asic_port_name core_id core_port_id num_voq Ethernet0 6,7 Ethernet1/1 1 Ext 100000 Eth0 0 1 8 Ethernet4 2,3 Ethernet2/1 2 Ext 100000 Eth4 0 2 8 Ethernet8 4,5 Ethernet3/1 3 Ext 100000 Eth8 0 3 8 diff --git a/device/arista/x86_64-arista_7800r3_48cq2_lc/fabric_monitor_config.json b/device/arista/x86_64-arista_7800r3_48cq2_lc/fabric_monitor_config.json new file mode 100644 index 000000000000..653b25d1e276 --- /dev/null +++ b/device/arista/x86_64-arista_7800r3_48cq2_lc/fabric_monitor_config.json @@ -0,0 +1,8 @@ +{ + "FABRIC_MONITOR_DATA": { + "monErrThreshCrcCells": 1, + "monErrThreshRxCells": 61035156, + "monPollThreshRecovery": 8, + "monPollThreshIsolation": 1 + } +} diff --git a/device/arista/x86_64-arista_7800r3_48cq2_lc/fabric_port_config.ini b/device/arista/x86_64-arista_7800r3_48cq2_lc/fabric_port_config.ini new file mode 100644 index 000000000000..e07e256dc169 --- /dev/null +++ b/device/arista/x86_64-arista_7800r3_48cq2_lc/fabric_port_config.ini @@ -0,0 +1,113 @@ +# name lanes isolateStatus +Fabric0 0 False +Fabric1 1 False +Fabric2 2 False +Fabric3 3 False +Fabric4 4 False +Fabric5 5 False +Fabric6 6 False +Fabric7 7 False +Fabric8 8 False +Fabric9 9 False +Fabric10 10 False +Fabric11 11 False +Fabric12 12 False +Fabric13 13 False +Fabric14 14 False +Fabric15 15 False +Fabric16 16 False +Fabric17 17 False +Fabric18 18 False +Fabric19 19 False +Fabric20 20 False +Fabric21 21 False +Fabric22 22 False +Fabric23 23 False +Fabric24 24 False +Fabric25 25 False +Fabric26 26 False +Fabric27 27 False +Fabric28 28 False +Fabric29 29 False +Fabric30 30 False +Fabric31 31 False +Fabric32 32 False +Fabric33 33 False +Fabric34 34 False +Fabric35 35 False +Fabric36 36 False +Fabric37 37 False +Fabric38 38 False +Fabric39 39 False +Fabric40 40 False +Fabric41 41 False +Fabric42 42 False +Fabric43 43 False +Fabric44 44 False +Fabric45 45 False +Fabric46 46 False +Fabric47 47 False +Fabric48 48 False +Fabric49 49 False +Fabric50 50 False +Fabric51 51 False +Fabric52 52 False +Fabric53 53 False +Fabric54 54 False +Fabric55 55 False +Fabric56 56 False +Fabric57 57 False +Fabric58 58 False +Fabric59 59 False +Fabric60 60 False +Fabric61 61 False +Fabric62 62 False +Fabric63 63 False +Fabric64 64 False +Fabric65 65 False +Fabric66 66 False +Fabric67 67 False +Fabric68 68 False +Fabric69 69 False +Fabric70 70 False +Fabric71 71 False +Fabric72 72 False +Fabric73 73 False +Fabric74 74 False +Fabric75 75 False +Fabric76 76 False +Fabric77 77 False +Fabric78 78 False +Fabric79 79 False +Fabric80 80 False +Fabric81 81 False +Fabric82 82 False +Fabric83 83 False +Fabric84 84 False +Fabric85 85 False +Fabric86 86 False +Fabric87 87 False +Fabric88 88 False +Fabric89 89 False +Fabric90 90 False +Fabric91 91 False +Fabric92 92 False +Fabric93 93 False +Fabric94 94 False +Fabric95 95 False +Fabric96 96 False +Fabric97 97 False +Fabric98 98 False +Fabric99 99 False +Fabric100 100 False +Fabric101 101 False +Fabric102 102 False +Fabric103 103 False +Fabric104 104 False +Fabric105 105 False +Fabric106 106 False +Fabric107 107 False +Fabric108 108 False +Fabric109 109 False +Fabric110 110 False +Fabric111 111 False diff --git a/device/arista/x86_64-arista_7800r3_48cqm2_lc/Arista-7800R3-48CQM2-C48/fabric_monitor_config.json b/device/arista/x86_64-arista_7800r3_48cqm2_lc/Arista-7800R3-48CQM2-C48/fabric_monitor_config.json new file mode 100644 index 000000000000..653b25d1e276 --- /dev/null +++ b/device/arista/x86_64-arista_7800r3_48cqm2_lc/Arista-7800R3-48CQM2-C48/fabric_monitor_config.json @@ -0,0 +1,8 @@ +{ + "FABRIC_MONITOR_DATA": { + "monErrThreshCrcCells": 1, + "monErrThreshRxCells": 61035156, + "monPollThreshRecovery": 8, + "monPollThreshIsolation": 1 + } +} diff --git a/device/arista/x86_64-arista_7800r3_48cqm2_lc/Arista-7800R3-48CQM2-C48/fabric_port_config.ini b/device/arista/x86_64-arista_7800r3_48cqm2_lc/Arista-7800R3-48CQM2-C48/fabric_port_config.ini new file mode 100644 index 000000000000..e07e256dc169 --- /dev/null +++ b/device/arista/x86_64-arista_7800r3_48cqm2_lc/Arista-7800R3-48CQM2-C48/fabric_port_config.ini @@ -0,0 +1,113 @@ +# name lanes isolateStatus +Fabric0 0 False +Fabric1 1 False +Fabric2 2 False +Fabric3 3 False +Fabric4 4 False +Fabric5 5 False +Fabric6 6 False +Fabric7 7 False +Fabric8 8 False +Fabric9 9 False +Fabric10 10 False +Fabric11 11 False +Fabric12 12 False +Fabric13 13 False +Fabric14 14 False +Fabric15 15 False +Fabric16 16 False +Fabric17 17 False +Fabric18 18 False +Fabric19 19 False +Fabric20 20 False +Fabric21 21 False +Fabric22 22 False +Fabric23 23 False +Fabric24 24 False +Fabric25 25 False +Fabric26 26 False +Fabric27 27 False +Fabric28 28 False +Fabric29 29 False +Fabric30 30 False +Fabric31 31 False +Fabric32 32 False +Fabric33 33 False +Fabric34 34 False +Fabric35 35 False +Fabric36 36 False +Fabric37 37 False +Fabric38 38 False +Fabric39 39 False +Fabric40 40 False +Fabric41 41 False +Fabric42 42 False +Fabric43 43 False +Fabric44 44 False +Fabric45 45 False +Fabric46 46 False +Fabric47 47 False +Fabric48 48 False +Fabric49 49 False +Fabric50 50 False +Fabric51 51 False +Fabric52 52 False +Fabric53 53 False +Fabric54 54 False +Fabric55 55 False +Fabric56 56 False +Fabric57 57 False +Fabric58 58 False +Fabric59 59 False +Fabric60 60 False +Fabric61 61 False +Fabric62 62 False +Fabric63 63 False +Fabric64 64 False +Fabric65 65 False +Fabric66 66 False +Fabric67 67 False +Fabric68 68 False +Fabric69 69 False +Fabric70 70 False +Fabric71 71 False +Fabric72 72 False +Fabric73 73 False +Fabric74 74 False +Fabric75 75 False +Fabric76 76 False +Fabric77 77 False +Fabric78 78 False +Fabric79 79 False +Fabric80 80 False +Fabric81 81 False +Fabric82 82 False +Fabric83 83 False +Fabric84 84 False +Fabric85 85 False +Fabric86 86 False +Fabric87 87 False +Fabric88 88 False +Fabric89 89 False +Fabric90 90 False +Fabric91 91 False +Fabric92 92 False +Fabric93 93 False +Fabric94 94 False +Fabric95 95 False +Fabric96 96 False +Fabric97 97 False +Fabric98 98 False +Fabric99 99 False +Fabric100 100 False +Fabric101 101 False +Fabric102 102 False +Fabric103 103 False +Fabric104 104 False +Fabric105 105 False +Fabric106 106 False +Fabric107 107 False +Fabric108 108 False +Fabric109 109 False +Fabric110 110 False +Fabric111 111 False diff --git a/device/arista/x86_64-arista_7800r3_48cqm2_lc/fabric_monitor_config.json b/device/arista/x86_64-arista_7800r3_48cqm2_lc/fabric_monitor_config.json new file mode 100644 index 000000000000..653b25d1e276 --- /dev/null +++ b/device/arista/x86_64-arista_7800r3_48cqm2_lc/fabric_monitor_config.json @@ -0,0 +1,8 @@ +{ + "FABRIC_MONITOR_DATA": { + "monErrThreshCrcCells": 1, + "monErrThreshRxCells": 61035156, + "monPollThreshRecovery": 8, + "monPollThreshIsolation": 1 + } +} diff --git a/device/arista/x86_64-arista_7800r3_48cqm2_lc/fabric_port_config.ini b/device/arista/x86_64-arista_7800r3_48cqm2_lc/fabric_port_config.ini new file mode 100644 index 000000000000..e07e256dc169 --- /dev/null +++ b/device/arista/x86_64-arista_7800r3_48cqm2_lc/fabric_port_config.ini @@ -0,0 +1,113 @@ +# name lanes isolateStatus +Fabric0 0 False +Fabric1 1 False +Fabric2 2 False +Fabric3 3 False +Fabric4 4 False +Fabric5 5 False +Fabric6 6 False +Fabric7 7 False +Fabric8 8 False +Fabric9 9 False +Fabric10 10 False +Fabric11 11 False +Fabric12 12 False +Fabric13 13 False +Fabric14 14 False +Fabric15 15 False +Fabric16 16 False +Fabric17 17 False +Fabric18 18 False +Fabric19 19 False +Fabric20 20 False +Fabric21 21 False +Fabric22 22 False +Fabric23 23 False +Fabric24 24 False +Fabric25 25 False +Fabric26 26 False +Fabric27 27 False +Fabric28 28 False +Fabric29 29 False +Fabric30 30 False +Fabric31 31 False +Fabric32 32 False +Fabric33 33 False +Fabric34 34 False +Fabric35 35 False +Fabric36 36 False +Fabric37 37 False +Fabric38 38 False +Fabric39 39 False +Fabric40 40 False +Fabric41 41 False +Fabric42 42 False +Fabric43 43 False +Fabric44 44 False +Fabric45 45 False +Fabric46 46 False +Fabric47 47 False +Fabric48 48 False +Fabric49 49 False +Fabric50 50 False +Fabric51 51 False +Fabric52 52 False +Fabric53 53 False +Fabric54 54 False +Fabric55 55 False +Fabric56 56 False +Fabric57 57 False +Fabric58 58 False +Fabric59 59 False +Fabric60 60 False +Fabric61 61 False +Fabric62 62 False +Fabric63 63 False +Fabric64 64 False +Fabric65 65 False +Fabric66 66 False +Fabric67 67 False +Fabric68 68 False +Fabric69 69 False +Fabric70 70 False +Fabric71 71 False +Fabric72 72 False +Fabric73 73 False +Fabric74 74 False +Fabric75 75 False +Fabric76 76 False +Fabric77 77 False +Fabric78 78 False +Fabric79 79 False +Fabric80 80 False +Fabric81 81 False +Fabric82 82 False +Fabric83 83 False +Fabric84 84 False +Fabric85 85 False +Fabric86 86 False +Fabric87 87 False +Fabric88 88 False +Fabric89 89 False +Fabric90 90 False +Fabric91 91 False +Fabric92 92 False +Fabric93 93 False +Fabric94 94 False +Fabric95 95 False +Fabric96 96 False +Fabric97 97 False +Fabric98 98 False +Fabric99 99 False +Fabric100 100 False +Fabric101 101 False +Fabric102 102 False +Fabric103 103 False +Fabric104 104 False +Fabric105 105 False +Fabric106 106 False +Fabric107 107 False +Fabric108 108 False +Fabric109 109 False +Fabric110 110 False +Fabric111 111 False diff --git a/device/arista/x86_64-arista_7800r3a_36d2_lc/Arista-7800R3A-36D2-C36/0/port_config.ini b/device/arista/x86_64-arista_7800r3a_36d2_lc/Arista-7800R3A-36D2-C36/0/port_config.ini index a67c9b3f7d2f..c199d4af0b47 100644 --- a/device/arista/x86_64-arista_7800r3a_36d2_lc/Arista-7800R3A-36D2-C36/0/port_config.ini +++ b/device/arista/x86_64-arista_7800r3a_36d2_lc/Arista-7800R3A-36D2-C36/0/port_config.ini @@ -1,4 +1,4 @@ -# name lanes alias index role speed asic_port_name coreId corePortId numVoq +# name lanes alias index role speed asic_port_name core_id core_port_id num_voq Ethernet0 72,73,74,75 Ethernet1/1 1 Ext 100000 Eth0 1 1 8 Ethernet8 80,81,82,83 Ethernet2/1 2 Ext 100000 Eth8 1 2 8 Ethernet16 88,89,90,91 Ethernet3/1 3 Ext 100000 Eth16 1 3 8 diff --git a/device/arista/x86_64-arista_7800r3a_36d2_lc/Arista-7800R3A-36D2-C36/1/port_config.ini b/device/arista/x86_64-arista_7800r3a_36d2_lc/Arista-7800R3A-36D2-C36/1/port_config.ini index 4af1dc77b2a6..6763a4342594 100644 --- a/device/arista/x86_64-arista_7800r3a_36d2_lc/Arista-7800R3A-36D2-C36/1/port_config.ini +++ b/device/arista/x86_64-arista_7800r3a_36d2_lc/Arista-7800R3A-36D2-C36/1/port_config.ini @@ -1,4 +1,4 @@ -# name lanes alias index role speed asic_port_name coreId corePortId numVoq +# name lanes alias index role speed asic_port_name core_id core_port_id num_voq Ethernet144 72,73,74,75 Ethernet19/1 19 Ext 100000 Eth0 1 1 8 Ethernet152 80,81,82,83 Ethernet20/1 20 Ext 100000 Eth8 1 2 8 Ethernet160 88,89,90,91 Ethernet21/1 21 Ext 100000 Eth16 1 3 8 diff --git a/device/arista/x86_64-arista_7800r3a_36d2_lc/Arista-7800R3A-36D2-C72/0/port_config.ini b/device/arista/x86_64-arista_7800r3a_36d2_lc/Arista-7800R3A-36D2-C72/0/port_config.ini index f9f02ffb83a0..e38d580c72cd 100644 --- a/device/arista/x86_64-arista_7800r3a_36d2_lc/Arista-7800R3A-36D2-C72/0/port_config.ini +++ b/device/arista/x86_64-arista_7800r3a_36d2_lc/Arista-7800R3A-36D2-C72/0/port_config.ini @@ -1,4 +1,4 @@ -# name lanes alias index role speed asic_port_name coreId corePortId numVoq +# name lanes alias index role speed asic_port_name core_id core_port_id num_voq Ethernet0 72,73,74,75 Ethernet1/1 1 Ext 100000 Eth0 1 1 8 Ethernet4 76,77,78,79 Ethernet1/5 1 Ext 100000 Eth4 1 2 8 Ethernet8 80,81,82,83 Ethernet2/1 2 Ext 100000 Eth8 1 3 8 diff --git a/device/arista/x86_64-arista_7800r3a_36d2_lc/Arista-7800R3A-36D2-C72/1/port_config.ini b/device/arista/x86_64-arista_7800r3a_36d2_lc/Arista-7800R3A-36D2-C72/1/port_config.ini index 53988f0b7a26..ec3f5fbf971c 100644 --- a/device/arista/x86_64-arista_7800r3a_36d2_lc/Arista-7800R3A-36D2-C72/1/port_config.ini +++ b/device/arista/x86_64-arista_7800r3a_36d2_lc/Arista-7800R3A-36D2-C72/1/port_config.ini @@ -1,4 +1,4 @@ -# name lanes alias index role speed asic_port_name coreId corePortId numVoq +# name lanes alias index role speed asic_port_name core_id core_port_id num_voq Ethernet144 72,73,74,75 Ethernet19/1 19 Ext 100000 Eth144 1 1 8 Ethernet148 76,77,78,79 Ethernet19/5 19 Ext 100000 Eth148 1 2 8 Ethernet152 80,81,82,83 Ethernet20/1 20 Ext 100000 Eth152 1 3 8 diff --git a/device/arista/x86_64-arista_7800r3a_36d2_lc/Arista-7800R3A-36D2-C72/fabric_monitor_config.json b/device/arista/x86_64-arista_7800r3a_36d2_lc/Arista-7800R3A-36D2-C72/fabric_monitor_config.json new file mode 100644 index 000000000000..653b25d1e276 --- /dev/null +++ b/device/arista/x86_64-arista_7800r3a_36d2_lc/Arista-7800R3A-36D2-C72/fabric_monitor_config.json @@ -0,0 +1,8 @@ +{ + "FABRIC_MONITOR_DATA": { + "monErrThreshCrcCells": 1, + "monErrThreshRxCells": 61035156, + "monPollThreshRecovery": 8, + "monPollThreshIsolation": 1 + } +} diff --git a/device/arista/x86_64-arista_7800r3a_36d2_lc/Arista-7800R3A-36D2-C72/fabric_port_config.ini b/device/arista/x86_64-arista_7800r3a_36d2_lc/Arista-7800R3A-36D2-C72/fabric_port_config.ini new file mode 100644 index 000000000000..f9a60d04e5ea --- /dev/null +++ b/device/arista/x86_64-arista_7800r3a_36d2_lc/Arista-7800R3A-36D2-C72/fabric_port_config.ini @@ -0,0 +1,193 @@ +# name lanes isolateStatus +Fabric0 0 False +Fabric1 1 False +Fabric2 2 False +Fabric3 3 False +Fabric4 4 False +Fabric5 5 False +Fabric6 6 False +Fabric7 7 False +Fabric8 8 False +Fabric9 9 False +Fabric10 10 False +Fabric11 11 False +Fabric12 12 False +Fabric13 13 False +Fabric14 14 False +Fabric15 15 False +Fabric16 16 False +Fabric17 17 False +Fabric18 18 False +Fabric19 19 False +Fabric20 20 False +Fabric21 21 False +Fabric22 22 False +Fabric23 23 False +Fabric24 24 False +Fabric25 25 False +Fabric26 26 False +Fabric27 27 False +Fabric28 28 False +Fabric29 29 False +Fabric30 30 False +Fabric31 31 False +Fabric32 32 False +Fabric33 33 False +Fabric34 34 False +Fabric35 35 False +Fabric36 36 False +Fabric37 37 False +Fabric38 38 False +Fabric39 39 False +Fabric40 40 False +Fabric41 41 False +Fabric42 42 False +Fabric43 43 False +Fabric44 44 False +Fabric45 45 False +Fabric46 46 False +Fabric47 47 False +Fabric48 48 False +Fabric49 49 False +Fabric50 50 False +Fabric51 51 False +Fabric52 52 False +Fabric53 53 False +Fabric54 54 False +Fabric55 55 False +Fabric56 56 False +Fabric57 57 False +Fabric58 58 False +Fabric59 59 False +Fabric60 60 False +Fabric61 61 False +Fabric62 62 False +Fabric63 63 False +Fabric64 64 False +Fabric65 65 False +Fabric66 66 False +Fabric67 67 False +Fabric68 68 False +Fabric69 69 False +Fabric70 70 False +Fabric71 71 False +Fabric72 72 False +Fabric73 73 False +Fabric74 74 False +Fabric75 75 False +Fabric76 76 False +Fabric77 77 False +Fabric78 78 False +Fabric79 79 False +Fabric80 80 False +Fabric81 81 False +Fabric82 82 False +Fabric83 83 False +Fabric84 84 False +Fabric85 85 False +Fabric86 86 False +Fabric87 87 False +Fabric88 88 False +Fabric89 89 False +Fabric90 90 False +Fabric91 91 False +Fabric92 92 False +Fabric93 93 False +Fabric94 94 False +Fabric95 95 False +Fabric96 96 False +Fabric97 97 False +Fabric98 98 False +Fabric99 99 False +Fabric100 100 False +Fabric101 101 False +Fabric102 102 False +Fabric103 103 False +Fabric104 104 False +Fabric105 105 False +Fabric106 106 False +Fabric107 107 False +Fabric108 108 False +Fabric109 109 False +Fabric110 110 False +Fabric111 111 False +Fabric112 112 False +Fabric113 113 False +Fabric114 114 False +Fabric115 115 False +Fabric116 116 False +Fabric117 117 False +Fabric118 118 False +Fabric119 119 False +Fabric120 120 False +Fabric121 121 False +Fabric122 122 False +Fabric123 123 False +Fabric124 124 False +Fabric125 125 False +Fabric126 126 False +Fabric127 127 False +Fabric128 128 False +Fabric129 129 False +Fabric130 130 False +Fabric131 131 False +Fabric132 132 False +Fabric133 133 False +Fabric134 134 False +Fabric135 135 False +Fabric136 136 False +Fabric137 137 False +Fabric138 138 False +Fabric139 139 False +Fabric140 140 False +Fabric141 141 False +Fabric142 142 False +Fabric143 143 False +Fabric144 144 False +Fabric145 145 False +Fabric146 146 False +Fabric147 147 False +Fabric148 148 False +Fabric149 149 False +Fabric150 150 False +Fabric151 151 False +Fabric152 152 False +Fabric153 153 False +Fabric154 154 False +Fabric155 155 False +Fabric156 156 False +Fabric157 157 False +Fabric158 158 False +Fabric159 159 False +Fabric160 160 False +Fabric161 161 False +Fabric162 162 False +Fabric163 163 False +Fabric164 164 False +Fabric165 165 False +Fabric166 166 False +Fabric167 167 False +Fabric168 168 False +Fabric169 169 False +Fabric170 170 False +Fabric171 171 False +Fabric172 172 False +Fabric173 173 False +Fabric174 174 False +Fabric175 175 False +Fabric176 176 False +Fabric177 177 False +Fabric178 178 False +Fabric179 179 False +Fabric180 180 False +Fabric181 181 False +Fabric182 182 False +Fabric183 183 False +Fabric184 184 False +Fabric185 185 False +Fabric186 186 False +Fabric187 187 False +Fabric188 188 False +Fabric189 189 False +Fabric190 190 False +Fabric191 191 False diff --git a/device/arista/x86_64-arista_7800r3a_36d2_lc/Arista-7800R3A-36D2-D36/0/port_config.ini b/device/arista/x86_64-arista_7800r3a_36d2_lc/Arista-7800R3A-36D2-D36/0/port_config.ini index d6b5da8404dd..3ba9272d43a4 100644 --- a/device/arista/x86_64-arista_7800r3a_36d2_lc/Arista-7800R3A-36D2-D36/0/port_config.ini +++ b/device/arista/x86_64-arista_7800r3a_36d2_lc/Arista-7800R3A-36D2-D36/0/port_config.ini @@ -1,4 +1,4 @@ -# name lanes alias index role speed asic_port_name coreId corePortId numVoq +# name lanes alias index role speed asic_port_name core_id core_port_id num_voq Ethernet0 72,73,74,75,76,77,78,79 Ethernet1/1 1 Ext 400000 Eth0 1 1 8 Ethernet8 80,81,82,83,84,85,86,87 Ethernet2/1 2 Ext 400000 Eth8 1 2 8 Ethernet16 88,89,90,91,92,93,94,95 Ethernet3/1 3 Ext 400000 Eth16 1 3 8 diff --git a/device/arista/x86_64-arista_7800r3a_36d2_lc/Arista-7800R3A-36D2-D36/1/port_config.ini b/device/arista/x86_64-arista_7800r3a_36d2_lc/Arista-7800R3A-36D2-D36/1/port_config.ini index 6e6b7765b749..84839fb90957 100644 --- a/device/arista/x86_64-arista_7800r3a_36d2_lc/Arista-7800R3A-36D2-D36/1/port_config.ini +++ b/device/arista/x86_64-arista_7800r3a_36d2_lc/Arista-7800R3A-36D2-D36/1/port_config.ini @@ -1,4 +1,4 @@ -# name lanes alias index role speed asic_port_name coreId corePortId numVoq +# name lanes alias index role speed asic_port_name core_id core_port_id num_voq Ethernet144 72,73,74,75,76,77,78,79 Ethernet19/1 19 Ext 400000 Eth0 1 1 8 Ethernet152 80,81,82,83,84,85,86,87 Ethernet20/1 20 Ext 400000 Eth8 1 2 8 Ethernet160 88,89,90,91,92,93,94,95 Ethernet21/1 21 Ext 400000 Eth16 1 3 8 diff --git a/device/nokia/x86_64-nokia_ixr7250e_36x400g-r0/Nokia-IXR7250E-36x100G/0/jr2cp-nokia-18x100g-4x25g-config.bcm b/device/nokia/x86_64-nokia_ixr7250e_36x400g-r0/Nokia-IXR7250E-36x100G/0/jr2cp-nokia-18x100g-4x25g-config.bcm index ad80dd63242d..0d6f12693a27 100644 --- a/device/nokia/x86_64-nokia_ixr7250e_36x400g-r0/Nokia-IXR7250E-36x100G/0/jr2cp-nokia-18x100g-4x25g-config.bcm +++ b/device/nokia/x86_64-nokia_ixr7250e_36x400g-r0/Nokia-IXR7250E-36x100G/0/jr2cp-nokia-18x100g-4x25g-config.bcm @@ -2084,7 +2084,7 @@ serdes_lane_config_channel_mode_447=force_nr rif_id_max=24576 dpp_db_path=/usr/share/bcm/db -sai_recycle_port_lane_base=96 +sai_recycle_port_lane_base=200 appl_param_nof_ports_per_modid=64 udh_exists=1 modreg IPS_FORCE_LOCAL_OR_FABRIC FORCE_FABRIC=1 @@ -2095,3 +2095,4 @@ sai_pfc_dlr_init_capability=0 sai_disable_srcmacqedstmac_ctrl=1 trunk_group_max_members=16 sai_default_cpu_tx_tc=7 +sai_postinit_cmd_file=/usr/share/sonic/hwsku/sai_postinit_cmd.soc \ No newline at end of file diff --git a/device/nokia/x86_64-nokia_ixr7250e_36x400g-r0/Nokia-IXR7250E-36x100G/0/port_config.ini b/device/nokia/x86_64-nokia_ixr7250e_36x400g-r0/Nokia-IXR7250E-36x100G/0/port_config.ini index ea7ae717e8c5..8b4e625ec7a5 100644 --- a/device/nokia/x86_64-nokia_ixr7250e_36x400g-r0/Nokia-IXR7250E-36x100G/0/port_config.ini +++ b/device/nokia/x86_64-nokia_ixr7250e_36x400g-r0/Nokia-IXR7250E-36x100G/0/port_config.ini @@ -1,4 +1,4 @@ -# name lanes alias index role speed asic_port_name coreid coreportid numvoq +# name lanes alias index role speed asic_port_name core_id core_port_id num_voq Ethernet0 72,73,74,75 Ethernet1/1 1 Ext 100000 Eth0 1 1 8 Ethernet8 80,81,82,83 Ethernet2/1 2 Ext 100000 Eth8 1 2 8 Ethernet16 88,89,90,91 Ethernet3/1 3 Ext 100000 Eth16 1 3 8 @@ -17,5 +17,5 @@ Ethernet112 24,25,26,27 Ethernet15/1 15 Ext 100000 Eth112 Ethernet120 16,17,18,19 Ethernet16/1 16 Ext 100000 Eth120 0 16 8 Ethernet128 8,9,10,11 Ethernet17/1 17 Ext 100000 Eth128 0 17 8 Ethernet136 0,1,2,3 Ethernet18/1 18 Ext 100000 Eth136 0 18 8 -Ethernet-IB0 115 Recirc0/0 37 Inb 10000 Rcy0 0 19 8 -Ethernet-Rec0 116 Recirc0/1 39 Rec 10000 Rcy1 1 20 8 +Ethernet-IB0 219 Recirc0/0 37 Inb 10000 Rcy0 0 19 8 +Ethernet-Rec0 220 Recirc0/1 39 Rec 10000 Rcy1 1 20 8 diff --git a/device/nokia/x86_64-nokia_ixr7250e_36x400g-r0/Nokia-IXR7250E-36x100G/0/sai_postinit_cmd.soc b/device/nokia/x86_64-nokia_ixr7250e_36x400g-r0/Nokia-IXR7250E-36x100G/0/sai_postinit_cmd.soc index 8b137891791f..80338902b828 100644 --- a/device/nokia/x86_64-nokia_ixr7250e_36x400g-r0/Nokia-IXR7250E-36x100G/0/sai_postinit_cmd.soc +++ b/device/nokia/x86_64-nokia_ixr7250e_36x400g-r0/Nokia-IXR7250E-36x100G/0/sai_postinit_cmd.soc @@ -1 +1,29 @@ +INTeRrupt ENAble id=2209 +INTeRrupt ENAble id=2210 +INTeRrupt ENAble id=2211 +INTeRrupt ENAble id=2212 +INTeRrupt ENAble id=2213 +INTeRrupt ENAble id=2214 +INTeRrupt ENAble id=2215 +INTeRrupt ENAble id=2216 +INTeRrupt ENAble id=2217 +INTeRrupt ENAble id=2218 +INTeRrupt ENAble id=2219 +INTeRrupt ENAble id=2220 +INTeRrupt ENAble id=2221 +INTeRrupt ENAble id=2222 +INTeRrupt ENAble id=2223 +INTeRrupt ENAble id=2224 +INTeRrupt ENAble id=2225 +INTeRrupt ENAble id=2226 +INTeRrupt ENAble id=482 +INTeRrupt ENAble id=483 +INTeRrupt ENAble id=484 +INTeRrupt ENAble id=485 +INTeRrupt ENAble id=486 +INTeRrupt ENAble id=487 +INTeRrupt ENAble id=488 + +INTeRrupt ENAble id=1597 +debug intr error \ No newline at end of file diff --git a/device/nokia/x86_64-nokia_ixr7250e_36x400g-r0/Nokia-IXR7250E-36x100G/1/jr2cp-nokia-18x100g-4x25g-config.bcm b/device/nokia/x86_64-nokia_ixr7250e_36x400g-r0/Nokia-IXR7250E-36x100G/1/jr2cp-nokia-18x100g-4x25g-config.bcm index 66aeb4ffa076..aa66d05c6ac7 100644 --- a/device/nokia/x86_64-nokia_ixr7250e_36x400g-r0/Nokia-IXR7250E-36x100G/1/jr2cp-nokia-18x100g-4x25g-config.bcm +++ b/device/nokia/x86_64-nokia_ixr7250e_36x400g-r0/Nokia-IXR7250E-36x100G/1/jr2cp-nokia-18x100g-4x25g-config.bcm @@ -2085,7 +2085,7 @@ serdes_lane_config_channel_mode_447=force_nr rif_id_max=24576 dpp_db_path=/usr/share/bcm/db -sai_recycle_port_lane_base=96 +sai_recycle_port_lane_base=200 appl_param_nof_ports_per_modid=64 udh_exists=1 modreg IPS_FORCE_LOCAL_OR_FABRIC FORCE_FABRIC=1 @@ -2096,3 +2096,4 @@ sai_pfc_dlr_init_capability=0 sai_disable_srcmacqedstmac_ctrl=1 trunk_group_max_members=16 sai_default_cpu_tx_tc=7 +sai_postinit_cmd_file=/usr/share/sonic/hwsku/sai_postinit_cmd.soc \ No newline at end of file diff --git a/device/nokia/x86_64-nokia_ixr7250e_36x400g-r0/Nokia-IXR7250E-36x100G/1/port_config.ini b/device/nokia/x86_64-nokia_ixr7250e_36x400g-r0/Nokia-IXR7250E-36x100G/1/port_config.ini index b919d1b97b10..630e5109d077 100644 --- a/device/nokia/x86_64-nokia_ixr7250e_36x400g-r0/Nokia-IXR7250E-36x100G/1/port_config.ini +++ b/device/nokia/x86_64-nokia_ixr7250e_36x400g-r0/Nokia-IXR7250E-36x100G/1/port_config.ini @@ -1,4 +1,4 @@ -# name lanes alias index role speed asic_port_name coreid coreportid numvoq +# name lanes alias index role speed asic_port_name core_id core_port_id num_voq Ethernet144 72,73,74,75 Ethernet19/1 19 Ext 100000 Eth0 1 1 8 Ethernet152 80,81,82,83 Ethernet20/1 20 Ext 100000 Eth8 1 2 8 Ethernet160 88,89,90,91 Ethernet21/1 21 Ext 100000 Eth16 1 3 8 @@ -17,5 +17,5 @@ Ethernet256 24,25,26,27 Ethernet33/1 33 Ext 100000 Eth112 Ethernet264 16,17,18,19 Ethernet34/1 34 Ext 100000 Eth120 0 16 8 Ethernet272 8,9,10,11 Ethernet35/1 35 Ext 100000 Eth128 0 17 8 Ethernet280 0,1,2,3 Ethernet36/1 36 Ext 100000 Eth136 0 18 8 -Ethernet-IB1 115 Recirc1/0 38 Inb 10000 Rcy0 0 19 8 -Ethernet-Rec1 116 Recirc1/1 40 Rec 10000 Rcy1 1 20 8 +Ethernet-IB1 219 Recirc1/0 38 Inb 10000 Rcy0 0 19 8 +Ethernet-Rec1 220 Recirc1/1 40 Rec 10000 Rcy1 1 20 8 diff --git a/device/nokia/x86_64-nokia_ixr7250e_36x400g-r0/Nokia-IXR7250E-36x100G/1/sai_postinit_cmd.soc b/device/nokia/x86_64-nokia_ixr7250e_36x400g-r0/Nokia-IXR7250E-36x100G/1/sai_postinit_cmd.soc index 8b137891791f..80338902b828 100644 --- a/device/nokia/x86_64-nokia_ixr7250e_36x400g-r0/Nokia-IXR7250E-36x100G/1/sai_postinit_cmd.soc +++ b/device/nokia/x86_64-nokia_ixr7250e_36x400g-r0/Nokia-IXR7250E-36x100G/1/sai_postinit_cmd.soc @@ -1 +1,29 @@ +INTeRrupt ENAble id=2209 +INTeRrupt ENAble id=2210 +INTeRrupt ENAble id=2211 +INTeRrupt ENAble id=2212 +INTeRrupt ENAble id=2213 +INTeRrupt ENAble id=2214 +INTeRrupt ENAble id=2215 +INTeRrupt ENAble id=2216 +INTeRrupt ENAble id=2217 +INTeRrupt ENAble id=2218 +INTeRrupt ENAble id=2219 +INTeRrupt ENAble id=2220 +INTeRrupt ENAble id=2221 +INTeRrupt ENAble id=2222 +INTeRrupt ENAble id=2223 +INTeRrupt ENAble id=2224 +INTeRrupt ENAble id=2225 +INTeRrupt ENAble id=2226 +INTeRrupt ENAble id=482 +INTeRrupt ENAble id=483 +INTeRrupt ENAble id=484 +INTeRrupt ENAble id=485 +INTeRrupt ENAble id=486 +INTeRrupt ENAble id=487 +INTeRrupt ENAble id=488 + +INTeRrupt ENAble id=1597 +debug intr error \ No newline at end of file diff --git a/device/nokia/x86_64-nokia_ixr7250e_36x400g-r0/Nokia-IXR7250E-36x400G/0/jr2cp-nokia-18x400g-config.bcm b/device/nokia/x86_64-nokia_ixr7250e_36x400g-r0/Nokia-IXR7250E-36x400G/0/jr2cp-nokia-18x400g-config.bcm index aebe7d29380d..29726c5f2d13 100644 --- a/device/nokia/x86_64-nokia_ixr7250e_36x400g-r0/Nokia-IXR7250E-36x400G/0/jr2cp-nokia-18x400g-config.bcm +++ b/device/nokia/x86_64-nokia_ixr7250e_36x400g-r0/Nokia-IXR7250E-36x400G/0/jr2cp-nokia-18x400g-config.bcm @@ -2085,7 +2085,7 @@ serdes_lane_config_channel_mode_447=force_nr rif_id_max=24576 dpp_db_path=/usr/share/bcm/db -sai_recycle_port_lane_base=96 +sai_recycle_port_lane_base=200 appl_param_nof_ports_per_modid=64 udh_exists=1 modreg IPS_FORCE_LOCAL_OR_FABRIC FORCE_FABRIC=1 diff --git a/device/nokia/x86_64-nokia_ixr7250e_36x400g-r0/Nokia-IXR7250E-36x400G/0/port_config.ini b/device/nokia/x86_64-nokia_ixr7250e_36x400g-r0/Nokia-IXR7250E-36x400G/0/port_config.ini index 162eca454fca..18449e8cbcba 100644 --- a/device/nokia/x86_64-nokia_ixr7250e_36x400g-r0/Nokia-IXR7250E-36x400G/0/port_config.ini +++ b/device/nokia/x86_64-nokia_ixr7250e_36x400g-r0/Nokia-IXR7250E-36x400G/0/port_config.ini @@ -1,4 +1,4 @@ -# name lanes alias index role speed asic_port_name coreid coreportid numvoq +# name lanes alias index role speed asic_port_name core_id core_port_id num_voq Ethernet0 72,73,74,75,76,77,78,79 Ethernet1/1 1 Ext 400000 Eth0 1 1 8 Ethernet8 80,81,82,83,84,85,86,87 Ethernet2/1 2 Ext 400000 Eth8 1 2 8 Ethernet16 88,89,90,91,92,93,94,95 Ethernet3/1 3 Ext 400000 Eth16 1 3 8 @@ -17,5 +17,5 @@ Ethernet112 24,25,26,27,28,29,30,31 Ethernet15/1 15 Ext 40000 Ethernet120 16,17,18,19,20,21,22,23 Ethernet16/1 16 Ext 400000 Eth120 0 16 8 Ethernet128 8,9,10,11,12,13,14,15 Ethernet17/1 17 Ext 400000 Eth128 0 17 8 Ethernet136 0,1,2,3,4,5,6,7 Ethernet18/1 18 Ext 400000 Eth136 0 18 8 -Ethernet-IB0 115 Recirc0/0 37 Inb 10000 Rcy0 0 19 8 -Ethernet-Rec0 116 Recirc0/1 39 Rec 10000 Rcy1 1 20 8 +Ethernet-IB0 219 Recirc0/0 37 Inb 10000 Rcy0 0 19 8 +Ethernet-Rec0 220 Recirc0/1 39 Rec 10000 Rcy1 1 20 8 diff --git a/device/nokia/x86_64-nokia_ixr7250e_36x400g-r0/Nokia-IXR7250E-36x400G/0/sai_postinit_cmd.soc b/device/nokia/x86_64-nokia_ixr7250e_36x400g-r0/Nokia-IXR7250E-36x400G/0/sai_postinit_cmd.soc index 97f62c07cc77..26b9099a949a 100644 --- a/device/nokia/x86_64-nokia_ixr7250e_36x400g-r0/Nokia-IXR7250E-36x400G/0/sai_postinit_cmd.soc +++ b/device/nokia/x86_64-nokia_ixr7250e_36x400g-r0/Nokia-IXR7250E-36x400G/0/sai_postinit_cmd.soc @@ -36,3 +36,32 @@ phy set 17 reg=0xd137 data=0 lane=2 phy set 17 reg=0xd138 data=0 lane=2 phy set 17 reg=0xd133 data=0x1804 lane=2 +INTeRrupt ENAble id=2209 +INTeRrupt ENAble id=2210 +INTeRrupt ENAble id=2211 +INTeRrupt ENAble id=2212 +INTeRrupt ENAble id=2213 +INTeRrupt ENAble id=2214 +INTeRrupt ENAble id=2215 +INTeRrupt ENAble id=2216 +INTeRrupt ENAble id=2217 +INTeRrupt ENAble id=2218 +INTeRrupt ENAble id=2219 +INTeRrupt ENAble id=2220 +INTeRrupt ENAble id=2221 +INTeRrupt ENAble id=2222 +INTeRrupt ENAble id=2223 +INTeRrupt ENAble id=2224 +INTeRrupt ENAble id=2225 +INTeRrupt ENAble id=2226 + +INTeRrupt ENAble id=482 +INTeRrupt ENAble id=483 +INTeRrupt ENAble id=484 +INTeRrupt ENAble id=485 +INTeRrupt ENAble id=486 +INTeRrupt ENAble id=487 +INTeRrupt ENAble id=488 + +INTeRrupt ENAble id=1597 +debug intr error \ No newline at end of file diff --git a/device/nokia/x86_64-nokia_ixr7250e_36x400g-r0/Nokia-IXR7250E-36x400G/1/jr2cp-nokia-18x400g-config.bcm b/device/nokia/x86_64-nokia_ixr7250e_36x400g-r0/Nokia-IXR7250E-36x400G/1/jr2cp-nokia-18x400g-config.bcm index ebb95bf345a7..5f9132fb78eb 100644 --- a/device/nokia/x86_64-nokia_ixr7250e_36x400g-r0/Nokia-IXR7250E-36x400G/1/jr2cp-nokia-18x400g-config.bcm +++ b/device/nokia/x86_64-nokia_ixr7250e_36x400g-r0/Nokia-IXR7250E-36x400G/1/jr2cp-nokia-18x400g-config.bcm @@ -2087,7 +2087,7 @@ serdes_lane_config_channel_mode_447=force_nr rif_id_max=24576 dpp_db_path=/usr/share/bcm/db -sai_recycle_port_lane_base=96 +sai_recycle_port_lane_base=200 appl_param_nof_ports_per_modid=64 udh_exists=1 modreg IPS_FORCE_LOCAL_OR_FABRIC FORCE_FABRIC=1 diff --git a/device/nokia/x86_64-nokia_ixr7250e_36x400g-r0/Nokia-IXR7250E-36x400G/1/port_config.ini b/device/nokia/x86_64-nokia_ixr7250e_36x400g-r0/Nokia-IXR7250E-36x400G/1/port_config.ini index 1531e5a14278..faccc8e39def 100644 --- a/device/nokia/x86_64-nokia_ixr7250e_36x400g-r0/Nokia-IXR7250E-36x400G/1/port_config.ini +++ b/device/nokia/x86_64-nokia_ixr7250e_36x400g-r0/Nokia-IXR7250E-36x400G/1/port_config.ini @@ -1,4 +1,4 @@ -# name lanes alias index role speed asic_port_name coreid coreportid numvoq +# name lanes alias index role speed asic_port_name core_id core_port_id num_voq Ethernet144 72,73,74,75,76,77,78,79 Ethernet19/1 19 Ext 400000 Eth0 1 1 8 Ethernet152 80,81,82,83,84,85,86,87 Ethernet20/1 20 Ext 400000 Eth8 1 2 8 Ethernet160 88,89,90,91,92,93,94,95 Ethernet21/1 21 Ext 400000 Eth16 1 3 8 @@ -17,5 +17,5 @@ Ethernet256 24,25,26,27,28,29,30,31 Ethernet33/1 33 Ext 40000 Ethernet264 16,17,18,19,20,21,22,23 Ethernet34/1 34 Ext 400000 Eth120 0 16 8 Ethernet272 8,9,10,11,12,13,14,15 Ethernet35/1 35 Ext 400000 Eth128 0 17 8 Ethernet280 0,1,2,3,4,5,6,7 Ethernet36/1 36 Ext 400000 Eth136 0 18 8 -Ethernet-IB1 115 Recirc1/0 38 Inb 10000 Rcy0 0 19 8 -Ethernet-Rec1 116 Recirc1/1 40 Rec 10000 Rcy1 1 20 8 +Ethernet-IB1 219 Recirc1/0 38 Inb 10000 Rcy0 0 19 8 +Ethernet-Rec1 220 Recirc1/1 40 Rec 10000 Rcy1 1 20 8 diff --git a/device/nokia/x86_64-nokia_ixr7250e_36x400g-r0/Nokia-IXR7250E-36x400G/1/sai_postinit_cmd.soc b/device/nokia/x86_64-nokia_ixr7250e_36x400g-r0/Nokia-IXR7250E-36x400G/1/sai_postinit_cmd.soc index ed471c6c19b2..19c3f73e9e30 100644 --- a/device/nokia/x86_64-nokia_ixr7250e_36x400g-r0/Nokia-IXR7250E-36x400G/1/sai_postinit_cmd.soc +++ b/device/nokia/x86_64-nokia_ixr7250e_36x400g-r0/Nokia-IXR7250E-36x400G/1/sai_postinit_cmd.soc @@ -13,3 +13,32 @@ phy set 8 reg=0xd137 data=0 lane=1 phy set 8 reg=0xd138 data=0 lane=1 phy set 8 reg=0xd133 data=0x1802 lane=1 +INTeRrupt ENAble id=2209 +INTeRrupt ENAble id=2210 +INTeRrupt ENAble id=2211 +INTeRrupt ENAble id=2212 +INTeRrupt ENAble id=2213 +INTeRrupt ENAble id=2214 +INTeRrupt ENAble id=2215 +INTeRrupt ENAble id=2216 +INTeRrupt ENAble id=2217 +INTeRrupt ENAble id=2218 +INTeRrupt ENAble id=2219 +INTeRrupt ENAble id=2220 +INTeRrupt ENAble id=2221 +INTeRrupt ENAble id=2222 +INTeRrupt ENAble id=2223 +INTeRrupt ENAble id=2224 +INTeRrupt ENAble id=2225 +INTeRrupt ENAble id=2226 + +INTeRrupt ENAble id=482 +INTeRrupt ENAble id=483 +INTeRrupt ENAble id=484 +INTeRrupt ENAble id=485 +INTeRrupt ENAble id=486 +INTeRrupt ENAble id=487 +INTeRrupt ENAble id=488 + +INTeRrupt ENAble id=1597 +debug intr error \ No newline at end of file diff --git a/device/nokia/x86_64-nokia_ixr7250e_36x400g-r0/platform_ndk.json b/device/nokia/x86_64-nokia_ixr7250e_36x400g-r0/platform_ndk.json index 4fbd84df39b6..57bc959d7104 100644 --- a/device/nokia/x86_64-nokia_ixr7250e_36x400g-r0/platform_ndk.json +++ b/device/nokia/x86_64-nokia_ixr7250e_36x400g-r0/platform_ndk.json @@ -14,7 +14,7 @@ }, { "key": "monitor_action", - "stringval": "warn" + "stringval": "reboot" }, { "key": "grpc_thermal_monitor", @@ -43,6 +43,26 @@ { "key": "sonic_log_level", "stringval": "debug" + }, + { + "key": "thermal_low_margin_threshold", + "intval": 10 + }, + { + "key": "thermal_log_current_threshold", + "intval": 5 + }, + { + "key": "thermal_log_margin_threshold", + "intval": 5 + }, + { + "key": "thermal_log_min_threshold", + "intval": 2 + }, + { + "key": "thermal_log_max_threshold", + "intval": 1 } ] } diff --git a/device/nokia/x86_64-nokia_ixr7250e_36x400g-r0/platform_reboot b/device/nokia/x86_64-nokia_ixr7250e_36x400g-r0/platform_reboot index 43aace70f7ee..454a14c5ab74 100755 --- a/device/nokia/x86_64-nokia_ixr7250e_36x400g-r0/platform_reboot +++ b/device/nokia/x86_64-nokia_ixr7250e_36x400g-r0/platform_reboot @@ -1,12 +1,27 @@ #!/bin/bash +DEVICE_MGR_REBOOT_FILE=/tmp/device_mgr_reboot +REBOOT_CAUSE_FILE=/host/reboot-cause/reboot-cause.txt +DEVICE_REBOOT_CAUSE_FILE=/etc/opt/srlinux/reboot-cause.txt +kHeartbeatLostRebootCause="Heartbeat with the Supervisor card lost" +DEVICE_DETAILS_FILE="/etc/opt/srlinux/devices/hw_details.json" + +ungraceful_reboot_handle() +{ + str=$(grep "$kHeartbeatLostRebootCause" $DEVICE_REBOOT_CAUSE_FILE 2> /dev/null) + status=$? + if [ $status -eq 0 ]; then + slot_num=$(jq -r '.slot_num' $DEVICE_DETAILS_FILE 2>/dev/null) + slot_num=$((slot_num - 1)) + sonic-db-cli CHASSIS_STATE_DB del "CHASSIS_MODULE_REBOOT_INFO_TABLE|LINE-CARD${slot_num}" + fi +} update_reboot_cause() { - DEVICE_MGR_REBOOT_FILE=/tmp/device_mgr_reboot - REBOOT_CAUSE_FILE=/host/reboot-cause/reboot-cause.txt - DEVICE_REBOOT_CAUSE_FILE=/etc/opt/srlinux/reboot-cause.txt if [ -e $DEVICE_MGR_REBOOT_FILE ]; then if [ -e $DEVICE_REBOOT_CAUSE_FILE ]; then + # reomve the REBOOT_INFO_TABLE entry for unpexected reboot + ungraceful_reboot_handle cp -f $DEVICE_REBOOT_CAUSE_FILE $REBOOT_CAUSE_FILE fi rm -f $DEVICE_MGR_REBOOT_FILE @@ -17,6 +32,10 @@ update_reboot_cause() sync } +echo "Disable all SFPs" +python3 -c 'import sonic_platform.platform; platform_chassis = sonic_platform.platform.Platform().get_chassis(); platform_chassis.tx_disable_all_sfps()' & +sleep 3 + # update the reboot_cuase file when reboot is trigger by device-mgr update_reboot_cause diff --git a/device/nokia/x86_64-nokia_ixr7250e_36x400g-r0/startup-tsa-tsb.conf b/device/nokia/x86_64-nokia_ixr7250e_36x400g-r0/startup-tsa-tsb.conf new file mode 100644 index 000000000000..150337493256 --- /dev/null +++ b/device/nokia/x86_64-nokia_ixr7250e_36x400g-r0/startup-tsa-tsb.conf @@ -0,0 +1 @@ +STARTUP_TSB_TIMER=900 diff --git a/device/nokia/x86_64-nokia_ixr7250e_sup-r0/platform_env.conf b/device/nokia/x86_64-nokia_ixr7250e_sup-r0/platform_env.conf index d4a267afb984..df041049bfb4 100644 --- a/device/nokia/x86_64-nokia_ixr7250e_sup-r0/platform_env.conf +++ b/device/nokia/x86_64-nokia_ixr7250e_sup-r0/platform_env.conf @@ -2,3 +2,4 @@ usemsi=1 dmasize=128M default_mtu=9100 supervisor=1 +linecard_reboot_timeout=180 diff --git a/device/nokia/x86_64-nokia_ixr7250e_sup-r0/platform_ndk.json b/device/nokia/x86_64-nokia_ixr7250e_sup-r0/platform_ndk.json index dddefb0bcf73..bf7f1ed57427 100644 --- a/device/nokia/x86_64-nokia_ixr7250e_sup-r0/platform_ndk.json +++ b/device/nokia/x86_64-nokia_ixr7250e_sup-r0/platform_ndk.json @@ -31,6 +31,26 @@ { "key": "sonic_log_level", "stringval": "debug" + }, + { + "key": "thermal_low_margin_threshold", + "intval": 10 + }, + { + "key": "thermal_log_current_threshold", + "intval": 5 + }, + { + "key": "thermal_log_margin_threshold", + "intval": 5 + }, + { + "key": "thermal_log_min_threshold", + "intval": 5 + }, + { + "key": "thermal_log_max_threshold", + "intval": 1 } ] } diff --git a/device/nokia/x86_64-nokia_ixr7250e_sup-r0/platform_reboot b/device/nokia/x86_64-nokia_ixr7250e_sup-r0/platform_reboot index 00ae76c9de86..dc4f934339c9 100755 --- a/device/nokia/x86_64-nokia_ixr7250e_sup-r0/platform_reboot +++ b/device/nokia/x86_64-nokia_ixr7250e_sup-r0/platform_reboot @@ -1,15 +1,39 @@ #!/bin/bash -echo "Rebooting all Linecards" -python3 -c 'import sonic_platform.platform; platform_chassis = sonic_platform.platform.Platform().get_chassis(); platform_chassis.reboot_imms()' -sleep 3 + +DEVICE_MGR_REBOOT_FILE="/tmp/device_mgr_reboot" + +update_reboot_cause() +{ + DEVICE_MGR_REBOOT_FILE=/tmp/device_mgr_reboot + REBOOT_CAUSE_FILE=/host/reboot-cause/reboot-cause.txt + DEVICE_REBOOT_CAUSE_FILE=/etc/opt/srlinux/reboot-cause.txt + if [ -e $DEVICE_MGR_REBOOT_FILE ]; then + if [ -e $DEVICE_REBOOT_CAUSE_FILE ]; then + cp -f $DEVICE_REBOOT_CAUSE_FILE $REBOOT_CAUSE_FILE + fi + rm -f $DEVICE_MGR_REBOOT_FILE + else + touch /etc/opt/srlinux/devmgr_reboot_cause.done + rm -f $DEVICE_REBOOT_CAUSE_FILE &> /dev/null + fi + sync +} + +if [ ! -e $DEVICE_MGR_REBOOT_FILE ]; then + echo "Rebooting all Linecards" + python3 -c 'import sonic_platform.platform; platform_chassis = sonic_platform.platform.Platform().get_chassis(); platform_chassis.reboot_imms()' + sleep 3 +fi + +# update the reboot_cuase file when reboot is trigger by device-mgr +update_reboot_cause + systemctl stop nokia-watchdog.service sleep 2 echo "w" > /dev/watchdog kick_date=`date -u` echo "last watchdog kick $kick_date" > /var/log/nokia-watchdog-last.log rm -f /sys/firmware/efi/efivars/dump-* -touch /etc/opt/srlinux/devmgr_reboot_cause.done -rm -f /etc/opt/srlinux/reboot-cause.txt echo "Shutdown midplane" ifconfig xe0 down sync diff --git a/dockers/docker-fpm-frr/TS b/dockers/docker-fpm-frr/TS index 1ff08431edb3..fda750d9c224 100755 --- a/dockers/docker-fpm-frr/TS +++ b/dockers/docker-fpm-frr/TS @@ -4,7 +4,12 @@ switch_type=`sonic-cfggen -d -v "DEVICE_METADATA['localhost']['switch_type']"` # Check whether the routemap is for internal BGP sessions. function is_internal_route_map() { - [[ "$1" =~ .*"_INTERNAL_".* && $switch_type != "chassis-packet" ]] + if [[ "$1" =~ .*"_INTERNAL_".* || "$1" =~ .*"VOQ_".* ]] + then + return 1 + else + return 0 + fi } function check_not_installed() @@ -13,10 +18,15 @@ function check_not_installed() config=$(vtysh -c "show run") for route_map_name in $(echo "$config" | sed -ne 's/ neighbor \S* route-map \(\S*\) out/\1/p' | egrep 'V4|V6' | uniq); do - is_internal_route_map $route_map_name && continue + is_internal_route_map $route_map_name + if [[ $? -eq 1 ]]; then + continue + fi echo "$config" | egrep -q "^route-map $route_map_name permit 20$" c=$((c+$?)) - echo "$config" | egrep -q "^route-map $route_map_name deny 30$" + echo "$config" | egrep -q "^route-map $route_map_name permit 30$" + c=$((c+$?)) + echo "$config" | egrep -q "^route-map $route_map_name deny 40$" c=$((c+$?)) done return $c @@ -29,11 +39,17 @@ function check_installed() config=$(vtysh -c "show run") for route_map_name in $(echo "$config" | sed -ne 's/ neighbor \S* route-map \(\S*\) out/\1/p' | egrep 'V4|V6' | uniq); do - is_internal_route_map $route_map_name && continue + is_internal_route_map $route_map_name + if [[ $? -eq 1 ]]; then + continue + fi echo "$config" | egrep -q "^route-map $route_map_name permit 20$" c=$((c+$?)) e=$((e+1)) - echo "$config" | egrep -q "^route-map $route_map_name deny 30$" + echo "$config" | egrep -q "^route-map $route_map_name permit 30$" + c=$((c+$?)) + e=$((e+1)) + echo "$config" | egrep -q "^route-map $route_map_name deny 40$" c=$((c+$?)) e=$((e+1)) done @@ -46,7 +62,10 @@ function find_num_routemap() config=$(vtysh -c "show run") for route_map_name in $(echo "$config" | sed -ne 's/ neighbor \S* route-map \(\S*\) out/\1/p' | egrep 'V4|V6' | uniq); do - is_internal_route_map $route_map_name && continue + is_internal_route_map $route_map_name + if [[ $? -eq 1 ]]; then + continue + fi c=$((c+1)) done return $c diff --git a/dockers/docker-fpm-frr/TSA b/dockers/docker-fpm-frr/TSA index f45d3bf0bcb3..c94a35ea05f0 100755 --- a/dockers/docker-fpm-frr/TSA +++ b/dockers/docker-fpm-frr/TSA @@ -16,7 +16,8 @@ then TSA_FILE=$(mktemp) for route_map_name in $(echo "$config" | sed -ne 's/ neighbor \S* route-map \(\S*\) out/\1/p' | uniq); do - is_internal_route_map $route_map_name && continue + is_internal_route_map $route_map_name + internal_route_map=$? case "$route_map_name" in *V4*) ip_version=V4 @@ -30,7 +31,7 @@ then continue ;; esac - sonic-cfggen -d -a "{\"route_map_name\":\"$route_map_name\", \"ip_version\": \"$ip_version\", \"ip_protocol\": \"$ip_protocol\"}" -y /etc/sonic/constants.yml -t /usr/share/sonic/templates/bgpd/tsa/bgpd.tsa.isolate.conf.j2 > "$TSA_FILE" + sonic-cfggen -d -a "{\"route_map_name\":\"$route_map_name\", \"ip_version\": \"$ip_version\", \"ip_protocol\": \"$ip_protocol\", \"internal_route_map\": \"$internal_route_map\"}" -y /etc/sonic/constants.yml -t /usr/share/sonic/templates/bgpd/tsa/bgpd.tsa.isolate.conf.j2 > "$TSA_FILE" vtysh -f "$TSA_FILE" rm -f "$TSA_FILE" done diff --git a/dockers/docker-fpm-frr/TSB b/dockers/docker-fpm-frr/TSB index 50f1ebc3ce8b..add7eda94504 100755 --- a/dockers/docker-fpm-frr/TSB +++ b/dockers/docker-fpm-frr/TSB @@ -16,7 +16,8 @@ then TSB_FILE=$(mktemp) for route_map_name in $(echo "$config" | sed -ne 's/ neighbor \S* route-map \(\S*\) out/\1/p' | uniq); do - is_internal_route_map $route_map_name && continue + is_internal_route_map $route_map_name + internal_route_map=$? case "$route_map_name" in *V4*) ;; @@ -26,7 +27,7 @@ then continue ;; esac - sonic-cfggen -d -a "{\"route_map_name\":\"$route_map_name\"}" -t /usr/share/sonic/templates/bgpd/tsa/bgpd.tsa.unisolate.conf.j2 > "$TSB_FILE" + sonic-cfggen -d -a "{\"route_map_name\":\"$route_map_name\", \"internal_route_map\": \"$internal_route_map\"}" -t /usr/share/sonic/templates/bgpd/tsa/bgpd.tsa.unisolate.conf.j2 > "$TSB_FILE" vtysh -f "$TSB_FILE" rm -f "$TSB_FILE" done diff --git a/dockers/docker-fpm-frr/base_image_files/TS b/dockers/docker-fpm-frr/base_image_files/TS index e0e7ce0ebabf..fcff1f80674c 100755 --- a/dockers/docker-fpm-frr/base_image_files/TS +++ b/dockers/docker-fpm-frr/base_image_files/TS @@ -65,3 +65,17 @@ else docker exec -i bgp /usr/bin/$1 fi fi + +# If TSA was issued by startup_tsa_tsb.service, show it +if [[ $1 == "TSC" ]]; then + service='startup_tsa_tsb.service' + if [[ $(/bin/systemctl show $service --property ActiveState --value) == "active" ]] && \ + [[ $(/bin/systemctl show $service --property SubState --value) == "running" ]]; then + TSA_TSB_CONF=/usr/share/sonic/device/$PLATFORM/startup-tsa-tsb.conf + [ -f $TSA_TSB_CONF ] && . $TSA_TSB_CONF + service_start_sec=$(date -d "$(systemctl show --property=ActiveEnterTimestamp $service --value)" +%s) + service_elapsed_sec=$(( $(date +%s) - service_start_sec)) + tsb_time_remaining=$((STARTUP_TSB_TIMER - service_elapsed_sec)) + echo "TSB : Pending (Time Remaining:$tsb_time_remaining seconds, service:$service)" + fi +fi diff --git a/dockers/docker-fpm-frr/base_image_files/TSA b/dockers/docker-fpm-frr/base_image_files/TSA index eba79c6ae87b..4b26b2d430b5 100755 --- a/dockers/docker-fpm-frr/base_image_files/TSA +++ b/dockers/docker-fpm-frr/base_image_files/TSA @@ -1,5 +1,17 @@ #!/bin/bash +# Restrict command to sudo users +if [ "$EUID" -ne 0 ] ; then + echo "Root priveleges are needed for this operation" + exit 1 +fi + +if [ -f /etc/sonic/chassisdb.conf ]; then + rexec all -c "sudo TSA chassis" + echo "Please execute \"rexec all -c 'sudo config save -y'\" to preserve System mode in Maintenance after reboot\ + or config reload on all linecards" + exit 0 +fi # toggle the mux to standby if dualtor and any mux active if [[ "$(sonic-cfggen -d -v DEVICE_METADATA.localhost.subtype | tr [:upper:] [:lower:])" == *"dualtor"* ]] && @@ -9,5 +21,21 @@ then sudo config mux mode standby all fi +if [ -z "$STARTED_BY_TSA_TSB_SERVICE" ]; then + service='startup_tsa_tsb.service' + if [[ $(/bin/systemctl show $service --property ActiveState --value) == "active" ]] && \ + [[ $(/bin/systemctl show $service --property SubState --value) == "running" ]]; then + echo "Stopping $service before configuring TSA" + systemctl stop $service + fi +fi + /usr/bin/TS TSA -echo "Please execute 'config save' to preserve System mode in Maintenance after reboot or config reload" +if [[ "$(sonic-cfggen -d -v DEVICE_METADATA.localhost.type)" == *"SpineRouter"* ]] ; then + if [[ "$1" != "chassis" ]] ; then + echo "Please execute 'sudo config save' to preserve System mode in Maintenance after reboot or config reload" + echo -e "\nWARNING: Please execute 'TSA' on all other linecards of the chassis to fully isolate this device" + fi +else + echo "Please execute 'sudo config save' to preserve System mode in Maintenance after reboot or config reload" +fi diff --git a/dockers/docker-fpm-frr/base_image_files/TSB b/dockers/docker-fpm-frr/base_image_files/TSB index 1343a6349f9d..ec353148a72f 100755 --- a/dockers/docker-fpm-frr/base_image_files/TSB +++ b/dockers/docker-fpm-frr/base_image_files/TSB @@ -1,5 +1,19 @@ #!/bin/bash +# Restrict command to sudo users +if [ "$EUID" -ne 0 ] ; then + echo "Root priveleges are needed for this operation" + exit 1 +fi + +# If run on supervisor of chassis, trigger remote execution of TSB on all linecards +if [ -f /etc/sonic/chassisdb.conf ]; then + rexec all -c "sudo TSB chassis" + echo "Please execute \"rexec all -c 'sudo config save -y'\" to preserve System mode in Normal state after reboot\ + or config reload on all linecards" + exit 0 +fi + # toggle the mux to auto if dualtor if [[ "$(sonic-cfggen -d -v DEVICE_METADATA.localhost.subtype | tr [:upper:] [:lower:])" == *"dualtor"* ]]; then @@ -7,5 +21,20 @@ then sudo config mux mode auto all fi +if [ -z "$STARTED_BY_TSA_TSB_SERVICE" ]; then + service='startup_tsa_tsb.service' + if [[ $(/bin/systemctl show $service --property ActiveState --value) == "active" ]] && \ + [[ $(/bin/systemctl show $service --property SubState --value) == "running" ]]; then + echo "Stopping $service before configuring TSB" + systemctl stop $service + fi +fi + /usr/bin/TS TSB -echo "Please execute 'config save' to preserve System mode in Normal state after reboot or config reload" +if [[ "$(sonic-cfggen -d -v DEVICE_METADATA.localhost.type)" == *"SpineRouter"* ]] ; then + if [[ "$1" != "chassis" ]] ; then + echo "Please execute 'sudo config save' to preserve System mode in Normal state after reboot or config reload" + fi +else + echo "Please execute 'sudo config save' to preserve System mode in Normal state after reboot or config reload" +fi diff --git a/dockers/docker-fpm-frr/base_image_files/TSC b/dockers/docker-fpm-frr/base_image_files/TSC index 12af5d621af7..bcdd9d1872ae 100755 --- a/dockers/docker-fpm-frr/base_image_files/TSC +++ b/dockers/docker-fpm-frr/base_image_files/TSC @@ -1,8 +1,22 @@ #!/bin/bash -/usr/bin/TS TSC +# Restrict command to sudo users +if [ "$EUID" -ne 0 ] ; then + echo "Root priveleges are needed for this operation" + exit 1 +fi -portstat -p 5 +if [ -f /etc/sonic/chassisdb.conf ]; then + if [[ $1 == "no-stats" ]]; then + rexec all -c "sudo TSC no-stats" + else + rexec all -c "sudo TSC" + fi + exit 0 +fi + +/usr/bin/TS TSC +[[ $1 != "no-stats" ]] && portstat -p 5 if [[ "$(sonic-cfggen -d -v DEVICE_METADATA.localhost.subtype | tr [:upper:] [:lower:])" == *"dualtor"* ]] then 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 c1418e4cfc8e..923b218ec239 100644 --- a/dockers/docker-fpm-frr/frr/bgpd/bgpd.main.conf.j2 +++ b/dockers/docker-fpm-frr/frr/bgpd/bgpd.main.conf.j2 @@ -93,6 +93,9 @@ router bgp {{ DEVICE_METADATA['localhost']['bgp_asn'] }} {% if get_ipv6_loopback_address(LOOPBACK_INTERFACE, "Loopback0") != 'None' %} address-family ipv6 network {{ get_ipv6_loopback_address(LOOPBACK_INTERFACE, "Loopback0") | ip }}/64 +{% if DEVICE_METADATA['localhost']['switch_type'] == 'voq' or DEVICE_METADATA['localhost']['switch_type'] == 'chassis-packet' %} + network {{ get_ipv6_loopback_address(LOOPBACK_INTERFACE, "Loopback0") | ip }}/128 route-map HIDE_INTERNAL +{% endif %} exit-address-family {% endif %} {% if ((multi_asic is defined and DEVICE_METADATA['localhost']['switch_type'] != 'chassis-packet') or (DEVICE_METADATA['localhost']['switch_type'] == 'voq')) %} diff --git a/dockers/docker-fpm-frr/frr/bgpd/templates/internal/policies.conf.j2 b/dockers/docker-fpm-frr/frr/bgpd/templates/internal/policies.conf.j2 index 855a68635653..bedc6eeea422 100644 --- a/dockers/docker-fpm-frr/frr/bgpd/templates/internal/policies.conf.j2 +++ b/dockers/docker-fpm-frr/frr/bgpd/templates/internal/policies.conf.j2 @@ -4,26 +4,65 @@ ! {% from "common/functions.conf.j2" import get_ipv4_loopback_address %} ! -route-map FROM_BGP_INTERNAL_PEER_V4 permit 100 -! -route-map TO_BGP_INTERNAL_PEER_V4 permit 100 -! +{% if CONFIG_DB__DEVICE_METADATA['localhost']['sub_role'] == 'BackEnd' %} +route-map FROM_BGP_INTERNAL_PEER_V4 permit 1 + set originator-id {{ get_ipv4_loopback_address(CONFIG_DB__LOOPBACK_INTERFACE, "Loopback4096") | ip }} ! route-map FROM_BGP_INTERNAL_PEER_V6 permit 1 set ipv6 next-hop prefer-global on-match next ! -route-map FROM_BGP_INTERNAL_PEER_V6 permit 100 +route-map FROM_BGP_INTERNAL_PEER_V6 permit 2 + set originator-id {{ get_ipv4_loopback_address(CONFIG_DB__LOOPBACK_INTERFACE, "Loopback4096") | ip }} +{% elif CONFIG_DB__DEVICE_METADATA['localhost']['switch_type'] == 'chassis-packet' %} +bgp community-list standard DEVICE_INTERNAL_COMMUNITY permit {{ constants.bgp.internal_community }} +bgp community-list standard NO_EXPORT permit no-export ! -route-map TO_BGP_INTERNAL_PEER_V6 permit 100 +route-map FROM_BGP_INTERNAL_PEER_V4 permit 1 + match community DEVICE_INTERNAL_COMMUNITY + set comm-list DEVICE_INTERNAL_COMMUNITY delete + set tag {{ constants.bgp.internal_community_match_tag }} ! -{% if CONFIG_DB__DEVICE_METADATA['localhost']['sub_role'] == 'BackEnd' %} route-map FROM_BGP_INTERNAL_PEER_V4 permit 2 - set originator-id {{ get_ipv4_loopback_address(CONFIG_DB__LOOPBACK_INTERFACE, "Loopback4096") | ip }} + match community NO_EXPORT + set local-preference 80 +! +route-map FROM_BGP_INTERNAL_PEER_V6 permit 1 + set ipv6 next-hop prefer-global + on-match next ! route-map FROM_BGP_INTERNAL_PEER_V6 permit 2 - set originator-id {{ get_ipv4_loopback_address(CONFIG_DB__LOOPBACK_INTERFACE, "Loopback4096") | ip }} + match community DEVICE_INTERNAL_COMMUNITY + set comm-list DEVICE_INTERNAL_COMMUNITY delete + set tag {{ constants.bgp.internal_community_match_tag }} +! +route-map FROM_BGP_INTERNAL_PEER_V6 permit 3 + match community NO_EXPORT + set local-preference 80 +! +route-map TO_BGP_INTERNAL_PEER_V4 permit 1 + match ip address prefix-list PL_LoopbackV4 + set community {{ constants.bgp.internal_community }} +! +route-map TO_BGP_INTERNAL_PEER_V6 permit 2 + match ipv6 address prefix-list PL_LoopbackV6 + set community {{ constants.bgp.internal_community }} +! +{% else %} +route-map FROM_BGP_INTERNAL_PEER_V6 permit 1 + set ipv6 next-hop prefer-global + on-match next +! {% endif %} ! +route-map FROM_BGP_INTERNAL_PEER_V4 permit 100 +! +route-map FROM_BGP_INTERNAL_PEER_V6 permit 100 +! +route-map TO_BGP_INTERNAL_PEER_V4 permit 100 +! +route-map TO_BGP_INTERNAL_PEER_V6 permit 100 +! +! ! end of template: bgpd/templates/internal/policies.conf.j2 ! diff --git a/dockers/docker-fpm-frr/frr/bgpd/templates/monitors/peer-group.conf.j2 b/dockers/docker-fpm-frr/frr/bgpd/templates/monitors/peer-group.conf.j2 index a36278619015..08df8adf755a 100644 --- a/dockers/docker-fpm-frr/frr/bgpd/templates/monitors/peer-group.conf.j2 +++ b/dockers/docker-fpm-frr/frr/bgpd/templates/monitors/peer-group.conf.j2 @@ -2,11 +2,30 @@ ! template: bgpd/templates/BGPMON/peer-group.conf.j2 ! neighbor BGPMON peer-group +{% if CONFIG_DB__DEVICE_METADATA['localhost']['type'] == 'SpineRouter' %} + neighbor BGPMON update-source Loopback4096 +{% else %} neighbor BGPMON update-source {{ loopback0_ipv4 | ip }} - neighbor BGPMON route-map FROM_BGPMON in - neighbor BGPMON route-map TO_BGPMON out - neighbor BGPMON send-community - neighbor BGPMON maximum-prefix 1 +{% endif %} + + address-family ipv4 + neighbor BGPMON activate + neighbor BGPMON route-map FROM_BGPMON in + neighbor BGPMON route-map TO_BGPMON out + neighbor BGPMON send-community + neighbor BGPMON maximum-prefix 1 + exit-address-family + +{% if CONFIG_DB__DEVICE_METADATA['localhost']['type'] == 'SpineRouter' %} + address-family ipv6 + neighbor BGPMON activate + neighbor BGPMON route-map FROM_BGPMON in + neighbor BGPMON route-map TO_BGPMON out + neighbor BGPMON send-community + neighbor BGPMON maximum-prefix 1 + exit-address-family +{% endif %} ! ! end of template: bgpd/templates/BGPMON/peer-group.conf.j2 ! + diff --git a/dockers/docker-fpm-frr/frr/bgpd/templates/voq_chassis/policies.conf.j2 b/dockers/docker-fpm-frr/frr/bgpd/templates/voq_chassis/policies.conf.j2 index c26db7bde241..7002a0ac1a41 100644 --- a/dockers/docker-fpm-frr/frr/bgpd/templates/voq_chassis/policies.conf.j2 +++ b/dockers/docker-fpm-frr/frr/bgpd/templates/voq_chassis/policies.conf.j2 @@ -1,8 +1,24 @@ ! ! template: bgpd/templates/voq_chassis/policies.conf.j2 ! +bgp community-list standard DEVICE_INTERNAL_COMMUNITY permit {{ constants.bgp.internal_community }} +bgp community-list standard NO_EXPORT permit no-export +! +route-map FROM_VOQ_CHASSIS_V4_PEER permit 1 + match community DEVICE_INTERNAL_COMMUNITY + set comm-list DEVICE_INTERNAL_COMMUNITY delete + set tag {{ constants.bgp.internal_community_match_tag }} +! +route-map FROM_VOQ_CHASSIS_V4_PEER permit 2 + match community NO_EXPORT + set local-preference 80 +! route-map FROM_VOQ_CHASSIS_V4_PEER permit 100 ! +route-map TO_VOQ_CHASSIS_V4_PEER permit 1 + match ip address prefix-list PL_LoopbackV4 + set community {{ constants.bgp.internal_community }} +! route-map TO_VOQ_CHASSIS_V4_PEER permit 100 ! ! @@ -10,8 +26,21 @@ route-map FROM_VOQ_CHASSIS_V6_PEER permit 1 set ipv6 next-hop prefer-global on-match next ! +route-map FROM_VOQ_CHASSIS_V6_PEER permit 2 + match community DEVICE_INTERNAL_COMMUNITY + set comm-list DEVICE_INTERNAL_COMMUNITY delete + set tag {{ constants.bgp.internal_community_match_tag }} +! +route-map FROM_VOQ_CHASSIS_V6_PEER permit 3 + match community NO_EXPORT + set local-preference 80 +! route-map FROM_VOQ_CHASSIS_V6_PEER permit 100 ! +route-map TO_VOQ_CHASSIS_V6_PEER permit 1 + match ipv6 address prefix-list PL_LoopbackV6 + set community {{ constants.bgp.internal_community }} +! route-map TO_VOQ_CHASSIS_V6_PEER permit 100 ! ! end of template: bgpd/templates/voq_chassis/policies.conf.j2 diff --git a/dockers/docker-fpm-frr/frr/bgpd/tsa/bgpd.tsa.isolate.conf.j2 b/dockers/docker-fpm-frr/frr/bgpd/tsa/bgpd.tsa.isolate.conf.j2 index 1256d1cd4f96..1d39af2a8942 100644 --- a/dockers/docker-fpm-frr/frr/bgpd/tsa/bgpd.tsa.isolate.conf.j2 +++ b/dockers/docker-fpm-frr/frr/bgpd/tsa/bgpd.tsa.isolate.conf.j2 @@ -1,5 +1,15 @@ +{%- if internal_route_map == '1' -%} +route-map {{ route_map_name }} permit 20 + set community no-export additive +{# #} +{%- else -%} route-map {{ route_map_name }} permit 20 match {{ ip_protocol }} address prefix-list PL_Loopback{{ ip_version }} set community {{ constants.bgp.traffic_shift_community }} -route-map {{ route_map_name }} deny 30 +route-map {{ route_map_name }} permit 30 + match tag {{ constants.bgp.internal_community_match_tag }} + set community {{ constants.bgp.traffic_shift_community }} +route-map {{ route_map_name }} deny 40 +{# #} +{%- endif -%} ! diff --git a/dockers/docker-fpm-frr/frr/bgpd/tsa/bgpd.tsa.unisolate.conf.j2 b/dockers/docker-fpm-frr/frr/bgpd/tsa/bgpd.tsa.unisolate.conf.j2 index 649f6d8e9db8..45caddc2196d 100644 --- a/dockers/docker-fpm-frr/frr/bgpd/tsa/bgpd.tsa.unisolate.conf.j2 +++ b/dockers/docker-fpm-frr/frr/bgpd/tsa/bgpd.tsa.unisolate.conf.j2 @@ -1,3 +1,10 @@ +{%- if internal_route_map == '1' -%} no route-map {{ route_map_name }} permit 20 -no route-map {{ route_map_name }} deny 30 +{# #} +{%- else -%} +no route-map {{ route_map_name }} permit 20 +no route-map {{ route_map_name }} permit 30 +no route-map {{ route_map_name }} deny 40 +{# #} +{%- endif -%} ! diff --git a/dockers/docker-fpm-frr/frr/supervisord/supervisord.conf.j2 b/dockers/docker-fpm-frr/frr/supervisord/supervisord.conf.j2 index 105c03345b48..2c99eb66f7c5 100644 --- a/dockers/docker-fpm-frr/frr/supervisord/supervisord.conf.j2 +++ b/dockers/docker-fpm-frr/frr/supervisord/supervisord.conf.j2 @@ -141,6 +141,20 @@ stderr_logfile=syslog dependent_startup=true dependent_startup_wait_for=bgpd:running +{% if DEVICE_METADATA.localhost.frr_mgmt_framework_config is defined and DEVICE_METADATA.localhost.frr_mgmt_framework_config == "true" %} +{% else %} +[program:staticroutebfd] +command=/usr/local/bin/staticroutebfd +priority=6 +autostart=false +autorestart=true +startsecs=0 +stdout_logfile=syslog +stderr_logfile=syslog +dependent_startup=true +dependent_startup_wait_for=bgpd:running +{% endif %} + [program:bgpmon] command=/usr/local/bin/bgpmon priority=6 diff --git a/dockers/docker-fpm-frr/frr/zebra/zebra.interfaces.conf.j2 b/dockers/docker-fpm-frr/frr/zebra/zebra.interfaces.conf.j2 index 57d83163d67b..44e8bca8b987 100644 --- a/dockers/docker-fpm-frr/frr/zebra/zebra.interfaces.conf.j2 +++ b/dockers/docker-fpm-frr/frr/zebra/zebra.interfaces.conf.j2 @@ -12,6 +12,7 @@ vni {{ vnet_metadata['vni'] }} {% block interfaces %} ! Enable nht through default route ip nht resolve-via-default +ipv6 nht resolve-via-default ! Enable link-detect (default disabled) {% for (name, prefix) in INTERFACE|pfx_filter %} interface {{ name }} diff --git a/dockers/docker-macsec/cli-plugin-tests/config_db.json b/dockers/docker-macsec/cli-plugin-tests/config_db.json index 9f4c266d4284..d145fb7c724e 100644 --- a/dockers/docker-macsec/cli-plugin-tests/config_db.json +++ b/dockers/docker-macsec/cli-plugin-tests/config_db.json @@ -11,14 +11,14 @@ "PORT|Ethernet0": { "alias": "Ethernet1/1", "asic_port_name": "Eth0-ASIC0", - "coreid": "1", - "coreportid": "1", + "core_id": "1", + "core_port_id": "1", "description": "Ethernet1/1", "index": "1", "lanes": "72,73,74,75,76,77,78,79", "macsec": "macsec_profile", "mtu": "9100", - "numvoq": "8", + "num_voq": "8", "pfc_asym": "off", "role": "Ext", "speed": "400000", @@ -27,14 +27,14 @@ "PORT|Ethernet1": { "alias": "Ethernet2/1", "asic_port_name": "Eth0-ASIC0", - "coreid": "1", - "coreportid": "1", + "core_id": "1", + "core_port_id": "1", "description": "Ethernet2/1", "index": "1", "lanes": "72,73,74,75,76,77,78,79", "macsec": "macsec_profile", "mtu": "9100", - "numvoq": "8", + "num_voq": "8", "pfc_asym": "off", "role": "Ext", "speed": "400000", @@ -43,14 +43,14 @@ "PORT|Ethernet4": { "alias": "Ethernet5/1", "asic_port_name": "Eth0-ASIC0", - "coreid": "1", - "coreportid": "1", + "core_id": "1", + "core_port_id": "1", "description": "Ethernet5/1", "index": "1", "lanes": "72,73,74,75,76,77,78,79", "macsec": "macsec_profile", "mtu": "9100", - "numvoq": "8", + "num_voq": "8", "pfc_asym": "off", "role": "Ext", "speed": "400000", @@ -59,14 +59,14 @@ "PORT|Ethernet5": { "alias": "Ethernet6/1", "asic_port_name": "Eth0-ASIC0", - "coreid": "1", - "coreportid": "1", + "core_id": "1", + "core_port_id": "1", "description": "Ethernet6/1", "index": "1", "lanes": "72,73,74,75,76,77,78,79", "macsec": "macsec_profile", "mtu": "9100", - "numvoq": "8", + "num_voq": "8", "pfc_asym": "off", "role": "Ext", "speed": "400000", diff --git a/files/build_templates/docker_image_ctl.j2 b/files/build_templates/docker_image_ctl.j2 index dc677204e726..d0b053459bbd 100644 --- a/files/build_templates/docker_image_ctl.j2 +++ b/files/build_templates/docker_image_ctl.j2 @@ -376,27 +376,32 @@ start() { DOCKERCHECK=`docker inspect --type container ${DOCKERNAME} 2>/dev/null` if [ "$?" -eq "0" ]; then - {%- if docker_container_name == "database" %} - DOCKERMOUNT="" + {%- if docker_container_name == "database" and sonic_asic_platform == "vs" %} + echo "Removing existing ${DOCKERNAME} container" + docker rm -f ${DOCKERNAME} {%- else %} - DOCKERMOUNT=`getMountPoint "$DOCKERCHECK"` - {%- endif %} - if [ x"$DOCKERMOUNT" == x"$MOUNTPATH" ]; then - preStartAction {%- if docker_container_name == "database" %} - echo "Starting existing ${DOCKERNAME} container" - docker start ${DOCKERNAME} + DOCKERMOUNT="" {%- else %} - echo "Starting existing ${DOCKERNAME} container with HWSKU $HWSKU" - /usr/local/bin/container start ${DOCKERNAME} + DOCKERMOUNT=`getMountPoint "$DOCKERCHECK"` {%- endif %} - postStartAction - exit $? - fi + if [ x"$DOCKERMOUNT" == x"$MOUNTPATH" ]; then + preStartAction + {%- if docker_container_name == "database" %} + echo "Starting existing ${DOCKERNAME} container" + docker start ${DOCKERNAME} + {%- else %} + echo "Starting existing ${DOCKERNAME} container with HWSKU $HWSKU" + /usr/local/bin/container start ${DOCKERNAME} + {%- endif %} + postStartAction + exit $? + fi - # docker created with a different HWSKU, remove and recreate - echo "Removing obsolete ${DOCKERNAME} container with HWSKU $DOCKERMOUNT" - docker rm -f ${DOCKERNAME} + # docker created with a different HWSKU, remove and recreate + echo "Removing obsolete ${DOCKERNAME} container with HWSKU $DOCKERMOUNT" + docker rm -f ${DOCKERNAME} + {%- endif %} fi {%- if docker_container_name == "database" %} diff --git a/files/build_templates/init_cfg.json.j2 b/files/build_templates/init_cfg.json.j2 index 1080d018a05b..e6563762b0a2 100644 --- a/files/build_templates/init_cfg.json.j2 +++ b/files/build_templates/init_cfg.json.j2 @@ -116,5 +116,16 @@ "digits_class": "true", "special_class": "true" } + }, + "KDUMP": { + "config": { +{%- if sonic_asic_platform == "cisco-8000" %} + "enabled": "true", +{% else %} + "enabled": "false", +{% endif %} + "memory": "0M-2G:256M,2G-4G:320M,4G-8G:384M,8G-:448M", + "num_dumps": "3" + } } } diff --git a/files/build_templates/sonic_debian_extension.j2 b/files/build_templates/sonic_debian_extension.j2 index ce71eed7c29c..0c4bade6d1a3 100644 --- a/files/build_templates/sonic_debian_extension.j2 +++ b/files/build_templates/sonic_debian_extension.j2 @@ -78,6 +78,10 @@ fi # Update apt's snapshot of its repos sudo LANG=C DEBIAN_FRONTEND=noninteractive chroot $FILESYSTEM_ROOT apt-get update +# Install efitools to support secure upgrade +sudo LANG=C DEBIAN_FRONTEND=noninteractive chroot $FILESYSTEM_ROOT apt-get -y install efitools +sudo LANG=C DEBIAN_FRONTEND=noninteractive chroot $FILESYSTEM_ROOT apt-get -y install mokutil + # Apply environtment configuration files sudo cp $IMAGE_CONFIGS/environment/environment $FILESYSTEM_ROOT/etc/ sudo cp $IMAGE_CONFIGS/environment/motd $FILESYSTEM_ROOT/etc/ @@ -210,6 +214,9 @@ sudo LANG=C DEBIAN_FRONTEND=noninteractive chroot $FILESYSTEM_ROOT apt-get -y in # Install prerequisites needed for using the Python m2crypto package, used by sonic-utilities sudo LANG=C DEBIAN_FRONTEND=noninteractive chroot $FILESYSTEM_ROOT apt-get -y install openssl +# install libffi-dev to match utilities' dependency. +sudo LANG=C DEBIAN_FRONTEND=noninteractive chroot $FILESYSTEM_ROOT apt-get -y install libffi-dev + # Install SONiC Utilities Python package SONIC_UTILITIES_PY3_WHEEL_NAME=$(basename {{sonic_utilities_py3_wheel_path}}) sudo cp {{sonic_utilities_py3_wheel_path}} $FILESYSTEM_ROOT/$SONIC_UTILITIES_PY3_WHEEL_NAME @@ -864,6 +871,7 @@ sudo LANG=C cp $SCRIPTS_DIR/telemetry.sh $FILESYSTEM_ROOT/usr/local/bin/telemetr sudo LANG=C cp $SCRIPTS_DIR/mgmt-framework.sh $FILESYSTEM_ROOT/usr/local/bin/mgmt-framework.sh sudo LANG=C cp $SCRIPTS_DIR/asic_status.sh $FILESYSTEM_ROOT/usr/local/bin/asic_status.sh sudo LANG=C cp $SCRIPTS_DIR/asic_status.py $FILESYSTEM_ROOT/usr/local/bin/asic_status.py +sudo LANG=C cp $SCRIPTS_DIR/startup_tsa_tsb.py $FILESYSTEM_ROOT/usr/local/bin/startup_tsa_tsb.py # Copy sonic-netns-exec script sudo LANG=C cp $SCRIPTS_DIR/sonic-netns-exec $FILESYSTEM_ROOT/usr/bin/sonic-netns-exec @@ -892,6 +900,9 @@ echo "mgmt-framework.timer" | sudo tee -a $GENERATED_SERVICE_FILE sudo cp $BUILD_TEMPLATES/pmon.timer $FILESYSTEM_ROOT_USR_LIB_SYSTEMD_SYSTEM echo "pmon.timer" | sudo tee -a $GENERATED_SERVICE_FILE +sudo cp files/build_templates/startup_tsa_tsb.service $FILESYSTEM_ROOT_USR_LIB_SYSTEMD_SYSTEM/ +echo "startup_tsa_tsb.service" | sudo tee -a $GENERATED_SERVICE_FILE + sudo cp $BUILD_TEMPLATES/sonic.target $FILESYSTEM_ROOT_USR_LIB_SYSTEMD_SYSTEM sudo LANG=C chroot $FILESYSTEM_ROOT systemctl enable sonic.target diff --git a/files/build_templates/startup_tsa_tsb.service b/files/build_templates/startup_tsa_tsb.service new file mode 100644 index 000000000000..5bc15c62962d --- /dev/null +++ b/files/build_templates/startup_tsa_tsb.service @@ -0,0 +1,15 @@ +[Unit] +Description= STARTUP TSA-TSB SERVICE +Requires=updategraph.service database.service +After=updategraph.service database.service +Before=bgp.service +ConditionPathExists=!/etc/sonic/chassisdb.conf + +[Service] +Environment="STARTED_BY_TSA_TSB_SERVICE=1" +ExecStart=/usr/bin/python3 -u /usr/local/bin/startup_tsa_tsb.py start +ExecStop=/usr/bin/python3 -u /usr/local/bin/startup_tsa_tsb.py stop +RemainAfterExit=yes + +[Install] +WantedBy=multi-user.target diff --git a/files/image_config/constants/constants.yml b/files/image_config/constants/constants.yml index 94f3d0e9706c..413d93551335 100644 --- a/files/image_config/constants/constants.yml +++ b/files/image_config/constants/constants.yml @@ -4,6 +4,8 @@ constants: "2" : 65433 bgp: traffic_shift_community: 12345:12345 + internal_community: 11111:11111 + internal_community_match_tag: 1002 families: - ipv4 - ipv6 diff --git a/files/image_config/hostname/hostname-config.sh b/files/image_config/hostname/hostname-config.sh index c2a4f1e546ce..5f4bfede2097 100755 --- a/files/image_config/hostname/hostname-config.sh +++ b/files/image_config/hostname/hostname-config.sh @@ -11,10 +11,16 @@ fi echo $HOSTNAME > /etc/hostname hostname -F /etc/hostname +#Don't update the /etc/hosts if hostname is not changed +#This is to prevent intermittent redis_chassis.server reachability issue +if [ $CURRENT_HOSTNAME == $HOSTNAME ] ; then + exit 0 +fi + # Remove the old hostname entry from hosts file. # But, 'localhost' entry is used by multiple applications. Don't remove it altogether. # Edit contents of /etc/hosts and put in /etc/hosts.new -if [ $CURRENT_HOSTNAME != "localhost" ] || [ $CURRENT_HOSTNAME == $HOSTNAME ] ; then +if [ $CURRENT_HOSTNAME != "localhost" ] ; then sed "/\s$CURRENT_HOSTNAME$/d" /etc/hosts > /etc/hosts.new else cp -f /etc/hosts /etc/hosts.new diff --git a/files/image_config/topology/topology.service b/files/image_config/topology/topology.service index eea4bf65230a..73fa4d2d0145 100644 --- a/files/image_config/topology/topology.service +++ b/files/image_config/topology/topology.service @@ -12,5 +12,4 @@ ExecStart=/usr/bin/topology.sh start ExecStop=/usr/bin/topology.sh stop [Install] -WantedBy=multi-user.target - +WantedBy=sonic.target diff --git a/files/image_config/topology/topology.sh b/files/image_config/topology/topology.sh index 2f038095be62..995cb8804379 100755 --- a/files/image_config/topology/topology.sh +++ b/files/image_config/topology/topology.sh @@ -22,12 +22,99 @@ get_hwsku() { echo "${HWSKU}" } +bind_ports_to_ns() { + PLATFORM="$1" + HWSKU="$2" + BIND="$3" + + # Check if the directory exists + if [[ ! -d "/usr/share/sonic/device/$PLATFORM/$HWSKU" ]]; then + echo "Directory /usr/share/sonic/device/$PLATFORM/$HWSKU does not exist" + exit 1 + fi + + # Read NUM_ASIC from asic.conf file + asic_conf="/usr/share/sonic/device/$PLATFORM/asic.conf" + if [[ ! -f "$asic_conf" ]]; then + echo "Error: $asic_conf file not found" + exit 1 + fi + + # Read NUM_ASIC from asic.conf file + num_asic=$(awk -F "=" '/^NUM_ASIC=/ {print $2}' "$asic_conf") + if [[ -z $num_asic ]]; then + echo "NUM_ASIC not found in $asic_conf" + exit 1 + fi + + for ((asic_num = 0; asic_num < num_asic; asic_num++)); do + echo "Processing $PLATFORM/$HWSKU/$asic_num" + asic_dir="/usr/share/sonic/device/$PLATFORM/$HWSKU/$asic_num" + + # Check if the directory exists for the ASIC number + if [[ ! -d "$asic_dir" ]]; then + echo "Directory $asic_dir does not exist" + exit 1 + fi + + lanemap_ini="$asic_dir/lanemap.ini" + + if [[ ! -f "$lanemap_ini" ]]; then + echo "lanemap.ini not found in $asic_dir" + exit 1 + fi + + # Loop through each line of lanemap.ini + while IFS= read -r line; do + # Extract interface before ":" + intf=$(echo "$line" | cut -d ":" -f 1) + if [[ $BIND == true ]]; then + echo "Moving interface $intf to asic$asic_num" + if [[ $intf == "Cpu0" ]]; then + # Extract the numeric part of the interface name + num="${prev#eth}" + # Increment the numeric part + ((num++)) + # Construct the new interface name + cur="eth$num" + echo "Renaming $cur to $intf" + ip link sev dev $cur down + ip link set dev $cur name $intf + fi + ip link set dev $intf netns asic$asic_num + sudo ip netns exec asic$asic_num ip link set dev $intf mtu 9100 + sudo ip netns exec asic$asic_num ip link set $intf up + else + echo "Moving interface $intf back to default ns" + sudo ip netns exec asic$asic_num ip link set dev $intf netns 1 + if [[ $intf == "Cpu0" ]]; then + # Extract the numeric part of the interface name + num="${prev#eth}" + # Increment the numeric part + ((num++)) + # Construct the new interface name + cur="eth$num" + echo "Renaming $intf to $cur" + ip link set dev $intf down + ip link set dev $intf name $cur + ip link set dev $cur up + fi + fi + prev=$intf + done < "$lanemap_ini" + done + exit 0 # Exit script with success +} + + start() { TOPOLOGY_SCRIPT="topology.sh" PLATFORM=`sonic-cfggen -H -v DEVICE_METADATA.localhost.platform` HWSKU=`get_hwsku` - if [[ $HWSKU != "" ]]; then + if [[ $HWSKU == "msft_"* ]]; then /usr/share/sonic/device/$PLATFORM/$HWSKU/$TOPOLOGY_SCRIPT start + elif [[ $HWSKU != "" ]]; then + bind_ports_to_ns "$PLATFORM" "$HWSKU" true else echo "Failed to get HWSKU" exit 1 @@ -38,8 +125,10 @@ stop() { TOPOLOGY_SCRIPT="topology.sh" PLATFORM=`sonic-cfggen -H -v DEVICE_METADATA.localhost.platform` HWSKU=`get_hwsku` - if [[ $HWSKU != "" ]]; then + if [[ $HWSKU == "msft_"* ]]; then /usr/share/sonic/device/$PLATFORM/$HWSKU/$TOPOLOGY_SCRIPT stop + elif [[ $HWSKU != "" ]]; then + bind_ports_to_ns "$PLATFORM" "$HWSKU" false else echo "Failed to get HWSKU" exit 1 diff --git a/files/scripts/asic_status.py b/files/scripts/asic_status.py index 81a7aabc9758..a518caac8b43 100755 --- a/files/scripts/asic_status.py +++ b/files/scripts/asic_status.py @@ -69,8 +69,9 @@ def main(): logger.log_info('Detected asic{} is online'.format(global_asic_id)) sys.exit(0) elif asic_op == 'DEL': - logger.log_info('Detected asic{} is offline'.format(global_asic_id)) - sys.exit(1) + if (global_asic_id == args_asic_id): + logger.log_info('Detected asic{} is offline'.format(global_asic_id)) + sys.exit(1) else: continue diff --git a/files/scripts/startup_tsa_tsb.py b/files/scripts/startup_tsa_tsb.py new file mode 100644 index 000000000000..5d0495ead601 --- /dev/null +++ b/files/scripts/startup_tsa_tsb.py @@ -0,0 +1,156 @@ +#!/usr/bin/env python3 + +# Name: startup_tsa_tsb.py, version: 1.0 +# +# Description: Module contains the definitions to the VOQ Startup TSA-TSB service +from sonic_py_common import multi_asic, device_info +from sonic_py_common.logger import Logger +import subprocess +import sys, getopt +from threading import Timer +import os + +# Global Logger class instance +logger = Logger("startup_tsa_tsb") +logger.set_min_log_priority_info() + +def get_tsb_timer_interval(): + platform = device_info.get_platform() + conf_file = '/usr/share/sonic/device/{}/startup-tsa-tsb.conf'.format(platform) + file = open(conf_file, 'r') + Lines = file.readlines() + for line in Lines: + field = line.split('=')[0].strip() + if field == "STARTUP_TSB_TIMER": + return line.split('=')[1].strip() + return 0 + +def get_sonic_config(ns, config_name): + if ns == "": + return subprocess.check_output(['sonic-cfggen', '-d', '-v', config_name.replace('"', "'"), ]).strip() + else: + return subprocess.check_output(['sonic-cfggen', '-d', '-v', config_name.replace('"', "'"), '-n', ns.replace('"', "'")]).strip() + +def get_sub_role(asic_ns): + sub_role_config = "DEVICE_METADATA['localhost']['sub_role']" + sub_role = (get_sonic_config(asic_ns, sub_role_config)).decode() + return sub_role + +def get_tsa_config(asic_ns): + tsa_config = 'BGP_DEVICE_GLOBAL.STATE.tsa_enabled' + tsa_ena = (get_sonic_config(asic_ns, tsa_config)).decode() + if asic_ns == "": + logger.log_info('CONFIG_DB.{} : {}'.format(tsa_config, tsa_ena)) + else: + logger.log_info('{} - CONFIG_DB.{} : {}'.format(asic_ns, tsa_config, tsa_ena)) + return tsa_ena + +def get_tsa_status(num_asics): + if num_asics > 1: + counter = 0 + for asic_id in range(int(num_asics)): + asic_ns = 'asic{}'.format(asic_id) + sub_role = get_sub_role(asic_ns) + if sub_role == 'FrontEnd': + tsa_enabled = get_tsa_config(asic_ns) + if tsa_enabled == 'false': + counter += 1 + if counter == int(num_asics): + return True; + else: + tsa_enabled = get_tsa_config("") + if tsa_enabled == 'false': + return True; + return False; + +def config_tsa(): + num_asics = multi_asic.get_num_asics() + tsa_ena = get_tsa_status(num_asics) + if tsa_ena == True: + logger.log_info("Configuring TSA") + subprocess.check_output(['TSA']).strip() + else: + if num_asics > 1: + logger.log_info("Either TSA is already configured or switch sub_role is not Frontend - not configuring TSA") + else: + logger.log_info("Either TSA is already configured - not configuring TSA") + return tsa_ena + +def config_tsb(): + logger.log_info("Configuring TSB") + subprocess.check_output(['TSB']).strip() + tsb_issued = True + return + +def start_tsb_timer(interval): + global timer + logger.log_info("Starting timer with interval {} seconds to configure TSB".format(interval)) + timer = Timer(int(interval), config_tsb) + timer.start() + timer.join() + return + +def print_usage(): + logger.log_info("Usage: startup_tsa_tsb.py [options] command") + logger.log_info("options:") + logger.log_info(" -h | --help : this help message") + logger.log_info("command:") + logger.log_info("start : start the TSA/TSB") + logger.log_info("stop : stop the TSA/TSB") + return + +def reset_env_variables(): + logger.log_info("Resetting environment variable") + os.environ.pop('STARTED_BY_TSA_TSB_SERVICE') + return + +def start_tsa_tsb(timer): + #Configure TSA if it was not configured already in CONFIG_DB + tsa_enabled = config_tsa() + if tsa_enabled == True: + #Start the timer to configure TSB + start_tsb_timer(timer) + return + +def stop_tsa_tsb(): + reset_env_variables() + return + +def main(): + platform = device_info.get_platform() + conf_file = '/usr/share/sonic/device/{}/startup-tsa-tsb.conf'.format(platform) + #This check should be moved to service file or make this feature as configurable. + #Adding it here for now. + if not os.path.exists(conf_file): + logger.log_info("{} does not exist, exiting the service".format(conf_file)) + return + if len(sys.argv) <= 1: + print_usage() + return + + # parse command line options: + try: + opts, args = getopt.getopt(sys.argv[1:], 'h:', ['help' ]) + except getopt.GetoptError: + print_usage() + return + + for opt, arg in opts: + if opt in ("-h", "--help"): + print_usage() + return + + for arg in args: + if arg == 'start': + tsb_timer = get_tsb_timer_interval() + start_tsa_tsb(tsb_timer) + elif arg == 'stop': + stop_tsa_tsb() + else: + print_usage() + return + + return + +if __name__ == "__main__": + main() diff --git a/files/scripts/swss.sh b/files/scripts/swss.sh index dac74d19d4e4..f39d338656d7 100755 --- a/files/scripts/swss.sh +++ b/files/scripts/swss.sh @@ -132,12 +132,23 @@ function clean_up_chassis_db_tables() return fi - if [[ !($($SONIC_DB_CLI CHASSIS_APP_DB PING | grep -c True) -gt 0) ]]; then - return - fi + until [[ $($SONIC_DB_CLI CHASSIS_APP_DB PING | grep -c True) -gt 0 ]]; do + sleep 1 + done lc=`$SONIC_DB_CLI CONFIG_DB hget 'DEVICE_METADATA|localhost' 'hostname'` + until [[ -n "${lc}" ]]; do + lc=`$SONIC_DB_CLI CONFIG_DB hget 'DEVICE_METADATA|localhost' 'hostname'` + sleep 1 + done + debug "Chassis db clean up for ${SERVICE}$DEV. hostname=$lc" + asic=`$SONIC_DB_CLI CONFIG_DB hget 'DEVICE_METADATA|localhost' 'asic_name'` + until [[ -n "${asic}" ]]; do + asic=`$SONIC_DB_CLI CONFIG_DB hget 'DEVICE_METADATA|localhost' 'asic_name'` + sleep 1 + done + debug "Chassis db clean up for ${SERVICE}$DEV. asic=$asic" # First, delete SYSTEM_NEIGH entries num_neigh=`$SONIC_DB_CLI CHASSIS_APP_DB EVAL " diff --git a/installer/x86_64/install.sh b/installer/x86_64/install.sh index 87c37243dc31..c27c4bc25784 100755 --- a/installer/x86_64/install.sh +++ b/installer/x86_64/install.sh @@ -415,6 +415,59 @@ demo_install_grub() } +# Install UEFI BIOS SHIM for DEMO OS +demo_install_uefi_shim() +{ + echo "demo_install_uefi_shim(): Installing Secure Boot components" + local demo_mnt="$1" + local blk_dev="$2" + # make sure /boot/efi is mounted + if ! mount | grep -q "/boot/efi"; then + mount /boot/efi + fi + # Look for the EFI system partition UUID on the same block device as + # the ONIE-BOOT partition. + local uefi_part=0 + for p in $(seq 8) ; do + if sgdisk -i $p $blk_dev | grep -q C12A7328-F81F-11D2-BA4B-00A0C93EC93B ; then + uefi_part=$p + break + fi + done + [ $uefi_part -eq 0 ] && { + echo "ERROR: Unable to determine UEFI system partition" + exit 1 + } + echo "creating demo_volume_label=$demo_volume_label in dir: /boot/efi/EFI/ ." + mkdir -p /boot/efi/EFI/$demo_volume_label + if [ ! -f $demo_mnt/$image_dir/boot/mmx64.efi ]; then + echo "ERROR: $demo_mnt/$image_dir/boot/mmx64.efi file does not exist" + exit 1 + fi + if [ ! -f $demo_mnt/$image_dir/boot/shimx64.efi ]; then + echo "ERROR: $demo_mnt/$image_dir/boot/shimx64.efi file does not exist" + exit 1 + fi + if [ ! -f $demo_mnt/$image_dir/boot/grubx64.efi ]; then + echo "ERROR: $demo_mnt/$image_dir/boot/grubx64.efi file does not exist" + exit 1 + fi + echo "copying signed shim, mm, grub, grub.cfg from $demo_mnt/$image_dir/boot/ to /boot/efi/EFI/$demo_volume_label directory" + cp $demo_mnt/$image_dir/boot/mmx64.efi /boot/efi/EFI/$demo_volume_label/mmx64.efi + cp $demo_mnt/$image_dir/boot/shimx64.efi /boot/efi/EFI/$demo_volume_label/shimx64.efi + cp $demo_mnt/$image_dir/boot/grubx64.efi /boot/efi/EFI/$demo_volume_label/grubx64.efi + # Configure EFI NVRAM Boot variables. --create also sets the + # new boot number as active. + efibootmgr --quiet --create \ + --label "$demo_volume_label" \ + --disk $blk_dev --part $uefi_part \ + --loader "/EFI/$demo_volume_label/shimx64.efi" || { + echo "ERROR: efibootmgr failed to create new boot variable on: $blk_dev" + exit 1 + } + echo "demo_install_uefi_shim(): Secure Boot components installed successfully" +} + # Install UEFI BIOS GRUB for DEMO OS demo_install_uefi_grub() { @@ -568,8 +621,25 @@ if [ "$install_env" = "onie" ]; then ${onie_bin} onie-support /tmp mv $onie_initrd_tmp/tmp/onie-support*.tar.bz2 $demo_mnt/$image_dir/ + echo "firmware=$firmware" if [ "$firmware" = "uefi" ] ; then - demo_install_uefi_grub "$demo_mnt" "$blk_dev" + secure_boot_state=0 + reg_sb_guid="" + ENABLED=1 + echo "checking secure boot state" + reg_sb_guid=$(efivar -l | grep "SecureBoot$") || echo "Secure Boot GUID not found in efivar list" + echo "Secure Boot GUID=$reg_sb_guid" + if [ -n "$reg_sb_guid" ]; then + secure_boot_state=$(efivar -d --name $reg_sb_guid) || echo "Could not read Secure Boot state from efivar" + fi + echo secure_boot_state=$secure_boot_state + if expr "$secure_boot_state" : '[[:digit:]]\{1,\}' >/dev/null && [ "$secure_boot_state" -eq "$ENABLED" ]; then + echo "UEFI Secure Boot is enabled - Installing shim bootloader" + demo_install_uefi_shim "$demo_mnt" "$blk_dev" + else + echo "UEFI Secure Boot is disabled - Installing regular grub bootloader" + demo_install_uefi_grub "$demo_mnt" "$blk_dev" + fi else demo_install_grub "$demo_mnt" "$blk_dev" fi @@ -669,10 +739,34 @@ else # install_env = "onie" fi fi +# Make a first grub config file that located in default debian path:/boot/efi/EFI/debian/ +# this first grub.cfg will call the complete grub.cfg created below with sonic configuration +tmp_config=$(mktemp) +cat < $tmp_config +search --no-floppy --label --set=root $demo_volume_label +set prefix=(\$root)'/grub' +configfile \$prefix/grub.cfg +EOF +# Copy first grub.cfg as entrypoint to default debian path where grubx64.efi expected it. +mkdir -p /boot/efi/EFI/debian/ +echo "cp $tmp_config /boot/efi/EFI/debian/grub.cfg" +cp $tmp_config /boot/efi/EFI/debian/grub.cfg + # Add extra linux command line extra_cmdline_linux=%%EXTRA_CMDLINE_LINUX%% echo "EXTRA_CMDLINE_LINUX=$extra_cmdline_linux" GRUB_CMDLINE_LINUX="$GRUB_CMDLINE_LINUX $extra_cmdline_linux" +GRUB_CFG_LINUX_CMD="" +GRUB_CFG_INITRD_CMD="" +if [ "$firmware" = "uefi" ] && expr "$secure_boot_state" : '[[:digit:]]\{1,\}' >/dev/null && [ "$secure_boot_state" -eq "$ENABLED" ]; then + # grub.cfg when BIOS is UEFI and support Secure Boot + GRUB_CFG_LINUX_CMD="linuxefi" + GRUB_CFG_INITRD_CMD="initrdefi" +else + # grub.cfg when BIOS is Legacy + GRUB_CFG_LINUX_CMD="linux" + GRUB_CFG_INITRD_CMD="initrd" +fi cat <> $grub_cfg menuentry '$demo_grub_entry' { @@ -682,13 +776,13 @@ menuentry '$demo_grub_entry' { if [ x$grub_platform = xxen ]; then insmod xzio; insmod lzopio; fi insmod part_msdos insmod ext2 - linux /$image_dir/boot/vmlinuz-5.10.0-23-2-amd64 root=$grub_cfg_root rw $GRUB_CMDLINE_LINUX \ + $GRUB_CFG_LINUX_CMD /$image_dir/boot/vmlinuz-5.10.0-23-2-amd64 root=$grub_cfg_root rw $GRUB_CMDLINE_LINUX \ net.ifnames=0 biosdevname=0 \ loop=$image_dir/$FILESYSTEM_SQUASHFS loopfstype=squashfs \ systemd.unified_cgroup_hierarchy=0 \ apparmor=1 security=apparmor varlog_size=$VAR_LOG_SIZE usbcore.autosuspend=-1 $ONIE_PLATFORM_EXTRA_CMDLINE_LINUX echo 'Loading $demo_volume_label $demo_type initial ramdisk ...' - initrd /$image_dir/boot/initrd.img-5.10.0-23-2-amd64 + $GRUB_CFG_INITRD_CMD /$image_dir/boot/initrd.img-5.10.0-23-2-amd64 } EOF @@ -711,6 +805,17 @@ else cp $grub_cfg $onie_initrd_tmp/$demo_mnt/grub/grub.cfg fi +if [ "$secure_boot_state" = "SecureBoot enabled" ]; then + # Secure Boot grub.cfg support + # Saving grub_cfg in the same place where is grubx64.efi, + # this grub_cfg file will be called by first grub.cfg file from: /boot/efi/EFI/debian/grub.cfg + if [ -f $NVOS_BOOT_DIR/grub.cfg ]; then + rm $NVOS_BOOT_DIR/grub.cfg + fi + cp $grub_cfg $NVOS_BOOT_DIR/grub.cfg +fi + + cd / echo "Installed SONiC base image $demo_volume_label successfully" diff --git a/platform/broadcom/platform-modules-nokia.mk b/platform/broadcom/platform-modules-nokia.mk index fb5199375e5e..6a355d17b3aa 100644 --- a/platform/broadcom/platform-modules-nokia.mk +++ b/platform/broadcom/platform-modules-nokia.mk @@ -12,3 +12,7 @@ $(NOKIA_IXR7250_PLATFORM_MODULE)_PLATFORM = x86_64-nokia_ixr7250e_sup-r0 $(NOKIA_IXR7250_PLATFORM_MODULE)_PLATFORM += x86_64-nokia_ixr7250e_36x400g-r0 SONIC_DPKG_DEBS += $(NOKIA_IXR7250_PLATFORM_MODULE) +NDK_VERSION = 22.9.26 +NOKIA_NDK_DEBIAN = ndk_$(NDK_VERSION)_amd64.deb +$(NOKIA_NDK_DEBIAN)_URL = "https://github.com/Nokia-ION/ndk-releases/releases/download/v$(NDK_VERSION)/$(NOKIA_NDK_DEBIAN)" +SONIC_ONLINE_DEBS += $(NOKIA_NDK_DEBIAN) diff --git a/platform/broadcom/sonic-platform-modules-nokia b/platform/broadcom/sonic-platform-modules-nokia index 2b8a303af664..9a752971e84e 160000 --- a/platform/broadcom/sonic-platform-modules-nokia +++ b/platform/broadcom/sonic-platform-modules-nokia @@ -1 +1 @@ -Subproject commit 2b8a303af664d7eb7838429e92fed09a97a3d97c +Subproject commit 9a752971e84e06b33d8f9e20397312eb84dbf4e8 diff --git a/platform/checkout/cisco-8000.ini b/platform/checkout/cisco-8000.ini index 26ff8849ae08..417d6293ae7e 100644 --- a/platform/checkout/cisco-8000.ini +++ b/platform/checkout/cisco-8000.ini @@ -1,3 +1,3 @@ [module] repo=git@github.com:Cisco-8000-sonic/platform-cisco-8000.git -ref=202205.2.3.2 +ref=202205.3.2.4 diff --git a/platform/vs/kvm-image.mk b/platform/vs/kvm-image.mk index 911b7e9a86be..08d013a66f52 100644 --- a/platform/vs/kvm-image.mk +++ b/platform/vs/kvm-image.mk @@ -2,6 +2,7 @@ SONIC_KVM_IMAGE = sonic-vs.img.gz $(SONIC_KVM_IMAGE)_INSTALLS += $(SYSTEMD_SONIC_GENERATOR) +$(SONIC_KVM_IMAGE)_LAZY_INSTALLS += $(VS_PLATFORM_MODULE) $(SONIC_KVM_IMAGE)_MACHINE = vs $(SONIC_KVM_IMAGE)_IMAGE_TYPE = kvm ifeq ($(INSTALL_DEBUG_TOOLS),y) diff --git a/platform/vs/one-image.mk b/platform/vs/one-image.mk index a0e176df1497..0f344a101217 100644 --- a/platform/vs/one-image.mk +++ b/platform/vs/one-image.mk @@ -4,6 +4,7 @@ SONIC_ONE_IMAGE = sonic-vs.bin $(SONIC_ONE_IMAGE)_MACHINE = vs $(SONIC_ONE_IMAGE)_IMAGE_TYPE = onie $(SONIC_ONE_IMAGE)_INSTALLS += $(SYSTEMD_SONIC_GENERATOR) +$(SONIC_ONE_IMAGE)_LAZY_INSTALLS += $(VS_PLATFORM_MODULE) ifeq ($(INSTALL_DEBUG_TOOLS),y) $(SONIC_ONE_IMAGE)_DOCKERS += $(SONIC_INSTALL_DOCKER_DBG_IMAGES) $(SONIC_ONE_IMAGE)_DOCKERS += $(filter-out $(patsubst %-$(DBG_IMAGE_MARK).gz,%.gz, $(SONIC_INSTALL_DOCKER_DBG_IMAGES)), $(SONIC_INSTALL_DOCKER_IMAGES)) diff --git a/platform/vs/platform-modules-vs.mk b/platform/vs/platform-modules-vs.mk new file mode 100644 index 000000000000..20a5edb94d77 --- /dev/null +++ b/platform/vs/platform-modules-vs.mk @@ -0,0 +1,11 @@ +# VS Platform modules + +VS_PLATFORM_MODULE_VERSION = 1.0 + +export VS_PLATFORM_MODULE_VERSION + +VS_PLATFORM_MODULE = sonic-platform-vs_$(VS_PLATFORM_MODULE_VERSION)_amd64.deb +$(VS_PLATFORM_MODULE)_SRC_PATH = $(PLATFORM_PATH)/sonic-platform-modules-vs +$(VS_PLATFORM_MODULE)_DEPENDS = +$(VS_PLATFORM_MODULE)_PLATFORM = x86_64-kvm_x86_64-r0 +SONIC_DPKG_DEBS += $(VS_PLATFORM_MODULE) diff --git a/platform/vs/rules.mk b/platform/vs/rules.mk index 461c3f84dd02..6f67778ea55b 100644 --- a/platform/vs/rules.mk +++ b/platform/vs/rules.mk @@ -6,6 +6,7 @@ include $(PLATFORM_PATH)/docker-gbsyncd-vs.mk include $(PLATFORM_PATH)/docker-ptf.mk include $(PLATFORM_PATH)/docker-ptf-sai.mk include $(PLATFORM_PATH)/libsaithrift-dev.mk +include $(PLATFORM_PATH)/platform-modules-vs.mk include $(PLATFORM_PATH)/one-image.mk include $(PLATFORM_PATH)/onie.mk include $(PLATFORM_PATH)/kvm-image.mk diff --git a/platform/vs/sonic-platform-modules-vs/debian/changelog b/platform/vs/sonic-platform-modules-vs/debian/changelog new file mode 100755 index 000000000000..600264d5112b --- /dev/null +++ b/platform/vs/sonic-platform-modules-vs/debian/changelog @@ -0,0 +1,10 @@ +sonic-platform-vs (1.0) UNRELEASED; urgency=low + + * Initial release of the sonic-platform-vs package. + * This package provides platform-specific modules for SONiC on virtualized VS platforms. + * Included modules: + - Chassis module + * This package is part of the initial release of SONiC for VS platforms. + + -- Deepak Singhal Fri, 26 Feb 2024 12:00:00 +0000 + diff --git a/platform/vs/sonic-platform-modules-vs/debian/compat b/platform/vs/sonic-platform-modules-vs/debian/compat new file mode 100644 index 000000000000..f599e28b8ab0 --- /dev/null +++ b/platform/vs/sonic-platform-modules-vs/debian/compat @@ -0,0 +1 @@ +10 diff --git a/platform/vs/sonic-platform-modules-vs/debian/control b/platform/vs/sonic-platform-modules-vs/debian/control new file mode 100755 index 000000000000..6f416e0d800d --- /dev/null +++ b/platform/vs/sonic-platform-modules-vs/debian/control @@ -0,0 +1,10 @@ +Source: sonic-platform-vs +Section: main +Priority: extra +Maintainer: Deepak Singhal +Build-Depends: debhelper (>= 9), bzip2 +Standards-Version: 3.9.3 + +Package: sonic-platform-vs +Architecture: amd64 +Description: Sonic VS platform Module diff --git a/platform/vs/sonic-platform-modules-vs/debian/rules b/platform/vs/sonic-platform-modules-vs/debian/rules new file mode 100755 index 000000000000..ab27fce12045 --- /dev/null +++ b/platform/vs/sonic-platform-modules-vs/debian/rules @@ -0,0 +1,58 @@ +#!/usr/bin/make -f +# -*- makefile -*- +# Sample debian/rules that uses debhelper. +# As a special exception, when this file is copied by dh-make into a +# dh-make output file, you may use that output file without restriction. + +include /usr/share/dpkg/pkg-info.mk + +# Uncomment this to turn on verbose mode. +export DH_VERBOSE=1 + +PYTHON ?= python3 +PACKAGE_PRE_NAME := sonic-platform-vs +SRC_DIR:= $(shell pwd) + +%: + dh $@ --with python3 --buildsystem=pybuild + +clean: + dh_testdir + dh_testroot + dh_clean + +build: + # Nothing to do + + +binary: binary-arch binary-indep + # Nothing to do + +binary-arch: + # Nothing to do + +binary-indep: +# temporary commented out +# dh_testdir + dh_installdirs + + # Custom package commands + $(PYTHON) setup.py install --root=$(SRC_DIR)/debian/$(PACKAGE_PRE_NAME) --install-layout=deb; + + # Resuming debhelper scripts + dh_testroot + dh_install + dh_installchangelogs + dh_installdocs + dh_systemd_enable + dh_installinit + dh_systemd_start + dh_link + dh_fixperms + dh_compress + dh_strip + dh_installdeb + dh_gencontrol + dh_md5sums + dh_builddeb +.PHONY: build binary binary-arch binary-indep clean diff --git a/platform/vs/sonic-platform-modules-vs/setup.py b/platform/vs/sonic-platform-modules-vs/setup.py new file mode 100755 index 000000000000..803081689748 --- /dev/null +++ b/platform/vs/sonic-platform-modules-vs/setup.py @@ -0,0 +1,15 @@ +#!/usr/bin/env python + +import os +import sys +from setuptools import setup +os.listdir + +setup( + name='sonic_platform', + version='1.0', + description='Module to initialize VS platforms', + + packages=['sonic_platform'], + package_dir={'sonic_platform': 'sonic_platform'} +) diff --git a/platform/vs/sonic-platform-modules-vs/sonic_platform/__init__.py b/platform/vs/sonic-platform-modules-vs/sonic_platform/__init__.py new file mode 100644 index 000000000000..290d8cd1a50f --- /dev/null +++ b/platform/vs/sonic-platform-modules-vs/sonic_platform/__init__.py @@ -0,0 +1,2 @@ +__all__ = ["platform"] +from sonic_platform import * diff --git a/platform/vs/sonic-platform-modules-vs/sonic_platform/chassis.py b/platform/vs/sonic-platform-modules-vs/sonic_platform/chassis.py new file mode 100644 index 000000000000..32b8656c2cd0 --- /dev/null +++ b/platform/vs/sonic-platform-modules-vs/sonic_platform/chassis.py @@ -0,0 +1,56 @@ +# Description: Module contains the definitions of SONiC platform APIs +# which provide the chassis specific details +# +# Copyright (c) 2019, Nokia +# All rights reserved. +# + +try: + from sonic_platform_base.chassis_base import ChassisBase + from sonic_platform_base.module_base import ModuleBase + import os + import json + import threading + +except ImportError as e: + raise ImportError(str(e) + "- required module not found") + + +class Chassis(ChassisBase): + """ + VS Platform-specific Chassis class + """ + def __init__(self): + ChassisBase.__init__(self) + self.metadata_file = '/etc/sonic/vs_chassis_metadata.json' + self.metadata = self._read_metadata() + + def _read_metadata(self): + metadata = {} + if os.path.exists(self.metadata_file): + with open(self.metadata_file, 'r') as f: + metadata = json.load(f) + else: + raise FileNotFoundError("Metadata file {} not found".format(self.metadata_file)) + return metadata + + def get_supervisor_slot(self): + if 'sup_slot_num' not in self.metadata: + raise KeyError("sup_slot_num not found in Metadata file {}".format(self.metadata_file)) + return self.metadata['sup_slot_num'] + + def get_linecard_slot(self): + if 'lc_slot_num' not in self.metadata: + raise KeyError("lc_slot_num not found in Metadata file {}".format(self.metadata_file)) + return self.metadata['lc_slot_num'] + + def get_my_slot(self): + if 'is_supervisor' not in self.metadata or 'is_linecard' not in self.metadata: + raise KeyError("is_supervisor or is_linecard not found in metadata file {}".format(self.metadata_file)) + + if self.metadata['is_supervisor']: + return self.get_supervisor_slot() + elif self.metadata['is_linecard']: + return self.get_linecard_slot() + else: + raise ValueError("Invalid configuration: Neither supervisor nor line card") diff --git a/platform/vs/sonic-platform-modules-vs/sonic_platform/platform.py b/platform/vs/sonic-platform-modules-vs/sonic_platform/platform.py new file mode 100644 index 000000000000..0e6a571aaa04 --- /dev/null +++ b/platform/vs/sonic-platform-modules-vs/sonic_platform/platform.py @@ -0,0 +1,40 @@ +# Name: platform.py, version: 1.0 +# +# Description: Module contains the definitions of SONiC platform APIs +# which provide the platform specific details +# +# Copyright (c) 2019, Nokia +# All rights reserved. +# + +try: + from sonic_platform_base.platform_base import PlatformBase +except ImportError as e: + raise ImportError("%s - required module not found" % e) + +platformDict = {'platform': 'vs'} + + +class Platform(PlatformBase): + def __init__(self): + self.platform = self.getPlatform() + try: + from sonic_platform.chassis import Chassis + except ImportError as e: + raise ImportError("%s - required module not found" % e) + self.chassis = Chassis() + + def getPlatformDict(self): + global platformDict + if platformDict: + return platformDict + + def readPlatformName(self): + return self.getPlatformDict().get('platform') + + def getPlatform(self): + platformCls = self.readPlatformName() + return platformCls + + def get_chassis(self): + return self.chassis diff --git a/rules/config b/rules/config index db7801d6db5a..a81a0dcbcb3e 100644 --- a/rules/config +++ b/rules/config @@ -209,6 +209,15 @@ SONIC_ENABLE_IMAGE_SIGNATURE ?= n # The absolute path should be provided. SONIC_ENABLE_SECUREBOOT_SIGNATURE ?= n +# Full Secure Boot feature flags. +# SECURE_UPGRADE_DEV_SIGNING_KEY - path to development signing key, used for image signing during build +# SECURE_UPGRADE_DEV_SIGNING_CERT - path to development signing certificate, used for image signing during build +# SECURE_UPGRADE_MODE - enum value for secure upgrade mode, valid options are "dev", "prod" and "no_sign" +# SECURE_UPGRADE_PROD_SIGNING_TOOL - path to a vendor signing tool for production flow. +SECURE_UPGRADE_DEV_SIGNING_KEY = /sonic/your/private/key/path/private_key.pem +SECURE_UPGRADE_DEV_SIGNING_CERT = /sonic/your/certificate/path/cert.pem +SECURE_UPGRADE_MODE = "no_sign" +SECURE_UPGRADE_PROD_SIGNING_TOOL ?= none # PACKAGE_URL_PREFIX - the package url prefix PACKAGE_URL_PREFIX ?= https://packages.trafficmanager.net/public/packages diff --git a/rules/linux-kernel.dep b/rules/linux-kernel.dep index 4706f56afbaf..7e2dd4741486 100644 --- a/rules/linux-kernel.dep +++ b/rules/linux-kernel.dep @@ -4,11 +4,10 @@ DEP_FILES := rules/linux-kernel.mk rules/linux-kernel.dep SMDEP_FILES := $(addprefix $(SPATH)/,$(shell cd $(SPATH) && git ls-files)) DEP_FLAGS := $(SONIC_COMMON_FLAGS_LIST) \ - $(KERNEL_PROCURE_METHOD) $(KERNEL_CACHE_PATH) + $(KERNEL_PROCURE_METHOD) $(KERNEL_CACHE_PATH) $(SECURE_UPGRADE_MODE) $(SECURE_UPGRADE_DEV_SIGNING_CERT) $(LINUX_HEADERS_COMMON)_CACHE_MODE := GIT_CONTENT_SHA $(LINUX_HEADERS_COMMON)_DEP_FLAGS := $(DEP_FLAGS) $(LINUX_HEADERS_COMMON)_DEP_FILES := $(DEP_FILES) $(LINUX_HEADERS_COMMON)_SMDEP_FILES := $(SMDEP_FILES) $(LINUX_HEADERS_COMMON)_SMDEP_PATHS := $(SPATH) - diff --git a/scripts/efi-sign.sh b/scripts/efi-sign.sh new file mode 100755 index 000000000000..34dca50b067d --- /dev/null +++ b/scripts/efi-sign.sh @@ -0,0 +1,63 @@ +#!/bin/sh + +set -e + +# +# Sign efi file with secret key and certificate +# - shim +# - grub +# - vmlinuz +# +print_usage() { + cat < -c -e -s +Usage example: efi-sign.sh -p priv-key.pem -c pub-key.pem -e shimx64.efi -s shimx64-signed.efi + +EOF +} + +while getopts 'p:c:e:s:hv' flag; do + case "${flag}" in + p) PRIVATE_KEY_PEM="${OPTARG}" ;; + c) CERT_PEM="${OPTARG}" ;; + e) EFI_FILE="${OPTARG}" ;; + s) EFI_FILE_SIGNED="${OPTARG}" ;; + v) VERBOSE='true' ;; + h) print_usage + exit 1 ;; + esac +done +if [ $OPTIND -eq 1 ]; then echo "no options were pass"; print_usage; exit 1 ;fi + +[ -f "$PRIVATE_KEY_PEM" ] || { + echo "Error: PRIVATE_KEY_PEM file does not exist: $PRIVATE_KEY_PEM" + print_usage + exit 1 +} + +[ -f "$CERT_PEM" ] || { + echo "Error: CERT_PEM file does not exist: $CERT_PEM" + print_usage + exit 1 +} + +[ -f "$EFI_FILE" ] || { + echo "Error: File for signing does not exist: $EFI_FILE" + print_usage + exit 1 +} + +if [ -z ${EFI_FILE_SIGNED} ]; then + echo "ERROR: no arg named supplied" + print_usage + exit 1 +fi + +echo "$0 signing $EFI_FILE with ${PRIVATE_KEY_PEM}, ${CERT_PEM} to create $EFI_FILE_SIGNED" +sbsign --key ${PRIVATE_KEY_PEM} --cert ${CERT_PEM} \ + --output ${EFI_FILE_SIGNED} ${EFI_FILE} || { + echo "EFI sign error" + exit 1 +} diff --git a/scripts/secure_boot_signature_verification.sh b/scripts/secure_boot_signature_verification.sh new file mode 100755 index 000000000000..e704d8fabc35 --- /dev/null +++ b/scripts/secure_boot_signature_verification.sh @@ -0,0 +1,96 @@ +#!/bin/bash +# This Script is verifying the efi file signature by using sbverify. +# In addition, is verifying that kernel modules a directory contained a signature. +# Note: Kernel Module verification is not checking that the signature is correct, but its checking that the Kernel Modules have one. + +EFI_FILE='' +KERNEL_MODULES_DIR='' +CERT_PEM='' +VERBOSE='false' + +print_usage() { + cat < -c -k +Run Example: secure_boot_signature_verification.sh -e shimx64.efi -c pub-key.pem -k fsroot-mellanox +Run Example: secure_boot_signature_verification.sh -e /boot/efi_dir -c pub-key.pem -k fsroot-mellanox + +EOF +} + +verify_efi(){ + cert_pem=$1 + efi_file=$2 + echo "sbverify --cert $cert_pem $efi_file" + sbverify --cert $cert_pem $efi_file || { + echo "sbverify error with $efi_file" + exit 1 + } + echo "$efi_file signed OK." +} + +while getopts 'e:k:c:hv' flag; do + case "${flag}" in + e) EFI_FILE="${OPTARG}" ;; + k) KERNEL_MODULES_DIR="${OPTARG}" ;; + c) CERT_PEM="${OPTARG}" ;; + v) VERBOSE='true' ;; + h) print_usage + exit 1 ;; + esac +done +if [ $OPTIND -eq 1 ]; then echo "no options were pass"; print_usage; exit 1 ;fi + +if [ -d "$EFI_FILE" ];then + [ -f "$CERT_PEM" ] || { + echo "Error: option '-c' incorrect, file: certificate=$CERT_PEM does not exist" + print_usage + exit 1 + } + + # find all efi files. + efi_file_list=$(sudo find ${EFI_FILE} -name "*.efi") + for efi_file in $efi_file_list + do + echo "verifying efi_file named: ${efi_file} .." + verify_efi $CERT_PEM ${efi_file} + done + echo "$0: All EFI files SIGNED OK." +fi + +if [ -f "$EFI_FILE" ]; then + [ -f "$CERT_PEM" ] || { + echo "Error: option '-c' incorrect, file: certificate=$CERT_PEM does not exist" + print_usage + exit 1 + } + verify_efi $CERT_PEM $EFI_FILE +fi + +if [ -d "$KERNEL_MODULES_DIR" ]; then + # Condition checking that all the kernel modules in the KERNEL_MODULES_DIR contain a signature. + + # find all the kernel modules. + modules_list=$(sudo find ${KERNEL_MODULES_DIR} -name "*.ko") + + # Do sign for each found module + kernel_modules_cnt=0 + for mod in $modules_list + do + # check Kernel module is signed. + if ! grep -q "~Module signature appended~" "${mod}"; then + echo "Error: Kernel module=${mod} have no signature appened." + exit 1 + fi + + if [ $VERBOSE = 'true' ]; then + echo "kernel module named=${mod} have signature appended." + fi + + kernel_modules_cnt=$((kernel_modules_cnt+1)) + done + echo "Num of kernel modules signed: kernel_modules_cnt=$kernel_modules_cnt" + echo "$0: All Kernel Modules SIGNED OK." +fi + diff --git a/scripts/signing_kernel_modules.sh b/scripts/signing_kernel_modules.sh new file mode 100755 index 000000000000..5270d23b86f4 --- /dev/null +++ b/scripts/signing_kernel_modules.sh @@ -0,0 +1,124 @@ +#!/bin/bash +# This script is signing kernel modules by using sign-file tool + +usage() { + cat < -c -p -s -e -k +Sign kernel modules in using private & public keys. + +Parameters description: +LINUX_KERNEL_VERSION +PEM_CERT public key (pem format) +PEM_PRIVATE_KEY private key (pem format) +LOCAL_SIGN_FILE path of the sign-file tool for signing Kernel Modules, if the value is empty it will used the sign-file installed in /usr/lib/linux-kbuild-/scripts +LOCAL_EXTRACT_CERT path of the extract-cert tool for Extract X.509 certificate, if the value is empty it will used the extract-cert installed in /usr/lib/linux-kbuild-/scripts +KERNEL_MODULES_DIR root directory of all the kernel modules to be sign by the script, if the value empty it will use the call script location as root. + +Runs examples: +1. ./scripts/signing_kernel_modules.sh -l 5.10.0-8-2 -c cert.pem -p priv-key.pem +2. ./scripts/signing_kernel_modules.sh -l 5.10.0-8-2 -c cert.pem -p priv-key.pem -k fsroot-mellanox -e /usr/lib/linux-kbuild-5.10/scripts/extract-cert -s /usr/lib/linux-kbuild-5.10/scripts/sign-file +EOF +} + +while getopts 'l:c:p:k:s:e:hv' flag; do + case "${flag}" in + l) LINUX_KERNEL_VERSION="${OPTARG}" ;; + c) PEM_CERT="${OPTARG}" ;; + p) PEM_PRIVATE_KEY="${OPTARG}" ;; + k) KERNEL_MODULES_DIR="${OPTARG}" ;; + s) LOCAL_SIGN_FILE="${OPTARG}" ;; + e) LOCAL_EXTRACT_CERT="${OPTARG}" ;; + v) VERBOSE='true' ;; + h) print_usage + exit 1 ;; + esac +done +if [ $OPTIND -eq 1 ]; then echo "no options were pass"; print_usage; exit 1 ;fi + +if [ -z ${LINUX_KERNEL_VERSION} ]; then + echo "ERROR: LINUX_KERNEL_VERSION arg1 is empty" + usage + exit 1 +fi + +if [ ! -f ${PEM_CERT} ]; then + echo "ERROR: arg2 PEM_CERT=${PEM_CERT} file does not exist" + usage + exit 1 +fi + +if [ ! -f ${PEM_PRIVATE_KEY} ]; then + echo "ERROR: arg3 PEM_PRIVATE_KEY=${PEM_PRIVATE_KEY} file does not exist" + usage + exit 1 +fi + +kbuild_ver_major="$(cut -d '.' -f 1 <<< "$LINUX_KERNEL_VERSION")"."$(cut -d '.' -f 2 <<< "$LINUX_KERNEL_VERSION")" +if [ -z ${LOCAL_SIGN_FILE} ]; then + LOCAL_SIGN_FILE="/usr/lib/linux-kbuild-${kbuild_ver_major}/scripts/sign-file" +fi + +if [ ! -f ${LOCAL_SIGN_FILE} ]; then + echo "ERROR: LOCAL_SIGN_FILE=${LOCAL_SIGN_FILE} file does not exist" + usage + exit 1 +fi + +if [ -z ${LOCAL_EXTRACT_CERT} ]; then + LOCAL_EXTRACT_CERT="/usr/lib/linux-kbuild-${kbuild_ver_major}/scripts/extract-cert" +fi + +if [ ! -f ${LOCAL_EXTRACT_CERT} ]; then + echo "ERROR: LOCAL_EXTRACT_CERT=${LOCAL_EXTRACT_CERT} file does not exist" + usage + exit 1 +fi + +if [ ! -d "$KERNEL_MODULES_DIR" ]; then + # If the user do not provide a KERNEL_MODULES_DIR, the script is going to search in the script call path for Kernel modules. + KERNEL_MODULES_DIR="./" + echo "KERNEL_MODULES_DIR set to default path: $KERNEL_MODULES_DIR" + +fi + +# find all the kernel modules. +modules_list=$(find ${KERNEL_MODULES_DIR} -name "*.ko") + +dev_certs_tmp_folder="/tmp/dev_kmod_sign" + +# clean env +if [ -d ${dev_certs_tmp_folder} ]; then + rm -r ${dev_certs_tmp_folder} +fi + +mkdir -p ${dev_certs_tmp_folder} +local_sign_key="${dev_certs_tmp_folder}/$(basename $PEM_PRIVATE_KEY)" +local_sign_cert="${dev_certs_tmp_folder}/$(basename $PEM_CERT)" + +# Combine cert for module signing +echo "keys concat: cat ${PEM_PRIVATE_KEY} ${PEM_CERT} > ${local_sign_key}" +cat ${PEM_PRIVATE_KEY} ${PEM_CERT} > ${local_sign_key} + +# Extract x509 cert in corect format +echo "create x509 cert: ${LOCAL_EXTRACT_CERT} ${local_sign_key} ${local_sign_cert}" +${LOCAL_EXTRACT_CERT} ${local_sign_key} ${local_sign_cert} + +# Do sign for each found module +kernel_modules_cnt=0 +for mod in $modules_list +do + echo "signing module named: ${mod} .." + echo "${LOCAL_SIGN_FILE} sha512 ${local_sign_key} ${local_sign_cert} ${mod}" + kernel_modules_cnt=$((kernel_modules_cnt+1)) + ${LOCAL_SIGN_FILE} sha512 ${local_sign_key} ${local_sign_cert} ${mod} + + # check Kernel module is signed. + if ! grep -q "~Module signature appended~" "${mod}"; then + echo "Error: Kernel module=${mod} have no signature appened." + exit 1 + fi +done + +echo "Num of kernel modules signed: kernel_modules_cnt=$kernel_modules_cnt" +echo "$0: All Kernel Modules SIGNED OK." \ No newline at end of file diff --git a/scripts/signing_secure_boot_dev.sh b/scripts/signing_secure_boot_dev.sh new file mode 100755 index 000000000000..cc937215b9b2 --- /dev/null +++ b/scripts/signing_secure_boot_dev.sh @@ -0,0 +1,121 @@ +#!/bin/bash +# This script is signing boot components: shim, mmx, grub, kernel and kernel modules in development env. + +## Enable debug output for script & exit code when failing occurs +set -x -e + +print_usage() { + cat < -l -c -p + +EOF +} + +clean_file() { + if [ -f $1 ]; then + echo "clean old file named: $1" + echo "rm -f $1" + rm -f $1 + fi +} + +while getopts 'a:r:l:c:p:hv' flag; do + case "${flag}" in + a) CONFIGURED_ARCH="${OPTARG}" ;; + r) FS_ROOT="${OPTARG}" ;; + l) LINUX_KERNEL_VERSION="${OPTARG}" ;; + c) PEM_CERT="${OPTARG}" ;; + p) PEM_PRIV_KEY="${OPTARG}" ;; + v) VERBOSE='true' ;; + h) print_usage + exit 1 ;; + esac +done +if [ $OPTIND -eq 1 ]; then echo "no options were pass"; print_usage; exit 1 ;fi + +echo "$0 signing & verifying EFI files and Kernel Modules start ..." + +if [ -z ${CONFIGURED_ARCH} ]; then + echo "ERROR: CONFIGURED_ARCH=${CONFIGURED_ARCH} is empty" + print_usage + exit 1 +fi + +if [ -z ${FS_ROOT} ]; then + echo "ERROR: FS_ROOT=${FS_ROOT} is empty" + print_usage + exit 1 +fi + +if [ -z ${LINUX_KERNEL_VERSION} ]; then + echo "ERROR: LINUX_KERNEL_VERSION=${LINUX_KERNEL_VERSION} is empty" + print_usage + exit 1 +fi + +if [ ! -f "${PEM_CERT}" ]; then + echo "ERROR: PEM_CERT=${PEM_CERT} file does not exist" + print_usage + exit 1 +fi + +if [ ! -f "${PEM_PRIV_KEY}" ]; then + echo "ERROR: PEM_PRIV_KEY=${PEM_PRIV_KEY} file does not exist" + print_usage + exit 1 +fi + +# efi-sign.sh is used to sign: shim, mmx, grub, and kernel (vmlinuz) +EFI_SIGNING=scripts/efi-sign.sh + +# ###################################### +# Signing EFI files: mm, shim, grub +# ##################################### +efi_file_list=$(sudo find ${KERNEL_MODULES_DIR} -name "*.efi") + +for efi in $efi_file_list +do + # grep filename from full path + efi_filename=$(echo $efi | grep -o '[^/]*$') + + if echo $efi_filename | grep -e "shim" -e "grub" -e "mm"; then + + clean_file ${efi}-signed + + echo "signing efi file - full path: ${efi} filename: ${efi_filename}" + echo "sudo ${EFI_SIGNING} -p $PEM_PRIV_KEY -c $PEM_CERT -e ${efi} -s ${efi}-signed" + ${EFI_SIGNING} -p $PEM_PRIV_KEY -c $PEM_CERT -e ${efi} -s ${efi}-signed + + # cp shim & mmx signed files to boot directory in the fs. + cp ${efi}-signed $FS_ROOT/boot/${efi_filename} + + # verifying signature of mm & shim efi files. + ./scripts/secure_boot_signature_verification.sh -c $PEM_CERT -e $FS_ROOT/boot/${efi_filename} + fi +done + +###################### +## vmlinuz signing +###################### + +CURR_VMLINUZ=$FS_ROOT/boot/vmlinuz-${LINUX_KERNEL_VERSION}-${CONFIGURED_ARCH} + +# clean old files +clean_file ${CURR_VMLINUZ}-signed + +echo "signing ${CURR_VMLINUZ} .." +${EFI_SIGNING} -p $PEM_PRIV_KEY -c $PEM_CERT -e ${CURR_VMLINUZ} -s ${CURR_VMLINUZ}-signed + +# rename signed vmlinuz with the name vmlinuz without signed suffix +mv ${CURR_VMLINUZ}-signed ${CURR_VMLINUZ} + +./scripts/secure_boot_signature_verification.sh -c $PEM_CERT -e ${CURR_VMLINUZ} + +######################### +# Kernel Modules signing +######################### +./scripts/signing_kernel_modules.sh -l $LINUX_KERNEL_VERSION -c ${PEM_CERT} -p ${PEM_PRIV_KEY} -k ${FS_ROOT} + +echo "$0 signing & verifying EFI files and Kernel Modules DONE" diff --git a/slave.mk b/slave.mk index 8b354977b87c..91f66c274eb4 100644 --- a/slave.mk +++ b/slave.mk @@ -300,6 +300,10 @@ $(info "USE_NATIVE_DOCKERD_FOR_BUILD" : "$(SONIC_CONFIG_USE_NATIVE_DOCKERD_FO $(info "SONIC_USE_DOCKER_BUILDKIT" : "$(SONIC_USE_DOCKER_BUILDKIT)") $(info "USERNAME" : "$(USERNAME)") $(info "PASSWORD" : "$(PASSWORD)") +$(info "SECURE_UPGRADE_MODE" : "$(SECURE_UPGRADE_MODE)") +$(info "SECURE_UPGRADE_DEV_SIGNING_KEY" : "$(SECURE_UPGRADE_DEV_SIGNING_KEY)") +$(info "SECURE_UPGRADE_DEV_SIGNING_CERT" : "$(SECURE_UPGRADE_DEV_SIGNING_CERT)") +$(info "SECURE_UPGRADE_PROD_SIGNING_TOOL": "$(SECURE_UPGRADE_PROD_SIGNING_TOOL)") $(info "ENABLE_DHCP_GRAPH_SERVICE" : "$(ENABLE_DHCP_GRAPH_SERVICE)") $(info "SHUTDOWN_BGP_ON_START" : "$(SHUTDOWN_BGP_ON_START)") $(info "ENABLE_PFCWD_ON_START" : "$(ENABLE_PFCWD_ON_START)") @@ -1119,6 +1123,10 @@ $(addprefix $(TARGET_PATH)/, $(SONIC_INSTALLERS)) : $(TARGET_PATH)/% : \ export enable_organization_extensions="$(ENABLE_ORGANIZATION_EXTENSIONS)" export enable_dhcp_graph_service="$(ENABLE_DHCP_GRAPH_SERVICE)" export enable_ztp="$(ENABLE_ZTP)" + export sonic_su_dev_signing_key="$(SECURE_UPGRADE_DEV_SIGNING_KEY)" + export sonic_su_dev_signing_cert="$(SECURE_UPGRADE_DEV_SIGNING_CERT)" + export sonic_su_mode="$(SECURE_UPGRADE_MODE)" + export sonic_su_prod_signing_tool="$(SECURE_UPGRADE_PROD_SIGNING_TOOL)" export include_system_telemetry="$(INCLUDE_SYSTEM_TELEMETRY)" export include_restapi="$(INCLUDE_RESTAPI)" export include_nat="$(INCLUDE_NAT)" @@ -1316,6 +1324,10 @@ $(addprefix $(TARGET_PATH)/, $(SONIC_INSTALLERS)) : $(TARGET_PATH)/% : \ TARGET_MACHINE=$(dep_machine) \ IMAGE_TYPE=$($*_IMAGE_TYPE) \ SONIC_ENABLE_IMAGE_SIGNATURE="$(SONIC_ENABLE_IMAGE_SIGNATURE)" \ + SECURE_UPGRADE_MODE="$(SECURE_UPGRADE_MODE)" \ + SECURE_UPGRADE_DEV_SIGNING_KEY="$(SECURE_UPGRADE_DEV_SIGNING_KEY)" \ + SECURE_UPGRADE_DEV_SIGNING_CERT="$(SECURE_UPGRADE_DEV_SIGNING_CERT)" \ + SECURE_UPGRADE_PROD_SIGNING_TOOL="$(SECURE_UPGRADE_PROD_SIGNING_TOOL)" \ SIGNING_KEY="$(SIGNING_KEY)" \ SIGNING_CERT="$(SIGNING_CERT)" \ CA_CERT="$(CA_CERT)" \ diff --git a/src/sonic-bgpcfgd/bgpcfgd/managers_bgp.py b/src/sonic-bgpcfgd/bgpcfgd/managers_bgp.py index 55a16a273993..5c90571fdef3 100644 --- a/src/sonic-bgpcfgd/bgpcfgd/managers_bgp.py +++ b/src/sonic-bgpcfgd/bgpcfgd/managers_bgp.py @@ -107,6 +107,7 @@ def __init__(self, common_objs, db_name, table_name, peer_type, check_neig_meta) deps = [ ("CONFIG_DB", swsscommon.CFG_DEVICE_METADATA_TABLE_NAME, "localhost/bgp_asn"), ("CONFIG_DB", swsscommon.CFG_LOOPBACK_INTERFACE_TABLE_NAME, "Loopback0"), + ("CONFIG_DB", swsscommon.CFG_BGP_DEVICE_GLOBAL_TABLE_NAME, "tsa_enabled"), ("LOCAL", "local_addresses", ""), ("LOCAL", "interfaces", ""), ] diff --git a/src/sonic-bgpcfgd/bgpcfgd/managers_device_global.py b/src/sonic-bgpcfgd/bgpcfgd/managers_device_global.py index 192527f1cd85..04d8400e6154 100644 --- a/src/sonic-bgpcfgd/bgpcfgd/managers_device_global.py +++ b/src/sonic-bgpcfgd/bgpcfgd/managers_device_global.py @@ -90,15 +90,17 @@ def __generate_routemaps_from_template(self, route_map_names, template): for rm in sorted(route_map_names): # For packet-based chassis, the bgp session between the linecards are also considered internal sessions # While isolating a single linecard, these sessions should not be skipped - if "_INTERNAL_" in rm and self.switch_type != "chassis-packet": - continue + if "_INTERNAL_" in rm or "VOQ_" in rm: + is_internal="1" + else: + is_internal="0" if "V4" in rm: ipv="V4" ; ipp="ip" elif "V6" in rm: ipv="V6" ; ipp="ipv6" else: - continue - cmd += template.render(route_map_name=rm,ip_version=ipv,ip_protocol=ipp, constants=self.constants) + continue + cmd += template.render(route_map_name=rm,ip_version=ipv,ip_protocol=ipp,internal_route_map=is_internal, constants=self.constants) cmd += "\n" return cmd diff --git a/src/sonic-bgpcfgd/bgpcfgd/managers_static_rt.py b/src/sonic-bgpcfgd/bgpcfgd/managers_static_rt.py index fae7a5365aba..e091dbde06ba 100644 --- a/src/sonic-bgpcfgd/bgpcfgd/managers_static_rt.py +++ b/src/sonic-bgpcfgd/bgpcfgd/managers_static_rt.py @@ -25,6 +25,7 @@ def __init__(self, common_objs, db, table): self.directory.subscribe([("CONFIG_DB", swsscommon.CFG_DEVICE_METADATA_TABLE_NAME, "localhost/bgp_asn"),], self.on_bgp_asn_change) self.static_routes = {} self.vrf_pending_redistribution = set() + self.config_db = None OP_DELETE = 'DELETE' OP_ADD = 'ADD' @@ -41,8 +42,18 @@ def set_handler(self, key, data): intf_list = arg_list(data['ifname']) if 'ifname' in data else None dist_list = arg_list(data['distance']) if 'distance' in data else None nh_vrf_list = arg_list(data['nexthop-vrf']) if 'nexthop-vrf' in data else None + bfd_enable = arg_list(data['bfd']) if 'bfd' in data else None route_tag = self.ROUTE_ADVERTISE_DISABLE_TAG if 'advertise' in data and data['advertise'] == "false" else self.ROUTE_ADVERTISE_ENABLE_TAG + # bfd enabled route would be handled in staticroutebfd, skip here + if bfd_enable and bfd_enable[0].lower() == "true": + log_debug("{} static route {} bfd flag is true".format(self.db_name, key)) + tmp_nh_set, tmp_route_tag = self.static_routes.get(vrf, {}).get(ip_prefix, (IpNextHopSet(is_ipv6), route_tag)) + if tmp_nh_set: #clear nexthop set if it is not empty + log_debug("{} static route {} bfd flag is true, cur_nh is not empty, clear it".format(self.db_name, key)) + self.static_routes.setdefault(vrf, {}).pop(ip_prefix, None) + return True + try: ip_nh_set = IpNextHopSet(is_ipv6, bkh_list, nh_list, intf_list, dist_list, nh_vrf_list) cur_nh_set, cur_route_tag = self.static_routes.get(vrf, {}).get(ip_prefix, (IpNextHopSet(is_ipv6), route_tag)) @@ -60,19 +71,70 @@ def set_handler(self, key, data): if cmd_list: self.cfg_mgr.push_list(cmd_list) - log_debug("Static route {} is scheduled for updates".format(key)) + log_debug("{} Static route {} is scheduled for updates. {}".format(self.db_name, key, str(cmd_list))) else: - log_debug("Nothing to update for static route {}".format(key)) + log_debug("{} Nothing to update for static route {}".format(self.db_name, key)) self.static_routes.setdefault(vrf, {})[ip_prefix] = (ip_nh_set, route_tag) return True + def skip_appl_del(self, vrf, ip_prefix): + """ + If a static route is bfd enabled, the processed static route is written into application DB by staticroutebfd. + When we disable bfd for that route at runtime, that static route entry will be removed from APPL_DB STATIC_ROUTE_TABLE. + In the case, the StaticRouteMgr(appl_db) cannot uninstall the static route from FRR if the static route is still in CONFIG_DB, + so need this checking (skip appl_db deletion) to avoid race condition between StaticRouteMgr(appl_db) and StaticRouteMgr(config_db) + For more detailed information: + https://github.com/sonic-net/SONiC/blob/master/doc/static-route/SONiC_static_route_bfd_hld.md#bfd-field-changes-from-true-to-false + but if the deletion is caused by no nexthop available (bfd field is true but all the sessions are down), need to allow this deletion. + :param vrf: vrf from the split_key(key) return + :param ip_prefix: ip_prefix from the split_key(key) return + :return: True if the deletion comes from APPL_DB and the vrf|ip_prefix exists in CONFIG_DB, otherwise return False + """ + if self.db_name == "CONFIG_DB": + return False + + if self.config_db is None: + self.config_db = swsscommon.SonicV2Connector() + self.config_db.connect(self.config_db.CONFIG_DB) + + #just pop local cache if the route exist in config_db + cfg_key = "STATIC_ROUTE|" + vrf + "|" + ip_prefix + if vrf == "default": + default_key = "STATIC_ROUTE|" + ip_prefix + bfd = self.config_db.get(self.config_db.CONFIG_DB, default_key, "bfd") + if bfd == "true": + log_debug("skip_appl_del: {}, key {}, bfd flag {}".format(self.db_name, default_key, bfd)) + return False + bfd = self.config_db.get(self.config_db.CONFIG_DB, cfg_key, "bfd") + if bfd == "true": + log_debug("skip_appl_del: {}, key {}, bfd flag {}".format(self.db_name, cfg_key, bfd)) + return False + + nexthop = self.config_db.get(self.config_db.CONFIG_DB, cfg_key, "nexthop") + if nexthop and len(nexthop)>0: + self.static_routes.setdefault(vrf, {}).pop(ip_prefix, None) + return True + + if vrf == "default": + cfg_key = "STATIC_ROUTE|" + ip_prefix + nexthop = self.config_db.get(self.config_db.CONFIG_DB, cfg_key, "nexthop") + if nexthop and len(nexthop)>0: + self.static_routes.setdefault(vrf, {}).pop(ip_prefix, None) + return True + + return False + def del_handler(self, key): vrf, ip_prefix = self.split_key(key) is_ipv6 = TemplateFabric.is_ipv6(ip_prefix) + if self.skip_appl_del(vrf, ip_prefix): + log_debug("{} ignore appl_db static route deletion because of key {} exist in config_db and bfd is not true".format(self.db_name, key)) + return + ip_nh_set = IpNextHopSet(is_ipv6) cur_nh_set, route_tag = self.static_routes.get(vrf, {}).get(ip_prefix, (IpNextHopSet(is_ipv6), self.ROUTE_ADVERTISE_DISABLE_TAG)) cmd_list = self.static_route_commands(ip_nh_set, cur_nh_set, ip_prefix, vrf, route_tag, route_tag) @@ -85,9 +147,9 @@ def del_handler(self, key): if cmd_list: self.cfg_mgr.push_list(cmd_list) - log_debug("Static route {} is scheduled for updates".format(key)) + log_debug("{} Static route {} is scheduled for updates. {}".format(self.db_name, key, str(cmd_list))) else: - log_debug("Nothing to update for static route {}".format(key)) + log_debug("{} Nothing to update for static route {}".format(self.db_name, key)) self.static_routes.setdefault(vrf, {}).pop(ip_prefix, None) diff --git a/src/sonic-bgpcfgd/setup.py b/src/sonic-bgpcfgd/setup.py index b451accb9792..30298fea989a 100755 --- a/src/sonic-bgpcfgd/setup.py +++ b/src/sonic-bgpcfgd/setup.py @@ -11,6 +11,7 @@ entry_points = { 'console_scripts': [ 'bgpcfgd = bgpcfgd.main:main', + 'staticroutebfd = staticroutebfd.main:main', 'bgpmon = bgpmon.bgpmon:main', ] }, diff --git a/src/sonic-bgpcfgd/staticroutebfd/__init__.py b/src/sonic-bgpcfgd/staticroutebfd/__init__.py new file mode 100644 index 000000000000..e69de29bb2d1 diff --git a/src/sonic-bgpcfgd/staticroutebfd/main.py b/src/sonic-bgpcfgd/staticroutebfd/main.py new file mode 100644 index 000000000000..268dbd3c1669 --- /dev/null +++ b/src/sonic-bgpcfgd/staticroutebfd/main.py @@ -0,0 +1,787 @@ +import os +import signal +import sys +import syslog +import threading +import traceback +from collections import defaultdict +from ipaddress import IPv4Address, IPv6Address +from copy import deepcopy + +from swsscommon import swsscommon + +from .vars import g_debug, bfd_multihop, bfd_rx_interval, bfd_tx_interval, bfd_multiplier + +g_run = True + +CONFIG_DB_NAME = "CONFIG_DB" +APPL_DB_NAME = "APPL_DB" +STATE_DB_NAME = "STATE_DB" + +INTERFACE_TABLE_NAME = "INTERFACE" +PORTCHANNEL_INTERFACE_TABLE_NAME = "PORTCHANNEL_INTERFACE" +STATIC_ROUTE_TABLE_NAME = "STATIC_ROUTE" +BFD_SESSION_TABLE_NAME = "BFD_SESSION_TABLE" + +LOCAL_CONFIG_TABLE = "config" +LOCAL_NEXTHOP_TABLE = "nexthop" +LOCAL_SRT_TABLE = "srt" +LOCAL_BFD_TABLE = "bfd" +LOCAL_BFD_PENDING_TABLE = "bfd_pending" +LOCAL_INTERFACE_TABLE = "interface" + +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 signal_handler(_, __): # signal_handler(signum, frame) + """ signal handler """ + global g_run + g_run = False + +def static_route_split_key(key): + """ + Split key into vrf name and prefix. + :param key: key to split + :return: valid, vrf name extracted from the key, ip prefix extracted from the key + """ + if key is None or len(key) == 0: + return False, "", "" + + l = tuple(key.split('|')) + + if len(l) == 1: + return True, 'default', l[0] + + return True, l[0], l[1] + +def check_ip(ip): + if len(ip) == 0: + return False, False, "" + + value = ip.split('/',1) + v = value[0] + try: + IPv4Address(v) + valid = True + is_ipv4 = True + except: + is_ipv4 = False + try: + IPv6Address(v) + valid = True + except: + valid = False + return valid, is_ipv4, v + +class StaticRouteBfd(object): + + SELECT_TIMEOUT = 1000 + BFD_DEFAULT_CFG = {"multihop": "false", "rx_interval": "50", "tx_interval": "50"} + + def __init__(self): + self.local_db = defaultdict(dict) + self.local_db[LOCAL_CONFIG_TABLE] = defaultdict(dict) + self.local_db[LOCAL_NEXTHOP_TABLE] = defaultdict(set) + self.local_db[LOCAL_SRT_TABLE] = defaultdict(set) + self.local_db[LOCAL_BFD_TABLE] = defaultdict(dict) + self.local_db[LOCAL_BFD_PENDING_TABLE] = defaultdict(dict) + #interface, portchannel_interface and loopback_interface share same table, assume name is unique + #assume only one ipv4 and/or one ipv6 for each interface + self.local_db[LOCAL_INTERFACE_TABLE] = defaultdict(dict) + + self.config_db = swsscommon.DBConnector(CONFIG_DB_NAME, 0, True) + self.appl_db = swsscommon.DBConnector(APPL_DB_NAME, 0, True) + self.state_db = swsscommon.DBConnector(STATE_DB_NAME, 0, True) + + self.bfd_appl_tbl = swsscommon.ProducerStateTable(self.appl_db, BFD_SESSION_TABLE_NAME) + + self.static_route_appl_tbl = swsscommon.Table(self.appl_db, STATIC_ROUTE_TABLE_NAME) + + self.selector = swsscommon.Select() + self.callbacks = defaultdict(lambda: defaultdict(list)) # db -> table -> handlers[] + self.subscribers = set() + self.first_time = True + + def get_ip_from_key(self, key): + """ + Get ip address from key for LOOPBACK/INTERFACE/PORTCHANNEL_INTERFACE table + :param key: key in the tables + :return: valid, is_ipv4, ip address + """ + if '|' not in key: + return False, False, "", "" + else: + if_ip = key.split('|') + if len(if_ip) < 2: + return False, False, "", "" + if_name = if_ip[0] + value = if_ip[1] + valid, is_ipv4, ip = check_ip(value) + log_debug("get ip from intf key: valid %s is_ipv4 %s, if_name %s ip %s"%(str(valid), str(is_ipv4), if_name, ip)) + return valid, is_ipv4, if_name, ip + + def set_local_db(self, table, key, data): + try: + self.local_db[table][key] = data + return + except: + log_err("set_local_db error, table %s key %s"%(table, key)) + pass + + def get_local_db(self, table, key): + try: + v = self.local_db[table][key] + return v + except: + return {} + + def remove_from_local_db(self, table, key): + if table in self.local_db: + if key in self.local_db[table]: + del self.local_db[table][key] + + def append_to_nh_table_entry(self, nh_key, ip_prefix): + entry = self.get_local_db(LOCAL_NEXTHOP_TABLE, nh_key) + entry.add(ip_prefix) + + def remove_from_nh_table_entry(self, nh_key, ip_prefix): + entry = self.get_local_db(LOCAL_NEXTHOP_TABLE, nh_key) + if ip_prefix in entry: + entry.remove(ip_prefix) + if len(entry) == 0: + self.remove_from_local_db(LOCAL_NEXTHOP_TABLE, nh_key) + + def set_bfd_session_into_appl_db(self, key, data): + fvs = swsscommon.FieldValuePairs(list(data.items())) + self.bfd_appl_tbl.set(key, fvs) + log_debug("set bfd session to appl_db, key %s, data %s"%(key, str(data))) + + def del_bfd_session_from_appl_db(self, key): + self.bfd_appl_tbl.delete(key) + + def interface_set_handler(self, key, data): + valid, is_ipv4, if_name, ip = self.get_ip_from_key(key) + if not valid: + return True + value = self.get_local_db(LOCAL_INTERFACE_TABLE, if_name) + if len(value) == 0: + value = {is_ipv4: ip} + else: + value[is_ipv4] = ip + self.set_local_db(LOCAL_INTERFACE_TABLE, if_name, value) + self.update_bfd_pending(if_name) + return True + + def interface_del_handler(self, key): + valid, is_ipv4, if_name, ip = self.get_ip_from_key(key) + if not valid: + return True + value = self.get_local_db(LOCAL_INTERFACE_TABLE, if_name) + if len(value) == 0: + return + else: + value[is_ipv4] = "" #remove the IP address for the interface + self.set_local_db(LOCAL_INTERFACE_TABLE, if_name, value) + + def find_interface_ip(self, if_name, ip_example): + valid, is_ipv4, nh = check_ip(ip_example) + if not valid: + return False, "" + + value = self.get_local_db(LOCAL_INTERFACE_TABLE, if_name) + ip = value.get(is_ipv4, "") + if len(ip)>0: #ip should be verified when add to local_db + return True, ip + + return False, "" + + def update_bfd_pending(self, if_name): + del_list=[] + for k, v in self.local_db[LOCAL_BFD_PENDING_TABLE].items(): + if len(v) == 3 and v[0] == if_name: + intf, nh_ip, bfd_key = v[0], v[1], v[2] + valid, local_addr = self.find_interface_ip(intf, nh_ip) + if not valid: #IP address might not be available for this type of nh_ip (IPv4 or IPv6) yet + continue + log_notice("bfd_pending: get ip for interface: %s, create bfd session for %s"%(intf, bfd_key)) + bfd_entry_cfg = self.BFD_DEFAULT_CFG.copy() + if all([bfd_rx_interval, bfd_tx_interval, bfd_multiplier, bfd_multihop]): + bfd_entry_cfg["multihop"] = bfd_multihop + bfd_entry_cfg["rx_interval"] = bfd_rx_interval + bfd_entry_cfg["tx_interval"] = bfd_tx_interval + bfd_entry_cfg["multiplier"] = bfd_multiplier + + bfd_entry_cfg["local_addr"] = local_addr + self.set_bfd_session_into_appl_db(bfd_key, bfd_entry_cfg) + bfd_entry_cfg["static_route"] = "true" + self.set_local_db(LOCAL_BFD_TABLE, bfd_key, bfd_entry_cfg) + del_list.append(k) + + for k in del_list: + self.local_db[LOCAL_BFD_PENDING_TABLE].pop(k) + + def strip_table_name(self, key, splitter): + return key.split(splitter, 1)[1] + + def reconciliation(self): + #to use SonicV2Connector get_all method, DBConnector doesn't have get_all + db = swsscommon.SonicV2Connector() + db.connect(db.CONFIG_DB) + db.connect(db.APPL_DB) + db.connect(db.STATE_DB) + + #MUST keep the restore sequene + #restore interface(loopback/interface/portchannel_interface) tables + + #restore interface tables + log_info("restore interface table -->") + keys = db.keys(db.CONFIG_DB, "LOOPBACK_INTERFACE|*") + for key in keys: + key_new = self.strip_table_name(key, "|") + self.interface_set_handler(key_new, "") + keys = db.keys(db.CONFIG_DB, "INTERFACE|*") + for key in keys: + key_new = self.strip_table_name(key, "|") + self.interface_set_handler(key_new, "") + keys = db.keys(db.CONFIG_DB, "PORTCHANNEL_INTERFACE|*") + for key in keys: + key_new = self.strip_table_name(key, "|") + self.interface_set_handler(key_new, "") + + #restore bfd session table, static route won't create bfd session if it is already in appl_db + log_info("restore bfd session table -->") + keys = db.keys(db.APPL_DB, "BFD_SESSION_TABLE:*") + for key in keys: + data = db.get_all(db.APPL_DB, key) + key_new = self.strip_table_name(key, ":") + self.set_local_db(LOCAL_BFD_TABLE, key_new, data) + + #restore static route table + log_info("restore static route table -->") + keys = db.keys(db.CONFIG_DB, "STATIC_ROUTE|*") + for key in keys: + data = db.get_all(db.CONFIG_DB, key) + key_new = self.strip_table_name(key, "|") + log_debug("SRT_BFD: restore static route from config_db, key %s, data %s"%(key, str(data))) + self.static_route_set_handler(key_new, data) + + #clean up local bfd table, remove non static route bfd session + log_info("cleanup bfd session table -->") + self.cleanup_local_bfd_table() + + #restore bfd state table + log_info("restore bfd state table -->") + keys = db.keys(db.STATE_DB, "BFD_SESSION_TABLE|*") + for key in keys: + data = db.get_all(db.STATE_DB, key) + key_new = self.strip_table_name(key, "|") + self.bfd_state_set_handler(key_new, data) + + def cleanup_local_bfd_table(self): + kl=[] + for key in self.local_db[LOCAL_BFD_TABLE]: + kl.append(key) + for key in kl: + bfd_session = self.local_db[LOCAL_BFD_TABLE][key] + if "static_route" not in bfd_session or bfd_session["static_route"] != "true": + self.local_db[LOCAL_BFD_TABLE].pop(key) + + def isFieldTrue(self, bfd_field): + if isinstance(bfd_field, list): + if len(bfd_field) == 1: + if isinstance(bfd_field[0], str): + if bfd_field[0].lower() == "true": + return True + return False + + def refresh_active_nh(self, route_cfg_key): + data = self.get_local_db(LOCAL_CONFIG_TABLE, route_cfg_key) + + arg_list = lambda v: [x.strip() for x in v.split(',')] if len(v.strip()) != 0 else None + nh_list = arg_list(data['nexthop']) if 'nexthop' in data else None + nh_vrf_list = arg_list(data['nexthop-vrf']) if 'nexthop-vrf' in data else None + nh_cnt = 0 + + for index in range(len(nh_list)): + nh_ip = nh_list[index] + nh_vrf = nh_vrf_list[index] + nh_key = nh_vrf + "|" + nh_ip + bfd_key = nh_vrf + ":default:" + nh_ip + + bfd_session = self.get_local_db(LOCAL_BFD_TABLE, bfd_key) + if len(bfd_session) == 0: + continue + if "state" in bfd_session and bfd_session["state"].upper() == "UP": + self.append_to_srt_table_entry(route_cfg_key, (nh_vrf, nh_ip)) + nh_cnt += 1 + + #do not write to appl_db is no nexthop reachable + if nh_cnt == 0: + return + + #if there is any bfd session state UP, we don't need to hold the static route update. + data['bfd_nh_hold'] = "false" + new_config = self.reconstruct_static_route_config(data, self.get_local_db(LOCAL_SRT_TABLE, route_cfg_key)) + self.set_static_route_into_appl_db(route_cfg_key.replace("|", ":"), new_config) + + def handle_bfd_change(self, cfg_key, data, to_bfd_enable): + valid, vrf, ip_prefix = static_route_split_key(cfg_key) + key = vrf + ":" + ip_prefix + log_debug("SRT_BFD: handle_bfd_change. key %s, data %s, to_bfd_enable %s"%(key, str(data), str(to_bfd_enable))) + if to_bfd_enable: + #write route with full_nh_list to appl_db, let StaticRouteMgr(appl_db) install this route to update its cache + data['bfd'] = "false" + data['expiry'] = "false" + self.set_static_route_into_appl_db(key, data) + log_debug("SRT_BFD: bfd toggle to true. write the route to appl_db, update StaticRouteMgr(appl_db), key %s"%(key)) + else: + self.del_static_route_from_appl_db(key) + log_debug("SRT_BFD: bfd toggle to false. delete static route from appl_db, key %s"%(key)) + + #treat it as static route deletion, but do not delete it from LOCAL_CONFIG_TABLE + self.static_route_del_handler(cfg_key, False) + + def static_route_set_handler(self, key, data): + + #sanity checking + if len(data) == 0: + return True + + valid, vrf, ip_prefix = static_route_split_key(key) + route_cfg_key = vrf + "|" + ip_prefix + if not valid: + return True + + valid, is_ipv4, ip = check_ip(ip_prefix) + if not valid: + log_err("invalid ip prefix for static route: ", key) + return True + + #use lower case if there is letter in IPv6 address string + if 'nexthop' in data: + nh = data['nexthop'] + data['nexthop'] = nh.lower() + + arg_list = lambda v: [x.strip() for x in v.split(',')] if len(v.strip()) != 0 else None + bfd_field = arg_list(data['bfd']) if 'bfd' in data else ["false"] + + cur_data = self.get_local_db(LOCAL_CONFIG_TABLE, route_cfg_key) + cur_bfd_enabled = False + if cur_data: + cur_bfd_field = arg_list(cur_data['bfd']) if 'bfd' in cur_data else ["false"] + cur_bfd_enabled = self.isFieldTrue(cur_bfd_field) + + # this process, staticroutebfd, only handle the bfd enabled case, other cases would be handled in bgpcfgd/StaticRouteMgr + bfd_enabled = self.isFieldTrue(bfd_field) + + #when bfd changed from "false" to "true", before bfd session created and state becomes up, + #the installed static route need to be kept in the system system, so put this route in "hold" state until at least one + #bfd session becomes UP. + data_copy = data.copy() + data['bfd_nh_hold'] = "false" + if cur_data: + if cur_bfd_enabled and not bfd_enabled: # dynamic bfd flag change from TRUE to FALSE + self.handle_bfd_change(key, data_copy, False) + if not cur_bfd_enabled and bfd_enabled: # dynamic bfd flag change from FALSE to TRUE + self.handle_bfd_change(key, data_copy, True) + data['bfd_nh_hold'] = "true" + + # preprocess empty nexthop-vrf list before save to LOCAL_CONFIG_TABLE, bfd session need this information + nh_list = arg_list(data['nexthop']) if 'nexthop' in data else None + nh_vrf_list = arg_list(data['nexthop-vrf']) if 'nexthop-vrf' in data else None + if nh_vrf_list is None: + nh_vrf_list = [vrf] * len(nh_list) if len(nh_list) > 0 else None + data['nexthop-vrf'] = ','.join(nh_vrf_list) if nh_vrf_list else '' + else: # preprocess empty nexthop-vrf member + for index in range(len(nh_vrf_list)): + if len(nh_vrf_list[index]) == 0: + nh_vrf_list[index] = vrf + data['nexthop-vrf'] = ','.join(nh_vrf_list) + + if not bfd_enabled: + #skip if bfd is not enabled, but store it to local_db to detect bfd field dynamic change + data['bfd'] = "false" + self.set_local_db(LOCAL_CONFIG_TABLE, route_cfg_key, data) + return True + + bkh_list = arg_list(data['blackhole']) if 'blackhole' in data else None + intf_list = arg_list(data['ifname']) if 'ifname' in data else None + dist_list = arg_list(data['distance']) if 'distance' in data else None + if intf_list is None or nh_list is None or nh_vrf_list is None or \ + len(intf_list) != len(nh_list) or len(intf_list) != len(nh_vrf_list): + log_err("Static route bfd set Failed, nexthop, interface and vrf lists do not match.") + return True + + + if cur_data and cur_bfd_enabled: + # route with the prefix already exist, remove the deleted nexthops + nh_list_exist = arg_list(cur_data['nexthop']) if 'nexthop' in cur_data else None + nh_vrf_list_exist = arg_list(cur_data['nexthop-vrf']) if 'nexthop-vrf' in cur_data else None + if nh_vrf_list_exist is None: + nh_vrf_list_exist = [] + for nh in nh_list: + nh_vrf_list_exist.append(vrf) + + intf_list_exist = arg_list(cur_data['ifname']) if 'ifname' in cur_data else None + nh_key_list_exist = list(zip(nh_vrf_list_exist, intf_list_exist, nh_list_exist)) + nh_key_list_new = list(zip(nh_vrf_list, intf_list, nh_list)) + for nh in nh_key_list_exist: + if nh not in nh_key_list_new: + nh_vrf = nh[0] + nh_ip = nh[2] + nh_key = nh_vrf + "|" + nh_ip + self.remove_from_srt_table_entry(route_cfg_key, (nh_vrf, nh_ip)) + self.remove_from_nh_table_entry(nh_key, route_cfg_key) + if len(self.get_local_db(LOCAL_NEXTHOP_TABLE, nh_key)) == 0: + bfd_key = nh_vrf + ":default:" + nh_ip + self.remove_from_local_db(LOCAL_BFD_TABLE, bfd_key) + self.del_bfd_session_from_appl_db(bfd_key) + + self.set_local_db(LOCAL_CONFIG_TABLE, route_cfg_key, data) + for index in range(len(nh_list)): + nh_ip = nh_list[index] + intf = intf_list[index] + nh_vrf = nh_vrf_list[index] + nh_key = nh_vrf + "|" + nh_ip + + #check if the bfd session is already created + bfd_key = nh_vrf + ":default:" + nh_ip + bfd_session = self.get_local_db(LOCAL_BFD_TABLE, bfd_key) + if len(bfd_session)>0: + self.local_db[LOCAL_BFD_TABLE][bfd_key]["static_route"] = "true" + + if len(self.get_local_db(LOCAL_NEXTHOP_TABLE, nh_key)) == 0 and len(bfd_session) == 0: + valid, local_addr = self.find_interface_ip(intf, nh_ip) + if not valid: + #interface IP is not available yet, put this request to cache + self.set_local_db(LOCAL_BFD_PENDING_TABLE, intf+"_"+bfd_key, [intf, nh_ip, bfd_key]) + self.append_to_nh_table_entry(nh_key, vrf + "|" + ip_prefix) + log_warn("bfd_pending: cannot find ip for interface: %s, postpone bfd session creation" %intf) + continue + + bfd_entry_cfg = self.BFD_DEFAULT_CFG.copy() + if all([bfd_rx_interval, bfd_tx_interval, bfd_multiplier, bfd_multihop]): + bfd_entry_cfg["multihop"] = bfd_multihop + bfd_entry_cfg["rx_interval"] = bfd_rx_interval + bfd_entry_cfg["tx_interval"] = bfd_tx_interval + bfd_entry_cfg["multiplier"] = bfd_multiplier + + bfd_entry_cfg["local_addr"] = local_addr + self.set_bfd_session_into_appl_db(bfd_key, bfd_entry_cfg) + bfd_entry_cfg["static_route"] = "true" + self.set_local_db(LOCAL_BFD_TABLE, bfd_key, bfd_entry_cfg) + + self.append_to_nh_table_entry(nh_key, vrf + "|" + ip_prefix) + + self.refresh_active_nh(route_cfg_key) + + return True + + def static_route_del_handler(self, key, redis_del): + valid, vrf, ip_prefix = static_route_split_key(key) + if not valid: + return True + route_cfg_key = vrf + "|" + ip_prefix + + valid, is_ipv4, ip = check_ip(ip_prefix) + if not valid: + return True + + data = self.get_local_db(LOCAL_CONFIG_TABLE, route_cfg_key) + if len(data) == 0: + # this route is not handled by StaticRouteBfd, skip + return True + + arg_list = lambda v: [x.strip() for x in v.split(',')] if len(v.strip()) != 0 else None + nh_list = arg_list(data['nexthop']) if 'nexthop' in data else None + nh_vrf_list = arg_list(data['nexthop-vrf']) if 'nexthop-vrf' in data else None + bfd_field = arg_list(data['bfd']) if 'bfd' in data else ["false"] + bfd_enabled = self.isFieldTrue(bfd_field) + + # for a bfd_enabled static route, the nh_vrf_list was processed, has same length with nh_list + if bfd_enabled and nh_list and nh_vrf_list and len(nh_list) == len(nh_vrf_list): + for index in range(len(nh_list)): + nh_ip = nh_list[index] + nh_vrf = nh_vrf_list[index] + nh_key = nh_vrf + "|" + nh_ip + self.remove_from_nh_table_entry(nh_key, route_cfg_key) + + if len(self.get_local_db(LOCAL_NEXTHOP_TABLE, nh_key)) == 0: + bfd_key = nh_vrf + ":default:" + nh_ip + self.remove_from_local_db(LOCAL_BFD_TABLE, bfd_key) + self.del_bfd_session_from_appl_db(bfd_key) + + # do not delete it from appl_db if the route is not bfd enabled + if bfd_enabled: + self.del_static_route_from_appl_db(route_cfg_key.replace("|", ":")) + + self.remove_from_local_db(LOCAL_SRT_TABLE, route_cfg_key) + + if redis_del: + self.remove_from_local_db(LOCAL_CONFIG_TABLE, route_cfg_key) + + return True + + def interface_callback(self, key, op, data): + if op == swsscommon.SET_COMMAND: + self.interface_set_handler(key, data) + elif op == swsscommon.DEL_COMMAND: + self.interface_del_handler(key) + else: + log_err("Invalid operation '%s' for key '%s'" % (op, key)) + + def static_route_callback(self, key, op, data): + if op == swsscommon.SET_COMMAND: + self.static_route_set_handler(key, data) + elif op == swsscommon.DEL_COMMAND: + self.static_route_del_handler(key, True) + else: + log_err("Invalid operation '%s' for key '%s'" % (op, key)) + + def bfd_state_split_key(self, key): + """ + Split key into table name, vrf name, interface name and peer ip. + :param key: key to split + :return: table name, vrf name, interface name and peer ip extracted from the key + """ + if key.count("|") < 2: + return 'default', 'default', key + else: + return tuple(key.split('|')) + + def append_to_srt_table_entry(self, srt_key, nh_info): + entry = self.get_local_db(LOCAL_SRT_TABLE, srt_key) + entry.add(nh_info) + + def remove_from_srt_table_entry(self, srt_key, nh_info): + entry = self.get_local_db(LOCAL_SRT_TABLE, srt_key) + if nh_info in entry: + entry.remove(nh_info) + if len(entry) == 0: + self.remove_from_local_db(LOCAL_SRT_TABLE, srt_key) + + def set_static_route_into_appl_db(self, key, data): + fvs = swsscommon.FieldValuePairs(list(data.items())) + self.static_route_appl_tbl.set(key, fvs) + log_debug("SRT_BFD: set static route to appl_db, key %s, data %s"%(key, str(data))) + + def del_static_route_from_appl_db(self, key): + self.static_route_appl_tbl.delete(key) + + def reconstruct_static_route_config(self, original_config, reachable_nexthops): + arg_list = lambda v: [x.strip() for x in v.split(',')] if len(v.strip()) != 0 else None + bkh_list = arg_list(original_config['blackhole']) if 'blackhole' in original_config else None + nh_list = arg_list(original_config['nexthop']) if 'nexthop' in original_config else None + intf_list = arg_list(original_config['ifname']) if 'ifname' in original_config else None + dist_list = arg_list(original_config['distance']) if 'distance' in original_config else None + nh_vrf_list = arg_list(original_config['nexthop-vrf']) if 'nexthop-vrf' in original_config else None + + bkh_candidate = "" + nh_candidate = "" + intf_candidate = "" + dist_candidate = "" + nh_vrf_candidate = "" + + + for i in range(len(nh_list)): + if (nh_vrf_list[i], nh_list[i]) in reachable_nexthops: + bkh_candidate += "," + (bkh_list[i] if bkh_list else "") + nh_candidate += "," + (nh_list[i] if nh_list else "") + intf_candidate += "," + (intf_list[i] if intf_list else "") + dist_candidate += "," + (dist_list[i] if dist_list else "") + nh_vrf_candidate += "," + (nh_vrf_list[i] if nh_vrf_list else "") + + new_config = dict() + for key in original_config: + if key == "bfd": + continue + if key == "bfd_nh_hold": + continue + if key == "blackhole": + new_config[key] = bkh_candidate[1:] + elif key == "nexthop": + new_config[key] = nh_candidate[1:] + elif key == "ifname": + new_config[key] = intf_candidate[1:] + elif key == "distance": + new_config[key] = dist_candidate[1:] + elif key == "nexthop-vrf": + new_config[key] = nh_vrf_candidate[1:] + else: + new_config[key] = original_config[key] + new_config["expiry"] = "false" + + return new_config + + + def bfd_state_set_handler(self, key, data): + #key are diff in state db and appl_db, + #intf is always default for multihop bfd + vrf, intf, peer_ip = self.bfd_state_split_key(key) + bfd_key = vrf + ":" + intf + ":" + peer_ip + + #check if the BFD session is in local table + bfd_session = self.get_local_db(LOCAL_BFD_TABLE, bfd_key) + if len(bfd_session) == 0: + return True + + nh_key = vrf + "|" + peer_ip + state = data['state'] if 'state' in data else "DOWN" + log_info("bfd seesion %s state %s" %(bfd_key, state)) + + self.local_db[LOCAL_BFD_TABLE][bfd_key]["state"] = state + + if state.upper() == "UP": + for prefix in self.get_local_db(LOCAL_NEXTHOP_TABLE, nh_key): + srt_key = prefix + config_key = prefix + #skip if the (vrf, peer_ip) is already in the nexthop list + if (vrf, peer_ip) in self.get_local_db(LOCAL_SRT_TABLE, srt_key): + continue + self.append_to_srt_table_entry(srt_key, (vrf, peer_ip)) + config_data = self.get_local_db(LOCAL_CONFIG_TABLE, config_key) + #exit "hold" state when any BFD session becomes UP + config_data['bfd_nh_hold'] = "false" + new_config = self.reconstruct_static_route_config(config_data, self.get_local_db(LOCAL_SRT_TABLE, srt_key)) + self.set_static_route_into_appl_db(srt_key.replace("|", ":"), new_config) + + elif state.upper() == "DOWN": + for prefix in self.get_local_db(LOCAL_NEXTHOP_TABLE, nh_key): + srt_key = prefix + config_key = prefix + config_data = self.get_local_db(LOCAL_CONFIG_TABLE, config_key) + #skip if the static route is in "hold" state + if config_data['bfd_nh_hold'] == "true": + continue + self.remove_from_srt_table_entry(srt_key, (vrf, peer_ip)) + if len(self.get_local_db(LOCAL_SRT_TABLE, srt_key)) == 0: + log_debug("SRT_BFD: bfd_state DOWN. nh_list is empty, delete static route from appl_db, key %s"%(srt_key.replace("|", ":"))) + self.del_static_route_from_appl_db(srt_key.replace("|", ":")) + else: + config_data = self.get_local_db(LOCAL_CONFIG_TABLE, config_key) + new_config = self.reconstruct_static_route_config(config_data, self.get_local_db(LOCAL_SRT_TABLE, srt_key)) + self.set_static_route_into_appl_db(srt_key.replace("|", ":"), new_config) + + + def bfd_state_del_handler(self, key): + vrf, intf, peer_ip = self.bfd_state_split_key(key) + bfd_key = vrf + ":" + intf + ":" + peer_ip + + nh_key = vrf + "|" + peer_ip + + for prefix in self.get_local_db(LOCAL_NEXTHOP_TABLE, nh_key): + srt_key = prefix + config_key = prefix + self.remove_from_srt_table_entry(srt_key, (vrf, peer_ip)) + if len(self.get_local_db(LOCAL_SRT_TABLE, srt_key)) == 0: + log_debug("SRT_BFD: bfd_state deletion. nh_list is empty, delete static route from appl_db, key %s"%(srt_key.replace("|", ":"))) + self.del_static_route_from_appl_db(srt_key.replace("|", ":")) + else: + config_data = self.get_local_db(LOCAL_CONFIG_TABLE, config_key) + new_config = self.reconstruct_static_route_config(config_data, self.get_local_db(LOCAL_SRT_TABLE, srt_key)) + self.set_static_route_into_appl_db(srt_key.replace("|", ":"), new_config) + + def bfd_state_callback(self, key, op, data): + if op == swsscommon.SET_COMMAND: + self.bfd_state_set_handler(key, data) + elif op == swsscommon.DEL_COMMAND: + self.bfd_state_del_handler(key) + else: + log_err("Invalid operation '%s' for key '%s'" % (op, key)) + + + def prepare_selector(self): + interface_subscriber = swsscommon.SubscriberStateTable(self.config_db, INTERFACE_TABLE_NAME) + portchannel_interface_subscriber = swsscommon.SubscriberStateTable(self.config_db, PORTCHANNEL_INTERFACE_TABLE_NAME) + static_route_subscriber = swsscommon.SubscriberStateTable(self.config_db, STATIC_ROUTE_TABLE_NAME) + bfd_state_subscriber = swsscommon.SubscriberStateTable(self.state_db, swsscommon.STATE_BFD_SESSION_TABLE_NAME) + + self.selector.addSelectable(interface_subscriber) + self.selector.addSelectable(portchannel_interface_subscriber) + self.selector.addSelectable(static_route_subscriber) + self.selector.addSelectable(bfd_state_subscriber) + + self.subscribers.add(interface_subscriber) + self.subscribers.add(portchannel_interface_subscriber) + self.subscribers.add(static_route_subscriber) + self.subscribers.add(bfd_state_subscriber) + + self.callbacks[self.config_db.getDbId()][INTERFACE_TABLE_NAME].append(self.interface_callback) + self.callbacks[self.config_db.getDbId()][PORTCHANNEL_INTERFACE_TABLE_NAME].append(self.interface_callback) + self.callbacks[self.config_db.getDbId()][STATIC_ROUTE_TABLE_NAME].append(self.static_route_callback) + self.callbacks[self.state_db.getDbId()][swsscommon.STATE_BFD_SESSION_TABLE_NAME].append(self.bfd_state_callback) + + def run(self): + self.prepare_selector() + while g_run: + state, _ = self.selector.select(self.SELECT_TIMEOUT) + if state == self.selector.TIMEOUT: + continue + elif state == self.selector.ERROR: + raise Exception("Received error from select") + + if self.first_time: + self.first_time = False + self.reconciliation() + + for sub in self.subscribers: + while True: + key, op, fvs = sub.pop() + if len(key) == 0: + break + log_debug("Received message : '%s'" % str((key, op, fvs))) + for callback in self.callbacks[sub.getDbConnector().getDbId()][sub.getTableName()]: + callback(key, op, dict(fvs)) + +def do_work(): + sr_bfd = StaticRouteBfd() + sr_bfd.run() + +def main(): + rc = 0 + try: + syslog.openlog('staticroutebfd') + signal.signal(signal.SIGTERM, signal_handler) + signal.signal(signal.SIGINT, signal_handler) + do_work() + except KeyboardInterrupt: + syslog.syslog(syslog.LOG_NOTICE, "Keyboard interrupt") + pass + except RuntimeError as exc: + syslog.syslog(syslog.LOG_CRIT, str(exc)) + rc = -2 + if g_debug: + raise + except Exception as exc: + syslog.syslog(syslog.LOG_CRIT, "Got an exception %s: Traceback: %s" % (str(exc), traceback.format_exc())) + rc = -1 + if g_debug: + raise + finally: + syslog.closelog() + try: + sys.exit(rc) + except SystemExit: + os._exit(rc) diff --git a/src/sonic-bgpcfgd/staticroutebfd/vars.py b/src/sonic-bgpcfgd/staticroutebfd/vars.py new file mode 100644 index 000000000000..30a0baa236c1 --- /dev/null +++ b/src/sonic-bgpcfgd/staticroutebfd/vars.py @@ -0,0 +1,5 @@ +g_debug = True +bfd_multihop = "false" +bfd_rx_interval = "50" +bfd_tx_interval = "50" +bfd_multiplier = "3" diff --git a/src/sonic-bgpcfgd/tests/data/general/peer-group.conf/result_all_isolate.conf b/src/sonic-bgpcfgd/tests/data/general/peer-group.conf/result_all_isolate.conf index a078dadd6f04..bf3abfc0464e 100644 --- a/src/sonic-bgpcfgd/tests/data/general/peer-group.conf/result_all_isolate.conf +++ b/src/sonic-bgpcfgd/tests/data/general/peer-group.conf/result_all_isolate.conf @@ -23,11 +23,17 @@ route-map TO_BGP_PEER_V4 permit 20 match ip address prefix-list PL_LoopbackV4 set community 12345:12345 -route-map TO_BGP_PEER_V4 deny 30 +route-map TO_BGP_PEER_V4 permit 30 + match tag 1001 + set community 12345:12345 +route-map TO_BGP_PEER_V4 deny 40 ! route-map TO_BGP_PEER_V6 permit 20 match ipv6 address prefix-list PL_LoopbackV6 set community 12345:12345 -route-map TO_BGP_PEER_V6 deny 30 +route-map TO_BGP_PEER_V6 permit 30 + match tag 1001 + set community 12345:12345 +route-map TO_BGP_PEER_V6 deny 40 ! diff --git a/src/sonic-bgpcfgd/tests/data/general/peer-group.conf/result_all_unisolate.conf b/src/sonic-bgpcfgd/tests/data/general/peer-group.conf/result_all_unisolate.conf index 1cd4442f4f3d..fa56d296e4d3 100644 --- a/src/sonic-bgpcfgd/tests/data/general/peer-group.conf/result_all_unisolate.conf +++ b/src/sonic-bgpcfgd/tests/data/general/peer-group.conf/result_all_unisolate.conf @@ -21,9 +21,11 @@ no route-map TO_BGP_PEER_V4 permit 20 -no route-map TO_BGP_PEER_V4 deny 30 +no route-map TO_BGP_PEER_V4 permit 30 +no route-map TO_BGP_PEER_V4 deny 40 ! no route-map TO_BGP_PEER_V6 permit 20 -no route-map TO_BGP_PEER_V6 deny 30 +no route-map TO_BGP_PEER_V6 permit 30 +no route-map TO_BGP_PEER_V6 deny 40 ! diff --git a/src/sonic-bgpcfgd/tests/data/general/peer-group.conf/result_isolate.conf b/src/sonic-bgpcfgd/tests/data/general/peer-group.conf/result_isolate.conf index 902b8cfcdab9..88017bf2f30a 100644 --- a/src/sonic-bgpcfgd/tests/data/general/peer-group.conf/result_isolate.conf +++ b/src/sonic-bgpcfgd/tests/data/general/peer-group.conf/result_isolate.conf @@ -2,10 +2,16 @@ route-map TO_BGP_PEER_V4 permit 20 match ip address prefix-list PL_LoopbackV4 set community 12345:12345 -route-map TO_BGP_PEER_V4 deny 30 +route-map TO_BGP_PEER_V4 permit 30 + match tag 1001 + set community 12345:12345 +route-map TO_BGP_PEER_V4 deny 40 ! route-map TO_BGP_PEER_V6 permit 20 match ipv6 address prefix-list PL_LoopbackV6 set community 12345:12345 -route-map TO_BGP_PEER_V6 deny 30 +route-map TO_BGP_PEER_V6 permit 30 + match tag 1001 + set community 12345:12345 +route-map TO_BGP_PEER_V6 deny 40 ! diff --git a/src/sonic-bgpcfgd/tests/data/general/peer-group.conf/result_unisolate.conf b/src/sonic-bgpcfgd/tests/data/general/peer-group.conf/result_unisolate.conf index 8fd9fde7f759..8bfcdee993d4 100644 --- a/src/sonic-bgpcfgd/tests/data/general/peer-group.conf/result_unisolate.conf +++ b/src/sonic-bgpcfgd/tests/data/general/peer-group.conf/result_unisolate.conf @@ -1,7 +1,9 @@ no route-map TO_BGP_PEER_V4 permit 20 -no route-map TO_BGP_PEER_V4 deny 30 +no route-map TO_BGP_PEER_V4 permit 30 +no route-map TO_BGP_PEER_V4 deny 40 ! no route-map TO_BGP_PEER_V6 permit 20 -no route-map TO_BGP_PEER_V6 deny 30 +no route-map TO_BGP_PEER_V6 permit 30 +no route-map TO_BGP_PEER_V6 deny 40 ! diff --git a/src/sonic-bgpcfgd/tests/data/internal/peer-group.conf/result_chassis_packet_isolate.conf b/src/sonic-bgpcfgd/tests/data/internal/peer-group.conf/result_chassis_packet_isolate.conf new file mode 100644 index 000000000000..cfb47916e655 --- /dev/null +++ b/src/sonic-bgpcfgd/tests/data/internal/peer-group.conf/result_chassis_packet_isolate.conf @@ -0,0 +1,35 @@ +! +! template: bgpd/templates/internal/peer-group.conf.j2 +! + neighbor INTERNAL_PEER_V4 peer-group + neighbor INTERNAL_PEER_V6 peer-group + neighbor INTERNAL_PEER_V4 update-source Loopback4096 + address-family ipv4 + neighbor INTERNAL_PEER_V4 soft-reconfiguration inbound + neighbor INTERNAL_PEER_V4 allowas-in 1 + neighbor INTERNAL_PEER_V4 route-map FROM_BGP_INTERNAL_PEER_V4 in + neighbor INTERNAL_PEER_V4 route-map TO_BGP_INTERNAL_PEER_V4 out + neighbor INTERNAL_PEER_V4 send-community + neighbor INTERNAL_PEER_V4 ttl-security hops 1 + exit-address-family + neighbor INTERNAL_PEER_V6 update-source Loopback4096 + address-family ipv6 + neighbor INTERNAL_PEER_V6 soft-reconfiguration inbound + neighbor INTERNAL_PEER_V6 allowas-in 1 + neighbor INTERNAL_PEER_V6 route-map FROM_BGP_INTERNAL_PEER_V6 in + neighbor INTERNAL_PEER_V6 route-map TO_BGP_INTERNAL_PEER_V6 out + neighbor INTERNAL_PEER_V6 send-community + neighbor INTERNAL_PEER_V6 ttl-security hops 1 + exit-address-family +! +! end of template: bgpd/templates/internal/peer-group.conf.j2 +! + + +route-map TO_BGP_INTERNAL_PEER_V4 permit 20 + set community no-export additive +! +route-map TO_BGP_INTERNAL_PEER_V6 permit 20 + set community no-export additive +! + diff --git a/src/sonic-bgpcfgd/tests/data/internal/peer-group.conf/result_chassis_packet_unisolate.conf b/src/sonic-bgpcfgd/tests/data/internal/peer-group.conf/result_chassis_packet_unisolate.conf new file mode 100644 index 000000000000..2711f46d567b --- /dev/null +++ b/src/sonic-bgpcfgd/tests/data/internal/peer-group.conf/result_chassis_packet_unisolate.conf @@ -0,0 +1,33 @@ +! +! template: bgpd/templates/internal/peer-group.conf.j2 +! + neighbor INTERNAL_PEER_V4 peer-group + neighbor INTERNAL_PEER_V6 peer-group + neighbor INTERNAL_PEER_V4 update-source Loopback4096 + address-family ipv4 + neighbor INTERNAL_PEER_V4 soft-reconfiguration inbound + neighbor INTERNAL_PEER_V4 allowas-in 1 + neighbor INTERNAL_PEER_V4 route-map FROM_BGP_INTERNAL_PEER_V4 in + neighbor INTERNAL_PEER_V4 route-map TO_BGP_INTERNAL_PEER_V4 out + neighbor INTERNAL_PEER_V4 send-community + neighbor INTERNAL_PEER_V4 ttl-security hops 1 + exit-address-family + neighbor INTERNAL_PEER_V6 update-source Loopback4096 + address-family ipv6 + neighbor INTERNAL_PEER_V6 soft-reconfiguration inbound + neighbor INTERNAL_PEER_V6 allowas-in 1 + neighbor INTERNAL_PEER_V6 route-map FROM_BGP_INTERNAL_PEER_V6 in + neighbor INTERNAL_PEER_V6 route-map TO_BGP_INTERNAL_PEER_V6 out + neighbor INTERNAL_PEER_V6 send-community + neighbor INTERNAL_PEER_V6 ttl-security hops 1 + exit-address-family +! +! end of template: bgpd/templates/internal/peer-group.conf.j2 +! + + +no route-map TO_BGP_INTERNAL_PEER_V4 permit 20 +! +no route-map TO_BGP_INTERNAL_PEER_V6 permit 20 +! + diff --git a/src/sonic-bgpcfgd/tests/data/internal/policies.conf/param_back.json b/src/sonic-bgpcfgd/tests/data/internal/policies.conf/param_back.json index 37e54d785e27..d39721ae0c87 100644 --- a/src/sonic-bgpcfgd/tests/data/internal/policies.conf/param_back.json +++ b/src/sonic-bgpcfgd/tests/data/internal/policies.conf/param_back.json @@ -6,5 +6,11 @@ }, "CONFIG_DB__LOOPBACK_INTERFACE": { "Loopback4096|10.10.10.10/32": {} + }, + "constants": { + "bgp": { + "internal_community": "12345:556", + "internal_community_match_tag": "101" + } } } diff --git a/src/sonic-bgpcfgd/tests/data/internal/policies.conf/param_chasiss_packet.json b/src/sonic-bgpcfgd/tests/data/internal/policies.conf/param_chasiss_packet.json new file mode 100644 index 000000000000..1e600cc9d72b --- /dev/null +++ b/src/sonic-bgpcfgd/tests/data/internal/policies.conf/param_chasiss_packet.json @@ -0,0 +1,16 @@ +{ + "CONFIG_DB__DEVICE_METADATA": { + "localhost": { + "type": "SpineRouter", + "sub_role": "FrontEnd", + "switch_type": "chassis-packet" + } + }, + "constants": { + "bgp": { + "internal_community": "12345:556", + "internal_community_match_tag": "101" + } + }, + "loopback0_ipv4": "10.10.10.10/32" +} diff --git a/src/sonic-bgpcfgd/tests/data/internal/policies.conf/param_front.json b/src/sonic-bgpcfgd/tests/data/internal/policies.conf/param_front.json index 68c27766d257..f18513d815c8 100644 --- a/src/sonic-bgpcfgd/tests/data/internal/policies.conf/param_front.json +++ b/src/sonic-bgpcfgd/tests/data/internal/policies.conf/param_front.json @@ -1,7 +1,13 @@ { "CONFIG_DB__DEVICE_METADATA": { "localhost": { - "sub_role": "FrontkEnd" + "sub_role": "FrontEnd" + } + }, + "constants": { + "bgp": { + "internal_community": "12345:556", + "internal_community_match_tag": "101" } }, "loopback0_ipv4": "10.10.10.10/32" diff --git a/src/sonic-bgpcfgd/tests/data/internal/policies.conf/result_back.conf b/src/sonic-bgpcfgd/tests/data/internal/policies.conf/result_back.conf index 81b5aab193c6..5ee9967d85ea 100644 --- a/src/sonic-bgpcfgd/tests/data/internal/policies.conf/result_back.conf +++ b/src/sonic-bgpcfgd/tests/data/internal/policies.conf/result_back.conf @@ -1,23 +1,23 @@ ! ! template: bgpd/templates/internal/policies.conf.j2 ! -route-map FROM_BGP_INTERNAL_PEER_V4 permit 100 -! -route-map TO_BGP_INTERNAL_PEER_V4 permit 100 +route-map FROM_BGP_INTERNAL_PEER_V4 permit 1 + set originator-id 10.10.10.10 ! route-map FROM_BGP_INTERNAL_PEER_V6 permit 1 set ipv6 next-hop prefer-global on-match next ! -route-map FROM_BGP_INTERNAL_PEER_V6 permit 100 +route-map FROM_BGP_INTERNAL_PEER_V6 permit 2 + set originator-id 10.10.10.10 ! -route-map TO_BGP_INTERNAL_PEER_V6 permit 100 +route-map FROM_BGP_INTERNAL_PEER_V4 permit 100 ! -route-map FROM_BGP_INTERNAL_PEER_V4 permit 2 - set originator-id 10.10.10.10 +route-map FROM_BGP_INTERNAL_PEER_V6 permit 100 ! -route-map FROM_BGP_INTERNAL_PEER_V6 permit 2 - set originator-id 10.10.10.10 +route-map TO_BGP_INTERNAL_PEER_V4 permit 100 +! +route-map TO_BGP_INTERNAL_PEER_V6 permit 100 ! ! end of template: bgpd/templates/internal/policies.conf.j2 ! diff --git a/src/sonic-bgpcfgd/tests/data/internal/policies.conf/result_chasiss_packet.conf b/src/sonic-bgpcfgd/tests/data/internal/policies.conf/result_chasiss_packet.conf new file mode 100644 index 000000000000..4b346d635975 --- /dev/null +++ b/src/sonic-bgpcfgd/tests/data/internal/policies.conf/result_chasiss_packet.conf @@ -0,0 +1,46 @@ +! +! template: bgpd/templates/internal/policies.conf.j2 +! +bgp community-list standard DEVICE_INTERNAL_COMMUNITY permit 12345:556 +bgp community-list standard NO_EXPORT permit no-export +! +route-map FROM_BGP_INTERNAL_PEER_V4 permit 1 + match community DEVICE_INTERNAL_COMMUNITY + set comm-list DEVICE_INTERNAL_COMMUNITY delete + set tag 101 +! +route-map FROM_BGP_INTERNAL_PEER_V4 permit 2 + match community NO_EXPORT + set local-preference 80 +! +route-map FROM_BGP_INTERNAL_PEER_V6 permit 1 + set ipv6 next-hop prefer-global + on-match next +! +route-map FROM_BGP_INTERNAL_PEER_V6 permit 2 + match community DEVICE_INTERNAL_COMMUNITY + set comm-list DEVICE_INTERNAL_COMMUNITY delete + set tag 101 +! +route-map FROM_BGP_INTERNAL_PEER_V6 permit 3 + match community NO_EXPORT + set local-preference 80 +! +route-map TO_BGP_INTERNAL_PEER_V4 permit 1 + match ip address prefix-list PL_LoopbackV4 + set community 12345:556 +! +route-map TO_BGP_INTERNAL_PEER_V6 permit 2 + match ipv6 address prefix-list PL_LoopbackV6 + set community 12345:556 +! +route-map FROM_BGP_INTERNAL_PEER_V4 permit 100 +! +route-map FROM_BGP_INTERNAL_PEER_V6 permit 100 +! +route-map TO_BGP_INTERNAL_PEER_V4 permit 100 +! +route-map TO_BGP_INTERNAL_PEER_V6 permit 100 +! +! end of template: bgpd/templates/internal/policies.conf.j2 +! diff --git a/src/sonic-bgpcfgd/tests/data/internal/policies.conf/result_front.conf b/src/sonic-bgpcfgd/tests/data/internal/policies.conf/result_front.conf index 880530a2797e..0c6405321f17 100644 --- a/src/sonic-bgpcfgd/tests/data/internal/policies.conf/result_front.conf +++ b/src/sonic-bgpcfgd/tests/data/internal/policies.conf/result_front.conf @@ -1,16 +1,16 @@ ! ! template: bgpd/templates/internal/policies.conf.j2 ! -route-map FROM_BGP_INTERNAL_PEER_V4 permit 100 -! -route-map TO_BGP_INTERNAL_PEER_V4 permit 100 -! route-map FROM_BGP_INTERNAL_PEER_V6 permit 1 set ipv6 next-hop prefer-global on-match next ! +route-map FROM_BGP_INTERNAL_PEER_V4 permit 100 +! route-map FROM_BGP_INTERNAL_PEER_V6 permit 100 ! +route-map TO_BGP_INTERNAL_PEER_V4 permit 100 +! route-map TO_BGP_INTERNAL_PEER_V6 permit 100 ! ! end of template: bgpd/templates/internal/policies.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 index 4f45f8a0f3f4..355e4b6b58a3 100644 --- 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 @@ -1,3 +1,8 @@ { + "CONFIG_DB__DEVICE_METADATA": { + "localhost": { + "type": "LeafRouter" + } + }, "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/param_chassis.json b/src/sonic-bgpcfgd/tests/data/monitors/peer-group.conf/param_chassis.json new file mode 100644 index 000000000000..a09a731b1e68 --- /dev/null +++ b/src/sonic-bgpcfgd/tests/data/monitors/peer-group.conf/param_chassis.json @@ -0,0 +1,7 @@ +{ + "CONFIG_DB__DEVICE_METADATA": { + "localhost": { + "type": "SpineRouter" + } + } +} 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 index d5e9624ff1a5..4bceb7cf3365 100644 --- 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 @@ -3,10 +3,14 @@ ! 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 + address-family ipv4 + neighbor BGPMON activate + neighbor BGPMON route-map FROM_BGPMON in + neighbor BGPMON route-map TO_BGPMON out + neighbor BGPMON send-community + neighbor BGPMON maximum-prefix 1 + exit-address-family ! ! end of template: bgpd/templates/BGPMON/peer-group.conf.j2 ! + diff --git a/src/sonic-bgpcfgd/tests/data/monitors/peer-group.conf/result_chassis.conf b/src/sonic-bgpcfgd/tests/data/monitors/peer-group.conf/result_chassis.conf new file mode 100644 index 000000000000..f0050367b892 --- /dev/null +++ b/src/sonic-bgpcfgd/tests/data/monitors/peer-group.conf/result_chassis.conf @@ -0,0 +1,22 @@ +! +! template: bgpd/templates/BGPMON/peer-group.conf.j2 +! + neighbor BGPMON peer-group + neighbor BGPMON update-source Loopback4096 + address-family ipv4 + neighbor BGPMON activate + neighbor BGPMON route-map FROM_BGPMON in + neighbor BGPMON route-map TO_BGPMON out + neighbor BGPMON send-community + neighbor BGPMON maximum-prefix 1 + exit-address-family + address-family ipv6 + neighbor BGPMON activate + neighbor BGPMON route-map FROM_BGPMON in + neighbor BGPMON route-map TO_BGPMON out + neighbor BGPMON send-community + neighbor BGPMON maximum-prefix 1 + exit-address-family +! +! end of template: bgpd/templates/BGPMON/peer-group.conf.j2 +! diff --git a/src/sonic-bgpcfgd/tests/data/sonic-cfggen/bgpd.main.conf.j2/packet_chassis.conf b/src/sonic-bgpcfgd/tests/data/sonic-cfggen/bgpd.main.conf.j2/packet_chassis.conf index 37ac8827dc46..a949ce6e4512 100644 --- a/src/sonic-bgpcfgd/tests/data/sonic-cfggen/bgpd.main.conf.j2/packet_chassis.conf +++ b/src/sonic-bgpcfgd/tests/data/sonic-cfggen/bgpd.main.conf.j2/packet_chassis.conf @@ -46,6 +46,7 @@ router bgp 55555 ! address-family ipv6 network fc00::1/64 + network fc00::1/128 route-map HIDE_INTERNAL exit-address-family ! network 10.10.10.1/24 diff --git a/src/sonic-bgpcfgd/tests/data/sonic-cfggen/bgpd.main.conf.j2/voq_chassis.conf b/src/sonic-bgpcfgd/tests/data/sonic-cfggen/bgpd.main.conf.j2/voq_chassis.conf index d8ee10ada1e0..0d9eeebe9e8e 100644 --- a/src/sonic-bgpcfgd/tests/data/sonic-cfggen/bgpd.main.conf.j2/voq_chassis.conf +++ b/src/sonic-bgpcfgd/tests/data/sonic-cfggen/bgpd.main.conf.j2/voq_chassis.conf @@ -47,6 +47,7 @@ router bgp 55555 ! address-family ipv6 network fc00::1/64 + network fc00::1/128 route-map HIDE_INTERNAL exit-address-family address-family ipv6 network fc00::2/128 route-map HIDE_INTERNAL 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 index 606788cba999..af2e974ee9b7 100644 --- 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 @@ -17,6 +17,7 @@ agentx ! ! Enable nht through default route ip nht resolve-via-default +ipv6 nht resolve-via-default ! Enable link-detect (default disabled) interface Ethernet0 link-detect diff --git a/src/sonic-bgpcfgd/tests/data/sonic-cfggen/tsa/isolate.conf b/src/sonic-bgpcfgd/tests/data/sonic-cfggen/tsa/isolate.conf index 2ea4111dfc26..e775b6d0acb5 100644 --- a/src/sonic-bgpcfgd/tests/data/sonic-cfggen/tsa/isolate.conf +++ b/src/sonic-bgpcfgd/tests/data/sonic-cfggen/tsa/isolate.conf @@ -1,5 +1,8 @@ route-map test_rm_name permit 20 match ip address prefix-list PL_LoopbackV4 set community 12345:555 -route-map test_rm_name deny 30 +route-map test_rm_name permit 30 + match tag 1002 + set community 12345:555 +route-map test_rm_name deny 40 ! diff --git a/src/sonic-bgpcfgd/tests/data/sonic-cfggen/tsa/isolate.json b/src/sonic-bgpcfgd/tests/data/sonic-cfggen/tsa/isolate.json index 807dfe7e1a0c..68ffe27c46a3 100644 --- a/src/sonic-bgpcfgd/tests/data/sonic-cfggen/tsa/isolate.json +++ b/src/sonic-bgpcfgd/tests/data/sonic-cfggen/tsa/isolate.json @@ -1,10 +1,11 @@ { "constants": { "bgp": { - "traffic_shift_community": "12345:555" + "traffic_shift_community": "12345:555", + "internal_community_match_tag": "1002" } }, "route_map_name": "test_rm_name", "ip_version": "V4", "ip_protocol": "ip" -} \ 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 index 2adeac6e0ef7..31553e3a9844 100644 --- a/src/sonic-bgpcfgd/tests/data/sonic-cfggen/tsa/unisolate.conf +++ b/src/sonic-bgpcfgd/tests/data/sonic-cfggen/tsa/unisolate.conf @@ -1,3 +1,4 @@ no route-map test_rm permit 20 -no route-map test_rm deny 30 +no route-map test_rm permit 30 +no route-map test_rm deny 40 ! diff --git a/src/sonic-bgpcfgd/tests/data/sonic-cfggen/zebra/interfaces.conf b/src/sonic-bgpcfgd/tests/data/sonic-cfggen/zebra/interfaces.conf index ddd129bcd18b..d185af6f9b07 100644 --- a/src/sonic-bgpcfgd/tests/data/sonic-cfggen/zebra/interfaces.conf +++ b/src/sonic-bgpcfgd/tests/data/sonic-cfggen/zebra/interfaces.conf @@ -1,6 +1,7 @@ ! ! Enable nht through default route ip nht resolve-via-default +ipv6 nht resolve-via-default ! Enable link-detect (default disabled) interface Ethernet0 link-detect diff --git a/src/sonic-bgpcfgd/tests/data/sonic-cfggen/zebra/zebra.conf b/src/sonic-bgpcfgd/tests/data/sonic-cfggen/zebra/zebra.conf index ac2d8dac88f2..058ca6477dd5 100644 --- a/src/sonic-bgpcfgd/tests/data/sonic-cfggen/zebra/zebra.conf +++ b/src/sonic-bgpcfgd/tests/data/sonic-cfggen/zebra/zebra.conf @@ -22,6 +22,7 @@ vni 20 ! ! Enable nht through default route ip nht resolve-via-default +ipv6 nht resolve-via-default ! Enable link-detect (default disabled) interface Ethernet0 link-detect diff --git a/src/sonic-bgpcfgd/tests/data/voq_chassis/policies.conf/param_base.json b/src/sonic-bgpcfgd/tests/data/voq_chassis/policies.conf/param_base.json index 7ef21c181d7e..483cc938c59d 100644 --- a/src/sonic-bgpcfgd/tests/data/voq_chassis/policies.conf/param_base.json +++ b/src/sonic-bgpcfgd/tests/data/voq_chassis/policies.conf/param_base.json @@ -1,5 +1,11 @@ { "CONFIG_DB__DEVICE_METADATA": { "localhost": {} + }, + "constants": { + "bgp": { + "internal_community": "12345:556", + "internal_community_match_tag": "101" + } } } diff --git a/src/sonic-bgpcfgd/tests/data/voq_chassis/policies.conf/result_base.conf b/src/sonic-bgpcfgd/tests/data/voq_chassis/policies.conf/result_base.conf index c26db7bde241..f0e3771d1a39 100644 --- a/src/sonic-bgpcfgd/tests/data/voq_chassis/policies.conf/result_base.conf +++ b/src/sonic-bgpcfgd/tests/data/voq_chassis/policies.conf/result_base.conf @@ -1,17 +1,45 @@ ! ! template: bgpd/templates/voq_chassis/policies.conf.j2 ! +bgp community-list standard DEVICE_INTERNAL_COMMUNITY permit 12345:556 +bgp community-list standard NO_EXPORT permit no-export +! +route-map FROM_VOQ_CHASSIS_V4_PEER permit 1 + match community DEVICE_INTERNAL_COMMUNITY + set comm-list DEVICE_INTERNAL_COMMUNITY delete + set tag 101 +! +route-map FROM_VOQ_CHASSIS_V4_PEER permit 2 + match community NO_EXPORT + set local-preference 80 +! route-map FROM_VOQ_CHASSIS_V4_PEER permit 100 ! -route-map TO_VOQ_CHASSIS_V4_PEER permit 100 +route-map TO_VOQ_CHASSIS_V4_PEER permit 1 + match ip address prefix-list PL_LoopbackV4 + set community 12345:556 ! +route-map TO_VOQ_CHASSIS_V4_PEER permit 100 ! route-map FROM_VOQ_CHASSIS_V6_PEER permit 1 set ipv6 next-hop prefer-global on-match next ! +route-map FROM_VOQ_CHASSIS_V6_PEER permit 2 + match community DEVICE_INTERNAL_COMMUNITY + set comm-list DEVICE_INTERNAL_COMMUNITY delete + set tag 101 +! +route-map FROM_VOQ_CHASSIS_V6_PEER permit 3 + match community NO_EXPORT + set local-preference 80 +! route-map FROM_VOQ_CHASSIS_V6_PEER permit 100 ! +route-map TO_VOQ_CHASSIS_V6_PEER permit 1 + match ipv6 address prefix-list PL_LoopbackV6 + set community 12345:556 +! route-map TO_VOQ_CHASSIS_V6_PEER permit 100 ! ! end of template: bgpd/templates/voq_chassis/policies.conf.j2 diff --git a/src/sonic-bgpcfgd/tests/test_device_global.py b/src/sonic-bgpcfgd/tests/test_device_global.py index ad79158aaa06..ebb0361d5aab 100644 --- a/src/sonic-bgpcfgd/tests/test_device_global.py +++ b/src/sonic-bgpcfgd/tests/test_device_global.py @@ -11,13 +11,15 @@ TEMPLATE_PATH = os.path.abspath('../../dockers/docker-fpm-frr/frr') BASE_PATH = os.path.abspath('../sonic-bgpcfgd/tests/data/general/peer-group.conf/') +INTERNAL_BASE_PATH = os.path.abspath('../sonic-bgpcfgd/tests/data/internal/peer-group.conf/') global_constants = { "bgp": { - "traffic_shift_community" :"12345:12345" + "traffic_shift_community" :"12345:12345", + "internal_community_match_tag" : "1001" } } -def constructor(): +def constructor(check_internal=False): cfg_mgr = MagicMock() def get_text(): text = [] @@ -28,7 +30,10 @@ def get_text(): text += [" "] return text def update(): - cfg_mgr.changes = get_string_from_file("/result_all.conf") + if check_internal: + cfg_mgr.changes = get_string_from_file("/result_chasiss_packet.conf", INTERNAL_BASE_PATH) + else: + cfg_mgr.changes = get_string_from_file("/result_all.conf") def push(cfg): cfg_mgr.changes += cfg + "\n" def get_config(): @@ -59,13 +64,31 @@ def test_isolate_device(mocked_log_info): assert m.cfg_mgr.get_config() == get_string_from_file("/result_all_isolate.conf") @patch('bgpcfgd.managers_device_global.log_debug') -def test_unisolate_device(mocked_log_info): +def test_isolate_device_internal_session(mocked_log_info): + m = constructor(check_internal=True) + res = m.set_handler("STATE", {"tsa_enabled": "true"}) + assert res, "Expect True return value for set_handler" + mocked_log_info.assert_called_with("DeviceGlobalCfgMgr::Done") + assert m.cfg_mgr.get_config() == get_string_from_file("/result_chassis_packet_isolate.conf", INTERNAL_BASE_PATH) + + +@patch('bgpcfgd.managers_device_global.log_debug') +def test_unisolate_device(mocked_log_info): m = constructor() res = m.set_handler("STATE", {"tsa_enabled": "false"}) assert res, "Expect True return value for set_handler" mocked_log_info.assert_called_with("DeviceGlobalCfgMgr::Done") assert m.cfg_mgr.get_config() == get_string_from_file("/result_all_unisolate.conf") +@patch('bgpcfgd.managers_device_global.log_debug') +def test_unisolate_device_internal_session(mocked_log_info): + m = constructor(check_internal=True) + res = m.set_handler("STATE", {"tsa_enabled": "false"}) + assert res, "Expect True return value for set_handler" + mocked_log_info.assert_called_with("DeviceGlobalCfgMgr::Done") + assert m.cfg_mgr.get_config() == get_string_from_file("/result_chassis_packet_unisolate.conf", INTERNAL_BASE_PATH) + + def test_check_state_and_get_tsa_routemaps(): m = constructor() m.set_handler("STATE", {"tsa_enabled": "true"}) @@ -92,8 +115,8 @@ def test_get_tsb_routemaps(): expected_res = get_string_from_file("/result_unisolate.conf") assert res == expected_res -def get_string_from_file(filename): - fp = open(BASE_PATH + filename, "r") +def get_string_from_file(filename, base_path=BASE_PATH): + fp = open(base_path + filename, "r") cfg = fp.read() fp.close() diff --git a/src/sonic-bgpcfgd/tests/test_static_rt.py b/src/sonic-bgpcfgd/tests/test_static_rt.py index 881bba1563b7..422a3451c4fb 100644 --- a/src/sonic-bgpcfgd/tests/test_static_rt.py +++ b/src/sonic-bgpcfgd/tests/test_static_rt.py @@ -73,6 +73,167 @@ def test_set(): ] ) +@patch('bgpcfgd.managers_static_rt.log_debug') +def test_del_for_appl(mocked_log_debug): + class MockRedisConfigDbGet: + def __init__(self, cache=dict()): + self.cache = cache + self.CONFIG_DB = "CONFIG_DB" + + def get(self, db, key, field): + if key in self.cache: + if field in self.cache[key]["value"]: + return self.cache[key]["value"][field] + return None # return nil + + mgr = constructor() + + set_del_test( + mgr, + "SET", + ("10.1.0.0/24", { + "nexthop": "PortChannel0001", + }), + True, + [ + "ip route 10.1.0.0/24 PortChannel0001 tag 1", + "route-map STATIC_ROUTE_FILTER permit 10", + " match tag 1", + "router bgp 65100", + " address-family ipv4", + " redistribute static route-map STATIC_ROUTE_FILTER", + " address-family ipv6", + " redistribute static route-map STATIC_ROUTE_FILTER" + ] + ) + + #from "APPL_DB" instance, static route can not be uninstalled if the static route exists in config_db and "bfd"="false" (or no bfd field) + mgr.db_name = "APPL_DB" + cfg_db_cache = { + "STATIC_ROUTE|10.1.0.0/24": { + "value": { + "advertise": "false", + "nexthop": "PortChannel0001" + } + } + } + mgr.config_db = MockRedisConfigDbGet(cfg_db_cache) + + set_del_test( + mgr, + "DEL", + ("10.1.0.0/24",), + True, + [] + ) + mocked_log_debug.assert_called_with("{} ignore appl_db static route deletion because of key {} exist in config_db and bfd is not true".format(mgr.db_name, "10.1.0.0/24")) + + cfg_db_cache = { + "STATIC_ROUTE|10.1.0.0/24": { + "value": { + "advertise": "false", + "bfd": "false", + "nexthop": "PortChannel0001" + } + } + } + mgr.db_name = "APPL_DB" + mgr.config_db = MockRedisConfigDbGet(cfg_db_cache) + + set_del_test( + mgr, + "DEL", + ("10.1.0.0/24",), + True, + [] + ) + mocked_log_debug.assert_called_with("{} ignore appl_db static route deletion because of key {} exist in config_db and bfd is not true".format(mgr.db_name, "10.1.0.0/24")) + + #From "APPL_DB" instance, static route can be deleted if bfd field is true in config_db + set_del_test( + mgr, + "SET", + ("10.1.0.0/24", { + "nexthop": "PortChannel0001", + }), + True, + [ + "ip route 10.1.0.0/24 PortChannel0001 tag 1", + "route-map STATIC_ROUTE_FILTER permit 10", + " match tag 1", + "router bgp 65100", + " address-family ipv4", + " redistribute static route-map STATIC_ROUTE_FILTER", + " address-family ipv6", + " redistribute static route-map STATIC_ROUTE_FILTER" + ] + ) + cfg_db_cache = { + "STATIC_ROUTE|10.1.0.0/24": { + "value": { + "advertise": "false", + "bfd": "true", + "nexthop": "PortChannel0001" + } + } + } + mgr.db_name = "APPL_DB" + mgr.config_db = MockRedisConfigDbGet(cfg_db_cache) + set_del_test( + mgr, + "DEL", + ("10.1.0.0/24",), + True, + [ + "no ip route 10.1.0.0/24 PortChannel0001 tag 1", + "router bgp 65100", + " address-family ipv4", + " no redistribute static route-map STATIC_ROUTE_FILTER", + " address-family ipv6", + " no redistribute static route-map STATIC_ROUTE_FILTER", + "no route-map STATIC_ROUTE_FILTER" + ] + ) + + #From "APPL_DB" instance, static route can be deleted if the static route does not in config_db + set_del_test( + mgr, + "SET", + ("10.1.0.0/24", { + "nexthop": "PortChannel0001", + }), + True, + [ + "ip route 10.1.0.0/24 PortChannel0001 tag 1", + "route-map STATIC_ROUTE_FILTER permit 10", + " match tag 1", + "router bgp 65100", + " address-family ipv4", + " redistribute static route-map STATIC_ROUTE_FILTER", + " address-family ipv6", + " redistribute static route-map STATIC_ROUTE_FILTER" + ] + ) + + cfg_db_cache = {} + mgr.db_name = "APPL_DB" + mgr.config_db = MockRedisConfigDbGet(cfg_db_cache) + set_del_test( + mgr, + "DEL", + ("10.1.0.0/24",), + True, + [ + "no ip route 10.1.0.0/24 PortChannel0001 tag 1", + "router bgp 65100", + " address-family ipv4", + " no redistribute static route-map STATIC_ROUTE_FILTER", + " address-family ipv6", + " no redistribute static route-map STATIC_ROUTE_FILTER", + "no route-map STATIC_ROUTE_FILTER" + ] + ) + def test_set_nhportchannel(): mgr = constructor() set_del_test( @@ -604,7 +765,7 @@ def test_set_no_action(mocked_log_debug): True, [] ) - mocked_log_debug.assert_called_with("Nothing to update for static route default|10.1.1.0/24") + mocked_log_debug.assert_called_with("CONFIG_DB Nothing to update for static route default|10.1.1.0/24") @patch('bgpcfgd.managers_static_rt.log_debug') def test_del_no_action(mocked_log_debug): @@ -616,7 +777,7 @@ def test_del_no_action(mocked_log_debug): True, [] ) - mocked_log_debug.assert_called_with("Nothing to update for static route default|10.1.1.0/24") + mocked_log_debug.assert_called_with("CONFIG_DB Nothing to update for static route default|10.1.1.0/24") def test_set_invalid_arg(): mgr = constructor() @@ -821,3 +982,109 @@ def test_set_tag_change(): "ip route 10.1.0.0/24 10.0.0.57 tag 2", ] ) + +def test_set_bfd_false(): + mgr = constructor() + set_del_test( + mgr, + "SET", + ("10.1.0.0/24", { + "bfd": "false", + "nexthop": "PortChannel0001", + }), + True, + [ + "ip route 10.1.0.0/24 PortChannel0001 tag 1", + "route-map STATIC_ROUTE_FILTER permit 10", + " match tag 1", + "router bgp 65100", + " address-family ipv4", + " redistribute static route-map STATIC_ROUTE_FILTER", + " address-family ipv6", + " redistribute static route-map STATIC_ROUTE_FILTER" + ] + ) + + set_del_test( + mgr, + "DEL", + ("10.1.0.0/24",), + True, + [ + "no ip route 10.1.0.0/24 PortChannel0001 tag 1", + "router bgp 65100", + " address-family ipv4", + " no redistribute static route-map STATIC_ROUTE_FILTER", + " address-family ipv6", + " no redistribute static route-map STATIC_ROUTE_FILTER", + "no route-map STATIC_ROUTE_FILTER" + ] + ) + +def test_set_bfd_true(): + mgr = constructor() + set_del_test( + mgr, + "SET", + ("10.1.0.0/24", { + "bfd": "false", + "nexthop": "PortChannel0001", + }), + True, + [ + "ip route 10.1.0.0/24 PortChannel0001 tag 1", + "route-map STATIC_ROUTE_FILTER permit 10", + " match tag 1", + "router bgp 65100", + " address-family ipv4", + " redistribute static route-map STATIC_ROUTE_FILTER", + " address-family ipv6", + " redistribute static route-map STATIC_ROUTE_FILTER" + ] + ) + #do nothing for adding smae route second time + set_del_test( + mgr, + "SET", + ("10.1.0.0/24", { + "bfd": "false", + "nexthop": "PortChannel0001", + }), + True, + [ + ] + ) + #clear internal cache if bfd flag is true + set_del_test( + mgr, + "SET", + ("10.1.0.0/24", { + "bfd": "true", + "nexthop": "PortChannel0001", + }), + True, + [ + ] + ) + + #install the route becasue that cache was cleared above + set_del_test( + mgr, + "SET", + ("10.1.0.0/24", { + "bfd": "false", + "nexthop": "PortChannel0001", + }), + True, + [ + "ip route 10.1.0.0/24 PortChannel0001 tag 1", + "route-map STATIC_ROUTE_FILTER permit 10", + " match tag 1", + "router bgp 65100", + " address-family ipv4", + " redistribute static route-map STATIC_ROUTE_FILTER", + " address-family ipv6", + " redistribute static route-map STATIC_ROUTE_FILTER" + ] + ) + diff --git a/src/sonic-bgpcfgd/tests/test_static_rt_bfd.py b/src/sonic-bgpcfgd/tests/test_static_rt_bfd.py new file mode 100644 index 000000000000..11aa2ae678a0 --- /dev/null +++ b/src/sonic-bgpcfgd/tests/test_static_rt_bfd.py @@ -0,0 +1,681 @@ +from unittest.mock import patch +#from unittest.mock import MagicMock, patch + +from staticroutebfd.main import * +from swsscommon import swsscommon + +@patch('swsscommon.swsscommon.DBConnector.__init__') +@patch('swsscommon.swsscommon.ProducerStateTable.__init__') +@patch('swsscommon.swsscommon.Table.__init__') +def constructor(mock_db, mock_producer, mock_tbl): + mock_db.return_value = None + mock_producer.return_value = None + mock_tbl.return_value = None + + srt_bfd = StaticRouteBfd() + return srt_bfd + +def set_del_test(dut, hdlr, op, args, e_bfd_dict, e_srt_dict): + set_del_test.bfd_dict = {} + set_del_test.srt_dict = {} + + def bfd_app_set(key, data): + set_del_test.bfd_dict["set_"+key] = data.copy() + def bfd_app_del(key): + set_del_test.bfd_dict["del_"+key] = {} + def srt_app_set(key, data): + set_del_test.srt_dict["set_"+key] = data.copy() + def srt_app_del(key): + set_del_test.srt_dict["del_"+key] = {} + + def compare_dict(r, e): + if len(r) == 0 and len(e) == 0: + return True + if len(r) != len(e): + return False + for k in e: + if k not in r: + return False + if type(e[k]) is str: + r_sort = "".join(sorted([x.strip() for x in r[k].split(',')])) + e_sort = "".join(sorted([x.strip() for x in e[k].split(',')])) + if r_sort != e_sort: + return False + if type(e[k]) is dict: + ret = compare_dict(r[k], e[k]) + if not ret: + return False + return True + + dut.set_bfd_session_into_appl_db = bfd_app_set + dut.del_bfd_session_from_appl_db = bfd_app_del + dut.set_static_route_into_appl_db = srt_app_set + dut.del_static_route_from_appl_db = srt_app_del + + if op == "SET": + if hdlr == "bfd": + dut.bfd_state_set_handler(*args) + if hdlr == "srt": + dut.static_route_set_handler(*args) + if hdlr == "intf": + dut.interface_set_handler(*args) + elif op == "DEL": + if hdlr == "bfd": + dut.bfd_state_del_handler(*args) + if hdlr == "srt": + dut.static_route_del_handler(*args) + if hdlr == "intf": + dut.interface_del_handler(*args) + else: + assert False, "Wrong operation" + + assert compare_dict(set_del_test.bfd_dict, e_bfd_dict) + assert compare_dict(set_del_test.srt_dict, e_srt_dict) + +def intf_setup(dut): + set_del_test(dut, "intf", + "SET", + ("if1|192.168.1.1/24", {} + ), + {}, + {} + ) + set_del_test(dut, "intf", + "SET", + ("if2|192.168.2.1/24", {} + ), + {}, + {} + ) + set_del_test(dut, "intf", + "SET", + ("if3|192.168.3.1/24", {} + ), + {}, + {} + ) + set_del_test(dut, "intf", + "SET", + ("if1|2603:10E2:400:1::1/64",{} + ), + {}, + {} + ) + set_del_test(dut, "intf", + "SET", + ("if2|2603:10E2:400:2::1/64",{} + ), + {}, + {} + ) + set_del_test(dut, "intf", + "SET", + ("if3|2603:10E2:400:3::1/64",{} + ), + {}, + {} + ) + +def test_set_del_ipv6(): + dut = constructor() + intf_setup(dut) + + set_del_test(dut, "srt", + "SET", + ("2603:10e2:400::4/128", { + "bfd": "true", + "ifname": "if1, if2, if3", + "nexthop": "2603:10E2:400:1::2,2603:10E2:400:2::2,2603:10e2:400:3::2" + }), + { + "set_default:default:2603:10e2:400:1::2" : {'multihop': 'false', 'rx_interval': '50', 'tx_interval': '50', 'multiplier': '3', 'local_addr': '2603:10E2:400:1::1'}, + "set_default:default:2603:10e2:400:2::2" : {'multihop': 'false', 'rx_interval': '50', 'tx_interval': '50', 'multiplier': '3', 'local_addr': '2603:10E2:400:2::1'}, + "set_default:default:2603:10e2:400:3::2" : {'multihop': 'false', 'rx_interval': '50', 'tx_interval': '50', 'multiplier': '3', 'local_addr': '2603:10E2:400:3::1'} + }, + {} + ) + + set_del_test(dut, "bfd", + "SET", + ("2603:10e2:400:1::2", { + "state": "Up" + }), + {}, + {'set_default:2603:10e2:400::4/128': {'nexthop': '2603:10e2:400:1::2', 'ifname': 'if1', 'nexthop-vrf': 'default', 'expiry': 'false'}} + ) + set_del_test(dut, "bfd", + "SET", + ("2603:10e2:400:2::2", { + "state": "Up" + }), + {}, + {'set_default:2603:10e2:400::4/128': {'nexthop': '2603:10e2:400:1::2,2603:10e2:400:2::2', 'ifname': 'if1,if2', 'nexthop-vrf': 'default,default', 'expiry': 'false'}} + ) + set_del_test(dut, "bfd", + "SET", + ("2603:10e2:400:3::2", { + "state": "Up" + }), + {}, + {'set_default:2603:10e2:400::4/128': {'nexthop': '2603:10e2:400:1::2,2603:10e2:400:2::2,2603:10e2:400:3::2', 'ifname': 'if1,if2,if3', 'nexthop-vrf': 'default,default,default', 'expiry': 'false'}} + ) + + set_del_test(dut, "srt", + "DEL", + ("2603:10e2:400::4/128", { }), + { + "del_default:default:2603:10e2:400:1::2" : {}, + "del_default:default:2603:10e2:400:2::2" : {}, + "del_default:default:2603:10e2:400:3::2" : {} + }, + {'del_default:2603:10e2:400::4/128': { }} + ) + +def test_set_del(): + dut = constructor() + intf_setup(dut) + + #test #1 + set_del_test(dut, "srt", + "SET", + ("2.2.2.0/24", { + "bfd": "true", + "nexthop": "192.168.1.2 , 192.168.2.2, 192.168.3.2", + "ifname": "if1, if2, if3", + }), + { + "set_default:default:192.168.1.2" : {'multihop': 'false', 'rx_interval': '50', 'tx_interval': '50', 'multiplier': '3', 'local_addr': '192.168.1.1'}, + "set_default:default:192.168.2.2" : {'multihop': 'false', 'rx_interval': '50', 'tx_interval': '50', 'multiplier': '3', 'local_addr': '192.168.2.1'}, + "set_default:default:192.168.3.2" : {'multihop': 'false', 'rx_interval': '50', 'tx_interval': '50', 'multiplier': '3', 'local_addr': '192.168.3.1'} + }, + {} + ) + + set_del_test(dut, "bfd", + "SET", + ("192.168.1.2", { + "state": "Up" + }), + {}, + {'set_default:2.2.2.0/24': {'nexthop': '192.168.1.2', 'ifname': 'if1', 'nexthop-vrf': 'default', 'expiry': 'false'}} + ) + set_del_test(dut, "bfd", + "SET", + ("192.168.2.2", { + "state": "Up" + }), + {}, + {'set_default:2.2.2.0/24': {'nexthop': '192.168.2.2,192.168.1.2 ', 'ifname': 'if2,if1', 'nexthop-vrf': 'default,default', 'expiry': 'false'}} + ) + set_del_test(dut, "bfd", + "SET", + ("192.168.3.2", { + "state": "Up" + }), + {}, + {'set_default:2.2.2.0/24': {'nexthop': '192.168.2.2,192.168.1.2,192.168.3.2 ', 'ifname': 'if2,if1,if3', 'nexthop-vrf': 'default,default,default', 'expiry': 'false'}} + ) + + #test #2 + set_del_test(dut, "srt", + "SET", + ("2.2.2.0/24", { + "bfd": "true", + "nexthop": "192.168.1.2 , 192.168.2.2", + "ifname": "if1, if2", + }), + { + "del_default:default:192.168.3.2" : {} + }, + {'set_default:2.2.2.0/24': {'nexthop': '192.168.2.2,192.168.1.2 ', 'ifname': 'if2,if1', 'nexthop-vrf': 'default,default', 'expiry': 'false'}} + ) + + #test #3 + set_del_test(dut, "srt", + "DEL", + ("2.2.2.0/24", { + "bfd": "true", + "nexthop": "192.168.1.2 , 192.168.2.2", + "ifname": "if1, if2", + }), + { + "del_default:default:192.168.1.2" : {}, + "del_default:default:192.168.2.2" : {} + }, + {'del_default:2.2.2.0/24': {}} + ) + + # test add a non-bfd static route + set_del_test(dut, "srt", + "SET", + ("3.3.3.0/24", { + "nexthop": "192.168.1.2 , 192.168.2.2", + "ifname": "if1, if2", + }), + {}, + {} + ) + + # test delete a non-bfd static route + set_del_test(dut, "srt", + "DEL", + ("3.3.3.0/24", {}), + {}, + {} + ) + +def test_set_del_vrf(): + dut = constructor() + intf_setup(dut) + + set_del_test(dut, "srt", + "SET", + ("vrfred|2.2.2.0/24", { + "bfd": "true", + "nexthop": "192.168.1.2 , 192.168.2.2, 192.168.3.2", + "ifname": "if1, if2, if3", + "nexthop-vrf": "testvrf1, , default", + }), + { + "set_testvrf1:default:192.168.1.2" : {'multihop': 'false', 'rx_interval': '50', 'tx_interval': '50', 'multiplier': '3', 'local_addr': '192.168.1.1'}, + "set_vrfred:default:192.168.2.2" : {'multihop': 'false', 'rx_interval': '50', 'tx_interval': '50', 'multiplier': '3', 'local_addr': '192.168.2.1'}, + "set_default:default:192.168.3.2" : {'multihop': 'false', 'rx_interval': '50', 'tx_interval': '50', 'multiplier': '3', 'local_addr': '192.168.3.1'} + }, + {} + ) + + set_del_test(dut, "bfd", + "SET", + ("testvrf1|default|192.168.1.2", { + "state": "Up" + }), + {}, + {'set_vrfred:2.2.2.0/24': {'nexthop': '192.168.1.2', 'ifname': 'if1', 'nexthop-vrf': 'testvrf1', 'expiry': 'false'}} + ) + set_del_test(dut, "bfd", + "SET", + ("vrfred|default|192.168.2.2", { + "state": "Up" + }), + {}, + {'set_vrfred:2.2.2.0/24': {'nexthop': '192.168.2.2,192.168.1.2 ', 'ifname': 'if2,if1', 'nexthop-vrf': 'testvrf1,vrfred', 'expiry': 'false'}} + ) + set_del_test(dut, "bfd", + "SET", + ("default|default|192.168.3.2", { + "state": "Up" + }), + {}, + {'set_vrfred:2.2.2.0/24': {'nexthop': '192.168.2.2,192.168.1.2,192.168.3.2 ', 'ifname': 'if2,if1,if3', 'nexthop-vrf': 'testvrf1,vrfred,default', 'expiry': 'false'}} + ) + + set_del_test(dut, "srt", + "SET", + ("vrfred|2.2.2.0/24", { + "bfd": "true", + "nexthop": "192.168.1.2 , 192.168.2.2", + "ifname": "if1, if2", + "nexthop-vrf": "testvrf1,", + }), + { + "del_default:default:192.168.3.2" : {} + }, + {'set_vrfred:2.2.2.0/24': {'nexthop': '192.168.2.2,192.168.1.2 ', 'ifname': 'if2,if1', 'nexthop-vrf': 'vrfred, testvrf1', 'expiry': 'false'}} + ) + + set_del_test(dut, "srt", + "DEL", + ("vrfred|2.2.2.0/24", { }), + { + "del_testvrf1:default:192.168.1.2" : {}, + "del_vrfred:default:192.168.2.2" : {} + }, + {'del_vrfred:2.2.2.0/24': {}} + ) + +def test_bfd_del(): + dut = constructor() + intf_setup(dut) + + set_del_test(dut, "srt", + "SET", + ("2.2.2.0/24", { + "bfd": "true", + "nexthop": "192.168.1.2 , 192.168.2.2, 192.168.3.2", + "ifname": "if1, if2, if3", + }), + { + "set_default:default:192.168.1.2" : {'multihop': 'false', 'rx_interval': '50', 'tx_interval': '50', 'multiplier': '3', 'local_addr': '192.168.1.1'}, + "set_default:default:192.168.2.2" : {'multihop': 'false', 'rx_interval': '50', 'tx_interval': '50', 'multiplier': '3', 'local_addr': '192.168.2.1'}, + "set_default:default:192.168.3.2" : {'multihop': 'false', 'rx_interval': '50', 'tx_interval': '50', 'multiplier': '3', 'local_addr': '192.168.3.1'} + }, + {} + ) + + set_del_test(dut, "bfd", + "SET", + ("192.168.1.2", { + "state": "Up" + }), + {}, + {'set_default:2.2.2.0/24': {'nexthop': '192.168.1.2', 'ifname': 'if1', 'nexthop-vrf': 'default', 'expiry': 'false'}} + ) + set_del_test(dut, "bfd", + "SET", + ("192.168.2.2", { + "state": "Up" + }), + {}, + {'set_default:2.2.2.0/24': {'nexthop': '192.168.2.2,192.168.1.2 ', 'ifname': 'if2,if1', 'nexthop-vrf': 'default,default', 'expiry': 'false'}} + ) + set_del_test(dut, "bfd", + "SET", + ("192.168.3.2", { + "state": "Up" + }), + {}, + {'set_default:2.2.2.0/24': {'nexthop': '192.168.2.2,192.168.1.2,192.168.3.2 ', 'ifname': 'if2,if1,if3', 'nexthop-vrf': 'default,default,default', 'expiry': 'false'}} + ) + + #test bfd state del + set_del_test(dut, "bfd", + "DEL", + ({"192.168.2.2"}), + {}, + {'set_default:2.2.2.0/24': {'nexthop': '192.168.1.2,192.168.3.2 ', 'ifname': 'if1,if3', 'nexthop-vrf': 'default,default', 'expiry': 'false'}} + ) + +def test_set_2routes(): + dut = constructor() + intf_setup(dut) + + #test #4 + set_del_test(dut, "srt", + "SET", + ("2.2.2.0/24", { + "bfd": "true", + "nexthop": "192.168.1.2 , 192.168.2.2, 192.168.3.2", + "ifname": "if1, if2, if3", + }), + { + "set_default:default:192.168.1.2" : {'multihop': 'false', 'rx_interval': '50', 'tx_interval': '50', 'multiplier': '3', 'local_addr': '192.168.1.1'}, + "set_default:default:192.168.2.2" : {'multihop': 'false', 'rx_interval': '50', 'tx_interval': '50', 'multiplier': '3', 'local_addr': '192.168.2.1'}, + "set_default:default:192.168.3.2" : {'multihop': 'false', 'rx_interval': '50', 'tx_interval': '50', 'multiplier': '3', 'local_addr': '192.168.3.1'} + }, + {} + ) + + set_del_test(dut, "bfd", + "SET", + ("192.168.1.2", { + "state": "Up" + }), + {}, + {'set_default:2.2.2.0/24': {'nexthop': '192.168.1.2', 'ifname': 'if1', 'nexthop-vrf': 'default', 'expiry': 'false'}} + ) + set_del_test(dut, "bfd", + "SET", + ("192.168.2.2", { + "state": "Up" + }), + {}, + {'set_default:2.2.2.0/24': {'nexthop': '192.168.2.2,192.168.1.2 ', 'ifname': 'if2,if1', 'nexthop-vrf': 'default,default', 'expiry': 'false'}} + ) + set_del_test(dut, "bfd", + "SET", + ("192.168.3.2", { + "state": "Up" + }), + {}, + {'set_default:2.2.2.0/24': {'nexthop': '192.168.2.2,192.168.1.2,192.168.3.2 ', 'ifname': 'if2,if1,if3', 'nexthop-vrf': 'default,default,default', 'expiry': 'false'}} + ) + + set_del_test(dut, "srt", + "SET", + ("3.3.3.0/24", { + "bfd": "true", + "nexthop": "192.168.2.2", + "ifname": "if2", + }), + {}, + {'set_default:3.3.3.0/24': {'nexthop': '192.168.2.2', 'ifname': 'if2', 'nexthop-vrf': 'default', 'expiry': 'false'}} + ) + + #test #5 + set_del_test(dut, "bfd", + "SET", + ("192.168.2.2", { + "state": "Down" + }), + {}, + {'set_default:2.2.2.0/24': {'nexthop': '192.168.3.2,192.168.1.2 ', 'ifname': 'if3,if1', 'nexthop-vrf': 'default,default', 'expiry': 'false'}, 'del_default:3.3.3.0/24': {}} + ) + + #test #6 + set_del_test(dut, "bfd", + "SET", + ("192.168.2.2", { + "state": "Up" + }), + {}, + {'set_default:2.2.2.0/24': {'nexthop': '192.168.2.2,192.168.1.2,192.168.3.2 ', 'ifname': 'if2,if1,if3', 'nexthop-vrf': 'default,default,default', 'expiry': 'false'}, + 'set_default:3.3.3.0/24': {'nexthop': '192.168.2.2', 'ifname': 'if2', 'nexthop-vrf': 'default', 'expiry': 'false'}} + ) + +def test_set_bfd_change_hold(): + dut = constructor() + intf_setup(dut) + + #test #9 bfd: true -> false + set_del_test(dut, "srt", + "SET", + ("2.2.2.0/24", { + "bfd": "true", + "nexthop": "192.168.1.2 , 192.168.2.2, 192.168.3.2", + "ifname": "if1, if2, if3", + }), + { + "set_default:default:192.168.1.2" : {'multihop': 'false', 'rx_interval': '50', 'tx_interval': '50', 'multiplier': '3', 'local_addr': '192.168.1.1'}, + "set_default:default:192.168.2.2" : {'multihop': 'false', 'rx_interval': '50', 'tx_interval': '50', 'multiplier': '3', 'local_addr': '192.168.2.1'}, + "set_default:default:192.168.3.2" : {'multihop': 'false', 'rx_interval': '50', 'tx_interval': '50', 'multiplier': '3', 'local_addr': '192.168.3.1'} + }, + {} + ) + + set_del_test(dut, "bfd", + "SET", + ("192.168.1.2", { + "state": "Up" + }), + {}, + {'set_default:2.2.2.0/24': {'nexthop': '192.168.1.2', 'ifname': 'if1', 'nexthop-vrf': 'default', 'expiry': 'false'}} + ) + set_del_test(dut, "bfd", + "SET", + ("192.168.2.2", { + "state": "Up" + }), + {}, + {'set_default:2.2.2.0/24': {'nexthop': '192.168.2.2,192.168.1.2 ', 'ifname': 'if2,if1', 'nexthop-vrf': 'default,default', 'expiry': 'false'}} + ) + set_del_test(dut, "bfd", + "SET", + ("192.168.3.2", { + "state": "Up" + }), + {}, + {'set_default:2.2.2.0/24': {'nexthop': '192.168.2.2,192.168.1.2,192.168.3.2 ', 'ifname': 'if2,if1,if3', 'nexthop-vrf': 'default,default,default', 'expiry': 'false'}} + ) + + set_del_test(dut, "srt", + "SET", + ("2.2.2.0/24", { + "bfd": "false", + "nexthop": "192.168.1.2 , 192.168.2.2, 192.168.3.2", + "ifname": "if1, if2, if3", + }), + { + "del_default:default:192.168.1.2" : {}, + "del_default:default:192.168.2.2" : {}, + "del_default:default:192.168.3.2" : {} + }, + { + 'del_default:2.2.2.0/24': {} + } + ) + return + + #test #10 'bfd': false --> true, write original rout first + set_del_test(dut, "srt", + "SET", + ("2.2.2.0/24", { + "bfd": "true", + "nexthop": "192.168.1.2 , 192.168.2.2, 192.168.3.2", + "ifname": "if1, if2, if3", + }), + { + "set_default:default:192.168.1.2" : {'multihop': 'false', 'rx_interval': '50', 'tx_interval': '50', 'multiplier': '3', 'local_addr': '192.168.1.1'}, + "set_default:default:192.168.2.2" : {'multihop': 'false', 'rx_interval': '50', 'tx_interval': '50', 'multiplier': '3', 'local_addr': '192.168.2.1'}, + "set_default:default:192.168.3.2" : {'multihop': 'false', 'rx_interval': '50', 'tx_interval': '50', 'multiplier': '3', 'local_addr': '192.168.3.1'} + }, + {'set_default:2.2.2.0/24': {'bfd':'false', 'nexthop': '192.168.2.2,192.168.1.2,192.168.3.2 ', 'ifname': 'if2,if1,if3', 'expiry': 'false'}} + ) + + set_del_test(dut, "bfd", + "SET", + ("192.168.1.2", { + "state": "Up" + }), + {}, + {'set_default:2.2.2.0/24': {'nexthop': '192.168.1.2', 'ifname': 'if1', 'nexthop-vrf': 'default', 'expiry': 'false'}} + ) + set_del_test(dut, "bfd", + "SET", + ("192.168.2.2", { + "state": "Up" + }), + {}, + {'set_default:2.2.2.0/24': {'nexthop': '192.168.2.2,192.168.1.2 ', 'ifname': 'if2,if1', 'nexthop-vrf': 'default,default', 'expiry': 'false'}} + ) + set_del_test(dut, "bfd", + "SET", + ("192.168.3.2", { + "state": "Up" + }), + {}, + {'set_default:2.2.2.0/24': {'nexthop': '192.168.2.2,192.168.1.2,192.168.3.2 ', 'ifname': 'if2,if1,if3', 'nexthop-vrf': 'default,default,default', 'expiry': 'false'}} + ) + + +def test_set_bfd_change_no_hold(): + dut = constructor() + intf_setup(dut) + + #setup runtime "bfd"="false" condition`` + set_del_test(dut, "srt", + "SET", + ("2.2.2.0/24", { + "bfd": "true", + "nexthop": "192.168.1.2 , 192.168.2.2, 192.168.3.2", + "ifname": "if1, if2, if3", + }), + { + "set_default:default:192.168.1.2" : {'multihop': 'false', 'rx_interval': '50', 'tx_interval': '50', 'multiplier': '3', 'local_addr': '192.168.1.1'}, + "set_default:default:192.168.2.2" : {'multihop': 'false', 'rx_interval': '50', 'tx_interval': '50', 'multiplier': '3', 'local_addr': '192.168.2.1'}, + "set_default:default:192.168.3.2" : {'multihop': 'false', 'rx_interval': '50', 'tx_interval': '50', 'multiplier': '3', 'local_addr': '192.168.3.1'} + }, + {} + ) + set_del_test(dut, "bfd", + "SET", + ("192.168.1.2", { + "state": "Up" + }), + {}, + {'set_default:2.2.2.0/24': {'nexthop': '192.168.1.2', 'ifname': 'if1', 'nexthop-vrf': 'default', 'expiry': 'false'}} + ) + set_del_test(dut, "bfd", + "SET", + ("192.168.2.2", { + "state": "Up" + }), + {}, + {'set_default:2.2.2.0/24': {'nexthop': '192.168.2.2,192.168.1.2 ', 'ifname': 'if2,if1', 'nexthop-vrf': 'default,default', 'expiry': 'false'}} + ) + set_del_test(dut, "bfd", + "SET", + ("192.168.3.2", { + "state": "Up" + }), + {}, + {'set_default:2.2.2.0/24': {'nexthop': '192.168.2.2,192.168.1.2,192.168.3.2 ', 'ifname': 'if2,if1,if3', 'nexthop-vrf': 'default,default,default', 'expiry': 'false'}} + ) + set_del_test(dut, "srt", + "SET", + ("3.3.3.0/24", { + "bfd": "true", + "nexthop": "192.168.2.2", + "ifname": "if2", + }), + {}, + {'set_default:3.3.3.0/24': {'nexthop': '192.168.2.2', 'ifname': 'if2', 'nexthop-vrf': 'default', 'expiry': 'false'}} + ) + + set_del_test(dut, "srt", + "SET", + ("2.2.2.0/24", { + "bfd": "false", + "nexthop": "192.168.1.2 , 192.168.2.2, 192.168.3.2", + "ifname": "if1, if2, if3", + }), + { + "del_default:default:192.168.1.2" : {}, + "del_default:default:192.168.3.2" : {} + }, + { + 'del_default:2.2.2.0/24': {} + } + ) + + #test #10 change 'bfd': false to true, because the bfd session "default:default:192.168.2.2" is up, so add that nexthop right after "bfd" change to "true" + set_del_test(dut, "srt", + "SET", + ("2.2.2.0/24", { + "bfd": "true", + "nexthop": "192.168.1.2 , 192.168.2.2, 192.168.3.2", + "ifname": "if1, if2, if3", + }), + { + "set_default:default:192.168.1.2" : {'multihop': 'false', 'rx_interval': '50', 'tx_interval': '50', 'multiplier': '3', 'local_addr': '192.168.1.1'}, + "set_default:default:192.168.3.2" : {'multihop': 'false', 'rx_interval': '50', 'tx_interval': '50', 'multiplier': '3', 'local_addr': '192.168.3.1'} + }, + {'set_default:2.2.2.0/24': {'nexthop': '192.168.2.2', 'ifname': 'if2', 'nexthop-vrf': 'default', 'expiry': 'false'}} + ) + + set_del_test(dut, "bfd", + "SET", + ("192.168.1.2", { + "state": "Up" + }), + {}, + {'set_default:2.2.2.0/24': {'nexthop': '192.168.2.2,192.168.1.2 ', 'ifname': 'if2,if1', 'nexthop-vrf': 'default,default', 'expiry': 'false'}} + ) + set_del_test(dut, "bfd", + "SET", + ("192.168.2.2", { + "state": "Up" + }), + {}, + {} + ) + set_del_test(dut, "bfd", + "SET", + ("192.168.3.2", { + "state": "Up" + }), + {}, + {'set_default:2.2.2.0/24': {'nexthop': '192.168.2.2,192.168.1.2,192.168.3.2 ', 'ifname': 'if2,if1,if3', 'nexthop-vrf': 'default,default,default', 'expiry': 'false'}} + ) + + + diff --git a/src/sonic-config-engine/minigraph.py b/src/sonic-config-engine/minigraph.py index 13a66a53c1f1..66f7f11515ea 100644 --- a/src/sonic-config-engine/minigraph.py +++ b/src/sonic-config-engine/minigraph.py @@ -12,7 +12,7 @@ from lxml.etree import QName -from portconfig import get_port_config +from portconfig import get_port_config, get_fabric_port_config, get_fabric_monitor_config from sonic_py_common.interface import backplane_prefix # TODO: Remove this once we no longer support Python 2 @@ -1417,7 +1417,7 @@ def select_mmu_profiles(profile, platform, hwsku): # Main functions # ############################################################################### -def parse_xml(filename, platform=None, port_config_file=None, asic_name=None, hwsku_config_file=None): +def parse_xml(filename, platform=None, port_config_file=None, asic_name=None, hwsku_config_file=None, fabric_port_config_file=None ): """ Parse minigraph xml file. Keyword arguments: @@ -1426,6 +1426,7 @@ def parse_xml(filename, platform=None, port_config_file=None, asic_name=None, hw port_config_file -- port config file name asic_name -- asic name; to parse multi-asic device minigraph to generate asic specific configuration. + fabric_port_config_file -- fabric port config file name """ root = ET.parse(filename).getroot() @@ -1848,6 +1849,16 @@ def parse_xml(filename, platform=None, port_config_file=None, asic_name=None, hw results['PORT'] = ports results['CONSOLE_PORT'] = console_ports + # Get the global fabric monitoring data + fabric_monitor = get_fabric_monitor_config(hwsku=hwsku, asic_name=asic_name) + if bool( fabric_monitor ): + results[ 'FABRIC_MONITOR' ] = fabric_monitor + + # parse fabric + fabric_ports = get_fabric_port_config(hwsku=hwsku, platform=platform, fabric_port_config_file=fabric_port_config_file, asic_name=asic_name, hwsku_config_file=hwsku_config_file) + if bool( fabric_ports ): + results['FABRIC_PORT'] = fabric_ports + if port_config_file: port_set = set(ports.keys()) for (pc_name, pc_member) in list(pc_members.keys()): @@ -2173,6 +2184,19 @@ def parse_device_desc_xml(filename): return results +def parse_hostname(filename): + hostName = None + if not os.path.isfile(filename): + return None + root = ET.parse(filename).getroot() + hostname_qn = QName(ns, "Hostname") + for child in root: + if child.tag == str(hostname_qn): + hostName = child.text + break + + return hostName + def parse_asic_sub_role(filename, asic_name): if not os.path.isfile(filename): return None diff --git a/src/sonic-config-engine/portconfig.py b/src/sonic-config-engine/portconfig.py index 0c056d1cdab7..e0fb8253a797 100644 --- a/src/sonic-config-engine/portconfig.py +++ b/src/sonic-config-engine/portconfig.py @@ -105,6 +105,74 @@ def get_hwsku_file_name(hwsku=None, platform=None): return candidate return None +def get_fabric_monitor_config(hwsku=None, asic_name=None): + config_db = db_connect_configdb(asic_name) + if config_db is not None: + fabric_monitor_global = config_db.get_table("FABRIC_MONITOR") + if bool( fabric_monitor_global ): + return fabric_monitor_global + + fabric_monitor_global = {} + if asic_name is not None: + asic_id = str(get_asic_id_from_name(asic_name)) + else: + asic_id = None + fabric_monitor_config_file = device_info.get_path_to_fabric_monitor_config_file(hwsku, asic_id) + if not fabric_monitor_config_file: + return fabric_monitor_global + with open( fabric_monitor_config_file, "r" ) as openfile: + fabric_monitor_global = json.load( openfile ) + openfile.close() + + return fabric_monitor_global + + +def get_fabric_port_config(hwsku=None, platform=None, fabric_port_config_file=None, hwsku_config_file=None, asic_name=None): + config_db = db_connect_configdb(asic_name) + if config_db is not None and fabric_port_config_file is None: + port_data = config_db.get_table("FABRIC_PORT") + if bool(port_data): + ports = ast.literal_eval(json.dumps(port_data)) + return ports + + if asic_name is not None: + asic_id = str(get_asic_id_from_name(asic_name)) + else: + asic_id = None + + if not fabric_port_config_file: + fabric_port_config_file = device_info.get_path_to_fabric_port_config_file(hwsku, asic_id) + if not fabric_port_config_file: + return {} + # else parse fabric_port_config.ini + ports = {} + + # Default column definition + # ../../device/arista/x86_64-arista_7800r3_48cq2_lc/Arista-7800R3-48CQ2-C48/fabric_port_config.ini + # # name lanes isolateStatus + # Fabric0 0 False + + titles = ['name', 'lanes', 'isolateStatus'] + with open(fabric_port_config_file) as data: + for line in data: + if line.startswith('#'): + if "name" in line: + titles = line.strip('#').split() + continue; + tokens = line.split() + if len(tokens) < 2: + continue + name_index = titles.index('name') + name = tokens[name_index] + data = {} + for i, item in enumerate(tokens): + if i == name_index: + continue + data[titles[i]] = item + data.setdefault('alias', name) + ports[name] = data + return ports + def get_port_config(hwsku=None, platform=None, port_config_file=None, hwsku_config_file=None, asic_name=None): config_db = db_connect_configdb(asic_name) # If available, Read from CONFIG DB first diff --git a/src/sonic-config-engine/sonic-cfggen b/src/sonic-config-engine/sonic-cfggen index 0e53e6309325..52b6ed158949 100755 --- a/src/sonic-config-engine/sonic-cfggen +++ b/src/sonic-config-engine/sonic-cfggen @@ -29,7 +29,7 @@ import yaml from collections import OrderedDict from config_samples import generate_sample_config, get_available_config from functools import partial -from minigraph import minigraph_encoder, parse_xml, parse_device_desc_xml, parse_asic_sub_role, parse_asic_switch_type +from minigraph import minigraph_encoder, parse_xml, parse_device_desc_xml, parse_asic_sub_role, parse_asic_switch_type, parse_hostname from portconfig import get_port_config, get_breakout_mode from sonic_py_common.multi_asic import get_asic_id_from_name, get_asic_device_id from sonic_py_common import device_info @@ -365,18 +365,24 @@ def main(): if args.platform_info: asic_role = None switch_type = None + hostname = None + + if args.minigraph is not None: + hostname = parse_hostname(args.minigraph) + if asic_name is not None: if args.minigraph is not None: asic_role = parse_asic_sub_role(args.minigraph, asic_name) switch_type = parse_asic_switch_type(args.minigraph, asic_name) if ((switch_type is not None and switch_type.lower() == "chassis-packet") or - (asic_role is not None and asic_role.lower() == "backend")): - mac = device_info.get_system_mac(namespace=asic_name) + (asic_role is not None and asic_role.lower() == "backend") or + (platform == device_info.VS_PLATFORM)) : + mac = device_info.get_system_mac(namespace=asic_name, hostname=hostname) else: mac = device_info.get_system_mac() else: - mac = device_info.get_system_mac() + mac = device_info.get_system_mac(hostname=hostname) hardware_data = {'DEVICE_METADATA': {'localhost': { 'platform': platform, diff --git a/src/sonic-config-engine/tests/sample-voq-graph.xml b/src/sonic-config-engine/tests/sample-voq-graph.xml index b152d74df8a8..b6e8ff1521a0 100644 --- a/src/sonic-config-engine/tests/sample-voq-graph.xml +++ b/src/sonic-config-engine/tests/sample-voq-graph.xml @@ -619,7 +619,7 @@ 8 - Ethernet1/1 + Ethernet0 linecard-1 Asic0 40000 @@ -630,7 +630,7 @@ 8 - Ethernet1/2 + Ethernet4 linecard-1 Asic0 40000 @@ -641,7 +641,7 @@ 8 - Ethernet1/3 + Ethernet8 linecard-1 Asic0 40000 @@ -652,7 +652,7 @@ 8 - Ethernet1/4 + Ethernet12 linecard-1 Asic0 40000 @@ -675,7 +675,7 @@ 8 - Ethernet1/5 + Ethernet0 linecard-2 Asic0 40000 @@ -686,7 +686,7 @@ 8 - Ethernet1/6 + Ethernet4 linecard-2 Asic0 40000 @@ -709,7 +709,7 @@ 8 - Ethernet1/7 + Ethernet8 linecard-2 Asic1 40000 @@ -720,7 +720,7 @@ 8 - Ethernet1/8 + Ethernet12 linecard-2 Asic1 40000 diff --git a/src/sonic-config-engine/tests/sample_output/py2/frr.conf b/src/sonic-config-engine/tests/sample_output/py2/frr.conf index 7d985db93b97..2653f8fc0893 100644 --- a/src/sonic-config-engine/tests/sample_output/py2/frr.conf +++ b/src/sonic-config-engine/tests/sample_output/py2/frr.conf @@ -20,6 +20,7 @@ agentx ! ! Enable nht through default route ip nht resolve-via-default +ipv6 nht resolve-via-default ! Enable link-detect (default disabled) interface PortChannel03 link-detect diff --git a/src/sonic-config-engine/tests/sample_output/py2/t2-chassis-fe-vni-zebra.conf b/src/sonic-config-engine/tests/sample_output/py2/t2-chassis-fe-vni-zebra.conf index fb441f69f6f0..cb1d884821ef 100644 --- a/src/sonic-config-engine/tests/sample_output/py2/t2-chassis-fe-vni-zebra.conf +++ b/src/sonic-config-engine/tests/sample_output/py2/t2-chassis-fe-vni-zebra.conf @@ -21,6 +21,7 @@ vni 9000 ! ! Enable nht through default route ip nht resolve-via-default +ipv6 nht resolve-via-default ! Enable link-detect (default disabled) interface Ethernet8 link-detect diff --git a/src/sonic-config-engine/tests/sample_output/py2/t2-chassis-fe-zebra.conf b/src/sonic-config-engine/tests/sample_output/py2/t2-chassis-fe-zebra.conf index 908280e2ddfa..da4e671f1980 100644 --- a/src/sonic-config-engine/tests/sample_output/py2/t2-chassis-fe-zebra.conf +++ b/src/sonic-config-engine/tests/sample_output/py2/t2-chassis-fe-zebra.conf @@ -21,6 +21,7 @@ vni 8000 ! ! Enable nht through default route ip nht resolve-via-default +ipv6 nht resolve-via-default ! Enable link-detect (default disabled) interface Ethernet8 link-detect diff --git a/src/sonic-config-engine/tests/sample_output/py2/zebra_frr.conf b/src/sonic-config-engine/tests/sample_output/py2/zebra_frr.conf index 4024f4b340e2..cf1dda9d1737 100644 --- a/src/sonic-config-engine/tests/sample_output/py2/zebra_frr.conf +++ b/src/sonic-config-engine/tests/sample_output/py2/zebra_frr.conf @@ -18,6 +18,7 @@ log facility local4 ! ! Enable nht through default route ip nht resolve-via-default +ipv6 nht resolve-via-default ! Enable link-detect (default disabled) interface PortChannel03 link-detect diff --git a/src/sonic-config-engine/tests/sample_output/py3/frr.conf b/src/sonic-config-engine/tests/sample_output/py3/frr.conf index 43bed33c4bd0..5b7eacefe8ba 100644 --- a/src/sonic-config-engine/tests/sample_output/py3/frr.conf +++ b/src/sonic-config-engine/tests/sample_output/py3/frr.conf @@ -20,6 +20,7 @@ agentx ! ! Enable nht through default route ip nht resolve-via-default +ipv6 nht resolve-via-default ! Enable link-detect (default disabled) interface PortChannel01 link-detect diff --git a/src/sonic-config-engine/tests/sample_output/py3/t2-chassis-fe-vni-zebra.conf b/src/sonic-config-engine/tests/sample_output/py3/t2-chassis-fe-vni-zebra.conf index 7b7987650d61..e81395cf30f7 100644 --- a/src/sonic-config-engine/tests/sample_output/py3/t2-chassis-fe-vni-zebra.conf +++ b/src/sonic-config-engine/tests/sample_output/py3/t2-chassis-fe-vni-zebra.conf @@ -21,6 +21,7 @@ vni 9000 ! ! Enable nht through default route ip nht resolve-via-default +ipv6 nht resolve-via-default ! Enable link-detect (default disabled) interface Ethernet0 link-detect diff --git a/src/sonic-config-engine/tests/sample_output/py3/t2-chassis-fe-zebra.conf b/src/sonic-config-engine/tests/sample_output/py3/t2-chassis-fe-zebra.conf index fc8a8a2fb3bf..91577487993f 100644 --- a/src/sonic-config-engine/tests/sample_output/py3/t2-chassis-fe-zebra.conf +++ b/src/sonic-config-engine/tests/sample_output/py3/t2-chassis-fe-zebra.conf @@ -21,6 +21,7 @@ vni 8000 ! ! Enable nht through default route ip nht resolve-via-default +ipv6 nht resolve-via-default ! Enable link-detect (default disabled) interface Ethernet0 link-detect diff --git a/src/sonic-config-engine/tests/sample_output/py3/zebra_frr.conf b/src/sonic-config-engine/tests/sample_output/py3/zebra_frr.conf index f596c5579d3b..c364831d6628 100644 --- a/src/sonic-config-engine/tests/sample_output/py3/zebra_frr.conf +++ b/src/sonic-config-engine/tests/sample_output/py3/zebra_frr.conf @@ -18,6 +18,7 @@ log facility local4 ! ! Enable nht through default route ip nht resolve-via-default +ipv6 nht resolve-via-default ! Enable link-detect (default disabled) interface PortChannel01 link-detect diff --git a/src/sonic-config-engine/tests/test_cfggen.py b/src/sonic-config-engine/tests/test_cfggen.py index 15950cdf61a5..94985748baf2 100644 --- a/src/sonic-config-engine/tests/test_cfggen.py +++ b/src/sonic-config-engine/tests/test_cfggen.py @@ -914,16 +914,16 @@ def test_minigraph_voq_system_ports(self): json.loads(self.run_script(argument)), { "linecard-1|Asic0|Cpu0": { "core_port_index": "0", "num_voq": "8", "switch_id": "0", "speed": "1000", "core_index": "0", "system_port_id": "1" }, - "linecard-1|Asic0|Ethernet1/1": { "core_port_index": "1", "num_voq": "8", "switch_id": "0", "speed": "40000", "core_index": "0", "system_port_id": "2" }, - "linecard-1|Asic0|Ethernet1/2": { "core_port_index": "2", "num_voq": "8", "switch_id": "0", "speed": "40000", "core_index": "0", "system_port_id": "3" }, - "linecard-1|Asic0|Ethernet1/3": { "core_port_index": "3", "num_voq": "8", "switch_id": "0", "speed": "40000", "core_index": "1", "system_port_id": "4" }, - "linecard-1|Asic0|Ethernet1/4": { "core_port_index": "4", "num_voq": "8", "switch_id": "0", "speed": "40000", "core_index": "1", "system_port_id": "5" }, + "linecard-1|Asic0|Ethernet0": { "core_port_index": "1", "num_voq": "8", "switch_id": "0", "speed": "40000", "core_index": "0", "system_port_id": "2" }, + "linecard-1|Asic0|Ethernet4": { "core_port_index": "2", "num_voq": "8", "switch_id": "0", "speed": "40000", "core_index": "0", "system_port_id": "3" }, + "linecard-1|Asic0|Ethernet8": { "core_port_index": "3", "num_voq": "8", "switch_id": "0", "speed": "40000", "core_index": "1", "system_port_id": "4" }, + "linecard-1|Asic0|Ethernet12": { "core_port_index": "4", "num_voq": "8", "switch_id": "0", "speed": "40000", "core_index": "1", "system_port_id": "5" }, "linecard-2|Asic0|Cpu0": { "core_port_index": "0", "num_voq": "8", "switch_id": "2", "speed": "1000", "core_index": "0", "system_port_id": "256" }, - "linecard-2|Asic0|Ethernet1/5": { "core_port_index": "1", "num_voq": "8", "switch_id": "2", "speed": "40000", "core_index": "0", "system_port_id": "257" }, - "linecard-2|Asic0|Ethernet1/6": { "core_port_index": "2", "num_voq": "8", "switch_id": "2", "speed": "40000", "core_index": "1", "system_port_id": "258" }, + "linecard-2|Asic0|Ethernet0": { "core_port_index": "1", "num_voq": "8", "switch_id": "2", "speed": "40000", "core_index": "0", "system_port_id": "257" }, + "linecard-2|Asic0|Ethernet4": { "core_port_index": "2", "num_voq": "8", "switch_id": "2", "speed": "40000", "core_index": "1", "system_port_id": "258" }, "linecard-2|Asic1|Cpu0": { "core_port_index": "0", "num_voq": "8", "switch_id": "4", "speed": "1000", "core_index": "0", "system_port_id": "259" }, - "linecard-2|Asic1|Ethernet1/7": { "core_port_index": "1", "num_voq": "8", "switch_id": "4", "speed": "40000", "core_index": "0", "system_port_id": "260" }, - "linecard-2|Asic1|Ethernet1/8": { "core_port_index": "2", "num_voq": "8", "switch_id": "4", "speed": "40000", "core_index": "1", "system_port_id": "261" } + "linecard-2|Asic1|Ethernet8": { "core_port_index": "1", "num_voq": "8", "switch_id": "4", "speed": "40000", "core_index": "0", "system_port_id": "260" }, + "linecard-2|Asic1|Ethernet12": { "core_port_index": "2", "num_voq": "8", "switch_id": "4", "speed": "40000", "core_index": "1", "system_port_id": "261" } } ) diff --git a/src/sonic-config-engine/tests/test_cfggen_from_yang.py b/src/sonic-config-engine/tests/test_cfggen_from_yang.py index d673e1e206d7..3a72dee76e51 100644 --- a/src/sonic-config-engine/tests/test_cfggen_from_yang.py +++ b/src/sonic-config-engine/tests/test_cfggen_from_yang.py @@ -265,3 +265,26 @@ def test_vlan_crm(self): "ipv6_neighbor_threshold_type": "used" } }) + + def test_fabric_monitor_data_table(self): + arg = ["--var-json", "FABRIC_MONITOR"] + output = json.loads(self.run_script_with_yang_arg(arg)) + assert(output == {\ + "FABRIC_MONITOR_DATA": { + "monErrThreshCrcCells": "1", + "monErrThreshRxCells": "61035156", + "monPollThreshIsolation": "1", + "monPollThreshRecovery": "8" + } + }) + + def test_fabric_port_table(self): + arg = ["--var-json", "FABRIC_PORT"] + output = json.loads(self.run_script_with_yang_arg(arg)) + assert(output == {\ + "Fabric0": { + "alias": "Fabric0", + "isolateStatus": "False", + "lanes": "0" + } + }) diff --git a/src/sonic-config-engine/tests/test_yang_data.json b/src/sonic-config-engine/tests/test_yang_data.json index 3a28872317a6..f7a8dcb28bac 100644 --- a/src/sonic-config-engine/tests/test_yang_data.json +++ b/src/sonic-config-engine/tests/test_yang_data.json @@ -377,5 +377,27 @@ "ipv6_neighbor_threshold_type": "used" } } + }, + "sonic-fabric-monitor:sonic-fabric-monitor": { + "sonic-fabric-monitor:FABRIC_MONITOR": { + "FABRIC_MONITOR_DATA": { + "monErrThreshCrcCells": "1", + "monErrThreshRxCells": "61035156", + "monPollThreshIsolation": "1", + "monPollThreshRecovery": "8" + } + } + }, + "sonic-fabric-port:sonic-fabric-port": { + "sonic-fabric-port:FABRIC_PORT": { + "FABRIC_PORT_LIST": [ + { + "name": "Fabric0", + "alias": "Fabric0", + "isolateStatus": "False", + "lanes": "0" + } + ] + } } -} \ No newline at end of file +} diff --git a/src/sonic-device-data/Makefile b/src/sonic-device-data/Makefile index 2077e98f3e98..f14417cea85b 100644 --- a/src/sonic-device-data/Makefile +++ b/src/sonic-device-data/Makefile @@ -15,14 +15,89 @@ $(addprefix $(DEST)/, $(MAIN_TARGET)): $(DEST)/% : cp -r -L ../../../device/*/* ./device/ # Create hwsku for virtual switch - for d in `find -L ../../../device -maxdepth 3 -mindepth 3 -type d | grep -vE "(plugins|led-code)"`; do \ + for d in `find -L ../../../device -maxdepth 3 -mindepth 3 -type d | grep -vE "(plugins|led-code|sonic_platform)"`; do \ + # check if hwsku dir exists, if yes, then continue + if [ -d device/x86_64-kvm_x86_64-r0/$$(basename $$d) ]; then \ + continue; \ + fi; \ cp -Lr $$d device/x86_64-kvm_x86_64-r0/ ; \ + if [ -f $$(dirname $$d)/asic.conf ]; then \ + cp $$(dirname $$d)/asic.conf device/x86_64-kvm_x86_64-r0/$$(basename $$d)/asic.conf; \ + fi; \ cp ./sai.vs_profile device/x86_64-kvm_x86_64-r0/$$(basename $$d)/sai.profile; \ cp ./sai_mlnx.vs_profile device/x86_64-kvm_x86_64-r0/$$(basename $$d)/sai_mlnx.profile; \ - grep -v ^# device/x86_64-kvm_x86_64-r0/$$(basename $$d)/port_config.ini | awk '{i=i+1;print "eth"i":"$$2}' > device/x86_64-kvm_x86_64-r0/$$(basename $$d)/lanemap.ini cp ./pai.vs_profile device/x86_64-kvm_x86_64-r0/$$(basename $$d)/pai.profile; \ - grep -v ^# device/x86_64-kvm_x86_64-r0/$$(basename $$d)/port_config.ini | awk '{i=i+1;print "eth"i":"$$2}' > device/x86_64-kvm_x86_64-r0/$$(basename $$d)/lanemap.ini - + cp ./fabriclanemap_vs.ini device/x86_64-kvm_x86_64-r0/$$(basename $$d)/fabriclanemap.ini; \ + if [ -f device/x86_64-kvm_x86_64-r0/$$(basename $$d)/port_config.ini ]; then \ + last_line=$$(tail -n 1 device/x86_64-kvm_x86_64-r0/$$(basename $$d)/port_config.ini); \ + num_columns=$$(echo $$last_line | awk '{print NF}'); \ + i=0; \ + if [ -f $$(dirname $$d)/chassisdb.conf ]; then \ + i=$$(($$i+1)); \ + fi; \ + while IFS= read -r line; do \ + if ! grep -q "^#" <<< "$$line"; then \ + i=$$(($$i+1)); \ + lanes=$$(echo "$$line" | awk '{print $$2}'); \ + echo "eth$$i:$$lanes" >> device/x86_64-kvm_x86_64-r0/$$(basename $$d)/lanemap.ini; \ + if [ $$num_columns -ge 9 ]; then \ + core=$$(echo "$$line" | awk '{print $$8}'); \ + core_port=$$(echo "$$line" | awk '{print $$9}'); \ + echo "eth$$i:$$core,$$core_port" >> device/x86_64-kvm_x86_64-r0/$$(basename $$d)/coreportindexmap.ini; \ + fi; \ + fi; \ + done < device/x86_64-kvm_x86_64-r0/$$(basename $$d)/port_config.ini; \ + fi; \ + if [ -f device/x86_64-kvm_x86_64-r0/$$(basename $$d)/context_config.json ]; then \ + rm device/x86_64-kvm_x86_64-r0/$$(basename $$d)/context_config.json; \ + fi; \ + i=0; \ + if [ -f $$(dirname $$d)/chassisdb.conf ]; then \ + # Append Cpu0 Port in lanemap.ini + if [ -f device/x86_64-kvm_x86_64-r0/$$(basename $$d)/lanemap.ini ]; then \ + echo "Cpu0:999" >> device/x86_64-kvm_x86_64-r0/$$(basename $$d)/lanemap.ini; \ + fi; \ + if [ -f device/x86_64-kvm_x86_64-r0/$$(basename $$d)/coreportindexmap.ini ]; then \ + echo "Cpu0:0,0" >> device/x86_64-kvm_x86_64-r0/$$(basename $$d)/coreportindexmap.ini; \ + fi; \ + i=$$(($$i+1)); \ + fi; \ + subdirs="0 1 2"; \ + for subdir_idx in $$subdirs; do \ + subdir="device/x86_64-kvm_x86_64-r0/$$(basename $$d)/$$subdir_idx"; \ + if [ -d "$$subdir" ]; then \ + cp ./sai.vs_profile device/x86_64-kvm_x86_64-r0/$$(basename $$d)/$$(basename $$subdir)/sai.profile; \ + cp ./fabriclanemap_vs.ini device/x86_64-kvm_x86_64-r0/$$(basename $$d)/$$(basename $$subdir)/fabriclanemap.ini; \ + if [ -f device/x86_64-kvm_x86_64-r0/$$(basename $$d)/$$(basename $$subdir)/context_config.json ]; then \ + rm device/x86_64-kvm_x86_64-r0/$$(basename $$d)/$$(basename $$subdir)/context_config.json; \ + fi; \ + if [ -f device/x86_64-kvm_x86_64-r0/$$(basename $$d)/$$(basename $$subdir)/port_config.ini ]; then \ + last_line=$$(tail -n 1 device/x86_64-kvm_x86_64-r0/$$(basename $$d)/$$(basename $$subdir)/port_config.ini); \ + num_columns=$$(echo $$last_line | awk '{print NF}'); \ + while IFS= read -r line; do \ + if ! grep -q "^#" <<< "$$line"; then \ + i=$$(($$i+1)); \ + lanes=$$(echo "$$line" | awk '{print $$2}'); \ + echo "eth$$i:$$lanes" >> device/x86_64-kvm_x86_64-r0/$$(basename $$d)/$$(basename $$subdir)/lanemap.ini; \ + if [ $$num_columns -ge 9 ]; then \ + core=$$(echo "$$line" | awk '{print $$8}'); \ + core_port=$$(echo "$$line" | awk '{print $$9}'); \ + echo "eth$$i:$$core,$$core_port" >> device/x86_64-kvm_x86_64-r0/$$(basename $$d)/$$(basename $$subdir)/coreportindexmap.ini; \ + fi; \ + fi; \ + done < device/x86_64-kvm_x86_64-r0/$$(basename $$d)/$$(basename $$subdir)/port_config.ini; \ + fi; \ + if [ -f $$(dirname $$d)/chassisdb.conf ]; then \ + if [ -f device/x86_64-kvm_x86_64-r0/$$(basename $$d)/$$(basename $$subdir)/lanemap.ini ]; then \ + echo "Cpu0:999" >> device/x86_64-kvm_x86_64-r0/$$(basename $$d)/$$(basename $$subdir)/lanemap.ini; \ + i=$$(($$i+1)); \ + fi; \ + if [ -f device/x86_64-kvm_x86_64-r0/$$(basename $$d)/$$(basename $$subdir)/coreportindexmap.ini ]; then \ + echo "Cpu0:0,0" >> device/x86_64-kvm_x86_64-r0/$$(basename $$d)/$$(basename $$subdir)/coreportindexmap.ini; \ + fi; \ + fi; \ + fi; \ + done; \ done; # Build the package diff --git a/src/sonic-device-data/src/fabriclanemap_vs.ini b/src/sonic-device-data/src/fabriclanemap_vs.ini new file mode 100644 index 000000000000..20ea8fe3a720 --- /dev/null +++ b/src/sonic-device-data/src/fabriclanemap_vs.ini @@ -0,0 +1,16 @@ +fabric1:1 +fabric2:2 +fabric3:3 +fabric4:4 +fabric5:5 +fabric6:6 +fabric7:7 +fabric8:8 +fabric9:9 +fabric10:10 +fabric11:11 +fabric12:12 +fabric13:13 +fabric14:14 +fabric15:15 +fabric16:16 diff --git a/src/sonic-platform-daemons b/src/sonic-platform-daemons index a5669598ee0a..85e5b19a576e 160000 --- a/src/sonic-platform-daemons +++ b/src/sonic-platform-daemons @@ -1 +1 @@ -Subproject commit a5669598ee0a3e2a7ad4e32b0c315a29fe7e8872 +Subproject commit 85e5b19a576e269f119a27878cdb2af65d6a533a diff --git a/src/sonic-py-common/sonic_py_common/device_info.py b/src/sonic-py-common/sonic_py_common/device_info.py index 35bbdca524fa..1029ae9ce7e8 100644 --- a/src/sonic-py-common/sonic_py_common/device_info.py +++ b/src/sonic-py-common/sonic_py_common/device_info.py @@ -1,6 +1,8 @@ import glob +import hashlib import json import os +import random import re import subprocess @@ -21,6 +23,12 @@ PORT_CONFIG_FILE = "port_config.ini" PLATFORM_JSON_FILE = "platform.json" +# Fabric port configuration file names +FABRIC_MONITOR_CONFIG_FILE = "fabric_monitor_config.json" + +# Fabric port configuration file names +FABRIC_PORT_CONFIG_FILE = "fabric_port_config.ini" + # HwSKU configuration file name HWSKU_JSON_FILE = 'hwsku.json' @@ -32,6 +40,7 @@ PLATFORM_ENV_CONF_FILENAME = "platform_env.conf" FRONTEND_ASIC_SUB_ROLE = "FrontEnd" BACKEND_ASIC_SUB_ROLE = "BackEnd" +VS_PLATFORM = "x86_64-kvm_x86_64-r0" # Chassis STATE_DB keys CHASSIS_INFO_TABLE = 'CHASSIS_INFO|chassis {}' @@ -246,6 +255,113 @@ def get_path_to_hwsku_dir(): return hwsku_path +def get_path_to_fabric_monitor_config_file(hwsku=None, asic=None): + """ + Retrieves the path to the device's fabric monitor configuration file + + Args: + hwsku: a string, it is allowed to be passed in args because when loading the + initial configuration on the device, the HwSKU is not yet present in ConfigDB. + asic: a string , asic argument should be passed on multi-ASIC devices only, + it should be omitted on single-ASIC platforms. + + Returns: + A string containing the path the the device's fabric monitor configuration file + """ + + """ + This platform check is performed to make sure we return a None + in case of unit-tests within sonic-cfggen where platform is not expected to be + present because tests are not run on actual Hardware/Container. + TODO: refactor sonic-cfggen such that we can remove this check + """ + + platform = get_platform() + if not platform: + return None + + if hwsku: + try: + platform_path = get_path_to_platform_dir() + except OSError: + return None + hwsku_path = os.path.join(platform_path, hwsku) + else: + (platform_path, hwsku_path) = get_paths_to_platform_and_hwsku_dirs() + + fabric_monitor_config_candidates = [] + + # Check for 'hwsku.json' file presence first + hwsku_json_file = os.path.join(hwsku_path, HWSKU_JSON_FILE) + + # Check for 'fabric_monitor_config.json' file presence + fabric_monitor_config_candidates.append(os.path.join(hwsku_path, FABRIC_MONITOR_CONFIG_FILE)) + + for candidate in fabric_monitor_config_candidates: + if os.path.isfile(candidate): + return candidate + + return None + + +def get_path_to_fabric_port_config_file(hwsku=None, asic=None): + """ + Retrieves the path to the device's fabric port configuration file + + Args: + hwsku: a string, it is allowed to be passed in args because when loading the + initial configuration on the device, the HwSKU is not yet present in ConfigDB. + asic: a string , asic argument should be passed on multi-ASIC devices only, + it should be omitted on single-ASIC platforms. + + Returns: + A string containing the path the the device's fabric port configuration file + """ + + """ + This platform check is performed to make sure we return a None + in case of unit-tests within sonic-cfggen where platform is not expected to be + present because tests are not run on actual Hardware/Container. + TODO: refactor sonic-cfggen such that we can remove this check + """ + + platform = get_platform() + if not platform: + return None + + if hwsku: + try: + platform_path = get_path_to_platform_dir() + except OSError: + return None + hwsku_path = os.path.join(platform_path, hwsku) + else: + (platform_path, hwsku_path) = get_paths_to_platform_and_hwsku_dirs() + + fabric_port_config_candidates = [] + + # Check for 'hwsku.json' file presence first + hwsku_json_file = os.path.join(hwsku_path, HWSKU_JSON_FILE) + + # if 'hwsku.json' file is available, Check for 'platform.json' file presence, + # if 'platform.json' is available, APPEND it. Otherwise, SKIP it. + + # Check for 'fabric_port_config.ini' file presence in a few locations + if asic: + # Check if there is a file that is specific for the asic. + fabric_port_config_candidates.append(os.path.join(hwsku_path, asic, FABRIC_PORT_CONFIG_FILE)) + # Check if there is a file for the hardware type. + fabric_port_config_candidates.append(os.path.join(hwsku_path, FABRIC_PORT_CONFIG_FILE)) + else: + fabric_port_config_candidates.append(os.path.join(hwsku_path, FABRIC_PORT_CONFIG_FILE)) + + for candidate in fabric_port_config_candidates: + if os.path.isfile(candidate): + return candidate + + return None + + def get_paths_to_platform_and_hwsku_dirs(): """ Retreives the paths to the device's platform and hardware SKU data @@ -558,11 +674,40 @@ def get_all_namespaces(config_db=None): def _valid_mac_address(mac): return bool(re.match("^([0-9A-Fa-f]{2}[:-]){5}([0-9A-Fa-f]{2})$", mac)) +def _modify_mac_for_asic(mac, namespace=None): + if namespace is None: + return mac + if namespace in get_namespaces(): + asic_id = namespace[-1] + mac = mac[:-1] + asic_id + return mac -def get_system_mac(namespace=None): +def generate_mac_for_vs(hostname, namespace): + mac = None + if hostname is None: + # return random mac address randomize each byte of mac address b/w 0-255 + mac = "22:%02x:%02x:%02x:%02x:%02x" % (random.randint(0, 255), random.randint(0, 255), random.randint(0, 255), random.randint(0, 255), random.randint(0, 255)) + else: + # Calculate the SHA-256 hash of the UTF-8 encoded hostname + hash_value = hashlib.sha256(hostname.encode('utf-8')).digest() + + # Extract the last 6 bytes (48 bits) from the hash value + mac_bytes = hash_value[-6:] + # Set the first octet to 02 to indicate a locally administered MAC address + mac_bytes = bytearray([0x22, mac_bytes[1], mac_bytes[2], mac_bytes[3], mac_bytes[4], mac_bytes[5]]) + # Format the MAC address with colons + mac = ':'.join('{:02x}'.format(byte) for byte in mac_bytes) + + return _modify_mac_for_asic(mac, namespace) + +def get_system_mac(namespace=None, hostname=None): version_info = get_sonic_version_info() + platform = get_platform() + + if platform == VS_PLATFORM: + return generate_mac_for_vs(hostname, namespace) - if (version_info['asic_type'] == 'mellanox'): + elif (version_info['asic_type'] == 'mellanox'): # With Mellanox ONIE release(2019.05-5.2.0012) and above # "onie_base_mac" was added to /host/machine.conf: # onie_base_mac=e4:1d:2d:44:5e:80 @@ -579,7 +724,6 @@ def get_system_mac(namespace=None): hw_mac_entry_cmds = [ "sudo decode-syseeprom -m" ] elif (version_info['asic_type'] == 'marvell'): # Try valid mac in eeprom, else fetch it from eth0 - platform = get_platform() machine_key = "onie_machine" machine_vars = get_machine_info() if machine_vars is not None and machine_key in machine_vars: @@ -590,7 +734,6 @@ def get_system_mac(namespace=None): hw_mac_entry_cmds = ["sudo decode-syseeprom -m", profile_cmd, "ip link show eth0 | grep ether | awk '{print $2}'"] elif (version_info['asic_type'] == 'cisco-8000'): # Try to get valid MAC from profile.ini first, else fetch it from syseeprom or eth0 - platform = get_platform() if namespace is not None: profile_cmd = 'cat ' + HOST_DEVICE_PATH + '/' + platform + '/profile.ini | grep ' + namespace + 'switchMacAddress | cut -f2 -d=' else: diff --git a/src/sonic-utilities b/src/sonic-utilities index 724178c69098..af721c971363 160000 --- a/src/sonic-utilities +++ b/src/sonic-utilities @@ -1 +1 @@ -Subproject commit 724178c69098c66909a7e07621e470f0493b4e1e +Subproject commit af721c971363ca15e45736a1ee2c1536a1a88209 diff --git a/src/sonic-yang-models/doc/Configuration.md b/src/sonic-yang-models/doc/Configuration.md index a5db1b0b1929..931094cd1541 100644 --- a/src/sonic-yang-models/doc/Configuration.md +++ b/src/sonic-yang-models/doc/Configuration.md @@ -20,6 +20,7 @@ Table of Contents * [Cable length](#cable-length) * [Chassis module](#chassis-module) * [COPP_TABLE](#copp_table) + * [Console](#console) * [CRM](#crm) * [Data Plane L3 Interfaces](#data-plane-l3-interfaces) * [DEFAULT_LOSSLESS_BUFFER_PARAMETER](#DEFAULT_LOSSLESS_BUFFER_PARAMETER) @@ -27,6 +28,8 @@ Table of Contents * [Device neighbor metada](#device-neighbor-metada) * [DHCP_RELAY](#dhcp_relay) * [DSCP_TO_TC_MAP](#dscp_to_tc_map) + * [FABRIC_MONITOR](#fabric-monitor) + * [FABRIC_PORT](#fabric-port) * [FLEX_COUNTER_TABLE](#flex_counter_table) * [IPv6 Link-local] (#ipv6-link-local) * [KDUMP](#kdump) @@ -49,7 +52,9 @@ Table of Contents * [Scheduler](#scheduler) * [Port QoS Map](#port-qos-map) * [Queue](#queue) - * [Sflow](#sflow) + * [Sflow](#sflow) + * [Restapi](#restapi) + * [System Port](#system-port) * [Tacplus Server](#tacplus-server) * [TC to Priority group map](#tc-to-priority-group-map) * [TC to Queue map](#tc-to-queue-map) @@ -712,6 +717,29 @@ It currently allows user to administratively bring down a line-card or fabric-ca } ``` +### Console + +``` +{ +"CONSOLE_PORT": { + "1": { + "baud_rate": "115200", + "flow_control": "0", + "remote_device": "host-1" + }, + "2": { + "baud_rate": "9600", + "flow_control": "1" + } + }, +"CONSOLE_SWITCH": { + "console_mgmt": { + "enabled": "yes" + } + } +} +``` + ### CRM ``` @@ -817,6 +845,8 @@ instance is supported in SONiC. { "DEVICE_METADATA": { "localhost": { + "asic_id": "06:00.0", + "asic_name": "asic0", "hwsku": "Force10-S6100", "default_bgp_status": "up", "docker_routing_config_mode": "unified", @@ -898,6 +928,37 @@ instance is supported in SONiC. ``` +### FABRIC_MONITOR +``` +{ +"FABRIC_MONITOR": { + "FABRIC_MONITOR_DATA": { + "monErrThreshCrcCells": "1", + "monErrThreshRxCells": "61035156", + "monPollThreshIsolation": "1", + "monPollThreshRecovery": "8" + } + } +} +``` + +### FABRIC_PORT +``` +{ +"FABRIC_PORT": { + "Fabric0": { + "alias": "Fabric0", + "isolateStatus": "False", + "lanes": "0" + }, + "Fabric1": { + "alias": "Fabric1", + "isolateStatus": "False", + "lanes": "1" + } + } +} +``` ### MPLS_TC_TO_TC_MAP ``` @@ -1316,7 +1377,10 @@ optional attributes. "speed": "40000", "link_training": "off", "laser_freq": "191300", - "tx_power": "-27.3" + "tx_power": "-27.3", + "core_id": "1", + "core_port_id": "1", + "num_voq": "8" }, "Ethernet1": { "index": "1", @@ -1328,7 +1392,10 @@ optional attributes. "speed": "40000", "link_training": "on", "laser_freq": "191300", - "tx_power": "-27.3" + "tx_power": "-27.3", + "core_id": "0", + "core_port_id": "14", + "num_voq": "8" }, "Ethernet63": { "index": "63", @@ -1338,7 +1405,10 @@ optional attributes. "alias": "fortyGigE1/4/16", "speed": "40000", "laser_freq": "191300", - "tx_power": "-27.3" + "tx_power": "-27.3", + "core_id": "0", + "core_port_id": "15", + "num_voq": "8" } } } @@ -1476,6 +1546,25 @@ name as object key and member list as attribute. } ``` +### Restapi +``` +{ +"RESTAPI": { + "certs": { + "ca_crt": "/etc/sonic/credentials/ame_root.pem", + "server_key": "/etc/sonic/credentials/restapiserver.key", + "server_crt": "/etc/sonic/credentials/restapiserver.crt", + "client_crt_cname": "client.sonic.net" + }, + "config": { + "client_auth": "true", + "log_level": "trace", + "allow_insecure": "false" + } +} + +``` + ### Sflow The below are the tables and their schema for SFLOW feature @@ -1539,6 +1628,49 @@ Container side configuration: } ``` +### System Port +Every port on the system requires a global representation, known as a System Port, +and is listed in this table. + +``` +{ +"SYSTEM_PORT": { + "host227-4|asic0|Ethernet0": { + "core_index": "1", + "core_port_index": "1", + "num_voq": "8", + "speed": "100000", + "switch_id": "0", + "system_port_id": "1" + }, + "host227-4|asic0|Ethernet4": { + "core_index": "1", + "core_port_index": "2", + "num_voq": "8", + "speed": "100000", + "switch_id": "0", + "system_port_id": "2" + }, + "host227-5|asic0|Ethernet0": { + "core_index": "1", + "core_port_index": "1", + "num_voq": "8", + "speed": "100000", + "switch_id": "4", + "system_port_id": "80" + }, + "host227-5|asic0|Ethernet4": { + "core_index": "1", + "core_port_index": "2", + "num_voq": "8", + "speed": "100000", + "switch_id": "4", + "system_port_id": "81" + } + } +} +``` + ### Tacplus Server ``` diff --git a/src/sonic-yang-models/setup.py b/src/sonic-yang-models/setup.py index 0c478ffe4b04..da8214387060 100644 --- a/src/sonic-yang-models/setup.py +++ b/src/sonic-yang-models/setup.py @@ -99,6 +99,7 @@ def run(self): './yang-models/sonic-cable-length.yang', './yang-models/sonic-chassis-module.yang', './yang-models/sonic-copp.yang', + './yang-models/sonic-console.yang', './yang-models/sonic-crm.yang', './yang-models/sonic-default-lossless-buffer-parameter.yang', './yang-models/sonic-device_metadata.yang', @@ -106,6 +107,8 @@ def run(self): './yang-models/sonic-device_neighbor_metadata.yang', './yang-models/sonic-dhcpv6-relay.yang', './yang-models/sonic-extension.yang', + './yang-models/sonic-fabric-monitor.yang', + './yang-models/sonic-fabric-port.yang', './yang-models/sonic-flex_counter.yang', './yang-models/sonic-feature.yang', './yang-models/sonic-system-defaults.yang', @@ -128,6 +131,7 @@ def run(self): './yang-models/sonic-policer.yang', './yang-models/sonic-portchannel.yang', './yang-models/sonic-pfcwd.yang', + './yang-models/sonic-restapi.yang', './yang-models/sonic-route-common.yang', './yang-models/sonic-route-map.yang', './yang-models/sonic-routing-policy-sets.yang', @@ -161,6 +165,7 @@ def run(self): './yang-models/sonic-pfc-priority-queue-map.yang', './yang-models/sonic-pfc-priority-priority-group-map.yang', './yang-models/sonic-port-qos-map.yang', + './yang-models/sonic-system-port.yang', './yang-models/sonic-macsec.yang']), ('cvlyang-models', ['./cvlyang-models/sonic-acl.yang', './cvlyang-models/sonic-bgp-common.yang', @@ -177,6 +182,8 @@ def run(self): './cvlyang-models/sonic-device_neighbor.yang', './cvlyang-models/sonic-device_neighbor_metadata.yang', './cvlyang-models/sonic-extension.yang', + './cvlyang-models/sonic-fabric-monitor.yang', + './cvlyang-models/sonic-fabric-port.yang', './cvlyang-models/sonic-flex_counter.yang', './cvlyang-models/sonic-feature.yang', './cvlyang-models/sonic-system-defaults.yang', @@ -218,6 +225,7 @@ def run(self): './cvlyang-models/sonic-pfc-priority-queue-map.yang', './cvlyang-models/sonic-pfc-priority-priority-group-map.yang', './cvlyang-models/sonic-port-qos-map.yang', + './cvlyang-models/sonic-system-port.yang', './cvlyang-models/sonic-macsec.yang']), ], zip_safe=False, diff --git a/src/sonic-yang-models/tests/files/sample_config_db.json b/src/sonic-yang-models/tests/files/sample_config_db.json index b2faa0d51cbb..ab53f41dbf53 100644 --- a/src/sonic-yang-models/tests/files/sample_config_db.json +++ b/src/sonic-yang-models/tests/files/sample_config_db.json @@ -305,6 +305,7 @@ "DEVICE_METADATA": { "localhost": { "type": "ToRRouter", + "asic_id": "06:00.0", "mac": "00:11:22:33:dd:5a", "hostname": "asw.dc", "bgp_asn": "64850", @@ -314,7 +315,6 @@ "region": "usfoo", "asic_name": "Asic0", "switch_id": "2", - "switch_type": "voq", "max_cores": "8", "sub_role": "FrontEnd", "dhcp_server": "disabled", @@ -449,6 +449,9 @@ "PORT": { "Ethernet0": { "alias": "Eth1/1", + "core_id": "1", + "core_port_id": "1", + "num_voq": "8", "lanes": "65", "description": "", "speed": "11100", @@ -464,6 +467,9 @@ }, "Ethernet1": { "alias": "Eth1/2", + "core_id": "1", + "core_port_id": "1", + "num_voq": "8", "lanes": "66", "description": "", "speed": "11100", @@ -478,6 +484,9 @@ }, "Ethernet2": { "alias": "Eth1/3", + "core_id": "1", + "core_port_id": "1", + "num_voq": "8", "lanes": "67", "description": "", "speed": "11100", @@ -1102,6 +1111,39 @@ "port": "50051" } }, + "FABRIC_MONITOR": { + "FABRIC_MONITOR_DATA": { + "monErrThreshCrcCells": "1", + "monErrThreshRxCells": "61035156", + "monPollThreshIsolation": "1", + "monPollThreshRecovery": "8" + } + }, + "FABRIC_PORT": { + "Fabric0": { + "alias": "Fabric0", + "isolateStatus": "False", + "lanes": "0" + }, + "Fabric1": { + "alias": "Fabric1", + "isolateStatus": "False", + "lanes": "1" + } + }, + "RESTAPI": { + "certs": { + "ca_crt": "/etc/sonic/credentials/ame_root.pem", + "server_key": "/etc/sonic/credentials/restapiserver.key", + "server_crt": "/etc/sonic/credentials/restapiserver.crt", + "client_crt_cname": "client.sonic.net" + }, + "config": { + "client_auth": "true", + "log_level": "trace", + "allow_insecure": "false" + } + }, "FLEX_COUNTER_TABLE": { "PFCWD": { "FLEX_COUNTER_STATUS": "enable" @@ -1247,6 +1289,80 @@ "login": "local" } }, + "SYSTEM_PORT": { + "host227-4|asic0|Cpu0": { + "core_index": "0", + "core_port_index": "0", + "num_voq": "8", + "speed": "10000", + "switch_id": "0", + "system_port_id": "1" + }, + "host227-4|asic0|Ethernet0": { + "core_index": "1", + "core_port_index": "1", + "num_voq": "8", + "speed": "100000", + "switch_id": "0", + "system_port_id": "2" + }, + "host227-4|asic0|Ethernet4": { + "core_index": "1", + "core_port_index": "2", + "num_voq": "8", + "speed": "100000", + "switch_id": "0", + "system_port_id": "3" + }, + "host227-4|asic1|Cpu0": { + "core_index": "0", + "core_port_index": "0", + "num_voq": "8", + "speed": "10000", + "switch_id": "0", + "system_port_id": "41" + }, + "host227-4|asic1|Ethernet8": { + "core_index": "0", + "core_port_index": "1", + "num_voq": "8", + "speed": "100000", + "switch_id": "2", + "system_port_id": "42" + }, + "host227-4|asic1|Ethernet12": { + "core_index": "0", + "core_port_index": "2", + "num_voq": "8", + "speed": "100000", + "switch_id": "2", + "system_port_id": "43" + }, + "host227-5|asic0|Cpu0": { + "core_index": "0", + "core_port_index": "0", + "num_voq": "8", + "speed": "10000", + "switch_id": "0", + "system_port_id": "81" + }, + "host227-5|asic0|Ethernet0": { + "core_index": "1", + "core_port_index": "1", + "num_voq": "8", + "speed": "100000", + "switch_id": "4", + "system_port_id": "82" + }, + "host227-5|asic0|Ethernet4": { + "core_index": "1", + "core_port_index": "2", + "num_voq": "8", + "speed": "100000", + "switch_id": "4", + "system_port_id": "83" + } + }, "TACPLUS": { "global": { "auth_type": "pap", @@ -2016,6 +2132,22 @@ "default_dynamic_th": "0", "over_subscribe_ratio": "0" } + }, + "CONSOLE_PORT": { + "1": { + "baud_rate": "115200", + "flow_control": "0", + "remote_device": "host-1" + }, + "2": { + "baud_rate": "9600", + "flow_control": "1" + } + }, + "CONSOLE_SWITCH": { + "console_mgmt": { + "enabled": "yes" + } } }, "SAMPLE_CONFIG_DB_UNKNOWN": { diff --git a/src/sonic-yang-models/tests/yang_model_tests/tests/buffer_pool.json b/src/sonic-yang-models/tests/yang_model_tests/tests/buffer_pool.json index 907fa9101ab3..974ece55dd79 100644 --- a/src/sonic-yang-models/tests/yang_model_tests/tests/buffer_pool.json +++ b/src/sonic-yang-models/tests/yang_model_tests/tests/buffer_pool.json @@ -5,6 +5,9 @@ "BUFFER_POOL_CORRECT_TYPE_EGRESS_VALUE": { "desc": "BUFFER_POOL_CORRECT_TYPE_EGRESS_VALUE no failure." }, + "BUFFER_POOL_CORRECT_TYPE_BOTH_VALUE": { + "desc": "BUFFER_POOL_CORRECT_TYPE_BOTH_VALUE no failure." + }, "BUFFER_POOL_WRONG_TYPE_VALUE": { "desc": "BUFFER_POOL_WRONG_TYPE_VALUE pattern failure.", "eStr": "wrong" diff --git a/src/sonic-yang-models/tests/yang_model_tests/tests/buffer_queue.json b/src/sonic-yang-models/tests/yang_model_tests/tests/buffer_queue.json index d6e05eeafb4b..32619dcd5fb0 100644 --- a/src/sonic-yang-models/tests/yang_model_tests/tests/buffer_queue.json +++ b/src/sonic-yang-models/tests/yang_model_tests/tests/buffer_queue.json @@ -13,5 +13,8 @@ "BUFFER_QUEUE_WRONG_PORT_VALUE": { "desc": "BUFFER_QUEUE_WRONG_PORT_VALUE pattern failure", "eStr": "wrong" + }, + "VOQ_BUFFER_QUEUE_CONFIG": { + "desc": "VOQ_BUFFER_QUEUE_CONFIG has no failure" } } diff --git a/src/sonic-yang-models/tests/yang_model_tests/tests/console.json b/src/sonic-yang-models/tests/yang_model_tests/tests/console.json new file mode 100644 index 000000000000..cd305e4a2086 --- /dev/null +++ b/src/sonic-yang-models/tests/yang_model_tests/tests/console.json @@ -0,0 +1,40 @@ +{ + "CONSOLE_DISABLED": { + "desc": "Verifying CONSOLE_SWITCH configuration." + }, + "CONSOLE_DEFAULT_CONSOLE_MGMT": { + "desc": "CONSOLE_SWITCH default value for console_mgmt enabled field.", + "eStrKey": "Verify", + "verify": { + "xpath": "/sonic-console:sonic-console/CONSOLE_SWITCH/console_mgmt/enabled", + "key": "sonic-console:enabled", + "value": "no" + } + }, + "CONSOLE_DISABLED_INCORRECT_PATTERN": { + "desc": "CONSOLE_SWITCH configuration pattern failure.", + "eStrKey": "Pattern" + }, + "CONSOLE_PORT_DEFAULT_FLOW_CONTROL": { + "desc": "CONSOLE_PORT default value for flow_control field.", + "eStrKey": "Verify", + "verify": { + "xpath": "/sonic-console:sonic-console/CONSOLE_PORT/CONSOLE_PORT_LIST[name='1']/flow_control", + "key": "sonic-console:flow_control", + "value": "0" + } + }, + "CONSOLE_PORT_INVALID_NAME": { + "desc": "CONSOLE_PORT invalid name failure.", + "eStrKey": "InvalidValue", + "eStr": ["name"] + }, + "CONSOLE_PORT_INVALID_BAUD": { + "desc": "CONSOLE_PORT invalid baud failure.", + "eStrKey": "InvalidValue", + "eStr": ["baud"] + }, + "CONSOLE_PORT_VALID": { + "desc": "Verifying CONSOLE_PORT configuration no failure." + } +} diff --git a/src/sonic-yang-models/tests/yang_model_tests/tests/device_metadata.json b/src/sonic-yang-models/tests/yang_model_tests/tests/device_metadata.json index d2779804d594..8c96fdc4558f 100644 --- a/src/sonic-yang-models/tests/yang_model_tests/tests/device_metadata.json +++ b/src/sonic-yang-models/tests/yang_model_tests/tests/device_metadata.json @@ -2,6 +2,12 @@ "DEV_META_DEV_NEIGH_VERSION_TABLE": { "desc": "DEVICE_METADATA DEVICE_NEIGHBOR VERSION TABLE." }, + "DEVICE_METADATA_ASIC_ID": { + "desc": "DEVICE_METADATA ASIC ID." + }, + "DEVICE_METADATA_ASIC_NAME": { + "desc": "DEVICE_METADATA ASIC NAME." + }, "DEVICE_METADATA_DEFAULT_BGP_STATUS": { "desc": "DEVICE_METADATA DEFAULT VALUE FOR BGP_STATUS FIELD.", "eStrKey" : "Verify", diff --git a/src/sonic-yang-models/tests/yang_model_tests/tests/fabric_monitor_data.json b/src/sonic-yang-models/tests/yang_model_tests/tests/fabric_monitor_data.json new file mode 100644 index 000000000000..0bff2427c971 --- /dev/null +++ b/src/sonic-yang-models/tests/yang_model_tests/tests/fabric_monitor_data.json @@ -0,0 +1,5 @@ +{ + "FABRIC_MONITOR_POSITIVE_CONFIG": { + "desc": "Configure FABRIC_MONITOR_DATA no failure." + } +} diff --git a/src/sonic-yang-models/tests/yang_model_tests/tests/fabric_port.json b/src/sonic-yang-models/tests/yang_model_tests/tests/fabric_port.json new file mode 100644 index 000000000000..8c8db3ca1655 --- /dev/null +++ b/src/sonic-yang-models/tests/yang_model_tests/tests/fabric_port.json @@ -0,0 +1,5 @@ +{ + "FABRIC_PORT_POSITIVE_CONFIG": { + "desc": "Configure FABRIC_PORT no failure." + } +} diff --git a/src/sonic-yang-models/tests/yang_model_tests/tests/port.json b/src/sonic-yang-models/tests/yang_model_tests/tests/port.json index c8a3ce102c25..e93df4e6af93 100644 --- a/src/sonic-yang-models/tests/yang_model_tests/tests/port.json +++ b/src/sonic-yang-models/tests/yang_model_tests/tests/port.json @@ -49,6 +49,15 @@ "PORT_VALID_TYPE_TEST": { "desc": "PORT_VALID_TYPE_TEST no failure." }, + "PORT_COREID_TYPE_TEST": { + "desc": "PORT_COREID_TYPE_TEST no failure." + }, + "PORT_COREPORTID_TYPE_TEST": { + "desc": "PORT_COREPORTID_TYPE_TEST no failure." + }, + "PORT_NUMVOQ_TYPE_TEST": { + "desc": "PORT_NUMVOQ_TYPE_TEST no failure." + }, "PORT_INVALID_TYPE_TEST": { "desc": "PORT_INVALID_TYPE_TEST InvalidValue condition failure.", "eStrKey" : "InvalidValue", diff --git a/src/sonic-yang-models/tests/yang_model_tests/tests/qos.json b/src/sonic-yang-models/tests/yang_model_tests/tests/qos.json index 189cec177a2d..3704e5ba245b 100644 --- a/src/sonic-yang-models/tests/yang_model_tests/tests/qos.json +++ b/src/sonic-yang-models/tests/yang_model_tests/tests/qos.json @@ -85,5 +85,8 @@ "QUEUE_WRED_NOT_EXIST": { "desc": "Referring non-existing WRED table.", "eStrKey" : "LeafRef" + }, + "VOQ_QUEUE_CONFIG": { + "desc": "Attach scheduler and wred profiles to VOQ." } } diff --git a/src/sonic-yang-models/tests/yang_model_tests/tests/restapi.json b/src/sonic-yang-models/tests/yang_model_tests/tests/restapi.json new file mode 100644 index 000000000000..42ce64ba330f --- /dev/null +++ b/src/sonic-yang-models/tests/yang_model_tests/tests/restapi.json @@ -0,0 +1,16 @@ +{ + "RESTAPI_TABLE_WITH_INCORRECT_CERT": { + "desc": "RESTAPI TABLE_WITH_INCORRECT_CERT failure.", + "eStr": ["Value", "does not satisfy the constraint"] + }, + "RESTAPI_TABLE_WITH_INCORRECT_CLIENT": { + "desc": "RESTAPI TABLE_WITH_INCORRECT_CLIENT failure.", + "eStr": ["Value", "does not satisfy the constraint"] + }, + "RESTAPI_TABLE_WITH_VALID_CONFIG": { + "desc": "RESTAPI TABLE WITH VALID CONFIG." + }, + "RESTAPI_TABLE_WITH_MULTIPLE_CERTS": { + "desc": "RESTAPI TABLE WITH MULTIPLE CERTS." + } +} diff --git a/src/sonic-yang-models/tests/yang_model_tests/tests/system_port.json b/src/sonic-yang-models/tests/yang_model_tests/tests/system_port.json new file mode 100644 index 000000000000..727373ade25a --- /dev/null +++ b/src/sonic-yang-models/tests/yang_model_tests/tests/system_port.json @@ -0,0 +1,9 @@ +{ + "SYSTEM_PORT_POSITIVE_CONFIG": { + "desc": "Configure SYSTEM_PORT positive config." + }, + "SYSTEM_PORT_WRONG_SPEED_PATTERN": { + "desc": "Configure SYSTEM_PORT wrong speed.", + "eStr": ["pattern", "does not satisfy"] + } +} diff --git a/src/sonic-yang-models/tests/yang_model_tests/tests_config/buffer_pool.json b/src/sonic-yang-models/tests/yang_model_tests/tests_config/buffer_pool.json index 8a0005305faa..a2a4d6fc1f0e 100644 --- a/src/sonic-yang-models/tests/yang_model_tests/tests_config/buffer_pool.json +++ b/src/sonic-yang-models/tests/yang_model_tests/tests_config/buffer_pool.json @@ -27,6 +27,20 @@ } } }, + "BUFFER_POOL_CORRECT_TYPE_BOTH_VALUE": { + "sonic-buffer-pool:sonic-buffer-pool": { + "sonic-buffer-pool:BUFFER_POOL": { + "BUFFER_POOL_LIST": [ + { + "name": "Ethernet4", + "mode": "static", + "size": "12766208", + "type": "both" + } + ] + } + } + }, "BUFFER_POOL_WRONG_TYPE_VALUE": { "sonic-buffer-pool:sonic-buffer-pool": { "sonic-buffer-pool:BUFFER_POOL": { diff --git a/src/sonic-yang-models/tests/yang_model_tests/tests_config/buffer_queue.json b/src/sonic-yang-models/tests/yang_model_tests/tests_config/buffer_queue.json index e737c129682e..91a39a89e3a5 100644 --- a/src/sonic-yang-models/tests/yang_model_tests/tests_config/buffer_queue.json +++ b/src/sonic-yang-models/tests/yang_model_tests/tests_config/buffer_queue.json @@ -3,51 +3,51 @@ "sonic-port:sonic-port": { "sonic-port:PORT": { "PORT_LIST": [ - { - "admin_status": "up", - "alias": "eth0", - "description": "Ethernet0", - "lanes": "65", - "mtu": "9000", - "name": "Ethernet4", - "tpid": "0x8100", - "speed": "25000" - } + { + "admin_status": "up", + "alias": "eth0", + "description": "Ethernet0", + "lanes": "65", + "mtu": "9000", + "name": "Ethernet4", + "tpid": "0x8100", + "speed": "25000" + } ] } }, "sonic-buffer-pool:sonic-buffer-pool": { "sonic-buffer-pool:BUFFER_POOL": { "BUFFER_POOL_LIST": [ - { - "name": "egress_lossless_pool", - "mode": "static", - "size": "12766208", - "type": "ingress" - } + { + "name": "egress_lossless_pool", + "mode": "static", + "size": "12766208", + "type": "ingress" + } ] } }, "sonic-buffer-profile:sonic-buffer-profile": { "sonic-buffer-profile:BUFFER_PROFILE": { "BUFFER_PROFILE_LIST": [ - { - "name": "lossless_buffer_profile", - "size": 1518, - "dynamic_th": "2", - "pool": "egress_lossless_pool" - } + { + "name": "lossless_buffer_profile", + "size": 1518, + "dynamic_th": "2", + "pool": "egress_lossless_pool" + } ] } }, "sonic-buffer-queue:sonic-buffer-queue": { "sonic-buffer-queue:BUFFER_QUEUE": { "BUFFER_QUEUE_LIST": [ - { - "port": "Ethernet4", - "qindex": "15", - "profile": "lossless_buffer_profile" - } + { + "port": "Ethernet4", + "qindex": "15", + "profile": "lossless_buffer_profile" + } ] } } @@ -56,50 +56,50 @@ "sonic-port:sonic-port": { "sonic-port:PORT": { "PORT_LIST": [ - { - "admin_status": "up", - "alias": "eth0", - "description": "Ethernet0", - "lanes": "65", - "mtu": "9000", - "name": "Ethernet4", - "tpid": "0x8100", - "speed": "25000" - } + { + "admin_status": "up", + "alias": "eth0", + "description": "Ethernet0", + "lanes": "65", + "mtu": "9000", + "name": "Ethernet4", + "tpid": "0x8100", + "speed": "25000" + } ] } }, "sonic-buffer-pool:sonic-buffer-pool": { "sonic-buffer-pool:BUFFER_POOL": { "BUFFER_POOL_LIST": [ - { - "name": "egress_lossless_pool", - "mode": "static", - "size": "12766208", - "type": "ingress" - } + { + "name": "egress_lossless_pool", + "mode": "static", + "size": "12766208", + "type": "ingress" + } ] } }, "sonic-buffer-profile:sonic-buffer-profile": { "sonic-buffer-profile:BUFFER_PROFILE": { "BUFFER_PROFILE_LIST": [ - { - "name": "lossless_buffer_profile", - "size": "1518", - "pool": "egress_lossless_pool" - } + { + "name": "lossless_buffer_profile", + "size": "1518", + "pool": "egress_lossless_pool" + } ] } }, "sonic-buffer-queue:sonic-buffer-queue": { "sonic-buffer-queue:BUFFER_QUEUE": { "BUFFER_QUEUE_LIST": [ - { - "port": "Ethernet4", - "qindex": "3", - "profile": "wrong" - } + { + "port": "Ethernet4", + "qindex": "3", + "profile": "wrong" + } ] } } @@ -108,50 +108,50 @@ "sonic-port:sonic-port": { "sonic-port:PORT": { "PORT_LIST": [ - { - "admin_status": "up", - "alias": "eth0", - "description": "Ethernet0", - "lanes": "65", - "mtu": "9000", - "name": "Ethernet4", - "tpid": "0x8100", - "speed": "25000" - } + { + "admin_status": "up", + "alias": "eth0", + "description": "Ethernet0", + "lanes": "65", + "mtu": "9000", + "name": "Ethernet4", + "tpid": "0x8100", + "speed": "25000" + } ] } }, "sonic-buffer-pool:sonic-buffer-pool": { "sonic-buffer-pool:BUFFER_POOL": { "BUFFER_POOL_LIST": [ - { - "name": "egress_lossless_pool", - "mode": "static", - "size": "12766208", - "type": "ingress" - } + { + "name": "egress_lossless_pool", + "mode": "static", + "size": "12766208", + "type": "ingress" + } ] } }, "sonic-buffer-profile:sonic-buffer-profile": { "sonic-buffer-profile:BUFFER_PROFILE": { "BUFFER_PROFILE_LIST": [ - { - "name": "lossless_buffer_profile", - "size": "1518", - "pool": "egress_lossless_pool" - } + { + "name": "lossless_buffer_profile", + "size": "1518", + "pool": "egress_lossless_pool" + } ] } }, "sonic-buffer-queue:sonic-buffer-queue": { "sonic-buffer-queue:BUFFER_QUEUE": { "BUFFER_QUEUE_LIST": [ - { - "port": "Ethernet4", - "qindex": "16", - "profile": "lossless_buffer_profile" - } + { + "port": "Ethernet4", + "qindex": "16", + "profile": "lossless_buffer_profile" + } ] } } @@ -160,52 +160,98 @@ "sonic-port:sonic-port": { "sonic-port:PORT": { "PORT_LIST": [ - { - "admin_status": "up", - "alias": "eth0", - "description": "Ethernet0", - "lanes": "65", - "mtu": "9000", - "name": "Ethernet4", - "tpid": "0x8100", - "speed": "25000" - } + { + "admin_status": "up", + "alias": "eth0", + "description": "Ethernet0", + "lanes": "65", + "mtu": "9000", + "name": "Ethernet4", + "tpid": "0x8100", + "speed": "25000" + } ] } }, "sonic-buffer-pool:sonic-buffer-pool": { "sonic-buffer-pool:BUFFER_POOL": { "BUFFER_POOL_LIST": [ - { - "name": "egress_lossless_pool", - "mode": "static", - "size": "12766208", - "type": "ingress" - } + { + "name": "egress_lossless_pool", + "mode": "static", + "size": "12766208", + "type": "ingress" + } ] } }, "sonic-buffer-profile:sonic-buffer-profile": { "sonic-buffer-profile:BUFFER_PROFILE": { "BUFFER_PROFILE_LIST": [ - { - "name": "lossless_buffer_profile", - "size": "1518", - "pool": "egress_lossless_pool" - } + { + "name": "lossless_buffer_profile", + "size": "1518", + "pool": "egress_lossless_pool" + } ] } }, "sonic-buffer-queue:sonic-buffer-queue": { "sonic-buffer-queue:BUFFER_QUEUE": { "BUFFER_QUEUE_LIST": [ - { - "port": "wrong", - "qindex": "4", - "profile": "lossless_buffer_profile" + { + "port": "wrong", + "qindex": "4", + "profile": "lossless_buffer_profile" + } + ] + } + } + }, + "VOQ_BUFFER_QUEUE_CONFIG": { + "sonic-device_metadata:sonic-device_metadata": { + "sonic-device_metadata:DEVICE_METADATA": { + "sonic-device_metadata:localhost": { + "switch_type": "voq" } + } + }, + "sonic-buffer-pool:sonic-buffer-pool": { + "sonic-buffer-pool:BUFFER_POOL": { + "BUFFER_POOL_LIST": [ + { + "name": "egress_lossless_pool", + "mode": "static", + "size": "12766208", + "type": "ingress" + } + ] + } + }, + "sonic-buffer-profile:sonic-buffer-profile": { + "sonic-buffer-profile:BUFFER_PROFILE": { + "BUFFER_PROFILE_LIST": [ + { + "name": "lossless_buffer_profile", + "size": 1518, + "dynamic_th": "2", + "pool": "egress_lossless_pool" + } + ] + } + }, + "sonic-buffer-queue:sonic-buffer-queue": { + "sonic-buffer-queue:BUFFER_QUEUE": { + "VOQ_BUFFER_QUEUE_LIST": [ + { + "hostname": "lc1", + "asic_name": "asic0", + "port": "Ethernet4", + "qindex": "15", + "profile": "lossless_buffer_profile" + } ] } } } -} +} \ No newline at end of file diff --git a/src/sonic-yang-models/tests/yang_model_tests/tests_config/console.json b/src/sonic-yang-models/tests/yang_model_tests/tests_config/console.json new file mode 100644 index 000000000000..1ccfb4a3ae11 --- /dev/null +++ b/src/sonic-yang-models/tests/yang_model_tests/tests_config/console.json @@ -0,0 +1,88 @@ +{ + "CONSOLE_DISABLED": { + "sonic-console:sonic-console": { + "sonic-console:CONSOLE_SWITCH": { + "sonic-console:console_mgmt": { + "enabled": "no" + } + } + } + }, + "CONSOLE_DEFAULT_CONSOLE_MGMT": { + "sonic-console:sonic-console": { + "sonic-console:CONSOLE_SWITCH": { + "sonic-console:console_mgmt": { + } + } + } + }, + "CONSOLE_DISABLED_INCORRECT_PATTERN": { + "sonic-console:sonic-console": { + "sonic-console:CONSOLE_SWITCH": { + "sonic-console:console_mgmt": { + "enabled": "false" + } + } + } + }, + "CONSOLE_PORT_DEFAULT_FLOW_CONTROL": { + "sonic-console:sonic-console": { + "sonic-console:CONSOLE_PORT": { + "CONSOLE_PORT_LIST": [ + { + "name": "1", + "baud_rate": "9600" + } + ] + } + } + }, + "CONSOLE_PORT_INVALID_NAME": { + "sonic-console:sonic-console": { + "sonic-console:CONSOLE_PORT": { + "CONSOLE_PORT_LIST": [ + { + "name": "invalid", + "baud_rate": "9600" + } + ] + } + } + }, + "CONSOLE_PORT_INVALID_BAUD": { + "sonic-console:sonic-console": { + "sonic-console:CONSOLE_PORT": { + "CONSOLE_PORT_LIST": [ + { + "name": "1", + "baud_rate": "invalid" + } + ] + } + } + }, + "CONSOLE_PORT_VALID": { + "sonic-console:sonic-console": { + "sonic-console:CONSOLE_PORT": { + "CONSOLE_PORT_LIST": [ + { + "name": "1", + "baud_rate": "9600", + "flow_control": "1", + "remote_device": "remote_host_1" + }, + { + "name": "2", + "baud_rate": "9600", + "flow_control": "0", + "remote_device": "remote_host_2" + }, + { + "name": "3", + "baud_rate": "9600" + } + ] + } + } + } +} diff --git a/src/sonic-yang-models/tests/yang_model_tests/tests_config/device_metadata.json b/src/sonic-yang-models/tests/yang_model_tests/tests_config/device_metadata.json index 21cf3808a636..16c42a92a398 100644 --- a/src/sonic-yang-models/tests/yang_model_tests/tests_config/device_metadata.json +++ b/src/sonic-yang-models/tests/yang_model_tests/tests_config/device_metadata.json @@ -11,6 +11,34 @@ } } }, + "DEVICE_METADATA_ASIC_ID": { + "sonic-device_metadata:sonic-device_metadata": { + "sonic-device_metadata:DEVICE_METADATA": { + "sonic-device_metadata:localhost": { + "bgp_asn": "65001", + "default_bgp_status": "up", + "hostname": "DUT-CSW", + "asic_id": "06:00.0", + "asic_name": "asic0", + "platform": "Stone-DX010" + } + } + } + }, + "DEVICE_METADATA_ASIC_NAME": { + "sonic-device_metadata:sonic-device_metadata": { + "sonic-device_metadata:DEVICE_METADATA": { + "sonic-device_metadata:localhost": { + "bgp_asn": "65001", + "default_bgp_status": "up", + "hostname": "DUT-CSW", + "asic_id": "06:00.0", + "asic_name": "asic0", + "platform": "Stone-DX010" + } + } + } + }, "DEVICE_METADATA_DEFAULT_DOCKER_ROUTING_CONFIG_MODE": { "sonic-device_metadata:sonic-device_metadata": { "sonic-device_metadata:DEVICE_METADATA": { diff --git a/src/sonic-yang-models/tests/yang_model_tests/tests_config/fabric_monitor_data.json b/src/sonic-yang-models/tests/yang_model_tests/tests_config/fabric_monitor_data.json new file mode 100644 index 000000000000..ad71aabd9c4c --- /dev/null +++ b/src/sonic-yang-models/tests/yang_model_tests/tests_config/fabric_monitor_data.json @@ -0,0 +1,14 @@ +{ + "FABRIC_MONITOR_POSITIVE_CONFIG": { + "sonic-fabric-monitor:sonic-fabric-monitor": { + "sonic-fabric-monitor:FABRIC_MONITOR": { + "FABRIC_MONITOR_DATA": { + "monErrThreshCrcCells": "1", + "monErrThreshRxCells": "61035156", + "monPollThreshIsolation": "1", + "monPollThreshRecovery": "8" + } + } + } + } +} diff --git a/src/sonic-yang-models/tests/yang_model_tests/tests_config/fabric_port.json b/src/sonic-yang-models/tests/yang_model_tests/tests_config/fabric_port.json new file mode 100644 index 000000000000..278834826120 --- /dev/null +++ b/src/sonic-yang-models/tests/yang_model_tests/tests_config/fabric_port.json @@ -0,0 +1,16 @@ +{ + "FABRIC_PORT_POSITIVE_CONFIG": { + "sonic-fabric-port:sonic-fabric-port": { + "sonic-fabric-port:FABRIC_PORT": { + "FABRIC_PORT_LIST": [ + { + "name": "Fabric0", + "alias": "Fabric0", + "isolateStatus": "False", + "lanes": "0" + } + ] + } + } + } +} diff --git a/src/sonic-yang-models/tests/yang_model_tests/tests_config/port.json b/src/sonic-yang-models/tests/yang_model_tests/tests_config/port.json index 7444040036e9..d511d6cdda92 100644 --- a/src/sonic-yang-models/tests/yang_model_tests/tests_config/port.json +++ b/src/sonic-yang-models/tests/yang_model_tests/tests_config/port.json @@ -226,6 +226,66 @@ } }, + "PORT_COREID_TYPE_TEST": { + "sonic-port:sonic-port": { + "sonic-port:PORT": { + "PORT_LIST": [ + { + "name": "Ethernet8", + "alias": "eth8", + "core_id": "1", + "core_port_id": "1", + "num_voq": "8", + "lanes": "65", + "speed": 25000, + "autoneg": "on", + "interface_type": "CR4" + } + ] + } + } + }, + + "PORT_COREPORTID_TYPE_TEST": { + "sonic-port:sonic-port": { + "sonic-port:PORT": { + "PORT_LIST": [ + { + "name": "Ethernet8", + "alias": "eth8", + "core_id": "2", + "core_port_id": "2", + "num_voq": "8", + "lanes": "65", + "speed": 25000, + "autoneg": "on", + "interface_type": "CR4" + } + ] + } + } + }, + + "PORT_NUMVOQ_TYPE_TEST": { + "sonic-port:sonic-port": { + "sonic-port:PORT": { + "PORT_LIST": [ + { + "name": "Ethernet8", + "alias": "eth8", + "core_id": "3", + "core_port_id": "3", + "num_voq": "8", + "lanes": "65", + "speed": 25000, + "autoneg": "on", + "interface_type": "CR4" + } + ] + } + } + }, + "PORT_INVALID_TYPE_TEST": { "sonic-port:sonic-port": { "sonic-port:PORT": { diff --git a/src/sonic-yang-models/tests/yang_model_tests/tests_config/qos.json b/src/sonic-yang-models/tests/yang_model_tests/tests_config/qos.json index 67775b11db81..922d3c8a2e18 100644 --- a/src/sonic-yang-models/tests/yang_model_tests/tests_config/qos.json +++ b/src/sonic-yang-models/tests/yang_model_tests/tests_config/qos.json @@ -511,5 +511,68 @@ ] } } + }, + "VOQ_QUEUE_CONFIG": { + "sonic-device_metadata:sonic-device_metadata": { + "sonic-device_metadata:DEVICE_METADATA": { + "sonic-device_metadata:localhost": { + "switch_type": "voq" + } + } + }, + "sonic-scheduler:sonic-scheduler":{ + "sonic-scheduler:SCHEDULER": { + "SCHEDULER_LIST": [ + { + "name":"Test@0", + "cbs": 256, + "cir": 1250000, + "meter_type": "bytes", + "pbs": 1024, + "pir": 25000000, + "type": "DWRR", + "weight": 10 + } + ] + } + }, + "sonic-wred-profile:sonic-wred-profile":{ + "sonic-wred-profile:WRED_PROFILE": { + "WRED_PROFILE_LIST": [ + { + "name":"Wred1", + "yellow_min_threshold": 2048, + "green_min_threshold": 4096, + "red_min_threshold": 1024, + "yellow_max_threshold": 4096, + "green_max_threshold": 8192, + "red_max_threshold": 2048, + "ecn": "ecn_none", + "wred_green_enable": true, + "wred_yellow_enable": true, + "wred_red_enable": true, + "yellow_drop_probability": 50, + "green_drop_probability": 25, + "red_drop_probability": 100 + } + ] + } + }, + + "sonic-queue:sonic-queue": { + "sonic-queue:QUEUE": { + "VOQ_QUEUE_LIST": [ + { + "hostname": "lc1", + "asic_name": "asic0", + "ifname": "Ethernet0", + "qindex": "0", + "scheduler": "Test@0", + "wred_profile": "Wred1" + } + ] + } + } } + } diff --git a/src/sonic-yang-models/tests/yang_model_tests/tests_config/restapi.json b/src/sonic-yang-models/tests/yang_model_tests/tests_config/restapi.json new file mode 100644 index 000000000000..f2a3b15643c6 --- /dev/null +++ b/src/sonic-yang-models/tests/yang_model_tests/tests_config/restapi.json @@ -0,0 +1,50 @@ +{ + "RESTAPI_TABLE_WITH_INCORRECT_CERT": { + "sonic-restapi:sonic-restapi": { + "sonic-restapi:RESTAPI": { + "certs": { + "ca_crt": "/etc/sonic/credentials/ame_root.pem", + "server_crt": "a/b/c", + "server_key": "/etc/sonic/credentials/restapiserver.key", + "client_crt_cname": "client" + } + } + } + }, + "RESTAPI_TABLE_WITH_INCORRECT_CLIENT": { + "sonic-restapi:sonic-restapi": { + "sonic-restapi:RESTAPI": { + "certs": { + "ca_crt": "/etc/sonic/credentials/ame_root.pem", + "server_crt": "/etc/sonic/credentials/restapiserver.crt", + "server_key": "/etc/sonic/credentials/restapiserver.key", + "client_crt_cname": "/client" + } + } + } + }, + "RESTAPI_TABLE_WITH_VALID_CONFIG": { + "sonic-restapi:sonic-restapi": { + "sonic-restapi:RESTAPI": { + "certs": { + "ca_crt": "/etc/sonic/credentials/ame_root.pem", + "server_crt": "/etc/sonic/credentials/restapiserver.crt", + "server_key": "/etc/sonic/credentials/restapiserver.key", + "client_crt_cname": "client.sonic.net" + } + } + } + }, + "RESTAPI_TABLE_WITH_MULTIPLE_CERTS": { + "sonic-restapi:sonic-restapi": { + "sonic-restapi:RESTAPI": { + "certs": { + "ca_crt": "/etc/sonic/credentials/ame_root.pem", + "server_crt": "/etc/sonic/credentials/restapiserver.crt", + "server_key": "/etc/sonic/credentials/restapiserver.key", + "client_crt_cname": "client.sonic.net,clientds.prod.net" + } + } + } + } +} diff --git a/src/sonic-yang-models/tests/yang_model_tests/tests_config/system_port.json b/src/sonic-yang-models/tests/yang_model_tests/tests_config/system_port.json new file mode 100644 index 000000000000..28edae5727a1 --- /dev/null +++ b/src/sonic-yang-models/tests/yang_model_tests/tests_config/system_port.json @@ -0,0 +1,91 @@ +{ + "SYSTEM_PORT_POSITIVE_CONFIG": { + "sonic-port:sonic-port": { + "sonic-port:PORT": { + "PORT_LIST": [ + { + "admin_status": "up", + "alias": "eth0", + "description": "Ethernet0", + "lanes": "65", + "mtu": 9000, + "name": "Ethernet0", + "speed": 100000 + }, + { + "admin_status": "up", + "alias": "eth4", + "description": "Ethernet4", + "lanes": "65", + "mtu": 9000, + "name": "Ethernet4", + "speed": 100000 + } + ] + } + }, + "sonic-system-port:sonic-system-port": { + "sonic-system-port:SYSTEM_PORT": { + "SYSTEM_PORT_LIST": [ + { + "hostname": "host123", + "asic_name": "asic0", + "ifname": "Ethernet0", + "core_index": "0", + "core_port_index": "10", + "num_voq": "8", + "speed": "100000", + "switch_id": "0", + "system_port_id": "100" + }, + { + "hostname": "host123", + "asic_name": "asic1", + "ifname": "Ethernet4", + "core_index": "1", + "core_port_index": "20", + "num_voq": "8", + "speed": "100000", + "switch_id": "1", + "system_port_id": "200" + } + ] + } + } + }, + "SYSTEM_PORT_WRONG_SPEED_PATTERN": { + "sonic-port:sonic-port": { + "sonic-port:PORT": { + "PORT_LIST": [ + { + "admin_status": "up", + "alias": "eth0", + "description": "Ethernet0", + "lanes": "65", + "mtu": 9000, + "name": "Ethernet0", + "speed": 100000 + } + ] + } + }, + "sonic-system-port:sonic-system-port": { + "sonic-system-port:SYSTEM_PORT": { + "SYSTEM_PORT_LIST": [ + { + "hostname": "host456", + "asic_name": "asic0", + "ifname": "Ethernet0", + "core_index": "1", + "core_port_index": "20", + "num_voq": "8", + "speed": "900000", + "switch_id": "1", + "system_port_id": "200" + } + ] + } + } + } + +} diff --git a/src/sonic-yang-models/yang-models/sonic-buffer-pool.yang b/src/sonic-yang-models/yang-models/sonic-buffer-pool.yang index c59d4ec66ab5..ba506c506ce3 100644 --- a/src/sonic-yang-models/yang-models/sonic-buffer-pool.yang +++ b/src/sonic-yang-models/yang-models/sonic-buffer-pool.yang @@ -33,6 +33,7 @@ module sonic-buffer-pool { type enumeration { enum ingress; enum egress; + enum both; } description "Buffer Pool Type"; } diff --git a/src/sonic-yang-models/yang-models/sonic-buffer-queue.yang b/src/sonic-yang-models/yang-models/sonic-buffer-queue.yang index f8c951aa4dd1..c36eb5415d88 100644 --- a/src/sonic-yang-models/yang-models/sonic-buffer-queue.yang +++ b/src/sonic-yang-models/yang-models/sonic-buffer-queue.yang @@ -14,6 +14,14 @@ module sonic-buffer-queue { prefix bpf; } + import sonic-device_metadata { + prefix sdm; + } + + import sonic-types { + prefix stypes; + } + organization "SONiC"; @@ -34,6 +42,9 @@ module sonic-buffer-queue { container BUFFER_QUEUE { list BUFFER_QUEUE_LIST { + when "not(/sdm:sonic-device_metadata/sdm:DEVICE_METADATA/sdm:localhost/sdm:switch_type) or + (/sdm:sonic-device_metadata/sdm:DEVICE_METADATA/sdm:localhost/sdm:switch_type!='voq')"; + key "port qindex"; leaf port { @@ -61,6 +72,50 @@ module sonic-buffer-queue { } } + list VOQ_BUFFER_QUEUE_LIST { + when "boolean(/sdm:sonic-device_metadata/sdm:DEVICE_METADATA/sdm:localhost/sdm:switch_type) and + (/sdm:sonic-device_metadata/sdm:DEVICE_METADATA/sdm:localhost/sdm:switch_type='voq')"; + + key "hostname asic_name port qindex"; + + + leaf hostname { + type stypes:hostname; + } + + leaf asic_name { + type string { + pattern "[Aa]sic[0-4]"; + } + } + + leaf port { + type string { + length 1..128; + } + + description "port name."; + } + + leaf qindex { + type string { + pattern "(1[0-5]|[0-9])((-)(1[0-5]|[0-9]))?"{ + error-message "Invalid Q-index"; + error-app-tag qindex-invalid; + } + } + description "Egress Queue Index for a port"; + } + + leaf profile { + default 0; + type leafref { + path "/bpf:sonic-buffer-profile/bpf:BUFFER_PROFILE/bpf:BUFFER_PROFILE_LIST/bpf:name"; + } + description "Buffer Profile associated with Priority Queue for a port"; + } + + } } } } diff --git a/src/sonic-yang-models/yang-models/sonic-console.yang b/src/sonic-yang-models/yang-models/sonic-console.yang new file mode 100644 index 000000000000..341abaf8d26a --- /dev/null +++ b/src/sonic-yang-models/yang-models/sonic-console.yang @@ -0,0 +1,76 @@ +module sonic-console { + yang-version 1.1; + namespace "http://github.com/sonic-net/sonic-console"; + prefix console; + + import sonic-types { + prefix stypes; + } + + description "SONiC CONSOLE"; + + revision 2022-08-22 { + description "First Revision"; + } + + typedef console-mgmt-enabled { + description "configuration to set if console switch is enabled or not"; + type string { + pattern "yes|no"; + } + } + + typedef console-flow-control { + description "configuration to set if enable flow control on a console port"; + type string { + pattern "0|1"; + } + } + + container sonic-console { + container CONSOLE_PORT { + description "CONSOLE_PORT part of config_db.json"; + + list CONSOLE_PORT_LIST { + key "name"; + + leaf name { + description "Configure console port name"; + type uint16; + } + + leaf baud_rate { + description "Configure baud rate"; + type uint32; + } + + leaf flow_control { + description "Configure if enable/disable flow control"; + type console-flow-control; + default "0"; + } + + leaf remote_device { + description "Configure the remote device name"; + type stypes:hostname; + } + } + + } /* end of container CONSOLE_PORT */ + + container CONSOLE_SWITCH { + description "CONSOLE_SWITCH part of config_db.json"; + + container console_mgmt { + leaf enabled { + description "This configuration indicate if enable console management feature on SONiC"; + type console-mgmt-enabled; + default "no"; + } + } + + } /* end of container CONSOLE_SWITCH */ + + } /* end of top level container */ + +} /* end of module sonic-console */ diff --git a/src/sonic-yang-models/yang-models/sonic-device_metadata.yang b/src/sonic-yang-models/yang-models/sonic-device_metadata.yang index 83e113cff3ae..5657e55ef22f 100644 --- a/src/sonic-yang-models/yang-models/sonic-device_metadata.yang +++ b/src/sonic-yang-models/yang-models/sonic-device_metadata.yang @@ -40,6 +40,13 @@ module sonic-device_metadata { type stypes:hwsku; } + leaf asic_id { + type string { + length 1..16; + } + description "asic_id is unique identifier of the asic used by SAI for initialization."; + } + leaf default_bgp_status { type enumeration { enum up; diff --git a/src/sonic-yang-models/yang-models/sonic-fabric-monitor.yang b/src/sonic-yang-models/yang-models/sonic-fabric-monitor.yang new file mode 100644 index 000000000000..0c0464ab965d --- /dev/null +++ b/src/sonic-yang-models/yang-models/sonic-fabric-monitor.yang @@ -0,0 +1,53 @@ +module sonic-fabric-monitor{ + + yang-version 1.1; + + namespace "http://github.com/sonic-net/sonic-fabric-monitor"; + prefix fabric-monitor; + + description "FABRIC_MONITOR yang Module for SONiC OS"; + + revision 2023-03-14 { + description "First Revision"; + } + + container sonic-fabric-monitor { + + container FABRIC_MONITOR { + + description "FABRIC_MONITOR part of config_db.json"; + + container FABRIC_MONITOR_DATA { + + leaf monErrThreshCrcCells { + type uint32; + default 1; + description "The number of cells with errors."; + } + + leaf monErrThreshRxCells { + type uint32; + default 61035156; + description "The number of cells received. If more than monErrThreshCrcCells out of monErrThreshRxCells seen with errors, the fabric port needs to be isolated"; + } + + leaf monPollThreshIsolation { + type uint32; + default 1; + description "Consecutive polls with higher error rate for isolation."; + } + + leaf monPollThreshRecovery { + type uint32; + default 8; + description "Consecutive polls with lesser error rate for inclusion."; + } + + } /* end of container FABRIC_MONITOR_DATA */ + + } /* end of container FABRIC_MONITOR */ + + } /* end of container sonic-fabric-monitor */ + +} /* end of module sonic-fabric-monitor */ + diff --git a/src/sonic-yang-models/yang-models/sonic-fabric-port.yang b/src/sonic-yang-models/yang-models/sonic-fabric-port.yang new file mode 100644 index 000000000000..f2266507deef --- /dev/null +++ b/src/sonic-yang-models/yang-models/sonic-fabric-port.yang @@ -0,0 +1,61 @@ +module sonic-fabric-port{ + + yang-version 1.1; + + namespace "http://github.com/sonic-net/sonic-fabric-port"; + prefix fabric-port; + + import sonic-types { + prefix stypes; + } + + description "FABRIC_PORT yang Module for SONiC OS"; + + revision 2023-03-14 { + description "First Revision"; + } + + container sonic-fabric-port { + + container FABRIC_PORT { + + description "FABRIC_PORT part of config_db.json"; + + list FABRIC_PORT_LIST { + + key "name"; + + leaf name { + type string { + length 1..128; + } + } + + leaf isolateStatus { + description "Isolation status of a fabric port"; + type stypes:boolean_type; + default "False"; + } + + leaf alias { + description "Alias of a fabric port"; + type string { + length 1..128; + } + } + + leaf lanes { + description "Lanes of a fabric port"; + mandatory true; + type string { + length 1..128; + } + } + + } /* end of list FABRIC_PORT_LIST */ + + } /* end of container FABRIC_PORT */ + + } /* end of container sonic-fabric-port */ + +} /* end of module sonic-fabric-port */ diff --git a/src/sonic-yang-models/yang-models/sonic-port.yang b/src/sonic-yang-models/yang-models/sonic-port.yang index 1b9c6b14b5a9..6ad6919c0c13 100644 --- a/src/sonic-yang-models/yang-models/sonic-port.yang +++ b/src/sonic-yang-models/yang-models/sonic-port.yang @@ -39,6 +39,27 @@ module sonic-port{ } } + leaf core_id { + description "The ASIC core where the port belongs to."; + type string { + length 1..16; + } + } + + leaf core_port_id { + description "The ASIC core port for this port."; + type string { + length 1..16; + } + } + + leaf num_voq { + description "The number of virtual output queue supportted on this port."; + type string { + length 1..16; + } + } + leaf alias { type string { length 1..128; @@ -163,8 +184,8 @@ module sonic-port{ leaf tpid { description "This leaf describes the possible TPID value that can be configured - to the specified port if the HW supports TPID configuration. The possible - values are 0x8100, 0x9100, 0x9200, 0x88a8, and 0x88A8"; + to the specified port if the HW supports TPID configuration. The possible + values are 0x8100, 0x9100, 0x9200, 0x88a8, and 0x88A8"; type stypes:tpid_type; } diff --git a/src/sonic-yang-models/yang-models/sonic-queue.yang b/src/sonic-yang-models/yang-models/sonic-queue.yang index 8e24faa72cb0..e249b78f3930 100644 --- a/src/sonic-yang-models/yang-models/sonic-queue.yang +++ b/src/sonic-yang-models/yang-models/sonic-queue.yang @@ -22,6 +22,14 @@ module sonic-queue { prefix wrd; } + import sonic-device_metadata { + prefix sdm; + } + + import sonic-types { + prefix stypes; + } + organization "SONiC"; @@ -43,10 +51,12 @@ module sonic-queue { description "QUEUE part of config_db.json"; list QUEUE_LIST { + when "not(/sdm:sonic-device_metadata/sdm:DEVICE_METADATA/sdm:localhost/sdm:switch_type) or + (/sdm:sonic-device_metadata/sdm:DEVICE_METADATA/sdm:localhost/sdm:switch_type!='voq')"; key "ifname qindex"; - // sonic-ext:key-pattern "QUEUE|{ifname}|{qindex}"; //special pattern used for extracting keys from redis-key and populate the yang instance +// sonic-ext:key-pattern "QUEUE|{ifname}|{qindex}"; //special pattern used for extracting keys from redis-key and populate the yang instance // Total list instances = number(key1) * number(key2) * number(key3) leaf ifname { @@ -83,6 +93,54 @@ module sonic-queue { description "Wred profile for queue."; } } + + list VOQ_QUEUE_LIST { + when "boolean(/sdm:sonic-device_metadata/sdm:DEVICE_METADATA/sdm:localhost/sdm:switch_type) and + (/sdm:sonic-device_metadata/sdm:DEVICE_METADATA/sdm:localhost/sdm:switch_type='voq')"; + key "hostname asic_name ifname qindex"; + + + leaf hostname { + type stypes:hostname; + } + + leaf asic_name { + type string { + pattern "[Aa]sic[0-4]"; + } + } + + leaf ifname { + type string { + length 1..128; + } + + description "Interface name."; + } + // qindex format is (X) | (X-Y). X is start and Y is end index. + // X and Y value depends on platform, example for physical ports 0-7 and + // for CPU port 0-48. Example qindex is 3-4 + leaf qindex { + // sonic-ext:custom-validation ValidateQindexPattern; + type string; + description "Queue index on the interface."; + } + + leaf scheduler { + type leafref { + path "/sch:sonic-scheduler/sch:SCHEDULER/sch:SCHEDULER_LIST/sch:name"; //Reference to SCHEDULER table + } + description "Scheduler for queue."; + } + + leaf wred_profile { + type leafref { + path "/wrd:sonic-wred-profile/wrd:WRED_PROFILE/wrd:WRED_PROFILE_LIST/wrd:name"; // Reference to WRED_PROFILE table + } + description "Wred profile for queue."; + } + } } + } } diff --git a/src/sonic-yang-models/yang-models/sonic-restapi.yang b/src/sonic-yang-models/yang-models/sonic-restapi.yang new file mode 100644 index 000000000000..094ed18eb7bd --- /dev/null +++ b/src/sonic-yang-models/yang-models/sonic-restapi.yang @@ -0,0 +1,85 @@ +module sonic-restapi { + + yang-version 1.1; + + namespace "http://github.com/sonic-net/sonic-restapi"; + prefix restapi; + + import ietf-inet-types { + prefix inet; + } + + organization + "SONiC"; + + contact + "SONiC"; + + description "RESTAPI YANG Module for SONiC OS"; + + revision 2022-10-05 { + description "First Revision"; + } + + container sonic-restapi { + + container RESTAPI { + + description "RESTAPI TABLE part of config_db.json"; + + container certs { + + leaf ca_crt { + type string { + pattern '(/[a-zA-Z0-9_-]+)*/([a-zA-Z0-9_-]+).([a-z]+)'; + } + description "Local path for ca_crt."; + } + + leaf server_crt { + type string { + pattern '(/[a-zA-Z0-9_-]+)*/([a-zA-Z0-9_-]+).crt'; + } + description "Local path for server_crt."; + } + + leaf client_crt_cname { + type string { + pattern '([a-zA-Z0-9_\-\.]+,)*([a-zA-Z0-9_\-\.]+)'; + } + description "Client cert name."; + } + + leaf server_key { + type string { + pattern '(/[a-zA-Z0-9_-]+)*/([a-zA-Z0-9_-]+).key'; + } + description "Local path for server_key."; + } + + } + + container config { + + leaf client_auth { + type boolean; + default true; + description "Enable client authentication"; + } + + leaf log_level { + type string { + pattern "trace|info"; + } + description "container log level for restapi"; + } + + leaf allow_insecure { + type boolean; + default false; + description "Allow insecure connection"; + } + } + } + } +} diff --git a/src/sonic-yang-models/yang-models/sonic-system-port.yang b/src/sonic-yang-models/yang-models/sonic-system-port.yang new file mode 100644 index 000000000000..f95405ac662f --- /dev/null +++ b/src/sonic-yang-models/yang-models/sonic-system-port.yang @@ -0,0 +1,90 @@ +module sonic-system-port { + + yang-version 1.1; + + namespace "http://github.com/sonic-net/sonic-system-port"; + prefix system-port; + + import sonic-port { + prefix port; + } + + import sonic-types { + prefix stypes; + } + + description "SYSTEM_PORT YANG Module for SONiC OS"; + + revision 2022-11-10 { + description "First Revision"; + } + + container sonic-system-port { + + container SYSTEM_PORT { + + description "SYSTEM_PORT table of config_db.json"; + + list SYSTEM_PORT_LIST { + + key "hostname asic_name ifname"; + + leaf hostname { + type stypes:hostname; + } + + leaf asic_name { + type string { + pattern "[Aa]sic[0-4]"; + } + } + + leaf ifname { + type string { + length 1..128; + } + } + + leaf core_index { + type uint8 { + range 0..7; + } + description "Hardware core index a port is affiliated with."; + } + + leaf core_port_index { + type uint16; + description "Local port index index to an ASIC core."; + } + + leaf num_voq { + type uint8 { + range 1..8; + } + description "Number of VoQs associated with a port."; + } + + leaf speed { + type uint32 { + range 1..800000; + } + description "Port speed in Mbps."; + } + + leaf switch_id { + type uint16; + description "On a VoQ switch, the global ASIC identifier."; + } + + leaf system_port_id { + type uint32; + description "On a VoQ switch, the global port identifier."; + } + } + /* end of list SYSTEM_PORT_LIST */ + } + /* end of container SYSTEM_PORT */ + } + /* end of container sonic-system-port */ +} +/* end of module sonic-system-port */ diff --git a/src/system-health/health_checker/service_checker.py b/src/system-health/health_checker/service_checker.py index 0c6bba50b2ca..3145fbc2ec8a 100644 --- a/src/system-health/health_checker/service_checker.py +++ b/src/system-health/health_checker/service_checker.py @@ -4,7 +4,7 @@ import re from swsscommon import swsscommon -from sonic_py_common import multi_asic +from sonic_py_common import multi_asic, device_info from sonic_py_common.logger import Logger from .health_checker import HealthChecker from . import utils @@ -95,7 +95,10 @@ def get_expected_running_containers(self, feature_table): else: expected_running_containers.add(feature_name) container_feature_dict[feature_name] = feature_name - + + if device_info.is_supervisor(): + expected_running_containers.add("database-chassis") + container_feature_dict["database-chassis"] = "database" return expected_running_containers, container_feature_dict def get_current_running_containers(self): diff --git a/src/systemd-sonic-generator/Makefile b/src/systemd-sonic-generator/Makefile index 565fcb8030a7..2e6b769c11f7 100644 --- a/src/systemd-sonic-generator/Makefile +++ b/src/systemd-sonic-generator/Makefile @@ -1,9 +1,9 @@ CC=gcc CFLAGS=-std=gnu99 -D_GNU_SOURCE -CPP=g++ -CPPFLAGS=-std=c++11 -D_GNU_SOURCE -LFLAGS=-lpthread -lboost_filesystem -lboost_system -lgtest +CXX=g++ +CXXFLAGS += -std=c++11 -D_GNU_SOURCE -I ./ +LDFLAGS += -l stdc++ -lpthread -lboost_filesystem -lboost_system -lgtest BINARY = systemd-sonic-generator MAIN_TARGET = $(BINARY)_1.0.0_$(CONFIGURED_ARCH).deb @@ -13,10 +13,10 @@ $(addprefix $(DEST)/, $(MAIN_TARGET)): $(DEST)/% : mv ../$(MAIN_TARGET) $(DEST)/ rm ../$(BINARY)-* ../$(BINARY)_* -$(BINARY): systemd-sonic-generator.c +$(BINARY): systemd-sonic-generator.cpp rm -f ./systemd-sonic-generator - $(CC) $(CFLAGS) -o $@ $^ + $(CXX) $(CXXFLAGS) -o $@ $^ $(LDFLAGS) install: $(BINARY) mkdir -p $(DESTDIR) @@ -30,10 +30,12 @@ test: ssg_test ./ssg_test ssg_test: ssg-test.cc systemd-sonic-generator.o - $(CPP) $(CPPFLAGS) -o $@ $^ $(LFLAGS) + $(CXX) $(CXXFLAGS) -ggdb -o $@ $^ $(LDFLAGS) -systemd-sonic-generator.o: systemd-sonic-generator.c - $(CC) $(CFLAGS) -D_SSG_UNITTEST -o $@ -c $^ +systemd-sonic-generator.o: systemd-sonic-generator.cpp + $(CXX) $(CXXFLAGS) -ggdb -D_SSG_UNITTEST -o $@ -c $^ + +all: $(BINARY) test clean: rm -f ./systemd-sonic-generator diff --git a/src/systemd-sonic-generator/ssg-test.cc b/src/systemd-sonic-generator/ssg-test.cc index 1d0f33d54bec..567da24ec05d 100644 --- a/src/systemd-sonic-generator/ssg-test.cc +++ b/src/systemd-sonic-generator/ssg-test.cc @@ -181,8 +181,7 @@ class SsgMainTest : public SsgFunctionTest { /* Find a string in a file */ bool find_string_in_file(std::string str, - std::string file_name, - int num_asics) { + std::string file_name) { bool found = false; std::string line; @@ -214,7 +213,7 @@ class SsgMainTest : public SsgFunctionTest { /* Run once for single instance */ finished = true; } - EXPECT_EQ(find_string_in_file(str_t, target, num_asics), + EXPECT_EQ(find_string_in_file(str_t, target), expected_result) << "Error validating " + str_t + " in " + target; } @@ -460,9 +459,8 @@ TEST_F(SsgFunctionTest, insert_instance_number) { char input[] = "test@.service"; for (int i = 0; i <= 100; ++i) { std::string out = "test@" + std::to_string(i) + ".service"; - char* ret = insert_instance_number(input, i); - ASSERT_NE(ret, nullptr); - EXPECT_STREQ(ret, out.c_str()); + std::string ret = insert_instance_number(input, i); + EXPECT_EQ(ret, out); } } @@ -513,7 +511,6 @@ TEST_F(SsgFunctionTest, get_unit_files) { /* TEST ssg_main() argv error */ TEST_F(SsgMainTest, ssg_main_argv) { - FILE* fp; std::vector argv_; std::vector arguments = { "ssg_main", diff --git a/src/systemd-sonic-generator/systemd-sonic-generator.c b/src/systemd-sonic-generator/systemd-sonic-generator.cpp similarity index 69% rename from src/systemd-sonic-generator/systemd-sonic-generator.c rename to src/systemd-sonic-generator/systemd-sonic-generator.cpp index ff748ca97767..d0359a4a1dff 100644 --- a/src/systemd-sonic-generator/systemd-sonic-generator.c +++ b/src/systemd-sonic-generator/systemd-sonic-generator.cpp @@ -1,13 +1,15 @@ -#include #include #include #include #include #include -#include +// #include #include #include #include +#include +#include +#include #define MAX_NUM_TARGETS 48 #define MAX_NUM_INSTALL_LINES 48 @@ -48,13 +50,25 @@ void strip_trailing_newline(char* str) { Strips trailing newline from a string if it exists ***/ + if (str == NULL) { + return; + } size_t l = strlen(str); if (l > 0 && str[l-1] == '\n') str[l-1] = '\0'; } +void strip_trailing_newline(std::string& str) { + /*** + Strips trailing newline from a string if it exists + ***/ + if (!str.empty() && str.back() == '\n') { + str.pop_back(); + } +} + -static int get_target_lines(char* unit_file, char* target_lines[]) { +static int get_target_lines(const char* unit_file, char* target_lines[]) { /*** Gets installation information for a given unit file @@ -101,26 +115,32 @@ static int get_target_lines(char* unit_file, char* target_lines[]) { return num_target_lines; } -static bool is_multi_instance_service(char *service_name){ - int i; - for(i=0; i < num_multi_inst; i++){ - /* - * The service name may contain @.service or .service. Remove these - * postfixes and extract service name. Compare service name for absolute - * match in multi_instance_services[]. - * This is to prevent services like database-chassis and systemd-timesyncd marked - * as multi instance services as they contain strings 'database' and 'syncd' respectively - * which are multi instance services in multi_instance_services[]. - */ - char *saveptr; - char *token = strtok_r(service_name, "@", &saveptr); - if (token) { - if (strstr(token, ".service") != NULL) { - /* If we are here, service_name did not have '@' delimiter but contains '.service' */ - token = strtok_r(service_name, ".", &saveptr); +static bool is_multi_instance_service(std::string service_file, std::unordered_set service_list=std::unordered_set()){ + /* + * The service name may contain @.service or .service. Remove these + * postfixes and extract service name. Compare service name for absolute + * match in multi_instance_services[]. + * This is to prevent services like database-chassis and systemd-timesyncd marked + * as multi instance services as they contain strings 'database' and 'syncd' respectively + * which are multi instance services in multi_instance_services[]. + */ + std::string delimiter; + if (service_file.find("@") != std::string::npos) { + delimiter = "@"; + } else { + delimiter = "."; + } + std::string service_name = service_file.substr(0, service_file.find(delimiter)); + + if (service_list.empty()) { + for(int i=0; i < num_multi_inst; i++){ + + if (service_name == multi_instance_services[i]) { + return true; } } - if (strncmp(service_name, multi_instance_services[i], strlen(service_name)) == 0) { + } else { + if (service_list.count(service_name) > 0) { return true; } } @@ -128,59 +148,49 @@ static bool is_multi_instance_service(char *service_name){ } -static int get_install_targets_from_line(char* target_string, char* install_type, char* targets[], int existing_targets) { +static int get_install_targets_from_line(std::string target_string, std::string install_type, char* targets[], int existing_targets) { /*** Helper fuction for get_install_targets Given a space delimited string of target directories and a suffix, puts each target directory plus the suffix into the targets array ***/ - char* token; - char* target; - char* saveptr; - char final_target[PATH_MAX]; + std::string target; int num_targets = 0; - while ((token = strtok_r(target_string, " ", &target_string))) { - if (num_targets + existing_targets >= MAX_NUM_TARGETS) { - fputs("Number of targets found exceeds MAX_NUM_TARGETS\n", stderr); - fputs("Additional targets will be ignored \n", stderr); - return num_targets; - } - - target = strdup(token); - strip_trailing_newline(target); + if (target_string.empty() || install_type.empty()) { + fprintf(stderr, "Invalid target string or install type\n"); + exit(EXIT_FAILURE); + } - if (strstr(target, "%") != NULL) { - char* prefix = strtok_r(target, ".", &saveptr); - char* suffix = strtok_r(NULL, ".", &saveptr); - int prefix_len = strlen(prefix); + std::stringstream ss(target_string); - strncpy(final_target, prefix, prefix_len - 2); - final_target[prefix_len - 2] = '\0'; - strcat(final_target, "."); - strcat(final_target, suffix); + while (ss >> target) { + if (num_targets + existing_targets >= MAX_NUM_TARGETS) { + fprintf(stderr, "Number of targets exceeds MAX_NUM_TARGETS\n"); + fputs("Additional targets will be ignored\n", stderr); + break; } - else { - strcpy(final_target, target); + // handle install targets using the '%i' systemd specifier + if (target.find("%") != std::string::npos) { + target = target.substr(0, target.find("%")) + target.substr(target.find(".")); } - strcat(final_target, install_type); - - free(target); - - targets[num_targets + existing_targets] = strdup(final_target); + strip_trailing_newline(target); + target += install_type; + targets[num_targets + existing_targets] = (char*) calloc(target.length() + 1, sizeof(char)); + snprintf(targets[num_targets + existing_targets], PATH_MAX, "%s", target.c_str()); num_targets++; } return num_targets; } -static void replace_multi_inst_dep(char *src) { +static void replace_multi_inst_dep(const char *src) { FILE *fp_src; FILE *fp_tmp; char buf[MAX_BUF_SIZE]; char* line = NULL; int i; - ssize_t len; + size_t len; char *token; char *word; char *line_copy; @@ -254,14 +264,14 @@ static void replace_multi_inst_dep(char *src) { rename(tmp_file_path, src); } -int get_install_targets(char* unit_file, char* targets[]) { +int get_install_targets(std::string unit_file, char* targets[]) { /*** Returns install targets for a unit file Parses the information in the [Install] section of a given unit file to determine which directories to install the unit in ***/ - char file_path[PATH_MAX]; + std::string file_path; char *target_lines[MAX_NUM_INSTALL_LINES]; int num_target_lines; int num_targets; @@ -269,25 +279,20 @@ int get_install_targets(char* unit_file, char* targets[]) { char* token; char* line = NULL; bool first; - char* target_suffix; - char *instance_name; - char *dot_ptr; + std::string target_suffix; + std::string instance_name; - strcpy(file_path, get_unit_file_prefix()); - strcat(file_path, unit_file); + file_path = get_unit_file_prefix() + unit_file; - instance_name = strdup(unit_file); - dot_ptr = strchr(instance_name, '.'); - *dot_ptr = '\0'; + instance_name = unit_file.substr(0, unit_file.find('.')); if((num_asics > 1) && (!is_multi_instance_service(instance_name))) { - replace_multi_inst_dep(file_path); + replace_multi_inst_dep(file_path.c_str()); } - free(instance_name); - num_target_lines = get_target_lines(file_path, target_lines); + num_target_lines = get_target_lines(file_path.c_str(), target_lines); if (num_target_lines < 0) { - fprintf(stderr, "Error parsing targets for %s\n", unit_file); + fprintf(stderr, "Error parsing targets for %s\n", unit_file.c_str()); return -1; } @@ -340,7 +345,7 @@ int get_unit_files(char* unit_files[]) { int num_unit_files = 0; num_multi_inst = 0; - multi_instance_services = calloc(MAX_NUM_UNITS, sizeof(char *)); + multi_instance_services = (char**) calloc(MAX_NUM_UNITS, sizeof(char *)); while ((read = getline(&line, &len, fp)) != -1) { if (num_unit_files >= MAX_NUM_UNITS) { @@ -352,8 +357,8 @@ int get_unit_files(char* unit_files[]) { /* Get the multi-instance services */ pos = strchr(line, '@'); if (pos != NULL) { - multi_instance_services[num_multi_inst] = calloc(strlen(line), sizeof(char)); - strncpy(multi_instance_services[num_multi_inst], line, pos-line); + multi_instance_services[num_multi_inst] = (char*) calloc(pos-line+1, sizeof(char)); + snprintf(multi_instance_services[num_multi_inst], pos-line+1, "%s", line); num_multi_inst++; } @@ -374,100 +379,80 @@ int get_unit_files(char* unit_files[]) { } -char* insert_instance_number(char* unit_file, int instance) { +std::string insert_instance_number(const std::string& unit_file, int instance) { /*** Adds an instance number to a systemd template name E.g. given unit_file='example@.service', instance=3, returns a pointer to 'example@3.service' ***/ - char* instance_name; - int ret; - int prefix_len; - const char *suffix = strchr(unit_file, '@'); - if (!suffix) { - fprintf(stderr, "Invalid unit file %s for instance %d\n", unit_file, instance); - return NULL; + size_t at_pos = unit_file.find("@"); + if (at_pos == std::string::npos) { + fprintf(stderr, "Invalid unit file %s for instance %d\n", unit_file.c_str(), instance); + return ""; } - /*** - suffix is "@.service", set suffix=".service" - prefix_len is length of "example@" - ***/ - prefix_len = ++suffix - unit_file; - ret = asprintf(&instance_name, "%.*s%d%s", prefix_len, unit_file, instance, suffix); - if (ret == -1) { - fprintf(stderr, "Error creating instance %d of %s\n", instance, unit_file); - return NULL; - } - - return instance_name; + return unit_file.substr(0, at_pos + 1) + std::to_string(instance) + unit_file.substr(at_pos + 1); } -static int create_symlink(char* unit, char* target, char* install_dir, int instance) { +static int create_symlink(const std::string& unit, const std::string& target, const std::string& install_dir, int instance) { struct stat st; - char src_path[PATH_MAX]; - char dest_path[PATH_MAX]; - char final_install_dir[PATH_MAX]; - char* unit_instance; + std::string src_path; + std::string dest_path; + std::string final_install_dir; + std::string unit_instance; int r; - strcpy(src_path, get_unit_file_prefix()); - strcat(src_path, unit); + src_path = get_unit_file_prefix() + unit; if (instance < 0) { - unit_instance = strdup(unit); + unit_instance = unit; } else { unit_instance = insert_instance_number(unit, instance); } - strcpy(final_install_dir, install_dir); - strcat(final_install_dir, target); - strcpy(dest_path, final_install_dir); - strcat(dest_path, "/"); - strcat(dest_path, unit_instance); - - free(unit_instance); + final_install_dir = install_dir + std::string(target); + dest_path = final_install_dir + "/" + unit_instance; - if (stat(final_install_dir, &st) == -1) { + if (stat(final_install_dir.c_str(), &st) == -1) { // If doesn't exist, create - r = mkdir(final_install_dir, 0755); + r = mkdir(final_install_dir.c_str(), 0755); if (r == -1) { - fprintf(stderr, "Unable to create target directory %s\n", final_install_dir); + fprintf(stderr, "Unable to create target directory %s\n", final_install_dir.c_str()); return -1; } } else if (S_ISREG(st.st_mode)) { // If is regular file, remove and create - r = remove(final_install_dir); + r = remove(final_install_dir.c_str()); if (r == -1) { - fprintf(stderr, "Unable to remove file with same name as target directory %s\n", final_install_dir); + fprintf(stderr, "Unable to remove file with same name as target directory %s\n", final_install_dir.c_str()); return -1; } - r = mkdir(final_install_dir, 0755); + r = mkdir(final_install_dir.c_str(), 0755); if (r == -1) { - fprintf(stderr, "Unable to create target directory %s\n", final_install_dir); + fprintf(stderr, "Unable to create target directory %s\n", final_install_dir.c_str()); return -1; } } else if (S_ISDIR(st.st_mode)) { // If directory, verify correct permissions - r = chmod(final_install_dir, 0755); + r = chmod(final_install_dir.c_str(), 0755); if (r == -1) { - fprintf(stderr, "Unable to change permissions of existing target directory %s\n", final_install_dir); + fprintf(stderr, "Unable to change permissions of existing target directory %s\n", final_install_dir.c_str()); return -1; } } - r = symlink(src_path, dest_path); + r = symlink(src_path.c_str(), dest_path.c_str()); if (r < 0) { if (errno == EEXIST) return 0; - fprintf(stderr, "Error creating symlink %s from source %s\n", dest_path, src_path); + fprintf(stderr, "Error creating symlink %s from source %s\n", dest_path.c_str(), src_path.c_str()); return -1; } @@ -476,7 +461,7 @@ static int create_symlink(char* unit, char* target, char* install_dir, int insta } -static int install_unit_file(char* unit_file, char* target, char* install_dir) { +static int install_unit_file(std::string unit_file, std::string target, std::string install_dir) { /*** Creates a symlink for a unit file installation @@ -487,38 +472,34 @@ static int install_unit_file(char* unit_file, char* target, char* install_dir) { If a multi ASIC platform is detected, enables multi-instance services as well ***/ - char* target_instance; - char* prefix; - char* suffix; + std::string target_instance; int r; - assert(unit_file); - assert(target); - + if (unit_file.empty() || target.empty() || install_dir.empty()){ + fprintf(stderr, "Invalid unit file, target or install directory\n"); + exit(EXIT_FAILURE); + } - if ((num_asics > 1) && strstr(unit_file, "@") != NULL) { + if ((num_asics > 1) && unit_file.find("@") != std::string::npos) { for (int i = 0; i < num_asics; i++) { - if (strstr(target, "@") != NULL) { + if (target.find("@") != std::string::npos) { target_instance = insert_instance_number(target, i); } else { - target_instance = strdup(target); + target_instance = target; } r = create_symlink(unit_file, target_instance, install_dir, i); if (r < 0) - fprintf(stderr, "Error installing %s for target %s\n", unit_file, target_instance); - - free(target_instance); - + fprintf(stderr, "Error installing %s for target %s\n", unit_file.c_str(), target_instance.c_str()); } } else { r = create_symlink(unit_file, target, install_dir, -1); if (r < 0) - fprintf(stderr, "Error installing %s for target %s\n", unit_file, target); + fprintf(stderr, "Error installing %s for target %s\n", unit_file.c_str(), target.c_str()); } return 0; @@ -531,12 +512,10 @@ int get_num_of_asic() { ***/ FILE *fp; char *line = NULL; - char* token; - char* platform; + char* platform = NULL; char* saveptr; size_t len = 0; ssize_t nread; - bool ans; char asic_file[512]; char* str_num_asic; int num_asic = 1; @@ -552,7 +531,7 @@ int get_num_of_asic() { while ((nread = getline(&line, &len, fp)) != -1) { if ((strstr(line, "onie_platform") != NULL) || (strstr(line, "aboot_platform") != NULL)) { - token = strtok_r(line, "=", &saveptr); + strtok_r(line, "=", &saveptr); platform = strtok_r(NULL, "=", &saveptr); strip_trailing_newline(platform); break; @@ -565,7 +544,7 @@ int get_num_of_asic() { if (fp != NULL) { while ((nread = getline(&line, &len, fp)) != -1) { if (strstr(line, "NUM_ASIC") != NULL) { - token = strtok_r(line, "=", &saveptr); + strtok_r(line, "=", &saveptr); str_num_asic = strtok_r(NULL, "=", &saveptr); strip_trailing_newline(str_num_asic); if (str_num_asic != NULL){ @@ -584,15 +563,13 @@ int get_num_of_asic() { int ssg_main(int argc, char **argv) { char* unit_files[MAX_NUM_UNITS]; - char install_dir[PATH_MAX]; + std::string install_dir; char* targets[MAX_NUM_TARGETS]; - char* unit_instance; - char* prefix; - char* suffix; - char* saveptr; + std::string unit_instance; + std::string prefix; + std::string suffix; int num_unit_files; int num_targets; - int r; if (argc <= 1) { fputs("Installation directory required as argument\n", stderr); @@ -600,40 +577,33 @@ int ssg_main(int argc, char **argv) { } num_asics = get_num_of_asic(); - strcpy(install_dir, argv[1]); - strcat(install_dir, "/"); + install_dir = std::string(argv[1]) + "/"; num_unit_files = get_unit_files(unit_files); // 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]); - if ((num_asics == 1) && strstr(unit_instance, "@") != NULL) { - prefix = strdup(strtok_r(unit_instance, "@", &saveptr)); - suffix = strdup(strtok_r(NULL, "@", &saveptr)); - - strcpy(unit_instance, prefix); - strcat(unit_instance, suffix); + unit_instance = unit_files[i]; + if ((num_asics == 1 && unit_instance.find("@") != std::string::npos)) { + prefix = unit_instance.substr(0, unit_instance.find("@")); + suffix = unit_instance.substr(unit_instance.find("@") + 1); - free(prefix); - free(suffix); + unit_instance = prefix + suffix; } num_targets = get_install_targets(unit_instance, targets); if (num_targets < 0) { - fprintf(stderr, "Error parsing %s\n", unit_instance); - free(unit_instance); + fprintf(stderr, "Error parsing %s\n", unit_instance.c_str()); free(unit_files[i]); continue; } for (int j = 0; j < num_targets; j++) { if (install_unit_file(unit_instance, targets[j], install_dir) != 0) - fprintf(stderr, "Error installing %s to target directory %s\n", unit_instance, targets[j]); + fprintf(stderr, "Error installing %s to target directory %s\n", unit_instance.c_str(), targets[j]); free(targets[j]); } - free(unit_instance); free(unit_files[i]); } diff --git a/src/systemd-sonic-generator/systemd-sonic-generator.h b/src/systemd-sonic-generator/systemd-sonic-generator.h index 25c179caa0bf..febbda092760 100644 --- a/src/systemd-sonic-generator/systemd-sonic-generator.h +++ b/src/systemd-sonic-generator/systemd-sonic-generator.h @@ -6,9 +6,11 @@ * Copyright (c) 2021 by Cisco Systems, Inc. *------------------------------------------------------------------ */ -#ifdef __cplusplus -extern "C" { -#endif +// #ifdef __cplusplus +// extern "C" { +// #endif +#include +#include /* expose global vars for testing purpose */ extern const char* UNIT_FILE_PREFIX; @@ -25,11 +27,11 @@ extern const char* get_unit_file_prefix(); extern const char* get_config_file(); extern const char* get_machine_config_file(); extern const char* get_asic_conf_format(); -extern char* insert_instance_number(char* unit_file, int instance); +extern std::string insert_instance_number(const std::string& unit_file, int instance); extern int ssg_main(int argc, char** argv); extern int get_num_of_asic(); -extern int get_install_targets(char* unit_file, char* targets[]); +extern int get_install_targets(std::string unit_file, char* targets[]); extern int get_unit_files(char* unit_files[]); -#ifdef __cplusplus -} -#endif +// #ifdef __cplusplus +// } +// #endif