diff options
author | Remi NGUYEN VAN <reminv@google.com> | 2020-04-02 14:10:08 +0000 |
---|---|---|
committer | Remi NGUYEN VAN <reminv@google.com> | 2020-04-07 03:07:46 +0000 |
commit | 5f3bb6d04bc1f0d3d80f58d738be7411cd2cd348 (patch) | |
tree | 34fff0d74d9fea659e02112873630c6d0c232965 | |
parent | f8783184b025b0ac2353b0f384cee1b3340f2f18 (diff) |
Add tests for IpReachabilityMonitor
The first tests just verify that provisioning is lost if all IPv4/6 DNS
servers or gateways are lost.
Test: atest NetworkStackTests
Bug: 152819907
Merged-In: I8da6a8f4f237ce963c0a1610432d310160fd3f20
Change-Id: I8da6a8f4f237ce963c0a1610432d310160fd3f20
6 files changed, 376 insertions, 152 deletions
diff --git a/common/moduleutils/src/android/net/util/FdEventsReader.java b/common/moduleutils/src/android/net/util/FdEventsReader.java index 5a1154f..ebd6c53 100644 --- a/common/moduleutils/src/android/net/util/FdEventsReader.java +++ b/common/moduleutils/src/android/net/util/FdEventsReader.java @@ -27,6 +27,7 @@ import android.system.OsConstants; import androidx.annotation.NonNull; import androidx.annotation.Nullable; +import androidx.annotation.VisibleForTesting; import java.io.FileDescriptor; import java.io.IOException; @@ -92,6 +93,12 @@ public abstract class FdEventsReader<BufferType> { mBuffer = buffer; } + @VisibleForTesting + @NonNull + protected MessageQueue getMessageQueue() { + return mQueue; + } + /** Start this FdEventsReader. */ public boolean start() { if (!onCorrectThread()) { @@ -185,7 +192,7 @@ public abstract class FdEventsReader<BufferType> { if (mFd == null) return false; - mQueue.addOnFileDescriptorEventListener( + getMessageQueue().addOnFileDescriptorEventListener( mFd, FD_EVENTS, (fd, events) -> { @@ -247,7 +254,7 @@ public abstract class FdEventsReader<BufferType> { private void unregisterAndDestroyFd() { if (mFd == null) return; - mQueue.removeOnFileDescriptorEventListener(mFd); + getMessageQueue().removeOnFileDescriptorEventListener(mFd); closeFd(mFd); mFd = null; onStop(); diff --git a/src/android/net/ip/IpReachabilityMonitor.java b/src/android/net/ip/IpReachabilityMonitor.java index 17b1f3c..e1d4548 100644 --- a/src/android/net/ip/IpReachabilityMonitor.java +++ b/src/android/net/ip/IpReachabilityMonitor.java @@ -27,6 +27,7 @@ import android.net.INetd; import android.net.LinkProperties; import android.net.RouteInfo; import android.net.ip.IpNeighborMonitor.NeighborEvent; +import android.net.ip.IpNeighborMonitor.NeighborEventConsumer; import android.net.metrics.IpConnectivityLog; import android.net.metrics.IpReachabilityEvent; import android.net.netlink.StructNdMsg; @@ -154,11 +155,12 @@ public class IpReachabilityMonitor { } /** - * Encapsulates IpReachabilityMonitor depencencies on systems that hinder unit testing. + * Encapsulates IpReachabilityMonitor dependencies on systems that hinder unit testing. * TODO: consider also wrapping MultinetworkPolicyTracker in this interface. */ interface Dependencies { void acquireWakeLock(long durationMs); + IpNeighborMonitor makeIpNeighborMonitor(Handler h, SharedLog log, NeighborEventConsumer cb); static Dependencies makeDefault(Context context, String iface) { final String lockName = TAG + "." + iface; @@ -169,6 +171,11 @@ public class IpReachabilityMonitor { public void acquireWakeLock(long durationMs) { lock.acquire(durationMs); } + + public IpNeighborMonitor makeIpNeighborMonitor(Handler h, SharedLog log, + NeighborEventConsumer cb) { + return new IpNeighborMonitor(h, log, cb); + } }; } } @@ -223,7 +230,7 @@ public class IpReachabilityMonitor { } setNeighbourParametersForSteadyState(); - mIpNeighborMonitor = new IpNeighborMonitor(h, mLog, + mIpNeighborMonitor = mDependencies.makeIpNeighborMonitor(h, mLog, (NeighborEvent event) -> { if (mInterfaceParams.index != event.ifindex) return; if (!mNeighborWatchList.containsKey(event.ip)) return; diff --git a/tests/unit/src/android/net/ip/IpReachabilityMonitorTest.java b/tests/unit/src/android/net/ip/IpReachabilityMonitorTest.java deleted file mode 100644 index ba3b306..0000000 --- a/tests/unit/src/android/net/ip/IpReachabilityMonitorTest.java +++ /dev/null @@ -1,70 +0,0 @@ -/* - * Copyright (C) 2017 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package android.net.ip; - -import static org.mockito.Mockito.anyString; -import static org.mockito.Mockito.when; - -import android.content.Context; -import android.net.INetd; -import android.net.util.InterfaceParams; -import android.net.util.SharedLog; -import android.os.Handler; -import android.os.Looper; - -import androidx.test.filters.SmallTest; -import androidx.test.runner.AndroidJUnit4; - -import org.junit.Before; -import org.junit.Test; -import org.junit.runner.RunWith; -import org.mockito.Mock; -import org.mockito.MockitoAnnotations; - -/** - * Tests for IpReachabilityMonitor. - */ -@RunWith(AndroidJUnit4.class) -@SmallTest -public class IpReachabilityMonitorTest { - @Mock IpReachabilityMonitor.Callback mCallback; - @Mock IpReachabilityMonitor.Dependencies mDependencies; - @Mock SharedLog mLog; - @Mock Context mContext; - @Mock INetd mNetd; - Handler mHandler; - - @Before - public void setUp() { - MockitoAnnotations.initMocks(this); - when(mLog.forSubComponent(anyString())).thenReturn(mLog); - mHandler = new Handler(Looper.getMainLooper()); - } - - IpReachabilityMonitor makeMonitor() { - final InterfaceParams ifParams = new InterfaceParams("fake0", 1, null); - return new IpReachabilityMonitor( - mContext, ifParams, mHandler, mLog, mCallback, false, mDependencies, mNetd); - } - - @Test - public void testNothing() { - // make sure the unit test runs in the same thread with main looper. - // Otherwise, throwing IllegalStateException would cause test fails. - mHandler.post(() -> makeMonitor()); - } -} diff --git a/tests/unit/src/android/net/ip/IpReachabilityMonitorTest.kt b/tests/unit/src/android/net/ip/IpReachabilityMonitorTest.kt new file mode 100644 index 0000000..ac50651 --- /dev/null +++ b/tests/unit/src/android/net/ip/IpReachabilityMonitorTest.kt @@ -0,0 +1,247 @@ +/* + * Copyright (C) 2017 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package android.net.ip + +import android.content.Context +import android.net.INetd +import android.net.InetAddresses.parseNumericAddress +import android.net.IpPrefix +import android.net.LinkAddress +import android.net.LinkProperties +import android.net.RouteInfo +import android.net.netlink.StructNdMsg.NUD_FAILED +import android.net.netlink.StructNdMsg.NUD_STALE +import android.net.netlink.makeNewNeighMessage +import android.net.util.InterfaceParams +import android.net.util.SharedLog +import android.os.Handler +import android.os.HandlerThread +import android.os.MessageQueue +import android.os.MessageQueue.OnFileDescriptorEventListener +import android.system.ErrnoException +import android.system.OsConstants.EAGAIN +import androidx.test.filters.SmallTest +import androidx.test.runner.AndroidJUnit4 +import org.junit.After +import org.junit.Before +import org.junit.Test +import org.junit.runner.RunWith +import org.mockito.ArgumentCaptor +import org.mockito.ArgumentMatchers.any +import org.mockito.ArgumentMatchers.anyInt +import org.mockito.ArgumentMatchers.anyString +import org.mockito.ArgumentMatchers.eq +import org.mockito.Mockito.doAnswer +import org.mockito.Mockito.doReturn +import org.mockito.Mockito.mock +import org.mockito.Mockito.never +import org.mockito.Mockito.timeout +import org.mockito.Mockito.verify +import java.io.FileDescriptor +import java.net.Inet4Address +import java.net.Inet6Address +import java.net.InetAddress +import java.util.concurrent.CompletableFuture +import java.util.concurrent.ConcurrentLinkedQueue +import java.util.concurrent.TimeUnit +import kotlin.test.assertTrue +import kotlin.test.fail + +private const val TEST_TIMEOUT_MS = 10_000L + +private val TEST_IPV4_GATEWAY = parseNumericAddress("192.168.222.3") as Inet4Address +private val TEST_IPV6_GATEWAY = parseNumericAddress("2001:db8::1") as Inet6Address + +private val TEST_IPV4_LINKADDR = LinkAddress("192.168.222.123/24") +private val TEST_IPV6_LINKADDR = LinkAddress("2001:db8::123/64") + +// DNSes inside IP prefix +private val TEST_IPV4_DNS = parseNumericAddress("192.168.222.1") as Inet4Address +private val TEST_IPV6_DNS = parseNumericAddress("2001:db8::321") as Inet6Address + +private val TEST_IFACE = InterfaceParams("fake0", 21, null) +private val TEST_LINK_PROPERTIES = LinkProperties().apply { + interfaceName = TEST_IFACE.name + addLinkAddress(TEST_IPV4_LINKADDR) + addLinkAddress(TEST_IPV6_LINKADDR) + + // Add on link routes + addRoute(RouteInfo(TEST_IPV4_LINKADDR, null /* gateway */, TEST_IFACE.name)) + addRoute(RouteInfo(TEST_IPV6_LINKADDR, null /* gateway */, TEST_IFACE.name)) + + // Add default routes + addRoute(RouteInfo(IpPrefix(parseNumericAddress("0.0.0.0"), 0), TEST_IPV4_GATEWAY)) + addRoute(RouteInfo(IpPrefix(parseNumericAddress("::"), 0), TEST_IPV6_GATEWAY)) + + addDnsServer(TEST_IPV4_DNS) + addDnsServer(TEST_IPV6_DNS) +} + +/** + * Tests for IpReachabilityMonitor. + */ +@RunWith(AndroidJUnit4::class) +@SmallTest +class IpReachabilityMonitorTest { + private val callback = mock(IpReachabilityMonitor.Callback::class.java) + private val dependencies = mock(IpReachabilityMonitor.Dependencies::class.java) + private val log = mock(SharedLog::class.java) + private val context = mock(Context::class.java) + private val netd = mock(INetd::class.java) + private val fd = mock(FileDescriptor::class.java) + + private val handlerThread = HandlerThread(IpReachabilityMonitorTest::class.simpleName) + private val handler by lazy { Handler(handlerThread.looper) } + + private lateinit var reachabilityMonitor: IpReachabilityMonitor + private lateinit var neighborMonitor: TestIpNeighborMonitor + + /** + * A version of [IpNeighborMonitor] that overrides packet reading from a socket, and instead + * allows the test to enqueue test packets via [enqueuePacket]. + */ + private class TestIpNeighborMonitor( + handler: Handler, + log: SharedLog, + cb: NeighborEventConsumer, + private val fd: FileDescriptor + ) : IpNeighborMonitor(handler, log, cb) { + + private val pendingPackets = ConcurrentLinkedQueue<ByteArray>() + val msgQueue = mock(MessageQueue::class.java) + + private var eventListener: OnFileDescriptorEventListener? = null + + override fun createFd() = fd + override fun getMessageQueue() = msgQueue + + fun enqueuePacket(packet: ByteArray) { + val listener = eventListener ?: fail("IpNeighborMonitor was not yet started") + pendingPackets.add(packet) + handler.post { + listener.onFileDescriptorEvents(fd, OnFileDescriptorEventListener.EVENT_INPUT) + } + } + + override fun readPacket(fd: FileDescriptor, packetBuffer: ByteArray): Int { + val packet = pendingPackets.poll() ?: throw ErrnoException("No pending packet", EAGAIN) + if (packet.size > packetBuffer.size) { + fail("Buffer (${packetBuffer.size}) is too small for packet (${packet.size})") + } + System.arraycopy(packet, 0, packetBuffer, 0, packet.size) + return packet.size + } + + override fun onStart() { + super.onStart() + + // Find the file descriptor listener that was registered on the instrumented queue + val captor = ArgumentCaptor.forClass(OnFileDescriptorEventListener::class.java) + verify(msgQueue).addOnFileDescriptorEventListener( + eq(fd), anyInt(), captor.capture()) + eventListener = captor.value + } + } + + @Before + fun setUp() { + doReturn(log).`when`(log).forSubComponent(anyString()) + doReturn(true).`when`(fd).valid() + handlerThread.start() + + doAnswer { inv -> + val handler = inv.getArgument<Handler>(0) + val log = inv.getArgument<SharedLog>(1) + val cb = inv.getArgument<IpNeighborMonitor.NeighborEventConsumer>(2) + neighborMonitor = TestIpNeighborMonitor(handler, log, cb, fd) + neighborMonitor + }.`when`(dependencies).makeIpNeighborMonitor(any(), any(), any()) + + val monitorFuture = CompletableFuture<IpReachabilityMonitor>() + // IpReachabilityMonitor needs to be started from the handler thread + handler.post { + monitorFuture.complete(IpReachabilityMonitor( + context, + TEST_IFACE, + handler, + log, + callback, + false /* useMultinetworkPolicyTracker */, + dependencies, + netd)) + } + reachabilityMonitor = monitorFuture.get(TEST_TIMEOUT_MS, TimeUnit.MILLISECONDS) + assertTrue(::neighborMonitor.isInitialized, + "IpReachabilityMonitor did not call makeIpNeighborMonitor") + } + + @After + fun tearDown() { + doReturn(false).`when`(fd).valid() + handlerThread.quitSafely() + } + + // TODO: fix this bug + @Test + fun testLoseProvisioning_CrashIfFirstProbeIsFailed() { + reachabilityMonitor.updateLinkProperties(TEST_LINK_PROPERTIES) + + doAnswer { + // Set the fd as invalid when the event listener is removed, to avoid a crash when the + // reader tries to close the mock fd. + // This does not exactly reflect behavior on close, but this test is only demonstrating + // a bug that causes the close, and it will be removed when the bug fixed. + doReturn(false).`when`(fd).valid() + }.`when`(neighborMonitor.msgQueue).removeOnFileDescriptorEventListener(any()) + + neighborMonitor.enqueuePacket(makeNewNeighMessage(TEST_IPV4_DNS, NUD_FAILED)) + verify(neighborMonitor.msgQueue, timeout(TEST_TIMEOUT_MS)) + .removeOnFileDescriptorEventListener(any()) + verify(callback, never()).notifyLost(eq(TEST_IPV4_DNS), anyString()) + } + + private fun runLoseProvisioningTest(lostNeighbor: InetAddress) { + reachabilityMonitor.updateLinkProperties(TEST_LINK_PROPERTIES) + + neighborMonitor.enqueuePacket(makeNewNeighMessage(TEST_IPV4_GATEWAY, NUD_STALE)) + neighborMonitor.enqueuePacket(makeNewNeighMessage(TEST_IPV6_GATEWAY, NUD_STALE)) + neighborMonitor.enqueuePacket(makeNewNeighMessage(TEST_IPV4_DNS, NUD_STALE)) + neighborMonitor.enqueuePacket(makeNewNeighMessage(TEST_IPV6_DNS, NUD_STALE)) + + neighborMonitor.enqueuePacket(makeNewNeighMessage(lostNeighbor, NUD_FAILED)) + verify(callback, timeout(TEST_TIMEOUT_MS)).notifyLost(eq(lostNeighbor), anyString()) + } + + @Test + fun testLoseProvisioning_Ipv4DnsLost() { + runLoseProvisioningTest(TEST_IPV4_DNS) + } + + @Test + fun testLoseProvisioning_Ipv6DnsLost() { + runLoseProvisioningTest(TEST_IPV6_DNS) + } + + @Test + fun testLoseProvisioning_Ipv4GatewayLost() { + runLoseProvisioningTest(TEST_IPV4_GATEWAY) + } + + @Test + fun testLoseProvisioning_Ipv6GatewayLost() { + runLoseProvisioningTest(TEST_IPV6_GATEWAY) + } +}
\ No newline at end of file diff --git a/tests/unit/src/android/net/netlink/NetlinkTestUtils.kt b/tests/unit/src/android/net/netlink/NetlinkTestUtils.kt new file mode 100644 index 0000000..6655e96 --- /dev/null +++ b/tests/unit/src/android/net/netlink/NetlinkTestUtils.kt @@ -0,0 +1,100 @@ +/* + * Copyright (C) 2020 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package android.net.netlink + +import android.net.netlink.NetlinkConstants.RTM_DELNEIGH +import android.net.netlink.NetlinkConstants.RTM_NEWNEIGH +import libcore.util.HexEncoding +import libcore.util.HexEncoding.encodeToString +import java.net.Inet6Address +import java.net.InetAddress + +/** + * Make a RTM_NEWNEIGH netlink message. + */ +fun makeNewNeighMessage( + neighAddr: InetAddress, + nudState: Short +) = makeNeighborMessage( + neighAddr = neighAddr, + type = RTM_NEWNEIGH, + nudState = nudState +) + +/** + * Make a RTM_DELNEIGH netlink message. + */ +fun makeDelNeighMessage( + neighAddr: InetAddress, + nudState: Short +) = makeNeighborMessage( + neighAddr = neighAddr, + type = RTM_DELNEIGH, + nudState = nudState +) + +private fun makeNeighborMessage( + neighAddr: InetAddress, + type: Short, + nudState: Short +) = HexEncoding.decode( + /* ktlint-disable indent */ + // -- struct nlmsghdr -- + // length = 88 or 76: + (if (neighAddr is Inet6Address) "58000000" else "4c000000") + + type.toLEHex() + // type + "0000" + // flags + "00000000" + // seqno + "00000000" + // pid (0 == kernel) + // struct ndmsg + // family (AF_INET6 or AF_INET) + (if (neighAddr is Inet6Address) "0a" else "02") + + "00" + // pad1 + "0000" + // pad2 + "15000000" + // interface index (21 == wlan0, on test device) + nudState.toLEHex() + // NUD state + "00" + // flags + "01" + // type + // -- struct nlattr: NDA_DST -- + // length = 20 or 8: + (if (neighAddr is Inet6Address) "1400" else "0800") + + "0100" + // type (1 == NDA_DST, for neighbor messages) + // IP address: + encodeToString(neighAddr.address, false /* upperCase */) + + // -- struct nlattr: NDA_LLADDR -- + "0a00" + // length = 10 + "0200" + // type (2 == NDA_LLADDR, for neighbor messages) + "00005e000164" + // MAC Address (== 00:00:5e:00:01:64) + "0000" + // padding, for 4 byte alignment + // -- struct nlattr: NDA_PROBES -- + "0800" + // length = 8 + "0400" + // type (4 == NDA_PROBES, for neighbor messages) + "01000000" + // number of probes + // -- struct nlattr: NDA_CACHEINFO -- + "1400" + // length = 20 + "0300" + // type (3 == NDA_CACHEINFO, for neighbor messages) + "05190000" + // ndm_used, as "clock ticks ago" + "05190000" + // ndm_confirmed, as "clock ticks ago" + "190d0000" + // ndm_updated, as "clock ticks ago" + "00000000", // ndm_refcnt + false /* allowSingleChar */) + /* ktlint-enable indent */ + +/** + * Convert a [Short] to a little-endian hex string. + */ +private fun Short.toLEHex() = String.format("%04x", java.lang.Short.reverseBytes(this)) diff --git a/tests/unit/src/android/net/netlink/RtNetlinkNeighborMessageTest.java b/tests/unit/src/android/net/netlink/RtNetlinkNeighborMessageTest.java index 72e6bca..34257b8 100644 --- a/tests/unit/src/android/net/netlink/RtNetlinkNeighborMessageTest.java +++ b/tests/unit/src/android/net/netlink/RtNetlinkNeighborMessageTest.java @@ -16,10 +16,15 @@ package android.net.netlink; +import static android.net.netlink.NetlinkTestUtilsKt.makeDelNeighMessage; +import static android.net.netlink.NetlinkTestUtilsKt.makeNewNeighMessage; +import static android.net.netlink.StructNdMsg.NUD_STALE; + import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertNotNull; import static org.junit.Assert.assertTrue; +import android.net.InetAddresses; import android.net.netlink.NetlinkConstants; import android.net.netlink.NetlinkMessage; import android.net.netlink.RtNetlinkNeighborMessage; @@ -46,83 +51,11 @@ import java.util.Arrays; public class RtNetlinkNeighborMessageTest { private final String TAG = "RtNetlinkNeighborMessageTest"; - // Hexadecimal representation of packet capture. - public static final String RTM_DELNEIGH_HEX = - // struct nlmsghdr - "4c000000" + // length = 76 - "1d00" + // type = 29 (RTM_DELNEIGH) - "0000" + // flags - "00000000" + // seqno - "00000000" + // pid (0 == kernel) - // struct ndmsg - "02" + // family - "00" + // pad1 - "0000" + // pad2 - "15000000" + // interface index (21 == wlan0, on test device) - "0400" + // NUD state (0x04 == NUD_STALE) - "00" + // flags - "01" + // type - // struct nlattr: NDA_DST - "0800" + // length = 8 - "0100" + // type (1 == NDA_DST, for neighbor messages) - "c0a89ffe" + // IPv4 address (== 192.168.159.254) - // struct nlattr: NDA_LLADDR - "0a00" + // length = 10 - "0200" + // type (2 == NDA_LLADDR, for neighbor messages) - "00005e000164" + // MAC Address (== 00:00:5e:00:01:64) - "0000" + // padding, for 4 byte alignment - // struct nlattr: NDA_PROBES - "0800" + // length = 8 - "0400" + // type (4 == NDA_PROBES, for neighbor messages) - "01000000" + // number of probes - // struct nlattr: NDA_CACHEINFO - "1400" + // length = 20 - "0300" + // type (3 == NDA_CACHEINFO, for neighbor messages) - "05190000" + // ndm_used, as "clock ticks ago" - "05190000" + // ndm_confirmed, as "clock ticks ago" - "190d0000" + // ndm_updated, as "clock ticks ago" - "00000000"; // ndm_refcnt - public static final byte[] RTM_DELNEIGH = - HexEncoding.decode(RTM_DELNEIGH_HEX.toCharArray(), false); + public static final byte[] RTM_DELNEIGH = makeDelNeighMessage( + InetAddresses.parseNumericAddress("192.168.159.254"), NUD_STALE); - // Hexadecimal representation of packet capture. - public static final String RTM_NEWNEIGH_HEX = - // struct nlmsghdr - "58000000" + // length = 88 - "1c00" + // type = 28 (RTM_NEWNEIGH) - "0000" + // flags - "00000000" + // seqno - "00000000" + // pid (0 == kernel) - // struct ndmsg - "0a" + // family - "00" + // pad1 - "0000" + // pad2 - "15000000" + // interface index (21 == wlan0, on test device) - "0400" + // NUD state (0x04 == NUD_STALE) - "80" + // flags - "01" + // type - // struct nlattr: NDA_DST - "1400" + // length = 20 - "0100" + // type (1 == NDA_DST, for neighbor messages) - "fe8000000000000086c9b2fffe6aed4b" + // IPv6 address (== fe80::86c9:b2ff:fe6a:ed4b) - // struct nlattr: NDA_LLADDR - "0a00" + // length = 10 - "0200" + // type (2 == NDA_LLADDR, for neighbor messages) - "84c9b26aed4b" + // MAC Address (== 84:c9:b2:6a:ed:4b) - "0000" + // padding, for 4 byte alignment - // struct nlattr: NDA_PROBES - "0800" + // length = 8 - "0400" + // type (4 == NDA_PROBES, for neighbor messages) - "01000000" + // number of probes - // struct nlattr: NDA_CACHEINFO - "1400" + // length = 20 - "0300" + // type (3 == NDA_CACHEINFO, for neighbor messages) - "eb0e0000" + // ndm_used, as "clock ticks ago" - "861f0000" + // ndm_confirmed, as "clock ticks ago" - "00000000" + // ndm_updated, as "clock ticks ago" - "05000000"; // ndm_refcnt - public static final byte[] RTM_NEWNEIGH = - HexEncoding.decode(RTM_NEWNEIGH_HEX.toCharArray(), false); + public static final byte[] RTM_NEWNEIGH = makeNewNeighMessage( + InetAddresses.parseNumericAddress("fe80::86c9:b2ff:fe6a:ed4b"), NUD_STALE); // An example of the full response from an RTM_GETNEIGH query. private static final String RTM_GETNEIGH_RESPONSE_HEX = @@ -165,7 +98,7 @@ public class RtNetlinkNeighborMessageTest { assertNotNull(ndmsgHdr); assertEquals((byte) OsConstants.AF_INET, ndmsgHdr.ndm_family); assertEquals(21, ndmsgHdr.ndm_ifindex); - assertEquals(StructNdMsg.NUD_STALE, ndmsgHdr.ndm_state); + assertEquals(NUD_STALE, ndmsgHdr.ndm_state); final InetAddress destination = neighMsg.getDestination(); assertNotNull(destination); assertEquals(InetAddress.parseNumericAddress("192.168.159.254"), destination); @@ -192,7 +125,7 @@ public class RtNetlinkNeighborMessageTest { assertNotNull(ndmsgHdr); assertEquals((byte) OsConstants.AF_INET6, ndmsgHdr.ndm_family); assertEquals(21, ndmsgHdr.ndm_ifindex); - assertEquals(StructNdMsg.NUD_STALE, ndmsgHdr.ndm_state); + assertEquals(NUD_STALE, ndmsgHdr.ndm_state); final InetAddress destination = neighMsg.getDestination(); assertNotNull(destination); assertEquals(InetAddress.parseNumericAddress("fe80::86c9:b2ff:fe6a:ed4b"), destination); |