Move attaching and detaching clsact from ClatdController to RouteController

The clsact attaching and detaching control plane is moved to:
  RouteController::addInterfaceToPhysicalNetwork      - add clsact
  RouteController::removeInterfaceFromPhysicalNetwork - del clsact

The above change implies that the clsact lifetime for each interface
has been extended from clat enabled time to interface lifetime.

The only exception is that attaching clsact to v4- tun interface
still lives in ClatdController. The reason is that clat is started
before the v4- tun interface is added to the network and clat has
already needed to add the bpf filters.

After all, keep attaching and detaching clat {in, e}gress bpf
filters in ClatdController.

Test: manual clatd test
1. Connect to IPv6-Only WiFi hotspot
2. Browse 172.217.0.46 (google.com) successfully
3. Disconnect from WiFi
Repeat the above steps three times.

Change-Id: I971e105484c7678ac304788e5ffff7cc709c400d
diff --git a/server/RouteController.cpp b/server/RouteController.cpp
index c2163cd..52fdcda 100644
--- a/server/RouteController.cpp
+++ b/server/RouteController.cpp
@@ -33,14 +33,17 @@
 #include "Fwmark.h"
 #include "NetdConstants.h"
 #include "NetlinkCommands.h"
+#include "OffloadUtils.h"
 #include "UidRanges.h"
 
 #include <android-base/file.h>
 #include <android-base/stringprintf.h>
+#include <android-base/strings.h>
 #include "log/log.h"
 #include "netid_client.h"
 #include "netutils/ifc.h"
 
+using android::base::StartsWith;
 using android::base::StringPrintf;
 using android::base::WriteStringToFile;
 using android::net::UidRangeParcel;
@@ -688,7 +691,7 @@
     const char *interface = DummyNetwork::INTERFACE_NAME;
     uint32_t table = getRouteTableForInterface(interface);
     if (table == RT_TABLE_UNSPEC) {
-        // getRouteTableForInterface has already looged an error.
+        // getRouteTableForInterface has already logged an error.
         return -ESRCH;
     }
 
@@ -905,6 +908,38 @@
     return 0;
 }
 
+void maybeModifyQdiscClsact(const char* interface, bool add) {
+    if (!bpf::isBpfSupported()) return;
+
+    // The clsact attaching of v4- tun interface is triggered by ClatdController::maybeStartBpf
+    // because the clat is started before the v4- interface is added to the network and the
+    // clat startup needs to add {in, e}gress filters.
+    // TODO: remove this workaround once v4- tun interface clsact attaching is moved out from
+    // ClatdController::maybeStartBpf.
+    if (StartsWith(interface, "v4-") && add) return;
+
+    // The interface may have already gone away in the delete case.
+    uint32_t ifindex = if_nametoindex(interface);
+    if (!ifindex) {
+        ALOGE("cannot find interface %s", interface);
+        return;
+    }
+
+    if (add) {
+        if (int ret = tcQdiscAddDevClsact(ifindex)) {
+            ALOGE("tcQdiscAddDevClsact(%d[%s]) failure: %s", ifindex, interface, strerror(-ret));
+            return;
+        }
+    } else {
+        if (int ret = tcQdiscDelDevClsact(ifindex)) {
+            ALOGE("tcQdiscDelDevClsact(%d[%s]) failure: %s", ifindex, interface, strerror(-ret));
+            return;
+        }
+    }
+
+    return;
+}
+
 [[nodiscard]] static int clearTetheringRules(const char* inputInterface) {
     int ret = 0;
     while (ret == 0) {
@@ -996,6 +1031,7 @@
     if (int ret = modifyPhysicalNetwork(netId, interface, permission, ACTION_ADD)) {
         return ret;
     }
+    maybeModifyQdiscClsact(interface, ACTION_ADD);
     updateTableNamesFile();
     return 0;
 }
@@ -1011,6 +1047,7 @@
     if (int ret = clearTetheringRules(interface)) {
         return ret;
     }
+    maybeModifyQdiscClsact(interface, ACTION_DEL);
     updateTableNamesFile();
     return 0;
 }