1 /* 2 * Copyright (C) 2023 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 package android.net.apf 17 18 import android.net.apf.ApfCounterTracker.Counter 19 import android.net.apf.ApfCounterTracker.Counter.CORRUPT_DNS_PACKET 20 import android.net.apf.ApfCounterTracker.Counter.DROPPED_ETHERTYPE_NOT_ALLOWED 21 import android.net.apf.ApfCounterTracker.Counter.DROPPED_ETH_BROADCAST 22 import android.net.apf.ApfCounterTracker.Counter.DROPPED_RA 23 import android.net.apf.ApfCounterTracker.Counter.PASSED_ALLOCATE_FAILURE 24 import android.net.apf.ApfCounterTracker.Counter.PASSED_ARP_REQUEST 25 import android.net.apf.ApfCounterTracker.Counter.PASSED_MDNS 26 import android.net.apf.ApfCounterTracker.Counter.PASSED_TRANSMIT_FAILURE 27 import android.net.apf.ApfCounterTracker.Counter.TOTAL_PACKETS 28 import android.net.apf.ApfTestHelpers.Companion.DROP 29 import android.net.apf.ApfTestHelpers.Companion.MIN_PKT_SIZE 30 import android.net.apf.ApfTestHelpers.Companion.PASS 31 import android.net.apf.ApfTestHelpers.Companion.decodeCountersIntoMap 32 import android.net.apf.BaseApfGenerator.APF_VERSION_2 33 import android.net.apf.BaseApfGenerator.APF_VERSION_3 34 import android.net.apf.BaseApfGenerator.DROP_LABEL 35 import android.net.apf.BaseApfGenerator.IllegalInstructionException 36 import android.net.apf.BaseApfGenerator.MemorySlot 37 import android.net.apf.BaseApfGenerator.PASS_LABEL 38 import android.net.apf.BaseApfGenerator.Register.R0 39 import android.net.apf.BaseApfGenerator.Register.R1 40 import androidx.test.filters.SmallTest 41 import com.android.net.module.util.HexDump 42 import com.android.net.module.util.Struct 43 import com.android.net.module.util.structs.EthernetHeader 44 import com.android.net.module.util.structs.Ipv4Header 45 import com.android.net.module.util.structs.UdpHeader 46 import com.android.testutils.DevSdkIgnoreRule 47 import com.android.testutils.DevSdkIgnoreRunner 48 import java.nio.ByteBuffer 49 import kotlin.test.assertContentEquals 50 import kotlin.test.assertEquals 51 import kotlin.test.assertFailsWith 52 import org.junit.After 53 import org.junit.Assume.assumeTrue 54 import org.junit.Before 55 import org.junit.Rule 56 import org.junit.Test 57 import org.junit.runner.RunWith 58 import org.junit.runners.Parameterized 59 60 const val ETH_HLEN = 14 61 const val IPV4_HLEN = 20 62 const val IPPROTO_UDP = 17 63 64 /** 65 * Tests for APF generator instructions. 66 */ 67 @RunWith(DevSdkIgnoreRunner::class) 68 @SmallTest 69 class ApfGeneratorTest { 70 71 companion object { 72 @Parameterized.Parameters 73 @JvmStatic datanull74 fun data(): Iterable<Any?> { 75 return mutableListOf<Int?>( 76 ApfJniUtils.APF_INTERPRETER_VERSION_V6, 77 ApfJniUtils.APF_INTERPRETER_VERSION_NEXT 78 ) 79 } 80 } 81 82 @get:Rule val ignoreRule = DevSdkIgnoreRule() 83 84 // Indicates which apfInterpreter to load. 85 @Parameterized.Parameter(0) 86 @JvmField 87 var apfInterpreterVersion: Int = ApfJniUtils.APF_INTERPRETER_VERSION_NEXT 88 89 private val ramSize = 2048 90 private val clampSize = 2048 91 92 private val testPacket = byteArrayOf(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16) 93 private lateinit var apfTestHelpers: ApfTestHelpers 94 95 @Before setUpnull96 fun setUp() { 97 apfTestHelpers = ApfTestHelpers(apfInterpreterVersion) 98 } 99 100 @After tearDownnull101 fun tearDown() { 102 apfTestHelpers.resetTransmittedPacketMemory() 103 } 104 105 @Test testDataInstructionMustComeFirstnull106 fun testDataInstructionMustComeFirst() { 107 var gen = ApfV6Generator(apfInterpreterVersion, ramSize, clampSize) 108 gen.addAllocateR0() 109 assertFailsWith<IllegalInstructionException> { gen.addData(ByteArray(3) { 0x01 }) } 110 } 111 112 @Test testApfInstructionEncodingSizeChecknull113 fun testApfInstructionEncodingSizeCheck() { 114 var gen = ApfV6Generator(apfInterpreterVersion, ramSize, clampSize) 115 assertFailsWith<IllegalArgumentException> { 116 ApfV6Generator(ByteArray(65536) { 0x01 }, apfInterpreterVersion, ramSize, clampSize) 117 } 118 assertFailsWith<IllegalArgumentException> { gen.addAllocate(65536) } 119 assertFailsWith<IllegalArgumentException> { gen.addAllocate(-1) } 120 assertFailsWith<IllegalArgumentException> { gen.addDataCopy(-1, 1) } 121 assertFailsWith<IllegalArgumentException> { gen.addPacketCopy(-1, 1) } 122 assertFailsWith<IllegalArgumentException> { gen.addDataCopy(1, 256) } 123 assertFailsWith<IllegalArgumentException> { gen.addPacketCopy(1, 256) } 124 assertFailsWith<IllegalArgumentException> { gen.addDataCopy(1, -1) } 125 assertFailsWith<IllegalArgumentException> { gen.addPacketCopy(1, -1) } 126 assertFailsWith<IllegalArgumentException> { gen.addPacketCopyFromR0(256) } 127 assertFailsWith<IllegalArgumentException> { gen.addDataCopyFromR0(256) } 128 assertFailsWith<IllegalArgumentException> { gen.addPacketCopyFromR0(-1) } 129 assertFailsWith<IllegalArgumentException> { gen.addDataCopyFromR0(-1) } 130 assertFailsWith<IllegalArgumentException> { gen.addJumpIfPktAtR0DoesNotContainDnsQ( 131 byteArrayOf(1, 'A'.code.toByte(), 0, 0), 132 256, 133 ApfV4Generator.DROP_LABEL 134 ) } 135 assertFailsWith<IllegalArgumentException> { gen.addJumpIfPktAtR0DoesNotContainDnsQ( 136 byteArrayOf(1, 'a'.code.toByte(), 0, 0), 137 0x0c, 138 ApfV4Generator.DROP_LABEL 139 ) } 140 assertFailsWith<IllegalArgumentException> { gen.addJumpIfPktAtR0DoesNotContainDnsQ( 141 byteArrayOf(1, '.'.code.toByte(), 0, 0), 142 0x0c, 143 ApfV4Generator.DROP_LABEL 144 ) } 145 assertFailsWith<IllegalArgumentException> { gen.addJumpIfPktAtR0DoesNotContainDnsQ( 146 byteArrayOf(0, 0), 147 0xc0, 148 ApfV4Generator.DROP_LABEL 149 ) } 150 assertFailsWith<IllegalArgumentException> { gen.addJumpIfPktAtR0DoesNotContainDnsQ( 151 byteArrayOf(1, 'A'.code.toByte()), 152 0xc0, 153 ApfV4Generator.DROP_LABEL 154 ) } 155 assertFailsWith<IllegalArgumentException> { gen.addJumpIfPktAtR0DoesNotContainDnsQ( 156 byteArrayOf(64) + ByteArray(64) { 'A'.code.toByte() } + byteArrayOf(0, 0), 157 0xc0, 158 ApfV4Generator.DROP_LABEL 159 ) } 160 assertFailsWith<IllegalArgumentException> { gen.addJumpIfPktAtR0DoesNotContainDnsQ( 161 byteArrayOf(1, 'A'.code.toByte(), 1, 'B'.code.toByte(), 0), 162 0xc0, 163 ApfV4Generator.DROP_LABEL 164 ) } 165 assertFailsWith<IllegalArgumentException> { gen.addJumpIfPktAtR0DoesNotContainDnsQ( 166 byteArrayOf(1, 'A'.code.toByte(), 1, 'B'.code.toByte()), 167 0xc0, 168 ApfV4Generator.DROP_LABEL 169 ) } 170 assertFailsWith<IllegalArgumentException> { gen.addJumpIfPktAtR0ContainDnsQ( 171 byteArrayOf(1, 'A'.code.toByte(), 0, 0), 172 256, 173 ApfV4Generator.DROP_LABEL 174 ) } 175 assertFailsWith<IllegalArgumentException> { gen.addJumpIfPktAtR0ContainDnsQ( 176 byteArrayOf(1, 'a'.code.toByte(), 0, 0), 177 0x0c, 178 ApfV4Generator.DROP_LABEL 179 ) } 180 assertFailsWith<IllegalArgumentException> { gen.addJumpIfPktAtR0ContainDnsQ( 181 byteArrayOf(1, '.'.code.toByte(), 0, 0), 182 0x0c, 183 ApfV4Generator.DROP_LABEL 184 ) } 185 assertFailsWith<IllegalArgumentException> { gen.addJumpIfPktAtR0ContainDnsQ( 186 byteArrayOf(0, 0), 187 0xc0, 188 ApfV4Generator.DROP_LABEL 189 ) } 190 assertFailsWith<IllegalArgumentException> { gen.addJumpIfPktAtR0ContainDnsQ( 191 byteArrayOf(1, 'A'.code.toByte()), 192 0xc0, 193 ApfV4Generator.DROP_LABEL 194 ) } 195 assertFailsWith<IllegalArgumentException> { gen.addJumpIfPktAtR0ContainDnsQ( 196 byteArrayOf(64) + ByteArray(64) { 'A'.code.toByte() } + byteArrayOf(0, 0), 197 0xc0, 198 ApfV4Generator.DROP_LABEL 199 ) } 200 assertFailsWith<IllegalArgumentException> { gen.addJumpIfPktAtR0ContainDnsQ( 201 byteArrayOf(1, 'A'.code.toByte(), 1, 'B'.code.toByte(), 0), 202 0xc0, 203 ApfV4Generator.DROP_LABEL 204 ) } 205 assertFailsWith<IllegalArgumentException> { gen.addJumpIfPktAtR0ContainDnsQ( 206 byteArrayOf(1, 'A'.code.toByte(), 1, 'B'.code.toByte()), 207 0xc0, 208 ApfV4Generator.DROP_LABEL 209 ) } 210 assertFailsWith<IllegalArgumentException> { gen.addJumpIfPktAtR0DoesNotContainDnsA( 211 byteArrayOf(1, 'a'.code.toByte(), 0, 0), 212 ApfV4Generator.DROP_LABEL 213 ) } 214 assertFailsWith<IllegalArgumentException> { gen.addJumpIfPktAtR0DoesNotContainDnsA( 215 byteArrayOf(1, '.'.code.toByte(), 0, 0), 216 ApfV4Generator.DROP_LABEL 217 ) } 218 assertFailsWith<IllegalArgumentException> { gen.addJumpIfPktAtR0DoesNotContainDnsA( 219 byteArrayOf(0, 0), 220 ApfV4Generator.DROP_LABEL 221 ) } 222 assertFailsWith<IllegalArgumentException> { gen.addJumpIfPktAtR0DoesNotContainDnsA( 223 byteArrayOf(1, 'A'.code.toByte()), 224 ApfV4Generator.DROP_LABEL 225 ) } 226 assertFailsWith<IllegalArgumentException> { gen.addJumpIfPktAtR0DoesNotContainDnsA( 227 byteArrayOf(64) + ByteArray(64) { 'A'.code.toByte() } + byteArrayOf(0, 0), 228 ApfV4Generator.DROP_LABEL 229 ) } 230 assertFailsWith<IllegalArgumentException> { gen.addJumpIfPktAtR0DoesNotContainDnsA( 231 byteArrayOf(1, 'A'.code.toByte(), 1, 'B'.code.toByte(), 0), 232 ApfV4Generator.DROP_LABEL 233 ) } 234 assertFailsWith<IllegalArgumentException> { gen.addJumpIfPktAtR0DoesNotContainDnsA( 235 byteArrayOf(1, 'A'.code.toByte(), 1, 'B'.code.toByte()), 236 ApfV4Generator.DROP_LABEL 237 ) } 238 assertFailsWith<IllegalArgumentException> { gen.addJumpIfPktAtR0ContainDnsA( 239 byteArrayOf(1, 'a'.code.toByte(), 0, 0), 240 ApfV4Generator.DROP_LABEL 241 ) } 242 assertFailsWith<IllegalArgumentException> { gen.addJumpIfPktAtR0ContainDnsA( 243 byteArrayOf(1, '.'.code.toByte(), 0, 0), 244 ApfV4Generator.DROP_LABEL 245 ) } 246 assertFailsWith<IllegalArgumentException> { gen.addJumpIfPktAtR0ContainDnsA( 247 byteArrayOf(0, 0), 248 ApfV4Generator.DROP_LABEL 249 ) } 250 assertFailsWith<IllegalArgumentException> { gen.addJumpIfPktAtR0ContainDnsA( 251 byteArrayOf(1, 'A'.code.toByte()), 252 ApfV4Generator.DROP_LABEL 253 ) } 254 assertFailsWith<IllegalArgumentException> { gen.addJumpIfPktAtR0ContainDnsA( 255 byteArrayOf(64) + ByteArray(64) { 'A'.code.toByte() } + byteArrayOf(0, 0), 256 ApfV4Generator.DROP_LABEL 257 ) } 258 assertFailsWith<IllegalArgumentException> { gen.addJumpIfPktAtR0ContainDnsA( 259 byteArrayOf(1, 'A'.code.toByte(), 1, 'B'.code.toByte(), 0), 260 ApfV4Generator.DROP_LABEL 261 ) } 262 assertFailsWith<IllegalArgumentException> { gen.addJumpIfPktAtR0ContainDnsA( 263 byteArrayOf(1, 'A'.code.toByte(), 1, 'B'.code.toByte()), 264 ApfV4Generator.DROP_LABEL 265 ) } 266 assertFailsWith<IllegalArgumentException> { 267 gen.addJumpIfBytesAtR0Equal(ByteArray(2048) { 1 }, DROP_LABEL) 268 } 269 assertFailsWith<IllegalArgumentException> { 270 gen.addJumpIfBytesAtR0NotEqual(ByteArray(2048) { 1 }, DROP_LABEL) 271 } 272 assertFailsWith<IllegalArgumentException> { gen.addCountAndDrop(PASSED_ARP_REQUEST) } 273 assertFailsWith<IllegalArgumentException> { gen.addCountAndPass(DROPPED_ETH_BROADCAST) } 274 assertFailsWith<IllegalArgumentException> { 275 gen.addCountAndDropIfR0Equals(3, PASSED_ARP_REQUEST) 276 } 277 assertFailsWith<IllegalArgumentException> { 278 gen.addCountAndPassIfR0Equals(3, DROPPED_ETH_BROADCAST) 279 } 280 assertFailsWith<IllegalArgumentException> { 281 gen.addCountAndDropIfR0NotEquals(3, PASSED_ARP_REQUEST) 282 } 283 assertFailsWith<IllegalArgumentException> { 284 gen.addCountAndPassIfR0NotEquals(3, DROPPED_ETH_BROADCAST) 285 } 286 assertFailsWith<IllegalArgumentException> { 287 gen.addCountAndDropIfR0LessThan(3, PASSED_ARP_REQUEST) 288 } 289 assertFailsWith<IllegalArgumentException> { 290 gen.addCountAndPassIfR0LessThan(3, DROPPED_ETH_BROADCAST) 291 } 292 assertFailsWith<IllegalArgumentException> { 293 gen.addCountAndDropIfR0GreaterThan(3, PASSED_ARP_REQUEST) 294 } 295 assertFailsWith<IllegalArgumentException> { 296 gen.addCountAndPassIfR0GreaterThan(3, DROPPED_ETH_BROADCAST) 297 } 298 assertFailsWith<IllegalArgumentException> { 299 gen.addCountAndDropIfBytesAtR0NotEqual(byteArrayOf(1), PASSED_ARP_REQUEST) 300 } 301 assertFailsWith<IllegalArgumentException> { 302 gen.addCountAndDropIfBytesAtR0Equal(byteArrayOf(1), PASSED_ARP_REQUEST) 303 } 304 assertFailsWith<IllegalArgumentException> { 305 gen.addCountAndPassIfBytesAtR0Equal(byteArrayOf(1), DROPPED_ETH_BROADCAST) 306 } 307 assertFailsWith<IllegalArgumentException> { 308 gen.addCountAndDropIfR0AnyBitsSet(3, PASSED_ARP_REQUEST) 309 } 310 assertFailsWith<IllegalArgumentException> { 311 gen.addCountAndPassIfR0AnyBitsSet(3, DROPPED_ETH_BROADCAST) 312 } 313 assertFailsWith<IllegalArgumentException> { 314 gen.addCountAndDropIfR0IsOneOf(setOf(3), PASSED_ARP_REQUEST) 315 } 316 assertFailsWith<IllegalArgumentException> { 317 gen.addCountAndPassIfR0IsOneOf(setOf(3), DROPPED_ETH_BROADCAST) 318 } 319 assertFailsWith<IllegalArgumentException> { 320 gen.addCountAndDropIfR0IsNoneOf(setOf(3), PASSED_ARP_REQUEST) 321 } 322 assertFailsWith<IllegalArgumentException> { 323 gen.addCountAndPassIfR0IsNoneOf(setOf(3), DROPPED_ETH_BROADCAST) 324 } 325 assertFailsWith<IllegalArgumentException> { 326 gen.addCountAndDropIfBytesAtR0EqualsAnyOf(listOf(byteArrayOf(1)), PASSED_ARP_REQUEST) 327 } 328 assertFailsWith<IllegalArgumentException> { 329 gen.addCountAndPassIfBytesAtR0EqualsAnyOf(listOf(byteArrayOf(1)), DROPPED_ETH_BROADCAST) 330 } 331 assertFailsWith<IllegalArgumentException> { 332 gen.addCountAndDropIfBytesAtR0EqualsNoneOf(listOf(byteArrayOf(1)), PASSED_ARP_REQUEST) 333 } 334 assertFailsWith<IllegalArgumentException> { 335 gen.addCountAndPassIfBytesAtR0EqualsNoneOf( 336 listOf(byteArrayOf(1)), 337 DROPPED_ETH_BROADCAST 338 ) 339 } 340 assertFailsWith<IllegalArgumentException> { 341 gen.addWrite32(byteArrayOf()) 342 } 343 assertFailsWith<IllegalArgumentException> { 344 gen.addJumpIfOneOf(R0, setOf(), PASS_LABEL) 345 } 346 assertFailsWith<IllegalArgumentException> { 347 gen.addJumpIfOneOf(R0, setOf(-1, 1), PASS_LABEL) 348 } 349 assertFailsWith<IllegalArgumentException> { 350 gen.addJumpIfOneOf(R0, setOf(4294967296L, 1), PASS_LABEL) 351 } 352 assertFailsWith<IllegalArgumentException> { 353 gen.addJumpIfOneOf(R0, List(34) { (it + 1).toLong() }.toSet(), PASS_LABEL) 354 } 355 assertFailsWith<IllegalArgumentException> { 356 gen.addJumpIfBytesAtR0EqualsAnyOf(listOf(ByteArray(2048) { 1 }), PASS_LABEL ) 357 } 358 assertFailsWith<IllegalArgumentException> { 359 gen.addJumpIfBytesAtR0EqualsAnyOf( 360 listOf(byteArrayOf(1), byteArrayOf(1, 2)), 361 PASS_LABEL 362 ) 363 } 364 365 val v4gen = ApfV4Generator(APF_VERSION_3, ramSize, clampSize) 366 assertFailsWith<IllegalArgumentException> { v4gen.addCountAndDrop(PASSED_ARP_REQUEST) } 367 assertFailsWith<IllegalArgumentException> { v4gen.addCountAndPass(DROPPED_ETH_BROADCAST) } 368 assertFailsWith<IllegalArgumentException> { 369 v4gen.addCountAndDropIfR0Equals(3, PASSED_ARP_REQUEST) 370 } 371 assertFailsWith<IllegalArgumentException> { 372 v4gen.addCountAndPassIfR0Equals(3, DROPPED_ETH_BROADCAST) 373 } 374 assertFailsWith<IllegalArgumentException> { 375 v4gen.addCountAndDropIfR0NotEquals(3, PASSED_ARP_REQUEST) 376 } 377 assertFailsWith<IllegalArgumentException> { 378 v4gen.addCountAndPassIfR0NotEquals(3, DROPPED_ETH_BROADCAST) 379 } 380 assertFailsWith<IllegalArgumentException> { 381 v4gen.addCountAndDropIfBytesAtR0Equal(byteArrayOf(1), PASSED_ARP_REQUEST) 382 } 383 assertFailsWith<IllegalArgumentException> { 384 v4gen.addCountAndPassIfBytesAtR0Equal(byteArrayOf(1), DROPPED_ETH_BROADCAST) 385 } 386 assertFailsWith<IllegalArgumentException> { 387 v4gen.addCountAndDropIfR0LessThan(3, PASSED_ARP_REQUEST) 388 } 389 assertFailsWith<IllegalArgumentException> { 390 v4gen.addCountAndPassIfR0LessThan(3, DROPPED_ETH_BROADCAST) 391 } 392 assertFailsWith<IllegalArgumentException> { 393 v4gen.addCountAndDropIfR0GreaterThan(3, PASSED_ARP_REQUEST) 394 } 395 assertFailsWith<IllegalArgumentException> { 396 v4gen.addCountAndPassIfR0GreaterThan(3, DROPPED_ETH_BROADCAST) 397 } 398 assertFailsWith<IllegalArgumentException> { 399 v4gen.addCountAndDropIfBytesAtR0NotEqual(byteArrayOf(1), PASSED_ARP_REQUEST) 400 } 401 assertFailsWith<IllegalArgumentException> { 402 v4gen.addCountAndDropIfR0AnyBitsSet(3, PASSED_ARP_REQUEST) 403 } 404 assertFailsWith<IllegalArgumentException> { 405 v4gen.addCountAndPassIfR0AnyBitsSet(3, DROPPED_ETH_BROADCAST) 406 } 407 assertFailsWith<IllegalArgumentException> { 408 v4gen.addCountAndDropIfR0IsOneOf(setOf(3), PASSED_ARP_REQUEST) 409 } 410 assertFailsWith<IllegalArgumentException> { 411 v4gen.addCountAndPassIfR0IsOneOf(setOf(3), DROPPED_ETH_BROADCAST) 412 } 413 assertFailsWith<IllegalArgumentException> { 414 v4gen.addCountAndDropIfR0IsNoneOf(setOf(3), PASSED_ARP_REQUEST) 415 } 416 assertFailsWith<IllegalArgumentException> { 417 v4gen.addCountAndPassIfR0IsNoneOf(setOf(3), DROPPED_ETH_BROADCAST) 418 } 419 assertFailsWith<IllegalArgumentException> { 420 v4gen.addCountAndDropIfBytesAtR0EqualsAnyOf(listOf(byteArrayOf(1)), PASSED_ARP_REQUEST) 421 } 422 assertFailsWith<IllegalArgumentException> { 423 v4gen.addCountAndPassIfBytesAtR0EqualsAnyOf( 424 listOf(byteArrayOf(1)), 425 DROPPED_ETH_BROADCAST 426 ) 427 } 428 assertFailsWith<IllegalArgumentException> { 429 v4gen.addCountAndDropIfBytesAtR0EqualsNoneOf(listOf(byteArrayOf(1)), PASSED_ARP_REQUEST) 430 } 431 assertFailsWith<IllegalArgumentException> { 432 v4gen.addCountAndPassIfBytesAtR0EqualsNoneOf( 433 listOf(byteArrayOf(1)), 434 DROPPED_ETH_BROADCAST 435 ) 436 } 437 } 438 439 @Test testValidateDnsNamesnull440 fun testValidateDnsNames() { 441 // '%' is a valid label character in mDNS subtype 442 // byte == 0xff means it is a '*' wildcard, which is a valid encoding. 443 val program = ApfV6Generator(ramSize, ramSize, clampSize).addJumpIfPktAtR0ContainDnsQ( 444 byteArrayOf(1, '%'.code.toByte(), 0, 0), 445 1, 446 DROP_LABEL 447 ).addJumpIfPktAtR0ContainDnsA( 448 byteArrayOf(0xff.toByte(), 1, 'B'.code.toByte(), 0, 0), 449 DROP_LABEL 450 ).generate() 451 } 452 453 @Test testApfInstructionsEncodingnull454 fun testApfInstructionsEncoding() { 455 val v4gen = ApfV4Generator(APF_VERSION_2, ramSize, clampSize) 456 v4gen.addPass() 457 var program = v4gen.generate() 458 // encoding PASS opcode: opcode=0, imm_len=0, R=0 459 assertContentEquals( 460 byteArrayOf(encodeInstruction(opcode = 0, immLength = 0, register = 0)), 461 program 462 ) 463 assertContentEquals( 464 listOf("0: pass"), 465 apfTestHelpers.disassembleApf(program).map { it.trim() } 466 ) 467 468 var gen = ApfV6Generator(apfInterpreterVersion, ramSize, clampSize) 469 gen.addDrop() 470 program = gen.generate().skipDataAndDebug() 471 // encoding DROP opcode: opcode=0, imm_len=0, R=1 472 assertContentEquals( 473 byteArrayOf(encodeInstruction(opcode = 0, immLength = 0, register = 1)), 474 program 475 ) 476 assertContentEquals( 477 listOf("0: drop"), 478 apfTestHelpers.disassembleApf(program).map { it.trim() } 479 ) 480 481 gen = ApfV6Generator(apfInterpreterVersion, ramSize, clampSize) 482 gen.addCountAndPass(129) 483 program = gen.generate().skipDataAndDebug() 484 // encoding COUNT(PASS) opcode: opcode=0, imm_len=size_of(imm), R=0, imm=counterNumber 485 assertContentEquals( 486 byteArrayOf( 487 encodeInstruction(opcode = 0, immLength = 1, register = 0), 488 0x81.toByte() 489 ), 490 program 491 ) 492 assertContentEquals( 493 listOf("0: pass counter=129"), 494 apfTestHelpers.disassembleApf(program).map { it.trim() } 495 ) 496 497 gen = ApfV6Generator(apfInterpreterVersion, ramSize, clampSize) 498 gen.addCountAndDrop(1000) 499 program = gen.generate().skipDataAndDebug() 500 // encoding COUNT(DROP) opcode: opcode=0, imm_len=size_of(imm), R=1, imm=counterNumber 501 assertContentEquals( 502 byteArrayOf( 503 encodeInstruction(opcode = 0, immLength = 2, register = 1), 504 0x03, 505 0xe8.toByte() 506 ), 507 program 508 ) 509 assertContentEquals( 510 listOf("0: drop counter=1000"), 511 apfTestHelpers.disassembleApf(program).map { it.trim() } 512 ) 513 514 gen = ApfV6Generator(apfInterpreterVersion, ramSize, clampSize) 515 gen.addCountAndPass(PASSED_ARP_REQUEST) 516 program = gen.generate().skipDataAndDebug() 517 // encoding COUNT(PASS) opcode: opcode=0, imm_len=size_of(imm), R=0, imm=counterNumber 518 assertContentEquals( 519 byteArrayOf( 520 encodeInstruction(opcode = 0, immLength = 1, register = 0), 521 PASSED_ARP_REQUEST.value().toByte() 522 ), 523 program 524 ) 525 val expectedCounterValue1 = PASSED_ARP_REQUEST.value() 526 assertContentEquals( 527 listOf("0: pass counter=$expectedCounterValue1"), 528 apfTestHelpers.disassembleApf(program).map { it.trim() } 529 ) 530 531 gen = ApfV6Generator(apfInterpreterVersion, ramSize, clampSize) 532 gen.addCountAndDrop(DROPPED_ETHERTYPE_NOT_ALLOWED) 533 program = gen.generate().skipDataAndDebug() 534 // encoding COUNT(DROP) opcode: opcode=0, imm_len=size_of(imm), R=1, imm=counterNumber 535 assertContentEquals( 536 byteArrayOf( 537 encodeInstruction(opcode = 0, immLength = 1, register = 1), 538 DROPPED_ETHERTYPE_NOT_ALLOWED.value().toByte() 539 ), 540 program 541 ) 542 val expectedCounterValue2 = DROPPED_ETHERTYPE_NOT_ALLOWED.value() 543 assertContentEquals( 544 listOf("0: drop counter=$expectedCounterValue2"), 545 apfTestHelpers.disassembleApf(program).map { it.trim() } 546 ) 547 548 gen = ApfV6Generator(apfInterpreterVersion, ramSize, clampSize) 549 gen.addAllocateR0() 550 gen.addAllocate(1500) 551 program = gen.generate().skipDataAndDebug() 552 // encoding ALLOC opcode: opcode=21(EXT opcode number), imm=36(TRANS opcode number). 553 // R=0 means length stored in R0. R=1 means the length stored in imm1. 554 assertContentEquals( 555 byteArrayOf( 556 encodeInstruction(opcode = 21, immLength = 1, register = 0), 557 36, 558 encodeInstruction(opcode = 21, immLength = 1, register = 1), 559 36, 560 0x05, 561 0xDC.toByte() 562 ), 563 program 564 ) 565 assertContentEquals(listOf( 566 "0: allocate r0", 567 "2: allocate 1500" 568 ), apfTestHelpers.disassembleApf(program).map { it.trim() }) 569 570 gen = ApfV6Generator(apfInterpreterVersion, ramSize, clampSize) 571 gen.addTransmitWithoutChecksum() 572 gen.addTransmitL4(30, 40, 50, 256, true) 573 program = gen.generate().skipDataAndDebug() 574 // encoding TRANSMIT opcode: opcode=21(EXT opcode number), 575 // imm=37(TRANSMIT opcode number), 576 assertContentEquals(byteArrayOf( 577 encodeInstruction(opcode = 21, immLength = 1, register = 0), 578 37, 255.toByte(), 255.toByte(), 579 encodeInstruction(opcode = 21, immLength = 1, register = 1), 37, 30, 40, 50, 1, 0 580 ), program) 581 assertContentEquals(listOf( 582 "0: transmit ip_ofs=255", 583 "4: transmitudp ip_ofs=30, csum_ofs=40, csum_start=50, partial_csum=0x0100", 584 ), apfTestHelpers.disassembleApf(program).map { it.trim() }) 585 586 val largeByteArray = ByteArray(256) { 0x01 } 587 gen = ApfV6Generator(largeByteArray, apfInterpreterVersion, ramSize, clampSize) 588 program = gen.generate() 589 val debugBufferSize = ramSize - program.size - Counter.totalSize() 590 assertContentEquals( 591 byteArrayOf( 592 encodeInstruction(opcode = 14, immLength = 2, register = 1), 1, 0 593 ) + largeByteArray + byteArrayOf( 594 encodeInstruction(opcode = 21, immLength = 1, register = 0), 595 48, (debugBufferSize shr 8).toByte(), debugBufferSize.toByte() 596 ), 597 program 598 ) 599 assertContentEquals( 600 listOf( 601 "0: data 256, " + "01".repeat(256), 602 "259: debugbuf size=$debugBufferSize" 603 ), 604 apfTestHelpers.disassembleApf(program).map { it.trim() } 605 ) 606 607 gen = ApfV6Generator(apfInterpreterVersion, ramSize, clampSize) 608 gen.addWriteU8(0x01) 609 gen.addWriteU16(0x0102) 610 gen.addWriteU32(0x01020304) 611 gen.addWriteU8(0x00) 612 gen.addWriteU8(0x80) 613 gen.addWriteU16(0x0000) 614 gen.addWriteU16(0x8000) 615 gen.addWriteU32(0x00000000) 616 gen.addWriteU32(0x80000000) 617 gen.addWrite32(-2) 618 gen.addWrite32(byteArrayOf(0xff.toByte(), 0xfe.toByte(), 0xfd.toByte(), 0xfc.toByte())) 619 program = gen.generate().skipDataAndDebug() 620 assertContentEquals(byteArrayOf( 621 encodeInstruction(24, 1, 0), 0x01, 622 encodeInstruction(24, 2, 0), 0x01, 0x02, 623 encodeInstruction(24, 4, 0), 0x01, 0x02, 0x03, 0x04, 624 encodeInstruction(24, 1, 0), 0x00, 625 encodeInstruction(24, 1, 0), 0x80.toByte(), 626 encodeInstruction(24, 2, 0), 0x00, 0x00, 627 encodeInstruction(24, 2, 0), 0x80.toByte(), 0x00, 628 encodeInstruction(24, 4, 0), 0x00, 0x00, 0x00, 0x00, 629 encodeInstruction(24, 4, 0), 0x80.toByte(), 0x00, 0x00, 0x00, 630 encodeInstruction(24, 4, 0), 0xff.toByte(), 0xff.toByte(), 631 0xff.toByte(), 0xfe.toByte(), 632 encodeInstruction(24, 4, 0), 0xff.toByte(), 0xfe.toByte(), 633 0xfd.toByte(), 0xfc.toByte()), program) 634 assertContentEquals(listOf( 635 "0: write 0x01", 636 "2: write 0x0102", 637 "5: write 0x01020304", 638 "10: write 0x00", 639 "12: write 0x80", 640 "14: write 0x0000", 641 "17: write 0x8000", 642 "20: write 0x00000000", 643 "25: write 0x80000000", 644 "30: write 0xfffffffe", 645 "35: write 0xfffefdfc" 646 ), apfTestHelpers.disassembleApf(program).map { it.trim() }) 647 648 gen = ApfV6Generator(apfInterpreterVersion, ramSize, clampSize) 649 gen.addWriteU8(R0) 650 gen.addWriteU16(R0) 651 gen.addWriteU32(R0) 652 gen.addWriteU8(R1) 653 gen.addWriteU16(R1) 654 gen.addWriteU32(R1) 655 program = gen.generate().skipDataAndDebug() 656 assertContentEquals(byteArrayOf( 657 encodeInstruction(21, 1, 0), 38, 658 encodeInstruction(21, 1, 0), 39, 659 encodeInstruction(21, 1, 0), 40, 660 encodeInstruction(21, 1, 1), 38, 661 encodeInstruction(21, 1, 1), 39, 662 encodeInstruction(21, 1, 1), 40 663 ), program) 664 assertContentEquals(listOf( 665 "0: ewrite1 r0", 666 "2: ewrite2 r0", 667 "4: ewrite4 r0", 668 "6: ewrite1 r1", 669 "8: ewrite2 r1", 670 "10: ewrite4 r1" 671 ), apfTestHelpers.disassembleApf(program).map { it.trim() }) 672 673 gen = ApfV6Generator(apfInterpreterVersion, ramSize, clampSize) 674 gen.addDataCopy(0, 2) 675 gen.addDataCopy(1, 1) 676 gen.addPacketCopy(1000, 255) 677 program = gen.generate().skipDataAndDebug() 678 assertContentEquals(byteArrayOf( 679 encodeInstruction(25, 0, 1), 2, 680 encodeInstruction(25, 1, 1), 1, 1, 681 encodeInstruction(25, 2, 0), 682 0x03.toByte(), 0xe8.toByte(), 0xff.toByte(), 683 ), program) 684 assertContentEquals(listOf( 685 "0: datacopy src=0, (2)c902", 686 "2: datacopy src=1, (1)02", 687 "5: pktcopy src=1000, len=255" 688 ), apfTestHelpers.disassembleApf(program).map { it.trim() }) 689 690 gen = ApfV6Generator(apfInterpreterVersion, ramSize, clampSize) 691 gen.addDataCopyFromR0(5) 692 gen.addPacketCopyFromR0(5) 693 gen.addDataCopyFromR0LenR1() 694 gen.addPacketCopyFromR0LenR1() 695 program = gen.generate().skipDataAndDebug() 696 assertContentEquals(byteArrayOf( 697 encodeInstruction(21, 1, 1), 41, 5, 698 encodeInstruction(21, 1, 0), 41, 5, 699 encodeInstruction(21, 1, 1), 42, 700 encodeInstruction(21, 1, 0), 42, 701 ), program) 702 assertContentEquals(listOf( 703 "0: edatacopy src=r0, len=5", 704 "3: epktcopy src=r0, len=5", 705 "6: edatacopy src=r0, len=r1", 706 "8: epktcopy src=r0, len=r1" 707 ), apfTestHelpers.disassembleApf(program).map{ it.trim() }) 708 709 gen = ApfV6Generator(apfInterpreterVersion, ramSize, clampSize) 710 gen.addJumpIfBytesAtR0Equal(byteArrayOf('a'.code.toByte()), ApfV4Generator.DROP_LABEL) 711 program = gen.generate().skipDataAndDebug() 712 assertContentEquals(byteArrayOf( 713 encodeInstruction(opcode = 20, immLength = 1, register = 1), 714 1, 715 1, 716 'a'.code.toByte() 717 ), program) 718 assertContentEquals(listOf( 719 "0: jbseq r0, (1), DROP, 61" 720 ), apfTestHelpers.disassembleApf(program).map{ it.trim() }) 721 722 val qnames = byteArrayOf(1, 'A'.code.toByte(), 1, 'B'.code.toByte(), 0, 0) 723 gen = ApfV6Generator(apfInterpreterVersion, ramSize, clampSize) 724 gen.addJumpIfPktAtR0DoesNotContainDnsQ(qnames, 0x0c, ApfV4Generator.DROP_LABEL) 725 gen.addJumpIfPktAtR0ContainDnsQ(qnames, 0x0c, ApfV4Generator.DROP_LABEL) 726 program = gen.generate().skipDataAndDebug() 727 assertContentEquals(byteArrayOf( 728 encodeInstruction(21, 1, 0), 43, 11, 0x0c.toByte(), 729 ) + qnames + byteArrayOf( 730 encodeInstruction(21, 1, 1), 43, 1, 0x0c.toByte(), 731 ) + qnames, program) 732 assertContentEquals(listOf( 733 "0: jdnsqne r0, DROP, PTR, (1)A(1)B(0)(0)", 734 "10: jdnsqeq r0, DROP, PTR, (1)A(1)B(0)(0)" 735 ), apfTestHelpers.disassembleApf(program).map{ it.trim() }) 736 737 gen = ApfV6Generator(apfInterpreterVersion, ramSize, clampSize) 738 gen.addJumpIfPktAtR0DoesNotContainDnsQSafe(qnames, 0x0c, ApfV4Generator.DROP_LABEL) 739 gen.addJumpIfPktAtR0ContainDnsQSafe(qnames, 0x0c, ApfV4Generator.DROP_LABEL) 740 program = gen.generate().skipDataAndDebug() 741 assertContentEquals(byteArrayOf( 742 encodeInstruction(21, 1, 0), 45, 11, 0x0c.toByte(), 743 ) + qnames + byteArrayOf( 744 encodeInstruction(21, 1, 1), 45, 1, 0x0c.toByte(), 745 ) + qnames, program) 746 assertContentEquals(listOf( 747 "0: jdnsqnesafe r0, DROP, PTR, (1)A(1)B(0)(0)", 748 "10: jdnsqeqsafe r0, DROP, PTR, (1)A(1)B(0)(0)" 749 ), apfTestHelpers.disassembleApf(program).map{ it.trim() }) 750 751 gen = ApfV6Generator(apfInterpreterVersion, ramSize, clampSize) 752 gen.addJumpIfPktAtR0DoesNotContainDnsA(qnames, ApfV4Generator.DROP_LABEL) 753 gen.addJumpIfPktAtR0ContainDnsA(qnames, ApfV4Generator.DROP_LABEL) 754 program = gen.generate().skipDataAndDebug() 755 assertContentEquals(byteArrayOf( 756 encodeInstruction(21, 1, 0), 44, 10, 757 ) + qnames + byteArrayOf( 758 encodeInstruction(21, 1, 1), 44, 1, 759 ) + qnames, program) 760 assertContentEquals(listOf( 761 "0: jdnsane r0, DROP, (1)A(1)B(0)(0)", 762 "9: jdnsaeq r0, DROP, (1)A(1)B(0)(0)" 763 ), apfTestHelpers.disassembleApf(program).map{ it.trim() }) 764 765 gen = ApfV6Generator(apfInterpreterVersion, ramSize, clampSize) 766 gen.addJumpIfPktAtR0DoesNotContainDnsASafe(qnames, ApfV4Generator.DROP_LABEL) 767 gen.addJumpIfPktAtR0ContainDnsASafe(qnames, ApfV4Generator.DROP_LABEL) 768 program = gen.generate().skipDataAndDebug() 769 assertContentEquals(byteArrayOf( 770 encodeInstruction(21, 1, 0), 46, 10, 771 ) + qnames + byteArrayOf( 772 encodeInstruction(21, 1, 1), 46, 1, 773 ) + qnames, program) 774 assertContentEquals(listOf( 775 "0: jdnsanesafe r0, DROP, (1)A(1)B(0)(0)", 776 "9: jdnsaeqsafe r0, DROP, (1)A(1)B(0)(0)" 777 ), apfTestHelpers.disassembleApf(program).map{ it.trim() }) 778 779 gen = ApfV6Generator(apfInterpreterVersion, ramSize, clampSize) 780 gen.addJumpIfOneOf(R1, List(32) { (it + 1).toLong() }.toSet(), DROP_LABEL) 781 gen.addJumpIfOneOf(R0, setOf(0, 257, 65536), DROP_LABEL) 782 gen.addJumpIfNoneOf(R0, setOf(1, 2, 3), DROP_LABEL) 783 program = gen.generate().skipDataAndDebug() 784 assertContentEquals(byteArrayOf( 785 encodeInstruction(21, 1, 1), 47, 24, -16, 1, 2, 3, 4, 5, 6, 786 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 787 29, 30, 31, 32, 788 encodeInstruction(21, 1, 0), 47, 8, 14, 0, 0, 0, 0, 0, 0, 789 1, 1, 0, 1, 0, 0, 790 encodeInstruction(21, 1, 0), 47, 1, 9, 1, 2, 3 791 ), program) 792 793 gen = ApfV6Generator(apfInterpreterVersion, ramSize, clampSize) 794 gen.addJumpIfOneOf(R0, setOf(0, 128, 256, 65536), DROP_LABEL) 795 gen.addJumpIfNoneOf(R1, setOf(0, 128, 256, 65536), DROP_LABEL) 796 program = gen.generate().skipDataAndDebug() 797 assertContentEquals(listOf( 798 "0: joneof r0, DROP, { 0, 128, 256, 65536 }", 799 "20: jnoneof r1, DROP, { 0, 128, 256, 65536 }" 800 ), apfTestHelpers.disassembleApf(program).map{ it.trim() }) 801 802 gen = ApfV6Generator(apfInterpreterVersion, ramSize, clampSize) 803 gen.addJumpIfBytesAtR0EqualsAnyOf(listOf(byteArrayOf(1, 2), byteArrayOf(3, 4)), DROP_LABEL) 804 gen.addJumpIfBytesAtR0EqualsNoneOf(listOf(byteArrayOf(1, 2), byteArrayOf(3, 4)), DROP_LABEL) 805 gen.addJumpIfBytesAtR0EqualsNoneOf(listOf(byteArrayOf(1, 1), byteArrayOf(1, 1)), DROP_LABEL) 806 program = gen.generate().skipDataAndDebug() 807 assertContentEquals(byteArrayOf( 808 encodeInstruction(opcode = 20, immLength = 2, register = 1), 809 0, 15, 8, 2, 1, 2, 3, 4, 810 encodeInstruction(opcode = 20, immLength = 2, register = 0), 811 0, 6, 8, 2, 1, 2, 3, 4, 812 encodeInstruction(opcode = 20, immLength = 1, register = 0), 813 1, 2, 1, 1 814 ), program) 815 assertContentEquals(listOf( 816 "0: jbseq r0, (2), DROP, { 0102, 0304 }[2]", 817 "9: jbsne r0, (2), DROP, { 0102, 0304 }[2]", 818 "18: jbsne r0, (2), DROP, 0101" 819 ), apfTestHelpers.disassembleApf(program).map{ it.trim() }) 820 } 821 822 @Test testApf61InstructionEncodingnull823 fun testApf61InstructionEncoding() { 824 var gen = ApfV61Generator(apfInterpreterVersion, ramSize, clampSize) 825 gen.addCountAndDropIfR0Equals(1, DROPPED_RA) 826 var program = gen.generate().skipDataAndDebug() 827 assertContentEquals(byteArrayOf( 828 encodeInstruction(15, 1, 0), 829 DROPPED_RA.jumpDropLabel.toByte(), 830 1, 831 ), program) 832 833 gen = ApfV61Generator(apfInterpreterVersion, ramSize, clampSize) 834 gen.addCountAndPassIfR0Equals(1, PASSED_MDNS) 835 program = gen.generate().skipDataAndDebug() 836 assertContentEquals(byteArrayOf( 837 encodeInstruction(15, 1, 0), 838 PASSED_MDNS.jumpPassLabel.toByte(), 839 1, 840 ), program) 841 } 842 843 @Test testWriteToTxBuffernull844 fun testWriteToTxBuffer() { 845 var program = ApfV6Generator(apfInterpreterVersion, ramSize, clampSize) 846 .addAllocate(14) 847 .addWriteU8(0x01) 848 .addWriteU16(0x0203) 849 .addWriteU32(0x04050607) 850 .addWrite32(-2) 851 .addWrite32(byteArrayOf(0xff.toByte(), 0xfe.toByte(), 0xfd.toByte(), 0xfc.toByte())) 852 .addLoadImmediate(R0, 1) 853 .addWriteU8(R0) 854 .addLoadImmediate(R0, 0x0203) 855 .addWriteU16(R0) 856 .addLoadImmediate(R1, 0x04050607) 857 .addWriteU32(R1) 858 .addTransmitWithoutChecksum() 859 .generate() 860 apfTestHelpers.assertPass(apfInterpreterVersion, program, ByteArray(MIN_PKT_SIZE)) 861 val transmitPackets = apfTestHelpers.consumeTransmittedPackets(1) 862 assertContentEquals( 863 byteArrayOf( 864 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0xff.toByte(), 865 0xff.toByte(), 0xff.toByte(), 0xfe.toByte(), 0xff.toByte(), 0xfe.toByte(), 866 0xfd.toByte(), 0xfc.toByte(), 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07), 867 transmitPackets[0] 868 ) 869 } 870 871 @Test testCopyToTxBuffernull872 fun testCopyToTxBuffer() { 873 var program = ApfV6Generator( 874 byteArrayOf(33, 34, 35), 875 apfInterpreterVersion, 876 ramSize, 877 clampSize 878 ) 879 .addAllocate(14) 880 .addDataCopy(3, 2) // arg1=src, arg2=len 881 .addDataCopy(5, 1) // arg1=src, arg2=len 882 .addPacketCopy(0, 1) // arg1=src, arg2=len 883 .addPacketCopy(1, 3) // arg1=src, arg2=len 884 .addLoadImmediate(R0, 3) // data copy offset 885 .addDataCopyFromR0(2) // len 886 .addLoadImmediate(R0, 5) // data copy offset 887 .addLoadImmediate(R1, 1) // len 888 .addDataCopyFromR0LenR1() 889 .addLoadImmediate(R0, 0) // packet copy offset 890 .addPacketCopyFromR0(1) // len 891 .addLoadImmediate(R0, 1) // packet copy offset 892 .addLoadImmediate(R1, 3) // len 893 .addPacketCopyFromR0LenR1() 894 .addTransmitWithoutChecksum() 895 .generate() 896 apfTestHelpers.assertPass(apfInterpreterVersion, program, testPacket) 897 val transmitPackets = apfTestHelpers.consumeTransmittedPackets(1) 898 assertContentEquals( 899 byteArrayOf(33, 34, 35, 1, 2, 3, 4, 33, 34, 35, 1, 2, 3, 4), 900 transmitPackets[0] 901 ) 902 } 903 904 @Test testCopyContentToTxBuffernull905 fun testCopyContentToTxBuffer() { 906 val program = ApfV6Generator(apfInterpreterVersion, ramSize, clampSize) 907 .addAllocate(18) 908 .addDataCopy(HexDump.hexStringToByteArray("112233445566")) 909 .addDataCopy(HexDump.hexStringToByteArray("223344")) 910 .addDataCopy(HexDump.hexStringToByteArray("778899")) 911 .addDataCopy(HexDump.hexStringToByteArray("112233445566")) 912 .addTransmitWithoutChecksum() 913 .generate() 914 assertContentEquals(listOf( 915 "0: data 9, 112233445566778899", 916 "12: debugbuf size=${ramSize - program.size - Counter.totalSize()}", 917 "16: allocate 18", 918 "20: datacopy src=3, (6)112233445566", 919 "23: datacopy src=4, (3)223344", 920 "26: datacopy src=9, (3)778899", 921 "29: datacopy src=3, (6)112233445566", 922 "32: transmit ip_ofs=255" 923 ), apfTestHelpers.disassembleApf(program).map{ it.trim() }) 924 apfTestHelpers.assertPass(apfInterpreterVersion, program, testPacket) 925 val transmitPackets = apfTestHelpers.consumeTransmittedPackets(1) 926 val transmitPkt = HexDump.toHexString(transmitPackets[0]) 927 assertEquals("112233445566223344778899112233445566", transmitPkt) 928 } 929 930 @Test testCopyLargeContentToTxBufferWithCompressionnull931 fun testCopyLargeContentToTxBufferWithCompression() { 932 val program = ApfV6Generator(apfInterpreterVersion, ramSize, clampSize) 933 .addAllocate(300) 934 // Chunked into 255 and 35 bytes. 935 // 255 bytes appended to data region. 936 // 35 bytes compressed by reusing the duplicated chunk from the data region. 937 .addDataCopy(ByteArray(290) { 1 }) 938 // Appended to the data region. 939 .addDataCopy(ByteArray(5) { 2 }) 940 // Compressed by reusing the duplicated chunk from the data region. 941 .addDataCopy(ByteArray(3) { 1 } + ByteArray(2) { 2 }) 942 .addTransmitWithoutChecksum() 943 .generate() 944 945 val byteHexString = "01".repeat(255) + "02".repeat(5) 946 assertContentEquals(listOf( 947 "0: data 260, $byteHexString", 948 "263: debugbuf size=${ramSize - program.size - Counter.totalSize()}", 949 "267: allocate 300", 950 "271: datacopy src=3, (255)" + "01".repeat(255), 951 "274: datacopy src=3, (35)" + "01".repeat(35), 952 "277: datacopy src=258, (5)" + "02".repeat(5), 953 "281: datacopy src=255, (5)" + "01".repeat(3) + "02".repeat(2), 954 "284: transmit ip_ofs=255" 955 ), apfTestHelpers.disassembleApf(program).map{ it.trim() }) 956 apfTestHelpers.assertPass(apfInterpreterVersion, program, testPacket) 957 val transmitPackets = apfTestHelpers.consumeTransmittedPackets(1) 958 val transmitPkt = HexDump.toHexString(transmitPackets[0]) 959 assertEquals( 960 "01".repeat(290) + "02".repeat(5) + "01".repeat(3) + "02".repeat(2), 961 transmitPkt 962 ) 963 } 964 965 @Test testCopyLargeContentToTxBufferWithoutCompressionnull966 fun testCopyLargeContentToTxBufferWithoutCompression() { 967 val program = ApfV6Generator(apfInterpreterVersion, ramSize, clampSize) 968 .addAllocate(300) 969 // Chunked into 255 and 45 bytes and then appended to the data region. 970 .addDataCopy(ByteArray(255) { 3 } + ByteArray(45) { 4 }) 971 .addTransmitWithoutChecksum() 972 .generate() 973 974 val byteHexString = "03".repeat(255) + "04".repeat(45) 975 assertContentEquals(listOf( 976 "0: data 300, $byteHexString", 977 "303: debugbuf size=${ramSize - program.size - Counter.totalSize()}", 978 "307: allocate 300", 979 "311: datacopy src=3, (255)" + "03".repeat(255), 980 "314: datacopy src=258, (45)" + "04".repeat(45), 981 "318: transmit ip_ofs=255" 982 ), apfTestHelpers.disassembleApf(program).map{ it.trim() }) 983 apfTestHelpers.assertPass(apfInterpreterVersion, program, testPacket) 984 val transmitPackets = apfTestHelpers.consumeTransmittedPackets(1) 985 val transmitPkt = HexDump.toHexString(transmitPackets[0]) 986 assertEquals( "03".repeat(255) + "04".repeat(45), transmitPkt) 987 } 988 989 @Test testJBSPTRMATCHOpcodeEncodingnull990 fun testJBSPTRMATCHOpcodeEncoding() { 991 assumeTrue(apfInterpreterVersion != ApfJniUtils.APF_INTERPRETER_VERSION_V6) 992 val dataBytes = HexDump.hexStringToByteArray( 993 "01020304050607080910111213141516171819202122232425262728293031323334353637383940" 994 ) 995 val bytes1 = HexDump.hexStringToByteArray("0102") 996 val bytes2 = HexDump.hexStringToByteArray("0304") 997 val bytes3 = HexDump.hexStringToByteArray("0506") 998 val bytes4 = HexDump.hexStringToByteArray("0708") 999 val bytes5 = HexDump.hexStringToByteArray("0910") 1000 val bytes6 = HexDump.hexStringToByteArray("1112") 1001 val bytes7 = HexDump.hexStringToByteArray("1314") 1002 val bytes8 = HexDump.hexStringToByteArray("1516") 1003 val bytes9 = HexDump.hexStringToByteArray("1718") 1004 val bytes10 = HexDump.hexStringToByteArray("1920") 1005 val bytes11 = HexDump.hexStringToByteArray("2122") 1006 val bytes12 = HexDump.hexStringToByteArray("2324") 1007 val bytes13 = HexDump.hexStringToByteArray("2526") 1008 val bytes14 = HexDump.hexStringToByteArray("2728") 1009 val bytes15 = HexDump.hexStringToByteArray("2930") 1010 val bytes16 = HexDump.hexStringToByteArray("3132") 1011 val bytes17 = HexDump.hexStringToByteArray("3334") 1012 val bytesAtOddIndex = HexDump.hexStringToByteArray("0203") 1013 val notExistBytes = HexDump.hexStringToByteArray("ffff") 1014 val total17BytesList = listOf( 1015 bytes1, 1016 bytes2, 1017 bytes3, 1018 bytes4, 1019 bytes5, 1020 bytes6, 1021 bytes7, 1022 bytes8, 1023 bytes9, 1024 bytes10, 1025 bytes11, 1026 bytes12, 1027 bytes13, 1028 bytes14, 1029 bytes15, 1030 bytes16, 1031 bytes17, 1032 ) 1033 val joinedBytes: ByteArray = total17BytesList.flatMap { it.toList() }.toByteArray() 1034 var program = ApfV61Generator(apfInterpreterVersion, ramSize, clampSize) 1035 .addPreloadData(dataBytes) 1036 .addJumpIfBytesAtOffsetEqualsNoneOf(0, listOf(bytes1, notExistBytes), PASS_LABEL) 1037 .addJumpIfBytesAtOffsetEqualsAnyOf(1, listOf(bytes1, bytes2), PASS_LABEL) 1038 .addJumpIfBytesAtOffsetEqualsNoneOf(2, listOf(notExistBytes), PASS_LABEL) 1039 .addJumpIfBytesAtOffsetEqualsAnyOf(3, total17BytesList, PASS_LABEL) 1040 .addJumpIfBytesAtOffsetEqualsNoneOf(4, listOf(bytesAtOddIndex), PASS_LABEL) 1041 .addJumpIfBytesAtOffsetEqualsNoneOf(6, listOf(joinedBytes), PASS_LABEL) 1042 .generate() 1043 var debugBufferSize = ramSize - program.size - Counter.totalSize() 1044 assertContentEquals(listOf( 1045 "0: data 40, ${HexDump.toHexString(dataBytes)}", 1046 "43: debugbuf size=$debugBufferSize", 1047 "47: jbsptrne pktofs=0, (2), PASS, @0[0102]", 1048 "52: li r0, 0", 1049 "53: jbsne r0, (2), PASS, ffff", 1050 "58: jbsptreq pktofs=1, (2), PASS, { @0[0102], @2[0304] }[2]", 1051 "64: li r0, 2", 1052 "66: jbsne r0, (2), PASS, ffff", 1053 "71: jbsptreq pktofs=3, (2), PASS, { @0[0102], @2[0304], @4[0506], @6[0708], " + 1054 "@8[0910], @10[1112], @12[1314], @14[1516], @16[1718], @18[1920], @20[2122], " + 1055 "@22[2324], @24[2526], @26[2728], @28[2930], @30[3132] }[16]", 1056 "91: jbsptreq pktofs=3, (2), PASS, @32[3334]", 1057 "96: li r0, 4", 1058 "98: jbsne r0, (2), PASS, 0203", 1059 "103: li r0, 6", 1060 "105: jbsne r0, (34), PASS, ${HexDump.toHexString(joinedBytes)}", 1061 ), apfTestHelpers.disassembleApf(program).map{ it.trim() }) 1062 1063 val largePrefix = ByteArray(510) { 0 } 1064 program = ApfV61Generator(apfInterpreterVersion, ramSize, clampSize) 1065 .addPreloadData(largePrefix + dataBytes) 1066 .addJumpIfBytesAtOffsetEqualsAnyOf(1, listOf(bytes1, bytes2), PASS_LABEL) 1067 .generate() 1068 debugBufferSize = ramSize - program.size - Counter.totalSize() 1069 assertContentEquals(listOf( 1070 "0: data 550, ${HexDump.toHexString(largePrefix + dataBytes)}", 1071 "553: debugbuf size=$debugBufferSize", 1072 "557: jbsptreq pktofs=1, (2), PASS, @510[0102]", 1073 "562: li r0, 1", 1074 "564: jbseq r0, (2), PASS, 0304", 1075 ), apfTestHelpers.disassembleApf(program).map{ it.trim() }) 1076 } 1077 1078 @Test testPassDropnull1079 fun testPassDrop() { 1080 var program = ApfV6Generator(apfInterpreterVersion, ramSize, clampSize) 1081 .addDrop() 1082 .addPass() 1083 .generate() 1084 apfTestHelpers.assertDrop(apfInterpreterVersion, program, testPacket) 1085 1086 program = ApfV6Generator(apfInterpreterVersion, ramSize, clampSize) 1087 .addCountAndDrop(Counter.DROPPED_ETH_BROADCAST) 1088 .generate() 1089 apfTestHelpers.verifyProgramRun( 1090 apfInterpreterVersion, 1091 program, 1092 testPacket, 1093 DROPPED_ETH_BROADCAST 1094 ) 1095 1096 program = ApfV6Generator(apfInterpreterVersion, ramSize, clampSize) 1097 .addCountAndPass(Counter.PASSED_ARP_REQUEST) 1098 .generate() 1099 apfTestHelpers.verifyProgramRun( 1100 apfInterpreterVersion, 1101 program, 1102 testPacket, 1103 PASSED_ARP_REQUEST 1104 ) 1105 } 1106 1107 @Test testLoadStoreCounternull1108 fun testLoadStoreCounter() { 1109 doTestLoadStoreCounter ( 1110 { mutableMapOf() }, 1111 { ApfV4Generator(APF_VERSION_3, ramSize, clampSize) } 1112 ) 1113 doTestLoadStoreCounter ( 1114 { mutableMapOf(TOTAL_PACKETS to 1) }, 1115 { ApfV6Generator(apfInterpreterVersion, ramSize, clampSize) } 1116 ) 1117 } 1118 doTestLoadStoreCounternull1119 private fun doTestLoadStoreCounter( 1120 getInitialMap: () -> MutableMap<Counter, Long>, 1121 getGenerator: () -> ApfV4GeneratorBase<*> 1122 ) { 1123 val program = getGenerator() 1124 .addIncrementCounter(PASSED_ARP_REQUEST, 2) 1125 .addPass() 1126 .generate() 1127 var dataRegion = ByteArray(Counter.totalSize()) { 0 } 1128 apfTestHelpers.assertVerdict(apfInterpreterVersion, PASS, program, testPacket, dataRegion) 1129 var counterMap = decodeCountersIntoMap(dataRegion) 1130 var expectedMap = getInitialMap() 1131 expectedMap[PASSED_ARP_REQUEST] = 2 1132 assertEquals(expectedMap, counterMap) 1133 } 1134 1135 @Test testV4CountAndPassDropCompareR0null1136 fun testV4CountAndPassDropCompareR0() { 1137 doTestCountAndPassDropCompareR0( 1138 getGenerator = { ApfV4Generator(APF_VERSION_3, ramSize, clampSize) }, 1139 incTotal = false 1140 ) 1141 } 1142 1143 @Test testV6CountAndPassDropCompareR0null1144 fun testV6CountAndPassDropCompareR0() { 1145 doTestCountAndPassDropCompareR0( 1146 getGenerator = { ApfV6Generator(apfInterpreterVersion, ramSize, clampSize) }, 1147 incTotal = true 1148 ) 1149 } 1150 1151 @Test testV61CountAndPassDropCompareR0null1152 fun testV61CountAndPassDropCompareR0() { 1153 assumeTrue(apfInterpreterVersion > ApfJniUtils.APF_INTERPRETER_VERSION_V6) 1154 doTestCountAndPassDropCompareR0( 1155 getGenerator = { ApfV61Generator(apfInterpreterVersion, ramSize, clampSize) }, 1156 incTotal = true 1157 ) 1158 } 1159 doTestCountAndPassDropCompareR0null1160 private fun doTestCountAndPassDropCompareR0( 1161 getGenerator: () -> ApfV4GeneratorBase<*>, 1162 incTotal: Boolean 1163 ) { 1164 var program = getGenerator() 1165 .addLoadImmediate(R0, 123) 1166 .addCountAndDropIfR0Equals(123, Counter.DROPPED_ETH_BROADCAST) 1167 .addPass() 1168 .addCountTrampoline() 1169 .generate() 1170 apfTestHelpers.verifyProgramRun( 1171 apfInterpreterVersion, 1172 program, 1173 testPacket, 1174 DROPPED_ETH_BROADCAST, 1175 incTotal = incTotal 1176 ) 1177 1178 program = getGenerator() 1179 .addLoadImmediate(R0, 123) 1180 .addCountAndPassIfR0Equals(123, Counter.PASSED_ARP_REQUEST) 1181 .addPass() 1182 .addCountTrampoline() 1183 .generate() 1184 apfTestHelpers.verifyProgramRun( 1185 apfInterpreterVersion, 1186 program, 1187 testPacket, 1188 PASSED_ARP_REQUEST, 1189 incTotal = incTotal 1190 ) 1191 1192 program = getGenerator() 1193 .addLoadImmediate(R0, 123) 1194 .addCountAndDropIfR0NotEquals(124, Counter.DROPPED_ETH_BROADCAST) 1195 .addPass() 1196 .addCountTrampoline() 1197 .generate() 1198 apfTestHelpers.verifyProgramRun( 1199 apfInterpreterVersion, 1200 program, 1201 testPacket, 1202 DROPPED_ETH_BROADCAST, 1203 incTotal = incTotal 1204 ) 1205 1206 program = getGenerator() 1207 .addLoadImmediate(R0, 123) 1208 .addCountAndPassIfR0NotEquals(124, Counter.PASSED_ARP_REQUEST) 1209 .addPass() 1210 .addCountTrampoline() 1211 .generate() 1212 apfTestHelpers.verifyProgramRun( 1213 apfInterpreterVersion, 1214 program, 1215 testPacket, 1216 PASSED_ARP_REQUEST, 1217 incTotal = incTotal 1218 ) 1219 1220 program = getGenerator() 1221 .addLoadImmediate(R0, 123) 1222 .addCountAndDropIfR0LessThan(124, Counter.DROPPED_ETH_BROADCAST) 1223 .addPass() 1224 .addCountTrampoline() 1225 .generate() 1226 apfTestHelpers.verifyProgramRun( 1227 apfInterpreterVersion, 1228 program, 1229 testPacket, 1230 DROPPED_ETH_BROADCAST, 1231 incTotal = incTotal 1232 ) 1233 1234 program = getGenerator() 1235 .addLoadImmediate(R0, 123) 1236 .addCountAndPassIfR0LessThan(124, Counter.PASSED_ARP_REQUEST) 1237 .addPass() 1238 .addCountTrampoline() 1239 .generate() 1240 apfTestHelpers.verifyProgramRun( 1241 apfInterpreterVersion, 1242 program, 1243 testPacket, 1244 PASSED_ARP_REQUEST, 1245 incTotal = incTotal 1246 ) 1247 1248 program = getGenerator() 1249 .addLoadImmediate(R0, 123) 1250 .addCountAndDropIfR0GreaterThan(122, Counter.DROPPED_ETH_BROADCAST) 1251 .addPass() 1252 .addCountTrampoline() 1253 .generate() 1254 apfTestHelpers.verifyProgramRun( 1255 apfInterpreterVersion, 1256 program, 1257 testPacket, 1258 DROPPED_ETH_BROADCAST, 1259 incTotal = incTotal 1260 ) 1261 1262 program = getGenerator() 1263 .addLoadImmediate(R0, 123) 1264 .addCountAndPassIfR0GreaterThan(122, Counter.PASSED_ARP_REQUEST) 1265 .addPass() 1266 .addCountTrampoline() 1267 .generate() 1268 apfTestHelpers.verifyProgramRun( 1269 apfInterpreterVersion, 1270 program, 1271 testPacket, 1272 PASSED_ARP_REQUEST, 1273 incTotal = incTotal 1274 ) 1275 1276 program = getGenerator() 1277 .addLoadImmediate(R0, 1) 1278 .addCountAndDropIfBytesAtR0NotEqual( 1279 byteArrayOf(5, 5), DROPPED_ETH_BROADCAST) 1280 .addPass() 1281 .addCountTrampoline() 1282 .generate() 1283 apfTestHelpers.verifyProgramRun( 1284 apfInterpreterVersion, 1285 program, 1286 testPacket, 1287 DROPPED_ETH_BROADCAST, 1288 incTotal = incTotal 1289 ) 1290 1291 program = getGenerator() 1292 .addLoadImmediate(R0, 1) 1293 .addCountAndPassIfBytesAtR0NotEqual( 1294 byteArrayOf(5, 5), PASSED_ARP_REQUEST) 1295 .addPass() 1296 .addCountTrampoline() 1297 .generate() 1298 apfTestHelpers.verifyProgramRun( 1299 apfInterpreterVersion, 1300 program, 1301 testPacket, 1302 PASSED_ARP_REQUEST, 1303 incTotal = incTotal 1304 ) 1305 1306 program = getGenerator() 1307 .addLoadImmediate(R0, 1) 1308 .addCountAndDropIfR0AnyBitsSet(0xffff, DROPPED_ETH_BROADCAST) 1309 .addPass() 1310 .addCountTrampoline() 1311 .generate() 1312 apfTestHelpers.verifyProgramRun( 1313 apfInterpreterVersion, 1314 program, 1315 testPacket, 1316 DROPPED_ETH_BROADCAST, 1317 incTotal = incTotal 1318 ) 1319 1320 program = getGenerator() 1321 .addLoadImmediate(R0, 1) 1322 .addCountAndPassIfR0AnyBitsSet(0xffff, PASSED_ARP_REQUEST) 1323 .addPass() 1324 .addCountTrampoline() 1325 .generate() 1326 apfTestHelpers.verifyProgramRun( 1327 apfInterpreterVersion, 1328 program, 1329 testPacket, 1330 PASSED_ARP_REQUEST, 1331 incTotal = incTotal 1332 ) 1333 1334 program = getGenerator() 1335 .addLoadImmediate(R0, 123) 1336 .addCountAndDropIfR0IsOneOf(setOf(123), DROPPED_ETH_BROADCAST) 1337 .addPass() 1338 .addCountTrampoline() 1339 .generate() 1340 apfTestHelpers.verifyProgramRun( 1341 apfInterpreterVersion, 1342 program, 1343 testPacket, 1344 DROPPED_ETH_BROADCAST, 1345 incTotal = incTotal 1346 ) 1347 1348 program = getGenerator() 1349 .addLoadImmediate(R0, 123) 1350 .addCountAndPassIfR0IsOneOf(setOf(123), PASSED_ARP_REQUEST) 1351 .addPass() 1352 .addCountTrampoline() 1353 .generate() 1354 apfTestHelpers.verifyProgramRun( 1355 apfInterpreterVersion, 1356 program, 1357 testPacket, 1358 PASSED_ARP_REQUEST, 1359 incTotal = incTotal 1360 ) 1361 1362 program = getGenerator() 1363 .addLoadImmediate(R0, 123) 1364 .addCountAndDropIfR0IsNoneOf(setOf(124), DROPPED_ETH_BROADCAST) 1365 .addPass() 1366 .addCountTrampoline() 1367 .generate() 1368 apfTestHelpers.verifyProgramRun( 1369 apfInterpreterVersion, 1370 program, 1371 testPacket, 1372 DROPPED_ETH_BROADCAST, 1373 incTotal = incTotal 1374 ) 1375 1376 program = getGenerator() 1377 .addLoadImmediate(R0, 123) 1378 .addCountAndPassIfR0IsNoneOf(setOf(124), PASSED_ARP_REQUEST) 1379 .addPass() 1380 .addCountTrampoline() 1381 .generate() 1382 apfTestHelpers.verifyProgramRun( 1383 apfInterpreterVersion, 1384 program, 1385 testPacket, 1386 PASSED_ARP_REQUEST, 1387 incTotal = incTotal 1388 ) 1389 1390 program = getGenerator() 1391 .addLoadImmediate(R0, 123) 1392 .addCountAndDropIfR0IsOneOf(setOf(123, 124), DROPPED_ETH_BROADCAST) 1393 .addPass() 1394 .addCountTrampoline() 1395 .generate() 1396 apfTestHelpers.verifyProgramRun( 1397 apfInterpreterVersion, 1398 program, 1399 testPacket, 1400 DROPPED_ETH_BROADCAST, 1401 incTotal = incTotal 1402 ) 1403 1404 program = getGenerator() 1405 .addLoadImmediate(R0, 123) 1406 .addCountAndPassIfR0IsOneOf(setOf(123, 124), PASSED_ARP_REQUEST) 1407 .addPass() 1408 .addCountTrampoline() 1409 .generate() 1410 apfTestHelpers.verifyProgramRun( 1411 apfInterpreterVersion, 1412 program, 1413 testPacket, 1414 PASSED_ARP_REQUEST, 1415 incTotal = incTotal 1416 ) 1417 1418 program = getGenerator() 1419 .addLoadImmediate(R0, 123) 1420 .addCountAndDropIfR0IsNoneOf(setOf(122, 124), DROPPED_ETH_BROADCAST) 1421 .addPass() 1422 .addCountTrampoline() 1423 .generate() 1424 apfTestHelpers.verifyProgramRun( 1425 apfInterpreterVersion, 1426 program, 1427 testPacket, 1428 DROPPED_ETH_BROADCAST, 1429 incTotal = incTotal 1430 ) 1431 1432 program = getGenerator() 1433 .addLoadImmediate(R0, 123) 1434 .addCountAndPassIfR0IsNoneOf(setOf(122, 124), PASSED_ARP_REQUEST) 1435 .addPass() 1436 .addCountTrampoline() 1437 .generate() 1438 apfTestHelpers.verifyProgramRun( 1439 apfInterpreterVersion, 1440 program, 1441 testPacket, 1442 PASSED_ARP_REQUEST, 1443 incTotal = incTotal 1444 ) 1445 1446 program = getGenerator() 1447 .addLoadImmediate(R0, 0) 1448 .addCountAndDropIfBytesAtR0EqualsAnyOf( 1449 listOf(byteArrayOf(1, 2), byteArrayOf(3, 4)), 1450 DROPPED_ETH_BROADCAST 1451 ) 1452 .addPass() 1453 .addCountTrampoline() 1454 .generate() 1455 apfTestHelpers.verifyProgramRun( 1456 apfInterpreterVersion, 1457 program, 1458 testPacket, 1459 DROPPED_ETH_BROADCAST, 1460 incTotal = incTotal 1461 ) 1462 1463 program = getGenerator() 1464 .addLoadImmediate(R0, 0) 1465 .addCountAndPassIfBytesAtR0EqualsAnyOf( 1466 listOf(byteArrayOf(1, 2), byteArrayOf(3, 4)), 1467 PASSED_ARP_REQUEST 1468 ) 1469 .addPass() 1470 .addCountTrampoline() 1471 .generate() 1472 apfTestHelpers.verifyProgramRun( 1473 apfInterpreterVersion, 1474 program, 1475 testPacket, 1476 PASSED_ARP_REQUEST, 1477 incTotal = incTotal 1478 ) 1479 1480 program = getGenerator() 1481 .addLoadImmediate(R0, 0) 1482 .addCountAndDropIfBytesAtR0EqualsNoneOf( 1483 listOf(byteArrayOf(1, 3), byteArrayOf(3, 4)), 1484 DROPPED_ETH_BROADCAST 1485 ) 1486 .addPass() 1487 .addCountTrampoline() 1488 .generate() 1489 apfTestHelpers.verifyProgramRun( 1490 apfInterpreterVersion, 1491 program, 1492 testPacket, 1493 DROPPED_ETH_BROADCAST, 1494 incTotal = incTotal 1495 ) 1496 1497 program = getGenerator() 1498 .addLoadImmediate(R0, 0) 1499 .addCountAndPassIfBytesAtR0EqualsNoneOf( 1500 listOf(byteArrayOf(1, 3), byteArrayOf(3, 4)), 1501 PASSED_ARP_REQUEST 1502 ) 1503 .addPass() 1504 .addCountTrampoline() 1505 .generate() 1506 apfTestHelpers.verifyProgramRun( 1507 apfInterpreterVersion, 1508 program, 1509 testPacket, 1510 PASSED_ARP_REQUEST, 1511 incTotal = incTotal 1512 ) 1513 1514 program = getGenerator() 1515 .addLoadImmediate(R0, 1) 1516 .addCountAndDropIfBytesAtR0Equal( 1517 byteArrayOf(2, 3), DROPPED_ETH_BROADCAST) 1518 .addPass() 1519 .addCountTrampoline() 1520 .generate() 1521 apfTestHelpers.verifyProgramRun( 1522 apfInterpreterVersion, 1523 program, 1524 testPacket, 1525 DROPPED_ETH_BROADCAST, 1526 incTotal = incTotal 1527 ) 1528 1529 program = getGenerator() 1530 .addLoadImmediate(R0, 1) 1531 .addCountAndPassIfBytesAtR0Equal( 1532 byteArrayOf(2, 3), PASSED_ARP_REQUEST) 1533 .addPass() 1534 .addCountTrampoline() 1535 .generate() 1536 apfTestHelpers.verifyProgramRun( 1537 apfInterpreterVersion, 1538 program, 1539 testPacket, 1540 PASSED_ARP_REQUEST, 1541 incTotal = incTotal 1542 ) 1543 } 1544 1545 @Test testV4CountAndPassDropnull1546 fun testV4CountAndPassDrop() { 1547 var program = ApfV4Generator(APF_VERSION_3, ramSize, clampSize) 1548 .addCountAndDrop(Counter.DROPPED_ETH_BROADCAST) 1549 .addCountTrampoline() 1550 .generate() 1551 apfTestHelpers.verifyProgramRun( 1552 apfInterpreterVersion, 1553 program, 1554 testPacket, 1555 DROPPED_ETH_BROADCAST, 1556 incTotal = false 1557 ) 1558 1559 program = ApfV4Generator(APF_VERSION_3, ramSize, clampSize) 1560 .addCountAndPass(Counter.PASSED_ARP_REQUEST) 1561 .addCountTrampoline() 1562 .generate() 1563 apfTestHelpers.verifyProgramRun( 1564 apfInterpreterVersion, 1565 program, 1566 testPacket, 1567 PASSED_ARP_REQUEST, 1568 incTotal = false 1569 ) 1570 } 1571 1572 @Test testV2CountAndPassDropnull1573 fun testV2CountAndPassDrop() { 1574 var program = ApfV4Generator(APF_VERSION_2, ramSize, clampSize) 1575 .addCountAndDrop(Counter.DROPPED_ETH_BROADCAST) 1576 .addCountTrampoline() 1577 .generate() 1578 var dataRegion = ByteArray(Counter.totalSize()) { 0 } 1579 apfTestHelpers.assertVerdict(apfInterpreterVersion, DROP, program, testPacket, dataRegion) 1580 assertContentEquals(ByteArray(Counter.totalSize()) { 0 }, dataRegion) 1581 1582 program = ApfV4Generator(APF_VERSION_2, ramSize, clampSize) 1583 .addCountAndPass(PASSED_ARP_REQUEST) 1584 .addCountTrampoline() 1585 .generate() 1586 dataRegion = ByteArray(Counter.totalSize()) { 0 } 1587 apfTestHelpers.assertVerdict(apfInterpreterVersion, PASS, program, testPacket, dataRegion) 1588 assertContentEquals(ByteArray(Counter.totalSize()) { 0 }, dataRegion) 1589 } 1590 1591 @Test testAllocateFailurenull1592 fun testAllocateFailure() { 1593 val program = ApfV6Generator(apfInterpreterVersion, ramSize, clampSize) 1594 // allocate size: 65535 > sizeof(apf_test_buffer): 1514, trigger allocate failure. 1595 .addAllocate(65535) 1596 .addDrop() 1597 .generate() 1598 apfTestHelpers.verifyProgramRun( 1599 apfInterpreterVersion, 1600 program, 1601 testPacket, 1602 PASSED_ALLOCATE_FAILURE 1603 ) 1604 } 1605 1606 @Test testTransmitFailurenull1607 fun testTransmitFailure() { 1608 val program = ApfV6Generator(apfInterpreterVersion, ramSize, clampSize) 1609 .addAllocate(14) 1610 // len: 13 is less than ETH_HLEN, trigger transmit failure. 1611 .addLoadImmediate(R0, 13) 1612 .addStoreToMemory(MemorySlot.TX_BUFFER_OUTPUT_POINTER, R0) 1613 .addTransmitWithoutChecksum() 1614 .addDrop() 1615 .generate() 1616 apfTestHelpers.verifyProgramRun( 1617 apfInterpreterVersion, 1618 program, 1619 testPacket, 1620 PASSED_TRANSMIT_FAILURE 1621 ) 1622 } 1623 1624 @Test testTransmitL4null1625 fun testTransmitL4() { 1626 val etherIpv4UdpPacket = intArrayOf( 1627 0x01, 0x00, 0x5e, 0x00, 0x00, 0xfb, 1628 0x38, 0xca, 0x84, 0xb7, 0x7f, 0x16, 1629 0x08, 0x00, // end of ethernet header 1630 0x45, 1631 0x04, 1632 0x00, 0x3f, 1633 0x43, 0xcd, 1634 0x40, 0x00, 1635 0xff, 1636 0x11, 1637 0x00, 0x00, // ipv4 checksum set to 0 1638 0xc0, 0xa8, 0x01, 0x03, 1639 0xe0, 0x00, 0x00, 0xfb, // end of ipv4 header 1640 0x14, 0xe9, 1641 0x14, 0xe9, 1642 0x00, 0x2b, 1643 0x00, 0x2b, // end of udp header. udp checksum set to udp (header + payload) size 1644 0x00, 0x00, 0x84, 0x00, 0x00, 0x00, 1645 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x01, 0x62, 0x05, 0x6c, 0x6f, 0x63, 0x61, 0x6c, 1646 0x00, 0x00, 0x01, 0x80, 0x01, 0x00, 0x00, 0x00, 0x78, 0x00, 0x04, 0xc0, 0xa8, 0x01, 1647 0x09, 1648 ).map { it.toByte() }.toByteArray() 1649 val program = ApfV6Generator(etherIpv4UdpPacket, apfInterpreterVersion, ramSize, clampSize) 1650 .addAllocate(etherIpv4UdpPacket.size) 1651 .addDataCopy(3, etherIpv4UdpPacket.size) // arg1=src, arg2=len 1652 .addTransmitL4( 1653 ETH_HLEN, // ipOfs, 1654 ETH_HLEN + IPV4_HLEN + 6, // csumOfs 1655 ETH_HLEN + IPV4_HLEN - 8, // csumStart 1656 IPPROTO_UDP, // partialCsum 1657 true // isUdp 1658 ) 1659 .generate() 1660 apfTestHelpers.assertPass(apfInterpreterVersion, program, testPacket) 1661 val transmitPackets = apfTestHelpers.consumeTransmittedPackets(1) 1662 val txBuf = ByteBuffer.wrap(transmitPackets[0]) 1663 Struct.parse(EthernetHeader::class.java, txBuf) 1664 val ipv4Hdr = Struct.parse(Ipv4Header::class.java, txBuf) 1665 val udpHdr = Struct.parse(UdpHeader::class.java, txBuf) 1666 assertEquals(0x9535.toShort(), ipv4Hdr.checksum) 1667 assertEquals(0xa73d.toShort(), udpHdr.checksum) 1668 } 1669 1670 @Test testDnsQuestionMatchnull1671 fun testDnsQuestionMatch() { 1672 // needles = { A, B.LOCAL } 1673 val needlesMatch = intArrayOf( 1674 0x01, 'A'.code, 1675 0x00, 1676 0x01, 'B'.code, 1677 0x05, 'L'.code, 'O'.code, 'C'.code, 'A'.code, 'L'.code, 1678 0x00, 1679 0x00 1680 ).map { it.toByte() }.toByteArray() 1681 val udpPayload = intArrayOf( 1682 0x00, 0x00, 0x00, 0x00, // tid = 0x00, flags = 0x00, 1683 0x00, 0x02, // qdcount = 2 1684 0x00, 0x00, // ancount = 0 1685 0x00, 0x00, // nscount = 0 1686 0x00, 0x00, // arcount = 0 1687 0x01, 'a'.code, 1688 0x01, 'b'.code, 1689 0x05, 'l'.code, 'o'.code, 'c'.code, 'a'.code, 'l'.code, 1690 0x00, // qname1 = a.b.local 1691 0x00, 0x01, 0x00, 0x01, // type = A, class = 0x0001 1692 0xc0, 0x0e, // qname2 = b.local (name compression) 1693 0x00, 0x01, 0x00, 0x01 // type = A, class = 0x0001 1694 ).map { it.toByte() }.toByteArray() 1695 1696 var program = ApfV6Generator(apfInterpreterVersion, ramSize, clampSize) 1697 .addLoadImmediate(R0, 0) 1698 .addJumpIfPktAtR0ContainDnsQ(needlesMatch, 0x01, DROP_LABEL) // arg2=qtype 1699 .addPass() 1700 .generate() 1701 apfTestHelpers.assertDrop(apfInterpreterVersion, program, udpPayload) 1702 1703 program = ApfV6Generator(apfInterpreterVersion, ramSize, clampSize) 1704 .addLoadImmediate(R0, 0) 1705 .addJumpIfPktAtR0ContainDnsQSafe(needlesMatch, 0x01, DROP_LABEL) 1706 .addPass() 1707 .generate() 1708 apfTestHelpers.assertDrop(apfInterpreterVersion, program, udpPayload) 1709 1710 program = ApfV6Generator(apfInterpreterVersion, ramSize, clampSize) 1711 .addLoadImmediate(R0, 0) 1712 .addJumpIfPktAtR0DoesNotContainDnsQ(needlesMatch, 0x01, DROP_LABEL) // arg2=qtype 1713 .addPass() 1714 .generate() 1715 apfTestHelpers.assertPass(apfInterpreterVersion, program, udpPayload) 1716 1717 program = ApfV6Generator(apfInterpreterVersion, ramSize, clampSize) 1718 .addLoadImmediate(R0, 0) 1719 .addJumpIfPktAtR0DoesNotContainDnsQSafe(needlesMatch, 0x01, DROP_LABEL) // arg2=qtype 1720 .addPass() 1721 .generate() 1722 apfTestHelpers.assertPass(apfInterpreterVersion, program, udpPayload) 1723 1724 val badUdpPayload = intArrayOf( 1725 0x00, 0x00, 0x00, 0x00, // tid = 0x00, flags = 0x00, 1726 0x00, 0x02, // qdcount = 2 1727 0x00, 0x00, // ancount = 0 1728 0x00, 0x00, // nscount = 0 1729 0x00, 0x00, // arcount = 0 1730 0x01, 'a'.code, 1731 0x01, 'b'.code, 1732 0x05, 'l'.code, 'o'.code, 'c'.code, 'a'.code, 'l'.code, 1733 0x00, // qname1 = a.b.local 1734 0x00, 0x01, 0x00, 0x01, // type = A, class = 0x0001 1735 0xc0, 0x1b, // corrupted pointer cause infinite loop 1736 0x00, 0x01, 0x00, 0x01 // type = A, class = 0x0001 1737 ).map { it.toByte() }.toByteArray() 1738 1739 program = ApfV6Generator(apfInterpreterVersion, ramSize, clampSize) 1740 .addLoadImmediate(R0, 0) 1741 .addJumpIfPktAtR0ContainDnsQ(needlesMatch, 0x01, DROP_LABEL) // arg2=qtype 1742 .addPass() 1743 .generate() 1744 apfTestHelpers.verifyProgramRun( 1745 apfInterpreterVersion, 1746 program, 1747 badUdpPayload, 1748 CORRUPT_DNS_PACKET, 1749 result = DROP 1750 ) 1751 1752 program = ApfV6Generator(apfInterpreterVersion, ramSize, clampSize) 1753 .addLoadImmediate(R0, 0) 1754 .addJumpIfPktAtR0ContainDnsQSafe(needlesMatch, 0x01, DROP_LABEL) // arg2=qtype 1755 .addPass() 1756 .generate() 1757 apfTestHelpers.verifyProgramRun( 1758 apfInterpreterVersion, 1759 program, 1760 badUdpPayload, 1761 CORRUPT_DNS_PACKET, 1762 result = PASS 1763 ) 1764 } 1765 1766 @Test testDnsAnswerMatchnull1767 fun testDnsAnswerMatch() { 1768 // needles = { A, B.LOCAL } 1769 val needlesMatch = intArrayOf( 1770 0x01, 'A'.code, 1771 0x00, 1772 0x01, 'B'.code, 1773 0x05, 'L'.code, 'O'.code, 'C'.code, 'A'.code, 'L'.code, 1774 0x00, 1775 0x00 1776 ).map { it.toByte() }.toByteArray() 1777 1778 val udpPayload = intArrayOf( 1779 0x00, 0x00, 0x84, 0x00, // tid = 0x00, flags = 0x8400, 1780 0x00, 0x00, // qdcount = 0 1781 0x00, 0x02, // ancount = 2 1782 0x00, 0x00, // nscount = 0 1783 0x00, 0x00, // arcount = 0 1784 0x01, 'a'.code, 1785 0x01, 'b'.code, 1786 0x05, 'l'.code, 'o'.code, 'c'.code, 'a'.code, 'l'.code, 1787 0x00, // name1 = a.b.local 1788 0x00, 0x01, 0x80, 0x01, // type = A, class = 0x8001 1789 0x00, 0x00, 0x00, 0x78, // ttl = 120 1790 0x00, 0x04, 0xc0, 0xa8, 0x01, 0x09, // rdlengh = 4, rdata = 192.168.1.9 1791 0xc0, 0x0e, // name2 = b.local (name compression) 1792 0x00, 0x01, 0x80, 0x01, // type = A, class = 0x8001 1793 0x00, 0x00, 0x00, 0x78, // ttl = 120 1794 0x00, 0x04, 0xc0, 0xa8, 0x01, 0x09 // rdlengh = 4, rdata = 192.168.1.9 1795 ).map { it.toByte() }.toByteArray() 1796 1797 var program = ApfV6Generator(apfInterpreterVersion, ramSize, clampSize) 1798 .addLoadImmediate(R0, 0) 1799 .addJumpIfPktAtR0ContainDnsA(needlesMatch, DROP_LABEL) 1800 .addPass() 1801 .generate() 1802 apfTestHelpers.assertDrop(apfInterpreterVersion, program, udpPayload) 1803 1804 program = ApfV6Generator(apfInterpreterVersion, ramSize, clampSize) 1805 .addLoadImmediate(R0, 0) 1806 .addJumpIfPktAtR0ContainDnsASafe(needlesMatch, DROP_LABEL) 1807 .addPass() 1808 .generate() 1809 apfTestHelpers.assertDrop(apfInterpreterVersion, program, udpPayload) 1810 1811 program = ApfV6Generator(apfInterpreterVersion, ramSize, clampSize) 1812 .addLoadImmediate(R0, 0) 1813 .addJumpIfPktAtR0DoesNotContainDnsA(needlesMatch, DROP_LABEL) 1814 .addPass() 1815 .generate() 1816 apfTestHelpers.assertPass(apfInterpreterVersion, program, udpPayload) 1817 1818 program = ApfV6Generator(apfInterpreterVersion, ramSize, clampSize) 1819 .addLoadImmediate(R0, 0) 1820 .addJumpIfPktAtR0DoesNotContainDnsASafe(needlesMatch, DROP_LABEL) 1821 .addPass() 1822 .generate() 1823 apfTestHelpers.assertPass(apfInterpreterVersion, program, udpPayload) 1824 1825 val badUdpPayload = intArrayOf( 1826 0x00, 0x00, 0x84, 0x00, // tid = 0x00, flags = 0x8400, 1827 0x00, 0x00, // qdcount = 0 1828 0x00, 0x02, // ancount = 2 1829 0x00, 0x00, // nscount = 0 1830 0x00, 0x00, // arcount = 0 1831 0x01, 'a'.code, 1832 0x01, 'b'.code, 1833 0x05, 'l'.code, 'o'.code, 'c'.code, 'a'.code, 'l'.code, 1834 0x00, // name1 = a.b.local 1835 0x00, 0x01, 0x80, 0x01, // type = A, class = 0x8001 1836 0x00, 0x00, 0x00, 0x78, // ttl = 120 1837 0x00, 0x04, 0xc0, 0xa8, 0x01, 0x09, // rdlengh = 4, rdata = 192.168.1.9 1838 0xc0, 0x25, // corrupted pointer cause infinite loop 1839 0x00, 0x01, 0x80, 0x01, // type = A, class = 0x8001 1840 0x00, 0x00, 0x00, 0x78, // ttl = 120 1841 0x00, 0x04, 0xc0, 0xa8, 0x01, 0x09 // rdlengh = 4, rdata = 192.168.1.9 1842 ).map { it.toByte() }.toByteArray() 1843 1844 program = ApfV6Generator(apfInterpreterVersion, ramSize, clampSize) 1845 .addLoadImmediate(R0, 0) 1846 .addJumpIfPktAtR0ContainDnsA(needlesMatch, DROP_LABEL) 1847 .addPass() 1848 .generate() 1849 apfTestHelpers.verifyProgramRun( 1850 apfInterpreterVersion, 1851 program, 1852 badUdpPayload, 1853 CORRUPT_DNS_PACKET, 1854 result = DROP 1855 ) 1856 1857 program = ApfV6Generator(apfInterpreterVersion, ramSize, clampSize) 1858 .addLoadImmediate(R0, 0) 1859 .addJumpIfPktAtR0ContainDnsASafe(needlesMatch, DROP_LABEL) 1860 .addPass() 1861 .generate() 1862 apfTestHelpers.verifyProgramRun( 1863 apfInterpreterVersion, 1864 program, 1865 badUdpPayload, 1866 CORRUPT_DNS_PACKET, 1867 result = PASS 1868 ) 1869 } 1870 1871 @Test testGetCounterValuenull1872 fun testGetCounterValue() { 1873 val counterBytes = intArrayOf(0xff, 0, 0, 0, 0x78, 0x56, 0x34, 0x12) 1874 .map { it.toByte() }.toByteArray() 1875 assertEquals(0xff, ApfCounterTracker.getCounterValue(counterBytes, Counter.TOTAL_PACKETS)) 1876 } 1877 1878 @Test testJumpMultipleByteSequencesMatchnull1879 fun testJumpMultipleByteSequencesMatch() { 1880 var program = ApfV6Generator(apfInterpreterVersion, ramSize, clampSize) 1881 .addLoadImmediate(R0, 0) 1882 .addJumpIfBytesAtR0EqualsAnyOf( 1883 listOf(byteArrayOf(1, 2, 3), byteArrayOf(6, 5, 4)), 1884 DROP_LABEL 1885 ) 1886 .addPass() 1887 .generate() 1888 apfTestHelpers.assertDrop(apfInterpreterVersion, program, testPacket) 1889 1890 program = ApfV6Generator(apfInterpreterVersion, ramSize, clampSize) 1891 .addLoadImmediate(R0, 2) 1892 .addJumpIfBytesAtR0EqualsAnyOf( 1893 listOf(byteArrayOf(1, 2, 3), byteArrayOf(6, 5, 4)), 1894 DROP_LABEL 1895 ) 1896 .addPass() 1897 .generate() 1898 apfTestHelpers.assertPass(apfInterpreterVersion, program, testPacket) 1899 1900 program = ApfV6Generator(apfInterpreterVersion, ramSize, clampSize) 1901 .addLoadImmediate(R0, 1) 1902 .addJumpIfBytesAtR0EqualsNoneOf( 1903 listOf(byteArrayOf(1, 2, 3), byteArrayOf(6, 5, 4)), 1904 DROP_LABEL 1905 ) 1906 .addPass() 1907 .generate() 1908 apfTestHelpers.assertDrop(apfInterpreterVersion, program, testPacket) 1909 1910 program = ApfV6Generator(apfInterpreterVersion, ramSize, clampSize) 1911 .addLoadImmediate(R0, 0) 1912 .addJumpIfBytesAtR0EqualsNoneOf( 1913 listOf(byteArrayOf(1, 2, 3), byteArrayOf(6, 5, 4)), 1914 DROP_LABEL 1915 ) 1916 .addPass() 1917 .generate() 1918 apfTestHelpers.assertPass(apfInterpreterVersion, program, testPacket) 1919 } 1920 1921 @Test testJumpOneOfnull1922 fun testJumpOneOf() { 1923 var program = ApfV6Generator(apfInterpreterVersion, ramSize, clampSize) 1924 .addLoadImmediate(R0, 255) 1925 .addJumpIfOneOf(R0, setOf(1, 2, 3, 128, 255), DROP_LABEL) 1926 .addPass() 1927 .generate() 1928 apfTestHelpers.assertDrop(apfInterpreterVersion, program, testPacket) 1929 1930 program = ApfV6Generator(apfInterpreterVersion, ramSize, clampSize) 1931 .addLoadImmediate(R0, 254) 1932 .addJumpIfOneOf(R0, setOf(1, 2, 3, 128, 255), DROP_LABEL) 1933 .addPass() 1934 .generate() 1935 apfTestHelpers.assertPass(apfInterpreterVersion, program, testPacket) 1936 1937 program = ApfV6Generator(apfInterpreterVersion, ramSize, clampSize) 1938 .addLoadImmediate(R0, 254) 1939 .addJumpIfNoneOf(R0, setOf(1, 2, 3, 128, 255), DROP_LABEL) 1940 .addPass() 1941 .generate() 1942 apfTestHelpers.assertDrop(apfInterpreterVersion, program, testPacket) 1943 1944 program = ApfV6Generator(apfInterpreterVersion, ramSize, clampSize) 1945 .addLoadImmediate(R0, 255) 1946 .addJumpIfNoneOf(R0, setOf(1, 2, 3, 128, 255), DROP_LABEL) 1947 .addPass() 1948 .generate() 1949 apfTestHelpers.assertPass(apfInterpreterVersion, program, testPacket) 1950 } 1951 1952 @Test testDebugBuffernull1953 fun testDebugBuffer() { 1954 val program = ApfV6Generator(apfInterpreterVersion, ramSize, clampSize) 1955 .addLoad8intoR0(255) 1956 .generate() 1957 val dataRegion = ByteArray(ramSize - program.size) { 0 } 1958 1959 apfTestHelpers.assertVerdict(apfInterpreterVersion, PASS, program, testPacket, dataRegion) 1960 // offset 3 in the data region should contain if the interpreter is APFv6 mode or not 1961 assertEquals(1, dataRegion[3]) 1962 } 1963 1964 @Test testGetApfV6BaseProgramSizenull1965 fun testGetApfV6BaseProgramSize() { 1966 val gen = ApfV6Generator(apfInterpreterVersion, ramSize, clampSize) 1967 assertEquals(gen.baseProgramSize, gen.generate().size) 1968 assertEquals(7, gen.baseProgramSize) 1969 } 1970 1971 @Test testGetApfV4BaseProgramSizenull1972 fun testGetApfV4BaseProgramSize() { 1973 val gen = ApfV4Generator(apfInterpreterVersion, ramSize, clampSize) 1974 assertEquals(gen.baseProgramSize, gen.generate().size) 1975 assertEquals(0, gen.baseProgramSize) 1976 } 1977 1978 @Test testGetApfV6DefaultPacketHandlingSizeOverEstimatenull1979 fun testGetApfV6DefaultPacketHandlingSizeOverEstimate() { 1980 val gen = ApfV6Generator(apfInterpreterVersion, ramSize, clampSize) 1981 gen.addDefaultPacketHandling() 1982 val size = gen.programLengthOverEstimate() - gen.baseProgramSize 1983 assertEquals(2, size) 1984 assertEquals(size, gen.defaultPacketHandlingSizeOverEstimate) 1985 } 1986 1987 @Test testGetApfV4DefaultPacketHandlingSizeOverEstimatenull1988 fun testGetApfV4DefaultPacketHandlingSizeOverEstimate() { 1989 val gen = ApfV4Generator(apfInterpreterVersion, ramSize, clampSize) 1990 gen.addDefaultPacketHandling() 1991 val size = gen.programLengthOverEstimate() - gen.baseProgramSize 1992 assertEquals(25, size) 1993 assertEquals(size, gen.defaultPacketHandlingSizeOverEstimate) 1994 } 1995 encodeInstructionnull1996 private fun encodeInstruction(opcode: Int, immLength: Int, register: Int): Byte { 1997 val immLengthEncoding = if (immLength == 4) 3 else immLength 1998 return opcode.shl(3).or(immLengthEncoding.shl(1)).or(register).toByte() 1999 } 2000 ByteArraynull2001 private fun ByteArray.skipDataAndDebug(): ByteArray { 2002 assertEquals( 2003 listOf( 2004 encodeInstruction(14, 2, 1), 2005 0, 2006 0, 2007 encodeInstruction(21, 1, 0), 2008 48 2009 // the actual exception buffer size is not checked here. 2010 ), 2011 this.take(5) 2012 ) 2013 return this.drop(7).toByteArray() 2014 } 2015 } 2016