diff --git a/.artifactignore b/.artifactignore index 9f327601071..5af70cce642 100644 --- a/.artifactignore +++ b/.artifactignore @@ -2,3 +2,11 @@ !target/*.bin !target/*.log !target/*.img.gz +!target/docker-sonic-vs.gz +!target/docker-ptf.gz +!target/debs/**/*.deb +!target/debs/**/*.deb.log +!target/debs/**/*.deb-install.log +!target/python-wheels/*.whl +!target/python-wheels/*.whl.log +!target/python-wheels/*.whl-install.log diff --git a/.azure-pipelines/build-template.yml b/.azure-pipelines/build-template.yml new file mode 100644 index 00000000000..55b5e4d26a7 --- /dev/null +++ b/.azure-pipelines/build-template.yml @@ -0,0 +1,103 @@ +parameters: +- name: platform + type: string + values: + - broadcom + - mellanox + - marvell-armhf + - centec-arm64 + +- name: platform_arch + type: string + values: + - amd64 + - armhf + - arm64 + default: amd64 + +- name: platform_short + type: string + values: + - brcm + - mlnx + - marvell-armhf + - centec-arm64 + +- name: cache_mode + type: string + values: + - wcache + - rcache + - cache + +- name: pool + type: string + values: + - sonicbld + - sonicbld_8c + default: sonicbld + +- name: dbg_image + type: boolean + default: false + +- name: swi_image + type: boolean + default: false + +- name: raw_image + type: boolean + default: false + +- name: sync_rpc_image + type: boolean + default: false + +- name: timeout + type: number + default: 600 + +jobs: +- job: + pool: ${{ parameters.pool }} + displayName: ${{ parameters.platform }} + timeoutInMinutes: ${{ parameters.timeout }} + steps: + - template: cleanup.yml + - checkout: self + clean: true + submodules: recursive + displayName: 'Checkout code' + - script: | + git submodule foreach --recursive 'git clean -xfdf || true' + git submodule foreach --recursive 'git reset --hard || true' + git submodule foreach --recursive 'git remote update || true' + git submodule update --init --recursive + displayName: 'Reset submodules' + - script: | + set -e + sudo modprobe overlay + sudo apt-get install -y acl + export DOCKER_DATA_ROOT_FOR_MULTIARCH=/data/march/docker + CACHE_OPTIONS="SONIC_DPKG_CACHE_METHOD=${{ parameters.cache_mode }} SONIC_DPKG_CACHE_SOURCE=/nfs/dpkg_cache/${{ parameters.platform }}" + ENABLE_DOCKER_BASE_PULL=y make configure PLATFORM=${{ parameters.platform }} PLATFORM_ARCH=${{ parameters.platform_arch }} + trap "sudo rm -rf fsroot" EXIT + if [ ${{ parameters.dbg_image }} == true ];then + make USERNAME=admin $CACHE_OPTIONS SONIC_BUILD_JOBS=$(nproc) INSTALL_DEBUG_TOOLS=y target/sonic-${{ parameters.platform }}.bin && \ + mv target/sonic-${{ parameters.platform }}.bin target/sonic-${{ parameters.platform }}-dbg.bin + fi + if [ ${{ parameters.swi_image }} == true ];then + make USERNAME=admin $CACHE_OPTIONS SONIC_BUILD_JOBS=$(nproc) ENABLE_IMAGE_SIGNATURE=y target/sonic-aboot-${{ parameters.platform }}.swi + fi + if [ ${{ parameters.raw_image }} == true ];then + make USERNAME=admin $CACHE_OPTIONS SONIC_BUILD_JOBS=$(nproc) target/sonic-${{ parameters.platform }}.raw + fi + if [ ${{ parameters.sync_rpc_image }} == true ];then + make USERNAME=admin $CACHE_OPTIONS SONIC_BUILD_JOBS=$(nproc) ENABLE_SYNCD_RPC=y target/docker-syncd-${{ parameters.platform_short }}-rpc.gz + fi + make USERNAME=admin $CACHE_OPTIONS SONIC_BUILD_JOBS=$(nproc) target/sonic-${{ parameters.platform }}.bin + displayName: 'Build sonic image' + - publish: $(System.DefaultWorkingDirectory)/ + artifact: sonic-buildimage.${{ parameters.platform }} + displayName: "Archive sonic image" + - template: cleanup.yml diff --git a/.azure-pipelines/cleanup.yml b/.azure-pipelines/cleanup.yml new file mode 100644 index 00000000000..409af73da12 --- /dev/null +++ b/.azure-pipelines/cleanup.yml @@ -0,0 +1,15 @@ +steps: +- script: | + if sudo [ -f /var/run/march/docker.pid ] ; then + pid=`sudo cat /var/run/march/docker.pid` ; sudo kill $pid + fi + sudo rm -f /var/run/march/docker.pid + sudo rm -rf /data/march/docker + + # clean native docker build + if sudo [ -f dockerfs/var/run/docker.pid ] ; then + pid=`sudo cat dockerfs/var/run/docker.pid` ; sudo kill $pid + fi + sudo rm -rf dockerfs + sudo rm -rf fsroot + displayName: "Clean Workspace" diff --git a/.azure-pipelines/official-build.yml b/.azure-pipelines/official-build.yml new file mode 100644 index 00000000000..519b7fa5ef0 --- /dev/null +++ b/.azure-pipelines/official-build.yml @@ -0,0 +1,47 @@ +# Starter pipeline +# Start with a minimal pipeline that you can customize to build and deploy your code. +# Add steps that build, run tests, deploy, and more: +# https://aka.ms/yaml + +schedules: +- cron: "0 8 * * *" + displayName: Daily midnight build + branches: + include: + - master + always: true + +trigger: none +pr: none + +stages: +- stage: Build + + jobs: + - template: build-template.yml + parameters: + platform: broadcom + platform_short: brcm + cache_mode: wcache + dbg_image: true + swi_image: true + raw_image: true + sync_rpc_image: true + + - template: build-template.yml + parameters: + timeout: 3600 + platform: marvell-armhf + platform_arch: armhf + platform_short: marvell-armhf + cache_mode: wcache + pool: sonicbld_8c + + - template: build-template.yml + parameters: + timeout: 3600 + platform: centec-arm64 + platform_arch: arm64 + platform_short: centec-arm64 + cache_mode: wcache + pool: sonicbld_8c diff --git a/.azure-pipelines/run-test-template.yml b/.azure-pipelines/run-test-template.yml new file mode 100644 index 00000000000..cabee8f34d3 --- /dev/null +++ b/.azure-pipelines/run-test-template.yml @@ -0,0 +1,82 @@ +parameters: +- name: dut + type: string +- name: tbname + type: string +- name: tbtype + type: string +- name: ptf_name + type: string + +steps: +- checkout: self + clean: true + displayName: 'checkout sonic-mgmt repo' + +- task: DownloadPipelineArtifact@2 + inputs: + artifact: sonic-buildimage.kvm + displayName: "Download sonic-buildimage.kvm artifact" + +- script: | + set -x + sudo mkdir -p /data/sonic-vm/images + sudo cp -v ../target/sonic-vs.img.gz /data/sonic-vm/images/sonic-vs.img.gz + sudo gzip -fd /data/sonic-vm/images/sonic-vs.img.gz + username=$(id -un) + sudo chown -R $username.$username /data/sonic-vm + + pushd /data/sonic-mgmt + git remote update + git reset --hard origin/master + sed -i s/use_own_value/${username}/ ansible/veos_vtb + echo aaa > ansible/password.txt + docker exec sonic-mgmt bash -c "pushd /data/sonic-mgmt/ansible;./testbed-cli.sh -d /data/sonic-vm -m $(inventory) -t $(testbed_file) -k ceos refresh-dut ${{ parameters.tbname }} password.txt" && sleep 180 + displayName: "Setup testbed" + +- script: | + rm -rf $(Build.ArtifactStagingDirectory)/* + docker exec sonic-mgmt bash -c "/data/sonic-mgmt/tests/kvmtest.sh -en -T ${{ parameters.tbtype }} ${{ parameters.tbname }} ${{ parameters.dut }}" + displayName: "Run tests" + +- script: | + # save dut state if test fails + virsh_version=$(virsh --version) + if [ $virsh_version == "6.0.0" ]; then + mkdir -p $(Build.ArtifactStagingDirectory)/kvmdump + virsh -c qemu:///system list + virsh -c qemu:///system save ${{ parameters.dut }} $(Build.ArtifactStagingDirectory)/kvmdump/${{ parameters.dut }}.memdmp + virsh -c qemu:///system dumpxml ${{ parameters.dut }} > $(Build.ArtifactStagingDirectory)/kvmdump/${{ parameters.dut }}.xml + img=$(virsh -c qemu:///system domblklist ${{ parameters.dut }} | grep vda | awk '{print $2}') + cp $img $(Build.ArtifactStagingDirectory)/kvmdump/${{ parameters.dut }}.img + virsh -c qemu:///system undefine ${{ parameters.dut }} + fi + + docker commit ${{ parameters.ptf_name }} docker-ptf:$(Build.BuildNumber) + docker save docker-ptf:$(Build.BuildNumber) | gzip -c > $(Build.ArtifactStagingDirectory)/kvmdump/docker-ptf-dump.gz + docker rmi docker-ptf:$(Build.BuildNumber) + displayName: "Collect kvmdump" + condition: failed() + +- script: | + cp -r /data/sonic-mgmt/tests/logs $(Build.ArtifactStagingDirectory)/ + username=$(id -un) + sudo chown -R $username.$username $(Build.ArtifactStagingDirectory) + displayName: "Collect test logs" + condition: succeededOrFailed() + +- publish: $(Build.ArtifactStagingDirectory)/kvmdump + artifact: sonic-buildimage.kvmtest.${{ parameters.tbtype}}.memdump@$(System.JobAttempt) + displayName: "Archive sonic kvm memdump" + condition: failed() + +- publish: $(Build.ArtifactStagingDirectory)/logs + artifact: sonic-buildimage.kvmtest.${{ parameters.tbtype }}.log@$(System.JobAttempt) + displayName: "Archive sonic kvm logs" + condition: succeededOrFailed() + +- task: PublishTestResults@2 + inputs: + testResultsFiles: '$(Build.ArtifactStagingDirectory)/logs/**/*.xml' + testRunTitle: kvmtest.${{ parameters.tbtype }} + condition: succeededOrFailed() diff --git a/.github/CODEOWNERS b/.github/CODEOWNERS new file mode 100644 index 00000000000..8790ea4efd6 --- /dev/null +++ b/.github/CODEOWNERS @@ -0,0 +1,35 @@ +# This is a comment. +# Each line is a file pattern followed by one or more owners. + +# rules are explained here +# https://docs.github.com/en/github/creating-cloning-and-archiving-repositories/about-code-owners + +# These owners will be the default owners for everything in +# the repo. Unless a later match takes precedence, +# @lguohan will be requested for review when someone opens +# a pull request. +* @lguohan + +/device/ @jleveque + +# build +/rules/ @qiluo-msft @xumia @lguohan +/Makefile @qiluo-msft @xumia @lguohan +/Makefile.cache @qiluo-msft @xumia @lguohan +/Makefile.work @qiluo-msft @xumia @lguohan +/slave.mk @qiluo-msft @xumia @lguohan +/scripts @qiluo-msft @xumia @lguohan + +# installer +/installer/ @qiluo-msft + +# permission +/files/image_config/sudoers/ @qiluo-msft + +# dockers +/dockers/docker-base*/ @qiluo-msft +/dockers/docker-config-engine*/ @qiluo-msft +/dockers/docker-snmp/ @qiluo-msft + +# src +/src/initramfs-tools/ @qiluo-msft diff --git a/Makefile.work b/Makefile.work index 0d7f62af391..654ccb660eb 100644 --- a/Makefile.work +++ b/Makefile.work @@ -114,7 +114,7 @@ $(shell CONFIGURED_ARCH=$(CONFIGURED_ARCH) j2 $(SLAVE_DIR)/Dockerfile.user.j2 > $(shell BUILD_SLAVE=y scripts/prepare_docker_buildinfo.sh $(SLAVE_BASE_IMAGE) $(SLAVE_DIR)/Dockerfile $(CONFIGURED_ARCH) "" $(BLDENV)) # Add the versions in the tag, if the version change, need to rebuild the slave -SLAVE_BASE_TAG = $(shell cat $(SLAVE_DIR)/Dockerfile $(SLAVE_DIR)/buildinfo/versions/versions-* | sha1sum | awk '{print substr($$1,0,11);}') +SLAVE_BASE_TAG = $(shell cat $(SLAVE_DIR)/Dockerfile $(SLAVE_DIR)/buildinfo/versions/versions-* src/sonic-build-hooks/hooks/* | sha1sum | awk '{print substr($$1,0,11);}') SLAVE_TAG = $(shell cat $(SLAVE_DIR)/Dockerfile.user $(SLAVE_DIR)/Dockerfile $(SLAVE_DIR)/buildinfo/versions/versions-* | sha1sum | awk '{print substr($$1,0,11);}') OVERLAY_MODULE_CHECK := \ @@ -246,6 +246,7 @@ SONIC_BUILD_INSTRUCTION := make \ EXTRA_DOCKER_TARGETS=$(EXTRA_DOCKER_TARGETS) \ BUILD_LOG_TIMESTAMP=$(BUILD_LOG_TIMESTAMP) \ SONIC_ENABLE_IMAGE_SIGNATURE=$(ENABLE_IMAGE_SIGNATURE) \ + ENABLE_HOST_SERVICE_ON_START=$(ENABLE_HOST_SERVICE_ON_START) \ SLAVE_DIR=$(SLAVE_DIR) \ $(SONIC_OVERRIDE_BUILD_VARS) diff --git a/azure-pipelines.yml b/azure-pipelines.yml index 8ba75bd8687..31533d21686 100644 --- a/azure-pipelines.yml +++ b/azure-pipelines.yml @@ -4,10 +4,21 @@ # https://aka.ms/yaml trigger: -- main + branches: + include: + - master + - 202012 + paths: + exclude: + - .github pr: -- master + branches: + include: + - master + paths: + exclude: + - .github name: $(TeamProject)_$(Build.DefinitionName)_$(SourceBranchName)_$(Date:yyyyMMdd)$(Rev:.r) @@ -23,126 +34,129 @@ stages: pool: sonicbld jobs: - - job: - displayName: "broadcom" - timeoutInMinutes: 600 - steps: - - checkout: self - submodules: recursive - displayName: 'Checkout code' - - - script: | - sudo modprobe overlay - CACHE_OPTIONS="SONIC_DPKG_CACHE_METHOD=rcache SONIC_DPKG_CACHE_SOURCE=/nfs/dpkg_cache/broadcom" - ENABLE_DOCKER_BASE_PULL=y make configure PLATFORM=broadcom - trap "sudo rm -rf fsroot" EXIT - make USERNAME=admin SONIC_BUILD_JOBS=$(nproc) $CACHE_OPTIONS target/sonic-broadcom.bin - displayName: 'Build sonic image' - - publish: $(System.DefaultWorkingDirectory)/ - artifact: sonic-buildimage.broadcom - displayName: "Archive sonic image" - - - job: - displayName: "mellanox" - timeoutInMinutes: 600 - steps: - - checkout: self - submodules: recursive - displayName: 'Checkout code' - - - script: | - sudo modprobe overlay - CACHE_OPTIONS="SONIC_DPKG_CACHE_METHOD=rcache SONIC_DPKG_CACHE_SOURCE=/nfs/dpkg_cache/mellanox" - ENABLE_DOCKER_BASE_PULL=y make configure PLATFORM=mellanox - trap "sudo rm -rf fsroot" EXIT - make USERNAME=admin SONIC_BUILD_JOBS=$(nproc) $CACHE_OPTIONS target/sonic-mellanox.bin - displayName: 'Build sonic image' - - publish: $(System.DefaultWorkingDirectory)/ - artifact: sonic-buildimage.mellanox - displayName: "Archive sonic image" + - template: .azure-pipelines/build-template.yml + parameters: + platform: broadcom + platform_short: brcm + cache_mode: rcache + sync_rpc_image: true + + - template: .azure-pipelines/build-template.yml + parameters: + platform: mellanox + platform_short: mlnx + cache_mode: rcache + sync_rpc_image: true - job: displayName: "kvm" timeoutInMinutes: 600 steps: + - script: | + sudo rm -rf fsroot + username=$(id -un) + sudo chown -R ${username}.${username} . + displayName: 'Cleanup' - checkout: self + clean: true submodules: recursive displayName: 'Checkout code' + - script: | + git submodule foreach --recursive git clean -xfdf + git submodule foreach --recursive git reset --hard + git submodule update --init --recursive + displayName: 'reset submodules' - script: | echo $(Build.BuildNumber) sudo modprobe overlay CACHE_OPTIONS="SONIC_DPKG_CACHE_METHOD=rcache SONIC_DPKG_CACHE_SOURCE=/nfs/dpkg_cache/vs" ENABLE_DOCKER_BASE_PULL=y make configure PLATFORM=vs trap "sudo rm -rf fsroot" EXIT - make USERNAME=admin SONIC_BUILD_JOBS=$(nproc) $CACHE_OPTIONS target/sonic-vs.img.gz && \ - sudo cp target/sonic-vs.img.gz /nfs/azpl/kvmimage/sonic-vs.$(Build.BuildNumber).img.gz + make USERNAME=admin SONIC_BUILD_JOBS=$(nproc) $CACHE_OPTIONS \ + target/docker-sonic-vs.gz target/sonic-vs.img.gz target/docker-ptf.gz displayName: 'Build sonic image' - publish: $(System.DefaultWorkingDirectory)/ artifact: sonic-buildimage.kvm displayName: "Archive sonic image" - stage: Test - pool: sonictest variables: - - name: dut - value: vlab-01 - - name: tbname - value: vms-kvm-t0 - name: inventory value: veos_vtb - name: testbed_file value: vtestbed.csv - - name: ptf_name - value: ptf_vms6-1 jobs: - job: - displayName: "kvmtest" - timeoutInMinutes: 240 + pool: sonictest + displayName: "vstest" + timeoutInMinutes: 60 steps: + - checkout: self + clean: true + submodules: recursive + displayName: 'Checkout code' + + - task: DownloadPipelineArtifact@2 + inputs: + source: specific + project: build + pipeline: 9 + artifacts: sonic-swss-common.amd64.ubuntu20_04 + runVersion: 'latestFromBranch' + runBranch: 'refs/heads/master' + displayName: "Download sonic swss common deb packages" + + - task: DownloadPipelineArtifact@2 + inputs: + artifact: sonic-buildimage.kvm + displayName: "Download sonic-buildimage.kvm artifact" + - script: | - sudo mkdir -p /data/sonic-vm/images - sudo cp -v /nfs/azpl/kvmimage/sonic-vs.$(Build.BuildNumber).img.gz /data/sonic-vm/images/sonic-vs.img.gz - sudo gzip -fd /data/sonic-vm/images/sonic-vs.img.gz - username=$(id -un) - sudo chown -R $username.$username /data/sonic-vm - pushd /data/sonic-mgmt - git remote update - git reset --hard origin/master - sed -i s/use_own_value/${username}/ ansible/veos_vtb - echo aaa > ansible/password.txt - docker exec sonic-mgmt bash -c "pushd /data/sonic-mgmt/ansible;./testbed-cli.sh -d /data/sonic-vm -m $(inventory) -t $(testbed_file) refresh-dut $(tbname) password.txt" && sleep 180 - displayName: "Setup T0 testbed" - - script: | - pwd + set -x + sudo dpkg -i --force-confask,confnew ../sonic-swss-common.amd64.ubuntu20_04/libswsscommon_1.0.0_amd64.deb + sudo dpkg -i ../sonic-swss-common.amd64.ubuntu20_04/python3-swsscommon_1.0.0_amd64.deb + sudo docker load -i ../target/docker-sonic-vs.gz + docker tag docker-sonic-vs:latest docker-sonic-vs:$(Build.BuildNumber) username=$(id -un) - docker exec sonic-mgmt bash -c "/data/sonic-mgmt/tests/kvmtest.sh -en $(tbname) $(dut)" - - # save dut state if test fails - if [ $? != 0 ]; then - virsh_version=$(virsh --version) - if [ $virsh_version == "6.0.0" ]; then - rm -rf kvmdump - mkdir -p kvmdump - virsh -c qemu:///system list - virsh -c qemu:///system save $(dut) kvmdump/$(dut).memdmp - virsh -c qemu:///system dumpxml $(dut) > kvmdump/$(dut).xml - img=$(virsh -c qemu:///system domblklist $(dut) | grep vda | awk '{print $2}') - cp $img kvmdump/$(dut).img - sudo chown -R $username.$username kvmdump - virsh -c qemu:///system undefine $(dut) - fi - - rm -rf ptfdump - mkdir -p ptfdump - docker commit $(ptf_name) docker-ptf:$(Build.BuildNumber) - docker save docker-ptf:$(Build.BuildNumber) | gzip -c > ptfdump/docker-ptf-dump.gz - docker rmi docker-ptf:$(Build.BuildNumber) - - exit 2 - else - sudo rm /nfs/azpl/kvmimage/sonic-vs.$(Build.BuildNumber).img.gz - fi - displayName: "Run T0 tests" + trap "docker ps; docker images; ip netns list; \ + docker rmi docker-sonic-vs:$(Build.BuildNumber); \ + ip netns list | grep -E [-]srv[0-9]+ | awk '{print $1}' | xargs -I {} sudo ip netns delete {}; \ + sudo chown -R ${username}.${username} .; \ + sudo chown -R ${username}.${username} $(System.DefaultWorkingDirectory)" EXIT + pushd platform/vs/tests + sudo py.test -v --junitxml=tr.xml --imgname=docker-sonic-vs:$(Build.BuildNumber) + displayName: "Run vs tests" + + - task: PublishTestResults@2 + inputs: + testResultsFiles: '**/tr.xml' + testRunTitle: vstest + + - job: + pool: sonictest + displayName: "kvmtest-t0" + timeoutInMinutes: 240 + + steps: + - template: .azure-pipelines/run-test-template.yml + parameters: + dut: vlab-01 + tbname: vms-kvm-t0 + ptf_name: ptf_vms6-1 + tbtype: t0 + + - job: + pool: sonictest-t1-lag + displayName: "kvmtest-t1-lag" + timeoutInMinutes: 240 + + steps: + - template: .azure-pipelines/run-test-template.yml + parameters: + dut: vlab-03 + tbname: vms-kvm-t1-lag + ptf_name: ptf_vms6-2 + tbtype: t1-lag diff --git a/build_debian.sh b/build_debian.sh index 4ef993e4ac3..17a5aea4e61 100755 --- a/build_debian.sh +++ b/build_debian.sh @@ -32,7 +32,7 @@ CONFIGURED_ARCH=$([ -f .arch ] && cat .arch || echo amd64) ## docker engine version (with platform) DOCKER_VERSION=5:18.09.8~3-0~debian-$IMAGE_DISTRO -LINUX_KERNEL_VERSION=4.19.0-9-2 +LINUX_KERNEL_VERSION=4.19.0-12-2 ## Working directory to prepare the file system FILESYSTEM_ROOT=./fsroot @@ -214,7 +214,9 @@ else sudo LANG=C chroot $FILESYSTEM_ROOT apt-get -y install docker-ce=${DOCKER_VERSION} fi -sudo LANG=C chroot $FILESYSTEM_ROOT apt-get -y remove software-properties-common gnupg2 +# Uninstall 'python3-gi' installed as part of 'software-properties-common' to remove debian version of 'PyGObject' +# pip version of 'PyGObject' will be installed during installation of 'sonic-host-services' +sudo LANG=C chroot $FILESYSTEM_ROOT apt-get -y remove software-properties-common gnupg2 python3-gi if [ "$INCLUDE_KUBERNETES" == "y" ] then @@ -417,7 +419,7 @@ done < files/image_config/sysctl/sysctl-net.conf sudo augtool --autosave "$sysctl_net_cmd_string" -r $FILESYSTEM_ROOT # Upgrade pip via PyPI and uninstall the Debian version -sudo https_proxy=$https_proxy LANG=C chroot $FILESYSTEM_ROOT pip2 install --upgrade pip +sudo https_proxy=$https_proxy LANG=C chroot $FILESYSTEM_ROOT pip2 install --upgrade 'pip<21' sudo https_proxy=$https_proxy LANG=C chroot $FILESYSTEM_ROOT pip3 install --upgrade pip sudo LANG=C DEBIAN_FRONTEND=noninteractive chroot $FILESYSTEM_ROOT apt-get purge -y python-pip python3-pip @@ -498,13 +500,8 @@ if [ "${enable_organization_extensions}" = "y" ]; then fi fi -## Setup ebtable rules (rule file is in binary format) -sudo cp -f files/image_config/ebtables/ebtables.default $FILESYSTEM_ROOT/etc/default/ebtables -sudo cp -f files/image_config/ebtables/ebtables.init $FILESYSTEM_ROOT/etc/init.d/ebtables -sudo cp -f files/image_config/ebtables/ebtables.service $FILESYSTEM_ROOT/lib/systemd/system/ebtables.service +## Setup ebtable rules (rule file in text format) sudo cp files/image_config/ebtables/ebtables.filter.cfg ${FILESYSTEM_ROOT}/etc -sudo LANG=C chroot $FILESYSTEM_ROOT update-alternatives --set ebtables /usr/sbin/ebtables-legacy -sudo LANG=C chroot $FILESYSTEM_ROOT systemctl enable ebtables.service ## Debug Image specific changes ## Update motd for debug image diff --git a/check_install.py b/check_install.py index 08759db127f..ed0d8018afe 100755 --- a/check_install.py +++ b/check_install.py @@ -58,6 +58,8 @@ def main(): # check version time.sleep(5) + p.sendline('uptime') + p.expect([cmd_prompt]) p.sendline('show version') p.expect([cmd_prompt]) p.sendline('show ip bgp sum') diff --git a/device/accton/x86_64-accton_as4630_54pe-r0/Accton-AS4630-54PE/hx5-as4630-48x1G+4x25G+2x100G.bcm b/device/accton/x86_64-accton_as4630_54pe-r0/Accton-AS4630-54PE/hx5-as4630-48x1G+4x25G+2x100G.bcm index a7f89ba4c62..331f6d00264 100755 --- a/device/accton/x86_64-accton_as4630_54pe-r0/Accton-AS4630-54PE/hx5-as4630-48x1G+4x25G+2x100G.bcm +++ b/device/accton/x86_64-accton_as4630_54pe-r0/Accton-AS4630-54PE/hx5-as4630-48x1G+4x25G+2x100G.bcm @@ -19,7 +19,10 @@ l2_mem_entries=32768 #l3_mem_entries=49152 #fpem_mem_entries=16384 l2xmsg_mode=1 +l3_alpm_enable=2 +ipv6_lpm_128b_enable=1 port_flex_enable=1 +ifp_inports_support_enable=1 #3x PM4x10Q (3 * 16 = 48 physical ports) #Doesn't support oversubscribe in Q mode diff --git a/device/accton/x86_64-accton_as4630_54pe-r0/custom_led.bin b/device/accton/x86_64-accton_as4630_54pe-r0/custom_led.bin index b402867a7d2..0f6e37a8249 100644 Binary files a/device/accton/x86_64-accton_as4630_54pe-r0/custom_led.bin and b/device/accton/x86_64-accton_as4630_54pe-r0/custom_led.bin differ diff --git a/device/accton/x86_64-accton_as7116_54x-r0/sonic_platform/sfp.py b/device/accton/x86_64-accton_as7116_54x-r0/sonic_platform/sfp.py index 9d85b96be73..2006561ffef 100644 --- a/device/accton/x86_64-accton_as7116_54x-r0/sonic_platform/sfp.py +++ b/device/accton/x86_64-accton_as7116_54x-r0/sonic_platform/sfp.py @@ -698,7 +698,7 @@ def get_qsfp_transceiver_bulk_status(self): qsfp_dom_capability_raw = self.__read_eeprom_specific_bytes( (offset_xcvr + XCVR_DOM_CAPABILITY_OFFSET), XCVR_DOM_CAPABILITY_WIDTH) if qsfp_dom_capability_raw is not None: - qspf_dom_capability_data = sfpi_obj.parse_qsfp_dom_capability( + qspf_dom_capability_data = sfpi_obj.parse_dom_capability( qsfp_dom_capability_raw, 0) else: return None diff --git a/device/accton/x86_64-accton_as7326_56x-r0/Accton-AS7326-56X/td3-as7326-48x25G+8x100G.config.bcm b/device/accton/x86_64-accton_as7326_56x-r0/Accton-AS7326-56X/td3-as7326-48x25G+8x100G.config.bcm index 83f614bf093..5da8cd015da 100755 --- a/device/accton/x86_64-accton_as7326_56x-r0/Accton-AS7326-56X/td3-as7326-48x25G+8x100G.config.bcm +++ b/device/accton/x86_64-accton_as7326_56x-r0/Accton-AS7326-56X/td3-as7326-48x25G+8x100G.config.bcm @@ -1,3 +1,4 @@ +sai_load_hw_config=/etc/bcm/flex/bcm56870_a0_issu/b870.6.4.1/ #polarity/lanemap is using TH2 style. core_clock_frequency=1525 dpp_clock_ratio=2:3 diff --git a/device/accton/x86_64-accton_as7726_32x-r0/Accton-AS7726-32X/td3-as7726-32x100G.config.bcm b/device/accton/x86_64-accton_as7726_32x-r0/Accton-AS7726-32X/td3-as7726-32x100G.config.bcm index 8042955fcae..f88656bfd5c 100755 --- a/device/accton/x86_64-accton_as7726_32x-r0/Accton-AS7726-32X/td3-as7726-32x100G.config.bcm +++ b/device/accton/x86_64-accton_as7726_32x-r0/Accton-AS7726-32X/td3-as7726-32x100G.config.bcm @@ -1,3 +1,4 @@ +sai_load_hw_config=/etc/bcm/flex/bcm56870_a0_issu/b870.6.4.1/ #polarity/lanemap is using TH2 style. core_clock_frequency=1525 dpp_clock_ratio=2:3 diff --git a/device/arista/x86_64-arista_7050cx3_32s/Arista-7050CX3-32S-C32/port_config.ini b/device/arista/x86_64-arista_7050cx3_32s/Arista-7050CX3-32S-C32/port_config.ini index d3d339076a5..4b96b8cf87c 100644 --- a/device/arista/x86_64-arista_7050cx3_32s/Arista-7050CX3-32S-C32/port_config.ini +++ b/device/arista/x86_64-arista_7050cx3_32s/Arista-7050CX3-32S-C32/port_config.ini @@ -1,35 +1,35 @@ -# name lanes alias index -Ethernet0 1,2,3,4 Ethernet1/1 1 -Ethernet4 5,6,7,8 Ethernet2/1 2 -Ethernet8 9,10,11,12 Ethernet3/1 3 -Ethernet12 13,14,15,16 Ethernet4/1 4 -Ethernet16 21,22,23,24 Ethernet5/1 5 -Ethernet20 17,18,19,20 Ethernet6/1 6 -Ethernet24 25,26,27,28 Ethernet7/1 7 -Ethernet28 29,30,31,32 Ethernet8/1 8 -Ethernet32 37,38,39,40 Ethernet9/1 9 -Ethernet36 33,34,35,36 Ethernet10/1 10 -Ethernet40 41,42,43,44 Ethernet11/1 11 -Ethernet44 45,46,47,48 Ethernet12/1 12 -Ethernet48 53,54,55,56 Ethernet13/1 13 -Ethernet52 49,50,51,52 Ethernet14/1 14 -Ethernet56 57,58,59,60 Ethernet15/1 15 -Ethernet60 61,62,63,64 Ethernet16/1 16 -Ethernet64 69,70,71,72 Ethernet17/1 17 -Ethernet68 65,66,67,68 Ethernet18/1 18 -Ethernet72 73,74,75,76 Ethernet19/1 19 -Ethernet76 77,78,79,80 Ethernet20/1 20 -Ethernet80 85,86,87,88 Ethernet21/1 21 -Ethernet84 81,82,83,84 Ethernet22/1 22 -Ethernet88 89,90,91,92 Ethernet23/1 23 -Ethernet92 93,94,95,96 Ethernet24/1 24 -Ethernet96 101,102,103,104 Ethernet25/1 25 -Ethernet100 97,98,99,100 Ethernet26/1 26 -Ethernet104 105,106,107,108 Ethernet27/1 27 -Ethernet108 109,110,111,112 Ethernet28/1 28 -Ethernet112 117,118,119,120 Ethernet29/1 29 -Ethernet116 113,114,115,116 Ethernet30/1 30 -Ethernet120 121,122,123,124 Ethernet31/1 31 -Ethernet124 125,126,127,128 Ethernet32/1 32 -Ethernet128 129 Ethernet33 33 -Ethernet132 128 Ethernet34 34 +# name lanes alias index speed +Ethernet0 1,2,3,4 Ethernet1/1 1 100000 +Ethernet4 5,6,7,8 Ethernet2/1 2 100000 +Ethernet8 9,10,11,12 Ethernet3/1 3 100000 +Ethernet12 13,14,15,16 Ethernet4/1 4 100000 +Ethernet16 21,22,23,24 Ethernet5/1 5 100000 +Ethernet20 17,18,19,20 Ethernet6/1 6 100000 +Ethernet24 25,26,27,28 Ethernet7/1 7 100000 +Ethernet28 29,30,31,32 Ethernet8/1 8 100000 +Ethernet32 37,38,39,40 Ethernet9/1 9 100000 +Ethernet36 33,34,35,36 Ethernet10/1 10 100000 +Ethernet40 41,42,43,44 Ethernet11/1 11 100000 +Ethernet44 45,46,47,48 Ethernet12/1 12 100000 +Ethernet48 53,54,55,56 Ethernet13/1 13 100000 +Ethernet52 49,50,51,52 Ethernet14/1 14 100000 +Ethernet56 57,58,59,60 Ethernet15/1 15 100000 +Ethernet60 61,62,63,64 Ethernet16/1 16 100000 +Ethernet64 69,70,71,72 Ethernet17/1 17 100000 +Ethernet68 65,66,67,68 Ethernet18/1 18 100000 +Ethernet72 73,74,75,76 Ethernet19/1 19 100000 +Ethernet76 77,78,79,80 Ethernet20/1 20 100000 +Ethernet80 85,86,87,88 Ethernet21/1 21 100000 +Ethernet84 81,82,83,84 Ethernet22/1 22 100000 +Ethernet88 89,90,91,92 Ethernet23/1 23 100000 +Ethernet92 93,94,95,96 Ethernet24/1 24 100000 +Ethernet96 101,102,103,104 Ethernet25/1 25 100000 +Ethernet100 97,98,99,100 Ethernet26/1 26 100000 +Ethernet104 105,106,107,108 Ethernet27/1 27 100000 +Ethernet108 109,110,111,112 Ethernet28/1 28 100000 +Ethernet112 117,118,119,120 Ethernet29/1 29 100000 +Ethernet116 113,114,115,116 Ethernet30/1 30 100000 +Ethernet120 121,122,123,124 Ethernet31/1 31 100000 +Ethernet124 125,126,127,128 Ethernet32/1 32 100000 +Ethernet128 129 Ethernet33 33 10000 +Ethernet132 128 Ethernet34 34 10000 diff --git a/device/arista/x86_64-arista_7050cx3_32s/Arista-7050CX3-32S-C32/td3-a7050cx3-32s-32x100G.config.bcm b/device/arista/x86_64-arista_7050cx3_32s/Arista-7050CX3-32S-C32/td3-a7050cx3-32s-32x100G.config.bcm index 09354d6fd8e..c3b35020487 100644 --- a/device/arista/x86_64-arista_7050cx3_32s/Arista-7050CX3-32S-C32/td3-a7050cx3-32s-32x100G.config.bcm +++ b/device/arista/x86_64-arista_7050cx3_32s/Arista-7050CX3-32S-C32/td3-a7050cx3-32s-32x100G.config.bcm @@ -1,3 +1,13 @@ +sai_load_hw_config=/etc/bcm/flex/bcm56870_a0_issu/b870.6.4.1/ +host_as_route_disable=1 +use_all_splithorizon_groups=1 +riot_enable=1 +sai_tunnel_support=1 +riot_overlay_l3_intf_mem_size=4096 +riot_overlay_l3_egress_mem_size=32768 +l3_ecmp_levels=3 +riot_overlay_ecmp_resilient_hash_size=16384 +flow_init_mode=1 arl_clean_timeout_usec=15000000 asf_mem_profile=2 bcm_num_cos=10 diff --git a/device/arista/x86_64-arista_7050cx3_32s/Arista-7050CX3-32S-D48C8/td3-a7050cx3-32s-48x50G+8x100G.config.bcm b/device/arista/x86_64-arista_7050cx3_32s/Arista-7050CX3-32S-D48C8/td3-a7050cx3-32s-48x50G+8x100G.config.bcm index 2b7da96358d..1b5b7e33870 100644 --- a/device/arista/x86_64-arista_7050cx3_32s/Arista-7050CX3-32S-D48C8/td3-a7050cx3-32s-48x50G+8x100G.config.bcm +++ b/device/arista/x86_64-arista_7050cx3_32s/Arista-7050CX3-32S-D48C8/td3-a7050cx3-32s-48x50G+8x100G.config.bcm @@ -1,3 +1,13 @@ +sai_load_hw_config=/etc/bcm/flex/bcm56870_a0_issu/b870.6.4.1/ +host_as_route_disable=1 +use_all_splithorizon_groups=1 +riot_enable=1 +sai_tunnel_support=1 +riot_overlay_l3_intf_mem_size=4096 +riot_overlay_l3_egress_mem_size=32768 +l3_ecmp_levels=3 +riot_overlay_ecmp_resilient_hash_size=16384 +flow_init_mode=1 arl_clean_timeout_usec=15000000 asf_mem_profile=2 bcm_num_cos=8 diff --git a/device/barefoot/x86_64-accton_wedge100bf_32x-r0/montara/hwsku.json b/device/barefoot/x86_64-accton_wedge100bf_32x-r0/montara/hwsku.json new file mode 100644 index 00000000000..a253fa3bd48 --- /dev/null +++ b/device/barefoot/x86_64-accton_wedge100bf_32x-r0/montara/hwsku.json @@ -0,0 +1,164 @@ +{ + "interfaces": { + "Ethernet0": { + "default_brkout_mode": "1x100G[40G]", + "autoneg": "0", + "fec": "rs" + }, + "Ethernet4": { + "default_brkout_mode": "1x100G[40G]", + "autoneg": "0", + "fec": "rs" + }, + "Ethernet8": { + "default_brkout_mode": "1x100G[40G]", + "autoneg": "0", + "fec": "rs" + }, + "Ethernet12": { + "default_brkout_mode": "1x100G[40G]", + "autoneg": "0", + "fec": "rs" + }, + "Ethernet16": { + "default_brkout_mode": "1x100G[40G]", + "autoneg": "0", + "fec": "rs" + }, + "Ethernet20": { + "default_brkout_mode": "1x100G[40G]", + "autoneg": "0", + "fec": "rs" + }, + "Ethernet24": { + "default_brkout_mode": "1x100G[40G]", + "autoneg": "0", + "fec": "rs" + }, + "Ethernet28": { + "default_brkout_mode": "1x100G[40G]", + "autoneg": "0", + "fec": "rs" + }, + "Ethernet32": { + "default_brkout_mode": "1x100G[40G]", + "autoneg": "0", + "fec": "rs" + }, + "Ethernet36": { + "default_brkout_mode": "1x100G[40G]", + "autoneg": "0", + "fec": "rs" + }, + "Ethernet40": { + "default_brkout_mode": "1x100G[40G]", + "autoneg": "0", + "fec": "rs" + }, + "Ethernet44": { + "default_brkout_mode": "1x100G[40G]", + "autoneg": "0", + "fec": "rs" + }, + "Ethernet48": { + "default_brkout_mode": "1x100G[40G]", + "autoneg": "0", + "fec": "rs" + }, + "Ethernet52": { + "default_brkout_mode": "1x100G[40G]", + "autoneg": "0", + "fec": "rs" + }, + "Ethernet56": { + "default_brkout_mode": "1x100G[40G]", + "autoneg": "0", + "fec": "rs" + }, + "Ethernet60": { + "default_brkout_mode": "1x100G[40G]", + "autoneg": "0", + "fec": "rs" + }, + "Ethernet64": { + "default_brkout_mode": "1x100G[40G]", + "autoneg": "0", + "fec": "rs" + }, + "Ethernet68": { + "default_brkout_mode": "1x100G[40G]", + "autoneg": "0", + "fec": "rs" + }, + "Ethernet72": { + "default_brkout_mode": "1x100G[40G]", + "autoneg": "0", + "fec": "rs" + }, + "Ethernet76": { + "default_brkout_mode": "1x100G[40G]", + "autoneg": "0", + "fec": "rs" + }, + "Ethernet80": { + "default_brkout_mode": "1x100G[40G]", + "autoneg": "0", + "fec": "rs" + }, + "Ethernet84": { + "default_brkout_mode": "1x100G[40G]", + "autoneg": "0", + "fec": "rs" + }, + "Ethernet88": { + "default_brkout_mode": "1x100G[40G]", + "autoneg": "0", + "fec": "rs" + }, + "Ethernet92": { + "default_brkout_mode": "1x100G[40G]", + "autoneg": "0", + "fec": "rs" + }, + "Ethernet96": { + "default_brkout_mode": "1x100G[40G]", + "autoneg": "0", + "fec": "rs" + }, + "Ethernet100": { + "default_brkout_mode": "1x100G[40G]", + "autoneg": "0", + "fec": "rs" + }, + "Ethernet104": { + "default_brkout_mode": "1x100G[40G]", + "autoneg": "0", + "fec": "rs" + }, + "Ethernet108": { + "default_brkout_mode": "1x100G[40G]", + "autoneg": "0", + "fec": "rs" + }, + "Ethernet112": { + "default_brkout_mode": "1x100G[40G]", + "autoneg": "0", + "fec": "rs" + }, + "Ethernet116": { + "default_brkout_mode": "1x100G[40G]", + "autoneg": "0", + "fec": "rs" + }, + "Ethernet120": { + "default_brkout_mode": "1x100G[40G]", + "autoneg": "0", + "fec": "rs" + }, + "Ethernet124": { + "default_brkout_mode": "1x100G[40G]", + "autoneg": "0", + "fec": "rs" + } + } +} diff --git a/device/barefoot/x86_64-accton_wedge100bf_32x-r0/platform.json b/device/barefoot/x86_64-accton_wedge100bf_32x-r0/platform.json new file mode 100644 index 00000000000..0b68edf1610 --- /dev/null +++ b/device/barefoot/x86_64-accton_wedge100bf_32x-r0/platform.json @@ -0,0 +1,196 @@ +{ + "interfaces": { + "Ethernet0": { + "index": "1,1,1,1", + "lanes": "0,1,2,3", + "alias_at_lanes": "Ethernet0,Ethernet1,Ethernet2,Ethernet3", + "breakout_modes": "1x100G[40G],2x50G,4x25G[10G]" + }, + "Ethernet4": { + "index": "2,2,2,2", + "lanes": "4,5,6,7", + "alias_at_lanes": "Ethernet4,Ethernet5,Ethernet6,Ethernet7", + "breakout_modes": "1x100G[40G],2x50G,4x25G[10G]" + }, + "Ethernet8": { + "index": "3,3,3,3", + "lanes": "8,9,10,11", + "alias_at_lanes": "Ethernet8,Ethernet9,Ethernet10,Ethernet11", + "breakout_modes": "1x100G[40G],2x50G,4x25G[10G]" + }, + "Ethernet12": { + "index": "4,4,4,4", + "lanes": "12,13,14,15", + "alias_at_lanes": "Ethernet12,Ethernet13,Ethernet14,Ethernet15", + "breakout_modes": "1x100G[40G],2x50G,4x25G[10G]" + }, + "Ethernet16": { + "index": "5,5,5,5", + "lanes": "16,17,18,19", + "alias_at_lanes": "Ethernet16,Ethernet17,Ethernet18,Ethernet19", + "breakout_modes": "1x100G[40G],2x50G,4x25G[10G]" + }, + "Ethernet20": { + "index": "6,6,6,6", + "lanes": "20,21,22,23", + "alias_at_lanes": "Ethernet20,Ethernet21,Ethernet22,Ethernet23", + "breakout_modes": "1x100G[40G],2x50G,4x25G[10G]" + }, + "Ethernet24": { + "index": "7,7,7,7", + "lanes": "24,25,26,27", + "alias_at_lanes": "Ethernet24,Ethernet25,Ethernet26,Ethernet27", + "breakout_modes": "1x100G[40G],2x50G,4x25G[10G]" + }, + "Ethernet28": { + "index": "8,8,8,8", + "lanes": "28,29,30,31", + "alias_at_lanes": "Ethernet28,Ethernet29,Ethernet30,Ethernet31", + "breakout_modes": "1x100G[40G],2x50G,4x25G[10G]" + }, + "Ethernet32": { + "index": "9,9,9,9", + "lanes": "32,33,34,35", + "alias_at_lanes": "Ethernet32,Ethernet33,Ethernet34,Ethernet35", + "breakout_modes": "1x100G[40G],2x50G,4x25G[10G]" + }, + "Ethernet36": { + "index": "10,10,10,10", + "lanes": "36,37,38,39", + "alias_at_lanes": "Ethernet36,Ethernet37,Ethernet38,Ethernet39", + "breakout_modes": "1x100G[40G],2x50G,4x25G[10G]" + }, + "Ethernet40": { + "index": "11,11,11,11", + "lanes": "40,41,42,43", + "alias_at_lanes": "Ethernet40,Ethernet41,Ethernet42,Ethernet43", + "breakout_modes": "1x100G[40G],2x50G,4x25G[10G]" + }, + "Ethernet44": { + "index": "12,12,12,12", + "lanes": "44,45,46,47", + "alias_at_lanes": "Ethernet44,Ethernet45,Ethernet46,Ethernet47", + "breakout_modes": "1x100G[40G],2x50G,4x25G[10G]" + }, + "Ethernet48": { + "index": "13,13,13,13", + "lanes": "48,49,50,51", + "alias_at_lanes": "Ethernet48,Ethernet49,Ethernet50,Ethernet51", + "breakout_modes": "1x100G[40G],2x50G,4x25G[10G]" + }, + "Ethernet52": { + "index": "14,14,14,14", + "lanes": "52,53,54,55", + "alias_at_lanes": "Ethernet52,Ethernet53,Ethernet54,Ethernet55", + "breakout_modes": "1x100G[40G],2x50G,4x25G[10G]" + }, + "Ethernet56": { + "index": "15,15,15,15", + "lanes": "56,57,58,59", + "alias_at_lanes": "Ethernet56,Ethernet57,Ethernet58,Ethernet59", + "breakout_modes": "1x100G[40G],2x50G,4x25G[10G]" + }, + "Ethernet60": { + "index": "16,16,16,16", + "lanes": "60,61,62,63", + "alias_at_lanes": "Ethernet60,Ethernet61,Ethernet62,Ethernet63", + "breakout_modes": "1x100G[40G],2x50G,4x25G[10G]" + }, + "Ethernet64": { + "index": "17,17,17,17", + "lanes": "64,65,66,67", + "alias_at_lanes": "Ethernet64,Ethernet65,Ethernet66,Ethernet67", + "breakout_modes": "1x100G[40G],2x50G,4x25G[10G]" + }, + "Ethernet68": { + "index": "18,18,18,18", + "lanes": "68,69,70,71", + "alias_at_lanes": "Ethernet68,Ethernet69,Ethernet70,Ethernet71", + "breakout_modes": "1x100G[40G],2x50G,4x25G[10G]" + }, + "Ethernet72": { + "index": "19,19,19,19", + "lanes": "72,73,74,75", + "alias_at_lanes": "Ethernet72,Ethernet73,Ethernet74,Ethernet75", + "breakout_modes": "1x100G[40G],2x50G,4x25G[10G]" + }, + "Ethernet76": { + "index": "20,20,20,20", + "lanes": "76,77,78,79", + "alias_at_lanes": "Ethernet76,Ethernet77,Ethernet78,Ethernet79", + "breakout_modes": "1x100G[40G],2x50G,4x25G[10G]" + }, + "Ethernet80": { + "index": "21,21,21,21", + "lanes": "80,81,82,83", + "alias_at_lanes": "Ethernet80,Ethernet81,Ethernet82,Ethernet83", + "breakout_modes": "1x100G[40G],2x50G,4x25G[10G]" + }, + "Ethernet84": { + "index": "22,22,22,22", + "lanes": "84,85,86,87", + "alias_at_lanes": "Ethernet84,Ethernet85,Ethernet86,Ethernet87", + "breakout_modes": "1x100G[40G],2x50G,4x25G[10G]" + }, + "Ethernet88": { + "index": "23,23,23,23", + "lanes": "88,89,90,91", + "alias_at_lanes": "Ethernet88,Ethernet89,Ethernet90,Ethernet91", + "breakout_modes": "1x100G[40G],2x50G,4x25G[10G]" + }, + "Ethernet92": { + "index": "24,24,24,24", + "lanes": "92,93,94,95", + "alias_at_lanes": "Ethernet92,Ethernet93,Ethernet94,Ethernet95", + "breakout_modes": "1x100G[40G],2x50G,4x25G[10G]" + }, + "Ethernet96": { + "index": "25,25,25,25", + "lanes": "96,97,98,99", + "alias_at_lanes": "Ethernet96,Ethernet97,Ethernet98,Ethernet99", + "breakout_modes": "1x100G[40G],2x50G,4x25G[10G]" + }, + "Ethernet100": { + "index": "26,26,26,26", + "lanes": "100,101,102,103", + "alias_at_lanes": "Ethernet100,Ethernet101,Ethernet102,Ethernet103", + "breakout_modes": "1x100G[40G],2x50G,4x25G[10G]" + }, + "Ethernet104": { + "index": "27,27,27,27", + "lanes": "104,105,106,107", + "alias_at_lanes": "Ethernet104,Ethernet105,Ethernet106,Ethernet107", + "breakout_modes": "1x100G[40G],2x50G,4x25G[10G]" + }, + "Ethernet108": { + "index": "28,28,28,28", + "lanes": "108,109,110,111", + "alias_at_lanes": "Ethernet108,Ethernet109,Ethernet110,Ethernet111", + "breakout_modes": "1x100G[40G],2x50G,4x25G[10G]" + }, + "Ethernet112": { + "index": "29,29,29,29", + "lanes": "112,113,114,115", + "alias_at_lanes": "Ethernet112,Ethernet113,Ethernet114,Ethernet115", + "breakout_modes": "1x100G[40G],2x50G,4x25G[10G]" + }, + "Ethernet116": { + "index": "30,30,30,30", + "lanes": "116,117,118,119", + "alias_at_lanes": "Ethernet116,Ethernet117,Ethernet118,Ethernet119", + "breakout_modes": "1x100G[40G],2x50G,4x25G[10G]" + }, + "Ethernet120": { + "index": "31,31,31,31", + "lanes": "120,121,122,123", + "alias_at_lanes": "Ethernet120,Ethernet121,Ethernet122,Ethernet123", + "breakout_modes": "1x100G[40G],2x50G,4x25G[10G]" + }, + "Ethernet124": { + "index": "32,32,32,32", + "lanes": "124,125,126,127", + "alias_at_lanes": "Ethernet124,Ethernet125,Ethernet126,Ethernet127", + "breakout_modes": "1x100G[40G],2x50G,4x25G[10G]" + } + } +} diff --git a/device/barefoot/x86_64-accton_wedge100bf_65x-r0/mavericks/hwsku.json b/device/barefoot/x86_64-accton_wedge100bf_65x-r0/mavericks/hwsku.json new file mode 100644 index 00000000000..857b00852c0 --- /dev/null +++ b/device/barefoot/x86_64-accton_wedge100bf_65x-r0/mavericks/hwsku.json @@ -0,0 +1,329 @@ +{ + "interfaces": { + "Ethernet0": { + "default_brkout_mode": "1x100G[40G]", + "autoneg": "0", + "fec": "rs" + }, + "Ethernet4": { + "default_brkout_mode": "1x100G[40G]", + "autoneg": "0", + "fec": "rs" + }, + "Ethernet8": { + "default_brkout_mode": "1x100G[40G]", + "autoneg": "0", + "fec": "rs" + }, + "Ethernet12": { + "default_brkout_mode": "1x100G[40G]", + "autoneg": "0", + "fec": "rs" + }, + "Ethernet16": { + "default_brkout_mode": "1x100G[40G]", + "autoneg": "0", + "fec": "rs" + }, + "Ethernet20": { + "default_brkout_mode": "1x100G[40G]", + "autoneg": "0", + "fec": "rs" + }, + "Ethernet24": { + "default_brkout_mode": "1x100G[40G]", + "autoneg": "0", + "fec": "rs" + }, + "Ethernet28": { + "default_brkout_mode": "1x100G[40G]", + "autoneg": "0", + "fec": "rs" + }, + "Ethernet32": { + "default_brkout_mode": "1x100G[40G]", + "autoneg": "0", + "fec": "rs" + }, + "Ethernet36": { + "default_brkout_mode": "1x100G[40G]", + "autoneg": "0", + "fec": "rs" + }, + "Ethernet40": { + "default_brkout_mode": "1x100G[40G]", + "autoneg": "0", + "fec": "rs" + }, + "Ethernet44": { + "default_brkout_mode": "1x100G[40G]", + "autoneg": "0", + "fec": "rs" + }, + "Ethernet48": { + "default_brkout_mode": "1x100G[40G]", + "autoneg": "0", + "fec": "rs" + }, + "Ethernet52": { + "default_brkout_mode": "1x100G[40G]", + "autoneg": "0", + "fec": "rs" + }, + "Ethernet56": { + "default_brkout_mode": "1x100G[40G]", + "autoneg": "0", + "fec": "rs" + }, + "Ethernet60": { + "default_brkout_mode": "1x100G[40G]", + "autoneg": "0", + "fec": "rs" + }, + "Ethernet64": { + "default_brkout_mode": "1x100G[40G]", + "autoneg": "0", + "fec": "rs" + }, + "Ethernet68": { + "default_brkout_mode": "1x100G[40G]", + "autoneg": "0", + "fec": "rs" + }, + "Ethernet72": { + "default_brkout_mode": "1x100G[40G]", + "autoneg": "0", + "fec": "rs" + }, + "Ethernet76": { + "default_brkout_mode": "1x100G[40G]", + "autoneg": "0", + "fec": "rs" + }, + "Ethernet80": { + "default_brkout_mode": "1x100G[40G]", + "autoneg": "0", + "fec": "rs" + }, + "Ethernet84": { + "default_brkout_mode": "1x100G[40G]", + "autoneg": "0", + "fec": "rs" + }, + "Ethernet88": { + "default_brkout_mode": "1x100G[40G]", + "autoneg": "0", + "fec": "rs" + }, + "Ethernet92": { + "default_brkout_mode": "1x100G[40G]", + "autoneg": "0", + "fec": "rs" + }, + "Ethernet96": { + "default_brkout_mode": "1x100G[40G]", + "autoneg": "0", + "fec": "rs" + }, + "Ethernet100": { + "default_brkout_mode": "1x100G[40G]", + "autoneg": "0", + "fec": "rs" + }, + "Ethernet104": { + "default_brkout_mode": "1x100G[40G]", + "autoneg": "0", + "fec": "rs" + }, + "Ethernet108": { + "default_brkout_mode": "1x100G[40G]", + "autoneg": "0", + "fec": "rs" + }, + "Ethernet112": { + "default_brkout_mode": "1x100G[40G]", + "autoneg": "0", + "fec": "rs" + }, + "Ethernet116": { + "default_brkout_mode": "1x100G[40G]", + "autoneg": "0", + "fec": "rs" + }, + "Ethernet120": { + "default_brkout_mode": "1x100G[40G]", + "autoneg": "0", + "fec": "rs" + }, + "Ethernet124": { + "default_brkout_mode": "1x100G[40G]", + "autoneg": "0", + "fec": "rs" + }, + "Ethernet128": { + "default_brkout_mode": "1x100G[40G]", + "autoneg": "0", + "fec": "rs" + }, + "Ethernet132": { + "default_brkout_mode": "1x100G[40G]", + "autoneg": "0", + "fec": "rs" + }, + "Ethernet136": { + "default_brkout_mode": "1x100G[40G]", + "autoneg": "0", + "fec": "rs" + }, + "Ethernet140": { + "default_brkout_mode": "1x100G[40G]", + "autoneg": "0", + "fec": "rs" + }, + "Ethernet144": { + "default_brkout_mode": "1x100G[40G]", + "autoneg": "0", + "fec": "rs" + }, + "Ethernet148": { + "default_brkout_mode": "1x100G[40G]", + "autoneg": "0", + "fec": "rs" + }, + "Ethernet152": { + "default_brkout_mode": "1x100G[40G]", + "autoneg": "0", + "fec": "rs" + }, + "Ethernet156": { + "default_brkout_mode": "1x100G[40G]", + "autoneg": "0", + "fec": "rs" + }, + "Ethernet160": { + "default_brkout_mode": "1x100G[40G]", + "autoneg": "0", + "fec": "rs" + }, + "Ethernet164": { + "default_brkout_mode": "1x100G[40G]", + "autoneg": "0", + "fec": "rs" + }, + "Ethernet168": { + "default_brkout_mode": "1x100G[40G]", + "autoneg": "0", + "fec": "rs" + }, + "Ethernet172": { + "default_brkout_mode": "1x100G[40G]", + "autoneg": "0", + "fec": "rs" + }, + "Ethernet176": { + "default_brkout_mode": "1x100G[40G]", + "autoneg": "0", + "fec": "rs" + }, + "Ethernet180": { + "default_brkout_mode": "1x100G[40G]", + "autoneg": "0", + "fec": "rs" + }, + "Ethernet184": { + "default_brkout_mode": "1x100G[40G]", + "autoneg": "0", + "fec": "rs" + }, + "Ethernet188": { + "default_brkout_mode": "1x100G[40G]", + "autoneg": "0", + "fec": "rs" + }, + "Ethernet192": { + "default_brkout_mode": "1x100G[40G]", + "autoneg": "0", + "fec": "rs" + }, + "Ethernet196": { + "default_brkout_mode": "1x100G[40G]", + "autoneg": "0", + "fec": "rs" + }, + "Ethernet200": { + "default_brkout_mode": "1x100G[40G]", + "autoneg": "0", + "fec": "rs" + }, + "Ethernet204": { + "default_brkout_mode": "1x100G[40G]", + "autoneg": "0", + "fec": "rs" + }, + "Ethernet208": { + "default_brkout_mode": "1x100G[40G]", + "autoneg": "0", + "fec": "rs" + }, + "Ethernet212": { + "default_brkout_mode": "1x100G[40G]", + "autoneg": "0", + "fec": "rs" + }, + "Ethernet216": { + "default_brkout_mode": "1x100G[40G]", + "autoneg": "0", + "fec": "rs" + }, + "Ethernet220": { + "default_brkout_mode": "1x100G[40G]", + "autoneg": "0", + "fec": "rs" + }, + "Ethernet224": { + "default_brkout_mode": "1x100G[40G]", + "autoneg": "0", + "fec": "rs" + }, + "Ethernet228": { + "default_brkout_mode": "1x100G[40G]", + "autoneg": "0", + "fec": "rs" + }, + "Ethernet232": { + "default_brkout_mode": "1x100G[40G]", + "autoneg": "0", + "fec": "rs" + }, + "Ethernet236": { + "default_brkout_mode": "1x100G[40G]", + "autoneg": "0", + "fec": "rs" + }, + "Ethernet240": { + "default_brkout_mode": "1x100G[40G]", + "autoneg": "0", + "fec": "rs" + }, + "Ethernet244": { + "default_brkout_mode": "1x100G[40G]", + "autoneg": "0", + "fec": "rs" + }, + "Ethernet248": { + "default_brkout_mode": "1x100G[40G]", + "autoneg": "0", + "fec": "rs" + }, + "Ethernet252": { + "default_brkout_mode": "1x100G[40G]", + "autoneg": "0", + "fec": "rs" + }, + "Ethernet256": { + "default_brkout_mode": "1x100G[40G]", + "autoneg": "0", + "fec": "none" + } + } +} diff --git a/device/barefoot/x86_64-accton_wedge100bf_65x-r0/platform.json b/device/barefoot/x86_64-accton_wedge100bf_65x-r0/platform.json new file mode 100644 index 00000000000..866706a2835 --- /dev/null +++ b/device/barefoot/x86_64-accton_wedge100bf_65x-r0/platform.json @@ -0,0 +1,394 @@ +{ + "interfaces": { + "Ethernet0": { + "index": "1,1,1,1", + "lanes": "0,1,2,3", + "alias_at_lanes": "Ethernet0,Ethernet1,Ethernet2,Ethernet3", + "breakout_modes": "1x100G[40G],2x50G,4x25G[10G]" + }, + "Ethernet4": { + "index": "2,2,2,2", + "lanes": "4,5,6,7", + "alias_at_lanes": "Ethernet4,Ethernet5,Ethernet6,Ethernet7", + "breakout_modes": "1x100G[40G],2x50G,4x25G[10G]" + }, + "Ethernet8": { + "index": "3,3,3,3", + "lanes": "8,9,10,11", + "alias_at_lanes": "Ethernet8,Ethernet9,Ethernet10,Ethernet11", + "breakout_modes": "1x100G[40G],2x50G,4x25G[10G]" + }, + "Ethernet12": { + "index": "4,4,4,4", + "lanes": "12,13,14,15", + "alias_at_lanes": "Ethernet12,Ethernet13,Ethernet14,Ethernet15", + "breakout_modes": "1x100G[40G],2x50G,4x25G[10G]" + }, + "Ethernet16": { + "index": "5,5,5,5", + "lanes": "16,17,18,19", + "alias_at_lanes": "Ethernet16,Ethernet17,Ethernet18,Ethernet19", + "breakout_modes": "1x100G[40G],2x50G,4x25G[10G]" + }, + "Ethernet20": { + "index": "6,6,6,6", + "lanes": "20,21,22,23", + "alias_at_lanes": "Ethernet20,Ethernet21,Ethernet22,Ethernet23", + "breakout_modes": "1x100G[40G],2x50G,4x25G[10G]" + }, + "Ethernet24": { + "index": "7,7,7,7", + "lanes": "24,25,26,27", + "alias_at_lanes": "Ethernet24,Ethernet25,Ethernet26,Ethernet27", + "breakout_modes": "1x100G[40G],2x50G,4x25G[10G]" + }, + "Ethernet28": { + "index": "8,8,8,8", + "lanes": "28,29,30,31", + "alias_at_lanes": "Ethernet28,Ethernet29,Ethernet30,Ethernet31", + "breakout_modes": "1x100G[40G],2x50G,4x25G[10G]" + }, + "Ethernet32": { + "index": "9,9,9,9", + "lanes": "32,33,34,35", + "alias_at_lanes": "Ethernet32,Ethernet33,Ethernet34,Ethernet35", + "breakout_modes": "1x100G[40G],2x50G,4x25G[10G]" + }, + "Ethernet36": { + "index": "10,10,10,10", + "lanes": "36,37,38,39", + "alias_at_lanes": "Ethernet36,Ethernet37,Ethernet38,Ethernet39", + "breakout_modes": "1x100G[40G],2x50G,4x25G[10G]" + }, + "Ethernet40": { + "index": "11,11,11,11", + "lanes": "40,41,42,43", + "alias_at_lanes": "Ethernet40,Ethernet41,Ethernet42,Ethernet43", + "breakout_modes": "1x100G[40G],2x50G,4x25G[10G]" + }, + "Ethernet44": { + "index": "12,12,12,12", + "lanes": "44,45,46,47", + "alias_at_lanes": "Ethernet44,Ethernet45,Ethernet46,Ethernet47", + "breakout_modes": "1x100G[40G],2x50G,4x25G[10G]" + }, + "Ethernet48": { + "index": "13,13,13,13", + "lanes": "48,49,50,51", + "alias_at_lanes": "Ethernet48,Ethernet49,Ethernet50,Ethernet51", + "breakout_modes": "1x100G[40G],2x50G,4x25G[10G]" + }, + "Ethernet52": { + "index": "14,14,14,14", + "lanes": "52,53,54,55", + "alias_at_lanes": "Ethernet52,Ethernet53,Ethernet54,Ethernet55", + "breakout_modes": "1x100G[40G],2x50G,4x25G[10G]" + }, + "Ethernet56": { + "index": "15,15,15,15", + "lanes": "56,57,58,59", + "alias_at_lanes": "Ethernet56,Ethernet57,Ethernet58,Ethernet59", + "breakout_modes": "1x100G[40G],2x50G,4x25G[10G]" + }, + "Ethernet60": { + "index": "16,16,16,16", + "lanes": "60,61,62,63", + "alias_at_lanes": "Ethernet60,Ethernet61,Ethernet62,Ethernet63", + "breakout_modes": "1x100G[40G],2x50G,4x25G[10G]" + }, + "Ethernet64": { + "index": "17,17,17,17", + "lanes": "64,65,66,67", + "alias_at_lanes": "Ethernet64,Ethernet65,Ethernet66,Ethernet67", + "breakout_modes": "1x100G[40G],2x50G,4x25G[10G]" + }, + "Ethernet68": { + "index": "18,18,18,18", + "lanes": "68,69,70,71", + "alias_at_lanes": "Ethernet68,Ethernet69,Ethernet70,Ethernet71", + "breakout_modes": "1x100G[40G],2x50G,4x25G[10G]" + }, + "Ethernet72": { + "index": "19,19,19,19", + "lanes": "72,73,74,75", + "alias_at_lanes": "Ethernet72,Ethernet73,Ethernet74,Ethernet75", + "breakout_modes": "1x100G[40G],2x50G,4x25G[10G]" + }, + "Ethernet76": { + "index": "20,20,20,20", + "lanes": "76,77,78,79", + "alias_at_lanes": "Ethernet76,Ethernet77,Ethernet78,Ethernet79", + "breakout_modes": "1x100G[40G],2x50G,4x25G[10G]" + }, + "Ethernet80": { + "index": "21,21,21,21", + "lanes": "80,81,82,83", + "alias_at_lanes": "Ethernet80,Ethernet81,Ethernet82,Ethernet83", + "breakout_modes": "1x100G[40G],2x50G,4x25G[10G]" + }, + "Ethernet84": { + "index": "22,22,22,22", + "lanes": "84,85,86,87", + "alias_at_lanes": "Ethernet84,Ethernet85,Ethernet86,Ethernet87", + "breakout_modes": "1x100G[40G],2x50G,4x25G[10G]" + }, + "Ethernet88": { + "index": "23,23,23,23", + "lanes": "88,89,90,91", + "alias_at_lanes": "Ethernet88,Ethernet89,Ethernet90,Ethernet91", + "breakout_modes": "1x100G[40G],2x50G,4x25G[10G]" + }, + "Ethernet92": { + "index": "24,24,24,24", + "lanes": "92,93,94,95", + "alias_at_lanes": "Ethernet92,Ethernet93,Ethernet94,Ethernet95", + "breakout_modes": "1x100G[40G],2x50G,4x25G[10G]" + }, + "Ethernet96": { + "index": "25,25,25,25", + "lanes": "96,97,98,99", + "alias_at_lanes": "Ethernet96,Ethernet97,Ethernet98,Ethernet99", + "breakout_modes": "1x100G[40G],2x50G,4x25G[10G]" + }, + "Ethernet100": { + "index": "26,26,26,26", + "lanes": "100,101,102,103", + "alias_at_lanes": "Ethernet100,Ethernet101,Ethernet102,Ethernet103", + "breakout_modes": "1x100G[40G],2x50G,4x25G[10G]" + }, + "Ethernet104": { + "index": "27,27,27,27", + "lanes": "104,105,106,107", + "alias_at_lanes": "Ethernet104,Ethernet105,Ethernet106,Ethernet107", + "breakout_modes": "1x100G[40G],2x50G,4x25G[10G]" + }, + "Ethernet108": { + "index": "28,28,28,28", + "lanes": "108,109,110,111", + "alias_at_lanes": "Ethernet108,Ethernet109,Ethernet110,Ethernet111", + "breakout_modes": "1x100G[40G],2x50G,4x25G[10G]" + }, + "Ethernet112": { + "index": "29,29,29,29", + "lanes": "112,113,114,115", + "alias_at_lanes": "Ethernet112,Ethernet113,Ethernet114,Ethernet115", + "breakout_modes": "1x100G[40G],2x50G,4x25G[10G]" + }, + "Ethernet116": { + "index": "30,30,30,30", + "lanes": "116,117,118,119", + "alias_at_lanes": "Ethernet116,Ethernet117,Ethernet118,Ethernet119", + "breakout_modes": "1x100G[40G],2x50G,4x25G[10G]" + }, + "Ethernet120": { + "index": "31,31,31,31", + "lanes": "120,121,122,123", + "alias_at_lanes": "Ethernet120,Ethernet121,Ethernet122,Ethernet123", + "breakout_modes": "1x100G[40G],2x50G,4x25G[10G]" + }, + "Ethernet124": { + "index": "32,32,32,32", + "lanes": "124,125,126,127", + "alias_at_lanes": "Ethernet124,Ethernet125,Ethernet126,Ethernet127", + "breakout_modes": "1x100G[40G],2x50G,4x25G[10G]" + }, + "Ethernet128": { + "index": "33,33,33,33", + "lanes": "128,129,130,131", + "alias_at_lanes": "Ethernet128,Ethernet129,Ethernet130,Ethernet131", + "breakout_modes": "1x100G[40G],2x50G,4x25G[10G]" + }, + "Ethernet132": { + "index": "34,34,34,34", + "lanes": "132,133,134,135", + "alias_at_lanes": "Ethernet132,Ethernet133,Ethernet134,Ethernet135", + "breakout_modes": "1x100G[40G],2x50G,4x25G[10G]" + }, + "Ethernet136": { + "index": "35,35,35,35", + "lanes": "136,137,138,139", + "alias_at_lanes": "Ethernet136,Ethernet137,Ethernet138,Ethernet139", + "breakout_modes": "1x100G[40G],2x50G,4x25G[10G]" + }, + "Ethernet140": { + "index": "36,36,36,36", + "lanes": "140,141,142,143", + "alias_at_lanes": "Ethernet140,Ethernet141,Ethernet142,Ethernet143", + "breakout_modes": "1x100G[40G],2x50G,4x25G[10G]" + }, + "Ethernet144": { + "index": "37,37,37,37", + "lanes": "144,145,146,147", + "alias_at_lanes": "Ethernet144,Ethernet145,Ethernet146,Ethernet147", + "breakout_modes": "1x100G[40G],2x50G,4x25G[10G]" + }, + "Ethernet148": { + "index": "38,38,38,38", + "lanes": "148,149,150,151", + "alias_at_lanes": "Ethernet148,Ethernet149,Ethernet150,Ethernet151", + "breakout_modes": "1x100G[40G],2x50G,4x25G[10G]" + }, + "Ethernet152": { + "index": "39,39,39,39", + "lanes": "152,153,154,155", + "alias_at_lanes": "Ethernet152,Ethernet153,Ethernet154,Ethernet155", + "breakout_modes": "1x100G[40G],2x50G,4x25G[10G]" + }, + "Ethernet156": { + "index": "40,40,40,40", + "lanes": "156,157,158,159", + "alias_at_lanes": "Ethernet156,Ethernet157,Ethernet158,Ethernet159", + "breakout_modes": "1x100G[40G],2x50G,4x25G[10G]" + }, + "Ethernet160": { + "index": "41,41,41,41", + "lanes": "160,161,162,163", + "alias_at_lanes": "Ethernet160,Ethernet161,Ethernet162,Ethernet163", + "breakout_modes": "1x100G[40G],2x50G,4x25G[10G]" + }, + "Ethernet164": { + "index": "42,42,42,42", + "lanes": "164,165,166,167", + "alias_at_lanes": "Ethernet164,Ethernet165,Ethernet166,Ethernet167", + "breakout_modes": "1x100G[40G],2x50G,4x25G[10G]" + }, + "Ethernet168": { + "index": "43,43,43,43", + "lanes": "168,169,170,171", + "alias_at_lanes": "Ethernet168,Ethernet169,Ethernet170,Ethernet171", + "breakout_modes": "1x100G[40G],2x50G,4x25G[10G]" + }, + "Ethernet172": { + "index": "44,44,44,44", + "lanes": "172,173,174,175", + "alias_at_lanes": "Ethernet172,Ethernet173,Ethernet174,Ethernet175", + "breakout_modes": "1x100G[40G],2x50G,4x25G[10G]" + }, + "Ethernet176": { + "index": "45,45,45,45", + "lanes": "176,177,178,179", + "alias_at_lanes": "Ethernet176,Ethernet177,Ethernet178,Ethernet179", + "breakout_modes": "1x100G[40G],2x50G,4x25G[10G]" + }, + "Ethernet180": { + "index": "46,46,46,46", + "lanes": "180,181,182,183", + "alias_at_lanes": "Ethernet180,Ethernet181,Ethernet182,Ethernet183", + "breakout_modes": "1x100G[40G],2x50G,4x25G[10G]" + }, + "Ethernet184": { + "index": "47,47,47,47", + "lanes": "184,185,186,187", + "alias_at_lanes": "Ethernet184,Ethernet185,Ethernet186,Ethernet187", + "breakout_modes": "1x100G[40G],2x50G,4x25G[10G]" + }, + "Ethernet188": { + "index": "48,48,48,48", + "lanes": "188,189,190,191", + "alias_at_lanes": "Ethernet188,Ethernet189,Ethernet190,Ethernet191", + "breakout_modes": "1x100G[40G],2x50G,4x25G[10G]" + }, + "Ethernet192": { + "index": "49,49,49,49", + "lanes": "192,193,194,195", + "alias_at_lanes": "Ethernet192,Ethernet193,Ethernet194,Ethernet195", + "breakout_modes": "1x100G[40G],2x50G,4x25G[10G]" + }, + "Ethernet196": { + "index": "50,50,50,50", + "lanes": "196,197,198,199", + "alias_at_lanes": "Ethernet196,Ethernet197,Ethernet198,Ethernet199", + "breakout_modes": "1x100G[40G],2x50G,4x25G[10G]" + }, + "Ethernet200": { + "index": "51,51,51,51", + "lanes": "200,201,202,203", + "alias_at_lanes": "Ethernet200,Ethernet201,Ethernet202,Ethernet203", + "breakout_modes": "1x100G[40G],2x50G,4x25G[10G]" + }, + "Ethernet204": { + "index": "52,52,52,52", + "lanes": "204,205,206,207", + "alias_at_lanes": "Ethernet204,Ethernet205,Ethernet206,Ethernet207", + "breakout_modes": "1x100G[40G],2x50G,4x25G[10G]" + }, + "Ethernet208": { + "index": "53,53,53,53", + "lanes": "208,209,210,211", + "alias_at_lanes": "Ethernet208,Ethernet209,Ethernet210,Ethernet211", + "breakout_modes": "1x100G[40G],2x50G,4x25G[10G]" + }, + "Ethernet212": { + "index": "54,54,54,54", + "lanes": "212,213,214,215", + "alias_at_lanes": "Ethernet212,Ethernet213,Ethernet214,Ethernet215", + "breakout_modes": "1x100G[40G],2x50G,4x25G[10G]" + }, + "Ethernet216": { + "index": "55,55,55,55", + "lanes": "216,217,218,219", + "alias_at_lanes": "Ethernet216,Ethernet217,Ethernet218,Ethernet219", + "breakout_modes": "1x100G[40G],2x50G,4x25G[10G]" + }, + "Ethernet220": { + "index": "56,56,56,56", + "lanes": "220,221,222,223", + "alias_at_lanes": "Ethernet220,Ethernet221,Ethernet222,Ethernet223", + "breakout_modes": "1x100G[40G],2x50G,4x25G[10G]" + }, + "Ethernet224": { + "index": "57,57,57,57", + "lanes": "224,225,226,227", + "alias_at_lanes": "Ethernet224,Ethernet225,Ethernet226,Ethernet227", + "breakout_modes": "1x100G[40G],2x50G,4x25G[10G]" + }, + "Ethernet228": { + "index": "58,58,58,58", + "lanes": "228,229,230,231", + "alias_at_lanes": "Ethernet228,Ethernet229,Ethernet230,Ethernet231", + "breakout_modes": "1x100G[40G],2x50G,4x25G[10G]" + }, + "Ethernet232": { + "index": "59,59,59,59", + "lanes": "232,233,234,235", + "alias_at_lanes": "Ethernet232,Ethernet233,Ethernet234,Ethernet235", + "breakout_modes": "1x100G[40G],2x50G,4x25G[10G]" + }, + "Ethernet236": { + "index": "60,60,60,60", + "lanes": "236,237,238,239", + "alias_at_lanes": "Ethernet236,Ethernet237,Ethernet238,Ethernet239", + "breakout_modes": "1x100G[40G],2x50G,4x25G[10G]" + }, + "Ethernet240": { + "index": "61,61,61,61", + "lanes": "240,241,242,243", + "alias_at_lanes": "Ethernet240,Ethernet241,Ethernet242,Ethernet243", + "breakout_modes": "1x100G[40G],2x50G,4x25G[10G]" + }, + "Ethernet244": { + "index": "62,62,62,62", + "lanes": "244,245,246,247", + "alias_at_lanes": "Ethernet244,Ethernet245,Ethernet246,Ethernet247", + "breakout_modes": "1x100G[40G],2x50G,4x25G[10G]" + }, + "Ethernet248": { + "index": "63,63,63,63", + "lanes": "248,249,250,251", + "alias_at_lanes": "Ethernet248,Ethernet249,Ethernet250,Ethernet251", + "breakout_modes": "1x100G[40G],2x50G,4x25G[10G]" + }, + "Ethernet252": { + "index": "64,64,64,64", + "lanes": "252,253,254,255", + "alias_at_lanes": "Ethernet252,Ethernet253,Ethernet254,Ethernet255", + "breakout_modes": "1x100G[40G],2x50G,4x25G[10G]" + }, + "Ethernet256": { + "index": "65,65,65,65", + "lanes": "256,257,258,259", + "alias_at_lanes": "Ethernet256,Ethernet257,Ethernet258,Ethernet259", + "breakout_modes": "1x100G[40G],2x50G,4x25G[10G]" + } + } +} diff --git a/device/celestica/x86_64-cel_seastone-r0/sonic_platform/sfp.py b/device/celestica/x86_64-cel_seastone-r0/sonic_platform/sfp.py index 9daa005cd2b..13ae4b8a47a 100644 --- a/device/celestica/x86_64-cel_seastone-r0/sonic_platform/sfp.py +++ b/device/celestica/x86_64-cel_seastone-r0/sonic_platform/sfp.py @@ -279,7 +279,7 @@ def _dom_capability_detect(self): QSFP_VERSION_COMPLIANCE_OFFSET, QSFP_VERSION_COMPLIANCE_WIDTH) qsfp_version_compliance = int( qsfp_version_compliance_raw[0], 16) - dom_capability = sfpi_obj.parse_qsfp_dom_capability( + dom_capability = sfpi_obj.parse_dom_capability( qsfp_dom_capability_raw, 0) if qsfp_version_compliance >= 0x08: self.dom_temp_supported = dom_capability['data']['Temp_support']['value'] == 'On' diff --git a/device/celestica/x86_64-cel_seastone_2-r0/Seastone_2/td3-seastone_2-32x100G.config.bcm b/device/celestica/x86_64-cel_seastone_2-r0/Seastone_2/td3-seastone_2-32x100G.config.bcm index 2c23d0da2f2..62bcdbc5884 100644 --- a/device/celestica/x86_64-cel_seastone_2-r0/Seastone_2/td3-seastone_2-32x100G.config.bcm +++ b/device/celestica/x86_64-cel_seastone_2-r0/Seastone_2/td3-seastone_2-32x100G.config.bcm @@ -1,3 +1,4 @@ +sai_load_hw_config=/etc/bcm/flex/bcm56870_a0_issu/b870.6.4.1/ help_cli_enable=1 ifp_inports_support_enable=1 ipv6_lpm_128b_enable=0x1 diff --git a/device/celestica/x86_64-cel_silverstone-r0/sonic_platform/sfp.py b/device/celestica/x86_64-cel_silverstone-r0/sonic_platform/sfp.py index b04b49ca438..e909416e908 100644 --- a/device/celestica/x86_64-cel_silverstone-r0/sonic_platform/sfp.py +++ b/device/celestica/x86_64-cel_silverstone-r0/sonic_platform/sfp.py @@ -328,7 +328,7 @@ def _dom_capability_detect(self): QSFP_VERSION_COMPLIANCE_OFFSET, QSFP_VERSION_COMPLIANCE_WIDTH) qsfp_version_compliance = int( qsfp_version_compliance_raw[0], 16) - dom_capability = sfpi_obj.parse_qsfp_dom_capability( + dom_capability = sfpi_obj.parse_dom_capability( qsfp_dom_capability_raw, 0) if qsfp_version_compliance >= 0x08: self.dom_temp_supported = dom_capability['data']['Temp_support']['value'] == 'On' diff --git a/device/dell/x86_64-dell_s6000_s1220-r0/platform_reboot b/device/dell/x86_64-dell_s6000_s1220-r0/platform_reboot index d973f4f810e..28f2ec62660 100755 --- a/device/dell/x86_64-dell_s6000_s1220-r0/platform_reboot +++ b/device/dell/x86_64-dell_s6000_s1220-r0/platform_reboot @@ -4,10 +4,11 @@ import sys import os import struct +PORT_RES = '/dev/port' NVRAM_RES = '/dev/nvram' COLD_RESET = 0xE # Cold Reset WARM_RESET = 0x6 # Warm Reset - +RESET_REG = 0xCF9 def io_reg_write(resource, offset, val): fd = os.open(resource, os.O_RDWR) @@ -23,39 +24,40 @@ def io_reg_write(resource, offset, val): return os.close(fd) - def power_reset(val): with open('/sys/devices/platform/dell-s6000-cpld.0/power_reset', 'w') as p: p.write(str(int(val)) + '\n') p.flush() - def gpio_direction(pin, direction): kernpath = '/sys/class/gpio/gpio'+str(pin)+'/direction' with open(('kernpath'), 'w') as p: p.write(str(direction) + '\n') p.flush() - def gpio_set(pin, value): kernpath = '/sys/class/gpio/gpio'+str(pin)+'/value' with open(('kernpath'), 'w') as p: p.write(str(int(value)) + '\n') p.flush() - def gpio_export(value): with open('/sys/class/gpio/export', 'w') as p: p.write(str(int(value)) + '\n') p.flush() - if __name__ == "__main__": + + retry_count = 0 io_reg_write(NVRAM_RES, 0x49, COLD_RESET) - if not os.path.isdir("/sys/class/gpio/gpio10"): - gpio_export(10) - gpio_direction("10", "out") - # Toggle GPIO10 pin (to reset MUX) - gpio_set("10", 1) - gpio_set("10", 0) - power_reset(1) + + while retry_count < 3: + if not os.path.isdir("/sys/class/gpio/gpio10"): + gpio_export(10) + gpio_direction("10", "out") + # Toggle GPIO10 pin (to reset MUX) + gpio_set("10", 1) + gpio_set("10", 0) + power_reset(1) + retry_count += 1 + io_reg_write(PORT_RES, RESET_REG, COLD_RESET) diff --git a/device/dell/x86_64-dell_s6000_s1220-r0/pmon_daemon_control.json b/device/dell/x86_64-dell_s6000_s1220-r0/pmon_daemon_control.json index 44871c057e8..94592fa8ceb 100644 --- a/device/dell/x86_64-dell_s6000_s1220-r0/pmon_daemon_control.json +++ b/device/dell/x86_64-dell_s6000_s1220-r0/pmon_daemon_control.json @@ -1,4 +1,3 @@ { - "skip_ledd": true, - "skip_thermalctld": true + "skip_ledd": true } diff --git a/device/dell/x86_64-dell_s6100_c2538-r0/pmon_daemon_control.json b/device/dell/x86_64-dell_s6100_c2538-r0/pmon_daemon_control.json index 44871c057e8..94592fa8ceb 100644 --- a/device/dell/x86_64-dell_s6100_c2538-r0/pmon_daemon_control.json +++ b/device/dell/x86_64-dell_s6100_c2538-r0/pmon_daemon_control.json @@ -1,4 +1,3 @@ { - "skip_ledd": true, - "skip_thermalctld": true + "skip_ledd": true } diff --git a/device/dell/x86_64-dellemc_s5232f_c3538-r0/DellEMC-S5232f-C32/td3-s5232f-32x100G.config.bcm b/device/dell/x86_64-dellemc_s5232f_c3538-r0/DellEMC-S5232f-C32/td3-s5232f-32x100G.config.bcm index 3f50f39db8e..bf15510bf49 100644 --- a/device/dell/x86_64-dellemc_s5232f_c3538-r0/DellEMC-S5232f-C32/td3-s5232f-32x100G.config.bcm +++ b/device/dell/x86_64-dellemc_s5232f_c3538-r0/DellEMC-S5232f-C32/td3-s5232f-32x100G.config.bcm @@ -1,3 +1,4 @@ +sai_load_hw_config=/etc/bcm/flex/bcm56870_a0_issu/b870.6.4.1/ os=unix core_clock_frequency=1525 diff --git a/device/dell/x86_64-dellemc_s5232f_c3538-r0/DellEMC-S5232f-C8D48/td3-s5232f-8x100G+48x50G.config.bcm b/device/dell/x86_64-dellemc_s5232f_c3538-r0/DellEMC-S5232f-C8D48/td3-s5232f-8x100G+48x50G.config.bcm index 4f3121387de..68fb77a4219 100644 --- a/device/dell/x86_64-dellemc_s5232f_c3538-r0/DellEMC-S5232f-C8D48/td3-s5232f-8x100G+48x50G.config.bcm +++ b/device/dell/x86_64-dellemc_s5232f_c3538-r0/DellEMC-S5232f-C8D48/td3-s5232f-8x100G+48x50G.config.bcm @@ -1,3 +1,4 @@ +sai_load_hw_config=/etc/bcm/flex/bcm56870_a0_issu/b870.6.4.1/ os=unix core_clock_frequency=1525 diff --git a/device/dell/x86_64-dellemc_s5232f_c3538-r0/DellEMC-S5232f-P-100G/td3-s5232f-32x100G.config.bcm b/device/dell/x86_64-dellemc_s5232f_c3538-r0/DellEMC-S5232f-P-100G/td3-s5232f-32x100G.config.bcm index 099d1270443..c44e4805c62 100644 --- a/device/dell/x86_64-dellemc_s5232f_c3538-r0/DellEMC-S5232f-P-100G/td3-s5232f-32x100G.config.bcm +++ b/device/dell/x86_64-dellemc_s5232f_c3538-r0/DellEMC-S5232f-P-100G/td3-s5232f-32x100G.config.bcm @@ -1,3 +1,4 @@ +sai_load_hw_config=/etc/bcm/flex/bcm56870_a0_issu/b870.6.4.1/ os=unix core_clock_frequency=1525 diff --git a/device/dell/x86_64-dellemc_s5232f_c3538-r0/DellEMC-S5232f-P-10G/td3-s5232f-96x10G+8x100G.config.bcm b/device/dell/x86_64-dellemc_s5232f_c3538-r0/DellEMC-S5232f-P-10G/td3-s5232f-96x10G+8x100G.config.bcm index caf255d892e..6f62b720919 100644 --- a/device/dell/x86_64-dellemc_s5232f_c3538-r0/DellEMC-S5232f-P-10G/td3-s5232f-96x10G+8x100G.config.bcm +++ b/device/dell/x86_64-dellemc_s5232f_c3538-r0/DellEMC-S5232f-P-10G/td3-s5232f-96x10G+8x100G.config.bcm @@ -1,3 +1,4 @@ +sai_load_hw_config=/etc/bcm/flex/bcm56870_a0_issu/b870.6.4.1/ os=unix core_clock_frequency=1525 diff --git a/device/dell/x86_64-dellemc_s5232f_c3538-r0/DellEMC-S5232f-P-25G/td3-s5232f-96x25G+8x100G.config.bcm b/device/dell/x86_64-dellemc_s5232f_c3538-r0/DellEMC-S5232f-P-25G/td3-s5232f-96x25G+8x100G.config.bcm index 84bd873acc4..a4fccde1968 100644 --- a/device/dell/x86_64-dellemc_s5232f_c3538-r0/DellEMC-S5232f-P-25G/td3-s5232f-96x25G+8x100G.config.bcm +++ b/device/dell/x86_64-dellemc_s5232f_c3538-r0/DellEMC-S5232f-P-25G/td3-s5232f-96x25G+8x100G.config.bcm @@ -1,3 +1,4 @@ +sai_load_hw_config=/etc/bcm/flex/bcm56870_a0_issu/b870.6.4.1/ os=unix core_clock_frequency=1525 diff --git a/device/dell/x86_64-dellemc_s5232f_c3538-r0/plugins/sfputil.py b/device/dell/x86_64-dellemc_s5232f_c3538-r0/plugins/sfputil.py index f53e8e944d1..b56fcc5aafd 100644 --- a/device/dell/x86_64-dellemc_s5232f_c3538-r0/plugins/sfputil.py +++ b/device/dell/x86_64-dellemc_s5232f_c3538-r0/plugins/sfputil.py @@ -311,7 +311,7 @@ def get_transceiver_dom_info_dict(self, port_num): qsfp_dom_capability_raw = self._read_eeprom_specific_bytes( sysfsfile_eeprom, (offset_xcvr + XCVR_DOM_CAPABILITY_OFFSET), XCVR_DOM_CAPABILITY_WIDTH) if qsfp_dom_capability_raw is not None: - qspf_dom_capability_data = sfpi_obj.parse_qsfp_dom_capability( + qspf_dom_capability_data = sfpi_obj.parse_dom_capability( qsfp_dom_capability_raw, 0) else: return transceiver_dom_info_dict diff --git a/device/dell/x86_64-dellemc_s5248f_c3538-r0/DellEMC-S5248f-P-10G/td3-s5248f-10g.config.bcm b/device/dell/x86_64-dellemc_s5248f_c3538-r0/DellEMC-S5248f-P-10G/td3-s5248f-10g.config.bcm index 2369f459079..021f94dc32f 100644 --- a/device/dell/x86_64-dellemc_s5248f_c3538-r0/DellEMC-S5248f-P-10G/td3-s5248f-10g.config.bcm +++ b/device/dell/x86_64-dellemc_s5248f_c3538-r0/DellEMC-S5248f-P-10G/td3-s5248f-10g.config.bcm @@ -1,3 +1,4 @@ +sai_load_hw_config=/etc/bcm/flex/bcm56870_a0_issu/b870.6.4.1/ os=unix dpp_clock_ratio=2:3 oversubscribe_mode=1 diff --git a/device/dell/x86_64-dellemc_s5248f_c3538-r0/DellEMC-S5248f-P-25G/td3-s5248f-25g.config.bcm b/device/dell/x86_64-dellemc_s5248f_c3538-r0/DellEMC-S5248f-P-25G/td3-s5248f-25g.config.bcm index 4095c2d0a4f..2630512df0c 100644 --- a/device/dell/x86_64-dellemc_s5248f_c3538-r0/DellEMC-S5248f-P-25G/td3-s5248f-25g.config.bcm +++ b/device/dell/x86_64-dellemc_s5248f_c3538-r0/DellEMC-S5248f-P-25G/td3-s5248f-25g.config.bcm @@ -1,3 +1,4 @@ +sai_load_hw_config=/etc/bcm/flex/bcm56870_a0_issu/b870.6.4.1/ os=unix dpp_clock_ratio=2:3 diff --git a/device/dell/x86_64-dellemc_s5248f_c3538-r0/plugins/sfputil.py b/device/dell/x86_64-dellemc_s5248f_c3538-r0/plugins/sfputil.py index 2b941d02896..dba21ed11bd 100644 --- a/device/dell/x86_64-dellemc_s5248f_c3538-r0/plugins/sfputil.py +++ b/device/dell/x86_64-dellemc_s5248f_c3538-r0/plugins/sfputil.py @@ -358,7 +358,7 @@ def get_transceiver_dom_info_dict(self, port_num): qsfp_dom_capability_raw = self._read_eeprom_specific_bytes( sysfsfile_eeprom, (offset_xcvr + XCVR_DOM_CAPABILITY_OFFSET), XCVR_DOM_CAPABILITY_WIDTH) if qsfp_dom_capability_raw is not None: - qspf_dom_capability_data = sfpi_obj.parse_qsfp_dom_capability( + qspf_dom_capability_data = sfpi_obj.parse_dom_capability( qsfp_dom_capability_raw, 0) else: return transceiver_dom_info_dict diff --git a/device/dell/x86_64-dellemc_s5296f_c3538-r0/DellEMC-S5296f-P-10G/td3-s5296f-10g.config.bcm b/device/dell/x86_64-dellemc_s5296f_c3538-r0/DellEMC-S5296f-P-10G/td3-s5296f-10g.config.bcm index 7351e6908e7..ddc14d9363d 100644 --- a/device/dell/x86_64-dellemc_s5296f_c3538-r0/DellEMC-S5296f-P-10G/td3-s5296f-10g.config.bcm +++ b/device/dell/x86_64-dellemc_s5296f_c3538-r0/DellEMC-S5296f-P-10G/td3-s5296f-10g.config.bcm @@ -1,3 +1,4 @@ +sai_load_hw_config=/etc/bcm/flex/bcm56870_a0_issu/b870.6.4.1/ os=unix portmap_5.0=5:10 portmap_6.0=6:10 diff --git a/device/dell/x86_64-dellemc_s5296f_c3538-r0/DellEMC-S5296f-P-25G/td3-s5296f-25g.config.bcm b/device/dell/x86_64-dellemc_s5296f_c3538-r0/DellEMC-S5296f-P-25G/td3-s5296f-25g.config.bcm index 81a42406e75..dd0901f5d01 100644 --- a/device/dell/x86_64-dellemc_s5296f_c3538-r0/DellEMC-S5296f-P-25G/td3-s5296f-25g.config.bcm +++ b/device/dell/x86_64-dellemc_s5296f_c3538-r0/DellEMC-S5296f-P-25G/td3-s5296f-25g.config.bcm @@ -1,3 +1,4 @@ +sai_load_hw_config=/etc/bcm/flex/bcm56870_a0_issu/b870.6.4.1/ os=unix portmap_5.0=5:25 portmap_6.0=6:25 diff --git a/device/dell/x86_64-dellemc_s5296f_c3538-r0/plugins/sfputil.py b/device/dell/x86_64-dellemc_s5296f_c3538-r0/plugins/sfputil.py index 8b4ab0dcae1..c270ef47f1e 100644 --- a/device/dell/x86_64-dellemc_s5296f_c3538-r0/plugins/sfputil.py +++ b/device/dell/x86_64-dellemc_s5296f_c3538-r0/plugins/sfputil.py @@ -305,7 +305,7 @@ def get_transceiver_dom_info_dict(self, port_num): qsfp_dom_capability_raw = self._read_eeprom_specific_bytes( sysfsfile_eeprom, (offset_xcvr + XCVR_DOM_CAPABILITY_OFFSET), XCVR_DOM_CAPABILITY_WIDTH) if qsfp_dom_capability_raw is not None: - qspf_dom_capability_data = sfpi_obj.parse_qsfp_dom_capability(qsfp_dom_capability_raw, 0) + qspf_dom_capability_data = sfpi_obj.parse_dom_capability(qsfp_dom_capability_raw, 0) else: return transceiver_dom_info_dict diff --git a/device/dell/x86_64-dellemc_z9264f_c3538-r0/plugins/sfputil.py b/device/dell/x86_64-dellemc_z9264f_c3538-r0/plugins/sfputil.py index 5b01882762a..48f722a5d96 100644 --- a/device/dell/x86_64-dellemc_z9264f_c3538-r0/plugins/sfputil.py +++ b/device/dell/x86_64-dellemc_z9264f_c3538-r0/plugins/sfputil.py @@ -378,7 +378,7 @@ def get_transceiver_dom_info_dict(self, port_num): qsfp_dom_capability_raw = self._read_eeprom_specific_bytes( sysfsfile_eeprom, (offset_xcvr + XCVR_DOM_CAPABILITY_OFFSET), XCVR_DOM_CAPABILITY_WIDTH) if qsfp_dom_capability_raw is not None: - qspf_dom_capability_data = sfpi_obj.parse_qsfp_dom_capability(qsfp_dom_capability_raw, 0) + qspf_dom_capability_data = sfpi_obj.parse_dom_capability(qsfp_dom_capability_raw, 0) else: return transceiver_dom_info_dict diff --git a/device/dell/x86_64-dellemc_z9332f_d1508-r0/system_health_monitoring_config.json b/device/dell/x86_64-dellemc_z9332f_d1508-r0/system_health_monitoring_config.json new file mode 100644 index 00000000000..d52b24cf905 --- /dev/null +++ b/device/dell/x86_64-dellemc_z9332f_d1508-r0/system_health_monitoring_config.json @@ -0,0 +1,11 @@ +{ + "services_to_ignore": [], + "devices_to_ignore": ["asic","fan.speed"], + "user_defined_checkers": [], + "polling_interval": 60, + "led_color": { + "fault": "yellow", + "normal": "green", + "booting": "flash_green" + } +} diff --git a/device/delta/x86_64-delta_ag9032v2a-r0/Delta-ag9032v2a/td3-ag9032v2a-32x100G+1x10G.config.bcm b/device/delta/x86_64-delta_ag9032v2a-r0/Delta-ag9032v2a/td3-ag9032v2a-32x100G+1x10G.config.bcm index 2cef2f4261a..07600e0b8a6 100755 --- a/device/delta/x86_64-delta_ag9032v2a-r0/Delta-ag9032v2a/td3-ag9032v2a-32x100G+1x10G.config.bcm +++ b/device/delta/x86_64-delta_ag9032v2a-r0/Delta-ag9032v2a/td3-ag9032v2a-32x100G+1x10G.config.bcm @@ -1,3 +1,4 @@ +sai_load_hw_config=/etc/bcm/flex/bcm56870_a0_issu/b870.6.4.1/ pbmp_oversubscribe=0x00003fc000000ff0000003fc000001fe pbmp_xport_xe=0xffffffffffffffffffffffffffffffffffff core_clock_frequency=1525 diff --git a/device/inventec/x86_64-inventec_d6332-r0/INVENTEC-D6332/td3-d6332-32x100G-SR4.config.bcm b/device/inventec/x86_64-inventec_d6332-r0/INVENTEC-D6332/td3-d6332-32x100G-SR4.config.bcm index 27670075cf9..8fe7622f4b8 100644 --- a/device/inventec/x86_64-inventec_d6332-r0/INVENTEC-D6332/td3-d6332-32x100G-SR4.config.bcm +++ b/device/inventec/x86_64-inventec_d6332-r0/INVENTEC-D6332/td3-d6332-32x100G-SR4.config.bcm @@ -1,3 +1,4 @@ +sai_load_hw_config=/etc/bcm/flex/bcm56870_a0_issu/b870.6.4.1/ ### fix for sonic ptp_ts_pll_fref=50000000 ptp_bs_fref_0=50000000 diff --git a/device/inventec/x86_64-inventec_d6356-r0/INVENTEC-D6356/td3-d6356-48x25G-8x100G.config.bcm b/device/inventec/x86_64-inventec_d6356-r0/INVENTEC-D6356/td3-d6356-48x25G-8x100G.config.bcm index 57fd5cd5716..089207abd13 100644 --- a/device/inventec/x86_64-inventec_d6356-r0/INVENTEC-D6356/td3-d6356-48x25G-8x100G.config.bcm +++ b/device/inventec/x86_64-inventec_d6356-r0/INVENTEC-D6356/td3-d6356-48x25G-8x100G.config.bcm @@ -1,3 +1,4 @@ +sai_load_hw_config=/etc/bcm/flex/bcm56870_a0_issu/b870.6.4.1/ ### fix for sonic ptp_ts_pll_fref=50000000 ptp_bs_fref_0=50000000 diff --git a/device/juniper/x86_64-juniper_qfx5200-r0/plugins/sfputil.py b/device/juniper/x86_64-juniper_qfx5200-r0/plugins/sfputil.py index 54dbdacc1c2..db85347be3f 100644 --- a/device/juniper/x86_64-juniper_qfx5200-r0/plugins/sfputil.py +++ b/device/juniper/x86_64-juniper_qfx5200-r0/plugins/sfputil.py @@ -870,7 +870,7 @@ def get_transceiver_dom_info_dict(self, port_num): qsfp_dom_capability_raw = self._read_eeprom_specific_bytes( sysfsfile_eeprom, (offset_xcvr + XCVR_DOM_CAPABILITY_OFFSET), XCVR_DOM_CAPABILITY_WIDTH) if qsfp_dom_capability_raw is not None: - qspf_dom_capability_data = sfpi_obj.parse_qsfp_dom_capability(qsfp_dom_capability_raw, 0) + qspf_dom_capability_data = sfpi_obj.parse_dom_capability(qsfp_dom_capability_raw, 0) else: return None diff --git a/device/juniper/x86_64-juniper_qfx5210-r0/plugins/sfputil.py b/device/juniper/x86_64-juniper_qfx5210-r0/plugins/sfputil.py index a854f8fa291..673bb05ed10 100644 --- a/device/juniper/x86_64-juniper_qfx5210-r0/plugins/sfputil.py +++ b/device/juniper/x86_64-juniper_qfx5210-r0/plugins/sfputil.py @@ -583,7 +583,7 @@ def get_transceiver_dom_info_dict(self, port_num): qsfp_dom_capability_raw = self._read_eeprom_specific_bytes( sysfsfile_eeprom, (offset_xcvr + XCVR_DOM_CAPABILITY_OFFSET), XCVR_DOM_CAPABILITY_WIDTH) if qsfp_dom_capability_raw is not None: - qspf_dom_capability_data = sfpi_obj.parse_qsfp_dom_capability(qsfp_dom_capability_raw, 0) + qspf_dom_capability_data = sfpi_obj.parse_dom_capability(qsfp_dom_capability_raw, 0) else: return None diff --git a/device/mellanox/x86_64-mlnx_msn2700-r0/plugins/sfputil.py b/device/mellanox/x86_64-mlnx_msn2700-r0/plugins/sfputil.py index 954ed23d8ea..df60c5256f2 100644 --- a/device/mellanox/x86_64-mlnx_msn2700-r0/plugins/sfputil.py +++ b/device/mellanox/x86_64-mlnx_msn2700-r0/plugins/sfputil.py @@ -513,7 +513,7 @@ def get_transceiver_dom_info_dict(self, port_num): qsfp_dom_capability_raw = self._read_eeprom_specific_bytes_via_ethtool( port_num, (offset_xcvr + XCVR_DOM_CAPABILITY_OFFSET), XCVR_DOM_CAPABILITY_WIDTH) if qsfp_dom_capability_raw is not None: - qspf_dom_capability_data = sfpi_obj.parse_qsfp_dom_capability(qsfp_dom_capability_raw, 0) + qspf_dom_capability_data = sfpi_obj.parse_dom_capability(qsfp_dom_capability_raw, 0) else: return transceiver_dom_info_dict diff --git a/device/mellanox/x86_64-mlnx_msn3420-r0/ACS-MSN3420/hwsku.json b/device/mellanox/x86_64-mlnx_msn3420-r0/ACS-MSN3420/hwsku.json new file mode 100644 index 00000000000..59c3aa2c968 --- /dev/null +++ b/device/mellanox/x86_64-mlnx_msn3420-r0/ACS-MSN3420/hwsku.json @@ -0,0 +1,184 @@ +{ + "interfaces": { + "Ethernet0": { + "default_brkout_mode": "1x25G[10G,1G]" + }, + "Ethernet4": { + "default_brkout_mode": "1x25G[10G,1G]" + }, + "Ethernet8": { + "default_brkout_mode": "1x25G[10G,1G]" + }, + "Ethernet12": { + "default_brkout_mode": "1x25G[10G,1G]" + }, + "Ethernet16": { + "default_brkout_mode": "1x25G[10G,1G]" + }, + "Ethernet20": { + "default_brkout_mode": "1x25G[10G,1G]" + }, + "Ethernet24": { + "default_brkout_mode": "1x25G[10G,1G]" + }, + "Ethernet28": { + "default_brkout_mode": "1x25G[10G,1G]" + }, + "Ethernet32": { + "default_brkout_mode": "1x25G[10G,1G]" + }, + "Ethernet36": { + "default_brkout_mode": "1x25G[10G,1G]" + }, + "Ethernet40": { + "default_brkout_mode": "1x25G[10G,1G]" + }, + "Ethernet44": { + "default_brkout_mode": "1x25G[10G,1G]" + }, + "Ethernet48": { + "default_brkout_mode": "1x25G[10G,1G]" + }, + "Ethernet52": { + "default_brkout_mode": "1x25G[10G,1G]" + }, + "Ethernet56": { + "default_brkout_mode": "1x25G[10G,1G]" + }, + "Ethernet60": { + "default_brkout_mode": "1x25G[10G,1G]" + }, + "Ethernet64": { + "default_brkout_mode": "1x25G[10G,1G]" + }, + "Ethernet68": { + "default_brkout_mode": "1x25G[10G,1G]" + }, + "Ethernet72": { + "default_brkout_mode": "1x25G[10G,1G]" + }, + "Ethernet76": { + "default_brkout_mode": "1x25G[10G,1G]" + }, + "Ethernet80": { + "default_brkout_mode": "1x25G[10G,1G]" + }, + "Ethernet84": { + "default_brkout_mode": "1x25G[10G,1G]" + }, + "Ethernet88": { + "default_brkout_mode": "1x25G[10G,1G]" + }, + "Ethernet92": { + "default_brkout_mode": "1x25G[10G,1G]" + }, + "Ethernet96": { + "default_brkout_mode": "1x25G[10G,1G]" + }, + "Ethernet100": { + "default_brkout_mode": "1x25G[10G,1G]" + }, + "Ethernet104": { + "default_brkout_mode": "1x25G[10G,1G]" + }, + "Ethernet108": { + "default_brkout_mode": "1x25G[10G,1G]" + }, + "Ethernet112": { + "default_brkout_mode": "1x25G[10G,1G]" + }, + "Ethernet116": { + "default_brkout_mode": "1x25G[10G,1G]" + }, + "Ethernet120": { + "default_brkout_mode": "1x25G[10G,1G]" + }, + "Ethernet124": { + "default_brkout_mode": "1x25G[10G,1G]" + }, + "Ethernet128": { + "default_brkout_mode": "1x25G[10G,1G]" + }, + "Ethernet132": { + "default_brkout_mode": "1x25G[10G,1G]" + }, + "Ethernet136": { + "default_brkout_mode": "1x25G[10G,1G]" + }, + "Ethernet140": { + "default_brkout_mode": "1x25G[10G,1G]" + }, + "Ethernet144": { + "default_brkout_mode": "1x25G[10G,1G]" + }, + "Ethernet148": { + "default_brkout_mode": "1x25G[10G,1G]" + }, + "Ethernet152": { + "default_brkout_mode": "1x25G[10G,1G]" + }, + "Ethernet156": { + "default_brkout_mode": "1x25G[10G,1G]" + }, + "Ethernet160": { + "default_brkout_mode": "1x25G[10G,1G]" + }, + "Ethernet164": { + "default_brkout_mode": "1x25G[10G,1G]" + }, + "Ethernet168": { + "default_brkout_mode": "1x25G[10G,1G]" + }, + "Ethernet172": { + "default_brkout_mode": "1x25G[10G,1G]" + }, + "Ethernet176": { + "default_brkout_mode": "1x25G[10G,1G]" + }, + "Ethernet180": { + "default_brkout_mode": "1x25G[10G,1G]" + }, + "Ethernet184": { + "default_brkout_mode": "1x25G[10G,1G]" + }, + "Ethernet188": { + "default_brkout_mode": "1x25G[10G,1G]" + }, + "Ethernet192": { + "default_brkout_mode": "1x100G[50G,40G,25G,10G,1G]" + }, + "Ethernet196": { + "default_brkout_mode": "1x100G[50G,40G,25G,10G,1G]" + }, + "Ethernet200": { + "default_brkout_mode": "1x100G[50G,40G,25G,10G,1G]" + }, + "Ethernet204": { + "default_brkout_mode": "1x100G[50G,40G,25G,10G,1G]" + }, + "Ethernet208": { + "default_brkout_mode": "1x100G[50G,40G,25G,10G,1G]" + }, + "Ethernet212": { + "default_brkout_mode": "1x100G[50G,40G,25G,10G,1G]" + }, + "Ethernet216": { + "default_brkout_mode": "1x100G[50G,40G,25G,10G,1G]" + }, + "Ethernet220": { + "default_brkout_mode": "1x100G[50G,40G,25G,10G,1G]" + }, + "Ethernet224": { + "default_brkout_mode": "1x100G[50G,40G,25G,10G,1G]" + }, + "Ethernet228": { + "default_brkout_mode": "1x100G[50G,40G,25G,10G,1G]" + }, + "Ethernet232": { + "default_brkout_mode": "1x100G[50G,40G,25G,10G,1G]" + }, + "Ethernet236": { + "default_brkout_mode": "1x100G[50G,40G,25G,10G,1G]" + } + } +} diff --git a/device/mellanox/x86_64-mlnx_msn3420-r0/platform.json b/device/mellanox/x86_64-mlnx_msn3420-r0/platform.json new file mode 100644 index 00000000000..401cd4b660e --- /dev/null +++ b/device/mellanox/x86_64-mlnx_msn3420-r0/platform.json @@ -0,0 +1,364 @@ +{ + "interfaces": { + "Ethernet0": { + "index": "1", + "lanes": "0", + "alias_at_lanes": "etp1", + "breakout_modes": "1x25G[10G,1G]" + }, + "Ethernet4": { + "index": "2", + "lanes": "4", + "alias_at_lanes": "etp2", + "breakout_modes": "1x25G[10G,1G]" + }, + "Ethernet8": { + "index": "3", + "lanes": "8", + "alias_at_lanes": "etp3", + "breakout_modes": "1x25G[10G,1G]" + }, + "Ethernet12": { + "index": "4", + "lanes": "12", + "alias_at_lanes": "etp4", + "breakout_modes": "1x25G[10G,1G]" + }, + "Ethernet16": { + "index": "5", + "lanes": "16", + "alias_at_lanes": "etp5", + "breakout_modes": "1x25G[10G,1G]" + }, + "Ethernet20": { + "index": "6", + "lanes": "20", + "alias_at_lanes": "etp6", + "breakout_modes": "1x25G[10G,1G]" + }, + "Ethernet24": { + "index": "7", + "lanes": "24", + "alias_at_lanes": "etp7", + "breakout_modes": "1x25G[10G,1G]" + }, + "Ethernet28": { + "index": "8", + "lanes": "28", + "alias_at_lanes": "etp8", + "breakout_modes": "1x25G[10G,1G]" + }, + "Ethernet32": { + "index": "9", + "lanes": "32", + "alias_at_lanes": "etp9", + "breakout_modes": "1x25G[10G,1G]" + }, + "Ethernet36": { + "index": "10", + "lanes": "36", + "alias_at_lanes": "etp10", + "breakout_modes": "1x25G[10G,1G]" + }, + "Ethernet40": { + "index": "11", + "lanes": "40", + "alias_at_lanes": "etp11", + "breakout_modes": "1x25G[10G,1G]" + }, + "Ethernet44": { + "index": "12", + "lanes": "44", + "alias_at_lanes": "etp12", + "breakout_modes": "1x25G[10G,1G]" + }, + "Ethernet48": { + "index": "13", + "lanes": "48", + "alias_at_lanes": "etp13", + "breakout_modes": "1x25G[10G,1G]" + }, + "Ethernet52": { + "index": "14", + "lanes": "52", + "alias_at_lanes": "etp14", + "breakout_modes": "1x25G[10G,1G]" + }, + "Ethernet56": { + "index": "15", + "lanes": "56", + "alias_at_lanes": "etp15", + "breakout_modes": "1x25G[10G,1G]" + }, + "Ethernet60": { + "index": "16", + "lanes": "60", + "alias_at_lanes": "etp16", + "breakout_modes": "1x25G[10G,1G]" + }, + "Ethernet64": { + "index": "17", + "lanes": "64", + "alias_at_lanes": "etp17", + "breakout_modes": "1x25G[10G,1G]" + }, + "Ethernet68": { + "index": "18", + "lanes": "68", + "alias_at_lanes": "etp18", + "breakout_modes": "1x25G[10G,1G]" + }, + "Ethernet72": { + "index": "19", + "lanes": "72", + "alias_at_lanes": "etp19", + "breakout_modes": "1x25G[10G,1G]" + }, + "Ethernet76": { + "index": "20", + "lanes": "76", + "alias_at_lanes": "etp20", + "breakout_modes": "1x25G[10G,1G]" + }, + "Ethernet80": { + "index": "21", + "lanes": "80", + "alias_at_lanes": "etp21", + "breakout_modes": "1x25G[10G,1G]" + }, + "Ethernet84": { + "index": "22", + "lanes": "84", + "alias_at_lanes": "etp22", + "breakout_modes": "1x25G[10G,1G]" + }, + "Ethernet88": { + "index": "23", + "lanes": "88", + "alias_at_lanes": "etp23", + "breakout_modes": "1x25G[10G,1G]" + }, + "Ethernet92": { + "index": "24", + "lanes": "92", + "alias_at_lanes": "etp24", + "breakout_modes": "1x25G[10G,1G]" + }, + "Ethernet96": { + "index": "25", + "lanes": "96", + "alias_at_lanes": "etp25", + "breakout_modes": "1x25G[10G,1G]" + }, + "Ethernet100": { + "index": "26", + "lanes": "100", + "alias_at_lanes": "etp26", + "breakout_modes": "1x25G[10G,1G]" + }, + "Ethernet104": { + "index": "27", + "lanes": "104", + "alias_at_lanes": "etp27", + "breakout_modes": "1x25G[10G,1G]" + }, + "Ethernet108": { + "index": "28", + "lanes": "108", + "alias_at_lanes": "etp28", + "breakout_modes": "1x25G[10G,1G]" + }, + "Ethernet112": { + "index": "29", + "lanes": "112", + "alias_at_lanes": "etp29", + "breakout_modes": "1x25G[10G,1G]" + }, + "Ethernet116": { + "index": "30", + "lanes": "116", + "alias_at_lanes": "etp30", + "breakout_modes": "1x25G[10G,1G]" + }, + "Ethernet120": { + "index": "31", + "lanes": "120", + "alias_at_lanes": "etp31", + "breakout_modes": "1x25G[10G,1G]" + }, + "Ethernet124": { + "index": "32", + "lanes": "124", + "alias_at_lanes": "etp32", + "breakout_modes": "1x25G[10G,1G]" + }, + "Ethernet128": { + "index": "33", + "lanes": "128", + "alias_at_lanes": "etp33", + "breakout_modes": "1x25G[10G,1G]" + }, + "Ethernet132": { + "index": "34", + "lanes": "132", + "alias_at_lanes": "etp34", + "breakout_modes": "1x25G[10G,1G]" + }, + "Ethernet136": { + "index": "35", + "lanes": "136", + "alias_at_lanes": "etp35", + "breakout_modes": "1x25G[10G,1G]" + }, + "Ethernet140": { + "index": "36", + "lanes": "140", + "alias_at_lanes": "etp36", + "breakout_modes": "1x25G[10G,1G]" + }, + "Ethernet144": { + "index": "37", + "lanes": "144", + "alias_at_lanes": "etp37", + "breakout_modes": "1x25G[10G,1G]" + }, + "Ethernet148": { + "index": "38", + "lanes": "148", + "alias_at_lanes": "etp38", + "breakout_modes": "1x25G[10G,1G]" + }, + "Ethernet152": { + "index": "39", + "lanes": "152", + "alias_at_lanes": "etp39", + "breakout_modes": "1x25G[10G,1G]" + }, + "Ethernet156": { + "index": "40", + "lanes": "156", + "alias_at_lanes": "etp40", + "breakout_modes": "1x25G[10G,1G]" + }, + "Ethernet160": { + "index": "41", + "lanes": "160", + "alias_at_lanes": "etp41", + "breakout_modes": "1x25G[10G,1G]" + }, + "Ethernet164": { + "index": "42", + "lanes": "164", + "alias_at_lanes": "etp42", + "breakout_modes": "1x25G[10G,1G]" + }, + "Ethernet168": { + "index": "43", + "lanes": "168", + "alias_at_lanes": "etp43", + "breakout_modes": "1x25G[10G,1G]" + }, + "Ethernet172": { + "index": "44", + "lanes": "172", + "alias_at_lanes": "etp44", + "breakout_modes": "1x25G[10G,1G]" + }, + "Ethernet176": { + "index": "45", + "lanes": "176", + "alias_at_lanes": "etp45", + "breakout_modes": "1x25G[10G,1G]" + }, + "Ethernet180": { + "index": "46", + "lanes": "180", + "alias_at_lanes": "etp46", + "breakout_modes": "1x25G[10G,1G]" + }, + "Ethernet184": { + "index": "47", + "lanes": "184", + "alias_at_lanes": "etp47", + "breakout_modes": "1x25G[10G,1G]" + }, + "Ethernet188": { + "index": "48", + "lanes": "188", + "alias_at_lanes": "etp48", + "breakout_modes": "1x25G[10G,1G]" + }, + "Ethernet192": { + "index": "49,49,49,49", + "lanes": "192,193,194,195", + "alias_at_lanes": "etp49a, etp49b, etp49c, etp49d", + "breakout_modes": "1x100G[50G,40G,25G,10G,1G],2x50G[40G,25G,10G,1G],4x25G[10G,1G]" + }, + "Ethernet196": { + "index": "50,50,50,50", + "lanes": "196,197,198,199", + "alias_at_lanes": "etp50a, etp50b, etp50c, etp50d", + "breakout_modes": "1x100G[50G,40G,25G,10G,1G],2x50G[40G,25G,10G,1G],4x25G[10G,1G]" + }, + "Ethernet200": { + "index": "51,51,51,51", + "lanes": "200,201,202,203", + "alias_at_lanes": "etp51a, etp51b, etp51c, etp51d", + "breakout_modes": "1x100G[50G,40G,25G,10G,1G],2x50G[40G,25G,10G,1G],4x25G[10G,1G]" + }, + "Ethernet204": { + "index": "52,52,52,52", + "lanes": "204,205,206,207", + "alias_at_lanes": "etp52a, etp52b, etp52c, etp52d", + "breakout_modes": "1x100G[50G,40G,25G,10G,1G],2x50G[40G,25G,10G,1G],4x25G[10G,1G]" + }, + "Ethernet208": { + "index": "53,53,53,53", + "lanes": "208,209,210,211", + "alias_at_lanes": "etp53a, etp53b, etp53c, etp53d", + "breakout_modes": "1x100G[50G,40G,25G,10G,1G],2x50G[40G,25G,10G,1G],4x25G[10G,1G]" + }, + "Ethernet212": { + "index": "54,54,54,54", + "lanes": "212,213,214,215", + "alias_at_lanes": "etp54a, etp54b, etp54c, etp54d", + "breakout_modes": "1x100G[50G,40G,25G,10G,1G],2x50G[40G,25G,10G,1G],4x25G[10G,1G]" + }, + "Ethernet216": { + "index": "55,55,55,55", + "lanes": "216,217,218,219", + "alias_at_lanes": "etp55a, etp55b, etp55c, etp55d", + "breakout_modes": "1x100G[50G,40G,25G,10G,1G],2x50G[40G,25G,10G,1G],4x25G[10G,1G]" + }, + "Ethernet220": { + "index": "56,56,56,56", + "lanes": "220,221,222,223", + "alias_at_lanes": "etp56a, etp56b, etp56c, etp56d", + "breakout_modes": "1x100G[50G,40G,25G,10G,1G],2x50G[40G,25G,10G,1G],4x25G[10G,1G]" + }, + "Ethernet224": { + "index": "57,57,57,57", + "lanes": "224,225,226,227", + "alias_at_lanes": "etp57a, etp57b, etp57c, etp57d", + "breakout_modes": "1x100G[50G,40G,25G,10G,1G],2x50G[40G,25G,10G,1G],4x25G[10G,1G]" + }, + "Ethernet228": { + "index": "58,58,58,58", + "lanes": "228,229,230,231", + "alias_at_lanes": "etp58a, etp58b, etp58c, etp58d", + "breakout_modes": "1x100G[50G,40G,25G,10G,1G],2x50G[40G,25G,10G,1G],4x25G[10G,1G]" + }, + "Ethernet232": { + "index": "59,59,59,59", + "lanes": "232,233,234,235", + "alias_at_lanes": "etp59a, etp59b, etp59c, etp59d", + "breakout_modes": "1x100G[50G,40G,25G,10G,1G],2x50G[40G,25G,10G,1G],4x25G[10G,1G]" + }, + "Ethernet236": { + "index": "60,60,60,60", + "lanes": "236,237,238,239", + "alias_at_lanes": "etp60a, etp60b, etp60c, etp60d", + "breakout_modes": "1x100G[50G,40G,25G,10G,1G],2x50G[40G,25G,10G,1G],4x25G[10G,1G]" + } + } +} diff --git a/device/mellanox/x86_64-mlnx_msn3700c-r0/ACS-MSN3700C/hwsku.json b/device/mellanox/x86_64-mlnx_msn3700c-r0/ACS-MSN3700C/hwsku.json index 7c5a8c1d95d..cac9d1d14da 100644 --- a/device/mellanox/x86_64-mlnx_msn3700c-r0/ACS-MSN3700C/hwsku.json +++ b/device/mellanox/x86_64-mlnx_msn3700c-r0/ACS-MSN3700C/hwsku.json @@ -1,100 +1,100 @@ { "interfaces": { "Ethernet0": { - "default_brkout_mode": "1x100G[40G]" + "default_brkout_mode": "1x100G[50G,40G,25G,10G,1G]" }, "Ethernet4": { - "default_brkout_mode": "1x100G[40G]" + "default_brkout_mode": "1x100G[50G,40G,25G,10G,1G]" }, "Ethernet8": { - "default_brkout_mode": "1x100G[40G]" + "default_brkout_mode": "1x100G[50G,40G,25G,10G,1G]" }, "Ethernet12": { - "default_brkout_mode": "1x100G[40G]" + "default_brkout_mode": "1x100G[50G,40G,25G,10G,1G]" }, "Ethernet16": { - "default_brkout_mode": "1x100G[40G]" + "default_brkout_mode": "1x100G[50G,40G,25G,10G,1G]" }, "Ethernet20": { - "default_brkout_mode": "1x100G[40G]" + "default_brkout_mode": "1x100G[50G,40G,25G,10G,1G]" }, "Ethernet24": { - "default_brkout_mode": "1x100G[40G]" + "default_brkout_mode": "1x100G[50G,40G,25G,10G,1G]" }, "Ethernet28": { - "default_brkout_mode": "1x100G[40G]" + "default_brkout_mode": "1x100G[50G,40G,25G,10G,1G]" }, "Ethernet32": { - "default_brkout_mode": "1x100G[40G]" + "default_brkout_mode": "1x100G[50G,40G,25G,10G,1G]" }, "Ethernet36": { - "default_brkout_mode": "1x100G[40G]" + "default_brkout_mode": "1x100G[50G,40G,25G,10G,1G]" }, "Ethernet40": { - "default_brkout_mode": "1x100G[40G]" + "default_brkout_mode": "1x100G[50G,40G,25G,10G,1G]" }, "Ethernet44": { - "default_brkout_mode": "1x100G[40G]" + "default_brkout_mode": "1x100G[50G,40G,25G,10G,1G]" }, "Ethernet48": { - "default_brkout_mode": "1x100G[40G]" + "default_brkout_mode": "1x100G[50G,40G,25G,10G,1G]" }, "Ethernet52": { - "default_brkout_mode": "1x100G[40G]" + "default_brkout_mode": "1x100G[50G,40G,25G,10G,1G]" }, "Ethernet56": { - "default_brkout_mode": "1x100G[40G]" + "default_brkout_mode": "1x100G[50G,40G,25G,10G,1G]" }, "Ethernet60": { - "default_brkout_mode": "1x100G[40G]" + "default_brkout_mode": "1x100G[50G,40G,25G,10G,1G]" }, "Ethernet64": { - "default_brkout_mode": "1x100G[40G]" + "default_brkout_mode": "1x100G[50G,40G,25G,10G,1G]" }, "Ethernet68": { - "default_brkout_mode": "1x100G[40G]" + "default_brkout_mode": "1x100G[50G,40G,25G,10G,1G]" }, "Ethernet72": { - "default_brkout_mode": "1x100G[40G]" + "default_brkout_mode": "1x100G[50G,40G,25G,10G,1G]" }, "Ethernet76": { - "default_brkout_mode": "1x100G[40G]" + "default_brkout_mode": "1x100G[50G,40G,25G,10G,1G]" }, "Ethernet80": { - "default_brkout_mode": "1x100G[40G]" + "default_brkout_mode": "1x100G[50G,40G,25G,10G,1G]" }, "Ethernet84": { - "default_brkout_mode": "1x100G[40G]" + "default_brkout_mode": "1x100G[50G,40G,25G,10G,1G]" }, "Ethernet88": { - "default_brkout_mode": "1x100G[40G]" + "default_brkout_mode": "1x100G[50G,40G,25G,10G,1G]" }, "Ethernet92": { - "default_brkout_mode": "1x100G[40G]" + "default_brkout_mode": "1x100G[50G,40G,25G,10G,1G]" }, "Ethernet96": { - "default_brkout_mode": "1x100G[40G]" + "default_brkout_mode": "1x100G[50G,40G,25G,10G,1G]" }, "Ethernet100": { - "default_brkout_mode": "1x100G[40G]" + "default_brkout_mode": "1x100G[50G,40G,25G,10G,1G]" }, "Ethernet104": { - "default_brkout_mode": "1x100G[40G]" + "default_brkout_mode": "1x100G[50G,40G,25G,10G,1G]" }, "Ethernet108": { - "default_brkout_mode": "1x100G[40G]" + "default_brkout_mode": "1x100G[50G,40G,25G,10G,1G]" }, "Ethernet112": { - "default_brkout_mode": "1x100G[40G]" + "default_brkout_mode": "1x100G[50G,40G,25G,10G,1G]" }, "Ethernet116": { - "default_brkout_mode": "1x100G[40G]" + "default_brkout_mode": "1x100G[50G,40G,25G,10G,1G]" }, "Ethernet120": { - "default_brkout_mode": "1x100G[40G]" + "default_brkout_mode": "1x100G[50G,40G,25G,10G,1G]" }, "Ethernet124": { - "default_brkout_mode": "1x100G[40G]" + "default_brkout_mode": "1x100G[50G,40G,25G,10G,1G]" } } } diff --git a/device/mellanox/x86_64-mlnx_msn3700c-r0/platform.json b/device/mellanox/x86_64-mlnx_msn3700c-r0/platform.json index 26eb952ab52..33db99b06a3 100644 --- a/device/mellanox/x86_64-mlnx_msn3700c-r0/platform.json +++ b/device/mellanox/x86_64-mlnx_msn3700c-r0/platform.json @@ -4,193 +4,193 @@ "index": "1,1,1,1", "lanes": "0,1,2,3", "alias_at_lanes": "etp1a, etp1b, etp1c, etp1d", - "breakout_modes": "1x100G[40G],2x50G,4x25G[10G]" + "breakout_modes": "1x100G[50G,40G,25G,10G,1G],2x50G[40G,25G,10G,1G],4x25G[10G,1G]" }, "Ethernet4": { "index": "2,2,2,2", "lanes": "4,5,6,7", "alias_at_lanes": "etp2a, etp2b, etp2c, etp2d", - "breakout_modes": "1x100G[40G],2x50G,4x25G[10G]" + "breakout_modes": "1x100G[50G,40G,25G,10G,1G],2x50G[40G,25G,10G,1G],4x25G[10G,1G]" }, "Ethernet8": { "index": "3,3,3,3", "lanes": "8,9,10,11", "alias_at_lanes": "etp3a, etp3b, etp3c, etp3d", - "breakout_modes": "1x100G[40G],2x50G,4x25G[10G]" + "breakout_modes": "1x100G[50G,40G,25G,10G,1G],2x50G[40G,25G,10G,1G],4x25G[10G,1G]" }, "Ethernet12": { "index": "4,4,4,4", "lanes": "12,13,14,15", "alias_at_lanes": "etp4a, etp4b, etp4c, etp4d", - "breakout_modes": "1x100G[40G],2x50G,4x25G[10G]" + "breakout_modes": "1x100G[50G,40G,25G,10G,1G],2x50G[40G,25G,10G,1G],4x25G[10G,1G]" }, "Ethernet16": { "index": "5,5,5,5", "lanes": "16,17,18,19", "alias_at_lanes": "etp5a, etp5b, etp5c, etp5d", - "breakout_modes": "1x100G[40G],2x50G,4x25G[10G]" + "breakout_modes": "1x100G[50G,40G,25G,10G,1G],2x50G[40G,25G,10G,1G],4x25G[10G,1G]" }, "Ethernet20": { "index": "6,6,6,6", "lanes": "20,21,22,23", "alias_at_lanes": "etp6a, etp6b, etp6c, etp6d", - "breakout_modes": "1x100G[40G],2x50G,4x25G[10G]" + "breakout_modes": "1x100G[50G,40G,25G,10G,1G],2x50G[40G,25G,10G,1G],4x25G[10G,1G]" }, "Ethernet24": { "index": "7,7,7,7", "lanes": "24,25,26,27", "alias_at_lanes": "etp7a, etp7b, etp7c, etp7d", - "breakout_modes": "1x100G[40G],2x50G,4x25G[10G]" + "breakout_modes": "1x100G[50G,40G,25G,10G,1G],2x50G[40G,25G,10G,1G],4x25G[10G,1G]" }, "Ethernet28": { "index": "8,8,8,8", "lanes": "28,29,30,31", "alias_at_lanes": "etp8a, etp8b, etp8c, etp8d", - "breakout_modes": "1x100G[40G],2x50G,4x25G[10G]" + "breakout_modes": "1x100G[50G,40G,25G,10G,1G],2x50G[40G,25G,10G,1G],4x25G[10G,1G]" }, "Ethernet32": { "index": "9,9,9,9", "lanes": "32,33,34,35", "alias_at_lanes": "etp9a, etp9b, etp9c, etp9d", - "breakout_modes": "1x100G[40G],2x50G,4x25G[10G]" + "breakout_modes": "1x100G[50G,40G,25G,10G,1G],2x50G[40G,25G,10G,1G],4x25G[10G,1G]" }, "Ethernet36": { "index": "10,10,10,10", "lanes": "36,37,38,39", "alias_at_lanes": "etp10a, etp10b, etp10c, etp10d", - "breakout_modes": "1x100G[40G],2x50G,4x25G[10G]" + "breakout_modes": "1x100G[50G,40G,25G,10G,1G],2x50G[40G,25G,10G,1G],4x25G[10G,1G]" }, "Ethernet40": { "index": "11,11,11,11", "lanes": "40,41,42,43", "alias_at_lanes": "etp11a, etp11b, etp11c, etp11d", - "breakout_modes": "1x100G[40G],2x50G,4x25G[10G]" + "breakout_modes": "1x100G[50G,40G,25G,10G,1G],2x50G[40G,25G,10G,1G],4x25G[10G,1G]" }, "Ethernet44": { "index": "12,12,12,12", "lanes": "44,45,46,47", "alias_at_lanes": "etp12a, etp12b, etp12c, etp12d", - "breakout_modes": "1x100G[40G],2x50G,4x25G[10G]" + "breakout_modes": "1x100G[50G,40G,25G,10G,1G],2x50G[40G,25G,10G,1G],4x25G[10G,1G]" }, "Ethernet48": { "index": "13,13,13,13", "lanes": "48,49,50,51", "alias_at_lanes": "etp13a, etp13b, etp13c, etp13d", - "breakout_modes": "1x100G[40G],2x50G,4x25G[10G]" + "breakout_modes": "1x100G[50G,40G,25G,10G,1G],2x50G[40G,25G,10G,1G],4x25G[10G,1G]" }, "Ethernet52": { "index": "14,14,14,14", "lanes": "52,53,54,55", "alias_at_lanes": "etp14a, etp14b, etp14c, etp14d", - "breakout_modes": "1x100G[40G],2x50G,4x25G[10G]" + "breakout_modes": "1x100G[50G,40G,25G,10G,1G],2x50G[40G,25G,10G,1G],4x25G[10G,1G]" }, "Ethernet56": { "index": "15,15,15,15", "lanes": "56,57,58,59", "alias_at_lanes": "etp15a, etp15b, etp15c, etp15d", - "breakout_modes": "1x100G[40G],2x50G,4x25G[10G]" + "breakout_modes": "1x100G[50G,40G,25G,10G,1G],2x50G[40G,25G,10G,1G],4x25G[10G,1G]" }, "Ethernet60": { "index": "16,16,16,16", "lanes": "60,61,62,63", "alias_at_lanes": "etp16a, etp16b, etp16c, etp16d", - "breakout_modes": "1x100G[40G],2x50G,4x25G[10G]" + "breakout_modes": "1x100G[50G,40G,25G,10G,1G],2x50G[40G,25G,10G,1G],4x25G[10G,1G]" }, "Ethernet64": { "index": "17,17,17,17", "lanes": "64,65,66,67", "alias_at_lanes": "etp17a, etp17b, etp17c, etp17d", - "breakout_modes": "1x100G[40G],2x50G,4x25G[10G]" + "breakout_modes": "1x100G[50G,40G,25G,10G,1G],2x50G[40G,25G,10G,1G],4x25G[10G,1G]" }, "Ethernet68": { "index": "18,18,18,18", "lanes": "68,69,70,71", "alias_at_lanes": "etp18a, etp18b, etp18c, etp18d", - "breakout_modes": "1x100G[40G],2x50G,4x25G[10G]" + "breakout_modes": "1x100G[50G,40G,25G,10G,1G],2x50G[40G,25G,10G,1G],4x25G[10G,1G]" }, "Ethernet72": { "index": "19,19,19,19", "lanes": "72,73,74,75", "alias_at_lanes": "etp19a, etp19b, etp19c, etp19d", - "breakout_modes": "1x100G[40G],2x50G,4x25G[10G]" + "breakout_modes": "1x100G[50G,40G,25G,10G,1G],2x50G[40G,25G,10G,1G],4x25G[10G,1G]" }, "Ethernet76": { "index": "20,20,20,20", "lanes": "76,77,78,79", "alias_at_lanes": "etp20a, etp20b, etp20c, etp20d", - "breakout_modes": "1x100G[40G],2x50G,4x25G[10G]" + "breakout_modes": "1x100G[50G,40G,25G,10G,1G],2x50G[40G,25G,10G,1G],4x25G[10G,1G]" }, "Ethernet80": { "index": "21,21,21,21", "lanes": "80,81,82,83", "alias_at_lanes": "etp21a, etp21b, etp21c, etp21d", - "breakout_modes": "1x100G[40G],2x50G,4x25G[10G]" + "breakout_modes": "1x100G[50G,40G,25G,10G,1G],2x50G[40G,25G,10G,1G],4x25G[10G,1G]" }, "Ethernet84": { "index": "22,22,22,22", "lanes": "84,85,86,87", "alias_at_lanes": "etp22a, etp22b, etp22c, etp22d", - "breakout_modes": "1x100G[40G],2x50G,4x25G[10G]" + "breakout_modes": "1x100G[50G,40G,25G,10G,1G],2x50G[40G,25G,10G,1G],4x25G[10G,1G]" }, "Ethernet88": { "index": "23,23,23,23", "lanes": "88,89,90,91", "alias_at_lanes": "etp23a, etp23b, etp23c, etp23d", - "breakout_modes": "1x100G[40G],2x50G,4x25G[10G]" + "breakout_modes": "1x100G[50G,40G,25G,10G,1G],2x50G[40G,25G,10G,1G],4x25G[10G,1G]" }, "Ethernet92": { "index": "24,24,24,24", "lanes": "92,93,94,95", "alias_at_lanes": "etp24a, etp24b, etp24c, etp24d", - "breakout_modes": "1x100G[40G],2x50G,4x25G[10G]" + "breakout_modes": "1x100G[50G,40G,25G,10G,1G],2x50G[40G,25G,10G,1G],4x25G[10G,1G]" }, "Ethernet96": { "index": "25,25,25,25", "lanes": "96,97,98,99", "alias_at_lanes": "etp25a, etp25b, etp25c, etp25d", - "breakout_modes": "1x100G[40G],2x50G,4x25G[10G]" + "breakout_modes": "1x100G[50G,40G,25G,10G,1G],2x50G[40G,25G,10G,1G],4x25G[10G,1G]" }, "Ethernet100": { "index": "26,26,26,26", "lanes": "100,101,102,103", "alias_at_lanes": "etp26a, etp26b, etp26c, etp26d", - "breakout_modes": "1x100G[40G],2x50G,4x25G[10G]" + "breakout_modes": "1x100G[50G,40G,25G,10G,1G],2x50G[40G,25G,10G,1G],4x25G[10G,1G]" }, "Ethernet104": { "index": "27,27,27,27", "lanes": "104,105,106,107", "alias_at_lanes": "etp27a, etp27b, etp27c, etp27d", - "breakout_modes": "1x100G[40G],2x50G,4x25G[10G]" + "breakout_modes": "1x100G[50G,40G,25G,10G,1G],2x50G[40G,25G,10G,1G],4x25G[10G,1G]" }, "Ethernet108": { "index": "28,28,28,28", "lanes": "108,109,110,111", "alias_at_lanes": "etp28a, etp28b, etp28c, etp28d", - "breakout_modes": "1x100G[40G],2x50G,4x25G[10G]" + "breakout_modes": "1x100G[50G,40G,25G,10G,1G],2x50G[40G,25G,10G,1G],4x25G[10G,1G]" }, "Ethernet112": { "index": "29,29,29,29", "lanes": "112,113,114,115", "alias_at_lanes": "etp29a, etp29b, etp29c, etp29d", - "breakout_modes": "1x100G[40G],2x50G,4x25G[10G]" + "breakout_modes": "1x100G[50G,40G,25G,10G,1G],2x50G[40G,25G,10G,1G],4x25G[10G,1G]" }, "Ethernet116": { "index": "30,30,30,30", "lanes": "116,117,118,119", "alias_at_lanes": "etp30a, etp30b, etp30c, etp30d", - "breakout_modes": "1x100G[40G],2x50G,4x25G[10G]" + "breakout_modes": "1x100G[50G,40G,25G,10G,1G],2x50G[40G,25G,10G,1G],4x25G[10G,1G]" }, "Ethernet120": { "index": "31,31,31,31", "lanes": "120,121,122,123", "alias_at_lanes": "etp31a, etp31b, etp31c, etp31d", - "breakout_modes": "1x100G[40G],2x50G,4x25G[10G]" + "breakout_modes": "1x100G[50G,40G,25G,10G,1G],2x50G[40G,25G,10G,1G],4x25G[10G,1G]" }, "Ethernet124": { "index": "32,32,32,32", "lanes": "124,125,126,127", "alias_at_lanes": "etp32a, etp32b, etp32c, etp32d", - "breakout_modes": "1x100G[40G],2x50G,4x25G[10G]" + "breakout_modes": "1x100G[50G,40G,25G,10G,1G],2x50G[40G,25G,10G,1G],4x25G[10G,1G]" } } } diff --git a/device/mellanox/x86_64-mlnx_msn4410-r0/plugins/sfputil.py b/device/mellanox/x86_64-mlnx_msn4410-r0/plugins/sfputil.py index 336d729e95a..c94b65881fe 100644 --- a/device/mellanox/x86_64-mlnx_msn4410-r0/plugins/sfputil.py +++ b/device/mellanox/x86_64-mlnx_msn4410-r0/plugins/sfputil.py @@ -488,7 +488,7 @@ def get_transceiver_dom_info_dict(self, port_num): # in SFF-8636 dom capability definitions evolving with the versions. qsfp_dom_capability_raw = self._read_eeprom_specific_bytes_via_ethtool(port_num, (offset_xcvr + XCVR_DOM_CAPABILITY_OFFSET), XCVR_DOM_CAPABILITY_WIDTH) if qsfp_dom_capability_raw is not None: - qspf_dom_capability_data = sfpi_obj.parse_qsfp_dom_capability(qsfp_dom_capability_raw, 0) + qspf_dom_capability_data = sfpi_obj.parse_dom_capability(qsfp_dom_capability_raw, 0) else: return transceiver_dom_info_dict diff --git a/device/mellanox/x86_64-mlnx_msn4700-r0/ACS-MSN4700/hwsku.json b/device/mellanox/x86_64-mlnx_msn4700-r0/ACS-MSN4700/hwsku.json index 4c3dee3d17a..c226252e525 100644 --- a/device/mellanox/x86_64-mlnx_msn4700-r0/ACS-MSN4700/hwsku.json +++ b/device/mellanox/x86_64-mlnx_msn4700-r0/ACS-MSN4700/hwsku.json @@ -1,100 +1,100 @@ { "interfaces": { "Ethernet0": { - "default_brkout_mode": "1x400G[200G]" - }, + "default_brkout_mode": "1x400G[200G,100G,50G,40G,25G,10G,1G]" + }, "Ethernet8": { - "default_brkout_mode": "1x400G[200G]" - }, + "default_brkout_mode": "1x400G[200G,100G,50G,40G,25G,10G,1G]" + }, "Ethernet16": { - "default_brkout_mode": "1x400G[200G]" - }, + "default_brkout_mode": "1x400G[200G,100G,50G,40G,25G,10G,1G]" + }, "Ethernet24": { - "default_brkout_mode": "1x400G[200G]" - }, + "default_brkout_mode": "1x400G[200G,100G,50G,40G,25G,10G,1G]" + }, "Ethernet32": { - "default_brkout_mode": "1x400G[200G]" - }, + "default_brkout_mode": "1x400G[200G,100G,50G,40G,25G,10G,1G]" + }, "Ethernet40": { - "default_brkout_mode": "1x400G[200G]" - }, + "default_brkout_mode": "1x400G[200G,100G,50G,40G,25G,10G,1G]" + }, "Ethernet48": { - "default_brkout_mode": "1x400G[200G]" - }, + "default_brkout_mode": "1x400G[200G,100G,50G,40G,25G,10G,1G]" + }, "Ethernet56": { - "default_brkout_mode": "1x400G[200G]" - }, + "default_brkout_mode": "1x400G[200G,100G,50G,40G,25G,10G,1G]" + }, "Ethernet64": { - "default_brkout_mode": "1x400G[200G]" - }, + "default_brkout_mode": "1x400G[200G,100G,50G,40G,25G,10G,1G]" + }, "Ethernet72": { - "default_brkout_mode": "1x400G[200G]" - }, + "default_brkout_mode": "1x400G[200G,100G,50G,40G,25G,10G,1G]" + }, "Ethernet80": { - "default_brkout_mode": "1x400G[200G]" - }, + "default_brkout_mode": "1x400G[200G,100G,50G,40G,25G,10G,1G]" + }, "Ethernet88": { - "default_brkout_mode": "1x400G[200G]" - }, + "default_brkout_mode": "1x400G[200G,100G,50G,40G,25G,10G,1G]" + }, "Ethernet96": { - "default_brkout_mode": "1x400G[200G]" - }, + "default_brkout_mode": "1x400G[200G,100G,50G,40G,25G,10G,1G]" + }, "Ethernet104": { - "default_brkout_mode": "1x400G[200G]" - }, + "default_brkout_mode": "1x400G[200G,100G,50G,40G,25G,10G,1G]" + }, "Ethernet112": { - "default_brkout_mode": "1x400G[200G]" - }, + "default_brkout_mode": "1x400G[200G,100G,50G,40G,25G,10G,1G]" + }, "Ethernet120": { - "default_brkout_mode": "1x400G[200G]" - }, + "default_brkout_mode": "1x400G[200G,100G,50G,40G,25G,10G,1G]" + }, "Ethernet128": { - "default_brkout_mode": "1x400G[200G]" - }, + "default_brkout_mode": "1x400G[200G,100G,50G,40G,25G,10G,1G]" + }, "Ethernet136": { - "default_brkout_mode": "1x400G[200G]" - }, + "default_brkout_mode": "1x400G[200G,100G,50G,40G,25G,10G,1G]" + }, "Ethernet144": { - "default_brkout_mode": "1x400G[200G]" - }, + "default_brkout_mode": "1x400G[200G,100G,50G,40G,25G,10G,1G]" + }, "Ethernet152": { - "default_brkout_mode": "1x400G[200G]" - }, + "default_brkout_mode": "1x400G[200G,100G,50G,40G,25G,10G,1G]" + }, "Ethernet160": { - "default_brkout_mode": "1x400G[200G]" - }, + "default_brkout_mode": "1x400G[200G,100G,50G,40G,25G,10G,1G]" + }, "Ethernet168": { - "default_brkout_mode": "1x400G[200G]" - }, + "default_brkout_mode": "1x400G[200G,100G,50G,40G,25G,10G,1G]" + }, "Ethernet176": { - "default_brkout_mode": "1x400G[200G]" - }, + "default_brkout_mode": "1x400G[200G,100G,50G,40G,25G,10G,1G]" + }, "Ethernet184": { - "default_brkout_mode": "1x400G[200G]" - }, + "default_brkout_mode": "1x400G[200G,100G,50G,40G,25G,10G,1G]" + }, "Ethernet192": { - "default_brkout_mode": "1x400G[200G]" - }, + "default_brkout_mode": "1x400G[200G,100G,50G,40G,25G,10G,1G]" + }, "Ethernet200": { - "default_brkout_mode": "1x400G[200G]" - }, + "default_brkout_mode": "1x400G[200G,100G,50G,40G,25G,10G,1G]" + }, "Ethernet208": { - "default_brkout_mode": "1x400G[200G]" - }, + "default_brkout_mode": "1x400G[200G,100G,50G,40G,25G,10G,1G]" + }, "Ethernet216": { - "default_brkout_mode": "1x400G[200G]" - }, + "default_brkout_mode": "1x400G[200G,100G,50G,40G,25G,10G,1G]" + }, "Ethernet224": { - "default_brkout_mode": "1x400G[200G]" - }, + "default_brkout_mode": "1x400G[200G,100G,50G,40G,25G,10G,1G]" + }, "Ethernet232": { - "default_brkout_mode": "1x400G[200G]" - }, + "default_brkout_mode": "1x400G[200G,100G,50G,40G,25G,10G,1G]" + }, "Ethernet240": { - "default_brkout_mode": "1x400G[200G]" - }, + "default_brkout_mode": "1x400G[200G,100G,50G,40G,25G,10G,1G]" + }, "Ethernet248": { - "default_brkout_mode": "1x400G[200G]" + "default_brkout_mode": "1x400G[200G,100G,50G,40G,25G,10G,1G]" } } -} \ No newline at end of file +} diff --git a/device/mellanox/x86_64-mlnx_msn4700-r0/platform.json b/device/mellanox/x86_64-mlnx_msn4700-r0/platform.json index 7a3d3d1048b..750fc49f6e3 100644 --- a/device/mellanox/x86_64-mlnx_msn4700-r0/platform.json +++ b/device/mellanox/x86_64-mlnx_msn4700-r0/platform.json @@ -4,193 +4,193 @@ "index": "1,1,1,1,1,1,1,1", "lanes": "0,1,2,3,4,5,6,7", "alias_at_lanes": "etp1a, etp1b, etp1c, etp1d, etp1e, etp1f, etp1g, etp1h", - "breakout_modes": "1x400G[200G],2x200G[100G,40G],4x100G" + "breakout_modes": "1x400G[200G,100G,50G,40G,25G,10G,1G],2x200G[100G,50G,40G,25G,10G,1G],4x100G[50G,40G,25G,10G,1G]" }, "Ethernet8": { "index": "2,2,2,2,2,2,2,2", "lanes": "8,9,10,11,12,13,14,15", "alias_at_lanes": "etp2a, etp2b, etp2c, etp2d, etp2e, etp2f, etp2g, etp2h", - "breakout_modes": "1x400G[200G],2x200G[100G,40G],4x100G" + "breakout_modes": "1x400G[200G,100G,50G,40G,25G,10G,1G],2x200G[100G,50G,40G,25G,10G,1G],4x100G[50G,40G,25G,10G,1G]" }, "Ethernet16": { "index": "3,3,3,3,3,3,3,3", "lanes": "16,17,18,19,20,21,22,23", "alias_at_lanes": "etp3a, etp3b, etp3c, etp3d, etp3e, etp3f, etp3g, etp3h", - "breakout_modes": "1x400G[200G],2x200G[100G,40G],4x100G" + "breakout_modes": "1x400G[200G,100G,50G,40G,25G,10G,1G],2x200G[100G,50G,40G,25G,10G,1G],4x100G[50G,40G,25G,10G,1G]" }, "Ethernet24": { "index": "4,4,4,4,4,4,4,4", "lanes": "24,25,26,27,28,29,30,31", "alias_at_lanes": "etp4a, etp4b, etp4c, etp4d, etp4e, etp4f, etp4g, etp4h", - "breakout_modes": "1x400G[200G],2x200G[100G,40G],4x100G" + "breakout_modes": "1x400G[200G,100G,50G,40G,25G,10G,1G],2x200G[100G,50G,40G,25G,10G,1G],4x100G[50G,40G,25G,10G,1G]" }, "Ethernet32": { "index": "5,5,5,5,5,5,5,5", "lanes": "32,33,34,35,36,37,38,39", "alias_at_lanes": "etp5a, etp5b, etp5c, etp5d, etp5e, etp5f, etp5g, etp5h", - "breakout_modes": "1x400G[200G],2x200G[100G,40G],4x100G" + "breakout_modes": "1x400G[200G,100G,50G,40G,25G,10G,1G],2x200G[100G,50G,40G,25G,10G,1G],4x100G[50G,40G,25G,10G,1G]" }, "Ethernet40": { "index": "6,6,6,6,6,6,6,6", "lanes": "40,41,42,43,44,45,46,47", "alias_at_lanes": "etp6a, etp6b, etp6c, etp6d, etp6e, etp6f, etp6g, etp6h", - "breakout_modes": "1x400G[200G],2x200G[100G,40G],4x100G" + "breakout_modes": "1x400G[200G,100G,50G,40G,25G,10G,1G],2x200G[100G,50G,40G,25G,10G,1G],4x100G[50G,40G,25G,10G,1G]" }, "Ethernet48": { "index": "7,7,7,7,7,7,7,7", "lanes": "48,49,50,51,52,53,54,55", "alias_at_lanes": "etp7a, etp7b, etp7c, etp7d, etp7e, etp7f, etp7g, etp7h", - "breakout_modes": "1x400G[200G],2x200G[100G,40G],4x100G" + "breakout_modes": "1x400G[200G,100G,50G,40G,25G,10G,1G],2x200G[100G,50G,40G,25G,10G,1G],4x100G[50G,40G,25G,10G,1G]" }, "Ethernet56": { "index": "8,8,8,8,8,8,8,8", "lanes": "56,57,58,59,60,61,62,63", "alias_at_lanes": "etp8a, etp8b, etp8c, etp8d, etp8e, etp8f, etp8g, etp8h", - "breakout_modes": "1x400G[200G],2x200G[100G,40G],4x100G" + "breakout_modes": "1x400G[200G,100G,50G,40G,25G,10G,1G],2x200G[100G,50G,40G,25G,10G,1G],4x100G[50G,40G,25G,10G,1G]" }, "Ethernet64": { "index": "9,9,9,9,9,9,9,9", "lanes": "64,65,66,67,68,69,70,71", "alias_at_lanes": "etp9a, etp9b, etp9c, etp9d, etp9e, etp9f, etp9g, etp9h", - "breakout_modes": "1x400G[200G],2x200G[100G,40G],4x100G" + "breakout_modes": "1x400G[200G,100G,50G,40G,25G,10G,1G],2x200G[100G,50G,40G,25G,10G,1G],4x100G[50G,40G,25G,10G,1G]" }, "Ethernet72": { "index": "10,10,10,10,10,10,10,10", "lanes": "72,73,74,75,76,77,78,79", "alias_at_lanes": "etp10a, etp10b, etp10c, etp10d, etp10e, etp10f, etp10g, etp10h", - "breakout_modes": "1x400G[200G],2x200G[100G,40G],4x100G" + "breakout_modes": "1x400G[200G,100G,50G,40G,25G,10G,1G],2x200G[100G,50G,40G,25G,10G,1G],4x100G[50G,40G,25G,10G,1G]" }, "Ethernet80": { "index": "11,11,11,11,11,11,11,11", "lanes": "80,81,82,83,84,85,86,87", "alias_at_lanes": "etp11a, etp11b, etp11c, etp11d, etp11e, etp11f, etp11g, etp11h", - "breakout_modes": "1x400G[200G],2x200G[100G,40G],4x100G" + "breakout_modes": "1x400G[200G,100G,50G,40G,25G,10G,1G],2x200G[100G,50G,40G,25G,10G,1G],4x100G[50G,40G,25G,10G,1G]" }, "Ethernet88": { "index": "12,12,12,12,12,12,12,12", "lanes": "88,89,90,91,92,93,94,95", "alias_at_lanes": "etp12a, etp12b, etp12c, etp12d, etp12e, etp12f, etp12g, etp12h", - "breakout_modes": "1x400G[200G],2x200G[100G,40G],4x100G" + "breakout_modes": "1x400G[200G,100G,50G,40G,25G,10G,1G],2x200G[100G,50G,40G,25G,10G,1G],4x100G[50G,40G,25G,10G,1G]" }, "Ethernet96": { "index": "13,13,13,13,13,13,13,13", "lanes": "96,97,98,99,100,101,102,103", "alias_at_lanes": "etp13a, etp13b, etp13c, etp13d, etp13e, etp13f, etp13g, etp13h", - "breakout_modes": "1x400G[200G],2x200G[100G,40G],4x100G" + "breakout_modes": "1x400G[200G,100G,50G,40G,25G,10G,1G],2x200G[100G,50G,40G,25G,10G,1G],4x100G[50G,40G,25G,10G,1G]" }, "Ethernet104": { "index": "14,14,14,14,14,14,14,14", "lanes": "104,105,106,107,108,109,110,111", "alias_at_lanes": "etp14a, etp14b, etp14c, etp14d, etp14e, etp14f, etp14g, etp14h", - "breakout_modes": "1x400G[200G],2x200G[100G,40G],4x100G" + "breakout_modes": "1x400G[200G,100G,50G,40G,25G,10G,1G],2x200G[100G,50G,40G,25G,10G,1G],4x100G[50G,40G,25G,10G,1G]" }, "Ethernet112": { "index": "15,15,15,15,15,15,15,15", "lanes": "112,113,114,115,116,117,118,119", "alias_at_lanes": "etp15a, etp15b, etp15c, etp15d, etp15e, etp15f, etp15g, etp15h", - "breakout_modes": "1x400G[200G],2x200G[100G,40G],4x100G" + "breakout_modes": "1x400G[200G,100G,50G,40G,25G,10G,1G],2x200G[100G,50G,40G,25G,10G,1G],4x100G[50G,40G,25G,10G,1G]" }, "Ethernet120": { "index": "16,16,16,16,16,16,16,16", "lanes": "120,121,122,123,124,125,126,127", "alias_at_lanes": "etp16a, etp16b, etp16c, etp16d, etp16e, etp16f, etp16g, etp16h", - "breakout_modes": "1x400G[200G],2x200G[100G,40G],4x100G" + "breakout_modes": "1x400G[200G,100G,50G,40G,25G,10G,1G],2x200G[100G,50G,40G,25G,10G,1G],4x100G[50G,40G,25G,10G,1G]" }, "Ethernet128": { "index": "17,17,17,17,17,17,17,17", "lanes": "128,129,130,131,132,133,134,135", "alias_at_lanes": "etp17a, etp17b, etp17c, etp17d, etp17e, etp17f, etp17g, etp17h", - "breakout_modes": "1x400G[200G],2x200G[100G,40G],4x100G" + "breakout_modes": "1x400G[200G,100G,50G,40G,25G,10G,1G],2x200G[100G,50G,40G,25G,10G,1G],4x100G[50G,40G,25G,10G,1G]" }, "Ethernet136": { "index": "18,18,18,18,18,18,18,18", "lanes": "136,137,138,139,140,141,142,143", "alias_at_lanes": "etp18a, etp18b, etp18c, etp18d, etp18e, etp18f, etp18g, etp18h", - "breakout_modes": "1x400G[200G],2x200G[100G,40G],4x100G" + "breakout_modes": "1x400G[200G,100G,50G,40G,25G,10G,1G],2x200G[100G,50G,40G,25G,10G,1G],4x100G[50G,40G,25G,10G,1G]" }, "Ethernet144": { "index": "19,19,19,19,19,19,19,19", "lanes": "144,145,146,147,148,149,150,151", "alias_at_lanes": "etp19a, etp19b, etp19c, etp19d, etp19e, etp19f, etp19g, etp19h", - "breakout_modes": "1x400G[200G],2x200G[100G,40G],4x100G" + "breakout_modes": "1x400G[200G,100G,50G,40G,25G,10G,1G],2x200G[100G,50G,40G,25G,10G,1G],4x100G[50G,40G,25G,10G,1G]" }, "Ethernet152": { "index": "20,20,20,20,20,20,20,20", "lanes": "152,153,154,155,156,157,158,159", "alias_at_lanes": "etp20a, etp20b, etp20c, etp20d, etp20e, etp20f, etp20g, etp20h", - "breakout_modes": "1x400G[200G],2x200G[100G,40G],4x100G" + "breakout_modes": "1x400G[200G,100G,50G,40G,25G,10G,1G],2x200G[100G,50G,40G,25G,10G,1G],4x100G[50G,40G,25G,10G,1G]" }, "Ethernet160": { "index": "21,21,21,21,21,21,21,21", "lanes": "160,161,162,163,164,165,166,167", "alias_at_lanes": "etp21a, etp21b, etp21c, etp21d, etp21e, etp21f, etp21g, etp21h", - "breakout_modes": "1x400G[200G],2x200G[100G,40G],4x100G" + "breakout_modes": "1x400G[200G,100G,50G,40G,25G,10G,1G],2x200G[100G,50G,40G,25G,10G,1G],4x100G[50G,40G,25G,10G,1G]" }, "Ethernet168": { "index": "22,22,22,22,22,22,22,22", "lanes": "168,169,170,171,172,173,174,175", "alias_at_lanes": "etp22a, etp22b, etp22c, etp22d, etp22e, etp22f, etp22g, etp22h", - "breakout_modes": "1x400G[200G],2x200G[100G,40G],4x100G" + "breakout_modes": "1x400G[200G,100G,50G,40G,25G,10G,1G],2x200G[100G,50G,40G,25G,10G,1G],4x100G[50G,40G,25G,10G,1G]" }, "Ethernet176": { "index": "23,23,23,23,23,23,23,23", "lanes": "176,177,178,179,180,181,182,183", "alias_at_lanes": "etp23a, etp23b, etp23c, etp23d, etp23e, etp23f, etp23g, etp23h", - "breakout_modes": "1x400G[200G],2x200G[100G,40G],4x100G" + "breakout_modes": "1x400G[200G,100G,50G,40G,25G,10G,1G],2x200G[100G,50G,40G,25G,10G,1G],4x100G[50G,40G,25G,10G,1G]" }, "Ethernet184": { "index": "24,24,24,24,24,24,24,24", "lanes": "184,185,186,187,188,189,190,191", "alias_at_lanes": "etp24a, etp24b, etp24c, etp24d, etp24e, etp24f, etp24g, etp24h", - "breakout_modes": "1x400G[200G],2x200G[100G,40G],4x100G" + "breakout_modes": "1x400G[200G,100G,50G,40G,25G,10G,1G],2x200G[100G,50G,40G,25G,10G,1G],4x100G[50G,40G,25G,10G,1G]" }, "Ethernet192": { "index": "25,25,25,25,25,25,25,25", "lanes": "192,193,194,195,196,197,198,199", "alias_at_lanes": "etp25a, etp25b, etp25c, etp25d, etp25e, etp25f, etp25g, etp25h", - "breakout_modes": "1x400G[200G],2x200G[100G,40G],4x100G" + "breakout_modes": "1x400G[200G,100G,50G,40G,25G,10G,1G],2x200G[100G,50G,40G,25G,10G,1G],4x100G[50G,40G,25G,10G,1G]" }, "Ethernet200": { "index": "26,26,26,26,26,26,26,26", "lanes": "200,201,202,203,204,205,206,207", "alias_at_lanes": "etp26a, etp26b, etp26c, etp26d, etp26e, etp26f, etp26g, etp26h", - "breakout_modes": "1x400G[200G],2x200G[100G,40G],4x100G" + "breakout_modes": "1x400G[200G,100G,50G,40G,25G,10G,1G],2x200G[100G,50G,40G,25G,10G,1G],4x100G[50G,40G,25G,10G,1G]" }, "Ethernet208": { "index": "27,27,27,27,27,27,27,27", "lanes": "208,209,210,211,212,213,214,215", "alias_at_lanes": "etp27a, etp27b, etp27c, etp27d, etp27e, etp27f, etp27g, etp27h", - "breakout_modes": "1x400G[200G],2x200G[100G,40G],4x100G" + "breakout_modes": "1x400G[200G,100G,50G,40G,25G,10G,1G],2x200G[100G,50G,40G,25G,10G,1G],4x100G[50G,40G,25G,10G,1G]" }, "Ethernet216": { "index": "28,28,28,28,28,28,28,28", "lanes": "216,217,218,219,220,221,222,223", "alias_at_lanes": "etp28a, etp28b, etp28c, etp28d, etp28e, etp28f, etp28g, etp28h", - "breakout_modes": "1x400G[200G],2x200G[100G,40G],4x100G" + "breakout_modes": "1x400G[200G,100G,50G,40G,25G,10G,1G],2x200G[100G,50G,40G,25G,10G,1G],4x100G[50G,40G,25G,10G,1G]" }, "Ethernet224": { "index": "29,29,29,29,29,29,29,29", "lanes": "224,225,226,227,228,229,230,231", "alias_at_lanes": "etp29a, etp29b, etp29c, etp29d, etp29e, etp29f, etp29g, etp29h", - "breakout_modes": "1x400G[200G],2x200G[100G,40G],4x100G" + "breakout_modes": "1x400G[200G,100G,50G,40G,25G,10G,1G],2x200G[100G,50G,40G,25G,10G,1G],4x100G[50G,40G,25G,10G,1G]" }, "Ethernet232": { "index": "30,30,30,30,30,30,30,30", "lanes": "232,233,234,235,236,237,238,239", "alias_at_lanes": "etp30a, etp30b, etp30c, etp30d, etp30e, etp30f, etp30g, etp30h", - "breakout_modes": "1x400G[200G],2x200G[100G,40G],4x100G" + "breakout_modes": "1x400G[200G,100G,50G,40G,25G,10G,1G],2x200G[100G,50G,40G,25G,10G,1G],4x100G[50G,40G,25G,10G,1G]" }, "Ethernet240": { "index": "31,31,31,31,31,31,31,31", "lanes": "240,241,242,243,244,245,246,247", "alias_at_lanes": "etp31a, etp31b, etp31c, etp31d, etp31e, etp31f, etp31g, etp31h", - "breakout_modes": "1x400G[200G],2x200G[100G,40G],4x100G" + "breakout_modes": "1x400G[200G,100G,50G,40G,25G,10G,1G],2x200G[100G,50G,40G,25G,10G,1G],4x100G[50G,40G,25G,10G,1G]" }, "Ethernet248": { "index": "32,32,32,32,32,32,32,32", "lanes": "248,249,250,251,252,253,254,255", "alias_at_lanes": "etp32a, etp32b, etp32c, etp32d, etp32e, etp32f, etp32g, etp32h", - "breakout_modes": "1x400G[200G],2x200G[100G,40G],4x100G" + "breakout_modes": "1x400G[200G,100G,50G,40G,25G,10G,1G],2x200G[100G,50G,40G,25G,10G,1G],4x100G[50G,40G,25G,10G,1G]" } } } \ No newline at end of file diff --git a/device/quanta/x86_64-quanta_ix7_rglbmc-r0/Quanta-IX7-32X/td3-ix7-32x100G.config.bcm b/device/quanta/x86_64-quanta_ix7_rglbmc-r0/Quanta-IX7-32X/td3-ix7-32x100G.config.bcm index aaea0380e50..7361ad2f57f 100644 --- a/device/quanta/x86_64-quanta_ix7_rglbmc-r0/Quanta-IX7-32X/td3-ix7-32x100G.config.bcm +++ b/device/quanta/x86_64-quanta_ix7_rglbmc-r0/Quanta-IX7-32X/td3-ix7-32x100G.config.bcm @@ -1,3 +1,4 @@ +sai_load_hw_config=/etc/bcm/flex/bcm56870_a0_issu/b870.6.4.1/ bcm_tunnel_term_compatible_mode=1 core_clock_frequency=1525 dpp_clock_ratio=2:3 diff --git a/device/quanta/x86_64-quanta_ix8_rglbmc-r0/Quanta-IX8-56X/td3-ix8-48x25G+8x100G.config.bcm b/device/quanta/x86_64-quanta_ix8_rglbmc-r0/Quanta-IX8-56X/td3-ix8-48x25G+8x100G.config.bcm index 407105d0ca0..94560fb7e86 100644 --- a/device/quanta/x86_64-quanta_ix8_rglbmc-r0/Quanta-IX8-56X/td3-ix8-48x25G+8x100G.config.bcm +++ b/device/quanta/x86_64-quanta_ix8_rglbmc-r0/Quanta-IX8-56X/td3-ix8-48x25G+8x100G.config.bcm @@ -1,3 +1,4 @@ +sai_load_hw_config=/etc/bcm/flex/bcm56870_a0_issu/b870.6.4.1/ bcm_tunnel_term_compatible_mode=1 core_clock_frequency=1525 dpp_clock_ratio=2:3 diff --git a/device/quanta/x86_64-quanta_ix8c_bwde-r0/Quanta-IX8C-56X/td3-ix8c-48x25G+8x100G.config.bcm b/device/quanta/x86_64-quanta_ix8c_bwde-r0/Quanta-IX8C-56X/td3-ix8c-48x25G+8x100G.config.bcm index 407105d0ca0..94560fb7e86 100644 --- a/device/quanta/x86_64-quanta_ix8c_bwde-r0/Quanta-IX8C-56X/td3-ix8c-48x25G+8x100G.config.bcm +++ b/device/quanta/x86_64-quanta_ix8c_bwde-r0/Quanta-IX8C-56X/td3-ix8c-48x25G+8x100G.config.bcm @@ -1,3 +1,4 @@ +sai_load_hw_config=/etc/bcm/flex/bcm56870_a0_issu/b870.6.4.1/ bcm_tunnel_term_compatible_mode=1 core_clock_frequency=1525 dpp_clock_ratio=2:3 diff --git a/device/virtual/x86_64-kvm_x86_64-r0/installer.conf b/device/virtual/x86_64-kvm_x86_64-r0/installer.conf index e69de29bb2d..530ee964f33 100644 --- a/device/virtual/x86_64-kvm_x86_64-r0/installer.conf +++ b/device/virtual/x86_64-kvm_x86_64-r0/installer.conf @@ -0,0 +1 @@ +ONIE_PLATFORM_EXTRA_CMDLINE_LINUX="swiotlb=65536" diff --git a/dockers/docker-database/supervisord.conf.j2 b/dockers/docker-database/supervisord.conf.j2 index 65a172b3743..616475fb07c 100644 --- a/dockers/docker-database/supervisord.conf.j2 +++ b/dockers/docker-database/supervisord.conf.j2 @@ -5,7 +5,7 @@ nodaemon=true [eventlistener:supervisor-proc-exit-listener] command=/usr/bin/supervisor-proc-exit-listener --container-name database -events=PROCESS_STATE_EXITED +events=PROCESS_STATE_EXITED,PROCESS_STATE_RUNNING autostart=true autorestart=unexpected diff --git a/dockers/docker-dhcp-relay/docker-dhcp-relay.supervisord.conf.j2 b/dockers/docker-dhcp-relay/docker-dhcp-relay.supervisord.conf.j2 index 59d6c1f5f2c..19a6cc294f7 100644 --- a/dockers/docker-dhcp-relay/docker-dhcp-relay.supervisord.conf.j2 +++ b/dockers/docker-dhcp-relay/docker-dhcp-relay.supervisord.conf.j2 @@ -14,7 +14,7 @@ buffer_size=50 [eventlistener:supervisor-proc-exit-listener] command=/usr/bin/supervisor-proc-exit-listener --container-name dhcp_relay -events=PROCESS_STATE_EXITED +events=PROCESS_STATE_EXITED,PROCESS_STATE_RUNNING autostart=true autorestart=unexpected @@ -39,11 +39,11 @@ dependent_startup=true dependent_startup_wait_for=rsyslogd:running {# If our configuration has VLANs... #} -{% if VLAN %} +{% if VLAN_INTERFACE %} {# Count how many VLANs require a DHCP relay agent... #} {% set num_relays = { 'count': 0 } %} -{% for vlan_name in VLAN %} -{% if VLAN[vlan_name]['dhcp_servers'] %} +{% for vlan_name in VLAN_INTERFACE %} +{% if VLAN and vlan_name in VLAN and VLAN[vlan_name]['dhcp_servers'] %} {% set _dummy = num_relays.update({'count': num_relays.count + 1}) %} {% endif %} {% endfor %} @@ -52,8 +52,8 @@ dependent_startup_wait_for=rsyslogd:running [group:isc-dhcp-relay] programs= {%- set add_preceding_comma = { 'flag': False } %} -{% for vlan_name in VLAN %} -{% if VLAN[vlan_name]['dhcp_servers'] %} +{% for vlan_name in VLAN_INTERFACE %} +{% if VLAN and vlan_name in VLAN and VLAN[vlan_name]['dhcp_servers'] %} {% if add_preceding_comma.flag %},{% endif %} {% set _dummy = add_preceding_comma.update({'flag': True}) %} isc-dhcp-relay-{{ vlan_name }} @@ -63,8 +63,8 @@ isc-dhcp-relay-{{ vlan_name }} {# Create a program entry for each DHCP relay agent instance #} {% set relay_for_ipv4 = { 'flag': False } %} -{% for vlan_name in VLAN %} -{% if VLAN[vlan_name]['dhcp_servers'] %} +{% for vlan_name in VLAN_INTERFACE %} +{% if VLAN and vlan_name in VLAN and VLAN[vlan_name]['dhcp_servers'] %} {% for dhcp_server in VLAN[vlan_name]['dhcp_servers'] %} {% if dhcp_server | ipv4 %} {% set _dummy = relay_for_ipv4.update({'flag': True}) %} @@ -106,8 +106,8 @@ dependent_startup_wait_for=start:exited [group:dhcpmon] programs= {%- set add_preceding_comma = { 'flag': False } %} -{% for vlan_name in VLAN %} -{% if VLAN[vlan_name]['dhcp_servers'] %} +{% for vlan_name in VLAN_INTERFACE %} +{% if VLAN and vlan_name in VLAN and VLAN[vlan_name]['dhcp_servers'] %} {% if add_preceding_comma.flag %},{% endif %} {% set _dummy = add_preceding_comma.update({'flag': True}) %} dhcpmon-{{ vlan_name }} @@ -117,8 +117,8 @@ dhcpmon-{{ vlan_name }} {# Create a program entry for each DHCP MONitor instance #} {% set relay_for_ipv4 = { 'flag': False } %} -{% for vlan_name in VLAN %} -{% if VLAN[vlan_name]['dhcp_servers'] %} +{% for vlan_name in VLAN_INTERFACE %} +{% if VLAN and vlan_name in VLAN and VLAN[vlan_name]['dhcp_servers'] %} {% for dhcp_server in VLAN[vlan_name]['dhcp_servers'] %} {% if dhcp_server | ipv4 %} {% set _dummy = relay_for_ipv4.update({'flag': True}) %} diff --git a/dockers/docker-fpm-frr/Dockerfile.j2 b/dockers/docker-fpm-frr/Dockerfile.j2 index 69e3655d0c3..360d64a12b8 100644 --- a/dockers/docker-fpm-frr/Dockerfile.j2 +++ b/dockers/docker-fpm-frr/Dockerfile.j2 @@ -54,10 +54,10 @@ COPY ["TSA", "/usr/bin/TSA"] COPY ["TSB", "/usr/bin/TSB"] COPY ["TSC", "/usr/bin/TSC"] COPY ["files/supervisor-proc-exit-listener", "/usr/bin"] -COPY ["critical_processes", "/etc/supervisor"] -COPY ["bgpd.sh", "/usr/bin/"] +COPY ["zsocket.sh", "/usr/bin/"] RUN chmod a+x /usr/bin/TSA && \ chmod a+x /usr/bin/TSB && \ - chmod a+x /usr/bin/TSC + chmod a+x /usr/bin/TSC && \ + chmod a+x /usr/bin/zsocket.sh ENTRYPOINT ["/usr/bin/docker_init.sh"] diff --git a/dockers/docker-fpm-frr/critical_processes b/dockers/docker-fpm-frr/critical_processes deleted file mode 100644 index 2631fee15e6..00000000000 --- a/dockers/docker-fpm-frr/critical_processes +++ /dev/null @@ -1,5 +0,0 @@ -program:zebra -program:staticd -program:bgpd -program:fpmsyncd -program:bgpcfgd diff --git a/dockers/docker-fpm-frr/docker_init.sh b/dockers/docker-fpm-frr/docker_init.sh index 94cd7fbb132..96149de4c37 100755 --- a/dockers/docker-fpm-frr/docker_init.sh +++ b/dockers/docker-fpm-frr/docker_init.sh @@ -6,16 +6,25 @@ mkdir -p /etc/supervisor/conf.d CFGGEN_PARAMS=" \ -d \ -y /etc/sonic/constants.yml \ - -t /usr/share/sonic/templates/supervisord/frr_vars.j2 \ + -t /usr/share/sonic/templates/frr_vars.j2 \ -t /usr/share/sonic/templates/supervisord/supervisord.conf.j2,/etc/supervisor/conf.d/supervisord.conf \ - -t /usr/share/sonic/templates/bgpd/bgpd.conf.j2,/etc/frr/bgpd.conf \ + -t /usr/share/sonic/templates/bgpd/gen_bgpd.conf.j2,/etc/frr/bgpd.conf \ + -t /usr/share/sonic/templates/supervisord/critical_processes.j2,/etc/supervisor/critical_processes \ -t /usr/share/sonic/templates/zebra/zebra.conf.j2,/etc/frr/zebra.conf \ - -t /usr/share/sonic/templates/staticd/staticd.conf.j2,/etc/frr/staticd.conf \ - -t /usr/share/sonic/templates/frr.conf.j2,/etc/frr/frr.conf \ + -t /usr/share/sonic/templates/staticd/gen_staticd.conf.j2,/etc/frr/staticd.conf \ + -t /usr/share/sonic/templates/gen_frr.conf.j2,/etc/frr/frr.conf \ -t /usr/share/sonic/templates/isolate.j2,/usr/sbin/bgp-isolate \ -t /usr/share/sonic/templates/unisolate.j2,/usr/sbin/bgp-unisolate \ + -t /usr/local/sonic/frrcfgd/bfdd.conf.j2,/etc/frr/bfdd.conf \ + -t /usr/local/sonic/frrcfgd/ospfd.conf.j2,/etc/frr/ospfd.conf \ " -CONFIG_TYPE=$(sonic-cfggen $CFGGEN_PARAMS) + +FRR_VARS=$(sonic-cfggen $CFGGEN_PARAMS) +MGMT_FRAMEWORK_CONFIG=$(echo $FRR_VARS | jq -r '.frr_mgmt_framework_config') +CONFIG_TYPE=$(echo $FRR_VARS | jq -r '.docker_routing_config_mode') +if [ -z "$MGMT_FRAMEWORK_CONFIG" ] || [ "$MGMT_FRAMEWORK_CONFIG" == "false" ]; then + rm /etc/frr/bfdd.conf /etc/frr/ospfd.conf +fi update_default_gw() { @@ -52,7 +61,8 @@ if [ -z "$CONFIG_TYPE" ] || [ "$CONFIG_TYPE" == "separated" ]; then rm -f /etc/frr/frr.conf elif [ "$CONFIG_TYPE" == "unified" ]; then echo "service integrated-vtysh-config" > /etc/frr/vtysh.conf - rm -f /etc/frr/bgpd.conf /etc/frr/zebra.conf /etc/frr/staticd.conf + rm -f /etc/frr/bgpd.conf /etc/frr/zebra.conf /etc/frr/staticd.conf \ + /etc/frr/bfdd.conf /etc/frr/ospfd.conf /etc/frr/pimd.conf fi chown -R frr:frr /etc/frr/ diff --git a/dockers/docker-fpm-frr/frr/bgpd/gen_bgpd.conf.j2 b/dockers/docker-fpm-frr/frr/bgpd/gen_bgpd.conf.j2 new file mode 100644 index 00000000000..bb6d7f6a5a6 --- /dev/null +++ b/dockers/docker-fpm-frr/frr/bgpd/gen_bgpd.conf.j2 @@ -0,0 +1,5 @@ +{% if DEVICE_METADATA.localhost.frr_mgmt_framework_config is defined and DEVICE_METADATA.localhost.frr_mgmt_framework_config == "true" %} + {% include "/usr/local/sonic/frrcfgd/bgpd.conf.j2" %} +{% else %} + {% include "/usr/share/sonic/templates/bgpd/bgpd.conf.j2" %} +{% endif %} diff --git a/dockers/docker-fpm-frr/frr/frr_vars.j2 b/dockers/docker-fpm-frr/frr/frr_vars.j2 index 9909604e5f1..662608a1fd8 100644 --- a/dockers/docker-fpm-frr/frr/frr_vars.j2 +++ b/dockers/docker-fpm-frr/frr/frr_vars.j2 @@ -1 +1,14 @@ -{{ DEVICE_METADATA["localhost"]["docker_routing_config_mode"] }} +{ + "frr_mgmt_framework_config": + {% if "frr_mgmt_framework_config" in DEVICE_METADATA["localhost"].keys() %} + "{{ DEVICE_METADATA["localhost"]["frr_mgmt_framework_config"] }}" + {% else %} + "" + {% endif %}, + "docker_routing_config_mode": + {% if "docker_routing_config_mode" in DEVICE_METADATA["localhost"].keys() %} + "{{ DEVICE_METADATA["localhost"]["docker_routing_config_mode"] }}" + {% else %} + "" + {% endif %} +} diff --git a/dockers/docker-fpm-frr/frr/gen_frr.conf.j2 b/dockers/docker-fpm-frr/frr/gen_frr.conf.j2 new file mode 100644 index 00000000000..181437da07a --- /dev/null +++ b/dockers/docker-fpm-frr/frr/gen_frr.conf.j2 @@ -0,0 +1,5 @@ +{% if DEVICE_METADATA.localhost.frr_mgmt_framework_config is defined and DEVICE_METADATA.localhost.frr_mgmt_framework_config == "true" %} + {% include "/usr/local/sonic/frrcfgd/frr.conf.j2" %} +{% else %} + {% include "/usr/share/sonic/templates/frr.conf.j2" %} +{% endif %} diff --git a/dockers/docker-fpm-frr/frr/staticd/gen_staticd.conf.j2 b/dockers/docker-fpm-frr/frr/staticd/gen_staticd.conf.j2 new file mode 100644 index 00000000000..1346c9a4993 --- /dev/null +++ b/dockers/docker-fpm-frr/frr/staticd/gen_staticd.conf.j2 @@ -0,0 +1,5 @@ +{% if DEVICE_METADATA.localhost.frr_mgmt_framework_config is defined and DEVICE_METADATA.localhost.frr_mgmt_framework_config == "true" %} + {% include "/usr/local/sonic/frrcfgd/staticd.conf.j2" %} +{% else %} + {% include "/usr/share/sonic/templates/staticd/staticd.conf.j2" %} +{% endif %} diff --git a/dockers/docker-fpm-frr/frr/supervisord/critical_processes.j2 b/dockers/docker-fpm-frr/frr/supervisord/critical_processes.j2 new file mode 100644 index 00000000000..69f4e8e6931 --- /dev/null +++ b/dockers/docker-fpm-frr/frr/supervisord/critical_processes.j2 @@ -0,0 +1,12 @@ +program:zebra +program:staticd +program:bgpd +program:fpmsyncd +{% if DEVICE_METADATA.localhost.frr_mgmt_framework_config is defined and DEVICE_METADATA.localhost.frr_mgmt_framework_config == "true" %} +program:bfdd +program:ospfd +program:pimd +program:frrcfgd +{%- else %} +program:bgpcfgd +{%- endif %} diff --git a/dockers/docker-fpm-frr/frr/supervisord/supervisord.conf.j2 b/dockers/docker-fpm-frr/frr/supervisord/supervisord.conf.j2 index e71d6fa7132..dd43e0cc4ec 100644 --- a/dockers/docker-fpm-frr/frr/supervisord/supervisord.conf.j2 +++ b/dockers/docker-fpm-frr/frr/supervisord/supervisord.conf.j2 @@ -14,7 +14,7 @@ buffer_size=50 [eventlistener:supervisor-proc-exit-listener] command=/usr/bin/supervisor-proc-exit-listener --container-name bgp -events=PROCESS_STATE_EXITED +events=PROCESS_STATE_EXITED,PROCESS_STATE_RUNNING autostart=true autorestart=unexpected @@ -39,6 +39,17 @@ stderr_logfile=syslog dependent_startup=true dependent_startup_wait_for=rsyslogd:running +[program:zsocket] +command=/usr/bin/zsocket.sh +priority=4 +autostart=false +autorestart=false +startsecs=0 +stdout_logfile=syslog +stderr_logfile=syslog +dependent_startup=true +dependent_startup_wait_for=zebra:running + [program:staticd] command=/usr/lib/frr/staticd -A 127.0.0.1 priority=4 @@ -48,10 +59,49 @@ startsecs=0 stdout_logfile=syslog stderr_logfile=syslog dependent_startup=true +dependent_startup_wait_for=zsocket:exited + +{% if DEVICE_METADATA.localhost.frr_mgmt_framework_config is defined and DEVICE_METADATA.localhost.frr_mgmt_framework_config == "true" %} +[program:bfdd] +command=/usr/lib/frr/bfdd -A 127.0.0.1 +priority=4 +stopsignal=KILL +autostart=false +autorestart=false +startsecs=0 +stdout_logfile=syslog +stderr_logfile=syslog +dependent_startup=true dependent_startup_wait_for=zebra:running +{% endif %} [program:bgpd] -command=/usr/bin/bgpd.sh -A 127.0.0.1 -M snmp +command=/usr/lib/frr/bgpd -A 127.0.0.1 -M snmp +priority=5 +stopsignal=KILL +autostart=false +autorestart=false +startsecs=0 +stdout_logfile=syslog +stderr_logfile=syslog +dependent_startup=true +dependent_startup_wait_for=zsocket:exited + +{% if DEVICE_METADATA.localhost.frr_mgmt_framework_config is defined and DEVICE_METADATA.localhost.frr_mgmt_framework_config == "true" %} +[program:ospfd] +command=/usr/lib/frr/ospfd -A 127.0.0.1 -M snmp +priority=5 +stopsignal=KILL +autostart=false +autorestart=false +startsecs=0 +stdout_logfile=syslog +stderr_logfile=syslog +dependent_startup=true +dependent_startup_wait_for=zebra:running + +[program:pimd] +command=/usr/lib/frr/pimd -A 127.0.0.1 priority=5 stopsignal=KILL autostart=false @@ -61,6 +111,7 @@ stdout_logfile=syslog stderr_logfile=syslog dependent_startup=true dependent_startup_wait_for=zebra:running +{% endif %} [program:fpmsyncd] command=fpmsyncd @@ -73,8 +124,13 @@ 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" %} +[program:frrcfgd] +command=/usr/local/bin/frrcfgd +{% else %} [program:bgpcfgd] command=/usr/local/bin/bgpcfgd +{% endif %} priority=6 autostart=false autorestart=false diff --git a/dockers/docker-fpm-frr/bgpd.sh b/dockers/docker-fpm-frr/zsocket.sh similarity index 70% rename from dockers/docker-fpm-frr/bgpd.sh rename to dockers/docker-fpm-frr/zsocket.sh index c61a594a1ef..111492f960e 100755 --- a/dockers/docker-fpm-frr/bgpd.sh +++ b/dockers/docker-fpm-frr/zsocket.sh @@ -5,8 +5,8 @@ port=2601 function help() { - echo "This script aims to ensure zebra is ready to accept connections before starting bgpd" - echo "Usage: $0 [options] [bgpd options]" + echo "This script aims to ensure zebra is ready to accept connections" + echo "Usage: $0 [options]" echo "Options:" echo " -a Zebra address" echo " -o Zebra port" @@ -23,11 +23,14 @@ while getopts ":a:o:h" opt; do ;; esac done -shift $((OPTIND-1)) +start=$(date +%s.%N) timeout 5s bash -c -- "until "$image_path/kernel-cmdline" + cmdline_echo | sed 's/ cmdline-aboot-end.*$//' > "$target_path/kernel-params-base" +} + write_common_configs() { write_default_cmdline write_platform_specific_cmdline @@ -667,28 +689,14 @@ write_secureboot_configs() { cmdline_add aboot.secureboot=enabled # setting panic= has the side effect of disabling the initrd shell on error cmdline_add panic=0 + write_cmdline } write_regular_configs() { write_common_configs cmdline_add "loop=$image_name/fs.squashfs" cmdline_add loopfstype=squashfs - - # use extra parameters from kernel-params hook if the file exists - if [ -f "$target_path/$kernel_params" ]; then - cat "$target_path/$kernel_params" | cmdline_append - fi - - # FIXME: sonic sometimes adds extra kernel parameters from user space - # this is unsafe but some will be kept as part of the regular boot - if [ -f "$image_path/kernel-cmdline" ]; then - cat "$image_path/kernel-cmdline" | tr ' ' '\n' | grep -E "$cmdline_allowlist" | cmdline_append - fi - - # FIXME: legacy configuration files used by fast-reboot and eos2sonic - # these should be deprecated over time. - cmdline_echo > "$image_path/kernel-cmdline" - cmdline_echo | sed 's/ cmdline-aboot-end.*$//' > "$target_path/kernel-params-base" + write_cmdline } run_kexec() { @@ -753,8 +761,8 @@ secureboot_boot() { regular_boot() { # boot uses the image installed on the flash - run_hooks pre-kexec write_regular_configs "$image_path" + run_hooks pre-kexec update_next_boot run_kexec } diff --git a/files/build_templates/docker_image_ctl.j2 b/files/build_templates/docker_image_ctl.j2 index dd37506f372..388451fe720 100644 --- a/files/build_templates/docker_image_ctl.j2 +++ b/files/build_templates/docker_image_ctl.j2 @@ -42,6 +42,18 @@ function updateSyslogConf() rm -rf $TMP_FILE fi } +function ebtables_config() +{ + if [ "$DEV" ]; then + # Install ebtables filter in namespaces on multi-asic. + ip netns exec $NET_NS ebtables-restore < /etc/ebtables.filter.cfg + else + if [[ ! ($NUM_ASIC -gt 1) ]]; then + # Install ebtables filter in host for single asic. + ebtables-restore < /etc/ebtables.filter.cfg + fi + fi +} function getMountPoint() { @@ -100,6 +112,8 @@ function postStartAction() docker exec -i database$DEV sysctl --system -e link_namespace $DEV fi + # Setup ebtables configuration + ebtables_config # chassisdb starts before database starts, bypass the PING check since other # databases are not availbale until database container is ready. @@ -424,6 +438,9 @@ stop() { if [ "$DEV" ]; then ip netns delete "$NET_NS" fi + {%- elif docker_container_name == "teamd" %} + # Longer timeout of 60 sec to wait for Portchannels to be cleaned. + /usr/local/bin/container stop -t 60 $DOCKERNAME {%- else %} /usr/local/bin/container stop $DOCKERNAME {%- endif %} diff --git a/files/build_templates/per_namespace/teamd.service.j2 b/files/build_templates/per_namespace/teamd.service.j2 index 322ffdc407e..f5936baa6a7 100644 --- a/files/build_templates/per_namespace/teamd.service.j2 +++ b/files/build_templates/per_namespace/teamd.service.j2 @@ -1,6 +1,10 @@ [Unit] Description=TEAMD container After=swss{% if multi_instance == 'true' %}@%i{% endif %}.service +{% if multi_instance == 'true' and sonic_asic_platform == 'vs' %} +Requires=topology.service +After=topology.service +{% endif %} Requires=updategraph.service After=updategraph.service Before=ntp-config.service diff --git a/files/build_templates/sonic_debian_extension.j2 b/files/build_templates/sonic_debian_extension.j2 index fd5a9735bfa..1589ba708bd 100644 --- a/files/build_templates/sonic_debian_extension.j2 +++ b/files/build_templates/sonic_debian_extension.j2 @@ -246,6 +246,13 @@ sudo dpkg --root=$FILESYSTEM_ROOT -i $debs_path/sonic-utilities-data_*.deb || \ # in bash.bashrc, so we copy a version of the file with it enabled here. sudo cp -f $IMAGE_CONFIGS/bash/bash.bashrc $FILESYSTEM_ROOT/etc/ +# Install prerequisites needed for installing the dependent Python packages of sonic-host-services +# These packages can be uninstalled after installation +sudo LANG=C DEBIAN_FRONTEND=noninteractive chroot $FILESYSTEM_ROOT apt-get -y install libcairo2-dev libdbus-1-dev libgirepository1.0-dev libsystemd-dev pkg-config + +# Manually install runtime dependencies to avoid them being auto-removed while uninstalling build dependencies +sudo LANG=C DEBIAN_FRONTEND=noninteractive chroot $FILESYSTEM_ROOT apt-get -y install gir1.2-glib-2.0 libdbus-1-3 libgirepository-1.0-1 libsystemd0 + # Install SONiC host services package SONIC_HOST_SERVICES_PY3_WHEEL_NAME=$(basename {{sonic_host_services_py3_wheel_path}}) sudo cp {{sonic_host_services_py3_wheel_path}} $FILESYSTEM_ROOT/$SONIC_HOST_SERVICES_PY3_WHEEL_NAME @@ -262,12 +269,6 @@ sudo dpkg --root=$FILESYSTEM_ROOT -i $debs_path/sonic-ztp_*.deb || \ sudo LANG=C DEBIAN_FRONTEND=noninteractive chroot $FILESYSTEM_ROOT apt-get -y install -f {% endif %} -{% if include_host_service == "y" %} -# Install SONiC Host Service (and its dependencies via 'apt-get -y install -f') -sudo dpkg --root=$FILESYSTEM_ROOT -i $debs_path/sonic-host-service_*.deb || \ - sudo LANG=C DEBIAN_FRONTEND=noninteractive chroot $FILESYSTEM_ROOT apt-get -y install -f -{% endif %} - # Install SONiC Device Data (and its dependencies via 'apt-get -y install -f') sudo dpkg --root=$FILESYSTEM_ROOT -i $debs_path/sonic-device-data_*.deb || \ sudo LANG=C DEBIAN_FRONTEND=noninteractive chroot $FILESYSTEM_ROOT apt-get -y install -f @@ -676,6 +677,7 @@ echo "mgmt-framework.timer" | sudo tee -a $GENERATED_SERVICE_FILE sudo LANG=C DEBIAN_FRONTEND=noninteractive chroot $FILESYSTEM_ROOT apt-get purge -y python-dev python3-dev sudo LANG=C DEBIAN_FRONTEND=noninteractive chroot $FILESYSTEM_ROOT apt-get purge -y build-essential libssl-dev swig +sudo LANG=C DEBIAN_FRONTEND=noninteractive chroot $FILESYSTEM_ROOT apt-get purge -y libcairo2-dev libdbus-1-dev libgirepository1.0-dev libsystemd-dev pkg-config sudo LANG=C DEBIAN_FRONTEND=noninteractive chroot $FILESYSTEM_ROOT apt-get clean -y sudo LANG=C DEBIAN_FRONTEND=noninteractive chroot $FILESYSTEM_ROOT apt-get autoremove -y diff --git a/files/image_config/ebtables/ebtables.default b/files/image_config/ebtables/ebtables.default deleted file mode 100644 index 93706fe5625..00000000000 --- a/files/image_config/ebtables/ebtables.default +++ /dev/null @@ -1,35 +0,0 @@ -# Unload modules on restart and stop -# Value: yes|no, default: yes -# This option has to be 'yes' to get to a sane state for a firewall -# restart or stop. Only set to 'no' if there are problems unloading netfilter -# modules. -EBTABLES_MODULES_UNLOAD="yes" - -# Load firewall rules on system startup. -# Value: yes|no, default: no -# Restores the ebtables rulesets from the last saved state when the -# system boots up. -EBTABLES_LOAD_ON_START="yes" - -# Save current firewall rules on stop. -# Value: yes|no, default: no -# Saves all firewall rules if firewall gets stopped -# (e.g. on system shutdown). -EBTABLES_SAVE_ON_STOP="no" - -# Save current firewall rules on restart. -# Value: yes|no, default: no -# Saves all firewall rules if firewall gets restarted. -EBTABLES_SAVE_ON_RESTART="no" - -# Save (and restore) rule counters. -# Value: yes|no, default: no -# Save rule counters when saving a kernel table to a file. If the -# rule counters were saved, they will be restored when restoring the table. -EBTABLES_SAVE_COUNTER="no" - -# Backup suffix for ruleset save files. -# Value: , default: "~" -# Keep one backup level of saved rules. -# Set this variable to the empty string to disable backups. -EBTABLES_BACKUP_SUFFIX="~" diff --git a/files/image_config/ebtables/ebtables.init b/files/image_config/ebtables/ebtables.init deleted file mode 100755 index 12182902319..00000000000 --- a/files/image_config/ebtables/ebtables.init +++ /dev/null @@ -1,175 +0,0 @@ -#!/bin/bash -# -# init script for the Ethernet Bridge filter tables -# -# Written by Dag Wieers -# Modified by Rok Papez -# Bart De Schuymer -# Adapted to Debian by Jan Christoph Nordholz -# -# chkconfig: - 15 85 -# description: Ethernet Bridge filtering tables -# -### BEGIN INIT INFO -# Provides: ebtables -# Required-Start: -# Required-Stop: -# Should-Start: $local_fs -# Should-Stop: $local_fs -# Default-Start: S -# Default-Stop: 0 1 6 -# Short-Description: ebtables ruleset management -# Description: Saves and restores the state of the ebtables rulesets. -### END INIT INFO - -. /lib/lsb/init-functions - -test -f /sbin/ebtables || exit 0 - -EBTABLES_DUMPFILE_STEM=/etc/ebtables - -RETVAL=0 -prog="ebtables" -desc="Ethernet bridge filtering" -umask 0077 - -#default configuration -EBTABLES_MODULES_UNLOAD="yes" -EBTABLES_LOAD_ON_START="no" -EBTABLES_SAVE_ON_STOP="no" -EBTABLES_SAVE_ON_RESTART="no" -EBTABLES_SAVE_COUNTER="no" -EBTABLES_BACKUP_SUFFIX="~" - -config=/etc/default/$prog -[ -f "$config" ] && . "$config" - -function get_supported_tables() { - EBTABLES_SUPPORTED_TABLES= - /sbin/ebtables -t filter -L 2>&1 1>/dev/null | grep -q permission - if [ $? -eq 0 ]; then - log_failure_msg "Error: insufficient privileges to access the ebtables rulesets." - exit 1 - fi - for table in filter nat broute; do - /sbin/ebtables -t $table -L &> /dev/null - if [ $? -eq 0 ]; then - EBTABLES_SUPPORTED_TABLES="${EBTABLES_SUPPORTED_TABLES} $table" - fi - done -} - -function load() { - RETVAL=0 - get_supported_tables - log_daemon_msg "Restoring ebtables rulesets" - for table in $EBTABLES_SUPPORTED_TABLES; do - log_progress_msg "$table" - if [ -s ${EBTABLES_DUMPFILE_STEM}.$table ]; then - /sbin/ebtables -t $table --atomic-file ${EBTABLES_DUMPFILE_STEM}.$table --atomic-commit - RET=$? - if [ $RET -ne 0 ]; then - log_progress_msg "(failed)" - RETVAL=$RET - fi - else - log_progress_msg "(no saved state)" - fi - done - if [ -z "$EBTABLES_SUPPORTED_TABLES" ]; then - log_progress_msg "no kernel support" - else - log_progress_msg "done" - fi - log_end_msg $RETVAL -} - -function clear() { - RETVAL=0 - get_supported_tables - log_daemon_msg "Clearing ebtables rulesets" - for table in $EBTABLES_SUPPORTED_TABLES; do - log_progress_msg "$table" - /sbin/ebtables -t $table --init-table - done - - if [ "$EBTABLES_MODULES_UNLOAD" = "yes" ]; then - for mod in $(grep -E '^(ebt|ebtable)_' /proc/modules | cut -d' ' -f1) ebtables; do - rmmod $mod 2> /dev/null - done - fi - if [ -z "$EBTABLES_SUPPORTED_TABLES" ]; then - log_progress_msg "no kernel support" - else - log_progress_msg "done" - fi - log_end_msg $RETVAL -} - -function save() { - RETVAL=0 - get_supported_tables - log_daemon_msg "Saving ebtables rulesets" - for table in $EBTABLES_SUPPORTED_TABLES; do - log_progress_msg "$table" - [ -n "$EBTABLES_BACKUP_SUFFIX" ] && [ -s ${EBTABLES_DUMPFILE_STEM}.$table ] && \ - mv ${EBTABLES_DUMPFILE_STEM}.$table ${EBTABLES_DUMPFILE_STEM}.$table$EBTABLES_BACKUP_SUFFIX - /sbin/ebtables -t $table --atomic-file ${EBTABLES_DUMPFILE_STEM}.$table --atomic-save - RET=$? - if [ $RET -ne 0 ]; then - log_progress_msg "(failed)" - RETVAL=$RET - else - if [ "$EBTABLES_SAVE_COUNTER" = "no" ]; then - /sbin/ebtables -t $table --atomic-file ${EBTABLES_DUMPFILE_STEM}.$table -Z - fi - fi - done - if [ -z "$EBTABLES_SUPPORTED_TABLES" ]; then - log_progress_msg "no kernel support" - else - log_progress_msg "done" - fi - log_end_msg $RETVAL -} - -case "$1" in - start) - [ "$EBTABLES_LOAD_ON_START" = "yes" ] && load - ;; - stop) - [ "$EBTABLES_SAVE_ON_STOP" = "yes" ] && save - clear - ;; - restart|reload|force-reload) - [ "$EBTABLES_SAVE_ON_RESTART" = "yes" ] && save - clear - [ "$EBTABLES_LOAD_ON_START" = "yes" ] && load - ;; - load) - load - ;; - save) - save - ;; - status) - get_supported_tables - if [ -z "$EBTABLES_SUPPORTED_TABLES" ]; then - log_failure_msg "No kernel support for ebtables." - RETVAL=1 - else - log_daemon_msg "Ebtables support available, number of installed rules" - for table in $EBTABLES_SUPPORTED_TABLES; do - COUNT=$(( $(/sbin/ebtables -t $table -L | sed -e "/^Bridge chain/! d" -e "s/^.*entries: //" -e "s/,.*$/ +/") 0 )) - log_progress_msg "$table($COUNT)" - done - log_end_msg 0 - RETVAL=0 - fi - ;; - *) - echo "Usage: $0 {start|stop|restart|reload|force-reload|load|save|status}" >&2 - RETVAL=1 -esac - -exit $RETVAL diff --git a/files/image_config/ebtables/ebtables.service b/files/image_config/ebtables/ebtables.service deleted file mode 100644 index bb2cb8fd0a0..00000000000 --- a/files/image_config/ebtables/ebtables.service +++ /dev/null @@ -1,19 +0,0 @@ -[Unit] -Description=ebtables ruleset management -DefaultDependencies=no -Before=network-pre.target -Wants=network-pre.target -After=local-fs.target -# n.b. use below if we want to tear down rules before shutting down. -#Before=shutdown.target -#Conflicts=shutdown.target - -[Service] -Type=oneshot -RemainAfterExit=yes -ExecStart=/etc/init.d/ebtables start -ExecStop=/etc/init.d/ebtables stop -ExecReload=/etc/init.d/ebtables reload - -[Install] -WantedBy=multi-user.target diff --git a/files/image_config/logrotate/logrotate.d/rsyslog b/files/image_config/logrotate/logrotate.d/rsyslog index 792e3e9a2d5..cbf6e722eb9 100644 --- a/files/image_config/logrotate/logrotate.d/rsyslog +++ b/files/image_config/logrotate/logrotate.d/rsyslog @@ -30,8 +30,8 @@ /var/log/telemetry.log /var/log/frr/bgpd.log /var/log/frr/zebra.log -/var/log/swss/sairedis.rec -/var/log/swss/swss.rec +/var/log/swss/sairedis*.rec +/var/log/swss/swss*.rec { size 1M rotate 5000 @@ -85,7 +85,22 @@ endscript postrotate if [ $(echo $1 | grep -c "/var/log/swss/") -gt 0 ]; then - pgrep -x orchagent | xargs /bin/kill -HUP 2>/dev/null || true + # for multi asic platforms, there are multiple orchagents + # send the SIGHUP only to the orchagent the which needs log file rotation + PLATFORM=`sonic-cfggen -H -v DEVICE_METADATA.localhost.platform` + ASIC_CONF=/usr/share/sonic/device/$PLATFORM/asic.conf + if [ -f "$ASIC_CONF" ]; then + . $ASIC_CONF + fi + if [ $NUM_ASIC -gt 1 ]; then + log_file=$1 + log_file_name=${log_file#/var/log/swss/} + logger -p syslog.info -t "logrotate" "Sending SIGHUP to OA log_file_name: $log_file_name" + pgrep -xa orchagent | grep $log_file_name | awk '{ print $1; }' | xargs /bin/kill -HUP 2>/dev/null || true + else + logger -p syslog.info -t "logrotate" "Sending SIGHUP to OA log_file_name: $1" + pgrep -x orchagent | xargs /bin/kill -HUP 2>/dev/null || true + fi else /bin/kill -HUP $(cat /var/run/rsyslogd.pid) fi diff --git a/files/image_config/pcie-check/pcie-check.sh b/files/image_config/pcie-check/pcie-check.sh index 4ef2ce3047f..4257a2544c4 100755 --- a/files/image_config/pcie-check/pcie-check.sh +++ b/files/image_config/pcie-check/pcie-check.sh @@ -16,11 +16,11 @@ function debug() function check_and_rescan_pcie_devices() { - PCIE_CHK_CMD='sudo pcieutil pcie-check |grep "$RESULTS"' + PCIE_CHK_CMD='sudo pcieutil check | grep "$RESULTS"' PLATFORM=$(sonic-cfggen -H -v DEVICE_METADATA.localhost.platform) if [ ! -f /usr/share/sonic/device/$PLATFORM/plugins/pcie.yaml ]; then - debug "pcie.yaml does not exist! can't check pcie status!" + debug "pcie.yaml does not exist! Can't check PCIe status!" exit fi diff --git a/files/image_config/platform/rc.local b/files/image_config/platform/rc.local index 23531fb74f4..b299f9fe2bb 100755 --- a/files/image_config/platform/rc.local +++ b/files/image_config/platform/rc.local @@ -186,12 +186,6 @@ program_console_speed() systemctl daemon-reload } -ebtables_config() -{ - # Generate atomic config file and save it persistent - /usr/sbin/ebtables-restore < /etc/ebtables.filter.cfg - /usr/sbin/ebtables -t filter --atomic-file /etc/ebtables.filter --atomic-save -} #### Begin Main Body #### @@ -362,9 +356,6 @@ if [ -f $FIRST_BOOT_FILE ]; then # Create dir where following scripts put their output files mkdir -p /var/platform - # Firsttime ebtables configuration - ebtables_config - # Kdump tools configuration sed -i -e "s/__PLATFORM__/$platform/g" /etc/default/kdump-tools diff --git a/files/image_config/secureboot/allowlist_paths.conf b/files/image_config/secureboot/allowlist_paths.conf index c80b39d74bc..f1021f5c13e 100644 --- a/files/image_config/secureboot/allowlist_paths.conf +++ b/files/image_config/secureboot/allowlist_paths.conf @@ -1,5 +1,6 @@ home/.* var/core/.* +var/crash/.* var/log/.* etc/adjtime etc/default/ntp diff --git a/files/image_config/sudoers/sudoers b/files/image_config/sudoers/sudoers index 9e59c885430..8ec8799c7cc 100644 --- a/files/image_config/sudoers/sudoers +++ b/files/image_config/sudoers/sudoers @@ -23,9 +23,9 @@ Cmnd_Alias READ_ONLY_CMDS = /bin/cat /var/log/syslog*, \ /sbin/brctl show, \ /usr/bin/docker exec snmp cat /etc/snmp/snmpd.conf, \ /usr/bin/docker exec bgp cat /etc/quagga/bgpd.conf, \ - /usr/bin/docker exec * ps aux, \ /usr/bin/docker images *, \ - /usr/bin/docker ps*, \ + /usr/bin/docker ps *, \ + /usr/bin/docker ps, \ /usr/bin/lldpctl, \ /usr/bin/sensors, \ /usr/bin/tail -F /var/log/syslog, \ @@ -34,9 +34,12 @@ Cmnd_Alias READ_ONLY_CMDS = /bin/cat /var/log/syslog*, \ /usr/local/bin/decode-syseeprom, \ /usr/local/bin/generate_dump, \ /usr/local/bin/lldpshow, \ + /usr/local/bin/pcieutil *, \ /usr/local/bin/psuutil *, \ /usr/local/bin/sonic-installer list, \ - /usr/local/bin/sfputil show * + /usr/local/bin/sfputil show *, \ + /bin/ip netns identify [0-9]* + Cmnd_Alias PASSWD_CMDS = /usr/local/bin/config tacacs passkey *, \ /usr/sbin/chpasswd * diff --git a/files/initramfs-tools/arista-convertfs.j2 b/files/initramfs-tools/arista-convertfs.j2 index 348272c5955..9af44f221fe 100644 --- a/files/initramfs-tools/arista-convertfs.j2 +++ b/files/initramfs-tools/arista-convertfs.j2 @@ -19,7 +19,8 @@ block_flash='' aboot_flag='' backup_file='' prev_os='' -sonic_fast_reboot='' +sonic_fast_reboot=false +in_kdump=false # Wait until get the fullpath of flash device, e.g., /dev/sda wait_get_flash_dev() { @@ -141,14 +142,20 @@ for x in "$@"; do SONIC_BOOT_TYPE=warm*|SONIC_BOOT_TYPE=fast*) sonic_fast_reboot=true ;; + systemd.unit=kdump-tools.service) + in_kdump=true + ;; esac done # Check aboot [ -z "$aboot_flag" ] && exit 0 +# Check kdump +[ "$in_kdump" = true ] && exit 0 + # Skip this script for warm-reboot/fast-reboot from sonic -[ "$sonic_fast_reboot" == true ] && [ "$prev_os" != eos ] && exit 0 +[ "$sonic_fast_reboot" = true ] && [ "$prev_os" != eos ] && exit 0 # Get flash dev name if [ -z "$block_flash" ]; then diff --git a/files/initramfs-tools/arista-hook b/files/initramfs-tools/arista-hook index 521e38435b3..868521b0db9 100644 --- a/files/initramfs-tools/arista-hook +++ b/files/initramfs-tools/arista-hook @@ -45,6 +45,10 @@ for x in "$@"; do # Skip this script for warm-reboot and fast-reboot exit 0 ;; + systemd.unit=kdump-tools.service) + # In kdump environment, skip hooks + exit 0 + ;; esac done diff --git a/files/initramfs-tools/union-mount.j2 b/files/initramfs-tools/union-mount.j2 index a2b5a5266da..a97137a00c2 100644 --- a/files/initramfs-tools/union-mount.j2 +++ b/files/initramfs-tools/union-mount.j2 @@ -15,6 +15,7 @@ docker_inram=false logs_inram=false secureboot=false bootloader=generic +in_kdump=false # Extract kernel parameters for x in $(cat /proc/cmdline); do @@ -35,6 +36,9 @@ for x in $(cat /proc/cmdline); do platform=*) platform_flag="${x#platform=}" ;; + systemd.unit=kdump-tools.service) + in_kdump=true + ;; esac done @@ -86,7 +90,7 @@ mkdir -p "$rw_dir" mkdir -p "$work_dir" ## Remove the files not in allowlist in the rw folder -if $secureboot; then +if [ "$secureboot" = true ] && [ "$in_kdump" = false ]; then if [ "$bootloader" = "aboot" ]; then swi_path="${rootmnt}/host/$(sed -E 's/.*loop=([^ ]+).*/\1/' /proc/cmdline)" unzip -q "$swi_path" allowlist_paths.conf -d /tmp @@ -120,23 +124,25 @@ case "${ROOT}" in esac mkdir -p ${rootmnt}/var/lib/docker -if $secureboot; then - mount -t tmpfs -o rw,nodev,size={{ DOCKER_RAMFS_SIZE }} tmpfs ${rootmnt}/var/lib/docker - if [ "$bootloader" = "aboot" ]; then - unzip -qp "$swi_path" dockerfs.tar.gz | tar xz --numeric-owner -C ${rootmnt}/var/lib/docker - ## Boot folder is not extracted during secureboot since content would inherently become unsafe - mkdir -p ${rootmnt}/host/$image_dir/boot +if [ "$in_kdump" = false ]; then + if [ "$secureboot" = true ]; then + mount -t tmpfs -o rw,nodev,size={{ DOCKER_RAMFS_SIZE }} tmpfs ${rootmnt}/var/lib/docker + if [ "$bootloader" = "aboot" ]; then + unzip -qp "$swi_path" dockerfs.tar.gz | tar xz --numeric-owner -C ${rootmnt}/var/lib/docker + ## Boot folder is not extracted during secureboot since content would inherently become unsafe + mkdir -p ${rootmnt}/host/$image_dir/boot + else + echo "secureboot unsupported for bootloader $bootloader" 1>&2 + exit 1 + fi + elif [ -f ${rootmnt}/host/$image_dir/{{ FILESYSTEM_DOCKERFS }} ]; then + ## mount tmpfs and extract docker into it + mount -t tmpfs -o rw,nodev,size={{ DOCKER_RAMFS_SIZE }} tmpfs ${rootmnt}/var/lib/docker + tar xz --numeric-owner -f ${rootmnt}/host/$image_dir/{{ FILESYSTEM_DOCKERFS }} -C ${rootmnt}/var/lib/docker else - echo "secureboot unsupported for bootloader $bootloader" 1>&2 - exit 1 + ## Mount the working directory of docker engine in the raw partition, bypass the overlay + mount --bind ${rootmnt}/host/$image_dir/{{ DOCKERFS_DIR }} ${rootmnt}/var/lib/docker fi -elif [ -f ${rootmnt}/host/$image_dir/{{ FILESYSTEM_DOCKERFS }} ]; then - ## mount tmpfs and extract docker into it - mount -t tmpfs -o rw,nodev,size={{ DOCKER_RAMFS_SIZE }} tmpfs ${rootmnt}/var/lib/docker - tar xz --numeric-owner -f ${rootmnt}/host/$image_dir/{{ FILESYSTEM_DOCKERFS }} -C ${rootmnt}/var/lib/docker -else - ## Mount the working directory of docker engine in the raw partition, bypass the overlay - mount --bind ${rootmnt}/host/$image_dir/{{ DOCKERFS_DIR }} ${rootmnt}/var/lib/docker fi ## Mount the boot directory in the raw partition, bypass the overlay diff --git a/files/scripts/supervisor-proc-exit-listener b/files/scripts/supervisor-proc-exit-listener index 143e539a168..e8565b4d52f 100755 --- a/files/scripts/supervisor-proc-exit-listener +++ b/files/scripts/supervisor-proc-exit-listener @@ -2,11 +2,15 @@ import getopt import os +import re +import select import signal import sys import syslog +import time import swsssdk + from supervisor import childutils # Each line of this file should specify either one critical process or one @@ -20,15 +24,26 @@ CRITICAL_PROCESSES_FILE = '/etc/supervisor/critical_processes' # The FEATURE table in config db contains auto-restart field FEATURE_TABLE_NAME = 'FEATURE' -# Read the critical processes/group names from CRITICAL_PROCESSES_FILE +# Value of parameter 'timeout' in select(...) method +SELECT_TIMEOUT_SECS = 1.0 + +# Alerting message will be written into syslog in the following interval +ALERTING_INTERVAL_SECS = 60 def get_critical_group_and_process_list(): + """ + @summary: Read the critical processes/group names from CRITICAL_PROCESSES_FILE. + @return: Two lists which contain critical processes and group names respectively. + """ critical_group_list = [] critical_process_list = [] with open(CRITICAL_PROCESSES_FILE, 'r') as file: for line in file: + # ignore blank lines + if re.match(r"^\s*$", line): + continue line_info = line.strip(' \n').split(':') if len(line_info) != 2: syslog.syslog(syslog.LOG_ERR, @@ -49,6 +64,47 @@ def get_critical_group_and_process_list(): return critical_group_list, critical_process_list +def generate_alerting_message(process_name): + """ + @summary: If a critical process was not running, this function will determine it resides in host + or in a specific namespace. Then an alerting message will be written into syslog. + """ + namespace_prefix = os.environ.get("NAMESPACE_PREFIX") + namespace_id = os.environ.get("NAMESPACE_ID") + + if not namespace_prefix or not namespace_id: + namespace = "host" + else: + namespace = namespace_prefix + namespace_id + + syslog.syslog(syslog.LOG_ERR, "Process '{}' is not running in namespace '{}'.".format(process_name, namespace)) + + +def get_autorestart_state(container_name): + """ + @summary: Read the status of auto-restart feature from Config_DB. + @return: Return the status of auto-restart feature. + """ + config_db = swsssdk.ConfigDBConnector() + config_db.connect() + features_table = config_db.get_table(FEATURE_TABLE_NAME) + if not features_table: + syslog.syslog(syslog.LOG_ERR, "Unable to retrieve features table from Config DB. Exiting...") + sys.exit(2) + + if container_name not in features_table: + syslog.syslog(syslog.LOG_ERR, "Unable to retrieve feature '{}'. Exiting...".format(container_name)) + sys.exit(3) + + is_auto_restart = features_table[container_name].get('auto_restart') + if not is_auto_restart: + syslog.syslog( + syslog.LOG_ERR, "Unable to determine auto-restart feature status for '{}'. Exiting...".format(container_name)) + sys.exit(4) + + return is_auto_restart + + def main(argv): container_name = None opts, args = getopt.getopt(argv, "c:", ["container-name="]) @@ -62,51 +118,55 @@ def main(argv): critical_group_list, critical_process_list = get_critical_group_and_process_list() + process_under_alerting = {} + # Transition from ACKNOWLEDGED to READY + childutils.listener.ready() + while True: - # Transition from ACKNOWLEDGED to READY - childutils.listener.ready() - - line = sys.stdin.readline() - headers = childutils.get_headers(line) - payload = sys.stdin.read(int(headers['len'])) - - # Transition from READY to ACKNOWLEDGED - childutils.listener.ok() - - # We only care about PROCESS_STATE_EXITED events - if headers['eventname'] == 'PROCESS_STATE_EXITED': - payload_headers, payload_data = childutils.eventdata(payload + '\n') - - expected = int(payload_headers['expected']) - processname = payload_headers['processname'] - groupname = payload_headers['groupname'] - - # Read the status of auto-restart feature from Config_DB. - config_db = swsssdk.ConfigDBConnector() - config_db.connect() - features_table = config_db.get_table(FEATURE_TABLE_NAME) - if not features_table: - syslog.syslog(syslog.LOG_ERR, "Unable to retrieve features table from Config DB. Exiting...") - sys.exit(2) - - if container_name not in features_table: - syslog.syslog(syslog.LOG_ERR, "Unable to retrieve feature '{}'. Exiting...".format(container_name)) - sys.exit(3) - - restart_feature = features_table[container_name].get('auto_restart') - if not restart_feature: - syslog.syslog( - syslog.LOG_ERR, "Unable to determine auto-restart feature status for '{}'. Exiting...".format(container_name)) - sys.exit(4) - - # If auto-restart feature is not disabled and at the same time - # a critical process exited unexpectedly, terminate supervisor - if (restart_feature != 'disabled' and expected == 0 and - (processname in critical_process_list or groupname in critical_group_list)): - MSG_FORMAT_STR = "Process {} exited unxepectedly. Terminating supervisor..." - msg = MSG_FORMAT_STR.format(payload_headers['processname']) - syslog.syslog(syslog.LOG_INFO, msg) - os.kill(os.getppid(), signal.SIGTERM) + file_descriptor_list = select.select([sys.stdin], [], [], SELECT_TIMEOUT_SECS)[0] + if len(file_descriptor_list) > 0: + line = file_descriptor_list[0].readline() + headers = childutils.get_headers(line) + payload = sys.stdin.read(int(headers['len'])) + + # Handle the PROCESS_STATE_EXITED event + if headers['eventname'] == 'PROCESS_STATE_EXITED': + payload_headers, payload_data = childutils.eventdata(payload + '\n') + + expected = int(payload_headers['expected']) + process_name = payload_headers['processname'] + group_name = payload_headers['groupname'] + + if (process_name in critical_process_list or group_name in critical_group_list) and expected == 0: + is_auto_restart = get_autorestart_state(container_name) + if is_auto_restart != "disabled": + MSG_FORMAT_STR = "Process '{}' exited unexpectedly. Terminating supervisor '{}'" + msg = MSG_FORMAT_STR.format(payload_headers['processname'], container_name) + syslog.syslog(syslog.LOG_INFO, msg) + os.kill(os.getppid(), signal.SIGTERM) + else: + process_under_alerting[process_name] = time.time() + + # Handle the PROCESS_STATE_RUNNING event + elif headers['eventname'] == 'PROCESS_STATE_RUNNING': + payload_headers, payload_data = childutils.eventdata(payload + '\n') + process_name = payload_headers['processname'] + + if process_name in process_under_alerting: + process_under_alerting.pop(process_name) + + # Transition from BUSY to ACKNOWLEDGED + childutils.listener.ok() + + # Transition from ACKNOWLEDGED to READY + childutils.listener.ready() + + # Check whether we need write alerting messages into syslog + for process in process_under_alerting.keys(): + epoch_time = time.time() + if epoch_time - process_under_alerting[process] >= ALERTING_INTERVAL_SECS: + process_under_alerting[process] = epoch_time + generate_alerting_message(process) if __name__ == "__main__": diff --git a/installer/x86_64/install.sh b/installer/x86_64/install.sh index 349880114d0..a21054db368 100755 --- a/installer/x86_64/install.sh +++ b/installer/x86_64/install.sh @@ -20,6 +20,26 @@ _trap_push() { } _trap_push true +read_conf_file() { + local conf_file=$1 + while IFS='=' read -r var value || [ -n "$var" ] + do + # remove newline character + var=$(echo $var | tr -d '\r\n') + value=$(echo $value | tr -d '\r\n') + # remove comment string + var=${var%#*} + value=${value%#*} + # skip blank line + [ -z "$var" ] && continue + # remove double quote in the beginning + tmp_val=${value#\"} + # remove double quote in the end + value=${tmp_val%\"} + eval "$var=\"$value\"" + done < "$conf_file" +} + # Main set -e cd $(dirname $0) @@ -37,7 +57,7 @@ else fi if [ -r ./machine.conf ]; then -. ./machine.conf + read_conf_file "./machine.conf" fi if [ -r ./onie-image.conf ]; then @@ -54,9 +74,9 @@ fi # get running machine from conf file if [ -r /etc/machine.conf ]; then - . /etc/machine.conf + read_conf_file "/etc/machine.conf" elif [ -r /host/machine.conf ]; then - . /host/machine.conf + read_conf_file "/host/machine.conf" elif [ "$install_env" != "build" ]; then echo "cannot find machine.conf" exit 1 @@ -624,12 +644,12 @@ 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-4.19.0-9-2-amd64 root=$grub_cfg_root rw $GRUB_CMDLINE_LINUX \ + linux /$image_dir/boot/vmlinuz-4.19.0-12-2-amd64 root=$grub_cfg_root rw $GRUB_CMDLINE_LINUX \ net.ifnames=0 biosdevname=0 \ loop=$image_dir/$FILESYSTEM_SQUASHFS loopfstype=squashfs \ 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-4.19.0-9-2-amd64 + initrd /$image_dir/boot/initrd.img-4.19.0-12-2-amd64 } EOF diff --git a/installer/x86_64/tests/sample_machine.conf b/installer/x86_64/tests/sample_machine.conf new file mode 100644 index 00000000000..a8028cc6d8d --- /dev/null +++ b/installer/x86_64/tests/sample_machine.conf @@ -0,0 +1,16 @@ +# sample_machine.conf for onie + # A space in front of comment line +# One blank line below + +onie_machine_rev=0 +onie_arch=x86_64# some comment after declaration +# no value declaration +onie_config_version= +onie_build_date="2021-02-03T01:50+0800" +onie_partition_type=gpt +onie_disco_ntpsrv=192.168.0.1 192.168.0.2 +onie_firmware=auto +# another blank line below + +onie_skip_ethmgmt_macs=no +onie_grub_image_name=grubx64.efi \ No newline at end of file diff --git a/installer/x86_64/tests/test_read_conf.sh b/installer/x86_64/tests/test_read_conf.sh new file mode 100644 index 00000000000..06b7fc145ea --- /dev/null +++ b/installer/x86_64/tests/test_read_conf.sh @@ -0,0 +1,61 @@ +#!/bin/sh +# This is a standalone test file to test read_conf_file function for +# some types of machine.conf file. +# The read_conf_file function is copy from the install.sh + +MACHINE_CONF="sample_machine.conf" + +read_conf_file() { + local conf_file=$1 + while IFS='=' read -r var value || [ -n "$var" ] + do + # remove newline character + var=$(echo $var | tr -d '\r\n') + value=$(echo $value | tr -d '\r\n') + # remove comment string + var=${var%#*} + value=${value%#*} + # skip blank line + [ -z "$var" ] && continue + # remove double quote in the beginning + tmp_val=${value#\"} + # remove double quote in the end + value=${tmp_val%\"} + eval "$var=\"$value\"" + done < "$conf_file" +} + +TEST_CONF() { + input_value=$1 + exp_value=$2 + if [ "$input_value" != "$exp_value" ]; then + echo "[ERR] Expect value($exp_value) is not equal to input value($input_value)" + exit 1 + fi +} + +# define the expected variable value +exp_onie_machine_rev="0" +exp_onie_arch="x86_64" +exp_onie_build_date="2021-02-03T01:50+0800" +exp_onie_partition_type="gpt" +exp_onie_disco_ntpsrv="192.168.0.1 192.168.0.2" +exp_onie_firmware="auto" +exp_onie_skip_ethmgmt_macs="no" +exp_onie_grub_image_name="grubx64.efi" + +# read the sample conf file +read_conf_file $MACHINE_CONF + +# check each variable and its expected value +TEST_CONF "$onie_machine_rev" "$exp_onie_machine_rev" +TEST_CONF "$onie_arch" "$exp_onie_arch" +TEST_CONF "$onie_build_date" "$exp_onie_build_date" +TEST_CONF "$onie_partition_type" "$exp_onie_partition_type" +TEST_CONF "$onie_disco_ntpsrv" "$exp_onie_disco_ntpsrv" +TEST_CONF "$onie_firmware" "$exp_onie_firmware" +TEST_CONF "$onie_skip_ethmgmt_macs" "$exp_onie_skip_ethmgmt_macs" +TEST_CONF "$onie_grub_image_name" "$exp_onie_grub_image_name" + +echo "PASS!!" +exit 0 \ No newline at end of file diff --git a/platform/barefoot/bfn-modules/debian/control b/platform/barefoot/bfn-modules/debian/control index 2c3d8368bc4..be1f6cc0443 100644 --- a/platform/barefoot/bfn-modules/debian/control +++ b/platform/barefoot/bfn-modules/debian/control @@ -7,6 +7,6 @@ Standards-Version: 3.9.3 Package: bfn-modules Architecture: amd64 -Depends: linux-image-4.19.0-9-2-amd64-unsigned +Depends: linux-image-4.19.0-12-2-amd64-unsigned Description: kernel modules for bfn asic for mmap diff --git a/platform/barefoot/docker-ptf-bfn.mk b/platform/barefoot/docker-ptf-bfn.mk deleted file mode 100644 index 573e9cd9cff..00000000000 --- a/platform/barefoot/docker-ptf-bfn.mk +++ /dev/null @@ -1,5 +0,0 @@ -# docker image for docker-ptf - -DOCKER_PTF_BFN = docker-ptf-bfn.gz -$(DOCKER_PTF_BFN)_PATH = $(DOCKERS_PATH)/docker-ptf-saithrift -$(DOCKER_PTF_BFN)_LOAD_DOCKERS += $(DOCKER_PTF) diff --git a/platform/barefoot/docker-syncd-bfn-rpc/Dockerfile.j2 b/platform/barefoot/docker-syncd-bfn-rpc/Dockerfile.j2 index f3c9979dfa6..cf89b26b65e 100644 --- a/platform/barefoot/docker-syncd-bfn-rpc/Dockerfile.j2 +++ b/platform/barefoot/docker-syncd-bfn-rpc/Dockerfile.j2 @@ -21,6 +21,7 @@ RUN apt-get update \ && apt-get -y install \ net-tools \ python-pip \ + python-setuptools \ build-essential \ libssl-dev \ libffi-dev \ @@ -38,9 +39,10 @@ RUN apt-get update \ && cd .. \ && rm -fr nanomsg-1.0.0 \ && rm -f 1.0.0.tar.gz \ - && pip install cffi==1.7.0 \ - && pip install --upgrade cffi==1.7.0 \ - && pip install nnpy \ + && pip2 install cffi==1.7.0 \ + && pip2 install --upgrade cffi==1.7.0 \ + && pip2 install wheel \ + && pip2 install nnpy \ && mkdir -p /opt \ && cd /opt \ && wget https://raw.githubusercontent.com/p4lang/ptf/master/ptf_nn/ptf_nn_agent.py \ diff --git a/platform/barefoot/docker-syncd-bfn/supervisord.conf b/platform/barefoot/docker-syncd-bfn/supervisord.conf index 39ea308277d..c83484e5e93 100644 --- a/platform/barefoot/docker-syncd-bfn/supervisord.conf +++ b/platform/barefoot/docker-syncd-bfn/supervisord.conf @@ -14,7 +14,7 @@ buffer_size=25 [eventlistener:supervisor-proc-exit-listener] command=/usr/bin/supervisor-proc-exit-listener --container-name syncd -events=PROCESS_STATE_EXITED +events=PROCESS_STATE_EXITED,PROCESS_STATE_RUNNING autostart=true autorestart=unexpected diff --git a/platform/barefoot/rules.mk b/platform/barefoot/rules.mk index a2948b12892..98dcef0f7b8 100644 --- a/platform/barefoot/rules.mk +++ b/platform/barefoot/rules.mk @@ -10,7 +10,6 @@ include $(PLATFORM_PATH)/docker-syncd-bfn-rpc.mk include $(PLATFORM_PATH)/one-aboot.mk include $(PLATFORM_PATH)/one-image.mk include $(PLATFORM_PATH)/libsaithrift-dev.mk -include $(PLATFORM_PATH)/docker-ptf-bfn.mk include $(PLATFORM_PATH)/bfn-platform.mk #include $(PLATFORM_PATH)/bfn-platform-wnc.mk #include $(PLATFORM_PATH)/bfn-platform-ingrasys.mk diff --git a/platform/barefoot/sonic-platform-modules-bfn-montara/debian/control b/platform/barefoot/sonic-platform-modules-bfn-montara/debian/control index 7c46f1f96fa..a3ea06992dc 100644 --- a/platform/barefoot/sonic-platform-modules-bfn-montara/debian/control +++ b/platform/barefoot/sonic-platform-modules-bfn-montara/debian/control @@ -7,6 +7,6 @@ Standards-Version: 3.9.3 Package: sonic-platform-modules-bfn-montara Architecture: amd64 -Depends: linux-image-4.19.0-9-2-amd64-unsigned +Depends: linux-image-4.19.0-12-2-amd64-unsigned Description: kernel modules for platform devices such as fan, led, sfp diff --git a/platform/barefoot/sonic-platform-modules-bfn-montara/debian/postinst b/platform/barefoot/sonic-platform-modules-bfn-montara/debian/postinst new file mode 100755 index 00000000000..a218d59e265 --- /dev/null +++ b/platform/barefoot/sonic-platform-modules-bfn-montara/debian/postinst @@ -0,0 +1,10 @@ +#!/bin/sh +set -e + +PLATFORM_NAME=x86_64-accton_wedge100bf_32x-r0 +SONIC_PLATFORM_WHEEL_PY2="/usr/share/sonic/device/${PLATFORM_NAME}/sonic_platform-1.0-py2-none-any.whl" +python2 -m pip install ${SONIC_PLATFORM_WHEEL_PY2} +SONIC_PLATFORM_WHEEL_PY3="/usr/share/sonic/device/${PLATFORM_NAME}/sonic_platform-1.0-py3-none-any.whl" +python3 -m pip install ${SONIC_PLATFORM_WHEEL_PY3} + +#DEBHELPER# diff --git a/platform/barefoot/sonic-platform-modules-bfn-montara/debian/prerm b/platform/barefoot/sonic-platform-modules-bfn-montara/debian/prerm new file mode 100755 index 00000000000..ee19dbb1db9 --- /dev/null +++ b/platform/barefoot/sonic-platform-modules-bfn-montara/debian/prerm @@ -0,0 +1,6 @@ +#!/bin/sh + +python2 -m pip uninstall -y sonic-platform +python3 -m pip uninstall -y sonic-platform + +#DEBHELPER# diff --git a/platform/barefoot/sonic-platform-modules-bfn-montara/sonic_platform/eeprom.py b/platform/barefoot/sonic-platform-modules-bfn-montara/sonic_platform/eeprom.py index e25d224c1e8..a98a6bc1d45 100644 --- a/platform/barefoot/sonic-platform-modules-bfn-montara/sonic_platform/eeprom.py +++ b/platform/barefoot/sonic-platform-modules-bfn-montara/sonic_platform/eeprom.py @@ -17,7 +17,7 @@ from sonic_eeprom import eeprom_base from sonic_eeprom import eeprom_tlvinfo - from .platform_thrift_client import thrift_try + from platform_thrift_client import thrift_try except ImportError as e: raise ImportError (str(e) + "- required module not found") @@ -64,6 +64,11 @@ EEPROM_SYMLINK = "/var/run/platform/eeprom/syseeprom" EEPROM_STATUS = "/var/run/platform/eeprom/status" +try: + _str_type = basestring +except NameError: + _str_type = str + class Eeprom(eeprom_tlvinfo.TlvInfoDecoder): def __init__(self): @@ -101,7 +106,7 @@ def eeprom_parse(self): f.close() eeprom_params = "" - for attr, val in self.eeprom.__dict__.iteritems(): + for attr, val in self.eeprom.__dict__.items(): if val is None: continue @@ -109,7 +114,7 @@ def eeprom_parse(self): if elem is None: continue - if isinstance(val, basestring): + if isinstance(val, _str_type): value = val.replace('\0', '') else: value = str(val) @@ -136,14 +141,17 @@ def eeprom_parse(self): return True - def serial_number_str(self): + def serial_str(self): return self.eeprom.prod_ser_num def system_eeprom_info(self): return self.eeprom.__dict__ - def get_base_mac(self): - return self.eeprom.ext_mac_addr + def base_mac_addr(self): + return self.eeprom.ext_mac_addr.rstrip('\x00') def part_number_str(self): return self.eeprom.prod_part_num + + def modelstr(self): + return self.eeprom.prod_name diff --git a/platform/barefoot/sonic-platform-modules-bfn-newport/debian/control b/platform/barefoot/sonic-platform-modules-bfn-newport/debian/control index 89135fda247..d2c37fe8d2b 100644 --- a/platform/barefoot/sonic-platform-modules-bfn-newport/debian/control +++ b/platform/barefoot/sonic-platform-modules-bfn-newport/debian/control @@ -7,11 +7,11 @@ Standards-Version: 3.9.3 Package: sonic-platform-modules-bfn-newport-as9516 Architecture: amd64 -Depends: linux-image-4.19.0-9-2-amd64-unsigned +Depends: linux-image-4.19.0-12-2-amd64-unsigned Description: kernel module for bfn platform fpga and scripts for the devices such as fan, led, sfp Package: sonic-platform-modules-bfn-newport-as9516bf Architecture: amd64 -Depends: linux-image-4.19.0-9-2-amd64-unsigned +Depends: linux-image-4.19.0-12-2-amd64-unsigned Description: kernel module for bfn platform fpga and scripts for the devices such as fan, led, sfp diff --git a/platform/barefoot/sonic-platform-modules-bfn-newport/debian/postinst b/platform/barefoot/sonic-platform-modules-bfn-newport/debian/postinst index a89ac4f4f5b..90d772ef89d 100644 --- a/platform/barefoot/sonic-platform-modules-bfn-newport/debian/postinst +++ b/platform/barefoot/sonic-platform-modules-bfn-newport/debian/postinst @@ -1,6 +1,27 @@ #!/bin/sh set -e -depmod -a +depmod -a systemctl enable bfn-newport.service systemctl start bfn-newport.service + +PLATFORM_NAME=x86_64-accton_as9516bf_32d-r0 +SONIC_PLATFORM_WHEEL_PY2="/usr/share/sonic/device/${PLATFORM_NAME}/sonic_platform-1.0-py2-none-any.whl" +if [ -e ${SONIC_PLATFORM_WHEEL_PY2} ]; then + python2 -m pip install ${SONIC_PLATFORM_WHEEL_PY2} +fi +SONIC_PLATFORM_WHEEL_PY3="/usr/share/sonic/device/${PLATFORM_NAME}/sonic_platform-1.0-py3-none-any.whl" +if [ -e ${SONIC_PLATFORM_WHEEL_PY3} ]; then + python3 -m pip install ${SONIC_PLATFORM_WHEEL_PY3} +fi + +PLATFORM_NAME=x86_64-accton_as9516_32d-r0 +SONIC_PLATFORM_WHEEL_PY2="/usr/share/sonic/device/${PLATFORM_NAME}/sonic_platform-1.0-py2-none-any.whl" +if [ -e ${SONIC_PLATFORM_WHEEL_PY2} ]; then + python2 -m pip install ${SONIC_PLATFORM_WHEEL_PY2} +fi +SONIC_PLATFORM_WHEEL_PY3="/usr/share/sonic/device/${PLATFORM_NAME}/sonic_platform-1.0-py3-none-any.whl" +if [ -e ${SONIC_PLATFORM_WHEEL_PY3} ]; then + python3 -m pip install ${SONIC_PLATFORM_WHEEL_PY3} +fi + #DEBHELPER# diff --git a/platform/barefoot/sonic-platform-modules-bfn-newport/debian/prerm b/platform/barefoot/sonic-platform-modules-bfn-newport/debian/prerm new file mode 100644 index 00000000000..ee19dbb1db9 --- /dev/null +++ b/platform/barefoot/sonic-platform-modules-bfn-newport/debian/prerm @@ -0,0 +1,6 @@ +#!/bin/sh + +python2 -m pip uninstall -y sonic-platform +python3 -m pip uninstall -y sonic-platform + +#DEBHELPER# diff --git a/platform/barefoot/sonic-platform-modules-bfn/debian/control b/platform/barefoot/sonic-platform-modules-bfn/debian/control index e5ce77ba712..89c597303a7 100644 --- a/platform/barefoot/sonic-platform-modules-bfn/debian/control +++ b/platform/barefoot/sonic-platform-modules-bfn/debian/control @@ -7,6 +7,6 @@ Standards-Version: 3.9.3 Package: sonic-platform-modules-bfn Architecture: amd64 -Depends: linux-image-4.19.0-9-2-amd64-unsigned +Depends: linux-image-4.19.0-12-2-amd64-unsigned Description: kernel modules for platform devices such as fan, led, sfp diff --git a/platform/barefoot/sonic-platform-modules-bfn/debian/postinst b/platform/barefoot/sonic-platform-modules-bfn/debian/postinst new file mode 100644 index 00000000000..bd24c078778 --- /dev/null +++ b/platform/barefoot/sonic-platform-modules-bfn/debian/postinst @@ -0,0 +1,10 @@ +#!/bin/sh +set -e + +PLATFORM_NAME=x86_64-accton_wedge100bf_65x-r0 +SONIC_PLATFORM_WHEEL_PY2="/usr/share/sonic/device/${PLATFORM_NAME}/sonic_platform-1.0-py2-none-any.whl" +python2 -m pip install ${SONIC_PLATFORM_WHEEL_PY2} +SONIC_PLATFORM_WHEEL_PY3="/usr/share/sonic/device/${PLATFORM_NAME}/sonic_platform-1.0-py3-none-any.whl" +python3 -m pip install ${SONIC_PLATFORM_WHEEL_PY3} + +#DEBHELPER# diff --git a/platform/barefoot/sonic-platform-modules-bfn/debian/prerm b/platform/barefoot/sonic-platform-modules-bfn/debian/prerm new file mode 100755 index 00000000000..ee19dbb1db9 --- /dev/null +++ b/platform/barefoot/sonic-platform-modules-bfn/debian/prerm @@ -0,0 +1,6 @@ +#!/bin/sh + +python2 -m pip uninstall -y sonic-platform +python3 -m pip uninstall -y sonic-platform + +#DEBHELPER# diff --git a/platform/barefoot/sonic-platform-modules-wnc-osw1800/debian/control b/platform/barefoot/sonic-platform-modules-wnc-osw1800/debian/control index 6f7bd62ffcc..eab1adcadec 100644 --- a/platform/barefoot/sonic-platform-modules-wnc-osw1800/debian/control +++ b/platform/barefoot/sonic-platform-modules-wnc-osw1800/debian/control @@ -7,6 +7,6 @@ Standards-Version: 3.9.3 Package: platform-modules-wnc-osw1800 Architecture: amd64 -Depends: linux-image-4.19.0-9-2-amd64-unsigned +Depends: linux-image-4.19.0-12-2-amd64-unsigned Description: kernel modules for platform devices such as fan, led, sfp diff --git a/platform/broadcom/docker-ptf-brcm.dep b/platform/broadcom/docker-ptf-brcm.dep deleted file mode 100644 index b899d058d44..00000000000 --- a/platform/broadcom/docker-ptf-brcm.dep +++ /dev/null @@ -1,10 +0,0 @@ - -DPATH := $($(DOCKER_PTF_BRCM)_PATH) -DEP_FILES := $(SONIC_COMMON_FILES_LIST) platform/broadcom/docker-ptf-brcm.mk platform/broadcom/docker-ptf-brcm.dep -DEP_FILES += $(SONIC_COMMON_BASE_FILES_LIST) -DEP_FILES += $(shell git ls-files $(DPATH)) - -$(DOCKER_PTF_BRCM)_CACHE_MODE := GIT_CONTENT_SHA -$(DOCKER_PTF_BRCM)_DEP_FLAGS := $(SONIC_COMMON_FLAGS_LIST) -$(DOCKER_PTF_BRCM)_DEP_FILES := $(DEP_FILES) - diff --git a/platform/broadcom/docker-ptf-brcm.mk b/platform/broadcom/docker-ptf-brcm.mk deleted file mode 100644 index 35780aea76c..00000000000 --- a/platform/broadcom/docker-ptf-brcm.mk +++ /dev/null @@ -1,8 +0,0 @@ -# docker image for docker-ptf-brcm - -DOCKER_PTF_BRCM = docker-ptf-brcm.gz -$(DOCKER_PTF_BRCM)_PATH = $(DOCKERS_PATH)/docker-ptf-saithrift -$(DOCKER_PTF_BRCM)_DEPENDS += $(PYTHON_SAITHRIFT) -$(DOCKER_PTF_BRCM)_LOAD_DOCKERS += $(DOCKER_PTF) -SONIC_DOCKER_IMAGES += $(DOCKER_PTF_BRCM) -SONIC_STRETCH_DOCKERS += $(DOCKER_PTF_BRCM) diff --git a/platform/broadcom/docker-syncd-brcm-rpc/Dockerfile.j2 b/platform/broadcom/docker-syncd-brcm-rpc/Dockerfile.j2 index f68fbb661d9..ada6113ddf4 100644 --- a/platform/broadcom/docker-syncd-brcm-rpc/Dockerfile.j2 +++ b/platform/broadcom/docker-syncd-brcm-rpc/Dockerfile.j2 @@ -21,6 +21,7 @@ RUN apt-get update \ && apt-get -y install \ net-tools \ python-pip \ + python-setuptools \ build-essential \ libssl-dev \ libffi-dev \ @@ -37,9 +38,10 @@ RUN apt-get update \ && cd .. \ && rm -fr nanomsg-1.0.0 \ && rm -f 1.0.0.tar.gz \ - && pip install cffi==1.7.0 \ - && pip install --upgrade cffi==1.7.0 \ - && pip install nnpy \ + && pip2 install cffi==1.7.0 \ + && pip2 install --upgrade cffi==1.7.0 \ + && pip2 install wheel \ + && pip2 install nnpy \ && mkdir -p /opt \ && cd /opt \ && wget https://raw.githubusercontent.com/p4lang/ptf/master/ptf_nn/ptf_nn_agent.py \ diff --git a/platform/broadcom/docker-syncd-brcm.dep b/platform/broadcom/docker-syncd-brcm.dep index 48fa57f3347..c020a72f2a0 100644 --- a/platform/broadcom/docker-syncd-brcm.dep +++ b/platform/broadcom/docker-syncd-brcm.dep @@ -1,6 +1,6 @@ #DPKG FRK DPATH := $($(DOCKER_SYNCD_BASE)_PATH) -DEP_FILES := $(SONIC_COMMON_FILES_LIST) platform/broadcom/docker-syncd-brcm.mk platform/broadcom/docker-syncd-brcm.dep +DEP_FILES := $(SONIC_COMMON_FILES_LIST) platform/broadcom/docker-syncd-brcm.mk platform/broadcom/docker-syncd-brcm.dep platform/broadcom/sai.mk DEP_FILES += $(SONIC_COMMON_BASE_FILES_LIST) DEP_FILES += $(shell git ls-files $(DPATH)) diff --git a/platform/broadcom/docker-syncd-brcm/Dockerfile.j2 b/platform/broadcom/docker-syncd-brcm/Dockerfile.j2 index cf597df680d..0ba71bb5d78 100755 --- a/platform/broadcom/docker-syncd-brcm/Dockerfile.j2 +++ b/platform/broadcom/docker-syncd-brcm/Dockerfile.j2 @@ -21,6 +21,9 @@ debs/ ## TODO: add kmod into Depends RUN apt-get install -yf kmod +## BRCM uses ethtool to set host interface speed +RUN apt-get install -y ethtool + COPY ["files/dsserve", "files/bcmcmd", "start.sh", "start_led.sh", "bcmsh", "/usr/bin/"] RUN chmod +x /usr/bin/dsserve /usr/bin/bcmcmd diff --git a/platform/broadcom/docker-syncd-brcm/supervisord.conf b/platform/broadcom/docker-syncd-brcm/supervisord.conf index a8e594c47ae..5e801106972 100644 --- a/platform/broadcom/docker-syncd-brcm/supervisord.conf +++ b/platform/broadcom/docker-syncd-brcm/supervisord.conf @@ -14,7 +14,7 @@ buffer_size=25 [eventlistener:supervisor-proc-exit-listener] command=/usr/bin/supervisor-proc-exit-listener --container-name syncd -events=PROCESS_STATE_EXITED +events=PROCESS_STATE_EXITED,PROCESS_STATE_RUNNING autostart=true autorestart=unexpected diff --git a/platform/broadcom/rules.dep b/platform/broadcom/rules.dep index d8142ae3fb7..2e2d44ed018 100644 --- a/platform/broadcom/rules.dep +++ b/platform/broadcom/rules.dep @@ -22,4 +22,3 @@ include $(PLATFORM_PATH)/one-pde-image.dep include $(PLATFORM_PATH)/raw-image.dep include $(PLATFORM_PATH)/one-aboot.dep include $(PLATFORM_PATH)/libsaithrift-dev.dep -include $(PLATFORM_PATH)/docker-ptf-brcm.dep diff --git a/platform/broadcom/rules.mk b/platform/broadcom/rules.mk index 34edfa0d37f..fbe0dd689a2 100644 --- a/platform/broadcom/rules.mk +++ b/platform/broadcom/rules.mk @@ -19,7 +19,6 @@ include $(PLATFORM_PATH)/one-image.mk include $(PLATFORM_PATH)/raw-image.mk include $(PLATFORM_PATH)/one-aboot.mk include $(PLATFORM_PATH)/libsaithrift-dev.mk -include $(PLATFORM_PATH)/docker-ptf-brcm.mk BCMCMD = bcmcmd $(BCMCMD)_URL = "https://sonicstorage.blob.core.windows.net/packages/20190307/bcmcmd?sv=2015-04-05&sr=b&sig=sUdbU7oVbh5exbXXHVL5TDFBTWDDBASHeJ8Cp0B0TIc%3D&se=2038-05-06T22%3A34%3A19Z&sp=r" diff --git a/platform/broadcom/sai-modules.mk b/platform/broadcom/sai-modules.mk index 84d97c09ac8..2d4262518c6 100644 --- a/platform/broadcom/sai-modules.mk +++ b/platform/broadcom/sai-modules.mk @@ -1,6 +1,6 @@ # Broadcom SAI modules -BRCM_OPENNSL_KERNEL_VERSION = 4.2.1.3-1 +BRCM_OPENNSL_KERNEL_VERSION = 4.3.0.10-2 BRCM_OPENNSL_KERNEL = opennsl-modules_$(BRCM_OPENNSL_KERNEL_VERSION)_amd64.deb $(BRCM_OPENNSL_KERNEL)_SRC_PATH = $(PLATFORM_PATH)/saibcm-modules diff --git a/platform/broadcom/sai.mk b/platform/broadcom/sai.mk index fcb175d3d0c..e36319619b0 100644 --- a/platform/broadcom/sai.mk +++ b/platform/broadcom/sai.mk @@ -1,8 +1,8 @@ -BRCM_SAI = libsaibcm_4.2.1.5-10_amd64.deb -$(BRCM_SAI)_URL = "https://sonicstorage.blob.core.windows.net/packages/bcmsai/4.2/master/buster/libsaibcm_4.2.1.5-10_amd64.deb?sv=2019-12-12&st=2021-01-12T07%3A30%3A31Z&se=2035-01-13T07%3A30%3A00Z&sr=b&sp=r&sig=yCGwk%2FW%2Fg%2FaFxhr0oNSTZ%2BVy5B6kX1WDEsbbyz9J088%3D" -BRCM_SAI_DEV = libsaibcm-dev_4.2.1.5-10_amd64.deb +BRCM_SAI = libsaibcm_4.3.0.10-5_amd64.deb +$(BRCM_SAI)_URL = "https://sonicstorage.blob.core.windows.net/packages/bcmsai/4.3/master/libsaibcm_4.3.0.10-5_amd64.deb?sv=2019-12-12&st=2021-02-08T00%3A20%3A49Z&se=2030-02-09T00%3A20%3A00Z&sr=b&sp=r&sig=rEpcTHNsSr10rKhpr6Cx3EFNa2dRE7VLP7ybZijQKpE%3D" +BRCM_SAI_DEV = libsaibcm-dev_4.3.0.10-5_amd64.deb $(eval $(call add_derived_package,$(BRCM_SAI),$(BRCM_SAI_DEV))) -$(BRCM_SAI_DEV)_URL = "https://sonicstorage.blob.core.windows.net/packages/bcmsai/4.2/master/buster/libsaibcm-dev_4.2.1.5-10_amd64.deb?sv=2019-12-12&st=2021-01-12T07%3A32%3A43Z&se=2035-01-13T07%3A32%3A00Z&sr=b&sp=r&sig=wuCNc6pa12JQCBi%2BM9rLWvVI92ldan9hKNF%2BfVfUWN8%3D" +$(BRCM_SAI_DEV)_URL = "https://sonicstorage.blob.core.windows.net/packages/bcmsai/4.3/master/libsaibcm-dev_4.3.0.10-5_amd64.deb?sv=2019-12-12&st=2021-02-08T00%3A21%3A42Z&se=2030-02-09T00%3A21%3A00Z&sr=b&sp=r&sig=gvDnVYkQe%2FA2Yqw9p404Vtmx%2Fo8NwJMFoCn7K4W1k0M%3D" SONIC_ONLINE_DEBS += $(BRCM_SAI) $(BRCM_SAI_DEV)_DEPENDS += $(BRCM_SAI) diff --git a/platform/broadcom/saibcm-modules/debian/changelog b/platform/broadcom/saibcm-modules/debian/changelog index f2b0db31e66..87d659d21a6 100644 --- a/platform/broadcom/saibcm-modules/debian/changelog +++ b/platform/broadcom/saibcm-modules/debian/changelog @@ -1,3 +1,10 @@ +opennsl (4.3.0.10-2) unstable; urgency=medium + + * Update to Broadcom SAI 4.3.0.10 + * Added SDKLT modules 4.3.0.10-2 + + -- Mahesh Maddikayala Thu, 21 Jan 2021 18:36:38 +0000 + opennsl (4.2.1.3-1) unstable; urgency=medium * Update to Broadcom SAI 4.2.1.3 diff --git a/platform/broadcom/saibcm-modules/debian/control b/platform/broadcom/saibcm-modules/debian/control index d022eadb050..60bcbafb1b1 100644 --- a/platform/broadcom/saibcm-modules/debian/control +++ b/platform/broadcom/saibcm-modules/debian/control @@ -10,5 +10,5 @@ Standards-Version: 3.9.3 Package: opennsl-modules Architecture: amd64 Section: main -Depends: linux-image-4.19.0-9-2-amd64-unsigned +Depends: linux-image-4.19.0-12-2-amd64-unsigned Description: kernel modules for broadcom SAI diff --git a/platform/broadcom/saibcm-modules/debian/opennsl-modules.dirs b/platform/broadcom/saibcm-modules/debian/opennsl-modules.dirs index 27fae96d8a1..140d1186059 100644 --- a/platform/broadcom/saibcm-modules/debian/opennsl-modules.dirs +++ b/platform/broadcom/saibcm-modules/debian/opennsl-modules.dirs @@ -1 +1 @@ -lib/modules/4.19.0-9-2-amd64/extra +lib/modules/4.19.0-12-2-amd64/extra diff --git a/platform/broadcom/saibcm-modules/debian/opennsl-modules.init b/platform/broadcom/saibcm-modules/debian/opennsl-modules.init index 7def10cbff8..09112f5331c 100755 --- a/platform/broadcom/saibcm-modules/debian/opennsl-modules.init +++ b/platform/broadcom/saibcm-modules/debian/opennsl-modules.init @@ -18,7 +18,9 @@ function create_devices() rm -f /dev/linux-bcm-knet rm -f /dev/linux-bcm-bde rm -f /dev/linux-kernel-bde + rm -f /dev/linux_ngbde + mknod /dev/linux_ngbde c 120 0 mknod /dev/linux-knet-cb c 121 0 mknod /dev/linux-bcm-knet c 122 0 mknod /dev/linux-bcm-bde c 126 0 @@ -57,8 +59,9 @@ function load_kernel_modules() # There is a different psample.ko module getting created at net/psample/psample.ko insmod /lib/modules/$(uname -r)/extra/psample.ko - modprobe linux-bcm-knet use_rx_skb=1 rx_buffer_size=9238 debug=0x5020 + modprobe linux-bcm-knet use_rx_skb=1 rx_buffer_size=9238 debug=0x5020 default_mtu=9100 modprobe linux-knet-cb + modprobe linux_ngbde } function remove_kernel_modules() @@ -68,6 +71,7 @@ function remove_kernel_modules() rmmod linux-bcm-knet rmmod linux-user-bde rmmod linux-kernel-bde + rmmod linux_ngbde } case "$1" in diff --git a/platform/broadcom/saibcm-modules/debian/opennsl-modules.install b/platform/broadcom/saibcm-modules/debian/opennsl-modules.install index 0e8051fbbca..c4d7ace7969 100644 --- a/platform/broadcom/saibcm-modules/debian/opennsl-modules.install +++ b/platform/broadcom/saibcm-modules/debian/opennsl-modules.install @@ -1,7 +1,8 @@ -systems/linux/user/x86-smp_generic_64-2_6/linux-bcm-knet.ko lib/modules/4.19.0-9-2-amd64/extra -systems/linux/user/x86-smp_generic_64-2_6/linux-kernel-bde.ko lib/modules/4.19.0-9-2-amd64/extra -systems/linux/user/x86-smp_generic_64-2_6/linux-user-bde.ko lib/modules/4.19.0-9-2-amd64/extra -systems/linux/user/x86-smp_generic_64-2_6/linux-knet-cb.ko lib/modules/4.19.0-9-2-amd64/extra -systems/linux/user/x86-smp_generic_64-2_6/psample.ko lib/modules/4.19.0-9-2-amd64/extra -systems/linux/user/x86-smp_generic_64-2_6/linux-bcm-ptp-clock.ko lib/modules/4.19.0-9-2-amd64/extra +systems/linux/user/x86-smp_generic_64-2_6/linux-bcm-knet.ko lib/modules/4.19.0-12-2-amd64/extra +systems/linux/user/x86-smp_generic_64-2_6/linux-kernel-bde.ko lib/modules/4.19.0-12-2-amd64/extra +systems/linux/user/x86-smp_generic_64-2_6/linux-user-bde.ko lib/modules/4.19.0-12-2-amd64/extra +systems/linux/user/x86-smp_generic_64-2_6/linux-knet-cb.ko lib/modules/4.19.0-12-2-amd64/extra +systems/linux/user/x86-smp_generic_64-2_6/psample.ko lib/modules/4.19.0-12-2-amd64/extra +systems/linux/user/x86-smp_generic_64-2_6/linux-bcm-ptp-clock.ko lib/modules/4.19.0-12-2-amd64/extra systemd/opennsl-modules.service lib/systemd/system +sdklt/linux/bde/linux_ngbde.ko lib/modules/4.19.0-9-2-amd64/extra diff --git a/platform/broadcom/saibcm-modules/debian/rules b/platform/broadcom/saibcm-modules/debian/rules index 64cc9b6c07e..572471027c8 100755 --- a/platform/broadcom/saibcm-modules/debian/rules +++ b/platform/broadcom/saibcm-modules/debian/rules @@ -34,8 +34,8 @@ sname:=opennsl PACKAGE=opennsl-modules # modifieable for experiments or debugging m-a MA_DIR ?= /usr/share/modass -KVERSION ?= 4.19.0-9-2-amd64 -KERNVERSION ?= 4.19.0-9-2 +KVERSION ?= 4.19.0-12-2-amd64 +KERNVERSION ?= 4.19.0-12-2 # load generic variable handling -include $(MA_DIR)/include/generic.make @@ -67,6 +67,9 @@ kdist_clean: clean KERNDIR=/usr/src/linux-headers-$(KERNVERSION)-common \ KERNEL_SRC=/usr/src/linux-headers-$(KERNVERSION)-amd64 \ $(MAKE) -C systems/linux/user/x86-smp_generic_64-2_6 clean + SDK=$(realpath .) BUILD_KNET_CB=1 BUILD_PSAMPLE=1 \ + KDIR=/usr/src/linux-headers-$(KERNVERSION)-common \ + $(MAKE) -C sdklt/ clean # rm -f driver/*.o driver/*.ko # ### end KERNEL SETUP @@ -100,6 +103,10 @@ build-arch-stamp: KERNEL_SRC=/usr/src/linux-headers-$(KERNVERSION)-amd64 \ $(MAKE) -C systems/linux/user/x86-smp_generic_64-2_6 + SDK=$(realpath .) BUILD_KNET_CB=1 BUILD_PSAMPLE=1 \ + KDIR=/usr/src/linux-headers-$(KERNVERSION)-common \ + $(MAKE) -C sdklt/ kmod + touch $@ #k = $(shell echo $(KVERS) | grep -q ^2.6 && echo k) @@ -128,6 +135,10 @@ clean: KERNEL_SRC=/usr/src/linux-headers-$(KERNVERSION)-amd64 \ $(MAKE) -C systems/linux/user/x86-smp_generic_64-2_6 clean + SDK=$(realpath .) BUILD_KNET_CB=1 BUILD_PSAMPLE=1 \ + KDIR=/usr/src/linux-headers-$(KERNVERSION)-common \ + $(MAKE) -C sdklt/ clean + dh_clean install: DH_OPTIONS= diff --git a/platform/broadcom/saibcm-modules/include/ibde.h b/platform/broadcom/saibcm-modules/include/ibde.h index 5f371b2667c..fb9d13d1d5f 100644 --- a/platform/broadcom/saibcm-modules/include/ibde.h +++ b/platform/broadcom/saibcm-modules/include/ibde.h @@ -1,5 +1,10 @@ /* - * Copyright 2017 Broadcom + * Copyright 2007-2020 Broadcom Inc. All rights reserved. + * + * Permission is granted to use, copy, modify and/or distribute this + * software under either one of the licenses below. + * + * License Option 1: GPL * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License, version 2, as @@ -12,6 +17,12 @@ * * You should have received a copy of the GNU General Public License * version 2 (GPLv2) along with this source code. + * + * + * License Option 2: Broadcom Open Network Switch APIs (OpenNSA) license + * + * This software is governed by the Broadcom Open Network Switch APIs license: + * https://www.broadcom.com/products/ethernet-connectivity/software/opennsa */ /* * $Id: ibde.h,v 1.27 Broadcom SDK $ diff --git a/platform/broadcom/saibcm-modules/include/kcom.h b/platform/broadcom/saibcm-modules/include/kcom.h index eb41e1a5aaf..5129400ca8c 100644 --- a/platform/broadcom/saibcm-modules/include/kcom.h +++ b/platform/broadcom/saibcm-modules/include/kcom.h @@ -1,5 +1,10 @@ /* - * Copyright 2017 Broadcom + * Copyright 2007-2020 Broadcom Inc. All rights reserved. + * + * Permission is granted to use, copy, modify and/or distribute this + * software under either one of the licenses below. + * + * License Option 1: GPL * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License, version 2, as @@ -12,6 +17,12 @@ * * You should have received a copy of the GNU General Public License * version 2 (GPLv2) along with this source code. + * + * + * License Option 2: Broadcom Open Network Switch APIs (OpenNSA) license + * + * This software is governed by the Broadcom Open Network Switch APIs license: + * https://www.broadcom.com/products/ethernet-connectivity/software/opennsa */ /* * $Id: kcom.h,v 1.9 Broadcom SDK $ @@ -341,6 +352,8 @@ typedef struct kcom_msg_version_s { #define KSYNC_M_HW_DEINIT 1 #define KSYNC_M_VERSION 2 #define KSYNC_M_HW_TS_DISABLE 3 +#define KSYNC_M_MTP_TS_UPDATE_ENABLE 4 +#define KSYNC_M_MTP_TS_UPDATE_DISABLE 5 typedef struct kcom_clock_info_s { uint8 cmd; diff --git a/platform/broadcom/saibcm-modules/include/sal/core/sync.h b/platform/broadcom/saibcm-modules/include/sal/core/sync.h index 75dd6ce6831..03fd2facc90 100644 --- a/platform/broadcom/saibcm-modules/include/sal/core/sync.h +++ b/platform/broadcom/saibcm-modules/include/sal/core/sync.h @@ -1,5 +1,10 @@ /* - * Copyright 2017 Broadcom + * Copyright 2007-2020 Broadcom Inc. All rights reserved. + * + * Permission is granted to use, copy, modify and/or distribute this + * software under either one of the licenses below. + * + * License Option 1: GPL * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License, version 2, as @@ -12,6 +17,12 @@ * * You should have received a copy of the GNU General Public License * version 2 (GPLv2) along with this source code. + * + * + * License Option 2: Broadcom Open Network Switch APIs (OpenNSA) license + * + * This software is governed by the Broadcom Open Network Switch APIs license: + * https://www.broadcom.com/products/ethernet-connectivity/software/opennsa */ /* * $Id: sync.h,v 1.1 Broadcom SDK $ diff --git a/platform/broadcom/saibcm-modules/include/sal/core/thread.h b/platform/broadcom/saibcm-modules/include/sal/core/thread.h index b7ecb722489..86713d1e074 100644 --- a/platform/broadcom/saibcm-modules/include/sal/core/thread.h +++ b/platform/broadcom/saibcm-modules/include/sal/core/thread.h @@ -1,5 +1,10 @@ /* - * Copyright 2017 Broadcom + * Copyright 2007-2020 Broadcom Inc. All rights reserved. + * + * Permission is granted to use, copy, modify and/or distribute this + * software under either one of the licenses below. + * + * License Option 1: GPL * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License, version 2, as @@ -12,6 +17,12 @@ * * You should have received a copy of the GNU General Public License * version 2 (GPLv2) along with this source code. + * + * + * License Option 2: Broadcom Open Network Switch APIs (OpenNSA) license + * + * This software is governed by the Broadcom Open Network Switch APIs license: + * https://www.broadcom.com/products/ethernet-connectivity/software/opennsa */ /* * $Id: thread.h,v 1.1 Broadcom SDK $ diff --git a/platform/broadcom/saibcm-modules/include/sal/types.h b/platform/broadcom/saibcm-modules/include/sal/types.h index 7ed68f43e5e..43d64dbcc6b 100644 --- a/platform/broadcom/saibcm-modules/include/sal/types.h +++ b/platform/broadcom/saibcm-modules/include/sal/types.h @@ -1,5 +1,10 @@ /* - * Copyright 2017 Broadcom + * Copyright 2007-2020 Broadcom Inc. All rights reserved. + * + * Permission is granted to use, copy, modify and/or distribute this + * software under either one of the licenses below. + * + * License Option 1: GPL * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License, version 2, as @@ -12,6 +17,12 @@ * * You should have received a copy of the GNU General Public License * version 2 (GPLv2) along with this source code. + * + * + * License Option 2: Broadcom Open Network Switch APIs (OpenNSA) license + * + * This software is governed by the Broadcom Open Network Switch APIs license: + * https://www.broadcom.com/products/ethernet-connectivity/software/opennsa */ /* * $Id: types.h,v 1.3 Broadcom SDK $ diff --git a/platform/broadcom/saibcm-modules/include/sdk_config.h b/platform/broadcom/saibcm-modules/include/sdk_config.h index 9d781114bdf..6ce7d77d52d 100644 --- a/platform/broadcom/saibcm-modules/include/sdk_config.h +++ b/platform/broadcom/saibcm-modules/include/sdk_config.h @@ -1,5 +1,10 @@ /* - * Copyright 2017 Broadcom + * Copyright 2007-2020 Broadcom Inc. All rights reserved. + * + * Permission is granted to use, copy, modify and/or distribute this + * software under either one of the licenses below. + * + * License Option 1: GPL * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License, version 2, as @@ -12,6 +17,12 @@ * * You should have received a copy of the GNU General Public License * version 2 (GPLv2) along with this source code. + * + * + * License Option 2: Broadcom Open Network Switch APIs (OpenNSA) license + * + * This software is governed by the Broadcom Open Network Switch APIs license: + * https://www.broadcom.com/products/ethernet-connectivity/software/opennsa */ /* * $Id: sdk_config.h,v 1.5 Broadcom SDK $ diff --git a/platform/broadcom/saibcm-modules/include/soc/devids.h b/platform/broadcom/saibcm-modules/include/soc/devids.h index bb91d90be03..89fabac4453 100644 --- a/platform/broadcom/saibcm-modules/include/soc/devids.h +++ b/platform/broadcom/saibcm-modules/include/soc/devids.h @@ -1,5 +1,10 @@ /* - * Copyright 2017 Broadcom + * Copyright 2007-2020 Broadcom Inc. All rights reserved. + * + * Permission is granted to use, copy, modify and/or distribute this + * software under either one of the licenses below. + * + * License Option 1: GPL * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License, version 2, as @@ -12,6 +17,12 @@ * * You should have received a copy of the GNU General Public License * version 2 (GPLv2) along with this source code. + * + * + * License Option 2: Broadcom Open Network Switch APIs (OpenNSA) license + * + * This software is governed by the Broadcom Open Network Switch APIs license: + * https://www.broadcom.com/products/ethernet-connectivity/software/opennsa */ /* * Copyright: (c) 2020 Broadcom. @@ -1274,6 +1285,18 @@ #define BCM56278_A0_REV_ID 1 #define BCM56278_A1_REV_ID 2 +#define BCM56279_DEVICE_ID 0xb279 +#define BCM56279_A1_REV_ID 2 + +#define BCM56575_DEVICE_ID 0xb575 +#define BCM56575_A1_REV_ID 2 + +#define BCM56175_DEVICE_ID 0xb175 +#define BCM56175_A1_REV_ID 2 + +#define BCM56176_DEVICE_ID 0xb176 +#define BCM56176_A1_REV_ID 2 + #define BCM53440_DEVICE_ID 0x8440 #define BCM53440_A0_REV_ID 1 #define BCM53440_B0_REV_ID 0x11 @@ -1404,6 +1427,8 @@ #define BCM56070_A0_REV_ID 1 #define BCM56071_DEVICE_ID 0xb071 #define BCM56071_A0_REV_ID 1 +#define BCM56072_DEVICE_ID 0xb072 +#define BCM56072_A0_REV_ID 1 #define BCM56965_DEVICE_ID 0xb965 @@ -1499,6 +1524,8 @@ #define BCM56471_A0_REV_ID 1 #define BCM56472_DEVICE_ID 0xb472 #define BCM56472_A0_REV_ID 1 +#define BCM56475_DEVICE_ID 0xb475 +#define BCM56475_A0_REV_ID 1 #define BCM53540_DEVICE_ID 0x8540 @@ -1537,19 +1564,6 @@ #define BCM88650_A0_REV_ID ARAD_A0_REV_ID #define BCM88650_B0_REV_ID ARAD_B0_REV_ID #define BCM88650_B1_REV_ID ARAD_B1_REV_ID -#define BCM88750_DEVICE_ID 0x8750 -#define BCM88750_A0_REV_ID 0x0000 -#define BCM88750_B0_REV_ID 0x0011 -#define BCM88753_DEVICE_ID 0x8753 -#define BCM88753_A0_REV_ID 0x0000 -#define BCM88753_B0_REV_ID 0x0011 -#define BCM88754_DEVICE_ID 0x8754 -#define BCM88754_A0_REV_ID 0x0000 -#define BCM88754_ORIGINAL_VENDOR_ID 0x16FC -#define BCM88754_ORIGINAL_DEVICE_ID 0x020F -#define BCM88754_A0_ORIGINAL_REV_ID 0x0001 -#define BCM88755_DEVICE_ID 0x8755 -#define BCM88755_B0_REV_ID 0x0011 #define BCM88770_DEVICE_ID 0x8770 #define BCM88770_A1_REV_ID 0x0002 #define BCM88773_DEVICE_ID 0x8773 @@ -1767,22 +1781,57 @@ #define BCM88820_DEVICE_ID J2C_2ND_DEVICE_ID #define BCM88800_A0_REV_ID J2C_A0_REV_ID #define BCM88800_A1_REV_ID J2C_A1_REV_ID -#define BCM88821_DEVICE_ID 0x8821 -#define BCM88826_DEVICE_ID 0x8826 +#define BCM88801_DEVICE_ID 0x8801 #define BCM88802_DEVICE_ID 0x8802 #define BCM88803_DEVICE_ID 0x8803 #define BCM88804_DEVICE_ID 0x8804 #define BCM88805_DEVICE_ID 0x8805 #define BCM88806_DEVICE_ID 0x8806 +#define BCM88807_DEVICE_ID 0x8807 +#define BCM88808_DEVICE_ID 0x8808 +#define BCM88809_DEVICE_ID 0x8809 +#define BCM8880A_DEVICE_ID 0x880A +#define BCM8880B_DEVICE_ID 0x880B +#define BCM8880C_DEVICE_ID 0x880C +#define BCM8880D_DEVICE_ID 0x880D +#define BCM8880E_DEVICE_ID 0x880E +#define BCM8880F_DEVICE_ID 0x880F +#define BCM88821_DEVICE_ID 0x8821 #define BCM88822_DEVICE_ID 0x8822 #define BCM88823_DEVICE_ID 0x8823 #define BCM88824_DEVICE_ID 0x8824 #define BCM88825_DEVICE_ID 0x8825 +#define BCM88826_DEVICE_ID 0x8826 +#define BCM88827_DEVICE_ID 0x8827 +#define BCM88828_DEVICE_ID 0x8828 +#define BCM88829_DEVICE_ID 0x8829 +#define BCM8882A_DEVICE_ID 0x882A +#define BCM8882B_DEVICE_ID 0x882B +#define BCM8882C_DEVICE_ID 0x882C +#define BCM8882D_DEVICE_ID 0x882D +#define BCM8882E_DEVICE_ID 0x882E +#define BCM8882F_DEVICE_ID 0x882F #define J2P_DEVICE_ID 0x8850 #define J2P_A0_REV_ID DNXC_A0_REV_ID #define BCM88850_DEVICE_ID J2P_DEVICE_ID #define BCM88850_A0_REV_ID J2P_A0_REV_ID +#define BCM88851_DEVICE_ID 0x8851 +#define BCM88852_DEVICE_ID 0x8852 +#define BCM88853_DEVICE_ID 0x8853 +#define BCM88854_DEVICE_ID 0x8854 +#define BCM88855_DEVICE_ID 0x8855 +#define BCM88856_DEVICE_ID 0x8856 +#define BCM88857_DEVICE_ID 0x8857 +#define BCM88858_DEVICE_ID 0x8858 +#define BCM88859_DEVICE_ID 0x8859 +#define BCM8885A_DEVICE_ID 0x885A +#define BCM8885B_DEVICE_ID 0x885B +#define BCM8885C_DEVICE_ID 0x885C +#define BCM8885D_DEVICE_ID 0x885D +#define BCM8885E_DEVICE_ID 0x885E +#define BCM8885F_DEVICE_ID 0x885F + #define Q2A_DEVICE_ID 0x8480 #define Q2A_A0_REV_ID DNXC_A0_REV_ID @@ -1808,6 +1857,24 @@ #define BCM8848E_DEVICE_ID 0x848E #define BCM8848F_DEVICE_ID 0x848F +#define Q2U_DEVICE_ID 0x8280 +#define BCM88280_DEVICE_ID Q2U_DEVICE_ID +#define BCM88281_DEVICE_ID 0x8281 +#define BCM88282_DEVICE_ID 0x8282 +#define BCM88283_DEVICE_ID 0x8283 +#define BCM88284_DEVICE_ID 0x8284 +#define BCM88285_DEVICE_ID 0x8285 +#define BCM88286_DEVICE_ID 0x8286 +#define BCM88287_DEVICE_ID 0x8287 +#define BCM88288_DEVICE_ID 0x8288 +#define BCM88289_DEVICE_ID 0x8289 +#define BCM8828A_DEVICE_ID 0x828A +#define BCM8828B_DEVICE_ID 0x828B +#define BCM8828C_DEVICE_ID 0x828C +#define BCM8828D_DEVICE_ID 0x828D +#define BCM8828E_DEVICE_ID 0x828E +#define BCM8828F_DEVICE_ID 0x828F + #define QAX_DEVICE_ID 0x8470 #define QAX_A0_REV_ID 0x0001 #define QAX_B0_REV_ID 0x0011 @@ -1833,9 +1900,11 @@ #define BCM88270_DEVICE_ID QUX_DEVICE_ID #define BCM88270_A0_REV_ID QUX_A0_REV_ID #define BCM88270_A1_REV_ID QUX_A1_REV_ID +#define BCM88271_DEVICE_ID 0x8271 #define BCM88272_DEVICE_ID 0x8272 #define BCM88273_DEVICE_ID 0x8273 #define BCM88274_DEVICE_ID 0x8274 +#define BCM88276_DEVICE_ID 0x8276 #define BCM88278_DEVICE_ID 0x8278 #define BCM88279_DEVICE_ID 0x8279 @@ -1844,16 +1913,6 @@ #define BCM8206_DEVICE_ID FLAIR_DEVICE_ID #define BCM8206_A0_REV_ID FLAIR_A0_REV_ID -#define ARDON_DEVICE_ID 0x8202 -#define ARDON_A0_REV_ID 0x0000 -#define BCM88202_DEVICE_ID ARDON_DEVICE_ID -#define BCM88202_A0_REV_ID ARDON_A0_REV_ID -#define ARDON_A1_REV_ID 0x0001 -#define BCM88202_A1_REV_ID ARDON_A1_REV_ID -#define ARDON_A2_REV_ID 0x0002 -#define BCM88202_A2_REV_ID ARDON_A2_REV_ID -#define BCM2801PM_DEVICE_ID 0x2801 -#define BCM2801PM_A0_REV_ID 0x0000 #define BCM88360_DEVICE_ID 0x8360 #define BCM88360_A0_REV_ID ARADPLUS_A0_REV_ID #define BCM88361_DEVICE_ID 0x8361 @@ -1901,16 +1960,6 @@ #define BCM88952_A0_REV_ID 0x0001 #define BCM88952_A1_REV_ID 0x0002 -#define BCM88752_DEVICE_ID 0x8752 -#define BCM88752_A0_REV_ID 0x0000 -#define BCM88752_B0_REV_ID 0x0011 - - -#define BCM83207_DEVICE_ID 0x3207 -#define BCM83208_DEVICE_ID 0x3208 -#define BCM83207_A0_REV_ID 0x0001 -#define BCM83208_A0_REV_ID 1 - #define PCP_PCI_VENDOR_ID 0x1172 #define PCP_PCI_DEVICE_ID 0x4 @@ -1930,7 +1979,33 @@ #define BCM56883_DEVICE_ID 0xb883 #define BCM56883_A0_REV_ID 0x0001 #define BCM56883_B0_REV_ID 0x0011 - +#define BCM56889_DEVICE_ID 0xb889 +#define BCM56889_A0_REV_ID 0x0001 +#define BCM56889_B0_REV_ID 0x0011 + +#define BCM56780_DEVICE_ID 0xb780 +#define BCM56780_A0_REV_ID 0x0001 +#define BCM56782_DEVICE_ID 0xb782 +#define BCM56782_A0_REV_ID 0x0001 +#define BCM56784_DEVICE_ID 0xb784 +#define BCM56784_A0_REV_ID 0x0001 +#define BCM56786_DEVICE_ID 0xb786 +#define BCM56786_A0_REV_ID 0x0001 +#define BCM56788_DEVICE_ID 0xb788 +#define BCM56788_A0_REV_ID 0x0001 +#define BCM56789_DEVICE_ID 0xb789 +#define BCM56789_A0_REV_ID 0x0001 + +#define BCM56990_DEVICE_ID 0xb990 +#define BCM56990_A0_REV_ID 0x0001 +#define BCM56990_B0_REV_ID 0x0011 +#define BCM56992_DEVICE_ID 0xb992 +#define BCM56992_B0_REV_ID 0x0011 + +#define BCM56996_DEVICE_ID 0xb996 +#define BCM56996_A0_REV_ID 0x0001 +#define BCM56997_DEVICE_ID 0xb997 +#define BCM56997_A0_REV_ID 0x0001 #endif #endif diff --git a/platform/broadcom/saibcm-modules/make/Make.config b/platform/broadcom/saibcm-modules/make/Make.config index 409a6a49b3f..b086aa3aa79 100644 --- a/platform/broadcom/saibcm-modules/make/Make.config +++ b/platform/broadcom/saibcm-modules/make/Make.config @@ -1,5 +1,10 @@ # -# Copyright 2017 Broadcom +# Copyright 2007-2020 Broadcom Inc. All rights reserved. +# +# Permission is granted to use, copy, modify and/or distribute this +# software under either one of the licenses below. +# +# License Option 1: GPL # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License, version 2, as @@ -12,6 +17,12 @@ # # You should have received a copy of the GNU General Public License # version 2 (GPLv2) along with this source code. +# +# +# License Option 2: Broadcom Open Network Switch APIs (OpenNSA) license +# +# This software is governed by the Broadcom Open Network Switch APIs license: +# https://www.broadcom.com/products/ethernet-connectivity/software/opennsa # # $Id: Make.config,v 1.3 Broadcom SDK $ # $Copyright: (c) 2005 Broadcom Corp. diff --git a/platform/broadcom/saibcm-modules/make/Make.depend b/platform/broadcom/saibcm-modules/make/Make.depend index de709938766..802f5f4483c 100644 --- a/platform/broadcom/saibcm-modules/make/Make.depend +++ b/platform/broadcom/saibcm-modules/make/Make.depend @@ -1,5 +1,10 @@ # -# Copyright 2017 Broadcom +# Copyright 2007-2020 Broadcom Inc. All rights reserved. +# +# Permission is granted to use, copy, modify and/or distribute this +# software under either one of the licenses below. +# +# License Option 1: GPL # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License, version 2, as @@ -12,6 +17,12 @@ # # You should have received a copy of the GNU General Public License # version 2 (GPLv2) along with this source code. +# +# +# License Option 2: Broadcom Open Network Switch APIs (OpenNSA) license +# +# This software is governed by the Broadcom Open Network Switch APIs license: +# https://www.broadcom.com/products/ethernet-connectivity/software/opennsa # # $Id: Make.depend,v 1.14 Broadcom SDK $ # $Copyright: (c) 2005 Broadcom Corp. diff --git a/platform/broadcom/saibcm-modules/make/Make.kernlib b/platform/broadcom/saibcm-modules/make/Make.kernlib index 6ec8a1c8df7..94801acd4a6 100644 --- a/platform/broadcom/saibcm-modules/make/Make.kernlib +++ b/platform/broadcom/saibcm-modules/make/Make.kernlib @@ -1,5 +1,10 @@ # -# Copyright 2017 Broadcom +# Copyright 2007-2020 Broadcom Inc. All rights reserved. +# +# Permission is granted to use, copy, modify and/or distribute this +# software under either one of the licenses below. +# +# License Option 1: GPL # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License, version 2, as @@ -12,6 +17,12 @@ # # You should have received a copy of the GNU General Public License # version 2 (GPLv2) along with this source code. +# +# +# License Option 2: Broadcom Open Network Switch APIs (OpenNSA) license +# +# This software is governed by the Broadcom Open Network Switch APIs license: +# https://www.broadcom.com/products/ethernet-connectivity/software/opennsa # # $Id: Make.kernlib,v 1.7 Broadcom SDK $ # $Copyright: (c) 2005 Broadcom Corp. diff --git a/platform/broadcom/saibcm-modules/make/Make.lib b/platform/broadcom/saibcm-modules/make/Make.lib index d67325c5dd2..ac81cc134f6 100644 --- a/platform/broadcom/saibcm-modules/make/Make.lib +++ b/platform/broadcom/saibcm-modules/make/Make.lib @@ -1,5 +1,10 @@ # -# Copyright 2017 Broadcom +# Copyright 2007-2020 Broadcom Inc. All rights reserved. +# +# Permission is granted to use, copy, modify and/or distribute this +# software under either one of the licenses below. +# +# License Option 1: GPL # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License, version 2, as @@ -12,6 +17,12 @@ # # You should have received a copy of the GNU General Public License # version 2 (GPLv2) along with this source code. +# +# +# License Option 2: Broadcom Open Network Switch APIs (OpenNSA) license +# +# This software is governed by the Broadcom Open Network Switch APIs license: +# https://www.broadcom.com/products/ethernet-connectivity/software/opennsa # # $Id: Make.lib,v 1.14 Broadcom SDK $ # $Copyright: (c) 2005 Broadcom Corp. @@ -62,7 +73,7 @@ endif ifeq ($(LINUX_MAKE_SHARED_LIB),1) $(CC) -shared -Wl,-soname,${lib}.${LIBSUFFIX}${EXTRA_LIB_LDFLAGS} -o ${targetlib} ${BOBJS} -lc else - ${Q}cd $(dir $(word 1,${BOBJS}));$(AR) ${ARFLAGS} $@ $(sort $(notdir ${BOBJS})) + $(AR) ${ARFLAGS} $@ $(sort ${BOBJS}) endif endif # !Borland diff --git a/platform/broadcom/saibcm-modules/make/Make.linux b/platform/broadcom/saibcm-modules/make/Make.linux index 81e88daf16b..ad18872a34e 100644 --- a/platform/broadcom/saibcm-modules/make/Make.linux +++ b/platform/broadcom/saibcm-modules/make/Make.linux @@ -1,5 +1,10 @@ # -# Copyright 2017 Broadcom +# Copyright 2007-2020 Broadcom Inc. All rights reserved. +# +# Permission is granted to use, copy, modify and/or distribute this +# software under either one of the licenses below. +# +# License Option 1: GPL # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License, version 2, as @@ -12,6 +17,12 @@ # # You should have received a copy of the GNU General Public License # version 2 (GPLv2) along with this source code. +# +# +# License Option 2: Broadcom Open Network Switch APIs (OpenNSA) license +# +# This software is governed by the Broadcom Open Network Switch APIs license: +# https://www.broadcom.com/products/ethernet-connectivity/software/opennsa # # # $Id: Make.linux,v 1.18 Broadcom SDK $ @@ -85,7 +96,7 @@ endif build: $(MAKE) $(CMD) -DELIVER clean C_COMPILER CXX_COMPILER variable mod bcm user issu: +DELIVER clean C_COMPILER CXX_COMPILER variable mod bcm user issu libopennsa: $(MAKE) $(CMD) $@ clean_d: clean diff --git a/platform/broadcom/saibcm-modules/make/Make.subdirs b/platform/broadcom/saibcm-modules/make/Make.subdirs index 1033e296c0a..374d817d212 100644 --- a/platform/broadcom/saibcm-modules/make/Make.subdirs +++ b/platform/broadcom/saibcm-modules/make/Make.subdirs @@ -1,5 +1,10 @@ # -# Copyright 2017 Broadcom +# Copyright 2007-2020 Broadcom Inc. All rights reserved. +# +# Permission is granted to use, copy, modify and/or distribute this +# software under either one of the licenses below. +# +# License Option 1: GPL # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License, version 2, as @@ -12,6 +17,12 @@ # # You should have received a copy of the GNU General Public License # version 2 (GPLv2) along with this source code. +# +# +# License Option 2: Broadcom Open Network Switch APIs (OpenNSA) license +# +# This software is governed by the Broadcom Open Network Switch APIs license: +# https://www.broadcom.com/products/ethernet-connectivity/software/opennsa # # $Id: Make.subdirs,v 1.8 Broadcom SDK $ # $Copyright: (c) 2005 Broadcom Corp. diff --git a/platform/broadcom/saibcm-modules/make/Make.tools b/platform/broadcom/saibcm-modules/make/Make.tools index 8ed77727fef..0d55eb2e653 100644 --- a/platform/broadcom/saibcm-modules/make/Make.tools +++ b/platform/broadcom/saibcm-modules/make/Make.tools @@ -1,5 +1,10 @@ # -# Copyright 2017 Broadcom +# Copyright 2007-2020 Broadcom Inc. All rights reserved. +# +# Permission is granted to use, copy, modify and/or distribute this +# software under either one of the licenses below. +# +# License Option 1: GPL # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License, version 2, as @@ -12,6 +17,12 @@ # # You should have received a copy of the GNU General Public License # version 2 (GPLv2) along with this source code. +# +# +# License Option 2: Broadcom Open Network Switch APIs (OpenNSA) license +# +# This software is governed by the Broadcom Open Network Switch APIs license: +# https://www.broadcom.com/products/ethernet-connectivity/software/opennsa # # $Id: Make.tools,v 1.2 Broadcom SDK $ # $Copyright: (c) 2005 Broadcom Corp. diff --git a/platform/broadcom/saibcm-modules/make/Makefile.linux-gts b/platform/broadcom/saibcm-modules/make/Makefile.linux-gts index ddc94afa13f..726dfdf505b 100644 --- a/platform/broadcom/saibcm-modules/make/Makefile.linux-gts +++ b/platform/broadcom/saibcm-modules/make/Makefile.linux-gts @@ -1,5 +1,10 @@ # -# Copyright 2017 Broadcom +# Copyright 2007-2020 Broadcom Inc. All rights reserved. +# +# Permission is granted to use, copy, modify and/or distribute this +# software under either one of the licenses below. +# +# License Option 1: GPL # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License, version 2, as @@ -12,6 +17,12 @@ # # You should have received a copy of the GNU General Public License # version 2 (GPLv2) along with this source code. +# +# +# License Option 2: Broadcom Open Network Switch APIs (OpenNSA) license +# +# This software is governed by the Broadcom Open Network Switch APIs license: +# https://www.broadcom.com/products/ethernet-connectivity/software/opennsa # # $Id: Makefile.linux-xlr-4_19,v 0.1 Broadcom SDK $ # $Copyright: (c) 2015 Broadcom Corp. @@ -37,6 +48,8 @@ # some basic path variables for tools and kernel source, etc # export XLR_TOOLS_BASE = /projects/ntsw-tools/linux/xlr-419 TOOLCHAIN_DIR = $(XLR_TOOLS_BASE)/buildroot/host/usr +# Target machine for EDK-Host defconfig +TARGET_MACHINE ?= x86_64 KERNDIR = $(XLR_TOOLS_BASE)/kernel/linux # set up cross compile prefix, tools dir variables. # @@ -125,12 +138,21 @@ OPENSRC_BUILD ?= fed21-x86_64 # Hardware interface (see $SDKLT/bcma/sys/probe directory) SYSTEM_INTERFACE ?= ngbde +# Support BCMSIM in the same build +ifeq (1,$(BCM_SIM_PATH_SUPPORT)) +EXTRA_SYSTEM_INTERFACES = plisim +endif + # Turn on direct register access if running on real hardware. ifeq (ngbde,$(SYSTEM_INTERFACE)) +# Except if using multiple probe interfaces +ifeq (,$(EXTRA_SYSTEM_INTERFACES)) LTSW_ADD_CPPFLAGS += -DBCMDRD_CONFIG_MEMMAP_DIRECT=1 endif +endif export SYSTEM_INTERFACE +export EXTRA_SYSTEM_INTERFACES endif ifneq ($(targetplat),user) diff --git a/platform/broadcom/saibcm-modules/make/Makefile.linux-iproc b/platform/broadcom/saibcm-modules/make/Makefile.linux-iproc index 7d8adb98de3..fa4911185aa 100644 --- a/platform/broadcom/saibcm-modules/make/Makefile.linux-iproc +++ b/platform/broadcom/saibcm-modules/make/Makefile.linux-iproc @@ -1,5 +1,10 @@ # -# Copyright 2017 Broadcom +# Copyright 2007-2020 Broadcom Inc. All rights reserved. +# +# Permission is granted to use, copy, modify and/or distribute this +# software under either one of the licenses below. +# +# License Option 1: GPL # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License, version 2, as @@ -12,6 +17,12 @@ # # You should have received a copy of the GNU General Public License # version 2 (GPLv2) along with this source code. +# +# +# License Option 2: Broadcom Open Network Switch APIs (OpenNSA) license +# +# This software is governed by the Broadcom Open Network Switch APIs license: +# https://www.broadcom.com/products/ethernet-connectivity/software/opennsa # # $Id: Makefile.linux-iproc Exp $ # $Copyright: (c) 2007 Broadcom Corp. diff --git a/platform/broadcom/saibcm-modules/make/Makefile.linux-iproc-3_14 b/platform/broadcom/saibcm-modules/make/Makefile.linux-iproc-3_14 index 723fea6c73c..8d9f66aa50a 100644 --- a/platform/broadcom/saibcm-modules/make/Makefile.linux-iproc-3_14 +++ b/platform/broadcom/saibcm-modules/make/Makefile.linux-iproc-3_14 @@ -1,5 +1,10 @@ # -# Copyright 2017 Broadcom +# Copyright 2007-2020 Broadcom Inc. All rights reserved. +# +# Permission is granted to use, copy, modify and/or distribute this +# software under either one of the licenses below. +# +# License Option 1: GPL # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License, version 2, as @@ -12,6 +17,12 @@ # # You should have received a copy of the GNU General Public License # version 2 (GPLv2) along with this source code. +# +# +# License Option 2: Broadcom Open Network Switch APIs (OpenNSA) license +# +# This software is governed by the Broadcom Open Network Switch APIs license: +# https://www.broadcom.com/products/ethernet-connectivity/software/opennsa # # $Id: Makefile.linux-iproc-3_6,v 1.1 Broadcom SDK $ # $Copyright: (c) 2007 Broadcom Corp. diff --git a/platform/broadcom/saibcm-modules/make/Makefile.linux-iproc-4_4 b/platform/broadcom/saibcm-modules/make/Makefile.linux-iproc-4_4 index df31f84e9d8..bcef1ff69dd 100644 --- a/platform/broadcom/saibcm-modules/make/Makefile.linux-iproc-4_4 +++ b/platform/broadcom/saibcm-modules/make/Makefile.linux-iproc-4_4 @@ -1,5 +1,10 @@ # -# Copyright 2017 Broadcom +# Copyright 2007-2020 Broadcom Inc. All rights reserved. +# +# Permission is granted to use, copy, modify and/or distribute this +# software under either one of the licenses below. +# +# License Option 1: GPL # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License, version 2, as @@ -12,6 +17,12 @@ # # You should have received a copy of the GNU General Public License # version 2 (GPLv2) along with this source code. +# +# +# License Option 2: Broadcom Open Network Switch APIs (OpenNSA) license +# +# This software is governed by the Broadcom Open Network Switch APIs license: +# https://www.broadcom.com/products/ethernet-connectivity/software/opennsa # # $Id: Makefile.linux-iproc Exp $ # $Copyright: (c) 2007 Broadcom Corp. diff --git a/platform/broadcom/saibcm-modules/make/Makefile.linux-iproc_64 b/platform/broadcom/saibcm-modules/make/Makefile.linux-iproc_64 index dbccd7e2573..247da738637 100644 --- a/platform/broadcom/saibcm-modules/make/Makefile.linux-iproc_64 +++ b/platform/broadcom/saibcm-modules/make/Makefile.linux-iproc_64 @@ -1,5 +1,10 @@ # -# Copyright 2017 Broadcom +# Copyright 2007-2020 Broadcom Inc. All rights reserved. +# +# Permission is granted to use, copy, modify and/or distribute this +# software under either one of the licenses below. +# +# License Option 1: GPL # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License, version 2, as @@ -12,6 +17,12 @@ # # You should have received a copy of the GNU General Public License # version 2 (GPLv2) along with this source code. +# +# +# License Option 2: Broadcom Open Network Switch APIs (OpenNSA) license +# +# This software is governed by the Broadcom Open Network Switch APIs license: +# https://www.broadcom.com/products/ethernet-connectivity/software/opennsa # # $Id: Makefile.linux-iproc Exp $ # $Copyright: (c) 2007 Broadcom Corp. diff --git a/platform/broadcom/saibcm-modules/make/Makefile.linux-kernel b/platform/broadcom/saibcm-modules/make/Makefile.linux-kernel index 7cbf8451f91..ccb0c30d2ac 100644 --- a/platform/broadcom/saibcm-modules/make/Makefile.linux-kernel +++ b/platform/broadcom/saibcm-modules/make/Makefile.linux-kernel @@ -1,5 +1,10 @@ # -# Copyright 2017 Broadcom +# Copyright 2007-2020 Broadcom Inc. All rights reserved. +# +# Permission is granted to use, copy, modify and/or distribute this +# software under either one of the licenses below. +# +# License Option 1: GPL # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License, version 2, as @@ -12,6 +17,12 @@ # # You should have received a copy of the GNU General Public License # version 2 (GPLv2) along with this source code. +# +# +# License Option 2: Broadcom Open Network Switch APIs (OpenNSA) license +# +# This software is governed by the Broadcom Open Network Switch APIs license: +# https://www.broadcom.com/products/ethernet-connectivity/software/opennsa # # $Id: Makefile.linux-kernel,v 1.27 Broadcom SDK $ # $Copyright: (c) 2005 Broadcom Corp. diff --git a/platform/broadcom/saibcm-modules/make/Makefile.linux-kernel-2_6 b/platform/broadcom/saibcm-modules/make/Makefile.linux-kernel-2_6 index 559f2ae5e5e..08461e4c4b7 100644 --- a/platform/broadcom/saibcm-modules/make/Makefile.linux-kernel-2_6 +++ b/platform/broadcom/saibcm-modules/make/Makefile.linux-kernel-2_6 @@ -1,5 +1,10 @@ # -# Copyright 2017 Broadcom +# Copyright 2007-2020 Broadcom Inc. All rights reserved. +# +# Permission is granted to use, copy, modify and/or distribute this +# software under either one of the licenses below. +# +# License Option 1: GPL # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License, version 2, as @@ -12,6 +17,12 @@ # # You should have received a copy of the GNU General Public License # version 2 (GPLv2) along with this source code. +# +# +# License Option 2: Broadcom Open Network Switch APIs (OpenNSA) license +# +# This software is governed by the Broadcom Open Network Switch APIs license: +# https://www.broadcom.com/products/ethernet-connectivity/software/opennsa # # $Id: Makefile.linux-kernel-2_6,v 1.40 Broadcom SDK $ # $Copyright: (c) 2005 Broadcom Corp. diff --git a/platform/broadcom/saibcm-modules/make/Makefile.linux-kernel-3_6 b/platform/broadcom/saibcm-modules/make/Makefile.linux-kernel-3_6 index 0d54c4474fc..528522ec4bd 100644 --- a/platform/broadcom/saibcm-modules/make/Makefile.linux-kernel-3_6 +++ b/platform/broadcom/saibcm-modules/make/Makefile.linux-kernel-3_6 @@ -1,5 +1,10 @@ # -# Copyright 2017 Broadcom +# Copyright 2007-2020 Broadcom Inc. All rights reserved. +# +# Permission is granted to use, copy, modify and/or distribute this +# software under either one of the licenses below. +# +# License Option 1: GPL # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License, version 2, as @@ -12,6 +17,12 @@ # # You should have received a copy of the GNU General Public License # version 2 (GPLv2) along with this source code. +# +# +# License Option 2: Broadcom Open Network Switch APIs (OpenNSA) license +# +# This software is governed by the Broadcom Open Network Switch APIs license: +# https://www.broadcom.com/products/ethernet-connectivity/software/opennsa # # $Id: Makefile.linux-kernel-3_6,v 1.2 Broadcom SDK $ # $Copyright: (c) 2005 Broadcom Corp. diff --git a/platform/broadcom/saibcm-modules/make/Makefile.linux-kernel-4_4 b/platform/broadcom/saibcm-modules/make/Makefile.linux-kernel-4_4 index 0e8e22e1b32..c02fc0edd89 100644 --- a/platform/broadcom/saibcm-modules/make/Makefile.linux-kernel-4_4 +++ b/platform/broadcom/saibcm-modules/make/Makefile.linux-kernel-4_4 @@ -1,5 +1,10 @@ # -# Copyright 2017 Broadcom +# Copyright 2007-2020 Broadcom Inc. All rights reserved. +# +# Permission is granted to use, copy, modify and/or distribute this +# software under either one of the licenses below. +# +# License Option 1: GPL # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License, version 2, as @@ -12,6 +17,12 @@ # # You should have received a copy of the GNU General Public License # version 2 (GPLv2) along with this source code. +# +# +# License Option 2: Broadcom Open Network Switch APIs (OpenNSA) license +# +# This software is governed by the Broadcom Open Network Switch APIs license: +# https://www.broadcom.com/products/ethernet-connectivity/software/opennsa # # $Id: Makefile.linux-kernel-2_6,v 1.40 Broadcom SDK $ # $Copyright: (c) 2005 Broadcom Corp. diff --git a/platform/broadcom/saibcm-modules/make/Makefile.linux-kmodule b/platform/broadcom/saibcm-modules/make/Makefile.linux-kmodule index 540c497ea25..46caf00f20b 100644 --- a/platform/broadcom/saibcm-modules/make/Makefile.linux-kmodule +++ b/platform/broadcom/saibcm-modules/make/Makefile.linux-kmodule @@ -1,5 +1,10 @@ # -# Copyright 2017 Broadcom +# Copyright 2007-2020 Broadcom Inc. All rights reserved. +# +# Permission is granted to use, copy, modify and/or distribute this +# software under either one of the licenses below. +# +# License Option 1: GPL # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License, version 2, as @@ -12,6 +17,12 @@ # # You should have received a copy of the GNU General Public License # version 2 (GPLv2) along with this source code. +# +# +# License Option 2: Broadcom Open Network Switch APIs (OpenNSA) license +# +# This software is governed by the Broadcom Open Network Switch APIs license: +# https://www.broadcom.com/products/ethernet-connectivity/software/opennsa # # $Id: Makefile.linux-kmodule-3_6,v 1.2 Broadcom SDK $ # $Copyright: (c) 2006 Broadcom Corp. @@ -61,6 +72,13 @@ KERNBLDDIR ?= $(KERNDIR) # kernel symbols. override EXTRA_CFLAGS = -I${SDK}/include -I${SDK}/systems/linux/kernel/modules/include -I${SDK}/systems/bde/linux/include +# +# If, for any reason, the definition of LD was erased, then +# set it, again. +# +ifeq ($(LD),) +LD = $(CROSS_COMPILE)ld +endif # The precopiled object needs a dummy command file to avoid warnings # from the Kbuild scripts (modpost stage). diff --git a/platform/broadcom/saibcm-modules/make/Makefile.linux-slk b/platform/broadcom/saibcm-modules/make/Makefile.linux-slk index 00131c2f2af..656835019a0 100644 --- a/platform/broadcom/saibcm-modules/make/Makefile.linux-slk +++ b/platform/broadcom/saibcm-modules/make/Makefile.linux-slk @@ -1,5 +1,10 @@ # -# Copyright 2017 Broadcom +# Copyright 2007-2020 Broadcom Inc. All rights reserved. +# +# Permission is granted to use, copy, modify and/or distribute this +# software under either one of the licenses below. +# +# License Option 1: GPL # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License, version 2, as @@ -12,6 +17,12 @@ # # You should have received a copy of the GNU General Public License # version 2 (GPLv2) along with this source code. +# +# +# License Option 2: Broadcom Open Network Switch APIs (OpenNSA) license +# +# This software is governed by the Broadcom Open Network Switch APIs license: +# https://www.broadcom.com/products/ethernet-connectivity/software/opennsa # # $Id: Makefile.linux-slk-3_14,v 1.2 Broadcom SDK $ # $Copyright: (c) 2013 Broadcom Corp. @@ -27,11 +38,15 @@ endif ifeq (BE,$(ENDIAN_MODE)) TOOLCHAIN_BASE_DIR ?= /projects/ntsw-tools/toolchains/slk/linaro-be TARGET_ARCHITECTURE:=aarch64_be-linux-gnu +# Target machine for EDK-Host defconfig +TARGET_MACHINE ?= slk_be KERNDIR ?= /projects/ntsw-tools/linux/iproc_ldks/slk-be/poky/brcm-released-source/git else TOOLCHAIN_BASE_DIR ?= /projects/ntsw-tools/toolchains/slk/linaro-le # Compiler for target architecture TARGET_ARCHITECTURE:= aarch64-linux-gnu +# Target machine for EDK-Host defconfig +TARGET_MACHINE ?= slk_le # Kernel directory KERNDIR ?= /projects/ntsw-tools/linux/iproc_ldks/slk/poky/brcm-released-source/git endif diff --git a/platform/broadcom/saibcm-modules/make/Makefile.linux-x86-common-2_6 b/platform/broadcom/saibcm-modules/make/Makefile.linux-x86-common-2_6 index 25e953136bc..dbd51ee1f62 100644 --- a/platform/broadcom/saibcm-modules/make/Makefile.linux-x86-common-2_6 +++ b/platform/broadcom/saibcm-modules/make/Makefile.linux-x86-common-2_6 @@ -1,5 +1,10 @@ # -# Copyright 2017 Broadcom +# Copyright 2007-2020 Broadcom Inc. All rights reserved. +# +# Permission is granted to use, copy, modify and/or distribute this +# software under either one of the licenses below. +# +# License Option 1: GPL # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License, version 2, as @@ -12,6 +17,12 @@ # # You should have received a copy of the GNU General Public License # version 2 (GPLv2) along with this source code. +# +# +# License Option 2: Broadcom Open Network Switch APIs (OpenNSA) license +# +# This software is governed by the Broadcom Open Network Switch APIs license: +# https://www.broadcom.com/products/ethernet-connectivity/software/opennsa # # $Id: Makefile.linux-x86-common-2_6,v 1.13 Broadcom SDK $ # $Copyright: (c) 2005 Broadcom Corp. diff --git a/platform/broadcom/saibcm-modules/make/Makefile.linux-x86-generic-common-2_6 b/platform/broadcom/saibcm-modules/make/Makefile.linux-x86-generic-common-2_6 index b443a3d4733..4b02aa53cda 100644 --- a/platform/broadcom/saibcm-modules/make/Makefile.linux-x86-generic-common-2_6 +++ b/platform/broadcom/saibcm-modules/make/Makefile.linux-x86-generic-common-2_6 @@ -1,5 +1,10 @@ # -# Copyright 2017 Broadcom +# Copyright 2007-2020 Broadcom Inc. All rights reserved. +# +# Permission is granted to use, copy, modify and/or distribute this +# software under either one of the licenses below. +# +# License Option 1: GPL # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License, version 2, as @@ -12,6 +17,12 @@ # # You should have received a copy of the GNU General Public License # version 2 (GPLv2) along with this source code. +# +# +# License Option 2: Broadcom Open Network Switch APIs (OpenNSA) license +# +# This software is governed by the Broadcom Open Network Switch APIs license: +# https://www.broadcom.com/products/ethernet-connectivity/software/opennsa # # $Id: Makefile.linux-x86-generic-common-2_6,v 1.2 Broadcom SDK $ # $Copyright: (c) 2008 Broadcom Corp. @@ -48,5 +59,4 @@ AUTOCONF = $(KERNDIR)/include/linux/autoconf.h endif # gcc system include path -# SAI_FIXUP /* SDK-218654 */ SYSINC = $(shell $(CC) -print-search-dirs | grep install | cut -c 10-)include diff --git a/platform/broadcom/saibcm-modules/make/Makefile.linux-x86-smp_generic_64-2_6 b/platform/broadcom/saibcm-modules/make/Makefile.linux-x86-smp_generic_64-2_6 index 8a97f395430..9df0bee5a77 100644 --- a/platform/broadcom/saibcm-modules/make/Makefile.linux-x86-smp_generic_64-2_6 +++ b/platform/broadcom/saibcm-modules/make/Makefile.linux-x86-smp_generic_64-2_6 @@ -1,5 +1,10 @@ # -# Copyright 2017 Broadcom +# Copyright 2007-2020 Broadcom Inc. All rights reserved. +# +# Permission is granted to use, copy, modify and/or distribute this +# software under either one of the licenses below. +# +# License Option 1: GPL # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License, version 2, as @@ -12,6 +17,12 @@ # # You should have received a copy of the GNU General Public License # version 2 (GPLv2) along with this source code. +# +# +# License Option 2: Broadcom Open Network Switch APIs (OpenNSA) license +# +# This software is governed by the Broadcom Open Network Switch APIs license: +# https://www.broadcom.com/products/ethernet-connectivity/software/opennsa # # $Id: Makefile.linux-x86-smp_generic_64-2_6,v 1.5 Broadcom SDK $ # $Copyright: (c) 2008 Broadcom Corp. @@ -25,7 +36,7 @@ CFGFLAGS += -DSAL_SPL_LOCK_ON_IRQ include ${SDK}/make/Makefile.linux-x86-generic-common-2_6 ifeq (,$(KFLAGS)) -KFLAGS := -nostdinc -isystem $(SYSINC) -I$(KERNDIR)/include -I$(KERNDIR)/arch/x86/include -include $(AUTOCONF) -D__KERNEL__ -Wall -Wundef -Wstrict-prototypes -Wno-trigraphs -fno-strict-aliasing -fno-common -Werror-implicit-function-declaration -Wno-format-security -fno-delete-null-pointer-checks -Os -m64 -mtune=generic -mno-red-zone -mcmodel=kernel -funit-at-a-time -maccumulate-outgoing-args -DCONFIG_AS_CFI=1 -DCONFIG_AS_CFI_SIGNAL_FRAME=1 -pipe -Wno-sign-compare -fno-asynchronous-unwind-tables -mno-sse -mno-mmx -mno-sse2 -mno-3dnow -fno-stack-protector -fomit-frame-pointer -g -Wdeclaration-after-statement -Wno-pointer-sign +KFLAGS := -nostdinc -isystem $(SYSINC) -I$(KERNDIR)/include -I$(KERNDIR)/arch/x86/include -include $(AUTOCONF) -D__KERNEL__ -Wall -Wundef -Wstrict-prototypes -Wno-trigraphs -fno-strict-aliasing -fno-common -Werror-implicit-function-declaration -Wno-format-security -fno-delete-null-pointer-checks -Os -m64 -mtune=generic -mno-red-zone -fno-pie -mcmodel=kernel -funit-at-a-time -maccumulate-outgoing-args -DCONFIG_AS_CFI=1 -DCONFIG_AS_CFI_SIGNAL_FRAME=1 -pipe -Wno-sign-compare -fno-asynchronous-unwind-tables -mno-sse -mno-mmx -mno-sse2 -mno-3dnow -fno-stack-protector -fomit-frame-pointer -g -Wdeclaration-after-statement -Wno-pointer-sign endif ifeq ($(LINUX_MAKE_SHARED_LIB), 1) diff --git a/platform/broadcom/saibcm-modules/make/Makefile.linux-xlr b/platform/broadcom/saibcm-modules/make/Makefile.linux-xlr index ddc94afa13f..726dfdf505b 100644 --- a/platform/broadcom/saibcm-modules/make/Makefile.linux-xlr +++ b/platform/broadcom/saibcm-modules/make/Makefile.linux-xlr @@ -1,5 +1,10 @@ # -# Copyright 2017 Broadcom +# Copyright 2007-2020 Broadcom Inc. All rights reserved. +# +# Permission is granted to use, copy, modify and/or distribute this +# software under either one of the licenses below. +# +# License Option 1: GPL # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License, version 2, as @@ -12,6 +17,12 @@ # # You should have received a copy of the GNU General Public License # version 2 (GPLv2) along with this source code. +# +# +# License Option 2: Broadcom Open Network Switch APIs (OpenNSA) license +# +# This software is governed by the Broadcom Open Network Switch APIs license: +# https://www.broadcom.com/products/ethernet-connectivity/software/opennsa # # $Id: Makefile.linux-xlr-4_19,v 0.1 Broadcom SDK $ # $Copyright: (c) 2015 Broadcom Corp. @@ -37,6 +48,8 @@ # some basic path variables for tools and kernel source, etc # export XLR_TOOLS_BASE = /projects/ntsw-tools/linux/xlr-419 TOOLCHAIN_DIR = $(XLR_TOOLS_BASE)/buildroot/host/usr +# Target machine for EDK-Host defconfig +TARGET_MACHINE ?= x86_64 KERNDIR = $(XLR_TOOLS_BASE)/kernel/linux # set up cross compile prefix, tools dir variables. # @@ -125,12 +138,21 @@ OPENSRC_BUILD ?= fed21-x86_64 # Hardware interface (see $SDKLT/bcma/sys/probe directory) SYSTEM_INTERFACE ?= ngbde +# Support BCMSIM in the same build +ifeq (1,$(BCM_SIM_PATH_SUPPORT)) +EXTRA_SYSTEM_INTERFACES = plisim +endif + # Turn on direct register access if running on real hardware. ifeq (ngbde,$(SYSTEM_INTERFACE)) +# Except if using multiple probe interfaces +ifeq (,$(EXTRA_SYSTEM_INTERFACES)) LTSW_ADD_CPPFLAGS += -DBCMDRD_CONFIG_MEMMAP_DIRECT=1 endif +endif export SYSTEM_INTERFACE +export EXTRA_SYSTEM_INTERFACES endif ifneq ($(targetplat),user) diff --git a/platform/broadcom/saibcm-modules/sdklt/LICENSES/gpl-2.0.txt b/platform/broadcom/saibcm-modules/sdklt/LICENSES/gpl-2.0.txt new file mode 100644 index 00000000000..d159169d105 --- /dev/null +++ b/platform/broadcom/saibcm-modules/sdklt/LICENSES/gpl-2.0.txt @@ -0,0 +1,339 @@ + GNU GENERAL PUBLIC LICENSE + Version 2, June 1991 + + Copyright (C) 1989, 1991 Free Software Foundation, Inc., + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + + Preamble + + The licenses for most software are designed to take away your +freedom to share and change it. By contrast, the GNU General Public +License is intended to guarantee your freedom to share and change free +software--to make sure the software is free for all its users. This +General Public License applies to most of the Free Software +Foundation's software and to any other program whose authors commit to +using it. (Some other Free Software Foundation software is covered by +the GNU Lesser General Public License instead.) You can apply it to +your programs, too. + + When we speak of free software, we are referring to freedom, not +price. Our General Public Licenses are designed to make sure that you +have the freedom to distribute copies of free software (and charge for +this service if you wish), that you receive source code or can get it +if you want it, that you can change the software or use pieces of it +in new free programs; and that you know you can do these things. + + To protect your rights, we need to make restrictions that forbid +anyone to deny you these rights or to ask you to surrender the rights. +These restrictions translate to certain responsibilities for you if you +distribute copies of the software, or if you modify it. + + For example, if you distribute copies of such a program, whether +gratis or for a fee, you must give the recipients all the rights that +you have. You must make sure that they, too, receive or can get the +source code. And you must show them these terms so they know their +rights. + + We protect your rights with two steps: (1) copyright the software, and +(2) offer you this license which gives you legal permission to copy, +distribute and/or modify the software. + + Also, for each author's protection and ours, we want to make certain +that everyone understands that there is no warranty for this free +software. If the software is modified by someone else and passed on, we +want its recipients to know that what they have is not the original, so +that any problems introduced by others will not reflect on the original +authors' reputations. + + Finally, any free program is threatened constantly by software +patents. We wish to avoid the danger that redistributors of a free +program will individually obtain patent licenses, in effect making the +program proprietary. To prevent this, we have made it clear that any +patent must be licensed for everyone's free use or not licensed at all. + + The precise terms and conditions for copying, distribution and +modification follow. + + GNU GENERAL PUBLIC LICENSE + TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION + + 0. This License applies to any program or other work which contains +a notice placed by the copyright holder saying it may be distributed +under the terms of this General Public License. The "Program", below, +refers to any such program or work, and a "work based on the Program" +means either the Program or any derivative work under copyright law: +that is to say, a work containing the Program or a portion of it, +either verbatim or with modifications and/or translated into another +language. (Hereinafter, translation is included without limitation in +the term "modification".) Each licensee is addressed as "you". + +Activities other than copying, distribution and modification are not +covered by this License; they are outside its scope. The act of +running the Program is not restricted, and the output from the Program +is covered only if its contents constitute a work based on the +Program (independent of having been made by running the Program). +Whether that is true depends on what the Program does. + + 1. You may copy and distribute verbatim copies of the Program's +source code as you receive it, in any medium, provided that you +conspicuously and appropriately publish on each copy an appropriate +copyright notice and disclaimer of warranty; keep intact all the +notices that refer to this License and to the absence of any warranty; +and give any other recipients of the Program a copy of this License +along with the Program. + +You may charge a fee for the physical act of transferring a copy, and +you may at your option offer warranty protection in exchange for a fee. + + 2. You may modify your copy or copies of the Program or any portion +of it, thus forming a work based on the Program, and copy and +distribute such modifications or work under the terms of Section 1 +above, provided that you also meet all of these conditions: + + a) You must cause the modified files to carry prominent notices + stating that you changed the files and the date of any change. + + b) You must cause any work that you distribute or publish, that in + whole or in part contains or is derived from the Program or any + part thereof, to be licensed as a whole at no charge to all third + parties under the terms of this License. + + c) If the modified program normally reads commands interactively + when run, you must cause it, when started running for such + interactive use in the most ordinary way, to print or display an + announcement including an appropriate copyright notice and a + notice that there is no warranty (or else, saying that you provide + a warranty) and that users may redistribute the program under + these conditions, and telling the user how to view a copy of this + License. (Exception: if the Program itself is interactive but + does not normally print such an announcement, your work based on + the Program is not required to print an announcement.) + +These requirements apply to the modified work as a whole. If +identifiable sections of that work are not derived from the Program, +and can be reasonably considered independent and separate works in +themselves, then this License, and its terms, do not apply to those +sections when you distribute them as separate works. But when you +distribute the same sections as part of a whole which is a work based +on the Program, the distribution of the whole must be on the terms of +this License, whose permissions for other licensees extend to the +entire whole, and thus to each and every part regardless of who wrote it. + +Thus, it is not the intent of this section to claim rights or contest +your rights to work written entirely by you; rather, the intent is to +exercise the right to control the distribution of derivative or +collective works based on the Program. + +In addition, mere aggregation of another work not based on the Program +with the Program (or with a work based on the Program) on a volume of +a storage or distribution medium does not bring the other work under +the scope of this License. + + 3. You may copy and distribute the Program (or a work based on it, +under Section 2) in object code or executable form under the terms of +Sections 1 and 2 above provided that you also do one of the following: + + a) Accompany it with the complete corresponding machine-readable + source code, which must be distributed under the terms of Sections + 1 and 2 above on a medium customarily used for software interchange; or, + + b) Accompany it with a written offer, valid for at least three + years, to give any third party, for a charge no more than your + cost of physically performing source distribution, a complete + machine-readable copy of the corresponding source code, to be + distributed under the terms of Sections 1 and 2 above on a medium + customarily used for software interchange; or, + + c) Accompany it with the information you received as to the offer + to distribute corresponding source code. (This alternative is + allowed only for noncommercial distribution and only if you + received the program in object code or executable form with such + an offer, in accord with Subsection b above.) + +The source code for a work means the preferred form of the work for +making modifications to it. For an executable work, complete source +code means all the source code for all modules it contains, plus any +associated interface definition files, plus the scripts used to +control compilation and installation of the executable. However, as a +special exception, the source code distributed need not include +anything that is normally distributed (in either source or binary +form) with the major components (compiler, kernel, and so on) of the +operating system on which the executable runs, unless that component +itself accompanies the executable. + +If distribution of executable or object code is made by offering +access to copy from a designated place, then offering equivalent +access to copy the source code from the same place counts as +distribution of the source code, even though third parties are not +compelled to copy the source along with the object code. + + 4. You may not copy, modify, sublicense, or distribute the Program +except as expressly provided under this License. Any attempt +otherwise to copy, modify, sublicense or distribute the Program is +void, and will automatically terminate your rights under this License. +However, parties who have received copies, or rights, from you under +this License will not have their licenses terminated so long as such +parties remain in full compliance. + + 5. You are not required to accept this License, since you have not +signed it. However, nothing else grants you permission to modify or +distribute the Program or its derivative works. These actions are +prohibited by law if you do not accept this License. Therefore, by +modifying or distributing the Program (or any work based on the +Program), you indicate your acceptance of this License to do so, and +all its terms and conditions for copying, distributing or modifying +the Program or works based on it. + + 6. Each time you redistribute the Program (or any work based on the +Program), the recipient automatically receives a license from the +original licensor to copy, distribute or modify the Program subject to +these terms and conditions. You may not impose any further +restrictions on the recipients' exercise of the rights granted herein. +You are not responsible for enforcing compliance by third parties to +this License. + + 7. If, as a consequence of a court judgment or allegation of patent +infringement or for any other reason (not limited to patent issues), +conditions are imposed on you (whether by court order, agreement or +otherwise) that contradict the conditions of this License, they do not +excuse you from the conditions of this License. If you cannot +distribute so as to satisfy simultaneously your obligations under this +License and any other pertinent obligations, then as a consequence you +may not distribute the Program at all. For example, if a patent +license would not permit royalty-free redistribution of the Program by +all those who receive copies directly or indirectly through you, then +the only way you could satisfy both it and this License would be to +refrain entirely from distribution of the Program. + +If any portion of this section is held invalid or unenforceable under +any particular circumstance, the balance of the section is intended to +apply and the section as a whole is intended to apply in other +circumstances. + +It is not the purpose of this section to induce you to infringe any +patents or other property right claims or to contest validity of any +such claims; this section has the sole purpose of protecting the +integrity of the free software distribution system, which is +implemented by public license practices. Many people have made +generous contributions to the wide range of software distributed +through that system in reliance on consistent application of that +system; it is up to the author/donor to decide if he or she is willing +to distribute software through any other system and a licensee cannot +impose that choice. + +This section is intended to make thoroughly clear what is believed to +be a consequence of the rest of this License. + + 8. If the distribution and/or use of the Program is restricted in +certain countries either by patents or by copyrighted interfaces, the +original copyright holder who places the Program under this License +may add an explicit geographical distribution limitation excluding +those countries, so that distribution is permitted only in or among +countries not thus excluded. In such case, this License incorporates +the limitation as if written in the body of this License. + + 9. The Free Software Foundation may publish revised and/or new versions +of the General Public License from time to time. Such new versions will +be similar in spirit to the present version, but may differ in detail to +address new problems or concerns. + +Each version is given a distinguishing version number. If the Program +specifies a version number of this License which applies to it and "any +later version", you have the option of following the terms and conditions +either of that version or of any later version published by the Free +Software Foundation. If the Program does not specify a version number of +this License, you may choose any version ever published by the Free Software +Foundation. + + 10. If you wish to incorporate parts of the Program into other free +programs whose distribution conditions are different, write to the author +to ask for permission. For software which is copyrighted by the Free +Software Foundation, write to the Free Software Foundation; we sometimes +make exceptions for this. Our decision will be guided by the two goals +of preserving the free status of all derivatives of our free software and +of promoting the sharing and reuse of software generally. + + NO WARRANTY + + 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY +FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN +OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES +PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED +OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS +TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE +PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, +REPAIR OR CORRECTION. + + 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING +WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR +REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, +INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING +OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED +TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY +YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER +PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE +POSSIBILITY OF SUCH DAMAGES. + + END OF TERMS AND CONDITIONS + + How to Apply These Terms to Your New Programs + + If you develop a new program, and you want it to be of the greatest +possible use to the public, the best way to achieve this is to make it +free software which everyone can redistribute and change under these terms. + + To do so, attach the following notices to the program. It is safest +to attach them to the start of each source file to most effectively +convey the exclusion of warranty; and each file should have at least +the "copyright" line and a pointer to where the full notice is found. + + + Copyright (C) + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License along + with this program; if not, write to the Free Software Foundation, Inc., + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + +Also add information on how to contact you by electronic and paper mail. + +If the program is interactive, make it output a short notice like this +when it starts in an interactive mode: + + Gnomovision version 69, Copyright (C) year name of author + Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. + This is free software, and you are welcome to redistribute it + under certain conditions; type `show c' for details. + +The hypothetical commands `show w' and `show c' should show the appropriate +parts of the General Public License. Of course, the commands you use may +be called something other than `show w' and `show c'; they could even be +mouse-clicks or menu items--whatever suits your program. + +You should also get your employer (if you work as a programmer) or your +school, if any, to sign a "copyright disclaimer" for the program, if +necessary. Here is a sample; alter the names: + + Yoyodyne, Inc., hereby disclaims all copyright interest in the program + `Gnomovision' (which makes passes at compilers) written by James Hacker. + + , 1 April 1989 + Ty Coon, President of Vice + +This General Public License does not permit incorporating your program into +proprietary programs. If your program is a subroutine library, you may +consider it more useful to permit linking proprietary applications with the +library. If this is what you want to do, use the GNU Lesser General +Public License instead of this License. diff --git a/platform/broadcom/saibcm-modules/sdklt/Makefile b/platform/broadcom/saibcm-modules/sdklt/Makefile new file mode 100644 index 00000000000..d6f358c5528 --- /dev/null +++ b/platform/broadcom/saibcm-modules/sdklt/Makefile @@ -0,0 +1,83 @@ +# +# $Copyright: Copyright 2018-2020 Broadcom. All rights reserved. +# The term 'Broadcom' refers to Broadcom Inc. and/or its subsidiaries. +# +# This program is free software; you can redistribute it and/or +# modify it under the terms of the GNU General Public License +# version 2 as published by the Free Software Foundation. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# A copy of the GNU General Public License version 2 (GPLv2) can +# be found in the LICENSES folder.$ +# + +help: + @echo '' + @echo 'Build Linux GPL kernel modules for SDKLT.' + @echo '' + @echo 'Available make targets:' + @echo 'kmod - Build kernel modules' + @echo 'clean - Remove object files' + @echo '' + @echo 'Supported make variables:' + @echo 'KDIR - Linux kernel source directory (mandatory)' + @echo 'CROSS_COPILE - Cross-compiler prefix (optional)' + @echo '' + @echo 'Examples:' + @echo 'make -s KDIR=$$KERNEL/linux kmod' + @echo 'make -s clean' + @echo '' + +ifndef KDIR +nokdir: + @echo 'Error: The $$KDIR environment variable is not set.' + @echo '$$KDIR must point to a configured Linux kernel source tree.' + exit 1 +endif + +export KDIR +export CROSS_COMPILE + +override SDK := $(CURDIR) + +ifeq ($(BUILD_PSAMPLE),1) +PSAMPLE=psample +PSAMPLE_SYMVERS=$(SDK)/linux/psample/Module.symvers +endif + +kmod: bde knet knetcb $(PSAMPLE) + +bde: + $(MAKE) -C $(SDK)/linux/bde SDK=$(SDK) \ + $(TARGET) + ln -sf $(SDK)/linux/bde/*.ko + +knet: bde + $(MAKE) -C $(SDK)/linux/knet SDK=$(SDK) \ + KBUILD_EXTRA_SYMBOLS=$(SDK)/linux/bde/Module.symvers \ + $(TARGET) + ln -sf $(SDK)/linux/knet/*.ko + +knetcb: knet $(PSAMPLE) + $(MAKE) -C $(SDK)/linux/knetcb SDK=$(SDK) \ + KBUILD_EXTRA_SYMBOLS=$(SDK)/linux/knet/Module.symvers \ + KBUILD_EXTRA_SYMBOLS+=$(PSAMPLE_SYMVERS) \ + $(TARGET) + ln -sf $(SDK)/linux/knetcb/*.ko + +ifeq ($(BUILD_PSAMPLE),1) +$(PSAMPLE): + $(MAKE) -C $(SDK)/linux/psample SDK=$(SDK) \ + $(TARGET) + ln -sf $(SDK)/linux/psample/*.ko +endif + +clean: + $(MAKE) kmod TARGET=clean + rm -f *.ko + +.PHONY: help kmod bde knet knetcb $(PSAMPLE) clean diff --git a/platform/broadcom/saibcm-modules/sdklt/bcmcnet/chip/bcm56780_a0/bcm56780_a0_pdma_attach.c b/platform/broadcom/saibcm-modules/sdklt/bcmcnet/chip/bcm56780_a0/bcm56780_a0_pdma_attach.c new file mode 100644 index 00000000000..e06dcb68bfc --- /dev/null +++ b/platform/broadcom/saibcm-modules/sdklt/bcmcnet/chip/bcm56780_a0/bcm56780_a0_pdma_attach.c @@ -0,0 +1,38 @@ +/*! \file bcm56780_a0_pdma_attach.c + * + * Initialize PDMA driver resources. + * + */ +/* + * $Copyright: Copyright 2018-2020 Broadcom. All rights reserved. + * The term 'Broadcom' refers to Broadcom Inc. and/or its subsidiaries. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * version 2 as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * A copy of the GNU General Public License version 2 (GPLv2) can + * be found in the LICENSES folder.$ + */ + +#include +#include +#include + +int +bcm56780_a0_cnet_pdma_attach(struct pdma_dev *dev) +{ + return bcmcnet_cmicx_pdma_driver_attach(dev); +} + +int +bcm56780_a0_cnet_pdma_detach(struct pdma_dev *dev) +{ + return bcmcnet_cmicx_pdma_driver_detach(dev); +} + diff --git a/platform/broadcom/saibcm-modules/sdklt/bcmcnet/chip/bcm56880_a0/bcm56880_a0_pdma_attach.c b/platform/broadcom/saibcm-modules/sdklt/bcmcnet/chip/bcm56880_a0/bcm56880_a0_pdma_attach.c new file mode 100644 index 00000000000..9a2152e99ac --- /dev/null +++ b/platform/broadcom/saibcm-modules/sdklt/bcmcnet/chip/bcm56880_a0/bcm56880_a0_pdma_attach.c @@ -0,0 +1,38 @@ +/*! \file bcm56880_a0_pdma_attach.c + * + * Initialize PDMA driver resources. + * + */ +/* + * $Copyright: Copyright 2018-2020 Broadcom. All rights reserved. + * The term 'Broadcom' refers to Broadcom Inc. and/or its subsidiaries. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * version 2 as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * A copy of the GNU General Public License version 2 (GPLv2) can + * be found in the LICENSES folder.$ + */ + +#include +#include +#include + +int +bcm56880_a0_cnet_pdma_attach(struct pdma_dev *dev) +{ + return bcmcnet_cmicx_pdma_driver_attach(dev); +} + +int +bcm56880_a0_cnet_pdma_detach(struct pdma_dev *dev) +{ + return bcmcnet_cmicx_pdma_driver_detach(dev); +} + diff --git a/platform/broadcom/saibcm-modules/sdklt/bcmcnet/chip/bcm56990_a0/bcm56990_a0_pdma_attach.c b/platform/broadcom/saibcm-modules/sdklt/bcmcnet/chip/bcm56990_a0/bcm56990_a0_pdma_attach.c new file mode 100644 index 00000000000..7827ef25de3 --- /dev/null +++ b/platform/broadcom/saibcm-modules/sdklt/bcmcnet/chip/bcm56990_a0/bcm56990_a0_pdma_attach.c @@ -0,0 +1,38 @@ +/*! \file bcm56990_a0_pdma_attach.c + * + * Initialize PDMA driver resources. + * + */ +/* + * $Copyright: Copyright 2018-2020 Broadcom. All rights reserved. + * The term 'Broadcom' refers to Broadcom Inc. and/or its subsidiaries. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * version 2 as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * A copy of the GNU General Public License version 2 (GPLv2) can + * be found in the LICENSES folder.$ + */ + +#include +#include +#include + +int +bcm56990_a0_cnet_pdma_attach(struct pdma_dev *dev) +{ + return bcmcnet_cmicx_pdma_driver_attach(dev); +} + +int +bcm56990_a0_cnet_pdma_detach(struct pdma_dev *dev) +{ + return bcmcnet_cmicx_pdma_driver_detach(dev); +} + diff --git a/platform/broadcom/saibcm-modules/sdklt/bcmcnet/chip/bcm56990_b0/bcm56990_b0_pdma_attach.c b/platform/broadcom/saibcm-modules/sdklt/bcmcnet/chip/bcm56990_b0/bcm56990_b0_pdma_attach.c new file mode 100644 index 00000000000..e34ae1f0b45 --- /dev/null +++ b/platform/broadcom/saibcm-modules/sdklt/bcmcnet/chip/bcm56990_b0/bcm56990_b0_pdma_attach.c @@ -0,0 +1,38 @@ +/*! \file bcm56990_b0_pdma_attach.c + * + * Initialize PDMA driver resources. + * + */ +/* + * $Copyright: Copyright 2018-2020 Broadcom. All rights reserved. + * The term 'Broadcom' refers to Broadcom Inc. and/or its subsidiaries. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * version 2 as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * A copy of the GNU General Public License version 2 (GPLv2) can + * be found in the LICENSES folder.$ + */ + +#include +#include +#include + +int +bcm56990_b0_cnet_pdma_attach(struct pdma_dev *dev) +{ + return bcmcnet_cmicx_pdma_driver_attach(dev); +} + +int +bcm56990_b0_cnet_pdma_detach(struct pdma_dev *dev) +{ + return bcmcnet_cmicx_pdma_driver_detach(dev); +} + diff --git a/platform/broadcom/saibcm-modules/sdklt/bcmcnet/chip/bcm56996_a0/bcm56996_a0_pdma_attach.c b/platform/broadcom/saibcm-modules/sdklt/bcmcnet/chip/bcm56996_a0/bcm56996_a0_pdma_attach.c new file mode 100644 index 00000000000..aab5822f68b --- /dev/null +++ b/platform/broadcom/saibcm-modules/sdklt/bcmcnet/chip/bcm56996_a0/bcm56996_a0_pdma_attach.c @@ -0,0 +1,38 @@ +/*! \file bcm56996_a0_pdma_attach.c + * + * Initialize PDMA driver resources. + * + */ +/* + * $Copyright: Copyright 2018-2020 Broadcom. All rights reserved. + * The term 'Broadcom' refers to Broadcom Inc. and/or its subsidiaries. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * version 2 as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * A copy of the GNU General Public License version 2 (GPLv2) can + * be found in the LICENSES folder.$ + */ + +#include +#include +#include + +int +bcm56996_a0_cnet_pdma_attach(struct pdma_dev *dev) +{ + return bcmcnet_cmicx_pdma_driver_attach(dev); +} + +int +bcm56996_a0_cnet_pdma_detach(struct pdma_dev *dev) +{ + return bcmcnet_cmicx_pdma_driver_detach(dev); +} + diff --git a/platform/broadcom/saibcm-modules/sdklt/bcmcnet/hmi/cmicd/bcmcnet_cmicd_pdma_hw.c b/platform/broadcom/saibcm-modules/sdklt/bcmcnet/hmi/cmicd/bcmcnet_cmicd_pdma_hw.c new file mode 100644 index 00000000000..83ce4d11b97 --- /dev/null +++ b/platform/broadcom/saibcm-modules/sdklt/bcmcnet/hmi/cmicd/bcmcnet_cmicd_pdma_hw.c @@ -0,0 +1,530 @@ +/*! \file bcmcnet_cmicd_pdma_hw.c + * + * Utility routines for handling BCMCNET hardware (CMICd). + * + */ +/* + * $Copyright: Copyright 2018-2020 Broadcom. All rights reserved. + * The term 'Broadcom' refers to Broadcom Inc. and/or its subsidiaries. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * version 2 as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * A copy of the GNU General Public License version 2 (GPLv2) can + * be found in the LICENSES folder.$ + */ + +#include +#include +#include +#include + +/*! + * Read 32-bit register + */ +static inline void +cmicd_pdma_reg_read32(struct pdma_hw *hw, uint32_t addr, uint32_t *data) +{ + if (hw->dev->dev_read32) { + hw->dev->dev_read32(hw->dev, addr, data); + } else { + DEV_READ32(&hw->dev->ctrl, addr, data); + } +} + +/*! + * Write 32-bit register + */ +static inline void +cmicd_pdma_reg_write32(struct pdma_hw *hw, uint32_t addr, uint32_t data) +{ + if (hw->dev->dev_write32) { + hw->dev->dev_write32(hw->dev, addr, data); + } else { + DEV_WRITE32(&hw->dev->ctrl, addr, data); + } +} + +/*! + * Enable interrupt for a channel + */ +static inline void +cmicd_pdma_intr_enable(struct pdma_hw *hw, int cmc, int chan, uint32_t mask) +{ + uint32_t reg = CMICD_IRQ_STAT(cmc); + + hw->dev->intr_unmask(hw->dev, cmc, chan, reg, mask); +} + +/*! + * Disable interrupt for a channel + */ +static inline void +cmicd_pdma_intr_disable(struct pdma_hw *hw, int cmc, int chan, uint32_t mask) +{ + uint32_t reg = CMICD_IRQ_STAT(cmc); + + hw->dev->intr_mask(hw->dev, cmc, chan, reg, mask); +} + +/*! + * Initialize HW + */ +static int +cmicd_pdma_hw_init(struct pdma_hw *hw) +{ + dev_mode_t mode = DEV_MODE_MAX; + uint32_t val; + + /* Temporarily upgrade work mode to get HW information in VNET mode. */ + if (hw->dev->mode == DEV_MODE_VNET) { + mode = DEV_MODE_VNET; + hw->dev->mode = DEV_MODE_UNET; + } + + /* Release credits to EP. Only do this once when HW is initialized. */ + hw->hdls.reg_rd32(hw, CMICD_EPINTF_RELEASE_CREDITS, &val); + if (!val) { + hw->hdls.reg_wr32(hw, CMICD_EPINTF_RELEASE_CREDITS, 1); + } + + hw->info.name = CMICD_DEV_NAME; + hw->hdls.reg_rd32(hw, CMICD_CMICM_REV_ID, &val); + hw->info.ver_no = val; + hw->hdls.reg_rd32(hw, CMICD_DEV_REV_ID, &val); + hw->info.dev_id = val & 0xffff; + hw->info.rev_id = val >> 16; + hw->info.num_cmcs = CMICD_PDMA_CMC_MAX; + hw->info.cmc_chans = CMICD_PDMA_CMC_CHAN; + hw->info.num_chans = CMICD_PDMA_CMC_MAX * CMICD_PDMA_CMC_CHAN; + hw->info.rx_dcb_size = CMICD_PDMA_DCB_SIZE; + hw->info.tx_dcb_size = CMICD_PDMA_DCB_SIZE; + hw->info.rx_ph_size = 0; + hw->info.tx_ph_size = 0; + + /* Restore work mode to VNET. */ + if (mode == DEV_MODE_VNET) { + hw->dev->mode = DEV_MODE_VNET; + } + + return SHR_E_NONE; +} + +/*! + * Configure HW + */ +static int +cmicd_pdma_hw_config(struct pdma_hw *hw) +{ + struct dev_ctrl *ctrl = &hw->dev->ctrl; + struct pdma_rx_queue *rxq = NULL; + struct pdma_tx_queue *txq = NULL; + uint32_t val, que_ctrl; + int grp, que; + uint32_t qi; + + for (qi = 0; qi < ctrl->nb_rxq; qi++) { + rxq = (struct pdma_rx_queue *)ctrl->rx_queue[qi]; + grp = rxq->group_id; + que = rxq->chan_id % CMICD_PDMA_CMC_CHAN; + que_ctrl = ctrl->grp[grp].que_ctrl[que]; + + hw->hdls.reg_wr32(hw, CMICD_PDMA_STAT_CLR(grp), CMICD_PDMA_DESC_CMPLT(que)); + hw->hdls.reg_wr32(hw, CMICD_PDMA_STAT_CLR(grp), CMICD_PDMA_DESC_CNTLD(que)); + val = 0; + if (que_ctrl & PDMA_PKT_BYTE_SWAP) { + val |= CMICD_PDMA_PKT_BIG_ENDIAN; + } + if (que_ctrl & PDMA_OTH_BYTE_SWAP) { + val |= CMICD_PDMA_DESC_BIG_ENDIAN; + } + if (!(hw->dev->flags & PDMA_CHAIN_MODE)) { + val |= CMICD_PDMA_CONTINUOUS; + } + val |= CMICD_PDMA_CNTLD_INTR; + val &= ~CMICD_PDMA_DIR; + hw->hdls.reg_wr32(hw, CMICD_PDMA_CTRL(grp, que), val); + } + + for (qi = 0; qi < ctrl->nb_txq; qi++) { + txq = (struct pdma_tx_queue *)ctrl->tx_queue[qi]; + grp = txq->group_id; + que = txq->chan_id % CMICD_PDMA_CMC_CHAN; + que_ctrl = ctrl->grp[grp].que_ctrl[que]; + + hw->hdls.reg_wr32(hw, CMICD_PDMA_STAT_CLR(grp), CMICD_PDMA_DESC_CMPLT(que)); + hw->hdls.reg_wr32(hw, CMICD_PDMA_STAT_CLR(grp), CMICD_PDMA_DESC_CNTLD(que)); + val = 0; + if (que_ctrl & PDMA_PKT_BYTE_SWAP) { + val |= CMICD_PDMA_PKT_BIG_ENDIAN; + } + if (que_ctrl & PDMA_OTH_BYTE_SWAP) { + val |= CMICD_PDMA_DESC_BIG_ENDIAN; + } + if (!(hw->dev->flags & PDMA_CHAIN_MODE)) { + val |= CMICD_PDMA_CONTINUOUS; + } + val |= CMICD_PDMA_CNTLD_INTR | CMICD_PDMA_DIR; + hw->hdls.reg_wr32(hw, CMICD_PDMA_CTRL(grp, que), val); + } + + return SHR_E_NONE; +} + +/*! + * Reset HW + */ +static int +cmicd_pdma_hw_reset(struct pdma_hw *hw) +{ + int gi, qi; + + for (gi = 0; gi < hw->dev->num_groups; gi++) { + if (!hw->dev->ctrl.grp[gi].attached) { + continue; + } + for (qi = 0; qi < CMICD_PDMA_CMC_CHAN; qi++) { + if (1 << qi & hw->dev->ctrl.grp[gi].bm_rxq || + 1 << qi & hw->dev->ctrl.grp[gi].bm_txq) { + hw->hdls.reg_wr32(hw, CMICD_PDMA_CTRL(gi, qi), 0); + } + } + } + + return SHR_E_NONE; +} + +/*! + * Start a channel + */ +static int +cmicd_pdma_chan_start(struct pdma_hw *hw, int chan) +{ + uint32_t val; + int grp, que; + + grp = chan / CMICD_PDMA_CMC_CHAN; + que = chan % CMICD_PDMA_CMC_CHAN; + + hw->hdls.reg_rd32(hw, CMICD_PDMA_CTRL(grp, que), &val); + val |= CMICD_PDMA_ENABLE; + hw->hdls.reg_wr32(hw, CMICD_PDMA_CTRL(grp, que), val); + + MEMORY_BARRIER; + + return SHR_E_NONE; +} + +/*! + * Stop a channel + */ +static int +cmicd_pdma_chan_stop(struct pdma_hw *hw, int chan) +{ + uint32_t val; + int grp, que; + int retry = CMICD_HW_RETRY_TIMES; + + grp = chan / CMICD_PDMA_CMC_CHAN; + que = chan % CMICD_PDMA_CMC_CHAN; + + hw->hdls.reg_rd32(hw, CMICD_PDMA_CTRL(grp, que), &val); + val |= CMICD_PDMA_ENABLE | CMICD_PDMA_ABORT; + hw->hdls.reg_wr32(hw, CMICD_PDMA_CTRL(grp, que), val); + + MEMORY_BARRIER; + + do { + val = ~CMICD_PDMA_ACTIVE(que); + hw->hdls.reg_rd32(hw, CMICD_PDMA_STAT(grp), &val); + } while ((val & CMICD_PDMA_ACTIVE(que)) && (--retry > 0)); + + hw->hdls.reg_rd32(hw, CMICD_PDMA_CTRL(grp, que), &val); + val &= ~(CMICD_PDMA_ENABLE | CMICD_PDMA_ABORT); + hw->hdls.reg_wr32(hw, CMICD_PDMA_CTRL(grp, que), val); + + hw->hdls.reg_wr32(hw, CMICD_PDMA_STAT_CLR(grp), CMICD_PDMA_DESC_CNTLD(que)); + + MEMORY_BARRIER; + + return SHR_E_NONE; +} + +/*! + * Setup a channel + */ +static int +cmicd_pdma_chan_setup(struct pdma_hw *hw, int chan, uint64_t addr) +{ + int grp, que; + + grp = chan / CMICD_PDMA_CMC_CHAN; + que = chan % CMICD_PDMA_CMC_CHAN; + + hw->hdls.reg_wr32(hw, CMICD_PDMA_DESC(grp, que), addr); + + MEMORY_BARRIER; + + return SHR_E_NONE; +} + +/*! + * Set halt point for a channel + */ +static int +cmicd_pdma_chan_goto(struct pdma_hw *hw, int chan, uint64_t addr) +{ + int grp, que; + + grp = chan / CMICD_PDMA_CMC_CHAN; + que = chan % CMICD_PDMA_CMC_CHAN; + + hw->hdls.reg_wr32(hw, CMICD_PDMA_DESC_HALT(grp, que), addr); + + MEMORY_BARRIER; + + return SHR_E_NONE; +} + +/*! + * Clear a channel + */ +static int +cmicd_pdma_chan_clear(struct pdma_hw *hw, int chan) +{ + int grp, que; + + grp = chan / CMICD_PDMA_CMC_CHAN; + que = chan % CMICD_PDMA_CMC_CHAN; + + hw->hdls.reg_wr32(hw, CMICD_PDMA_STAT_CLR(grp), CMICD_PDMA_DESC_CNTLD(que)); + + MEMORY_BARRIER; + + return SHR_E_NONE; +} + +/*! + * Get interrupt number for a channel + */ +static int +cmicd_pdma_chan_intr_num_get(struct pdma_hw *hw, int chan) +{ + int grp, que, start_num, mask_shift; + + grp = chan / CMICD_PDMA_CMC_CHAN; + que = chan % CMICD_PDMA_CMC_CHAN; + + mask_shift = 0; + if (grp > 0) { + mask_shift = CMICD_IRQ_MASK_SHIFT + grp * 32; + } + start_num = CMICD_IRQ_START_NUM + mask_shift; + + return start_num + (que * CMICD_IRQ_NUM_OFFSET); +} + +/*! + * Enable interrupt for a channel + */ +static int +cmicd_pdma_chan_intr_enable(struct pdma_hw *hw, int chan) +{ + int grp, que; + + grp = chan / CMICD_PDMA_CMC_CHAN; + que = chan % CMICD_PDMA_CMC_CHAN; + + cmicd_pdma_intr_enable(hw, grp, que, CMICD_IRQ_DESC_CNTLD(que)); + + return SHR_E_NONE; +} + +/*! + * Disable interrupt for a channel + */ +static int +cmicd_pdma_chan_intr_disable(struct pdma_hw *hw, int chan) +{ + int grp, que; + + grp = chan / CMICD_PDMA_CMC_CHAN; + que = chan % CMICD_PDMA_CMC_CHAN; + + cmicd_pdma_intr_disable(hw, grp, que, CMICD_IRQ_DESC_CNTLD(que)); + + return SHR_E_NONE; +} + +/*! + * Query interrupt status for a channel + * + * In group mode (interrupt processing per CMC), need to query each channel's + * interrupt status. + * + */ +static int +cmicd_pdma_chan_intr_query(struct pdma_hw *hw, int chan) +{ + uint32_t val; + int grp, que; + + grp = chan / CMICD_PDMA_CMC_CHAN; + que = chan % CMICD_PDMA_CMC_CHAN; + + hw->hdls.reg_rd32(hw, CMICD_IRQ_STAT(grp), &val); + + return val & CMICD_IRQ_DESC_CNTLD(que); +} + +/*! + * Check interrupt validity for a channel + * + * In group mode (interrupt processing per CMC), need to check each channel's + * interrupt validity based on its interrupt mask. + * + */ +static int +cmicd_pdma_chan_intr_check(struct pdma_hw *hw, int chan) +{ + int grp, que; + + grp = chan / CMICD_PDMA_CMC_CHAN; + que = chan % CMICD_PDMA_CMC_CHAN; + + if (!(hw->dev->ctrl.grp[grp].irq_mask & CMICD_IRQ_DESC_CNTLD(que))) { + return 0; + } + + return cmicd_pdma_chan_intr_query(hw, chan); +} + +/*! + * Coalesce interrupt for a channel + */ +static int +cmicd_pdma_chan_intr_coalesce(struct pdma_hw *hw, int chan, int count, int timer) +{ + uint32_t val; + int grp, que; + + grp = chan / CMICD_PDMA_CMC_CHAN; + que = chan % CMICD_PDMA_CMC_CHAN; + + val = CMICD_PDMA_INTR_COAL_ENA | + CMICD_PDMA_INTR_THRESH(count) | + CMICD_PDMA_INTR_TIMER(timer); + hw->hdls.reg_wr32(hw, CMICD_PDMA_INTR_COAL(grp, que), val); + + return SHR_E_NONE; +} + +/*! + * Dump registers for a channel + */ +static int +cmicd_pdma_chan_reg_dump(struct pdma_hw *hw, int chan) +{ + uint32_t val; + int grp, que; + + grp = chan / CMICD_PDMA_CMC_CHAN; + que = chan % CMICD_PDMA_CMC_CHAN; + + hw->hdls.reg_rd32(hw, CMICD_PDMA_CTRL(grp, que), &val); + CNET_PR("CMIC_CMC%d_CH%d_DMA_CTRL: 0x%08x\n", grp, que, val); + + hw->hdls.reg_rd32(hw, CMICD_PDMA_DESC(grp, que), &val); + CNET_PR("CMIC_CMC%d_DMA_DESC%d: 0x%08x\n", grp, que, val); + + hw->hdls.reg_rd32(hw, CMICD_PDMA_CURR_DESC(grp, que), &val); + CNET_PR("CMIC_CMC%d_CH%d_DMA_CURR_DESC: 0x%08x\n", grp, que, val); + + hw->hdls.reg_rd32(hw, CMICD_PDMA_DESC_HALT(grp, que), &val); + CNET_PR("CMIC_CMC%d_DMA_CH%d_DESC_HALT_ADDR: 0x%08x\n", grp, que, val); + + hw->hdls.reg_rd32(hw, CMICD_PDMA_COS_RX0(grp, que), &val); + CNET_PR("CMIC_CMC%d_CH%d_COS_CTRL_RX_0: 0x%08x\n", grp, que, val); + + hw->hdls.reg_rd32(hw, CMICD_PDMA_COS_RX1(grp, que), &val); + CNET_PR("CMIC_CMC%d_CH%d_COS_CTRL_RX_1: 0x%08x\n", grp, que, val); + + hw->hdls.reg_rd32(hw, CMICD_PDMA_COS_MASK0(grp), &val); + CNET_PR("CMIC_CMC%d_PROGRAMMABLE_COS_MASK0: 0x%08x\n", grp, val); + + hw->hdls.reg_rd32(hw, CMICD_PDMA_COS_MASK1(grp), &val); + CNET_PR("CMIC_CMC%d_PROGRAMMABLE_COS_MASK1: 0x%08x\n", grp, val); + + hw->hdls.reg_rd32(hw, CMICD_PDMA_INTR_COAL(grp, que), &val); + CNET_PR("CMIC_CMC%d_DMA_CH%d_INTR_COAL: 0x%08x\n", grp, que, val); + + hw->hdls.reg_rd32(hw, CMICD_PDMA_RBUF_THRE(grp, que), &val); + CNET_PR("CMIC_CMC%d_CH%d_RXBUF_THRESHOLD_CONFIG: 0x%08x\n", grp, que, val); + + hw->hdls.reg_rd32(hw, CMICD_PDMA_STAT(grp), &val); + CNET_PR("CMIC_CMC%d_DMA_STAT: 0x%08x\n", grp, val); + + hw->hdls.reg_rd32(hw, CMICD_PDMA_STAT_HI(grp), &val); + CNET_PR("CMIC_CMC%d_DMA_STAT_HI: 0x%08x\n", grp, val); + + hw->hdls.reg_rd32(hw, CMICD_PDMA_STAT_CLR(grp), &val); + CNET_PR("CMIC_CMC%d_DMA_STAT_CLR: 0x%08x\n", grp, val); + + hw->hdls.reg_rd32(hw, CMICD_PDMA_COUNT_RX(grp, que), &val); + CNET_PR("CMIC_CMC%d_PKT_COUNT_CH%d_RXPKT: 0x%08x\n", grp, que, val); + + hw->hdls.reg_rd32(hw, CMICD_PDMA_COUNT_TX(grp, que), &val); + CNET_PR("CMIC_CMC%d_PKT_COUNT_CH%d_TXPKT: 0x%08x\n", grp, que, val); + + hw->hdls.reg_rd32(hw, CMICD_IRQ_STAT(grp), &val); + CNET_PR("CMIC_CMC%d_IRQ_STAT0: 0x%08x\n", grp, val); + + hw->hdls.reg_rd32(hw, CMICD_IRQ_PCI_MASK(grp), &val); + CNET_PR("CMIC_CMC%d_PCIE_IRQ_MASK0: 0x%08x\n", grp, val); + + hw->hdls.reg_rd32(hw, CMICD_DEV_REV_ID, &val); + CNET_PR("CMIC_DEV_REV_ID: 0x%08x\n", val); + + hw->hdls.reg_rd32(hw, CMICD_CMICM_REV_ID, &val); + CNET_PR("CMIC_CMICM_REV_ID: 0x%08x\n", val); + + return SHR_E_NONE; +} + +/*! + * Initialize function pointers + */ +int +bcmcnet_cmicd_pdma_hw_hdls_init(struct pdma_hw *hw) +{ + if (!hw) { + return SHR_E_PARAM; + } + + hw->hdls.reg_rd32 = cmicd_pdma_reg_read32; + hw->hdls.reg_wr32 = cmicd_pdma_reg_write32; + hw->hdls.hw_init = cmicd_pdma_hw_init; + hw->hdls.hw_config = cmicd_pdma_hw_config; + hw->hdls.hw_reset = cmicd_pdma_hw_reset; + hw->hdls.chan_start = cmicd_pdma_chan_start; + hw->hdls.chan_stop = cmicd_pdma_chan_stop; + hw->hdls.chan_setup = cmicd_pdma_chan_setup; + hw->hdls.chan_goto = cmicd_pdma_chan_goto; + hw->hdls.chan_clear = cmicd_pdma_chan_clear; + hw->hdls.chan_intr_num_get = cmicd_pdma_chan_intr_num_get; + hw->hdls.chan_intr_enable = cmicd_pdma_chan_intr_enable; + hw->hdls.chan_intr_disable = cmicd_pdma_chan_intr_disable; + hw->hdls.chan_intr_query = cmicd_pdma_chan_intr_query; + hw->hdls.chan_intr_check = cmicd_pdma_chan_intr_check; + hw->hdls.chan_intr_coalesce = cmicd_pdma_chan_intr_coalesce; + hw->hdls.chan_reg_dump = cmicd_pdma_chan_reg_dump; + + return SHR_E_NONE; +} + diff --git a/platform/broadcom/saibcm-modules/sdklt/bcmcnet/hmi/cmicd/bcmcnet_cmicd_pdma_rxtx.c b/platform/broadcom/saibcm-modules/sdklt/bcmcnet/hmi/cmicd/bcmcnet_cmicd_pdma_rxtx.c new file mode 100644 index 00000000000..c4a10e160db --- /dev/null +++ b/platform/broadcom/saibcm-modules/sdklt/bcmcnet/hmi/cmicd/bcmcnet_cmicd_pdma_rxtx.c @@ -0,0 +1,1062 @@ +/*! \file bcmcnet_cmicd_pdma_rxtx.c + * + * Utility routines for BCMCNET hardware (CMICd) specific Rx/Tx. + * + * Here are the CMIC specific Rx/Tx routines including DCBs resource allocation + * and clean up, DCBs configuration, Rx buffers allocation, Tx buffers release, + * Rx/Tx packets processing, etc. + * They are shared among all the modes (UNET, KNET, VNET, HNET) and in both of + * user space and kernel space. + * + * The driver uses a ring of DCBs per DMA channel based on Continuous DMA mode. + * The beginning is written to register pointing to the physical address of the + * start of the ring. The ring size is maintained by the driver. A HALT DCB + * physical address is written to DMA register timely to indicate how many DCBs + * can be handled by HW. + * + * When a packet is received, an interrupt is triggered. The handler will go + * through the Rx DCB ring to process the current completed DCB and every + * subsequent DCBs until no one is left. The received packet is processed and + * passed up to the high level SW. After that, a new buffer is allocated and + * the DCB is updated for receiving a new packet. A new HALT DCB is selected + * and its physical address is written to DMA register. + * + * When a packet is transmitted, the driver starts where it left off last time + * in the Tx DCB ring, updates the DCB and writes its physical address to DMA + * register so as to start DMA. Once the transmitting is finished, the handler + * is informed to clean up the buffer based on the work mode. In KNET or HNET + * mode, an interrupt will be triggered. Polling mode is used in CNET or VNET + * mode, the buffers will be cleaned up when the number of dirty DCBs reaches + * a pre-defined threshold. + * + * In VNET and HNET modes, DCB updating between virtual ring and real ring and + * a IOCTL based notification mechanism are involved. The hypervisor in kernel + * emulates the DMA HW behaviors to update DCBs in virtual network and inform + * the handler something happened. Likewise, the hypervisor updates itself real + * DCB ring from the virtual ring to start DMA for transmitting a packet once a + * notification is received from the virtual network. + * + */ +/* + * $Copyright: Copyright 2018-2020 Broadcom. All rights reserved. + * The term 'Broadcom' refers to Broadcom Inc. and/or its subsidiaries. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * version 2 as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * A copy of the GNU General Public License version 2 (GPLv2) can + * be found in the LICENSES folder.$ + */ + +#include +#include +#include +#include +#include + +/*! + * Configure Rx descriptor + */ +static inline void +cmicd_rx_desc_config(struct cmicd_rx_desc *rd, uint32_t addr, uint32_t len) +{ + rd->addr = addr; + rd->md.status = 0; + rd->ctrl = CMICD_DESC_CTRL_CNTLD_INTR | CMICD_DESC_CTRL_CHAIN | + CMICD_DESC_CTRL_LEN(len); +} + +/*! + * Configure Tx descriptor + */ +static inline void +cmicd_tx_desc_config(struct cmicd_tx_desc *td, uint32_t addr, uint32_t len, uint32_t flags) +{ + td->addr = addr; + td->md.status = 0; + td->ctrl = CMICD_DESC_CTRL_CNTLD_INTR | CMICD_DESC_CTRL_CHAIN | + CMICD_DESC_CTRL_FLAGS(flags) | CMICD_DESC_CTRL_LEN(len); +} + +/*! + * Configure Rx reload descriptor + */ +static inline void +cmicd_rx_rldesc_config(struct cmicd_rx_desc *rd, uint32_t addr) +{ + rd->addr = addr; + rd->md.status = 0; + rd->ctrl = CMICD_DESC_CTRL_CNTLD_INTR | CMICD_DESC_CTRL_CHAIN | + CMICD_DESC_CTRL_RELOAD; +} + +/*! + * Configure Tx reload descriptor + */ +static inline void +cmicd_tx_rldesc_config(struct cmicd_tx_desc *td, uint32_t addr) +{ + td->addr = addr; + td->md.status = 0; + td->ctrl = CMICD_DESC_CTRL_CNTLD_INTR | CMICD_DESC_CTRL_CHAIN | + CMICD_DESC_CTRL_RELOAD; +} + +/*! + * Chain Rx descriptor + */ +static inline void +cmicd_rx_desc_chain(struct cmicd_rx_desc *rd, int chain) +{ + if (chain) { + rd->ctrl |= CMICD_DESC_CTRL_CHAIN; + } else { + rd->ctrl &= ~CMICD_DESC_CTRL_CHAIN; + } +} + +/*! + * Chain Tx descriptor + */ +static inline void +cmicd_tx_desc_chain(struct cmicd_tx_desc *td, int chain) +{ + if (chain) { + td->ctrl |= CMICD_DESC_CTRL_CHAIN; + } else { + td->ctrl &= ~CMICD_DESC_CTRL_CHAIN; + } +} + +/*! + * Get unused descriptors in a Rx ring + */ +static inline int +cmicd_pdma_rx_ring_unused(struct pdma_rx_queue *rxq) +{ + /* Leave one descriptor unused so as not to halt */ + return rxq->curr > rxq->halt ? + rxq->curr - rxq->halt - 1 : + rxq->nb_desc + rxq->curr - rxq->halt - 1; +} + +/*! + * Get unused descriptors in a Tx ring + */ +static inline int +cmicd_pdma_tx_ring_unused(struct pdma_tx_queue *txq) +{ + /* Leave one descriptor unused so as not to halt */ + return txq->dirt > txq->curr ? + txq->dirt - txq->curr - 1 : + txq->nb_desc + txq->dirt - txq->curr - 1; +} + +/*! + * Initialize Rx descriptors + */ +static int +cmicd_pdma_rx_desc_init(struct pdma_hw *hw, struct pdma_rx_queue *rxq) +{ + struct pdma_dev *dev = hw->dev; + struct pdma_buf_mngr *bm = (struct pdma_buf_mngr *)dev->ctrl.buf_mngr; + struct cmicd_rx_desc *ring = (struct cmicd_rx_desc *)rxq->ring; + dma_addr_t addr; + uint32_t di; + int rv; + + for (di = 0; di < rxq->nb_desc; di++) { + if (!rxq->pbuf[di].dma) { + /* Allocate pktbuf for ring entry */ + rxq->pbuf[di].adj = CMICD_RX_META_RESV; + rv = bm->rx_buf_alloc(dev, rxq, &rxq->pbuf[di]); + if (SHR_FAILURE(rv)) { + goto cleanup; + } + } + /* Config receive descriptor ring */ + bm->rx_buf_dma(dev, rxq, &rxq->pbuf[di], &addr); + cmicd_rx_desc_config(&ring[di], addr, rxq->buf_size); + if (hw->dev->flags & PDMA_CHAIN_MODE && di == rxq->nb_desc - 1) { + cmicd_rx_desc_chain(&ring[di], 0); + } + } + /* Config the last descriptor in the ring as reload descriptor */ + cmicd_rx_rldesc_config(&ring[di], rxq->ring_addr); + + rxq->curr = 0; + rxq->halt = rxq->state & PDMA_RX_BATCH_REFILL ? 0 : rxq->nb_desc; + + rxq->halt_addr = rxq->ring_addr + sizeof(struct cmicd_rx_desc) * di; + hw->hdls.chan_goto(hw, rxq->chan_id, rxq->halt_addr); + hw->hdls.chan_setup(hw, rxq->chan_id, rxq->ring_addr); + + return SHR_E_NONE; + +cleanup: + for (di = 0; di < rxq->nb_desc; di++) { + if (rxq->pbuf[di].dma) { + bm->rx_buf_free(dev, rxq, &rxq->pbuf[di]); + } + cmicd_rx_desc_config(&ring[di], 0, 0); + } + + CNET_PR("RX: Failed to allocate mem\n"); + + return SHR_E_MEMORY; +} + +/*! + * Cleanup Rx descriptors + */ +static int +cmicd_pdma_rx_desc_clean(struct pdma_hw *hw, struct pdma_rx_queue *rxq) +{ + struct pdma_dev *dev = hw->dev; + struct pdma_buf_mngr *bm = (struct pdma_buf_mngr *)dev->ctrl.buf_mngr; + struct cmicd_rx_desc *ring = (struct cmicd_rx_desc *)rxq->ring; + uint32_t di; + + /* Go through all the descriptors and free pktbuf */ + for (di = 0; di < rxq->nb_desc; di++) { + if (rxq->pbuf[di].dma) { + bm->rx_buf_free(dev, rxq, &rxq->pbuf[di]); + } + cmicd_rx_desc_config(&ring[di], 0, 0); + } + + rxq->curr = 0; + rxq->halt = 0; + + return SHR_E_NONE; +} + +/*! + * Initialize Tx descriptors + */ +static int +cmicd_pdma_tx_desc_init(struct pdma_hw *hw, struct pdma_tx_queue *txq) +{ + struct pdma_dev *dev = hw->dev; + struct pdma_buf_mngr *bm = (struct pdma_buf_mngr *)dev->ctrl.buf_mngr; + struct cmicd_tx_desc *ring = (struct cmicd_tx_desc *)txq->ring; + uint32_t di; + + for (di = 0; di < txq->nb_desc; di++) { + if (txq->pbuf[di].dma) { + bm->tx_buf_free(dev, txq, &txq->pbuf[di]); + } + /* Config transmit descriptor ring */ + cmicd_tx_desc_config(&ring[di], 0, 0, 0); + if (hw->dev->flags & PDMA_CHAIN_MODE) { + cmicd_tx_desc_chain(&ring[di], 0); + } + } + /* Config the last descriptor in the ring as reload descriptor */ + cmicd_tx_rldesc_config(&ring[di], txq->ring_addr); + + txq->curr = 0; + txq->dirt = 0; + txq->halt = 0; + + txq->halt_addr = txq->ring_addr; + hw->hdls.chan_goto(hw, txq->chan_id, txq->halt_addr); + hw->hdls.chan_setup(hw, txq->chan_id, txq->ring_addr); + + return SHR_E_NONE; +} + +/*! + * Cleanup Tx descriptors + */ +static int +cmicd_pdma_tx_desc_clean(struct pdma_hw *hw, struct pdma_tx_queue *txq) +{ + struct pdma_dev *dev = hw->dev; + struct pdma_buf_mngr *bm = (struct pdma_buf_mngr *)dev->ctrl.buf_mngr; + struct cmicd_tx_desc *ring = (struct cmicd_tx_desc *)txq->ring; + uint32_t di; + + /* Go through all the descriptors and free pktbuf */ + for (di = 0; di < txq->nb_desc; di++) { + if (txq->pbuf[di].dma) { + bm->tx_buf_free(dev, txq, &txq->pbuf[di]); + } + cmicd_tx_desc_config(&ring[di], 0, 0, 0); + } + + txq->curr = 0; + txq->dirt = 0; + txq->halt = 0; + + return SHR_E_NONE; +} + +/*! + * Process Rx vring + */ +static int +cmicd_pdma_rx_vring_process(struct pdma_hw *hw, struct pdma_rx_queue *rxq, + struct pdma_rx_buf *pbuf) +{ + struct pdma_dev *dev = hw->dev; + struct cmicd_rx_desc *ring = (struct cmicd_rx_desc *)rxq->ring; + struct pdma_rx_queue *vrxq = NULL; + struct cmicd_rx_desc *vring = NULL; + struct pkt_hdr *pkh = &pbuf->pkb->pkh; + + vrxq = (struct pdma_rx_queue *)dev->ctrl.vnet_rxq[rxq->queue_id]; + vring = (struct cmicd_rx_desc *)vrxq->ring; + if (!vring) { + rxq->stats.dropped++; + return SHR_E_UNAVAIL; + } + + if (vring[vrxq->curr].md.status & CMICD_DESC_STAT_RTX_DONE) { + dev->xnet_wake(dev); + return SHR_E_BUSY; + } + + /* Copy descriptor and packet to vring */ + sal_memcpy(dev->sys_p2v(dev, (uint64_t)vring[vrxq->curr].addr), + &pbuf->pkb->data + pkh->meta_len, pkh->data_len); + sal_memcpy(&vring[vrxq->curr].md, &ring[rxq->curr].md, + sizeof(((struct rx_metadata *)0)->data)); + vring[vrxq->curr].md.status = ring[rxq->curr].md.status; + + MEMORY_BARRIER; + + /* Notify VNET to process if needed */ + if (!vring[(vrxq->curr + vrxq->nb_desc - 1) % vrxq->nb_desc].md.status) { + dev->xnet_wake(dev); + } + vrxq->curr = (vrxq->curr + 1) % vrxq->nb_desc; + + return SHR_E_NONE; +} + +/*! + * Refill Rx ring + */ +static int +cmicd_pdma_rx_ring_refill(struct pdma_hw *hw, struct pdma_rx_queue *rxq) +{ + struct pdma_dev *dev = hw->dev; + struct pdma_buf_mngr *bm = (struct pdma_buf_mngr *)dev->ctrl.buf_mngr; + struct cmicd_rx_desc *ring = (struct cmicd_rx_desc *)rxq->ring; + struct pdma_rx_buf *pbuf = NULL; + int unused = cmicd_pdma_rx_ring_unused(rxq); + dma_addr_t addr; + uint32_t halt; + int rv; + + for (halt = rxq->halt; halt < rxq->halt + unused; halt++) { + pbuf = &rxq->pbuf[halt % rxq->nb_desc]; + /* Allocate a new pktbuf */ + if (!bm->rx_buf_avail(dev, rxq, pbuf)) { + rv = bm->rx_buf_alloc(dev, rxq, pbuf); + if (SHR_FAILURE(rv)) { + rxq->halt = halt % rxq->nb_desc; + rxq->stats.nomems++; + goto fail; + } + } + /* Setup the new descriptor */ + bm->rx_buf_dma(dev, rxq, pbuf, &addr); + cmicd_rx_desc_config(&ring[halt % rxq->nb_desc], addr, rxq->buf_size); + if (dev->flags & PDMA_CHAIN_MODE && halt % rxq->nb_desc == rxq->nb_desc - 1) { + cmicd_rx_desc_chain(&ring[halt % rxq->nb_desc], 0); + } + } + + sal_spinlock_lock(rxq->lock); + rxq->halt = halt % rxq->nb_desc; + if (!(rxq->state & PDMA_RX_QUEUE_XOFF)) { + /* Descriptor cherry pick */ + rxq->halt_addr = rxq->ring_addr + sizeof(struct cmicd_rx_desc) * rxq->halt; + hw->hdls.chan_goto(hw, rxq->chan_id, rxq->halt_addr); + } + sal_spinlock_unlock(rxq->lock); + + return SHR_E_NONE; + +fail: + CNET_PR("RX: Failed to allocate mem\n"); + + return SHR_E_MEMORY; +} + +/*! + * \brief Clean Rx ring + * + * \param [in] hw HW structure point. + * \param [in] rxq Rx queue structure point. + * \param [in] budget Polling budget. + * + * \retval SHR_E_NONE No errors. + * \retval SHR_E_XXXX Operation failed. + */ +static int +cmicd_pdma_rx_ring_clean(struct pdma_hw *hw, struct pdma_rx_queue *rxq, int budget) +{ + struct pdma_dev *dev = hw->dev; + struct pdma_buf_mngr *bm = (struct pdma_buf_mngr *)dev->ctrl.buf_mngr; + struct cmicd_rx_desc *ring = (struct cmicd_rx_desc *)rxq->ring; + struct pdma_rx_buf *pbuf = NULL; + struct pkt_hdr *pkh = NULL; + dma_addr_t addr; + uint32_t stat, curr; + int len, done = 0; + int rv; + + curr = rxq->curr; + while (CMICD_DESC_STAT_DONE(ring[curr].md.status)) { + if (dev->mode == DEV_MODE_VNET && rxq->state & PDMA_RX_QUEUE_XOFF) { + break; + } + if (!(rxq->state & PDMA_RX_BATCH_REFILL) && + !(rxq->state & PDMA_RX_QUEUE_XOFF)) { + /* Descriptor cherry pick */ + rxq->halt_addr = rxq->ring_addr + sizeof(struct cmicd_rx_desc) * curr; + hw->hdls.chan_goto(hw, rxq->chan_id, rxq->halt_addr); + rxq->halt = curr; + } + if (done == budget) { + break; + } + + /* Get the current pktbuf to process */ + pbuf = &rxq->pbuf[curr]; + stat = ring[curr].md.status; + len = CMICD_DESC_STAT_LEN(stat); + pkh = bm->rx_buf_get(dev, rxq, pbuf, len); + if (!pkh) { + rxq->stats.nomems++; + goto fail; + } + + /* Setup packet header */ + pkh->data_len = len; + pkh->meta_len = pbuf->adj; + pkh->queue_id = rxq->queue_id; + pkh->attrs = CMICD_DESC_STAT_FLAGS(stat); + sal_memcpy(&pbuf->pkb->data, &ring[curr].md, sizeof(struct rx_metadata)); + + /* Send up the packet */ + rv = dev->pkt_recv(dev, rxq->queue_id, (void *)pbuf->skb); + if (SHR_FAILURE(rv)) { + if (dev->mode == DEV_MODE_HNET && pkh->attrs & PDMA_RX_TO_VNET) { + rv = cmicd_pdma_rx_vring_process(hw, rxq, pbuf); + if (SHR_FAILURE(rv) && rv == SHR_E_BUSY) { + rxq->state |= PDMA_RX_QUEUE_BUSY; + return done; + } + } else { + rxq->stats.dropped++; + } + bm->rx_buf_put(dev, rxq, pbuf, len); + } + + /* Count the packets/bytes */ + rxq->stats.packets++; + rxq->stats.bytes += len; + + /* Count the errors if any */ + if (stat & CMICD_DESC_STAT_ERR_MASK) { + rxq->stats.errors++; + if (stat & CMICD_DESC_STAT_HEAD_ERR) { + rxq->stats.head_errors++; + } + if (stat & CMICD_DESC_STAT_DATA_ERR) { + rxq->stats.data_errors++; + } + if (stat & CMICD_DESC_STAT_CELL_ERR) { + rxq->stats.cell_errors++; + } + } + + /* Setup the new descriptor */ + if (!(rxq->state & PDMA_RX_BATCH_REFILL)) { + if (!bm->rx_buf_avail(dev, rxq, pbuf)) { + rv = bm->rx_buf_alloc(dev, rxq, pbuf); + if (SHR_FAILURE(rv)) { + rxq->stats.nomems++; + goto fail; + } + } + bm->rx_buf_dma(dev, rxq, pbuf, &addr); + cmicd_rx_desc_config(&ring[curr], addr, rxq->buf_size); + if (dev->flags & PDMA_CHAIN_MODE && curr == rxq->nb_desc - 1) { + cmicd_rx_desc_chain(&ring[curr], 0); + } + } else { + cmicd_rx_desc_config(&ring[curr], 0, 0); + } + + /* Notify HNET to process if needed */ + if (dev->mode == DEV_MODE_VNET) { + MEMORY_BARRIER; + if (ring[(curr + rxq->nb_desc - 1) % rxq->nb_desc].md.status) { + dev->xnet_wake(dev); + } + } + + /* Update the indicators */ + if (!(rxq->state & PDMA_RX_BATCH_REFILL) && rxq->halt != curr) { + sal_spinlock_lock(rxq->lock); + if (!(rxq->state & PDMA_RX_QUEUE_XOFF)) { + /* Descriptor cherry pick */ + rxq->halt_addr = rxq->ring_addr + sizeof(struct cmicd_rx_desc) * curr; + hw->hdls.chan_goto(hw, rxq->chan_id, rxq->halt_addr); + rxq->halt = curr; + } + curr = (curr + 1) % rxq->nb_desc; + sal_spinlock_unlock(rxq->lock); + } else { + curr = (curr + 1) % rxq->nb_desc; + } + rxq->curr = curr; + done++; + + /* Restart DMA if in chain mode */ + if (dev->flags & PDMA_CHAIN_MODE) { + if (curr == 0 && !(rxq->state & PDMA_RX_QUEUE_XOFF)) { + hw->hdls.chan_stop(hw, rxq->chan_id); + hw->hdls.chan_start(hw, rxq->chan_id); + } + } + } + + /* One more poll for chain done in chain mode */ + if (dev->flags & PDMA_CHAIN_MODE) { + if (curr == rxq->nb_desc - 1 && done) { + done = budget; + } + } + + /* In batching mode, replenish all the unused descriptors */ + if (rxq->state & PDMA_RX_BATCH_REFILL && + cmicd_pdma_rx_ring_unused(rxq) >= (int)rxq->free_thresh) { + cmicd_pdma_rx_ring_refill(hw, rxq); + } + + /* Notify the other side to process */ + if (dev->mode == DEV_MODE_VNET || dev->mode == DEV_MODE_HNET) { + if (done) { + dev->xnet_wake(dev); + } + } + + return done; + +fail: + CNET_PR("RX: Failed to allocate mem\n"); + + return done; +} + +/*! + * Process Tx vring + */ +static int +cmicd_pdma_tx_vring_process(struct pdma_hw *hw, struct pdma_tx_queue *txq, + struct pdma_tx_buf *pbuf) +{ + struct pdma_dev *dev = hw->dev; + struct cmicd_tx_desc *ring = (struct cmicd_tx_desc *)txq->ring; + struct pdma_tx_queue *vtxq = NULL; + struct cmicd_tx_desc *vring = NULL; + + vtxq = (struct pdma_tx_queue *)dev->ctrl.vnet_txq[txq->queue_id]; + vring = (struct cmicd_tx_desc *)vtxq->ring; + if (!vring) { + return SHR_E_UNAVAIL; + } + + /* Update vring descriptor */ + vring[vtxq->dirt].md.status = ring[txq->dirt].md.status; + pbuf->dma = 0; + + MEMORY_BARRIER; + + /* Notify VNET to process if needed */ + if (!vring[(vtxq->dirt + vtxq->nb_desc - 1) % vtxq->nb_desc].md.status) { + dev->xnet_wake(dev); + } + vtxq->dirt = (vtxq->dirt + 1) % vtxq->nb_desc; + + return SHR_E_NONE; +} + +/*! + * \brief Clean Tx ring + * + * \param [in] hw HW structure point. + * \param [in] txq Tx queue structure point. + * \param [in] budget Polling budget. + * + * \retval SHR_E_NONE No errors. + * \retval SHR_E_XXXX Operation failed. + */ +static int +cmicd_pdma_tx_ring_clean(struct pdma_hw *hw, struct pdma_tx_queue *txq, int budget) +{ + struct pdma_dev *dev = hw->dev; + struct pdma_buf_mngr *bm = (struct pdma_buf_mngr *)dev->ctrl.buf_mngr; + struct cmicd_tx_desc *ring = (struct cmicd_tx_desc *)txq->ring; + uint32_t dirt, curr; + int done = 0; + + dirt = txq->dirt; + while (txq->pbuf[dirt].dma) { + if (!CMICD_DESC_STAT_DONE(ring[dirt].md.status)) { + break; + } + if (done == budget) { + break; + } + + if (dev->mode == DEV_MODE_HNET && !txq->pbuf[dirt].skb) { + cmicd_pdma_tx_vring_process(hw, txq, &txq->pbuf[dirt]); + } else { + /* Free the done pktbuf */ + bm->tx_buf_free(dev, txq, &txq->pbuf[dirt]); + } + + cmicd_tx_desc_config(&ring[dirt], 0, 0, 0); + + /* Update the indicators */ + dirt = (dirt + 1) % txq->nb_desc; + txq->dirt = dirt; + done++; + + /* Restart DMA if in chain mode */ + if (dev->flags & PDMA_CHAIN_MODE) { + sal_spinlock_lock(txq->lock); + curr = txq->curr; + if (dirt == txq->halt && dirt != curr) { + hw->hdls.chan_stop(hw, txq->chan_id); + cmicd_tx_desc_chain(&ring[(curr + txq->nb_desc - 1) % txq->nb_desc], 0); + hw->hdls.chan_setup(hw, txq->chan_id, + txq->ring_addr + sizeof(struct cmicd_tx_desc) * txq->halt); + hw->hdls.chan_start(hw, txq->chan_id); + txq->halt = curr; + } + sal_spinlock_unlock(txq->lock); + } + } + + /* One more poll for chain done in chain mode */ + if (dev->flags & PDMA_CHAIN_MODE) { + sal_spinlock_lock(txq->lock); + if (dirt != txq->halt) { + done = budget; + } + sal_spinlock_unlock(txq->lock); + } + + /* Resume Tx if any */ + sal_spinlock_lock(txq->lock); + if (cmicd_pdma_tx_ring_unused(txq) && txq->state & PDMA_TX_QUEUE_XOFF) { + txq->state &= ~PDMA_TX_QUEUE_XOFF; + sal_spinlock_unlock(txq->lock); + if (dev->tx_resume) { + dev->tx_resume(dev, txq->queue_id); + } else if (!(txq->state & PDMA_TX_QUEUE_POLL)) { + sal_sem_give(txq->sem); + } + return done; + } + sal_spinlock_unlock(txq->lock); + + return done; +} + +/*! + * Dump Rx ring + */ +static int +cmicd_pdma_rx_ring_dump(struct pdma_hw *hw, struct pdma_rx_queue *rxq) +{ + struct cmicd_rx_desc *ring = (struct cmicd_rx_desc *)rxq->ring; + struct cmicd_rx_desc *rd; + uint32_t di; + + CNET_PR("\nRX: queue=%d, chan=%d, curr=%d, halt=%d, halt@%p\n", + rxq->queue_id, rxq->chan_id, rxq->curr, rxq->halt, (void *)&ring[rxq->halt]); + CNET_PR("----------------------------------------------------------------\n"); + for (di = 0; di < rxq->nb_desc + 1; di++) { + rd = &ring[di]; + CNET_PR("DESC[%03d]: (%p)->%08x %08x ... %08x\n", + di, (void *)(unsigned long)(rxq->ring_addr + di * CMICD_PDMA_DCB_SIZE), + rd->addr, rd->ctrl, rd->md.status); + } + + return SHR_E_NONE; +} + +/*! + * Dump Tx ring + */ +static int +cmicd_pdma_tx_ring_dump(struct pdma_hw *hw, struct pdma_tx_queue *txq) +{ + struct cmicd_tx_desc *ring = (struct cmicd_tx_desc *)txq->ring; + struct cmicd_tx_desc *td; + uint32_t di; + + CNET_PR("\nTX: queue=%d, chan=%d, curr=%d, dirt=%d, halt@%p\n", + txq->queue_id, txq->chan_id, txq->curr, txq->dirt, (void *)&ring[txq->curr]); + CNET_PR("----------------------------------------------------------------\n"); + for (di = 0; di < txq->nb_desc + 1; di++) { + td = &ring[di]; + CNET_PR("DESC[%03d]: (%p)->%08x %08x ... %08x\n", + di, (void *)(unsigned long)(txq->ring_addr + di * CMICD_PDMA_DCB_SIZE), + td->addr, td->ctrl, td->md.status); + } + + return SHR_E_NONE; +} + +/*! + * Fetch Tx vring + */ +static int +cmicd_pdma_tx_vring_fetch(struct pdma_hw *hw, struct pdma_tx_queue *txq, + struct pdma_tx_buf *pbuf) +{ + struct pdma_dev *dev = hw->dev; + struct cmicd_tx_desc *ring = (struct cmicd_tx_desc *)txq->ring; + struct pdma_tx_queue *vtxq = NULL; + struct cmicd_tx_desc *vring = NULL; + + vtxq = (struct pdma_tx_queue *)dev->ctrl.vnet_txq[txq->queue_id]; + vring = (struct cmicd_tx_desc *)vtxq->ring; + if (!vring || !CMICD_DESC_CTRL_LEN(vring[vtxq->curr].ctrl)) { + return SHR_E_UNAVAIL; + } + + /* Fetch vring descriptor */ + sal_memcpy(&ring[txq->curr], &vring[vtxq->curr], sizeof(struct cmicd_tx_desc)); + vring[vtxq->curr].ctrl &= ~CMICD_DESC_CTRL_LEN(-1); + + MEMORY_BARRIER; + + pbuf->dma = vring[vtxq->curr].addr; + pbuf->len = CMICD_DESC_CTRL_LEN(ring[txq->curr].ctrl); + vtxq->curr = (vtxq->curr + 1) % vtxq->nb_desc; + + return SHR_E_NONE; +} + +/*! + * Check Tx ring + */ +static inline int +cmicd_pdma_tx_ring_check(struct pdma_hw *hw, struct pdma_tx_queue *txq) +{ + if (cmicd_pdma_tx_ring_unused(txq)) { + return SHR_E_NONE; + } + + sal_spinlock_lock(txq->lock); + if (!cmicd_pdma_tx_ring_unused(txq)) { + txq->state |= PDMA_TX_QUEUE_XOFF; + txq->stats.xoffs++; + sal_spinlock_unlock(txq->lock); + if (hw->dev->tx_suspend) { + hw->dev->tx_suspend(hw->dev, txq->queue_id); + } + return SHR_E_BUSY; + } + sal_spinlock_unlock(txq->lock); + + return SHR_E_NONE; +} + +/*! + * \brief Start packet transmission + * + * \param [in] hw HW structure point. + * \param [in] txq Tx queue structure point. + * \param [in] buf Tx packet buffer. + * + * \retval SHR_E_NONE No errors. + * \retval SHR_E_XXXX Operation failed. + */ +static int +cmicd_pdma_pkt_xmit(struct pdma_hw *hw, struct pdma_tx_queue *txq, void *buf) +{ + struct pdma_dev *dev = hw->dev; + struct pdma_buf_mngr *bm = (struct pdma_buf_mngr *)dev->ctrl.buf_mngr; + struct cmicd_tx_desc *ring = (struct cmicd_tx_desc *)txq->ring; + struct pdma_tx_buf *pbuf = NULL; + struct pkt_hdr *pkh = NULL; + dma_addr_t addr; + uint32_t curr, flags = 0; + int retry = 5000000; + int rv; + + if (!(txq->state & PDMA_TX_QUEUE_ACTIVE)) { + return SHR_E_UNAVAIL; + } + + if (dev->tx_suspend) { + sal_spinlock_lock(txq->mutex); + } else { + sal_sem_take(txq->sem, SAL_SEM_FOREVER); + } + + /* Check Tx resource */ + if (dev->tx_suspend) { + /* Suspend Tx if no resource */ + rv = cmicd_pdma_tx_ring_check(hw, txq); + if (SHR_FAILURE(rv)) { + sal_spinlock_unlock(txq->mutex); + return rv; + } + } else { + /* Abort Tx if a fatal error happened */ + if (txq->state & PDMA_TX_QUEUE_XOFF) { + sal_sem_give(txq->sem); + return SHR_E_RESOURCE; + } + } + + /* Setup the new descriptor */ + curr = txq->curr; + pbuf = &txq->pbuf[curr]; + if (dev->mode == DEV_MODE_HNET && !buf) { + rv = cmicd_pdma_tx_vring_fetch(hw, txq, pbuf); + if (SHR_FAILURE(rv)) { + sal_spinlock_unlock(txq->mutex); + return SHR_E_EMPTY; + } + } else { + pbuf->adj = 0; + pkh = bm->tx_buf_get(dev, txq, pbuf, buf); + if (!pkh) { + txq->stats.dropped++; + if (dev->tx_suspend) { + sal_spinlock_unlock(txq->mutex); + } else { + sal_sem_give(txq->sem); + } + return SHR_E_NONE; + } + bm->tx_buf_dma(dev, txq, pbuf, &addr); + flags |= pkh->attrs & PDMA_TX_HIGIG_PKT ? CMICD_DESC_TX_HIGIG_PKT : 0; + flags |= pkh->attrs & PDMA_TX_PAUSE_PKT ? CMICD_DESC_TX_PAUSE_PKT : 0; + flags |= pkh->attrs & PDMA_TX_PURGE_PKT ? CMICD_DESC_TX_PURGE_PKT : 0; + cmicd_tx_desc_config(&ring[curr], addr, pbuf->len, flags); + if (pkh->meta_len) { + sal_memcpy(&ring[curr].md, &pbuf->pkb->data, sizeof(ring->md.data)); + } + } + + /* Notify HNET to process if needed */ + if (dev->mode == DEV_MODE_VNET) { + MEMORY_BARRIER; + if (!CMICD_DESC_CTRL_LEN(ring[(curr + txq->nb_desc - 1) % txq->nb_desc].ctrl)) { + dev->xnet_wake(dev); + } + } + + /* Update the indicators */ + curr = (curr + 1) % txq->nb_desc; + txq->curr = curr; + + /* Start DMA if in chain mode */ + if (dev->flags & PDMA_CHAIN_MODE) { + if (txq->state & PDMA_TX_QUEUE_POLL) { + do { + rv = cmicd_pdma_tx_ring_clean(hw, txq, txq->nb_desc - 1); + if (rv != (int)txq->nb_desc - 1) { + break; + } + sal_usleep(1); + } while (retry--); + if (retry <= 0) { + CNET_PR("Last Tx could not be done in given time\n"); + } + } + sal_spinlock_lock(txq->lock); + if (txq->dirt == txq->halt && txq->dirt != curr) { + hw->hdls.chan_stop(hw, txq->chan_id); + cmicd_tx_desc_chain(&ring[(curr + txq->nb_desc - 1) % txq->nb_desc], 0); + hw->hdls.chan_setup(hw, txq->chan_id, + txq->ring_addr + sizeof(struct cmicd_tx_desc) * txq->halt); + hw->hdls.chan_start(hw, txq->chan_id); + txq->halt = curr; + } + sal_spinlock_unlock(txq->lock); + } + + /* Kick off DMA */ + txq->halt_addr = txq->ring_addr + sizeof(struct cmicd_tx_desc) * curr; + hw->hdls.chan_goto(hw, txq->chan_id, txq->halt_addr); + + /* Count the packets/bytes */ + txq->stats.packets++; + txq->stats.bytes += pbuf->len; + + /* Clean up ring if in polling mode */ + if (txq->state & PDMA_TX_QUEUE_POLL && + cmicd_pdma_tx_ring_unused(txq) <= (int)txq->free_thresh) { + cmicd_pdma_tx_ring_clean(hw, txq, txq->nb_desc - txq->free_thresh); + } + + /* Suspend Tx if no resource */ + rv = cmicd_pdma_tx_ring_check(hw, txq); + if (SHR_FAILURE(rv)) { + if (dev->mode == DEV_MODE_VNET) { + dev->xnet_wake(dev); + } + + if (txq->state & PDMA_TX_QUEUE_POLL) { + /* In polling mode, must wait till the ring is available */ + do { + cmicd_pdma_tx_ring_clean(hw, txq, txq->free_thresh); + if (!(txq->state & PDMA_TX_QUEUE_XOFF)) { + break; + } + sal_usleep(1); + } while (retry--); + if (retry <= 0) { + CNET_PR("Fatal error: Tx ring is full, packets have not been transmitted for 5 seconds\n"); + if (!dev->tx_suspend) { + sal_sem_give(txq->sem); + return SHR_E_RESOURCE; + } + } + } else { + /* In interrupt mode, the handle thread will wake up Tx */ + if (!dev->tx_suspend) { + return SHR_E_NONE; + } + } + } + + if (dev->tx_suspend) { + sal_spinlock_unlock(txq->mutex); + } else { + sal_sem_give(txq->sem); + } + + return SHR_E_NONE; +} + +/*! + * Suspend Rx queue + */ +static int +cmicd_pdma_rx_suspend(struct pdma_hw *hw, struct pdma_rx_queue *rxq) +{ + sal_spinlock_lock(rxq->lock); + rxq->state |= PDMA_RX_QUEUE_XOFF; + if (hw->dev->flags & PDMA_CHAIN_MODE) { + hw->hdls.chan_stop(hw, rxq->chan_id); + } + sal_spinlock_unlock(rxq->lock); + + return SHR_E_NONE; +} + +/*! + * Resume Rx queue + */ +static int +cmicd_pdma_rx_resume(struct pdma_hw *hw, struct pdma_rx_queue *rxq) +{ + sal_spinlock_lock(rxq->lock); + if (!(rxq->state & PDMA_RX_QUEUE_XOFF)) { + sal_spinlock_unlock(rxq->lock); + return SHR_E_NONE; + } + if (rxq->state & PDMA_RX_BATCH_REFILL) { + rxq->halt_addr = rxq->ring_addr + sizeof(struct cmicd_rx_desc) * rxq->halt; + hw->hdls.chan_goto(hw, rxq->chan_id, rxq->halt_addr); + } else if (rxq->halt == rxq->curr || (rxq->halt == rxq->nb_desc && rxq->curr == 0)) { + rxq->halt = (rxq->curr + 1) % rxq->nb_desc; + rxq->halt_addr = rxq->ring_addr + sizeof(struct cmicd_rx_desc) * rxq->halt; + hw->hdls.chan_goto(hw, rxq->chan_id, rxq->halt_addr); + } + if (hw->dev->flags & PDMA_CHAIN_MODE) { + rxq->curr = 0; + hw->hdls.chan_start(hw, rxq->chan_id); + } + rxq->state &= ~PDMA_RX_QUEUE_XOFF; + sal_spinlock_unlock(rxq->lock); + + return SHR_E_NONE; +} + +/*! + * Initialize function pointers + */ +int +bcmcnet_cmicd_pdma_desc_ops_init(struct pdma_hw *hw) +{ + if (!hw) { + return SHR_E_PARAM; + } + + hw->dops.rx_desc_init = cmicd_pdma_rx_desc_init; + hw->dops.rx_desc_clean = cmicd_pdma_rx_desc_clean; + hw->dops.rx_ring_clean = cmicd_pdma_rx_ring_clean; + hw->dops.rx_ring_dump = cmicd_pdma_rx_ring_dump; + hw->dops.rx_suspend = cmicd_pdma_rx_suspend; + hw->dops.rx_resume = cmicd_pdma_rx_resume; + hw->dops.tx_desc_init = cmicd_pdma_tx_desc_init; + hw->dops.tx_desc_clean = cmicd_pdma_tx_desc_clean; + hw->dops.tx_ring_clean = cmicd_pdma_tx_ring_clean; + hw->dops.tx_ring_dump = cmicd_pdma_tx_ring_dump; + hw->dops.pkt_xmit = cmicd_pdma_pkt_xmit; + + return SHR_E_NONE; +} + +/*! + * Attach device driver + */ +int +bcmcnet_cmicd_pdma_driver_attach(struct pdma_dev *dev) +{ + struct pdma_hw *hw = NULL; + + /* Allocate memory for HW data */ + hw = sal_alloc(sizeof(*hw), "bcmcnetPdmaHw"); + if (!hw) { + return SHR_E_MEMORY; + } + sal_memset(hw, 0, sizeof(*hw)); + hw->unit = dev->unit; + hw->dev = dev; + dev->ctrl.hw = hw; + + bcmcnet_cmicd_pdma_hw_hdls_init(hw); + bcmcnet_cmicd_pdma_desc_ops_init(hw); + + return SHR_E_NONE; +} + +/*! + * Detach device driver + */ +int +bcmcnet_cmicd_pdma_driver_detach(struct pdma_dev *dev) +{ + if (dev->ctrl.hw) { + sal_free(dev->ctrl.hw); + } + dev->ctrl.hw = NULL; + + return SHR_E_NONE; +} + diff --git a/platform/broadcom/saibcm-modules/sdklt/bcmcnet/hmi/cmicx/bcmcnet_cmicx_pdma_hw.c b/platform/broadcom/saibcm-modules/sdklt/bcmcnet/hmi/cmicx/bcmcnet_cmicx_pdma_hw.c new file mode 100644 index 00000000000..6dc77c4b7c0 --- /dev/null +++ b/platform/broadcom/saibcm-modules/sdklt/bcmcnet/hmi/cmicx/bcmcnet_cmicx_pdma_hw.c @@ -0,0 +1,604 @@ +/*! \file bcmcnet_cmicx_pdma_hw.c + * + * Utility routines for handling BCMCNET hardware (CMICx). + * + */ +/* + * $Copyright: Copyright 2018-2020 Broadcom. All rights reserved. + * The term 'Broadcom' refers to Broadcom Inc. and/or its subsidiaries. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * version 2 as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * A copy of the GNU General Public License version 2 (GPLv2) can + * be found in the LICENSES folder.$ + */ + +#include +#include +#include +#include + +/*! + * Read 32-bit register + */ +static inline void +cmicx_pdma_reg_read32(struct pdma_hw *hw, uint32_t addr, uint32_t *data) +{ + if (hw->dev->dev_read32) { + hw->dev->dev_read32(hw->dev, addr, data); + } else { + DEV_READ32(&hw->dev->ctrl, addr, data); + } +} + +/*! + * Write 32-bit register + */ +static inline void +cmicx_pdma_reg_write32(struct pdma_hw *hw, uint32_t addr, uint32_t data) +{ + if (hw->dev->dev_write32) { + hw->dev->dev_write32(hw->dev, addr, data); + } else { + DEV_WRITE32(&hw->dev->ctrl, addr, data); + } +} + +/*! + * Enable interrupt for a channel + */ +static inline void +cmicx_pdma_intr_enable(struct pdma_hw *hw, int cmc, int chan, uint32_t mask) +{ + uint32_t reg, irq_mask; + + hw->dev->ctrl.grp[cmc].irq_mask |= mask; + irq_mask = hw->dev->ctrl.grp[cmc].irq_mask; + if (cmc == 0) { + reg = CMICX_PDMA_IRQ_RAW_STAT0; + } else { + if (chan < 4) { + reg = CMICX_PDMA_IRQ_RAW_STAT1; + hw->dev->ctrl.grp[cmc].irq_mask <<= CMICX_IRQ_MASK_SHIFT; + } else { + reg = CMICX_PDMA_IRQ_RAW_STAT2; + hw->dev->ctrl.grp[cmc].irq_mask >>= 32 - CMICX_IRQ_MASK_SHIFT; + } + } + + hw->dev->intr_unmask(hw->dev, cmc, chan, reg & 0xfff, 0); + hw->dev->ctrl.grp[cmc].irq_mask = irq_mask; +} + +/*! + * Disable interrupt for a channel + */ +static inline void +cmicx_pdma_intr_disable(struct pdma_hw *hw, int cmc, int chan, uint32_t mask) +{ + uint32_t reg, irq_mask; + + hw->dev->ctrl.grp[cmc].irq_mask &= ~mask; + irq_mask = hw->dev->ctrl.grp[cmc].irq_mask; + if (cmc == 0) { + reg = CMICX_PDMA_IRQ_RAW_STAT0; + } else { + if (chan < 4) { + reg = CMICX_PDMA_IRQ_RAW_STAT1; + hw->dev->ctrl.grp[cmc].irq_mask <<= CMICX_IRQ_MASK_SHIFT; + } else { + reg = CMICX_PDMA_IRQ_RAW_STAT2; + hw->dev->ctrl.grp[cmc].irq_mask >>= 32 - CMICX_IRQ_MASK_SHIFT; + } + } + + hw->dev->intr_mask(hw->dev, cmc, chan, reg & 0xfff, 0); + hw->dev->ctrl.grp[cmc].irq_mask = irq_mask; +} + +/*! + * Release Packet DMA credits to EP. + */ +static int +cmicx_pdma_credits_release(struct pdma_hw *hw) +{ + int credits; + uint32_t val; + + /* + * Since only 6 bits of iproc_cmic_to_ep_credits[5:0] are being used, + * so we have to set the max credits value twice in order to release + * 64 credits to EP. + * Only do this once when HW is initialized. + */ + hw->hdls.reg_rd32(hw, CMICX_EPINTF_RELEASE_CREDITS, &val); + if (!val) { + credits = 63; + hw->hdls.reg_wr32(hw, CMICX_EPINTF_MAX_CREDITS, (0x1 << 8) | credits); + hw->hdls.reg_wr32(hw, CMICX_EPINTF_RELEASE_CREDITS, 1); + + hw->hdls.reg_wr32(hw, CMICX_EPINTF_RELEASE_CREDITS, 0); + credits = 1; + hw->hdls.reg_wr32(hw, CMICX_EPINTF_MAX_CREDITS, (0x1 << 8) | credits); + hw->hdls.reg_wr32(hw, CMICX_EPINTF_RELEASE_CREDITS, 1); + } + + return SHR_E_NONE; +} + +/*! + * Initialize HW + */ +static int +cmicx_pdma_hw_init(struct pdma_hw *hw) +{ + dev_mode_t mode = DEV_MODE_MAX; + uint32_t val; + + /* Temporarily upgrade work mode to get HW information in VNET mode. */ + if (hw->dev->mode == DEV_MODE_VNET) { + mode = DEV_MODE_VNET; + hw->dev->mode = DEV_MODE_UNET; + } + + /* Release Packet DMA credits to EP. */ + cmicx_pdma_credits_release(hw); + + hw->info.name = CMICX_DEV_NAME; + hw->info.dev_id = hw->dev->dev_id; + hw->info.num_cmcs = CMICX_PDMA_CMC_MAX; + hw->info.cmc_chans = CMICX_PDMA_CMC_CHAN; + hw->info.num_chans = CMICX_PDMA_CMC_MAX * CMICX_PDMA_CMC_CHAN; + hw->info.rx_dcb_size = CMICX_PDMA_DCB_SIZE; + hw->info.tx_dcb_size = CMICX_PDMA_DCB_SIZE; + hw->hdls.reg_rd32(hw, CMICX_EP_TO_CPU_HEADER_SIZE, &val); + hw->info.rx_ph_size = (val & 0xf) * 8; + hw->info.tx_ph_size = CMICX_TX_PKT_HDR_SIZE; + + /* Restore work mode to VNET. */ + if (mode == DEV_MODE_VNET) { + hw->dev->mode = DEV_MODE_VNET; + } + + return SHR_E_NONE; +} + +/*! + * Configure HW + */ +static int +cmicx_pdma_hw_config(struct pdma_hw *hw) +{ + struct dev_ctrl *ctrl = &hw->dev->ctrl; + struct pdma_rx_queue *rxq = NULL; + struct pdma_tx_queue *txq = NULL; + uint32_t val, que_ctrl; + int grp, que; + uint32_t qi; + int ip_if_hdr_endian = 0; + + for (qi = 0; qi < ctrl->nb_rxq; qi++) { + rxq = (struct pdma_rx_queue *)ctrl->rx_queue[qi]; + grp = rxq->group_id; + que = rxq->chan_id % CMICX_PDMA_CMC_CHAN; + que_ctrl = ctrl->grp[grp].que_ctrl[que]; + + hw->hdls.reg_wr32(hw, CMICX_PDMA_IRQ_STAT_CLR(grp), CMICX_PDMA_IRQ_MASK(que)); + val = 0; + if (que_ctrl & PDMA_PKT_BYTE_SWAP) { + val |= CMICX_PDMA_PKT_BIG_ENDIAN; + } + if (que_ctrl & PDMA_OTH_BYTE_SWAP) { + val |= CMICX_PDMA_DESC_BIG_ENDIAN; + } + if (que_ctrl & PDMA_HDR_BYTE_SWAP) { + val |= CMICX_PDMA_HDR_BIG_ENDIAN; + } + if (!(hw->dev->flags & PDMA_CHAIN_MODE)) { + val |= CMICX_PDMA_CONTINUOUS; + } + if (hw->dev->flags & PDMA_DESC_PREFETCH) { + val |= CMICX_PDMA_CONTINUOUS_DESC; + } + val |= CMICX_PDMA_INTR_ON_DESC; + hw->hdls.reg_wr32(hw, CMICX_PDMA_CTRL(grp, que), val); + } + + for (qi = 0; qi < ctrl->nb_txq; qi++) { + txq = (struct pdma_tx_queue *)ctrl->tx_queue[qi]; + grp = txq->group_id; + que = txq->chan_id % CMICX_PDMA_CMC_CHAN; + que_ctrl = ctrl->grp[grp].que_ctrl[que]; + + hw->hdls.reg_wr32(hw, CMICX_PDMA_IRQ_STAT_CLR(grp), CMICX_PDMA_IRQ_MASK(que)); + val = 0; + if (que_ctrl & PDMA_PKT_BYTE_SWAP) { + val |= CMICX_PDMA_PKT_BIG_ENDIAN; + val |= CMICX_PDMA_HDR_BIG_ENDIAN; + ip_if_hdr_endian = 1; + } + if (que_ctrl & PDMA_OTH_BYTE_SWAP) { + val |= CMICX_PDMA_DESC_BIG_ENDIAN; + } + if (que_ctrl & PDMA_HDR_BYTE_SWAP) { + ip_if_hdr_endian = 1; + } + if (!(hw->dev->flags & PDMA_CHAIN_MODE)) { + val |= CMICX_PDMA_CONTINUOUS; + } + if (hw->dev->flags & PDMA_DESC_PREFETCH) { + val |= CMICX_PDMA_CONTINUOUS_DESC; + } + val |= CMICX_PDMA_INTR_ON_DESC | CMICX_PDMA_DIR; + hw->hdls.reg_wr32(hw, CMICX_PDMA_CTRL(grp, que), val); + } + + if (ip_if_hdr_endian == 1) { + hw->hdls.reg_rd32(hw, CMICX_TOP_CONFIG, &val); + val |= 0x80; + hw->hdls.reg_wr32(hw, CMICX_TOP_CONFIG, val); + } + + return SHR_E_NONE; +} + +/*! + * Reset HW + */ +static int +cmicx_pdma_hw_reset(struct pdma_hw *hw) +{ + int gi, qi; + + for (gi = 0; gi < hw->dev->num_groups; gi++) { + if (!hw->dev->ctrl.grp[gi].attached) { + continue; + } + for (qi = 0; qi < CMICX_PDMA_CMC_CHAN; qi++) { + if (1 << qi & hw->dev->ctrl.grp[gi].bm_rxq || + 1 << qi & hw->dev->ctrl.grp[gi].bm_txq) { + hw->hdls.reg_wr32(hw, CMICX_PDMA_CTRL(gi, qi), 0); + } + } + } + + return SHR_E_NONE; +} + +/*! + * Start a channel + */ +static int +cmicx_pdma_chan_start(struct pdma_hw *hw, int chan) +{ + uint32_t val; + int grp, que; + + grp = chan / CMICX_PDMA_CMC_CHAN; + que = chan % CMICX_PDMA_CMC_CHAN; + + hw->hdls.reg_rd32(hw, CMICX_PDMA_CTRL(grp, que), &val); + val |= CMICX_PDMA_ENABLE; + hw->hdls.reg_wr32(hw, CMICX_PDMA_CTRL(grp, que), val); + + MEMORY_BARRIER; + + return SHR_E_NONE; +} + +/*! + * Stop a channel + */ +static int +cmicx_pdma_chan_stop(struct pdma_hw *hw, int chan) +{ + uint32_t val; + int grp, que; + int retry = CMICX_HW_RETRY_TIMES; + + grp = chan / CMICX_PDMA_CMC_CHAN; + que = chan % CMICX_PDMA_CMC_CHAN; + + hw->hdls.reg_rd32(hw, CMICX_PDMA_CTRL(grp, que), &val); + val |= CMICX_PDMA_ENABLE | CMICX_PDMA_ABORT; + hw->hdls.reg_wr32(hw, CMICX_PDMA_CTRL(grp, que), val); + + MEMORY_BARRIER; + + do { + val = ~CMICX_PDMA_IS_ACTIVE; + hw->hdls.reg_rd32(hw, CMICX_PDMA_STAT(grp, que), &val); + } while ((val & CMICX_PDMA_IS_ACTIVE) && (--retry > 0)); + + hw->hdls.reg_rd32(hw, CMICX_PDMA_CTRL(grp, que), &val); + val &= ~(CMICX_PDMA_ENABLE | CMICX_PDMA_ABORT); + hw->hdls.reg_wr32(hw, CMICX_PDMA_CTRL(grp, que), val); + + hw->hdls.reg_wr32(hw, CMICX_PDMA_IRQ_STAT_CLR(grp), CMICX_PDMA_IRQ_MASK(que)); + + MEMORY_BARRIER; + + return SHR_E_NONE; +} + +/*! + * Setup a channel + */ +static int +cmicx_pdma_chan_setup(struct pdma_hw *hw, int chan, uint64_t addr) +{ + int grp, que; + + grp = chan / CMICX_PDMA_CMC_CHAN; + que = chan % CMICX_PDMA_CMC_CHAN; + + hw->hdls.reg_wr32(hw, CMICX_PDMA_DESC_LO(grp, que), addr); + hw->hdls.reg_wr32(hw, CMICX_PDMA_DESC_HI(grp, que), DMA_TO_BUS_HI(addr >> 32)); + + MEMORY_BARRIER; + + return SHR_E_NONE; +} + +/*! + * Set halt point for a channel + */ +static int +cmicx_pdma_chan_goto(struct pdma_hw *hw, int chan, uint64_t addr) +{ + int grp, que; + + grp = chan / CMICX_PDMA_CMC_CHAN; + que = chan % CMICX_PDMA_CMC_CHAN; + + hw->hdls.reg_wr32(hw, CMICX_PDMA_DESC_HALT_LO(grp, que), addr); + hw->hdls.reg_wr32(hw, CMICX_PDMA_DESC_HALT_HI(grp, que), DMA_TO_BUS_HI(addr >> 32)); + + MEMORY_BARRIER; + + return SHR_E_NONE; +} + +/*! + * Clear a channel + */ +static int +cmicx_pdma_chan_clear(struct pdma_hw *hw, int chan) +{ + int grp, que; + + grp = chan / CMICX_PDMA_CMC_CHAN; + que = chan % CMICX_PDMA_CMC_CHAN; + + hw->hdls.reg_wr32(hw, CMICX_PDMA_IRQ_STAT_CLR(grp), CMICX_PDMA_IRQ_CTRLD_INTR(que)); + + MEMORY_BARRIER; + + return SHR_E_NONE; +} + +/*! + * Get interrupt number for a channel + */ +static int +cmicx_pdma_chan_intr_num_get(struct pdma_hw *hw, int chan) +{ + int grp, que, start_num, mask_shift; + + grp = chan / CMICX_PDMA_CMC_CHAN; + que = chan % CMICX_PDMA_CMC_CHAN; + + mask_shift = 0; + if (grp > 0) { + mask_shift = CMICX_IRQ_MASK_SHIFT + grp * 32; + } + start_num = CMICX_IRQ_START_NUM + mask_shift; + + return start_num + (que * CMICX_IRQ_NUM_OFFSET); +} + +/*! + * Enable interrupt for a channel + */ +static int +cmicx_pdma_chan_intr_enable(struct pdma_hw *hw, int chan) +{ + int grp, que; + + grp = chan / CMICX_PDMA_CMC_CHAN; + que = chan % CMICX_PDMA_CMC_CHAN; + + cmicx_pdma_intr_enable(hw, grp, que, CMICX_PDMA_IRQ_CTRLD_INTR(que)); + + return SHR_E_NONE; +} + +/*! + * Disable interrupt for a channel + */ +static int +cmicx_pdma_chan_intr_disable(struct pdma_hw *hw, int chan) +{ + int grp, que; + + grp = chan / CMICX_PDMA_CMC_CHAN; + que = chan % CMICX_PDMA_CMC_CHAN; + + cmicx_pdma_intr_disable(hw, grp, que, CMICX_PDMA_IRQ_CTRLD_INTR(que)); + + return SHR_E_NONE; +} + +/*! + * Query interrupt status for a channel + * + * In group mode (interrupt processing per CMC), need to query each channel's + * interrupt status. + * + */ +static int +cmicx_pdma_chan_intr_query(struct pdma_hw *hw, int chan) +{ + uint32_t val; + int grp, que; + + grp = chan / CMICX_PDMA_CMC_CHAN; + que = chan % CMICX_PDMA_CMC_CHAN; + + hw->hdls.reg_rd32(hw, CMICX_PDMA_IRQ_STAT(grp), &val); + + return val & CMICX_PDMA_IRQ_CTRLD_INTR(que); +} + +/*! + * Check interrupt validity for a channel + * + * In group mode (interrupt processing per CMC), need to check each channel's + * interrupt validity based on its interrupt mask. + * + */ +static int +cmicx_pdma_chan_intr_check(struct pdma_hw *hw, int chan) +{ + int grp, que; + + grp = chan / CMICX_PDMA_CMC_CHAN; + que = chan % CMICX_PDMA_CMC_CHAN; + + if (!(hw->dev->ctrl.grp[grp].irq_mask & CMICX_PDMA_IRQ_CTRLD_INTR(que))) { + return 0; + } + + return cmicx_pdma_chan_intr_query(hw, chan); +} + +/*! + * Coalesce interrupt for a channel + */ +static int +cmicx_pdma_chan_intr_coalesce(struct pdma_hw *hw, int chan, int count, int timer) +{ + uint32_t val; + int grp, que; + + grp = chan / CMICX_PDMA_CMC_CHAN; + que = chan % CMICX_PDMA_CMC_CHAN; + + val = CMICX_PDMA_INTR_COAL_ENA | + CMICX_PDMA_INTR_THRESH(count) | + CMICX_PDMA_INTR_TIMER(timer); + hw->hdls.reg_wr32(hw, CMICX_PDMA_INTR_COAL(grp, que), val); + + return SHR_E_NONE; +} + +/*! + * Dump registers for a channel + */ +static int +cmicx_pdma_chan_reg_dump(struct pdma_hw *hw, int chan) +{ + uint32_t val; + int grp, que; + + grp = chan / CMICX_PDMA_CMC_CHAN; + que = chan % CMICX_PDMA_CMC_CHAN; + + hw->hdls.reg_rd32(hw, CMICX_PDMA_CTRL(grp, que), &val); + CNET_PR("CMIC_CMC%d_DMA_CH%d_CTRL: 0x%08x\n", grp, que, val); + + hw->hdls.reg_rd32(hw, CMICX_PDMA_DESC_LO(grp, que), &val); + CNET_PR("CMIC_CMC%d_DMA_CH%d_DESC_LO: 0x%08x\n", grp, que, val); + + hw->hdls.reg_rd32(hw, CMICX_PDMA_DESC_HI(grp, que), &val); + CNET_PR("CMIC_CMC%d_DMA_CH%d_DESC_HI: 0x%08x\n", grp, que, val); + + hw->hdls.reg_rd32(hw, CMICX_PDMA_CURR_DESC_LO(grp, que), &val); + CNET_PR("CMIC_CMC%d_DMA_CH%d_CURR_DESC_LO: 0x%08x\n", grp, que, val); + + hw->hdls.reg_rd32(hw, CMICX_PDMA_CURR_DESC_HI(grp, que), &val); + CNET_PR("CMIC_CMC%d_DMA_CH%d_CURR_DESC_HI: 0x%08x\n", grp, que, val); + + hw->hdls.reg_rd32(hw, CMICX_PDMA_DESC_HALT_LO(grp, que), &val); + CNET_PR("CMIC_CMC%d_DMA_CH%d_DESC_HALT_ADDR_LO: 0x%08x\n", grp, que, val); + + hw->hdls.reg_rd32(hw, CMICX_PDMA_DESC_HALT_HI(grp, que), &val); + CNET_PR("CMIC_CMC%d_DMA_CH%d_DESC_HALT_ADDR_HI: 0x%08x\n", grp, que, val); + + hw->hdls.reg_rd32(hw, CMICX_PDMA_COS_CTRL_RX0(grp, que), &val); + CNET_PR("CMIC_CMC%d_DMA_CH%d_COS_CTRL_RX_0: 0x%08x\n", grp, que, val); + + hw->hdls.reg_rd32(hw, CMICX_PDMA_COS_CTRL_RX1(grp, que), &val); + CNET_PR("CMIC_CMC%d_DMA_CH%d_COS_CTRL_RX_1: 0x%08x\n", grp, que, val); + + hw->hdls.reg_rd32(hw, CMICX_PDMA_INTR_COAL(grp, que), &val); + CNET_PR("CMIC_CMC%d_DMA_CH%d_INTR_COAL: 0x%08x\n", grp, que, val); + + hw->hdls.reg_rd32(hw, CMICX_PDMA_RBUF_THRE(grp, que), &val); + CNET_PR("CMIC_CMC%d_DMA_CH%d_RXBUF_THRESHOLD_CONFIG: 0x%08x\n", grp, que, val); + + hw->hdls.reg_rd32(hw, CMICX_PDMA_STAT(grp, que), &val); + CNET_PR("CMIC_CMC%d_DMA_CH%d_STAT: 0x%08x\n", grp, que, val); + + hw->hdls.reg_rd32(hw, CMICX_PDMA_COUNT_RX(grp, que), &val); + CNET_PR("CMIC_CMC%d_DMA_CH%d_PKT_COUNT_RXPKT: 0x%08x\n", grp, que, val); + + hw->hdls.reg_rd32(hw, CMICX_PDMA_COUNT_TX(grp, que), &val); + CNET_PR("CMIC_CMC%d_DMA_CH%d_PKT_COUNT_TXPKT: 0x%08x\n", grp, que, val); + + hw->hdls.reg_rd32(hw, CMICX_PDMA_COUNT_RX_DROP(grp, que), &val); + CNET_PR("CMIC_CMC%d_DMA_CH%d_PKT_COUNT_RXPKT_DROP: 0x%08x\n", grp, que, val); + + hw->hdls.reg_rd32(hw, CMICX_PDMA_IRQ_STAT(grp), &val); + CNET_PR("CMIC_CMC%d_IRQ_STAT: 0x%08x\n", grp, val); + + hw->hdls.reg_rd32(hw, CMICX_PDMA_IRQ_STAT_CLR(grp), &val); + CNET_PR("CMIC_CMC%d_IRQ_STAT_CLR: 0x%08x\n", grp, val); + + val = hw->dev->ctrl.grp[grp].irq_mask; + CNET_PR("CMIC_CMC%d_IRQ_ENAB: 0x%08x\n", grp, val); + + hw->hdls.reg_rd32(hw, CMICX_EP_TO_CPU_HEADER_SIZE, &val); + CNET_PR("CMIC_EP_TO_CPU_HEADER_SIZE: 0x%08x\n", val); + + return SHR_E_NONE; +} + +/*! + * Initialize function pointers + */ +int +bcmcnet_cmicx_pdma_hw_hdls_init(struct pdma_hw *hw) +{ + if (!hw) { + return SHR_E_PARAM; + } + + hw->hdls.reg_rd32 = cmicx_pdma_reg_read32; + hw->hdls.reg_wr32 = cmicx_pdma_reg_write32; + hw->hdls.hw_init = cmicx_pdma_hw_init; + hw->hdls.hw_config = cmicx_pdma_hw_config; + hw->hdls.hw_reset = cmicx_pdma_hw_reset; + hw->hdls.chan_start = cmicx_pdma_chan_start; + hw->hdls.chan_stop = cmicx_pdma_chan_stop; + hw->hdls.chan_setup = cmicx_pdma_chan_setup; + hw->hdls.chan_goto = cmicx_pdma_chan_goto; + hw->hdls.chan_clear = cmicx_pdma_chan_clear; + hw->hdls.chan_intr_num_get = cmicx_pdma_chan_intr_num_get; + hw->hdls.chan_intr_enable = cmicx_pdma_chan_intr_enable; + hw->hdls.chan_intr_disable = cmicx_pdma_chan_intr_disable; + hw->hdls.chan_intr_query = cmicx_pdma_chan_intr_query; + hw->hdls.chan_intr_check = cmicx_pdma_chan_intr_check; + hw->hdls.chan_intr_coalesce = cmicx_pdma_chan_intr_coalesce; + hw->hdls.chan_reg_dump = cmicx_pdma_chan_reg_dump; + + return SHR_E_NONE; +} + diff --git a/platform/broadcom/saibcm-modules/sdklt/bcmcnet/hmi/cmicx/bcmcnet_cmicx_pdma_rxtx.c b/platform/broadcom/saibcm-modules/sdklt/bcmcnet/hmi/cmicx/bcmcnet_cmicx_pdma_rxtx.c new file mode 100644 index 00000000000..651728465d5 --- /dev/null +++ b/platform/broadcom/saibcm-modules/sdklt/bcmcnet/hmi/cmicx/bcmcnet_cmicx_pdma_rxtx.c @@ -0,0 +1,1094 @@ +/*! \file bcmcnet_cmicx_pdma_rxtx.c + * + * Utility routines for BCMCNET hardware (CMICx) specific Rx/Tx. + * + * Here are the CMIC specific Rx/Tx routines including DCBs resource allocation + * and clean up, DCBs configuration, Rx buffers allocation, Tx buffers release, + * Rx/Tx packets processing, etc. + * They are shared among all the modes (UNET, KNET, VNET, HNET) and in both of + * user space and kernel space. + * + * The driver uses a ring of DCBs per DMA channel based on Continuous DMA mode. + * The beginning is written to register pointing to the physical address of the + * start of the ring. The ring size is maintained by the driver. A HALT DCB + * physical address is written to DMA register timely to indicate how many DCBs + * can be handled by HW. + * + * When a packet is received, an interrupt is triggered. The handler will go + * through the Rx DCB ring to process the current completed DCB and every + * subsequent DCBs until no one is left. The received packet is processed and + * passed up to the high level SW. After that, a new buffer is allocated and + * the DCB is updated for receiving a new packet. A new HALT DCB is selected + * and its physical address is written to DMA register. + * + * When a packet is transmitted, the driver starts where it left off last time + * in the Tx DCB ring, updates the DCB and writes its physical address to DMA + * register so as to start DMA. Once the transmitting is finished, the handler + * is informed to clean up the buffer based on the work mode. In KNET or HNET + * mode, an interrupt will be triggered. Polling mode is used in CNET or VNET + * mode, the buffers will be cleaned up when the number of dirty DCBs reaches + * a pre-defined threshold. + * + * In VNET and HNET modes, DCB updating between virtual ring and real ring and + * a IOCTL based notification mechanism are involved. The hypervisor in kernel + * emulates the DMA HW behaviors to update DCBs in virtual network and inform + * the handler something happened. Likewise, the hypervisor updates itself real + * DCB ring from the virtual ring to start DMA for transmitting a packet once a + * notification is received from the virtual network. + * + */ +/* + * $Copyright: Copyright 2018-2020 Broadcom. All rights reserved. + * The term 'Broadcom' refers to Broadcom Inc. and/or its subsidiaries. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * version 2 as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * A copy of the GNU General Public License version 2 (GPLv2) can + * be found in the LICENSES folder.$ + */ + +#include +#include +#include +#include +#include + +/*! + * Configure Rx descriptor + */ +static inline void +cmicx_rx_desc_config(struct cmicx_rx_desc *rd, uint64_t addr, uint32_t len) +{ + uint32_t ctrl; + + rd->addr_lo = addr; + rd->addr_hi = DMA_TO_BUS_HI(addr >> 32); + rd->status = 0; + ctrl = rd->ctrl; + ctrl &= CMICX_DESC_CTRL_REMAIN(0xf); + ctrl |= CMICX_DESC_CTRL_CNTLD_INTR | CMICX_DESC_CTRL_CHAIN | + CMICX_DESC_CTRL_LEN(len); + rd->ctrl = ctrl; +} + +/*! + * Configure Tx descriptor + */ +static inline void +cmicx_tx_desc_config(struct cmicx_tx_desc *td, uint64_t addr, uint32_t len, uint32_t flags) +{ + uint32_t ctrl; + + td->addr_lo = addr; + td->addr_hi = DMA_TO_BUS_HI(addr >> 32); + td->status = 0; + ctrl = td->ctrl; + ctrl &= CMICX_DESC_CTRL_REMAIN(0xf); + ctrl |= CMICX_DESC_CTRL_CNTLD_INTR | CMICX_DESC_CTRL_CHAIN | + CMICX_DESC_CTRL_FLAGS(flags) | CMICX_DESC_CTRL_LEN(len); + td->ctrl = ctrl; +} + +/*! + * Configure Rx reload descriptor + */ +static inline void +cmicx_rx_rldesc_config(struct cmicx_rx_desc *rd, uint64_t addr) +{ + rd->addr_lo = addr; + rd->addr_hi = DMA_TO_BUS_HI(addr >> 32); + rd->status = 0; + rd->ctrl = CMICX_DESC_CTRL_CNTLD_INTR | CMICX_DESC_CTRL_CHAIN | + CMICX_DESC_CTRL_RELOAD; +} + +/*! + * Configure Tx reload descriptor + */ +static inline void +cmicx_tx_rldesc_config(struct cmicx_tx_desc *td, uint64_t addr) +{ + td->addr_lo = addr; + td->addr_hi = DMA_TO_BUS_HI(addr >> 32); + td->status = 0; + td->ctrl = CMICX_DESC_CTRL_CNTLD_INTR | CMICX_DESC_CTRL_CHAIN | + CMICX_DESC_CTRL_RELOAD; +} + +/*! + * Chain Rx descriptor + */ +static inline void +cmicx_rx_desc_chain(struct cmicx_rx_desc *rd, int chain) +{ + if (chain) { + rd->ctrl |= CMICX_DESC_CTRL_CHAIN; + } else { + rd->ctrl &= ~CMICX_DESC_CTRL_CHAIN; + } +} + +/*! + * Chain Tx descriptor + */ +static inline void +cmicx_tx_desc_chain(struct cmicx_tx_desc *td, int chain) +{ + if (chain) { + td->ctrl |= CMICX_DESC_CTRL_CHAIN; + } else { + td->ctrl &= ~CMICX_DESC_CTRL_CHAIN; + } +} + +/*! + * Set Rx descriptor remain + */ +static inline void +cmicx_rx_desc_remain(struct cmicx_rx_desc *rd, uint32_t rm) +{ + rd->ctrl &= ~CMICX_DESC_CTRL_REMAIN(0xf); + rd->ctrl |= CMICX_DESC_CTRL_REMAIN(rm); +} + +/*! + * Set Tx descriptor remain + */ +static inline void +cmicx_tx_desc_remain(struct cmicx_tx_desc *td, uint32_t rm) +{ + td->ctrl &= ~CMICX_DESC_CTRL_REMAIN(0xf); + td->ctrl |= CMICX_DESC_CTRL_REMAIN(rm); +} + +/*! + * Get unused descriptors in a Rx ring + */ +static inline int +cmicx_pdma_rx_ring_unused(struct pdma_rx_queue *rxq) +{ + /* Leave one descriptor unused so as not to halt */ + return rxq->curr > rxq->halt ? + rxq->curr - rxq->halt - 1 : + rxq->nb_desc + rxq->curr - rxq->halt - 1; +} + +/*! + * Get unused descriptors in a Tx ring + */ +static inline int +cmicx_pdma_tx_ring_unused(struct pdma_tx_queue *txq) +{ + /* Leave one descriptor unused so as not to halt */ + return txq->dirt > txq->curr ? + txq->dirt - txq->curr - 1 : + txq->nb_desc + txq->dirt - txq->curr - 1; +} + +/*! + * Initialize Rx descriptors + */ +static int +cmicx_pdma_rx_desc_init(struct pdma_hw *hw, struct pdma_rx_queue *rxq) +{ + struct pdma_dev *dev = hw->dev; + struct pdma_buf_mngr *bm = (struct pdma_buf_mngr *)dev->ctrl.buf_mngr; + struct cmicx_rx_desc *ring = (struct cmicx_rx_desc *)rxq->ring; + dma_addr_t addr; + uint32_t di, rm; + int rv; + + for (di = 0; di < rxq->nb_desc; di++) { + if (!rxq->pbuf[di].dma) { + /* Allocate pktbuf for ring entry */ + rv = bm->rx_buf_alloc(dev, rxq, &rxq->pbuf[di]); + if (SHR_FAILURE(rv)) { + goto cleanup; + } + } + /* Config receive descriptor ring */ + bm->rx_buf_dma(dev, rxq, &rxq->pbuf[di], &addr); + cmicx_rx_desc_config(&ring[di], addr, rxq->buf_size); + rm = (rxq->nb_desc - di) >= CMICX_DESC_REMAIN_MAX ? + CMICX_DESC_REMAIN_MAX : rxq->nb_desc - di; + cmicx_rx_desc_remain(&ring[di], rm); + if (hw->dev->flags & PDMA_CHAIN_MODE && di == rxq->nb_desc - 1) { + cmicx_rx_desc_chain(&ring[di], 0); + } + } + /* Config the last descriptor in the ring as reload descriptor */ + cmicx_rx_rldesc_config(&ring[di], rxq->ring_addr); + + rxq->curr = 0; + rxq->halt = rxq->state & PDMA_RX_BATCH_REFILL ? 0 : rxq->nb_desc; + + rxq->halt_addr = rxq->ring_addr + sizeof(struct cmicx_rx_desc) * di; + hw->hdls.chan_goto(hw, rxq->chan_id, rxq->halt_addr); + hw->hdls.chan_setup(hw, rxq->chan_id, rxq->ring_addr); + + return SHR_E_NONE; + +cleanup: + for (di = 0; di < rxq->nb_desc; di++) { + if (rxq->pbuf[di].dma) { + bm->rx_buf_free(dev, rxq, &rxq->pbuf[di]); + } + cmicx_rx_desc_config(&ring[di], 0, 0); + } + + CNET_PR("RX: Failed to allocate mem\n"); + + return SHR_E_MEMORY; +} + +/*! + * Cleanup Rx descriptors + */ +static int +cmicx_pdma_rx_desc_clean(struct pdma_hw *hw, struct pdma_rx_queue *rxq) +{ + struct pdma_dev *dev = hw->dev; + struct pdma_buf_mngr *bm = (struct pdma_buf_mngr *)dev->ctrl.buf_mngr; + struct cmicx_rx_desc *ring = (struct cmicx_rx_desc *)rxq->ring; + uint32_t di; + + /* Go through all the descriptors and free pktbuf */ + for (di = 0; di < rxq->nb_desc; di++) { + if (rxq->pbuf[di].dma) { + bm->rx_buf_free(dev, rxq, &rxq->pbuf[di]); + } + cmicx_rx_desc_config(&ring[di], 0, 0); + } + + rxq->curr = 0; + rxq->halt = 0; + + return SHR_E_NONE; +} + +/*! + * Initialize Tx descriptors + */ +static int +cmicx_pdma_tx_desc_init(struct pdma_hw *hw, struct pdma_tx_queue *txq) +{ + struct pdma_dev *dev = hw->dev; + struct pdma_buf_mngr *bm = (struct pdma_buf_mngr *)dev->ctrl.buf_mngr; + struct cmicx_tx_desc *ring = (struct cmicx_tx_desc *)txq->ring; + uint32_t di, rm; + + for (di = 0; di < txq->nb_desc; di++) { + if (txq->pbuf[di].dma) { + bm->tx_buf_free(dev, txq, &txq->pbuf[di]); + } + /* Config transmit descriptor ring */ + cmicx_tx_desc_config(&ring[di], 0, 0, 0); + rm = (txq->nb_desc - di) >= CMICX_DESC_REMAIN_MAX ? + CMICX_DESC_REMAIN_MAX : txq->nb_desc - di; + cmicx_tx_desc_remain(&ring[di], rm); + if (hw->dev->flags & PDMA_CHAIN_MODE) { + cmicx_tx_desc_chain(&ring[di], 0); + } + } + /* Config the last descriptor in the ring as reload descriptor */ + cmicx_tx_rldesc_config(&ring[di], txq->ring_addr); + + txq->curr = 0; + txq->dirt = 0; + txq->halt = 0; + + txq->halt_addr = txq->ring_addr; + hw->hdls.chan_goto(hw, txq->chan_id, txq->halt_addr); + hw->hdls.chan_setup(hw, txq->chan_id, txq->ring_addr); + + return SHR_E_NONE; +} + +/*! + * Cleanup Tx descriptors + */ +static int +cmicx_pdma_tx_desc_clean(struct pdma_hw *hw, struct pdma_tx_queue *txq) +{ + struct pdma_dev *dev = hw->dev; + struct pdma_buf_mngr *bm = (struct pdma_buf_mngr *)dev->ctrl.buf_mngr; + struct cmicx_tx_desc *ring = (struct cmicx_tx_desc *)txq->ring; + uint32_t di; + + /* Go through all the descriptors and free pktbuf */ + for (di = 0; di < txq->nb_desc; di++) { + if (txq->pbuf[di].dma) { + bm->tx_buf_free(dev, txq, &txq->pbuf[di]); + } + cmicx_tx_desc_config(&ring[di], 0, 0, 0); + } + + txq->curr = 0; + txq->dirt = 0; + txq->halt = 0; + + return SHR_E_NONE; +} + +/*! + * Process Rx vring + */ +static int +cmicx_pdma_rx_vring_process(struct pdma_hw *hw, struct pdma_rx_queue *rxq, + struct pdma_rx_buf *pbuf) +{ + struct pdma_dev *dev = hw->dev; + struct cmicx_rx_desc *ring = (struct cmicx_rx_desc *)rxq->ring; + struct pdma_rx_queue *vrxq = NULL; + struct cmicx_rx_desc *vring = NULL; + struct pkt_hdr *pkh = &pbuf->pkb->pkh; + uint64_t buf_addr; + + vrxq = (struct pdma_rx_queue *)dev->ctrl.vnet_rxq[rxq->queue_id]; + vring = (struct cmicx_rx_desc *)vrxq->ring; + if (!vring) { + rxq->stats.dropped++; + return SHR_E_UNAVAIL; + } + + if (vring[vrxq->curr].status & CMICX_DESC_STAT_RTX_DONE) { + dev->xnet_wake(dev); + return SHR_E_BUSY; + } + + /* Copy descriptor and packet to vring */ + buf_addr = BUS_TO_DMA_HI(vring[vrxq->curr].addr_hi); + buf_addr = buf_addr << 32 | vring[vrxq->curr].addr_lo; + sal_memcpy(dev->sys_p2v(dev, buf_addr), &pbuf->pkb->data, + pkh->meta_len + pkh->data_len); + vring[vrxq->curr].status = ring[rxq->curr].status; + + MEMORY_BARRIER; + + /* Notify VNET to process if needed */ + if (!vring[(vrxq->curr + vrxq->nb_desc - 1) % vrxq->nb_desc].status) { + dev->xnet_wake(dev); + } + vrxq->curr = (vrxq->curr + 1) % vrxq->nb_desc; + + return SHR_E_NONE; +} + +/*! + * Refill Rx ring + */ +static int +cmicx_pdma_rx_ring_refill(struct pdma_hw *hw, struct pdma_rx_queue *rxq) +{ + struct pdma_dev *dev = hw->dev; + struct pdma_buf_mngr *bm = (struct pdma_buf_mngr *)dev->ctrl.buf_mngr; + struct cmicx_rx_desc *ring = (struct cmicx_rx_desc *)rxq->ring; + struct pdma_rx_buf *pbuf = NULL; + int unused = cmicx_pdma_rx_ring_unused(rxq); + dma_addr_t addr; + uint32_t halt; + int rv; + + for (halt = rxq->halt; halt < rxq->halt + unused; halt++) { + pbuf = &rxq->pbuf[halt % rxq->nb_desc]; + /* Allocate a new pktbuf */ + if (!bm->rx_buf_avail(dev, rxq, pbuf)) { + rv = bm->rx_buf_alloc(dev, rxq, pbuf); + if (SHR_FAILURE(rv)) { + rxq->halt = halt % rxq->nb_desc; + rxq->stats.nomems++; + goto fail; + } + } + /* Setup the new descriptor */ + bm->rx_buf_dma(dev, rxq, pbuf, &addr); + cmicx_rx_desc_config(&ring[halt % rxq->nb_desc], addr, rxq->buf_size); + if (dev->flags & PDMA_CHAIN_MODE && halt % rxq->nb_desc == rxq->nb_desc - 1) { + cmicx_rx_desc_chain(&ring[halt % rxq->nb_desc], 0); + } + } + + sal_spinlock_lock(rxq->lock); + rxq->halt = halt % rxq->nb_desc; + if (!(rxq->state & PDMA_RX_QUEUE_XOFF)) { + /* Descriptor cherry pick */ + rxq->halt_addr = rxq->ring_addr + sizeof(struct cmicx_rx_desc) * rxq->halt; + hw->hdls.chan_goto(hw, rxq->chan_id, rxq->halt_addr); + } + sal_spinlock_unlock(rxq->lock); + + return SHR_E_NONE; + +fail: + CNET_PR("RX: Failed to allocate mem\n"); + + return SHR_E_MEMORY; +} + +/*! + * \brief Clean Rx ring + * + * \param [in] hw HW structure point. + * \param [in] rxq Rx queue structure point. + * \param [in] budget Polling budget. + * + * \retval SHR_E_NONE No errors. + * \retval SHR_E_XXXX Operation failed. + */ +static int +cmicx_pdma_rx_ring_clean(struct pdma_hw *hw, struct pdma_rx_queue *rxq, int budget) +{ + struct pdma_dev *dev = hw->dev; + struct pdma_buf_mngr *bm = (struct pdma_buf_mngr *)dev->ctrl.buf_mngr; + struct cmicx_rx_desc *ring = (struct cmicx_rx_desc *)rxq->ring; + struct pdma_rx_buf *pbuf = NULL; + struct pkt_hdr *pkh = NULL; + dma_addr_t addr; + uint32_t stat, curr; + int len, done = 0; + int rv; + + curr = rxq->curr; + while (CMICX_DESC_STAT_DONE(ring[curr].status)) { + if (dev->mode == DEV_MODE_VNET && rxq->state & PDMA_RX_QUEUE_XOFF) { + break; + } + if (!(rxq->state & PDMA_RX_BATCH_REFILL) && + !(rxq->state & PDMA_RX_QUEUE_XOFF)) { + /* Descriptor cherry pick */ + rxq->halt_addr = rxq->ring_addr + sizeof(struct cmicx_rx_desc) * curr; + hw->hdls.chan_goto(hw, rxq->chan_id, rxq->halt_addr); + rxq->halt = curr; + } + if (done == budget) { + break; + } + + /* Get the current pktbuf to process */ + pbuf = &rxq->pbuf[curr]; + stat = ring[curr].status; + len = CMICX_DESC_STAT_LEN(stat); + pkh = bm->rx_buf_get(dev, rxq, pbuf, len); + if (!pkh) { + rxq->stats.nomems++; + goto fail; + } + + /* Setup packet header */ + pkh->data_len = len - hw->info.rx_ph_size; + pkh->meta_len = hw->info.rx_ph_size; + pkh->queue_id = rxq->queue_id; + pkh->attrs = CMICX_DESC_STAT_FLAGS(stat); + + /* Send up the packet */ + rv = dev->pkt_recv(dev, rxq->queue_id, (void *)pbuf->skb); + if (SHR_FAILURE(rv)) { + if (dev->mode == DEV_MODE_HNET && pkh->attrs & PDMA_RX_TO_VNET) { + rv = cmicx_pdma_rx_vring_process(hw, rxq, pbuf); + if (SHR_FAILURE(rv) && rv == SHR_E_BUSY) { + rxq->state |= PDMA_RX_QUEUE_BUSY; + return done; + } + } else { + rxq->stats.dropped++; + } + bm->rx_buf_put(dev, rxq, pbuf, len); + } + + /* Count the packets/bytes */ + rxq->stats.packets++; + rxq->stats.bytes += len; + + /* Count the errors if any */ + if (stat & CMICX_DESC_STAT_ERR_MASK) { + rxq->stats.errors++; + if (stat & CMICX_DESC_STAT_DATA_ERR) { + rxq->stats.data_errors++; + } + if (stat & CMICX_DESC_STAT_CELL_ERR) { + rxq->stats.cell_errors++; + } + } + + /* Setup the new descriptor */ + if (!(rxq->state & PDMA_RX_BATCH_REFILL)) { + if (!bm->rx_buf_avail(dev, rxq, pbuf)) { + rv = bm->rx_buf_alloc(dev, rxq, pbuf); + if (SHR_FAILURE(rv)) { + rxq->stats.nomems++; + goto fail; + } + } + bm->rx_buf_dma(dev, rxq, pbuf, &addr); + cmicx_rx_desc_config(&ring[curr], addr, rxq->buf_size); + if (dev->flags & PDMA_CHAIN_MODE && curr == rxq->nb_desc - 1) { + cmicx_rx_desc_chain(&ring[curr], 0); + } + } else { + cmicx_rx_desc_config(&ring[curr], 0, 0); + } + + /* Notify HNET to process if needed */ + if (dev->mode == DEV_MODE_VNET) { + MEMORY_BARRIER; + if (ring[(curr + rxq->nb_desc - 1) % rxq->nb_desc].status) { + dev->xnet_wake(dev); + } + } + + /* Update the indicators */ + if (!(rxq->state & PDMA_RX_BATCH_REFILL) && rxq->halt != curr) { + sal_spinlock_lock(rxq->lock); + if (!(rxq->state & PDMA_RX_QUEUE_XOFF)) { + /* Descriptor cherry pick */ + rxq->halt_addr = rxq->ring_addr + sizeof(struct cmicx_rx_desc) * curr; + hw->hdls.chan_goto(hw, rxq->chan_id, rxq->halt_addr); + rxq->halt = curr; + } + curr = (curr + 1) % rxq->nb_desc; + sal_spinlock_unlock(rxq->lock); + } else { + curr = (curr + 1) % rxq->nb_desc; + } + rxq->curr = curr; + done++; + + /* Restart DMA if in chain mode */ + if (dev->flags & PDMA_CHAIN_MODE) { + if (curr == 0 && !(rxq->state & PDMA_RX_QUEUE_XOFF)) { + hw->hdls.chan_stop(hw, rxq->chan_id); + hw->hdls.chan_start(hw, rxq->chan_id); + } + } + } + + /* One more poll for chain done in chain mode */ + if (dev->flags & PDMA_CHAIN_MODE) { + if (curr == rxq->nb_desc - 1 && done) { + done = budget; + } + } + + /* In batching mode, replenish all the unused descriptors */ + if (rxq->state & PDMA_RX_BATCH_REFILL && + cmicx_pdma_rx_ring_unused(rxq) >= (int)rxq->free_thresh) { + cmicx_pdma_rx_ring_refill(hw, rxq); + } + + /* Notify the other side to process */ + if (dev->mode == DEV_MODE_VNET || dev->mode == DEV_MODE_HNET) { + if (done) { + dev->xnet_wake(dev); + } + } + + return done; + +fail: + CNET_PR("RX: Failed to allocate mem\n"); + + return done; +} + +/*! + * Process Tx vring + */ +static int +cmicx_pdma_tx_vring_process(struct pdma_hw *hw, struct pdma_tx_queue *txq, + struct pdma_tx_buf *pbuf) +{ + struct pdma_dev *dev = hw->dev; + struct cmicx_tx_desc *ring = (struct cmicx_tx_desc *)txq->ring; + struct pdma_tx_queue *vtxq = NULL; + struct cmicx_tx_desc *vring = NULL; + + vtxq = (struct pdma_tx_queue *)dev->ctrl.vnet_txq[txq->queue_id]; + vring = (struct cmicx_tx_desc *)vtxq->ring; + if (!vring) { + return SHR_E_UNAVAIL; + } + + /* Update vring descriptor */ + vring[vtxq->dirt].status = ring[txq->dirt].status; + pbuf->dma = 0; + + MEMORY_BARRIER; + + /* Notify VNET to process if needed */ + if (!vring[(vtxq->dirt + vtxq->nb_desc - 1) % vtxq->nb_desc].status) { + dev->xnet_wake(dev); + } + vtxq->dirt = (vtxq->dirt + 1) % vtxq->nb_desc; + + return SHR_E_NONE; +} + +/*! + * \brief Clean Tx ring + * + * \param [in] hw HW structure point. + * \param [in] txq Tx queue structure point. + * \param [in] budget Polling budget. + * + * \retval SHR_E_NONE No errors. + * \retval SHR_E_XXXX Operation failed. + */ +static int +cmicx_pdma_tx_ring_clean(struct pdma_hw *hw, struct pdma_tx_queue *txq, int budget) +{ + struct pdma_dev *dev = hw->dev; + struct pdma_buf_mngr *bm = (struct pdma_buf_mngr *)dev->ctrl.buf_mngr; + struct cmicx_tx_desc *ring = (struct cmicx_tx_desc *)txq->ring; + uint32_t dirt, curr; + int done = 0; + + dirt = txq->dirt; + while (txq->pbuf[dirt].dma) { + if (!CMICX_DESC_STAT_DONE(ring[dirt].status)) { + break; + } + if (done == budget) { + break; + } + + if (dev->mode == DEV_MODE_HNET && !txq->pbuf[dirt].skb) { + cmicx_pdma_tx_vring_process(hw, txq, &txq->pbuf[dirt]); + } else { + /* Free the done pktbuf */ + bm->tx_buf_free(dev, txq, &txq->pbuf[dirt]); + } + + cmicx_tx_desc_config(&ring[dirt], 0, 0, 0); + + /* Update the indicators */ + dirt = (dirt + 1) % txq->nb_desc; + txq->dirt = dirt; + done++; + + /* Restart DMA if in chain mode */ + if (dev->flags & PDMA_CHAIN_MODE) { + sal_spinlock_lock(txq->lock); + curr = txq->curr; + if (dirt == txq->halt && dirt != curr) { + hw->hdls.chan_stop(hw, txq->chan_id); + cmicx_tx_desc_chain(&ring[(curr + txq->nb_desc - 1) % txq->nb_desc], 0); + hw->hdls.chan_setup(hw, txq->chan_id, + txq->ring_addr + sizeof(struct cmicx_tx_desc) * txq->halt); + hw->hdls.chan_start(hw, txq->chan_id); + txq->halt = curr; + } + sal_spinlock_unlock(txq->lock); + } + } + + /* One more poll for chain done in chain mode */ + if (dev->flags & PDMA_CHAIN_MODE) { + sal_spinlock_lock(txq->lock); + if (dirt != txq->halt) { + done = budget; + } + sal_spinlock_unlock(txq->lock); + } + + /* Resume Tx if any */ + sal_spinlock_lock(txq->lock); + if (cmicx_pdma_tx_ring_unused(txq) && txq->state & PDMA_TX_QUEUE_XOFF) { + txq->state &= ~PDMA_TX_QUEUE_XOFF; + sal_spinlock_unlock(txq->lock); + if (dev->tx_resume) { + dev->tx_resume(dev, txq->queue_id); + } else if (!(txq->state & PDMA_TX_QUEUE_POLL)) { + sal_sem_give(txq->sem); + } + return done; + } + sal_spinlock_unlock(txq->lock); + + return done; +} + +/*! + * Dump Rx ring + */ +static int +cmicx_pdma_rx_ring_dump(struct pdma_hw *hw, struct pdma_rx_queue *rxq) +{ + struct cmicx_rx_desc *ring = (struct cmicx_rx_desc *)rxq->ring; + struct cmicx_rx_desc *rd; + uint32_t di; + + CNET_PR("\nRX: queue=%d, chan=%d, curr=%d, halt=%d, halt@%p\n", + rxq->queue_id, rxq->chan_id, rxq->curr, rxq->halt, (void *)&ring[rxq->halt]); + CNET_PR("----------------------------------------------------------------\n"); + for (di = 0; di < rxq->nb_desc + 1; di++) { + rd = &ring[di]; + CNET_PR("DESC[%03d]: (%p)->%08x %08x %08x %08x\n", + di, (void *)(unsigned long)(rxq->ring_addr + di * CMICX_PDMA_DCB_SIZE), + rd->addr_lo, rd->addr_hi, rd->ctrl, rd->status); + } + + return SHR_E_NONE; +} + +/*! + * Dump Tx ring + */ +static int +cmicx_pdma_tx_ring_dump(struct pdma_hw *hw, struct pdma_tx_queue *txq) +{ + struct cmicx_tx_desc *ring = (struct cmicx_tx_desc *)txq->ring; + struct cmicx_tx_desc *td; + uint32_t di; + + CNET_PR("\nTX: queue=%d, chan=%d, curr=%d, dirt=%d, halt@%p\n", + txq->queue_id, txq->chan_id, txq->curr, txq->dirt, (void *)&ring[txq->curr]); + CNET_PR("----------------------------------------------------------------\n"); + for (di = 0; di < txq->nb_desc + 1; di++) { + td = &ring[di]; + CNET_PR("DESC[%03d]: (%p)->%08x %08x %08x %08x\n", + di, (void *)(unsigned long)(txq->ring_addr + di * CMICX_PDMA_DCB_SIZE), + td->addr_lo, td->addr_hi, td->ctrl, td->status); + } + + return SHR_E_NONE; +} + +/*! + * Fetch Tx vring + */ +static int +cmicx_pdma_tx_vring_fetch(struct pdma_hw *hw, struct pdma_tx_queue *txq, + struct pdma_tx_buf *pbuf) +{ + struct pdma_dev *dev = hw->dev; + struct cmicx_tx_desc *ring = (struct cmicx_tx_desc *)txq->ring; + struct pdma_tx_queue *vtxq = NULL; + struct cmicx_tx_desc *vring = NULL; + + vtxq = (struct pdma_tx_queue *)dev->ctrl.vnet_txq[txq->queue_id]; + vring = (struct cmicx_tx_desc *)vtxq->ring; + if (!vring || !CMICX_DESC_CTRL_LEN(vring[vtxq->curr].ctrl)) { + return SHR_E_UNAVAIL; + } + + /* Fetch vring descriptor */ + sal_memcpy(&ring[txq->curr], &vring[vtxq->curr], sizeof(struct cmicx_tx_desc)); + vring[vtxq->curr].ctrl &= ~CMICX_DESC_CTRL_LEN(-1); + + MEMORY_BARRIER; + + pbuf->dma = vring[vtxq->curr].addr_lo; + pbuf->len = CMICX_DESC_CTRL_LEN(ring[txq->curr].ctrl); + vtxq->curr = (vtxq->curr + 1) % vtxq->nb_desc; + + return SHR_E_NONE; +} + +/*! + * Check Tx ring + */ +static inline int +cmicx_pdma_tx_ring_check(struct pdma_hw *hw, struct pdma_tx_queue *txq) +{ + if (cmicx_pdma_tx_ring_unused(txq)) { + return SHR_E_NONE; + } + + sal_spinlock_lock(txq->lock); + if (!cmicx_pdma_tx_ring_unused(txq)) { + txq->state |= PDMA_TX_QUEUE_XOFF; + txq->stats.xoffs++; + sal_spinlock_unlock(txq->lock); + if (hw->dev->tx_suspend) { + hw->dev->tx_suspend(hw->dev, txq->queue_id); + } + return SHR_E_BUSY; + } + sal_spinlock_unlock(txq->lock); + + return SHR_E_NONE; +} + +/*! + * \brief Start packet transmission + * + * \param [in] hw HW structure point. + * \param [in] txq Tx queue structure point. + * \param [in] buf Tx packet buffer. + * + * \retval SHR_E_NONE No errors. + * \retval SHR_E_XXXX Operation failed. + */ +static int +cmicx_pdma_pkt_xmit(struct pdma_hw *hw, struct pdma_tx_queue *txq, void *buf) +{ + struct pdma_dev *dev = hw->dev; + struct pdma_buf_mngr *bm = (struct pdma_buf_mngr *)dev->ctrl.buf_mngr; + struct cmicx_tx_desc *ring = (struct cmicx_tx_desc *)txq->ring; + struct pdma_tx_buf *pbuf = NULL; + struct pkt_hdr *pkh = NULL; + dma_addr_t addr; + uint32_t curr, flags = 0; + int retry = 5000000; + int rv; + + if (!(txq->state & PDMA_TX_QUEUE_ACTIVE)) { + return SHR_E_UNAVAIL; + } + + if (dev->tx_suspend) { + sal_spinlock_lock(txq->mutex); + } else { + sal_sem_take(txq->sem, SAL_SEM_FOREVER); + } + + /* Check Tx resource */ + if (dev->tx_suspend) { + /* Suspend Tx if no resource */ + rv = cmicx_pdma_tx_ring_check(hw, txq); + if (SHR_FAILURE(rv)) { + sal_spinlock_unlock(txq->mutex); + return rv; + } + } else { + /* Abort Tx if a fatal error happened */ + if (txq->state & PDMA_TX_QUEUE_XOFF) { + sal_sem_give(txq->sem); + return SHR_E_RESOURCE; + } + } + + /* Setup the new descriptor */ + curr = txq->curr; + pbuf = &txq->pbuf[curr]; + if (dev->mode == DEV_MODE_HNET && !buf) { + rv = cmicx_pdma_tx_vring_fetch(hw, txq, pbuf); + if (SHR_FAILURE(rv)) { + sal_spinlock_unlock(txq->mutex); + return SHR_E_EMPTY; + } + } else { + pbuf->adj = 1; + pkh = bm->tx_buf_get(dev, txq, pbuf, buf); + if (!pkh) { + txq->stats.dropped++; + if (dev->tx_suspend) { + sal_spinlock_unlock(txq->mutex); + } else { + sal_sem_give(txq->sem); + } + return SHR_E_NONE; + } + bm->tx_buf_dma(dev, txq, pbuf, &addr); + flags |= pkh->attrs & PDMA_TX_HIGIG_PKT ? CMICX_DESC_TX_HIGIG_PKT : 0; + flags |= pkh->attrs & PDMA_TX_PURGE_PKT ? CMICX_DESC_TX_PURGE_PKT : 0; + cmicx_tx_desc_config(&ring[curr], addr, pbuf->len, flags); + } + + /* Notify HNET to process if needed */ + if (dev->mode == DEV_MODE_VNET) { + MEMORY_BARRIER; + if (!CMICX_DESC_CTRL_LEN(ring[(curr + txq->nb_desc - 1) % txq->nb_desc].ctrl)) { + dev->xnet_wake(dev); + } + } + + /* Update the indicators */ + curr = (curr + 1) % txq->nb_desc; + txq->curr = curr; + + /* Start DMA if in chain mode */ + if (dev->flags & PDMA_CHAIN_MODE) { + if (txq->state & PDMA_TX_QUEUE_POLL) { + do { + rv = cmicx_pdma_tx_ring_clean(hw, txq, txq->nb_desc - 1); + if (rv != (int)txq->nb_desc - 1) { + break; + } + sal_usleep(1); + } while (retry--); + if (retry <= 0) { + CNET_PR("Last Tx could not be done in given time\n"); + } + } + sal_spinlock_lock(txq->lock); + if (txq->dirt == txq->halt && txq->dirt != curr) { + hw->hdls.chan_stop(hw, txq->chan_id); + cmicx_tx_desc_chain(&ring[(curr + txq->nb_desc - 1) % txq->nb_desc], 0); + hw->hdls.chan_setup(hw, txq->chan_id, + txq->ring_addr + sizeof(struct cmicx_tx_desc) * txq->halt); + hw->hdls.chan_start(hw, txq->chan_id); + txq->halt = curr; + } + sal_spinlock_unlock(txq->lock); + } + + /* Kick off DMA */ + txq->halt_addr = txq->ring_addr + sizeof(struct cmicx_tx_desc) * curr; + hw->hdls.chan_goto(hw, txq->chan_id, txq->halt_addr); + + /* Count the packets/bytes */ + txq->stats.packets++; + txq->stats.bytes += pbuf->len; + + /* Clean up ring if in polling mode */ + if (txq->state & PDMA_TX_QUEUE_POLL && + cmicx_pdma_tx_ring_unused(txq) <= (int)txq->free_thresh) { + cmicx_pdma_tx_ring_clean(hw, txq, txq->nb_desc - txq->free_thresh); + } + + /* Suspend Tx if no resource */ + rv = cmicx_pdma_tx_ring_check(hw, txq); + if (SHR_FAILURE(rv)) { + if (dev->mode == DEV_MODE_VNET) { + dev->xnet_wake(dev); + } + + if (txq->state & PDMA_TX_QUEUE_POLL) { + /* In polling mode, must wait till the ring is available */ + do { + cmicx_pdma_tx_ring_clean(hw, txq, txq->free_thresh); + if (!(txq->state & PDMA_TX_QUEUE_XOFF)) { + break; + } + sal_usleep(1); + } while (retry--); + if (retry <= 0) { + CNET_PR("Fatal error: Tx ring is full, packets have not been transmitted for 5 seconds\n"); + if (!dev->tx_suspend) { + sal_sem_give(txq->sem); + return SHR_E_RESOURCE; + } + } + } else { + /* In interrupt mode, the handle thread will wake up Tx */ + if (!dev->tx_suspend) { + return SHR_E_NONE; + } + } + } + + if (dev->tx_suspend) { + sal_spinlock_unlock(txq->mutex); + } else { + sal_sem_give(txq->sem); + } + + return SHR_E_NONE; +} + +/*! + * Suspend Rx queue + */ +static int +cmicx_pdma_rx_suspend(struct pdma_hw *hw, struct pdma_rx_queue *rxq) +{ + sal_spinlock_lock(rxq->lock); + rxq->state |= PDMA_RX_QUEUE_XOFF; + if (hw->dev->flags & PDMA_CHAIN_MODE) { + hw->hdls.chan_stop(hw, rxq->chan_id); + } + sal_spinlock_unlock(rxq->lock); + + return SHR_E_NONE; +} + +/*! + * Resume Rx queue + */ +static int +cmicx_pdma_rx_resume(struct pdma_hw *hw, struct pdma_rx_queue *rxq) +{ + sal_spinlock_lock(rxq->lock); + if (!(rxq->state & PDMA_RX_QUEUE_XOFF)) { + sal_spinlock_unlock(rxq->lock); + return SHR_E_NONE; + } + if (rxq->state & PDMA_RX_BATCH_REFILL) { + rxq->halt_addr = rxq->ring_addr + sizeof(struct cmicx_rx_desc) * rxq->halt; + hw->hdls.chan_goto(hw, rxq->chan_id, rxq->halt_addr); + } else if (rxq->halt == rxq->curr || (rxq->halt == rxq->nb_desc && rxq->curr == 0)) { + rxq->halt = (rxq->curr + 1) % rxq->nb_desc; + rxq->halt_addr = rxq->ring_addr + sizeof(struct cmicx_rx_desc) * rxq->halt; + hw->hdls.chan_goto(hw, rxq->chan_id, rxq->halt_addr); + } + if (hw->dev->flags & PDMA_CHAIN_MODE) { + rxq->curr = 0; + hw->hdls.chan_start(hw, rxq->chan_id); + } + rxq->state &= ~PDMA_RX_QUEUE_XOFF; + sal_spinlock_unlock(rxq->lock); + + return SHR_E_NONE; +} + +/*! + * Initialize function pointers + */ +int +bcmcnet_cmicx_pdma_desc_ops_init(struct pdma_hw *hw) +{ + if (!hw) { + return SHR_E_PARAM; + } + + hw->dops.rx_desc_init = cmicx_pdma_rx_desc_init; + hw->dops.rx_desc_clean = cmicx_pdma_rx_desc_clean; + hw->dops.rx_ring_clean = cmicx_pdma_rx_ring_clean; + hw->dops.rx_ring_dump = cmicx_pdma_rx_ring_dump; + hw->dops.rx_suspend = cmicx_pdma_rx_suspend; + hw->dops.rx_resume = cmicx_pdma_rx_resume; + hw->dops.tx_desc_init = cmicx_pdma_tx_desc_init; + hw->dops.tx_desc_clean = cmicx_pdma_tx_desc_clean; + hw->dops.tx_ring_clean = cmicx_pdma_tx_ring_clean; + hw->dops.tx_ring_dump = cmicx_pdma_tx_ring_dump; + hw->dops.pkt_xmit = cmicx_pdma_pkt_xmit; + + return SHR_E_NONE; +} + +/*! + * Attach device driver + */ +int +bcmcnet_cmicx_pdma_driver_attach(struct pdma_dev *dev) +{ + struct pdma_hw *hw = NULL; + + /* Allocate memory for HW data */ + hw = sal_alloc(sizeof(*hw), "bcmcnetPdmaHw"); + if (!hw) { + return SHR_E_MEMORY; + } + sal_memset(hw, 0, sizeof(*hw)); + hw->unit = dev->unit; + hw->dev = dev; + dev->ctrl.hw = hw; + + bcmcnet_cmicx_pdma_hw_hdls_init(hw); + bcmcnet_cmicx_pdma_desc_ops_init(hw); + + return SHR_E_NONE; +} + +/*! + * Detach device driver + */ +int +bcmcnet_cmicx_pdma_driver_detach(struct pdma_dev *dev) +{ + if (dev->ctrl.hw) { + sal_free(dev->ctrl.hw); + } + dev->ctrl.hw = NULL; + + return SHR_E_NONE; +} + diff --git a/platform/broadcom/saibcm-modules/sdklt/bcmcnet/include/bcmcnet/bcmcnet_cmicd.h b/platform/broadcom/saibcm-modules/sdklt/bcmcnet/include/bcmcnet/bcmcnet_cmicd.h new file mode 100644 index 00000000000..ef9717923e7 --- /dev/null +++ b/platform/broadcom/saibcm-modules/sdklt/bcmcnet/include/bcmcnet/bcmcnet_cmicd.h @@ -0,0 +1,369 @@ +/*! \file bcmcnet_cmicd.h + * + * CMICd registers and descriptors definitions. + * + */ +/* + * $Copyright: Copyright 2018-2020 Broadcom. All rights reserved. + * The term 'Broadcom' refers to Broadcom Inc. and/or its subsidiaries. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * version 2 as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * A copy of the GNU General Public License version 2 (GPLv2) can + * be found in the LICENSES folder.$ + */ + +#ifndef BCMCNET_CMICD_H +#define BCMCNET_CMICD_H + +/*! + * \name CMICD PDMA HW definitions + */ +/*! \{ */ +/*! CMICD CMC number */ +#define CMICD_PDMA_CMC_MAX 3 +/*! CMICD CMC PDMA channels */ +#define CMICD_PDMA_CMC_CHAN 4 +/*! CMICD PDMA DCB size */ +#define CMICD_PDMA_DCB_SIZE 64 +/*! \} */ + +/*! + * \name CMICD PDMA register definitions + */ +/*! \{ */ +#define CMICD_PDMA_CTRLr 0x0140 +#define CMICD_PDMA_STATr 0x0150 +#define CMICD_PDMA_STAT_HIr 0x0130 +#define CMICD_PDMA_STAT_CLRr 0x01a4 +#define CMICD_PDMA_DESCr 0x0158 +#define CMICD_PDMA_CURR_DESCr 0x01a8 +#define CMICD_PDMA_DESC_HALTr 0x0120 +#define CMICD_PDMA_COS_RX0r 0x0168 +#define CMICD_PDMA_COS_RX1r 0x016c +#define CMICD_PDMA_COS_MASK0r 0x019c +#define CMICD_PDMA_COS_MASK1r 0x01a0 +#define CMICD_PDMA_INTR_COALr 0x0188 +#define CMICD_PDMA_RBUF_THREr 0x0110 +#define CMICD_PDMA_COUNT_RXr 0x0480 +#define CMICD_PDMA_COUNT_TXr 0x0484 +#define CMICD_PDMA_COUNT_ALL_RXr 0x04a0 +#define CMICD_PDMA_COUNT_ALL_TXr 0x04a4 +#define CMICD_IRQ_STATr 0x0400 +#define CMICD_IRQ_PCI_MASKr 0x0414 +#define CMICD_IRQ_UC0_MASKr 0x0428 +/*! \} */ + +/*! + * \name CMICD PDMA register address + */ +/*! \{ */ +/*! Base address */ +#define CMICD_GRP_BASE(g) (0x00031000 + 0x1000 * g) +/*! Control register address */ +#define CMICD_PDMA_CTRL(g, q) (CMICD_GRP_BASE(g) + CMICD_PDMA_CTRLr + q * 4) +/*! Status register address */ +#define CMICD_PDMA_STAT(g) (CMICD_GRP_BASE(g) + CMICD_PDMA_STATr) +/*! Status higher register address */ +#define CMICD_PDMA_STAT_HI(g) (CMICD_GRP_BASE(g) + CMICD_PDMA_STAT_HIr) +/*! Status clear register address */ +#define CMICD_PDMA_STAT_CLR(g) (CMICD_GRP_BASE(g) + CMICD_PDMA_STAT_CLRr) +/*! Descriptor register address */ +#define CMICD_PDMA_DESC(g, q) (CMICD_GRP_BASE(g) + CMICD_PDMA_DESCr + q * 4) +/*! Current descriptor register address */ +#define CMICD_PDMA_CURR_DESC(g, q) (CMICD_GRP_BASE(g) + CMICD_PDMA_CURR_DESCr + q * 4) +/*! Descriptor halt register address */ +#define CMICD_PDMA_DESC_HALT(g, q) (CMICD_GRP_BASE(g) + CMICD_PDMA_DESC_HALTr + q * 4) +/*! COS Rx0 register address */ +#define CMICD_PDMA_COS_RX0(g, q) (CMICD_GRP_BASE(g) + CMICD_PDMA_COS_RX0r + q * 8) +/*! COS Rx1 register address */ +#define CMICD_PDMA_COS_RX1(g, q) (CMICD_GRP_BASE(g) + CMICD_PDMA_COS_RX1r + q * 8) +/*! COS Mask0 register address */ +#define CMICD_PDMA_COS_MASK0(g) (CMICD_GRP_BASE(g) + CMICD_PDMA_COS_MASK0r) +/*! COS Mask1 register address */ +#define CMICD_PDMA_COS_MASK1(g) (CMICD_GRP_BASE(g) + CMICD_PDMA_COS_MASK1r) +/*! Interrupt coalesce register address */ +#define CMICD_PDMA_INTR_COAL(g, q) (CMICD_GRP_BASE(g) + CMICD_PDMA_INTR_COALr + q * 4) +/*! Rx buffer threshhold register address */ +#define CMICD_PDMA_RBUF_THRE(g, q) (CMICD_GRP_BASE(g) + CMICD_PDMA_RBUF_THREr + q * 4) +/*! Rx counter register address */ +#define CMICD_PDMA_COUNT_RX(g, q) (CMICD_GRP_BASE(g) + CMICD_PDMA_COUNT_RXr + q * 8) +/*! Tx counter register address */ +#define CMICD_PDMA_COUNT_TX(g, q) (CMICD_GRP_BASE(g) + CMICD_PDMA_COUNT_TXr + q * 8) +/*! Rx global counter register address */ +#define CMICD_PDMA_COUNT_ALL_RX(g) (CMICD_GRP_BASE(g) + CMICD_PDMA_COUNT_ALL_RXr) +/*! Tx gloable counter register address */ +#define CMICD_PDMA_COUNT_ALL_TX(g) (CMICD_GRP_BASE(g) + CMICD_PDMA_COUNT_ALL_TXr) +/*! Interrupt status register address */ +#define CMICD_IRQ_STAT(g) (CMICD_GRP_BASE(g) + CMICD_IRQ_STATr) +/*! Interrupt PCI mask register address */ +#define CMICD_IRQ_PCI_MASK(g) (CMICD_GRP_BASE(g) + CMICD_IRQ_PCI_MASKr) +/*! Interrupt UC0 mask register address */ +#define CMICD_IRQ_UC0_MASK(g) (CMICD_GRP_BASE(g) + CMICD_IRQ_UC0_MASKr) +/*! Credits release release register address */ +#define CMICD_EPINTF_RELEASE_CREDITS 0x0001a000 +/*! Device revision register address */ +#define CMICD_DEV_REV_ID 0x00010224 +/*! CMIC revison register address */ +#define CMICD_CMICM_REV_ID 0x00010228 +/*! \} */ + +/*! + * \name Control register definitions + */ +/*! \{ */ +/*! Continuous DMA mode */ +#define CMICD_PDMA_CONTINUOUS 0x00000200 +/*! Controlled interrupt */ +#define CMICD_PDMA_CNTLD_INTR 0x00000100 +/*! Update status on reload */ +#define CMICD_PDMA_RLD_STAT_DIS 0x00000080 +/*! Dropped on chain end */ +#define CMICD_PDMA_DROP_ON_END 0x00000040 +/*! Descriptor big endianess */ +#define CMICD_PDMA_DESC_BIG_ENDIAN 0x00000020 +/*! Packet DMA big endianess */ +#define CMICD_PDMA_PKT_BIG_ENDIAN 0x00000010 +/*! Interrupt after descriptor */ +#define CMICD_PDMA_INTR_ON_DESC 0x00000008 +/*! Abort DMA */ +#define CMICD_PDMA_ABORT 0x00000004 +/*! Enable DMA */ +#define CMICD_PDMA_ENABLE 0x00000002 +/*! DMA direction */ +#define CMICD_PDMA_DIR 0x00000001 +/*! \} */ + +/*! + * \name Status register definitions + */ +/*! \{ */ +/*! Chain done */ +#define CMICD_PDMA_CHAIN_DONE(q) (0x00000001 << (q)) +/*! Descriptor done */ +#define CMICD_PDMA_DESC_DONE(q) (0x00000010 << (q)) +/*! Active */ +#define CMICD_PDMA_ACTIVE(q) (0x00000100 << (q)) +/*! \} */ + +/*! + * \name Status clear register definitions + */ +/*! \{ */ +/*! Clear completed interrupt */ +#define CMICD_PDMA_DESC_CMPLT(q) (0x00000001 << (q)) +/*! Clear controlled interrupt */ +#define CMICD_PDMA_DESC_CNTLD(q) (0x00000100 << (q)) +/*! \} */ + +/*! + * \name Interrupt_coalesce register definitions + */ +/*! \{ */ +/*! Interrupt coalesce enable */ +#define CMICD_PDMA_INTR_COAL_ENA (1 << 31) +/*! Interrupt coalesce threshhold */ +#define CMICD_PDMA_INTR_THRESH(cnt) (((cnt) & 0x7fff) << 16) +/*! Interrupt coalesce timeout */ +#define CMICD_PDMA_INTR_TIMER(tmr) ((tmr) & 0xffff) +/*! \} */ + +/*! + * \name Interrupt status&mask register definitions + */ +/*! \{ */ +/*! Interrupt mask */ +#define CMICD_PDMA_IRQ_MASK 0x78000000 +/*! Descriptor done */ +#define CMICD_IRQ_DESC_DONE(q) (0x00004000 >> (2 * (q))) +/*! Chain done */ +#define CMICD_IRQ_CHAIN_DONE(q) (0x00008000 >> (2 * (q))) +/*! Controlled interrupt */ +#define CMICD_IRQ_DESC_CNTLD(q) (0x08000000 << (q)) +/*! Interrupt start number */ +#define CMICD_IRQ_START_NUM 27 +/*! Interrupt number offset */ +#define CMICD_IRQ_NUM_OFFSET 1 +/*! Interrupt mask shift */ +#define CMICD_IRQ_MASK_SHIFT 0 +/*! Interrupt mask zeroing */ +#define CMICD_IRQ_ACT_CHAN(mask) (((mask) & CMICD_PDMA_IRQ_MASK) >> CMICD_IRQ_START_NUM) +/*! \} */ + +/*! 32-bit register read */ +#define DEV_READ32(_c, _a, _p) \ + do { \ + if ((_c)->dev->mode != DEV_MODE_VNET) { \ + *(_p) = ((volatile uint32_t *)(_c)->hw_addr)[(_a) / 4]; \ + } \ + } while (0) + +/*! 32-bit register write */ +#define DEV_WRITE32(_c, _a, _v) \ + do { \ + if ((_c)->dev->mode != DEV_MODE_VNET) { \ + ((volatile uint32_t *)(_c)->hw_addr)[(_a) / 4] = (_v); \ + } \ + } while (0) + +/*! + * \brief Rx metadata in descriptor. + */ +struct rx_metadata { + /*! Metadata */ + volatile uint32_t data[13]; + + /*! Status */ + volatile uint32_t status; +} __attribute__((packed)); + +/*! + * \brief Rx descriptor. + */ +struct cmicd_rx_desc { + /*! Packet address */ + volatile uint32_t addr; + + /*! Packet control */ + volatile uint32_t ctrl; + + /*! Metadata fields */ + struct rx_metadata md; +} __attribute__((packed)); + +/*! Reserve Rx meta data size in packet buffer */ +#define CMICD_RX_META_RESV 64 + +/*! + * \brief Tx metadata in descriptor. + */ +struct tx_metadata { + /*! Metadata */ + volatile uint32_t data[4]; + + /*! Reserved */ + volatile uint32_t rsvd[9]; + + /*! Status */ + volatile uint32_t status; +} __attribute__((packed)); + +/*! + * \brief Tx descriptor. + */ +struct cmicd_tx_desc { + /*! Packet address */ + volatile uint32_t addr; + + /*! Packet control */ + volatile uint32_t ctrl; + + /*! Metadata fields */ + struct tx_metadata md; +} __attribute__((packed)); + +/*! Reserve Tx meta data size in packet buffer */ +#define CMICD_TX_META_RESV 16 + +/*! + * Flags related to descriptors. + */ +/*! Controlled interrupt */ +#define CMICD_DESC_CTRL_CNTLD_INTR (1 << 24) +/*! Completed interrupt */ +#define CMICD_DESC_CTRL_CMPLT_INTR (1 << 23) +/*! Reload DCB */ +#define CMICD_DESC_CTRL_RELOAD (1 << 18) +/*! Scatter DCB */ +#define CMICD_DESC_CTRL_SCATTER (1 << 17) +/*! Chained DCB */ +#define CMICD_DESC_CTRL_CHAIN (1 << 16) +/*! Control flags */ +#define CMICD_DESC_CTRL_FLAGS(f) (((f) & 0xffff) << 16) +/*! Purge packet */ +#define CMICD_DESC_TX_PURGE_PKT (1 << 6) +/*! Pause packet */ +#define CMICD_DESC_TX_PAUSE_PKT (1 << 5) +/*! Higig packet */ +#define CMICD_DESC_TX_HIGIG_PKT (1 << 3) +/*! Packet length */ +#define CMICD_DESC_CTRL_LEN(len) ((len) & 0xffff) +/*! Done */ +#define CMICD_DESC_STAT_RTX_DONE (1 << 31) +/*! Head error */ +#define CMICD_DESC_STAT_HEAD_ERR (1 << 20) +/*! Data error */ +#define CMICD_DESC_STAT_DATA_ERR (1 << 19) +/*! Cell error */ +#define CMICD_DESC_STAT_CELL_ERR (1 << 18) +/*! Error mask */ +#define CMICD_DESC_STAT_ERR_MASK (CMICD_DESC_STAT_HEAD_ERR | \ + CMICD_DESC_STAT_DATA_ERR | \ + CMICD_DESC_STAT_CELL_ERR) +/*! Packet start */ +#define CMICD_DESC_STAT_PKT_START (1 << 17) +/*! Packet end */ +#define CMICD_DESC_STAT_PKT_END (1 << 16) +/*! Get done state */ +#define CMICD_DESC_STAT_DONE(stat) ((stat) & CMICD_DESC_STAT_RTX_DONE) +/*! Get flags */ +#define CMICD_DESC_STAT_FLAGS(stat) (((stat) >> 16) & ~0x8003) +/*! Get packet length */ +#define CMICD_DESC_STAT_LEN(stat) ((stat) & 0xffff) + +/*! HW access retry times */ +#define CMICD_HW_RETRY_TIMES 100000 + +/*! + * \brief Initialize HW handles. + * + * \param [in] hw HW structure point. + * + * \retval SHR_E_NONE No errors. + * \retval SHR_E_XXXX Operation failed. + */ +extern int +bcmcnet_cmicd_pdma_hw_hdls_init(struct pdma_hw *hw); + +/*! + * \brief Initialize descriptor operations. + * + * \param [in] hw HW structure point. + * + * \retval SHR_E_NONE No errors. + * \retval SHR_E_XXXX Operation failed. + */ +extern int +bcmcnet_cmicd_pdma_desc_ops_init(struct pdma_hw *hw); + +/*! + * \brief Attach device driver. + * + * \param [in] dev Device structure point. + * + * \retval SHR_E_NONE No errors. + * \retval SHR_E_XXXX Operation failed. + */ +extern int +bcmcnet_cmicd_pdma_driver_attach(struct pdma_dev *dev); + +/*! + * \brief Detach device driver. + * + * \param [in] dev Device structure point. + * + * \retval SHR_E_NONE No errors. + * \retval SHR_E_XXXX Operation failed. + */ +extern int +bcmcnet_cmicd_pdma_driver_detach(struct pdma_dev *dev); + +#endif /* BCMCNET_CMICD_H */ + diff --git a/platform/broadcom/saibcm-modules/sdklt/bcmcnet/include/bcmcnet/bcmcnet_cmicx.h b/platform/broadcom/saibcm-modules/sdklt/bcmcnet/include/bcmcnet/bcmcnet_cmicx.h new file mode 100644 index 00000000000..a8657c8b46a --- /dev/null +++ b/platform/broadcom/saibcm-modules/sdklt/bcmcnet/include/bcmcnet/bcmcnet_cmicx.h @@ -0,0 +1,379 @@ +/*! \file bcmcnet_cmicx.h + * + * CMICx registers and descriptors definitions. + * + */ +/* + * $Copyright: Copyright 2018-2020 Broadcom. All rights reserved. + * The term 'Broadcom' refers to Broadcom Inc. and/or its subsidiaries. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * version 2 as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * A copy of the GNU General Public License version 2 (GPLv2) can + * be found in the LICENSES folder.$ + */ + +#ifndef BCMCNET_CMICX_H +#define BCMCNET_CMICX_H + +/*! + * \name CMICX PDMA HW definitions + */ +/*! \{ */ +/*! CMICX CMC number */ +#define CMICX_PDMA_CMC_MAX 2 +/*! CMICX CMC PDMA channels */ +#define CMICX_PDMA_CMC_CHAN 8 +/*! CMICX PDMA DCB size */ +#define CMICX_PDMA_DCB_SIZE 16 +/*! \} */ + +/*! + * \name CMICX PCIe device address definitions + */ +/*! \{ */ +/*! CMICX PCIE offset */ +#define CMICX_PCIE_SO_OFFSET 0x10000000 +/*! Higher DMA address to bus address */ +#define DMA_TO_BUS_HI(dma) ((dma) | CMICX_PCIE_SO_OFFSET) +/*! Higher bus address to DMA address */ +#define BUS_TO_DMA_HI(bus) ((bus) & ~CMICX_PCIE_SO_OFFSET) +/*! \} */ + +/*! + * \name CMICX PDMA register definitions + */ +/*! \{ */ +#define CMICX_PDMA_CTRLr 0x2100 +#define CMICX_PDMA_STATr 0x2114 +#define CMICX_PDMA_DESC_LOr 0x2104 +#define CMICX_PDMA_DESC_HIr 0x2108 +#define CMICX_PDMA_CURR_DESC_LOr 0x2124 +#define CMICX_PDMA_CURR_DESC_HIr 0x2128 +#define CMICX_PDMA_DESC_HALT_LOr 0x210c +#define CMICX_PDMA_DESC_HALT_HIr 0x2110 +#define CMICX_PDMA_COS_CTRL_RX0r 0x2118 +#define CMICX_PDMA_COS_CTRL_RX1r 0x211c +#define CMICX_PDMA_INTR_COALr 0x2120 +#define CMICX_PDMA_RBUF_THREr 0x212c +#define CMICX_PDMA_DEBUG_CTRLr 0x2130 +#define CMICX_PDMA_DEBUG_SM_STATr 0x2134 +#define CMICX_PDMA_DEBUG_STATr 0x2138 +#define CMICX_PDMA_COUNT_RXr 0x213c +#define CMICX_PDMA_COUNT_TXr 0x2140 +#define CMICX_PDMA_COUNT_RX_DROPr 0x2144 +#define CMICX_PDMA_DESC_CNT_REQr 0x2148 +#define CMICX_PDMA_DESC_CNT_RXr 0x214c +#define CMICX_PDMA_DESC_CNT_STATr 0x2150 +#define CMICX_PDMA_IRQ_STATr 0x106c +#define CMICX_PDMA_IRQ_STAT_CLRr 0x1074 +/*! \} */ + +/*! + * \name CMICX PDMA register address + */ +/*! \{ */ +/*! Base address */ +#define CMICX_GRP_BASE(g) (0x00000000 + 0x3000 * g) +/*! Control register address */ +#define CMICX_PDMA_CTRL(g, q) (CMICX_GRP_BASE(g) + CMICX_PDMA_CTRLr + q * 0x80) +/*! Status register address */ +#define CMICX_PDMA_STAT(g, q) (CMICX_GRP_BASE(g) + CMICX_PDMA_STATr + q * 0x80) +/*! Descriptor Address Lower register address */ +#define CMICX_PDMA_DESC_LO(g, q) (CMICX_GRP_BASE(g) + CMICX_PDMA_DESC_LOr + q * 0x80) +/*! Descriptor Address Higher register address */ +#define CMICX_PDMA_DESC_HI(g, q) (CMICX_GRP_BASE(g) + CMICX_PDMA_DESC_HIr + q * 0x80) +/*! Current Descriptor Address Lower register address */ +#define CMICX_PDMA_CURR_DESC_LO(g, q) (CMICX_GRP_BASE(g) + CMICX_PDMA_CURR_DESC_LOr + q * 0x80) +/*! Current Descriptor Address Higher register address */ +#define CMICX_PDMA_CURR_DESC_HI(g, q) (CMICX_GRP_BASE(g) + CMICX_PDMA_CURR_DESC_HIr + q * 0x80) +/*! Descriptor Halt Address Lower register address */ +#define CMICX_PDMA_DESC_HALT_LO(g, q) (CMICX_GRP_BASE(g) + CMICX_PDMA_DESC_HALT_LOr + q * 0x80) +/*! Descriptor Halt Address Higher register address */ +#define CMICX_PDMA_DESC_HALT_HI(g, q) (CMICX_GRP_BASE(g) + CMICX_PDMA_DESC_HALT_HIr + q * 0x80) +/*! COS Control Rx0 register address */ +#define CMICX_PDMA_COS_CTRL_RX0(g, q) (CMICX_GRP_BASE(g) + CMICX_PDMA_COS_CTRL_RX0r + q * 0x80) +/*! COS Control Rx1 register address */ +#define CMICX_PDMA_COS_CTRL_RX1(g, q) (CMICX_GRP_BASE(g) + CMICX_PDMA_COS_CTRL_RX1r + q * 0x80) +/*! Interrupt Coalesce register address */ +#define CMICX_PDMA_INTR_COAL(g, q) (CMICX_GRP_BASE(g) + CMICX_PDMA_INTR_COALr + q * 0x80) +/*! Rx Buffer Threshhold register address */ +#define CMICX_PDMA_RBUF_THRE(g, q) (CMICX_GRP_BASE(g) + CMICX_PDMA_RBUF_THREr + q * 0x80) +/*! Debug Control register address */ +#define CMICX_PDMA_DEBUG_CTRL(g, q) (CMICX_GRP_BASE(g) + CMICX_PDMA_DEBUG_CTRLr + q * 0x80) +/*! Debug Status register address */ +#define CMICX_PDMA_DEBUG_STAT(g, q) (CMICX_GRP_BASE(g) + CMICX_PDMA_DEBUG_STATr + q * 0x80) +/*! Debug State Machine Status register address */ +#define CMICX_PDMA_DEBUG_SM_STAT(g, q) (CMICX_GRP_BASE(g) + CMICX_PDMA_DEBUG_SM_STATr + q * 0x80) +/*! Rx Packet Count register address */ +#define CMICX_PDMA_COUNT_RX(g, q) (CMICX_GRP_BASE(g) + CMICX_PDMA_COUNT_RXr + q * 0x80) +/*! Tx Packet Count register address */ +#define CMICX_PDMA_COUNT_TX(g, q) (CMICX_GRP_BASE(g) + CMICX_PDMA_COUNT_TXr + q * 0x80) +/*! Dropped Rx Packet Count register address */ +#define CMICX_PDMA_COUNT_RX_DROP(g, q) (CMICX_GRP_BASE(g) + CMICX_PDMA_COUNT_RX_DROPr + q * 0x80) +/*! Requested Descriptor Count register address */ +#define CMICX_PDMA_DESC_CNT_REQ(g, q) (CMICX_GRP_BASE(g) + CMICX_PDMA_DESC_CNT_REQr + q * 0x80) +/*! Received Descriptor Count register address */ +#define CMICX_PDMA_DESC_CNT_RX(g, q) (CMICX_GRP_BASE(g) + CMICX_PDMA_DESC_CNT_RXr + q * 0x80) +/*! Updated Descriptor Count register address */ +#define CMICX_PDMA_DESC_CNT_STAT(g, q) (CMICX_GRP_BASE(g) + CMICX_PDMA_DESC_CNT_STATr + q * 0x80) +/*! Interrupt Status register address */ +#define CMICX_PDMA_IRQ_STAT(g) (CMICX_GRP_BASE(g) + CMICX_PDMA_IRQ_STATr) +/*! Interrupt Status Clear register address */ +#define CMICX_PDMA_IRQ_STAT_CLR(g) (CMICX_GRP_BASE(g) + CMICX_PDMA_IRQ_STAT_CLRr) +/*! Interrupt Enable register address0 */ +#define CMICX_PDMA_IRQ_ENAB0 0x18013100 +/*! Interrupt Enable register address1 */ +#define CMICX_PDMA_IRQ_ENAB1 0x18013104 +/*! Interrupt Enable register address2 */ +#define CMICX_PDMA_IRQ_ENAB2 0x18013108 +/*! Interrupt raw status register address0 */ +#define CMICX_PDMA_IRQ_RAW_STAT0 0x18013150 +/*! Interrupt raw status register address1 */ +#define CMICX_PDMA_IRQ_RAW_STAT1 0x18013154 +/*! Interrupt raw status register address2 */ +#define CMICX_PDMA_IRQ_RAW_STAT2 0x18013158 +/*! EP_TO_CPU Header Size register address */ +#define CMICX_EP_TO_CPU_HEADER_SIZE 0x00000004 +/*! Top config register address */ +#define CMICX_TOP_CONFIG 0x00000008 +/*! Credits release register address */ +#define CMICX_EPINTF_RELEASE_CREDITS 0x0000006c +/*! Max credits register address */ +#define CMICX_EPINTF_MAX_CREDITS 0x00000070 +/*! \} */ + +/*! + * \name Control register definitions + */ +/*! \{ */ +/*! Disable abort on error */ +#define CMICX_PDMA_NO_ABORT_ON_ERR 0x00002000 +/*! EP_TO_CPU header big endianess */ +#define CMICX_PDMA_HDR_BIG_ENDIAN 0x00001000 +/*! Continuous descriptor mode */ +#define CMICX_PDMA_CONTINUOUS_DESC 0x00000200 +/*! Continuous DMA mode */ +#define CMICX_PDMA_CONTINUOUS 0x00000100 +/*! Interrupt after descriptor */ +#define CMICX_PDMA_INTR_ON_DESC 0x00000080 +/*! Update status on reload */ +#define CMICX_PDMA_RLD_STAT_DIS 0x00000040 +/*! Dropped on chain end */ +#define CMICX_PDMA_DROP_ON_END 0x00000020 +/*! Descriptor big endianess */ +#define CMICX_PDMA_DESC_BIG_ENDIAN 0x00000010 +/*! Packet DMA big endianess */ +#define CMICX_PDMA_PKT_BIG_ENDIAN 0x00000008 +/*! Abort DMA */ +#define CMICX_PDMA_ABORT 0x00000004 +/*! Enable DMA */ +#define CMICX_PDMA_ENABLE 0x00000002 +/*! DMA direction */ +#define CMICX_PDMA_DIR 0x00000001 +/*! EP_TO_CPU header alignment bytes */ +#define CMICX_PDMA_HDR_ALMNT(bytes) (((bytes) & 0x3) << 10) +/*! \} */ + +/*! + * \name Status register definitions + */ +/*! \{ */ +/*! Channel in halt */ +#define CMICX_PDMA_IN_HALT 0x00000040 +/*! Channel active */ +#define CMICX_PDMA_IS_ACTIVE 0x00000002 +/*! Chain done */ +#define CMICX_PDMA_CHAIN_DONE 0x00000001 +/*! \} */ + +/*! + * \name Interrupt_coalesce register definitions + */ +/*! \{ */ +/*! Interrupt coalesce enable */ +#define CMICX_PDMA_INTR_COAL_ENA (1 << 31) +/*! Interrupt coalesce threshhold */ +#define CMICX_PDMA_INTR_THRESH(cnt) (((cnt) & 0x7fff) << 16) +/*! Interrupt coalesce timeout */ +#define CMICX_PDMA_INTR_TIMER(tmr) ((tmr) & 0xffff) +/*! \} */ + +/*! + * \name Interrupt status&clear register definitions + */ +/*! \{ */ +/*! Descriptor done */ +#define CMICX_PDMA_IRQ_DESC_DONE(q) (0x00000001 << ((q) * 4)) +/*! Chain done */ +#define CMICX_PDMA_IRQ_CHAIN_DONE(q) (0x00000002 << ((q) * 4)) +/*! Coalescing interrupt */ +#define CMICX_PDMA_IRQ_COALESCE_INTR(q) (0x00000004 << ((q) * 4)) +/*! Controlled interrupt */ +#define CMICX_PDMA_IRQ_CTRLD_INTR(q) (0x00000008 << ((q) * 4)) +/*! Interrupt mask */ +#define CMICX_PDMA_IRQ_MASK(q) (0xf << ((q) * 4)) +/*! Interrupt start number */ +#define CMICX_IRQ_START_NUM (128 + 3) +/*! Interrupt number offset */ +#define CMICX_IRQ_NUM_OFFSET 4 +/*! Interrupt mask shift */ +#define CMICX_IRQ_MASK_SHIFT 16 +/*! \} */ + +/*! 32-bit register read */ +#define DEV_READ32(_c, _a, _p) \ + do { \ + if ((_c)->dev->mode != DEV_MODE_VNET) { \ + *(_p) = ((volatile uint32_t *)(_c)->hw_addr)[(_a) / 4]; \ + } \ + } while (0) + +/*! 32-bit register write */ +#define DEV_WRITE32(_c, _a, _v) \ + do { \ + if ((_c)->dev->mode != DEV_MODE_VNET) { \ + ((volatile uint32_t *)(_c)->hw_addr)[(_a) / 4] = (_v); \ + } \ + } while (0) + +/*! + * \brief Rx descriptor. + */ +struct cmicx_rx_desc { + /*! Packet address lower */ + volatile uint32_t addr_lo; + + /*! Packet address higher */ + volatile uint32_t addr_hi; + + /*! Packet control */ + volatile uint32_t ctrl; + + /*! Packet status */ + volatile uint32_t status; +} __attribute__((packed)); + +/*! + * \brief Tx descriptor. + */ +struct cmicx_tx_desc { + /*! Packet address lower */ + volatile uint32_t addr_lo; + + /*! Packet address higher */ + volatile uint32_t addr_hi; + + /*! Packet control */ + volatile uint32_t ctrl; + + /*! Packet status */ + volatile uint32_t status; +} __attribute__((packed)); + +/*! + * Flags related to descriptors. + */ +/*! Disable descriptor status write */ +#define CMICX_DESC_CTRL_STAT_WR_DIS (1 << 29) +/*! Descriptors remaining */ +#define CMICX_DESC_CTRL_REMAIN(cnt) (((cnt) & 0xf) << 25) +/*! Max remaining descriptors */ +#define CMICX_DESC_REMAIN_MAX 8 +/*! Controlled interrupt */ +#define CMICX_DESC_CTRL_CNTLD_INTR (1 << 24) +/*! Completed interrupt */ +#define CMICX_DESC_CTRL_CMPLT_INTR (1 << 23) +/*! Reload DCB */ +#define CMICX_DESC_CTRL_RELOAD (1 << 18) +/*! Scatter DCB */ +#define CMICX_DESC_CTRL_SCATTER (1 << 17) +/*! Chained DCB */ +#define CMICX_DESC_CTRL_CHAIN (1 << 16) +/*! Control flags */ +#define CMICX_DESC_CTRL_FLAGS(f) (((f) & 0xffff) << 16) +/*! Purge packet */ +#define CMICX_DESC_TX_PURGE_PKT (1 << 6) +/*! Higig packet */ +#define CMICX_DESC_TX_HIGIG_PKT (1 << 3) +/*! Packet length */ +#define CMICX_DESC_CTRL_LEN(len) ((len) & 0xffff) +/*! Done */ +#define CMICX_DESC_STAT_RTX_DONE (1 << 31) +/*! Ecc error */ +#define CMICX_DESC_STAT_DATA_ERR (1 << 19) +/*! Cell error */ +#define CMICX_DESC_STAT_CELL_ERR (1 << 18) +/*! Error mask */ +#define CMICX_DESC_STAT_ERR_MASK (CMICX_DESC_STAT_DATA_ERR | \ + CMICX_DESC_STAT_CELL_ERR) +/*! Packet start */ +#define CMICX_DESC_STAT_PKT_START (1 << 17) +/*! Packet end */ +#define CMICX_DESC_STAT_PKT_END (1 << 16) +/*! Get done state */ +#define CMICX_DESC_STAT_DONE(stat) ((stat) & CMICX_DESC_STAT_RTX_DONE) +/*! Get flags */ +#define CMICX_DESC_STAT_FLAGS(stat) (((stat) >> 16) & ~0x8003) +/*! Get packet length */ +#define CMICX_DESC_STAT_LEN(stat) ((stat) & 0xffff) + +/*! Tx packet header size */ +#define CMICX_TX_PKT_HDR_SIZE 16 + +/*! HW access retry times */ +#define CMICX_HW_RETRY_TIMES 100000 + +/*! + * \brief Initialize HW handles. + * + * \param [in] hw HW structure point. + * + * \retval SHR_E_NONE No errors. + * \retval SHR_E_XXXX Operation failed. + */ +extern int +bcmcnet_cmicx_pdma_hw_hdls_init(struct pdma_hw *hw); + +/*! + * \brief Initialize descriptor operations. + * + * \param [in] hw HW structure point. + * + * \retval SHR_E_NONE No errors. + * \retval SHR_E_XXXX Operation failed. + */ +extern int +bcmcnet_cmicx_pdma_desc_ops_init(struct pdma_hw *hw); + +/*! + * \brief Attach device driver. + * + * \param [in] dev Device structure point. + * + * \retval SHR_E_NONE No errors. + * \retval SHR_E_XXXX Operation failed. + */ +extern int +bcmcnet_cmicx_pdma_driver_attach(struct pdma_dev *dev); + +/*! + * \brief Detach device driver. + * + * \param [in] dev Device structure point. + * + * \retval SHR_E_NONE No errors. + * \retval SHR_E_XXXX Operation failed. + */ +extern int +bcmcnet_cmicx_pdma_driver_detach(struct pdma_dev *dev); + +#endif /* BCMCNET_CMICX_H */ + diff --git a/platform/broadcom/saibcm-modules/sdklt/bcmcnet/include/bcmcnet/bcmcnet_core.h b/platform/broadcom/saibcm-modules/sdklt/bcmcnet/include/bcmcnet/bcmcnet_core.h new file mode 100644 index 00000000000..13db809dda3 --- /dev/null +++ b/platform/broadcom/saibcm-modules/sdklt/bcmcnet/include/bcmcnet/bcmcnet_core.h @@ -0,0 +1,1323 @@ +/*! \file bcmcnet_core.h + * + * Generic data structure definitions and APIs for BCMCNET driver. + * + */ +/* + * $Copyright: Copyright 2018-2020 Broadcom. All rights reserved. + * The term 'Broadcom' refers to Broadcom Inc. and/or its subsidiaries. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * version 2 as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * A copy of the GNU General Public License version 2 (GPLv2) can + * be found in the LICENSES folder.$ + */ + +#ifndef BCMCNET_CORE_H +#define BCMCNET_CORE_H + +#include +#include + +/*! + * \brief Packet header structure. + */ +struct pkt_hdr { + /*! Meta data or outer header */ + uint8_t meta_data[16]; + + /*! Reserved */ + uint16_t rsvd0; + + /*! Packet signature */ + uint16_t pkt_sig; + + /*! Reserved */ + uint32_t rsvd1; + + /*! Data length */ + uint16_t data_len; + + /*! Reserved */ + uint16_t rsvd2; + + /*! Meta length */ + uint8_t meta_len; + + /*! Queue index */ + uint8_t queue_id; + + /*! Attributes */ + uint16_t attrs; + /*! Tx higig packet */ +#define PDMA_TX_HIGIG_PKT (1 << 0) + /*! Tx pause packet */ +#define PDMA_TX_PAUSE_PKT (1 << 1) + /*! Tx purge packet */ +#define PDMA_TX_PURGE_PKT (1 << 2) + /*! Tx queue number */ +#define PDMA_TX_BIND_QUE (1 << 3) + /*! Tx cookded header */ +#define PDMA_TX_HDR_COOKED (1 << 4) + /*! Tx to HNET */ +#define PDMA_TX_TO_HNET (1 << 5) + /*! Rx to VNET */ +#define PDMA_RX_TO_VNET (1 << 10) + /*! Rx strip vlan tag */ +#define PDMA_RX_STRIP_TAG (1 << 11) + /*! Rx set protocol type */ +#define PDMA_RX_SET_PROTO (1 << 12) + /*! Rx IP checksum */ +#define PDMA_RX_IP_CSUM (1 << 13) + /*! Rx TCPUDP checksum */ +#define PDMA_RX_TU_CSUM (1 << 14) +}; + +/*! Packet header size */ +#define PKT_HDR_SIZE sizeof(struct pkt_hdr) + +/*! + * \brief Packet buffer structure. + */ +struct pkt_buf { + /*! Packet header */ + struct pkt_hdr pkh; + + /*! Packet data */ + uint8_t data; +}; + +/*! + * \brief Interrupt handle. + */ +struct intr_handle { + /*! Device number */ + int unit; + + /*! Group number */ + int group; + + /*! Channel number */ + int chan; + + /*! Queue number */ + int queue; + + /*! Direction */ + int dir; + + /*! Polling budget */ + int budget; + + /*! Device point */ + void *dev; + + /*! Private point */ + void *priv; + + /*! Interrupt number */ + int intr_num; + + /*! Interrupt flags */ + uint32_t intr_flags; +}; + +/*! + * \brief Queue group structure. + */ +struct queue_group { + /*! Pointer to the device control structure */ + struct dev_ctrl *ctrl; + + /*! Interrupt handles */ + struct intr_handle intr_hdl[NUM_Q_PER_GRP]; + + /*! Rx queue pointers */ + void *rx_queue[NUM_Q_PER_GRP]; + + /*! Tx queue pointers */ + void *tx_queue[NUM_Q_PER_GRP]; + + /*! Virtual Rx queue pointers */ + void *vnet_rxq[NUM_Q_PER_GRP]; + + /*! Virtual Tx queue pointers */ + void *vnet_txq[NUM_Q_PER_GRP]; + + /*! Bitmap for Rx queues at work */ + uint32_t bm_rxq; + + /*! Bitmap for Tx queues at work */ + uint32_t bm_txq; + + /*! Number of Rx queues at work */ + uint32_t nb_rxq; + + /*! Number of Tx queues at work */ + uint32_t nb_txq; + + /*! Number of descriptors */ + uint32_t nb_desc[NUM_Q_PER_GRP]; + + /*! Rx buffer size */ + uint32_t rx_size[NUM_Q_PER_GRP]; + + /*! Queue mode */ + uint32_t que_ctrl[NUM_Q_PER_GRP]; + /*! Packet_byte_swap */ +#define PDMA_PKT_BYTE_SWAP (1 << 0) + /*! Non packet_byte_swap */ +#define PDMA_OTH_BYTE_SWAP (1 << 1) + /*! Header_byte_swap */ +#define PDMA_HDR_BYTE_SWAP (1 << 2) + + /*! Group ID */ + int id; + + /*! Queues need to poll */ + uint32_t poll_queues; + + /*! Active IRQs for DMA control */ + uint32_t irq_mask; + + /*! Indicating the group is attached */ + int attached; +}; + +/*! + * \brief Device control structure. + */ +struct dev_ctrl { + /*! Pointer to the device structure */ + struct pdma_dev *dev; + + /*! Pointer to hardware-specific data */ + void *hw; + + /*! HW base address */ + volatile void *hw_addr; + + /*! Queue groups */ + struct queue_group grp[NUM_GRP_MAX]; + + /*! Pointers to Rx queues */ + void *rx_queue[NUM_QUE_MAX]; + + /*! Pointers to Tx queues */ + void *tx_queue[NUM_QUE_MAX]; + + /*! Pointers to virtual Rx queues */ + void *vnet_rxq[NUM_QUE_MAX]; + + /*! Pointers to virtual Tx queues */ + void *vnet_txq[NUM_QUE_MAX]; + + /*! Pointer to buffer manager */ + void *buf_mngr; + + /*! VNET sync data */ + vnet_sync_t vsync; + + /*! Bitmap of groups at work */ + uint32_t bm_grp; + + /*! Bitmap of Rx queues at work */ + uint32_t bm_rxq; + + /*! Bitmap of Tx queues at work */ + uint32_t bm_txq; + + /*! Number of groups at work */ + uint32_t nb_grp; + + /*! Number of Rx queues at work */ + uint32_t nb_rxq; + + /*! Number of Tx queues at work */ + uint32_t nb_txq; + + /*! Number of descriptors for a queue */ + uint32_t nb_desc; + + /*! Budget for once queue processing */ + uint32_t budget; + + /*! Common Rx buffer size for all queues */ + uint32_t rx_buf_size; + + /*! Rx descriptor size */ + uint32_t rx_desc_size; + + /*! Tx descriptor size */ + uint32_t tx_desc_size; +}; + +/*! + * Configure device. + * + * \param [in] dev Pointer to device structure. + * \param [in] bm_rxq Rx queue bitmap. + * \param [in] bm_txq Tx queue bitmap. + * + * \retval SHR_E_NONE No errors. + * \retval SHR_E_XXXX Operation failed. + */ +typedef int (*pdma_dev_config_f)(struct pdma_dev *dev, uint32_t bm_rxq, uint32_t bm_txq); + +/*! + * Start device. + * + * \param [in] dev Pointer to device structure. + * + * \retval SHR_E_NONE No errors. + * \retval SHR_E_XXXX Operation failed. + */ +typedef int (*pdma_dev_start_f)(struct pdma_dev *dev); + +/*! + * Stop device. + * + * \param [in] dev Pointer to device structure. + * + * \retval SHR_E_NONE No errors. + * \retval SHR_E_XXXX Operation failed. + */ +typedef int (*pdma_dev_stop_f)(struct pdma_dev *dev); + +/*! + * Close device. + * + * \param [in] dev Pointer to device structure. + * + * \retval SHR_E_NONE No errors. + * \retval SHR_E_XXXX Operation failed. + */ +typedef int (*pdma_dev_close_f)(struct pdma_dev *dev); + +/*! + * Suspend device. + * + * \param [in] dev Pointer to device structure. + * + * \retval SHR_E_NONE No errors. + * \retval SHR_E_XXXX Operation failed. + */ +typedef int (*pdma_dev_suspend_f)(struct pdma_dev *dev); + +/*! + * Resume device. + * + * \param [in] dev Pointer to device structure. + * + * \retval SHR_E_NONE No errors. + * \retval SHR_E_XXXX Operation failed. + */ +typedef int (*pdma_dev_resume_f)(struct pdma_dev *dev); + +/*! + * Get device information. + * + * \param [in] dev Pointer to device structure. + */ +typedef void (*pdma_dev_info_get_f)(struct pdma_dev *dev); + +/*! + * Get device statistics. + * + * \param [in] dev Pointer to device structure. + */ +typedef void (*pdma_dev_stats_get_f)(struct pdma_dev *dev); + +/*! + * Reset device statistics. + * + * \param [in] dev Pointer to device structure. + */ +typedef void (*pdma_dev_stats_reset_f)(struct pdma_dev *dev); + +/*! + * Convert logic queue to physical queue. + * + * \param [in] dev Pointer to device structure. + * \param [in] queue Logic queue number. + * \param [in] dir Transmit direction. + * \param [in] chan Channel number. + * + * \retval SHR_E_NONE No errors. + * \retval SHR_E_XXXX Operation failed. + */ +typedef int (*pdma_dev_lq2pq_f)(struct pdma_dev *dev, int queue, int dir, int *chan); + +/*! + * Convert physical queue to logic queue. + * + * \param [in] dev Pointer to device structure. + * \param [in] chan Channel number. + * \param [in] queue Logic queue number. + * \param [in] dir Transmit direction. + * + * \retval SHR_E_NONE No errors. + * \retval SHR_E_XXXX Operation failed. + */ +typedef int (*pdma_dev_pq2lq_f)(struct pdma_dev *dev, int chan, int *queue, int *dir); + +/*! + * Start queue. + * + * \param [in] dev Pointer to device structure. + * \param [in] queue Queue number. + * + * \retval SHR_E_NONE No errors. + * \retval SHR_E_XXXX Operation failed. + */ +typedef int (*pdma_queue_start_f)(struct pdma_dev *dev, int queue); + +/*! + * Stop queue. + * + * \param [in] dev Pointer to device structure. + * \param [in] queue Queue number. + * + * \retval SHR_E_NONE No errors. + * \retval SHR_E_XXXX Operation failed. + */ +typedef int (*pdma_queue_stop_f)(struct pdma_dev *dev, int queue); + +/*! + * Set up queue. + * + * \param [in] dev Pointer to device structure. + * \param [in] queue Queue number. + * + * \retval SHR_E_NONE No errors. + * \retval SHR_E_XXXX Operation failed. + */ +typedef int (*pdma_queue_setup_f)(struct pdma_dev *dev, int queue); + +/*! + * Release queue. + * + * \param [in] dev Pointer to device structure. + * \param [in] queue Queue number. + * + * \retval SHR_E_NONE No errors. + * \retval SHR_E_XXXX Operation failed. + */ +typedef int (*pdma_queue_release_f)(struct pdma_dev *dev, int queue); + +/*! + * Restore queue. + * + * \param [in] dev Pointer to device structure. + * \param [in] queue Queue number. + * + * \retval SHR_E_NONE No errors. + * \retval SHR_E_XXXX Operation failed. + */ +typedef int (*pdma_queue_restore_f)(struct pdma_dev *dev, int queue); + +/*! + * Enable queue interrupt. + * + * \param [in] dev Pointer to device structure. + * \param [in] queue Queue number. + * + * \retval SHR_E_NONE No errors. + * \retval SHR_E_XXXX Operation failed. + */ +typedef int (*pdma_intr_enable_f)(struct pdma_dev *dev, int queue); + +/*! + * Disable queue interrupt. + * + * \param [in] dev Pointer to device structure. + * \param [in] queue Queue number. + * + * \retval SHR_E_NONE No errors. + * \retval SHR_E_XXXX Operation failed. + */ +typedef int (*pdma_intr_disable_f)(struct pdma_dev *dev, int queue); + +/*! + * Acknowledge queue interrupt. + * + * \param [in] dev Pointer to device structure. + * \param [in] queue Queue number. + * + * \retval SHR_E_NONE No errors. + * \retval SHR_E_XXXX Operation failed. + */ +typedef int (*pdma_intr_ack_f)(struct pdma_dev *dev, int queue); + +/*! + * Query queue interrupt. + * + * \param [in] dev Pointer to device structure. + * \param [in] queue Queue number. + * + * \retval SHR_E_NONE No errors. + * \retval SHR_E_XXXX Operation failed. + */ +typedef int (*pdma_intr_query_f)(struct pdma_dev *dev, int queue); + +/*! + * Check queue interrupt. + * + * \param [in] dev Pointer to device structure. + * \param [in] queue Queue number. + * + * \retval SHR_E_NONE No errors. + * \retval SHR_E_XXXX Operation failed. + */ +typedef int (*pdma_intr_check_f)(struct pdma_dev *dev, int queue); + +/*! + * Suspend Rx queue. + * + * \param [in] dev Pointer to device structure. + * \param [in] queue Queue number. + * + * \retval SHR_E_NONE No errors. + * \retval SHR_E_XXXX Operation failed. + */ +typedef int (*pdma_rx_queue_suspend_f)(struct pdma_dev *dev, int queue); + +/*! + * Resume Rx queue. + * + * \param [in] dev Pointer to device structure. + * \param [in] queue Queue number. + * + * \retval SHR_E_NONE No errors. + * \retval SHR_E_XXXX Operation failed. + */ +typedef int (*pdma_rx_queue_resume_f)(struct pdma_dev *dev, int queue); + +/*! + * Wake up Tx queue. + * + * \param [in] dev Pointer to device structure. + * \param [in] queue Queue number. + * + * \retval SHR_E_NONE No errors. + * \retval SHR_E_XXXX Operation failed. + */ +typedef int (*pdma_tx_queue_wakeup_f)(struct pdma_dev *dev, int queue); + +/*! + * Poll Rx queue. + * + * \param [in] dev Pointer to device structure. + * \param [in] queue Queue number. + * \param [in] budget Max number of descriptor to poll. + * + * \retval SHR_E_NONE No errors. + * \retval SHR_E_XXXX Operation failed. + */ +typedef int (*pdma_rx_queue_poll_f)(struct pdma_dev *dev, int queue, int budget); + +/*! + * Poll Tx queue. + * + * \param [in] dev Pointer to device structure. + * \param [in] queue Queue number. + * \param [in] budget Max number of descriptor to poll. + * + * \retval SHR_E_NONE No errors. + * \retval SHR_E_XXXX Operation failed. + */ +typedef int (*pdma_tx_queue_poll_f)(struct pdma_dev *dev, int queue, int budget); + +/*! + * Poll queue group. + * + * \param [in] dev Pointer to device structure. + * \param [in] queue Queue number. + * \param [in] budget Max number of descriptor to poll. + * + * \retval SHR_E_NONE No errors. + * \retval SHR_E_XXXX Operation failed. + */ +typedef int (*pdma_group_poll_f)(struct pdma_dev *dev, int group, int budget); + +/*! + * \brief Exported functions structure. + */ +struct dev_ops { + /*! Configure device */ + pdma_dev_config_f dev_config; + + /*! Start device */ + pdma_dev_start_f dev_start; + + /*! Stop device */ + pdma_dev_stop_f dev_stop; + + /*! Close device */ + pdma_dev_close_f dev_close; + + /*! Suspend device */ + pdma_dev_suspend_f dev_suspend; + + /*! Resume device */ + pdma_dev_resume_f dev_resume; + + /*! Get device information */ + pdma_dev_info_get_f dev_info_get; + + /*! Get device statistics */ + pdma_dev_stats_get_f dev_stats_get; + + /*! Reset device statistics */ + pdma_dev_stats_reset_f dev_stats_reset; + + /*! Logic queue to physical queue */ + pdma_dev_lq2pq_f dev_lq_to_pq; + + /*! Physical queue to logic queue */ + pdma_dev_pq2lq_f dev_pq_to_lq; + + /*! Start Rx for a queue */ + pdma_queue_start_f rx_queue_start; + + /*! Stop Rx for a queue */ + pdma_queue_stop_f rx_queue_stop; + + /*! Start Tx for a queue */ + pdma_queue_start_f tx_queue_start; + + /*! Stop Tx for a queue */ + pdma_queue_stop_f tx_queue_stop; + + /*! Set up Rx queue */ + pdma_queue_setup_f rx_queue_setup; + + /*! Release Rx queue */ + pdma_queue_release_f rx_queue_release; + + /*! Restore stopped Rx queue */ + pdma_queue_restore_f rx_queue_restore; + + /*! Set up virtual Rx queue */ + pdma_queue_setup_f rx_vqueue_setup; + + /*! Release virtual Rx queue */ + pdma_queue_release_f rx_vqueue_release; + + /*! Set up Tx queue */ + pdma_queue_setup_f tx_queue_setup; + + /*! Release Tx queue */ + pdma_queue_release_f tx_queue_release; + + /*! Restore stopped Tx queue */ + pdma_queue_restore_f tx_queue_restore; + + /*! Set up virtual Tx queue */ + pdma_queue_setup_f tx_vqueue_setup; + + /*! Release virtual Tx queue */ + pdma_queue_release_f tx_vqueue_release; + + /*! Enable Rx queue interrupt */ + pdma_intr_enable_f rx_queue_intr_enable; + + /*! Disable Rx queue interrupt */ + pdma_intr_disable_f rx_queue_intr_disable; + + /*! Acknowledge interrupt for Rx queue */ + pdma_intr_ack_f rx_queue_intr_ack; + + /*! Query interrupt status for Rx queue */ + pdma_intr_query_f rx_queue_intr_query; + + /*! Check interrupt validity for Rx queue */ + pdma_intr_check_f rx_queue_intr_check; + + /*! Enable Tx queue interrupt */ + pdma_intr_enable_f tx_queue_intr_enable; + + /*! Disable Tx queue interrupt */ + pdma_intr_disable_f tx_queue_intr_disable; + + /*! Acknowledge interrupt for Tx queue */ + pdma_intr_ack_f tx_queue_intr_ack; + + /*! Query interrupt status for Tx queue */ + pdma_intr_query_f tx_queue_intr_query; + + /*! Check interrupt validity for Tx queue */ + pdma_intr_check_f tx_queue_intr_check; + + /*! Suspend a Rx queue */ + pdma_rx_queue_suspend_f rx_queue_suspend; + + /*! Resume a Rx queue */ + pdma_rx_queue_resume_f rx_queue_resume; + + /*! Wake up a Tx queue to transmit */ + pdma_tx_queue_wakeup_f tx_queue_wakeup; + + /*! Poll for a Rx queue */ + pdma_rx_queue_poll_f rx_queue_poll; + + /*! Poll for a Tx queue */ + pdma_tx_queue_poll_f tx_queue_poll; + + /*! Poll for a group */ + pdma_group_poll_f group_poll; +}; + +/*! + * Read 32-bit device register. + * + * \param [in] dev Pointer to device structure. + * \param [in] addr Register address. + * \param [in] data Pointer to read data. + * + * \retval SHR_E_NONE No errors. + */ +typedef int (*reg32_read_f)(struct pdma_dev *dev, uint32_t addr, uint32_t *data); + +/*! + * Write 32-bit device register. + * + * \param [in] dev Pointer to device structure. + * \param [in] addr Register address. + * \param [in] data Data to write. + * + * \retval SHR_E_NONE No errors. + */ +typedef int (*reg32_write_f)(struct pdma_dev *dev, uint32_t addr, uint32_t data); + +/*! + * Receive packet. + * + * \param [in] dev Pointer to device structure. + * \param [in] queue Rx queue number. + * \param [in] buf Pointer to packet buffer. + * + * \retval SHR_E_NONE No errors. + */ +typedef int (*pdma_rx_f)(struct pdma_dev *dev, int queue, void *buf); + +/*! + * Transmit packet. + * + * \param [in] dev Pointer to device structure. + * \param [in] queue Tx queue number. + * \param [in] buf Pointer to packet buffer. + * + * \retval SHR_E_NONE No errors. + */ +typedef int (*pdma_tx_f)(struct pdma_dev *dev, int queue, void *buf); + +/*! + * Suspend Tx queue. + * + * \param [in] dev Pointer to device structure. + * \param [in] queue Tx queue number. + */ +typedef void (*sys_tx_suspend_f)(struct pdma_dev *dev, int queue); + +/*! + * Resume Tx queue. + * + * \param [in] dev Pointer to device structure. + * \param [in] queue Tx queue number. + */ +typedef void (*sys_tx_resume_f)(struct pdma_dev *dev, int queue); + +/*! + * Enable interrupts. + * + * \param [in] dev Pointer to device structure. + * \param [in] group Channel group number. + * \param [in] chan Channel number. + * \param [in] reg Interrupt enable register. + * \param [in] mask Interrupt mask. + */ +typedef void (*sys_intr_unmask_f)(struct pdma_dev *dev, int group, int chan, + uint32_t reg, uint32_t mask); + +/*! + * Disable interrupts. + * + * \param [in] dev Pointer to device structure. + * \param [in] group Channel group number. + * \param [in] chan Channel number. + * \param [in] reg Interrupt enable register. + * \param [in] mask Interrupt mask. + */ +typedef void (*sys_intr_mask_f)(struct pdma_dev *dev, int group, int chan, + uint32_t reg, uint32_t mask); + +/*! + * Wait for notification from the other side. + * + * \param [in] dev Pointer to device structure. + * + * \retval SHR_E_NONE No errors. + */ +typedef int (*xnet_wait_f)(struct pdma_dev *dev); + +/*! + * Wake up the other side. + * + * \param [in] dev Pointer to device structure. + * + * \retval SHR_E_NONE No errors. + */ +typedef int (*xnet_wake_f)(struct pdma_dev *dev); + +/*! + * Convert physical address to virtual address. + * + * \param [in] dev Pointer to device structure. + * \param [in] paddr Physical address. + * + * \retval Virtual address. + */ +typedef void *(*sys_p2v_f)(struct pdma_dev *dev, uint64_t paddr); + +/*! + * Convert virtual address to physical address. + * + * \param [in] dev Pointer to device structure. + * \param [in] vaddr Virtual address. + * + * \retval Physical address. + */ +typedef uint64_t (*sys_v2p_f)(struct pdma_dev *dev, void *vaddr); + +/*! + * \brief Device structure. + */ +struct pdma_dev { + /*! Device name */ + char name[DEV_NAME_LEN_MAX]; + + /*! Device ID */ + uint32_t dev_id; + + /*! Device type */ + uint32_t dev_type; + + /*! Device Number */ + int unit; + + /*! Device control structure */ + struct dev_ctrl ctrl; + + /*! Pointer to the exported funtions structure */ + struct dev_ops *ops; + + /*! Device information */ + struct bcmcnet_dev_info info; + + /*! Device statistics data */ + struct bcmcnet_dev_stats stats; + + /*! Private data */ + void *priv; + + /*! Read 32-bit device register */ + reg32_read_f dev_read32; + + /*! Write 32-bit device register */ + reg32_write_f dev_write32; + + /*! Packet reception */ + pdma_rx_f pkt_recv; + + /*! Packet transmission */ + pdma_tx_f pkt_xmit; + + /*! Tx suspend */ + sys_tx_suspend_f tx_suspend; + + /*! Tx resume */ + sys_tx_resume_f tx_resume; + + /*! Enable a set of interrupts */ + sys_intr_unmask_f intr_unmask; + + /*! Disable a set of interrupts */ + sys_intr_mask_f intr_mask; + + /*! Virtual network wait for */ + xnet_wait_f xnet_wait; + + /*! Virtual network wake up */ + xnet_wake_f xnet_wake; + + /*! Physical address to virtual address */ + sys_p2v_f sys_p2v; + + /*! Virtual address to physical address */ + sys_v2p_f sys_v2p; + + /*! Maximum number of groups */ + int num_groups; + + /*! Maximum number of group queues */ + int grp_queues; + + /*! Maximum number of queues */ + int num_queues; + + /*! Rx packet header size */ + uint32_t rx_ph_size; + + /*! Tx packet header size */ + uint32_t tx_ph_size; + + /*! Flags */ + uint32_t flags; + /*! Interrupt processing per group */ +#define PDMA_GROUP_INTR (1 << 0) + /*! Tx polling mode */ +#define PDMA_TX_POLLING (1 << 1) + /*! Rx batch refilling */ +#define PDMA_RX_BATCHING (1 << 2) + /*! DMA chain mode */ +#define PDMA_CHAIN_MODE (1 << 3) + /*! Descriptor prefetch mode */ +#define PDMA_DESC_PREFETCH (1 << 4) + /*! VNET is docked */ +#define PDMA_VNET_DOCKED (1 << 5) + + /*! Device mode */ + dev_mode_t mode; + + /*! Device is started */ + int started; + + /*! Device is initialized and HMI driver is attached */ + int attached; +}; + +/*! + * \brief Initialize device. + * + * \param [in] dev Device structure point. + * + * \retval SHR_E_NONE No errors. + * \retval SHR_E_XXXX Operation failed. + */ +extern int +bcmcnet_pdma_dev_init(struct pdma_dev *dev); + +/*! + * \brief Clean up device. + * + * \param [in] dev Device structure point. + * + * \retval SHR_E_NONE No errors. + * \retval SHR_E_XXXX Operation failed. + */ +extern int +bcmcnet_pdma_dev_cleanup(struct pdma_dev *dev); + +/*! + * \brief Start device. + * + * \param [in] dev Device structure point. + * + * \retval SHR_E_NONE No errors. + * \retval SHR_E_XXXX Operation failed. + */ +extern int +bcmcnet_pdma_dev_start(struct pdma_dev *dev); + +/*! + * \brief Stop device. + * + * \param [in] dev Device structure point. + * + * \retval SHR_E_NONE No errors. + * \retval SHR_E_XXXX Operation failed. + */ +extern int +bcmcnet_pdma_dev_stop(struct pdma_dev *dev); + +/*! + * \brief Suspend device. + * + * \param [in] dev Device structure point. + * + * \retval SHR_E_NONE No errors. + * \retval SHR_E_XXXX Operation failed. + */ +extern int +bcmcnet_pdma_dev_suspend(struct pdma_dev *dev); + +/*! + * \brief Resume device. + * + * \param [in] dev Device structure point. + * + * \retval SHR_E_NONE No errors. + * \retval SHR_E_XXXX Operation failed. + */ +extern int +bcmcnet_pdma_dev_resume(struct pdma_dev *dev); + +/*! + * \brief Suspend device Rx. + * + * \param [in] dev Device structure point. + * + * \retval SHR_E_NONE No errors. + * \retval SHR_E_XXXX Operation failed. + */ +extern int +bcmcnet_pdma_dev_rx_suspend(struct pdma_dev *dev); + +/*! + * \brief Resume device Rx. + * + * \param [in] dev Device structure point. + * + * \retval SHR_E_NONE No errors. + * \retval SHR_E_XXXX Operation failed. + */ +extern int +bcmcnet_pdma_dev_rx_resume(struct pdma_dev *dev); + +/*! + * \brief Dock device. + * + * \param [in] dev Device structure point. + * + * \retval SHR_E_NONE No errors. + * \retval SHR_E_XXXX Operation failed. + */ +extern int +bcmcnet_pdma_dev_dock(struct pdma_dev *dev); + +/*! + * \brief Undock device. + * + * \param [in] dev Device structure point. + * + * \retval SHR_E_NONE No errors. + * \retval SHR_E_XXXX Operation failed. + */ +extern int +bcmcnet_pdma_dev_undock(struct pdma_dev *dev); + +/*! + * \brief Get device information. + * + * \param [in] dev Device structure point. + * + * \retval SHR_E_NONE No errors. + * \retval SHR_E_XXXX Operation failed. + */ +extern int +bcmcnet_pdma_dev_info_get(struct pdma_dev *dev); + +/*! + * \brief Get device statistics. + * + * \param [in] dev Device structure point. + * + * \retval SHR_E_NONE No errors. + * \retval SHR_E_XXXX Operation failed. + */ +extern int +bcmcnet_pdma_dev_stats_get(struct pdma_dev *dev); + +/*! + * \brief Reset device statistics. + * + * \param [in] dev Device structure point. + * + * \retval SHR_E_NONE No errors. + * \retval SHR_E_XXXX Operation failed. + */ +extern int +bcmcnet_pdma_dev_stats_reset(struct pdma_dev *dev); + +/*! + * \brief Change queue number to channel number. + * + * \param [in] dev Device structure point. + * \param [in] queue Queue number. + * \param [in] dir Transmit direction. + * \param [out] chan Channel number. + * + * \retval SHR_E_NONE No errors. + * \retval SHR_E_XXXX Operation failed. + */ +extern int +bcmcnet_pdma_dev_queue_to_chan(struct pdma_dev *dev, int queue, int dir, int *chan); + +/*! + * \brief Change channel number to queue number. + * + * \param [in] dev Device structure point. + * \param [in] chan Channel number. + * \param [out] queue Queue number. + * \param [out] dir Transmit direction. + * + * \retval SHR_E_NONE No errors. + * \retval SHR_E_XXXX Operation failed. + */ +extern int +bcmcnet_pdma_dev_chan_to_queue(struct pdma_dev *dev, int chan, int *queue, int *dir); + +/*! + * \brief Enable Rx queue interrupt. + * + * \param [in] dev Device structure point. + * \param [in] queue Rx queue number. + * + * \retval SHR_E_NONE No errors. + * \retval SHR_E_XXXX Operation failed. + */ +extern int +bcmcnet_rx_queue_intr_enable(struct pdma_dev *dev, int queue); + +/*! + * \brief Disable Rx queue interrupt. + * + * \param [in] dev Device structure point. + * \param [in] queue Rx queue number. + * + * \retval SHR_E_NONE No errors. + * \retval SHR_E_XXXX Operation failed. + */ +extern int +bcmcnet_rx_queue_intr_disable(struct pdma_dev *dev, int queue); + +/*! + * \brief Acknowledge Rx queue interrupt. + * + * \param [in] dev Device structure point. + * \param [in] queue Rx queue number. + * + * \retval SHR_E_NONE No errors. + * \retval SHR_E_XXXX Operation failed. + */ +extern int +bcmcnet_rx_queue_intr_ack(struct pdma_dev *dev, int queue); + +/*! + * \brief Check Rx queue interrupt. + * + * \param [in] dev Device structure point. + * \param [in] queue Rx queue number. + * + * \retval SHR_E_NONE No errors. + * \retval SHR_E_XXXX Operation failed. + */ +extern int +bcmcnet_rx_queue_intr_check(struct pdma_dev *dev, int queue); + +/*! + * \brief Enable Tx queue interrupt. + * + * \param [in] dev Device structure point. + * \param [in] queue Tx queue number. + * + * \retval SHR_E_NONE No errors. + * \retval SHR_E_XXXX Operation failed. + */ +extern int +bcmcnet_tx_queue_intr_enable(struct pdma_dev *dev, int queue); + +/*! + * \brief Disable Tx queue interrupt. + * + * \param [in] dev Device structure point. + * \param [in] queue Tx queue number. + * + * \retval SHR_E_NONE No errors. + * \retval SHR_E_XXXX Operation failed. + */ +extern int +bcmcnet_tx_queue_intr_disable(struct pdma_dev *dev, int queue); + +/*! + * \brief Acknowledge Tx queue interrupt. + * + * \param [in] dev Device structure point. + * \param [in] queue Tx queue number. + * + * \retval SHR_E_NONE No errors. + * \retval SHR_E_XXXX Operation failed. + */ +extern int +bcmcnet_tx_queue_intr_ack(struct pdma_dev *dev, int queue); + +/*! + * \brief Check Tx queue interrupt. + * + * \param [in] dev Device structure point. + * \param [in] queue Tx queue number. + * + * \retval SHR_E_NONE No errors. + * \retval SHR_E_XXXX Operation failed. + */ +extern int +bcmcnet_tx_queue_intr_check(struct pdma_dev *dev, int queue); + +/*! + * \brief Enable queue interrupt. + * + * \param [in] dev Device structure point. + * \param [in] hdl Queue interrupt handle. + * + * \retval SHR_E_NONE No errors. + * \retval SHR_E_XXXX Operation failed. + */ +extern int +bcmcnet_queue_intr_enable(struct pdma_dev *dev, struct intr_handle *hdl); + +/*! + * \brief Disable queue interrupt. + * + * \param [in] dev Device structure point. + * \param [in] hdl Queue interrupt handle. + * + * \retval SHR_E_NONE No errors. + * \retval SHR_E_XXXX Operation failed. + */ +extern int +bcmcnet_queue_intr_disable(struct pdma_dev *dev, struct intr_handle *hdl); + +/*! + * \brief Acknowledge queue interrupt. + * + * \param [in] dev Device structure point. + * \param [in] hdl Queue interrupt handle. + * + * \retval SHR_E_NONE No errors. + * \retval SHR_E_XXXX Operation failed. + */ +extern int +bcmcnet_queue_intr_ack(struct pdma_dev *dev, struct intr_handle *hdl); + +/*! + * \brief Check queue interrupt. + * + * \param [in] dev Device structure point. + * \param [in] hdl Queue interrupt handle. + * + * \retval SHR_E_NONE No errors. + * \retval SHR_E_XXXX Operation failed. + */ +extern int +bcmcnet_queue_intr_check(struct pdma_dev *dev, struct intr_handle *hdl); + +/*! + * \brief Enable group interrupt. + * + * \param [in] dev Device structure point. + * \param [in] group Group number. + * + * \retval SHR_E_NONE No errors. + * \retval SHR_E_XXXX Operation failed. + */ +extern int +bcmcnet_group_intr_enable(struct pdma_dev *dev, int group); + +/*! + * \brief Disable group interrupt. + * + * \param [in] dev Device structure point. + * \param [in] group Group number. + * + * \retval SHR_E_NONE No errors. + * \retval SHR_E_XXXX Operation failed. + */ +extern int +bcmcnet_group_intr_disable(struct pdma_dev *dev, int group); + +/*! + * \brief Acknowledge group interrupt. + * + * \param [in] dev Device structure point. + * \param [in] group Group number. + * + * \retval SHR_E_NONE No errors. + * \retval SHR_E_XXXX Operation failed. + */ +extern int +bcmcnet_group_intr_ack(struct pdma_dev *dev, int group); + +/*! + * \brief Check group interrupt. + * + * \param [in] dev Device structure point. + * \param [in] group Group number. + * + * \retval SHR_E_NONE No errors. + * \retval SHR_E_XXXX Operation failed. + */ +extern int +bcmcnet_group_intr_check(struct pdma_dev *dev, int group); + +/*! + * \brief Poll Rx queue. + * + * \param [in] dev Device structure point. + * \param [in] queue Rx queue number. + * \param [in] budget Poll budget. + * + * \retval SHR_E_NONE No errors. + * \retval SHR_E_XXXX Operation failed. + */ +extern int +bcmcnet_rx_queue_poll(struct pdma_dev *dev, int queue, int budget); + +/*! + * \brief Poll Tx queue. + * + * \param [in] dev Device structure point. + * \param [in] queue Tx queue number. + * \param [in] budget Poll budget. + * + * \retval SHR_E_NONE No errors. + * \retval SHR_E_XXXX Operation failed. + */ +extern int +bcmcnet_tx_queue_poll(struct pdma_dev *dev, int queue, int budget); + +/*! + * \brief Poll queue. + * + * \param [in] dev Device structure point. + * \param [in] hdl Queue interrupt handle. + * \param [in] budget Poll budget. + * + * \retval SHR_E_NONE No errors. + * \retval SHR_E_XXXX Operation failed. + */ +extern int +bcmcnet_queue_poll(struct pdma_dev *dev, struct intr_handle *hdl, int budget); + +/*! + * \brief Poll group. + * + * \param [in] dev Device structure point. + * \param [in] group Group number. + * \param [in] budget Poll budget. + * + * \retval SHR_E_NONE No errors. + * \retval SHR_E_XXXX Operation failed. + */ +extern int +bcmcnet_group_poll(struct pdma_dev *dev, int group, int budget); + +#endif /* BCMCNET_CORE_H */ + diff --git a/platform/broadcom/saibcm-modules/sdklt/bcmcnet/include/bcmcnet/bcmcnet_dev.h b/platform/broadcom/saibcm-modules/sdklt/bcmcnet/include/bcmcnet/bcmcnet_dev.h new file mode 100644 index 00000000000..bc3367b34fa --- /dev/null +++ b/platform/broadcom/saibcm-modules/sdklt/bcmcnet/include/bcmcnet/bcmcnet_dev.h @@ -0,0 +1,544 @@ +/*! \file bcmcnet_dev.h + * + * Generic data structure and macro definitions for BCMCNET device. + * + */ +/* + * $Copyright: Copyright 2018-2020 Broadcom. All rights reserved. + * The term 'Broadcom' refers to Broadcom Inc. and/or its subsidiaries. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * version 2 as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * A copy of the GNU General Public License version 2 (GPLv2) can + * be found in the LICENSES folder.$ + */ + +#ifndef BCMCNET_DEV_H +#define BCMCNET_DEV_H + +#include + +/*! + * \brief HW information. + */ +struct hw_info { + /*! HW name */ + char *name; + + /*! HW version */ + int ver_no; + + /*! Device ID */ + uint32_t dev_id; + + /*! Revision ID */ + uint32_t rev_id; + + /*! Number of CMCs */ + uint32_t num_cmcs; + + /*! Number of CMC channels */ + uint32_t cmc_chans; + + /*! Number of channels */ + uint32_t num_chans; + + /*! Rx DCB size */ + uint32_t rx_dcb_size; + + /*! Tx DCB size */ + uint32_t tx_dcb_size; + + /*! Rx packet header size */ + uint32_t rx_ph_size; + + /*! Tx packet header size */ + uint32_t tx_ph_size; + + /*! HW structure point */ + struct pdma_hw *hw; +}; + +/*! + * \brief Read 32-bit register. + * + * \param [in] hw Pointer to hardware structure. + * \param [in] addr Register address. + * \param [in] data Pointer to read data. + */ +typedef void (*reg_rd32_f)(struct pdma_hw *hw, uint32_t addr, uint32_t *data); + +/*! + * \brief Write 32-bit register. + * + * \param [in] hw Pointer to hardware structure. + * \param [in] addr Register address. + * \param [in] data Data to write. + */ +typedef void (*reg_wr32_f)(struct pdma_hw *hw, uint32_t addr, uint32_t data); + +/*! + * \brief Pre-initialize hardware. + * + * \param [in] hw Pointer to hardware structure. + * + * \retval SHR_E_NONE No errors. + */ +typedef int (*pre_init_f)(struct pdma_hw *hw); + +/*! + * \brief Initialize hardware. + * + * \param [in] hw Pointer to hardware structure. + * + * \retval SHR_E_NONE No errors. + */ +typedef int (*hw_init_f)(struct pdma_hw *hw); + +/*! + * \brief Configure hardware. + * + * \param [in] hw Pointer to hardware structure. + * + * \retval SHR_E_NONE No errors. + */ +typedef int (*hw_config_f)(struct pdma_hw *hw); + +/*! + * \brief Reset hardware. + * + * \param [in] hw Pointer to hardware structure. + * + * \retval SHR_E_NONE No errors. + */ +typedef int (*hw_reset_f)(struct pdma_hw *hw); + +/*! + * \brief Start channel. + * + * \param [in] hw Pointer to hardware structure. + * \param [in] chan Channel number. + * + * \retval SHR_E_NONE No errors. + */ +typedef int (*chan_start_f)(struct pdma_hw *hw, int chan); + +/*! + * \brief Stop channel. + * + * \param [in] hw Pointer to hardware structure. + * \param [in] chan Channel number. + * + * \retval SHR_E_NONE No errors. + */ +typedef int (*chan_stop_f)(struct pdma_hw *hw, int chan); + +/*! + * \brief Set up channel. + * + * \param [in] hw Pointer to hardware structure. + * \param [in] chan Channel number. + * \param [in] addr Start DMA address of descriptors. + * + * \retval SHR_E_NONE No errors. + */ +typedef int (*chan_setup_f)(struct pdma_hw *hw, int chan, uint64_t addr); + +/*! + * \brief Go to ohter descriptor. + * + * \param [in] hw Pointer to hardware structure. + * \param [in] chan Channel number. + * \param [in] addr Destination DMA address of descriptors. + * + * \retval SHR_E_NONE No errors. + */ +typedef int (*chan_goto_f)(struct pdma_hw *hw, int chan, uint64_t addr); + +/*! + * \brief Clear channel. + * + * \param [in] hw Pointer to hardware structure. + * \param [in] chan Channel number. + * + * \retval SHR_E_NONE No errors. + */ +typedef int (*chan_clear_f)(struct pdma_hw *hw, int chan); + +/*! + * \brief Get interrupt number. + * + * \param [in] hw Pointer to hardware structure. + * \param [in] chan Channel number. + * + * \retval Returned interrupt number, errors if negative value. + */ +typedef int (*chan_intr_num_get_f)(struct pdma_hw *hw, int chan); + +/*! + * \brief Enable interrupt. + * + * \param [in] hw Pointer to hardware structure. + * \param [in] chan Channel number. + * + * \retval SHR_E_NONE No errors. + */ +typedef int (*chan_intr_enable_f)(struct pdma_hw *hw, int chan); + +/*! + * \brief Disable interrupt. + * + * \param [in] hw Pointer to hardware structure. + * \param [in] chan Channel number. + * + * \retval SHR_E_NONE No errors. + */ +typedef int (*chan_intr_disable_f)(struct pdma_hw *hw, int chan); + +/*! + * \brief Query interrupt. + * + * \param [in] hw Pointer to hardware structure. + * \param [in] chan Channel number. + * + * \retval SHR_E_NONE No errors. + */ +typedef int (*chan_intr_query_f)(struct pdma_hw *hw, int chan); + +/*! + * \brief Check interrupt. + * + * \param [in] hw Pointer to hardware structure. + * \param [in] chan Channel number. + * + * \retval SHR_E_NONE No errors. + */ +typedef int (*chan_intr_check_f)(struct pdma_hw *hw, int chan); + +/*! + * \brief Coalesce interrupt. + * + * \param [in] hw Pointer to hardware structure. + * \param [in] chan Channel number. + * \param [in] count Count value to trigger interrupt. + * \param [in] timer Timer value to triggre interrupt. + * + * \retval SHR_E_NONE No errors. + */ +typedef int (*chan_intr_coalesce_f)(struct pdma_hw *hw, int chan, int count, int timer); + +/*! + * \brief Dump registers. + * + * \param [in] hw Pointer to hardware structure. + * \param [in] chan Channel number. + * + * \retval SHR_E_NONE No errors. + */ +typedef int (*chan_reg_dump_f)(struct pdma_hw *hw, int chan); + +/*! + * \brief HW handlers. + */ +struct hw_handlers { + /*! 32 bits register read */ + reg_rd32_f reg_rd32; + + /*! 32 bits register write */ + reg_wr32_f reg_wr32; + + /*! HW pre-initialize */ + pre_init_f pre_init; + + /*! HW initialize */ + hw_init_f hw_init; + + /*! HW configure */ + hw_config_f hw_config; + + /*! HW reset */ + hw_reset_f hw_reset; + + /*! Channel start */ + chan_start_f chan_start; + + /*! Channel stop */ + chan_stop_f chan_stop; + + /*! Channel setup */ + chan_setup_f chan_setup; + + /*! Channel goto */ + chan_goto_f chan_goto; + + /*! Channel clear */ + chan_clear_f chan_clear; + + /*! Channel interrupt number get */ + chan_intr_num_get_f chan_intr_num_get; + + /*! Channel interrupt enable */ + chan_intr_enable_f chan_intr_enable; + + /*! Channel interrupt disable */ + chan_intr_disable_f chan_intr_disable; + + /*! Channel interrupt query */ + chan_intr_query_f chan_intr_query; + + /*! Channel interrupt check */ + chan_intr_check_f chan_intr_check; + + /*! Channel interrupt coalesce */ + chan_intr_coalesce_f chan_intr_coalesce; + + /*! Channel registers dump */ + chan_reg_dump_f chan_reg_dump; +}; + +/*! + * \brief Initialize Rx descriptor. + * + * \param [in] hw Pointer to hardware structure. + * \param [in] rxq Pointer to Rx queue struture. + * + * \retval SHR_E_NONE No errors. + * \retval SHR_E_MEMORY Allocation failed. + */ +typedef int (*rx_desc_init_f)(struct pdma_hw *hw, struct pdma_rx_queue *rxq); + +/*! + * \brief Clean up Rx descriptor. + * + * \param [in] hw Pointer to hardware structure. + * \param [in] rxq Pointer to Rx queue struture. + * + * \retval SHR_E_NONE No errors. + */ +typedef int (*rx_desc_clean_f)(struct pdma_hw *hw, struct pdma_rx_queue *rxq); + +/*! + * \brief Clean up Rx ring. + * + * \param [in] hw Pointer to hardware structure. + * \param [in] rxq Pointer to Rx queue struture. + * \param [in] budget Budget for each operation. + * + * \retval Number of descriptors finished. + */ +typedef int (*rx_ring_clean_f)(struct pdma_hw *hw, struct pdma_rx_queue *rxq, int budget); + +/*! + * \brief Dump Rx ring. + * + * \param [in] hw Pointer to hardware structure. + * \param [in] rxq Pointer to Rx queue struture. + * + * \retval SHR_E_NONE No errors. + */ +typedef int (*rx_ring_dump_f)(struct pdma_hw *hw, struct pdma_rx_queue *rxq); + +/*! + * \brief Suspend Rx queue. + * + * \param [in] hw Pointer to hardware structure. + * \param [in] rxq Pointer to Rx queue struture. + * + * \retval SHR_E_NONE No errors. + */ +typedef int (*rx_suspend_f)(struct pdma_hw *hw, struct pdma_rx_queue *rxq); + +/*! + * \brief Resume Rx queue. + * + * \param [in] hw Pointer to hardware structure. + * \param [in] rxq Pointer to Rx queue struture. + * + * \retval SHR_E_NONE No errors. + */ +typedef int (*rx_resume_f)(struct pdma_hw *hw, struct pdma_rx_queue *rxq); + +/*! + * \brief Initialize Tx descriptor. + * + * \param [in] hw Pointer to hardware structure. + * \param [in] txq Pointer to Tx queue struture. + * + * \retval SHR_E_NONE No errors. + * \retval SHR_E_MEMORY Allocation failed. + */ +typedef int (*tx_desc_init_f)(struct pdma_hw *hw, struct pdma_tx_queue *txq); + +/*! + * \brief Clean up Tx descriptor. + * + * \param [in] hw Pointer to hardware structure. + * \param [in] txq Pointer to Tx queue struture. + * + * \retval SHR_E_NONE No errors. + */ +typedef int (*tx_desc_clean_f)(struct pdma_hw *hw, struct pdma_tx_queue *txq); + +/*! + * \brief Clean up Tx ring. + * + * \param [in] hw Pointer to hardware structure. + * \param [in] txq Pointer to Tx queue struture. + * \param [in] budget Budget for each operation. + * + * \retval Number of descriptors finished. + */ +typedef int (*tx_ring_clean_f)(struct pdma_hw *hw, struct pdma_tx_queue *txq, int budget); + +/*! + * \brief Dump Tx ring. + * + * \param [in] hw Pointer to hardware structure. + * \param [in] txq Pointer to Tx queue struture. + * + * \retval SHR_E_NONE No errors. + */ +typedef int (*tx_ring_dump_f)(struct pdma_hw *hw, struct pdma_tx_queue *txq); + +/*! + * \brief Transmit packet. + * + * \param [in] hw Pointer to hardware structure. + * \param [in] txq Pointer to Tx queue struture. + * \param [in] buf Pointer to packet buffer struture. + * + * \retval SHR_E_NONE No errors. + * \retval SHR_E_XXXX Operation failed. + */ +typedef int (*pkt_xmit_f)(struct pdma_hw *hw, struct pdma_tx_queue *txq, void *buf); + +/*! + * \brief Descriptor operations. + */ +struct desc_operations { + /*! Rx descriptor initialize */ + rx_desc_init_f rx_desc_init; + + /*! Rx descriptor cleanup */ + rx_desc_clean_f rx_desc_clean; + + /*! Rx ring cleanup */ + rx_ring_clean_f rx_ring_clean; + + /*! Rx ring dump */ + rx_ring_dump_f rx_ring_dump; + + /*! Rx suspend */ + rx_suspend_f rx_suspend; + + /*! Rx resume */ + rx_resume_f rx_resume; + + /*! Tx descriptor initialize */ + tx_desc_init_f tx_desc_init; + + /*! Tx descriptor cleanup */ + tx_desc_clean_f tx_desc_clean; + + /*! Tx ring cleanup */ + tx_ring_clean_f tx_ring_clean; + + /*! Tx ring dump */ + tx_ring_dump_f tx_ring_dump; + + /*! Tx transmit */ + pkt_xmit_f pkt_xmit; +}; + +/*! + * \brief HW structure. + */ +struct pdma_hw { + /*! Device number */ + int unit; + + /*! Device structure point */ + struct pdma_dev *dev; + + /*! HW information */ + struct hw_info info; + + /*! HW handlers */ + struct hw_handlers hdls; + + /*! HW operations */ + struct desc_operations dops; +}; + +/*! + * \brief Open device. + * + * \param [in] dev Device structure point. + * + * \retval SHR_E_NONE No errors. + * \retval SHR_E_XXXX Operation failed. + */ +extern int +bcmcnet_pdma_open(struct pdma_dev *dev); + +/*! + * \brief Coalesce Rx interrupt. + * + * \param [in] dev Device structure point. + * \param [in] queue Rx queue number. + * \param [in] count Interrupt threshhold. + * \param [in] timer Timer value. + * + * \retval SHR_E_NONE No errors. + * \retval SHR_E_XXXX Operation failed. + */ +extern int +bcmcnet_pdma_rx_queue_int_coalesce(struct pdma_dev *dev, int queue, int count, int timer); + +/*! + * \brief Coalesce Tx interrupt. + * + * \param [in] dev Device structure point. + * \param [in] queue Tx queue number. + * \param [in] count Interrupt threshhold. + * \param [in] timer Timer value. + * + * \retval SHR_E_NONE No errors. + * \retval SHR_E_XXXX Operation failed. + */ +extern int +bcmcnet_pdma_tx_queue_int_coalesce(struct pdma_dev *dev, int queue, int count, int timer); + +/*! + * \brief Dump Rx queue registers. + * + * \param [in] dev Device structure point. + * \param [in] queue Rx queue number. + * + * \retval SHR_E_NONE No errors. + * \retval SHR_E_XXXX Operation failed. + */ +extern int +bcmcnet_pdma_rx_queue_reg_dump(struct pdma_dev *dev, int queue); + +/*! + * \brief Dump Tx queue registers. + * + * \param [in] dev Device structure point. + * \param [in] queue Tx queue number. + * + * \retval SHR_E_NONE No errors. + * \retval SHR_E_XXXX Operation failed. + */ +extern int +bcmcnet_pdma_tx_queue_reg_dump(struct pdma_dev *dev, int queue); + +#endif /* BCMCNET_DEV_H */ + diff --git a/platform/broadcom/saibcm-modules/sdklt/bcmcnet/include/bcmcnet/bcmcnet_internal.h b/platform/broadcom/saibcm-modules/sdklt/bcmcnet/include/bcmcnet/bcmcnet_internal.h new file mode 100644 index 00000000000..e4b2051a34b --- /dev/null +++ b/platform/broadcom/saibcm-modules/sdklt/bcmcnet/include/bcmcnet/bcmcnet_internal.h @@ -0,0 +1,305 @@ +/*! \file bcmcnet_internal.h + * + * BCMCNET internal data structure and macro definitions. + * + */ +/* + * $Copyright: Copyright 2018-2020 Broadcom. All rights reserved. + * The term 'Broadcom' refers to Broadcom Inc. and/or its subsidiaries. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * version 2 as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * A copy of the GNU General Public License version 2 (GPLv2) can + * be found in the LICENSES folder.$ + */ + +#ifndef BCMCNET_INTERNAL_H +#define BCMCNET_INTERNAL_H + +#include + +/*! CMICD name */ +#define CMICD_DEV_NAME "cmicd" + +/*! CMICX name */ +#define CMICX_DEV_NAME "cmicx" + +/*! + * \brief Allocate descriptor ring buffer. + * + * \param [in] dev Pointer to Packet DMA device. + * \param [in] dma DMA address of ring buffer. + * + * \retval Pointer to DMA buffer or NULL if an error occurred. + */ +typedef void *(*ring_buf_alloc_f)(struct pdma_dev *dev, uint32_t, dma_addr_t *dma); + +/*! + * \brief Free descriptor ring buffer. + * + * \param [in] dev Pointer to Packet DMA device. + * \param [in] size Size of DMA buffer. + * \param [in] mem Pointer to DMA buffer. + * \param [in] dma DMA address of ring buffer. + */ +typedef void (*ring_buf_free_f)(struct pdma_dev *dev, uint32_t size, void *mem, + dma_addr_t dma); + +/*! + * \brief Allocate Rx packet buffer. + * + * \param [in] dev Pointer to Packet DMA device. + * \param [in] rxq Pointer to Rx queue struture. + * \param [in] pbuf Pointer to packet buffer structure. + * + * \retval SHR_E_NONE No errors. + * \retval SHR_E_MEMORY Allocation failed. + */ +typedef int (*rx_buf_alloc_f)(struct pdma_dev *dev, struct pdma_rx_queue *rxq, + struct pdma_rx_buf *pbuf); + +/*! + * \brief Get Rx packet buffer DMA address. + * + * \param [in] dev Pointer to Packet DMA device. + * \param [in] rxq Pointer to Rx queue struture. + * \param [in] pbuf Pointer to packet buffer structure. + * \param [in] dma DMA address of packet buffer. + */ +typedef void (*rx_buf_dma_f)(struct pdma_dev *dev, struct pdma_rx_queue *rxq, + struct pdma_rx_buf *pbuf, dma_addr_t *dma); + +/*! + * \brief Check Rx packet buffer validity. + * + * \param [in] dev Pointer to Packet DMA device. + * \param [in] rxq Pointer to Rx queue struture. + * \param [in] pbuf Pointer to packet buffer structure. + * + * \retval Ture Buffer is available or FALSE. + */ +typedef int (*rx_buf_avail_f)(struct pdma_dev *dev, struct pdma_rx_queue *rxq, + struct pdma_rx_buf *pbuf); + +/*! + * \brief Get Rx packet buffer. + * + * \param [in] dev Pointer to Packet DMA device. + * \param [in] rxq Pointer to Rx queue struture. + * \param [in] pbuf Pointer to packet buffer structure. + * \param [in] len Packet length. + * + * \retval Pointer to packet header structure or NULL if failed. + */ +typedef struct pkt_hdr *(*rx_buf_get_f)(struct pdma_dev *dev, struct pdma_rx_queue *rxq, + struct pdma_rx_buf *pbuf, int len); + +/*! + * \brief Put Rx packet buffer. + * + * \param [in] dev Pointer to Packet DMA device. + * \param [in] rxq Pointer to Rx queue struture. + * \param [in] pbuf Pointer to packet buffer structure. + * \param [in] len Packet length. + * + * \retval SHR_E_NONE No errors. + * \retval SHR_E_MEMORY Allocation failed. + */ +typedef int (*rx_buf_put_f)(struct pdma_dev *dev, struct pdma_rx_queue *rxq, + struct pdma_rx_buf *pbuf, int len); + +/*! + * \brief Free Rx packet buffer. + * + * \param [in] dev Pointer to Packet DMA device. + * \param [in] rxq Pointer to Rx queue struture. + * \param [in] pbuf Pointer to packet buffer structure. + */ +typedef void (*rx_buf_free_f)(struct pdma_dev *dev, struct pdma_rx_queue *rxq, + struct pdma_rx_buf *pbuf); + +/*! + * \brief Get Rx packet buffer mode. + * + * \param [in] dev Pointer to Packet DMA device. + * \param [in] rxq Pointer to Rx queue struture. + * + * \retval Buffer mode. + */ +typedef enum buf_mode (*rx_buf_mode_f)(struct pdma_dev *dev, struct pdma_rx_queue *rxq); + +/*! + * \brief Get Tx packet buffer. + * + * \param [in] dev Pointer to Packet DMA device. + * \param [in] txq Pointer to Rx queue struture. + * \param [in] pbuf Pointer to packet buffer structure. + * \param [in] buf Packet buffer. + * + * \retval Pointer to packet header structure or NULL if failed. + */ +typedef struct pkt_hdr *(*tx_buf_get_f)(struct pdma_dev *dev, struct pdma_tx_queue *txq, + struct pdma_tx_buf *pbuf, void *buf); + +/*! + * \brief Get Tx packet buffer DMA address. + * + * \param [in] dev Pointer to Packet DMA device. + * \param [in] txq Pointer to Rx queue struture. + * \param [in] pbuf Pointer to packet buffer structure. + * \param [in] dma DMA address of packet buffer. + */ +typedef void (*tx_buf_dma_f)(struct pdma_dev *dev, struct pdma_tx_queue *txq, + struct pdma_tx_buf *pbuf, dma_addr_t *dma); + +/*! + * \brief Free Tx packet buffer. + * + * \param [in] dev Pointer to Packet DMA device. + * \param [in] txq Pointer to Rx queue struture. + * \param [in] pbuf Pointer to packet buffer structure. + */ +typedef void (*tx_buf_free_f)(struct pdma_dev *dev, struct pdma_tx_queue *txq, + struct pdma_tx_buf *pbuf); + +/*! + * \brief Buffer manager. + */ +struct pdma_buf_mngr { + /*! Allocate descriptor ring buffer */ + ring_buf_alloc_f ring_buf_alloc; + + /*! Free descriptor ring buffer */ + ring_buf_free_f ring_buf_free; + + /*! Allocate Rx packet buffer */ + rx_buf_alloc_f rx_buf_alloc; + + /*! Get Rx packet buffer DMA address */ + rx_buf_dma_f rx_buf_dma; + + /*! Check Rx packet buffer validity */ + rx_buf_avail_f rx_buf_avail; + + /*! Get Rx packet buffer */ + rx_buf_get_f rx_buf_get; + + /*! Put Rx packet buffer */ + rx_buf_put_f rx_buf_put; + + /*! Free Rx packet buffer */ + rx_buf_free_f rx_buf_free; + + /*! Get Rx packet buffer mode */ + rx_buf_mode_f rx_buf_mode; + + /*! Get Tx packet buffer */ + tx_buf_get_f tx_buf_get; + + /*! Get Tx packet buffer DMA address */ + tx_buf_dma_f tx_buf_dma; + + /*! Free Tx packet buffer */ + tx_buf_free_f tx_buf_free; +}; + +/*! + * \brief Wait for the kernel networking subsystem. + * + * \param [in] unit Device number. + * + * \retval SHR_E_NONE No errors. + * \retval SHR_E_FAIL Operation failed. + */ +typedef int (*bcmcnet_vnet_wait_f)(int unit); + +/*! + * \brief Wake up the kernel networking subsystem. + * + * \param [in] unit Device number. + * + * \retval SHR_E_NONE No errors. + * \retval SHR_E_FAIL Operation failed. + */ +typedef int (*bcmcnet_hnet_wake_f)(int unit); + +/*! + * \brief Dock to the kernel networking subsystem. + * + * \param [in] unit Device number. + * \param [in] vsync Sync data. + * + * \retval SHR_E_NONE No errors. + * \retval SHR_E_FAIL Operation failed. + */ +typedef int (*bcmcnet_vnet_dock_f)(int unit, vnet_sync_t *vsync); + +/*! + * \brief Undock from the kernel networking subsystem. + * + * \param [in] unit Device number. + * + * \retval SHR_E_NONE No errors. + * \retval SHR_E_FAIL Operation failed. + */ +typedef int (*bcmcnet_vnet_undock_f)(int unit); + +/*! + * \brief VNET operations. + */ +typedef struct bcmcnet_vnet_ops_s { + /*! + * VNET wait for HNET. + * VNET calls this to wait for any notification from HNET. + */ + bcmcnet_vnet_wait_f vnet_wait; + + /*! + * VNET wake up HNET. + * VNET calls this to notify HNET that Tx/Rx is ready. + */ + bcmcnet_hnet_wake_f hnet_wake; + + /*! + * VNET dock to HNET. + * This is called to notify HNET that VNET is ready to work and synchronize + * vrings information to HNET. + */ + bcmcnet_vnet_dock_f vnet_dock; + + /*! + * VNET undock from HNET. + * This is called to notify HNET that VNET is ready to leave. + */ + bcmcnet_vnet_undock_f vnet_undock; +} bcmcnet_vnet_ops_t; + +/*! + * \brief Initialize buffer manager. + * + * \param [in] dev Device structure pointer. + */ +extern void +bcmcnet_buf_mngr_init(struct pdma_dev *dev); + +/*! + * \brief Register VNET operations. + * + * \param [in] unit Device number. + * \param [in] vnet_ops VNET operations. + * + * \retval SHR_E_NONE No errors. + * \retval SHR_E_PARAM Invalid parameters. + */ +extern int +bcmcnet_vnet_ops_register(int unit, bcmcnet_vnet_ops_t *vnet_ops); + +#endif /* BCMCNET_INTERNAL_H */ + diff --git a/platform/broadcom/saibcm-modules/sdklt/bcmcnet/include/bcmcnet/bcmcnet_rxtx.h b/platform/broadcom/saibcm-modules/sdklt/bcmcnet/include/bcmcnet/bcmcnet_rxtx.h new file mode 100644 index 00000000000..eb5834d895b --- /dev/null +++ b/platform/broadcom/saibcm-modules/sdklt/bcmcnet/include/bcmcnet/bcmcnet_rxtx.h @@ -0,0 +1,512 @@ +/*! \file bcmcnet_rxtx.h + * + * Generic data structure and macro definitions for BCMCNET Rx/Tx. + * + */ +/* + * $Copyright: Copyright 2018-2020 Broadcom. All rights reserved. + * The term 'Broadcom' refers to Broadcom Inc. and/or its subsidiaries. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * version 2 as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * A copy of the GNU General Public License version 2 (GPLv2) can + * be found in the LICENSES folder.$ + */ + +#ifndef BCMCNET_RXTX_H +#define BCMCNET_RXTX_H + +/*! Default descriptor number in each ring */ +#define NUM_RING_DESC 64 + +/*! Maximum number of packets to be handled in one poll call */ +#define NUM_RXTX_BUDGET 64 + +/*! + * \brief Rx buffer mode definitions. + */ +enum buf_mode { + /*! Private DMA buffer in user space */ + PDMA_BUF_MODE_PRIV, + + /*! SKB in kernel */ + PDMA_BUF_MODE_SKB, + + /*! Paged buffer in kernel */ + PDMA_BUF_MODE_PAGE, + + /*! Kernel buffer mapped to user space */ + PDMA_BUF_MODE_MAPPED, + + /*! MAX mode */ + PDMA_BUF_MODE_MAX +}; + +/*! + * \brief Rx queue statistics. + */ +struct rx_stats { + /*! Number of received packets */ + uint64_t packets; + + /*! Number of received bytes */ + uint64_t bytes; + + /*! Number of dropped packets */ + uint64_t dropped; + + /*! Number of errors */ + uint64_t errors; + + /*! Number of head errors */ + uint64_t head_errors; + + /*! Number of data errors */ + uint64_t data_errors; + + /*! Number of cell errors */ + uint64_t cell_errors; + + /*! Number of failed allocation */ + uint64_t nomems; +}; + +/*! + * Rx queue structure + */ +struct pdma_rx_queue { + /*! Group index to which this queue belongs */ + uint32_t group_id; + + /*! Global channel index */ + uint32_t chan_id; + + /*! Queue index */ + uint32_t queue_id; + + /*! Pointer to the device control structure */ + struct dev_ctrl *ctrl; + + /*! Rx packet buffer pointers */ + struct pdma_rx_buf *pbuf; + + /*! Rx ring address */ + void *ring; + + /*! Rx ring DMA address */ + dma_addr_t ring_addr; + + /*! Rx ring DMA halt address */ + dma_addr_t halt_addr; + + /*! Rx buffer size */ + uint32_t buf_size; + + /*! Total number of descriptors */ + uint32_t nb_desc; + + /*! Next free ring entry */ + uint32_t curr; + + /*! Halt ring entry */ + uint32_t halt; + + /*! Max free descriptors to hold */ + uint32_t free_thresh; + + /*! Rx interrupt coalesce value */ + uint32_t ic_val; + + /*! Rx interrupt coalescing */ + int intr_coalescing; + + /*! Queue statistics */ + struct rx_stats stats; + + /*! Rx queue spin lock */ + sal_spinlock_t lock; + + /*! Queue state */ + int state; + /*! Queue is used */ +#define PDMA_RX_QUEUE_USED (1 << 0) + /*! Queue is setup */ +#define PDMA_RX_QUEUE_SETUP (1 << 1) + /*! Queue is active */ +#define PDMA_RX_QUEUE_ACTIVE (1 << 2) + /*! Queue is busy */ +#define PDMA_RX_QUEUE_BUSY (1 << 3) + /*! Queue is suspended */ +#define PDMA_RX_QUEUE_XOFF (1 << 4) + /*! Queue is batch refilled */ +#define PDMA_RX_BATCH_REFILL (1 << 5) + + /*! DMA buffer mode */ + enum buf_mode mode; +}; + +/*! + * \brief Tx queue statistics. + */ +struct tx_stats { + /*! Number of sent packets */ + uint64_t packets; + + /*! Number of sent bytes */ + uint64_t bytes; + + /*! Number of dropped packets */ + uint64_t dropped; + + /*! Number of errors */ + uint64_t errors; + + /*! Number of suspends */ + uint64_t xoffs; +}; + +/*! + * \brief Tx queue structure. + */ +struct pdma_tx_queue { + /*! Group index to which this queue belongs */ + uint32_t group_id; + + /*! Global channel index */ + uint32_t chan_id; + + /*! Queue index */ + uint32_t queue_id; + + /*! pointer to the device control structure */ + struct dev_ctrl *ctrl; + + /*! Tx packet buffer pointers */ + struct pdma_tx_buf *pbuf; + + /*! Tx ring address */ + void *ring; + + /*! Tx ring DMA address */ + dma_addr_t ring_addr; + + /*! Tx ring DMA halt address */ + dma_addr_t halt_addr; + + /*! Total number of descriptors */ + uint32_t nb_desc; + + /*! Next free ring entry */ + uint32_t curr; + + /*! First entry to be transmitted */ + uint32_t dirt; + + /*! Halt ring entry */ + uint32_t halt; + + /*! Max free descriptors to hold in non-intr mode */ + uint32_t free_thresh; + + /*! Tx interrupt coalesce value */ + uint32_t ic_val; + + /*! Tx interrupt coalescing */ + int intr_coalescing; + + /*! Queue statistics */ + struct tx_stats stats; + + /*! Tx queue spin lock */ + sal_spinlock_t lock; + + /*! Tx mutex spin lock */ + sal_spinlock_t mutex; + + /*! Tx mutex and flow control semaphore */ + sal_sem_t sem; + + /*! Queue state */ + int state; + /*! Queue is used */ +#define PDMA_TX_QUEUE_USED (1 << 0) + /*! Queue is setup */ +#define PDMA_TX_QUEUE_SETUP (1 << 1) + /*! Queue is active */ +#define PDMA_TX_QUEUE_ACTIVE (1 << 2) + /*! Queue is setup */ +#define PDMA_TX_QUEUE_BUSY (1 << 3) + /*! Queue is suspended */ +#define PDMA_TX_QUEUE_XOFF (1 << 4) + /*! Queue is poll mode */ +#define PDMA_TX_QUEUE_POLL (1 << 5) + + /*! DMA buffer mode */ + enum buf_mode mode; +}; + +/*! + * \brief Setup Rx queue. + * + * \param [in] dev Device structure point. + * \param [in] queue Rx queue number. + * + * \retval SHR_E_NONE No errors. + * \retval SHR_E_XXXX Operation failed. + */ +extern int +bcmcnet_pdma_rx_queue_setup(struct pdma_dev *dev, int queue); + +/*! + * \brief Release Rx queue. + * + * \param [in] dev Device structure point. + * \param [in] queue Rx queue number. + * + * \retval SHR_E_NONE No errors. + * \retval SHR_E_XXXX Operation failed. + */ +extern int +bcmcnet_pdma_rx_queue_release(struct pdma_dev *dev, int queue); + +/*! + * \brief Restore Rx queue. + * + * \param [in] dev Device structure point. + * \param [in] queue Rx queue number. + * + * \retval SHR_E_NONE No errors. + * \retval SHR_E_XXXX Operation failed. + */ +extern int +bcmcnet_pdma_rx_queue_restore(struct pdma_dev *dev, int queue); + +/*! + * \brief Setup virtual Rx queue. + * + * \param [in] dev Device structure point. + * \param [in] queue Rx queue number. + * + * \retval SHR_E_NONE No errors. + * \retval SHR_E_XXXX Operation failed. + */ +extern int +bcmcnet_pdma_rx_vqueue_setup(struct pdma_dev *dev, int queue); + +/*! + * \brief Release virtual Rx queue. + * + * \param [in] dev Device structure point. + * \param [in] queue Rx queue number. + * + * \retval SHR_E_NONE No errors. + * \retval SHR_E_XXXX Operation failed. + */ +extern int +bcmcnet_pdma_rx_vqueue_release(struct pdma_dev *dev, int queue); + +/*! + * \brief Setup Tx queue. + * + * \param [in] dev Device structure point. + * \param [in] queue Tx queue number. + * + * \retval SHR_E_NONE No errors. + * \retval SHR_E_XXXX Operation failed. + */ +extern int +bcmcnet_pdma_tx_queue_setup(struct pdma_dev *dev, int queue); + +/*! + * \brief Release Tx queue. + * + * \param [in] dev Device structure point. + * \param [in] queue Tx queue number. + * + * \retval SHR_E_NONE No errors. + * \retval SHR_E_XXXX Operation failed. + */ +extern int +bcmcnet_pdma_tx_queue_release(struct pdma_dev *dev, int queue); + +/*! + * \brief Restore Tx queue. + * + * \param [in] dev Device structure point. + * \param [in] queue Tx queue number. + * + * \retval SHR_E_NONE No errors. + * \retval SHR_E_XXXX Operation failed. + */ +extern int +bcmcnet_pdma_tx_queue_restore(struct pdma_dev *dev, int queue); + +/*! + * \brief Setup virtual Tx queue. + * + * \param [in] dev Device structure point. + * \param [in] queue Rx queue number. + * + * \retval SHR_E_NONE No errors. + * \retval SHR_E_XXXX Operation failed. + */ +extern int +bcmcnet_pdma_tx_vqueue_setup(struct pdma_dev *dev, int queue); + +/*! + * \brief Release virtual Tx queue. + * + * \param [in] dev Device structure point. + * \param [in] queue Rx queue number. + * + * \retval SHR_E_NONE No errors. + * \retval SHR_E_XXXX Operation failed. + */ +extern int +bcmcnet_pdma_tx_vqueue_release(struct pdma_dev *dev, int queue); + +/*! + * \brief Suspend Rx queue. + * + * \param [in] dev Device structure point. + * \param [in] queue Rx queue number. + * + * \retval SHR_E_NONE No errors. + * \retval SHR_E_XXXX Operation failed. + */ +extern int +bcmcnet_pdma_rx_queue_suspend(struct pdma_dev *dev, int queue); + +/*! + * \brief Resume Rx queue. + * + * \param [in] dev Device structure point. + * \param [in] queue Rx queue number. + * + * \retval SHR_E_NONE No errors. + * \retval SHR_E_XXXX Operation failed. + */ +extern int +bcmcnet_pdma_rx_queue_resume(struct pdma_dev *dev, int queue); + +/*! + * \brief Suspend Tx queue. + * + * \param [in] dev Device structure point. + * \param [in] queue Tx queue number. + * + * \retval SHR_E_NONE No errors. + * \retval SHR_E_XXXX Operation failed. + */ +extern int +bcmcnet_pdma_tx_queue_suspend(struct pdma_dev *dev, int queue); + +/*! + * \brief Resume Tx queue. + * + * \param [in] dev Device structure point. + * \param [in] queue Tx queue number. + * + * \retval SHR_E_NONE No errors. + * \retval SHR_E_XXXX Operation failed. + */ +extern int +bcmcnet_pdma_tx_queue_resume(struct pdma_dev *dev, int queue); + +/*! + * \brief Wakeup Tx queue. + * + * \param [in] dev Device structure point. + * \param [in] queue Tx queue number. + * + * \retval SHR_E_NONE No errors. + * \retval SHR_E_XXXX Operation failed. + */ +extern int +bcmcnet_pdma_tx_queue_wakeup(struct pdma_dev *dev, int queue); + +/*! + * \brief Start Tx queue transmission. + * + * \param [in] dev Device structure point. + * \param [in] queue Tx queue number. + * \param [in] buf Tx packet buffer. + * + * \retval SHR_E_NONE No errors. + * \retval SHR_E_XXXX Operation failed. + */ +extern int +bcmcnet_pdma_tx_queue_xmit(struct pdma_dev *dev, int queue, void *buf); + +/*! + * \brief Poll Rx queue. + * + * \param [in] dev Device structure point. + * \param [in] queue Rx queue number. + * \param [in] budget Poll budget. + * + * \retval SHR_E_NONE No errors. + * \retval SHR_E_XXXX Operation failed. + */ +extern int +bcmcnet_pdma_rx_queue_poll(struct pdma_dev *dev, int queue, int budget); + +/*! + * \brief Poll Tx queue. + * + * \param [in] dev Device structure point. + * \param [in] queue Tx queue number. + * \param [in] budget Poll budget. + * + * \retval SHR_E_NONE No errors. + * \retval SHR_E_XXXX Operation failed. + */ +extern int +bcmcnet_pdma_tx_queue_poll(struct pdma_dev *dev, int queue, int budget); + +/*! + * \brief Poll queue group. + * + * \param [in] dev Device structure point. + * \param [in] group Group number. + * \param [in] budget Poll budget. + * + * \retval SHR_E_NONE No errors. + * \retval SHR_E_XXXX Operation failed. + */ +extern int +bcmcnet_pdma_group_poll(struct pdma_dev *dev, int group, int budget); + +/*! + * \brief Dump Rx ring. + * + * \param [in] dev Device structure point. + * \param [in] queue Rx queue number. + * + * \retval SHR_E_NONE No errors. + * \retval SHR_E_XXXX Operation failed. + */ +extern int +bcmcnet_pdma_rx_ring_dump(struct pdma_dev *dev, int queue); + +/*! + * \brief Dump Tx ring. + * + * \param [in] dev Device structure point. + * \param [in] queue Tx queue number. + * + * \retval SHR_E_NONE No errors. + * \retval SHR_E_XXXX Operation failed. + */ +extern int +bcmcnet_pdma_tx_ring_dump(struct pdma_dev *dev, int queue); + +#endif /* BCMCNET_RXTX_H */ + diff --git a/platform/broadcom/saibcm-modules/sdklt/bcmcnet/include/bcmcnet/bcmcnet_types.h b/platform/broadcom/saibcm-modules/sdklt/bcmcnet/include/bcmcnet/bcmcnet_types.h new file mode 100644 index 00000000000..42bd9240828 --- /dev/null +++ b/platform/broadcom/saibcm-modules/sdklt/bcmcnet/include/bcmcnet/bcmcnet_types.h @@ -0,0 +1,263 @@ +/*! \file bcmcnet_types.h + * + * BCMCNET public data structure and macro definitions. + * + */ +/* + * $Copyright: Copyright 2018-2020 Broadcom. All rights reserved. + * The term 'Broadcom' refers to Broadcom Inc. and/or its subsidiaries. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * version 2 as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * A copy of the GNU General Public License version 2 (GPLv2) can + * be found in the LICENSES folder.$ + */ + +#ifndef BCMCNET_TYPES_H +#define BCMCNET_TYPES_H + +#include + +/*! Maximum length of device name */ +#define DEV_NAME_LEN_MAX 16 + +/*! Maximum number of groups supported each device */ +#define NUM_GRP_MAX 4 + +/*! Maximum number of queues supported each group */ +#define NUM_Q_PER_GRP 8 + +/*! Maximum number of queues supported each device */ +#define NUM_QUE_MAX (NUM_GRP_MAX * NUM_Q_PER_GRP) + +/*! Maximum length of jumbo frame */ +#define JUMBO_FRAME_LEN_MAX 0xffff + +/*! Maximum Rx buffer size */ +#define RX_BUF_SIZE_MAX JUMBO_FRAME_LEN_MAX + +/*! Minimum Rx buffer size */ +#define RX_BUF_SIZE_MIN 68 + +/*! Default Rx buffer size */ +#define RX_BUF_SIZE_DFLT 9216 + +/*! + * \brief Transmission direction. + */ +enum pdma_dir { + PDMA_Q_RX = 0, + PDMA_Q_TX +}; + +/*! + * \brief Device information. + */ +typedef struct bcmcnet_dev_info { + /*! Device name */ + char dev_name[DEV_NAME_LEN_MAX]; + + /*! Device ID */ + uint32_t dev_id; + + /*! Device type */ + uint32_t dev_type; + + /*! Maximum number of groups */ + uint32_t max_groups; + + /*! Maximum number of queues */ + uint32_t max_queues; + + /*! Bitmap of groups at work */ + uint32_t bm_groups; + + /*! Bitmap of Rx queues at work */ + uint32_t bm_rx_queues; + + /*! Bitmap of Tx queues at work */ + uint32_t bm_tx_queues; + + /*! Number of groups at work */ + uint32_t nb_groups; + + /*! Number of Rx queues at work */ + uint32_t nb_rx_queues; + + /*! Number of Tx queues at work */ + uint32_t nb_tx_queues; + + /*! Rx descriptor size */ + uint32_t rx_desc_size; + + /*! Tx descriptor size */ + uint32_t tx_desc_size; + + /*! Rx packet header size */ + uint32_t rx_ph_size; + + /*! Tx packet header size */ + uint32_t tx_ph_size; + + /*! Rx buffer size */ + uint32_t rx_buf_dflt; + + /*! Number of descriptors for a queue */ + uint32_t nb_desc_dflt; + + /*! Rx buffer size per queue */ + uint32_t rx_buf_size[NUM_QUE_MAX]; + + /*! Number of Rx descriptors per queue */ + uint32_t nb_rx_desc[NUM_QUE_MAX]; + + /*! Number of Tx descriptors per queue */ + uint32_t nb_tx_desc[NUM_QUE_MAX]; +} bcmcnet_dev_info_t; + +/*! + * \brief Device statistics. + */ +typedef struct bcmcnet_dev_stats { + /*! Number of successfully received packets */ + uint64_t rx_packets; + + /*! Number of successfully received bytes */ + uint64_t rx_bytes; + + /*! Number of dropped packets */ + uint64_t rx_dropped; + + /*! Number of erroneous received packets */ + uint64_t rx_errors; + + /*! Number of error head packets */ + uint64_t rx_head_errors; + + /*! Number of error data packets */ + uint64_t rx_data_errors; + + /*! Number of error cell packets */ + uint64_t rx_cell_errors; + + /*! Number of RX pktbuf allocation failures */ + uint64_t rx_nomems; + + /*! Number of successfully transmitted packets */ + uint64_t tx_packets; + + /*! Number of successfully transmitted bytes */ + uint64_t tx_bytes; + + /*! Number of dropped packets */ + uint64_t tx_dropped; + + /*! Number of failed transmitted packets */ + uint64_t tx_errors; + + /*! Number of suspended transmission */ + uint64_t tx_xoffs; + + /*! Number of interrupts */ + uint64_t intrs; + + /*! Number of successfully received packets per queue */ + uint64_t rxq_packets[NUM_QUE_MAX]; + + /*! Number of successfully received bytes per queue */ + uint64_t rxq_bytes[NUM_QUE_MAX]; + + /*! Number of dropped packets per queue */ + uint64_t rxq_dropped[NUM_QUE_MAX]; + + /*! Number of erroneous received packets per queue */ + uint64_t rxq_errors[NUM_QUE_MAX]; + + /*! Number of error head packets per queue */ + uint64_t rxq_head_errors[NUM_QUE_MAX]; + + /*! Number of error data packets per queue */ + uint64_t rxq_data_errors[NUM_QUE_MAX]; + + /*! Number of error cell packets per queue */ + uint64_t rxq_cell_errors[NUM_QUE_MAX]; + + /*! Number of RX pktbuf allocation failures per queue */ + uint64_t rxq_nomems[NUM_QUE_MAX]; + + /*! Number of successfully transmitted bytes per queue */ + uint64_t txq_packets[NUM_QUE_MAX]; + + /*! Number of successfully transmitted bytes per queue */ + uint64_t txq_bytes[NUM_QUE_MAX]; + + /*! Number of dropped packets per queue */ + uint64_t txq_dropped[NUM_QUE_MAX]; + + /*! Number of failed transmitted packets per queue */ + uint64_t txq_errors[NUM_QUE_MAX]; + + /*! Number of suspended transmission per queue */ + uint64_t txq_xoffs[NUM_QUE_MAX]; +} bcmcnet_dev_stats_t; + +/*! + * \brief Device modes. + */ +typedef enum dev_mode_e { + /*! + * User network mode. + * The standalone CNET works in user space. + */ + DEV_MODE_UNET = 0, + + /*! + * Kernel network mode. + * Combined with KNET module, CNET works in kernel space. + */ + DEV_MODE_KNET, + + /*! + * Virtual network mode. + * CNET works in user space as a virtual network. + * The hypervisor must be deployed in KNET module. + */ + DEV_MODE_VNET, + + /*! + * Hyper network mode. + * Combined with KNET module, CNET works in kernel space as a hypervisor. + * The virtual network is not neccessary in this mode. + */ + DEV_MODE_HNET, + + /*! Maximum number of mode */ + DEV_MODE_MAX +} dev_mode_t; + +/*! + * \brief VNET sync data. + */ +typedef struct vnet_sync_s { + /*! Rx ring address */ + uint64_t rx_ring_addr[NUM_QUE_MAX]; + + /*! Rx ring size */ + uint32_t rx_ring_size[NUM_QUE_MAX]; + + /*! Tx ring address */ + uint64_t tx_ring_addr[NUM_QUE_MAX]; + + /*! Tx ring size */ + uint32_t tx_ring_size[NUM_QUE_MAX]; +} vnet_sync_t; + +#endif /* BCMCNET_TYPES_H */ + diff --git a/platform/broadcom/saibcm-modules/sdklt/bcmcnet/main/bcmcnet_core.c b/platform/broadcom/saibcm-modules/sdklt/bcmcnet/main/bcmcnet_core.c new file mode 100644 index 00000000000..ef4aca7da49 --- /dev/null +++ b/platform/broadcom/saibcm-modules/sdklt/bcmcnet/main/bcmcnet_core.c @@ -0,0 +1,701 @@ +/*! \file bcmcnet_core.c + * + * Utility routines for BCMCNET driver. + * + */ +/* + * $Copyright: Copyright 2018-2020 Broadcom. All rights reserved. + * The term 'Broadcom' refers to Broadcom Inc. and/or its subsidiaries. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * version 2 as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * A copy of the GNU General Public License version 2 (GPLv2) can + * be found in the LICENSES folder.$ + */ + +#include +#include + +/*! + * Initialize a device + */ +int +bcmcnet_pdma_dev_init(struct pdma_dev *dev) +{ + int rv; + + /* Open the device */ + rv = bcmcnet_pdma_open(dev); + if (SHR_FAILURE(rv)) { + return rv; + } + + dev->attached = 1; + + return SHR_E_NONE; +} + +/*! + * Clean up a device + */ +int +bcmcnet_pdma_dev_cleanup(struct pdma_dev *dev) +{ + if (!dev->attached) { + return SHR_E_NONE; + } + + dev->ops->dev_close(dev); + dev->ops = NULL; + + dev->attached = 0; + + return SHR_E_NONE; +} + +/*! + * Start a device + */ +int +bcmcnet_pdma_dev_start(struct pdma_dev *dev) +{ + struct dev_ctrl *ctrl = &dev->ctrl; + uint32_t qi; + int rv; + + if (!dev->attached) { + return SHR_E_UNAVAIL; + } + + if (dev->started) { + return SHR_E_NONE; + } + + rv = dev->ops->dev_config(dev, ctrl->bm_rxq, ctrl->bm_txq); + if (SHR_FAILURE(rv)) { + return rv; + } + + /* Start all the Rx queues */ + for (qi = 0; qi < ctrl->nb_rxq; qi++) { + rv = dev->ops->rx_queue_setup(dev, qi); + if (SHR_FAILURE(rv)) { + return rv; + } + dev->ops->rx_queue_intr_enable(dev, qi); + dev->ops->rx_queue_start(dev, qi); + } + + /* Start all the Tx queues */ + for (qi = 0; qi < ctrl->nb_txq; qi++) { + dev->ops->tx_queue_setup(dev, qi); + dev->ops->tx_queue_intr_enable(dev, qi); + dev->ops->tx_queue_start(dev, qi); + dev->ops->tx_queue_wakeup(dev, qi); + } + + bcmcnet_pdma_dev_info_get(dev); + + dev->started = 1; + + return SHR_E_NONE; +} + +/*! + * Stop a device + */ +int +bcmcnet_pdma_dev_stop(struct pdma_dev *dev) +{ + struct dev_ctrl *ctrl = &dev->ctrl; + uint32_t qi; + + if (!dev->attached) { + return SHR_E_UNAVAIL; + } + + if (!dev->started) { + return SHR_E_NONE; + } + + /* Stop all the Rx queues */ + for (qi = 0; qi < ctrl->nb_rxq; qi++) { + dev->ops->rx_queue_intr_disable(dev, qi); + dev->ops->rx_queue_stop(dev, qi); + dev->ops->rx_queue_release(dev, qi); + } + + /* Stop all the Tx queues */ + for (qi = 0; qi < ctrl->nb_txq; qi++) { + dev->ops->tx_queue_intr_disable(dev, qi); + dev->ops->tx_queue_stop(dev, qi); + dev->ops->tx_queue_wakeup(dev, qi); + dev->ops->tx_queue_release(dev, qi); + } + + dev->started = 0; + + return SHR_E_NONE; +} + +/*! + * Suspend a device + */ +int +bcmcnet_pdma_dev_suspend(struct pdma_dev *dev) +{ + if (!dev->attached) { + return SHR_E_UNAVAIL; + } + + return dev->ops->dev_suspend(dev); +} + +/*! + * Resume a device + */ +int +bcmcnet_pdma_dev_resume(struct pdma_dev *dev) +{ + if (!dev->attached) { + return SHR_E_UNAVAIL; + } + + return dev->ops->dev_resume(dev); +} + +/*! + * Suspend Rx + */ +int +bcmcnet_pdma_dev_rx_suspend(struct pdma_dev *dev) +{ + struct dev_ctrl *ctrl = &dev->ctrl; + uint32_t qi; + + if (!dev->attached) { + return SHR_E_UNAVAIL; + } + + /* Suspend all the Rx queues */ + for (qi = 0; qi < ctrl->nb_rxq; qi++) { + dev->ops->rx_queue_suspend(dev, qi); + } + + return SHR_E_NONE; +} + +/*! + * Resume Rx + */ +int +bcmcnet_pdma_dev_rx_resume(struct pdma_dev *dev) +{ + struct dev_ctrl *ctrl = &dev->ctrl; + uint32_t qi; + + if (!dev->attached) { + return SHR_E_UNAVAIL; + } + + /* Resume all the Rx queues */ + for (qi = 0; qi < ctrl->nb_rxq; qi++) { + dev->ops->rx_queue_resume(dev, qi); + } + + return SHR_E_NONE; +} + +/*! + * Dock to HNET + */ +int +bcmcnet_pdma_dev_dock(struct pdma_dev *dev) +{ + struct dev_ctrl *ctrl = &dev->ctrl; + uint32_t qi; + int rv; + + if (!dev->attached) { + return SHR_E_UNAVAIL; + } + + /* Set up all the virtual Rx queues */ + for (qi = 0; qi < ctrl->nb_rxq; qi++) { + rv = dev->ops->rx_vqueue_setup(dev, qi); + if (SHR_FAILURE(rv)) { + return rv; + } + } + + /* Set up all the virtual Tx queues */ + for (qi = 0; qi < ctrl->nb_txq; qi++) { + rv = dev->ops->tx_vqueue_setup(dev, qi); + if (SHR_FAILURE(rv)) { + return rv; + } + } + + return SHR_E_NONE; +} + +/*! + * Undock from HNET + */ +int +bcmcnet_pdma_dev_undock(struct pdma_dev *dev) +{ + struct dev_ctrl *ctrl = &dev->ctrl; + uint32_t qi; + + if (!dev->attached) { + return SHR_E_UNAVAIL; + } + + /* Release all the virtual Rx queues */ + for (qi = 0; qi < ctrl->nb_rxq; qi++) { + dev->ops->rx_vqueue_release(dev, qi); + } + + /* Release all the virtual Tx queues */ + for (qi = 0; qi < ctrl->nb_txq; qi++) { + dev->ops->tx_vqueue_release(dev, qi); + } + + return SHR_E_NONE; +} + +/*! + * Get device information + */ +int +bcmcnet_pdma_dev_info_get(struct pdma_dev *dev) +{ + if (!dev->ops || !dev->ops->dev_info_get) { + return SHR_E_INTERNAL; + } + + dev->ops->dev_info_get(dev); + + return SHR_E_NONE; +} + +/*! + * Get device statistics + */ +int +bcmcnet_pdma_dev_stats_get(struct pdma_dev *dev) +{ + if (!dev->ops || !dev->ops->dev_stats_get) { + return SHR_E_INTERNAL; + } + + dev->ops->dev_stats_get(dev); + + return SHR_E_NONE; +} + +/*! + * Reset device statistics + */ +int +bcmcnet_pdma_dev_stats_reset(struct pdma_dev *dev) +{ + if (!dev->ops || !dev->ops->dev_stats_reset) { + return SHR_E_INTERNAL; + } + + dev->ops->dev_stats_reset(dev); + + return SHR_E_NONE; +} + +/*! + * Convert a queue index to channel index + */ +int +bcmcnet_pdma_dev_queue_to_chan(struct pdma_dev *dev, int queue, int dir, int *chan) +{ + struct dev_ctrl *ctrl = &dev->ctrl; + + if (dir == PDMA_Q_RX) { + if ((uint32_t)queue >= ctrl->nb_rxq || chan == NULL) { + return SHR_E_PARAM; + } + } else { + if ((uint32_t)queue >= ctrl->nb_txq || chan == NULL) { + return SHR_E_PARAM; + } + } + + if (!dev->ops || !dev->ops->dev_lq_to_pq) { + return SHR_E_INTERNAL; + } + + return dev->ops->dev_lq_to_pq(dev, queue, dir, chan); +} + +/*! + * Convert a channel index to queue index + */ +int +bcmcnet_pdma_dev_chan_to_queue(struct pdma_dev *dev, int chan, int *queue, int *dir) +{ + if (chan < 0 || chan >= dev->num_queues || queue == NULL || dir == NULL) { + return SHR_E_PARAM; + } + + if (!dev->ops || !dev->ops->dev_pq_to_lq) { + return SHR_E_INTERNAL; + } + + return dev->ops->dev_pq_to_lq(dev, chan, queue, dir); +} + +/*! + * Enable interrupt for a Rx queue + */ +int +bcmcnet_rx_queue_intr_enable(struct pdma_dev *dev, int queue) +{ + if (!dev->ops || !dev->ops->rx_queue_intr_enable) { + return SHR_E_INTERNAL; + } + + return dev->ops->rx_queue_intr_enable(dev, queue); +} + +/*! + * Disable interrupt for a Rx queue + */ +int +bcmcnet_rx_queue_intr_disable(struct pdma_dev *dev, int queue) +{ + if (!dev->ops || !dev->ops->rx_queue_intr_disable) { + return SHR_E_INTERNAL; + } + + return dev->ops->rx_queue_intr_disable(dev, queue); +} + +/*! + * Acknowledge interrupt for a Rx queue + */ +int +bcmcnet_rx_queue_intr_ack(struct pdma_dev *dev, int queue) +{ + if (!dev->ops || !dev->ops->rx_queue_intr_ack) { + return SHR_E_INTERNAL; + } + + return dev->ops->rx_queue_intr_ack(dev, queue); +} + +/*! + * Check interrupt for a Rx queue + */ +int +bcmcnet_rx_queue_intr_check(struct pdma_dev *dev, int queue) +{ + if (!dev->ops || !dev->ops->rx_queue_intr_check) { + return SHR_E_INTERNAL; + } + + return dev->ops->rx_queue_intr_check(dev, queue); +} + +/*! + * Enable interrupt for a Tx queue + */ +int +bcmcnet_tx_queue_intr_enable(struct pdma_dev *dev, int queue) +{ + if (!dev->ops || !dev->ops->tx_queue_intr_enable) { + return SHR_E_INTERNAL; + } + + return dev->ops->tx_queue_intr_enable(dev, queue); +} + +/*! + * Disable interrupt for a Tx queue + */ +int +bcmcnet_tx_queue_intr_disable(struct pdma_dev *dev, int queue) +{ + if (!dev->ops || !dev->ops->tx_queue_intr_disable) { + return SHR_E_INTERNAL; + } + + return dev->ops->tx_queue_intr_disable(dev, queue); +} + +/*! + * Acknowledge interrupt for a Tx queue + */ +int +bcmcnet_tx_queue_intr_ack(struct pdma_dev *dev, int queue) +{ + if (!dev->ops || !dev->ops->tx_queue_intr_ack) { + return SHR_E_INTERNAL; + } + + return dev->ops->tx_queue_intr_ack(dev, queue); +} + +/*! + * Check interrupt for a Tx queue + */ +int +bcmcnet_tx_queue_intr_check(struct pdma_dev *dev, int queue) +{ + if (!dev->ops || !dev->ops->tx_queue_intr_check) { + return SHR_E_INTERNAL; + } + + return dev->ops->tx_queue_intr_check(dev, queue); +} + +/*! + * Enable interrupt for a queue + */ +int +bcmcnet_queue_intr_enable(struct pdma_dev *dev, struct intr_handle *hdl) +{ + if (hdl->dir == PDMA_Q_RX) { + return bcmcnet_rx_queue_intr_enable(dev, hdl->queue); + } else { + return bcmcnet_tx_queue_intr_enable(dev, hdl->queue); + } +} + +/*! + * Disable interrupt for a queue + */ +int +bcmcnet_queue_intr_disable(struct pdma_dev *dev, struct intr_handle *hdl) +{ + if (hdl->dir == PDMA_Q_RX) { + return bcmcnet_rx_queue_intr_disable(dev, hdl->queue); + } else { + return bcmcnet_tx_queue_intr_disable(dev, hdl->queue); + } +} + +/*! + * Acknowledge interrupt for a queue + */ +int +bcmcnet_queue_intr_ack(struct pdma_dev *dev, struct intr_handle *hdl) +{ + if (hdl->dir == PDMA_Q_RX) { + return bcmcnet_rx_queue_intr_ack(dev, hdl->queue); + } else { + return bcmcnet_tx_queue_intr_ack(dev, hdl->queue); + } +} + +/*! + * Check interrupt for a queue + */ +int +bcmcnet_queue_intr_check(struct pdma_dev *dev, struct intr_handle *hdl) +{ + if (hdl->dir == PDMA_Q_RX) { + return bcmcnet_rx_queue_intr_check(dev, hdl->queue); + } else { + return bcmcnet_tx_queue_intr_check(dev, hdl->queue); + } +} + +/*! + * Enable interrupt for a queue group + */ +int +bcmcnet_group_intr_enable(struct pdma_dev *dev, int group) +{ + struct dev_ctrl *ctrl = &dev->ctrl; + struct queue_group *grp = &ctrl->grp[group]; + int queue, dir; + int i; + + if (!dev->ops) { + return SHR_E_INTERNAL; + } + + for (i = 0; i < dev->grp_queues; i++) { + if (1 << i & grp->bm_rxq) { + dev->ops->dev_pq_to_lq(dev, i + group * dev->grp_queues, &queue, &dir); + dev->ops->rx_queue_intr_enable(dev, queue); + } + } + + for (i = 0; i < dev->grp_queues; i++) { + if (1 << i & grp->bm_txq) { + dev->ops->dev_pq_to_lq(dev, i + group * dev->grp_queues, &queue, &dir); + dev->ops->tx_queue_intr_enable(dev, queue); + } + } + + return SHR_E_NONE; +} + +/*! + * Disable interrupt for a queue group + */ +int +bcmcnet_group_intr_disable(struct pdma_dev *dev, int group) +{ + struct dev_ctrl *ctrl = &dev->ctrl; + struct queue_group *grp = &ctrl->grp[group]; + int queue, dir; + int i; + + if (!dev->ops) { + return SHR_E_INTERNAL; + } + + for (i = 0; i < dev->grp_queues; i++) { + if (1 << i & grp->bm_rxq) { + dev->ops->dev_pq_to_lq(dev, i + group * dev->grp_queues, &queue, &dir); + dev->ops->rx_queue_intr_disable(dev, queue); + } + } + + for (i = 0; i < dev->grp_queues; i++) { + if (1 << i & grp->bm_txq) { + dev->ops->dev_pq_to_lq(dev, i + group * dev->grp_queues, &queue, &dir); + dev->ops->tx_queue_intr_disable(dev, queue); + } + } + + return SHR_E_NONE; +} + +/*! + * Acknowledge interrupt for a queue group + */ +int +bcmcnet_group_intr_ack(struct pdma_dev *dev, int group) +{ + struct dev_ctrl *ctrl = &dev->ctrl; + struct queue_group *grp = &ctrl->grp[group]; + int queue, dir; + int i; + + if (!dev->ops) { + return SHR_E_INTERNAL; + } + + for (i = 0; i < dev->grp_queues; i++) { + if (1 << i & grp->bm_rxq) { + dev->ops->dev_pq_to_lq(dev, i + group * dev->grp_queues, &queue, &dir); + dev->ops->rx_queue_intr_ack(dev, queue); + } + } + + for (i = 0; i < dev->grp_queues; i++) { + if (1 << i & grp->bm_txq) { + dev->ops->dev_pq_to_lq(dev, i + group * dev->grp_queues, &queue, &dir); + dev->ops->tx_queue_intr_ack(dev, queue); + } + } + + return SHR_E_NONE; +} + +/*! + * Check interrupt for a queue group + */ +int +bcmcnet_group_intr_check(struct pdma_dev *dev, int group) +{ + struct dev_ctrl *ctrl = &dev->ctrl; + struct queue_group *grp = &ctrl->grp[group]; + int queue, dir; + int i; + + if (!dev->ops) { + return SHR_E_INTERNAL; + } + + for (i = 0; i < dev->grp_queues; i++) { + if (1 << i & grp->bm_rxq) { + dev->ops->dev_pq_to_lq(dev, i + group * dev->grp_queues, &queue, &dir); + if (dev->ops->rx_queue_intr_check(dev, queue)) { + return TRUE; + } + } + } + + for (i = 0; i < dev->grp_queues; i++) { + if (1 << i & grp->bm_txq) { + dev->ops->dev_pq_to_lq(dev, i + group * dev->grp_queues, &queue, &dir); + if (dev->ops->tx_queue_intr_check(dev, queue)) { + return TRUE; + } + } + } + + return FALSE; +} + +/*! + * Poll a Rx queue + */ +int +bcmcnet_rx_queue_poll(struct pdma_dev *dev, int queue, int budget) +{ + if (!dev->ops || !dev->ops->rx_queue_poll) { + return SHR_E_INTERNAL; + } + + return dev->ops->rx_queue_poll(dev, queue, budget); +} + +/*! + * Poll a Tx queue + */ +int +bcmcnet_tx_queue_poll(struct pdma_dev *dev, int queue, int budget) +{ + if (!dev->ops || !dev->ops->tx_queue_poll) { + return SHR_E_INTERNAL; + } + + return dev->ops->tx_queue_poll(dev, queue, budget); +} + +/*! + * Poll a queue + */ +int +bcmcnet_queue_poll(struct pdma_dev *dev, struct intr_handle *hdl, int budget) +{ + if (hdl->dir == PDMA_Q_RX) { + return bcmcnet_rx_queue_poll(dev, hdl->queue, budget); + } else { + return bcmcnet_tx_queue_poll(dev, hdl->queue, budget); + } +} + +/*! + * Poll a queue group + */ +int +bcmcnet_group_poll(struct pdma_dev *dev, int group, int budget) +{ + if (!dev->ops || !dev->ops->group_poll) { + return SHR_E_INTERNAL; + } + + return dev->ops->group_poll(dev, group, budget); +} + diff --git a/platform/broadcom/saibcm-modules/sdklt/bcmcnet/main/bcmcnet_dev.c b/platform/broadcom/saibcm-modules/sdklt/bcmcnet/main/bcmcnet_dev.c new file mode 100644 index 00000000000..1f39515a7a6 --- /dev/null +++ b/platform/broadcom/saibcm-modules/sdklt/bcmcnet/main/bcmcnet_dev.c @@ -0,0 +1,1059 @@ +/*! \file bcmcnet_dev.c + * + * Utility routines for BCMCNET device. + * + */ +/* + * $Copyright: Copyright 2018-2020 Broadcom. All rights reserved. + * The term 'Broadcom' refers to Broadcom Inc. and/or its subsidiaries. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * version 2 as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * A copy of the GNU General Public License version 2 (GPLv2) can + * be found in the LICENSES folder.$ + */ + +#include +#include +#include +#include + +/*! + * Free resource for a Rx queue + */ +static void +bcn_rx_queues_free(struct pdma_dev *dev) +{ + struct dev_ctrl *ctrl = &dev->ctrl; + struct pdma_rx_queue *rxq = NULL; + int gi, qi; + + for (gi = 0; gi < dev->num_groups; gi++) { + for (qi = 0; qi < dev->grp_queues; qi++) { + rxq = (struct pdma_rx_queue *)ctrl->grp[gi].rx_queue[qi]; + if (!rxq) { + continue; + } + sal_free(rxq); + ctrl->grp[gi].rx_queue[qi] = NULL; + if (dev->mode == DEV_MODE_HNET && ctrl->grp[gi].vnet_rxq[qi]) { + sal_free(ctrl->grp[gi].vnet_rxq[qi]); + ctrl->grp[gi].vnet_rxq[qi] = NULL; + } + } + } +} + +/*! + * Allocate resource for a Rx queue + */ +static int +bcn_rx_queues_alloc(struct pdma_dev *dev) +{ + struct dev_ctrl *ctrl = &dev->ctrl; + struct pdma_rx_queue *rxq = NULL, *vrxq = NULL; + int gi, qi; + + for (gi = 0; gi < dev->num_groups; gi++) { + for (qi = 0; qi < dev->grp_queues; qi++) { + rxq = sal_alloc(sizeof(*rxq), "bcmcnetRxQueue"); + if (!rxq) { + goto error; + } + sal_memset(rxq, 0, sizeof(*rxq)); + rxq->group_id = gi; + rxq->chan_id = qi + gi * dev->grp_queues; + rxq->ctrl = ctrl; + ctrl->grp[gi].rx_queue[qi] = rxq; + if (dev->mode == DEV_MODE_HNET) { + vrxq = sal_alloc(sizeof(*vrxq), "bcmcnetVnetRxQueue"); + if (!vrxq) { + goto error; + } + sal_memset(vrxq, 0, sizeof(*vrxq)); + vrxq->group_id = gi; + vrxq->chan_id = qi + gi * dev->grp_queues; + vrxq->ctrl = ctrl; + ctrl->grp[gi].vnet_rxq[qi] = vrxq; + } + } + } + + return SHR_E_NONE; + +error: + bcn_rx_queues_free(dev); + + return SHR_E_MEMORY; +} + +/*! + * Free resource for a Tx queue + */ +static void +bcn_tx_queues_free(struct pdma_dev *dev) +{ + struct dev_ctrl *ctrl = &dev->ctrl; + struct pdma_tx_queue *txq = NULL; + int gi, qi; + + for (gi = 0; gi < dev->num_groups; gi++) { + for (qi = 0; qi < dev->grp_queues; qi++) { + txq = (struct pdma_tx_queue *)ctrl->grp[gi].tx_queue[qi]; + if (!txq) { + continue; + } + sal_free(txq); + ctrl->grp[gi].tx_queue[qi] = NULL; + if (dev->mode == DEV_MODE_HNET && ctrl->grp[gi].vnet_txq[qi]) { + sal_free(ctrl->grp[gi].vnet_txq[qi]); + ctrl->grp[gi].vnet_txq[qi] = NULL; + } + } + } +} + +/*! + * Allocate resource for a Tx queue + */ +static int +bcn_tx_queues_alloc(struct pdma_dev *dev) +{ + struct dev_ctrl *ctrl = &dev->ctrl; + struct pdma_tx_queue *txq = NULL, *vtxq = NULL; + int gi, qi; + + for (gi = 0; gi < dev->num_groups; gi++) { + for (qi = 0; qi < dev->grp_queues; qi++) { + txq = sal_alloc(sizeof(*txq), "bcmcnetTxQueue"); + if (!txq) { + goto error; + } + sal_memset(txq, 0, sizeof(*txq)); + txq->group_id = gi; + txq->chan_id = qi + gi * dev->grp_queues; + txq->ctrl = ctrl; + ctrl->grp[gi].tx_queue[qi] = txq; + if (dev->mode == DEV_MODE_HNET) { + vtxq = sal_alloc(sizeof(*vtxq), "bcmcnetVnetTxQueue"); + if (!vtxq) { + goto error; + } + sal_memset(vtxq, 0, sizeof(*vtxq)); + vtxq->group_id = gi; + vtxq->chan_id = qi + gi * dev->grp_queues; + vtxq->ctrl = ctrl; + ctrl->grp[gi].vnet_txq[qi] = vtxq; + } + } + } + + return SHR_E_NONE; + +error: + bcn_tx_queues_free(dev); + + return SHR_E_MEMORY; +} + +/*! + * \brief Parse Rx groups + * + * \param [in] dev Device structure point. + * \param [in] qbm Rx queue bitmap. + * + * \retval SHR_E_NONE No errors. + * \retval SHR_E_XXXX Operation failed. + */ +static int +bcn_rx_queue_group_parse(struct pdma_dev *dev, uint32_t qbm) +{ + struct dev_ctrl *ctrl = &dev->ctrl; + struct pdma_buf_mngr *bm = (struct pdma_buf_mngr *)ctrl->buf_mngr; + struct pdma_rx_queue *rxq = NULL; + struct intr_handle *hdl = NULL; + uint32_t mask; + int gi, qi, qn; + + ctrl->nb_rxq = 0; + sal_memset(ctrl->rx_queue, 0, sizeof(ctrl->rx_queue)); + + /* Figure out available groups and Rx queues */ + for (gi = 0; gi < dev->num_groups; gi++) { + if (!ctrl->grp[gi].attached) { + continue; + } + qn = 0; + mask = 0; + for (qi = 0; qi < dev->grp_queues; qi++) { + rxq = (struct pdma_rx_queue *)ctrl->grp[gi].rx_queue[qi]; + hdl = &ctrl->grp[gi].intr_hdl[qi]; + if (1 << (qi + gi * dev->grp_queues) & qbm) { + /* Set the number of descriptors */ + rxq->nb_desc = ctrl->grp[gi].nb_desc[qi]; + if (!rxq->nb_desc) { + rxq->nb_desc = ctrl->nb_desc; + ctrl->grp[gi].nb_desc[qi] = rxq->nb_desc; + } + /* Set Rx buffer size */ + rxq->buf_size = ctrl->grp[gi].rx_size[qi]; + if (rxq->buf_size < RX_BUF_SIZE_MIN) { + rxq->buf_size = RX_BUF_SIZE_MIN; + ctrl->grp[gi].rx_size[qi] = rxq->buf_size; + } else if (rxq->buf_size > RX_BUF_SIZE_MAX) { + rxq->buf_size = ctrl->rx_buf_size; + ctrl->grp[gi].rx_size[qi] = rxq->buf_size; + } + rxq->buf_size += dev->rx_ph_size; + /* Set mode and state for the queue */ + rxq->mode = bm->rx_buf_mode(dev, rxq); + rxq->state = PDMA_RX_QUEUE_USED; + if (dev->flags & PDMA_RX_BATCHING) { + rxq->free_thresh = rxq->nb_desc / 4; + rxq->state |= PDMA_RX_BATCH_REFILL; + } + /* Update queue index */ + rxq->queue_id = ctrl->nb_rxq; + ctrl->rx_queue[rxq->queue_id] = rxq; + ctrl->nb_rxq++; + qn++; + mask |= 1 << qi; + /* Set up handler for the queue */ + hdl->queue = rxq->queue_id; + hdl->dir = PDMA_Q_RX; + hdl->budget = ctrl->budget < rxq->nb_desc ? + ctrl->budget : rxq->nb_desc; + if (dev->mode == DEV_MODE_HNET) { + ctrl->vnet_rxq[rxq->queue_id] = ctrl->grp[gi].vnet_rxq[qi]; + } + } else { + rxq->state = 0; + } + } + + /* Set group metadata */ + if (qn) { + ctrl->grp[gi].bm_rxq = mask; + ctrl->grp[gi].nb_rxq = qn; + } else { + ctrl->grp[gi].bm_rxq = 0; + ctrl->grp[gi].nb_rxq = 0; + } + } + + return SHR_E_NONE; +} + +/*! + * \brief Parse Tx groups + * + * \param [in] dev Device structure point. + * \param [in] qbm Tx queue bitmap. + * + * \retval SHR_E_NONE No errors. + * \retval SHR_E_XXXX Operation failed. + */ +static int +bcn_tx_queue_group_parse(struct pdma_dev *dev, uint32_t qbm) +{ + struct dev_ctrl *ctrl = &dev->ctrl; + struct pdma_tx_queue *txq = NULL; + struct intr_handle *hdl = NULL; + uint32_t mask; + int gi, qi, qn; + + ctrl->nb_txq = 0; + sal_memset(ctrl->tx_queue, 0, sizeof(ctrl->tx_queue)); + + /* Figure out available groups and Tx queues */ + for (gi = 0; gi < dev->num_groups; gi++) { + if (!ctrl->grp[gi].attached) { + continue; + } + qn = 0; + mask = 0; + for (qi = 0; qi < dev->grp_queues; qi++) { + txq = (struct pdma_tx_queue *)ctrl->grp[gi].tx_queue[qi]; + hdl = &ctrl->grp[gi].intr_hdl[qi]; + if (1 << (qi + gi * dev->grp_queues) & qbm) { + /* Set the number of descriptors */ + txq->nb_desc = ctrl->grp[gi].nb_desc[qi]; + if (!txq->nb_desc) { + txq->nb_desc = ctrl->nb_desc; + ctrl->grp[gi].nb_desc[qi] = txq->nb_desc; + } + /* Set mode and state for the queue */ + txq->state = PDMA_TX_QUEUE_USED; + if (dev->flags & PDMA_TX_POLLING) { + txq->free_thresh = txq->nb_desc / 4; + txq->state |= PDMA_TX_QUEUE_POLL; + } + /* Update queue index */ + txq->queue_id = ctrl->nb_txq; + ctrl->tx_queue[txq->queue_id] = txq; + ctrl->nb_txq++; + qn++; + mask |= 1 << qi; + /* Set up handler for the queue */ + hdl->queue = txq->queue_id; + hdl->dir = PDMA_Q_TX; + hdl->budget = ctrl->budget < txq->nb_desc ? + ctrl->budget : txq->nb_desc; + if (dev->mode == DEV_MODE_HNET) { + ctrl->vnet_txq[txq->queue_id] = ctrl->grp[gi].vnet_txq[qi]; + } + } else { + txq->state = 0; + } + } + + /* Set group metadata */ + if (qn) { + ctrl->grp[gi].bm_txq = mask; + ctrl->grp[gi].nb_txq = qn; + } else { + ctrl->grp[gi].bm_txq = 0; + ctrl->grp[gi].nb_txq = 0; + } + } + + return SHR_E_NONE; +} + +/*! + * \brief Configure device + * + * \param [in] dev Device structure point. + * \param [in] bm_rxq Rx queue bitmap. + * \param [in] bm_txq Tx queue bitmap. + * + * \retval SHR_E_NONE No errors. + * \retval SHR_E_XXXX Operation failed. + */ +static int +bcmcnet_pdma_config(struct pdma_dev *dev, uint32_t bm_rxq, uint32_t bm_txq) +{ + struct dev_ctrl *ctrl = &dev->ctrl; + struct pdma_hw *hw = (struct pdma_hw *)ctrl->hw; + int gi; + + if (!bm_rxq || !bm_txq || (bm_rxq & bm_txq)) { + return SHR_E_PARAM; + } + + bcn_rx_queue_group_parse(dev, bm_rxq); + bcn_tx_queue_group_parse(dev, bm_txq); + + for (gi = 0; gi < dev->num_groups; gi++) { + if (!ctrl->grp[gi].attached) { + continue; + } + /* Update group metadata */ + if (!ctrl->grp[gi].bm_rxq && !ctrl->grp[gi].bm_txq) { + ctrl->grp[gi].attached = 0; + ctrl->bm_grp &= ~(1 << gi); + ctrl->nb_grp--; + continue; + } + ctrl->grp[gi].ctrl = ctrl; + ctrl->grp[gi].id = gi; + ctrl->grp[gi].irq_mask = 0; + } + + return hw->hdls.hw_config(hw); +} + +/*! + * Close device + */ +static int +bcmcnet_pdma_close(struct pdma_dev *dev) +{ + struct dev_ctrl *ctrl = &dev->ctrl; + struct pdma_hw *hw = (struct pdma_hw *)dev->ctrl.hw; + int gi; + + hw->hdls.hw_reset(hw); + + for (gi = 0; gi < dev->num_groups; gi++) { + if (!ctrl->grp[gi].attached) { + continue; + } + /* Reset group metadata */ + ctrl->bm_grp &= ~(1 << gi); + ctrl->nb_grp--; + ctrl->grp[gi].irq_mask = 0; + ctrl->grp[gi].poll_queues = 0; + ctrl->grp[gi].attached = 0; + } + + bcn_rx_queues_free(dev); + bcn_tx_queues_free(dev); + + return SHR_E_NONE; +} + +/*! + * Suspend device + */ +static int +bcmcnet_pdma_suspend(struct pdma_dev *dev) +{ + struct dev_ctrl *ctrl = &dev->ctrl; + uint32_t qi; + + for (qi = 0; qi < ctrl->nb_rxq; qi++) { + bcmcnet_pdma_rx_queue_suspend(dev, qi); + } + + for (qi = 0; qi < ctrl->nb_txq; qi++) { + bcmcnet_pdma_tx_queue_suspend(dev, qi); + } + + return SHR_E_NONE; +} + +/*! + * Resume device + */ +static int +bcmcnet_pdma_resume(struct pdma_dev *dev) +{ + struct dev_ctrl *ctrl = &dev->ctrl; + uint32_t qi; + + for (qi = 0; qi < ctrl->nb_rxq; qi++) { + bcmcnet_pdma_rx_queue_resume(dev, qi); + } + + for (qi = 0; qi < ctrl->nb_txq; qi++) { + bcmcnet_pdma_tx_queue_resume(dev, qi); + } + + return SHR_E_NONE; +} + +/*! + * Get device information + */ +static void +bcmcnet_pdma_info_get(struct pdma_dev *dev) +{ + struct dev_ctrl *ctrl = &dev->ctrl; + struct pdma_hw *hw = (struct pdma_hw *)ctrl->hw; + struct pdma_rx_queue *rxq = NULL; + struct pdma_tx_queue *txq = NULL; + uint32_t qi; + + sal_strncpy(dev->info.dev_name, dev->name, sizeof(dev->info.dev_name) - 1); + dev->info.dev_name[sizeof(dev->info.dev_name) - 1] = 0; + dev->info.dev_id = dev->dev_id; + dev->info.dev_type = dev->dev_type; + dev->info.max_groups = hw->info.num_cmcs; + dev->info.max_queues = hw->info.num_chans; + dev->info.bm_groups = ctrl->bm_grp; + dev->info.bm_rx_queues = ctrl->bm_rxq; + dev->info.bm_tx_queues = ctrl->bm_txq; + dev->info.nb_groups = ctrl->nb_grp; + dev->info.nb_rx_queues = ctrl->nb_rxq; + dev->info.nb_tx_queues = ctrl->nb_txq; + dev->info.rx_desc_size = hw->info.rx_dcb_size; + dev->info.tx_desc_size = hw->info.tx_dcb_size; + dev->info.rx_ph_size = hw->info.rx_ph_size; + dev->info.tx_ph_size = hw->info.tx_ph_size; + dev->info.rx_buf_dflt = ctrl->rx_buf_size; + dev->info.nb_desc_dflt = ctrl->nb_desc; + + for (qi = 0; qi < ctrl->nb_rxq; qi++) { + rxq = (struct pdma_rx_queue *)ctrl->rx_queue[qi]; + if (!rxq) { + continue; + } + dev->info.rx_buf_size[qi] = rxq->buf_size; + dev->info.nb_rx_desc[qi] = rxq->nb_desc; + } + + for (qi = 0; qi < ctrl->nb_txq; qi++) { + txq = (struct pdma_tx_queue *)ctrl->tx_queue[qi]; + if (!txq) { + continue; + } + dev->info.nb_tx_desc[qi] = txq->nb_desc; + } +} + +/*! + * Get device statistics + */ +static void +bcmcnet_pdma_stats_get(struct pdma_dev *dev) +{ + struct dev_ctrl *ctrl = &dev->ctrl; + struct pdma_rx_queue *rxq = NULL; + struct pdma_tx_queue *txq = NULL; + uint32_t packets = 0, bytes = 0, dropped = 0, errors = 0, nomems = 0, xoffs = 0; + uint32_t head_errors = 0, data_errors = 0, cell_errors = 0; + uint32_t qi; + + for (qi = 0; qi < ctrl->nb_rxq; qi++) { + rxq = (struct pdma_rx_queue *)ctrl->rx_queue[qi]; + if (!rxq) { + continue; + } + packets += rxq->stats.packets; + bytes += rxq->stats.bytes; + dropped += rxq->stats.dropped; + errors += rxq->stats.errors; + head_errors += rxq->stats.head_errors; + data_errors += rxq->stats.data_errors; + cell_errors += rxq->stats.cell_errors; + nomems += rxq->stats.nomems; + dev->stats.rxq_packets[qi] = rxq->stats.packets; + dev->stats.rxq_bytes[qi] = rxq->stats.bytes; + dev->stats.rxq_dropped[qi] = rxq->stats.dropped; + dev->stats.rxq_errors[qi] = rxq->stats.errors; + dev->stats.rxq_head_errors[qi] = rxq->stats.head_errors; + dev->stats.rxq_data_errors[qi] = rxq->stats.data_errors; + dev->stats.rxq_cell_errors[qi] = rxq->stats.cell_errors; + dev->stats.rxq_nomems[qi] = rxq->stats.nomems; + } + + dev->stats.rx_packets = packets; + dev->stats.rx_bytes = bytes; + dev->stats.rx_dropped = dropped; + dev->stats.rx_errors = errors; + dev->stats.rx_head_errors = head_errors; + dev->stats.rx_data_errors = data_errors; + dev->stats.rx_cell_errors = cell_errors; + dev->stats.rx_nomems = nomems; + + packets = bytes = dropped = errors = 0; + for (qi = 0; qi < ctrl->nb_txq; qi++) { + txq = (struct pdma_tx_queue *)ctrl->tx_queue[qi]; + if (!txq) { + continue; + } + packets += txq->stats.packets; + bytes += txq->stats.bytes; + dropped += txq->stats.dropped; + errors += txq->stats.errors; + xoffs += txq->stats.xoffs; + dev->stats.txq_packets[qi] = txq->stats.packets; + dev->stats.txq_bytes[qi] = txq->stats.bytes; + dev->stats.txq_dropped[qi] = txq->stats.dropped; + dev->stats.txq_errors[qi] = txq->stats.errors; + dev->stats.txq_xoffs[qi] = txq->stats.xoffs; + } + + dev->stats.tx_packets = packets; + dev->stats.tx_bytes = bytes; + dev->stats.tx_dropped = dropped; + dev->stats.tx_errors = errors; + dev->stats.tx_xoffs = xoffs; +} + +/*! + * Reset device statistics + */ +static void +bcmcnet_pdma_stats_reset(struct pdma_dev *dev) +{ + struct dev_ctrl *ctrl = &dev->ctrl; + struct pdma_rx_queue *rxq = NULL; + struct pdma_tx_queue *txq = NULL; + uint32_t qi; + + sal_memset(&dev->stats, 0, sizeof(struct bcmcnet_dev_stats)); + + for (qi = 0; qi < ctrl->nb_rxq; qi++) { + rxq = (struct pdma_rx_queue *)ctrl->rx_queue[qi]; + if (!rxq) { + continue; + } + rxq->stats.packets = 0; + rxq->stats.bytes = 0; + rxq->stats.dropped = 0; + rxq->stats.errors = 0; + rxq->stats.head_errors = 0; + rxq->stats.data_errors = 0; + rxq->stats.cell_errors = 0; + rxq->stats.nomems = 0; + } + + for (qi = 0; qi < ctrl->nb_txq; qi++) { + txq = (struct pdma_tx_queue *)ctrl->tx_queue[qi]; + if (!txq) { + continue; + } + txq->stats.packets = 0; + txq->stats.bytes = 0; + txq->stats.dropped = 0; + txq->stats.errors = 0; + txq->stats.xoffs = 0; + } +} + +/*! + * Convert logic queue to physical queue + */ +static int +bcmcnet_pdma_lq_to_pq(struct pdma_dev *dev, int queue, int dir, int *chan) +{ + struct dev_ctrl *ctrl = &dev->ctrl; + struct pdma_rx_queue *rxq = NULL; + struct pdma_tx_queue *txq = NULL; + + if (dir == PDMA_Q_RX) { + rxq = (struct pdma_rx_queue *)ctrl->rx_queue[queue]; + if (rxq->state & PDMA_RX_QUEUE_USED) { + *chan = rxq->chan_id; + return SHR_E_NONE; + } + } else { + txq = (struct pdma_tx_queue *)ctrl->tx_queue[queue]; + if (txq->state & PDMA_TX_QUEUE_USED) { + *chan = txq->chan_id; + return SHR_E_NONE; + } + } + + return SHR_E_UNAVAIL; +} + +/*! + * Convert physical queue to logic queue + */ +static int +bcmcnet_pdma_pq_to_lq(struct pdma_dev *dev, int chan, int *queue, int *dir) +{ + struct dev_ctrl *ctrl = &dev->ctrl; + struct pdma_rx_queue *rxq = NULL; + struct pdma_tx_queue *txq = NULL; + + rxq = ctrl->grp[chan / dev->grp_queues].rx_queue[chan % dev->grp_queues]; + if (rxq->state & PDMA_RX_QUEUE_USED) { + *queue = rxq->queue_id; + *dir = PDMA_Q_RX; + return SHR_E_NONE; + } + + txq = ctrl->grp[chan / dev->grp_queues].tx_queue[chan % dev->grp_queues]; + if (txq->state & PDMA_TX_QUEUE_USED) { + *queue = txq->queue_id; + *dir = PDMA_Q_TX; + return SHR_E_NONE; + } + + return SHR_E_UNAVAIL; +} + +/*! + * Start Rx queue + */ +static int +bcmcnet_pdma_rx_queue_start(struct pdma_dev *dev, int queue) +{ + struct dev_ctrl *ctrl = &dev->ctrl; + struct pdma_hw *hw = (struct pdma_hw *)ctrl->hw; + struct pdma_rx_queue *rxq = NULL; + + rxq = (struct pdma_rx_queue *)ctrl->rx_queue[queue]; + rxq->state |= PDMA_RX_QUEUE_ACTIVE; + + return hw->hdls.chan_start(hw, rxq->chan_id); +} + +/*! + * Stop Rx queue + */ +static int +bcmcnet_pdma_rx_queue_stop(struct pdma_dev *dev, int queue) +{ + struct dev_ctrl *ctrl = &dev->ctrl; + struct pdma_hw *hw = (struct pdma_hw *)ctrl->hw; + struct pdma_rx_queue *rxq = NULL; + + rxq = (struct pdma_rx_queue *)ctrl->rx_queue[queue]; + rxq->state &= ~PDMA_RX_QUEUE_ACTIVE; + + return hw->hdls.chan_stop(hw, rxq->chan_id); +} + +/*! + * Start Tx queue + */ +static int +bcmcnet_pdma_tx_queue_start(struct pdma_dev *dev, int queue) +{ + struct dev_ctrl *ctrl = &dev->ctrl; + struct pdma_hw *hw = (struct pdma_hw *)ctrl->hw; + struct pdma_tx_queue *txq = NULL; + + txq = (struct pdma_tx_queue *)ctrl->tx_queue[queue]; + txq->state |= PDMA_TX_QUEUE_ACTIVE; + + return dev->flags & PDMA_CHAIN_MODE ? SHR_E_NONE : + hw->hdls.chan_start(hw, txq->chan_id); +} + +/*! + * Stop Tx queue + */ +static int +bcmcnet_pdma_tx_queue_stop(struct pdma_dev *dev, int queue) +{ + struct dev_ctrl *ctrl = &dev->ctrl; + struct pdma_hw *hw = (struct pdma_hw *)ctrl->hw; + struct pdma_tx_queue *txq = NULL; + + txq = (struct pdma_tx_queue *)ctrl->tx_queue[queue]; + txq->state &= ~PDMA_TX_QUEUE_ACTIVE; + + return hw->hdls.chan_stop(hw, txq->chan_id); +} + +/*! + * Enable Rx queue interrupt + */ +static int +bcmcnet_pdma_rx_queue_intr_enable(struct pdma_dev *dev, int queue) +{ + struct dev_ctrl *ctrl = &dev->ctrl; + struct pdma_hw *hw = (struct pdma_hw *)ctrl->hw; + struct pdma_rx_queue *rxq = NULL; + + rxq = (struct pdma_rx_queue *)ctrl->rx_queue[queue]; + + return hw->hdls.chan_intr_enable(hw, rxq->chan_id); +} + +/*! + * Disable Rx queue interrupt + */ +static int +bcmcnet_pdma_rx_queue_intr_disable(struct pdma_dev *dev, int queue) +{ + struct dev_ctrl *ctrl = &dev->ctrl; + struct pdma_hw *hw = (struct pdma_hw *)ctrl->hw; + struct pdma_rx_queue *rxq = NULL; + + rxq = (struct pdma_rx_queue *)ctrl->rx_queue[queue]; + + return hw->hdls.chan_intr_disable(hw, rxq->chan_id); +} + +/*! + * Acknowledge Rx queue interrupt + */ +static int +bcmcnet_pdma_rx_queue_intr_ack(struct pdma_dev *dev, int queue) +{ + struct dev_ctrl *ctrl = &dev->ctrl; + struct pdma_hw *hw = (struct pdma_hw *)ctrl->hw; + struct pdma_rx_queue *rxq = NULL; + + rxq = (struct pdma_rx_queue *)ctrl->rx_queue[queue]; + + return hw->hdls.chan_clear(hw, rxq->chan_id); +} + +/*! + * Query Rx queue interrupt + */ +static int +bcmcnet_pdma_rx_queue_intr_query(struct pdma_dev *dev, int queue) +{ + struct dev_ctrl *ctrl = &dev->ctrl; + struct pdma_hw *hw = (struct pdma_hw *)ctrl->hw; + struct pdma_rx_queue *rxq = NULL; + + rxq = (struct pdma_rx_queue *)ctrl->rx_queue[queue]; + + return hw->hdls.chan_intr_query(hw, rxq->chan_id); +} + +/*! + * Check Rx queue interrupt + */ +static int +bcmcnet_pdma_rx_queue_intr_check(struct pdma_dev *dev, int queue) +{ + struct dev_ctrl *ctrl = &dev->ctrl; + struct pdma_hw *hw = (struct pdma_hw *)ctrl->hw; + struct pdma_rx_queue *rxq = NULL; + + rxq = (struct pdma_rx_queue *)ctrl->rx_queue[queue]; + + return hw->hdls.chan_intr_check(hw, rxq->chan_id); +} + +/*! + * Enable Tx queue interrupt + */ +static int +bcmcnet_pdma_tx_queue_intr_enable(struct pdma_dev *dev, int queue) +{ + struct dev_ctrl *ctrl = &dev->ctrl; + struct pdma_hw *hw = (struct pdma_hw *)ctrl->hw; + struct pdma_tx_queue *txq = NULL; + + txq = (struct pdma_tx_queue *)ctrl->tx_queue[queue]; + + if (txq->state & PDMA_TX_QUEUE_POLL) { + return SHR_E_NONE; + } else { + return hw->hdls.chan_intr_enable(hw, txq->chan_id); + } +} + +/*! + * Disable Tx queue interrupt + */ +static int +bcmcnet_pdma_tx_queue_intr_disable(struct pdma_dev *dev, int queue) +{ + struct dev_ctrl *ctrl = &dev->ctrl; + struct pdma_hw *hw = (struct pdma_hw *)ctrl->hw; + struct pdma_tx_queue *txq = NULL; + + txq = (struct pdma_tx_queue *)ctrl->tx_queue[queue]; + + return hw->hdls.chan_intr_disable(hw, txq->chan_id); +} + +/*! + * Acknowledge Tx queue interrupt + */ +static int +bcmcnet_pdma_tx_queue_intr_ack(struct pdma_dev *dev, int queue) +{ + struct dev_ctrl *ctrl = &dev->ctrl; + struct pdma_hw *hw = (struct pdma_hw *)ctrl->hw; + struct pdma_tx_queue *txq = NULL; + + txq = (struct pdma_tx_queue *)ctrl->tx_queue[queue]; + + return hw->hdls.chan_clear(hw, txq->chan_id); +} + +/*! + * Query Tx queue interrupt + */ +static int +bcmcnet_pdma_tx_queue_intr_query(struct pdma_dev *dev, int queue) +{ + struct dev_ctrl *ctrl = &dev->ctrl; + struct pdma_hw *hw = (struct pdma_hw *)ctrl->hw; + struct pdma_tx_queue *txq = NULL; + + txq = (struct pdma_tx_queue *)ctrl->tx_queue[queue]; + + return hw->hdls.chan_intr_query(hw, txq->chan_id); +} + +/*! + * Check Tx queue interrupt + */ +static int +bcmcnet_pdma_tx_queue_intr_check(struct pdma_dev *dev, int queue) +{ + struct dev_ctrl *ctrl = &dev->ctrl; + struct pdma_hw *hw = (struct pdma_hw *)ctrl->hw; + struct pdma_tx_queue *txq = NULL; + + txq = (struct pdma_tx_queue *)ctrl->tx_queue[queue]; + + return hw->hdls.chan_intr_check(hw, txq->chan_id); +} + +/*! + * \brief Device operation functions. + */ +static const struct dev_ops pdma_dev_ops = { + .dev_config = bcmcnet_pdma_config, + .dev_close = bcmcnet_pdma_close, + .dev_suspend = bcmcnet_pdma_suspend, + .dev_resume = bcmcnet_pdma_resume, + .dev_info_get = bcmcnet_pdma_info_get, + .dev_stats_get = bcmcnet_pdma_stats_get, + .dev_stats_reset = bcmcnet_pdma_stats_reset, + .dev_lq_to_pq = bcmcnet_pdma_lq_to_pq, + .dev_pq_to_lq = bcmcnet_pdma_pq_to_lq, + .rx_queue_start = bcmcnet_pdma_rx_queue_start, + .rx_queue_stop = bcmcnet_pdma_rx_queue_stop, + .tx_queue_start = bcmcnet_pdma_tx_queue_start, + .tx_queue_stop = bcmcnet_pdma_tx_queue_stop, + .rx_queue_setup = bcmcnet_pdma_rx_queue_setup, + .rx_queue_release = bcmcnet_pdma_rx_queue_release, + .rx_queue_restore = bcmcnet_pdma_rx_queue_restore, + .rx_vqueue_setup = bcmcnet_pdma_rx_vqueue_setup, + .rx_vqueue_release = bcmcnet_pdma_rx_vqueue_release, + .tx_queue_setup = bcmcnet_pdma_tx_queue_setup, + .tx_queue_release = bcmcnet_pdma_tx_queue_release, + .tx_queue_restore = bcmcnet_pdma_tx_queue_restore, + .tx_vqueue_setup = bcmcnet_pdma_tx_vqueue_setup, + .tx_vqueue_release = bcmcnet_pdma_tx_vqueue_release, + .rx_queue_intr_enable = bcmcnet_pdma_rx_queue_intr_enable, + .rx_queue_intr_disable = bcmcnet_pdma_rx_queue_intr_disable, + .rx_queue_intr_ack = bcmcnet_pdma_rx_queue_intr_ack, + .rx_queue_intr_query = bcmcnet_pdma_rx_queue_intr_query, + .rx_queue_intr_check = bcmcnet_pdma_rx_queue_intr_check, + .tx_queue_intr_enable = bcmcnet_pdma_tx_queue_intr_enable, + .tx_queue_intr_disable = bcmcnet_pdma_tx_queue_intr_disable, + .tx_queue_intr_ack = bcmcnet_pdma_tx_queue_intr_ack, + .tx_queue_intr_query = bcmcnet_pdma_tx_queue_intr_query, + .tx_queue_intr_check = bcmcnet_pdma_tx_queue_intr_check, + .rx_queue_suspend = bcmcnet_pdma_rx_queue_suspend, + .rx_queue_resume = bcmcnet_pdma_rx_queue_resume, + .tx_queue_wakeup = bcmcnet_pdma_tx_queue_wakeup, + .rx_queue_poll = bcmcnet_pdma_rx_queue_poll, + .tx_queue_poll = bcmcnet_pdma_tx_queue_poll, + .group_poll = bcmcnet_pdma_group_poll, +}; + +/*! + * Open a device + */ +int +bcmcnet_pdma_open(struct pdma_dev *dev) +{ + struct pdma_hw *hw = (struct pdma_hw *)dev->ctrl.hw; + struct intr_handle *hdl = NULL; + int chan, gi, qi; + + if (!hw) { + return SHR_E_INIT; + } + + /* Initialize the hardware */ + hw->hdls.hw_reset(hw); + hw->hdls.hw_init(hw); + + if ((uint32_t)dev->num_groups > hw->info.num_cmcs) { + return SHR_E_PARAM; + } + dev->grp_queues = hw->info.cmc_chans; + dev->num_queues = hw->info.num_chans; + dev->rx_ph_size = hw->info.rx_ph_size; + dev->tx_ph_size = hw->info.tx_ph_size; + dev->ctrl.nb_desc = NUM_RING_DESC; + dev->ctrl.budget = NUM_RXTX_BUDGET; + dev->ctrl.rx_desc_size = hw->info.rx_dcb_size; + dev->ctrl.tx_desc_size = hw->info.tx_dcb_size; + + /* Initialize interrupt handler */ + for (chan = 0; chan < dev->num_queues; chan++) { + gi = chan / dev->grp_queues; + qi = chan % dev->grp_queues; + hdl = &dev->ctrl.grp[gi].intr_hdl[qi]; + hdl->unit = dev->unit; + hdl->group = gi; + hdl->chan = chan; + hdl->dev = dev; + hdl->intr_num = hw->hdls.chan_intr_num_get(hw, chan); + if (hdl->intr_num < 0) { + return SHR_E_INTERNAL; + } + } + + /* Initialize buffer manager */ + bcmcnet_buf_mngr_init(dev); + + /* Allocate all the queues */ + bcn_rx_queues_alloc(dev); + bcn_tx_queues_alloc(dev); + + dev->pkt_xmit = bcmcnet_pdma_tx_queue_xmit; + + dev->ops = (struct dev_ops *)&pdma_dev_ops; + + return SHR_E_NONE; +} + +/*! + * Coalesce Rx interrupt + */ +int +bcmcnet_pdma_rx_queue_int_coalesce(struct pdma_dev *dev, int queue, int count, int timer) +{ + struct dev_ctrl *ctrl = &dev->ctrl; + struct pdma_hw *hw = (struct pdma_hw *)ctrl->hw; + struct pdma_rx_queue *rxq = NULL; + + if ((uint32_t)queue >= ctrl->nb_rxq) { + return SHR_E_PARAM; + } + + rxq = (struct pdma_rx_queue *)ctrl->rx_queue[queue]; + rxq->intr_coalescing = 1; + rxq->ic_val = (count & 0x7fff) << 16 | (timer & 0xffff); + + return hw->hdls.chan_intr_coalesce(hw, rxq->chan_id, count, timer); +} + +/*! + * Coalesce Tx interrupt + */ +int +bcmcnet_pdma_tx_queue_int_coalesce(struct pdma_dev *dev, int queue, int count, int timer) +{ + struct dev_ctrl *ctrl = &dev->ctrl; + struct pdma_hw *hw = (struct pdma_hw *)ctrl->hw; + struct pdma_tx_queue *txq = NULL; + + if ((uint32_t)queue >= ctrl->nb_txq) { + return SHR_E_PARAM; + } + + txq = (struct pdma_tx_queue *)ctrl->tx_queue[queue]; + txq->intr_coalescing = 1; + txq->ic_val = (count & 0x7fff) << 16 | (timer & 0xffff); + + return hw->hdls.chan_intr_coalesce(hw, txq->chan_id, count, timer); +} + +/*! + * Dump Rx queue registers + */ +int +bcmcnet_pdma_rx_queue_reg_dump(struct pdma_dev *dev, int queue) +{ + struct dev_ctrl *ctrl = &dev->ctrl; + struct pdma_hw *hw = (struct pdma_hw *)ctrl->hw; + struct pdma_rx_queue *rxq = NULL; + + if ((uint32_t)queue >= ctrl->nb_rxq) { + return SHR_E_PARAM; + } + + rxq = (struct pdma_rx_queue *)ctrl->rx_queue[queue]; + + return hw->hdls.chan_reg_dump(hw, rxq->chan_id); +} + +/*! + * Dump Tx queue registers + */ +int +bcmcnet_pdma_tx_queue_reg_dump(struct pdma_dev *dev, int queue) +{ + struct dev_ctrl *ctrl = &dev->ctrl; + struct pdma_hw *hw = (struct pdma_hw *)ctrl->hw; + struct pdma_tx_queue *txq = NULL; + + if ((uint32_t)queue >= ctrl->nb_txq) { + return SHR_E_PARAM; + } + + txq = (struct pdma_tx_queue *)ctrl->tx_queue[queue]; + + return hw->hdls.chan_reg_dump(hw, txq->chan_id); +} + diff --git a/platform/broadcom/saibcm-modules/sdklt/bcmcnet/main/bcmcnet_rxtx.c b/platform/broadcom/saibcm-modules/sdklt/bcmcnet/main/bcmcnet_rxtx.c new file mode 100644 index 00000000000..cfabe9d95d5 --- /dev/null +++ b/platform/broadcom/saibcm-modules/sdklt/bcmcnet/main/bcmcnet_rxtx.c @@ -0,0 +1,708 @@ +/*! \file bcmcnet_rxtx.c + * + * Utility routines for BCMCNET Rx/Tx. + * + */ +/* + * $Copyright: Copyright 2018-2020 Broadcom. All rights reserved. + * The term 'Broadcom' refers to Broadcom Inc. and/or its subsidiaries. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * version 2 as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * A copy of the GNU General Public License version 2 (GPLv2) can + * be found in the LICENSES folder.$ + */ + +#include +#include +#include +#include + +/*! + * Free a Rx ring + */ +static void +bcn_rx_ring_free(struct pdma_rx_queue *rxq) +{ + struct dev_ctrl *ctrl = rxq->ctrl; + struct pdma_buf_mngr *bm = (struct pdma_buf_mngr *)ctrl->buf_mngr; + + if (rxq->lock) { + sal_spinlock_destroy(rxq->lock); + rxq->lock = NULL; + } + + if (rxq->ring) { + bm->ring_buf_free(ctrl->dev, ctrl->rx_desc_size * (rxq->nb_desc + 1), + rxq->ring, rxq->ring_addr); + rxq->ring = NULL; + } + + if (rxq->pbuf) { + sal_free(rxq->pbuf); + rxq->pbuf = NULL; + } +} + +/*! + * Allocate a Rx ring + */ +static int +bcn_rx_ring_alloc(struct pdma_rx_queue *rxq) +{ + struct dev_ctrl *ctrl = rxq->ctrl; + struct pdma_buf_mngr *bm = (struct pdma_buf_mngr *)ctrl->buf_mngr; + + /* Setup pktbuf ring */ + rxq->pbuf = sal_alloc(sizeof(*rxq->pbuf) * rxq->nb_desc, "bcmcnetRxBufRing"); + if (!rxq->pbuf) { + goto cleanup; + } + sal_memset(rxq->pbuf, 0, sizeof(*rxq->pbuf) * rxq->nb_desc); + + /* Allocate memory for descriptors */ + rxq->ring = bm->ring_buf_alloc(ctrl->dev, ctrl->rx_desc_size * (rxq->nb_desc + 1), + &rxq->ring_addr); + if (!rxq->ring) { + goto cleanup; + } + sal_memset(rxq->ring, 0, ctrl->rx_desc_size * (rxq->nb_desc + 1)); + + rxq->lock = sal_spinlock_create("bcmcnetRxQueueLock"); + if (!rxq->lock) { + goto cleanup; + } + + return SHR_E_NONE; + +cleanup: + bcn_rx_ring_free(rxq); + + return SHR_E_MEMORY; +} + +/*! + * Free a Tx ring + */ +static void +bcn_tx_ring_free(struct pdma_tx_queue *txq) +{ + struct dev_ctrl *ctrl = txq->ctrl; + struct pdma_buf_mngr *bm = (struct pdma_buf_mngr *)ctrl->buf_mngr; + + if (txq->sem) { + sal_sem_destroy(txq->sem); + txq->sem = NULL; + } + + if (txq->mutex) { + sal_spinlock_destroy(txq->mutex); + txq->mutex = NULL; + } + + if (txq->lock) { + sal_spinlock_destroy(txq->lock); + txq->lock = NULL; + } + + if (txq->ring) { + bm->ring_buf_free(ctrl->dev, ctrl->tx_desc_size * (txq->nb_desc + 1), + txq->ring, txq->ring_addr); + txq->ring = NULL; + } + + if (txq->pbuf) { + sal_free(txq->pbuf); + txq->pbuf = NULL; + } +} + +/*! + * Allocate a Tx ring + */ +static int +bcn_tx_ring_alloc(struct pdma_tx_queue *txq) +{ + struct dev_ctrl *ctrl = txq->ctrl; + struct pdma_buf_mngr *bm = (struct pdma_buf_mngr *)ctrl->buf_mngr; + + /* Setup pktbuf ring */ + txq->pbuf = sal_alloc(sizeof(*txq->pbuf) * txq->nb_desc, "bcmcnetTxBufRing"); + if (!txq->pbuf) { + goto cleanup; + } + sal_memset(txq->pbuf, 0, sizeof(*txq->pbuf) * txq->nb_desc); + + /* Allocate memory for descriptors */ + txq->ring = bm->ring_buf_alloc(ctrl->dev, ctrl->tx_desc_size * (txq->nb_desc + 1), + &txq->ring_addr); + if (!txq->ring) { + goto cleanup; + } + sal_memset(txq->ring, 0, ctrl->tx_desc_size * (txq->nb_desc + 1)); + + txq->lock = sal_spinlock_create("bcmcnetTxQueueLock"); + if (!txq->lock) { + goto cleanup; + } + + txq->mutex = sal_spinlock_create("bcmcnetTxMutexLock"); + if (!txq->mutex) { + goto cleanup; + } + + txq->sem = sal_sem_create("bcmcnetTxMutexSem", SAL_SEM_BINARY, 0); + if (!txq->sem) { + goto cleanup; + } + + return SHR_E_NONE; + +cleanup: + bcn_tx_ring_free(txq); + + return SHR_E_MEMORY; +} + +/*! + * Rx polling + */ +static int +bcn_rx_poll(struct pdma_rx_queue *rxq, int budget) +{ + struct dev_ctrl *ctrl = rxq->ctrl; + struct pdma_hw *hw = (struct pdma_hw *)ctrl->hw; + + return hw->dops.rx_ring_clean(hw, rxq, budget); +} + +/*! + * Tx polling + */ +static int +bcn_tx_poll(struct pdma_tx_queue *txq, int budget) +{ + struct dev_ctrl *ctrl = txq->ctrl; + struct pdma_hw *hw = (struct pdma_hw *)ctrl->hw; + + return hw->dops.tx_ring_clean(hw, txq, budget); +} + +/*! + * Setup a Rx queue + */ +int +bcmcnet_pdma_rx_queue_setup(struct pdma_dev *dev, int queue) +{ + struct dev_ctrl *ctrl = &dev->ctrl; + struct pdma_hw *hw = (struct pdma_hw *)ctrl->hw; + struct pdma_rx_queue *rxq = NULL; + int rv; + + rxq = (struct pdma_rx_queue *)ctrl->rx_queue[queue]; + if (rxq->state & PDMA_RX_QUEUE_SETUP) { + return SHR_E_NONE; + } + + rv = bcn_rx_ring_alloc(rxq); + if (SHR_FAILURE(rv)) { + return rv; + } + + rv = hw->dops.rx_desc_init(hw, rxq); + if (SHR_FAILURE(rv)) { + return rv; + } + + if (dev->mode == DEV_MODE_VNET) { + ctrl->vsync.rx_ring_addr[queue] = rxq->ring_addr; + ctrl->vsync.rx_ring_size[queue] = rxq->nb_desc; + } + + rxq->state |= PDMA_RX_QUEUE_SETUP; + + return SHR_E_NONE; +} + +/*! + * Release a Rx queue + */ +int +bcmcnet_pdma_rx_queue_release(struct pdma_dev *dev, int queue) +{ + struct dev_ctrl *ctrl = &dev->ctrl; + struct pdma_hw *hw = (struct pdma_hw *)ctrl->hw; + struct pdma_rx_queue *rxq = NULL; + + rxq = (struct pdma_rx_queue *)ctrl->rx_queue[queue]; + if (rxq->state & PDMA_RX_QUEUE_SETUP) { + hw->dops.rx_desc_clean(hw, rxq); + bcn_rx_ring_free(rxq); + rxq->state &= ~PDMA_RX_QUEUE_SETUP; + } + + return SHR_E_NONE; +} + +/*! + * Restore a Rx queue + */ +int +bcmcnet_pdma_rx_queue_restore(struct pdma_dev *dev, int queue) +{ + struct dev_ctrl *ctrl = &dev->ctrl; + struct pdma_hw *hw = (struct pdma_hw *)ctrl->hw; + struct pdma_rx_queue *rxq = NULL; + + rxq = (struct pdma_rx_queue *)ctrl->rx_queue[queue]; + if (rxq->state & PDMA_RX_QUEUE_SETUP) { + hw->dops.rx_desc_init(hw, rxq); + } + + return SHR_E_NONE; +} + +/*! + * Set up a virtual Rx queue + */ +int +bcmcnet_pdma_rx_vqueue_setup(struct pdma_dev *dev, int queue) +{ + struct dev_ctrl *ctrl = &dev->ctrl; + struct pdma_rx_queue *vrxq = NULL; + + vrxq = (struct pdma_rx_queue *)ctrl->vnet_rxq[queue]; + if (vrxq->state & PDMA_RX_QUEUE_SETUP) { + return SHR_E_NONE; + } + + if (dev->ctrl.vsync.rx_ring_addr[queue]) { + vrxq->curr = 0; + vrxq->nb_desc = dev->ctrl.vsync.rx_ring_size[queue]; + vrxq->ring_addr = dev->ctrl.vsync.rx_ring_addr[queue]; + vrxq->ring = dev->sys_p2v(dev, vrxq->ring_addr); + vrxq->state |= PDMA_RX_QUEUE_SETUP; + } else { + return SHR_E_UNAVAIL; + } + + return SHR_E_NONE; +} + +/*! + * Release a virtual Rx queue + */ +int +bcmcnet_pdma_rx_vqueue_release(struct pdma_dev *dev, int queue) +{ + struct dev_ctrl *ctrl = &dev->ctrl; + struct pdma_rx_queue *vrxq = NULL; + + vrxq = (struct pdma_rx_queue *)ctrl->vnet_rxq[queue]; + if (vrxq->state & PDMA_RX_QUEUE_SETUP) { + vrxq->state &= ~PDMA_RX_QUEUE_SETUP; + vrxq->ring = NULL; + } + + return SHR_E_NONE; +} + +/*! + * Setup a Tx queue + */ +int +bcmcnet_pdma_tx_queue_setup(struct pdma_dev *dev, int queue) +{ + struct dev_ctrl *ctrl = &dev->ctrl; + struct pdma_hw *hw = (struct pdma_hw *)ctrl->hw; + struct pdma_tx_queue *txq = NULL; + int rv; + + txq = (struct pdma_tx_queue *)ctrl->tx_queue[queue]; + if (txq->state & PDMA_TX_QUEUE_SETUP) { + return SHR_E_NONE; + } + + rv = bcn_tx_ring_alloc(txq); + if (SHR_FAILURE(rv)) { + return rv; + } + + rv = hw->dops.tx_desc_init(hw, txq); + if (SHR_FAILURE(rv)) { + return rv; + } + + if (dev->mode == DEV_MODE_VNET) { + ctrl->vsync.tx_ring_addr[queue] = txq->ring_addr; + ctrl->vsync.tx_ring_size[queue] = txq->nb_desc; + } + + txq->state |= PDMA_TX_QUEUE_SETUP; + + return SHR_E_NONE; +} + +/*! + * Release a Tx queue + */ +int +bcmcnet_pdma_tx_queue_release(struct pdma_dev *dev, int queue) +{ + struct dev_ctrl *ctrl = &dev->ctrl; + struct pdma_hw *hw = (struct pdma_hw *)ctrl->hw; + struct pdma_tx_queue *txq = NULL; + + txq = (struct pdma_tx_queue *)ctrl->tx_queue[queue]; + if (txq->state & PDMA_TX_QUEUE_SETUP) { + hw->dops.tx_desc_clean(hw, txq); + bcn_tx_ring_free(txq); + txq->state &= ~PDMA_TX_QUEUE_SETUP; + } + + return SHR_E_NONE; +} + +/*! + * Restore a Tx queue + */ +int +bcmcnet_pdma_tx_queue_restore(struct pdma_dev *dev, int queue) +{ + struct dev_ctrl *ctrl = &dev->ctrl; + struct pdma_hw *hw = (struct pdma_hw *)ctrl->hw; + struct pdma_tx_queue *txq = NULL; + + txq = (struct pdma_tx_queue *)ctrl->tx_queue[queue]; + if (txq->state & PDMA_TX_QUEUE_SETUP) { + hw->dops.tx_desc_init(hw, txq); + } + + return SHR_E_NONE; +} + +/*! + * Set up a virtual Tx queue + */ +int +bcmcnet_pdma_tx_vqueue_setup(struct pdma_dev *dev, int queue) +{ + struct dev_ctrl *ctrl = &dev->ctrl; + struct pdma_tx_queue *vtxq = NULL; + + vtxq = (struct pdma_tx_queue *)ctrl->vnet_txq[queue]; + if (vtxq->state & PDMA_TX_QUEUE_SETUP) { + return SHR_E_NONE; + } + + if (dev->ctrl.vsync.tx_ring_addr[queue]) { + vtxq->curr = 0; + vtxq->dirt = 0; + vtxq->nb_desc = dev->ctrl.vsync.tx_ring_size[queue]; + vtxq->ring_addr = dev->ctrl.vsync.tx_ring_addr[queue]; + vtxq->ring = dev->sys_p2v(dev, vtxq->ring_addr); + vtxq->state |= PDMA_TX_QUEUE_SETUP; + } else { + return SHR_E_UNAVAIL; + } + + return SHR_E_NONE; +} + +/*! + * Release a virtual Tx queue + */ +int +bcmcnet_pdma_tx_vqueue_release(struct pdma_dev *dev, int queue) +{ + struct dev_ctrl *ctrl = &dev->ctrl; + struct pdma_tx_queue *vtxq = NULL; + + vtxq = (struct pdma_tx_queue *)ctrl->vnet_txq[queue]; + if (vtxq->state & PDMA_TX_QUEUE_SETUP) { + vtxq->state &= ~PDMA_TX_QUEUE_SETUP; + vtxq->ring = NULL; + } + + return SHR_E_NONE; +} + +/*! + * Suspend a Rx queue + */ +int +bcmcnet_pdma_rx_queue_suspend(struct pdma_dev *dev, int queue) +{ + struct dev_ctrl *ctrl = &dev->ctrl; + struct pdma_hw *hw = (struct pdma_hw *)ctrl->hw; + struct pdma_rx_queue *rxq = NULL; + + rxq = (struct pdma_rx_queue *)ctrl->rx_queue[queue]; + if (!rxq || !(rxq->state & PDMA_RX_QUEUE_ACTIVE)) { + return SHR_E_UNAVAIL; + } + + return hw->dops.rx_suspend(hw, rxq); +} + +/*! + * Resume a Rx queue + */ +int +bcmcnet_pdma_rx_queue_resume(struct pdma_dev *dev, int queue) +{ + struct dev_ctrl *ctrl = &dev->ctrl; + struct pdma_hw *hw = (struct pdma_hw *)ctrl->hw; + struct pdma_rx_queue *rxq = NULL; + + rxq = (struct pdma_rx_queue *)ctrl->rx_queue[queue]; + if (!rxq || !(rxq->state & PDMA_RX_QUEUE_ACTIVE)) { + return SHR_E_UNAVAIL; + } + + return hw->dops.rx_resume(hw, rxq); +} + +/*! + * Suspend a Tx queue + */ +int +bcmcnet_pdma_tx_queue_suspend(struct pdma_dev *dev, int queue) +{ + struct dev_ctrl *ctrl = &dev->ctrl; + struct pdma_tx_queue *txq = NULL; + + txq = (struct pdma_tx_queue *)ctrl->tx_queue[queue]; + if (!txq || !(txq->state & PDMA_TX_QUEUE_ACTIVE)) { + return SHR_E_UNAVAIL; + } + + if (txq->sem) { + sal_sem_take(txq->sem, SAL_SEM_FOREVER); + } + if (dev->tx_suspend) { + dev->tx_suspend(dev, txq->queue_id); + } + + return SHR_E_NONE; +} + +/*! + * Resume a Tx queue + */ +int +bcmcnet_pdma_tx_queue_resume(struct pdma_dev *dev, int queue) +{ + struct dev_ctrl *ctrl = &dev->ctrl; + struct pdma_tx_queue *txq = NULL; + + txq = (struct pdma_tx_queue *)ctrl->tx_queue[queue]; + if (!txq || !(txq->state & PDMA_TX_QUEUE_ACTIVE)) { + return SHR_E_UNAVAIL; + } + + if (txq->sem) { + sal_sem_give(txq->sem); + } + if (dev->tx_resume) { + dev->tx_resume(dev, txq->queue_id); + } + + return SHR_E_NONE; +} + +/*! + * Wake up a Tx queue + */ +int +bcmcnet_pdma_tx_queue_wakeup(struct pdma_dev *dev, int queue) +{ + struct dev_ctrl *ctrl = &dev->ctrl; + struct pdma_tx_queue *txq = NULL; + + txq = (struct pdma_tx_queue *)ctrl->tx_queue[queue]; + if (txq->sem) { + sal_sem_give(txq->sem); + } + + return SHR_E_NONE; +} + +/*! + * Transmit a outputing packet + */ +int +bcmcnet_pdma_tx_queue_xmit(struct pdma_dev *dev, int queue, void *buf) +{ + struct dev_ctrl *ctrl = &dev->ctrl; + struct pdma_hw *hw = (struct pdma_hw *)ctrl->hw; + struct pdma_tx_queue *txq = NULL; + + txq = (struct pdma_tx_queue *)ctrl->tx_queue[queue]; + if (!txq || !(txq->state & PDMA_TX_QUEUE_ACTIVE)) { + return SHR_E_UNAVAIL; + } + + return hw->dops.pkt_xmit(hw, txq, buf); +} + +/*! + * Poll a Rx queues + */ +int +bcmcnet_pdma_rx_queue_poll(struct pdma_dev *dev, int queue, int budget) +{ + struct dev_ctrl *ctrl = &dev->ctrl; + struct pdma_rx_queue *rxq = ctrl->rx_queue[queue]; + + return bcn_rx_poll(rxq, budget); +} + +/*! + * Poll a Tx queues + */ +int +bcmcnet_pdma_tx_queue_poll(struct pdma_dev *dev, int queue, int budget) +{ + struct dev_ctrl *ctrl = &dev->ctrl; + struct pdma_tx_queue *txq = ctrl->tx_queue[queue]; + + return bcn_tx_poll(txq, budget); +} + +/*! + * Poll for Rx/Tx queues in a group + */ +int +bcmcnet_pdma_group_poll(struct pdma_dev *dev, int group, int budget) +{ + struct dev_ctrl *ctrl = &dev->ctrl; + struct pdma_hw *hw = (struct pdma_hw *)ctrl->hw; + struct pdma_rx_queue *rxq = NULL; + struct pdma_tx_queue *txq = NULL; + struct queue_group *grp = &ctrl->grp[group]; + int done = 0, done_que, budget_que; + int i; + + /* Acknowledge the interrupts */ + for (i = 0; i < dev->grp_queues; i++) { + rxq = grp->rx_queue[i]; + if (rxq->state & PDMA_RX_QUEUE_ACTIVE) { + if (hw->hdls.chan_intr_query(hw, rxq->chan_id)) { + hw->hdls.chan_clear(hw, rxq->chan_id); + grp->poll_queues |= 1 << i; + } else if (rxq->state & PDMA_RX_QUEUE_BUSY) { + rxq->state &= ~PDMA_RX_QUEUE_BUSY; + grp->poll_queues |= 1 << i; + } + continue; + } + txq = grp->tx_queue[i]; + if (txq->state & PDMA_TX_QUEUE_ACTIVE) { + if (hw->hdls.chan_intr_query(hw, txq->chan_id)) { + hw->hdls.chan_clear(hw, txq->chan_id); + grp->poll_queues |= 1 << i; + } + } + } + + /* Calculate per queue budget */ + if (!grp->poll_queues) { + grp->poll_queues = grp->bm_rxq | grp->bm_txq; + budget_que = budget / grp->nb_rxq; + } else { + budget_que = 0; + for (i = 0; i < dev->grp_queues; i++) { + if (1 << i & grp->bm_rxq & grp->poll_queues) { + budget_que++; + } + } + if (budget_que) { + budget_que = budget / budget_que; + } + } + + /* Poll Rx queues */ + for (i = 0; i < dev->grp_queues; i++) { + if (1 << i & grp->bm_rxq & grp->poll_queues) { + rxq = grp->rx_queue[i]; + done_que = bcn_rx_poll(rxq, budget_que); + if (done_que < budget_que) { + grp->poll_queues &= ~(1 << i); + } + done += done_que; + } + } + + /* Poll Tx queues */ + for (i = 0; i < dev->grp_queues; i++) { + txq = grp->tx_queue[i]; + if (1 << i & grp->bm_txq & grp->poll_queues && !txq->free_thresh) { + if (bcn_tx_poll(txq, budget) < budget) { + grp->poll_queues &= ~(1 << i); + } + } + } + + return grp->poll_queues ? budget : done; +} + +/*! + * Dump a Rx ring + */ +int +bcmcnet_pdma_rx_ring_dump(struct pdma_dev *dev, int queue) +{ + struct dev_ctrl *ctrl = &dev->ctrl; + struct pdma_hw *hw = ctrl->hw; + struct pdma_rx_queue *rxq = NULL; + + if ((uint32_t)queue >= ctrl->nb_rxq) { + return SHR_E_PARAM; + } + + rxq = (struct pdma_rx_queue *)ctrl->rx_queue[queue]; + if (rxq->state & PDMA_RX_QUEUE_ACTIVE) { + hw->dops.rx_ring_dump(hw, rxq); + } + if (dev->mode == DEV_MODE_HNET) { + rxq = (struct pdma_rx_queue *)ctrl->vnet_rxq[queue]; + hw->dops.rx_ring_dump(hw, rxq); + } + + return SHR_E_NONE; +} + +/*! + * Dump a Tx ring + */ +int +bcmcnet_pdma_tx_ring_dump(struct pdma_dev *dev, int queue) +{ + struct dev_ctrl *ctrl = &dev->ctrl; + struct pdma_hw *hw = ctrl->hw; + struct pdma_tx_queue *txq = NULL; + + if ((uint32_t)queue >= ctrl->nb_txq) { + return SHR_E_PARAM; + } + + txq = (struct pdma_tx_queue *)ctrl->tx_queue[queue]; + if (txq->state & PDMA_TX_QUEUE_ACTIVE) { + hw->dops.tx_ring_dump(hw, txq); + } + if (dev->mode == DEV_MODE_HNET) { + txq = (struct pdma_tx_queue *)ctrl->vnet_txq[queue]; + hw->dops.tx_ring_dump(hw, txq); + } + + return SHR_E_NONE; +} + diff --git a/platform/broadcom/saibcm-modules/sdklt/bcmdrd/include/bcmdrd/bcmdrd_devlist.h b/platform/broadcom/saibcm-modules/sdklt/bcmdrd/include/bcmdrd/bcmdrd_devlist.h new file mode 100644 index 00000000000..675b9426ea0 --- /dev/null +++ b/platform/broadcom/saibcm-modules/sdklt/bcmdrd/include/bcmdrd/bcmdrd_devlist.h @@ -0,0 +1,337 @@ +/* + * DO NOT EDIT THIS FILE! + * This file is auto-generated. + * Edits to this file will be lost when it is regenerated. + * Tool: INTERNAL/drd/instpkgs.pl + * + * $Copyright: Copyright 2018-2020 Broadcom. All rights reserved. + * The term 'Broadcom' refers to Broadcom Inc. and/or its subsidiaries. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * version 2 as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * A copy of the GNU General Public License version 2 (GPLv2) can + * be found in the LICENSES folder.$ + */ + +/* + * This file contains the complete list of supported devices. + * No other device lists should be used anywhere in the SDK. + */ + +#ifndef BCMDRD_DEVIDS_H +#define BCMDRD_DEVIDS_H + +#include + +/* + * All Supported Devices and Revisions + */ + +#define BROADCOM_VENDOR_ID 0x14e4 +#define BROADCOM_PHYID_MSB 0x0143 + +/* BCM56780 */ +#define BCM56780_VENDOR_ID 0x14e4 +#define BCM56780_DEVICE_ID 0xb780 +#define BCM56780_REV_A0 0x01 + +/* BCM56782 */ +#define BCM56782_VENDOR_ID 0x14e4 +#define BCM56782_DEVICE_ID 0xb782 +#define BCM56782_REV_A0 0x01 + +/* BCM56784 */ +#define BCM56784_VENDOR_ID 0x14e4 +#define BCM56784_DEVICE_ID 0xb784 +#define BCM56784_REV_A0 0x01 + +/* BCM56786 */ +#define BCM56786_VENDOR_ID 0x14e4 +#define BCM56786_DEVICE_ID 0xb786 +#define BCM56786_REV_A0 0x01 + +/* BCM56788 */ +#define BCM56788_VENDOR_ID 0x14e4 +#define BCM56788_DEVICE_ID 0xb788 +#define BCM56788_REV_A0 0x01 + +/* BCM56789 */ +#define BCM56789_VENDOR_ID 0x14e4 +#define BCM56789_DEVICE_ID 0xb789 +#define BCM56789_REV_A0 0x01 + +/* BCM56880 */ +#define BCM56880_VENDOR_ID 0x14e4 +#define BCM56880_DEVICE_ID 0xb880 +#define BCM56880_REV_A0 0x01 +#define BCM56880_REV_B0 0x11 + +/* BCM56881 */ +#define BCM56881_VENDOR_ID 0x14e4 +#define BCM56881_DEVICE_ID 0xb881 +#define BCM56881_REV_A0 0x01 +#define BCM56881_REV_B0 0x11 + +/* BCM56883 */ +#define BCM56883_VENDOR_ID 0x14e4 +#define BCM56883_DEVICE_ID 0xb883 +#define BCM56883_REV_A0 0x01 +#define BCM56883_REV_B0 0x11 + +/* BCM56889 */ +#define BCM56889_VENDOR_ID 0x14e4 +#define BCM56889_DEVICE_ID 0xb889 +#define BCM56889_REV_A0 0x01 +#define BCM56889_REV_B0 0x11 + +/* BCM56990 */ +#define BCM56990_VENDOR_ID 0x14e4 +#define BCM56990_DEVICE_ID 0xb990 +#define BCM56990_REV_A0 0x01 +#define BCM56990_REV_B0 0x11 + +/* BCM56992 */ +#define BCM56992_VENDOR_ID 0x14e4 +#define BCM56992_DEVICE_ID 0xb992 +#define BCM56992_REV_B0 0x11 + +/* BCM56996 */ +#define BCM56996_VENDOR_ID 0x14e4 +#define BCM56996_DEVICE_ID 0xb996 +#define BCM56996_REV_A0 0x01 + +/* BCM56997 */ +#define BCM56997_VENDOR_ID 0x14e4 +#define BCM56997_DEVICE_ID 0xb997 +#define BCM56997_REV_A0 0x01 + +/* + * End of Supported Devices and Revisions + */ + +#endif /* BCMDRD_DEVIDS_H */ + +#ifdef BCMDRD_DEVLIST_ENTRY +/* + * BCMDRD_DEVLIST_ENTRY macros. + * + * Before including this file, define BCMDRD_DEVLIST_ENTRY + * as a macro to operate on the following parameters: + * + * #define BCMDRD_DEVLIST_ENTRY(_nm,_vn,_dv,_rv,_md,_pi,_bd,_bc,_fn,_cn,_pf,_pd,_r0,_r1) + * + * _nm: Chip Name + * _vn: Chip Vendor ID + * _dv: Chip Device ID + * _rv: Chip Revision + * _md: Chip Model + * _pi: Probe Information + * _bd: SW Base Driver + * _bc: SW Base Configuration + * _fn: SW Full Name + * _cn: Code Name + * _pf: Product Family + * _pd: Product Description + * _r0: Reserved + * _r1: Reserved + * + * Note that this macro will be undefined at the end of this file. + */ + +#if BCMDRD_CONFIG_INCLUDE_BCM56780_A0 == 1 || defined(BCMDRD_DEVLIST_OVERRIDE) +BCMDRD_DEVLIST_ENTRY(BCM56780, BCM56780_VENDOR_ID, BCM56780_DEVICE_ID, BCM56780_REV_A0, \ + 0, 0, \ + bcm56780_a0, bcm56780_a0, bcm56780_a0, \ + "Trident4-X9", "BCM56780", \ + "8 Tb/s 160x50G-PAM4 Programmable Switch", 0, 0) +#endif + +#if BCMDRD_CONFIG_INCLUDE_BCM56782_A0 == 1 || defined(BCMDRD_DEVLIST_OVERRIDE) +#ifdef BCMDRD_DEVLIST_INCLUDE_ALL +BCMDRD_DEVLIST_ENTRY(BCM56782, BCM56782_VENDOR_ID, BCM56782_DEVICE_ID, BCM56782_REV_A0, \ + 0, 0, \ + bcm56780_a0, bcm56782_a0, bcm56782_a0, \ + "Trident4-X9", "BCM56780", \ + "8 Tb/s 160x50G-PAM4 Programmable Switch w/MACsec", 0, 0) +#endif +#endif + +#if BCMDRD_CONFIG_INCLUDE_BCM56784_A0 == 1 || defined(BCMDRD_DEVLIST_OVERRIDE) +#ifdef BCMDRD_DEVLIST_INCLUDE_ALL +BCMDRD_DEVLIST_ENTRY(BCM56784, BCM56784_VENDOR_ID, BCM56784_DEVICE_ID, BCM56784_REV_A0, \ + 0, 0, \ + bcm56780_a0, bcm56784_a0, bcm56784_a0, \ + "Trident4-X9", "BCM56780", \ + "5.6 Tb/s 96x50G-PAM4/32x35G-NRZ Programmable Switch", 0, 0) +#endif +#endif + +#if BCMDRD_CONFIG_INCLUDE_BCM56786_A0 == 1 || defined(BCMDRD_DEVLIST_OVERRIDE) +#ifdef BCMDRD_DEVLIST_INCLUDE_ALL +BCMDRD_DEVLIST_ENTRY(BCM56786, BCM56786_VENDOR_ID, BCM56786_DEVICE_ID, BCM56786_REV_A0, \ + 0, 0, \ + bcm56780_a0, bcm56786_a0, bcm56786_a0, \ + "Trident4-X9", "BCM56780", \ + "5.6 Tb/s 96x50G-PAM4/32x35G-NRZ Programmable Switch w/MACsec", 0, 0) +#endif +#endif + +#if BCMDRD_CONFIG_INCLUDE_BCM56788_A0 == 1 || defined(BCMDRD_DEVLIST_OVERRIDE) +#ifdef BCMDRD_DEVLIST_INCLUDE_ALL +BCMDRD_DEVLIST_ENTRY(BCM56788, BCM56788_VENDOR_ID, BCM56788_DEVICE_ID, BCM56788_REV_A0, \ + 0, 0, \ + bcm56780_a0, bcm56788_a0, bcm56788_a0, \ + "Trident4-X9", "BCM56780", \ + "8 Tb/s 160x50G-PAM4 Programmable Switch w/MACsec w/MTop", 0, 0) +#endif +#endif + +#if BCMDRD_CONFIG_INCLUDE_BCM56789_A0 == 1 || defined(BCMDRD_DEVLIST_OVERRIDE) +#ifdef BCMDRD_DEVLIST_INCLUDE_ALL +BCMDRD_DEVLIST_ENTRY(BCM56789, BCM56789_VENDOR_ID, BCM56789_DEVICE_ID, BCM56789_REV_A0, \ + 0, 0, \ + bcm56780_a0, bcm56789_a0, bcm56789_a0, \ + "Trident4-X9", "BCM56780", \ + "8 Tb/s 160x50G-PAM4 Programmable Switch w/MTop", 0, 0) +#endif +#endif + +#if BCMDRD_CONFIG_INCLUDE_BCM56880_A0 == 1 || defined(BCMDRD_DEVLIST_OVERRIDE) +BCMDRD_DEVLIST_ENTRY(BCM56880, BCM56880_VENDOR_ID, BCM56880_DEVICE_ID, BCM56880_REV_A0, \ + 0, 0, \ + bcm56880_a0, bcm56880_a0, bcm56880_a0, \ + "Trident4", "BCM56880", \ + "12.8 Tb/s Switch Fabric 128x100G/64x200G/32x400G Multilayer Switch", 0, 0) +#endif + +#if BCMDRD_CONFIG_INCLUDE_BCM56880_B0 == 1 || defined(BCMDRD_DEVLIST_OVERRIDE) +#ifdef BCMDRD_DEVLIST_INCLUDE_ALL +BCMDRD_DEVLIST_ENTRY(BCM56880, BCM56880_VENDOR_ID, BCM56880_DEVICE_ID, BCM56880_REV_B0, \ + 0, 0, \ + bcm56880_a0, bcm56880_a0, bcm56880_b0, \ + "Trident4", "BCM56880", \ + "12.8 Tb/s Switch Fabric 128x100G/64x200G/32x400G Multilayer Switch", 0, 0) +#endif +#endif + +#if BCMDRD_CONFIG_INCLUDE_BCM56881_A0 == 1 || defined(BCMDRD_DEVLIST_OVERRIDE) +#ifdef BCMDRD_DEVLIST_INCLUDE_ALL +BCMDRD_DEVLIST_ENTRY(BCM56881, BCM56881_VENDOR_ID, BCM56881_DEVICE_ID, BCM56881_REV_A0, \ + 0, 0, \ + bcm56880_a0, bcm56881_a0, bcm56881_a0, \ + "Trident4", "BCM56880", \ + "12.8 Tb/s Switch Fabric 128x100G/64x200G/32x400G Multilayer Switch", 0, 0) +#endif +#endif + +#if BCMDRD_CONFIG_INCLUDE_BCM56881_B0 == 1 || defined(BCMDRD_DEVLIST_OVERRIDE) +#ifdef BCMDRD_DEVLIST_INCLUDE_ALL +BCMDRD_DEVLIST_ENTRY(BCM56881, BCM56881_VENDOR_ID, BCM56881_DEVICE_ID, BCM56881_REV_B0, \ + 0, 0, \ + bcm56880_a0, bcm56881_a0, bcm56881_b0, \ + "Trident4", "BCM56880", \ + "12.8 Tb/s Switch Fabric 128x100G/64x200G/32x400G Multilayer Switch", 0, 0) +#endif +#endif + +#if BCMDRD_CONFIG_INCLUDE_BCM56883_A0 == 1 || defined(BCMDRD_DEVLIST_OVERRIDE) +#ifdef BCMDRD_DEVLIST_INCLUDE_ALL +BCMDRD_DEVLIST_ENTRY(BCM56883, BCM56883_VENDOR_ID, BCM56883_DEVICE_ID, BCM56883_REV_A0, \ + 0, 0, \ + bcm56880_a0, bcm56883_a0, bcm56883_a0, \ + "Trident4", "BCM56880", \ + "8.0 Tb/s Switch Fabric 80x100G/40x200G/20x400G Multilayer Switch", 0, 0) +#endif +#endif + +#if BCMDRD_CONFIG_INCLUDE_BCM56883_B0 == 1 || defined(BCMDRD_DEVLIST_OVERRIDE) +#ifdef BCMDRD_DEVLIST_INCLUDE_ALL +BCMDRD_DEVLIST_ENTRY(BCM56883, BCM56883_VENDOR_ID, BCM56883_DEVICE_ID, BCM56883_REV_B0, \ + 0, 0, \ + bcm56880_a0, bcm56883_a0, bcm56883_b0, \ + "Trident4", "BCM56880", \ + "8.0 Tb/s Switch Fabric 80x100G/40x200G/20x400G Multilayer Switch", 0, 0) +#endif +#endif + +#if BCMDRD_CONFIG_INCLUDE_BCM56889_A0 == 1 || defined(BCMDRD_DEVLIST_OVERRIDE) +#ifdef BCMDRD_DEVLIST_INCLUDE_ALL +BCMDRD_DEVLIST_ENTRY(BCM56889, BCM56889_VENDOR_ID, BCM56889_DEVICE_ID, BCM56889_REV_A0, \ + 0, 0, \ + bcm56880_a0, bcm56889_a0, bcm56889_a0, \ + "Trident4", "BCM56880", \ + "12.8 Tb/s Switch Fabric 128x100G/64x200G/32x400G Multilayer Switch", 0, 0) +#endif +#endif + +#if BCMDRD_CONFIG_INCLUDE_BCM56889_B0 == 1 || defined(BCMDRD_DEVLIST_OVERRIDE) +#ifdef BCMDRD_DEVLIST_INCLUDE_ALL +BCMDRD_DEVLIST_ENTRY(BCM56889, BCM56889_VENDOR_ID, BCM56889_DEVICE_ID, BCM56889_REV_B0, \ + 0, 0, \ + bcm56880_a0, bcm56889_a0, bcm56889_b0, \ + "Trident4", "BCM56880", \ + "12.8 Tb/s Switch Fabric 128x100G/64x200G/32x400G Multilayer Switch", 0, 0) +#endif +#endif + +#if BCMDRD_CONFIG_INCLUDE_BCM56990_A0 == 1 || defined(BCMDRD_DEVLIST_OVERRIDE) +BCMDRD_DEVLIST_ENTRY(BCM56990, BCM56990_VENDOR_ID, BCM56990_DEVICE_ID, BCM56990_REV_A0, \ + 0, 0, \ + bcm56990_a0, bcm56990_a0, bcm56990_a0, \ + "Tomahawk4", "BCM56990", \ + "25.6 Tbps Multilayer Switch", 0, 0) +#endif + +#if BCMDRD_CONFIG_INCLUDE_BCM56990_B0 == 1 || defined(BCMDRD_DEVLIST_OVERRIDE) +BCMDRD_DEVLIST_ENTRY(BCM56990, BCM56990_VENDOR_ID, BCM56990_DEVICE_ID, BCM56990_REV_B0, \ + 0, 0, \ + bcm56990_b0, bcm56990_b0, bcm56990_b0, \ + "Tomahawk4", "BCM56990", \ + "25.6 Tbps Multilayer Switch", 0, 0) +#endif + +#if BCMDRD_CONFIG_INCLUDE_BCM56992_B0 == 1 || defined(BCMDRD_DEVLIST_OVERRIDE) +#ifdef BCMDRD_DEVLIST_INCLUDE_ALL +BCMDRD_DEVLIST_ENTRY(BCM56992, BCM56992_VENDOR_ID, BCM56992_DEVICE_ID, BCM56992_REV_B0, \ + 0, 0, \ + bcm56990_b0, bcm56992_b0, bcm56992_b0, \ + "Tomahawk4", "BCM56990", \ + "25.6 Tbps Multilayer Switch", 0, 0) +#endif +#endif + +#if BCMDRD_CONFIG_INCLUDE_BCM56996_A0 == 1 || defined(BCMDRD_DEVLIST_OVERRIDE) +BCMDRD_DEVLIST_ENTRY(BCM56996, BCM56996_VENDOR_ID, BCM56996_DEVICE_ID, BCM56996_REV_A0, \ + 0, 0, \ + bcm56996_a0, bcm56996_a0, bcm56996_a0, \ + "Tomahawk4G", "BCM56996", \ + "25.6 Tbps Multilayer Switch", 0, 0) +#endif + +#if BCMDRD_CONFIG_INCLUDE_BCM56997_A0 == 1 || defined(BCMDRD_DEVLIST_OVERRIDE) +#ifdef BCMDRD_DEVLIST_INCLUDE_ALL +BCMDRD_DEVLIST_ENTRY(BCM56997, BCM56997_VENDOR_ID, BCM56997_DEVICE_ID, BCM56997_REV_A0, \ + 0, 0, \ + bcm56996_a0, bcm56997_a0, bcm56997_a0, \ + "Tomahawk4G", "BCM56996", \ + "12.8 Tbps Multilayer Switch", 0, 0) +#endif +#endif + +/* End BCMDRD_DEVLIST_ENTRY Macros */ + +#ifdef BCMDRD_DEVLIST_INCLUDE_ALL +#undef BCMDRD_DEVLIST_INCLUDE_ALL +#endif +#ifdef BCMDRD_DEVLIST_OVERRIDE +#undef BCMDRD_DEVLIST_OVERRIDE +#endif +#undef BCMDRD_DEVLIST_ENTRY +#endif /* BCMDRD_DEVLIST_ENTRY */ diff --git a/platform/broadcom/saibcm-modules/sdklt/bcmdrd/include/bcmdrd_config.h b/platform/broadcom/saibcm-modules/sdklt/bcmdrd/include/bcmdrd_config.h new file mode 100644 index 00000000000..68e5a089109 --- /dev/null +++ b/platform/broadcom/saibcm-modules/sdklt/bcmdrd/include/bcmdrd_config.h @@ -0,0 +1,166 @@ +/* + * $Copyright: Copyright 2018-2020 Broadcom. All rights reserved. + * The term 'Broadcom' refers to Broadcom Inc. and/or its subsidiaries. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * version 2 as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * A copy of the GNU General Public License version 2 (GPLv2) can + * be found in the LICENSES folder.$ + * + * DO NOT EDIT THIS FILE! + * This file will be auto-generated in the near future. + * + * This config file defines all compilation-time specifications for + * the BCMDRD. + * + * Reasonable defaults are provided for all configuration options + * where appropriate. + * + * You need not edit this file directly to change your configuration, + * nor is modifying this file advised -- so doing will require + * manually merging whenever the BCMDRD is upgraded. + * + * You should provide your own configuration options or overrides + * through a combination of: + * + * 1. The compiler command line, such as -D{OPTION}={VALUE} + * + * 2. Create your own custom configuration file: + * a) Create a file called 'bcmdrd_custom_config.h' + * b) Define all custom settings, using this file as + * the reference + * c) Add -DBCMDRD_INCLUDE_CUSTOM_CONFIG to your + * compilation + * d) Make sure the compilation include path includes + * 'bcmdrd_custom_config.h' + * + */ + +#ifndef BCMDRD_CONFIG_H +#define BCMDRD_CONFIG_H + + +/* + * Include system config file if specified: + */ +#ifdef BCMDRD_INCLUDE_CUSTOM_CONFIG +#include +#endif + + +/* + * OPTIONAL configuration and feature values. + * Defaults are provided for all non-specified values. + */ + +/* Maximum number of chips supported */ +#ifndef BCMDRD_CONFIG_MAX_UNITS +#define BCMDRD_CONFIG_MAX_UNITS 8 +#endif + +/* Maximum number of ports per chip supported */ +#ifndef BCMDRD_CONFIG_MAX_PORTS +#define BCMDRD_CONFIG_MAX_PORTS 576 +#endif + +/* Maximum number of SCHAN polls */ +#ifndef BCMDRD_CONFIG_SCHAN_MAX_POLLS +#define BCMDRD_CONFIG_SCHAN_MAX_POLLS 100000 +#endif + +/* Maximum number of MIIM polls */ +#ifndef BCMDRD_CONFIG_MIIM_MAX_POLLS +#define BCMDRD_CONFIG_MIIM_MAX_POLLS 100000 +#endif + +/* Direct access to memory-mapped registers */ +#ifndef BCMDRD_CONFIG_MEMMAP_DIRECT +#define BCMDRD_CONFIG_MEMMAP_DIRECT 0 +#endif + +/* + * Include chip symbol tables for the debug shell. + * + * No symbolic debugging (register/memory names) will be available + * without this defined. + * + * You should enable at least these symbols if you can afford the + * space. + * + * This define is required to get any symbols at all. + * + * If you only wish to include symbols for a subset of chips in the + * system (probably for code space reasons), you can define the + * following for each chip whose symbols you wish to EXCLUDE: + * + * BCMDRD_CONFIG_EXCLUDE_CHIP_SYMBOLS_ + * + */ +#ifndef BCMDRD_CONFIG_INCLUDE_CHIP_SYMBOLS +#define BCMDRD_CONFIG_INCLUDE_CHIP_SYMBOLS 1 +#endif + +/* + * Include register and memory field information for the debug shell. + * + * This provides encoding, decoding, and displaying individual field + * values for each register and memory. + * + * Requires more code space than just the chip symbols alone. + * + * The per-chip exclusion define + * (BCMDRD_CONFIG_EXCLUDE_FIELD_INFO_) also applies. + */ +#ifndef BCMDRD_CONFIG_INCLUDE_FIELD_INFO +#define BCMDRD_CONFIG_INCLUDE_FIELD_INFO 1 +#endif + +/* + * Include alternative symbol names for registers and memories. + * + * Mainly for internal Broadcom use, so you can safely leave this + * option off. + */ +#ifndef BCMDRD_CONFIG_INCLUDE_ALIAS_NAMES +#define BCMDRD_CONFIG_INCLUDE_ALIAS_NAMES 1 +#endif + +#endif /* BCMDRD_CONFIG_H */ + +#ifdef CONFIG_OPTION +#ifdef BCMDRD_INCLUDE_CUSTOM_CONFIG +CONFIG_OPTION(BCMDRD_INCLUDE_CUSTOM_CONFIG) +#endif +#ifdef BCMDRD_CONFIG_MAX_UNITS +CONFIG_OPTION(BCMDRD_CONFIG_MAX_UNITS) +#endif +#ifdef BCMDRD_CONFIG_MAX_PORTS +CONFIG_OPTION(BCMDRD_CONFIG_MAX_PORTS) +#endif +#ifdef BCMDRD_CONFIG_SCHAN_MAX_POLLS +CONFIG_OPTION(BCMDRD_CONFIG_SCHAN_MAX_POLLS) +#endif +#ifdef BCMDRD_CONFIG_MIIM_MAX_POLLS +CONFIG_OPTION(BCMDRD_CONFIG_MIIM_MAX_POLLS) +#endif +#ifdef BCMDRD_CONFIG_MEMMAP_DIRECT +CONFIG_OPTION(BCMDRD_CONFIG_MEMMAP_DIRECT) +#endif +#ifdef BCMDRD_CONFIG_INCLUDE_CHIP_SYMBOLS +CONFIG_OPTION(BCMDRD_CONFIG_INCLUDE_CHIP_SYMBOLS) +#endif +#ifdef BCMDRD_CONFIG_INCLUDE_FIELD_INFO +CONFIG_OPTION(BCMDRD_CONFIG_INCLUDE_FIELD_INFO) +#endif +#ifdef BCMDRD_CONFIG_INCLUDE_ALIAS_NAMES +CONFIG_OPTION(BCMDRD_CONFIG_INCLUDE_ALIAS_NAMES) +#endif +#endif /* CONFIG_OPTION */ +#include "bcmdrd_config_chips.h" diff --git a/platform/broadcom/saibcm-modules/sdklt/bcmdrd/include/bcmdrd_config_chips.h b/platform/broadcom/saibcm-modules/sdklt/bcmdrd/include/bcmdrd_config_chips.h new file mode 100644 index 00000000000..5b45879c90e --- /dev/null +++ b/platform/broadcom/saibcm-modules/sdklt/bcmdrd/include/bcmdrd_config_chips.h @@ -0,0 +1,545 @@ +/* + * DO NOT EDIT THIS FILE! + * This file is auto-generated. + * Edits to this file will be lost when it is regenerated. + * Tool: INTERNAL/drd/instpkgs.pl + * + * $Copyright: Copyright 2018-2020 Broadcom. All rights reserved. + * The term 'Broadcom' refers to Broadcom Inc. and/or its subsidiaries. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * version 2 as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * A copy of the GNU General Public License version 2 (GPLv2) can + * be found in the LICENSES folder.$ + */ + +/* + * Chip inclusion and exclusion support within the BCMDRD can be + * specified as a combination of the following defines: + * + * (1) #define BCMDRD_CONFIG_INCLUDE_ [1|0] + * -- Include or exclude all revisions of the given device + * Example: #define BCMDRD_CONFIG_INCLUDE_BCM56780 1 + * + * (2) #define BCMDRD_CONFIG_INCLUDE__X [1|0] + * -- Include or exclude all versions of the given revision + * Example: #define BCMDRD_CONFIG_INCLUDE_BCM56780_Ax 0 + * #define BCMDRD_CONFIG_INCLUde_BCM56780_Bx 1 + * + * (3) #define BCMDRD_CONFIG_INCLUDE_ [1|0] + * -- Include or exclude an exact device + * Example: #define BCMDRD_CONFIG_INCLUDE_BCM56780_A0 1 + * #define BCMDRD_CONFIG_INCLUDE_BCM56780_A1 0 + * + * + * The value of BCMDRD_CONFIG_INCLUDE_CHIP_DEFAULT is used for any + * chips which are left unspecified. Set this value to 1 or 0 to + * include or exclude all chips by default. + * + */ + +#ifndef BCMDRD_CONFIG_CHIPS_H +#define BCMDRD_CONFIG_CHIPS_H + +/* This determines whether a chip is included or excluded by default */ +#ifndef BCMDRD_CONFIG_INCLUDE_CHIP_DEFAULT +#define BCMDRD_CONFIG_INCLUDE_CHIP_DEFAULT 1 +#endif + +/* + * Default configuration and dependencies for all chips + */ + +/* + * BCM56780 + */ + +/* Sets the default include state if it was not given */ +#ifndef BCMDRD_CONFIG_INCLUDE_BCM56780 +#define BCMDRD_CONFIG_INCLUDE_BCM56780 BCMDRD_CONFIG_INCLUDE_CHIP_DEFAULT +#endif +/* Resolve revision dependencies */ +#ifndef BCMDRD_CONFIG_INCLUDE_BCM56780_Ax +#define BCMDRD_CONFIG_INCLUDE_BCM56780_Ax BCMDRD_CONFIG_INCLUDE_BCM56780 +#endif +#ifndef BCMDRD_CONFIG_INCLUDE_BCM56780_A0 +#define BCMDRD_CONFIG_INCLUDE_BCM56780_A0 BCMDRD_CONFIG_INCLUDE_BCM56780_Ax +#endif + + +/* + * BCM56782 + */ + +/* Sets the default include state if it was not given */ +#ifndef BCMDRD_CONFIG_INCLUDE_BCM56782 +#define BCMDRD_CONFIG_INCLUDE_BCM56782 BCMDRD_CONFIG_INCLUDE_CHIP_DEFAULT +#endif +/* Resolve revision dependencies */ +#ifndef BCMDRD_CONFIG_INCLUDE_BCM56782_Ax +#define BCMDRD_CONFIG_INCLUDE_BCM56782_Ax BCMDRD_CONFIG_INCLUDE_BCM56782 +#endif +#ifndef BCMDRD_CONFIG_INCLUDE_BCM56782_A0 +#define BCMDRD_CONFIG_INCLUDE_BCM56782_A0 BCMDRD_CONFIG_INCLUDE_BCM56782_Ax +#endif +/* Resolve all interchip dependencies */ +#if BCMDRD_CONFIG_INCLUDE_BCM56782_A0 == 1 +#ifndef BCMDRD_CONFIG_INCLUDE_BCM56780_A0 +#define BCMDRD_CONFIG_INCLUDE_BCM56780_A0 BCMDRD_CONFIG_INCLUDE_CHIP_DEFAULT +#endif +#if BCMDRD_CONFIG_INCLUDE_BCM56780_A0 != 1 +#undef BCMDRD_CONFIG_INCLUDE_BCM56780_A0 +#define BCMDRD_CONFIG_INCLUDE_BCM56780_A0 1 +#define BCMDRD_CONFIG_INCLUDE_BCM56780_A0_IMPLIED 1 +#endif +#endif + + +/* + * BCM56784 + */ + +/* Sets the default include state if it was not given */ +#ifndef BCMDRD_CONFIG_INCLUDE_BCM56784 +#define BCMDRD_CONFIG_INCLUDE_BCM56784 BCMDRD_CONFIG_INCLUDE_CHIP_DEFAULT +#endif +/* Resolve revision dependencies */ +#ifndef BCMDRD_CONFIG_INCLUDE_BCM56784_Ax +#define BCMDRD_CONFIG_INCLUDE_BCM56784_Ax BCMDRD_CONFIG_INCLUDE_BCM56784 +#endif +#ifndef BCMDRD_CONFIG_INCLUDE_BCM56784_A0 +#define BCMDRD_CONFIG_INCLUDE_BCM56784_A0 BCMDRD_CONFIG_INCLUDE_BCM56784_Ax +#endif +/* Resolve all interchip dependencies */ +#if BCMDRD_CONFIG_INCLUDE_BCM56784_A0 == 1 +#ifndef BCMDRD_CONFIG_INCLUDE_BCM56780_A0 +#define BCMDRD_CONFIG_INCLUDE_BCM56780_A0 BCMDRD_CONFIG_INCLUDE_CHIP_DEFAULT +#endif +#if BCMDRD_CONFIG_INCLUDE_BCM56780_A0 != 1 +#undef BCMDRD_CONFIG_INCLUDE_BCM56780_A0 +#define BCMDRD_CONFIG_INCLUDE_BCM56780_A0 1 +#define BCMDRD_CONFIG_INCLUDE_BCM56780_A0_IMPLIED 1 +#endif +#endif + + +/* + * BCM56786 + */ + +/* Sets the default include state if it was not given */ +#ifndef BCMDRD_CONFIG_INCLUDE_BCM56786 +#define BCMDRD_CONFIG_INCLUDE_BCM56786 BCMDRD_CONFIG_INCLUDE_CHIP_DEFAULT +#endif +/* Resolve revision dependencies */ +#ifndef BCMDRD_CONFIG_INCLUDE_BCM56786_Ax +#define BCMDRD_CONFIG_INCLUDE_BCM56786_Ax BCMDRD_CONFIG_INCLUDE_BCM56786 +#endif +#ifndef BCMDRD_CONFIG_INCLUDE_BCM56786_A0 +#define BCMDRD_CONFIG_INCLUDE_BCM56786_A0 BCMDRD_CONFIG_INCLUDE_BCM56786_Ax +#endif +/* Resolve all interchip dependencies */ +#if BCMDRD_CONFIG_INCLUDE_BCM56786_A0 == 1 +#ifndef BCMDRD_CONFIG_INCLUDE_BCM56780_A0 +#define BCMDRD_CONFIG_INCLUDE_BCM56780_A0 BCMDRD_CONFIG_INCLUDE_CHIP_DEFAULT +#endif +#if BCMDRD_CONFIG_INCLUDE_BCM56780_A0 != 1 +#undef BCMDRD_CONFIG_INCLUDE_BCM56780_A0 +#define BCMDRD_CONFIG_INCLUDE_BCM56780_A0 1 +#define BCMDRD_CONFIG_INCLUDE_BCM56780_A0_IMPLIED 1 +#endif +#endif + + +/* + * BCM56788 + */ + +/* Sets the default include state if it was not given */ +#ifndef BCMDRD_CONFIG_INCLUDE_BCM56788 +#define BCMDRD_CONFIG_INCLUDE_BCM56788 BCMDRD_CONFIG_INCLUDE_CHIP_DEFAULT +#endif +/* Resolve revision dependencies */ +#ifndef BCMDRD_CONFIG_INCLUDE_BCM56788_Ax +#define BCMDRD_CONFIG_INCLUDE_BCM56788_Ax BCMDRD_CONFIG_INCLUDE_BCM56788 +#endif +#ifndef BCMDRD_CONFIG_INCLUDE_BCM56788_A0 +#define BCMDRD_CONFIG_INCLUDE_BCM56788_A0 BCMDRD_CONFIG_INCLUDE_BCM56788_Ax +#endif +/* Resolve all interchip dependencies */ +#if BCMDRD_CONFIG_INCLUDE_BCM56788_A0 == 1 +#ifndef BCMDRD_CONFIG_INCLUDE_BCM56780_A0 +#define BCMDRD_CONFIG_INCLUDE_BCM56780_A0 BCMDRD_CONFIG_INCLUDE_CHIP_DEFAULT +#endif +#if BCMDRD_CONFIG_INCLUDE_BCM56780_A0 != 1 +#undef BCMDRD_CONFIG_INCLUDE_BCM56780_A0 +#define BCMDRD_CONFIG_INCLUDE_BCM56780_A0 1 +#define BCMDRD_CONFIG_INCLUDE_BCM56780_A0_IMPLIED 1 +#endif +#endif + + +/* + * BCM56789 + */ + +/* Sets the default include state if it was not given */ +#ifndef BCMDRD_CONFIG_INCLUDE_BCM56789 +#define BCMDRD_CONFIG_INCLUDE_BCM56789 BCMDRD_CONFIG_INCLUDE_CHIP_DEFAULT +#endif +/* Resolve revision dependencies */ +#ifndef BCMDRD_CONFIG_INCLUDE_BCM56789_Ax +#define BCMDRD_CONFIG_INCLUDE_BCM56789_Ax BCMDRD_CONFIG_INCLUDE_BCM56789 +#endif +#ifndef BCMDRD_CONFIG_INCLUDE_BCM56789_A0 +#define BCMDRD_CONFIG_INCLUDE_BCM56789_A0 BCMDRD_CONFIG_INCLUDE_BCM56789_Ax +#endif +/* Resolve all interchip dependencies */ +#if BCMDRD_CONFIG_INCLUDE_BCM56789_A0 == 1 +#ifndef BCMDRD_CONFIG_INCLUDE_BCM56780_A0 +#define BCMDRD_CONFIG_INCLUDE_BCM56780_A0 BCMDRD_CONFIG_INCLUDE_CHIP_DEFAULT +#endif +#if BCMDRD_CONFIG_INCLUDE_BCM56780_A0 != 1 +#undef BCMDRD_CONFIG_INCLUDE_BCM56780_A0 +#define BCMDRD_CONFIG_INCLUDE_BCM56780_A0 1 +#define BCMDRD_CONFIG_INCLUDE_BCM56780_A0_IMPLIED 1 +#endif +#endif + + +/* + * BCM56880 + */ + +/* Sets the default include state if it was not given */ +#ifndef BCMDRD_CONFIG_INCLUDE_BCM56880 +#define BCMDRD_CONFIG_INCLUDE_BCM56880 BCMDRD_CONFIG_INCLUDE_CHIP_DEFAULT +#endif +/* Resolve revision dependencies */ +#ifndef BCMDRD_CONFIG_INCLUDE_BCM56880_Ax +#define BCMDRD_CONFIG_INCLUDE_BCM56880_Ax BCMDRD_CONFIG_INCLUDE_BCM56880 +#endif +#ifndef BCMDRD_CONFIG_INCLUDE_BCM56880_A0 +#define BCMDRD_CONFIG_INCLUDE_BCM56880_A0 BCMDRD_CONFIG_INCLUDE_BCM56880_Ax +#endif +#ifndef BCMDRD_CONFIG_INCLUDE_BCM56880_Bx +#define BCMDRD_CONFIG_INCLUDE_BCM56880_Bx BCMDRD_CONFIG_INCLUDE_BCM56880 +#endif +#ifndef BCMDRD_CONFIG_INCLUDE_BCM56880_B0 +#define BCMDRD_CONFIG_INCLUDE_BCM56880_B0 BCMDRD_CONFIG_INCLUDE_BCM56880_Bx +#endif +/* Resolve all interchip dependencies */ +#if BCMDRD_CONFIG_INCLUDE_BCM56880_B0 == 1 +#ifndef BCMDRD_CONFIG_INCLUDE_BCM56880_A0 +#define BCMDRD_CONFIG_INCLUDE_BCM56880_A0 BCMDRD_CONFIG_INCLUDE_CHIP_DEFAULT +#endif +#if BCMDRD_CONFIG_INCLUDE_BCM56880_A0 != 1 +#undef BCMDRD_CONFIG_INCLUDE_BCM56880_A0 +#define BCMDRD_CONFIG_INCLUDE_BCM56880_A0 1 +#define BCMDRD_CONFIG_INCLUDE_BCM56880_A0_IMPLIED 1 +#endif +#endif + + +/* + * BCM56881 + */ + +/* Sets the default include state if it was not given */ +#ifndef BCMDRD_CONFIG_INCLUDE_BCM56881 +#define BCMDRD_CONFIG_INCLUDE_BCM56881 BCMDRD_CONFIG_INCLUDE_CHIP_DEFAULT +#endif +/* Resolve revision dependencies */ +#ifndef BCMDRD_CONFIG_INCLUDE_BCM56881_Ax +#define BCMDRD_CONFIG_INCLUDE_BCM56881_Ax BCMDRD_CONFIG_INCLUDE_BCM56881 +#endif +#ifndef BCMDRD_CONFIG_INCLUDE_BCM56881_A0 +#define BCMDRD_CONFIG_INCLUDE_BCM56881_A0 BCMDRD_CONFIG_INCLUDE_BCM56881_Ax +#endif +#ifndef BCMDRD_CONFIG_INCLUDE_BCM56881_Bx +#define BCMDRD_CONFIG_INCLUDE_BCM56881_Bx BCMDRD_CONFIG_INCLUDE_BCM56881 +#endif +#ifndef BCMDRD_CONFIG_INCLUDE_BCM56881_B0 +#define BCMDRD_CONFIG_INCLUDE_BCM56881_B0 BCMDRD_CONFIG_INCLUDE_BCM56881_Bx +#endif +/* Resolve all interchip dependencies */ +#if BCMDRD_CONFIG_INCLUDE_BCM56881_A0 == 1 +#ifndef BCMDRD_CONFIG_INCLUDE_BCM56880_A0 +#define BCMDRD_CONFIG_INCLUDE_BCM56880_A0 BCMDRD_CONFIG_INCLUDE_CHIP_DEFAULT +#endif +#if BCMDRD_CONFIG_INCLUDE_BCM56880_A0 != 1 +#undef BCMDRD_CONFIG_INCLUDE_BCM56880_A0 +#define BCMDRD_CONFIG_INCLUDE_BCM56880_A0 1 +#define BCMDRD_CONFIG_INCLUDE_BCM56880_A0_IMPLIED 1 +#endif +#endif +#if BCMDRD_CONFIG_INCLUDE_BCM56881_B0 == 1 +#if BCMDRD_CONFIG_INCLUDE_BCM56880_A0 != 1 +#undef BCMDRD_CONFIG_INCLUDE_BCM56880_A0 +#define BCMDRD_CONFIG_INCLUDE_BCM56880_A0 1 +#define BCMDRD_CONFIG_INCLUDE_BCM56880_A0_IMPLIED 1 +#endif +#endif + + +/* + * BCM56883 + */ + +/* Sets the default include state if it was not given */ +#ifndef BCMDRD_CONFIG_INCLUDE_BCM56883 +#define BCMDRD_CONFIG_INCLUDE_BCM56883 BCMDRD_CONFIG_INCLUDE_CHIP_DEFAULT +#endif +/* Resolve revision dependencies */ +#ifndef BCMDRD_CONFIG_INCLUDE_BCM56883_Ax +#define BCMDRD_CONFIG_INCLUDE_BCM56883_Ax BCMDRD_CONFIG_INCLUDE_BCM56883 +#endif +#ifndef BCMDRD_CONFIG_INCLUDE_BCM56883_A0 +#define BCMDRD_CONFIG_INCLUDE_BCM56883_A0 BCMDRD_CONFIG_INCLUDE_BCM56883_Ax +#endif +#ifndef BCMDRD_CONFIG_INCLUDE_BCM56883_Bx +#define BCMDRD_CONFIG_INCLUDE_BCM56883_Bx BCMDRD_CONFIG_INCLUDE_BCM56883 +#endif +#ifndef BCMDRD_CONFIG_INCLUDE_BCM56883_B0 +#define BCMDRD_CONFIG_INCLUDE_BCM56883_B0 BCMDRD_CONFIG_INCLUDE_BCM56883_Bx +#endif +/* Resolve all interchip dependencies */ +#if BCMDRD_CONFIG_INCLUDE_BCM56883_A0 == 1 +#ifndef BCMDRD_CONFIG_INCLUDE_BCM56880_A0 +#define BCMDRD_CONFIG_INCLUDE_BCM56880_A0 BCMDRD_CONFIG_INCLUDE_CHIP_DEFAULT +#endif +#if BCMDRD_CONFIG_INCLUDE_BCM56880_A0 != 1 +#undef BCMDRD_CONFIG_INCLUDE_BCM56880_A0 +#define BCMDRD_CONFIG_INCLUDE_BCM56880_A0 1 +#define BCMDRD_CONFIG_INCLUDE_BCM56880_A0_IMPLIED 1 +#endif +#endif +#if BCMDRD_CONFIG_INCLUDE_BCM56883_B0 == 1 +#if BCMDRD_CONFIG_INCLUDE_BCM56880_A0 != 1 +#undef BCMDRD_CONFIG_INCLUDE_BCM56880_A0 +#define BCMDRD_CONFIG_INCLUDE_BCM56880_A0 1 +#define BCMDRD_CONFIG_INCLUDE_BCM56880_A0_IMPLIED 1 +#endif +#endif + + +/* + * BCM56889 + */ + +/* Sets the default include state if it was not given */ +#ifndef BCMDRD_CONFIG_INCLUDE_BCM56889 +#define BCMDRD_CONFIG_INCLUDE_BCM56889 BCMDRD_CONFIG_INCLUDE_CHIP_DEFAULT +#endif +/* Resolve revision dependencies */ +#ifndef BCMDRD_CONFIG_INCLUDE_BCM56889_Ax +#define BCMDRD_CONFIG_INCLUDE_BCM56889_Ax BCMDRD_CONFIG_INCLUDE_BCM56889 +#endif +#ifndef BCMDRD_CONFIG_INCLUDE_BCM56889_A0 +#define BCMDRD_CONFIG_INCLUDE_BCM56889_A0 BCMDRD_CONFIG_INCLUDE_BCM56889_Ax +#endif +#ifndef BCMDRD_CONFIG_INCLUDE_BCM56889_Bx +#define BCMDRD_CONFIG_INCLUDE_BCM56889_Bx BCMDRD_CONFIG_INCLUDE_BCM56889 +#endif +#ifndef BCMDRD_CONFIG_INCLUDE_BCM56889_B0 +#define BCMDRD_CONFIG_INCLUDE_BCM56889_B0 BCMDRD_CONFIG_INCLUDE_BCM56889_Bx +#endif +/* Resolve all interchip dependencies */ +#if BCMDRD_CONFIG_INCLUDE_BCM56889_A0 == 1 +#ifndef BCMDRD_CONFIG_INCLUDE_BCM56880_A0 +#define BCMDRD_CONFIG_INCLUDE_BCM56880_A0 BCMDRD_CONFIG_INCLUDE_CHIP_DEFAULT +#endif +#if BCMDRD_CONFIG_INCLUDE_BCM56880_A0 != 1 +#undef BCMDRD_CONFIG_INCLUDE_BCM56880_A0 +#define BCMDRD_CONFIG_INCLUDE_BCM56880_A0 1 +#define BCMDRD_CONFIG_INCLUDE_BCM56880_A0_IMPLIED 1 +#endif +#endif +#if BCMDRD_CONFIG_INCLUDE_BCM56889_B0 == 1 +#if BCMDRD_CONFIG_INCLUDE_BCM56880_A0 != 1 +#undef BCMDRD_CONFIG_INCLUDE_BCM56880_A0 +#define BCMDRD_CONFIG_INCLUDE_BCM56880_A0 1 +#define BCMDRD_CONFIG_INCLUDE_BCM56880_A0_IMPLIED 1 +#endif +#endif + + +/* + * BCM56990 + */ + +/* Sets the default include state if it was not given */ +#ifndef BCMDRD_CONFIG_INCLUDE_BCM56990 +#define BCMDRD_CONFIG_INCLUDE_BCM56990 BCMDRD_CONFIG_INCLUDE_CHIP_DEFAULT +#endif +/* Resolve revision dependencies */ +#ifndef BCMDRD_CONFIG_INCLUDE_BCM56990_Ax +#define BCMDRD_CONFIG_INCLUDE_BCM56990_Ax BCMDRD_CONFIG_INCLUDE_BCM56990 +#endif +#ifndef BCMDRD_CONFIG_INCLUDE_BCM56990_A0 +#define BCMDRD_CONFIG_INCLUDE_BCM56990_A0 BCMDRD_CONFIG_INCLUDE_BCM56990_Ax +#endif +#ifndef BCMDRD_CONFIG_INCLUDE_BCM56990_Bx +#define BCMDRD_CONFIG_INCLUDE_BCM56990_Bx BCMDRD_CONFIG_INCLUDE_BCM56990 +#endif +#ifndef BCMDRD_CONFIG_INCLUDE_BCM56990_B0 +#define BCMDRD_CONFIG_INCLUDE_BCM56990_B0 BCMDRD_CONFIG_INCLUDE_BCM56990_Bx +#endif + + +/* + * BCM56992 + */ + +/* Sets the default include state if it was not given */ +#ifndef BCMDRD_CONFIG_INCLUDE_BCM56992 +#define BCMDRD_CONFIG_INCLUDE_BCM56992 BCMDRD_CONFIG_INCLUDE_CHIP_DEFAULT +#endif +/* Resolve revision dependencies */ +#ifndef BCMDRD_CONFIG_INCLUDE_BCM56992_Bx +#define BCMDRD_CONFIG_INCLUDE_BCM56992_Bx BCMDRD_CONFIG_INCLUDE_BCM56992 +#endif +#ifndef BCMDRD_CONFIG_INCLUDE_BCM56992_B0 +#define BCMDRD_CONFIG_INCLUDE_BCM56992_B0 BCMDRD_CONFIG_INCLUDE_BCM56992_Bx +#endif +/* Resolve all interchip dependencies */ +#if BCMDRD_CONFIG_INCLUDE_BCM56992_B0 == 1 +#ifndef BCMDRD_CONFIG_INCLUDE_BCM56990_B0 +#define BCMDRD_CONFIG_INCLUDE_BCM56990_B0 BCMDRD_CONFIG_INCLUDE_CHIP_DEFAULT +#endif +#if BCMDRD_CONFIG_INCLUDE_BCM56990_B0 != 1 +#undef BCMDRD_CONFIG_INCLUDE_BCM56990_B0 +#define BCMDRD_CONFIG_INCLUDE_BCM56990_B0 1 +#define BCMDRD_CONFIG_INCLUDE_BCM56990_B0_IMPLIED 1 +#endif +#endif + + +/* + * BCM56996 + */ + +/* Sets the default include state if it was not given */ +#ifndef BCMDRD_CONFIG_INCLUDE_BCM56996 +#define BCMDRD_CONFIG_INCLUDE_BCM56996 BCMDRD_CONFIG_INCLUDE_CHIP_DEFAULT +#endif +/* Resolve revision dependencies */ +#ifndef BCMDRD_CONFIG_INCLUDE_BCM56996_Ax +#define BCMDRD_CONFIG_INCLUDE_BCM56996_Ax BCMDRD_CONFIG_INCLUDE_BCM56996 +#endif +#ifndef BCMDRD_CONFIG_INCLUDE_BCM56996_A0 +#define BCMDRD_CONFIG_INCLUDE_BCM56996_A0 BCMDRD_CONFIG_INCLUDE_BCM56996_Ax +#endif + + +/* + * BCM56997 + */ + +/* Sets the default include state if it was not given */ +#ifndef BCMDRD_CONFIG_INCLUDE_BCM56997 +#define BCMDRD_CONFIG_INCLUDE_BCM56997 BCMDRD_CONFIG_INCLUDE_CHIP_DEFAULT +#endif +/* Resolve revision dependencies */ +#ifndef BCMDRD_CONFIG_INCLUDE_BCM56997_Ax +#define BCMDRD_CONFIG_INCLUDE_BCM56997_Ax BCMDRD_CONFIG_INCLUDE_BCM56997 +#endif +#ifndef BCMDRD_CONFIG_INCLUDE_BCM56997_A0 +#define BCMDRD_CONFIG_INCLUDE_BCM56997_A0 BCMDRD_CONFIG_INCLUDE_BCM56997_Ax +#endif +/* Resolve all interchip dependencies */ +#if BCMDRD_CONFIG_INCLUDE_BCM56997_A0 == 1 +#ifndef BCMDRD_CONFIG_INCLUDE_BCM56996_A0 +#define BCMDRD_CONFIG_INCLUDE_BCM56996_A0 BCMDRD_CONFIG_INCLUDE_CHIP_DEFAULT +#endif +#if BCMDRD_CONFIG_INCLUDE_BCM56996_A0 != 1 +#undef BCMDRD_CONFIG_INCLUDE_BCM56996_A0 +#define BCMDRD_CONFIG_INCLUDE_BCM56996_A0 1 +#define BCMDRD_CONFIG_INCLUDE_BCM56996_A0_IMPLIED 1 +#endif +#endif + + +#endif /* BCMDRD_CONFIG_CHIPS_H */ + +/* + * CONFIG_OPTION Macros. Can be used to determine the build configuration. + */ + +#ifdef CONFIG_OPTION +CONFIG_OPTION(BCMDRD_CONFIG_INCLUDE_BCM56780) +CONFIG_OPTION(BCMDRD_CONFIG_INCLUDE_BCM56780_Ax) +CONFIG_OPTION(BCMDRD_CONFIG_INCLUDE_BCM56780_A0) +#ifdef BCMDRD_CONFIG_INCLUDE_BCM56780_A0_IMPLIED +CONFIG_OPTION(BCMDRD_CONFIG_INCLUDE_BCM56780_A0_IMPLIED) +#endif +CONFIG_OPTION(BCMDRD_CONFIG_INCLUDE_BCM56782) +CONFIG_OPTION(BCMDRD_CONFIG_INCLUDE_BCM56782_Ax) +CONFIG_OPTION(BCMDRD_CONFIG_INCLUDE_BCM56782_A0) +CONFIG_OPTION(BCMDRD_CONFIG_INCLUDE_BCM56784) +CONFIG_OPTION(BCMDRD_CONFIG_INCLUDE_BCM56784_Ax) +CONFIG_OPTION(BCMDRD_CONFIG_INCLUDE_BCM56784_A0) +CONFIG_OPTION(BCMDRD_CONFIG_INCLUDE_BCM56786) +CONFIG_OPTION(BCMDRD_CONFIG_INCLUDE_BCM56786_Ax) +CONFIG_OPTION(BCMDRD_CONFIG_INCLUDE_BCM56786_A0) +CONFIG_OPTION(BCMDRD_CONFIG_INCLUDE_BCM56788) +CONFIG_OPTION(BCMDRD_CONFIG_INCLUDE_BCM56788_Ax) +CONFIG_OPTION(BCMDRD_CONFIG_INCLUDE_BCM56788_A0) +CONFIG_OPTION(BCMDRD_CONFIG_INCLUDE_BCM56789) +CONFIG_OPTION(BCMDRD_CONFIG_INCLUDE_BCM56789_Ax) +CONFIG_OPTION(BCMDRD_CONFIG_INCLUDE_BCM56789_A0) +CONFIG_OPTION(BCMDRD_CONFIG_INCLUDE_BCM56880) +CONFIG_OPTION(BCMDRD_CONFIG_INCLUDE_BCM56880_Ax) +CONFIG_OPTION(BCMDRD_CONFIG_INCLUDE_BCM56880_A0) +CONFIG_OPTION(BCMDRD_CONFIG_INCLUDE_BCM56880_Bx) +CONFIG_OPTION(BCMDRD_CONFIG_INCLUDE_BCM56880_B0) +#ifdef BCMDRD_CONFIG_INCLUDE_BCM56880_A0_IMPLIED +CONFIG_OPTION(BCMDRD_CONFIG_INCLUDE_BCM56880_A0_IMPLIED) +#endif +CONFIG_OPTION(BCMDRD_CONFIG_INCLUDE_BCM56881) +CONFIG_OPTION(BCMDRD_CONFIG_INCLUDE_BCM56881_Ax) +CONFIG_OPTION(BCMDRD_CONFIG_INCLUDE_BCM56881_A0) +CONFIG_OPTION(BCMDRD_CONFIG_INCLUDE_BCM56881_Bx) +CONFIG_OPTION(BCMDRD_CONFIG_INCLUDE_BCM56881_B0) +CONFIG_OPTION(BCMDRD_CONFIG_INCLUDE_BCM56883) +CONFIG_OPTION(BCMDRD_CONFIG_INCLUDE_BCM56883_Ax) +CONFIG_OPTION(BCMDRD_CONFIG_INCLUDE_BCM56883_A0) +CONFIG_OPTION(BCMDRD_CONFIG_INCLUDE_BCM56883_Bx) +CONFIG_OPTION(BCMDRD_CONFIG_INCLUDE_BCM56883_B0) +CONFIG_OPTION(BCMDRD_CONFIG_INCLUDE_BCM56889) +CONFIG_OPTION(BCMDRD_CONFIG_INCLUDE_BCM56889_Ax) +CONFIG_OPTION(BCMDRD_CONFIG_INCLUDE_BCM56889_A0) +CONFIG_OPTION(BCMDRD_CONFIG_INCLUDE_BCM56889_Bx) +CONFIG_OPTION(BCMDRD_CONFIG_INCLUDE_BCM56889_B0) +CONFIG_OPTION(BCMDRD_CONFIG_INCLUDE_BCM56990) +CONFIG_OPTION(BCMDRD_CONFIG_INCLUDE_BCM56990_Ax) +CONFIG_OPTION(BCMDRD_CONFIG_INCLUDE_BCM56990_A0) +CONFIG_OPTION(BCMDRD_CONFIG_INCLUDE_BCM56990_Bx) +CONFIG_OPTION(BCMDRD_CONFIG_INCLUDE_BCM56990_B0) +#ifdef BCMDRD_CONFIG_INCLUDE_BCM56990_A0_IMPLIED +CONFIG_OPTION(BCMDRD_CONFIG_INCLUDE_BCM56990_A0_IMPLIED) +#endif +#ifdef BCMDRD_CONFIG_INCLUDE_BCM56990_B0_IMPLIED +CONFIG_OPTION(BCMDRD_CONFIG_INCLUDE_BCM56990_B0_IMPLIED) +#endif +CONFIG_OPTION(BCMDRD_CONFIG_INCLUDE_BCM56992) +CONFIG_OPTION(BCMDRD_CONFIG_INCLUDE_BCM56992_Bx) +CONFIG_OPTION(BCMDRD_CONFIG_INCLUDE_BCM56992_B0) +CONFIG_OPTION(BCMDRD_CONFIG_INCLUDE_BCM56996) +CONFIG_OPTION(BCMDRD_CONFIG_INCLUDE_BCM56996_Ax) +CONFIG_OPTION(BCMDRD_CONFIG_INCLUDE_BCM56996_A0) +#ifdef BCMDRD_CONFIG_INCLUDE_BCM56996_A0_IMPLIED +CONFIG_OPTION(BCMDRD_CONFIG_INCLUDE_BCM56996_A0_IMPLIED) +#endif +CONFIG_OPTION(BCMDRD_CONFIG_INCLUDE_BCM56997) +CONFIG_OPTION(BCMDRD_CONFIG_INCLUDE_BCM56997_Ax) +CONFIG_OPTION(BCMDRD_CONFIG_INCLUDE_BCM56997_A0) +#undef CONFIG_OPTION +#endif /* #ifdef CONFIG_OPTION */ diff --git a/platform/broadcom/saibcm-modules/sdklt/linux/bde/Kbuild b/platform/broadcom/saibcm-modules/sdklt/linux/bde/Kbuild new file mode 100644 index 00000000000..76581c02eed --- /dev/null +++ b/platform/broadcom/saibcm-modules/sdklt/linux/bde/Kbuild @@ -0,0 +1,39 @@ +# -*- Kbuild -*- +# +# Linux kernel BDE module. +# +# $Copyright: Copyright 2018-2020 Broadcom. All rights reserved. +# The term 'Broadcom' refers to Broadcom Inc. and/or its subsidiaries. +# +# This program is free software; you can redistribute it and/or +# modify it under the terms of the GNU General Public License +# version 2 as published by the Free Software Foundation. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# A copy of the GNU General Public License version 2 (GPLv2) can +# be found in the LICENSES folder.$ +# + +obj-m := linux_ngbde.o + +ccflags-y := $(LKM_CFLAGS) \ + -I$(SDK)/linux/include \ + -I$(SDK)/linux/bde \ + -I$(SDK)/bcmdrd/include + +linux_ngbde-y := ngbde_main.o \ + ngbde_kapi.o \ + ngbde_ioctl.o \ + ngbde_procfs.o \ + ngbde_pio.o \ + ngbde_iio.o \ + ngbde_dma.o \ + ngbde_intr.o \ + ngbde_pgmem.o \ + ngbde_pci_probe.o \ + ngbde_iproc_probe.o \ + ngbde_swdev.o diff --git a/platform/broadcom/saibcm-modules/sdklt/linux/bde/Makefile b/platform/broadcom/saibcm-modules/sdklt/linux/bde/Makefile new file mode 100644 index 00000000000..590f4132306 --- /dev/null +++ b/platform/broadcom/saibcm-modules/sdklt/linux/bde/Makefile @@ -0,0 +1,33 @@ +# -*- Makefile -*- +# +# Linux kernel BDE module. +# +# $Copyright: Copyright 2018-2020 Broadcom. All rights reserved. +# The term 'Broadcom' refers to Broadcom Inc. and/or its subsidiaries. +# +# This program is free software; you can redistribute it and/or +# modify it under the terms of the GNU General Public License +# version 2 as published by the Free Software Foundation. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# A copy of the GNU General Public License version 2 (GPLv2) can +# be found in the LICENSES folder.$ +# + +include Kbuild + +ifeq ($(KERNELRELEASE),) + +MOD_NAME = linux_ngbde + +include $(SDK)/make/lkm.mk + +endif + +.PHONY: distclean + +distclean: diff --git a/platform/broadcom/saibcm-modules/sdklt/linux/bde/ngbde.h b/platform/broadcom/saibcm-modules/sdklt/linux/bde/ngbde.h new file mode 100644 index 00000000000..56e925f7098 --- /dev/null +++ b/platform/broadcom/saibcm-modules/sdklt/linux/bde/ngbde.h @@ -0,0 +1,836 @@ +/*! \file ngbde.h + * + * Shared definitions and APIs for NGBDE kernel module. + * + */ +/* + * $Copyright: Copyright 2018-2020 Broadcom. All rights reserved. + * The term 'Broadcom' refers to Broadcom Inc. and/or its subsidiaries. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * version 2 as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * A copy of the GNU General Public License version 2 (GPLv2) can + * be found in the LICENSES folder.$ + */ + +#ifndef NGBDE_H +#define NGBDE_H + +#include +#include + +/*! Module name. */ +#define MOD_NAME "linux_ngbde" + +/*! Major number for associated charcter device file. */ +#define MOD_MAJOR 120 + +/*! Read memory-mapped device register without byte-swap. */ +#define NGBDE_IOREAD32(_a) __raw_readl(_a) + +/*! Write memory-mapped device register without byte-swap. */ +#define NGBDE_IOWRITE32(_v, _a) __raw_writel(_v, _a) + +/*! Maximum number of I/O windows supported per device. */ +#define NGBDE_NUM_IOWIN_MAX 3 + +/*! Maximum number of DMA memory pools supported per device. */ +#define NGBDE_NUM_DMAPOOL_MAX 2 + +/*! Maximum number of IRQ status registers per interrupt source. */ +#define NGBDE_NUM_IRQ_REGS_MAX 16 + +/*! Maximum number of IRQ lines (MSI vectors) per device. */ +#define NGBDE_NUM_IRQS_MAX 1 + +/*! + * Maximum number of interrupt controller registers which may be + * written from both a user mode driver and a kernel mode driver. + * + * This feature is used when the kernel mode driver owns a subset of + * bits within a register, which is also used by the user mode driver. + * + * Both drivers must access such registers through a lock-protected + * access function. + */ +#define NGBDE_NUM_INTR_SHR_REGS_MAX 1 + +/*! I/O memory window definition. */ +struct ngbde_memwin_s { + + /*! Physical address of I/O window. */ + phys_addr_t addr; + + /*! Size of I/O window (in bytes). */ + phys_addr_t size; +}; + +/*! + * \brief Shared register value. + * + * This structure contains the current value of a register where user + * mode and kernel mode owns different bits within the same + * register. In this case access must be carefully controlled to avoid + * that one context overwrites the bits owned by the other context. + * + * The structure also contains the offset of the shared register in + * order to identify the register (in case there is more than one + * shared register). + */ +typedef struct ngbde_shr_reg_s { + + /*! Offset of the shared register. */ + uint32_t reg_offs; + + /*! Current value of the shared register. */ + uint32_t cur_val; + +} ngbde_shr_reg_t; + +/*! + * \brief Shared interrupt mask register control. + * + * This defines which bits of an interrupt mask register are owned by + * user mode context, and which are owned by kernel context. + * + * The structure contains the corresponding interrupt status register + * in order to allow identification of the interrupt mask register + * irrespective of the host CPU being used. + * + * For example, if the host CPU is connected via PCI, then we use one + * mask register, but if the host CPU is an embedded ARM CPU, then we + * use a different mask register (for the same interrupt status + * register). By using the status register to identify the shared mask + * register, the kernel mode driver does not need to know which host + * CPU it is running off. + */ +typedef struct ngbde_irq_reg_s { + + /*! Interrupt status register corresponding to the mask register. */ + uint32_t status_reg; + + /*! Shared interrupt mask register. */ + uint32_t mask_reg; + + /*! Mask identifying the register bits owned by the kernel mode driver. */ + uint32_t kmask; + +} ngbde_irq_reg_t; + +/*! + * \name Interrupt ACK register access flags. + * \anchor NGBDE_INTR_ACK_F_xxx + */ + +/*! \{ */ + +/*! ACK registers resides in PCI bridge I/O window. */ +#define NGBDE_INTR_ACK_F_PAXB (1 << 0) + +/*! \} */ + +/*! + * \brief Interrupt ACK register control. + * + * The structure contains the corresponding register offset + * and value in order to acknowledge interrupt in kernel driver. + * + * For example, if the host CPU is connected via PCI, then we use one + * ACK register, but if the host CPU is an embedded ARM CPU, then we + * use a different ACK register. + */ +typedef struct ngbde_intr_ack_reg_s { + + /*! Ack register offset. */ + uint32_t ack_reg; + + /*! Ack value. */ + uint32_t ack_val; + + /*! Flags to indicate ack_reg resides in PCI bridge window. */ + uint32_t flags; + +} ngbde_intr_ack_reg_t; + +/*! + * \brief BDE interrupt handler. + * + * The BDE will use a function of this type to register an interrupt + * handler with the Linux kernel. + * + * \param [in] data Interrupt handler context. + * + * \retval 0 Interrupt not recognized. + * \retval 1 Interrupt recognized and handled. + */ +typedef int (*ngbde_isr_f)(void *data); + +/*! + * \brief Kernel interrupt control. + * + * This structure controls the sharing of interrupt processing between + * a user mode thread and a kernel mode interrupt handler. + */ +typedef struct ngbde_intr_ctrl_s { + + /*! Handle for device I/O (for writing interrupt registers). */ + uint8_t *iomem; + + /*! Kernel device number (similar to user mode unit number). */ + int kdev; + + /*! Indicates that our interrupt handler is connected to the kernel. */ + int irq_active; + + /*! Interrupt number (IRQ# or MSI vector). */ + int irq_vect; + + /*! Number of interrupt status/mask register pairs. */ + int num_regs; + + /*! Interrupt status/mask register pairs for this device. */ + ngbde_irq_reg_t regs[NGBDE_NUM_IRQ_REGS_MAX]; + + /*! Interrupt ACK register/value for this device. */ + ngbde_intr_ack_reg_t intr_ack; + + /*! Wait queue for user mode interrupt thread. */ + wait_queue_head_t user_thread_wq; + + /*! Flag to wake up user mode interrupt thread. */ + atomic_t run_user_thread; + + /*! Primary interrupt handler. */ + ngbde_isr_f isr_func; + + /*! Context for primary interrupt handler. */ + void *isr_data; + +} ngbde_intr_ctrl_t; + +/*! Convenience macro for 1 kilobyte. */ +#define ONE_KB 1024 + +/*! Convenience macro for 1 megabyte. */ +#define ONE_MB (1024*1024) + +/*! + * \name DMA allocation types. + * \anchor NGBDE_DMA_T_xxx + */ + +/*! \{ */ + +/*! + * Do not allocate any DMA memory. + */ +#define NGBDE_DMA_T_NONE 0 + +/*! + * Try different allocation methods until DMA memory is successfully + * allocated. + */ +#define NGBDE_DMA_T_AUTO 1 + +/*! Use kernel DMA API (dma_alloc_coherent). */ +#define NGBDE_DMA_T_KAPI 2 + +/*! Use page allocator and map to physical address manually. */ +#define NGBDE_DMA_T_PGMEM 3 + +/*! \} */ + +/*! DMA memory allocation control structure. */ +typedef struct ngbde_dmactrl_s { + + /*! Requested size of DMA memory block (in bytes). */ + size_t size; + + /*! Kernel flags for memory allocation. */ + gfp_t flags; + + /*! Preferred DMA memory type (NGBDE_DMA_T_xxx). */ + int pref_type; + + /*! Kernel device for DMA memory management. */ + struct device *dev; + +} ngbde_dmactrl_t; + +/*! DMA memory descriptor. */ +typedef struct ngbde_dmamem_s { + + /*! Logical address of DMA memory block. */ + void *vaddr; + + /*! Physical address of DMA memory block. */ + dma_addr_t paddr; + + /*! Bus address of DMA memory block. */ + dma_addr_t baddr; + + /*! Actual size of DMA memory block (in bytes). */ + size_t size; + + /*! Actual DMA memory type (NGBDE_DMA_T_xxx). */ + int type; + + /*! Kernel device for DMA memory management. */ + struct device *dev; + +} ngbde_dmamem_t; + +/*! DMA memory pool. */ +typedef struct ngbde_dmapool_s { + + /*! DMA control parameters. */ + struct ngbde_dmactrl_s dmactrl; + + /*! DMA memory resources. */ + struct ngbde_dmamem_s dmamem; + +} ngbde_dmapool_t; + +/*! Switch device descriptor. */ +struct ngbde_dev_s { + + /*! Vendor ID (typically PCI vendor ID). */ + uint16_t vendor_id; + + /*! Device ID (typically PCI device ID). */ + uint16_t device_id; + + /*! Device revision (typically PCI revision). */ + uint16_t revision; + + /*! Additional device identification when primary ID is not unique. */ + uint16_t model; + + /*! Bus number (typically PCI bus number). */ + int bus_no; + + /*! Slot number (typically PCI slot number). */ + int slot_no; + + /*! Interrupt line associated with this device. */ + int irq_line; + + /*! Use MSI interrupts with this device. */ + int use_msi; + + /*! Non-zero if device was removed. */ + int inactive; + + /*! Physical I/O window for kernel driver device access. */ + struct ngbde_memwin_s pio_win; + + /*! Memory mapped I/O window for kernel driver device access. */ + uint8_t *pio_mem; + + /*! Physical I/O window for interrupt controller access. */ + struct ngbde_memwin_s iio_win; + + /*! Memory mapped I/O window for interrupt controller access. */ + uint8_t *iio_mem; + + /*! Physical I/O window for device PCI bridge access. */ + struct ngbde_memwin_s paxb_win; + + /*! Memory mapped I/O window for device PCI bridge access. */ + uint8_t *paxb_mem; + + /*! Current value of shared register (typically an IRQ mask register). */ + struct ngbde_shr_reg_s intr_shr_reg[NGBDE_NUM_INTR_SHR_REGS_MAX]; + + /*! Lock for shared register synchronization. */ + spinlock_t lock; + + /*! Interrupt control information. */ + struct ngbde_intr_ctrl_s intr_ctrl[NGBDE_NUM_IRQS_MAX]; + + /*! Linux PCI handle. */ + struct pci_dev *pci_dev; + + /*! Kernel device for DMA memory management. */ + struct device *dma_dev; + + /*! Physical device I/O. */ + struct ngbde_memwin_s iowin[NGBDE_NUM_IOWIN_MAX]; + + /*! DMA memory pools. */ + struct ngbde_dmapool_s dmapool[NGBDE_NUM_DMAPOOL_MAX]; +}; + +/*! + * \brief Linux IOCTL handler. + * + * This function handles communication between user mode and kernel + * mode. + * + * \param [in] file Device file handle. + * \param [in] cmd IOCTL command. + * \param [in] arg IOCTL command argument. + * + * \retval 0 No errors + */ +extern long +ngbde_ioctl(struct file *file, unsigned int cmd, unsigned long arg); + +/*! + * \brief Initialize procfs for BDE driver. + * + * Create procfs read interface for dumping probe information. + * + * \return 0 if no errors, otherwise -1. + */ +extern int +ngbde_procfs_init(void); + +/*! + * \brief Clean up procfs for BDE driver. + * + * Clean up resources allocated by \ref ngbde_procfs_init. + * + * \return 0 if no errors, otherwise -1. + */ +extern int +ngbde_procfs_cleanup(void); + +/*! + * \brief Allocate DMA memory pools for all probed devices. + * + * \return 0 if no errors, otherwise -1. + */ +extern int +ngbde_dma_init(void); + +/*! + * \brief Free DMA memory pools for all probed devices. + * + * \return Nothing. + */ +extern void +ngbde_dma_cleanup(void); + +/*! + * \brief Connect to hardware interrupt handler. + * + * \param [in] kdev Device number. + * \param [in] irq_num Interrupt number (MSI vector). + * + * \retval 0 No errors + * \retval -1 Something went wrong. + */ +extern int +ngbde_intr_connect(int kdev, unsigned int irq_num); + +/*! + * \brief Disconnect from hardware interrupt handler. + * + * \param [in] kdev Device number. + * \param [in] irq_num Interrupt number (MSI vector). + * + * \retval 0 No errors + * \retval -1 Something went wrong. + */ +extern int +ngbde_intr_disconnect(int kdev, unsigned int irq_num); + +/*! + * \brief Disconnect from all hardware interrupt handlers. + */ +void +ngbde_intr_cleanup(void); + +/*! + * \brief Wait for hardware interrupt. + * + * A user mode thread will call this function and sleep until a + * hardware interrupt occurs. + * + * \param [in] kdev Device number. + * \param [in] irq_num Interrupt number (MSI vector). + * + * \retval 0 No errors + * \retval -1 Something went wrong. + */ +extern int +ngbde_intr_wait(int kdev, unsigned int irq_num); + +/*! + * \brief Wake up sleeping interrupt thread. + * + * Wake up interrupt thread even if no interrupt has occurred. + * + * Intended for graceful shut-down procedure. + * + * \param [in] kdev Device number. + * \param [in] irq_num Interrupt number (MSI vector). + * + * \retval 0 No errors + * \retval -1 Something went wrong. + */ +extern int +ngbde_intr_stop(int kdev, unsigned int irq_num); + +/*! + * \brief Clear list of interrupt status/mask registers. + * + * This function is typically called before new interrupt register + * information is added. + * + * \param [in] kdev Device number. + * \param [in] irq_num Interrupt number (MSI vector). + * + * \retval 0 No errors + * \retval -1 Something went wrong. + */ +extern int +ngbde_intr_regs_clr(int kdev, unsigned int irq_num); + +/*! + * \brief Add interrupt status/mask register to monitor. + * + * This function adds a new interrupt status/mask register set to the + * list of registers monitored by the user-mode interrupt handler. + * + * The register list is used to determine whether a user-mode + * interrupt has occurred. + * + * See also \ref ngbde_intr_regs_clr. + * + * \param [in] kdev Device number. + * \param [in] irq_num Interrupt number (MSI vector). + * \param [in] ireg Interrupt status/mask register information. + * + * \retval 0 No errors + * \retval -1 Something went wrong. + */ +extern int +ngbde_intr_reg_add(int kdev, unsigned int irq_num, + struct ngbde_irq_reg_s *ireg); + +/*! + * \brief Add interrupt ack register to monitor. + * + * This function adds a interrupt register and mask value + * to acknowledge corresponding irq_num. + * + * \param [in] kdev Device number. + * \param [in] irq_num Interrupt number (MSI vector). + * \param [in] ackreg Interrupt ack register information. + * + * \retval 0 No errors + * \retval -1 Something went wrong. + */ +extern int +ngbde_intr_ack_reg_add(int kdev, unsigned int irq_num, + struct ngbde_intr_ack_reg_s *ackreg); + +/*! + * \brief Write shared interrupt mask register. + * + * This function is used by an interrupt handler when a shared + * interrupt mask register needs to be updated. + * + * Since the register is shared between multiple interrupt handlers, + * access must be protected by a lock. + * + * The register information provided via \ref ngbde_intr_reg_add is + * used to detemine which bits of the mask register belong to the user + * mode driver. + * + * Note that the mask register to access is referenced by the + * corresponding status register. This is because the mask register + * may be different depending on the host CPU interface being used + * (e.g. PCI vs. AXI). On the other hand, the status register is the + * same irrespective of the host CPU interface. + * + * \param [in] kdev Device number. + * \param [in] irq_num Interrupt number (MSI vector). + * \param [in] kapi Must be set to 1 if called from kernel API. + * \param [in] status_reg Corresponding interrupt status register offset. + * \param [in] mask_val New value to write to mask register. + * + * \retval 0 No errors + * \retval -1 Something went wrong. + */ +extern int +ngbde_intr_mask_write(int kdev, unsigned int irq_num, int kapi, + uint32_t status_reg, uint32_t mask_val); + +/*! + * \brief Probe for PCI-attached Broadcom switch devices. + * + * \return 0 if no errors, otherwise -1. + */ +extern int +ngbde_pci_probe(void); + +/*! + * \brief Clean up resources for PCI-attached Broadcom switch devices. + * + * \return 0 if no errors, otherwise -1. + */ +extern int +ngbde_pci_cleanup(void); + +/*! + * \brief Add new switch device to BDE database. + * + * Add device information for probed or fixed switch device. + * + * \param [in] nd Switch device information. + * + * \return 0 if no errors, otherwise -1. + */ +extern int +ngbde_swdev_add(struct ngbde_dev_s *nd); + +/*! + * \brief Get device information for a BDE switch device. + * + * \param [in] kdev Switch device number. + * + * \return Pointer to switch device structure or NULL on error. + */ +struct ngbde_dev_s * +ngbde_swdev_get(int kdev); + +/*! + * \brief Get list of all probed switch devices. + * + * Return a pointer to the array of registered switch devices. + * + * \param [out] nd Pointer to array of switch devices. + * \param [in] num_nd number of valid entries in switch device array. + * + * \retval 0 No errors + */ +extern int +ngbde_swdev_get_all(struct ngbde_dev_s **nd, unsigned int *num_nd); + +/*! + * \brief Allocate memory using page allocator + * + * For any sizes less than MEM_CHUNK_SIZE, we ask the page allocator + * for the entire memory block, otherwise we try to assemble a + * contiguous cmblock ourselves. + * + * Upon successful allocation, the memory block will be added to the + * global list of allocated memory blocks. + * + * \param [in] size Number of bytes to allocate. + * \param [in] flags Kernel flags (GFP_xxx) for memory allocation. + * + * \return Pointer to allocated memory or NULL if failure. + */ +void * +ngbde_pgmem_alloc(size_t size, gfp_t flags); + +/*! + * \brief Free memory block allocated by ngbde_pgmem_alloc. + * + * \param [in] ptr Pointer returned by ngbde_pgmem_alloc. + * + * \return 0 if succesfully freed, otherwise -1. + */ +extern int +ngbde_pgmem_free(void *ptr); + +/*! + * \brief Free all memory blocks allocated by ngbde_pgmem_alloc. + * + * This function will walk the global list of allocated memory blocks + * and free all associated resources. + * + * Intended for a full clean up before the module is unloaded. + * + * \return Nothing. + */ +extern void +ngbde_pgmem_free_all(void); + +/*! + * \brief Map I/O memory in kernel driver. + * + * This function is used to provide device I/O access to a kernel mode + * driver. + * + * \param [in] devh Device handle (\ref ngbde_dev_s). + * \param [in] addr Physical address to map. + * \param [in] size Size of I/O window to map. + * + * \return Pointer to mapped I/O memory, or NULL on error. + */ +extern void * +ngbde_pio_map(void *devh, phys_addr_t addr, phys_addr_t size); + +/*! + * \brief Unmap I/O memory in kernel driver. + * + * Unmap I/O memory previously mapped via \ref ngbde_pio_map. + * + * \param [in] devh Device handle (\ref ngbde_dev_s). + * + * \return Nothing. + */ +extern void +ngbde_pio_unmap(void *devh); + +/*! + * \brief Unmap all I/O windows. + */ +extern void +ngbde_pio_cleanup(void); + +/*! + * \brief Write a memory-mapped register from kernel driver. + * + * Write a 32-bit register using I/O memory previously mapped via \ref + * ngbde_pio_map. + * + * \param [in] devh Device handle (\ref ngbde_dev_s). + * \param [in] offs Register address offset. + * \param [in] val Value to write to register. + * + * \return Nothing. + */ +extern void +ngbde_pio_write32(void *devh, uint32_t offs, uint32_t val); + +/*! + * \brief Read a memory-mapped register from kernel driver. + * + * Read a 32-bit register using I/O memory previously mapped via \ref + * ngbde_pio_map. + * + * \param [in] devh Device handle (\ref ngbde_dev_s). + * \param [in] offs Register address offset. + * + * \return Value read from register. + */ +extern uint32_t +ngbde_pio_read32(void *devh, uint32_t offs); + +/*! + * \brief Map interrupt controller I/O memory. + * + * On some devices the interrupt controller is a device separate from + * the main switch device. This function is used to provide interrupt + * controller I/O access to a kernel mode driver. + * + * \param [in] devh Device handle (\ref ngbde_dev_s). + * \param [in] addr Physical address to map. + * \param [in] size Size of I/O window to map. + * + * \return Pointer to mapped I/O memory, or NULL on error. + */ +extern void * +ngbde_iio_map(void *devh, phys_addr_t addr, phys_addr_t size); + +/*! + * \brief Unmap interrupt controller I/O memory. + * + * Unmap I/O memory previously mapped via \ref ngbde_iio_map. + * + * \param [in] devh Device handle (\ref ngbde_dev_s). + * + * \return Nothing. + */ +extern void +ngbde_iio_unmap(void *devh); + +/*! + * \brief Unmap all interrupt controller I/O windows. + */ +extern void +ngbde_iio_cleanup(void); + +/*! + * \brief Write a memory-mapped interrupt controller register. + * + * Write a 32-bit register using I/O memory previously mapped via \ref + * ngbde_iio_map. + * + * \param [in] devh Device handle (\ref ngbde_dev_s). + * \param [in] offs Register address offset. + * \param [in] val Value to write to register. + * + * \return Nothing. + */ +extern void +ngbde_iio_write32(void *devh, uint32_t offs, uint32_t val); + +/*! + * \brief Read a memory-mapped interrupt controller register. + * + * Read a 32-bit register using I/O memory previously mapped via \ref + * ngbde_iio_map. + * + * \param [in] devh Device handle (\ref ngbde_dev_s). + * \param [in] offs Register address offset. + * + * \return Value read from register. + */ +extern uint32_t +ngbde_iio_read32(void *devh, uint32_t offs); + +/*! + * \brief Map PCI bridge I/O memory. + * + * On some devices the interrupt controller is a device separate from + * the main switch device. This function is used to provide interrupt + * controller I/O access to a kernel mode driver. + * + * \param [in] devh Device handle (\ref ngbde_dev_s). + * \param [in] addr Physical address to map. + * \param [in] size Size of I/O window to map. + * + * \return Pointer to mapped I/O memory, or NULL on error. + */ +extern void * +ngbde_paxb_map(void *devh, phys_addr_t addr, phys_addr_t size); + +/*! + * \brief Unmap PCI bridge I/O memory. + * + * Unmap I/O memory previously mapped via \ref ngbde_paxb_map. + * + * \param [in] devh Device handle (\ref ngbde_dev_s). + * + * \return Nothing. + */ +extern void +ngbde_paxb_unmap(void *devh); + +/*! + * \brief Unmap all PCI bridge I/O windows. + */ +extern void +ngbde_paxb_cleanup(void); + +/*! + * \brief Probe for Broadcom switch devices on IPROC internal bus. + * + * \return 0 if no errors, otherwise -1. + */ +extern int +ngbde_iproc_probe(void); + +/*! + * \brief Clean up resources for Broadcom switch devices on IPROC internal bus. + * + * \return 0 if no errors, otherwise -1. + */ +extern int +ngbde_iproc_cleanup(void); + +#endif /* NGBDE_H */ diff --git a/platform/broadcom/saibcm-modules/sdklt/linux/bde/ngbde_dma.c b/platform/broadcom/saibcm-modules/sdklt/linux/bde/ngbde_dma.c new file mode 100644 index 00000000000..9cc2b191f48 --- /dev/null +++ b/platform/broadcom/saibcm-modules/sdklt/linux/bde/ngbde_dma.c @@ -0,0 +1,340 @@ +/*! \file ngbde_dma.c + * + * This module handles allocation of DMA memory pools. + * + */ +/* + * $Copyright: Copyright 2018-2020 Broadcom. All rights reserved. + * The term 'Broadcom' refers to Broadcom Inc. and/or its subsidiaries. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * version 2 as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * A copy of the GNU General Public License version 2 (GPLv2) can + * be found in the LICENSES folder.$ + */ + +#include + +/*! \cond */ +static int dma_debug = 0; +module_param(dma_debug, int, 0); +MODULE_PARM_DESC(dma_debug, +"DMA debug output enable (default 0)."); +/*! \endcond */ + +/*! Default size of of DMA memory pools (in MB). */ +#define DMAPOOL_SIZE_DEFAULT 16 + +/*! Default number of DMA memory pools per device. */ +#define NUM_DMAPOOL_DEFAULT 1 + +/*! \cond */ +static int dma_size = DMAPOOL_SIZE_DEFAULT; +module_param(dma_size, int, 0); +MODULE_PARM_DESC(dma_size, +"Size of of DMA memory pools in MB (default 16 MB)."); +/*! \endcond */ + +/*! \cond */ +static char *dma_alloc; +module_param(dma_alloc, charp, 0); +MODULE_PARM_DESC(dma_alloc, +"DMA allocation method auto|kapi|pgmem (default auto)"); +/*! \endcond */ + +/*! \cond */ +static int dma_pools = NUM_DMAPOOL_DEFAULT; +module_param(dma_pools, int, 0); +MODULE_PARM_DESC(dma_pools, +"Number of DMA memory pools to pre-allocate per device (default 1)."); +/*! \endcond */ + +/*! + * \brief Allocate DMA memory via kernel API. + * + * \param [in] dmactrl DMA allocation control. + * \param [out] dmamem DMA allocation result. + * + * \return Nothing. + */ +static void +ngbde_dmamem_kapi_alloc(ngbde_dmactrl_t *dmactrl, ngbde_dmamem_t *dmamem) +{ + void *vaddr; + dma_addr_t baddr; + + vaddr = dma_alloc_coherent(dmactrl->dev, dmactrl->size, &baddr, + dmactrl->flags); + if (vaddr) { + /* Store allocation information in dmamem structure */ + dmamem->vaddr = vaddr; + dmamem->paddr = virt_to_phys(vaddr); + dmamem->dev = dmactrl->dev; + dmamem->size = dmactrl->size; + dmamem->type = NGBDE_DMA_T_KAPI; + dmamem->baddr = baddr; + + /* Write small signature for debug purposes */ + strcpy((char *)vaddr, "DMA_KAPI"); + + if (dma_debug) { + printk("DMA: Allocated %d KB of KAPI memory at 0x%08lx\n", + (int)(dmamem->size / ONE_KB), + (unsigned long)dmamem->paddr); + } + } else { + if (dma_debug) { + printk("DMA: Failed to allocate KAPI memory\n"); + } + } +} + +/*! + * \brief Allocate DMA memory via page allocator. + * + * \param [in] dmactrl DMA allocation control. + * \param [out] dmamem DMA allocation result. + * + * \return Nothing. + */ +static void +ngbde_dmamem_pgmem_alloc(ngbde_dmactrl_t *dmactrl, ngbde_dmamem_t *dmamem) +{ + void *vaddr; + + vaddr = ngbde_pgmem_alloc(dmactrl->size, dmactrl->flags); + if (vaddr) { + /* Store allocation information in dmamem structure */ + dmamem->vaddr = vaddr; + dmamem->paddr = virt_to_phys(vaddr); + dmamem->dev = dmactrl->dev; + dmamem->size = dmactrl->size; + dmamem->type = NGBDE_DMA_T_PGMEM; + dmamem->baddr = dma_map_single(dmamem->dev, dmamem->vaddr, + dmamem->size, DMA_BIDIRECTIONAL); + if (dma_mapping_error(dmactrl->dev, dmamem->baddr)) { + dmamem->baddr = 0; + if (dma_debug) { + printk("DMA: Failed to map PGMEM memory\n"); + } + } + + /* Write small signature for debug purposes */ + strcpy((char *)vaddr, "DMA_PGMEM"); + + if (dma_debug) { + printk("DMA: Allocated %d KB of PGMEM memory at 0x%08lx\n", + (int)(dmamem->size / ONE_KB), + (unsigned long)dmamem->paddr); + } + } else { + if (dma_debug) { + printk("DMA: Failed to allocate PGMEM memory\n"); + } + } +} + +/*! + * \brief Allocate DMA memory. + * + * Depending on the DMA allocation control parameters, we select one + * of several DMA memory allocation methods. + * + * \param [in] dmactrl DMA allocation control. + * \param [out] dmamem DMA allocation result. + * + * \return Nothing. + */ +static int +ngbde_dmamem_alloc(ngbde_dmactrl_t *dmactrl, ngbde_dmamem_t *dmamem) +{ + int kapi = 0; + + if (dmamem->vaddr) { + /* Already allocated */ + return 0; + } + +#ifdef CONFIG_CMA + /* Always allow KAPI when CMA is available */ + kapi = 1; +#else + if (dmactrl->size <= (1 << (MAX_ORDER - 1 + PAGE_SHIFT))) { + kapi = 1; + } +#endif + + /* Allocation via kernel DMA API (if allowed) */ + if (kapi) { + switch (dmactrl->pref_type) { + case NGBDE_DMA_T_AUTO: + case NGBDE_DMA_T_KAPI: + ngbde_dmamem_kapi_alloc(dmactrl, dmamem); + break; + default: + break; + } + } + + /* Allocation via private page allocator */ + if (dmamem->vaddr == NULL) { + switch (dmactrl->pref_type) { + case NGBDE_DMA_T_AUTO: + case NGBDE_DMA_T_PGMEM: + ngbde_dmamem_pgmem_alloc(dmactrl, dmamem); + break; + default: + break; + } + } + + if (dmamem->vaddr == NULL) { + printk(KERN_WARNING "%s: Failed to allocate DMA memory\n", + MOD_NAME); + return -1; + } + + return 0; +} + +/*! + * \brief Free DMA memory. + * + * Free DMA memory allocated via \ref ngbde_dmamem_alloc. + * + * \param [in] dmamem DMA allocation result from \ref ngbde_dmamem_alloc. + * + * \return Nothing. + */ +static int +ngbde_dmamem_free(ngbde_dmamem_t *dmamem) +{ + switch (dmamem->type) { + case NGBDE_DMA_T_KAPI: + if (dma_debug) { + printk("DMA: Freeing %d KB of KAPI memory\n", + (int)(dmamem->size / ONE_KB)); + } + dma_free_coherent(dmamem->dev, dmamem->size, + dmamem->vaddr, dmamem->paddr); + memset(dmamem, 0, sizeof(*dmamem)); + break; + case NGBDE_DMA_T_PGMEM: + if (dma_debug) { + printk("DMA: Freeing %d KB of PGMEM memory\n", + (int)(dmamem->size / ONE_KB)); + } + if (dmamem->baddr) { + if (dma_debug) { + printk("DMA: Unmapping PGMEM memory at 0x%08lx\n", + (unsigned long)dmamem->baddr); + } + dma_unmap_single(dmamem->dev, dmamem->baddr, + dmamem->size, DMA_BIDIRECTIONAL); + } + ngbde_pgmem_free(dmamem->vaddr); + memset(dmamem, 0, sizeof(*dmamem)); + break; + case NGBDE_DMA_T_NONE: + /* Nothing to free */ + break; + default: + printk(KERN_WARNING "%s: Unable to free unknown DMA memory type\n", + MOD_NAME); + break; + } + return 0; +} + +/*! + * \brief Free all DMA memory pools for all devices. + * + * \return Nothing. + */ +void +ngbde_dma_cleanup(void) +{ + struct ngbde_dev_s *swdev; + unsigned int num_swdev, idx; + unsigned int pool; + + ngbde_swdev_get_all(&swdev, &num_swdev); + + for (idx = 0; idx < num_swdev; idx++) { + for (pool = 0; pool < NGBDE_NUM_DMAPOOL_MAX; pool++) { + if (swdev[idx].inactive) { + ngbde_dmamem_free(&swdev[idx].dmapool[pool].dmamem); + } + } + } +} + +/*! + * \brief Allocate DMA memory pools for all devices. + * + * \return Nothing. + */ +int +ngbde_dma_init(void) +{ + int rv; + struct ngbde_dev_s *swdev; + unsigned int num_swdev, idx; + int dma_type = NGBDE_DMA_T_AUTO; + struct ngbde_dmapool_s *dmapool; + unsigned int pool; + + /* Default DMA memory size per device */ + if (dma_size < 0) { + dma_size = DMAPOOL_SIZE_DEFAULT; + } + + /* Check for forced DMA allocation method */ + if (dma_alloc) { + if (strcmp(dma_alloc, "kapi") == 0) { + dma_type = NGBDE_DMA_T_KAPI; + } else if (strcmp(dma_alloc, "pgmem") == 0) { + dma_type = NGBDE_DMA_T_PGMEM; + } else { + printk(KERN_WARNING "%s: Unknown DMA type: %s\n", + MOD_NAME, dma_alloc); + } + } + + /* Number of DMA memory pools per device */ + if ((unsigned int)dma_pools >= NGBDE_NUM_DMAPOOL_MAX) { + dma_pools = NUM_DMAPOOL_DEFAULT; + } + + ngbde_swdev_get_all(&swdev, &num_swdev); + + for (idx = 0; idx < num_swdev; idx++) { + + /* Set DMA allocation parameters */ + for (pool = 0; pool < NGBDE_NUM_DMAPOOL_MAX; pool++) { + dmapool = &swdev[idx].dmapool[pool]; + dmapool->dmactrl.dev = swdev[idx].dma_dev; + dmapool->dmactrl.size = dma_size * ONE_MB; + dmapool->dmactrl.pref_type = dma_type; + dmapool->dmactrl.flags = GFP_KERNEL | GFP_DMA32; + } + + /* Allocate DMA pools */ + for (pool = 0; pool < dma_pools; pool++) { + dmapool = &swdev[idx].dmapool[pool]; + rv = ngbde_dmamem_alloc(&dmapool->dmactrl, &dmapool->dmamem); + if (rv < 0) { + printk(KERN_WARNING "%s: Unable to allocate DMA pool %d %d\n", + MOD_NAME, idx, pool); + } + } + } + return 0; +} diff --git a/platform/broadcom/saibcm-modules/sdklt/linux/bde/ngbde_iio.c b/platform/broadcom/saibcm-modules/sdklt/linux/bde/ngbde_iio.c new file mode 100644 index 00000000000..e97f1fcea73 --- /dev/null +++ b/platform/broadcom/saibcm-modules/sdklt/linux/bde/ngbde_iio.c @@ -0,0 +1,143 @@ +/*! \file ngbde_iio.c + * + * API for managing and accessing memory-mapped I/O for interrupt + * controller registers. + * + */ +/* + * $Copyright: Copyright 2018-2020 Broadcom. All rights reserved. + * The term 'Broadcom' refers to Broadcom Inc. and/or its subsidiaries. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * version 2 as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * A copy of the GNU General Public License version 2 (GPLv2) can + * be found in the LICENSES folder.$ + */ + +#include + +void * +ngbde_iio_map(void *devh, phys_addr_t addr, phys_addr_t size) +{ + struct ngbde_dev_s *sd = (struct ngbde_dev_s *)devh; + + if (sd->iio_mem) { + if (addr == sd->iio_win.addr && size == sd->iio_win.size) { + /* Already mapped */ + return sd->iio_mem; + } + ngbde_iio_unmap(devh); + } + + sd->iio_mem = ioremap_nocache(addr, size); + + if (sd->iio_mem) { + /* Save mapped resources */ + sd->iio_win.addr = addr; + sd->iio_win.size = size; + } + + return sd->iio_mem; +} + +void +ngbde_iio_unmap(void *devh) +{ + struct ngbde_dev_s *sd = (struct ngbde_dev_s *)devh; + + if (sd->iio_mem) { + iounmap(sd->iio_mem); + sd->iio_mem = NULL; + } +} + +void +ngbde_iio_cleanup(void) +{ + struct ngbde_dev_s *swdev, *sd; + unsigned int num_swdev, idx; + + ngbde_swdev_get_all(&swdev, &num_swdev); + + for (idx = 0; idx < num_swdev; idx++) { + sd = ngbde_swdev_get(idx); + ngbde_iio_unmap(sd); + } +} + +void +ngbde_iio_write32(void *devh, uint32_t offs, uint32_t val) +{ + struct ngbde_dev_s *sd = (struct ngbde_dev_s *)devh; + + if (sd->iio_mem) { + NGBDE_IOWRITE32(val, sd->iio_mem + offs); + } +} + +uint32_t +ngbde_iio_read32(void *devh, uint32_t offs) +{ + struct ngbde_dev_s *sd = (struct ngbde_dev_s *)devh; + + if (sd->iio_mem) { + return NGBDE_IOREAD32(sd->iio_mem + offs); + } + return 0; +} + +void * +ngbde_paxb_map(void *devh, phys_addr_t addr, phys_addr_t size) +{ + struct ngbde_dev_s *sd = (struct ngbde_dev_s *)devh; + + if (sd->paxb_mem) { + if (addr == sd->paxb_win.addr && size == sd->paxb_win.size) { + /* Already mapped */ + return sd->paxb_mem; + } + iounmap(sd->paxb_mem); + } + + sd->paxb_mem = ioremap_nocache(addr, size); + + if (sd->paxb_mem) { + /* Save mapped resources */ + sd->paxb_win.addr = addr; + sd->paxb_win.size = size; + } + + return sd->paxb_mem; +} + +void +ngbde_paxb_unmap(void *devh) +{ + struct ngbde_dev_s *sd = (struct ngbde_dev_s *)devh; + + if (sd->paxb_mem) { + iounmap(sd->paxb_mem); + sd->paxb_mem = NULL; + } +} + +void +ngbde_paxb_cleanup(void) +{ + struct ngbde_dev_s *swdev, *sd; + unsigned int num_swdev, idx; + + ngbde_swdev_get_all(&swdev, &num_swdev); + + for (idx = 0; idx < num_swdev; idx++) { + sd = ngbde_swdev_get(idx); + ngbde_paxb_unmap(sd); + } +} diff --git a/platform/broadcom/saibcm-modules/sdklt/linux/bde/ngbde_intr.c b/platform/broadcom/saibcm-modules/sdklt/linux/bde/ngbde_intr.c new file mode 100644 index 00000000000..acec7da100f --- /dev/null +++ b/platform/broadcom/saibcm-modules/sdklt/linux/bde/ngbde_intr.c @@ -0,0 +1,550 @@ +/*! \file ngbde_intr.c + * + * API for controlling a thread-based user-mode interrupt handler. + * + */ +/* + * $Copyright: Copyright 2018-2020 Broadcom. All rights reserved. + * The term 'Broadcom' refers to Broadcom Inc. and/or its subsidiaries. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * version 2 as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * A copy of the GNU General Public License version 2 (GPLv2) can + * be found in the LICENSES folder.$ + */ + +#include + +/*! \cond */ +static int intr_debug = 0; +module_param(intr_debug, int, 0); +MODULE_PARM_DESC(intr_debug, +"Interrupt debug output enable (default 0)."); +/*! \endcond */ + +static int +ngbde_intr_shared_write32(struct ngbde_dev_s *sd, struct ngbde_intr_ctrl_s *ic, + uint32_t reg_offs, uint32_t reg_val, uint32_t shr_mask) +{ + unsigned long flags; + struct ngbde_shr_reg_s *sr; + int idx; + + sr = NULL; + for (idx = 0; idx < NGBDE_NUM_INTR_SHR_REGS_MAX; idx++) { + if (sd->intr_shr_reg[idx].reg_offs == 0) { + /* If not found, then we add a new entry */ + sd->intr_shr_reg[idx].reg_offs = reg_offs; + } + if (sd->intr_shr_reg[idx].reg_offs == reg_offs) { + sr = &sd->intr_shr_reg[idx]; + break; + } + } + + if (sr == NULL) { + return -1; + } + + spin_lock_irqsave(&sd->lock, flags); + + sr->cur_val &= ~shr_mask; + sr->cur_val |= (reg_val & shr_mask); + + NGBDE_IOWRITE32(sr->cur_val, ic->iomem + reg_offs); + + spin_unlock_irqrestore(&sd->lock, flags); + + return 0; +} + +/*! + * \brief Interrupt handler for user mode thread. + * + * This function will determine whether a user-mode interrupt has + * occurred by reading the configured interrupt status and mask + * registers. + * + * If an interrupt has occurred, any waiting user-mode thread is woken + * up. + * + * \param [in] ic Interrupt control information. + * + * \retval 1 One or more user mode interrupts occurred. + * \retval 0 No user mode interrupts occurred. + */ +static int +ngbde_user_isr(ngbde_intr_ctrl_t *ic) +{ + int idx; + int active_interrupts = 0; + uint32_t stat = 0, mask = 0; + uint32_t kmask; + + /* Check if any enabled interrupts are active */ + for (idx = 0; idx < ic->num_regs; idx++) { + ngbde_irq_reg_t *ir = &ic->regs[idx]; + + /* Get mask of all kernel interrupt sources for this register address */ + kmask = ir->kmask; + + stat = NGBDE_IOREAD32(&ic->iomem[ir->status_reg]); + mask = NGBDE_IOREAD32(&ic->iomem[ir->mask_reg]); + + if (stat & mask & ~kmask) { + active_interrupts = 1; + break; + } + } + + /* No active interrupts to service */ + if (!active_interrupts) { + return 0; + } + + /* Disable (mask off) all interrupts */ + for (idx = 0; idx < ic->num_regs; idx++) { + ngbde_irq_reg_t *ir = &ic->regs[idx]; + + /* Get mask of all kernel interrupt sources for this register address */ + kmask = ir->kmask; + + if (kmask == 0xffffffff) { + /* Kernel driver owns all interrupts in this register */ + continue; + } else if (kmask) { + /* Synchronized write */ + struct ngbde_dev_s *sd = ngbde_swdev_get(ic->kdev); + if (ngbde_intr_shared_write32(sd, ic, ir->mask_reg, 0, ~kmask) < 0) { + printk(KERN_WARNING + "%s: Failed to write shared register for device %d\n", + MOD_NAME, ic->kdev); + /* Fall back to normal write to ensure interrupts are masked */ + NGBDE_IOWRITE32(0, &ic->iomem[ir->mask_reg]); + } + } else { + NGBDE_IOWRITE32(0, &ic->iomem[ir->mask_reg]); + } + } + + atomic_set(&ic->run_user_thread, 1); + wake_up_interruptible(&ic->user_thread_wq); + + return 1; +} + +/*! + * \brief Interrupt handler for kernel driver. + * + * Typically used by the KNET driver. + * + * \param [in] ic Interrupt control information. + * + * \retval 1 One or more kernel mode interrupts occurred. + * \retval 0 No kernel mode interrupts occurred. + */ +static int +ngbde_kernel_isr(ngbde_intr_ctrl_t *ic) +{ + if (ic->isr_func) { + return ic->isr_func(ic->isr_data); + } + return 0; +} + +/*! + * \brief Acknowledge interrupt + * + * \param [in] data Interrupt control information + * + * \retval 0 + */ +static int +ngbde_intr_ack(ngbde_intr_ctrl_t *ic) +{ + struct ngbde_dev_s *sd = ngbde_swdev_get(ic->kdev); + struct ngbde_intr_ack_reg_s *ar = &ic->intr_ack; + + if (sd->use_msi) { + if (ar->flags & NGBDE_INTR_ACK_F_PAXB) { + NGBDE_IOWRITE32(ar->ack_val, &sd->paxb_mem[ar->ack_reg]); + } else { + NGBDE_IOWRITE32(ar->ack_val, &sd->pio_mem[ar->ack_reg]); + } + } + + return 0; +} + +/*! + * \brief Linux ISR + * + * Will call the user-mode interrupts handler and optionally also a + * kernel mode interrupt handler (typically KNET). + * + * \param [in] irq_num Interrupt vector from kernel. + * \param [in] data Interrupt control information + * + * \retval IRQ_NONE Interrupt not recognized. + * \retval IRQ_HANDLED Interrupt recognized and handled (masked off). + */ +static irqreturn_t +ngbde_isr(int irq_num, void *data) +{ + struct ngbde_intr_ctrl_s *ic = (struct ngbde_intr_ctrl_s *)data; + irqreturn_t rv = IRQ_NONE; + + ngbde_intr_ack(ic); + + if (ngbde_user_isr(ic)) { + rv = IRQ_HANDLED; + } + if (ngbde_kernel_isr(ic)) { + rv = IRQ_HANDLED; + } + return rv; +} + +int +ngbde_intr_connect(int kdev, unsigned int irq_num) +{ + struct ngbde_dev_s *sd; + struct ngbde_intr_ctrl_s *ic; + unsigned long irq_flags; + + sd = ngbde_swdev_get(kdev); + if (!sd) { + return -1; + } + + if (irq_num >= NGBDE_NUM_IRQS_MAX) { + return -1; + } + + ic = &sd->intr_ctrl[irq_num]; + + if (ic->irq_active) { + return 0; + } + + if (sd->irq_line >= 0) { + if (sd->pio_mem == NULL) { + printk(KERN_WARNING "%s: No memory-mapped I/O for device %d\n", + MOD_NAME, kdev); + return -1; + } + ic->kdev = kdev; + ic->iomem = sd->pio_mem; + if (sd->iio_mem) { + if (intr_debug) { + printk("INTR: Using dedicated interrupt controller\n"); + } + ic->iomem = sd->iio_mem; + } + init_waitqueue_head(&ic->user_thread_wq); + atomic_set(&ic->run_user_thread, 0); + irq_flags = IRQF_SHARED; + ic->irq_vect = sd->irq_line; + + /* + * The pci_enable_msi function must be called after enabling + * BAR0_PAXB_OARR_FUNC0_MSI_PAGE, otherwise, MSI interrupts + * cannot be triggered! + */ + if (sd->use_msi) { + if (pci_enable_msi(sd->pci_dev) == 0) { + irq_flags = 0; + ic->irq_vect = sd->pci_dev->irq; + if (intr_debug) { + printk("INTR: Enabled MSI interrupts\n"); + } + } else { + printk(KERN_WARNING "%s: Failed to enable MSI for device %d\n", + MOD_NAME, kdev); + sd->use_msi = 0; + } + } + if (intr_debug) { + printk("INTR: Request IRQ %d\n", ic->irq_vect); + } + if (request_irq(ic->irq_vect, ngbde_isr, irq_flags, MOD_NAME, ic) < 0) { + printk(KERN_WARNING "%s: Could not get IRQ %d for device %d\n", + MOD_NAME, ic->irq_vect, kdev); + return -1; + } + ic->irq_active = 1; + } + + return 0; +} + +int +ngbde_intr_disconnect(int kdev, unsigned int irq_num) +{ + struct ngbde_dev_s *sd; + struct ngbde_intr_ctrl_s *ic; + + sd = ngbde_swdev_get(kdev); + if (!sd) { + return -1; + } + + if (irq_num >= NGBDE_NUM_IRQS_MAX) { + return -1; + } + + ic = &sd->intr_ctrl[irq_num]; + + if (!ic->irq_active) { + return 0; + } + + if (ic->isr_func) { + printk(KERN_WARNING "%s: Disconnecting IRQ %d blocked by kernel ISR\n", + MOD_NAME, irq_num); + return 0; + } + + if (ic->irq_vect >= 0) { + free_irq(ic->irq_vect, ic); + if (sd->use_msi) { + pci_disable_msi(sd->pci_dev); + } + ic->irq_active = 0; + } + + return 0; +} + +void +ngbde_intr_cleanup(void) +{ + struct ngbde_dev_s *swdev; + unsigned int num_swdev, idx, irq_num; + + ngbde_swdev_get_all(&swdev, &num_swdev); + + for (idx = 0; idx < num_swdev; idx++) { + for (irq_num = 0; irq_num < NGBDE_NUM_IRQS_MAX; irq_num++) { + ngbde_intr_disconnect(idx, irq_num); + } + } +} + +int +ngbde_intr_wait(int kdev, unsigned int irq_num) +{ + struct ngbde_dev_s *sd; + struct ngbde_intr_ctrl_s *ic; + + sd = ngbde_swdev_get(kdev); + if (!sd) { + return -1; + } + + if (irq_num >= NGBDE_NUM_IRQS_MAX) { + return -1; + } + + ic = &sd->intr_ctrl[irq_num]; + + if (!ic->irq_active) { + return 0; + } + + wait_event_interruptible(ic->user_thread_wq, + atomic_read(&ic->run_user_thread) != 0); + atomic_set(&ic->run_user_thread, 0); + + return 0; +} + +int +ngbde_intr_stop(int kdev, unsigned int irq_num) +{ + struct ngbde_dev_s *sd; + struct ngbde_intr_ctrl_s *ic; + + sd = ngbde_swdev_get(kdev); + if (!sd) { + return -1; + } + + if (irq_num >= NGBDE_NUM_IRQS_MAX) { + return -1; + } + + ic = &sd->intr_ctrl[irq_num]; + + if (!ic->irq_active) { + return 0; + } + + /* Wake up user thread */ + atomic_set(&ic->run_user_thread, 1); + wake_up_interruptible(&ic->user_thread_wq); + + return 0; +} + +int +ngbde_intr_regs_clr(int kdev, unsigned int irq_num) +{ + struct ngbde_dev_s *sd; + struct ngbde_intr_ctrl_s *ic; + + sd = ngbde_swdev_get(kdev); + if (!sd) { + return -1; + } + + if (irq_num >= NGBDE_NUM_IRQS_MAX) { + return -1; + } + + ic = &sd->intr_ctrl[irq_num]; + + if (ic->irq_active) { + /* Do not clear configuration with interrupt connected */ + return 0; + } + + ic->num_regs = 0; + memset(ic->regs, 0, sizeof(ic->regs)); + + return 0; +} + +int +ngbde_intr_reg_add(int kdev, unsigned int irq_num, + struct ngbde_irq_reg_s *ireg) +{ + struct ngbde_dev_s *sd; + struct ngbde_intr_ctrl_s *ic; + struct ngbde_irq_reg_s *ir; + unsigned int idx; + + sd = ngbde_swdev_get(kdev); + if (!sd) { + return -1; + } + + if (irq_num >= NGBDE_NUM_IRQS_MAX) { + return -1; + } + + ic = &sd->intr_ctrl[irq_num]; + + if (ic->irq_active) { + /* + * If the interrupt is connected, then we only update the + * kernel mask for existing entries. + */ + for (idx = 0; idx < ic->num_regs; idx++) { + ir = &ic->regs[idx]; + if (ir->status_reg == ireg->status_reg && + ir->mask_reg == ireg->mask_reg) { + ir->kmask = ireg->kmask; + if (intr_debug) { + printk("INTR: Updating interrupt register " + "0x%08x/0x%08x (0x%08x)\n", + ir->status_reg, ir->mask_reg, ir->kmask); + } + return 0; + } + } + return -1; + } + + if (ic->num_regs >= NGBDE_NUM_IRQ_REGS_MAX) { + return -1; + } + + ir = &ic->regs[ic->num_regs++]; + + memcpy(ir, ireg, sizeof (*ir)); + + if (intr_debug) { + printk("INTR: Adding interrupt register 0x%08x/0x%08x (0x%08x)\n", + ir->status_reg, ir->mask_reg, ir->kmask); + } + + return ic->num_regs; +} + +int +ngbde_intr_ack_reg_add(int kdev, unsigned int irq_num, + struct ngbde_intr_ack_reg_s *ackreg) +{ + struct ngbde_dev_s *sd; + struct ngbde_intr_ctrl_s *ic; + struct ngbde_intr_ack_reg_s *ar; + + sd = ngbde_swdev_get(kdev); + if (!sd) { + return -1; + } + + if (irq_num >= NGBDE_NUM_IRQS_MAX) { + return -1; + } + + ic = &sd->intr_ctrl[irq_num]; + + if (ic->irq_active) { + /* Ignore request if interrupt is connected */ + return 0; + } + + ar = &ic->intr_ack; + + memcpy(ar, ackreg, sizeof (*ar)); + + if (intr_debug) { + printk("INTR: Adding interrupt ACK register 0x%08x/0x%08x (0x%08x)\n", + ar->ack_reg, ar->ack_val, ar->flags); + } + + return 0; +} + +int +ngbde_intr_mask_write(int kdev, unsigned int irq_num, int kapi, + uint32_t status_reg, uint32_t mask_val) +{ + struct ngbde_dev_s *sd; + struct ngbde_intr_ctrl_s *ic; + struct ngbde_irq_reg_s *ir; + unsigned int idx; + uint32_t bmask; + + sd = ngbde_swdev_get(kdev); + if (!sd) { + return -1; + } + + if (irq_num >= NGBDE_NUM_IRQS_MAX) { + return -1; + } + + ic = &sd->intr_ctrl[irq_num]; + + ir = ic->regs; + for (idx = 0; idx < ic->num_regs; idx++) { + if (ir->status_reg == status_reg) { + bmask = kapi ? ir->kmask : ~ir->kmask; + ngbde_intr_shared_write32(sd, ic, ir->mask_reg, mask_val, bmask); + return 0; + } + ir++; + } + + return -1; +} diff --git a/platform/broadcom/saibcm-modules/sdklt/linux/bde/ngbde_ioctl.c b/platform/broadcom/saibcm-modules/sdklt/linux/bde/ngbde_ioctl.c new file mode 100644 index 00000000000..ccd0b7ee01d --- /dev/null +++ b/platform/broadcom/saibcm-modules/sdklt/linux/bde/ngbde_ioctl.c @@ -0,0 +1,237 @@ +/*! \file ngbde_ioctl.c + * + * NGBDE IOCTL interface. + * + */ +/* + * $Copyright: Copyright 2018-2020 Broadcom. All rights reserved. + * The term 'Broadcom' refers to Broadcom Inc. and/or its subsidiaries. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * version 2 as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * A copy of the GNU General Public License version 2 (GPLv2) can + * be found in the LICENSES folder.$ + */ + +#include + +#include + +long +ngbde_ioctl(struct file *file, unsigned int cmd, unsigned long arg) +{ + struct ngbde_ioc_cmd_s ioc; + struct ngbde_dev_s *swdev; + struct ngbde_irq_reg_s ireg; + struct ngbde_intr_ack_reg_s ackreg; + phys_addr_t addr, size; + unsigned int num_swdev; + unsigned int rsrc_type, rsrc_idx; + unsigned int irq_num, intr_cmd; + uint32_t mreg, mval; + + if (copy_from_user(&ioc, (void *)arg, sizeof(ioc))) { + return -EFAULT; + } + + ioc.rc = NGBDE_IOC_SUCCESS; + + switch (cmd) { + case NGBDE_IOC_MOD_INFO: + ioc.op.mod_info.version = NGBDE_IOC_VERSION; + break; + case NGBDE_IOC_PROBE_INFO: + ngbde_swdev_get_all(NULL, &num_swdev); + ioc.op.probe_info.num_swdev = num_swdev; + break; + case NGBDE_IOC_DEV_INFO: + swdev = ngbde_swdev_get(ioc.devid); + if (!swdev) { + ioc.rc = NGBDE_IOC_FAIL; + break; + } + ioc.op.dev_info.vendor_id = swdev->vendor_id; + ioc.op.dev_info.device_id = swdev->device_id; + ioc.op.dev_info.revision = swdev->revision; + ioc.op.dev_info.model = swdev->model; + if (swdev->use_msi) { + ioc.op.dev_info.flags |= NGBDE_DEV_F_MSI; + } + break; + case NGBDE_IOC_PHYS_ADDR: + swdev = ngbde_swdev_get(ioc.devid); + if (!swdev) { + ioc.rc = NGBDE_IOC_FAIL; + break; + } + rsrc_type = ioc.op.rsrc_id.type; + rsrc_idx = ioc.op.rsrc_id.inst; + switch (rsrc_type) { + case NGBDE_IO_RSRC_DEV_IO: + if (rsrc_idx >= NGBDE_NUM_IOWIN_MAX) { + printk(KERN_WARNING + "ngbde: invalid resource index (%d)\n", + rsrc_idx); + ioc.rc = NGBDE_IOC_FAIL; + break; + } + ioc.op.phys_addr.addr = swdev->iowin[rsrc_idx].addr; + ioc.op.phys_addr.size = swdev->iowin[rsrc_idx].size; + break; + case NGBDE_IO_RSRC_DMA_MEM: + if (rsrc_idx >= NGBDE_NUM_DMAPOOL_MAX) { + printk(KERN_WARNING + "ngbde: invalid resource index (%d)\n", + rsrc_idx); + ioc.rc = NGBDE_IOC_FAIL; + break; + } + ioc.op.phys_addr.addr = swdev->dmapool[rsrc_idx].dmamem.paddr; + ioc.op.phys_addr.size = swdev->dmapool[rsrc_idx].dmactrl.size; + break; + case NGBDE_IO_RSRC_DMA_BUS: + if (rsrc_idx >= NGBDE_NUM_DMAPOOL_MAX) { + printk(KERN_WARNING + "ngbde: invalid resource index (%d)\n", + rsrc_idx); + ioc.rc = NGBDE_IOC_FAIL; + break; + } + ioc.op.phys_addr.addr = swdev->dmapool[rsrc_idx].dmamem.baddr; + ioc.op.phys_addr.size = swdev->dmapool[rsrc_idx].dmactrl.size; + break; + default: + printk(KERN_WARNING + "ngbde: unknown resource type (%d)\n", + rsrc_type); + ioc.rc = NGBDE_IOC_FAIL; + break; + } + break; + case NGBDE_IOC_INTR_CTRL: + irq_num = ioc.op.intr_ctrl.irq_num; + intr_cmd = ioc.op.intr_ctrl.cmd; + switch (intr_cmd) { + case NGBDE_ICTL_INTR_CONN: + if (ngbde_intr_connect(ioc.devid, irq_num) < 0) { + ioc.rc = NGBDE_IOC_FAIL; + } + break; + case NGBDE_ICTL_INTR_DISC: + if (ngbde_intr_disconnect(ioc.devid, irq_num) < 0) { + ioc.rc = NGBDE_IOC_FAIL; + } + break; + case NGBDE_ICTL_INTR_WAIT: + if (ngbde_intr_wait(ioc.devid, irq_num) < 0) { + ioc.rc = NGBDE_IOC_FAIL; + } + break; + case NGBDE_ICTL_INTR_STOP: + if (ngbde_intr_stop(ioc.devid, irq_num) < 0) { + ioc.rc = NGBDE_IOC_FAIL; + } + break; + case NGBDE_ICTL_REGS_CLR: + if (ngbde_intr_regs_clr(ioc.devid, irq_num) < 0) { + ioc.rc = NGBDE_IOC_FAIL; + } + break; + default: + printk(KERN_WARNING + "%s: unknown interrupt control command (%d)\n", + MOD_NAME, intr_cmd); + ioc.rc = NGBDE_IOC_FAIL; + break; + } + break; + case NGBDE_IOC_IRQ_REG_ADD: + irq_num = ioc.op.irq_reg_add.irq_num; + ireg.status_reg = ioc.op.irq_reg_add.status_reg; + ireg.mask_reg = ioc.op.irq_reg_add.mask_reg; + ireg.kmask = ioc.op.irq_reg_add.kmask; + if (ngbde_intr_reg_add(ioc.devid, irq_num, &ireg) < 0) { + printk(KERN_WARNING + "%s: Unable to add interrupt register\n", + MOD_NAME); + ioc.rc = NGBDE_IOC_FAIL; + } + break; + case NGBDE_IOC_INTR_ACK_REG_ADD: + irq_num = ioc.op.intr_ack_reg_add.irq_num; + ackreg.ack_reg = ioc.op.intr_ack_reg_add.ack_reg; + ackreg.ack_val = ioc.op.intr_ack_reg_add.ack_val; + ackreg.flags = ioc.op.intr_ack_reg_add.flags; + if (ngbde_intr_ack_reg_add(ioc.devid, irq_num, &ackreg) < 0) { + printk(KERN_WARNING + "%s: Unable to add interrupt ack register\n", + MOD_NAME); + ioc.rc = NGBDE_IOC_FAIL; + } + break; + case NGBDE_IOC_IRQ_MASK_WR: + irq_num = ioc.op.irq_mask_wr.irq_num; + mreg = ioc.op.irq_mask_wr.offs; + mval = ioc.op.irq_mask_wr.val; + if (ngbde_intr_mask_write(ioc.devid, irq_num, 0, mreg, mval) < 0) { + printk(KERN_WARNING + "%s: Unable to write shared register\n", + MOD_NAME); + ioc.rc = NGBDE_IOC_FAIL; + } + break; + case NGBDE_IOC_PIO_WIN_MAP: + swdev = ngbde_swdev_get(ioc.devid); + if (!swdev) { + ioc.rc = NGBDE_IOC_FAIL; + break; + } + addr = ioc.op.pio_win.addr; + size = ioc.op.pio_win.size; + if (ngbde_pio_map(swdev, addr, size) == NULL) { + ioc.rc = NGBDE_IOC_FAIL; + } + break; + case NGBDE_IOC_IIO_WIN_MAP: + swdev = ngbde_swdev_get(ioc.devid); + if (!swdev) { + ioc.rc = NGBDE_IOC_FAIL; + break; + } + addr = ioc.op.pio_win.addr; + size = ioc.op.pio_win.size; + if (ngbde_iio_map(swdev, addr, size) == NULL) { + ioc.rc = NGBDE_IOC_FAIL; + } + break; + case NGBDE_IOC_PAXB_WIN_MAP: + swdev = ngbde_swdev_get(ioc.devid); + if (!swdev) { + ioc.rc = NGBDE_IOC_FAIL; + break; + } + addr = ioc.op.pio_win.addr; + size = ioc.op.pio_win.size; + if (ngbde_paxb_map(swdev, addr, size) == NULL) { + ioc.rc = NGBDE_IOC_FAIL; + } + break; + default: + printk(KERN_ERR "ngbde: invalid ioctl (%08x)\n", cmd); + ioc.rc = NGBDE_IOC_FAIL; + break; + } + + if (copy_to_user((void *)arg, &ioc, sizeof(ioc))) { + return -EFAULT; + } + + return 0; +} diff --git a/platform/broadcom/saibcm-modules/sdklt/linux/bde/ngbde_iproc_probe.c b/platform/broadcom/saibcm-modules/sdklt/linux/bde/ngbde_iproc_probe.c new file mode 100644 index 00000000000..63b02a4075a --- /dev/null +++ b/platform/broadcom/saibcm-modules/sdklt/linux/bde/ngbde_iproc_probe.c @@ -0,0 +1,164 @@ +/*! \file ngbde_iproc_probe.c + * + * BDE probe for IPROC internal bus devices. + * + * Validate CMICD existence on the platform. If Linux device tree matched, + * probe function of platform driver is called and the switch device read from + * CMICD register is added to the device list. + * + */ +/* + * $Copyright: Copyright 2018-2020 Broadcom. All rights reserved. + * The term 'Broadcom' refers to Broadcom Inc. and/or its subsidiaries. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * version 2 as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * A copy of the GNU General Public License version 2 (GPLv2) can + * be found in the LICENSES folder.$ + */ + +#include +#include +#include + +/*! \cond */ +static int iproc_debug = 0; +module_param(iproc_debug, int, 0); +MODULE_PARM_DESC(iproc_debug, +"IPROC debug output enable (default 0)."); +/*! \endcond */ + +/*! + * \brief Probe devices on the IPROC internal bus. + * + * \param [in] pldev Platform device. + * + * \retval 0 No errors + * \retval -1 Something went wrong. + */ +static int +iproc_cmicd_probe(struct platform_device *pldev) +{ + int rv; + uint32_t size; + void *base_address; + uint32_t dev_rev_id; + struct ngbde_dev_s ngbde_dev, *nd = &ngbde_dev; + struct resource *memres, *irqres; + + memres = platform_get_resource(pldev, IORESOURCE_MEM, 0); + if (memres == NULL) { + printk("Unable to retrieve iProc CMIC memory resource."); + return -1; + } + size = memres->end - memres->start + 1; + + if (iproc_debug) { + printk("CMIC info : Memory start=%p, end=%p\n", + (void *)memres->start, (void *)memres->end); + } + + base_address = ioremap_nocache(memres->start, size); + if (!base_address) { + printk(KERN_WARNING "Error mapping iProc CMIC registers"); + return -1; + } + + memset(nd, 0, sizeof(*nd)); + nd->pci_dev = NULL; /* No PCI bus */ + nd->dma_dev = &pldev->dev; + + /* Read switch device ID from CMIC */ + dev_rev_id = *((uint32_t*)(base_address + 0x10224)); + nd->vendor_id = 0x14e4; + nd->device_id = dev_rev_id & 0xffff; + nd->revision = (dev_rev_id >> 16) & 0xff; + + irqres = platform_get_resource(pldev, IORESOURCE_IRQ, 0); + if (irqres == NULL) { + printk(KERN_WARNING "Unable to retrieve iProc CMIC IRQ resource."); + return -1; + } + nd->irq_line = irqres->start; + if (iproc_debug) { + printk("CMIC info : IRQ line=%p\n", (void *)irqres->start); + } + + nd->iowin[0].addr = memres->start; + nd->iowin[0].size = size; + + if (base_address) { + iounmap(base_address); + } + rv = ngbde_swdev_add(nd); + + return rv; +} + +/*! + * \brief Remove the platform device. + * + * \param [in] pldev Platform device. + * + * \retval 0 No errors + */ +static int +iproc_cmicd_remove(struct platform_device *pldev) +{ + return 0; +} + +/*! Matching compatible property with device tree. */ +static const struct of_device_id iproc_cmicd_of_match[] = { + { .compatible = "brcm,iproc-cmicd" }, + {}, +}; +MODULE_DEVICE_TABLE(of, iproc_cmicd_of_match); + +static char iproc_cmicd_string[] = "bcmiproc-cmicd"; + +/*! Platform driver definition. */ +static struct platform_driver iproc_cmicd_driver = +{ + .probe = iproc_cmicd_probe, + .remove = iproc_cmicd_remove, + .driver = + { + .name = iproc_cmicd_string, + .owner = THIS_MODULE, + .of_match_table = iproc_cmicd_of_match, + }, +}; + +/*! + * \brief Probe for Broadcom switch devices on IPROC internal bus. + * + * \return 0 if no errors, otherwise -1. + */ +int +ngbde_iproc_probe(void) +{ + platform_driver_register(&iproc_cmicd_driver); + + return 0; +} + +/*! + * \brief Clean up resources for Broadcom switch devices on IPROC internal bus. + * + * \return 0 if no errors, otherwise -1. + */ +int +ngbde_iproc_cleanup(void) +{ + platform_driver_unregister(&iproc_cmicd_driver); + + return 0; +} diff --git a/platform/broadcom/saibcm-modules/sdklt/linux/bde/ngbde_kapi.c b/platform/broadcom/saibcm-modules/sdklt/linux/bde/ngbde_kapi.c new file mode 100644 index 00000000000..340e7b057d4 --- /dev/null +++ b/platform/broadcom/saibcm-modules/sdklt/linux/bde/ngbde_kapi.c @@ -0,0 +1,216 @@ +/*! \file ngbde_kapi.c + * + * Public BDE kernel API for use with other kernel modules. + * + */ +/* + * $Copyright: Copyright 2018-2020 Broadcom. All rights reserved. + * The term 'Broadcom' refers to Broadcom Inc. and/or its subsidiaries. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * version 2 as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * A copy of the GNU General Public License version 2 (GPLv2) can + * be found in the LICENSES folder.$ + */ + +#include + +#include + +struct pci_dev * +ngbde_kapi_pci_dev_get(int kdev) +{ + struct ngbde_dev_s *sd; + + sd = ngbde_swdev_get(kdev); + if (!sd) { + return NULL; + } + + return sd->pci_dev; +} +/*! \cond */ +EXPORT_SYMBOL(ngbde_kapi_pci_dev_get); +/*! \endcond */ + +struct device * +ngbde_kapi_dma_dev_get(int kdev) +{ + struct ngbde_dev_s *sd; + + sd = ngbde_swdev_get(kdev); + if (!sd) { + return NULL; + } + + return sd->dma_dev; +} +/*! \cond */ +EXPORT_SYMBOL(ngbde_kapi_dma_dev_get); +/*! \endcond */ + +void * +ngbde_kapi_dma_bus_to_virt(int kdev, dma_addr_t baddr) +{ + struct ngbde_dev_s *sd; + struct ngbde_dmamem_s *dmamem; + size_t dma_offset; + int idx; + + sd = ngbde_swdev_get(kdev); + if (!sd) { + return NULL; + } + + for (idx = 0; idx < NGBDE_NUM_DMAPOOL_MAX; idx++) { + dmamem = &sd->dmapool[idx].dmamem; + dma_offset = baddr - dmamem->baddr; + if (dma_offset < dmamem->size) { + return (uint8_t *)dmamem->vaddr + dma_offset; + } + } + return NULL; +} +/*! \cond */ +EXPORT_SYMBOL(ngbde_kapi_dma_bus_to_virt); +/*! \endcond */ + +dma_addr_t +ngbde_kapi_dma_virt_to_bus(int kdev, void *vaddr) +{ + struct ngbde_dev_s *sd; + struct ngbde_dmamem_s *dmamem; + size_t dma_offset; + int idx; + + sd = ngbde_swdev_get(kdev); + if (!sd) { + return 0UL; + } + + for (idx = 0; idx < NGBDE_NUM_DMAPOOL_MAX; idx++) { + dmamem = &sd->dmapool[idx].dmamem; + dma_offset = (uintptr_t)vaddr - (uintptr_t)dmamem->vaddr; + if (dma_offset < dmamem->size) { + return dmamem->baddr + dma_offset; + } + } + return 0UL; +} +/*! \cond */ +EXPORT_SYMBOL(ngbde_kapi_dma_virt_to_bus); +/*! \endcond */ + +void +ngbde_kapi_pio_write32(int kdev, uint32_t offs, uint32_t val) +{ + struct ngbde_dev_s *sd; + + sd = ngbde_swdev_get(kdev); + if (sd) { + return ngbde_pio_write32(sd, offs, val); + } +} +/*! \cond */ +EXPORT_SYMBOL(ngbde_kapi_pio_write32); +/*! \endcond */ + +uint32_t +ngbde_kapi_pio_read32(int kdev, uint32_t offs) +{ + struct ngbde_dev_s *sd; + + sd = ngbde_swdev_get(kdev); + if (sd) { + return ngbde_pio_read32(sd, offs); + } + + return (uint32_t)-1; +} +/*! \cond */ +EXPORT_SYMBOL(ngbde_kapi_pio_read32); +/*! \endcond */ + +void * +ngbde_kapi_pio_membase(int kdev) +{ + struct ngbde_dev_s *sd; + + sd = ngbde_swdev_get(kdev); + if (!sd) { + return NULL; + } + + return sd->pio_mem; +} +/*! \cond */ +EXPORT_SYMBOL(ngbde_kapi_pio_membase); +/*! \endcond */ + +int +ngbde_kapi_intr_connect(int kdev, unsigned int irq_num, + int (*isr_func)(void *), void *isr_data) +{ + struct ngbde_dev_s *sd; + struct ngbde_intr_ctrl_s *ic; + + sd = ngbde_swdev_get(kdev); + if (!sd) { + return -1; + } + + if (irq_num >= NGBDE_NUM_IRQS_MAX) { + return -1; + } + + ic = &sd->intr_ctrl[irq_num]; + ic->isr_func = isr_func; + ic->isr_data = isr_data; + + return 0; +} +/*! \cond */ +EXPORT_SYMBOL(ngbde_kapi_intr_connect); +/*! \endcond */ + +int +ngbde_kapi_intr_disconnect(int kdev, unsigned int irq_num) +{ + struct ngbde_dev_s *sd; + struct ngbde_intr_ctrl_s *ic; + + sd = ngbde_swdev_get(kdev); + if (!sd) { + return -1; + } + + if (irq_num >= NGBDE_NUM_IRQS_MAX) { + return -1; + } + + ic = &sd->intr_ctrl[irq_num]; + ic->isr_func = NULL; + ic->isr_data = NULL; + + return 0; +} +/*! \cond */ +EXPORT_SYMBOL(ngbde_kapi_intr_disconnect); +/*! \endcond */ + +int +ngbde_kapi_intr_mask_write(int kdev, unsigned int irq_num, + uint32_t status_reg, uint32_t mask_val) +{ + return ngbde_intr_mask_write(kdev, irq_num, 1, status_reg, mask_val); +} +/*! \cond */ +EXPORT_SYMBOL(ngbde_kapi_intr_mask_write); +/*! \endcond */ diff --git a/platform/broadcom/saibcm-modules/sdklt/linux/bde/ngbde_main.c b/platform/broadcom/saibcm-modules/sdklt/linux/bde/ngbde_main.c new file mode 100644 index 00000000000..5ce48ebc513 --- /dev/null +++ b/platform/broadcom/saibcm-modules/sdklt/linux/bde/ngbde_main.c @@ -0,0 +1,297 @@ +/*! \file ngbde_main.c + * + * NGBDE module entry. + * + */ +/* + * $Copyright: Copyright 2018-2020 Broadcom. All rights reserved. + * The term 'Broadcom' refers to Broadcom Inc. and/or its subsidiaries. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * version 2 as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * A copy of the GNU General Public License version 2 (GPLv2) can + * be found in the LICENSES folder.$ + */ + +#include + +/*! \cond */ +MODULE_AUTHOR("Broadcom Corporation"); +MODULE_DESCRIPTION("NG BDE Module"); +MODULE_LICENSE("GPL"); +/*! \endcond */ + +/*! \cond */ +static int mmap_debug = 0; +module_param(mmap_debug, int, 0); +MODULE_PARM_DESC(mmap_debug, +"MMAP debug output enable (default 0)."); +/*! \endcond */ + +/*! + * \brief Remap user space DMA memory to non-cached area. + * + * Since we cannot flush and invalidate DMA memory from user space, + * the DMA memory pools need to be cache-coherent, even if this means + * that we need to remap the DMA memory as non-cached. + * + * If undefined, we set this value according to kernel configuration. + */ +#ifndef REMAP_DMA_NONCACHED +# ifdef CONFIG_DMA_NONCOHERENT +# define REMAP_DMA_NONCACHED 1 +# else +# define REMAP_DMA_NONCACHED 0 +# endif +#endif + +static int +ngbde_open(struct inode *inode, struct file *filp) +{ + return 0; +} + +static int +ngbde_release(struct inode *inode, struct file *filp) +{ + return 0; +} + +/*! + * \brief Check if memory range is within existing DMA memory pools. + * + * \param [in] paddr Physical start address of memory range. + * \param [in] size Size of memory range. + * + * \retval true Range is valid. + * \retval false Range is not valid. + */ +static bool +ngbde_dma_range_valid(unsigned long paddr, unsigned long size) +{ + struct ngbde_dev_s *swdev; + unsigned int num_swdev, idx; + struct ngbde_dmamem_s *dmamem; + unsigned int pool; + + ngbde_swdev_get_all(&swdev, &num_swdev); + + for (idx = 0; idx < num_swdev; idx++) { + for (pool = 0; pool < NGBDE_NUM_DMAPOOL_MAX; pool++) { + dmamem = &swdev[idx].dmapool[pool].dmamem; + if (paddr >= dmamem->paddr && + (paddr + size) <= (dmamem->paddr + dmamem->size)) { + return true; + } + } + } + return false; +} + +/*! + * \brief Check if memory range is within device I/O ranges. + * + * \param [in] paddr Physical start address of I/O memory range. + * \param [in] size Size of memory range. + * + * \retval true Range is valid. + * \retval false Range is not valid. + */ +static bool +ngbde_pio_range_valid(unsigned long paddr, unsigned long size) +{ + struct ngbde_dev_s *swdev; + unsigned int num_swdev, idx; + struct ngbde_memwin_s *iowin; + unsigned long iowin_size; + unsigned int wdx; + + ngbde_swdev_get_all(&swdev, &num_swdev); + + for (idx = 0; idx < num_swdev; idx++) { + for (wdx = 0; wdx < NGBDE_NUM_IOWIN_MAX; wdx++) { + iowin = &swdev[idx].iowin[wdx]; + iowin_size = iowin->size; + if (iowin_size < PAGE_SIZE) { + iowin_size = PAGE_SIZE; + } + if (mmap_debug) { + printk("MMAP: Check 0x%08lx/0x%08lx against " + "0x%08lx/0x%08lx(0x%08lx)\n", + paddr, size, + (unsigned long)iowin->addr, + (unsigned long)iowin->size, iowin_size); + } + if (paddr >= iowin->addr && + (paddr + size) <= (iowin->addr + iowin_size)) { + return true; + } + } + } + return false; +} + +/*! + * \brief Match incomplete address with device base addresses. + * + * Use for physical addresses larger than 44 bits. + * + * \param [in] paddr Physical address from user space. + * + * \return Matched device base addess or 0 if no match. + */ +static unsigned long +ngbde_pio_base_match(unsigned long paddr) +{ + struct ngbde_dev_s *swdev; + unsigned int num_swdev, idx; + struct ngbde_memwin_s *iowin; + unsigned int wdx; + + ngbde_swdev_get_all(&swdev, &num_swdev); + + for (idx = 0; idx < num_swdev; idx++) { + for (wdx = 0; wdx < NGBDE_NUM_IOWIN_MAX; wdx++) { + iowin = &swdev[idx].iowin[wdx]; + if (((paddr ^ iowin->addr) & 0xfffffffffffULL) == 0) { + if (mmap_debug) { + printk("MMAP: Matched 0x%08lx to 0x%08lx\n", + (unsigned long)paddr, + (unsigned long)iowin->addr); + } + return iowin->addr; + } + } + } + return 0; +} + +/* + * Some kernels are configured to prevent mapping of kernel RAM memory + * into user space via the /dev/mem device. + * + * The function below provides a backdoor to mapping the DMA pool to + * user space via the BDE device file. + */ +static int +ngbde_mmap(struct file *filp, struct vm_area_struct *vma) +{ + unsigned long paddr = vma->vm_pgoff << PAGE_SHIFT; + unsigned long size = vma->vm_end - vma->vm_start; + int map_noncached = REMAP_DMA_NONCACHED; + int range_valid = 0; + + if (mmap_debug) { + printk("MMAP: Mapping %lu Kbytes at 0x%08lx (0x%lx)\n", + size / 1024, paddr, vma->vm_pgoff); + } + + if (ngbde_dma_range_valid(paddr, size)) { + range_valid = 1; + } else { + map_noncached = 1; + if (ngbde_pio_range_valid(paddr, size)) { + range_valid = 1; + } else { + paddr = ngbde_pio_base_match(paddr); + if (ngbde_pio_range_valid(paddr, size)) { + range_valid = 1; + } + } + } + + if (!range_valid) { + printk("BDE: Invalid mmap range 0x%08lx/0x%lx\n", paddr, size); + return -EINVAL; + } + + if (map_noncached) { + vma->vm_page_prot = pgprot_noncached(vma->vm_page_prot); + } + + if (remap_pfn_range(vma, vma->vm_start, vma->vm_pgoff, + size, vma->vm_page_prot)) { + printk("BDE: Failed to mmap phys range 0x%lx-0x%lx to 0x%lx-0x%lx\n", + paddr, paddr + size, vma->vm_start, vma->vm_end); + return -EAGAIN; + } + + return 0; +} + +static struct file_operations fops = { + .open = ngbde_open, + .release = ngbde_release, + .unlocked_ioctl = ngbde_ioctl, + .compat_ioctl = ngbde_ioctl, + .mmap = ngbde_mmap, +}; + +/*! + * \brief Standard module cleanup. + * + * \return Nothing. + */ +void __exit +cleanup_module(void) +{ + ngbde_intr_cleanup(); + ngbde_iio_cleanup(); + ngbde_paxb_cleanup(); + ngbde_pio_cleanup(); + ngbde_dma_cleanup(); + ngbde_procfs_cleanup(); + unregister_chrdev(MOD_MAJOR, MOD_NAME); + ngbde_pci_cleanup(); + ngbde_iproc_cleanup(); + printk(KERN_INFO "Broadcom NGBDE unloaded successfully\n"); +} + +/*! + * \brief Standard module initialization. + * + * \return Nothing. + */ +int __init +init_module(void) +{ + int rv; + + rv = register_chrdev(MOD_MAJOR, MOD_NAME, &fops); + if (rv < 0) { + printk(KERN_WARNING "%s: can't get major %d\n", + MOD_NAME, MOD_MAJOR); + return rv; + } + + rv = ngbde_iproc_probe(); + if (rv < 0) { + printk(KERN_WARNING "%s: Error probing for AXI bus devices.\n", + MOD_NAME); + return rv; + } + + rv = ngbde_pci_probe(); + if (rv < 0) { + printk(KERN_WARNING "%s: Error probing for PCI bus devices.\n", + MOD_NAME); + return rv; + } + + rv = ngbde_procfs_init(); + if (rv < 0) { + printk(KERN_WARNING "%s: Unable to initialize proc files\n", + MOD_NAME); + return rv; + } + + printk(KERN_INFO "Broadcom NGBDE loaded successfully\n"); + return 0; +} diff --git a/platform/broadcom/saibcm-modules/sdklt/linux/bde/ngbde_pci_probe.c b/platform/broadcom/saibcm-modules/sdklt/linux/bde/ngbde_pci_probe.c new file mode 100644 index 00000000000..37da39cd38a --- /dev/null +++ b/platform/broadcom/saibcm-modules/sdklt/linux/bde/ngbde_pci_probe.c @@ -0,0 +1,211 @@ +/*! \file ngbde_pci_probe.c + * + * NG BDE probe for PCI devices. + * + */ +/* + * $Copyright: Copyright 2018-2020 Broadcom. All rights reserved. + * The term 'Broadcom' refers to Broadcom Inc. and/or its subsidiaries. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * version 2 as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * A copy of the GNU General Public License version 2 (GPLv2) can + * be found in the LICENSES folder.$ + */ + +#include + +/*! \cond */ +static int use_msi = 1; +module_param(use_msi, int, 0); +MODULE_PARM_DESC(use_msi, +"Use MSI interrupts if supported by the kernel (default 1)."); +/*! \endcond */ + +/*! \cond */ +static int pci_debug = 0; +module_param(pci_debug, int, 0); +MODULE_PARM_DESC(pci_debug, +"PCI debug output enable (default 0)."); +/*! \endcond */ + +/*! + * Use BCMDRD_DEVLIST_ENTRY macro to generate a device list based on + * supported/installed devices. + */ +#define BCMDRD_DEVLIST_ENTRY(_nm,_vn,_dv,_rv,_md,_pi,_bd,_bc,_fn,_cn,_pf,_pd,_r0,_r1) \ + { _vn, _dv, PCI_ANY_ID, PCI_ANY_ID }, + +/*! Include all chip variants in the list of supported devices. */ +#define BCMDRD_DEVLIST_INCLUDE_ALL + +static struct pci_device_id pci_id_table[] = { +#include + { BROADCOM_VENDOR_ID, 0xb524, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, 0xb684, PCI_ANY_ID, PCI_ANY_ID }, + { 0, 0, 0, 0 } +}; + +static int +pci_probe(struct pci_dev *pci_dev, const struct pci_device_id *ent) +{ + int rv; + int bdx; + int cmic_bar = 0; + uint8_t rev; + struct ngbde_dev_s ngbde_dev, *nd = &ngbde_dev; + int bus_no = pci_dev->bus ? pci_dev->bus->number : 0; + int slot_no = PCI_SLOT(pci_dev->devfn); + + if (PCI_FUNC(pci_dev->devfn) > 0) { + return 0; + } + + if (pci_debug) { + printk("PCI: pci_probe: bus %d slot %d: %04x:%04x\n", + bus_no, slot_no, + pci_dev->vendor, pci_dev->device); + } + + memset(nd, 0, sizeof(*nd)); + nd->pci_dev = pci_dev; + nd->dma_dev = &pci_dev->dev; + nd->vendor_id = pci_dev->vendor; + nd->device_id = pci_dev->device; + nd->bus_no = bus_no; + nd->slot_no = slot_no; + + /* PCI revision must extracted "manually */ + pci_read_config_byte(pci_dev, PCI_REVISION_ID, &rev); + nd->revision = rev; + + if (pci_enable_device(pci_dev)) { + printk(KERN_WARNING "%s: Cannot enable PCI device: " + "vendor_id = %x, device_id = %x\n", + MOD_NAME, pci_dev->vendor, pci_dev->device); + } + pci_set_master(pci_dev); + + /* IRQ number is only valid if PCI device is enabled */ + nd->irq_line = pci_dev->irq; + + /* Check for iProc */ + if (pci_resource_len(pci_dev, 2)) { + nd->iowin[1].addr = pci_resource_start(pci_dev, 0); + nd->iowin[1].size = pci_resource_len(pci_dev, 0); + cmic_bar = 2; + } + nd->iowin[0].addr = pci_resource_start(pci_dev, cmic_bar); + nd->iowin[0].size = pci_resource_len(pci_dev, cmic_bar); + + /* Verify basic I/O access by reading first word of each BAR window */ + for (bdx = 0; bdx < 2; bdx++) { + if (nd->iowin[bdx].size == 0) { + continue; + } + if (ngbde_pio_map(nd, nd->iowin[bdx].addr, nd->iowin[bdx].size)) { + if (pci_debug) { + printk("PCI: BAR %d adddress 0 = 0x%x\n", + bdx, (unsigned int)ngbde_pio_read32(nd, 0)); + } + ngbde_pio_unmap(nd); + } else { + printk(KERN_WARNING "%s: Cannot map PCI BAR %d: " + "start = %08lx, len = %lx\n", + MOD_NAME, bdx, + (unsigned long)nd->iowin[bdx].addr, + (unsigned long)nd->iowin[bdx].size); + } + } + + spin_lock_init(&nd->lock); + + /* Determine MSI configuration by enabling MSI on the device */ + nd->use_msi = use_msi; + if (nd->use_msi) { + if (pci_enable_msi(nd->pci_dev) == 0) { + pci_disable_msi(nd->pci_dev); + } else { + nd->use_msi = 0; + } + } + + rv = ngbde_swdev_add(nd); + + if (rv == 0) { + /* Update DMA pools for all devices */ + rv = ngbde_dma_init(); + if (rv < 0) { + printk(KERN_WARNING "%s: Error initializing DMA memory\n", + MOD_NAME); + /* Mark device as inactive */ + nd->inactive = 1; + } + } + + return rv; +} + +static void +pci_remove(struct pci_dev* pci_dev) +{ + struct ngbde_dev_s *swdev; + unsigned int num_swdev, idx; + int bus_no = pci_dev->bus ? pci_dev->bus->number : 0; + int slot_no = PCI_SLOT(pci_dev->devfn); + + if (pci_debug) { + printk("PCI: pci_remove: bus %d slot %d: %04x:%04x\n", + bus_no, slot_no, + pci_dev->vendor, pci_dev->device); + } + + ngbde_swdev_get_all(&swdev, &num_swdev); + for (idx = 0; idx < num_swdev; idx++) { + if (swdev[idx].bus_no == bus_no && + swdev[idx].slot_no == slot_no) { + if (swdev[idx].inactive) { + printk(KERN_WARNING "%s: Device already removed\n", + MOD_NAME); + } + /* Active device in this slot already? */ + swdev[idx].inactive = 1; + } + } + + /* Update DMA pools for all devices */ + ngbde_dma_cleanup(); +} + +static struct pci_driver pci_driver = { + .name = MOD_NAME, + .probe = pci_probe, + .remove = pci_remove, + .id_table = pci_id_table, + /* The rest are dynamic */ +}; + +int +ngbde_pci_probe(void) +{ + if (pci_register_driver(&pci_driver) < 0) { + return -ENODEV; + } + + return 0; +} + +int +ngbde_pci_cleanup(void) +{ + pci_unregister_driver(&pci_driver); + + return 0; +} diff --git a/platform/broadcom/saibcm-modules/sdklt/linux/bde/ngbde_pgmem.c b/platform/broadcom/saibcm-modules/sdklt/linux/bde/ngbde_pgmem.c new file mode 100644 index 00000000000..e473f0c545c --- /dev/null +++ b/platform/broadcom/saibcm-modules/sdklt/linux/bde/ngbde_pgmem.c @@ -0,0 +1,472 @@ +/*! \file ngbde_pgmem.c + * + * \brief PGMEM allocator. + * + * This module is used to allocate large physically contiguous memory + * blocks using the Linux kernel page allocator. + * + * The Linux page allocator can allocate contiguous memory up until a + * certain size, which depends on the kernel version and the CPU + * architecture. + * + * If a larger contiguous memory block is requested, then we need to + * allocate multiple blocks from the Linux page allocator and then + * check if which ones are contiguous. + * + * The smaller memory blocks from which the larger block is assembled + * are referred to as "chunks". + * + * The PGMEM allocator will continue to allocate chunks from the Linux + * page allocator, until a contiguous memory block of the requested + * size has been assembled, or until a predefined maximum number of + * chunks have been allocated. Obviously the process is also stopped + * if the Linux page allocator returns an error. + * + * A physically contiguous memory block assembled from smaller memory + * chunks are referred to as "cmblocks". + * + * The chance of success depends on the requested memory block size as + * well as the fragmentation level of the system memory, i.e. the + * sooner after system boot these memory block are requested, the more + * likely these requests are to succeed. + */ +/* + * $Copyright: Copyright 2018-2020 Broadcom. All rights reserved. + * The term 'Broadcom' refers to Broadcom Inc. and/or its subsidiaries. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * version 2 as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * A copy of the GNU General Public License version 2 (GPLv2) can + * be found in the LICENSES folder.$ + */ + +#include + + +/******************************************************************************* + * Local definitions + ******************************************************************************/ + +/*! Maximum size the kernel can allocate in a single allocation. */ +#define MEM_CHUNK_SIZE_MAX (1 << (MAX_ORDER - 1 + PAGE_SHIFT)) + +/*! Default block size we wil request from the kernel. */ +#define MEM_CHUNK_SIZE_DEFAULT (512 * ONE_KB) + +/*! \cond */ +static int pgmem_chunk_size = 0; +module_param(pgmem_chunk_size, int, 0); +MODULE_PARM_DESC(pgmem_chunk_size, +"Memory chunk size in KB used by page allocator (default auto)."); +/*! \endcond */ + +/*! \cond */ +static int pgmem_debug = 0; +module_param(pgmem_debug, int, 0); +MODULE_PARM_DESC(pgmem_debug, +"Enable page memory allocator debug output (default 0)."); +/*! \endcond */ + +/*! Helper macro for debug trace output. */ +#define PGMEM_TRACE(_s) \ + do { \ + if (pgmem_debug) { \ + printk(_s); \ + } \ + } while (0) + +/*! + * Chunk memory block descriptor. + */ +typedef struct cmblock_desc_s { + + /*! Linked-list handle. */ + struct list_head list; + + /*! Requested cmblock size. */ + unsigned long req_size; + + /*! Memory chunk size. */ + unsigned long chunk_size; + + /*! Memory chunk size in alternate format (2^x). */ + unsigned long chunk_order; + + /*! Current cmblock size. */ + unsigned long cmblk_size; + + /*! Logical address of cmblock. */ + unsigned long cmblk_begin; + + /*! Logical end address of cmblock. */ + unsigned long cmblk_end; + + /*! Array of logical chunk addresses. */ + unsigned long *chunk_ptr; + + /*! Maximum number of chunks to allocate. */ + int chunk_cnt_max; + + /*! Current number of chunks allocated. */ + int chunk_cnt; + +} cmblock_desc_t; + +static LIST_HEAD(cmblocks_list); + + +/*! + * \name Chunk tag mask. + * \anchor CT_xxx + * + * The lower two bits of the chunk address is used to tag the chunk + * with its current state. + */ +#define CT_MASK 0x3 + +/*! Chunk is untagged. */ +#define CT_UNTAGGED 0 + +/*! Chunk was discarded. */ +#define CT_DISCARDED 1 + +/*! Chunk is part of largest cmblock. */ +#define CT_LARGEST 2 + +/*! Chunk is part of current cmblock. */ +#define CT_CURRENT 3 + +/*! Set block as untagged. */ +#define CTAG_SET(_a, _t) \ + do { \ + (_a) &= ~CT_MASK; \ + (_a) |= _t; \ + } while (0) + +/*! Set block as untagged. */ +#define CTAG_GET(_a) \ + ((_a) & CT_MASK) + + +/******************************************************************************* + * Private Functions + ******************************************************************************/ + +/*! + * \brief Find largest contiguous memory block. + * + * Find largest contiguous memory block from a pool of memory chunks. + * + * Assembly stops if a cmblock of the requested cmblock size has been + * obtained. + * + * The lower two address bits of the memory chunks are encoded as a + * tag according to \ref CT_xxx. + * + * \param [in] cmbd cmblock descriptor. + * + * \return Always 0. + */ +static int +find_largest_cmblock(cmblock_desc_t *cmbd) +{ + int i, j, chunks, found; + unsigned long b, e, a; + unsigned long *cptr; + + /* Convenience variable */ + chunks = cmbd->chunk_cnt; + cptr = cmbd->chunk_ptr; + + /* Clear all chunk tags */ + for (i = 0; i < chunks; i++) { + CTAG_SET(cptr[i], CT_UNTAGGED); + } + for (i = 0; i < chunks && cmbd->cmblk_size < cmbd->req_size; i++) { + /* First chunk must be an untagged chunk */ + if (CTAG_GET(cptr[i]) == CT_UNTAGGED) { + /* Initial cmblock size is the chunk size */ + b = cptr[i]; + e = b + cmbd->chunk_size; + CTAG_SET(cptr[i], CT_CURRENT); + /* Loop looking for adjacent chunks */ + do { + found = 0; + for (j = i + 1; j < chunks && (e - b) < cmbd->req_size; j++) { + a = cptr[j]; + /* Check untagged chunks only */ + if (CTAG_GET(a) == CT_UNTAGGED) { + if (a == (b - cmbd->chunk_size)) { + /* Found adjacent chunk below current cmblock */ + CTAG_SET(cptr[j], CT_CURRENT); + b = a; + found = 1; + } else if (a == e) { + /* Found adjacent chunk above current cmblock */ + CTAG_SET(cptr[j], CT_CURRENT); + e += cmbd->chunk_size; + found = 1; + } + } + } + } while (found); + /* Now check the size of the assembled memory block */ + if ((e - b) > cmbd->cmblk_size) { + /* The current block is largest so far */ + cmbd->cmblk_begin = b; + cmbd->cmblk_end = e; + cmbd->cmblk_size = e - b; + /* Re-tag current and previous largest cmblock */ + for (j = 0; j < chunks; j++) { + if (CTAG_GET(cptr[j]) == CT_CURRENT) { + /* Tag current cmblock as the largest */ + CTAG_SET(cptr[j], CT_LARGEST); + } else if (CTAG_GET(cptr[j]) == CT_LARGEST) { + /* Discard previous largest cmblock */ + CTAG_SET(cptr[j], CT_DISCARDED); + } + } + } else { + /* Discard all chunks in current cmblock */ + for (j = 0; j < chunks; j++) { + if (CTAG_GET(cptr[j]) == CT_CURRENT) { + CTAG_SET(cptr[j], CT_DISCARDED); + } + } + } + } + } + return 0; +} + +/*! + * \brief Allocate memory chunks and add them to the pool. + * + * Memory chunks are allocated using the kernel page allocator. + * + * \param [in] cmbd - cmblock descriptor. + * \param [in] chunks - Number of memory chunks to allocate. + * + * \return 0 if no errors, otherwise -1. + */ +static int +alloc_mem_chunks(cmblock_desc_t *cmbd, int chunks) +{ + int i, start; + unsigned long addr; + + if (cmbd->chunk_cnt + chunks > cmbd->chunk_cnt_max) { + printk("PGMEM: No more memory chunks\n"); + return -1; + } + start = cmbd->chunk_cnt; + cmbd->chunk_cnt += chunks; + for (i = start; i < cmbd->chunk_cnt; i++) { + /* Get chunk from kernel allocator */ + addr = __get_free_pages(GFP_KERNEL | GFP_DMA32, cmbd->chunk_order); + PGMEM_TRACE("."); + if (addr) { + cmbd->chunk_ptr[i] = addr; + } else { + printk("PGMEM: Page memory allocation failed\n"); + return -1; + } + } + return 0; +} + +/*! + * \brief Allocate large physically contiguous memory block. + * + * If we cannot allocate a sufficiently large block of contiguous + * memory from the kernel, then we simply keep allocating smaller + * chunks until we can assemble a contiguous block of the desired + * size. + * + * When maximum amount of system memory has been allocated without the + * successful assembly of a contiguous memory block, the allocation + * function will return the largest contiguous block found so far. It + * is then up to the calling function to decide whether this amount is + * sufficient to proceed. + * + * \param [in] size Requested memory block size. + * \param [in] chunk_size Assemble cmblock from chunks of this size. + * + * \return Pointer to cmblock descriptor, or NULL if error. + */ +static cmblock_desc_t * +cmblock_alloc(size_t size, size_t chunk_size) +{ + cmblock_desc_t *cmbd; + int i, chunk_ptr_size; + unsigned long page_addr; + struct sysinfo si; + + /* Sanity check */ + if (size == 0 || chunk_size == 0) { + return NULL; + } + + /* Allocate an initialize memory cmblock descriptor */ + if ((cmbd = kmalloc(sizeof(cmblock_desc_t), GFP_KERNEL)) == NULL) { + return NULL; + } + memset(cmbd, 0, sizeof(*cmbd)); + cmbd->req_size = size; + cmbd->chunk_size = PAGE_ALIGN(chunk_size); + while ((PAGE_SIZE << cmbd->chunk_order) < cmbd->chunk_size) { + cmbd->chunk_order++; + } + + /* Determine the maximum possible number of memory chunks */ + si_meminfo(&si); + cmbd->chunk_cnt_max = (si.totalram << PAGE_SHIFT) / cmbd->chunk_size; + chunk_ptr_size = cmbd->chunk_cnt_max * sizeof(unsigned long); + + /* Allocate an initialize memory chunk pool */ + cmbd->chunk_ptr = kmalloc(chunk_ptr_size, GFP_KERNEL); + if (cmbd->chunk_ptr == NULL) { + kfree(cmbd); + return NULL; + } + memset(cmbd->chunk_ptr, 0, chunk_ptr_size); + + /* Allocate minimum number of memory chunks */ + (void)alloc_mem_chunks(cmbd, cmbd->req_size / cmbd->chunk_size); + + /* Allocate more chunks until we have a complete cmblock */ + do { + find_largest_cmblock(cmbd); + PGMEM_TRACE("o"); + if (cmbd->cmblk_size >= cmbd->req_size) { + break; + } + } while (alloc_mem_chunks(cmbd, 8) == 0); + + /* Reserve all pages in the cmblock and free unused chunks */ + for (i = 0; i < cmbd->chunk_cnt; i++) { + if (CTAG_GET(cmbd->chunk_ptr[i]) == CT_LARGEST) { + CTAG_SET(cmbd->chunk_ptr[i], CT_UNTAGGED); + for (page_addr = cmbd->chunk_ptr[i]; + page_addr < cmbd->chunk_ptr[i] + cmbd->chunk_size; + page_addr += PAGE_SIZE) { + SetPageReserved(virt_to_page((void *)page_addr)); + } + } else if (cmbd->chunk_ptr[i]) { + CTAG_SET(cmbd->chunk_ptr[i], CT_UNTAGGED); + free_pages(cmbd->chunk_ptr[i], cmbd->chunk_order); + PGMEM_TRACE("x"); + cmbd->chunk_ptr[i] = 0; + } + } + PGMEM_TRACE("O\n"); + return cmbd; +} + +/*! + * \brief Free cmblock and associated resources. + * + * Free all memory chunks and other associated resources associated + * with a contiguous memory block. + * + * See alse \ref cmblock_alloc. + * + * \param [in] cmbd Command block descriptor to free. + * + * \return Nothing. + */ +static void +cmblock_free(cmblock_desc_t *cmbd) +{ + int i; + unsigned long page_addr; + + if (cmbd->chunk_ptr) { + for (i = 0; i < cmbd->chunk_cnt; i++) { + if (cmbd->chunk_ptr[i]) { + for (page_addr = cmbd->chunk_ptr[i]; + page_addr < cmbd->chunk_ptr[i] + cmbd->chunk_size; + page_addr += PAGE_SIZE) { + ClearPageReserved(virt_to_page((void *)page_addr)); + } + free_pages(cmbd->chunk_ptr[i], cmbd->chunk_order); + PGMEM_TRACE("X"); + } + } + kfree(cmbd->chunk_ptr); + kfree(cmbd); + } +} + + +/******************************************************************************* + * Public Functions + ******************************************************************************/ + +void * +ngbde_pgmem_alloc(size_t size, gfp_t flags) +{ + cmblock_desc_t *cmbd; + size_t chunk_size; + + chunk_size = size; + + if (pgmem_chunk_size > 0) { + chunk_size = pgmem_chunk_size * ONE_KB; + } + + if (chunk_size > MEM_CHUNK_SIZE_MAX) { + chunk_size = MEM_CHUNK_SIZE_DEFAULT; + } + + if (pgmem_debug) { + printk("PGMEM: Allocate %d MB in %d KB chunks\n", + (int)(size / ONE_MB), (int)(chunk_size / ONE_KB)); + } + + if ((cmbd = cmblock_alloc(size, chunk_size)) == NULL) { + return NULL; + } + if (cmbd->cmblk_size < size) { + /* If we didn't get the full size then forget it */ + cmblock_free(cmbd); + return NULL; + } + list_add(&cmbd->list, &cmblocks_list); + return (void *)cmbd->cmblk_begin; +} + +int +ngbde_pgmem_free(void *ptr) +{ + struct list_head *pos; + + list_for_each(pos, &cmblocks_list) { + cmblock_desc_t *cmbd = list_entry(pos, cmblock_desc_t, list); + if (ptr == (void *)cmbd->cmblk_begin) { + list_del(&cmbd->list); + cmblock_free(cmbd); + return 0; + } + } + return -1; +} + +void +ngbde_pgmem_free_all(void) +{ + struct list_head *pos, *tmp; + + list_for_each_safe(pos, tmp, &cmblocks_list) { + cmblock_desc_t *cmbd = list_entry(pos, cmblock_desc_t, list); + list_del(&cmbd->list); + cmblock_free(cmbd); + } +} diff --git a/platform/broadcom/saibcm-modules/sdklt/linux/bde/ngbde_pio.c b/platform/broadcom/saibcm-modules/sdklt/linux/bde/ngbde_pio.c new file mode 100644 index 00000000000..cab094a2fec --- /dev/null +++ b/platform/broadcom/saibcm-modules/sdklt/linux/bde/ngbde_pio.c @@ -0,0 +1,97 @@ +/*! \file ngbde_pio.c + * + * API for managing and accessing memory-mapped I/O for switch + * registers. + * + */ +/* + * $Copyright: Copyright 2018-2020 Broadcom. All rights reserved. + * The term 'Broadcom' refers to Broadcom Inc. and/or its subsidiaries. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * version 2 as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * A copy of the GNU General Public License version 2 (GPLv2) can + * be found in the LICENSES folder.$ + */ + +#include + +void * +ngbde_pio_map(void *devh, phys_addr_t addr, phys_addr_t size) +{ + struct ngbde_dev_s *sd = (struct ngbde_dev_s *)devh; + + if (sd->pio_mem) { + if (addr == sd->pio_win.addr && size == sd->pio_win.size) { + /* Already mapped */ + return sd->pio_mem; + } + ngbde_pio_unmap(devh); + } + + sd->pio_mem = ioremap_nocache(addr, size); + + if (sd->pio_mem) { + /* Save mapped resources */ + sd->pio_win.addr = addr; + sd->pio_win.size = size; + } else { + printk(KERN_WARNING "%s: Unable to map address 0x%08lu\n", + MOD_NAME, (unsigned long)addr); + } + + return sd->pio_mem; +} + +void +ngbde_pio_unmap(void *devh) +{ + struct ngbde_dev_s *sd = (struct ngbde_dev_s *)devh; + + if (sd->pio_mem) { + iounmap(sd->pio_mem); + sd->pio_mem = NULL; + } +} + +void +ngbde_pio_cleanup(void) +{ + struct ngbde_dev_s *swdev, *sd; + unsigned int num_swdev, idx; + + ngbde_swdev_get_all(&swdev, &num_swdev); + + for (idx = 0; idx < num_swdev; idx++) { + sd = ngbde_swdev_get(idx); + ngbde_pio_unmap(sd); + } +} + +void +ngbde_pio_write32(void *devh, uint32_t offs, uint32_t val) +{ + struct ngbde_dev_s *sd = (struct ngbde_dev_s *)devh; + + if (sd->pio_mem) { + NGBDE_IOWRITE32(val, sd->pio_mem + offs); + } +} + +uint32_t +ngbde_pio_read32(void *devh, uint32_t offs) +{ + struct ngbde_dev_s *sd = (struct ngbde_dev_s *)devh; + + if (sd->pio_mem) { + return NGBDE_IOREAD32(sd->pio_mem + offs); + } + return 0; +} diff --git a/platform/broadcom/saibcm-modules/sdklt/linux/bde/ngbde_procfs.c b/platform/broadcom/saibcm-modules/sdklt/linux/bde/ngbde_procfs.c new file mode 100644 index 00000000000..f99339a5b0d --- /dev/null +++ b/platform/broadcom/saibcm-modules/sdklt/linux/bde/ngbde_procfs.c @@ -0,0 +1,120 @@ +/*! \file ngbde_procfs.c + * + * + * + */ +/* + * $Copyright: Copyright 2018-2020 Broadcom. All rights reserved. + * The term 'Broadcom' refers to Broadcom Inc. and/or its subsidiaries. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * version 2 as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * A copy of the GNU General Public License version 2 (GPLv2) can + * be found in the LICENSES folder.$ + */ + +#include + +static int +proc_show(struct seq_file *m, void *v) +{ + struct ngbde_dev_s *swdev; + unsigned int num_swdev, idx; + struct ngbde_dmamem_s *dmamem; + unsigned int pool; + unsigned int dma_pools; + char *dma_str; + + ngbde_swdev_get_all(&swdev, &num_swdev); + + seq_printf(m, "Broadcom Device Enumerator (%s)\n", MOD_NAME); + + seq_printf(m, "Found %d switch device(s):\n", num_swdev); + for (idx = 0; idx < num_swdev; idx++) { + if (swdev->inactive) { + seq_printf(m, "%d:removed\n", idx); + continue; + } + seq_printf(m, "%d:%04x:%04x:%02x,%s(%d)\n", idx, + swdev->vendor_id, swdev->device_id, swdev->revision, + swdev->use_msi ? "MSI" : "IRQ", swdev->irq_line); + } + + seq_printf(m, "DMA pools:\n"); + for (idx = 0; idx < num_swdev; idx++) { + seq_printf(m, "%d", idx); + dma_pools = 0; + for (pool = 0; pool < NGBDE_NUM_DMAPOOL_MAX; pool++) { + dmamem = &swdev[idx].dmapool[pool].dmamem; + dma_str = "unknown"; + if (dmamem->type == NGBDE_DMA_T_NONE) { + /* Skip empty DMA pools */ + continue; + } else if (dmamem->type == NGBDE_DMA_T_KAPI) { + dma_str = "kapi"; + } else if (dmamem->type == NGBDE_DMA_T_PGMEM) { + dma_str = "pgmem"; + } + seq_printf(m, ":%dMB@0x%08lx(%s)", + (int)(dmamem->size / ONE_MB), + (unsigned long)dmamem->baddr, dma_str); + dma_pools++; + } + if (dma_pools == 0) { + seq_printf(m, ":none"); + } + seq_printf(m, "\n"); + } + + return 0; +} + +static int +proc_open(struct inode *inode, struct file *file) +{ + return single_open(file, proc_show, NULL); +} + +static int +proc_release(struct inode *inode, struct file *file) +{ + return single_release(inode, file); +} + +static struct file_operations proc_fops = { + owner: THIS_MODULE, + open: proc_open, + read: seq_read, + llseek: seq_lseek, + release: proc_release, +}; + +int +ngbde_procfs_init(void) +{ + struct proc_dir_entry *entry; + + PROC_CREATE(entry, MOD_NAME, 0666, NULL, &proc_fops); + + if (entry == NULL) { + printk(KERN_ERR "ngbde: proc_create failed\n"); + return -1; + } + + return 0; +} + +int +ngbde_procfs_cleanup(void) +{ + remove_proc_entry(MOD_NAME, NULL); + + return 0; +} diff --git a/platform/broadcom/saibcm-modules/sdklt/linux/bde/ngbde_swdev.c b/platform/broadcom/saibcm-modules/sdklt/linux/bde/ngbde_swdev.c new file mode 100644 index 00000000000..60d328ad252 --- /dev/null +++ b/platform/broadcom/saibcm-modules/sdklt/linux/bde/ngbde_swdev.c @@ -0,0 +1,79 @@ +/*! \file ngbde_swdev.c + * + * + * + */ +/* + * $Copyright: Copyright 2018-2020 Broadcom. All rights reserved. + * The term 'Broadcom' refers to Broadcom Inc. and/or its subsidiaries. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * version 2 as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * A copy of the GNU General Public License version 2 (GPLv2) can + * be found in the LICENSES folder.$ + */ + +#include + +/* Switch devices */ +static struct ngbde_dev_s swdevs[NGBDE_NUM_SWDEV_MAX]; + +/* Number of probed switch devices */ +static unsigned int num_swdev; + +int +ngbde_swdev_add(struct ngbde_dev_s *nd) +{ + unsigned int idx; + + /* Look for existing slot */ + for (idx = 0; idx < num_swdev; idx++) { + if (swdevs[idx].bus_no == nd->bus_no && + swdevs[idx].slot_no == nd->slot_no) { + if (swdevs[idx].inactive) { + memcpy(&swdevs[idx], nd, sizeof(swdevs[0])); + return 0; + } + /* Active device in this slot already? */ + printk(KERN_WARNING "%s: Device exists\n", + MOD_NAME); + return -EBUSY; + } + } + + /* Add new device */ + if (num_swdev >= NGBDE_NUM_SWDEV_MAX) { + return -ENOMEM; + } + memcpy(&swdevs[num_swdev], nd, sizeof(swdevs[0])); + ++num_swdev; + return 0; +} + +struct ngbde_dev_s * +ngbde_swdev_get(int kdev) +{ + if ((unsigned int)kdev < num_swdev) { + return &swdevs[kdev]; + } + return NULL; +} + +int +ngbde_swdev_get_all(struct ngbde_dev_s **nd, unsigned int *num_nd) +{ + if (nd) { + *nd = swdevs; + } + if (num_nd) { + *num_nd = num_swdev; + } + return 0; +} diff --git a/platform/broadcom/saibcm-modules/sdklt/linux/include/lkm/lkm.h b/platform/broadcom/saibcm-modules/sdklt/linux/include/lkm/lkm.h new file mode 100644 index 00000000000..c0ba0a31976 --- /dev/null +++ b/platform/broadcom/saibcm-modules/sdklt/linux/include/lkm/lkm.h @@ -0,0 +1,126 @@ +/*! \file lkm.h + * + * + * + */ +/* + * $Copyright: Copyright 2018-2020 Broadcom. All rights reserved. + * The term 'Broadcom' refers to Broadcom Inc. and/or its subsidiaries. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * version 2 as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * A copy of the GNU General Public License version 2 (GPLv2) can + * be found in the LICENSES folder.$ + */ + +#ifndef LKM_H +#define LKM_H + +#include +#include +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,20) +#error Kernel too old +#endif +#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,1,0) +#include +#endif +#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,10,0) +#include +#endif +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,39) +#include +#endif +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +#ifdef CONFIG_DEVFS_FS +#include +#endif + +/* Compatibility Macros */ + +#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,10,0) +#define PROC_CREATE(_entry, _name, _acc, _path, _fops) \ + do { \ + _entry = proc_create(_name, _acc, _path, _fops); \ + } while (0) + +#define PROC_CREATE_DATA(_entry, _name, _acc, _path, _fops, _data) \ + do { \ + _entry = proc_create_data(_name, _acc, _path, _fops, _data); \ + } while (0) + +#define PROC_PDE_DATA(_node) PDE_DATA(_node) +#else +#define PROC_CREATE(_entry, _name, _acc, _path, _fops) \ + do { \ + _entry = create_proc_entry(_name, _acc, _path); \ + if (_entry) { \ + _entry->proc_fops = _fops; \ + } \ + } while (0) + +#define PROC_CREATE_DATA(_entry, _name, _acc, _path, _fops, _data) \ + do { \ + _entry = create_proc_entry(_name, _acc, _path); \ + if (_entry) { \ + _entry->proc_fops = _fops; \ + _entry->data=_data; \ + } \ + } while (0) + +#define PROC_PDE_DATA(_node) PROC_I(_node)->pde->data +#endif + +#if LINUX_VERSION_CODE < KERNEL_VERSION(4,15,0) +#define timer_arg(var, context, timer_fieldname) \ + (typeof(var))(context) +#define timer_context_t unsigned long +#else +#define timer_context_t struct timer_list * +#define timer_arg(var, context, timer_fieldname) \ + from_timer(var, context, timer_fieldname) +#endif + +#ifndef setup_timer +#define setup_timer(timer, fn, data) \ + timer_setup(timer, fn, 0) +#endif + +#if LINUX_VERSION_CODE < KERNEL_VERSION(4,6,0) +static inline void page_ref_inc(struct page *page) +{ + atomic_inc(&page->_count); +} + +static inline void page_ref_dec(struct page *page) +{ + atomic_dec(&page->_count); +} +#endif + +#endif /* LKM_H */ diff --git a/platform/broadcom/saibcm-modules/sdklt/linux/include/lkm/ngbde_ioctl.h b/platform/broadcom/saibcm-modules/sdklt/linux/include/lkm/ngbde_ioctl.h new file mode 100644 index 00000000000..b90486ce06f --- /dev/null +++ b/platform/broadcom/saibcm-modules/sdklt/linux/include/lkm/ngbde_ioctl.h @@ -0,0 +1,345 @@ +/*! \file ngbde_ioctl.h + * + * NGBDE device I/O control definitions. + * + * This file is intended for use in both kernel mode and user mode. + * + * IMPORTANT! + * All shared structures must be properly 64-bit aligned. + * + */ +/* + * $Copyright: Copyright 2018-2020 Broadcom. All rights reserved. + * The term 'Broadcom' refers to Broadcom Inc. and/or its subsidiaries. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * version 2 as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * A copy of the GNU General Public License version 2 (GPLv2) can + * be found in the LICENSES folder.$ + */ + +#ifndef NGBDE_IOCTL_H +#define NGBDE_IOCTL_H + +#include +#include + +/*! Must be updated if backward compatibility is broken. */ +#define NGBDE_IOC_VERSION 2 + +/*! LUBDE IOCTL command magic. */ +#define NGBDE_IOC_MAGIC 'L' + +/*! + * \name IOCTL commands for the NGBDE kernel module. + * \anchor NGBDE_IOC_xxx + * + * Note that we use __u64 for the IOCTL parameter size because + * sizeof(void *) is different between 32-bit and 64-bit code, and we + * need a 32-bit user mode application to generate the same IOCTL + * command codes as a 64-bit kernel when using the _IOW macro. + */ + +/*! \{ */ + +/*! Get kernel module information. */ +#define NGBDE_IOC_MOD_INFO _IOW(NGBDE_IOC_MAGIC, 0, __u64) + +/*! Get information about registered devices. */ +#define NGBDE_IOC_PROBE_INFO _IOW(NGBDE_IOC_MAGIC, 1, __u64) + +/*! Get detailed switch device information. */ +#define NGBDE_IOC_DEV_INFO _IOW(NGBDE_IOC_MAGIC, 2, __u64) + +/*! Get a physical memory address associated with a switch device. */ +#define NGBDE_IOC_PHYS_ADDR _IOW(NGBDE_IOC_MAGIC, 3, __u64) + +/*! Interrupt control command (see \ref NGBDE_ICTL_xxx). */ +#define NGBDE_IOC_INTR_CTRL _IOW(NGBDE_IOC_MAGIC, 4, __u64) + +/*! Add interrupt status/mask register for kernel to control. */ +#define NGBDE_IOC_IRQ_REG_ADD _IOW(NGBDE_IOC_MAGIC, 5, __u64) + +/*! Write to a shared interrupt mask register. */ +#define NGBDE_IOC_IRQ_MASK_WR _IOW(NGBDE_IOC_MAGIC, 6, __u64) + +/*! Map device registers in kernel space. */ +#define NGBDE_IOC_PIO_WIN_MAP _IOW(NGBDE_IOC_MAGIC, 7, __u64) + +/*! Map interrupt controller registers in kernel space. */ +#define NGBDE_IOC_IIO_WIN_MAP _IOW(NGBDE_IOC_MAGIC, 8, __u64) + +/*! Map PCI bridge registers in kernel space. */ +#define NGBDE_IOC_PAXB_WIN_MAP _IOW(NGBDE_IOC_MAGIC, 9, __u64) + +/*! Add interrupt ACK register for kernel to control. */ +#define NGBDE_IOC_INTR_ACK_REG_ADD _IOW(NGBDE_IOC_MAGIC, 10, __u64) + +/*! \} */ + +/*! IOCTL command return code for success. */ +#define NGBDE_IOC_SUCCESS 0 + +/*! IOCTL command return code for failure. */ +#define NGBDE_IOC_FAIL ((__u32)-1) + +/*! + * \name Device flags. + * \anchor NGBDE_DEV_F_xxx + */ + +/*! \{ */ + +/*! Message-signaled interrupts, PCI interrupts are operating in MSI mode. */ +#define NGBDE_DEV_F_MSI (1 << 0) + +/*! \} */ + +/*! + * \name Interrupt control commands. + * \anchor NGBDE_ICTL_xxx + */ + +/*! \{ */ + +/*! Connect interrupt handler. */ +#define NGBDE_ICTL_INTR_CONN 0 + +/*! Disconnect interrupt handler. */ +#define NGBDE_ICTL_INTR_DISC 1 + +/*! Wait for interrupt. */ +#define NGBDE_ICTL_INTR_WAIT 2 + +/*! Force waiting thread to return. */ +#define NGBDE_ICTL_INTR_STOP 3 + +/*! Clear list of interrupt status/mask registers. */ +#define NGBDE_ICTL_REGS_CLR 4 + +/*! \} */ + +/*! Kernel module information. */ +struct ngbde_ioc_mod_info_s { + + /*! IOCTL version used by kernel module. */ + __u16 version; +}; + +/*! Probing results. */ +struct ngbde_ioc_probe_info_s { + + /*! Number of switch devices. */ + __u16 num_swdev; +}; + +/*! Device information. */ +struct ngbde_ioc_dev_info_s { + + /*! Device type. */ + __u16 type; + + /*! Device flags (\ref NGBDE_DEV_F_xxx). */ + __u16 flags; + + /*! Vendor ID (typically the PCI vendor ID). */ + __u16 vendor_id; + + /*! Device ID (typically the PCI vendor ID). */ + __u16 device_id; + + /*! Device revision (typically the PCI device revision). */ + __u16 revision; + + /*! Device model (device-identification beyond PCI generic ID). */ + __u16 model; +}; + +/*! + * \name I/O resource types. + * \anchor NGBDE_IO_RSRC_xxx + */ + +/*! \{ */ + +/*! Memory-mapped I/O. */ +#define NGBDE_IO_RSRC_DEV_IO 0 + +/*! DMA memory pool. */ +#define NGBDE_IO_RSRC_DMA_MEM 1 + +/*! DMA memory pool as mapped by IOMMU. */ +#define NGBDE_IO_RSRC_DMA_BUS 2 + +/*! \} */ + +/*! + * \brief Resource ID (IOCTL input). + * + * This structure is used to query a physical address resource in the + * kernel module. The caller must provide a resource type (device I/O, + * DMA memory, etc.) and a resource instance number (e.g. a PCI BAR + * address will have multiple instances). + * + * Also see \ref ngbde_ioc_phys_addr_s. + */ +struct ngbde_ioc_rsrc_id_s { + + /*! Resource type (\ref NGBDE_IO_RSRC_xxx). */ + __u32 type; + + /*! Resource instance number. */ + __u32 inst; +}; + +/*! + * \brief Physical device address. + * + * This structure is returned in response to the \ref + * NGBDE_IOC_PHYS_ADDR command. The caller must identify the requested + * physical address using the \ref ngbde_ioc_rsrc_id_s structure. + */ +struct ngbde_ioc_phys_addr_s { + + /*! Physical address. */ + __u64 addr; + + /*! Resource size (in bytes). */ + __u32 size; +}; + +/*! Interrupt control operation */ +struct ngbde_ioc_intr_ctrl_s { + + /*! Interrupt instance for this device. */ + __u32 irq_num; + + /*! Interrupt control command. */ + __u32 cmd; +}; + +/*! Add interrupt register information. */ +struct ngbde_ioc_irq_reg_add_s { + + /*! Interrupt instance for this device. */ + __u32 irq_num; + + /*! Interrupt status register address offset. */ + __u32 status_reg; + + /*! Interrupt mask register address offset. */ + __u32 mask_reg; + + /*! Interrupt mask for interrupts handled by the kernel. */ + __u32 kmask; + + /*! Reserved for future use. */ + __u32 flags; +}; + +/*! + * \name Interrupt ACK register access flags. + * \anchor NGBDE_DEV_INTR_ACK_F_xxx + */ + +/*! \{ */ + +/*! ACK registers resides in PCI bridge I/O window. */ +#define NGBDE_DEV_INTR_ACK_F_PAXB (1 << 0) + +/*! \} */ + +/*! Add interrupt ACK register information. */ +struct ngbde_ioc_intr_ack_reg_add_s { + + /*! Interrupt instance for this device. */ + __u32 irq_num; + + /*! Interrupt ACK register address offset. */ + __u32 ack_reg; + + /*! Interrupt ACK value. */ + __u32 ack_val; + + /*! Flags to indicate ack_reg resides in PCI bridge window. */ + __u32 flags; +}; + +/*! Memory-mapped I/O window */ +struct ngbde_ioc_pio_win_s { + + /*! Physical address */ + __u64 addr; + + /*! Resource size */ + __u32 size; +}; + +/*! Interrupt mask register write */ +struct ngbde_ioc_irq_mask_wr_s { + + /*! Interrupt instance for this device. */ + __u32 irq_num; + + /*! Register offset. */ + __u32 offs; + + /*! Value to write. */ + __u32 val; +}; + +/*! IOCTL operation data. */ +union ngbde_ioc_op_s { + + /*! Get kernel module information. */ + struct ngbde_ioc_mod_info_s mod_info; + + /*! Get information about registered devices. */ + struct ngbde_ioc_probe_info_s probe_info; + + /*! Get detailed switch device information. */ + struct ngbde_ioc_dev_info_s dev_info; + + /*! Resource ID (input). */ + struct ngbde_ioc_rsrc_id_s rsrc_id; + + /*! Get a physical memory address associated with a switch device. */ + struct ngbde_ioc_phys_addr_s phys_addr; + + /*! Interrupt control command (see \ref NGBDE_ICTL_xxx). */ + struct ngbde_ioc_intr_ctrl_s intr_ctrl; + + /*! Add interrupt status/mask register for kernel to control. */ + struct ngbde_ioc_irq_reg_add_s irq_reg_add; + + /*! Add interrupt ACK register for kernel to control. */ + struct ngbde_ioc_intr_ack_reg_add_s intr_ack_reg_add; + + /*! Write to a shared interrupt mask register. */ + struct ngbde_ioc_irq_mask_wr_s irq_mask_wr; + + /*! Map device registers in kernel space. */ + struct ngbde_ioc_pio_win_s pio_win; +}; + +/*! IOCTL command message. */ +typedef struct ngbde_ioc_cmd_s { + + /*! Device handle. */ + __u32 devid; + + /*! Return code (0 means success). */ + __u32 rc; + + /*! IOCTL operation. */ + union ngbde_ioc_op_s op; +} ngbde_ioc_cmd_t; + +#endif /* NGBDE_IOCTL_H */ diff --git a/platform/broadcom/saibcm-modules/sdklt/linux/include/lkm/ngbde_kapi.h b/platform/broadcom/saibcm-modules/sdklt/linux/include/lkm/ngbde_kapi.h new file mode 100644 index 00000000000..142aa63b572 --- /dev/null +++ b/platform/broadcom/saibcm-modules/sdklt/linux/include/lkm/ngbde_kapi.h @@ -0,0 +1,169 @@ +/*! \file ngbde_kapi.h + * + * NGBDE kernel API. + * + * This file is intended for use by other kernel modules relying on the BDE. + * + */ +/* + * $Copyright: Copyright 2018-2020 Broadcom. All rights reserved. + * The term 'Broadcom' refers to Broadcom Inc. and/or its subsidiaries. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * version 2 as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * A copy of the GNU General Public License version 2 (GPLv2) can + * be found in the LICENSES folder.$ + */ + +#ifndef NGBDE_KAPI_H +#define NGBDE_KAPI_H + +#include + +/*! Maximum number of switch devices supported. */ +#ifndef NGBDE_NUM_SWDEV_MAX +#define NGBDE_NUM_SWDEV_MAX 16 +#endif + +/*! + * \brief Get Linux PCI device handle for a switch device. + * + * \param [in] kdev Device number. + * + * \return Linux PCI device handle or NULL if unavailable. + */ +extern struct pci_dev * +ngbde_kapi_pci_dev_get(int kdev); + +/*! + * \brief Get Linux kernel device handle for a switch device. + * + * \param [in] kdev Device number. + * + * \return Linux kernel device handle or NULL if unavailable. + */ +extern struct device * +ngbde_kapi_dma_dev_get(int kdev); + +/*! + * \brief Convert DMA bus address to virtual address. + * + * This API will convert a physical DMA bus address to a kernel + * virtual address for a memory location that belongs to one of the + * DMA memory pools allocated by the BDE module. + * + * \param [in] kdev Device number. + * \param [in] baddr Physical DMA bus address for this device. + * + * \return Virtual kernel address or NULL on error. + */ +void * +ngbde_kapi_dma_bus_to_virt(int kdev, dma_addr_t baddr); + +/*! + * \brief Convert virtual address to DMA bus address. + * + * This API will convert a kernel virtual address to a physical DMA + * bus address for a memory location that belongs to one of the DMA + * memory pools allocated by the BDE module. + * + * \param [in] kdev Device number. + * \param [in] vaddr Virtual kernel address. + * + * \return Physical DMA bus address for this device or 0 on error. + */ +dma_addr_t +ngbde_kapi_dma_virt_to_bus(int kdev, void *vaddr); + +/*! + * \brief Write a memory-mapped register from kernel driver. + * + * \param [in] kdev Device number. + * \param [in] offs Register address offset. + * \param [in] val Value to write to register. + * + * \return Nothing. + */ +extern void +ngbde_kapi_pio_write32(int kdev, uint32_t offs, uint32_t val); + +/*! + * \brief Read a memory-mapped register from kernel driver. + * + * \param [in] kdev Device number. + * \param [in] offs Register address offset. + * + * \return Value read from register. + */ +extern uint32_t +ngbde_kapi_pio_read32(int kdev, uint32_t offs); + +/*! + * \brief Get base address fo memory-mapped I/O memory. + * + * The lgical base address returned can be used with ioread32, etc. + * + * \param [in] kdev Device number. + * + * \return Logical base address or NULL if unavailable. + */ +extern void * +ngbde_kapi_pio_membase(int kdev); + +/*! + * \brief Install kernel mode interrupt handler. + * + * \param [in] kdev Device number. + * \param [in] irq_num MSI interrupt number. + * \param [in] isr_func Interrupt handler function. + * \param [in] isr_data Interrupt handler context. + * + * \retval 0 No errors + */ +extern int +ngbde_kapi_intr_connect(int kdev, unsigned int irq_num, + int (*isr_func)(void *), void *isr_data); + +/*! + * \brief Uninstall kernel mode interrupt handler. + * + * \param [in] kdev Device number. + * \param [in] irq_num MSI interrupt number. + * + * \retval 0 No errors + */ +extern int +ngbde_kapi_intr_disconnect(int kdev, unsigned int irq_num); + +/*! + * \brief Write shared interrupt mask register. + * + * This function is used by an interrupt handler when a shared + * interrupt mask register needs to be updated. + * + * Note that the mask register to access is referenced by the + * corrsponding status register. This is because the mask register may + * be different depending on the host CPU interface being used + * (e.g. PCI vs. AXI). On the other hand, the status register is the + * same irrespective of the host CPU interface. + * + * \param [in] kdev Device number. + * \param [in] irq_num Interrupt number (MSI vector). + * \param [in] status_reg Corresponding interrupt status register offset. + * \param [in] mask_val New value to write to mask register. + * + * \retval 0 No errors + * \retval -1 Something went wrong. + */ +extern int +ngbde_kapi_intr_mask_write(int kdev, unsigned int irq_num, + uint32_t status_reg, uint32_t mask_val); + +#endif /* NGBDE_KAPI_H */ diff --git a/platform/broadcom/saibcm-modules/sdklt/linux/include/lkm/ngknet_dev.h b/platform/broadcom/saibcm-modules/sdklt/linux/include/lkm/ngknet_dev.h new file mode 100644 index 00000000000..74d3d5b350b --- /dev/null +++ b/platform/broadcom/saibcm-modules/sdklt/linux/include/lkm/ngknet_dev.h @@ -0,0 +1,408 @@ +/*! \file ngknet_dev.h + * + * NGKNET device definitions. + * + * This file is intended for use in both kernel mode and user mode. + * + * IMPORTANT! + * All shared structures must be properly 64-bit aligned. + * + */ +/* + * $Copyright: Copyright 2018-2020 Broadcom. All rights reserved. + * The term 'Broadcom' refers to Broadcom Inc. and/or its subsidiaries. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * version 2 as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * A copy of the GNU General Public License version 2 (GPLv2) can + * be found in the LICENSES folder.$ + */ + +#ifndef NGKNET_DEV_H +#define NGKNET_DEV_H + +#include + +/*! Device name length */ +#define NGKNET_DEV_NAME_MAX 16 + +/*! Maximum number of virtual network devices */ +#ifndef NGKNET_NETIF_MAX +#define NUM_VDEV_MAX 128 +#else +#define NUM_VDEV_MAX NGKNET_NETIF_MAX +#endif + +/*! Maximum number of filters */ +#ifndef NGKNET_FILTER_MAX +#define NUM_FILTER_MAX 128 +#else +#define NUM_FILTER_MAX NGKNET_FILTER_MAX +#endif + +/*! + * \brief System network interface + * + * Network interface types: + * + * NGKNET_NETIF_T_VLAN + * Transmits to this interface will go to ingress PIPE of switch + * CPU port using specified VLAN ID. Packet will be switched. + * + * NGKNET_NETIF_T_PORT + * Transmits to this interface will go to unmodified to specified + * physical switch port. All switching logic is bypassed. Meta data + * should be provided when this interface is created. + * + * NGKNET_NETIF_T_META + * Transmits to this interface will be done using raw meta data + * as DMA descriptors. + * + * Network interface flags: + * + * NGKNET_NETIF_F_RCPU_ENCAP + * Use RCPU encapsulation for packets that enter and exit this + * interface. + * + * NGKNET_NETIF_F_ADD_TAG + * Add VLAN tag to packets sent directly to physical port. + * + * NGKNET_NETIF_F_BIND_CHAN + * Bind this interface to a Rx channel. + */ +/*! Max network interface name length */ +#define NGKNET_NETIF_NAME_MAX 16 +/*! Max network interface meta bytes */ +#define NGKNET_NETIF_META_MAX 16 +/*! Max netif user data in bytes */ +#define NGKNET_NETIF_USER_DATA 64 + +/*! Send packets to switch */ +#define NGKNET_NETIF_T_VLAN 0 +/*! Send packets to port */ +#define NGKNET_NETIF_T_PORT 1 +/*! Send packets with matadata attached */ +#define NGKNET_NETIF_T_META 2 + +/*! Send packets with RCPU encapsulation */ +#define NGKNET_NETIF_F_RCPU_ENCAP (1U << 0) +/*! Send packets with vlan tag */ +#define NGKNET_NETIF_F_ADD_TAG (1U << 1) +/*! Bind network interface to Rx channel */ +#define NGKNET_NETIF_F_BIND_CHAN (1U << 2) + +/*! + * \brief Network interface description. + */ +typedef struct ngknet_netif_s { + /*! This network interface ID */ + uint16_t id; + + /*! Next network interface ID */ + uint16_t next; + + /*! Network interface type */ + uint16_t type; + + /*! Network interface flags */ + uint16_t flags; + + /*! Network interface VLAN ID */ + uint16_t vlan; + + /*! Network interface MAC address */ + uint8_t macaddr[6]; + + /*! Network interface MTU */ + uint32_t mtu; + + /*! Network interface bound to channel */ + uint32_t chan; + + /*! Network interface name */ + char name[NGKNET_NETIF_NAME_MAX]; + + /*! Metadata offset from Ethernet header */ + uint16_t meta_off; + + /*! Metadata length */ + uint16_t meta_len; + + /*! Metadata used to send packets to physical port */ + uint8_t meta_data[NGKNET_NETIF_META_MAX]; + + /*! User data gotten back through callbacks */ + uint8_t user_data[NGKNET_NETIF_USER_DATA]; +} ngknet_netif_t; + +/*! + * \brief Packet filters + * + * Filters work like software TCAMs where a mask is applied to the + * source data, and the result is then compared to the filter data. + * + * Filters are checked in priority order with the lowest priority + * values being checked first (i.e. 0 is the highest priority). + * + * Filter types: + * + * NGKNET_FILTER_T_RX_PKT + * Filter data and mask are applied to the Rx DMA control block + * as well as to the Rx packet contents. + * + * Destination types: + * + * NGKNET_FILTER_DEST_T_NULL + * Packet is dropped. + * + * NGKNET_FILTER_DEST_T_NETIF + * Packet is sent to network interface with ID . + * + * NGKNET_FILTER_DEST_T_VNET + * Packet is sent to VNET in user space. + * + * Filter flags: + * + * NGKNET_FILTER_F_ANY_DATA + * When this flags is set the filter will match any packet on + * the associated unit. + * + * NGKNET_FILTER_F_STRIP_TAG + * Strip VLAN tag before packet is sent to destination. + */ +/*! Roundup to word */ +#define NGKNET_BYTES2WORDS(bytes) ((bytes + 3) / 4) + +/*! Max filter description length */ +#define NGKNET_FILTER_DESC_MAX 32 +/*! Max filter bytes size */ +#define NGKNET_FILTER_BYTES_MAX 256 +/*! Max filter words size */ +#define NGKNET_FILTER_WORDS_MAX NGKNET_BYTES2WORDS(NGKNET_FILTER_BYTES_MAX) +/*! Max filter user data in bytes */ +#define NGKNET_FILTER_USER_DATA 64 + +/*! Filter to Rx */ +#define NGKNET_FILTER_T_RX_PKT 1 + +/*! Drop packet */ +#define NGKNET_FILTER_DEST_T_NULL 0 +/*! Send packet to netif */ +#define NGKNET_FILTER_DEST_T_NETIF 1 +/*! Send packet to VNET */ +#define NGKNET_FILTER_DEST_T_VNET 2 +/*! Send packet to kernel callback function (BCMPKT_DEST_T_CALLBACK) */ +#define NGKNET_FILTER_DEST_T_CB 3 + +/*! Match any data */ +#define NGKNET_FILTER_F_ANY_DATA (1U << 0) +/*! Strip vlan tag */ +#define NGKNET_FILTER_F_STRIP_TAG (1U << 1) +/*! Match Rx channel */ +#define NGKNET_FILTER_F_MATCH_CHAN (1U << 2) +/*! Filter created with raw metadata */ +#define NGKNET_FILTER_F_RAW_PMD (1U << 15) + +/*! + * \brief Filter description. + */ +typedef struct ngknet_filter_s { + /*! This filter ID */ + uint16_t id; + + /*! Next filter ID */ + uint16_t next; + + /*! Filter type. Refer to \ref NGKNET_FILTER_T_XXX. */ + uint16_t type; + + /*! Filter flags. Refer to \ref NGKNET_FILTER_F_XXX. */ + uint16_t flags; + + /*! Filter priority */ + uint32_t priority; + + /*! Filter belong to */ + uint32_t chan; + + /*! Filter description */ + char desc[NGKNET_FILTER_DESC_MAX]; + + /*! Destination type. Refer to \ref NGKNET_FILTER_DEST_T_XXX. */ + uint16_t dest_type; + + /*! Destination network interface ID */ + uint16_t dest_id; + + /*! Destination network interface protocol type */ + uint16_t dest_proto; + + /*! Mirror type */ + uint16_t mirror_type; + + /*! Mirror network interface ID */ + uint16_t mirror_id; + + /*! Mirror network interface protocol type */ + uint16_t mirror_proto; + + /*! Out band data offset */ + uint16_t oob_data_offset; + + /*! Out band data size */ + uint16_t oob_data_size; + + /*! Packet data offset */ + uint16_t pkt_data_offset; + + /*! Packet data size */ + uint16_t pkt_data_size; + + /*! Filtering data */ + union { + uint8_t b[NGKNET_FILTER_BYTES_MAX]; + uint32_t w[NGKNET_FILTER_WORDS_MAX]; + } data; + + /*! Filtering mask */ + union { + uint8_t b[NGKNET_FILTER_BYTES_MAX]; + uint32_t w[NGKNET_FILTER_WORDS_MAX]; + } mask; + + /*! User data gotten back through callbacks */ + uint8_t user_data[NGKNET_FILTER_USER_DATA]; +} ngknet_filter_t; + +/*! + * \brief Device configure structure. + */ +typedef struct ngknet_dev_cfg_s { + /*! Device name */ + char name[NGKNET_DEV_NAME_MAX]; + + /*! Device type string */ + char type_str[NGKNET_DEV_NAME_MAX]; + + /*! Device ID */ + uint32_t dev_id; + + /*! Device mode */ + dev_mode_t mode; + + /*! Number of groups */ + uint32_t nb_grp; + + /*! Bitmap of groups */ + uint32_t bm_grp; + + /*! Rx packet header size */ + uint32_t rx_ph_size; + + /*! Tx packet header size */ + uint32_t tx_ph_size; + + /*! Base network interface */ + ngknet_netif_t base_netif; +} ngknet_dev_cfg_t; + +/*! + * \brief Channel configure structure. + */ +typedef struct ngknet_chan_cfg_s { + /*! Channel number */ + int chan; + + /*! Number of descriptors */ + uint32_t nb_desc; + + /*! Rx buffer size */ + uint32_t rx_buf_size; + + /*! Channel control */ + uint32_t chan_ctrl; + /*! Packet_byte_swap */ +#define NGKNET_PKT_BYTE_SWAP (1 << 0) + /*! Non packet_byte_swap */ +#define NGKNET_OTH_BYTE_SWAP (1 << 1) + /*! Header_byte_swap */ +#define NGKNET_HDR_BYTE_SWAP (1 << 2) + + /*! Rx or Tx */ + int dir; + /*! Rx channel */ +#define NGKNET_RX_CHAN 0 + /*! Tx channel */ +#define NGKNET_TX_CHAN 1 +} ngknet_chan_cfg_t; + +/*! + * \brief RCPU header structure. + */ +struct ngknet_rcpu_hdr { + /*! Destination MAC address */ + uint8_t dst_mac[6]; + + /*! Source MAC address */ + uint8_t src_mac[6]; + + /*! VLAN TPID */ + uint16_t vlan_tpid; + + /*! VLAN TCI */ + uint16_t vlan_tci; + + /*! Ethernet type */ + uint16_t eth_type; + + /*! Packet signature */ + uint16_t pkt_sig; + + /*! Operation code */ + uint8_t op_code; + + /*! Flags */ + uint8_t flags; + + /*! Transaction number */ + uint16_t trans_id; + + /*! Packet data length */ + uint16_t data_len; + + /*! Reserved must be 0 */ + uint16_t rsvd0; + + /*! packet meta data length */ + uint8_t meta_len; + + /*! Transmission queue number */ + uint8_t queue_id; + + /*! Reserved must be 0 */ + uint16_t rsvd1; +}; + +/*! RCPU Rx operation */ +#define RCPU_OPCODE_RX 0x10 +/*! RCPU Tx operation */ +#define RCPU_OPCODE_TX 0x20 + +/*! RCPU purge flag */ +#define RCPU_FLAG_PURGE (1 << 0) +/*! RCPU pause flag */ +#define RCPU_FLAG_PAUSE (1 << 1) +/*! RCPU modhdr flag */ +#define RCPU_FLAG_MODHDR (1 << 2) +/*! RCPU bind queue flag */ +#define RCPU_FLAG_BIND_QUE (1 << 3) + +#endif /* NGKNET_DEV_H */ + diff --git a/platform/broadcom/saibcm-modules/sdklt/linux/include/lkm/ngknet_ioctl.h b/platform/broadcom/saibcm-modules/sdklt/linux/include/lkm/ngknet_ioctl.h new file mode 100644 index 00000000000..6da52c77819 --- /dev/null +++ b/platform/broadcom/saibcm-modules/sdklt/linux/include/lkm/ngknet_ioctl.h @@ -0,0 +1,112 @@ +/*! \file ngknet_ioctl.h + * + * NGKNET I/O control definitions. + * + * This file is intended for use in both kernel mode and user mode. + * + * IMPORTANT! + * All shared structures must be properly 64-bit aligned. + * + */ +/* + * $Copyright: Copyright 2018-2020 Broadcom. All rights reserved. + * The term 'Broadcom' refers to Broadcom Inc. and/or its subsidiaries. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * version 2 as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * A copy of the GNU General Public License version 2 (GPLv2) can + * be found in the LICENSES folder.$ + */ + +#ifndef NGKNET_IOCTL_H +#define NGKNET_IOCTL_H + +/*! Module information */ +#define NGKNET_MODULE_NAME "linux_ngknet" +#define NGKNET_MODULE_MAJOR 121 + +/*! Must be updated if backward compatibility is broken */ +#define NGKNET_IOC_VERSION 2 + +/*! Max number of input arguments */ +#define NGKNET_IOC_IARG_MAX 2 + +#define NGKNET_IOC_MAGIC 'K' + +#define NGKNET_VERSION_GET _IOR(NGKNET_IOC_MAGIC, 0xa0, unsigned int) +#define NGKNET_RX_RATE_LIMIT _IOWR(NGKNET_IOC_MAGIC, 0xa1, unsigned int) +#define NGKNET_DEV_INIT _IOWR(NGKNET_IOC_MAGIC, 0xb0, unsigned int) +#define NGKNET_DEV_DEINIT _IOWR(NGKNET_IOC_MAGIC, 0xb1, unsigned int) +#define NGKNET_DEV_SUSPEND _IOWR(NGKNET_IOC_MAGIC, 0xb2, unsigned int) +#define NGKNET_DEV_RESUME _IOWR(NGKNET_IOC_MAGIC, 0xb3, unsigned int) +#define NGKNET_DEV_VNET_WAIT _IOWR(NGKNET_IOC_MAGIC, 0xb4, unsigned int) +#define NGKNET_DEV_HNET_WAKE _IOWR(NGKNET_IOC_MAGIC, 0xb5, unsigned int) +#define NGKNET_DEV_VNET_DOCK _IOWR(NGKNET_IOC_MAGIC, 0xb6, unsigned int) +#define NGKNET_DEV_VNET_UNDOCK _IOWR(NGKNET_IOC_MAGIC, 0xb7, unsigned int) +#define NGKNET_QUEUE_CONFIG _IOWR(NGKNET_IOC_MAGIC, 0xc0, unsigned int) +#define NGKNET_QUEUE_QUERY _IOR(NGKNET_IOC_MAGIC, 0xc1, unsigned int) +#define NGKNET_RCPU_CONFIG _IOWR(NGKNET_IOC_MAGIC, 0xc2, unsigned int) +#define NGKNET_RCPU_GET _IOR(NGKNET_IOC_MAGIC, 0xc3, unsigned int) +#define NGKNET_NETIF_CREATE _IOWR(NGKNET_IOC_MAGIC, 0xd0, unsigned int) +#define NGKNET_NETIF_DESTROY _IOWR(NGKNET_IOC_MAGIC, 0xd1, unsigned int) +#define NGKNET_NETIF_GET _IOR(NGKNET_IOC_MAGIC, 0xd2, unsigned int) +#define NGKNET_NETIF_NEXT _IOR(NGKNET_IOC_MAGIC, 0xd3, unsigned int) +#define NGKNET_NETIF_LINK_SET _IOW(NGKNET_IOC_MAGIC, 0xd4, unsigned int) +#define NGKNET_FILT_CREATE _IOWR(NGKNET_IOC_MAGIC, 0xe0, unsigned int) +#define NGKNET_FILT_DESTROY _IOWR(NGKNET_IOC_MAGIC, 0xe1, unsigned int) +#define NGKNET_FILT_GET _IOR(NGKNET_IOC_MAGIC, 0xe2, unsigned int) +#define NGKNET_FILT_NEXT _IOR(NGKNET_IOC_MAGIC, 0xe3, unsigned int) +#define NGKNET_INFO_GET _IOR(NGKNET_IOC_MAGIC, 0xf0, unsigned int) +#define NGKNET_STATS_GET _IOR(NGKNET_IOC_MAGIC, 0xf1, unsigned int) +#define NGKNET_STATS_RESET _IOWR(NGKNET_IOC_MAGIC, 0xf2, unsigned int) +#define NGKNET_PTP_DEV_CTRL _IOWR(NGKNET_IOC_MAGIC, 0x90, unsigned int) + +/*! Kernel module information. */ +struct ngknet_ioc_mod_info { + /*! IOCTL version used by kernel module */ + uint32_t version; +}; + +/*! Data transmission */ +struct ngknet_ioc_data_xmit { + /*! Data buffer address */ + uint64_t buf; + + /*! Data buffer length */ + uint32_t len; +}; + +/*! IOCTL operations */ +union ngknet_ioc_op { + /*! Get module info */ + struct ngknet_ioc_mod_info info; + /*! Transmit data */ + struct ngknet_ioc_data_xmit data; +}; + +/*! + * \brief NGKNET IOCTL command message. + */ +struct ngknet_ioctl { + /*! Device number */ + uint32_t unit; + + /*! Return code (0 means success) */ + uint32_t rc; + + /*! Input arguments */ + int iarg[NGKNET_IOC_IARG_MAX]; + + /*! IOCTL operation */ + union ngknet_ioc_op op; +}; + +#endif /* NGKNET_IOCTL_H */ + diff --git a/platform/broadcom/saibcm-modules/sdklt/linux/include/net/psample.h b/platform/broadcom/saibcm-modules/sdklt/linux/include/net/psample.h new file mode 100644 index 00000000000..64188c95dae --- /dev/null +++ b/platform/broadcom/saibcm-modules/sdklt/linux/include/net/psample.h @@ -0,0 +1,24 @@ +#ifndef __NET_PSAMPLE_H +#define __NET_PSAMPLE_H + +#include +#include +#include +#include + +struct psample_group { + struct list_head list; + struct net *net; + u32 group_num; + u32 refcount; + u32 seq; +}; + +extern struct psample_group *psample_group_get(struct net *net, u32 group_num); +extern void psample_group_put(struct psample_group *group); + +extern void psample_sample_packet(struct psample_group *group, struct sk_buff *skb, + u32 trunc_size, int in_ifindex, int out_ifindex, + u32 sample_rate); + +#endif /* __NET_PSAMPLE_H */ diff --git a/platform/broadcom/saibcm-modules/sdklt/linux/include/uapi/linux/psample.h b/platform/broadcom/saibcm-modules/sdklt/linux/include/uapi/linux/psample.h new file mode 100644 index 00000000000..ed48996ec0e --- /dev/null +++ b/platform/broadcom/saibcm-modules/sdklt/linux/include/uapi/linux/psample.h @@ -0,0 +1,35 @@ +#ifndef __UAPI_PSAMPLE_H +#define __UAPI_PSAMPLE_H + +enum { + /* sampled packet metadata */ + PSAMPLE_ATTR_IIFINDEX, + PSAMPLE_ATTR_OIFINDEX, + PSAMPLE_ATTR_ORIGSIZE, + PSAMPLE_ATTR_SAMPLE_GROUP, + PSAMPLE_ATTR_GROUP_SEQ, + PSAMPLE_ATTR_SAMPLE_RATE, + PSAMPLE_ATTR_DATA, + + /* commands attributes */ + PSAMPLE_ATTR_GROUP_REFCOUNT, + + __PSAMPLE_ATTR_MAX +}; + +enum psample_command { + PSAMPLE_CMD_SAMPLE, + PSAMPLE_CMD_GET_GROUP, + PSAMPLE_CMD_NEW_GROUP, + PSAMPLE_CMD_DEL_GROUP, +}; + +/* Can be overridden at runtime by module option */ +#define PSAMPLE_ATTR_MAX (__PSAMPLE_ATTR_MAX - 1) + +#define PSAMPLE_NL_MCGRP_CONFIG_NAME "config" +#define PSAMPLE_NL_MCGRP_SAMPLE_NAME "packets" +#define PSAMPLE_GENL_NAME "psample" +#define PSAMPLE_GENL_VERSION 1 + +#endif diff --git a/platform/broadcom/saibcm-modules/sdklt/linux/knet/Kbuild b/platform/broadcom/saibcm-modules/sdklt/linux/knet/Kbuild new file mode 100644 index 00000000000..fe5d5c5bfef --- /dev/null +++ b/platform/broadcom/saibcm-modules/sdklt/linux/knet/Kbuild @@ -0,0 +1,44 @@ +# -*- Kbuild -*- +# +# Linux KNET module. +# +# $Copyright: Copyright 2018-2020 Broadcom. All rights reserved. +# The term 'Broadcom' refers to Broadcom Inc. and/or its subsidiaries. +# +# This program is free software; you can redistribute it and/or +# modify it under the terms of the GNU General Public License +# version 2 as published by the Free Software Foundation. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# A copy of the GNU General Public License version 2 (GPLv2) can +# be found in the LICENSES folder.$ +# + +obj-m := linux_ngknet.o + +ccflags-y := $(KNET_CPPFLAGS) $(LKM_CFLAGS) \ + -I$(SDK)/shr/include \ + -I$(SDK)/bcmdrd/include \ + -I$(SDK)/linux/include \ + -I$(SDK)/linux/knet/include \ + -I$(SDK)/linux/knet + +linux_ngknet-y := $(CHIP_OBJS) \ + bcmcnet_cmicd_pdma_hw.o \ + bcmcnet_cmicd_pdma_rxtx.o \ + bcmcnet_cmicx_pdma_hw.o \ + bcmcnet_cmicx_pdma_rxtx.o \ + bcmcnet_core.o \ + bcmcnet_dev.o \ + bcmcnet_rxtx.o \ + ngknet_buff.o \ + ngknet_callback.o \ + ngknet_extra.o \ + ngknet_linux.o \ + ngknet_main.o \ + ngknet_procfs.o \ + ngknet_ptp.o diff --git a/platform/broadcom/saibcm-modules/sdklt/linux/knet/Makefile b/platform/broadcom/saibcm-modules/sdklt/linux/knet/Makefile new file mode 100644 index 00000000000..785b81fadb1 --- /dev/null +++ b/platform/broadcom/saibcm-modules/sdklt/linux/knet/Makefile @@ -0,0 +1,105 @@ +# -*- Makefile -*- +# +# Linux KNET module. +# +# $Copyright: Copyright 2018-2020 Broadcom. All rights reserved. +# The term 'Broadcom' refers to Broadcom Inc. and/or its subsidiaries. +# +# This program is free software; you can redistribute it and/or +# modify it under the terms of the GNU General Public License +# version 2 as published by the Free Software Foundation. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# A copy of the GNU General Public License version 2 (GPLv2) can +# be found in the LICENSES folder.$ +# + +CNETDIR = $(SDK)/bcmcnet +KNETDIR = $(SDK)/linux/knet +SRCIDIR = $(CNETDIR)/include/bcmcnet +DSTIDIR = $(KNETDIR)/include/bcmcnet + +# Change comma-separated list to space-separated list +comma = , +empty = +space = $(empty) $(empty) +spc_sep = $(subst $(comma),$(space),$1) + +# Convert chip name to uppercase +chip_uc = $(subst a,A,$(subst b,B,$(subst c,C,$(subst m,M,$1)))) + +# Convert chip name to lowercase +chip_lc = $(subst A,a,$(subst B,b,$(subst C,c,$(subst M,m,$1)))) + +# +# If SDK_CHIPS is defined, then exclude any chip directory which is +# not part of this list. +# +KNET_CHIPS := $(subst $(CNETDIR)/chip/,,$(wildcard $(CNETDIR)/chip/bcm*)) +ifdef SDK_CHIPS +# Create space-separated lowercase version of chip list +SDK_CHIPS_SPC := $(call spc_sep,$(SDK_CHIPS)) +SDK_CHIPS_LC := $(call chip_lc,$(SDK_CHIPS_SPC)) +# Configure build flags according to chip list +KNET_CHIPS := $(filter $(SDK_CHIPS_LC),$(KNET_CHIPS)) +KNET_CPPFLAGS := CHIP_DEFAULT=0 $(addsuffix =1,$(call chip_uc,$(KNET_CHIPS))) +KNET_CPPFLAGS := $(addprefix -DBCMDRD_CONFIG_INCLUDE_,$(KNET_CPPFLAGS)) +export KNET_CPPFLAGS +endif + +.PHONY: mklinks rmlinks + +knet: mklinks + $(MAKE) all + +# +# Suppress symlink error messages. +# +# Note that we do not use "ln -f" as this may cause failures if +# multiple builds are done in parallel on the same source tree. +# +R = 2>/dev/null + +mklinks: + mkdir -p $(DSTIDIR) + -ln -s $(KNETDIR)/ngknet_dep.h $(DSTIDIR)/bcmcnet_dep.h $(R) + -ln -s $(KNETDIR)/ngknet_buff.h $(DSTIDIR)/bcmcnet_buff.h $(R) + -ln -s $(SRCIDIR)/bcmcnet_types.h $(DSTIDIR) $(R) + -ln -s $(SRCIDIR)/bcmcnet_internal.h $(DSTIDIR) $(R) + -ln -s $(SRCIDIR)/bcmcnet_core.h $(DSTIDIR) $(R) + -ln -s $(SRCIDIR)/bcmcnet_dev.h $(DSTIDIR) $(R) + -ln -s $(SRCIDIR)/bcmcnet_rxtx.h $(DSTIDIR) $(R) + -ln -s $(SRCIDIR)/bcmcnet_cmicd.h $(DSTIDIR) $(R) + -ln -s $(SRCIDIR)/bcmcnet_cmicx.h $(DSTIDIR) $(R) + -ln -s $(CNETDIR)/chip/*/*attach.c $(KNETDIR) $(R) + -ln -s $(CNETDIR)/hmi/cmicd/*.c $(KNETDIR) $(R) + -ln -s $(CNETDIR)/hmi/cmicx/*.c $(KNETDIR) $(R) + -ln -s $(CNETDIR)/main/bcmcnet_core.c $(KNETDIR) $(R) + -ln -s $(CNETDIR)/main/bcmcnet_dev.c $(KNETDIR) $(R) + -ln -s $(CNETDIR)/main/bcmcnet_rxtx.c $(KNETDIR) $(R) + +rmlinks: + -rm -f bcm* + -rm -rf include + +CHIP_SRCS := $(addsuffix _pdma_attach.c,$(KNET_CHIPS)) +CHIP_OBJS ?= $(patsubst %.c, %.o, $(CHIP_SRCS)) +export CHIP_OBJS + +include Kbuild + +ifeq ($(KERNELRELEASE),) + +MOD_NAME = linux_ngknet + +include $(SDK)/make/lkm.mk + +endif + +.PHONY: distclean + +distclean: rmlinks diff --git a/platform/broadcom/saibcm-modules/sdklt/linux/knet/ngknet_buff.c b/platform/broadcom/saibcm-modules/sdklt/linux/knet/ngknet_buff.c new file mode 100644 index 00000000000..750fff69caf --- /dev/null +++ b/platform/broadcom/saibcm-modules/sdklt/linux/knet/ngknet_buff.c @@ -0,0 +1,326 @@ +/*! \file ngknet_buff.c + * + * Utility routines for NGKNET packet buffer management in Linux kernel mode. + * + */ +/* + * $Copyright: Copyright 2018-2020 Broadcom. All rights reserved. + * The term 'Broadcom' refers to Broadcom Inc. and/or its subsidiaries. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * version 2 as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * A copy of the GNU General Public License version 2 (GPLv2) can + * be found in the LICENSES folder.$ + */ + +#include +#include +#include +#include "ngknet_main.h" +#include "ngknet_buff.h" + +/*! + * Allocate coherent memory + */ +static void * +bcmcnet_ring_buf_alloc(struct pdma_dev *dev, uint32_t size, dma_addr_t *dma) +{ + struct ngknet_dev *kdev = (struct ngknet_dev *)dev->priv; + + return dma_alloc_coherent(kdev->dev, size, dma, GFP_KERNEL); +} + +/*! + * Free coherent memory + */ +static void +bcmcnet_ring_buf_free(struct pdma_dev *dev, uint32_t size, void *addr, dma_addr_t dma) +{ + struct ngknet_dev *kdev = (struct ngknet_dev *)dev->priv; + + dma_free_coherent(kdev->dev, size, addr, dma); +} + +/*! + * Allocate Rx buffer + */ +static int +bcmcnet_rx_buf_alloc(struct pdma_dev *dev, struct pdma_rx_queue *rxq, + struct pdma_rx_buf *pbuf) +{ + struct ngknet_dev *kdev = (struct ngknet_dev *)dev->priv; + dma_addr_t dma; + struct page *page; + struct sk_buff *skb; + + if (rxq->mode == PDMA_BUF_MODE_PAGE) { + page = kal_dev_alloc_page(); + if (unlikely(!page)) { + return SHR_E_MEMORY; + } + dma = dma_map_page(kdev->dev, page, 0, PAGE_SIZE, DMA_FROM_DEVICE); + if (unlikely(dma_mapping_error(kdev->dev, dma))) { + __free_page(page); + return SHR_E_MEMORY; + } + pbuf->dma = dma; + pbuf->page = page; + pbuf->page_offset = 0; + } else { + skb = netdev_alloc_skb(kdev->net_dev, PDMA_RXB_RESV + pbuf->adj + rxq->buf_size); + if (unlikely(!skb)) { + return SHR_E_MEMORY; + } + skb_reserve(skb, PDMA_RXB_ALIGN - (((unsigned long)skb->data) & (PDMA_RXB_ALIGN - 1))); + pbuf->skb = skb; + pbuf->pkb = (struct pkt_buf *)skb->data; + dma = dma_map_single(kdev->dev, &pbuf->pkb->data + pbuf->adj, rxq->buf_size, DMA_FROM_DEVICE); + if (unlikely(dma_mapping_error(kdev->dev, dma))) { + dev_kfree_skb_any(skb); + return SHR_E_MEMORY; + } + pbuf->dma = dma; + } + + return SHR_E_NONE; +} + +/*! + * Get Rx buffer DMA address + */ +static void +bcmcnet_rx_buf_dma(struct pdma_dev *dev, struct pdma_rx_queue *rxq, + struct pdma_rx_buf *pbuf, dma_addr_t *addr) +{ + if (rxq->mode == PDMA_BUF_MODE_PAGE) { + *addr = pbuf->dma + pbuf->page_offset + PDMA_RXB_RESV + pbuf->adj; + } else { + *addr = pbuf->dma; + } +} + +/*! + * Check Rx buffer + */ +static int +bcmcnet_rx_buf_avail(struct pdma_dev *dev, struct pdma_rx_queue *rxq, + struct pdma_rx_buf *pbuf) +{ + if (rxq->mode == PDMA_BUF_MODE_PAGE) { + pbuf->skb = NULL; + } + + return pbuf->dma != 0; +} + +/*! + * Get Rx buffer + */ +static struct pkt_hdr * +bcmcnet_rx_buf_get(struct pdma_dev *dev, struct pdma_rx_queue *rxq, + struct pdma_rx_buf *pbuf, int len) +{ + struct ngknet_dev *kdev = (struct ngknet_dev *)dev->priv; + struct sk_buff *skb; + + if (rxq->mode == PDMA_BUF_MODE_PAGE) { + if (pbuf->skb) { + return &pbuf->pkb->pkh; + } + skb = kal_build_skb(page_address(pbuf->page) + pbuf->page_offset, + PDMA_SKB_RESV + pbuf->adj + rxq->buf_size); + if (unlikely(!skb)) { + return NULL; + } + skb_reserve(skb, PDMA_RXB_ALIGN); + dma_sync_single_range_for_cpu(kdev->dev, pbuf->dma, pbuf->page_offset, + PDMA_PAGE_BUF_MAX, DMA_FROM_DEVICE); + pbuf->skb = skb; + pbuf->pkb = (struct pkt_buf *)skb->data; + + /* Try to reuse this page */ + if (unlikely(page_count(pbuf->page) != 1)) { + dma_unmap_page(kdev->dev, pbuf->dma, PAGE_SIZE, DMA_FROM_DEVICE); + pbuf->dma = 0; + } else { + pbuf->page_offset ^= PDMA_PAGE_BUF_MAX; + page_ref_inc(pbuf->page); + dma_sync_single_range_for_device(kdev->dev, pbuf->dma, pbuf->page_offset, + PDMA_PAGE_BUF_MAX, DMA_FROM_DEVICE); + } + } else { + if (!pbuf->dma) { + return &pbuf->pkb->pkh; + } + skb = pbuf->skb; + dma_unmap_single(kdev->dev, pbuf->dma, rxq->buf_size, DMA_FROM_DEVICE); + pbuf->dma = 0; + } + + skb_put(skb, PKT_HDR_SIZE + pbuf->adj + len); + + return &pbuf->pkb->pkh; +} + +/*! + * Put Rx buffer + */ +static int +bcmcnet_rx_buf_put(struct pdma_dev *dev, struct pdma_rx_queue *rxq, + struct pdma_rx_buf *pbuf, int len) +{ + struct ngknet_dev *kdev = (struct ngknet_dev *)dev->priv; + dma_addr_t dma; + struct sk_buff *skb; + + if (rxq->mode == PDMA_BUF_MODE_PAGE) { + dev_kfree_skb_any(pbuf->skb); + } else { + skb = pbuf->skb; + dma = dma_map_single(kdev->dev, &pbuf->pkb->data + pbuf->adj, + rxq->buf_size, DMA_FROM_DEVICE); + if (unlikely(dma_mapping_error(kdev->dev, dma))) { + dev_kfree_skb_any(skb); + pbuf->dma = 0; + return SHR_E_MEMORY; + } + pbuf->dma = dma; + skb_trim(skb, skb->len - (PKT_HDR_SIZE + pbuf->adj + len)); + } + + return SHR_E_NONE; +} + +/*! + * Free Rx buffer + */ +static void +bcmcnet_rx_buf_free(struct pdma_dev *dev, struct pdma_rx_queue *rxq, + struct pdma_rx_buf *pbuf) +{ + struct ngknet_dev *kdev = (struct ngknet_dev *)dev->priv; + + if (rxq->mode == PDMA_BUF_MODE_PAGE) { + dma_unmap_single(kdev->dev, pbuf->dma, PAGE_SIZE, DMA_FROM_DEVICE); + __free_page(pbuf->page); + } else { + dma_unmap_single(kdev->dev, pbuf->dma, rxq->buf_size, DMA_FROM_DEVICE); + dev_kfree_skb_any(pbuf->skb); + } + + pbuf->dma = 0; + pbuf->page = NULL; + pbuf->page_offset = 0; + pbuf->skb = NULL; + pbuf->pkb = NULL; + pbuf->adj = 0; +} + +/*! + * Get Rx buffer mode + */ +static enum buf_mode +bcmcnet_rx_buf_mode(struct pdma_dev *dev, struct pdma_rx_queue *rxq) +{ + uint32_t len; + + len = dev->rx_ph_size ? rxq->buf_size : rxq->buf_size + PDMA_RXB_META; + if (PDMA_RXB_SIZE(len) <= PDMA_PAGE_BUF_MAX && PAGE_SIZE < 8192 && + kal_support_paged_skb()) { + return PDMA_BUF_MODE_PAGE; + } + + return PDMA_BUF_MODE_SKB; +} + +/*! + * Get Tx buffer + */ +static struct pkt_hdr * +bcmcnet_tx_buf_get(struct pdma_dev *dev, struct pdma_tx_queue *txq, + struct pdma_tx_buf *pbuf, void *buf) +{ + struct ngknet_dev *kdev = (struct ngknet_dev *)dev->priv; + struct sk_buff *skb = (struct sk_buff *)buf; + struct pkt_buf *pkb = (struct pkt_buf *)skb->data; + dma_addr_t dma; + + pbuf->len = pkb->pkh.data_len + (pbuf->adj ? pkb->pkh.meta_len : 0); + dma = dma_map_single(kdev->dev, &pkb->data + (pbuf->adj ? 0 : pkb->pkh.meta_len), + pbuf->len, DMA_TO_DEVICE); + if (unlikely(dma_mapping_error(kdev->dev, dma))) { + dev_kfree_skb_any(skb); + return NULL; + } + pbuf->dma = dma; + pbuf->skb = skb; + pbuf->pkb = pkb; + + return &pkb->pkh; +} + +/*! + * Get Tx buffer DMA address + */ +static void +bcmcnet_tx_buf_dma(struct pdma_dev *dev, struct pdma_tx_queue *txq, + struct pdma_tx_buf *pbuf, dma_addr_t *addr) +{ + *addr = pbuf->dma; +} + +/*! + * Free Tx buffer + */ +static void +bcmcnet_tx_buf_free(struct pdma_dev *dev, struct pdma_tx_queue *txq, + struct pdma_tx_buf *pbuf) +{ + struct ngknet_dev *kdev = (struct ngknet_dev *)dev->priv; + + dma_unmap_single(kdev->dev, pbuf->dma, pbuf->len, DMA_TO_DEVICE); + if (skb_shinfo(pbuf->skb)->tx_flags & SKBTX_IN_PROGRESS) { + skb_queue_tail(&kdev->ptp_tx_queue, pbuf->skb); + schedule_work(&kdev->ptp_tx_work); + } else { + dev_kfree_skb_any(pbuf->skb); + } + + pbuf->dma = 0; + pbuf->len = 0; + pbuf->skb = NULL; + pbuf->pkb = NULL; + pbuf->adj = 0; +} + +static const struct pdma_buf_mngr buf_mngr = { + .ring_buf_alloc = bcmcnet_ring_buf_alloc, + .ring_buf_free = bcmcnet_ring_buf_free, + .rx_buf_alloc = bcmcnet_rx_buf_alloc, + .rx_buf_dma = bcmcnet_rx_buf_dma, + .rx_buf_avail = bcmcnet_rx_buf_avail, + .rx_buf_get = bcmcnet_rx_buf_get, + .rx_buf_put = bcmcnet_rx_buf_put, + .rx_buf_free = bcmcnet_rx_buf_free, + .rx_buf_mode = bcmcnet_rx_buf_mode, + .tx_buf_get = bcmcnet_tx_buf_get, + .tx_buf_dma = bcmcnet_tx_buf_dma, + .tx_buf_free = bcmcnet_tx_buf_free, +}; + +/*! + * Open a device + */ +void +bcmcnet_buf_mngr_init(struct pdma_dev *dev) +{ + dev->ctrl.buf_mngr = (struct pdma_buf_mngr *)&buf_mngr; +} + diff --git a/platform/broadcom/saibcm-modules/sdklt/linux/knet/ngknet_buff.h b/platform/broadcom/saibcm-modules/sdklt/linux/knet/ngknet_buff.h new file mode 100644 index 00000000000..54768e82691 --- /dev/null +++ b/platform/broadcom/saibcm-modules/sdklt/linux/knet/ngknet_buff.h @@ -0,0 +1,83 @@ +/*! \file ngknet_buff.h + * + * Generic data structure definitions for NGKNET packet buffer management. + * + */ +/* + * $Copyright: Copyright 2018-2020 Broadcom. All rights reserved. + * The term 'Broadcom' refers to Broadcom Inc. and/or its subsidiaries. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * version 2 as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * A copy of the GNU General Public License version 2 (GPLv2) can + * be found in the LICENSES folder.$ + */ + +#ifndef NGKNET_BUFF_H +#define NGKNET_BUFF_H + +/*! Rx buffer align size */ +#define PDMA_RXB_ALIGN 32 +/*! Rx buffer reserved size */ +#define PDMA_RXB_RESV (PDMA_RXB_ALIGN + PKT_HDR_SIZE) +/*! Rx SKB reserved size */ +#define PDMA_SKB_RESV (PDMA_RXB_RESV + SKB_DATA_ALIGN(sizeof(struct skb_shared_info))) +/*! Rx buffer size */ +#define PDMA_RXB_SIZE(len) (SKB_DATA_ALIGN(len + NET_SKB_PAD) + PDMA_SKB_RESV) +/*! Rx reserved meta size */ +#define PDMA_RXB_META 64 +/*! Max page buffer size */ +#define PDMA_PAGE_BUF_MAX 2048 + +/*! + * \brief Rx buffer. + */ +struct pdma_rx_buf { + /*! DMA address */ + dma_addr_t dma; + + /*! Buffer page */ + struct page *page; + + /*! Buffer page offset */ + unsigned int page_offset; + + /*! Rx SKB */ + struct sk_buff *skb; + + /*! Packet buffer point */ + struct pkt_buf *pkb; + + /*! Packet buffer adjustment */ + uint32_t adj; +}; + +/*! + * \brief Tx buffer. + */ +struct pdma_tx_buf { + /*! DMA address */ + dma_addr_t dma; + + /*! Tx buffer length */ + uint32_t len; + + /*! Tx SKB */ + struct sk_buff *skb; + + /*! Packet buffer point */ + struct pkt_buf *pkb; + + /*! Packet buffer adjustment */ + uint32_t adj; +}; + +#endif /* NGKNET_BUFF_H */ + diff --git a/platform/broadcom/saibcm-modules/sdklt/linux/knet/ngknet_callback.c b/platform/broadcom/saibcm-modules/sdklt/linux/knet/ngknet_callback.c new file mode 100644 index 00000000000..21512a51fbd --- /dev/null +++ b/platform/broadcom/saibcm-modules/sdklt/linux/knet/ngknet_callback.c @@ -0,0 +1,315 @@ +/*! \file ngknet_callback.c + * + * Utility routines for NGKNET callbacks. + * + */ +/* + * $Copyright: Copyright 2018-2020 Broadcom. All rights reserved. + * The term 'Broadcom' refers to Broadcom Inc. and/or its subsidiaries. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * version 2 as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * A copy of the GNU General Public License version 2 (GPLv2) can + * be found in the LICENSES folder.$ + */ + +#include "ngknet_callback.h" + +static struct ngknet_callback_ctrl callback_ctrl; + +int +ngknet_callback_control_get(struct ngknet_callback_ctrl **cbc) +{ + *cbc = &callback_ctrl; + + return 0; +} + +/*! + * Call-back interfaces for other Linux kernel drivers. + * + * The Rx call-back allows an external module to modify packet contents + * before it is handed off to the Linux network stack. + * + * The Tx call-back allows an external module to modify packet contents + * before it is injected into the switch. + */ + +int +ngknet_rx_cb_register(ngknet_rx_cb_f rx_cb) +{ + if (callback_ctrl.rx_cb != NULL) { + return -1; + } + callback_ctrl.rx_cb = rx_cb; + + return 0; +} + +int +ngknet_rx_cb_unregister(ngknet_rx_cb_f rx_cb) +{ + if (rx_cb == NULL || callback_ctrl.rx_cb != rx_cb) { + return -1; + } + callback_ctrl.rx_cb = NULL; + + return 0; +} + +int +ngknet_tx_cb_register(ngknet_tx_cb_f tx_cb) +{ + if (callback_ctrl.tx_cb != NULL) { + return -1; + } + callback_ctrl.tx_cb = tx_cb; + + return 0; +} + +int +ngknet_tx_cb_unregister(ngknet_tx_cb_f tx_cb) +{ + if (tx_cb == NULL || callback_ctrl.tx_cb != tx_cb) { + return -1; + } + callback_ctrl.tx_cb = NULL; + + return 0; +} + +int +ngknet_ptp_rx_config_set_cb_register(ngknet_ptp_config_set_cb_f ptp_rx_config_set_cb) +{ + if (callback_ctrl.ptp_rx_config_set_cb != NULL) { + return -1; + } + callback_ctrl.ptp_rx_config_set_cb = ptp_rx_config_set_cb; + + return 0; +} + +int +ngknet_ptp_rx_config_set_cb_unregister(ngknet_ptp_config_set_cb_f ptp_rx_config_set_cb) +{ + if (ptp_rx_config_set_cb == NULL || + callback_ctrl.ptp_rx_config_set_cb != ptp_rx_config_set_cb) { + return -1; + } + callback_ctrl.ptp_rx_config_set_cb = NULL; + + return 0; +} + +int +ngknet_ptp_tx_config_set_cb_register(ngknet_ptp_config_set_cb_f ptp_tx_config_set_cb) +{ + if (callback_ctrl.ptp_tx_config_set_cb != NULL) { + return -1; + } + callback_ctrl.ptp_tx_config_set_cb = ptp_tx_config_set_cb; + + return 0; +} + +int +ngknet_ptp_tx_config_set_cb_unregister(ngknet_ptp_config_set_cb_f ptp_tx_config_set_cb) +{ + if (ptp_tx_config_set_cb == NULL || + callback_ctrl.ptp_tx_config_set_cb != ptp_tx_config_set_cb) { + return -1; + } + callback_ctrl.ptp_tx_config_set_cb = NULL; + + return 0; +} + +int +ngknet_ptp_rx_hwts_get_cb_register(ngknet_ptp_hwts_get_cb_f ptp_rx_hwts_get_cb) +{ + if (callback_ctrl.ptp_rx_hwts_get_cb != NULL) { + return -1; + } + callback_ctrl.ptp_rx_hwts_get_cb = ptp_rx_hwts_get_cb; + + return 0; +} + +int +ngknet_ptp_rx_hwts_get_cb_unregister(ngknet_ptp_hwts_get_cb_f ptp_rx_hwts_get_cb) +{ + if (ptp_rx_hwts_get_cb == NULL || + callback_ctrl.ptp_rx_hwts_get_cb != ptp_rx_hwts_get_cb) { + return -1; + } + callback_ctrl.ptp_rx_hwts_get_cb = NULL; + + return 0; +} + +int +ngknet_ptp_tx_hwts_get_cb_register(ngknet_ptp_hwts_get_cb_f ptp_tx_hwts_get_cb) +{ + if (callback_ctrl.ptp_tx_hwts_get_cb != NULL) { + return -1; + } + callback_ctrl.ptp_tx_hwts_get_cb = ptp_tx_hwts_get_cb; + + return 0; +} + +int +ngknet_ptp_tx_hwts_get_cb_unregister(ngknet_ptp_hwts_get_cb_f ptp_tx_hwts_get_cb) +{ + if (ptp_tx_hwts_get_cb == NULL || + callback_ctrl.ptp_tx_hwts_get_cb != ptp_tx_hwts_get_cb) { + return -1; + } + callback_ctrl.ptp_tx_hwts_get_cb = NULL; + + return 0; +} + +int +ngknet_ptp_tx_meta_set_cb_register(ngknet_ptp_meta_set_cb_f ptp_tx_meta_set_cb) +{ + if (callback_ctrl.ptp_tx_meta_set_cb != NULL) { + return -1; + } + callback_ctrl.ptp_tx_meta_set_cb = ptp_tx_meta_set_cb; + + return 0; +} + +int +ngknet_ptp_tx_meta_set_cb_unregister(ngknet_ptp_meta_set_cb_f ptp_tx_meta_set_cb) +{ + if (ptp_tx_meta_set_cb == NULL || + callback_ctrl.ptp_tx_meta_set_cb != ptp_tx_meta_set_cb) { + return -1; + } + callback_ctrl.ptp_tx_meta_set_cb = NULL; + + return 0; +} + +int +ngknet_ptp_phc_index_get_cb_register(ngknet_ptp_phc_index_get_cb_f ptp_phc_index_get_cb) +{ + if (callback_ctrl.ptp_phc_index_get_cb != NULL) { + return -1; + } + callback_ctrl.ptp_phc_index_get_cb = ptp_phc_index_get_cb; + + return 0; +} + +int +ngknet_ptp_phc_index_get_cb_unregister(ngknet_ptp_phc_index_get_cb_f ptp_phc_index_get_cb) +{ + if (ptp_phc_index_get_cb == NULL || + callback_ctrl.ptp_phc_index_get_cb != ptp_phc_index_get_cb) { + return -1; + } + callback_ctrl.ptp_phc_index_get_cb = NULL; + + return 0; +} + +int +ngknet_ptp_dev_ctrl_cb_register(ngknet_ptp_dev_ctrl_cb_f ptp_dev_ctrl_cb) +{ + if (callback_ctrl.ptp_dev_ctrl_cb != NULL) { + return -1; + } + callback_ctrl.ptp_dev_ctrl_cb = ptp_dev_ctrl_cb; + + return 0; +} + +int +ngknet_ptp_dev_ctrl_cb_unregister(ngknet_ptp_dev_ctrl_cb_f ptp_dev_ctrl_cb) +{ + if (ptp_dev_ctrl_cb == NULL || + callback_ctrl.ptp_dev_ctrl_cb != ptp_dev_ctrl_cb) { + return -1; + } + callback_ctrl.ptp_dev_ctrl_cb = NULL; + + return 0; +} + +int +ngknet_netif_create_cb_register(ngknet_netif_cb_f netif_cb) +{ + if (callback_ctrl.netif_create_cb != NULL) { + return -1; + } + callback_ctrl.netif_create_cb = netif_cb; + + return 0; +} + +int +ngknet_netif_create_cb_unregister(ngknet_netif_cb_f netif_cb) +{ + if (netif_cb == NULL || callback_ctrl.netif_create_cb != netif_cb) { + return -1; + } + callback_ctrl.netif_create_cb = NULL; + + return 0; +} + +int +ngknet_netif_destroy_cb_register(ngknet_netif_cb_f netif_cb) +{ + if (callback_ctrl.netif_destroy_cb != NULL) { + return -1; + } + callback_ctrl.netif_destroy_cb = netif_cb; + + return 0; +} + +int +ngknet_netif_destroy_cb_unregister(ngknet_netif_cb_f netif_cb) +{ + if (netif_cb == NULL || callback_ctrl.netif_destroy_cb != netif_cb) { + return -1; + } + callback_ctrl.netif_destroy_cb = NULL; + + return 0; +} + +EXPORT_SYMBOL(ngknet_rx_cb_register); +EXPORT_SYMBOL(ngknet_rx_cb_unregister); +EXPORT_SYMBOL(ngknet_tx_cb_register); +EXPORT_SYMBOL(ngknet_tx_cb_unregister); +EXPORT_SYMBOL(ngknet_ptp_rx_config_set_cb_register); +EXPORT_SYMBOL(ngknet_ptp_rx_config_set_cb_unregister); +EXPORT_SYMBOL(ngknet_ptp_tx_config_set_cb_register); +EXPORT_SYMBOL(ngknet_ptp_tx_config_set_cb_unregister); +EXPORT_SYMBOL(ngknet_ptp_rx_hwts_get_cb_register); +EXPORT_SYMBOL(ngknet_ptp_rx_hwts_get_cb_unregister); +EXPORT_SYMBOL(ngknet_ptp_tx_hwts_get_cb_register); +EXPORT_SYMBOL(ngknet_ptp_tx_hwts_get_cb_unregister); +EXPORT_SYMBOL(ngknet_ptp_tx_meta_set_cb_register); +EXPORT_SYMBOL(ngknet_ptp_tx_meta_set_cb_unregister); +EXPORT_SYMBOL(ngknet_ptp_phc_index_get_cb_register); +EXPORT_SYMBOL(ngknet_ptp_phc_index_get_cb_unregister); +EXPORT_SYMBOL(ngknet_ptp_dev_ctrl_cb_register); +EXPORT_SYMBOL(ngknet_ptp_dev_ctrl_cb_unregister); +EXPORT_SYMBOL(ngknet_netif_create_cb_register); +EXPORT_SYMBOL(ngknet_netif_create_cb_unregister); +EXPORT_SYMBOL(ngknet_netif_destroy_cb_register); +EXPORT_SYMBOL(ngknet_netif_destroy_cb_unregister); diff --git a/platform/broadcom/saibcm-modules/sdklt/linux/knet/ngknet_callback.h b/platform/broadcom/saibcm-modules/sdklt/linux/knet/ngknet_callback.h new file mode 100644 index 00000000000..54583adffa3 --- /dev/null +++ b/platform/broadcom/saibcm-modules/sdklt/linux/knet/ngknet_callback.h @@ -0,0 +1,364 @@ +/*! \file ngknet_callback.h + * + * Data structure definitions for NGKNET callbacks. + * + */ +/* + * $Copyright: Copyright 2018-2020 Broadcom. All rights reserved. + * The term 'Broadcom' refers to Broadcom Inc. and/or its subsidiaries. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * version 2 as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * A copy of the GNU General Public License version 2 (GPLv2) can + * be found in the LICENSES folder.$ + */ + +#ifndef NGKNET_CALLBACK_H +#define NGKNET_CALLBACK_H + +#include +#include "ngknet_main.h" + +/*! + * \brief NGKNET callback description. + */ +struct ngknet_callback_desc { + /*! Device number */ + int dev_no; + + /*! Device ID */ + uint32_t dev_id; + + /*! Device type string */ + const char *type_str; + + /*! Network interface private data */ + struct ngknet_private *priv; + + /*! Matched filter */ + struct ngknet_filter_s *filt; + + /*! Packet meta data */ + uint8_t *pmd; + + /*! Packet meta data length */ + int pmd_len; + + /*! Packet data length */ + int pkt_len; + + /*! Matched callback filter */ + struct ngknet_filter_s *filt_cb; +}; + +#define NGKNET_SKB_CB(_skb) ((struct ngknet_callback_desc *)_skb->cb) + +/*! Handle Rx packet */ +typedef struct sk_buff * +(*ngknet_rx_cb_f)(struct sk_buff *skb); + +/*! Handle Tx packet */ +typedef struct sk_buff * +(*ngknet_tx_cb_f)(struct sk_buff *skb); + +/*! PTP Rx/Tx config set */ +typedef int +(*ngknet_ptp_config_set_cb_f)(struct ngknet_private *priv, int *value); + +/*! PTP Rx/Tx HW timestamp get */ +typedef int +(*ngknet_ptp_hwts_get_cb_f)(struct sk_buff *skb, uint64_t *ts); + +/*! PTP Tx meta set */ +typedef int +(*ngknet_ptp_meta_set_cb_f)(struct sk_buff *skb); + +/*! PTP PHC index get */ +typedef int +(*ngknet_ptp_phc_index_get_cb_f)(struct ngknet_private *priv, int *index); + +/*! PTP device control */ +typedef int +(*ngknet_ptp_dev_ctrl_cb_f)(struct ngknet_dev *dev, int cmd, char *data, int len); + +/*! Netif callback */ +typedef int +(*ngknet_netif_cb_f)(struct net_device *dev); + +/*! + * \brief NGKNET callback control. + */ +struct ngknet_callback_ctrl { + /*! Handle Rx packet */ + ngknet_rx_cb_f rx_cb; + + /*! Handle Tx packet */ + ngknet_tx_cb_f tx_cb; + + /*! PTP Rx config set */ + ngknet_ptp_config_set_cb_f ptp_rx_config_set_cb; + + /*! PTP Tx config set */ + ngknet_ptp_config_set_cb_f ptp_tx_config_set_cb; + + /*! PTP Rx HW timestamp get */ + ngknet_ptp_hwts_get_cb_f ptp_rx_hwts_get_cb; + + /*! PTP Tx HW timestamp get */ + ngknet_ptp_hwts_get_cb_f ptp_tx_hwts_get_cb; + + /*! PTP Tx meta set */ + ngknet_ptp_meta_set_cb_f ptp_tx_meta_set_cb; + + /*! PTP PHC index get */ + ngknet_ptp_phc_index_get_cb_f ptp_phc_index_get_cb; + + /*! PTP device control */ + ngknet_ptp_dev_ctrl_cb_f ptp_dev_ctrl_cb; + + /*! Handle Netif create */ + ngknet_netif_cb_f netif_create_cb; + + /*! Handle Netif destroy */ + ngknet_netif_cb_f netif_destroy_cb; +}; + +/*! + * \brief Get callback control. + * + * \param [in] cbc Pointer to callback control. + * + * \retval SHR_E_NONE No errors. + */ +extern int +ngknet_callback_control_get(struct ngknet_callback_ctrl **cbc); + +/*! + * \brief Register Rx callback. + * + * \param [in] rx_cb Rx callback function. + * + * \retval SHR_E_NONE No errors. + */ +extern int +ngknet_rx_cb_register(ngknet_rx_cb_f rx_cb); + +/*! + * \brief Unregister Rx callback. + * + * \param [in] rx_cb Rx callback function. + * + * \retval SHR_E_NONE No errors. + */ +extern int +ngknet_rx_cb_unregister(ngknet_rx_cb_f rx_cb); + +/*! + * \brief Register Tx callback. + * + * \param [in] tx_cb Tx callback function. + * + * \retval SHR_E_NONE No errors. + */ +extern int +ngknet_tx_cb_register(ngknet_tx_cb_f tx_cb); + +/*! + * \brief Unregister Tx callback. + * + * \param [in] tx_cb Tx callback function. + * + * \retval SHR_E_NONE No errors. + */ +extern int +ngknet_tx_cb_unregister(ngknet_tx_cb_f tx_cb); + +/*! + * \brief Register PTP Rx config set callback. + * + * \param [in] ptp_rx_config_set_cb Rx config set callback function. + * + * \retval SHR_E_NONE No errors. + */ +extern int +ngknet_ptp_rx_config_set_cb_register(ngknet_ptp_config_set_cb_f ptp_rx_config_set_cb); + +/*! + * \brief Unregister PTP Rx config set callback. + * + * \param [in] ptp_rx_config_set_cb Rx config set callback function. + * + * \retval SHR_E_NONE No errors. + */ +extern int +ngknet_ptp_rx_config_set_cb_unregister(ngknet_ptp_config_set_cb_f ptp_rx_config_set_cb); + +/*! + * \brief Register PTP Tx config set callback. + * + * \param [in] ptp_tx_config_set_cb Tx config set callback function. + * + * \retval SHR_E_NONE No errors. + */ +extern int +ngknet_ptp_tx_config_set_cb_register(ngknet_ptp_config_set_cb_f ptp_tx_config_set_cb); + +/*! + * \brief Unregister PTP Tx config set callback. + * + * \param [in] ptp_tx_config_set_cb Tx config set callback function. + * + * \retval SHR_E_NONE No errors. + */ +extern int +ngknet_ptp_tx_config_set_cb_unregister(ngknet_ptp_config_set_cb_f ptp_tx_config_set_cb); + +/*! + * \brief Register PTP Rx HW timestamp get callback. + * + * \param [in] ptp_rx_hwts_get_cb Rx HW timestamp get callback function. + * + * \retval SHR_E_NONE No errors. + */ +extern int +ngknet_ptp_rx_hwts_get_cb_register(ngknet_ptp_hwts_get_cb_f ptp_rx_hwts_get_cb); + +/*! + * \brief Unregister PTP Rx HW timestamp get callback. + * + * \param [in] ptp_rx_hwts_get_cb Rx HW timestamp get callback function. + * + * \retval SHR_E_NONE No errors. + */ +extern int +ngknet_ptp_rx_hwts_get_cb_unregister(ngknet_ptp_hwts_get_cb_f ptp_rx_hwts_get_cb); + +/*! + * \brief Register PTP Tx HW timestamp get callback. + * + * \param [in] ptp_tx_hwts_get_cb Tx HW timestamp get callback function. + * + * \retval SHR_E_NONE No errors. + */ +extern int +ngknet_ptp_tx_hwts_get_cb_register(ngknet_ptp_hwts_get_cb_f ptp_tx_hwts_get_cb); + +/*! + * \brief Unregister PTP Tx HW timestamp get callback. + * + * \param [in] ptp_tx_hwts_get_cb Tx HW timestamp get callback function. + * + * \retval SHR_E_NONE No errors. + */ +extern int +ngknet_ptp_tx_hwts_get_cb_unregister(ngknet_ptp_hwts_get_cb_f ptp_tx_hwts_get_cb); + +/*! + * \brief Register PTP Tx meta set callback. + * + * \param [in] ptp_tx_meta_set_cb Tx meta set callback function. + * + * \retval SHR_E_NONE No errors. + */ +extern int +ngknet_ptp_tx_meta_set_cb_register(ngknet_ptp_meta_set_cb_f ptp_tx_meta_set_cb); + +/*! + * \brief Unregister PTP Tx meta set callback. + * + * \param [in] ptp_tx_meta_set_cb Tx meta set callback function. + * + * \retval SHR_E_NONE No errors. + */ +extern int +ngknet_ptp_tx_meta_set_cb_unregister(ngknet_ptp_meta_set_cb_f ptp_tx_meta_set_cb); + +/*! + * \brief Register PTP PHC index get callback. + * + * \param [in] ptp_phc_index_get_cb PHC index get callback function. + * + * \retval SHR_E_NONE No errors. + */ +extern int +ngknet_ptp_phc_index_get_cb_register(ngknet_ptp_phc_index_get_cb_f ptp_phc_index_get_cb); + +/*! + * \brief Unregister PTP PHC index get callback. + * + * \param [in] ptp_phc_index_get_cb PHC index get callback function. + * + * \retval SHR_E_NONE No errors. + */ +extern int +ngknet_ptp_phc_index_get_cb_unregister(ngknet_ptp_phc_index_get_cb_f ptp_phc_index_get_cb); + +/*! + * \brief Register PTP device control callback. + * + * \param [in] ptp_dev_ctrl_cb Device control callback function. + * + * \retval SHR_E_NONE No errors. + */ +extern int +ngknet_ptp_dev_ctrl_cb_register(ngknet_ptp_dev_ctrl_cb_f ptp_dev_ctrl_cb); + +/*! + * \brief Unregister PTP device control callback. + * + * \param [in] ptp_dev_ctrl_cb Device control callback function. + * + * \retval SHR_E_NONE No errors. + */ +extern int +ngknet_ptp_dev_ctrl_cb_unregister(ngknet_ptp_dev_ctrl_cb_f ptp_dev_ctrl_cb); + +/*! + * \brief Register Netif Create callback. + * + * \param [netif_cb] netif_cb create callback function. + * + * \retval SHR_E_NONE No errors. + */ +extern int +ngknet_netif_create_cb_register(ngknet_netif_cb_f netif_cb); + +/*! + * \brief Unregister Netif Create callback. + * + * \param [netif_cb] netif_cb destroy callback function. + * + * \retval SHR_E_NONE No errors. + */ +extern int +ngknet_netif_create_cb_unregister(ngknet_netif_cb_f netif_cb); + +/*! + * \brief Register Netif Destroy callback. + * + * \param [netif_cb] netif_cb destroy callback function. + * + * \retval SHR_E_NONE No errors. + */ +extern int +ngknet_netif_destroy_cb_register(ngknet_netif_cb_f netif_cb); + +/*! + * \brief Unregister Netif Destroy callback. + * + * \param [netif_cb] netif_cb destroy callback function. + * + * \retval SHR_E_NONE No errors. + */ +extern int +ngknet_netif_destroy_cb_unregister(ngknet_netif_cb_f netif_cb); + +#endif /* NGKNET_CALLBACK_H */ + diff --git a/platform/broadcom/saibcm-modules/sdklt/linux/knet/ngknet_dep.h b/platform/broadcom/saibcm-modules/sdklt/linux/knet/ngknet_dep.h new file mode 100644 index 00000000000..919dd645034 --- /dev/null +++ b/platform/broadcom/saibcm-modules/sdklt/linux/knet/ngknet_dep.h @@ -0,0 +1,61 @@ +/*! \file ngknet_dep.h + * + * Macro definitions for NGKNET dependence. + * + */ +/* + * $Copyright: Copyright 2018-2020 Broadcom. All rights reserved. + * The term 'Broadcom' refers to Broadcom Inc. and/or its subsidiaries. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * version 2 as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * A copy of the GNU General Public License version 2 (GPLv2) can + * be found in the LICENSES folder.$ + */ + +#ifndef NGKNET_DEP_H +#define NGKNET_DEP_H + +#include +#include + +#ifndef TRUE +#define TRUE 1 +#endif +#ifndef FALSE +#define FALSE 0 +#endif + +/*! Memorry barrier */ +#define MEMORY_BARRIER smp_mb() + +/*! CNET print uitility */ +#define CNET_PR(fmt, args...) printk(fmt, ##args) + +struct pdma_dev; + +/*! Externs for the required functions. */ +#define BCMDRD_DEVLIST_ENTRY(_nm,_vn,_dv,_rv,_md,_pi,_bd,_bc,_fn,_cn,_pf,_pd,_r0,_r1) \ +extern int _bd##_cnet_pdma_attach(struct pdma_dev *dev); \ +extern int _bd##_cnet_pdma_detach(struct pdma_dev *dev); +#include + +/*! Create enumeration values from list of supported devices. */ +#define BCMDRD_DEVLIST_ENTRY(_nm,_vn,_dv,_rv,_md,_pi,_bd,_bc,_fn,_cn,_pf,_pd,_r0,_r1) \ + NGKNET_DEV_T_##_bd, +/*! Enumeration for all base device types. */ +typedef enum { + NGKNET_DEV_T_NONE = 0, +#include + NGKNET_DEV_T_COUNT +} ngknet_dev_type_t; + +#endif /* NGKNET_DEP_H */ + diff --git a/platform/broadcom/saibcm-modules/sdklt/linux/knet/ngknet_extra.c b/platform/broadcom/saibcm-modules/sdklt/linux/knet/ngknet_extra.c new file mode 100644 index 00000000000..00fdb3da884 --- /dev/null +++ b/platform/broadcom/saibcm-modules/sdklt/linux/knet/ngknet_extra.c @@ -0,0 +1,505 @@ +/*! \file ngknet_extra.c + * + * Utility routines for NGKNET enhancement. + * + */ +/* + * $Copyright: Copyright 2018-2020 Broadcom. All rights reserved. + * The term 'Broadcom' refers to Broadcom Inc. and/or its subsidiaries. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * version 2 as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * A copy of the GNU General Public License version 2 (GPLv2) can + * be found in the LICENSES folder.$ + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include "ngknet_main.h" +#include "ngknet_extra.h" +#include "ngknet_callback.h" + +static struct ngknet_rl_ctrl rl_ctrl; + +int +ngknet_filter_create(struct ngknet_dev *dev, ngknet_filter_t *filter) +{ + struct filt_ctrl *fc = NULL; + struct list_head *list = NULL; + ngknet_filter_t *filt = NULL; + unsigned long flags; + int num, id, done = 0; + + switch (filter->type) { + case NGKNET_FILTER_T_RX_PKT: + break; + default: + return SHR_E_UNAVAIL; + } + + switch (filter->dest_type) { + case NGKNET_FILTER_DEST_T_NULL: + case NGKNET_FILTER_DEST_T_NETIF: + case NGKNET_FILTER_DEST_T_VNET: + case NGKNET_FILTER_DEST_T_CB: /* SDKLT-26907: support NGKNET_FILTER_DEST_T_CB */ + break; + default: + return SHR_E_UNAVAIL; + } + + spin_lock_irqsave(&dev->lock, flags); + + num = (long)dev->fc[0]; + for (id = 1; id < num + 1; id++) { + if (!dev->fc[id]) { + break; + } + } + if (id > NUM_FILTER_MAX) { + spin_unlock_irqrestore(&dev->lock, flags); + return SHR_E_RESOURCE; + } + + fc = kzalloc(sizeof(*fc), GFP_KERNEL); + if (!fc) { + spin_unlock_irqrestore(&dev->lock, flags); + return SHR_E_MEMORY; + } + + dev->fc[id] = fc; + num += id == (num + 1) ? 1 : 0; + dev->fc[0] = (void *)(long)num; + + memcpy(&fc->filt, filter, sizeof(fc->filt)); + fc->filt.id = id; + + list_for_each(list, &dev->filt_list) { + filt = &((struct filt_ctrl *)list)->filt; + if (filt->flags & NGKNET_FILTER_F_MATCH_CHAN) { + if (!(fc->filt.flags & NGKNET_FILTER_F_MATCH_CHAN) || + fc->filt.chan > filt->chan) { + continue; + } + if (fc->filt.chan < filt->chan || + fc->filt.priority < filt->priority) { + list_add_tail(&fc->list, list); + done = 1; + break; + } + } else { + if (fc->filt.flags & NGKNET_FILTER_F_MATCH_CHAN || + fc->filt.priority < filt->priority) { + list_add_tail(&fc->list, list); + done = 1; + break; + } + } + } + if (!done) { + list_add_tail(&fc->list, &dev->filt_list); + } + + filter->id = fc->filt.id; + + spin_unlock_irqrestore(&dev->lock, flags); + + return SHR_E_NONE; +} + +int +ngknet_filter_destroy(struct ngknet_dev *dev, int id) +{ + struct filt_ctrl *fc = NULL; + unsigned long flags; + int num; + + if (id <= 0 || id > NUM_FILTER_MAX) { + return SHR_E_PARAM; + } + + spin_lock_irqsave(&dev->lock, flags); + + fc = (struct filt_ctrl *)dev->fc[id]; + if (!fc) { + spin_unlock_irqrestore(&dev->lock, flags); + return SHR_E_NOT_FOUND; + } + + list_del(&fc->list); + kfree(fc); + + dev->fc[id] = NULL; + num = (long)dev->fc[0]; + while (num-- == id--) { + if (dev->fc[id]) { + dev->fc[0] = (void *)(long)num; + break; + } + } + + spin_unlock_irqrestore(&dev->lock, flags); + + return SHR_E_NONE; +} + +int +ngknet_filter_destroy_all(struct ngknet_dev *dev) +{ + int id; + int rv; + + for (id = 1; id <= NUM_FILTER_MAX; id++) { + rv = ngknet_filter_destroy(dev, id); + if (SHR_FAILURE(rv)) { + return rv; + } + } + + return SHR_E_NONE; +} + +int +ngknet_filter_get(struct ngknet_dev *dev, int id, ngknet_filter_t *filter) +{ + struct filt_ctrl *fc = NULL; + unsigned long flags; + int num; + + if (id <= 0 || id > NUM_FILTER_MAX) { + return SHR_E_PARAM; + } + + spin_lock_irqsave(&dev->lock, flags); + + fc = (struct filt_ctrl *)dev->fc[id]; + if (!fc) { + spin_unlock_irqrestore(&dev->lock, flags); + return SHR_E_NOT_FOUND; + } + + memcpy(filter, &fc->filt, sizeof(*filter)); + + num = (long)dev->fc[0]; + for (id++; id < num + 1; id++) { + if (dev->fc[id]) { + break; + } + } + filter->next = id == (num + 1) ? 0 : id; + + spin_unlock_irqrestore(&dev->lock, flags); + + return SHR_E_NONE; +} + +int +ngknet_filter_get_next(struct ngknet_dev *dev, ngknet_filter_t *filter) +{ + int id; + int rv; + + if (!filter->next) { + for (id = 1; id <= NUM_FILTER_MAX; id++) { + rv = ngknet_filter_get(dev, id, filter); + if (SHR_SUCCESS(rv)) { + return rv; + } + } + if (id > NUM_FILTER_MAX) { + return SHR_E_NOT_FOUND; + } + } + + return ngknet_filter_get(dev, filter->next, filter); +} + +int +ngknet_rx_pkt_filter(struct ngknet_dev *dev, struct sk_buff *skb, struct net_device **ndev, + struct net_device **mndev, struct sk_buff **mskb) +{ + struct pkt_buf *pkb = (struct pkt_buf *)skb->data; + struct net_device *dest_ndev = NULL, *mirror_ndev = NULL; + struct sk_buff *mirror_skb = NULL; + struct ngknet_private *priv = NULL; + struct filt_ctrl *fc = NULL; + struct list_head *list = NULL; + ngknet_filter_t scratch, *filt = NULL, *filt_cb = NULL; + uint8_t *oob = &pkb->data, *data = NULL; + uint16_t tpid; + unsigned long flags; + int wsize; + int chan_id; + int idx, match = 0, match_cb = 0; + + bcmcnet_pdma_dev_queue_to_chan(&dev->pdma_dev, pkb->pkh.queue_id, + PDMA_Q_RX, &chan_id); + + spin_lock_irqsave(&dev->lock, flags); + + dest_ndev = dev->bdev[chan_id]; + if (dest_ndev) { + skb->dev = dest_ndev; + priv = netdev_priv(dest_ndev); + priv->users++; + *ndev = dest_ndev; + spin_unlock_irqrestore(&dev->lock, flags); + return SHR_E_NONE; + } + + if (list_empty(&dev->filt_list)) { + spin_unlock_irqrestore(&dev->lock, flags); + return SHR_E_NONE; + } + + list_for_each(list, &dev->filt_list) { + fc = (struct filt_ctrl *)list; + filt = &fc->filt; + if (filt->flags & NGKNET_FILTER_F_ANY_DATA) { + match = 1; + break; + } + if (filt->flags & NGKNET_FILTER_F_MATCH_CHAN && filt->chan != chan_id) { + continue; + } + memcpy(&scratch.data.b[0], + &oob[filt->oob_data_offset], filt->oob_data_size); + memcpy(&scratch.data.b[filt->oob_data_size], + &pkb->data + pkb->pkh.meta_len + filt->pkt_data_offset, + filt->pkt_data_size); + wsize = NGKNET_BYTES2WORDS(filt->oob_data_size + filt->pkt_data_size); + for (idx = 0; idx < wsize; idx++) { + scratch.data.w[idx] &= filt->mask.w[idx]; + if (scratch.data.w[idx] != filt->data.w[idx]) { + break; + } + } + if (idx == wsize) { + if (NGKNET_FILTER_DEST_T_CB == filt->dest_type) { + match_cb = 1; + filt_cb = filt; + continue; + } + match = 1; + break; + } + } + + if (match) { + fc->hits++; + switch (filt->dest_type) { + case NGKNET_FILTER_DEST_T_NETIF: + if (filt->dest_id == 0) { + dest_ndev = dev->net_dev; + } else { + dest_ndev = dev->vdev[filt->dest_id]; + } + if (dest_ndev) { + skb->dev = dest_ndev; + if (filt->dest_proto) { + pkb->pkh.attrs |= PDMA_RX_SET_PROTO; + skb->protocol = filt->dest_proto; + } + priv = netdev_priv(dest_ndev); + priv->users++; + } + break; + case NGKNET_FILTER_DEST_T_VNET: + pkb->pkh.attrs |= PDMA_RX_TO_VNET; + spin_unlock_irqrestore(&dev->lock, flags); + return SHR_E_NO_HANDLER; + case NGKNET_FILTER_DEST_T_NULL: + default: + spin_unlock_irqrestore(&dev->lock, flags); + return SHR_E_UNAVAIL; + } + } + + spin_unlock_irqrestore(&dev->lock, flags); + + if (!dest_ndev) { + return SHR_E_NONE; + } else { + *ndev = dest_ndev; + } + + if (filt->flags & NGKNET_FILTER_F_STRIP_TAG) { + pkb->pkh.attrs |= PDMA_RX_STRIP_TAG; + data = skb->data + PKT_HDR_SIZE + pkb->pkh.meta_len; + tpid = data[12] << 8 | data[13]; + if (tpid == ETH_P_8021Q || tpid == ETH_P_8021AD) { + pkb->pkh.data_len -= VLAN_HLEN; + memmove(skb->data + VLAN_HLEN, skb->data, + PKT_HDR_SIZE + pkb->pkh.meta_len + 2 * ETH_ALEN); + skb_pull(skb, VLAN_HLEN); + } + } + + if (dev->cbc->rx_cb) { + NGKNET_SKB_CB(skb)->filt = filt; + + /* Add callback filter if matched */ + if (match_cb) { + NGKNET_SKB_CB(skb)->filt_cb = filt_cb; + } + } + + if (filt->mirror_type == NGKNET_FILTER_DEST_T_NETIF) { + spin_lock_irqsave(&dev->lock, flags); + if (filt->mirror_id == 0) { + mirror_ndev = dev->net_dev; + } else { + mirror_ndev = dev->vdev[filt->mirror_id]; + } + if (mirror_ndev) { + mirror_skb = pskb_copy(skb, GFP_ATOMIC); + if (mirror_skb) { + mirror_skb->dev = mirror_ndev; + if (filt->mirror_proto) { + pkb->pkh.attrs |= PDMA_RX_SET_PROTO; + mirror_skb->protocol = filt->mirror_proto; + } + if (dev->cbc->rx_cb) { + NGKNET_SKB_CB(mirror_skb)->filt = filt; + } + priv = netdev_priv(mirror_ndev); + priv->users++; + *mndev = mirror_ndev; + *mskb = mirror_skb; + } + } + spin_unlock_irqrestore(&dev->lock, flags); + } + + return SHR_E_NONE; +} + +static void +ngknet_rl_process(timer_context_t data) +{ + struct ngknet_rl_ctrl *rc = timer_arg(rc, data, timer); + struct ngknet_dev *dev; + unsigned long flags; + int idx; + + spin_lock_irqsave(&rc->lock, flags); + rc->rx_pkts = 0; + for (idx = 0; idx < NUM_PDMA_DEV_MAX; idx++) { + dev = &rc->devs[idx]; + if (rc->dev_active[idx] && rc->dev_paused[idx]) { + bcmcnet_pdma_dev_rx_resume(&dev->pdma_dev); + rl_ctrl.dev_paused[dev->dev_no] = 0; + } + } + spin_unlock_irqrestore(&rc->lock, flags); + + rc->timer.expires = jiffies + HZ / rc->rx_ticks; + add_timer(&rc->timer); +} + +void +ngknet_rx_rate_limit_init(struct ngknet_dev *devs) +{ + sal_memset(&rl_ctrl, 0, sizeof(rl_ctrl)); + rl_ctrl.rx_ticks = 10; + setup_timer(&rl_ctrl.timer, ngknet_rl_process, (timer_context_t)&rl_ctrl); + spin_lock_init(&rl_ctrl.lock); + rl_ctrl.devs = devs; +} + +void +ngknet_rx_rate_limit_cleanup(void) +{ + del_timer_sync(&rl_ctrl.timer); +} + +int +ngknet_rx_rate_limit_started(void) +{ + return rl_ctrl.started; +} + +void +ngknet_rx_rate_limit_start(struct ngknet_dev *dev) +{ + unsigned long flags; + + spin_lock_irqsave(&rl_ctrl.lock, flags); + rl_ctrl.dev_active[dev->dev_no] = 1; + spin_unlock_irqrestore(&rl_ctrl.lock, flags); + + if (!rl_ctrl.started) { + rl_ctrl.started = 1; + rl_ctrl.timer.expires = jiffies + HZ / rl_ctrl.rx_ticks; + add_timer(&rl_ctrl.timer); + } +} + +void +ngknet_rx_rate_limit_stop(struct ngknet_dev *dev) +{ + unsigned long flags; + + spin_lock_irqsave(&rl_ctrl.lock, flags); + rl_ctrl.dev_active[dev->dev_no] = 0; + spin_unlock_irqrestore(&rl_ctrl.lock, flags); +} + +void +ngknet_rx_rate_limit(struct ngknet_dev *dev, int limit) +{ + unsigned long flags; + + spin_lock_irqsave(&rl_ctrl.lock, flags); + if ((++rl_ctrl.rx_pkts + rl_ctrl.rx_overruns > limit / rl_ctrl.rx_ticks) && + !rl_ctrl.dev_paused[dev->dev_no] && rl_ctrl.dev_active[dev->dev_no]) { + rl_ctrl.dev_paused[dev->dev_no] = 1; + rl_ctrl.rx_overruns = 0; + bcmcnet_pdma_dev_rx_suspend(&dev->pdma_dev); + } + if (rl_ctrl.dev_paused[dev->dev_no]) { + rl_ctrl.rx_overruns++; + } + spin_unlock_irqrestore(&rl_ctrl.lock, flags); +} + +void +ngknet_tx_queue_schedule(struct ngknet_dev *dev, struct sk_buff *skb, int *queue) +{ + struct pkt_buf *pkb = (struct pkt_buf *)skb->data; + + if (pkb->pkh.attrs & PDMA_TX_BIND_QUE) { + *queue = pkb->pkh.queue_id; + } +} + diff --git a/platform/broadcom/saibcm-modules/sdklt/linux/knet/ngknet_extra.h b/platform/broadcom/saibcm-modules/sdklt/linux/knet/ngknet_extra.h new file mode 100644 index 00000000000..27dea9e368e --- /dev/null +++ b/platform/broadcom/saibcm-modules/sdklt/linux/knet/ngknet_extra.h @@ -0,0 +1,218 @@ +/*! \file ngknet_extra.h + * + * Generic data structure definitions for NGKNET enhancement. + * + */ +/* + * $Copyright: Copyright 2018-2020 Broadcom. All rights reserved. + * The term 'Broadcom' refers to Broadcom Inc. and/or its subsidiaries. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * version 2 as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * A copy of the GNU General Public License version 2 (GPLv2) can + * be found in the LICENSES folder.$ + */ + +#ifndef NGKNET_EXTRA_H +#define NGKNET_EXTRA_H + +/*! + * \brief Filter control. + */ +struct filt_ctrl { + /*! List head */ + struct list_head list; + + /*! Device number */ + int dev_no; + + /*! Number of hits */ + uint64_t hits; + + /*! Filter description */ + ngknet_filter_t filt; +}; + +/*! + * \brief Create filter. + * + * \param [in] dev Device structure point. + * \param [in] filter Filter structure point. + * + * \retval SHR_E_NONE No errors. + * \retval SHR_E_XXXX Operation failed. + */ +extern int +ngknet_filter_create(struct ngknet_dev *dev, ngknet_filter_t *filter); + +/*! + * \brief Destroy filter. + * + * \param [in] dev Device structure point. + * \param [in] id Filter ID. + * + * \retval SHR_E_NONE No errors. + * \retval SHR_E_XXXX Operation failed. + */ +extern int +ngknet_filter_destroy(struct ngknet_dev *dev, int id); + +/*! + * \brief Destroy all the filters. + * + * \param [in] dev Device structure point. + * + * \retval SHR_E_NONE No errors. + * \retval SHR_E_XXXX Operation failed. + */ +extern int +ngknet_filter_destroy_all(struct ngknet_dev *dev); + +/*! + * \brief Get filter. + * + * \param [in] dev Device structure point. + * \param [in] id Filter ID. + * \param [out] filter Filter structure point. + * + * \retval SHR_E_NONE No errors. + * \retval SHR_E_XXXX Operation failed. + */ +extern int +ngknet_filter_get(struct ngknet_dev *dev, int id, ngknet_filter_t *filter); + +/*! + * \brief Get the next filter. + * + * \param [in] dev Device structure point. + * \param [out] filter Filter structure point. + * + * \retval SHR_E_NONE No errors. + * \retval SHR_E_XXXX Operation failed. + */ +extern int +ngknet_filter_get_next(struct ngknet_dev *dev, ngknet_filter_t *filter); + +/*! + * \brief Filter packet. + * + * \param [in] dev Device structure point. + * \param [in] skb Rx packet SKB. + * \param [out] mndev Mirror network interface. + * \param [out] mskb Mirror Rx packet SKB. + * + * \retval Matched network interface. + * \retval NULL No matched network interface. + */ +extern int +ngknet_rx_pkt_filter(struct ngknet_dev *dev, struct sk_buff *skb, struct net_device **ndev, + struct net_device **mndev, struct sk_buff **mskb); + +/*! + * \brief Rx rate limit control. + * + * This contains all the control information for Rx rate limit such as + * the number of Rx packets, status related to Rx rate limit, etc. + * + * The rate limit is kernel-oriented, i.e. all the Rx packets from any + * device/channel will be accounted for. Once the received packets reach + * the limit value in an 1-Sec interval, the driver API XXXX_rx_suspend() + * will be called to suspend Rx. The 1-Sec basis timer will call the driver + * API XXXX_rx_resume() to resume Rx and reset rate-related status/counters + * at the begin of the next 1-Sec interval. + * + * The NGKNET module parameter 'rx_rate_limit' is used to decide the maximum + * Rx rate. Disable Rx rate limit if set 0. It can be set when inserting + * NGKNET module or modified using its SYSFS attributions. + */ +struct ngknet_rl_ctrl { + /*! Rx packets */ + int rx_pkts; + + /*! Rx overruns */ + int rx_overruns; + + /*! Rx ticks */ + int rx_ticks; + + /*! Active devices under rate control */ + int dev_active[NUM_PDMA_DEV_MAX]; + + /*! Paused devices due to no Rx credit */ + int dev_paused[NUM_PDMA_DEV_MAX]; + + /*! Rate limit timer */ + struct timer_list timer; + + /*! Rate limit lock */ + spinlock_t lock; + + /*! Devices */ + struct ngknet_dev *devs; + + /*! Rate limit status indicator */ + int started; +}; + +/*! + * \brief Initialize Rx rate limit. + * + * \param [in] devs Devices array. + */ +extern void +ngknet_rx_rate_limit_init(struct ngknet_dev *devs); + +/*! + * \brief Cleanup Rx rate limit. + */ +extern void +ngknet_rx_rate_limit_cleanup(void); + +/*! + * \brief Get Rx rate limit state. + */ +extern int +ngknet_rx_rate_limit_started(void); + +/*! + * \brief Start Rx rate limit. + * + * \param [in] dev Device structure point. + */ +extern void +ngknet_rx_rate_limit_start(struct ngknet_dev *dev); + +/*! + * \brief Stop Rx rate limit. + * + * \param [in] dev Device structure point. + */ +extern void +ngknet_rx_rate_limit_stop(struct ngknet_dev *dev); + +/*! + * \brief Limit Rx rate. + * + * \param [in] dev Device structure point. + */ +extern void +ngknet_rx_rate_limit(struct ngknet_dev *dev, int limit); + +/*! + * \brief Schedule Tx queue. + * + * \param [in] dev Device structure point. + * \param [in] queue Tx queue number. + */ +extern void +ngknet_tx_queue_schedule(struct ngknet_dev *dev, struct sk_buff *skb, int *queue); + +#endif /* NGKNET_EXTRA_H */ + diff --git a/platform/broadcom/saibcm-modules/sdklt/linux/knet/ngknet_linux.c b/platform/broadcom/saibcm-modules/sdklt/linux/knet/ngknet_linux.c new file mode 100644 index 00000000000..0162ae5b96c --- /dev/null +++ b/platform/broadcom/saibcm-modules/sdklt/linux/knet/ngknet_linux.c @@ -0,0 +1,173 @@ +/*! \file ngknet_linux.c + * + * Utility routines for Linux kernel APIs abstraction. + * + */ +/* + * $Copyright: Copyright 2018-2020 Broadcom. All rights reserved. + * The term 'Broadcom' refers to Broadcom Inc. and/or its subsidiaries. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * version 2 as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * A copy of the GNU General Public License version 2 (GPLv2) can + * be found in the LICENSES folder.$ + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "ngknet_linux.h" + +/*! + * Time + */ + +unsigned long +sal_time_usecs(void) +{ + struct timeval tv; + + kal_time_val_get(&tv); + + return tv.tv_sec * 1000000 + tv.tv_usec; +} + +void +sal_usleep(unsigned long usec) +{ + unsigned long then, now, hz; + + hz = usec * HZ / 1000000; + if (hz) { + schedule_timeout(hz); + } + usec = usec * HZ % 1000000 / HZ; + if (usec) { + then = sal_time_usecs(); + do { + schedule(); + now = sal_time_usecs(); + } while (now > then && (now - then) < usec); + } +} + +/*! + * Synchronization + */ + +typedef struct { + struct semaphore sem; + char *desc; + int binary; +} sem_ctrl_t; + +sal_sem_t +sal_sem_create(char *desc, int binary, int count) +{ + sem_ctrl_t *sc = kmalloc(sizeof(*sc), GFP_KERNEL); + + if (sc != NULL) { + sema_init(&sc->sem, count); + sc->desc = desc; + sc->binary = binary; + } + + return (sal_sem_t)sc; +} + +void +sal_sem_destroy(sal_sem_t sem) +{ + sem_ctrl_t *sc = (sem_ctrl_t *)sem; + + kfree(sc); +} + +int +sal_sem_take(sal_sem_t sem, int usec) +{ + sem_ctrl_t *sc = (sem_ctrl_t *)sem; + int rv; + + if (usec == SAL_SEM_FOREVER) { + do { + rv = down_interruptible(&sc->sem); + } while (rv == -EINTR); + return rv ? -1 : 0; + } + + return -1; +} + +int +sal_sem_give(sal_sem_t sem) +{ + sem_ctrl_t *sc = (sem_ctrl_t *)sem; + + up(&sc->sem); + + return 0; +} + +typedef struct spinlock_ctrl_s { + spinlock_t spinlock; + unsigned long flags; + char *desc; +} *spinlock_ctrl_t; + +sal_spinlock_t +sal_spinlock_create(char *desc) +{ + spinlock_ctrl_t sl = kmalloc(sizeof(*sl), GFP_KERNEL); + + if (sl != NULL) { + spin_lock_init(&sl->spinlock); + sl->flags = 0; + sl->desc = desc; + } + + return (sal_spinlock_t)sl; +} + +void +sal_spinlock_destroy(sal_spinlock_t lock) +{ + spinlock_ctrl_t sl = (spinlock_ctrl_t)lock; + + kfree(sl); +} + +int +sal_spinlock_lock(sal_spinlock_t lock) +{ + spinlock_ctrl_t sl = (spinlock_ctrl_t)lock; + + spin_lock_irqsave(&sl->spinlock, sl->flags); + + return 0; +} + +int +sal_spinlock_unlock(sal_spinlock_t lock) +{ + spinlock_ctrl_t sl = (spinlock_ctrl_t)lock; + + spin_unlock_irqrestore(&sl->spinlock, sl->flags); + + return 0; +} + diff --git a/platform/broadcom/saibcm-modules/sdklt/linux/knet/ngknet_linux.h b/platform/broadcom/saibcm-modules/sdklt/linux/knet/ngknet_linux.h new file mode 100644 index 00000000000..686aac8f557 --- /dev/null +++ b/platform/broadcom/saibcm-modules/sdklt/linux/knet/ngknet_linux.h @@ -0,0 +1,240 @@ +/*! \file ngknet_linux.h + * + * Data structure and macro definitions for Linux kernel APIs abstraction. + * + */ +/* + * $Copyright: Copyright 2018-2020 Broadcom. All rights reserved. + * The term 'Broadcom' refers to Broadcom Inc. and/or its subsidiaries. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * version 2 as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * A copy of the GNU General Public License version 2 (GPLv2) can + * be found in the LICENSES folder.$ + */ + +#ifndef NGKNET_LINUX_H +#define NGKNET_LINUX_H + +#include +#include +#include +#include + +/*! + * Kernel abstraction + */ + +#define MODULE_PARAM(n, t, p) module_param(n, t, p) + +#if LINUX_VERSION_CODE < KERNEL_VERSION(3,10,0) +#define kal_vlan_hwaccel_put_tag(skb, proto, tci) \ + __vlan_hwaccel_put_tag(skb, tci) +#define NETIF_F_HW_VLAN_CTAG_RX NETIF_F_HW_VLAN_RX +#define NETIF_F_HW_VLAN_CTAG_TX NETIF_F_HW_VLAN_TX +#else +#define kal_vlan_hwaccel_put_tag(skb, proto, tci) \ + __vlan_hwaccel_put_tag(skb, htons(proto), tci) +#endif /* KERNEL_VERSION(3,10,0) */ + +#if LINUX_VERSION_CODE < KERNEL_VERSION(3,6,0) +static inline int +kal_support_paged_skb(void) +{ + return false; +} +#else +static inline int +kal_support_paged_skb(void) +{ + return true; +} +#endif /* KERNEL_VERSION(3,6,0) */ + +#if LINUX_VERSION_CODE < KERNEL_VERSION(3,6,0) +static inline struct page * +kal_dev_alloc_page(void) +{ + return NULL; +} +#elif LINUX_VERSION_CODE < KERNEL_VERSION(3,19,0) +static inline struct page * +kal_dev_alloc_page(void) +{ + return alloc_pages(GFP_ATOMIC | __GFP_ZERO | __GFP_COLD | + __GFP_COMP | __GFP_MEMALLOC, 0); +} +#else +static inline struct page * +kal_dev_alloc_page(void) +{ + return dev_alloc_page(); +} +#endif /* KERNEL_VERSION(3,6,0) */ + +#if LINUX_VERSION_CODE < KERNEL_VERSION(3,6,0) +static inline struct sk_buff * +kal_build_skb(void *data, unsigned int frag_size) +{ + return NULL; +} +#else +static inline struct sk_buff * +kal_build_skb(void *data, unsigned int frag_size) +{ + return build_skb(data, frag_size); +} +#endif /* KERNEL_VERSION(3,6,0) */ + +#if LINUX_VERSION_CODE < KERNEL_VERSION(4,7,0) +static inline void +kal_netif_trans_update(struct net_device *dev) +{ + dev->trans_start = jiffies; +} +#else +static inline void +kal_netif_trans_update(struct net_device *dev) +{ + netif_trans_update(dev); +} +#endif /* KERNEL_VERSION(4,7,0) */ + +#if LINUX_VERSION_CODE < KERNEL_VERSION(3,17,0) +static inline void +kal_time_val_get(struct timeval *tv) +{ + do_gettimeofday(tv); +} +#else +static inline void +kal_time_val_get(struct timeval *tv) +{ + struct timespec64 ts; + ktime_get_real_ts64(&ts); + tv->tv_sec = ts.tv_sec; + tv->tv_usec = ts.tv_nsec / 1000; +} +#endif /* KERNEL_VERSION(3,17,0) */ + +static inline unsigned long +kal_copy_from_user(void *to, const void __user *from, + unsigned int dl, unsigned int sl) +{ + unsigned int len = dl; + + if (unlikely(len != sl)) { + printk(KERN_WARNING "Unmatched linux_ngknet.ko, please use the latest.\n"); + len = min(dl, sl); + } + + return copy_from_user(to, from, len); +} + +static inline unsigned long +kal_copy_to_user(void __user *to, const void *from, + unsigned int dl, unsigned int sl) +{ + unsigned int len = dl; + + if (unlikely(len != sl)) { + printk(KERN_WARNING "Unmatched linux_ngknet.ko, please use the latest.\n"); + len = min(dl, sl); + } + + return copy_to_user(to, from, len); +} + +/*! + * System abstraction + */ + +static inline void * +sal_alloc(unsigned int sz, char *s) +{ + return kmalloc(sz, GFP_KERNEL); +} + +static inline void +sal_free(void *addr) +{ + kfree(addr); +} + +static inline void * +sal_memset(void *dest, int c, size_t cnt) +{ + return memset(dest, c, cnt); +} + +static inline void * +sal_memcpy(void *dest, const void *src, size_t cnt) +{ + return memcpy(dest, src, cnt); +} + +static inline char * +sal_strncpy(char *dest, const char *src, size_t cnt) +{ + return strncpy(dest, src, cnt); +} + +/*! + * Time + */ + +extern unsigned long +sal_time_usecs(void); + +extern void +sal_usleep(unsigned long usec); + +/*! + * Synchronization + */ + +typedef struct sal_sem_s { + char semaphore_opaque_type; +} *sal_sem_t; + +typedef struct sal_spinlock_s { + char spinlock_opaque_type; +} *sal_spinlock_t; + +#define SAL_SEM_FOREVER -1 +#define SAL_SEM_BINARY 1 +#define SAL_SEM_COUNTING 0 + +extern sal_sem_t +sal_sem_create(char *desc, int binary, int count); + +extern void +sal_sem_destroy(sal_sem_t sem); + +extern int +sal_sem_take(sal_sem_t sem, int usec); + +extern int +sal_sem_give(sal_sem_t sem); + +extern sal_spinlock_t +sal_spinlock_create(char *desc); + +extern void +sal_spinlock_destroy(sal_spinlock_t lock); + +extern int +sal_spinlock_lock(sal_spinlock_t lock); + +extern int +sal_spinlock_unlock(sal_spinlock_t lock); + +#endif /* NGKNET_LINUX_H */ + diff --git a/platform/broadcom/saibcm-modules/sdklt/linux/knet/ngknet_main.c b/platform/broadcom/saibcm-modules/sdklt/linux/knet/ngknet_main.c new file mode 100644 index 00000000000..b8af31d85ff --- /dev/null +++ b/platform/broadcom/saibcm-modules/sdklt/linux/knet/ngknet_main.c @@ -0,0 +1,2689 @@ +/*! \file ngknet_main.c + * + * NGKNET module entry. + * + */ +/* + * $Copyright: Copyright 2018-2020 Broadcom. All rights reserved. + * The term 'Broadcom' refers to Broadcom Inc. and/or its subsidiaries. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * version 2 as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * A copy of the GNU General Public License version 2 (GPLv2) can + * be found in the LICENSES folder.$ + */ + +/* + * This module implements a Linux network driver for Broadcom + * XGS switch devices. The driver simultaneously serves a + * number of virtual Linux network devices. + * + * Packets received from the switch device are sent to a virtual + * Linux network device based on a set of packet filters. + * + * Packets from the virtual Linux network devices are multiplexed + * with fifo mode if only one Tx queue enabled. + * + * A command-based IOCTL interface is used for managing the devices, + * packet filters and virtual Linux network interfaces. + * + * A virtual network interface can be configured to work in RCPU + * mode, which means that packets from the switch device will + * be encapsulated with a RCPU header and a block of meta data + * that basically contains the core DCB information. Likewise, + * packets received from the Linux network stack are assumed to + * be RCPU encapsulated when going out on an interface in RCPU + * mode. If a virtual network interface does not work in RCPU + * mode and transmits to this interface will unmodified go to + * specified physical switch port, DCB information should be + * provided when the interface is created. + * + * The module implements basic Rx DMA rate control. The rate is + * specified in packets per second, and different Rx DMA channels + * can be configured to use different maximum packet rates. + * The packet rate can be configure as a module parameter, and + * it can also be changed dynamically through the proc file + * system (syntax is described in function header comment). + * + * For a list of supported module parameters, please see below. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include "ngknet_main.h" +#include "ngknet_extra.h" +#include "ngknet_procfs.h" +#include "ngknet_callback.h" +#include "ngknet_ptp.h" + +/*! \cond */ +MODULE_AUTHOR("Broadcom Corporation"); +MODULE_DESCRIPTION("Network Device Driver Module"); +MODULE_LICENSE("GPL"); +/*! \endcond */ + +/*! \cond */ +static int debug = 0; +MODULE_PARAM(debug, int, 0); +MODULE_PARM_DESC(debug, +"Debug level (default 0)"); +/*! \endcond */ + +/*! \cond */ +static char *base_dev_name = "bcm"; +MODULE_PARAM(base_dev_name, charp, 0); +MODULE_PARM_DESC(base_dev_name, +"Base device name (default bcm0, bcm1, etc.)"); +/*! \endcond */ + +/*! \cond */ +static char *mac_addr = NULL; +MODULE_PARAM(mac_addr, charp, 0); +MODULE_PARM_DESC(mac_addr, +"Ethernet MAC address (default 02:10:18:xx:xx:xx)"); +/*! \endcond */ + +/*! \cond */ +static int default_mtu = 1500; +MODULE_PARAM(default_mtu, int, 0); +MODULE_PARM_DESC(default_mtu, +"Default MTU for NGKNET network interfaces (default 1500)"); +/*! \endcond */ + +/*! \cond */ +static int rx_buffer_size = RX_BUF_SIZE_DFLT; +MODULE_PARAM(rx_buffer_size, int, 0); +MODULE_PARM_DESC(rx_buffer_size, +"Default size of RX packet buffers (default 9216)"); +/*! \endcond */ + +/*! \cond */ +static int rx_rate_limit = -1; +MODULE_PARAM(rx_rate_limit, int, 0); +MODULE_PARM_DESC(rx_rate_limit, +"Rx rate limit (pps, default -1 no limit)"); +/*! \endcond */ + +/*! \cond */ +static int tx_polling = 0; +MODULE_PARAM(tx_polling, int, 0); +MODULE_PARM_DESC(tx_polling, +"Tx polling mode (default 0 in interrupt mode)"); +/*! \endcond */ + +/*! \cond */ +static int rx_batching = 0; +MODULE_PARAM(rx_batching, int, 0); +MODULE_PARM_DESC(rx_batching, +"Rx batching mode (default 0 in single fill mode)"); +/*! \endcond */ + +typedef int (*drv_ops_attach)(struct pdma_dev *dev); + +struct bcmcnet_drv_ops { + const char *drv_desc; + drv_ops_attach drv_attach; + drv_ops_attach drv_detach; +}; + +#define BCMDRD_DEVLIST_ENTRY(_nm,_vn,_dv,_rv,_md,_pi,_bd,_bc,_fn,_cn,_pf,_pd,_r0,_r1) \ + static struct bcmcnet_drv_ops _bd##_cnet_drv_ops = { \ + #_bd, \ + _bd##_cnet_pdma_attach, \ + _bd##_cnet_pdma_detach, \ + }; +#include + +#define BCMDRD_DEVLIST_ENTRY(_nm,_vn,_dv,_rv,_md,_pi,_bd,_bc,_fn,_cn,_pf,_pd,_r0,_r1) \ + &_bd##_cnet_drv_ops, +static struct bcmcnet_drv_ops *drv_ops[] = { + NULL, +#include + NULL +}; +static int drv_num = sizeof(drv_ops) / sizeof(drv_ops[0]); + +struct ngknet_dev ngknet_devices[NUM_PDMA_DEV_MAX]; + +/* Default random MAC address has Broadcom OUI with local admin bit set */ +static uint8_t ngknet_dev_mac[6] = {0x02, 0x10, 0x18, 0x00, 0x00, 0x00}; + +/* Interrupt handles */ +struct ngknet_intr_handle { + struct napi_struct napi; + struct intr_handle *hdl; + int napi_resched; + int napi_pending; +}; + +static struct ngknet_intr_handle priv_hdl[NUM_PDMA_DEV_MAX][NUM_QUE_MAX]; + +/*! + * Dump packet content for debug + */ +static void +ngknet_pkt_dump(uint8_t *data, int len) +{ + char str[128]; + int i; + + len = len > 256 ? 256 : len; + + for (i = 0; i < len; i++) { + if ((i & 0x1f) == 0) { + sprintf(str, "%04x: ", i); + } + sprintf(&str[strlen(str)], "%02x", data[i]); + if ((i & 0x1f) == 0x1f) { + sprintf(&str[strlen(str)], "\n"); + printk(str); + continue; + } + if ((i & 0x3) == 0x3) { + sprintf(&str[strlen(str)], " "); + } + } + if ((i & 0x1f) != 0) { + sprintf(&str[strlen(str)], "\n"); + printk(str); + } + printk("\n"); +} + +/*! + * Rx packets rate test for debug + */ +static void +ngknet_pkt_stats(struct pdma_dev *pdev, int dir) +{ + static struct timeval tv0[2], tv1[2]; + static uint32_t pkts[2] = {0}, prts[2] = {0}; + static uint64_t intrs = 0; + + if (pkts[dir] == 0) { + kal_time_val_get(&tv0[dir]); + intrs = pdev->stats.intrs; + } + if (++pkts[dir] >= 100000) { + uint32_t iv_time; + uint32_t pps; + kal_time_val_get(&tv1[dir]); + iv_time = (tv1[dir].tv_sec - tv0[dir].tv_sec) * 1000000 + + (tv1[dir].tv_usec - tv0[dir].tv_usec); + pps = 100000 * 1000 / (iv_time / 1000); + prts[dir]++; + if (pps <= 100000 || prts[dir] * 100000 >= pps) { + printk(KERN_CRIT "%s -- limit: %d pps, 100K pkts time: %d usec, rate: %d pps, intrs: %llu\n", + dir == PDMA_Q_RX ? "Rx" : "Tx", + dir == PDMA_Q_RX ? rx_rate_limit : -1, + iv_time, pps, pdev->stats.intrs - intrs); + prts[dir] = 0; + } + pkts[dir] = 0; + } +} + +/*! + * Read 32-bit register callback + */ +static int +ngknet_dev_read32(struct pdma_dev *dev, uint32_t addr, uint32_t *data) +{ + *data = ngbde_kapi_pio_read32(dev->unit, addr); + + return 0; +} + +/*! + * Write 32-bit register callback + */ +static int +ngknet_dev_write32(struct pdma_dev *dev, uint32_t addr, uint32_t data) +{ + ngbde_kapi_pio_write32(dev->unit, addr, data); + + return 0; +} + +/*! + * Set Rx HW timestamping. + */ +static int +ngknet_ptp_rx_hwts_set(struct net_device *ndev, struct sk_buff *skb) +{ + struct skb_shared_hwtstamps *shhwtstamps = skb_hwtstamps(skb); + uint64_t ts = 0; + int rv; + + rv = ngknet_ptp_rx_hwts_get(ndev, skb, &ts); + if (SHR_FAILURE(rv) || !ts) { + return SHR_E_FAIL; + } + + memset(shhwtstamps, 0, sizeof(*shhwtstamps)); + shhwtstamps->hwtstamp = ns_to_ktime(ts); + + return SHR_E_NONE; +} + +/*! + * \brief Process Rx packet. + * + * Add RCPU encapsulation or strip matadata if needed + * + * \param [in] ndev Network device structure point. + * \param [in] oskb Rx packet SKB. + * + * \retval SHR_E_NONE No errors. + * \retval SHR_E_XXXX Operation failed. + */ +static int +ngknet_rx_frame_process(struct net_device *ndev, struct sk_buff **oskb) +{ + struct ngknet_private *priv = netdev_priv(ndev); + struct ngknet_dev *dev = priv->bkn_dev; + struct sk_buff *skb = *oskb; + struct ngknet_rcpu_hdr *rch = (struct ngknet_rcpu_hdr *)skb->data; + struct pkt_hdr *pkh = (struct pkt_hdr *)skb->data; + uint8_t meta_len = pkh->meta_len; + + /* Do Rx timestamping */ + if (priv->hwts_rx_filter) { + ngknet_ptp_rx_hwts_set(ndev, skb); + } + + /* Remove FCS from packet length */ + skb_trim(skb, skb->len - ETH_FCS_LEN); + pkh->data_len -= ETH_FCS_LEN; + + if (priv->flags & NGKNET_NETIF_F_RCPU_ENCAP) { + /* Set up RCPU header */ + memcpy(skb->data, skb->data + PKT_HDR_SIZE + meta_len, 2 * ETH_ALEN); + if (*(uint32_t *)&dev->rcpu_ctrl.dst_mac[0] != 0 || + *(uint16_t *)&dev->rcpu_ctrl.dst_mac[4] != 0) { + memcpy(rch->dst_mac, dev->rcpu_ctrl.dst_mac, ETH_ALEN); + } + if (*(uint32_t *)&dev->rcpu_ctrl.src_mac[0] != 0 || + *(uint16_t *)&dev->rcpu_ctrl.src_mac[4] != 0) { + memcpy(rch->src_mac, dev->rcpu_ctrl.src_mac, ETH_ALEN); + } + rch->vlan_tpid = htons(dev->rcpu_ctrl.vlan_tpid); + rch->vlan_tci = htons(dev->rcpu_ctrl.vlan_tci); + rch->eth_type = htons(dev->rcpu_ctrl.eth_type); + rch->pkt_sig = htons(dev->rcpu_ctrl.pkt_sig); + rch->op_code = RCPU_OPCODE_RX; + rch->flags = RCPU_FLAG_MODHDR; + rch->trans_id = htons(dev->rcpu_ctrl.trans_id); + rch->data_len = htons(pkh->data_len); + } else { + /* Remove packet header and meta data */ + skb_pull(skb, PKT_HDR_SIZE + meta_len); + } + + /* Optional callback handle */ + if (dev->cbc->rx_cb) { + struct ngknet_callback_desc *cbd = NGKNET_SKB_CB(skb); + cbd->dev_no = dev->dev_no; + cbd->dev_id = dev->pdma_dev.dev_id; + cbd->type_str = drv_ops[dev->pdma_dev.dev_type]->drv_desc; + cbd->priv = priv; + if (priv->flags & NGKNET_NETIF_F_RCPU_ENCAP) { + cbd->pmd = skb->data + PKT_HDR_SIZE; + cbd->pkt_len = ntohs(rch->data_len); + } else { + cbd->pmd = skb->data - meta_len; + cbd->pkt_len = pkh->data_len; + } + cbd->pmd_len = meta_len; + skb = dev->cbc->rx_cb(skb); + if (!skb) { + *oskb = NULL; + return SHR_E_UNAVAIL; + } + if (priv->flags & NGKNET_NETIF_F_RCPU_ENCAP) { + rch = (struct ngknet_rcpu_hdr *)skb->data; + rch->data_len = htons(skb->len - PKT_HDR_SIZE - meta_len); + } + } + + /* Update SKB pointer */ + *oskb = skb; + + return SHR_E_NONE; +} + +/*! + * \brief Network interface Rx function. + * + * After processing the packet, send it up to network stack. + * + * \param [in] ndev Network device structure point. + * \param [in] skb Rx packet SKB. + * + * \retval SHR_E_NONE No errors. + * \retval SHR_E_XXXX Operation failed. + */ +static int +ngknet_netif_recv(struct net_device *ndev, struct sk_buff *skb) +{ + struct ngknet_private *priv = netdev_priv(ndev); + struct ngknet_dev *dev = priv->bkn_dev; + struct pdma_dev *pdev = &dev->pdma_dev; + struct pkt_hdr *pkh = (struct pkt_hdr *)skb->data; + struct napi_struct *napi = NULL; + uint16_t proto; + int chan, gi, qi; + int rv; + + /* Handle one incoming packet */ + rv = ngknet_rx_frame_process(ndev, &skb); + if (SHR_FAILURE(rv)) { + if (!skb) { + return SHR_E_NONE; + } + } + + DBG_VERB(("Rx packet sent up to ndev%d (%d bytes).\n", priv->id, skb->len)); + if (debug & DBG_LVL_PDMP) { + ngknet_pkt_dump(skb->data, skb->len); + } + + if (ndev->features & NETIF_F_RXCSUM) { + if ((pkh->attrs & (PDMA_RX_TU_CSUM | PDMA_RX_IP_CSUM)) == + (PDMA_RX_TU_CSUM | PDMA_RX_IP_CSUM)) { + skb->ip_summed = CHECKSUM_UNNECESSARY; + } else { + skb_checksum_none_assert(skb); + } + } + + if (!(priv->flags & NGKNET_NETIF_F_RCPU_ENCAP) && + ndev->features & NETIF_F_HW_VLAN_CTAG_RX && + pkh->attrs & PDMA_RX_STRIP_TAG) { + kal_vlan_hwaccel_put_tag(skb, ETH_P_8021Q, priv->vlan); + } + + proto = eth_type_trans(skb, ndev); + if (priv->flags & NGKNET_NETIF_F_RCPU_ENCAP) { + skb->protocol = htons(dev->rcpu_ctrl.eth_type); + } else if (!(pkh->attrs & PDMA_RX_SET_PROTO) || !skb->protocol) { + skb->protocol = proto; + } + + skb_record_rx_queue(skb, pkh->queue_id); + + bcmcnet_pdma_dev_queue_to_chan(pdev, pkh->queue_id, PDMA_Q_RX, &chan); + gi = chan / pdev->grp_queues; + if (pdev->flags & PDMA_GROUP_INTR) { + napi = (struct napi_struct *)pdev->ctrl.grp[gi].intr_hdl[0].priv; + } else { + qi = pkh->queue_id; + napi = (struct napi_struct *)pdev->ctrl.grp[gi].intr_hdl[qi].priv; + } + napi_gro_receive(napi, skb); + + /* Update accounting */ + priv->stats.rx_packets++; + priv->stats.rx_bytes += skb->len; + + /* Rate limit */ + if (rx_rate_limit >= 0) { + if (!ngknet_rx_rate_limit_started()) { + ngknet_rx_rate_limit_start(dev); + } + ngknet_rx_rate_limit(dev, rx_rate_limit); + } + + return SHR_E_NONE; +} + +/*! + * \brief Driver Rx callback. + * + * After processing the packet, send it up to network stack. + * + * \param [in] pdev Packet DMA device structure point. + * \param [in] buf Raw Rx buffer. + * + * \retval SHR_E_NONE No errors. + * \retval SHR_E_XXXX Operation failed. + */ +static int +ngknet_frame_recv(struct pdma_dev *pdev, int queue, void *buf) +{ + struct ngknet_dev *dev = (struct ngknet_dev *)pdev->priv; + struct sk_buff *skb = (struct sk_buff *)buf, *mskb = NULL; + struct net_device *ndev = NULL, *mndev = NULL; + struct ngknet_private *priv = NULL; + unsigned long flags; + int rv; + + DBG_VERB(("Rx packet (%d bytes).\n", skb->len)); + if (debug & DBG_LVL_PDMP) { + ngknet_pkt_dump(skb->data, skb->len); + } + + /* Go through the filters */ + rv = ngknet_rx_pkt_filter(dev, skb, &ndev, &mndev, &mskb); + if (SHR_FAILURE(rv) || !ndev) { + return SHR_E_FAIL; + } + + /* Populate header, checksum status, VLAN, and protocol */ + priv = netdev_priv(ndev); + if (netif_carrier_ok(ndev)) { + ngknet_netif_recv(ndev, skb); + } else { + priv->stats.rx_dropped++; + rv = SHR_E_UNAVAIL; + } + + spin_lock_irqsave(&dev->lock, flags); + priv->users--; + if (!priv->users && priv->wait) { + wake_up(&dev->wq); + } + spin_unlock_irqrestore(&dev->lock, flags); + + /* Handle mirrored packet */ + if (mndev && mskb) { + priv = netdev_priv(mndev); + if (netif_carrier_ok(mndev)) { + ngknet_netif_recv(mndev, mskb); + } else { + priv->stats.rx_dropped++; + dev_kfree_skb_any(mskb); + } + spin_lock_irqsave(&dev->lock, flags); + priv->users--; + if (!priv->users && priv->wait) { + wake_up(&dev->wq); + } + spin_unlock_irqrestore(&dev->lock, flags); + } + + /* Measure speed */ + if (debug & DBG_LVL_RATE) { + ngknet_pkt_stats(pdev, PDMA_Q_RX); + } + + return rv; +} + +/*! + * Set Tx HW timestamping. + */ +static int +ngknet_ptp_tx_hwts_set(struct net_device *ndev, struct sk_buff *skb) +{ + struct skb_shared_hwtstamps shhwtstamps; + uint64_t ts = 0; + int rv; + + rv = ngknet_ptp_tx_hwts_get(ndev, skb, &ts); + if (SHR_FAILURE(rv) || !ts) { + return SHR_E_FAIL; + } + + memset(&shhwtstamps, 0, sizeof(shhwtstamps)); + shhwtstamps.hwtstamp = ns_to_ktime(ts); + skb_tstamp_tx(skb, &shhwtstamps); + + return SHR_E_NONE; +} + +/*! + * PTP Tx worker. + */ +static void +ngknet_ptp_tx_work(struct work_struct *work) +{ + struct ngknet_dev *dev = container_of(work, struct ngknet_dev, ptp_tx_work); + struct sk_buff *skb; + int rv; + + while (skb_queue_len(&dev->ptp_tx_queue)) { + skb = skb_dequeue(&dev->ptp_tx_queue); + rv = ngknet_ptp_tx_hwts_set(dev->net_dev, skb); + if (SHR_FAILURE(rv)) { + printk("Timestamp value has not been set for current skb.\n"); + } + dev_kfree_skb_any(skb); + } +} + +/*! + * Config Tx metadata for HW timestamping. + */ +static int +ngknet_ptp_tx_config(struct net_device *ndev, struct sk_buff *skb) +{ + struct ngknet_private *priv = netdev_priv(ndev); + struct ngknet_dev *dev = priv->bkn_dev; + int rv; + + if (priv->type == NGKNET_NETIF_T_PORT) { + rv = ngknet_ptp_tx_meta_set(ndev, skb); + if (SHR_FAILURE(rv)) { + return rv; + } + } else if (priv->hwts_tx_type != HWTSTAMP_TX_ONESTEP_SYNC) { + return SHR_E_UNAVAIL; + } + + skb_shinfo(skb)->tx_flags |= SKBTX_IN_PROGRESS; + + if (priv->hwts_tx_type == HWTSTAMP_TX_ONESTEP_SYNC) { + skb_queue_tail(&dev->ptp_tx_queue, skb_get(skb)); + schedule_work(&dev->ptp_tx_work); + } + + return SHR_E_NONE; +} + +/*! + * \brief Process Tx packet. + * + * Strip RCPU encapsulation, setup CNET packet buffer, add vlan tag + * or pad the packet. + * + * \param [in] ndev Network device structure point. + * \param [in] oskb Tx packet SKB. + * + * \retval SHR_E_NONE No errors. + * \retval SHR_E_XXXX Operation failed. + */ +static int +ngknet_tx_frame_process(struct net_device *ndev, struct sk_buff **oskb) +{ + struct ngknet_private *priv = netdev_priv(ndev); + struct ngknet_dev *dev = priv->bkn_dev; + struct sk_buff *skb = *oskb; + struct ngknet_rcpu_hdr *rch = (struct ngknet_rcpu_hdr *)skb->data; + struct pkt_hdr *pkh = (struct pkt_hdr *)skb->data; + struct sk_buff *nskb = NULL; + char *data = NULL; + uint32_t copy_len, meta_len, data_len, pkt_len, tag_len; + uint16_t tpid; + + /* Set up packet header */ + if (priv->flags & NGKNET_NETIF_F_RCPU_ENCAP) { + /* RCPU encapsulation packet */ + data_len = pkh->attrs & PDMA_TX_HDR_COOKED ? + pkh->data_len - ETH_FCS_LEN : ntohs(rch->data_len); + pkt_len = PKT_HDR_SIZE + rch->meta_len + data_len; + if (skb->len != pkt_len || skb->len < (PKT_HDR_SIZE + 14)) { + DBG_WARN(("Tx drop: Invalid RCPU encapsulation\n")); + return SHR_E_FAIL; + } + if (dev->rcpu_ctrl.pkt_sig && dev->rcpu_ctrl.pkt_sig != ntohs(rch->pkt_sig)) { + DBG_WARN(("Tx drop: Invalid RCPU signature\n")); + return SHR_E_FAIL; + } + if (pkh->attrs & PDMA_TX_HDR_COOKED) { + /* Resumed packet */ + return SHR_E_NONE; + } + pkh->data_len = data_len + ETH_FCS_LEN; + pkh->meta_len = rch->meta_len; + pkh->attrs = 0; + if (rch->flags & RCPU_FLAG_MODHDR) { + pkh->attrs |= PDMA_TX_HIGIG_PKT; + } + if (rch->flags & RCPU_FLAG_PAUSE) { + pkh->attrs |= PDMA_TX_PAUSE_PKT; + } + if (rch->flags & RCPU_FLAG_PURGE) { + pkh->attrs |= PDMA_TX_PURGE_PKT; + } + if (rch->flags & RCPU_FLAG_BIND_QUE) { + pkh->attrs |= PDMA_TX_BIND_QUE; + } + } else { + /* Non-RCPU encapsulation packet */ + data_len = pkh->data_len - ETH_FCS_LEN; + pkt_len = PKT_HDR_SIZE + pkh->meta_len + data_len; + if (skb->len == pkt_len && pkh->attrs & PDMA_TX_HDR_COOKED && + pkh->pkt_sig == dev->rcpu_ctrl.pkt_sig) { + /* Resumed packet */ + return SHR_E_NONE; + } + meta_len = 0; + if (priv->type == NGKNET_NETIF_T_PORT) { + meta_len = priv->meta_len; + if (!meta_len) { + printk("Tx abort: no metadata\n"); + return SHR_E_UNAVAIL; + } + } + if (skb_header_cloned(skb) || + skb_headroom(skb) < (PKT_HDR_SIZE + meta_len + VLAN_HLEN) || + skb_tailroom(skb) < ETH_FCS_LEN) { + nskb = skb_copy_expand(skb, PKT_HDR_SIZE + meta_len + VLAN_HLEN, + ETH_FCS_LEN, GFP_ATOMIC); + if (!nskb) { + return SHR_E_MEMORY; + } + skb_shinfo(nskb)->tx_flags = skb_shinfo(skb)->tx_flags; + skb = nskb; + } + skb_push(skb, PKT_HDR_SIZE + meta_len); + memset(skb->data, 0, PKT_HDR_SIZE + meta_len); + pkh = (struct pkt_hdr *)skb->data; + pkh->data_len = skb->len - PKT_HDR_SIZE - meta_len + ETH_FCS_LEN; + pkh->meta_len = meta_len; + pkh->attrs = 0; + if (priv->type == NGKNET_NETIF_T_PORT) { + /* Send to physical port using netif metadata */ + if (priv->meta_off) { + memmove(skb->data + PKT_HDR_SIZE, skb->data + PKT_HDR_SIZE + meta_len, priv->meta_off); + } + memcpy(skb->data + PKT_HDR_SIZE + priv->meta_off, priv->meta_data, priv->meta_len); + pkh->attrs |= PDMA_TX_HIGIG_PKT; + } + pkh->pkt_sig = dev->rcpu_ctrl.pkt_sig; + } + + /* Packet header done here */ + pkh->attrs |= PDMA_TX_HDR_COOKED; + + data = skb->data + PKT_HDR_SIZE + pkh->meta_len; + tpid = data[12] << 8 | data[13]; + tag_len = (tpid == ETH_P_8021Q || tpid == ETH_P_8021AD) ? VLAN_HLEN : 0; + + /* Need to add VLAN tag if packet is untagged */ + if (!tag_len && (!(pkh->attrs & PDMA_TX_HIGIG_PKT) || priv->flags & NGKNET_NETIF_F_ADD_TAG)) { + copy_len = PKT_HDR_SIZE + pkh->meta_len + 2 * ETH_ALEN; + if (skb_header_cloned(skb) || skb_headroom(skb) < VLAN_HLEN) { + nskb = skb_copy_expand(skb, VLAN_HLEN, 0, GFP_ATOMIC); + if (!nskb) { + return SHR_E_MEMORY; + } + skb_shinfo(nskb)->tx_flags = skb_shinfo(skb)->tx_flags; + skb = nskb; + } + skb_push(skb, VLAN_HLEN); + memmove(skb->data, skb->data + VLAN_HLEN, copy_len); + pkh = (struct pkt_hdr *)skb->data; + data = skb->data + PKT_HDR_SIZE + pkh->meta_len; + data[12] = 0x81; + data[13] = 0x00; + data[14] = priv->vlan >> 8 & 0xf; + data[15] = priv->vlan & 0xff; + pkh->data_len += VLAN_HLEN; + tag_len = VLAN_HLEN; + } + + /* Optional callback handle */ + if (dev->cbc->tx_cb) { + struct ngknet_callback_desc *cbd = NGKNET_SKB_CB(skb); + cbd->dev_no = dev->dev_no; + cbd->dev_id = dev->pdma_dev.dev_id; + cbd->type_str = drv_ops[dev->pdma_dev.dev_type]->drv_desc; + cbd->priv = priv; + cbd->pmd = skb->data + PKT_HDR_SIZE; + cbd->pmd_len = pkh->meta_len; + cbd->pkt_len = skb->len - PKT_HDR_SIZE - pkh->meta_len; + skb = dev->cbc->tx_cb(skb); + if (!skb) { + if (!nskb) { + *oskb = NULL; + } + return SHR_E_UNAVAIL; + } + pkh = (struct pkt_hdr *)skb->data; + pkh->data_len = skb->len - PKT_HDR_SIZE - pkh->meta_len + ETH_FCS_LEN; + } + + /* Pad packet if needed */ + if (pkh->data_len < (64 + tag_len)) { + pkh->data_len = 64 + tag_len; + if (skb_padto(skb, PKT_HDR_SIZE + pkh->meta_len + pkh->data_len - ETH_FCS_LEN)) { + if (!nskb) { + *oskb = NULL; + } + return SHR_E_MEMORY; + } + } + + /* Update SKB pointer */ + *oskb = skb; + + return SHR_E_NONE; +} + +/*! + * Suspend Tx queue callback + */ +static void +ngknet_tx_suspend(struct pdma_dev *pdev, int queue) +{ + struct ngknet_dev *dev = (struct ngknet_dev *)pdev->priv; + unsigned long flags; + int vdi; + + netif_stop_subqueue(dev->net_dev, queue); + + spin_lock_irqsave(&dev->lock, flags); + for (vdi = 1; vdi <= NUM_VDEV_MAX; vdi++) { + if (!dev->vdev[vdi]) { + continue; + } + netif_stop_subqueue(dev->vdev[vdi], queue); + } + spin_unlock_irqrestore(&dev->lock, flags); +} + +/*! + * Resume Tx queue callback + */ +static void +ngknet_tx_resume(struct pdma_dev *pdev, int queue) +{ + struct ngknet_dev *dev = (struct ngknet_dev *)pdev->priv; + unsigned long flags; + int vdi; + + if (__netif_subqueue_stopped(dev->net_dev, queue)) { + netif_wake_subqueue(dev->net_dev, queue); + } + + spin_lock_irqsave(&dev->lock, flags); + for (vdi = 1; vdi <= NUM_VDEV_MAX; vdi++) { + if (!dev->vdev[vdi]) { + continue; + } + if (__netif_subqueue_stopped(dev->vdev[vdi], queue)) { + netif_wake_subqueue(dev->vdev[vdi], queue); + } + } + spin_unlock_irqrestore(&dev->lock, flags); + + if (pdev->mode == DEV_MODE_HNET) { + atomic_set(&dev->hnet_active, 1); + wake_up_interruptible(&dev->hnet_wq); + } +} + +/*! + * Enable interrupt callback + */ +static void +ngknet_intr_enable(struct pdma_dev *pdev, int cmc, int chan, + uint32_t reg, uint32_t mask) +{ + pdev->ctrl.grp[cmc].irq_mask |= mask; + ngbde_kapi_intr_mask_write(pdev->unit, 0, reg, pdev->ctrl.grp[cmc].irq_mask); +} + +/*! + * Disable interrupt callback + */ +static void +ngknet_intr_disable(struct pdma_dev *pdev, int cmc, int chan, + uint32_t reg, uint32_t mask) +{ + pdev->ctrl.grp[cmc].irq_mask &= ~mask; + ngbde_kapi_intr_mask_write(pdev->unit, 0, reg, pdev->ctrl.grp[cmc].irq_mask); +} + +/*! + * NAPI polling function + */ +static int +ngknet_poll(struct napi_struct *napi, int budget) +{ + struct ngknet_intr_handle *kih = (struct ngknet_intr_handle *)napi; + struct intr_handle *hdl = kih->hdl; + struct pdma_dev *pdev = (struct pdma_dev *)hdl->dev; + struct ngknet_dev *dev = (struct ngknet_dev *)pdev->priv; + unsigned long flags; + int work_done; + + DBG_NAPI(("Scheduled NAPI on queue %d.\n", hdl->queue)); + + kih->napi_resched = 0; + kih->napi_pending = 0; + + if (pdev->flags & PDMA_GROUP_INTR) { + work_done = bcmcnet_group_poll(pdev, hdl->group, budget); + } else { + work_done = bcmcnet_queue_poll(pdev, hdl, budget); + } + + if (work_done < budget) { + napi_complete(napi); + if (kih->napi_pending && napi_schedule_prep(napi)) { + __napi_schedule(napi); + return work_done; + } + spin_lock_irqsave(&dev->lock, flags); + if (!kih->napi_resched) { + if (pdev->flags & PDMA_GROUP_INTR) { + bcmcnet_group_intr_enable(pdev, hdl->group); + } else { + bcmcnet_queue_intr_enable(pdev, hdl); + } + } + spin_unlock_irqrestore(&dev->lock, flags); + } + + return work_done; +} + +/*! + * NGKNET ISR + */ +static int +ngknet_isr(void *isr_data) +{ + struct ngknet_dev *dev = isr_data; + struct pdma_dev *pdev = &dev->pdma_dev; + struct intr_handle *hdl = NULL; + struct napi_struct *napi = NULL; + unsigned long flags; + int gi, qi; + int iv = 0; + + for (gi = 0; gi < pdev->num_groups; gi++) { + if (!pdev->ctrl.grp[gi].attached) { + continue; + } + for (qi = 0; qi < pdev->grp_queues; qi++) { + hdl = &pdev->ctrl.grp[gi].intr_hdl[qi]; + if (pdev->flags & PDMA_GROUP_INTR) { + if (!bcmcnet_group_intr_check(pdev, gi)) { + break; + } + } else { + if (!bcmcnet_queue_intr_check(pdev, hdl)) { + continue; + } + } + spin_lock_irqsave(&dev->lock, flags); + if (pdev->flags & PDMA_GROUP_INTR) { + bcmcnet_group_intr_disable(pdev, gi); + } else { + bcmcnet_queue_intr_disable(pdev, hdl); + } + spin_unlock_irqrestore(&dev->lock, flags); + napi = (struct napi_struct *)hdl->priv; + if (likely(napi_schedule_prep(napi))) { + __napi_schedule(napi); + } + iv++; + if (pdev->flags & PDMA_GROUP_INTR) { + break; + } + } + } + + if (iv) { + DBG_IRQ(("Got interrupt on device %d.\n", dev->dev_no)); + pdev->stats.intrs++; + return IRQ_HANDLED; + } else { + return IRQ_NONE; + } +} + +/*! + * Hypervisor network work handler + */ +static void +ngknet_dev_hnet_work(struct pdma_dev *pdev) +{ + struct ngknet_dev *dev = (struct ngknet_dev *)pdev->priv; + struct intr_handle *hdl = NULL; + struct napi_struct *napi = NULL; + struct ngknet_intr_handle *kih = NULL; + unsigned long flags; + int gi, qi; + + for (gi = 0; gi < pdev->num_groups; gi++) { + if (!pdev->ctrl.grp[gi].attached) { + continue; + } + for (qi = 0; qi < pdev->grp_queues; qi++) { + hdl = &pdev->ctrl.grp[gi].intr_hdl[qi]; + napi = (struct napi_struct *)hdl->priv; + kih = (struct ngknet_intr_handle *)napi; + kih->napi_pending = 1; + if (napi_schedule_prep(napi)) { + spin_lock_irqsave(&dev->lock, flags); + kih->napi_resched = 1; + spin_unlock_irqrestore(&dev->lock, flags); + local_bh_disable(); + __napi_schedule(napi); + local_bh_enable(); + } + if (pdev->flags & PDMA_GROUP_INTR) { + break; + } + } + } +} + +/*! + * Hypervisor network wait handler + */ +static int +ngknet_dev_hnet_wait(struct pdma_dev *pdev) +{ + struct ngknet_dev *dev = (struct ngknet_dev *)pdev->priv; + int qi; + int rv; + + while (!kthread_should_stop()) { + wait_event_interruptible(dev->hnet_wq, + atomic_read(&dev->hnet_active) != 0); + if (!(dev->flags & NGKNET_DEV_ACTIVE)) { + schedule_timeout(HZ); + continue; + } + atomic_set(&dev->hnet_active, 0); + for (qi = 0; qi < pdev->ctrl.nb_txq; qi++) { + do { + rv = pdev->pkt_xmit(pdev, qi, 0); + } while (rv == SHR_E_NONE); + } + schedule_work(&dev->hnet_work); + } + + return 0; +} + +/*! + * Hypervisor network wake handler + */ +static int +ngknet_dev_vnet_wake(struct pdma_dev *pdev) +{ + struct ngknet_dev *dev = (struct ngknet_dev *)pdev->priv; + + atomic_set(&dev->vnet_active, 1); + wake_up_interruptible(&dev->vnet_wq); + + return SHR_E_NONE; +} + +/*! + * Hypervisor network process + */ +static int +ngknet_dev_hnet_process(void *data) +{ + return ngknet_dev_hnet_wait((struct pdma_dev *)data); +} + +/*! + * Hypervisor network schedule + */ +static void +ngknet_dev_hnet_schedule(struct work_struct *work) +{ + struct ngknet_dev *dev = container_of(work, struct ngknet_dev, hnet_work); + + ngknet_dev_hnet_work(&dev->pdma_dev); +} + +/*! + * Convert physical address to virtual address + */ +static void * +ngknet_sys_p2v(struct pdma_dev *pdev, uint64_t paddr) +{ + return ngbde_kapi_dma_bus_to_virt(pdev->unit, (dma_addr_t)paddr); +} + +/*! + * Convert virtual address to physical address + */ +static uint64_t +ngknet_sys_v2p(struct pdma_dev *pdev, void *vaddr) +{ + return (uint64_t)ngbde_kapi_dma_virt_to_bus(pdev->unit, vaddr); +} + +/*! + * Open network device + */ +static int +ngknet_enet_open(struct net_device *ndev) +{ + struct ngknet_private *priv = netdev_priv(ndev); + struct ngknet_dev *dev = priv->bkn_dev; + struct pdma_dev *pdev = &dev->pdma_dev; + struct napi_struct *napi = NULL; + unsigned long bm_queue; + int gi, qi; + int rv; + + if (!pdev->ctrl.bm_rxq || !pdev->ctrl.bm_txq) { + printk("Not config Rx or Tx queue yet!\n"); + return -EPERM; + } + + if (priv->id <= 0) { + /* Register interrupt handler */ + ngbde_kapi_intr_connect(dev->dev_no, 0, ngknet_isr, dev); + + /* Start PDMA device */ + rv = bcmcnet_pdma_dev_start(pdev); + if (SHR_FAILURE(rv)) { + ngbde_kapi_intr_disconnect(dev->dev_no, 0); + return -EPERM; + } + + /* Start rate limit */ + if (rx_rate_limit >= 0) { + ngknet_rx_rate_limit_start(dev); + } + + /* Notify the stack of the actual queue counts. */ + rv = netif_set_real_num_rx_queues(dev->net_dev, pdev->ctrl.nb_rxq); + if (rv < 0) { + ngbde_kapi_intr_disconnect(dev->dev_no, 0); + return rv; + } + rv = netif_set_real_num_tx_queues(dev->net_dev, pdev->ctrl.nb_txq); + if (rv < 0) { + ngbde_kapi_intr_disconnect(dev->dev_no, 0); + return rv; + } + + for (gi = 0; gi < pdev->num_groups; gi++) { + if (!pdev->ctrl.grp[gi].attached) { + continue; + } + bm_queue = pdev->ctrl.grp[gi].bm_rxq | pdev->ctrl.grp[gi].bm_txq; + for (qi = 0; qi < pdev->grp_queues; qi++) { + napi = (struct napi_struct *)pdev->ctrl.grp[gi].intr_hdl[qi].priv; + if (pdev->flags & PDMA_GROUP_INTR) { + napi_enable(napi); + break; + } + if (1 << qi & bm_queue) { + napi_enable(napi); + } + } + } + } else { + /* Notify the stack of the actual queue counts. */ + rv = netif_set_real_num_rx_queues(ndev, pdev->ctrl.nb_rxq); + if (rv < 0) { + return rv; + } + rv = netif_set_real_num_tx_queues(ndev, pdev->ctrl.nb_txq); + if (rv < 0) { + return rv; + } + } + + /* Prevent tx timeout */ + kal_netif_trans_update(ndev); + + netif_tx_wake_all_queues(ndev); + + return 0; +} + +/*! + * Stop network device + */ +static int +ngknet_enet_stop(struct net_device *ndev) +{ + struct ngknet_private *priv = netdev_priv(ndev); + struct ngknet_dev *dev = priv->bkn_dev; + struct pdma_dev *pdev = &dev->pdma_dev; + struct napi_struct *napi = NULL; + unsigned long bm_queue; + int gi, qi; + + netif_tx_stop_all_queues(ndev); + + if (priv->id <= 0) { + /* Stop rate limit */ + if (rx_rate_limit >= 0) { + ngknet_rx_rate_limit_stop(dev); + } + + /* Suspend PDMA device */ + bcmcnet_pdma_dev_suspend(pdev); + + for (gi = 0; gi < pdev->num_groups; gi++) { + if (!pdev->ctrl.grp[gi].attached) { + continue; + } + bm_queue = pdev->ctrl.grp[gi].bm_rxq | pdev->ctrl.grp[gi].bm_txq; + for (qi = 0; qi < pdev->grp_queues; qi++) { + napi = (struct napi_struct *)pdev->ctrl.grp[gi].intr_hdl[qi].priv; + if (pdev->flags & PDMA_GROUP_INTR) { + napi_disable(napi); + break; + } + if (1 << qi & bm_queue) { + napi_disable(napi); + } + } + } + + /* Stop PDMA device */ + bcmcnet_pdma_dev_stop(pdev); + + /* Unregister interrupt handler */ + ngbde_kapi_intr_disconnect(dev->dev_no, 0); + } + + return 0; +} + +/*! + * Start transmission + */ +static int +ngknet_start_xmit(struct sk_buff *skb, struct net_device *ndev) +{ + struct ngknet_private *priv = netdev_priv(ndev); + struct ngknet_dev *dev = priv->bkn_dev; + struct pdma_dev *pdev = &dev->pdma_dev; + struct sk_buff *bskb = skb; + uint32_t len = skb->len; + int queue; + int rv; + + DBG_VERB(("Tx packet from ndev%d (%d bytes).\n", priv->id, skb->len)); + if (debug & DBG_LVL_PDMP) { + ngknet_pkt_dump(skb->data, skb->len); + } + + /* Do not transmit on base device */ + if (priv->id <= 0) { + priv->stats.tx_dropped++; + dev_kfree_skb_any(skb); + return NETDEV_TX_OK; + } + + /* Measure speed */ + if (debug & DBG_LVL_RATE) { + ngknet_pkt_stats(pdev, PDMA_Q_TX); + } + + queue = skb->queue_mapping; + + /* Handle one outgoing packet */ + rv = ngknet_tx_frame_process(ndev, &skb); + if (SHR_FAILURE(rv)) { + priv->stats.tx_dropped++; + if (skb) { + dev_kfree_skb_any(skb); + } + return NETDEV_TX_OK; + } + + /* Schedule Tx queue */ + ngknet_tx_queue_schedule(dev, skb, &queue); + skb->queue_mapping = queue; + + DBG_VERB(("Tx packet (%d bytes).\n", skb->len)); + if (debug & DBG_LVL_PDMP) { + ngknet_pkt_dump(skb->data, skb->len); + } + + /* Do Tx timestamping */ + if (skb_shinfo(skb)->tx_flags & SKBTX_HW_TSTAMP) { + ngknet_ptp_tx_config(ndev, skb); + } + + skb_tx_timestamp(skb); + + rv = pdev->pkt_xmit(pdev, queue, skb); + + if (rv == SHR_E_UNAVAIL) { + DBG_WARN(("Tx drop: DMA device not ready\n")); + priv->stats.tx_dropped++; + if (skb != bskb) { + dev_kfree_skb_any(skb); + } + dev_kfree_skb_any(bskb); + return NETDEV_TX_OK; + } + + if (rv == SHR_E_BUSY) { + DBG_WARN(("Tx suspend: No DMA resources\n")); + priv->stats.tx_fifo_errors++; + if (skb != bskb) { + dev_kfree_skb_any(skb); + } + return NETDEV_TX_BUSY; + } else { + if (skb != bskb) { + dev_kfree_skb_any(bskb); + } + } + + /* Update accounting */ + priv->stats.tx_packets++; + priv->stats.tx_bytes += len; + + return NETDEV_TX_OK; +} + +/*! + * Get network device stats + */ +static struct net_device_stats * +ngknet_get_stats(struct net_device *ndev) +{ + struct ngknet_private *priv = netdev_priv(ndev); + + return &priv->stats; +} + +/*! + * Set network device MC list + */ +static void +ngknet_set_multicast_list(struct net_device *ndev) +{ + return; +} + +/*! + * Set network device MAC address + */ +static int +ngknet_set_mac_address(struct net_device *ndev, void *addr) +{ + if (!is_valid_ether_addr(((struct sockaddr *)addr)->sa_data)) { + return -EINVAL; + } + + netdev_info(ndev, "Setting new MAC address\n"); + memcpy(ndev->dev_addr, ((struct sockaddr *)addr)->sa_data, ndev->addr_len); + + return 0; +} + +/*! + * Change network device MTU + */ +static int +ngknet_change_mtu(struct net_device *ndev, int new_mtu) +{ + int frame_size = new_mtu + ETH_HLEN + VLAN_HLEN + ETH_FCS_LEN; + + if (frame_size < 68 || frame_size > rx_buffer_size) { + return -EINVAL; + } + + netdev_info(ndev, "Changing MTU from %d to %d\n", ndev->mtu, new_mtu); + ndev->mtu = new_mtu; + + return 0; +} + +/*! + * Do I/O control + */ +static int +ngknet_do_ioctl(struct net_device *ndev, struct ifreq *ifr, int cmd) +{ + struct ngknet_private *priv = netdev_priv(ndev); + struct hwtstamp_config config; + int rv; + + if (cmd == SIOCSHWTSTAMP) { + if (copy_from_user(&config, ifr->ifr_data, sizeof(config))) { + return -EFAULT; + } + + if (priv->type != NGKNET_NETIF_T_PORT) { + return -ENOSYS; + } + + switch (config.tx_type) { + case HWTSTAMP_TX_OFF: + priv->hwts_tx_type = HWTSTAMP_TX_OFF; + rv = ngknet_ptp_tx_config_set(ndev, priv->hwts_tx_type); + if (SHR_FAILURE(rv)) { + return -ENOSYS; + } + break; + case HWTSTAMP_TX_ON: + priv->hwts_tx_type = HWTSTAMP_TX_ON; + rv = ngknet_ptp_tx_config_set(ndev, priv->hwts_tx_type); + if (SHR_FAILURE(rv)) { + return -ENOSYS; + } + break; + case HWTSTAMP_TX_ONESTEP_SYNC: + priv->hwts_tx_type = HWTSTAMP_TX_ONESTEP_SYNC; + rv = ngknet_ptp_tx_config_set(ndev, priv->hwts_tx_type); + if (SHR_FAILURE(rv)) { + return -ENOSYS; + } + break; + default: + return -ERANGE; + } + + switch (config.rx_filter) { + case HWTSTAMP_FILTER_NONE: + rv = ngknet_ptp_rx_config_set(ndev, &config.rx_filter); + if (SHR_FAILURE(rv)) { + return -ENOSYS; + } + priv->hwts_rx_filter = HWTSTAMP_FILTER_NONE; + break; + default: + rv = ngknet_ptp_rx_config_set(ndev, &config.rx_filter); + if (SHR_FAILURE(rv)) { + return -ENOSYS; + } + priv->hwts_rx_filter = config.rx_filter; + break; + } + + return copy_to_user(ifr->ifr_data, &config, sizeof(config)) ? -EFAULT : 0; + } + +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,14,0)) + if (cmd == SIOCGHWTSTAMP) { + config.flags = 0; + config.tx_type = priv->hwts_tx_type; + config.rx_filter = priv->hwts_rx_filter; + + return copy_to_user(ifr->ifr_data, &config, sizeof(config)) ? -EFAULT : 0; + } +#endif + + return -EINVAL; +} + +#ifdef CONFIG_NET_POLL_CONTROLLER +/*! + * Poll network device + */ +static void +ngknet_poll_controller(struct net_device *ndev) +{ + struct ngknet_private *priv = netdev_priv(ndev); + + disable_irq(ndev->irq); + ngknet_isr(priv->bkn_dev); + enable_irq(ndev->irq); +} +#endif + +static const struct net_device_ops ngknet_netdev_ops = { + .ndo_open = ngknet_enet_open, + .ndo_stop = ngknet_enet_stop, + .ndo_start_xmit = ngknet_start_xmit, + .ndo_get_stats = ngknet_get_stats, + .ndo_validate_addr = eth_validate_addr, + .ndo_set_rx_mode = ngknet_set_multicast_list, + .ndo_set_mac_address = ngknet_set_mac_address, + .ndo_change_mtu = ngknet_change_mtu, + .ndo_set_features = NULL, + .ndo_do_ioctl = ngknet_do_ioctl, + .ndo_tx_timeout = NULL, +#ifdef CONFIG_NET_POLL_CONTROLLER + .ndo_poll_controller = ngknet_poll_controller, +#endif +}; + +static void +ngknet_get_drvinfo(struct net_device *dev, struct ethtool_drvinfo *drvinfo) +{ + strlcpy(drvinfo->driver, "linux_ngknet", sizeof(drvinfo->driver)); + snprintf(drvinfo->version, sizeof(drvinfo->version), "%d", NGKNET_IOC_VERSION); + strlcpy(drvinfo->fw_version, "N/A", sizeof(drvinfo->fw_version)); + strlcpy(drvinfo->bus_info, "N/A", sizeof(drvinfo->bus_info)); +} + +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,5,0)) +static int +ngknet_get_ts_info(struct net_device *ndev, struct ethtool_ts_info *info) +{ + int rv; + + info->so_timestamping = SOF_TIMESTAMPING_TX_HARDWARE | + SOF_TIMESTAMPING_TX_SOFTWARE | + SOF_TIMESTAMPING_RX_HARDWARE | + SOF_TIMESTAMPING_RX_SOFTWARE | + SOF_TIMESTAMPING_SOFTWARE | + SOF_TIMESTAMPING_RAW_HARDWARE; + info->tx_types = 1 << HWTSTAMP_TX_OFF | 1 << HWTSTAMP_TX_ON | 1 << HWTSTAMP_TX_ONESTEP_SYNC; + info->rx_filters = 1 << HWTSTAMP_FILTER_NONE | 1 << HWTSTAMP_FILTER_ALL; + rv = ngknet_ptp_phc_index_get(ndev, &info->phc_index); + if (SHR_FAILURE(rv)) { + info->phc_index = -1; + } + + return 0; +} +#endif + +static const struct ethtool_ops ngknet_ethtool_ops = { + .get_drvinfo = ngknet_get_drvinfo, +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,5,0)) + .get_ts_info = ngknet_get_ts_info, +#endif +}; + +/*! + * \brief Initialize network device. + * + * \param [in] name Network device name. + * \param [in] mac Network device MAC address. + * \param [out] nd New registered network device. + * + * \retval SHR_E_NONE No errors. + * \retval SHR_E_XXXX Operation failed. + */ +static int +ngknet_ndev_init(ngknet_netif_t *netif, struct net_device **nd) +{ + struct net_device *ndev = NULL; + uint8_t *ma; + int rv; + + if (!netif) { + DBG_WARN(("Network interface is NULL.\n")); + return SHR_E_PARAM; + } + if (!nd) { + DBG_WARN(("Network device is NULL.\n")); + return SHR_E_PARAM; + } + + ndev = alloc_etherdev_mq(sizeof(struct ngknet_private), NUM_QUE_MAX); + if (!ndev) { + DBG_WARN(("Error allocating network device.\n")); + return SHR_E_MEMORY; + } + if (!ndev->dev_addr) { + DBG_WARN(("ndev->dev_addr is NULL\n")); + free_netdev(ndev); + return SHR_E_INTERNAL; + } + + /* Device information -- not available right now */ + ndev->irq = 0; + ndev->base_addr = 0; + + /* Fill in the dev structure */ + ndev->watchdog_timeo = 5 * HZ; + + /* Default MTU should not exceed MTU of switch front-panel ports */ + ndev->mtu = netif->mtu; + if (!ndev->mtu) { + ndev->mtu = default_mtu ? default_mtu : rx_buffer_size; + } + + ndev->netdev_ops = &ngknet_netdev_ops; + ndev->ethtool_ops = &ngknet_ethtool_ops; + + /* Network device name */ + if (netif->name && *netif->name) { + strncpy(ndev->name, netif->name, IFNAMSIZ - 1); + } + + /* Set the device MAC address */ + ma = netif->macaddr; + if ((ma[0] | ma[1] | ma[2] | ma[3] | ma[4] | ma[5]) == 0) { + ngknet_dev_mac[5]++; + ma = ngknet_dev_mac; + } + memcpy(ndev->dev_addr, ma, ETH_ALEN); + + /* Initialize the device features */ + ndev->hw_features = NETIF_F_SG | NETIF_F_RXCSUM | + NETIF_F_HW_VLAN_CTAG_RX | NETIF_F_HW_VLAN_CTAG_TX; + ndev->features |= NETIF_F_HIGHDMA | NETIF_F_HW_VLAN_CTAG_RX; + + /* Register the kernel network device */ + rv = register_netdev(ndev); + if (rv < 0) { + DBG_WARN(("Error registering network device %s.\n", ndev->name)); + free_netdev(ndev); + return SHR_E_FAIL; + } + + *nd = ndev; + + DBG_VERB(("Created network device %s.\n", ndev->name)); + + return SHR_E_NONE; +} + +/*! + * \brief Initialize Packet DMA device. + * + * \param [in] dev NGKNET device structure point. + * + * \retval SHR_E_NONE No errors. + * \retval SHR_E_XXXX Operation failed. + */ +static int +ngknet_pdev_init(struct ngknet_dev *dev) +{ + struct pdma_dev *pdev = &dev->pdma_dev; + int rv; + + /* Initialize PDMA control structure */ + pdev->unit = dev->dev_no; + pdev->priv = dev; + pdev->ctrl.dev = pdev; + pdev->ctrl.hw_addr = dev->base_addr; + pdev->ctrl.rx_buf_size = rx_buffer_size; + + /* Hook callbacks */ + pdev->dev_read32 = ngknet_dev_read32; + pdev->dev_write32 = ngknet_dev_write32; + pdev->pkt_recv = ngknet_frame_recv; + pdev->tx_suspend = ngknet_tx_suspend; + pdev->tx_resume = ngknet_tx_resume; + pdev->intr_unmask = ngknet_intr_enable; + pdev->intr_mask = ngknet_intr_disable; + pdev->xnet_wait = ngknet_dev_hnet_wait; + pdev->xnet_wake = ngknet_dev_vnet_wake; + pdev->sys_p2v = ngknet_sys_p2v; + pdev->sys_v2p = ngknet_sys_v2p; + + pdev->flags |= PDMA_GROUP_INTR; + if (tx_polling) { + pdev->flags |= PDMA_TX_POLLING; + } + if (rx_batching || pdev->mode == DEV_MODE_HNET) { + pdev->flags |= PDMA_RX_BATCHING; + } + + /* Attach PDMA driver */ + rv = drv_ops[pdev->dev_type]->drv_attach(pdev); + if (SHR_FAILURE(rv)) { + DBG_WARN(("Attach DMA driver failed.\n")); + return rv; + } + + /* Initialize PDMA device */ + rv = bcmcnet_pdma_dev_init(pdev); + if (SHR_FAILURE(rv)) { + DBG_WARN(("Init DMA device.failed.\n")); + return rv; + } + + DBG_VERB(("Attached DMA device %s.\n", pdev->name)); + + return SHR_E_NONE; +} + +/*! + * \brief Get device information from BDE. + * + * \param [in] dn Device number. + * + * \retval SHR_E_NONE No errors. + * \retval SHR_E_XXXX Operation failed. + */ +static int +ngknet_dev_info_get(int dn) +{ + struct ngknet_dev *dev = &ngknet_devices[dn]; + + dev->base_addr = ngbde_kapi_pio_membase(dn); + dev->dev = ngbde_kapi_dma_dev_get(dn); + + if (!dev->base_addr || !dev->dev) { + return SHR_E_ACCESS; + } + + dev->dev_no = dn; + + return SHR_E_NONE; +} + +/*! + * \brief Probe device. + * + * Get the information from BDE, initialize Packet DMA device, + * initialize base network device and allocate other resources. + * + * \param [in] dn Device number. + * + * \retval SHR_E_NONE No errors. + * \retval SHR_E_XXXX Operation failed. + */ +static int +ngknet_dev_probe(int dn, ngknet_netif_t *netif) +{ + struct ngknet_dev *dev = &ngknet_devices[dn]; + struct pdma_dev *pdev = &dev->pdma_dev; + struct net_device *ndev = NULL; + struct ngknet_private *priv = NULL; + struct intr_handle *hdl = NULL; + struct cpumask mask; + int gi, qi; + int rv; + + DBG_VERB(("%s: dev %d\n",__FUNCTION__, dn)); + + /* Get device information */ + rv = ngknet_dev_info_get(dn); + if (SHR_FAILURE(rv)) { + return rv; + } + + /* Initialize PDMA device */ + rv = ngknet_pdev_init(dev); + if (SHR_FAILURE(rv)) { + return rv; + } + + /* Get base network device name */ + if (netif->name[0] == '\0') { + /* Reserve 6 vacancies for base&vitual device number, i.e. nameAB_XYZ */ + if (strlen(base_dev_name) < IFNAMSIZ - 6) { + snprintf(netif->name, IFNAMSIZ, "%s%d", base_dev_name, dn); + } else { + DBG_WARN(("Too long network device name: %s.\n", base_dev_name)); + return SHR_E_PARAM; + } + } + + rv = ngknet_ndev_init(netif, &ndev); + if (SHR_FAILURE(rv)) { + bcmcnet_pdma_dev_cleanup(pdev); + return rv; + } + dev->net_dev = ndev; + + /* Initialize private information for base network device */ + priv = netdev_priv(ndev); + priv->net_dev = ndev; + priv->bkn_dev = dev; + priv->id = 0; + priv->type = netif->type; + if (priv->type == NGKNET_NETIF_T_PORT) { + priv->meta_off = netif->meta_off; + priv->meta_len = netif->meta_len; + memcpy(priv->meta_data, netif->meta_data, priv->meta_len); + } + priv->flags = netif->flags; + priv->vlan = netif->vlan; + priv->chan = netif->chan; + memcpy(priv->user_data, netif->user_data, sizeof(priv->user_data)); + + netif->id = priv->id; + memcpy(netif->macaddr, ndev->dev_addr, ETH_ALEN); + netif->mtu = ndev->mtu; + memcpy(netif->name, ndev->name, sizeof(netif->name) - 1); + + if (priv->flags & NGKNET_NETIF_F_BIND_CHAN) { + dev->bdev[priv->chan] = ndev; + } + + /* Register for napi */ + for (gi = 0; gi < pdev->num_groups; gi++) { + if (!pdev->ctrl.grp[gi].attached) { + continue; + } + for (qi = 0; qi < pdev->grp_queues; qi++) { + hdl = &pdev->ctrl.grp[gi].intr_hdl[qi]; + priv_hdl[hdl->unit][hdl->chan].hdl = hdl; + hdl->priv = &priv_hdl[hdl->unit][hdl->chan]; + netif_napi_add(ndev, (struct napi_struct *)hdl->priv, + ngknet_poll, pdev->ctrl.budget); + if (pdev->flags & PDMA_GROUP_INTR) { + break; + } + } + } + + /* Get callback control */ + ngknet_callback_control_get(&dev->cbc); + + INIT_LIST_HEAD(&dev->filt_list); + spin_lock_init(&dev->lock); + init_waitqueue_head(&dev->wq); + if (pdev->mode == DEV_MODE_HNET) { + init_waitqueue_head(&dev->vnet_wq); + atomic_set(&dev->vnet_active, 0); + init_waitqueue_head(&dev->hnet_wq); + atomic_set(&dev->hnet_active, 0); + dev->hnet_task = kthread_run(ngknet_dev_hnet_process, pdev, pdev->name); + if (IS_ERR(dev->hnet_task)) { + dev->hnet_task = NULL; + return SHR_E_INTERNAL; + } + cpumask_clear(&mask); + cpumask_set_cpu(1, &mask); + set_cpus_allowed_ptr(dev->hnet_task, &mask); + INIT_WORK(&dev->hnet_work, ngknet_dev_hnet_schedule); + } + + skb_queue_head_init(&dev->ptp_tx_queue); + INIT_WORK(&dev->ptp_tx_work, ngknet_ptp_tx_work); + + dev->flags |= NGKNET_DEV_ACTIVE; + + DBG_NDEV(("Broadcom NGKNET Attached\n")); + DBG_NDEV(("MAC: %pM\n", ndev->dev_addr)); + DBG_NDEV(("Running with NAPI enabled\n")); + + return SHR_E_NONE; +} + +/*! + * \brief Remove device. + * + * Suspend device firstly, destroy all virtual network devices + * and filters, clean up Packet DMA device. + * + * \param [in] dn Device number. + * + * \retval SHR_E_NONE No errors. + * \retval SHR_E_XXXX Operation failed. + */ +static int +ngknet_dev_remove(int dn) +{ + struct ngknet_dev *dev = &ngknet_devices[dn]; + struct pdma_dev *pdev = &dev->pdma_dev; + struct net_device *ndev = NULL; + struct intr_handle *hdl = NULL; + int di, gi, qi; + int rv; + + if (!(dev->flags & NGKNET_DEV_ACTIVE)) { + return SHR_E_NONE; + } + + DBG_VERB(("%s: dev %d\n",__FUNCTION__, dn)); + + dev->flags &= ~NGKNET_DEV_ACTIVE; + + skb_queue_purge(&dev->ptp_tx_queue); + + if (pdev->mode == DEV_MODE_HNET && dev->hnet_task) { + atomic_set(&dev->hnet_active, 1); + wake_up_interruptible(&dev->hnet_wq); + kthread_stop(dev->hnet_task); + dev->hnet_task = NULL; + } + + /* Destroy all the filters */ + ngknet_filter_destroy_all(dev); + + /* Destroy all the virtual devices */ + for (di = 1; di <= NUM_VDEV_MAX; di++) { + ndev = dev->vdev[di]; + if (ndev) { + netif_carrier_off(ndev); + unregister_netdev(ndev); + free_netdev(ndev); + dev->vdev[di] = NULL; + } + } + dev->vdev[0] = NULL; + + DBG_VERB(("Removing base network device %s.\n", dev->net_dev->name)); + + /* Destroy the base network device */ + ndev = dev->net_dev; + unregister_netdev(ndev); + free_netdev(ndev); + + for (qi = 0; qi < NUM_QUE_MAX; qi++) { + dev->bdev[qi] = NULL; + } + + for (gi = 0; gi < pdev->num_groups; gi++) { + if (!pdev->ctrl.grp[gi].attached) { + continue; + } + for (qi = 0; qi < pdev->grp_queues; qi++) { + hdl = &pdev->ctrl.grp[gi].intr_hdl[qi]; + netif_napi_del((struct napi_struct *)hdl->priv); + priv_hdl[hdl->unit][hdl->chan].hdl = NULL; + if (pdev->flags & PDMA_GROUP_INTR) { + break; + } + } + } + + /* Clean up PDMA device */ + bcmcnet_pdma_dev_cleanup(pdev); + + /* Detach PDMA driver */ + rv = drv_ops[pdev->dev_type]->drv_detach(pdev); + if (SHR_FAILURE(rv)) { + DBG_WARN(("Detach DMA driver failed.\n")); + } + + return rv; +} + +/*! + * Network interface functions + */ + +int +ngknet_netif_create(struct ngknet_dev *dev, ngknet_netif_t *netif) +{ + struct net_device *ndev = NULL; + struct ngknet_private *priv = NULL; + unsigned long flags; + int num, id; + int rv; + + switch (netif->type) { + case NGKNET_NETIF_T_VLAN: + case NGKNET_NETIF_T_PORT: + case NGKNET_NETIF_T_META: + break; + default: + return SHR_E_UNAVAIL; + } + + /* Get vitual network device name */ + if (netif->name[0] == '\0') { + /* Reserve 6 vacancies for base&vitual device number, i.e. nameAB_XYZ */ + if (strlen(base_dev_name) < IFNAMSIZ - 6) { + snprintf(netif->name, IFNAMSIZ, "%s%d%s", base_dev_name, dev->dev_no, "_"); + strncat(netif->name, "%d", 3); + } else { + DBG_WARN(("Too long network device name: %s.\n", base_dev_name)); + return SHR_E_PARAM; + } + } + + rv = ngknet_ndev_init(netif, &ndev); + if (SHR_FAILURE(rv)) { + return rv; + } + + spin_lock_irqsave(&dev->lock, flags); + + num = (long)dev->vdev[0]; + for (id = 1; id < num + 1; id++) { + if (!dev->vdev[id]) { + break; + } + } + if (id > NUM_VDEV_MAX) { + spin_unlock_irqrestore(&dev->lock, flags); + unregister_netdev(ndev); + free_netdev(ndev); + return SHR_E_RESOURCE; + } + + dev->vdev[id] = ndev; + num += id == (num + 1) ? 1 : 0; + dev->vdev[0] = (struct net_device *)(long)num; + + spin_unlock_irqrestore(&dev->lock, flags); + + priv = netdev_priv(ndev); + priv->net_dev = ndev; + priv->bkn_dev = dev; + priv->id = id; + priv->type = netif->type; + if (priv->type == NGKNET_NETIF_T_PORT) { + priv->meta_off = netif->meta_off; + priv->meta_len = netif->meta_len; + memcpy(priv->meta_data, netif->meta_data, priv->meta_len); + } + priv->flags = netif->flags; + priv->vlan = netif->vlan; + priv->chan = netif->chan; + memcpy(priv->user_data, netif->user_data, sizeof(priv->user_data)); + + netif->id = priv->id; + memcpy(netif->macaddr, ndev->dev_addr, ETH_ALEN); + netif->mtu = ndev->mtu; + memcpy(netif->name, ndev->name, sizeof(netif->name) - 1); + + if (priv->flags & NGKNET_NETIF_F_BIND_CHAN) { + dev->bdev[priv->chan] = ndev; + } + + /* Optional netif create callback handle */ + if (dev->cbc->netif_create_cb) { + rv = dev->cbc->netif_create_cb(ndev); + if (rv) { + DBG_WARN(("Netif create callback failed with rv %d for '%s'\n", rv, ndev->name)); + } + } + + DBG_VERB(("Created virtual network device %s (%d).\n", ndev->name, priv->id)); + + return SHR_E_NONE; +} + +int +ngknet_netif_destroy(struct ngknet_dev *dev, int id) +{ + struct net_device *ndev = NULL; + struct ngknet_private *priv = NULL; + unsigned long flags; + int num; + DECLARE_WAITQUEUE(wait, current); + + if (id <= 0 || id > NUM_VDEV_MAX) { + return SHR_E_PARAM; + } + + spin_lock_irqsave(&dev->lock, flags); + + ndev = dev->vdev[id]; + if (!ndev) { + spin_unlock_irqrestore(&dev->lock, flags); + return SHR_E_NOT_FOUND; + } + priv = netdev_priv(ndev); + + add_wait_queue(&dev->wq, &wait); + + while (priv->users) { + priv->wait = 1; + set_current_state(TASK_INTERRUPTIBLE); + spin_unlock_irqrestore(&dev->lock, flags); + schedule(); + spin_lock_irqsave(&dev->lock, flags); + priv->wait = 0; + set_current_state(TASK_RUNNING); + } + + if (priv->flags & NGKNET_NETIF_F_BIND_CHAN) { + dev->bdev[priv->chan] = NULL; + } + + dev->vdev[id] = NULL; + num = (long)dev->vdev[0]; + while (num-- == id--) { + if (dev->vdev[id]) { + dev->vdev[0] = (struct net_device *)(long)num; + break; + } + } + + spin_unlock_irqrestore(&dev->lock, flags); + + remove_wait_queue(&dev->wq, &wait); + + /* Optional netif destroy callback handle */ + if (dev->cbc->netif_destroy_cb) { + int rv = dev->cbc->netif_destroy_cb(ndev); + if (rv) { + DBG_WARN(("Netif destroy callback failed with rv %d for '%s'\n", rv, ndev->name)); + } + } + DBG_VERB(("Removing virtual network device %s (%d).\n", ndev->name, priv->id)); + + netif_carrier_off(ndev); + unregister_netdev(ndev); + free_netdev(ndev); + + return SHR_E_NONE; +} + +int +ngknet_netif_get(struct ngknet_dev *dev, int id, ngknet_netif_t *netif) +{ + struct net_device *ndev = NULL; + struct ngknet_private *priv = NULL; + unsigned long flags; + int num; + + if (id < 0 || id > NUM_VDEV_MAX) { + return SHR_E_PARAM; + } + + spin_lock_irqsave(&dev->lock, flags); + + ndev = id == 0 ? dev->net_dev : dev->vdev[id]; + if (!ndev) { + spin_unlock_irqrestore(&dev->lock, flags); + return SHR_E_NOT_FOUND; + } + + priv = netdev_priv(ndev); + netif->id = priv->id; + netif->type = priv->type; + netif->flags = priv->flags; + netif->vlan = priv->vlan; + memcpy(netif->macaddr, priv->net_dev->dev_addr, ETH_ALEN); + netif->mtu = priv->net_dev->mtu; + netif->chan = priv->chan; + memcpy(netif->name, priv->net_dev->name, sizeof(netif->name) - 1); + netif->meta_off = priv->meta_off; + netif->meta_len = priv->meta_len; + memcpy(netif->meta_data, priv->meta_data, netif->meta_len); + memcpy(netif->user_data, priv->user_data, sizeof(netif->user_data)); + + num = (long)dev->vdev[0]; + for (id++; id < num + 1; id++) { + if (dev->vdev[id]) { + break; + } + } + netif->next = id == (num + 1) ? 0 : id; + + spin_unlock_irqrestore(&dev->lock, flags); + + DBG_VERB(("Got virtual network device %s (%d).\n", ndev->name, priv->id)); + + return SHR_E_NONE; +} + +int +ngknet_netif_get_next(struct ngknet_dev *dev, ngknet_netif_t *netif) +{ + return ngknet_netif_get(dev, netif->next, netif); +} + +/*! + * System control interfaces + */ + +int +ngknet_debug_level_get(void) +{ + return debug; +} + +void +ngknet_debug_level_set(int debug_level) +{ + debug = debug_level; +} + +int +ngknet_rx_rate_limit_get(void) +{ + return rx_rate_limit; +} + +void +ngknet_rx_rate_limit_set(int rate_limit) +{ + rx_rate_limit = rate_limit; +} + +/*! + * Generic module functions + */ + +static int +ngknet_open(struct inode *inode, struct file *filp) +{ + return 0; +} + +static int +ngknet_release(struct inode *inode, struct file *filp) +{ + return 0; +} + +static long +ngknet_ioctl(struct file *file, unsigned int cmd, unsigned long arg) +{ + struct ngknet_ioctl ioc; + struct ngknet_dev *dev = NULL; + struct net_device *ndev = NULL; + struct pdma_dev *pdev = NULL; + union { + ngknet_dev_cfg_t dev_cfg; + ngknet_chan_cfg_t chan_cfg; + ngknet_netif_t netif; + ngknet_filter_t filter; + } iod; + ngknet_dev_cfg_t *dev_cfg = &iod.dev_cfg; + ngknet_chan_cfg_t *chan_cfg = &iod.chan_cfg; + ngknet_netif_t *netif = &iod.netif; + ngknet_filter_t *filter = &iod.filter; + char *data = NULL; + int dt, gi, qi; + + if (_IOC_TYPE(cmd) != NGKNET_IOC_MAGIC) { + DBG_WARN(("Unsupported command (cmd=%d)\n", cmd)); + return -EINVAL; + } + + if (copy_from_user(&ioc, (void *)arg, sizeof(ioc))) { + return -EFAULT; + } + + ioc.rc = SHR_E_NONE; + + dev = &ngknet_devices[ioc.unit]; + pdev = &dev->pdma_dev; + + if (cmd != NGKNET_VERSION_GET && + cmd != NGKNET_RX_RATE_LIMIT && + cmd != NGKNET_DEV_INIT && + !(dev->flags & NGKNET_DEV_ACTIVE)) { + ioc.rc = SHR_E_UNAVAIL; + if (copy_to_user((void *)arg, &ioc, sizeof(ioc))) { + return -EFAULT; + } + return 0; + } + + switch (cmd) { + case NGKNET_VERSION_GET: + DBG_CMD(("NGKNET_VERSION_GET\n")); + ioc.op.info.version = NGKNET_IOC_VERSION; + break; + case NGKNET_RX_RATE_LIMIT: + DBG_CMD(("NGKNET_RX_RATE_LIMIT\n")); + if (ioc.iarg[0]) { + ngknet_rx_rate_limit_set(ioc.iarg[1]); + } else { + ioc.iarg[1] = ngknet_rx_rate_limit_get(); + } + break; + case NGKNET_DEV_INIT: + DBG_CMD(("NGKNET_DEV_INIT\n")); + if (dev->flags & NGKNET_DEV_ACTIVE) { + DBG_CMD(("NGKNET_DEV_INIT, retrieve device configurations.\n")); + strlcpy(dev_cfg->name, pdev->name, sizeof(dev_cfg->name)); + dev_cfg->dev_id = pdev->dev_id; + dev_cfg->nb_grp = pdev->ctrl.nb_grp; + dev_cfg->bm_grp = pdev->ctrl.bm_grp; + ioc.rc = ngknet_netif_get(dev, 0, &dev_cfg->base_netif); + if (SHR_FAILURE((int)ioc.rc)) { + break; + } + if (kal_copy_to_user((void *)(unsigned long)ioc.op.data.buf, dev_cfg, + ioc.op.data.len, sizeof(*dev_cfg))) { + return -EFAULT; + } + break; + } + if (kal_copy_from_user(dev_cfg, (void *)(unsigned long)ioc.op.data.buf, + sizeof(*dev_cfg), ioc.op.data.len)) { + return -EFAULT; + } + if (!dev_cfg->name[0] || !dev_cfg->bm_grp || + dev_cfg->bm_grp >= (1 << NUM_GRP_MAX)) { + DBG_WARN(("Invalid parameter: name=%s, bm_grp=0x%x\n", + dev_cfg->name, dev_cfg->bm_grp)); + ioc.rc = SHR_E_PARAM; + break; + } + memset(pdev, 0, sizeof(*pdev)); + strlcpy(pdev->name, dev_cfg->name, sizeof(pdev->name)); + pdev->dev_id = dev_cfg->dev_id; + for (dt = 0; dt < drv_num; dt++) { + if (!drv_ops[dt]) { + continue; + } + if (!strcasecmp(dev_cfg->type_str, drv_ops[dt]->drv_desc)) { + pdev->dev_type = dt; + break; + } + } + if (pdev->dev_type <= NGKNET_DEV_T_NONE || + pdev->dev_type >= NGKNET_DEV_T_COUNT) { + ioc.rc = SHR_E_PARAM; + break; + } + pdev->ctrl.bm_grp = dev_cfg->bm_grp; + for (gi = 0; gi < NUM_GRP_MAX; gi++) { + if (1 << gi & dev_cfg->bm_grp) { + pdev->ctrl.nb_grp++; + pdev->ctrl.grp[gi].attached = 1; + pdev->num_groups = gi + 1; + } + } + pdev->rx_ph_size = dev_cfg->rx_ph_size; + pdev->tx_ph_size = dev_cfg->tx_ph_size; + pdev->mode = dev_cfg->mode; + if (pdev->mode != DEV_MODE_KNET && pdev->mode != DEV_MODE_HNET) { + pdev->mode = DEV_MODE_KNET; + } + ioc.rc = ngknet_dev_probe(ioc.unit, &dev_cfg->base_netif); + if (SHR_FAILURE((int)ioc.rc)) { + break; + } + if (kal_copy_to_user((void *)(unsigned long)ioc.op.data.buf, dev_cfg, + ioc.op.data.len, sizeof(*dev_cfg))) { + return -EFAULT; + } + break; + case NGKNET_DEV_DEINIT: + DBG_CMD(("NGKNET_DEV_DEINIT\n")); + if (dev->flags & NGKNET_DEV_ACTIVE) { + ioc.rc = ngknet_dev_remove(ioc.unit); + } + break; + case NGKNET_QUEUE_CONFIG: + DBG_CMD(("NGKNET_QUEUE_CONFIG\n")); + if (kal_copy_from_user(chan_cfg, (void *)(unsigned long)ioc.op.data.buf, + sizeof(*chan_cfg), ioc.op.data.len)) { + return -EFAULT; + } + gi = chan_cfg->chan / pdev->grp_queues; + if (!(1 << gi & pdev->ctrl.bm_grp)) { + DBG_WARN(("Invalid parameter: chan=%d (bm_grp=0x%x)\n", + chan_cfg->chan, pdev->ctrl.bm_grp)); + ioc.rc = SHR_E_PARAM; + break; + } + if (chan_cfg->dir == PDMA_Q_RX) { + if (1 << chan_cfg->chan & pdev->ctrl.bm_txq) { + pdev->ctrl.bm_txq &= ~(1 << chan_cfg->chan); + pdev->ctrl.nb_txq--; + } + if (!(1 << chan_cfg->chan & pdev->ctrl.bm_rxq)) { + pdev->ctrl.bm_rxq |= 1 << chan_cfg->chan; + pdev->ctrl.nb_rxq++; + } + } else { + if (1 << chan_cfg->chan & pdev->ctrl.bm_rxq) { + pdev->ctrl.bm_rxq &= ~(1 << chan_cfg->chan); + pdev->ctrl.nb_rxq--; + } + if (!(1 << chan_cfg->chan & pdev->ctrl.bm_txq)) { + pdev->ctrl.bm_txq |= 1 << chan_cfg->chan; + pdev->ctrl.nb_txq++; + } + } + qi = chan_cfg->chan % pdev->grp_queues; + pdev->ctrl.grp[gi].nb_desc[qi] = chan_cfg->nb_desc; + pdev->ctrl.grp[gi].rx_size[qi] = chan_cfg->rx_buf_size; + pdev->ctrl.grp[gi].que_ctrl[qi] &= ~(PDMA_PKT_BYTE_SWAP | + PDMA_OTH_BYTE_SWAP | + PDMA_HDR_BYTE_SWAP); + if (chan_cfg->chan_ctrl & NGKNET_PKT_BYTE_SWAP) { + pdev->ctrl.grp[gi].que_ctrl[qi] |= PDMA_PKT_BYTE_SWAP; + } + if (chan_cfg->chan_ctrl & NGKNET_OTH_BYTE_SWAP) { + pdev->ctrl.grp[gi].que_ctrl[qi] |= PDMA_OTH_BYTE_SWAP; + } + if (chan_cfg->chan_ctrl & NGKNET_HDR_BYTE_SWAP) { + pdev->ctrl.grp[gi].que_ctrl[qi] |= PDMA_HDR_BYTE_SWAP; + } + break; + case NGKNET_QUEUE_QUERY: + DBG_CMD(("NGKNET_QUEUE_QUERY\n")); + if (kal_copy_from_user(chan_cfg, (void *)(unsigned long)ioc.op.data.buf, + sizeof(*chan_cfg), ioc.op.data.len)) { + return -EFAULT; + } + if (1 << chan_cfg->chan & pdev->ctrl.bm_rxq) { + chan_cfg->dir = PDMA_Q_RX; + } else if (1 << chan_cfg->chan & pdev->ctrl.bm_txq) { + chan_cfg->dir = PDMA_Q_TX; + } else { + ioc.rc = SHR_E_UNAVAIL; + break; + } + gi = chan_cfg->chan / pdev->grp_queues; + qi = chan_cfg->chan % pdev->grp_queues; + chan_cfg->nb_desc = pdev->ctrl.grp[gi].nb_desc[qi]; + chan_cfg->chan_ctrl = pdev->ctrl.grp[gi].que_ctrl[qi]; + if (chan_cfg->dir == PDMA_Q_RX) { + chan_cfg->rx_buf_size = pdev->ctrl.grp[gi].rx_size[qi]; + } else { + chan_cfg->rx_buf_size = 0; + } + if (kal_copy_to_user((void *)(unsigned long)ioc.op.data.buf, chan_cfg, + ioc.op.data.len, sizeof(*chan_cfg))) { + return -EFAULT; + } + break; + case NGKNET_DEV_SUSPEND: + DBG_CMD(("NGKNET_DEV_SUSPEND\n")); + if (rx_rate_limit >= 0) { + ngknet_rx_rate_limit_stop(dev); + } + ioc.rc = bcmcnet_pdma_dev_suspend(pdev); + break; + case NGKNET_DEV_RESUME: + DBG_CMD(("NGKNET_DEV_RESUME\n")); + ioc.rc = bcmcnet_pdma_dev_resume(pdev); + if (rx_rate_limit >= 0) { + ngknet_rx_rate_limit_start(dev); + } + break; + case NGKNET_DEV_VNET_WAIT: + DBG_CMD(("NGKNET_DEV_VNET_WAIT\n")); + if (pdev->mode != DEV_MODE_HNET) { + ioc.rc = SHR_E_UNAVAIL; + break; + } + wait_event_interruptible(dev->vnet_wq, + atomic_read(&dev->vnet_active) != 0); + atomic_set(&dev->vnet_active, 0); + break; + case NGKNET_DEV_HNET_WAKE: + DBG_CMD(("NGKNET_DEV_HNET_WAKE\n")); + if (pdev->mode != DEV_MODE_HNET) { + ioc.rc = SHR_E_UNAVAIL; + break; + } + atomic_set(&dev->hnet_active, 1); + wake_up_interruptible(&dev->hnet_wq); + break; + case NGKNET_DEV_VNET_DOCK: + DBG_CMD(("NGKNET_DEV_VNET_DOCK\n")); + if (pdev->mode != DEV_MODE_HNET) { + ioc.rc = SHR_E_UNAVAIL; + break; + } + if (kal_copy_from_user(&pdev->ctrl.vsync, (void *)(unsigned long)ioc.op.data.buf, + sizeof(pdev->ctrl.vsync), ioc.op.data.len)) { + return -EFAULT; + } + ioc.rc = bcmcnet_pdma_dev_dock(pdev); + break; + case NGKNET_DEV_VNET_UNDOCK: + DBG_CMD(("NGKNET_DEV_VNET_UNDOCK\n")); + if (pdev->mode != DEV_MODE_HNET) { + ioc.rc = SHR_E_UNAVAIL; + break; + } + ngknet_dev_vnet_wake(pdev); + ioc.rc = bcmcnet_pdma_dev_undock(pdev); + break; + case NGKNET_RCPU_CONFIG: + DBG_CMD(("NGKNET_RCPU_CONFIG\n")); + if (kal_copy_from_user(&dev->rcpu_ctrl, (void *)(unsigned long)ioc.op.data.buf, + sizeof(dev->rcpu_ctrl), ioc.op.data.len)) { + return -EFAULT; + } + break; + case NGKNET_RCPU_GET: + DBG_CMD(("NGKNET_RCPU_GET\n")); + if (kal_copy_to_user((void *)(unsigned long)ioc.op.data.buf, &dev->rcpu_ctrl, + ioc.op.data.len, sizeof(dev->rcpu_ctrl))) { + return -EFAULT; + } + break; + case NGKNET_INFO_GET: + DBG_CMD(("NGKNET_INFO_GET\n")); + bcmcnet_pdma_dev_info_get(pdev); + if (kal_copy_to_user((void *)(unsigned long)ioc.op.data.buf, &pdev->info, + ioc.op.data.len, sizeof(pdev->info))) { + return -EFAULT; + } + break; + case NGKNET_STATS_GET: + DBG_CMD(("NGKNET_STATS_GET\n")); + bcmcnet_pdma_dev_stats_get(pdev); + if (kal_copy_to_user((void *)(unsigned long)ioc.op.data.buf, &pdev->stats, + ioc.op.data.len, sizeof(pdev->stats))) { + return -EFAULT; + } + break; + case NGKNET_STATS_RESET: + DBG_CMD(("NGKNET_STATS_RESET\n")); + bcmcnet_pdma_dev_stats_reset(pdev); + break; + case NGKNET_NETIF_CREATE: + DBG_CMD(("NGKNET_NETIF_CREATE\n")); + if (kal_copy_from_user(netif, (void *)(unsigned long)ioc.op.data.buf, + sizeof(*netif), ioc.op.data.len)) { + return -EFAULT; + } + ioc.rc = ngknet_netif_create(dev, netif); + if (SHR_FAILURE((int)ioc.rc)) { + break; + } + if (kal_copy_to_user((void *)(unsigned long)ioc.op.data.buf, netif, + ioc.op.data.len, sizeof(*netif))) { + return -EFAULT; + } + break; + case NGKNET_NETIF_DESTROY: + DBG_CMD(("NGKNET_NETIF_DESTROY\n")); + ioc.rc = ngknet_netif_destroy(dev, ioc.iarg[0]); + break; + case NGKNET_NETIF_GET: + DBG_CMD(("NGKNET_NETIF_GET\n")); + ioc.rc = ngknet_netif_get(dev, ioc.iarg[0], netif); + if (SHR_FAILURE((int)ioc.rc)) { + break; + } + if (kal_copy_to_user((void *)(unsigned long)ioc.op.data.buf, netif, + ioc.op.data.len, sizeof(*netif))) { + return -EFAULT; + } + break; + case NGKNET_NETIF_NEXT: + DBG_CMD(("NGKNET_NETIF_NEXT\n")); + if (kal_copy_from_user(netif, (void *)(unsigned long)ioc.op.data.buf, + sizeof(*netif), ioc.op.data.len)) { + return -EFAULT; + } + ioc.rc = ngknet_netif_get_next(dev, netif); + if (SHR_FAILURE((int)ioc.rc)) { + break; + } + if (kal_copy_to_user((void *)(unsigned long)ioc.op.data.buf, netif, + ioc.op.data.len, sizeof(*netif))) { + return -EFAULT; + } + break; + case NGKNET_NETIF_LINK_SET: + DBG_CMD(("NGKNET_NETIF_LINK_SET\n")); + ioc.rc = ngknet_netif_get(dev, ioc.iarg[0], netif); + if (SHR_FAILURE((int)ioc.rc)) { + break; + } + ndev = dev->vdev[netif->id]; + if (ioc.iarg[1]) { + if (!netif_carrier_ok(ndev)) { + netif_carrier_on(ndev); + netif_tx_wake_all_queues(ndev); + DBG_LINK(("%s: link up\n", netif->name)); + } + } else { + if (netif_carrier_ok(ndev)) { + netif_carrier_off(ndev); + netif_tx_stop_all_queues(ndev); + DBG_LINK(("%s: link down\n", netif->name)); + } + } + break; + case NGKNET_FILT_CREATE: + DBG_CMD(("NGKNET_FILT_CREATE\n")); + if (kal_copy_from_user(filter, (void *)(unsigned long)ioc.op.data.buf, + sizeof(*filter), ioc.op.data.len)) { + return -EFAULT; + } + ioc.rc = ngknet_filter_create(dev, filter); + if (SHR_FAILURE((int)ioc.rc)) { + break; + } + if (kal_copy_to_user((void *)(unsigned long)ioc.op.data.buf, filter, + ioc.op.data.len, sizeof(*filter))) { + return -EFAULT; + } + break; + case NGKNET_FILT_DESTROY: + DBG_CMD(("NGKNET_FILT_DESTROY\n")); + ioc.rc = ngknet_filter_destroy(dev, ioc.iarg[0]); + break; + case NGKNET_FILT_GET: + DBG_CMD(("NGKNET_FILT_GET\n")); + ioc.rc = ngknet_filter_get(dev, ioc.iarg[0], filter); + if (SHR_FAILURE((int)ioc.rc)) { + break; + } + if (kal_copy_to_user((void *)(unsigned long)ioc.op.data.buf, filter, + ioc.op.data.len, sizeof(*filter))) { + return -EFAULT; + } + break; + case NGKNET_FILT_NEXT: + DBG_CMD(("NGKNET_FILT_NEXT\n")); + if (kal_copy_from_user(filter, (void *)(unsigned long)ioc.op.data.buf, + sizeof(*filter), ioc.op.data.len)) { + return -EFAULT; + } + ioc.rc = ngknet_filter_get_next(dev, filter); + if (SHR_FAILURE((int)ioc.rc)) { + break; + } + if (kal_copy_to_user((void *)(unsigned long)ioc.op.data.buf, filter, + ioc.op.data.len, sizeof(*filter))) { + return -EFAULT; + } + break; + case NGKNET_PTP_DEV_CTRL: + DBG_CMD(("NGKNET_PTP_DEV_CTRL\n")); + if (ioc.op.data.len) { + data = kmalloc(ioc.op.data.len, GFP_ATOMIC); + if (data == NULL) { + printk("Fatal error: no memory for PTP device ioctl\n"); + return -EFAULT; + } + if (copy_from_user(data, (void *)(unsigned long)ioc.op.data.buf, + ioc.op.data.len)) { + kfree(data); + return -EFAULT; + } + } + ioc.rc = ngknet_ptp_dev_ctrl(dev, ioc.iarg[0], data, ioc.op.data.len); + if (SHR_FAILURE((int)ioc.rc)) { + if (data) { + kfree(data); + } + break; + } + if (ioc.op.data.len) { + if (copy_to_user((void *)(unsigned long)ioc.op.data.buf, data, + ioc.op.data.len)) { + kfree(data); + return -EFAULT; + } + kfree(data); + } + break; + default: + ioc.rc = SHR_E_UNAVAIL; + printk("Invalid IOCTL"); + break; + } + + if (copy_to_user((void *)arg, &ioc, sizeof(ioc))) { + return -EFAULT; + } + + return 0; +} + +static int +ngknet_mmap(struct file *filp, struct vm_area_struct *vma) +{ + return 0; +} + +static struct file_operations ngknet_fops = { + .open = ngknet_open, + .release = ngknet_release, + .unlocked_ioctl = ngknet_ioctl, + .compat_ioctl = ngknet_ioctl, + .mmap = ngknet_mmap, +}; + +static int __init +ngknet_init_module(void) +{ + int idx; + int rv; + + rv = register_chrdev(NGKNET_MODULE_MAJOR, NGKNET_MODULE_NAME, &ngknet_fops); + if (rv < 0) { + printk(KERN_WARNING "%s: can't get major %d\n", + NGKNET_MODULE_NAME, NGKNET_MODULE_MAJOR); + return rv; + } + + /* Randomize lower 3 bytes of the MAC address (TESTING ONLY) */ + get_random_bytes(&ngknet_dev_mac[3], 3); + + /* Check for user-supplied MAC address (recommended) */ + if (mac_addr != NULL && strlen(mac_addr) == 17) { + for (idx = 0; idx < 6; idx++) { + ngknet_dev_mac[idx] = simple_strtoul(&mac_addr[idx * 3], NULL, 16); + } + /* Do not allow multicast address */ + ngknet_dev_mac[0] &= ~0x01; + } + + /* Initialize procfs */ + ngknet_procfs_init(); + + /* Initialize Rx rate limit */ + ngknet_rx_rate_limit_init(ngknet_devices); + + return 0; +} + +static void __exit +ngknet_exit_module(void) +{ + int idx; + + /* Cleanup Rx rate limit */ + ngknet_rx_rate_limit_cleanup(); + + /* Cleanup procfs */ + ngknet_procfs_cleanup(); + + /* Remove all the devices */ + for (idx = 0; idx < NUM_PDMA_DEV_MAX; idx++) { + ngknet_dev_remove(idx); + } + + unregister_chrdev(NGKNET_MODULE_MAJOR, NGKNET_MODULE_NAME); +} + +module_init(ngknet_init_module); +module_exit(ngknet_exit_module); + diff --git a/platform/broadcom/saibcm-modules/sdklt/linux/knet/ngknet_main.h b/platform/broadcom/saibcm-modules/sdklt/linux/knet/ngknet_main.h new file mode 100644 index 00000000000..fb38f1b9abc --- /dev/null +++ b/platform/broadcom/saibcm-modules/sdklt/linux/knet/ngknet_main.h @@ -0,0 +1,278 @@ +/*! \file ngknet_main.h + * + * Data structure and macro definitions for NGKNET kernel module. + * + */ +/* + * $Copyright: Copyright 2018-2020 Broadcom. All rights reserved. + * The term 'Broadcom' refers to Broadcom Inc. and/or its subsidiaries. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * version 2 as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * A copy of the GNU General Public License version 2 (GPLv2) can + * be found in the LICENSES folder.$ + */ + +#ifndef NGKNET_MAIN_H +#define NGKNET_MAIN_H + +#include +#include +#include +#include + +/*! Maximum number of PDMA devices supported */ +#ifdef NGBDE_NUM_SWDEV_MAX +#define NUM_PDMA_DEV_MAX NGBDE_NUM_SWDEV_MAX +#else +#define NUM_PDMA_DEV_MAX 16 +#endif + +/*! + * Debug levels + */ +#define DBG_LVL_VERB 0x0001 +#define DBG_LVL_PKT 0x0002 +#define DBG_LVL_CMD 0x0004 +#define DBG_LVL_IRQ 0x0008 +#define DBG_LVL_NAPI 0x0010 +#define DBG_LVL_NDEV 0x0020 +#define DBG_LVL_FILT 0x0040 +#define DBG_LVL_RCPU 0x0080 +#define DBG_LVL_WARN 0x0100 +#define DBG_LVL_PDMP 0x0200 +#define DBG_LVL_RATE 0x0400 +#define DBG_LVL_LINK 0x0800 + +#define DBG_VERB(_s) do { if (debug & DBG_LVL_VERB) printk _s; } while (0) +#define DBG_PKT(_s) do { if (debug & DBG_LVL_PKT) printk _s; } while (0) +#define DBG_CMD(_s) do { if (debug & DBG_LVL_CMD) printk _s; } while (0) +#define DBG_IRQ(_s) do { if (debug & DBG_LVL_IRQ) printk _s; } while (0) +#define DBG_NAPI(_s) do { if (debug & DBG_LVL_NAPI) printk _s; } while (0) +#define DBG_NDEV(_s) do { if (debug & DBG_LVL_NDEV) printk _s; } while (0) +#define DBG_FILT(_s) do { if (debug & DBG_LVL_FILT) printk _s; } while (0) +#define DBG_RCPU(_s) do { if (debug & DBG_LVL_RCPU) printk _s; } while (0) +#define DBG_WARN(_s) do { if (debug & DBG_LVL_WARN) printk _s; } while (0) +#define DBG_PDMP(_s) do { if (debug & DBG_LVL_PDMP) printk _s; } while (0) +#define DBG_RATE(_s) do { if (debug & DBG_LVL_RATE) printk _s; } while (0) +#define DBG_LINK(_s) do { if (debug & DBG_LVL_LINK) printk _s; } while (0) + +/*! + * Device description + */ +struct ngknet_dev { + /*! Base address for PCI register access */ + volatile void *base_addr; + + /*! Required for DMA memory control */ + struct device *dev; + + /*! Required for PCI memory control */ + struct pci_dev *pci_dev; + + /*! Base network device */ + struct net_device *net_dev; + + /*! PDMA device */ + struct pdma_dev pdma_dev; + + /*! Device number (from BDE) */ + int dev_no; + + /*! Vitual network devices, 0 is reserved */ + struct net_device *vdev[NUM_VDEV_MAX + 1]; + + /*! Vitual network devices bound to queue */ + struct net_device *bdev[NUM_QUE_MAX]; + + /*! Filter list */ + struct list_head filt_list; + + /*! Filter control, 0 is reserved */ + void *fc[NUM_FILTER_MAX + 1]; + + /*! Callback control */ + struct ngknet_callback_ctrl *cbc; + + /*! RCPU control */ + struct ngknet_rcpu_hdr rcpu_ctrl; + + /*! NGKNET lock */ + spinlock_t lock; + + /*! NGKNET wait queue */ + wait_queue_head_t wq; + + /*! VNET wait queue */ + wait_queue_head_t vnet_wq; + + /*! VNET is active */ + atomic_t vnet_active; + + /*! HNET wait queue */ + wait_queue_head_t hnet_wq; + + /*! HNET is active */ + atomic_t hnet_active; + + /*! HNET deamon */ + struct task_struct *hnet_task; + + /*! HNET work */ + struct work_struct hnet_work; + + /*! PTP Tx queue */ + struct sk_buff_head ptp_tx_queue; + + /*! PTP Tx work */ + struct work_struct ptp_tx_work; + + /*! Flags */ + int flags; + /*! NGKNET device is active */ +#define NGKNET_DEV_ACTIVE (1 << 0) +}; + +/*! + * Network interface specific private data + */ +struct ngknet_private { + /*! Network device */ + struct net_device *net_dev; + + /*! Network stats */ + struct net_device_stats stats; + + /*! NGKNET device */ + struct ngknet_dev *bkn_dev; + + /*! Network interface ID */ + int id; + + /*! Network interface type */ + int type; + + /*! Network interface flags */ + uint32_t flags; + + /*! Network interface vlan */ + uint32_t vlan; + + /*! Network interface bound to */ + uint32_t chan; + + /*! Metadata offset from Ethernet header */ + uint32_t meta_off; + + /*! Metadata length */ + uint32_t meta_len; + + /*! Metadata used to send packets to physical port */ + uint8_t meta_data[NGKNET_NETIF_META_MAX]; + + /*! User data gotten back through callbacks */ + uint8_t user_data[NGKNET_NETIF_USER_DATA]; + + /*! Users of this network interface */ + int users; + + /*! Wait for this network interface free */ + int wait; + + /*! HW timestamp Rx filter */ + int hwts_rx_filter; + + /*! HW timestamp Tx type */ + int hwts_tx_type; +}; + +/*! + * \brief Create network interface. + * + * \param [in] dev NGKNET device structure point. + * \param [in] netif Network interface structure point. + * + * \retval SHR_E_NONE No errors. + * \retval SHR_E_XXXX Operation failed. + */ +extern int +ngknet_netif_create(struct ngknet_dev *dev, ngknet_netif_t *netif); + +/*! + * \brief Destroy network interface. + * + * \param [in] dev NGKNET device structure point. + * \param [in] id Network interface ID. + * + * \retval SHR_E_NONE No errors. + * \retval SHR_E_XXXX Operation failed. + */ +extern int +ngknet_netif_destroy(struct ngknet_dev *dev, int id); + +/*! + * \brief Get network interface. + * + * \param [in] dev NGKNET device structure point. + * \param [in] id Network interface ID. + * \param [out] netif Network interface structure point. + * + * \retval SHR_E_NONE No errors. + * \retval SHR_E_XXXX Operation failed. + */ +extern int +ngknet_netif_get(struct ngknet_dev *dev, int id, ngknet_netif_t *netif); + +/*! + * \brief Get the next network interface. + * + * \param [in] dev NGKNET device structure point. + * \param [out] netif Network interface structure point. + * + * \retval SHR_E_NONE No errors. + * \retval SHR_E_XXXX Operation failed. + */ +extern int +ngknet_netif_get_next(struct ngknet_dev *dev, ngknet_netif_t *netif); + +/*! + * \brief Get debug level. + * + * \retval Current debug level. + */ +extern int +ngknet_debug_level_get(void); + +/*! + * \brief Set debug level. + * + * \param [in] debug_level Debug level to be set. + */ +extern void +ngknet_debug_level_set(int debug_level); + +/*! + * \brief Get Rx rate limit. + * + * \retval Current Rx rate limit. + */ +extern int +ngknet_rx_rate_limit_get(void); + +/*! + * \brief Set Rx rate limit. + * + * \param [in] rate_limit Rx rate limit to be set. + */ +extern void +ngknet_rx_rate_limit_set(int rate_limit); + +#endif /* NGKNET_MAIN_H */ + diff --git a/platform/broadcom/saibcm-modules/sdklt/linux/knet/ngknet_procfs.c b/platform/broadcom/saibcm-modules/sdklt/linux/knet/ngknet_procfs.c new file mode 100644 index 00000000000..85edaa26abb --- /dev/null +++ b/platform/broadcom/saibcm-modules/sdklt/linux/knet/ngknet_procfs.c @@ -0,0 +1,655 @@ +/*! \file ngknet_procfs.c + * + * + * + */ +/* + * $Copyright: Copyright 2018-2020 Broadcom. All rights reserved. + * The term 'Broadcom' refers to Broadcom Inc. and/or its subsidiaries. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * version 2 as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * A copy of the GNU General Public License version 2 (GPLv2) can + * be found in the LICENSES folder.$ + */ + +#include +#include +#include "ngknet_main.h" +#include "ngknet_extra.h" + +extern struct ngknet_dev ngknet_devices[]; + +static struct proc_dir_entry *proc_root = NULL; + +static void +proc_data_show(struct seq_file *m, const unsigned char *buf, size_t len) +{ + uint32_t i; + + if (!buf || !len) { + seq_printf(m, "\n"); + return; + } + + for (i = 0; i < len; i++) { + seq_printf(m, "%02x ", buf[i]); + if ((i + 1) % 32 == 0 || (i + 1) == len) { + seq_printf(m, "\n"); + if ((i + 1) < len) { + seq_printf(m, " "); + } + } + } +} + +static int +proc_debug_level_show(struct seq_file *m, void *v) +{ + seq_printf(m, "Debug level: 0x%x\n", ngknet_debug_level_get()); + + return 0; +} + +static int +proc_debug_level_open(struct inode *inode, struct file *file) +{ + return single_open(file, proc_debug_level_show, NULL); +} + +static ssize_t +proc_debug_level_write(struct file *file, const char *buf, + size_t count, loff_t *loff) +{ + char level_str[11] = {0}; + int debug_level; + + if (copy_from_user(level_str, buf, sizeof(level_str) - 1)) { + return -EFAULT; + } + debug_level = simple_strtol(level_str, NULL, 16); + + ngknet_debug_level_set(debug_level); + printk("Debug level set to: 0x%x\n", debug_level); + + return count; +} + +static int +proc_debug_level_release(struct inode *inode, struct file *file) +{ + return single_release(inode, file); +} + +static struct file_operations proc_debug_level_fops = { + owner: THIS_MODULE, + open: proc_debug_level_open, + read: seq_read, + write: proc_debug_level_write, + llseek: seq_lseek, + release: proc_debug_level_release, +}; + +static int +proc_device_info_show(struct seq_file *m, void *v) +{ + struct ngknet_dev *dev; + struct bcmcnet_dev_info *info; + int di, qi, ai = 0; + int rv; + + for (di = 0; di < NUM_PDMA_DEV_MAX; di++) { + dev = &ngknet_devices[di]; + if (!(dev->flags & NGKNET_DEV_ACTIVE)) { + continue; + } + ai++; + + rv = bcmcnet_pdma_dev_info_get(&dev->pdma_dev); + if (SHR_FAILURE(rv)) { + printk("ngknet: get device%d info failed\n", di); + break; + } + + info = &dev->pdma_dev.info; + seq_printf(m, "dev_no: %d\n", di); + seq_printf(m, "dev_name: %s\n", info->dev_name); + seq_printf(m, "dev_id: 0x%x\n", info->dev_id); + seq_printf(m, "dev_type: %d\n", info->dev_type); + seq_printf(m, "max_groups: %d\n", info->max_groups); + seq_printf(m, "max_queues: %d\n", info->max_queues); + seq_printf(m, "bm_groups: 0x%x\n", info->bm_groups); + seq_printf(m, "bm_rx_queues: 0x%x\n", info->bm_rx_queues); + seq_printf(m, "bm_tx_queues: 0x%x\n", info->bm_tx_queues); + seq_printf(m, "nb_groups: %d\n", info->nb_groups); + seq_printf(m, "nb_rx_queues: %d\n", info->nb_rx_queues); + seq_printf(m, "nb_tx_queues: %d\n", info->nb_tx_queues); + seq_printf(m, "rx_desc_size: %d\n", info->rx_desc_size); + seq_printf(m, "tx_desc_size: %d\n", info->tx_desc_size); + seq_printf(m, "rx_ph_size: %d\n", info->rx_ph_size); + seq_printf(m, "tx_ph_size: %d\n", info->tx_ph_size); + for (qi = 0; qi < info->nb_rx_queues; qi++) { + seq_printf(m, "rx_buf_sz[%d]: %d\n", qi, info->rx_buf_size[qi]); + } + for (qi = 0; qi < info->nb_rx_queues; qi++) { + seq_printf(m, "nb_rx_desc[%d]: %d\n", qi, info->nb_rx_desc[qi]); + } + for (qi = 0; qi < info->nb_tx_queues; qi++) { + seq_printf(m, "nb_tx_desc[%d]: %d\n", qi, info->nb_tx_desc[qi]); + } + } + + if (!ai) { + seq_printf(m, "%s\n", "No active device"); + } else { + seq_printf(m, "------------------------\n"); + seq_printf(m, "Total %d devices\n", ai); + } + + return 0; +} + +static int +proc_device_info_open(struct inode *inode, struct file *file) +{ + return single_open(file, proc_device_info_show, NULL); +} + +static int +proc_device_info_release(struct inode *inode, struct file *file) +{ + return single_release(inode, file); +} + +static struct file_operations proc_device_info_fops = { + owner: THIS_MODULE, + open: proc_device_info_open, + read: seq_read, + llseek: seq_lseek, + release: proc_device_info_release, +}; + +static int +proc_filter_info_show(struct seq_file *m, void *v) +{ + struct ngknet_dev *dev; + ngknet_filter_t filt = {0}; + int di, dn = 0, fn = 0; + int rv; + + for (di = 0; di < NUM_PDMA_DEV_MAX; di++) { + dev = &ngknet_devices[di]; + if (!(dev->flags & NGKNET_DEV_ACTIVE)) { + continue; + } + dn++; + + do { + rv = ngknet_filter_get_next(dev, &filt); + if (SHR_FAILURE(rv)) { + printk("ngknet: get device%d filter failed\n", di); + break; + } + fn++; + + seq_printf(m, "\n"); + seq_printf(m, "dev_no: %d\n", di); + seq_printf(m, "id: %d\n", filt.id); + seq_printf(m, "next: %d\n", filt.next); + seq_printf(m, "type: %d\n", filt.type); + seq_printf(m, "flags: 0x%x\n", filt.flags); + seq_printf(m, "prio: %d\n", filt.priority); + seq_printf(m, "chan: %d\n", filt.chan); + seq_printf(m, "desc: %s\n", filt.desc); + seq_printf(m, "dest_type: %d\n", filt.dest_type); + seq_printf(m, "dest_id: %d\n", filt.dest_id); + seq_printf(m, "dest_proto: 0x%x\n", filt.dest_proto); + seq_printf(m, "mirror_type: %d\n", filt.mirror_type); + seq_printf(m, "mirror_id: %d\n", filt.mirror_id); + seq_printf(m, "mirror_proto: 0x%x\n", filt.mirror_proto); + seq_printf(m, "oob_offset: %d\n", filt.oob_data_offset); + seq_printf(m, "oob_size: %d\n", filt.oob_data_size); + seq_printf(m, "pkt_offset: %d\n", filt.pkt_data_offset); + seq_printf(m, "pkt_size: %d\n", filt.pkt_data_size); + seq_printf(m, "filt_data: "); + proc_data_show(m, filt.data.b, filt.oob_data_size + filt.pkt_data_size); + seq_printf(m, "filt_mask: "); + proc_data_show(m, filt.mask.b, filt.oob_data_size + filt.pkt_data_size); + seq_printf(m, "user_data: "); + proc_data_show(m, filt.user_data, NGKNET_FILTER_USER_DATA); + seq_printf(m, "hits: %llu\n", ((struct filt_ctrl *)dev->fc[filt.id])->hits); + } while (filt.next); + } + + if (!dn) { + seq_printf(m, "%s\n", "No active device"); + } else { + seq_printf(m, "--------------------------------\n"); + seq_printf(m, "Total %d devices, %d filters\n", dn, fn); + } + + return 0; +} + +static int +proc_filter_info_open(struct inode *inode, struct file *file) +{ + return single_open(file, proc_filter_info_show, NULL); +} + +static int +proc_filter_info_release(struct inode *inode, struct file *file) +{ + return single_release(inode, file); +} + +static struct file_operations proc_filter_info_fops = { + owner: THIS_MODULE, + open: proc_filter_info_open, + read: seq_read, + llseek: seq_lseek, + release: proc_filter_info_release, +}; + +static int +proc_netif_info_show(struct seq_file *m, void *v) +{ + struct ngknet_dev *dev; + struct net_device *ndev; + struct ngknet_private *priv; + ngknet_netif_t netif = {0}; + int di, ma, dn = 0, nn = 0; + int rv; + + for (di = 0; di < NUM_PDMA_DEV_MAX; di++) { + dev = &ngknet_devices[di]; + if (!(dev->flags & NGKNET_DEV_ACTIVE)) { + continue; + } + dn++; + + do { + rv = ngknet_netif_get_next(dev, &netif); + if (SHR_FAILURE(rv)) { + printk("ngknet: get device%d netif failed\n", di); + break; + } + nn++; + ndev = netif.id == 0 ? dev->net_dev : dev->vdev[netif.id]; + priv = netdev_priv(ndev); + + seq_printf(m, "\n"); + seq_printf(m, "dev_no: %d\n", di); + seq_printf(m, "id: %d\n", netif.id); + seq_printf(m, "next: %d\n", netif.next); + seq_printf(m, "type: %d\n", netif.type); + seq_printf(m, "flags: 0x%x\n", netif.flags); + seq_printf(m, "vlan: %d\n", netif.vlan); + seq_printf(m, "mac: "); + for (ma = 0; ma < 6; ma++) { + if (ma == 5) { + seq_printf(m, "%02x\n", netif.macaddr[ma]); + } else { + seq_printf(m, "%02x:", netif.macaddr[ma]); + } + } + seq_printf(m, "mtu: %d\n", netif.mtu); + seq_printf(m, "chan: %d\n", netif.chan); + seq_printf(m, "name: %s\n", netif.name); + seq_printf(m, "meta_off: %d\n", netif.meta_off); + seq_printf(m, "meta_len: %d\n", netif.meta_len); + seq_printf(m, "meta_data: "); + proc_data_show(m, netif.meta_data, netif.meta_len); + seq_printf(m, "user_data: "); + proc_data_show(m, netif.user_data, NGKNET_NETIF_USER_DATA); + seq_printf(m, "rx_packets: %lu\n", priv->stats.rx_packets); + seq_printf(m, "rx_bytes: %lu\n", priv->stats.rx_bytes); + seq_printf(m, "rx_dropped: %lu\n", priv->stats.rx_dropped); + seq_printf(m, "rx_errors: %lu\n", priv->stats.rx_errors); + seq_printf(m, "tx_packets: %lu\n", priv->stats.tx_packets); + seq_printf(m, "tx_bytes: %lu\n", priv->stats.tx_bytes); + seq_printf(m, "tx_dropped: %lu\n", priv->stats.tx_dropped); + seq_printf(m, "tx_errors: %lu\n", priv->stats.tx_errors); + } while (netif.next); + } + + if (!dn) { + seq_printf(m, "%s\n", "No active device"); + } else { + seq_printf(m, "--------------------------------\n"); + seq_printf(m, "Total %d devices, %d netifs\n", dn, nn); + } + + return 0; +} + +static int +proc_netif_info_open(struct inode *inode, struct file *file) +{ + return single_open(file, proc_netif_info_show, NULL); +} + +static int +proc_netif_info_release(struct inode *inode, struct file *file) +{ + return single_release(inode, file); +} + +static struct file_operations proc_netif_info_fops = { + owner: THIS_MODULE, + open: proc_netif_info_open, + read: seq_read, + llseek: seq_lseek, + release: proc_netif_info_release, +}; + +static int +proc_pkt_stats_show(struct seq_file *m, void *v) +{ + struct ngknet_dev *dev; + struct bcmcnet_dev_stats *stats; + int di, qi, ai = 0; + int rv; + + for (di = 0; di < NUM_PDMA_DEV_MAX; di++) { + dev = &ngknet_devices[di]; + if (!(dev->flags & NGKNET_DEV_ACTIVE)) { + continue; + } + ai++; + + rv = bcmcnet_pdma_dev_stats_get(&dev->pdma_dev); + if (SHR_FAILURE(rv)) { + printk("ngknet: get device%d stats failed\n", di); + break; + } + + stats = &dev->pdma_dev.stats; + seq_printf(m, "rx_packets: %llu\n", (unsigned long long)stats->rx_packets); + seq_printf(m, "rx_bytes: %llu\n", (unsigned long long)stats->rx_bytes); + for (qi = 0; qi < dev->pdma_dev.ctrl.nb_rxq; qi++) { + seq_printf(m, "rx_packets[%d]: %llu\n", qi, (unsigned long long)stats->rxq_packets[qi]); + seq_printf(m, "rx_bytes[%d]: %llu\n", qi, (unsigned long long)stats->rxq_bytes[qi]); + } + seq_printf(m, "rx_dropped: %llu\n", (unsigned long long)stats->rx_dropped); + seq_printf(m, "rx_errors: %llu\n", (unsigned long long)stats->rx_errors); + seq_printf(m, "rx_nomems: %llu\n", (unsigned long long)stats->rx_nomems); + seq_printf(m, "tx_packets: %llu\n", (unsigned long long)stats->tx_packets); + seq_printf(m, "tx_bytes: %llu\n", (unsigned long long)stats->tx_bytes); + for (qi = 0; qi < dev->pdma_dev.ctrl.nb_txq; qi++) { + seq_printf(m, "tx_packets[%d]: %llu\n", qi, (unsigned long long)stats->txq_packets[qi]); + seq_printf(m, "tx_bytes[%d]: %llu\n", qi, (unsigned long long)stats->txq_bytes[qi]); + } + seq_printf(m, "tx_dropped: %llu\n", (unsigned long long)stats->tx_dropped); + seq_printf(m, "tx_errors: %llu\n", (unsigned long long)stats->tx_errors); + seq_printf(m, "tx_xoffs: %llu\n", (unsigned long long)stats->tx_xoffs); + seq_printf(m, "interrupts: %llu\n", (unsigned long long)stats->intrs); + } + + if (!ai) { + seq_printf(m, "%s\n", "No active device"); + } else { + seq_printf(m, "------------------------\n"); + seq_printf(m, "Total %d devices\n", ai); + } + + return 0; +} + +static int +proc_pkt_stats_open(struct inode *inode, struct file *file) +{ + return single_open(file, proc_pkt_stats_show, NULL); +} + +static int +proc_pkt_stats_release(struct inode *inode, struct file *file) +{ + return single_release(inode, file); +} + +static struct file_operations proc_pkt_stats_fops = { + owner: THIS_MODULE, + open: proc_pkt_stats_open, + read: seq_read, + llseek: seq_lseek, + release: proc_pkt_stats_release, +}; + +static int +proc_rate_limit_show(struct seq_file *m, void *v) +{ + seq_printf(m, "Rx rate limit: %d pps\n", ngknet_rx_rate_limit_get()); + + return 0; +} + +static int +proc_rate_limit_open(struct inode *inode, struct file *file) +{ + return single_open(file, proc_rate_limit_show, NULL); +} + +static ssize_t +proc_rate_limit_write(struct file *file, const char *buf, + size_t count, loff_t *loff) +{ + char limit_str[9] = {0}; + int rate_limit; + + if (copy_from_user(limit_str, buf, sizeof(limit_str) - 1)) { + return -EFAULT; + } + rate_limit = simple_strtol(limit_str, NULL, 10); + + ngknet_rx_rate_limit_set(rate_limit); + printk("Rx rate limit set to: %d pps\n", rate_limit); + + return count; +} + +static int +proc_rate_limit_release(struct inode *inode, struct file *file) +{ + return single_release(inode, file); +} + +static struct file_operations proc_rate_limit_fops = { + owner: THIS_MODULE, + open: proc_rate_limit_open, + read: seq_read, + write: proc_rate_limit_write, + llseek: seq_lseek, + release: proc_rate_limit_release, +}; + +static int +proc_reg_status_show(struct seq_file *m, void *v) +{ + struct ngknet_dev *dev; + int di, qi, ai = 0; + + for (di = 0; di < NUM_PDMA_DEV_MAX; di++) { + dev = &ngknet_devices[di]; + if (!(dev->flags & NGKNET_DEV_ACTIVE)) { + continue; + } + ai++; + for (qi = 0; qi < dev->pdma_dev.ctrl.nb_rxq; qi++) { + bcmcnet_pdma_rx_queue_reg_dump(&dev->pdma_dev, qi); + } + for (qi = 0; qi < dev->pdma_dev.ctrl.nb_txq; qi++) { + bcmcnet_pdma_tx_queue_reg_dump(&dev->pdma_dev, qi); + } + } + + if (!ai) { + seq_printf(m, "%s\n", "No active device"); + } else { + seq_printf(m, "------------------------\n"); + seq_printf(m, "Total %d devices\n", ai); + } + + return 0; +} + +static int +proc_reg_status_open(struct inode *inode, struct file *file) +{ + return single_open(file, proc_reg_status_show, NULL); +} + +static int +proc_reg_status_release(struct inode *inode, struct file *file) +{ + return single_release(inode, file); +} + +static struct file_operations proc_reg_status_fops = { + owner: THIS_MODULE, + open: proc_reg_status_open, + read: seq_read, + llseek: seq_lseek, + release: proc_reg_status_release, +}; + +static int +proc_ring_status_show(struct seq_file *m, void *v) +{ + struct ngknet_dev *dev; + int di, qi, ai = 0; + + for (di = 0; di < NUM_PDMA_DEV_MAX; di++) { + dev = &ngknet_devices[di]; + if (!(dev->flags & NGKNET_DEV_ACTIVE)) { + continue; + } + ai++; + seq_printf(m, "%s-%d, ", "Unit", di); + for (qi = 0; qi < dev->pdma_dev.ctrl.nb_rxq; qi++) { + bcmcnet_pdma_rx_ring_dump(&dev->pdma_dev, qi); + } + seq_printf(m, "%s%d, ", "Rx queues: ", qi); + for (qi = 0; qi < dev->pdma_dev.ctrl.nb_txq; qi++) { + bcmcnet_pdma_tx_ring_dump(&dev->pdma_dev, qi); + } + seq_printf(m, "%s%d. ", "Tx queues: ", qi); + seq_printf(m, "\n"); + } + + if (!ai) { + seq_printf(m, "%s\n", "No active device"); + } else { + seq_printf(m, "------------------------\n"); + seq_printf(m, "Total %d devices\n", ai); + } + + return 0; +} + +static int +proc_ring_status_open(struct inode *inode, struct file *file) +{ + return single_open(file, proc_ring_status_show, NULL); +} + +static int +proc_ring_status_release(struct inode *inode, struct file *file) +{ + return single_release(inode, file); +} + +static struct file_operations proc_ring_status_fops = { + owner: THIS_MODULE, + open: proc_ring_status_open, + read: seq_read, + llseek: seq_lseek, + release: proc_ring_status_release, +}; + +int +ngknet_procfs_init(void) +{ + struct proc_dir_entry *entry = NULL; + + proc_root = proc_mkdir(NGKNET_MODULE_NAME, NULL); + if (proc_root == NULL) { + printk(KERN_ERR "ngknet: proc_mkdir failed\n"); + return -1; + } + + PROC_CREATE(entry, "debug_level", 0666, proc_root, &proc_debug_level_fops); + if (entry == NULL) { + printk(KERN_ERR "ngknet: proc_create failed\n"); + return -1; + } + + PROC_CREATE(entry, "device_info", 0444, proc_root, &proc_device_info_fops); + if (entry == NULL) { + printk(KERN_ERR "ngknet: proc_create failed\n"); + return -1; + } + + PROC_CREATE(entry, "filter_info", 0444, proc_root, &proc_filter_info_fops); + if (entry == NULL) { + printk(KERN_ERR "ngknet: proc_create failed\n"); + return -1; + } + + PROC_CREATE(entry, "netif_info", 0444, proc_root, &proc_netif_info_fops); + if (entry == NULL) { + printk(KERN_ERR "ngknet: proc_create failed\n"); + return -1; + } + + PROC_CREATE(entry, "pkt_stats", 0444, proc_root, &proc_pkt_stats_fops); + if (entry == NULL) { + printk(KERN_ERR "ngknet: proc_create failed\n"); + return -1; + } + + PROC_CREATE(entry, "rate_limit", 0666, proc_root, &proc_rate_limit_fops); + if (entry == NULL) { + printk(KERN_ERR "ngknet: proc_create failed\n"); + return -1; + } + + PROC_CREATE(entry, "reg_status", 0444, proc_root, &proc_reg_status_fops); + if (entry == NULL) { + printk(KERN_ERR "ngknet: proc_create failed\n"); + return -1; + } + + PROC_CREATE(entry, "ring_status", 0444, proc_root, &proc_ring_status_fops); + if (entry == NULL) { + printk(KERN_ERR "ngknet: proc_create failed\n"); + return -1; + } + + return 0; +} + +int +ngknet_procfs_cleanup(void) +{ + remove_proc_entry("debug_level", proc_root); + remove_proc_entry("device_info", proc_root); + remove_proc_entry("filter_info", proc_root); + remove_proc_entry("netif_info", proc_root); + remove_proc_entry("pkt_stats", proc_root); + remove_proc_entry("rate_limit", proc_root); + remove_proc_entry("reg_status", proc_root); + remove_proc_entry("ring_status", proc_root); + + remove_proc_entry(NGKNET_MODULE_NAME, NULL); + + return 0; +} + diff --git a/platform/broadcom/saibcm-modules/sdklt/linux/knet/ngknet_procfs.h b/platform/broadcom/saibcm-modules/sdklt/linux/knet/ngknet_procfs.h new file mode 100644 index 00000000000..3c1938121eb --- /dev/null +++ b/platform/broadcom/saibcm-modules/sdklt/linux/knet/ngknet_procfs.h @@ -0,0 +1,47 @@ +/*! \file ngknet_procfs.h + * + * Procfs-related definitions and APIs for NGKNET module. + * + */ +/* + * $Copyright: Copyright 2018-2020 Broadcom. All rights reserved. + * The term 'Broadcom' refers to Broadcom Inc. and/or its subsidiaries. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * version 2 as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * A copy of the GNU General Public License version 2 (GPLv2) can + * be found in the LICENSES folder.$ + */ + +#ifndef NGKNET_PROCFS_H +#define NGKNET_PROCFS_H + +/*! + * \brief Initialize procfs for KNET driver. + * + * Create procfs read/write interfaces. + * + * \return 0 if no errors, otherwise -1. + */ +extern int +ngknet_procfs_init(void); + +/*! + * \brief Clean up procfs for KNET driver. + * + * Clean up resources allocated by \ref ngknet_procfs_init. + * + * \return 0 if no errors, otherwise -1. + */ +extern int +ngknet_procfs_cleanup(void); + +#endif /* NGKNET_PROCFS_H */ + diff --git a/platform/broadcom/saibcm-modules/sdklt/linux/knet/ngknet_ptp.c b/platform/broadcom/saibcm-modules/sdklt/linux/knet/ngknet_ptp.c new file mode 100644 index 00000000000..13579208eab --- /dev/null +++ b/platform/broadcom/saibcm-modules/sdklt/linux/knet/ngknet_ptp.c @@ -0,0 +1,194 @@ +/*! \file ngknet_ptp.c + * + * Utility routines for PTP. + * + */ +/* + * $Copyright: Copyright 2018-2020 Broadcom. All rights reserved. + * The term 'Broadcom' refers to Broadcom Inc. and/or its subsidiaries. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * version 2 as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * A copy of the GNU General Public License version 2 (GPLv2) can + * be found in the LICENSES folder.$ + */ + +#include "ngknet_callback.h" +#include "ngknet_ptp.h" + +int +ngknet_ptp_rx_config_set(struct net_device *ndev, int *filter) +{ + struct ngknet_private *priv = netdev_priv(ndev); + struct ngknet_dev *dev = priv->bkn_dev; + + if (!dev->cbc->ptp_rx_config_set_cb) { + return SHR_E_UNAVAIL; + } + + /* + * The expected Rx filter value is passed to the callback. The callback + * should pass back the actual filter value by the paramter . + * The callback can use priv->user_data to get other private parameters + * such as phys_port, dev_type, etc, which should be introduced when the + * netif is created. + */ + return dev->cbc->ptp_rx_config_set_cb(priv, filter); +} + +int +ngknet_ptp_tx_config_set(struct net_device *ndev, int type) +{ + struct ngknet_private *priv = netdev_priv(ndev); + struct ngknet_dev *dev = priv->bkn_dev; + + if (!dev->cbc->ptp_tx_config_set_cb) { + return SHR_E_UNAVAIL; + } + + /* + * The Tx type value is passed to the callback by the parameter . + * The callback should do the configuration according to the type. + * The callback can use priv->user_data to get other private parameters + * such as phys_port, dev_type, etc, which should be introduced when the + * netif is created. + */ + return dev->cbc->ptp_tx_config_set_cb(priv, &type); +} + +int +ngknet_ptp_rx_hwts_get(struct net_device *ndev, struct sk_buff *skb, uint64_t *ts) +{ + struct ngknet_private *priv = netdev_priv(ndev); + struct ngknet_dev *dev = priv->bkn_dev; + struct ngknet_callback_desc *cbd = NGKNET_SKB_CB(skb); + struct pkt_hdr *pkh = (struct pkt_hdr *)skb->data; + + if (!dev->cbc->ptp_rx_hwts_get_cb) { + return SHR_E_UNAVAIL; + } + + cbd->dev_no = dev->dev_no; + cbd->dev_id = dev->pdma_dev.dev_id; + cbd->priv = priv; + cbd->pmd = skb->data + PKT_HDR_SIZE; + cbd->pmd_len = pkh->meta_len; + cbd->pkt_len = pkh->data_len; + + /* + * The callback should get timestamp value for a Rx packet and return + * by the parameter . + * Some parameters have been consolidated to SKB as above. They can be + * achieved by NGKNET_SKB_CB(skb). Specially more private paramters are + * in NGKNET_SKB_CB(skb)->priv->user_data[]. + */ + return dev->cbc->ptp_rx_hwts_get_cb(skb, ts); +} + +int +ngknet_ptp_tx_hwts_get(struct net_device *ndev, struct sk_buff *skb, uint64_t *ts) +{ + struct ngknet_private *priv = netdev_priv(ndev); + struct ngknet_dev *dev = priv->bkn_dev; + struct ngknet_callback_desc *cbd = NGKNET_SKB_CB(skb); + struct pkt_hdr *pkh = (struct pkt_hdr *)skb->data; + + if (!dev->cbc->ptp_tx_hwts_get_cb) { + return SHR_E_UNAVAIL; + } + + cbd->dev_no = dev->dev_no; + cbd->dev_id = dev->pdma_dev.dev_id; + cbd->priv = priv; + cbd->pmd = skb->data + PKT_HDR_SIZE; + cbd->pmd_len = pkh->meta_len; + cbd->pkt_len = pkh->data_len; + + /* + * The callback should get timestamp value for a Tx packet and return + * by the parameter . + * For HWTSTAMP_TX_ONESTEP_SYNC type, the time value can be achieved and + * returned immediately. Otherwise, for HWTSTAMP_TX_ON type, the callback + * should wait till the time value can be available, i.e. the packet has + * been tranmitted out from port. + * Some parameters have been consolidated to SKB as above. They can be + * achieved by NGKNET_SKB_CB(skb). Specially more private paramters are + * in NGKNET_SKB_CB(skb)->priv->user_data[] such as phys_port, dev_type, + * and so on. + */ + return dev->cbc->ptp_tx_hwts_get_cb(skb, ts); +} + +int +ngknet_ptp_tx_meta_set(struct net_device *ndev, struct sk_buff *skb) +{ + struct ngknet_private *priv = netdev_priv(ndev); + struct ngknet_dev *dev = priv->bkn_dev; + struct ngknet_callback_desc *cbd = NGKNET_SKB_CB(skb); + struct pkt_hdr *pkh = (struct pkt_hdr *)skb->data; + + if (!dev->cbc->ptp_tx_meta_set_cb) { + return SHR_E_UNAVAIL; + } + + cbd->dev_no = dev->dev_no; + cbd->dev_id = dev->pdma_dev.dev_id; + cbd->priv = priv; + cbd->pmd = skb->data + PKT_HDR_SIZE; + cbd->pmd_len = pkh->meta_len; + cbd->pkt_len = pkh->data_len; + + /* + * The callback should configure the metadata pmd> + * for HW timestamping according to the corresponding switch device. + * Some parameters have been consolidated to SKB as above. They can be + * achieved by NGKNET_SKB_CB(skb). Specially more private paramters are + * in NGKNET_SKB_CB(skb)->priv->user_data[] such as phys_port, dev_type, + * and so on. + */ + return dev->cbc->ptp_tx_meta_set_cb(skb); +} + +int +ngknet_ptp_phc_index_get(struct net_device *ndev, int *index) +{ + struct ngknet_private *priv = netdev_priv(ndev); + struct ngknet_dev *dev = priv->bkn_dev; + + if (!dev->cbc->ptp_phc_index_get_cb) { + return SHR_E_UNAVAIL; + } + + /* + * The callback should return the HPC index by the parameter . + * priv->user_data[] can be used to get other private parameters such as + * phys_port, dev_type, etc, which should be introduced when the netif is + * created. + */ + return dev->cbc->ptp_phc_index_get_cb(priv, index); +} + +int +ngknet_ptp_dev_ctrl(struct ngknet_dev *dev, int cmd, char *data, int len) +{ + if (!dev->cbc->ptp_dev_ctrl_cb) { + return SHR_E_UNAVAIL; + } + + /* + * The callback is IOCTL dispatcher for PTP driver/module. + * The parameter is the command defined by the user. The parameter + * and are used for interactions between the user application + * and the driver for PTP device start/stop, enable/disable, set/get, and + * so on. + */ + return dev->cbc->ptp_dev_ctrl_cb(dev, cmd, data, len); +} + diff --git a/platform/broadcom/saibcm-modules/sdklt/linux/knet/ngknet_ptp.h b/platform/broadcom/saibcm-modules/sdklt/linux/knet/ngknet_ptp.h new file mode 100644 index 00000000000..86dcb6c4904 --- /dev/null +++ b/platform/broadcom/saibcm-modules/sdklt/linux/knet/ngknet_ptp.h @@ -0,0 +1,111 @@ +/*! \file ngknet_ptp.h + * + * Definitions and APIs declaration for PTP. + * + */ +/* + * $Copyright: Copyright 2018-2020 Broadcom. All rights reserved. + * The term 'Broadcom' refers to Broadcom Inc. and/or its subsidiaries. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * version 2 as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * A copy of the GNU General Public License version 2 (GPLv2) can + * be found in the LICENSES folder.$ + */ + +#ifndef NGKNET_PTP_H +#define NGKNET_PTP_H + +#include +#include "ngknet_main.h" + +/*! + * \brief PTP Rx config set. + * + * \param [in] ndev Network device structure point. + * \param [in] filter Rx filter. + * + * \retval SHR_E_NONE No errors. + */ +extern int +ngknet_ptp_rx_config_set(struct net_device *ndev, int *filter); + +/*! + * \brief PTP Tx config set. + * + * \param [in] ndev Network device structure point. + * \param [in] type Tx type. + * + * \retval SHR_E_NONE No errors. + */ +extern int +ngknet_ptp_tx_config_set(struct net_device *ndev, int type); + +/*! + * \brief PTP Rx HW timestamping get. + * + * \param [in] ndev Network device structure point. + * \param [in] skb Rx packet SKB. + * \param [out] ts Timestamp value. + * + * \retval SHR_E_NONE No errors. + */ +extern int +ngknet_ptp_rx_hwts_get(struct net_device *ndev, struct sk_buff *skb, uint64_t *ts); + +/*! + * \brief PTP Tx HW timestamping get. + * + * \param [in] ndev Network device structure point. + * \param [in] skb Tx packet SKB. + * \param [out] ts Timestamp value. + * + * \retval SHR_E_NONE No errors. + */ +extern int +ngknet_ptp_tx_hwts_get(struct net_device *ndev, struct sk_buff *skb, uint64_t *ts); + +/*! + * \brief PTP Tx meta set. + * + * \param [in] ndev Network device structure point. + * \param [in] skb Tx packet SKB. + * + * \retval SHR_E_NONE No errors. + */ +extern int +ngknet_ptp_tx_meta_set(struct net_device *ndev, struct sk_buff *skb); + +/*! + * \brief PTP PHC index get. + * + * \param [in] ndev Network device structure point. + * \param [out] index PHC index. + * + * \retval SHR_E_NONE No errors. + */ +extern int +ngknet_ptp_phc_index_get(struct net_device *ndev, int *index); + +/*! + * \brief PTP device control. + * + * \param [in] dev NGKNET device structure point. + * \param [in] cmd Command. + * \param [in] data Data buffer. + * \param [in] len Data length. + * + * \retval SHR_E_NONE No errors. + */ +extern int +ngknet_ptp_dev_ctrl(struct ngknet_dev *dev, int cmd, char *data, int len); + +#endif /* NGKNET_PTP_H */ + diff --git a/platform/broadcom/saibcm-modules/sdklt/linux/knetcb/Kbuild b/platform/broadcom/saibcm-modules/sdklt/linux/knetcb/Kbuild new file mode 100644 index 00000000000..2ce66edb3c6 --- /dev/null +++ b/platform/broadcom/saibcm-modules/sdklt/linux/knetcb/Kbuild @@ -0,0 +1,36 @@ +# -*- Kbuild -*- +# +# Linux KNET Callback module. +# +# $Copyright: Copyright 2018-2020 Broadcom. All rights reserved. +# The term 'Broadcom' refers to Broadcom Inc. and/or its subsidiaries. +# +# This program is free software; you can redistribute it and/or +# modify it under the terms of the GNU General Public License +# version 2 as published by the Free Software Foundation. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# A copy of the GNU General Public License version 2 (GPLv2) can +# be found in the LICENSES folder.$ +# +ifeq ($(BUILD_PSAMPLE),1) +PSAMPLE_CFLAGS=-DPSAMPLE_SUPPORT +PSAMPLE_CB_OBJS=psample-cb.o +endif + +obj-m := linux_ngknetcb.o + +ccflags-y := $(LKM_CFLAGS) \ + -I$(SDK)/shr/include \ + -I$(SDK)/bcmdrd/include \ + -I$(SDK)/linux/include \ + -I$(SDK)/linux/knet/include \ + -I$(SDK)/linux/knet \ + $(PSAMPLE_CFLAGS) + +linux_ngknetcb-y := ngknetcb_main.o \ + $(PSAMPLE_CB_OBJS) diff --git a/platform/broadcom/saibcm-modules/sdklt/linux/knetcb/Makefile b/platform/broadcom/saibcm-modules/sdklt/linux/knetcb/Makefile new file mode 100644 index 00000000000..e2acfed49d6 --- /dev/null +++ b/platform/broadcom/saibcm-modules/sdklt/linux/knetcb/Makefile @@ -0,0 +1,33 @@ +# -*- Makefile -*- +# +# Linux KNET Callback module. +# +# $Copyright: Copyright 2018-2020 Broadcom. All rights reserved. +# The term 'Broadcom' refers to Broadcom Inc. and/or its subsidiaries. +# +# This program is free software; you can redistribute it and/or +# modify it under the terms of the GNU General Public License +# version 2 as published by the Free Software Foundation. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# A copy of the GNU General Public License version 2 (GPLv2) can +# be found in the LICENSES folder.$ +# + +include Kbuild + +ifeq ($(KERNELRELEASE),) + +MOD_NAME = linux_ngknetcb + +include $(SDK)/make/lkm.mk + +endif + +.PHONY: distclean + +distclean: diff --git a/platform/broadcom/saibcm-modules/sdklt/linux/knetcb/ngknetcb_main.c b/platform/broadcom/saibcm-modules/sdklt/linux/knetcb/ngknetcb_main.c new file mode 100644 index 00000000000..aa248dafce5 --- /dev/null +++ b/platform/broadcom/saibcm-modules/sdklt/linux/knetcb/ngknetcb_main.c @@ -0,0 +1,444 @@ +/*! \file ngknetcb_main.c + * + * NGKNET Callback module entry. + */ +/* + * $Copyright: (c) 2019 Broadcom. + * Broadcom Proprietary and Confidential. All rights reserved.$ + */ + +#include +#include +#include "psample-cb.h" + +/*! \cond */ +MODULE_AUTHOR("Broadcom Corporation"); +MODULE_DESCRIPTION("NGKNET Callback Module"); +MODULE_LICENSE("GPL"); +/*! \endcond */ + +/*! \cond */ +int debug = 0; +MODULE_PARAM(debug, int, 0); +MODULE_PARM_DESC(debug, +"Debug level (default 0)"); +/*! \endcond */ + +/*! Module information */ +#define NGKNETCB_MODULE_NAME "linux_ngknetcb" +#define NGKNETCB_MODULE_MAJOR 122 + +/* set KNET_CB_DEBUG for debug info */ +#define KNET_CB_DEBUG + +/* These below need to match incoming enum values */ +#define FILTER_TAG_STRIP 0 +#define FILTER_TAG_KEEP 1 +#define FILTER_TAG_ORIGINAL 2 + +/* Maintain tag strip statistics */ +struct strip_stats_s { + unsigned long stripped; /* Number of packets that have been stripped */ + unsigned long checked; + unsigned long skipped; +}; + +static struct strip_stats_s strip_stats; +static unsigned int rx_count = 0; + +/* Local function prototypes */ +static void strip_vlan_tag(struct sk_buff *skb); + +/* Remove VLAN tag for select TPIDs */ +static void +strip_vlan_tag(struct sk_buff *skb) +{ + uint16_t vlan_proto; + uint8_t *pkt = skb->data; + + vlan_proto = (uint16_t) ((pkt[12] << 8) | pkt[13]); + if ((vlan_proto == 0x8100) || (vlan_proto == 0x88a8) || (vlan_proto == 0x9100)) { + /* Move first 12 bytes of packet back by 4 */ + memmove(&skb->data[4], skb->data, 12); + skb_pull(skb, 4); /* Remove 4 bytes from start of buffer */ + } +} + +/* + * The function get_tag_status() returns the tag status. + * 0 = Untagged + * 1 = Single inner-tag + * 2 = Single outer-tag + * 3 = Double tagged. + * -1 = Unsupported type + */ +static int +get_tag_status(uint32_t dev_type, void *meta) +{ + uint32_t *valptr; + uint32_t fd_index; + uint32_t outer_l2_hdr; + int tag_status = -1; + + if ((dev_type == 0xb880) || (dev_type == 0xb780)) + { + /* Field BCM_PKTIO_RXPMD_MATCH_ID_LO has tag status in RX PMD */ + fd_index = 2; + valptr = (uint32_t *)meta; + outer_l2_hdr = (valptr[fd_index] >> ((dev_type == 0xb780) ? 2 : 1) & 0xFF); + + if (outer_l2_hdr & 0x1) { +#ifdef KNET_CB_DEBUG + if (debug & 0x1) { + printk(" L2 Header Present\n"); + } +#endif + tag_status = 0; + if (outer_l2_hdr & 0x4) { +#ifdef KNET_CB_DEBUG + if (debug & 0x1) { + printk(" SNAP/LLC\n"); + } +#endif + tag_status = 0; + } + if (outer_l2_hdr & 0x10) { +#ifdef KNET_CB_DEBUG + if (debug & 0x1) { + printk(" Outer Tagged\n"); + } +#endif + tag_status = 2; + if (outer_l2_hdr & 0x20) { +#ifdef KNET_CB_DEBUG + if (debug & 0x1) { + printk(" Double Tagged\n"); + } +#endif + tag_status = 3; + } + } + else if (outer_l2_hdr & 0x20) { +#ifdef KNET_CB_DEBUG + if (debug & 0x1) { + printk(" Inner Tagged\n"); + } +#endif + tag_status = 1; + } + } + } + else if ((dev_type == 0xb990)|| (dev_type == 0xb996)) + { + fd_index = 9; + valptr = (uint32_t *)meta; + /* On TH4, outer_l2_header means INCOMING_TAG_STATUS. + * TH4 only supports single tagging, so if TAG_STATUS + * says there's a tag, then we don't want to strip. + * Otherwise, we do. + */ + outer_l2_hdr = (valptr[fd_index] >> 13) & 3; + + if (outer_l2_hdr) + { + tag_status = 2; +#ifdef KNET_CB_DEBUG + if (debug & 0x1) + { + printk(" Incoming frame tagged\n"); + } +#endif + } + else + { + tag_status = 0; +#ifdef KNET_CB_DEBUG + if (debug & 0x1) + { + printk(" Incoming frame untagged\n"); + } +#endif + } + } +#ifdef KNET_CB_DEBUG + if (debug & 0x1) { + printk("%s; Device Type: %d; tag status: %d\n", __func__, dev_type, tag_status); + } +#endif + return tag_status; +} + +#ifdef KNET_CB_DEBUG +static void +dump_buffer(uint8_t * data, int size) +{ + const char *const to_hex = "0123456789ABCDEF"; + int i; + char buffer[128]; + char *buffer_ptr; + int addr = 0; + + buffer_ptr = buffer; + for (i = 0; i < size; i++) { + *buffer_ptr++ = ' '; + *buffer_ptr++ = to_hex[(data[i] >> 4) & 0xF]; + *buffer_ptr++ = to_hex[data[i] & 0xF]; + if (((i % 16) == 15) || (i == size - 1)) { + *buffer_ptr = '\0'; + buffer_ptr = buffer; + printk(KERN_INFO "%04X %s\n", addr, buffer); + addr = i + 1; + } + } +} + +static void +show_pmd(uint8_t *pmd, int len) +{ + if (debug & 0x1) { + printk("PMD (%d bytes):\n", len); + dump_buffer(pmd, len); + } +} + +static void +show_mac(uint8_t *pkt) +{ + if (debug & 0x1) { + printk("DMAC=%02X:%02X:%02X:%02X:%02X:%02X\n", + pkt[0], pkt[1], pkt[2], pkt[3], pkt[4], pkt[5]); + } +} +#endif + +static struct sk_buff * +strip_tag_rx_cb(struct sk_buff *skb) +{ + const struct ngknet_callback_desc *cbd = NGKNET_SKB_CB(skb); + const struct ngknet_private *priv = cbd->priv; + int rcpu_mode = 0; + int tag_status; + + rcpu_mode = (priv->flags & NGKNET_NETIF_F_RCPU_ENCAP)? 1 : 0; +#ifdef KNET_CB_DEBUG + if (debug & 0x1) + { + printk(KERN_INFO + "\n%4u --------------------------------------------------------------------------------\n", + rx_count); + printk(KERN_INFO + "RX KNET callback: dev_no=%1d; dev_id=0x%04X; type_str=%4s; RCPU: %3s \n", + cbd->dev_no, cbd->dev_id, cbd->type_str, rcpu_mode ? "yes" : "no"); + printk(KERN_INFO " pkt_len=%4d; pmd_len=%2d; SKB len: %4d\n", + cbd->pkt_len, cbd->pmd_len, skb->len); + if (cbd->filt) { + printk(KERN_INFO "Filter user data: 0x%08x\n", + *(uint32_t *) cbd->filt->user_data); + } + printk(KERN_INFO "Before SKB (%d bytes):\n", skb->len); + dump_buffer(skb->data, skb->len); + printk("rx_cb for dev %d: id 0x%x, %s\n", cbd->dev_no, cbd->dev_id, cbd->type_str); + printk("netif user data: 0x%08x\n", *(uint32_t *)cbd->priv->user_data); + show_pmd(cbd->pmd, cbd->pmd_len); + if (rcpu_mode) { + const int RCPU_header_len = PKT_HDR_SIZE + cbd->pmd_len; + const int payload_len = skb->len - RCPU_header_len; + unsigned char *payload_start = skb->data + payload_len; + + printk(KERN_INFO "Packet Payload (%d bytes):\n", payload_len); + dump_buffer(payload_start, payload_len); + } else { + printk(KERN_INFO "Packet (%d bytes):\n", cbd->pkt_len); + dump_buffer(skb->data, cbd->pkt_len); + } + } +#endif + + if ((!rcpu_mode) && (cbd->filt)) { + if (FILTER_TAG_ORIGINAL == cbd->filt->user_data[0]) { + tag_status = get_tag_status(cbd->dev_id, (void *)cbd->pmd); + if (tag_status < 0) { + strip_stats.skipped++; + goto _strip_tag_rx_cb_exit; + } + strip_stats.checked++; + if (tag_status < 2) { + strip_stats.stripped++; + strip_vlan_tag(skb); + } + } + } +_strip_tag_rx_cb_exit: +#ifdef KNET_CB_DEBUG + if (debug & 0x1) { + printk(KERN_INFO "After SKB (%d bytes):\n", skb->len); + dump_buffer(skb->data, skb->len); + printk(KERN_INFO + "\n%4u --------------------------------------------------------------------------------\n", + rx_count++); + } +#endif + return skb; +} + +static struct sk_buff * +strip_tag_tx_cb(struct sk_buff *skb) +{ +#ifdef KNET_CB_DEBUG + struct ngknet_callback_desc *cbd = NGKNET_SKB_CB(skb); + + if (debug & 0x1) { + printk("tx_cb for dev %d: %s\n", cbd->dev_no, cbd->type_str); + } + show_pmd(cbd->pmd, cbd->pmd_len); + show_mac(cbd->pmd + cbd->pmd_len); +#endif + return skb; +} + +static struct sk_buff * +ngknet_rx_cb(struct sk_buff *skb) +{ + skb = strip_tag_rx_cb(skb); +#ifdef PSAMPLE_SUPPORT + skb = psample_rx_cb(skb); +#endif + return skb; +} + +static struct sk_buff * +ngknet_tx_cb(struct sk_buff *skb) +{ + skb = strip_tag_tx_cb(skb); + return skb; +} + +static int +ngknet_netif_create_cb(struct net_device *dev) +{ + int retv = 0; +#ifdef PSAMPLE_SUPPORT + retv = psample_netif_create_cb(dev); +#endif + return retv; +} + +static int +ngknet_netif_destroy_cb(struct net_device *dev) +{ + int retv = 0; +#ifdef PSAMPLE_SUPPORT + retv = psample_netif_destroy_cb(dev); +#endif + return retv; +} + +/*! + * Generic module functions + */ +static int +ngknetcb_show(struct seq_file *m, void *v) +{ + seq_printf(m, "Broadcom Linux NGKNET Callback: Untagged VLAN Stripper\n"); + seq_printf(m, " %lu stripped packets\n", strip_stats.stripped); + seq_printf(m, " %lu packets checked\n", strip_stats.checked); + seq_printf(m, " %lu packets skipped\n", strip_stats.skipped); + return 0; +} + +static int +ngknetcb_open(struct inode *inode, struct file *filp) +{ + return single_open(filp, ngknetcb_show, NULL); +} + +static int +ngknetcb_release(struct inode *inode, struct file *filp) +{ + return 0; +} + +static ssize_t +ngknetcb_write(struct file *file, const char *buf, + size_t count, loff_t *loff) +{ + memset(&strip_stats, 0, sizeof(strip_stats)); + printk("Cleared NGKNET callback stats\n"); + return count; +} + +static long +ngknetcb_ioctl(struct file *file, unsigned int cmd, unsigned long arg) +{ + return 0; +} + +static int +ngknetcb_mmap(struct file *filp, struct vm_area_struct *vma) +{ + return 0; +} + +static struct file_operations ngknetcb_fops = { + .owner = THIS_MODULE, + .open = ngknetcb_open, + .read = seq_read, + .write = ngknetcb_write, + .llseek = seq_lseek, + .release = ngknetcb_release, + .unlocked_ioctl = ngknetcb_ioctl, + .compat_ioctl = ngknetcb_ioctl, + .mmap = ngknetcb_mmap, +}; + +static int __init +ngknetcb_init_module(void) +{ + int rv; + struct proc_dir_entry *entry = NULL; + + rv = register_chrdev(NGKNETCB_MODULE_MAJOR, NGKNETCB_MODULE_NAME, &ngknetcb_fops); + if (rv < 0) { + printk(KERN_WARNING "%s: can't get major %d\n", + NGKNETCB_MODULE_NAME, NGKNETCB_MODULE_MAJOR); + return rv; + } + + PROC_CREATE(entry, NGKNETCB_MODULE_NAME, 0666, NULL, &ngknetcb_fops); + if (entry == NULL) { + printk(KERN_ERR "%s: proc_mkdir failed\n", + NGKNETCB_MODULE_NAME); + } + + ngknet_rx_cb_register(ngknet_rx_cb); + ngknet_tx_cb_register(ngknet_tx_cb); + +#ifdef PSAMPLE_SUPPORT + psample_init(); +#endif + + ngknet_netif_create_cb_register(ngknet_netif_create_cb); + ngknet_netif_destroy_cb_register(ngknet_netif_destroy_cb); + return 0; +} + +static void __exit +ngknetcb_exit_module(void) +{ + ngknet_netif_create_cb_unregister(ngknet_netif_create_cb); + ngknet_netif_destroy_cb_unregister(ngknet_netif_destroy_cb); + +#ifdef PSAMPLE_SUPPORT + psample_cleanup(); +#endif + + ngknet_rx_cb_unregister(ngknet_rx_cb); + ngknet_tx_cb_unregister(ngknet_tx_cb); + + remove_proc_entry(NGKNETCB_MODULE_NAME, NULL); + + unregister_chrdev(NGKNETCB_MODULE_MAJOR, NGKNETCB_MODULE_NAME); +} + +module_init(ngknetcb_init_module); +module_exit(ngknetcb_exit_module); diff --git a/platform/broadcom/saibcm-modules/sdklt/linux/knetcb/psample-cb.c b/platform/broadcom/saibcm-modules/sdklt/linux/knetcb/psample-cb.c new file mode 100644 index 00000000000..be34430218d --- /dev/null +++ b/platform/broadcom/saibcm-modules/sdklt/linux/knetcb/psample-cb.c @@ -0,0 +1,995 @@ +/* + * Copyright 2017-2019 Broadcom + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License, version 2, as + * published by the Free Software Foundation (the "GPL"). + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License version 2 (GPLv2) for more details. + * + * You should have received a copy of the GNU General Public License + * version 2 (GPLv2) along with this source code. + */ +/* + * $Id: psample_cb.c $ + * $Copyright: (c) 2019 Broadcom Corp. + * All Rights Reserved.$ + */ + +/* + * Driver for call-back functions for Linux KNET driver. + * + * This code is used to integrate packet sampling KNET callback to + * the psample infra for sending sampled pkts to userspace sflow + * applications such as Host Sflow (https://github.com/sflow/host-sflow) + * using genetlink interfaces. + * + * The module can be built from the standard Linux user mode target + * directories using the following command (assuming bash), e.g. + * + * cd $SDK/systems/linux/user/ + * make BUILD_KNET_CB=1 + * + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include "psample-cb.h" + +#define PSAMPLE_CB_DBG +#ifdef PSAMPLE_CB_DBG +extern int debug; +#define PSAMPLE_CB_DBG_LVL_VERB (0x1) +#define PSAMPLE_CB_DBG_LVL_PMD (0x2) +#define PSAMPLE_CB_DBG_PRINT(...) if (debug & PSAMPLE_CB_DBG_LVL_VERB) { printk(__VA_ARGS__); } +#define PSAMPLE_CB_PMD_PRINT(...) if (debug & PSAMPLE_CB_DBG_LVL_PMD) { printk(__VA_ARGS__); } +#else +#define PSAMPLE_CB_DBG_PRINT(...) +#define PSAMPLE_CB_PMD_PRINT(...) +#endif + +#define FCS_SZ 4 +#define PSAMPLE_NLA_PADDING 4 +#define PSAMPLE_PKT_HANDLED (1) + +#define PSAMPLE_RATE_DFLT 1 +#define PSAMPLE_SIZE_DFLT 128 +static int psample_size = PSAMPLE_SIZE_DFLT; +MODULE_PARAM(psample_size, int, 0); +MODULE_PARM_DESC(psample_size, +"psample pkt size (default 128 bytes)"); + +#define PSAMPLE_QLEN_DFLT 1024 +static int psample_qlen = PSAMPLE_QLEN_DFLT; +MODULE_PARAM(psample_qlen, int, 0); +MODULE_PARM_DESC(psample_qlen, +"psample queue length (default 1024 buffers)"); + +/* driver proc entry root */ +static struct proc_dir_entry *psample_proc_root = NULL; +static struct proc_dir_entry *knet_cb_proc_root = NULL; + +/* psample general info */ +typedef struct { + struct list_head netif_list; + int netif_count; + struct net *netns; + spinlock_t lock; + int dcb_type; +} psample_info_t; +static psample_info_t g_psample_info = {0}; + +/* Maintain sampled pkt statistics */ +typedef struct psample_stats_s { + unsigned long pkts_f_psample_cb; + unsigned long pkts_f_psample_mod; + unsigned long pkts_f_handled; + unsigned long pkts_f_pass_through; + unsigned long pkts_f_dst_mc; + unsigned long pkts_c_qlen_cur; + unsigned long pkts_c_qlen_hi; + unsigned long pkts_d_qlen_max; + unsigned long pkts_d_no_mem; + unsigned long pkts_d_no_group; + unsigned long pkts_d_sampling_disabled; + unsigned long pkts_d_not_ready; + unsigned long pkts_d_metadata; + unsigned long pkts_d_skb; + unsigned long pkts_d_skb_cbd; + unsigned long pkts_d_meta_srcport; + unsigned long pkts_d_meta_dstport; + unsigned long pkts_d_invalid_size; +} psample_stats_t; +static psample_stats_t g_psample_stats = {0}; + +typedef struct psample_meta_s { + int trunc_size; + int src_ifindex; + int dst_ifindex; + int sample_rate; +} psample_meta_t; + +typedef struct psample_pkt_s { + struct list_head list; + struct psample_group *group; + psample_meta_t meta; + struct sk_buff *skb; +} psample_pkt_t; + +typedef struct psample_work_s { + struct list_head pkt_list; + struct work_struct wq; + spinlock_t lock; +} psample_work_t; +static psample_work_t g_psample_work = {0}; + +static psample_netif_t* +psample_netif_lookup_by_ifindex(int ifindex) +{ + struct list_head *list; + psample_netif_t *psample_netif = NULL; + unsigned long flags; + + /* look for port from list of available net_devices */ + spin_lock_irqsave(&g_psample_info.lock, flags); + list_for_each(list, &g_psample_info.netif_list) { + psample_netif = (psample_netif_t*)list; + if (psample_netif->dev->ifindex == ifindex) { + spin_unlock_irqrestore(&g_psample_info.lock, flags); + return psample_netif; + } + } + spin_unlock_irqrestore(&g_psample_info.lock, flags); + return (NULL); +} + +static psample_netif_t* +psample_netif_lookup_by_port(int port) +{ + struct list_head *list; + psample_netif_t *psample_netif = NULL; + unsigned long flags; + + /* look for port from list of available net_devices */ + spin_lock_irqsave(&g_psample_info.lock, flags); + list_for_each(list, &g_psample_info.netif_list) { + psample_netif = (psample_netif_t*)list; + if (psample_netif->port == port) { + spin_unlock_irqrestore(&g_psample_info.lock, flags); + return psample_netif; + } + } + spin_unlock_irqrestore(&g_psample_info.lock, flags); + return (NULL); +} + +static int +psample_meta_sample_reason(uint8_t *pkt, void *pkt_meta) +{ + uint32_t *metadata = (uint32_t*)pkt_meta; + uint32_t reason = 0; + uint32_t reason_hi = 0; + uint32_t sample_rx_reason_mask = 0; + + if (metadata) { + /* Sample Pkt reason code (bcmRxReasonSampleSource) */ + switch(g_psample_info.dcb_type) { + case 36: /* TD3 */ + case 38: /* TH3 */ + reason_hi = *(metadata + 4); + reason = *(metadata + 5); + sample_rx_reason_mask = (1 << 3); + break; + case 32: /* TH1/TH2 */ + case 26: /* TD2 */ + case 23: /* HX4 */ + reason_hi = *(metadata + 2); + reason = *(metadata + 3); + sample_rx_reason_mask = (1 << 5); + break; + default: + break; + } + } + PSAMPLE_CB_DBG_PRINT("%s: DCB%d sample_rx_reason_mask: 0x%08x, reason: 0x%08x, reason_hi: 0x%08x\n", + __func__, g_psample_info.dcb_type, sample_rx_reason_mask, reason, reason_hi); + + /* Check if only sample reason code is set. + * If only sample reason code, then consume pkt. + * If other reason codes exist, then pkt should be + * passed through to Linux network stack. + */ + if ((reason & ~sample_rx_reason_mask) || reason_hi) { + return 0; /* multiple reasons set, pass through */ + } + + /* only sample rx reason set, consume pkt */ + return (PSAMPLE_PKT_HANDLED); +} + +static int +psample_meta_get(struct sk_buff *skb, psample_meta_t *sflow_meta) +{ + int src_ifindex = 0; + int sample_rate = 1; + int sample_size = PSAMPLE_SIZE_DFLT; + psample_netif_t *psample_netif = NULL; + const struct ngknet_callback_desc *cbd = NGKNET_SKB_CB(skb); + const struct ngknet_private *netif = cbd->priv; + memset(sflow_meta, 0, sizeof(psample_meta_t)); + + /* find src port */ + if ((psample_netif = psample_netif_lookup_by_ifindex(netif->net_dev->ifindex))) { + src_ifindex = psample_netif->dev->ifindex; + sample_rate = psample_netif->sample_rate; + sample_size = psample_netif->sample_size; + } else { + g_psample_stats.pkts_d_meta_srcport++; + PSAMPLE_CB_DBG_PRINT("%s: could not find psample netif for src dev %s (ifidx %d)\n", + __func__, netif->net_dev->name, netif->net_dev->ifindex); + } + + sflow_meta->src_ifindex = src_ifindex; + sflow_meta->trunc_size = sample_size; + sflow_meta->sample_rate = sample_rate; + return (0); +} + +static void +psample_task(struct work_struct *work) +{ + psample_work_t *psample_work = container_of(work, psample_work_t, wq); + unsigned long flags; + struct list_head *list_ptr, *list_next; + psample_pkt_t *pkt; + + spin_lock_irqsave(&psample_work->lock, flags); + list_for_each_safe(list_ptr, list_next, &psample_work->pkt_list) { + /* dequeue pkt from list */ + pkt = list_entry(list_ptr, psample_pkt_t, list); + list_del(list_ptr); + g_psample_stats.pkts_c_qlen_cur--; + spin_unlock_irqrestore(&psample_work->lock, flags); + + /* send to psample */ + if (pkt) { + PSAMPLE_CB_DBG_PRINT("%s: group 0x%x, trunc_size %d, src_ifdx 0x%x, dst_ifdx 0x%x, sample_rate %d\n", + __func__, pkt->group->group_num, + pkt->meta.trunc_size, pkt->meta.src_ifindex, + pkt->meta.dst_ifindex, pkt->meta.sample_rate); + + psample_sample_packet(pkt->group, + pkt->skb, + pkt->meta.trunc_size, + pkt->meta.src_ifindex, + pkt->meta.dst_ifindex, + pkt->meta.sample_rate); + g_psample_stats.pkts_f_psample_mod++; + + dev_kfree_skb_any(pkt->skb); + kfree(pkt); + } + spin_lock_irqsave(&psample_work->lock, flags); + } + spin_unlock_irqrestore(&psample_work->lock, flags); +} + +struct sk_buff* +psample_rx_cb(struct sk_buff *skb) +{ + struct psample_group *group; + psample_meta_t meta; + int rv = 0, size; + const struct ngknet_callback_desc *cbd = NULL; + const struct ngknet_private *netif = NULL; + const struct ngknet_filter_s *filt = NULL; + const struct ngknet_filter_s *filt_src = NULL; + + if (!skb) { + printk("%s: skb is NULL\n", __func__); + g_psample_stats.pkts_d_skb++; + return (NULL); + } + cbd = NGKNET_SKB_CB(skb); + netif = cbd->priv; + filt_src = cbd->filt; + filt = cbd->filt_cb; + + if (!cbd || !netif || !filt_src) { + printk("%s: cbd(0x%p) or priv(0x%p) or filter src(0x%p) is NULL\n", + __func__, cbd, netif, filt_src); + g_psample_stats.pkts_d_skb_cbd++; + return (skb); + } + + /* Enable PMD output in dmesg: "echo "debug=0x2" > /proc/bcm/knet-cb/psample/debug" + * Use bshell cmd "pmddecode rxpmd ..." to decode pkt metadata + */ + if (debug & PSAMPLE_CB_DBG_LVL_PMD) { + char str[128]; + int i, len = cbd->pmd_len > 128? 128 : cbd->pmd_len; + PSAMPLE_CB_PMD_PRINT("PMD (%d bytes): %s\n", + cbd->pmd_len, skb->dev->name); + for (i=0; ipmd+i))); + if ((i & 0x1c) == 0x1c) { + sprintf(&str[strlen(str)], "\n"); + printk(str); + continue; + } + } + if ((i & 0x1f) != 0) { + sprintf(&str[strlen(str)], "\n"); + PSAMPLE_CB_PMD_PRINT(str); + } + } + + /* check if this packet is sampled packet (from sample filter) */ + if (!filt || + (NGKNET_FILTER_DEST_T_CB != filt->dest_type) || + (strncmp(filt->desc, PSAMPLE_CB_NAME, NGKNET_FILTER_DESC_MAX) != 0)) { + return (skb); + } + + PSAMPLE_CB_DBG_PRINT("%s: src dev %s, pkt size %d, filt->dest_id %d\n", + __func__, skb->dev->name, cbd->pkt_len, filt->dest_id); + g_psample_stats.pkts_f_psample_cb++; + + /* get psample group info. psample genetlink group ID passed in filt->dest_id */ + group = psample_group_get(g_psample_info.netns, filt->dest_id); + if (!group) { + printk("%s: Could not find psample genetlink group %d\n", __func__, filt->dest_id); + g_psample_stats.pkts_d_no_group++; + goto PSAMPLE_FILTER_CB_PKT_HANDLED; + } + + /* get psample metadata */ + rv = psample_meta_get(skb, &meta); + if (rv < 0) { + printk("%s: Could not parse pkt metadata\n", __func__); + g_psample_stats.pkts_d_metadata++; + goto PSAMPLE_FILTER_CB_PKT_HANDLED; + } + + /* Adjust original pkt size to remove 4B FCS */ + size = cbd->pkt_len; + if (size < FCS_SZ) { + g_psample_stats.pkts_d_invalid_size++; + goto PSAMPLE_FILTER_CB_PKT_HANDLED; + } else { + size -= FCS_SZ; + } + + /* Account for padding in libnl used by psample */ + if (meta.trunc_size >= size) { + meta.trunc_size = size - PSAMPLE_NLA_PADDING; + } + + PSAMPLE_CB_DBG_PRINT("%s: group 0x%x, trunc_size %d, src_ifdx 0x%x, dst_ifdx 0x%x, sample_rate %d\n", + __func__, group->group_num, meta.trunc_size, meta.src_ifindex, meta.dst_ifindex, meta.sample_rate); + + /* drop if configured sample rate is 0 */ + if (meta.sample_rate > 0) { + unsigned long flags; + psample_pkt_t *psample_pkt; + struct sk_buff *skb_psample; + + if (g_psample_stats.pkts_c_qlen_cur >= psample_qlen) { + printk("%s: tail drop due to max qlen %d reached\n", __func__, psample_qlen); + g_psample_stats.pkts_d_qlen_max++; + goto PSAMPLE_FILTER_CB_PKT_HANDLED; + } + + if ((psample_pkt = kmalloc(sizeof(psample_pkt_t), GFP_ATOMIC)) == NULL) { + printk("%s: failed to alloc psample mem for pkt\n", __func__); + g_psample_stats.pkts_d_no_mem++; + goto PSAMPLE_FILTER_CB_PKT_HANDLED; + } + memcpy(&psample_pkt->meta, &meta, sizeof(psample_meta_t)); + psample_pkt->group = group; + + if ((skb_psample = dev_alloc_skb(meta.trunc_size)) == NULL) { + printk("%s: failed to alloc psample mem for pkt skb\n", __func__); + g_psample_stats.pkts_d_no_mem++; + goto PSAMPLE_FILTER_CB_PKT_HANDLED; + } + + /* setup skb to point to pkt */ + memcpy(skb_psample->data, skb->data, meta.trunc_size); + skb_put(skb_psample, meta.trunc_size); + skb_psample->len = meta.trunc_size; + psample_pkt->skb = skb_psample; + + spin_lock_irqsave(&g_psample_work.lock, flags); + list_add_tail(&psample_pkt->list, &g_psample_work.pkt_list); + + g_psample_stats.pkts_c_qlen_cur++; + if (g_psample_stats.pkts_c_qlen_cur > g_psample_stats.pkts_c_qlen_hi) { + g_psample_stats.pkts_c_qlen_hi = g_psample_stats.pkts_c_qlen_cur; + } + + schedule_work(&g_psample_work.wq); + spin_unlock_irqrestore(&g_psample_work.lock, flags); + } else { + g_psample_stats.pkts_d_sampling_disabled++; + } + +PSAMPLE_FILTER_CB_PKT_HANDLED: + /* if sample reason only, consume pkt. else pass through */ + rv = psample_meta_sample_reason(skb->data, cbd->pmd); + if (rv) { + g_psample_stats.pkts_f_handled++; + return NULL; + } + g_psample_stats.pkts_f_pass_through++; + return skb; +} + +int +psample_netif_create_cb(struct net_device *dev) +{ + int found; + struct list_head *list; + psample_netif_t *psample_netif, *lpsample_netif; + unsigned long flags; + struct ngknet_private *netif = NULL; + + if (!dev) { + printk("%s: net_device is NULL\n", __func__); + return (-1); + } + netif = netdev_priv(dev); + + if ((psample_netif = kmalloc(sizeof(psample_netif_t), GFP_ATOMIC)) == NULL) { + printk("%s: failed to alloc psample mem for netif '%s'\n", + __func__, dev->name); + return (-1); + } + + spin_lock_irqsave(&g_psample_info.lock, flags); + + psample_netif->dev = dev; + psample_netif->id = netif->id; + /* FIXME: port is not saved in ngknet_private, need to get from metadata?? */ + //psample_netif->port = netif->port; + psample_netif->vlan = netif->vlan; + psample_netif->sample_rate = PSAMPLE_RATE_DFLT; + psample_netif->sample_size = PSAMPLE_SIZE_DFLT; + + /* insert netif sorted by ID similar to bkn_knet_netif_create() */ + found = 0; + list_for_each(list, &g_psample_info.netif_list) { + lpsample_netif = (psample_netif_t*)list; + if (netif->id < lpsample_netif->id) { + found = 1; + g_psample_info.netif_count++; + break; + } + } + + if (found) { + /* Replace previously removed interface */ + list_add_tail(&psample_netif->list, &lpsample_netif->list); + } else { + /* No holes - add to end of list */ + list_add_tail(&psample_netif->list, &g_psample_info.netif_list); + } + + spin_unlock_irqrestore(&g_psample_info.lock, flags); + + PSAMPLE_CB_DBG_PRINT("%s: added psample netif '%s'\n", __func__, dev->name); + return (0); +} + +int +psample_netif_destroy_cb(struct net_device *dev) +{ + int found; + struct list_head *list; + psample_netif_t *psample_netif; + unsigned long flags; + struct ngknet_private *netif = NULL; + + if (!dev) { + printk("%s: net_device is NULL\n", __func__); + return (-1); + } + netif = netdev_priv(dev); + + spin_lock_irqsave(&g_psample_info.lock, flags); + + list_for_each(list, &g_psample_info.netif_list) { + psample_netif = (psample_netif_t*)list; + if (netif->id == psample_netif->id) { + found = 1; + list_del(&psample_netif->list); + PSAMPLE_CB_DBG_PRINT("%s: removing psample netif '%s'\n", __func__, dev->name); + kfree(psample_netif); + g_psample_info.netif_count--; + break; + } + } + + spin_unlock_irqrestore(&g_psample_info.lock, flags); + + if (!found) { + printk("%s: netif ID %d not found!\n", __func__, netif->id); + return (-1); + } + return (0); +} + +/* + * psample rate Proc Read Entry + */ +static int +psample_proc_rate_show(struct seq_file *m, void *v) +{ + struct list_head *list; + psample_netif_t *psample_netif; + unsigned long flags; + + spin_lock_irqsave(&g_psample_info.lock, flags); + + list_for_each(list, &g_psample_info.netif_list) { + psample_netif = (psample_netif_t*)list; + seq_printf(m, " %-14s %d\n", psample_netif->dev->name, psample_netif->sample_rate); + } + + spin_unlock_irqrestore(&g_psample_info.lock, flags); + + return 0; +} + +static int +psample_proc_rate_open(struct inode * inode, struct file * file) +{ + return single_open(file, psample_proc_rate_show, NULL); +} + +/* + * psample rate Proc Write Entry + * + * Syntax: + * = + * + * Where is a virtual network interface name. + * + * Examples: + * eth4=1000 + */ +static ssize_t +psample_proc_rate_write(struct file *file, const char *buf, + size_t count, loff_t *loff) +{ + int found; + struct list_head *list; + psample_netif_t *psample_netif; + char sample_str[40], *ptr, *newline; + unsigned long flags; + + + if (count > sizeof(sample_str)) { + count = sizeof(sample_str) - 1; + sample_str[count] = '\0'; + } + if (copy_from_user(sample_str, buf, count)) { + return -EFAULT; + } + sample_str[count] = 0; + newline = strchr(sample_str, '\n'); + if (newline) { + /* Chop off the trailing newline */ + *newline = '\0'; + } + + if ((ptr = strchr(sample_str, '=')) == NULL && + (ptr = strchr(sample_str, ':')) == NULL) { + printk("Error: Pkt sample rate syntax not recognized: '%s'\n", sample_str); + return count; + } + *ptr++ = 0; + + spin_lock_irqsave(&g_psample_info.lock, flags); + + found = 0; + list_for_each(list, &g_psample_info.netif_list) { + psample_netif = (psample_netif_t*)list; + if (strcmp(psample_netif->dev->name, sample_str) == 0) { + psample_netif->sample_rate = simple_strtol(ptr, NULL, 10); + // TODO MLI@BRCM - check valid sample rate + found = 1; + break; + } + } + + spin_unlock_irqrestore(&g_psample_info.lock, flags); + + if (!found) { + printk("Warning: Failed setting psample rate on unknown network interface: '%s'\n", sample_str); + } + return count; +} + +struct file_operations psample_proc_rate_file_ops = { + owner: THIS_MODULE, + open: psample_proc_rate_open, + read: seq_read, + llseek: seq_lseek, + write: psample_proc_rate_write, + release: single_release, +}; + +/* + * psample size Proc Read Entry + */ +static int +psample_proc_size_show(struct seq_file *m, void *v) +{ + struct list_head *list; + psample_netif_t *psample_netif; + unsigned long flags; + + spin_lock_irqsave(&g_psample_info.lock, flags); + + list_for_each(list, &g_psample_info.netif_list) { + psample_netif = (psample_netif_t*)list; + seq_printf(m, " %-14s %d\n", psample_netif->dev->name, psample_netif->sample_size); + } + + spin_unlock_irqrestore(&g_psample_info.lock, flags); + return 0; +} + +static int +psample_proc_size_open(struct inode * inode, struct file * file) +{ + return single_open(file, psample_proc_size_show, NULL); +} + +/* + * psample size Proc Write Entry + * + * Syntax: + * = + * + * Where is a virtual network interface name. + * + * Examples: + * eth4=128 + */ +static ssize_t +psample_proc_size_write(struct file *file, const char *buf, + size_t count, loff_t *loff) +{ + int found; + struct list_head *list; + psample_netif_t *psample_netif; + char sample_str[40], *ptr, *newline; + unsigned long flags; + + if (count > sizeof(sample_str)) { + count = sizeof(sample_str) - 1; + sample_str[count] = '\0'; + } + if (copy_from_user(sample_str, buf, count)) { + return -EFAULT; + } + sample_str[count] = 0; + newline = strchr(sample_str, '\n'); + if (newline) { + /* Chop off the trailing newline */ + *newline = '\0'; + } + + if ((ptr = strchr(sample_str, '=')) == NULL && + (ptr = strchr(sample_str, ':')) == NULL) { + printk("Error: Pkt sample size syntax not recognized: '%s'\n", sample_str); + return count; + } + *ptr++ = 0; + + spin_lock_irqsave(&g_psample_info.lock, flags); + + found = 0; + list_for_each(list, &g_psample_info.netif_list) { + psample_netif = (psample_netif_t*)list; + if (strcmp(psample_netif->dev->name, sample_str) == 0) { + psample_netif->sample_size = simple_strtol(ptr, NULL, 10); + // TODO MLI@BRCM - check valid sample size + found = 1; + break; + } + } + + spin_unlock_irqrestore(&g_psample_info.lock, flags); + + if (!found) { + printk("Warning: Failed setting psample size on unknown network interface: '%s'\n", sample_str); + } + return count; +} + +struct file_operations psample_proc_size_file_ops = { + owner: THIS_MODULE, + open: psample_proc_size_open, + read: seq_read, + llseek: seq_lseek, + write: psample_proc_size_write, + release: single_release, +}; + +/* + * psample map Proc Read Entry + */ +static int +psample_proc_map_show(struct seq_file *m, void *v) +{ + struct list_head *list; + psample_netif_t *psample_netif; + unsigned long flags; + + seq_printf(m, " Interface logical port ifindex\n"); + seq_printf(m, "------------- ------------ -------\n"); + spin_lock_irqsave(&g_psample_info.lock, flags); + + list_for_each(list, &g_psample_info.netif_list) { + psample_netif = (psample_netif_t*)list; + seq_printf(m, " %-14s %-14d %d\n", + psample_netif->dev->name, + psample_netif->port, + psample_netif->dev->ifindex); + } + + spin_unlock_irqrestore(&g_psample_info.lock, flags); + return 0; +} + +static int +psample_proc_map_open(struct inode * inode, struct file * file) +{ + return single_open(file, psample_proc_map_show, NULL); +} + +struct file_operations psample_proc_map_file_ops = { + owner: THIS_MODULE, + open: psample_proc_map_open, + read: seq_read, + llseek: seq_lseek, + write: NULL, + release: single_release, +}; + +/* + * psample debug Proc Read Entry + */ +static int +psample_proc_debug_show(struct seq_file *m, void *v) +{ + seq_printf(m, "BCM KNET %s Callback Config\n", PSAMPLE_CB_NAME); + seq_printf(m, " debug: 0x%x\n", debug); + seq_printf(m, " dcb_type: %d\n", g_psample_info.dcb_type); + seq_printf(m, " netif_count: %d\n", g_psample_info.netif_count); + seq_printf(m, " queue length: %d\n", psample_qlen); + + return 0; +} + +static int +psample_proc_debug_open(struct inode * inode, struct file * file) +{ + return single_open(file, psample_proc_debug_show, NULL); +} + +/* + * psample debug Proc Write Entry + * + * Syntax: + * debug= + * + * Where corresponds to the debug module parameter. + * + * Examples: + * debug=0x1 + */ +static ssize_t +psample_proc_debug_write(struct file *file, const char *buf, + size_t count, loff_t *loff) +{ + char debug_str[40]; + char *ptr; + + if (count > sizeof(debug_str)) { + count = sizeof(debug_str) - 1; + debug_str[count] = '\0'; + } + if (copy_from_user(debug_str, buf, count)) { + return -EFAULT; + } + + if ((ptr = strstr(debug_str, "debug=")) != NULL) { + ptr += 6; + debug = simple_strtol(ptr, NULL, 0); + } else { + printk("Warning: unknown configuration setting\n"); + } + + return count; +} + +struct file_operations psample_proc_debug_file_ops = { + owner: THIS_MODULE, + open: psample_proc_debug_open, + read: seq_read, + llseek: seq_lseek, + write: psample_proc_debug_write, + release: single_release, +}; + +static int +psample_proc_stats_show(struct seq_file *m, void *v) +{ + seq_printf(m, "BCM KNET %s Callback Stats\n", PSAMPLE_CB_NAME); + seq_printf(m, " DCB type %d\n", g_psample_info.dcb_type); + seq_printf(m, " pkts filter psample cb %10lu\n", g_psample_stats.pkts_f_psample_cb); + seq_printf(m, " pkts sent to psample module %10lu\n", g_psample_stats.pkts_f_psample_mod); + seq_printf(m, " pkts handled by psample %10lu\n", g_psample_stats.pkts_f_handled); + seq_printf(m, " pkts pass through %10lu\n", g_psample_stats.pkts_f_pass_through); + seq_printf(m, " pkts with mc destination %10lu\n", g_psample_stats.pkts_f_dst_mc); + seq_printf(m, " pkts current queue length %10lu\n", g_psample_stats.pkts_c_qlen_cur); + seq_printf(m, " pkts high queue length %10lu\n", g_psample_stats.pkts_c_qlen_hi); + seq_printf(m, " pkts drop max queue length %10lu\n", g_psample_stats.pkts_d_qlen_max); + seq_printf(m, " pkts drop no memory %10lu\n", g_psample_stats.pkts_d_no_mem); + seq_printf(m, " pkts drop no psample group %10lu\n", g_psample_stats.pkts_d_no_group); + seq_printf(m, " pkts drop sampling disabled %10lu\n", g_psample_stats.pkts_d_sampling_disabled); + seq_printf(m, " pkts drop psample not ready %10lu\n", g_psample_stats.pkts_d_not_ready); + seq_printf(m, " pkts drop metadata parse error %10lu\n", g_psample_stats.pkts_d_metadata); + seq_printf(m, " pkts drop skb error %10lu\n", g_psample_stats.pkts_d_skb); + seq_printf(m, " pkts drop skb cbd error %10lu\n", g_psample_stats.pkts_d_skb_cbd); + seq_printf(m, " pkts with invalid src port %10lu\n", g_psample_stats.pkts_d_meta_srcport); + seq_printf(m, " pkts with invalid dst port %10lu\n", g_psample_stats.pkts_d_meta_dstport); + seq_printf(m, " pkts with invalid orig pkt sz %10lu\n", g_psample_stats.pkts_d_invalid_size); + return 0; +} + +static int +psample_proc_stats_open(struct inode * inode, struct file * file) +{ + return single_open(file, psample_proc_stats_show, NULL); +} + +/* + * psample stats Proc Write Entry + * + * Syntax: + * write any value to clear stats + */ +static ssize_t +psample_proc_stats_write(struct file *file, const char *buf, + size_t count, loff_t *loff) +{ + int qlen_cur = 0; + unsigned long flags; + + spin_lock_irqsave(&g_psample_work.lock, flags); + qlen_cur = g_psample_stats.pkts_c_qlen_cur; + memset(&g_psample_stats, 0, sizeof(psample_stats_t)); + g_psample_stats.pkts_c_qlen_cur = qlen_cur; + spin_unlock_irqrestore(&g_psample_work.lock, flags); + + return count; +} +struct file_operations psample_proc_stats_file_ops = { + owner: THIS_MODULE, + open: psample_proc_stats_open, + read: seq_read, + llseek: seq_lseek, + write: psample_proc_stats_write, + release: single_release, +}; + +int psample_cleanup(void) +{ + cancel_work_sync(&g_psample_work.wq); + remove_proc_entry("stats", psample_proc_root); + remove_proc_entry("rate", psample_proc_root); + remove_proc_entry("size", psample_proc_root); + remove_proc_entry("debug", psample_proc_root); + remove_proc_entry("map" , psample_proc_root); + remove_proc_entry("psample", knet_cb_proc_root); + remove_proc_entry("bcm/knet-cb", NULL); + remove_proc_entry("bcm", NULL); + return 0; +} + +int psample_init(void) +{ + #define PROCFS_MAX_PATH 1024 + char psample_procfs_path[PROCFS_MAX_PATH]; + struct proc_dir_entry *entry; + + /* initialize proc files (for ngknet) */ + proc_mkdir("bcm", NULL); + + /* create procfs for psample */ + snprintf(psample_procfs_path, PROCFS_MAX_PATH, "bcm/knet-cb"); + knet_cb_proc_root = proc_mkdir(psample_procfs_path, NULL); + snprintf(psample_procfs_path, PROCFS_MAX_PATH, "%s/%s", psample_procfs_path, PSAMPLE_CB_NAME); + psample_proc_root = proc_mkdir(psample_procfs_path, NULL); + + /* create procfs for psample stats */ + PROC_CREATE(entry, "stats", 0666, psample_proc_root, &psample_proc_stats_file_ops); + if (entry == NULL) { + printk("%s: Unable to create procfs entry '/procfs/%s/stats'\n", __func__, psample_procfs_path); + return -1; + } + + /* create procfs for setting sample rates */ + PROC_CREATE(entry, "rate", 0666, psample_proc_root, &psample_proc_rate_file_ops); + if (entry == NULL) { + printk("%s: Unable to create procfs entry '/procfs/%s/rate'\n", __func__, psample_procfs_path); + return -1; + } + + /* create procfs for setting sample size */ + PROC_CREATE(entry, "size", 0666, psample_proc_root, &psample_proc_size_file_ops); + if (entry == NULL) { + printk("%s: Unable to create procfs entry '/procfs/%s/size'\n", __func__, psample_procfs_path); + return -1; + } + + /* create procfs for getting netdev mapping */ + PROC_CREATE(entry, "map", 0666, psample_proc_root, &psample_proc_map_file_ops); + if (entry == NULL) { + printk("%s: Unable to create procfs entry '/procfs/%s/map'\n", __func__, psample_procfs_path); + return -1; + } + + /* create procfs for debug log */ + PROC_CREATE(entry, "debug", 0666, psample_proc_root, &psample_proc_debug_file_ops); + if (entry == NULL) { + printk("%s: Unable to create procfs entry '/procfs/%s/debug'\n", __func__, psample_procfs_path); + return -1; + } + + /* clear data structs */ + memset(&g_psample_stats, 0, sizeof(psample_stats_t)); + memset(&g_psample_info, 0, sizeof(psample_info_t)); + memset(&g_psample_work, 0, sizeof(psample_work_t)); + + /* FIXME: How to get DCB type from NGKNET? */ + //g_psample_info.dcb_type + + /* setup psample_info struct */ + INIT_LIST_HEAD(&g_psample_info.netif_list); + spin_lock_init(&g_psample_info.lock); + + /* setup psample work queue */ + spin_lock_init(&g_psample_work.lock); + INIT_LIST_HEAD(&g_psample_work.pkt_list); + INIT_WORK(&g_psample_work.wq, psample_task); + + /* get net namespace */ + g_psample_info.netns = get_net_ns_by_pid(current->pid); + if (!g_psample_info.netns) { + printk("%s: Could not get network namespace for pid %d\n", __func__, current->pid); + return (-1); + } + PSAMPLE_CB_DBG_PRINT("%s: current->pid %d, netns 0x%p, sample_size %d\n", __func__, + current->pid, g_psample_info.netns, psample_size); + + + return 0; +} diff --git a/platform/broadcom/saibcm-modules/sdklt/linux/knetcb/psample-cb.h b/platform/broadcom/saibcm-modules/sdklt/linux/knetcb/psample-cb.h new file mode 100644 index 00000000000..2e3342ead5c --- /dev/null +++ b/platform/broadcom/saibcm-modules/sdklt/linux/knetcb/psample-cb.h @@ -0,0 +1,57 @@ +/* + * Copyright 2017 Broadcom + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License, version 2, as + * published by the Free Software Foundation (the "GPL"). + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License version 2 (GPLv2) for more details. + * + * You should have received a copy of the GNU General Public License + * version 2 (GPLv2) along with this source code. + */ +/* + * $Id: psample_cb.h $ + * $Copyright: (c) 2019 Broadcom Corp. + * All Rights Reserved.$ + */ +#ifndef __PSAMPLE_CB_H__ +#define __PSAMPLE_CB_H__ + +#include +#include + +//#define PSAMPLE_SUPPORT 1 // TODO: MLI@BRCM - Add this as part of conditional in Makefile +#define PSAMPLE_CB_NAME "psample" + +extern int +psample_init(void); + +extern int +psample_cleanup(void); + +extern struct sk_buff* +psample_rx_cb(struct sk_buff *skb); + +/* psample data per interface */ +typedef struct { + struct list_head list; + struct net_device *dev; + uint16_t id; + uint8_t port; + uint16_t vlan; + uint16_t qnum; + uint32_t sample_rate; + uint32_t sample_size; +} psample_netif_t; + +extern int +psample_netif_create_cb(struct net_device *dev); + +extern int +psample_netif_destroy_cb(struct net_device *dev); + +#endif /* __PSAMPLE_CB_H__ */ diff --git a/platform/broadcom/saibcm-modules/sdklt/linux/psample/Kbuild b/platform/broadcom/saibcm-modules/sdklt/linux/psample/Kbuild new file mode 100644 index 00000000000..0049e399076 --- /dev/null +++ b/platform/broadcom/saibcm-modules/sdklt/linux/psample/Kbuild @@ -0,0 +1,18 @@ +# -*- Kbuild -*- +# +# Linux psample module. +# +# $Copyright: (c) 2020 Broadcom. +# Broadcom Proprietary and Confidential. All rights reserved.$ +# + +obj-m := linux_psample.o + +ccflags-y := $(LKM_CFLAGS) \ + -I$(SDK)/shr/include \ + -I$(SDK)/bcmdrd/include \ + -I$(SDK)/linux/include \ + -I$(SDK)/linux/knet/include \ + -I$(SDK)/linux/knet + +linux_psample-y := psample.o diff --git a/platform/broadcom/saibcm-modules/sdklt/linux/psample/Makefile b/platform/broadcom/saibcm-modules/sdklt/linux/psample/Makefile new file mode 100644 index 00000000000..b37b8ebb1c2 --- /dev/null +++ b/platform/broadcom/saibcm-modules/sdklt/linux/psample/Makefile @@ -0,0 +1,21 @@ +# -*- Makefile -*- +# +# Linux psample module. +# +# $Copyright: (c) 2020 Broadcom. +# Broadcom Proprietary and Confidential. All rights reserved.$ +# + +include Kbuild + +ifeq ($(KERNELRELEASE),) + +MOD_NAME = linux_psample + +include $(SDK)/make/lkm.mk + +endif + +.PHONY: distclean + +distclean: diff --git a/platform/broadcom/saibcm-modules/sdklt/linux/psample/psample.c b/platform/broadcom/saibcm-modules/sdklt/linux/psample/psample.c new file mode 100644 index 00000000000..f0c9beab578 --- /dev/null +++ b/platform/broadcom/saibcm-modules/sdklt/linux/psample/psample.c @@ -0,0 +1,302 @@ +/* + * net/psample/psample.c - Netlink channel for packet sampling + * Copyright (c) 2017 Yotam Gigi + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define PSAMPLE_MAX_PACKET_SIZE 0xffff + +static LIST_HEAD(psample_groups_list); +static DEFINE_SPINLOCK(psample_groups_lock); + +/* multicast groups */ +enum psample_nl_multicast_groups { + PSAMPLE_NL_MCGRP_CONFIG, + PSAMPLE_NL_MCGRP_SAMPLE, +}; + +static const struct genl_multicast_group psample_nl_mcgrps[] = { + [PSAMPLE_NL_MCGRP_CONFIG] = { .name = PSAMPLE_NL_MCGRP_CONFIG_NAME }, + [PSAMPLE_NL_MCGRP_SAMPLE] = { .name = PSAMPLE_NL_MCGRP_SAMPLE_NAME }, +}; + +static struct genl_family psample_nl_family; + +static int psample_group_nl_fill(struct sk_buff *msg, + struct psample_group *group, + enum psample_command cmd, u32 portid, u32 seq, + int flags) +{ + void *hdr; + int ret; + + hdr = genlmsg_put(msg, portid, seq, &psample_nl_family, flags, cmd); + if (!hdr) + return -EMSGSIZE; + + ret = nla_put_u32(msg, PSAMPLE_ATTR_SAMPLE_GROUP, group->group_num); + if (ret < 0) + goto error; + + ret = nla_put_u32(msg, PSAMPLE_ATTR_GROUP_REFCOUNT, group->refcount); + if (ret < 0) + goto error; + + ret = nla_put_u32(msg, PSAMPLE_ATTR_GROUP_SEQ, group->seq); + if (ret < 0) + goto error; + + genlmsg_end(msg, hdr); + return 0; + +error: + genlmsg_cancel(msg, hdr); + return -EMSGSIZE; +} + +static int psample_nl_cmd_get_group_dumpit(struct sk_buff *msg, + struct netlink_callback *cb) +{ + struct psample_group *group; + int start = cb->args[0]; + int idx = 0; + int err; + + spin_lock(&psample_groups_lock); + list_for_each_entry(group, &psample_groups_list, list) { + if (!net_eq(group->net, sock_net(msg->sk))) + continue; + if (idx < start) { + idx++; + continue; + } + err = psample_group_nl_fill(msg, group, PSAMPLE_CMD_NEW_GROUP, + NETLINK_CB(cb->skb).portid, + cb->nlh->nlmsg_seq, NLM_F_MULTI); + if (err) + break; + idx++; + } + + spin_unlock(&psample_groups_lock); + cb->args[0] = idx; + return msg->len; +} + +static const struct genl_ops psample_nl_ops[] = { + { + .cmd = PSAMPLE_CMD_GET_GROUP, + .dumpit = psample_nl_cmd_get_group_dumpit, + /* can be retrieved by unprivileged users */ + } +}; + +static struct genl_family psample_nl_family = { + .name = PSAMPLE_GENL_NAME, + .version = PSAMPLE_GENL_VERSION, + .maxattr = PSAMPLE_ATTR_MAX, + .netnsok = true, + .module = THIS_MODULE, + .mcgrps = psample_nl_mcgrps, + .ops = psample_nl_ops, + .n_ops = ARRAY_SIZE(psample_nl_ops), + .n_mcgrps = ARRAY_SIZE(psample_nl_mcgrps), +}; + +static void psample_group_notify(struct psample_group *group, + enum psample_command cmd) +{ + struct sk_buff *msg; + int err; + + msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_ATOMIC); + if (!msg) + return; + + err = psample_group_nl_fill(msg, group, cmd, 0, 0, NLM_F_MULTI); + if (!err) + genlmsg_multicast_netns(&psample_nl_family, group->net, msg, 0, + PSAMPLE_NL_MCGRP_CONFIG, GFP_ATOMIC); + else + nlmsg_free(msg); +} + +static struct psample_group *psample_group_create(struct net *net, + u32 group_num) +{ + struct psample_group *group; + + group = kzalloc(sizeof(*group), GFP_ATOMIC); + if (!group) + return NULL; + + group->net = net; + group->group_num = group_num; + list_add_tail(&group->list, &psample_groups_list); + + psample_group_notify(group, PSAMPLE_CMD_NEW_GROUP); + return group; +} + +static void psample_group_destroy(struct psample_group *group) +{ + psample_group_notify(group, PSAMPLE_CMD_DEL_GROUP); + list_del(&group->list); + kfree(group); +} + +static struct psample_group * +psample_group_lookup(struct net *net, u32 group_num) +{ + struct psample_group *group; + + list_for_each_entry(group, &psample_groups_list, list) + if ((group->group_num == group_num) && (group->net == net)) + return group; + return NULL; +} + +struct psample_group *psample_group_get(struct net *net, u32 group_num) +{ + struct psample_group *group; + + spin_lock(&psample_groups_lock); + + group = psample_group_lookup(net, group_num); + if (!group) { + group = psample_group_create(net, group_num); + if (!group) + goto out; + } + group->refcount++; + +out: + spin_unlock(&psample_groups_lock); + return group; +} +EXPORT_SYMBOL_GPL(psample_group_get); + +void psample_group_put(struct psample_group *group) +{ + spin_lock(&psample_groups_lock); + + if (--group->refcount == 0) + psample_group_destroy(group); + + spin_unlock(&psample_groups_lock); +} +EXPORT_SYMBOL_GPL(psample_group_put); + +void psample_sample_packet(struct psample_group *group, struct sk_buff *skb, + u32 trunc_size, int in_ifindex, int out_ifindex, + u32 sample_rate) +{ + struct sk_buff *nl_skb; + int data_len; + int meta_len; + void *data; + int ret; + + meta_len = (in_ifindex ? nla_total_size(sizeof(u16)) : 0) + + (out_ifindex ? nla_total_size(sizeof(u16)) : 0) + + nla_total_size(sizeof(u32)) + /* sample_rate */ + nla_total_size(sizeof(u32)) + /* orig_size */ + nla_total_size(sizeof(u32)) + /* group_num */ + nla_total_size(sizeof(u32)); /* seq */ + + data_len = min(skb->len, trunc_size); + if (meta_len + nla_total_size(data_len) > PSAMPLE_MAX_PACKET_SIZE) + data_len = PSAMPLE_MAX_PACKET_SIZE - meta_len - NLA_HDRLEN + - NLA_ALIGNTO; + + nl_skb = genlmsg_new(meta_len + nla_total_size(data_len), GFP_ATOMIC); + if (unlikely(!nl_skb)) + return; + + data = genlmsg_put(nl_skb, 0, 0, &psample_nl_family, 0, + PSAMPLE_CMD_SAMPLE); + if (unlikely(!data)) + goto error; + + if (in_ifindex) { + ret = nla_put_u16(nl_skb, PSAMPLE_ATTR_IIFINDEX, in_ifindex); + if (unlikely(ret < 0)) + goto error; + } + + if (out_ifindex) { + ret = nla_put_u16(nl_skb, PSAMPLE_ATTR_OIFINDEX, out_ifindex); + if (unlikely(ret < 0)) + goto error; + } + + ret = nla_put_u32(nl_skb, PSAMPLE_ATTR_SAMPLE_RATE, sample_rate); + if (unlikely(ret < 0)) + goto error; + + ret = nla_put_u32(nl_skb, PSAMPLE_ATTR_ORIGSIZE, skb->len); + if (unlikely(ret < 0)) + goto error; + + ret = nla_put_u32(nl_skb, PSAMPLE_ATTR_SAMPLE_GROUP, group->group_num); + if (unlikely(ret < 0)) + goto error; + + ret = nla_put_u32(nl_skb, PSAMPLE_ATTR_GROUP_SEQ, group->seq++); + if (unlikely(ret < 0)) + goto error; + + if (data_len) { + int nla_len = nla_total_size(data_len); + struct nlattr *nla; + + nla = (struct nlattr *)skb_put(nl_skb, nla_len); + nla->nla_type = PSAMPLE_ATTR_DATA; + nla->nla_len = nla_attr_size(data_len); + + if (skb_copy_bits(skb, 0, nla_data(nla), data_len)) + goto error; + } + + genlmsg_end(nl_skb, data); + genlmsg_multicast_netns(&psample_nl_family, group->net, nl_skb, 0, + PSAMPLE_NL_MCGRP_SAMPLE, GFP_ATOMIC); + + return; +error: + pr_err_ratelimited("Could not create psample log message\n"); + nlmsg_free(nl_skb); +} +EXPORT_SYMBOL_GPL(psample_sample_packet); + +static int __init psample_module_init(void) +{ + return genl_register_family(&psample_nl_family); +} + +static void __exit psample_module_exit(void) +{ + genl_unregister_family(&psample_nl_family); +} + +module_init(psample_module_init); +module_exit(psample_module_exit); + +MODULE_AUTHOR("Yotam Gigi "); +MODULE_DESCRIPTION("netlink channel for packet sampling"); +MODULE_LICENSE("GPL v2"); diff --git a/platform/broadcom/saibcm-modules/sdklt/make/lkm.mk b/platform/broadcom/saibcm-modules/sdklt/make/lkm.mk new file mode 100644 index 00000000000..c3d2a4d40b5 --- /dev/null +++ b/platform/broadcom/saibcm-modules/sdklt/make/lkm.mk @@ -0,0 +1,76 @@ +# +# $Copyright: Copyright 2018-2020 Broadcom. All rights reserved. +# The term 'Broadcom' refers to Broadcom Inc. and/or its subsidiaries. +# +# This program is free software; you can redistribute it and/or +# modify it under the terms of the GNU General Public License +# version 2 as published by the Free Software Foundation. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# A copy of the GNU General Public License version 2 (GPLv2) can +# be found in the LICENSES folder.$ +# +# Shared makefile include for building Linux kernel modules. +# + +# KDIR must point to the Linux kernel sources +ifndef KDIR +nokdir:; @echo 'The $$KDIR variable is not set'; exit 1 +endif + +# Required for older kernels +export EXTRA_CFLAGS = $(ccflags-y) + +PWD := $(shell pwd) + +ifneq ($(LKM_BLDDIR),) +# +# If a build directory has been specified, then we symlink all sources +# to this directory and redirect the module build path. +# +# Note that the KBUILD_OUTPUT variable cannot be used to redirect the +# output as we want it. +# +MDIR = $(LKM_BLDDIR) +MSRCS = $(patsubst %.o,%.c,$($(MOD_NAME)-y)) +MSRCS += Makefile Kbuild +BSRCS = $(addprefix $(PWD)/,$(MSRCS)) +else +# +# Build in current directory by default. +# +MDIR = $(PWD) +endif + +all: + $(Q)echo Building kernel module $(MOD_NAME) +ifneq ($(LKM_BLDDIR),) +ifneq ($(LKM_BLDDIR),$(PWD)) + $(Q)mkdir -p $(MDIR) + (cd $(MDIR); \ + rm -rf *.c Makefile Kbuild; \ + for f in $(BSRCS); do \ + ln -s $$f; \ + done) +endif +endif + $(MAKE) -C $(KDIR) M=$(MDIR) + +clean:: + $(Q)echo Cleaning kernel module $(MOD_NAME) + $(MAKE) -C $(KDIR) M=$(MDIR) clean +ifneq ($(LKM_BLDDIR),) +ifneq ($(LKM_BLDDIR),$(PWD)) +# Remove all files except for Makefile (needed by 'make clean') + rm -f $(LKM_BLDDIR)/*[cdors] +endif +endif + +.PHONY: all clean + +# Standard documentation targets +-include $(SDK)/make/doc.mk diff --git a/platform/broadcom/saibcm-modules/sdklt/shr/include/shr/shr_error.h b/platform/broadcom/saibcm-modules/sdklt/shr/include/shr/shr_error.h new file mode 100644 index 00000000000..1924d600de5 --- /dev/null +++ b/platform/broadcom/saibcm-modules/sdklt/shr/include/shr/shr_error.h @@ -0,0 +1,195 @@ +/*! \file shr_error.h + * + * Shared error codes. + * + */ +/* + * $Copyright: Copyright 2018-2020 Broadcom. All rights reserved. + * The term 'Broadcom' refers to Broadcom Inc. and/or its subsidiaries. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * version 2 as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * A copy of the GNU General Public License version 2 (GPLv2) can + * be found in the LICENSES folder.$ + */ + +#ifndef SHR_ERROR_H +#define SHR_ERROR_H + +/*! + * \brief Standard SDK error codes. + * + * IMPORTANT: These error codes must match the corresponding text + * messages in shr_error.c. + */ +typedef enum { + + /*! + * The operation completed successfully. + */ + SHR_E_NONE = 0, + + /*! + * This usually indicates that software encountered an internal + * data inconsistency or an unanticipated hardware state. + */ + SHR_E_INTERNAL = -1, + + /*! + * An operation failed due to insufficient dynamically allocated + * memory. + */ + SHR_E_MEMORY = -2, + + /*! + * The first argument of many API routines is a unit number. This + * error occurs if that number refers to a non-existent unit. + */ + SHR_E_UNIT = -3, + + /*! + * A parameter to an API routine was invalid. A null pointer value + * may have been passed to the routine, or an integer parameter + * may be outside of its allowed range. + */ + SHR_E_PARAM = -4, + + /*! + * The operation encountered a pooled resource (e.g. a table or a + * list) with no valid elements. + */ + SHR_E_EMPTY = -5, + + /*! + * The operation encountered a pooled resource (e.g. a table or a + * list) with no room for new elements. + */ + SHR_E_FULL = -6, + + /*! + * The specified entry in a pooled resource (e.g. a table or a + * list) could not be found. + */ + SHR_E_NOT_FOUND = -7, + + /*! + * The specified entry of a pooled resource (e.g. a table or a + * list) already exists. + */ + SHR_E_EXISTS = -8, + + /*! + * The operation did not complete within the maximum allowed time frame. + */ + SHR_E_TIMEOUT = -9, + + /*! + * An operation was attempted before the previous operation had + * completed. + */ + SHR_E_BUSY = -10, + + /*! + * An operation could not be completed. This may be due to a + * hardware or configuration problem. + */ + SHR_E_FAIL = -11, + + /*! + * The operation could not be completed because a required feature + * was disabled. + */ + SHR_E_DISABLED = -12, + + /*! + * The specified identifier was not valid. Note that this error + * code will normally take precedence over \ref SHR_E_PARAM. + */ + SHR_E_BADID = -13, + + /*! + * The operation could not be completed due to lack of hardware + * resources. + */ + SHR_E_RESOURCE = -14, + + /*! + * The operation could not be completed due to incomplete or + * incorrect configuration. + */ + SHR_E_CONFIG = -15, + + /*! + * The hardware does not support the requested operation. + */ + SHR_E_UNAVAIL = -16, + + /*! + * An operation was attempted before initialization was complete. + */ + SHR_E_INIT = -17, + + /*! + * The specified port value was not valid. Note that this error + * code will normally take precedence over \ref SHR_E_PARAM. + */ + SHR_E_PORT = -18, + + /*! + * A low-level register or memory access failed. + */ + SHR_E_IO = -19, + + /*! + * Access method not permitted. Typically returned if attempting + * to write to a read-only object. + */ + SHR_E_ACCESS = -20, + + /*! + * No handler exists to perform the hardware access associated + * with a an operation on a software object. + */ + SHR_E_NO_HANDLER = -21, + + /*! + * The operation was only partially completed, and this could + * potentially leave the system in an unexpected state. + */ + SHR_E_PARTIAL = -22, + + /*! + * The operation failed because of a hash collision. + */ + SHR_E_COLL = -23, + + SHR_E_LIMIT = -24 /* Must come last */ + +} shr_error_t; + +/*! Check for successful return value. */ +#define SHR_SUCCESS(_expr) ((_expr) >= 0) + +/*! Check for error return value. */ +#define SHR_FAILURE(_expr) ((_expr) < 0) + +/*! + * \brief Get standard error message + * + * Returns a text message corresponding to the error code passed in. + * + * \param [in] rv Error code + * + * \return Pointer to error message + */ +extern const char * +shr_errmsg(int rv); + +#endif /* SHR_ERROR_H */ diff --git a/platform/broadcom/saibcm-modules/systems/bde/linux/include/linux-bde.h b/platform/broadcom/saibcm-modules/systems/bde/linux/include/linux-bde.h index bdf7a56dcab..c4d31579bfd 100644 --- a/platform/broadcom/saibcm-modules/systems/bde/linux/include/linux-bde.h +++ b/platform/broadcom/saibcm-modules/systems/bde/linux/include/linux-bde.h @@ -1,5 +1,10 @@ /* - * Copyright 2017 Broadcom + * Copyright 2007-2020 Broadcom Inc. All rights reserved. + * + * Permission is granted to use, copy, modify and/or distribute this + * software under either one of the licenses below. + * + * License Option 1: GPL * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License, version 2, as @@ -12,6 +17,12 @@ * * You should have received a copy of the GNU General Public License * version 2 (GPLv2) along with this source code. + * + * + * License Option 2: Broadcom Open Network Switch APIs (OpenNSA) license + * + * This software is governed by the Broadcom Open Network Switch APIs license: + * https://www.broadcom.com/products/ethernet-connectivity/software/opennsa */ /*********************************************************************** * @@ -58,7 +69,6 @@ #define __LINUX_BDE_H__ #include - #include @@ -104,12 +114,17 @@ /* Max devices */ /* 16 switch chips + 2 out-of-band Ethernet + 2 CPUs */ +#ifndef LINUX_BDE_MAX_SWITCH_DEVICES #define LINUX_BDE_MAX_SWITCH_DEVICES 16 +#endif #define LINUX_BDE_MAX_ETHER_DEVICES 2 #define LINUX_BDE_MAX_CPU_DEVICES 2 #define LINUX_BDE_MAX_DEVICES (LINUX_BDE_MAX_SWITCH_DEVICES + \ LINUX_BDE_MAX_ETHER_DEVICES + \ - LINUX_BDE_MAX_CPU_DEVICES) + LINUX_BDE_MAX_CPU_DEVICES) +#define LINUX_BDE_NOF_DEVICE_BITMAP_WORDS ((LINUX_BDE_MAX_DEVICES+31)/32) +#define LINUX_BDE_MAX_IPROC_UC_CORES 12 /* Maximum number of R5 cores per device */ +typedef uint32 linux_bde_device_bitmap_t[LINUX_BDE_NOF_DEVICE_BITMAP_WORDS]; /* * PCI devices will be initialized by the Linux Kernel, @@ -148,14 +163,24 @@ typedef struct linux_bde_bus_s { */ #define BDE_DEV_STATE_CHANGED (2) +/* + * BDE_DEV_INST_ID_INVALID : The invalid instance identifier. + */ +#define BDE_DEV_INST_ID_INVALID ((uint32)-1) + extern int linux_bde_create(linux_bde_bus_t* bus, ibde_t** bde); extern int linux_bde_destroy(ibde_t* bde); #ifdef BCM_INSTANCE_SUPPORT extern int linux_bde_instance_attach(unsigned int dev_mask,unsigned int dma_size); +extern int linux_bde_instance_config(linux_bde_device_bitmap_t dev_mask,unsigned int dma_size); #endif #ifdef __KERNEL__ +#ifdef INCLUDE_EDK +#define BDE_EDK_SUPPORT +#endif + /* * Backdoors provided by the kernel bde * @@ -171,6 +196,10 @@ extern int linux_bde_instance_attach(unsigned int dev_mask,unsigned int dma_size extern int lkbde_get_dma_info(phys_addr_t *cpu_pbase, phys_addr_t *dma_pbase, ssize_t *size); extern uint32 lkbde_get_dev_phys(int d); extern uint32 lkbde_get_dev_phys_hi(int d); +#ifdef BDE_EDK_SUPPORT +extern int lkbde_edk_get_dma_info(int dev_id, phys_addr_t* cpu_pbase, + phys_addr_t* dma_pbase, ssize_t* size); +#endif /* * Virtual device address needed by kernel space @@ -183,8 +212,8 @@ extern void *lkbde_get_dev_virt(int d); * the userland code to mmap. The following functions * supports multiple resources for a single device. */ -extern int lkbde_get_dev_resource(int d, int rsrc, uint32 *flags, - uint32 *phys_lo, uint32 *phys_hi); +extern int lkbde_get_dev_resource(int d, int rsrc, uint32_t *phys_lo, + uint32_t *phys_hi, uint32_t *size); /* * Backdoor to retrieve OS device structure to be used for @@ -215,6 +244,19 @@ extern int lkbde_dev_state_set(int d, uint32 state); extern int lkbde_dev_instid_get(int d, uint32 *instid); extern int lkbde_dev_instid_set(int d, uint32 instid); + +/* + * Return none-zero if the SDK instance with the given instance ID + * manages the given device. + */ +extern int lkbde_is_dev_managed_by_instance(uint32 dev, uint32 inst_id); + +/* + * Return a pointer to the bitmap of the SDK instance managed devices. + */ +extern linux_bde_device_bitmap_t* lkbde_get_inst_devs(uint32 inst_id); + + /* * Functions that allow an interrupt handler in user mode to * coexist with interrupt handler in kernel module. @@ -256,13 +298,6 @@ extern int lkbde_cpu_pci_register(int d); #endif #endif -/* Don't use _SIMPLE_MEMORY_ALLOCATION_ method for newer kernel than 3.10.0 */ -#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,10,0)) -#ifndef _SIMPLE_MEMORY_ALLOCATION_ -#define _SIMPLE_MEMORY_ALLOCATION_ 0 -#endif -#endif - /* Allocation via dma_alloc_coherent is turned off by default */ #ifndef _SIMPLE_MEMORY_ALLOCATION_ #define _SIMPLE_MEMORY_ALLOCATION_ 9 /* compile in the allocation method, but do not use it by default */ diff --git a/platform/broadcom/saibcm-modules/systems/bde/linux/include/linux_dma.h b/platform/broadcom/saibcm-modules/systems/bde/linux/include/linux_dma.h index 3bf7488abce..23eb3fa33e9 100644 --- a/platform/broadcom/saibcm-modules/systems/bde/linux/include/linux_dma.h +++ b/platform/broadcom/saibcm-modules/systems/bde/linux/include/linux_dma.h @@ -1,5 +1,10 @@ /* - * Copyright 2017 Broadcom + * Copyright 2007-2020 Broadcom Inc. All rights reserved. + * + * Permission is granted to use, copy, modify and/or distribute this + * software under either one of the licenses below. + * + * License Option 1: GPL * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License, version 2, as @@ -12,6 +17,12 @@ * * You should have received a copy of the GNU General Public License * version 2 (GPLv2) along with this source code. + * + * + * License Option 2: Broadcom Open Network Switch APIs (OpenNSA) license + * + * This software is governed by the Broadcom Open Network Switch APIs license: + * https://www.broadcom.com/products/ethernet-connectivity/software/opennsa */ /*********************************************************************** * @@ -60,7 +71,7 @@ extern void _dma_init(int dev_index); extern int _dma_cleanup(void); -extern void _dma_pprint(void); +extern void _dma_pprint(struct seq_file *m); extern uint32_t *_salloc(int d, int size, const char *name); extern void _sfree(int d, void *ptr); extern int _sinval(int d, void *ptr, int length); diff --git a/platform/broadcom/saibcm-modules/systems/bde/linux/include/mpool.h b/platform/broadcom/saibcm-modules/systems/bde/linux/include/mpool.h index be4d436f8da..15d496ff623 100644 --- a/platform/broadcom/saibcm-modules/systems/bde/linux/include/mpool.h +++ b/platform/broadcom/saibcm-modules/systems/bde/linux/include/mpool.h @@ -1,5 +1,10 @@ /* - * Copyright 2017 Broadcom + * Copyright 2007-2020 Broadcom Inc. All rights reserved. + * + * Permission is granted to use, copy, modify and/or distribute this + * software under either one of the licenses below. + * + * License Option 1: GPL * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License, version 2, as @@ -12,6 +17,12 @@ * * You should have received a copy of the GNU General Public License * version 2 (GPLv2) along with this source code. + * + * + * License Option 2: Broadcom Open Network Switch APIs (OpenNSA) license + * + * This software is governed by the Broadcom Open Network Switch APIs license: + * https://www.broadcom.com/products/ethernet-connectivity/software/opennsa */ /* * $Id: mpool.h,v 1.2 Broadcom SDK $ diff --git a/platform/broadcom/saibcm-modules/systems/bde/linux/kernel/Makefile b/platform/broadcom/saibcm-modules/systems/bde/linux/kernel/Makefile index cfd72d3a921..2aa3bec11d7 100644 --- a/platform/broadcom/saibcm-modules/systems/bde/linux/kernel/Makefile +++ b/platform/broadcom/saibcm-modules/systems/bde/linux/kernel/Makefile @@ -1,5 +1,10 @@ # -# Copyright 2017 Broadcom +# Copyright 2007-2020 Broadcom Inc. All rights reserved. +# +# Permission is granted to use, copy, modify and/or distribute this +# software under either one of the licenses below. +# +# License Option 1: GPL # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License, version 2, as @@ -12,6 +17,12 @@ # # You should have received a copy of the GNU General Public License # version 2 (GPLv2) along with this source code. +# +# +# License Option 2: Broadcom Open Network Switch APIs (OpenNSA) license +# +# This software is governed by the Broadcom Open Network Switch APIs license: +# https://www.broadcom.com/products/ethernet-connectivity/software/opennsa # # -*- Makefile -*- # $Id: Makefile,v 1.18 Broadcom SDK $ diff --git a/platform/broadcom/saibcm-modules/systems/bde/linux/kernel/linux-kernel-bde.c b/platform/broadcom/saibcm-modules/systems/bde/linux/kernel/linux-kernel-bde.c index 3a60ac4dd54..9029b3b5147 100644 --- a/platform/broadcom/saibcm-modules/systems/bde/linux/kernel/linux-kernel-bde.c +++ b/platform/broadcom/saibcm-modules/systems/bde/linux/kernel/linux-kernel-bde.c @@ -339,10 +339,19 @@ typedef struct bde_ctrl_s { uint32 dev_state; /* inst_id */ - uint32 inst_id; + uint32 inst_id; /* The instance ID of the instance controlling the device */ } bde_ctrl_t; static bde_ctrl_t _devices[LINUX_BDE_MAX_DEVICES]; + +/* information stored per SDK instance, curently the devices it manages */ +typedef struct { + linux_bde_device_bitmap_t devices; /* The devices controlled by this instance */ +} lkbde_inst_info_t; + +/* Information for each SDK instance (array index), the device that it manages */ +static lkbde_inst_info_t _instance_info[LINUX_BDE_MAX_DEVICES] = {{ .devices = {0}}}; + static int _ndevices = 0; static int _switch_ndevices = 0; static int _ether_ndevices = 0; @@ -810,6 +819,25 @@ iproc_cmicd_probe(struct platform_device *pldev) static int iproc_cmicd_remove(struct platform_device *pldev) { + int i; + uint32 mask = BDE_SWITCH_DEV_TYPE | BDE_AXI_DEV_TYPE; + bde_ctrl_t *ctrl; + + for (i = 0; i < _ndevices; i++) { + ctrl = _devices + i; + if ((ctrl->dev_type & mask) == mask) { + if (ctrl->bde_dev.base_address1) { + iounmap((void *)ctrl->bde_dev.base_address1); + ctrl->bde_dev.base_address1 = 0; + } + + if (ctrl->bde_dev.base_address) { + iounmap((void *)ctrl->bde_dev.base_address); + ctrl->bde_dev.base_address = 0; + } + } + } + return 0; } #ifdef CONFIG_OF @@ -1429,6 +1457,7 @@ static const struct pci_device_id _id_table[] = { { BROADCOM_VENDOR_ID, BCM53575_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, { BROADCOM_VENDOR_ID, BCM56070_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, { BROADCOM_VENDOR_ID, BCM56071_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM56072_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, { PCI_VENDOR_ID_PLX, PCI_DEVICE_ID_PLX_9656, PCI_ANY_ID, PCI_ANY_ID }, { PCI_VENDOR_ID_PLX, PCI_DEVICE_ID_PLX_9056, PCI_ANY_ID, PCI_ANY_ID }, { BCM53000_VENDOR_ID, BCM53000PCIE_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, @@ -1474,9 +1503,11 @@ static const struct pci_device_id _id_table[] = { { BROADCOM_VENDOR_ID, BCM88270_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM88271_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, { BROADCOM_VENDOR_ID, BCM88272_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, { BROADCOM_VENDOR_ID, BCM88273_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, { BROADCOM_VENDOR_ID, BCM88274_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM88276_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, { BROADCOM_VENDOR_ID, BCM88278_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, { BROADCOM_VENDOR_ID, BCM88279_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, @@ -1496,7 +1527,6 @@ static const struct pci_device_id _id_table[] = { { BROADCOM_VENDOR_ID, BCM88687_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, { BROADCOM_VENDOR_ID, BCM88380_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, { BROADCOM_VENDOR_ID, BCM88381_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, - { BROADCOM_VENDOR_ID, BCM88202_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, { BROADCOM_VENDOR_ID, BCM88360_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, { BROADCOM_VENDOR_ID, BCM88361_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, { BROADCOM_VENDOR_ID, BCM88363_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, @@ -1527,18 +1557,37 @@ static const struct pci_device_id _id_table[] = { { BROADCOM_VENDOR_ID, BCM8869E_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, { BROADCOM_VENDOR_ID, BCM8869F_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, { BROADCOM_VENDOR_ID, BCM88800_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, - { BROADCOM_VENDOR_ID, BCM88821_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, - { BROADCOM_VENDOR_ID, BCM88826_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM88801_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, { BROADCOM_VENDOR_ID, BCM88802_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, { BROADCOM_VENDOR_ID, BCM88803_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, { BROADCOM_VENDOR_ID, BCM88804_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, { BROADCOM_VENDOR_ID, BCM88805_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, { BROADCOM_VENDOR_ID, BCM88806_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM88807_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM88808_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM88809_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM8880A_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM8880B_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM8880C_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM8880D_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM8880E_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM8880F_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, { BROADCOM_VENDOR_ID, BCM88820_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM88821_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, { BROADCOM_VENDOR_ID, BCM88822_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, { BROADCOM_VENDOR_ID, BCM88823_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, { BROADCOM_VENDOR_ID, BCM88824_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, { BROADCOM_VENDOR_ID, BCM88825_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM88826_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM88827_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM88828_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM88829_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM8882A_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM8882B_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM8882C_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM8882D_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM8882E_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM8882F_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, { BROADCOM_VENDOR_ID, BCM88480_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, { BROADCOM_VENDOR_ID, BCM88481_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, { BROADCOM_VENDOR_ID, BCM88482_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, @@ -1555,12 +1604,40 @@ static const struct pci_device_id _id_table[] = { { BROADCOM_VENDOR_ID, BCM8848D_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, { BROADCOM_VENDOR_ID, BCM8848E_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, { BROADCOM_VENDOR_ID, BCM8848F_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM88280_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM88281_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM88282_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM88283_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM88284_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM88285_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM88286_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM88287_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM88288_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM88289_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM8828A_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM8828B_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM8828C_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM8828D_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM8828E_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM8828F_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, { BROADCOM_VENDOR_ID, BCM88850_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM88851_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM88852_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM88853_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM88854_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM88855_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM88856_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM88857_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM88858_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM88859_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM8885A_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM8885B_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM8885C_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM8885D_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM8885E_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM8885F_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, #endif /* BCM_DNX_SUPPORT */ #ifdef BCM_DFE_SUPPORT - { BROADCOM_VENDOR_ID, BCM88750_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, - { BROADCOM_VENDOR_ID, BCM88753_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, - { BROADCOM_VENDOR_ID, BCM88755_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, { BROADCOM_VENDOR_ID, BCM88770_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, { BROADCOM_VENDOR_ID, BCM88773_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, { BROADCOM_VENDOR_ID, BCM88774_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, @@ -1574,7 +1651,6 @@ static const struct pci_device_id _id_table[] = { { BROADCOM_VENDOR_ID, BCM88954_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, { BROADCOM_VENDOR_ID, BCM88955_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, { BROADCOM_VENDOR_ID, BCM88956_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, - { BROADCOM_VENDOR_ID, BCM88752_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, { BROADCOM_VENDOR_ID, BCM88772_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, { BROADCOM_VENDOR_ID, BCM88952_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, #endif @@ -1613,6 +1689,10 @@ static const struct pci_device_id _id_table[] = { { BROADCOM_VENDOR_ID, BCM56276_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, { BROADCOM_VENDOR_ID, BCM56277_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, { BROADCOM_VENDOR_ID, BCM56278_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM56279_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM56575_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM56175_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM56176_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, { BROADCOM_VENDOR_ID, BCM56370_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, { BROADCOM_VENDOR_ID, BCM56371_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, { BROADCOM_VENDOR_ID, BCM56372_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, @@ -1638,6 +1718,7 @@ static const struct pci_device_id _id_table[] = { { BROADCOM_VENDOR_ID, BCM56470_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, { BROADCOM_VENDOR_ID, BCM56471_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, { BROADCOM_VENDOR_ID, BCM56472_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, + { BROADCOM_VENDOR_ID, BCM56475_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID }, { 0, 0, 0, 0 } };; @@ -2540,9 +2621,6 @@ _pci_probe(struct pci_dev *dev, const struct pci_device_id *ent) #if defined(BCM_DFE_SUPPORT) switch (dev->device) { - case BCM88750_DEVICE_ID: - case BCM88753_DEVICE_ID: - case BCM88755_DEVICE_ID: case BCM88770_DEVICE_ID: case BCM88773_DEVICE_ID: case BCM88774_DEVICE_ID: @@ -2554,7 +2632,6 @@ _pci_probe(struct pci_dev *dev, const struct pci_device_id *ent) case BCM88954_DEVICE_ID: case BCM88955_DEVICE_ID: case BCM88956_DEVICE_ID: - case BCM88752_DEVICE_ID: case BCM88772_DEVICE_ID: case BCM88952_DEVICE_ID: @@ -2801,9 +2878,10 @@ _pci_remove(struct pci_dev* dev) } static struct pci_driver _device_driver = { - probe: _pci_probe, - remove: _pci_remove, - id_table: _id_table, + .name = LINUX_KERNEL_BDE_NAME, + .probe = _pci_probe, + .remove = _pci_remove, + .id_table = _id_table, /* The rest are dynamic */ }; @@ -2978,7 +3056,13 @@ probe_plx_local_bus(void) static int _init(void) { + unsigned i; #ifdef IPROC_CMICD + /* + * Adjust the PCI driver name to prevent our device file from + * getting removed when the module is unloaded. + */ + _device_driver.name = LINUX_KERNEL_BDE_NAME ".iproc"; #ifdef CONFIG_OF if (of_find_compatible_node(NULL, NULL, IPROC_CMICX_COMPATIBLE)) { iproc_platform_driver_register(&iproc_cmicd_driver); @@ -3000,9 +3084,6 @@ _init(void) #ifdef BCM_ICS _ics_bde_create(); #else /* PCI */ - /* Register our goodies */ - _device_driver.name = LINUX_KERNEL_BDE_NAME; - /* Configure MSI interrupt support */ use_msi = usemsi; @@ -3078,6 +3159,10 @@ _init(void) } } + for (i = 0; i < LINUX_BDE_MAX_DEVICES; ++i) { + _devices[i].inst_id = BDE_DEV_INST_ID_INVALID; + } + return 0; } @@ -3150,45 +3235,45 @@ _cleanup(void) * Always 0 */ static int -_pprint(void) +_pprint(struct seq_file *m) { int i = 0; - pprintf("Broadcom Device Enumerator (%s)\n", LINUX_KERNEL_BDE_NAME); + pprintf(m, "Broadcom Device Enumerator (%s)\n", LINUX_KERNEL_BDE_NAME); - pprintf("Module parameters:\n"); - pprintf("\tmaxpayload=%d\n", maxpayload); - pprintf("\tusemsi=%d\n", usemsi); + pprintf(m, "Module parameters:\n"); + pprintf(m, "\tmaxpayload=%d\n", maxpayload); + pprintf(m, "\tusemsi=%d\n", usemsi); - _dma_pprint(); + _dma_pprint(m); if (_ndevices == 0) { - pprintf("No devices found\n"); + pprintf(m, "No devices found\n"); } else { - pprintf("Devices:\n"); + pprintf(m, "Devices:\n"); } for (i = 0; i < _ndevices; i++) { bde_ctrl_t *ctrl = _devices + i; if (ctrl->dev_type & BDE_SWITCH_DEV_TYPE) { - pprintf("\t%d (swi) : ", i); + pprintf(m, "\t%d (swi) : ", i); } else if (ctrl->dev_type & BDE_ETHER_DEV_TYPE) { - pprintf("\t%d (eth) : ", i); + pprintf(m, "\t%d (eth) : ", i); } else if (ctrl->dev_type & BDE_CPU_DEV_TYPE) { - pprintf("\t%d (cpu) : ", i); + pprintf(m, "\t%d (cpu) : ", i); } else { - pprintf("\t%d (?) : ", i); + pprintf(m, "\t%d (?) : ", i); } if (ctrl->dev_state == BDE_DEV_STATE_REMOVED) { - pprintf("PCI device 0x%x:0x%x:%d REMOVED\n", + pprintf(m, "PCI device 0x%x:0x%x:%d REMOVED\n", ctrl->pci_device->vendor, ctrl->pci_device->device, ctrl->bde_dev.rev); continue; } if (ctrl->dev_type & BDE_PCI_DEV_TYPE) { - pprintf("PCI device %02x:%02x.%x 0x%x:0x%x:%d:0x%.8lx:0x%.8lx:%d%s\n", + pprintf(m, "PCI device %02x:%02x.%x 0x%x:0x%x:%d:0x%.8lx:0x%.8lx:%d%s\n", (unsigned int)ctrl->pci_device->bus->number, PCI_SLOT(ctrl->pci_device->devfn), PCI_FUNC(ctrl->pci_device->devfn), @@ -3200,7 +3285,7 @@ _pprint(void) ctrl->pci_device->irq, ctrl->use_msi ? " (MSI)" : ""); } else if (ctrl->dev_type & BDE_SPI_DEV_TYPE) { - pprintf("SPI Device %d:%x:%x:0x%x:0x%x:%d\n", + pprintf(m, "SPI Device %d:%x:%x:0x%x:0x%x:%d\n", ctrl->spi_device->cid, ctrl->spi_device->part, ctrl->spi_device->rev, @@ -3208,26 +3293,35 @@ _pprint(void) ctrl->spi_device->phyid_low, ctrl->bde_dev.rev); } else if (ctrl->dev_type & BDE_ICS_DEV_TYPE) { - pprintf("ICS Device 0x%x:0x%x\n", + pprintf(m, "ICS Device 0x%x:0x%x\n", ctrl->bde_dev.device, ctrl->bde_dev.rev); } else if (ctrl->dev_type & BDE_AXI_DEV_TYPE) { - pprintf("AXI Device 0x%x:0x%x:0x%.8lx:%d\n", + pprintf(m, "AXI Device 0x%x:0x%x:0x%.8lx:%d\n", ctrl->bde_dev.device, ctrl->bde_dev.rev, (unsigned long)ctrl->iowin[0].addr, ctrl->iLine); } else if (ctrl->dev_type & BDE_EB_DEV_TYPE) { - pprintf("EB Bus Device 0x%x:0x%x\n", + pprintf(m, "EB Bus Device 0x%x:0x%x\n", ctrl->bde_dev.device, ctrl->bde_dev.rev); } if (debug >= 1) { - pprintf("\t\timask:imask2:fmask 0x%x:0x%x:0x%x\n", + pprintf(m, "\t\timask:imask2:fmask 0x%x:0x%x:0x%x\n", ctrl->imask, ctrl->imask2, ctrl->fmask); } + if (debug >= 1) { + if (ctrl->inst_id == BDE_DEV_INST_ID_INVALID) { + pprintf(m, "\t\tinst_id INVALID\n"); + } else { + pprintf(m, "\t\tinst_id %u%s\n", + ctrl->inst_id, + ctrl->inst_id < LINUX_BDE_MAX_DEVICES ? "":"(Illegal)"); + } + } } return 0; } @@ -3952,9 +4046,6 @@ lkbde_cpu_pci_register(int d) pci_write_config_byte(ctrl->pci_device, 0x88, 0x2f); pci_write_config_byte(ctrl->pci_device, 0x89, 0x10); break; - case BCM88750_DEVICE_ID: - case BCM88753_DEVICE_ID: - case BCM88755_DEVICE_ID: case BCM88770_DEVICE_ID: case BCM88773_DEVICE_ID: case BCM88774_DEVICE_ID: @@ -3966,7 +4057,6 @@ lkbde_cpu_pci_register(int d) case BCM88954_DEVICE_ID: case BCM88955_DEVICE_ID: case BCM88956_DEVICE_ID: - case BCM88752_DEVICE_ID: case BCM88772_DEVICE_ID: case BCM88952_DEVICE_ID: case ACP_PCI_DEVICE_ID: @@ -4013,9 +4103,11 @@ lkbde_cpu_pci_register(int d) case BCM88476_DEVICE_ID: case BCM88477_DEVICE_ID: case BCM88270_DEVICE_ID: + case BCM88271_DEVICE_ID: case BCM88272_DEVICE_ID: case BCM88273_DEVICE_ID: case BCM88274_DEVICE_ID: + case BCM88276_DEVICE_ID: case BCM88278_DEVICE_ID: case BCM8206_DEVICE_ID: case BCM88350_DEVICE_ID: @@ -4061,6 +4153,7 @@ lkbde_cpu_pci_register(int d) case J2C_DEVICE_ID: case J2C_2ND_DEVICE_ID: case Q2A_DEVICE_ID: + case Q2U_DEVICE_ID: case J2P_DEVICE_ID: #endif #ifdef BCM_DNXF_SUPPORT @@ -4277,14 +4370,14 @@ lkbde_get_dev_virt(int d) } int -lkbde_get_dev_resource(int d, int rsrc, uint32_t *flags, - uint32_t *phys_lo, uint32_t *phys_hi) +lkbde_get_dev_resource(int d, int rsrc, uint32_t *phys_lo, + uint32_t *phys_hi, uint32_t *size) { if (!VALID_DEVICE(d)) { return -1; } - *flags = 0; + *size = 0; *phys_lo = 0; *phys_hi = 0; @@ -4300,12 +4393,14 @@ lkbde_get_dev_resource(int d, int rsrc, uint32_t *flags, #ifdef PHYS_ADDR_IS_64BIT *phys_hi = (uint32_t)(_devices[d].iowin[0].addr >> 32); #endif + *size = _devices[d].iowin[0].size; break; case 1: *phys_lo = (uint32_t)(_devices[d].iowin[1].addr); #ifdef PHYS_ADDR_IS_64BIT *phys_hi = (uint32_t)(_devices[d].iowin[1].addr >> 32); #endif + *size = _devices[d].iowin[1].size; break; default: break; @@ -4431,7 +4526,7 @@ lkbde_irq_mask_set(int d, uint32_t addr, uint32_t mask, uint32_t fmask) if (iproc_reg) { _iproc_write(d, addr, ctrl->imask | ctrl->imask2); } else { - _write(d, addr, ctrl->imask | ctrl->imask2); + _write(d, addr, ctrl->imask | ctrl->imask2); } spin_unlock_irqrestore(&ctrl->lock, flags); @@ -4481,6 +4576,29 @@ lkbde_get_num_devices(int type) return _num_devices(type); } +/* + * Return none-zero if the SDK instance with the given instance ID + * manages the given device. + */ +int lkbde_is_dev_managed_by_instance(uint32 dev, uint32 inst_id) +{ + if (inst_id >= LINUX_BDE_MAX_DEVICES || dev >= _ndevices) { + return 0; + } + return _instance_info[inst_id].devices[dev / 32] & (1 << (dev % 32)) ? 1 : 0; +} + +/* + * Return a pointer to the bitmap of the SDK instance managed devices. + */ +linux_bde_device_bitmap_t* lkbde_get_inst_devs(uint32 inst_id) +{ + if (inst_id >= LINUX_BDE_MAX_DEVICES) { + return NULL; + } + return &_instance_info[inst_id].devices; +} + /* * Export functions */ @@ -4503,3 +4621,5 @@ LKM_EXPORT_SYM(lkbde_cpu_write); LKM_EXPORT_SYM(lkbde_cpu_read); LKM_EXPORT_SYM(lkbde_cpu_pci_register); #endif +LKM_EXPORT_SYM(lkbde_is_dev_managed_by_instance); +LKM_EXPORT_SYM(lkbde_get_inst_devs); diff --git a/platform/broadcom/saibcm-modules/systems/bde/linux/kernel/linux_dma.c b/platform/broadcom/saibcm-modules/systems/bde/linux/kernel/linux_dma.c index 4f9518e9f4a..52711964a53 100644 --- a/platform/broadcom/saibcm-modules/systems/bde/linux/kernel/linux_dma.c +++ b/platform/broadcom/saibcm-modules/systems/bde/linux/kernel/linux_dma.c @@ -1,5 +1,10 @@ /* - * Copyright 2017 Broadcom + * Copyright 2007-2020 Broadcom Inc. All rights reserved. + * + * Permission is granted to use, copy, modify and/or distribute this + * software under either one of the licenses below. + * + * License Option 1: GPL * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License, version 2, as @@ -12,6 +17,12 @@ * * You should have received a copy of the GNU General Public License * version 2 (GPLv2) along with this source code. + * + * + * License Option 2: Broadcom Open Network Switch APIs (OpenNSA) license + * + * This software is governed by the Broadcom Open Network Switch APIs license: + * https://www.broadcom.com/products/ethernet-connectivity/software/opennsa */ /* * $Id: linux_dma.c,v 1.414 Broadcom SDK $ @@ -78,9 +89,10 @@ /* allocation types/methods for the DMA memory pool */ #define ALLOC_TYPE_CHUNK 0 /* use small allocations and join them */ #define ALLOC_TYPE_API 1 /* use one allocation */ + #if _SIMPLE_MEMORY_ALLOCATION_ #include -#if defined(IPROC_CMICD) && defined(CONFIG_CMA) && defined(CONFIG_CMA_SIZE_MBYTES) +#if defined(CONFIG_CMA) && defined(CONFIG_CMA_SIZE_MBYTES) #define DMA_MAX_ALLOC_SIZE (CONFIG_CMA_SIZE_MBYTES * 1024 * 1024) #else #define DMA_MAX_ALLOC_SIZE (1 << (MAX_ORDER - 1 + PAGE_SHIFT)) /* Maximum size the kernel can allocate in one allocation */ @@ -88,6 +100,7 @@ #endif /* _SIMPLE_MEMORY_ALLOCATION_ */ #if _SIMPLE_MEMORY_ALLOCATION_ == 1 +/* Use Linux DMA API to allocate contiguous memory */ #define ALLOC_METHOD_DEFAULT ALLOC_TYPE_API #if defined(__arm__) #define USE_DMA_MMAP_COHERENT @@ -196,6 +209,17 @@ MODULE_PARM_DESC(himemaddr, #define DMA_MEM_DEFAULT (8 * ONE_MB) #endif +#ifdef BDE_EDK_SUPPORT +typedef struct { + phys_addr_t cpu_pbase; /* CPU physical base address of the DMA pool */ + phys_addr_t dma_pbase; /* Bus base address of the DMA pool */ + void __iomem *dma_vbase; + uint32 size; /* Total size of the pool */ +}_edk_dma_pool_t; +static _edk_dma_pool_t _edk_dma_pool[LINUX_BDE_MAX_DEVICES]; +static int _edk_use_dma_mapping = 0; +#endif + /* We try to assemble a contiguous segment from chunks of this size */ #define DMA_BLOCK_SIZE (512 * ONE_KB) @@ -552,18 +576,145 @@ _pgfree(void *ptr) return -1; } +#ifdef BDE_EDK_SUPPORT +/* + * Function: _edk_mpool_free + * + * Purpose: + * Free all memory allocated by _adk_mpool_alloc + * Parameters: + * None + * Returns: + * Nothing. + */ +static void +_edk_mpool_free(void) +{ + int i, ndevices; + + ndevices = BDE_NUM_DEVICES(BDE_SWITCH_DEVICES); + for (i = 0; i < ndevices && DMA_DEV(i); i ++) { + if (_edk_dma_pool[i].dma_vbase) { + if (_edk_use_dma_mapping) { + dma_unmap_single(DMA_DEV(i), (dma_addr_t)_edk_dma_pool[i].dma_pbase, + _edk_dma_pool[i].size, DMA_BIDIRECTIONAL); + } + _pgfree(_edk_dma_pool[i].dma_vbase); + _edk_dma_pool[i].dma_vbase = NULL; + } + } + _edk_use_dma_mapping = 0; +} + +/* + * Function: edk_mpool_alloc + * + * Purpose: + * Allocate DMA memory pool for EDK + * Parameters: + * size - size of DMA memory pool + * Returns: + * Nothing. + */ +static void +_edk_mpool_alloc(int dev_id, size_t size) +{ + static void __iomem *dma_vbase = NULL; + static phys_addr_t cpu_pbase = 0; + static phys_addr_t dma_pbase = 0; + + struct device *dev = DMA_DEV(DMA_DEV_INDEX); + unsigned long pbase = 0; + + dma_vbase = _pgalloc(size); + if (!dma_vbase) { + gprintk("Failed to allocate memory pool of size 0x%lx for EDK\n", + (unsigned long)size); + return; + } + cpu_pbase = virt_to_bus(dma_vbase); + + /* Use dma_map_single to obtain DMA bus address or IOVA if IOMMU is present. */ + if (dev) { + pbase = dma_map_single(dev, dma_vbase, size, DMA_BIDIRECTIONAL); + if (BDE_DMA_MAPPING_ERROR(dev, pbase)) { + gprintk("Failed to map memory at %p for EDK\n", dma_vbase); + _pgfree(dma_vbase); + dma_vbase = NULL; + return; + } + _edk_use_dma_mapping = 1; + } else { + pbase = cpu_pbase; + } + + dma_pbase = pbase; + +#ifdef REMAP_DMA_NONCACHED + _dma_vbase = IOREMAP(dma_pbase, size); +#endif + _edk_dma_pool[dev_id].cpu_pbase = cpu_pbase; + _edk_dma_pool[dev_id].dma_pbase = dma_pbase; + _edk_dma_pool[dev_id].dma_vbase = dma_vbase; + _edk_dma_pool[dev_id].size = size; +} + +int +lkbde_edk_get_dma_info(int dev_id, phys_addr_t* cpu_pbase, phys_addr_t* dma_pbase, ssize_t* size) +{ + if (_edk_dma_pool[dev_id].dma_vbase == NULL) { + _edk_mpool_alloc(dev_id, *size * ONE_MB); + } + + if (cpu_pbase) { + *cpu_pbase = _edk_dma_pool[dev_id].cpu_pbase; + } + + if (dma_pbase) { + *dma_pbase = _edk_dma_pool[dev_id].dma_pbase; + } + + *size = (_edk_dma_pool[dev_id].dma_vbase) ? _edk_dma_pool[dev_id].size : 0; + return 0; +} + /* - * Function: _pgcleanup + * The below function validates the memory to the EDK allocated DMA pool, + * required to user space via the BDE device file. + */ +static int +_edk_vm_is_valid(struct file *filp, struct vm_area_struct *vma) +{ + unsigned long phys_addr = vma->vm_pgoff << PAGE_SHIFT; + unsigned long size = vma->vm_end - vma->vm_start; + int i, ndevices; + + ndevices = BDE_NUM_DEVICES(BDE_SWITCH_DEVICES); + for (i = 0; i < ndevices; i++) { + if (phys_addr < (unsigned long )_edk_dma_pool[i].cpu_pbase || + (phys_addr + size) > ((unsigned long )_edk_dma_pool[i].cpu_pbase + + _edk_dma_pool[i].size)) { + continue; + } + return 1; + } + + return 0; +} +#endif + +/* + * Function: _mpool_free * * Purpose: - * Free all memory allocated by _pgalloc + * Free all memory allocated by _mpool_alloc * Parameters: * None * Returns: * Nothing. */ static void -_pgcleanup(void) +_mpool_free(void) { switch (dmaalloc) { #if _SIMPLE_MEMORY_ALLOCATION_ @@ -599,7 +750,7 @@ _pgcleanup(void) } /* - * Function: _alloc_mpool + * Function: _mpool_alloc * * Purpose: * Allocate DMA memory pool @@ -613,7 +764,7 @@ _pgcleanup(void) * It is assumed there is only one pool. */ static void -_alloc_mpool(size_t size) +_mpool_alloc(size_t size) { unsigned long pbase = 0; struct device *dev = DMA_DEV(DMA_DEV_INDEX); @@ -643,7 +794,22 @@ _alloc_mpool(size_t size) gprintk("DMA in high memory at 0x%lx size 0x%lx is beyond the 4GB limit and not supported.\n", pbase, (unsigned long)size); return; } - _cpu_pbase = _dma_pbase = pbase; + _cpu_pbase = pbase; + if (dev) { + /* Use dma_map_single to obtain DMA bus address or I/O virtual address, if + IOMMU is present. */ + pbase = dma_map_single(dev, bus_to_virt(_cpu_pbase), size, DMA_BIDIRECTIONAL); + if (BDE_DMA_MAPPING_ERROR(dev, pbase)) { + gprintk("Error !! Failed to map memory at phys base 0x%lx\n", + (unsigned long)_cpu_pbase); + _cpu_pbase = 0; + return; + } + _use_dma_mapping = 1; + } else { + pbase = _cpu_pbase; + } + _dma_pbase = pbase; _dma_vbase = IOREMAP(_dma_pbase, size); } else { /* Get DMA memory from kernel */ @@ -684,14 +850,13 @@ _alloc_mpool(size_t size) return; } _cpu_pbase = virt_to_bus(_dma_vbase); - /* Use dma_map_single to obtain DMA bus address or IOVA if iommu is present. */ + /* Use dma_map_single to obtain DMA bus address or IOVA if IOMMU is present. */ if (dev) { pbase = dma_map_single(dev, _dma_vbase, size, DMA_BIDIRECTIONAL); if (BDE_DMA_MAPPING_ERROR(dev, pbase)) { gprintk("Failed to map memory at %p\n", _dma_vbase); - _pgcleanup(); + _mpool_free(); _dma_vbase = NULL; - _cpu_pbase = 0; return; } _use_dma_mapping = 1; @@ -709,7 +874,7 @@ _alloc_mpool(size_t size) if (!dma64_support && ((pbase + (size - 1)) >> 16) > DMA_BIT_MASK(16)) { gprintk("DMA memory allocated at 0x%lx size 0x%lx is beyond the 4GB limit and not supported.\n", pbase, (unsigned long)size); - _pgcleanup(); + _mpool_free(); _dma_vbase = NULL; _dma_pbase = 0; return; @@ -739,15 +904,27 @@ _alloc_mpool(size_t size) int _dma_cleanup(void) { +#ifdef BDE_EDK_SUPPORT + _edk_mpool_free(); +#endif if (_dma_vbase) { mpool_destroy(_dma_pool); if (_use_himem) { + int i, ndevices; iounmap(_dma_vbase); + if (_use_dma_mapping) { + ndevices = BDE_NUM_DEVICES(BDE_SWITCH_DEVICES); + for (i = 0; i < ndevices && DMA_DEV(i); i ++) { + dma_unmap_single(DMA_DEV(i), (dma_addr_t)_dma_pbase, _dma_mem_size, + DMA_BIDIRECTIONAL); + } + _use_dma_mapping = 0; + } } else { #ifdef REMAP_DMA_NONCACHED iounmap(_dma_vbase); #endif - _pgcleanup(); + _mpool_free(); } _dma_vbase = NULL; _dma_pbase = 0; @@ -811,7 +988,7 @@ void _dma_init(int dev_index) } if (_dma_mem_size) { - _alloc_mpool(_dma_mem_size); + _mpool_alloc(_dma_mem_size); if (_dma_vbase == NULL) { gprintk("no DMA memory available\n"); } else { @@ -835,10 +1012,17 @@ int _dma_mmap(struct file *filp, struct vm_area_struct *vma) if (phys_addr < (unsigned long )_cpu_pbase || (phys_addr + size) > ((unsigned long )_cpu_pbase + _dma_mem_size)) { +#ifdef BDE_EDK_SUPPORT + if(!_edk_vm_is_valid(filp, vma)) { + gprintk("range 0x%lx-0x%lx outside DMA pool\n", phys_addr, phys_addr + size); + return -EINVAL; + } +#else gprintk("range 0x%lx-0x%lx outside DMA pool 0x%lx-0x%lx\n", phys_addr, phys_addr + size, (unsigned long )_cpu_pbase, (unsigned long )_cpu_pbase + _dma_mem_size); return -EINVAL; +#endif } #ifdef USE_DMA_MMAP_COHERENT @@ -995,7 +1179,7 @@ lkbde_get_dma_info(phys_addr_t* cpu_pbase, phys_addr_t* dma_pbase, ssize_t* size if (_dma_mem_size == 0) { _dma_mem_size = DMA_MEM_DEFAULT; } - _alloc_mpool(_dma_mem_size); + _mpool_alloc(_dma_mem_size); } *cpu_pbase = _cpu_pbase; *dma_pbase = _dma_pbase; @@ -1004,12 +1188,12 @@ lkbde_get_dma_info(phys_addr_t* cpu_pbase, phys_addr_t* dma_pbase, ssize_t* size } void -_dma_pprint(void) +_dma_pprint(struct seq_file *m) { - pprintf("\tdmasize=%s\n", dmasize); - pprintf("\thimem=%s\n", himem); - pprintf("\thimemaddr=%s\n", himemaddr); - pprintf("DMA Memory (%s): %d bytes, %d used, %d free%s\n", + pprintf(m, "\tdmasize=%s\n", dmasize); + pprintf(m, "\thimem=%s\n", himem); + pprintf(m, "\thimemaddr=%s\n", himemaddr); + pprintf(m, "DMA Memory (%s): %d bytes, %d used, %d free%s\n", (_use_himem) ? "high" : "kernel", (_dma_vbase) ? _dma_mem_size : 0, (_dma_vbase) ? mpool_usage(_dma_pool) : 0, @@ -1020,6 +1204,10 @@ _dma_pprint(void) /* * Export functions */ + +#ifdef BDE_EDK_SUPPORT +LKM_EXPORT_SYM(lkbde_edk_get_dma_info); +#endif LKM_EXPORT_SYM(kmalloc_giant); LKM_EXPORT_SYM(kfree_giant); LKM_EXPORT_SYM(lkbde_get_dma_info); diff --git a/platform/broadcom/saibcm-modules/systems/bde/linux/kernel/linux_shbde.c b/platform/broadcom/saibcm-modules/systems/bde/linux/kernel/linux_shbde.c index a2d58858a5a..dd003e1f929 100644 --- a/platform/broadcom/saibcm-modules/systems/bde/linux/kernel/linux_shbde.c +++ b/platform/broadcom/saibcm-modules/systems/bde/linux/kernel/linux_shbde.c @@ -1,5 +1,10 @@ /* - * Copyright 2017 Broadcom + * Copyright 2007-2020 Broadcom Inc. All rights reserved. + * + * Permission is granted to use, copy, modify and/or distribute this + * software under either one of the licenses below. + * + * License Option 1: GPL * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License, version 2, as @@ -12,6 +17,12 @@ * * You should have received a copy of the GNU General Public License * version 2 (GPLv2) along with this source code. + * + * + * License Option 2: Broadcom Open Network Switch APIs (OpenNSA) license + * + * This software is governed by the Broadcom Open Network Switch APIs license: + * https://www.broadcom.com/products/ethernet-connectivity/software/opennsa */ /* * $Id: $ diff --git a/platform/broadcom/saibcm-modules/systems/bde/linux/kernel/linux_shbde.h b/platform/broadcom/saibcm-modules/systems/bde/linux/kernel/linux_shbde.h index 5e8a70119e8..ef4b49dc212 100644 --- a/platform/broadcom/saibcm-modules/systems/bde/linux/kernel/linux_shbde.h +++ b/platform/broadcom/saibcm-modules/systems/bde/linux/kernel/linux_shbde.h @@ -1,5 +1,10 @@ /* - * Copyright 2017 Broadcom + * Copyright 2007-2020 Broadcom Inc. All rights reserved. + * + * Permission is granted to use, copy, modify and/or distribute this + * software under either one of the licenses below. + * + * License Option 1: GPL * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License, version 2, as @@ -12,6 +17,12 @@ * * You should have received a copy of the GNU General Public License * version 2 (GPLv2) along with this source code. + * + * + * License Option 2: Broadcom Open Network Switch APIs (OpenNSA) license + * + * This software is governed by the Broadcom Open Network Switch APIs license: + * https://www.broadcom.com/products/ethernet-connectivity/software/opennsa */ /* * $Id: $ diff --git a/platform/broadcom/saibcm-modules/systems/bde/linux/shared/mpool.c b/platform/broadcom/saibcm-modules/systems/bde/linux/shared/mpool.c index 13206596ee2..4c2db5e4de6 100644 --- a/platform/broadcom/saibcm-modules/systems/bde/linux/shared/mpool.c +++ b/platform/broadcom/saibcm-modules/systems/bde/linux/shared/mpool.c @@ -1,5 +1,10 @@ /* - * Copyright 2017 Broadcom + * Copyright 2007-2020 Broadcom Inc. All rights reserved. + * + * Permission is granted to use, copy, modify and/or distribute this + * software under either one of the licenses below. + * + * License Option 1: GPL * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License, version 2, as @@ -12,6 +17,12 @@ * * You should have received a copy of the GNU General Public License * version 2 (GPLv2) along with this source code. + * + * + * License Option 2: Broadcom Open Network Switch APIs (OpenNSA) license + * + * This software is governed by the Broadcom Open Network Switch APIs license: + * https://www.broadcom.com/products/ethernet-connectivity/software/opennsa */ /* * $Id: mpool.c,v 1.18 Broadcom SDK $ @@ -71,7 +82,7 @@ static sal_sem_t _mpool_lock; #endif #define MPOOL_BUF_SIZE 1024 -#define MPOOL_BUF_ALLOC_COUNT_MAX 16 +#define MPOOL_BUF_ALLOC_COUNT_MAX 128 typedef struct mpool_mem_s { unsigned char *address; @@ -80,20 +91,42 @@ typedef struct mpool_mem_s { struct mpool_mem_s *next; } mpool_mem_t; +static int _mpool_count; static int _buf_alloc_count; static mpool_mem_t *mpool_buf[MPOOL_BUF_ALLOC_COUNT_MAX]; static mpool_mem_t *free_list; -#define ALLOC_INIT_MPOOL_BUF(ptr) \ - ptr = MALLOC((sizeof(mpool_mem_t) * MPOOL_BUF_SIZE)); \ - if (ptr) { \ - int i; \ - for (i = 0; i < MPOOL_BUF_SIZE - 1; i++) { \ - ptr[i].next = &ptr[i+1]; \ - } \ - ptr[MPOOL_BUF_SIZE - 1].next = NULL; \ - free_list = &ptr[0]; \ - } +static mpool_mem_t * +_mpool_buf_create(void) +{ + int i; + mpool_mem_t *ptr; + + if (_buf_alloc_count == MPOOL_BUF_ALLOC_COUNT_MAX) { + return NULL; + } + + mpool_buf[_buf_alloc_count] = MALLOC((sizeof(mpool_mem_t) * MPOOL_BUF_SIZE)); + if (!mpool_buf[_buf_alloc_count]) { + return NULL; + } + + ptr = mpool_buf[_buf_alloc_count]; + for (i = 0; i < MPOOL_BUF_SIZE - 1; i++) { + ptr[i].next = &ptr[i+1]; + } + + ptr[MPOOL_BUF_SIZE - 1].next = NULL; + + if (free_list) { + free_list->next = &ptr[0]; + } else { + free_list = &ptr[0]; + } + + _buf_alloc_count++; + return ptr; +} /* * Function: mpool_init @@ -108,7 +141,15 @@ static mpool_mem_t *free_list; int mpool_init(void) { + int i; + MPOOL_LOCK_INIT(); + _buf_alloc_count = 0; + _mpool_count = 0; + for (i = 0; i < MPOOL_BUF_ALLOC_COUNT_MAX; i++) { + mpool_buf[i] = NULL; + } + free_list = NULL; return 0; } @@ -140,7 +181,7 @@ mpool_alloc(mpool_handle_t pool, int size) } mod = size & (BCM_CACHE_LINE_BYTES - 1); - if (mod != 0 ) { + if (mod != 0) { size += (BCM_CACHE_LINE_BYTES - mod); } while (ptr && ptr->next) { @@ -155,20 +196,9 @@ mpool_alloc(mpool_handle_t pool, int size) return NULL; } - if (!free_list) { - if (_buf_alloc_count == MPOOL_BUF_ALLOC_COUNT_MAX) { - MPOOL_UNLOCK(); - return NULL; - } - - ALLOC_INIT_MPOOL_BUF(mpool_buf[_buf_alloc_count]); - - if (mpool_buf[_buf_alloc_count] == NULL) { - MPOOL_UNLOCK(); - return NULL; - } - - _buf_alloc_count++; + if (!free_list && !_mpool_buf_create()) { + MPOOL_UNLOCK(); + return NULL; } newptr = free_list; @@ -251,25 +281,16 @@ mpool_create(void *base_ptr, int size) { mpool_mem_t *head, *tail; int mod = (int)(((unsigned long)base_ptr) & (BCM_CACHE_LINE_BYTES - 1)); - int i; MPOOL_LOCK(); - for (i = 0; i < MPOOL_BUF_ALLOC_COUNT_MAX; i++) { - mpool_buf[i] = NULL; - } - - _buf_alloc_count = 0; - - ALLOC_INIT_MPOOL_BUF(mpool_buf[_buf_alloc_count]); - - if (mpool_buf[_buf_alloc_count] == NULL) { - MPOOL_UNLOCK(); - return NULL; + if (!free_list || !(free_list->next)) { + if (!_mpool_buf_create()) { + MPOOL_UNLOCK(); + return NULL; + } } - _buf_alloc_count++; - if (mod) { base_ptr = (char*)base_ptr + (BCM_CACHE_LINE_BYTES - mod); size -= (BCM_CACHE_LINE_BYTES - mod); @@ -288,6 +309,7 @@ mpool_create(void *base_ptr, int size) head->next = tail; tail->prev = head; tail->next = NULL; + _mpool_count++; MPOOL_UNLOCK(); return head; @@ -307,19 +329,27 @@ int mpool_destroy(mpool_handle_t pool) { int i; + mpool_mem_t *head = pool; MPOOL_LOCK(); - if ((mpool_mem_t *)pool != mpool_buf[0]) { + if (!(head && head->prev)) { MPOOL_UNLOCK(); return 0; } - for (i = 0; i < MPOOL_BUF_ALLOC_COUNT_MAX; i++) { - if (mpool_buf[i]) { - FREE(mpool_buf[i]); - mpool_buf[i] = NULL; + head->prev->next = free_list; + free_list = head; + _mpool_count--; + + if (_mpool_count == 0) { + for (i = 0; i < MPOOL_BUF_ALLOC_COUNT_MAX; i++) { + if (mpool_buf[i]) { + FREE(mpool_buf[i]); + mpool_buf[i] = NULL; + } } + free_list = NULL; } MPOOL_UNLOCK(); diff --git a/platform/broadcom/saibcm-modules/systems/bde/linux/user/kernel/Makefile b/platform/broadcom/saibcm-modules/systems/bde/linux/user/kernel/Makefile index 424f2fe24be..2cc96df02d0 100644 --- a/platform/broadcom/saibcm-modules/systems/bde/linux/user/kernel/Makefile +++ b/platform/broadcom/saibcm-modules/systems/bde/linux/user/kernel/Makefile @@ -1,5 +1,10 @@ # -# Copyright 2017 Broadcom +# Copyright 2007-2020 Broadcom Inc. All rights reserved. +# +# Permission is granted to use, copy, modify and/or distribute this +# software under either one of the licenses below. +# +# License Option 1: GPL # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License, version 2, as @@ -12,6 +17,12 @@ # # You should have received a copy of the GNU General Public License # version 2 (GPLv2) along with this source code. +# +# +# License Option 2: Broadcom Open Network Switch APIs (OpenNSA) license +# +# This software is governed by the Broadcom Open Network Switch APIs license: +# https://www.broadcom.com/products/ethernet-connectivity/software/opennsa # # -*- Makefile -*- # $Id: Makefile,v 1.1 Broadcom SDK $ diff --git a/platform/broadcom/saibcm-modules/systems/bde/linux/user/kernel/linux-user-bde.c b/platform/broadcom/saibcm-modules/systems/bde/linux/user/kernel/linux-user-bde.c index 46f60c8a3ae..4e6186e2d80 100644 --- a/platform/broadcom/saibcm-modules/systems/bde/linux/user/kernel/linux-user-bde.c +++ b/platform/broadcom/saibcm-modules/systems/bde/linux/user/kernel/linux-user-bde.c @@ -24,14 +24,13 @@ #include #include #include - +#include #include "linux-user-bde.h" #if LINUX_VERSION_CODE >= KERNEL_VERSION(4,12,0) #include #endif - MODULE_AUTHOR("Broadcom Corporation"); MODULE_DESCRIPTION("User BDE Helper Module"); MODULE_LICENSE("GPL"); @@ -71,7 +70,7 @@ MODULE_LICENSE("GPL"); /* CMICX defines */ #define INTC_INTR_REG_NUM (8) - +#define PAXB_INTRCLR_DELAY_REG_NUM (16) /* TODO:HX5 The INTR base address values are changed for HX5, @@ -80,15 +79,27 @@ be made. */ #define PAXB_0_PAXB_IC_INTRCLR_0 (0x180123a0) #define PAXB_0_PAXB_IC_INTRCLR_1 (0x180123a4) - #define PAXB_0_PAXB_IC_INTRCLR_MODE_0 (0x180123a8) #define PAXB_0_PAXB_IC_INTRCLR_MODE_1 (0x180123ac) +#define PAXB_0_PAXB_INTR_STATUS (0x18012f38) +#define PAXB_0_PAXB_IC_INTR_PACING_CTRL (0x18012398) +#define PAXB_0_PAXB_INTRCLR_DELAY_UNIT (0x1801239c) +#define PAXB_0_PAXB_IC_INTRCLR_DELAY_REG0 (0x180123b0) +#define PAXB_0_PCIE_ERROR_STATUS (0x18012024) #define HX5_PAXB_0_PAXB_IC_INTRCLR_0 (0x102303a0) #define HX5_PAXB_0_PAXB_IC_INTRCLR_1 (0x102303a4) #define HX5_PAXB_0_PAXB_IC_INTRCLR_MODE_0 (0x102303a8) #define HX5_PAXB_0_PAXB_IC_INTRCLR_MODE_1 (0x102303ac) +#define HX5_PAXB_0_PAXB_INTR_STATUS (0x10230f38) +#define HX5_PAXB_0_PAXB_IC_INTR_PACING_CTRL (0x10230398) +#define HX5_PAXB_0_PAXB_INTRCLR_DELAY_UNIT (0x1023039c) +#define HX5_PAXB_0_PAXB_IC_INTRCLR_DELAY_REG0 (0x102303b0) +#define HX5_PAXB_0_PCIE_ERROR_STATUS (0x10230024) + +#define PAXB_0_PAXB_IC_INTRCLR_DELAY_BASE (PAXB_0_PAXB_IC_INTRCLR_DELAY_REG0) +#define HX5_PAXB_0_PAXB_IC_INTRCLR_DELAY_BASE (HX5_PAXB_0_PAXB_IC_INTRCLR_DELAY_REG0) #define INTC_INTR_ENABLE_REG0 (0x180130f0) #define INTC_INTR_STATUS_REG0 (0x18013190) @@ -129,9 +140,9 @@ be made. #define INTC_LOW_PRIORITY_INTR_REG_IND IRQ_MASK_INDEX(HX5_CHIP_INTR_LOW_PRIORITY) #define INTC_PDMA_INTR_REG_IND 4 -#define READ_INTC_INTR(d, reg, v) \ +#define IPROC_READ(d, reg, v) \ (v = user_bde->iproc_read(d, reg)) -#define WRITE_INTC_INTR(d, reg, v) \ +#define IPROC_WRITE(d, reg, v) \ (user_bde->iproc_write(d, reg, v)) #define IHOST_READ_INTR(d, reg, v) \ @@ -155,6 +166,22 @@ be made. static uint32 *ihost_intr_status_base = NULL; static uint32 *ihost_intr_enable_base = NULL; +/* Module parameter for Interruptible timeout */ +static int intr_timeout = 0; +LKM_MOD_PARAM(intr_timeout, "i", int, (S_IRUGO | S_IWUSR)); +MODULE_PARM_DESC(intr_timeout, +"Interruptible wait timeout in milliseconds for Interrupt to be triggered."); + +static ulong intr_count = 0; +LKM_MOD_PARAM(intr_count, "intr_count", ulong, (S_IRUGO | S_IWUSR)); +MODULE_PARM_DESC(intr_count, +"Interrupt count provides information about the number of times the ISR is called."); + +static ulong intr_timeout_count = 0; +LKM_MOD_PARAM(intr_timeout_count, "intr_timeout_count", ulong, (S_IRUGO | S_IWUSR)); +MODULE_PARM_DESC(intr_timeout_count, +"Interrupt timeout count provides information about the number of times the interrupt wait is timeed out."); + /* Debug output */ static int debug; LKM_MOD_PARAM(debug, "i", int, (S_IRUGO | S_IWUSR)); @@ -168,10 +195,16 @@ typedef void (*isr_f)(void *); typedef struct _intr_regs_s { uint32 intc_intr_status_base; uint32 intc_intr_enable_base; + uint32 intc_intr_raw_status_base; uint32 intc_intr_clear_0; uint32 intc_intr_clear_1; uint32 intc_intr_clear_mode_0; uint32 intc_intr_clear_mode_1; + uint32 intc_intr_status; + uint32 intc_intr_pacing_ctrl; + uint32 intc_intr_clear_delay_unit; + uint32 intc_intr_clear_delay_base; + uint32 intc_intr_pcie_err_status; } _intr_regs_t; typedef struct bde_ctrl_s { @@ -181,7 +214,8 @@ typedef struct bde_ctrl_s { int devid; isr_f isr; uint32 *ba; - int inst; /* associate to _bde_inst_resource[] */ + uint32 inst; /* the resource/instance index in _bde_inst_resource[] */ + int edk_irq_enabled; _intr_regs_t intr_regs; } bde_ctrl_t; @@ -199,20 +233,37 @@ static atomic_t _ether_interrupt_has_taken_place = ATOMIC_INIT(0); */ static int _bde_multi_inst = 0; +#define MAX_UC_CORES LINUX_BDE_MAX_IPROC_UC_CORES + +/* Structure to hold info about interrupts handled by EDK */ typedef struct { - unsigned int inst_id; - unsigned int dma_offset; - unsigned int dma_size; + uint32_t timer_intrc_offset; /* Timer interrupts INTC offset */ + uint32_t timer_intrc_mask; /* Timer interrupts mask */ + uint32_t sw_intr_intrc_offset; /* SW Programmable Interrupt's offset */ + uint32_t sw_intr_intrc_mask; /* SW interrupt's mask */ + uint32_t sw_intr_src_bitmap; /* SW interrupt's bitmask to navigate ICFG registers */ + uint32_t sw_intr_icfg_reg[MAX_UC_CORES]; /* ICFG registers for each core */ +} bde_edk_intr_t; + +typedef struct { + int is_active; /* Is the instance active */ + unsigned int dma_offset; /* offset of the instance's DMA memory in the DMA buffer pool */ + unsigned int dma_size; /* size of the instance's DMA memory (in the DMA buffer pool) */ wait_queue_head_t intr_wq; + wait_queue_head_t edk_intr_wq; atomic_t intr; + atomic_t edk_intr; + bde_edk_intr_t edk_irqs; } bde_inst_resource_t; +/* This array contains information for SDK instance, the index in the array is the instance ID */ static bde_inst_resource_t _bde_inst_resource[LINUX_BDE_MAX_DEVICES]; /* * Lock used to protect changes to _bde_inst_resource */ static spinlock_t bde_resource_lock; + typedef struct { phys_addr_t cpu_pbase; /* CPU physical base address of the DMA pool */ phys_addr_t dma_pbase; /* Bus base address of the DMA pool */ @@ -291,23 +342,98 @@ _cmic_interrupt(bde_ctrl_t *ctrl) #endif } -static void -_cmicx_interrupt(bde_ctrl_t *ctrl) +void +dump_interrupt_regs(bde_ctrl_t *ctrl , int dev) +{ + int ind; + uint32_t val; + + if (debug >= 2) { + gprintk("Interrupt timeout count = %lu\n", intr_timeout_count); + gprintk("Interrupt count = %lu\n", intr_count); + for (ind = 0; ind < INTC_INTR_REG_NUM; ind++) { + IPROC_READ(dev, ctrl->intr_regs.intc_intr_status_base + 4 * ind, val); + gprintk("INTC_INTR_STATUS_REG_%d = 0x%x\n", ind, val); + IPROC_READ(dev, ctrl->intr_regs.intc_intr_raw_status_base + 4 * ind, val); + gprintk("INTC_INTR_RAW_STATUS_REG_%d = 0x%x\n", ind, val); + IPROC_READ(dev, ctrl->intr_regs.intc_intr_enable_base + 4 * ind, val); + gprintk("INTC_INTR_ENABLE_REG_%d = 0x%x\n", ind, val); + } + /* Dump PAXB Register */ + IPROC_READ(dev, ctrl->intr_regs.intc_intr_status, val); + gprintk("PAXB_0_PAXB_INTR_STATUS = 0x%x\n", val); + IPROC_READ(dev, ctrl->intr_regs.intc_intr_pacing_ctrl, val); + gprintk("PAXB_0_PAXB_IC_INTR_PACING_CTRL = 0x%x\n", val); + IPROC_READ(dev, ctrl->intr_regs.intc_intr_clear_delay_unit, val); + gprintk("PAXB_0_PAXB_INTRCLR_DELAY_UNIT = 0x%x\n", val); + IPROC_READ(dev, ctrl->intr_regs.intc_intr_pcie_err_status, val); + gprintk("PAXB_0_PCIE_ERROR_STATUS = 0x%x\n", val); + + for (ind = 0; ind < PAXB_INTRCLR_DELAY_REG_NUM; ind++) { + IPROC_READ(dev, ctrl->intr_regs.intc_intr_clear_delay_base + 4 * ind, val); + gprintk("PAXB_0_PAXB_IC_INTRCLR_DELAY_REG_%d = 0x%x\n", ind, val); + } + } + /* Clear interrupt enable registers */ + for (ind = 0; ind < INTC_INTR_REG_NUM; ind++) { + IPROC_WRITE(dev, ctrl->intr_regs.intc_intr_enable_base + 4 * ind, 0); + } +} + +#ifdef BDE_EDK_SUPPORT +static int +_cmicx_edk_interrupt_check(bde_ctrl_t *ctrl, int d) { - int d, ind; - uint32 stat, iena, mask, fmask; bde_inst_resource_t *res; + uint32 stat, mask = 0, bitmap = 0; + int idx; + + res = &_bde_inst_resource[ctrl->inst]; + bitmap = res->edk_irqs.sw_intr_src_bitmap; + + /* Explicitly reading raw_status so as to not clear the status on read */ + IPROC_READ(d, ctrl->intr_regs.intc_intr_raw_status_base + + (res->edk_irqs.sw_intr_intrc_offset * 4), stat); + /* Check whether Software Programmable Interrupt is set */ + if (stat & res->edk_irqs.sw_intr_intrc_mask) { + for (idx = 0; (bitmap && (idx < MAX_UC_CORES)); idx++) { + if (bitmap & 1) { + IPROC_READ(d, res->edk_irqs.sw_intr_icfg_reg[idx], stat); + mask |= (stat & 1) << idx; + } + bitmap = (bitmap >> 1); + } + if (mask) + return 1; + } + + /* EDK uses timer interrupt as watchdog to indicate the the firmware has crashed */ + IPROC_READ(d, ctrl->intr_regs.intc_intr_raw_status_base + + (res->edk_irqs.timer_intrc_offset * 4), stat); + if (stat & res->edk_irqs.timer_intrc_mask) { + return 1; + } + return 0; +} +#endif + +static int +_cmicx_interrupt_prepare(bde_ctrl_t *ctrl) +{ + int d, ind, ret = 0; + uint32 stat, iena, mask, fmask; d = (((uint8 *)ctrl - (uint8 *)_devices) / sizeof (bde_ctrl_t)); if (ctrl->dev_type & BDE_PCI_DEV_TYPE) { + IPROC_READ(d, ctrl->intr_regs.intc_intr_clear_mode_0, stat); /* Clear MSI interrupts immediately to prevent spurious interrupts */ - WRITE_INTC_INTR(d, ctrl->intr_regs.intc_intr_clear_0, 0xFFFFFFFF); - WRITE_INTC_INTR(d, ctrl->intr_regs.intc_intr_clear_1, 0xFFFFFFFF); + if (stat == 0) { + IPROC_WRITE(d, ctrl->intr_regs.intc_intr_clear_0, 0xFFFFFFFF); + IPROC_WRITE(d, ctrl->intr_regs.intc_intr_clear_1, 0xFFFFFFFF); + } } - res = &_bde_inst_resource[ctrl->inst]; - lkbde_irq_mask_get(d, &mask, &fmask); if (fmask) { @@ -315,15 +441,15 @@ _cmicx_interrupt(bde_ctrl_t *ctrl) IHOST_READ_INTR(d, ihost_intr_status_base + INTC_PDMA_INTR_REG_IND, stat); IHOST_READ_INTR(d, ihost_intr_enable_base + INTC_PDMA_INTR_REG_IND, iena); } else { - READ_INTC_INTR(d, ctrl->intr_regs.intc_intr_status_base + 4 * INTC_PDMA_INTR_REG_IND, stat); - READ_INTC_INTR(d, ctrl->intr_regs.intc_intr_enable_base + 4 * INTC_PDMA_INTR_REG_IND, iena); + IPROC_READ(d, ctrl->intr_regs.intc_intr_status_base + 4 * INTC_PDMA_INTR_REG_IND, stat); + IPROC_READ(d, ctrl->intr_regs.intc_intr_enable_base + 4 * INTC_PDMA_INTR_REG_IND, iena); } if (stat & iena) { if (ctrl->dev_type & BDE_AXI_DEV_TYPE) { IHOST_WRITE_INTR(d, ihost_intr_enable_base + INTC_PDMA_INTR_REG_IND + HX5_IHOST_IRQ_MASK_OFFSET, ~0); } else { - WRITE_INTC_INTR(d, ctrl->intr_regs.intc_intr_enable_base + 4 * INTC_PDMA_INTR_REG_IND, 0); + IPROC_WRITE(d, ctrl->intr_regs.intc_intr_enable_base + 4 * INTC_PDMA_INTR_REG_IND, 0); } for (ind = 0; ind < INTC_INTR_REG_NUM; ind++) { @@ -344,16 +470,16 @@ _cmicx_interrupt(bde_ctrl_t *ctrl) } } } else { - READ_INTC_INTR(d, ctrl->intr_regs.intc_intr_status_base + 4 * ind, stat); - READ_INTC_INTR(d, ctrl->intr_regs.intc_intr_enable_base + 4 * ind, iena); + IPROC_READ(d, ctrl->intr_regs.intc_intr_status_base + 4 * ind, stat); + IPROC_READ(d, ctrl->intr_regs.intc_intr_enable_base + 4 * ind, iena); } if (stat & iena) { break; } } - + /* No pending interrupts */ if (ind >= INTC_INTR_REG_NUM) { - return; + return -1; } } } @@ -362,6 +488,11 @@ _cmicx_interrupt(bde_ctrl_t *ctrl) * So as to avoid getting new interrupts until the user level driver * enumerates the interrupts to be serviced */ +#ifdef BDE_EDK_SUPPORT + if (ctrl->edk_irq_enabled) + ret = _cmicx_edk_interrupt_check(ctrl, d); +#endif + for (ind = 0; ind < INTC_INTR_REG_NUM; ind++) { if (fmask && ind == INTC_PDMA_INTR_REG_IND) { continue; @@ -381,17 +512,42 @@ _cmicx_interrupt(bde_ctrl_t *ctrl) HX5_IHOST_IRQ_MASK_OFFSET, ~0); } } else { - WRITE_INTC_INTR(d, ctrl->intr_regs.intc_intr_enable_base + 4*ind, 0); + IPROC_WRITE(d, ctrl->intr_regs.intc_intr_enable_base + (4 * ind), 0); } } - /* Notify */ - atomic_set(&res->intr, 1); + return ret; +} + +static void +_cmicx_interrupt(bde_ctrl_t *ctrl) +{ + bde_inst_resource_t *res; + int ret; + + intr_count++; + + res = &_bde_inst_resource[ctrl->inst]; + ret = _cmicx_interrupt_prepare(ctrl); + if (ret < 0) { + return; + } else if (ret > 0) { + /* Notify */ + atomic_set(&res->edk_intr, 1); #ifdef BDE_LINUX_NON_INTERRUPTIBLE - wake_up(&res->intr_wq); + wake_up(&res->edk_intr_wq); #else - wake_up_interruptible(&res->intr_wq); + wake_up_interruptible(&res->edk_intr_wq); #endif + } else { + /* Notify */ + atomic_set(&res->intr, 1); +#ifdef BDE_LINUX_NON_INTERRUPTIBLE + wake_up(&res->intr_wq); +#else + wake_up_interruptible(&res->intr_wq); +#endif + } } static void @@ -695,25 +851,6 @@ _cmicd_interrupt(bde_ctrl_t *ctrl) #endif } -static void -_bcm88750_interrupt(bde_ctrl_t *ctrl) -{ - int d; - bde_inst_resource_t *res; - - d = (((uint8 *)ctrl - (uint8 *)_devices) / sizeof (bde_ctrl_t)); - res = &_bde_inst_resource[ctrl->inst]; - lkbde_irq_mask_set(d, CMIC_IRQ_MASK, 0, 0); - - lkbde_irq_mask_set(d, CMIC_IRQ_MASK_1, 0, 0); - lkbde_irq_mask_set(d, CMIC_IRQ_MASK_2, 0, 0); - atomic_set(&res->intr, 1); -#ifdef BDE_LINUX_NON_INTERRUPTIBLE - wake_up(&res->intr_wq); -#else - wake_up_interruptible(&res->intr_wq); -#endif -} /* The actual interrupt handler of ethernet devices */ static void @@ -738,7 +875,6 @@ static struct _intr_mode_s { { (isr_f)_cmicm_interrupt, "CMICm" }, { (isr_f)_cmicd_interrupt, "CMICd" }, { (isr_f)_cmicd_cmc0_interrupt, "CMICd CMC0" }, - { (isr_f)_bcm88750_interrupt, "BCM88750" }, { (isr_f)_cmicx_interrupt, "CMICx" }, { NULL, NULL } }; @@ -764,17 +900,31 @@ _intr_regs_init(bde_ctrl_t *ctrl, int hx5_intr) if (hx5_intr) { ctrl->intr_regs.intc_intr_status_base = HX5_INTC_INTR_STATUS_BASE; ctrl->intr_regs.intc_intr_enable_base = HX5_INTC_INTR_ENABLE_BASE; + ctrl->intr_regs.intc_intr_raw_status_base = HX5_INTC_INTR_RAW_STATUS_BASE; ctrl->intr_regs.intc_intr_clear_0 = HX5_PAXB_0_PAXB_IC_INTRCLR_0; ctrl->intr_regs.intc_intr_clear_1 = HX5_PAXB_0_PAXB_IC_INTRCLR_1; ctrl->intr_regs.intc_intr_clear_mode_0 = HX5_PAXB_0_PAXB_IC_INTRCLR_MODE_0; ctrl->intr_regs.intc_intr_clear_mode_1 = HX5_PAXB_0_PAXB_IC_INTRCLR_MODE_1; + ctrl->intr_regs.intc_intr_status = HX5_PAXB_0_PAXB_INTR_STATUS; + ctrl->intr_regs.intc_intr_pacing_ctrl = HX5_PAXB_0_PAXB_IC_INTR_PACING_CTRL; + ctrl->intr_regs.intc_intr_clear_delay_unit = HX5_PAXB_0_PAXB_INTRCLR_DELAY_UNIT; + ctrl->intr_regs.intc_intr_clear_delay_base = HX5_PAXB_0_PAXB_IC_INTRCLR_DELAY_BASE; + ctrl->intr_regs.intc_intr_pcie_err_status = HX5_PAXB_0_PCIE_ERROR_STATUS; + } else { ctrl->intr_regs.intc_intr_status_base = INTC_INTR_STATUS_BASE; + ctrl->intr_regs.intc_intr_raw_status_base = INTC_INTR_RAW_STATUS_BASE; ctrl->intr_regs.intc_intr_enable_base = INTC_INTR_ENABLE_BASE; ctrl->intr_regs.intc_intr_clear_0 = PAXB_0_PAXB_IC_INTRCLR_0; ctrl->intr_regs.intc_intr_clear_1 = PAXB_0_PAXB_IC_INTRCLR_1; ctrl->intr_regs.intc_intr_clear_mode_0 = PAXB_0_PAXB_IC_INTRCLR_MODE_0; ctrl->intr_regs.intc_intr_clear_mode_1 = PAXB_0_PAXB_IC_INTRCLR_MODE_1; + ctrl->intr_regs.intc_intr_status = PAXB_0_PAXB_INTR_STATUS; + ctrl->intr_regs.intc_intr_pacing_ctrl = PAXB_0_PAXB_IC_INTR_PACING_CTRL; + ctrl->intr_regs.intc_intr_clear_delay_unit = PAXB_0_PAXB_INTRCLR_DELAY_UNIT; + ctrl->intr_regs.intc_intr_clear_delay_base = PAXB_0_PAXB_IC_INTRCLR_DELAY_BASE; + ctrl->intr_regs.intc_intr_pcie_err_status = PAXB_0_PCIE_ERROR_STATUS; + } } @@ -804,13 +954,6 @@ _devices_init(int d) } if (ctrl->dev_type & BDE_SWITCH_DEV_TYPE) { switch (user_bde->get_dev(d)->device) { - case BCM88750_DEVICE_ID: - case BCM88753_DEVICE_ID: - case BCM88754_DEVICE_ID: - case BCM88755_DEVICE_ID: - case BCM88752_DEVICE_ID: - ctrl->isr = (isr_f)_bcm88750_interrupt; - break; case BCM53540_DEVICE_ID: case BCM53547_DEVICE_ID: case BCM53548_DEVICE_ID: @@ -894,6 +1037,10 @@ _devices_init(int d) case BCM56276_DEVICE_ID: case BCM56277_DEVICE_ID: case BCM56278_DEVICE_ID: + case BCM56279_DEVICE_ID: + case BCM56575_DEVICE_ID: + case BCM56175_DEVICE_ID: + case BCM56176_DEVICE_ID: ctrl->isr = (isr_f)_cmicx_interrupt; if (ctrl->dev_type & BDE_AXI_DEV_TYPE) { if (!ihost_intr_enable_base) { @@ -944,6 +1091,7 @@ _devices_init(int d) case J2C_DEVICE_ID: case J2C_2ND_DEVICE_ID: case Q2A_DEVICE_ID: + case Q2U_DEVICE_ID: case J2P_DEVICE_ID: #endif #ifdef BCM_DNXF_SUPPORT @@ -974,10 +1122,11 @@ _devices_init(int d) static int _init(void) { - int i; + int i, nof_devices; phys_addr_t cpu_pbase, dma_pbase; ssize_t dmasize; bde_inst_resource_t *res; + uint32 *bitmap_ptr; /* Connect to the kernel bde */ if ((linux_bde_create(NULL, &user_bde) < 0) || user_bde == NULL) { @@ -1002,16 +1151,30 @@ _init(void) res->dma_offset = 0; res->dma_size = _dma_pool.total_size; init_waitqueue_head(&res->intr_wq); + init_waitqueue_head(&res->edk_intr_wq); atomic_set(&res->intr, 0); + atomic_set(&res->edk_intr, 0); ihost_intr_enable_base = NULL; ihost_intr_status_base = NULL; - for (i = 0; i < user_bde->num_devices(BDE_ALL_DEVICES); i++) { - res->inst_id |= (1 << i); + nof_devices = user_bde->num_devices(BDE_ALL_DEVICES); + /* for no BDE instances, mark the single SDK as controlling all devices */ + bitmap_ptr = *lkbde_get_inst_devs(0); + for (i = nof_devices; i >=32; i -= 32) { + *(bitmap_ptr++) = 0xffffffff; + } + *bitmap_ptr = (((uint32)1) << i) - 1; + res->is_active = 1; + + for (i = 0; i < nof_devices; i++) { /* init all devices */ _devices_init(i); } + if (intr_timeout > 0) { + gprintk("Interruptible wait timeout = %d msecs\n", intr_timeout); + } + return 0; } @@ -1036,7 +1199,7 @@ _cleanup(void) BDE_DEV_MEM_MAPPED(_devices[i].dev_type)) { user_bde->interrupt_disconnect(i); } - lkbde_dev_instid_set(i, 0); + lkbde_dev_instid_set(i, BDE_DEV_INST_ID_INVALID); } linux_bde_destroy(user_bde); user_bde = NULL; @@ -1065,48 +1228,53 @@ _cleanup(void) * Always 0 */ static int -_pprint(void) +_pprint(struct seq_file *m) { int idx; const char *name; bde_inst_resource_t *res; uint32 state, instid; - pprintf("Broadcom Device Enumerator (%s)\n", LINUX_USER_BDE_NAME); + pprintf(m, "Broadcom Device Enumerator (%s)\n", LINUX_USER_BDE_NAME); for (idx = 0; idx < user_bde->num_devices(BDE_ALL_DEVICES); idx++) { name = _intr_mode_str(_devices[idx].isr); if (name == NULL) { name = "unknown"; } - pprintf("\t%d: Interrupt mode %s ",idx, name); + pprintf(m, "\t%d: Interrupt mode %s ",idx, name); (void)lkbde_dev_state_get(idx, &state); if (state == BDE_DEV_STATE_REMOVED) { - pprintf(" Device REMOVED ! \n"); + pprintf(m, " Device REMOVED ! \n"); } else { (void)lkbde_dev_instid_get(idx, &instid); - if (instid) { - pprintf("Inst id 0x%x\n",instid); + if (instid != BDE_DEV_INST_ID_INVALID) { + pprintf(m, "Inst id 0x%x\n",instid); } else { - pprintf("\n"); + pprintf(m, "\n"); } } } - pprintf("Instance resource \n"); + pprintf(m, "Instance resource \n"); for (idx = 0; idx < user_bde->num_devices(BDE_ALL_DEVICES); idx++) { res = &_bde_inst_resource[idx]; - if (res->inst_id) { - pprintf("\tDev mask 0x%x : " - "DMA offset %d size %d MB\n", - res->inst_id, + if (res->is_active) { + linux_bde_device_bitmap_t* bitmap_p = lkbde_get_inst_devs(idx); + pprintf(m, "\t%d: DMA offset %d size %d MB Dev mask 0x", + idx, res->dma_offset, res->dma_size); + for (state = 0; state * 32 < user_bde->num_devices(BDE_ALL_DEVICES); ++state) { + pprintf(m,"%.8x ", (*bitmap_p)[state]); + } + pprintf(m,"\n"); } } return 0; } +#ifdef BCM_INSTANCE_SUPPORT /* * Allocate the DMA resource from DMA pool * Parameter : @@ -1127,22 +1295,21 @@ _dma_resource_alloc(unsigned int dma_size, unsigned int *dma_offset) _dma_pool.offset += dma_size; return 0; } +#endif static int -_dma_resource_get(int inst_id, phys_addr_t *cpu_pbase, phys_addr_t *dma_pbase, ssize_t* size) +_dma_resource_get(unsigned inst_id, phys_addr_t *cpu_pbase, phys_addr_t *dma_pbase, ssize_t* size) { - int i; unsigned int dma_size = 0, dma_offset = 0; bde_inst_resource_t *res; - for (i = 0; i < user_bde->num_devices(BDE_ALL_DEVICES); i++) { - res = &_bde_inst_resource[i]; - if (res->inst_id == inst_id) { - dma_size = res->dma_size; - dma_offset = res->dma_offset; - break; - } + if (inst_id >= user_bde->num_devices(BDE_ALL_DEVICES)) { + gprintk("ERROR: requested DMA resources for an instance number out of range: %u\n", inst_id); + return -1; } + res = &_bde_inst_resource[inst_id]; + dma_size = res->dma_size; + dma_offset = res->dma_offset; *cpu_pbase = _dma_pool.cpu_pbase + dma_offset * ONE_MB; *dma_pbase = _dma_pool.dma_pbase + dma_offset * ONE_MB; @@ -1151,28 +1318,49 @@ _dma_resource_get(int inst_id, phys_addr_t *cpu_pbase, phys_addr_t *dma_pbase, s return 0; } +#ifdef BCM_INSTANCE_SUPPORT +/* + * Checks if we have the instance in _bde_inst_resource. If not, return LUBDE_SUCCESS==0 (considered a new instance). + * If it exists with the same dmasize, return 1 (It is considered already in use) + * Otherwise if the device with the same index of the resource, has resource/instance index 0, return LUBDE_SUCCESS==0. (bug) + * Otherwise return LUBDE_FAIL==-1 (It is considered to exist with a different dmasize). + */ static int -_instance_validate(unsigned int inst_id, unsigned int dmasize) +_instance_validate(unsigned int inst_id, unsigned int dmasize, linux_bde_device_bitmap_t inst_devices) { - int i; - bde_inst_resource_t *res; + unsigned i; + uint32 bits; + bde_inst_resource_t *res = _bde_inst_resource + inst_id; + linux_bde_device_bitmap_t* bitmap_p; - for (i = 0; i < user_bde->num_devices(BDE_ALL_DEVICES); i++) { - res = &_bde_inst_resource[i]; - if (res->inst_id == inst_id) { - if (res->dma_size != dmasize) { - if(_devices[i].inst == 0){ - /* Skip _instance_validate (not init yet) */ - return LUBDE_SUCCESS; - } - gprintk("ERROR: dma_size mismatch\n"); - return LUBDE_FAIL; - } - return (1); + if (inst_id >= user_bde->num_devices(BDE_ALL_DEVICES)) { + gprintk("ERROR: instance number out of range: %u\n", inst_id); + return LUBDE_FAIL; + } + + if (res->is_active == 0) { + /* FIXME SDK-225233 check that the devices are not used by another active instance */ + return LUBDE_SUCCESS; + } + + bitmap_p = lkbde_get_inst_devs(inst_id); + for (i = 0; i < LINUX_BDE_NOF_DEVICE_BITMAP_WORDS; ++i) { + bits = inst_devices[i] ^ (*bitmap_p)[i]; + if (bits != 0) { + for (i *= 32; (bits & 1) == 0; bits >>= 1, ++i); + gprintk("ERROR: existing instance number %u does not control the same devices, see device %u\n", inst_id, i); + return LUBDE_FAIL; } } - return LUBDE_SUCCESS; + + if (res->dma_size == dmasize) { + return 1; /* For an existing same instance with the same DMA size, do nothing */ + } + /* with a different DMS size */ + gprintk("ERROR: dma_size mismatch\n"); + return LUBDE_FAIL; } +#endif static int _device_reprobe(void) @@ -1187,33 +1375,49 @@ _device_reprobe(void) return 0; } +#ifdef BCM_INSTANCE_SUPPORT +/* + * Attach an SDK instance: + * _device_reprobe(); + * Check If an instance with the same bitmap exists, if yes with the same dmasize, return, if yes a different dmasize return an error, if no: + * Allocate DMA for the instance. + * This loop finds the first free resource in _bde_inst_resource[] and configure it for the instance. + * Store the resource/instance index in _bde_inst_resource for every device in the instance. + */ static int -_instance_attach(unsigned int inst_id, unsigned int dma_size) +_instance_attach(unsigned int inst_id, unsigned int dma_size, linux_bde_device_bitmap_t inst_devices) { unsigned int dma_offset; int i, exist; bde_inst_resource_t *res; - int inst_idx = -1; - uint32 instid; + uint32 previous_inst_id; /* Reprobe the system for hot-plugged device */ _device_reprobe(); if (debug >= 2) { - gprintk("INFO: Request to attach to instance_id %d with dma size %d!\n", inst_id, dma_size); + gprintk("INFO: Request to attach to instance_id %u with dma size %d!\n", inst_id, dma_size); } spin_lock(&bde_resource_lock); - /* Validate the resource with inst_id */ - exist = _instance_validate(inst_id, dma_size); - if (exist < 0) { + /* If not in multi instance mode, move to the mode and fix the first instance that represented all devices */ + if (_bde_multi_inst == 0) { + _bde_multi_inst = 1; + _bde_inst_resource->is_active = 0; + /*_bde_inst_resource->dev will not be used when _bde_inst_resource->is_active == 0 */ + } + + /* Validate the resource with inst_devices */ + exist = _instance_validate(inst_id, dma_size, inst_devices); + + if (exist == LUBDE_FAIL) { spin_unlock(&bde_resource_lock); return LUBDE_FAIL; } if (exist > 0) { if (debug >= 2) { - gprintk("INFO: Already attached to instance_id %d with dma size %d!\n", inst_id, dma_size); + gprintk("INFO: Already attached to instance_id %u with dma size %d!\n", inst_id, dma_size); } spin_unlock(&bde_resource_lock); return LUBDE_SUCCESS; @@ -1222,38 +1426,59 @@ _instance_attach(unsigned int inst_id, unsigned int dma_size) spin_unlock(&bde_resource_lock); return LUBDE_FAIL; } - for (i = 0; i < user_bde->num_devices(BDE_ALL_DEVICES); i++) { - res = &_bde_inst_resource[i]; - if ((_bde_multi_inst == 0) || (res->inst_id == 0)) { - res->inst_id = inst_id; - res->dma_offset = dma_offset; - res->dma_size = dma_size; - _bde_multi_inst++; - inst_idx = i; - init_waitqueue_head(&res->intr_wq); - atomic_set(&res->intr, 0); - break; - } + + /* configure the instance ID resources */ + res = _bde_inst_resource + inst_id; + res->is_active = 1; + res->dma_offset = dma_offset; + res->dma_size = dma_size; +#ifdef SAI_FIXUP /* SDK-240875 */ + /* skip instance 0, WQ for instance 0 has been initialized in user_bde init, see _init() */ + if (inst_id != 0) { + init_waitqueue_head(&res->intr_wq); + init_waitqueue_head(&res->edk_intr_wq); + atomic_set(&res->intr, 0); + atomic_set(&res->edk_intr, 0); } +#endif + memcpy(*lkbde_get_inst_devs(inst_id), inst_devices, sizeof(linux_bde_device_bitmap_t)); /* SDK-225233 */ + /* store the resource/instance index in _bde_inst_resource for every device in the instance */ for (i = 0; i < user_bde->num_devices(BDE_ALL_DEVICES); i++) { - if (inst_id & (1 << i)) { - _devices[i].inst = inst_idx; - /* Pass the instid to the kernel BDE */ - if (lkbde_dev_instid_get(i, &instid) == 0) { - if (!instid) { + if (inst_devices[i / 32] & (1 << (i % 32))) { + _devices[i].inst = inst_id; + /* Pass the inst_id to the kernel BDE */ + if (lkbde_dev_instid_get(i, &previous_inst_id) == 0) { /* If the linux-kernel-bde inst_id is not set for the device, set it to the instance ID */ + if (previous_inst_id == BDE_DEV_INST_ID_INVALID) { lkbde_dev_instid_set(i, inst_id); } - } + } /* TODO handle the case where the device is marked belonging to a different instance */ } } spin_unlock(&bde_resource_lock); if (debug >= 2) { - gprintk("INFO: Attached to instance_id %d with dma size %d! SUCCESS\n", inst_id, dma_size); + gprintk("INFO: Attached to instance_id %lu with dma size %d! SUCCESS\n", (unsigned long)inst_devices, dma_size); } return LUBDE_SUCCESS; } +#endif /* BCM_INSTANCE_SUPPORT */ + +#ifdef BDE_EDK_SUPPORT +static int +_edk_instance_attach(unsigned int inst_id, unsigned int dma_size) +{ + ssize_t size = (ssize_t)dma_size; + if (size) { + lkbde_edk_get_dma_info(inst_id, NULL, NULL, &size); + if (!size) { + gprintk("Error: EDK Attached to instance_id %lu failed\n", (unsigned long)inst_id); + return LUBDE_FAIL; + } + } + return LUBDE_SUCCESS; +} +#endif /* * Function: _ioctl @@ -1273,7 +1498,7 @@ _ioctl(unsigned int cmd, unsigned long arg) phys_addr_t cpu_pbase, dma_pbase; ssize_t size; const ibde_dev_t *bde_dev; - int inst_id; + int inst_id, idx; bde_inst_resource_t *res; uint32_t *mapaddr; @@ -1341,10 +1566,19 @@ _ioctl(unsigned int cmd, unsigned long arg) case LUBDE_GET_DMA_INFO: inst_id = io.dev; if (_bde_multi_inst){ - _dma_resource_get(inst_id, &cpu_pbase, &dma_pbase, &size); + if (_dma_resource_get(inst_id, &cpu_pbase, &dma_pbase, &size)) { + io.rc = LUBDE_FAIL; + } } else { lkbde_get_dma_info(&cpu_pbase, &dma_pbase, &size); } +#ifdef BDE_EDK_SUPPORT + case LUBDE_GET_EDK_DMA_INFO: + if (cmd == LUBDE_GET_EDK_DMA_INFO) { + inst_id = io.dev; + lkbde_edk_get_dma_info(inst_id, &cpu_pbase, &dma_pbase, &size); + } +#endif io.d0 = dma_pbase; io.d1 = size; /* Optionally enable DMA mmap via /dev/linux-kernel-bde */ @@ -1365,14 +1599,6 @@ _ioctl(unsigned int cmd, unsigned long arg) } if (_devices[io.dev].dev_type & BDE_SWITCH_DEV_TYPE) { if (_devices[io.dev].isr && !_devices[io.dev].enabled) { - bde_ctrl_t *ctrl; - ctrl = &_devices[io.dev]; - if ((ctrl->isr == (isr_f)_cmicx_interrupt) && - (ctrl->dev_type & BDE_PCI_DEV_TYPE)) { - /* Set MSI mode to SW clear vs auto clear */ - WRITE_INTC_INTR(io.dev, ctrl->intr_regs.intc_intr_clear_mode_0, 0x0); - WRITE_INTC_INTR(io.dev, ctrl->intr_regs.intc_intr_clear_mode_1, 0x0); - } user_bde->interrupt_connect(io.dev, _devices[io.dev].isr, _devices+io.dev); @@ -1398,6 +1624,32 @@ _ioctl(unsigned int cmd, unsigned long arg) _devices[io.dev].enabled = 0; } break; + case LUBDE_SET_EDK_INTERRUPTS: + if (!VALID_DEVICE(io.dev)) { + return -EINVAL; + } + res = &_bde_inst_resource[_devices[io.dev].inst]; + res->edk_irqs.timer_intrc_offset = io.d0; + res->edk_irqs.timer_intrc_mask = io.d1; + res->edk_irqs.sw_intr_intrc_offset = io.d2; + res->edk_irqs.sw_intr_intrc_mask = io.d3; + res->edk_irqs.sw_intr_src_bitmap = io.dx.dw[0]; + for (idx = 0; idx < MAX_UC_CORES; idx++) { + res->edk_irqs.sw_intr_icfg_reg[idx] = io.dx.dw[idx + 1]; + } + break; + case LUBDE_ENABLE_EDK_INTERRUPTS: + if (!VALID_DEVICE(io.dev)) { + return -EINVAL; + } + _devices[io.dev].edk_irq_enabled = 1; + break; + case LUBDE_DISABLE_EDK_INTERRUPTS: + if (!VALID_DEVICE(io.dev)) { + return -EINVAL; + } + _devices[io.dev].edk_irq_enabled = 0; + break; case LUBDE_WAIT_FOR_INTERRUPT: if (!VALID_DEVICE(io.dev)) { return -EINVAL; @@ -1409,8 +1661,34 @@ _ioctl(unsigned int cmd, unsigned long arg) atomic_read(&res->intr) != 0, 100); #else - wait_event_interruptible(res->intr_wq, - atomic_read(&res->intr) != 0); + /* CMICX Devices */ + if ((_devices[io.dev].dev_type & BDE_PCI_DEV_TYPE) && + (_devices[io.dev].isr == (isr_f)_cmicx_interrupt) && + (intr_timeout > 0)) { + unsigned long t_jiffies; + int err=0; + t_jiffies = msecs_to_jiffies(intr_timeout); + err = wait_event_interruptible_timeout(res->intr_wq, + atomic_read(&res->intr) != 0, + t_jiffies); + /* Timeout happend and condition not set */ + if (err == 0) { + bde_ctrl_t *ctrl; + ctrl = &_devices[io.dev]; + intr_timeout_count++; + if (debug >= 1) { + gprintk("Timeout happend and condition not set\n"); + } + dump_interrupt_regs(ctrl, io.dev); + } else if (err == -ERESTARTSYS) { + if (debug >= 1) { + gprintk("Interrupted by Signal\n"); + } + } + } else { + wait_event_interruptible(res->intr_wq, + atomic_read(&res->intr) != 0); + } #endif /* * Even if we get multiple interrupts, we @@ -1424,14 +1702,56 @@ _ioctl(unsigned int cmd, unsigned long arg) #else wait_event_interruptible(_ether_interrupt_wq, atomic_read(&_ether_interrupt_has_taken_place) != 0); + #endif /* - * Even if we get multiple interrupts, we + * Even if we get multiple interrupts, we * only run the interrupt handler once. */ atomic_set(&_ether_interrupt_has_taken_place, 0); } break; + case LUBDE_WAIT_FOR_EDK_INTERRUPT: + if (!VALID_DEVICE(io.dev)) { + return -EINVAL; + } + res = &_bde_inst_resource[_devices[io.dev].inst]; +#ifdef BDE_LINUX_NON_INTERRUPTIBLE + wait_event_timeout(res->edk_intr_wq, + atomic_read(&res->edk_intr) != 0, 100); + +#else + /* CMICX Devices */ + if ((_devices[io.dev].dev_type & BDE_PCI_DEV_TYPE) && + (_devices[io.dev].isr == (isr_f)_cmicx_interrupt) && + (intr_timeout > 0)) { + unsigned long t_jiffies; + int err = 0; + t_jiffies = msecs_to_jiffies(intr_timeout); + err = wait_event_interruptible_timeout(res->edk_intr_wq, + atomic_read(&res->edk_intr) != 0, t_jiffies); + /* Timeout happend and condition not set */ + if (err == 0) { + bde_ctrl_t *ctrl; + ctrl = &_devices[io.dev]; + intr_timeout_count++; + if (debug >= 1) { + gprintk("EDK Interrrupt: Timeout happened\n"); + } + dump_interrupt_regs(ctrl, io.dev); + } else if (err == -ERESTARTSYS) { + if (debug >= 1) { + gprintk("EDK Interrrupt: Interrupted by Signal\n"); + } + } + } else { + wait_event_interruptible(res->edk_intr_wq, atomic_read(&res->edk_intr) != 0); + } +#endif + /* Even if we get multiple interrupts, we + * only run the interrupt handler once. */ + atomic_set(&res->edk_intr, 0); + break; case LUBDE_USLEEP: case LUBDE_UDELAY: case LUBDE_SEM_OP: @@ -1487,7 +1807,7 @@ _ioctl(unsigned int cmd, unsigned long arg) if (BDE_DEV_MEM_MAPPED(_devices[io.dev].dev_type)) { /* Get physical address to map */ io.rc = lkbde_get_dev_resource(io.dev, io.d0, - &io.d1, &io.d2, &io.d3); + &io.d2, &io.d3, &io.d1); } } else { io.rc = LUBDE_FAIL; @@ -1517,9 +1837,16 @@ _ioctl(unsigned int cmd, unsigned long arg) io.rc = LUBDE_FAIL; } break; +#ifdef BDE_EDK_SUPPORT + case LUBDE_ATTACH_EDK_INSTANCE: + io.rc = _edk_instance_attach(io.d0, io.d1); + break; +#endif +#ifdef BCM_INSTANCE_SUPPORT case LUBDE_ATTACH_INSTANCE: - io.rc = _instance_attach(io.d0, io.d1); + io.rc = _instance_attach(io.d0, io.d1, io.dx.dw); break; +#endif case LUBDE_GET_DEVICE_STATE: io.rc = lkbde_dev_state_get(io.dev, &io.d0); break; diff --git a/platform/broadcom/saibcm-modules/systems/bde/linux/user/kernel/linux-user-bde.h b/platform/broadcom/saibcm-modules/systems/bde/linux/user/kernel/linux-user-bde.h index 535ccac9fad..4bd4b746c52 100644 --- a/platform/broadcom/saibcm-modules/systems/bde/linux/user/kernel/linux-user-bde.h +++ b/platform/broadcom/saibcm-modules/systems/bde/linux/user/kernel/linux-user-bde.h @@ -1,5 +1,10 @@ /* - * Copyright 2017 Broadcom + * Copyright 2007-2020 Broadcom Inc. All rights reserved. + * + * Permission is granted to use, copy, modify and/or distribute this + * software under either one of the licenses below. + * + * License Option 1: GPL * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License, version 2, as @@ -12,6 +17,12 @@ * * You should have received a copy of the GNU General Public License * version 2 (GPLv2) along with this source code. + * + * + * License Option 2: Broadcom Open Network Switch APIs (OpenNSA) license + * + * This software is governed by the Broadcom Open Network Switch APIs license: + * https://www.broadcom.com/products/ethernet-connectivity/software/opennsa */ /* * $Id: linux-user-bde.h,v 1.23 Broadcom SDK $ @@ -45,7 +56,7 @@ typedef struct { unsigned int d3; bde_kernel_addr_t p0; union { - unsigned int dw[2]; + uint32_t dw[16]; unsigned char buf[64]; } dx; } lubde_ioctl_t; @@ -54,34 +65,41 @@ typedef struct { /* LUBDE ioctls */ #define LUBDE_MAGIC 'L' -#define LUBDE_VERSION _IO(LUBDE_MAGIC, 0) -#define LUBDE_GET_NUM_DEVICES _IO(LUBDE_MAGIC, 1) -#define LUBDE_GET_DEVICE _IO(LUBDE_MAGIC, 2) -#define LUBDE_PCI_CONFIG_PUT32 _IO(LUBDE_MAGIC, 3) -#define LUBDE_PCI_CONFIG_GET32 _IO(LUBDE_MAGIC, 4) -#define LUBDE_GET_DMA_INFO _IO(LUBDE_MAGIC, 5) -#define LUBDE_ENABLE_INTERRUPTS _IO(LUBDE_MAGIC, 6) -#define LUBDE_DISABLE_INTERRUPTS _IO(LUBDE_MAGIC, 7) -#define LUBDE_USLEEP _IO(LUBDE_MAGIC, 8) -#define LUBDE_WAIT_FOR_INTERRUPT _IO(LUBDE_MAGIC, 9) -#define LUBDE_SEM_OP _IO(LUBDE_MAGIC, 10) -#define LUBDE_UDELAY _IO(LUBDE_MAGIC, 11) -#define LUBDE_GET_DEVICE_TYPE _IO(LUBDE_MAGIC, 12) -#define LUBDE_SPI_READ_REG _IO(LUBDE_MAGIC, 13) -#define LUBDE_SPI_WRITE_REG _IO(LUBDE_MAGIC, 14) -#define LUBDE_READ_REG_16BIT_BUS _IO(LUBDE_MAGIC, 19) -#define LUBDE_WRITE_REG_16BIT_BUS _IO(LUBDE_MAGIC, 20) -#define LUBDE_GET_BUS_FEATURES _IO(LUBDE_MAGIC, 21) -#define LUBDE_WRITE_IRQ_MASK _IO(LUBDE_MAGIC, 22) -#define LUBDE_CPU_WRITE_REG _IO(LUBDE_MAGIC, 23) -#define LUBDE_CPU_READ_REG _IO(LUBDE_MAGIC, 24) -#define LUBDE_CPU_PCI_REGISTER _IO(LUBDE_MAGIC, 25) -#define LUBDE_DEV_RESOURCE _IO(LUBDE_MAGIC, 26) -#define LUBDE_IPROC_READ_REG _IO(LUBDE_MAGIC, 27) -#define LUBDE_IPROC_WRITE_REG _IO(LUBDE_MAGIC, 28) -#define LUBDE_ATTACH_INSTANCE _IO(LUBDE_MAGIC, 29) -#define LUBDE_GET_DEVICE_STATE _IO(LUBDE_MAGIC, 30) -#define LUBDE_REPROBE _IO(LUBDE_MAGIC, 31) +#define LUBDE_VERSION _IO(LUBDE_MAGIC, 0) +#define LUBDE_GET_NUM_DEVICES _IO(LUBDE_MAGIC, 1) +#define LUBDE_GET_DEVICE _IO(LUBDE_MAGIC, 2) +#define LUBDE_PCI_CONFIG_PUT32 _IO(LUBDE_MAGIC, 3) +#define LUBDE_PCI_CONFIG_GET32 _IO(LUBDE_MAGIC, 4) +#define LUBDE_GET_DMA_INFO _IO(LUBDE_MAGIC, 5) +#define LUBDE_ENABLE_INTERRUPTS _IO(LUBDE_MAGIC, 6) +#define LUBDE_DISABLE_INTERRUPTS _IO(LUBDE_MAGIC, 7) +#define LUBDE_USLEEP _IO(LUBDE_MAGIC, 8) +#define LUBDE_WAIT_FOR_INTERRUPT _IO(LUBDE_MAGIC, 9) +#define LUBDE_SEM_OP _IO(LUBDE_MAGIC, 10) +#define LUBDE_UDELAY _IO(LUBDE_MAGIC, 11) +#define LUBDE_GET_DEVICE_TYPE _IO(LUBDE_MAGIC, 12) +#define LUBDE_SPI_READ_REG _IO(LUBDE_MAGIC, 13) +#define LUBDE_SPI_WRITE_REG _IO(LUBDE_MAGIC, 14) +#define LUBDE_READ_REG_16BIT_BUS _IO(LUBDE_MAGIC, 19) +#define LUBDE_WRITE_REG_16BIT_BUS _IO(LUBDE_MAGIC, 20) +#define LUBDE_GET_BUS_FEATURES _IO(LUBDE_MAGIC, 21) +#define LUBDE_WRITE_IRQ_MASK _IO(LUBDE_MAGIC, 22) +#define LUBDE_CPU_WRITE_REG _IO(LUBDE_MAGIC, 23) +#define LUBDE_CPU_READ_REG _IO(LUBDE_MAGIC, 24) +#define LUBDE_CPU_PCI_REGISTER _IO(LUBDE_MAGIC, 25) +#define LUBDE_DEV_RESOURCE _IO(LUBDE_MAGIC, 26) +#define LUBDE_IPROC_READ_REG _IO(LUBDE_MAGIC, 27) +#define LUBDE_IPROC_WRITE_REG _IO(LUBDE_MAGIC, 28) +#define LUBDE_ATTACH_INSTANCE _IO(LUBDE_MAGIC, 29) +#define LUBDE_GET_DEVICE_STATE _IO(LUBDE_MAGIC, 30) +#define LUBDE_REPROBE _IO(LUBDE_MAGIC, 31) +#define LUBDE_SET_EDK_INTERRUPTS _IO(LUBDE_MAGIC, 32) +#define LUBDE_ENABLE_EDK_INTERRUPTS _IO(LUBDE_MAGIC, 33) +#define LUBDE_DISABLE_EDK_INTERRUPTS _IO(LUBDE_MAGIC, 34) +#define LUBDE_WAIT_FOR_EDK_INTERRUPT _IO(LUBDE_MAGIC, 35) +#define LUBDE_ATTACH_EDK_INSTANCE _IO(LUBDE_MAGIC, 36) +#define LUBDE_GET_EDK_DMA_INFO _IO(LUBDE_MAGIC, 37) + #define LUBDE_SEM_OP_CREATE 1 #define LUBDE_SEM_OP_DESTROY 2 diff --git a/platform/broadcom/saibcm-modules/systems/bde/shared/include/shbde.h b/platform/broadcom/saibcm-modules/systems/bde/shared/include/shbde.h index 53003a40ce5..2d0651191fb 100644 --- a/platform/broadcom/saibcm-modules/systems/bde/shared/include/shbde.h +++ b/platform/broadcom/saibcm-modules/systems/bde/shared/include/shbde.h @@ -1,5 +1,10 @@ /* - * Copyright 2017 Broadcom + * Copyright 2007-2020 Broadcom Inc. All rights reserved. + * + * Permission is granted to use, copy, modify and/or distribute this + * software under either one of the licenses below. + * + * License Option 1: GPL * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License, version 2, as @@ -12,6 +17,12 @@ * * You should have received a copy of the GNU General Public License * version 2 (GPLv2) along with this source code. + * + * + * License Option 2: Broadcom Open Network Switch APIs (OpenNSA) license + * + * This software is governed by the Broadcom Open Network Switch APIs license: + * https://www.broadcom.com/products/ethernet-connectivity/software/opennsa */ /* * $Id: $ diff --git a/platform/broadcom/saibcm-modules/systems/bde/shared/include/shbde_iproc.h b/platform/broadcom/saibcm-modules/systems/bde/shared/include/shbde_iproc.h index 4b614ba5313..4b71b8f16ee 100644 --- a/platform/broadcom/saibcm-modules/systems/bde/shared/include/shbde_iproc.h +++ b/platform/broadcom/saibcm-modules/systems/bde/shared/include/shbde_iproc.h @@ -1,5 +1,10 @@ /* - * Copyright 2017 Broadcom + * Copyright 2007-2020 Broadcom Inc. All rights reserved. + * + * Permission is granted to use, copy, modify and/or distribute this + * software under either one of the licenses below. + * + * License Option 1: GPL * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License, version 2, as @@ -12,6 +17,12 @@ * * You should have received a copy of the GNU General Public License * version 2 (GPLv2) along with this source code. + * + * + * License Option 2: Broadcom Open Network Switch APIs (OpenNSA) license + * + * This software is governed by the Broadcom Open Network Switch APIs license: + * https://www.broadcom.com/products/ethernet-connectivity/software/opennsa */ /* * $Id: $ diff --git a/platform/broadcom/saibcm-modules/systems/bde/shared/include/shbde_mdio.h b/platform/broadcom/saibcm-modules/systems/bde/shared/include/shbde_mdio.h index 5f8fa63533f..a51dd2ac6f5 100644 --- a/platform/broadcom/saibcm-modules/systems/bde/shared/include/shbde_mdio.h +++ b/platform/broadcom/saibcm-modules/systems/bde/shared/include/shbde_mdio.h @@ -1,5 +1,10 @@ /* - * Copyright 2017 Broadcom + * Copyright 2007-2020 Broadcom Inc. All rights reserved. + * + * Permission is granted to use, copy, modify and/or distribute this + * software under either one of the licenses below. + * + * License Option 1: GPL * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License, version 2, as @@ -12,6 +17,12 @@ * * You should have received a copy of the GNU General Public License * version 2 (GPLv2) along with this source code. + * + * + * License Option 2: Broadcom Open Network Switch APIs (OpenNSA) license + * + * This software is governed by the Broadcom Open Network Switch APIs license: + * https://www.broadcom.com/products/ethernet-connectivity/software/opennsa */ /* * $Id: $ diff --git a/platform/broadcom/saibcm-modules/systems/bde/shared/include/shbde_pci.h b/platform/broadcom/saibcm-modules/systems/bde/shared/include/shbde_pci.h index 1f045d7b02c..a0b88494823 100644 --- a/platform/broadcom/saibcm-modules/systems/bde/shared/include/shbde_pci.h +++ b/platform/broadcom/saibcm-modules/systems/bde/shared/include/shbde_pci.h @@ -1,5 +1,10 @@ /* - * Copyright 2017 Broadcom + * Copyright 2007-2020 Broadcom Inc. All rights reserved. + * + * Permission is granted to use, copy, modify and/or distribute this + * software under either one of the licenses below. + * + * License Option 1: GPL * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License, version 2, as @@ -12,6 +17,12 @@ * * You should have received a copy of the GNU General Public License * version 2 (GPLv2) along with this source code. + * + * + * License Option 2: Broadcom Open Network Switch APIs (OpenNSA) license + * + * This software is governed by the Broadcom Open Network Switch APIs license: + * https://www.broadcom.com/products/ethernet-connectivity/software/opennsa */ /* * $Id: $ diff --git a/platform/broadcom/saibcm-modules/systems/bde/shared/shbde_iproc.c b/platform/broadcom/saibcm-modules/systems/bde/shared/shbde_iproc.c index 087720a20a8..ca8024c78a3 100644 --- a/platform/broadcom/saibcm-modules/systems/bde/shared/shbde_iproc.c +++ b/platform/broadcom/saibcm-modules/systems/bde/shared/shbde_iproc.c @@ -1,5 +1,10 @@ /* - * Copyright 2017 Broadcom + * Copyright 2007-2020 Broadcom Inc. All rights reserved. + * + * Permission is granted to use, copy, modify and/or distribute this + * software under either one of the licenses below. + * + * License Option 1: GPL * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License, version 2, as @@ -12,6 +17,12 @@ * * You should have received a copy of the GNU General Public License * version 2 (GPLv2) along with this source code. + * + * + * License Option 2: Broadcom Open Network Switch APIs (OpenNSA) license + * + * This software is governed by the Broadcom Open Network Switch APIs license: + * https://www.broadcom.com/products/ethernet-connectivity/software/opennsa */ /* * $Id: $ @@ -292,12 +303,19 @@ shbde_iproc_paxb_init(shbde_hal_t *shbde, void *iproc_regs, /* Configure MSIX interrupt page, need for iproc ver 0x10 and 0x12 */ if ((icfg->use_msi == 2) && - ((icfg->iproc_ver == 0x10) || (icfg->iproc_ver == 0x12))){ + ((icfg->iproc_ver == 0x10) + || (icfg->iproc_ver == 0x12) + || (icfg->iproc_ver == 0x11))){ unsigned int mask = (0x1 << PAXB_0_FUNC0_IMAP1_3_ADDR_SHIFT) - 1; reg = ROFFS(iproc_regs, PAXB_0_FUNC0_IMAP1_3); data = iproc32_read(shbde, reg); data &= mask; - data |= 0x410 << PAXB_0_FUNC0_IMAP1_3_ADDR_SHIFT; + if (icfg->iproc_ver == 0x11) { + data |= 0x400 << PAXB_0_FUNC0_IMAP1_3_ADDR_SHIFT; + } else { + data |= 0x410 << PAXB_0_FUNC0_IMAP1_3_ADDR_SHIFT; + } + iproc32_write(shbde, reg, data); } diff --git a/platform/broadcom/saibcm-modules/systems/bde/shared/shbde_mdio.c b/platform/broadcom/saibcm-modules/systems/bde/shared/shbde_mdio.c index ef4a72071b3..1e38eb024ad 100644 --- a/platform/broadcom/saibcm-modules/systems/bde/shared/shbde_mdio.c +++ b/platform/broadcom/saibcm-modules/systems/bde/shared/shbde_mdio.c @@ -1,5 +1,10 @@ /* - * Copyright 2017 Broadcom + * Copyright 2007-2020 Broadcom Inc. All rights reserved. + * + * Permission is granted to use, copy, modify and/or distribute this + * software under either one of the licenses below. + * + * License Option 1: GPL * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License, version 2, as @@ -12,6 +17,12 @@ * * You should have received a copy of the GNU General Public License * version 2 (GPLv2) along with this source code. + * + * + * License Option 2: Broadcom Open Network Switch APIs (OpenNSA) license + * + * This software is governed by the Broadcom Open Network Switch APIs license: + * https://www.broadcom.com/products/ethernet-connectivity/software/opennsa */ /* * $Id: $ diff --git a/platform/broadcom/saibcm-modules/systems/bde/shared/shbde_pci.c b/platform/broadcom/saibcm-modules/systems/bde/shared/shbde_pci.c index 5cc46d0d463..8e64b475a41 100644 --- a/platform/broadcom/saibcm-modules/systems/bde/shared/shbde_pci.c +++ b/platform/broadcom/saibcm-modules/systems/bde/shared/shbde_pci.c @@ -1,5 +1,10 @@ /* - * Copyright 2017 Broadcom + * Copyright 2007-2020 Broadcom Inc. All rights reserved. + * + * Permission is granted to use, copy, modify and/or distribute this + * software under either one of the licenses below. + * + * License Option 1: GPL * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License, version 2, as @@ -12,6 +17,12 @@ * * You should have received a copy of the GNU General Public License * version 2 (GPLv2) along with this source code. + * + * + * License Option 2: Broadcom Open Network Switch APIs (OpenNSA) license + * + * This software is governed by the Broadcom Open Network Switch APIs license: + * https://www.broadcom.com/products/ethernet-connectivity/software/opennsa */ /* * $Id: $ diff --git a/platform/broadcom/saibcm-modules/systems/linux/kernel/modules/Makefile b/platform/broadcom/saibcm-modules/systems/linux/kernel/modules/Makefile index 448b4b9a931..b599580ae86 100644 --- a/platform/broadcom/saibcm-modules/systems/linux/kernel/modules/Makefile +++ b/platform/broadcom/saibcm-modules/systems/linux/kernel/modules/Makefile @@ -1,5 +1,10 @@ # -# Copyright 2017 Broadcom +# Copyright 2007-2020 Broadcom Inc. All rights reserved. +# +# Permission is granted to use, copy, modify and/or distribute this +# software under either one of the licenses below. +# +# License Option 1: GPL # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License, version 2, as @@ -12,6 +17,12 @@ # # You should have received a copy of the GNU General Public License # version 2 (GPLv2) along with this source code. +# +# +# License Option 2: Broadcom Open Network Switch APIs (OpenNSA) license +# +# This software is governed by the Broadcom Open Network Switch APIs license: +# https://www.broadcom.com/products/ethernet-connectivity/software/opennsa # # -*- Makefile -*- # $Id: Makefile,v 1.10 Broadcom SDK $ diff --git a/platform/broadcom/saibcm-modules/systems/linux/kernel/modules/bcm-knet/Makefile b/platform/broadcom/saibcm-modules/systems/linux/kernel/modules/bcm-knet/Makefile index a3f430a6a90..9879be69b0b 100644 --- a/platform/broadcom/saibcm-modules/systems/linux/kernel/modules/bcm-knet/Makefile +++ b/platform/broadcom/saibcm-modules/systems/linux/kernel/modules/bcm-knet/Makefile @@ -1,5 +1,10 @@ # -# Copyright 2017 Broadcom +# Copyright 2007-2020 Broadcom Inc. All rights reserved. +# +# Permission is granted to use, copy, modify and/or distribute this +# software under either one of the licenses below. +# +# License Option 1: GPL # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License, version 2, as @@ -12,6 +17,12 @@ # # You should have received a copy of the GNU General Public License # version 2 (GPLv2) along with this source code. +# +# +# License Option 2: Broadcom Open Network Switch APIs (OpenNSA) license +# +# This software is governed by the Broadcom Open Network Switch APIs license: +# https://www.broadcom.com/products/ethernet-connectivity/software/opennsa # # -*- Makefile -*- # $Id: Makefile,v 1.3 Broadcom SDK $ diff --git a/platform/broadcom/saibcm-modules/systems/linux/kernel/modules/bcm-knet/bcm-knet.c b/platform/broadcom/saibcm-modules/systems/linux/kernel/modules/bcm-knet/bcm-knet.c index a9eda27ad4d..a3f92b17584 100644 --- a/platform/broadcom/saibcm-modules/systems/linux/kernel/modules/bcm-knet/bcm-knet.c +++ b/platform/broadcom/saibcm-modules/systems/linux/kernel/modules/bcm-knet/bcm-knet.c @@ -60,10 +60,6 @@ #include #include -#if LINUX_VERSION_CODE <= KERNEL_VERSION(3,16,0) -#include -#endif - #include #include #include @@ -222,6 +218,7 @@ MODULE_PARM_DESC(ft_vid, #define DBG_LVL_DCB_RX 0x20000 #define DBG_LVL_PDMP_TX 0x40000 #define DBG_LVL_PDMP_RX 0x80000 +#define DBG_LVL_PTP 0x100000 #define DBG_VERB(_s) do { if (debug & DBG_LVL_VERB) gprintk _s; } while (0) #define DBG_PKT(_s) do { if (debug & DBG_LVL_PKT) gprintk _s; } while (0) @@ -245,6 +242,7 @@ MODULE_PARM_DESC(ft_vid, #define DBG_DCB(_s) do { if (debug & (DBG_LVL_DCB|DBG_LVL_DCB_TX| \ DBG_LVL_DCB_RX)) \ gprintk _s; } while (0) +#define DBG_PTP(_s) do { if (debug & DBG_LVL_PTP) gprintk _s; } while (0) /* This flag is used to indicate if debugging packet function is open or closed */ @@ -499,6 +497,12 @@ static inline void bkn_skb_tx_timestamp(struct sk_buff *skb) #define BKN_DMA_MAPPING_ERROR(d,a) bkn_pci_dma_mapping_error(d,a) #endif +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,29)) +#define BKN_NETDEV_TX_BUSY NETDEV_TX_BUSY +#else +#define BKN_NETDEV_TX_BUSY 1 +#endif + /* * Get a 16-bit value from packet offset * _data Pointer to packet @@ -672,6 +676,8 @@ typedef struct bkn_switch_info_s { } rx[NUM_RX_CHAN]; } bkn_switch_info_t; +#define INVALID_INSTANCE_ID BDE_DEV_INST_ID_INVALID + /* 0x1 - Jericho 2 mode */ #define BKN_DNX_JR2_MODE 1 /* PTCH_2 */ @@ -936,13 +942,6 @@ typedef struct bkn_filter_s { kcom_filter_t kf; } bkn_filter_t; -#ifdef SAI_FIXUP /* SDK-224448 */ -#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,29)) -#define BKN_NETDEV_TX_BUSY NETDEV_TX_BUSY -#else -#define BKN_NETDEV_TX_BUSY 1 -#endif -#endif /* SDK-224448 */ /* * Multiple instance support in KNET @@ -1071,6 +1070,7 @@ bkn_sleep(int clicks) #define DEV_IS_CMICX(_sinfo) ((_sinfo)->cmic_type == 'x') #define DEV_IS_CMICM(_sinfo) ((_sinfo)->cmic_type == 'm') +#define DEV_IS_CMIC(_sinfo) ((_sinfo)->cmic_type != 0) #define CDMA_CH(_d, _ch) ((_d)->cdma_channels & (1 << (_ch))) /* @@ -2125,12 +2125,13 @@ bkn_api_rx_chain_done(bkn_switch_info_t *sinfo, int chan) static int bkn_api_rx_copy_from_skb(bkn_switch_info_t *sinfo, - int chan, bkn_desc_info_t *desc) + int chan, bkn_desc_info_t *desc, int rx_hwts) { bkn_dcb_chain_t *dcb_chain; uint32_t *dcb; uint32_t dcb_stat; uint8_t *pkt; + uint8_t *skb_pkt; uint64_t pkt_dma; int pktlen; int i; @@ -2168,8 +2169,18 @@ bkn_api_rx_copy_from_skb(bkn_switch_info_t *sinfo, return -1; } + skb_pkt = desc->skb->data; + + /* Strip custom header from KNETSync packets. */ + if ((rx_hwts) && + ((skb_pkt[0] == 'B') && (skb_pkt[1] == 'C') && + (skb_pkt[2] == 'M') && (skb_pkt[3] == 'C'))) { + + skb_pkt = skb_pkt + skb_pkt[4]; + } + /* Copy packet data */ - memcpy(pkt, desc->skb->data, pktlen); + memcpy(pkt, skb_pkt, pktlen); /* Copy packet metadata and mark as done */ if (sinfo->cmic_type != 'x') { @@ -2235,11 +2246,11 @@ bkn_rx_refill(bkn_switch_info_t *sinfo, int chan) while (sinfo->rx[chan].free < MAX_RX_DCBS) { desc = &sinfo->rx[chan].desc[sinfo->rx[chan].cur]; if (desc->skb == NULL) { - skb = dev_alloc_skb(rx_buffer_size + RCPU_RX_ENCAP_SIZE); + skb = dev_alloc_skb(rx_buffer_size + SKB_DATA_ALIGN(resv_size)); if (skb == NULL) { break; } - skb_reserve(skb, resv_size); + skb_reserve(skb, SKB_DATA_ALIGN(resv_size)); desc->skb = skb; } else { DBG_DCB_RX(("Refill Rx%d SKB in DCB %d recycled.\n", @@ -3832,6 +3843,11 @@ bkn_do_skb_rx(bkn_switch_info_t *sinfo, int chan, int budget) while (dcbs_done < budget) { char str[32]; + + if (!sinfo->rx[chan].running) { + /* DCBs might be cleaned up when bkn_knet_hw_reset is triggered. */ + return 0; + } sprintf(str, "Rx DCB (%d)", sinfo->rx[chan].dirty); desc = &sinfo->rx[chan].desc[sinfo->rx[chan].dirty]; dcb = desc->dcb_mem; @@ -3850,6 +3866,12 @@ bkn_do_skb_rx(bkn_switch_info_t *sinfo, int chan, int budget) sinfo->rx[chan].pkts++; skb = desc->skb; + DBG_DCB_RX(("Rx%d SKB DMA done (%d).\n", chan, sinfo->rx[chan].dirty)); + BKN_DMA_UNMAP_SINGLE(sinfo->dma_dev, + desc->skb_dma, desc->dma_size, + BKN_DMA_FROMDEV); + desc->skb_dma = 0; + if (device_is_sand(sinfo)) { err_woff = BKN_SAND_SCRATCH_DATA_SIZE - 1; sand_scratch_data[err_woff] = dcb[sinfo->dcb_wsize-1]; @@ -3868,11 +3890,6 @@ bkn_do_skb_rx(bkn_switch_info_t *sinfo, int chan, int budget) pktlen = dcb[sinfo->dcb_wsize-1] & 0xffff; priv = netdev_priv(sinfo->dev); - DBG_DCB_RX(("Rx%d SKB DMA done (%d).\n", chan, sinfo->rx[chan].dirty)); - BKN_DMA_UNMAP_SINGLE(sinfo->dma_dev, - desc->skb_dma, desc->dma_size, - BKN_DMA_FROMDEV); - desc->skb_dma = 0; bkn_dump_pkt(skb->data, pktlen, XGS_DMA_RX_CHAN); if (device_is_sand(sinfo)) { @@ -3945,7 +3962,7 @@ bkn_do_skb_rx(bkn_switch_info_t *sinfo, int chan, int budget) case KCOM_DEST_T_API: DBG_FLTR(("Send to Rx API\n")); sinfo->rx[chan].pkts_f_api++; - bkn_api_rx_copy_from_skb(sinfo, chan, desc); + bkn_api_rx_copy_from_skb(sinfo, chan, desc, 0); break; case KCOM_DEST_T_NETIF: priv = bkn_netif_lookup(sinfo, filter->kf.dest_id); @@ -3961,7 +3978,7 @@ bkn_do_skb_rx(bkn_switch_info_t *sinfo, int chan, int budget) if ((filter->kf.mirror_type == KCOM_DEST_T_API) || dbg_pkt_enable) { sinfo->rx[chan].pkts_m_api++; - bkn_api_rx_copy_from_skb(sinfo, chan, desc); + bkn_api_rx_copy_from_skb(sinfo, chan, desc, priv->rx_hwts); } if (device_is_sand(sinfo)) { @@ -4095,6 +4112,9 @@ bkn_do_skb_rx(bkn_switch_info_t *sinfo, int chan, int budget) } } + /* Ensure that we reallocate SKB for this DCB */ + desc->skb = NULL; + /* Unlock while calling up network stack */ spin_unlock(&sinfo->lock); if (use_napi) { @@ -4104,8 +4124,6 @@ bkn_do_skb_rx(bkn_switch_info_t *sinfo, int chan, int budget) } spin_lock(&sinfo->lock); - /* Ensure that we reallocate SKB for this DCB */ - desc->skb = NULL; } else { DBG_FLTR(("Unknown netif %d\n", filter->kf.dest_id)); @@ -4299,11 +4317,28 @@ bkn_hw_tstamp_tx_work(struct work_struct *work) { bkn_switch_info_t *sinfo = container_of(work, bkn_switch_info_t, tx_ptp_work); struct sk_buff *skb; + int ret; while (skb_queue_len(&sinfo->tx_ptp_queue)) { skb = skb_dequeue(&sinfo->tx_ptp_queue); - if (bkn_hw_tstamp_tx_set(sinfo, skb) < 0) { - gprintk("Timestamp has not been taken for the current skb.\n"); + ret = bkn_hw_tstamp_tx_set(sinfo, skb); + if (ret < 0) { +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,26)) + ktime_t now; + now = ktime_get(); + DBG_PTP(("2Step TX Timestamp has not been taken for the current skb (%lld us)\n", + ktime_us_delta(now, skb->tstamp))); + } else { + ktime_t now; + now = ktime_get(); + /* Timeout 20 should be same as configured by PTP4L */ + if (ktime_us_delta(now, skb->tstamp) >= 20000) { + DBG_PTP(("2Step TX Timestamp fetch took long time %lld us\n", + ktime_us_delta(now, skb->tstamp))); + } +#else + DBG_PTP(("2Step TX Timestamp has not been taken for the current skb\n")); +#endif } dev_kfree_skb_any(skb); } @@ -4346,6 +4381,9 @@ bkn_do_tx(bkn_switch_info_t *sinfo) } if (bkn_skb_tx_flags(desc->skb) & SKBTX_IN_PROGRESS) { +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,26)) + desc->skb->tstamp = ktime_get(); +#endif skb_queue_tail(&sinfo->tx_ptp_queue, desc->skb); schedule_work(&sinfo->tx_ptp_work); } else { @@ -5310,6 +5348,7 @@ bkn_hw_tstamp_tx_config(bkn_switch_info_t *sinfo, case 26: case 32: case 33: + case 35: meta[2] |= md[0]; meta[3] |= md[1]; meta[4] |= md[2]; @@ -5342,6 +5381,7 @@ bkn_tx(struct sk_buff *skb, struct net_device *dev) uint32_t *metadata; unsigned long flags; uint32_t cpu_channel = 0; + int headroom, tailroom; DBG_VERB(("Netif Tx: Len=%d priv->id=%d\n", skb->len, priv->id)); @@ -5449,7 +5489,16 @@ bkn_tx(struct sk_buff *skb, struct net_device *dev) if (skb_header_cloned(skb)) { /* Current SKB cannot be modified */ DBG_SKB(("Realloc Tx SKB\n")); - new_skb = dev_alloc_skb(pktlen + TAG_SZ + FCS_SZ); + /* + * New SKB needs extra TAG_SZ for VLAN tag + * and extra FCS_SZ for Ethernet FCS. + */ + headroom = TAG_SZ; + tailroom = FCS_SZ; + new_skb = skb_copy_expand(skb, + headroom + skb_headroom(skb), + tailroom + skb_tailroom(skb), + GFP_ATOMIC); if (new_skb == NULL) { DBG_WARN(("Tx drop: No SKB memory\n")); priv->stats.tx_dropped++; @@ -5458,9 +5507,12 @@ bkn_tx(struct sk_buff *skb, struct net_device *dev) spin_unlock_irqrestore(&sinfo->lock, flags); return 0; } + /* Remove rcpulen from buffer. */ + skb_pull(new_skb, rcpulen); + /* Extended by TAG_SZ at the start of buffer. */ + skb_push(new_skb, TAG_SZ); + /* Restore the data before the tag. */ memcpy(new_skb->data, pktdata, 12); - memcpy(&new_skb->data[16], &pktdata[12], pktlen - 12); - skb_put(new_skb, pktlen + TAG_SZ); bkn_skb_tstamp_copy(new_skb, skb); dev_kfree_skb_any(skb); skb = new_skb; @@ -5489,7 +5541,16 @@ bkn_tx(struct sk_buff *skb, struct net_device *dev) if (skb_header_cloned(skb) || skb_headroom(skb) < hdrlen + 4) { /* Current SKB cannot be modified */ DBG_SKB(("Realloc Tx SKB\n")); - new_skb = dev_alloc_skb(pktlen + hdrlen + 4 + FCS_SZ); + if (device_is_sand(sinfo)) { + headroom = hdrlen; + } else { + headroom = hdrlen + 4; + } + tailroom = FCS_SZ; + new_skb = skb_copy_expand(skb, + headroom + skb_headroom(skb), + tailroom + skb_tailroom(skb), + GFP_ATOMIC); if (new_skb == NULL) { DBG_WARN(("Tx drop: No SKB memory\n")); priv->stats.tx_dropped++; @@ -5498,12 +5559,7 @@ bkn_tx(struct sk_buff *skb, struct net_device *dev) spin_unlock_irqrestore(&sinfo->lock, flags); return 0; } - if (!device_is_sand(sinfo)) - { - skb_reserve(new_skb, 4); - } - memcpy(new_skb->data + hdrlen, skb->data, pktlen); - skb_put(new_skb, pktlen + hdrlen); + skb_push(new_skb, hdrlen); bkn_skb_tstamp_copy(new_skb, skb); dev_kfree_skb_any(skb); skb = new_skb; @@ -5526,7 +5582,12 @@ bkn_tx(struct sk_buff *skb, struct net_device *dev) if (skb_header_cloned(skb) || skb_headroom(skb) < 4) { /* Current SKB cannot be modified */ DBG_SKB(("Realloc Tx SKB\n")); - new_skb = dev_alloc_skb(pktlen + TAG_SZ + FCS_SZ); + headroom = TAG_SZ; + tailroom = FCS_SZ; + new_skb = skb_copy_expand(skb, + headroom + skb_headroom(skb), + tailroom + skb_tailroom(skb), + GFP_ATOMIC); if (new_skb == NULL) { DBG_WARN(("Tx drop: No SKB memory\n")); priv->stats.tx_dropped++; @@ -5535,10 +5596,8 @@ bkn_tx(struct sk_buff *skb, struct net_device *dev) spin_unlock_irqrestore(&sinfo->lock, flags); return 0; } - memcpy(new_skb->data, skb->data, hdrlen + 12); - memcpy(&new_skb->data[hdrlen + 16], &skb->data[hdrlen + 12], - pktlen - hdrlen - 12); - skb_put(new_skb, pktlen + TAG_SZ); + skb_push(new_skb, TAG_SZ); + memcpy(new_skb->data, pktdata, hdrlen + 12); bkn_skb_tstamp_copy(new_skb, skb); dev_kfree_skb_any(skb); skb = new_skb; @@ -5868,24 +5927,11 @@ bkn_tx(struct sk_buff *skb, struct net_device *dev) priv->stats.tx_bytes += pktlen; sinfo->tx.pkts++; } else { -#ifdef SAI_FIXUP /* SDK-224448 */ DBG_VERB(("Tx busy: No DMA resources\n")); sinfo->tx.pkts_d_dma_resrc++; -#else - DBG_WARN(("Tx drop: No DMA resources\n")); - priv->stats.tx_dropped++; - sinfo->tx.pkts_d_dma_resrc++; - dev_kfree_skb_any(skb); - } - - /* Check our Tx resources */ - if (sinfo->tx.free <= 1) { -#endif /* SDK-224448 */ bkn_suspend_tx(sinfo); -#ifdef SAI_FIXUP /* SDK-224448 */ spin_unlock_irqrestore(&sinfo->lock, flags); return BKN_NETDEV_TX_BUSY; -#endif /* SDK-224448 */ } NETDEV_UPDATE_TRANS_START_TIME(dev); @@ -6105,6 +6151,7 @@ bkn_create_sinfo(int dev_no) sinfo->dma_dev = lkbde_get_dma_dev(dev_no); sinfo->pdev = lkbde_get_hw_dev(dev_no); sinfo->dev_no = dev_no; + sinfo->inst_id = INVALID_INSTANCE_ID; sinfo->evt_idx = -1; spin_lock_init(&sinfo->lock); @@ -6196,6 +6243,7 @@ bkn_get_ts_info(struct net_device *dev, struct ethtool_ts_info *info) case 26: case 32: case 33: + case 35: case 36: case 38: case 40: @@ -6292,10 +6340,6 @@ bkn_init_ndev(u8 *mac, char *name) if (dev->mtu == 0) { dev->mtu = rx_buffer_size; } -#if (LINUX_VERSION_CODE >= KERNEL_VERSION(4,10,0)) - dev->min_mtu = 68; - dev->max_mtu = rx_buffer_size; -#endif /* Device vectors */ #if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,29)) @@ -7296,9 +7340,9 @@ bkn_proc_cleanup(void) */ static int -_pprint(void) +_pprint(struct seq_file *m) { - pprintf("Broadcom BCM KNET Linux Network Driver\n"); + pprintf(m, "Broadcom BCM KNET Linux Network Driver\n"); return 0; } @@ -7460,7 +7504,7 @@ bkn_create_inst(uint32 inst_id) DBG_INST(("%s evt_idx %d inst_id 0x%x\n",__FUNCTION__, i, inst_id)); break; } - if ((_bkn_multi_inst == 0) || (evt->inst_id == 0)) { + if ((_bkn_multi_inst == 0) || (evt->inst_id == INVALID_INSTANCE_ID)) { _bkn_multi_inst ++; evt_idx = i; init_waitqueue_head(&evt->evt_wq); @@ -7475,7 +7519,7 @@ bkn_create_inst(uint32 inst_id) return -1; } for (i = 0; i < kernel_bde->num_devices(BDE_ALL_DEVICES); i++) { - if (inst_id & (1 << i)) { + if (lkbde_is_dev_managed_by_instance(i, inst_id)) { sinfo = bkn_sinfo_from_unit(i); spin_lock_irqsave(&sinfo->lock, flags); sinfo->evt_idx = evt_idx; @@ -7519,23 +7563,28 @@ bkn_knet_dev_inst_set(kcom_msg_reprobe_t *kmsg) { bkn_switch_info_t *sinfo; int d = kmsg->hdr.unit; - uint32 inst = 0; + uint32 inst = INVALID_INSTANCE_ID; unsigned long flags; struct list_head *list; sinfo = bkn_sinfo_from_unit(d); +#ifdef BCM_INSTANCE_SUPPORT lkbde_dev_instid_get(d, &inst); +#else + inst = INVALID_INSTANCE_ID; +#endif + DBG_INST(("%s sinfo->inst_id %d d %d inst %d\n",__FUNCTION__,sinfo->inst_id, d, inst)); spin_lock_irqsave(&sinfo->lock, flags); if (sinfo->inst_id != inst) { /* Instance database changed, reinit the inst_id */ - sinfo->inst_id = 0; + sinfo->inst_id = INVALID_INSTANCE_ID; sinfo->evt_idx = -1; } spin_unlock_irqrestore(&sinfo->lock, flags); - if (inst) { - if (sinfo->inst_id == 0) { + if (inst != INVALID_INSTANCE_ID) { + if (sinfo->inst_id == INVALID_INSTANCE_ID) { if (bkn_create_inst(inst) != 0) { return -1; } @@ -7549,7 +7598,7 @@ bkn_knet_dev_inst_set(kcom_msg_reprobe_t *kmsg) sinfo = (bkn_switch_info_t *)list; spin_lock_irqsave(&sinfo->lock, flags); sinfo->evt_idx = 0; - sinfo->inst_id = 0; + sinfo->inst_id = INVALID_INSTANCE_ID; spin_unlock_irqrestore(&sinfo->lock, flags); } } @@ -7880,16 +7929,16 @@ bkn_knet_netif_create(kcom_msg_netif_create_t *kmsg, int len) } } + DBG_VERB(("Assigned ID %d to Ethernet device %s\n", priv->id, dev->name)); kmsg->netif.id = priv->id; memcpy(kmsg->netif.macaddr, dev->dev_addr, 6); memcpy(kmsg->netif.name, dev->name, KCOM_NETIF_NAME_MAX - 1); - if (knet_netif_create_cb != NULL) { int retv = knet_netif_create_cb(kmsg->hdr.unit, &(kmsg->netif), dev); - if (retv) { + if (retv) { gprintk("Warning: knet_netif_create_cb() returned %d for netif '%s'\n", retv, dev->name); } } @@ -7947,6 +7996,7 @@ bkn_knet_netif_destroy(kcom_msg_netif_destroy_t *kmsg, int len) netif.id = priv->id; knet_netif_destroy_cb(kmsg->hdr.unit, &netif, priv->dev); } + list_del(&priv->list); if (priv->id < sinfo->ndev_max) { @@ -8473,8 +8523,8 @@ bkn_get_next_dma_event(kcom_msg_dma_info_t *kmsg) sinfo = bkn_sinfo_from_unit(dev_no); } - if (sinfo && (sinfo->inst_id != 0) && - ((sinfo->inst_id & (1 << dev_evt)) == 0)) { + if (sinfo && (sinfo->inst_id != INVALID_INSTANCE_ID) && + (!lkbde_is_dev_managed_by_instance(dev_evt, sinfo->inst_id))) { DBG_INST((" %s skip dev(%d)\n",__FUNCTION__,dev_no)); continue; } @@ -8540,8 +8590,10 @@ _cleanup(void) del_timer_sync(&sinfo->rxtick); spin_lock_irqsave(&sinfo->lock, flags); - bkn_dma_abort(sinfo); - dev_irq_mask_set(sinfo, 0); + if (DEV_IS_CMIC(sinfo)) { + bkn_dma_abort(sinfo); + dev_irq_mask_set(sinfo, 0); + } spin_unlock_irqrestore(&sinfo->lock, flags); DBG_IRQ(("Unregister ISR.\n")); @@ -8759,6 +8811,7 @@ _init(void) /* Initialize event queue */ for (idx = 0; idx < LINUX_BDE_MAX_DEVICES; idx++) { memset(&_bkn_evt[idx], 0, sizeof(bkn_evt_resource_t)); + _bkn_evt[idx].inst_id = INVALID_INSTANCE_ID; } evt = &_bkn_evt[0]; init_waitqueue_head(&evt->evt_wq); diff --git a/platform/broadcom/saibcm-modules/systems/linux/kernel/modules/bcm-ptp-clock/Makefile b/platform/broadcom/saibcm-modules/systems/linux/kernel/modules/bcm-ptp-clock/Makefile index 1c9a3209e13..9aa3be68685 100644 --- a/platform/broadcom/saibcm-modules/systems/linux/kernel/modules/bcm-ptp-clock/Makefile +++ b/platform/broadcom/saibcm-modules/systems/linux/kernel/modules/bcm-ptp-clock/Makefile @@ -14,9 +14,9 @@ # version 2 (GPLv2) along with this source code. # # -*- Makefile -*- -# $Id: Makefile,v 1.3 Broadcom SDK $ -# $Copyright: (c) 2020 Broadcom. -# Broadcom Proprietary and Confidential. All rights reserved.$ +# $Id: Makefile,v 1.3 2012/07/17 07:39:51 mlarsen Exp $ +# $Copyright: (c) 2005 Broadcom Corp. +# All Rights Reserved.$ # LOCALDIR = systems/linux/kernel/modules/bcm-ptp-clock diff --git a/platform/broadcom/saibcm-modules/systems/linux/kernel/modules/bcm-ptp-clock/bcm-ptp-clock.c b/platform/broadcom/saibcm-modules/systems/linux/kernel/modules/bcm-ptp-clock/bcm-ptp-clock.c index 5b0a6bde738..edc4a38c741 100644 --- a/platform/broadcom/saibcm-modules/systems/linux/kernel/modules/bcm-ptp-clock/bcm-ptp-clock.c +++ b/platform/broadcom/saibcm-modules/systems/linux/kernel/modules/bcm-ptp-clock/bcm-ptp-clock.c @@ -76,9 +76,13 @@ MODULE_PARM_DESC(fw_core, /* Debug levels */ #define DBG_LVL_VERB 0x1 #define DBG_LVL_WARN 0x2 +#define DBG_LVL_TXTS 0x4 +#define DBG_LVL_CMDS 0x8 #define DBG_VERB(_s) do { if (debug & DBG_LVL_VERB) gprintk _s; } while (0) #define DBG_WARN(_s) do { if (debug & DBG_LVL_WARN) gprintk _s; } while (0) +#define DBG_TXTS(_s) do { if (debug & DBG_LVL_TXTS) gprintk _s; } while (0) +#define DBG_CMDS(_s) do { if (debug & DBG_LVL_CMDS) gprintk _s; } while (0) #define DBG_ERR(_s) do { if (1) gprintk _s; } while (0) @@ -98,41 +102,37 @@ MODULE_PARM_DESC(fw_core, #define BKSYNC_PACKLEN_U24 3 #define BKSYNC_PACKLEN_U32 4 -#define BKSYNC_UNPACK_U8(_buf, _var) \ +#define BKSYNC_UNPACK_U8(_buf, _var) \ _var = *_buf++ -#define BKSYNC_UNPACK_U16(_buf, _var) \ +#define BKSYNC_UNPACK_U16(_buf, _var) \ do { \ (_var) = (((_buf)[0] << 8) | \ (_buf)[1]); \ - (_buf) += BKSYNC_PACKLEN_U16; \ + (_buf) += BKSYNC_PACKLEN_U16; \ } while (0) -#define BKSYNC_UNPACK_U24(_buf, _var) \ +#define BKSYNC_UNPACK_U24(_buf, _var) \ do { \ (_var) = (((_buf)[0] << 16) | \ ((_buf)[1] << 8) | \ (_buf)[2]); \ - (_buf) += BKSYNC_PACKLEN_U24; \ + (_buf) += BKSYNC_PACKLEN_U24; \ } while (0) -#define BKSYNC_UNPACK_U32(_buf, _var) \ +#define BKSYNC_UNPACK_U32(_buf, _var) \ do { \ (_var) = (((_buf)[0] << 24) | \ ((_buf)[1] << 16) | \ ((_buf)[2] << 8) | \ (_buf)[3]); \ - (_buf) += BKSYNC_PACKLEN_U32; \ + (_buf) += BKSYNC_PACKLEN_U32; \ } while (0) #define CMICX_DEV_TYPE ((ptp_priv->dcb_type == 38) || \ (ptp_priv->dcb_type == 36)) -#define HOSTCMD_USE_REGS ((ptp_priv->dcb_type == 38) || \ - (ptp_priv->dcb_type == 36) || \ - (ptp_priv->dcb_type == 32)) - /* CMIC MCS-0 SCHAN Messaging registers */ /* Core0:CMC1 Core1:CMC2 */ #define CMIC_CMC_BASE \ @@ -154,30 +154,58 @@ MODULE_PARM_DESC(fw_core, u32 hostcmd_regs[5] = { 0 }; -/* TX Timestamp FIFO Access */ -#define BCM_NUM_PORTS 128 +#define BCMKSYNC_NUM_PORTS 128 /* NUM_PORTS where 2-step is supported. */ +#define BCMKSYNC_MAX_NUM_PORTS 256 /* Max ever NUM_PORTS in the system */ +#define BCMKSYNC_MAX_MTP_IDX 8 /* Max number of mtps in the system */ -/* Service request commands to R5 */ +/* Service request commands to Firmware. */ enum { - BCM_KSYNC_DONE = 0x0, - BCM_KSYNC_INIT = 0x1, - BCM_KSYNC_DEINIT = 0x2, - BCM_KSYNC_GETTIME = 0x3, - BCM_KSYNC_SETTIME = 0x4, - BCM_KSYNC_FREQCOR = 0x5, - BCM_KSYNC_PBM_UPDATE = 0x6, - BCM_KSYNC_ADJTIME = 0x7, - BCM_KSYNC_GET_TSTIME = 0x8, + BKSYNC_DONE = (0x0), + BKSYNC_INIT = (0x1), + BKSYNC_DEINIT = (0x2), + BKSYNC_GETTIME = (0x3), + BKSYNC_SETTIME = (0x4), + BKSYNC_FREQCOR = (0x5), + BKSYNC_PBM_UPDATE = (0x6), + BKSYNC_ADJTIME = (0x7), + BKSYNC_GET_TSTIME = (0x8), + BKSYNC_MTP_TS_UPDATE_ENABLE = (0x9), + BKSYNC_MTP_TS_UPDATE_DISABLE = (0xa), + BKSYNC_ACK_TSTIME = (0xb), +}; + + +/* 1588 message types. */ +enum +{ + IEEE1588_MSGTYPE_SYNC = (0x0), + IEEE1588_MSGTYPE_DELREQ = (0x1), + IEEE1588_MSGTYPE_PDELREQ = (0x2), + IEEE1588_MSGTYPE_PDELRESP = (0x3), + /* reserved (0x4) */ + /* reserved (0x5) */ + /* reserved (0x6) */ + /* reserved (0x7) */ + IEEE1588_MSGTYPE_GENERALMASK = (0x8), /* all non-event messages have this bit set */ + IEEE1588_MSGTYPE_FLWUP = (0x8), + IEEE1588_MSGTYPE_DELRESP = (0x9), + IEEE1588_MSGTYPE_PDELRES_FLWUP = (0xA), + IEEE1588_MSGTYPE_ANNOUNCE = (0xB), + IEEE1588_MSGTYPE_SGNLNG = (0xC), + IEEE1588_MSGTYPE_MNGMNT = (0xD) + /* reserved (0xE) */ + /* reserved (0xF) */ }; /* Usage macros */ #define ONE_BILLION (1000000000) #define SKB_U16_GET(_skb, _pkt_offset) \ - ((_skb->data[_pkt_offset] << 8) | _skb->data[_pkt_offset + 1]) + ((_skb->data[_pkt_offset] << 8) | _skb->data[_pkt_offset + 1]) #define BKSYNC_PTP_EVENT_MSG(_ptp_msg_type) \ - ((_ptp_msg_type == DELAY_REQ) || (_ptp_msg_type == SYNC)) + ((_ptp_msg_type == IEEE1588_MSGTYPE_DELREQ) || \ + (_ptp_msg_type == IEEE1588_MSGTYPE_SYNC)) #if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,30) @@ -187,10 +215,6 @@ enum { #endif -/* Values for the messageType field */ -#define SYNC 0x0 -#define DELAY_REQ 0x1 - /* * Hardware specific information. * 4 words of information used from this data set. @@ -225,6 +249,19 @@ uint32_t sobmhudpipv6_dcb32[24] = {0x00000000, 0x00013E00, 0x00000000, 0x0000000 0x00000000, 0x000C3E00, 0x00000000, 0x00000000, 0x00000000, 0x000C4200, 0x00000000, 0x00000000, 0x00000000, 0x000C3E00, 0x00000000, 0x00000000, 0x00000000, 0x000C4200, 0x00000000, 0x00000000}; +uint32_t sobmhrawpkts_dcb35[24] = {0x00000000, 0x0020E000, 0x00000000, 0x00000000, 0x00000000, 0x00212000, 0x00000000, 0x00000000, + 0x00000000, 0x0100E000, 0x00000000, 0x00000000, 0x00000000, 0x01012000, 0x00000000, 0x00000000, + 0x00000000, 0x0140E000, 0x00000000, 0x00000000, 0x00000000, 0x01412000, 0x00000000, 0x00000000}; + +uint32_t sobmhudpipv4_dcb35[24] = {0x00000000, 0x0022A000, 0x00000000, 0x00000000, 0x00000000, 0x0022E000, 0x00000000, 0x00000000, + 0x00000000, 0x0102A000, 0x00000000, 0x00000000, 0x00000000, 0x0102E000, 0x00000000, 0x00000000, + 0x00000000, 0x0142A000, 0x00000000, 0x00000000, 0x00000000, 0x0142E000, 0x00000000, 0x00000000}; + +uint32_t sobmhudpipv6_dcb35[24] = {0x00000000, 0x0023E000, 0x00000000, 0x00000000, 0x00000000, 0x00242000, 0x00000000, 0x00000000, + 0x00000000, 0x0103E000, 0x00000000, 0x00000000, 0x00000000, 0x01042000, 0x00000000, 0x00000000, + 0x00000000, 0x0143E000, 0x00000000, 0x00000000, 0x00000000, 0x01442000, 0x00000000, 0x00000000}; + + uint32_t sobmhrawpkts_dcb36[24] = {0x00000000, 0x00010E00, 0x00000000, 0x00000000, 0x00000000, 0x00011200, 0x00000000, 0x00000000, 0x00000000, 0x00080E00, 0x00000000, 0x00000000, 0x00000000, 0x00081200, 0x00000000, 0x00000000, 0x00000000, 0x00080E00, 0x00000000, 0x00000000, 0x00000000, 0x00081200, 0x00000000, 0x00000000}; @@ -267,21 +304,26 @@ typedef struct _bksync_uc_linux_ipc_s u32 ksyncinit; u32 dev_id; s64 freqcorr; - u64 portmap[BCM_NUM_PORTS/64]; + u64 portmap[BCMKSYNC_NUM_PORTS/64]; /* Two-step enabled ports */ u64 ptptime; u64 reftime; s64 phase_offset; - bksync_tx_ts_data_t port_ts_data[BCM_NUM_PORTS]; + bksync_tx_ts_data_t port_ts_data[BCMKSYNC_NUM_PORTS]; } bksync_uc_linux_ipc_t; typedef struct bksync_port_stats_s { u32 pkt_rxctr; /* All ingress packets */ u32 pkt_txctr; /* All egress packets */ + u32 pkt_txonestep; /* 1-step Tx packet counter */ u32 tsts_match; /* 2-Step tstamp req match */ u32 tsts_timeout; /* 2-Step tstamp req timeouts */ u32 tsts_discard; /* 2-Step tstamp req discards */ u32 osts_event_pkts; /* 1-step event packet counter */ u32 osts_tstamp_reqs; /* 1-step events with tstamp request */ + u32 fifo_rxctr; /* 2-Step tstamp req match */ + u64 tsts_best_fetch_time; /* 1-step events with tstamp request */ + u64 tsts_worst_fetch_time; /* 1-step events with tstamp request */ + u32 tsts_avg_fetch_time; /* 1-step events with tstamp request */ } bksync_port_stats_t; /* Clock Private Data */ @@ -296,14 +338,10 @@ struct bksync_ptp_priv { volatile bksync_uc_linux_ipc_t *shared_addr; /* address for shared memory access */ uint64_t dma_mem; int dma_mem_size; - int num_pports; struct DMA_DEV *dma_dev; /* Required for DMA memory control */ - u32 pkt_rxctr[BCM_NUM_PORTS]; - u32 pkt_txctr[BCM_NUM_PORTS]; - u32 ts_match[BCM_NUM_PORTS]; - u32 ts_timeout[BCM_NUM_PORTS]; - u32 ts_discard[BCM_NUM_PORTS]; + int num_pports; int timekeep_status; + u32 mirror_encap_bmp; struct delayed_work time_keep; bksync_port_stats_t *port_stats; }; @@ -311,7 +349,7 @@ struct bksync_ptp_priv { static struct bksync_ptp_priv *ptp_priv; volatile bksync_uc_linux_ipc_t *linuxPTPMemory = (bksync_uc_linux_ipc_t*)(0); static volatile int module_initialized; -static int retry_count = 10; /* Default retry for 10 jiffies */ +static int num_retries = 10; /* Retry count */ static void bksync_ptp_time_keep_init(void); static void bksync_ptp_time_keep_deinit(void); @@ -366,64 +404,6 @@ ptp_sleep(int jiffies) } -static int bksync_cmd_cmicm_go(u32 cmd, void *data0, void *data1) -{ - int ret = -1; - int retry_cnt = retry_count; - u32 cmd_status; - - mutex_lock(&ptp_priv->ptp_lock); - ptp_priv->shared_addr->ksyncinit = cmd; - switch (cmd) { - case BCM_KSYNC_INIT: - ptp_priv->shared_addr->phase_offset = 0; - ret = 0; - break; - case BCM_KSYNC_FREQCOR: - ptp_priv->shared_addr->freqcorr = *((s32 *)data0); - break; - case BCM_KSYNC_ADJTIME: - ptp_priv->shared_addr->phase_offset = *((s64 *)data0); - break; - case BCM_KSYNC_GETTIME: - break; - case BCM_KSYNC_SETTIME: - ptp_priv->shared_addr->ptptime = *((s64 *)data0); - ptp_priv->shared_addr->phase_offset = 0; - break; - default: - break; - } - - do { - cmd_status = ptp_priv->shared_addr->ksyncinit; - if (cmd_status == BCM_KSYNC_DONE) { - switch (cmd) { - case BCM_KSYNC_GETTIME: - *((s64 *)data0) = ptp_priv->shared_addr->ptptime; - *((s64 *)data1) = ptp_priv->shared_addr->reftime; /* ptp counter */ - break; - default: - break; - } - ret = 0; - break; - } - ptp_sleep(1); - retry_cnt--; - } while (retry_cnt); - mutex_unlock(&ptp_priv->ptp_lock); - - if (retry_cnt == 0) { - DBG_ERR(("Timeout on response from R5\n")); - } - - - return ret; -} - - - static void bksync_hostcmd_data_op(int setget, u64 *d1, u64 *d2) { u32 w0, w1; @@ -455,14 +435,28 @@ static void bksync_hostcmd_data_op(int setget, u64 *d1, u64 *d2) } -static int bksync_cmd_cmicx_go(u32 cmd, void *data0, void *data1) +static int bksync_cmd_go(u32 cmd, void *data0, void *data1) { int ret = -1; - int retry_cnt = (retry_count * 100); + int retry_cnt = (1000); /* 1ms default timeout for hostcmd response */ u32 cmd_status; char cmd_str[20]; + int port; + uint32_t seq_id; + ktime_t start, now; + + if (ptp_priv == NULL || ptp_priv->shared_addr == NULL) { + return ret; + } mutex_lock(&ptp_priv->ptp_lock); + + if (cmd == BKSYNC_GET_TSTIME || cmd == BKSYNC_ACK_TSTIME) { + port = *((uint64_t *)data0) & 0xFFF; + seq_id = *((uint64_t*)data0) >> 16; + } + start = ktime_get(); + ptp_priv->shared_addr->ksyncinit = cmd; /* init data */ @@ -472,36 +466,53 @@ static int bksync_cmd_cmicx_go(u32 cmd, void *data0, void *data1) DEV_WRITE32(ptp_priv, hostcmd_regs[4], 0x0); switch (cmd) { - case BCM_KSYNC_INIT: + case BKSYNC_INIT: sprintf(cmd_str, "KSYNC_INIT"); ptp_priv->shared_addr->phase_offset = 0; bksync_hostcmd_data_op(1, (u64 *)&(ptp_priv->shared_addr->phase_offset), 0); break; - case BCM_KSYNC_FREQCOR: + case BKSYNC_FREQCOR: sprintf(cmd_str, "KSYNC_FREQCORR"); ptp_priv->shared_addr->freqcorr = *((s32 *)data0); bksync_hostcmd_data_op(1, (u64 *)&(ptp_priv->shared_addr->freqcorr), 0); break; - case BCM_KSYNC_ADJTIME: + case BKSYNC_ADJTIME: sprintf(cmd_str, "KSYNC_ADJTIME"); ptp_priv->shared_addr->phase_offset = *((s64 *)data0); bksync_hostcmd_data_op(1, (u64 *)&(ptp_priv->shared_addr->phase_offset), 0); break; - case BCM_KSYNC_GETTIME: + case BKSYNC_GETTIME: + retry_cnt = (retry_cnt * 2); sprintf(cmd_str, "KSYNC_GETTIME"); break; - case BCM_KSYNC_GET_TSTIME: + case BKSYNC_GET_TSTIME: retry_cnt = (retry_cnt * 2); sprintf(cmd_str, "KSYNC_GET_TSTIME"); bksync_hostcmd_data_op(1, data0, data1); break; - case BCM_KSYNC_SETTIME: + case BKSYNC_ACK_TSTIME: + retry_cnt = (retry_cnt * 2); + sprintf(cmd_str, "KSYNC_ACK_TSTIME"); + bksync_hostcmd_data_op(1, data0, data1); + break; + case BKSYNC_SETTIME: sprintf(cmd_str, "KSYNC_SETTIME"); ptp_priv->shared_addr->ptptime = *((s64 *)data0); ptp_priv->shared_addr->phase_offset = 0; bksync_hostcmd_data_op(1, (u64 *)&(ptp_priv->shared_addr->ptptime), (u64 *)&(ptp_priv->shared_addr->phase_offset)); break; - case BCM_KSYNC_DEINIT: + case BKSYNC_MTP_TS_UPDATE_ENABLE: + retry_cnt = (retry_cnt * 6); + sprintf(cmd_str, "KSYNC_MTP_TS_UPDATE_ENABLE"); + bksync_hostcmd_data_op(1, (u64 *)data0, 0); + break; + case BKSYNC_MTP_TS_UPDATE_DISABLE: + retry_cnt = (retry_cnt * 6); + sprintf(cmd_str, "KSYNC_MTP_TS_UPDATE_DISABLE"); + bksync_hostcmd_data_op(1, (u64 *)data0, 0); + break; + case BKSYNC_DEINIT: + retry_cnt = (retry_cnt * 4); sprintf(cmd_str, "KSYNC_DEINIT"); break; default: @@ -514,11 +525,11 @@ static int bksync_cmd_cmicx_go(u32 cmd, void *data0, void *data1) DEV_READ32(ptp_priv, hostcmd_regs[0], &cmd_status); ptp_priv->shared_addr->ksyncinit = cmd_status; - if (cmd_status == BCM_KSYNC_DONE) { + if (cmd_status == BKSYNC_DONE) { ret = 0; switch (cmd) { - case BCM_KSYNC_GET_TSTIME: - case BCM_KSYNC_GETTIME: + case BKSYNC_GET_TSTIME: + case BKSYNC_GETTIME: bksync_hostcmd_data_op(0, (u64 *)data0, (u64 *)data1); break; default: @@ -530,37 +541,20 @@ static int bksync_cmd_cmicx_go(u32 cmd, void *data0, void *data1) retry_cnt--; } while (retry_cnt); + now = ktime_get(); mutex_unlock(&ptp_priv->ptp_lock); if (retry_cnt == 0) { - DBG_ERR(("Timeout on response from R5 to cmd %s\n", cmd_str)); + DBG_ERR(("Timeout on response from R5 to cmd %s time taken %lld us\n", cmd_str, ktime_us_delta(now, start))); + if (cmd == BKSYNC_GET_TSTIME) { + DBG_TXTS(("Timeout Port %d SeqId %d\n", port, seq_id)); + } } - - - return ret; -} - - -static int bksync_cmd_go(u32 cmd, void *data0, void *data1) -{ - int ret = -1; - - if (ptp_priv == NULL || ptp_priv->shared_addr == NULL) { - return ret; + if (debug & DBG_LVL_CMDS) { + if (ktime_us_delta(now, start) > 5000) + DBG_CMDS(("R5 Command %s exceeded time expected (%lld us)\n", cmd_str, ktime_us_delta(now, start))); } - switch (ptp_priv->dcb_type) { - case 26: - ret = bksync_cmd_cmicm_go(cmd, data0, data1); - break; - case 32: - case 36: - case 38: - ret = bksync_cmd_cmicx_go(cmd, data0, data1); - break; - default: - break; - } return ret; } @@ -577,7 +571,7 @@ static int bksync_cmd_go(u32 cmd, void *data0, void *data1) static int bksync_ptp_adjfreq(struct ptp_clock_info *ptp, s32 ppb) { int ret = -1; - u32 cmd_status = BCM_KSYNC_FREQCOR; + u32 cmd_status = BKSYNC_FREQCOR; ret = bksync_cmd_go(cmd_status, &ppb, NULL); DBG_VERB(("applying freq correction: %x\n", ppb)); @@ -595,7 +589,7 @@ static int bksync_ptp_adjfreq(struct ptp_clock_info *ptp, s32 ppb) */ static int bksync_ptp_adjtime(struct ptp_clock_info *ptp, s64 delta) { - u32 cmd_status = BCM_KSYNC_ADJTIME; + u32 cmd_status = BKSYNC_ADJTIME; int ret = -1; ret = bksync_cmd_go(cmd_status, (void *)&delta, NULL); @@ -616,18 +610,20 @@ static int bksync_ptp_adjtime(struct ptp_clock_info *ptp, s64 delta) static int bksync_ptp_gettime(struct ptp_clock_info *ptp, struct timespec64 *ts) { int ret = -1; - u32 cmd_status = BCM_KSYNC_GETTIME; + u32 cmd_status = BKSYNC_GETTIME; s64 reftime = 0; s64 refctr = 0; ret = bksync_cmd_go(cmd_status, (void *)&reftime, (void *)&refctr); - DBG_VERB(("ptp gettime: 0x%llx refctr:0x%llx\n", reftime, refctr)); - mutex_lock(&ptp_priv->ptp_pair_lock); - ptp_priv->shared_addr->ptptime = reftime; - ptp_priv->shared_addr->reftime = refctr; - mutex_unlock(&ptp_priv->ptp_pair_lock); - - *ts = ns_to_timespec64(reftime); + if (ret == 0) { + DBG_VERB(("ptp gettime: 0x%llx refctr:0x%llx\n", reftime, refctr)); + mutex_lock(&ptp_priv->ptp_pair_lock); + ptp_priv->shared_addr->ptptime = reftime; + ptp_priv->shared_addr->reftime = refctr; + mutex_unlock(&ptp_priv->ptp_pair_lock); + + *ts = ns_to_timespec64(reftime); + } return ret; } @@ -646,7 +642,7 @@ static int bksync_ptp_settime(struct ptp_clock_info *ptp, { s64 reftime, phaseadj; int ret = -1; - u32 cmd_status = BCM_KSYNC_SETTIME; + u32 cmd_status = BKSYNC_SETTIME; phaseadj = 0; reftime = timespec64_to_ns(ts); @@ -663,6 +659,38 @@ static int bksync_ptp_enable(struct ptp_clock_info *ptp, return 0; } + +static int bksync_ptp_mirror_encap_update(struct ptp_clock_info *ptp, + int mtp_idx, int start) +{ + int ret = -1; + u64 mirror_encap_idx; + u32 cmd_status; + + if (mtp_idx > BCMKSYNC_MAX_MTP_IDX) { + return ret; + } + + mirror_encap_idx = mtp_idx; + if (start) { + cmd_status = BKSYNC_MTP_TS_UPDATE_ENABLE; + ptp_priv->mirror_encap_bmp |= (1 << mtp_idx); + } else { + if (!(ptp_priv->mirror_encap_bmp & mtp_idx)) { + /* Not running */ + return ret; + } + cmd_status = BKSYNC_MTP_TS_UPDATE_DISABLE; + ptp_priv->mirror_encap_bmp &= ~mtp_idx; + } + + ret = bksync_cmd_go(cmd_status, &mirror_encap_idx, NULL); + DBG_VERB(("ptp mmirror_encap_update: %d, mpt_index: %d, ret:%d \n", start, mtp_idx, ret)); + + return ret; + +} + /* structure describing a PTP hardware clock */ static struct ptp_clock_info bksync_ptp_caps = { .owner = THIS_MODULE, @@ -721,7 +749,7 @@ int bksync_ptp_hw_tstamp_enable(int dev_no, int port, int tx_type) portmap |= (uint64_t)0x1 << port; ptp_priv->shared_addr->portmap[map] = portmap; /* Command to R5 for the update */ - ptp_priv->shared_addr->ksyncinit=BCM_KSYNC_PBM_UPDATE; + ptp_priv->shared_addr->ksyncinit=BKSYNC_PBM_UPDATE; } exit: @@ -769,7 +797,7 @@ int bksync_ptp_hw_tstamp_disable(int dev_no, int port, int tx_type) ptp_priv->shared_addr->portmap[map]= portmap; /* Command to R5 for the update */ - ptp_priv->shared_addr->ksyncinit = BCM_KSYNC_PBM_UPDATE; + ptp_priv->shared_addr->ksyncinit = BKSYNC_PBM_UPDATE; } exit: return ret; @@ -818,23 +846,26 @@ bksync_txpkt_tsts_tsamp_get(int port, uint32_t pkt_seq_id, uint32_t *ts_valid, u { int ret = 0; uint64_t tmp; + u32 fifo_rxctr = 0; tmp = (port & 0xFFFF) | (pkt_seq_id << 16); - if (HOSTCMD_USE_REGS) { - ret = bksync_cmd_go(BCM_KSYNC_GET_TSTIME, &tmp, timestamp); - - if (ret >= 0) { - *seq_id = ((tmp >> 16) & 0xFFFF); - *ts_valid = (tmp & 0x1); + ret = bksync_cmd_go(BKSYNC_GET_TSTIME, &tmp, timestamp); + + if (ret >= 0) { + fifo_rxctr = (tmp >> 32) & 0xFFFF; + *seq_id = ((tmp >> 16) & 0xFFFF); + *ts_valid = (tmp & 0x1); + if (*ts_valid) { + tmp = (port & 0xFFFF) | (pkt_seq_id << 16); + bksync_cmd_go(BKSYNC_ACK_TSTIME, &tmp, 0); + if (fifo_rxctr != 0) { + if (fifo_rxctr != ptp_priv->port_stats[port].fifo_rxctr + 1) { + DBG_ERR(("FW Reset or Lost Timestamp RxSeq:(Prev %d : Current %d)\n", ptp_priv->port_stats[port].fifo_rxctr, fifo_rxctr)); + } + ptp_priv->port_stats[port].fifo_rxctr = fifo_rxctr; + } } -#if 0 - if (tmp & 0x1) gprintk("in_port: %d in_seq_id: %d out_port: %lld ts_valid: %lld seq_id: %lld ts: %llx\n", port, pkt_seq_id, ((tmp & 0xFFFF) >> 1), (tmp & 0x1), (tmp >> 16), *timestamp); -#endif - } else { - *ts_valid = ptp_priv->shared_addr->port_ts_data[port].ts_valid; - *seq_id = ptp_priv->shared_addr->port_ts_data[port].ts_seq_id; - *timestamp = ptp_priv->shared_addr->port_ts_data[port].timestamp; } @@ -861,9 +892,12 @@ int bksync_ptp_hw_tstamp_tx_time_get(int dev_no, int port, uint8_t *pkt, uint64_ uint32_t pktseq_id = 0; uint64_t timestamp = 0; uint16_t tpid = 0; - int retry_cnt = retry_count; + ktime_t start; + u64 delta; + int retry_cnt = num_retries; int seq_id_offset, tpid_offset; int transport = network_transport; + start = ktime_get(); if (!ptp_priv || !pkt || !ts || port < 1 || port > 255 || ptp_priv->shared_addr == NULL) { return -1; @@ -918,25 +952,26 @@ int bksync_ptp_hw_tstamp_tx_time_get(int dev_no, int port, uint8_t *pkt, uint64_ if (seq_id == pktseq_id) { *ts = timestamp; - if (HOSTCMD_USE_REGS) { - ptp_priv->port_stats[port].tsts_match += 1; - } else { - ptp_priv->ts_match[port] += 1; - } + ptp_priv->port_stats[port].tsts_match += 1; - DBG_VERB(("Port: %d Skb_SeqID %d FW_SeqId %d and TS:%llx\n", - port, pktseq_id, seq_id, timestamp)); + delta = ktime_us_delta(ktime_get(), start); + DBG_VERB(("Port: %d Skb_SeqID %d FW_SeqId %d and TS:%llx FetchTime %lld\n", + port, pktseq_id, seq_id, timestamp, delta)); + if (delta < ptp_priv->port_stats[port].tsts_best_fetch_time || ptp_priv->port_stats[port].tsts_best_fetch_time == 0) { + ptp_priv->port_stats[port].tsts_best_fetch_time = delta; + } + if (delta > ptp_priv->port_stats[port].tsts_worst_fetch_time || ptp_priv->port_stats[port].tsts_worst_fetch_time == 0) { + ptp_priv->port_stats[port].tsts_worst_fetch_time = delta; + } + /* Calculate Moving Average*/ + ptp_priv->port_stats[port].tsts_avg_fetch_time = ((u32)delta + ((ptp_priv->port_stats[port].tsts_match - 1) * ptp_priv->port_stats[port].tsts_avg_fetch_time)) / ptp_priv->port_stats[port].tsts_match; break; } else { - DBG_ERR(("discard timestamp on port %d Skb_SeqID %d FW_SeqId %d\n", - port, pktseq_id, seq_id)); + DBG_TXTS(("Discard timestamp on port %d Skb_SeqID %d FW_SeqId %d RetryCnt %d TimeLapsed (%lld us)\n", + port, pktseq_id, seq_id, (num_retries - retry_cnt), ktime_us_delta(ktime_get(),start))); - if (HOSTCMD_USE_REGS) { - ptp_priv->port_stats[port].tsts_discard += 1; - } else { - ptp_priv->ts_discard[port] += 1; - } + ptp_priv->port_stats[port].tsts_discard += 1; continue; } } @@ -945,19 +980,12 @@ int bksync_ptp_hw_tstamp_tx_time_get(int dev_no, int port, uint8_t *pkt, uint64_ } while(retry_cnt); - if (HOSTCMD_USE_REGS) { - ptp_priv->port_stats[port].pkt_txctr += 1; - } else { - ptp_priv->pkt_txctr[port] += 1; - } + ptp_priv->port_stats[port].pkt_txctr += 1; if (retry_cnt == 0) { - if (HOSTCMD_USE_REGS) { - ptp_priv->port_stats[port].tsts_timeout += 1; - } else { - ptp_priv->ts_timeout[port] += 1; - } - DBG_ERR(("FW Response timeout: Tx TS on phy port:%d Skb_SeqID: %d\n", port, seq_id)); + ptp_priv->port_stats[port].tsts_timeout += 1; + DBG_ERR(("FW Response timeout: Tx TS on phy port:%d Skb_SeqID: %d TimeLapsed (%lld us)\n", + port, pktseq_id, ktime_us_delta(ktime_get(), start))); } @@ -1113,6 +1141,7 @@ int bksync_ptp_hw_tstamp_rx_time_upscale(int dev_no, int port, struct sk_buff *s switch (KNET_SKB_CB(skb)->dcb_type) { case 26: case 32: + case 35: if (pci_cos != (meta[4] & 0x3F)) { return -1; } @@ -1142,12 +1171,8 @@ int bksync_ptp_hw_tstamp_rx_time_upscale(int dev_no, int port, struct sk_buff *s } if (port > 0){ - port -= 1; - if (HOSTCMD_USE_REGS) { + port -= 1; ptp_priv->port_stats[port].pkt_rxctr += 1; - } else { - ptp_priv->pkt_rxctr[port] += 1; - } } return ret; @@ -1240,6 +1265,8 @@ int bksync_ptp_hw_tstamp_tx_meta_get(int dev_no, if (md) *md = &sobmhrawpkts_dcb32[md_offset]; } else if(KNET_SKB_CB(skb)->dcb_type == 26) { if (md) *md = &sobmhrawpkts_dcb26[md_offset]; + } else if(KNET_SKB_CB(skb)->dcb_type == 35) { + if (md) *md = &sobmhrawpkts_dcb35[md_offset]; } else if(KNET_SKB_CB(skb)->dcb_type == 36) { if (md) *md = &sobmhrawpkts_dcb36[md_offset]; } else if(KNET_SKB_CB(skb)->dcb_type == 38) { @@ -1252,6 +1279,8 @@ int bksync_ptp_hw_tstamp_tx_meta_get(int dev_no, if (md) *md = &sobmhudpipv4_dcb32[md_offset]; } else if(KNET_SKB_CB(skb)->dcb_type == 26) { if (md) *md = &sobmhudpipv4_dcb26[md_offset]; + } else if(KNET_SKB_CB(skb)->dcb_type == 35) { + if (md) *md = &sobmhudpipv4_dcb35[md_offset]; } else if(KNET_SKB_CB(skb)->dcb_type == 36) { if (md) *md = &sobmhudpipv4_dcb36[md_offset]; } else if(KNET_SKB_CB(skb)->dcb_type == 38) { @@ -1264,6 +1293,8 @@ int bksync_ptp_hw_tstamp_tx_meta_get(int dev_no, if (md) *md = &sobmhudpipv6_dcb32[md_offset]; } else if(KNET_SKB_CB(skb)->dcb_type == 26) { if (md) *md = &sobmhudpipv6_dcb26[md_offset]; + } else if(KNET_SKB_CB(skb)->dcb_type == 35) { + if (md) *md = &sobmhudpipv6_dcb35[md_offset]; } else if(KNET_SKB_CB(skb)->dcb_type == 36) { if (md) *md = &sobmhudpipv6_dcb36[md_offset]; } else if(KNET_SKB_CB(skb)->dcb_type == 38) { @@ -1276,6 +1307,8 @@ int bksync_ptp_hw_tstamp_tx_meta_get(int dev_no, if (md) *md = &sobmhudpipv4_dcb32[md_offset]; } else if(KNET_SKB_CB(skb)->dcb_type == 26) { if (md) *md = &sobmhudpipv4_dcb26[md_offset]; + } else if(KNET_SKB_CB(skb)->dcb_type == 35) { + if (md) *md = &sobmhudpipv4_dcb35[md_offset]; } else if(KNET_SKB_CB(skb)->dcb_type == 36) { if (md) *md = &sobmhudpipv4_dcb36[md_offset]; } else if(KNET_SKB_CB(skb)->dcb_type == 38) { @@ -1285,7 +1318,7 @@ int bksync_ptp_hw_tstamp_tx_meta_get(int dev_no, } - if ((hwts == HWTSTAMP_TX_ONESTEP_SYNC) && + if ((hwts == HWTSTAMP_TX_ONESTEP_SYNC) && BKSYNC_PTP_EVENT_MSG(skb->data[ptp_hdr_offset])) { /* One Step Timestamp Field updation */ int corr_offset = ptp_hdr_offset + 8; @@ -1295,6 +1328,7 @@ int bksync_ptp_hw_tstamp_tx_meta_get(int dev_no, int udp_csum_regen; u32 udp_csum20; u16 udp_csum; + int port; udp_csum = SKB_U16_GET(skb, (ptp_hdr_offset - 2)); @@ -1360,12 +1394,15 @@ int bksync_ptp_hw_tstamp_tx_meta_get(int dev_no, skb->data[ptp_hdr_offset - 1] = ((udp_csum ) & 0xFF); } - if (skb->data[ptp_hdr_offset] == DELAY_REQ) { + if (skb->data[ptp_hdr_offset] == IEEE1588_MSGTYPE_DELREQ) { *tstamp = ptptime; DBG_VERB(("ptp delay req packet tstamp : 0x%llx corrField: 0x%llx\n", ptptime, corrField)); } + port = KNET_SKB_CB(skb)->port; + port -= 1; + ptp_priv->port_stats[port].pkt_txonestep += 1; } return 0; @@ -1425,14 +1462,14 @@ static void bksync_ptp_time_keep_deinit(void) static int bksync_ptp_init(struct ptp_clock_info *ptp) { - return bksync_cmd_go(BCM_KSYNC_INIT, NULL, NULL); + return bksync_cmd_go(BKSYNC_INIT, NULL, NULL); } static int bksync_ptp_deinit(struct ptp_clock_info *ptp) { bksync_ptp_time_keep_deinit(); - return bksync_cmd_go(BCM_KSYNC_DEINIT, NULL, NULL); + return bksync_cmd_go(BKSYNC_DEINIT, NULL, NULL); } /* @@ -1450,14 +1487,15 @@ static void *bksync_proc_seq_start(struct seq_file *s, loff_t *pos) /* beginning a new sequence ? */ if ( (int)*pos == 0 && ptp_priv->shared_addr != NULL) { - seq_printf(s, "Port Bitmap : %08llx%08llx\n", + seq_printf(s, "TwoStep Port Bitmap : %08llx%08llx\n", (uint64_t)(ptp_priv->shared_addr->portmap[1]), (uint64_t)(ptp_priv->shared_addr->portmap[0])); - seq_printf(s,"%4s| %9s| %9s| %9s| %9s| %9s| %9s|\n", - "Port", "RxCounter", "TxCounter", "TSTimeout", "TSRead", "TSMatch", "TSDiscard"); + seq_printf(s,"%4s| %9s| %9s| %9s| %9s| %9s| %9s| %9s| %9s| %9s| %9s| %9s\n", + "Port", "RxCounter", "TxCounter", "TxOneStep", "TSTimeout", "TSRead", "TSMatch", "TSDiscard", + "TimeHi" , "TimeLo", "TimeAvg", "FIFORx"); } - if (ptp_priv->shared_addr != NULL && (int)*pos < (ptp_priv->num_pports)) + if ((int)*pos < (ptp_priv->num_pports)) return (void *)(unsigned long)(*pos + 1); /* End of the sequence, return NULL */ return NULL; @@ -1490,33 +1528,24 @@ static int bksync_proc_seq_show(struct seq_file *s, void *v) { unsigned long port = (unsigned long)v; port = port - 1; - if (HOSTCMD_USE_REGS) { - if (ptp_priv->port_stats[port].pkt_rxctr || ptp_priv->port_stats[port].pkt_txctr || - ptp_priv->port_stats[port].tsts_discard || ptp_priv->port_stats[port].tsts_timeout || - ptp_priv->shared_addr->port_ts_data[port].ts_cnt || ptp_priv->port_stats[port].tsts_match) { - seq_printf(s, "%4lu | %9d| %9d| %9d| %9d| %9d| %9d| %s\n", (port + 1), - ptp_priv->port_stats[port].pkt_rxctr, - ptp_priv->port_stats[port].pkt_txctr, - ptp_priv->port_stats[port].tsts_timeout, - ptp_priv->shared_addr->port_ts_data[port].ts_cnt, - ptp_priv->port_stats[port].tsts_match, - ptp_priv->port_stats[port].tsts_discard, - ptp_priv->port_stats[port].pkt_txctr != ptp_priv->port_stats[port].tsts_match ? "***":""); - } - } else { - if (ptp_priv->pkt_rxctr[port] || ptp_priv->pkt_txctr[port] || - ptp_priv->ts_discard[port] || ptp_priv->ts_timeout[port] || - ptp_priv->shared_addr->port_ts_data[port].ts_cnt || ptp_priv->ts_match[port]) { - seq_printf(s, "%4lu | %9d| %9d| %9d| %9d| %9d| %9d| %s\n", (port + 1), - ptp_priv->pkt_rxctr[port], - ptp_priv->pkt_txctr[port], - ptp_priv->ts_timeout[port], + if (ptp_priv->port_stats[port].pkt_rxctr || ptp_priv->port_stats[port].pkt_txctr || + ptp_priv->port_stats[port].pkt_txonestep|| + ptp_priv->port_stats[port].tsts_discard || ptp_priv->port_stats[port].tsts_timeout || + ptp_priv->shared_addr->port_ts_data[port].ts_cnt || ptp_priv->port_stats[port].tsts_match) { + seq_printf(s, "%4lu | %9d| %9d| %9d| %9d| %9d| %9d| %9d| %9lld| %9lld | %9d|%9d | %s\n", (port + 1), + ptp_priv->port_stats[port].pkt_rxctr, + ptp_priv->port_stats[port].pkt_txctr, + ptp_priv->port_stats[port].pkt_txonestep, + ptp_priv->port_stats[port].tsts_timeout, ptp_priv->shared_addr->port_ts_data[port].ts_cnt, - ptp_priv->ts_match[port], - ptp_priv->ts_discard[port], - ptp_priv->pkt_txctr[port] != ptp_priv->ts_match[port] ? "***":""); + ptp_priv->port_stats[port].tsts_match, + ptp_priv->port_stats[port].tsts_discard, + ptp_priv->port_stats[port].tsts_worst_fetch_time, + ptp_priv->port_stats[port].tsts_best_fetch_time, + ptp_priv->port_stats[port].tsts_avg_fetch_time, + ptp_priv->port_stats[port].fifo_rxctr, + ptp_priv->port_stats[port].pkt_txctr != ptp_priv->port_stats[port].tsts_match ? "***":""); } - } return 0; } @@ -1549,19 +1578,12 @@ bksync_proc_txts_write(struct file *file, const char *buf, if ((ptr = strstr(debug_str, "clear")) != NULL) { for (port = 0; port < ptp_priv->num_pports; port++) { - if (HOSTCMD_USE_REGS) { - ptp_priv->port_stats[port].pkt_rxctr = 0; - ptp_priv->port_stats[port].pkt_txctr = 0; - ptp_priv->port_stats[port].tsts_discard = 0; - ptp_priv->port_stats[port].tsts_timeout = 0; - ptp_priv->port_stats[port].tsts_match = 0; - } else { - ptp_priv->pkt_rxctr[port] = 0; - ptp_priv->pkt_txctr[port] = 0; - ptp_priv->ts_discard[port] = 0; - ptp_priv->ts_timeout[port] = 0; - ptp_priv->ts_match[port] = 0; - } + ptp_priv->port_stats[port].pkt_rxctr = 0; + ptp_priv->port_stats[port].pkt_txctr = 0; + ptp_priv->port_stats[port].pkt_txonestep = 0; + ptp_priv->port_stats[port].tsts_timeout = 0; + ptp_priv->port_stats[port].tsts_match = 0; + ptp_priv->port_stats[port].tsts_discard = 0; if (ptp_priv->shared_addr) ptp_priv->shared_addr->port_ts_data[port].ts_cnt = 0; } @@ -1581,91 +1603,90 @@ struct file_operations bksync_proc_txts_file_ops = { release: seq_release, }; +/* + * Driver Debug Proc Entry + */ static int -bksync_proc_init(void) +bksync_proc_debug_show(struct seq_file *m, void *v) { - struct proc_dir_entry *entry; - - PROC_CREATE(entry, "stats", 0666, bksync_proc_root, &bksync_proc_txts_file_ops); - if (entry == NULL) { - return -1; - } + seq_printf(m, "Configuration:\n"); + seq_printf(m, " debug: 0x%x\n", debug); return 0; } -static int -bksync_proc_cleanup(void) +static ssize_t +bksync_proc_debug_write(struct file *file, const char *buf, + size_t count, loff_t *loff) { - remove_proc_entry("stats", bksync_proc_root); - return 0; -} + char debug_str[40]; + char *ptr; -static void bksync_ptp_cmicm_dma_init(int dcb_type) -{ - int endianess; - int num_pports = 128; - dma_addr_t dma_mem = 0; + if (copy_from_user(debug_str, buf, count)) { + return -EFAULT; + } - /* Initialize the Base address for CMIC and shared Memory access */ - ptp_priv->base_addr = lkbde_get_dev_virt(0); - ptp_priv->dma_dev = lkbde_get_dma_dev(0); + if ((ptr = strstr(debug_str, "debug=")) != NULL) { + ptr += 6; + debug = simple_strtol(ptr, NULL, 0); + } else { + gprintk("Warning: unknown configuration\n"); + } - ptp_priv->dma_mem_size = 16384;/*sizeof(bksync_uc_linux_ipc_t);*/ + return count; +} - if (ptp_priv->shared_addr == NULL) { - DBG_ERR(("Allocate shared memory with R5\n")); - ptp_priv->shared_addr = DMA_ALLOC_COHERENT(ptp_priv->dma_dev, - ptp_priv->dma_mem_size, - &dma_mem); - ptp_priv->dma_mem = (uint64_t)dma_mem; - ptp_priv->num_pports = num_pports; - ptp_priv->port_stats = kzalloc((sizeof(bksync_port_stats_t) * num_pports), GFP_KERNEL); - } +static int bksync_proc_debug_open(struct inode * inode, struct file * file) +{ + return single_open(file, bksync_proc_debug_show, NULL); +} - if (ptp_priv->shared_addr != NULL) { - /* Reset memory */ - memset((void *)ptp_priv->shared_addr, 0, ptp_priv->dma_mem_size); - DBG_ERR(("Shared memory allocation (%d bytes) successful at 0x%016lx.\n", - ptp_priv->dma_mem_size, (long unsigned int)ptp_priv->dma_mem)); -#ifdef __LITTLE_ENDIAN - endianess = 0; -#else - endianess = 1; -#endif - DEV_WRITE32(ptp_priv, CMIC_CMC_SCHAN_MESSAGE_12r(CMIC_CMC_BASE), ((pci_cos << 16) | endianess)); +struct file_operations bksync_proc_debug_file_ops = { + owner: THIS_MODULE, + open: bksync_proc_debug_open, + read: seq_read, + llseek: seq_lseek, + write: bksync_proc_debug_write, + release: single_release, +}; - DEV_WRITE32(ptp_priv, CMIC_CMC_SCHAN_MESSAGE_10r(CMIC_CMC_BASE), - (ptp_priv->dma_mem & 0xffffffff)); - DEV_WRITE32(ptp_priv, CMIC_CMC_SCHAN_MESSAGE_11r(CMIC_CMC_BASE), - (ptp_priv->dma_mem >> 32) & 0xffffffff); - ptp_priv->dcb_type = dcb_type; - } +static int +bksync_proc_init(void) +{ + struct proc_dir_entry *entry; - if (debug & DBG_LVL_VERB) { - printk(KERN_EMERG"%s %p:%p\n",__FUNCTION__, - ptp_priv->base_addr,(void *)ptp_priv->shared_addr); + PROC_CREATE(entry, "stats", 0666, bksync_proc_root, &bksync_proc_txts_file_ops); + if (entry == NULL) { + return -1; + } + PROC_CREATE(entry, "debug", 0666, bksync_proc_root, &bksync_proc_debug_file_ops); + if (entry == NULL) { + return -1; } + return 0; +} - return; +static int +bksync_proc_cleanup(void) +{ + remove_proc_entry("stats", bksync_proc_root); + remove_proc_entry("debug", bksync_proc_root); + return 0; } -static void bksync_ptp_cmicx_dma_init(int dcb_type) +static void bksync_ptp_dma_init(int dcb_type) { int endianess; int num_pports = 256; - /* Initialize the Base address for CMIC and shared Memory access */ - ptp_priv->base_addr = lkbde_get_dev_virt(0); - ptp_priv->dma_dev = lkbde_get_dma_dev(0); + ptp_priv->num_pports = num_pports; ptp_priv->dcb_type = dcb_type; ptp_priv->dma_mem_size = 16384;/*sizeof(bksync_uc_linux_ipc_t);*/ if (ptp_priv->shared_addr == NULL) { ptp_priv->shared_addr = kzalloc(16384, GFP_KERNEL); - ptp_priv->num_pports = num_pports; ptp_priv->port_stats = kzalloc((sizeof(bksync_port_stats_t) * num_pports), GFP_KERNEL); } @@ -1678,10 +1699,10 @@ static void bksync_ptp_cmicx_dma_init(int dcb_type) #else endianess = 1; #endif - DEV_WRITE32(ptp_priv, CMIC_CMC_SCHAN_MESSAGE_12r(CMIC_CMC_BASE), ((pci_cos << 16) | endianess)); + DEV_WRITE32(ptp_priv, CMIC_CMC_SCHAN_MESSAGE_14r(CMIC_CMC_BASE), ((pci_cos << 16) | endianess)); - DEV_WRITE32(ptp_priv, CMIC_CMC_SCHAN_MESSAGE_10r(CMIC_CMC_BASE), 1); - DEV_WRITE32(ptp_priv, CMIC_CMC_SCHAN_MESSAGE_11r(CMIC_CMC_BASE), 1); + DEV_WRITE32(ptp_priv, CMIC_CMC_SCHAN_MESSAGE_15r(CMIC_CMC_BASE), 1); + DEV_WRITE32(ptp_priv, CMIC_CMC_SCHAN_MESSAGE_16r(CMIC_CMC_BASE), 1); } @@ -1690,6 +1711,7 @@ static void bksync_ptp_cmicx_dma_init(int dcb_type) ptp_priv->base_addr,(void *)ptp_priv->shared_addr); } + ptp_priv->mirror_encap_bmp = 0x0; hostcmd_regs[0] = CMIC_CMC_SCHAN_MESSAGE_21r(CMIC_CMC_BASE); hostcmd_regs[1] = CMIC_CMC_SCHAN_MESSAGE_20r(CMIC_CMC_BASE); @@ -1701,28 +1723,6 @@ static void bksync_ptp_cmicx_dma_init(int dcb_type) } -static void bksync_ptp_dma_init(int dcb_type) -{ - switch (dcb_type) { - case 26: - bksync_ptp_cmicm_dma_init(dcb_type); - ptp_priv->dcb_type = dcb_type; - break; - case 32: - case 36: - case 38: - bksync_ptp_cmicx_dma_init(dcb_type); - ptp_priv->dcb_type = dcb_type; - break; - default: - break; - } - - return; -} - - - /** * bksync_ioctl_cmd_handler * @kmsg: kcom message - ptp clock ioctl command. @@ -1732,6 +1732,7 @@ static void bksync_ptp_dma_init(int dcb_type) static int bksync_ioctl_cmd_handler(kcom_msg_clock_cmd_t *kmsg, int len, int dcb_type) { + u32 fw_status; kmsg->hdr.type = KCOM_MSG_TYPE_RSP; if (!module_initialized && kmsg->clock_info.cmd != KSYNC_M_HW_INIT) { @@ -1744,6 +1745,20 @@ bksync_ioctl_cmd_handler(kcom_msg_clock_cmd_t *kmsg, int len, int dcb_type) pci_cos = kmsg->clock_info.data[0]; if (kmsg->clock_info.data[1] == 0 || kmsg->clock_info.data[1] == 1) { fw_core = kmsg->clock_info.data[1]; + DEV_READ32(ptp_priv, CMIC_CMC_SCHAN_MESSAGE_21r(CMIC_CMC_BASE), &fw_status); + + /* Return success if the app is already initialized. */ + if (module_initialized) { + kmsg->hdr.status = KCOM_E_NONE; + return sizeof(kcom_msg_hdr_t); + } + + /* Return error if the app is not ready yet. */ + if (fw_status != 0xBADC0DE1) { + kmsg->hdr.status = KCOM_E_RESOURCE; + return sizeof(kcom_msg_hdr_t); + } + bksync_ptp_dma_init(dcb_type); if (bksync_ptp_init(&(ptp_priv->ptp_caps)) >= 0) { module_initialized = 1; @@ -1757,6 +1772,12 @@ bksync_ioctl_cmd_handler(kcom_msg_clock_cmd_t *kmsg, int len, int dcb_type) case KSYNC_M_HW_TS_DISABLE: bksync_ptp_hw_tstamp_disable(0, kmsg->clock_info.data[0], 0); break; + case KSYNC_M_MTP_TS_UPDATE_ENABLE: + bksync_ptp_mirror_encap_update(0, kmsg->clock_info.data[0], TRUE); + break; + case KSYNC_M_MTP_TS_UPDATE_DISABLE: + bksync_ptp_mirror_encap_update(0, kmsg->clock_info.data[0], FALSE); + break; case KSYNC_M_VERSION: break; default: @@ -1813,6 +1834,10 @@ static int bksync_ptp_register(void) /* Register ptp clock driver with bksync_ptp_caps */ ptp_priv->ptp_clock = ptp_clock_register(&ptp_priv->ptp_caps, NULL); + /* Initialize the Base address for CMIC and shared Memory access */ + ptp_priv->base_addr = lkbde_get_dev_virt(0); + ptp_priv->dma_dev = lkbde_get_dma_dev(0); + if (IS_ERR(ptp_priv->ptp_clock)) { ptp_priv->ptp_clock = NULL; } else if (ptp_priv->ptp_clock) { @@ -1858,8 +1883,8 @@ static int bksync_ptp_remove(void) bkn_hw_tstamp_ioctl_cmd_cb_unregister(bksync_ioctl_cmd_handler); if (module_initialized) { - DEV_WRITE32(ptp_priv, CMIC_CMC_SCHAN_MESSAGE_10r(CMIC_CMC_BASE), 0); - DEV_WRITE32(ptp_priv, CMIC_CMC_SCHAN_MESSAGE_11r(CMIC_CMC_BASE), 0); + DEV_WRITE32(ptp_priv, CMIC_CMC_SCHAN_MESSAGE_15r(CMIC_CMC_BASE), 0); + DEV_WRITE32(ptp_priv, CMIC_CMC_SCHAN_MESSAGE_16r(CMIC_CMC_BASE), 0); } /* Deinitialize the PTP */ bksync_ptp_deinit(&(ptp_priv->ptp_caps)); @@ -1870,12 +1895,7 @@ static int bksync_ptp_remove(void) ptp_priv->port_stats = NULL; } if (ptp_priv->shared_addr != NULL) { - if (HOSTCMD_USE_REGS) { - kfree((void *)ptp_priv->shared_addr); - } else { - DMA_FREE_COHERENT(ptp_priv->dma_dev, ptp_priv->dma_mem_size, - (void *)ptp_priv->shared_addr, (dma_addr_t)ptp_priv->dma_mem); - } + kfree((void *)ptp_priv->shared_addr); ptp_priv->shared_addr = NULL; DBG_ERR(("Free R5 memory\n")); } @@ -1906,13 +1926,13 @@ static int bksync_ptp_remove(void) * Always 0 */ static int -_pprint(void) +_pprint(struct seq_file *m) { #if LINUX_VERSION_CODE > KERNEL_VERSION(3,17,0) /* put some goodies here */ - pprintf("Broadcom BCM PTP Hardware Clock Module\n"); + pprintf(m, "Broadcom BCM PTP Hardware Clock Module\n"); #else - pprintf("Broadcom BCM PTP Hardware Clock Module not supported\n"); + pprintf(m, "Broadcom BCM PTP Hardware Clock Module not supported\n"); #endif return 0; } diff --git a/platform/broadcom/saibcm-modules/systems/linux/kernel/modules/include/bcm-knet.h b/platform/broadcom/saibcm-modules/systems/linux/kernel/modules/include/bcm-knet.h index df8874fb1f7..8d710869824 100644 --- a/platform/broadcom/saibcm-modules/systems/linux/kernel/modules/include/bcm-knet.h +++ b/platform/broadcom/saibcm-modules/systems/linux/kernel/modules/include/bcm-knet.h @@ -1,5 +1,10 @@ /* - * Copyright 2017 Broadcom + * Copyright 2007-2020 Broadcom Inc. All rights reserved. + * + * Permission is granted to use, copy, modify and/or distribute this + * software under either one of the licenses below. + * + * License Option 1: GPL * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License, version 2, as @@ -12,6 +17,12 @@ * * You should have received a copy of the GNU General Public License * version 2 (GPLv2) along with this source code. + * + * + * License Option 2: Broadcom Open Network Switch APIs (OpenNSA) license + * + * This software is governed by the Broadcom Open Network Switch APIs license: + * https://www.broadcom.com/products/ethernet-connectivity/software/opennsa */ /* * $Id: bcm-knet.h,v 1.4 Broadcom SDK $ @@ -137,7 +148,6 @@ bkn_hw_tstamp_ioctl_cmd_cb_register(knet_hw_tstamp_ioctl_cmd_cb_f hw_tstamp_ioct extern int bkn_hw_tstamp_ioctl_cmd_cb_unregister(knet_hw_tstamp_ioctl_cmd_cb_f hw_tstamp_ioctl_cmd_cb); - typedef struct { uint8 cmic_type; uint8 dcb_type; diff --git a/platform/broadcom/saibcm-modules/systems/linux/kernel/modules/include/gmodule.h b/platform/broadcom/saibcm-modules/systems/linux/kernel/modules/include/gmodule.h index 22cef82a8dd..a9db097f306 100644 --- a/platform/broadcom/saibcm-modules/systems/linux/kernel/modules/include/gmodule.h +++ b/platform/broadcom/saibcm-modules/systems/linux/kernel/modules/include/gmodule.h @@ -1,5 +1,10 @@ /* - * Copyright 2017 Broadcom + * Copyright 2007-2020 Broadcom Inc. All rights reserved. + * + * Permission is granted to use, copy, modify and/or distribute this + * software under either one of the licenses below. + * + * License Option 1: GPL * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License, version 2, as @@ -12,6 +17,12 @@ * * You should have received a copy of the GNU General Public License * version 2 (GPLv2) along with this source code. + * + * + * License Option 2: Broadcom Open Network Switch APIs (OpenNSA) license + * + * This software is governed by the Broadcom Open Network Switch APIs license: + * https://www.broadcom.com/products/ethernet-connectivity/software/opennsa */ /* * $Id: gmodule.h,v 1.9 Broadcom SDK $ @@ -23,6 +34,7 @@ #define __COMMON_LINUX_KRN_GMODULE_H__ #include +#include typedef struct gmodule_s { @@ -32,9 +44,7 @@ typedef struct gmodule_s { int (*init)(void); int (*cleanup)(void); - - int (*pprint)(void); - + int (*pprint)(struct seq_file *m); int (*open)(void); int (*ioctl)(unsigned int cmd, unsigned long arg); int (*close)(void); @@ -48,8 +58,8 @@ extern gmodule_t* gmodule_get(void); /* Proc Filesystem information */ -extern int pprintf(const char* fmt, ...) - __attribute__ ((format (printf, 1, 2))); +extern int pprintf(struct seq_file *m, const char* fmt, ...) + __attribute__ ((format (printf, 2, 3))); extern int gmodule_vpprintf(char** page, const char* fmt, va_list args) __attribute__ ((format (printf, 2, 0))); extern int gmodule_pprintf(char** page, const char* fmt, ...) diff --git a/platform/broadcom/saibcm-modules/systems/linux/kernel/modules/include/lkm.h b/platform/broadcom/saibcm-modules/systems/linux/kernel/modules/include/lkm.h index 56d641c9c87..9ea8fc5896d 100644 --- a/platform/broadcom/saibcm-modules/systems/linux/kernel/modules/include/lkm.h +++ b/platform/broadcom/saibcm-modules/systems/linux/kernel/modules/include/lkm.h @@ -1,5 +1,10 @@ /* - * Copyright 2017 Broadcom + * Copyright 2007-2020 Broadcom Inc. All rights reserved. + * + * Permission is granted to use, copy, modify and/or distribute this + * software under either one of the licenses below. + * + * License Option 1: GPL * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License, version 2, as @@ -12,6 +17,12 @@ * * You should have received a copy of the GNU General Public License * version 2 (GPLv2) along with this source code. + * + * + * License Option 2: Broadcom Open Network Switch APIs (OpenNSA) license + * + * This software is governed by the Broadcom Open Network Switch APIs license: + * https://www.broadcom.com/products/ethernet-connectivity/software/opennsa */ /* * $Id: lkm.h,v 1.22 Broadcom SDK $ @@ -34,7 +45,8 @@ #if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0) #include #endif -#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,1,0) +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,32) +/* The version kconfig.h became available in. */ #include #endif #if LINUX_VERSION_CODE >= KERNEL_VERSION(3,10,0) diff --git a/platform/broadcom/saibcm-modules/systems/linux/kernel/modules/knet-cb/Makefile b/platform/broadcom/saibcm-modules/systems/linux/kernel/modules/knet-cb/Makefile index 3de3e07080c..b8697731dd4 100644 --- a/platform/broadcom/saibcm-modules/systems/linux/kernel/modules/knet-cb/Makefile +++ b/platform/broadcom/saibcm-modules/systems/linux/kernel/modules/knet-cb/Makefile @@ -1,5 +1,10 @@ # -# Copyright 2017 Broadcom +# Copyright 2007-2020 Broadcom Inc. All rights reserved. +# +# Permission is granted to use, copy, modify and/or distribute this +# software under either one of the licenses below. +# +# License Option 1: GPL # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License, version 2, as @@ -12,6 +17,12 @@ # # You should have received a copy of the GNU General Public License # version 2 (GPLv2) along with this source code. +# +# +# License Option 2: Broadcom Open Network Switch APIs (OpenNSA) license +# +# This software is governed by the Broadcom Open Network Switch APIs license: +# https://www.broadcom.com/products/ethernet-connectivity/software/opennsa # # -*- Makefile -*- # $Id: Makefile,v 1.3 Broadcom SDK $ diff --git a/platform/broadcom/saibcm-modules/systems/linux/kernel/modules/knet-cb/knet-cb.c b/platform/broadcom/saibcm-modules/systems/linux/kernel/modules/knet-cb/knet-cb.c index 1626d33c1c5..650a4ced1d7 100644 --- a/platform/broadcom/saibcm-modules/systems/linux/kernel/modules/knet-cb/knet-cb.c +++ b/platform/broadcom/saibcm-modules/systems/linux/kernel/modules/knet-cb/knet-cb.c @@ -107,7 +107,7 @@ static struct sk_buff *strip_tag_rx_cb(struct sk_buff *skb, int dev_no, void *me static struct sk_buff *strip_tag_tx_cb(struct sk_buff *skb, int dev_no, void *meta); static int strip_tag_filter_cb(uint8_t * pkt, int size, int dev_no, void *meta, int chan, kcom_filter_t * kf); -static int _pprint(void); +static int _pprint(struct seq_file *m); static int _cleanup(void); static int _init(void); @@ -333,11 +333,11 @@ knet_filter_cb(uint8_t * pkt, int size, int dev_no, void *meta, int chan, kcom_filter_t *kf) { /* check for filter callback handler */ -#ifdef PSAMPLE_SUPPORT + #ifdef PSAMPLE_SUPPORT if (strncmp(kf->desc, PSAMPLE_CB_NAME, KCOM_FILTER_DESC_MAX) == 0) { return psample_filter_cb (pkt, size, dev_no, meta, chan, kf); } -#endif + #endif return strip_tag_filter_cb (pkt, size, dev_no, meta, chan, kf); } @@ -366,12 +366,12 @@ knet_netif_destroy_cb(int unit, kcom_netif_t *netif, struct net_device *dev) * % cat /proc/linux-knet-cb */ static int -_pprint(void) +_pprint(struct seq_file *m) { - pprintf("Broadcom Linux KNET Call-Back: Untagged VLAN Stripper\n"); - pprintf(" %lu stripped packets\n", strip_stats.stripped); - pprintf(" %lu packets checked\n", strip_stats.checked); - pprintf(" %lu packets skipped\n", strip_stats.skipped); + pprintf(m, "Broadcom Linux KNET Call-Back: Untagged VLAN Stripper\n"); + pprintf(m, " %lu stripped packets\n", strip_stats.stripped); + pprintf(m ," %lu packets checked\n", strip_stats.checked); + pprintf(m, " %lu packets skipped\n", strip_stats.skipped); return 0; } @@ -395,6 +395,7 @@ _cleanup(void) #ifdef PSAMPLE_SUPPORT psample_cleanup(); #endif + return 0; } @@ -410,9 +411,10 @@ _init(void) bkn_tx_skb_cb_register(strip_tag_tx_cb); } -#ifdef PSAMPLE_SUPPORT + #ifdef PSAMPLE_SUPPORT psample_init(); -#endif + #endif + bkn_filter_cb_register(knet_filter_cb); bkn_netif_create_cb_register(knet_netif_create_cb); diff --git a/platform/broadcom/saibcm-modules/systems/linux/kernel/modules/knet-cb/psample-cb.c b/platform/broadcom/saibcm-modules/systems/linux/kernel/modules/knet-cb/psample-cb.c index e1a6086a52a..755955b20fd 100644 --- a/platform/broadcom/saibcm-modules/systems/linux/kernel/modules/knet-cb/psample-cb.c +++ b/platform/broadcom/saibcm-modules/systems/linux/kernel/modules/knet-cb/psample-cb.c @@ -967,7 +967,7 @@ psample_proc_stats_open(struct inode * inode, struct file * file) * psample stats Proc Write Entry * * Syntax: - * write any value to clear stats + * write any value to clear stats */ static ssize_t psample_proc_stats_write(struct file *file, const char *buf, @@ -1009,13 +1009,13 @@ int psample_cleanup(void) int psample_init(void) { #define PROCFS_MAX_PATH 1024 + #define PSAMPLE_PROCFS_PATH "bcm/knet-cb" char psample_procfs_path[PROCFS_MAX_PATH]; struct proc_dir_entry *entry; /* create procfs for psample */ - snprintf(psample_procfs_path, PROCFS_MAX_PATH, "bcm/knet-cb"); - knet_cb_proc_root = proc_mkdir(psample_procfs_path, NULL); - snprintf(psample_procfs_path, PROCFS_MAX_PATH, "%s/%s", psample_procfs_path, PSAMPLE_CB_NAME); + proc_mkdir(PSAMPLE_PROCFS_PATH, NULL); + snprintf(psample_procfs_path, sizeof(psample_procfs_path), "%s/%s", PSAMPLE_PROCFS_PATH, PSAMPLE_CB_NAME); psample_proc_root = proc_mkdir(psample_procfs_path, NULL); /* create procfs for psample stats */ @@ -1031,7 +1031,7 @@ int psample_init(void) gprintk("%s: Unable to create procfs entry '/procfs/%s/rate'\n", __func__, psample_procfs_path); return -1; } - + /* create procfs for setting sample size */ PROC_CREATE(entry, "size", 0666, psample_proc_root, &psample_proc_size_file_ops); if (entry == NULL) { @@ -1059,23 +1059,23 @@ int psample_init(void) memset(&g_psample_work, 0, sizeof(psample_work_t)); /* setup psample_info struct */ - INIT_LIST_HEAD(&g_psample_info.netif_list); + INIT_LIST_HEAD(&g_psample_info.netif_list); spin_lock_init(&g_psample_info.lock); /* setup psample work queue */ - spin_lock_init(&g_psample_work.lock); - INIT_LIST_HEAD(&g_psample_work.pkt_list); + spin_lock_init(&g_psample_work.lock); + INIT_LIST_HEAD(&g_psample_work.pkt_list); INIT_WORK(&g_psample_work.wq, psample_task); - /* get net namespace */ + /* get net namespace */ g_psample_info.netns = get_net_ns_by_pid(current->pid); if (!g_psample_info.netns) { gprintk("%s: Could not get network namespace for pid %d\n", __func__, current->pid); return (-1); } - PSAMPLE_CB_DBG_PRINT("%s: current->pid %d, netns 0x%p, sample_size %d\n", __func__, + PSAMPLE_CB_DBG_PRINT("%s: current->pid %d, netns 0x%p, sample_size %d\n", __func__, current->pid, g_psample_info.netns, psample_size); - + return 0; } diff --git a/platform/broadcom/saibcm-modules/systems/linux/kernel/modules/psample/psample.c b/platform/broadcom/saibcm-modules/systems/linux/kernel/modules/psample/psample.c index 1deccacc5ed..99317cbf30c 100644 --- a/platform/broadcom/saibcm-modules/systems/linux/kernel/modules/psample/psample.c +++ b/platform/broadcom/saibcm-modules/systems/linux/kernel/modules/psample/psample.c @@ -224,7 +224,7 @@ void psample_sample_packet(struct psample_group *group, struct sk_buff *skb, data_len = PSAMPLE_MAX_PACKET_SIZE - meta_len - NLA_HDRLEN - NLA_ALIGNTO; - nl_skb = genlmsg_new(meta_len + data_len, GFP_ATOMIC); + nl_skb = genlmsg_new(meta_len + nla_total_size(data_len), GFP_ATOMIC); if (unlikely(!nl_skb)) return; diff --git a/platform/broadcom/saibcm-modules/systems/linux/kernel/modules/shared/Makefile b/platform/broadcom/saibcm-modules/systems/linux/kernel/modules/shared/Makefile index 5e97a3a3212..966f639f698 100644 --- a/platform/broadcom/saibcm-modules/systems/linux/kernel/modules/shared/Makefile +++ b/platform/broadcom/saibcm-modules/systems/linux/kernel/modules/shared/Makefile @@ -1,5 +1,10 @@ # -# Copyright 2017 Broadcom +# Copyright 2007-2020 Broadcom Inc. All rights reserved. +# +# Permission is granted to use, copy, modify and/or distribute this +# software under either one of the licenses below. +# +# License Option 1: GPL # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License, version 2, as @@ -12,6 +17,12 @@ # # You should have received a copy of the GNU General Public License # version 2 (GPLv2) along with this source code. +# +# +# License Option 2: Broadcom Open Network Switch APIs (OpenNSA) license +# +# This software is governed by the Broadcom Open Network Switch APIs license: +# https://www.broadcom.com/products/ethernet-connectivity/software/opennsa # # -*- Makefile -*- # $Id: Makefile,v 1.2 Broadcom SDK $ diff --git a/platform/broadcom/saibcm-modules/systems/linux/kernel/modules/shared/gmodule.c b/platform/broadcom/saibcm-modules/systems/linux/kernel/modules/shared/gmodule.c index cdfaf089674..3ef00096183 100644 --- a/platform/broadcom/saibcm-modules/systems/linux/kernel/modules/shared/gmodule.c +++ b/platform/broadcom/saibcm-modules/systems/linux/kernel/modules/shared/gmodule.c @@ -1,5 +1,10 @@ /* - * Copyright 2017 Broadcom + * Copyright 2007-2020 Broadcom Inc. All rights reserved. + * + * Permission is granted to use, copy, modify and/or distribute this + * software under either one of the licenses below. + * + * License Option 1: GPL * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License, version 2, as @@ -12,6 +17,12 @@ * * You should have received a copy of the GNU General Public License * version 2 (GPLv2) along with this source code. + * + * + * License Option 2: Broadcom Open Network Switch APIs (OpenNSA) license + * + * This software is governed by the Broadcom Open Network Switch APIs license: + * https://www.broadcom.com/products/ethernet-connectivity/software/opennsa */ /* * $Id: gmodule.c,v 1.20 Broadcom SDK $ @@ -26,8 +37,6 @@ #include #include #include -#include - /* Module Vector Table */ static gmodule_t* _gmodule = NULL; @@ -94,21 +103,18 @@ gdbg(const char* fmt, ...) * Proc FS Utilities */ #if PROC_INTERFACE_KERN_VER_3_10 -static struct seq_file* _proc_buf = NULL; - int -pprintf(const char* fmt, ...) +pprintf(struct seq_file *m, const char* fmt, ...) { va_list args; va_start(args, fmt); - seq_vprintf(_proc_buf, fmt, args); + seq_vprintf(m, fmt, args); va_end(args); return 0; } static int _gmodule_proc_show(struct seq_file *m, void *v){ - _proc_buf = m; - _gmodule->pprint(); + _gmodule->pprint(m); return 0; } @@ -174,7 +180,7 @@ gmodule_pprintf(char** page_ptr, const char* fmt, ...) static char* _proc_buf = NULL; int -pprintf(const char* fmt, ...) +pprintf(struct seq_file *m, const char* fmt, ...) { int rv; @@ -193,7 +199,7 @@ static int _gmodule_pprint(char* buf) { PSTART(buf); - _gmodule->pprint(); + _gmodule->pprint(NULL); return PEND(buf); } diff --git a/platform/broadcom/saibcm-modules/systems/linux/kernel/modules/shared/ksal.c b/platform/broadcom/saibcm-modules/systems/linux/kernel/modules/shared/ksal.c index d1caf871f0e..7f90c59c3a3 100644 --- a/platform/broadcom/saibcm-modules/systems/linux/kernel/modules/shared/ksal.c +++ b/platform/broadcom/saibcm-modules/systems/linux/kernel/modules/shared/ksal.c @@ -1,5 +1,10 @@ /* - * Copyright 2017 Broadcom + * Copyright 2007-2020 Broadcom Inc. All rights reserved. + * + * Permission is granted to use, copy, modify and/or distribute this + * software under either one of the licenses below. + * + * License Option 1: GPL * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License, version 2, as @@ -12,6 +17,12 @@ * * You should have received a copy of the GNU General Public License * version 2 (GPLv2) along with this source code. + * + * + * License Option 2: Broadcom Open Network Switch APIs (OpenNSA) license + * + * This software is governed by the Broadcom Open Network Switch APIs license: + * https://www.broadcom.com/products/ethernet-connectivity/software/opennsa */ /* * $Id: ksal.c,v 1.1 Broadcom SDK $ diff --git a/platform/broadcom/saibcm-modules/systems/linux/user/common/Makefile b/platform/broadcom/saibcm-modules/systems/linux/user/common/Makefile index f95593a383c..8f59a763e31 100644 --- a/platform/broadcom/saibcm-modules/systems/linux/user/common/Makefile +++ b/platform/broadcom/saibcm-modules/systems/linux/user/common/Makefile @@ -1,5 +1,10 @@ # -# Copyright 2017 Broadcom +# Copyright 2007-2020 Broadcom Inc. All rights reserved. +# +# Permission is granted to use, copy, modify and/or distribute this +# software under either one of the licenses below. +# +# License Option 1: GPL # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License, version 2, as @@ -12,6 +17,12 @@ # # You should have received a copy of the GNU General Public License # version 2 (GPLv2) along with this source code. +# +# +# License Option 2: Broadcom Open Network Switch APIs (OpenNSA) license +# +# This software is governed by the Broadcom Open Network Switch APIs license: +# https://www.broadcom.com/products/ethernet-connectivity/software/opennsa # # -*- Makefile -*- # $Id: Makefile,v 1.4 Broadcom SDK $ @@ -113,6 +124,7 @@ endif ifndef BUILD_KNET BUILD_KNET = 1 endif + # Remove this when LinuxPTP support becomes optional. ifndef BUILD_LPTP BUILD_LPTP = 1 @@ -141,7 +153,6 @@ ifdef BUILD_PSAMPLE all_targets += $(PSAMPLE) ADD_TO_CFLAGS += -DPSAMPLE_SUPPORT - # KnetSync support ifdef BUILD_KNETSYNC @@ -151,17 +162,17 @@ LOCAL_KERNEL_TARGETS += $(patsubst %,$(realpath ..)/$(platform)/%,$(BCM_PTP_CLOC endif # BUILD_KNETSYNC ifeq ($(NO_LOCAL_TARGETS),) -LOCAL_TARGETS +=$(patsubst %,../$(platform)/%,$(PSAMPLE_LOCAL)) -all_targets +=$(LOCAL_TARGETS) + LOCAL_TARGETS +=$(patsubst %,../$(platform)/%,$(PSAMPLE_LOCAL)) + all_targets +=$(LOCAL_TARGETS) endif endif ifdef BUILD_LPTP -all_targets += $(BCM_LPTP) + all_targets += $(BCM_LPTP) ifeq ($(NO_LOCAL_TARGETS),) -LOCAL_TARGETS +=$(patsubst %,../$(platform)/%,$(BCM_LPTP_LOCAL)) -all_targets +=$(LOCAL_TARGETS) + LOCAL_TARGETS +=$(patsubst %,../$(platform)/%,$(BCM_LPTP_LOCAL)) + all_targets +=$(LOCAL_TARGETS) endif endif @@ -191,7 +202,7 @@ CFLAGS:=$(filter-out -fPIC, $(CFLAGS)) # KnetSync Support ifdef BUILD_KNETSYNC -knetsync_subdirs = bcm-ptp-clock + knetsync_subdirs = bcm-ptp-clock endif # BUILD_KNETSYNC kernel_modules: @@ -200,7 +211,7 @@ kernel_modules: ifeq ($(BUILD_KNET),1) $(MAKE) -C $(SDK)/systems/linux/kernel/modules kernel_version=$(kernel_version) \ subdirs="shared bcm-knet" override-target=linux-$(platform) CFLAGS="$(CFLAGS)" -ifdef BUILD_PSAMPLE +ifdef BUILD_PSAMPLE $(MAKE) -C $(SDK)/systems/linux/kernel/modules kernel_version=$(kernel_version) \ subdirs="psample" override-target=linux-$(platform) CFLAGS="$(CFLAGS)" endif diff --git a/platform/broadcom/saibcm-modules/systems/linux/user/gts/Makefile b/platform/broadcom/saibcm-modules/systems/linux/user/gts/Makefile index 466faf02a51..5acaeab271c 100644 --- a/platform/broadcom/saibcm-modules/systems/linux/user/gts/Makefile +++ b/platform/broadcom/saibcm-modules/systems/linux/user/gts/Makefile @@ -1,5 +1,10 @@ # -# Copyright 2017 Broadcom +# Copyright 2007-2020 Broadcom Inc. All rights reserved. +# +# Permission is granted to use, copy, modify and/or distribute this +# software under either one of the licenses below. +# +# License Option 1: GPL # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License, version 2, as @@ -12,6 +17,12 @@ # # You should have received a copy of the GNU General Public License # version 2 (GPLv2) along with this source code. +# +# +# License Option 2: Broadcom Open Network Switch APIs (OpenNSA) license +# +# This software is governed by the Broadcom Open Network Switch APIs license: +# https://www.broadcom.com/products/ethernet-connectivity/software/opennsa # # -*- Makefile -*- # $Id: Makefile,v 0.1 Broadcom SDK $ diff --git a/platform/broadcom/saibcm-modules/systems/linux/user/iproc-3_14/Makefile b/platform/broadcom/saibcm-modules/systems/linux/user/iproc-3_14/Makefile index c9f538802f6..b874340ddec 100644 --- a/platform/broadcom/saibcm-modules/systems/linux/user/iproc-3_14/Makefile +++ b/platform/broadcom/saibcm-modules/systems/linux/user/iproc-3_14/Makefile @@ -1,5 +1,10 @@ # -# Copyright 2017 Broadcom +# Copyright 2007-2020 Broadcom Inc. All rights reserved. +# +# Permission is granted to use, copy, modify and/or distribute this +# software under either one of the licenses below. +# +# License Option 1: GPL # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License, version 2, as @@ -12,6 +17,12 @@ # # You should have received a copy of the GNU General Public License # version 2 (GPLv2) along with this source code. +# +# +# License Option 2: Broadcom Open Network Switch APIs (OpenNSA) license +# +# This software is governed by the Broadcom Open Network Switch APIs license: +# https://www.broadcom.com/products/ethernet-connectivity/software/opennsa # # -*- Makefile -*- # $Id: Makefile,v 1.7 Broadcom SDK $ diff --git a/platform/broadcom/saibcm-modules/systems/linux/user/iproc-4_4/Makefile b/platform/broadcom/saibcm-modules/systems/linux/user/iproc-4_4/Makefile index e8405f5c2a0..2b724be3202 100644 --- a/platform/broadcom/saibcm-modules/systems/linux/user/iproc-4_4/Makefile +++ b/platform/broadcom/saibcm-modules/systems/linux/user/iproc-4_4/Makefile @@ -1,5 +1,10 @@ # -# Copyright 2017 Broadcom +# Copyright 2007-2020 Broadcom Inc. All rights reserved. +# +# Permission is granted to use, copy, modify and/or distribute this +# software under either one of the licenses below. +# +# License Option 1: GPL # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License, version 2, as @@ -12,6 +17,12 @@ # # You should have received a copy of the GNU General Public License # version 2 (GPLv2) along with this source code. +# +# +# License Option 2: Broadcom Open Network Switch APIs (OpenNSA) license +# +# This software is governed by the Broadcom Open Network Switch APIs license: +# https://www.broadcom.com/products/ethernet-connectivity/software/opennsa # # -*- Makefile -*- # $Id: Makefile,v 1.7 Broadcom SDK $ diff --git a/platform/broadcom/saibcm-modules/systems/linux/user/iproc/Makefile b/platform/broadcom/saibcm-modules/systems/linux/user/iproc/Makefile index 03300ff8a04..f10c5c37a08 100644 --- a/platform/broadcom/saibcm-modules/systems/linux/user/iproc/Makefile +++ b/platform/broadcom/saibcm-modules/systems/linux/user/iproc/Makefile @@ -1,5 +1,10 @@ # -# Copyright 2017 Broadcom +# Copyright 2007-2020 Broadcom Inc. All rights reserved. +# +# Permission is granted to use, copy, modify and/or distribute this +# software under either one of the licenses below. +# +# License Option 1: GPL # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License, version 2, as @@ -12,6 +17,12 @@ # # You should have received a copy of the GNU General Public License # version 2 (GPLv2) along with this source code. +# +# +# License Option 2: Broadcom Open Network Switch APIs (OpenNSA) license +# +# This software is governed by the Broadcom Open Network Switch APIs license: +# https://www.broadcom.com/products/ethernet-connectivity/software/opennsa # # -*- Makefile -*- # $Id: Makefile,v 1.7 Broadcom SDK $ diff --git a/platform/broadcom/saibcm-modules/systems/linux/user/iproc_64/Makefile b/platform/broadcom/saibcm-modules/systems/linux/user/iproc_64/Makefile index 778c85a03be..983b3abbced 100644 --- a/platform/broadcom/saibcm-modules/systems/linux/user/iproc_64/Makefile +++ b/platform/broadcom/saibcm-modules/systems/linux/user/iproc_64/Makefile @@ -1,5 +1,10 @@ # -# Copyright 2017 Broadcom +# Copyright 2007-2020 Broadcom Inc. All rights reserved. +# +# Permission is granted to use, copy, modify and/or distribute this +# software under either one of the licenses below. +# +# License Option 1: GPL # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License, version 2, as @@ -12,6 +17,12 @@ # # You should have received a copy of the GNU General Public License # version 2 (GPLv2) along with this source code. +# +# +# License Option 2: Broadcom Open Network Switch APIs (OpenNSA) license +# +# This software is governed by the Broadcom Open Network Switch APIs license: +# https://www.broadcom.com/products/ethernet-connectivity/software/opennsa # # -*- Makefile -*- # $Id: Makefile,v 1.7 Broadcom SDK $ diff --git a/platform/broadcom/saibcm-modules/systems/linux/user/slk/Makefile b/platform/broadcom/saibcm-modules/systems/linux/user/slk/Makefile index 99d49d28514..6ef36015657 100644 --- a/platform/broadcom/saibcm-modules/systems/linux/user/slk/Makefile +++ b/platform/broadcom/saibcm-modules/systems/linux/user/slk/Makefile @@ -1,5 +1,10 @@ # -# Copyright 2017 Broadcom +# Copyright 2007-2020 Broadcom Inc. All rights reserved. +# +# Permission is granted to use, copy, modify and/or distribute this +# software under either one of the licenses below. +# +# License Option 1: GPL # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License, version 2, as @@ -12,6 +17,12 @@ # # You should have received a copy of the GNU General Public License # version 2 (GPLv2) along with this source code. +# +# +# License Option 2: Broadcom Open Network Switch APIs (OpenNSA) license +# +# This software is governed by the Broadcom Open Network Switch APIs license: +# https://www.broadcom.com/products/ethernet-connectivity/software/opennsa # # -*- Makefile -*- # $Id: Makefile,v 0.1 Broadcom SDK $ diff --git a/platform/broadcom/saibcm-modules/systems/linux/user/x86-smp_generic_64-2_6/Makefile b/platform/broadcom/saibcm-modules/systems/linux/user/x86-smp_generic_64-2_6/Makefile index 29717b3af42..78c2c0cb170 100644 --- a/platform/broadcom/saibcm-modules/systems/linux/user/x86-smp_generic_64-2_6/Makefile +++ b/platform/broadcom/saibcm-modules/systems/linux/user/x86-smp_generic_64-2_6/Makefile @@ -1,5 +1,10 @@ # -# Copyright 2017 Broadcom +# Copyright 2007-2020 Broadcom Inc. All rights reserved. +# +# Permission is granted to use, copy, modify and/or distribute this +# software under either one of the licenses below. +# +# License Option 1: GPL # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License, version 2, as @@ -12,6 +17,12 @@ # # You should have received a copy of the GNU General Public License # version 2 (GPLv2) along with this source code. +# +# +# License Option 2: Broadcom Open Network Switch APIs (OpenNSA) license +# +# This software is governed by the Broadcom Open Network Switch APIs license: +# https://www.broadcom.com/products/ethernet-connectivity/software/opennsa # # -*- Makefile -*- # $Id: Makefile,v 1.2 Broadcom SDK $ diff --git a/platform/broadcom/saibcm-modules/systems/linux/user/xlr/Makefile b/platform/broadcom/saibcm-modules/systems/linux/user/xlr/Makefile index 13246d09e78..e19eeff4aef 100644 --- a/platform/broadcom/saibcm-modules/systems/linux/user/xlr/Makefile +++ b/platform/broadcom/saibcm-modules/systems/linux/user/xlr/Makefile @@ -1,5 +1,10 @@ # -# Copyright 2017 Broadcom +# Copyright 2007-2020 Broadcom Inc. All rights reserved. +# +# Permission is granted to use, copy, modify and/or distribute this +# software under either one of the licenses below. +# +# License Option 1: GPL # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License, version 2, as @@ -12,6 +17,12 @@ # # You should have received a copy of the GNU General Public License # version 2 (GPLv2) along with this source code. +# +# +# License Option 2: Broadcom Open Network Switch APIs (OpenNSA) license +# +# This software is governed by the Broadcom Open Network Switch APIs license: +# https://www.broadcom.com/products/ethernet-connectivity/software/opennsa # # -*- Makefile -*- # $Id: Makefile,v 0.1 Broadcom SDK $ diff --git a/platform/broadcom/saibcm-modules/tools/mktool.pl b/platform/broadcom/saibcm-modules/tools/mktool.pl index 8800c00613d..518ab25535c 100644 --- a/platform/broadcom/saibcm-modules/tools/mktool.pl +++ b/platform/broadcom/saibcm-modules/tools/mktool.pl @@ -1,5 +1,10 @@ # -# Copyright 2017 Broadcom +# Copyright 2007-2020 Broadcom Inc. All rights reserved. +# +# Permission is granted to use, copy, modify and/or distribute this +# software under either one of the licenses below. +# +# License Option 1: GPL # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License, version 2, as @@ -12,6 +17,12 @@ # # You should have received a copy of the GNU General Public License # version 2 (GPLv2) along with this source code. +# +# +# License Option 2: Broadcom Open Network Switch APIs (OpenNSA) license +# +# This software is governed by the Broadcom Open Network Switch APIs license: +# https://www.broadcom.com/products/ethernet-connectivity/software/opennsa # # # mktool.pl diff --git a/platform/broadcom/sonic-platform-modules-accton/as4630-54pe/utils/accton_as4630_54pe_util.py b/platform/broadcom/sonic-platform-modules-accton/as4630-54pe/utils/accton_as4630_54pe_util.py index ed0df177ee1..4039119288a 100755 --- a/platform/broadcom/sonic-platform-modules-accton/as4630-54pe/utils/accton_as4630_54pe_util.py +++ b/platform/broadcom/sonic-platform-modules-accton/as4630-54pe/utils/accton_as4630_54pe_util.py @@ -214,10 +214,12 @@ def log_os_system(cmd, show): return status, output def driver_inserted(): - ret, lsmod = log_os_system("lsmod| grep accton", 0) + ret, lsmod = log_os_system("ls /sys/module/*accton*", 0) logging.info('mods:'+lsmod) - if len(lsmod) ==0: + if ret : return False + else : + return True #'modprobe cpr_4011_4mxx', diff --git a/platform/broadcom/sonic-platform-modules-alphanetworks/debian/control b/platform/broadcom/sonic-platform-modules-alphanetworks/debian/control index 6c7b1c41446..6535dbb88bb 100644 --- a/platform/broadcom/sonic-platform-modules-alphanetworks/debian/control +++ b/platform/broadcom/sonic-platform-modules-alphanetworks/debian/control @@ -7,11 +7,11 @@ Standards-Version: 3.9.3 Package: sonic-platform-alphanetworks-snh60a0-320fv2 Architecture: amd64 -Depends: linux-image-4.19.0-9-2-amd64-unsigned +Depends: linux-image-4.19.0-12-2-amd64-unsigned Description: kernel modules for platform devices such as fan, led, sfp Package: sonic-platform-alphanetworks-snh60b0-640f Architecture: amd64 -Depends: linux-image-4.19.0-9-2-amd64-unsigned +Depends: linux-image-4.19.0-12-2-amd64-unsigned Description: kernel modules for platform devices such as fan, led, sfp diff --git a/platform/broadcom/sonic-platform-modules-cel/debian/control b/platform/broadcom/sonic-platform-modules-cel/debian/control index 1eedf83d07b..a41f92ab54e 100644 --- a/platform/broadcom/sonic-platform-modules-cel/debian/control +++ b/platform/broadcom/sonic-platform-modules-cel/debian/control @@ -7,21 +7,21 @@ Standards-Version: 3.9.3 Package: platform-modules-dx010 Architecture: amd64 -Depends: linux-image-4.19.0-9-2-amd64-unsigned +Depends: linux-image-4.19.0-12-2-amd64-unsigned Description: kernel modules for platform devices such as fan, led, sfp Package: platform-modules-haliburton Architecture: amd64 -Depends: linux-image-4.19.0-9-2-amd64-unsigned +Depends: linux-image-4.19.0-12-2-amd64-unsigned Description: kernel modules for platform devices such as fan, led, sfp Package: platform-modules-seastone2 Architecture: amd64 -Depends: linux-image-4.19.0-9-2-amd64-unsigned +Depends: linux-image-4.19.0-12-2-amd64-unsigned Description: kernel modules for platform devices such as led, sfp Package: platform-modules-silverstone Architecture: amd64 -Depends: linux-image-4.19.0-9-2-amd64-unsigned +Depends: linux-image-4.19.0-12-2-amd64-unsigned Description: kernel modules for platform devices such as led, sfp. diff --git a/platform/broadcom/sonic-platform-modules-cel/services/platform_api/sonic_platform/sfp.py b/platform/broadcom/sonic-platform-modules-cel/services/platform_api/sonic_platform/sfp.py index 17f2756dee1..5906050fa13 100644 --- a/platform/broadcom/sonic-platform-modules-cel/services/platform_api/sonic_platform/sfp.py +++ b/platform/broadcom/sonic-platform-modules-cel/services/platform_api/sonic_platform/sfp.py @@ -358,7 +358,7 @@ def _dom_capability_detect(self): QSFP_VERSION_COMPLIANCE_OFFSET, QSFP_VERSION_COMPLIANCE_WIDTH) qsfp_version_compliance = int( qsfp_version_compliance_raw[0], 16) - dom_capability = sfpi_obj.parse_qsfp_dom_capability( + dom_capability = sfpi_obj.parse_dom_capability( qsfp_dom_capability_raw, 0) if qsfp_version_compliance >= 0x08: self.dom_temp_supported = dom_capability['data']['Temp_support']['value'] == 'On' diff --git a/platform/broadcom/sonic-platform-modules-dell/common/dell_pmc.c b/platform/broadcom/sonic-platform-modules-dell/common/dell_pmc.c index 3193e8b4642..5712c0fbb55 100644 --- a/platform/broadcom/sonic-platform-modules-dell/common/dell_pmc.c +++ b/platform/broadcom/sonic-platform-modules-dell/common/dell_pmc.c @@ -174,6 +174,9 @@ /* Mailbox PowerOn Reason */ #define TRACK_POWERON_REASON 0x05FF +/* System Status LED */ +#define SYSTEM_STATUS_LED 0x04DF + /* CPU Set IO Modules */ #define CPU_IOM1_CTRL_FLAG 0x04D9 #define CPU_IOM2_CTRL_FLAG 0x04DA @@ -607,6 +610,44 @@ static ssize_t show_mb_poweron_reason(struct device *dev, return sprintf(buf, "0x%x\n", ret); } +/* System Status LED */ +static ssize_t set_sys_status_led(struct device *dev, + struct device_attribute *devattr, const char *buf, size_t count) +{ + int err = 0; + unsigned int dev_data = 0; + struct smf_data *data = dev_get_drvdata(dev); + + if (data->kind == z9100smf) + return -1; + + err = kstrtouint(buf, 16, &dev_data); + if (err) + return err; + + err = smf_write_reg(data, SYSTEM_STATUS_LED, dev_data); + if(err < 0) + return err; + + return count; +} + +static ssize_t show_sys_status_led(struct device *dev, + struct device_attribute *devattr, char *buf) +{ + unsigned int ret = 0; + struct smf_data *data = dev_get_drvdata(dev); + + if (data->kind == z9100smf) + return 0; + + ret = smf_read_reg(data, SYSTEM_STATUS_LED); + if(ret < 0) + return ret; + + return sprintf(buf, "0x%x\n", ret); +} + /* FANIN ATTR */ static ssize_t show_fan_label(struct device *dev, struct device_attribute *attr, char *buf) @@ -2081,12 +2122,17 @@ static SENSOR_DEVICE_ATTR(smf_poweron_reason, S_IRUGO, static SENSOR_DEVICE_ATTR(mb_poweron_reason, S_IRUGO|S_IWUSR, show_mb_poweron_reason, set_mb_poweron_reason, 0); +/* System Status LED */ +static SENSOR_DEVICE_ATTR(sys_status_led, S_IRUGO|S_IWUSR, + show_sys_status_led, set_sys_status_led, 0); + static struct attribute *smf_dell_attrs[] = { &sensor_dev_attr_smf_version.dev_attr.attr, &sensor_dev_attr_smf_firmware_ver.dev_attr.attr, &sensor_dev_attr_smf_reset_reason.dev_attr.attr, &sensor_dev_attr_smf_poweron_reason.dev_attr.attr, &sensor_dev_attr_mb_poweron_reason.dev_attr.attr, + &sensor_dev_attr_sys_status_led.dev_attr.attr, &sensor_dev_attr_fan_tray_presence.dev_attr.attr, &sensor_dev_attr_fan1_airflow.dev_attr.attr, &sensor_dev_attr_fan3_airflow.dev_attr.attr, diff --git a/platform/broadcom/sonic-platform-modules-dell/common/ipmihelper.py b/platform/broadcom/sonic-platform-modules-dell/common/ipmihelper.py index f70c505d491..d95329c40de 100644 --- a/platform/broadcom/sonic-platform-modules-dell/common/ipmihelper.py +++ b/platform/broadcom/sonic-platform-modules-dell/common/ipmihelper.py @@ -33,12 +33,12 @@ def get_ipmitool_raw_output(args): command = "ipmitool raw {}".format(args) try: proc = subprocess.Popen(command.split(), stdout=subprocess.PIPE, - stderr=subprocess.STDOUT) + universal_newlines=True, stderr=subprocess.STDOUT) stdout = proc.communicate()[0] proc.wait() if not proc.returncode: result = stdout.rstrip('\n') - except: + except EnvironmentError: pass for i in result.split(): @@ -175,12 +175,12 @@ def _get_ipmitool_fru_print(self): command = "ipmitool fru print {}".format(self.id) try: proc = subprocess.Popen(command.split(), stdout=subprocess.PIPE, - stderr=subprocess.STDOUT) + universal_newlines=True, stderr=subprocess.STDOUT) stdout = proc.communicate()[0] proc.wait() if not proc.returncode: - result = stdout.decode('utf-8').rstrip('\n') - except: + result = stdout.rstrip('\n') + except EnvironmentError: pass return result @@ -248,12 +248,12 @@ def get_fru_data(self, offset, count=1): offset_MSB, count) try: proc = subprocess.Popen(command.split(), stdout=subprocess.PIPE, - stderr=subprocess.STDOUT) + universal_newlines=True, stderr=subprocess.STDOUT) stdout = proc.communicate()[0] proc.wait() if not proc.returncode: - result = stdout.decode('utf-8').rstrip('\n') - except: + result = stdout.rstrip('\n') + except EnvironmentError: is_valid = False if (not result) or (not is_valid): diff --git a/platform/broadcom/sonic-platform-modules-dell/common/sonic_platform/hwaccess.py b/platform/broadcom/sonic-platform-modules-dell/common/sonic_platform/hwaccess.py index b0020144a4f..567669d36fc 100644 --- a/platform/broadcom/sonic-platform-modules-dell/common/sonic_platform/hwaccess.py +++ b/platform/broadcom/sonic-platform-modules-dell/common/sonic_platform/hwaccess.py @@ -1,5 +1,6 @@ # Helper functions to access hardware +import os import struct import mmap import subprocess @@ -22,3 +23,31 @@ def pci_get_value(resource, offset): def i2c_get(bus, i2caddr, ofs): return int(subprocess.check_output(['/usr/sbin/i2cget', '-y', str(bus), str(i2caddr), str(ofs)]), 16) + +def io_reg_read(io_resource, offset): + fd = os.open(io_resource, os.O_RDONLY) + if fd < 0: + print('file open failed %s' % io_resource) + return -1 + if os.lseek(fd, offset, os.SEEK_SET) != offset: + print('lseek failed on %s' % io_resource) + return -1 + buf = os.read(fd, 1) + reg_val1 = ord(buf) + os.close(fd) + return reg_val1 + +def io_reg_write(io_resource, offset, val): + fd = os.open(io_resource, os.O_RDWR) + if fd < 0: + print('file open failed %s' % io_resource) + return False + if os.lseek(fd, offset, os.SEEK_SET) != offset: + print('lseek failed on %s' % io_resource) + return False + ret = os.write(fd, struct.pack('B', val)) + if ret != 1: + print('write failed %d' % ret) + return False + os.close(fd) + return True diff --git a/platform/broadcom/sonic-platform-modules-dell/debian/control b/platform/broadcom/sonic-platform-modules-dell/debian/control index 82b0e402a15..2920602fcd6 100644 --- a/platform/broadcom/sonic-platform-modules-dell/debian/control +++ b/platform/broadcom/sonic-platform-modules-dell/debian/control @@ -7,37 +7,37 @@ Standards-Version: 3.9.3 Package: platform-modules-s6000 Architecture: amd64 -Depends: linux-image-4.19.0-9-2-amd64-unsigned +Depends: linux-image-4.19.0-12-2-amd64-unsigned Description: kernel modules for platform devices such as fan, led, sfp Package: platform-modules-z9100 Architecture: amd64 -Depends: linux-image-4.19.0-9-2-amd64-unsigned +Depends: linux-image-4.19.0-12-2-amd64-unsigned Description: kernel modules for platform devices such as fan, led, sfp Package: platform-modules-s6100 Architecture: amd64 -Depends: linux-image-4.19.0-9-2-amd64-unsigned +Depends: linux-image-4.19.0-12-2-amd64-unsigned Description: kernel modules for platform devices such as fan, led, sfp Package: platform-modules-z9264f Architecture: amd64 -Depends: linux-image-4.19.0-9-2-amd64-unsigned +Depends: linux-image-4.19.0-12-2-amd64-unsigned Description: kernel modules for platform devices such as fan, led, sfp Package: platform-modules-s5232f Architecture: amd64 -Depends: linux-image-4.19.0-9-2-amd64-unsigned +Depends: linux-image-4.19.0-12-2-amd64-unsigned Description: kernel modules for platform devices such as fan, led, sfp Package: platform-modules-s5248f Architecture: amd64 -Depends: linux-image-4.19.0-9-2-amd64-unsigned +Depends: linux-image-4.19.0-12-2-amd64-unsigned Description: kernel modules for platform devices such as fan, led, sfp Package: platform-modules-z9332f Architecture: amd64 -Depends: linux-image-4.19.0-9-2-amd64-unsigned +Depends: linux-image-4.19.0-12-2-amd64-unsigned Description: kernel modules for platform devices such as fan, led, sfp Package: platform-modules-s5296f diff --git a/platform/broadcom/sonic-platform-modules-dell/s5232f/sonic_platform/sfp.py b/platform/broadcom/sonic-platform-modules-dell/s5232f/sonic_platform/sfp.py index 56f37afea6e..b2cceab9b08 100644 --- a/platform/broadcom/sonic-platform-modules-dell/s5232f/sonic_platform/sfp.py +++ b/platform/broadcom/sonic-platform-modules-dell/s5232f/sonic_platform/sfp.py @@ -118,7 +118,7 @@ 'hardware_rev': [QSFP_INFO_OFFSET, 56, 2, 'parse_vendor_rev'], 'serial': [QSFP_INFO_OFFSET, 68, 16, 'parse_vendor_sn'], 'vendor_date': [QSFP_INFO_OFFSET, 84, 8, 'parse_vendor_date'], - 'dom_capability': [QSFP_INFO_OFFSET, 92, 1, 'parse_qsfp_dom_capability'], + 'dom_capability': [QSFP_INFO_OFFSET, 92, 1, 'parse_dom_capability'], 'dom_rev': [QSFP_DOM_OFFSET, 1, 1, 'parse_sfp_dom_rev'], 'ModuleThreshold': [QSFP_DOM_OFFSET1, 128, 24, 'parse_module_threshold_values'], 'ChannelThreshold': [QSFP_DOM_OFFSET1, 176, 16, 'parse_channel_threshold_values'], diff --git a/platform/broadcom/sonic-platform-modules-dell/s6000/sonic_platform/chassis.py b/platform/broadcom/sonic-platform-modules-dell/s6000/sonic_platform/chassis.py index 899754709bc..7f6e9ec573f 100755 --- a/platform/broadcom/sonic-platform-modules-dell/s6000/sonic_platform/chassis.py +++ b/platform/broadcom/sonic-platform-modules-dell/s6000/sonic_platform/chassis.py @@ -24,7 +24,7 @@ MAX_S6000_FANTRAY = 3 MAX_S6000_PSU = 2 -MAX_S6000_THERMAL = 10 +MAX_S6000_THERMAL = 6 MAX_S6000_COMPONENT = 4 @@ -44,6 +44,8 @@ class Chassis(ChassisBase): def __init__(self): ChassisBase.__init__(self) + self.status_led_reg = "system_led" + self.supported_led_color = ['green', 'blinking green', 'amber', 'blinking amber'] # Initialize SFP list self.PORT_START = 0 self.PORT_END = 31 @@ -101,13 +103,30 @@ def _get_cpld_register(self, reg_name): try: with open(mb_reg_file, 'r') as fd: rv = fd.read() - except Exception as error: + except IOError: rv = 'ERR' rv = rv.rstrip('\r\n') rv = rv.lstrip(" ") return rv + def _set_cpld_register(self, reg_name, value): + # On successful write, returns the value will be written on + # reg_name and on failure returns 'ERR' + rv = 'ERR' + cpld_reg_file = self.CPLD_DIR+'/'+reg_name + + if (not os.path.isfile(cpld_reg_file)): + return rv + + try: + with open(cpld_reg_file, 'w') as fd: + rv = fd.write(str(value)) + except IOError: + rv = 'ERR' + + return rv + def _nvram_write(self, offset, val): resource = "/dev/nvram" fd = os.open(resource, os.O_RDWR) @@ -179,6 +198,23 @@ def get_status(self): """ return True + def get_position_in_parent(self): + """ + Retrieves 1-based relative physical position in parent device. + Returns: + integer: The 1-based relative physical position in parent + device or -1 if cannot determine the position + """ + return -1 + + def is_replaceable(self): + """ + Indicate whether Chassis is replaceable. + Returns: + bool: True if it is replaceable. + """ + return False + def get_base_mac(self): """ Retrieves the base MAC address for the chassis @@ -305,4 +341,41 @@ def get_change_event(self, timeout=0): return True, ret_dict return False, ret_dict + def set_status_led(self, color): + """ + Sets the state of the system LED + Args: + color: A string representing the color with which to set the + system LED + + Returns: + bool: True if system LED state is set successfully, False if not + """ + if color not in self.supported_led_color: + return False + + # Change color string format to the one used by driver + color = color.replace('amber', 'yellow') + color = color.replace('blinking ', 'blink_') + rv = self._set_cpld_register(self.status_led_reg, color) + if (rv != 'ERR'): + return True + else: + return False + + def get_status_led(self): + """ + Gets the state of the system LED + + Returns: + A string, one of the valid LED color strings which could be vendor + specified. + """ + status_led = self._get_cpld_register(self.status_led_reg) + if (status_led != 'ERR'): + status_led = status_led.replace('yellow', 'amber') + status_led = status_led.replace('blink_', 'blinking ') + return status_led + else: + return None diff --git a/platform/broadcom/sonic-platform-modules-dell/s6000/sonic_platform/component.py b/platform/broadcom/sonic-platform-modules-dell/s6000/sonic_platform/component.py index 1e21c233f5d..d9459be47c4 100644 --- a/platform/broadcom/sonic-platform-modules-dell/s6000/sonic_platform/component.py +++ b/platform/broadcom/sonic-platform-modules-dell/s6000/sonic_platform/component.py @@ -29,8 +29,8 @@ class Component(ComponentBase): "booting")], ["System-CPLD", "Used for managing CPU board devices and power"], ["Master-CPLD", ("Used for managing Fan, PSU, system LEDs, QSFP " - "modules (1-16)")], - ["Slave-CPLD", "Used for managing QSFP modules (17-32)"] + "modules (17-32)")], + ["Slave-CPLD", "Used for managing QSFP modules (1-16)"] ] def __init__(self, component_index): @@ -90,6 +90,55 @@ def get_name(self): """ return self.name + def get_model(self): + """ + Retrieves the part number of the component + Returns: + string: Part number of component + """ + return 'NA' + + def get_serial(self): + """ + Retrieves the serial number of the component + Returns: + string: Serial number of component + """ + return 'NA' + + def get_presence(self): + """ + Retrieves the presence of the component + Returns: + bool: True if present, False if not + """ + return True + + def get_status(self): + """ + Retrieves the operational status of the component + Returns: + bool: True if component is operating properly, False if not + """ + return True + + def get_position_in_parent(self): + """ + Retrieves 1-based relative physical position in parent device. + Returns: + integer: The 1-based relative physical position in parent + device or -1 if cannot determine the position + """ + return -1 + + def is_replaceable(self): + """ + Indicate whether component is replaceable. + Returns: + bool: True if it is replaceable. + """ + return False + def get_description(self): """ Retrieves the description of the component diff --git a/platform/broadcom/sonic-platform-modules-dell/s6000/sonic_platform/eeprom.py b/platform/broadcom/sonic-platform-modules-dell/s6000/sonic_platform/eeprom.py index ef736089c44..5afe0112441 100644 --- a/platform/broadcom/sonic-platform-modules-dell/s6000/sonic_platform/eeprom.py +++ b/platform/broadcom/sonic-platform-modules-dell/s6000/sonic_platform/eeprom.py @@ -36,8 +36,8 @@ ('Fab Rev', 's', 2) ] -# Fan eeprom fields in format required by EepromDecoder -fan_eeprom_format = [ +# FanTray eeprom fields in format required by EepromDecoder +fantray_eeprom_format = [ ('PPID', 's', 20), ('DPN Rev', 's', 3), ('Service Tag', 's', 7), ('Part Number', 's', 10), ('Part Num Revision', 's', 3), ('Mfg Test', 's', 2), ('Redundant copy', 's', 83), @@ -51,10 +51,10 @@ class Eeprom(TlvInfoDecoder): I2C_DIR = "/sys/class/i2c-adapter/" - def __init__(self, is_psu=False, psu_index=0, is_fan=False, fan_index=0): + def __init__(self, is_psu=False, psu_index=0, is_fantray=False, fantray_index=0): self.is_psu_eeprom = is_psu - self.is_fan_eeprom = is_fan - self.is_sys_eeprom = not (is_psu | is_fan) + self.is_fantray_eeprom = is_fantray + self.is_sys_eeprom = not (is_psu | is_fantray) if self.is_sys_eeprom: self.start_offset = 0 @@ -71,10 +71,10 @@ def __init__(self, is_psu=False, psu_index=0, is_fan=False, fan_index=0): + "i2c-1/1-005{}/eeprom".format(2 - self.index) self.format = psu_eeprom_format else: - self.index = fan_index + self.index = fantray_index self.eeprom_path = self.I2C_DIR \ + "i2c-11/11-005{}/eeprom".format(4 - self.index) - self.format = fan_eeprom_format + self.format = fantray_eeprom_format EepromDecoder.__init__(self, self.eeprom_path, self.format, self.start_offset, '', True) self._load_device_eeprom() diff --git a/platform/broadcom/sonic-platform-modules-dell/s6000/sonic_platform/fan.py b/platform/broadcom/sonic-platform-modules-dell/s6000/sonic_platform/fan.py index fbdbf650db7..d5a4f379e90 100644 --- a/platform/broadcom/sonic-platform-modules-dell/s6000/sonic_platform/fan.py +++ b/platform/broadcom/sonic-platform-modules-dell/s6000/sonic_platform/fan.py @@ -13,7 +13,6 @@ import os import glob from sonic_platform_base.fan_base import FanBase - from sonic_platform.eeprom import Eeprom except ImportError as e: raise ImportError(str(e) + "- required module not found") @@ -25,33 +24,37 @@ class Fan(FanBase): """DellEMC Platform-specific Fan class""" - CPLD_DIR = "/sys/devices/platform/dell-s6000-cpld.0/" I2C_DIR = "/sys/class/i2c-adapter/" - - def __init__(self, fan_index, psu_fan=False, dependency=None): + FAN_DEV_MAPPING = { + 1: {1: ("i2c-11/11-002a", 1), 2: ("i2c-11/11-002a", 2)}, + 2: {1: ("i2c-11/11-0029", 3), 2: ("i2c-11/11-0029", 4)}, + 3: {1: ("i2c-11/11-0029", 1), 2: ("i2c-11/11-0029", 2)} + } + + def __init__(self, fantray_index=1, fan_index=1, + psu_index=1, psu_fan=False, dependency=None): self.is_psu_fan = psu_fan self.is_driver_initialized = True if not self.is_psu_fan: # Fan is 1-based in DellEMC platforms - self.index = fan_index + 1 - self.fan_presence_reg = "fan_prs" - self.fan_led_reg = "fan{}_led".format(fan_index) - self.get_fan_speed_reg = self.I2C_DIR + "i2c-11/11-0029/" +\ - "fan{}_input".format(self.index) - self.set_fan_speed_reg = self.I2C_DIR + "i2c-11/11-0029/" +\ - "fan{}_target".format(self.index) - self.eeprom = Eeprom(is_fan=True, fan_index=self.index) + self.fantray_index = fantray_index + self.index = fan_index + self.dependency = dependency + self.get_fan_speed_reg = self.I2C_DIR +\ + "{}/fan{}_input".format(*self.FAN_DEV_MAPPING[fantray_index][fan_index]) + self.set_fan_speed_reg = self.I2C_DIR +\ + "{}/fan{}_target".format(*self.FAN_DEV_MAPPING[fantray_index][fan_index]) self.max_fan_speed = MAX_S6000_FAN_SPEED - self.supported_led_color = ['off', 'green', 'amber'] else: - self.index = fan_index + self.psu_index = psu_index + self.index = 1 self.dependency = dependency self.set_fan_speed_reg = self.I2C_DIR +\ - "i2c-1/1-005{}/fan1_target".format(10 - self.index) + "i2c-1/1-005{}/fan1_target".format(10 - self.psu_index) hwmon_dir = self.I2C_DIR +\ - "i2c-1/1-005{}/hwmon/".format(10 - self.index) + "i2c-1/1-005{}/hwmon/".format(10 - self.psu_index) try: hwmon_node = os.listdir(hwmon_dir)[0] except OSError: @@ -61,43 +64,6 @@ def __init__(self, fan_index, psu_fan=False, dependency=None): self.get_fan_speed_reg = hwmon_dir + hwmon_node + '/fan1_input' self.max_fan_speed = MAX_S6000_PSU_FAN_SPEED - def _get_cpld_register(self, reg_name): - # On successful read, returns the value read from given - # reg_name and on failure returns 'ERR' - rv = 'ERR' - cpld_reg_file = self.CPLD_DIR + reg_name - - if (not os.path.isfile(cpld_reg_file)): - return rv - - try: - with open(cpld_reg_file, 'r') as fd: - rv = fd.read() - except: - rv = 'ERR' - - rv = rv.rstrip('\r\n') - rv = rv.lstrip(" ") - return rv - - def _set_cpld_register(self, reg_name, value): - # On successful write, returns the value will be written on - # reg_name and on failure returns 'ERR' - rv = 'ERR' - cpld_reg_file = self.CPLD_DIR + reg_name - - if (not os.path.isfile(cpld_reg_file)): - print("open error") - return rv - - try: - with open(cpld_reg_file, 'w') as fd: - rv = fd.write(str(value)) - except: - rv = 'ERR' - - return rv - def _get_i2c_register(self, reg_file): # On successful read, returns the value read from given # reg_name and on failure returns 'ERR' @@ -155,9 +121,9 @@ def get_name(self): string: The name of the Fan """ if not self.is_psu_fan: - return "FanTray{}-Fan1".format(self.index) + return "FanTray{}-Fan{}".format(self.fantray_index, self.index) else: - return "PSU{} Fan".format(self.index) + return "PSU{} Fan".format(self.psu_index) def get_presence(self): """ @@ -166,42 +132,23 @@ def get_presence(self): Returns: bool: True if Fan is present, False if not """ - status = False - if self.is_psu_fan: - return self.dependency.get_presence() - - fan_presence = self._get_cpld_register(self.fan_presence_reg) - if (fan_presence != 'ERR'): - fan_presence = int(fan_presence,16) & self.index - if fan_presence: - status = True - - return status + return self.dependency.get_presence() def get_model(self): """ Retrieves the part number of the Fan - Returns: string: Part number of Fan """ - if not self.is_psu_fan: - return self.eeprom.get_part_number() - else: - return 'NA' + return 'NA' def get_serial(self): """ Retrieves the serial number of the Fan - Returns: string: Serial number of Fan """ - # Sample Serial number format "US-01234D-54321-25A-0123-A00" - if not self.is_psu_fan: - return self.eeprom.get_serial_number() - else: - return 'NA' + return 'NA' def get_status(self): """ @@ -218,6 +165,23 @@ def get_status(self): return status + def get_position_in_parent(self): + """ + Retrieves 1-based relative physical position in parent device. + Returns: + integer: The 1-based relative physical position in parent + device or -1 if cannot determine the position + """ + return self.index + + def is_replaceable(self): + """ + Indicate whether Fan is replaceable. + Returns: + bool: True if it is replaceable. + """ + return False + def get_direction(self): """ Retrieves the fan airflow direction @@ -234,11 +198,10 @@ def get_direction(self): if self.is_psu_fan: direction = {1: self.FAN_DIRECTION_EXHAUST, 2: self.FAN_DIRECTION_INTAKE, 3: self.FAN_DIRECTION_EXHAUST, 4: self.FAN_DIRECTION_INTAKE} - fan_direction = self.dependency.eeprom.airflow_fan_type() else: direction = {1: self.FAN_DIRECTION_EXHAUST, 2: self.FAN_DIRECTION_INTAKE} - fan_direction = self.eeprom.airflow_fan_type() + fan_direction = self.dependency.eeprom.airflow_fan_type() return direction.get(fan_direction, self.FAN_DIRECTION_NOT_APPLICABLE) def get_speed(self): @@ -282,8 +245,8 @@ def set_speed(self, speed): Returns: bool: True if set success, False if fail. """ - fan_set = (speed * self.max_fan_speed)/ 100 - rv = self._set_i2c_register(self.set_fan_speed_reg , fan_set) + fan_set = (speed * self.max_fan_speed) // 100 + rv = self._set_i2c_register(self.set_fan_speed_reg, fan_set) if (rv != 'ERR'): return True else: @@ -298,16 +261,9 @@ def set_status_led(self, color): Returns: bool: True if set success, False if fail. """ - if self.is_psu_fan or (color not in self.supported_led_color): - return False - if(color == self.STATUS_LED_COLOR_AMBER): - color = 'yellow' - - rv = self._set_cpld_register(self.fan_led_reg ,color) - if (rv != 'ERR'): - return True - else: - return False + # No LED available for FanTray and PSU Fan + # Return True to avoid thermalctld alarm. + return True def get_status_led(self): """ @@ -316,18 +272,8 @@ def get_status_led(self): Returns: A string, one of the predefined STATUS_LED_COLOR_* strings. """ - if self.is_psu_fan: - # No LED available for PSU Fan - return None - - fan_led = self._get_cpld_register(self.fan_led_reg) - if (fan_led != 'ERR'): - if (fan_led == 'yellow'): - return self.STATUS_LED_COLOR_AMBER - else: - return fan_led - else: - return self.STATUS_LED_COLOR_OFF + # No LED available for FanTray and PSU Fan + return None def get_target_speed(self): """ diff --git a/platform/broadcom/sonic-platform-modules-dell/s6000/sonic_platform/fan_drawer.py b/platform/broadcom/sonic-platform-modules-dell/s6000/sonic_platform/fan_drawer.py index c8ea283e5ba..2e5e3446cd8 100644 --- a/platform/broadcom/sonic-platform-modules-dell/s6000/sonic_platform/fan_drawer.py +++ b/platform/broadcom/sonic-platform-modules-dell/s6000/sonic_platform/fan_drawer.py @@ -9,26 +9,176 @@ ######################################################################## try: + import os + from sonic_platform_base.fan_drawer_base import FanDrawerBase + from sonic_platform.eeprom import Eeprom from sonic_platform.fan import Fan except ImportError as e: raise ImportError(str(e) + "- required module not found") +MAX_S6000_FANS_PER_FANTRAY = 2 + class FanDrawer(FanDrawerBase): - """DellEMC Platform-specific Fan class""" + """DellEMC Platform-specific Fan Drawer class""" - def __init__(self, fantray_index): + CPLD_DIR = "/sys/devices/platform/dell-s6000-cpld.0/" + def __init__(self, fantray_index): FanDrawerBase.__init__(self) # FanTray is 1-based in DellEMC platforms - self.fantrayindex = fantray_index + 1 - self._fan_list.append(Fan(fantray_index)) + self.index = fantray_index + 1 + self.eeprom = Eeprom(is_fantray=True, fantray_index=self.index) + self.fantray_presence_reg = "fan_prs" + self.fantray_led_reg = "fan{}_led".format(self.index - 1) + self.supported_led_color = ['off', 'green', 'amber'] + + for i in range(1, MAX_S6000_FANS_PER_FANTRAY+1): + self._fan_list.append(Fan(fantray_index=self.index, fan_index=i, dependency=self)) + + def _get_cpld_register(self, reg_name): + # On successful read, returns the value read from given + # reg_name and on failure returns 'ERR' + rv = 'ERR' + cpld_reg_file = self.CPLD_DIR + reg_name + + if (not os.path.isfile(cpld_reg_file)): + return rv + + try: + with open(cpld_reg_file, 'r') as fd: + rv = fd.read() + except IOError: + rv = 'ERR' + + rv = rv.rstrip('\r\n') + rv = rv.lstrip(" ") + return rv + + def _set_cpld_register(self, reg_name, value): + # On successful write, returns the value will be written on + # reg_name and on failure returns 'ERR' + rv = 'ERR' + cpld_reg_file = self.CPLD_DIR + reg_name + + if (not os.path.isfile(cpld_reg_file)): + return rv + + try: + with open(cpld_reg_file, 'w') as fd: + rv = fd.write(str(value)) + except IOError: + rv = 'ERR' + + return rv def get_name(self): """ - Retrieves the fan drawer name + Retrieves the Fandrawer name Returns: string: The name of the device """ - return "FanTray{}".format(self.fantrayindex) + return "FanTray{}".format(self.index) + + def get_presence(self): + """ + Retrieves the presence of the Fandrawer + + Returns: + bool: True if Fandrawer is present, False if not + """ + presence = False + + fantray_presence = self._get_cpld_register(self.fantray_presence_reg) + if (fantray_presence != 'ERR'): + fantray_presence = int(fantray_presence, 16) & (1 << (self.index - 1)) + if fantray_presence: + presence = True + + return presence + + def get_model(self): + """ + Retrieves the part number of the Fandrawer + + Returns: + string: Part number of Fandrawer + """ + return self.eeprom.get_part_number() + + def get_serial(self): + """ + Retrieves the serial number of the Fandrawer + + Returns: + string: Serial number of Fandrawer + """ + # Sample Serial number format "US-01234D-54321-25A-0123-A00" + return self.eeprom.get_serial_number() + + def get_status(self): + """ + Retrieves the operational status of the Fandrawer + + Returns: + bool: True if Fandrawer is operating properly, False if not + """ + status = True + for fan in self.get_all_fans(): + status &= fan.get_status() + + return status + + def get_position_in_parent(self): + """ + Retrieves 1-based relative physical position in parent device. + Returns: + integer: The 1-based relative physical position in parent + device or -1 if cannot determine the position + """ + return self.index + + def is_replaceable(self): + """ + Indicate whether this fan drawer is replaceable. + Returns: + bool: True if it is replaceable. + """ + return True + + def set_status_led(self, color): + """ + Set led to expected color + Args: + color: A string representing the color with which to set the + fandrawer status LED + Returns: + bool: True if set success, False if fail. + """ + if color not in self.supported_led_color: + return False + if color == self.STATUS_LED_COLOR_AMBER: + color = 'yellow' + + rv = self._set_cpld_register(self.fantray_led_reg, color) + if (rv != 'ERR'): + return True + else: + return False + + def get_status_led(self): + """ + Gets the state of the fandrawer status LED + + Returns: + A string, one of the predefined STATUS_LED_COLOR_* strings. + """ + fantray_led = self._get_cpld_register(self.fantray_led_reg) + if (fantray_led != 'ERR'): + if (fantray_led == 'yellow'): + return self.STATUS_LED_COLOR_AMBER + else: + return fantray_led + else: + return self.STATUS_LED_COLOR_OFF diff --git a/platform/broadcom/sonic-platform-modules-dell/s6000/sonic_platform/psu.py b/platform/broadcom/sonic-platform-modules-dell/s6000/sonic_platform/psu.py index af52ccedbc4..e217c0a08c4 100644 --- a/platform/broadcom/sonic-platform-modules-dell/s6000/sonic_platform/psu.py +++ b/platform/broadcom/sonic-platform-modules-dell/s6000/sonic_platform/psu.py @@ -15,9 +15,12 @@ from sonic_platform_base.psu_base import PsuBase from sonic_platform.eeprom import Eeprom from sonic_platform.fan import Fan + from sonic_platform.thermal import Thermal except ImportError as e: raise ImportError(str(e) + "- required module not found") +MAX_S6000_THERMALS_PER_PSU = 2 + class Psu(PsuBase): """DellEMC Platform-specific PSU class""" @@ -53,7 +56,10 @@ def __init__(self, psu_index): self.eeprom = Eeprom(is_psu=True, psu_index=self.index) - self._fan_list.append(Fan(self.index, psu_fan=True, dependency=self)) + self._fan_list.append(Fan(psu_index=self.index, psu_fan=True, dependency=self)) + for i in range(1, MAX_S6000_THERMALS_PER_PSU+1): + self._thermal_list.append(Thermal(psu_index=self.index, thermal_index=i, + psu_thermal=True, dependency=self)) def _get_cpld_register(self, reg_name): # On successful read, returns the value read from given @@ -171,6 +177,23 @@ def get_status(self): return status + def get_position_in_parent(self): + """ + Retrieves 1-based relative physical position in parent device. + Returns: + integer: The 1-based relative physical position in parent + device or -1 if cannot determine the position + """ + return self.index + + def is_replaceable(self): + """ + Indicate whether PSU is replaceable. + Returns: + bool: True if it is replaceable. + """ + return True + def get_voltage(self): """ Retrieves current PSU voltage output @@ -266,3 +289,50 @@ def set_status_led(self, color): # In S6000, the firmware running in the PSU controls the LED # and the PSU LED state cannot be changed from CPU. return False + + def get_temperature(self): + """ + Retrieves current temperature reading from PSU + + Returns: + A float number of current temperature in Celsius up to + nearest thousandth of one degree Celsius, e.g. 30.125 + """ + if self.get_presence(): + return self.get_thermal(0).get_temperature() + else: + return 0.0 + + def get_temperature_high_threshold(self): + """ + Retrieves the high threshold temperature of PSU + + Returns: + A float number, the high threshold temperature of PSU in + Celsius up to nearest thousandth of one degree Celsius, + e.g. 30.125 + """ + if self.get_presence(): + return self.get_thermal(0).get_high_threshold() + else: + return 0.0 + + def get_voltage_high_threshold(self): + """ + Retrieves the high threshold PSU voltage output + + Returns: + A float number, the high threshold output voltage in volts, + e.g. 12.1 + """ + return 12.6 + + def get_voltage_low_threshold(self): + """ + Retrieves the low threshold PSU voltage output + + Returns: + A float number, the low threshold output voltage in volts, + e.g. 12.1 + """ + return 11.4 diff --git a/platform/broadcom/sonic-platform-modules-dell/s6000/sonic_platform/sfp.py b/platform/broadcom/sonic-platform-modules-dell/s6000/sonic_platform/sfp.py index 175e601dbe7..b66cb31ec96 100644 --- a/platform/broadcom/sonic-platform-modules-dell/s6000/sonic_platform/sfp.py +++ b/platform/broadcom/sonic-platform-modules-dell/s6000/sonic_platform/sfp.py @@ -10,6 +10,7 @@ try: import re + import struct import time from sonic_platform_base.sfp_base import SfpBase from sonic_platform_base.sonic_sfp.sff8436 import sff8436InterfaceId @@ -27,6 +28,9 @@ DOM_OFFSET = 0 DOM_OFFSET1 = 384 +QSFP_CONTROL_OFFSET = 86 +QSFP_POWEROVERRIDE_OFFSET = 93 + cable_length_tup = ('Length(km)', 'Length OM3(2m)', 'Length OM2(m)', 'Length OM1(m)', 'Length Cable Assembly(m)') @@ -108,7 +112,7 @@ def __init__(self, index, sfp_type, eeprom_path, sfp_control, sfp_ctrl_idx): SfpBase.__init__(self) self.sfp_type = sfp_type - self.index = index + self.index = index + 1 self.eeprom_path = eeprom_path self.sfp_control = sfp_control self.sfp_ctrl_idx = sfp_ctrl_idx @@ -132,9 +136,10 @@ def _read_eeprom_bytes(self, eeprom_path, offset, num_bytes): eeprom.close() return None + raw = bytearray(raw) try: for n in range(0, num_bytes): - eeprom_raw[n] = hex(ord(raw[n]))[2:].zfill(2) + eeprom_raw[n] = hex(raw[n])[2:].zfill(2) except BaseException: eeprom.close() return None @@ -588,40 +593,14 @@ def get_tx_disable_channel(self): """ Retrieves the TX disabled channels in this SFP """ - tx_disable = None - tx_disable_list = [] + tx_disable_channel = 0 - tx_disable_data = self._get_eeprom_data('tx_disable') - if (tx_disable_data is not None): - tx_disable = tx_disable_data['data']['Tx1Disable']['value'] - if (tx_disable == 'On'): - tx_disable_list.append(1) - else: - tx_disable_list.append(0) - tx_disable = tx_disable_data['data']['Tx2Disable']['value'] - if (tx_disable == 'On'): - tx_disable_list.append(1) - else: - tx_disable_list.append(0) - tx_disable = tx_disable_data['data']['Tx3Disable']['value'] - if (tx_disable == 'On'): - tx_disable_list.append(1) - else: - tx_disable_list.append(0) - tx_disable = tx_disable_data['data']['Tx4Disable']['value'] - if (tx_disable == 'On'): - tx_disable_list.append(1) - else: - tx_disable_list.append(0) - - bit4 = int(tx_disable_list[3]) * 8 - bit3 = int(tx_disable_list[2]) * 4 - bit2 = int(tx_disable_list[1]) * 2 - bit1 = int(tx_disable_list[0]) * 1 - - tx_disable_channel = hex(bit4 + bit3 + bit2 + bit1) + tx_disable = self.get_tx_disable() + for channel, disable in enumerate(tx_disable): + if disable: + tx_disable_channel |= 1 << channel - return tx_disable_channel + return tx_disable_channel def get_lpmode(self): """ @@ -722,7 +701,6 @@ def get_rx_power(self): return rx_power_list - def get_tx_power(self): """ Retrieves the TX power of this SFP @@ -822,19 +800,68 @@ def tx_disable(self, tx_disable): """ Disable SFP TX for all channels """ - return False + eeprom = None + tx_disable_value = 0xf if tx_disable else 0x0 + + try: + eeprom = open(self.eeprom_path, "r+b") + eeprom.seek(QSFP_CONTROL_OFFSET) + eeprom.write(struct.pack('B', tx_disable_value)) + except IOError: + return False + finally: + if eeprom is not None: + eeprom.close() + time.sleep(0.01) + + return True def tx_disable_channel(self, channel, disable): """ Sets the tx_disable for specified SFP channels """ - return False + eeprom = None + current_state = self.get_tx_disable_channel() + + if disable: + tx_disable_value = current_state | channel + else: + tx_disable_value = current_state & (~channel) + + try: + eeprom = open(self.eeprom_path, "r+b") + eeprom.seek(QSFP_CONTROL_OFFSET) + eeprom.write(struct.pack('B', tx_disable_value)) + except IOError: + return False + finally: + if eeprom is not None: + eeprom.close() + time.sleep(0.01) + + return True def set_power_override(self, power_override, power_set): """ Sets SFP power level using power_override and power_set """ - return False + eeprom = None + power_override_bit = 0x1 if power_override else 0 + power_set_bit = 0x2 if power_set else 0 + value = power_override_bit | power_set_bit + + try: + eeprom = open(self.eeprom_path, "r+b") + eeprom.seek(QSFP_POWEROVERRIDE_OFFSET) + eeprom.write(struct.pack('B', value)) + except IOError: + return False + finally: + if eeprom is not None: + eeprom.close() + time.sleep(0.01) + + return True def get_status(self): """ @@ -848,3 +875,20 @@ def get_status(self): status = True return status + + def get_position_in_parent(self): + """ + Retrieves 1-based relative physical position in parent device. + Returns: + integer: The 1-based relative physical position in parent + device or -1 if cannot determine the position + """ + return self.index + + def is_replaceable(self): + """ + Indicate whether this device is replaceable. + Returns: + bool: True if it is replaceable. + """ + return True diff --git a/platform/broadcom/sonic-platform-modules-dell/s6000/sonic_platform/thermal.py b/platform/broadcom/sonic-platform-modules-dell/s6000/sonic_platform/thermal.py index 2f130ebabbb..ad089a8946a 100644 --- a/platform/broadcom/sonic-platform-modules-dell/s6000/sonic_platform/thermal.py +++ b/platform/broadcom/sonic-platform-modules-dell/s6000/sonic_platform/thermal.py @@ -13,7 +13,6 @@ import os import glob from sonic_platform_base.thermal_base import ThermalBase - from sonic_platform.psu import Psu except ImportError as e: raise ImportError(str(e) + "- required module not found") @@ -34,11 +33,20 @@ class Thermal(ThermalBase): 'PSU1-Sensor 1', 'PSU1-Sensor 2', 'PSU2-Sensor 1', 'PSU2-Sensor 2', 'CPU Core 0', 'CPU Core 1') - def __init__(self, thermal_index): - self.index = thermal_index + 1 - self.is_psu_thermal = False + def __init__(self, thermal_index, + psu_index=1, psu_thermal=False, dependency=None): + self.is_psu_thermal = psu_thermal + self.dependency = dependency self.is_driver_initialized = True - self.dependency = None + + if self.is_psu_thermal: + self.index = (2 * psu_index) + thermal_index + 2 + else: + # CPU thermal + if thermal_index > 3: + self.index = thermal_index + 5 + else: + self.index = thermal_index + 1 if self.index < 9: i2c_path = self.I2C_DIR + self.I2C_DEV_MAPPING[self.index - 1][0] @@ -54,10 +62,6 @@ def __init__(self, thermal_index): if self.index == 4: hwmon_temp_suffix = "crit" - - if self.index > 4: - self.is_psu_thermal = True - self.dependency = Psu(self.index / 7) else: dev_path = "/sys/devices/platform/coretemp.0/hwmon/" hwmon_temp_index = self.index - 7 @@ -168,6 +172,23 @@ def get_status(self): else: return True + def get_position_in_parent(self): + """ + Retrieves 1-based relative physical position in parent device. + Returns: + integer: The 1-based relative physical position in parent + device or -1 if cannot determine the position + """ + return self.index + + def is_replaceable(self): + """ + Indicate whether Thermal is replaceable. + Returns: + bool: True if it is replaceable. + """ + return False + def get_temperature(self): """ Retrieves current temperature reading from thermal diff --git a/platform/broadcom/sonic-platform-modules-dell/s6100/sonic_platform/chassis.py b/platform/broadcom/sonic-platform-modules-dell/s6100/sonic_platform/chassis.py index 47ef87b951d..f8e009cdbef 100755 --- a/platform/broadcom/sonic-platform-modules-dell/s6100/sonic_platform/chassis.py +++ b/platform/broadcom/sonic-platform-modules-dell/s6100/sonic_platform/chassis.py @@ -54,9 +54,21 @@ class Chassis(ChassisBase): power_reason_dict[33] = ChassisBase.REBOOT_CAUSE_THERMAL_OVERLOAD_ASIC power_reason_dict[44] = ChassisBase.REBOOT_CAUSE_INSUFFICIENT_FAN_SPEED + status_led_reg_to_color = { + 0x00: 'green', 0x01: 'blinking green', 0x02: 'amber', + 0x04: 'amber', 0x08: 'blinking amber', 0x10: 'blinking amber' + } + + color_to_status_led_reg = { + 'green': 0x00, 'blinking green': 0x01, + 'amber': 0x02, 'blinking amber': 0x08 + } + def __init__(self): ChassisBase.__init__(self) + self.status_led_reg = "sys_status_led" + self.supported_led_color = ['green', 'blinking green', 'amber', 'blinking amber'] # Initialize EEPROM self._eeprom = Eeprom() for i in range(MAX_S6100_MODULE): @@ -113,6 +125,23 @@ def _get_pmc_register(self, reg_name): rv = rv.lstrip(" ") return rv + def _set_pmc_register(self, reg_name, value): + # On successful write, returns the length of value written on + # reg_name and on failure returns 'ERR' + rv = 'ERR' + mb_reg_file = self.MAILBOX_DIR + '/' + reg_name + + if (not os.path.isfile(mb_reg_file)): + return rv + + try: + with open(mb_reg_file, 'w') as fd: + rv = fd.write(str(value)) + except IOError: + rv = 'ERR' + + return rv + def _get_register(self, reg_file): # On successful read, returns the value read from given # reg_name and on failure returns 'ERR' @@ -172,6 +201,23 @@ def get_status(self): """ return True + def get_position_in_parent(self): + """ + Retrieves 1-based relative physical position in parent device. + Returns: + integer: The 1-based relative physical position in parent + device or -1 if cannot determine the position + """ + return -1 + + def is_replaceable(self): + """ + Indicate whether Chassis is replaceable. + Returns: + bool: True if it is replaceable. + """ + return False + def get_base_mac(self): """ Retrieves the base MAC address for the chassis @@ -325,3 +371,38 @@ def get_change_event(self, timeout=0): break return True, ret_dict + + def set_status_led(self, color): + """ + Sets the state of the system LED + + Args: + color: A string representing the color with which to set the + system LED + + Returns: + bool: True if system LED state is set successfully, False if not + """ + if color not in self.supported_led_color: + return False + + value = self.color_to_status_led_reg[color] + rv = self._set_pmc_register(self.status_led_reg, value) + if (rv != 'ERR'): + return True + else: + return False + + def get_status_led(self): + """ + Gets the state of the system LED + + Returns: + A string, one of the valid LED color strings which could be + vendor specified. + """ + reg_val = self._get_pmc_register(self.status_led_reg) + if (reg_val != 'ERR'): + return self.status_led_reg_to_color.get(int(reg_val, 16), None) + else: + return None diff --git a/platform/broadcom/sonic-platform-modules-dell/s6100/sonic_platform/component.py b/platform/broadcom/sonic-platform-modules-dell/s6100/sonic_platform/component.py index 6b1420a9860..bea180d440b 100644 --- a/platform/broadcom/sonic-platform-modules-dell/s6100/sonic_platform/component.py +++ b/platform/broadcom/sonic-platform-modules-dell/s6100/sonic_platform/component.py @@ -39,9 +39,10 @@ class Component(ComponentBase): ] def __init__(self, component_index=0, - is_module=False, iom_index=0, i2c_line=0): + is_module=False, iom_index=0, i2c_line=0, dependency=None): self.is_module_component = is_module + self.dependency = dependency if self.is_module_component: self.index = iom_index @@ -132,6 +133,61 @@ def get_name(self): """ return self.name + def get_model(self): + """ + Retrieves the part number of the component + Returns: + string: Part number of component + """ + return 'NA' + + def get_serial(self): + """ + Retrieves the serial number of the component + Returns: + string: Serial number of component + """ + return 'NA' + + def get_presence(self): + """ + Retrieves the presence of the component + Returns: + bool: True if present, False if not + """ + if self.is_module_component: + return self.dependency.get_presence() + else: + return True + + def get_status(self): + """ + Retrieves the operational status of the component + Returns: + bool: True if component is operating properly, False if not + """ + if self.is_module_component: + return self.dependency.get_status() + else: + return True + + def get_position_in_parent(self): + """ + Retrieves 1-based relative physical position in parent device. + Returns: + integer: The 1-based relative physical position in parent + device or -1 if cannot determine the position + """ + return -1 + + def is_replaceable(self): + """ + Indicate whether component is replaceable. + Returns: + bool: True if it is replaceable. + """ + return False + def get_description(self): """ Retrieves the description of the component diff --git a/platform/broadcom/sonic-platform-modules-dell/s6100/sonic_platform/fan.py b/platform/broadcom/sonic-platform-modules-dell/s6100/sonic_platform/fan.py index 8404a8d2bf5..5b3c8977ac0 100644 --- a/platform/broadcom/sonic-platform-modules-dell/s6100/sonic_platform/fan.py +++ b/platform/broadcom/sonic-platform-modules-dell/s6100/sonic_platform/fan.py @@ -26,30 +26,23 @@ class Fan(FanBase): HWMON_NODE = os.listdir(HWMON_DIR)[0] MAILBOX_DIR = HWMON_DIR + HWMON_NODE - def __init__(self, fantray_index=1, fan_index=1, psu_fan=False): + def __init__(self, fantray_index=1, psu_index=1, psu_fan=False, dependency=None): self.is_psu_fan = psu_fan if not self.is_psu_fan: - # API index is starting from 0, DellEMC platform index is starting - # from 1 - self.fantrayindex = fantray_index + 1 - self.fanindex = fan_index + 1 - self.fan_presence_reg = "fan{}_fault".format( - 2 * self.fantrayindex - 1) + self.fantrayindex = fantray_index + self.dependency = dependency self.fan_status_reg = "fan{}_alarm".format( 2 * self.fantrayindex - 1) self.get_fan_speed_reg = "fan{}_input".format( 2 * self.fantrayindex - 1) self.get_fan_dir_reg = "fan{}_airflow".format( 2 * self.fantrayindex - 1) - self.fan_serialno_reg = "fan{}_serialno".format( - 2 * self.fantrayindex - 1) self.max_fan_speed = MAX_S6100_FAN_SPEED else: - # PSU Fan index starts from 11 - self.fanindex = fan_index + 10 - self.fan_presence_reg = "fan{}_fault".format(self.fanindex) - self.get_fan_speed_reg = "fan{}_input".format(self.fanindex) - self.get_fan_dir_reg = "fan{}_airflow".format(self.fanindex) + self.psuindex = psu_index + self.fan_presence_reg = "fan{}_fault".format(self.psuindex + 10) + self.get_fan_speed_reg = "fan{}_input".format(self.psuindex + 10) + self.get_fan_dir_reg = "fan{}_airflow".format(self.psuindex + 10) self.max_fan_speed = MAX_S6100_PSU_FAN_SPEED def _get_pmc_register(self, reg_name): @@ -77,10 +70,9 @@ def get_name(self): string: The name of the device """ if not self.is_psu_fan: - return "FanTray{}-Fan{}".format( - self.fantrayindex, self.fanindex - 1) + return "FanTray{}-Fan1".format(self.fantrayindex) else: - return "PSU{} Fan".format(self.fanindex - 10) + return "PSU{} Fan".format(self.psuindex) def get_model(self): """ @@ -88,21 +80,7 @@ def get_model(self): Returns: string: Part number of FAN """ - # For Serial number "US-01234D-54321-25A-0123-A00", the part - # number is "01234D" - if self.is_psu_fan: - return 'NA' - - fan_serialno = self._get_pmc_register(self.fan_serialno_reg) - if (fan_serialno != 'ERR') and self.get_presence(): - if (len(fan_serialno.split('-')) > 1): - fan_partno = fan_serialno.split('-')[1] - else: - fan_partno = 'NA' - else: - fan_partno = 'NA' - - return fan_partno + return 'NA' def get_serial(self): """ @@ -110,15 +88,7 @@ def get_serial(self): Returns: string: Serial number of FAN """ - # Sample Serial number format "US-01234D-54321-25A-0123-A00" - if self.is_psu_fan: - return 'NA' - - fan_serialno = self._get_pmc_register(self.fan_serialno_reg) - if (fan_serialno == 'ERR') or not self.get_presence(): - fan_serialno = 'NA' - - return fan_serialno + return 'NA' def get_presence(self): """ @@ -126,14 +96,17 @@ def get_presence(self): Returns: bool: True if fan is present, False if not """ - status = False - fantray_presence = self._get_pmc_register(self.fan_presence_reg) - if (fantray_presence != 'ERR'): - fantray_presence = int(fantray_presence, 10) - if (~fantray_presence & 0b1): - status = True + if not self.is_psu_fan: + return self.dependency.get_presence() - return status + presence = False + fan_presence = self._get_pmc_register(self.fan_presence_reg) + if (fan_presence != 'ERR'): + fan_presence = int(fan_presence, 10) + if (~fan_presence & 0b1): + presence = True + + return presence def get_status(self): """ @@ -157,6 +130,23 @@ def get_status(self): return status + def get_position_in_parent(self): + """ + Retrieves 1-based relative physical position in parent device. + Returns: + integer: The 1-based relative physical position in parent + device or -1 if cannot determine the position + """ + return 1 + + def is_replaceable(self): + """ + Indicate whether Fan is replaceable. + Returns: + bool: True if it is replaceable. + """ + return False + def get_direction(self): """ Retrieves the fan airflow direction @@ -216,7 +206,6 @@ def set_speed(self, speed): Returns: bool: True if set success, False if fail. """ - # Fan speeds are controlled by Smart-fussion FPGA. return False @@ -229,7 +218,7 @@ def set_status_led(self, color): Returns: bool: True if set success, False if fail. """ - # Leds are controlled by Smart-fussion FPGA. + # No LED available for FanTray and PSU Fan # Return True to avoid thermalctld alarm. return True @@ -240,17 +229,8 @@ def get_status_led(self): Returns: A string, one of the predefined STATUS_LED_COLOR_* strings. """ - if self.is_psu_fan: - # No LED available for PSU Fan - return None - else: - if self.get_presence(): - if self.get_status(): - return self.STATUS_LED_COLOR_GREEN - else: - return self.STATUS_LED_COLOR_AMBER - else: - return self.STATUS_LED_COLOR_OFF + # No LED available for FanTray and PSU Fan + return None def get_target_speed(self): """ @@ -262,5 +242,3 @@ def get_target_speed(self): # Fan speeds are controlled by Smart-fussion FPGA. # Return current speed to avoid false thermalctld alarm. return self.get_speed() - - diff --git a/platform/broadcom/sonic-platform-modules-dell/s6100/sonic_platform/fan_drawer.py b/platform/broadcom/sonic-platform-modules-dell/s6100/sonic_platform/fan_drawer.py index ada5e93393c..41e870a6397 100644 --- a/platform/broadcom/sonic-platform-modules-dell/s6100/sonic_platform/fan_drawer.py +++ b/platform/broadcom/sonic-platform-modules-dell/s6100/sonic_platform/fan_drawer.py @@ -9,6 +9,8 @@ ######################################################################## try: + import os + from sonic_platform_base.fan_drawer_base import FanDrawerBase from sonic_platform.fan import Fan except ImportError as e: @@ -16,14 +18,38 @@ class FanDrawer(FanDrawerBase): - """DellEMC Platform-specific Fan class""" + """DellEMC Platform-specific Fan Drawer class""" - def __init__(self, fantray_index): + HWMON_DIR = "/sys/devices/platform/SMF.512/hwmon/" + HWMON_NODE = os.listdir(HWMON_DIR)[0] + MAILBOX_DIR = HWMON_DIR + HWMON_NODE + def __init__(self, fantray_index): FanDrawerBase.__init__(self) # FanTray is 1-based in DellEMC platforms - self.fantrayindex = fantray_index + 1 - self._fan_list.append(Fan(fantray_index)) + self.index = fantray_index + 1 + self.presence_reg = "fan{}_fault".format(2 * self.index - 1) + self.serialno_reg = "fan{}_serialno".format(2 * self.index - 1) + + self._fan_list.append(Fan(self.index, dependency=self)) + + def _get_pmc_register(self, reg_name): + # On successful read, returns the value read from given + # reg_name and on failure returns 'ERR' + rv = 'ERR' + mb_reg_file = self.MAILBOX_DIR+'/'+reg_name + + if (not os.path.isfile(mb_reg_file)): + return rv + try: + with open(mb_reg_file, 'r') as fd: + rv = fd.read() + except Exception as error: + rv = 'ERR' + + rv = rv.rstrip('\r\n') + rv = rv.lstrip(" ") + return rv def get_name(self): """ @@ -31,4 +57,105 @@ def get_name(self): Returns: string: The name of the device """ - return "FanTray{}".format(self.fantrayindex) + return "FanTray{}".format(self.index) + + def get_model(self): + """ + Retrieves the part number of Fandrawer + Returns: + string: Part number of Fandrawer + """ + # For Serial number "US-01234D-54321-25A-0123-A00", the part + # number is "01234D" + fantray_serialno = self._get_pmc_register(self.serialno_reg) + if (fantray_serialno != 'ERR') and self.get_presence(): + if (len(fantray_serialno.split('-')) > 1): + fantray_partno = fantray_serialno.split('-')[1] + else: + fantray_partno = 'NA' + else: + fantray_partno = 'NA' + + return fantray_partno + + def get_serial(self): + """ + Retrieves the serial number of Fandrawer + Returns: + string: Serial number of Fandrawer + """ + # Sample Serial number format "US-01234D-54321-25A-0123-A00" + fantray_serialno = self._get_pmc_register(self.serialno_reg) + if (fantray_serialno == 'ERR') or not self.get_presence(): + fantray_serialno = 'NA' + + return fantray_serialno + + def get_presence(self): + """ + Retrieves the presence of the Fandrawer + Returns: + bool: True if fan is present, False if not + """ + presence = False + fantray_presence = self._get_pmc_register(self.presence_reg) + if (fantray_presence != 'ERR'): + fantray_presence = int(fantray_presence, 10) + if (~fantray_presence & 0b1): + presence = True + + return presence + + def get_status(self): + """ + Retrieves the operational status of the Fandrawer + + Returns: + bool: True if Fandrawer is operating properly, False if not + """ + return self.get_fan(0).get_status() + + def get_position_in_parent(self): + """ + Retrieves 1-based relative physical position in parent device. + Returns: + integer: The 1-based relative physical position in parent + device or -1 if cannot determine the position + """ + return self.index + + def is_replaceable(self): + """ + Indicate whether this Fandrawer is replaceable. + Returns: + bool: True if it is replaceable. + """ + return True + + def set_status_led(self, color): + """ + Set led to expected color + Args: + color: A string representing the color with which to set the + fan module status LED + Returns: + bool: True if set success, False if fail. + """ + # Leds are controlled by Smart-fussion FPGA. + # Return True to avoid thermalctld alarm. + return True + + def get_status_led(self): + """ + Gets the state of the Fan status LED + + Returns: + A string, one of the predefined STATUS_LED_COLOR_* strings. + """ + if self.get_presence(): + if self.get_fan(0).get_status(): + return self.STATUS_LED_COLOR_GREEN + else: + return self.STATUS_LED_COLOR_AMBER + else: + return self.STATUS_LED_COLOR_OFF diff --git a/platform/broadcom/sonic-platform-modules-dell/s6100/sonic_platform/module.py b/platform/broadcom/sonic-platform-modules-dell/s6100/sonic_platform/module.py index 6b93bcfd1fa..923bb5c0550 100644 --- a/platform/broadcom/sonic-platform-modules-dell/s6100/sonic_platform/module.py +++ b/platform/broadcom/sonic-platform-modules-dell/s6100/sonic_platform/module.py @@ -63,7 +63,7 @@ def __init__(self, module_index): self.iom_presence_reg = "iom_presence" component = Component(is_module=True, iom_index=self.index, - i2c_line=self.port_i2c_line) + i2c_line=self.port_i2c_line, dependency=self) self._component_list.append(component) eeprom_base = "/sys/class/i2c-adapter/i2c-{0}/i2c-{1}/{1}-0050/eeprom" @@ -157,6 +157,23 @@ def get_status(self): return status + def get_position_in_parent(self): + """ + Retrieves 1-based relative physical position in parent device. + Returns: + integer: The 1-based relative physical position in parent + device or -1 if cannot determine the position + """ + return self.index + + def is_replaceable(self): + """ + Indicate whether Module is replaceable. + Returns: + bool: True if it is replaceable. + """ + return True + def get_base_mac(self): """ Retrieves the base MAC address for the module diff --git a/platform/broadcom/sonic-platform-modules-dell/s6100/sonic_platform/psu.py b/platform/broadcom/sonic-platform-modules-dell/s6100/sonic_platform/psu.py index 48b266daa27..4e528b679e4 100644 --- a/platform/broadcom/sonic-platform-modules-dell/s6100/sonic_platform/psu.py +++ b/platform/broadcom/sonic-platform-modules-dell/s6100/sonic_platform/psu.py @@ -34,13 +34,15 @@ def __init__(self, psu_index): self.psu_voltage_reg = "in30_input" self.psu_current_reg = "curr602_input" self.psu_power_reg = "power2_input" + self.psu_temperature_reg = "temp14_input" elif self.index == 2: self.psu_voltage_reg = "in32_input" self.psu_current_reg = "curr702_input" self.psu_power_reg = "power4_input" + self.psu_temperature_reg = "temp15_input" # Passing True to specify it is a PSU fan - psu_fan = Fan(fan_index=self.index, psu_fan=True) + psu_fan = Fan(psu_index=self.index, psu_fan=True) self._fan_list.append(psu_fan) def _get_pmc_register(self, reg_name): @@ -232,3 +234,87 @@ def set_status_led(self, color): # In S6100, SmartFusion FPGA controls the PSU LED and the PSU # LED state cannot be changed from CPU. return False + + def get_position_in_parent(self): + """ + Retrieves 1-based relative physical position in parent device. + Returns: + integer: The 1-based relative physical position in parent + device or -1 if cannot determine the position + """ + return self.index + + def is_replaceable(self): + """ + Indicate whether this PSU is replaceable. + Returns: + bool: True if it is replaceable. + """ + return True + + def get_temperature(self): + """ + Retrieves current temperature reading from PSU + + Returns: + A float number of current temperature in Celsius up to + nearest thousandth of one degree Celsius, e.g. 30.125 + """ + temperature = 0.0 + if self.get_presence(): + psu_temperature = self._get_pmc_register(self.psu_temperature_reg) + if (psu_temperature != 'ERR'): + temperature = float(psu_temperature) / 1000 + + return temperature + + def get_temperature_high_threshold(self): + """ + Retrieves the high threshold temperature of PSU + + Returns: + A float number, the high threshold temperature of PSU in + Celsius up to nearest thousandth of one degree Celsius, + e.g. 30.125 + """ + return 90.0 + + def get_voltage_high_threshold(self): + """ + Retrieves the high threshold PSU voltage output + + Returns: + A float number, the high threshold output voltage in volts, + e.g. 12.1 + """ + voltage_high_threshold = 0.0 + if self.get_presence(): + psu_type = self._get_pmc_register(self.psu_presence_reg) + if (psu_type != 'ERR'): + psu_type = int(psu_type, 16) + if (psu_type & 0b10): + voltage_high_threshold = 12.6 + else: + voltage_high_threshold = 12.8 + + return voltage_high_threshold + + def get_voltage_low_threshold(self): + """ + Retrieves the low threshold PSU voltage output + + Returns: + A float number, the low threshold output voltage in volts, + e.g. 12.1 + """ + voltage_low_threshold = 0.0 + if self.get_presence(): + psu_type = self._get_pmc_register(self.psu_presence_reg) + if (psu_type != 'ERR'): + psu_type = int(psu_type, 16) + if (psu_type & 0b10): + voltage_low_threshold = 11.4 + else: + voltage_low_threshold = 11.6 + + return voltage_low_threshold diff --git a/platform/broadcom/sonic-platform-modules-dell/s6100/sonic_platform/sfp.py b/platform/broadcom/sonic-platform-modules-dell/s6100/sonic_platform/sfp.py index 6947b6cf2b6..0b242ab74d7 100755 --- a/platform/broadcom/sonic-platform-modules-dell/s6100/sonic_platform/sfp.py +++ b/platform/broadcom/sonic-platform-modules-dell/s6100/sonic_platform/sfp.py @@ -10,6 +10,7 @@ try: import re + import struct import time from sonic_platform_base.sfp_base import SfpBase from sonic_platform_base.sonic_sfp.sff8436 import sff8436InterfaceId @@ -27,6 +28,9 @@ DOM_OFFSET = 0 DOM_OFFSET1 = 384 +QSFP_CONTROL_OFFSET = 86 +QSFP_POWEROVERRIDE_OFFSET = 93 + cable_length_tup = ('Length(km)', 'Length OM3(2m)', 'Length OM2(m)', 'Length OM1(m)', 'Length Cable Assembly(m)') @@ -107,7 +111,7 @@ def __init__(self, index, sfp_type, eeprom_path, sfp_control, sfp_ctrl_idx): SfpBase.__init__(self) self.sfp_type = sfp_type - self.index = index + self.index = index + 1 self.eeprom_path = eeprom_path self.sfp_control = sfp_control self.sfp_ctrl_idx = sfp_ctrl_idx @@ -131,9 +135,10 @@ def _read_eeprom_bytes(self, eeprom_path, offset, num_bytes): eeprom.close() return None + raw = bytearray(raw) try: for n in range(0, num_bytes): - eeprom_raw[n] = hex(ord(raw[n]))[2:].zfill(2) + eeprom_raw[n] = hex(raw[n])[2:].zfill(2) except BaseException: eeprom.close() return None @@ -594,40 +599,14 @@ def get_tx_disable_channel(self): """ Retrieves the TX disabled channels in this SFP """ - tx_disable = None - tx_disable_list = [] + tx_disable_channel = 0 - tx_disable_data = self._get_eeprom_data('tx_disable') - if (tx_disable_data is not None): - tx_disable = tx_disable_data['data']['Tx1Disable']['value'] - if (tx_disable == 'On'): - tx_disable_list.append(1) - else: - tx_disable_list.append(0) - tx_disable = tx_disable_data['data']['Tx2Disable']['value'] - if (tx_disable == 'On'): - tx_disable_list.append(1) - else: - tx_disable_list.append(0) - tx_disable = tx_disable_data['data']['Tx3Disable']['value'] - if (tx_disable == 'On'): - tx_disable_list.append(1) - else: - tx_disable_list.append(0) - tx_disable = tx_disable_data['data']['Tx4Disable']['value'] - if (tx_disable == 'On'): - tx_disable_list.append(1) - else: - tx_disable_list.append(0) - - bit4 = int(tx_disable_list[3]) * 8 - bit3 = int(tx_disable_list[2]) * 4 - bit2 = int(tx_disable_list[1]) * 2 - bit1 = int(tx_disable_list[0]) * 1 - - tx_disable_channel = hex(bit4 + bit3 + bit2 + bit1) + tx_disable = self.get_tx_disable() + for channel, disable in enumerate(tx_disable): + if disable: + tx_disable_channel |= 1 << channel - return tx_disable_channel + return tx_disable_channel def get_lpmode(self): """ @@ -836,19 +815,68 @@ def tx_disable(self, tx_disable): """ Disable SFP TX for all channels """ - return False + eeprom = None + tx_disable_value = 0xf if tx_disable else 0x0 + + try: + eeprom = open(self.eeprom_path, "r+b") + eeprom.seek(QSFP_CONTROL_OFFSET) + eeprom.write(struct.pack('B', tx_disable_value)) + except IOError: + return False + finally: + if eeprom is not None: + eeprom.close() + time.sleep(0.01) + + return True def tx_disable_channel(self, channel, disable): """ Sets the tx_disable for specified SFP channels """ - return False + eeprom = None + current_state = self.get_tx_disable_channel() + + if disable: + tx_disable_value = current_state | channel + else: + tx_disable_value = current_state & (~channel) + + try: + eeprom = open(self.eeprom_path, "r+b") + eeprom.seek(QSFP_CONTROL_OFFSET) + eeprom.write(struct.pack('B', tx_disable_value)) + except IOError: + return False + finally: + if eeprom is not None: + eeprom.close() + time.sleep(0.01) + + return True def set_power_override(self, power_override, power_set): """ Sets SFP power level using power_override and power_set """ - return False + eeprom = None + power_override_bit = 0x1 if power_override else 0 + power_set_bit = 0x2 if power_set else 0 + value = power_override_bit | power_set_bit + + try: + eeprom = open(self.eeprom_path, "r+b") + eeprom.seek(QSFP_POWEROVERRIDE_OFFSET) + eeprom.write(struct.pack('B', value)) + except IOError: + return False + finally: + if eeprom is not None: + eeprom.close() + time.sleep(0.01) + + return True def get_status(self): """ @@ -862,3 +890,20 @@ def get_status(self): status = True return status + + def get_position_in_parent(self): + """ + Retrieves 1-based relative physical position in parent device. + Returns: + integer: The 1-based relative physical position in parent + device or -1 if cannot determine the position + """ + return self.index + + def is_replaceable(self): + """ + Indicate whether this device is replaceable. + Returns: + bool: True if it is replaceable. + """ + return True diff --git a/platform/broadcom/sonic-platform-modules-dell/s6100/sonic_platform/thermal.py b/platform/broadcom/sonic-platform-modules-dell/s6100/sonic_platform/thermal.py index f7037b000c5..cac17f4b83a 100644 --- a/platform/broadcom/sonic-platform-modules-dell/s6100/sonic_platform/thermal.py +++ b/platform/broadcom/sonic-platform-modules-dell/s6100/sonic_platform/thermal.py @@ -131,6 +131,23 @@ def get_status(self): return status + def get_position_in_parent(self): + """ + Retrieves 1-based relative physical position in parent device. + Returns: + integer: The 1-based relative physical position in parent + device or -1 if cannot determine the position + """ + return self.index + + def is_replaceable(self): + """ + Indicate whether this Thermal is replaceable. + Returns: + bool: True if it is replaceable. + """ + return False + def get_temperature(self): """ Retrieves current temperature reading from thermal diff --git a/platform/broadcom/sonic-platform-modules-dell/z9264f/sonic_platform/sfp.py b/platform/broadcom/sonic-platform-modules-dell/z9264f/sonic_platform/sfp.py index 8d9bd36c6ab..225aef90e00 100644 --- a/platform/broadcom/sonic-platform-modules-dell/z9264f/sonic_platform/sfp.py +++ b/platform/broadcom/sonic-platform-modules-dell/z9264f/sonic_platform/sfp.py @@ -122,7 +122,7 @@ 'hardware_rev': [QSFP_INFO_OFFSET, 56, 2, 'parse_vendor_rev'], 'serial': [QSFP_INFO_OFFSET, 68, 16, 'parse_vendor_sn'], 'vendor_date': [QSFP_INFO_OFFSET, 84, 8, 'parse_vendor_date'], - 'dom_capability': [QSFP_INFO_OFFSET, 92, 1, 'parse_qsfp_dom_capability'], + 'dom_capability': [QSFP_INFO_OFFSET, 92, 1, 'parse_dom_capability'], 'dom_rev': [QSFP_DOM_OFFSET, 1, 1, 'parse_sfp_dom_rev'], 'ModuleThreshold': [QSFP_DOM_OFFSET1, 128, 24, 'parse_module_threshold_values'], 'ChannelThreshold': [QSFP_DOM_OFFSET1, 176, 16, 'parse_channel_threshold_values'], diff --git a/platform/broadcom/sonic-platform-modules-dell/z9332f/sonic_platform/chassis.py b/platform/broadcom/sonic-platform-modules-dell/z9332f/sonic_platform/chassis.py index 3651b0d4bf0..cead0eb326e 100755 --- a/platform/broadcom/sonic-platform-modules-dell/z9332f/sonic_platform/chassis.py +++ b/platform/broadcom/sonic-platform-modules-dell/z9332f/sonic_platform/chassis.py @@ -19,6 +19,7 @@ from sonic_platform.thermal import Thermal from sonic_platform.fan_drawer import FanDrawer from sonic_platform.watchdog import Watchdog + import sonic_platform.hwaccess as hwaccess except ImportError as e: raise ImportError(str(e) + "- required module not found") @@ -53,9 +54,25 @@ class Chassis(ChassisBase): REBOOT_CAUSE_PATH = "/host/reboot-cause/platform/reboot_reason" oir_fd = -1 epoll = -1 + io_res = "/dev/port" + sysled_offset = 0xA162 + SYSLED_COLOR_TO_REG = { + "green": 0xd0, + "yellow": 0xe0, + "flash_green": 0xd2, + "flash_yellow": 0xe2 + } + + REG_TO_SYSLED_COLOR = { + 0xd0 : "green", + 0xe0 : "yellow", + 0xd2 : "flash_green", + 0xd1 : "flash_green", + 0xe2 : "flash_yellow", + 0xe1 : "flash_yellow" + } _global_port_pres_dict = {} - _port_to_i2c_mapping = { 1: 10, 2: 11, @@ -317,3 +334,35 @@ def get_reboot_cause(self): def get_qualified_media_list(self): return media_part_num_list + + def initizalize_system_led(self): + self.sys_ledcolor = "green" + + def get_status_led(self): + """ + Gets the current system LED color + + Returns: + A string that represents the supported color + """ + val = hwaccess.io_reg_read(self.io_res, self.sysled_offset) + if val != -1: + return self.REG_TO_SYSLED_COLOR.get(val) + return self.sys_ledcolor + + def set_status_led(self, color): + """ + Set system LED status based on the color type passed in the argument. + Argument: Color to be set + Returns: + bool: True is specified color is set, Otherwise return False + """ + + if color not in list(self.SYSLED_COLOR_TO_REG.keys()): + return False + + if(not hwaccess.io_reg_write(self.io_res, self.sysled_offset, self.SYSLED_COLOR_TO_REG[color])): + return False + self.sys_ledcolor = color + return True + diff --git a/platform/broadcom/sonic-platform-modules-dell/z9332f/sonic_platform/ipmihelper.py b/platform/broadcom/sonic-platform-modules-dell/z9332f/sonic_platform/ipmihelper.py deleted file mode 100644 index ceeaebfbf04..00000000000 --- a/platform/broadcom/sonic-platform-modules-dell/z9332f/sonic_platform/ipmihelper.py +++ /dev/null @@ -1,269 +0,0 @@ -#!/usr/bin/python3 - -######################################################################## -# DellEMC -# -# Module contains implementation of IpmiSensor and IpmiFru classes that -# provide Sensor's and FRU's information respectively. -# -######################################################################## - -import subprocess -import re - -# IPMI Request Network Function Codes -NetFn_SensorEvent = 0x04 -NetFn_Storage = 0x0A - -# IPMI Sensor Device Commands -Cmd_GetSensorReadingFactors = 0x23 -Cmd_GetSensorThreshold = 0x27 -Cmd_GetSensorReading = 0x2D - -# IPMI FRU Device Commands -Cmd_ReadFRUData = 0x11 - -def get_ipmitool_raw_output(args): - """ - Returns a list the elements of which are the individual bytes of - ipmitool raw command output. - """ - result_bytes = list() - result = "" - command = "ipmitool raw {}".format(args) - try: - proc = subprocess.Popen(command.split(), stdout=subprocess.PIPE, - stderr=subprocess.STDOUT) - stdout = proc.communicate()[0] - proc.wait() - if not proc.returncode: - result = stdout.rstrip('\n') - except EnvironmentError: - pass - - for i in result.split(): - result_bytes.append(int(i, 16)) - - return result_bytes - -class IpmiSensor(object): - - # Sensor Threshold types and their respective bit masks - THRESHOLD_BIT_MASK = { - "LowerNonCritical" : 0, - "LowerCritical" : 1, - "LowerNonRecoverable" : 2, - "UpperNonCritical" : 3, - "UpperCritical" : 4, - "UpperNonRecoverable" : 5 - } - - def __init__(self, sensor_id, is_discrete=False): - self.id = sensor_id - self.is_discrete = is_discrete - - def _get_converted_sensor_reading(self, raw_value): - """ - Returns a 2 element tuple(bool, int) in which first element - provides the validity of the reading and the second element is - the converted sensor reading - """ - # Get Sensor Reading Factors - cmd_args = "{} {} {} {}".format(NetFn_SensorEvent, - Cmd_GetSensorReadingFactors, - self.id, raw_value) - factors = get_ipmitool_raw_output(cmd_args) - - if len(factors) != 7: - return False, 0 - - # Compute Twos complement - def get_twos_complement(val, bits): - if val & (1 << (bits - 1)): - val = val - (1 << bits) - return val - - # Calculate actual sensor value from the raw sensor value - # using the sensor reading factors. - M = get_twos_complement(((factors[2] & 0xC0) << 8) | factors[1], 10) - B = get_twos_complement(((factors[4] & 0xC0) << 8) | factors[3], 10) - R_exp = get_twos_complement((factors[6] & 0xF0) >> 4, 4) - B_exp = get_twos_complement(factors[6] & 0x0F, 4) - - converted_reading = ((M * raw_value) + (B * 10**B_exp)) * 10**R_exp - - return True, converted_reading - - def get_reading(self): - """ - For Threshold sensors, returns the sensor reading. - For Discrete sensors, returns the state value. - - Returns: - A tuple (bool, int) where the first element provides the - validity of the reading and the second element provides the - sensor reading/state value. - """ - # Get Sensor Reading - cmd_args = "{} {} {}".format(NetFn_SensorEvent, Cmd_GetSensorReading, - self.id) - output = get_ipmitool_raw_output(cmd_args) - if len(output) != 4: - return False, 0 - - # Check reading/state unavailable - if output[1] & 0x20: - return False, 0 - - if self.is_discrete: - state = ((output[3] & 0x7F) << 8) | output[2] - return True, state - else: - return self._get_converted_sensor_reading(output[0]) - - def get_threshold(self, threshold_type): - """ - Returns the sensor's threshold value for a given threshold type. - - Args: - threshold_type (str) - one of the below mentioned - threshold type strings - - "LowerNonCritical" - "LowerCritical" - "LowerNonRecoverable" - "UpperNonCritical" - "UpperCritical" - "UpperNonRecoverable" - Returns: - A tuple (bool, int) where the first element provides the - validity of that threshold and second element provides the - threshold value. - """ - # Thresholds are not valid for discrete sensors - if self.is_discrete: - raise TypeError("Threshold is not applicable for Discrete Sensor") - - if threshold_type not in list(self.THRESHOLD_BIT_MASK.keys()): - raise ValueError("Invalid threshold type {} provided. Valid types " - "are {}".format(threshold_type, - list(self.THRESHOLD_BIT_MASK.keys()))) - - bit_mask = self.THRESHOLD_BIT_MASK[threshold_type] - - # Get Sensor Threshold - cmd_args = "{} {} {}".format(NetFn_SensorEvent, Cmd_GetSensorThreshold, - self.id) - thresholds = get_ipmitool_raw_output(cmd_args) - if len(thresholds) != 7: - return False, 0 - - valid_thresholds = thresholds.pop(0) - # Check whether particular threshold is readable - if valid_thresholds & (1 << bit_mask): - return self._get_converted_sensor_reading(thresholds[bit_mask]) - else: - return False, 0 - -class IpmiFru(object): - - def __init__(self, fru_id): - self.id = fru_id - - def _get_ipmitool_fru_print(self): - result = "" - command = "ipmitool fru print {}".format(self.id) - try: - proc = subprocess.Popen(command.split(), stdout=subprocess.PIPE, - stderr=subprocess.STDOUT) - stdout = proc.communicate()[0] - proc.wait() - if not proc.returncode: - result = stdout.decode('utf-8').rstrip('\n') - except EnvironmentError: - pass - - return result - - def _get_from_fru(self, info): - """ - Returns a string containing the info from FRU - """ - fru_output = self._get_ipmitool_fru_print() - if not fru_output: - return "NA" - - info_req = re.search(r"%s\s*:(.*)" % info, fru_output) - if not info_req: - return "NA" - - return info_req.group(1).strip() - - def get_board_serial(self): - """ - Returns a string containing the Serial Number of the device. - """ - return self._get_from_fru('Board Serial') - - def get_board_part_number(self): - """ - Returns a string containing the Part Number of the device. - """ - return self._get_from_fru('Board Part Number') - - def get_board_mfr_id(self): - """ - Returns a string containing the manufacturer id of the FRU. - """ - return self._get_from_fru('Board Mfg') - - def get_board_product(self): - """ - Returns a string containing the manufacturer id of the FRU. - """ - return self._get_from_fru('Board Product') - - def get_fru_data(self, offset, count=1): - """ - Reads and returns the FRU data at the provided offset. - - Args: - offset (int) - FRU offset to read - count (int) - Number of bytes to read [optional, default = 1] - Returns: - A tuple (bool, list(int)) where the first element provides - the validity of the data read and the second element is a - list, the elements of which are the individual bytes of the - FRU data read. - """ - result_bytes = list() - is_valid = True - result = "" - - offset_LSB = offset & 0xFF - offset_MSB = offset & 0xFF00 - command = "ipmitool raw {} {} {} {} {} {}".format(NetFn_Storage, - Cmd_ReadFRUData, - self.id, offset_LSB, - offset_MSB, count) - try: - proc = subprocess.Popen(command.split(), stdout=subprocess.PIPE, - stderr=subprocess.STDOUT) - stdout = proc.communicate()[0] - proc.wait() - if not proc.returncode: - result = stdout.decode('utf-8').rstrip('\n') - except EnvironmentError: - is_valid = False - - if (not result) or (not is_valid): - return False, result_bytes - - for i in result.split(): - result_bytes.append(int(i, 16)) - - read_count = result_bytes.pop(0) - if read_count != count: - return False, result_bytes - else: - return True, result_bytes diff --git a/platform/broadcom/sonic-platform-modules-dell/z9332f/sonic_platform/psu.py b/platform/broadcom/sonic-platform-modules-dell/z9332f/sonic_platform/psu.py index 3be32043ade..0d06c31fcf8 100644 --- a/platform/broadcom/sonic-platform-modules-dell/z9332f/sonic_platform/psu.py +++ b/platform/broadcom/sonic-platform-modules-dell/z9332f/sonic_platform/psu.py @@ -21,9 +21,11 @@ class Psu(PsuBase): # { PSU-ID: { Sensor-Name: Sensor-ID } } SENSOR_MAPPING = { 1: { "State": 0x2f, "Current": 0x37, - "Power": 0x38, "Voltage": 0x36 }, + "Power": 0x38, "Voltage": 0x36, + "Temperature": 0x35 }, 2: { "State": 0x39, "Current": 0x41, - "Power": 0x42, "Voltage": 0x40 } } + "Power": 0x42, "Voltage": 0x40, + "Temperature": 0x3F } } # ( PSU-ID: FRU-ID } FRU_MAPPING = { 1: 3, 2: 4 } @@ -36,6 +38,7 @@ def __init__(self, psu_index): self.voltage_sensor = IpmiSensor(self.SENSOR_MAPPING[self.index]["Voltage"]) self.current_sensor = IpmiSensor(self.SENSOR_MAPPING[self.index]["Current"]) self.power_sensor = IpmiSensor(self.SENSOR_MAPPING[self.index]["Power"]) + self.temp_sensor = IpmiSensor(self.SENSOR_MAPPING[self.index ]["Temperature"]) self.fru = IpmiFru(self.FRU_MAPPING[self.index]) self.psu_type_raw_cmd = "0x3A 0x0B {}".format(psu_index+1) @@ -112,6 +115,38 @@ def get_voltage(self): return "{:.1f}".format(voltage) + def get_voltage_low_threshold(self): + """ + Returns PSU low threshold in Volts + """ + return 11.4 + + def get_voltage_high_threshold(self): + """ + Returns PSU high threshold in Volts + """ + return 12.6 + + def get_temperature(self): + """ + Retrieves current temperature reading from thermal + + Returns: + A float number of current temperature in Celsius up to + nearest thousandth of one degree Celsius, e.g. 30.125 + """ + is_valid, temperature = self.temp_sensor.get_reading() + if not is_valid: + temperature = 0 + + return float(temperature) + + def get_temperature_high_threshold(self): + """ + Returns the high temperature threshold for PSU in Celsius + """ + return 45.0 + def get_current(self): """ Retrieves present electric current supplied by PSU diff --git a/platform/broadcom/sonic-platform-modules-dell/z9332f/sonic_platform/sfp.py b/platform/broadcom/sonic-platform-modules-dell/z9332f/sonic_platform/sfp.py index 7fc50958c9e..ef6a2c5d339 100644 --- a/platform/broadcom/sonic-platform-modules-dell/z9332f/sonic_platform/sfp.py +++ b/platform/broadcom/sonic-platform-modules-dell/z9332f/sonic_platform/sfp.py @@ -127,7 +127,7 @@ 'hardware_rev': [QSFP_INFO_OFFSET, 56, 2, 'parse_vendor_rev'], 'serial': [QSFP_INFO_OFFSET, 68, 16, 'parse_vendor_sn'], 'vendor_date': [QSFP_INFO_OFFSET, 84, 8, 'parse_vendor_date'], - 'dom_capability': [QSFP_INFO_OFFSET, 92, 1, 'parse_qsfp_dom_capability'], + 'dom_capability': [QSFP_INFO_OFFSET, 92, 1, 'parse_dom_capability'], 'dom_rev': [QSFP_DOM_OFFSET, 1, 1, 'parse_sfp_dom_rev'], 'ModuleThreshold': [QSFP_DOM_OFFSET1, 128, 24, 'parse_module_threshold_values'], 'ChannelThreshold': [QSFP_DOM_OFFSET1, 176, 16, 'parse_channel_threshold_values'], diff --git a/platform/broadcom/sonic-platform-modules-delta/debian/control b/platform/broadcom/sonic-platform-modules-delta/debian/control index 6105f280ad3..809c58b0c0b 100644 --- a/platform/broadcom/sonic-platform-modules-delta/debian/control +++ b/platform/broadcom/sonic-platform-modules-delta/debian/control @@ -7,30 +7,30 @@ Standards-Version: 3.9.3 Package: platform-modules-ag9032v1 Architecture: amd64 -Depends: linux-image-4.19.0-9-2-amd64-unsigned +Depends: linux-image-4.19.0-12-2-amd64-unsigned Description: kernel modules for platform devices such as fan, led, sfp Package: platform-modules-ag9064 Architecture: amd64 -Depends: linux-image-4.19.0-9-2-amd64-unsigned +Depends: linux-image-4.19.0-12-2-amd64-unsigned Description: kernel modules for platform devices such as fan, led, sfp Package: platform-modules-ag5648 Architecture: amd64 -Depends: linux-image-4.19.0-9-2-amd64-unsigned +Depends: linux-image-4.19.0-12-2-amd64-unsigned Description: kernel modules for platform devices such as fan, led, sfp Package: platform-modules-et-6248brb Architecture: amd64 -Depends: linux-image-4.19.0-9-2-amd64-unsigned +Depends: linux-image-4.19.0-12-2-amd64-unsigned Description: kernel modules for platform devices such as fan, led, sfp Package: platform-modules-ag9032v2a Architecture: amd64 -Depends: linux-image-4.19.0-9-2-amd64-unsigned +Depends: linux-image-4.19.0-12-2-amd64-unsigned Description: kernel modules for platform devices such as syseeprom, sfp Package: platform-modules-agc032 Architecture: amd64 -Depends: linux-image-4.19.0-9-2-amd64-unsigned +Depends: linux-image-4.19.0-12-2-amd64-unsigned Description: kernel modules for platform devices such as fan, led, sfp diff --git a/platform/broadcom/sonic-platform-modules-inventec/d6332/sonic_platform/qsfp.py b/platform/broadcom/sonic-platform-modules-inventec/d6332/sonic_platform/qsfp.py index 178ac0cf9aa..17763cd1264 100644 --- a/platform/broadcom/sonic-platform-modules-inventec/d6332/sonic_platform/qsfp.py +++ b/platform/broadcom/sonic-platform-modules-inventec/d6332/sonic_platform/qsfp.py @@ -436,7 +436,7 @@ def get_transceiver_bulk_status(self): # in SFF-8636 dom capability definitions evolving with the versions. qsfp_dom_capability_raw = self.__read_eeprom_specific_bytes((offset_xcvr + XCVR_DOM_CAPABILITY_OFFSET), XCVR_DOM_CAPABILITY_WIDTH) if qsfp_dom_capability_raw is not None: - qspf_dom_capability_data = sfpi_obj.parse_qsfp_dom_capability(qsfp_dom_capability_raw, 0) + qspf_dom_capability_data = sfpi_obj.parse_dom_capability(qsfp_dom_capability_raw, 0) else: return None @@ -793,7 +793,7 @@ def get_tx_bias(self): qsfp_dom_capability_raw = self.__read_eeprom_specific_bytes((offset_xcvr + XCVR_DOM_CAPABILITY_OFFSET), XCVR_DOM_CAPABILITY_WIDTH) if qsfp_dom_capability_raw is not None: - qspf_dom_capability_data = sfpi_obj.parse_qsfp_dom_capability(qsfp_dom_capability_raw, 0) + qspf_dom_capability_data = sfpi_obj.parse_dom_capability(qsfp_dom_capability_raw, 0) else: return None @@ -844,7 +844,7 @@ def get_rx_power(self): qsfp_dom_capability_raw = self.__read_eeprom_specific_bytes((offset_xcvr + XCVR_DOM_CAPABILITY_OFFSET), XCVR_DOM_CAPABILITY_WIDTH) if qsfp_dom_capability_raw is not None: - qspf_dom_capability_data = sfpi_obj.parse_qsfp_dom_capability(qsfp_dom_capability_raw, 0) + qspf_dom_capability_data = sfpi_obj.parse_dom_capability(qsfp_dom_capability_raw, 0) else: return None @@ -895,7 +895,7 @@ def get_tx_power(self): qsfp_dom_capability_raw = self.__read_eeprom_specific_bytes((offset_xcvr + XCVR_DOM_CAPABILITY_OFFSET), XCVR_DOM_CAPABILITY_WIDTH) if qsfp_dom_capability_raw is not None: - qspf_dom_capability_data = sfpi_obj.parse_qsfp_dom_capability(qsfp_dom_capability_raw, 0) + qspf_dom_capability_data = sfpi_obj.parse_dom_capability(qsfp_dom_capability_raw, 0) else: return None diff --git a/platform/broadcom/sonic-platform-modules-inventec/d6356/sonic_platform/qsfp.py b/platform/broadcom/sonic-platform-modules-inventec/d6356/sonic_platform/qsfp.py index c002697d96a..2cc4b6ca593 100644 --- a/platform/broadcom/sonic-platform-modules-inventec/d6356/sonic_platform/qsfp.py +++ b/platform/broadcom/sonic-platform-modules-inventec/d6356/sonic_platform/qsfp.py @@ -388,7 +388,7 @@ def get_transceiver_bulk_status(self): # in SFF-8636 dom capability definitions evolving with the versions. qsfp_dom_capability_raw = self.__read_eeprom_specific_bytes((offset_xcvr + XCVR_DOM_CAPABILITY_OFFSET), XCVR_DOM_CAPABILITY_WIDTH) if qsfp_dom_capability_raw is not None: - qspf_dom_capability_data = sfpi_obj.parse_qsfp_dom_capability(qsfp_dom_capability_raw, 0) + qspf_dom_capability_data = sfpi_obj.parse_dom_capability(qsfp_dom_capability_raw, 0) else: return None diff --git a/platform/broadcom/sonic-platform-modules-inventec/d7054q28b/sonic_platform/sfp.py b/platform/broadcom/sonic-platform-modules-inventec/d7054q28b/sonic_platform/sfp.py index 760aa179c25..a18d98d502f 100644 --- a/platform/broadcom/sonic-platform-modules-inventec/d7054q28b/sonic_platform/sfp.py +++ b/platform/broadcom/sonic-platform-modules-inventec/d7054q28b/sonic_platform/sfp.py @@ -636,7 +636,7 @@ def get_transceiver_bulk_status(self): qsfp_dom_capability_raw = self.__read_eeprom_specific_bytes( (offset_xcvr + XCVR_DOM_CAPABILITY_OFFSET), XCVR_DOM_CAPABILITY_WIDTH) if qsfp_dom_capability_raw is not None: - qspf_dom_capability_data = sfpi_obj.parse_qsfp_dom_capability( + qspf_dom_capability_data = sfpi_obj.parse_dom_capability( qsfp_dom_capability_raw, 0) else: return None diff --git a/platform/broadcom/sonic-platform-modules-inventec/debian/control b/platform/broadcom/sonic-platform-modules-inventec/debian/control index d5ba6b0869e..7a435d9b6e6 100644 --- a/platform/broadcom/sonic-platform-modules-inventec/debian/control +++ b/platform/broadcom/sonic-platform-modules-inventec/debian/control @@ -7,35 +7,35 @@ Standards-Version: 3.9.3 Package: platform-modules-d7032q28b Architecture: amd64 -Depends: linux-image-4.19.0-9-2-amd64-unsigned +Depends: linux-image-4.19.0-12-2-amd64-unsigned Description: kernel modules for platform devices such as fan, led Package: platform-modules-d7054q28b Architecture: amd64 -Depends: linux-image-4.19.0-9-2-amd64-unsigned +Depends: linux-image-4.19.0-12-2-amd64-unsigned Description: kernel modules for platform devices such as fan, led Package: platform-modules-d6254qs Architecture: amd64 -Depends: linux-image-4.19.0-9-2-amd64-unsigned +Depends: linux-image-4.19.0-12-2-amd64-unsigned Description: kernel modules for platform devices such as fan, led Package: platform-modules-d6556 Architecture: amd64 -Depends: linux-image-4.19.0-9-2-amd64-unsigned +Depends: linux-image-4.19.0-12-2-amd64-unsigned Description: kernel modules for platform devices such as fan, led Package: platform-modules-d6356 Architecture: amd64 -Depends: linux-image-4.19.0-9-2-amd64-unsigned +Depends: linux-image-4.19.0-12-2-amd64-unsigned Description: kernel modules for platform devices such as fan, led Package: platform-modules-d7264q28b Architecture: amd64 -Depends: linux-image-4.19.0-9-2-amd64-unsigned +Depends: linux-image-4.19.0-12-2-amd64-unsigned Description: kernel modules for platform devices such as fan, led Package: platform-modules-d6332 Architecture: amd64 -Depends: linux-image-4.19.0-9-2-amd64-unsigned +Depends: linux-image-4.19.0-12-2-amd64-unsigned Description: kernel modules for platform devices such as fan, led diff --git a/platform/broadcom/sonic-platform-modules-mitac/debian/control b/platform/broadcom/sonic-platform-modules-mitac/debian/control index f1a62577f6e..f909c6af948 100644 --- a/platform/broadcom/sonic-platform-modules-mitac/debian/control +++ b/platform/broadcom/sonic-platform-modules-mitac/debian/control @@ -7,6 +7,6 @@ Standards-Version: 3.9.3 Package: sonic-platform-mitac-ly1200-32x Architecture: amd64 -Depends: linux-image-4.19.0-9-2-amd64-unsigned +Depends: linux-image-4.19.0-12-2-amd64-unsigned Description: kernel modules for platform devices such as fan, led, sfp diff --git a/platform/cavium/cavm_platform_modules/DEBIAN/control b/platform/cavium/cavm_platform_modules/DEBIAN/control index 938215c8f8e..6a665e88c71 100755 --- a/platform/cavium/cavm_platform_modules/DEBIAN/control +++ b/platform/cavium/cavm_platform_modules/DEBIAN/control @@ -1,6 +1,6 @@ Package: cavm-platform-modules Version: 1.0 Architecture: amd64 -Depends: linux-image-4.19.0-9-2-amd64-unsigned +Depends: linux-image-4.19.0-12-2-amd64-unsigned Maintainer: Nadiya.Stetskovych@cavium.com Description: kernel modules for platform devices such as fan, led, sfp diff --git a/platform/cavium/docker-ptf-cavm.mk b/platform/cavium/docker-ptf-cavm.mk deleted file mode 100644 index ea96fd050bf..00000000000 --- a/platform/cavium/docker-ptf-cavm.mk +++ /dev/null @@ -1,8 +0,0 @@ -# docker image for docker-ptf-cavm - -DOCKER_PTF_CAVM = docker-ptf-cavm.gz -$(DOCKER_PTF_CAVM)_PATH = $(DOCKERS_PATH)/docker-ptf-saithrift -$(DOCKER_PTF_CAVM)_DEPENDS += $(PYTHON_SAITHRIFT_CAVM) -$(DOCKER_PTF_CAVM)_LOAD_DOCKERS += $(DOCKER_PTF) -SONIC_DOCKER_IMAGES += $(DOCKER_PTF_CAVM) -SONIC_STRETCH_DOCKERS += $(DOCKER_PTF_CAVM) diff --git a/platform/cavium/docker-syncd-cavm/supervisord.conf b/platform/cavium/docker-syncd-cavm/supervisord.conf index 0c6285d46ae..91b94a25803 100644 --- a/platform/cavium/docker-syncd-cavm/supervisord.conf +++ b/platform/cavium/docker-syncd-cavm/supervisord.conf @@ -5,7 +5,7 @@ nodaemon=true [eventlistener:supervisor-proc-exit-listener] command=/usr/bin/supervisor-proc-exit-listener --container-name syncd -events=PROCESS_STATE_EXITED +events=PROCESS_STATE_EXITED,PROCESS_STATE_RUNNING autostart=true autorestart=unexpected diff --git a/platform/cavium/rules.mk b/platform/cavium/rules.mk index bbc2e4d2d2f..a526774d295 100644 --- a/platform/cavium/rules.mk +++ b/platform/cavium/rules.mk @@ -5,7 +5,6 @@ include $(PLATFORM_PATH)/cavm-platform-modules.mk include $(PLATFORM_PATH)/cavm-xpnet.mk include $(PLATFORM_PATH)/one-image.mk include $(PLATFORM_PATH)/libsaithrift-dev.mk -include $(PLATFORM_PATH)/docker-ptf-cavm.mk SONIC_ALL += $(SONIC_ONE_IMAGE) \ $(DOCKER_FPM) \ diff --git a/platform/centec-arm64/docker-ptf-centec.mk b/platform/centec-arm64/docker-ptf-centec.mk deleted file mode 100755 index 3d4fe50e5f1..00000000000 --- a/platform/centec-arm64/docker-ptf-centec.mk +++ /dev/null @@ -1,7 +0,0 @@ -# docker image for docker-ptf-centec - -DOCKER_PTF_CENTEC = docker-ptf-centec.gz -$(DOCKER_PTF_CENTEC)_PATH = $(DOCKERS_PATH)/docker-ptf-saithrift -$(DOCKER_PTF_CENTEC)_DEPENDS += $(PYTHON_SAITHRIFT) -$(DOCKER_PTF_CENTEC)_LOAD_DOCKERS += $(DOCKER_PTF) -SONIC_DOCKER_IMAGES += $(DOCKER_PTF_CENTEC) diff --git a/platform/centec-arm64/docker-syncd-centec-rpc/Dockerfile.j2 b/platform/centec-arm64/docker-syncd-centec-rpc/Dockerfile.j2 index d6719b224ab..057d93efb6b 100755 --- a/platform/centec-arm64/docker-syncd-centec-rpc/Dockerfile.j2 +++ b/platform/centec-arm64/docker-syncd-centec-rpc/Dockerfile.j2 @@ -21,6 +21,7 @@ RUN apt-get update \ && apt-get -y install \ net-tools \ python-pip \ + python-setuptools \ build-essential \ libssl-dev \ libffi-dev \ @@ -37,9 +38,10 @@ RUN apt-get update \ && cd .. \ && rm -fr nanomsg-1.0.0 \ && rm -f 1.0.0.tar.gz \ - && pip install cffi==1.7.0 \ - && pip install --upgrade cffi==1.7.0 \ - && pip install nnpy \ + && pip2 install cffi==1.7.0 \ + && pip2 install --upgrade cffi==1.7.0 \ + && pip2 install wheel \ + && pip2 install nnpy \ && mkdir -p /opt \ && cd /opt \ && wget https://raw.githubusercontent.com/p4lang/ptf/master/ptf_nn/ptf_nn_agent.py \ diff --git a/platform/centec-arm64/docker-syncd-centec/supervisord.conf b/platform/centec-arm64/docker-syncd-centec/supervisord.conf index 2cf6814ddaa..10f406129d9 100755 --- a/platform/centec-arm64/docker-syncd-centec/supervisord.conf +++ b/platform/centec-arm64/docker-syncd-centec/supervisord.conf @@ -14,7 +14,7 @@ buffer_size=25 [eventlistener:supervisor-proc-exit-listener] command=python2 /usr/bin/supervisor-proc-exit-listener --container-name syncd -events=PROCESS_STATE_EXITED +events=PROCESS_STATE_EXITED,PROCESS_STATE_RUNNING autostart=true autorestart=unexpected diff --git a/platform/centec-arm64/rules.mk b/platform/centec-arm64/rules.mk index 79e1ab12b88..1982f86b757 100755 --- a/platform/centec-arm64/rules.mk +++ b/platform/centec-arm64/rules.mk @@ -3,7 +3,6 @@ include $(PLATFORM_PATH)/docker-syncd-centec.mk include $(PLATFORM_PATH)/docker-syncd-centec-rpc.mk include $(PLATFORM_PATH)/one-image.mk include $(PLATFORM_PATH)/libsaithrift-dev.mk -include $(PLATFORM_PATH)/docker-ptf-centec.mk include $(PLATFORM_PATH)/tsingma-bsp.mk include $(PLATFORM_PATH)/platform-modules-centec-e530.mk diff --git a/platform/centec-arm64/sonic-platform-modules-e530/debian/control b/platform/centec-arm64/sonic-platform-modules-e530/debian/control index 023a365f4d7..2a1bc972a8b 100644 --- a/platform/centec-arm64/sonic-platform-modules-e530/debian/control +++ b/platform/centec-arm64/sonic-platform-modules-e530/debian/control @@ -7,10 +7,10 @@ Standards-Version: 3.9.3 Package: platform-modules-e530-48t4x-p Architecture: arm64 -Depends: linux-image-4.19.0-9-2-arm64-unsigned +Depends: linux-image-4.19.0-12-2-arm64-unsigned Description: kernel modules for platform devices such as fan, led, sfp Package: platform-modules-e530-24x2c Architecture: arm64 -Depends: linux-image-4.19.0-9-2-arm64-unsigned +Depends: linux-image-4.19.0-12-2-arm64-unsigned Description: kernel modules for platform devices such as fan, led, sfp diff --git a/platform/centec-arm64/sonic-platform-modules-e530/debian/platform-modules-e530-24x2c.install b/platform/centec-arm64/sonic-platform-modules-e530/debian/platform-modules-e530-24x2c.install index f9fceaf20f2..b74a968fe97 100644 --- a/platform/centec-arm64/sonic-platform-modules-e530/debian/platform-modules-e530-24x2c.install +++ b/platform/centec-arm64/sonic-platform-modules-e530/debian/platform-modules-e530-24x2c.install @@ -1,3 +1,3 @@ -../../centec/centec-dal/dal.ko /lib/modules/4.19.0-9-2-arm64/kernel/extra -24x2c/modules/centec_e530_24x2c_platform.ko /lib/modules/4.19.0-9-2-arm64/kernel/extra +../../centec/centec-dal/dal.ko /lib/modules/4.19.0-12-2-arm64/kernel/extra +24x2c/modules/centec_e530_24x2c_platform.ko /lib/modules/4.19.0-12-2-arm64/kernel/extra 24x2c/service/24x2c_platform.service /lib/systemd/system diff --git a/platform/centec-arm64/sonic-platform-modules-e530/debian/platform-modules-e530-48t4x-p.install b/platform/centec-arm64/sonic-platform-modules-e530/debian/platform-modules-e530-48t4x-p.install index 57d2eb4470a..7d1c00eebea 100644 --- a/platform/centec-arm64/sonic-platform-modules-e530/debian/platform-modules-e530-48t4x-p.install +++ b/platform/centec-arm64/sonic-platform-modules-e530/debian/platform-modules-e530-48t4x-p.install @@ -1,3 +1,3 @@ -../../centec/centec-dal/dal.ko /lib/modules/4.19.0-9-2-arm64/kernel/extra -48t4x_p/modules/centec_e530_48t4x_p_platform.ko /lib/modules/4.19.0-9-2-arm64/kernel/extra +../../centec/centec-dal/dal.ko /lib/modules/4.19.0-12-2-arm64/kernel/extra +48t4x_p/modules/centec_e530_48t4x_p_platform.ko /lib/modules/4.19.0-12-2-arm64/kernel/extra 48t4x_p/service/48t4x_p_platform.service /lib/systemd/system diff --git a/platform/centec-arm64/sonic_fit.its b/platform/centec-arm64/sonic_fit.its index 8a358ac325f..7ee89e6c812 100644 --- a/platform/centec-arm64/sonic_fit.its +++ b/platform/centec-arm64/sonic_fit.its @@ -12,7 +12,7 @@ images { kernel_ctc { description = "ARM64 Kernel"; - data = /incbin/("./vmlinuz-4.19.0-9-2-arm64"); + data = /incbin/("./vmlinuz-4.19.0-12-2-arm64"); type = "kernel"; arch = "arm64"; os = "linux"; @@ -25,7 +25,7 @@ }; initramfs { description = "initramfs"; - data = /incbin/("./initrd.img-4.19.0-9-2-arm64"); + data = /incbin/("./initrd.img-4.19.0-12-2-arm64"); type = "ramdisk"; arch = "arm64"; os = "linux"; diff --git a/platform/centec-arm64/tsingma-bsp/debian/control b/platform/centec-arm64/tsingma-bsp/debian/control index e183844f01e..fc6d0b8def4 100644 --- a/platform/centec-arm64/tsingma-bsp/debian/control +++ b/platform/centec-arm64/tsingma-bsp/debian/control @@ -7,5 +7,5 @@ Standards-Version: 3.9.3 Package: tsingma-bsp Architecture: arm64 -Depends: linux-image-4.19.0-9-2-arm64-unsigned +Depends: linux-image-4.19.0-12-2-arm64-unsigned Description: kernel modules for tsingma bsp diff --git a/platform/centec-arm64/tsingma-bsp/debian/tsingma-bsp.install b/platform/centec-arm64/tsingma-bsp/debian/tsingma-bsp.install index 81d328b6899..e2fb35af1b6 100644 --- a/platform/centec-arm64/tsingma-bsp/debian/tsingma-bsp.install +++ b/platform/centec-arm64/tsingma-bsp/debian/tsingma-bsp.install @@ -1,17 +1,17 @@ -src/ctc5236-mc/ctc5236-mc.ko /lib/modules/4.19.0-9-2-arm64/kernel/extra -src/pwm-ctc/pwm-ctc.ko /lib/modules/4.19.0-9-2-arm64/kernel/extra -src/ctc5236_switch/ctc5236_switch.ko /lib/modules/4.19.0-9-2-arm64/kernel/extra -src/pinctrl-ctc/pinctrl-ctc.ko /lib/modules/4.19.0-9-2-arm64/kernel/extra -src/ctc_wdt/ctc_wdt.ko /lib/modules/4.19.0-9-2-arm64/kernel/extra -src/ctcmac/ctcmac.ko /lib/modules/4.19.0-9-2-arm64/kernel/extra -src/ctcmac/ctcmac_test.ko /lib/modules/4.19.0-9-2-arm64/kernel/extra -src/ctcmac/ctc5236_mdio.ko /lib/modules/4.19.0-9-2-arm64/kernel/extra -src/i2c-ctc/i2c-ctc.ko /lib/modules/4.19.0-9-2-arm64/kernel/extra -src/gpio-ctc/gpio-ctc.ko /lib/modules/4.19.0-9-2-arm64/kernel/extra -src/ehci-ctc/ehci-ctc.ko /lib/modules/4.19.0-9-2-arm64/kernel/extra -src/rtc-sd2405/rtc-sd2405.ko /lib/modules/4.19.0-9-2-arm64/kernel/extra -src/sdhci-ctc5236/sdhci-ctc5236.ko /lib/modules/4.19.0-9-2-arm64/kernel/extra -src/spi-ctc-qspi/spi-ctc-qspi.ko /lib/modules/4.19.0-9-2-arm64/kernel/extra +src/ctc5236-mc/ctc5236-mc.ko /lib/modules/4.19.0-12-2-arm64/kernel/extra +src/pwm-ctc/pwm-ctc.ko /lib/modules/4.19.0-12-2-arm64/kernel/extra +src/ctc5236_switch/ctc5236_switch.ko /lib/modules/4.19.0-12-2-arm64/kernel/extra +src/pinctrl-ctc/pinctrl-ctc.ko /lib/modules/4.19.0-12-2-arm64/kernel/extra +src/ctc_wdt/ctc_wdt.ko /lib/modules/4.19.0-12-2-arm64/kernel/extra +src/ctcmac/ctcmac.ko /lib/modules/4.19.0-12-2-arm64/kernel/extra +src/ctcmac/ctcmac_test.ko /lib/modules/4.19.0-12-2-arm64/kernel/extra +src/ctcmac/ctc5236_mdio.ko /lib/modules/4.19.0-12-2-arm64/kernel/extra +src/i2c-ctc/i2c-ctc.ko /lib/modules/4.19.0-12-2-arm64/kernel/extra +src/gpio-ctc/gpio-ctc.ko /lib/modules/4.19.0-12-2-arm64/kernel/extra +src/ehci-ctc/ehci-ctc.ko /lib/modules/4.19.0-12-2-arm64/kernel/extra +src/rtc-sd2405/rtc-sd2405.ko /lib/modules/4.19.0-12-2-arm64/kernel/extra +src/sdhci-ctc5236/sdhci-ctc5236.ko /lib/modules/4.19.0-12-2-arm64/kernel/extra +src/spi-ctc-qspi/spi-ctc-qspi.ko /lib/modules/4.19.0-12-2-arm64/kernel/extra src/ctc-dts/e530-ctc5236.dtb /boot/ src/config/fw_env.config /etc/ src/config/tsingma-bsp.service /lib/systemd/system diff --git a/platform/centec/docker-ptf-centec.mk b/platform/centec/docker-ptf-centec.mk deleted file mode 100644 index 47284f71756..00000000000 --- a/platform/centec/docker-ptf-centec.mk +++ /dev/null @@ -1,8 +0,0 @@ -# docker image for docker-ptf-centec - -DOCKER_PTF_CENTEC = docker-ptf-centec.gz -$(DOCKER_PTF_CENTEC)_PATH = $(DOCKERS_PATH)/docker-ptf-saithrift -$(DOCKER_PTF_CENTEC)_DEPENDS += $(PYTHON_SAITHRIFT) -$(DOCKER_PTF_CENTEC)_LOAD_DOCKERS += $(DOCKER_PTF) -SONIC_DOCKER_IMAGES += $(DOCKER_PTF_CENTEC) -SONIC_STRETCH_DOCKERS += $(DOCKER_PTF_CENTEC) diff --git a/platform/centec/docker-syncd-centec-rpc/Dockerfile.j2 b/platform/centec/docker-syncd-centec-rpc/Dockerfile.j2 index d6719b224ab..057d93efb6b 100644 --- a/platform/centec/docker-syncd-centec-rpc/Dockerfile.j2 +++ b/platform/centec/docker-syncd-centec-rpc/Dockerfile.j2 @@ -21,6 +21,7 @@ RUN apt-get update \ && apt-get -y install \ net-tools \ python-pip \ + python-setuptools \ build-essential \ libssl-dev \ libffi-dev \ @@ -37,9 +38,10 @@ RUN apt-get update \ && cd .. \ && rm -fr nanomsg-1.0.0 \ && rm -f 1.0.0.tar.gz \ - && pip install cffi==1.7.0 \ - && pip install --upgrade cffi==1.7.0 \ - && pip install nnpy \ + && pip2 install cffi==1.7.0 \ + && pip2 install --upgrade cffi==1.7.0 \ + && pip2 install wheel \ + && pip2 install nnpy \ && mkdir -p /opt \ && cd /opt \ && wget https://raw.githubusercontent.com/p4lang/ptf/master/ptf_nn/ptf_nn_agent.py \ diff --git a/platform/centec/docker-syncd-centec/supervisord.conf b/platform/centec/docker-syncd-centec/supervisord.conf index 831b7256a43..6df1893a0be 100644 --- a/platform/centec/docker-syncd-centec/supervisord.conf +++ b/platform/centec/docker-syncd-centec/supervisord.conf @@ -13,7 +13,7 @@ events=PROCESS_STATE [eventlistener:supervisor-proc-exit-listener] command=python2 /usr/bin/supervisor-proc-exit-listener --container-name syncd -events=PROCESS_STATE_EXITED +events=PROCESS_STATE_EXITED,PROCESS_STATE_RUNNING autostart=true autorestart=unexpected diff --git a/platform/centec/rules.mk b/platform/centec/rules.mk index 52bb0275abf..182248ec1ac 100644 --- a/platform/centec/rules.mk +++ b/platform/centec/rules.mk @@ -5,7 +5,6 @@ include $(PLATFORM_PATH)/docker-syncd-centec.mk include $(PLATFORM_PATH)/docker-syncd-centec-rpc.mk include $(PLATFORM_PATH)/one-image.mk include $(PLATFORM_PATH)/libsaithrift-dev.mk -include $(PLATFORM_PATH)/docker-ptf-centec.mk SONIC_ALL += $(SONIC_ONE_IMAGE) diff --git a/platform/centec/sonic-platform-modules-e582/debian/control b/platform/centec/sonic-platform-modules-e582/debian/control index 5d6bcc7002e..97f617d4836 100644 --- a/platform/centec/sonic-platform-modules-e582/debian/control +++ b/platform/centec/sonic-platform-modules-e582/debian/control @@ -7,11 +7,11 @@ Standards-Version: 3.9.3 Package: platform-modules-e582-48x2q4z Architecture: amd64 -Depends: linux-image-4.19.0-9-2-amd64-unsigned +Depends: linux-image-4.19.0-12-2-amd64-unsigned Description: kernel modules for platform devices such as fan, led, sfp Package: platform-modules-e582-48x6q Architecture: amd64 -Depends: linux-image-4.19.0-9-2-amd64-unsigned +Depends: linux-image-4.19.0-12-2-amd64-unsigned Description: kernel modules for platform devices such as fan, led, sfp diff --git a/platform/centec/sonic-platform-modules-embedway/debian/control b/platform/centec/sonic-platform-modules-embedway/debian/control index 781f4df4342..6fb02a82482 100644 --- a/platform/centec/sonic-platform-modules-embedway/debian/control +++ b/platform/centec/sonic-platform-modules-embedway/debian/control @@ -7,6 +7,6 @@ Standards-Version: 3.9.3 Package: platform-modules-embedway-es6220 Architecture: amd64 -Depends: linux-image-4.19.0-9-2-amd64-unsigned +Depends: linux-image-4.19.0-12-2-amd64-unsigned Description: kernel modules for platform devices such as fan, led, sfp diff --git a/platform/innovium/docker-ptf-invm.mk b/platform/innovium/docker-ptf-invm.mk deleted file mode 100755 index 53ba41e9d38..00000000000 --- a/platform/innovium/docker-ptf-invm.mk +++ /dev/null @@ -1,8 +0,0 @@ -# docker image for docker-ptf-invm - -DOCKER_PTF_INVM = docker-ptf-invm.gz -$(DOCKER_PTF_INVM)_PATH = $(DOCKERS_PATH)/docker-ptf-saithrift -$(DOCKER_PTF_INVM)_DEPENDS += $(PYTHON_SAITHRIFT_INVM) -$(DOCKER_PTF_INVM)_LOAD_DOCKERS += $(DOCKER_PTF) -SONIC_DOCKER_IMAGES += $(DOCKER_PTF_INVM) -SONIC_STRETCH_DOCKERS += $(DOCKER_PTF_INVM) diff --git a/platform/innovium/rules.mk b/platform/innovium/rules.mk index 0387a4ba30f..ea23466ad57 100755 --- a/platform/innovium/rules.mk +++ b/platform/innovium/rules.mk @@ -6,7 +6,6 @@ include $(PLATFORM_PATH)/docker-syncd-invm-rpc.mk include $(PLATFORM_PATH)/one-image.mk include $(PLATFORM_PATH)/libsaithrift-dev.mk include $(PLATFORM_PATH)/python-saithrift.mk -include $(PLATFORM_PATH)/docker-ptf-invm.mk SONIC_ALL += $(SONIC_INVM_ONE_IMAGE) \ $(DOCKER_FPM) \ diff --git a/platform/innovium/sonic-platform-modules-cel/debian/control b/platform/innovium/sonic-platform-modules-cel/debian/control index 3b9152232d3..374f1f75d3a 100755 --- a/platform/innovium/sonic-platform-modules-cel/debian/control +++ b/platform/innovium/sonic-platform-modules-cel/debian/control @@ -7,5 +7,5 @@ Standards-Version: 3.9.3 Package: platform-modules-midstone-200i Architecture: amd64 -Depends: linux-image-4.19.0-9-2-amd64-unsigned +Depends: linux-image-4.19.0-12-2-amd64-unsigned Description: kernel modules for platform devices diff --git a/platform/innovium/sonic-platform-modules-delta/debian/control b/platform/innovium/sonic-platform-modules-delta/debian/control index ac94e19b4cf..bcfea2d42f1 100644 --- a/platform/innovium/sonic-platform-modules-delta/debian/control +++ b/platform/innovium/sonic-platform-modules-delta/debian/control @@ -7,7 +7,7 @@ Standards-Version: 3.9.3 Package: platform-modules-et-c032if Architecture: amd64 -Depends: linux-image-4.19.0-9-2-amd64-unsigned +Depends: linux-image-4.19.0-12-2-amd64-unsigned Description: kernel modules for platform devices such as fan, led, sfp diff --git a/platform/marvell-arm64/docker-ptf-mrvl.mk b/platform/marvell-arm64/docker-ptf-mrvl.mk deleted file mode 100644 index 72c860aec86..00000000000 --- a/platform/marvell-arm64/docker-ptf-mrvl.mk +++ /dev/null @@ -1,8 +0,0 @@ -# docker image for docker-ptf-mrvl - -DOCKER_PTF_MRVL = docker-ptf-mrvl.gz -$(DOCKER_PTF_MRVL)_PATH = $(DOCKERS_PATH)/docker-ptf-saithrift -$(DOCKER_PTF_MRVL)_DEPENDS += $(PYTHON_SAITHRIFT) -$(DOCKER_PTF_MRVL)_LOAD_DOCKERS += $(DOCKER_PTF) -SONIC_DOCKER_IMAGES += $(DOCKER_PTF_MRVL) -SONIC_STRETCH_DOCKERS += $(DOCKER_PTF_MRVL) diff --git a/platform/marvell-arm64/docker-syncd-mrvl/supervisord.conf b/platform/marvell-arm64/docker-syncd-mrvl/supervisord.conf index 2cf6814ddaa..10f406129d9 100644 --- a/platform/marvell-arm64/docker-syncd-mrvl/supervisord.conf +++ b/platform/marvell-arm64/docker-syncd-mrvl/supervisord.conf @@ -14,7 +14,7 @@ buffer_size=25 [eventlistener:supervisor-proc-exit-listener] command=python2 /usr/bin/supervisor-proc-exit-listener --container-name syncd -events=PROCESS_STATE_EXITED +events=PROCESS_STATE_EXITED,PROCESS_STATE_RUNNING autostart=true autorestart=unexpected diff --git a/platform/marvell-arm64/rules.mk b/platform/marvell-arm64/rules.mk index c3d7092ebb8..f8e4c12a49f 100644 --- a/platform/marvell-arm64/rules.mk +++ b/platform/marvell-arm64/rules.mk @@ -4,7 +4,6 @@ include $(PLATFORM_PATH)/docker-syncd-mrvl.mk include $(PLATFORM_PATH)/docker-syncd-mrvl-rpc.mk include $(PLATFORM_PATH)/docker-saiserver-mrvl.mk include $(PLATFORM_PATH)/libsaithrift-dev.mk -include $(PLATFORM_PATH)/docker-ptf-mrvl.mk include $(PLATFORM_PATH)/one-image.mk include $(PLATFORM_PATH)/linux-kernel-arm64.mk INCLUDE_SYSTEM_TELEMETRY = "" diff --git a/platform/marvell-armhf/docker-ptf-mrvl.mk b/platform/marvell-armhf/docker-ptf-mrvl.mk deleted file mode 100644 index 72c860aec86..00000000000 --- a/platform/marvell-armhf/docker-ptf-mrvl.mk +++ /dev/null @@ -1,8 +0,0 @@ -# docker image for docker-ptf-mrvl - -DOCKER_PTF_MRVL = docker-ptf-mrvl.gz -$(DOCKER_PTF_MRVL)_PATH = $(DOCKERS_PATH)/docker-ptf-saithrift -$(DOCKER_PTF_MRVL)_DEPENDS += $(PYTHON_SAITHRIFT) -$(DOCKER_PTF_MRVL)_LOAD_DOCKERS += $(DOCKER_PTF) -SONIC_DOCKER_IMAGES += $(DOCKER_PTF_MRVL) -SONIC_STRETCH_DOCKERS += $(DOCKER_PTF_MRVL) diff --git a/platform/marvell-armhf/docker-syncd-mrvl/supervisord.conf b/platform/marvell-armhf/docker-syncd-mrvl/supervisord.conf index c099bbccbf0..e633b4fe115 100644 --- a/platform/marvell-armhf/docker-syncd-mrvl/supervisord.conf +++ b/platform/marvell-armhf/docker-syncd-mrvl/supervisord.conf @@ -14,7 +14,7 @@ buffer_size=25 [eventlistener:supervisor-proc-exit-listener] command=python2 /usr/bin/supervisor-proc-exit-listener --container-name syncd -events=PROCESS_STATE_EXITED +events=PROCESS_STATE_EXITED,PROCESS_STATE_RUNNING autostart=true autorestart=unexpected diff --git a/platform/marvell-armhf/platform.conf b/platform/marvell-armhf/platform.conf index 7fc7af8519b..78f64b6fbe1 100644 --- a/platform/marvell-armhf/platform.conf +++ b/platform/marvell-armhf/platform.conf @@ -10,8 +10,8 @@ fdt_addr=0x1000000 initrd_addr=0x2000000 VAR_LOG=512 -kernel_fname="/boot/vmlinuz-4.19.0-9-2-armmp" -initrd_fname="/boot/initrd.img-4.19.0-9-2-armmp" +kernel_fname="/boot/vmlinuz-4.19.0-12-2-armmp" +initrd_fname="/boot/initrd.img-4.19.0-12-2-armmp" fdt_fname="/boot/armada-385-ET6448M_4G_Nand.dtb" if [ "$install_env" = "onie" ]; then diff --git a/platform/marvell-armhf/rules.mk b/platform/marvell-armhf/rules.mk index 27d3167edd0..58b9654956f 100644 --- a/platform/marvell-armhf/rules.mk +++ b/platform/marvell-armhf/rules.mk @@ -4,7 +4,6 @@ include $(PLATFORM_PATH)/docker-syncd-mrvl.mk include $(PLATFORM_PATH)/docker-syncd-mrvl-rpc.mk include $(PLATFORM_PATH)/docker-saiserver-mrvl.mk include $(PLATFORM_PATH)/libsaithrift-dev.mk -include $(PLATFORM_PATH)/docker-ptf-mrvl.mk include $(PLATFORM_PATH)/one-image.mk include $(PLATFORM_PATH)/linux-kernel-armhf.mk include $(PLATFORM_PATH)/platform-et6448m.mk diff --git a/platform/marvell/docker-syncd-mrvl/supervisord.conf b/platform/marvell/docker-syncd-mrvl/supervisord.conf index 85442933cf8..94be9dd268f 100644 --- a/platform/marvell/docker-syncd-mrvl/supervisord.conf +++ b/platform/marvell/docker-syncd-mrvl/supervisord.conf @@ -14,7 +14,7 @@ buffer_size=25 [eventlistener:supervisor-proc-exit-listener] command=python2 /usr/bin/supervisor-proc-exit-listener --container-name syncd -events=PROCESS_STATE_EXITED +events=PROCESS_STATE_EXITED,PROCESS_STATE_RUNNING autostart=true autorestart=unexpected diff --git a/platform/mellanox/docker-ptf-mlnx.dep b/platform/mellanox/docker-ptf-mlnx.dep deleted file mode 100644 index 652fe0001c7..00000000000 --- a/platform/mellanox/docker-ptf-mlnx.dep +++ /dev/null @@ -1,10 +0,0 @@ -# DPKG FRK - -DPATH := $($(DOCKER_PTF_MLNX)_PATH) -DEP_FILES := $(SONIC_COMMON_FILES_LIST) $(PLATFORM_PATH)/docker-ptf-mlnx.mk $(PLATFORM_PATH)/docker-ptf-mlnx.dep -DEP_FILES += $(SONIC_COMMON_BASE_FILES_LIST) -DEP_FILES += $(shell git ls-files -- $(DPATH)) - -$(DOCKER_PTF_MLNX)_CACHE_MODE := GIT_CONTENT_SHA -$(DOCKER_PTF_MLNX)_DEP_FLAGS := $(SONIC_COMMON_FLAGS_LIST) -$(DOCKER_PTF_MLNX)_DEP_FILES := $(DEP_FILES) diff --git a/platform/mellanox/docker-ptf-mlnx.mk b/platform/mellanox/docker-ptf-mlnx.mk deleted file mode 100644 index eaaa54897d8..00000000000 --- a/platform/mellanox/docker-ptf-mlnx.mk +++ /dev/null @@ -1,8 +0,0 @@ -# docker image for docker-ptf-mlnx - -DOCKER_PTF_MLNX = docker-ptf-mlnx.gz -$(DOCKER_PTF_MLNX)_PATH = $(DOCKERS_PATH)/docker-ptf-saithrift -$(DOCKER_PTF_MLNX)_DEPENDS += $(PYTHON_SAITHRIFT) -$(DOCKER_PTF_MLNX)_LOAD_DOCKERS += $(DOCKER_PTF) -SONIC_DOCKER_IMAGES += $(DOCKER_PTF_MLNX) -SONIC_STRETCH_DOCKERS += $(DOCKER_PTF_MLNX) diff --git a/platform/mellanox/docker-syncd-mlnx-rpc/Dockerfile.j2 b/platform/mellanox/docker-syncd-mlnx-rpc/Dockerfile.j2 index e35c6582d2d..b9aaa78118e 100644 --- a/platform/mellanox/docker-syncd-mlnx-rpc/Dockerfile.j2 +++ b/platform/mellanox/docker-syncd-mlnx-rpc/Dockerfile.j2 @@ -29,6 +29,7 @@ RUN apt-get update \ && apt-get -y install \ net-tools \ python-pip \ + python-setuptools \ build-essential \ libssl-dev \ libffi-dev \ @@ -45,9 +46,10 @@ RUN apt-get update \ && cd .. \ && rm -fr nanomsg-1.0.0 \ && rm -f 1.0.0.tar.gz \ - && pip install cffi==1.7.0 \ - && pip install --upgrade cffi==1.7.0 \ - && pip install nnpy \ + && pip2 install cffi==1.7.0 \ + && pip2 install --upgrade cffi==1.7.0 \ + && pip2 install wheel \ + && pip2 install nnpy \ && mkdir -p /opt \ && cd /opt \ && wget https://raw.githubusercontent.com/p4lang/ptf/master/ptf_nn/ptf_nn_agent.py \ diff --git a/platform/mellanox/docker-syncd-mlnx.dep b/platform/mellanox/docker-syncd-mlnx.dep index b8bdfdf625b..659b09cec8f 100644 --- a/platform/mellanox/docker-syncd-mlnx.dep +++ b/platform/mellanox/docker-syncd-mlnx.dep @@ -1,7 +1,7 @@ # DPKG FRK DPATH := $($(DOCKER_SYNCD_BASE)_PATH) -DEP_FILES := $(SONIC_COMMON_FILES_LIST) $(PLATFORM_PATH)/docker-syncd-mlnx.mk $(PLATFORM_PATH)/docker-syncd-mlnx.dep +DEP_FILES := $(SONIC_COMMON_FILES_LIST) $(PLATFORM_PATH)/docker-syncd-mlnx.mk $(PLATFORM_PATH)/docker-syncd-mlnx.dep platform/mellanox/mlnx-sai.mk DEP_FILES += $(SONIC_COMMON_BASE_FILES_LIST) DEP_FILES += $(shell git ls-files -- $(DPATH)) diff --git a/platform/mellanox/docker-syncd-mlnx/supervisord.conf b/platform/mellanox/docker-syncd-mlnx/supervisord.conf index 9311a255b0c..8491d762bf5 100644 --- a/platform/mellanox/docker-syncd-mlnx/supervisord.conf +++ b/platform/mellanox/docker-syncd-mlnx/supervisord.conf @@ -14,7 +14,7 @@ buffer_size=25 [eventlistener:supervisor-proc-exit-listener] command=/usr/bin/supervisor-proc-exit-listener --container-name syncd -events=PROCESS_STATE_EXITED +events=PROCESS_STATE_EXITED,PROCESS_STATE_RUNNING autostart=true autorestart=unexpected diff --git a/platform/mellanox/fw.mk b/platform/mellanox/fw.mk index 5c9a7442b98..094a038c31b 100644 --- a/platform/mellanox/fw.mk +++ b/platform/mellanox/fw.mk @@ -11,17 +11,17 @@ else FW_FROM_URL = n endif -MLNX_SPC_FW_VERSION = 13.2008.2208 +MLNX_SPC_FW_VERSION = 13.2008.2308 MLNX_SPC_FW_FILE = fw-SPC-rel-$(subst .,_,$(MLNX_SPC_FW_VERSION))-EVB.mfa $(MLNX_SPC_FW_FILE)_PATH = $(MLNX_FW_BASE_PATH) $(MLNX_SPC_FW_FILE)_URL = $(MLNX_FW_BASE_URL)/$(MLNX_SPC_FW_FILE) -MLNX_SPC2_FW_VERSION = 29.2008.2208 +MLNX_SPC2_FW_VERSION = 29.2008.2308 MLNX_SPC2_FW_FILE = fw-SPC2-rel-$(subst .,_,$(MLNX_SPC2_FW_VERSION))-EVB.mfa $(MLNX_SPC2_FW_FILE)_PATH = $(MLNX_FW_BASE_PATH) $(MLNX_SPC2_FW_FILE)_URL = $(MLNX_FW_BASE_URL)/$(MLNX_SPC2_FW_FILE) -MLNX_SPC3_FW_VERSION = 30.2008.2208 +MLNX_SPC3_FW_VERSION = 30.2008.2308 MLNX_SPC3_FW_FILE = fw-SPC3-rel-$(subst .,_,$(MLNX_SPC3_FW_VERSION))-EVB.mfa $(MLNX_SPC3_FW_FILE)_PATH = $(MLNX_FW_BASE_PATH) $(MLNX_SPC3_FW_FILE)_URL = $(MLNX_FW_BASE_URL)/$(MLNX_SPC3_FW_FILE) diff --git a/platform/mellanox/hw-management/0002-hw-mgmt-events-Add-support-for-SDK-OFFLINE-event-for.patch b/platform/mellanox/hw-management/0002-hw-mgmt-events-Add-support-for-SDK-OFFLINE-event-for.patch new file mode 100644 index 00000000000..6c58f7299c2 --- /dev/null +++ b/platform/mellanox/hw-management/0002-hw-mgmt-events-Add-support-for-SDK-OFFLINE-event-for.patch @@ -0,0 +1,30 @@ +From 3e511778248403968e0a02857b7003f352669ba3 Mon Sep 17 00:00:00 2001 +From: Vadim Pasternak +Date: Wed, 13 Jan 2021 13:19:17 +0200 +Subject: [PATCH] hw-mgmt: events: Add support for SDK OFFLINE event for + handling flow with in service firmware upgrade + +In order to prevent "mlxsw_minimal" driver access to ASIC during in +service firmware upgrade flow, SDK will raise "OFFLINE" 'udev' event +at early beginning of such flow. When this event is received, +hw-managemnet will remove "mlxsw_minimal" driver. +There is no need to implement opposite "ONLINE" event, since this flow +is ended up with "kexec". + +Signed-off-by: Vadim Pasternak +--- + usr/lib/udev/rules.d/50-hw-management-events.rules | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/usr/lib/udev/rules.d/50-hw-management-events.rules b/usr/lib/udev/rules.d/50-hw-management-events.rules +index cf4219e..33ea1bc 100644 +--- a/usr/lib/udev/rules.d/50-hw-management-events.rules ++++ b/usr/lib/udev/rules.d/50-hw-management-events.rules +@@ -269,3 +269,4 @@ SUBSYSTEM=="i2c", DEVPATH=="/devices/platform/mlxplat/i2c_mlxcpld*/i2c-*/i2c-*/* + # SDK + SUBSYSTEM=="pci", DRIVERS=="sx_core", ACTION=="add", RUN+="/usr/bin/hw-management-thermal-events.sh add sxcore add" + SUBSYSTEM=="pci", DRIVERS=="sx_core", ACTION=="remove", RUN+="/usr/bin/hw-management-thermal-events.sh rm sxcore remove" ++SUBSYSTEM=="pci", DRIVERS=="sx_core", ACTION=="offline", RUN+="/usr/bin/hw-management-thermal-events.sh rm sxcore remove" +-- +1.9.1 + diff --git a/platform/mellanox/mlnx-fw-upgrade.j2 b/platform/mellanox/mlnx-fw-upgrade.j2 index 69f3d621cc4..245ce75d5f1 100755 --- a/platform/mellanox/mlnx-fw-upgrade.j2 +++ b/platform/mellanox/mlnx-fw-upgrade.j2 @@ -29,6 +29,7 @@ declare -r SPC1_ASIC="spc1" declare -r SPC2_ASIC="spc2" declare -r SPC3_ASIC="spc3" declare -r UNKN_ASIC="unknown" +declare -r UNKN_MST="unknown" declare -rA FW_FILE_MAP=( \ [$SPC1_ASIC]="/etc/mlnx/fw-SPC.mfa" \ @@ -152,6 +153,18 @@ function GetAsicType() { exit "${EXIT_FAILURE}" } +function GetMstDevice() { + local _MST_DEVICE="$(ls /dev/mst/*_pci_cr0 2>&1)" + + if [[ ! -c "${_MST_DEVICE}" ]]; then + echo "${UNKN_MST}" + else + echo "${_MST_DEVICE}" + fi + + exit "${EXIT_SUCCESS}" +} + function RunCmd() { local ERROR_CODE="${EXIT_SUCCESS}" @@ -207,7 +220,13 @@ function UpgradeFW() { ExitSuccess "firmware is up to date" else LogNotice "firmware upgrade is required. Installing compatible version..." - RunCmd "${BURN_CMD} -i ${_FW_FILE}" + local -r _MST_DEVICE="$(GetMstDevice)" + if [[ "${_MST_DEVICE}" = "${UNKN_MST}" ]]; then + LogWarning "could not find fastest mst device, using default device" + RunCmd "${BURN_CMD} -i ${_FW_FILE}" + else + RunCmd "${BURN_CMD} -d ${_MST_DEVICE} -i ${_FW_FILE}" + fi fi } diff --git a/platform/mellanox/mlnx-platform-api/sonic_platform/sfp.py b/platform/mellanox/mlnx-platform-api/sonic_platform/sfp.py index 4b397b3f3ff..75ae9c8907e 100644 --- a/platform/mellanox/mlnx-platform-api/sonic_platform/sfp.py +++ b/platform/mellanox/mlnx-platform-api/sonic_platform/sfp.py @@ -440,7 +440,7 @@ def _dom_capability_detect(self): if qsfp_dom_capability_raw is not None: qsfp_version_compliance_raw = self._read_eeprom_specific_bytes(QSFP_VERSION_COMPLIANCE_OFFSET, QSFP_VERSION_COMPLIANCE_WIDTH) qsfp_version_compliance = int(qsfp_version_compliance_raw[0], 16) - dom_capability = sfpi_obj.parse_qsfp_dom_capability(qsfp_dom_capability_raw, 0) + dom_capability = sfpi_obj.parse_dom_capability(qsfp_dom_capability_raw, 0) if qsfp_version_compliance >= 0x08: self.dom_temp_supported = dom_capability['data']['Temp_support']['value'] == 'On' self.dom_volt_supported = dom_capability['data']['Voltage_support']['value'] == 'On' diff --git a/platform/mellanox/mlnx-platform-api/sonic_platform/thermal_conditions.py b/platform/mellanox/mlnx-platform-api/sonic_platform/thermal_conditions.py index 94e18a2e00b..a682061d12a 100644 --- a/platform/mellanox/mlnx-platform-api/sonic_platform/thermal_conditions.py +++ b/platform/mellanox/mlnx-platform-api/sonic_platform/thermal_conditions.py @@ -85,7 +85,7 @@ def is_match(self, thermal_info_dict): trust_state = Thermal.check_module_temperature_trustable() temperature = Thermal.get_min_amb_temperature() - temperature = temperature / 1000 + temperature = int(temperature / 1000) change_cooling_level = False if trust_state != MinCoolingLevelChangeCondition.trust_state: diff --git a/platform/mellanox/mlnx-platform-api/tests/test_thermal_policy.py b/platform/mellanox/mlnx-platform-api/tests/test_thermal_policy.py index 87fac359b2f..4d69a39c58a 100644 --- a/platform/mellanox/mlnx-platform-api/tests/test_thermal_policy.py +++ b/platform/mellanox/mlnx-platform-api/tests/test_thermal_policy.py @@ -482,7 +482,7 @@ def test_dynamic_minimum_policy(thermal_manager): condition = policy.conditions[MinCoolingLevelChangeCondition] action = policy.actions[ChangeMinCoolingLevelAction] Thermal.check_module_temperature_trustable = MagicMock(return_value='trust') - Thermal.get_min_amb_temperature = MagicMock(return_value=35000) + Thermal.get_min_amb_temperature = MagicMock(return_value=35001) assert condition.is_match(None) assert MinCoolingLevelChangeCondition.trust_state == 'trust' assert MinCoolingLevelChangeCondition.temperature == 35 @@ -492,7 +492,7 @@ def test_dynamic_minimum_policy(thermal_manager): assert condition.is_match(None) assert MinCoolingLevelChangeCondition.trust_state == 'untrust' - Thermal.get_min_amb_temperature = MagicMock(return_value=25000) + Thermal.get_min_amb_temperature = MagicMock(return_value=25999) assert condition.is_match(None) assert MinCoolingLevelChangeCondition.temperature == 25 diff --git a/platform/mellanox/mlnx-sai.mk b/platform/mellanox/mlnx-sai.mk index 0c1795cf41a..7f16a72cc07 100644 --- a/platform/mellanox/mlnx-sai.mk +++ b/platform/mellanox/mlnx-sai.mk @@ -1,6 +1,6 @@ # Mellanox SAI -MLNX_SAI_VERSION = SAIRel1.18.0.2-master +MLNX_SAI_VERSION = SAIRel1.18.1.0 export MLNX_SAI_VERSION diff --git a/platform/mellanox/mlnx-sai/SAI-Implementation b/platform/mellanox/mlnx-sai/SAI-Implementation index ad1e9c7279e..abdc7c069ea 160000 --- a/platform/mellanox/mlnx-sai/SAI-Implementation +++ b/platform/mellanox/mlnx-sai/SAI-Implementation @@ -1 +1 @@ -Subproject commit ad1e9c7279e544b93fef9a40fb41df375338b55e +Subproject commit abdc7c069ea8714af53cd4337f05bd493f133668 diff --git a/platform/mellanox/rules.dep b/platform/mellanox/rules.dep index 8986eb2e080..40985759215 100644 --- a/platform/mellanox/rules.dep +++ b/platform/mellanox/rules.dep @@ -11,7 +11,6 @@ include $(PLATFORM_PATH)/docker-syncd-mlnx-rpc.dep include $(PLATFORM_PATH)/docker-saiserver-mlnx.dep include $(PLATFORM_PATH)/one-image.dep include $(PLATFORM_PATH)/libsaithrift-dev.dep -include $(PLATFORM_PATH)/docker-ptf-mlnx.dep include $(PLATFORM_PATH)/mlnx-ffb.dep include $(PLATFORM_PATH)/issu-version.dep include $(PLATFORM_PATH)/mlnx-onie-fw-update.dep diff --git a/platform/mellanox/rules.mk b/platform/mellanox/rules.mk index 1e2ca78a195..179e20f3fff 100644 --- a/platform/mellanox/rules.mk +++ b/platform/mellanox/rules.mk @@ -9,7 +9,6 @@ include $(PLATFORM_PATH)/docker-syncd-mlnx-rpc.mk include $(PLATFORM_PATH)/docker-saiserver-mlnx.mk include $(PLATFORM_PATH)/one-image.mk include $(PLATFORM_PATH)/libsaithrift-dev.mk -include $(PLATFORM_PATH)/docker-ptf-mlnx.mk include $(PLATFORM_PATH)/mlnx-ffb.mk include $(PLATFORM_PATH)/issu-version.mk include $(PLATFORM_PATH)/mlnx-onie-fw-update.mk diff --git a/platform/mellanox/sdk-src/sx-kernel/Switch-SDK-drivers b/platform/mellanox/sdk-src/sx-kernel/Switch-SDK-drivers index f2d3ccc99c0..68f452e52bb 160000 --- a/platform/mellanox/sdk-src/sx-kernel/Switch-SDK-drivers +++ b/platform/mellanox/sdk-src/sx-kernel/Switch-SDK-drivers @@ -1 +1 @@ -Subproject commit f2d3ccc99c03a54a874278d33ae77c38586eb70b +Subproject commit 68f452e52bbbe9a9f68926867dd9ffcee41e15a9 diff --git a/platform/mellanox/sdk.mk b/platform/mellanox/sdk.mk index e020d1a575c..7ae3289f249 100644 --- a/platform/mellanox/sdk.mk +++ b/platform/mellanox/sdk.mk @@ -1,6 +1,6 @@ MLNX_SDK_BASE_PATH = $(PLATFORM_PATH)/sdk-src/sx-kernel/Switch-SDK-drivers/bin/ MLNX_SDK_PKG_BASE_PATH = $(MLNX_SDK_BASE_PATH)/$(BLDENV)/ -MLNX_SDK_VERSION = 4.4.2208 +MLNX_SDK_VERSION = 4.4.2308 MLNX_SDK_ISSU_VERSION = 101 MLNX_SDK_DEB_VERSION = $(subst -,.,$(subst _,.,$(MLNX_SDK_VERSION))) diff --git a/platform/nephos/docker-ptf-nephos.mk b/platform/nephos/docker-ptf-nephos.mk deleted file mode 100644 index 15855bc89a1..00000000000 --- a/platform/nephos/docker-ptf-nephos.mk +++ /dev/null @@ -1,8 +0,0 @@ -# docker image for docker-ptf-nephos - -DOCKER_PTF_NEPHOS = docker-ptf-nephos.gz -$(DOCKER_PTF_NEPHOS)_PATH = $(DOCKERS_PATH)/docker-ptf-saithrift -$(DOCKER_PTF_NEPHOS)_DEPENDS += $(PYTHON_SAITHRIFT_NEPHOS) -$(DOCKER_PTF_NEPHOS)_LOAD_DOCKERS += $(DOCKER_PTF) -SONIC_DOCKER_IMAGES += $(DOCKER_PTF_NEPHOS) -SONIC_STRETCH_DOCKERS += $(DOCKER_PTF_NEPHOS) diff --git a/platform/nephos/docker-syncd-nephos/supervisord.conf b/platform/nephos/docker-syncd-nephos/supervisord.conf index a05bf7bfec7..955021ad2d5 100644 --- a/platform/nephos/docker-syncd-nephos/supervisord.conf +++ b/platform/nephos/docker-syncd-nephos/supervisord.conf @@ -14,7 +14,7 @@ buffer_size=25 [eventlistener:supervisor-proc-exit-listener] command=python2 /usr/bin/supervisor-proc-exit-listener --container-name syncd -events=PROCESS_STATE_EXITED +events=PROCESS_STATE_EXITED,PROCESS_STATE_RUNNING autostart=true autorestart=unexpected diff --git a/platform/nephos/nephos-modules/debian/control b/platform/nephos/nephos-modules/debian/control index 78eb7af671f..1b485d808f3 100644 --- a/platform/nephos/nephos-modules/debian/control +++ b/platform/nephos/nephos-modules/debian/control @@ -7,6 +7,6 @@ Standards-Version: 3.9.3 Package: nephos-modules Architecture: amd64 -Depends: linux-image-4.19.0-9-2-amd64-unsigned +Depends: linux-image-4.19.0-12-2-amd64-unsigned Description: kernel modules for nephos asic diff --git a/platform/nephos/rules.mk b/platform/nephos/rules.mk index 8950c665dee..4ee2443e758 100644 --- a/platform/nephos/rules.mk +++ b/platform/nephos/rules.mk @@ -7,7 +7,6 @@ include $(PLATFORM_PATH)/docker-syncd-nephos.mk include $(PLATFORM_PATH)/docker-syncd-nephos-rpc.mk include $(PLATFORM_PATH)/one-image.mk include $(PLATFORM_PATH)/libsaithrift-dev.mk -include $(PLATFORM_PATH)/docker-ptf-nephos.mk NPX_DIAG = npx_diag $(NPX_DIAG)_URL = "https://github.com/NephosInc/SONiC/raw/master/sdk/npx_diag" diff --git a/platform/nephos/sonic-platform-modules-accton/debian/control b/platform/nephos/sonic-platform-modules-accton/debian/control index e2b67b03b9e..3020b86408d 100755 --- a/platform/nephos/sonic-platform-modules-accton/debian/control +++ b/platform/nephos/sonic-platform-modules-accton/debian/control @@ -7,5 +7,5 @@ Standards-Version: 3.9.3 Package: sonic-platform-accton-as7116-54x Architecture: amd64 -Depends: linux-image-4.19.0-9-2-amd64-unsigned +Depends: linux-image-4.19.0-12-2-amd64-unsigned Description: kernel modules for platform devices such as fan, led, sfp diff --git a/platform/nephos/sonic-platform-modules-cig/debian/control b/platform/nephos/sonic-platform-modules-cig/debian/control index 870edcf1a23..fc0c6736ffa 100644 --- a/platform/nephos/sonic-platform-modules-cig/debian/control +++ b/platform/nephos/sonic-platform-modules-cig/debian/control @@ -7,15 +7,15 @@ Standards-Version: 3.9.3 Package: sonic-platform-cig-cs6436-56p Architecture: amd64 -Depends: linux-image-4.19.0-9-2-amd64-unsigned +Depends: linux-image-4.19.0-12-2-amd64-unsigned Description: kernel modules for platform devices such as fan, led, sfp Package: sonic-platform-cig-cs6436-54p Architecture: amd64 -Depends: linux-image-4.19.0-9-2-amd64-unsigned +Depends: linux-image-4.19.0-12-2-amd64-unsigned Description: kernel modules for platform devices such as fan, led, sfp Package: sonic-platform-cig-cs5435-54p Architecture: amd64 -Depends: linux-image-4.19.0-9-2-amd64-unsigned +Depends: linux-image-4.19.0-12-2-amd64-unsigned Description: kernel modules for platform devices such as fan, led, sfp diff --git a/platform/nephos/sonic-platform-modules-pegatron/debian/control b/platform/nephos/sonic-platform-modules-pegatron/debian/control index fc3054a4c87..8fc19980fc1 100755 --- a/platform/nephos/sonic-platform-modules-pegatron/debian/control +++ b/platform/nephos/sonic-platform-modules-pegatron/debian/control @@ -7,6 +7,6 @@ Standards-Version: 3.9.3 Package: sonic-platform-pegatron-porsche Architecture: amd64 -Depends: linux-image-4.19.0-9-2-amd64-unsigned +Depends: linux-image-4.19.0-12-2-amd64-unsigned Description: kernel modules for platform devices such as fan, led, sfp diff --git a/platform/pddf/platform-api-pddf-base/sonic_platform_pddf_base/pddf_sfp.py b/platform/pddf/platform-api-pddf-base/sonic_platform_pddf_base/pddf_sfp.py index 3bd3a0ac2ca..dc37bba6e88 100755 --- a/platform/pddf/platform-api-pddf-base/sonic_platform_pddf_base/pddf_sfp.py +++ b/platform/pddf/platform-api-pddf-base/sonic_platform_pddf_base/pddf_sfp.py @@ -418,7 +418,7 @@ def get_transceiver_bulk_status(self): qsfp_dom_capability_raw = self.__read_eeprom_specific_bytes( (offset_xcvr + XCVR_DOM_CAPABILITY_OFFSET), XCVR_DOM_CAPABILITY_WIDTH) if qsfp_dom_capability_raw is not None: - qspf_dom_capability_data = sfpi_obj.parse_qsfp_dom_capability( + qspf_dom_capability_data = sfpi_obj.parse_dom_capability( qsfp_dom_capability_raw, 0) else: return None diff --git a/platform/vs/docker-gbsyncd-vs/Dockerfile.j2 b/platform/vs/docker-gbsyncd-vs/Dockerfile.j2 index d740dca663c..ae7e1c99b7c 100644 --- a/platform/vs/docker-gbsyncd-vs/Dockerfile.j2 +++ b/platform/vs/docker-gbsyncd-vs/Dockerfile.j2 @@ -8,7 +8,7 @@ ENV DEBIAN_FRONTEND=noninteractive RUN apt-get update -RUN apt-get install -f -y iproute2=4.20.0-2 libcap2-bin=1:2.25-2 +RUN apt-get install -f -y iproute2 libcap2-bin COPY \ {% for deb in docker_gbsyncd_vs_debs.split(' ') -%} diff --git a/platform/vs/docker-gbsyncd-vs/supervisord.conf b/platform/vs/docker-gbsyncd-vs/supervisord.conf index 3583ef6b5a8..52267c8fa58 100644 --- a/platform/vs/docker-gbsyncd-vs/supervisord.conf +++ b/platform/vs/docker-gbsyncd-vs/supervisord.conf @@ -13,7 +13,7 @@ events=PROCESS_STATE [eventlistener:supervisor-proc-exit-listener] command=/usr/bin/supervisor-proc-exit-listener --container-name gbsyncd -events=PROCESS_STATE_EXITED +events=PROCESS_STATE_EXITED,PROCESS_STATE_RUNNING autostart=true autorestart=unexpected diff --git a/rules/docker-ptf.dep b/platform/vs/docker-ptf.dep similarity index 62% rename from rules/docker-ptf.dep rename to platform/vs/docker-ptf.dep index d62019e9b38..8cd9f7b7a27 100644 --- a/rules/docker-ptf.dep +++ b/platform/vs/docker-ptf.dep @@ -1,10 +1,10 @@ DPATH := $($(DOCKER_PTF)_PATH) -DEP_FILES := $(SONIC_COMMON_FILES_LIST) rules/docker-ptf.mk rules/docker-ptf.dep +DEP_FILES := $(SONIC_COMMON_FILES_LIST) platform/vs/docker-ptf.mk platform/vs/docker-ptf.dep DEP_FILES += $(SONIC_COMMON_BASE_FILES_LIST) DEP_FILES += $(shell git ls-files $(DPATH)) -$(DOCKER_PTF)_CACHE_MODE := GIT_CONTENT_SHA +$(DOCKER_PTF)_CACHE_MODE := GIT_CONTENT_SHA $(DOCKER_PTF)_DEP_FLAGS := $(SONIC_COMMON_FLAGS_LIST) $(DOCKER_PTF)_DEP_FILES := $(DEP_FILES) diff --git a/rules/docker-ptf.mk b/platform/vs/docker-ptf.mk similarity index 57% rename from rules/docker-ptf.mk rename to platform/vs/docker-ptf.mk index b2d45068334..4fde844fe24 100644 --- a/rules/docker-ptf.mk +++ b/platform/vs/docker-ptf.mk @@ -1,7 +1,7 @@ -# docker image for ptf +# docker image for docker-ptf DOCKER_PTF = docker-ptf.gz $(DOCKER_PTF)_PATH = $(DOCKERS_PATH)/docker-ptf -$(DOCKER_PTF)_DEPENDS += $(LIBTHRIFT) $(PYTHON_THRIFT) $(PTF) +$(DOCKER_PTF)_DEPENDS += $(LIBTHRIFT) $(PYTHON_THRIFT) $(PTF) $(PYTHON_SAITHRIFT) SONIC_DOCKER_IMAGES += $(DOCKER_PTF) SONIC_STRETCH_DOCKERS += $(DOCKER_PTF) diff --git a/platform/vs/docker-sonic-vs.mk b/platform/vs/docker-sonic-vs.mk index 7b82fce71ee..c48c8f12c70 100644 --- a/platform/vs/docker-sonic-vs.mk +++ b/platform/vs/docker-sonic-vs.mk @@ -18,10 +18,9 @@ $(DOCKER_SONIC_VS)_DEPENDS += $(SWSS) \ # swsssdk is a dependency of sonic-py-common # TODO: sonic-py-common should depend on swsscommon instead -$(DOCKER_SONIC_VS)_PYTHON_WHEELS += $(SWSSSDK_PY2) \ - $(SWSSSDK_PY3) \ - $(SONIC_PY_COMMON_PY2) \ +$(DOCKER_SONIC_VS)_PYTHON_WHEELS += $(SWSSSDK_PY3) \ $(SONIC_PY_COMMON_PY3) \ + $(SONIC_PLATFORM_COMMON_PY3) \ $(SONIC_YANG_MODELS_PY3) \ $(SONIC_YANG_MGMT_PY3) \ $(SONIC_UTILITIES_PY3) \ diff --git a/platform/vs/docker-sonic-vs/Dockerfile.j2 b/platform/vs/docker-sonic-vs/Dockerfile.j2 index 837e8fc3cb6..4313d84a237 100644 --- a/platform/vs/docker-sonic-vs/Dockerfile.j2 +++ b/platform/vs/docker-sonic-vs/Dockerfile.j2 @@ -53,7 +53,20 @@ RUN apt-get install -y net-tools \ libssl-dev \ swig \ # For using Python m2crypto package - openssl + openssl \ + # For installing dependent Python packages of sonic-host-services + # (these can be uninstalled after installation) + libcairo2-dev \ + libdbus-1-dev \ + libgirepository1.0-dev \ + libsystemd-dev \ + pkg-config \ + # For installing dependent Python packages of sonic-host-services + # these packages are needed at runtime + gir1.2-glib-2.0 \ + libdbus-1-3 \ + libgirepository-1.0-1 \ + libsystemd0 # Install redis-server {% if CONFIGURED_ARCH == "armhf" %} @@ -129,6 +142,7 @@ RUN pip{% if 'py3' in whl %}3{% else %}2{% endif %} install python-wheels/{{ whl # Clean up RUN apt-get purge -y build-essential libssl-dev swig RUN apt-get purge -y python-dev python3-dev +RUN apt-get purge -y libcairo2-dev libdbus-1-dev libgirepository1.0-dev libsystemd-dev pkg-config RUN apt-get clean -y RUN apt-get autoclean -y RUN apt-get autoremove -y diff --git a/platform/vs/docker-sonic-vs/start.sh b/platform/vs/docker-sonic-vs/start.sh index 7b246a49de1..7ee70efa081 100755 --- a/platform/vs/docker-sonic-vs/start.sh +++ b/platform/vs/docker-sonic-vs/start.sh @@ -31,6 +31,11 @@ if [[ -f /usr/share/sonic/virtual_chassis/default_config.json ]]; then CHASS_CFG="-j /usr/share/sonic/virtual_chassis/default_config.json" fi +# Note: libswsscommon requires a dabase_config file in /var/run/redis/sonic-db/ +# Prepare this file before any dependent application, such as sonic-cfggen +mkdir -p /var/run/redis/sonic-db +cp /etc/default/sonic-db/database_config.json /var/run/redis/sonic-db/ + SYSTEM_MAC_ADDRESS=$(ip link show eth0 | grep ether | awk '{print $2}') sonic-cfggen -a '{"DEVICE_METADATA":{"localhost": {"mac": "'$SYSTEM_MAC_ADDRESS'", "buffer_model": "traditional"}}}' $CHASS_CFG --print-data > /etc/sonic/init_cfg.json @@ -68,9 +73,6 @@ else echo "10.8.1.200 redis_chassis.server" >> /etc/hosts fi -mkdir -p /var/run/redis/sonic-db -cp /etc/default/sonic-db/database_config.json /var/run/redis/sonic-db/ - supervisorctl start redis-server start_chassis_db=`sonic-cfggen -v DEVICE_METADATA.localhost.start_chassis_db -y $chassisdb_cfg_file` diff --git a/platform/vs/docker-syncd-vs/Dockerfile.j2 b/platform/vs/docker-syncd-vs/Dockerfile.j2 index 1ef1245e14f..b3d7dcef490 100644 --- a/platform/vs/docker-syncd-vs/Dockerfile.j2 +++ b/platform/vs/docker-syncd-vs/Dockerfile.j2 @@ -8,7 +8,7 @@ ENV DEBIAN_FRONTEND=noninteractive RUN apt-get update -RUN apt-get install -f -y iproute2=4.20.0-2 libcap2-bin=1:2.25-2 +RUN apt-get install -f -y iproute2 libcap2-bin COPY \ {% for deb in docker_syncd_vs_debs.split(' ') -%} diff --git a/platform/vs/docker-syncd-vs/supervisord.conf b/platform/vs/docker-syncd-vs/supervisord.conf index 7416f23a45e..6a6d946632e 100644 --- a/platform/vs/docker-syncd-vs/supervisord.conf +++ b/platform/vs/docker-syncd-vs/supervisord.conf @@ -14,7 +14,7 @@ buffer_size=25 [eventlistener:supervisor-proc-exit-listener] command=/usr/bin/supervisor-proc-exit-listener --container-name syncd -events=PROCESS_STATE_EXITED +events=PROCESS_STATE_EXITED,PROCESS_STATE_RUNNING autostart=true autorestart=unexpected diff --git a/platform/vs/libsaithrift-dev.dep b/platform/vs/libsaithrift-dev.dep new file mode 100644 index 00000000000..be1d3f74b23 --- /dev/null +++ b/platform/vs/libsaithrift-dev.dep @@ -0,0 +1,13 @@ +#DPKG FRK +SPATH := $($(LIBSAITHRIFT_DEV)_SRC_PATH) +DEP_FILES := $(SONIC_COMMON_FILES_LIST) platform/broadcom/libsaithrift-dev.mk platform/broadcom/libsaithrift-dev.dep +DEP_FILES += $(SONIC_COMMON_BASE_FILES_LIST) +SMDEP_PATHS := $(SPATH) $(SPATH)/bm/behavioral-model $(SPATH)/test/ptf $(SPATH)/test/saithrift/ctypesgen +$(foreach path, $(SMDEP_PATHS), $(eval $(path) :=$(filter-out $(SMDEP_PATHS),$(addprefix $(path)/, $(shell cd $(path) && git ls-files | grep -Ev " " ))))) + +$(LIBSAITHRIFT_DEV)_CACHE_MODE := GIT_CONTENT_SHA +$(LIBSAITHRIFT_DEV)_DEP_FLAGS := $(SONIC_COMMON_FLAGS_LIST) +$(LIBSAITHRIFT_DEV)_DEP_FILES := $(DEP_FILES) +$(LIBSAITHRIFT_DEV)_SMDEP_FILES := $(foreach path, $(SMDEP_PATHS), $($(path))) +$(LIBSAITHRIFT_DEV)_SMDEP_PATHS := $(SMDEP_PATHS) + diff --git a/platform/vs/libsaithrift-dev.mk b/platform/vs/libsaithrift-dev.mk new file mode 100644 index 00000000000..ba8a63d539a --- /dev/null +++ b/platform/vs/libsaithrift-dev.mk @@ -0,0 +1,22 @@ +# libsaithrift-dev package + +SAI_VER = 0.9.4 + +LIBSAITHRIFT_DEV = libsaithrift-dev_$(SAI_VER)_$(CONFIGURED_ARCH).deb +$(LIBSAITHRIFT_DEV)_SRC_PATH = $(SRC_PATH)/sonic-sairedis/SAI +$(LIBSAITHRIFT_DEV)_DEPENDS += $(LIBTHRIFT) $(LIBTHRIFT_DEV) $(PYTHON_THRIFT) $(THRIFT_COMPILER) \ + $(LIBSAIVS) $(LIBSAIVS_DEV) $(LIBSAIMETADATA) $(LIBSAIMETADATA_DEV) +$(LIBSAITHRIFT_DEV)_RDEPENDS += $(LIBTHRIFT) $(LIBSAIVS) $(LIBSAIMETADATA) +$(LIBSAITHRIFT_DEV)_BUILD_ENV = platform=vs +SONIC_DPKG_DEBS += $(LIBSAITHRIFT_DEV) + +PYTHON_SAITHRIFT = python-saithrift_$(SAI_VER)_$(CONFIGURED_ARCH).deb +$(eval $(call add_extra_package,$(LIBSAITHRIFT_DEV),$(PYTHON_SAITHRIFT))) + +SAISERVER = saiserver_$(SAI_VER)_$(CONFIGURED_ARCH).deb +$(SAISERVER)_RDEPENDS += $(LIBTHRIFT) $(LIBSAIVS) +$(eval $(call add_extra_package,$(LIBSAITHRIFT_DEV),$(SAISERVER))) + +SAISERVER_DBG = saiserver-dbg_$(SAI_VER)_$(CONFIGURED_ARCH).deb +$(SAISERVER_DBG)_RDEPENDS += $(SAISERVER) +$(eval $(call add_extra_package,$(LIBSAITHRIFT_DEV),$(SAISERVER_DBG))) diff --git a/platform/vs/rules.dep b/platform/vs/rules.dep index 7a5346619e7..0d485e8004d 100644 --- a/platform/vs/rules.dep +++ b/platform/vs/rules.dep @@ -3,6 +3,8 @@ include $(PLATFORM_PATH)/sonic-version.dep include $(PLATFORM_PATH)/docker-sonic-vs.dep include $(PLATFORM_PATH)/docker-syncd-vs.dep include $(PLATFORM_PATH)/docker-gbsyncd-vs.dep +include $(PLATFORM_PATH)/docker-ptf.dep +include $(PLATFORM_PATH)/libsaithrift-dev.dep include $(PLATFORM_PATH)/one-image.dep include $(PLATFORM_PATH)/onie.dep include $(PLATFORM_PATH)/kvm-image.dep diff --git a/platform/vs/rules.mk b/platform/vs/rules.mk index 66e8bad5fe7..cbb52847edf 100644 --- a/platform/vs/rules.mk +++ b/platform/vs/rules.mk @@ -3,6 +3,8 @@ include $(PLATFORM_PATH)/sonic-version.mk include $(PLATFORM_PATH)/docker-sonic-vs.mk include $(PLATFORM_PATH)/docker-syncd-vs.mk include $(PLATFORM_PATH)/docker-gbsyncd-vs.mk +include $(PLATFORM_PATH)/docker-ptf.mk +include $(PLATFORM_PATH)/libsaithrift-dev.mk include $(PLATFORM_PATH)/one-image.mk include $(PLATFORM_PATH)/onie.mk include $(PLATFORM_PATH)/kvm-image.mk diff --git a/platform/vs/tests/bgp/files/default_route/bgpd.conf b/platform/vs/tests/bgp/files/default_route/bgpd.conf new file mode 100644 index 00000000000..bc0dffcdbb8 --- /dev/null +++ b/platform/vs/tests/bgp/files/default_route/bgpd.conf @@ -0,0 +1,4 @@ +router bgp 65501 + bgp router-id 1.1.1.1 + no bgp ebgp-requires-policy + neighbor 10.10.10.1 remote-as 65502 diff --git a/platform/vs/tests/bgp/files/default_route/default_route.conf b/platform/vs/tests/bgp/files/default_route/default_route.conf new file mode 100644 index 00000000000..9f9d3cf32f8 --- /dev/null +++ b/platform/vs/tests/bgp/files/default_route/default_route.conf @@ -0,0 +1,17 @@ +neighbor 10.10.10.0 { + router-id 1.2.3.4; + local-address 10.10.10.1; + local-as 65502; + peer-as 65501; + group-updates false; + + family { + ipv4 unicast; + } + + static { + route 0.0.0.0/0 { + next-hop 10.10.10.1; + } + } +} diff --git a/platform/vs/tests/bgp/test_default_route.py b/platform/vs/tests/bgp/test_default_route.py new file mode 100644 index 00000000000..2cc9021ba78 --- /dev/null +++ b/platform/vs/tests/bgp/test_default_route.py @@ -0,0 +1,48 @@ +from swsscommon import swsscommon +import os +import re +import time +import json +import pytest + +def test_DefaultRoute(dvs, testlog): + + dvs.copy_file("/etc/frr/", "bgp/files/default_route/bgpd.conf") + dvs.runcmd("supervisorctl start bgpd") + dvs.runcmd("ip addr add 10.10.10.0/31 dev Ethernet0") + dvs.runcmd("config interface startup Ethernet0") + dvs.runcmd("ip route del 0.0.0.0/0") + dvs.runcmd("vtysh -c \"confgure terminal\" -c \"ip route 0.0.0.0/0 via 172.17.0.1 200\"") + + dvs.servers[0].runcmd("ip addr add 10.10.10.1/31 dev eth0") + dvs.servers[0].runcmd("ifconfig eth0 up") + + time.sleep(5) + + print(dvs.runcmd("supervisorctl status")) + + p = dvs.servers[0].runcmd_async("exabgp -d bgp/files/default_route/default_route.conf") + + time.sleep(10) + + (exit_code, output) = dvs.runcmd(["redis-cli", "hgetall", "ROUTE_TABLE:0.0.0.0/0"]) + print(exit_code, output) + + # make sure 10.10.10.1 is the correct next hop for default route + assert "10.10.10.1" in output + + # insert default route for table default + dvs.runcmd("ip route add default via 172.17.0.1 table default") + + (exit_code, output) = dvs.runcmd(["redis-cli", "hgetall", "ROUTE_TABLE:0.0.0.0/0"]) + print(exit_code, output) + + time.sleep(10) + # make sure 10.10.10.1 is still the correct next hop for default route + assert "10.10.10.1" in output + + p.terminate() + p = p.wait() + + + diff --git a/rules/asyncsnmp-py3.mk b/rules/asyncsnmp-py3.mk index 990cc4512f8..2592eb004ee 100644 --- a/rules/asyncsnmp-py3.mk +++ b/rules/asyncsnmp-py3.mk @@ -5,5 +5,5 @@ $(ASYNCSNMP_PY3)_SRC_PATH = $(SRC_PATH)/sonic-snmpagent $(ASYNCSNMP_PY3)_PYTHON_VERSION = 3 # Depends on sonic-platform-common so it is possible to import sonic_psu $(ASYNCSNMP_PY3)_DEPENDS += $(SWSSSDK_PY3) $(SONIC_PLATFORM_COMMON_PY3) -$(ASYNCSNMP_PY3)_DEBS_DEPENDS += $(LIBSWSSCOMMON) $(PYTHON_SWSSCOMMON) $(PYTHON3_SWSSCOMMON) +$(ASYNCSNMP_PY3)_DEBS_DEPENDS += $(LIBSWSSCOMMON) $(PYTHON3_SWSSCOMMON) SONIC_PYTHON_WHEELS += $(ASYNCSNMP_PY3) diff --git a/rules/config b/rules/config index 39eb786f2ff..433bbeedebf 100644 --- a/rules/config +++ b/rules/config @@ -129,9 +129,9 @@ INCLUDE_SFLOW = y # INCLUDE_MGMT_FRAMEWORK - build docker-sonic-mgmt-framework for CLI and REST server support INCLUDE_MGMT_FRAMEWORK = y -# INCLUDE_HOST_SERVICE - build sonic-host-services for mgmt-framework and/or -# telemetry containers to access host functionality -INCLUDE_HOST_SERVICE = n +# ENABLE_HOST_SERVICE_ON_START - enable sonic-host-server for mgmt-framework and/or +# telemetry containers to access host functionality by default +ENABLE_HOST_SERVICE_ON_START = n # INCLUDE_RESTAPI - build docker-sonic-restapi for configuring the switch using REST APIs INCLUDE_RESTAPI = n diff --git a/rules/dbsyncd-py2.dep b/rules/dbsyncd-py2.dep deleted file mode 100644 index 6ca1ab8dd78..00000000000 --- a/rules/dbsyncd-py2.dep +++ /dev/null @@ -1,12 +0,0 @@ - -SPATH := $($(DBSYNCD_PY2)_SRC_PATH) -DEP_FILES := $(SONIC_COMMON_FILES_LIST) rules/dbsyncd-py2.mk rules/dbsyncd-py2.dep -DEP_FILES += $(SONIC_COMMON_BASE_FILES_LIST) -SMDEP_FILES := $(addprefix $(SPATH)/,$(shell cd $(SPATH) && git ls-files)) - -$(DBSYNCD_PY2)_CACHE_MODE := GIT_CONTENT_SHA -$(DBSYNCD_PY2)_DEP_FLAGS := $(SONIC_COMMON_FLAGS_LIST) -$(DBSYNCD_PY2)_DEP_FILES := $(DEP_FILES) -$(DBSYNCD_PY2)_SMDEP_FILES := $(SMDEP_FILES) -$(DBSYNCD_PY2)_SMDEP_PATHS := $(SPATH) - diff --git a/rules/dbsyncd-py2.mk b/rules/dbsyncd-py2.mk deleted file mode 100644 index 220dc5fe7a1..00000000000 --- a/rules/dbsyncd-py2.mk +++ /dev/null @@ -1,7 +0,0 @@ -# sonic-dbsyncd python2 wheel - -DBSYNCD_PY2 = sonic_d-2.0.0-py2-none-any.whl -$(DBSYNCD_PY2)_SRC_PATH = $(SRC_PATH)/sonic-dbsyncd -$(DBSYNCD_PY2)_PYTHON_VERSION = 2 -$(DBSYNCD_PY2)_DEPENDS += $(SWSSSDK_PY2) -SONIC_PYTHON_WHEELS += $(DBSYNCD_PY2) diff --git a/rules/dbsyncd-py3.mk b/rules/dbsyncd-py3.mk index 0f150c0c59f..12cf13cafe3 100644 --- a/rules/dbsyncd-py3.mk +++ b/rules/dbsyncd-py3.mk @@ -4,4 +4,5 @@ DBSYNCD_PY3 = sonic_d-2.0.0-py3-none-any.whl $(DBSYNCD_PY3)_SRC_PATH = $(SRC_PATH)/sonic-dbsyncd $(DBSYNCD_PY3)_PYTHON_VERSION = 3 $(DBSYNCD_PY3)_DEPENDS += $(SWSSSDK_PY3) +$(DBSYNCD_PY3)_DEBS_DEPENDS += $(LIBSWSSCOMMON) $(PYTHON3_SWSSCOMMON) SONIC_PYTHON_WHEELS += $(DBSYNCD_PY3) diff --git a/rules/docker-config-engine-stretch.mk b/rules/docker-config-engine-stretch.mk index 485e10fbb71..7e90c1587a9 100644 --- a/rules/docker-config-engine-stretch.mk +++ b/rules/docker-config-engine-stretch.mk @@ -2,6 +2,7 @@ DOCKER_CONFIG_ENGINE_STRETCH = docker-config-engine-stretch.gz $(DOCKER_CONFIG_ENGINE_STRETCH)_PATH = $(DOCKERS_PATH)/docker-config-engine-stretch +$(DOCKER_CONFIG_ENGINE_STRETCH)_DEPENDS += $(LIBSWSSCOMMON) $(PYTHON_SWSSCOMMON) $(DOCKER_CONFIG_ENGINE_STRETCH)_PYTHON_WHEELS += $(SWSSSDK_PY2) $(DOCKER_CONFIG_ENGINE_STRETCH)_PYTHON_WHEELS += $(SONIC_PY_COMMON_PY2) $(DOCKER_CONFIG_ENGINE_STRETCH)_PYTHON_WHEELS += $(SONIC_CONFIG_ENGINE_PY2) diff --git a/rules/docker-fpm-frr.mk b/rules/docker-fpm-frr.mk index e6473ef5eee..d4aace307a1 100644 --- a/rules/docker-fpm-frr.mk +++ b/rules/docker-fpm-frr.mk @@ -5,7 +5,7 @@ DOCKER_FPM_FRR = $(DOCKER_FPM_FRR_STEM).gz DOCKER_FPM_FRR_DBG = $(DOCKER_FPM_FRR_STEM)-$(DBG_IMAGE_MARK).gz $(DOCKER_FPM_FRR)_PATH = $(DOCKERS_PATH)/$(DOCKER_FPM_FRR_STEM) -$(DOCKER_FPM_FRR)_PYTHON_WHEELS += $(SONIC_BGPCFGD) +$(DOCKER_FPM_FRR)_PYTHON_WHEELS += $(SONIC_BGPCFGD) $(SONIC_FRR_MGMT_FRAMEWORK) $(DOCKER_FPM_FRR)_DEPENDS += $(FRR) $(FRR_SNMP) $(SWSS) $(LIBYANG1) $(DOCKER_FPM_FRR)_DBG_DEPENDS = $($(DOCKER_CONFIG_ENGINE_BUSTER)_DBG_DEPENDS) diff --git a/rules/frr.mk b/rules/frr.mk index 7572beb3b06..bb6a96a61fa 100644 --- a/rules/frr.mk +++ b/rules/frr.mk @@ -3,7 +3,7 @@ FRR_VERSION = 7.5 FRR_SUBVERSION = 0 FRR_BRANCH = frr/7.5 -FRR_TAG = frr-7.5-s1 +FRR_TAG = frr-7.5-s2 export FRR_VERSION FRR_SUBVERSION FRR_BRANCH FRR_TAG diff --git a/rules/functions b/rules/functions index 35b63aeabaf..c6caebe8285 100644 --- a/rules/functions +++ b/rules/functions @@ -48,7 +48,7 @@ log_green = echo -e "$(GREEN)$(1)$(GRAY)" FLUSH_LOG = rm -f $@.log LOG_SIMPLE = &>> $(PROJECT_ROOT)/$@.log || { [ $$? -eq 0 ] || pushd $(PROJECT_ROOT) > /dev/null ; ./update_screen.sh -e $@ ; popd > /dev/null ; false ; } -LOG = |& $(PROJECT_ROOT)/scripts/process_log.sh $(PROCESS_LOG_OPTION) &>> $(PROJECT_ROOT)/$@.log ; test $${PIPESTATUS[-2]} -eq 0 || { [ $$? -eq 0 ] || pushd $(PROJECT_ROOT) > /dev/null ; ./update_screen.sh -e $@ ; popd > /dev/null ; false ; } +LOG = < /dev/null |& $(PROJECT_ROOT)/scripts/process_log.sh $(PROCESS_LOG_OPTION) &>> $(PROJECT_ROOT)/$@.log ; test $${PIPESTATUS[-2]} -eq 0 || { [ $$? -eq 0 ] || pushd $(PROJECT_ROOT) > /dev/null ; ./update_screen.sh -e $@ ; popd > /dev/null ; false ; } ############################################################################### ## Header and footer for each target diff --git a/rules/linux-kernel.mk b/rules/linux-kernel.mk index 600600cc96f..44107c4c774 100644 --- a/rules/linux-kernel.mk +++ b/rules/linux-kernel.mk @@ -1,9 +1,9 @@ # linux kernel package -KVERSION_SHORT = 4.19.0-9-2 +KVERSION_SHORT = 4.19.0-12-2 KVERSION = $(KVERSION_SHORT)-$(CONFIGURED_ARCH) -KERNEL_VERSION = 4.19.118 -KERNEL_SUBVERSION = 2+deb10u1 +KERNEL_VERSION = 4.19.152 +KERNEL_SUBVERSION = 1 ifeq ($(CONFIGURED_ARCH), armhf) # Override kernel version for ARMHF as it uses arm MP (multi-platform) for short version KVERSION = $(KVERSION_SHORT)-armmp diff --git a/rules/sflow.mk b/rules/sflow.mk index f41bde774f0..7f0ac72bed3 100644 --- a/rules/sflow.mk +++ b/rules/sflow.mk @@ -1,7 +1,7 @@ # host-sflow package -HSFLOWD_VERSION = 2.0.28 -HSFLOWD_SUBVERSION = 2 +HSFLOWD_VERSION = 2.0.32 +HSFLOWD_SUBVERSION = 1 export HSFLOWD_VERSION HSFLOWD_SUBVERSION HSFLOWD = hsflowd_$(HSFLOWD_VERSION)-$(HSFLOWD_SUBVERSION)_$(CONFIGURED_ARCH).deb diff --git a/rules/sonic-config.mk b/rules/sonic-config.mk index 996e311b5fe..e8e59fc1b92 100644 --- a/rules/sonic-config.mk +++ b/rules/sonic-config.mk @@ -2,7 +2,8 @@ SONIC_CONFIG_ENGINE_PY2 = sonic_config_engine-1.0-py2-none-any.whl $(SONIC_CONFIG_ENGINE_PY2)_SRC_PATH = $(SRC_PATH)/sonic-config-engine -$(SONIC_CONFIG_ENGINE_PY2)_DEPENDS += $(SWSSSDK_PY2) $(SONIC_PY_COMMON_PY2) +$(SONIC_CONFIG_ENGINE_PY2)_DEPENDS += $(SONIC_PY_COMMON_PY2) +$(SONIC_CONFIG_ENGINE_PY2)_DEBS_DEPENDS += $(PYTHON_SWSSCOMMON) $(SONIC_CONFIG_ENGINE_PY2)_PYTHON_VERSION = 2 SONIC_PYTHON_WHEELS += $(SONIC_CONFIG_ENGINE_PY2) @@ -10,7 +11,8 @@ SONIC_PYTHON_WHEELS += $(SONIC_CONFIG_ENGINE_PY2) SONIC_CONFIG_ENGINE_PY3 = sonic_config_engine-1.0-py3-none-any.whl $(SONIC_CONFIG_ENGINE_PY3)_SRC_PATH = $(SRC_PATH)/sonic-config-engine -$(SONIC_CONFIG_ENGINE_PY3)_DEPENDS += $(SWSSSDK_PY3) $(SONIC_PY_COMMON_PY3) +$(SONIC_CONFIG_ENGINE_PY3)_DEPENDS += $(SONIC_PY_COMMON_PY3) +$(SONIC_CONFIG_ENGINE_PY3)_DEBS_DEPENDS += $(PYTHON3_SWSSCOMMON) # Synthetic dependency to avoid building the Python 2 and 3 packages # simultaneously and any potential conflicts which may arise $(SONIC_CONFIG_ENGINE_PY3)_DEPENDS += $(SONIC_CONFIG_ENGINE_PY2) diff --git a/rules/sonic-frr-mgmt-framework.dep b/rules/sonic-frr-mgmt-framework.dep new file mode 100644 index 00000000000..318c4edd1da --- /dev/null +++ b/rules/sonic-frr-mgmt-framework.dep @@ -0,0 +1,8 @@ +SPATH := $($(SONIC_FRR_MGMT_FRAMEWORK)_SRC_PATH) +DEP_FILES := $(SONIC_COMMON_FILES_LIST) rules/sonic-frr-mgmt-framework.mk rules/sonic-frr-mgmt-framework.dep +DEP_FILES += $(SONIC_COMMON_BASE_FILES_LIST) +DEP_FILES += $(shell git ls-files $(SPATH)) + +$(SONIC_FRR_MGMT_FRAMEWORK)_CACHE_MODE := GIT_CONTENT_SHA +$(SONIC_FRR_MGMT_FRAMEWORK)_DEP_FLAGS := $(SONIC_COMMON_FLAGS_LIST) +$(SONIC_FRR_MGMT_FRAMEWORK)_DEP_FILES := $(DEP_FILES) diff --git a/rules/sonic-frr-mgmt-framework.mk b/rules/sonic-frr-mgmt-framework.mk new file mode 100644 index 00000000000..dfe981b440a --- /dev/null +++ b/rules/sonic-frr-mgmt-framework.mk @@ -0,0 +1,13 @@ +# sonic-frr-mgmt-framework package + +SONIC_FRR_MGMT_FRAMEWORK = sonic_frr_mgmt_framework-1.0-py3-none-any.whl +$(SONIC_FRR_MGMT_FRAMEWORK)_SRC_PATH = $(SRC_PATH)/sonic-frr-mgmt-framework +# These dependencies are only needed because they are dependencies +# of sonic-config-engine and frrcfgd explicitly calls sonic-cfggen +# as part of its unit tests. +# TODO: Refactor unit tests so that these dependencies are not needed + +$(SONIC_FRR_MGMT_FRAMEWORK)_DEPENDS += $(SONIC_CONFIG_ENGINE_PY3) +$(SONIC_FRR_MGMT_FRAMEWORK)_DEBS_DEPENDS += $(PYTHON_SWSSCOMMON) +$(SONIC_FRR_MGMT_FRAMEWORK)_PYTHON_VERSION = 3 +SONIC_PYTHON_WHEELS += $(SONIC_FRR_MGMT_FRAMEWORK) diff --git a/rules/sonic-host-service.dep b/rules/sonic-host-service.dep deleted file mode 100644 index f19d30a0c0c..00000000000 --- a/rules/sonic-host-service.dep +++ /dev/null @@ -1,12 +0,0 @@ - -ifeq ($(INCLUDE_HOST_SERVICE), y) -SPATH := $($(SONIC_HOST_SERVICE)_SRC_PATH) -DEP_FILES := $(SONIC_COMMON_FILES_LIST) rules/sonic-host-service.mk rules/sonic-host-service.dep -SMDEP_FILES := $(addprefix $(SPATH)/,$(shell cd $(SPATH) && git ls-files)) - -$(SONIC_HOST_SERVICE)_CACHE_MODE := GIT_CONTENT_SHA -$(SONIC_HOST_SERVICE)_DEP_FLAGS := $(SONIC_COMMON_FLAGS_LIST) -$(SONIC_HOST_SERVICE)_DEP_FILES := $(DEP_FILES) -$(SONIC_HOST_SERVICE)_SMDEP_FILES := $(SMDEP_FILES) -$(SONIC_HOST_SERVICE)_SMDEP_PATHS := $(SPATH) -endif diff --git a/rules/sonic-host-service.mk b/rules/sonic-host-service.mk deleted file mode 100644 index ad786f1a9d1..00000000000 --- a/rules/sonic-host-service.mk +++ /dev/null @@ -1,9 +0,0 @@ -# SONiC host service package - -ifeq ($(INCLUDE_HOST_SERVICE), y) - -SONIC_HOST_SERVICE = sonic-host-service_1.0.0_all.deb -$(SONIC_HOST_SERVICE)_SRC_PATH = $(SRC_PATH)/sonic-host-service -SONIC_MAKE_DEBS += $(SONIC_HOST_SERVICE) - -endif diff --git a/rules/sonic-utilities.mk b/rules/sonic-utilities.mk index 41d785b0628..4e5b5adbc5d 100644 --- a/rules/sonic-utilities.mk +++ b/rules/sonic-utilities.mk @@ -6,6 +6,7 @@ $(SONIC_UTILITIES_PY3)_PYTHON_VERSION = 3 $(SONIC_UTILITIES_PY3)_DEPENDS += $(SONIC_PY_COMMON_PY3) \ $(SWSSSDK_PY3) \ $(SONIC_CONFIG_ENGINE_PY3) \ + $(SONIC_PLATFORM_COMMON_PY3) \ $(SONIC_YANG_MGMT_PY3) \ $(SONIC_YANG_MODELS_PY3) $(SONIC_UTILITIES_PY3)_DEBS_DEPENDS = $(LIBYANG) \ @@ -13,5 +14,4 @@ $(SONIC_UTILITIES_PY3)_DEBS_DEPENDS = $(LIBYANG) \ $(LIBYANG_PY3) \ $(LIBSWSSCOMMON) \ $(PYTHON3_SWSSCOMMON) -$(SONIC_UTILITIES_PY3)_TEST = n SONIC_PYTHON_WHEELS += $(SONIC_UTILITIES_PY3) diff --git a/scripts/build_kvm_image.sh b/scripts/build_kvm_image.sh index 4531ca25a5f..06bb8750918 100755 --- a/scripts/build_kvm_image.sh +++ b/scripts/build_kvm_image.sh @@ -23,6 +23,7 @@ on_exit() on_error() { netstat -antp + ps aux echo "============= kvm_log ==============" cat $kvm_log } @@ -48,6 +49,7 @@ prepare_installer_disk() umount $tmpdir } +apt-get install -y net-tools create_disk prepare_installer_disk diff --git a/slave.mk b/slave.mk index 485649e8cf4..5eceaf6a0d4 100644 --- a/slave.mk +++ b/slave.mk @@ -247,7 +247,7 @@ $(info "VS_PREPARE_MEM" : "$(VS_PREPARE_MEM)") $(info "INCLUDE_MGMT_FRAMEWORK" : "$(INCLUDE_MGMT_FRAMEWORK)") $(info "INCLUDE_ICCPD" : "$(INCLUDE_ICCPD)") $(info "INCLUDE_SYSTEM_TELEMETRY" : "$(INCLUDE_SYSTEM_TELEMETRY)") -$(info "INCLUDE_HOST_SERVICE" : "$(INCLUDE_HOST_SERVICE)") +$(info "ENABLE_HOST_SERVICE_ON_START" : "$(ENABLE_HOST_SERVICE_ON_START)") $(info "INCLUDE_RESTAPI" : "$(INCLUDE_RESTAPI)") $(info "INCLUDE_SFLOW" : "$(INCLUDE_SFLOW)") $(info "INCLUDE_NAT" : "$(INCLUDE_NAT)") @@ -464,14 +464,14 @@ $(addprefix $(DEBS_PATH)/, $(SONIC_DPKG_DEBS)) : $(DEBS_PATH)/% : .platform $$(a if [ -f ./autogen.sh ]; then ./autogen.sh $(LOG); fi $(SETUP_OVERLAYFS_FOR_DPKG_ADMINDIR) $(if $($*_DPKG_TARGET), - DEB_BUILD_OPTIONS="${DEB_BUILD_OPTIONS_GENERIC} ${$*_DEB_BUILD_OPTIONS}" dpkg-buildpackage -rfakeroot -b -us -uc -j$(SONIC_CONFIG_MAKE_JOBS) --as-root -T$($*_DPKG_TARGET) --admindir $$mergedir $(LOG), - DEB_BUILD_OPTIONS="${DEB_BUILD_OPTIONS_GENERIC} ${$*_DEB_BUILD_OPTIONS}" dpkg-buildpackage -rfakeroot -b -us -uc -j$(SONIC_CONFIG_MAKE_JOBS) --admindir $$mergedir $(LOG) + ${$*_BUILD_ENV} DEB_BUILD_OPTIONS="${DEB_BUILD_OPTIONS_GENERIC} ${$*_DEB_BUILD_OPTIONS}" dpkg-buildpackage -rfakeroot -b -us -uc -j$(SONIC_CONFIG_MAKE_JOBS) --as-root -T$($*_DPKG_TARGET) --admindir $$mergedir $(LOG), + ${$*_BUILD_ENV} DEB_BUILD_OPTIONS="${DEB_BUILD_OPTIONS_GENERIC} ${$*_DEB_BUILD_OPTIONS}" dpkg-buildpackage -rfakeroot -b -us -uc -j$(SONIC_CONFIG_MAKE_JOBS) --admindir $$mergedir $(LOG) ) popd $(LOG_SIMPLE) # Clean up if [ -f $($*_SRC_PATH).patch/series ]; then pushd $($*_SRC_PATH) && quilt pop -a -f; [ -d .pc ] && rm -rf .pc; popd; fi # Take built package(s) - mv $(addprefix $($*_SRC_PATH)/../, $* $($*_DERIVED_DEBS) $($*_EXTRA_DEBS)) $(DEBS_PATH) $(LOG) + mv -f $(addprefix $($*_SRC_PATH)/../, $* $($*_DERIVED_DEBS) $($*_EXTRA_DEBS)) $(DEBS_PATH) $(LOG) # Save the target deb into DPKG cache $(call SAVE_CACHE,$*,$@) @@ -572,7 +572,7 @@ $(addprefix $(PYTHON_DEBS_PATH)/, $(SONIC_PYTHON_STDEB_DEBS)) : $(PYTHON_DEBS_PA # Clean up if [ -f $($*_SRC_PATH).patch/series ]; then pushd $($*_SRC_PATH) && quilt pop -a -f; [ -d .pc ] && rm -rf .pc; popd; fi # Take built package(s) - mv $(addprefix $($*_SRC_PATH)/deb_dist/, $* $($*_DERIVED_DEBS)) $(PYTHON_DEBS_PATH) $(LOG) + mv -f $(addprefix $($*_SRC_PATH)/deb_dist/, $* $($*_DERIVED_DEBS)) $(PYTHON_DEBS_PATH) $(LOG) # Save the target deb into DPKG cache $(call SAVE_CACHE,$*,$@) @@ -609,7 +609,7 @@ $(addprefix $(PYTHON_WHEELS_PATH)/, $(SONIC_PYTHON_WHEELS)) : $(PYTHON_WHEELS_PA # clean up if [ -f ../$(notdir $($*_SRC_PATH)).patch/series ]; then quilt pop -a -f; [ -d .pc ] && rm -rf .pc; fi popd $(LOG_SIMPLE) - mv $($*_SRC_PATH)/dist/$* $(PYTHON_WHEELS_PATH) $(LOG) + mv -f $($*_SRC_PATH)/dist/$* $(PYTHON_WHEELS_PATH) $(LOG) # Save the target deb into DPKG cache $(call SAVE_CACHE,$*,$@) @@ -857,7 +857,6 @@ $(addprefix $(TARGET_PATH)/, $(SONIC_INSTALLERS)) : $(TARGET_PATH)/% : \ $$(addprefix $(TARGET_PATH)/,$$($$*_DOCKERS)) \ $$(addprefix $(FILES_PATH)/,$$($$*_FILES)) \ $(if $(findstring y,$(ENABLE_ZTP)),$(addprefix $(IMAGE_DISTRO_DEBS_PATH)/,$(SONIC_ZTP))) \ - $(if $(findstring y,$(INCLUDE_HOST_SERVICE)),$(addprefix $(IMAGE_DISTRO_DEBS_PATH)/,$(SONIC_HOST_SERVICE))) \ $(addprefix $(PYTHON_WHEELS_PATH)/,$(SONIC_UTILITIES_PY3)) \ $(addprefix $(PYTHON_WHEELS_PATH)/,$(SONIC_PY_COMMON_PY2)) \ $(addprefix $(PYTHON_WHEELS_PATH)/,$(SONIC_PY_COMMON_PY3)) \ @@ -892,7 +891,6 @@ $(addprefix $(TARGET_PATH)/, $(SONIC_INSTALLERS)) : $(TARGET_PATH)/% : \ export enable_ztp="$(ENABLE_ZTP)" export include_system_telemetry="$(INCLUDE_SYSTEM_TELEMETRY)" export include_restapi="$(INCLUDE_RESTAPI)" - export include_host_service="$(INCLUDE_HOST_SERVICE)" export include_nat="$(INCLUDE_NAT)" export include_sflow="$(INCLUDE_SFLOW)" export include_mgmt_framework="$(INCLUDE_MGMT_FRAMEWORK)" diff --git a/sonic-slave-buster/Dockerfile.j2 b/sonic-slave-buster/Dockerfile.j2 index 61ece64a113..ed541ec5356 100644 --- a/sonic-slave-buster/Dockerfile.j2 +++ b/sonic-slave-buster/Dockerfile.j2 @@ -61,7 +61,6 @@ RUN apt-get update && apt-get install -y \ dh-exec \ kmod \ libtinyxml2-6a \ - libboost-program-options1.67-dev \ libtinyxml2-dev \ python \ python-pip \ @@ -121,7 +120,6 @@ RUN apt-get update && apt-get install -y \ module-assistant \ # For thrift build\ gem2deb \ - libboost-all-dev \ libevent-dev \ libglib2.0-dev \ libqt4-dev \ @@ -321,7 +319,33 @@ RUN apt-get update && apt-get install -y \ docbook-to-man \ docbook-utils \ # For kdump-tools - libbz2-dev + libbz2-dev \ +# For linkmgrd + libboost1.71-dev \ + libboost-program-options1.71-dev \ + libboost-system1.71-dev \ + libboost-thread1.71-dev \ + libboost-atomic1.71-dev \ + libboost-chrono1.71-dev \ + libboost-container1.71-dev \ + libboost-context1.71-dev \ + libboost-contract1.71-dev \ + libboost-coroutine1.71-dev \ + libboost-date-time1.71-dev \ + libboost-fiber1.71-dev \ + libboost-filesystem1.71-dev \ + libboost-graph-parallel1.71-dev \ + libboost-log1.71-dev \ + libboost-regex1.71-dev \ + googletest \ + libgtest-dev \ + libgcc-8-dev \ +# For sonic-host-services build + libcairo2-dev \ + libdbus-1-dev \ + libgirepository1.0-dev \ + libsystemd-dev \ + pkg-config # Build fix for ARMHF buster libsairedis {%- if CONFIGURED_ARCH == "armhf" %} @@ -372,7 +396,7 @@ RUN export VERSION=1.14.2 \ RUN pip3 install --upgrade pip RUN pip2 install --upgrade 'pip<21' -RUN apt-get purge -y python-pip python3-pip +RUN apt-get purge -y python-pip python3-pip python3-yaml # For building Python packages RUN pip2 install setuptools==40.8.0 @@ -411,8 +435,8 @@ RUN pip3 uninstall -y enum34 RUN pip2 install j2cli==0.3.10 # For sonic-mgmt-framework -RUN pip2 install "PyYAML==5.3.1" -RUN pip3 install "PyYAML==5.3.1" +RUN pip2 install "PyYAML==5.4.1" +RUN pip3 install "PyYAML==5.4.1" RUN pip2 install "lxml==4.6.2" RUN pip3 install "lxml==4.6.2" diff --git a/src/snmpd/Makefile b/src/snmpd/Makefile index b66af241e5c..2e0ac828169 100644 --- a/src/snmpd/Makefile +++ b/src/snmpd/Makefile @@ -29,7 +29,11 @@ $(addprefix $(DEST)/, $(MAIN_TARGET)): $(DEST)/% : stg init stg import -s ../patch-$(SNMPD_VERSION)/series +ifeq ($(CONFIGURED_ARCH), arm64) + dpkg-buildpackage -rfakeroot -b -d -us -uc -j1 --admindir $(SONIC_DPKG_ADMINDIR) +else dpkg-buildpackage -rfakeroot -b -d -us -uc -j$(SONIC_CONFIG_MAKE_JOBS) --admindir $(SONIC_DPKG_ADMINDIR) +endif popd mv $(DERIVED_TARGETS) $* $(DEST)/ diff --git a/src/sonic-bgpcfgd/bgpcfgd/managers_allow_list.py b/src/sonic-bgpcfgd/bgpcfgd/managers_allow_list.py index 1e4eb6e404e..435be91d20d 100644 --- a/src/sonic-bgpcfgd/bgpcfgd/managers_allow_list.py +++ b/src/sonic-bgpcfgd/bgpcfgd/managers_allow_list.py @@ -173,6 +173,7 @@ def __remove_policy(self, deployment_id, community_value): msg += " deployment_id '%s'. community: '%s'" log_info(msg % info) + default_action = self.__get_default_action_community() names = self.__generate_names(deployment_id, community_value) self.cfg_mgr.update() cmds = [] @@ -181,6 +182,8 @@ def __remove_policy(self, deployment_id, community_value): cmds += self.__remove_prefix_list(self.V4, names['pl_v4']) cmds += self.__remove_prefix_list(self.V6, names['pl_v6']) cmds += self.__remove_community(names['community']) + cmds += self.__update_default_route_map_entry(names['rm_v4'], default_action) + cmds += self.__update_default_route_map_entry(names['rm_v6'], default_action) if cmds: self.cfg_mgr.push_list(cmds) peer_groups = self.__find_peer_group_by_deployment_id(deployment_id) @@ -676,7 +679,7 @@ def __af_to_family(self, af): """ return 'ip' if af == self.V4 else 'ipv6' - def __get_default_action_community(self, data): + def __get_default_action_community(self, data=None): """ Determine the default action community based on the request. If request doesn't contain "default_action" field - the default_action value @@ -685,7 +688,7 @@ def __get_default_action_community(self, data): :return: returns community value for "default_action" """ drop_community = self.constants["bgp"]["allow_list"]["drop_community"] - if "default_action" in data: + if data and "default_action" in data: if data["default_action"] == "deny": return "no-export" else: # "permit" diff --git a/src/sonic-bgpcfgd/bgpcfgd/managers_bbr.py b/src/sonic-bgpcfgd/bgpcfgd/managers_bbr.py index 27f3646ac42..0e82d0a4b6d 100644 --- a/src/sonic-bgpcfgd/bgpcfgd/managers_bbr.py +++ b/src/sonic-bgpcfgd/bgpcfgd/managers_bbr.py @@ -113,9 +113,10 @@ def __set_prepare_config(self, status): for af in ["ipv4", "ipv6"]: cmds.append(" address-family %s" % af) for pg_name in sorted(self.bbr_enabled_pgs.keys()): - if pg_name in available_peer_groups and af in self.bbr_enabled_pgs[pg_name]: - cmds.append(" %sneighbor %s allowas-in 1" % (prefix_of_commands, pg_name)) - peer_groups_to_restart.add(pg_name) + for peer_group_name in available_peer_groups: + if peer_group_name.startswith(pg_name) and af in self.bbr_enabled_pgs[pg_name]: + cmds.append(" %sneighbor %s allowas-in 1" % (prefix_of_commands, peer_group_name)) + peer_groups_to_restart.add(peer_group_name) return cmds, list(peer_groups_to_restart) def __get_available_peer_groups(self): diff --git a/src/sonic-bgpcfgd/bgpcfgd/managers_intf.py b/src/sonic-bgpcfgd/bgpcfgd/managers_intf.py index ef4958ad920..c633c43046e 100644 --- a/src/sonic-bgpcfgd/bgpcfgd/managers_intf.py +++ b/src/sonic-bgpcfgd/bgpcfgd/managers_intf.py @@ -30,7 +30,7 @@ def set_handler(self, key, data): try: network = netaddr.IPNetwork(str(network_str)) except (netaddr.NotRegisteredError, netaddr.AddrFormatError, netaddr.AddrConversionError): - log_warn("Subnet '%s' format is wrong for interface '%s'" % (network_str, data["interface"])) + log_warn("Subnet '%s' format is wrong for interface '%s'" % (network_str, interface_name)) return True data["interface"] = interface_name data["prefixlen"] = str(network.prefixlen) diff --git a/src/sonic-bgpcfgd/bgpmon/bgpmon.py b/src/sonic-bgpcfgd/bgpmon/bgpmon.py index c20c2110a6b..2b50bd6cf58 100755 --- a/src/sonic-bgpcfgd/bgpmon/bgpmon.py +++ b/src/sonic-bgpcfgd/bgpmon/bgpmon.py @@ -4,20 +4,20 @@ Description: bgpmon.py -- populating bgp related information in stateDB. script is started by supervisord in bgp docker when the docker is started. - Initial creation of this daemon is to assist SNMP agent in obtaining the + Initial creation of this daemon is to assist SNMP agent in obtaining the BGP related information for its MIB support. The MIB that this daemon is assisting is for the CiscoBgp4MIB (Neighbor state only). If there are other - BGP related items that needs to be updated in a periodic manner in the + BGP related items that needs to be updated in a periodic manner in the future, then more can be added into this process. The script check if there are any bgp activities by monitoring the bgp frr.log file timestamp. If activity is detected, then it will request bgp - neighbor state via vtysh cli interface. This bgp activity monitoring is + neighbor state via vtysh cli interface. This bgp activity monitoring is done periodically (every 15 second). When triggered, it looks specifically for the neighbor state in the json output of show ip bgp neighbors json and update the state DB for each neighbor accordingly. In order to not disturb and hold on to the State DB access too long and - removal of the stale neighbors (neighbors that was there previously on + removal of the stale neighbors (neighbors that was there previously on previous get request but no longer there in the current get request), a "previous" neighbor dictionary will be kept and used to determine if there is a need to perform update or the peer is stale to be removed from the @@ -34,13 +34,13 @@ class BgpStateGet: def __init__(self): - # list peer_l stores the Neighbor peer Ip address + # set peer_l stores the Neighbor peer Ip address # dic peer_state stores the Neighbor peer state entries - # list new_peer_l stores the new snapshot of Neighbor peer ip address + # set new_peer_l stores the new snapshot of Neighbor peer ip address # dic new_peer_state stores the new snapshot of Neighbor peer states - self.peer_l = [] + self.peer_l = set() self.peer_state = {} - self.new_peer_l = [] + self.new_peer_l = set() self.new_peer_state = {} self.cached_timestamp = 0 self.db = swsssdk.SonicV2Connector() @@ -67,7 +67,7 @@ def bgp_activity_detected(self): def update_new_peer_states(self, peer_dict): peer_l = peer_dict["peers"].keys() - self.new_peer_l.extend(peer_l) + self.new_peer_l.update(peer_l) for peer in peer_l: self.new_peer_state[peer] = peer_dict["peers"][peer]["state"] @@ -80,8 +80,8 @@ def get_all_neigh_states(self): return peer_info = json.loads(output) - # cmd ran successfully, safe to Clean the "new" lists/dic for new snapshot - del self.new_peer_l[:] + # cmd ran successfully, safe to Clean the "new" set/dict for new snapshot + self.new_peer_l.clear() self.new_peer_state.clear() for key, value in peer_info.items(): if key == "ipv4Unicast" or key == "ipv6Unicast": @@ -115,8 +115,7 @@ def flush_pipe(self, data): def update_neigh_states(self): data = {} - for i in range (0, len(self.new_peer_l)): - peer = self.new_peer_l[i] + for peer in self.new_peer_l: key = "NEIGH_STATE_TABLE|%s" % peer if peer in self.peer_l: # only update the entry if state changed @@ -125,7 +124,7 @@ def update_neigh_states(self): state = self.new_peer_state[peer] data[key] = {'state':state} self.peer_state[peer] = state - # remove this neighbor from old list since it is accounted for + # remove this neighbor from old set since it is accounted for self.peer_l.remove(peer) else: # New neighbor found case. Add to dictionary and state DB @@ -135,19 +134,19 @@ def update_neigh_states(self): if len(data) > PIPE_BATCH_MAX_COUNT: self.flush_pipe(data) # Check for stale state entries to be cleaned up - while len(self.peer_l) > 0: + for peer in self.peer_l: # remove this from the stateDB and the current neighbor state entry - peer = self.peer_l.pop(0) del_key = "NEIGH_STATE_TABLE|%s" % peer data[del_key] = None - del self.peer_state[peer] + if peer in self.peer_state: + del self.peer_state[peer] if len(data) > PIPE_BATCH_MAX_COUNT: self.flush_pipe(data) # If anything in the pipeline not yet flushed, flush them now if len(data) > 0: self.flush_pipe(data) - # Save the new List - self.peer_l = self.new_peer_l[:] + # Save the new set + self.peer_l = self.new_peer_l.copy() def main(): diff --git a/src/sonic-bgpcfgd/setup.py b/src/sonic-bgpcfgd/setup.py index d6290bccb2b..ab86ca20ec1 100755 --- a/src/sonic-bgpcfgd/setup.py +++ b/src/sonic-bgpcfgd/setup.py @@ -17,7 +17,7 @@ install_requires = [ 'jinja2>=2.10', 'netaddr==0.8.0', - 'pyyaml==5.3.1', + 'pyyaml==5.4.1', ], setup_requires = [ 'pytest-runner', diff --git a/src/sonic-bgpcfgd/tests/test_allow_list.py b/src/sonic-bgpcfgd/tests/test_allow_list.py index 6a53e2f49ca..cb0896982a3 100644 --- a/src/sonic-bgpcfgd/tests/test_allow_list.py +++ b/src/sonic-bgpcfgd/tests/test_allow_list.py @@ -4,6 +4,7 @@ from bgpcfgd.directory import Directory from bgpcfgd.template import TemplateFabric import bgpcfgd +from copy import deepcopy swsscommon_module_mock = MagicMock() @@ -26,7 +27,7 @@ } @patch.dict("sys.modules", swsscommon=swsscommon_module_mock) -def set_del_test(op, args, currect_config, expected_config): +def set_del_test(op, args, currect_config, expected_config, update_global_default_action=None): from bgpcfgd.managers_allow_list import BGPAllowListMgr set_del_test.push_list_called = False def push_list(args): @@ -44,10 +45,12 @@ def push_list(args): 'directory': Directory(), 'cfg_mgr': cfg_mgr, 'tf': TemplateFabric(), - 'constants': global_constants, + 'constants': deepcopy(global_constants), } mgr = BGPAllowListMgr(common_objs, "CONFIG_DB", "BGP_ALLOWED_PREFIXES") + if update_global_default_action: + mgr.constants["bgp"]["allow_list"]["default_action"] = update_global_default_action if op == "SET": mgr.set_handler(*args) elif op == "DEL": @@ -89,6 +92,74 @@ def test_set_handler_with_community(): ' match community COMMUNITY_ALLOW_LIST_DEPLOYMENT_ID_5_COMMUNITY_1010:2020', ] ) +def test_set_handler_with_community_and_permit_action(): + set_del_test( + "SET", + ("DEPLOYMENT_ID|5|1010:2020", { + "prefixes_v4": "10.20.30.0/24,30.50.0.0/16", + "prefixes_v6": "fc00:20::/64,fc00:30::/64", + "default_action":"permit" + }), + [ + 'route-map ALLOW_LIST_DEPLOYMENT_ID_5_V4 permit 65535', + ' set community 123:123 additive', + 'route-map ALLOW_LIST_DEPLOYMENT_ID_5_V6 permit 65535', + ' set community 123:123 additive' + ], + [ + 'ip prefix-list PL_ALLOW_LIST_DEPLOYMENT_ID_5_COMMUNITY_1010:2020_V4 seq 10 deny 0.0.0.0/0 le 17', + 'ip prefix-list PL_ALLOW_LIST_DEPLOYMENT_ID_5_COMMUNITY_1010:2020_V4 seq 20 permit 10.20.30.0/24 le 32', + 'ip prefix-list PL_ALLOW_LIST_DEPLOYMENT_ID_5_COMMUNITY_1010:2020_V4 seq 30 permit 30.50.0.0/16 le 32', + 'ipv6 prefix-list PL_ALLOW_LIST_DEPLOYMENT_ID_5_COMMUNITY_1010:2020_V6 seq 10 deny 0::/0 le 59', + 'ipv6 prefix-list PL_ALLOW_LIST_DEPLOYMENT_ID_5_COMMUNITY_1010:2020_V6 seq 20 deny 0::/0 ge 65', + 'ipv6 prefix-list PL_ALLOW_LIST_DEPLOYMENT_ID_5_COMMUNITY_1010:2020_V6 seq 30 permit fc00:20::/64 le 128', + 'ipv6 prefix-list PL_ALLOW_LIST_DEPLOYMENT_ID_5_COMMUNITY_1010:2020_V6 seq 40 permit fc00:30::/64 le 128', + 'bgp community-list standard COMMUNITY_ALLOW_LIST_DEPLOYMENT_ID_5_COMMUNITY_1010:2020 permit 1010:2020', + 'route-map ALLOW_LIST_DEPLOYMENT_ID_5_V4 permit 10', + ' match ip address prefix-list PL_ALLOW_LIST_DEPLOYMENT_ID_5_COMMUNITY_1010:2020_V4', + ' match community COMMUNITY_ALLOW_LIST_DEPLOYMENT_ID_5_COMMUNITY_1010:2020', + 'route-map ALLOW_LIST_DEPLOYMENT_ID_5_V6 permit 10', + ' match ipv6 address prefix-list PL_ALLOW_LIST_DEPLOYMENT_ID_5_COMMUNITY_1010:2020_V6', + ' match community COMMUNITY_ALLOW_LIST_DEPLOYMENT_ID_5_COMMUNITY_1010:2020', + ] + ) + +def test_set_handler_with_community_and_deny_action(): + set_del_test( + "SET", + ("DEPLOYMENT_ID|5|1010:2020", { + "prefixes_v4": "10.20.30.0/24,30.50.0.0/16", + "prefixes_v6": "fc00:20::/64,fc00:30::/64", + "default_action":"deny" + }), + [ + 'route-map ALLOW_LIST_DEPLOYMENT_ID_5_V4 permit 65535', + ' set community 123:123 additive', + 'route-map ALLOW_LIST_DEPLOYMENT_ID_5_V6 permit 65535', + ' set community 123:123 additive' + ], + [ + 'ip prefix-list PL_ALLOW_LIST_DEPLOYMENT_ID_5_COMMUNITY_1010:2020_V4 seq 10 deny 0.0.0.0/0 le 17', + 'ip prefix-list PL_ALLOW_LIST_DEPLOYMENT_ID_5_COMMUNITY_1010:2020_V4 seq 20 permit 10.20.30.0/24 le 32', + 'ip prefix-list PL_ALLOW_LIST_DEPLOYMENT_ID_5_COMMUNITY_1010:2020_V4 seq 30 permit 30.50.0.0/16 le 32', + 'ipv6 prefix-list PL_ALLOW_LIST_DEPLOYMENT_ID_5_COMMUNITY_1010:2020_V6 seq 10 deny 0::/0 le 59', + 'ipv6 prefix-list PL_ALLOW_LIST_DEPLOYMENT_ID_5_COMMUNITY_1010:2020_V6 seq 20 deny 0::/0 ge 65', + 'ipv6 prefix-list PL_ALLOW_LIST_DEPLOYMENT_ID_5_COMMUNITY_1010:2020_V6 seq 30 permit fc00:20::/64 le 128', + 'ipv6 prefix-list PL_ALLOW_LIST_DEPLOYMENT_ID_5_COMMUNITY_1010:2020_V6 seq 40 permit fc00:30::/64 le 128', + 'bgp community-list standard COMMUNITY_ALLOW_LIST_DEPLOYMENT_ID_5_COMMUNITY_1010:2020 permit 1010:2020', + 'route-map ALLOW_LIST_DEPLOYMENT_ID_5_V4 permit 10', + ' match ip address prefix-list PL_ALLOW_LIST_DEPLOYMENT_ID_5_COMMUNITY_1010:2020_V4', + ' match community COMMUNITY_ALLOW_LIST_DEPLOYMENT_ID_5_COMMUNITY_1010:2020', + 'route-map ALLOW_LIST_DEPLOYMENT_ID_5_V6 permit 10', + ' match ipv6 address prefix-list PL_ALLOW_LIST_DEPLOYMENT_ID_5_COMMUNITY_1010:2020_V6', + ' match community COMMUNITY_ALLOW_LIST_DEPLOYMENT_ID_5_COMMUNITY_1010:2020', + 'route-map ALLOW_LIST_DEPLOYMENT_ID_5_V4 permit 65535', + ' set community no-export additive', + 'route-map ALLOW_LIST_DEPLOYMENT_ID_5_V6 permit 65535', + ' set community no-export additive' + ] + ) + def test_set_handler_no_community(): set_del_test( @@ -117,6 +188,66 @@ def test_set_handler_no_community(): ' match ipv6 address prefix-list PL_ALLOW_LIST_DEPLOYMENT_ID_5_COMMUNITY_empty_V6', ] ) +def test_set_handler_no_community_with_permit_action(): + set_del_test( + "SET", + ("DEPLOYMENT_ID|5", { + "prefixes_v4": "20.20.30.0/24,40.50.0.0/16", + "prefixes_v6": "fc01:20::/64,fc01:30::/64", + "default_action":"permit" + }), + [ + 'route-map ALLOW_LIST_DEPLOYMENT_ID_5_V4 permit 65535', + ' set community 123:123 additive', + 'route-map ALLOW_LIST_DEPLOYMENT_ID_5_V6 permit 65535', + ' set community 123:123 additive', + ], + [ + 'ip prefix-list PL_ALLOW_LIST_DEPLOYMENT_ID_5_COMMUNITY_empty_V4 seq 10 deny 0.0.0.0/0 le 17', + 'ip prefix-list PL_ALLOW_LIST_DEPLOYMENT_ID_5_COMMUNITY_empty_V4 seq 20 permit 20.20.30.0/24 le 32', + 'ip prefix-list PL_ALLOW_LIST_DEPLOYMENT_ID_5_COMMUNITY_empty_V4 seq 30 permit 40.50.0.0/16 le 32', + 'ipv6 prefix-list PL_ALLOW_LIST_DEPLOYMENT_ID_5_COMMUNITY_empty_V6 seq 10 deny 0::/0 le 59', + 'ipv6 prefix-list PL_ALLOW_LIST_DEPLOYMENT_ID_5_COMMUNITY_empty_V6 seq 20 deny 0::/0 ge 65', + 'ipv6 prefix-list PL_ALLOW_LIST_DEPLOYMENT_ID_5_COMMUNITY_empty_V6 seq 30 permit fc01:20::/64 le 128', + 'ipv6 prefix-list PL_ALLOW_LIST_DEPLOYMENT_ID_5_COMMUNITY_empty_V6 seq 40 permit fc01:30::/64 le 128', + 'route-map ALLOW_LIST_DEPLOYMENT_ID_5_V4 permit 30000', + ' match ip address prefix-list PL_ALLOW_LIST_DEPLOYMENT_ID_5_COMMUNITY_empty_V4', + 'route-map ALLOW_LIST_DEPLOYMENT_ID_5_V6 permit 30000', + ' match ipv6 address prefix-list PL_ALLOW_LIST_DEPLOYMENT_ID_5_COMMUNITY_empty_V6', + ] + ) +def test_set_handler_no_community_with_deny_action(): + set_del_test( + "SET", + ("DEPLOYMENT_ID|5", { + "prefixes_v4": "20.20.30.0/24,40.50.0.0/16", + "prefixes_v6": "fc01:20::/64,fc01:30::/64", + "default_action":"deny" + }), + [ + 'route-map ALLOW_LIST_DEPLOYMENT_ID_5_V4 permit 65535', + ' set community 123:123 additive', + 'route-map ALLOW_LIST_DEPLOYMENT_ID_5_V6 permit 65535', + ' set community 123:123 additive', + ], + [ + 'ip prefix-list PL_ALLOW_LIST_DEPLOYMENT_ID_5_COMMUNITY_empty_V4 seq 10 deny 0.0.0.0/0 le 17', + 'ip prefix-list PL_ALLOW_LIST_DEPLOYMENT_ID_5_COMMUNITY_empty_V4 seq 20 permit 20.20.30.0/24 le 32', + 'ip prefix-list PL_ALLOW_LIST_DEPLOYMENT_ID_5_COMMUNITY_empty_V4 seq 30 permit 40.50.0.0/16 le 32', + 'ipv6 prefix-list PL_ALLOW_LIST_DEPLOYMENT_ID_5_COMMUNITY_empty_V6 seq 10 deny 0::/0 le 59', + 'ipv6 prefix-list PL_ALLOW_LIST_DEPLOYMENT_ID_5_COMMUNITY_empty_V6 seq 20 deny 0::/0 ge 65', + 'ipv6 prefix-list PL_ALLOW_LIST_DEPLOYMENT_ID_5_COMMUNITY_empty_V6 seq 30 permit fc01:20::/64 le 128', + 'ipv6 prefix-list PL_ALLOW_LIST_DEPLOYMENT_ID_5_COMMUNITY_empty_V6 seq 40 permit fc01:30::/64 le 128', + 'route-map ALLOW_LIST_DEPLOYMENT_ID_5_V4 permit 30000', + ' match ip address prefix-list PL_ALLOW_LIST_DEPLOYMENT_ID_5_COMMUNITY_empty_V4', + 'route-map ALLOW_LIST_DEPLOYMENT_ID_5_V6 permit 30000', + ' match ipv6 address prefix-list PL_ALLOW_LIST_DEPLOYMENT_ID_5_COMMUNITY_empty_V6', + 'route-map ALLOW_LIST_DEPLOYMENT_ID_5_V4 permit 65535', + ' set community no-export additive', + 'route-map ALLOW_LIST_DEPLOYMENT_ID_5_V6 permit 65535', + ' set community no-export additive' + ] + ) def test_del_handler_with_community(): set_del_test( @@ -137,6 +268,11 @@ def test_del_handler_with_community(): 'route-map ALLOW_LIST_DEPLOYMENT_ID_5_V6 permit 10', ' match ipv6 address prefix-list PL_ALLOW_LIST_DEPLOYMENT_ID_5_COMMUNITY_1010:2020_V6', ' match community COMMUNITY_ALLOW_LIST_DEPLOYMENT_ID_5_COMMUNITY_1010:2020', + 'route-map ALLOW_LIST_DEPLOYMENT_ID_5_V4 permit 65535', + ' set community 123:123 additive', + 'route-map ALLOW_LIST_DEPLOYMENT_ID_5_V6 permit 65535', + ' set community 123:123 additive', + "" ], [ @@ -148,6 +284,155 @@ def test_del_handler_with_community(): ] ) +def test_del_handler_with_exiting_community_deny_action(): + set_del_test( + "DEL", + ("DEPLOYMENT_ID|5|1010:2020",), + [ + 'ip prefix-list PL_ALLOW_LIST_DEPLOYMENT_ID_5_COMMUNITY_1010:2020_V4 seq 10 deny 0.0.0.0/0 le 17', + 'ip prefix-list PL_ALLOW_LIST_DEPLOYMENT_ID_5_COMMUNITY_1010:2020_V4 seq 20 permit 10.20.30.0/24 ge 25', + 'ip prefix-list PL_ALLOW_LIST_DEPLOYMENT_ID_5_COMMUNITY_1010:2020_V4 seq 30 permit 30.50.0.0/16 ge 17', + 'ipv6 prefix-list PL_ALLOW_LIST_DEPLOYMENT_ID_5_COMMUNITY_1010:2020_V6 seq 10 deny 0::/0 le 59', + 'ipv6 prefix-list PL_ALLOW_LIST_DEPLOYMENT_ID_5_COMMUNITY_1010:2020_V6 seq 20 deny 0::/0 ge 65', + 'ipv6 prefix-list PL_ALLOW_LIST_DEPLOYMENT_ID_5_COMMUNITY_1010:2020_V6 seq 30 permit fc00:20::/64 ge 65', + 'ipv6 prefix-list PL_ALLOW_LIST_DEPLOYMENT_ID_5_COMMUNITY_1010:2020_V6 seq 40 permit fc00:30::/64 ge 65', + 'bgp community-list standard COMMUNITY_ALLOW_LIST_DEPLOYMENT_ID_5_COMMUNITY_1010:2020 permit 1010:2020', + 'route-map ALLOW_LIST_DEPLOYMENT_ID_5_V4 permit 10', + ' match ip address prefix-list PL_ALLOW_LIST_DEPLOYMENT_ID_5_COMMUNITY_1010:2020_V4', + ' match community COMMUNITY_ALLOW_LIST_DEPLOYMENT_ID_5_COMMUNITY_1010:2020', + 'route-map ALLOW_LIST_DEPLOYMENT_ID_5_V6 permit 10', + ' match ipv6 address prefix-list PL_ALLOW_LIST_DEPLOYMENT_ID_5_COMMUNITY_1010:2020_V6', + ' match community COMMUNITY_ALLOW_LIST_DEPLOYMENT_ID_5_COMMUNITY_1010:2020', + 'route-map ALLOW_LIST_DEPLOYMENT_ID_5_V4 permit 65535', + ' set community no-export additive', + 'route-map ALLOW_LIST_DEPLOYMENT_ID_5_V6 permit 65535', + ' set community no-export additive', + "" + ], + [ + 'no route-map ALLOW_LIST_DEPLOYMENT_ID_5_V4 permit 10', + 'no route-map ALLOW_LIST_DEPLOYMENT_ID_5_V6 permit 10', + 'no ip prefix-list PL_ALLOW_LIST_DEPLOYMENT_ID_5_COMMUNITY_1010:2020_V4', + 'no ipv6 prefix-list PL_ALLOW_LIST_DEPLOYMENT_ID_5_COMMUNITY_1010:2020_V6', + 'no bgp community-list standard COMMUNITY_ALLOW_LIST_DEPLOYMENT_ID_5_COMMUNITY_1010:2020', + 'route-map ALLOW_LIST_DEPLOYMENT_ID_5_V4 permit 65535', + ' set community 123:123 additive', + 'route-map ALLOW_LIST_DEPLOYMENT_ID_5_V6 permit 65535', + ' set community 123:123 additive', + ] + ) + + +def test_del_handler_with_exiting_community_permit_action(): + set_del_test( + "DEL", + ("DEPLOYMENT_ID|5|1010:2020",), + [ + 'ip prefix-list PL_ALLOW_LIST_DEPLOYMENT_ID_5_COMMUNITY_1010:2020_V4 seq 10 deny 0.0.0.0/0 le 17', + 'ip prefix-list PL_ALLOW_LIST_DEPLOYMENT_ID_5_COMMUNITY_1010:2020_V4 seq 20 permit 10.20.30.0/24 ge 25', + 'ip prefix-list PL_ALLOW_LIST_DEPLOYMENT_ID_5_COMMUNITY_1010:2020_V4 seq 30 permit 30.50.0.0/16 ge 17', + 'ipv6 prefix-list PL_ALLOW_LIST_DEPLOYMENT_ID_5_COMMUNITY_1010:2020_V6 seq 10 deny 0::/0 le 59', + 'ipv6 prefix-list PL_ALLOW_LIST_DEPLOYMENT_ID_5_COMMUNITY_1010:2020_V6 seq 20 deny 0::/0 ge 65', + 'ipv6 prefix-list PL_ALLOW_LIST_DEPLOYMENT_ID_5_COMMUNITY_1010:2020_V6 seq 30 permit fc00:20::/64 ge 65', + 'ipv6 prefix-list PL_ALLOW_LIST_DEPLOYMENT_ID_5_COMMUNITY_1010:2020_V6 seq 40 permit fc00:30::/64 ge 65', + 'bgp community-list standard COMMUNITY_ALLOW_LIST_DEPLOYMENT_ID_5_COMMUNITY_1010:2020 permit 1010:2020', + 'route-map ALLOW_LIST_DEPLOYMENT_ID_5_V4 permit 10', + ' match ip address prefix-list PL_ALLOW_LIST_DEPLOYMENT_ID_5_COMMUNITY_1010:2020_V4', + ' match community COMMUNITY_ALLOW_LIST_DEPLOYMENT_ID_5_COMMUNITY_1010:2020', + 'route-map ALLOW_LIST_DEPLOYMENT_ID_5_V6 permit 10', + ' match ipv6 address prefix-list PL_ALLOW_LIST_DEPLOYMENT_ID_5_COMMUNITY_1010:2020_V6', + ' match community COMMUNITY_ALLOW_LIST_DEPLOYMENT_ID_5_COMMUNITY_1010:2020', + 'route-map ALLOW_LIST_DEPLOYMENT_ID_5_V4 permit 65535', + ' set community 123:123 additive', + 'route-map ALLOW_LIST_DEPLOYMENT_ID_5_V6 permit 65535', + ' set community 123:123 additive', + "" + ], + [ + 'no route-map ALLOW_LIST_DEPLOYMENT_ID_5_V4 permit 10', + 'no route-map ALLOW_LIST_DEPLOYMENT_ID_5_V6 permit 10', + 'no ip prefix-list PL_ALLOW_LIST_DEPLOYMENT_ID_5_COMMUNITY_1010:2020_V4', + 'no ipv6 prefix-list PL_ALLOW_LIST_DEPLOYMENT_ID_5_COMMUNITY_1010:2020_V6', + 'no bgp community-list standard COMMUNITY_ALLOW_LIST_DEPLOYMENT_ID_5_COMMUNITY_1010:2020', + ] + ) + +def test_del_handler_with_exiting_community_deny_action_global_deny(): + set_del_test( + "DEL", + ("DEPLOYMENT_ID|5|1010:2020",), + [ + 'ip prefix-list PL_ALLOW_LIST_DEPLOYMENT_ID_5_COMMUNITY_1010:2020_V4 seq 10 deny 0.0.0.0/0 le 17', + 'ip prefix-list PL_ALLOW_LIST_DEPLOYMENT_ID_5_COMMUNITY_1010:2020_V4 seq 20 permit 10.20.30.0/24 ge 25', + 'ip prefix-list PL_ALLOW_LIST_DEPLOYMENT_ID_5_COMMUNITY_1010:2020_V4 seq 30 permit 30.50.0.0/16 ge 17', + 'ipv6 prefix-list PL_ALLOW_LIST_DEPLOYMENT_ID_5_COMMUNITY_1010:2020_V6 seq 10 deny 0::/0 le 59', + 'ipv6 prefix-list PL_ALLOW_LIST_DEPLOYMENT_ID_5_COMMUNITY_1010:2020_V6 seq 20 deny 0::/0 ge 65', + 'ipv6 prefix-list PL_ALLOW_LIST_DEPLOYMENT_ID_5_COMMUNITY_1010:2020_V6 seq 30 permit fc00:20::/64 ge 65', + 'ipv6 prefix-list PL_ALLOW_LIST_DEPLOYMENT_ID_5_COMMUNITY_1010:2020_V6 seq 40 permit fc00:30::/64 ge 65', + 'bgp community-list standard COMMUNITY_ALLOW_LIST_DEPLOYMENT_ID_5_COMMUNITY_1010:2020 permit 1010:2020', + 'route-map ALLOW_LIST_DEPLOYMENT_ID_5_V4 permit 10', + ' match ip address prefix-list PL_ALLOW_LIST_DEPLOYMENT_ID_5_COMMUNITY_1010:2020_V4', + ' match community COMMUNITY_ALLOW_LIST_DEPLOYMENT_ID_5_COMMUNITY_1010:2020', + 'route-map ALLOW_LIST_DEPLOYMENT_ID_5_V6 permit 10', + ' match ipv6 address prefix-list PL_ALLOW_LIST_DEPLOYMENT_ID_5_COMMUNITY_1010:2020_V6', + ' match community COMMUNITY_ALLOW_LIST_DEPLOYMENT_ID_5_COMMUNITY_1010:2020', + 'route-map ALLOW_LIST_DEPLOYMENT_ID_5_V4 permit 65535', + ' set community no-export additive', + 'route-map ALLOW_LIST_DEPLOYMENT_ID_5_V6 permit 65535', + ' set community no-export additive', + "" + ], + [ + 'no route-map ALLOW_LIST_DEPLOYMENT_ID_5_V4 permit 10', + 'no route-map ALLOW_LIST_DEPLOYMENT_ID_5_V6 permit 10', + 'no ip prefix-list PL_ALLOW_LIST_DEPLOYMENT_ID_5_COMMUNITY_1010:2020_V4', + 'no ipv6 prefix-list PL_ALLOW_LIST_DEPLOYMENT_ID_5_COMMUNITY_1010:2020_V6', + 'no bgp community-list standard COMMUNITY_ALLOW_LIST_DEPLOYMENT_ID_5_COMMUNITY_1010:2020', + ], + "deny" + ) + + +def test_del_handler_with_exiting_community_permit_action_global_deny(): + set_del_test( + "DEL", + ("DEPLOYMENT_ID|5|1010:2020",), + [ + 'ip prefix-list PL_ALLOW_LIST_DEPLOYMENT_ID_5_COMMUNITY_1010:2020_V4 seq 10 deny 0.0.0.0/0 le 17', + 'ip prefix-list PL_ALLOW_LIST_DEPLOYMENT_ID_5_COMMUNITY_1010:2020_V4 seq 20 permit 10.20.30.0/24 ge 25', + 'ip prefix-list PL_ALLOW_LIST_DEPLOYMENT_ID_5_COMMUNITY_1010:2020_V4 seq 30 permit 30.50.0.0/16 ge 17', + 'ipv6 prefix-list PL_ALLOW_LIST_DEPLOYMENT_ID_5_COMMUNITY_1010:2020_V6 seq 10 deny 0::/0 le 59', + 'ipv6 prefix-list PL_ALLOW_LIST_DEPLOYMENT_ID_5_COMMUNITY_1010:2020_V6 seq 20 deny 0::/0 ge 65', + 'ipv6 prefix-list PL_ALLOW_LIST_DEPLOYMENT_ID_5_COMMUNITY_1010:2020_V6 seq 30 permit fc00:20::/64 ge 65', + 'ipv6 prefix-list PL_ALLOW_LIST_DEPLOYMENT_ID_5_COMMUNITY_1010:2020_V6 seq 40 permit fc00:30::/64 ge 65', + 'bgp community-list standard COMMUNITY_ALLOW_LIST_DEPLOYMENT_ID_5_COMMUNITY_1010:2020 permit 1010:2020', + 'route-map ALLOW_LIST_DEPLOYMENT_ID_5_V4 permit 10', + ' match ip address prefix-list PL_ALLOW_LIST_DEPLOYMENT_ID_5_COMMUNITY_1010:2020_V4', + ' match community COMMUNITY_ALLOW_LIST_DEPLOYMENT_ID_5_COMMUNITY_1010:2020', + 'route-map ALLOW_LIST_DEPLOYMENT_ID_5_V6 permit 10', + ' match ipv6 address prefix-list PL_ALLOW_LIST_DEPLOYMENT_ID_5_COMMUNITY_1010:2020_V6', + ' match community COMMUNITY_ALLOW_LIST_DEPLOYMENT_ID_5_COMMUNITY_1010:2020', + 'route-map ALLOW_LIST_DEPLOYMENT_ID_5_V4 permit 65535', + ' set community 123:123 additive', + 'route-map ALLOW_LIST_DEPLOYMENT_ID_5_V6 permit 65535', + ' set community 123:123 additive', + "" + ], + [ + 'no route-map ALLOW_LIST_DEPLOYMENT_ID_5_V4 permit 10', + 'no route-map ALLOW_LIST_DEPLOYMENT_ID_5_V6 permit 10', + 'no ip prefix-list PL_ALLOW_LIST_DEPLOYMENT_ID_5_COMMUNITY_1010:2020_V4', + 'no ipv6 prefix-list PL_ALLOW_LIST_DEPLOYMENT_ID_5_COMMUNITY_1010:2020_V6', + 'no bgp community-list standard COMMUNITY_ALLOW_LIST_DEPLOYMENT_ID_5_COMMUNITY_1010:2020', + 'route-map ALLOW_LIST_DEPLOYMENT_ID_5_V4 permit 65535', + ' set community no-export additive', + 'route-map ALLOW_LIST_DEPLOYMENT_ID_5_V6 permit 65535', + ' set community no-export additive', + ], + "deny" + ) + + def test_del_handler_no_community(): set_del_test( "DEL", @@ -164,6 +449,10 @@ def test_del_handler_no_community(): ' match ip address prefix-list PL_ALLOW_LIST_DEPLOYMENT_ID_5_COMMUNITY_empty_V4', 'route-map ALLOW_LIST_DEPLOYMENT_ID_5_V6 permit 30000', ' match ipv6 address prefix-list PL_ALLOW_LIST_DEPLOYMENT_ID_5_COMMUNITY_empty_V6', + 'route-map ALLOW_LIST_DEPLOYMENT_ID_5_V4 permit 65535', + ' set community 123:123 additive', + 'route-map ALLOW_LIST_DEPLOYMENT_ID_5_V6 permit 65535', + ' set community 123:123 additive', " " ], [ @@ -173,6 +462,75 @@ def test_del_handler_no_community(): 'no ipv6 prefix-list PL_ALLOW_LIST_DEPLOYMENT_ID_5_COMMUNITY_empty_V6', ] ) +def test_del_handler_with_no_community_deny_action(): + set_del_test( + "DEL", + ("DEPLOYMENT_ID|5",), + [ + 'ip prefix-list PL_ALLOW_LIST_DEPLOYMENT_ID_5_COMMUNITY_empty_V4 seq 10 deny 0.0.0.0/0 le 17', + 'ip prefix-list PL_ALLOW_LIST_DEPLOYMENT_ID_5_COMMUNITY_empty_V4 seq 20 permit 20.20.30.0/24 ge 25', + 'ip prefix-list PL_ALLOW_LIST_DEPLOYMENT_ID_5_COMMUNITY_empty_V4 seq 30 permit 40.50.0.0/16 ge 17', + 'ipv6 prefix-list PL_ALLOW_LIST_DEPLOYMENT_ID_5_COMMUNITY_empty_V6 seq 10 deny 0::/0 le 59', + 'ipv6 prefix-list PL_ALLOW_LIST_DEPLOYMENT_ID_5_COMMUNITY_empty_V6 seq 20 deny 0::/0 ge 65', + 'ipv6 prefix-list PL_ALLOW_LIST_DEPLOYMENT_ID_5_COMMUNITY_empty_V6 seq 30 permit fc01:20::/64 ge 65', + 'ipv6 prefix-list PL_ALLOW_LIST_DEPLOYMENT_ID_5_COMMUNITY_empty_V6 seq 40 permit fc01:30::/64 ge 65', + 'route-map ALLOW_LIST_DEPLOYMENT_ID_5_V4 permit 30000', + ' match ip address prefix-list PL_ALLOW_LIST_DEPLOYMENT_ID_5_COMMUNITY_empty_V4', + 'route-map ALLOW_LIST_DEPLOYMENT_ID_5_V6 permit 30000', + ' match ipv6 address prefix-list PL_ALLOW_LIST_DEPLOYMENT_ID_5_COMMUNITY_empty_V6', + 'route-map ALLOW_LIST_DEPLOYMENT_ID_5_V4 permit 65535', + ' set community no-export additive', + 'route-map ALLOW_LIST_DEPLOYMENT_ID_5_V6 permit 65535', + ' set community no-export additive', + "" + ], + [ + 'no route-map ALLOW_LIST_DEPLOYMENT_ID_5_V4 permit 30000', + 'no route-map ALLOW_LIST_DEPLOYMENT_ID_5_V6 permit 30000', + 'no ip prefix-list PL_ALLOW_LIST_DEPLOYMENT_ID_5_COMMUNITY_empty_V4', + 'no ipv6 prefix-list PL_ALLOW_LIST_DEPLOYMENT_ID_5_COMMUNITY_empty_V6', + 'route-map ALLOW_LIST_DEPLOYMENT_ID_5_V4 permit 65535', + ' set community 123:123 additive', + 'route-map ALLOW_LIST_DEPLOYMENT_ID_5_V6 permit 65535', + ' set community 123:123 additive', + ] + ) +def test_del_handler_with_no_community_permit_action_global_deny(): + set_del_test( + "DEL", + ("DEPLOYMENT_ID|5",), + [ + 'ip prefix-list PL_ALLOW_LIST_DEPLOYMENT_ID_5_COMMUNITY_empty_V4 seq 10 deny 0.0.0.0/0 le 17', + 'ip prefix-list PL_ALLOW_LIST_DEPLOYMENT_ID_5_COMMUNITY_empty_V4 seq 20 permit 20.20.30.0/24 ge 25', + 'ip prefix-list PL_ALLOW_LIST_DEPLOYMENT_ID_5_COMMUNITY_empty_V4 seq 30 permit 40.50.0.0/16 ge 17', + 'ipv6 prefix-list PL_ALLOW_LIST_DEPLOYMENT_ID_5_COMMUNITY_empty_V6 seq 10 deny 0::/0 le 59', + 'ipv6 prefix-list PL_ALLOW_LIST_DEPLOYMENT_ID_5_COMMUNITY_empty_V6 seq 20 deny 0::/0 ge 65', + 'ipv6 prefix-list PL_ALLOW_LIST_DEPLOYMENT_ID_5_COMMUNITY_empty_V6 seq 30 permit fc01:20::/64 ge 65', + 'ipv6 prefix-list PL_ALLOW_LIST_DEPLOYMENT_ID_5_COMMUNITY_empty_V6 seq 40 permit fc01:30::/64 ge 65', + 'route-map ALLOW_LIST_DEPLOYMENT_ID_5_V4 permit 30000', + ' match ip address prefix-list PL_ALLOW_LIST_DEPLOYMENT_ID_5_COMMUNITY_empty_V4', + 'route-map ALLOW_LIST_DEPLOYMENT_ID_5_V6 permit 30000', + ' match ipv6 address prefix-list PL_ALLOW_LIST_DEPLOYMENT_ID_5_COMMUNITY_empty_V6', + 'route-map ALLOW_LIST_DEPLOYMENT_ID_5_V4 permit 65535', + ' set community 123:123 additive', + 'route-map ALLOW_LIST_DEPLOYMENT_ID_5_V6 permit 65535', + ' set community 123:123 additive', + "" + ], + [ + 'no route-map ALLOW_LIST_DEPLOYMENT_ID_5_V4 permit 30000', + 'no route-map ALLOW_LIST_DEPLOYMENT_ID_5_V6 permit 30000', + 'no ip prefix-list PL_ALLOW_LIST_DEPLOYMENT_ID_5_COMMUNITY_empty_V4', + 'no ipv6 prefix-list PL_ALLOW_LIST_DEPLOYMENT_ID_5_COMMUNITY_empty_V6', + 'route-map ALLOW_LIST_DEPLOYMENT_ID_5_V4 permit 65535', + ' set community no-export additive', + 'route-map ALLOW_LIST_DEPLOYMENT_ID_5_V6 permit 65535', + ' set community no-export additive', + ], + "deny" + ) + + def test_set_handler_with_community_data_is_already_presented(): set_del_test( @@ -245,7 +603,12 @@ def test_del_handler_with_community_no_data(): set_del_test( "DEL", ("DEPLOYMENT_ID|5|1010:2020",), - [""], + [ + 'route-map ALLOW_LIST_DEPLOYMENT_ID_5_V4 permit 65535', + ' set community 123:123 additive', + 'route-map ALLOW_LIST_DEPLOYMENT_ID_5_V6 permit 65535', + ' set community 123:123 additive' + ], [] ) @@ -253,7 +616,12 @@ def test_del_handler_no_community_no_data(): set_del_test( "DEL", ("DEPLOYMENT_ID|5",), - [""], + [ + 'route-map ALLOW_LIST_DEPLOYMENT_ID_5_V4 permit 65535', + ' set community 123:123 additive', + 'route-map ALLOW_LIST_DEPLOYMENT_ID_5_V6 permit 65535', + ' set community 123:123 additive' + ], [] ) @@ -588,4 +956,4 @@ def test___get_default_action_permit_3(): mgr = construct_BGPAllowListMgr(constants) assert mgr._BGPAllowListMgr__get_default_action_community(data) == "123:123" -# FIXME: more testcases for coverage \ No newline at end of file +# FIXME: more testcases for coverage diff --git a/src/sonic-bgpcfgd/tests/test_bbr.py b/src/sonic-bgpcfgd/tests/test_bbr.py index 45b8aa7c8f0..b11277bae7b 100644 --- a/src/sonic-bgpcfgd/tests/test_bbr.py +++ b/src/sonic-bgpcfgd/tests/test_bbr.py @@ -252,7 +252,7 @@ def test___set_validation_4(): def test___set_validation_5(): __set_validation_common("all", {"status": "disabled"}, None, True) -def __set_prepare_config_common(status, bbr_enabled_pgs, available_pgs, expected_cmds): +def __set_prepare_config_common(status, bbr_enabled_pgs, available_pgs, expected_cmds, bbr_applied_pgs=None): cfg_mgr = MagicMock() common_objs = { 'directory': Directory(), @@ -269,10 +269,10 @@ def __set_prepare_config_common(status, bbr_enabled_pgs, available_pgs, expected } } m.bbr_enabled_pgs = bbr_enabled_pgs - m._BBRMgr__get_available_peer_groups = MagicMock(return_value = available_pgs) + m._BBRMgr__get_available_peer_groups = MagicMock(return_value = sorted(available_pgs)) cmds, peer_groups = m._BBRMgr__set_prepare_config(status) assert cmds == expected_cmds - assert set(peer_groups) == available_pgs + assert set(peer_groups) == (available_pgs if not bbr_applied_pgs else bbr_applied_pgs) def test___set_prepare_config_enabled(): __set_prepare_config_common("enabled", { @@ -327,7 +327,41 @@ def test___set_prepare_config_disabled_part(): ' no neighbor PEER_V4 allowas-in 1', ' no neighbor PEER_V6 allowas-in 1', ]) +def test___set_prepare_config_enabled_multiple_peers(): + __set_prepare_config_common("enabled", { + "PEER_V4": ["ipv4"], + "PEER_V6": ["ipv6"], + }, {"PEER_V4", "PEER_V4_DEPLOYMENT_ID_0", "PEER_V4_DEPLOYMENT_ID_1", "PEER_V6", "PEER_V6_DEPLOYMENT_ID_0", "PEER_V6_DEPLOYMENT_ID_1", "PEER_INVALID"}, + [ + 'router bgp 65500', + ' address-family ipv4', + ' neighbor PEER_V4 allowas-in 1', + ' neighbor PEER_V4_DEPLOYMENT_ID_0 allowas-in 1', + ' neighbor PEER_V4_DEPLOYMENT_ID_1 allowas-in 1', + ' address-family ipv6', + ' neighbor PEER_V6 allowas-in 1', + ' neighbor PEER_V6_DEPLOYMENT_ID_0 allowas-in 1', + ' neighbor PEER_V6_DEPLOYMENT_ID_1 allowas-in 1', + ], + {"PEER_V4", "PEER_V4_DEPLOYMENT_ID_0", "PEER_V4_DEPLOYMENT_ID_1", "PEER_V6", "PEER_V6_DEPLOYMENT_ID_0", "PEER_V6_DEPLOYMENT_ID_1"}) +def test___set_prepare_config_disabled_multiple_peers(): + __set_prepare_config_common("disabled", { + "PEER_V4": ["ipv4"], + "PEER_V6": ["ipv6"], + }, {"PEER_V4", "PEER_V4_DEPLOYMENT_ID_0", "PEER_V4_DEPLOYMENT_ID_1", "PEER_V6", "PEER_V6_DEPLOYMENT_ID_0", "PEER_V6_DEPLOYMENT_ID_1", "PEER_INVALID"}, + [ + 'router bgp 65500', + ' address-family ipv4', + ' no neighbor PEER_V4 allowas-in 1', + ' no neighbor PEER_V4_DEPLOYMENT_ID_0 allowas-in 1', + ' no neighbor PEER_V4_DEPLOYMENT_ID_1 allowas-in 1', + ' address-family ipv6', + ' no neighbor PEER_V6 allowas-in 1', + ' no neighbor PEER_V6_DEPLOYMENT_ID_0 allowas-in 1', + ' no neighbor PEER_V6_DEPLOYMENT_ID_1 allowas-in 1', + ], + {"PEER_V4", "PEER_V4_DEPLOYMENT_ID_0", "PEER_V4_DEPLOYMENT_ID_1", "PEER_V6", "PEER_V6_DEPLOYMENT_ID_0", "PEER_V6_DEPLOYMENT_ID_1"}) def test__get_available_peer_groups(): cfg_mgr = MagicMock() diff --git a/src/sonic-bgpcfgd/tests/test_bgp.py b/src/sonic-bgpcfgd/tests/test_bgp.py new file mode 100644 index 00000000000..a4c5ef99772 --- /dev/null +++ b/src/sonic-bgpcfgd/tests/test_bgp.py @@ -0,0 +1,112 @@ +from unittest.mock import MagicMock, patch + +import os +from bgpcfgd.directory import Directory +from bgpcfgd.template import TemplateFabric +from . import swsscommon_test +from .util import load_constants +from swsscommon import swsscommon +import bgpcfgd.managers_bgp + +TEMPLATE_PATH = os.path.abspath('../../dockers/docker-fpm-frr/frr') + +def constructor(): + cfg_mgr = MagicMock() + constants = load_constants()['constants'] + common_objs = { + 'directory': Directory(), + 'cfg_mgr': cfg_mgr, + 'tf': TemplateFabric(TEMPLATE_PATH), + 'constants': constants + } + + return_value_map = { + "['vtysh', '-c', 'show bgp vrfs json']": (0, "{\"vrfs\": {\"default\": {}}}", ""), + "['vtysh', '-c', 'show bgp vrf default neighbors json']": (0, "{\"10.10.10.1\": {}, \"20.20.20.1\": {}, \"fc00:10::1\": {}}", "") + } + + bgpcfgd.managers_bgp.run_command = lambda cmd: return_value_map[str(cmd)] + m = bgpcfgd.managers_bgp.BGPPeerMgrBase(common_objs, "CONFIG_DB", swsscommon.CFG_BGP_NEIGHBOR_TABLE_NAME, "general", True) + assert m.peer_type == "general" + assert m.check_neig_meta == ('bgp' in constants and 'use_neighbors_meta' in constants['bgp'] and constants['bgp']['use_neighbors_meta']) + + m.directory.put("CONFIG_DB", swsscommon.CFG_DEVICE_METADATA_TABLE_NAME, "localhost", {"bgp_asn": "65100"}) + m.directory.put("CONFIG_DB", swsscommon.CFG_LOOPBACK_INTERFACE_TABLE_NAME, "Loopback0|11.11.11.11/32", {}) + m.directory.put("CONFIG_DB", swsscommon.CFG_LOOPBACK_INTERFACE_TABLE_NAME, "Loopback0|FC00:1::32/128", {}) + m.directory.put("LOCAL", "local_addresses", "30.30.30.30", {"interface": "Ethernet4|30.30.30.30/24"}) + m.directory.put("LOCAL", "local_addresses", "fc00:20::20", {"interface": "Ethernet8|fc00:20::20/96"}) + m.directory.put("LOCAL", "interfaces", "Ethernet4|30.30.30.30/24", {"anything": "anything"}) + m.directory.put("LOCAL", "interfaces", "Ethernet8|fc00:20::20/96", {"anything": "anything"}) + + return m + +@patch('bgpcfgd.managers_bgp.log_info') +def test_update_peer_up(mocked_log_info): + m = constructor() + res = m.set_handler("10.10.10.1", {"admin_status": "up"}) + assert res, "Expect True return value for peer update" + mocked_log_info.assert_called_with("Peer 'default|10.10.10.1' admin state is set to 'up'") + +@patch('bgpcfgd.managers_bgp.log_info') +def test_update_peer_up_ipv6(mocked_log_info): + m = constructor() + res = m.set_handler("fc00:10::1", {"admin_status": "up"}) + assert res, "Expect True return value for peer update" + mocked_log_info.assert_called_with("Peer 'default|fc00:10::1' admin state is set to 'up'") + +@patch('bgpcfgd.managers_bgp.log_info') +def test_update_peer_down(mocked_log_info): + m = constructor() + res = m.set_handler("10.10.10.1", {"admin_status": "down"}) + assert res, "Expect True return value for peer update" + mocked_log_info.assert_called_with("Peer 'default|10.10.10.1' admin state is set to 'down'") + +@patch('bgpcfgd.managers_bgp.log_err') +def test_update_peer_no_admin_status(mocked_log_err): + m = constructor() + res = m.set_handler("10.10.10.1", {"anything": "anything"}) + assert res, "Expect True return value for peer update" + mocked_log_err.assert_called_with("Peer '(default|10.10.10.1)': Can't update the peer. Only 'admin_status' attribute is supported") + +@patch('bgpcfgd.managers_bgp.log_err') +def test_update_peer_invalid_admin_status(mocked_log_err): + m = constructor() + res = m.set_handler("10.10.10.1", {"admin_status": "invalid"}) + assert res, "Expect True return value for peer update" + mocked_log_err.assert_called_with("Peer 'default|10.10.10.1': Can't update the peer. It has wrong attribute value attr['admin_status'] = 'invalid'") + +def test_add_peer(): + m = constructor() + res = m.set_handler("30.30.30.1", {"local_addr": "30.30.30.30", "admin_status": "up"}) + assert res, "Expect True return value" + +def test_add_peer_ipv6(): + m = constructor() + res = m.set_handler("fc00:20::1", {"local_addr": "fc00:20::20", "admin_status": "up"}) + assert res, "Expect True return value" + +@patch('bgpcfgd.managers_bgp.log_warn') +def test_add_peer_no_local_addr(mocked_log_warn): + m = constructor() + res = m.set_handler("30.30.30.1", {"admin_status": "up"}) + assert res, "Expect True return value" + mocked_log_warn.assert_called_with("Peer 30.30.30.1. Missing attribute 'local_addr'") + +@patch('bgpcfgd.managers_bgp.log_debug') +def test_add_peer_invalid_local_addr(mocked_log_debug): + m = constructor() + res = m.set_handler("30.30.30.1", {"local_addr": "40.40.40.40", "admin_status": "up"}) + assert not res, "Expect False return value" + mocked_log_debug.assert_called_with("Peer '30.30.30.1' with local address '40.40.40.40' wait for the corresponding interface to be set") + +@patch('bgpcfgd.managers_bgp.log_info') +def test_del_handler(mocked_log_info): + m = constructor() + m.del_handler("10.10.10.1") + mocked_log_info.assert_called_with("Peer '(default|10.10.10.1)' has been removed") + +@patch('bgpcfgd.managers_bgp.log_warn') +def test_del_handler_nonexist_peer(mocked_log_warn): + m = constructor() + m.del_handler("40.40.40.1") + mocked_log_warn.assert_called_with("Peer '(default|40.40.40.1)' has not been found") diff --git a/src/sonic-bgpcfgd/tests/test_db.py b/src/sonic-bgpcfgd/tests/test_db.py new file mode 100644 index 00000000000..7078bc2735f --- /dev/null +++ b/src/sonic-bgpcfgd/tests/test_db.py @@ -0,0 +1,40 @@ +from unittest.mock import MagicMock, patch + +from bgpcfgd.directory import Directory +from bgpcfgd.template import TemplateFabric +from . import swsscommon_test +from swsscommon import swsscommon + +with patch.dict("sys.modules", swsscommon=swsscommon_test): + from bgpcfgd.managers_db import BGPDataBaseMgr + +def test_set_del_handler(): + cfg_mgr = MagicMock() + common_objs = { + 'directory': Directory(), + 'cfg_mgr': cfg_mgr, + 'tf': TemplateFabric(), + 'constants': {}, + } + m = BGPDataBaseMgr(common_objs, "CONFIG_DB", swsscommon.CFG_DEVICE_METADATA_TABLE_NAME) + assert m.constants == {} + + # test set_handler + res = m.set_handler("test_key1", {"test_value1"}) + assert res, "Returns always True" + assert "test_key1" in m.directory.get_slot(m.db_name, m.table_name) + assert m.directory.get(m.db_name, m.table_name, "test_key1") == {"test_value1"} + + res = m.set_handler("test_key2", {}) + assert res, "Returns always True" + assert "test_key2" in m.directory.get_slot(m.db_name, m.table_name) + assert m.directory.get(m.db_name, m.table_name, "test_key2") == {} + + # test del_handler + m.del_handler("test_key") + assert "test_key" not in m.directory.get_slot(m.db_name, m.table_name) + assert "test_key2" in m.directory.get_slot(m.db_name, m.table_name) + assert m.directory.get(m.db_name, m.table_name, "test_key2") == {} + + m.del_handler("test_key2") + assert "test_key2" not in m.directory.get_slot(m.db_name, m.table_name) diff --git a/src/sonic-bgpcfgd/tests/test_directory.py b/src/sonic-bgpcfgd/tests/test_directory.py new file mode 100644 index 00000000000..b20803ed32c --- /dev/null +++ b/src/sonic-bgpcfgd/tests/test_directory.py @@ -0,0 +1,57 @@ +from unittest.mock import MagicMock, patch +from bgpcfgd.directory import Directory + +@patch('bgpcfgd.directory.log_err') +def test_directory(mocked_log_err): + test_values = { + "key1": { + "key1_1": { + "key1_1_1": "value1_1_1", + "key1_1_2": "value1_1_2", + "key1_1_3": "value1_1_3" + } + }, + "key2": { + "value2" + } + } + + directory = Directory() + + # Put test values + directory.put("db_name", "table", "key1", test_values["key1"]) + directory.put("db_name", "table", "key2", test_values["key2"]) + + # Test get_path() + assert directory.get_path("db_name", "table", "") == test_values + assert directory.get_path("db_name", "table", "key1/key1_1/key1_1_1") == "value1_1_1" + assert directory.get_path("db_name", "table", "key1/key_nonexist") == None + + # Test path_exist() + assert directory.path_exist("db_name", "table", "key1/key1_1/key1_1_1") + assert not directory.path_exist("db_name", "table_nonexist", "") + assert not directory.path_exist("db_name", "table", "key1/key_nonexist") + + # Test get_slot() + assert directory.get_slot("db_name", "table") == test_values + + # Test get() + assert directory.get("db_name", "table", "key2") == test_values["key2"] + + # Test remove() + directory.remove("db_name", "table", "key2") + assert not directory.path_exist("db_name", "table", "key2") + + # Test remove() with invalid input + directory.remove("db_name", "table_nonexist", "key2") + mocked_log_err.assert_called_with("Directory: Can't remove key 'key2' from slot 'db_name__table_nonexist'. The slot doesn't exist") + directory.remove("db_name", "table", "key_nonexist") + mocked_log_err.assert_called_with("Directory: Can't remove key 'key_nonexist' from slot 'db_name__table'. The key doesn't exist") + + # Test remove_slot() + directory.remove_slot("db_name", "table") + assert not directory.available("db_name", "table") + + # Test remove_slot() with nonexist table + directory.remove_slot("db_name", "table_nonexist") + mocked_log_err.assert_called_with("Directory: Can't remove slot 'db_name__table_nonexist'. The slot doesn't exist") diff --git a/src/sonic-bgpcfgd/tests/test_frr.py b/src/sonic-bgpcfgd/tests/test_frr.py index 47bdcaa82f1..5a20281fa55 100644 --- a/src/sonic-bgpcfgd/tests/test_frr.py +++ b/src/sonic-bgpcfgd/tests/test_frr.py @@ -1,6 +1,68 @@ -from bgpcfgd.frr import FRR - +from unittest.mock import patch +import bgpcfgd.frr +import pytest def test_constructor(): - f = FRR(["abc", "cde"]) + f = bgpcfgd.frr.FRR(["abc", "cde"]) assert f.daemons == ["abc", "cde"] + +def test_wait_for_daemons(): + bgpcfgd.frr.run_command = lambda cmd, **kwargs: (0, ["abc", "cde"], "") + f = bgpcfgd.frr.FRR(["abc", "cde"]) + f.wait_for_daemons(5) + +def test_wait_for_daemons_fail(): + bgpcfgd.frr.run_command = lambda cmd, **kwargs: (0, ["abc", "non_expected"], "") + f = bgpcfgd.frr.FRR(["abc", "cde"]) + with pytest.raises(Exception): + assert f.wait_for_daemons(5) + +def test_wait_for_daemons_error(): + bgpcfgd.frr.run_command = lambda cmd, **kwargs: (1, ["abc", "cde"], "some error") + f = bgpcfgd.frr.FRR(["abc", "cde"]) + with pytest.raises(Exception): + assert f.wait_for_daemons(5) + +def test_get_config(): + bgpcfgd.frr.run_command = lambda cmd: (0, "expected config", "") + f = bgpcfgd.frr.FRR(["abc", "cde"]) + out = f.get_config() + assert out == "expected config" + +@patch('bgpcfgd.frr.log_crit') +def test_get_config_fail(mocked_log_crit): + bgpcfgd.frr.run_command = lambda cmd: (1, "some config", "some error") + f = bgpcfgd.frr.FRR(["abc", "cde"]) + out = f.get_config() + assert out == "" + mocked_log_crit.assert_called_with("can't update running config: rc=1 out='some config' err='some error'") + +def test_write(): + bgpcfgd.frr.run_command = lambda cmd: (0, "some output", "") + f = bgpcfgd.frr.FRR(["abc", "cde"]) + res = f.write("config context") + assert res, "Expect True return value" + +def test_write_fail(): + bgpcfgd.frr.run_command = lambda cmd: (1, "some output", "some error") + f = bgpcfgd.frr.FRR(["abc", "cde"]) + res = f.write("config context") + assert not res, "Expect False return value" + +def test_restart_peer_groups(): + bgpcfgd.frr.run_command = lambda cmd: (0, "some output", "") + f = bgpcfgd.frr.FRR(["abc", "cde"]) + res = f.restart_peer_groups(["pg_1", "pg_2"]) + assert res, "Expect True return value" + +@patch('bgpcfgd.frr.log_crit') +def test_restart_peer_groups_fail(mocked_log_crit): + return_value_map = { + "['vtysh', '-c', 'clear bgp peer-group pg_1 soft in']": (0, "", ""), + "['vtysh', '-c', 'clear bgp peer-group pg_2 soft in']": (1, "some output", "some error") + } + bgpcfgd.frr.run_command = lambda cmd: return_value_map[str(cmd)] + f = bgpcfgd.frr.FRR(["abc", "cde"]) + res = f.restart_peer_groups(["pg_1", "pg_2"]) + assert not res, "Expect False return value" + mocked_log_crit.assert_called_with("Can't restart bgp peer-group 'pg_2'. rc='1', out='some output', err='some error'") diff --git a/src/sonic-bgpcfgd/tests/test_intf.py b/src/sonic-bgpcfgd/tests/test_intf.py new file mode 100644 index 00000000000..74fa8e471ac --- /dev/null +++ b/src/sonic-bgpcfgd/tests/test_intf.py @@ -0,0 +1,52 @@ +from unittest.mock import MagicMock, patch + +from bgpcfgd.directory import Directory +from bgpcfgd.template import TemplateFabric +from swsscommon import swsscommon +from bgpcfgd.managers_intf import InterfaceMgr + +def set_handler_test(manager, key, value): + res = manager.set_handler(key, value) + assert res, "Returns always True" + assert manager.directory.get(manager.db_name, manager.table_name, key) == value + +def del_handler_test(manager, key): + manager.del_handler(key) + assert manager.directory.get_path(manager.db_name, manager.table_name, key) == None + +@patch('bgpcfgd.managers_intf.log_warn') +def test_intf(mocked_log_warn): + cfg_mgr = MagicMock() + common_objs = { + 'directory': Directory(), + 'cfg_mgr': cfg_mgr, + 'tf': TemplateFabric(), + 'constants': {}, + } + m = InterfaceMgr(common_objs, "CONFIG_DB", swsscommon.CFG_VLAN_INTF_TABLE_NAME) + + set_handler_test(m, "Vlan1000", {}) + set_handler_test(m, "Vlan1000|192.168.0.1/21", {}) + + # test set handler with invalid ip network + res = m.set_handler("Vlan1000|invalid_netowrk", {}) + assert res, "Returns always True" + mocked_log_warn.assert_called_with("Subnet 'invalid_netowrk' format is wrong for interface 'Vlan1000'") + + del_handler_test(m, "Vlan1000") + del_handler_test(m, "Vlan1000|192.168.0.1/21") + del_handler_test(m, "Vlan1000|invalid_netowrk") + mocked_log_warn.assert_called_with("Subnet 'invalid_netowrk' format is wrong for interface 'Vlan1000'") + +def test_intf_ipv6(): + cfg_mgr = MagicMock() + common_objs = { + 'directory': Directory(), + 'cfg_mgr': cfg_mgr, + 'tf': TemplateFabric(), + 'constants': {}, + } + m = InterfaceMgr(common_objs, "CONFIG_DB", swsscommon.CFG_VLAN_INTF_TABLE_NAME) + + set_handler_test(m, "Vlan1000|fc02:1000::1/64", {}) + del_handler_test(m, "Vlan1000|fc02:1000::1/64") diff --git a/src/sonic-bgpcfgd/tests/test_setsrc.py b/src/sonic-bgpcfgd/tests/test_setsrc.py new file mode 100644 index 00000000000..5d1a8190883 --- /dev/null +++ b/src/sonic-bgpcfgd/tests/test_setsrc.py @@ -0,0 +1,62 @@ +from unittest.mock import MagicMock, patch + +import os +from bgpcfgd.directory import Directory +from bgpcfgd.template import TemplateFabric +from copy import deepcopy +from . import swsscommon_test +from swsscommon import swsscommon + +with patch.dict("sys.modules", swsscommon=swsscommon_test): + from bgpcfgd.managers_setsrc import ZebraSetSrc + +TEMPLATE_PATH = os.path.abspath('../../dockers/docker-fpm-frr/frr') + +def constructor(): + cfg_mgr = MagicMock() + common_objs = { + 'directory': Directory(), + 'cfg_mgr': cfg_mgr, + 'tf': TemplateFabric(TEMPLATE_PATH), + 'constants': {}, + } + + m = ZebraSetSrc(common_objs, "STATE_DB", swsscommon.STATE_INTERFACE_TABLE_NAME) + assert m.lo_ipv4 == None + assert m.lo_ipv6 == None + + return m + +@patch('bgpcfgd.managers_setsrc.log_info') +def test_set_handler(mocked_log_info): + m = constructor() + res = m.set_handler("Loopback0|10.1.0.32/32", {"state": "ok"}) + assert res, "Returns always True" + mocked_log_info.assert_called_with("The 'set src' configuration with Loopback0 ip '10.1.0.32' has been scheduled to be added") + +@patch('bgpcfgd.managers_setsrc.log_err') +def test_set_handler_no_slash(mocked_log_err): + m = constructor() + res = m.set_handler("Loopback0|10.1.0.32", {"state": "ok"}) + assert res, "Returns always True" + mocked_log_err.assert_called_with("Wrong Loopback0 ip prefix: '10.1.0.32'") + +@patch('bgpcfgd.managers_setsrc.log_info') +def test_set_handler_ipv6(mocked_log_info): + m = constructor() + res = m.set_handler("Loopback0|FC00:1::32/128", {"state": "ok"}) + assert res, "Returns always True" + mocked_log_info.assert_called_with("The 'set src' configuration with Loopback0 ip 'FC00:1::32' has been scheduled to be added") + +@patch('bgpcfgd.managers_setsrc.log_err') +def test_set_handler_invalid_ip(mocked_log_err): + m = constructor() + res = m.set_handler("Loopback0|invalid/ip", {"state": "ok"}) + assert res, "Returns always True" + mocked_log_err.assert_called_with("Got ambiguous ip address 'invalid'") + +@patch('bgpcfgd.managers_setsrc.log_warn') +def test_del_handler(mocked_log_warn): + m = constructor() + m.del_handler("Loopback0|10.1.0.32/32") + mocked_log_warn.assert_called_with("Delete command is not supported for 'zebra set src' templates") diff --git a/src/sonic-build-hooks/hooks/git b/src/sonic-build-hooks/hooks/git new file mode 100755 index 00000000000..644a01d5fe1 --- /dev/null +++ b/src/sonic-build-hooks/hooks/git @@ -0,0 +1,76 @@ +#!/bin/bash + +parse_config(){ + . /usr/local/share/buildinfo/scripts/buildinfo_base.sh + REAL_COMMAND=$(get_command git) + + version_file=$VERSION_PATH/versions-git + new_version_file=$BUILD_VERSION_PATH/versions-git + + MODE_CLONE=0 + # parse input parameters + for i in "$@" + do + if [[ $i == "clone" ]];then + MODE_CLONE=1 + fi + done +} + +get_clone_path(){ + # get paremater of clone path + while (( "$#" )); do + case $1 in + -b|--branch|--reference|--reference-if-able|-c|--config|--origin|-u|--upload-pack|-j|--jobs|--depth|--dissociate) + shift 2 + ;; + clone|-l|--local|--no-hardlinks|-s|--shared|--dissociate|-q|--quiet|-v|--verbose|--progress|--server-option=*|--bare|--sparse|--filter=*|--template=*|--mirror|--reference|--shallow-*|--no-tags|--recurse-submodules*|--remote-submodules|--no-remote-submodules|--separate-git-dir*) + shift 1 + ;; + *) + if [[ $URL == "" ]];then + URL=$1 + else + clone_PATH=$1 + fi + shift 1 + ;; + esac + done + + # if not specific clone path, get default clone path + [ -z $clone_PATH ] && clone_PATH=`echo $URL | rev | awk -F/ '{print$1}' | rev | awk -F. '{print$1}'` +} + +main(){ + parse_config "$@" + + # execute git. + $REAL_COMMAND "$@" + result=$? + + # if sub command is not "clone", exit + if [[ $MODE_CLONE != 1 ]];then + exit $result + fi + + get_clone_path "$@" + pushd $clone_PATH &> /dev/null + commit_latest=`$REAL_COMMAND log -n 1 | head -n 1| awk '{print$2}'` + [ -f $version_file ] && commit=`grep $URL $version_file | awk -F, '{print$2}'` + + # control version or record version file + if [[ $ENABLE_VERSION_CONTROL_GIT == "y" ]];then + # control version + [ ! -z $commit ] && $REAL_COMMAND reset --hard $commit &> /dev/null + else + # record version file + echo "$URL==$commit_latest" >> $new_version_file + sort $new_version_file -o $new_version_file -u &> /dev/null + fi + popd &> /dev/null + + exit $result +} + +main "$@" diff --git a/src/sonic-config-engine/minigraph.py b/src/sonic-config-engine/minigraph.py index f30e668251a..06b799cdeff 100644 --- a/src/sonic-config-engine/minigraph.py +++ b/src/sonic-config-engine/minigraph.py @@ -84,6 +84,7 @@ def parse_device(device): hwsku = None name = None deployment_id = None + cluster = None for node in device: if node.tag == str(QName(ns, "Address")): @@ -100,11 +101,13 @@ def parse_device(device): deployment_id = node.text elif node.tag == str(QName(ns, "ElementType")): d_type = node.text + elif node.tag == str(QName(ns, "ClusterName")): + cluster = node.text if d_type is None and str(QName(ns3, "type")) in device.attrib: d_type = device.attrib[str(QName(ns3, "type"))] - return (lo_prefix, lo_prefix_v6, mgmt_prefix, name, hwsku, d_type, deployment_id) + return (lo_prefix, lo_prefix_v6, mgmt_prefix, name, hwsku, d_type, deployment_id, cluster) def calculate_lcm_for_ecmp (nhdevices_bank_map, nhip_bank_map): banks_enumerated = {} @@ -244,8 +247,10 @@ def parse_png(png, hname, dpg_ecmp_content = None): if child.tag == str(QName(ns, "Devices")): for device in child.findall(str(QName(ns, "Device"))): - (lo_prefix, lo_prefix_v6, mgmt_prefix, name, hwsku, d_type, deployment_id) = parse_device(device) + (lo_prefix, lo_prefix_v6, mgmt_prefix, name, hwsku, d_type, deployment_id, cluster) = parse_device(device) device_data = {'lo_addr': lo_prefix, 'type': d_type, 'mgmt_addr': mgmt_prefix, 'hwsku': hwsku } + if cluster: + device_data['cluster'] = cluster if deployment_id: device_data['deployment_id'] = deployment_id if lo_prefix_v6: @@ -253,9 +258,7 @@ def parse_png(png, hname, dpg_ecmp_content = None): devices[name] = device_data if name == hname: - cluster = device.find(str(QName(ns, "ClusterName"))) - - if cluster != None and cluster.text != None and "str" in cluster.text.lower(): + if cluster and "str" in cluster.lower(): is_storage_device = True if child.tag == str(QName(ns, "DeviceInterfaceLinks")): @@ -380,8 +383,10 @@ def parse_asic_png(png, asic_name, hostname): if child.tag == str(QName(ns, "Devices")): for device in child.findall(str(QName(ns, "Device"))): - (lo_prefix, lo_prefix_v6, mgmt_prefix, name, hwsku, d_type, deployment_id) = parse_device(device) + (lo_prefix, lo_prefix_v6, mgmt_prefix, name, hwsku, d_type, deployment_id, cluster) = parse_device(device) device_data = {'lo_addr': lo_prefix, 'type': d_type, 'mgmt_addr': mgmt_prefix, 'hwsku': hwsku } + if cluster: + device_data['cluster'] = cluster if deployment_id: device_data['deployment_id'] = deployment_id if lo_prefix_v6: @@ -780,6 +785,7 @@ def parse_meta(meta, hname): region = None cloudtype = None resource_type = None + kube_data = {} device_metas = meta.find(str(QName(ns, "Devices"))) for device in device_metas.findall(str(QName(ns1, "DeviceMetadata"))): if device.find(str(QName(ns1, "Name"))).text.lower() == hname.lower(): @@ -808,7 +814,11 @@ def parse_meta(meta, hname): cloudtype = value elif name == "ResourceType": resource_type = value - return syslog_servers, dhcp_servers, ntp_servers, tacacs_servers, mgmt_routes, erspan_dst, deployment_id, region, cloudtype, resource_type + elif name == "KubernetesEnabled": + kube_data["enable"] = value + elif name == "KubernetesServerIp": + kube_data["ip"] = value + return syslog_servers, dhcp_servers, ntp_servers, tacacs_servers, mgmt_routes, erspan_dst, deployment_id, region, cloudtype, resource_type, kube_data def parse_linkmeta(meta, hname): @@ -1097,6 +1107,7 @@ def parse_xml(filename, platform=None, port_config_file=None, asic_name=None, hw host_lo_intfs = None is_storage_device = False local_devices = [] + kube_data = {} # hostname is the asic_name, get the asic_id from the asic_name if asic_name is not None: @@ -1133,7 +1144,7 @@ def parse_xml(filename, platform=None, port_config_file=None, asic_name=None, hw elif child.tag == str(QName(ns, "UngDec")): (u_neighbors, u_devices, _, _, _, _, _, _) = parse_png(child, hostname, None) elif child.tag == str(QName(ns, "MetadataDeclaration")): - (syslog_servers, dhcp_servers, ntp_servers, tacacs_servers, mgmt_routes, erspan_dst, deployment_id, region, cloudtype, resource_type) = parse_meta(child, hostname) + (syslog_servers, dhcp_servers, ntp_servers, tacacs_servers, mgmt_routes, erspan_dst, deployment_id, region, cloudtype, resource_type, kube_data) = parse_meta(child, hostname) elif child.tag == str(QName(ns, "LinkMetadataDeclaration")): linkmetas = parse_linkmeta(child, hostname) elif child.tag == str(QName(ns, "DeviceInfos")): @@ -1174,6 +1185,18 @@ def parse_xml(filename, platform=None, port_config_file=None, asic_name=None, hw } } + cluster = [devices[key] for key in devices if key.lower() == hostname.lower()][0].get('cluster', "") + if cluster: + results['DEVICE_METADATA']['localhost']['cluster'] = cluster + + if kube_data: + results['KUBERNETES_MASTER'] = { + 'SERVER': { + 'disable': str(kube_data.get('enable', '0') == '0'), + 'ip': kube_data.get('ip', '') + } + } + results['PEER_SWITCH'] = get_peer_switch_info(linkmetas, devices) if bool(results['PEER_SWITCH']): @@ -1512,8 +1535,10 @@ def get_mux_cable_entries(mux_cable_ports, neighbors, devices): server_ipv4_lo_prefix = ipaddress.ip_network(UNICODE_TYPE(server_ipv4_lo_addr)) entry['server_ipv4'] = str(server_ipv4_lo_prefix) - if 'lo_addr_v6' in devices[neighbor]: - entry['server_ipv6'] = devices[neighbor]['lo_addr_v6'] + if 'lo_addr_v6' in devices[neighbor] and devices[neighbor]['lo_addr_v6'] is not None: + server_ipv6_lo_addr = devices[neighbor]['lo_addr_v6'].split('/')[0] + server_ipv6_lo_prefix = ipaddress.ip_network(UNICODE_TYPE(server_ipv6_lo_addr)) + entry['server_ipv6'] = str(server_ipv6_lo_prefix) mux_cable_table[intf] = entry else: print("Warning: no server IPv4 loopback found for {}, skipping mux cable table entry".format(neighbor)) @@ -1522,7 +1547,7 @@ def get_mux_cable_entries(mux_cable_ports, neighbors, devices): def parse_device_desc_xml(filename): root = ET.parse(filename).getroot() - (lo_prefix, lo_prefix_v6, mgmt_prefix, hostname, hwsku, d_type, _) = parse_device(root) + (lo_prefix, lo_prefix_v6, mgmt_prefix, hostname, hwsku, d_type, _, _) = parse_device(root) results = {} results['DEVICE_METADATA'] = {'localhost': { diff --git a/src/sonic-config-engine/portconfig.py b/src/sonic-config-engine/portconfig.py index d20212eb55a..478198e5af8 100644 --- a/src/sonic-config-engine/portconfig.py +++ b/src/sonic-config-engine/portconfig.py @@ -5,7 +5,7 @@ import re import sys - from swsssdk import ConfigDBConnector + from swsscommon.swsscommon import ConfigDBConnector from sonic_py_common import device_info except ImportError as e: raise ImportError("%s - required module not found" % str(e)) @@ -24,6 +24,7 @@ BRKOUT_MODE = "default_brkout_mode" CUR_BRKOUT_MODE = "brkout_mode" INTF_KEY = "interfaces" +OPTIONAL_HWSKU_ATTRIBUTES = ["fec", "autoneg"] BRKOUT_PATTERN = r'(\d{1,3})x(\d{1,3}G)(\[\d{1,3}G\])?(\((\d{1,3})\))?' @@ -250,6 +251,12 @@ def parse_platform_json_file(hwsku_json_file, platform_json_file): brkout_mode = hwsku_dict[INTF_KEY][intf][BRKOUT_MODE] child_ports = get_child_ports(intf, brkout_mode, platform_json_file) + + # take optional fields from hwsku.json + for key, item in hwsku_dict[INTF_KEY][intf].items(): + if key in OPTIONAL_HWSKU_ATTRIBUTES: + child_ports.get(intf)[key] = item + ports.update(child_ports) if not ports: diff --git a/src/sonic-config-engine/redis_bcc.py b/src/sonic-config-engine/redis_bcc.py index 1045e0c5c8b..c9d3ebca239 100644 --- a/src/sonic-config-engine/redis_bcc.py +++ b/src/sonic-config-engine/redis_bcc.py @@ -19,11 +19,11 @@ def load_bytecode(self, bucket): return code = self._client.get(self._client.LOGLEVEL_DB, self.REDIS_HASH, bucket.key) if code is not None: - bucket.bytecode_from_string(b64decode(code)) + bucket.bytecode_from_string(b64decode(code.encode())) def dump_bytecode(self, bucket): if self._client is None: return self._client.set(self._client.LOGLEVEL_DB, self.REDIS_HASH, - bucket.key, b64encode(bucket.bytecode_to_string())) + bucket.key, b64encode(bucket.bytecode_to_string()).decode()) diff --git a/src/sonic-config-engine/setup.py b/src/sonic-config-engine/setup.py index c9dfd3609b9..d167e056643 100644 --- a/src/sonic-config-engine/setup.py +++ b/src/sonic-config-engine/setup.py @@ -9,7 +9,7 @@ 'ipaddress==1.0.23', 'lxml==4.6.2', 'netaddr==0.8.0', - 'pyyaml==5.3.1', + 'pyyaml==5.4.1', 'sonic-py-common', ] diff --git a/src/sonic-config-engine/sonic-cfggen b/src/sonic-config-engine/sonic-cfggen index af638c2c282..0f9ffafad63 100755 --- a/src/sonic-config-engine/sonic-cfggen +++ b/src/sonic-config-engine/sonic-cfggen @@ -43,7 +43,7 @@ from portconfig import get_port_config, get_breakout_mode from redis_bcc import RedisBytecodeCache from sonic_py_common.multi_asic import get_asic_id_from_name, is_multi_asic from sonic_py_common import device_info -from swsssdk import SonicV2Connector, ConfigDBConnector, SonicDBConfig, ConfigDBPipeConnector +from swsscommon.swsscommon import SonicV2Connector, ConfigDBConnector, SonicDBConfig, ConfigDBPipeConnector PY3x = sys.version_info >= (3, 0) diff --git a/src/sonic-config-engine/tests/sample_output/py2/docker-dhcp-relay.supervisord.conf b/src/sonic-config-engine/tests/sample_output/py2/docker-dhcp-relay.supervisord.conf index a213a251786..dad758947f2 100644 --- a/src/sonic-config-engine/tests/sample_output/py2/docker-dhcp-relay.supervisord.conf +++ b/src/sonic-config-engine/tests/sample_output/py2/docker-dhcp-relay.supervisord.conf @@ -14,7 +14,7 @@ buffer_size=50 [eventlistener:supervisor-proc-exit-listener] command=/usr/bin/supervisor-proc-exit-listener --container-name dhcp_relay -events=PROCESS_STATE_EXITED +events=PROCESS_STATE_EXITED,PROCESS_STATE_RUNNING autostart=true autorestart=unexpected diff --git a/src/sonic-config-engine/tests/sample_output/py3/docker-dhcp-relay.supervisord.conf b/src/sonic-config-engine/tests/sample_output/py3/docker-dhcp-relay.supervisord.conf index d5338b18cfa..e2135d05296 100644 --- a/src/sonic-config-engine/tests/sample_output/py3/docker-dhcp-relay.supervisord.conf +++ b/src/sonic-config-engine/tests/sample_output/py3/docker-dhcp-relay.supervisord.conf @@ -14,7 +14,7 @@ buffer_size=50 [eventlistener:supervisor-proc-exit-listener] command=/usr/bin/supervisor-proc-exit-listener --container-name dhcp_relay -events=PROCESS_STATE_EXITED +events=PROCESS_STATE_EXITED,PROCESS_STATE_RUNNING autostart=true autorestart=unexpected diff --git a/src/sonic-config-engine/tests/simple-sample-graph-case.xml b/src/sonic-config-engine/tests/simple-sample-graph-case.xml index d9a21158c4a..95f501200c8 100644 --- a/src/sonic-config-engine/tests/simple-sample-graph-case.xml +++ b/src/sonic-config-engine/tests/simple-sample-graph-case.xml @@ -303,7 +303,7 @@ 10.10.10.1/32 - fe80::0001/128 + fe80::0001/80 10.0.0.1/32 @@ -390,6 +390,16 @@ 10.0.10.7;10.0.10.8 + + KubernetesEnabled + + 0 + + + KubernetesServerIp + + 10.10.10.10 + diff --git a/src/sonic-config-engine/tests/t0-sample-graph.xml b/src/sonic-config-engine/tests/t0-sample-graph.xml index 237a2ff0f53..63f892fe6d0 100644 --- a/src/sonic-config-engine/tests/t0-sample-graph.xml +++ b/src/sonic-config-engine/tests/t0-sample-graph.xml @@ -237,11 +237,28 @@ fortyGigE0/4;fortyGigE0/8;fortyGigE0/12;fortyGigE0/16;fortyGigE0/20;fortyGigE0/24;fortyGigE0/28;fortyGigE0/32;fortyGigE0/36;fortyGigE0/40;fortyGigE0/44;fortyGigE0/48;fortyGigE0/52;fortyGigE0/56;fortyGigE0/60;fortyGigE0/64;fortyGigE0/68;fortyGigE0/72;fortyGigE0/76;fortyGigE0/80;fortyGigE0/84;fortyGigE0/88;fortyGigE0/92;fortyGigE0/96 False 0.0.0.0/0 + 192.0.0.1;192.0.0.2 1000 1000 192.168.0.0/27 + + + + + Vlan99 + fortyGigE0/100 + False + 0.0.0.0/0 + + UserDefinedL2Vlan + 192.0.0.1;192.0.0.2 + 99 + 99 + + + diff --git a/src/sonic-config-engine/tests/test_minigraph_case.py b/src/sonic-config-engine/tests/test_minigraph_case.py index cf8a7557aeb..64e0bb09d73 100644 --- a/src/sonic-config-engine/tests/test_minigraph_case.py +++ b/src/sonic-config-engine/tests/test_minigraph_case.py @@ -1,3 +1,4 @@ +import json import os import subprocess @@ -145,6 +146,11 @@ def test_minigraph_deployment_id(self): output = self.run_script(argument) self.assertEqual(output.strip(), "1") + def test_minigraph_cluster(self): + argument = '-m "' + self.sample_graph + '" -p "' + self.port_config + '" -v "DEVICE_METADATA[\'localhost\'][\'cluster\']"' + output = self.run_script(argument) + self.assertEqual(output.strip(), "AAA00PrdStr00") + def test_minigraph_neighbor_metadata(self): argument = '-m "' + self.sample_graph + '" -p "' + self.port_config + '" -v "DEVICE_NEIGHBOR_METADATA"' @@ -165,7 +171,7 @@ def test_minigraph_neighbor_metadata(self): 'server1': { 'hwsku': 'server-sku', 'lo_addr': '10.10.10.1/32', - 'lo_addr_v6': 'fe80::0001/128', + 'lo_addr_v6': 'fe80::0001/80', 'mgmt_addr': '10.0.0.1/32', 'type': 'Server' }, @@ -195,6 +201,12 @@ def test_metadata_tacacs(self): output = self.run_script(argument) self.assertEqual(output.strip(), "{'10.0.10.7': {'priority': '1', 'tcp_port': '49'}, '10.0.10.8': {'priority': '1', 'tcp_port': '49'}}") + def test_metadata_kube(self): + argument = '-m "' + self.sample_graph + '" -p "' + self.port_config + '" -v "KUBERNETES_MASTER[\'SERVER\']"' + output = self.run_script(argument) + self.assertEqual(json.loads(output.strip().replace("'", "\"")), + json.loads('{"ip": "10.10.10.10", "disable": "True"}')) + def test_minigraph_mgmt_port(self): argument = '-m "' + self.sample_graph + '" -p "' + self.port_config + '" -v "MGMT_PORT"' output = self.run_script(argument) @@ -275,12 +287,12 @@ def test_minigraph_mux_cable_table(self): 'Ethernet4': { 'state': 'auto', 'server_ipv4': '10.10.10.1/32', - 'server_ipv6': 'fe80::0001/128' + 'server_ipv6': 'fe80::1/128' }, 'Ethernet8': { 'state': 'auto', 'server_ipv4': '10.10.10.2/32', - 'server_ipv6': 'fe80::0002/128' + 'server_ipv6': 'fe80::2/128' } } @@ -289,4 +301,3 @@ def test_minigraph_mux_cable_table(self): utils.to_dict(output.strip()), expected_table ) - \ No newline at end of file diff --git a/src/sonic-ctrmgrd/ctrmgr/container b/src/sonic-ctrmgrd/ctrmgr/container index ca0963946f4..ff3706a6a7a 100755 --- a/src/sonic-ctrmgrd/ctrmgr/container +++ b/src/sonic-ctrmgrd/ctrmgr/container @@ -100,12 +100,12 @@ def read_state(feature): [(CURRENT_OWNER, "none"), (REMOTE_STATE, "none"), (CONTAINER_ID, "")]) -def docker_action(action, feature): +def docker_action(action, feature, **kwargs): """ Execute docker action """ try: client = docker.from_env() container = client.containers.get(feature) - getattr(container, action)() + getattr(container, action)(**kwargs) syslog.syslog(syslog.LOG_INFO, "docker cmd: {} for {}".format(action, feature)) return 0 @@ -161,7 +161,7 @@ def container_id(feature): return data.get(CONTAINER_ID, feature) -def container_start(feature): +def container_start(feature, **kwargs): """ Starts a container for given feature. @@ -219,7 +219,7 @@ def container_start(feature): update_data(feature, data) if (start_val & START_LOCAL): - ret = docker_action("start", feature) + ret = docker_action("start", feature, **kwargs) if (start_val & START_KUBE): set_label(feature, True) @@ -227,7 +227,7 @@ def container_start(feature): return ret -def container_stop(feature): +def container_stop(feature, **kwargs): """ Stops the running container for this feature. @@ -257,7 +257,7 @@ def container_stop(feature): set_label(feature, False) if docker_id: - docker_action("stop", docker_id) + docker_action("stop", docker_id, **kwargs) else: syslog.syslog( syslog.LOG_ERR if current_owner != "none" else syslog.LOG_INFO, @@ -289,7 +289,7 @@ def container_stop(feature): debug_msg("END") -def container_kill(feature): +def container_kill(feature, **kwargs): """ Kills the running container for this feature. @@ -314,7 +314,7 @@ def container_kill(feature): set_label(feature, False) if docker_id: - docker_action("kill", docker_id) + docker_action("kill", docker_id, **kwargs) else: syslog.syslog( @@ -325,7 +325,7 @@ def container_kill(feature): debug_msg("END") -def container_wait(feature): +def container_wait(feature, **kwargs): """ Waits on the running container for this feature. @@ -378,30 +378,34 @@ def container_wait(feature): format(feature)) else: debug_msg("END -- transitioning to docker wait") - docker_action("wait", docker_id) + docker_action("wait", docker_id, **kwargs) def main(): parser=argparse.ArgumentParser(description="container commands for start/stop/wait/kill/id") parser.add_argument("action", choices=["start", "stop", "wait", "kill", "id"]) + parser.add_argument('-t', '--timeout', type=int, help='container action timeout value', default=None) parser.add_argument("name") args = parser.parse_args() + kwargs = {} if args.action == "start": - container_start(args.name) + container_start(args.name, **kwargs) elif args.action == "stop": - container_stop(args.name) + if args.timeout is not None: + kwargs['timeout'] = args.timeout + container_stop(args.name, **kwargs) elif args.action == "kill": - container_kill(args.name) + container_kill(args.name, **kwargs) elif args.action == "wait": - container_wait(args.name) + container_wait(args.name, **kwargs) elif args.action == "id": - id = container_id(args.name) + id = container_id(args.name, **kwargs) print(id) diff --git a/src/sonic-device-data/src/Makefile b/src/sonic-device-data/src/Makefile index 10525fdeb27..5ecefbf3796 100644 --- a/src/sonic-device-data/src/Makefile +++ b/src/sonic-device-data/src/Makefile @@ -14,4 +14,7 @@ test: for f in $$(find ../../../device -name platform.json); do ./platform_json_checker $$f done + for f in $$(find ../../../device -name hwsku.json); do + ./hwsku_json_checker $$f + done popd diff --git a/src/sonic-device-data/tests/hwsku_json_checker b/src/sonic-device-data/tests/hwsku_json_checker new file mode 100755 index 00000000000..6fd3d82c4cf --- /dev/null +++ b/src/sonic-device-data/tests/hwsku_json_checker @@ -0,0 +1,91 @@ +#!/usr/bin/env python3 + +import glob +import json +import re +import sys + +# Global variable +PORT_ATTRIBUTES = ["default_brkout_mode"] +OPTIONAL_PORT_ATTRIBUTES = ["fec", "autoneg"] +PORT_REG = "Ethernet(\d+)" +HWSKU_JSON = '*hwsku.json' +INTF_KEY = "interfaces" + +def usage(): + print("Usage: " + sys.argv[0] + " ") + sys.exit(1) + +def check_port_attr(port_attr): + for each_key in port_attr: + if each_key not in PORT_ATTRIBUTES and each_key not in OPTIONAL_PORT_ATTRIBUTES: + print("Error: " + each_key + " is not the correct Port attribute.") + return False + if not port_attr[each_key]: + print("Error: " + each_key + " has no value.") + return False + if not isinstance(port_attr[each_key], str): + print("Error:value type of " + each_key + " must be string.") + return False + return True + +def check_file(hwsku_json_file): + try: + hwsku_cap_file = open(hwsku_json_file,"r") + hwsku_data_data = hwsku_cap_file.read() + hwsku_dict = json.loads(hwsku_data_data) + + for each_port in hwsku_dict[INTF_KEY]: + # Validate port at top level + port_id = re.search(PORT_REG, each_port) + if port_id is None: + print("Error: Unknown Interface " + str(each_port) + " at top level") + return False + + port_attr = hwsku_dict[INTF_KEY][each_port] + + # Check mandatory attributes + for each_key in PORT_ATTRIBUTES: + if each_key not in port_attr: + print("Error: " + each_key + " of " + each_port + " is/are missing") + return False + + #Validate port attributes for each port + if not check_port_attr(port_attr): + return False + except IOError: + print("Error: Cannot open file " + hwsku_json_file) + return False + except ValueError as e: + print("Error in parsing json file " + hwsku_json_file + " ") + print(str(e)) + return False + return True + +def main(argv): + if len(argv) > 0 and argv[0] == "-h": + usage() + + # Load target file + if len(argv) == 0: + files = glob.glob(HWSKU_JSON) + else: + files = argv + + all_good = True + + for f in files: + good = check_file(f) + if good: + print("File " + f + " passed validity check") + else: + print("File " + f + " failed validity check") + + all_good = all_good and good + + if not all_good: + sys.exit(-1) + + +if __name__ == "__main__": + main(sys.argv[1:]) diff --git a/src/sonic-device-data/tests/permitted_list b/src/sonic-device-data/tests/permitted_list index 8feb791875e..997250cbf6b 100644 --- a/src/sonic-device-data/tests/permitted_list +++ b/src/sonic-device-data/tests/permitted_list @@ -1,3 +1,13 @@ +sai_trap_group_priority +use_all_splithorizon_groups +riot_enable +sai_tunnel_support +riot_overlay_l3_intf_mem_size +riot_overlay_l3_egress_mem_size +l3_ecmp_levels +riot_overlay_ecmp_resilient_hash_size +flow_init_mode +sai_load_hw_config arl_clean_timeout_usec asf_mem_profile bcm_linkscan_interval @@ -219,3 +229,4 @@ serdes_fec_enable pbmp_gport_stack reglist_enable scache_filename +host_as_route_disable diff --git a/src/sonic-frr-mgmt-framework/.gitignore b/src/sonic-frr-mgmt-framework/.gitignore new file mode 100644 index 00000000000..f6411e4ee01 --- /dev/null +++ b/src/sonic-frr-mgmt-framework/.gitignore @@ -0,0 +1,12 @@ +.eggs/ +build/ +dist/ +*.egg-info/ +frrcfgd/*.pyc +tests/*.pyc +tests/__pycache__/ +.idea +.coverage +frrcfgd/__pycache__/ +venv +tests/.coverage* diff --git a/src/sonic-frr-mgmt-framework/frrcfgd/__init__.py b/src/sonic-frr-mgmt-framework/frrcfgd/__init__.py new file mode 100644 index 00000000000..e69de29bb2d diff --git a/src/sonic-frr-mgmt-framework/frrcfgd/frrcfgd.py b/src/sonic-frr-mgmt-framework/frrcfgd/frrcfgd.py new file mode 100755 index 00000000000..e3b8c3f264c --- /dev/null +++ b/src/sonic-frr-mgmt-framework/frrcfgd/frrcfgd.py @@ -0,0 +1,3795 @@ +#!/usr/bin/env python + +import copy +import subprocess +import time +import syslog +import os +from swsssdk import ConfigDBConnector +import socket +import threading +import queue +import signal +import re +import logging +import netaddr +import io +import struct + +class CachedDataWithOp: + OP_NONE = 0 + OP_ADD = 1 + OP_DELETE = 2 + OP_UPDATE = 3 + + STAT_SUCC = 0 + STAT_FAIL = 1 + + def __init__(self, data = None, op = OP_NONE): + self.data = data + self.op = op + self.status = self.STAT_FAIL + + def __repr__(self): + op_str = '' + if self.op == self.OP_NONE: + op_str = 'NONE' + elif self.op == self.OP_ADD: + op_str = 'ADD' + elif self.op == self.OP_DELETE: + op_str = 'DELETE' + elif self.op == self.OP_UPDATE: + op_str = 'UPDATE' + return '(%s, %s)' % (self.data, op_str) + +bgpd_client = None + +def g_run_command(table, command, use_bgpd_client, daemons, ignore_fail = False): + syslog.syslog(syslog.LOG_DEBUG, "execute command {} for table {}.".format(command, table)) + if not command.startswith('vtysh '): + use_bgpd_client = False + if use_bgpd_client: + if not bgpd_client.run_vtysh_command(table, command, daemons) and not ignore_fail: + syslog.syslog(syslog.LOG_ERR, 'command execution failure. Command: "{}"'.format(command)) + return False + else: + p = subprocess.Popen(command, shell=True, stdout=subprocess.PIPE) + stdout = p.communicate()[0] + p.wait() + if p.returncode != 0 and not ignore_fail: + syslog.syslog(syslog.LOG_ERR, '[bgp cfgd] command execution returned {}. Command: "{}", stdout: "{}"'.\ + format(p.returncode, command, stdout)) + return False + return True + +def extract_cmd_daemons(cmd_str): + # daemon list could be given within brackets at head of input lines + dm_mark = re.match(r'\[(?P.+)\]', cmd_str) + if dm_mark is not None and 'daemons' in dm_mark.groupdict(): + cmd_str = cmd_str[dm_mark.end():] + daemons = dm_mark.groupdict()['daemons'].split(',') + else: + daemons = None + return (daemons, cmd_str) + +class BgpdClientMgr(threading.Thread): + VTYSH_MARK = 'vtysh ' + PROXY_SERVER_ADDR = '/etc/frr/bgpd_client_sock' + ALL_DAEMONS = ['bgpd', 'zebra', 'staticd', 'bfdd', 'ospfd', 'pimd'] + TABLE_DAEMON = { + 'DEVICE_METADATA': ['bgpd'], + 'BGP_GLOBALS': ['bgpd'], + 'BGP_GLOBALS_AF': ['bgpd'], + 'PREFIX_SET': ['bgpd'], + 'COMMUNITY_SET': ['bgpd'], + 'EXTENDED_COMMUNITY_SET': ['bgpd'], + 'ROUTE_MAP': ['zebra', 'bgpd', 'ospfd'], + 'PREFIX': ['zebra', 'bgpd', 'ospfd', 'pimd'], + 'BGP_PEER_GROUP': ['bgpd'], + 'BGP_NEIGHBOR': ['bgpd'], + 'BGP_PEER_GROUP_AF': ['bgpd'], + 'BGP_NEIGHBOR_AF': ['bgpd'], + 'BGP_GLOBALS_LISTEN_PREFIX': ['bgpd'], + 'NEIGHBOR_SET': ['bgpd'], + 'NEXTHOP_SET': ['bgpd'], + 'TAG_SET': ['bgpd'], + 'AS_PATH_SET': ['bgpd'], + 'ROUTE_REDISTRIBUTE': ['bgpd'], + 'BGP_GLOBALS_AF_AGGREGATE_ADDR': ['bgpd'], + 'BGP_GLOBALS_AF_NETWORK': ['bgpd'], + 'VRF': ['zebra'], + 'BGP_GLOBALS_EVPN_VNI': ['bgpd'], + 'BGP_GLOBALS_EVPN_RT': ['bgpd'], + 'BGP_GLOBALS_EVPN_VNI_RT': ['bgpd'], + 'BFD_PEER': ['bfdd'], + 'BFD_PEER_SINGLE_HOP': ['bfdd'], + 'BFD_PEER_MULTI_HOP': ['bfdd'], + 'IP_SLA': ['iptrackd'], + 'OSPFV2_ROUTER': ['ospfd'], + 'OSPFV2_ROUTER_AREA': ['ospfd'], + 'OSPFV2_ROUTER_AREA_VIRTUAL_LINK': ['ospfd'], + 'OSPFV2_ROUTER_AREA_NETWORK': ['ospfd'], + 'OSPFV2_ROUTER_AREA_POLICY_ADDRESS_RANGE': ['ospfd'], + 'OSPFV2_ROUTER_DISTRIBUTE_ROUTE': ['ospfd'], + 'OSPFV2_INTERFACE': ['ospfd'], + 'OSPFV2_ROUTER_PASSIVE_INTERFACE': ['ospfd'], + 'STATIC_ROUTE': ['staticd'], + 'PIM_GLOBALS': ['pimd'], + 'PIM_INTERFACE': ['pimd'], + 'IGMP_INTERFACE': ['pimd'], + 'IGMP_INTERFACE_QUERY': ['pimd'], + } + VTYSH_CMD_DAEMON = [(r'show (ip|ipv6) route($|\s+\S+)', ['zebra']), + (r'show ip mroute($|\s+\S+)', ['pimd']), + (r'show bfd($|\s+\S+)', ['bfdd']), + (r'clear bfd($|\s+\S+)', ['bfdd']), + (r'clear ip mroute($|\s+\S+)', ['pimd']), + (r'clear ip pim($|\s+\S+)', ['pimd']), + (r'show ip ospf($|\s+\S+)', ['ospfd']), + (r'show ip pim($|\s+\S+)', ['pimd']), + (r'show ip igmp($|\s+\S+)', ['pimd']), + (r'clear ip ospf($|\s+\S+)', ['ospfd']), + (r'show ip sla($|\s+\S+)', ['iptrackd']), + (r'clear ip sla($|\s+\S+)', ['iptrackd']), + (r'clear ip igmp($|\s+\S+)', ['pimd']), + (r'.*', ['bgpd'])] + @staticmethod + def __create_proxy_socket(): + try: + os.unlink(BgpdClientMgr.PROXY_SERVER_ADDR) + except OSError: + if os.path.exists(BgpdClientMgr.PROXY_SERVER_ADDR): + raise + sock = socket.socket(socket.AF_UNIX, socket.SOCK_STREAM) + sock.bind(BgpdClientMgr.PROXY_SERVER_ADDR) + sock.listen(1) + return sock + @staticmethod + def __get_reply(sock): + reply_msg = None + ret_code = None + msg_buf = io.StringIO() + while True: + try: + rd_msg = sock.recv(16384) + msg_buf.write(rd_msg.decode()) + except socket.timeout: + syslog.syslog(syslog.LOG_ERR, 'socket reading timeout') + break + if len(rd_msg) < 4: + rd_msg = msg_buf.getvalue() + if len(rd_msg) < 4: + continue + msg_tail = rd_msg[-4:] + if isinstance(msg_tail, str): + msg_tail = bytes(msg_tail, 'utf-8') + if msg_tail[0] == 0 and msg_tail[1] == 0 and msg_tail[2] == 0: + ret_code = msg_tail[3] + reply_msg = msg_buf.getvalue()[:-4] + break + msg_buf.close() + return (ret_code, reply_msg) + @staticmethod + def __send_data(sock, data): + if isinstance(data, str): + data = bytes(data, 'utf-8') + sock.sendall(data) + def __create_frr_client(self): + self.client_socks = {} + for daemon in self.ALL_DAEMONS: + sock = socket.socket(socket.AF_UNIX, socket.SOCK_STREAM) + serv_addr = '/run/frr/%s.vty' % daemon + retry_cnt = 0 + while True: + try: + sock.connect(serv_addr) + break + except socket.error as msg: + syslog.syslog(syslog.LOG_ERR, 'failed to connect to frr daemon %s: %s' % (daemon, msg)) + retry_cnt += 1 + if retry_cnt > 100 or not main_loop: + syslog.syslog(syslog.LOG_ERR, 're-tried too many times, give up') + for _, sock in self.client_socks.items(): + sock.close() + return False + time.sleep(2) + continue + sock.settimeout(120) + self.client_socks[daemon] = sock + for daemon, sock in self.client_socks.items(): + syslog.syslog(syslog.LOG_DEBUG, 'send initial enable command to %s' % daemon) + try: + self.__send_data(sock, 'enable\0') + except socket.error as msg: + syslog.syslog(syslog.LOG_ERR, 'failed to send initial enable command to %s' % daemon) + return False + ret_code, reply = self.__get_reply(sock) + if ret_code is None: + syslog.syslog(syslog.LOG_ERR, 'failed to get command response for enable command from %s' % daemon) + return False + if ret_code != 0: + syslog.syslog(syslog.LOG_ERR, 'enable command failed: ret_code=%d' % ret_code) + syslog.syslog(syslog.LOG_ERR, reply) + return False + return True + def __init__(self): + super(BgpdClientMgr, self).__init__(name = 'VTYSH sub-process manager') + if not self.__create_frr_client(): + syslog.syslog(syslog.LOG_ERR, 'failed to create socket to FRR daemon') + raise RuntimeError('connect to FRR daemon failed') + self.proxy_running = True + self.lock = threading.Lock() + self.proxy_sock = self.__create_proxy_socket() + self.cmd_to_daemon = [] + for pat, daemons in self.VTYSH_CMD_DAEMON: + try: + self.cmd_to_daemon.append((re.compile(pat), daemons)) + except Exception: + syslog.syslog(syslog.LOG_ERR, 'invalid regex format: %s' % pat) + continue + def __get_cmd_daemons(self, cmd_list): + cmn_daemons = None + for cmd in cmd_list: + found = False + for re_comp, daemons in self.cmd_to_daemon: + if re_comp.match(cmd.strip()) is not None: + found = True + break + if not found: + syslog.syslog(syslog.LOG_ERR, 'no matched daemons found for command %s' % cmd) + return None + if cmn_daemons is None: + cmn_daemons = set(daemons) + else: + cmn_daemons = cmn_daemons.intersection(set(daemons)) + if len(cmn_daemons) == 0: + return [] + return list(cmn_daemons) + def __proc_command(self, command, daemons): + syslog.syslog(syslog.LOG_DEBUG, 'VTYSH CMD: %s daemons: %s' % (command, daemons)) + resp = '' + ret_val = False + for daemon in daemons: + sock = self.client_socks.get(daemon, None) + if sock is None: + syslog.syslog(syslog.LOG_ERR, 'daemon %s is not connected' % daemon) + continue + try: + self.__send_data(sock, command + '\0') + except socket.error as msg: + syslog.syslog(syslog.LOG_ERR, 'failed to send command to frr daemon: %s' % msg) + return (False, None) + ret_code, reply = self.__get_reply(sock) + if ret_code is None or ret_code != 0: + if ret_code is None: + syslog.syslog(syslog.LOG_ERR, 'failed to get reply from frr daemon') + continue + else: + syslog.syslog(syslog.LOG_DEBUG, '[%s] command return code: %d' % (daemon, ret_code)) + syslog.syslog(syslog.LOG_DEBUG, reply) + else: + # command is running successfully by at least one daemon + ret_val = True + resp += reply + return (ret_val, resp) + def run_vtysh_command(self, table, command, daemons): + if not command.startswith(self.VTYSH_MARK): + syslog.syslog(syslog.LOG_ERR, 'command %s is not for vtysh config' % command) + return False + cmd_line = command[len(self.VTYSH_MARK):] + cmd_list = re.findall(r"-c\s+'([^']+)'\s*", cmd_line) + cmd_list.append('end') + if daemons is None: + daemons = self.TABLE_DAEMON.get(table, None) + if daemons is None: + daemons = self.__get_cmd_daemons(cmd_list) + if daemons is None or len(daemons) == 0: + syslog.syslog(syslog.LOG_ERR, 'no common daemon list found for given commands') + return False + ret_val = True + with self.lock: + for cmd in cmd_list: + succ, _ = self.__proc_command(cmd.strip(), daemons) + if not succ: + ret_val = False + return ret_val + @staticmethod + def __read_all(sock, data_len): + in_buf = io.StringIO() + left_len = data_len + while left_len > 0: + data = sock.recv(left_len) + if data is None: + break + in_buf.write(data) + left_len -= len(data) + return in_buf.getvalue() + def shutdown(self): + syslog.syslog(syslog.LOG_DEBUG, 'terminate bgpd client manager') + if self.is_alive(): + self.proxy_running = False + sock = socket.socket(socket.AF_UNIX, socket.SOCK_STREAM) + try: + sock.connect(self.PROXY_SERVER_ADDR) + finally: + sock.close() + self.join() + for _, sock in self.client_socks.items(): + sock.close() + def run(self): + syslog.syslog(syslog.LOG_DEBUG, 'entering VTYSH proxy thread') + while self.proxy_running: + syslog.syslog(syslog.LOG_DEBUG, 'waiting for client connection ...') + conn_sock, clnt_addr = self.proxy_sock.accept() + if not self.proxy_running: + conn_sock.close() + break + try: + syslog.syslog(syslog.LOG_DEBUG, 'client connection from %s' % clnt_addr) + data = self.__read_all(conn_sock, 4) + if len(data) == 4: + data_len = struct.unpack('>I', data)[0] + in_cmd = self.__read_all(conn_sock, data_len) + if len(in_cmd) == data_len: + daemons, in_cmd = extract_cmd_daemons(in_cmd) + in_lines = in_cmd.splitlines() + if daemons is None: + daemons = self.__get_cmd_daemons(in_lines) + if daemons is not None and len(daemons) > 0: + with self.lock: + for line in in_lines: + _, reply = self.__proc_command(line.strip(), daemons) + if reply is not None: + self.__send_data(conn_sock, reply) + else: + syslog.syslog(syslog.LOG_ERR, 'failed running VTYSH command') + else: + syslog.syslog(syslog.LOG_ERR, 'could not find common daemons for input commands') + else: + syslog.syslog(syslog.LOG_ERR, 'read data of length %d is not expected length %d' % (data_len, len(in_cmd))) + else: + syslog.syslog(syslog.LOG_ERR, 'invalid data length %d' % len(data)) + except socket.error as msg: + syslog.syslog(syslog.LOG_ERR, 'socket writing failed: %s' % msg) + finally: + syslog.syslog(syslog.LOG_DEBUG, 'closing data socket from client') + conn_sock.close() + syslog.syslog(syslog.LOG_DEBUG, 'leaving VTYSH proxy thread') +class BGPPeerGroup: + def __init__(self, vrf): + self.vrf = vrf + self.ref_nbrs = set() + +def get_command_cmn(daemon, cmd_str, op, st_idx, vals, bool_values): + chk_val = None + if op == CachedDataWithOp.OP_DELETE: + if bool_values is not None and len(bool_values) >= 3: + # set to default if given + cmd_enable = bool_values[2] + else: + cmd_enable = False + else: + cmd_enable = True + if bool_values is not None: + if len(vals) <= st_idx: + syslog.syslog(syslog.LOG_ERR, 'No bool token of index %d for running cmd: %s' % (st_idx, cmd_str)) + return None + chk_val = vals[st_idx] + if type(chk_val) is dict: + cmd_enable = False + for _, v in chk_val.items(): + if not v[1]: + continue + if v[0] == bool_values[0]: + cmd_enable = True + break + else: + if chk_val == bool_values[0]: + cmd_enable = True + elif chk_val == bool_values[1]: + cmd_enable = False + else: + syslog.syslog(syslog.LOG_ERR, 'Input token %s is neither %s or %s for cmd: %s' % + (chk_val, bool_values[0], bool_values[1], cmd_str)) + return None + else: + cmd_enable = True + cmd_args = [] + for idx in range(len(vals)): + if bool_values is not None and idx == st_idx: + continue + cmd_args.append(CommandArgument(daemon, cmd_enable, vals[idx])) + return [cmd_str.format(*cmd_args, no = CommandArgument(daemon, cmd_enable))] + +def hdl_set_extcomm(daemon, cmd_str, op, st_idx, args, is_inline): + if is_inline: + if type(args[0]) is list: + com_list = args[0] + else: + com_list = [args[0]] + else: + com_set = daemon.extcomm_set_list.get(args[0], None) + if com_set is None or not com_set.is_configurable(): + syslog.syslog(syslog.LOG_ERR, 'extended community set %s not found or configured' % args[0]) + return None + com_list = com_set.mbr_list + rt_cnt = soo_cnt = 0 + for comm in com_list: + if comm.startswith(CommunityList.RT_TYPE_MARK): + rt_cnt += 1 + elif comm.startswith(CommunityList.SOO_TYPE_MARK): + soo_cnt += 1 + cmd_list = [] + if op != CachedDataWithOp.OP_DELETE: + for comm_type in ['rt', 'soo']: + cmd_list.append(('no set extcommunity %s' % comm_type, True)) + if rt_cnt > 0: + new_args = ((args[0], True),) + args[1:] + cmd_list += get_command_cmn(daemon, cmd_str, op, st_idx, new_args, None) + if soo_cnt > 0: + new_args = ((args[0], False),) + args[1:] + cmd_list += get_command_cmn(daemon, cmd_str, op, st_idx, new_args, None) + return cmd_list + +def hdl_set_asn(daemon, cmd_str, op, st_idx, args, data): + if 0 not in args[0]: + return None + if op == CachedDataWithOp.OP_DELETE: + if args[0][0][1]: + args[0][1] = ('0', True) + else: + args[0].pop(1, None) + op = CachedDataWithOp.OP_UPDATE + return get_command_cmn(daemon, cmd_str, op, st_idx, args, data) + +def hdl_set_asn_list(daemon, cmd_str, op, st_idx, args, data): + if op == CachedDataWithOp.OP_DELETE: + args = ('',) + return get_command_cmn(daemon, cmd_str, op, st_idx, args, data) + +def hdl_set_pim_hello_parms (daemon, cmd_str, op, st_idx, args, data): + if op == CachedDataWithOp.OP_DELETE: + args = ('',) + return get_command_cmn(daemon, cmd_str, op, st_idx, args, data) + +def handle_rmap_set_metric(daemon, cmd_str, op, st_idx, args, data): + cmd_list = [] + + syslog.syslog(syslog.LOG_INFO, 'handle_rmap_set_metric cmd_str {} op {} st_idx {} args {} data {}'.format( + cmd_str, op, st_idx, args, data)) + + no_op = 'no ' if op == CachedDataWithOp.OP_DELETE else '' + + arg_len = len(args) + metric_action = args[0] if arg_len >= 1 else '' + metric_value = args[1] if arg_len >= 2 else '' + med_value = args[2] if arg_len >= 3 else '' + metric_param = '' + + if metric_action != '' : + if metric_value != '' : + if metric_action == 'METRIC_SET_VALUE' : + metric_param = "{}".format(metric_value) + elif metric_action == 'METRIC_ADD_VALUE' : + metric_param = "+{}".format(metric_value) + elif metric_action == 'METRIC_SUBTRACT_VALUE' : + metric_param = "-{}".format(metric_value) + if metric_action == 'METRIC_SET_RTT' : + metric_param = "rtt" + elif metric_action == 'METRIC_ADD_RTT' : + metric_param = "+rtt" + elif metric_action == 'METRIC_SUBTRACT_RTT' : + metric_param = "-rtt" + + if metric_param == '' and med_value != '' : + metric_param = "{}".format(med_value) + + if op == CachedDataWithOp.OP_DELETE : + metric_param = '' + else : + if metric_param == '' : + syslog.syslog(syslog.LOG_ERR, 'handle_rmap_set_metric not set for {}'.format(args)) + return None + + cmd_list.append(cmd_str.format(CommandArgument(daemon, True, no_op), + CommandArgument(daemon, True, metric_param))) + return cmd_list + +class BGPKeyMapInfo: + def __init__(self, cmd_str, hdlr, data): + self.daemons, self.run_cmd = extract_cmd_daemons(cmd_str) + if hdlr is None: + self.hdl_func = get_command_cmn + else: + self.hdl_func = hdlr + self.data = data + def same_daemons(self, other): + dset = lambda d: set() if d is None else set(d) + return dset(self.daemons) == dset(other.daemons) + def __eq__(self, other): + return self.same_daemons(other) and self.run_cmd == other.run_cmd + def __ne__(self, other): + return not self.same_daemons(other) or self.run_cmd != other.run_cmd + def __hash__(self): + return hash(self.run_cmd) + def get_command(self, daemon, op, st_idx, *vals): + return self.hdl_func(daemon, self.run_cmd, op, st_idx, vals, self.data) + def __str__(self): + ret_str = '[CMD: %s' % self.run_cmd + if self.hdl_func == get_command_cmn and self.data is not None: + ret_str += ' BOOL: %s/%s' % (self.data[0], self.data[1]) + if len(self.data) >= 3: + ret_str += ' DFT: %s' % self.data[2] + ret_str += ']' + return ret_str + +class BGPKeyMapList(list): + def __init__(self, key_map_list, table_name, table_key = None): + super(BGPKeyMapList, self).__init__() + self.table_name = table_name + self.table_key = table_key + for key_map in key_map_list: + if len(key_map) < 2: + continue + db_field = key_map[0] + cmd_str = key_map[1] + hdl_data = None + hdl_func = None + if len(key_map) >= 3: + if callable(key_map[2]): + hdl_func = key_map[2] + if len(key_map) >= 4: + hdl_data = key_map[3] + else: + if len(key_map[2]) < 2: + continue + hdl_data = key_map[2] + fld_name, fld_key = self.get_map_field_key(db_field) + if fld_name is not None: + if table_key is not None and fld_name in table_key and table_key[fld_name] != fld_key: + continue + if type(db_field) is str: + db_field = fld_name + elif type(db_field) is list: + db_field = copy.copy(db_field) + try: + idx = db_field.index('|'.join([fld_name, fld_key])) + db_field[idx] = fld_name + except ValueError: + pass + super(BGPKeyMapList, self).append((db_field, BGPKeyMapInfo(cmd_str, hdl_func, hdl_data))) + def __eq__(self, other): + return super(BGPKeyMapList, self).__eq__(other) and self.table_name == other.table_name and self.table_key == other.table_key + def __ne__(self, other): + return super(BGPKeyMapList, self).__ne__(other) or self.table_name != other.table_name or self.table_key != other.table_key + @staticmethod + def get_map_field_key(field): + if type(field) is str: + field = [field] + elif type(field) is not list: + return (None, None) + for idx in range(len(field)): + tokens = field[idx].split('|', 1) + if len(tokens) == 2: + return tokens + return (None, None) + @staticmethod + def get_cmd_data(key_list, req_idx_list, opt_idx_list, data, chg_list, no_chg_list, merge_data, is_del): + for idx in req_idx_list: + if idx not in chg_list and idx not in no_chg_list: + syslog.syslog(syslog.LOG_DEBUG, 'mandatory key %s of idx %d not found in list' % (key_list[idx], idx)) + return None + if merge_data: + op = CachedDataWithOp.OP_DELETE if is_del else CachedDataWithOp.OP_UPDATE + cmd_data = {} + for idx in chg_list: + key = key_list[idx] + cmd_data[idx] = (data[key].data, True) + for idx in no_chg_list: + key = key_list[idx] + cmd_data[idx] = (data[key].data, False) + return ((cmd_data,), op) + else: + min_id = lambda id_set: None if len(id_set) == 0 else sorted(list(id_set))[0] + min_chg_id = min_id(chg_list) + if min_chg_id is None: + min_id_chged = False + else: + if min_chg_id in opt_idx_list: + min_id_chged = len(no_chg_list) == 0 + else: + min_unchg_id = min_id(no_chg_list) + min_id_chged = min_unchg_id is None or min_chg_id < min_unchg_id + op = CachedDataWithOp.OP_DELETE if is_del and min_id_chged else CachedDataWithOp.OP_UPDATE + cmd_data = [] + for idx in range(len(key_list)): + if (((not is_del or op == CachedDataWithOp.OP_DELETE) and (idx in chg_list or idx in no_chg_list)) or + (is_del and op == CachedDataWithOp.OP_UPDATE and idx in no_chg_list)): + cmd_data.append(data[key_list[idx]].data) + else: + if idx in opt_idx_list: + cmd_data.append('') + continue + else: + # stop adding following tokens + break + if len(cmd_data) == 0: + return None + idx = len(cmd_data) + while idx < len(key_list): + cmd_data.append('') + idx += 1 + return (tuple(cmd_data), op) + @staticmethod + def is_cmd_covered(src_cmd, dst_cmd): + src_tks = src_cmd.split() + dst_tks = dst_cmd.split() + if len(src_tks) >= len(dst_tks): + return False + for idx in range(len(src_tks)): + if src_tks[idx] != dst_tks[idx]: + return False + return True + @staticmethod + def is_cmd_list_covered(src_list, dst_list): + if len(src_list) == 0: + return True + if len(src_list) > len(dst_list): + return False + for idx in range(len(src_list)): + if not BGPKeyMapList.is_cmd_covered(src_list[idx], dst_list[idx]): + return False + return True + def run_command(self, daemon, table, data, prefix_list=None, *upper_vals): + start_idx = len(upper_vals) + ret_val = False + run_cmd_cnt = 0 + for db_field, key_map in self: + merge_vals = False + if type(db_field) is not list and type(db_field) is not tuple: + db_field = [db_field] + elif type(db_field) is tuple: + db_field = list(db_field) + merge_vals = True + + idx = 0 + req_idx_list = [] + key_list_list = [] + opt_idx_list = set() + run_cmd = True + for dkey in db_field: + optional = False + if len(dkey) > 0 and dkey[0] == '+': + if len(dkey) > 1 and dkey[1] == '+': + opt_idx_list.add(idx) + dkey = dkey[2:] + else: + dkey = dkey[1:] + optional = True + else: + req_idx_list.append(idx) + key_list = [] + for k in dkey.split('&'): + if k in data and isinstance(data[k], CachedDataWithOp): + key_list.append(k) + if not optional and len(key_list) == 0: + run_cmd = False + break + if len(key_list) == 0: + if len(key_list_list) == 0: + key_list_list.append([None]) + else: + for k_lst in key_list_list: + k_lst.append(None) + else: + new_list = [] + if len(key_list_list) == 0: + for k in key_list: + key_list_list.append([k]) + else: + for k_lst in key_list_list: + if len(key_list) == 1: + k_lst.append(key_list[0]) + else: + for k in key_list: + new_list.append(k_lst + [k]) + if len(new_list) > 0: + key_list_list = new_list + idx += 1 + if not run_cmd: + continue + + cmd_list_list = [] + for key_list in key_list_list: + upd_id_list = set() + del_id_list = set() + no_chg_id_list = set() + idx = 0 + for dkey in key_list: + if dkey is not None: + dval = data[dkey] + if dval.op == CachedDataWithOp.OP_NONE: + no_chg_id_list.add(idx) + elif dval.op == CachedDataWithOp.OP_ADD or dval.op == CachedDataWithOp.OP_UPDATE: + upd_id_list.add(idx) + elif dval.op == CachedDataWithOp.OP_DELETE: + del_id_list.add(idx) + idx += 1 + cmd_list = [] + if len(del_id_list) > 0: + data_val_op = self.get_cmd_data(key_list, req_idx_list, opt_idx_list, data, del_id_list, no_chg_id_list, merge_vals, True) + if data_val_op is not None: + cmd = key_map.get_command(daemon, data_val_op[1], start_idx, *(upper_vals + data_val_op[0])) + if cmd is not None: + cmd_list += cmd + else: + syslog.syslog(syslog.LOG_ERR, 'failed to get del cmd from value: %s' % data_val_op[0]) + if len(upd_id_list) > 0: + data_val_op = self.get_cmd_data(key_list, req_idx_list, opt_idx_list, data, upd_id_list, no_chg_id_list, merge_vals, False) + if data_val_op is not None: + cmd = key_map.get_command(daemon, data_val_op[1], start_idx, *(upper_vals + data_val_op[0])) + if cmd is not None: + cmd_list += cmd + else: + syslog.syslog(syslog.LOG_ERR, 'failed to get upd cmd from value: %s' % str(data_val_op[0])) + if len(cmd_list) > 0: + cmd_list_list.append(cmd_list) + cmd_list = [] + for chk_list in cmd_list_list: + if self.is_cmd_list_covered(cmd_list, chk_list): + cmd_list = chk_list + failed = False + if len(cmd_list) > 0: + run_cmd_cnt += 1 + cmd_prefix = 'vtysh ' + for pfx in prefix_list: + cmd_prefix += "-c '%s' " % pfx + for cmd in cmd_list: + ignore_fail = False + if type(cmd) is tuple: + cmd, ignore_fail = cmd + if not g_run_command(table, cmd_prefix + "-c '%s'" % cmd, True, key_map.daemons, ignore_fail): + syslog.syslog(syslog.LOG_ERR, 'failed running FRR command: %s' % cmd) + failed = True + break + if not failed: + ret_val = True + if not failed: + for key_list in key_list_list: + for dkey in key_list: + if dkey in data: + data[dkey].status = CachedDataWithOp.STAT_SUCC + if run_cmd_cnt == 0: + return True + return ret_val + +class CommandArgument(object): + def __init__(self, daemon, enabled, val = None): + self.daemon = daemon + self.enabled = enabled + self.value = val + self.tolower = False + def to_str(self): + if type(self.value) is list or type(self.value) is tuple: + ret_val = ' '.join([v for v in self.value]) + elif type(self.value) is dict: + id_list = self.value.keys() + id_list.sort() + ret_val = ' '.join([self.value[i][0] for i in id_list]) + else: + ret_val = str(self.value) + if self.tolower: + ret_val = ret_val.lower() + return ret_val + @staticmethod + def parse_ext_community(com_str, is_rt = None): + if com_str.startswith(CommunityList.RT_TYPE_MARK): + com_str = com_str[len(CommunityList.RT_TYPE_MARK):] + if is_rt is None: + return 'rt %s' % com_str + else: + return (com_str if is_rt else None) + elif com_str.startswith(CommunityList.SOO_TYPE_MARK): + com_str = com_str[len(CommunityList.SOO_TYPE_MARK):] + if is_rt is None: + return 'soo %s' % com_str + else: + return (None if is_rt else com_str) + return None + def __format__(self, format): + bool_format = {'allow-as-in': 'origin', + 'match-clust-len': 'equal-cluster-length', + 'network-backdoor': 'backdoor', + 'aggr-as-set': 'as-set', + 'aggr-summary-only': 'summary-only', + 'uchg-as-path': 'as-path', + 'uchg-med': 'med', + 'uchg-nh': 'next-hop', + 'rm-as-all': 'all', + 'rm-as-repl': 'replace-AS', + 'mp-as-set': ('as-set', 'no-as-set'), + 'no-prepend': 'no-prepend', + 'replace-as': 'replace-as', + 'blackhole': 'blackhole' + } + if format == 'no-prefix': + return 'no ' if not self.enabled else '' + elif format == 'enable-only' and not self.enabled: + return '' + elif format == 'com-ref': + com_set = self.daemon.comm_set_list.get(self.value, None) + if com_set is not None and com_set.is_configurable(): + return ' '.join(com_set.mbr_list) + elif format == 'ext-com-list': + if type(self.value) is tuple: + com_val, is_rt = self.value + else: + com_val = self.value + is_rt = None + if type(com_val) is list: + com_list = com_val + else: + com_list = [com_val] + frr_com_list = [] + for comm in com_list: + frr_comm = self.parse_ext_community(comm, is_rt) + if frr_comm is not None: + frr_com_list.append(frr_comm) + if is_rt is None: + return ' '.join(frr_com_list) + else: + return ('rt ' if is_rt else 'soo ') + ' '.join(frr_com_list) + elif format == 'ext-com-ref': + com_set_name, is_rt = self.value + com_set = self.daemon.extcomm_set_list.get(com_set_name, None) + if com_set is not None and com_set.is_configurable(): + frr_com_list = [] + for comm in com_set.mbr_list: + frr_comm = self.parse_ext_community(comm, is_rt) + if frr_comm is not None: + frr_com_list.append(frr_comm) + return ('rt ' if is_rt else 'soo ') + ' '.join(frr_com_list) + elif format == 'repeat' and type(self.value) is dict: + if 1 in self.value: + rep_cnt = int(self.value[1][0]) + else: + rep_cnt = 1 + if 0 in self.value: + return ' '.join([self.value[0][0]] * rep_cnt) + elif format == 'neighbor-set': + ret_val = BGPConfigDaemon.get_prefix_set_name(self.value, 'NEIGHBOR_SET') + return ret_val + elif format == 'nexthop-set': + ret_val = BGPConfigDaemon.get_prefix_set_name(self.value, 'NEXTHOP_SET') + return ret_val + elif format == 'peer-ip': + if type(self.value) is list and len(self.value) > 0: + return self.value[0] + else: + return self.value + elif format == 'tx-add-paths': + if self.value == 'tx_all_paths': + return 'addpath-tx-all-paths' + elif self.value == 'tx_best_path_per_as': + return 'addpath-tx-bestpath-per-AS' + elif format == 'shutdown-msg': + if len(self.value) > 0: + self.value = 'message %s' % self.value + elif format == 'default-rmap': + if len(self.value) > 0: + self.value = 'route-map %s' % self.value + elif format in bool_format: + false_val = '' + if type(bool_format[format]) is tuple: + if len(bool_format[format]) == 2: + true_val, false_val = bool_format[format] + else: + true_val = bool_format[format][0] + else: + true_val = bool_format[format] + if self.value == 'true': + self.value = true_val + elif self.value == 'false': + self.value = false_val + elif format == 'restart': + if self.value == 'true': + self.value = 'warning-only' + elif self.value == 'false': + self.value = '' + elif len(self.value) > 0: + self.value = 'restart %s' % self.value + elif format == 'redist-route-map': + if len(self.value) > 0: + self.value = 'route-map %s' % self.to_str() + elif format == 'redist-metric': + if len(self.value) > 0: + self.value = 'metric %s' % self.to_str() + elif format == 'track': + if len(self.value) > 0: + self.value = 'track %s' % self.to_str() + elif format == 'network-policy': + if len(self.value) > 0: + self.value = 'route-map %s' % self.to_str() + elif format == 'src-proto': + if self.value == 'ospf3': + self.value = 'ospf6' + elif format == 'aggr-policy': + if len(self.value) > 0: + self.value = 'route-map %s' % self.to_str() + elif format == 'asn_list': + self.value = ' '.join(self.value.split(',')) + elif format == 'nh-tag': + if len(self.value) > 0: + self.value = 'tag %s' % self.to_str() + elif format == 'nh-vrf': + if len(self.value) > 0: + self.value = 'nexthop-vrf %s' % self.to_str() + elif format == 'tolower': + self.tolower = True + elif format == 'pim_hello_parms': + self.value = ' '.join(self.value.split(',')) + return self.to_str() + +def hdl_send_com(daemon, cmd_str, op, st_idx, args, data): + if len(args) < 2: + return None + cmd_list = [] + cmd_list.append(cmd_str.format(CommandArgument(daemon, True, args[0]), CommandArgument(daemon, True, 'all'), no = CommandArgument(daemon, False))) + if op == CachedDataWithOp.OP_DELETE: + com_type = 'all' + else: + com_type = args[1] + if com_type != 'none': + cmd_list.append(cmd_str.format(CommandArgument(daemon, True, args[0]), CommandArgument(daemon, True, com_type), no = CommandArgument(daemon, True))) + return cmd_list + +def hdl_rm_priv_as(daemon, cmd_str, op, st_idx, args, data): + cmd_list = [] + cmd_list.append(cmd_str.format(CommandArgument(daemon, True, args[0]), CommandArgument(daemon, True, ''), CommandArgument(daemon, True, ''), + no = CommandArgument(daemon, False))) + cmd_list.append(cmd_str.format(CommandArgument(daemon, True, args[0]), CommandArgument(daemon, True, 'true'), CommandArgument(daemon, True, ''), + no = CommandArgument(daemon, False))) + cmd_list.append(cmd_str.format(CommandArgument(daemon, True, args[0]), CommandArgument(daemon, True, ''), CommandArgument(daemon, True, 'true'), + no = CommandArgument(daemon, False))) + cmd_list.append(cmd_str.format(CommandArgument(daemon, True, args[0]), CommandArgument(daemon, True, 'true'), CommandArgument(daemon, True, 'true'), + no = CommandArgument(daemon, False))) + if op != CachedDataWithOp.OP_DELETE: + cmd_list += get_command_cmn(daemon, cmd_str, op, st_idx, args, data) + return cmd_list + +def hdl_capa_orf_pfxlist(daemon, cmd_str, op, st_idx, args, data): + if len(args) < 2: + return None + cmd_list = [] + cmd_list.append(cmd_str.format(CommandArgument(daemon, True, args[0]), CommandArgument(daemon, True, 'both'), no = CommandArgument(daemon, False))) + if op != CachedDataWithOp.OP_DELETE: + cmd_list.append(cmd_str.format(CommandArgument(daemon, True, args[0]), CommandArgument(daemon, True, args[1]), no = CommandArgument(daemon, True))) + return cmd_list + +def hdl_com_set(daemon, cmd_str, op, st_idx, args, extended): + if len(args) < 2 or 0 not in args[1] or 1 not in args[1] or 2 not in args[1]: + return None + com_name = args[0] + set_type = args[1][0][0].lower() + arg_str = '{} {}'.format(set_type, com_name) + cmd_list = [] + com_set_list = daemon.comm_set_list if not extended else daemon.extcomm_set_list + if com_name in com_set_list and com_set_list[com_name].is_configurable(): + cmd_list.append(cmd_str.format(CommandArgument(daemon, True, arg_str), no = CommandArgument(daemon, False))) + if op != CachedDataWithOp.OP_DELETE: + match_action = args[1][1][0].lower() + member_list = args[1][2][0] + if match_action == 'all': + if extended and set_type == 'standard': + mbr_str = '{} permit {:ext-com-list}'.format(arg_str, CommandArgument(daemon, True, member_list)) + else: + mbr_str = '{} permit {}'.format(arg_str, ' '.join(member_list)) + cmd_list.append(cmd_str.format(CommandArgument(daemon, True, mbr_str), no = CommandArgument(daemon, True))) + elif match_action == 'any': + for member in member_list: + if extended and set_type == 'standard': + mbr_str = '{} permit {:ext-com-list}'.format(arg_str, CommandArgument(daemon, True, member)) + else: + mbr_str = '{} permit {}'.format(arg_str, member) + cmd_list.append(cmd_str.format(CommandArgument(daemon, True, mbr_str), no = CommandArgument(daemon, True))) + return cmd_list + +def hdl_aspath_set(daemon, cmd_str, op, st_idx, args, data): + if len(args) < 2: + return None + cmd_list = [] + as_set_name = args[0] + if as_set_name in daemon.as_path_set_list: + cmd_list.append(cmd_str.format(CommandArgument(daemon, True, as_set_name), no = CommandArgument(daemon, False))) + if op != CachedDataWithOp.OP_DELETE and len(args[1]) > 0: + for asn in args[1]: + mbr_str = '{} permit {}'.format(as_set_name, asn) + cmd_list.append(cmd_str.format(CommandArgument(daemon, True, mbr_str), no = CommandArgument(daemon, True))) + return cmd_list + +def hdl_ibgp_maxpath(daemon, cmd_str, op, st_idx, args, data): + cmd_list = [] + if op != CachedDataWithOp.OP_DELETE: + # blindly run no command first + cmd_list = [cmd_str.format(CommandArgument(daemon, True, args[0]), + CommandArgument(daemon, True, 'false'), + no = CommandArgument(daemon, False))] + upd_cmd_list = get_command_cmn(daemon, cmd_str, op, st_idx, args, data) + if upd_cmd_list is None: + return None + return cmd_list + upd_cmd_list + +def hdl_ospf_log(daemon, cmd_str, op, st_idx, args, data): + cmd_list = [] + + no_op = 'no ' if op == CachedDataWithOp.OP_DELETE else '' + + if (no_op == 'no '): + cmd_list.append(cmd_str.format(CommandArgument(daemon, True, no_op), + CommandArgument(daemon, True, ""))) + elif (args[0] == "DETAIL"): + cmd_list.append(cmd_str.format(CommandArgument(daemon, True, no_op), + CommandArgument(daemon, True, args[0].lower()))) + elif (args[0] == "BRIEF"): + cmd_list.append(cmd_str.format(CommandArgument(daemon, True, no_op), + CommandArgument(daemon, True, ""))) + + return cmd_list + +def handle_ospf_area_auth(daemon, cmd_str, op, st_idx, args, data): + cmd_list = [] + + no_op = 'no ' if op == CachedDataWithOp.OP_DELETE else '' + + if (args[1] == "MD5HMAC"): + cmd_list.append(cmd_str.format(CommandArgument(daemon, True, no_op), + CommandArgument(daemon, True, args[0]), + CommandArgument(daemon, True, "message-digest"))) + + elif (args[1] == "TEXT"): + cmd_list.append(cmd_str.format(CommandArgument(daemon, True, no_op), + CommandArgument(daemon, True, args[0]), + CommandArgument(daemon, True, ""))) + elif (args[1] == "NONE"): + cmd_list.append(cmd_str.format(CommandArgument(daemon, True, 'no '), + CommandArgument(daemon, True, args[0]), + CommandArgument(daemon, True, ""))) + return cmd_list + +def handle_ospf_area_shortcut(daemon, cmd_str, op, st_idx, args, data): + cmd_list = [] + + no_op = 'no ' if op == CachedDataWithOp.OP_DELETE else '' + + if (args[1] == "DEFAULT") and (no_op != 'no '): + cmd_list.append(cmd_str.format(CommandArgument(daemon, True, no_op), + CommandArgument(daemon, True, args[0]), + CommandArgument(daemon, True, "default"))) + + elif (args[1] == "ENABLE"): + cmd_list.append(cmd_str.format(CommandArgument(daemon, True, no_op), + CommandArgument(daemon, True, args[0]), + CommandArgument(daemon, True, "enable"))) + elif (args[1] == "DISABLE"): + cmd_list.append(cmd_str.format(CommandArgument(daemon, True, no_op), + CommandArgument(daemon, True, args[0]), + CommandArgument(daemon, True, "disable"))) + return cmd_list + +def handle_ospf_area_vlink_auth(daemon, cmd_str, op, st_idx, args, data): + cmd_list = [] + + no_op = 'no ' if op == CachedDataWithOp.OP_DELETE else '' + + if (args[2] == "MD5HMAC"): + cmd_list.append(cmd_str.format(CommandArgument(daemon, True, no_op), + CommandArgument(daemon, True, args[0]), + CommandArgument(daemon, True, args[1]), + CommandArgument(daemon, True, "message-digest"))) + elif (args[2] == "NONE"): + cmd_list.append(cmd_str.format(CommandArgument(daemon, True, no_op), + CommandArgument(daemon, True, args[0]), + CommandArgument(daemon, True, args[1]), + CommandArgument(daemon, True, "null"))) + + return cmd_list + +def handle_ospf_area_range_advt(daemon, cmd_str, op, st_idx, args, data): + cmd_list = [] + + + no_op = 'no ' if op == CachedDataWithOp.OP_DELETE else '' + + if (args[2] == 'true'): + cmd_list.append(cmd_str.format(CommandArgument(daemon, True, no_op), + CommandArgument(daemon, True, args[0]), + CommandArgument(daemon, True, args[1]), + CommandArgument(daemon, True, "advertise"))) + elif (args[2] == 'false'): + cmd_list.append(cmd_str.format(CommandArgument(daemon, True, no_op), + CommandArgument(daemon, True, args[0]), + CommandArgument(daemon, True, args[1]), + CommandArgument(daemon, True, "not-advertise"))) + return cmd_list + +def handle_ospf_abrtype(daemon, cmd_str, op, st_idx, args, data): + cmd_list = [] + + no_op = 'no ' if op == CachedDataWithOp.OP_DELETE else '' + + cmd_list.append(cmd_str.format(CommandArgument(daemon, True, no_op), + CommandArgument(daemon, True, args[0].lower()))) + + return cmd_list + + +def handle_ospf_if_common(daemon, cmd_str, op, st_idx, args, data): + cmd_list = [] + if_addr = "" if args[1] == '0.0.0.0' else args[1] + no_op = 'no ' if op == CachedDataWithOp.OP_DELETE else '' + param_value = args[2] + + syslog.syslog(syslog.LOG_INFO, 'handle_ospf_if_common cmd_str {} op {} st_idx {} args {} data {}'.format( + cmd_str, op, st_idx, args, data)) + + cmd_list.append(cmd_str.format(CommandArgument(daemon, True, no_op), + CommandArgument(daemon, True, param_value), + CommandArgument(daemon, True, if_addr))) + return cmd_list + + +def handle_ospf_if_authtype(daemon, cmd_str, op, st_idx, args, data): + cmd_list = [] + if_addr = "" if args[1] == '0.0.0.0' else args[1] + no_op = 'no ' if op == CachedDataWithOp.OP_DELETE else '' + + authtype = '' + if args[2] == 'TEXT' : + authtype = '' + elif args[2] == 'MD5HMAC' : + authtype = 'message-digest' + elif args[2] == 'NONE' : + authtype = 'null' + else : + syslog.syslog(syslog.LOG_ERR, 'handle_ospf_if_nwtype invalid auth type args {}'.format(args)) + + syslog.syslog(syslog.LOG_INFO, 'handle_ospf_if_authtype cmd_str {} op {} st_idx {} args {} data {}'.format( + cmd_str, op, st_idx, args, data)) + + cmd_list.append(cmd_str.format(CommandArgument(daemon, True, no_op), + CommandArgument(daemon, True, authtype), + CommandArgument(daemon, True, if_addr))) + return cmd_list + + +def handle_ospf_if_md5key(daemon, cmd_str, op, st_idx, args, data): + cmd_list = [] + if_addr = "" if args[1] == '0.0.0.0' else args[1] + no_op = 'no ' if op == CachedDataWithOp.OP_DELETE else '' + + md5key_id = args[2] + md5key = args[3] + + syslog.syslog(syslog.LOG_INFO, 'handle_ospf_if_md5key cmd_str {} op {} st_idx {} args {} data {}'.format( + cmd_str, op, st_idx, args, data)) + + cmd_list.append(cmd_str.format(CommandArgument(daemon, True, no_op), + CommandArgument(daemon, True, md5key_id), + CommandArgument(daemon, True, md5key), + CommandArgument(daemon, True, if_addr))) + return cmd_list + + +def handle_ospf_if_mtu_ignore(daemon, cmd_str, op, st_idx, args, data): + cmd_list = [] + if_addr = "" if args[1] == '0.0.0.0' else args[1] + no_op = 'no ' if op == CachedDataWithOp.OP_DELETE else '' + + syslog.syslog(syslog.LOG_INFO, 'handle_ospf_if_mtu_ignore cmd_str {} op {} st_idx {} args {} data {}'.format( + cmd_str, op, st_idx, args, data)) + + cmd_list.append(cmd_str.format(CommandArgument(daemon, True, no_op), + CommandArgument(daemon, True, if_addr))) + return cmd_list + + +def handle_ospf_if_nwtype(daemon, cmd_str, op, st_idx, args, data): + cmd_list = [] + no_op = 'no ' if op == CachedDataWithOp.OP_DELETE else '' + + nwtype = '' + if args[2] == 'POINT_TO_POINT_NETWORK' : + nwtype = 'point-to-point' + elif args[2] == 'BROADCAST_NETWORK' : + nwtype = 'broadcast' + else : + syslog.syslog(syslog.LOG_ERR, 'handle_ospf_if_nwtype invalid nw type args {}'.format(args)) + + syslog.syslog(syslog.LOG_INFO, 'handle_ospf_if_nwtype cmd_str {} op {} st_idx {} args {} data {}'.format( + cmd_str, op, st_idx, args, data)) + + cmd_list.append(cmd_str.format(CommandArgument(daemon, True, no_op), + CommandArgument(daemon, True, nwtype))) + return cmd_list + +def handle_igmp_if_common(daemon, cmd_str, op, st_idx, args, data): + if len(args) != 1: + return None + cmd_list = [] + param_value = args[0] + + syslog.syslog(syslog.LOG_INFO, 'handle_igmp_if_common cmd_str {} op {} st_idx {} args {} data {}'.format( + cmd_str, op, st_idx, args, data)) + + if op != CachedDataWithOp.OP_DELETE: + cmd_list.append(cmd_str.format(CommandArgument(daemon, True, param_value))) + else: + cmd_list.append('no ' + cmd_str.format(CommandArgument(daemon, True, ''))) + + syslog.syslog(syslog.LOG_INFO, 'handle_igmp_if_common param {}, cmd_list {}'.format(param_value, cmd_list)) + return cmd_list + +def handle_igmp_if_enable(daemon, cmd_str, op, st_idx, args, data): + if len(args) != 1: + return None + cmd_list = [] + param_value = args[0] + + syslog.syslog(syslog.LOG_INFO, 'handle_igmp_if_enable cmd_str {} op {} st_idx {} args {} data {}'.format( + cmd_str, op, st_idx, args, data)) + + if op != CachedDataWithOp.OP_DELETE: + if param_value == 'false': + cmd_list.append('no ' + cmd_str.format(CommandArgument(daemon, True, ''))) + else: + cmd_list.append(cmd_str.format(CommandArgument(daemon, True, ''))) + else: + cmd_list.append('no ' + cmd_str.format(CommandArgument(daemon, True, ''))) + + syslog.syslog(syslog.LOG_INFO, 'handle_igmp_if_enable param {}, cmd_list {}'.format(param_value, cmd_list)) + return cmd_list + +def handle_ip_sla_common(daemon, cmd_str, op, st_idx, args, data): + cmd_list = [] + + syslog.syslog(syslog.LOG_INFO, 'handle_ip_sla cmd_str {} op {} st_idx {} args {} data {}'.format( + cmd_str, op, st_idx, args, data)) + + if op != CachedDataWithOp.OP_DELETE: + cmd_list.append(cmd_str.format(CommandArgument(daemon, True, args[1]))) + else: + cmd_list.append('no ' + cmd_str.format(CommandArgument(daemon, True, ''))) + + return cmd_list + +def handle_ip_sla_tcp_connect(daemon, cmd_str, op, st_idx, args, data): + cmd_list = [] + + syslog.syslog(syslog.LOG_INFO, 'handle_ip_sla_tcp_connect cmd_str {} op {} st_idx {} args {} data {}'.format( + cmd_str, op, st_idx, args, data)) + tcp_cmd_token = ("tcp", "connect") + tcp_cmd_str = "-".join(tcp_cmd_token) + tcp_cmd_deconfig = ' no ' + tcp_cmd_str + + if op != CachedDataWithOp.OP_DELETE: + cmd_list.append(' ') + else: + cmd_list.append(tcp_cmd_deconfig) + + return cmd_list + +def handle_ip_sla_icmp_echo(daemon, cmd_str, op, st_idx, args, data): + cmd_list = [] + + syslog.syslog(syslog.LOG_INFO, 'handle_ip_sla_icmp_echo cmd_str {} op {} st_idx {} args {} data {}'.format( + cmd_str, op, st_idx, args, data)) + icmp_cmd_token = ("icmp", "echo") + icmp_cmd_str = "-".join(icmp_cmd_token) + icmp_cmd_deconfig = ' no ' + icmp_cmd_str + + if op != CachedDataWithOp.OP_DELETE: + cmd_list.append(' ') + syslog.syslog(syslog.LOG_INFO, 'handle_ip_sla_icmp_echo cmd_list {}'.format(cmd_list)) + else: + cmd_list.append(icmp_cmd_deconfig) + + syslog.syslog(syslog.LOG_INFO, 'handle_ip_sla_icmp_echo cmd_list {}'.format(cmd_list)) + return cmd_list + + + +def hdl_af_aggregate(daemon, cmd_str, op, st_idx, args, data): + if len(args) < 5: + return None + cmd_list = [] + if op != CachedDataWithOp.OP_DELETE: + vrf = args[0] + af = args[1] + ip_prefix = args[2] + if vrf in daemon.af_aggr_list and ip_prefix in daemon.af_aggr_list[vrf]: + cmd_list.append(cmd_str.format(CommandArgument(daemon, True, vrf), CommandArgument(daemon, True, af), CommandArgument(daemon, True, ip_prefix), + CommandArgument(daemon, True, ''), CommandArgument(daemon, True, ''), CommandArgument(daemon, True, ''), + no = CommandArgument(daemon, False))) + upd_cmd_list = get_command_cmn(daemon, cmd_str, op, st_idx, args, data) + if upd_cmd_list is None: + return None + return cmd_list + upd_cmd_list + +def hdl_route_redist_set(daemon, cmd_str, op, st_idx, args, data): + cmd_list = [] + if op != CachedDataWithOp.OP_DELETE: + proto = args[0] + # blindly run no command first + cmd_list.append(cmd_str.format(CommandArgument(daemon, True, proto), CommandArgument(daemon, True, ''), CommandArgument(daemon, True, ''), + no = CommandArgument(daemon, False))) + upd_cmd_list = get_command_cmn(daemon, cmd_str, op, st_idx, args, data) + if upd_cmd_list is None: + return None + return cmd_list + upd_cmd_list + +def hdl_attr_unchanged(daemon, cmd_str, op, st_idx, args, data): + # blindly run no command first + cmd_list = [cmd_str.format(CommandArgument(daemon, True, args[0]), + CommandArgument(daemon, True, ''), + CommandArgument(daemon, True, ''), + CommandArgument(daemon, True, ''), + no = CommandArgument(daemon, False))] + if op != CachedDataWithOp.OP_DELETE: + upd_cmd_list = get_command_cmn(daemon, cmd_str, op, st_idx, args, data) + if upd_cmd_list is None: + return None + cmd_list += upd_cmd_list + return cmd_list + +def hdl_leaf_list_expansion(daemon, cmd_str, op, st_idx, args, data, table_key, item_key): + cmd_list = [] + old_list = [] + if op != CachedDataWithOp.OP_DELETE: + new_list = args[st_idx] + else: + new_list = [] + + syslog.syslog(syslog.LOG_DEBUG, 'handle_leaf_list_expansion {} op {} st_idx {} args {} data {} table_key {} item_key {}'.format( + cmd_str, op, st_idx, args, data, table_key, item_key)) + + if table_key in daemon.table_data_cache.keys(): + cache_tbl_data = daemon.table_data_cache[table_key] + if item_key in cache_tbl_data: + old_list = cache_tbl_data[item_key] + + del_list = list(set(old_list) - set(new_list)) + add_list = list(set(new_list) - set(old_list)) + + for value in add_list: + cmd_list.append(cmd_str.format(CommandArgument(daemon, True, value), no = CommandArgument(daemon, True))) + for value in del_list: + cmd_list.append(cmd_str.format(CommandArgument(daemon, True, value), no = CommandArgument(daemon, False))) + + syslog.syslog(syslog.LOG_DEBUG, 'cmd_list {}'.format(cmd_list)) + return cmd_list + +def hdl_import_list(daemon, cmd_str, op, st_idx, args, data): + return hdl_leaf_list_expansion(daemon, cmd_str, op, st_idx, args, data, daemon.tmp_cache_key, 'import-rts') + +def hdl_export_list(daemon, cmd_str, op, st_idx, args, data): + return hdl_leaf_list_expansion(daemon, cmd_str, op, st_idx, args, data, daemon.tmp_cache_key, 'export-rts') + +def hdl_enum_conversion(daemon, cmd_str, op, st_idx, args, data): + cmd_list = [] + syslog.syslog(syslog.LOG_DEBUG, 'handle_enum_conversion {} op {} st_idx {} args {} data {}'.format( + cmd_str, op, st_idx, args, data)) + cmd_list.append(cmd_str.format(CommandArgument(daemon, True, args[st_idx].lower().replace('_','-')), + no = CommandArgument(daemon, (op != CachedDataWithOp.OP_DELETE)))) + syslog.syslog(syslog.LOG_DEBUG, 'cmd_list {}'.format(cmd_list)) + return cmd_list + +def hdl_confed_peers(daemon, cmd_str, op, st_idx, args, data): + del_list = [] + add_list = [] + if op == CachedDataWithOp.OP_DELETE: + del_list = list(daemon.upd_confed_peers) + daemon.upd_confed_peers.clear() + else: + for peer in args[0]: + if peer not in daemon.upd_confed_peers: + add_list.append(peer) + else: + daemon.upd_confed_peers.remove(peer) + del_list = list(daemon.upd_confed_peers) + daemon.upd_confed_peers = set(args[0]) + cmd_list = [] + if len(del_list) > 0: + cmd_list.append(cmd_str.format(CommandArgument(daemon, True, del_list), no = CommandArgument(daemon, False))) + if len(add_list) > 0: + cmd_list.append(cmd_str.format(CommandArgument(daemon, True, add_list), no = CommandArgument(daemon, True))) + return cmd_list + +def hdl_static_route(daemon, cmd_str, op, st_idx, args, data): + if len(args) < 6: + return None + vrf = args[0] + ip_prefix = args[1] + af = data + if op == CachedDataWithOp.OP_DELETE: + ip_nh_set = IpNextHopSet(af) + else: + arg_list = lambda v: v.split(',') if len(v.strip()) != 0 else None + bkh_list = arg_list(args[2]) + nh_list = arg_list(args[3]) + track_list = arg_list(args[5]) + intf_list = arg_list(args[4]) + tag_list = arg_list(args[6]) + dist_list = arg_list(args[7]) + nh_vrf_list = arg_list(args[8]) + ip_nh_set = IpNextHopSet(af, bkh_list, nh_list, track_list, intf_list, tag_list, dist_list, nh_vrf_list) + cur_nh_set = daemon.static_route_list.get(vrf, {}).get(ip_prefix, IpNextHopSet(af)) + diff_set = ip_nh_set.symmetric_difference(cur_nh_set) + op_cmd_list = {} + for ip_nh in diff_set: + if ip_nh in cur_nh_set: + op = CachedDataWithOp.OP_DELETE + else: + op = CachedDataWithOp.OP_ADD + try: + op_cmds = op_cmd_list.setdefault(op, []) + op_cmds += get_command_cmn(daemon, cmd_str, op, st_idx, [ip_prefix] + ip_nh.get_arg_list(), None) + except socket.error: + syslog.syslog(syslog.LOG_ERR, 'Invalid IP in next-hop %s' % ip_nh) + return None + cmd_list = op_cmd_list.get(CachedDataWithOp.OP_DELETE, []) + cmd_list += op_cmd_list.get(CachedDataWithOp.OP_ADD, []) + daemon.upd_nh_set = ip_nh_set + return cmd_list + +class ExtConfigDBConnector(ConfigDBConnector): + def __init__(self, ns_attrs = None): + super(ExtConfigDBConnector, self).__init__() + self.nosort_attrs = ns_attrs if ns_attrs is not None else {} + def raw_to_typed(self, raw_data, table = ''): + if len(raw_data) == 0: + raw_data = None + data = super(ExtConfigDBConnector, self).raw_to_typed(raw_data) + if data is None: + return None + for key, val in data.items(): + if type(val) is list and key not in self.nosort_attrs.get(table, set()): + val.sort() + return data + def sub_msg_handler(self, msg_item): + if msg_item['type'] == 'pmessage': + key = msg_item['channel'].split(':', 1)[1] + try: + (table, row) = key.split(self.TABLE_NAME_SEPARATOR, 1) + if table in self.handlers: + client = self.get_redis_client(self.db_name) + data = self.raw_to_typed(client.hgetall(key), table) + super(ExtConfigDBConnector, self)._ConfigDBConnector__fire(table, row, data) + except ValueError: + pass #Ignore non table-formated redis entries + except Exception as e: + syslog.syslog(syslog.LOG_ERR, '[bgp cfgd] Failed handling config DB update with exception:' + str(e)) + logging.exception(e) + def listen(self): + """Start listen Redis keyspace events and will trigger corresponding handlers when content of a table changes. + """ + self.pubsub = self.get_redis_client(self.db_name).pubsub() + self.pubsub.psubscribe(**{"__keyspace@{}__:*".format(self.get_dbid(self.db_name)): self.sub_msg_handler}) + self.sub_thread = self.pubsub.run_in_thread(sleep_time = 0.01) + @staticmethod + def get_table_key(table, key): + return table + '&&' + key + def get_table_data(self, table_list): + ret_data = {} + for table in table_list: + table_data = self.get_table(table) + for key, data in table_data.items(): + table_key = self.get_table_key(table, self.serialize_key(key)) + ret_data[table_key] = data + return ret_data + +class CommunityList: + MATCH_ALL = 0 + MATCH_ANY = 1 + RT_TYPE_MARK = 'route-target:' + SOO_TYPE_MARK = 'route-origin:' + def __init__(self, name, extended): + self.name = name + self.is_ext = extended + self.match_action = None + self.is_std = None + self.mbr_list = [] + def is_configurable(self): + return (self.match_action is not None and self.is_std is not None and + len(self.mbr_list) > 0) + def db_data_to_attr(self, name, val): + if name == 'match_action': + if val is None: + self.match_action = None + else: + if val.lower() == 'all': + self.match_action = self.MATCH_ALL + else: + self.match_action = self.MATCH_ANY + elif name == 'set_type': + if val is None: + self.is_std = None + else: + self.is_std = (val.lower() == 'standard') + elif name == 'community_member': + self.mbr_list = [] + if val is not None: + if type(val) is not list: + self.mbr_list = val.split(',') + else: + self.mbr_list = val + +class MatchPrefix: + IPV4_MAXLEN = 32 + IPV6_MAXLEN = 128 + @staticmethod + def normalize_ip_prefix(af, ip_prefix): + ip_mask = ip_prefix.split('/') + ip_addr = ip_mask[0] + if len(ip_mask) < 2: + mask_len = MatchPrefix.IPV4_MAXLEN if af == socket.AF_INET else MatchPrefix.IPV6_MAXLEN + return '%s/%d' % (ip_addr, mask_len) + mask_len = int(ip_mask[1]) + ip_net = netaddr.IPNetwork('%s/%d' % (ip_addr, mask_len)) + try: + normal_ip = socket.inet_ntop(af, ip_net.cidr.ip.packed) + except ValueError: + return None + return '%s/%d' % (normal_ip, mask_len) + def __init__(self, af, ip_prefix, len_range = None, action = 'permit'): + self.ip_prefix = self.normalize_ip_prefix(af, ip_prefix) + if self.ip_prefix is None: + raise ValueError + if len_range is not None: + min_len, max_len = len_range.split('..') + self.min_len = int(min_len) + self.max_len = int(max_len) + _, pfx_len = self.ip_prefix.split('/') + if int(pfx_len) >= self.min_len: + self.min_len = None + elif ((af == socket.AF_INET and self.max_len == self.IPV4_MAXLEN) or + (af == socket.AF_INET6 and self.max_len == self.IPV6_MAXLEN)): + self.max_len = None + else: + self.min_len = self.max_len = None + self.action = action + def __hash__(self): + return hash((self.ip_prefix, self.min_len, self.max_len)) + def __str__(self): + ret_str = '%s %s' % (self.action.lower(), self.ip_prefix) + if self.min_len is not None: + ret_str += ' ge %d' % self.min_len + if self.max_len is not None: + ret_str += ' le %d' % self.max_len + return ret_str + def __eq__(self, other): + return (self.ip_prefix == other.ip_prefix and + self.min_len == other.min_len and + self.max_len == other.max_len) + def __ne__(self, other): + return (self.ip_prefix != other.ip_prefix or + self.min_len != other.min_len or + self.max_len != other.max_len) + +class MatchPrefixList(list): + def __init__(self, af_mode = None): + super(MatchPrefixList, self).__init__() + if af_mode is None: + self.af = None + else: + self.af = socket.AF_INET if af_mode == 'ipv4' else socket.AF_INET6 + def __eq__(self, other): + return super(MatchPrefixList, self).__eq__(other) and self.af == other.af + def __ne__(self, other): + return super(MatchPrefixList, self).__ne__(other) or self.af != other.af + @staticmethod + def __get_ip_af(ip_pfx): + ip_pfx = ip_pfx.split('/') + ip_addr = ip_pfx[0] + af_list = [socket.AF_INET, socket.AF_INET6] + for af in af_list: + try: + socket.inet_pton(af, ip_addr) + return af + except socket.error: + continue + return None + def add_prefix(self, ip_pfx, len_range = None, action = 'permit'): + af = self.__get_ip_af(ip_pfx) + if self.af is None: + self.af = af + else: + if self.af != af: + syslog.syslog(syslog.LOG_ERR, 'af of prefix %s is not the same as prefix set' % ip_pfx) + raise ValueError + self.append(MatchPrefix(self.af, ip_pfx, len_range, action)) + return self[-1] + def get_prefix(self, ip_pfx, len_range = None, action = 'permit'): + if self.af is None: + return (None, None) + prefix = MatchPrefix(self.af, ip_pfx, len_range, action) + try: + idx = self.index(prefix) + except ValueError: + return (None, None) + return (self[idx], idx) + +class AggregateAddr: + def __init__(self): + self.as_set = False + self.summary_only = False + +class IpNextHop: + def __init__(self, af_id, blackhole, dst_ip, track, if_name, tag, dist, vrf): + zero_ip = lambda af: '0.0.0.0' if af == socket.AF_INET else '::' + self.af = af_id + self.blackhole = 'false' if blackhole is None or blackhole == '' else blackhole + self.distance = 0 if dist is None else int(dist) + self.track = 0 if track is None else int(track) + if self.blackhole == 'true': + dst_ip = if_name = vrf = None + self.ip = zero_ip(af_id) if dst_ip is None else dst_ip + self.interface = '' if if_name is None else if_name + self.tag = 0 if tag is None else int(tag) + self.nh_vrf = '' if vrf is None else vrf + if self.blackhole != 'true' and self.is_zero_ip() and len(self.interface.strip()) == 0: + syslog.syslog(syslog.LOG_ERR, 'Mandatory attribute not found for nexthop') + raise ValueError + def __eq__(self, other): + return (self.af == other.af and self.blackhole == other.blackhole and + self.ip == other.ip and self.track == other.track and self.interface == other.interface and + self.tag == other.tag and self.distance == other.distance and self.nh_vrf == other.nh_vrf) + def __ne__(self, other): + return (self.af != other.af or self.blackhole != other.blackhole or + self.ip != other.ip or self.track != other.track or self.interface != other.interface or + self.tag != other.tag or self.distance != other.distance or self.nh_vrf != other.nh_vrf) + def __hash__(self): + return hash((self.af, self.blackhole, self.ip, self.track, self.interface, self.tag, self.distance, self.nh_vrf)) + def __str__(self): + return 'AF %d BKH %s IP %s TRACK %d INTF %s TAG %d DIST %d VRF %s' % ( + self.af, self.blackhole, self.ip, self.track, self.interface, self.tag, self.distance, self.nh_vrf) + def is_zero_ip(self): + return sum([x for x in socket.inet_pton(self.af, self.ip)]) == 0 + def get_arg_list(self): + arg = lambda x: '' if x is None else x + num_arg = lambda x: '' if x is None or x == 0 else str(x) + ip_arg = lambda : '' if self.ip is None else ('' if self.is_zero_ip() else self.ip) + return [self.blackhole, ip_arg(), arg(self.interface), num_arg(self.track), num_arg(self.tag), num_arg(self.distance), arg(self.nh_vrf)] + +class IpNextHopSet(set): + def __init__(self, af, bkh_list = None, ip_list = None, track_list = None, intf_list = None, tag_list = None, dist_list = None, vrf_list = None): + super(IpNextHopSet, self).__init__() + if bkh_list is None and ip_list is None and intf_list is None: + # empty set, for delete case + return + nums = {len(x) for x in [bkh_list, ip_list, track_list, intf_list, tag_list, dist_list, vrf_list] if x is not None} + if len(nums) != 1: + syslog.syslog(syslog.LOG_ERR, 'Lists of next-hop attribute have different sizes: %s' % nums) + for x in [bkh_list, ip_list, track_list, intf_list, tag_list, dist_list, vrf_list]: + syslog.syslog(syslog.LOG_DEBUG, 'List: %s' % x) + return + nh_cnt = nums.pop() + item = lambda lst, i: lst[i] if lst is not None else None + for idx in range(nh_cnt): + try: + self.add(IpNextHop(af, item(bkh_list, idx), item(ip_list, idx), item(track_list, idx), item(intf_list, idx), + item(tag_list, idx), item(dist_list, idx), item(vrf_list, idx), )) + except ValueError: + continue + @staticmethod + def get_af_norm_prefix(ip_prefix): + for af_id in [socket.AF_INET, socket.AF_INET6]: + new_prefix = MatchPrefix.normalize_ip_prefix(af_id, ip_prefix) + if new_prefix is not None: + return (af_id, new_prefix) + return (None, None) + +class BGPConfigDaemon: + DEFAULT_VRF = 'default' + + global_key_map = [('router_id', '{no:no-prefix}bgp router-id {}'), + (['load_balance_mp_relax', '+as_path_mp_as_set'], '{no:no-prefix}bgp bestpath as-path multipath-relax {:mp-as-set}', ['true', 'false']), + ('always_compare_med', '{no:no-prefix}bgp always-compare-med', ['true', 'false']), + ('external_compare_router_id', '{no:no-prefix}bgp bestpath compare-routerid', ['true', 'false']), + ('ignore_as_path_length', '{no:no-prefix}bgp bestpath as-path ignore', ['true', 'false']), + ('graceful_restart_enable', '{no:no-prefix}bgp graceful-restart', ['true', 'false']), + ('gr_restart_time', '{no:no-prefix}bgp graceful-restart restart-time {}'), + ('gr_stale_routes_time', '{no:no-prefix}bgp graceful-restart stalepath-time {}'), + ('gr_preserve_fw_state', '{no:no-prefix}bgp graceful-restart preserve-fw-state', ['true', 'false']), + ('log_nbr_state_changes', '{no:no-prefix}bgp log-neighbor-changes', ['true', 'false']), + ('rr_cluster_id', '{no:no-prefix}bgp cluster-id {}'), + ('rr_allow_out_policy', '{no:no-prefix}bgp route-reflector allow-outbound-policy', ['true', 'false']), + ('disable_ebgp_connected_rt_check', '{no:no-prefix}bgp disable-ebgp-connected-route-check', ['true', 'false']), + ('fast_external_failover', '{no:no-prefix}bgp fast-external-failover', ['true', 'false', True]), + ('network_import_check', '{no:no-prefix}bgp network import-check', ['true', 'false']), + ('graceful_shutdown', '{no:no-prefix}bgp graceful-shutdown', ['true', 'false']), + ('rr_clnt_to_clnt_reflection', '{no:no-prefix}bgp client-to-client reflection', ['true', 'false', True]), + ('max_dynamic_neighbors', '{no:no-prefix}bgp listen limit {}'), + ('read_quanta', '{no:no-prefix}read-quanta {}'), + ('write_quanta', '{no:no-prefix}write-quanta {}'), + ('coalesce_time', '{no:no-prefix}coalesce-time {}'), + ('route_map_process_delay', '{no:no-prefix}bgp route-map delay-timer {}'), + ('deterministic_med', '{no:no-prefix}bgp deterministic-med', ['true', 'false']), + ('med_confed', '{no:no-prefix}bgp bestpath med confed', ['true', 'false']), + ('med_missing_as_worst', '{no:no-prefix}bgp bestpath med missing-as-worst', ['true', 'false']), + ('compare_confed_as_path', '{no:no-prefix}bgp bestpath as-path confed', ['true', 'false']), + ('default_ipv4_unicast', '{no:no-prefix}bgp default ipv4-unicast', ['true', 'false']), + ('default_local_preference', '{no:no-prefix}bgp default local-preference {}'), + ('default_show_hostname', '{no:no-prefix}bgp default show-hostname', ['true', 'false']), + ('default_shutdown', '{no:no-prefix}bgp default shutdown', ['true', 'false']), + ('default_subgroup_pkt_queue_max', '{no:no-prefix}bgp default subgroup-pkt-queue-max {}'), + (['max_med_time', '+max_med_val'], '{no:no-prefix}bgp max-med on-startup {} {}'), + (['max_delay', '+establish_wait'], '{no:no-prefix}update-delay {} {}'), + ('confed_id', '{no:no-prefix}bgp confederation identifier {}'), + ('confed_peers', '{no:no-prefix}bgp confederation peers {}', hdl_confed_peers), + (['keepalive', 'holdtime'], '{no:no-prefix}timers bgp {} {}'), + (['max_med_admin', '+max_med_admin_val'], '{no:no-prefix}bgp max-med administrative {}', ['true', 'false']) + ] + + global_af_key_map = [(['ebgp_route_distance', + 'ibgp_route_distance', + 'local_route_distance'], '{no:no-prefix}distance bgp {} {} {}'), + ('max_ebgp_paths', '{no:no-prefix}maximum-paths {}'), + (['max_ibgp_paths', + '+ibgp_equal_cluster_length'], '{no:no-prefix}maximum-paths ibgp {} {:match-clust-len}', hdl_ibgp_maxpath), + ('route_download_filter', '{no:no-prefix}table-map {}'), + (['route_flap_dampen', + '+route_flap_dampen_half_life', + '+route_flap_dampen_reuse_threshold', + '+route_flap_dampen_suppress_threshold', + '+route_flap_dampen_max_suppress'], '{no:no-prefix}bgp dampening {} {} {} {}', ['true', 'false']), + ('advertise-all-vni', '{no:no-prefix}advertise-all-vni', ['true','false']), + ('advertise-default-gw', '{no:no-prefix}advertise-default-gw', ['true','false']), + ('advertise-ipv4-unicast', '{no:no-prefix}advertise ipv4 unicast', ['true','false']), + ('advertise-ipv6-unicast', '{no:no-prefix}advertise ipv6 unicast', ['true','false']), + ('default-originate-ipv4', '{no:no-prefix}default-originate ipv4', ['true','false']), + ('default-originate-ipv6', '{no:no-prefix}default-originate ipv6', ['true','false']), + ('autort', '{no:no-prefix}autort {}', hdl_enum_conversion), + ('flooding', '{no:no-prefix}flooding {}'), + ('dad-enabled', '{no:no-prefix}dup-addr-detection', ['true','false']), + (['dad-max-moves', + 'dad-time'], '{no:no-prefix}dup-addr-detection max-moves {} time {}'), + ('dad-freeze', '{no:no-prefix}dup-addr-detection freeze {}'), + ('route-distinguisher', '{no:no-prefix}rd {}'), + ('import-rts', '{no:no-prefix}route-target import {}', hdl_import_list), + ('export-rts', '{no:no-prefix}route-target export {}', hdl_export_list), + ('import_vrf', '{no:no-prefix}import vrf {}'), + ('import_vrf_route_map', '{no:no-prefix}import vrf route-map {}') + ] + + cmn_key_map = [('asn&peer_type', '{no:no-prefix}neighbor {} remote-as {}'), + (['local_asn', '+local_as_no_prepend', + '+local_as_replace_as'], '{no:no-prefix}neighbor {} local-as {} {:no-prepend} {:replace-as}'), + (['admin_status', '+shutdown_message'], '{no:no-prefix}neighbor {} shutdown {:shutdown-msg}', ['false', 'true']), + ('local_addr', '{no:no-prefix}neighbor {} update-source {}'), + ('name', '{no:no-prefix}neighbor {} description {}'), + (['ebgp_multihop', '+ebgp_multihop_ttl'],'{no:no-prefix}neighbor {} ebgp-multihop {}', ['true', 'false']), + ('auth_password', '{no:no-prefix}neighbor {} password {} encrypted'), + (['keepalive', 'holdtime'], '{no:no-prefix}neighbor {} timers {} {}'), + ('conn_retry', '{no:no-prefix}neighbor {} timers connect {}'), + ('min_adv_interval', '{no:no-prefix}neighbor {} advertisement-interval {}'), + ('passive_mode', '{no:no-prefix}neighbor {} passive', ['true', 'false']), + ('capability_ext_nexthop', '{no:no-prefix}neighbor {} capability extended-nexthop', ['true', 'false']), + ('disable_ebgp_connected_route_check', '{no:no-prefix}neighbor {} disable-connected-check', ['true', 'false']), + ('enforce_first_as', '{no:no-prefix}neighbor {} enforce-first-as', ['true', 'false']), + ('solo_peer', '{no:no-prefix}neighbor {} solo', ['true', 'false']), + ('ttl_security_hops', '{no:no-prefix}neighbor {} ttl-security hops {}'), + ('bfd', '{no:no-prefix}neighbor {} bfd', ['true', 'false']), + ('bfd_check_ctrl_plane_failure', '{no:no-prefix}neighbor {} bfd check-control-plane-failure', ['true', 'false']), + ('capability_dynamic', '{no:no-prefix}neighbor {} capability dynamic', ['true', 'false']), + ('dont_negotiate_capability', '{no:no-prefix}neighbor {} dont-capability-negotiate', ['true', 'false']), + ('enforce_multihop', '{no:no-prefix}neighbor {} enforce-multihop', ['true', 'false']), + ('override_capability', '{no:no-prefix}neighbor {} override-capability', ['true', 'false']), + ('peer_port', '{no:no-prefix}neighbor {} port {}'), + ('strict_capability_match', '{no:no-prefix}neighbor {} strict-capability-match', ['true', 'false']) + ] + + nbr_key_map = [('peer_group_name', '{no:no-prefix}neighbor {} peer-group {}')] + + nbr_af_key_map = [(['allow_as_in', '+allow_as_count&allow_as_origin'], '{no:no-prefix}neighbor {} allowas-in {:allow-as-in}', ['true', 'false']), + ('admin_status|ipv4', '{no:no-prefix}neighbor {} activate', ['true', 'false', False]), + ('admin_status|ipv6', '{no:no-prefix}neighbor {} activate', ['true', 'false', False]), + ('admin_status|l2vpn', '{no:no-prefix}neighbor {} activate', ['true', 'false', False]), + (['send_default_route', '+default_rmap'], '{no:no-prefix}neighbor {} default-originate {:default-rmap}', ['true', 'false']), + ('default_rmap', '{no:no-prefix}neighbor {} default-originate route-map {}'), + (['max_prefix_limit', '++max_prefix_warning_threshold', + '+max_prefix_restart_interval&max_prefix_warning_only'], '{no:no-prefix}neighbor {} maximum-prefix {} {} {:restart}'), + ('route_map_in', '{no:no-prefix}neighbor {} route-map {} in'), + ('route_map_out', '{no:no-prefix}neighbor {} route-map {} out'), + ('soft_reconfiguration_in', '{no:no-prefix}neighbor {} soft-reconfiguration inbound', ['true', 'false']), + ('unsuppress_map_name', '{no:no-prefix}neighbor {} unsuppress-map {}'), + ('rrclient', '{no:no-prefix}neighbor {} route-reflector-client', ['true', 'false']), + ('weight', '{no:no-prefix}neighbor {} weight {}'), + ('as_override', '{no:no-prefix}neighbor {} as-override', ['true', 'false']), + ('send_community', '{no:no-prefix}neighbor {} send-community {}', hdl_send_com), + ('tx_add_paths', '{no:no-prefix}neighbor {} {:tx-add-paths}'), + (['++unchanged_as_path', + '++unchanged_med', '++unchanged_nexthop'], '{no:no-prefix}neighbor {} attribute-unchanged {:uchg-as-path} {:uchg-med} {:uchg-nh}', hdl_attr_unchanged), + ('filter_list_in', '{no:no-prefix}neighbor {} filter-list {} in'), + ('filter_list_out', '{no:no-prefix}neighbor {} filter-list {} out'), + ('nhself', '{no:no-prefix}neighbor {} next-hop-self', ['true', 'false']), + ('nexthop_self_force', '{no:no-prefix}neighbor {} next-hop-self force', ['true', 'false']), + ('prefix_list_in', '{no:no-prefix}neighbor {} prefix-list {} in'), + ('prefix_list_out', '{no:no-prefix}neighbor {} prefix-list {} out'), + (['remove_private_as_enabled', + '++remove_private_as_all', + '+replace_private_as'], '{no:no-prefix}neighbor {} remove-private-AS {:rm-as-all} {:rm-as-repl}', hdl_rm_priv_as, ['true', 'false']), + ('cap_orf', '{no:no-prefix}neighbor {} capability orf prefix-list {}', hdl_capa_orf_pfxlist), + ('route_server_client', '{no:no-prefix}neighbor {} route-server-client', ['true', 'false']), + ] + + route_map_key_map = [('match_interface', '{no:no-prefix}match interface {}'), + ('match_prefix_set|ipv4', '{no:no-prefix}match ip address prefix-list {}'), + ('match_prefix_set|ipv6', '{no:no-prefix}match ipv6 address prefix-list {}'), + ('match_neighbor', '[bgpd]{no:no-prefix}match peer {:peer-ip}'), + ('match_tag', '{no:no-prefix}match tag {}'), + ('match_protocol', '[zebra]{no:no-prefix}match source-protocol {:src-proto}'), + ('match_next_hop_set|ipv4', '{no:no-prefix}match ip next-hop prefix-list {}'), + ('match_next_hop_set|ipv6', '{no:no-prefix}match ip next-hop prefix-list {}'), #match ipv6 next-hop prefix-list not suppported by frr + ('match_med', '{no:no-prefix}match metric {}'), + ('match_origin', '[bgpd]{no:no-prefix}match origin {:tolower}'), + ('match_local_pref', '[bgpd]{no:no-prefix}match local-preference {}'), + ('match_community', '[bgpd]{no:no-prefix}match community {}'), + ('match_ext_community', '[bgpd]{no:no-prefix}match extcommunity {}'), + ('match_as_path', '[bgpd]{no:no-prefix}match as-path {}'), + ('match_src_vrf', '[bgpd]{no:no-prefix}match source-vrf {}'), + ('call_route_map', '{no:no-prefix}call {:enable-only}'), + ('set_origin', '[bgpd]{no:no-prefix}set origin {:tolower}'), + ('set_local_pref', '[bgpd]{no:no-prefix}set local-preference {}'), + ('set_next_hop', '{no:no-prefix}set ip next-hop {}'), + ('set_ipv6_next_hop_global', '[bgpd]{no:no-prefix}set ipv6 next-hop global {}'), + ('set_ipv6_next_hop_prefer_global', '[bgpd]{no:no-prefix}set ipv6 next-hop prefer-global', ['true', 'false']), + (['set_metric_action', '+set_metric', '+set_med'], '{}set metric {} ', handle_rmap_set_metric), + ('set_med', '{no:no-prefix}set metric {}'), + (('set_asn', '+set_repeat_asn'), '[bgpd]{no:no-prefix}set as-path prepend {:repeat}', hdl_set_asn), + ('set_asn_list', '[bgpd]{no:no-prefix}set as-path prepend {:asn_list}', hdl_set_asn_list), + ('set_community_inline', '[bgpd]{no:no-prefix}set community {}'), + ('set_community_ref', '[bgpd]{no:no-prefix}set community {:com-ref}'), + ('set_ext_community_inline', '[bgpd]{no:no-prefix}set extcommunity {:ext-com-list}', hdl_set_extcomm, True), + ('set_ext_community_ref', '[bgpd]{no:no-prefix}set extcommunity {:ext-com-ref}', hdl_set_extcomm, False) + ] + + bfd_peer_shop_key_map = [('enabled', '{no:no-prefix}shutdown', ['false', 'true']), + ('desired-minimum-tx-interval', '{no:no-prefix}transmit-interval {}'), + ('required-minimum-receive', '{no:no-prefix}receive-interval {}'), + ('desired-minimum-echo-receive', '{no:no-prefix}echo-interval {}'), + ('detection-multiplier', '{no:no-prefix}detect-multiplier {}'), + ('echo-active', '{no:no-prefix}echo-mode', ['true', 'false']) + ] + + bfd_peer_mhop_key_map = [('enabled', '{no:no-prefix}shutdown', ['false', 'true']), + ('desired-minimum-tx-interval', '{no:no-prefix}transmit-interval {}'), + ('required-minimum-receive', '{no:no-prefix}receive-interval {}'), + ('detection-multiplier', '{no:no-prefix}detect-multiplier {}'), + ] + + listen_prefix_key_map = [('peer_group', '{no:no-prefix}bgp listen range {} peer-group {}')] + + community_set_key_map = [(('set_type', 'match_action', 'community_member'), '{no:no-prefix}bgp community-list {}', hdl_com_set, False)] + extcommunity_set_key_map = [(('set_type', 'match_action', 'community_member'), '{no:no-prefix}bgp extcommunity-list {}', hdl_com_set, True)] + + aspath_set_key_map = [('as_path_set_member', '{no:no-prefix}bgp as-path access-list {}', hdl_aspath_set)] + + route_redist_key_map = [(['protocol', '++metric', '+route_map'], + '{no:no-prefix}redistribute {} {:redist-metric} {:redist-route-map}', hdl_route_redist_set)] + + af_aggregate_key_map = [(['ip_prefix', '++as_set', '++summary_only', '+policy'], + '{no:no-prefix}aggregate-address {2} {3:aggr-as-set} {4:aggr-summary-only} {5:aggr-policy}', hdl_af_aggregate)] + + af_network_key_map = [(['ip_prefix', '++policy', '+backdoor'], '{no:no-prefix}network {2} {3:network-policy} {4:network-backdoor}')] + + global_evpn_vni_key_map = [('advertise-default-gw', '{no:no-prefix}advertise-default-gw', ['true','false']), + ('route-distinguisher', '{no:no-prefix}rd {}'), + ('import-rts', '{no:no-prefix}route-target import {}', hdl_import_list), + ('export-rts', '{no:no-prefix}route-target export {}', hdl_export_list)] + + ospfv2_global_key_map = [('enable', '{no:no-prefix}'), + ('auto-cost-reference-bandwidth', '{no:no-prefix}auto-cost reference-bandwidth {}'), + ('ospf-rfc1583-compatible', '{no:no-prefix}compatible rfc1583', ['true', 'false']), + ('max-metric-administrative', '{no:no-prefix}max-metric router-lsa administrative', ['true', 'false']), + ('max-metric-on-shutdown', '{no:no-prefix}max-metric router-lsa on-shutdown {}'), + ('max-metric-on-startup', '{no:no-prefix}max-metric router-lsa on-startup {}'), + ('router-id', '{no:no-prefix}ospf router-id {}'), + ('abr-type', '{}ospf abr-type {:abrtype}', handle_ospf_abrtype), + ('write-multiplier', '{no:no-prefix}write-multiplier {}'), + ('passive-interface-default', '{no:no-prefix}passive-interface default', ['true', 'false']), + ('lsa-refresh-timer', '{no:no-prefix}refresh timer {}'), + ('lsa-min-arrival-timer', '{no:no-prefix}timers lsa min-arrival {}'), + ('lsa-min-interval-timer', '{no:no-prefix}timers throttle lsa all {}'), + (['spf-initial-delay', 'spf-maximum-delay', 'spf-throttle-delay'], '{no:no-prefix}timers throttle spf {} {} {}'), + ('log-adjacency-changes', '{}log-adjacency-changes {}', hdl_ospf_log), + ('default-metric', '{no:no-prefix}default-metric {}'), + ('distance-all', '{no:no-prefix}distance {}'), + ('distance-external', '{no:no-prefix}distance ospf external {}'), + ('distance-inter-area', '{no:no-prefix}distance ospf inter-area {}'), + ('distance-intra-area', '{no:no-prefix}distance ospf intra-area {}')] + + ospfv2_area_key_map = [('stub', '{no:no-prefix}area {} stub'), + ('stub-no-summary', '{no:no-prefix}area {} stub no-summary'), + ('import-list', '{no:no-prefix}area {} import-list {}'), + ('export-list', '{no:no-prefix}area {} export-list {}'), + ('filter-list-in', '{no:no-prefix}area {} filter-list prefix {} in'), + ('filter-list-out', '{no:no-prefix}area {} filter-list prefix {} out'), + ('authentication', '{}area {} authentication {}', handle_ospf_area_auth), + ('stub-default-cost', '{no:no-prefix}area {} default-cost {}'), + ('shortcut', '{}area {} shortcut {}', handle_ospf_area_shortcut)] + + ospfv2_area_vlink_key_map = [('enable', '{no:no-prefix}area {} virtual-link {}'), + ('dead-interval', '{no:no-prefix}area {} virtual-link {} dead-interval {}'), + ('hello-interval', '{no:no-prefix}area {} virtual-link {} hello-interval {}'), + ('retransmission-interval', '{no:no-prefix}area {} virtual-link {} retransmit-interval {}'), + ('transmit-delay', '{no:no-prefix}area {} virtual-link {} transmit-delay {}'), + ('authentication-type', '{}area {} virtual-link {} authentication {}', handle_ospf_area_vlink_auth), + ('authentication-key', '{no:no-prefix}area {} virtual-link {} authentication-key {}'), + (['authentication-key-id', 'authentication-md5-key'], '{no:no-prefix}area {} virtual-link {} authentication message-digest message-digest-key {} md5 {}')] + + ospfv2_area_range_key_map =[('advertise', '{} area {} range {} {}', handle_ospf_area_range_advt), + ('metric', '{no:no-prefix} area {} range {} cost {}'), + ('substitue-prefix', '{no:no-prefix} area {} range {} substitute {}')] + + ospfv2_distribution_key_map = [('route-map|BGP|IMPORT', '{no:no-prefix}distribute-list {} out bgp'), + ('route-map|STATIC|IMPORT', '{no:no-prefix}distribute-list {} out static')] + + ospfv2_interface_key_map = [ + ('area-id', '{}ip ospf area {} {}', handle_ospf_if_common), + ('authentication-type', '{}ip ospf authentication {} {}', handle_ospf_if_authtype), + ('authentication-key', '{}ip ospf authentication-key {} {}', handle_ospf_if_common), + ('bfd-enable', '{no:no-prefix}ip ospf bfd ', ['true', 'false']), + ('metric', '{}ip ospf cost {} {}', handle_ospf_if_common), + ('dead-interval', '{}ip ospf dead-interval {} {}', handle_ospf_if_common), + ('hello-multiplier', '{}ip ospf dead-interval minimal hello-multiplier {} {}', handle_ospf_if_common), + ('hello-interval', '{}ip ospf hello-interval {} {}', handle_ospf_if_common), + (['authentication-key-id', '+authentication-md5-key'], '{}ip ospf message-digest-key {} md5 {} {}', handle_ospf_if_md5key), + ('mtu-ignore', '{}ip ospf mtu-ignore {}', handle_ospf_if_mtu_ignore), + ('network-type', '{}ip ospf network {}', handle_ospf_if_nwtype), + ('priority', '{}ip ospf priority {} {}', handle_ospf_if_common), + ('retransmission-interval', '{}ip ospf retransmit-interval {} {}', handle_ospf_if_common), + ('transmit-delay', '{}ip ospf transmit-delay {} {}', handle_ospf_if_common), + ] + static_route_map = [(['ip_prefix|ipv4', '++blackhole', '++nexthop', '++ifname', '++track', '++tag', '++distance', '++nexthop-vrf'], + '{no:no-prefix}ip route {} {:blackhole} {} {} {:track} {:nh-tag} {} {:nh-vrf}', hdl_static_route, socket.AF_INET), + (['ip_prefix|ipv6', '++blackhole', '++nexthop', '++ifname', '++track', '++tag', '++distance', '++nexthop-vrf'], + '{no:no-prefix}ipv6 route {} {:blackhole} {} {} {:track} {:nh-tag} {} {:nh-vrf} ', hdl_static_route, socket.AF_INET6)] + pim_interface_key_map = [('mode', '{no:no-prefix}ip pim', ['sm','']), + ('dr-priority', '{no:no-prefix}ip pim drpriority {}'), + ('hello-interval', '{no:no-prefix}ip pim hello {:pim_hello_parms}', + hdl_set_pim_hello_parms), + ('bfd-enabled', '{no:no-prefix}ip pim bfd', ['true', 'false']), + ] + pim_global_key_map = [('join-prune-interval', '{no:no-prefix}ip pim join-prune-interval {}'), + ('keep-alive-timer', '{no:no-prefix}ip pim keep-alive-timer {}'), + ('ssm-ranges', '{no:no-prefix}ip pim ssm prefix-list {}'), + ('ecmp-enabled', '{no:no-prefix}ip pim ecmp', ['true', 'false']), + ('ecmp-rebalance-enabled', '{no:no-prefix}ip pim ecmp rebalance',['true', 'false']), + ] + + igmp_mcast_grp_key_map =[('enable', '{no:no-prefix}ip igmp join {} {}'), + ] + + igmp_interface_config_key_map = [ + ('enabled', 'ip igmp {}', handle_igmp_if_enable), + ('version', '{no:no-prefix}ip igmp version {}'), + ('query-interval', 'ip igmp query-interval {}', handle_igmp_if_common), + ('query-max-response-time', 'ip igmp query-max-response-time {}', handle_igmp_if_common), + ('last-member-query-count', 'ip igmp last-member-query-count {}', handle_igmp_if_common), + ('last-member-query-interval', 'ip igmp last-member-query-interval {}', handle_igmp_if_common), + ] + ip_sla_key_map = [ + ('sla_id', '{no:no-prefix}ip sla {}'), + ('frequency', 'frequency {}', handle_ip_sla_common), + ('threshold', 'threshold {}', handle_ip_sla_common), + ('timeout', 'timeout {}', handle_ip_sla_common), + ('tcp_source_port', 'source-port {}', handle_ip_sla_common), + ('tcp_source_ip', 'source-address {}', handle_ip_sla_common), + ('tcp_dst_ip', 'tcp-connect {} port {}', handle_ip_sla_tcp_connect), + ('tcp_vrf', 'source-vrf {}', handle_ip_sla_common), + ('tcp_dst_port', 'tcp-connect {} port {}', handle_ip_sla_tcp_connect), + ('tcp_source_interface', 'source-interface {}', handle_ip_sla_common), + ('tcp_ttl', 'ttl {}', handle_ip_sla_common), + ('tcp_tos', 'tos {}', handle_ip_sla_common), + ('icmp_source_interface', 'source-interface {}', handle_ip_sla_common), + ('icmp_source_ip', 'source-address {}', handle_ip_sla_common), + ('icmp_dst_ip', 'icmp-echo {}', handle_ip_sla_icmp_echo), + ('icmp_vrf', 'source-vrf {}', handle_ip_sla_common), + ('icmp_size', 'request-data-size {}', handle_ip_sla_common), + ('icmo_ttl', 'ttl {}', handle_ip_sla_common), + ('icmp_tos', 'tos {}', handle_ip_sla_common), + ] + + + tbl_to_key_map = {'BGP_GLOBALS': global_key_map, + 'BGP_GLOBALS_AF': global_af_key_map, + 'BGP_GLOBALS_LISTEN_PREFIX': listen_prefix_key_map, + 'BGP_NEIGHBOR': cmn_key_map[0:2] + nbr_key_map + cmn_key_map[2:], + 'BGP_PEER_GROUP': cmn_key_map, + 'BGP_NEIGHBOR_AF': nbr_af_key_map, + 'BGP_PEER_GROUP_AF': nbr_af_key_map, + 'ROUTE_MAP': route_map_key_map, + 'COMMUNITY_SET': community_set_key_map, + 'EXTENDED_COMMUNITY_SET': extcommunity_set_key_map, + 'AS_PATH_SET': aspath_set_key_map, + 'ROUTE_REDISTRIBUTE': route_redist_key_map, + 'BGP_GLOBALS_AF_AGGREGATE_ADDR': af_aggregate_key_map, + 'BGP_GLOBALS_AF_NETWORK': af_network_key_map, + 'BGP_GLOBALS_EVPN_VNI': global_evpn_vni_key_map, + 'BFD_PEER_SINGLE_HOP': bfd_peer_shop_key_map, + 'BFD_PEER_MULTI_HOP': bfd_peer_mhop_key_map, + 'IP_SLA': ip_sla_key_map, + 'OSPFV2_ROUTER': ospfv2_global_key_map, + 'OSPFV2_ROUTER_AREA': ospfv2_area_key_map, + 'OSPFV2_ROUTER_AREA_VIRTUAL_LINK':ospfv2_area_vlink_key_map, + 'OSPFV2_ROUTER_AREA_POLICY_ADDRESS_RANGE':ospfv2_area_range_key_map, + 'OSPFV2_INTERFACE': ospfv2_interface_key_map, + 'STATIC_ROUTE': static_route_map, + 'PIM_GLOBALS': pim_global_key_map, + 'PIM_INTERFACE': pim_interface_key_map, + 'IGMP_INTERFACE': igmp_mcast_grp_key_map, + 'IGMP_INTERFACE_QUERY': igmp_interface_config_key_map + } + + vrf_tables = {'BGP_GLOBALS', 'BGP_GLOBALS_AF', + 'BGP_NEIGHBOR', 'BGP_PEER_GROUP', 'BGP_NEIGHBOR_AF', 'BGP_PEER_GROUP_AF', + 'BGP_GLOBALS_LISTEN_PREFIX', 'ROUTE_REDISTRIBUTE', + 'BGP_GLOBALS_AF_AGGREGATE_ADDR', 'BGP_GLOBALS_AF_NETWORK', + 'BGP_GLOBALS_EVPN_RT', 'BGP_GLOBALS_EVPN_VNI', 'BGP_GLOBALS_EVPN_VNI_RT'} + + @staticmethod + def __peer_is_ip(peer): + try: + socket.inet_pton(socket.AF_INET, peer) + return True + except socket.error: + pass + try: + socket.inet_pton(socket.AF_INET6, peer) + return True + except socket.error: + pass + return False + + def __init__(self): + self.config_db = ExtConfigDBConnector({'STATIC_ROUTE': {'nexthop', 'ifname', 'distance', 'nexthop-vrf', 'blackhole', 'track'}}) + try: + self.config_db.connect() + except Exception as e: + syslog.syslog(syslog.LOG_ERR, '[bgp cfgd] Failed connecting to config DB with exception:' + str(e)) + db_entry = self.config_db.get_entry('DEVICE_METADATA', 'localhost') + if 'bgp_asn' in db_entry: + self.metadata_asn = db_entry['bgp_asn'] + else: + self.metadata_asn = None + if 'docker_routing_config_mode' in db_entry: + self.config_mode = db_entry['docker_routing_config_mode'] + else: + self.config_mode = "separated" + # VRF ==> local_as + self.bgp_asn = {} + # VRF ==> confederation peer list + self.bgp_confed_peers = {} + glb_table = self.config_db.get_table('BGP_GLOBALS') + for vrf, entry in glb_table.items(): + if 'local_asn' in entry: + self.bgp_asn[vrf] = entry['local_asn'] + syslog.syslog(syslog.LOG_DEBUG, 'Init Config DB Data: VRF %s Local_ASN %s' % (vrf, self.bgp_asn[vrf])) + if 'confed_peers' in entry: + self.bgp_confed_peers[vrf] = set(entry['confed_peers']) + # VRF ==> grp_name ==> peer_group + self.bgp_peer_group = {} + # VRF ==> set of interface neighbor + self.bgp_intf_nbr = {} + nbr_table = self.config_db.get_table('BGP_NEIGHBOR') + pg_table = self.config_db.get_table('BGP_PEER_GROUP') + for key, entry in pg_table.items(): + vrf, pg = key + self.bgp_peer_group.setdefault(vrf, {})[pg] = BGPPeerGroup(vrf) + syslog.syslog(syslog.LOG_DEBUG, 'Init Config DB Data: VRF %s Peer_Group %s' % (vrf, pg)) + for key, entry in nbr_table.items(): + if len(key) != 2: + continue + vrf, peer = key + if 'peer_group_name' in entry: + pg_name = entry['peer_group_name'] + if vrf in self.bgp_peer_group and pg_name in self.bgp_peer_group[vrf]: + self.bgp_peer_group[vrf][pg_name].ref_nbrs.add(peer) + syslog.syslog(syslog.LOG_DEBUG, 'Init Config DB Data: VRF %s Neighbor %s Peer_Group %s' % + (vrf, peer, pg_name)) + if not self.__peer_is_ip(peer): + self.bgp_intf_nbr.setdefault(vrf, set()).add(peer) + # map_name ==> seq_no ==> operation + self.route_map = {} + rtmap_table = self.config_db.get_table('ROUTE_MAP') + for key, entry in rtmap_table.items(): + rtmap_name, seq_no = key + syslog.syslog(syslog.LOG_DEBUG, 'Init Config DB Data: Route_Map %s Seq_NO %s' % (rtmap_name, seq_no)) + if 'route_operation' in entry: + self.route_map.setdefault(rtmap_name, {})[seq_no] = entry['route_operation'] + + self.comm_set_list = {} + comm_table = self.config_db.get_table('COMMUNITY_SET') + for key, entry in comm_table.items(): + syslog.syslog(syslog.LOG_DEBUG, 'Init Config DB Data: Community %s' % key) + self.comm_set_list[key] = CommunityList(key, False) + for k, v in entry.items(): + self.comm_set_list[key].db_data_to_attr(k, v) + self.extcomm_set_list = {} + extcomm_table = self.config_db.get_table('EXTENDED_COMMUNITY_SET') + for key, entry in extcomm_table.items(): + syslog.syslog(syslog.LOG_DEBUG, 'Init Config DB Data: Extended_Community %s' % key) + self.extcomm_set_list[key] = CommunityList(key, True) + for k, v in entry.items(): + self.extcomm_set_list[key].db_data_to_attr(k, v) + self.prefix_set_list = {} + pfx_set_table = self.config_db.get_table('PREFIX_SET') + for key, entry in pfx_set_table.items(): + if 'mode' in entry: + syslog.syslog(syslog.LOG_DEBUG, 'Init Config DB Data: Prefix_Set %s mode %s' % (key, entry['mode'])) + self.prefix_set_list[key] = MatchPrefixList(entry['mode'].lower()) + pfx_table = self.config_db.get_table('PREFIX') + for key, entry in pfx_table.items(): + pfx_set_name, ip_pfx, len_range = key + syslog.syslog(syslog.LOG_DEBUG, 'Init Config DB Data: Prefix %s range %s of set %s' % (ip_pfx, len_range, pfx_set_name)) + if len_range == 'exact': + len_range = None + if pfx_set_name in self.prefix_set_list and 'action' in entry: + try: + self.prefix_set_list[pfx_set_name].add_prefix(ip_pfx, len_range, entry['action']) + except ValueError: + pass + self.as_path_set_list = {} + aspath_table = self.config_db.get_table('AS_PATH_SET') + for key, entry in aspath_table.items(): + if 'as_path_set_member' in entry: + syslog.syslog(syslog.LOG_DEBUG, 'Init Config DB Data: AS_Path_Set %s member %s' % (key, entry['as_path_set_member'])) + self.as_path_set_list[key] = entry['as_path_set_member'][:] + self.tag_set_list = {} + + self.af_aggr_list = {} + af_aggr_table = self.config_db.get_table('BGP_GLOBALS_AF_AGGREGATE_ADDR') + for key, entry in af_aggr_table.items(): + vrf, af_type, ip_pfx = key + af, _ = af_type.lower().split('_') + norm_ip_pfx = MatchPrefix.normalize_ip_prefix((socket.AF_INET if af == 'ipv4' else socket.AF_INET6), ip_pfx) + if norm_ip_pfx is not None: + syslog.syslog(syslog.LOG_DEBUG, 'Init Config DB Data: AF Aggregate Prefix %s of vrf %s AF %s' % (norm_ip_pfx, vrf, af)) + aggr_obj = AggregateAddr() + for k, v in entry.items(): + if v == 'true': + setattr(aggr_obj, k, True) + self.af_aggr_list.setdefault(vrf, {})[norm_ip_pfx] = aggr_obj + + self.vrf_vni_map = {} + vrf_table = self.config_db.get_table('VRF') + for key, entry in vrf_table.items(): + if 'vni' in entry: + self.vrf_vni_map[key] = entry['vni'] + + # VRF ==> ip_prefix ==> nexthop list + self.static_route_list = {} + sroute_table = self.config_db.get_table('STATIC_ROUTE') + get_list = lambda v: v.split(',') if v is not None else None + for key, entry in sroute_table.items(): + if type(key) is tuple and len(key) == 2: + vrf, ip_prefix = key + else: + vrf = self.DEFAULT_VRF + ip_prefix = key + af, ip_prefix = IpNextHopSet.get_af_norm_prefix(ip_prefix) + nh_attr = lambda k: get_list(entry.get(k, None)) + self.static_route_list.setdefault(vrf, {})[ip_prefix] = IpNextHopSet(af, + nh_attr('blackhole'), nh_attr('nexthop'),nh_attr('track'), + nh_attr('ifname'), nh_attr('tag'), nh_attr('distance'), + nh_attr('nexthop-vrf')) + + self.table_handler_list = [ + ('VRF', self.vrf_handler), + ('DEVICE_METADATA', self.metadata_handler), + ('BGP_GLOBALS', self.bgp_global_handler), + ('BGP_GLOBALS_AF', self.bgp_af_handler), + ('PREFIX_SET', self.bgp_table_handler_common), + ('PREFIX', self.bgp_table_handler_common), + ('COMMUNITY_SET', self.comm_set_handler), + ('EXTENDED_COMMUNITY_SET', self.comm_set_handler), + ('ROUTE_MAP', self.bgp_table_handler_common), + ('BGP_PEER_GROUP', self.bgp_neighbor_handler), + ('BGP_NEIGHBOR', self.bgp_neighbor_handler), + ('BGP_PEER_GROUP_AF', self.bgp_table_handler_common), + ('BGP_NEIGHBOR_AF', self.bgp_table_handler_common), + ('BGP_GLOBALS_LISTEN_PREFIX', self.bgp_table_handler_common), + ('BGP_GLOBALS_EVPN_VNI', self.bgp_table_handler_common), + ('BGP_GLOBALS_EVPN_RT', self.bgp_table_handler_common), + ('BGP_GLOBALS_EVPN_VNI_RT', self.bgp_table_handler_common), + ('BFD_PEER', self.bfd_handler), + ('NEIGHBOR_SET', self.bgp_table_handler_common), + ('NEXTHOP_SET', self.bgp_table_handler_common), + ('TAG_SET', self.bgp_table_handler_common), + ('AS_PATH_SET', self.bgp_table_handler_common), + ('ROUTE_REDISTRIBUTE', self.bgp_table_handler_common), + ('BGP_GLOBALS_AF_AGGREGATE_ADDR', self.bgp_table_handler_common), + ('BGP_GLOBALS_AF_NETWORK', self.bgp_table_handler_common), + ('BFD_PEER_SINGLE_HOP', self.bgp_table_handler_common), + ('BFD_PEER_MULTI_HOP', self.bgp_table_handler_common), + ('IP_SLA', self.bgp_table_handler_common), + ('OSPFV2_ROUTER', self.bgp_table_handler_common), + ('OSPFV2_ROUTER_AREA', self.bgp_table_handler_common), + ('OSPFV2_ROUTER_AREA_VIRTUAL_LINK', self.bgp_table_handler_common), + ('OSPFV2_ROUTER_AREA_NETWORK', self.bgp_table_handler_common), + ('OSPFV2_ROUTER_AREA_POLICY_ADDRESS_RANGE', self.bgp_table_handler_common), + ('OSPFV2_ROUTER_DISTRIBUTE_ROUTE', self.bgp_table_handler_common), + ('OSPFV2_INTERFACE', self.bgp_table_handler_common), + ('OSPFV2_ROUTER_PASSIVE_INTERFACE', self.bgp_table_handler_common), + ('STATIC_ROUTE', self.bgp_table_handler_common), + ('PIM_GLOBALS', self.bgp_table_handler_common), + ('PIM_INTERFACE', self.bgp_table_handler_common), + ('IGMP_INTERFACE', self.bgp_table_handler_common), + ('IGMP_INTERFACE_QUERY', self.bgp_table_handler_common) + ] + self.bgp_message = queue.Queue(0) + self.table_data_cache = self.config_db.get_table_data([tbl for tbl, _ in self.table_handler_list]) + syslog.syslog(syslog.LOG_DEBUG, 'Init Cached DB data') + for key, entry in self.table_data_cache.items(): + syslog.syslog(syslog.LOG_DEBUG, ' %-20s : %s' % (key, entry)) + if self.config_mode == "unified": + for table, _ in self.table_handler_list: + table_list = self.config_db.get_table(table) + for key, data in table_list.items(): + syslog.syslog(syslog.LOG_DEBUG, 'config replay for table {} key {}'.format(table, key)) + upd_data = {} + for upd_key, upd_val in data.items(): + upd_data[upd_key] = CachedDataWithOp(upd_val, CachedDataWithOp.OP_ADD) + self.bgp_message.put((self.config_db.serialize_key(key), False, table, upd_data)) + upd_data_list = [] + self.__update_bgp(upd_data_list) + for table1, key1, data1 in upd_data_list: + table_key = ExtConfigDBConnector.get_table_key(table1, key1) + self.__update_cache_data(table_key, data1) + + def subscribe_all(self): + for table, hdlr in self.table_handler_list: + self.config_db.subscribe(table, hdlr) + + @staticmethod + def __run_command(table, command, daemons = None): + return g_run_command(table, command, True, daemons) + + def metadata_handler(self, table, key, data): + if key != 'localhost': + syslog.syslog(syslog.LOG_DEBUG, 'not localhost data update') + return + if data is None or 'bgp_asn' not in data: + self.metadata_asn = None + else: + self.metadata_asn = data['bgp_asn'] + + def bfd_handler(self, table, key, data): + syslog.syslog(syslog.LOG_INFO, '[bgp cfgd](bfd) value for {} changed to {}'.format(key, data)) + #get frr bfd session key + key_params = key.split('|') + cmd = 'peer {}'.format(key_params[0]) + if len(key_params) == 4 and key_params[3] == 'multihop': + cmd = cmd + ' multihop ' + if key_params[1] != 'null': + cmd = cmd + ' local-address ' + key_params[1] + if key_params[2] != 'null': + cmd = cmd + ' interface ' + key_params[2] + if not data: + #BFD peer is deleted + command = "vtysh -c 'configure terminal' -c 'bfd' -c 'no {}'".format(cmd) + self.__run_command(table, command) + else: + #create/update case + command = "vtysh -c 'configure terminal' -c 'bfd' -c '{}'".format(cmd) + for param in data: + if param == 'transmit_interval': + command = command + " -c 'transmit-interval {}'".format(data[param]) + elif param == 'receive_interval': + command = command + " -c 'receive-interval {}'".format(data[param]) + elif param == 'multiplier': + command = command + " -c 'detect-multiplier {}'".format(data[param]) + elif param == 'echo_mode' and data[param] == 'true': + command = command + " -c 'echo-mode'" + elif param == 'echo_interval': + command = command + " -c 'echo-interval {}'".format(data[param]) + elif param == 'label': + command = command + " -c 'label {}'".format(data[param]) + elif param == 'admin_status' and data[param] == 'up': + command = command + " -c 'no shutdown'" + elif param == 'admin_status' and data[param] == 'down': + command = command + " -c 'shutdown'" + self.__run_command(table, command) + + def vrf_handler(self, table, key, data): + syslog.syslog(syslog.LOG_INFO, '[bgp cfgd](vrf) value for {} changed to {}'.format(key, data)) + #get vrf key + key_params = key.split('|') + cmd = 'vrf {}'.format(key_params[0]) + if not data: + #VRF is deleted + command = "vtysh -c 'configure terminal' -c '{}'".format(cmd) + if key_params[0] in self.vrf_vni_map: + command = command + " -c 'no vni {}'".format(self.vrf_vni_map[key_params[0]]) + del self.vrf_vni_map[key_params[0]] + self.__run_command(table, command) + else: + #create/update case + command = "vtysh -c 'configure terminal' -c '{}'".format(cmd) + positive_execute = False + for param in data: + if param == 'vni': + if data[param] != '0': + command = command + " -c 'vni {}'".format(data[param]) + self.vrf_vni_map[key_params[0]] = data[param] + positive_execute = True + elif key_params[0] in self.vrf_vni_map: + command = command + " -c 'no vni {}'".format(self.vrf_vni_map[key_params[0]]) + del self.vrf_vni_map[key_params[0]] + positive_execute = True + if positive_execute == True: + self.__run_command(table, command) + + def __get_vrf_asn(self, vrf): + if vrf in self.bgp_asn: + return self.bgp_asn[vrf] + if vrf == self.DEFAULT_VRF and self.metadata_asn is not None: + return self.metadata_asn + return None + + def __delete_vrf_asn(self, vrf, table, data): + if vrf != self.DEFAULT_VRF and vrf not in self.bgp_asn: + syslog.syslog(syslog.LOG_ERR, 'non-default VRF {} was not configured'.format(vrf)) + return False + local_asn = self.__get_vrf_asn(vrf) + if local_asn is None: + syslog.syslog(syslog.LOG_ERR, 'failed to get local ASN of VRF {} for delete'.format(vrf)) + return False + command = "vtysh -c 'configure terminal' -c 'no router bgp {}".format(local_asn) + if vrf != self.DEFAULT_VRF: + command += " vrf {}'".format(vrf) + else: + command += "'" + if not self.__run_command(table, command): + syslog.syslog(syslog.LOG_ERR, 'failed to delete local_asn for VRF %s' % vrf) + return False + if vrf in self.bgp_asn: + del(self.bgp_asn[vrf]) + for dkey, dval in data.items(): + # force delete all VRF instance attributes in cache + dval.status = CachedDataWithOp.STAT_SUCC + dval.op = CachedDataWithOp.OP_DELETE + return True + + def __cleanup_nbr_cache(self, vrf, nbr): + nbr_key = ExtConfigDBConnector.get_table_key('BGP_NEIGHBOR', + self.config_db.serialize_key((vrf, nbr))) + self.table_data_cache.pop(nbr_key, None) + for af in ['ipv4', 'ipv6']: + nbr_af_key = ExtConfigDBConnector.get_table_key('BGP_NEIGHBOR_AF', + self.config_db.serialize_key((vrf, nbr, af + '_unicast'))) + self.table_data_cache.pop(nbr_af_key, None) + + def __delete_vrf_neighbor(self, vrf, peer, data, is_peer_grp): + if is_peer_grp: + if vrf in self.bgp_peer_group and peer in self.bgp_peer_group[vrf]: + del(self.bgp_peer_group[vrf][peer]) + else: + if vrf in self.bgp_peer_group: + for _, peer_grp in self.bgp_peer_group[vrf].items(): + if peer in peer_grp.ref_nbrs: + peer_grp.ref_nbrs.remove(peer) + if not self.__peer_is_ip(peer) and vrf in self.bgp_intf_nbr and peer in self.bgp_intf_nbr[vrf]: + self.bgp_intf_nbr[vrf].remove(peer) + self.__cleanup_nbr_cache(vrf, peer) + for dkey, dval in data.items(): + # bypass cache update because cache entry was removed + dval.status = CachedDataWithOp.STAT_SUCC + dval.op = CachedDataWithOp.OP_NONE + + def __delete_pg_neighbors(self, vrf, pg_name): + syslog.syslog(syslog.LOG_DEBUG, + 'delete all associated neighbors of peer group %s of vrf %s from cache' % (pg_name, vrf)) + if vrf in self.bgp_peer_group and pg_name in self.bgp_peer_group[vrf]: + peer_grp = self.bgp_peer_group[vrf][pg_name] + for nbr in peer_grp.ref_nbrs: + if vrf in self.bgp_intf_nbr and nbr in self.bgp_intf_nbr[vrf]: + self.bgp_intf_nbr[vrf].remove(nbr) + self.__cleanup_nbr_cache(vrf, nbr) + peer_grp.ref_nbrs.clear() + + def __delete_route_map(self, map_name, seq_no, data): + if map_name in self.route_map and seq_no in self.route_map[map_name]: + del(self.route_map[map_name][seq_no]) + for dkey, dval in data.items(): + # force delete all neighbor attributes in cache + dval.status = CachedDataWithOp.STAT_SUCC + dval.op = CachedDataWithOp.OP_DELETE + + @staticmethod + def __vrf_based_table(table_name): + return table_name in BGPConfigDaemon.vrf_tables + + @staticmethod + def get_prefix_set_name(orig_name, table_name): + new_name = orig_name + if table_name == 'NEIGHBOR_SET': + new_name += '_neighbor' + elif table_name == 'NEXTHOP_SET': + new_name += '_nexthop' + return new_name + + def __apply_dep_vrf_table(self, vrf, table_name, *table_key, **extra_args): + if len(table_key) > 0: + new_key = (vrf,) + table_key + entry_list = {new_key: self.config_db.get_entry(table_name, new_key)} + else: + entry_list = self.config_db.get_table(table_name) + match_fn = extra_args.get('match', None) + for key, data in entry_list.items(): + if data is None or len(key) == 0 or key[0] != vrf: + continue + if match_fn is not None and not match_fn(data): + continue + syslog.syslog(syslog.LOG_DEBUG, 'attr re-apply for vrf {} table {} key {} data {}'.format(vrf, table_name, key, data)) + upd_data = {} + for upd_key, upd_val in data.items(): + upd_data[upd_key] = CachedDataWithOp(upd_val, CachedDataWithOp.OP_ADD) + self.bgp_message.put((self.config_db.serialize_key(key), False, table_name, upd_data)) + + @staticmethod + def __nbr_impl_action(data, peer, is_pg): + if is_pg: + chk_attrs = ['asn'] + elif BGPConfigDaemon.__peer_is_ip(peer): + chk_attrs = ['asn', 'peer_group_name'] + else: + chk_attrs = ['peer_group_name'] + for attr in chk_attrs: + val = data.get(attr, None) + if val is not None: + if val.op == CachedDataWithOp.OP_ADD: + return 'apply' + elif val.op == CachedDataWithOp.OP_DELETE: + return 'delete' + return None + + def __apply_config_op_success(self, data, cfg_data={}): + op_list = [ CachedDataWithOp.OP_NONE, CachedDataWithOp.OP_ADD, + CachedDataWithOp.OP_DELETE, CachedDataWithOp.OP_UPDATE ] + if len(cfg_data) == 0: + for dkey, dval in data.items(): + dval.status = CachedDataWithOp.STAT_SUCC + else : + for dkey, dval in data.items(): + if dkey in cfg_data.keys(): + if cfg_data[dkey] not in op_list : + syslog.syslog(syslog.LOG_INFO, 'Invalid op {} received'.format(cfg_data[dkey])) + continue + dval.status = CachedDataWithOp.STAT_SUCC + dval.op = cfg_data[dkey] + syslog.syslog(syslog.LOG_INFO, 'apply_config_op_success on {}.'.format(data)) + + def __apply_config_delete_success(self, data): + for dkey, dval in data.items(): + dval.status = CachedDataWithOp.STAT_SUCC + dval.op = CachedDataWithOp.OP_DELETE + + def __ospf_delete (self, data): + for dkey, dval in data.items(): + # force delete all peer attributes in cache + dval.status = CachedDataWithOp.STAT_SUCC + dval.op = CachedDataWithOp.OP_DELETE + + def __ospf_apply_config(self, data, rmapoper, metricoper, metrictypeoper, alwaysoper, acclistoper): + for dkey, dval in data.items(): + + if 'route-map' == dkey: + dval.status = CachedDataWithOp.STAT_SUCC + dval.op = rmapoper + + if 'metric' == dkey: + dval.status = CachedDataWithOp.STAT_SUCC + dval.op = metricoper + + if 'metric-type' == dkey: + dval.status = CachedDataWithOp.STAT_SUCC + dval.op = metrictypeoper + + if 'always' == dkey: + dval.status = CachedDataWithOp.STAT_SUCC + dval.op = alwaysoper + + if 'access-list' == dkey: + dval.status = CachedDataWithOp.STAT_SUCC + dval.op = acclistoper + + def __delete_bfd_peer(self, data): + for dkey, dval in data.items(): + # force delete all peer attributes in cache + dval.status = CachedDataWithOp.STAT_SUCC + dval.op = CachedDataWithOp.OP_DELETE + + def __bfd_handle_delete (self, data): + cmd_suffix = "" + if 'desired-minimum-tx-interval' in data: + dval = data['desired-minimum-tx-interval'] + cmd_suffix = "transmit-interval 300" + elif 'required-minimum-receive' in data: + dval = data['required-minimum-receive'] + cmd_suffix = "receive-interval 300" + elif 'detection-multiplier' in data: + dval = data['detection-multiplier'] + cmd_suffix = "detect-multiplier 3" + elif 'desired-minimum-echo-receive' in data: + dval = data['desired-minimum-echo-receive'] + cmd_suffix = "echo-interval 300" + if cmd_suffix != "": + return cmd_suffix, dval.op + + return cmd_suffix, None + + def __update_bgp(self, data_list): + while not self.bgp_message.empty(): + key, del_table, table, data = self.bgp_message.get() + if table == 'STATIC_ROUTE' and len(key.split('|')) == 1: + key = self.DEFAULT_VRF + '|' + key + key_list = key.split('|', 1) + if table == 'BGP_NEIGHBOR' and len(key_list) == 1: + # bypass non-compatible neighbor table + continue + data_list.append((table, key, data)) + if len(key_list) > 1: + key = key_list[1] + else: + key = None + prefix = key_list[0] + syslog.syslog(syslog.LOG_INFO, 'value for table {} prefix {} key {} changed to {}'.format(table, prefix, key, data)) + if self.__vrf_based_table(table): + vrf = prefix + local_asn = self.__get_vrf_asn(vrf) + if local_asn is None and (table != 'BGP_GLOBALS' or 'local_asn' not in data): + syslog.syslog(syslog.LOG_DEBUG, 'ignore table {} update because local_asn for VRF {} was not configured'.\ + format(table, vrf)) + continue + if table in self.tbl_to_key_map: + tbl_key = None + if table == 'BGP_NEIGHBOR_AF' or table == 'BGP_PEER_GROUP_AF' and key is not None: + _, af_ip_type = key.split('|') + tbl_key, _ = af_ip_type.lower().split('_') + tbl_key = {'admin_status': tbl_key} + elif table == 'ROUTE_MAP': + tbl_key = {} + for attr_name, table_name in {'match_prefix_set': 'PREFIX', 'match_next_hop_set': 'PREFIX'}.items(): + if attr_name in data: + pfx_set_name = self.get_prefix_set_name(data[attr_name].data, table_name) + if pfx_set_name in self.prefix_set_list: + af_mode = self.prefix_set_list[pfx_set_name].af + tbl_key[attr_name] = 'ipv4' if af_mode == socket.AF_INET else 'ipv6' + elif table == 'STATIC_ROUTE': + af_id, new_key = IpNextHopSet.get_af_norm_prefix(key) + if new_key is not None: + key = new_key + tbl_key = {'ip_prefix': ('ipv4' if af_id == socket.AF_INET else 'ipv6')} + key_map = BGPKeyMapList(self.tbl_to_key_map[table], table, tbl_key) + else: + key_map = None + if table == 'BGP_GLOBALS': + if not del_table: + if 'local_asn' in data: + dval = data['local_asn'] + if dval.op == CachedDataWithOp.OP_DELETE: + # delete local_asn will delete whole VRF instance + self.__delete_vrf_asn(vrf, table, data) + continue + prog_asn = True + if dval.op == CachedDataWithOp.OP_UPDATE: + syslog.syslog(syslog.LOG_ERR, 'local_asn could not be modified') + prog_asn = False + if dval.op == CachedDataWithOp.OP_NONE: + prog_asn = False + if prog_asn: + command = "vtysh -c 'configure terminal' -c 'router bgp {} vrf {}' -c 'no bgp default ipv4-unicast'".format(dval.data, vrf) + if self.__run_command(table, command): + syslog.syslog(syslog.LOG_DEBUG, 'set local_asn %s to VRF %s, re-apply all VRF related tables' % (dval.data, vrf)) + self.bgp_asn[vrf] = dval.data + self.__apply_dep_vrf_table(vrf, 'ROUTE_REDISTRIBUTE') + dval.status = CachedDataWithOp.STAT_SUCC + else: + syslog.syslog(syslog.LOG_ERR, 'failed to set local_asn %s to VRF %s' % (dval.data, vrf)) + else: + dval.status = CachedDataWithOp.STAT_SUCC + if 'confed_peers' in data: + self.upd_confed_peers = copy.copy(self.bgp_confed_peers.get(vrf, set())) + local_asn = self.__get_vrf_asn(vrf) + if local_asn is None: + syslog.syslog(syslog.LOG_ERR, 'local ASN for VRF %s was not configured' % vrf) + continue + cmd_prefix = ['configure terminal', 'router bgp {} vrf {}'.format(local_asn, vrf)] + if not key_map.run_command(self, table, data, cmd_prefix): + syslog.syslog(syslog.LOG_ERR, 'failed running BGP global config command') + continue + if 'confed_peers' in data: + self.bgp_confed_peers[vrf] = copy.copy(self.upd_confed_peers) + else: + self.__delete_vrf_asn(vrf, table, data) + elif table == 'BGP_GLOBALS_AF': + af, ip_type = key.lower().split('_') + #this is to temporarily make table cache key accessible to key_map handler function + self.tmp_cache_key = 'BGP_GLOBALS_AF&&{}|{}'.format(vrf, key.lower()) + syslog.syslog(syslog.LOG_INFO, 'Set address family global to {} {} cache-key to {}'.format(af, ip_type, self.tmp_cache_key)) + cmd_prefix = ['configure terminal', + 'router bgp {} vrf {}'.format(local_asn, vrf), + 'address-family {} {}'.format(af, ip_type)] + if not key_map.run_command(self, table, data, cmd_prefix): + syslog.syslog(syslog.LOG_ERR, 'failed running BGP global AF config command') + continue + self.tmp_cache_key = '' + elif table == 'BGP_GLOBALS_LISTEN_PREFIX': + syslog.syslog(syslog.LOG_INFO, 'Set BGP listen prefix {}'.format(key)) + cmd_prefix = ['configure terminal', + 'router bgp {} vrf {}'.format(local_asn, vrf)] + if not key_map.run_command(self, table, data, cmd_prefix, key): + syslog.syslog(syslog.LOG_ERR, 'failed running BGP global listen prefix config command') + continue + elif table == 'BGP_NEIGHBOR' or table == 'BGP_PEER_GROUP': + is_peer_group = table == 'BGP_PEER_GROUP' + if not del_table: + if is_peer_group: + # if peer group is not created, create it before setting other attributes + if key not in self.bgp_peer_group.setdefault(vrf, {}): + command = "vtysh -c 'configure terminal' -c 'router bgp {} vrf {}' ".format(local_asn, vrf) + command += "-c 'neighbor {} peer-group'".format(key) + if not self.__run_command(table, command): + syslog.syslog(syslog.LOG_ERR, 'failed to create peer-group %s for VRF %s' % (key, vrf)) + continue + self.bgp_peer_group[vrf][key] = BGPPeerGroup(vrf) + elif not self.__peer_is_ip(key): + if key not in self.bgp_intf_nbr.setdefault(vrf, set()): + command = "vtysh -c 'configure terminal' -c 'router bgp {} vrf {}' ".format(local_asn, vrf) + command += "-c 'neighbor {} interface'".format(key) + if not self.__run_command(table, command): + syslog.syslog(syslog.LOG_ERR, 'failed to create neighbor of interface %s for VRF %s' % (key, vrf)) + continue + self.bgp_intf_nbr[vrf].add(key) + bfd_val = data.get('bfd', None) + if (bfd_val is not None and (bfd_val.op == CachedDataWithOp.OP_ADD or bfd_val.op == CachedDataWithOp.OP_UPDATE) and + bfd_val.data == 'true'): + cp_chk_val = data.get('bfd_check_ctrl_plane_failure', None) + if cp_chk_val is not None and cp_chk_val.op == CachedDataWithOp.OP_NONE and cp_chk_val.data == 'true': + cp_chk_val.op = CachedDataWithOp.OP_ADD + cmd_prefix = ['configure terminal', 'router bgp {} vrf {}'.format(local_asn, vrf)] + if not key_map.run_command(self, table, data, cmd_prefix, key): + syslog.syslog(syslog.LOG_ERR, 'failed running BGP neighbor config command') + continue + if ('peer_group_name' in data and + (data['peer_group_name'].op == CachedDataWithOp.OP_ADD or + data['peer_group_name'].op == CachedDataWithOp.OP_DELETE)): + dval = data['peer_group_name'] + if vrf not in self.bgp_peer_group or dval.data not in self.bgp_peer_group[vrf]: + # should not happen because vtysh command will fail if peer_group not exists + syslog.syslog(syslog.LOG_ERR, 'invalid peer-group %s was referenced' % dval.data) + continue + peer_grp = self.bgp_peer_group[vrf][dval.data] + if dval.op == CachedDataWithOp.OP_ADD: + peer_grp.ref_nbrs.add(key) + else: + peer_grp.ref_nbrs.discard(key) + nbr_action = self.__nbr_impl_action(data, key, is_peer_group) + if nbr_action == 'delete': + if not is_peer_group and self.__peer_is_ip(key): + # delete asn or peer_group will delete all neighbor + self.__delete_vrf_neighbor(vrf, key, data, False) + elif is_peer_group: + # clear associated neighbor list in cache + self.__delete_pg_neighbors(vrf, key) + elif nbr_action == 'apply': + if is_peer_group: + syslog.syslog(syslog.LOG_DEBUG, 'apply attributes to FRR for vrf %s peer_group %s' % (vrf, key)) + match_pg = lambda data: data.get('peer_group', None) == key + self.__apply_dep_vrf_table(vrf, 'BGP_GLOBALS_LISTEN_PREFIX', match = match_pg) + match_nbr = lambda data: data.get('peer_group_name', None) == key + self.__apply_dep_vrf_table(vrf, 'BGP_NEIGHBOR', match = match_nbr) + else: + for af in ['ipv4_unicast', 'ipv6_unicast']: + syslog.syslog(syslog.LOG_DEBUG, 'apply attributes to FRR for vrf %s neighbor %s af %s' % (vrf, key, af)) + self.__apply_dep_vrf_table(vrf, 'BGP_NEIGHBOR_AF', key, af) + else: + # Neighbor is deleted + if is_peer_group: + # clear associated neighbor list in cache + self.__delete_pg_neighbors(vrf, key) + command = "vtysh -c 'configure terminal' -c 'router bgp {} vrf {}' -c 'no neighbor {}'".\ + format(local_asn, vrf, key) + if not self.__run_command(table, command): + syslog.syslog(syslog.LOG_ERR, 'failed to delete VRF %s bgp neigbor %s' % (vrf, key)) + self.__delete_vrf_neighbor(vrf, key, data, is_peer_group) + elif table == 'BGP_NEIGHBOR_AF' or table == 'BGP_PEER_GROUP_AF': + nbr, af_type = key.split('|') + af, ip_type = af_type.lower().split('_') + syslog.syslog(syslog.LOG_INFO, 'Set address family for neighbor {} to {} {}'.format(nbr, af, ip_type)) + cmd_prefix = ['configure terminal', + 'router bgp {} vrf {}'.format(local_asn, vrf), + 'address-family {} {}'.format(af, ip_type)] + if not key_map.run_command(self, table, data, cmd_prefix, nbr): + syslog.syslog(syslog.LOG_ERR, 'failed running BGP neighbor AF config command') + continue + elif table == 'COMMUNITY_SET' or table == 'EXTENDED_COMMUNITY_SET': + comm_set_name = prefix + syslog.syslog(syslog.LOG_INFO, 'Set community set {} for table {}'.format(comm_set_name, table)) + cmd_prefix = ['configure terminal'] + if not key_map.run_command(self, table, data, cmd_prefix, comm_set_name): + syslog.syslog(syslog.LOG_ERR, 'failed running BGP community config command') + continue + extended = (table != 'COMMUNITY_SET') + comm_set = (self.comm_set_list if not extended else self.extcomm_set_list).setdefault(comm_set_name, + CommunityList(comm_set_name, extended)) + if del_table: + del((self.comm_set_list if not extended else self.extcomm_set_list)[comm_set_name]) + else: + for dkey, dval in data.items(): + if dval.op == CachedDataWithOp.OP_DELETE: + upd_val = None + else: + upd_val = dval.data + comm_set.db_data_to_attr(dkey, upd_val) + elif table == 'PREFIX_SET': + pfx_set_name = prefix + if not del_table: + if pfx_set_name in self.prefix_set_list: + syslog.syslog(syslog.LOG_DEBUG, 'prefix-set %s exists with af %d' % + (pfx_set_name, self.prefix_set_list[pfx_set_name].af)) + continue + if 'mode' not in data: + syslog.syslog(syslog.LOG_ERR, 'no mode given for prefix-set %s' % pfx_set_name) + continue + set_mode = data['mode'].data.lower() + self.prefix_set_list[pfx_set_name] = MatchPrefixList(set_mode) + else: + if pfx_set_name in self.prefix_set_list: + del(self.prefix_set_list[pfx_set_name]) + for _, dval in data.items(): + dval.status = CachedDataWithOp.STAT_SUCC + elif table == 'PREFIX' or table == 'NEIGHBOR_SET' or table == 'NEXTHOP_SET': + pfx_set_name = self.get_prefix_set_name(prefix, table) + if table == 'PREFIX': + if pfx_set_name not in self.prefix_set_list: + syslog.syslog(syslog.LOG_ERR, 'could not find prefix-set %s from cache' % pfx_set_name) + continue + ip_pfx, len_range = key.split('|') + if len_range == 'exact': + len_range = None + pfx_action = data.get('action', None) + if pfx_action is None or pfx_action.op == CachedDataWithOp.OP_NONE: + continue + af = self.prefix_set_list[pfx_set_name].af + if af == socket.AF_INET: + # use table daemons setting + daemons = None + else: + daemons = ['bgpd', 'zebra'] + if pfx_action.op == CachedDataWithOp.OP_DELETE or pfx_action.op == CachedDataWithOp.OP_UPDATE: + del_pfx, pfx_idx = self.prefix_set_list[pfx_set_name].get_prefix(ip_pfx, len_range) + if del_pfx is None: + syslog.syslog(syslog.LOG_ERR, 'prefix of {} with range {} not found from prefix-set {}'.\ + format(ip_pfx, len_range, pfx_set_name)) + continue + command = "vtysh -c 'configure terminal' -c 'no {} prefix-list {} {}'".\ + format(('ip' if af == socket.AF_INET else 'ipv6'), pfx_set_name, str(del_pfx)) + if not self.__run_command(table, command, daemons): + syslog.syslog(syslog.LOG_ERR, 'failed to delete prefix %s with range %s from set %s' % + (ip_pfx, len_range, pfx_set_name)) + continue + del(self.prefix_set_list[pfx_set_name][pfx_idx]) + if pfx_action.op == CachedDataWithOp.OP_ADD or pfx_action.op == CachedDataWithOp.OP_UPDATE: + try: + add_pfx = self.prefix_set_list[pfx_set_name].add_prefix(ip_pfx, len_range, pfx_action.data) + except ValueError: + syslog.syslog(syslog.LOG_ERR, 'failed to update prefix-set %s in cache with prefix %s range %s' % + (pfx_set_name, ip_pfx, len_range)) + continue + command = "vtysh -c 'configure terminal' -c '{} prefix-list {} {}'".\ + format(('ip' if af == socket.AF_INET else 'ipv6'), pfx_set_name, str(add_pfx)) + if not self.__run_command(table, command, daemons): + syslog.syslog(syslog.LOG_ERR, 'failed to add prefix %s with range %s to set %s' % + (ip_pfx, len_range, pfx_set_name)) + # revert cached update on failure + del_pfx, pfx_idx = self.prefix_set_list[pfx_set_name].get_prefix(ip_pfx, len_range) + if del_pfx is not None: + del(self.prefix_set_list[pfx_set_name][pfx_idx]) + continue + else: + if 'address' not in data or data['address'].op == CachedDataWithOp.OP_NONE: + continue + ip_addr_list = data['address'].data + if pfx_set_name in self.prefix_set_list: + af = self.prefix_set_list[pfx_set_name].af + command = "vtysh -c 'configure terminal' -c 'no {} prefix-list {}'".\ + format(('ip' if af == socket.AF_INET else 'ipv6'), pfx_set_name) + if not self.__run_command(table, command): + syslog.syslog(syslog.LOG_ERR, 'failed to delete existing prefix-set {}'.format(pfx_set_name)) + continue + del(self.prefix_set_list[pfx_set_name]) + if not del_table: + prefix_set = MatchPrefixList() + for ip_addr in ip_addr_list: + try: + prefix_set.add_prefix(ip_addr) + except ValueError: + continue + for prefix in prefix_set: + command = "vtysh -c 'configure terminal' -c '{} prefix-list {} {}'".\ + format(('ip' if prefix_set.af == socket.AF_INET else 'ipv6'), pfx_set_name, str(prefix)) + if not self.__run_command(table, command): + syslog.syslog(syslog.LOG_ERR, 'failed to delete existing prefix-set {}'.format(pfx_set_name)) + continue + self.prefix_set_list[pfx_set_name] = prefix_set + for _, dval in data.items(): + dval.status = CachedDataWithOp.STAT_SUCC + elif table == 'AS_PATH_SET': + as_set_name = prefix + syslog.syslog(syslog.LOG_INFO, 'Set AS path set {} for table {}'.format(as_set_name, table)) + cmd_prefix = ['configure terminal'] + if not key_map.run_command(self, table, data, cmd_prefix, as_set_name): + syslog.syslog(syslog.LOG_ERR, 'failed running BGP AS path set config command') + continue + as_set_data = data.get('as_path_set_member', None) + if as_set_data is not None and (as_set_data.op == CachedDataWithOp.OP_DELETE or len(as_set_data.data) == 0): + del_table = True + if del_table: + self.as_path_set_list.pop(as_set_name, None) + elif as_set_data is not None: + self.as_path_set_list[as_set_name] = as_set_data.data[:] + elif table == 'TAG_SET': + tag_set_name = prefix + if not del_table and 'tag_value' not in data: + continue + tag_set_data = data.get('tag_value', None) + if tag_set_data is not None and (tag_set_data.op == CachedDataWithOp.OP_DELETE or len(tag_set_data.data) == 0): + del_table = True + if not del_table: + self.tag_set_list[tag_set_name] = set(tag_set_data.data) + else: + self.tag_set_list.pop(tag_set_name, None) + for _, dval in data.items(): + dval.status = CachedDataWithOp.STAT_SUCC + elif table == 'BGP_GLOBALS_EVPN_VNI': + af_type, vni = key.split('|') + af, ip_type = af_type.lower().split('_') + #this is to temporarily make table cache key accessible to key_map handler function + self.tmp_cache_key = 'BGP_GLOBALS_EVPN_VNI&&{}|{}|{}'.format(vrf, af_type, vni) + syslog.syslog(syslog.LOG_INFO, 'Set address family for VNI {} to {} {} cache-key to {}'.format(vni, af, ip_type, self.tmp_cache_key)) + cmd_prefix = ['configure terminal', + 'router bgp {} vrf {}'.format(local_asn, vrf), + 'address-family {} {}'.format(af, ip_type), + 'vni {}'.format(vni)] + if not key_map.run_command(self, table, data, cmd_prefix): + syslog.syslog(syslog.LOG_ERR, 'failed running BGP L2VPN_EVPN VNI config command') + continue + self.tmp_cache_key = '' + if del_table: + cmd = "vtysh -c 'configure terminal'" + cmd += " -c 'router bgp {} vrf {}'".format(local_asn, vrf) + cmd += " -c 'address-family {} {}'".format(af, ip_type) + cmd += " -c 'no vni {}'".format(vni) + if not self.__run_command(table, cmd): + syslog.syslog(syslog.LOG_ERR, 'failed running BGP L2VPN_EVPN VNI unconfig command') + continue + else: + if not data: + cmd = "vtysh -c 'configure terminal'" + cmd += " -c 'router bgp {} vrf {}'".format(local_asn, vrf) + cmd += " -c 'address-family {} {}'".format(af, ip_type) + cmd += " -c 'vni {}'".format(vni) + if not self.__run_command(table, cmd): + syslog.syslog(syslog.LOG_ERR, 'failed running BGP L2VPN_EVPN VNI config command') + continue + elif table == 'BGP_GLOBALS_EVPN_RT': + af_type, rt = key.split('|') + af, ip_type = af_type.lower().split('_') + nostr = "no " if del_table else "" + syslog.syslog(syslog.LOG_INFO, 'Set address family for RT {} to {} {}'.format(rt, af, ip_type)) + cmd = "vtysh -c 'configure terminal'" + cmd += " -c 'router bgp {} vrf {}'".format(local_asn, vrf) + cmd += " -c 'address-family {} {}'".format(af, ip_type) + cmd += " -c '{}route-target {} {}'".format(nostr,data['route-target-type'].data, rt) + cache_tbl_key = 'BGP_GLOBALS_EVPN_RT&&{}|L2VPN_EVPN|{}'.format(vrf, rt) + if not del_table and cache_tbl_key in self.table_data_cache.keys(): + new_rttype = data['route-target-type'].data + cache_tbl_data = self.table_data_cache[cache_tbl_key] + if 'route-target-type' in cache_tbl_data: + old_rttype = cache_tbl_data['route-target-type'] + if new_rttype == "export": + if old_rttype == "import" or old_rttype == "both": + cmd += " -c 'no route-target import {}'".format(rt) + if new_rttype == "import": + if old_rttype == "export" or old_rttype == "both": + cmd += " -c 'no route-target export {}'".format(rt) + if not self.__run_command(table, cmd): + syslog.syslog(syslog.LOG_ERR, 'failed running BGP L2VPN_EVPN RT config command') + continue + else: + data['route-target-type'].status = CachedDataWithOp.STAT_SUCC + elif table == 'BGP_GLOBALS_EVPN_VNI_RT': + af_type, vni, rt = key.split('|') + af, ip_type = af_type.lower().split('_') + nostr = "no " if del_table else "" + syslog.syslog(syslog.LOG_INFO, 'Set address family for VNI {} RT {} to {} {}'.format(vni, rt, af, ip_type)) + cmd = "vtysh -c 'configure terminal'" + cmd += " -c 'router bgp {} vrf {}'".format(local_asn, vrf) + cmd += " -c 'address-family {} {}'".format(af, ip_type) + cmd += " -c 'vni {}'".format(vni) + cmd += " -c '{}route-target {} {}'".format(nostr,data['route-target-type'].data, rt) + cache_tbl_key = 'BGP_GLOBALS_EVPN_VNI_RT&&{}|L2VPN_EVPN|{}|{}'.format(vrf, vni, rt) + if not del_table and cache_tbl_key in self.table_data_cache.keys(): + new_rttype = data['route-target-type'].data + cache_tbl_data = self.table_data_cache[cache_tbl_key] + if 'route-target-type' in cache_tbl_data: + old_rttype = cache_tbl_data['route-target-type'] + if new_rttype == "export": + if old_rttype == "import" or old_rttype == "both": + cmd += " -c 'no route-target import {}'".format(rt) + if new_rttype == "import": + if old_rttype == "export" or old_rttype == "both": + cmd += " -c 'no route-target export {}'".format(rt) + if not self.__run_command(table, cmd): + syslog.syslog(syslog.LOG_ERR, 'failed running BGP L2VPN_EVPN VNI RT config command') + continue + else: + data['route-target-type'].status = CachedDataWithOp.STAT_SUCC + elif table == 'ROUTE_MAP': + map_name = prefix + seq_no = key + if not del_table: + if 'route_operation' in data: + dval = data['route_operation'] + if dval.op != CachedDataWithOp.OP_NONE: + enable = (dval.op != CachedDataWithOp.OP_DELETE) + no_arg = CommandArgument(self, enable) + command = "vtysh -c 'configure terminal' -c '{:no-prefix}route-map {} {} {}'".\ + format(no_arg, map_name, dval.data, seq_no) + if not self.__run_command(table, command): + syslog.syslog(syslog.LOG_ERR, 'failed to configure route-map {} seq {}'.format(map_name, seq_no)) + continue + if dval.op == CachedDataWithOp.OP_DELETE: + self.__delete_route_map(map_name, seq_no, data) + continue + self.route_map.setdefault(map_name, {})[seq_no] = dval.data + for k, v in data.items(): + if v.op == CachedDataWithOp.OP_NONE: + v.op = CachedDataWithOp.OP_UPDATE + dval.status = CachedDataWithOp.STAT_SUCC + if map_name not in self.route_map or seq_no not in self.route_map[map_name]: + syslog.syslog(syslog.LOG_ERR, 'route-map {} seq {} not found for update'.format(map_name, seq_no)) + continue + cmd_prefix = ['configure terminal', + 'route-map {} {} {}'.format(map_name, self.route_map[map_name][seq_no], seq_no)] + if not key_map.run_command(self, table, data, cmd_prefix): + syslog.syslog(syslog.LOG_ERR, 'failed running route-map config command') + continue + else: + if map_name not in self.route_map or seq_no not in self.route_map[map_name]: + syslog.syslog(syslog.LOG_ERR, 'route-map {} seq {} not found for delete'.format(map_name, seq_no)) + continue + command = "vtysh -c 'configure terminal' -c 'no route-map {} {} {}'".\ + format(map_name, self.route_map[map_name][seq_no], seq_no) + if not self.__run_command(table, command): + syslog.syslog(syslog.LOG_ERR, 'failed running route-map delete command') + continue + self.__delete_route_map(map_name, seq_no, data) + elif table == 'ROUTE_REDISTRIBUTE': + src_proto, dst_proto, af = key.split('|') + if af == 'ipv6' and src_proto == 'ospf3': + src_proto = 'ospf6' + ip_type = 'unicast' + syslog.syslog(syslog.LOG_INFO, 'Set route distribute for src_proto {} dst_proto {} {}'.\ + format(src_proto, dst_proto, af, ip_type)) + if dst_proto != 'bgp': + syslog.syslog(syslog.LOG_ERR, 'only bgp could be used as dst protocol, but {} was given'.format(dst_proto)) + continue + op = CachedDataWithOp.OP_DELETE if del_table else CachedDataWithOp.OP_UPDATE + data['protocol'] = CachedDataWithOp(src_proto, op) + cmd_prefix = ['configure terminal', + 'router bgp {} vrf {}'.format(local_asn, vrf), + 'address-family {} {}'.format(af, ip_type)] + ret_val = key_map.run_command(self, table, data, cmd_prefix) + del(data['protocol']) + if not ret_val: + syslog.syslog(syslog.LOG_ERR, 'failed running BGP route redistribute config command') + continue + elif table == 'BGP_GLOBALS_AF_AGGREGATE_ADDR' or table == 'BGP_GLOBALS_AF_NETWORK': + af_type, ip_prefix = key.split('|') + af, ip_type = af_type.lower().split('_') + norm_ip_prefix = MatchPrefix.normalize_ip_prefix((socket.AF_INET if af == 'ipv4' else socket.AF_INET6), ip_prefix) + if norm_ip_prefix is None: + syslog.syslog(syslog.LOG_ERR, 'invalid IP prefix format %s for af %s' % (ip_prefix, af)) + continue + syslog.syslog(syslog.LOG_INFO, 'Set address family for IP prefix {} to {} {}'.format(norm_ip_prefix, af, ip_type)) + op = CachedDataWithOp.OP_DELETE if del_table else CachedDataWithOp.OP_UPDATE + data['ip_prefix'] = CachedDataWithOp(norm_ip_prefix, op) + cmd_prefix = ['configure terminal', + 'router bgp {} vrf {}'.format(local_asn, vrf), + 'address-family {} {}'.format(af, ip_type)] + ret_val = key_map.run_command(self, table, data, cmd_prefix, vrf, af) + del(data['ip_prefix']) + if not ret_val: + syslog.syslog(syslog.LOG_ERR, 'failed running BGP IP prefix AF config command') + continue + if table == 'BGP_GLOBALS_AF_AGGREGATE_ADDR': + if not del_table: + aggr_obj = AggregateAddr() + for attr in ['as_set', 'summary_only']: + if attr in data and data[attr].op != CachedDataWithOp.OP_DELETE and data[attr].data == 'true': + setattr(aggr_obj, attr, True) + self.af_aggr_list.setdefault(vrf, {})[norm_ip_prefix] = aggr_obj + else: + if vrf in self.af_aggr_list: + self.af_aggr_list[vrf].pop(norm_ip_prefix, None) + + elif table == 'BFD_PEER_SINGLE_HOP': + key = prefix + '|' + key + remoteaddr, interface, vrf, localaddr = key.split('|') + if not del_table: + if not 'null' in localaddr: + syslog.syslog(syslog.LOG_INFO, 'Set BFD single hop peer {} {} {} {}'.format(remoteaddr, vrf, interface, localaddr)) + + suffix_cmd, oper = self.__bfd_handle_delete (data) + if suffix_cmd and oper == CachedDataWithOp.OP_DELETE: + command = "vtysh -c 'configure terminal' -c 'bfd' -c 'peer {} local-address {} vrf {} interface {}' -c '{}'".\ + format(remoteaddr, localaddr, vrf, interface, suffix_cmd) + + if not self.__run_command(table, command): + syslog.syslog(syslog.LOG_ERR, 'failed to delete single-hop peer {}'.format(key)) + continue + else: + cmd_prefix = ['configure terminal', + 'bfd', + 'peer {} local-address {} vrf {} interface {}'.format(remoteaddr, localaddr, vrf, interface)] + if not key_map.run_command(self, table, data, cmd_prefix): + syslog.syslog(syslog.LOG_ERR, 'failed running BFD single-hop config command') + continue + + else: + syslog.syslog(syslog.LOG_INFO, 'Set BFD single hop peer {} {} {}'.format(remoteaddr, vrf, interface)) + + suffix_cmd, oper = self.__bfd_handle_delete (data) + + if suffix_cmd and oper == CachedDataWithOp.OP_DELETE: + command = "vtysh -c 'configure terminal' -c 'bfd' -c 'peer {} vrf {} interface {}' -c '{}'".\ + format(remoteaddr, vrf, interface, suffix_cmd) + + if not self.__run_command(table, command): + syslog.syslog(syslog.LOG_ERR, 'failed to delete single-hop peer {}'.format(key)) + continue + else: + syslog.syslog(syslog.LOG_INFO, 'Set BFD single hop peer {} {} {}'.format(remoteaddr, vrf, interface)) + cmd_prefix = ['configure terminal', + 'bfd', + 'peer {} vrf {} interface {}'.format(remoteaddr, vrf, interface)] + if not key_map.run_command(self, table, data, cmd_prefix): + syslog.syslog(syslog.LOG_ERR, 'failed running BFD single-hop config command') + continue + else: + if 'local-address' in data: + dval = data['local-address'] + localaddr = dval.data + syslog.syslog(syslog.LOG_INFO, 'Delete BFD single hop to {} {} {}'.format(remoteaddr, vrf, interface, localaddr)) + command = "vtysh -c 'configure terminal' -c 'bfd' -c 'no peer {} local-address {} vrf {} interface {}'".\ + format(remoteaddr, localaddr, vrf, interface) + else: + syslog.syslog(syslog.LOG_INFO, 'Delete BFD single hop to {} {} {}'.format(remoteaddr, vrf, interface)) + command = "vtysh -c 'configure terminal' -c 'bfd' -c 'no peer {} vrf {} interface {}'".\ + format(remoteaddr, vrf, interface) + if not self.__run_command(table, command): + syslog.syslog(syslog.LOG_ERR, 'failed to delete single-hop peer {}'.format(key)) + continue + self.__delete_bfd_peer(data) + elif table == 'BFD_PEER_MULTI_HOP': + key = prefix + '|' + key + remoteaddr, interface, vrf, localaddr = key.split('|') + if not del_table: + syslog.syslog(syslog.LOG_INFO, 'Set BFD multi hop to {} {} {} {}'.format(remoteaddr, interface, vrf, localaddr)) + suffix_cmd, oper = self.__bfd_handle_delete (data) + if suffix_cmd and oper == CachedDataWithOp.OP_DELETE: + if not 'null' in interface: + command = "vtysh -c 'configure terminal' -c 'bfd' -c 'peer {} local-address {} vrf {} interface {}' -c '{}'".\ + format(remoteaddr, localaddr, vrf, interface, suffix_cmd) + else: + command = "vtysh -c 'configure terminal' -c 'bfd' -c 'peer {} local-address {} vrf {}' -c '{}'".\ + format(remoteaddr, localaddr, vrf, suffix_cmd) + + if not self.__run_command(table, command): + syslog.syslog(syslog.LOG_ERR, 'failed to delete single-hop peer {}'.format(key)) + continue + else: + if not 'null' in interface: + cmd_prefix = ['configure terminal', + 'bfd', + 'peer {} vrf {} multihop local-address {} interface {}'.format(remoteaddr, vrf, localaddr, interface)] + else: + cmd_prefix = ['configure terminal', + 'bfd', + 'peer {} vrf {} multihop local-address {}'.format(remoteaddr, vrf, localaddr)] + + if not key_map.run_command(self, table, data, cmd_prefix): + syslog.syslog(syslog.LOG_ERR, 'failed running BFD multi-hop config command') + continue + else: + syslog.syslog(syslog.LOG_INFO, 'Delete BFD multi hop to {} {} {} {}'.format(remoteaddr, vrf, localaddr, interface)) + if not 'null' in interface: + command = "vtysh -c 'configure terminal' -c 'bfd' -c 'no peer {} vrf {} multihop local-address {} interface {}'".\ + format(remoteaddr, vrf, localaddr, interface) + else: + command = "vtysh -c 'configure terminal' -c 'bfd' -c 'no peer {} vrf {} multihop local-address {}'".\ + format(remoteaddr, vrf, localaddr) + + if not self.__run_command(table, command): + syslog.syslog(syslog.LOG_ERR, 'failed to delete multihop peer {}'.format(key)) + continue + self.__delete_bfd_peer(data) + elif table == 'IP_SLA': + sla_id = prefix + icmp_config = False + tcp_config = False + cmd_prefix = ['configure terminal'] + ipsla_table = self.config_db.get_table('IP_SLA') + syslog.syslog(syslog.LOG_INFO, 'Config ip sla data {}'.format(data)) + found_in_configdb = False + for key, entry in ipsla_table.items(): + ipsla_id = key + if sla_id == ipsla_id: + found_in_configdb = True + break + syslog.syslog(syslog.LOG_INFO, 'Config ip sla found_in_configdb {}'.format(found_in_configdb)) + if 'icmp_source_interface' in data or 'icmp_source_ip' in data or 'icmp_size' in data or 'icmp_dst_ip' in data or 'icmp_vrf' in data or 'icmp_ttl' in data or 'icmp_tos' in data: + cmd_prefix = ['configure terminal','ip sla {}'.format(sla_id)] + icmp_config = True + for key, entry in ipsla_table.items(): + ipsla_id = key + if sla_id == ipsla_id: + if 'icmp_dst_ip' in entry: + icmp_cmd = ("icmp", "echo") + icmp_cmd_str = "-".join(icmp_cmd) + icmp_cmd_mode = icmp_cmd_str + " " + entry['icmp_dst_ip'] + syslog.syslog(syslog.LOG_INFO, 'Data: icmp_cmd_str %s icmp_cmd_mode %s' % (icmp_cmd_str, icmp_cmd_mode)) + + cmd_prefix = ['configure terminal','ip sla {}'.format(sla_id), icmp_cmd_mode] + chk_icmp_attrs = ['icmp_source_interface', 'icmp_source_ip', 'icmp_size', 'icmp_vrf', 'icmp_tos', 'icmp_ttl'] + chk_icmp_attrs_dict = {'icmp_source_interface':'source-interface ', 'icmp_source_ip':'source-address ', 'icmp_size':'request-data-size ', 'icmp_vrf':'source-vrf ', 'icmp_tos':'tos ', 'icmp_ttl':'ttl '} + for attr in chk_icmp_attrs: + if attr in data and data[attr].op != CachedDataWithOp.OP_DELETE: + command = "vtysh -c 'configure terminal' -c 'ip sla {}' -c '{}' -c '{} {}'".\ + format(sla_id, icmp_cmd_mode, chk_icmp_attrs_dict[attr], data[attr].data) + syslog.syslog(syslog.LOG_INFO, 'Execute Icmp Cmd {}'.format(command)) + if not self.__run_command(table, command): + syslog.syslog(syslog.LOG_ERR, 'failed to add icmp config for ip sla {}'.format(sla_id)) + continue + + syslog.syslog(syslog.LOG_INFO, 'Done with Icmp {}'.format(sla_id)) + if not key_map.run_command(self, table, data, cmd_prefix, sla_id): + syslog.syslog(syslog.LOG_ERR, 'failed running ip sla command') + continue + if 'tcp_source_interface' in data or 'tcp_source_port' in data or 'tcp_source_ip' in data or 'tcp_dst_ip' in data or 'tcp_dst_port' in data or 'tcp_vrf' in data or 'tcp_ttl' in data or 'tcp_tos' in data: + cmd_prefix = ['configure terminal','ip sla {}'.format(sla_id)] + tcp_config = True + for key, entry in ipsla_table.items(): + ipsla_id = key + if sla_id == ipsla_id: + if 'tcp_dst_ip' in entry and 'tcp_dst_port' in entry: + tcp_cmd = ("tcp", "connect") + tcp_cmd_str = "-".join(tcp_cmd) + tcp_cmd_mode = tcp_cmd_str + " " + entry['tcp_dst_ip'] + " port " + entry['tcp_dst_port'] + syslog.syslog(syslog.LOG_INFO, 'Init Config DB Data: tcp_cmd_str %s tcp_cmd_mode %s' % (tcp_cmd_str, tcp_cmd_mode)) + cmd_prefix = ['configure terminal','ip sla {}'.format(sla_id), tcp_cmd_mode] + chk_tcp_attrs = ['tcp_source_interface', 'tcp_source_ip', 'tcp_source_port', 'tcp_vrf', 'tcp_tos', 'tcp_ttl'] + chk_tcp_attrs_dict = {'tcp_source_interface':'source-interface ', 'tcp_source_ip':'source-address ', 'tcp_source_port':'source-port ', 'tcp_vrf':'source-vrf ', 'tcp_tos':'tos ', 'tcp_ttl':'ttl '} + for attr in chk_tcp_attrs: + if attr in data and data[attr].op != CachedDataWithOp.OP_DELETE: + command = "vtysh -c 'configure terminal' -c 'ip sla {}' -c '{}' -c '{} {}'".\ + format(sla_id, tcp_cmd_mode, chk_tcp_attrs_dict[attr], data[attr].data) + syslog.syslog(syslog.LOG_INFO, 'Execute Tcp Cmd {}'.format(command)) + if not self.__run_command(table, command): + syslog.syslog(syslog.LOG_ERR, 'failed to add Tcp config for ip sla {}'.format(sla_id)) + continue + + syslog.syslog(syslog.LOG_INFO, 'Done with Tcp {}'.format(sla_id)) + if not key_map.run_command(self, table, data, cmd_prefix, sla_id): + syslog.syslog(syslog.LOG_ERR, 'failed running ip sla command') + continue + if 'frequency' in data or 'threshold' in data or 'timeout' in data: + syslog.syslog(syslog.LOG_INFO, 'ip sla mode Configure freq/thresh/timeout for sla {}'.format(sla_id)) + cmd_prefix = ['configure terminal','ip sla {}'.format(sla_id)] + if not key_map.run_command(self, table, data, cmd_prefix, sla_id): + syslog.syslog(syslog.LOG_ERR, 'failed running ip sla command') + continue + + elif icmp_config == False or tcp_config == False: + syslog.syslog(syslog.LOG_INFO, 'Basic mode Configure for ip sla {}'.format(sla_id)) + cmd_prefix = ['configure terminal'] + + # Always delete ip sla if it is not found in configdb + if not found_in_configdb: + command = "vtysh -c 'configure terminal' -c 'no ip sla {}'".format(sla_id) + syslog.syslog(syslog.LOG_ERR, 'Entry deleted in ip sla config db') + if not self.__run_command(table, command): + syslog.syslog(syslog.LOG_ERR, 'failed to delete router ip sla {}'.format(sla_id)) + continue + elif not key_map.run_command(self, table, data, cmd_prefix, sla_id): + syslog.syslog(syslog.LOG_ERR, 'failed running ip sla command') + continue + + elif table == 'OSPFV2_ROUTER': + vrf = prefix + if not del_table: + syslog.syslog(syslog.LOG_INFO, 'Create router ospf vrf {}'.format(vrf)) + + cmd_prefix = ['configure terminal', + 'router ospf vrf {}'.format(vrf)] + + if not key_map.run_command(self, table, data, cmd_prefix): + syslog.syslog(syslog.LOG_ERR, 'failed running ospf config command') + continue + else: + command = "vtysh -c 'configure terminal' -c 'no router ospf vrf {}'".format(vrf) + + if not self.__run_command(table, command): + syslog.syslog(syslog.LOG_ERR, 'failed to delete router ospf vrf {}'.format(vrf)) + continue + else: + self.__ospf_delete(data) + + elif table == 'OSPFV2_ROUTER_AREA': + vrf = prefix + syslog.syslog(syslog.LOG_INFO, 'Create router ospf vrf {}'.format(vrf)) + + cmd_prefix = ['configure terminal', + 'router ospf vrf {}'.format(vrf)] + + if not key_map.run_command(self, table, data, cmd_prefix, key): + syslog.syslog(syslog.LOG_ERR, 'failed running ospf config command') + continue + elif table == 'OSPFV2_ROUTER_AREA_VIRTUAL_LINK': + vrf = prefix + + keyvals = key.split('|') + area = keyvals[0] + vlinkid = keyvals[1] + + syslog.syslog(syslog.LOG_INFO, 'Create router ospf vrf {}, Vlink: {}, tableop {}'.format(vrf, data, del_table)) + + if data == {}: + command = "vtysh -c 'configure terminal' -c 'router ospf vrf {}' -c 'no area {} virtual-link {}'".\ + format(vrf, area, vlinkid) + + if not self.__run_command(table, command): + syslog.syslog(syslog.LOG_ERR, 'failed to delete vlink {} {}'.format(area, vlinkid)) + continue + else: + self.__ospf_delete(data) + else: + cmd_prefix = ['configure terminal', + 'router ospf vrf {}'.format(vrf)] + + if not key_map.run_command(self, table, data, cmd_prefix, area, vlinkid): + syslog.syslog(syslog.LOG_ERR, 'failed running ospf config command') + continue + + if del_table: + command = "vtysh -c 'configure terminal' -c 'router ospf vrf {}' -c 'no area {} virtual-link {}'".\ + format(vrf, area, vlinkid) + + if not self.__run_command(table, command): + syslog.syslog(syslog.LOG_ERR, 'failed to delete vlink {} {}'.format(area, vlinkid)) + continue + else: + self.__ospf_delete(data) + + elif table == 'OSPFV2_ROUTER_AREA_NETWORK': + vrf = prefix + syslog.syslog(syslog.LOG_INFO, 'Create router ospf vrf {}'.format(vrf)) + + keyvals = key.split('|') + area = keyvals[0] + network = keyvals[1] + + if not del_table: + command = "vtysh -c 'configure terminal' -c 'router ospf vrf {}' -c 'network {} area {}'".\ + format(vrf, network, area) + + if not self.__run_command(table, command): + syslog.syslog(syslog.LOG_ERR, 'failed to create network {} {}'.format(area, network)) + continue + else: + command = "vtysh -c 'configure terminal' -c 'router ospf vrf {}' -c 'no network {} area {}'".\ + format(vrf, network, area) + + if not self.__run_command(table, command): + syslog.syslog(syslog.LOG_ERR, 'failed to delete network {} {}'.format(area, network)) + continue + else: + self.__ospf_delete(data) + + elif table == 'OSPFV2_ROUTER_AREA_POLICY_ADDRESS_RANGE': + vrf = prefix + + keyvals = key.split('|') + area = keyvals[0] + range = keyvals[1] + + syslog.syslog(syslog.LOG_INFO, 'Create router ospf vrf {}'.format(vrf)) + + if data == {}: + if not del_table: + command = "vtysh -c 'configure terminal' -c 'router ospf vrf {}' -c 'area {} range {}'".\ + format(vrf, area, range) + + if not self.__run_command(table, command): + syslog.syslog(syslog.LOG_ERR, 'failed to create range {} {}'.format(area, range)) + continue + else: + command = "vtysh -c 'configure terminal' -c 'router ospf vrf {}' -c 'no area {} range {}'".\ + format(vrf, area, range) + + if not self.__run_command(table, command): + syslog.syslog(syslog.LOG_ERR, 'failed to delete range {} {}'.format(area, range)) + continue + else: + self.__ospf_delete(data) + else: + cmd_prefix = ['configure terminal', + 'router ospf vrf {}'.format(vrf)] + + if not key_map.run_command(self, table, data, cmd_prefix, area, range): + syslog.syslog(syslog.LOG_ERR, 'failed running ospf config command') + continue + + elif table == 'OSPFV2_ROUTER_DISTRIBUTE_ROUTE': + vrf = prefix + + keyvals = key.split('|') + protocol = keyvals[0] + direction = keyvals[1] + + if (protocol == "DIRECTLY_CONNECTED"): + protocol = "CONNECTED" + + syslog.syslog(syslog.LOG_INFO, 'Create redistribute-list {} {}'.format(protocol, direction)) + + cmd_suffix = "" + del_cmd_suffix = "" + cmd_oper = "" + rmapcmd = "" + metriccmd = "" + metrictypecmd = "" + alwayscmd = "" + acclistname = "" + rmapoper = "" + metricoper = "" + metrictypeoper = "" + alwaysoper = "" + acclistoper = "" + + if 'route-map' in data: + dval = data['route-map'] + rmapoper = dval.op + rmapcmd = " route-map {}".format(dval.data) + + if 'access-list' in data: + dval = data['access-list'] + acclistoper = dval.op + acclistname = dval.data + + if 'metric' in data: + dval = data['metric'] + metricoper = dval.op + metriccmd = " metric {}".format(dval.data) + + if 'metric-type' in data: + dval = data['metric-type'] + metrictypeoper = dval.op + + if dval.data == "TYPE_1": + metrictypecmd = " metric-type 1" + else: + metrictypecmd = " metric-type 2" + + if 'always' in data: + dval = data['always'] + alwaysoper = dval.op + alwayscmd = " always" + + if not del_table: + + if ((rmapoper == CachedDataWithOp.OP_DELETE) or + (metricoper == CachedDataWithOp.OP_DELETE) or + (metrictypeoper == CachedDataWithOp.OP_DELETE) or + (alwaysoper == CachedDataWithOp.OP_DELETE) or + (acclistoper == CachedDataWithOp.OP_DELETE)): + + cmd_oper = "no" + + if (alwaysoper == CachedDataWithOp.OP_DELETE): + del_cmd_suffix = alwayscmd + if (rmapoper == CachedDataWithOp.OP_DELETE): + del_cmd_suffix = rmapcmd + if (metricoper == CachedDataWithOp.OP_DELETE): + del_cmd_suffix = metriccmd + if (metrictypeoper == CachedDataWithOp.OP_DELETE): + del_cmd_suffix = metrictypecmd + + if (direction == "EXPORT"): + if (cmd_oper != "no"): + cmd_suffix = "distribute-list {} out {}".format(acclistname, protocol.lower()) + else: + cmd_suffix = "no distribute-list {} out {}".format(acclistname, protocol.lower()) + + command = "vtysh -c 'configure terminal' -c 'router ospf vrf {}' -c '{}'".\ + format(vrf, cmd_suffix) + + if not self.__run_command(table, command): + syslog.syslog(syslog.LOG_ERR, 'failed to create distribute-list {} {}'.format(protocol, direction)) + continue + else: + self.__ospf_apply_config(data, rmapoper, metricoper, metrictypeoper, alwaysoper, acclistoper) + elif (direction == "IMPORT"): + if (cmd_oper != "no"): + if (protocol == "DEFAULT_ROUTE"): + cmd_suffix = cmd_suffix + "default-information originate" + alwayscmd + rmapcmd + metriccmd + metrictypecmd + else: + cmd_suffix = cmd_suffix + "redistribute {}".format(protocol.lower()) + rmapcmd + metriccmd + metrictypecmd + else: + if (protocol == "DEFAULT_ROUTE"): + cmd_suffix = "no default-information originate" + del_cmd_suffix + else: + cmd_suffix = "no redistribute {}".format(protocol.lower()) + del_cmd_suffix + + command = "vtysh -c 'configure terminal' -c 'router ospf vrf {}' -c '{}'".\ + format(vrf, cmd_suffix) + + if not self.__run_command(table, command): + syslog.syslog(syslog.LOG_ERR, 'failed to create default-info/redistribute {} {}'.format(protocol, direction)) + continue + else: + self.__ospf_apply_config(data, rmapoper, metricoper, metrictypeoper, alwaysoper, acclistoper) + else: + if (direction == "IMPORT"): + command = "" + if (protocol == "DEFAULT_ROUTE"): + command = "vtysh -c 'configure terminal' -c 'router ospf vrf {}' -c 'no default-information originate'".\ + format(vrf) + else: + command = "vtysh -c 'configure terminal' -c 'router ospf vrf {}' -c 'no redistribute {}'".\ + format(vrf, protocol.lower()) + + if (command != ""): + if not self.__run_command(table, command): + syslog.syslog(syslog.LOG_ERR, 'failed to delete default-info/redistribute {}'.format(protocol.lower())) + continue + else: + self.__ospf_delete(data) + else: + if (acclistname != ""): + command = "vtysh -c 'configure terminal' -c 'router ospf vrf {}' -c 'no distribute-list {} out {}'".\ + format(vrf, acclistname, protocol.lower()) + + if not self.__run_command(table, command): + syslog.syslog(syslog.LOG_ERR, 'failed to delete distribute-list {} {}'.format(protocol, direction)) + continue + + self.__ospf_delete(data) + + elif table == 'OSPFV2_INTERFACE': + + key = prefix + '|' + key + if_name, if_addr = key.split('|') + + vrf = "" + if 'vrf_name' in data : + vrf = 'vrf {}'.format(data['vrf_name'].data) + + cmd_prefix = ['configure terminal', + 'interface {} {}'.format(if_name, vrf) ] + + if del_table and len(data) == 0: + syslog.syslog(syslog.LOG_INFO, 'Delete table {} {} data {}'.format(key, vrf, data)) + + cmd_data = {} + cache_tbl_key = 'OSPFV2_INTERFACE&&{}|{}'.format(if_name, if_addr) + syslog.syslog(syslog.LOG_INFO, 'Row delete key {}'.format(cache_tbl_key)) + + if cache_tbl_key in self.table_data_cache.keys(): + cache_tbl_data = self.table_data_cache[cache_tbl_key] + syslog.syslog(syslog.LOG_INFO, 'Row delete cached data {} '.format(cache_tbl_data)) + + for key, data in cache_tbl_data.items() : + cached_op_data = CachedDataWithOp(data, CachedDataWithOp.OP_DELETE) + cmd_data.update({ key : cached_op_data } ) + + syslog.syslog(syslog.LOG_INFO, 'Row delete cmd data {} '.format(cmd_data)) + + if len(cmd_data) : + if not key_map.run_command(self, table, cmd_data, cmd_prefix, if_name, if_addr): + syslog.syslog(syslog.LOG_INFO, 'failed running interface no ip ospf config command') + self.__apply_config_delete_success(cmd_data) + continue + else : + self.__apply_config_delete_success(cmd_data) + + else : + syslog.syslog(syslog.LOG_INFO, 'Create/update ospf {} interface {} in {}'.format(key, if_name, vrf)) + + #Work arround for router area config fail, update area every time + if 'area-id' in data.keys(): + dval = data['area-id'] + if dval.op == CachedDataWithOp.OP_NONE : + dval.op = CachedDataWithOp.OP_ADD + + if not key_map.run_command(self, table, data, cmd_prefix, if_name, if_addr): + syslog.syslog(syslog.LOG_ERR, 'failed running interface ip ospf config command') + if 'area-id' in data.keys(): + dval = data['area-id'] + if dval.op == CachedDataWithOp.OP_DELETE: + #Work arround for router area config delete fail + self.__apply_config_op_success(data, {'area-id': dval.op } ) + syslog.syslog(syslog.LOG_INFO, 'area-id delete enforced') + continue + else : + self.__apply_config_op_success(data) + + elif table == 'OSPFV2_ROUTER_PASSIVE_INTERFACE': + syslog.syslog(syslog.LOG_INFO, 'Create passive interface') + + vrf = prefix + + keyvals = key.split('|') + if_name = keyvals[0] + if_addr = keyvals[1] + + syslog.syslog(syslog.LOG_INFO, 'Create passive interface vrf {}'.format(vrf)) + + if (if_addr == "0.0.0.0"): + if_addr = "" + + if data == {}: + if not del_table: + + command = "vtysh -c 'configure terminal' -c 'router ospf vrf {}' -c 'passive-interface {} {}'".\ + format(vrf, if_name, if_addr) + + if not self.__run_command(table, command): + syslog.syslog(syslog.LOG_ERR, 'failed to create passive interface {} {}'.format(if_name, if_addr)) + continue + else: + command = "vtysh -c 'configure terminal' -c 'router ospf vrf {}' -c 'no passive-interface {} {}'".\ + format(vrf, if_name, if_addr) + + if not self.__run_command(table, command): + syslog.syslog(syslog.LOG_ERR, 'failed to delete passive interface {} {}'.format(if_name, if_addr)) + continue + + elif table == 'STATIC_ROUTE': + vrf = prefix + syslog.syslog(syslog.LOG_INFO, 'Set static IP route for vrf {} prefix {}'.format(vrf, key)) + op = CachedDataWithOp.OP_DELETE if del_table else CachedDataWithOp.OP_UPDATE + data['ip_prefix'] = CachedDataWithOp(key, op) + cmd_prefix = ['configure terminal', 'vrf {}'.format(vrf)] + ret_val = key_map.run_command(self, table, data, cmd_prefix, vrf) + del(data['ip_prefix']) + if not ret_val: + syslog.syslog(syslog.LOG_ERR, 'failed running static route config command') + continue + self.static_route_list.setdefault(vrf, {})[key] = self.upd_nh_set + elif table == 'PIM_INTERFACE': + + vrf = prefix + af, if_name = key.split('|') + syslog.syslog(syslog.LOG_INFO, + 'PIM interface update for vrf {}, af: {}, interface {}'.format(vrf, af, if_name)) + cmd_prefix = ['configure terminal', + 'interface {}'.format(if_name)] + syslog.syslog(syslog.LOG_INFO, + 'Create/update PIM interface: key {} interface {} in {}'.format(key, if_name, vrf)) + + # If sparse-mode has been disabled, clear other interface + # entries in cache so that they will be re-programmed in FRR + # on re-enabling of sparse-mode. + + if 'mode' in data: + modeval = data['mode'] + modeval_pim_mode = modeval.data + modeval_op = modeval.op + if (modeval_op == CachedDataWithOp.OP_DELETE): + syslog.syslog(syslog.LOG_INFO, + "Flushing PIM interface cache for deletion " + "of PIM sparse-mode") + for dkey, dval in data.items(): + dval.status = CachedDataWithOp.STAT_SUCC + dval.op = CachedDataWithOp.OP_DELETE + + # Only send the VTYSH command to FRR if the PIM interface mode + # is present in the update. + if not key_map.run_command(self, table, data, cmd_prefix): + syslog.syslog(syslog.LOG_ERR, 'failed running PIM config command') + continue + + elif table == 'PIM_GLOBALS': + + vrf = prefix + + af = key.split('|') + syslog.syslog(syslog.LOG_INFO, + 'PIM global update for vrf {}, af: {}'.format(vrf, af)) + + cmd_prefix = ['configure terminal', + 'vrf {}'.format(vrf)] + + syslog.syslog(syslog.LOG_INFO, + 'Create/update PIM global {} af {} in {}'.format(key, af, vrf)) + + # if not key_map.run_command(self, table, data, cmd_prefix, vrf, af): + if not key_map.run_command(self, table, data, cmd_prefix): + syslog.syslog(syslog.LOG_ERR, 'failed running PIM config command') + continue + + elif table == 'IGMP_INTERFACE': + ifname = prefix + + syslog.syslog(syslog.LOG_INFO, 'IGMP Interface MCast Grp ifname {} prefix {}'.format(ifname, key)) + + keyvals = key.split('|') + mcast_grp = keyvals[0] + source_ip = keyvals[1] + + syslog.syslog(syslog.LOG_INFO, 'Configure ip igmp join interface {}, mcast_grp {}, source_ip {}'.format(ifname, mcast_grp, source_ip)) + + cmd_prefix = ['configure terminal', + 'interface {}'.format(ifname)] + + if not key_map.run_command(self, table, data, cmd_prefix, mcast_grp, source_ip): + syslog.syslog(syslog.LOG_ERR, 'failed running ip igmp join config command') + continue + + + elif table == 'IGMP_INTERFACE_QUERY': + ifname = prefix + + syslog.syslog(syslog.LOG_INFO, 'IGMP Interface {} Config prefix {}'.format(ifname, key)) + + cmd_prefix = ['configure terminal', + 'interface {}'.format(ifname)] + + if not key_map.run_command(self, table, data, cmd_prefix): + syslog.syslog(syslog.LOG_ERR, 'failed running ip igmp interface config command') + continue + + + def __add_op_to_data(self, table_key, data, comb_attr_list): + cached_data = self.table_data_cache.setdefault(table_key, {}) + for key in cached_data: + if key in data: + # both in cache and data, update/none + data[key] = (CachedDataWithOp(data[key], CachedDataWithOp.OP_NONE) if data[key] == cached_data[key] else + CachedDataWithOp(data[key], CachedDataWithOp.OP_UPDATE)) + else: + # in cache but not in data, delete + data[key] = CachedDataWithOp(cached_data[key], CachedDataWithOp.OP_DELETE) + for key in data: + if not isinstance(data[key], CachedDataWithOp): + # in data but not in cache, add + data[key] = CachedDataWithOp(data[key], CachedDataWithOp.OP_ADD) + # combo attributes handling + op_list = [CachedDataWithOp.OP_DELETE, CachedDataWithOp.OP_ADD, CachedDataWithOp.OP_UPDATE, CachedDataWithOp.OP_NONE] + for key_set in comb_attr_list: + all_in = True + op_idx = len(op_list) - 1 + for key in key_set: + if key not in data: + all_in = False + break + idx = op_list.index(data[key].op) + if idx >= 0 and idx < op_idx: + op_idx = idx + if all_in: + for key in key_set: + data[key].op = op_list[op_idx] + else: + # if one key doesn't exist, clean the whole key set + for key in key_set: + data.pop(key, None) + + def __update_cache_data(self, table_key, data): + cached_data = self.table_data_cache.setdefault(table_key, {}) + for key, val in data.items(): + if not isinstance(val, CachedDataWithOp) or val.op == CachedDataWithOp.OP_NONE or val.status == CachedDataWithOp.STAT_FAIL: + syslog.syslog(syslog.LOG_DEBUG, 'ignore cache update for %s because of %s%s%s' % + (key, ('' if isinstance(val, CachedDataWithOp) else 'INV_DATA '), + ('NO_OP ' if isinstance(val, CachedDataWithOp) and val.op == CachedDataWithOp.OP_NONE else ''), + ('STAT_FAIL ' if isinstance(val, CachedDataWithOp) and val.status == CachedDataWithOp.STAT_FAIL else ''))) + continue + if val.op == CachedDataWithOp.OP_ADD or val.op == CachedDataWithOp.OP_UPDATE: + cached_data[key] = val.data + syslog.syslog(syslog.LOG_INFO, 'Add {} data {} to cache'.format(key, cached_data[key])) + elif val.op == CachedDataWithOp.OP_DELETE: + syslog.syslog(syslog.LOG_INFO, 'delete {} data {} from cache'.format(key, cached_data.get(key, ''))) + cached_data.pop(key, None) + if len(cached_data) == 0: + syslog.syslog(syslog.LOG_INFO, 'delete table row {} from cache'.format(table_key)) + del(self.table_data_cache[table_key]) + + + def bgp_table_handler_common(self, table, key, data, comb_attr_list = []): + syslog.syslog(syslog.LOG_DEBUG, '----------------------------------') + syslog.syslog(syslog.LOG_DEBUG, ' BGP table handling') + syslog.syslog(syslog.LOG_DEBUG, '----------------------------------') + syslog.syslog(syslog.LOG_DEBUG, 'table : %s' % table) + syslog.syslog(syslog.LOG_DEBUG, 'key : %s' % key) + op_str = ('DELETE' if data is None else 'SET') + del_table = False + if data is None: + data = {} + del_table = True + syslog.syslog(syslog.LOG_DEBUG, 'op : %s' % op_str) + syslog.syslog(syslog.LOG_DEBUG, 'data :') + for dkey, dval in data.items(): + syslog.syslog(syslog.LOG_DEBUG, ' %-10s - %s' % (dkey, dval)) + syslog.syslog(syslog.LOG_DEBUG, '') + table_key = ExtConfigDBConnector.get_table_key(table, key) + self.__add_op_to_data(table_key, data, comb_attr_list) + self.bgp_message.put((key, del_table, table, data)) + upd_data_list = [] + self.__update_bgp(upd_data_list) + for table, key, data in upd_data_list: + table_key = ExtConfigDBConnector.get_table_key(table, key) + self.__update_cache_data(table_key, data) + + def bgp_global_handler(self, table, key, data): + self.bgp_table_handler_common(table, key, data, [{'keepalive', 'holdtime'}]) + + def bgp_af_handler(self, table, key, data): + self.bgp_table_handler_common(table, key, data, [{'ebgp_route_distance', 'ibgp_route_distance', 'local_route_distance'}, + {'route_flap_dampen_reuse_threshold', 'route_flap_dampen_suppress_threshold', 'route_flap_dampen_max_suppress'}]) + + def bgp_neighbor_handler(self, table, key, data): + self.bgp_table_handler_common(table, key, data, [{'keepalive', 'holdtime'}]) + + def comm_set_handler(self, table, key, data): + self.bgp_table_handler_common(table, key, data, [{'set_type', 'match_action', 'community_member'}]) + + def bfd_shop_handler(self, table, key, data): + self.bgp_table_handler_common(table, key, data, [{'remote-address', 'vrf', 'interface'}, + {'remote-address', 'vrf', 'interface', 'local-address'}]) + def bfd_mhop_handler(self, table, key, data): + self.bgp_table_handler_common(table, key, data, [{'remote-address', 'vrf', 'local-address'}]) + + def start(self): + self.subscribe_all() + self.config_db.listen() + def stop(self): + self.config_db.sub_thread.stop() + if self.config_db.sub_thread.is_alive(): + self.config_db.sub_thread.join() + +main_loop = True + +def sig_handler(signum, frame): + global main_loop + syslog.syslog(syslog.LOG_DEBUG, 'entering signal handler') + main_loop = False + +def main(): + global bgpd_client + for sig_num in [signal.SIGTERM, signal.SIGINT]: + signal.signal(sig_num, sig_handler) + syslog.syslog(syslog.LOG_DEBUG, 'entering BGP configuration daemon') + bgpd_client = BgpdClientMgr() + bgpd_client.start() + daemon = BGPConfigDaemon() + daemon.start() + while main_loop: + signal.pause() + syslog.syslog(syslog.LOG_DEBUG, 'leaving BGP configuration daemon') + bgpd_client.shutdown() + daemon.stop() + +if __name__ == "__main__": + main() diff --git a/src/sonic-frr-mgmt-framework/pytest.ini b/src/sonic-frr-mgmt-framework/pytest.ini new file mode 100644 index 00000000000..c857ef5cd50 --- /dev/null +++ b/src/sonic-frr-mgmt-framework/pytest.ini @@ -0,0 +1,2 @@ +[pytest] +addopts = --cov=frrcfgd --cov-report term diff --git a/src/sonic-frr-mgmt-framework/setup.cfg b/src/sonic-frr-mgmt-framework/setup.cfg new file mode 100644 index 00000000000..00ed5efbcba --- /dev/null +++ b/src/sonic-frr-mgmt-framework/setup.cfg @@ -0,0 +1,5 @@ +[aliases] +test=pytest +[tool:pytest] +addopts = --verbose +python_files = tests/*.py diff --git a/src/sonic-frr-mgmt-framework/setup.py b/src/sonic-frr-mgmt-framework/setup.py new file mode 100755 index 00000000000..d3c9f1dae17 --- /dev/null +++ b/src/sonic-frr-mgmt-framework/setup.py @@ -0,0 +1,51 @@ +import setuptools + +setuptools.setup( + name = 'sonic-frr-mgmt-framework', + version = '1.0', + description = 'Utility to dynamically configuration FRR based on config DB data update event', + url = 'https://github.com/Azure/sonic-buildimage', + packages = setuptools.find_packages(), + entry_points = { + 'console_scripts': [ + 'frrcfgd = frrcfgd.frrcfgd:main', + ] + }, + install_requires = [ + 'jinja2>=2.10', + 'netaddr==0.8.0', + 'pyyaml==5.4.1', + 'zipp==1.2.0', # importlib-resources needs zipp and seems to have a bug where it will try to import too new of a version for Python 2 + ], + setup_requires = [ + 'pytest-runner', + 'wheel' + ], + tests_require = [ + 'pytest', + 'pytest-cov', + 'sonic-config-engine' + ], + data_files = [('sonic/frrcfgd', ['templates/bgpd/bgpd.conf.j2', + 'templates/bgpd/bgpd.conf.db.j2', + 'templates/bgpd/bgpd.conf.db.route_map.j2', + 'templates/bgpd/bgpd.conf.db.pref_list.j2', + 'templates/bgpd/bgpd.conf.db.nbr_or_peer.j2', + 'templates/bgpd/bgpd.conf.db.nbr_af.j2', + 'templates/bgpd/bgpd.conf.db.comm_list.j2', + 'templates/bgpd/bgpd.conf.db.addr_family.j2', + 'templates/bgpd/bgpd.conf.db.addr_family.evpn.j2', + 'templates/bfdd/bfdd.conf.j2', + 'templates/ospfd/ospfd.conf.j2', + 'templates/ospfd/ospfd.conf.db.area.j2', + 'templates/ospfd/ospfd.conf.db.comm_list.j2', + 'templates/ospfd/ospfd.conf.db.distributeroute.j2', + 'templates/ospfd/ospfd.conf.db.interface.j2', + 'templates/ospfd/ospfd.conf.db.policyrange.j2', + 'templates/ospfd/ospfd.conf.db.vlink.j2', + 'templates/staticd/staticd.conf.j2', + 'templates/staticd/staticd.db.conf.j2', + 'templates/staticd/staticd.db.default_route.conf.j2', + 'templates/frr/frr.conf.j2']) + ] +) diff --git a/src/sonic-frr-mgmt-framework/templates/bfdd/bfdd.conf.j2 b/src/sonic-frr-mgmt-framework/templates/bfdd/bfdd.conf.j2 new file mode 100644 index 00000000000..a4c07c02637 --- /dev/null +++ b/src/sonic-frr-mgmt-framework/templates/bfdd/bfdd.conf.j2 @@ -0,0 +1,91 @@ +! +{% block banner %} +! =========== Managed by sonic-cfggen DO NOT edit manually! ==================== +! generated by templates/frr/bfd.conf.j2 with config DB data +! file: bfd.conf +! +{% endblock banner %} +! +{% block bfd_shop_peers %} +{% if BFD_PEER_SINGLE_HOP %} +bfd +{% for (peer_key, peer_info) in BFD_PEER_SINGLE_HOP.items() %} +{% set peer_args = '' %} +{% if peer_key[0] != 'null' %} +{% set peer_args = peer_args~' '~'peer'~' '~peer_key[0] %} +{% endif %} +{% if peer_key[1] != 'null' %} +{% set peer_args = peer_args~' '~'interface'~' '~peer_key[1] %} +{% endif %} +{% if peer_key[2] != 'null' %} +{% set peer_args = peer_args~' '~'vrf'~' '~peer_key[2] %} +{% endif %} +{% if peer_key[3] != 'null' %} +{% set peer_args = peer_args~' '~'local-address'~' '~peer_key[3] %} +{% endif %} +{{ peer_args }} +{# set the bfd peer timers #} +{% if (peer_info['desired-minimum-tx-interval'] is defined and peer_info['desired-minimum-tx-interval'] | int != 300) %} + transmit-interval {{ peer_info['desired-minimum-tx-interval'] }} +{% endif %} +{% if (peer_info['required-minimum-receive'] is defined and peer_info['required-minimum-receive'] | int != 300) %} + receive-interval {{ peer_info['required-minimum-receive'] }} +{% endif %} +{% if (peer_info['detection-multiplier'] is defined and peer_info['detection-multiplier'] | int != 3) %} + detect-multiplier {{ peer_info['detection-multiplier'] }} +{% endif %} +{% if (peer_info['echo-active'] is defined and peer_info['echo-active'] != 'false') %} + echo-mode +{% endif %} +{% if (peer_info['desired-minimum-echo-receive'] is defined and peer_info['desired-minimum-echo-receive'] | int != 50) %} + echo-interval {{ peer_info['desired-minimum-echo-receive'] }} +{% endif %} +{% if (peer_info['enabled'] is defined and peer_info['enabled'] == 'true') %} + no shutdown +{% else %} + shutdown +{% endif %} + ! +{% endfor %} +! +{% endif %} +{% endblock bfd_shop_peers%} +{% block bfd_mhop_peers %} +{% if BFD_PEER_MULTI_HOP %} +bfd +{% for (peer_key, peer_info) in BFD_PEER_MULTI_HOP.items() %} +{% set peer_args = '' %} +{% if peer_key[0] != 'null' %} +{% set peer_args = peer_args~' '~'peer'~' '~peer_key[0] %} +{% endif %} +{% if peer_key[1] != 'null' %} +{% set peer_args = peer_args~' '~'interface'~' '~peer_key[1] %} +{% endif %} +{% if peer_key[2] != 'null' %} +{% set peer_args = peer_args~' '~'vrf'~' '~peer_key[2] %} +{% endif %} +{% if peer_key[3] != 'null' %} +{% set peer_args = peer_args~' '~'local-address'~' '~peer_key[3] %} +{% endif %} +{% set peer_args = peer_args~' '~'multihop' %} +{{ peer_args }} +{# set the bfd peer timers #} +{% if (peer_info['desired-minimum-tx-interval'] is defined and peer_info['desired-minimum-tx-interval'] | int != 300) %} + transmit-interval {{ peer_info['desired-minimum-tx-interval'] }} +{% endif %} +{% if (peer_info['required-minimum-receive'] is defined and peer_info['required-minimum-receive'] | int != 300) %} + receive-interval {{ peer_info['required-minimum-receive'] }} +{% endif %} +{% if (peer_info['detection-multiplier'] is defined and peer_info['detection-multiplier'] | int != 3) %} + detect-multiplier {{ peer_info['detection-multiplier'] }} +{% endif %} +{% if (peer_info['enabled'] is defined and peer_info['enabled'] == 'true') %} + no shutdown +{% else %} + shutdown +{% endif %} + ! +{% endfor %} +! +{% endif %} +{% endblock bfd_mhop_peers%} diff --git a/src/sonic-frr-mgmt-framework/templates/bgpd/bgpd.conf.db.addr_family.evpn.j2 b/src/sonic-frr-mgmt-framework/templates/bgpd/bgpd.conf.db.addr_family.evpn.j2 new file mode 100644 index 00000000000..c0db96c24dd --- /dev/null +++ b/src/sonic-frr-mgmt-framework/templates/bgpd/bgpd.conf.db.addr_family.evpn.j2 @@ -0,0 +1,78 @@ +{% if 'advertise-all-vni' in af_val and af_val['advertise-all-vni'] == 'true' %} + advertise-all-vni +{% endif %} +{% if 'autort' in af_val %} + autort {{af_val['autort']}} +{% endif %} +{% if 'advertise-default-gw' in af_val and af_val['advertise-default-gw'] == 'true' %} + advertise-default-gw +{% endif %} +{% if 'dad-enabled' in af_val and 'dad-max-moves' in af_val and 'dad-time' in af_val %} + dup-addr-detection max-moves {{af_val['dad-max-moves']}} time {{af_val['dad-time']}} +{% endif %} +{% if 'dad-freeze' in af_val %} + dup-addr-detection freeze {{af_val['dad-freeze']}} +{% endif %} +{% if 'advertise-ipv4-unicast' in af_val and af_val['advertise-ipv4-unicast'] == 'true' %} + advertise ipv4 unicast +{% endif %} +{% if 'advertise-ipv6-unicast' in af_val and af_val['advertise-ipv6-unicast'] == 'true' %} + advertise ipv6 unicast +{% endif %} +{% if 'default-originate-ipv4' in af_val and af_val['default-originate-ipv4'] == 'true' %} + default-originate ipv4 +{% endif %} +{% if 'default-originate-ipv6' in af_val and af_val['default-originate-ipv6'] == 'true' %} + default-originate ipv6 +{% endif %} +{% if 'route-distinguisher' in af_val %} + rd {{af_val['route-distinguisher']}} +{% endif %} +{% if 'import-rts' in af_val %} +{% for irt in af_val['import-rts'] %} + route-target import {{irt}} +{% endfor %} +{% endif %} +{% if 'export-rts' in af_val %} +{% for irt in af_val['export-rts'] %} + route-target export {{irt}} +{% endfor %} +{% endif %} +{% if BGP_GLOBALS_EVPN_RT is defined and BGP_GLOBALS_EVPN_RT|length > 0 %} +{% for evpn_rt_key, evpn_rt_val in BGP_GLOBALS_EVPN_RT.items() %} +{% if vrf == evpn_rt_key[0] %} + route-target {{evpn_rt_val['route-target-type']}} {{evpn_rt_key[2]}} +{% endif %} +{% endfor %} +{% endif %} +{% if BGP_GLOBALS_EVPN_VNI is defined and BGP_GLOBALS_EVPN_VNI|length > 0 %} +{% for vni_key, vni_val in BGP_GLOBALS_EVPN_VNI.items() %} +{% if vrf == vni_key[0] %} + vni {{vni_key[2]}} +{% if 'route-distinguisher' in vni_val %} + rd {{vni_val['route-distinguisher']}} +{% endif %} +{% if 'import-rts' in vni_val %} +{% for irt in vni_val['import-rts'] %} + route-target import {{irt}} +{% endfor %} +{% endif %} +{% if 'export-rts' in vni_val %} +{% for irt in vni_val['export-rts'] %} + route-target export {{irt}} +{% endfor %} +{% endif %} +{% if BGP_GLOBALS_EVPN_VNI_RT is defined and BGP_GLOBALS_EVPN_VNI_RT|length > 0 %} +{% for vni_rt_key, vni_rt_val in BGP_GLOBALS_EVPN_VNI_RT.items() %} +{% if vrf == vni_rt_key[0] and vni_key[2] == vni_rt_key[2] %} + route-target {{vni_rt_val['route-target-type']}} {{vni_rt_key[3]}} +{% endif %} +{% endfor %} +{% endif %} +{% if 'advertise-default-gw' in vni_val and vni_val['advertise-default-gw'] == 'true' %} + advertise-default-gw +{% endif %} + exit-vni +{% endif %} +{% endfor %} +{% endif %} \ No newline at end of file diff --git a/src/sonic-frr-mgmt-framework/templates/bgpd/bgpd.conf.db.addr_family.j2 b/src/sonic-frr-mgmt-framework/templates/bgpd/bgpd.conf.db.addr_family.j2 new file mode 100644 index 00000000000..9bf005518cc --- /dev/null +++ b/src/sonic-frr-mgmt-framework/templates/bgpd/bgpd.conf.db.addr_family.j2 @@ -0,0 +1,143 @@ +{# -----------------------------------------------------------------------------------------#} +{# this is invoked with the "vrf" variable set #} +{# -----------------------------------------------------------------------------------------#} +{# -------address-family --------------------------- #} +{% if (BGP_GLOBALS_AF is defined and BGP_GLOBALS_AF|length > 0) or + (BGP_GLOBALS_AF_NETWORK is defined and BGP_GLOBALS_AF_NETWORK|length > 0) or + (BGP_GLOBALS_AF_AGGREGATE_ADDR is defined and BGP_GLOBALS_AF_AGGREGATE_ADDR|length > 0) or + (ROUTE_REDISTRIBUTE is defined and ROUTE_REDISTRIBUTE|length > 0) or + (BGP_PEER_GROUP_AF is defined and BGP_PEER_GROUP_AF|length > 0) or + (BGP_NEIGHBOR_AF is defined and BGP_NEIGHBOR_AF|length > 0) %} +{% set af_str_map = { 'ipv4_unicast': 'ipv4', 'ipv6_unicast':'ipv6', 'l2vpn_evpn':'l2vpn'} %} +{% set safi_str_map = { 'ipv4_unicast': 'unicast', 'ipv6_unicast':'unicast', 'l2vpn_evpn':'evpn'} %} +{% for af, af_str in af_str_map|dictsort %} + ! + address-family {{af_str}} {{safi_str_map[af]}} +{% if BGP_GLOBALS_AF is defined and BGP_GLOBALS_AF|length > 0 %} +{% for af_key, af_val in BGP_GLOBALS_AF.items() %} +{% if vrf == af_key[0] and af == af_key[1] %} +{% if 'ebgp_route_distance' in af_val and 'ibgp_route_distance' in af_val and 'local_route_distance' in af_val %} + distance bgp {{af_val['ebgp_route_distance']}} {{af_val['ibgp_route_distance']}} {{af_val['local_route_distance']}} +{% endif %} +{% if 'import_vrf' in af_val %} + import vrf {{af_val['import_vrf']}} +{% endif %} +{% if 'import_vrf_route_map' in af_val %} + import vrf route-map {{af_val['import_vrf_route_map']}} +{% endif %} +{% endif %} +{% endfor %} +{% endif %} +{# ------- network-prefix --------------------------- #} +{% if BGP_GLOBALS_AF_NETWORK is defined and BGP_GLOBALS_AF_NETWORK|length > 0 %} +{% for af_nw_key, af_nw_val in BGP_GLOBALS_AF_NETWORK.items() %} +{% if vrf == af_nw_key[0] and af == af_nw_key[1] %} +{% set af_nw_ns = namespace(nw_end = '') %} +{% if 'backdoor' in af_nw_val and af_nw_val['backdoor'] == 'true' %} +{% set af_nw_ns.nw_end = 'backdoor ' %} +{% endif %} +{% if 'policy' in af_nw_val %} +{% set af_nw_ns.nw_end = af_nw_ns.nw_end + 'route-map ' + af_nw_val['policy'] %} +{% endif %} + network {{af_nw_key[2]}} {{af_nw_ns.nw_end}} +{% endif %} +{% endfor %} +{% endif %} +{# ------- network-prefix end --------------------------- #} +{# ------- aggregate-prefix -Start--------------------------- #} +{% if BGP_GLOBALS_AF_AGGREGATE_ADDR is defined and BGP_GLOBALS_AF_AGGREGATE_ADDR|length > 0 %} +{% for af_ag_key, af_ag_val in BGP_GLOBALS_AF_AGGREGATE_ADDR.items() %} +{% set af_ag_ns = namespace(ag_end = '') %} +{% if vrf == af_ag_key[0] and af == af_ag_key[1] %} +{% if 'as_set' in af_ag_val and af_ag_val['as_set'] == 'true' %} +{% set af_ag_ns.ag_end = 'as-set ' %} +{% endif %} +{% if 'summary_only' in af_ag_val and af_ag_val['summary_only'] == 'true' %} +{% set af_ag_ns.ag_end = af_ag_ns.ag_end + 'summary-only' %} +{% endif %} + aggregate-address {{af_ag_key[2]}} {{af_ag_ns.ag_end}} +{% endif %} +{% endfor %} +{% endif %} +{# ------- aggregate-prefix - End --------------------------- #} +{# ------- redistribute - Start --------------------------- #} +{% if ROUTE_REDISTRIBUTE is defined and ROUTE_REDISTRIBUTE|length > 0 %} +{% for rr_key, rr_val in ROUTE_REDISTRIBUTE.items() %} +{% if vrf == rr_key[0] and af_str == rr_key[3] %} +{% if 'route_map' in rr_val %} +{% for rmap in rr_val['route_map'] %} + redistribute {{rr_key[1]}} route-map {{rmap}} +{% endfor %} +{% else %} + redistribute {{rr_key[1]}} +{% endif %} +{% endif %} +{% endfor %} +{% endif %} +{# ------- redistribute - End ----------------------------- #} +{# ------- peer-group af--------------------------- #} +{% if BGP_PEER_GROUP_AF is defined and BGP_PEER_GROUP_AF|length > 0 %} +{% for n_af_key, n_af_val in BGP_PEER_GROUP_AF.items() %} +{% if vrf == n_af_key[0] and af == n_af_key[2] %} +{% set nbr_name = n_af_key[1] %} +{% include "bgpd.conf.db.nbr_af.j2" %} +{% endif %} +{% endfor %} +{% endif %} +{# ------- peer-group af end --------------------------- #} +{# ------- neighbor af--------------------------- #} +{% if BGP_NEIGHBOR_AF is defined and BGP_NEIGHBOR_AF|length > 0 %} +{% for n_af_key, n_af_val in BGP_NEIGHBOR_AF.items() %} +{% if vrf == n_af_key[0] and af == n_af_key[2] %} +{% set nbr_name = n_af_key[1] %} +{% include "bgpd.conf.db.nbr_af.j2" %} +{% endif %} +{% endfor %} +{% endif %} +{# ------- neighbor af end --------------------------- #} +{% if BGP_GLOBALS_AF is defined and BGP_GLOBALS_AF|length > 0 %} +{% for af_key, af_val in BGP_GLOBALS_AF.items() %} +{% if vrf == af_key[0] and af == af_key[1] %} +{# -------bgp dampen - start--------------------------- #} +{% if 'route_flap_dampen' in af_val and af_val['route_flap_dampen'] == 'true' %} +{% set ns = namespace(route_dampen = '') %} +{% if 'route_flap_dampen_half_life' in af_val %} +{% set ns.route_dampen = ns.route_dampen + af_val['route_flap_dampen_half_life'] + ' ' %} +{% if 'route_flap_dampen_reuse_threshold' in af_val %} +{% set ns.route_dampen = ns.route_dampen + af_val['route_flap_dampen_reuse_threshold'] + ' ' %} +{% if 'route_flap_dampen_suppress_threshold' in af_val %} +{% set ns.route_dampen = ns.route_dampen + af_val['route_flap_dampen_suppress_threshold'] + ' ' %} +{% if 'route_flap_dampen_max_suppress' in af_val %} +{% set ns.route_dampen = ns.route_dampen + af_val['route_flap_dampen_max_suppress'] + ' ' %} +{% endif %} +{% endif %} +{% endif %} +{% endif %} + bgp dampening {{ns.route_dampen}} +{% endif %} +{# -------bgp dampen - end --------------------------- #} +{% if 'max_ebgp_paths' in af_val %} + maximum-paths {{af_val['max_ebgp_paths']}} +{% endif %} +{% if 'max_ibgp_paths' in af_val %} +{% set ns = namespace(max_ibgp = af_val['max_ibgp_paths']) %} +{% if 'ibgp_equal_cluster_length' in af_val and af_val['ibgp_equal_cluster_length'] == 'true' %} +{% set ns.max_ibgp = ns.max_ibgp + ' equal-cluster-length' %} +{% endif %} + maximum-paths ibgp {{ns.max_ibgp}} +{% endif %} +{% if 'route_download_filter' in af_val %} + table-map {{af_val['route_download_filter']}} +{% endif %} +{# -------bgp evpn - start --------------------------- #} +{% if af == 'l2vpn_evpn' %} +{% include "bgpd.conf.db.addr_family.evpn.j2" %} +{% endif %} +{# -------bgp evpn - end --------------------------- #} +{% endif %} +{% endfor %} +{% endif %} + exit-address-family +{% endfor %} +{% endif %} +{# -------address-family end --------------------------- #} diff --git a/src/sonic-frr-mgmt-framework/templates/bgpd/bgpd.conf.db.comm_list.j2 b/src/sonic-frr-mgmt-framework/templates/bgpd/bgpd.conf.db.comm_list.j2 new file mode 100644 index 00000000000..3fcce07ddc9 --- /dev/null +++ b/src/sonic-frr-mgmt-framework/templates/bgpd/bgpd.conf.db.comm_list.j2 @@ -0,0 +1,54 @@ +{# ------------------------------------------------------------------------------------ #} +{% if (COMMUNITY_SET is defined and COMMUNITY_SET|length > 0) or + (EXTENDED_COMMUNITY_SET is defined and EXTENDED_COMMUNITY_SET|length >0) %} +! +{% endif %} +{# ------------------------------------------------------------------------------------ #} +{% if COMMUNITY_SET is defined and COMMUNITY_SET|length > 0 %} +{% for cm_key, cm_val in COMMUNITY_SET.items() %} +{% if 'set_type' in cm_val and 'match_action' in cm_val and 'community_member' in cm_val %} +{% if cm_val['match_action']|lower == 'all' %} +{% set ns = namespace(cm_list = '') %} +{% for cm in cm_val['community_member'] %} +{% set ns.cm_list = ns.cm_list + cm + ' ' %} +{% endfor %} +bgp community-list {{cm_val['set_type']|lower}} {{cm_key}} permit {{ns.cm_list}} +{% elif cm_val['match_action']|lower == 'any' %} +{% for cm in cm_val['community_member'] %} +bgp community-list {{cm_val['set_type']|lower}} {{cm_key}} permit {{cm}} +{% endfor %} +{% endif %} +{% endif %} +{% endfor %} +{% endif %} +{# ------------------------------------------------------------------------------------ #} +{% if EXTENDED_COMMUNITY_SET is defined and EXTENDED_COMMUNITY_SET|length > 0 %} +{% for cm_key, cm_val in EXTENDED_COMMUNITY_SET.items() %} +{% if 'set_type' in cm_val and 'match_action' in cm_val and 'community_member' in cm_val %} +{% if cm_val['match_action']|lower == 'all' %} +{% set ns = namespace(cm_list = '') %} +{% for cm in cm_val['community_member'] %} +{% if 'route-target' in cm %} +{% set ns.cm_list = ns.cm_list + 'rt ' + cm[13:] + ' ' %} +{% elif 'route-origin' in cm %} +{% set ns.cm_list = ns.cm_list + 'soo ' + cm[13:] + ' ' %} +{% else %} +{% set ns.cm_list = ns.cm_list + cm + ' ' %} +{% endif %} +{% endfor %} +bgp extcommunity-list {{cm_val['set_type']|lower}} {{cm_key}} permit {{ns.cm_list}} +{% elif cm_val['match_action']|lower == 'any' %} +{% for cm in cm_val['community_member'] %} +{% if 'route-target' in cm %} +bgp extcommunity-list {{cm_val['set_type']|lower}} {{cm_key}} permit rt {{cm[13:]}} +{% elif 'route-origin' in cm %} +bgp extcommunity-list {{cm_val['set_type']|lower}} {{cm_key}} permit soo {{cm[13:]}} +{% else %} +bgp extcommunity-list {{cm_val['set_type']|lower}} {{cm_key}} permit {{cm}} +{% endif %} +{% endfor %} +{% endif %} +{% endif %} +{% endfor %} +{% endif %} +{# ------------------------------------------------------------------------------------ #} diff --git a/src/sonic-frr-mgmt-framework/templates/bgpd/bgpd.conf.db.j2 b/src/sonic-frr-mgmt-framework/templates/bgpd/bgpd.conf.db.j2 new file mode 100644 index 00000000000..4b49813e4c9 --- /dev/null +++ b/src/sonic-frr-mgmt-framework/templates/bgpd/bgpd.conf.db.j2 @@ -0,0 +1,204 @@ +! template: bgpd/bgpd.conf.db.j2 +! +! BGP configuration using config DB BGP instance tables +! +{# ------------------------------------------------------------------------------------ #} +{% include "bgpd.conf.db.pref_list.j2" %} +{# ------------------------------------------------------------------------------------ #} +{# ------------------------------------------------------------------------------------ #} +{% include "bgpd.conf.db.route_map.j2" %} +{# ------------------------------------------------------------------------------------ #} +{% if AS_PATH_SET is defined and AS_PATH_SET|length > 0 %} +! +{% for key, val in AS_PATH_SET.items() %} +{% if 'as_path_set_member' in val %} +{% for path in val['as_path_set_member'] %} +bgp as-path access-list {{key}} permit {{path}} +{% endfor %} +{% endif %} +{% endfor %} +{% endif %} +{# ------------------------------------------------------------------------------------ #} +{% include "bgpd.conf.db.comm_list.j2" %} +{# ------------------------------------------------------------------------------------ #} +{% if BGP_GLOBALS is defined and BGP_GLOBALS|length > 0 %} +{% for vrf, bgp_sess in BGP_GLOBALS.items() %} +{% if 'local_asn' in bgp_sess %} +! +{% if vrf == 'default' %} +router bgp {{ bgp_sess['local_asn']}} +{% else %} +router bgp {{ bgp_sess['local_asn']}} vrf {{ vrf }} +{% endif %} +{% if 'fast_external_failover' in bgp_sess and bgp_sess['fast_external_failover'] == 'false' %} + no bgp fast-external-failover +{% endif %} +{% if 'router_id' in bgp_sess %} + bgp router-id {{bgp_sess['router_id']}} +{% endif %} +{% if 'log_nbr_state_changes' in bgp_sess and bgp_sess['log_nbr_state_changes'] == 'true' %} + bgp log-neighbor-changes +{% endif %} +{% if 'always_compare_med' in bgp_sess and bgp_sess['always_compare_med'] == 'true' %} + bgp always-compare-med +{% endif %} +{# --------------------------bgp default - start -------------------------------------- #} +{% if 'default_ipv4_unicast' in bgp_sess and bgp_sess['default_ipv4_unicast'] == 'true' %} + bgp default ipv4-unicast +{% else %} + no bgp default ipv4-unicast +{% endif %} +{% if 'default_local_preference' in bgp_sess %} + bgp default local-preference {{bgp_sess['default_local_preference']}} +{% endif %} +{% if 'default_show_hostname' in bgp_sess and bgp_sess['default_show_hostname'] == 'true' %} + bgp default show-hostname +{% endif %} +{% if 'default_shutdown' in bgp_sess and bgp_sess['default_shutdown'] == 'true' %} + bgp default shutdown +{% endif %} +{% if 'default_subgroup_pkt_queue_max' in bgp_sess %} + bgp default subgroup-pkt-queue-max {{bgp_sess['default_subgroup_pkt_queue_max']}} +{% endif %} +{# --------------------------bgp default - end ---------------------------------------- #} +{% if 'rr_clnt_to_clnt_reflection' in bgp_sess and bgp_sess['rr_clnt_to_clnt_reflection'] == 'false' %} + no bgp client-to-client reflection +{% endif %} +{% if 'rr_cluster_id' in bgp_sess %} + bgp cluster-id {{bgp_sess['rr_cluster_id']}} +{% endif %} +{% if 'disable_ebgp_connected_rt_check' in bgp_sess and bgp_sess['disable_ebgp_connected_rt_check'] == 'true' %} + bgp disable-ebgp-connected-route-check +{% endif %} +{% if 'deterministic_med' in bgp_sess and bgp_sess['deterministic_med'] == 'true' %} + bgp deterministic-med +{% endif %} +{% if 'max_delay' in bgp_sess %} +{% set ns = namespace(max_delay = '') %} +{% set ns.max_delay = ns.max_delay + bgp_sess['max_delay'] %} +{% if 'establish_wait' in bgp_sess %} +{% set ns.max_delay = ns.max_delay + ' ' + bgp_sess['establish_wait'] %} +{% endif %} + update-delay {{ns.max_delay}} +{% endif %} +{% if 'max_med_time' in bgp_sess %} +{% set ns = namespace(max_med = '') %} +{% set ns.max_med = ns.max_med + bgp_sess['max_med_time'] %} +{% if 'max_med_val' in bgp_sess %} +{% set ns.max_med = ns.max_med + ' ' + bgp_sess['max_med_val'] %} +{% endif %} + bgp max-med on-startup {{ns.max_med}} +{% endif %} +{% if 'max_med_admin' in bgp_sess %} +{% set adm_ns = namespace(admin_val = '') %} +{% if 'max_med_admin_val' in bgp_sess %} +{% set adm_ns.admin_val = adm_ns.admin_val + ' ' + bgp_sess['max_med_admin_val'] %} +{% endif %} + bgp max-med administrative {{adm_ns.admin_val}} +{% endif %} +{% if 'read_quanta' in bgp_sess %} + read-quanta {{bgp_sess['read_quanta']}} +{% endif %} +{% if 'write_quanta' in bgp_sess %} + write-quanta {{bgp_sess['write_quanta']}} +{% endif %} +{% if 'coalesce_time' in bgp_sess %} + coalesce-time {{bgp_sess['coalesce_time']}} +{% endif %} +{# --------------------------bgp graceful-restart - start ----------------------------- #} +{% if 'gr_stale_routes_time' in bgp_sess %} + bgp graceful-restart stalepath-time {{bgp_sess['gr_stale_routes_time']}} +{% endif %} +{% if 'gr_restart_time' in bgp_sess %} + bgp graceful-restart restart-time {{bgp_sess['gr_restart_time']}} +{% endif %} +{% if 'graceful_restart_enable' in bgp_sess and bgp_sess['graceful_restart_enable'] == 'true' %} + bgp graceful-restart +{% endif %} +{% if 'graceful_shutdown' in bgp_sess and bgp_sess['graceful_shutdown'] == 'true' %} + bgp graceful-shutdown +{% endif %} +{% if 'gr_preserve_fw_state' in bgp_sess and bgp_sess['gr_preserve_fw_state'] == 'true' %} + bgp graceful-restart preserve-fw-state +{% endif %} +{# --------------------------bgp graceful-restart - end ----------------------------- #} +{# --------------------------bgp bestpath as-path - start ----------------------------- #} +{% if 'ignore_as_path_length' in bgp_sess %} + bgp bestpath as-path ignore +{% endif %} +{% if 'compare_confed_as_path' in bgp_sess and bgp_sess['compare_confed_as_path'] == 'true' %} + bgp bestpath as-path confed +{% endif %} +{% if 'load_balance_mp_relax' in bgp_sess and bgp_sess['load_balance_mp_relax'] == 'true' %} +{% set mp_ns = namespace(mp_val = '') %} +{% if 'as_path_mp_as_set' in bgp_sess and bgp_sess['as_path_mp_as_set'] == 'true' %} +{% set mp_ns.mp_val = mp_ns.mp_val + 'as-set' %} +{% elif 'as_path_mp_as_set' in bgp_sess and bgp_sess['as_path_mp_as_set'] == 'false' %} +{% set mp_ns.mp_val = mp_ns.mp_val + 'no-as-set' %} +{% endif %} + bgp bestpath as-path multipath-relax {{mp_ns.mp_val}} +{% endif %} +{# --------------------------bgp bestpath as-path - end ----------------------------- #} +{% if 'rr_allow_out_policy' in bgp_sess and bgp_sess['rr_allow_out_policy'] == 'true' %} + bgp route-reflector allow-outbound-policy +{% endif %} +{% if 'external_compare_router_id' in bgp_sess %} + bgp bestpath compare-routerid +{% endif %} +{% if 'med_confed' in bgp_sess and bgp_sess['med_confed'] == 'true' %} + bgp bestpath med confed +{% endif %} +{% if 'med_missing_as_worst' in bgp_sess and bgp_sess['med_missing_as_worst'] == 'true' %} + bgp bestpath med confed missing-as-worst +{% endif %} +{% if 'network_import_check' in bgp_sess and bgp_sess['network_import_check'] == 'true' %} + bgp network import-check +{% endif %} +{# -------globals end --------------------------- #} +{# -------peer-group --------------------------- #} +{% if BGP_PEER_GROUP is defined and BGP_PEER_GROUP|length > 0 %} +{% for peer_group, nbr_or_peer in BGP_PEER_GROUP.items() %} +{% if vrf == peer_group[0] %} +{% set name_or_ip = peer_group[1] %} +{% set nbr_or_peer_type = 'peer-group' %} +{% include "bgpd.conf.db.nbr_or_peer.j2" %} +{% endif %} +{% endfor %} +{% endif %} +{# -------peer-group end --------------------------- #} +{# -------neighbor --------------------------- #} +{% if BGP_NEIGHBOR is defined and BGP_NEIGHBOR|length > 0 %} +{% for nbr_addr, nbr_or_peer in BGP_NEIGHBOR.items() %} +{% if nbr_addr is not string and nbr_addr|length > 1 %} +{% if vrf == nbr_addr[0] %} +{% set name_or_ip = nbr_addr[1] %} +{% set nbr_or_peer_type = 'neighbor' %} +{% include "bgpd.conf.db.nbr_or_peer.j2" %} +{% endif %} +{% endif %} +{% endfor %} +{% endif %} +{# -------neighbor end --------------------------- #} +{% if 'max_dynamic_neighbors' in bgp_sess %} + bgp listen limit {{bgp_sess['max_dynamic_neighbors']}} +{% endif %} +{% if 'route_map_process_delay' in bgp_sess %} + bgp route-map delay-timer {{bgp_sess['route_map_process_delay']}} +{% endif %} +{# -------listen-prefix --------------------------- #} +{% if BGP_GLOBALS_LISTEN_PREFIX is defined and BGP_GLOBALS_LISTEN_PREFIX|length > 0 %} +{% for lpfx, lpfx_val in BGP_GLOBALS_LISTEN_PREFIX.items() %} +{% if vrf == lpfx[0] %} +{% if 'peer_group' in lpfx_val %} + bgp listen range {{lpfx[1]}} peer-group {{lpfx_val['peer_group']}} +{% endif %} +{% endif %} +{% endfor %} +{% endif %} +{# -------listen-prefix end --------------------------- #} +{# -------address-family --------------------------- #} +{% include "bgpd.conf.db.addr_family.j2" %} +{# -------address-family --------------------------- #} +{% endif %} +{% endfor %} +{% endif %} diff --git a/src/sonic-frr-mgmt-framework/templates/bgpd/bgpd.conf.db.nbr_af.j2 b/src/sonic-frr-mgmt-framework/templates/bgpd/bgpd.conf.db.nbr_af.j2 new file mode 100644 index 00000000000..8afb64e991c --- /dev/null +++ b/src/sonic-frr-mgmt-framework/templates/bgpd/bgpd.conf.db.nbr_af.j2 @@ -0,0 +1,150 @@ +{# ------------------------------------------------------------ #} +{# this is called with the "vrf" and "address-family matched #} +{# ------------------------------------------------------------ #} +{% if 'admin_status' in n_af_val %} +{% if n_af_val['admin_status'] == 'true' %} + neighbor {{nbr_name}} activate +{% else %} + no neighbor {{nbr_name}} activate +{% endif %} +{% endif %} +{% if 'tx_add_paths' in n_af_val %} +{% if n_af_val['tx_add_paths'] == 'tx_all_paths' %} + neighbor {{nbr_name}} addpath-tx-all-paths +{% elif n_af_val['tx_add_paths'] == 'tx_best_path_per_as' %} + neighbor {{nbr_name}} addpath-tx-bestpath-per-AS +{% endif %} +{% endif %} +{% if 'nhself' in n_af_val and n_af_val['nhself'] == 'true' %} +{% if 'nexthop_self_force' in n_af_val and n_af_val['nexthop_self_force'] == 'true' %} + neighbor {{nbr_name}} next-hop-self force +{% else %} + neighbor {{nbr_name}} next-hop-self +{% endif %} +{% endif %} +{% if 'remove_private_as_enabled' in n_af_val and n_af_val['remove_private_as_enabled'] == 'true' %} +{% set ns = namespace(rpas_str='') %} +{% if 'remove_private_as_all' in n_af_val and n_af_val['remove_private_as_all'] == 'true' %} +{% set ns.rpas_str = ns.rpas_str + ' all' %} +{% endif %} +{% if 'replace_private_as' in n_af_val and n_af_val['replace_private_as'] == 'true' %} +{% set ns.rpas_str = ns.rpas_str + ' replace-AS' %} +{% endif %} + neighbor {{nbr_name}} remove-private-AS{{ns.rpas_str}} +{% endif %} +{% if 'send_community' in n_af_val %} +{% if n_af_val['send_community'] == 'standard' %} + no neighbor {{nbr_name}} send-community extended + no neighbor {{nbr_name}} send-community large +{% elif n_af_val['send_community'] == 'extended' %} + no neighbor {{nbr_name}} send-community + no neighbor {{nbr_name}} send-community large +{% elif n_af_val['send_community'] == 'large' %} + no neighbor {{nbr_name}} send-community + no neighbor {{nbr_name}} send-community extended +{% elif n_af_val['send_community'] == 'both' %} + no neighbor {{nbr_name}} send-community large +{% elif n_af_val['send_community'] == 'none' %} + no neighbor {{nbr_name}} send-community all +{% endif %} +{% endif %} +{% if 'as_override' in n_af_val and n_af_val['as_override'] == 'true' %} + neighbor {{nbr_name}} as-override +{% endif %} +{% if 'send_default_route' in n_af_val and n_af_val['send_default_route'] == 'true' %} +{% if 'default_rmap' in n_af_val %} + neighbor {{nbr_name}} default-originate route-map {{n_af_val['default_rmap']}} +{% else %} + neighbor {{nbr_name}} default-originate +{% endif %} +{% endif %} +{% if 'rrclient' in n_af_val and n_af_val['rrclient'] == 'true' %} + neighbor {{nbr_name}} route-reflector-client +{% endif %} +{% if 'soft_reconfiguration_in' in n_af_val and n_af_val['soft_reconfiguration_in'] == 'true' %} + neighbor {{nbr_name}} soft-reconfiguration inbound +{% endif %} +{# ------- maximum-prefix --------------------------- #} +{% if 'max_prefix_limit' in n_af_val %} +{% set ns = namespace(mpfx_str='maximum-prefix ' + n_af_val['max_prefix_limit']) %} +{% if 'max_prefix_warning_threshold' in n_af_val %} +{% set ns.mpfx_str = ns.mpfx_str + ' ' + n_af_val['max_prefix_warning_threshold'] %} +{% endif %} +{% if 'max_prefix_restart_interval' in n_af_val %} +{% set ns.mpfx_str = ns.mpfx_str + ' restart ' + n_af_val['max_prefix_restart_interval'] %} +{% elif 'max_prefix_warning_only' in n_af_val and n_af_val['max_prefix_warning_only'] == 'true' %} +{% set ns.mpfx_str = ns.mpfx_str + ' warning-only' %} +{% endif %} + neighbor {{nbr_name}} {{ns.mpfx_str}} +{% endif %} +{# ------- maximum-prefix end --------------------------- #} +{% if 'route_server_client' in n_af_val and n_af_val['route_server_client'] == 'true' %} + neighbor {{nbr_name}} route-server-client +{% endif %} +{# ------- allow-as --------------------------- #} +{% if 'allow_as_in' in n_af_val and n_af_val['allow_as_in'] == 'true' %} +{% if 'allow_as_origin' in n_af_val and n_af_val['allow_as_origin'] == 'true' %} + neighbor {{nbr_name}} allowas-in origin +{% elif 'allow_as_count' in n_af_val %} + neighbor {{nbr_name}} allowas-in {{n_af_val['allow_as_count']}} +{% else %} + neighbor {{nbr_name}} allowas-in +{% endif %} +{% endif %} +{# ------- allow-as end --------------------------- #} +{% if 'add_path_tx_all' in n_af_val and n_af_val['add_path_tx_all'] == 'true' %} + neighbor {{nbr_name}} addpath-tx-all-paths +{% endif %} +{% if 'add_path_tx_bestpath' in n_af_val and n_af_val['add_path_tx_bestpath'] == 'true' %} + neighbor {{nbr_name}} addpath-tx-bestpath-per-AS +{% endif %} +{% if 'cap_orf' in n_af_val %} + neighbor {{nbr_name}} capability orf prefix-list {{n_af_val['cap_orf']}} +{% endif %} +{% if 'weight' in n_af_val %} + neighbor {{nbr_name}} weight {{n_af_val['weight']}} +{% endif %} +{% if 'prefix_list_in' in n_af_val %} + neighbor {{nbr_name}} prefix-list {{n_af_val['prefix_list_in']}} in +{% endif %} +{% if 'prefix_list_out' in n_af_val %} + neighbor {{nbr_name}} prefix-list {{n_af_val['prefix_list_out']}} out +{% endif %} +{# ------- route-map in --------------------------- #} +{% if 'route_map_in' in n_af_val %} +{% for map in n_af_val['route_map_in'] %} + neighbor {{nbr_name}} route-map {{map}} in +{% endfor %} +{% endif %} +{# ------- route-map in end --------------------------- #} +{# ------- route-map out --------------------------- #} +{% if 'route_map_out' in n_af_val %} +{% for map in n_af_val['route_map_out'] %} + neighbor {{nbr_name}} route-map {{map}} out +{% endfor %} +{% endif %} +{# ------- route-map out end --------------------------- #} +{% if 'unsuppress_map_name' in n_af_val %} + neighbor {{nbr_name}} unsuppress-map {{n_af_val['unsuppress_map_name']}} +{% endif %} +{% if 'filter_list_in' in n_af_val %} + neighbor {{nbr_name}} filter-list {{n_af_val['filter_list_in']}} in +{% endif %} +{% if 'filter_list_out' in n_af_val %} + neighbor {{nbr_name}} filter-list {{n_af_val['filter_list_out']}} out +{% endif %} +{# ------- attribute-unchanged --------------------------- #} +{% set attr = '' %} +{% if 'unchanged_as_path' in n_af_val and n_af_val['unchanged_as_path'] == 'true' %} +{% set attr = 'as-path ' %} +{% endif %} +{% if 'unchanged_med' in n_af_val and n_af_val['unchanged_med'] == 'true' %} +{% set attr = attr + 'med ' %} +{% endif %} +{% if 'unchanged_nexthop' in n_af_val and n_af_val['unchanged_nexthop'] == 'true' %} +{% set attr = attr + 'next-hop' %} +{% endif %} +{% if attr != '' %} + neighbor {{nbr_name}} attribute-unchanged {{attr}} +{% endif %} +{# ------- attribute-unchanged end --------------------------- #} diff --git a/src/sonic-frr-mgmt-framework/templates/bgpd/bgpd.conf.db.nbr_or_peer.j2 b/src/sonic-frr-mgmt-framework/templates/bgpd/bgpd.conf.db.nbr_or_peer.j2 new file mode 100644 index 00000000000..8fc5e061ad5 --- /dev/null +++ b/src/sonic-frr-mgmt-framework/templates/bgpd/bgpd.conf.db.nbr_or_peer.j2 @@ -0,0 +1,103 @@ +{# ------------------------------------------------------------- #} +{# this is called with the "vrf" matched #} +{# nbr_or_peer contains the information for the neighbor or peer #} +{# name_or_ip will be the IP or the name of the neighbor or peer #} +{# ------------------------------------------------------------- #} +{% set ns_intf = namespace(intf_arg = '') %} +{% if nbr_or_peer_type == 'peer-group' %} + neighbor {{name_or_ip}} peer-group +{% else %} +{% if not (name_or_ip | ipv4 or name_or_ip | ipv6) %} +{% set ns_intf.intf_arg = 'interface ' %} +{% endif %} +{% endif %} +{% set remote_as = '' %} +{% if 'asn' in nbr_or_peer %} +{% set remote_as = nbr_or_peer['asn'] %} +{% endif %} +{% if 'peer_type' in nbr_or_peer %} +{% set remote_as = nbr_or_peer['peer_type'] %} +{% endif %} +{% if remote_as != '' %} + neighbor {{name_or_ip}} {{ns_intf.intf_arg}}remote-as {{remote_as}} +{% endif %} +{% if 'peer_group_name' in nbr_or_peer %} + neighbor {{name_or_ip}} {{ns_intf.intf_arg}}peer-group {{nbr_or_peer['peer_group_name']}} +{% endif %} +{% if 'local_asn' in nbr_or_peer %} + neighbor {{name_or_ip}} local-as {{nbr_or_peer['local_asn']}} +{% endif %} +{% if 'name' in nbr_or_peer %} + neighbor {{name_or_ip}} description {{nbr_or_peer['name']}} +{% endif %} +{% if 'admin_status' in nbr_or_peer and nbr_or_peer['admin_status'] == 'false' %} +{% if 'shutdown_message' in nbr_or_peer %} + neighbor {{name_or_ip}} shutdown message {{nbr_or_peer['shutdown_message']}} +{% else %} + neighbor {{name_or_ip}} shutdown +{% endif %} +{% endif %} +{% if 'bfd' in nbr_or_peer and nbr_or_peer['bfd'] == 'true' %} + neighbor {{name_or_ip}} bfd +{% endif %} +{% if 'ttl_security_hops' in nbr_or_peer %} + neighbor {{name_or_ip}} ttl-security hops {{nbr_or_peer['ttl_security_hops']}} +{% endif %} +{% if 'auth_password' in nbr_or_peer %} + neighbor {{name_or_ip}} password {{nbr_or_peer['auth_password']}} encrypted +{% endif %} +{% if 'solo_peer' in nbr_or_peer and nbr_or_peer['solo_peer'] == 'true' %} + neighbor {{name_or_ip}} solo +{% endif %} +{% if 'peer_port' in nbr_or_peer %} + neighbor {{name_or_ip}} port {{nbr_or_peer['peer_port']}} +{% endif %} +{% if 'passive_mode' in nbr_or_peer and nbr_or_peer['passive_mode'] == 'true' %} + neighbor {{name_or_ip}} passive +{% endif %} +{% set mhop = '' %} +{% if 'ebgp_multihop' in nbr_or_peer and nbr_or_peer['ebgp_multihop'] == 'true' %} +{% set mhop = 255 %} +{% endif %} +{% if 'ebgp_multihop_ttl' in nbr_or_peer %} +{% set mhop = nbr_or_peer['ebgp_multihop_ttl'] %} +{% endif %} +{% if mhop != '' %} + neighbor {{name_or_ip}} ebgp-multihop {{mhop}} +{% endif %} +{% if 'disable_ebgp_connected_route_check' in nbr_or_peer and nbr_or_peer['disable_ebgp_connected_route_check'] == 'true' %} + neighbor {{name_or_ip}} disable-connected-check +{% endif %} +{% if 'enforce_first_as' in nbr_or_peer and nbr_or_peer['enforce_first_as'] == 'true' %} + neighbor {{name_or_ip}} enforce-first-as +{% endif %} +{% if 'local_addr' in nbr_or_peer %} + neighbor {{name_or_ip}} update-source {{nbr_or_peer['local_addr']}} +{% endif %} +{% if 'strict_capability_match' in nbr_or_peer and nbr_or_peer['strict_capability_match'] == true %} + neighbor {{name_or_ip}} strict-capability-match {{nbr_or_peer['strict_capability_match']}} +{% endif %} +{% if 'min_adv_interval' in nbr_or_peer %} + neighbor {{name_or_ip}} advertisement-interval {{nbr_or_peer['min_adv_interval']}} +{% endif %} +{% if 'keepalive' in nbr_or_peer and 'holdtime' in nbr_or_peer %} + neighbor {{name_or_ip}} timers {{nbr_or_peer['keepalive']}} {{nbr_or_peer['holdtime']}} +{% endif %} +{% if 'conn_retry' in nbr_or_peer %} + neighbor {{name_or_ip}} timers connect {{nbr_or_peer['conn_retry']}} +{% endif %} +{% if 'capability_dynamic' in nbr_or_peer and nbr_or_peer['capability_dynamic'] == 'true' %} + neighbor {{name_or_ip}} capability dynamic +{% endif %} +{% if 'capability_ext_nexthop' in nbr_or_peer and nbr_or_peer['capability_ext_nexthop'] == 'true' %} + neighbor {{name_or_ip}} capability extended-nexthop +{% endif %} +{% if 'dont_negotiate_capability' in nbr_or_peer and nbr_or_peer['dont_negotiate_capability'] == 'true' %} + neighbor {{name_or_ip}} dont-capability-negotiate +{% endif %} +{% if 'enforce_multihop' in nbr_or_peer and nbr_or_peer['enforce_multihop'] == 'true' %} + neighbor {{name_or_ip}} enforce-multihop +{% endif %} +{% if 'override_capability' in nbr_or_peer and nbr_or_peer['override_capability'] == 'true' %} + neighbor {{name_or_ip}} override-capability +{% endif %} diff --git a/src/sonic-frr-mgmt-framework/templates/bgpd/bgpd.conf.db.pref_list.j2 b/src/sonic-frr-mgmt-framework/templates/bgpd/bgpd.conf.db.pref_list.j2 new file mode 100644 index 00000000000..3409c51be06 --- /dev/null +++ b/src/sonic-frr-mgmt-framework/templates/bgpd/bgpd.conf.db.pref_list.j2 @@ -0,0 +1,30 @@ +{# ------------------------------------------------------------------------------------ #} +{% if (PREFIX_SET is defined and PREFIX_SET|length > 0) and + (PREFIX is defined and PREFIX|length > 0) %} +{% set modes = ['IPv4', 'IPv6'] %} +{% set ip_str = {'IPv4':'ip', 'IPv6':'ipv6' } %} +{% for md in modes %} +! +{% for key, val in PREFIX_SET.items() %} +{% if 'mode' in val %} +{% for pf_key, pf_val in PREFIX.items() %} +{% if pf_key[0] == key and md == val['mode'] %} +{% if pf_key[2] == 'exact' %} +{{ip_str[md]}} prefix-list {{key}} permit {{pf_key[1]}} +{% else %} +{% set len = pf_key[1].split('/')[1] %} +{% set rb = pf_key[2].split('..')[0] %} +{% set re = pf_key[2].split('..')[1] %} +{% if rb > len %} +{{ip_str[md]}} prefix-list {{key}} permit {{pf_key[1]}} ge {{rb}} le {{re}} +{% else %} +{{ip_str[md]}} prefix-list {{key}} permit {{pf_key[1]}} le {{re}} +{% endif %} +{% endif %} +{% endif %} +{% endfor %} +{% endif %} +{% endfor %} +{% endfor %} +{% endif %} +{# ------------------------------------------------------------------------------------ #} diff --git a/src/sonic-frr-mgmt-framework/templates/bgpd/bgpd.conf.db.route_map.j2 b/src/sonic-frr-mgmt-framework/templates/bgpd/bgpd.conf.db.route_map.j2 new file mode 100644 index 00000000000..29a4817dc28 --- /dev/null +++ b/src/sonic-frr-mgmt-framework/templates/bgpd/bgpd.conf.db.route_map.j2 @@ -0,0 +1,150 @@ +{% if ROUTE_MAP is defined and ROUTE_MAP|length > 0 %} +{% for rm_key, rm_val in ROUTE_MAP.items() %} +{% if 'route_operation' in rm_val %} +! +route-map {{rm_key[0]}} {{rm_val['route_operation']}} {{rm_key[1]}} +{% if 'match_as_path' in rm_val %} + match as-path {{rm_val['match_as_path']}} +{% endif %} +{% if 'call_route_map' in rm_val %} + call {{rm_val['call_route_map']}} +{% endif %} +{% if 'match_community' in rm_val %} + match community {{rm_val['match_community']}} +{% endif %} +{% if 'match_ext_community' in rm_val %} + match extcommunity {{rm_val['match_ext_community']}} +{% endif %} +{% if 'match_interface' in rm_val %} + match interface {{rm_val['match_interface']}} +{% endif %} +{% if 'match_tag' in rm_val %} + match tag {{rm_val['match_tag'][0]}} +{% endif %} +{% if 'match_src_vrf' in rm_val %} + match source-vrf {{rm_val['match_src_vrf']}} +{% endif %} +{# ---------------match ip/ipv6-Start-------------------------- #} +{% set ip_str = {'ipv4':'ip', 'ipv6':'ipv6' } %} +{% if PREFIX_SET is defined and PREFIX_SET|length > 0 %} +{% if 'match_prefix_set' in rm_val %} +{% for pfx_key, pfx_val in PREFIX_SET.items() %} +{% if rm_val['match_prefix_set'] == pfx_key %} + match {{ip_str[pfx_val['mode']]}} address prefix-list {{rm_val['match_prefix_set']}} +{% endif %} +{% endfor %} +{% endif %} +{% if 'match_next_hop_set' in rm_val %} +{% for pfx_key, pfx_val in PREFIX_SET.items() %} +{% if rm_val['match_next_hop_set'] == pfx_key %} + match {{ip_str[pfx_val['mode']]}} next-hop prefix-list {{rm_val['match_next_hop_set']}} +{% endif %} +{% endfor %} +{% endif %} +{% endif %} +{# ---------------match ip/ipv6- End-------------------------- #} +{% if 'match_local_pref' in rm_val %} + match local-preference {{rm_val['match_local_pref']}} +{% endif %} +{% if 'match_med' in rm_val %} + match metric {{rm_val['match_med']}} +{% endif %} +{% if 'match_origin' in rm_val %} + match origin {{rm_val['match_origin']|lower}} +{% endif %} +{% if 'match_neighbor' in rm_val %} + match peer {{rm_val['match_neighbor'][0]}} +{% endif %} +{% if 'match_protocol' in rm_val %} + match source-protocol {{rm_val['match_protocol']}} +{% endif %} +{# ---------------set as-path prepend - Start ----------------- #} +{% if 'set_asn' in rm_val and 'set_repeat_asn' in rm_val %} +{% set ns = namespace(as_str='') %} +{% if rm_val['set_repeat_asn'] > 0 %} +{% for i in range(rm_val['set_repeat_asn']|int) %} +{% set ns.as_str = ns.as_str+' '+rm_val['set_asn'] %} +{% endfor %} +{% else %} +{% set ns.as_str = rm_val['set_asn'] %} +{% endif %} + set as-path prepend{{ns.as_str}} +{% endif %} +{# ---------------set as-path prepend - End ------------------- #} +{# ---------------set community - Start------------------------ #} +{% if 'set_community_inline' in rm_val %} +{% set ns = namespace(comms = '') %} +{% for cm in rm_val['set_community_inline'] %} +{% set ns.comms = ns.comms + ' ' + cm %} +{% endfor %} + set community{{ns.comms}} +{% endif %} +{# ---------------set community - End-------------------------- #} +{% if 'set_community_ref' in rm_val %} + set community {{rm_val['set_community_ref']}} +{% endif %} +{# ---------------set extcommunity - Start--------------------- #} +{% if 'set_ext_community_inline' in rm_val %} +{% set ec_ns = namespace(rt_str='', soo_str='') %} +{% for ext_comm in rm_val['set_ext_community_inline'] %} +{% set comm = ext_comm.split(':') %} +{% if comm[0] == 'route-target' %} +{% set ec_ns.rt_str = ec_ns.rt_str+' '+comm[1]+':'+comm[2] %} +{% endif %} +{% if comm[0] == 'route-origin' %} +{% set ec_ns.soo_str = ec_ns.soo_str+' '+comm[1]+':'+comm[2] %} +{% endif %} +{% endfor %} +{% if ec_ns.rt_str != '' %} + set extcommunity rt{{ec_ns.rt_str}} +{% endif %} +{% if ec_ns.soo_str != '' %} + set extcommunity soo{{ec_ns.rt_str}} +{% endif %} +{% endif %} +{# ---------------set extcommunity - End----------------------- #} +{% if 'set_ext_community_ref' in rm_val %} + set extcommunity {{rm_val['set_ext_community_ref']}} +{% endif %} +{% if 'set_next_hop' in rm_val %} + set ip next-hop {{rm_val['set_next_hop']}} +{% endif %} +{% if 'set_ipv6_next_hop_global' in rm_val %} + set ipv6 next-hop global {{rm_val['set_ipv6_next_hop_global']}} +{% endif %} +{% if 'set_ipv6_next_hop_prefer_global' in rm_val and rm_val['set_ipv6_next_hop_prefer_global'] == 'true' %} + set ipv6 next-hop prefer-global +{% endif %} +{% if 'set_local_preference' in rm_val %} + set local-preference {{rm_val['set_local_preference']}} +{% endif %} +{# ---------------set metric and med - Start--------------------- #} +{% if 'set_metric_action' in rm_val %} +{% if 'set_metric' in rm_val %} +{% if rm_val['set_metric_action'] == 'METRIC_SET_VALUE' %} + set metric {{rm_val['set_metric']}} +{% elif rm_val['set_metric_action'] == 'METRIC_ADD_VALUE' %} + set metric +{{rm_val['set_metric']}} +{% elif rm_val['set_metric_action'] == 'METRIC_SUBTRACT_VALUE' %} + set metric -{{rm_val['set_metric']}} +{% endif %} +{% endif %} +{% if rm_val['set_metric_action'] == 'METRIC_SET_RTT' %} + set metric rtt +{% elif rm_val['set_metric_action'] == 'METRIC_ADD_RTT' %} + set metric +rtt +{% elif rm_val['set_metric_action'] == 'METRIC_SUBTRACT_RTT' %} + set metric -rtt +{% endif %} +{% elif 'set_med' in rm_val %} + set metric {{rm_val['set_med']}} +{% elif 'set_metric' in rm_val %} + set metric {{rm_val['set_metric']}} +{% endif %} +{# ---------------set metric and med - End--------------------- #} +{% if 'set_origin' in rm_val %} + set origin {{rm_val['set_origin']|lower}} +{% endif %} +{% endif %} +{% endfor %} +{% endif %} diff --git a/src/sonic-frr-mgmt-framework/templates/bgpd/bgpd.conf.j2 b/src/sonic-frr-mgmt-framework/templates/bgpd/bgpd.conf.j2 new file mode 100644 index 00000000000..e37ad2a3205 --- /dev/null +++ b/src/sonic-frr-mgmt-framework/templates/bgpd/bgpd.conf.j2 @@ -0,0 +1,15 @@ +{% block banner %} +! =========== Managed by sonic-cfggen DO NOT edit manually! ==================== +! generated by templates/quagga/bgpd.conf.j2 with config DB data +! file: bgpd.conf +! +{% endblock banner %} +! +{% include "common/daemons.common.conf.j2" %} +! +agentx +! +{% include "bgpd.conf.db.j2" %} +! +! end of template: bgpd/bgpd.conf.j2 +! diff --git a/src/sonic-frr-mgmt-framework/templates/frr/frr.conf.j2 b/src/sonic-frr-mgmt-framework/templates/frr/frr.conf.j2 new file mode 100644 index 00000000000..f1f015a6e7a --- /dev/null +++ b/src/sonic-frr-mgmt-framework/templates/frr/frr.conf.j2 @@ -0,0 +1,30 @@ +! +{% block banner %} +! =========== Managed by sonic-cfggen DO NOT edit manually! ==================== +! generated by templates/frr.conf.j2 with config DB data +! file: frr.conf +! +{% endblock banner %} +! +{% include "common/daemons.common.conf.j2" %} +! +agentx +! +{% include "zebra/zebra.interfaces.conf.j2" %} +! +{% if MGMT_VRF_CONFIG %} +{% if MGMT_VRF_CONFIG['vrf_global']['mgmtVrfEnabled'] == 'false' %} +{% include "staticd.db.default_route.conf.j2" %} +{% endif %} +{% else %} +{% include "staticd.db.default_route.conf.j2" %} +{% endif %} +! +{% include "staticd.db.conf.j2" %} +! +{% include "bgpd.conf.db.j2" %} +! +{% include "ospfd.conf.j2" %} +! +{% include "bfdd.conf.j2" %} +! diff --git a/src/sonic-frr-mgmt-framework/templates/ospfd/ospfd.conf.db.area.j2 b/src/sonic-frr-mgmt-framework/templates/ospfd/ospfd.conf.db.area.j2 new file mode 100644 index 00000000000..4dfaad02798 --- /dev/null +++ b/src/sonic-frr-mgmt-framework/templates/ospfd/ospfd.conf.db.area.j2 @@ -0,0 +1,37 @@ +{% set areaid = areakey[1] %} +{% if 'authentication' in area_instance %} +{% if area_instance['authentication'] == "MD5HMAC" %} + area {{ areaid }} authentication message-digest +{% else %} + area {{ areaid }} authentication +{% endif %} +{% endif %} +{% if 'stub-no-summary' in area_instance %} +{% if area_instance['stub-no-summary'] == 'true' %} + area {{ areaid }} stub no-summary +{% endif %} +{% else %} +{% if 'stub' in area_instance %} +{% if area_instance['stub'] == 'true' %} + area {{ areaid }} stub +{% endif %} +{% endif %} +{% endif %} +{% if 'stub-default-cost' in area_instance %} + area {{ areaid }} default-cost {{ area_instance['stub-default-cost'] }} +{% endif %} +{% if 'import-list' in area_instance %} + area {{ areaid }} import-list {{ area_instance['import-list'] }} +{% endif %} +{% if 'export-list' in area_instance %} + area {{ areaid }} export-list {{ area_instance['export-list'] }} +{% endif %} +{% if 'filter-list-in' in area_instance %} + area {{ areaid }} filter-list prefix {{ area_instance['filter-list-in'] }} in +{% endif %} +{% if 'filter-list-out' in area_instance %} + area {{ areaid }} filter-list prefix {{ area_instance['filter-list-out'] }} out +{% endif %} +{% if 'shortcut' in area_instance %} + area {{ areaid }} shortcut {{ (area_instance['shortcut']).lower() }} +{% endif %} diff --git a/src/sonic-frr-mgmt-framework/templates/ospfd/ospfd.conf.db.comm_list.j2 b/src/sonic-frr-mgmt-framework/templates/ospfd/ospfd.conf.db.comm_list.j2 new file mode 100644 index 00000000000..f6fcfe897fe --- /dev/null +++ b/src/sonic-frr-mgmt-framework/templates/ospfd/ospfd.conf.db.comm_list.j2 @@ -0,0 +1,129 @@ +{# ------------------------------------------------------------------------------------ #} +{# ------------------------------------------------------------------------------------ #} +{% if OSPFV2_ROUTER is defined and OSPFV2_ROUTER|length > 0 %} +{% for vrf, ospf_instance in OSPFV2_ROUTER.items() %} +! +router ospf vrf {{ vrf }} +{% if 'router-id' in ospf_instance %} + ospf router-id {{ ospf_instance['router-id'] }} +{% endif %} +{% if 'abr-type' in ospf_instance %} + ospf abr-type {{ (ospf_instance['abr-type']).lower() }} +{% endif %} +{% if 'auto-cost-reference-bandwidth' in ospf_instance %} + auto-cost reference-bandwidth {{ (ospf_instance['auto-cost-reference-bandwidth']) }} +{% endif %} +{% if 'log-adjacency-changes' in ospf_instance %} +{% if ospf_instance['log-adjacency-changes'] == 'DETAIL' %} + log-adjacency-changes detail +{% else %} + log-adjacency-changes +{% endif %} +{% endif %} +{% if 'default-metric' in ospf_instance %} + default-metric {{ ospf_instance['default-metric'] }} +{% endif %} +{% if 'ospf-rfc1583-compatible' in ospf_instance %} +{% if ospf_instance['ospf-rfc1583-compatible'] == 'true' %} + compatible rfc1583 +{% endif %} +{% endif %} +{% if 'passive-interface-default' in ospf_instance %} + passive-interface default +{% endif %} +{% if 'write-multiplier' in ospf_instance %} + write-multiplier {{ ospf_instance['write-multiplier'] }} +{% endif %} +{% if 'spf-throttle-delay' in ospf_instance and 'spf-initial-delay' in ospf_instance and 'spf-maximum-delay' in ospf_instance %} + timers throttle spf {{ ospf_instance['spf-throttle-delay'] }} {{ ospf_instance['spf-initial-delay'] }} {{ ospf_instance['spf-maximum-delay'] }} +{% endif %} +{% if 'lsa-min-interval-timer' in ospf_instance %} + timers throttle lsa all {{ ospf_instance['lsa-min-interval-timer'] }} +{% endif %} +{% if 'lsa-min-arrival-timer' in ospf_instance %} + timers lsa min-arrival {{ ospf_instance['lsa-min-arrival-timer'] }} +{% endif %} +{% if 'lsa-refresh-timer' in ospf_instance %} + refresh timer {{ ospf_instance['lsa-refresh-timer'] }} +{% endif %} +{% if 'max-metric-administrative' in ospf_instance %} +{% if ospf_instance['max-metric-administrative'] == 'true' %} + max-metric router-lsa administrative +{% endif %} +{% endif %} +{% if 'max-metric-on-startup' in ospf_instance %} + max-metric router-lsa on-startup {{ ospf_instance['max-metric-on-startup'] }} +{% endif %} +{% if 'max-metric-on-shutdown' in ospf_instance %} + max-metric router-lsa on-shutdown {{ ospf_instance['max-metric-on-shutdown'] }} +{% endif %} +{% if 'distance-all' in ospf_instance %} + distance {{ ospf_instance['distance-all'] }} +{% endif %} +{% if 'distance-inter-area' in ospf_instance or 'distance-intra-area' in ospf_instance or 'distance-external' in ospf_instance%} +{% set distance_cmd = '' %} +{% set distance_cmd = 'distance ospf' %} +{% if 'distance-intra-area' in ospf_instance %} +{% set distance_cmd = distance_cmd + ' intra-area ' + ospf_instance['distance-intra-area'] %} +{% endif %} +{% if 'distance-inter-area' in ospf_instance %} +{% set distance_cmd = distance_cmd + ' inter-area ' + ospf_instance['distance-inter-area'] %} +{% endif %} +{% if 'distance-external' in ospf_instance %} +{% set distance_cmd = distance_cmd + ' external ' + ospf_instance['distance-external'] %} +{% endif %} + {{ distance_cmd }} +{% endif %} +{# -------OSPFV2_ROUTER end --------------------------- #} +{# -------OSPFV2_ROUTER_AREA Begin --------------------------- #} +{% if OSPFV2_ROUTER_AREA is defined and OSPFV2_ROUTER_AREA|length > 0 %} +{% for areakey, area_instance in OSPFV2_ROUTER_AREA.items() %} +{% include "ospfd.conf.db.area.j2" %} +{% endfor %} +{% endif %} +{# -------OSPFV2_ROUTER_AREA end --------------------------- #} +{# -------OSPFV2_ROUTER_AREA_NETWORK Begin --------------------------- #} +{% if OSPFV2_ROUTER_AREA_NETWORK is defined and OSPFV2_ROUTER_AREA_NETWORK|length > 0 %} +{% for networkkey, ospf_network_instance in OSPFV2_ROUTER_AREA_NETWORK.items() %} +{% set networkareaid = networkkey[1] %} +{% set networkid = networkkey[2] %} + network {{ networkid }} area {{ networkareaid }} +{% endfor %} +{% endif %} +{# -------OSPFV2_ROUTER_AREA_NETWORK end --------------------------- #} +{# -------OSPFV2_ROUTER_AREA_VIRTUAL_LINK Begin --------------------------- #} +{% if OSPFV2_ROUTER_AREA_VIRTUAL_LINK is defined and OSPFV2_ROUTER_AREA_VIRTUAL_LINK|length > 0 %} +{% for vlinkkey, vlink_instance in OSPFV2_ROUTER_AREA_VIRTUAL_LINK.items() %} +{% include "ospfd.conf.db.vlink.j2" %} +{% endfor %} +{% endif %} +{# -------OSPFV2_ROUTER_AREA_VIRTUAL_LINK end --------------------------- #} +{# -------OSPFV2_ROUTER_AREA_POLICY_ADDRESS_RANGE Begin --------------------------- #} +{% if OSPFV2_ROUTER_AREA_POLICY_ADDRESS_RANGE is defined and OSPFV2_ROUTER_AREA_POLICY_ADDRESS_RANGE|length > 0 %} +{% for rangekey, area_range_instance in OSPFV2_ROUTER_AREA_POLICY_ADDRESS_RANGE.items() %} +{% include "ospfd.conf.db.policyrange.j2" %} +{% endfor %} +{% endif %} +{# -------OSPFV2_ROUTER_AREA_POLICY_ADDRESS_RANGE end --------------------------- #} +{# -------OSPFV2_ROUTER_DISTRIBUTE_ROUTE Begin --------------------------- #} +{% if OSPFV2_ROUTER_DISTRIBUTE_ROUTE is defined and OSPFV2_ROUTER_DISTRIBUTE_ROUTE|length > 0 %} +{% for routekey, route_instance in OSPFV2_ROUTER_DISTRIBUTE_ROUTE.items() %} +{% include "ospfd.conf.db.distributeroute.j2" %} +{% endfor %} +{% endif %} +{# -------OSPFV2_ROUTER_DISTRIBUTE_ROUTE end --------------------------- #} +{# -------OSPFV2_ROUTER_PASSIVE_INTERFACE Begin --------------------------- #} +{% if OSPFV2_ROUTER_PASSIVE_INTERFACE is defined and OSPFV2_ROUTER_PASSIVE_INTERFACE|length > 0 %} +{% for passintfkey, passintf_instance in OSPFV2_ROUTER_PASSIVE_INTERFACE.items() %} +{% set passintfname = passintfkey[1] %} +{% set passintfaddr = passintfkey[2] %} +{% if passintfaddr == '0.0.0.0' %} + passive-interface {{ passintfname }} +{% else %} + passive-interface {{ passintfname }} {{ passintfaddr }} +{% endif %} +{% endfor %} +{% endif %} +{# -------OSPFV2_ROUTER_PASSIVE_INTERFACE end --------------------------- #} +{% endfor %} +{% endif %} diff --git a/src/sonic-frr-mgmt-framework/templates/ospfd/ospfd.conf.db.distributeroute.j2 b/src/sonic-frr-mgmt-framework/templates/ospfd/ospfd.conf.db.distributeroute.j2 new file mode 100644 index 00000000000..d13ac7ada5b --- /dev/null +++ b/src/sonic-frr-mgmt-framework/templates/ospfd/ospfd.conf.db.distributeroute.j2 @@ -0,0 +1,52 @@ +{% set routeproto = routekey[1] %} +{% set routedirection = routekey[2] %} +{% set generic_protocols = [ "BGP", "KERNEL", "STATIC", "DIRECTLY_CONNECTED"] %} +{% if routeproto == "DEFAULT_ROUTE" and routedirection == "IMPORT" %} +{% set defaultinfo_cmd = '' %} +{% set defaultinfo_cmd = 'default-information originate' %} +{% if 'always' in route_instance %} +{% if route_instance['always'] == 'true' %} +{% set defaultinfo_cmd = defaultinfo_cmd + ' always' %} +{% endif %} +{% endif %} +{% if 'metric' in route_instance %} +{% set defaultinfo_cmd = defaultinfo_cmd + ' metric ' + route_instance['metric'] %} +{% endif %} +{% if 'metric-type' in route_instance %} +{% if route_instance['metric-type'] == "TYPE_1"%} +{% set defaultinfo_cmd = defaultinfo_cmd + ' metric-type ' + '1' %} +{% endif %} +{% endif %} +{% if 'route-map' in route_instance %} +{% set defaultinfo_cmd = defaultinfo_cmd + ' route-map ' + route_instance['route-map'] %} +{% endif %} + {{ defaultinfo_cmd }} +{% elif routedirection == "IMPORT" and routeproto in generic_protocols %} +{% set redistribute_cmd = '' %} +{% if routeproto == "DIRECTLY_CONNECTED" %} +{% set redistribute_cmd = 'redistribute ' + 'connected' %} +{% else %} +{% set redistribute_cmd = 'redistribute ' + routeproto.lower() %} +{% endif %} +{% if 'metric' in route_instance %} +{% set redistribute_cmd = redistribute_cmd + ' metric ' + route_instance['metric'] %} +{% endif %} +{% if 'metric-type' in route_instance %} +{% if route_instance['metric-type'] == "TYPE_1"%} +{% set redistribute_cmd = redistribute_cmd + ' metric-type ' + '1' %} +{% endif %} +{% endif %} +{% if 'route-map' in route_instance %} +{% set redistribute_cmd = redistribute_cmd + ' route-map ' + route_instance['route-map'] %} +{% endif %} + {{ redistribute_cmd }} +{% elif routedirection == "EXPORT" and routeproto in generic_protocols %} +{% if 'route-map' in route_instance %} +{% if routeproto == "DIRECTLY_CONNECTED" %} + distribute-list {{ route_instance['route-map'] }} out connected +{% else %} + distribute-list {{ route_instance['route-map'] }} out {{ routeproto.lower() }} +{% endif %} +{% endif %} +{% endif %} + diff --git a/src/sonic-frr-mgmt-framework/templates/ospfd/ospfd.conf.db.interface.j2 b/src/sonic-frr-mgmt-framework/templates/ospfd/ospfd.conf.db.interface.j2 new file mode 100644 index 00000000000..7969c81f2da --- /dev/null +++ b/src/sonic-frr-mgmt-framework/templates/ospfd/ospfd.conf.db.interface.j2 @@ -0,0 +1,76 @@ +{# ------------------------------------------------------------------------------------ #} +{# ------------------------------------------------------------------------------------ #} +{% if OSPFV2_INTERFACE is defined and OSPFV2_INTERFACE|length > 0 %} +{% for (intfkey, ospf_intf_instance) in OSPFV2_INTERFACE.items() %} +! +{% set intfname = intfkey[0] %} +{% set intfaddr = intfkey[1] %} +{% if intfaddr == "0.0.0.0" %} +{% set intfaddr = "" %} +{% endif %} +interface {{ intfname }} +{% if 'area-id' in ospf_intf_instance %} + ip ospf area {{ ospf_intf_instance['area-id'] }} {{ intfaddr }} +{% endif %} +{% if 'network-type' in ospf_intf_instance %} +{% if ospf_intf_instance['network-type'] == 'BROADCAST_NETWORK' %} + ip ospf network broadcast {{ intfaddr }} +{% endif %} +{% if ospf_intf_instance['network-type'] == 'POINT_TO_POINT_NETWORK' %} + ip ospf network point-to-point {{ intfaddr }} +{% endif %} +{% endif %} +{% if 'metric' in ospf_intf_instance %} + ip ospf cost {{ ospf_intf_instance['metric'] }} {{ intfaddr }} +{% endif %} +{% if 'priority' in ospf_intf_instance %} + ip ospf priority {{ ospf_intf_instance['priority'] }} {{ intfaddr }} +{% endif %} +{% if 'mtu-ignore' in ospf_intf_instance %} +{% if ospf_intf_instance['mtu-ignore'] == 'true' %} + ip ospf mtu-ignore {{ intfaddr }} +{% endif %} +{% endif %} +{% if 'bfd-enable' in ospf_intf_instance %} +{% if ospf_intf_instance['bfd-enable'] == 'true' %} + ip ospf bfd +{% endif %} +{% endif %} +{% if 'authentication-type' in ospf_intf_instance %} +{% if ospf_intf_instance['authentication-type'] == 'MD5HMAC' %} + ip ospf authentication message-digest {{ intfaddr }} +{% endif %} +{% if ospf_intf_instance['authentication-type'] == 'NONE' %} + ip ospf authentication null {{ intfaddr }} +{% endif %} +{% if ospf_intf_instance['authentication-type'] == 'TEXT' %} + ip ospf authentication {{ intfaddr }} +{% endif %} +{% endif %} +{% if 'authentication-key' in ospf_intf_instance %} + ip ospf authentication-key {{ ospf_intf_instance['authentication-key'] }} {{ intfaddr }} +{% endif %} +{% if 'authentication-key-id' in ospf_intf_instance and 'authentication-md5-key' in ospf_intf_instance %} + ip ospf message-digest-key {{ ospf_intf_instance['authentication-key-id'] }} md5 {{ ospf_intf_instance['authentication-md5-key'] }} {{ intfaddr }} +{% endif %} +{% if 'dead-interval' in ospf_intf_instance %} + ip ospf dead-interval {{ ospf_intf_instance['dead-interval'] }} {{ intfaddr }} +{% endif %} +{% if 'dead-interval-minimal' in ospf_intf_instance %} +{% if 'hello-multiplier' in ospf_intf_instance %} + ip ospf dead-interval minimal hello-multiplier {{ ospf_intf_instance['hello-multiplier'] }} {{ intfaddr }} +{% else %} + ip ospf dead-interval minimal {{ intfaddr }} +{% endif %} +{% endif %} +{% if 'hello-interval' in ospf_intf_instance %} + ip ospf hello-interval {{ ospf_intf_instance['hello-interval'] }} {{ intfaddr }} +{% endif %} +{% if 'retransmission-interval' in ospf_intf_instance %} + ip ospf retransmit-interval {{ ospf_intf_instance['retransmission-interval'] }} {{ intfaddr }} +{% endif %} +{% if 'transmit-delay' in ospf_intf_instance %} + ip ospf transmit-delay {{ ospf_intf_instance['transmit-delay'] }} {{ intfaddr }} +{% endif %} +{% endfor %} +{% endif %} diff --git a/src/sonic-frr-mgmt-framework/templates/ospfd/ospfd.conf.db.policyrange.j2 b/src/sonic-frr-mgmt-framework/templates/ospfd/ospfd.conf.db.policyrange.j2 new file mode 100644 index 00000000000..8d82b41c082 --- /dev/null +++ b/src/sonic-frr-mgmt-framework/templates/ospfd/ospfd.conf.db.policyrange.j2 @@ -0,0 +1,16 @@ +{% set rangeareaid = rangekey[1] %} +{% set rangeid = rangekey[2] %} + area {{ rangeareaid }} range {{ rangeid }} +{% if 'advertise' in area_range_instance %} +{% if area_range_instance['advertise'] == 'true' %} + area {{ rangeareaid }} range {{ rangeid }} advertise +{% else %} + area {{ rangeareaid }} range {{ rangeid }} not-advertise +{% endif %} +{% endif %} +{% if 'metric' in area_range_instance %} + area {{ rangeareaid }} range {{ rangeid }} advertise cost {{ area_range_instance['metric'] }} +{% endif %} +{% if 'substitue-prefix' in area_range_instance %} + area {{ rangeareaid }} range {{ rangeid }} substitute {{ area_range_instance['substitue-prefix'] }} +{% endif %} \ No newline at end of file diff --git a/src/sonic-frr-mgmt-framework/templates/ospfd/ospfd.conf.db.vlink.j2 b/src/sonic-frr-mgmt-framework/templates/ospfd/ospfd.conf.db.vlink.j2 new file mode 100644 index 00000000000..653db9f5458 --- /dev/null +++ b/src/sonic-frr-mgmt-framework/templates/ospfd/ospfd.conf.db.vlink.j2 @@ -0,0 +1,29 @@ +{% set vlinkareaid = vlinkkey[1] %} +{% set vlinkid = vlinkkey[2] %} + area {{ vlinkareaid }} virtual-link {{ vlinkid }} +{% if 'authentication' in vlink_instance %} +{% if vlink_instance['authentication'] == 'MD5HMAC' %} + area {{ vlinkareaid }} virtual-link {{ vlinkid }} authentication message-digest +{% else %} + area {{ vlinkareaid }} virtual-link {{ vlinkid }} null +{% endif %} +{% endif %} +{% if 'authentication-key' in vlink_instance %} + area {{ vlinkareaid }} virtual-link {{ vlinkid }} authentication-key {{ vlink_instance['authentication-key'] }} +{% endif %} +{% if 'authentication-key-id' in vlink_instance and 'authentication-md5-key' in vlink_instance %} + area {{ vlinkareaid }} virtual-link {{ vlinkid }} authentication message-digest message-digest-key {{ vlink_instance['authentication-key-id'] }} md5 {{ vlink_instance['authentication-md5-key'] }} +{% endif %} +{% if 'dead-interval' in vlink_instance %} + area {{ vlinkareaid }} virtual-link {{ vlinkid }} dead-interval {{ vlink_instance['dead-interval'] }} +{% endif %} +{% if 'hello-interval' in vlink_instance %} + area {{ vlinkareaid }} virtual-link {{ vlinkid }} hello-interval {{ vlink_instance['hello-interval'] }} +{% endif %} +{% if 'retransmission-interval' in vlink_instance %} + area {{ vlinkareaid }} virtual-link {{ vlinkid }} retransmit-interval {{ vlink_instance['retransmission-interval'] }} +{% endif %} +{% if 'transmit-delay' in vlink_instance %} + area {{ vlinkareaid }} virtual-link {{ vlinkid }} transmit-delay {{ vlink_instance['transmit-delay'] }} +{% endif %} + diff --git a/src/sonic-frr-mgmt-framework/templates/ospfd/ospfd.conf.j2 b/src/sonic-frr-mgmt-framework/templates/ospfd/ospfd.conf.j2 new file mode 100644 index 00000000000..d9ace5972da --- /dev/null +++ b/src/sonic-frr-mgmt-framework/templates/ospfd/ospfd.conf.j2 @@ -0,0 +1,6 @@ +! template: ospfd/ospfd.conf.j2 +! +! OSPF configuration using config DB OSPF instance tables +! +{% include "ospfd.conf.db.comm_list.j2" %} +{% include "ospfd.conf.db.interface.j2" %} diff --git a/src/sonic-frr-mgmt-framework/templates/staticd/staticd.conf.j2 b/src/sonic-frr-mgmt-framework/templates/staticd/staticd.conf.j2 new file mode 100644 index 00000000000..0ab193f4a1f --- /dev/null +++ b/src/sonic-frr-mgmt-framework/templates/staticd/staticd.conf.j2 @@ -0,0 +1,22 @@ + +{% block banner %} +! =========== Managed by sonic-cfggen DO NOT edit manually! ==================== +! generated by templates/frr/staticd.conf.j2 using config DB data +! file: staticd.conf +! +{% endblock banner %} +! +{% with agentx='false' %} +{% include "common/daemons.common.conf.j2" %} +{% endwith %} +! +{% if MGMT_VRF_CONFIG %} +{% if MGMT_VRF_CONFIG['vrf_global']['mgmtVrfEnabled'] == 'false' %} +{% include "staticd.db.default_route.conf.j2" %} +{% endif %} +{% else %} +{% include "staticd.db.default_route.conf.j2" %} +{% endif %} +! +{% include "staticd.db.conf.j2" %} +! diff --git a/src/sonic-frr-mgmt-framework/templates/staticd/staticd.db.conf.j2 b/src/sonic-frr-mgmt-framework/templates/staticd/staticd.db.conf.j2 new file mode 100644 index 00000000000..238f0f1acb6 --- /dev/null +++ b/src/sonic-frr-mgmt-framework/templates/staticd/staticd.db.conf.j2 @@ -0,0 +1,153 @@ +! template: staticd/staticd.db.conf.j2 +! +! Static Route configuration using config DB static route table +! +{% macro iproute(ip_prefix, nh_blackhole, nh_ip, nh_intf, nh_dist, nh_tag, nh_vrf) %} + {%- set ns = namespace(str = None) %} + {%- set ip_addr = ip_prefix.split('/')[0] %} + {%- if ip_addr|ipv4 %} + {%- set ns.str = 'ip route' %} + {%- else %} + {%- set ns.str = 'ipv6 route' %} + {%- endif %} + {%- if nh_blackhole %} + {#- ------------------------------ blackhole route ------------------------------ #} + {%- for item in [ip_prefix, 'blackhole', nh_tag, nh_dist] %} + {%- if item != None %} + {%- set ns.str = ns.str + ' ' + item %} + {%- endif %} + {%- endfor %} + {%- else %} + {#- ------------------------------ non-blackhole route ------------------------------ #} + {%- for item in [ip_prefix, nh_ip, nh_intf, nh_tag, nh_dist, nh_vrf] %} + {%- if item != None %} + {%- set ns.str = ns.str + ' ' + item %} + {%- endif %} + {%- endfor %} + {%- endif %} +{{ ns.str }} +{%- endmacro %} +{% if STATIC_ROUTE is defined and STATIC_ROUTE|length > 0 %} + {%- set vrf_rt_list = {} %} + {%- for key, val in STATIC_ROUTE.items() %} + {#- ------------------------------ for each route - start ------------------------------ #} + {%- set rt = namespace(vrf = 'default', ip_prefix = '', nh_num = 0, nh_list = [], valid = True) %} + {%- if key is not string and key|length > 1 %} + {%- set rt.vrf = key[0] %} + {%- set rt.ip_prefix = key[1] %} + {%- else %} + {%- set rt.ip_prefix = key %} + {%- endif %} + {%- set nh_attr = {} %} + {#- ------------------------------ get nh count - start ------------------------------ #} + {%- for fld_key, fld_val in val.items() if rt.valid %} + {%- set attr_list = fld_val.split(',') %} + {%- if rt.nh_num == 0 %} + {%- set rt.nh_num = attr_list|length %} + {%- else %} + {%- if rt.nh_num != attr_list|length %} + {%- set rt.valid = False %} + {%- endif %} + {%- endif %} + {%- if nh_attr.update({fld_key: attr_list}) %} + {%- endif %} + {%- endfor %} + {#- ------------------------------ get nh count - end ------------------------------ #} + {%- if rt.valid %} + {%- for nh_idx in range(rt.nh_num) %} + {#- ------------------------------ parse nh - start ------------------------------ #} + {%- set nh = namespace(blackhole = False, ip = None, intf = None, dist = None, tag = None, vrf = None) %} + {#- ------------------------------ nexthop blackhole ------------------------------ #} + {%- if 'blackhole' in nh_attr %} + {%- set nh.blackhole = nh_attr['blackhole'][nh_idx] %} + {%- if nh.blackhole == 'true' %} + {%- set nh.blackhole = True %} + {%- else %} + {%- set nh.blackhole = False %} + {%- endif %} + {%- endif %} + {#- ------------------------------ nexthop IP ------------------------------ #} + {%- if 'nexthop' in nh_attr %} + {%- set nh.ip = nh_attr['nexthop'][nh_idx] %} + {%- if nh.ip == '0.0.0.0' or nh.ip == '::' %} + {%- set nh.ip = None %} + {%- endif %} + {%- endif %} + {#- ------------------------------ nexthop interface ------------------------------ #} + {%- if 'ifname' in nh_attr %} + {%- set nh.intf = nh_attr['ifname'][nh_idx] %} + {%- if nh.intf == '' %} + {%- set nh.intf = None %} + {%- endif %} + {%- endif %} + {#- ------------------------------ nexthop distance ------------------------------ #} + {%- if 'distance' in nh_attr %} + {%- set nh.dist = nh_attr['distance'][nh_idx] %} + {%- if nh.dist == '0' %} + {%- set nh.dist = None %} + {%- endif %} + {%- endif %} + {#- ------------------------------ nexthop tag ------------------------------ #} + {%- if 'tag' in nh_attr %} + {%- set nh.tag = nh_attr['tag'][nh_idx] %} + {%- if nh.tag == '0' %} + {%- set nh.tag = None %} + {%- endif %} + {%- if nh.tag != None %} + {%- set nh.tag = 'tag ' + nh.tag %} + {%- endif %} + {%- endif %} + {#- ------------------------------ nexthop VRF ------------------------------ #} + {%- if 'nexthop-vrf' in nh_attr %} + {%- set nh.vrf = nh_attr['nexthop-vrf'][nh_idx] %} + {%- if nh.vrf == '' %} + {%- set nh.vrf = None %} + {%- endif %} + {%- if nh.vrf != None %} + {%- set nh.vrf = 'nexthop-vrf ' + nh.vrf %} + {%- endif %} + {%- endif %} + {#- ------------------------------ parse nh - end ------------------------------ #} + {%- if nh.blackhole or nh.ip != None or nh.intf != None %} + {%- if rt.nh_list.append(nh) %} + {%- endif %} + {%- endif %} + {%- endfor %} + {#- ------------------------------ for each route - end ------------------------------ #} + {%- if not rt.vrf in vrf_rt_list %} + {%- if vrf_rt_list.update({rt.vrf: []}) %} + {%- endif %} + {%- endif %} + {%- if vrf_rt_list[rt.vrf].append(rt) %} + {%- endif %} + {%- endif %} + {%- endfor %} + +{# ------------------------------ dump route - start ------------------------------ #} +{# ------------------------------ default VRF ------------------------------ #} +{% for vrf, rt_list in vrf_rt_list.items() if vrf == 'default' %} +{% for rt in rt_list %} +{% if rt.valid %} +{% for nh in rt.nh_list %} +{{ iproute(rt.ip_prefix, nh.blackhole, nh.ip, nh.intf, nh.dist, nh.tag, nh.vrf) }} +{% endfor %} +{% endif %} +{% endfor %} +{% endfor %} +{# ------------------------------ non-default VRF ------------------------------ #} +{% for vrf, rt_list in vrf_rt_list.items() if vrf != 'default' %} +! +vrf {{ vrf }} +{% for rt in rt_list %} +{% if rt.valid %} +{% for nh in rt.nh_list %} + {{ iproute(rt.ip_prefix, nh.blackhole, nh.ip, nh.intf, nh.dist, nh.tag, nh.vrf) }} +{% endfor %} +{% endif %} +{% endfor %} + exit-vrf +! +{% endfor %} +{# ------------------------------ dump route - end ------------------------------ #} + +{% endif %} diff --git a/src/sonic-frr-mgmt-framework/templates/staticd/staticd.db.default_route.conf.j2 b/src/sonic-frr-mgmt-framework/templates/staticd/staticd.db.default_route.conf.j2 new file mode 100644 index 00000000000..63d532203aa --- /dev/null +++ b/src/sonic-frr-mgmt-framework/templates/staticd/staticd.db.default_route.conf.j2 @@ -0,0 +1,9 @@ +! +{% block default_route %} +! set static default route to mgmt gateway as a backup to learned default +{% if MGMT_INTERFACE %} +{% for (name, prefix) in MGMT_INTERFACE|pfx_filter %} +{% endfor %} +{% endif %} +{% endblock default_route %} +! diff --git a/src/sonic-frr-mgmt-framework/tests/__init__.py b/src/sonic-frr-mgmt-framework/tests/__init__.py new file mode 100644 index 00000000000..e69de29bb2d diff --git a/src/sonic-frr-mgmt-framework/tests/test_config.py b/src/sonic-frr-mgmt-framework/tests/test_config.py new file mode 100644 index 00000000000..ed31c1e28ec --- /dev/null +++ b/src/sonic-frr-mgmt-framework/tests/test_config.py @@ -0,0 +1,176 @@ +import copy +import re +from unittest.mock import MagicMock, NonCallableMagicMock, patch + +swsssdk_module_mock = MagicMock(ConfigDBConnector = NonCallableMagicMock) + +@patch.dict('sys.modules', swsssdk = swsssdk_module_mock) +def test_contructor(): + from frrcfgd.frrcfgd import BGPConfigDaemon + daemon = BGPConfigDaemon() + daemon.start() + for table, hdlr in daemon.table_handler_list: + daemon.config_db.subscribe.assert_any_call(table, hdlr) + daemon.config_db.pubsub.psubscribe.assert_called_once() + daemon.stop() + daemon.config_db.sub_thread.stop.assert_called() + daemon.config_db.sub_thread.is_alive.assert_called_once() + daemon.config_db.sub_thread.join.assert_called_once() + +class CmdMapTestInfo: + data_buf = {} + def __init__(self, table, key, data, exp_cmd, no_del = False, neg_cmd = None, + chk_data = None, daemons = None, ignore_tail = False): + self.table_name = table + self.key = key + self.data = data + self.vtysh_cmd = exp_cmd + self.no_del = no_del + self.vtysh_neg_cmd = neg_cmd + self.chk_data = chk_data + self.daemons = daemons + self.ignore_tail = ignore_tail + @classmethod + def add_test_data(cls, test): + assert(isinstance(test.data, dict)) + cls.data_buf.setdefault( + test.table_name, {}).setdefault(test.key, {}).update(test.data) + @classmethod + def del_test_data(cls, test): + assert(test.table_name in cls.data_buf and + test.key in cls.data_buf[test.table_name]) + cache_data = cls.data_buf[test.table_name][test.key] + assert(isinstance(test.data, dict)) + for k, v in test.data.items(): + assert(k in cache_data and cache_data[k] == v) + del(cache_data[k]) + @classmethod + def get_test_data(cls, test): + assert(test.table_name in cls.data_buf and + test.key in cls.data_buf[test.table_name]) + return copy.deepcopy(cls.data_buf[test.table_name][test.key]) + @staticmethod + def compose_vtysh_cmd(cmd_list, negtive = False): + cmdline = 'vtysh' + for cmd in cmd_list: + cmd = cmd.format('no ' if negtive else '') + cmdline += " -c '%s'" % cmd + return cmdline + def check_running_cmd(self, mock, is_del): + if is_del: + vtysh_cmd = self.vtysh_cmd if self.vtysh_neg_cmd is None else self.vtysh_neg_cmd + else: + vtysh_cmd = self.vtysh_cmd + if callable(vtysh_cmd): + cmds = [] + for call in mock.call_args_list: + assert(call[0][0] == self.table_name) + cmds.append(call[0][1]) + vtysh_cmd(is_del, cmds, self.chk_data) + else: + if self.ignore_tail is None: + mock.assert_called_with(self.table_name, self.compose_vtysh_cmd(vtysh_cmd, is_del), + True, self.daemons) + else: + mock.assert_called_with(self.table_name, self.compose_vtysh_cmd(vtysh_cmd, is_del), + True, self.daemons, self.ignore_tail) + +def hdl_confed_peers_cmd(is_del, cmd_list, chk_data): + assert(len(chk_data) >= len(cmd_list)) + if is_del: + chk_data = list(reversed(chk_data)) + for idx, cmd in enumerate(cmd_list): + last_cmd = re.findall(r"-c\s+'([^']+)'\s*", cmd)[-1] + neg_cmd = False + if last_cmd.startswith('no '): + neg_cmd = True + last_cmd = last_cmd[len('no '):] + assert(last_cmd.startswith('bgp confederation peers ')) + peer_set = set(last_cmd[len('bgp confederation peers '):].split()) + if is_del or (len(chk_data) >= 3 and idx == 0): + assert(neg_cmd) + else: + assert(not neg_cmd) + assert(peer_set == chk_data[idx]) + +conf_cmd = 'configure terminal' +conf_bgp_cmd = lambda vrf, asn: [conf_cmd, 'router bgp %d vrf %s' % (asn, vrf)] +conf_no_bgp_cmd = lambda vrf, asn: [conf_cmd, 'no router bgp %d%s' % (asn, '' if vrf == 'default' else ' vrf %s' % vrf)] +conf_bgp_dft_cmd = lambda vrf, asn: conf_bgp_cmd(vrf, asn) + ['no bgp default ipv4-unicast'] +conf_bgp_af_cmd = lambda vrf, asn, af: conf_bgp_cmd(vrf, asn) + ['address-family %s unicast' % af] + +bgp_globals_data = [ + CmdMapTestInfo('BGP_GLOBALS', 'default', {'local_asn': 100}, + conf_bgp_dft_cmd('default', 100), False, conf_no_bgp_cmd('default', 100), None, None, None), + CmdMapTestInfo('BGP_GLOBALS', 'default', {'router_id': '1.1.1.1'}, + conf_bgp_cmd('default', 100) + ['{}bgp router-id 1.1.1.1']), + CmdMapTestInfo('BGP_GLOBALS', 'default', {'load_balance_mp_relax': 'true'}, + conf_bgp_cmd('default', 100) + ['{}bgp bestpath as-path multipath-relax ']), + CmdMapTestInfo('BGP_GLOBALS', 'default', {'as_path_mp_as_set': 'true'}, + conf_bgp_cmd('default', 100) + ['bgp bestpath as-path multipath-relax as-set'], False, + conf_bgp_cmd('default', 100) + ['bgp bestpath as-path multipath-relax ']), + CmdMapTestInfo('BGP_GLOBALS', 'default', {'always_compare_med': 'false'}, + conf_bgp_cmd('default', 100) + ['no bgp always-compare-med']), + CmdMapTestInfo('BGP_GLOBALS', 'default', {'external_compare_router_id': 'true'}, + conf_bgp_cmd('default', 100) + ['{}bgp bestpath compare-routerid']), + CmdMapTestInfo('BGP_GLOBALS', 'default', {'ignore_as_path_length': 'true'}, + conf_bgp_cmd('default', 100) + ['{}bgp bestpath as-path ignore']), + CmdMapTestInfo('BGP_GLOBALS', 'default', {'graceful_restart_enable': 'true'}, + conf_bgp_cmd('default', 100) + ['{}bgp graceful-restart']), + CmdMapTestInfo('BGP_GLOBALS', 'default', {'gr_restart_time': '10'}, + conf_bgp_cmd('default', 100) + ['{}bgp graceful-restart restart-time 10']), + CmdMapTestInfo('BGP_GLOBALS', 'default', {'gr_stale_routes_time': '20'}, + conf_bgp_cmd('default', 100) + ['{}bgp graceful-restart stalepath-time 20']), + CmdMapTestInfo('BGP_GLOBALS', 'default', {'gr_preserve_fw_state': 'true'}, + conf_bgp_cmd('default', 100) + ['{}bgp graceful-restart preserve-fw-state']), + CmdMapTestInfo('BGP_GLOBALS_AF', 'default|ipv4_unicast', {'ebgp_route_distance': '100', + 'ibgp_route_distance': '115', + 'local_route_distance': '238'}, + conf_bgp_af_cmd('default', 100, 'ipv4') + ['{}distance bgp 100 115 238']), + CmdMapTestInfo('BGP_GLOBALS_AF', 'default|ipv6_unicast', {'advertise-all-vni': 'true'}, + conf_bgp_af_cmd('default', 100, 'ipv6') + ['{}advertise-all-vni']), + CmdMapTestInfo('BGP_GLOBALS', 'Vrf_red', {'local_asn': 200}, + conf_bgp_dft_cmd('Vrf_red', 200), False, conf_no_bgp_cmd('Vrf_red', 200), None, None, None), + CmdMapTestInfo('BGP_GLOBALS', 'Vrf_red', {'med_confed': 'true'}, + conf_bgp_cmd('Vrf_red', 200) + ['{}bgp bestpath med confed']), + CmdMapTestInfo('BGP_GLOBALS', 'Vrf_red', {'confed_peers': ['2', '10', '5']}, + hdl_confed_peers_cmd, True, None, [{'2', '10', '5'}]), + CmdMapTestInfo('BGP_GLOBALS', 'Vrf_red', {'confed_peers': ['10', '8']}, + hdl_confed_peers_cmd, False, None, [{'2', '5'}, {'8'}, {'10', '8'}]), + CmdMapTestInfo('BGP_GLOBALS', 'Vrf_red', {'keepalive': '300', 'holdtime': '900'}, + conf_bgp_cmd('Vrf_red', 200) + ['{}timers bgp 300 900']), + CmdMapTestInfo('BGP_GLOBALS', 'Vrf_red', {'max_med_admin': 'true', 'max_med_admin_val': '20'}, + conf_bgp_cmd('Vrf_red', 200) + ['{}bgp max-med administrative 20']), + CmdMapTestInfo('BGP_GLOBALS_AF', 'Vrf_red|ipv4_unicast', {'import_vrf': 'Vrf_test'}, + conf_bgp_af_cmd('Vrf_red', 200, 'ipv4') + ['{}import vrf Vrf_test']), + CmdMapTestInfo('BGP_GLOBALS_AF', 'Vrf_red|ipv6_unicast', {'import_vrf_route_map': 'test_map'}, + conf_bgp_af_cmd('Vrf_red', 200, 'ipv6') + ['{}import vrf route-map test_map']), +] + +@patch.dict('sys.modules', swsssdk = swsssdk_module_mock) +@patch('frrcfgd.frrcfgd.g_run_command') +def data_set_del_test(test_data, run_cmd): + from frrcfgd.frrcfgd import BGPConfigDaemon + daemon = BGPConfigDaemon() + data_buf = {} + # add data in list + for test in test_data: + run_cmd.reset_mock() + hdlr = [h for t, h in daemon.table_handler_list if t == test.table_name] + assert(len(hdlr) == 1) + CmdMapTestInfo.add_test_data(test) + hdlr[0](test.table_name, test.key, CmdMapTestInfo.get_test_data(test)) + test.check_running_cmd(run_cmd, False) + # delete data in reverse direction + for test in reversed(test_data): + if test.no_del: + continue + run_cmd.reset_mock() + hdlr = [h for t, h in daemon.table_handler_list if t == test.table_name] + assert(len(hdlr) == 1) + CmdMapTestInfo.del_test_data(test) + hdlr[0](test.table_name, test.key, CmdMapTestInfo.get_test_data(test)) + test.check_running_cmd(run_cmd, True) + +def test_bgp_globals(): + data_set_del_test(bgp_globals_data) diff --git a/src/sonic-frr-mgmt-framework/tests/test_constructor.py b/src/sonic-frr-mgmt-framework/tests/test_constructor.py new file mode 100644 index 00000000000..14faa36d2e6 --- /dev/null +++ b/src/sonic-frr-mgmt-framework/tests/test_constructor.py @@ -0,0 +1,234 @@ +import socket +import pytest +from unittest.mock import MagicMock, NonCallableMagicMock, patch + +swsssdk_module_mock = MagicMock(ConfigDBConnector = NonCallableMagicMock) + +with patch.dict('sys.modules', swsssdk = swsssdk_module_mock): + from frrcfgd.frrcfgd import CachedDataWithOp + from frrcfgd.frrcfgd import BGPPeerGroup + from frrcfgd.frrcfgd import BGPKeyMapInfo + from frrcfgd.frrcfgd import BGPKeyMapList + from frrcfgd.frrcfgd import get_command_cmn + from frrcfgd.frrcfgd import CommunityList + from frrcfgd.frrcfgd import MatchPrefix + from frrcfgd.frrcfgd import MatchPrefixList + from frrcfgd.frrcfgd import AggregateAddr + from frrcfgd.frrcfgd import IpNextHop + from frrcfgd.frrcfgd import IpNextHopSet + +def test_data_with_op(): + data = CachedDataWithOp() + assert(data.data is None) + assert(data.op == CachedDataWithOp.OP_NONE) + data = CachedDataWithOp(10, CachedDataWithOp.OP_ADD) + assert(data.data == 10) + assert(data.op == CachedDataWithOp.OP_ADD) + +def test_peer_group(): + pg = BGPPeerGroup('Vrf_red') + assert(pg.vrf == 'Vrf_red') + assert(len(pg.ref_nbrs) == 0) + +def test_command_map(): + def cmd_hdlr(): + pass + key_map1 = BGPKeyMapInfo('test command', cmd_hdlr, None) + assert(key_map1.daemons is None) + assert(key_map1.run_cmd == 'test command') + assert(key_map1.hdl_func == cmd_hdlr) + assert(key_map1.data is None) + key_map2 = BGPKeyMapInfo('[bgpd,ospfd]daemon command', None, 100) + assert(key_map2.daemons == ['bgpd', 'ospfd']) + assert(key_map2.run_cmd == 'daemon command') + assert(key_map2.hdl_func == get_command_cmn) + assert(key_map2.data == 100) + +def get_cmd_map_list(attr_list, map_key = None): + map_list = [] + for attr in attr_list: + tokens = attr[0].split('|', 1) + if len(tokens) == 2: + key = tokens[1] + else: + key = None + if map_key is not None and key is not None and map_key != key: + continue + cmd_hdlr = cmd_data = None + if len(attr) >= 4: + cmd_hdlr = attr[2] + cmd_data = attr[3] + elif len(attr) == 3: + cmd_data = attr[2] + map_list.append(BGPKeyMapInfo(attr[1], cmd_hdlr, cmd_data)) + return map_list + +def test_command_map_list(): + def cmd_hdlr(num): + pass + map_list = [('abc', 'set attribute abc'), + ('defg', 'system config', cmd_hdlr, 10), + ('test', 'system test', [20, 30]), + ('xyz', 'config test'), + ('ip_cmd|ipv4', 'test on ipv4'), + ('ip_cmd|ipv6', 'test on ipv6')] + cmd_map_list = BGPKeyMapList(map_list, 'frrcfg', {'ip_cmd': 'ipv4'}) + chk_map_list = get_cmd_map_list(map_list, 'ipv4') + for idx, cmd_map in enumerate(cmd_map_list): + assert(chk_map_list[idx] == cmd_map[1]) + cmd_map_list = BGPKeyMapList(map_list, 'frrcfg', {'ip_cmd': 'ipv6'}) + chk_map_list = get_cmd_map_list(map_list, 'ipv6') + for idx, cmd_map in enumerate(cmd_map_list): + assert(chk_map_list[idx] == cmd_map[1]) + +def test_community_list(): + for ext in [False, True]: + comm_list = CommunityList('comm', ext) + assert(comm_list.name == 'comm') + assert(comm_list.is_ext == ext) + assert(comm_list.match_action is None) + assert(comm_list.is_std is None) + assert(len(comm_list.mbr_list) == 0) + +def test_match_prefix(): + pfx = MatchPrefix(socket.AF_INET, '1.2.3.4/16') + assert(pfx.ip_prefix == '1.2.0.0/16') + assert(pfx.min_len is None) + assert(pfx.max_len is None) + assert(pfx.action == 'permit') + pfx = MatchPrefix(socket.AF_INET, '10.10.10.10/24', '25..29', 'deny') + assert(pfx.ip_prefix == '10.10.10.0/24') + assert(pfx.min_len == 25) + assert(pfx.max_len == 29) + assert(pfx.action == 'deny') + pfx = MatchPrefix(socket.AF_INET, '100.0.0.0/8', '16..32') + assert(pfx.ip_prefix == '100.0.0.0/8') + assert(pfx.min_len == 16) + assert(pfx.max_len is None) + assert(pfx.action == 'permit') + pfx = MatchPrefix(socket.AF_INET, '20.20.20.20/28', '25..30', 'deny') + assert(pfx.ip_prefix == '20.20.20.16/28') + assert(pfx.min_len is None) + assert(pfx.max_len == 30) + assert(pfx.action == 'deny') + + pfx = MatchPrefix(socket.AF_INET6, '1:2::3:4/64') + assert(pfx.ip_prefix == '1:2::/64') + assert(pfx.min_len is None) + assert(pfx.max_len is None) + assert(pfx.action == 'permit') + pfx = MatchPrefix(socket.AF_INET6, '10:10::10:10/64', '70..100', 'deny') + assert(pfx.ip_prefix == '10:10::/64') + assert(pfx.min_len == 70) + assert(pfx.max_len == 100) + assert(pfx.action == 'deny') + pfx = MatchPrefix(socket.AF_INET6, '1001::/16', '16..128') + assert(pfx.ip_prefix == '1001::/16') + assert(pfx.min_len is None) + assert(pfx.max_len == 128) + assert(pfx.action == 'permit') + +def test_match_prefix_list(): + ipv4_pfx_attrs = [('10.1.1.1/16', '18..24', 'permit'), + ('20.2.2.2/24', None, 'deny'), + ('30.3.3.3/8', '10..32', 'permit'), + ('40.4.4.4/28', '20..30', 'deny')] + ipv6_pfx_attrs = [('1000:1::1/64', '80..120', 'permit'), + ('2000:2::2/96', None, 'deny'), + ('3000:3::3/32', '40..128', 'permit'), + ('4000:4::4/80', '60..100', 'deny')] + + pfx_list = MatchPrefixList() + for attr in ipv4_pfx_attrs: + pfx_list.add_prefix(*attr) + assert(pfx_list.af == socket.AF_INET) + assert(len(pfx_list) == len(ipv4_pfx_attrs)) + chk_pfx_list = [] + for attr in ipv4_pfx_attrs: + chk_pfx_list.append(MatchPrefix(socket.AF_INET, *attr)) + assert(all([x == y for x, y in zip(chk_pfx_list, pfx_list)])) + + pfx_list = MatchPrefixList() + for attr in ipv6_pfx_attrs: + pfx_list.add_prefix(*attr) + assert(pfx_list.af == socket.AF_INET6) + assert(len(pfx_list) == len(ipv6_pfx_attrs)) + chk_pfx_list = [] + for attr in ipv6_pfx_attrs: + chk_pfx_list.append(MatchPrefix(socket.AF_INET6, *attr)) + assert(all([x == y for x, y in zip(chk_pfx_list, pfx_list)])) + +def test_match_prefix_list_fail(): + pfx_list = MatchPrefixList() + pfx_list.add_prefix('1.2.3.0/24') + with pytest.raises(ValueError): + pfx_list.add_prefix('1::/64') + +def test_aggregate_address(): + addr = AggregateAddr() + assert(addr.as_set == False) + assert(addr.summary_only == False) + +def test_ip_nexthop(): + for af in [socket.AF_INET, socket.AF_INET6]: + nh = IpNextHop(af, None, None, None, 'Loopback0', None, None, None) + assert(nh.af == af) + assert(nh.blackhole == 'false') + assert(nh.ip == ('0.0.0.0' if af == socket.AF_INET else '::')) + assert(nh.track == 0) + assert(nh.interface == 'Loopback0') + assert(nh.tag == 0) + assert(nh.distance == 0) + assert(nh.nh_vrf == '') + arg_list = nh.get_arg_list() + assert(arg_list == ['false', '', 'Loopback0'] + [''] * 4) + nh = IpNextHop(af, 'true', '1.1.1.1' if af == socket.AF_INET else '1::1', + 1, 'Ethernet0', 100, 2, 'default') + assert(nh.blackhole == 'true') + assert(nh.ip == ('0.0.0.0' if af == socket.AF_INET else '::')) + assert(nh.track == 1) + assert(nh.interface == '') + assert(nh.tag == 100) + assert(nh.distance == 2) + assert(nh.nh_vrf == '') + arg_list = nh.get_arg_list() + assert(arg_list == ['true', '', '', '1', '100', '2', '']) + nh = IpNextHop(socket.AF_INET, 'false', '1.2.3.4', 5, 'Ethernet1', 2345, 3, 'Vrf_red') + assert(nh.af == socket.AF_INET) + assert(nh.blackhole == 'false') + assert(nh.ip == '1.2.3.4') + assert(nh.track == 5) + assert(nh.interface == 'Ethernet1') + assert(nh.tag == 2345) + assert(nh.distance == 3) + assert(nh.nh_vrf == 'Vrf_red') + arg_list = nh.get_arg_list() + assert(arg_list == ['false', '1.2.3.4', 'Ethernet1', '5', '2345', '3', 'Vrf_red']) + nh = IpNextHop(socket.AF_INET6, 'false', '1001:1::2002', 6, 'Ethernet2', 9000, 4, 'Vrf_blue') + assert(nh.af == socket.AF_INET6) + assert(nh.blackhole == 'false') + assert(nh.ip == '1001:1::2002') + assert(nh.track == 6) + assert(nh.interface == 'Ethernet2') + assert(nh.tag == 9000) + assert(nh.distance == 4) + assert(nh.nh_vrf == 'Vrf_blue') + arg_list = nh.get_arg_list() + assert(arg_list == ['false', '1001:1::2002', 'Ethernet2', '6', '9000', '4', 'Vrf_blue']) + +def test_nexthop_set(): + for af in [socket.AF_INET, socket.AF_INET6]: + nh_set = IpNextHopSet(af) + bkh_list = ['false', 'false', 'false', 'true'] + ip_list = ['1.1.1.1', '2.2.2.2', '3.3.3.3', None] + ip6_list = ['1::1', '2::2', '3::3', None] + intf_list = [None, 'Vlan0', 'Loopback1', None] + tag_list = [1000, 2000, 3000, 4000] + vrf_list = ['default', 'Vrf_red', 'Vrf_blue', None] + nh_set = IpNextHopSet(af, bkh_list, ip_list if af == socket.AF_INET else ip6_list, None, + intf_list, tag_list, None, vrf_list) + test_set = set() + for idx in range(len(ip_list)): + test_set.add(IpNextHop(af, bkh_list[idx], ip_list[idx] if af == socket.AF_INET else ip6_list[idx], + None, intf_list[idx], tag_list[idx], None, vrf_list[idx])) + assert(nh_set == test_set) diff --git a/src/sonic-frr/frr b/src/sonic-frr/frr index 4ed6312d10d..6b2b5cce355 160000 --- a/src/sonic-frr/frr +++ b/src/sonic-frr/frr @@ -1 +1 @@ -Subproject commit 4ed6312d10d369f621f69202ad39cfa6a597c59c +Subproject commit 6b2b5cce3557a383942fc194257da77e4e5270e4 diff --git a/src/sonic-frr/patch/0008-Add-support-of-bgp-l3vni-evpn.patch b/src/sonic-frr/patch/0008-Add-support-of-bgp-l3vni-evpn.patch new file mode 100644 index 00000000000..8a32e77a825 --- /dev/null +++ b/src/sonic-frr/patch/0008-Add-support-of-bgp-l3vni-evpn.patch @@ -0,0 +1,162 @@ +From 2e9ed539d29f13d874c6a5ab3120bf4bb26ab2bb Mon Sep 17 00:00:00 2001 +From: Kishore Kunal +Date: Fri, 15 Jan 2021 15:52:13 -0800 +Subject: [PATCH] This is temp patch till Prefix to ARP indirection is add in neighorch + +--- + lib/nexthop.c | 1 + + lib/nexthop.h | 7 ++++++- + zebra/rt_netlink.c | 2 +- + zebra/zapi_msg.c | 2 ++ + zebra/zebra_dplane.c | 2 +- + zebra/zebra_fpm_netlink.c | 19 +++++++++++++++++++ + 6 files changed, 30 insertions(+), 3 deletions(-) + +diff --git a/lib/nexthop.c b/lib/nexthop.c +index 0ea72d03e..02e826048 100644 +--- a/lib/nexthop.c ++++ b/lib/nexthop.c +@@ -657,6 +657,7 @@ void nexthop_copy_no_recurse(struct nexthop *copy, + nexthop_add_labels(copy, nexthop->nh_label_type, + nexthop->nh_label->num_labels, + &nexthop->nh_label->label[0]); ++ memcpy(©->nh_encap.encap_data.rmac, &nexthop->nh_encap.encap_data.rmac, ETH_ALEN); + } + + void nexthop_copy(struct nexthop *copy, const struct nexthop *nexthop, +diff --git a/lib/nexthop.h b/lib/nexthop.h +index cadcea1f4..fd959eb9e 100644 +--- a/lib/nexthop.h ++++ b/lib/nexthop.h +@@ -71,6 +71,11 @@ enum nh_encap_type { + /* Backup index value is limited */ + #define NEXTHOP_BACKUP_IDX_MAX 255 + ++struct vxlan_nh_encap { ++ vni_t vni; ++ struct ethaddr rmac; ++}; ++ + /* Nexthop structure. */ + struct nexthop { + struct nexthop *next; +@@ -140,7 +145,7 @@ struct nexthop { + /* Encapsulation information. */ + enum nh_encap_type nh_encap_type; + union { +- vni_t vni; ++ struct vxlan_nh_encap encap_data; + } nh_encap; + + /* SR-TE color used for matching SR-TE policies */ +diff --git a/zebra/rt_netlink.c b/zebra/rt_netlink.c +index 50b1a62d8..d8249f8e0 100644 +--- a/zebra/rt_netlink.c ++++ b/zebra/rt_netlink.c +@@ -1590,7 +1590,7 @@ static int netlink_route_nexthop_encap(struct nlmsghdr *n, size_t nlen, + return false; + + if (!nl_attr_put32(n, nlen, 0 /* VXLAN_VNI */, +- nh->nh_encap.vni)) ++ nh->nh_encap.encap_data.vni)) + return false; + nl_attr_nest_end(n, nest); + break; +diff --git a/zebra/zapi_msg.c b/zebra/zapi_msg.c +index e436e5a28..c10d50797 100644 +--- a/zebra/zapi_msg.c ++++ b/zebra/zapi_msg.c +@@ -1477,6 +1477,7 @@ static struct nexthop *nexthop_from_zapi(struct route_entry *re, + zebra_vxlan_evpn_vrf_route_add( + api_nh->vrf_id, &api_nh->rmac, + &vtep_ip, &api->prefix); ++ memcpy(&(nexthop->nh_encap.encap_data.rmac), &api_nh->rmac, ETH_ALEN); + } + break; + case NEXTHOP_TYPE_IPV6: +@@ -1511,6 +1512,7 @@ static struct nexthop *nexthop_from_zapi(struct route_entry *re, + zebra_vxlan_evpn_vrf_route_add( + api_nh->vrf_id, &api_nh->rmac, + &vtep_ip, &api->prefix); ++ memcpy(&(nexthop->nh_encap.encap_data.rmac), &api_nh->rmac, ETH_ALEN); + } + break; + case NEXTHOP_TYPE_BLACKHOLE: +diff --git a/zebra/zebra_dplane.c b/zebra/zebra_dplane.c +index abd0adb64..e66d7aae5 100644 +--- a/zebra/zebra_dplane.c ++++ b/zebra/zebra_dplane.c +@@ -1891,7 +1891,7 @@ int dplane_ctx_route_init(struct zebra_dplane_ctx *ctx, enum dplane_op_e op, + zl3vni = zl3vni_from_vrf(nexthop->vrf_id); + if (zl3vni && is_l3vni_oper_up(zl3vni)) { + nexthop->nh_encap_type = NET_VXLAN; +- nexthop->nh_encap.vni = zl3vni->vni; ++ nexthop->nh_encap.encap_data.vni = zl3vni->vni; + } + } + +diff --git a/zebra/zebra_fpm_netlink.c b/zebra/zebra_fpm_netlink.c +index 2c0741363..2731f64fb 100644 +--- a/zebra/zebra_fpm_netlink.c ++++ b/zebra/zebra_fpm_netlink.c +@@ -129,10 +129,12 @@ static const char *fpm_nh_encap_type_to_str(enum fpm_nh_encap_type_t encap_type) + + struct vxlan_encap_info_t { + vni_t vni; ++ struct ethaddr rmac; + }; + + enum vxlan_encap_info_type_t { + VXLAN_VNI = 0, ++ VXLAN_RMAC = 1, + }; + + struct fpm_nh_encap_info_t { +@@ -238,6 +240,8 @@ static int netlink_route_info_add_nh(struct netlink_route_info *ri, + + /* Add VNI to VxLAN encap info */ + nhi.encap_info.vxlan_encap.vni = zl3vni->vni; ++ memcpy(&nhi.encap_info.vxlan_encap.rmac, &(nexthop->nh_encap.encap_data.rmac), ++ ETH_ALEN); + } + } + +@@ -454,9 +458,16 @@ static int netlink_route_info_encode(struct netlink_route_info *ri, + nl_attr_put16(&req->n, in_buf_len, RTA_ENCAP_TYPE, + encap); + vxlan = &nhi->encap_info.vxlan_encap; ++ char buf[ETHER_ADDR_STRLEN]; ++ ++ zfpm_debug( ++ "%s: VNI:%d RMAC:%s", __func__, vxlan->vni, ++ prefix_mac2str(&vxlan->rmac, buf, sizeof(buf))); + nest = nl_attr_nest(&req->n, in_buf_len, RTA_ENCAP); + nl_attr_put32(&req->n, in_buf_len, VXLAN_VNI, + vxlan->vni); ++ nl_attr_put(&req->n, in_buf_len, VXLAN_RMAC, ++ &vxlan->rmac, sizeof(vxlan->rmac)); + nl_attr_nest_end(&req->n, nest); + break; + } +@@ -490,10 +501,18 @@ static int netlink_route_info_encode(struct netlink_route_info *ri, + nl_attr_put16(&req->n, in_buf_len, RTA_ENCAP_TYPE, + encap); + vxlan = &nhi->encap_info.vxlan_encap; ++ char rmac_buf[ETHER_ADDR_STRLEN]; ++ ++ zfpm_debug("%s: Multi VNI:%d RMAC:%s", __func__, ++ vxlan->vni, ++ prefix_mac2str(&vxlan->rmac, rmac_buf, ++ sizeof(rmac_buf))); + inner_nest = + nl_attr_nest(&req->n, in_buf_len, RTA_ENCAP); + nl_attr_put32(&req->n, in_buf_len, VXLAN_VNI, + vxlan->vni); ++ nl_attr_put(&req->n, in_buf_len, VXLAN_RMAC, ++ &vxlan->rmac, sizeof(vxlan->rmac)); + nl_attr_nest_end(&req->n, inner_nest); + break; + } +-- +2.18.0 + diff --git a/src/sonic-frr/patch/series b/src/sonic-frr/patch/series index d7c209e9b47..69dd5991a7c 100644 --- a/src/sonic-frr/patch/series +++ b/src/sonic-frr/patch/series @@ -4,4 +4,4 @@ 0004-Allow-BGP-attr-NEXT_HOP-to-be-0.0.0.0-due-to-allevia.patch 0005-nexthops-compare-vrf-only-if-ip-type.patch 0007-frr-remove-frr-log-outchannel-to-var-log-frr.log.patch - +0008-Add-support-of-bgp-l3vni-evpn.patch diff --git a/src/sonic-host-service/Makefile b/src/sonic-host-service/Makefile deleted file mode 100644 index c492c1f583a..00000000000 --- a/src/sonic-host-service/Makefile +++ /dev/null @@ -1,41 +0,0 @@ -################################################################################ -# # -# Copyright 2020 Dell Inc. # -# # -# Licensed under the Apache License, Version 2.0 (the "License"); # -# you may not use this file except in compliance with the License. # -# You may obtain a copy of the License at # -# # -# http://www.apache.org/licenses/LICENSE-2.0 # -# # -# Unless required by applicable law or agreed to in writing, software # -# distributed under the License is distributed on an "AS IS" BASIS, # -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # -# See the License for the specific language governing permissions and # -# limitations under the License. # -# # -################################################################################ - -TOPDIR := $(abspath .) -MAIN_TARGET = sonic-host-service_1.0.0_all.deb -INSTALL := /usr/bin/install - -$(addprefix $(DEST)/, $(MAIN_TARGET)): $(DEST)/% : - dpkg-buildpackage -us -uc -b -j$(SONIC_CONFIG_MAKE_JOBS) --admindir $(SONIC_DPKG_ADMINDIR) - mv ../$(MAIN_TARGET) $(DEST)/ - -SOURCES := $(wildcard '*.*') $(wildcard 'host_modules/*.py') -install: $(SOURCES) - # Scripts for host service - $(INSTALL) -d $(DESTDIR)/usr/lib/sonic_host_service/host_modules - $(INSTALL) -D $(TOPDIR)/sonic_host_server.py $(DESTDIR)/usr/lib/sonic_host_service - $(INSTALL) -D $(TOPDIR)/host_modules/*.py $(DESTDIR)/usr/lib/sonic_host_service/host_modules - - # D-Bus permissions configuration - $(INSTALL) -d $(DESTDIR)/etc/dbus-1/system.d - $(INSTALL) -D $(TOPDIR)/org.sonic.hostservice.conf $(DESTDIR)/etc/dbus-1/system.d - - # systemd unit - $(INSTALL) -d $(DESTDIR)/lib/systemd/system - $(INSTALL) -D $(TOPDIR)/sonic-hostservice.service $(DESTDIR)/lib/systemd/system - diff --git a/src/sonic-host-service/debian/.gitignore b/src/sonic-host-service/debian/.gitignore deleted file mode 100644 index 9a07690ac27..00000000000 --- a/src/sonic-host-service/debian/.gitignore +++ /dev/null @@ -1,4 +0,0 @@ -.debhelper -sonic-host-service.* -sonic-host-service/ -files diff --git a/src/sonic-host-service/debian/changelog b/src/sonic-host-service/debian/changelog deleted file mode 100644 index 5c512fe009e..00000000000 --- a/src/sonic-host-service/debian/changelog +++ /dev/null @@ -1,5 +0,0 @@ -sonic-host-service (1.0.0) UNRELEASED; urgency=low - - * Initial release. - - -- Nirenjan Krishnan Mon, 22 Jun 2020 00:00:00 +0000 diff --git a/src/sonic-host-service/debian/compat b/src/sonic-host-service/debian/compat deleted file mode 100644 index ec635144f60..00000000000 --- a/src/sonic-host-service/debian/compat +++ /dev/null @@ -1 +0,0 @@ -9 diff --git a/src/sonic-host-service/debian/control b/src/sonic-host-service/debian/control deleted file mode 100644 index 57d126af60d..00000000000 --- a/src/sonic-host-service/debian/control +++ /dev/null @@ -1,15 +0,0 @@ -Source: sonic-host-service -Maintainer: Nirenjan Krishnan -Build-Depends: debhelper (>= 8.0.0), - dh-systemd -Vcs-Git: https://github.com/Azure/sonic-buildimage -Homepage: https://github.com/Azure/SONiC/ -Standards-Version: 3.9.3 -Section: net - -Package: sonic-host-service -Priority: extra -Architecture: all -Depends: python3-systemd, python3-dbus, python3-gi, ${misc:Depends} -Description: SONiC Host Service - diff --git a/src/sonic-host-service/debian/rules b/src/sonic-host-service/debian/rules deleted file mode 100755 index eaed7a19038..00000000000 --- a/src/sonic-host-service/debian/rules +++ /dev/null @@ -1,9 +0,0 @@ -#!/usr/bin/make -f -%: - dh $@ --with systemd --parallel - -override_dh_auto_clean: -override_dh_auto_test: -override_dh_auto_build: -override_dh_auto_install: - make install DESTDIR=debian/sonic-host-service diff --git a/src/sonic-host-services-data/debian/install b/src/sonic-host-services-data/debian/install index 839eb8d0e12..91edbd1c040 100644 --- a/src/sonic-host-services-data/debian/install +++ b/src/sonic-host-services-data/debian/install @@ -1 +1,2 @@ templates/*.j2 /usr/share/sonic/templates/ +org.sonic.hostservice.conf /etc/dbus-1/system.d diff --git a/src/sonic-host-services-data/debian/rules b/src/sonic-host-services-data/debian/rules index be44a123270..02be0c9093d 100755 --- a/src/sonic-host-services-data/debian/rules +++ b/src/sonic-host-services-data/debian/rules @@ -1,5 +1,12 @@ #!/usr/bin/make -f +ifeq (${ENABLE_HOST_SERVICE_ON_START}, y) + HOST_SERVICE_OPTS := --no-start +else + HOST_SERVICE_OPTS := --no-start --no-enable +endif + + build: %: @@ -11,4 +18,5 @@ override_dh_installsystemd: dh_installsystemd --no-start --name=procdockerstatsd dh_installsystemd --no-start --name=determine-reboot-cause dh_installsystemd --no-start --name=process-reboot-cause + dh_installsystemd $(HOST_SERVICE_OPTS) --name=sonic-hostservice diff --git a/src/sonic-host-service/sonic-hostservice.service b/src/sonic-host-services-data/debian/sonic-host-services-data.sonic-hostservice.service similarity index 69% rename from src/sonic-host-service/sonic-hostservice.service rename to src/sonic-host-services-data/debian/sonic-host-services-data.sonic-hostservice.service index 7717022285b..bf9ff1d41d3 100644 --- a/src/sonic-host-service/sonic-hostservice.service +++ b/src/sonic-host-services-data/debian/sonic-host-services-data.sonic-hostservice.service @@ -5,7 +5,7 @@ Description=SONiC Host Service Type=dbus BusName=org.SONiC.HostService -ExecStart=/usr/bin/python3 -u /usr/lib/sonic_host_service/sonic_host_server.py +ExecStart=/usr/bin/python3 -u /usr/local/bin/sonic-host-server Restart=on-failure RestartSec=10 diff --git a/src/sonic-host-service/org.sonic.hostservice.conf b/src/sonic-host-services-data/org.sonic.hostservice.conf similarity index 100% rename from src/sonic-host-service/org.sonic.hostservice.conf rename to src/sonic-host-services-data/org.sonic.hostservice.conf diff --git a/src/sonic-host-service/host_modules/host_service.py b/src/sonic-host-services/host_modules/host_service.py similarity index 100% rename from src/sonic-host-service/host_modules/host_service.py rename to src/sonic-host-services/host_modules/host_service.py diff --git a/src/sonic-host-services/pytest.ini b/src/sonic-host-services/pytest.ini new file mode 100644 index 00000000000..83b74d373c0 --- /dev/null +++ b/src/sonic-host-services/pytest.ini @@ -0,0 +1,2 @@ +[pytest] +addopts = --cov=scripts --cov-report html --cov-report term --cov-report xml diff --git a/src/sonic-host-services/scripts/process-reboot-cause b/src/sonic-host-services/scripts/process-reboot-cause old mode 100644 new mode 100755 diff --git a/src/sonic-host-service/sonic_host_server.py b/src/sonic-host-services/scripts/sonic-host-server similarity index 96% rename from src/sonic-host-service/sonic_host_server.py rename to src/sonic-host-services/scripts/sonic-host-server index 9232209f7dc..a9fdc2eb25f 100755 --- a/src/sonic-host-service/sonic_host_server.py +++ b/src/sonic-host-services/scripts/sonic-host-server @@ -15,7 +15,7 @@ def register_modules(): """Register all host modules""" - mod_path = os.path.join(os.path.dirname(__file__), 'host_modules') + mod_path = '/usr/local/lib/python3.7/dist-packages/host_modules' sys.path.append(mod_path) for mod_file in glob.glob(os.path.join(mod_path, '*.py')): if os.path.isfile(mod_file) and not mod_file.endswith('__init__.py'): diff --git a/src/sonic-host-services/setup.py b/src/sonic-host-services/setup.py index 2da0561b9c5..e5431d034d9 100644 --- a/src/sonic-host-services/setup.py +++ b/src/sonic-host-services/setup.py @@ -10,17 +10,24 @@ url = 'https://github.com/Azure/sonic-buildimage', maintainer = 'Joe LeVeque', maintainer_email = 'jolevequ@microsoft.com', + packages = [ + 'host_modules' + ], scripts = [ 'scripts/caclmgrd', 'scripts/hostcfgd', 'scripts/procdockerstatsd', 'scripts/determine-reboot-cause', 'scripts/process-reboot-cause', + 'scripts/sonic-host-server' ], install_requires = [ + 'dbus-python', 'Jinja2>=2.10', + 'PyGObject', 'sonic-py-common', 'swsssdk>=2.0.1', + 'systemd-python', ], setup_requires = [ 'pytest-runner', diff --git a/src/sonic-linux-kernel b/src/sonic-linux-kernel index 548e8e0be49..11f0da688d5 160000 --- a/src/sonic-linux-kernel +++ b/src/sonic-linux-kernel @@ -1 +1 @@ -Subproject commit 548e8e0be49692050ea4071d5e9945816bc5aacc +Subproject commit 11f0da688d5bd7e206c3e50fd408d0717e9626d1 diff --git a/src/sonic-platform-common b/src/sonic-platform-common index 8664efc5472..6ad0004c29a 160000 --- a/src/sonic-platform-common +++ b/src/sonic-platform-common @@ -1 +1 @@ -Subproject commit 8664efc5472ae8cab04ad5a3499baa9a9c0d7f89 +Subproject commit 6ad0004c29a143a0635ad7f3c81ce652313569cb diff --git a/src/sonic-platform-daemons b/src/sonic-platform-daemons index 81318f7afdb..e72f6cd9588 160000 --- a/src/sonic-platform-daemons +++ b/src/sonic-platform-daemons @@ -1 +1 @@ -Subproject commit 81318f7afdb65bd15af387c97152948d22cf9834 +Subproject commit e72f6cd958810e3af9b18a71bc078dbb8c5d6cac diff --git a/src/sonic-sairedis b/src/sonic-sairedis index e9401364da2..b39e74610ad 160000 --- a/src/sonic-sairedis +++ b/src/sonic-sairedis @@ -1 +1 @@ -Subproject commit e9401364da28259f065b2106fa8590423490f3ea +Subproject commit b39e74610ad7a842618a025fdadbdc52d530483a diff --git a/src/sonic-snmpagent b/src/sonic-snmpagent index dfde06e2f5d..3885f193be0 160000 --- a/src/sonic-snmpagent +++ b/src/sonic-snmpagent @@ -1 +1 @@ -Subproject commit dfde06e2f5d70e23882af6c0f1af4ae43ec2fa43 +Subproject commit 3885f193be05099659808092d22c5f69407cdda4 diff --git a/src/sonic-swss b/src/sonic-swss index 321291aa7ac..288fb40d8ff 160000 --- a/src/sonic-swss +++ b/src/sonic-swss @@ -1 +1 @@ -Subproject commit 321291aa7aca89a3ccef2bed36aff074eac1054f +Subproject commit 288fb40d8ff4ec825645c2fbab1e79f50881a9f2 diff --git a/src/sonic-swss-common b/src/sonic-swss-common index 2db7bea9963..9e91e0d8913 160000 --- a/src/sonic-swss-common +++ b/src/sonic-swss-common @@ -1 +1 @@ -Subproject commit 2db7bea9963a988a575b8075e1f6c5369d057230 +Subproject commit 9e91e0d891398b468b8087682ae91335791fac51 diff --git a/src/sonic-utilities b/src/sonic-utilities index 0a4365aaa0a..28d358fc82c 160000 --- a/src/sonic-utilities +++ b/src/sonic-utilities @@ -1 +1 @@ -Subproject commit 0a4365aaa0adadcb4c3fa448e05f6d2e217bda5f +Subproject commit 28d358fc82c228fdbfa9f1715a5024c49f98c9b4 diff --git a/src/sonic-yang-models/tests/yang_model_tests/test_yang_model.py b/src/sonic-yang-models/tests/yang_model_tests/test_yang_model.py index 4754cea88eb..adf643ad793 100644 --- a/src/sonic-yang-models/tests/yang_model_tests/test_yang_model.py +++ b/src/sonic-yang-models/tests/yang_model_tests/test_yang_model.py @@ -81,6 +81,10 @@ def initTest(self): 'desc': 'Configure undefined packet_action in ACL_RULE table.', 'eStr': self.defaultYANGFailure['InvalidValue'] + ['PACKET_ACTION'] }, + 'ACL_TABLE_EMPTY_PORTS': { + 'desc': 'Configure ACL_TABLE with empty ports.', + 'eStr': self.defaultYANGFailure['None'] + }, 'ACL_TABLE_UNDEFINED_TABLE_TYPE': { 'desc': 'Configure undefined acl_table_type in ACL_TABLE table.', 'eStr': self.defaultYANGFailure['InvalidValue'] + ['type'] @@ -210,6 +214,14 @@ def initTest(self): 'value': 'up' } }, + 'DEVICE_METADATA_DEFAULT_DOCKER_ROUTING_CONFIG_MODE': { + 'desc': 'DEVICE_METADATA DEFAULT VALUE FOR DOCKER_ROUTING_CONFIG_MODE FIELD.', + 'eStr': self.defaultYANGFailure['Verify'], + 'verify': {'xpath': '/sonic-device_metadata:sonic-device_metadata/DEVICE_METADATA/localhost/hostname', + 'key': 'sonic-device_metadata:docker_routing_config_mode', + 'value': 'unified' + } + }, 'DEVICE_METADATA_DEFAULT_PFCWD_STATUS': { 'desc': 'DEVICE_METADATA DEFAULT VALUE FOR PFCWD FIELD.', 'eStr': self.defaultYANGFailure['Verify'], diff --git a/src/sonic-yang-models/tests/yang_model_tests/yangTest.json b/src/sonic-yang-models/tests/yang_model_tests/yangTest.json index cb67febe48a..92c841830d6 100644 --- a/src/sonic-yang-models/tests/yang_model_tests/yangTest.json +++ b/src/sonic-yang-models/tests/yang_model_tests/yangTest.json @@ -242,6 +242,20 @@ } }, + "ACL_TABLE_EMPTY_PORTS": { + "sonic-acl:sonic-acl": { + "sonic-acl:ACL_TABLE": { + "ACL_TABLE_LIST": [{ + "ACL_TABLE_NAME": "NO-NSW-PACL-V4", + "policy_desc": "Filter IPv4", + "type": "L3", + "stage": "EGRESS", + "ports": [""] + }] + } + } + }, + "ACL_RULE_UNDEFINED_PACKET_ACTION": { "sonic-acl:sonic-acl": { "sonic-acl:ACL_RULE": { @@ -837,6 +851,19 @@ } }, + "DEVICE_METADATA_DEFAULT_DOCKER_ROUTING_CONFIG_MODE": { + "sonic-device_metadata:sonic-device_metadata": { + "sonic-device_metadata:DEVICE_METADATA": { + "sonic-device_metadata:localhost": { + "default_bgp_status": "up", + "platform": "Stone-DX010", + "hostname": "DUT-CSW", + "bgp_asn": "65001" + } + } + } + }, + "DEVICE_METADATA_DEFAULT_PFCWD_STATUS": { "sonic-device_metadata:sonic-device_metadata": { "sonic-device_metadata:DEVICE_METADATA": { diff --git a/src/system-health/health_checker/hardware_checker.py b/src/system-health/health_checker/hardware_checker.py index cf5b86bea2b..7bbc4bdaca0 100644 --- a/src/system-health/health_checker/hardware_checker.py +++ b/src/system-health/health_checker/hardware_checker.py @@ -89,11 +89,6 @@ def _check_fan_status(self, config): self.set_object_not_ok('Fan', name, '{} is missing'.format(name)) continue - status = data_dict.get('status', 'false') - if status.lower() != 'true': - self.set_object_not_ok('Fan', name, '{} is broken'.format(name)) - continue - if not self._ignore_check(config.ignore_devices, 'fan', name, 'speed'): speed = data_dict.get('speed', None) speed_target = data_dict.get('speed_target', None) @@ -130,6 +125,11 @@ def _check_fan_status(self, config): speed_tolerance)) continue + status = data_dict.get('status', 'false') + if status.lower() != 'true': + self.set_object_not_ok('Fan', name, '{} is broken'.format(name)) + continue + self.set_object_ok('Fan', name) def _check_psu_status(self, config): diff --git a/src/tacacs/nss/Makefile b/src/tacacs/nss/Makefile index 5fafd93b87f..0c8f25f44ea 100644 --- a/src/tacacs/nss/Makefile +++ b/src/tacacs/nss/Makefile @@ -4,27 +4,16 @@ SHELL = /bin/bash MAIN_TARGET = libnss-tacplus_$(NSS_TACPLUS_VERSION)_$(CONFIGURED_ARCH).deb -GIT_APPLY = am -ifneq (,$(filter $(CONFIGURED_ARCH), armhf arm64)) -# Workaround git am issue "Out of memory getdelim failed" -GIT_APPLY = apply -endif - $(addprefix $(DEST)/, $(MAIN_TARGET)): $(DEST)/% : # Obtain libnss-tacplus rm -rf ./libnss-tacplus git clone https://github.com/daveolson53/libnss-tacplus.git pushd ./libnss-tacplus - git checkout -f 19008ab + git checkout -b test -f 19008ab # Apply patch - git $(GIT_APPLY) ../0001-Modify-user-map-profile.patch - git $(GIT_APPLY) ../0002-Enable-modifying-local-user-permission.patch - git $(GIT_APPLY) ../0003-management-vrf-support.patch - git $(GIT_APPLY) ../0004-Skip-accessing-tacacs-servers-for-local-non-tacacs-u.patch - git $(GIT_APPLY) ../0005-libnss-Modify-parsing-of-IP-addr-and-port-number-str.patch - git $(GIT_APPLY) ../0006-fix-compiling-warning-about-token-dereference.patch - git $(GIT_APPLY) ../0007-Add-support-for-TACACS-source-address.patch + stg init + stg import -s ../patch/series dpkg-buildpackage -rfakeroot -b -us -uc -j$(SONIC_CONFIG_MAKE_JOBS) --admindir $(SONIC_DPKG_ADMINDIR) popd diff --git a/src/tacacs/nss/0001-Modify-user-map-profile.patch b/src/tacacs/nss/patch/0001-Modify-user-map-profile.patch similarity index 100% rename from src/tacacs/nss/0001-Modify-user-map-profile.patch rename to src/tacacs/nss/patch/0001-Modify-user-map-profile.patch diff --git a/src/tacacs/nss/0002-Enable-modifying-local-user-permission.patch b/src/tacacs/nss/patch/0002-Enable-modifying-local-user-permission.patch similarity index 100% rename from src/tacacs/nss/0002-Enable-modifying-local-user-permission.patch rename to src/tacacs/nss/patch/0002-Enable-modifying-local-user-permission.patch diff --git a/src/tacacs/nss/0003-management-vrf-support.patch b/src/tacacs/nss/patch/0003-management-vrf-support.patch similarity index 100% rename from src/tacacs/nss/0003-management-vrf-support.patch rename to src/tacacs/nss/patch/0003-management-vrf-support.patch diff --git a/src/tacacs/nss/0004-Skip-accessing-tacacs-servers-for-local-non-tacacs-u.patch b/src/tacacs/nss/patch/0004-Skip-accessing-tacacs-servers-for-local-non-tacacs-u.patch similarity index 100% rename from src/tacacs/nss/0004-Skip-accessing-tacacs-servers-for-local-non-tacacs-u.patch rename to src/tacacs/nss/patch/0004-Skip-accessing-tacacs-servers-for-local-non-tacacs-u.patch diff --git a/src/tacacs/nss/0005-libnss-Modify-parsing-of-IP-addr-and-port-number-str.patch b/src/tacacs/nss/patch/0005-libnss-Modify-parsing-of-IP-addr-and-port-number-str.patch similarity index 100% rename from src/tacacs/nss/0005-libnss-Modify-parsing-of-IP-addr-and-port-number-str.patch rename to src/tacacs/nss/patch/0005-libnss-Modify-parsing-of-IP-addr-and-port-number-str.patch diff --git a/src/tacacs/nss/0006-fix-compiling-warning-about-token-dereference.patch b/src/tacacs/nss/patch/0006-fix-compiling-warning-about-token-dereference.patch similarity index 100% rename from src/tacacs/nss/0006-fix-compiling-warning-about-token-dereference.patch rename to src/tacacs/nss/patch/0006-fix-compiling-warning-about-token-dereference.patch diff --git a/src/tacacs/nss/0007-Add-support-for-TACACS-source-address.patch b/src/tacacs/nss/patch/0007-Add-support-for-TACACS-source-address.patch similarity index 100% rename from src/tacacs/nss/0007-Add-support-for-TACACS-source-address.patch rename to src/tacacs/nss/patch/0007-Add-support-for-TACACS-source-address.patch diff --git a/src/tacacs/nss/patch/0008-do-not-create-or-modify-local-user-if-there-is-no-pr.patch b/src/tacacs/nss/patch/0008-do-not-create-or-modify-local-user-if-there-is-no-pr.patch new file mode 100644 index 00000000000..1ab4a423663 --- /dev/null +++ b/src/tacacs/nss/patch/0008-do-not-create-or-modify-local-user-if-there-is-no-pr.patch @@ -0,0 +1,32 @@ +From c59b775a7c9226954c5eea4ba05469879b41a60d Mon Sep 17 00:00:00 2001 +From: Guohan Lu +Date: Sat, 6 Feb 2021 06:49:17 +0000 +Subject: [PATCH] do not create or modify local user if there is no privilege + +--- + nss_tacplus.c | 9 +++++++-- + 1 file changed, 7 insertions(+), 2 deletions(-) + +diff --git a/nss_tacplus.c b/nss_tacplus.c +index fc9316f..cc6f0aa 100644 +--- a/nss_tacplus.c ++++ b/nss_tacplus.c +@@ -629,8 +629,13 @@ static int lookup_user_pw(struct pwbuf *pb, int level) + if(0 != ret) + return ret; + +- if(0 != create_or_modify_local_user(username, level, found)) +- return -1; ++ if(0 == getuid()) { ++ if(0 != create_or_modify_local_user(username, level, found)) ++ return -1; ++ } else { ++ if(debug) ++ syslog(LOG_DEBUG, "%d does not privilege to create or modify user %s", getuid(), username); ++ } + + ret = lookup_pw_local(username, pb, &found); + if(0 == ret && !found) { +-- +2.25.1 + diff --git a/src/tacacs/nss/patch/series b/src/tacacs/nss/patch/series new file mode 100644 index 00000000000..b60214ead9b --- /dev/null +++ b/src/tacacs/nss/patch/series @@ -0,0 +1,8 @@ +0001-Modify-user-map-profile.patch +0002-Enable-modifying-local-user-permission.patch +0003-management-vrf-support.patch +0004-Skip-accessing-tacacs-servers-for-local-non-tacacs-u.patch +0005-libnss-Modify-parsing-of-IP-addr-and-port-number-str.patch +0006-fix-compiling-warning-about-token-dereference.patch +0007-Add-support-for-TACACS-source-address.patch +0008-do-not-create-or-modify-local-user-if-there-is-no-pr.patch diff --git a/src/wpasupplicant/sonic-wpa-supplicant b/src/wpasupplicant/sonic-wpa-supplicant index 288cca1bf02..3b330db4a33 160000 --- a/src/wpasupplicant/sonic-wpa-supplicant +++ b/src/wpasupplicant/sonic-wpa-supplicant @@ -1 +1 @@ -Subproject commit 288cca1bf02679313aec1bc7ba168ced9026a003 +Subproject commit 3b330db4a331d591cea5a1f3e820435181625793