Merge changes I73f30477,I84db13ac am: 2f1c2b25cd am: 2b82a04b56
Original change: https://android-review.googlesource.com/c/platform/packages/modules/Connectivity/+/1534829 MUST ONLY BE SUBMITTED BY AUTOMERGER Change-Id: I5cc251fb9b525ca3762e12f6d5ce4d935a4fa04a
This commit is contained in:
@@ -67,6 +67,7 @@ import com.android.internal.util.MessageUtils;
|
|||||||
import com.android.internal.util.State;
|
import com.android.internal.util.State;
|
||||||
import com.android.internal.util.StateMachine;
|
import com.android.internal.util.StateMachine;
|
||||||
import com.android.networkstack.tethering.BpfCoordinator;
|
import com.android.networkstack.tethering.BpfCoordinator;
|
||||||
|
import com.android.networkstack.tethering.BpfCoordinator.ClientInfo;
|
||||||
import com.android.networkstack.tethering.BpfCoordinator.Ipv6ForwardingRule;
|
import com.android.networkstack.tethering.BpfCoordinator.Ipv6ForwardingRule;
|
||||||
import com.android.networkstack.tethering.PrivateAddressCoordinator;
|
import com.android.networkstack.tethering.PrivateAddressCoordinator;
|
||||||
|
|
||||||
@@ -941,11 +942,38 @@ public class IpServer extends StateMachine {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// TODO: consider moving into BpfCoordinator.
|
||||||
|
private void updateClientInfoIpv4(NeighborEvent e) {
|
||||||
|
// TODO: Perhaps remove this protection check.
|
||||||
|
// See the related comment in #addIpv6ForwardingRule.
|
||||||
|
if (!mUsingBpfOffload) return;
|
||||||
|
|
||||||
|
if (e == null) return;
|
||||||
|
if (!(e.ip instanceof Inet4Address) || e.ip.isMulticastAddress()
|
||||||
|
|| e.ip.isLoopbackAddress() || e.ip.isLinkLocalAddress()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// When deleting clients, IpServer still need to pass a non-null MAC, even though it's
|
||||||
|
// ignored. Do this here instead of in the ClientInfo constructor to ensure that
|
||||||
|
// IpServer never add clients with a null MAC, only delete them.
|
||||||
|
final MacAddress clientMac = e.isValid() ? e.macAddr : NULL_MAC_ADDRESS;
|
||||||
|
final ClientInfo clientInfo = new ClientInfo(mInterfaceParams.index,
|
||||||
|
mInterfaceParams.macAddr, (Inet4Address) e.ip, clientMac);
|
||||||
|
if (e.isValid()) {
|
||||||
|
mBpfCoordinator.tetherOffloadClientAdd(this, clientInfo);
|
||||||
|
} else {
|
||||||
|
// TODO: Delete all related offload rules which are using this client.
|
||||||
|
mBpfCoordinator.tetherOffloadClientRemove(this, clientInfo);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private void handleNeighborEvent(NeighborEvent e) {
|
private void handleNeighborEvent(NeighborEvent e) {
|
||||||
if (mInterfaceParams != null
|
if (mInterfaceParams != null
|
||||||
&& mInterfaceParams.index == e.ifindex
|
&& mInterfaceParams.index == e.ifindex
|
||||||
&& mInterfaceParams.hasMacAddress) {
|
&& mInterfaceParams.hasMacAddress) {
|
||||||
updateIpv6ForwardingRules(mLastIPv6UpstreamIfindex, mLastIPv6UpstreamIfindex, e);
|
updateIpv6ForwardingRules(mLastIPv6UpstreamIfindex, mLastIPv6UpstreamIfindex, e);
|
||||||
|
updateClientInfoIpv4(e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -30,6 +30,7 @@ import static com.android.networkstack.tethering.TetheringConfiguration.DEFAULT_
|
|||||||
|
|
||||||
import android.app.usage.NetworkStatsManager;
|
import android.app.usage.NetworkStatsManager;
|
||||||
import android.net.INetd;
|
import android.net.INetd;
|
||||||
|
import android.net.LinkProperties;
|
||||||
import android.net.MacAddress;
|
import android.net.MacAddress;
|
||||||
import android.net.NetworkStats;
|
import android.net.NetworkStats;
|
||||||
import android.net.NetworkStats.Entry;
|
import android.net.NetworkStats.Entry;
|
||||||
@@ -38,6 +39,7 @@ import android.net.ip.ConntrackMonitor;
|
|||||||
import android.net.ip.ConntrackMonitor.ConntrackEventConsumer;
|
import android.net.ip.ConntrackMonitor.ConntrackEventConsumer;
|
||||||
import android.net.ip.IpServer;
|
import android.net.ip.IpServer;
|
||||||
import android.net.netstats.provider.NetworkStatsProvider;
|
import android.net.netstats.provider.NetworkStatsProvider;
|
||||||
|
import android.net.util.InterfaceParams;
|
||||||
import android.net.util.SharedLog;
|
import android.net.util.SharedLog;
|
||||||
import android.net.util.TetheringUtils.ForwardedStats;
|
import android.net.util.TetheringUtils.ForwardedStats;
|
||||||
import android.os.ConditionVariable;
|
import android.os.ConditionVariable;
|
||||||
@@ -56,8 +58,11 @@ import com.android.modules.utils.build.SdkLevel;
|
|||||||
import com.android.net.module.util.NetworkStackConstants;
|
import com.android.net.module.util.NetworkStackConstants;
|
||||||
import com.android.networkstack.tethering.apishim.common.BpfCoordinatorShim;
|
import com.android.networkstack.tethering.apishim.common.BpfCoordinatorShim;
|
||||||
|
|
||||||
|
import java.net.Inet4Address;
|
||||||
import java.net.Inet6Address;
|
import java.net.Inet6Address;
|
||||||
|
import java.net.InetAddress;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
|
import java.util.Collection;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.HashSet;
|
import java.util.HashSet;
|
||||||
import java.util.LinkedHashMap;
|
import java.util.LinkedHashMap;
|
||||||
@@ -162,9 +167,24 @@ public class BpfCoordinator {
|
|||||||
private final HashMap<IpServer, LinkedHashMap<Inet6Address, Ipv6ForwardingRule>>
|
private final HashMap<IpServer, LinkedHashMap<Inet6Address, Ipv6ForwardingRule>>
|
||||||
mIpv6ForwardingRules = new LinkedHashMap<>();
|
mIpv6ForwardingRules = new LinkedHashMap<>();
|
||||||
|
|
||||||
|
// Map of downstream client maps. Each of these maps represents the IPv4 clients for a given
|
||||||
|
// downstream. Needed to build IPv4 forwarding rules when conntrack events are received.
|
||||||
|
// Each map:
|
||||||
|
// - Is owned by the IpServer that is responsible for that downstream.
|
||||||
|
// - Must only be modified by that IpServer.
|
||||||
|
// - Is created when the IpServer adds its first client, and deleted when the IpServer deletes
|
||||||
|
// its last client.
|
||||||
|
private final HashMap<IpServer, HashMap<Inet4Address, ClientInfo>>
|
||||||
|
mTetherClients = new HashMap<>();
|
||||||
|
|
||||||
// Set for which downstream is monitoring the conntrack netlink message.
|
// Set for which downstream is monitoring the conntrack netlink message.
|
||||||
private final Set<IpServer> mMonitoringIpServers = new HashSet<>();
|
private final Set<IpServer> mMonitoringIpServers = new HashSet<>();
|
||||||
|
|
||||||
|
// Map of upstream interface IPv4 address to interface index.
|
||||||
|
// TODO: consider making the key to be unique because the upstream address is not unique. It
|
||||||
|
// is okay for now because there have only one upstream generally.
|
||||||
|
private final HashMap<Inet4Address, Integer> mIpv4UpstreamIndices = new HashMap<>();
|
||||||
|
|
||||||
// Runnable that used by scheduling next polling of stats.
|
// Runnable that used by scheduling next polling of stats.
|
||||||
private final Runnable mScheduledPollingTask = () -> {
|
private final Runnable mScheduledPollingTask = () -> {
|
||||||
updateForwardedStats();
|
updateForwardedStats();
|
||||||
@@ -504,6 +524,74 @@ public class BpfCoordinator {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Add downstream client.
|
||||||
|
*/
|
||||||
|
public void tetherOffloadClientAdd(@NonNull final IpServer ipServer,
|
||||||
|
@NonNull final ClientInfo client) {
|
||||||
|
if (!isUsingBpf()) return;
|
||||||
|
|
||||||
|
if (!mTetherClients.containsKey(ipServer)) {
|
||||||
|
mTetherClients.put(ipServer, new HashMap<Inet4Address, ClientInfo>());
|
||||||
|
}
|
||||||
|
|
||||||
|
HashMap<Inet4Address, ClientInfo> clients = mTetherClients.get(ipServer);
|
||||||
|
clients.put(client.clientAddress, client);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Remove downstream client.
|
||||||
|
*/
|
||||||
|
public void tetherOffloadClientRemove(@NonNull final IpServer ipServer,
|
||||||
|
@NonNull final ClientInfo client) {
|
||||||
|
if (!isUsingBpf()) return;
|
||||||
|
|
||||||
|
HashMap<Inet4Address, ClientInfo> clients = mTetherClients.get(ipServer);
|
||||||
|
if (clients == null) return;
|
||||||
|
|
||||||
|
// If no rule is removed, return early. Avoid unnecessary work on a non-existent rule
|
||||||
|
// which may have never been added or removed already.
|
||||||
|
if (clients.remove(client.clientAddress) == null) return;
|
||||||
|
|
||||||
|
// Remove the downstream entry if it has no more rule.
|
||||||
|
if (clients.isEmpty()) {
|
||||||
|
mTetherClients.remove(ipServer);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Call when UpstreamNetworkState may be changed.
|
||||||
|
* If upstream has ipv4 for tethering, update this new UpstreamNetworkState to map. The
|
||||||
|
* upstream interface index and its address mapping is prepared for building IPv4
|
||||||
|
* offload rule.
|
||||||
|
*
|
||||||
|
* TODO: Delete the unused upstream interface mapping.
|
||||||
|
* TODO: Support ether ip upstream interface.
|
||||||
|
*/
|
||||||
|
public void addUpstreamIfindexToMap(LinkProperties lp) {
|
||||||
|
if (!mPollingStarted) return;
|
||||||
|
|
||||||
|
// This will not work on a network that is using 464xlat because hasIpv4Address will not be
|
||||||
|
// true.
|
||||||
|
// TODO: need to consider 464xlat.
|
||||||
|
if (lp == null || !lp.hasIpv4Address()) return;
|
||||||
|
|
||||||
|
// Support raw ip upstream interface only.
|
||||||
|
final InterfaceParams params = InterfaceParams.getByName(lp.getInterfaceName());
|
||||||
|
if (params == null || params.hasMacAddress) return;
|
||||||
|
|
||||||
|
Collection<InetAddress> addresses = lp.getAddresses();
|
||||||
|
for (InetAddress addr: addresses) {
|
||||||
|
if (addr instanceof Inet4Address) {
|
||||||
|
Inet4Address i4addr = (Inet4Address) addr;
|
||||||
|
if (!i4addr.isAnyLocalAddress() && !i4addr.isLinkLocalAddress()
|
||||||
|
&& !i4addr.isLoopbackAddress() && !i4addr.isMulticastAddress()) {
|
||||||
|
mIpv4UpstreamIndices.put(i4addr, params.index);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Dump information.
|
* Dump information.
|
||||||
* Block the function until all the data are dumped on the handler thread or timed-out. The
|
* Block the function until all the data are dumped on the handler thread or timed-out. The
|
||||||
@@ -581,6 +669,7 @@ public class BpfCoordinator {
|
|||||||
public final int upstreamIfindex;
|
public final int upstreamIfindex;
|
||||||
public final int downstreamIfindex;
|
public final int downstreamIfindex;
|
||||||
|
|
||||||
|
// TODO: store a ClientInfo object instead of storing address, srcMac, and dstMac directly.
|
||||||
@NonNull
|
@NonNull
|
||||||
public final Inet6Address address;
|
public final Inet6Address address;
|
||||||
@NonNull
|
@NonNull
|
||||||
@@ -657,6 +746,48 @@ public class BpfCoordinator {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** Tethering client information class. */
|
||||||
|
public static class ClientInfo {
|
||||||
|
public final int downstreamIfindex;
|
||||||
|
|
||||||
|
@NonNull
|
||||||
|
public final MacAddress downstreamMac;
|
||||||
|
@NonNull
|
||||||
|
public final Inet4Address clientAddress;
|
||||||
|
@NonNull
|
||||||
|
public final MacAddress clientMac;
|
||||||
|
|
||||||
|
public ClientInfo(int downstreamIfindex,
|
||||||
|
@NonNull MacAddress downstreamMac, @NonNull Inet4Address clientAddress,
|
||||||
|
@NonNull MacAddress clientMac) {
|
||||||
|
this.downstreamIfindex = downstreamIfindex;
|
||||||
|
this.downstreamMac = downstreamMac;
|
||||||
|
this.clientAddress = clientAddress;
|
||||||
|
this.clientMac = clientMac;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean equals(Object o) {
|
||||||
|
if (!(o instanceof ClientInfo)) return false;
|
||||||
|
ClientInfo that = (ClientInfo) o;
|
||||||
|
return this.downstreamIfindex == that.downstreamIfindex
|
||||||
|
&& Objects.equals(this.downstreamMac, that.downstreamMac)
|
||||||
|
&& Objects.equals(this.clientAddress, that.clientAddress)
|
||||||
|
&& Objects.equals(this.clientMac, that.clientMac);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int hashCode() {
|
||||||
|
return Objects.hash(downstreamIfindex, downstreamMac, clientAddress, clientMac);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toString() {
|
||||||
|
return String.format("downstream: %d (%s), client: %s (%s)",
|
||||||
|
downstreamIfindex, downstreamMac, clientAddress, clientMac);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A BPF tethering stats provider to provide network statistics to the system.
|
* A BPF tethering stats provider to provide network statistics to the system.
|
||||||
* Note that this class' data may only be accessed on the handler thread.
|
* Note that this class' data may only be accessed on the handler thread.
|
||||||
|
|||||||
@@ -1636,6 +1636,13 @@ public class Tethering {
|
|||||||
protected void handleNewUpstreamNetworkState(UpstreamNetworkState ns) {
|
protected void handleNewUpstreamNetworkState(UpstreamNetworkState ns) {
|
||||||
mIPv6TetheringCoordinator.updateUpstreamNetworkState(ns);
|
mIPv6TetheringCoordinator.updateUpstreamNetworkState(ns);
|
||||||
mOffload.updateUpstreamNetworkState(ns);
|
mOffload.updateUpstreamNetworkState(ns);
|
||||||
|
|
||||||
|
// TODO: Delete all related offload rules which are using this upstream.
|
||||||
|
if (ns != null) {
|
||||||
|
// Add upstream index to the map. The upstream interface index is required while
|
||||||
|
// the conntrack event builds the offload rules.
|
||||||
|
mBpfCoordinator.addUpstreamIfindexToMap(ns.linkProperties);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void handleInterfaceServingStateActive(int mode, IpServer who) {
|
private void handleInterfaceServingStateActive(int mode, IpServer who) {
|
||||||
|
|||||||
Reference in New Issue
Block a user