[broadom]: Upgrade broadcom SAI to 3.7.3.2

[Broadcom] : update saibcm-modules to sdk 6.5.16
[Broadcom SAI] : upgrade Broadcom SAI to 3.7.3.2
This commit is contained in:
Judy Joseph 2019-12-19 06:26:34 +00:00 committed by Guohan Lu
parent 4458efbd71
commit 9c4c36e1b5
39 changed files with 3561 additions and 1968 deletions

View File

@ -1,3 +1,4 @@
{% from "dockers/dockerfile-macros.j2" import install_debian_packages %}
FROM docker-config-engine-stretch
ARG docker_container_name
@ -14,10 +15,8 @@ debs/{{ deb }}{{' '}}
{%- endfor -%}
debs/
RUN dpkg -i \
{% for deb in docker_syncd_brcm_debs.split(' ') -%}
debs/{{ deb }}{{' '}}
{%- endfor %}
# Install locally-built Debian packages and implicitly install their dependencies
{{ install_debian_packages(docker_syncd_brcm_debs.split(' ')) }}
## TODO: add kmod into Depends
RUN apt-get install -yf kmod

View File

@ -1,7 +1,7 @@
# Broadcom SAI modules
KVERSION = 4.9.0-9-2-amd64
BRCM_OPENNSL_KERNEL_VERSION = 3.4.1.11-1
BRCM_OPENNSL_KERNEL_VERSION = 3.7.3.3-1
BRCM_OPENNSL_KERNEL = opennsl-modules_$(BRCM_OPENNSL_KERNEL_VERSION)_amd64.deb
$(BRCM_OPENNSL_KERNEL)_SRC_PATH = $(PLATFORM_PATH)/saibcm-modules

View File

@ -1,9 +1,9 @@
BRCM_SAI = libsaibcm_3.5.3.1m-25_amd64.deb
$(BRCM_SAI)_URL = "https://sonicstorage.blob.core.windows.net/packages/bcmsai/3.5/libsaibcm_3.5.3.1m-26_amd64.deb?sv=2015-04-05&sr=b&sig=zo83IKnlT7goymXwynW8%2Fx6rR2eIh0AiIS%2BSrSMUhRE%3D&se=2033-07-21T18%3A50%3A27Z&sp=r"
BRCM_SAI = libsaibcm_3.7.3.3_amd64.deb
$(BRCM_SAI)_URL = "https://sonicstorage.blob.core.windows.net/packages/bcmsai/3.7/libsaibcm_3.7.3.3_amd64.deb?sv=2015-04-05&sr=b&sig=Y66VSRUEl4PDf5kHRo%2FS3DBBE9tONSyCzNJvi8IP9n8%3D&se=2033-08-25T01%3A22%3A08Z&sp=r"
BRCM_SAI_DEV = libsaibcm-dev_3.5.3.1m-25_amd64.deb
BRCM_SAI_DEV = libsaibcm-dev_3.7.3.3_amd64.deb
$(eval $(call add_derived_package,$(BRCM_SAI),$(BRCM_SAI_DEV)))
$(BRCM_SAI_DEV)_URL = "https://sonicstorage.blob.core.windows.net/packages/bcmsai/3.5/libsaibcm-dev_3.5.3.1m-26_amd64.deb?sv=2015-04-05&sr=b&sig=tQmkCIy2mnb9rH7B9oXFUZDwijMGXWnVtta2CNTMbFM%3D&se=2033-07-21T18%3A50%3A47Z&sp=r"
$(BRCM_SAI_DEV)_URL = "https://sonicstorage.blob.core.windows.net/packages/bcmsai/3.7/libsaibcm-dev_3.7.3.3_amd64.deb?sv=2015-04-05&sr=b&sig=6%2BWzgFL845H9lKE0COsN53P4MO4UWfSo0z%2FmUMFbYVk%3D&se=2033-08-25T01%3A21%3A50Z&sp=r"
SONIC_ONLINE_DEBS += $(BRCM_SAI)
$(BRCM_SAI_DEV)_DEPENDS += $(BRCM_SAI)
$(BRCM_SAI_DEV)_DEPENDS += $(BRCM_SAI)

View File

@ -1,3 +1,24 @@
opennsl (3.7.3.3-1) unstable; urgency=medium
* Port Broadcom SAI 3.7.3.3
* Cherry-pick change from master branch, 3.7.3.3-1
-- Judy Joseph <jujoseph@microsoft.com> Fri, 2 Dec 2019 15:32:47 +0000
opennsl (3.7.3.2-1) unstable; urgency=medium
* Port Broadcom SAI 3.7.3.2
* Cherry-pick change from master branch, 3.7.3.2-1
-- Judy Joseph <jujoseph@microsoft.com> Fri, 12 Nov 2019 15:22:47 +0000
opennsl (3.7.3.1-1) unstable; urgency=medium
* Port Broadcom SAI 3.7.3.1
* Cherry-pick change from master branch, 3.7.3.1-1
-- Judy Joseph <jujoseph@microsoft.com> Fri, 19 Sep 2019 13:11:47 +0000
opennsl (3.4.1.11-1) unstable; urgency=medium
* Port Broadcom SAI 3.4.1.11

View File

@ -32,14 +32,38 @@ function create_devices()
# level logs
function load_kernel_modules()
{
modprobe linux-kernel-bde dmasize=32M maxpayload=128 debug=4 dma_debug=1
. /host/machine.conf
if [ -n "$aboot_platform" ]; then
platform=$aboot_platform
elif [ -n "$onie_platform" ]; then
platform=$onie_platform
else
platform="unknown"
fi
# Set the default configuration for dmasize and usemsi parameters
dmasize=32M
usemsi=0
# Source the platform env file
env_file="/usr/share/sonic/device/$platform/platform_env.conf"
source $env_file
modprobe linux-kernel-bde dmasize=$dmasize maxpayload=128 debug=4 dma_debug=1 usemsi=$usemsi
modprobe linux-user-bde
# Using insmod with absolute path for psample to make sure bcm psample is loaded.
# 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-knet-cb
}
function remove_kernel_modules()
{
rmmod psample.ko
rmmod linux-knet-cb
rmmod linux-bcm-knet
rmmod linux-user-bde

View File

@ -2,4 +2,5 @@ systems/linux/user/x86-smp_generic_64-2_6/linux-bcm-knet.ko lib/modules/4.9.0-9-
systems/linux/user/x86-smp_generic_64-2_6/linux-kernel-bde.ko lib/modules/4.9.0-9-2-amd64/extra
systems/linux/user/x86-smp_generic_64-2_6/linux-user-bde.ko lib/modules/4.9.0-9-2-amd64/extra
systems/linux/user/x86-smp_generic_64-2_6/linux-knet-cb.ko lib/modules/4.9.0-9-2-amd64/extra
systems/linux/user/x86-smp_generic_64-2_6/psample.ko lib/modules/4.9.0-9-2-amd64/extra
systemd/opennsl-modules.service lib/systemd/system

View File

@ -60,7 +60,7 @@ kdist_config: prep-deb-files
kdist_clean: clean
dh_testdir
dh_clean
SDK=$(realpath .) LINUX_UAPI_SPLIT=1 DEBIAN_LINUX_HEADER=1 BUILD_KNET_CB=1 KERNDIR=/usr/src/linux-headers-4.9.0-9-2-amd64 KERNEL_SRC=/usr/src/linux-headers-4.9.0-9-2-amd64 $(MAKE) -C systems/linux/user/x86-smp_generic_64-2_6 clean
SDK=$(realpath .) LINUX_UAPI_SPLIT=1 DEBIAN_LINUX_HEADER=1 BUILD_KNET_CB=1 BUILD_PSAMPLE=1 KERNDIR=/usr/src/linux-headers-4.9.0-9-2-amd64 KERNEL_SRC=/usr/src/linux-headers-4.9.0-9-2-amd64 $(MAKE) -C systems/linux/user/x86-smp_generic_64-2_6 clean
# rm -f driver/*.o driver/*.ko
#
### end KERNEL SETUP
@ -78,7 +78,7 @@ build-arch-stamp:
dh_testdir
# Add here command to compile/build the package.
SDK=$(realpath .) LINUX_UAPI_SPLIT=1 DEBIAN_LINUX_HEADER=1 BUILD_KNET_CB=1 KERNDIR=/usr/src/linux-headers-4.9.0-9-2-amd64 KERNEL_SRC=/usr/src/linux-headers-4.9.0-9-2-amd64 $(MAKE) -C systems/linux/user/x86-smp_generic_64-2_6
SDK=$(realpath .) LINUX_UAPI_SPLIT=1 DEBIAN_LINUX_HEADER=1 BUILD_KNET_CB=1 BUILD_PSAMPLE=1 KERNDIR=/usr/src/linux-headers-4.9.0-9-2-amd64 KERNEL_SRC=/usr/src/linux-headers-4.9.0-9-2-amd64 $(MAKE) -C systems/linux/user/x86-smp_generic_64-2_6
touch $@
@ -103,7 +103,7 @@ clean:
rm -f build-arch-stamp build-indep-stamp configure-stamp
# Add here commands to clean up after the build process.
SDK=$(realpath .) LINUX_UAPI_SPLIT=1 DEBIAN_LINUX_HEADER=1 BUILD_KNET_CB=1 KERNDIR=/usr/src/linux-headers-4.9.0-9-2-amd64 KERNEL_SRC=/usr/src/linux-headers-4.9.0-9-2-amd64 $(MAKE) -C systems/linux/user/x86-smp_generic_64-2_6 clean
SDK=$(realpath .) LINUX_UAPI_SPLIT=1 DEBIAN_LINUX_HEADER=1 BUILD_KNET_CB=1 BUILD_PSAMPLE=1 KERNDIR=/usr/src/linux-headers-4.9.0-9-2-amd64 KERNEL_SRC=/usr/src/linux-headers-4.9.0-9-2-amd64 $(MAKE) -C systems/linux/user/x86-smp_generic_64-2_6 clean
dh_clean

View File

@ -148,14 +148,6 @@ typedef struct ibde_s {
*/
int (*get_cmic_ver)(int d, uint32 *ver);
/*
* Probe available devices.
* Return value :
* 0: success to probe available devices
* -1: error happens during probe
*/
int (*probe)(void);
/*
* I2C operations on the Device, assuming it is connected by I2C to the CPU.
*/

View File

@ -121,6 +121,13 @@ typedef struct kcom_msg_hdr_s {
#define KCOM_NETIF_NAME_MAX 16
/*
* Max size of Sand System Headers
* For DNX, Module Header(20B) + PTCH(2B) + ITMH(5B)
* For DPP, PTCH(2B) + ITMH(4B)
*/
#define KCOM_NETIF_SYSTEM_HEADERS_SIZE_MAX 27
typedef struct kcom_netif_s {
uint16 id;
uint8 type;
@ -133,6 +140,8 @@ typedef struct kcom_netif_s {
uint8 macaddr[6];
uint8 ptch[2];
uint8 itmh[4];
uint8 system_headers[KCOM_NETIF_SYSTEM_HEADERS_SIZE_MAX];
uint8 system_headers_size;
char name[KCOM_NETIF_NAME_MAX];
} kcom_netif_t;
@ -216,6 +225,13 @@ typedef struct kcom_filter_s {
uint8 b[KCOM_FILTER_BYTES_MAX];
uint32 w[KCOM_FILTER_WORDS_MAX];
} mask;
/** Information to parse Dune system headers */
uint32 ftmh_lb_key_ext_size;
uint32 ftmh_stacking_ext_size;
uint32 pph_base_size;
uint32 pph_lif_ext_size[8];
uint8 udh_enable;
uint32 udh_length_type[4];
} kcom_filter_t;
/*
@ -470,8 +486,7 @@ typedef struct kcom_msg_filter_destroy_s {
* Get list of currently defined packet filters.
*/
#ifndef KCOM_FILTER_MAX
/* SAI_FIXUP - Increased the filters to 1024 from 128 */
#define KCOM_FILTER_MAX 1024
#define KCOM_FILTER_MAX 128
#endif
typedef struct kcom_msg_filter_list_s {

View File

@ -14,7 +14,7 @@
* version 2 (GPLv2) along with this source code.
*/
/*
* Copyright: (c) 2018 Broadcom.
* Copyright: (c) 2019 Broadcom.
* All Rights Reserved.
*/
@ -835,31 +835,6 @@
#define BCM56746_A0_REV_ID 1
#define BCM56746_A1_REV_ID 2
#define BCM88230_DEVICE_ID 0x0230
#define BCM88230_A0_REV_ID 1
#define BCM88230_B0_REV_ID 0x11
#define BCM88230_C0_REV_ID 0x21
#define BCM88231_DEVICE_ID 0x0231
#define BCM88231_A0_REV_ID 1
#define BCM88231_B0_REV_ID 0x11
#define BCM88231_C0_REV_ID 0x21
#define BCM88235_DEVICE_ID 0x0235
#define BCM88235_A0_REV_ID 1
#define BCM88235_B0_REV_ID 0x11
#define BCM88235_C0_REV_ID 0x21
#define BCM88236_DEVICE_ID 0x0236
#define BCM88236_A0_REV_ID 1
#define BCM88236_B0_REV_ID 0x11
#define BCM88236_C0_REV_ID 0x21
#define BCM88239_DEVICE_ID 0x0239
#define BCM88239_A0_REV_ID 1
#define BCM88239_B0_REV_ID 0x11
#define BCM88239_C0_REV_ID 0x21
#define BCM56613_DEVICE_ID 0xb613
#define BCM56613_A0_REV_ID 1
#define BCM56613_B0_REV_ID 0x11
#define BCM56613_C0_REV_ID 0x21
#define BCM88732_DEVICE_ID 0x0732
#define BCM88732_A0_REV_ID 1
#define BCM88732_A1_REV_ID 2
@ -1243,10 +1218,13 @@
#define BCM56981_A0_REV_ID 1
#define BCM56982_DEVICE_ID 0xb982
#define BCM56982_A0_REV_ID 1
#define BCM56982_B0_REV_ID 0x11
#define BCM56983_DEVICE_ID 0xb983
#define BCM56983_A0_REV_ID 1
#define BCM56983_B0_REV_ID 0x11
#define BCM56984_DEVICE_ID 0xb984
#define BCM56984_A0_REV_ID 1
#define BCM56984_B0_REV_ID 0x11
#define BCM56968_DEVICE_ID 0xb968
#define BCM56968_A0_REV_ID 1
@ -1428,33 +1406,43 @@
#define BCM56370_DEVICE_ID 0xb370
#define BCM56370_A0_REV_ID 1
#define BCM56370_A1_REV_ID 0x02
#define BCM56371_DEVICE_ID 0xb371
#define BCM56371_A0_REV_ID 1
#define BCM56371_A1_REV_ID 0x02
#define BCM56372_DEVICE_ID 0xb372
#define BCM56372_A0_REV_ID 1
#define BCM56372_A1_REV_ID 0x02
#define BCM56374_DEVICE_ID 0xb374
#define BCM56374_A0_REV_ID 1
#define BCM56374_A1_REV_ID 0x02
#define BCM56375_DEVICE_ID 0xb375
#define BCM56375_A0_REV_ID 1
#define BCM56375_A1_REV_ID 0x02
#define BCM56376_DEVICE_ID 0xb376
#define BCM56376_A0_REV_ID 1
#define BCM56376_A1_REV_ID 0x02
#define BCM56377_DEVICE_ID 0xb377
#define BCM56377_A0_REV_ID 1
#define BCM56377_A1_REV_ID 0x02
#define BCM56577_DEVICE_ID 0xb577
#define BCM56577_A0_REV_ID 1
#define BCM56577_A1_REV_ID 0x02
#define BCM56578_DEVICE_ID 0xb578
#define BCM56578_A0_REV_ID 1
#define BCM56578_A1_REV_ID 0x02
#define BCM56579_DEVICE_ID 0xb579
#define BCM56579_A0_REV_ID 1
#define BCM56579_A1_REV_ID 0x02
#define BCM56770_DEVICE_ID 0xb770
#define BCM56770_A0_REV_ID 1
@ -1488,247 +1476,6 @@
#define BROADCOM_PHYID_HIGH 0x0040
#define BCM5338_PHYID_LOW 0x62b0
#define BCM5338_A0_REV_ID 0
#define BCM5338_A1_REV_ID 1
#define BCM5338_B0_REV_ID 3
#define BCM5324_PHYID_LOW 0xbc20
#define BCM5324_PHYID_HIGH 0x143
#define BCM5324_A1_PHYID_HIGH 0x153
#define BCM5324_DEVICE_ID 0xbc20
#define BCM5324_A0_REV_ID 0
#define BCM5324_A1_REV_ID 1
#define BCM5324_A2_REV_ID 2
#define BCM5380_PHYID_LOW 0x6250
#define BCM5380_A0_REV_ID 0
#define BCM5388_PHYID_LOW 0x6288
#define BCM5388_A0_REV_ID 0
#define BCM5396_PHYID_LOW 0xbd70
#define BCM5396_PHYID_HIGH 0x143
#define BCM5396_DEVICE_ID 0x96
#define BCM5396_A0_REV_ID 0
#define BCM5389_PHYID_LOW 0xbd70
#define BCM5389_PHYID_HIGH 0x143
#define BCM5389_DEVICE_ID 0x89
#define BCM5389_A0_REV_ID 0
#define BCM5389_A1_DEVICE_ID 0x86
#define BCM5389_A1_REV_ID 1
#define BCM5398_PHYID_LOW 0xbcd0
#define BCM5398_PHYID_HIGH 0x0143
#define BCM5398_DEVICE_ID 0x98
#define BCM5398_A0_REV_ID 0
#define BCM5325_PHYID_LOW 0xbc30
#define BCM5325_PHYID_HIGH 0x143
#define BCM5325_DEVICE_ID 0xbc30
#define BCM5325_A0_REV_ID 0
#define BCM5325_A1_REV_ID 1
#define BCM5348_PHYID_LOW 0xbe40
#define BCM5348_PHYID_HIGH 0x0143
#define BCM5348_DEVICE_ID 0x48
#define BCM5348_A0_REV_ID 0
#define BCM5348_A1_REV_ID 1
#define BCM5397_PHYID_LOW 0xbcd0
#define BCM5397_PHYID_HIGH 0x0143
#define BCM5397_DEVICE_ID 0x97
#define BCM5397_A0_REV_ID 0
#define BCM5347_PHYID_LOW 0xbe40
#define BCM5347_PHYID_HIGH 0x0143
#define BCM5347_DEVICE_ID 0x47
#define BCM5347_A0_REV_ID 0
#define BCM5395_PHYID_LOW 0xbcf0
#define BCM5395_PHYID_HIGH 0x0143
#define BCM5395_DEVICE_ID 0xbcf0
#define BCM5395_A0_REV_ID 0
#define BCM53242_PHYID_LOW 0xbf10
#define BCM53242_PHYID_HIGH 0x0143
#define BCM53242_DEVICE_ID 0xbf10
#define BCM53242_A0_REV_ID 0
#define BCM53242_B0_REV_ID 4
#define BCM53242_B1_REV_ID 5
#define BCM53262_PHYID_LOW 0xbf20
#define BCM53262_PHYID_HIGH 0x0143
#define BCM53262_DEVICE_ID 0xbf20
#define BCM53262_A0_REV_ID 0
#define BCM53262_B0_REV_ID 4
#define BCM53262_B1_REV_ID 5
#define BCM53115_PHYID_LOW 0xbf80
#define BCM53115_PHYID_HIGH 0x0143
#define BCM53115_DEVICE_ID 0xbf80
#define BCM53115_A0_REV_ID 0
#define BCM53115_A1_REV_ID 1
#define BCM53115_B0_REV_ID 2
#define BCM53115_B1_REV_ID 3
#define BCM53115_C0_REV_ID 8
#define BCM53118_PHYID_LOW 0xbfe0
#define BCM53118_PHYID_HIGH 0x0143
#define BCM53118_DEVICE_ID 0xbfe0
#define BCM53118_A0_REV_ID 0
#define BCM53118_B0_REV_ID 4
#define BCM53118_B1_REV_ID 5
#define BCM53280_PHYID_LOW 0x5e90
#define BCM53280_PHYID_HIGH 0x0362
#define BCM53280_DEVICE_ID (0x4 | BCM53280_PHYID_LOW)
#define BCM53280_A0_REV_ID 0
#define BCM53280_B0_REV_ID 0x4
#define BCM53280_B1_REV_ID 0x5
#define BCM53280_B2_REV_ID 0x6
#define BCM53286_DEVICE_ID (0x4 | BCM53280_PHYID_LOW)
#define BCM53288_DEVICE_ID (0xc | BCM53280_PHYID_LOW)
#define BCM53284_DEVICE_ID (0x7 | BCM53280_PHYID_LOW)
#define BCM53283_DEVICE_ID (0x6 | BCM53280_PHYID_LOW)
#define BCM53282_DEVICE_ID (0x5 | BCM53280_PHYID_LOW)
#define BCM53101_PHYID_LOW 0x5ed0
#define BCM53101_PHYID_HIGH 0x0362
#define BCM53101_DEVICE_ID 0x5ed0
#define BCM53101_A0_REV_ID 0
#define BCM53101_B0_REV_ID 4
#define BCM53125_PHYID_LOW 0x5f20
#define BCM53125_PHYID_HIGH 0x0362
#define BCM53125_DEVICE_ID 0x5f20
#define BCM53125_A0_REV_ID 0
#define BCM53125_B0_REV_ID 0x4
#define BCM53125_MODEL_ID 0x53125
#define BCM53134_PHYID_LOW 0x5350
#define BCM53134_PHYID_HIGH 0xAE02
#define BCM53134_DEVICE_ID 0x5350
#define BCM53134_A0_REV_ID 0x0
#define BCM53134_B0_REV_ID 0x1
#define BCM53134_B1_REV_ID 0x2
#define BCM53134_A0_MODEL_ID 0x5035
#define BCM53134_B0_MODEL_ID 0x5075
#define BCM53128_PHYID_LOW 0x5e10
#define BCM53128_PHYID_HIGH 0x0362
#define BCM53128_DEVICE_ID 0x5e10
#define BCM53128_A0_REV_ID 0
#define BCM53128_B0_REV_ID 0x4
#define BCM53128_MODEL_ID 0x53128
#define BCM53600_PHYID_LOW 0x5f40
#define BCM53600_PHYID_HIGH 0x0362
#define BCM53600_DEVICE_ID (0x3 | BCM53600_PHYID_LOW)
#define BCM53600_A0_REV_ID 0
#define BCM53602_DEVICE_ID (0x1 | BCM53600_PHYID_LOW)
#define BCM53603_DEVICE_ID (0x2 | BCM53600_PHYID_LOW)
#define BCM53604_DEVICE_ID (0x3 | BCM53600_PHYID_LOW)
#define BCM53606_DEVICE_ID (0x7 | BCM53600_PHYID_LOW)
#define BCM89500_PHYID_LOW 0x5d30
#define BCM89500_PHYID_HIGH 0x0362
#define BCM89500_DEVICE_ID 0x9500
#define BCM89501_DEVICE_ID 0x9501
#define BCM89200_DEVICE_ID 0x9200
#define BCM89500_A0_REV_ID 0
#define BCM89500_B0_REV_ID 0x4
#define BCM89500_MODEL_ID 0x89500
#define BCM53010_PHYID_LOW 0x8760
#define BCM53010_PHYID_HIGH 0x600d
#define BCM53010_DEVICE_ID 0x3010
#define BCM53011_DEVICE_ID 0x3011
#define BCM53012_DEVICE_ID 0x3012
#define BCM53010_A0_REV_ID 0
#define BCM53010_A2_REV_ID 0x2
#define BCM53010_MODEL_ID 0x53010
#define BCM53018_PHYID_LOW 0x87c0
#define BCM53018_PHYID_HIGH 0x600d
#define BCM53017_DEVICE_ID 0x3016
#define BCM53018_DEVICE_ID 0x3018
#define BCM53019_DEVICE_ID 0x3019
#define BCM53018_A0_REV_ID 0
#define BCM53018_MODEL_ID 0x53016
#define BCM53020_PHYID_LOW 0x87f0
#define BCM53020_PHYID_HIGH 0x600d
#define BCM53020_DEVICE_ID 0x8022
#define BCM53022_DEVICE_ID 0x8022
#define BCM53023_DEVICE_ID 0x8023
#define BCM53025_DEVICE_ID 0x8025
#define BCM58625_DEVICE_ID 0x8625
#define BCM58622_DEVICE_ID 0x8622
#define BCM58623_DEVICE_ID 0x8623
#define BCM58525_DEVICE_ID 0x8525
#define BCM58522_DEVICE_ID 0x8522
#define BCM53020_A0_REV_ID 0
#define BCM53020_MODEL_ID 0x3025
#define BCM4713_DEVICE_ID 0x4713
#define BCM4713_A0_REV_ID 0
#define BCM4713_A9_REV_ID 9
#define BCM53000_GMAC_DEVICE_ID 0x4715
#define BCM53000_A0_REV_ID 0
#define BCM53010_GMAC_DEVICE_ID 0x4715
#define BCM53000PCIE_DEVICE_ID 0x5300
#define SANDBURST_VENDOR_ID 0x17ba
#define BME3200_DEVICE_ID 0x0280
#define BME3200_A0_REV_ID 0x0000
#define BME3200_B0_REV_ID 0x0001
#define BM9600_DEVICE_ID 0x0480
#define BM9600_A0_REV_ID 0x0000
#define BM9600_B0_REV_ID 0x0010
#define QE2000_DEVICE_ID 0x0300
#define QE2000_A1_REV_ID 0x0001
#define QE2000_A2_REV_ID 0x0002
#define QE2000_A3_REV_ID 0x0003
#define QE2000_A4_REV_ID 0x0004
#define BCM88020_DEVICE_ID 0x0380
#define BCM88020_A0_REV_ID 0x0000
#define BCM88020_A1_REV_ID 0x0001
#define BCM88020_A2_REV_ID 0x0002
#define BCM88025_DEVICE_ID 0x0580
#define BCM88025_A0_REV_ID 0x0000
#define BCM88030_DEVICE_ID 0x0038
#define BCM88030_A0_REV_ID 0x0001
#define BCM88030_A1_REV_ID 0x0002
#define BCM88030_B0_REV_ID 0x0011
#define BCM88030_B1_REV_ID 0x0012
#define BCM88034_DEVICE_ID 0x0034
#define BCM88034_A0_REV_ID (BCM88030_A0_REV_ID)
#define BCM88034_A1_REV_ID (BCM88030_A1_REV_ID)
#define BCM88034_B0_REV_ID (BCM88030_B0_REV_ID)
#define BCM88034_B1_REV_ID (BCM88030_B1_REV_ID)
#define BCM88039_DEVICE_ID 0x0039
#define BCM88039_A0_REV_ID (BCM88030_A0_REV_ID)
#define BCM88039_A1_REV_ID (BCM88030_A1_REV_ID)
#define BCM88039_B0_REV_ID (BCM88030_B0_REV_ID)
#define BCM88039_B1_REV_ID (BCM88030_B1_REV_ID)
#define BCM88130_DEVICE_ID 0x0480
#define BCM88130_A0_REV_ID 0x0000
#define BCM88130_A1_REV_ID 0x0001
#define BCM88130_B0_REV_ID 0x0010
#define PLX_VENDOR_ID 0x10b5
#define PLX9656_DEVICE_ID 0x9656
#define PLX9656_REV_ID 0x0000
#define PLX9056_DEVICE_ID 0x9056
#define PLX9056_REV_ID 0x0000
#define TK371X_DEVICE_ID 0x8600
#define TK371X_A0_REV_ID 0x0
#define GEDI_DEVICE_ID 0xa100
#define GEDI_REV_ID 0x0001
#define ARAD_DEVICE_ID 0x8650
@ -1778,6 +1525,7 @@
#define DNXC_A0_REV_ID 0x0001
#define DNXC_A1_REV_ID 0x0002
#define DNXC_B0_REV_ID 0x0011
#define DNXC_B1_REV_ID 0x0012
#define BCM88790_DEVICE_ID 0x8790
#define BCM88790_A0_REV_ID DNXC_A0_REV_ID
#define BCM88790_B0_REV_ID DNXC_B0_REV_ID
@ -1933,9 +1681,34 @@
#define BCM88381_A0_REV_ID JERICHO_PLUS_A0_REV_ID
#define JERICHO_2_DEVICE_ID 0x8690
#define JERICHO_2_A0_REV_ID 0x0001
#define JERICHO_2_A0_REV_ID DNXC_A0_REV_ID
#define JERICHO_2_B0_REV_ID DNXC_B0_REV_ID
#define JERICHO_2_B1_REV_ID DNXC_B1_REV_ID
#define BCM88690_DEVICE_ID JERICHO_2_DEVICE_ID
#define BCM88690_A0_REV_ID JERICHO_2_A0_REV_ID
#define BCM88690_B0_REV_ID JERICHO_2_B0_REV_ID
#define BCM88690_B1_REV_ID JERICHO_2_B1_REV_ID
#define BCM88691_DEVICE_ID 0x8691
#define BCM88692_DEVICE_ID 0x8692
#define BCM88693_DEVICE_ID 0x8693
#define BCM88694_DEVICE_ID 0x8694
#define BCM88695_DEVICE_ID 0x8695
#define BCM88696_DEVICE_ID 0x8696
#define BCM88697_DEVICE_ID 0x8697
#define BCM88698_DEVICE_ID 0x8698
#define BCM88699_DEVICE_ID 0x8699
#define BCM8869A_DEVICE_ID 0x869A
#define BCM8869B_DEVICE_ID 0x869B
#define BCM8869C_DEVICE_ID 0x869C
#define BCM8869D_DEVICE_ID 0x869D
#define BCM8869E_DEVICE_ID 0x869E
#define BCM8869F_DEVICE_ID 0x869F
#define BCM_JR2_DEVID_MASK 0xFFF0
#define J2C_DEVICE_ID 0x8800
#define J2C_A0_REV_ID DNXC_A0_REV_ID
#define BCM88800_DEVICE_ID J2C_DEVICE_ID
#define BCM88800_A0_REV_ID J2C_A0_REV_ID
#define QAX_DEVICE_ID 0x8470
#define QAX_A0_REV_ID 0x0001
@ -1964,6 +1737,7 @@
#define BCM88270_A1_REV_ID QUX_A1_REV_ID
#define BCM88272_DEVICE_ID 0x8272
#define BCM88273_DEVICE_ID 0x8273
#define BCM88274_DEVICE_ID 0x8274
#define BCM88278_DEVICE_ID 0x8278
#define BCM88279_DEVICE_ID 0x8279
@ -2045,5 +1819,8 @@
#define ACP_PCI_VENDOR_ID 0x10ee
#define ACP_PCI_DEVICE_ID 0x7011
#define ACP_PCI_REV_ID 0x0001
#define PLX9056_DEVICE_ID 0x9056
#endif

View File

@ -54,12 +54,7 @@ endif
-include ${SDK}/make/Make.local
ifdef ALL_CHIPS
ROBO_CHIPS = 1
ESW_CHIPS = 1
else
ifndef ROBO_CHIPS
ESW_CHIPS = 1
endif
endif # ALL_CHIPS
#
@ -166,7 +161,7 @@ CFLAGS += ${INCFLAGS}
CXXFLAGS += ${INCFLAGS}
CPPFLAGS += ${INCFLAGS}
CFLAGS += -DSAI_FIXUP -DBCM_PORT_DEFAULT_DISABLE -DBCM_VLAN_NO_DEFAULT_ETHER -DBCM_VLAN_NO_DEFAULT_CPU -DBCM_WARM_BOOT_SUPPORT -DSAL_CONFIG_FILE_DISABLE -DSAL_THREAD_NAME_PRINT_DISABLE -UKCOM_FILTER_MAX -DKCOM_FILTER_MAX=256 -DALPM_ENABLE -DOPENNSL_PHY_ROUTINES -DTH2_CPU_POOL_SETUP -DINCLUDE_L3 -DSAI_ONLY -DPRINT_TO_SYSLOG -D_SHR_PBMP_WIDTH=256 -DINCLUDE_DIAG_SHELL -DSTATIC=static -DLOG_TEST -DLOG_SAI -D_GNU_SOURCE
CFLAGS += -DSAI_FIXUP -UKCOM_FILTER_MAX -DKCOM_FILTER_MAX=1024
#
# Debug #ifdef control

View File

@ -74,12 +74,6 @@ modname_flags = $(if $(filter 1,$(words $(modname))),\
KFLAG_INCLD = $(TOOLCHAIN_BIN_DIR)/../lib/gcc/$(TARGET_ARCHITECTURE)/4.6.4/include
ifdef BROADCOM_SVK
ifdef BCM_BME3200_B0
PLX_PCI2LBUS=1
endif
ifdef BCM_BM9600_B0
PLX_PCI2LBUS=1
endif
ifeq ($PLX_PCI2LBUS, 1)
CFLAGS += -DBCM_PLX9656_LOCAL_BUS -DBDE_LINUX_NON_INTERRUPTIBLE
endif

View File

@ -224,12 +224,6 @@ endif
endif
ifdef BROADCOM_SVK
ifdef BCM_BME3200_B0
PLX_PCI2LBUS=1
endif
ifdef BCM_BM9600_B0
PLX_PCI2LBUS=1
endif
ifeq ($PLX_PCI2LBUS, 1)
CFLAGS += -DBCM_PLX9656_LOCAL_BUS -DBDE_LINUX_NON_INTERRUPTIBLE
endif

View File

@ -27,11 +27,11 @@ endif
# TARGET_ARCHITECTURE Compiler for target architecture
# KERNDIR Kernel directory for iPROC-CMICd devices
ifeq (BE,$(ENDIAN_MODE))
TOOLCHAIN_BASE_DIR ?= /projects/ntsw-tools/linux/iproc_ldks/iproc-be/XLDK
TOOLCHAIN_BASE_DIR ?= /projects/ntsw-tools/linux/iproc_ldks/xldk50-be/XLDK32
TARGET_ARCHITECTURE:=armeb-broadcom-linux-uclibcgnueabi
KERNDIR ?= $(TOOLCHAIN_BASE_DIR)/kernel/linux
else
TOOLCHAIN_BASE_DIR ?= /projects/ntsw-tools/linux/iproc_ldks/iproc/XLDK
TOOLCHAIN_BASE_DIR ?= /projects/ntsw-tools/linux/iproc_ldks/xldk50/XLDK32
TARGET_ARCHITECTURE:= arm-broadcom-linux-uclibcgnueabi
KERNDIR ?= $(TOOLCHAIN_BASE_DIR)/kernel/linux
endif
@ -60,6 +60,8 @@ CFGFLAGS += -DSYS_BE_PIO=0 -DSYS_BE_PACKET=0 -DSYS_BE_OTHER=0
ENDIAN = LE_HOST=1
endif
CFLAGS += -fno-aggressive-loop-optimizations
CFGFLAGS += -D$(ENDIAN) -DIPROC_CMICD
CFGFLAGS += -DBCM_PLATFORM_STRING=\"IPROC_CMICD\"
@ -80,7 +82,7 @@ basename_flags = -D"KBUILD_BASENAME=KBUILD_STR($(call name-fix,$(basetarget)))"
modname_flags = $(if $(filter 1,$(words $(modname))),\
-D"KBUILD_MODNAME=KBUILD_STR($(call name-fix,$(modname)))")
KFLAG_INCLD ?= $(TOOLCHAIN_BASE_DIR)/buildroot/host/usr/lib/gcc/$(TARGET_ARCHITECTURE)/4.9.3/include
KFLAG_INCLD ?= $(TOOLCHAIN_BASE_DIR)/buildroot/host/usr/lib/gcc/$(TARGET_ARCHITECTURE)/4.9.4/include
ifeq (,$(KFLAGS))
KFLAGS := -D__LINUX_ARM_ARCH__=7 -D__KERNEL__ -nostdinc -isystem $(KFLAG_INCLD) -I$(LINUX_INCLUDE) -include $(LINUX_INCLUDE)/generated/autoconf.h -I$(KERNDIR)/arch/arm/include -I$(KERNDIR)/arch/arm/include/generated -I$(KERNDIR)/arch/arm/mach-iproc/include -Wall -Wstrict-prototypes -Wno-trigraphs -Os -fno-strict-aliasing -fno-common -marm -mabi=aapcs-linux -fno-pic -pipe -msoft-float -ffreestanding -march=armv7-a -mfpu=vfp -mfloat-abi=softfp -fomit-frame-pointer -g -fno-stack-protector -Wdeclaration-after-statement -Wno-pointer-sign -mlong-calls

View File

@ -71,7 +71,7 @@ $(KMODULE):
rm -f *.o *.ko .*.cmd
rm -fr .tmp_versions
ln -s $(LIBDIR)/$(MODULE) $(PRE_COMPILED_OBJ)_shipped
echo "suppress warning" > .$(PRE_COMPILED_OBJ).cmd
if [ ! -f $(KERNBLDDIR)/NO_SUPRESS ]; then echo "# suppress warning" > .$(PRE_COMPILED_OBJ).cmd; fi
$(MAKE) -C $(KERNBLDDIR) CROSS_COMPILE=$(CROSS_COMPILE) M=$(PWD) modules
if [ ! -f Module.symvers ]; then echo "old kernel (pre-2.6.17)" > Module.symvers; fi
cp -f $(KMODULE) $(LIBDIR)

View File

@ -22,7 +22,7 @@ ENDIAN = LE_HOST=1
CFGFLAGS += -D$(ENDIAN)
CFGFLAGS += -DBCM_PLATFORM_STRING=\"X86\"
ifeq (,$(findstring -DSAL_BDE_DMA_MEM_DEFAULT,$(CFGFLAGS)))
CFGFLAGS += -DSAL_BDE_DMA_MEM_DEFAULT=32
CFGFLAGS += -DSAL_BDE_DMA_MEM_DEFAULT=16
endif
# Extra variables.

View File

@ -48,4 +48,4 @@ AUTOCONF = $(KERNDIR)/include/linux/autoconf.h
endif
# gcc system include path
SYSINC = $(shell gcc -print-search-dirs | grep install | cut -c 10-)include
SYSINC = $(shell $(CC) -print-search-dirs | grep install | cut -c 10-)include

View File

@ -43,4 +43,3 @@ KFLAGS += -I$(KERNDIR_COMMON)/include -I$(KERNDIR_COMMON)/include/uapi -I$(KERND
endif
include ${SDK}/make/Makefile.linux-x86-common-2_6

View File

@ -222,7 +222,7 @@ extern int lkbde_dev_instid_set(int d, uint32 instid);
extern int lkbde_irq_mask_set(int d, uint32 addr, uint32 mask, uint32 fmask);
extern int lkbde_irq_mask_get(int d, uint32 *mask, uint32 *fmask);
#if (defined(BCM_PETRA_SUPPORT) || defined(BCM_DFE_SUPPORT))
#ifdef BCM_SAND_SUPPORT
extern int lkbde_cpu_write(int d, uint32 addr, uint32 *buf);
extern int lkbde_cpu_read(int d, uint32 addr, uint32 *buf);
extern int lkbde_cpu_pci_register(int d);
@ -241,15 +241,12 @@ extern int lkbde_cpu_pci_register(int d);
*/
#define LKBDE_IPROC_REG 0x4000
#if defined(BCM_PETRA_SUPPORT) || defined(BCM_DFE_SUPPORT)
#ifdef BCM_SAND_SUPPORT
#include <linux/version.h>
#if defined(__DUNE_LINUX_BCM_CPU_PCIE__) && LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,26)
#ifndef _SIMPLE_MEMORY_ALLOCATION_
#define _SIMPLE_MEMORY_ALLOCATION_ 1
#endif
#ifndef USE_LINUX_BDE_MMAP
#define USE_LINUX_BDE_MMAP 1
#endif
#endif
#endif
@ -271,13 +268,9 @@ extern int lkbde_cpu_pci_register(int d);
#define _SIMPLE_MEMORY_ALLOCATION_ 9 /* compile in the allocation method, but do not use it by default */
#endif
/* By default we use our private mmap only if /dev/mem mmap has restrictions */
/* By default we use our private mmap for DMA pool */
#ifndef USE_LINUX_BDE_MMAP
#ifdef CONFIG_STRICT_DEVMEM
#define USE_LINUX_BDE_MMAP 1
#else
#define USE_LINUX_BDE_MMAP 0
#endif
#endif
#endif /* __KERNEL__ */

View File

@ -58,7 +58,7 @@
#define DMA_BIT_MASK(n) (((n) == 64) ? ~0ULL : ((1ULL<<(n))-1))
#endif
extern void _dma_init(int robo_switch, int dev_index);
extern void _dma_init(int dev_index);
extern int _dma_cleanup(void);
extern void _dma_pprint(void);
extern uint32_t *_salloc(int d, int size, const char *name);
@ -68,7 +68,7 @@ extern int _sflush(int d, void *ptr, int length);
extern sal_paddr_t _l2p(int d, void *vaddr);
extern void *_p2l(int d, sal_paddr_t paddr);
extern int _dma_pool_allocated(void);
extern int _dma_range_valid(unsigned long phys_addr, unsigned long size);
extern int _dma_mmap(struct file *filp, struct vm_area_struct *vma);
#endif /* __KERNEL__ */

View File

@ -33,33 +33,11 @@ LIBS = $(LIBDIR)/libkern.a
BDE = linux-kernel-bde.o
ifdef ROBO_CHIPS
CFLAGS += -I$(ET_ROBO) -I${SDK}/include/shared/et
ET_ROBO = ${SDK}/systems/drv/et
endif
# need to add vpath sources
VPATH = ../shared $(ET_ROBO)
VPATH = ../shared
# Add the srcs to be found by vpath
LSRCS += mpool.c
ifdef ROBO_CHIPS
platformsplt = $(subst -, , ${platform}) # change hyphens to spaces
platformbase = $(word 1,${platformsplt})
ifeq ($(platformbase), keystone)
LSRCS += etc_robo_spi.c aiutils.c
else
ifeq ($(platformbase), keystone_le)
LSRCS += etc_robo_spi.c aiutils.c
else
ifeq ($(platformbase), iproc)
LSRCS += robo_srab.c robo_spi.c aiutils.c
endif
endif
endif # platformbase
endif # ROBO_CHIPS
# Add shared BDE sources
VPATH += ../../shared

View File

@ -85,10 +85,25 @@
#if _SIMPLE_MEMORY_ALLOCATION_ == 1
#define ALLOC_METHOD_DEFAULT ALLOC_TYPE_API
#if defined(__arm__)
#define USE_DMA_MMAP_COHERENT
#define _PGPROT_NONCACHED(x) x = pgprot_noncached((x))
#elif defined(__aarch64__ )
#define USE_DMA_MMAP_COHERENT
#define _PGPROT_NONCACHED(x) x = pgprot_writecombine((x))
#endif
#else
#define ALLOC_METHOD_DEFAULT ALLOC_TYPE_CHUNK
#endif
#ifndef _PGPROT_NONCACHED
#ifdef REMAP_DMA_NONCACHED
#define _PGPROT_NONCACHED(x) x = pgprot_noncached((x))
#else
#define _PGPROT_NONCACHED(x)
#endif
#endif
#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,10,0))
#include <linux/slab.h>
#define virt_to_bus virt_to_phys
@ -101,6 +116,12 @@
#define VIRT_TO_PAGE(p) virt_to_page((p))
#endif
#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,27))
#define DMA_MAPPING_ERROR(d, p) dma_mapping_error((d),(p))
#else
#define DMA_MAPPING_ERROR(d, p) dma_mapping_error((p))
#endif
#ifndef KMALLOC_MAX_SIZE
#define KMALLOC_MAX_SIZE (1UL << (MAX_ORDER - 1 + PAGE_SHIFT))
#endif
@ -170,7 +191,6 @@ MODULE_PARM_DESC(himemaddr,
#else
#define DMA_MEM_DEFAULT (8 * ONE_MB)
#endif
#define DMA_MEM_DEFAULT_ROBO (4 * ONE_MB)
/* We try to assemble a contiguous segment from chunks of this size */
#define DMA_BLOCK_SIZE (512 * ONE_KB)
@ -203,6 +223,7 @@ static unsigned long _himemaddr = 0;
static int _use_dma_mapping = 0;
static LIST_HEAD(_dma_seg);
#define DMA_DEV_INDEX 0 /* Device index to allocate memory pool */
#define DMA_DEV(n) lkbde_get_dma_dev(n)
#define BDE_NUM_DEVICES(t) lkbde_get_num_devices(t)
@ -545,7 +566,7 @@ _pgcleanup(void)
case ALLOC_TYPE_API:
if (_dma_vbase) {
if (dma_debug >= 1) gprintk("freeing v=%p p=0x%lx size=0x%lx\n", _dma_vbase,(unsigned long) _dma_pbase, (unsigned long)_dma_mem_size);
dma_free_coherent(DMA_DEV(0), _dma_mem_size, _dma_vbase, _dma_pbase);
dma_free_coherent(DMA_DEV(DMA_DEV_INDEX), _dma_mem_size, _dma_vbase, _dma_pbase);
}
break;
#endif /* _SIMPLE_MEMORY_ALLOCATION_ */
@ -554,7 +575,7 @@ _pgcleanup(void)
struct list_head *pos, *tmp;
int i, ndevices;
if (_use_dma_mapping) {
ndevices = BDE_NUM_DEVICES(BDE_ALL_DEVICES);
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);
}
@ -591,7 +612,6 @@ static void
_alloc_mpool(size_t size)
{
unsigned long pbase = 0;
#if defined(__arm__) && !defined(CONFIG_HIGHMEM)
if (_use_himem) {
gprintk("DMA in high memory requires CONFIG_HIGHMEM on ARM CPUs.\n");
@ -614,6 +634,9 @@ _alloc_mpool(size_t size)
_dma_vbase = IOREMAP(_dma_pbase, size);
} else {
/* Get DMA memory from kernel */
if (dma_debug >= 1) {
gprintk("Allocating DMA memory using method dmaalloc=%d\n", dmaalloc);
}
switch (dmaalloc) {
#if _SIMPLE_MEMORY_ALLOCATION_
case ALLOC_TYPE_API: {
@ -624,8 +647,9 @@ _alloc_mpool(size_t size)
/* get a memory allocation from the kernel */
{
dma_addr_t dma_handle;
if (!(_dma_vbase = dma_alloc_coherent(DMA_DEV(0), alloc_size, &dma_handle, GFP_KERNEL)) || !dma_handle) {
gprintk("failed to allocate the memory pool of size 0x%lx\n", (unsigned long)alloc_size);
if (!(_dma_vbase = dma_alloc_coherent(DMA_DEV(DMA_DEV_INDEX),
alloc_size, &dma_handle, GFP_KERNEL)) || !dma_handle) {
gprintk("Failed to allocate coherent memory pool of size 0x%lx\n", (unsigned long)alloc_size);
return;
}
_cpu_pbase = pbase = dma_handle;
@ -643,14 +667,14 @@ _alloc_mpool(size_t size)
case ALLOC_TYPE_CHUNK:
_dma_vbase = _pgalloc(size);
if (!_dma_vbase) {
gprintk("failed to allocate the memory pool of size 0x%lx\n", (unsigned long)size);
gprintk("Failed to allocate memory pool of size 0x%lx\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 (DMA_DEV(0)) {
pbase = dma_map_single(DMA_DEV(0), _dma_vbase, size, DMA_BIDIRECTIONAL);
if (dma_mapping_error(DMA_DEV(0), pbase)) {
if (DMA_DEV(DMA_DEV_INDEX)) {
pbase = dma_map_single(DMA_DEV(DMA_DEV_INDEX), _dma_vbase, size, DMA_BIDIRECTIONAL);
if (DMA_MAPPING_ERROR(DMA_DEV(DMA_DEV_INDEX), pbase)) {
gprintk("Failed to map memory at %p\n", _dma_vbase);
_pgcleanup();
_dma_vbase = NULL;
@ -659,7 +683,6 @@ _alloc_mpool(size_t size)
}
_use_dma_mapping = 1;
} else {
/* Device has not been probed. */
pbase = _cpu_pbase;
}
break;
@ -719,15 +742,21 @@ _dma_cleanup(void)
return 0;
}
void _dma_init(int robo_switch, int dev_index)
void _dma_init(int dev_index)
{
unsigned long pbase;
if (dev_index > 0) {
if ((_use_dma_mapping == 1) && DMA_DEV(dev_index) && _dma_vbase) {
if (dev_index > DMA_DEV_INDEX) {
if (_use_dma_mapping && DMA_DEV(dev_index) && _dma_vbase) {
pbase = dma_map_single(DMA_DEV(dev_index), _dma_vbase, _dma_mem_size, DMA_BIDIRECTIONAL);
if (dma_mapping_error(DMA_DEV(dev_index), pbase)) {
if (DMA_MAPPING_ERROR(DMA_DEV(dev_index), pbase)) {
gprintk("Failed to map memory for device %d at %p\n", dev_index, _dma_vbase);
return;
}
if (pbase != (unsigned long)_dma_pbase) {
/* Bus address/IOVA must be identical for all devices. */
gprintk("Device %d has different pbase: %lx (should be %lx)\n",
dev_index, pbase, (unsigned long)_dma_pbase);
}
}
return;
@ -745,10 +774,6 @@ void _dma_init(int robo_switch, int dev_index)
gprintk("dmasize must be a power of 2 (1M, 2M, 4M, 8M etc.)\n");
_dma_mem_size = 0;
}
} else {
if(robo_switch){
_dma_mem_size = DMA_MEM_DEFAULT_ROBO;
}
}
if (himem) {
@ -775,42 +800,54 @@ void _dma_init(int robo_switch, int dev_index)
_alloc_mpool(_dma_mem_size);
if (_dma_vbase == NULL) {
gprintk("no DMA memory available\n");
}
else {
} else {
mpool_init();
_dma_pool = mpool_create(_dma_vbase, _dma_mem_size);
}
}
}
#if USE_LINUX_BDE_MMAP
/*
* Function: _dma_range_valid
* Some kernels are configured to prevent mapping of kernel RAM memory
* into user space via the /dev/mem device.
*
* Purpose:
* Check if DMA address range is valid.
* Parameters:
* phys_addr - start physical address
* size - range size
* Returns:
* 0 : not valid
* 1 : valid
* The function below provides a backdoor to mapping the DMA pool to
* user space via the BDE device file.
*/
int
_dma_range_valid(unsigned long phys_addr, unsigned long size)
int _dma_mmap(struct file *filp, struct vm_area_struct *vma)
{
unsigned long pool_start = _cpu_pbase;
unsigned long pool_end = pool_start + _dma_mem_size;
unsigned long phys_addr = vma->vm_pgoff << PAGE_SHIFT;
unsigned long size = vma->vm_end - vma->vm_start;
if (phys_addr < pool_start || (phys_addr + size) > pool_end) {
if (phys_addr < (unsigned long )_cpu_pbase ||
(phys_addr + size) > ((unsigned long )_cpu_pbase + _dma_mem_size)) {
gprintk("range 0x%lx-0x%lx outside DMA pool 0x%lx-0x%lx\n",
phys_addr, phys_addr + size, pool_start, pool_end);
return 0;
phys_addr, phys_addr + size, (unsigned long )_cpu_pbase,
(unsigned long )_cpu_pbase + _dma_mem_size);
return -EINVAL;
}
#ifdef USE_DMA_MMAP_COHERENT
if (dmaalloc == ALLOC_TYPE_API) {
vma->vm_pgoff = 0;
return dma_mmap_coherent(DMA_DEV(DMA_DEV_INDEX), vma, (void *)_dma_vbase, phys_addr, size);
}
return 1;
}
#endif
_PGPROT_NONCACHED(vma->vm_page_prot);
if (remap_pfn_range(vma,
vma->vm_start,
vma->vm_pgoff,
size,
vma->vm_page_prot)) {
gprintk("Failed to mmap phys range 0x%lx-0x%lx to 0x%lx-0x%lx\n",
phys_addr, phys_addr + size, vma->vm_start,vma->vm_end);
return -EAGAIN;
}
return 0;
}
/*
* Function: _dma_pool_allocated
*

View File

@ -70,12 +70,31 @@ static sal_sem_t _mpool_lock;
#endif
#endif
#define MPOOL_BUF_SIZE 1024
#define MPOOL_BUF_ALLOC_COUNT_MAX 16
typedef struct mpool_mem_s {
unsigned char *address;
int size;
struct mpool_mem_s *prev;
struct mpool_mem_s *next;
} mpool_mem_t;
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]; \
}
/*
* Function: mpool_init
*
@ -116,6 +135,10 @@ mpool_alloc(mpool_handle_t pool, int size)
MPOOL_LOCK();
if (size < BCM_CACHE_LINE_BYTES) {
size = BCM_CACHE_LINE_BYTES;
}
mod = size & (BCM_CACHE_LINE_BYTES - 1);
if (mod != 0 ) {
size += (BCM_CACHE_LINE_BYTES - mod);
@ -131,21 +154,37 @@ mpool_alloc(mpool_handle_t pool, int size)
MPOOL_UNLOCK();
return NULL;
}
newptr = MALLOC(sizeof(mpool_mem_t));
if (!newptr) {
MPOOL_UNLOCK();
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++;
}
newptr = free_list;
free_list = free_list->next;
newptr->address = ptr->address + ptr->size;
newptr->size = size;
newptr->next = ptr->next;
newptr->prev = ptr;
ptr->next->prev = newptr;
ptr->next = newptr;
#ifdef TRACK_DMA_USAGE
_dma_mem_used += size;
#endif
MPOOL_UNLOCK();
MPOOL_UNLOCK();
return newptr->address;
}
@ -165,25 +204,29 @@ void
mpool_free(mpool_handle_t pool, void *addr)
{
unsigned char *address = (unsigned char *)addr;
mpool_mem_t *ptr = pool, *prev = NULL;
mpool_mem_t *head = pool, *ptr = NULL;
MPOOL_LOCK();
while (ptr && ptr->next) {
if (ptr->next->address == address) {
if (!(head && head->prev)) {
MPOOL_UNLOCK();
return;
}
ptr = head->prev->prev;
while (ptr && (ptr != head)) {
if (ptr->address == address) {
#ifdef TRACK_DMA_USAGE
_dma_mem_used -= ptr->next->size;
_dma_mem_used -= ptr->size;
#endif
ptr->prev->next = ptr->next;
ptr->next->prev = ptr->prev;
ptr->next = free_list;
free_list = ptr;
break;
}
ptr = ptr->next;
}
if (ptr && ptr->next) {
prev = ptr;
ptr = ptr->next;
prev->next = ptr->next;
FREE(ptr);
ptr = ptr->prev;
}
MPOOL_UNLOCK();
@ -208,34 +251,45 @@ 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;
}
_buf_alloc_count++;
if (mod) {
base_ptr = (char*)base_ptr + (BCM_CACHE_LINE_BYTES - mod);
size -= (BCM_CACHE_LINE_BYTES - mod);
}
size &= ~(BCM_CACHE_LINE_BYTES - 1);
head = (mpool_mem_t *)MALLOC(sizeof(mpool_mem_t));
if (head == NULL) {
return NULL;
}
tail = (mpool_mem_t *)MALLOC(sizeof(mpool_mem_t));
if (tail == NULL) {
FREE(head);
return NULL;
}
head = free_list;
free_list = free_list->next;
tail = free_list;
free_list = free_list->next;
head->size = tail->size = 0;
head->address = base_ptr;
tail->address = head->address + size;
head->prev = tail;
head->next = tail;
tail->prev = head;
tail->next = NULL;
MPOOL_UNLOCK();
return head;
}
@ -252,13 +306,20 @@ mpool_create(void *base_ptr, int size)
int
mpool_destroy(mpool_handle_t pool)
{
mpool_mem_t *ptr, *next;
int i;
MPOOL_LOCK();
for (ptr = pool; ptr; ptr = next) {
next = ptr->next;
FREE(ptr);
if ((mpool_mem_t *)pool != mpool_buf[0]) {
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;
}
}
MPOOL_UNLOCK();
@ -285,7 +346,7 @@ mpool_usage(mpool_handle_t pool)
MPOOL_LOCK();
for (ptr = pool; ptr; ptr = ptr->next) {
usage += ptr->size;
usage += ptr->size;
}
MPOOL_UNLOCK();

View File

@ -33,9 +33,6 @@
#if LINUX_VERSION_CODE >= KERNEL_VERSION(4,12,0)
#include <linux/uaccess.h>
#endif
#ifdef KEYSTONE
#include <shared/et/bcmdevs.h>
#endif
MODULE_AUTHOR("Broadcom Corporation");
@ -676,124 +673,10 @@ _bcm88750_interrupt(bde_ctrl_t *ctrl)
#endif
}
static void
_qe2k_interrupt(bde_ctrl_t *ctrl)
{
bde_inst_resource_t *res;
res = &_bde_inst_resource[ctrl->inst];
SSOC_WRITEL(0xffffffff, ctrl->ba + 0x20/sizeof(uint32));
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
_fe2k_interrupt(bde_ctrl_t *ctrl)
{
bde_inst_resource_t *res;
res = &_bde_inst_resource[ctrl->inst];
SSOC_WRITEL(0xffffffff, ctrl->ba + 0x18/sizeof(uint32)); /* PC_INTERRUPT_MASK */
SSOC_WRITEL(0xffffffff, ctrl->ba + 0x24/sizeof(uint32)); /* PC_ERROR0_MASK */
SSOC_WRITEL(0xffffffff, ctrl->ba + 0x2c/sizeof(uint32)); /* PC_ERROR1_MASK */
SSOC_WRITEL(0xffffffff, ctrl->ba + 0x34/sizeof(uint32)); /* PC_UNIT_MASK */
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
_fe2kxt_interrupt(bde_ctrl_t *ctrl)
{
bde_inst_resource_t *res;
res = &_bde_inst_resource[ctrl->inst];
SSOC_WRITEL(0xffffffff, ctrl->ba + 0x2c/sizeof(uint32)); /* PC_INTERRUPT_MASK */
SSOC_WRITEL(0xffffffff, ctrl->ba + 0x38/sizeof(uint32)); /* PC_ERROR0_MASK */
SSOC_WRITEL(0xffffffff, ctrl->ba + 0x40/sizeof(uint32)); /* PC_ERROR1_MASK */
SSOC_WRITEL(0xffffffff, ctrl->ba + 0x50/sizeof(uint32)); /* PC_UNIT_MASK */
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
_bme3200_interrupt(bde_ctrl_t *ctrl)
{
bde_inst_resource_t *res;
res = &_bde_inst_resource[ctrl->inst];
SSOC_WRITEL(0xffffffff, ctrl->ba + 0x54/sizeof(uint32)); /* PI_PT_ERROR0 */
SSOC_WRITEL(0xffffffff, ctrl->ba + 0x5c/sizeof(uint32)); /* PI_PT_ERROR1 */
SSOC_WRITEL(0xffffffff, ctrl->ba + 0x64/sizeof(uint32)); /* PI_PT_ERROR2 */
SSOC_WRITEL(0xffffffff, ctrl->ba + 0x6c/sizeof(uint32)); /* PI_PT_ERROR3 */
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
_bm9600_interrupt(bde_ctrl_t *ctrl)
{
bde_inst_resource_t *res;
res = &_bde_inst_resource[ctrl->inst];
SSOC_WRITEL(0xffffffff, ctrl->ba + 0x5c/sizeof(uint32)); /* PI_INTERRUPT_MASK */
SSOC_WRITEL(0xffffffff, ctrl->ba + 0xc/sizeof(uint32)); /* PI_UNIT_INTERRUPT0_MASK */
SSOC_WRITEL(0xffffffff, ctrl->ba + 0x14/sizeof(uint32)); /* PI_UNIT_INTERRUPT1_MASK */
SSOC_WRITEL(0xffffffff, ctrl->ba + 0x1c/sizeof(uint32)); /* PI_UNIT_INTERRUPT2_MASK */
SSOC_WRITEL(0xffffffff, ctrl->ba + 0x24/sizeof(uint32)); /* PI_UNIT_INTERRUPT3_MASK */
SSOC_WRITEL(0xffffffff, ctrl->ba + 0x2c/sizeof(uint32)); /* PI_UNIT_INTERRUPT4_MASK */
SSOC_WRITEL(0xffffffff, ctrl->ba + 0x34/sizeof(uint32)); /* PI_UNIT_INTERRUPT5_MASK */
SSOC_WRITEL(0xffffffff, ctrl->ba + 0x3c/sizeof(uint32)); /* PI_UNIT_INTERRUPT6_MASK */
SSOC_WRITEL(0xffffffff, ctrl->ba + 0x44/sizeof(uint32)); /* PI_UNIT_INTERRUPT7_MASK */
SSOC_WRITEL(0xffffffff, ctrl->ba + 0x4c/sizeof(uint32)); /* PI_UNIT_INTERRUPT8_MASK */
SSOC_WRITEL(0xffffffff, ctrl->ba + 0x54/sizeof(uint32)); /* PI_UNIT_INTERRUPT9_MASK */
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
_ether_interrupt(bde_ctrl_t *ctrl)
{
#ifdef KEYSTONE
/*
* Since the two GMAC cores are sharing the same IRQ.
* Add the checking to handle the interrupt events.
*/
if ((ctrl->devid == BCM53000_GMAC_ID)) {
if ((readl(ctrl->ba + 0x020/4) & readl(ctrl->ba + 0x024/4)) == 0) {
return;
}
}
#endif
SSOC_WRITEL(0, ctrl->ba + 0x024/4);
atomic_set(&_ether_interrupt_has_taken_place, 1);
@ -813,11 +696,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)_qe2k_interrupt, "QE2K" },
{ (isr_f)_fe2k_interrupt, "FE2K" },
{ (isr_f)_fe2kxt_interrupt, "FE2KXT" },
{ (isr_f)_bme3200_interrupt, "BME3200" },
{ (isr_f)_bm9600_interrupt, "BM9600" },
{ (isr_f)_bcm88750_interrupt, "BCM88750" },
{ (isr_f)_cmicx_interrupt, "CMICx" },
{ NULL, NULL }
@ -845,7 +723,7 @@ _devices_init(int d)
uint32 ver;
uint16 device_id_mask = 0xFFF0;
uint16 device_id;
int state = 0;
uint32 state = 0;
(void)lkbde_dev_state_get(d, &state);
if (state == BDE_DEV_STATE_REMOVED) {
@ -864,21 +742,6 @@ _devices_init(int d)
}
if (ctrl->dev_type & BDE_SWITCH_DEV_TYPE) {
switch (user_bde->get_dev(d)->device) {
case QE2000_DEVICE_ID:
ctrl->isr = (isr_f)_qe2k_interrupt;
break;
case BCM88020_DEVICE_ID:
ctrl->isr = (isr_f)_fe2k_interrupt;
break;
case BCM88025_DEVICE_ID:
ctrl->isr = (isr_f)_fe2kxt_interrupt;
break;
case BME3200_DEVICE_ID:
ctrl->isr = (isr_f)_bme3200_interrupt;
break;
case BM9600_DEVICE_ID:
ctrl->isr = (isr_f)_bm9600_interrupt;
break;
case BCM88750_DEVICE_ID:
case BCM88753_DEVICE_ID:
case BCM88754_DEVICE_ID:
@ -920,7 +783,7 @@ _devices_init(int d)
case BCM88380_DEVICE_ID:
case BCM88381_DEVICE_ID:
case BCM88680_DEVICE_ID:
case BCM88690_DEVICE_ID:
case BCM88800_DEVICE_ID:
case BCM88770_DEVICE_ID:
case BCM88773_DEVICE_ID:
case BCM88774_DEVICE_ID:
@ -938,6 +801,7 @@ _devices_init(int d)
case BCM88270_DEVICE_ID:
case BCM88272_DEVICE_ID:
case BCM88273_DEVICE_ID:
case BCM88274_DEVICE_ID:
case BCM88278_DEVICE_ID:
case BCM88279_DEVICE_ID:
case BCM8206_DEVICE_ID:
@ -1002,7 +866,15 @@ _devices_init(int d)
}
break;
}
/* All Ramon devices from 0x8790 to 0x879F */
#ifdef BCM_DNX_SUPPORT
/*All Jericho 2 devices from 0x8690 to 0x869F*/
if (SOC_IS_JERICHO_2_TYPE(user_bde->get_dev(d)->device)) {
ctrl->isr = (isr_f)_cmicx_interrupt;
}
#endif
/*All Ramon devices from 0x8790 to 0x879F*/
if ((user_bde->get_dev(d)->device & BCM88790_DEVICE_ID) == BCM88790_DEVICE_ID) {
ctrl->isr = (isr_f)_cmicx_interrupt;
}
@ -1456,30 +1328,9 @@ _ioctl(unsigned int cmd, unsigned long arg)
}
break;
case LUBDE_USLEEP:
sal_usleep(io.d0);
break;
case LUBDE_UDELAY:
sal_udelay(io.d0);
break;
case LUBDE_SEM_OP:
switch (io.d0) {
case LUBDE_SEM_OP_CREATE:
io.p0 = (bde_kernel_addr_t)sal_sem_create("", io.d1, io.d2);
break;
case LUBDE_SEM_OP_DESTROY:
sal_sem_destroy((sal_sem_t)io.p0);
break;
case LUBDE_SEM_OP_TAKE:
io.rc = sal_sem_take((sal_sem_t)io.p0, io.d2);
break;
case LUBDE_SEM_OP_GIVE:
io.rc = sal_sem_give((sal_sem_t)io.p0);
break;
default:
io.rc = LUBDE_FAIL;
break;
}
break;
return -EINVAL;
case LUBDE_WRITE_IRQ_MASK:
io.rc = lkbde_irq_mask_set(io.dev, io.d0, io.d1, 0);
break;
@ -1499,7 +1350,7 @@ _ioctl(unsigned int cmd, unsigned long arg)
case LUBDE_WRITE_REG_16BIT_BUS:
io.rc = user_bde->write(io.dev, io.d0, io.d1);
break;
#if (defined(BCM_PETRA_SUPPORT) || defined(BCM_DFE_SUPPORT))
#ifdef BCM_SAND_SUPPORT
case LUBDE_CPU_WRITE_REG:
{
if (lkbde_cpu_write(io.dev, io.d0, (uint32*)io.dx.buf) == -1) {

View File

@ -30,6 +30,8 @@
#define BAR0_PAXB_CONFIG_IND_ADDR 0x2120
#define BAR0_PAXB_CONFIG_IND_DATA 0x2124
#define PAXB_0_CMICD_TO_PCIE_INTR_EN 0x2380
#define BAR0_PAXB_IMAP0_0 (0x2c00)
#define BAR0_PAXB_IMAP0_1 (0x2c04)
#define BAR0_PAXB_IMAP0_2 (0x2c08)
@ -287,7 +289,8 @@ shbde_iproc_paxb_init(shbde_hal_t *shbde, void *iproc_regs,
iproc32_write(shbde, reg, data | 0x1);
}
}
/* Configure MSIX interrupt page, only need for iproc ver == 0x10 */
/* Configure MSIX interrupt page, only need for iproc ver == 0x10 */
if ((icfg->use_msi == 2) && (icfg->iproc_ver == 0x10)) {
unsigned int mask = (0x1 << PAXB_0_FUNC0_IMAP1_3_ADDR_SHIFT) - 1;
reg = ROFFS(iproc_regs, PAXB_0_FUNC0_IMAP1_3);
@ -296,6 +299,17 @@ shbde_iproc_paxb_init(shbde_hal_t *shbde, void *iproc_regs,
data |= 0x410 << PAXB_0_FUNC0_IMAP1_3_ADDR_SHIFT;
iproc32_write(shbde, reg, data);
}
/* Disable INTx interrupt if MSI/MSIX is selected */
reg = ROFFS(iproc_regs, PAXB_0_CMICD_TO_PCIE_INTR_EN);
data = iproc32_read(shbde, reg);
if (icfg->use_msi) {
data &= ~0x1;
} else {
data |= 0x1;
}
iproc32_write(shbde, reg, data);
return pci_num;
}

View File

@ -39,14 +39,17 @@ typedef struct {
* Call-back interfaces for other Linux kernel drivers.
*/
#include <linux/skbuff.h>
#include <linux/netdevice.h>
#include <kcom.h>
typedef struct {
uint32 netif_user_data;
uint32 filter_user_data;
uint16 dcb_type;
int port;
} knet_skb_cb_t;
#define KNET_SKB_CB(__skb) ((knet_skb_cb_t *)&((__skb)->cb[0]))
#define KNET_SKB_CB(_skb) ((knet_skb_cb_t *)_skb->cb)
typedef struct sk_buff *
(*knet_skb_cb_f)(struct sk_buff *skb, int dev_no, void *meta);
@ -55,6 +58,21 @@ typedef int
(*knet_filter_cb_f)(uint8_t *pkt, int size, int dev_no, void *meta,
int chan, kcom_filter_t *filter);
typedef int
(*knet_hw_tstamp_enable_cb_f)(int dev_no, int port);
typedef int
(*knet_hw_tstamp_tx_time_get_cb_f)(int dev_no, int port, uint8_t *pkt, uint64_t *ts);
typedef int
(*knet_hw_tstamp_tx_meta_get_cb_f)(int dev_no, struct sk_buff *skb, uint32_t **md);
typedef int
(*knet_hw_tstamp_ptp_clock_index_cb_f)(int dev_no);
typedef int
(*knet_hw_tstamp_rx_time_upscale_cb_f)(int dev_no, uint64_t *ts);
extern int
bkn_rx_skb_cb_register(knet_skb_cb_f rx_cb);
@ -73,6 +91,68 @@ bkn_filter_cb_register(knet_filter_cb_f filter_cb);
extern int
bkn_filter_cb_unregister(knet_filter_cb_f filter_cb);
#endif
extern int
bkn_hw_tstamp_enable_cb_register(knet_hw_tstamp_enable_cb_f hw_tstamp_enable_cb);
extern int
bkn_hw_tstamp_enable_cb_unregister(knet_hw_tstamp_enable_cb_f hw_tstamp_enable_cb);
extern int
bkn_hw_tstamp_disable_cb_register(knet_hw_tstamp_enable_cb_f hw_tstamp_disable_cb);
extern int
bkn_hw_tstamp_disable_cb_unregister(knet_hw_tstamp_enable_cb_f hw_tstamp_disable_cb);
extern int
bkn_hw_tstamp_tx_time_get_cb_register(knet_hw_tstamp_tx_time_get_cb_f hw_tstamp_tx_time_get_cb);
extern int
bkn_hw_tstamp_tx_time_get_cb_unregister(knet_hw_tstamp_tx_time_get_cb_f hw_tstamp_tx_time_get_cb);
extern int
bkn_hw_tstamp_tx_meta_get_cb_register(knet_hw_tstamp_tx_meta_get_cb_f hw_tstamp_tx_meta_get_cb);
extern int
bkn_hw_tstamp_tx_meta_get_cb_unregister(knet_hw_tstamp_tx_meta_get_cb_f hw_tstamp_tx_meta_get_cb);
extern int
bkn_hw_tstamp_ptp_clock_index_cb_register(knet_hw_tstamp_ptp_clock_index_cb_f hw_tstamp_ptp_clock_index_cb);
extern int
bkn_hw_tstamp_ptp_clock_index_cb_unregister(knet_hw_tstamp_ptp_clock_index_cb_f hw_tstamp_ptp_clock_index_cb);
extern int
bkn_hw_tstamp_rx_time_upscale_cb_register(knet_hw_tstamp_rx_time_upscale_cb_f hw_tstamp_rx_time_upscale_cb);
extern int
bkn_hw_tstamp_rx_time_upscale_cb_unregister(knet_hw_tstamp_rx_time_upscale_cb_f hw_tstamp_rx_time_upscale_cb);
typedef struct {
uint8 cmic_type;
uint8 dcb_type;
uint8 dcb_size;
uint8 pkt_hdr_size;
uint32 cdma_channels;
} knet_hw_info_t;
extern int
bkn_hw_info_get(int unit, knet_hw_info_t *hw_info);
typedef int
(*knet_netif_cb_f)(int unit, kcom_netif_t *netif, struct net_device *dev);
extern int
bkn_netif_create_cb_register(knet_netif_cb_f netif_cb);
extern int
bkn_netif_create_cb_unregister(knet_netif_cb_f netif_cb);
extern int
bkn_netif_destroy_cb_register(knet_netif_cb_f netif_cb);
extern int
bkn_netif_destroy_cb_unregister(knet_netif_cb_f netif_cb);
#endif /* __KERNEL__ */
#endif /* __LINUX_BCM_KNET_H__ */

View File

@ -0,0 +1,24 @@
#ifndef __NET_PSAMPLE_H
#define __NET_PSAMPLE_H
#include <gmodule.h>
#include <uapi/linux/psample.h>
#include <linux/module.h>
#include <linux/list.h>
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 */

View File

@ -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

View File

@ -36,7 +36,9 @@ KMODULE = $(LIBDIR)/$(THIS_MOD_NAME).ko
build: $(MODULE) $(KMODULE)
endif
KBUILD_EXTRA_SYMBOLS := ${BLDDIR}/../bcm-knet/kernel_module/Module.symvers
ifeq ($(BUILD_PSAMPLE),1)
KBUILD_EXTRA_SYMBOLS += ${BLDDIR}/../psample/kernel_module/Module.symvers
endif
# BCM Network Device

View File

@ -1,5 +1,5 @@
/*
* Copyright 2017 Broadcom
* 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
@ -45,17 +45,20 @@
#include <bcm-knet.h>
#include <linux/if_vlan.h>
/* Enable sflow sampling using psample */
#ifdef PSAMPLE_SUPPORT
#include "psample-cb.h"
#endif
MODULE_AUTHOR("Broadcom Corporation");
MODULE_DESCRIPTION("Broadcom Linux KNET Call-Back Driver");
MODULE_LICENSE("GPL");
static int debug;
int debug;
LKM_MOD_PARAM(debug, "i", int, 0);
MODULE_PARM_DESC(debug,
"Debug level (default 0)");
/* Module Information */
#define MODULE_MAJOR 121
#define MODULE_NAME "linux-knet-cb"
@ -63,8 +66,10 @@ MODULE_PARM_DESC(debug,
/* set KNET_CB_DEBUG for debug info */
#define KNET_CB_DEBUG
#define FILTER_TAG_STRIP 0
#define FILTER_TAG_KEEP 1
/* 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 {
@ -105,7 +110,7 @@ strip_vlan_tag(struct sk_buff *skb)
*
* DCB type 14: word 12, bits 10.11
* DCB type 19, 20, 21, 22, 30: word 12, bits 10..11
* DCB type 23, 29: word 13, bits 0..1
* DCB type 23, 29: word 13, bits 0..1
* DCB type 31, 34, 37: word 13, bits 0..1
* DCB type 26, 32, 33, 35: word 13, bits 0..1
*
@ -150,7 +155,7 @@ get_tag_status(int dcb_type, void *meta)
{
/* untested */
/* TH3 only parses outer tag. */
const int tag_map[4] = { 0, 2, -1, -1 };
const int tag_map[4] = { 0, 2, -1, -1 };
tag_status = tag_map[(dcb[9] >> 13) & 0x3];
}
break;
@ -162,7 +167,7 @@ get_tag_status(int dcb_type, void *meta)
if (debug & 0x1) {
gprintk("%s; DCB Type: %d; tag status: %d\n", __func__, dcb_type, tag_status);
}
#endif
#endif
return tag_status;
}
@ -183,12 +188,12 @@ strip_tag_rx_cb(struct sk_buff *skb, int dev_no, void *meta)
if (debug & 0x1) {
gprintk("%s Enter; netif Flags: %08X filter_flags %08X \n",
__func__, netif_flags, filter_flags);
}
}
#endif
/* KNET implements this already */
if (filter_flags == FILTER_TAG_KEEP)
{
{
strip_stats.skipped++;
return skb;
}
@ -217,8 +222,17 @@ strip_tag_rx_cb(struct sk_buff *skb, int dev_no, void *meta)
return skb;
}
if (filter_flags == FILTER_TAG_ORIGINAL)
{
/* If untagged or single inner, strip the extra tag that knet
keep tag will add. */
if (tag_status < 2)
{
strip_tag = 1;
}
}
strip_stats.checked++;
if (strip_tag) {
#ifdef KNET_CB_DEBUG
if (debug & 0x1) {
@ -235,7 +249,6 @@ strip_tag_rx_cb(struct sk_buff *skb, int dev_no, void *meta)
}
}
#endif
return skb;
}
@ -250,16 +263,50 @@ strip_tag_tx_cb(struct sk_buff *skb, int dev_no, void *meta)
/* Filter callback not used */
static int
strip_tag_filter_cb(uint8_t * pkt, int size, int dev_no, void *meta,
int chan, kcom_filter_t *kf)
int chan, kcom_filter_t *kf)
{
/* Pass through for now */
return 0;
}
static int
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
if (strncmp(kf->desc, PSAMPLE_CB_NAME, KCOM_FILTER_DESC_MAX) == 0) {
return psample_filter_cb (pkt, size, dev_no, meta, chan, kf);
}
#endif
return strip_tag_filter_cb (pkt, size, dev_no, meta, chan, kf);
}
static int
knet_netif_create_cb(int unit, kcom_netif_t *netif, struct net_device *dev)
{
int retv = 0;
#ifdef PSAMPLE_SUPPORT
retv = psample_netif_create_cb(unit, netif, dev);
#endif
return retv;
}
static int
knet_netif_destroy_cb(int unit, kcom_netif_t *netif, struct net_device *dev)
{
int retv = 0;
#ifdef PSAMPLE_SUPPORT
retv = psample_netif_destroy_cb(unit, netif, dev);
#endif
return retv;
}
/*
* Get statistics.
* % cat /proc/linux-knet-cb
*/
static int
_pprint(void)
{
@ -275,19 +322,40 @@ static int
_cleanup(void)
{
bkn_rx_skb_cb_unregister(strip_tag_rx_cb);
bkn_tx_skb_cb_unregister(strip_tag_tx_cb);
bkn_filter_cb_unregister(strip_tag_filter_cb);
/* strip_tag_tx_cb is currently a no-op, so no need to unregister */
if (0)
{
bkn_tx_skb_cb_unregister(strip_tag_tx_cb);
}
bkn_filter_cb_unregister(knet_filter_cb);
bkn_netif_create_cb_unregister(knet_netif_create_cb);
bkn_netif_destroy_cb_unregister(knet_netif_destroy_cb);
#ifdef PSAMPLE_SUPPORT
psample_cleanup();
#endif
return 0;
}
static int
_init(void)
{
bkn_rx_skb_cb_register(strip_tag_rx_cb);
bkn_tx_skb_cb_register(strip_tag_tx_cb);
bkn_filter_cb_register(strip_tag_filter_cb);
bkn_rx_skb_cb_register(strip_tag_rx_cb);
/* strip_tag_tx_cb is currently a no-op, so no need to register */
if (0)
{
bkn_tx_skb_cb_register(strip_tag_tx_cb);
}
#ifdef PSAMPLE_SUPPORT
psample_init();
#endif
bkn_filter_cb_register(knet_filter_cb);
bkn_netif_create_cb_register(knet_netif_create_cb);
bkn_netif_destroy_cb_register(knet_netif_destroy_cb);
return 0;
}

View File

@ -0,0 +1,875 @@
/*
* 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/<target>
* make BUILD_KNET_CB=1
*
*/
#include <gmodule.h> /* Must be included first */
#include <kcom.h>
#include <bcm-knet.h>
#include <linux/if_vlan.h>
#include <linux/skbuff.h>
#include <linux/sched.h>
#include <linux/netdevice.h>
#include <net/net_namespace.h>
#include <net/psample.h>
#include "psample-cb.h"
#define PSAMPLE_CB_DBG
#ifdef PSAMPLE_CB_DBG
extern int debug;
#define PSAMPLE_CB_DBG_PRINT(...) \
if (debug & 0x1) { \
gprintk(__VA_ARGS__); \
}
#else
#define PSAMPLE_CB_DBG_PRINT(...)
#endif
/* HIGIG2 header fields */
#define SOC_HIGIG_SOP (0xfb)
#define SOC_HIGIG_START(x) ((x[0] >> 24) & 0xff)
#define SOC_HIGIG_DSTPORT(x) ((x[1] >> 11) & 0x1f)
#define SOC_HIGIG_SRCPORT(x) ((x[1] >> 16) & 0x1f)
#define SOC_HIGIG2_SOP (0xfb) //0xfc - TODO: how can we differentiate between Higig and higig2?
#define SOC_HIGIG2_START(x) ((x[0] >> 24) & 0xff)
#define SOC_HIGIG2_DSTPORT(x) ((x[0] >> 0) & 0xff)
#define SOC_HIGIG2_SRCPORT(x) ((x[1] >> 16) & 0xff)
#define SOC_DCB32_HG_OFFSET (6)
#define FCS_SZ 4
#define PSAMPLE_NLA_PADDING 4
#define PSAMPLE_RATE_DFLT 1
#define PSAMPLE_SIZE_DFLT 128
static int psample_size = PSAMPLE_SIZE_DFLT;
LKM_MOD_PARAM(psample_size, "i", int, 0);
MODULE_PARM_DESC(psample_size,
"psample pkt size (default 128 bytes)");
/* driver proc entry root */
static struct proc_dir_entry *psample_proc_root = NULL;
/* psample general info */
typedef struct {
struct list_head netif_list;
knet_hw_info_t hw;
struct net *netns;
spinlock_t lock;
} 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_d_no_group;
unsigned long pkts_d_sampling_disabled;
unsigned long pkts_d_no_skb;
unsigned long pkts_d_not_ready;
unsigned long pkts_d_metadata;
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;
static psample_netif_t*
psample_netif_lookup_by_port(int unit, 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_info_get (int unit, psample_info_t *psample_info)
{
int rv = 0;
if (!psample_info) {
gprintk("%s: psample_info is NULL\n", __func__);
return (-1);
}
/* get hw info */
rv = bkn_hw_info_get(unit, &psample_info->hw);
if (rv < 0) {
gprintk("%s: failed to get hw info\n", __func__);
return (-1);
}
PSAMPLE_CB_DBG_PRINT("%s: DCB type %d\n",
__func__, psample_info->hw.dcb_type);
return (0);
}
static int
psample_meta_srcport_get(uint8_t *pkt, void *pkt_meta)
{
int srcport = 0;
uint32_t *metadata = (uint32_t*)pkt_meta;
switch(g_psample_info.hw.dcb_type) {
case 36: /* TD3 */
case 38: /* TH3 */
break;
case 32: /* TH1/TH2 */
case 26: /* TD2 */
case 23: /* HX4 */
metadata += SOC_DCB32_HG_OFFSET;
break;
default:
break;
}
if (SOC_HIGIG2_START(metadata) == SOC_HIGIG2_SOP)
{
srcport = SOC_HIGIG2_SRCPORT(metadata);
}
else if (SOC_HIGIG_START(metadata) == SOC_HIGIG_SOP)
{
srcport = SOC_HIGIG_SRCPORT(metadata);
}
else
{
PSAMPLE_CB_DBG_PRINT("%s: Could not detect metadata sop type: 0x%02x (w[0]: 0x%04x)\n", __func__,
SOC_HIGIG_START(metadata), metadata[0]);
return -1;
}
return srcport;
}
static int
psample_meta_dstport_get(uint8_t *pkt, void *pkt_meta)
{
int dstport = 0;
uint32_t *metadata = (uint32_t*)pkt_meta;
switch(g_psample_info.hw.dcb_type) {
case 36: /* TD3 */
case 38: /* TH3 */
break;
case 32: /* TH1/TH2 */
case 26: /* TD2 */
case 23: /* HX4 */
metadata += SOC_DCB32_HG_OFFSET;
break;
default:
break;
}
if (SOC_HIGIG2_START(metadata) == SOC_HIGIG2_SOP)
{
dstport = SOC_HIGIG2_DSTPORT(metadata);
}
else if (SOC_HIGIG_START(metadata) == SOC_HIGIG_SOP)
{
dstport = SOC_HIGIG_DSTPORT(metadata);
}
else
{
PSAMPLE_CB_DBG_PRINT("%s: Could not detect metadata sop type: 0x%02x (w[0]: 0x%04x)\n", __func__,
SOC_HIGIG_START(metadata), metadata[0]);
return (-1);
}
return dstport;
}
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;
/* Sample Pkt reason code (bcmRxReasonSampleSource) */
switch(g_psample_info.hw.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 */
default:
reason_hi = *(metadata + 2);
reason = *(metadata + 3);
sample_rx_reason_mask = (1 << 5);
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.hw.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 (1);
}
static int
psample_meta_get(int unit, uint8_t *pkt, void *pkt_meta, psample_meta_t *sflow_meta)
{
int srcport, dstport;
int src_ifindex = 0;
int dst_ifindex = 0;
int sample_rate = PSAMPLE_RATE_DFLT;
int sample_size = PSAMPLE_SIZE_DFLT;
psample_netif_t *psample_netif = NULL;
#ifdef PSAMPLE_CB_DBG
if (debug & 0x1) {
int i=0;
uint8_t *meta = (uint8_t*)pkt_meta;
PSAMPLE_CB_DBG_PRINT("%s: psample pkt metadata\n", __func__);
for (i=0; i<64; i+=16) {
PSAMPLE_CB_DBG_PRINT("%02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x\n",
meta[i+0], meta[i+1], meta[i+2], meta[i+3], meta[i+4], meta[i+5], meta[i+6], meta[i+7],
meta[i+8], meta[i+9], meta[i+10], meta[i+11], meta[i+12], meta[i+13], meta[i+14], meta[i+15]);
}
}
#endif
/* parse pkt metadata for src and dst ports */
srcport = psample_meta_srcport_get(pkt, pkt_meta);
dstport = psample_meta_dstport_get(pkt, pkt_meta);
if ((srcport == -1) || (dstport == -1)) {
gprintk("%s: invalid srcport %d or dstport %d\n", __func__, srcport, dstport);
return (-1);
}
/* find src port netif (no need to lookup CPU port) */
if (srcport != 0) {
if ((psample_netif = psample_netif_lookup_by_port(unit, srcport))) {
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 srcport(%d)\n", __func__, srcport);
}
}
/* find dst port netif (no need to lookup CPU port) */
if (dstport != 0) {
if ((psample_netif = psample_netif_lookup_by_port(unit, dstport))) {
dst_ifindex = psample_netif->dev->ifindex;
} else {
g_psample_stats.pkts_d_meta_dstport++;
PSAMPLE_CB_DBG_PRINT("%s: could not find dstport(%d)\n", __func__, dstport);
}
}
PSAMPLE_CB_DBG_PRINT("%s: srcport %d, dstport %d, src_ifindex %d, dst_ifindex %d, trunc_size %d, sample_rate %d\n",
__func__, srcport, dstport, src_ifindex, dst_ifindex, sample_size, sample_rate);
sflow_meta->src_ifindex = src_ifindex;
sflow_meta->dst_ifindex = dst_ifindex;
sflow_meta->trunc_size = sample_size;
sflow_meta->sample_rate = sample_rate;
return (0);
}
int
psample_filter_cb(uint8_t * pkt, int size, int dev_no, void *pkt_meta,
int chan, kcom_filter_t *kf)
{
struct psample_group *group;
psample_meta_t meta;
struct sk_buff skb;
int rv = 0;
static int info_get = 0;
if (!info_get) {
rv = psample_info_get (dev_no, &g_psample_info);
if (rv < 0) {
gprintk("%s: failed to get psample info\n", __func__);
goto PSAMPLE_FILTER_CB_PKT_HANDLED;
}
info_get = 1;
}
PSAMPLE_CB_DBG_PRINT("%s: pkt size %d, kf->dest_id %d, kf->cb_user_data %d\n",
__func__, size, kf->dest_id, kf->cb_user_data);
g_psample_stats.pkts_f_psample_cb++;
/* get psample group info. psample genetlink group ID passed in kf->dest_id */
group = psample_group_get(g_psample_info.netns, kf->dest_id);
if (!group) {
gprintk("%s: Could not find psample genetlink group %d\n", __func__, kf->cb_user_data);
g_psample_stats.pkts_d_no_group++;
goto PSAMPLE_FILTER_CB_PKT_HANDLED;
}
/* get psample metadata */
rv = psample_meta_get(dev_no, pkt, pkt_meta, &meta);
if (rv < 0) {
gprintk("%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 */
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 %d, dst_ifdx %d, 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) {
/* setup skb to point to pkt */
memset(&skb, 0, sizeof(struct sk_buff));
skb.len = size;
skb.data = pkt;
psample_sample_packet(group,
&skb,
meta.trunc_size,
meta.src_ifindex,
meta.dst_ifindex,
meta.sample_rate);
g_psample_stats.pkts_f_psample_mod++;
} 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(pkt, pkt_meta);
if (rv) {
g_psample_stats.pkts_f_handled++;
} else {
g_psample_stats.pkts_f_pass_through++;
}
return rv;
}
int
psample_netif_create_cb(int unit, kcom_netif_t *netif, struct net_device *dev)
{
int found;
struct list_head *list;
psample_netif_t *psample_netif, *lpsample_netif;
unsigned long flags;
if ((psample_netif = kmalloc(sizeof(psample_netif_t), GFP_KERNEL)) == NULL) {
gprintk("%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;
psample_netif->port = netif->port;
psample_netif->vlan = netif->vlan;
psample_netif->qnum = netif->qnum;
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;
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(int unit, kcom_netif_t *netif, struct net_device *dev)
{
int found;
struct list_head *list;
psample_netif_t *psample_netif;
unsigned long flags;
if (!netif || !dev) {
gprintk("%s: netif or net_device is NULL\n", __func__);
return (-1);
}
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);
break;
}
}
spin_unlock_irqrestore(&g_psample_info.lock, flags);
if (!found) {
gprintk("%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:
* <netif>=<pkt sample rate>
*
* Where <netif> 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) {
gprintk("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) {
gprintk("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:
* <netif>=<pkt sample size in bytes>
*
* Where <netif> 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) {
gprintk("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) {
gprintk("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 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, " cmic_type: %d\n", g_psample_info.hw.cmic_type);
seq_printf(m, " dcb_type: %d\n", g_psample_info.hw.dcb_type);
seq_printf(m, " dcb_size: %d\n", g_psample_info.hw.dcb_size);
seq_printf(m, " pkt_hdr_size: %d\n", g_psample_info.hw.pkt_hdr_size);
seq_printf(m, " cdma_channels: %d\n", g_psample_info.hw.cdma_channels);
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=<mask>
*
* Where <mask> 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 {
gprintk("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.hw.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 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 no skb %10lu\n", g_psample_stats.pkts_d_no_skb);
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 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);
}
struct file_operations psample_proc_stats_file_ops = {
owner: THIS_MODULE,
open: psample_proc_stats_open,
read: seq_read,
llseek: seq_lseek,
write: NULL,
release: single_release,
};
int psample_cleanup(void)
{
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);
return 0;
}
int psample_init(void)
{
#define PROCFS_MAX_PATH 1024
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");
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) {
gprintk("%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) {
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) {
gprintk("%s: Unable to create procfs entry '/procfs/%s/size'\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) {
gprintk("%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));
/* setup psample_info struct */
INIT_LIST_HEAD(&g_psample_info.netif_list);
spin_lock_init(&g_psample_info.lock);
/* 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__,
current->pid, g_psample_info.netns, psample_size);
return 0;
}

View File

@ -0,0 +1,58 @@
/*
* 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 <gmodule.h>
#include <kcom.h>
#include <linux/netdevice.h>
#define PSAMPLE_CB_NAME "psample"
extern int
psample_init(void);
extern int
psample_cleanup(void);
extern int
psample_filter_cb(uint8_t * pkt, int size, int dev_no, void *pkt_meta,
int chan, kcom_filter_t *kf);
/* psample data per interface */
typedef struct {
struct list_head list;
struct net_device *dev;
uint16 id;
uint8 port;
uint16 vlan;
uint16 qnum;
uint32 sample_rate;
uint32 sample_size;
} psample_netif_t;
extern int
psample_netif_create_cb(int unit, kcom_netif_t *netif, struct net_device *dev);
extern int
psample_netif_destroy_cb(int unit, kcom_netif_t *netif, struct net_device *dev);
#endif /* __PSAMPLE_CB_H__ */

View File

@ -0,0 +1,64 @@
#
# 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.
#
# -*- Makefile -*-
# $Id: Makefile,v 1.3 Broadcom SDK $
# $Copyright: (c) 2005 Broadcom Corp.
# All Rights Reserved.$
#
LOCALDIR = systems/linux/kernel/modules/psample
include ${SDK}/make/Make.config
LIBS = $(LIBDIR)/libkern.a
ifeq ($(kernel_version),2_4)
MODULE = $(LIBDIR)/psample.o
else
KERNEL_MODULE_DIR = kernel_module
THIS_MOD_NAME := psample
MODULE = $(LIBDIR)/$(THIS_MOD_NAME).o
KMODULE = $(LIBDIR)/$(THIS_MOD_NAME).ko
build: $(MODULE) $(KMODULE)
endif
KBUILD_EXTRA_SYMBOLS := ${BLDDIR}/../bcm-knet/kernel_module/Module.symvers
# BCM Network Device
$(MODULE): $(BLDDIR)/.tree $(BOBJS) $(LIBS)
$(LD) $(MODULE_LDFLAGS) -r -d $(BOBJS) $(LIBS) -o $@
ifneq ($(kernel_version),2_4)
$(KMODULE): $(MODULE)
rm -fr $(BLDDIR)/$(KERNEL_MODULE_DIR)
mkdir $(BLDDIR)/$(KERNEL_MODULE_DIR)
cp ${SDK}/make/Makefile.linux-kmodule $(BLDDIR)/$(KERNEL_MODULE_DIR)/Makefile
cat ${KBUILD_EXTRA_SYMBOLS} > $(BLDDIR)/$(KERNEL_MODULE_DIR)/Module.symvers
MOD_NAME=$(THIS_MOD_NAME) $(MAKE) -C $(BLDDIR)/$(KERNEL_MODULE_DIR) $(THIS_MOD_NAME).ko
endif
# Make.depend is before clean:: so that Make.depend's clean:: runs first.
include ${SDK}/make/Make.depend
clean::
$(RM) $(BLDDIR)/version.c $(BLDDIR)/version.o
$(RM) $(BOBJS) $(MODULE)
ifneq ($(kernel_version),2_4)
.PHONY: build
endif

View File

@ -0,0 +1,302 @@
/*
* net/psample/psample.c - Netlink channel for packet sampling
* Copyright (c) 2017 Yotam Gigi <yotamg@mellanox.com>
*
* 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 <gmodule.h>
#include <linux/types.h>
#include <linux/kernel.h>
#include <linux/skbuff.h>
#include <linux/module.h>
#include <net/net_namespace.h>
#include <net/sock.h>
#include <net/netlink.h>
#include <net/genetlink.h>
#include <net/psample.h>
#include <linux/spinlock.h>
#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 __ro_after_init;
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 __ro_after_init = {
.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 + 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 <yotamg@mellanox.com>");
MODULE_DESCRIPTION("netlink channel for packet sampling");
MODULE_LICENSE("GPL v2");

View File

@ -91,6 +91,9 @@ KNET_CB := $(DEST_DIR)/$(KNET_CB_LOCAL)
BCM_KNET_LOCAL :=linux-bcm-knet.$(KOBJ)
BCM_KNET=$(DEST_DIR)/$(BCM_KNET_LOCAL)
PSAMPLE_LOCAL := psample.$(KOBJ)
PSAMPLE := $(DEST_DIR)/$(PSAMPLE_LOCAL)
ifeq (,$(findstring DELIVER,$(MAKECMDGOALS)))
.DEFAULT_GOAL := all
all_targets := kernel_modules $(KERNEL_BDE) $(USER_BDE)
@ -126,6 +129,15 @@ all_targets +=$(LOCAL_TARGETS)
endif
endif
ifdef BUILD_PSAMPLE
all_targets += $(PSAMPLE)
ADD_TO_CFLAGS += -DPSAMPLE_SUPPORT
ifeq ($(NO_LOCAL_TARGETS),)
LOCAL_TARGETS +=$(patsubst %,../$(platform)/%,$(PSAMPLE_LOCAL))
all_targets +=$(LOCAL_TARGETS)
endif
endif
ADD_TO_CFLAGS += -I$(SDK)/systems/linux/kernel/modules/include
COND_KNET_LIBS = libuser.$(libext)
endif
@ -159,6 +171,10 @@ kernel_modules:
ifeq ($(BUILD_KNET),1)
$(MAKE) -j1 -C $(SDK)/systems/linux/kernel/modules kernel_version=$(kernel_version) \
subdirs="shared bcm-knet" override-target=linux-$(platform) CFLAGS="$(CFLAGS)"
ifdef BUILD_PSAMPLE
$(MAKE) -j1 -C $(SDK)/systems/linux/kernel/modules kernel_version=$(kernel_version) \
subdirs="psample" override-target=linux-$(platform) CFLAGS="$(CFLAGS)"
endif
ifdef BUILD_KNET_CB
$(MAKE) -j1 -C $(SDK)/systems/linux/kernel/modules kernel_version=$(kernel_version) \
subdirs="knet-cb" override-target=linux-$(platform) CFLAGS="$(CFLAGS)"
@ -178,6 +194,10 @@ $(BCM_KNET): $(KERN_BLDROOT)/linux-bcm-knet.$(KOBJ)
$(KNET_CB): $(KERN_BLDROOT)/linux-knet-cb.$(KOBJ)
$(OBJCOPY) --strip-debug $< $@
$(PSAMPLE): $(KERN_BLDROOT)/psample.$(KOBJ)
$(OBJCOPY) --strip-debug $< $@
ifeq ($(NO_LOCAL_TARGETS),)
$(foreach targ,$(LOCAL_TARGETS),$(eval $(call LOCAL_TARGET_DEF,$(targ))))
endif
@ -194,6 +214,7 @@ clean::
$(RM) $(KERN_BLDROOT)/linux-user-bde.$(KOBJ)
$(RM) $(KERN_BLDROOT)/linux-bcm-knet.$(KOBJ)
$(RM) $(KERN_BLDROOT)/linux-knet-cb.$(KOBJ)
$(RM) $(KERN_BLDROOT)/psample.$(KOBJ)
$(RM) $(LOCAL_TARGETS)
distclean:: clean

View File

@ -44,7 +44,7 @@ endif
export SDK
override kernel_version=4_4
override kernel_version=4_14
platform=iproc
IPROC_BUILD=1

View File

@ -291,7 +291,9 @@ RUN apt-get update && apt-get install -y \
automake1.11 \
libselinux1-dev \
# For kdump-tools
liblzo2-dev
liblzo2-dev \
# For SAI3.7
libprotobuf-dev
## Config dpkg
## install the configuration file if its currently missing