Add BpfDump#dumpMap
Bug: 217624062
Test: atest NetworkStaticLibTests
Change-Id: I7b0a949e667da4120cc20d8587019bfb0f922584
diff --git a/staticlibs/device/com/android/net/module/util/BpfDump.java b/staticlibs/device/com/android/net/module/util/BpfDump.java
index 67e9c93..2534d61 100644
--- a/staticlibs/device/com/android/net/module/util/BpfDump.java
+++ b/staticlibs/device/com/android/net/module/util/BpfDump.java
@@ -15,13 +15,17 @@
*/
package com.android.net.module.util;
+import android.system.ErrnoException;
+import android.system.Os;
import android.util.Base64;
import android.util.Pair;
import androidx.annotation.NonNull;
+import java.io.PrintWriter;
import java.nio.ByteBuffer;
import java.nio.ByteOrder;
+import java.util.function.BiFunction;
/**
* The classes and the methods for BPF dump utilization.
@@ -74,6 +78,38 @@
return new Pair<>(k, v);
}
+ /**
+ * Dump the BpfMap name and entries
+ */
+ public static <K extends Struct, V extends Struct> void dumpMap(IBpfMap<K, V> map,
+ PrintWriter pw, String mapName, BiFunction<K, V, String> entryToString) {
+ dumpMap(map, pw, mapName, "" /* header */, entryToString);
+ }
+
+ /**
+ * Dump the BpfMap name, header, and entries
+ */
+ public static <K extends Struct, V extends Struct> void dumpMap(IBpfMap<K, V> map,
+ PrintWriter pw, String mapName, String header, BiFunction<K, V, String> entryToString) {
+ pw.println(mapName + ":");
+ if (!header.isEmpty()) {
+ pw.println(" " + header);
+ }
+ try {
+ map.forEach((key, value) -> {
+ // Value could be null if there is a concurrent entry deletion.
+ // http://b/220084230.
+ if (value != null) {
+ pw.println(" " + entryToString.apply(key, value));
+ } else {
+ pw.println("Entry is deleted while dumping, iterating from first entry");
+ }
+ });
+ } catch (ErrnoException e) {
+ pw.println("Map dump end with error: " + Os.strerror(e.errno));
+ }
+ }
+
// TODO: add a helper to dump bpf map content with the map name, the header line
// (ex: "BPF ingress map: iif nat64Prefix v6Addr -> v4Addr oif"), a lambda that
// knows how to dump each line, and the PrintWriter.
diff --git a/staticlibs/tests/unit/src/com/android/net/module/util/BpfDumpTest.java b/staticlibs/tests/unit/src/com/android/net/module/util/BpfDumpTest.java
index 395011c..3932925 100644
--- a/staticlibs/tests/unit/src/com/android/net/module/util/BpfDumpTest.java
+++ b/staticlibs/tests/unit/src/com/android/net/module/util/BpfDumpTest.java
@@ -18,15 +18,21 @@
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertThrows;
+import static org.junit.Assert.assertTrue;
import android.util.Pair;
import androidx.test.filters.SmallTest;
import androidx.test.runner.AndroidJUnit4;
+import com.android.testutils.TestBpfMap;
+
import org.junit.Test;
import org.junit.runner.RunWith;
+import java.io.PrintWriter;
+import java.io.StringWriter;
+
@RunWith(AndroidJUnit4.class)
@SmallTest
public class BpfDumpTest {
@@ -79,4 +85,37 @@
assertThrowsIllegalArgumentException(
TEST_KEY_VAL_BASE64 + BASE64_DELIMITER + TEST_KEY_BASE64);
}
+
+ private String getDumpMap(final IBpfMap<Struct.U32, Struct.U32> map) {
+ final StringWriter sw = new StringWriter();
+ BpfDump.dumpMap(map, new PrintWriter(sw), "mapName", "header",
+ (key, val) -> "key=" + key.val + ", val=" + val.val);
+ return sw.toString();
+ }
+
+ @Test
+ public void testDumpMap() throws Exception {
+ final IBpfMap<Struct.U32, Struct.U32> map =
+ new TestBpfMap<>(Struct.U32.class, Struct.U32.class);
+ map.updateEntry(new Struct.U32(123), new Struct.U32(456));
+
+ final String dump = getDumpMap(map);
+ assertEquals(dump, "mapName:\n"
+ + " header\n"
+ + " key=123, val=456\n");
+ }
+
+ @Test
+ public void testDumpMapMultipleEntries() throws Exception {
+ final IBpfMap<Struct.U32, Struct.U32> map =
+ new TestBpfMap<>(Struct.U32.class, Struct.U32.class);
+ map.updateEntry(new Struct.U32(123), new Struct.U32(456));
+ map.updateEntry(new Struct.U32(789), new Struct.U32(123));
+
+ final String dump = getDumpMap(map);
+ assertTrue(dump.contains("mapName:"));
+ assertTrue(dump.contains("header"));
+ assertTrue(dump.contains("key=123, val=456"));
+ assertTrue(dump.contains("key=789, val=123"));
+ }
}