summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
author Lorenzo Colitti <lorenzo@google.com> 2020-06-24 03:44:31 +0000
committer Lorenzo Colitti <lorenzo@google.com> 2020-06-24 04:21:47 +0000
commit8c2e6b8a284051e3d2db8c99c9abd1076d431b6a (patch)
tree9fc2981aaba63977a8e6cfe59d14f5e7377f3788
parent77190b77f6cebc794ea0808d4645bb10d68c195d (diff)
tethering: offload: Netlink Req
Send netlink request over fd for offload config before completing init sequence. Provides existing conntrack entries to IPA. Resolves issue where there are NAT misses in IPA due to IPA only having the conntrack entries added after tethering starts. Bug: 149109043 Test: OffloadHardwareInterfaceTest Original-Change: https://android-review.googlesource.com/1290954 Merged-In: Iaf3e847e92f205b55f10fa85c17b9f3995d52099 Change-Id: Iaf3e847e92f205b55f10fa85c17b9f3995d52099
-rw-r--r--packages/Tethering/src/com/android/networkstack/tethering/OffloadHardwareInterface.java33
-rw-r--r--packages/Tethering/tests/unit/src/com/android/networkstack/tethering/OffloadHardwareInterfaceTest.java39
2 files changed, 72 insertions, 0 deletions
diff --git a/packages/Tethering/src/com/android/networkstack/tethering/OffloadHardwareInterface.java b/packages/Tethering/src/com/android/networkstack/tethering/OffloadHardwareInterface.java
index fe92204c25c8..33b9d00e70dc 100644
--- a/packages/Tethering/src/com/android/networkstack/tethering/OffloadHardwareInterface.java
+++ b/packages/Tethering/src/com/android/networkstack/tethering/OffloadHardwareInterface.java
@@ -16,8 +16,11 @@
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 android.annotation.NonNull;
import android.hardware.tetheroffload.config.V1_0.IOffloadConfig;
import android.hardware.tetheroffload.control.V1_0.IOffloadControl;
import android.hardware.tetheroffload.control.V1_0.ITetheringOffloadCallback;
@@ -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.OffloadCallbackEvent;
import android.net.netlink.NetlinkSocket;
+import android.net.netlink.StructNlMsgHdr;
import android.net.util.SharedLog;
import android.net.util.SocketUtils;
import android.os.Handler;
@@ -37,9 +41,11 @@ import android.system.OsConstants;
import com.android.internal.annotations.VisibleForTesting;
import java.io.FileDescriptor;
+import java.io.InterruptedIOException;
import java.io.IOException;
import java.net.SocketAddress;
import java.net.SocketException;
+import java.nio.ByteBuffer;
import java.util.ArrayList;
import java.util.NoSuchElementException;
@@ -63,6 +69,11 @@ public class OffloadHardwareInterface {
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_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 SharedLog mLog;
@@ -226,6 +237,9 @@ public class OffloadHardwareInterface {
NF_NETLINK_CONNTRACK_NEW | NF_NETLINK_CONNTRACK_DESTROY);
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(
NF_NETLINK_CONNTRACK_UPDATE | NF_NETLINK_CONNTRACK_DESTROY);
if (h2 == null) {
@@ -252,6 +266,25 @@ public class OffloadHardwareInterface {
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) {
try {
h.close();
diff --git a/packages/Tethering/tests/unit/src/com/android/networkstack/tethering/OffloadHardwareInterfaceTest.java b/packages/Tethering/tests/unit/src/com/android/networkstack/tethering/OffloadHardwareInterfaceTest.java
index f8ff1cb29c23..c543fad62dba 100644
--- a/packages/Tethering/tests/unit/src/com/android/networkstack/tethering/OffloadHardwareInterfaceTest.java
+++ b/packages/Tethering/tests/unit/src/com/android/networkstack/tethering/OffloadHardwareInterfaceTest.java
@@ -17,13 +17,17 @@
package com.android.networkstack.tethering;
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.assertNotNull;
+import static org.junit.Assert.fail;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.eq;
import static org.mockito.Mockito.spy;
import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
import android.hardware.tetheroffload.config.V1_0.IOffloadConfig;
import android.hardware.tetheroffload.control.V1_0.IOffloadControl;
@@ -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.NetworkProtocol;
import android.hardware.tetheroffload.control.V1_0.OffloadCallbackEvent;
+import android.net.netlink.StructNlMsgHdr;
import android.net.util.SharedLog;
import android.os.Handler;
import android.os.NativeHandle;
import android.os.test.TestLooper;
+import android.system.ErrnoException;
import android.system.OsConstants;
+import android.system.Os;
import androidx.test.filters.SmallTest;
import androidx.test.runner.AndroidJUnit4;
@@ -47,6 +54,9 @@ import org.mockito.ArgumentCaptor;
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
+import java.io.FileDescriptor;
+import java.io.OutputStream;
+import java.nio.ByteBuffer;
import java.util.ArrayList;
@RunWith(AndroidJUnit4.class)
@@ -64,6 +74,10 @@ public final class OffloadHardwareInterfaceTest {
@Mock private IOffloadControl mIOffloadControl;
@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 {
MyDependencies(SharedLog log) {
super(log);
@@ -203,6 +217,31 @@ public final class OffloadHardwareInterfaceTest {
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) {
final NatTimeoutUpdate params = new NatTimeoutUpdate();
params.proto = proto;