bpf tethering offload - add src subnet to upstream ipv6 direction

This patch is based on aosp/2535559 from maze@.

Add source prefix into the upstream key such that only packets which
source IPv6 address matches it will be forwarded to the upstream
interface.

In this patch, the source prefix is set to zero so there is no
behavior changes. Next CL in patch series will use the real source
prefixes retrieved from upstream interface.

Test: atest TetheringTests
Bug: 261923493
Change-Id: I43d068a29b937c7dfeb6fab632a8effb47ee2263
This commit is contained in:
KH Shi
2023-08-08 15:30:45 +08:00
parent cf0cc72629
commit c8fb1a2530
9 changed files with 55 additions and 26 deletions

View File

@@ -17,6 +17,7 @@
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;
@@ -81,14 +82,14 @@ public class BpfCoordinatorShimImpl
@Override
public boolean startUpstreamIpv6Forwarding(int downstreamIfindex, int upstreamIfindex,
@NonNull MacAddress inDstMac, @NonNull MacAddress outSrcMac,
@NonNull MacAddress outDstMac, int mtu) {
@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 MacAddress inDstMac) {
public boolean stopUpstreamIpv6Forwarding(int downstreamIfindex, int upstreamIfindex,
@NonNull IpPrefix sourcePrefix, @NonNull MacAddress inDstMac) {
return true;
}

View File

@@ -17,7 +17,9 @@
package com.android.networkstack.tethering.apishim.api31;
import static android.net.netstats.provider.NetworkStatsProvider.QUOTA_UNLIMITED;
import static android.net.util.NetworkConstants.RFC7421_PREFIX_LENGTH;
import android.net.IpPrefix;
import android.net.MacAddress;
import android.system.ErrnoException;
import android.system.Os;
@@ -48,6 +50,9 @@ 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.
@@ -196,13 +201,23 @@ 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 MacAddress inDstMac, @NonNull MacAddress outSrcMac,
@NonNull MacAddress outDstMac, int mtu) {
@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 = new TetherUpstream6Key(downstreamIfindex, inDstMac);
final TetherUpstream6Key key = makeUpstream6Key(downstreamIfindex, inDstMac, sourcePrefix);
final Tether6Value value = new Tether6Value(upstreamIfindex, outSrcMac,
outDstMac, OsConstants.ETH_P_IPV6, mtu);
try {
@@ -216,10 +231,12 @@ public class BpfCoordinatorShimImpl
@Override
public boolean stopUpstreamIpv6Forwarding(int downstreamIfindex, int upstreamIfindex,
@NonNull MacAddress inDstMac) {
@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 = new TetherUpstream6Key(downstreamIfindex, inDstMac);
final TetherUpstream6Key key = makeUpstream6Key(downstreamIfindex, inDstMac, sourcePrefix);
try {
mBpfUpstream6Map.deleteEntry(key);
} catch (ErrnoException e) {

View File

@@ -16,6 +16,7 @@
package com.android.networkstack.tethering.apishim.common;
import android.net.IpPrefix;
import android.net.MacAddress;
import android.util.SparseArray;
@@ -79,25 +80,27 @@ public abstract class BpfCoordinatorShim {
* @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 MacAddress inDstMac, @NonNull MacAddress outSrcMac,
@NonNull MacAddress outDstMac, int mtu);
@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 MacAddress inDstMac);
public abstract boolean stopUpstreamIpv6Forwarding(int downstreamIfindex, int upstreamIfindex,
@NonNull IpPrefix sourcePrefix, @NonNull MacAddress inDstMac);
/**
* Return BPF tethering offload statistics.

View File

@@ -37,6 +37,7 @@ import static com.android.networkstack.tethering.util.TetheringUtils.getTetherin
import android.app.usage.NetworkStatsManager;
import android.net.INetd;
import android.net.IpPrefix;
import android.net.LinkProperties;
import android.net.MacAddress;
import android.net.NetworkStats;
@@ -119,6 +120,7 @@ public class BpfCoordinator {
private static final int DUMP_TIMEOUT_MS = 10_000;
private static final MacAddress NULL_MAC_ADDRESS = MacAddress.fromString(
"00:00:00:00:00:00");
private static final IpPrefix IPV6_ZERO_PREFIX64 = new IpPrefix("::/64");
private static final String TETHER_DOWNSTREAM4_MAP_PATH = makeMapPath(DOWNSTREAM, 4);
private static final String TETHER_UPSTREAM4_MAP_PATH = makeMapPath(UPSTREAM, 4);
private static final String TETHER_DOWNSTREAM6_FS_PATH = makeMapPath(DOWNSTREAM, 6);
@@ -615,8 +617,9 @@ public class BpfCoordinator {
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, rule.srcMac,
NULL_MAC_ADDRESS, NULL_MAC_ADDRESS, NetworkStackConstants.ETHER_MTU)) {
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));
}
@@ -657,7 +660,7 @@ public class BpfCoordinator {
final int downstream = rule.downstreamIfindex;
final int upstream = rule.upstreamIfindex;
if (!mBpfCoordinatorShim.stopUpstreamIpv6Forwarding(downstream, upstream,
rule.srcMac)) {
IPV6_ZERO_PREFIX64, rule.srcMac)) {
mLog.e("Failed to disable upstream IPv6 forwarding from "
+ getIfName(downstream) + " to " + getIfName(upstream));
}

View File

@@ -29,13 +29,17 @@ public class TetherUpstream6Key extends Struct {
@Field(order = 0, type = Type.S32)
public final int iif; // The input interface index.
@Field(order = 1, type = Type.EUI48, padding = 2)
@Field(order = 1, type = Type.EUI48, padding = 6)
public final MacAddress dstMac; // Destination ethernet mac address (zeroed iff rawip ingress).
public TetherUpstream6Key(int iif, @NonNull final MacAddress dstMac) {
@Field(order = 2, type = Type.S64)
public final long src64; // The top 64-bits of the source ip.
public TetherUpstream6Key(int iif, @NonNull final MacAddress dstMac, long src64) {
Objects.requireNonNull(dstMac);
this.iif = iif;
this.dstMac = dstMac;
this.src64 = src64;
}
}

View File

@@ -985,7 +985,7 @@ public class IpServerTest {
throws Exception {
if (!mBpfDeps.isAtLeastS()) return;
final TetherUpstream6Key key = new TetherUpstream6Key(TEST_IFACE_PARAMS.index,
TEST_IFACE_PARAMS.macAddr);
TEST_IFACE_PARAMS.macAddr, 0);
final Tether6Value value = new Tether6Value(upstreamIfindex,
MacAddress.ALL_ZEROS_ADDRESS, MacAddress.ALL_ZEROS_ADDRESS,
ETH_P_IPV6, NetworkStackConstants.ETHER_MTU);
@@ -996,7 +996,7 @@ public class IpServerTest {
throws Exception {
if (!mBpfDeps.isAtLeastS()) return;
final TetherUpstream6Key key = new TetherUpstream6Key(TEST_IFACE_PARAMS.index,
TEST_IFACE_PARAMS.macAddr);
TEST_IFACE_PARAMS.macAddr, 0);
verifyWithOrder(inOrder, mBpfUpstream6Map).deleteEntry(key);
}

View File

@@ -641,7 +641,7 @@ public class BpfCoordinatorTest {
private void verifyStartUpstreamIpv6Forwarding(@Nullable InOrder inOrder, int downstreamIfIndex,
MacAddress downstreamMac, int upstreamIfindex) throws Exception {
if (!mDeps.isAtLeastS()) return;
final TetherUpstream6Key key = new TetherUpstream6Key(downstreamIfIndex, downstreamMac);
final TetherUpstream6Key key = new TetherUpstream6Key(downstreamIfIndex, downstreamMac, 0);
final Tether6Value value = new Tether6Value(upstreamIfindex,
MacAddress.ALL_ZEROS_ADDRESS, MacAddress.ALL_ZEROS_ADDRESS,
ETH_P_IPV6, NetworkStackConstants.ETHER_MTU);
@@ -652,7 +652,7 @@ public class BpfCoordinatorTest {
MacAddress downstreamMac)
throws Exception {
if (!mDeps.isAtLeastS()) return;
final TetherUpstream6Key key = new TetherUpstream6Key(downstreamIfIndex, downstreamMac);
final TetherUpstream6Key key = new TetherUpstream6Key(downstreamIfIndex, downstreamMac, 0);
verifyWithOrder(inOrder, mBpfUpstream6Map).deleteEntry(key);
}
@@ -2192,7 +2192,7 @@ public class BpfCoordinatorTest {
mBpfDownstream6Map.insertEntry(rule.makeTetherDownstream6Key(), rule.makeTether6Value());
final TetherUpstream6Key upstream6Key = new TetherUpstream6Key(DOWNSTREAM_IFINDEX,
DOWNSTREAM_MAC);
DOWNSTREAM_MAC, 0);
final Tether6Value upstream6Value = new Tether6Value(UPSTREAM_IFINDEX,
MacAddress.ALL_ZEROS_ADDRESS, MacAddress.ALL_ZEROS_ADDRESS,
ETH_P_IPV6, NetworkStackConstants.ETHER_MTU);

View File

@@ -194,6 +194,7 @@ static inline __always_inline int do_forward6(struct __sk_buff* skb, const bool
TetherUpstream6Key ku = {
.iif = skb->ifindex,
.src64 = 0,
};
if (is_ethernet) __builtin_memcpy(downstream ? kd.dstMac : ku.dstMac, eth->h_dest, ETH_ALEN);

View File

@@ -135,10 +135,10 @@ STRUCT_SIZE(TetherDownstream64Value, 4 + 14 + 2 + 4 + 4 + 2 + 2 + 8); // 40
typedef struct {
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
uint8_t zero[6]; // zero pad for 8 byte alignment
uint64_t src64; // Top 64-bits of the src ip
} TetherUpstream6Key;
STRUCT_SIZE(TetherUpstream6Key, 12);
STRUCT_SIZE(TetherUpstream6Key, 4 + 6 + 6 + 8); // 24
typedef struct {
uint32_t iif; // The input interface index