Merge "ClatCoordinator: use Java class TcUtils to attach program" am: 932459748a

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

Change-Id: I2a02006cfe6c21c476af8e350527321851a7043f
Signed-off-by: Automerger Merge Worker <android-build-automerger-merge-worker@system.gserviceaccount.com>
This commit is contained in:
Maciej Żenczykowski
2022-04-11 21:10:00 +00:00
committed by Automerger Merge Worker
3 changed files with 158 additions and 10 deletions

View File

@@ -404,15 +404,6 @@ static jint com_android_server_connectivity_ClatCoordinator_startClatd(
posix_spawnattr_destroy(&attr);
posix_spawn_file_actions_destroy(&fa);
// 6. Start BPF if any
if (!net::clat::initMaps()) {
net::clat::ClatdTracker tracker = {};
if (!initTracker(ifaceStr.c_str(), pfx96Str.c_str(), v4Str.c_str(), v6Str.c_str(),
&tracker)) {
net::clat::maybeStartBpf(tracker);
}
}
return pid;
}

View File

@@ -18,6 +18,8 @@ package com.android.server.connectivity;
import static android.net.INetd.IF_STATE_UP;
import static android.net.INetd.PERMISSION_SYSTEM;
import static android.system.OsConstants.ETH_P_IP;
import static android.system.OsConstants.ETH_P_IPV6;
import static com.android.net.module.util.NetworkStackConstants.IPV6_MIN_MTU;
@@ -80,6 +82,20 @@ public class ClatCoordinator {
private static final int INVALID_IFINDEX = 0;
// For better code clarity when used for 'bool ingress' parameter.
@VisibleForTesting
static final boolean EGRESS = false;
@VisibleForTesting
static final boolean INGRESS = true;
// For better code clarity when used for 'bool ether' parameter.
static final boolean RAWIP = false;
static final boolean ETHER = true;
// The priority of clat hook - must be after tethering.
@VisibleForTesting
static final int PRIO_CLAT = 4;
private static final String CLAT_EGRESS4_MAP_PATH = makeMapPath("egress4");
private static final String CLAT_INGRESS6_MAP_PATH = makeMapPath("ingress6");
@@ -87,6 +103,14 @@ public class ClatCoordinator {
return "/sys/fs/bpf/map_clatd_clat_" + which + "_map";
}
private static String makeProgPath(boolean ingress, boolean ether) {
String path = "/sys/fs/bpf/prog_clatd_schedcls_"
+ (ingress ? "ingress6" : "egress4")
+ "_clat_"
+ (ether ? "ether" : "rawip");
return path;
}
@NonNull
private final INetd mNetd;
@NonNull
@@ -254,6 +278,23 @@ public class ClatCoordinator {
public boolean isEthernet(String iface) throws IOException {
return TcUtils.isEthernet(iface);
}
/** Add a clsact qdisc. */
public void tcQdiscAddDevClsact(int ifIndex) throws IOException {
TcUtils.tcQdiscAddDevClsact(ifIndex);
}
/** Attach a tc bpf filter. */
public void tcFilterAddDevBpf(int ifIndex, boolean ingress, short prio, short proto,
String bpfProgPath) throws IOException {
TcUtils.tcFilterAddDevBpf(ifIndex, ingress, prio, proto, bpfProgPath);
}
/** Delete a tc filter. */
public void tcFilterDelDev(int ifIndex, boolean ingress, short prio, short proto)
throws IOException {
TcUtils.tcFilterDelDev(ifIndex, ingress, prio, proto);
}
}
@VisibleForTesting
@@ -370,7 +411,86 @@ public class ClatCoordinator {
return;
}
// TODO: attach program.
// Usually the clsact will be added in netd RouteController::addInterfaceToPhysicalNetwork.
// But clat is started before the v4- interface is added to the network. The clat startup
// have to add clsact of v4- tun interface first for adding bpf filter in maybeStartBpf.
try {
// tc qdisc add dev .. clsact
mDeps.tcQdiscAddDevClsact(tracker.v4ifIndex);
} catch (IOException e) {
Log.e(TAG, "tc qdisc add dev (" + tracker.v4ifIndex + "[" + tracker.v4iface
+ "]) failure: " + e);
try {
mEgressMap.deleteEntry(txKey);
} catch (ErrnoException | IllegalStateException e2) {
Log.e(TAG, "Could not delete entry (" + txKey + ") from egress map: " + e2);
}
try {
mIngressMap.deleteEntry(rxKey);
} catch (ErrnoException | IllegalStateException e3) {
Log.e(TAG, "Could not delete entry (" + rxKey + ") from ingress map: " + e3);
}
return;
}
// This program will be attached to the v4-* interface which is a TUN and thus always rawip.
try {
// tc filter add dev .. egress prio 4 protocol ip bpf object-pinned /sys/fs/bpf/...
// direct-action
mDeps.tcFilterAddDevBpf(tracker.v4ifIndex, EGRESS, (short) PRIO_CLAT, (short) ETH_P_IP,
makeProgPath(EGRESS, RAWIP));
} catch (IOException e) {
Log.e(TAG, "tc filter add dev (" + tracker.v4ifIndex + "[" + tracker.v4iface
+ "]) egress prio PRIO_CLAT protocol ip failure: " + e);
// The v4- interface clsact is not deleted for unwinding error because once it is
// created with interface addition, the lifetime is till interface deletion. Moreover,
// the clsact has no clat filter now. It should not break anything.
try {
mEgressMap.deleteEntry(txKey);
} catch (ErrnoException | IllegalStateException e2) {
Log.e(TAG, "Could not delete entry (" + txKey + ") from egress map: " + e2);
}
try {
mIngressMap.deleteEntry(rxKey);
} catch (ErrnoException | IllegalStateException e3) {
Log.e(TAG, "Could not delete entry (" + rxKey + ") from ingress map: " + e3);
}
return;
}
try {
// tc filter add dev .. ingress prio 4 protocol ipv6 bpf object-pinned /sys/fs/bpf/...
// direct-action
mDeps.tcFilterAddDevBpf(tracker.ifIndex, INGRESS, (short) PRIO_CLAT,
(short) ETH_P_IPV6, makeProgPath(INGRESS, isEthernet));
} catch (IOException e) {
Log.e(TAG, "tc filter add dev (" + tracker.ifIndex + "[" + tracker.iface
+ "]) ingress prio PRIO_CLAT protocol ipv6 failure: " + e);
// The v4- interface clsact is not deleted. See the reason in the error unwinding code
// of the egress filter attaching of v4- tun interface.
try {
mDeps.tcFilterDelDev(tracker.v4ifIndex, EGRESS, (short) PRIO_CLAT,
(short) ETH_P_IP);
} catch (IOException e2) {
Log.e(TAG, "tc filter del dev (" + tracker.v4ifIndex + "[" + tracker.v4iface
+ "]) egress prio PRIO_CLAT protocol ip failure: " + e2);
}
try {
mEgressMap.deleteEntry(txKey);
} catch (ErrnoException | IllegalStateException e3) {
Log.e(TAG, "Could not delete entry (" + txKey + ") from egress map: " + e3);
}
try {
mIngressMap.deleteEntry(rxKey);
} catch (ErrnoException | IllegalStateException e4) {
Log.e(TAG, "Could not delete entry (" + rxKey + ") from ingress map: " + e4);
}
return;
}
}
/**

View File

@@ -17,11 +17,16 @@
package com.android.server.connectivity;
import static android.net.INetd.IF_STATE_UP;
import static android.system.OsConstants.ETH_P_IP;
import static android.system.OsConstants.ETH_P_IPV6;
import static com.android.net.module.util.NetworkStackConstants.ETHER_MTU;
import static com.android.server.connectivity.ClatCoordinator.CLAT_MAX_MTU;
import static com.android.server.connectivity.ClatCoordinator.EGRESS;
import static com.android.server.connectivity.ClatCoordinator.INGRESS;
import static com.android.server.connectivity.ClatCoordinator.INIT_V4ADDR_PREFIX_LEN;
import static com.android.server.connectivity.ClatCoordinator.INIT_V4ADDR_STRING;
import static com.android.server.connectivity.ClatCoordinator.PRIO_CLAT;
import static com.android.testutils.MiscAsserts.assertThrows;
import static org.junit.Assert.assertEquals;
@@ -103,6 +108,10 @@ public class ClatCoordinatorTest {
private static final ParcelFileDescriptor PACKET_SOCK_PFD = new ParcelFileDescriptor(
new FileDescriptor());
private static final String EGRESS_PROG_PATH =
"/sys/fs/bpf/prog_clatd_schedcls_egress4_clat_rawip";
private static final String INGRESS_PROG_PATH =
"/sys/fs/bpf/prog_clatd_schedcls_ingress6_clat_ether";
private static final ClatEgress4Key EGRESS_KEY = new ClatEgress4Key(STACKED_IFINDEX,
INET4_LOCAL4);
private static final ClatEgress4Value EGRESS_VALUE = new ClatEgress4Value(BASE_IFINDEX,
@@ -334,6 +343,29 @@ public class ClatCoordinatorTest {
fail("unsupported arg: " + iface);
return false;
}
/** Add a clsact qdisc. */
@Override
public void tcQdiscAddDevClsact(int ifIndex) throws IOException {
// no-op
return;
}
/** Attach a tc bpf filter. */
@Override
public void tcFilterAddDevBpf(int ifIndex, boolean ingress, short prio, short proto,
String bpfProgPath) throws IOException {
// no-op
return;
}
/** Delete a tc filter. */
@Override
public void tcFilterDelDev(int ifIndex, boolean ingress, short prio, short proto)
throws IOException {
// no-op
return;
}
};
@NonNull
@@ -417,6 +449,11 @@ public class ClatCoordinatorTest {
eq(XLAT_LOCAL_IPV4ADDR_STRING), eq(XLAT_LOCAL_IPV6ADDR_STRING));
inOrder.verify(mEgressMap).insertEntry(eq(EGRESS_KEY), eq(EGRESS_VALUE));
inOrder.verify(mIngressMap).insertEntry(eq(INGRESS_KEY), eq(INGRESS_VALUE));
inOrder.verify(mDeps).tcQdiscAddDevClsact(eq(STACKED_IFINDEX));
inOrder.verify(mDeps).tcFilterAddDevBpf(eq(STACKED_IFINDEX), eq(EGRESS),
eq((short) PRIO_CLAT), eq((short) ETH_P_IP), eq(EGRESS_PROG_PATH));
inOrder.verify(mDeps).tcFilterAddDevBpf(eq(BASE_IFINDEX), eq(INGRESS),
eq((short) PRIO_CLAT), eq((short) ETH_P_IPV6), eq(INGRESS_PROG_PATH));
inOrder.verifyNoMoreInteractions();
// [2] Start clatd again failed.