Merge "Introduce Ipv6UpstreamRule to bpf tethering offload" into main
This commit is contained in:
@@ -17,8 +17,6 @@
|
||||
package com.android.networkstack.tethering.apishim.api30;
|
||||
|
||||
import android.net.INetd;
|
||||
import android.net.IpPrefix;
|
||||
import android.net.MacAddress;
|
||||
import android.net.TetherStatsParcel;
|
||||
import android.os.RemoteException;
|
||||
import android.os.ServiceSpecificException;
|
||||
@@ -33,7 +31,8 @@ import com.android.net.module.util.bpf.Tether4Key;
|
||||
import com.android.net.module.util.bpf.Tether4Value;
|
||||
import com.android.net.module.util.bpf.TetherStatsValue;
|
||||
import com.android.networkstack.tethering.BpfCoordinator.Dependencies;
|
||||
import com.android.networkstack.tethering.BpfCoordinator.Ipv6ForwardingRule;
|
||||
import com.android.networkstack.tethering.BpfCoordinator.Ipv6DownstreamRule;
|
||||
import com.android.networkstack.tethering.BpfCoordinator.Ipv6UpstreamRule;
|
||||
|
||||
/**
|
||||
* Bpf coordinator class for API shims.
|
||||
@@ -58,7 +57,17 @@ public class BpfCoordinatorShimImpl
|
||||
};
|
||||
|
||||
@Override
|
||||
public boolean tetherOffloadRuleAdd(@NonNull final Ipv6ForwardingRule rule) {
|
||||
public boolean addIpv6UpstreamRule(@NonNull final Ipv6UpstreamRule rule) {
|
||||
return true;
|
||||
};
|
||||
|
||||
@Override
|
||||
public boolean removeIpv6UpstreamRule(@NonNull final Ipv6UpstreamRule rule) {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean addIpv6DownstreamRule(@NonNull final Ipv6DownstreamRule rule) {
|
||||
try {
|
||||
mNetd.tetherOffloadRuleAdd(rule.toTetherOffloadRuleParcel());
|
||||
} catch (RemoteException | ServiceSpecificException e) {
|
||||
@@ -70,7 +79,7 @@ public class BpfCoordinatorShimImpl
|
||||
};
|
||||
|
||||
@Override
|
||||
public boolean tetherOffloadRuleRemove(@NonNull final Ipv6ForwardingRule rule) {
|
||||
public boolean removeIpv6DownstreamRule(@NonNull final Ipv6DownstreamRule rule) {
|
||||
try {
|
||||
mNetd.tetherOffloadRuleRemove(rule.toTetherOffloadRuleParcel());
|
||||
} catch (RemoteException | ServiceSpecificException e) {
|
||||
@@ -80,19 +89,6 @@ public class BpfCoordinatorShimImpl
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean startUpstreamIpv6Forwarding(int downstreamIfindex, int upstreamIfindex,
|
||||
@NonNull IpPrefix sourcePrefix, @NonNull MacAddress inDstMac,
|
||||
@NonNull MacAddress outSrcMac, @NonNull MacAddress outDstMac, int mtu) {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean stopUpstreamIpv6Forwarding(int downstreamIfindex, int upstreamIfindex,
|
||||
@NonNull IpPrefix sourcePrefix, @NonNull MacAddress inDstMac) {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
@Nullable
|
||||
public SparseArray<TetherStatsValue> tetherOffloadGetStats() {
|
||||
|
||||
@@ -20,8 +20,6 @@ import static android.net.netstats.provider.NetworkStatsProvider.QUOTA_UNLIMITED
|
||||
|
||||
import static com.android.net.module.util.NetworkStackConstants.RFC7421_PREFIX_LENGTH;
|
||||
|
||||
import android.net.IpPrefix;
|
||||
import android.net.MacAddress;
|
||||
import android.system.ErrnoException;
|
||||
import android.system.Os;
|
||||
import android.system.OsConstants;
|
||||
@@ -39,7 +37,8 @@ import com.android.net.module.util.bpf.Tether4Value;
|
||||
import com.android.net.module.util.bpf.TetherStatsKey;
|
||||
import com.android.net.module.util.bpf.TetherStatsValue;
|
||||
import com.android.networkstack.tethering.BpfCoordinator.Dependencies;
|
||||
import com.android.networkstack.tethering.BpfCoordinator.Ipv6ForwardingRule;
|
||||
import com.android.networkstack.tethering.BpfCoordinator.Ipv6DownstreamRule;
|
||||
import com.android.networkstack.tethering.BpfCoordinator.Ipv6UpstreamRule;
|
||||
import com.android.networkstack.tethering.BpfUtils;
|
||||
import com.android.networkstack.tethering.Tether6Value;
|
||||
import com.android.networkstack.tethering.TetherDevKey;
|
||||
@@ -51,9 +50,6 @@ import com.android.networkstack.tethering.TetherUpstream6Key;
|
||||
|
||||
import java.io.FileDescriptor;
|
||||
import java.io.IOException;
|
||||
import java.nio.ByteBuffer;
|
||||
import java.nio.ByteOrder;
|
||||
import java.util.Arrays;
|
||||
|
||||
/**
|
||||
* Bpf coordinator class for API shims.
|
||||
@@ -170,7 +166,40 @@ public class BpfCoordinatorShimImpl
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean tetherOffloadRuleAdd(@NonNull final Ipv6ForwardingRule rule) {
|
||||
public boolean addIpv6UpstreamRule(@NonNull final Ipv6UpstreamRule rule) {
|
||||
if (!isInitialized()) return false;
|
||||
// RFC7421_PREFIX_LENGTH = 64 which is the most commonly used IPv6 subnet prefix length.
|
||||
if (rule.sourcePrefix.getPrefixLength() != RFC7421_PREFIX_LENGTH) return false;
|
||||
|
||||
final TetherUpstream6Key key = rule.makeTetherUpstream6Key();
|
||||
final Tether6Value value = rule.makeTether6Value();
|
||||
|
||||
try {
|
||||
mBpfUpstream6Map.insertEntry(key, value);
|
||||
} catch (ErrnoException | IllegalStateException e) {
|
||||
mLog.e("Could not insert upstream IPv6 entry: " + e);
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean removeIpv6UpstreamRule(@NonNull final Ipv6UpstreamRule rule) {
|
||||
if (!isInitialized()) return false;
|
||||
// RFC7421_PREFIX_LENGTH = 64 which is the most commonly used IPv6 subnet prefix length.
|
||||
if (rule.sourcePrefix.getPrefixLength() != RFC7421_PREFIX_LENGTH) return false;
|
||||
|
||||
try {
|
||||
mBpfUpstream6Map.deleteEntry(rule.makeTetherUpstream6Key());
|
||||
} catch (ErrnoException e) {
|
||||
mLog.e("Could not delete upstream IPv6 entry: " + e);
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean addIpv6DownstreamRule(@NonNull final Ipv6DownstreamRule rule) {
|
||||
if (!isInitialized()) return false;
|
||||
|
||||
final TetherDownstream6Key key = rule.makeTetherDownstream6Key();
|
||||
@@ -187,7 +216,7 @@ public class BpfCoordinatorShimImpl
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean tetherOffloadRuleRemove(@NonNull final Ipv6ForwardingRule rule) {
|
||||
public boolean removeIpv6DownstreamRule(@NonNull final Ipv6DownstreamRule rule) {
|
||||
if (!isInitialized()) return false;
|
||||
|
||||
try {
|
||||
@@ -202,51 +231,6 @@ public class BpfCoordinatorShimImpl
|
||||
return true;
|
||||
}
|
||||
|
||||
@NonNull
|
||||
private TetherUpstream6Key makeUpstream6Key(int downstreamIfindex, @NonNull MacAddress inDstMac,
|
||||
@NonNull IpPrefix sourcePrefix) {
|
||||
byte[] prefixBytes = Arrays.copyOf(sourcePrefix.getRawAddress(), 8);
|
||||
long prefix64 = ByteBuffer.wrap(prefixBytes).order(ByteOrder.BIG_ENDIAN).getLong();
|
||||
return new TetherUpstream6Key(downstreamIfindex, inDstMac, prefix64);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean startUpstreamIpv6Forwarding(int downstreamIfindex, int upstreamIfindex,
|
||||
@NonNull IpPrefix sourcePrefix, @NonNull MacAddress inDstMac,
|
||||
@NonNull MacAddress outSrcMac, @NonNull MacAddress outDstMac, int mtu) {
|
||||
if (!isInitialized()) return false;
|
||||
// RFC7421_PREFIX_LENGTH = 64 which is the most commonly used IPv6 subnet prefix length.
|
||||
if (sourcePrefix.getPrefixLength() != RFC7421_PREFIX_LENGTH) return false;
|
||||
|
||||
final TetherUpstream6Key key = makeUpstream6Key(downstreamIfindex, inDstMac, sourcePrefix);
|
||||
final Tether6Value value = new Tether6Value(upstreamIfindex, outSrcMac,
|
||||
outDstMac, OsConstants.ETH_P_IPV6, mtu);
|
||||
try {
|
||||
mBpfUpstream6Map.insertEntry(key, value);
|
||||
} catch (ErrnoException | IllegalStateException e) {
|
||||
mLog.e("Could not insert upstream6 entry: " + e);
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean stopUpstreamIpv6Forwarding(int downstreamIfindex, int upstreamIfindex,
|
||||
@NonNull IpPrefix sourcePrefix, @NonNull MacAddress inDstMac) {
|
||||
if (!isInitialized()) return false;
|
||||
// RFC7421_PREFIX_LENGTH = 64 which is the most commonly used IPv6 subnet prefix length.
|
||||
if (sourcePrefix.getPrefixLength() != RFC7421_PREFIX_LENGTH) return false;
|
||||
|
||||
final TetherUpstream6Key key = makeUpstream6Key(downstreamIfindex, inDstMac, sourcePrefix);
|
||||
try {
|
||||
mBpfUpstream6Map.deleteEntry(key);
|
||||
} catch (ErrnoException e) {
|
||||
mLog.e("Could not delete upstream IPv6 entry: " + e);
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
@Nullable
|
||||
public SparseArray<TetherStatsValue> tetherOffloadGetStats() {
|
||||
|
||||
@@ -16,8 +16,6 @@
|
||||
|
||||
package com.android.networkstack.tethering.apishim.common;
|
||||
|
||||
import android.net.IpPrefix;
|
||||
import android.net.MacAddress;
|
||||
import android.util.SparseArray;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
@@ -28,7 +26,8 @@ import com.android.net.module.util.bpf.Tether4Key;
|
||||
import com.android.net.module.util.bpf.Tether4Value;
|
||||
import com.android.net.module.util.bpf.TetherStatsValue;
|
||||
import com.android.networkstack.tethering.BpfCoordinator.Dependencies;
|
||||
import com.android.networkstack.tethering.BpfCoordinator.Ipv6ForwardingRule;
|
||||
import com.android.networkstack.tethering.BpfCoordinator.Ipv6DownstreamRule;
|
||||
import com.android.networkstack.tethering.BpfCoordinator.Ipv6UpstreamRule;
|
||||
|
||||
/**
|
||||
* Bpf coordinator class for API shims.
|
||||
@@ -54,53 +53,51 @@ public abstract class BpfCoordinatorShim {
|
||||
public abstract boolean isInitialized();
|
||||
|
||||
/**
|
||||
* Adds a tethering offload rule to BPF map, or updates it if it already exists.
|
||||
* Adds a tethering offload upstream rule to BPF map, or updates it if it already exists.
|
||||
*
|
||||
* An existing rule will be updated if the input interface, destination MAC and source prefix
|
||||
* match. Otherwise, a new rule will be created. Note that this can be only called on handler
|
||||
* thread.
|
||||
*
|
||||
* @param rule The rule to add or update.
|
||||
* @return true if operation succeeded or was a no-op, false otherwise.
|
||||
*/
|
||||
public abstract boolean addIpv6UpstreamRule(@NonNull Ipv6UpstreamRule rule);
|
||||
|
||||
/**
|
||||
* Deletes a tethering offload upstream rule from the BPF map.
|
||||
*
|
||||
* An existing rule will be deleted if the input interface, destination MAC and source prefix
|
||||
* match. It is not an error if there is no matching rule to delete.
|
||||
*
|
||||
* @param rule The rule to delete.
|
||||
* @return true if operation succeeded or was a no-op, false otherwise.
|
||||
*/
|
||||
public abstract boolean removeIpv6UpstreamRule(@NonNull Ipv6UpstreamRule rule);
|
||||
|
||||
/**
|
||||
* Adds a tethering offload downstream rule to BPF map, or updates it if it already exists.
|
||||
*
|
||||
* Currently, only downstream /128 IPv6 entries are supported. An existing rule will be updated
|
||||
* if the input interface and destination prefix match. Otherwise, a new rule will be created.
|
||||
* Note that this can be only called on handler thread.
|
||||
*
|
||||
* @param rule The rule to add or update.
|
||||
* @return true if operation succeeded or was a no-op, false otherwise.
|
||||
*/
|
||||
public abstract boolean tetherOffloadRuleAdd(@NonNull Ipv6ForwardingRule rule);
|
||||
public abstract boolean addIpv6DownstreamRule(@NonNull Ipv6DownstreamRule rule);
|
||||
|
||||
/**
|
||||
* Deletes a tethering offload rule from the BPF map.
|
||||
* Deletes a tethering offload downstream rule from the BPF map.
|
||||
*
|
||||
* Currently, only downstream /128 IPv6 entries are supported. An existing rule will be deleted
|
||||
* if the destination IP address and the source interface match. It is not an error if there is
|
||||
* no matching rule to delete.
|
||||
*
|
||||
* @param rule The rule to delete.
|
||||
* @return true if operation succeeded or was a no-op, false otherwise.
|
||||
*/
|
||||
public abstract boolean tetherOffloadRuleRemove(@NonNull Ipv6ForwardingRule rule);
|
||||
|
||||
/**
|
||||
* Starts IPv6 forwarding between the specified interfaces.
|
||||
|
||||
* @param downstreamIfindex the downstream interface index
|
||||
* @param upstreamIfindex the upstream interface index
|
||||
* @param sourcePrefix the source IPv6 prefix
|
||||
* @param inDstMac the destination MAC address to use for XDP
|
||||
* @param outSrcMac the source MAC address to use for packets
|
||||
* @param outDstMac the destination MAC address to use for packets
|
||||
* @return true if operation succeeded or was a no-op, false otherwise
|
||||
*/
|
||||
public abstract boolean startUpstreamIpv6Forwarding(int downstreamIfindex, int upstreamIfindex,
|
||||
@NonNull IpPrefix sourcePrefix, @NonNull MacAddress inDstMac,
|
||||
@NonNull MacAddress outSrcMac, @NonNull MacAddress outDstMac, int mtu);
|
||||
|
||||
/**
|
||||
* Stops IPv6 forwarding between the specified interfaces.
|
||||
|
||||
* @param downstreamIfindex the downstream interface index
|
||||
* @param upstreamIfindex the upstream interface index
|
||||
* @param sourcePrefix the valid source IPv6 prefix
|
||||
* @param inDstMac the destination MAC address to use for XDP
|
||||
* @return true if operation succeeded or was a no-op, false otherwise
|
||||
*/
|
||||
public abstract boolean stopUpstreamIpv6Forwarding(int downstreamIfindex, int upstreamIfindex,
|
||||
@NonNull IpPrefix sourcePrefix, @NonNull MacAddress inDstMac);
|
||||
public abstract boolean removeIpv6DownstreamRule(@NonNull Ipv6DownstreamRule rule);
|
||||
|
||||
/**
|
||||
* Return BPF tethering offload statistics.
|
||||
|
||||
@@ -77,7 +77,7 @@ import com.android.net.module.util.ip.IpNeighborMonitor;
|
||||
import com.android.net.module.util.ip.IpNeighborMonitor.NeighborEvent;
|
||||
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.Ipv6DownstreamRule;
|
||||
import com.android.networkstack.tethering.PrivateAddressCoordinator;
|
||||
import com.android.networkstack.tethering.TetheringConfiguration;
|
||||
import com.android.networkstack.tethering.metrics.TetheringMetrics;
|
||||
@@ -327,8 +327,8 @@ public class IpServer extends StateMachine {
|
||||
|
||||
// IP neighbor monitor monitors the neighbor events for adding/removing offload
|
||||
// forwarding rules per client. If BPF offload is not supported, don't start listening
|
||||
// for neighbor events. See updateIpv6ForwardingRules, addIpv6ForwardingRule,
|
||||
// removeIpv6ForwardingRule.
|
||||
// for neighbor events. See updateIpv6ForwardingRules, addIpv6DownstreamRule,
|
||||
// removeIpv6DownstreamRule.
|
||||
if (mUsingBpfOffload && !mIpNeighborMonitor.start()) {
|
||||
mLog.e("Failed to create IpNeighborMonitor on " + mIfaceName);
|
||||
}
|
||||
@@ -890,21 +890,21 @@ public class IpServer extends StateMachine {
|
||||
}
|
||||
}
|
||||
|
||||
private void addIpv6ForwardingRule(Ipv6ForwardingRule rule) {
|
||||
private void addIpv6DownstreamRule(Ipv6DownstreamRule rule) {
|
||||
// Theoretically, we don't need this check because IP neighbor monitor doesn't start if BPF
|
||||
// offload is disabled. Add this check just in case.
|
||||
// TODO: Perhaps remove this protection check.
|
||||
if (!mUsingBpfOffload) return;
|
||||
|
||||
mBpfCoordinator.tetherOffloadRuleAdd(this, rule);
|
||||
mBpfCoordinator.addIpv6DownstreamRule(this, rule);
|
||||
}
|
||||
|
||||
private void removeIpv6ForwardingRule(Ipv6ForwardingRule rule) {
|
||||
private void removeIpv6DownstreamRule(Ipv6DownstreamRule rule) {
|
||||
// TODO: Perhaps remove this protection check.
|
||||
// See the related comment in #addIpv6ForwardingRule.
|
||||
// See the related comment in #addIpv6DownstreamRule.
|
||||
if (!mUsingBpfOffload) return;
|
||||
|
||||
mBpfCoordinator.tetherOffloadRuleRemove(this, rule);
|
||||
mBpfCoordinator.removeIpv6DownstreamRule(this, rule);
|
||||
}
|
||||
|
||||
private void clearIpv6ForwardingRules() {
|
||||
@@ -915,7 +915,7 @@ public class IpServer extends StateMachine {
|
||||
|
||||
private void updateIpv6ForwardingRule(int newIfindex) {
|
||||
// TODO: Perhaps remove this protection check.
|
||||
// See the related comment in #addIpv6ForwardingRule.
|
||||
// See the related comment in #addIpv6DownstreamRule.
|
||||
if (!mUsingBpfOffload) return;
|
||||
|
||||
mBpfCoordinator.tetherOffloadRuleUpdate(this, newIfindex);
|
||||
@@ -954,22 +954,22 @@ public class IpServer extends StateMachine {
|
||||
}
|
||||
|
||||
// When deleting rules, we still need to pass a non-null MAC, even though it's ignored.
|
||||
// Do this here instead of in the Ipv6ForwardingRule constructor to ensure that we never
|
||||
// add rules with a null MAC, only delete them.
|
||||
// Do this here instead of in the Ipv6DownstreamRule constructor to ensure that we
|
||||
// never add rules with a null MAC, only delete them.
|
||||
MacAddress dstMac = e.isValid() ? e.macAddr : NULL_MAC_ADDRESS;
|
||||
Ipv6ForwardingRule rule = new Ipv6ForwardingRule(upstreamIfindex,
|
||||
mInterfaceParams.index, (Inet6Address) e.ip, mInterfaceParams.macAddr, dstMac);
|
||||
Ipv6DownstreamRule rule = new Ipv6DownstreamRule(upstreamIfindex, mInterfaceParams.index,
|
||||
(Inet6Address) e.ip, mInterfaceParams.macAddr, dstMac);
|
||||
if (e.isValid()) {
|
||||
addIpv6ForwardingRule(rule);
|
||||
addIpv6DownstreamRule(rule);
|
||||
} else {
|
||||
removeIpv6ForwardingRule(rule);
|
||||
removeIpv6DownstreamRule(rule);
|
||||
}
|
||||
}
|
||||
|
||||
// TODO: consider moving into BpfCoordinator.
|
||||
private void updateClientInfoIpv4(NeighborEvent e) {
|
||||
// TODO: Perhaps remove this protection check.
|
||||
// See the related comment in #addIpv6ForwardingRule.
|
||||
// See the related comment in #addIpv6DownstreamRule.
|
||||
if (!mUsingBpfOffload) return;
|
||||
|
||||
if (e == null) return;
|
||||
|
||||
@@ -88,6 +88,8 @@ import java.net.InetAddress;
|
||||
import java.net.NetworkInterface;
|
||||
import java.net.SocketException;
|
||||
import java.net.UnknownHostException;
|
||||
import java.nio.ByteBuffer;
|
||||
import java.nio.ByteOrder;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collection;
|
||||
@@ -235,8 +237,8 @@ public class BpfCoordinator {
|
||||
// rules function without a valid IPv6 downstream interface index even if it may have one
|
||||
// before. IpServer would need to call getInterfaceParams() in the constructor instead of when
|
||||
// startIpv6() is called, and make mInterfaceParams final.
|
||||
private final HashMap<IpServer, LinkedHashMap<Inet6Address, Ipv6ForwardingRule>>
|
||||
mIpv6ForwardingRules = new LinkedHashMap<>();
|
||||
private final HashMap<IpServer, LinkedHashMap<Inet6Address, Ipv6DownstreamRule>>
|
||||
mIpv6DownstreamRules = 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.
|
||||
@@ -499,8 +501,8 @@ public class BpfCoordinator {
|
||||
/**
|
||||
* Stop BPF tethering offload stats polling.
|
||||
* The data limit cleanup and the tether stats maps cleanup are not implemented here.
|
||||
* These cleanups rely on all IpServers calling #tetherOffloadRuleRemove. After the
|
||||
* last rule is removed from the upstream, #tetherOffloadRuleRemove does the cleanup
|
||||
* These cleanups rely on all IpServers calling #removeIpv6DownstreamRule. After the
|
||||
* last rule is removed from the upstream, #removeIpv6DownstreamRule does the cleanup
|
||||
* functionality.
|
||||
* Note that this can be only called on handler thread.
|
||||
*/
|
||||
@@ -589,22 +591,22 @@ public class BpfCoordinator {
|
||||
}
|
||||
|
||||
/**
|
||||
* Add forwarding rule. After adding the first rule on a given upstream, must add the data
|
||||
* Add IPv6 downstream 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.
|
||||
*/
|
||||
public void tetherOffloadRuleAdd(
|
||||
@NonNull final IpServer ipServer, @NonNull final Ipv6ForwardingRule rule) {
|
||||
public void addIpv6DownstreamRule(
|
||||
@NonNull final IpServer ipServer, @NonNull final Ipv6DownstreamRule rule) {
|
||||
if (!isUsingBpf()) return;
|
||||
|
||||
// TODO: Perhaps avoid to add a duplicate rule.
|
||||
if (!mBpfCoordinatorShim.tetherOffloadRuleAdd(rule)) return;
|
||||
if (!mBpfCoordinatorShim.addIpv6DownstreamRule(rule)) return;
|
||||
|
||||
if (!mIpv6ForwardingRules.containsKey(ipServer)) {
|
||||
mIpv6ForwardingRules.put(ipServer, new LinkedHashMap<Inet6Address,
|
||||
Ipv6ForwardingRule>());
|
||||
if (!mIpv6DownstreamRules.containsKey(ipServer)) {
|
||||
mIpv6DownstreamRules.put(ipServer, new LinkedHashMap<Inet6Address,
|
||||
Ipv6DownstreamRule>());
|
||||
}
|
||||
LinkedHashMap<Inet6Address, Ipv6ForwardingRule> rules = mIpv6ForwardingRules.get(ipServer);
|
||||
LinkedHashMap<Inet6Address, Ipv6DownstreamRule> rules = mIpv6DownstreamRules.get(ipServer);
|
||||
|
||||
// Add upstream and downstream interface index to dev map.
|
||||
maybeAddDevMap(rule.upstreamIfindex, rule.downstreamIfindex);
|
||||
@@ -613,15 +615,13 @@ public class BpfCoordinator {
|
||||
maybeSetLimit(rule.upstreamIfindex);
|
||||
|
||||
if (!isAnyRuleFromDownstreamToUpstream(rule.downstreamIfindex, rule.upstreamIfindex)) {
|
||||
final int downstream = rule.downstreamIfindex;
|
||||
final int upstream = rule.upstreamIfindex;
|
||||
// TODO: support upstream forwarding on non-point-to-point interfaces.
|
||||
// TODO: get the MTU from LinkProperties and update the rules when it changes.
|
||||
if (!mBpfCoordinatorShim.startUpstreamIpv6Forwarding(downstream, upstream,
|
||||
IPV6_ZERO_PREFIX64, rule.srcMac, NULL_MAC_ADDRESS, NULL_MAC_ADDRESS,
|
||||
NetworkStackConstants.ETHER_MTU)) {
|
||||
mLog.e("Failed to enable upstream IPv6 forwarding from "
|
||||
+ getIfName(downstream) + " to " + getIfName(upstream));
|
||||
Ipv6UpstreamRule upstreamRule = new Ipv6UpstreamRule(rule.upstreamIfindex,
|
||||
rule.downstreamIfindex, IPV6_ZERO_PREFIX64, rule.srcMac, NULL_MAC_ADDRESS,
|
||||
NULL_MAC_ADDRESS);
|
||||
if (!mBpfCoordinatorShim.addIpv6UpstreamRule(upstreamRule)) {
|
||||
mLog.e("Failed to add upstream IPv6 forwarding rule: " + upstreamRule);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -631,17 +631,17 @@ public class BpfCoordinator {
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove forwarding rule. After removing the last rule on a given upstream, must clear
|
||||
* Remove IPv6 downstream rule. After removing the last rule on a given upstream, must clear
|
||||
* data limit, update the last tether stats and remove the tether stats in the BPF maps.
|
||||
* Note that this can be only called on handler thread.
|
||||
*/
|
||||
public void tetherOffloadRuleRemove(
|
||||
@NonNull final IpServer ipServer, @NonNull final Ipv6ForwardingRule rule) {
|
||||
public void removeIpv6DownstreamRule(
|
||||
@NonNull final IpServer ipServer, @NonNull final Ipv6DownstreamRule rule) {
|
||||
if (!isUsingBpf()) return;
|
||||
|
||||
if (!mBpfCoordinatorShim.tetherOffloadRuleRemove(rule)) return;
|
||||
if (!mBpfCoordinatorShim.removeIpv6DownstreamRule(rule)) return;
|
||||
|
||||
LinkedHashMap<Inet6Address, Ipv6ForwardingRule> rules = mIpv6ForwardingRules.get(ipServer);
|
||||
LinkedHashMap<Inet6Address, Ipv6DownstreamRule> rules = mIpv6DownstreamRules.get(ipServer);
|
||||
if (rules == null) return;
|
||||
|
||||
// Must remove rules before calling #isAnyRuleOnUpstream because it needs to check if
|
||||
@@ -652,17 +652,16 @@ public class BpfCoordinator {
|
||||
|
||||
// Remove the downstream entry if it has no more rule.
|
||||
if (rules.isEmpty()) {
|
||||
mIpv6ForwardingRules.remove(ipServer);
|
||||
mIpv6DownstreamRules.remove(ipServer);
|
||||
}
|
||||
|
||||
// If no more rules between this upstream and downstream, stop upstream forwarding.
|
||||
if (!isAnyRuleFromDownstreamToUpstream(rule.downstreamIfindex, rule.upstreamIfindex)) {
|
||||
final int downstream = rule.downstreamIfindex;
|
||||
final int upstream = rule.upstreamIfindex;
|
||||
if (!mBpfCoordinatorShim.stopUpstreamIpv6Forwarding(downstream, upstream,
|
||||
IPV6_ZERO_PREFIX64, rule.srcMac)) {
|
||||
mLog.e("Failed to disable upstream IPv6 forwarding from "
|
||||
+ getIfName(downstream) + " to " + getIfName(upstream));
|
||||
Ipv6UpstreamRule upstreamRule = new Ipv6UpstreamRule(rule.upstreamIfindex,
|
||||
rule.downstreamIfindex, IPV6_ZERO_PREFIX64, rule.srcMac, NULL_MAC_ADDRESS,
|
||||
NULL_MAC_ADDRESS);
|
||||
if (!mBpfCoordinatorShim.removeIpv6UpstreamRule(upstreamRule)) {
|
||||
mLog.e("Failed to remove upstream IPv6 forwarding rule: " + upstreamRule);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -678,13 +677,13 @@ public class BpfCoordinator {
|
||||
public void tetherOffloadRuleClear(@NonNull final IpServer ipServer) {
|
||||
if (!isUsingBpf()) return;
|
||||
|
||||
final LinkedHashMap<Inet6Address, Ipv6ForwardingRule> rules = mIpv6ForwardingRules.get(
|
||||
ipServer);
|
||||
final LinkedHashMap<Inet6Address, Ipv6DownstreamRule> rules =
|
||||
mIpv6DownstreamRules.get(ipServer);
|
||||
if (rules == null) return;
|
||||
|
||||
// Need to build a rule list because the rule map may be changed in the iteration.
|
||||
for (final Ipv6ForwardingRule rule : new ArrayList<Ipv6ForwardingRule>(rules.values())) {
|
||||
tetherOffloadRuleRemove(ipServer, rule);
|
||||
for (final Ipv6DownstreamRule rule : new ArrayList<Ipv6DownstreamRule>(rules.values())) {
|
||||
removeIpv6DownstreamRule(ipServer, rule);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -695,28 +694,28 @@ public class BpfCoordinator {
|
||||
public void tetherOffloadRuleUpdate(@NonNull final IpServer ipServer, int newUpstreamIfindex) {
|
||||
if (!isUsingBpf()) return;
|
||||
|
||||
final LinkedHashMap<Inet6Address, Ipv6ForwardingRule> rules = mIpv6ForwardingRules.get(
|
||||
ipServer);
|
||||
final LinkedHashMap<Inet6Address, Ipv6DownstreamRule> rules =
|
||||
mIpv6DownstreamRules.get(ipServer);
|
||||
if (rules == null) return;
|
||||
|
||||
// Need to build a rule list because the rule map may be changed in the iteration.
|
||||
// First remove all the old rules, then add all the new rules. This is because the upstream
|
||||
// forwarding code in tetherOffloadRuleAdd cannot support rules on two upstreams at the
|
||||
// forwarding code in addIpv6DownstreamRule cannot support rules on two upstreams at the
|
||||
// same time. Deleting the rules first ensures that upstream forwarding is disabled on the
|
||||
// old upstream when the last rule is removed from it, and re-enabled on the new upstream
|
||||
// when the first rule is added to it.
|
||||
// TODO: Once the IPv6 client processing code has moved from IpServer to BpfCoordinator, do
|
||||
// something smarter.
|
||||
final ArrayList<Ipv6ForwardingRule> rulesCopy = new ArrayList<>(rules.values());
|
||||
for (final Ipv6ForwardingRule rule : rulesCopy) {
|
||||
final ArrayList<Ipv6DownstreamRule> rulesCopy = new ArrayList<>(rules.values());
|
||||
for (final Ipv6DownstreamRule rule : rulesCopy) {
|
||||
// Remove the old rule before adding the new one because the map uses the same key for
|
||||
// both rules. Reversing the processing order causes that the new rule is removed as
|
||||
// unexpected.
|
||||
// TODO: Add new rule first to reduce the latency which has no rule.
|
||||
tetherOffloadRuleRemove(ipServer, rule);
|
||||
removeIpv6DownstreamRule(ipServer, rule);
|
||||
}
|
||||
for (final Ipv6ForwardingRule rule : rulesCopy) {
|
||||
tetherOffloadRuleAdd(ipServer, rule.onNewUpstream(newUpstreamIfindex));
|
||||
for (final Ipv6DownstreamRule rule : rulesCopy) {
|
||||
addIpv6DownstreamRule(ipServer, rule.onNewUpstream(newUpstreamIfindex));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1142,14 +1141,14 @@ public class BpfCoordinator {
|
||||
private void dumpIpv6ForwardingRulesByDownstream(@NonNull IndentingPrintWriter pw) {
|
||||
pw.println("IPv6 Forwarding rules by downstream interface:");
|
||||
pw.increaseIndent();
|
||||
if (mIpv6ForwardingRules.size() == 0) {
|
||||
pw.println("No IPv6 rules");
|
||||
if (mIpv6DownstreamRules.size() == 0) {
|
||||
pw.println("No downstream IPv6 rules");
|
||||
pw.decreaseIndent();
|
||||
return;
|
||||
}
|
||||
|
||||
for (Map.Entry<IpServer, LinkedHashMap<Inet6Address, Ipv6ForwardingRule>> entry :
|
||||
mIpv6ForwardingRules.entrySet()) {
|
||||
for (Map.Entry<IpServer, LinkedHashMap<Inet6Address, Ipv6DownstreamRule>> entry :
|
||||
mIpv6DownstreamRules.entrySet()) {
|
||||
IpServer ipServer = entry.getKey();
|
||||
// The rule downstream interface index is paired with the interface name from
|
||||
// IpServer#interfaceName. See #startIPv6, #updateIpv6ForwardingRules in IpServer.
|
||||
@@ -1158,8 +1157,8 @@ public class BpfCoordinator {
|
||||
+ "[srcmac] [dstmac]");
|
||||
|
||||
pw.increaseIndent();
|
||||
LinkedHashMap<Inet6Address, Ipv6ForwardingRule> rules = entry.getValue();
|
||||
for (Ipv6ForwardingRule rule : rules.values()) {
|
||||
LinkedHashMap<Inet6Address, Ipv6DownstreamRule> rules = entry.getValue();
|
||||
for (Ipv6DownstreamRule rule : rules.values()) {
|
||||
final int upstreamIfindex = rule.upstreamIfindex;
|
||||
pw.println(String.format("%d(%s) %d(%s) %s [%s] [%s]", upstreamIfindex,
|
||||
getIfName(upstreamIfindex), rule.downstreamIfindex,
|
||||
@@ -1406,13 +1405,13 @@ public class BpfCoordinator {
|
||||
pw.decreaseIndent();
|
||||
}
|
||||
|
||||
/** IPv6 forwarding rule class. */
|
||||
public static class Ipv6ForwardingRule {
|
||||
// The upstream6 and downstream6 rules are built as the following tables. Only raw ip
|
||||
// upstream interface is supported.
|
||||
/** IPv6 upstream forwarding rule class. */
|
||||
public static class Ipv6UpstreamRule {
|
||||
// The upstream6 rules are built as the following tables. Only raw ip upstream interface is
|
||||
// supported.
|
||||
// TODO: support ether ip upstream interface.
|
||||
//
|
||||
// NAT network topology:
|
||||
// Tethering network topology:
|
||||
//
|
||||
// public network (rawip) private network
|
||||
// | UE |
|
||||
@@ -1422,15 +1421,15 @@ public class BpfCoordinator {
|
||||
//
|
||||
// upstream6 key and value:
|
||||
//
|
||||
// +------+-------------+
|
||||
// +------+-------------------+
|
||||
// | TetherUpstream6Key |
|
||||
// +------+------+------+
|
||||
// |field |iif |dstMac|
|
||||
// | | | |
|
||||
// +------+------+------+
|
||||
// |value |downst|downst|
|
||||
// | |ream |ream |
|
||||
// +------+------+------+
|
||||
// +------+------+------+-----+
|
||||
// |field |iif |dstMac|src64|
|
||||
// | | | | |
|
||||
// +------+------+------+-----+
|
||||
// |value |downst|downst|upstr|
|
||||
// | |ream |ream |eam |
|
||||
// +------+------+------+-----+
|
||||
//
|
||||
// +------+----------------------------------+
|
||||
// | |Tether6Value |
|
||||
@@ -1442,6 +1441,92 @@ public class BpfCoordinator {
|
||||
// | |am | | |IP | |
|
||||
// +------+------+------+------+------+------+
|
||||
//
|
||||
public final int upstreamIfindex;
|
||||
public final int downstreamIfindex;
|
||||
@NonNull
|
||||
public final IpPrefix sourcePrefix;
|
||||
@NonNull
|
||||
public final MacAddress inDstMac;
|
||||
@NonNull
|
||||
public final MacAddress outSrcMac;
|
||||
@NonNull
|
||||
public final MacAddress outDstMac;
|
||||
|
||||
public Ipv6UpstreamRule(int upstreamIfindex, int downstreamIfindex,
|
||||
@NonNull IpPrefix sourcePrefix, @NonNull MacAddress inDstMac,
|
||||
@NonNull MacAddress outSrcMac, @NonNull MacAddress outDstMac) {
|
||||
this.upstreamIfindex = upstreamIfindex;
|
||||
this.downstreamIfindex = downstreamIfindex;
|
||||
this.sourcePrefix = sourcePrefix;
|
||||
this.inDstMac = inDstMac;
|
||||
this.outSrcMac = outSrcMac;
|
||||
this.outDstMac = outDstMac;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return a TetherUpstream6Key object built from the rule.
|
||||
*/
|
||||
@NonNull
|
||||
public TetherUpstream6Key makeTetherUpstream6Key() {
|
||||
byte[] prefixBytes = Arrays.copyOf(sourcePrefix.getRawAddress(), 8);
|
||||
long prefix64 = ByteBuffer.wrap(prefixBytes).order(ByteOrder.BIG_ENDIAN).getLong();
|
||||
return new TetherUpstream6Key(downstreamIfindex, inDstMac, prefix64);
|
||||
}
|
||||
|
||||
/**
|
||||
* Return a Tether6Value object built from the rule.
|
||||
*/
|
||||
@NonNull
|
||||
public Tether6Value makeTether6Value() {
|
||||
return new Tether6Value(upstreamIfindex, outDstMac, outSrcMac, ETH_P_IPV6,
|
||||
NetworkStackConstants.ETHER_MTU);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object o) {
|
||||
if (!(o instanceof Ipv6UpstreamRule)) return false;
|
||||
Ipv6UpstreamRule that = (Ipv6UpstreamRule) o;
|
||||
return this.upstreamIfindex == that.upstreamIfindex
|
||||
&& this.downstreamIfindex == that.downstreamIfindex
|
||||
&& Objects.equals(this.sourcePrefix, that.sourcePrefix)
|
||||
&& Objects.equals(this.inDstMac, that.inDstMac)
|
||||
&& Objects.equals(this.outSrcMac, that.outSrcMac)
|
||||
&& Objects.equals(this.outDstMac, that.outDstMac);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
// TODO: if this is ever used in production code, don't pass ifindices
|
||||
// to Objects.hash() to avoid autoboxing overhead.
|
||||
return Objects.hash(upstreamIfindex, downstreamIfindex, sourcePrefix, inDstMac,
|
||||
outSrcMac, outDstMac);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "upstreamIfindex: " + upstreamIfindex
|
||||
+ ", downstreamIfindex: " + downstreamIfindex
|
||||
+ ", sourcePrefix: " + sourcePrefix
|
||||
+ ", inDstMac: " + inDstMac
|
||||
+ ", outSrcMac: " + outSrcMac
|
||||
+ ", outDstMac: " + outDstMac;
|
||||
}
|
||||
}
|
||||
|
||||
/** IPv6 downstream forwarding rule class. */
|
||||
public static class Ipv6DownstreamRule {
|
||||
// The downstream6 rules are built as the following tables. Only raw ip upstream interface
|
||||
// is supported.
|
||||
// TODO: support ether ip upstream interface.
|
||||
//
|
||||
// Tethering network topology:
|
||||
//
|
||||
// public network (rawip) private network
|
||||
// | UE |
|
||||
// +------------+ V +------------+------------+ V +------------+
|
||||
// | Sever +---------+ Upstream | Downstream +---------+ Client |
|
||||
// +------------+ +------------+------------+ +------------+
|
||||
//
|
||||
// downstream6 key and value:
|
||||
//
|
||||
// +------+--------------------+
|
||||
@@ -1475,11 +1560,11 @@ public class BpfCoordinator {
|
||||
@NonNull
|
||||
public final MacAddress dstMac;
|
||||
|
||||
public Ipv6ForwardingRule(int upstreamIfindex, int downstreamIfIndex,
|
||||
public Ipv6DownstreamRule(int upstreamIfindex, int downstreamIfindex,
|
||||
@NonNull Inet6Address address, @NonNull MacAddress srcMac,
|
||||
@NonNull MacAddress dstMac) {
|
||||
this.upstreamIfindex = upstreamIfindex;
|
||||
this.downstreamIfindex = downstreamIfIndex;
|
||||
this.downstreamIfindex = downstreamIfindex;
|
||||
this.address = address;
|
||||
this.srcMac = srcMac;
|
||||
this.dstMac = dstMac;
|
||||
@@ -1487,8 +1572,8 @@ public class BpfCoordinator {
|
||||
|
||||
/** Return a new rule object which updates with new upstream index. */
|
||||
@NonNull
|
||||
public Ipv6ForwardingRule onNewUpstream(int newUpstreamIfindex) {
|
||||
return new Ipv6ForwardingRule(newUpstreamIfindex, downstreamIfindex, address, srcMac,
|
||||
public Ipv6DownstreamRule onNewUpstream(int newUpstreamIfindex) {
|
||||
return new Ipv6DownstreamRule(newUpstreamIfindex, downstreamIfindex, address, srcMac,
|
||||
dstMac);
|
||||
}
|
||||
|
||||
@@ -1528,8 +1613,8 @@ public class BpfCoordinator {
|
||||
|
||||
@Override
|
||||
public boolean equals(Object o) {
|
||||
if (!(o instanceof Ipv6ForwardingRule)) return false;
|
||||
Ipv6ForwardingRule that = (Ipv6ForwardingRule) o;
|
||||
if (!(o instanceof Ipv6DownstreamRule)) return false;
|
||||
Ipv6DownstreamRule that = (Ipv6DownstreamRule) o;
|
||||
return this.upstreamIfindex == that.upstreamIfindex
|
||||
&& this.downstreamIfindex == that.downstreamIfindex
|
||||
&& Objects.equals(this.address, that.address)
|
||||
@@ -1870,9 +1955,9 @@ public class BpfCoordinator {
|
||||
}
|
||||
|
||||
private int getInterfaceIndexFromRules(@NonNull String ifName) {
|
||||
for (LinkedHashMap<Inet6Address, Ipv6ForwardingRule> rules : mIpv6ForwardingRules
|
||||
.values()) {
|
||||
for (Ipv6ForwardingRule rule : rules.values()) {
|
||||
for (LinkedHashMap<Inet6Address, Ipv6DownstreamRule> rules :
|
||||
mIpv6DownstreamRules.values()) {
|
||||
for (Ipv6DownstreamRule rule : rules.values()) {
|
||||
final int upstreamIfindex = rule.upstreamIfindex;
|
||||
if (TextUtils.equals(ifName, mInterfaceNames.get(upstreamIfindex))) {
|
||||
return upstreamIfindex;
|
||||
@@ -1963,9 +2048,9 @@ public class BpfCoordinator {
|
||||
// TODO: Rename to isAnyIpv6RuleOnUpstream and define an isAnyRuleOnUpstream method that called
|
||||
// both isAnyIpv6RuleOnUpstream and mBpfCoordinatorShim.isAnyIpv4RuleOnUpstream.
|
||||
private boolean isAnyRuleOnUpstream(int upstreamIfindex) {
|
||||
for (LinkedHashMap<Inet6Address, Ipv6ForwardingRule> rules : mIpv6ForwardingRules
|
||||
.values()) {
|
||||
for (Ipv6ForwardingRule rule : rules.values()) {
|
||||
for (LinkedHashMap<Inet6Address, Ipv6DownstreamRule> rules :
|
||||
mIpv6DownstreamRules.values()) {
|
||||
for (Ipv6DownstreamRule rule : rules.values()) {
|
||||
if (upstreamIfindex == rule.upstreamIfindex) return true;
|
||||
}
|
||||
}
|
||||
@@ -1973,9 +2058,9 @@ public class BpfCoordinator {
|
||||
}
|
||||
|
||||
private boolean isAnyRuleFromDownstreamToUpstream(int downstreamIfindex, int upstreamIfindex) {
|
||||
for (LinkedHashMap<Inet6Address, Ipv6ForwardingRule> rules : mIpv6ForwardingRules
|
||||
.values()) {
|
||||
for (Ipv6ForwardingRule rule : rules.values()) {
|
||||
for (LinkedHashMap<Inet6Address, Ipv6DownstreamRule> rules :
|
||||
mIpv6DownstreamRules.values()) {
|
||||
for (Ipv6DownstreamRule rule : rules.values()) {
|
||||
if (downstreamIfindex == rule.downstreamIfindex
|
||||
&& upstreamIfindex == rule.upstreamIfindex) {
|
||||
return true;
|
||||
@@ -2226,13 +2311,13 @@ public class BpfCoordinator {
|
||||
CONNTRACK_TIMEOUT_UPDATE_INTERVAL_MS);
|
||||
}
|
||||
|
||||
// Return forwarding rule map. This is used for testing only.
|
||||
// Return IPv6 downstream forwarding rule map. This is used for testing only.
|
||||
// Note that this can be only called on handler thread.
|
||||
@NonNull
|
||||
@VisibleForTesting
|
||||
final HashMap<IpServer, LinkedHashMap<Inet6Address, Ipv6ForwardingRule>>
|
||||
getForwardingRulesForTesting() {
|
||||
return mIpv6ForwardingRules;
|
||||
final HashMap<IpServer, LinkedHashMap<Inet6Address, Ipv6DownstreamRule>>
|
||||
getIpv6DownstreamRulesForTesting() {
|
||||
return mIpv6DownstreamRules;
|
||||
}
|
||||
|
||||
// Return upstream interface name map. This is used for testing only.
|
||||
|
||||
@@ -114,7 +114,7 @@ import com.android.net.module.util.ip.IpNeighborMonitor.NeighborEvent;
|
||||
import com.android.net.module.util.ip.IpNeighborMonitor.NeighborEventConsumer;
|
||||
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.Ipv6DownstreamRule;
|
||||
import com.android.networkstack.tethering.PrivateAddressCoordinator;
|
||||
import com.android.networkstack.tethering.Tether6Value;
|
||||
import com.android.networkstack.tethering.TetherDevKey;
|
||||
@@ -899,9 +899,9 @@ public class IpServerTest {
|
||||
}
|
||||
|
||||
@NonNull
|
||||
private static Ipv6ForwardingRule makeForwardingRule(
|
||||
int upstreamIfindex, @NonNull InetAddress dst, @NonNull MacAddress dstMac) {
|
||||
return new Ipv6ForwardingRule(upstreamIfindex, TEST_IFACE_PARAMS.index,
|
||||
private static Ipv6DownstreamRule makeDownstreamRule(int upstreamIfindex,
|
||||
@NonNull InetAddress dst, @NonNull MacAddress dstMac) {
|
||||
return new Ipv6DownstreamRule(upstreamIfindex, TEST_IFACE_PARAMS.index,
|
||||
(Inet6Address) dst, TEST_IFACE_PARAMS.macAddr, dstMac);
|
||||
}
|
||||
|
||||
@@ -1064,16 +1064,16 @@ public class IpServerTest {
|
||||
|
||||
// Events on this interface are received and sent to netd.
|
||||
recvNewNeigh(myIfindex, neighA, NUD_REACHABLE, macA);
|
||||
verify(mBpfCoordinator).tetherOffloadRuleAdd(
|
||||
mIpServer, makeForwardingRule(UPSTREAM_IFINDEX, neighA, macA));
|
||||
verify(mBpfCoordinator).addIpv6DownstreamRule(
|
||||
mIpServer, makeDownstreamRule(UPSTREAM_IFINDEX, neighA, macA));
|
||||
verifyTetherOffloadRuleAdd(null,
|
||||
UPSTREAM_IFINDEX, UPSTREAM_IFACE_PARAMS.macAddr, neighA, macA);
|
||||
verifyStartUpstreamIpv6Forwarding(null, UPSTREAM_IFINDEX);
|
||||
resetNetdBpfMapAndCoordinator();
|
||||
|
||||
recvNewNeigh(myIfindex, neighB, NUD_REACHABLE, macB);
|
||||
verify(mBpfCoordinator).tetherOffloadRuleAdd(
|
||||
mIpServer, makeForwardingRule(UPSTREAM_IFINDEX, neighB, macB));
|
||||
verify(mBpfCoordinator).addIpv6DownstreamRule(
|
||||
mIpServer, makeDownstreamRule(UPSTREAM_IFINDEX, neighB, macB));
|
||||
verifyTetherOffloadRuleAdd(null,
|
||||
UPSTREAM_IFINDEX, UPSTREAM_IFACE_PARAMS.macAddr, neighB, macB);
|
||||
verifyNoUpstreamIpv6ForwardingChange(null);
|
||||
@@ -1088,8 +1088,8 @@ public class IpServerTest {
|
||||
// A neighbor that is no longer valid causes the rule to be removed.
|
||||
// NUD_FAILED events do not have a MAC address.
|
||||
recvNewNeigh(myIfindex, neighA, NUD_FAILED, null);
|
||||
verify(mBpfCoordinator).tetherOffloadRuleRemove(
|
||||
mIpServer, makeForwardingRule(UPSTREAM_IFINDEX, neighA, macNull));
|
||||
verify(mBpfCoordinator).removeIpv6DownstreamRule(
|
||||
mIpServer, makeDownstreamRule(UPSTREAM_IFINDEX, neighA, macNull));
|
||||
verifyTetherOffloadRuleRemove(null,
|
||||
UPSTREAM_IFINDEX, UPSTREAM_IFACE_PARAMS.macAddr, neighA, macNull);
|
||||
verifyNoUpstreamIpv6ForwardingChange(null);
|
||||
@@ -1097,8 +1097,8 @@ public class IpServerTest {
|
||||
|
||||
// A neighbor that is deleted causes the rule to be removed.
|
||||
recvDelNeigh(myIfindex, neighB, NUD_STALE, macB);
|
||||
verify(mBpfCoordinator).tetherOffloadRuleRemove(
|
||||
mIpServer, makeForwardingRule(UPSTREAM_IFINDEX, neighB, macNull));
|
||||
verify(mBpfCoordinator).removeIpv6DownstreamRule(
|
||||
mIpServer, makeDownstreamRule(UPSTREAM_IFINDEX, neighB, macNull));
|
||||
verifyTetherOffloadRuleRemove(null,
|
||||
UPSTREAM_IFINDEX, UPSTREAM_IFACE_PARAMS.macAddr, neighB, macNull);
|
||||
verifyStopUpstreamIpv6Forwarding(null);
|
||||
@@ -1155,13 +1155,13 @@ public class IpServerTest {
|
||||
lp.setInterfaceName(UPSTREAM_IFACE);
|
||||
dispatchTetherConnectionChanged(UPSTREAM_IFACE, lp, -1);
|
||||
recvNewNeigh(myIfindex, neighB, NUD_REACHABLE, macB);
|
||||
verify(mBpfCoordinator).tetherOffloadRuleAdd(
|
||||
mIpServer, makeForwardingRule(UPSTREAM_IFINDEX, neighB, macB));
|
||||
verify(mBpfCoordinator).addIpv6DownstreamRule(
|
||||
mIpServer, makeDownstreamRule(UPSTREAM_IFINDEX, neighB, macB));
|
||||
verifyTetherOffloadRuleAdd(null,
|
||||
UPSTREAM_IFINDEX, UPSTREAM_IFACE_PARAMS.macAddr, neighB, macB);
|
||||
verifyStartUpstreamIpv6Forwarding(null, UPSTREAM_IFINDEX);
|
||||
verify(mBpfCoordinator, never()).tetherOffloadRuleAdd(
|
||||
mIpServer, makeForwardingRule(UPSTREAM_IFINDEX, neighA, macA));
|
||||
verify(mBpfCoordinator, never()).addIpv6DownstreamRule(
|
||||
mIpServer, makeDownstreamRule(UPSTREAM_IFINDEX, neighA, macA));
|
||||
verifyNeverTetherOffloadRuleAdd(
|
||||
UPSTREAM_IFINDEX, UPSTREAM_IFACE_PARAMS.macAddr, neighA, macA);
|
||||
|
||||
@@ -1178,13 +1178,13 @@ public class IpServerTest {
|
||||
dispatchTetherConnectionChanged(UPSTREAM_IFACE, lp, -1);
|
||||
recvNewNeigh(myIfindex, neighA, NUD_REACHABLE, macA);
|
||||
recvNewNeigh(myIfindex, neighB, NUD_REACHABLE, macB);
|
||||
verify(mBpfCoordinator).tetherOffloadRuleAdd(
|
||||
mIpServer, makeForwardingRule(UPSTREAM_IFINDEX, neighA, macA));
|
||||
verify(mBpfCoordinator).addIpv6DownstreamRule(
|
||||
mIpServer, makeDownstreamRule(UPSTREAM_IFINDEX, neighA, macA));
|
||||
verifyTetherOffloadRuleAdd(null,
|
||||
UPSTREAM_IFINDEX, UPSTREAM_IFACE_PARAMS.macAddr, neighA, macA);
|
||||
verifyStartUpstreamIpv6Forwarding(null, UPSTREAM_IFINDEX);
|
||||
verify(mBpfCoordinator).tetherOffloadRuleAdd(
|
||||
mIpServer, makeForwardingRule(UPSTREAM_IFINDEX, neighB, macB));
|
||||
verify(mBpfCoordinator).addIpv6DownstreamRule(
|
||||
mIpServer, makeDownstreamRule(UPSTREAM_IFINDEX, neighB, macB));
|
||||
verifyTetherOffloadRuleAdd(null,
|
||||
UPSTREAM_IFINDEX, UPSTREAM_IFACE_PARAMS.macAddr, neighB, macB);
|
||||
resetNetdBpfMapAndCoordinator();
|
||||
@@ -1222,16 +1222,16 @@ public class IpServerTest {
|
||||
resetNetdBpfMapAndCoordinator();
|
||||
|
||||
recvNewNeigh(myIfindex, neigh, NUD_REACHABLE, macA);
|
||||
verify(mBpfCoordinator).tetherOffloadRuleAdd(
|
||||
mIpServer, makeForwardingRule(UPSTREAM_IFINDEX, neigh, macA));
|
||||
verify(mBpfCoordinator).addIpv6DownstreamRule(
|
||||
mIpServer, makeDownstreamRule(UPSTREAM_IFINDEX, neigh, macA));
|
||||
verifyTetherOffloadRuleAdd(null,
|
||||
UPSTREAM_IFINDEX, UPSTREAM_IFACE_PARAMS.macAddr, neigh, macA);
|
||||
verifyStartUpstreamIpv6Forwarding(null, UPSTREAM_IFINDEX);
|
||||
resetNetdBpfMapAndCoordinator();
|
||||
|
||||
recvDelNeigh(myIfindex, neigh, NUD_STALE, macA);
|
||||
verify(mBpfCoordinator).tetherOffloadRuleRemove(
|
||||
mIpServer, makeForwardingRule(UPSTREAM_IFINDEX, neigh, macNull));
|
||||
verify(mBpfCoordinator).removeIpv6DownstreamRule(
|
||||
mIpServer, makeDownstreamRule(UPSTREAM_IFINDEX, neigh, macNull));
|
||||
verifyTetherOffloadRuleRemove(null,
|
||||
UPSTREAM_IFINDEX, UPSTREAM_IFACE_PARAMS.macAddr, neigh, macNull);
|
||||
verifyStopUpstreamIpv6Forwarding(null);
|
||||
@@ -1244,13 +1244,13 @@ public class IpServerTest {
|
||||
resetNetdBpfMapAndCoordinator();
|
||||
|
||||
recvNewNeigh(myIfindex, neigh, NUD_REACHABLE, macA);
|
||||
verify(mBpfCoordinator, never()).tetherOffloadRuleAdd(any(), any());
|
||||
verify(mBpfCoordinator, never()).addIpv6DownstreamRule(any(), any());
|
||||
verifyNeverTetherOffloadRuleAdd();
|
||||
verifyNoUpstreamIpv6ForwardingChange(null);
|
||||
resetNetdBpfMapAndCoordinator();
|
||||
|
||||
recvDelNeigh(myIfindex, neigh, NUD_STALE, macA);
|
||||
verify(mBpfCoordinator, never()).tetherOffloadRuleRemove(any(), any());
|
||||
verify(mBpfCoordinator, never()).removeIpv6DownstreamRule(any(), any());
|
||||
verifyNeverTetherOffloadRuleRemove();
|
||||
verifyNoUpstreamIpv6ForwardingChange(null);
|
||||
resetNetdBpfMapAndCoordinator();
|
||||
@@ -1534,8 +1534,8 @@ public class IpServerTest {
|
||||
final InetAddress neigh = InetAddresses.parseNumericAddress("2001:db8::1");
|
||||
final MacAddress mac = MacAddress.fromString("00:00:00:00:00:0a");
|
||||
recvNewNeigh(myIfindex, neigh, NUD_REACHABLE, mac);
|
||||
verify(mBpfCoordinator, never()).tetherOffloadRuleAdd(
|
||||
mIpServer, makeForwardingRule(IPSEC_IFINDEX, neigh, mac));
|
||||
verify(mBpfCoordinator, never()).addIpv6DownstreamRule(
|
||||
mIpServer, makeDownstreamRule(IPSEC_IFINDEX, neigh, mac));
|
||||
}
|
||||
|
||||
// TODO: move to BpfCoordinatorTest once IpNeighborMonitor is migrated to BpfCoordinator.
|
||||
|
||||
@@ -118,7 +118,8 @@ import com.android.net.module.util.netlink.NetlinkConstants;
|
||||
import com.android.net.module.util.netlink.NetlinkUtils;
|
||||
import com.android.networkstack.tethering.BpfCoordinator.BpfConntrackEventConsumer;
|
||||
import com.android.networkstack.tethering.BpfCoordinator.ClientInfo;
|
||||
import com.android.networkstack.tethering.BpfCoordinator.Ipv6ForwardingRule;
|
||||
import com.android.networkstack.tethering.BpfCoordinator.Ipv6DownstreamRule;
|
||||
import com.android.networkstack.tethering.BpfCoordinator.Ipv6UpstreamRule;
|
||||
import com.android.testutils.DevSdkIgnoreRule;
|
||||
import com.android.testutils.DevSdkIgnoreRule.IgnoreAfter;
|
||||
import com.android.testutils.DevSdkIgnoreRule.IgnoreUpTo;
|
||||
@@ -192,6 +193,7 @@ public class BpfCoordinatorTest {
|
||||
private static final Inet4Address XLAT_LOCAL_IPV4ADDR =
|
||||
(Inet4Address) InetAddresses.parseNumericAddress("192.0.0.46");
|
||||
private static final IpPrefix NAT64_IP_PREFIX = new IpPrefix("64:ff9b::/96");
|
||||
private static final IpPrefix IPV6_ZERO_PREFIX = new IpPrefix("::/64");
|
||||
|
||||
// Generally, public port and private port are the same in the NAT conntrack message.
|
||||
// TODO: consider using different private port and public port for testing.
|
||||
@@ -669,8 +671,8 @@ public class BpfCoordinatorTest {
|
||||
}
|
||||
}
|
||||
|
||||
private void verifyTetherOffloadRuleAdd(@Nullable InOrder inOrder,
|
||||
@NonNull Ipv6ForwardingRule rule) throws Exception {
|
||||
private void verifyAddDownstreamRule(@Nullable InOrder inOrder,
|
||||
@NonNull Ipv6DownstreamRule rule) throws Exception {
|
||||
if (mDeps.isAtLeastS()) {
|
||||
verifyWithOrder(inOrder, mBpfDownstream6Map).updateEntry(
|
||||
rule.makeTetherDownstream6Key(), rule.makeTether6Value());
|
||||
@@ -679,7 +681,7 @@ public class BpfCoordinatorTest {
|
||||
}
|
||||
}
|
||||
|
||||
private void verifyNeverTetherOffloadRuleAdd() throws Exception {
|
||||
private void verifyNeverAddDownstreamRule() throws Exception {
|
||||
if (mDeps.isAtLeastS()) {
|
||||
verify(mBpfDownstream6Map, never()).updateEntry(any(), any());
|
||||
} else {
|
||||
@@ -687,8 +689,8 @@ public class BpfCoordinatorTest {
|
||||
}
|
||||
}
|
||||
|
||||
private void verifyTetherOffloadRuleRemove(@Nullable InOrder inOrder,
|
||||
@NonNull final Ipv6ForwardingRule rule) throws Exception {
|
||||
private void verifyRemoveDownstreamRule(@Nullable InOrder inOrder,
|
||||
@NonNull final Ipv6DownstreamRule rule) throws Exception {
|
||||
if (mDeps.isAtLeastS()) {
|
||||
verifyWithOrder(inOrder, mBpfDownstream6Map).deleteEntry(
|
||||
rule.makeTetherDownstream6Key());
|
||||
@@ -697,7 +699,7 @@ public class BpfCoordinatorTest {
|
||||
}
|
||||
}
|
||||
|
||||
private void verifyNeverTetherOffloadRuleRemove() throws Exception {
|
||||
private void verifyNeverRemoveDownstreamRule() throws Exception {
|
||||
if (mDeps.isAtLeastS()) {
|
||||
verify(mBpfDownstream6Map, never()).deleteEntry(any());
|
||||
} else {
|
||||
@@ -768,17 +770,17 @@ public class BpfCoordinatorTest {
|
||||
// The #verifyTetherOffloadGetAndClearStats can't distinguish who has ever called
|
||||
// mBpfStatsMap#getValue and get a wrong calling count which counts all.
|
||||
final InOrder inOrder = inOrder(mNetd, mBpfDownstream6Map, mBpfLimitMap, mBpfStatsMap);
|
||||
final Ipv6ForwardingRule rule = buildTestForwardingRule(mobileIfIndex, NEIGH_A, MAC_A);
|
||||
coordinator.tetherOffloadRuleAdd(mIpServer, rule);
|
||||
verifyTetherOffloadRuleAdd(inOrder, rule);
|
||||
final Ipv6DownstreamRule rule = buildTestDownstreamRule(mobileIfIndex, NEIGH_A, MAC_A);
|
||||
coordinator.addIpv6DownstreamRule(mIpServer, rule);
|
||||
verifyAddDownstreamRule(inOrder, rule);
|
||||
verifyTetherOffloadSetInterfaceQuota(inOrder, mobileIfIndex, QUOTA_UNLIMITED,
|
||||
true /* isInit */);
|
||||
|
||||
// Removing the last rule on current upstream immediately sends the cleanup stuff to netd.
|
||||
updateStatsEntryForTetherOffloadGetAndClearStats(
|
||||
buildTestTetherStatsParcel(mobileIfIndex, 0, 0, 0, 0));
|
||||
coordinator.tetherOffloadRuleRemove(mIpServer, rule);
|
||||
verifyTetherOffloadRuleRemove(inOrder, rule);
|
||||
coordinator.removeIpv6DownstreamRule(mIpServer, rule);
|
||||
verifyRemoveDownstreamRule(inOrder, rule);
|
||||
verifyTetherOffloadGetAndClearStats(inOrder, mobileIfIndex);
|
||||
}
|
||||
|
||||
@@ -947,7 +949,7 @@ public class BpfCoordinatorTest {
|
||||
public final MacAddress srcMac;
|
||||
public final MacAddress dstMac;
|
||||
|
||||
TetherOffloadRuleParcelMatcher(@NonNull Ipv6ForwardingRule rule) {
|
||||
TetherOffloadRuleParcelMatcher(@NonNull Ipv6DownstreamRule rule) {
|
||||
upstreamIfindex = rule.upstreamIfindex;
|
||||
downstreamIfindex = rule.downstreamIfindex;
|
||||
address = rule.address;
|
||||
@@ -971,21 +973,28 @@ public class BpfCoordinatorTest {
|
||||
}
|
||||
|
||||
@NonNull
|
||||
private TetherOffloadRuleParcel matches(@NonNull Ipv6ForwardingRule rule) {
|
||||
private TetherOffloadRuleParcel matches(@NonNull Ipv6DownstreamRule rule) {
|
||||
return argThat(new TetherOffloadRuleParcelMatcher(rule));
|
||||
}
|
||||
|
||||
@NonNull
|
||||
private static Ipv6ForwardingRule buildTestForwardingRule(
|
||||
private static Ipv6UpstreamRule buildTestUpstreamRule(int upstreamIfindex) {
|
||||
return new Ipv6UpstreamRule(upstreamIfindex, DOWNSTREAM_IFINDEX,
|
||||
IPV6_ZERO_PREFIX, DOWNSTREAM_MAC, MacAddress.ALL_ZEROS_ADDRESS,
|
||||
MacAddress.ALL_ZEROS_ADDRESS);
|
||||
}
|
||||
|
||||
@NonNull
|
||||
private static Ipv6DownstreamRule buildTestDownstreamRule(
|
||||
int upstreamIfindex, @NonNull InetAddress address, @NonNull MacAddress dstMac) {
|
||||
return new Ipv6ForwardingRule(upstreamIfindex, DOWNSTREAM_IFINDEX, (Inet6Address) address,
|
||||
DOWNSTREAM_MAC, dstMac);
|
||||
return new Ipv6DownstreamRule(upstreamIfindex, DOWNSTREAM_IFINDEX,
|
||||
(Inet6Address) address, DOWNSTREAM_MAC, dstMac);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testRuleMakeTetherDownstream6Key() throws Exception {
|
||||
final int mobileIfIndex = 100;
|
||||
final Ipv6ForwardingRule rule = buildTestForwardingRule(mobileIfIndex, NEIGH_A, MAC_A);
|
||||
final Ipv6DownstreamRule rule = buildTestDownstreamRule(mobileIfIndex, NEIGH_A, MAC_A);
|
||||
|
||||
final TetherDownstream6Key key = rule.makeTetherDownstream6Key();
|
||||
assertEquals(key.iif, mobileIfIndex);
|
||||
@@ -998,7 +1007,7 @@ public class BpfCoordinatorTest {
|
||||
@Test
|
||||
public void testRuleMakeTether6Value() throws Exception {
|
||||
final int mobileIfIndex = 100;
|
||||
final Ipv6ForwardingRule rule = buildTestForwardingRule(mobileIfIndex, NEIGH_A, MAC_A);
|
||||
final Ipv6DownstreamRule rule = buildTestDownstreamRule(mobileIfIndex, NEIGH_A, MAC_A);
|
||||
|
||||
final Tether6Value value = rule.makeTether6Value();
|
||||
assertEquals(value.oif, DOWNSTREAM_IFINDEX);
|
||||
@@ -1023,10 +1032,10 @@ public class BpfCoordinatorTest {
|
||||
// [1] Default limit.
|
||||
// Set the unlimited quota as default if the service has never applied a data limit for a
|
||||
// given upstream. Note that the data limit only be applied on an upstream which has rules.
|
||||
final Ipv6ForwardingRule rule = buildTestForwardingRule(mobileIfIndex, NEIGH_A, MAC_A);
|
||||
final Ipv6DownstreamRule rule = buildTestDownstreamRule(mobileIfIndex, NEIGH_A, MAC_A);
|
||||
final InOrder inOrder = inOrder(mNetd, mBpfDownstream6Map, mBpfLimitMap, mBpfStatsMap);
|
||||
coordinator.tetherOffloadRuleAdd(mIpServer, rule);
|
||||
verifyTetherOffloadRuleAdd(inOrder, rule);
|
||||
coordinator.addIpv6DownstreamRule(mIpServer, rule);
|
||||
verifyAddDownstreamRule(inOrder, rule);
|
||||
verifyTetherOffloadSetInterfaceQuota(inOrder, mobileIfIndex, QUOTA_UNLIMITED,
|
||||
true /* isInit */);
|
||||
inOrder.verifyNoMoreInteractions();
|
||||
@@ -1073,28 +1082,28 @@ public class BpfCoordinatorTest {
|
||||
verifyNeverTetherOffloadSetInterfaceQuota(inOrder);
|
||||
|
||||
// Adding the first rule on current upstream immediately sends the quota to netd.
|
||||
final Ipv6ForwardingRule ruleA = buildTestForwardingRule(mobileIfIndex, NEIGH_A, MAC_A);
|
||||
coordinator.tetherOffloadRuleAdd(mIpServer, ruleA);
|
||||
verifyTetherOffloadRuleAdd(inOrder, ruleA);
|
||||
final Ipv6DownstreamRule ruleA = buildTestDownstreamRule(mobileIfIndex, NEIGH_A, MAC_A);
|
||||
coordinator.addIpv6DownstreamRule(mIpServer, ruleA);
|
||||
verifyAddDownstreamRule(inOrder, ruleA);
|
||||
verifyTetherOffloadSetInterfaceQuota(inOrder, mobileIfIndex, limit, true /* isInit */);
|
||||
inOrder.verifyNoMoreInteractions();
|
||||
|
||||
// Adding the second rule on current upstream does not send the quota to netd.
|
||||
final Ipv6ForwardingRule ruleB = buildTestForwardingRule(mobileIfIndex, NEIGH_B, MAC_B);
|
||||
coordinator.tetherOffloadRuleAdd(mIpServer, ruleB);
|
||||
verifyTetherOffloadRuleAdd(inOrder, ruleB);
|
||||
final Ipv6DownstreamRule ruleB = buildTestDownstreamRule(mobileIfIndex, NEIGH_B, MAC_B);
|
||||
coordinator.addIpv6DownstreamRule(mIpServer, ruleB);
|
||||
verifyAddDownstreamRule(inOrder, ruleB);
|
||||
verifyNeverTetherOffloadSetInterfaceQuota(inOrder);
|
||||
|
||||
// Removing the second rule on current upstream does not send the quota to netd.
|
||||
coordinator.tetherOffloadRuleRemove(mIpServer, ruleB);
|
||||
verifyTetherOffloadRuleRemove(inOrder, ruleB);
|
||||
coordinator.removeIpv6DownstreamRule(mIpServer, ruleB);
|
||||
verifyRemoveDownstreamRule(inOrder, ruleB);
|
||||
verifyNeverTetherOffloadSetInterfaceQuota(inOrder);
|
||||
|
||||
// Removing the last rule on current upstream immediately sends the cleanup stuff to netd.
|
||||
updateStatsEntryForTetherOffloadGetAndClearStats(
|
||||
buildTestTetherStatsParcel(mobileIfIndex, 0, 0, 0, 0));
|
||||
coordinator.tetherOffloadRuleRemove(mIpServer, ruleA);
|
||||
verifyTetherOffloadRuleRemove(inOrder, ruleA);
|
||||
coordinator.removeIpv6DownstreamRule(mIpServer, ruleA);
|
||||
verifyRemoveDownstreamRule(inOrder, ruleA);
|
||||
verifyTetherOffloadGetAndClearStats(inOrder, mobileIfIndex);
|
||||
inOrder.verifyNoMoreInteractions();
|
||||
}
|
||||
@@ -1124,23 +1133,23 @@ public class BpfCoordinatorTest {
|
||||
|
||||
// [1] Adding rules on the upstream Ethernet.
|
||||
// Note that the default data limit is applied after the first rule is added.
|
||||
final Ipv6ForwardingRule ethernetRuleA = buildTestForwardingRule(
|
||||
final Ipv6DownstreamRule ethernetRuleA = buildTestDownstreamRule(
|
||||
ethIfIndex, NEIGH_A, MAC_A);
|
||||
final Ipv6ForwardingRule ethernetRuleB = buildTestForwardingRule(
|
||||
final Ipv6DownstreamRule ethernetRuleB = buildTestDownstreamRule(
|
||||
ethIfIndex, NEIGH_B, MAC_B);
|
||||
|
||||
coordinator.tetherOffloadRuleAdd(mIpServer, ethernetRuleA);
|
||||
verifyTetherOffloadRuleAdd(inOrder, ethernetRuleA);
|
||||
coordinator.addIpv6DownstreamRule(mIpServer, ethernetRuleA);
|
||||
verifyAddDownstreamRule(inOrder, ethernetRuleA);
|
||||
verifyTetherOffloadSetInterfaceQuota(inOrder, ethIfIndex, QUOTA_UNLIMITED,
|
||||
true /* isInit */);
|
||||
verifyStartUpstreamIpv6Forwarding(inOrder, DOWNSTREAM_IFINDEX, DOWNSTREAM_MAC, ethIfIndex);
|
||||
coordinator.tetherOffloadRuleAdd(mIpServer, ethernetRuleB);
|
||||
verifyTetherOffloadRuleAdd(inOrder, ethernetRuleB);
|
||||
coordinator.addIpv6DownstreamRule(mIpServer, ethernetRuleB);
|
||||
verifyAddDownstreamRule(inOrder, ethernetRuleB);
|
||||
|
||||
// [2] Update the existing rules from Ethernet to cellular.
|
||||
final Ipv6ForwardingRule mobileRuleA = buildTestForwardingRule(
|
||||
final Ipv6DownstreamRule mobileRuleA = buildTestDownstreamRule(
|
||||
mobileIfIndex, NEIGH_A, MAC_A);
|
||||
final Ipv6ForwardingRule mobileRuleB = buildTestForwardingRule(
|
||||
final Ipv6DownstreamRule mobileRuleB = buildTestDownstreamRule(
|
||||
mobileIfIndex, NEIGH_B, MAC_B);
|
||||
updateStatsEntryForTetherOffloadGetAndClearStats(
|
||||
buildTestTetherStatsParcel(ethIfIndex, 10, 20, 30, 40));
|
||||
@@ -1148,23 +1157,23 @@ public class BpfCoordinatorTest {
|
||||
// Update the existing rules for upstream changes. The rules are removed and re-added one
|
||||
// by one for updating upstream interface index by #tetherOffloadRuleUpdate.
|
||||
coordinator.tetherOffloadRuleUpdate(mIpServer, mobileIfIndex);
|
||||
verifyTetherOffloadRuleRemove(inOrder, ethernetRuleA);
|
||||
verifyTetherOffloadRuleRemove(inOrder, ethernetRuleB);
|
||||
verifyRemoveDownstreamRule(inOrder, ethernetRuleA);
|
||||
verifyRemoveDownstreamRule(inOrder, ethernetRuleB);
|
||||
verifyStopUpstreamIpv6Forwarding(inOrder, DOWNSTREAM_IFINDEX, DOWNSTREAM_MAC);
|
||||
verifyTetherOffloadGetAndClearStats(inOrder, ethIfIndex);
|
||||
verifyTetherOffloadRuleAdd(inOrder, mobileRuleA);
|
||||
verifyAddDownstreamRule(inOrder, mobileRuleA);
|
||||
verifyTetherOffloadSetInterfaceQuota(inOrder, mobileIfIndex, QUOTA_UNLIMITED,
|
||||
true /* isInit */);
|
||||
verifyStartUpstreamIpv6Forwarding(inOrder, DOWNSTREAM_IFINDEX, DOWNSTREAM_MAC,
|
||||
mobileIfIndex);
|
||||
verifyTetherOffloadRuleAdd(inOrder, mobileRuleB);
|
||||
verifyAddDownstreamRule(inOrder, mobileRuleB);
|
||||
|
||||
// [3] Clear all rules for a given IpServer.
|
||||
updateStatsEntryForTetherOffloadGetAndClearStats(
|
||||
buildTestTetherStatsParcel(mobileIfIndex, 50, 60, 70, 80));
|
||||
coordinator.tetherOffloadRuleClear(mIpServer);
|
||||
verifyTetherOffloadRuleRemove(inOrder, mobileRuleA);
|
||||
verifyTetherOffloadRuleRemove(inOrder, mobileRuleB);
|
||||
verifyRemoveDownstreamRule(inOrder, mobileRuleA);
|
||||
verifyRemoveDownstreamRule(inOrder, mobileRuleB);
|
||||
verifyStopUpstreamIpv6Forwarding(inOrder, DOWNSTREAM_IFINDEX, DOWNSTREAM_MAC);
|
||||
verifyTetherOffloadGetAndClearStats(inOrder, mobileIfIndex);
|
||||
|
||||
@@ -1201,37 +1210,37 @@ public class BpfCoordinatorTest {
|
||||
// The rule can't be added.
|
||||
final InetAddress neigh = InetAddresses.parseNumericAddress("2001:db8::1");
|
||||
final MacAddress mac = MacAddress.fromString("00:00:00:00:00:0a");
|
||||
final Ipv6ForwardingRule rule = buildTestForwardingRule(ifIndex, neigh, mac);
|
||||
coordinator.tetherOffloadRuleAdd(mIpServer, rule);
|
||||
verifyNeverTetherOffloadRuleAdd();
|
||||
LinkedHashMap<Inet6Address, Ipv6ForwardingRule> rules =
|
||||
coordinator.getForwardingRulesForTesting().get(mIpServer);
|
||||
final Ipv6DownstreamRule rule = buildTestDownstreamRule(ifIndex, neigh, mac);
|
||||
coordinator.addIpv6DownstreamRule(mIpServer, rule);
|
||||
verifyNeverAddDownstreamRule();
|
||||
LinkedHashMap<Inet6Address, Ipv6DownstreamRule> rules =
|
||||
coordinator.getIpv6DownstreamRulesForTesting().get(mIpServer);
|
||||
assertNull(rules);
|
||||
|
||||
// The rule can't be removed. This is not a realistic case because adding rule is not
|
||||
// allowed. That implies no rule could be removed, cleared or updated. Verify these
|
||||
// cases just in case.
|
||||
rules = new LinkedHashMap<Inet6Address, Ipv6ForwardingRule>();
|
||||
rules = new LinkedHashMap<Inet6Address, Ipv6DownstreamRule>();
|
||||
rules.put(rule.address, rule);
|
||||
coordinator.getForwardingRulesForTesting().put(mIpServer, rules);
|
||||
coordinator.tetherOffloadRuleRemove(mIpServer, rule);
|
||||
verifyNeverTetherOffloadRuleRemove();
|
||||
rules = coordinator.getForwardingRulesForTesting().get(mIpServer);
|
||||
coordinator.getIpv6DownstreamRulesForTesting().put(mIpServer, rules);
|
||||
coordinator.removeIpv6DownstreamRule(mIpServer, rule);
|
||||
verifyNeverRemoveDownstreamRule();
|
||||
rules = coordinator.getIpv6DownstreamRulesForTesting().get(mIpServer);
|
||||
assertNotNull(rules);
|
||||
assertEquals(1, rules.size());
|
||||
|
||||
// The rule can't be cleared.
|
||||
coordinator.tetherOffloadRuleClear(mIpServer);
|
||||
verifyNeverTetherOffloadRuleRemove();
|
||||
rules = coordinator.getForwardingRulesForTesting().get(mIpServer);
|
||||
verifyNeverRemoveDownstreamRule();
|
||||
rules = coordinator.getIpv6DownstreamRulesForTesting().get(mIpServer);
|
||||
assertNotNull(rules);
|
||||
assertEquals(1, rules.size());
|
||||
|
||||
// The rule can't be updated.
|
||||
coordinator.tetherOffloadRuleUpdate(mIpServer, rule.upstreamIfindex + 1 /* new */);
|
||||
verifyNeverTetherOffloadRuleRemove();
|
||||
verifyNeverTetherOffloadRuleAdd();
|
||||
rules = coordinator.getForwardingRulesForTesting().get(mIpServer);
|
||||
verifyNeverRemoveDownstreamRule();
|
||||
verifyNeverAddDownstreamRule();
|
||||
rules = coordinator.getIpv6DownstreamRulesForTesting().get(mIpServer);
|
||||
assertNotNull(rules);
|
||||
assertEquals(1, rules.size());
|
||||
}
|
||||
@@ -1669,17 +1678,17 @@ public class BpfCoordinatorTest {
|
||||
final BpfCoordinator coordinator = makeBpfCoordinator();
|
||||
|
||||
coordinator.addUpstreamNameToLookupTable(UPSTREAM_IFINDEX, UPSTREAM_IFACE);
|
||||
final Ipv6ForwardingRule ruleA = buildTestForwardingRule(UPSTREAM_IFINDEX, NEIGH_A, MAC_A);
|
||||
final Ipv6ForwardingRule ruleB = buildTestForwardingRule(UPSTREAM_IFINDEX, NEIGH_B, MAC_B);
|
||||
final Ipv6DownstreamRule ruleA = buildTestDownstreamRule(UPSTREAM_IFINDEX, NEIGH_A, MAC_A);
|
||||
final Ipv6DownstreamRule ruleB = buildTestDownstreamRule(UPSTREAM_IFINDEX, NEIGH_B, MAC_B);
|
||||
|
||||
coordinator.tetherOffloadRuleAdd(mIpServer, ruleA);
|
||||
coordinator.addIpv6DownstreamRule(mIpServer, ruleA);
|
||||
verify(mBpfDevMap).updateEntry(eq(new TetherDevKey(UPSTREAM_IFINDEX)),
|
||||
eq(new TetherDevValue(UPSTREAM_IFINDEX)));
|
||||
verify(mBpfDevMap).updateEntry(eq(new TetherDevKey(DOWNSTREAM_IFINDEX)),
|
||||
eq(new TetherDevValue(DOWNSTREAM_IFINDEX)));
|
||||
clearInvocations(mBpfDevMap);
|
||||
|
||||
coordinator.tetherOffloadRuleAdd(mIpServer, ruleB);
|
||||
coordinator.addIpv6DownstreamRule(mIpServer, ruleB);
|
||||
verify(mBpfDevMap, never()).updateEntry(any(), any());
|
||||
}
|
||||
|
||||
@@ -2139,9 +2148,15 @@ public class BpfCoordinatorTest {
|
||||
|
||||
@Test
|
||||
public void testIpv6ForwardingRuleToString() throws Exception {
|
||||
final Ipv6ForwardingRule rule = buildTestForwardingRule(UPSTREAM_IFINDEX, NEIGH_A, MAC_A);
|
||||
final Ipv6DownstreamRule downstreamRule = buildTestDownstreamRule(UPSTREAM_IFINDEX, NEIGH_A,
|
||||
MAC_A);
|
||||
assertEquals("upstreamIfindex: 1001, downstreamIfindex: 2001, address: 2001:db8::1, "
|
||||
+ "srcMac: 12:34:56:78:90:ab, dstMac: 00:00:00:00:00:0a", rule.toString());
|
||||
+ "srcMac: 12:34:56:78:90:ab, dstMac: 00:00:00:00:00:0a",
|
||||
downstreamRule.toString());
|
||||
final Ipv6UpstreamRule upstreamRule = buildTestUpstreamRule(UPSTREAM_IFINDEX);
|
||||
assertEquals("upstreamIfindex: 1001, downstreamIfindex: 2001, sourcePrefix: ::/64, "
|
||||
+ "inDstMac: 12:34:56:78:90:ab, outSrcMac: 00:00:00:00:00:00, "
|
||||
+ "outDstMac: 00:00:00:00:00:00", upstreamRule.toString());
|
||||
}
|
||||
|
||||
private void verifyDump(@NonNull final BpfCoordinator coordinator) {
|
||||
@@ -2177,7 +2192,7 @@ public class BpfCoordinatorTest {
|
||||
// - dumpCounters
|
||||
// * mBpfErrorMap
|
||||
// - dumpIpv6ForwardingRulesByDownstream
|
||||
// * mIpv6ForwardingRules
|
||||
// * mIpv6DownstreamRules
|
||||
|
||||
// dumpBpfForwardingRulesIpv4
|
||||
mBpfDownstream4Map.insertEntry(
|
||||
@@ -2188,7 +2203,7 @@ public class BpfCoordinatorTest {
|
||||
new TestUpstream4Value.Builder().build());
|
||||
|
||||
// dumpBpfForwardingRulesIpv6
|
||||
final Ipv6ForwardingRule rule = buildTestForwardingRule(UPSTREAM_IFINDEX, NEIGH_A, MAC_A);
|
||||
final Ipv6DownstreamRule rule = buildTestDownstreamRule(UPSTREAM_IFINDEX, NEIGH_A, MAC_A);
|
||||
mBpfDownstream6Map.insertEntry(rule.makeTetherDownstream6Key(), rule.makeTether6Value());
|
||||
|
||||
final TetherUpstream6Key upstream6Key = new TetherUpstream6Key(DOWNSTREAM_IFINDEX,
|
||||
@@ -2218,12 +2233,12 @@ public class BpfCoordinatorTest {
|
||||
new S32(1000 /* count */));
|
||||
|
||||
// dumpIpv6ForwardingRulesByDownstream
|
||||
final HashMap<IpServer, LinkedHashMap<Inet6Address, Ipv6ForwardingRule>>
|
||||
ipv6ForwardingRules = coordinator.getForwardingRulesForTesting();
|
||||
final LinkedHashMap<Inet6Address, Ipv6ForwardingRule> addressRuleMap =
|
||||
final HashMap<IpServer, LinkedHashMap<Inet6Address, Ipv6DownstreamRule>>
|
||||
ipv6DownstreamRules = coordinator.getIpv6DownstreamRulesForTesting();
|
||||
final LinkedHashMap<Inet6Address, Ipv6DownstreamRule> addressRuleMap =
|
||||
new LinkedHashMap<>();
|
||||
addressRuleMap.put(rule.address, rule);
|
||||
ipv6ForwardingRules.put(mIpServer, addressRuleMap);
|
||||
ipv6DownstreamRules.put(mIpServer, addressRuleMap);
|
||||
|
||||
verifyDump(coordinator);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user