Scripts/programs to test FreeBSD ethernet interfaces.
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 

158 lines
3.2 KiB

  1. import os
  2. import sys
  3. import unittest
  4. from ctypes import *
  5. __all__ = [ 'KVM' ]
  6. _kvm = CDLL('libkvm.so')
  7. class kvm_t(Structure):
  8. pass
  9. class timespec(Structure):
  10. _fields_ = [
  11. ('tv_sec', c_ulong),
  12. ('tv_nsec', c_long),
  13. ]
  14. KVM_K_UNSIGNED_INT = 1
  15. KVM_K_SIGNED_INT = 2
  16. _bytesizes = [ 1, 2, 4, 8 ]
  17. _ttvlookup = [ ((KVM_K_UNSIGNED_INT, x), globals()['c_uint%d' % (x * 8)]) for x
  18. in _bytesizes ] + [ ((KVM_K_SIGNED_INT, x),
  19. globals()['c_int%d' % (x * 8)]) for x in _bytesizes ]
  20. _ttvlookup = { k: POINTER(v) for k, v in _ttvlookup }
  21. kvm_t_p = POINTER(kvm_t)
  22. kvm_iter_struct_t = CFUNCTYPE(c_int, c_char_p, c_int, c_size_t,
  23. POINTER(c_char), c_void_p)
  24. _funs = dict(
  25. kvm_open=(kvm_t_p, (c_char_p, c_char_p, c_char_p, c_int, c_char_p)),
  26. kvm_close=(c_int, (kvm_t_p,)),
  27. kvm_geterr=(c_char_p, (kvm_t_p,)),
  28. kvm_structsize=(c_ssize_t, (kvm_t_p, c_char_p)),
  29. kvm_iterstruct=(c_int, (kvm_t_p, c_char_p, c_void_p,
  30. kvm_iter_struct_t, c_void_p)),
  31. )
  32. for k, v in _funs.items():
  33. f = getattr(_kvm, k)
  34. f.restype, f.argtypes = v
  35. def _fetchmembers(kd, typ, obj):
  36. res = []
  37. def func(memb, type, len, buf, arg):
  38. t = _ttvlookup[(type, len)]
  39. res.append((memb, cast(buf, t)[0]))
  40. return 0
  41. cbfun = kvm_iter_struct_t(func)
  42. r = _kvm.kvm_iterstruct(kd, typ, byref(obj), cbfun, None)
  43. if r == -1:
  44. err = _kvm.kvm_geterr(kd)
  45. raise RuntimeError(err.decode('us-ascii'))
  46. return res
  47. class KVM(object):
  48. def __init__(self):
  49. self.kd = _kvm.kvm_open(None, None, None, os.O_RDONLY, None)
  50. def __enter__(self):
  51. return self
  52. def close(self):
  53. if self.kd is not None:
  54. _kvm.kvm_close(self.kd)
  55. self.kd = None
  56. def __exit__(self, a, b, c):
  57. self.close()
  58. def _iferr(self, fun, *args):
  59. res = fun(*args)
  60. if res == -1:
  61. err = _kvm.kvm_geterr(self.kd)
  62. raise RuntimeError(err.decode('us-ascii'))
  63. return res
  64. def structsize(self, typ):
  65. return self._iferr(_kvm.kvm_structsize, self.kd,
  66. typ.encode('us-ascii'))
  67. def getstruct(self, typ, obj):
  68. res = _fetchmembers(self.kd, typ.encode('us-ascii'), obj)
  69. return { k.decode('us-ascii'): v for k, v in res }
  70. def __del__(self):
  71. self.close()
  72. def deb(*args):
  73. if True: #pragma: no cover
  74. print(*args)
  75. sys.stdout.flush()
  76. class _TestCase(unittest.TestCase):
  77. def setUp(self):
  78. self.kd = _kvm.kvm_open(None, None, None, os.O_RDONLY, None)
  79. def tearDown(self):
  80. _kvm.kvm_close(self.kd)
  81. self.kd = None
  82. def test_ss(self):
  83. self.assertEqual(_kvm.kvm_structsize(self.kd,
  84. b'struct timespec'), 16)
  85. def test_iter(self):
  86. exp = [
  87. (b'tv_sec', 0x1234),
  88. (b'tv_nsec', 0xabcd),
  89. ]
  90. ts = timespec(0x1234, 0xabcd)
  91. res = _fetchmembers(self.kd, b'struct timespec', ts)
  92. self.assertEqual(res, exp)
  93. def test_class_errs(self):
  94. kd = KVM()
  95. self.assertEqual(kd.structsize('struct timespec'), 16)
  96. sec = 1839238
  97. nsec = 19849873
  98. ts = timespec(sec, nsec)
  99. res = dict(
  100. tv_sec=sec,
  101. tv_nsec=nsec,
  102. )
  103. self.assertEqual(kd.getstruct('struct timespec', ts), res)
  104. def test_class(self):
  105. kd = KVM()
  106. with KVM() as kd:
  107. with self.assertRaisesRegex(RuntimeError,
  108. 'unable to find kernel type: struct flksjdi'):
  109. kd.structsize('struct flksjdi')
  110. ts = timespec(0, 0)
  111. with self.assertRaisesRegex(RuntimeError,
  112. 'unable to find kernel type: struct weoiud'):
  113. kd.getstruct('struct weoiud', ts)