ClatdController - attach egress clat ebpf program to v4-* interfaces

$ adb_clat_info

  ClatdController
    Trackers: iif[iface] nat64Prefix v6Addr -> v4Addr v4iif[v4iface] [netId]
      12[rmnet_data2] 2607:7700:0:1c:0:1::/96 2607:fb90:a48e:7e1c:1d2d:140d:5a1f:5343 -> 192.0.0.4 33[v4-rmnet_data2] [100]
      30[wlan0] 64:ff9b::/96 2401:fa00:480:13d:259b:4c5b:135a:16f6 -> 192.0.0.5 34[v4-wlan0] [102]
    BPF ingress map: iif(iface) nat64Prefix v6Addr -> v4Addr oif(iface)
      30(wlan0) 64:ff9b::/96 2401:fa00:480:13d:259b:4c5b:135a:16f6 -> 192.0.0.5 34(v4-wlan0)
      12(rmnet_data2) 2607:7700:0:1c:0:1::/96 2607:fb90:a48e:7e1c:1d2d:140d:5a1f:5343 -> 192.0.0.4 33(v4-rmnet_data2)
    BPF egress map: iif(iface) v4Addr -> v6Addr nat64Prefix oif(iface)
      34(v4-wlan0) 192.0.0.5 -> 2401:fa00:480:13d:259b:4c5b:135a:16f6 64:ff9b::/96 30(wlan0) ether
      33(v4-rmnet_data2) 192.0.0.4 -> 2607:fb90:a48e:7e1c:1d2d:140d:5a1f:5343 2607:7700:0:1c:0:1::/96 12(rmnet_data2) rawip

$ adb shell
crosshatch:/ # tc filter show dev v4-wlan0
crosshatch:/ # tc filter show dev v4-wlan0 ingress
crosshatch:/ # tc filter show dev v4-wlan0 egress
filter protocol ip pref 1 bpf
filter protocol ip pref 1 bpf handle 0x1 prog_clatd_schedcls_egress_clat_rawip:[*fsobj] direct-action
crosshatch:/ # tc filter show dev v4-rmnet_data2
crosshatch:/ # tc filter show dev v4-rmnet_data2 ingress
crosshatch:/ # tc filter show dev v4-rmnet_data2 egress
filter protocol ip pref 1 bpf
filter protocol ip pref 1 bpf handle 0x1 prog_clatd_schedcls_egress_clat_rawip:[*fsobj] direct-action

Test: compiles, atest, flashed to ipv6only cellular/wifi connected
      phone and observed tc filter setup on v4-* interfaces
Bug: 139396664
Signed-off-by: Maciej Żenczykowski <maze@google.com>
Change-Id: I75fd3de3b47d2e9f0321f946888169cbc797ba6a
diff --git a/server/ClatdController.cpp b/server/ClatdController.cpp
index cc34b65..ec64d29 100644
--- a/server/ClatdController.cpp
+++ b/server/ClatdController.cpp
@@ -292,6 +292,14 @@
             return;
     }
 
+    // This program will be attached to the v4-* interface which is a TUN and thus always rawip.
+    rv = getClatEgressProgFd(false);
+    if (rv < 0) {
+        ALOGE("getClatEgressProgFd(false) failure: %s", strerror(-rv));
+        return;
+    }
+    unique_fd txRawIpProgFd(rv);
+
     rv = getClatIngressProgFd(isEthernet);
     if (rv < 0) {
         ALOGE("getClatIngressProgFd(%d) failure: %s", isEthernet, strerror(-rv));
@@ -365,6 +373,32 @@
         return;
     }
 
+    rv = tcFilterAddDevEgressBpf(mNetlinkFd, tracker.v4ifIndex, txRawIpProgFd, false);
+    if (rv) {
+        if ((rv == -ENOENT) && (mClatEbpfMode == ClatEbpfMaybe)) {
+            ALOGI("tcFilterAddDevEgressBpf(%d[%s], false): %s", tracker.v4ifIndex, tracker.v4iface,
+                  strerror(-rv));
+        } else {
+            ALOGE("tcFilterAddDevEgressBpf(%d[%s], false) failure: %s", tracker.v4ifIndex,
+                  tracker.v4iface, strerror(-rv));
+        }
+        rv = tcQdiscDelDevClsact(mNetlinkFd, tracker.ifIndex);
+        if (rv) {
+            ALOGE("tcQdiscDelDevClsact(%d[%s]) failure: %s", tracker.ifIndex, tracker.iface,
+                  strerror(-rv));
+        }
+        rv = tcQdiscDelDevClsact(mNetlinkFd, tracker.v4ifIndex);
+        if (rv) {
+            ALOGE("tcQdiscDelDevClsact(%d[%s]) failure: %s", tracker.v4ifIndex, tracker.v4iface,
+                  strerror(-rv));
+        }
+        ret = mClatEgressMap.deleteValue(txKey);
+        if (!isOk(ret)) ALOGE("mClatEgressMap.deleteValue failure: %s", strerror(ret.code()));
+        ret = mClatIngressMap.deleteValue(rxKey);
+        if (!isOk(ret)) ALOGE("mClatIngressMap.deleteValue failure: %s", strerror(ret.code()));
+        return;
+    }
+
     rv = tcFilterAddDevIngressBpf(mNetlinkFd, tracker.ifIndex, rxProgFd, isEthernet);
     if (rv) {
         if ((rv == -ENOENT) && (mClatEbpfMode == ClatEbpfMaybe)) {