BpfCoordinator: Add an option to choose which raw bpf map to dump am: e4a6b28938

Original change: https://android-review.googlesource.com/c/platform/packages/modules/Connectivity/+/2054365

Change-Id: If53f14d542df8f282f6fa3264d89c619eed1d8a8
Signed-off-by: Automerger Merge Worker <android-build-automerger-merge-worker@system.gserviceaccount.com>
This commit is contained in:
Hungming Chen
2022-04-20 11:08:42 +00:00
committed by Automerger Merge Worker
3 changed files with 40 additions and 24 deletions

View File

@@ -65,6 +65,7 @@ import com.android.net.module.util.BpfMap;
import com.android.net.module.util.CollectionUtils;
import com.android.net.module.util.InterfaceParams;
import com.android.net.module.util.NetworkStackConstants;
import com.android.net.module.util.Struct;
import com.android.net.module.util.Struct.U32;
import com.android.net.module.util.bpf.Tether4Key;
import com.android.net.module.util.bpf.Tether4Value;
@@ -120,6 +121,7 @@ public class BpfCoordinator {
private static final String TETHER_LIMIT_MAP_PATH = makeMapPath("limit");
private static final String TETHER_ERROR_MAP_PATH = makeMapPath("error");
private static final String TETHER_DEV_MAP_PATH = makeMapPath("dev");
private static final String DUMPSYS_RAWMAP_ARG_UPSTREAM4 = "--upstream4";
// Using "," as a separator is safe because base64 characters are [0-9a-zA-Z/=+].
private static final String DUMP_BASE64_DELIMITER = ",";
@@ -1074,7 +1076,8 @@ public class BpfCoordinator {
}
}
private String ipv4RuleToBase64String(Tether4Key key, Tether4Value value) {
private <K extends Struct, V extends Struct> String bpfMapEntryToBase64String(
final K key, final V value) {
final byte[] keyBytes = key.writeToBytes();
final String keyBase64Str = Base64.encodeToString(keyBytes, Base64.DEFAULT)
.replace("\n", "");
@@ -1095,19 +1098,28 @@ public class BpfCoordinator {
pw.println("No rules");
return;
}
map.forEach((k, v) -> pw.println(ipv4RuleToBase64String(k, v)));
map.forEach((k, v) -> pw.println(bpfMapEntryToBase64String(k, v)));
}
/**
* Dump raw BPF map in base64 encoded strings. For test only.
* Only allow to dump one map path once.
* Format:
* $ dumpsys tethering bpfRawMap --<map name>
*/
public void dumpRawMap(@NonNull IndentingPrintWriter pw) {
public void dumpRawMap(@NonNull IndentingPrintWriter pw, @Nullable String[] args) {
// TODO: consider checking the arg order that <map name> is after "bpfRawMap". Probably
// it is okay for now because this is used by test only and test is supposed to use
// expected argument order.
// TODO: dump downstream4 map.
if (CollectionUtils.contains(args, DUMPSYS_RAWMAP_ARG_UPSTREAM4)) {
try (BpfMap<Tether4Key, Tether4Value> upstreamMap = mDeps.getBpfUpstream4Map()) {
// TODO: dump downstream map.
dumpRawIpv4ForwardingRuleMap(upstreamMap, pw);
} catch (ErrnoException e) {
pw.println("Error dumping IPv4 map: " + e);
}
return;
}
}
private String l4protoToString(int proto) {

View File

@@ -2513,9 +2513,8 @@ public class Tethering {
writer, " ");
// Used for testing instead of human debug.
// TODO: add options to choose which map to dump.
if (argsContain(args, "bpfRawMap")) {
mBpfCoordinator.dumpRawMap(pw);
mBpfCoordinator.dumpRawMap(pw, args);
return;
}

View File

@@ -136,6 +136,7 @@ public class EthernetTetheringTest {
ByteBuffer.wrap(new byte[] { (byte) 0x55, (byte) 0xaa });
private static final String DUMPSYS_TETHERING_RAWMAP_ARG = "bpfRawMap";
private static final String DUMPSYS_RAWMAP_ARG_UPSTREAM4 = "--upstream4";
private static final String BASE64_DELIMITER = ",";
private static final String LINE_DELIMITER = "\\n";
@@ -956,7 +957,8 @@ public class EthernetTetheringTest {
return isExpectedUdpPacket(p, false /* hasEther */, PAYLOAD3);
});
final HashMap<Tether4Key, Tether4Value> upstreamMap = pollIpv4UpstreamMapFromDump();
final HashMap<Tether4Key, Tether4Value> upstreamMap = pollRawMapFromDump(
Tether4Key.class, Tether4Value.class, DUMPSYS_RAWMAP_ARG_UPSTREAM4);
assertNotNull(upstreamMap);
assertEquals(1, upstreamMap.size());
@@ -1021,7 +1023,8 @@ public class EthernetTetheringTest {
}
@Nullable
private Pair<Tether4Key, Tether4Value> parseTether4KeyValue(@NonNull String dumpStr) {
private <K extends Struct, V extends Struct> Pair<K, V> parseMapKeyValue(
Class<K> keyClass, Class<V> valueClass, @NonNull String dumpStr) {
Log.w(TAG, "Parsing string: " + dumpStr);
String[] keyValueStrs = dumpStr.split(BASE64_DELIMITER);
@@ -1034,36 +1037,38 @@ public class EthernetTetheringTest {
Log.d(TAG, "keyBytes: " + dumpHexString(keyBytes));
final ByteBuffer keyByteBuffer = ByteBuffer.wrap(keyBytes);
keyByteBuffer.order(ByteOrder.nativeOrder());
final Tether4Key tether4Key = Struct.parse(Tether4Key.class, keyByteBuffer);
Log.w(TAG, "tether4Key: " + tether4Key);
final K k = Struct.parse(keyClass, keyByteBuffer);
final byte[] valueBytes = Base64.decode(keyValueStrs[1], Base64.DEFAULT);
Log.d(TAG, "valueBytes: " + dumpHexString(valueBytes));
final ByteBuffer valueByteBuffer = ByteBuffer.wrap(valueBytes);
valueByteBuffer.order(ByteOrder.nativeOrder());
final Tether4Value tether4Value = Struct.parse(Tether4Value.class, valueByteBuffer);
Log.w(TAG, "tether4Value: " + tether4Value);
final V v = Struct.parse(valueClass, valueByteBuffer);
return new Pair<>(tether4Key, tether4Value);
return new Pair<>(k, v);
}
@NonNull
private HashMap<Tether4Key, Tether4Value> dumpIpv4UpstreamMap() throws Exception {
final String rawMapStr = DumpTestUtils.dumpService(Context.TETHERING_SERVICE,
DUMPSYS_TETHERING_RAWMAP_ARG);
final HashMap<Tether4Key, Tether4Value> map = new HashMap<>();
private <K extends Struct, V extends Struct> HashMap<K, V> dumpAndParseRawMap(
Class<K> keyClass, Class<V> valueClass, @NonNull String mapArg)
throws Exception {
final String[] args = new String[] {DUMPSYS_TETHERING_RAWMAP_ARG, mapArg};
final String rawMapStr = DumpTestUtils.dumpService(Context.TETHERING_SERVICE, args);
final HashMap<K, V> map = new HashMap<>();
for (final String line : rawMapStr.split(LINE_DELIMITER)) {
final Pair<Tether4Key, Tether4Value> rule = parseTether4KeyValue(line.trim());
final Pair<K, V> rule = parseMapKeyValue(keyClass, valueClass, line.trim());
map.put(rule.first, rule.second);
}
return map;
}
@Nullable
private HashMap<Tether4Key, Tether4Value> pollIpv4UpstreamMapFromDump() throws Exception {
private <K extends Struct, V extends Struct> HashMap<K, V> pollRawMapFromDump(
Class<K> keyClass, Class<V> valueClass, @NonNull String mapArg)
throws Exception {
for (int retryCount = 0; retryCount < DUMP_POLLING_MAX_RETRY; retryCount++) {
final HashMap<Tether4Key, Tether4Value> map = dumpIpv4UpstreamMap();
final HashMap<K, V> map = dumpAndParseRawMap(keyClass, valueClass, mapArg);
if (!map.isEmpty()) return map;
Thread.sleep(DUMP_POLLING_INTERVAL_MS);