1#!/bin/bash 2# SPDX-License-Identifier: GPL-2.0 3# Copyright 2020 NXP Semiconductors 4 5WAIT_TIME=1 6NUM_NETIFS=4 7lib_dir=$(dirname $0)/../../../net/forwarding 8source $lib_dir/tc_common.sh 9source $lib_dir/lib.sh 10 11require_command tcpdump 12 13# 14# +---------------------------------------------+ 15# | DUT ports Generator ports | 16# | +--------+ +--------+ +--------+ +--------+ | 17# | | | | | | | | | | 18# | | eth0 | | eth1 | | eth2 | | eth3 | | 19# | | | | | | | | | | 20# +-+--------+-+--------+-+--------+-+--------+-+ 21# | | | | 22# | | | | 23# | +-----------+ | 24# | | 25# +--------------------------------+ 26 27eth0=${NETIFS[p1]} 28eth1=${NETIFS[p2]} 29eth2=${NETIFS[p3]} 30eth3=${NETIFS[p4]} 31 32eth0_mac="de:ad:be:ef:00:00" 33eth1_mac="de:ad:be:ef:00:01" 34eth2_mac="de:ad:be:ef:00:02" 35eth3_mac="de:ad:be:ef:00:03" 36 37# Helpers to map a VCAP IS1 and VCAP IS2 lookup and policy to a chain number 38# used by the kernel driver. The numbers are: 39# VCAP IS1 lookup 0: 10000 40# VCAP IS1 lookup 1: 11000 41# VCAP IS1 lookup 2: 12000 42# VCAP IS2 lookup 0 policy 0: 20000 43# VCAP IS2 lookup 0 policy 1: 20001 44# VCAP IS2 lookup 0 policy 255: 20255 45# VCAP IS2 lookup 1 policy 0: 21000 46# VCAP IS2 lookup 1 policy 1: 21001 47# VCAP IS2 lookup 1 policy 255: 21255 48IS1() 49{ 50 local lookup=$1 51 52 echo $((10000 + 1000 * lookup)) 53} 54 55IS2() 56{ 57 local lookup=$1 58 local pag=$2 59 60 echo $((20000 + 1000 * lookup + pag)) 61} 62 63ES0() 64{ 65 echo 0 66} 67 68# The Ocelot switches have a fixed ingress pipeline composed of: 69# 70# +----------------------------------------------+ +-----------------------------------------+ 71# | VCAP IS1 | | VCAP IS2 | 72# | | | | 73# | +----------+ +----------+ +----------+ | | +----------+ +----------+ | 74# | | Lookup 0 | | Lookup 1 | | Lookup 2 | | --+------> PAG 0: | Lookup 0 | -> | Lookup 1 | | 75# | +----------+ -> +----------+ -> +----------+ | | | +----------+ +----------+ | 76# | |key&action| |key&action| |key&action| | | | |key&action| |key&action| | 77# | |key&action| |key&action| |key&action| | | | | .. | | .. | | 78# | | .. | | .. | | .. | | | | +----------+ +----------+ | 79# | +----------+ +----------+ +----------+ | | | | 80# | selects PAG | | | +----------+ +----------+ | 81# +----------------------------------------------+ +------> PAG 1: | Lookup 0 | -> | Lookup 1 | | 82# | | +----------+ +----------+ | 83# | | |key&action| |key&action| | 84# | | | .. | | .. | | 85# | | +----------+ +----------+ | 86# | | ... | 87# | | | 88# | | +----------+ +----------+ | 89# +----> PAG 254: | Lookup 0 | -> | Lookup 1 | | 90# | | +----------+ +----------+ | 91# | | |key&action| |key&action| | 92# | | | .. | | .. | | 93# | | +----------+ +----------+ | 94# | | | 95# | | +----------+ +----------+ | 96# +----> PAG 255: | Lookup 0 | -> | Lookup 1 | | 97# | +----------+ +----------+ | 98# | |key&action| |key&action| | 99# | | .. | | .. | | 100# | +----------+ +----------+ | 101# +-----------------------------------------+ 102# 103# Both the VCAP IS1 (Ingress Stage 1) and IS2 (Ingress Stage 2) are indexed 104# (looked up) multiple times: IS1 3 times, and IS2 2 times. Each filter 105# (key and action pair) can be configured to only match during the first, or 106# second, etc, lookup. 107# 108# During one TCAM lookup, the filter processing stops at the first entry that 109# matches, then the pipeline jumps to the next lookup. 110# The driver maps each individual lookup of each individual ingress TCAM to a 111# separate chain number. For correct rule offloading, it is mandatory that each 112# filter installed in one TCAM is terminated by a non-optional GOTO action to 113# the next lookup from the fixed pipeline. 114# 115# A chain can only be used if there is a GOTO action correctly set up from the 116# prior lookup in the processing pipeline. Setting up all chains is not 117# mandatory. 118 119# NOTE: VCAP IS1 currently uses only S1_NORMAL half keys and VCAP IS2 120# dynamically chooses between MAC_ETYPE, ARP, IP4_TCP_UDP, IP4_OTHER, which are 121# all half keys as well. 122 123create_tcam_skeleton() 124{ 125 local eth=$1 126 127 tc qdisc add dev $eth clsact 128 129 # VCAP IS1 is the Ingress Classification TCAM and can offload the 130 # following actions: 131 # - skbedit priority 132 # - vlan pop 133 # - vlan modify 134 # - goto (only in lookup 2, the last IS1 lookup) 135 tc filter add dev $eth ingress chain 0 pref 49152 flower \ 136 skip_sw action goto chain $(IS1 0) 137 tc filter add dev $eth ingress chain $(IS1 0) pref 49152 \ 138 flower skip_sw action goto chain $(IS1 1) 139 tc filter add dev $eth ingress chain $(IS1 1) pref 49152 \ 140 flower skip_sw action goto chain $(IS1 2) 141 tc filter add dev $eth ingress chain $(IS1 2) pref 49152 \ 142 flower skip_sw action goto chain $(IS2 0 0) 143 144 # VCAP IS2 is the Security Enforcement ingress TCAM and can offload the 145 # following actions: 146 # - trap 147 # - drop 148 # - police 149 # The two VCAP IS2 lookups can be segmented into up to 256 groups of 150 # rules, called Policies. A Policy is selected through the Policy 151 # Association Group (PAG) action of VCAP IS1 (which is the 152 # GOTO offload). 153 tc filter add dev $eth ingress chain $(IS2 0 0) pref 49152 \ 154 flower skip_sw action goto chain $(IS2 1 0) 155} 156 157setup_prepare() 158{ 159 create_tcam_skeleton $eth0 160 161 ip link add br0 type bridge 162 ip link set $eth0 master br0 163 ip link set $eth1 master br0 164 ip link set br0 up 165 166 ip link add link $eth3 name $eth3.100 type vlan id 100 167 ip link set $eth3.100 up 168 169 ip link add link $eth3 name $eth3.200 type vlan id 200 170 ip link set $eth3.200 up 171 172 tc filter add dev $eth0 ingress chain $(IS1 1) pref 1 \ 173 protocol 802.1Q flower skip_sw vlan_id 100 \ 174 action vlan pop \ 175 action goto chain $(IS1 2) 176 177 tc filter add dev $eth0 egress chain $(ES0) pref 1 \ 178 flower skip_sw indev $eth1 \ 179 action vlan push protocol 802.1Q id 100 180 181 tc filter add dev $eth0 ingress chain $(IS1 0) pref 2 \ 182 protocol ipv4 flower skip_sw src_ip 10.1.1.2 \ 183 action skbedit priority 7 \ 184 action goto chain $(IS1 1) 185 186 tc filter add dev $eth0 ingress chain $(IS2 0 0) pref 1 \ 187 protocol ipv4 flower skip_sw ip_proto udp dst_port 5201 \ 188 action police rate 50mbit burst 64k \ 189 action goto chain $(IS2 1 0) 190} 191 192cleanup() 193{ 194 ip link del $eth3.200 195 ip link del $eth3.100 196 tc qdisc del dev $eth0 clsact 197 ip link del br0 198} 199 200test_vlan_pop() 201{ 202 printf "Testing VLAN pop.. " 203 204 tcpdump_start $eth2 205 206 # Work around Mausezahn VLAN builder bug 207 # (https://github.com/netsniff-ng/netsniff-ng/issues/225) by using 208 # an 8021q upper 209 $MZ $eth3.100 -q -c 1 -p 64 -a $eth3_mac -b $eth2_mac -t ip 210 211 sleep 1 212 213 tcpdump_stop 214 215 if tcpdump_show | grep -q "$eth3_mac > $eth2_mac, ethertype IPv4"; then 216 echo "OK" 217 else 218 echo "FAIL" 219 fi 220 221 tcpdump_cleanup 222} 223 224test_vlan_push() 225{ 226 printf "Testing VLAN push.. " 227 228 tcpdump_start $eth3.100 229 230 $MZ $eth2 -q -c 1 -p 64 -a $eth2_mac -b $eth3_mac -t ip 231 232 sleep 1 233 234 tcpdump_stop 235 236 if tcpdump_show | grep -q "$eth2_mac > $eth3_mac"; then 237 echo "OK" 238 else 239 echo "FAIL" 240 fi 241 242 tcpdump_cleanup 243} 244 245test_vlan_modify() 246{ 247 printf "Testing VLAN modification.. " 248 249 ip link set br0 type bridge vlan_filtering 1 250 bridge vlan add dev $eth0 vid 200 251 bridge vlan add dev $eth0 vid 300 252 bridge vlan add dev $eth1 vid 300 253 254 tc filter add dev $eth0 ingress chain $(IS1 2) pref 3 \ 255 protocol 802.1Q flower skip_sw vlan_id 200 \ 256 action vlan modify id 300 \ 257 action goto chain $(IS2 0 0) 258 259 tcpdump_start $eth2 260 261 $MZ $eth3.200 -q -c 1 -p 64 -a $eth3_mac -b $eth2_mac -t ip 262 263 sleep 1 264 265 tcpdump_stop 266 267 if tcpdump_show | grep -q "$eth3_mac > $eth2_mac, .* vlan 300"; then 268 echo "OK" 269 else 270 echo "FAIL" 271 fi 272 273 tcpdump_cleanup 274 275 tc filter del dev $eth0 ingress chain $(IS1 2) pref 3 276 277 bridge vlan del dev $eth0 vid 200 278 bridge vlan del dev $eth0 vid 300 279 bridge vlan del dev $eth1 vid 300 280 ip link set br0 type bridge vlan_filtering 0 281} 282 283test_skbedit_priority() 284{ 285 local num_pkts=100 286 287 printf "Testing frame prioritization.. " 288 289 before=$(ethtool_stats_get $eth0 'rx_green_prio_7') 290 291 $MZ $eth3 -q -c $num_pkts -p 64 -a $eth3_mac -b $eth2_mac -t ip -A 10.1.1.2 292 293 after=$(ethtool_stats_get $eth0 'rx_green_prio_7') 294 295 if [ $((after - before)) = $num_pkts ]; then 296 echo "OK" 297 else 298 echo "FAIL" 299 fi 300} 301 302trap cleanup EXIT 303 304ALL_TESTS=" 305 test_vlan_pop 306 test_vlan_push 307 test_vlan_modify 308 test_skbedit_priority 309" 310 311setup_prepare 312setup_wait 313 314tests_run 315 316exit $EXIT_STATUS 317