diff --git a/Tethering/apishim/31/com/android/networkstack/tethering/apishim/api31/BpfCoordinatorShimImpl.java b/Tethering/apishim/31/com/android/networkstack/tethering/apishim/api31/BpfCoordinatorShimImpl.java index 389ba7b7a8..091c4831e2 100644 --- a/Tethering/apishim/31/com/android/networkstack/tethering/apishim/api31/BpfCoordinatorShimImpl.java +++ b/Tethering/apishim/31/com/android/networkstack/tethering/apishim/api31/BpfCoordinatorShimImpl.java @@ -32,8 +32,8 @@ import com.android.networkstack.tethering.BpfCoordinator.Ipv6ForwardingRule; import com.android.networkstack.tethering.BpfMap; import com.android.networkstack.tethering.Tether4Key; import com.android.networkstack.tethering.Tether4Value; +import com.android.networkstack.tethering.Tether6Value; import com.android.networkstack.tethering.TetherDownstream6Key; -import com.android.networkstack.tethering.TetherDownstream6Value; import com.android.networkstack.tethering.TetherLimitKey; import com.android.networkstack.tethering.TetherLimitValue; import com.android.networkstack.tethering.TetherStatsKey; @@ -56,20 +56,17 @@ public class BpfCoordinatorShimImpl @NonNull private final SharedLog mLog; - // BPF map of ingress queueing discipline which pre-processes the packets by the IPv4 - // downstream rules. + // BPF map for downstream IPv4 forwarding. @Nullable private final BpfMap mBpfDownstream4Map; - // BPF map of ingress queueing discipline which pre-processes the packets by the IPv4 - // upstream rules. + // BPF map for downstream IPv4 forwarding. @Nullable private final BpfMap mBpfUpstream4Map; - // BPF map of ingress queueing discipline which pre-processes the packets by the IPv6 - // forwarding rules. + // BPF map for downstream IPv6 forwarding. @Nullable - private final BpfMap mBpfDownstream6Map; + private final BpfMap mBpfDownstream6Map; // BPF map of tethering statistics of the upstream interface since tethering startup. @Nullable @@ -99,7 +96,7 @@ public class BpfCoordinatorShimImpl if (!isInitialized()) return false; final TetherDownstream6Key key = rule.makeTetherDownstream6Key(); - final TetherDownstream6Value value = rule.makeTetherDownstream6Value(); + final Tether6Value value = rule.makeTether6Value(); try { mBpfDownstream6Map.updateEntry(key, value); diff --git a/Tethering/src/com/android/networkstack/tethering/BpfCoordinator.java b/Tethering/src/com/android/networkstack/tethering/BpfCoordinator.java index ffb45570a7..911f83f75c 100644 --- a/Tethering/src/com/android/networkstack/tethering/BpfCoordinator.java +++ b/Tethering/src/com/android/networkstack/tethering/BpfCoordinator.java @@ -83,20 +83,28 @@ import java.util.Set; * @hide */ public class BpfCoordinator { + static final boolean DOWNSTREAM = true; + static final boolean UPSTREAM = false; + private static final String TAG = BpfCoordinator.class.getSimpleName(); 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 String TETHER_DOWNSTREAM4_MAP_PATH = - "/sys/fs/bpf/tethering/map_offload_tether_downstream4_map"; - private static final String TETHER_UPSTREAM4_MAP_PATH = - "/sys/fs/bpf/tethering/map_offload_tether_upstream4_map"; - private static final String TETHER_DOWNSTREAM6_FS_PATH = - "/sys/fs/bpf/tethering/map_offload_tether_downstream6_map"; - private static final String TETHER_STATS_MAP_PATH = - "/sys/fs/bpf/tethering/map_offload_tether_stats_map"; - private static final String TETHER_LIMIT_MAP_PATH = - "/sys/fs/bpf/tethering/map_offload_tether_limit_map"; + 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); + private static final String TETHER_UPSTREAM6_FS_PATH = makeMapPath(UPSTREAM, 6); + private static final String TETHER_STATS_MAP_PATH = makeMapPath("stats"); + private static final String TETHER_LIMIT_MAP_PATH = makeMapPath("limit"); + + private static String makeMapPath(String which) { + return "/sys/fs/bpf/tethering/map_offload_tether_" + which + "_map"; + } + + private static String makeMapPath(boolean downstream, int ipVersion) { + return makeMapPath((downstream ? "downstream" : "upstream") + ipVersion); + } + @VisibleForTesting enum StatsType { @@ -256,16 +264,16 @@ public class BpfCoordinator { BpfMap.BPF_F_RDWR, Tether4Key.class, Tether4Value.class); } catch (ErrnoException e) { Log.e(TAG, "Cannot create upstream4 map: " + e); - return null; } + return null; } /** Get downstream6 BPF map. */ - @Nullable public BpfMap + @Nullable public BpfMap getBpfDownstream6Map() { try { return new BpfMap<>(TETHER_DOWNSTREAM6_FS_PATH, - BpfMap.BPF_F_RDWR, TetherDownstream6Key.class, TetherDownstream6Value.class); + BpfMap.BPF_F_RDWR, TetherDownstream6Key.class, Tether6Value.class); } catch (ErrnoException e) { Log.e(TAG, "Cannot create downstream6 map: " + e); return null; @@ -755,11 +763,11 @@ public class BpfCoordinator { } /** - * Return a TetherDownstream6Value object built from the rule. + * Return a Tether6Value object built from the rule. */ @NonNull - public TetherDownstream6Value makeTetherDownstream6Value() { - return new TetherDownstream6Value(downstreamIfindex, dstMac, srcMac, ETH_P_IPV6, + public Tether6Value makeTether6Value() { + return new Tether6Value(downstreamIfindex, dstMac, srcMac, ETH_P_IPV6, NetworkStackConstants.ETHER_MTU); } diff --git a/Tethering/src/com/android/networkstack/tethering/Tether4Key.java b/Tethering/src/com/android/networkstack/tethering/Tether4Key.java index 5884dceaee..58415caef8 100644 --- a/Tethering/src/com/android/networkstack/tethering/Tether4Key.java +++ b/Tethering/src/com/android/networkstack/tethering/Tether4Key.java @@ -28,7 +28,7 @@ import java.net.Inet4Address; import java.net.UnknownHostException; import java.util.Objects; -/** The key of BpfMap which is used for IPv4 bpf offload. */ +/** Key type for upstream IPv4 forwarding map. */ public class Tether4Key extends Struct { @Field(order = 0, type = Type.U32) public final long iif; diff --git a/Tethering/src/com/android/networkstack/tethering/Tether4Value.java b/Tethering/src/com/android/networkstack/tethering/Tether4Value.java index 3770f1ad6b..8084c05ea8 100644 --- a/Tethering/src/com/android/networkstack/tethering/Tether4Value.java +++ b/Tethering/src/com/android/networkstack/tethering/Tether4Value.java @@ -28,7 +28,7 @@ import java.net.InetAddress; import java.net.UnknownHostException; import java.util.Objects; -/** The value of BpfMap which is used for IPv4 bpf offload. */ +/** Value type for upstream IPv4 forwarding map. */ public class Tether4Value extends Struct { @Field(order = 0, type = Type.U32) public final long oif; diff --git a/Tethering/src/com/android/networkstack/tethering/TetherDownstream6Value.java b/Tethering/src/com/android/networkstack/tethering/Tether6Value.java similarity index 66% rename from Tethering/src/com/android/networkstack/tethering/TetherDownstream6Value.java rename to Tethering/src/com/android/networkstack/tethering/Tether6Value.java index a56269dad7..b3107fdd74 100644 --- a/Tethering/src/com/android/networkstack/tethering/TetherDownstream6Value.java +++ b/Tethering/src/com/android/networkstack/tethering/Tether6Value.java @@ -21,15 +21,13 @@ 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; import java.util.Objects; -/** The value of BpfMap which is used for bpf offload. */ -public class TetherDownstream6Value extends Struct { - @Field(order = 0, type = Type.U32) - public final long oif; // The output interface index. +/** Value type for downstream and upstream IPv6 forwarding maps. */ +public class Tether6Value extends Struct { + @Field(order = 0, type = Type.S32) + public final int oif; // The output interface index. // The ethhdr struct which is defined in uapi/linux/if_ether.h @Field(order = 1, type = Type.EUI48) @@ -42,7 +40,7 @@ public class TetherDownstream6Value extends Struct { @Field(order = 4, type = Type.U16) public final int pmtu; // The maximum L3 output path/route mtu. - public TetherDownstream6Value(final long oif, @NonNull final MacAddress ethDstMac, + public Tether6Value(final int oif, @NonNull final MacAddress ethDstMac, @NonNull final MacAddress ethSrcMac, final int ethProto, final int pmtu) { Objects.requireNonNull(ethSrcMac); Objects.requireNonNull(ethDstMac); @@ -54,24 +52,6 @@ public class TetherDownstream6Value extends Struct { this.pmtu = pmtu; } - @Override - public boolean equals(Object obj) { - if (this == obj) return true; - - if (!(obj instanceof TetherDownstream6Value)) return false; - - final TetherDownstream6Value that = (TetherDownstream6Value) obj; - - return oif == that.oif && ethDstMac.equals(that.ethDstMac) - && ethSrcMac.equals(that.ethSrcMac) && ethProto == that.ethProto - && pmtu == that.pmtu; - } - - @Override - public int hashCode() { - return Objects.hash(oif, ethDstMac, ethSrcMac, ethProto, pmtu); - } - @Override public String toString() { return String.format("oif: %d, dstMac: %s, srcMac: %s, proto: %d, pmtu: %d", oif, diff --git a/Tethering/tests/privileged/src/com/android/networkstack/tethering/BpfMapTest.java b/Tethering/tests/privileged/src/com/android/networkstack/tethering/BpfMapTest.java index 5520f3091f..6edfc477a2 100644 --- a/Tethering/tests/privileged/src/com/android/networkstack/tethering/BpfMapTest.java +++ b/Tethering/tests/privileged/src/com/android/networkstack/tethering/BpfMapTest.java @@ -54,7 +54,7 @@ public final class BpfMapTest { private static final String TETHER_DOWNSTREAM6_FS_PATH = "/sys/fs/bpf/tethering/map_test_tether_downstream6_map"; - private ArrayMap mTestData; + private ArrayMap mTestData; @BeforeClass public static void setupOnce() { @@ -71,13 +71,13 @@ public final class BpfMapTest { mTestData = new ArrayMap<>(); mTestData.put(createTetherDownstream6Key(101, "2001:db8::1"), - createTetherDownstream6Value(11, "00:00:00:00:00:0a", "11:11:11:00:00:0b", + 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"), - createTetherDownstream6Value(22, "00:00:00:00:00:0c", "22:22:22:00:00:0d", + 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"), - createTetherDownstream6Value(33, "00:00:00:00:00:0e", "33:33:33:00:00:0f", + createTether6Value(33, "00:00:00:00:00:0e", "33:33:33:00:00:0f", ETH_P_IPV6, 1500)); } @@ -86,14 +86,14 @@ public final class BpfMapTest { cleanTestMap(); } - private BpfMap getTestMap() throws Exception { + private BpfMap getTestMap() throws Exception { return new BpfMap<>( TETHER_DOWNSTREAM6_FS_PATH, BpfMap.BPF_F_RDWR, - TetherDownstream6Key.class, TetherDownstream6Value.class); + TetherDownstream6Key.class, Tether6Value.class); } private void cleanTestMap() throws Exception { - try (BpfMap bpfMap = getTestMap()) { + try (BpfMap bpfMap = getTestMap()) { bpfMap.forEach((key, value) -> { try { assertTrue(bpfMap.deleteEntry(key)); @@ -112,18 +112,18 @@ public final class BpfMapTest { return new TetherDownstream6Key(iif, ipv6Address.getAddress()); } - private TetherDownstream6Value createTetherDownstream6Value(long oif, String src, String dst, + private Tether6Value createTether6Value(int oif, String src, String dst, int proto, int pmtu) throws Exception { final MacAddress srcMac = MacAddress.fromString(src); final MacAddress dstMac = MacAddress.fromString(dst); - return new TetherDownstream6Value(oif, dstMac, srcMac, proto, pmtu); + return new Tether6Value(oif, dstMac, srcMac, proto, pmtu); } @Test public void testGetFd() throws Exception { try (BpfMap readOnlyMap = new BpfMap<>(TETHER_DOWNSTREAM6_FS_PATH, BpfMap.BPF_F_RDONLY, - TetherDownstream6Key.class, TetherDownstream6Value.class)) { + TetherDownstream6Key.class, Tether6Value.class)) { assertNotNull(readOnlyMap); try { readOnlyMap.insertEntry(mTestData.keyAt(0), mTestData.valueAt(0)); @@ -133,7 +133,7 @@ public final class BpfMapTest { } } try (BpfMap writeOnlyMap = new BpfMap<>(TETHER_DOWNSTREAM6_FS_PATH, BpfMap.BPF_F_WRONLY, - TetherDownstream6Key.class, TetherDownstream6Value.class)) { + TetherDownstream6Key.class, Tether6Value.class)) { assertNotNull(writeOnlyMap); try { writeOnlyMap.getFirstKey(); @@ -143,14 +143,14 @@ public final class BpfMapTest { } } try (BpfMap readWriteMap = new BpfMap<>(TETHER_DOWNSTREAM6_FS_PATH, BpfMap.BPF_F_RDWR, - TetherDownstream6Key.class, TetherDownstream6Value.class)) { + TetherDownstream6Key.class, Tether6Value.class)) { assertNotNull(readWriteMap); } } @Test public void testGetFirstKey() throws Exception { - try (BpfMap bpfMap = getTestMap()) { + try (BpfMap bpfMap = getTestMap()) { // getFirstKey on an empty map returns null. assertFalse(bpfMap.containsKey(mTestData.keyAt(0))); assertNull(bpfMap.getFirstKey()); @@ -164,7 +164,7 @@ public final class BpfMapTest { @Test public void testGetNextKey() throws Exception { - try (BpfMap bpfMap = getTestMap()) { + try (BpfMap bpfMap = getTestMap()) { // [1] If the passed-in key is not found on empty map, return null. final TetherDownstream6Key nonexistentKey = createTetherDownstream6Key(1234, "2001:db8::10"); @@ -177,7 +177,7 @@ public final class BpfMapTest { } catch (NullPointerException expected) { } // The BPF map has one entry now. - final ArrayMap resultMap = + final ArrayMap resultMap = new ArrayMap<>(); bpfMap.insertEntry(mTestData.keyAt(0), mTestData.valueAt(0)); resultMap.put(mTestData.keyAt(0), mTestData.valueAt(0)); @@ -214,23 +214,23 @@ public final class BpfMapTest { @Test public void testUpdateBpfMap() throws Exception { - try (BpfMap bpfMap = getTestMap()) { + try (BpfMap bpfMap = getTestMap()) { final TetherDownstream6Key key = mTestData.keyAt(0); - final TetherDownstream6Value value = mTestData.valueAt(0); - final TetherDownstream6Value value2 = mTestData.valueAt(1); + final Tether6Value value = mTestData.valueAt(0); + final Tether6Value value2 = mTestData.valueAt(1); assertFalse(bpfMap.deleteEntry(key)); // updateEntry will create an entry if it does not exist already. bpfMap.updateEntry(key, value); assertTrue(bpfMap.containsKey(key)); - final TetherDownstream6Value result = bpfMap.getValue(key); + final Tether6Value result = bpfMap.getValue(key); assertEquals(value, result); // updateEntry will update an entry that already exists. bpfMap.updateEntry(key, value2); assertTrue(bpfMap.containsKey(key)); - final TetherDownstream6Value result2 = bpfMap.getValue(key); + final Tether6Value result2 = bpfMap.getValue(key); assertEquals(value2, result2); assertTrue(bpfMap.deleteEntry(key)); @@ -240,11 +240,11 @@ public final class BpfMapTest { @Test public void testInsertReplaceEntry() throws Exception { - try (BpfMap bpfMap = getTestMap()) { + try (BpfMap bpfMap = getTestMap()) { final TetherDownstream6Key key = mTestData.keyAt(0); - final TetherDownstream6Value value = mTestData.valueAt(0); - final TetherDownstream6Value value2 = mTestData.valueAt(1); + final Tether6Value value = mTestData.valueAt(0); + final Tether6Value value2 = mTestData.valueAt(1); try { bpfMap.replaceEntry(key, value); @@ -254,7 +254,7 @@ public final class BpfMapTest { bpfMap.insertEntry(key, value); assertTrue(bpfMap.containsKey(key)); - final TetherDownstream6Value result = bpfMap.getValue(key); + final Tether6Value result = bpfMap.getValue(key); assertEquals(value, result); try { bpfMap.insertEntry(key, value); @@ -263,15 +263,15 @@ public final class BpfMapTest { bpfMap.replaceEntry(key, value2); assertTrue(bpfMap.containsKey(key)); - final TetherDownstream6Value result2 = bpfMap.getValue(key); + final Tether6Value result2 = bpfMap.getValue(key); assertEquals(value2, result2); } } @Test public void testIterateBpfMap() throws Exception { - try (BpfMap bpfMap = getTestMap()) { - final ArrayMap resultMap = + try (BpfMap bpfMap = getTestMap()) { + final ArrayMap resultMap = new ArrayMap<>(mTestData); for (int i = 0; i < resultMap.size(); i++) { @@ -289,7 +289,7 @@ public final class BpfMapTest { @Test public void testIterateEmptyMap() throws Exception { - try (BpfMap bpfMap = getTestMap()) { + try (BpfMap bpfMap = getTestMap()) { // Can't use an int because variables used in a lambda must be final. final AtomicInteger count = new AtomicInteger(); bpfMap.forEach((key, value) -> count.incrementAndGet()); @@ -300,8 +300,8 @@ public final class BpfMapTest { @Test public void testIterateDeletion() throws Exception { - try (BpfMap bpfMap = getTestMap()) { - final ArrayMap resultMap = + try (BpfMap bpfMap = getTestMap()) { + final ArrayMap resultMap = new ArrayMap<>(mTestData); for (int i = 0; i < resultMap.size(); i++) { @@ -329,14 +329,14 @@ public final class BpfMapTest { @Test public void testInsertOverflow() throws Exception { - try (BpfMap bpfMap = getTestMap()) { - final ArrayMap testData = + try (BpfMap bpfMap = getTestMap()) { + final ArrayMap testData = new ArrayMap<>(); // 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"), - createTetherDownstream6Value(100, "de:ad:be:ef:00:01", "de:ad:be:ef:00:02", + createTether6Value(100, "de:ad:be:ef:00:01", "de:ad:be:ef:00:02", ETH_P_IPV6, 1500)); } diff --git a/Tethering/tests/unit/src/android/net/ip/IpServerTest.java b/Tethering/tests/unit/src/android/net/ip/IpServerTest.java index 9223c9b03d..24edf3b03f 100644 --- a/Tethering/tests/unit/src/android/net/ip/IpServerTest.java +++ b/Tethering/tests/unit/src/android/net/ip/IpServerTest.java @@ -106,8 +106,8 @@ import com.android.networkstack.tethering.BpfMap; import com.android.networkstack.tethering.PrivateAddressCoordinator; import com.android.networkstack.tethering.Tether4Key; import com.android.networkstack.tethering.Tether4Value; +import com.android.networkstack.tethering.Tether6Value; import com.android.networkstack.tethering.TetherDownstream6Key; -import com.android.networkstack.tethering.TetherDownstream6Value; import com.android.networkstack.tethering.TetherLimitKey; import com.android.networkstack.tethering.TetherLimitValue; import com.android.networkstack.tethering.TetherStatsKey; @@ -177,7 +177,7 @@ public class IpServerTest { @Mock private ConntrackMonitor mConntrackMonitor; @Mock private BpfMap mBpfDownstream4Map; @Mock private BpfMap mBpfUpstream4Map; - @Mock private BpfMap mBpfDownstream6Map; + @Mock private BpfMap mBpfDownstream6Map; @Mock private BpfMap mBpfStatsMap; @Mock private BpfMap mBpfLimitMap; @@ -319,7 +319,7 @@ public class IpServerTest { } @Nullable - public BpfMap + public BpfMap getBpfDownstream6Map() { return mBpfDownstream6Map; } @@ -800,8 +800,8 @@ public class IpServerTest { } @NonNull - private static TetherDownstream6Value makeDownstream6Value(@NonNull final MacAddress dstMac) { - return new TetherDownstream6Value(TEST_IFACE_PARAMS.index, dstMac, + private static Tether6Value makeDownstream6Value(@NonNull final MacAddress dstMac) { + return new Tether6Value(TEST_IFACE_PARAMS.index, dstMac, TEST_IFACE_PARAMS.macAddr, ETH_P_IPV6, NetworkStackConstants.ETHER_MTU); } diff --git a/Tethering/tests/unit/src/com/android/networkstack/tethering/BpfCoordinatorTest.java b/Tethering/tests/unit/src/com/android/networkstack/tethering/BpfCoordinatorTest.java index af8053a7e9..037f45ef7b 100644 --- a/Tethering/tests/unit/src/com/android/networkstack/tethering/BpfCoordinatorTest.java +++ b/Tethering/tests/unit/src/com/android/networkstack/tethering/BpfCoordinatorTest.java @@ -160,7 +160,7 @@ public class BpfCoordinatorTest { @Mock private ConntrackMonitor mConntrackMonitor; @Mock private BpfMap mBpfDownstream4Map; @Mock private BpfMap mBpfUpstream4Map; - @Mock private BpfMap mBpfDownstream6Map; + @Mock private BpfMap mBpfDownstream6Map; // Late init since methods must be called by the thread that created this object. private TestableNetworkStatsProviderCbBinder mTetherStatsProviderCb; @@ -217,7 +217,7 @@ public class BpfCoordinatorTest { } @Nullable - public BpfMap + public BpfMap getBpfDownstream6Map() { return mBpfDownstream6Map; } @@ -366,7 +366,7 @@ public class BpfCoordinatorTest { @NonNull Ipv6ForwardingRule rule) throws Exception { if (mDeps.isAtLeastS()) { verifyWithOrder(inOrder, mBpfDownstream6Map).updateEntry( - rule.makeTetherDownstream6Key(), rule.makeTetherDownstream6Value()); + rule.makeTetherDownstream6Key(), rule.makeTether6Value()); } else { verifyWithOrder(inOrder, mNetd).tetherOffloadRuleAdd(matches(rule)); } @@ -688,11 +688,11 @@ public class BpfCoordinatorTest { } @Test - public void testRuleMakeTetherDownstream6Value() throws Exception { + public void testRuleMakeTether6Value() throws Exception { final Integer mobileIfIndex = 100; final Ipv6ForwardingRule rule = buildTestForwardingRule(mobileIfIndex, NEIGH_A, MAC_A); - final TetherDownstream6Value value = rule.makeTetherDownstream6Value(); + final Tether6Value value = rule.makeTether6Value(); assertEquals(value.oif, DOWNSTREAM_IFINDEX); assertEquals(value.ethDstMac, MAC_A); assertEquals(value.ethSrcMac, DOWNSTREAM_MAC);