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.net.cts.util.CtsNetUtils.TestNetworkCallback
20
21 import android.app.Instrumentation
22 import android.Manifest.permission.MANAGE_TEST_NETWORKS
23 import android.content.Context
24 import android.net.ConnectivityManager
25 import android.net.DscpPolicy
26 import android.net.InetAddresses
27 import android.net.IpPrefix
28 import android.net.LinkAddress
29 import android.net.LinkProperties
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.TestNetworkInterface
45 import android.net.TestNetworkManager
46 import android.net.RouteInfo
47 import android.os.HandlerThread
48 import android.platform.test.annotations.AppModeFull
49 import android.system.Os
50 import android.system.OsConstants.AF_INET
51 import android.system.OsConstants.AF_INET6
52 import android.system.OsConstants.IPPROTO_UDP
53 import android.system.OsConstants.SOCK_DGRAM
54 import android.system.OsConstants.SOCK_NONBLOCK
55 import android.util.Log
56 import android.util.Range
57 import androidx.test.InstrumentationRegistry
58 import androidx.test.runner.AndroidJUnit4
59 import com.android.testutils.CompatUtil
60 import com.android.testutils.DevSdkIgnoreRule
61 import com.android.testutils.assertParcelingIsLossless
62 import com.android.testutils.runAsShell
63 import com.android.testutils.SC_V2
64 import com.android.testutils.TapPacketReader
65 import com.android.testutils.TestableNetworkAgent
66 import com.android.testutils.TestableNetworkAgent.CallbackEntry.OnNetworkCreated
67 import com.android.testutils.TestableNetworkAgent.CallbackEntry.OnDscpPolicyStatusUpdated
68 import com.android.testutils.TestableNetworkCallback
69 import org.junit.After
70 import org.junit.Assume.assumeTrue
71 import org.junit.Before
72 import org.junit.Rule
73 import org.junit.Test
74 import org.junit.runner.RunWith
75 import java.net.Inet4Address
76 import java.net.Inet6Address
77 import java.net.InetAddress
78 import java.nio.ByteBuffer
79 import java.nio.ByteOrder
80 import java.util.regex.Pattern
81 import kotlin.test.assertEquals
82 import kotlin.test.assertNotNull
83 import kotlin.test.assertTrue
84 import kotlin.test.fail
85
86 private const val MAX_PACKET_LENGTH = 1500
87
88 private const val IP4_PREFIX_LEN = 32
89 private const val IP6_PREFIX_LEN = 128
90
91 private val instrumentation: Instrumentation
92 get() = InstrumentationRegistry.getInstrumentation()
93
94 private const val TAG = "DscpPolicyTest"
95 private const val PACKET_TIMEOUT_MS = 2_000L
96
97 @AppModeFull(reason = "Instant apps cannot create test networks")
98 @RunWith(AndroidJUnit4::class)
99 class DscpPolicyTest {
100 @JvmField
101 @Rule
102 val ignoreRule = DevSdkIgnoreRule(ignoreClassUpTo = SC_V2)
103
104 private val LOCAL_IPV4_ADDRESS = InetAddresses.parseNumericAddress("192.0.2.1")
105 private val TEST_TARGET_IPV4_ADDR =
106 InetAddresses.parseNumericAddress("8.8.8.8") as Inet4Address
107 private val LOCAL_IPV6_ADDRESS = InetAddresses.parseNumericAddress("2001:db8::1")
108 private val TEST_TARGET_IPV6_ADDR =
109 InetAddresses.parseNumericAddress("2001:4860:4860::8888") as Inet6Address
110
111 private val realContext = InstrumentationRegistry.getContext()
112 private val cm = realContext.getSystemService(ConnectivityManager::class.java)
113
114 private val agentsToCleanUp = mutableListOf<NetworkAgent>()
115 private val callbacksToCleanUp = mutableListOf<TestableNetworkCallback>()
116
117 private val handlerThread = HandlerThread(DscpPolicyTest::class.java.simpleName)
118
119 private lateinit var iface: TestNetworkInterface
120 private lateinit var tunNetworkCallback: TestNetworkCallback
121 private lateinit var reader: TapPacketReader
122
123 private fun getKernelVersion(): IntArray {
124 // Example:
125 // 4.9.29-g958411d --> 4.9
126 val release = Os.uname().release
127 val m = Pattern.compile("^(\\d+)\\.(\\d+)").matcher(release)
128 assertTrue(m.find(), "No pattern in release string: " + release)
129 return intArrayOf(Integer.parseInt(m.group(1)), Integer.parseInt(m.group(2)))
130 }
131
132 private fun kernelIsAtLeast(major: Int, minor: Int): Boolean {
133 val version = getKernelVersion()
134 return (version.get(0) > major || (version.get(0) == major && version.get(1) >= minor))
135 }
136
137 @Before
138 fun setUp() {
139 // For BPF support kernel needs to be at least 5.15.
140 assumeTrue(kernelIsAtLeast(5, 15))
141
142 runAsShell(MANAGE_TEST_NETWORKS) {
143 val tnm = realContext.getSystemService(TestNetworkManager::class.java)
144
145 iface = tnm.createTunInterface(arrayOf(
146 LinkAddress(LOCAL_IPV4_ADDRESS, IP4_PREFIX_LEN),
147 LinkAddress(LOCAL_IPV6_ADDRESS, IP6_PREFIX_LEN)))
148 assertNotNull(iface)
149 }
150
151 handlerThread.start()
152 reader = TapPacketReader(
153 handlerThread.threadHandler,
154 iface.fileDescriptor.fileDescriptor,
155 MAX_PACKET_LENGTH)
156 reader.startAsyncForTest()
157 }
158
159 @After
160 fun tearDown() {
161 if (!kernelIsAtLeast(5, 15)) {
162 return;
163 }
164 agentsToCleanUp.forEach { it.unregister() }
165 callbacksToCleanUp.forEach { cm.unregisterNetworkCallback(it) }
166
167 // reader.stop() cleans up tun fd
168 reader.handler.post { reader.stop() }
169 if (iface.fileDescriptor.fileDescriptor != null)
170 Os.close(iface.fileDescriptor.fileDescriptor)
171 handlerThread.quitSafely()
172 }
173
174 private fun requestNetwork(request: NetworkRequest, callback: TestableNetworkCallback) {
175 cm.requestNetwork(request, callback)
176 callbacksToCleanUp.add(callback)
177 }
178
179 private fun makeTestNetworkRequest(specifier: String? = null): NetworkRequest {
180 return NetworkRequest.Builder()
181 .clearCapabilities()
182 .addCapability(NET_CAPABILITY_NOT_RESTRICTED)
183 .addTransportType(TRANSPORT_TEST)
184 .also {
185 if (specifier != null) {
186 it.setNetworkSpecifier(CompatUtil.makeTestNetworkSpecifier(specifier))
187 }
188 }
189 .build()
190 }
191
192 private fun createConnectedNetworkAgent(
193 context: Context = realContext,
194 specifier: String? = iface.getInterfaceName()
195 ): Pair<TestableNetworkAgent, TestableNetworkCallback> {
196 val callback = TestableNetworkCallback()
197 // Ensure this NetworkAgent is never unneeded by filing a request with its specifier.
198 requestNetwork(makeTestNetworkRequest(specifier = specifier), callback)
199
200 val nc = NetworkCapabilities().apply {
201 addTransportType(TRANSPORT_TEST)
202 removeCapability(NET_CAPABILITY_TRUSTED)
203 removeCapability(NET_CAPABILITY_INTERNET)
204 addCapability(NET_CAPABILITY_NOT_SUSPENDED)
205 addCapability(NET_CAPABILITY_NOT_ROAMING)
206 addCapability(NET_CAPABILITY_NOT_VPN)
207 addCapability(NET_CAPABILITY_NOT_VCN_MANAGED)
208 if (null != specifier) {
209 setNetworkSpecifier(CompatUtil.makeTestNetworkSpecifier(specifier))
210 }
211 }
212 val lp = LinkProperties().apply {
213 addLinkAddress(LinkAddress(LOCAL_IPV4_ADDRESS, IP4_PREFIX_LEN))
214 addLinkAddress(LinkAddress(LOCAL_IPV6_ADDRESS, IP6_PREFIX_LEN))
215 addRoute(RouteInfo(IpPrefix("0.0.0.0/0"), null, null))
216 addRoute(RouteInfo(InetAddress.getByName("fe80::1234")))
217 setInterfaceName(specifier)
218 }
219 val config = NetworkAgentConfig.Builder().build()
220 val agent = TestableNetworkAgent(context, handlerThread.looper, nc, lp, config)
221 agentsToCleanUp.add(agent)
222
223 // Connect the agent and verify initial status callbacks.
224 runAsShell(MANAGE_TEST_NETWORKS) { agent.register() }
225 agent.markConnected()
226 agent.expectCallback<OnNetworkCreated>()
227 agent.expectSignalStrengths(intArrayOf())
228 agent.expectValidationBypassedStatus()
229 val network = agent.network ?: fail("Expected a non-null network")
230 return agent to callback
231 }
232
233 fun ByteArray.toHex(): String = joinToString(separator = "") {
234 eachByte -> "%02x".format(eachByte)
235 }
236
237 fun sendPacket(
238 agent: TestableNetworkAgent,
239 sendV6: Boolean,
240 dstPort: Int = 0,
241 ) {
242 val testString = "test string"
243 val testPacket = ByteBuffer.wrap(testString.toByteArray(Charsets.UTF_8))
244 var packetFound = false
245
246 val socket = Os.socket(if (sendV6) AF_INET6 else AF_INET, SOCK_DGRAM or SOCK_NONBLOCK,
247 IPPROTO_UDP)
248 agent.network.bindSocket(socket)
249
250 val originalPacket = testPacket.readAsArray()
251 Os.sendto(socket, originalPacket, 0 /* bytesOffset */, originalPacket.size, 0 /* flags */,
252 if(sendV6) TEST_TARGET_IPV6_ADDR else TEST_TARGET_IPV4_ADDR, dstPort)
253 Os.close(socket)
254 }
255
256 fun parseV4PacketDscp(buffer : ByteBuffer) : Int {
257 val ip_ver = buffer.get()
258 val tos = buffer.get()
259 val length = buffer.getShort()
260 val id = buffer.getShort()
261 val offset = buffer.getShort()
262 val ttl = buffer.get()
263 val ipType = buffer.get()
264 val checksum = buffer.getShort()
265 return tos.toInt().shr(2)
266 }
267
268 fun parseV6PacketDscp(buffer : ByteBuffer) : Int {
269 val ip_ver = buffer.get()
270 val tc = buffer.get()
271 val fl = buffer.getShort()
272 val length = buffer.getShort()
273 val proto = buffer.get()
274 val hop = buffer.get()
275 // DSCP is bottom 4 bits of ip_ver and top 2 of tc.
276 val ip_ver_bottom = ip_ver.toInt().and(0xf)
277 val tc_dscp = tc.toInt().shr(6)
278 return ip_ver_bottom.toInt().shl(2) + tc_dscp
279 }
280
281 fun parsePacketIp(
282 buffer : ByteBuffer,
283 sendV6 : Boolean,
284 ) : Boolean {
285 val ipAddr = if (sendV6) ByteArray(16) else ByteArray(4)
286 buffer.get(ipAddr)
287 val srcIp = if (sendV6) Inet6Address.getByAddress(ipAddr)
288 else Inet4Address.getByAddress(ipAddr)
289 buffer.get(ipAddr)
290 val dstIp = if (sendV6) Inet6Address.getByAddress(ipAddr)
291 else Inet4Address.getByAddress(ipAddr)
292
293 Log.e(TAG, "IP Src:" + srcIp + " dst: " + dstIp)
294
295 if ((sendV6 && srcIp == LOCAL_IPV6_ADDRESS && dstIp == TEST_TARGET_IPV6_ADDR) ||
296 (!sendV6 && srcIp == LOCAL_IPV4_ADDRESS && dstIp == TEST_TARGET_IPV4_ADDR)) {
297 Log.e(TAG, "IP return true");
298 return true
299 }
300 Log.e(TAG, "IP return false");
301 return false
302 }
303
304 fun parsePacketPort(
305 buffer : ByteBuffer,
306 srcPort : Int,
307 dstPort : Int
308 ) : Boolean {
309 if (srcPort == 0 && dstPort == 0) return true
310
311 val packetSrcPort = buffer.getShort().toInt()
312 val packetDstPort = buffer.getShort().toInt()
313
314 Log.e(TAG, "Port Src:" + packetSrcPort + " dst: " + packetDstPort)
315
316 if ((srcPort == 0 || (srcPort != 0 && srcPort == packetSrcPort)) &&
317 (dstPort == 0 || (dstPort != 0 && dstPort == packetDstPort))) {
318 Log.e(TAG, "Port return true");
319 return true
320 }
321 Log.e(TAG, "Port return false");
322 return false
323 }
324
325 fun validatePacket(
326 agent : TestableNetworkAgent,
327 sendV6 : Boolean = false,
328 dscpValue : Int = 0,
329 dstPort : Int = 0,
330 ) {
331 var packetFound = false;
332 sendPacket(agent, sendV6, dstPort)
333 // TODO: grab source port from socket in sendPacket
334
335 Log.e(TAG, "find DSCP value:" + dscpValue)
336 generateSequence { reader.poll(PACKET_TIMEOUT_MS) }.forEach { packet ->
337 val buffer = ByteBuffer.wrap(packet, 0, packet.size).order(ByteOrder.BIG_ENDIAN)
338 val dscp = if (sendV6) parseV6PacketDscp(buffer) else parseV4PacketDscp(buffer)
339 Log.e(TAG, "DSCP value:" + dscp)
340
341 // TODO: Add source port comparison. Use 0 for now.
342 if (parsePacketIp(buffer, sendV6) && parsePacketPort(buffer, 0, dstPort)) {
343 Log.e(TAG, "DSCP value found")
344 assertEquals(dscpValue, dscp)
345 packetFound = true
346 }
347 }
348 assertTrue(packetFound)
349 }
350
351 fun doRemovePolicyTest(
352 agent: TestableNetworkAgent,
353 callback: TestableNetworkCallback,
354 policyId: Int
355 ) {
356 val portNumber = 1111 * policyId
357 agent.sendRemoveDscpPolicy(policyId)
358 agent.expectCallback<OnDscpPolicyStatusUpdated>().let {
359 assertEquals(policyId, it.policyId)
360 assertEquals(DSCP_POLICY_STATUS_DELETED, it.status)
361 }
362 }
363
364 @Test
365 fun testDscpPolicyAddPolicies(): Unit = createConnectedNetworkAgent().let {
366 (agent, callback) ->
367 val policy = DscpPolicy.Builder(1, 1)
368 .setDestinationPortRange(Range(4444, 4444)).build()
369 agent.sendAddDscpPolicy(policy)
370 agent.expectCallback<OnDscpPolicyStatusUpdated>().let {
371 assertEquals(1, it.policyId)
372 assertEquals(DSCP_POLICY_STATUS_SUCCESS, it.status)
373 }
374 validatePacket(agent, dscpValue = 1, dstPort = 4444)
375
376 agent.sendRemoveDscpPolicy(1)
377 agent.expectCallback<OnDscpPolicyStatusUpdated>().let {
378 assertEquals(1, it.policyId)
379 assertEquals(DSCP_POLICY_STATUS_DELETED, it.status)
380 }
381
382 val policy2 = DscpPolicy.Builder(1, 4)
383 .setDestinationPortRange(Range(5555, 5555))
384 .setDestinationAddress(TEST_TARGET_IPV4_ADDR)
385 .setSourceAddress(LOCAL_IPV4_ADDRESS)
386 .setProtocol(IPPROTO_UDP).build()
387 agent.sendAddDscpPolicy(policy2)
388 agent.expectCallback<OnDscpPolicyStatusUpdated>().let {
389 assertEquals(1, it.policyId)
390 assertEquals(DSCP_POLICY_STATUS_SUCCESS, it.status)
391 }
392
393 validatePacket(agent, dscpValue = 4, dstPort = 5555)
394
395 agent.sendRemoveDscpPolicy(1)
396 agent.expectCallback<OnDscpPolicyStatusUpdated>().let {
397 assertEquals(1, it.policyId)
398 assertEquals(DSCP_POLICY_STATUS_DELETED, it.status)
399 }
400 }
401
402 @Test
403 fun testDscpPolicyAddV6Policies(): Unit = createConnectedNetworkAgent().let {
404 (agent, callback) ->
405 val policy = DscpPolicy.Builder(1, 1)
406 .setDestinationPortRange(Range(4444, 4444)).build()
407 agent.sendAddDscpPolicy(policy)
408 agent.expectCallback<OnDscpPolicyStatusUpdated>().let {
409 assertEquals(1, it.policyId)
410 assertEquals(DSCP_POLICY_STATUS_SUCCESS, it.status)
411 }
412 validatePacket(agent, true, dscpValue = 1, dstPort = 4444)
413
414 agent.sendRemoveDscpPolicy(1)
415 agent.expectCallback<OnDscpPolicyStatusUpdated>().let {
416 assertEquals(1, it.policyId)
417 assertEquals(DSCP_POLICY_STATUS_DELETED, it.status)
418 }
419
420 val policy2 = DscpPolicy.Builder(1, 4)
421 .setDestinationPortRange(Range(5555, 5555))
422 .setDestinationAddress(TEST_TARGET_IPV6_ADDR)
423 .setSourceAddress(LOCAL_IPV6_ADDRESS)
424 .setProtocol(IPPROTO_UDP).build()
425 agent.sendAddDscpPolicy(policy2)
426 agent.expectCallback<OnDscpPolicyStatusUpdated>().let {
427 assertEquals(1, it.policyId)
428 assertEquals(DSCP_POLICY_STATUS_SUCCESS, it.status)
429 }
430 validatePacket(agent, true, dscpValue = 4, dstPort = 5555)
431
432 agent.sendRemoveDscpPolicy(1)
433 agent.expectCallback<OnDscpPolicyStatusUpdated>().let {
434 assertEquals(1, it.policyId)
435 assertEquals(DSCP_POLICY_STATUS_DELETED, it.status)
436 }
437 }
438
439 @Test
440 // Remove policies in the same order as addition.
441 fun testRemoveDscpPolicy_RemoveSameOrderAsAdd(): Unit = createConnectedNetworkAgent().let {
442 (agent, callback) ->
443 val policy = DscpPolicy.Builder(1, 1).setDestinationPortRange(Range(1111, 1111)).build()
444 agent.sendAddDscpPolicy(policy)
445 agent.expectCallback<OnDscpPolicyStatusUpdated>().let {
446 assertEquals(1, it.policyId)
447 assertEquals(DSCP_POLICY_STATUS_SUCCESS, it.status)
448 validatePacket(agent, dscpValue = 1, dstPort = 1111)
449 }
450
451 val policy2 = DscpPolicy.Builder(2, 1).setDestinationPortRange(Range(2222, 2222)).build()
452 agent.sendAddDscpPolicy(policy2)
453 agent.expectCallback<OnDscpPolicyStatusUpdated>().let {
454 assertEquals(2, it.policyId)
455 assertEquals(DSCP_POLICY_STATUS_SUCCESS, it.status)
456 validatePacket(agent, dscpValue = 1, dstPort = 2222)
457 }
458
459 val policy3 = DscpPolicy.Builder(3, 1).setDestinationPortRange(Range(3333, 3333)).build()
460 agent.sendAddDscpPolicy(policy3)
461 agent.expectCallback<OnDscpPolicyStatusUpdated>().let {
462 assertEquals(3, it.policyId)
463 assertEquals(DSCP_POLICY_STATUS_SUCCESS, it.status)
464 validatePacket(agent, dscpValue = 1, dstPort = 3333)
465 }
466
467 /* Remove Policies and check CE is no longer set */
468 doRemovePolicyTest(agent, callback, 1)
469 validatePacket(agent, dscpValue = 0, dstPort = 1111)
470 doRemovePolicyTest(agent, callback, 2)
471 validatePacket(agent, dscpValue = 0, dstPort = 2222)
472 doRemovePolicyTest(agent, callback, 3)
473 validatePacket(agent, dscpValue = 0, dstPort = 3333)
474 }
475
476 @Test
477 fun testRemoveDscpPolicy_RemoveImmediatelyAfterAdd(): Unit =
478 createConnectedNetworkAgent().let { (agent, callback) ->
479 val policy = DscpPolicy.Builder(1, 1).setDestinationPortRange(Range(1111, 1111)).build()
480 agent.sendAddDscpPolicy(policy)
481 agent.expectCallback<OnDscpPolicyStatusUpdated>().let {
482 assertEquals(1, it.policyId)
483 assertEquals(DSCP_POLICY_STATUS_SUCCESS, it.status)
484 validatePacket(agent, dscpValue = 1, dstPort = 1111)
485 }
486 doRemovePolicyTest(agent, callback, 1)
487
488 val policy2 = DscpPolicy.Builder(2, 1).setDestinationPortRange(Range(2222, 2222)).build()
489 agent.sendAddDscpPolicy(policy2)
490 agent.expectCallback<OnDscpPolicyStatusUpdated>().let {
491 assertEquals(2, it.policyId)
492 assertEquals(DSCP_POLICY_STATUS_SUCCESS, it.status)
493 validatePacket(agent, dscpValue = 1, dstPort = 2222)
494 }
495 doRemovePolicyTest(agent, callback, 2)
496
497 val policy3 = DscpPolicy.Builder(3, 1).setDestinationPortRange(Range(3333, 3333)).build()
498 agent.sendAddDscpPolicy(policy3)
499 agent.expectCallback<OnDscpPolicyStatusUpdated>().let {
500 assertEquals(3, it.policyId)
501 assertEquals(DSCP_POLICY_STATUS_SUCCESS, it.status)
502 validatePacket(agent, dscpValue = 1, dstPort = 3333)
503 }
504 doRemovePolicyTest(agent, callback, 3)
505 }
506
507 @Test
508 // Remove policies in reverse order from addition.
509 fun testRemoveDscpPolicy_RemoveReverseOrder(): Unit =
510 createConnectedNetworkAgent().let { (agent, callback) ->
511 val policy = DscpPolicy.Builder(1, 1).setDestinationPortRange(Range(1111, 1111)).build()
512 agent.sendAddDscpPolicy(policy)
513 agent.expectCallback<OnDscpPolicyStatusUpdated>().let {
514 assertEquals(1, it.policyId)
515 assertEquals(DSCP_POLICY_STATUS_SUCCESS, it.status)
516 validatePacket(agent, dscpValue = 1, dstPort = 1111)
517 }
518
519 val policy2 = DscpPolicy.Builder(2, 1).setDestinationPortRange(Range(2222, 2222)).build()
520 agent.sendAddDscpPolicy(policy2)
521 agent.expectCallback<OnDscpPolicyStatusUpdated>().let {
522 assertEquals(2, it.policyId)
523 assertEquals(DSCP_POLICY_STATUS_SUCCESS, it.status)
524 validatePacket(agent, dscpValue = 1, dstPort = 2222)
525 }
526
527 val policy3 = DscpPolicy.Builder(3, 1).setDestinationPortRange(Range(3333, 3333)).build()
528 agent.sendAddDscpPolicy(policy3)
529 agent.expectCallback<OnDscpPolicyStatusUpdated>().let {
530 assertEquals(3, it.policyId)
531 assertEquals(DSCP_POLICY_STATUS_SUCCESS, it.status)
532 validatePacket(agent, dscpValue = 1, dstPort = 3333)
533 }
534
535 /* Remove Policies and check CE is no longer set */
536 doRemovePolicyTest(agent, callback, 3)
537 doRemovePolicyTest(agent, callback, 2)
538 doRemovePolicyTest(agent, callback, 1)
539 }
540
541 @Test
542 fun testRemoveDscpPolicy_InvalidPolicy(): Unit = createConnectedNetworkAgent().let {
543 (agent, callback) ->
544 agent.sendRemoveDscpPolicy(3)
545 // Is there something to add in TestableNetworkCallback to NOT expect a callback?
546 // Or should we send DSCP_POLICY_STATUS_DELETED in any case or a different STATUS?
547 }
548
549 @Test
550 fun testRemoveAllDscpPolicies(): Unit = createConnectedNetworkAgent().let {
551 (agent, callback) ->
552 val policy = DscpPolicy.Builder(1, 1)
553 .setDestinationPortRange(Range(1111, 1111)).build()
554 agent.sendAddDscpPolicy(policy)
555 agent.expectCallback<OnDscpPolicyStatusUpdated>().let {
556 assertEquals(1, it.policyId)
557 assertEquals(DSCP_POLICY_STATUS_SUCCESS, it.status)
558 validatePacket(agent, dscpValue = 1, dstPort = 1111)
559 }
560
561 val policy2 = DscpPolicy.Builder(2, 1)
562 .setDestinationPortRange(Range(2222, 2222)).build()
563 agent.sendAddDscpPolicy(policy2)
564 agent.expectCallback<OnDscpPolicyStatusUpdated>().let {
565 assertEquals(2, it.policyId)
566 assertEquals(DSCP_POLICY_STATUS_SUCCESS, it.status)
567 validatePacket(agent, dscpValue = 1, dstPort = 2222)
568 }
569
570 val policy3 = DscpPolicy.Builder(3, 1)
571 .setDestinationPortRange(Range(3333, 3333)).build()
572 agent.sendAddDscpPolicy(policy3)
573 agent.expectCallback<OnDscpPolicyStatusUpdated>().let {
574 assertEquals(3, it.policyId)
575 assertEquals(DSCP_POLICY_STATUS_SUCCESS, it.status)
576 validatePacket(agent, dscpValue = 1, dstPort = 3333)
577 }
578
579 agent.sendRemoveAllDscpPolicies()
580 agent.expectCallback<OnDscpPolicyStatusUpdated>().let {
581 assertEquals(1, it.policyId)
582 assertEquals(DSCP_POLICY_STATUS_DELETED, it.status)
583 validatePacket(agent, false, dstPort = 1111)
584 }
585 agent.expectCallback<OnDscpPolicyStatusUpdated>().let {
586 assertEquals(2, it.policyId)
587 assertEquals(DSCP_POLICY_STATUS_DELETED, it.status)
588 validatePacket(agent, false, dstPort = 2222)
589 }
590 agent.expectCallback<OnDscpPolicyStatusUpdated>().let {
591 assertEquals(3, it.policyId)
592 assertEquals(DSCP_POLICY_STATUS_DELETED, it.status)
593 validatePacket(agent, false, dstPort = 3333)
594 }
595 }
596
597 @Test
598 fun testAddDuplicateDscpPolicy(): Unit = createConnectedNetworkAgent().let {
599 (agent, callback) ->
600 val policy = DscpPolicy.Builder(1, 1).setDestinationPortRange(Range(4444, 4444)).build()
601 agent.sendAddDscpPolicy(policy)
602 agent.expectCallback<OnDscpPolicyStatusUpdated>().let {
603 assertEquals(1, it.policyId)
604 assertEquals(DSCP_POLICY_STATUS_SUCCESS, it.status)
605 validatePacket(agent, dscpValue = 1, dstPort = 4444)
606 }
607
608 val policy2 = DscpPolicy.Builder(1, 1).setDestinationPortRange(Range(5555, 5555)).build()
609 agent.sendAddDscpPolicy(policy2)
610 agent.expectCallback<OnDscpPolicyStatusUpdated>().let {
611 assertEquals(1, it.policyId)
612 assertEquals(DSCP_POLICY_STATUS_SUCCESS, it.status)
613
614 // Sending packet with old policy should fail
615 validatePacket(agent, dscpValue = 0, dstPort = 4444)
616 validatePacket(agent, dscpValue = 1, dstPort = 5555)
617 }
618
619 agent.sendRemoveDscpPolicy(1)
620 agent.expectCallback<OnDscpPolicyStatusUpdated>().let {
621 assertEquals(1, it.policyId)
622 assertEquals(DSCP_POLICY_STATUS_DELETED, it.status)
623 }
624 }
625
626 @Test
627 fun testParcelingDscpPolicyIsLossless(): Unit = createConnectedNetworkAgent().let {
628 (agent, callback) ->
629 val policyId = 1
630 val dscpValue = 1
631 val range = Range(4444, 4444)
632 val srcPort = 555
633
634 // Check that policy with partial parameters is lossless.
635 val policy = DscpPolicy.Builder(policyId, dscpValue).setDestinationPortRange(range).build()
636 assertEquals(policyId, policy.policyId)
637 assertEquals(dscpValue, policy.dscpValue)
638 assertEquals(range, policy.destinationPortRange)
639 assertParcelingIsLossless(policy)
640
641 // Check that policy with all parameters is lossless.
642 val policy2 = DscpPolicy.Builder(policyId, dscpValue).setDestinationPortRange(range)
643 .setSourceAddress(LOCAL_IPV4_ADDRESS)
644 .setDestinationAddress(TEST_TARGET_IPV4_ADDR)
645 .setSourcePort(srcPort)
646 .setProtocol(IPPROTO_UDP).build()
647 assertEquals(policyId, policy2.policyId)
648 assertEquals(dscpValue, policy2.dscpValue)
649 assertEquals(range, policy2.destinationPortRange)
650 assertEquals(TEST_TARGET_IPV4_ADDR, policy2.destinationAddress)
651 assertEquals(LOCAL_IPV4_ADDRESS, policy2.sourceAddress)
652 assertEquals(srcPort, policy2.sourcePort)
653 assertEquals(IPPROTO_UDP, policy2.protocol)
654 assertParcelingIsLossless(policy2)
655 }
656 }
657
readAsArraynull658 private fun ByteBuffer.readAsArray(): ByteArray {
659 val out = ByteArray(remaining())
660 get(out)
661 return out
662 }
663
assertHasServicenull664 private fun <T> Context.assertHasService(manager: Class<T>): T {
665 return getSystemService(manager) ?: fail("Service $manager not found")
666 }
667