diff options
author | Maciej Żenczykowski <maze@google.com> | 2022-04-11 20:47:26 +0000 |
---|---|---|
committer | Gerrit Code Review <noreply-gerritcodereview@google.com> | 2022-04-11 20:47:26 +0000 |
commit | 932459748a57b8bf249dfc362c59042a122d8b44 (patch) | |
tree | a2f36dbb74e1c8ca74feb65fa3e679de1416d12c | |
parent | 7b75c07cdae88372903171f7fbcdab9b00fe8ae7 (diff) | |
parent | 3dc0577ed3e30852fd6809ed5d84da1e7d586e1b (diff) | |
download | Connectivity-932459748a57b8bf249dfc362c59042a122d8b44.tar.gz |
Merge "ClatCoordinator: use Java class TcUtils to attach program"
3 files changed, 158 insertions, 10 deletions
diff --git a/service/jni/com_android_server_connectivity_ClatCoordinator.cpp b/service/jni/com_android_server_connectivity_ClatCoordinator.cpp index 4517b5cf5c..e2223621d6 100644 --- a/service/jni/com_android_server_connectivity_ClatCoordinator.cpp +++ b/service/jni/com_android_server_connectivity_ClatCoordinator.cpp @@ -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; } diff --git a/service/src/com/android/server/connectivity/ClatCoordinator.java b/service/src/com/android/server/connectivity/ClatCoordinator.java index 35b8f17c82..e2aa3e168d 100644 --- a/service/src/com/android/server/connectivity/ClatCoordinator.java +++ b/service/src/com/android/server/connectivity/ClatCoordinator.java @@ -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; + } } /** diff --git a/tests/unit/java/com/android/server/connectivity/ClatCoordinatorTest.java b/tests/unit/java/com/android/server/connectivity/ClatCoordinatorTest.java index 790473d5f7..340ab9bc2a 100644 --- a/tests/unit/java/com/android/server/connectivity/ClatCoordinatorTest.java +++ b/tests/unit/java/com/android/server/connectivity/ClatCoordinatorTest.java @@ -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. |