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:
@@ -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,18 +1098,27 @@ 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) {
|
||||
try (BpfMap<Tether4Key, Tether4Value> upstreamMap = mDeps.getBpfUpstream4Map()) {
|
||||
// TODO: dump downstream map.
|
||||
dumpRawIpv4ForwardingRuleMap(upstreamMap, pw);
|
||||
} catch (ErrnoException e) {
|
||||
pw.println("Error dumping IPv4 map: " + e);
|
||||
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()) {
|
||||
dumpRawIpv4ForwardingRuleMap(upstreamMap, pw);
|
||||
} catch (ErrnoException e) {
|
||||
pw.println("Error dumping IPv4 map: " + e);
|
||||
}
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
@@ -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);
|
||||
|
||||
Reference in New Issue
Block a user