Add methods for updating ingressDiscardRule bpf map to BpfNetMaps am: b01647922d am: 1002ddce1e
Original change: https://googleplex-android-review.googlesource.com/c/platform/packages/modules/Connectivity/+/28712473
Change-Id: Iee6925a417ad1d107e8d62f6d15cf92ab24adef6
Signed-off-by: Automerger Merge Worker <android-build-automerger-merge-worker@system.gserviceaccount.com>
diff --git a/common/src/com/android/net/module/util/bpf/IngressDiscardKey.java b/common/src/com/android/net/module/util/bpf/IngressDiscardKey.java
index eabcf3c..9fefb52 100644
--- a/common/src/com/android/net/module/util/bpf/IngressDiscardKey.java
+++ b/common/src/com/android/net/module/util/bpf/IngressDiscardKey.java
@@ -16,9 +16,12 @@
package com.android.net.module.util.bpf;
+import com.android.net.module.util.InetAddressUtils;
import com.android.net.module.util.Struct;
+import java.net.Inet4Address;
import java.net.Inet6Address;
+import java.net.InetAddress;
/** Key type for ingress discard map */
public class IngressDiscardKey extends Struct {
@@ -29,4 +32,14 @@
public IngressDiscardKey(final Inet6Address dstAddr) {
this.dstAddr = dstAddr;
}
+
+ private static Inet6Address getInet6Address(final InetAddress addr) {
+ return (addr instanceof Inet4Address)
+ ? InetAddressUtils.v4MappedV6Address((Inet4Address) addr)
+ : (Inet6Address) addr;
+ }
+
+ public IngressDiscardKey(final InetAddress dstAddr) {
+ this(getInet6Address(dstAddr));
+ }
}
diff --git a/service/src/com/android/server/BpfNetMaps.java b/service/src/com/android/server/BpfNetMaps.java
index ec168dd..98c73d0 100644
--- a/service/src/com/android/server/BpfNetMaps.java
+++ b/service/src/com/android/server/BpfNetMaps.java
@@ -40,6 +40,7 @@
import android.app.StatsManager;
import android.content.Context;
import android.net.INetd;
+import android.os.Build;
import android.os.RemoteException;
import android.os.ServiceSpecificException;
import android.provider.DeviceConfig;
@@ -51,6 +52,8 @@
import android.util.Pair;
import android.util.StatsEvent;
+import androidx.annotation.RequiresApi;
+
import com.android.internal.annotations.VisibleForTesting;
import com.android.modules.utils.BackgroundThread;
import com.android.modules.utils.build.SdkLevel;
@@ -64,9 +67,12 @@
import com.android.net.module.util.Struct.U8;
import com.android.net.module.util.bpf.CookieTagMapKey;
import com.android.net.module.util.bpf.CookieTagMapValue;
+import com.android.net.module.util.bpf.IngressDiscardKey;
+import com.android.net.module.util.bpf.IngressDiscardValue;
import java.io.FileDescriptor;
import java.io.IOException;
+import java.net.InetAddress;
import java.util.Arrays;
import java.util.List;
import java.util.Set;
@@ -113,6 +119,8 @@
"/sys/fs/bpf/netd_shared/map_netd_uid_permission_map";
private static final String COOKIE_TAG_MAP_PATH =
"/sys/fs/bpf/netd_shared/map_netd_cookie_tag_map";
+ public static final String INGRESS_DISCARD_MAP_PATH =
+ "/sys/fs/bpf/netd_shared/map_netd_ingress_discard_map";
private static final S32 UID_RULES_CONFIGURATION_KEY = new S32(0);
private static final S32 CURRENT_STATS_MAP_CONFIGURATION_KEY = new S32(1);
private static final long UID_RULES_DEFAULT_CONFIGURATION = 0;
@@ -124,6 +132,7 @@
private static IBpfMap<S32, UidOwnerValue> sUidOwnerMap = null;
private static IBpfMap<S32, U8> sUidPermissionMap = null;
private static IBpfMap<CookieTagMapKey, CookieTagMapValue> sCookieTagMap = null;
+ private static IBpfMap<IngressDiscardKey, IngressDiscardValue> sIngressDiscardMap = null;
// LINT.IfChange(match_type)
@VisibleForTesting public static final long NO_MATCH = 0;
@@ -201,6 +210,15 @@
sCookieTagMap = cookieTagMap;
}
+ /**
+ * Set ingressDiscardMap for test.
+ */
+ @VisibleForTesting
+ public static void setIngressDiscardMapForTest(
+ IBpfMap<IngressDiscardKey, IngressDiscardValue> ingressDiscardMap) {
+ sIngressDiscardMap = ingressDiscardMap;
+ }
+
private static IBpfMap<S32, U32> getConfigurationMap() {
try {
return new BpfMap<>(
@@ -237,6 +255,15 @@
}
}
+ private static IBpfMap<IngressDiscardKey, IngressDiscardValue> getIngressDiscardMap() {
+ try {
+ return new BpfMap<>(INGRESS_DISCARD_MAP_PATH, BpfMap.BPF_F_RDWR,
+ IngressDiscardKey.class, IngressDiscardValue.class);
+ } catch (ErrnoException e) {
+ throw new IllegalStateException("Cannot open ingress discard map", e);
+ }
+ }
+
private static void initBpfMaps() {
if (sConfigurationMap == null) {
sConfigurationMap = getConfigurationMap();
@@ -270,6 +297,15 @@
if (sCookieTagMap == null) {
sCookieTagMap = getCookieTagMap();
}
+
+ if (sIngressDiscardMap == null) {
+ sIngressDiscardMap = getIngressDiscardMap();
+ }
+ try {
+ sIngressDiscardMap.clear();
+ } catch (ErrnoException e) {
+ throw new IllegalStateException("Failed to initialize ingress discard map", e);
+ }
}
/**
@@ -308,6 +344,13 @@
}
/**
+ * Get interface name
+ */
+ public String getIfName(final int ifIndex) {
+ return Os.if_indextoname(ifIndex);
+ }
+
+ /**
* Call synchronize_rcu()
*/
public int synchronizeKernelRCU() {
@@ -987,6 +1030,45 @@
}
}
+ /**
+ * Set ingress discard rule
+ *
+ * @param address target address to set the ingress discard rule
+ * @param iface allowed interface
+ */
+ @RequiresApi(Build.VERSION_CODES.TIRAMISU)
+ public void setIngressDiscardRule(final InetAddress address, final String iface) {
+ throwIfPreT("setIngressDiscardRule is not available on pre-T devices");
+ final int ifIndex = mDeps.getIfIndex(iface);
+ if (ifIndex == 0) {
+ Log.e(TAG, "Failed to get if index, skip setting ingress discard rule for " + address
+ + "(" + iface + ")");
+ return;
+ }
+ try {
+ sIngressDiscardMap.updateEntry(new IngressDiscardKey(address),
+ new IngressDiscardValue(ifIndex, ifIndex));
+ } catch (ErrnoException e) {
+ Log.e(TAG, "Failed to set ingress discard rule for " + address + "("
+ + iface + "), " + e);
+ }
+ }
+
+ /**
+ * Remove ingress discard rule
+ *
+ * @param address target address to remove the ingress discard rule
+ */
+ @RequiresApi(Build.VERSION_CODES.TIRAMISU)
+ public void removeIngressDiscardRule(final InetAddress address) {
+ throwIfPreT("removeIngressDiscardRule is not available on pre-T devices");
+ try {
+ sIngressDiscardMap.deleteEntry(new IngressDiscardKey(address));
+ } catch (ErrnoException e) {
+ Log.e(TAG, "Failed to remove ingress discard rule for " + address + ", " + e);
+ }
+ }
+
/** Register callback for statsd to pull atom. */
public void setPullAtomCallback(final Context context) {
throwIfPreT("setPullAtomCallback is not available on pre-T devices");
@@ -1136,6 +1218,10 @@
});
BpfDump.dumpMap(sUidPermissionMap, pw, "sUidPermissionMap",
(uid, permission) -> uid.val + " " + permissionToString(permission.val));
+ BpfDump.dumpMap(sIngressDiscardMap, pw, "sIngressDiscardMap",
+ (key, value) -> "[" + key.dstAddr + "]: "
+ + value.iif1 + "(" + mDeps.getIfName(value.iif1) + "), "
+ + value.iif2 + "(" + mDeps.getIfName(value.iif2) + ")");
pw.decreaseIndent();
}
}
diff --git a/tests/unit/java/com/android/server/BpfNetMapsTest.java b/tests/unit/java/com/android/server/BpfNetMapsTest.java
index 19fa41d..319af50 100644
--- a/tests/unit/java/com/android/server/BpfNetMapsTest.java
+++ b/tests/unit/java/com/android/server/BpfNetMapsTest.java
@@ -78,6 +78,8 @@
import com.android.net.module.util.Struct.U8;
import com.android.net.module.util.bpf.CookieTagMapKey;
import com.android.net.module.util.bpf.CookieTagMapValue;
+import com.android.net.module.util.bpf.IngressDiscardKey;
+import com.android.net.module.util.bpf.IngressDiscardValue;
import com.android.testutils.DevSdkIgnoreRule;
import com.android.testutils.DevSdkIgnoreRule.IgnoreAfter;
import com.android.testutils.DevSdkIgnoreRule.IgnoreUpTo;
@@ -139,11 +141,14 @@
private final IBpfMap<S32, U8> mUidPermissionMap = new TestBpfMap<>(S32.class, U8.class);
private final IBpfMap<CookieTagMapKey, CookieTagMapValue> mCookieTagMap =
spy(new TestBpfMap<>(CookieTagMapKey.class, CookieTagMapValue.class));
+ private final IBpfMap<IngressDiscardKey, IngressDiscardValue> mIngressDiscardMap =
+ new TestBpfMap<>(IngressDiscardKey.class, IngressDiscardValue.class);
@Before
public void setUp() throws Exception {
MockitoAnnotations.initMocks(this);
doReturn(TEST_IF_INDEX).when(mDeps).getIfIndex(TEST_IF_NAME);
+ doReturn(TEST_IF_NAME).when(mDeps).getIfName(TEST_IF_INDEX);
doReturn(0).when(mDeps).synchronizeKernelRCU();
BpfNetMaps.setEnableJavaBpfMapForTest(true /* enable */);
BpfNetMaps.setConfigurationMapForTest(mConfigurationMap);
@@ -153,6 +158,7 @@
BpfNetMaps.setUidOwnerMapForTest(mUidOwnerMap);
BpfNetMaps.setUidPermissionMapForTest(mUidPermissionMap);
BpfNetMaps.setCookieTagMapForTest(mCookieTagMap);
+ BpfNetMaps.setIngressDiscardMapForTest(mIngressDiscardMap);
mBpfNetMaps = new BpfNetMaps(mContext, mNetd, mDeps);
}