1 /*
<lambda>null2 * Copyright (C) 2021 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
17 package android.net.cts
18
19 import android.Manifest.permission.MANAGE_TEST_NETWORKS
20 import android.app.Instrumentation
21 import android.content.Context
22 import android.net.ConnectivityManager
23 import android.net.DscpPolicy
24 import android.net.InetAddresses
25 import android.net.IpPrefix
26 import android.net.LinkAddress
27 import android.net.LinkProperties
28 import android.net.MacAddress
29 import android.net.Network
30 import android.net.NetworkAgent
31 import android.net.NetworkAgent.DSCP_POLICY_STATUS_DELETED
32 import android.net.NetworkAgent.DSCP_POLICY_STATUS_SUCCESS
33 import android.net.NetworkAgentConfig
34 import android.net.NetworkCapabilities
35 import android.net.NetworkCapabilities.NET_CAPABILITY_INTERNET
36 import android.net.NetworkCapabilities.NET_CAPABILITY_NOT_RESTRICTED
37 import android.net.NetworkCapabilities.NET_CAPABILITY_NOT_ROAMING
38 import android.net.NetworkCapabilities.NET_CAPABILITY_NOT_SUSPENDED
39 import android.net.NetworkCapabilities.NET_CAPABILITY_NOT_VCN_MANAGED
40 import android.net.NetworkCapabilities.NET_CAPABILITY_NOT_VPN
41 import android.net.NetworkCapabilities.NET_CAPABILITY_TRUSTED
42 import android.net.NetworkCapabilities.TRANSPORT_TEST
43 import android.net.NetworkRequest
44 import android.net.RouteInfo
45 import android.net.TestNetworkInterface
46 import android.net.TestNetworkManager
47 import android.net.TestNetworkManager.TestInterfaceRequest
48 import android.net.cts.util.CtsNetUtils.TestNetworkCallback
49 import android.os.HandlerThread
50 import android.os.SystemClock
51 import android.platform.test.annotations.AppModeFull
52 import android.system.ErrnoException
53 import android.system.Os
54 import android.system.OsConstants.AF_INET
55 import android.system.OsConstants.AF_INET6
56 import android.system.OsConstants.ENETUNREACH
57 import android.system.OsConstants.IPPROTO_UDP
58 import android.system.OsConstants.SOCK_DGRAM
59 import android.system.OsConstants.SOCK_NONBLOCK
60 import android.util.Log
61 import android.util.Range
62 import androidx.test.InstrumentationRegistry
63 import androidx.test.runner.AndroidJUnit4
64 import com.android.net.module.util.IpUtils
65 import com.android.net.module.util.NetworkStackConstants.ETHER_TYPE_IPV4
66 import com.android.net.module.util.NetworkStackConstants.ETHER_TYPE_IPV6
67 import com.android.net.module.util.Struct
68 import com.android.net.module.util.structs.EthernetHeader
69 import com.android.testutils.ArpResponder
70 import com.android.testutils.CompatUtil
71 import com.android.testutils.ConnectivityModuleTest
72 import com.android.testutils.DevSdkIgnoreRule
73 import com.android.testutils.RouterAdvertisementResponder
74 import com.android.testutils.SC_V2
75 import com.android.testutils.PollPacketReader
76 import com.android.testutils.TestableNetworkAgent
77 import com.android.testutils.TestableNetworkAgent.CallbackEntry.OnDscpPolicyStatusUpdated
78 import com.android.testutils.TestableNetworkAgent.CallbackEntry.OnNetworkCreated
79 import com.android.testutils.TestableNetworkCallback
80 import com.android.testutils.assertParcelingIsLossless
81 import com.android.testutils.runAsShell
82 import java.net.Inet4Address
83 import java.net.Inet6Address
84 import java.net.InetSocketAddress
85 import java.nio.ByteBuffer
86 import java.nio.ByteOrder
87 import java.util.regex.Pattern
88 import kotlin.test.assertEquals
89 import kotlin.test.assertNotNull
90 import kotlin.test.assertTrue
91 import kotlin.test.fail
92 import org.junit.After
93 import org.junit.Assume.assumeTrue
94 import org.junit.Before
95 import org.junit.Rule
96 import org.junit.Test
97 import org.junit.runner.RunWith
98
99 private const val MAX_PACKET_LENGTH = 1500
100
101 private const val IP4_PREFIX_LEN = 32
102 private const val IP6_PREFIX_LEN = 128
103
104 private val instrumentation: Instrumentation
105 get() = InstrumentationRegistry.getInstrumentation()
106
107 private const val TAG = "DscpPolicyTest"
108 private const val PACKET_TIMEOUT_MS = 2_000L
109 private const val IPV6_ADDRESS_WAIT_TIME_MS = 10_000L
110
111 @AppModeFull(reason = "Instant apps cannot create test networks")
112 @RunWith(AndroidJUnit4::class)
113 @ConnectivityModuleTest
114 class DscpPolicyTest {
115 @JvmField
116 @Rule
117 val ignoreRule = DevSdkIgnoreRule(ignoreClassUpTo = SC_V2)
118
119 private val LOCAL_IPV4_ADDRESS = InetAddresses.parseNumericAddress("192.0.2.1")
120 private val TEST_TARGET_IPV4_ADDR =
121 InetAddresses.parseNumericAddress("203.0.113.1") as Inet4Address
122 private val TEST_TARGET_IPV6_ADDR =
123 InetAddresses.parseNumericAddress("2001:4860:4860::8888") as Inet6Address
124 private val TEST_ROUTER_IPV6_ADDR =
125 InetAddresses.parseNumericAddress("fe80::1234") as Inet6Address
126 private val TEST_TARGET_MAC_ADDR = MacAddress.fromString("12:34:56:78:9a:bc")
127
128 private val realContext = InstrumentationRegistry.getContext()
129 private val cm = realContext.getSystemService(ConnectivityManager::class.java)!!
130
131 private val agentsToCleanUp = mutableListOf<NetworkAgent>()
132 private val callbacksToCleanUp = mutableListOf<TestableNetworkCallback>()
133
134 private val handlerThread = HandlerThread(DscpPolicyTest::class.java.simpleName)
135
136 private lateinit var srcAddressV6: Inet6Address
137 private lateinit var iface: TestNetworkInterface
138 private lateinit var tunNetworkCallback: TestNetworkCallback
139 private lateinit var reader: PollPacketReader
140 private lateinit var arpResponder: ArpResponder
141 private lateinit var raResponder: RouterAdvertisementResponder
142
143 private fun getKernelVersion(): IntArray {
144 // Example:
145 // 4.9.29-g958411d --> 4.9
146 val release = Os.uname().release
147 val m = Pattern.compile("^(\\d+)\\.(\\d+)").matcher(release)
148 assertTrue(m.find(), "No pattern in release string: " + release)
149 return intArrayOf(Integer.parseInt(m.group(1)), Integer.parseInt(m.group(2)))
150 }
151
152 // TODO: replace with DeviceInfoUtils#isKernelVersionAtLeast
153 private fun kernelIsAtLeast(major: Int, minor: Int): Boolean {
154 val version = getKernelVersion()
155 return (version.get(0) > major || (version.get(0) == major && version.get(1) >= minor))
156 }
157
158 @Before
159 fun setUp() {
160 // For BPF support kernel needs to be at least 5.15.
161 assumeTrue(kernelIsAtLeast(5, 15))
162
163 runAsShell(MANAGE_TEST_NETWORKS) {
164 val tnm = realContext.getSystemService(TestNetworkManager::class.java)!!
165
166 // Only statically configure the IPv4 address; for IPv6, use the SLAAC generated
167 // address.
168 val req = TestInterfaceRequest.Builder()
169 .setTap()
170 .addLinkAddress(LinkAddress(LOCAL_IPV4_ADDRESS, IP4_PREFIX_LEN))
171 .build()
172 iface = tnm.createTestInterface(req)
173 assertNotNull(iface)
174 }
175
176 handlerThread.start()
177 reader = PollPacketReader(
178 handlerThread.threadHandler,
179 iface.fileDescriptor.fileDescriptor,
180 MAX_PACKET_LENGTH)
181 reader.startAsyncForTest()
182
183 arpResponder = ArpResponder(reader, mapOf(TEST_TARGET_IPV4_ADDR to TEST_TARGET_MAC_ADDR))
184 arpResponder.start()
185 raResponder = RouterAdvertisementResponder(reader)
186 raResponder.addRouterEntry(TEST_TARGET_MAC_ADDR, TEST_ROUTER_IPV6_ADDR)
187 raResponder.start()
188 }
189
190 @After
191 fun tearDown() {
192 if (!kernelIsAtLeast(5, 15)) {
193 return
194 }
195 raResponder.stop()
196 arpResponder.stop()
197
198 agentsToCleanUp.forEach { it.unregister() }
199 callbacksToCleanUp.forEach { cm.unregisterNetworkCallback(it) }
200
201 // reader.stop() cleans up tun fd
202 reader.handler.post { reader.stop() }
203 // quitSafely processes all events in the queue, except delayed messages.
204 handlerThread.quitSafely()
205 handlerThread.join()
206 }
207
208 private fun requestNetwork(request: NetworkRequest, callback: TestableNetworkCallback) {
209 cm.requestNetwork(request, callback)
210 callbacksToCleanUp.add(callback)
211 }
212
213 private fun makeTestNetworkRequest(specifier: String? = null): NetworkRequest {
214 return NetworkRequest.Builder()
215 .clearCapabilities()
216 .addCapability(NET_CAPABILITY_NOT_RESTRICTED)
217 .addTransportType(TRANSPORT_TEST)
218 .also {
219 if (specifier != null) {
220 it.setNetworkSpecifier(CompatUtil.makeTestNetworkSpecifier(specifier))
221 }
222 }
223 .build()
224 }
225
226 private fun waitForGlobalIpv6Address(network: Network): Inet6Address {
227 // Wait for global IPv6 address to be available
228 var inet6Addr: Inet6Address? = null
229 val onLinkPrefix = raResponder.prefix
230 val startTime = SystemClock.elapsedRealtime()
231 while (SystemClock.elapsedRealtime() - startTime < IPV6_ADDRESS_WAIT_TIME_MS) {
232 SystemClock.sleep(50 /* ms */)
233 val sock = Os.socket(AF_INET6, SOCK_DGRAM, IPPROTO_UDP)
234 try {
235 network.bindSocket(sock)
236
237 try {
238 // Pick any arbitrary port
239 Os.connect(sock, TEST_TARGET_IPV6_ADDR, 12345)
240 } catch (e: ErrnoException) {
241 // there may not be an address available yet.
242 if (e.errno == ENETUNREACH) continue
243 throw e
244 }
245 val sockAddr = Os.getsockname(sock) as InetSocketAddress
246 if (onLinkPrefix.contains(sockAddr.address)) {
247 inet6Addr = sockAddr.address as Inet6Address
248 break
249 }
250 } finally {
251 Os.close(sock)
252 }
253 }
254 assertNotNull(inet6Addr)
255 return inet6Addr!!
256 }
257
258 private fun createConnectedNetworkAgent(
259 context: Context = realContext,
260 specifier: String? = iface.getInterfaceName()
261 ): Pair<TestableNetworkAgent, TestableNetworkCallback> {
262 val callback = TestableNetworkCallback()
263 // Ensure this NetworkAgent is never unneeded by filing a request with its specifier.
264 requestNetwork(makeTestNetworkRequest(specifier = specifier), callback)
265
266 val nc = NetworkCapabilities().apply {
267 addTransportType(TRANSPORT_TEST)
268 removeCapability(NET_CAPABILITY_TRUSTED)
269 removeCapability(NET_CAPABILITY_INTERNET)
270 addCapability(NET_CAPABILITY_NOT_SUSPENDED)
271 addCapability(NET_CAPABILITY_NOT_ROAMING)
272 addCapability(NET_CAPABILITY_NOT_VPN)
273 addCapability(NET_CAPABILITY_NOT_VCN_MANAGED)
274 if (null != specifier) {
275 setNetworkSpecifier(CompatUtil.makeTestNetworkSpecifier(specifier))
276 }
277 }
278 val lp = LinkProperties().apply {
279 addLinkAddress(LinkAddress(LOCAL_IPV4_ADDRESS, IP4_PREFIX_LEN))
280 addRoute(RouteInfo(IpPrefix("0.0.0.0/0"), null, null))
281 setInterfaceName(specifier)
282 }
283 val config = NetworkAgentConfig.Builder().build()
284 val agent = TestableNetworkAgent(context, handlerThread.looper, nc, lp, config)
285 agentsToCleanUp.add(agent)
286
287 // Connect the agent and verify initial status callbacks.
288 runAsShell(MANAGE_TEST_NETWORKS) { agent.register() }
289 agent.markConnected()
290 agent.expectCallback<OnNetworkCreated>()
291 agent.expectSignalStrengths(intArrayOf())
292 agent.expectValidationBypassedStatus()
293
294 val network = agent.network ?: fail("Expected a non-null network")
295 srcAddressV6 = waitForGlobalIpv6Address(network)
296 return agent to callback
297 }
298
299 fun ByteArray.toHex(): String = joinToString(separator = "") {
300 eachByte -> "%02x".format(eachByte)
301 }
302
303 fun sendPacket(
304 agent: TestableNetworkAgent,
305 sendV6: Boolean,
306 dstPort: Int = 0,
307 times: Int = 1
308 ) {
309 val testString = "test string"
310 val testPacket = ByteBuffer.wrap(testString.toByteArray(Charsets.UTF_8))
311 var packetFound = false
312
313 val socket = Os.socket(if (sendV6) AF_INET6 else AF_INET, SOCK_DGRAM or SOCK_NONBLOCK,
314 IPPROTO_UDP)
315 checkNotNull(agent.network).bindSocket(socket)
316
317 val origPacket = testPacket.readAsArray()
318 repeat(times) {
319 Os.sendto(socket, origPacket, 0 /* bytesOffset */, origPacket.size, 0 /* flags */,
320 if (sendV6) TEST_TARGET_IPV6_ADDR else TEST_TARGET_IPV4_ADDR, dstPort)
321 }
322 Os.close(socket)
323 }
324
325 fun parseV4PacketDscp(buffer: ByteBuffer): Int {
326 // Validate checksum before parsing packet.
327 val calCheck = IpUtils.ipChecksum(buffer, Struct.getSize(EthernetHeader::class.java))
328 assertEquals(0, calCheck, "Invalid IPv4 header checksum")
329
330 val ip_ver = buffer.get()
331 val tos = buffer.get()
332 val length = buffer.getShort()
333 val id = buffer.getShort()
334 val offset = buffer.getShort()
335 val ttl = buffer.get()
336 val ipType = buffer.get()
337 val checksum = buffer.getShort()
338
339 if (ipType.toInt() == 2 /* IPPROTO_IGMP */ && ip_ver.toInt() == 0x46) {
340 // Need to ignore 'igmp v3 report' with 'router alert' option
341 } else {
342 assertEquals(0x45, ip_ver.toInt(), "Invalid IPv4 version or IPv4 options present")
343 }
344 return tos.toInt().shr(2)
345 }
346
347 fun parseV6PacketDscp(buffer: ByteBuffer): Int {
348 val ip_ver = buffer.get()
349 val tc = buffer.get()
350 val fl = buffer.getShort()
351 val length = buffer.getShort()
352 val proto = buffer.get()
353 val hop = buffer.get()
354
355 assertEquals(6, ip_ver.toInt().shr(4), "Invalid IPv6 version")
356
357 // DSCP is bottom 4 bits of ip_ver and top 2 of tc.
358 val ip_ver_bottom = ip_ver.toInt().and(0xf)
359 val tc_dscp = tc.toInt().shr(6)
360 return ip_ver_bottom.toInt().shl(2) + tc_dscp
361 }
362
363 fun parsePacketIp(
364 buffer: ByteBuffer,
365 sendV6: Boolean
366 ): Boolean {
367 val ipAddr = if (sendV6) ByteArray(16) else ByteArray(4)
368 buffer.get(ipAddr)
369 val srcIp = if (sendV6) Inet6Address.getByAddress(ipAddr)
370 else Inet4Address.getByAddress(ipAddr)
371 buffer.get(ipAddr)
372 val dstIp = if (sendV6) Inet6Address.getByAddress(ipAddr)
373 else Inet4Address.getByAddress(ipAddr)
374
375 Log.e(TAG, "IP Src:" + srcIp + " dst: " + dstIp)
376
377 if ((sendV6 && srcIp == srcAddressV6 && dstIp == TEST_TARGET_IPV6_ADDR) ||
378 (!sendV6 && srcIp == LOCAL_IPV4_ADDRESS && dstIp == TEST_TARGET_IPV4_ADDR)) {
379 Log.e(TAG, "IP return true")
380 return true
381 }
382 Log.e(TAG, "IP return false")
383 return false
384 }
385
386 fun parsePacketPort(
387 buffer: ByteBuffer,
388 srcPort: Int,
389 dstPort: Int
390 ): Boolean {
391 if (srcPort == 0 && dstPort == 0) return true
392
393 val packetSrcPort = buffer.getShort().toInt()
394 val packetDstPort = buffer.getShort().toInt()
395
396 Log.e(TAG, "Port Src:" + packetSrcPort + " dst: " + packetDstPort)
397
398 if ((srcPort == 0 || (srcPort != 0 && srcPort == packetSrcPort)) &&
399 (dstPort == 0 || (dstPort != 0 && dstPort == packetDstPort))) {
400 Log.e(TAG, "Port return true")
401 return true
402 }
403 Log.e(TAG, "Port return false")
404 return false
405 }
406
407 fun validatePacket(
408 agent: TestableNetworkAgent,
409 sendV6: Boolean = false,
410 dscpValue: Int = 0,
411 dstPort: Int = 0,
412 times: Int = 1
413 ) {
414 var packetFound = 0
415 sendPacket(agent, sendV6, dstPort, times)
416 // TODO: grab source port from socket in sendPacket
417
418 Log.e(TAG, "find DSCP value:" + dscpValue)
419 val packets = generateSequence { reader.poll(PACKET_TIMEOUT_MS) }
420 for (packet in packets) {
421 val buffer = ByteBuffer.wrap(packet, 0, packet.size).order(ByteOrder.BIG_ENDIAN)
422
423 // TODO: consider using Struct.parse for all packet parsing.
424 val etherHdr = Struct.parse(EthernetHeader::class.java, buffer)
425 val expectedType = if (sendV6) ETHER_TYPE_IPV6 else ETHER_TYPE_IPV4
426 if (etherHdr.etherType != expectedType) {
427 continue
428 }
429 val dscp = if (sendV6) parseV6PacketDscp(buffer) else parseV4PacketDscp(buffer)
430 Log.e(TAG, "DSCP value:" + dscp)
431
432 // TODO: Add source port comparison. Use 0 for now.
433 if (parsePacketIp(buffer, sendV6) && parsePacketPort(buffer, 0, dstPort)) {
434 Log.e(TAG, "DSCP value found")
435 assertEquals(dscpValue, dscp)
436 packetFound++
437 }
438 }
439 assertTrue(packetFound == times)
440 }
441
442 fun validatePackets(
443 agent: TestableNetworkAgent,
444 sendV6: Boolean = false,
445 dscpValue: Int = 0,
446 dstPort: Int = 0
447 ) {
448 // We send two packets from the same socket to verify
449 // socket caching works correctly.
450 validatePacket(agent, sendV6, dscpValue, dstPort, 2)
451 // Try one more time from a different socket.
452 validatePacket(agent, sendV6, dscpValue, dstPort, 1)
453 }
454
455 fun doRemovePolicyTest(
456 agent: TestableNetworkAgent,
457 callback: TestableNetworkCallback,
458 policyId: Int
459 ) {
460 val portNumber = 1111 * policyId
461 agent.sendRemoveDscpPolicy(policyId)
462 agent.expectCallback<OnDscpPolicyStatusUpdated>().let {
463 assertEquals(policyId, it.policyId)
464 assertEquals(DSCP_POLICY_STATUS_DELETED, it.status)
465 }
466 }
467
468 @Test
469 fun testDscpPolicyAddPolicies(): Unit = createConnectedNetworkAgent().let {
470 (agent, callback) ->
471 val policy = DscpPolicy.Builder(1, 1)
472 .setDestinationPortRange(Range(4444, 4444)).build()
473 agent.sendAddDscpPolicy(policy)
474 agent.expectCallback<OnDscpPolicyStatusUpdated>().let {
475 assertEquals(1, it.policyId)
476 assertEquals(DSCP_POLICY_STATUS_SUCCESS, it.status)
477 }
478 validatePackets(agent, dscpValue = 1, dstPort = 4444)
479
480 agent.sendRemoveDscpPolicy(1)
481 agent.expectCallback<OnDscpPolicyStatusUpdated>().let {
482 assertEquals(1, it.policyId)
483 assertEquals(DSCP_POLICY_STATUS_DELETED, it.status)
484 }
485
486 val policy2 = DscpPolicy.Builder(1, 4)
487 .setDestinationPortRange(Range(5555, 5555))
488 .setDestinationAddress(TEST_TARGET_IPV4_ADDR)
489 .setSourceAddress(LOCAL_IPV4_ADDRESS)
490 .setProtocol(IPPROTO_UDP).build()
491 agent.sendAddDscpPolicy(policy2)
492 agent.expectCallback<OnDscpPolicyStatusUpdated>().let {
493 assertEquals(1, it.policyId)
494 assertEquals(DSCP_POLICY_STATUS_SUCCESS, it.status)
495 }
496
497 validatePackets(agent, dscpValue = 4, dstPort = 5555)
498
499 agent.sendRemoveDscpPolicy(1)
500 agent.expectCallback<OnDscpPolicyStatusUpdated>().let {
501 assertEquals(1, it.policyId)
502 assertEquals(DSCP_POLICY_STATUS_DELETED, it.status)
503 }
504 }
505
506 @Test
507 fun testDscpPolicyAddV6Policies(): Unit = createConnectedNetworkAgent().let {
508 (agent, callback) ->
509 val policy = DscpPolicy.Builder(1, 1)
510 .setDestinationPortRange(Range(4444, 4444)).build()
511 agent.sendAddDscpPolicy(policy)
512 agent.expectCallback<OnDscpPolicyStatusUpdated>().let {
513 assertEquals(1, it.policyId)
514 assertEquals(DSCP_POLICY_STATUS_SUCCESS, it.status)
515 }
516 validatePackets(agent, true, dscpValue = 1, dstPort = 4444)
517
518 agent.sendRemoveDscpPolicy(1)
519 agent.expectCallback<OnDscpPolicyStatusUpdated>().let {
520 assertEquals(1, it.policyId)
521 assertEquals(DSCP_POLICY_STATUS_DELETED, it.status)
522 }
523
524 val policy2 = DscpPolicy.Builder(1, 4)
525 .setDestinationPortRange(Range(5555, 5555))
526 .setDestinationAddress(TEST_TARGET_IPV6_ADDR)
527 .setSourceAddress(srcAddressV6)
528 .setProtocol(IPPROTO_UDP).build()
529 agent.sendAddDscpPolicy(policy2)
530 agent.expectCallback<OnDscpPolicyStatusUpdated>().let {
531 assertEquals(1, it.policyId)
532 assertEquals(DSCP_POLICY_STATUS_SUCCESS, it.status)
533 }
534 validatePackets(agent, true, dscpValue = 4, dstPort = 5555)
535
536 agent.sendRemoveDscpPolicy(1)
537 agent.expectCallback<OnDscpPolicyStatusUpdated>().let {
538 assertEquals(1, it.policyId)
539 assertEquals(DSCP_POLICY_STATUS_DELETED, it.status)
540 }
541 }
542
543 @Test
544 // Remove policies in the same order as addition.
545 fun testRemoveDscpPolicy_RemoveSameOrderAsAdd(): Unit = createConnectedNetworkAgent().let {
546 (agent, callback) ->
547 val policy = DscpPolicy.Builder(1, 1).setDestinationPortRange(Range(1111, 1111)).build()
548 agent.sendAddDscpPolicy(policy)
549 agent.expectCallback<OnDscpPolicyStatusUpdated>().let {
550 assertEquals(1, it.policyId)
551 assertEquals(DSCP_POLICY_STATUS_SUCCESS, it.status)
552 validatePackets(agent, dscpValue = 1, dstPort = 1111)
553 }
554
555 val policy2 = DscpPolicy.Builder(2, 1).setDestinationPortRange(Range(2222, 2222)).build()
556 agent.sendAddDscpPolicy(policy2)
557 agent.expectCallback<OnDscpPolicyStatusUpdated>().let {
558 assertEquals(2, it.policyId)
559 assertEquals(DSCP_POLICY_STATUS_SUCCESS, it.status)
560 validatePackets(agent, dscpValue = 1, dstPort = 2222)
561 }
562
563 val policy3 = DscpPolicy.Builder(3, 1).setDestinationPortRange(Range(3333, 3333)).build()
564 agent.sendAddDscpPolicy(policy3)
565 agent.expectCallback<OnDscpPolicyStatusUpdated>().let {
566 assertEquals(3, it.policyId)
567 assertEquals(DSCP_POLICY_STATUS_SUCCESS, it.status)
568 validatePackets(agent, dscpValue = 1, dstPort = 3333)
569 }
570
571 /* Remove Policies and check CE is no longer set */
572 doRemovePolicyTest(agent, callback, 1)
573 validatePackets(agent, dscpValue = 0, dstPort = 1111)
574 doRemovePolicyTest(agent, callback, 2)
575 validatePackets(agent, dscpValue = 0, dstPort = 2222)
576 doRemovePolicyTest(agent, callback, 3)
577 validatePackets(agent, dscpValue = 0, dstPort = 3333)
578 }
579
580 @Test
581 fun testRemoveDscpPolicy_RemoveImmediatelyAfterAdd(): Unit =
582 createConnectedNetworkAgent().let { (agent, callback) ->
583 val policy = DscpPolicy.Builder(1, 1).setDestinationPortRange(Range(1111, 1111)).build()
584 agent.sendAddDscpPolicy(policy)
585 agent.expectCallback<OnDscpPolicyStatusUpdated>().let {
586 assertEquals(1, it.policyId)
587 assertEquals(DSCP_POLICY_STATUS_SUCCESS, it.status)
588 validatePackets(agent, dscpValue = 1, dstPort = 1111)
589 }
590 doRemovePolicyTest(agent, callback, 1)
591
592 val policy2 = DscpPolicy.Builder(2, 1).setDestinationPortRange(Range(2222, 2222)).build()
593 agent.sendAddDscpPolicy(policy2)
594 agent.expectCallback<OnDscpPolicyStatusUpdated>().let {
595 assertEquals(2, it.policyId)
596 assertEquals(DSCP_POLICY_STATUS_SUCCESS, it.status)
597 validatePackets(agent, dscpValue = 1, dstPort = 2222)
598 }
599 doRemovePolicyTest(agent, callback, 2)
600
601 val policy3 = DscpPolicy.Builder(3, 1).setDestinationPortRange(Range(3333, 3333)).build()
602 agent.sendAddDscpPolicy(policy3)
603 agent.expectCallback<OnDscpPolicyStatusUpdated>().let {
604 assertEquals(3, it.policyId)
605 assertEquals(DSCP_POLICY_STATUS_SUCCESS, it.status)
606 validatePackets(agent, dscpValue = 1, dstPort = 3333)
607 }
608 doRemovePolicyTest(agent, callback, 3)
609 }
610
611 @Test
612 // Remove policies in reverse order from addition.
613 fun testRemoveDscpPolicy_RemoveReverseOrder(): Unit =
614 createConnectedNetworkAgent().let { (agent, callback) ->
615 val policy = DscpPolicy.Builder(1, 1).setDestinationPortRange(Range(1111, 1111)).build()
616 agent.sendAddDscpPolicy(policy)
617 agent.expectCallback<OnDscpPolicyStatusUpdated>().let {
618 assertEquals(1, it.policyId)
619 assertEquals(DSCP_POLICY_STATUS_SUCCESS, it.status)
620 validatePackets(agent, dscpValue = 1, dstPort = 1111)
621 }
622
623 val policy2 = DscpPolicy.Builder(2, 1).setDestinationPortRange(Range(2222, 2222)).build()
624 agent.sendAddDscpPolicy(policy2)
625 agent.expectCallback<OnDscpPolicyStatusUpdated>().let {
626 assertEquals(2, it.policyId)
627 assertEquals(DSCP_POLICY_STATUS_SUCCESS, it.status)
628 validatePackets(agent, dscpValue = 1, dstPort = 2222)
629 }
630
631 val policy3 = DscpPolicy.Builder(3, 1).setDestinationPortRange(Range(3333, 3333)).build()
632 agent.sendAddDscpPolicy(policy3)
633 agent.expectCallback<OnDscpPolicyStatusUpdated>().let {
634 assertEquals(3, it.policyId)
635 assertEquals(DSCP_POLICY_STATUS_SUCCESS, it.status)
636 validatePackets(agent, dscpValue = 1, dstPort = 3333)
637 }
638
639 /* Remove Policies and check CE is no longer set */
640 doRemovePolicyTest(agent, callback, 3)
641 doRemovePolicyTest(agent, callback, 2)
642 doRemovePolicyTest(agent, callback, 1)
643 }
644
645 @Test
646 fun testRemoveDscpPolicy_InvalidPolicy(): Unit = createConnectedNetworkAgent().let {
647 (agent, callback) ->
648 agent.sendRemoveDscpPolicy(3)
649 // Is there something to add in TestableNetworkCallback to NOT expect a callback?
650 // Or should we send DSCP_POLICY_STATUS_DELETED in any case or a different STATUS?
651 }
652
653 @Test
654 fun testRemoveAllDscpPolicies(): Unit = createConnectedNetworkAgent().let {
655 (agent, callback) ->
656 val policy = DscpPolicy.Builder(1, 1)
657 .setDestinationPortRange(Range(1111, 1111)).build()
658 agent.sendAddDscpPolicy(policy)
659 agent.expectCallback<OnDscpPolicyStatusUpdated>().let {
660 assertEquals(1, it.policyId)
661 assertEquals(DSCP_POLICY_STATUS_SUCCESS, it.status)
662 validatePackets(agent, dscpValue = 1, dstPort = 1111)
663 }
664
665 val policy2 = DscpPolicy.Builder(2, 1)
666 .setDestinationPortRange(Range(2222, 2222)).build()
667 agent.sendAddDscpPolicy(policy2)
668 agent.expectCallback<OnDscpPolicyStatusUpdated>().let {
669 assertEquals(2, it.policyId)
670 assertEquals(DSCP_POLICY_STATUS_SUCCESS, it.status)
671 validatePackets(agent, dscpValue = 1, dstPort = 2222)
672 }
673
674 val policy3 = DscpPolicy.Builder(3, 1)
675 .setDestinationPortRange(Range(3333, 3333)).build()
676 agent.sendAddDscpPolicy(policy3)
677 agent.expectCallback<OnDscpPolicyStatusUpdated>().let {
678 assertEquals(3, it.policyId)
679 assertEquals(DSCP_POLICY_STATUS_SUCCESS, it.status)
680 validatePackets(agent, dscpValue = 1, dstPort = 3333)
681 }
682
683 agent.sendRemoveAllDscpPolicies()
684 agent.expectCallback<OnDscpPolicyStatusUpdated>().let {
685 assertEquals(1, it.policyId)
686 assertEquals(DSCP_POLICY_STATUS_DELETED, it.status)
687 validatePackets(agent, false, dstPort = 1111)
688 }
689 agent.expectCallback<OnDscpPolicyStatusUpdated>().let {
690 assertEquals(2, it.policyId)
691 assertEquals(DSCP_POLICY_STATUS_DELETED, it.status)
692 validatePackets(agent, false, dstPort = 2222)
693 }
694 agent.expectCallback<OnDscpPolicyStatusUpdated>().let {
695 assertEquals(3, it.policyId)
696 assertEquals(DSCP_POLICY_STATUS_DELETED, it.status)
697 validatePackets(agent, false, dstPort = 3333)
698 }
699 }
700
701 @Test
702 fun testAddDuplicateDscpPolicy(): Unit = createConnectedNetworkAgent().let {
703 (agent, callback) ->
704 val policy = DscpPolicy.Builder(1, 1).setDestinationPortRange(Range(4444, 4444)).build()
705 agent.sendAddDscpPolicy(policy)
706 agent.expectCallback<OnDscpPolicyStatusUpdated>().let {
707 assertEquals(1, it.policyId)
708 assertEquals(DSCP_POLICY_STATUS_SUCCESS, it.status)
709 validatePackets(agent, dscpValue = 1, dstPort = 4444)
710 }
711
712 val policy2 = DscpPolicy.Builder(1, 1).setDestinationPortRange(Range(5555, 5555)).build()
713 agent.sendAddDscpPolicy(policy2)
714 agent.expectCallback<OnDscpPolicyStatusUpdated>().let {
715 assertEquals(1, it.policyId)
716 assertEquals(DSCP_POLICY_STATUS_SUCCESS, it.status)
717
718 // Sending packet with old policy should fail
719 validatePackets(agent, dscpValue = 0, dstPort = 4444)
720 validatePackets(agent, dscpValue = 1, dstPort = 5555)
721 }
722
723 agent.sendRemoveDscpPolicy(1)
724 agent.expectCallback<OnDscpPolicyStatusUpdated>().let {
725 assertEquals(1, it.policyId)
726 assertEquals(DSCP_POLICY_STATUS_DELETED, it.status)
727 }
728 }
729
730 @Test
731 fun testParcelingDscpPolicyIsLossless(): Unit = createConnectedNetworkAgent().let {
732 (agent, callback) ->
733 val policyId = 1
734 val dscpValue = 1
735 val range = Range(4444, 4444)
736 val srcPort = 555
737
738 // Check that policy with partial parameters is lossless.
739 val policy = DscpPolicy.Builder(policyId, dscpValue).setDestinationPortRange(range).build()
740 assertEquals(policyId, policy.policyId)
741 assertEquals(dscpValue, policy.dscpValue)
742 assertEquals(range, policy.destinationPortRange)
743 assertParcelingIsLossless(policy)
744
745 // Check that policy with all parameters is lossless.
746 val policy2 = DscpPolicy.Builder(policyId, dscpValue).setDestinationPortRange(range)
747 .setSourceAddress(LOCAL_IPV4_ADDRESS)
748 .setDestinationAddress(TEST_TARGET_IPV4_ADDR)
749 .setSourcePort(srcPort)
750 .setProtocol(IPPROTO_UDP).build()
751 assertEquals(policyId, policy2.policyId)
752 assertEquals(dscpValue, policy2.dscpValue)
753 assertEquals(range, policy2.destinationPortRange)
754 assertEquals(TEST_TARGET_IPV4_ADDR, policy2.destinationAddress)
755 assertEquals(LOCAL_IPV4_ADDRESS, policy2.sourceAddress)
756 assertEquals(srcPort, policy2.sourcePort)
757 assertEquals(IPPROTO_UDP, policy2.protocol)
758 assertParcelingIsLossless(policy2)
759 }
760
761 @Test
762 fun testSendDscpPolicyWithoutInterfaceName() {
763 val nc = NetworkCapabilities().apply {
764 addTransportType(TRANSPORT_TEST)
765 }
766 val agent = TestableNetworkAgent(
767 realContext,
768 handlerThread.looper,
769 nc,
770 LinkProperties() /* note: no interface name */,
771 NetworkAgentConfig.Builder().build()
772 )
773 agentsToCleanUp.add(agent)
774 runAsShell(MANAGE_TEST_NETWORKS) { agent.register() }
775 // Without the fix, this will crash the system with SIGSEGV.
776 agent.sendAddDscpPolicy(DscpPolicy.Builder(1, 1).build())
777 // Will receive OnNetworkCreated first if the agent is created early. To avoid reading
778 // the flag here, use eventuallyExpect.
779 agent.eventuallyExpect<OnDscpPolicyStatusUpdated>()
780 }
781 }
782
readAsArraynull783 private fun ByteBuffer.readAsArray(): ByteArray {
784 val out = ByteArray(remaining())
785 get(out)
786 return out
787 }
788
assertHasServicenull789 private fun <T> Context.assertHasService(manager: Class<T>): T {
790 return getSystemService(manager) ?: fail("Service $manager not found")
791 }
792