Merge changes I515be275,Ied159454,I5a29bdd1 am: 8ba40704f3 am: 7cc20e1782

Original change: https://android-review.googlesource.com/c/platform/packages/modules/Connectivity/+/1662791

Change-Id: Iecd18825990c22add32cdbb16b8ff86a8a06487c
This commit is contained in:
Nucca Chen
2021-04-07 15:31:05 +00:00
committed by Automerger Merge Worker
13 changed files with 353 additions and 143 deletions

View File

@@ -80,12 +80,14 @@ public class BpfCoordinatorShimImpl
@Override
public boolean startUpstreamIpv6Forwarding(int downstreamIfindex, int upstreamIfindex,
MacAddress srcMac, MacAddress dstMac, int mtu) {
@NonNull MacAddress inDstMac, @NonNull MacAddress outSrcMac,
@NonNull MacAddress outDstMac, int mtu) {
return true;
}
@Override
public boolean stopUpstreamIpv6Forwarding(int downstreamIfindex, int upstreamIfindex) {
public boolean stopUpstreamIpv6Forwarding(int downstreamIfindex,
int upstreamIfindex, @NonNull MacAddress inDstMac) {
return true;
}
@@ -170,6 +172,12 @@ public class BpfCoordinatorShimImpl
return true;
}
@Override
public boolean isAnyIpv4RuleOnUpstream(int ifIndex) {
/* no op */
return false;
}
@Override
public String toString() {
return "Netd used";

View File

@@ -23,6 +23,7 @@ import android.net.util.SharedLog;
import android.system.ErrnoException;
import android.system.Os;
import android.system.OsConstants;
import android.util.Log;
import android.util.SparseArray;
import androidx.annotation.NonNull;
@@ -84,6 +85,20 @@ public class BpfCoordinatorShimImpl
@Nullable
private final BpfMap<TetherLimitKey, TetherLimitValue> mBpfLimitMap;
// Tracking IPv4 rule count while any rule is using the given upstream interfaces. Used for
// reducing the BPF map iteration query. The count is increased or decreased when the rule is
// added or removed successfully on mBpfDownstream4Map. Counting the rules on downstream4 map
// is because tetherOffloadRuleRemove can't get upstream interface index from upstream key,
// unless pass upstream value which is not required for deleting map entry. The upstream
// interface index is the same in Upstream4Value.oif and Downstream4Key.iif. For now, it is
// okay to count on Downstream4Key. See BpfConntrackEventConsumer#accept.
// Note that except the constructor, any calls to mBpfDownstream4Map.clear() need to clear
// this counter as well.
// TODO: Count the rule on upstream if multi-upstream is supported and the
// packet needs to be sent and responded on different upstream interfaces.
// TODO: Add IPv6 rule count.
private final SparseArray<Integer> mRule4CountOnUpstream = new SparseArray<>();
public BpfCoordinatorShimImpl(@NonNull final Dependencies deps) {
mLog = deps.getSharedLog().forSubComponent(TAG);
@@ -169,12 +184,13 @@ public class BpfCoordinatorShimImpl
@Override
public boolean startUpstreamIpv6Forwarding(int downstreamIfindex, int upstreamIfindex,
MacAddress srcMac, MacAddress dstMac, int mtu) {
@NonNull MacAddress inDstMac, @NonNull MacAddress outSrcMac,
@NonNull MacAddress outDstMac, int mtu) {
if (!isInitialized()) return false;
final TetherUpstream6Key key = new TetherUpstream6Key(downstreamIfindex);
final Tether6Value value = new Tether6Value(upstreamIfindex, srcMac,
dstMac, OsConstants.ETH_P_IPV6, mtu);
final TetherUpstream6Key key = new TetherUpstream6Key(downstreamIfindex, inDstMac);
final Tether6Value value = new Tether6Value(upstreamIfindex, outSrcMac,
outDstMac, OsConstants.ETH_P_IPV6, mtu);
try {
mBpfUpstream6Map.insertEntry(key, value);
} catch (ErrnoException | IllegalStateException e) {
@@ -185,10 +201,11 @@ public class BpfCoordinatorShimImpl
}
@Override
public boolean stopUpstreamIpv6Forwarding(int downstreamIfindex, int upstreamIfindex) {
public boolean stopUpstreamIpv6Forwarding(int downstreamIfindex, int upstreamIfindex,
@NonNull MacAddress inDstMac) {
if (!isInitialized()) return false;
final TetherUpstream6Key key = new TetherUpstream6Key(downstreamIfindex);
final TetherUpstream6Key key = new TetherUpstream6Key(downstreamIfindex, inDstMac);
try {
mBpfUpstream6Map.deleteEntry(key);
} catch (ErrnoException e) {
@@ -324,18 +341,22 @@ public class BpfCoordinatorShimImpl
if (!isInitialized()) return false;
try {
// The last used time field of the value is updated by the bpf program. Adding the same
// map pair twice causes the unexpected refresh. Must be fixed before starting the
// conntrack timeout extension implementation.
// TODO: consider using insertEntry.
if (downstream) {
mBpfDownstream4Map.updateEntry(key, value);
mBpfDownstream4Map.insertEntry(key, value);
// Increase the rule count while a adding rule is using a given upstream interface.
final int upstreamIfindex = (int) key.iif;
int count = mRule4CountOnUpstream.get(upstreamIfindex, 0 /* default */);
mRule4CountOnUpstream.put(upstreamIfindex, ++count);
} else {
mBpfUpstream4Map.updateEntry(key, value);
mBpfUpstream4Map.insertEntry(key, value);
}
} catch (ErrnoException e) {
mLog.e("Could not update entry: ", e);
mLog.e("Could not insert entry (" + key + ", " + value + "): " + e);
return false;
} catch (IllegalStateException e) {
// Silent if the rule already exists. Note that the errno EEXIST was rethrown as
// IllegalStateException. See BpfMap#insertEntry.
}
return true;
}
@@ -346,7 +367,26 @@ public class BpfCoordinatorShimImpl
try {
if (downstream) {
mBpfDownstream4Map.deleteEntry(key);
if (!mBpfDownstream4Map.deleteEntry(key)) {
mLog.e("Could not delete entry (key: " + key + ")");
return false;
}
// Decrease the rule count while a deleting rule is not using a given upstream
// interface anymore.
final int upstreamIfindex = (int) key.iif;
Integer count = mRule4CountOnUpstream.get(upstreamIfindex);
if (count == null) {
Log.wtf(TAG, "Could not delete count for interface " + upstreamIfindex);
return false;
}
if (--count == 0) {
// Remove the entry if the count decreases to zero.
mRule4CountOnUpstream.remove(upstreamIfindex);
} else {
mRule4CountOnUpstream.put(upstreamIfindex, count);
}
} else {
mBpfUpstream4Map.deleteEntry(key);
}
@@ -386,6 +426,12 @@ public class BpfCoordinatorShimImpl
return true;
}
@Override
public boolean isAnyIpv4RuleOnUpstream(int ifIndex) {
// No entry means no rule for the given interface because 0 has never been stored.
return mRule4CountOnUpstream.get(ifIndex) != null;
}
private String mapStatus(BpfMap m, String name) {
return name + "{" + (m != null ? "OK" : "ERROR") + "}";
}

View File

@@ -78,21 +78,25 @@ public abstract class BpfCoordinatorShim {
* @param downstreamIfindex the downstream interface index
* @param upstreamIfindex the upstream interface index
* @param srcMac the source MAC address to use for packets
* @oaram dstMac the destination MAC address to use for packets
* @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,
MacAddress srcMac, MacAddress dstMac, int mtu);
@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 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);
public abstract boolean stopUpstreamIpv6Forwarding(int downstreamIfindex,
int upstreamIfindex, @NonNull MacAddress inDstMac);
/**
* Return BPF tethering offload statistics.
@@ -144,6 +148,11 @@ public abstract class BpfCoordinatorShim {
*/
public abstract boolean tetherOffloadRuleRemove(boolean downstream, @NonNull Tether4Key key);
/**
* Whether there is currently any IPv4 rule on the specified upstream.
*/
public abstract boolean isAnyIpv4RuleOnUpstream(int ifIndex);
/**
* Attach BPF program.
*

View File

@@ -107,11 +107,12 @@ typedef uint64_t TetherLimitValue; // in bytes
// Ethernet) have 6-byte MAC addresses.
typedef struct {
uint32_t iif; // The input interface index
// TODO: extend this to include dstMac
struct in6_addr neigh6; // The destination IPv6 address
uint32_t iif; // The input interface index
uint8_t dstMac[ETH_ALEN]; // destination ethernet mac address (zeroed iff rawip ingress)
uint8_t zero[2]; // zero pad for 8 byte alignment
struct in6_addr neigh6; // The destination IPv6 address
} TetherDownstream6Key;
STRUCT_SIZE(TetherDownstream6Key, 4 + 16); // 20
STRUCT_SIZE(TetherDownstream6Key, 4 + 6 + 2 + 16); // 28
typedef struct {
uint32_t oif; // The output interface to redirect to
@@ -154,10 +155,12 @@ STRUCT_SIZE(TetherDownstream64Value, 4 + 14 + 2 + 4 + 4 + 2 + 2 + 8); // 40
#define TETHER_UPSTREAM6_MAP_PATH BPF_PATH_TETHER "map_offload_tether_upstream6_map"
typedef struct {
uint32_t iif; // The input interface index
// TODO: extend this to include dstMac and src ip /64 subnet
uint32_t iif; // The input interface index
uint8_t dstMac[ETH_ALEN]; // destination ethernet mac address (zeroed iff rawip ingress)
uint8_t zero[2]; // zero pad for 8 byte alignment
// TODO: extend this to include src ip /64 subnet
} TetherUpstream6Key;
STRUCT_SIZE(TetherUpstream6Key, 4);
STRUCT_SIZE(TetherUpstream6Key, 12);
#define TETHER_DOWNSTREAM4_TC_PROG_RAWIP_NAME "prog_offload_schedcls_tether_downstream4_rawip"
#define TETHER_DOWNSTREAM4_TC_PROG_ETHER_NAME "prog_offload_schedcls_tether_downstream4_ether"

View File

@@ -176,6 +176,7 @@ static inline __always_inline int do_forward6(struct __sk_buff* skb, const bool
TetherUpstream6Key ku = {
.iif = skb->ifindex,
};
if (is_ethernet) __builtin_memcpy(downstream ? kd.dstMac : ku.dstMac, eth->h_dest, ETH_ALEN);
Tether6Value* v = downstream ? bpf_tether_downstream6_map_lookup_elem(&kd)
: bpf_tether_upstream6_map_lookup_elem(&ku);
@@ -488,7 +489,7 @@ static inline __always_inline int do_forward4(struct __sk_buff* skb, const bool
.srcPort = is_tcp ? tcph->source : udph->source,
.dstPort = is_tcp ? tcph->dest : udph->dest,
};
if (is_ethernet) for (int i = 0; i < ETH_ALEN; ++i) k.dstMac[i] = eth->h_dest[i];
if (is_ethernet) __builtin_memcpy(k.dstMac, eth->h_dest, ETH_ALEN);
Tether4Value* v = downstream ? bpf_tether_downstream4_map_lookup_elem(&k)
: bpf_tether_upstream4_map_lookup_elem(&k);

View File

@@ -742,16 +742,14 @@ public class IpServer extends StateMachine {
params.dnses.add(dnsServer);
}
}
// Add upstream index to name mapping for the tether stats usage in the coordinator.
// Although this mapping could be added by both class Tethering and IpServer, adding
// mapping from IpServer guarantees that the mapping is added before the adding
// forwarding rules. That is because there are different state machines in both
// classes. It is hard to guarantee the link property update order between multiple
// state machines.
mBpfCoordinator.addUpstreamNameToLookupTable(upstreamIfIndex, upstreamIface);
}
// Add upstream index to name mapping. See the comment of the interface mapping update in
// CMD_TETHER_CONNECTION_CHANGED. Adding the mapping update here to the avoid potential
// timing issue. It prevents that the IPv6 capability is updated later than
// CMD_TETHER_CONNECTION_CHANGED.
mBpfCoordinator.addUpstreamNameToLookupTable(upstreamIfIndex, upstreamIface);
// If v6only is null, we pass in null to setRaParams(), which handles
// deprecation of any existing RA data.
@@ -1335,6 +1333,26 @@ public class IpServer extends StateMachine {
mUpstreamIfaceSet = newUpstreamIfaceSet;
for (String ifname : added) {
// Add upstream index to name mapping for the tether stats usage in the
// coordinator. Although this mapping could be added by both class
// Tethering and IpServer, adding mapping from IpServer guarantees that
// the mapping is added before adding forwarding rules. That is because
// there are different state machines in both classes. It is hard to
// guarantee the link property update order between multiple state machines.
// Note that both IPv4 and IPv6 interface may be added because
// Tethering::setUpstreamNetwork calls getTetheringInterfaces which merges
// IPv4 and IPv6 interface name (if any) into an InterfaceSet. The IPv6
// capability may be updated later. In that case, IPv6 interface mapping is
// updated in updateUpstreamIPv6LinkProperties.
if (!ifname.startsWith("v4-")) { // ignore clat interfaces
final InterfaceParams upstreamIfaceParams =
mDeps.getInterfaceParams(ifname);
if (upstreamIfaceParams != null) {
mBpfCoordinator.addUpstreamNameToLookupTable(
upstreamIfaceParams.index, ifname);
}
}
mBpfCoordinator.maybeAttachProgram(mIfaceName, ifname);
try {
mNetd.tetherAddForward(mIfaceName, ifname);

View File

@@ -478,25 +478,14 @@ public class BpfCoordinator {
LinkedHashMap<Inet6Address, Ipv6ForwardingRule> rules = mIpv6ForwardingRules.get(ipServer);
// When the first rule is added to an upstream, setup upstream forwarding and data limit.
final int upstreamIfindex = rule.upstreamIfindex;
if (!isAnyRuleOnUpstream(upstreamIfindex)) {
// If failed to set a data limit, probably should not use this upstream, because
// the upstream may not want to blow through the data limit that was told to apply.
// TODO: Perhaps stop the coordinator.
boolean success = updateDataLimit(upstreamIfindex);
if (!success) {
final String iface = mInterfaceNames.get(upstreamIfindex);
mLog.e("Setting data limit for " + iface + " failed.");
}
}
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,
if (!mBpfCoordinatorShim.startUpstreamIpv6Forwarding(downstream, upstream, rule.srcMac,
NULL_MAC_ADDRESS, NULL_MAC_ADDRESS, NetworkStackConstants.ETHER_MTU)) {
mLog.e("Failed to enable upstream IPv6 forwarding from "
+ mInterfaceNames.get(downstream) + " to " + mInterfaceNames.get(upstream));
@@ -537,29 +526,15 @@ public class BpfCoordinator {
if (!isAnyRuleFromDownstreamToUpstream(rule.downstreamIfindex, rule.upstreamIfindex)) {
final int downstream = rule.downstreamIfindex;
final int upstream = rule.upstreamIfindex;
if (!mBpfCoordinatorShim.stopUpstreamIpv6Forwarding(downstream, upstream)) {
if (!mBpfCoordinatorShim.stopUpstreamIpv6Forwarding(downstream, upstream,
rule.srcMac)) {
mLog.e("Failed to disable upstream IPv6 forwarding from "
+ mInterfaceNames.get(downstream) + " to " + mInterfaceNames.get(upstream));
}
}
// Do cleanup functionality if there is no more rule on the given upstream.
final int upstreamIfindex = rule.upstreamIfindex;
if (!isAnyRuleOnUpstream(upstreamIfindex)) {
final TetherStatsValue statsValue =
mBpfCoordinatorShim.tetherOffloadGetAndClearStats(upstreamIfindex);
if (statsValue == null) {
Log.wtf(TAG, "Fail to cleanup tether stats for upstream index " + upstreamIfindex);
return;
}
SparseArray<TetherStatsValue> tetherStatsList = new SparseArray<TetherStatsValue>();
tetherStatsList.put(upstreamIfindex, statsValue);
// Update the last stats delta and delete the local cache for a given upstream.
updateQuotaAndStatsFromSnapshot(tetherStatsList);
mStats.remove(upstreamIfindex);
}
maybeClearLimit(rule.upstreamIfindex);
}
/**
@@ -821,8 +796,8 @@ public class BpfCoordinator {
}
private String ipv6UpstreamRuletoString(TetherUpstream6Key key, Tether6Value value) {
return String.format("%d(%s) -> %d(%s) %04x %s %s",
key.iif, getIfName(key.iif), value.oif, getIfName(value.oif),
return String.format("%d(%s) %s -> %d(%s) %04x %s %s",
key.iif, getIfName(key.iif), key.dstMac, value.oif, getIfName(value.oif),
value.ethProto, value.ethSrcMac, value.ethDstMac);
}
@@ -912,6 +887,62 @@ public class BpfCoordinator {
/** 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.
// TODO: support ether ip upstream interface.
//
// NAT network topology:
//
// public network (rawip) private network
// | UE |
// +------------+ V +------------+------------+ V +------------+
// | Sever +---------+ Upstream | Downstream +---------+ Client |
// +------------+ +------------+------------+ +------------+
//
// upstream6 key and value:
//
// +------+-------------+
// | TetherUpstream6Key |
// +------+------+------+
// |field |iif |dstMac|
// | | | |
// +------+------+------+
// |value |downst|downst|
// | |ream |ream |
// +------+------+------+
//
// +------+----------------------------------+
// | |Tether6Value |
// +------+------+------+------+------+------+
// |field |oif |ethDst|ethSrc|ethPro|pmtu |
// | | |mac |mac |to | |
// +------+------+------+------+------+------+
// |value |upstre|-- |-- |ETH_P_|1500 |
// | |am | | |IP | |
// +------+------+------+------+------+------+
//
// downstream6 key and value:
//
// +------+--------------------+
// | |TetherDownstream6Key|
// +------+------+------+------+
// |field |iif |dstMac|neigh6|
// | | | | |
// +------+------+------+------+
// |value |upstre|-- |client|
// | |am | | |
// +------+------+------+------+
//
// +------+----------------------------------+
// | |Tether6Value |
// +------+------+------+------+------+------+
// |field |oif |ethDst|ethSrc|ethPro|pmtu |
// | | |mac |mac |to | |
// +------+------+------+------+------+------+
// |value |downst|client|downst|ETH_P_|1500 |
// | |ream | |ream |IP | |
// +------+------+------+------+------+------+
//
public final int upstreamIfindex;
public final int downstreamIfindex;
@@ -961,7 +992,8 @@ public class BpfCoordinator {
*/
@NonNull
public TetherDownstream6Key makeTetherDownstream6Key() {
return new TetherDownstream6Key(upstreamIfindex, address.getAddress());
return new TetherDownstream6Key(upstreamIfindex, NULL_MAC_ADDRESS,
address.getAddress());
}
/**
@@ -1114,6 +1146,8 @@ public class BpfCoordinator {
// Support raw ip only.
// TODO: add ether ip support.
// TODO: parse CTA_PROTOINFO of conntrack event in ConntrackMonitor. For TCP, only add rules
// while TCP status is established.
private class BpfConntrackEventConsumer implements ConntrackEventConsumer {
@NonNull
private Tether4Key makeTetherUpstream4Key(
@@ -1179,8 +1213,9 @@ public class BpfCoordinator {
if (e.msgType == (NetlinkConstants.NFNL_SUBSYS_CTNETLINK << 8
| NetlinkConstants.IPCTNL_MSG_CT_DELETE)) {
mBpfCoordinatorShim.tetherOffloadRuleRemove(false, upstream4Key);
mBpfCoordinatorShim.tetherOffloadRuleRemove(true, downstream4Key);
mBpfCoordinatorShim.tetherOffloadRuleRemove(UPSTREAM, upstream4Key);
mBpfCoordinatorShim.tetherOffloadRuleRemove(DOWNSTREAM, downstream4Key);
maybeClearLimit(upstreamIndex);
return;
}
@@ -1188,8 +1223,9 @@ public class BpfCoordinator {
final Tether4Value downstream4Value = makeTetherDownstream4Value(e, tetherClient,
upstreamIndex);
mBpfCoordinatorShim.tetherOffloadRuleAdd(false, upstream4Key, upstream4Value);
mBpfCoordinatorShim.tetherOffloadRuleAdd(true, downstream4Key, downstream4Value);
maybeSetLimit(upstreamIndex);
mBpfCoordinatorShim.tetherOffloadRuleAdd(UPSTREAM, upstream4Key, upstream4Value);
mBpfCoordinatorShim.tetherOffloadRuleAdd(DOWNSTREAM, downstream4Key, downstream4Value);
}
}
@@ -1251,6 +1287,47 @@ public class BpfCoordinator {
return sendDataLimitToBpfMap(ifIndex, quotaBytes);
}
private void maybeSetLimit(int upstreamIfindex) {
if (isAnyRuleOnUpstream(upstreamIfindex)
|| mBpfCoordinatorShim.isAnyIpv4RuleOnUpstream(upstreamIfindex)) {
return;
}
// If failed to set a data limit, probably should not use this upstream, because
// the upstream may not want to blow through the data limit that was told to apply.
// TODO: Perhaps stop the coordinator.
boolean success = updateDataLimit(upstreamIfindex);
if (!success) {
final String iface = mInterfaceNames.get(upstreamIfindex);
mLog.e("Setting data limit for " + iface + " failed.");
}
}
// TODO: This should be also called while IpServer wants to clear all IPv4 rules. Relying on
// conntrack event can't cover this case.
private void maybeClearLimit(int upstreamIfindex) {
if (isAnyRuleOnUpstream(upstreamIfindex)
|| mBpfCoordinatorShim.isAnyIpv4RuleOnUpstream(upstreamIfindex)) {
return;
}
final TetherStatsValue statsValue =
mBpfCoordinatorShim.tetherOffloadGetAndClearStats(upstreamIfindex);
if (statsValue == null) {
Log.wtf(TAG, "Fail to cleanup tether stats for upstream index " + upstreamIfindex);
return;
}
SparseArray<TetherStatsValue> tetherStatsList = new SparseArray<TetherStatsValue>();
tetherStatsList.put(upstreamIfindex, statsValue);
// Update the last stats delta and delete the local cache for a given upstream.
updateQuotaAndStatsFromSnapshot(tetherStatsList);
mStats.remove(upstreamIfindex);
}
// 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()) {

View File

@@ -16,6 +16,10 @@
package com.android.networkstack.tethering;
import android.net.MacAddress;
import androidx.annotation.NonNull;
import com.android.net.module.util.Struct;
import com.android.net.module.util.Struct.Field;
import com.android.net.module.util.Struct.Type;
@@ -24,16 +28,23 @@ import java.net.Inet6Address;
import java.net.InetAddress;
import java.net.UnknownHostException;
import java.util.Arrays;
import java.util.Objects;
/** The key of BpfMap which is used for bpf offload. */
public class TetherDownstream6Key extends Struct {
@Field(order = 0, type = Type.U32)
public final long iif; // The input interface index.
@Field(order = 1, type = Type.ByteArray, arraysize = 16)
@Field(order = 1, type = Type.EUI48, padding = 2)
public final MacAddress dstMac; // Destination ethernet mac address (zeroed iff rawip ingress).
@Field(order = 2, type = Type.ByteArray, arraysize = 16)
public final byte[] neigh6; // The destination IPv6 address.
public TetherDownstream6Key(final long iif, final byte[] neigh6) {
public TetherDownstream6Key(final long iif, @NonNull final MacAddress dstMac,
final byte[] neigh6) {
Objects.requireNonNull(dstMac);
try {
final Inet6Address unused = (Inet6Address) InetAddress.getByAddress(neigh6);
} catch (ClassCastException | UnknownHostException e) {
@@ -41,29 +52,15 @@ public class TetherDownstream6Key extends Struct {
+ Arrays.toString(neigh6));
}
this.iif = iif;
this.dstMac = dstMac;
this.neigh6 = neigh6;
}
@Override
public boolean equals(Object obj) {
if (this == obj) return true;
if (!(obj instanceof TetherDownstream6Key)) return false;
final TetherDownstream6Key that = (TetherDownstream6Key) obj;
return iif == that.iif && Arrays.equals(neigh6, that.neigh6);
}
@Override
public int hashCode() {
return Long.hashCode(iif) ^ Arrays.hashCode(neigh6);
}
@Override
public String toString() {
try {
return String.format("iif: %d, neigh: %s", iif, Inet6Address.getByAddress(neigh6));
return String.format("iif: %d, dstMac: %s, neigh: %s", iif, dstMac,
Inet6Address.getByAddress(neigh6));
} catch (UnknownHostException e) {
// Should not happen because construtor already verify neigh6.
throw new IllegalStateException("Invalid TetherDownstream6Key");

View File

@@ -16,14 +16,26 @@
package com.android.networkstack.tethering;
import android.net.MacAddress;
import androidx.annotation.NonNull;
import com.android.net.module.util.Struct;
import java.util.Objects;
/** Key type for upstream IPv6 forwarding map. */
public class TetherUpstream6Key extends Struct {
@Field(order = 0, type = Type.S32)
public final int iif; // The input interface index.
public TetherUpstream6Key(int iif) {
@Field(order = 1, type = Type.EUI48, padding = 2)
public final MacAddress dstMac; // Destination ethernet mac address (zeroed iff rawip ingress).
public TetherUpstream6Key(int iif, @NonNull final MacAddress dstMac) {
Objects.requireNonNull(dstMac);
this.iif = iif;
this.dstMac = dstMac;
}
}

View File

@@ -65,13 +65,13 @@ public final class BpfMapTest {
@Before
public void setUp() throws Exception {
mTestData = new ArrayMap<>();
mTestData.put(createTetherDownstream6Key(101, "2001:db8::1"),
mTestData.put(createTetherDownstream6Key(101, "00:00:00:00:00:aa", "2001:db8::1"),
createTether6Value(11, "00:00:00:00:00:0a", "11:11:11:00:00:0b",
ETH_P_IPV6, 1280));
mTestData.put(createTetherDownstream6Key(102, "2001:db8::2"),
mTestData.put(createTetherDownstream6Key(102, "00:00:00:00:00:bb", "2001:db8::2"),
createTether6Value(22, "00:00:00:00:00:0c", "22:22:22:00:00:0d",
ETH_P_IPV6, 1400));
mTestData.put(createTetherDownstream6Key(103, "2001:db8::3"),
mTestData.put(createTetherDownstream6Key(103, "00:00:00:00:00:cc", "2001:db8::3"),
createTether6Value(33, "00:00:00:00:00:0e", "33:33:33:00:00:0f",
ETH_P_IPV6, 1500));
@@ -94,11 +94,12 @@ public final class BpfMapTest {
assertTrue(mTestMap.isEmpty());
}
private TetherDownstream6Key createTetherDownstream6Key(long iif, String address)
throws Exception {
private TetherDownstream6Key createTetherDownstream6Key(long iif, String mac,
String address) throws Exception {
final MacAddress dstMac = MacAddress.fromString(mac);
final InetAddress ipv6Address = InetAddress.getByName(address);
return new TetherDownstream6Key(iif, ipv6Address.getAddress());
return new TetherDownstream6Key(iif, dstMac, ipv6Address.getAddress());
}
private Tether6Value createTether6Value(int oif, String src, String dst, int proto, int pmtu) {
@@ -164,7 +165,7 @@ public final class BpfMapTest {
public void testGetNextKey() throws Exception {
// [1] If the passed-in key is not found on empty map, return null.
final TetherDownstream6Key nonexistentKey =
createTetherDownstream6Key(1234, "2001:db8::10");
createTetherDownstream6Key(1234, "00:00:00:00:00:01", "2001:db8::10");
assertNull(mTestMap.getNextKey(nonexistentKey));
// [2] If the passed-in key is null on empty map, throw NullPointerException.
@@ -367,7 +368,8 @@ public final class BpfMapTest {
// Build test data for TEST_MAP_SIZE + 1 entries.
for (int i = 1; i <= TEST_MAP_SIZE + 1; i++) {
testData.put(createTetherDownstream6Key(i, "2001:db8::1"),
testData.put(
createTetherDownstream6Key(i, "00:00:00:00:00:01", "2001:db8::1"),
createTether6Value(100, "de:ad:be:ef:00:01", "de:ad:be:ef:00:02",
ETH_P_IPV6, 1500));
}

View File

@@ -474,6 +474,8 @@ public class IpServerTest {
InOrder inOrder = inOrder(mNetd, mBpfCoordinator);
// Add the forwarding pair <IFACE_NAME, UPSTREAM_IFACE>.
inOrder.verify(mBpfCoordinator).addUpstreamNameToLookupTable(UPSTREAM_IFINDEX,
UPSTREAM_IFACE);
inOrder.verify(mBpfCoordinator).maybeAttachProgram(IFACE_NAME, UPSTREAM_IFACE);
inOrder.verify(mNetd).tetherAddForward(IFACE_NAME, UPSTREAM_IFACE);
inOrder.verify(mNetd).ipfwdAddInterfaceForward(IFACE_NAME, UPSTREAM_IFACE);
@@ -494,6 +496,8 @@ public class IpServerTest {
inOrder.verify(mNetd).tetherRemoveForward(IFACE_NAME, UPSTREAM_IFACE);
// Add the forwarding pair <IFACE_NAME, UPSTREAM_IFACE2>.
inOrder.verify(mBpfCoordinator).addUpstreamNameToLookupTable(UPSTREAM_IFINDEX2,
UPSTREAM_IFACE2);
inOrder.verify(mBpfCoordinator).maybeAttachProgram(IFACE_NAME, UPSTREAM_IFACE2);
inOrder.verify(mNetd).tetherAddForward(IFACE_NAME, UPSTREAM_IFACE2);
inOrder.verify(mNetd).ipfwdAddInterfaceForward(IFACE_NAME, UPSTREAM_IFACE2);
@@ -517,6 +521,8 @@ public class IpServerTest {
// Add the forwarding pair <IFACE_NAME, UPSTREAM_IFACE2> and expect that failed on
// tetherAddForward.
inOrder.verify(mBpfCoordinator).addUpstreamNameToLookupTable(UPSTREAM_IFINDEX2,
UPSTREAM_IFACE2);
inOrder.verify(mBpfCoordinator).maybeAttachProgram(IFACE_NAME, UPSTREAM_IFACE2);
inOrder.verify(mNetd).tetherAddForward(IFACE_NAME, UPSTREAM_IFACE2);
@@ -543,6 +549,8 @@ public class IpServerTest {
// Add the forwarding pair <IFACE_NAME, UPSTREAM_IFACE2> and expect that failed on
// ipfwdAddInterfaceForward.
inOrder.verify(mBpfCoordinator).addUpstreamNameToLookupTable(UPSTREAM_IFINDEX2,
UPSTREAM_IFACE2);
inOrder.verify(mBpfCoordinator).maybeAttachProgram(IFACE_NAME, UPSTREAM_IFACE2);
inOrder.verify(mNetd).tetherAddForward(IFACE_NAME, UPSTREAM_IFACE2);
inOrder.verify(mNetd).ipfwdAddInterfaceForward(IFACE_NAME, UPSTREAM_IFACE2);
@@ -830,8 +838,8 @@ public class IpServerTest {
@NonNull
private static TetherDownstream6Key makeDownstream6Key(int upstreamIfindex,
@NonNull final InetAddress dst) {
return new TetherDownstream6Key(upstreamIfindex, dst.getAddress());
@NonNull MacAddress upstreamMac, @NonNull final InetAddress dst) {
return new TetherDownstream6Key(upstreamIfindex, upstreamMac, dst.getAddress());
}
@NonNull
@@ -849,10 +857,12 @@ public class IpServerTest {
}
private void verifyTetherOffloadRuleAdd(@Nullable InOrder inOrder, int upstreamIfindex,
@NonNull final InetAddress dst, @NonNull final MacAddress dstMac) throws Exception {
@NonNull MacAddress upstreamMac, @NonNull final InetAddress dst,
@NonNull final MacAddress dstMac) throws Exception {
if (mBpfDeps.isAtLeastS()) {
verifyWithOrder(inOrder, mBpfDownstream6Map).updateEntry(
makeDownstream6Key(upstreamIfindex, dst), makeDownstream6Value(dstMac));
makeDownstream6Key(upstreamIfindex, upstreamMac, dst),
makeDownstream6Value(dstMac));
} else {
verifyWithOrder(inOrder, mNetd).tetherOffloadRuleAdd(matches(upstreamIfindex, dst,
dstMac));
@@ -860,10 +870,11 @@ public class IpServerTest {
}
private void verifyNeverTetherOffloadRuleAdd(int upstreamIfindex,
@NonNull final InetAddress dst, @NonNull final MacAddress dstMac) throws Exception {
@NonNull MacAddress upstreamMac, @NonNull final InetAddress dst,
@NonNull final MacAddress dstMac) throws Exception {
if (mBpfDeps.isAtLeastS()) {
verify(mBpfDownstream6Map, never()).updateEntry(
makeDownstream6Key(upstreamIfindex, dst),
makeDownstream6Key(upstreamIfindex, upstreamMac, dst),
makeDownstream6Value(dstMac));
} else {
verify(mNetd, never()).tetherOffloadRuleAdd(matches(upstreamIfindex, dst, dstMac));
@@ -879,10 +890,11 @@ public class IpServerTest {
}
private void verifyTetherOffloadRuleRemove(@Nullable InOrder inOrder, int upstreamIfindex,
@NonNull final InetAddress dst, @NonNull final MacAddress dstMac) throws Exception {
@NonNull MacAddress upstreamMac, @NonNull final InetAddress dst,
@NonNull final MacAddress dstMac) throws Exception {
if (mBpfDeps.isAtLeastS()) {
verifyWithOrder(inOrder, mBpfDownstream6Map).deleteEntry(makeDownstream6Key(
upstreamIfindex, dst));
upstreamIfindex, upstreamMac, dst));
} else {
// |dstMac| is not required for deleting rules. Used bacause tetherOffloadRuleRemove
// uses a whole rule to be a argument.
@@ -903,7 +915,8 @@ public class IpServerTest {
private void verifyStartUpstreamIpv6Forwarding(@Nullable InOrder inOrder, int upstreamIfindex)
throws Exception {
if (!mBpfDeps.isAtLeastS()) return;
final TetherUpstream6Key key = new TetherUpstream6Key(TEST_IFACE_PARAMS.index);
final TetherUpstream6Key key = new TetherUpstream6Key(TEST_IFACE_PARAMS.index,
TEST_IFACE_PARAMS.macAddr);
final Tether6Value value = new Tether6Value(upstreamIfindex,
MacAddress.ALL_ZEROS_ADDRESS, MacAddress.ALL_ZEROS_ADDRESS,
ETH_P_IPV6, NetworkStackConstants.ETHER_MTU);
@@ -913,7 +926,8 @@ public class IpServerTest {
private void verifyStopUpstreamIpv6Forwarding(@Nullable InOrder inOrder)
throws Exception {
if (!mBpfDeps.isAtLeastS()) return;
final TetherUpstream6Key key = new TetherUpstream6Key(TEST_IFACE_PARAMS.index);
final TetherUpstream6Key key = new TetherUpstream6Key(TEST_IFACE_PARAMS.index,
TEST_IFACE_PARAMS.macAddr);
verifyWithOrder(inOrder, mBpfUpstream6Map).deleteEntry(key);
}
@@ -983,14 +997,16 @@ public class IpServerTest {
recvNewNeigh(myIfindex, neighA, NUD_REACHABLE, macA);
verify(mBpfCoordinator).tetherOffloadRuleAdd(
mIpServer, makeForwardingRule(UPSTREAM_IFINDEX, neighA, macA));
verifyTetherOffloadRuleAdd(null, 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));
verifyTetherOffloadRuleAdd(null, UPSTREAM_IFINDEX, neighB, macB);
verifyTetherOffloadRuleAdd(null,
UPSTREAM_IFINDEX, UPSTREAM_IFACE_PARAMS.macAddr, neighB, macB);
verifyNoUpstreamIpv6ForwardingChange(null);
resetNetdBpfMapAndCoordinator();
@@ -1005,7 +1021,8 @@ public class IpServerTest {
recvNewNeigh(myIfindex, neighA, NUD_FAILED, null);
verify(mBpfCoordinator).tetherOffloadRuleRemove(
mIpServer, makeForwardingRule(UPSTREAM_IFINDEX, neighA, macNull));
verifyTetherOffloadRuleRemove(null, UPSTREAM_IFINDEX, neighA, macNull);
verifyTetherOffloadRuleRemove(null,
UPSTREAM_IFINDEX, UPSTREAM_IFACE_PARAMS.macAddr, neighA, macNull);
verifyNoUpstreamIpv6ForwardingChange(null);
resetNetdBpfMapAndCoordinator();
@@ -1013,7 +1030,8 @@ public class IpServerTest {
recvDelNeigh(myIfindex, neighB, NUD_STALE, macB);
verify(mBpfCoordinator).tetherOffloadRuleRemove(
mIpServer, makeForwardingRule(UPSTREAM_IFINDEX, neighB, macNull));
verifyTetherOffloadRuleRemove(null, UPSTREAM_IFINDEX, neighB, macNull);
verifyTetherOffloadRuleRemove(null,
UPSTREAM_IFINDEX, UPSTREAM_IFACE_PARAMS.macAddr, neighB, macNull);
verifyStopUpstreamIpv6Forwarding(null);
resetNetdBpfMapAndCoordinator();
@@ -1028,12 +1046,16 @@ public class IpServerTest {
lp.setInterfaceName(UPSTREAM_IFACE2);
dispatchTetherConnectionChanged(UPSTREAM_IFACE2, lp, -1);
verify(mBpfCoordinator).tetherOffloadRuleUpdate(mIpServer, UPSTREAM_IFINDEX2);
verifyTetherOffloadRuleRemove(inOrder, UPSTREAM_IFINDEX, neighA, macA);
verifyTetherOffloadRuleRemove(inOrder, UPSTREAM_IFINDEX, neighB, macB);
verifyTetherOffloadRuleRemove(inOrder,
UPSTREAM_IFINDEX, UPSTREAM_IFACE_PARAMS.macAddr, neighA, macA);
verifyTetherOffloadRuleRemove(inOrder,
UPSTREAM_IFINDEX, UPSTREAM_IFACE_PARAMS.macAddr, neighB, macB);
verifyStopUpstreamIpv6Forwarding(inOrder);
verifyTetherOffloadRuleAdd(inOrder, UPSTREAM_IFINDEX2, neighA, macA);
verifyTetherOffloadRuleAdd(inOrder,
UPSTREAM_IFINDEX2, UPSTREAM_IFACE_PARAMS2.macAddr, neighA, macA);
verifyStartUpstreamIpv6Forwarding(inOrder, UPSTREAM_IFINDEX2);
verifyTetherOffloadRuleAdd(inOrder, UPSTREAM_IFINDEX2, neighB, macB);
verifyTetherOffloadRuleAdd(inOrder,
UPSTREAM_IFINDEX2, UPSTREAM_IFACE_PARAMS2.macAddr, neighB, macB);
verifyNoUpstreamIpv6ForwardingChange(inOrder);
resetNetdBpfMapAndCoordinator();
@@ -1044,8 +1066,10 @@ public class IpServerTest {
// - processMessage CMD_IPV6_TETHER_UPDATE for the IPv6 upstream is lost.
// See dispatchTetherConnectionChanged.
verify(mBpfCoordinator, times(2)).tetherOffloadRuleClear(mIpServer);
verifyTetherOffloadRuleRemove(null, UPSTREAM_IFINDEX2, neighA, macA);
verifyTetherOffloadRuleRemove(null, UPSTREAM_IFINDEX2, neighB, macB);
verifyTetherOffloadRuleRemove(null,
UPSTREAM_IFINDEX2, UPSTREAM_IFACE_PARAMS2.macAddr, neighA, macA);
verifyTetherOffloadRuleRemove(null,
UPSTREAM_IFINDEX2, UPSTREAM_IFACE_PARAMS2.macAddr, neighB, macB);
verifyStopUpstreamIpv6Forwarding(inOrder);
resetNetdBpfMapAndCoordinator();
@@ -1064,17 +1088,20 @@ public class IpServerTest {
recvNewNeigh(myIfindex, neighB, NUD_REACHABLE, macB);
verify(mBpfCoordinator).tetherOffloadRuleAdd(
mIpServer, makeForwardingRule(UPSTREAM_IFINDEX, neighB, macB));
verifyTetherOffloadRuleAdd(null, 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));
verifyNeverTetherOffloadRuleAdd(UPSTREAM_IFINDEX, neighA, macA);
verifyNeverTetherOffloadRuleAdd(
UPSTREAM_IFINDEX, UPSTREAM_IFACE_PARAMS.macAddr, neighA, macA);
// If upstream IPv6 connectivity is lost, rules are removed.
resetNetdBpfMapAndCoordinator();
dispatchTetherConnectionChanged(UPSTREAM_IFACE, null, 0);
verify(mBpfCoordinator).tetherOffloadRuleClear(mIpServer);
verifyTetherOffloadRuleRemove(null, UPSTREAM_IFINDEX, neighB, macB);
verifyTetherOffloadRuleRemove(null,
UPSTREAM_IFINDEX, UPSTREAM_IFACE_PARAMS.macAddr, neighB, macB);
verifyStopUpstreamIpv6Forwarding(null);
// When the interface goes down, rules are removed.
@@ -1084,18 +1111,22 @@ public class IpServerTest {
recvNewNeigh(myIfindex, neighB, NUD_REACHABLE, macB);
verify(mBpfCoordinator).tetherOffloadRuleAdd(
mIpServer, makeForwardingRule(UPSTREAM_IFINDEX, neighA, macA));
verifyTetherOffloadRuleAdd(null, 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));
verifyTetherOffloadRuleAdd(null, UPSTREAM_IFINDEX, neighB, macB);
verifyTetherOffloadRuleAdd(null,
UPSTREAM_IFINDEX, UPSTREAM_IFACE_PARAMS.macAddr, neighB, macB);
resetNetdBpfMapAndCoordinator();
mIpServer.stop();
mLooper.dispatchAll();
verify(mBpfCoordinator).tetherOffloadRuleClear(mIpServer);
verifyTetherOffloadRuleRemove(null, UPSTREAM_IFINDEX, neighA, macA);
verifyTetherOffloadRuleRemove(null, UPSTREAM_IFINDEX, neighB, macB);
verifyTetherOffloadRuleRemove(null,
UPSTREAM_IFINDEX, UPSTREAM_IFACE_PARAMS.macAddr, neighA, macA);
verifyTetherOffloadRuleRemove(null,
UPSTREAM_IFINDEX, UPSTREAM_IFACE_PARAMS.macAddr, neighB, macB);
verifyStopUpstreamIpv6Forwarding(null);
verify(mIpNeighborMonitor).stop();
resetNetdBpfMapAndCoordinator();
@@ -1124,14 +1155,16 @@ public class IpServerTest {
recvNewNeigh(myIfindex, neigh, NUD_REACHABLE, macA);
verify(mBpfCoordinator).tetherOffloadRuleAdd(
mIpServer, makeForwardingRule(UPSTREAM_IFINDEX, neigh, macA));
verifyTetherOffloadRuleAdd(null, 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));
verifyTetherOffloadRuleRemove(null, UPSTREAM_IFINDEX, neigh, macNull);
verifyTetherOffloadRuleRemove(null,
UPSTREAM_IFINDEX, UPSTREAM_IFACE_PARAMS.macAddr, neigh, macNull);
verifyStopUpstreamIpv6Forwarding(null);
resetNetdBpfMapAndCoordinator();

View File

@@ -109,7 +109,7 @@ public class BpfCoordinatorTest {
public final DevSdkIgnoreRule mIgnoreRule = new DevSdkIgnoreRule();
private static final int DOWNSTREAM_IFINDEX = 10;
private static final MacAddress DOWNSTREAM_MAC = MacAddress.ALL_ZEROS_ADDRESS;
private static final MacAddress DOWNSTREAM_MAC = MacAddress.fromString("12:34:56:78:90:ab");
private static final InetAddress NEIGH_A = InetAddresses.parseNumericAddress("2001:db8::1");
private static final InetAddress NEIGH_B = InetAddresses.parseNumericAddress("2001:db8::2");
private static final MacAddress MAC_A = MacAddress.fromString("00:00:00:00:00:0a");
@@ -383,19 +383,20 @@ public class BpfCoordinatorTest {
}
private void verifyStartUpstreamIpv6Forwarding(@Nullable InOrder inOrder, int downstreamIfIndex,
int upstreamIfindex) throws Exception {
MacAddress downstreamMac, int upstreamIfindex) throws Exception {
if (!mDeps.isAtLeastS()) return;
final TetherUpstream6Key key = new TetherUpstream6Key(downstreamIfIndex);
final TetherUpstream6Key key = new TetherUpstream6Key(downstreamIfIndex, downstreamMac);
final Tether6Value value = new Tether6Value(upstreamIfindex,
MacAddress.ALL_ZEROS_ADDRESS, MacAddress.ALL_ZEROS_ADDRESS,
ETH_P_IPV6, NetworkStackConstants.ETHER_MTU);
verifyWithOrder(inOrder, mBpfUpstream6Map).insertEntry(key, value);
}
private void verifyStopUpstreamIpv6Forwarding(@Nullable InOrder inOrder, int downstreamIfIndex)
private void verifyStopUpstreamIpv6Forwarding(@Nullable InOrder inOrder, int downstreamIfIndex,
MacAddress downstreamMac)
throws Exception {
if (!mDeps.isAtLeastS()) return;
final TetherUpstream6Key key = new TetherUpstream6Key(downstreamIfIndex);
final TetherUpstream6Key key = new TetherUpstream6Key(downstreamIfIndex, downstreamMac);
verifyWithOrder(inOrder, mBpfUpstream6Map).deleteEntry(key);
}
@@ -732,9 +733,10 @@ public class BpfCoordinatorTest {
final TetherDownstream6Key key = rule.makeTetherDownstream6Key();
assertEquals(key.iif, (long) mobileIfIndex);
assertEquals(key.dstMac, MacAddress.ALL_ZEROS_ADDRESS); // rawip upstream
assertTrue(Arrays.equals(key.neigh6, NEIGH_A.getAddress()));
// iif (4) + neigh6 (16) = 20.
assertEquals(20, key.writeToBytes().length);
// iif (4) + dstMac(6) + padding(2) + neigh6 (16) = 28.
assertEquals(28, key.writeToBytes().length);
}
@Test
@@ -875,7 +877,7 @@ public class BpfCoordinatorTest {
verifyTetherOffloadRuleAdd(inOrder, ethernetRuleA);
verifyTetherOffloadSetInterfaceQuota(inOrder, ethIfIndex, QUOTA_UNLIMITED,
true /* isInit */);
verifyStartUpstreamIpv6Forwarding(inOrder, DOWNSTREAM_IFINDEX, ethIfIndex);
verifyStartUpstreamIpv6Forwarding(inOrder, DOWNSTREAM_IFINDEX, DOWNSTREAM_MAC, ethIfIndex);
coordinator.tetherOffloadRuleAdd(mIpServer, ethernetRuleB);
verifyTetherOffloadRuleAdd(inOrder, ethernetRuleB);
@@ -892,12 +894,13 @@ public class BpfCoordinatorTest {
coordinator.tetherOffloadRuleUpdate(mIpServer, mobileIfIndex);
verifyTetherOffloadRuleRemove(inOrder, ethernetRuleA);
verifyTetherOffloadRuleRemove(inOrder, ethernetRuleB);
verifyStopUpstreamIpv6Forwarding(inOrder, DOWNSTREAM_IFINDEX);
verifyStopUpstreamIpv6Forwarding(inOrder, DOWNSTREAM_IFINDEX, DOWNSTREAM_MAC);
verifyTetherOffloadGetAndClearStats(inOrder, ethIfIndex);
verifyTetherOffloadRuleAdd(inOrder, mobileRuleA);
verifyTetherOffloadSetInterfaceQuota(inOrder, mobileIfIndex, QUOTA_UNLIMITED,
true /* isInit */);
verifyStartUpstreamIpv6Forwarding(inOrder, DOWNSTREAM_IFINDEX, mobileIfIndex);
verifyStartUpstreamIpv6Forwarding(inOrder, DOWNSTREAM_IFINDEX, DOWNSTREAM_MAC,
mobileIfIndex);
verifyTetherOffloadRuleAdd(inOrder, mobileRuleB);
// [3] Clear all rules for a given IpServer.
@@ -906,7 +909,7 @@ public class BpfCoordinatorTest {
coordinator.tetherOffloadRuleClear(mIpServer);
verifyTetherOffloadRuleRemove(inOrder, mobileRuleA);
verifyTetherOffloadRuleRemove(inOrder, mobileRuleB);
verifyStopUpstreamIpv6Forwarding(inOrder, DOWNSTREAM_IFINDEX);
verifyStopUpstreamIpv6Forwarding(inOrder, DOWNSTREAM_IFINDEX, DOWNSTREAM_MAC);
verifyTetherOffloadGetAndClearStats(inOrder, mobileIfIndex);
// [4] Force pushing stats update to verify that the last diff of stats is reported on all

View File

@@ -334,13 +334,14 @@ public class TetheringTest {
assertTrue("Non-mocked interface " + ifName,
ifName.equals(TEST_USB_IFNAME)
|| ifName.equals(TEST_WLAN_IFNAME)
|| ifName.equals(TEST_WIFI_IFNAME)
|| ifName.equals(TEST_MOBILE_IFNAME)
|| ifName.equals(TEST_P2P_IFNAME)
|| ifName.equals(TEST_NCM_IFNAME)
|| ifName.equals(TEST_ETH_IFNAME));
final String[] ifaces = new String[] {
TEST_USB_IFNAME, TEST_WLAN_IFNAME, TEST_MOBILE_IFNAME, TEST_P2P_IFNAME,
TEST_NCM_IFNAME, TEST_ETH_IFNAME};
TEST_USB_IFNAME, TEST_WLAN_IFNAME, TEST_WIFI_IFNAME, TEST_MOBILE_IFNAME,
TEST_P2P_IFNAME, TEST_NCM_IFNAME, TEST_ETH_IFNAME};
return new InterfaceParams(ifName, ArrayUtils.indexOf(ifaces, ifName) + IFINDEX_OFFSET,
MacAddress.ALL_ZEROS_ADDRESS);
}