summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authordennishan <dennishan@realtek.com>2020-06-08 19:01:42 +0800
committerMaciej Żenczykowski <maze@google.com>2020-06-09 20:49:06 +0000
commit73cf98163867a226979341760ff42c82d608b11c (patch)
treeaacfc971950269e36988d5a3df82ba5c16ad2a46
parentd8385e2e7f732a73e9fe9130d3a974d1254681d1 (diff)
downloadkernel_tests-73cf98163867a226979341760ff42c82d608b11c.tar.gz
kernel_tests-73cf98163867a226979341760ff42c82d608b11c.tar.bz2
kernel_tests-73cf98163867a226979341760ff42c82d608b11c.zip
net-test: attempt to use namespaces on devices with ADB/TCP
Update all_tests.py and add namespace.py from master branch. Bug: 149894399 Test: run vts -m VtsKernelNetTest -s 192.168.1.100:5555 Change-Id: I00829029fea63a58a548455ed2edcbd7c5ae2b62 Merged-In: I2e5d136322ade41bfefcb46437b61a68fb842e15
-rwxr-xr-xnet/test/all_tests.py20
-rw-r--r--net/test/namespace.py165
2 files changed, 181 insertions, 4 deletions
diff --git a/net/test/all_tests.py b/net/test/all_tests.py
index bbef3ac4..17d9701d 100755
--- a/net/test/all_tests.py
+++ b/net/test/all_tests.py
@@ -14,10 +14,12 @@
# See the License for the specific language governing permissions and
# limitations under the License.
-from importlib import import_module
+import importlib
import sys
import unittest
+import namespace
+
test_modules = [
'anycast_test',
'bpf_test',
@@ -46,15 +48,25 @@ test_modules = [
]
if __name__ == '__main__':
+ # Check whether ADB over TCP is occupying TCP port 5555.
+ if namespace.HasEstablishedTcpSessionOnPort(5555):
+ namespace.IfPossibleEnterNewNetworkNamespace()
# First, run InjectTests on all modules, to ensure that any parameterized
# tests in those modules are injected.
for name in test_modules:
- import_module(name)
- if hasattr(sys.modules[name], "InjectTests"):
+ importlib.import_module(name)
+ if hasattr(sys.modules[name], 'InjectTests'):
sys.modules[name].InjectTests()
loader = unittest.defaultTestLoader
- test_suite = loader.loadTestsFromNames(test_modules)
+ if len(sys.argv) > 1:
+ test_suite = loader.loadTestsFromNames(sys.argv[1:])
+ else:
+ test_suite = loader.loadTestsFromNames(test_modules)
+
+ assert test_suite.countTestCases() > 0, (
+ 'Inconceivable: no tests found! Command line: %s' % ' '.join(sys.argv))
+
runner = unittest.TextTestRunner(verbosity=2)
result = runner.run(test_suite)
sys.exit(not result.wasSuccessful())
diff --git a/net/test/namespace.py b/net/test/namespace.py
new file mode 100644
index 00000000..85db6541
--- /dev/null
+++ b/net/test/namespace.py
@@ -0,0 +1,165 @@
+#!/usr/bin/python
+#
+# Copyright 2020 The Android Open Source Project
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+"""Namespace related support code."""
+
+import ctypes
+import ctypes.util
+import os
+import socket
+
+import net_test
+import sock_diag
+import tcp_test
+
+# //include/linux/fs.h
+MNT_FORCE = 1 # Attempt to forcibily umount
+MNT_DETACH = 2 # Just detach from the tree
+MNT_EXPIRE = 4 # Mark for expiry
+UMOUNT_NOFOLLOW = 8 # Don't follow symlink on umount
+
+# //include/uapi/linux/fs.h
+MS_RDONLY = 1 # Mount read-only
+MS_NOSUID = 2 # Ignore suid and sgid bits
+MS_NODEV = 4 # Disallow access to device special files
+MS_NOEXEC = 8 # Disallow program execution
+MS_SYNCHRONOUS = 16 # Writes are synced at once
+MS_REMOUNT = 32 # Alter flags of a mounted FS
+MS_MANDLOCK = 64 # Allow mandatory locks on an FS
+MS_DIRSYNC = 128 # Directory modifications are synchronous
+MS_NOATIME = 1024 # Do not update access times.
+MS_NODIRATIME = 2048 # Do not update directory access times
+MS_BIND = 4096 #
+MS_MOVE = 8192 #
+MS_REC = 16384 #
+MS_SILENT = 32768 #
+MS_POSIXACL = (1<<16) # VFS does not apply the umask
+MS_UNBINDABLE = (1<<17) # change to unbindable
+MS_PRIVATE = (1<<18) # change to private
+MS_SLAVE = (1<<19) # change to slave
+MS_SHARED = (1<<20) # change to shared
+MS_RELATIME = (1<<21) # Update atime relative to mtime/ctime.
+MS_STRICTATIME = (1<<24) # Always perform atime updates
+MS_LAZYTIME = (1<<25) # Update the on-disk [acm]times lazily
+
+# //include/uapi/linux/sched.h
+CLONE_NEWNS = 0x00020000 # New mount namespace group
+CLONE_NEWCGROUP = 0x02000000 # New cgroup namespace
+CLONE_NEWUTS = 0x04000000 # New utsname namespace
+CLONE_NEWIPC = 0x08000000 # New ipc namespace
+CLONE_NEWUSER = 0x10000000 # New user namespace
+CLONE_NEWPID = 0x20000000 # New pid namespace
+CLONE_NEWNET = 0x40000000 # New network namespace
+
+libc = ctypes.CDLL(ctypes.util.find_library('c'), use_errno=True)
+
+# See the relevant system call's man pages and:
+# https://docs.python.org/3/library/ctypes.html#fundamental-data-types
+libc.mount.argtypes = (ctypes.c_char_p, ctypes.c_char_p, ctypes.c_char_p,
+ ctypes.c_ulong, ctypes.c_void_p)
+libc.sethostname.argtype = (ctypes.c_char_p, ctypes.c_size_t)
+libc.umount2.argtypes = (ctypes.c_char_p, ctypes.c_int)
+libc.unshare.argtypes = (ctypes.c_int,)
+
+
+def Mount(src, tgt, fs, flags=MS_NODEV|MS_NOEXEC|MS_NOSUID|MS_RELATIME):
+ ret = libc.mount(src, tgt, fs, flags, None)
+ if ret < 0:
+ errno = ctypes.get_errno()
+ raise OSError(errno, '%s mounting %s on %s (fs=%s flags=0x%x)'
+ % (os.strerror(errno), src, tgt, fs, flags))
+
+
+def ReMountProc():
+ libc.umount2('/proc', MNT_DETACH) # Ignore failure: might not be mounted
+ Mount('proc', '/proc', 'proc')
+
+
+def ReMountSys():
+ libc.umount2('/sys', MNT_DETACH) # Ignore failure: might not be mounted
+ Mount('sysfs', '/sys', 'sysfs')
+
+
+def SetFileContents(f, s):
+ open(f, 'w').write(s)
+
+
+def SetHostname(s):
+ ret = libc.sethostname(s, len(s))
+ if ret < 0:
+ errno = ctypes.get_errno()
+ raise OSError(errno, '%s while sethostname(%s)' % (os.strerror(errno), s))
+
+
+def UnShare(flags):
+ ret = libc.unshare(flags)
+ if ret < 0:
+ errno = ctypes.get_errno()
+ raise OSError(errno, '%s while unshare(0x%x)' % (os.strerror(errno), flags))
+
+
+def DumpMounts(hdr):
+ print
+ print hdr
+ print open('/proc/mounts', 'r').read(),
+ print '---'
+
+
+# Requires at least kernel configuration options:
+# CONFIG_NAMESPACES=y
+# CONFIG_NET_NS=y
+# CONFIG_UTS_NS=y
+def IfPossibleEnterNewNetworkNamespace():
+ """Instantiate and transition into a fresh new network namespace if possible."""
+
+ print 'Creating clean namespace...',
+
+ try:
+ UnShare(CLONE_NEWNS | CLONE_NEWUTS | CLONE_NEWNET)
+ except OSError as err:
+ print 'failed: %s (likely: no privs or lack of kernel support).' % err
+ return False
+
+ try:
+ # DumpMounts('Before:')
+ Mount('none', '/', None, MS_REC|MS_PRIVATE)
+ ReMountProc()
+ ReMountSys()
+ # DumpMounts('After:')
+ SetHostname('netns')
+ SetFileContents('/proc/sys/net/ipv4/ping_group_range', '0 2147483647')
+ net_test.SetInterfaceUp('lo')
+ except:
+ print 'failed.'
+ # We've already transitioned into the new netns -- it's too late to recover.
+ raise
+
+ print 'succeeded.'
+ return True
+
+
+def HasEstablishedTcpSessionOnPort(port):
+ sd = sock_diag.SockDiag()
+
+ sock_id = sd._EmptyInetDiagSockId()
+ sock_id.sport = port
+
+ states = 1 << tcp_test.TCP_ESTABLISHED
+
+ matches = sd.DumpAllInetSockets(socket.IPPROTO_TCP, "",
+ sock_id=sock_id, states=states)
+
+ return len(matches) > 0