Add tests for adding / deleting bpf filter

Bug: 202086915
Bug: 157552970
Test: atest LibTcUtilsTest
Change-Id: I8adcb3df29e4b3e0c558714f90b2840698e40cb9
diff --git a/staticlibs/native/tcutils/tests/tcutils_test.cpp b/staticlibs/native/tcutils/tests/tcutils_test.cpp
index 6f28fbe..0a2be51 100644
--- a/staticlibs/native/tcutils/tests/tcutils_test.cpp
+++ b/staticlibs/native/tcutils/tests/tcutils_test.cpp
@@ -18,9 +18,12 @@
 
 #include <gtest/gtest.h>
 
+#include "kernelversion.h"
 #include <tcutils/tcutils.h>
 
+#include <BpfSyscallWrappers.h>
 #include <errno.h>
+#include <linux/if_ether.h>
 
 namespace android {
 
@@ -75,4 +78,36 @@
   EXPECT_EQ(-EINVAL, tcDeleteQdiscClsact(LOOPBACK_IFINDEX));
 }
 
+TEST(LibTcUtilsTest, AddAndDeleteBpfFilter) {
+  // TODO: this should use bpf_shared.h rather than hardcoding the path
+  static constexpr char bpfProgPath[] =
+      "/sys/fs/bpf/tethering/prog_offload_schedcls_tether_downstream6_ether";
+  const int errNOENT = isAtLeastKernelVersion(4, 19, 0) ? ENOENT : EINVAL;
+
+  // static test values
+  static constexpr bool ingress = true;
+  static constexpr uint16_t prio = 17;
+  static constexpr uint16_t proto = ETH_P_ALL;
+
+  // try to delete missing filter from missing qdisc
+  EXPECT_EQ(-EINVAL, tcDeleteFilter(LOOPBACK_IFINDEX, ingress, prio, proto));
+  // try to attach bpf filter to missing qdisc
+  EXPECT_EQ(-EINVAL, tcAddBpfFilter(LOOPBACK_IFINDEX, ingress, prio, proto,
+                                    bpfProgPath));
+  // add the clsact qdisc
+  EXPECT_EQ(0, tcAddQdiscClsact(LOOPBACK_IFINDEX));
+  // try to delete missing filter when there is a qdisc attached
+  EXPECT_EQ(-errNOENT, tcDeleteFilter(LOOPBACK_IFINDEX, ingress, prio, proto));
+  // add and delete a bpf filter
+  EXPECT_EQ(
+      0, tcAddBpfFilter(LOOPBACK_IFINDEX, ingress, prio, proto, bpfProgPath));
+  EXPECT_EQ(0, tcDeleteFilter(LOOPBACK_IFINDEX, ingress, prio, proto));
+  // try to remove the same filter a second time
+  EXPECT_EQ(-errNOENT, tcDeleteFilter(LOOPBACK_IFINDEX, ingress, prio, proto));
+  // remove the clsact qdisc
+  EXPECT_EQ(0, tcDeleteQdiscClsact(LOOPBACK_IFINDEX));
+  // once again, try to delete missing filter from missing qdisc
+  EXPECT_EQ(-EINVAL, tcDeleteFilter(LOOPBACK_IFINDEX, ingress, prio, proto));
+}
+
 } // namespace android