diff --git a/staticlibs/Android.bp b/staticlibs/Android.bp index a3ec405818..d13f9387f8 100644 --- a/staticlibs/Android.bp +++ b/staticlibs/Android.bp @@ -111,6 +111,7 @@ java_library { name: "net-utils-device-common-bpf", srcs: [ "device/com/android/net/module/util/BpfBitmap.java", + "device/com/android/net/module/util/BpfDump.java", "device/com/android/net/module/util/BpfMap.java", "device/com/android/net/module/util/BpfUtils.java", "device/com/android/net/module/util/HexDump.java", diff --git a/staticlibs/device/com/android/net/module/util/BpfDump.java b/staticlibs/device/com/android/net/module/util/BpfDump.java new file mode 100644 index 0000000000..fec225c10a --- /dev/null +++ b/staticlibs/device/com/android/net/module/util/BpfDump.java @@ -0,0 +1,49 @@ +/* + * Copyright (C) 2022 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.android.net.module.util; + +import android.util.Base64; + +import androidx.annotation.NonNull; + +/** + * The classes and the methods for BPF dump utilization. + */ +public class BpfDump { + // Using "," as a separator between base64 encoded key and value is safe because base64 + // characters are [0-9a-zA-Z/=+]. + public static final String BASE64_DELIMITER = ","; + + /** + * Encode BPF key and value into a base64 format string which uses the delimiter ',': + * , + */ + public static String toBase64EncodedString( + @NonNull final K key, @NonNull final V value) { + final byte[] keyBytes = key.writeToBytes(); + final String keyBase64Str = Base64.encodeToString(keyBytes, Base64.DEFAULT) + .replace("\n", ""); + final byte[] valueBytes = value.writeToBytes(); + final String valueBase64Str = Base64.encodeToString(valueBytes, Base64.DEFAULT) + .replace("\n", ""); + + return keyBase64Str + BASE64_DELIMITER + valueBase64Str; + } + + // 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 new file mode 100644 index 0000000000..b166b4a4db --- /dev/null +++ b/staticlibs/tests/unit/src/com/android/net/module/util/BpfDumpTest.java @@ -0,0 +1,43 @@ +/* + * Copyright (C) 2022 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.net.module.util; + +import static org.junit.Assert.assertEquals; + +import androidx.test.filters.SmallTest; +import androidx.test.runner.AndroidJUnit4; + +import org.junit.Test; +import org.junit.runner.RunWith; + +@RunWith(AndroidJUnit4.class) +@SmallTest +public class BpfDumpTest { + @Test + public void testToBase64EncodedString() { + final Struct.U32 key = new Struct.U32(123); + final Struct.U32 value = new Struct.U32(456); + + // Verified in python: + // import base64 + // print(base64.b64encode(b'\x7b\x00\x00\x00')) # key: ewAAAA== + // print(base64.b64encode(b'\xc8\x01\x00\x00')) # value: yAEAAA== + assertEquals("7B000000", HexDump.toHexString(key.writeToBytes())); + assertEquals("C8010000", HexDump.toHexString(value.writeToBytes())); + assertEquals("ewAAAA==,yAEAAA==", BpfDump.toBase64EncodedString(key, value)); + } +}