Make BPF tests pass on device.

1. Add __NR_bpf constants for armv8l and aarch64.
2. Move the temporary cgroup BPF mount from /tmp (which does not
   exist on device) to a temporary directory.
3. Use proper ctypes functions to pass pointers.

Bug: 36510518
Test: all_tests.sh passes on android-4.9
Test: 32-bit and 64-bit BPF tests pass on 4.9 device
Change-Id: Id3cca05d8ea547aeaa5cfd1d2d88b22115fe432d
diff --git a/net/test/bpf.py b/net/test/bpf.py
index 9e8cf1e..a96a95a 100755
--- a/net/test/bpf.py
+++ b/net/test/bpf.py
@@ -15,15 +15,20 @@
 # limitations under the License.
 
 import ctypes
+import os
 
 import csocket
 import cstruct
 import net_test
 import socket
 
-# TODO: figure out how to make this arch-dependent if we run these tests
-# on non-X86
-__NR_bpf = 321
+# __NR_bpf syscall numbers for various architectures.
+# TODO: is there a better way of doing this?
+__NR_bpf = {
+    "aarch64": 280,
+    "armv8l": 386,
+    "x86_64": 321}[os.uname()[4]]
+
 LOG_LEVEL = 1
 LOG_SIZE = 65536
 
@@ -159,7 +164,7 @@
 
 # BPF program syscalls
 def BpfSyscall(op, attr):
-  ret = libc.syscall(__NR_bpf, op, attr.CPointer(), len(attr))
+  ret = libc.syscall(__NR_bpf, op, csocket.VoidPointer(attr), len(attr))
   csocket.MaybeRaiseSocketError(ret)
   return ret
 
@@ -214,9 +219,9 @@
 
 # Attach a socket eBPF filter to a target socket
 def BpfProgAttachSocket(sock_fd, prog_fd):
-  prog_ptr = ctypes.c_uint32(prog_fd)
+  uint_fd = ctypes.c_uint32(prog_fd)
   ret = libc.setsockopt(sock_fd, socket.SOL_SOCKET, SO_ATTACH_BPF,
-                        ctypes.addressof(prog_ptr), ctypes.sizeof(prog_ptr))
+                        ctypes.pointer(uint_fd), ctypes.sizeof(uint_fd))
   csocket.MaybeRaiseSocketError(ret)
 
 # Attach a eBPF filter to a cgroup
diff --git a/net/test/bpf_test.py b/net/test/bpf_test.py
index f0505a7..7014da4 100755
--- a/net/test/bpf_test.py
+++ b/net/test/bpf_test.py
@@ -19,6 +19,8 @@
 import os
 import socket
 import struct
+import subprocess
+import tempfile
 import unittest
 
 from bpf import *  # pylint: disable=wildcard-import
@@ -281,15 +283,22 @@
 
   @classmethod
   def setUpClass(cls):
-    if not os.path.isdir("/tmp"):
-      os.mkdir('/tmp')
-    os.system('mount -t cgroup2 cg_bpf /tmp')
-    cls._cg_fd = os.open('/tmp', os.O_DIRECTORY | os.O_RDONLY)
+    cls._cg_dir = tempfile.mkdtemp(prefix="cg_bpf-")
+    cmd = "mount -t cgroup2 cg_bpf %s" % cls._cg_dir
+    try:
+      subprocess.check_call(cmd.split())
+    except subprocess.CalledProcessError:
+      # If an exception is thrown in setUpClass, the test fails and
+      # tearDownClass is not called.
+      os.rmdir(cls._cg_dir)
+      raise
+    cls._cg_fd = os.open(cls._cg_dir, os.O_DIRECTORY | os.O_RDONLY)
 
   @classmethod
   def tearDownClass(cls):
     os.close(cls._cg_fd)
-    os.system('umount cg_bpf')
+    subprocess.call(('umount %s' % cls._cg_dir).split())
+    os.rmdir(cls._cg_dir)
 
   def setUp(self):
     self.prog_fd = -1