1#!/bin/bash 2# SPDX-License-Identifier: GPL-2.0 3# Copyright 2020 NXP 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 ip link set $eth0 up 160 ip link set $eth1 up 161 ip link set $eth2 up 162 ip link set $eth3 up 163 164 create_tcam_skeleton $eth0 165 166 ip link add br0 type bridge 167 ip link set $eth0 master br0 168 ip link set $eth1 master br0 169 ip link set br0 up 170 171 ip link add link $eth3 name $eth3.100 type vlan id 100 172 ip link set $eth3.100 up 173 174 ip link add link $eth3 name $eth3.200 type vlan id 200 175 ip link set $eth3.200 up 176 177 tc filter add dev $eth0 ingress chain $(IS1 1) pref 1 \ 178 protocol 802.1Q flower skip_sw vlan_id 100 \ 179 action vlan pop \ 180 action goto chain $(IS1 2) 181 182 tc filter add dev $eth0 egress chain $(ES0) pref 1 \ 183 flower skip_sw indev $eth1 \ 184 action vlan push protocol 802.1Q id 100 185 186 tc filter add dev $eth0 ingress chain $(IS1 0) pref 2 \ 187 protocol ipv4 flower skip_sw src_ip 10.1.1.2 \ 188 action skbedit priority 7 \ 189 action goto chain $(IS1 1) 190 191 tc filter add dev $eth0 ingress chain $(IS2 0 0) pref 1 \ 192 protocol ipv4 flower skip_sw ip_proto udp dst_port 5201 \ 193 action police rate 50mbit burst 64k \ 194 action goto chain $(IS2 1 0) 195} 196 197cleanup() 198{ 199 ip link del $eth3.200 200 ip link del $eth3.100 201 tc qdisc del dev $eth0 clsact 202 ip link del br0 203} 204 205test_vlan_pop() 206{ 207 printf "Testing VLAN pop.. " 208 209 tcpdump_start $eth2 210 211 # Work around Mausezahn VLAN builder bug 212 # (https://github.com/netsniff-ng/netsniff-ng/issues/225) by using 213 # an 8021q upper 214 $MZ $eth3.100 -q -c 1 -p 64 -a $eth3_mac -b $eth2_mac -t ip 215 216 sleep 1 217 218 tcpdump_stop 219 220 if tcpdump_show | grep -q "$eth3_mac > $eth2_mac, ethertype IPv4"; then 221 echo "OK" 222 else 223 echo "FAIL" 224 fi 225 226 tcpdump_cleanup 227} 228 229test_vlan_push() 230{ 231 printf "Testing VLAN push.. " 232 233 tcpdump_start $eth3.100 234 235 $MZ $eth2 -q -c 1 -p 64 -a $eth2_mac -b $eth3_mac -t ip 236 237 sleep 1 238 239 tcpdump_stop 240 241 if tcpdump_show | grep -q "$eth2_mac > $eth3_mac"; then 242 echo "OK" 243 else 244 echo "FAIL" 245 fi 246 247 tcpdump_cleanup 248} 249 250test_vlan_ingress_modify() 251{ 252 printf "Testing ingress VLAN modification.. " 253 254 ip link set br0 type bridge vlan_filtering 1 255 bridge vlan add dev $eth0 vid 200 256 bridge vlan add dev $eth0 vid 300 257 bridge vlan add dev $eth1 vid 300 258 259 tc filter add dev $eth0 ingress chain $(IS1 2) pref 3 \ 260 protocol 802.1Q flower skip_sw vlan_id 200 \ 261 action vlan modify id 300 \ 262 action goto chain $(IS2 0 0) 263 264 tcpdump_start $eth2 265 266 $MZ $eth3.200 -q -c 1 -p 64 -a $eth3_mac -b $eth2_mac -t ip 267 268 sleep 1 269 270 tcpdump_stop 271 272 if tcpdump_show | grep -q "$eth3_mac > $eth2_mac, .* vlan 300"; then 273 echo "OK" 274 else 275 echo "FAIL" 276 fi 277 278 tcpdump_cleanup 279 280 tc filter del dev $eth0 ingress chain $(IS1 2) pref 3 281 282 bridge vlan del dev $eth0 vid 200 283 bridge vlan del dev $eth0 vid 300 284 bridge vlan del dev $eth1 vid 300 285 ip link set br0 type bridge vlan_filtering 0 286} 287 288test_vlan_egress_modify() 289{ 290 printf "Testing egress VLAN modification.. " 291 292 tc qdisc add dev $eth1 clsact 293 294 ip link set br0 type bridge vlan_filtering 1 295 bridge vlan add dev $eth0 vid 200 296 bridge vlan add dev $eth1 vid 200 297 298 tc filter add dev $eth1 egress chain $(ES0) pref 3 \ 299 protocol 802.1Q flower skip_sw vlan_id 200 vlan_prio 0 \ 300 action vlan modify id 300 priority 7 301 302 tcpdump_start $eth2 303 304 $MZ $eth3.200 -q -c 1 -p 64 -a $eth3_mac -b $eth2_mac -t ip 305 306 sleep 1 307 308 tcpdump_stop 309 310 if tcpdump_show | grep -q "$eth3_mac > $eth2_mac, .* vlan 300"; then 311 echo "OK" 312 else 313 echo "FAIL" 314 fi 315 316 tcpdump_cleanup 317 318 tc filter del dev $eth1 egress chain $(ES0) pref 3 319 tc qdisc del dev $eth1 clsact 320 321 bridge vlan del dev $eth0 vid 200 322 bridge vlan del dev $eth1 vid 200 323 ip link set br0 type bridge vlan_filtering 0 324} 325 326test_skbedit_priority() 327{ 328 local num_pkts=100 329 330 printf "Testing frame prioritization.. " 331 332 before=$(ethtool_stats_get $eth0 'rx_green_prio_7') 333 334 $MZ $eth3 -q -c $num_pkts -p 64 -a $eth3_mac -b $eth2_mac -t ip -A 10.1.1.2 335 336 after=$(ethtool_stats_get $eth0 'rx_green_prio_7') 337 338 if [ $((after - before)) = $num_pkts ]; then 339 echo "OK" 340 else 341 echo "FAIL" 342 fi 343} 344 345trap cleanup EXIT 346 347ALL_TESTS=" 348 test_vlan_pop 349 test_vlan_push 350 test_vlan_ingress_modify 351 test_vlan_egress_modify 352 test_skbedit_priority 353" 354 355setup_prepare 356setup_wait 357 358tests_run 359 360exit $EXIT_STATUS 361