Loading packages/Tethering/src/com/android/networkstack/tethering/OffloadHardwareInterface.java +33 −0 Original line number Original line Diff line number Diff line Loading @@ -16,8 +16,11 @@ package com.android.networkstack.tethering; package com.android.networkstack.tethering; import static android.net.netlink.StructNlMsgHdr.NLM_F_DUMP; import static android.net.netlink.StructNlMsgHdr.NLM_F_REQUEST; import static android.net.util.TetheringUtils.uint16; import static android.net.util.TetheringUtils.uint16; import android.annotation.NonNull; import android.hardware.tetheroffload.config.V1_0.IOffloadConfig; import android.hardware.tetheroffload.config.V1_0.IOffloadConfig; import android.hardware.tetheroffload.control.V1_0.IOffloadControl; import android.hardware.tetheroffload.control.V1_0.IOffloadControl; import android.hardware.tetheroffload.control.V1_0.ITetheringOffloadCallback; import android.hardware.tetheroffload.control.V1_0.ITetheringOffloadCallback; Loading @@ -25,6 +28,7 @@ import android.hardware.tetheroffload.control.V1_0.NatTimeoutUpdate; import android.hardware.tetheroffload.control.V1_0.NetworkProtocol; import android.hardware.tetheroffload.control.V1_0.NetworkProtocol; import android.hardware.tetheroffload.control.V1_0.OffloadCallbackEvent; import android.hardware.tetheroffload.control.V1_0.OffloadCallbackEvent; import android.net.netlink.NetlinkSocket; import android.net.netlink.NetlinkSocket; import android.net.netlink.StructNlMsgHdr; import android.net.util.SharedLog; import android.net.util.SharedLog; import android.net.util.SocketUtils; import android.net.util.SocketUtils; import android.os.Handler; import android.os.Handler; Loading @@ -37,9 +41,11 @@ import android.system.OsConstants; import com.android.internal.annotations.VisibleForTesting; import com.android.internal.annotations.VisibleForTesting; import java.io.FileDescriptor; import java.io.FileDescriptor; import java.io.InterruptedIOException; import java.io.IOException; import java.io.IOException; import java.net.SocketAddress; import java.net.SocketAddress; import java.net.SocketException; import java.net.SocketException; import java.nio.ByteBuffer; import java.util.ArrayList; import java.util.ArrayList; import java.util.NoSuchElementException; import java.util.NoSuchElementException; Loading @@ -63,6 +69,11 @@ public class OffloadHardwareInterface { private static final int NF_NETLINK_CONNTRACK_NEW = 1; private static final int NF_NETLINK_CONNTRACK_NEW = 1; private static final int NF_NETLINK_CONNTRACK_UPDATE = 2; private static final int NF_NETLINK_CONNTRACK_UPDATE = 2; private static final int NF_NETLINK_CONNTRACK_DESTROY = 4; private static final int NF_NETLINK_CONNTRACK_DESTROY = 4; // Reference libnetfilter_conntrack/linux_nfnetlink_conntrack.h public static final short NFNL_SUBSYS_CTNETLINK = 1; public static final short IPCTNL_MSG_CT_GET = 1; private final long NETLINK_MESSAGE_TIMEOUT_MS = 500; private final Handler mHandler; private final Handler mHandler; private final SharedLog mLog; private final SharedLog mLog; Loading Loading @@ -226,6 +237,9 @@ public class OffloadHardwareInterface { NF_NETLINK_CONNTRACK_NEW | NF_NETLINK_CONNTRACK_DESTROY); NF_NETLINK_CONNTRACK_NEW | NF_NETLINK_CONNTRACK_DESTROY); if (h1 == null) return false; if (h1 == null) return false; sendNetlinkMessage(h1, (short) ((NFNL_SUBSYS_CTNETLINK << 8) | IPCTNL_MSG_CT_GET), (short) (NLM_F_REQUEST | NLM_F_DUMP)); final NativeHandle h2 = mDeps.createConntrackSocket( final NativeHandle h2 = mDeps.createConntrackSocket( NF_NETLINK_CONNTRACK_UPDATE | NF_NETLINK_CONNTRACK_DESTROY); NF_NETLINK_CONNTRACK_UPDATE | NF_NETLINK_CONNTRACK_DESTROY); if (h2 == null) { if (h2 == null) { Loading @@ -252,6 +266,25 @@ public class OffloadHardwareInterface { return results.mSuccess; return results.mSuccess; } } @VisibleForTesting public void sendNetlinkMessage(@NonNull NativeHandle handle, short type, short flags) { final int length = StructNlMsgHdr.STRUCT_SIZE; final byte[] msg = new byte[length]; final StructNlMsgHdr nlh = new StructNlMsgHdr(); final ByteBuffer byteBuffer = ByteBuffer.wrap(msg); nlh.nlmsg_len = length; nlh.nlmsg_type = type; nlh.nlmsg_flags = flags; nlh.nlmsg_seq = 1; nlh.pack(byteBuffer); try { NetlinkSocket.sendMessage(handle.getFileDescriptor(), msg, 0 /* offset */, length, NETLINK_MESSAGE_TIMEOUT_MS); } catch (ErrnoException | InterruptedIOException e) { mLog.e("Unable to send netfilter message, error: " + e); } } private void closeFdInNativeHandle(final NativeHandle h) { private void closeFdInNativeHandle(final NativeHandle h) { try { try { h.close(); h.close(); Loading packages/Tethering/tests/unit/src/com/android/networkstack/tethering/OffloadHardwareInterfaceTest.java +39 −0 Original line number Original line Diff line number Diff line Loading @@ -17,13 +17,17 @@ package com.android.networkstack.tethering; package com.android.networkstack.tethering; import static android.net.util.TetheringUtils.uint16; import static android.net.util.TetheringUtils.uint16; import static android.system.OsConstants.SOCK_STREAM; import static android.system.OsConstants.AF_UNIX; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertNotNull; import static org.junit.Assert.assertNotNull; import static org.junit.Assert.fail; import static org.mockito.ArgumentMatchers.any; import static org.mockito.ArgumentMatchers.any; import static org.mockito.ArgumentMatchers.eq; import static org.mockito.ArgumentMatchers.eq; import static org.mockito.Mockito.spy; import static org.mockito.Mockito.spy; import static org.mockito.Mockito.verify; import static org.mockito.Mockito.verify; import static org.mockito.Mockito.when; import android.hardware.tetheroffload.config.V1_0.IOffloadConfig; import android.hardware.tetheroffload.config.V1_0.IOffloadConfig; import android.hardware.tetheroffload.control.V1_0.IOffloadControl; import android.hardware.tetheroffload.control.V1_0.IOffloadControl; Loading @@ -31,11 +35,14 @@ import android.hardware.tetheroffload.control.V1_0.ITetheringOffloadCallback; import android.hardware.tetheroffload.control.V1_0.NatTimeoutUpdate; import android.hardware.tetheroffload.control.V1_0.NatTimeoutUpdate; import android.hardware.tetheroffload.control.V1_0.NetworkProtocol; import android.hardware.tetheroffload.control.V1_0.NetworkProtocol; import android.hardware.tetheroffload.control.V1_0.OffloadCallbackEvent; import android.hardware.tetheroffload.control.V1_0.OffloadCallbackEvent; import android.net.netlink.StructNlMsgHdr; import android.net.util.SharedLog; import android.net.util.SharedLog; import android.os.Handler; import android.os.Handler; import android.os.NativeHandle; import android.os.NativeHandle; import android.os.test.TestLooper; import android.os.test.TestLooper; import android.system.ErrnoException; import android.system.OsConstants; import android.system.OsConstants; import android.system.Os; import androidx.test.filters.SmallTest; import androidx.test.filters.SmallTest; import androidx.test.runner.AndroidJUnit4; import androidx.test.runner.AndroidJUnit4; Loading @@ -47,6 +54,9 @@ import org.mockito.ArgumentCaptor; import org.mockito.Mock; import org.mockito.Mock; import org.mockito.MockitoAnnotations; import org.mockito.MockitoAnnotations; import java.io.FileDescriptor; import java.io.OutputStream; import java.nio.ByteBuffer; import java.util.ArrayList; import java.util.ArrayList; @RunWith(AndroidJUnit4.class) @RunWith(AndroidJUnit4.class) Loading @@ -64,6 +74,10 @@ public final class OffloadHardwareInterfaceTest { @Mock private IOffloadControl mIOffloadControl; @Mock private IOffloadControl mIOffloadControl; @Mock private NativeHandle mNativeHandle; @Mock private NativeHandle mNativeHandle; // Random values to test Netlink message. private static final short TEST_TYPE = 184; private static final short TEST_FLAGS = 263; class MyDependencies extends OffloadHardwareInterface.Dependencies { class MyDependencies extends OffloadHardwareInterface.Dependencies { MyDependencies(SharedLog log) { MyDependencies(SharedLog log) { super(log); super(log); Loading Loading @@ -203,6 +217,31 @@ public final class OffloadHardwareInterfaceTest { eq(uint16(udpParams.dst.port))); eq(uint16(udpParams.dst.port))); } } @Test public void testNetlinkMessage() throws Exception { FileDescriptor writeSocket = new FileDescriptor(); FileDescriptor readSocket = new FileDescriptor(); try { Os.socketpair(AF_UNIX, SOCK_STREAM, 0, writeSocket, readSocket); } catch (ErrnoException e) { fail(); return; } when(mNativeHandle.getFileDescriptor()).thenReturn(writeSocket); mOffloadHw.sendNetlinkMessage(mNativeHandle, TEST_TYPE, TEST_FLAGS); ByteBuffer buffer = ByteBuffer.allocate(StructNlMsgHdr.STRUCT_SIZE); int read = Os.read(readSocket, buffer); buffer.flip(); assertEquals(StructNlMsgHdr.STRUCT_SIZE, buffer.getInt()); assertEquals(TEST_TYPE, buffer.getShort()); assertEquals(TEST_FLAGS, buffer.getShort()); assertEquals(1 /* seq */, buffer.getInt()); assertEquals(0 /* pid */, buffer.getInt()); } private NatTimeoutUpdate buildNatTimeoutUpdate(final int proto) { private NatTimeoutUpdate buildNatTimeoutUpdate(final int proto) { final NatTimeoutUpdate params = new NatTimeoutUpdate(); final NatTimeoutUpdate params = new NatTimeoutUpdate(); params.proto = proto; params.proto = proto; Loading Loading
packages/Tethering/src/com/android/networkstack/tethering/OffloadHardwareInterface.java +33 −0 Original line number Original line Diff line number Diff line Loading @@ -16,8 +16,11 @@ package com.android.networkstack.tethering; package com.android.networkstack.tethering; import static android.net.netlink.StructNlMsgHdr.NLM_F_DUMP; import static android.net.netlink.StructNlMsgHdr.NLM_F_REQUEST; import static android.net.util.TetheringUtils.uint16; import static android.net.util.TetheringUtils.uint16; import android.annotation.NonNull; import android.hardware.tetheroffload.config.V1_0.IOffloadConfig; import android.hardware.tetheroffload.config.V1_0.IOffloadConfig; import android.hardware.tetheroffload.control.V1_0.IOffloadControl; import android.hardware.tetheroffload.control.V1_0.IOffloadControl; import android.hardware.tetheroffload.control.V1_0.ITetheringOffloadCallback; import android.hardware.tetheroffload.control.V1_0.ITetheringOffloadCallback; Loading @@ -25,6 +28,7 @@ import android.hardware.tetheroffload.control.V1_0.NatTimeoutUpdate; import android.hardware.tetheroffload.control.V1_0.NetworkProtocol; import android.hardware.tetheroffload.control.V1_0.NetworkProtocol; import android.hardware.tetheroffload.control.V1_0.OffloadCallbackEvent; import android.hardware.tetheroffload.control.V1_0.OffloadCallbackEvent; import android.net.netlink.NetlinkSocket; import android.net.netlink.NetlinkSocket; import android.net.netlink.StructNlMsgHdr; import android.net.util.SharedLog; import android.net.util.SharedLog; import android.net.util.SocketUtils; import android.net.util.SocketUtils; import android.os.Handler; import android.os.Handler; Loading @@ -37,9 +41,11 @@ import android.system.OsConstants; import com.android.internal.annotations.VisibleForTesting; import com.android.internal.annotations.VisibleForTesting; import java.io.FileDescriptor; import java.io.FileDescriptor; import java.io.InterruptedIOException; import java.io.IOException; import java.io.IOException; import java.net.SocketAddress; import java.net.SocketAddress; import java.net.SocketException; import java.net.SocketException; import java.nio.ByteBuffer; import java.util.ArrayList; import java.util.ArrayList; import java.util.NoSuchElementException; import java.util.NoSuchElementException; Loading @@ -63,6 +69,11 @@ public class OffloadHardwareInterface { private static final int NF_NETLINK_CONNTRACK_NEW = 1; private static final int NF_NETLINK_CONNTRACK_NEW = 1; private static final int NF_NETLINK_CONNTRACK_UPDATE = 2; private static final int NF_NETLINK_CONNTRACK_UPDATE = 2; private static final int NF_NETLINK_CONNTRACK_DESTROY = 4; private static final int NF_NETLINK_CONNTRACK_DESTROY = 4; // Reference libnetfilter_conntrack/linux_nfnetlink_conntrack.h public static final short NFNL_SUBSYS_CTNETLINK = 1; public static final short IPCTNL_MSG_CT_GET = 1; private final long NETLINK_MESSAGE_TIMEOUT_MS = 500; private final Handler mHandler; private final Handler mHandler; private final SharedLog mLog; private final SharedLog mLog; Loading Loading @@ -226,6 +237,9 @@ public class OffloadHardwareInterface { NF_NETLINK_CONNTRACK_NEW | NF_NETLINK_CONNTRACK_DESTROY); NF_NETLINK_CONNTRACK_NEW | NF_NETLINK_CONNTRACK_DESTROY); if (h1 == null) return false; if (h1 == null) return false; sendNetlinkMessage(h1, (short) ((NFNL_SUBSYS_CTNETLINK << 8) | IPCTNL_MSG_CT_GET), (short) (NLM_F_REQUEST | NLM_F_DUMP)); final NativeHandle h2 = mDeps.createConntrackSocket( final NativeHandle h2 = mDeps.createConntrackSocket( NF_NETLINK_CONNTRACK_UPDATE | NF_NETLINK_CONNTRACK_DESTROY); NF_NETLINK_CONNTRACK_UPDATE | NF_NETLINK_CONNTRACK_DESTROY); if (h2 == null) { if (h2 == null) { Loading @@ -252,6 +266,25 @@ public class OffloadHardwareInterface { return results.mSuccess; return results.mSuccess; } } @VisibleForTesting public void sendNetlinkMessage(@NonNull NativeHandle handle, short type, short flags) { final int length = StructNlMsgHdr.STRUCT_SIZE; final byte[] msg = new byte[length]; final StructNlMsgHdr nlh = new StructNlMsgHdr(); final ByteBuffer byteBuffer = ByteBuffer.wrap(msg); nlh.nlmsg_len = length; nlh.nlmsg_type = type; nlh.nlmsg_flags = flags; nlh.nlmsg_seq = 1; nlh.pack(byteBuffer); try { NetlinkSocket.sendMessage(handle.getFileDescriptor(), msg, 0 /* offset */, length, NETLINK_MESSAGE_TIMEOUT_MS); } catch (ErrnoException | InterruptedIOException e) { mLog.e("Unable to send netfilter message, error: " + e); } } private void closeFdInNativeHandle(final NativeHandle h) { private void closeFdInNativeHandle(final NativeHandle h) { try { try { h.close(); h.close(); Loading
packages/Tethering/tests/unit/src/com/android/networkstack/tethering/OffloadHardwareInterfaceTest.java +39 −0 Original line number Original line Diff line number Diff line Loading @@ -17,13 +17,17 @@ package com.android.networkstack.tethering; package com.android.networkstack.tethering; import static android.net.util.TetheringUtils.uint16; import static android.net.util.TetheringUtils.uint16; import static android.system.OsConstants.SOCK_STREAM; import static android.system.OsConstants.AF_UNIX; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertNotNull; import static org.junit.Assert.assertNotNull; import static org.junit.Assert.fail; import static org.mockito.ArgumentMatchers.any; import static org.mockito.ArgumentMatchers.any; import static org.mockito.ArgumentMatchers.eq; import static org.mockito.ArgumentMatchers.eq; import static org.mockito.Mockito.spy; import static org.mockito.Mockito.spy; import static org.mockito.Mockito.verify; import static org.mockito.Mockito.verify; import static org.mockito.Mockito.when; import android.hardware.tetheroffload.config.V1_0.IOffloadConfig; import android.hardware.tetheroffload.config.V1_0.IOffloadConfig; import android.hardware.tetheroffload.control.V1_0.IOffloadControl; import android.hardware.tetheroffload.control.V1_0.IOffloadControl; Loading @@ -31,11 +35,14 @@ import android.hardware.tetheroffload.control.V1_0.ITetheringOffloadCallback; import android.hardware.tetheroffload.control.V1_0.NatTimeoutUpdate; import android.hardware.tetheroffload.control.V1_0.NatTimeoutUpdate; import android.hardware.tetheroffload.control.V1_0.NetworkProtocol; import android.hardware.tetheroffload.control.V1_0.NetworkProtocol; import android.hardware.tetheroffload.control.V1_0.OffloadCallbackEvent; import android.hardware.tetheroffload.control.V1_0.OffloadCallbackEvent; import android.net.netlink.StructNlMsgHdr; import android.net.util.SharedLog; import android.net.util.SharedLog; import android.os.Handler; import android.os.Handler; import android.os.NativeHandle; import android.os.NativeHandle; import android.os.test.TestLooper; import android.os.test.TestLooper; import android.system.ErrnoException; import android.system.OsConstants; import android.system.OsConstants; import android.system.Os; import androidx.test.filters.SmallTest; import androidx.test.filters.SmallTest; import androidx.test.runner.AndroidJUnit4; import androidx.test.runner.AndroidJUnit4; Loading @@ -47,6 +54,9 @@ import org.mockito.ArgumentCaptor; import org.mockito.Mock; import org.mockito.Mock; import org.mockito.MockitoAnnotations; import org.mockito.MockitoAnnotations; import java.io.FileDescriptor; import java.io.OutputStream; import java.nio.ByteBuffer; import java.util.ArrayList; import java.util.ArrayList; @RunWith(AndroidJUnit4.class) @RunWith(AndroidJUnit4.class) Loading @@ -64,6 +74,10 @@ public final class OffloadHardwareInterfaceTest { @Mock private IOffloadControl mIOffloadControl; @Mock private IOffloadControl mIOffloadControl; @Mock private NativeHandle mNativeHandle; @Mock private NativeHandle mNativeHandle; // Random values to test Netlink message. private static final short TEST_TYPE = 184; private static final short TEST_FLAGS = 263; class MyDependencies extends OffloadHardwareInterface.Dependencies { class MyDependencies extends OffloadHardwareInterface.Dependencies { MyDependencies(SharedLog log) { MyDependencies(SharedLog log) { super(log); super(log); Loading Loading @@ -203,6 +217,31 @@ public final class OffloadHardwareInterfaceTest { eq(uint16(udpParams.dst.port))); eq(uint16(udpParams.dst.port))); } } @Test public void testNetlinkMessage() throws Exception { FileDescriptor writeSocket = new FileDescriptor(); FileDescriptor readSocket = new FileDescriptor(); try { Os.socketpair(AF_UNIX, SOCK_STREAM, 0, writeSocket, readSocket); } catch (ErrnoException e) { fail(); return; } when(mNativeHandle.getFileDescriptor()).thenReturn(writeSocket); mOffloadHw.sendNetlinkMessage(mNativeHandle, TEST_TYPE, TEST_FLAGS); ByteBuffer buffer = ByteBuffer.allocate(StructNlMsgHdr.STRUCT_SIZE); int read = Os.read(readSocket, buffer); buffer.flip(); assertEquals(StructNlMsgHdr.STRUCT_SIZE, buffer.getInt()); assertEquals(TEST_TYPE, buffer.getShort()); assertEquals(TEST_FLAGS, buffer.getShort()); assertEquals(1 /* seq */, buffer.getInt()); assertEquals(0 /* pid */, buffer.getInt()); } private NatTimeoutUpdate buildNatTimeoutUpdate(final int proto) { private NatTimeoutUpdate buildNatTimeoutUpdate(final int proto) { final NatTimeoutUpdate params = new NatTimeoutUpdate(); final NatTimeoutUpdate params = new NatTimeoutUpdate(); params.proto = proto; params.proto = proto; Loading