[NFCT.TETHER.1] Add conntrack monitor to BpfCoordinator
A preparation for starting monitoring conntrack event which is required
by IPv4 tethering offload.
Test: atest TetheringCoverageTests
Change-Id: Ied46aeca193554f52a90889dfdf92827e94845d6
diff --git a/Tethering/src/android/net/ip/IpServer.java b/Tethering/src/android/net/ip/IpServer.java
index 52d59fc..bcabc0f 100644
--- a/Tethering/src/android/net/ip/IpServer.java
+++ b/Tethering/src/android/net/ip/IpServer.java
@@ -1111,9 +1111,19 @@
}
}
+ private void startConntrackMonitoring() {
+ mBpfCoordinator.startMonitoring(this);
+ }
+
+ private void stopConntrackMonitoring() {
+ mBpfCoordinator.stopMonitoring(this);
+ }
+
class BaseServingState extends State {
@Override
public void enter() {
+ startConntrackMonitoring();
+
if (!startIPv4()) {
mLastError = TetheringManager.TETHER_ERROR_IFACE_CFG_ERROR;
return;
@@ -1149,6 +1159,7 @@
}
stopIPv4();
+ stopConntrackMonitoring();
resetLinkProperties();
}
diff --git a/Tethering/src/com/android/networkstack/tethering/BpfCoordinator.java b/Tethering/src/com/android/networkstack/tethering/BpfCoordinator.java
index f9a819e..8d50e5e 100644
--- a/Tethering/src/com/android/networkstack/tethering/BpfCoordinator.java
+++ b/Tethering/src/com/android/networkstack/tethering/BpfCoordinator.java
@@ -34,6 +34,8 @@
import android.net.NetworkStats;
import android.net.NetworkStats.Entry;
import android.net.TetherOffloadRuleParcel;
+import android.net.ip.ConntrackMonitor;
+import android.net.ip.ConntrackMonitor.ConntrackEventConsumer;
import android.net.ip.IpServer;
import android.net.netstats.provider.NetworkStatsProvider;
import android.net.util.SharedLog;
@@ -57,9 +59,11 @@
import java.net.Inet6Address;
import java.util.ArrayList;
import java.util.HashMap;
+import java.util.HashSet;
import java.util.LinkedHashMap;
import java.util.Map;
import java.util.Objects;
+import java.util.Set;
/**
* This coordinator is responsible for providing BPF offload relevant functionality.
@@ -94,6 +98,8 @@
private final SharedLog mLog;
@NonNull
private final Dependencies mDeps;
+ @NonNull
+ private final ConntrackMonitor mConntrackMonitor;
@Nullable
private final BpfTetherStatsProvider mStatsProvider;
@NonNull
@@ -156,6 +162,9 @@
private final HashMap<IpServer, LinkedHashMap<Inet6Address, Ipv6ForwardingRule>>
mIpv6ForwardingRules = new LinkedHashMap<>();
+ // Set for which downstream is monitoring the conntrack netlink message.
+ private final Set<IpServer> mMonitoringIpServers = new HashSet<>();
+
// Runnable that used by scheduling next polling of stats.
private final Runnable mScheduledPollingTask = () -> {
updateForwardedStats();
@@ -179,6 +188,11 @@
/** Get tethering configuration. */
@Nullable public abstract TetheringConfiguration getTetherConfig();
+ /** Get conntrack monitor. */
+ @NonNull public ConntrackMonitor getConntrackMonitor(ConntrackEventConsumer consumer) {
+ return new ConntrackMonitor(getHandler(), getSharedLog(), consumer);
+ }
+
/**
* Check OS Build at least S.
*
@@ -232,6 +246,7 @@
mNetd = mDeps.getNetd();
mLog = mDeps.getSharedLog().forSubComponent(TAG);
mIsBpfEnabled = isBpfEnabled();
+ mConntrackMonitor = mDeps.getConntrackMonitor(new BpfConntrackEventConsumer());
BpfTetherStatsProvider provider = new BpfTetherStatsProvider();
try {
mDeps.getNetworkStatsManager().registerNetworkStatsProvider(
@@ -296,6 +311,58 @@
}
/**
+ * Start conntrack message monitoring.
+ * Note that this can be only called on handler thread.
+ *
+ * TODO: figure out a better logging for non-interesting conntrack message.
+ * For example, the following logging is an IPCTNL_MSG_CT_GET message but looks scary.
+ * +---------------------------------------------------------------------------+
+ * | ERROR unparsable netlink msg: 1400000001010103000000000000000002000000 |
+ * +------------------+--------------------------------------------------------+
+ * | | struct nlmsghdr |
+ * | 14000000 | length = 20 |
+ * | 0101 | type = NFNL_SUBSYS_CTNETLINK << 8 | IPCTNL_MSG_CT_GET |
+ * | 0103 | flags |
+ * | 00000000 | seqno = 0 |
+ * | 00000000 | pid = 0 |
+ * | | struct nfgenmsg |
+ * | 02 | nfgen_family = AF_INET |
+ * | 00 | version = NFNETLINK_V0 |
+ * | 0000 | res_id |
+ * +------------------+--------------------------------------------------------+
+ * See NetlinkMonitor#handlePacket, NetlinkMessage#parseNfMessage.
+ */
+ public void startMonitoring(@NonNull final IpServer ipServer) {
+ if (!isUsingBpf()) return;
+
+ if (mMonitoringIpServers.contains(ipServer)) {
+ Log.wtf(TAG, "The same downstream " + ipServer.interfaceName()
+ + " should not start monitoring twice.");
+ return;
+ }
+
+ if (mMonitoringIpServers.isEmpty()) {
+ mConntrackMonitor.start();
+ mLog.i("Monitoring started");
+ }
+
+ mMonitoringIpServers.add(ipServer);
+ }
+
+ /**
+ * Stop conntrack event monitoring.
+ * Note that this can be only called on handler thread.
+ */
+ public void stopMonitoring(@NonNull final IpServer ipServer) {
+ mMonitoringIpServers.remove(ipServer);
+
+ if (!mMonitoringIpServers.isEmpty()) return;
+
+ mConntrackMonitor.stop();
+ mLog.i("Monitoring stopped");
+ }
+
+ /**
* Add forwarding rule. After adding the first rule on a given upstream, must add the data
* limit on the given upstream.
* Note that this can be only called on handler thread.
@@ -656,6 +723,10 @@
}
}
+ private class BpfConntrackEventConsumer implements ConntrackEventConsumer {
+ public void accept(ConntrackMonitor.ConntrackEvent e) { /* TODO */ }
+ }
+
private boolean isBpfEnabled() {
final TetheringConfiguration config = mDeps.getTetherConfig();
return (config != null) ? config.isBpfOffloadEnabled() : true /* default value */;