def flow_table(name, table): print("\nflow table name: %s\nflow table id: %x table_level: %x, \ type: %x (FS_FT_FDB: %d, FS_FT_NIC_RX: %d, max_fte: %d, %x), refcount: %d" % \ (name, table.id.value_(), table.level.value_(), table.type, \ prog['FS_FT_FDB'], prog['FS_FT_NIC_RX'], table.max_fte, table.max_fte, \ table.node.refcount.refs.counter)) print("mlx5_flow_table %lx" % table.value_()) # print("flow table address") # print("%lx" % table.value_()) fs_node = Object(prog, 'struct fs_node', address=table.value_()) # print("%lx" % fs_node.address_of_()) # print(fs_node) group_addr = fs_node.address_of_() # print("fs_node address") # print("%lx" % group_addr.value_()) group_addr = fs_node.children.address_of_() # print(group_addr) for group in list_for_each_entry('struct fs_node', group_addr, 'list'): print("mlx5_flow_group %lx" % group) fte_addr = group.children.address_of_() for fte in list_for_each_entry('struct fs_node', fte_addr, 'list'): fs_fte = Object(prog, 'struct fs_fte', address=fte.value_()) print_match(fs_fte) if fs_fte.action.action & 0x40: print("modify_hdr id: %x" % fs_fte.action.modify_hdr.id) dest_addr = fte.children.address_of_() for dest in list_for_each_entry('struct fs_node', dest_addr, 'list'): rule = Object(prog, 'struct mlx5_flow_rule', address=dest.value_()) print_dest(rule)
def test_float(self): obj = Object(self.prog, "double", value=3.14) self.assertIs(obj.prog_, self.prog) self.assertIdentical(obj.type_, self.prog.type("double")) self.assertFalse(obj.absent_) self.assertIsNone(obj.address_) self.assertEqual(obj.value_(), 3.14) self.assertEqual(repr(obj), "Object(prog, 'double', value=3.14)") obj = Object(self.prog, "double", value=-100.0) self.assertIdentical(Object(self.prog, "double", value=-100), obj) self.assertRaisesRegex( TypeError, "'double' value must be number", Object, self.prog, "double", value={}, ) self.assertEqual(Object(self.prog, "double", value=math.e).value_(), math.e) self.assertEqual( Object(self.prog, "float", value=math.e).value_(), struct.unpack("f", struct.pack("f", math.e))[0], )
def get_mlx5_core_devs(): devs = {} bus_type = prog["pci_bus_type"] subsys_private = bus_type.p k_list = subsys_private.klist_devices.k_list for dev in list_for_each_entry('struct device_private', k_list.address_of_(), 'knode_bus.n_node'): addr = dev.value_() device_private = Object(prog, 'struct device_private', address=addr) device = device_private.device # struct pci_dev { # struct device dev; # } pci_dev = container_of(device, "struct pci_dev", "dev") driver_data = device.driver_data mlx5_core = Object(prog, 'struct mlx5_core_dev', address=driver_data) driver = device.driver if driver_data.value_(): name = driver.name.string_().decode() if name == "mlx5_core": pci_name = device.kobj.name.string_().decode() index = pci_name.split('.')[1] devs[int(index)] = mlx5_core return devs
def test_init(self): m = TypeMember(self.prog.void_type()) self.assertIdentical(m.object, Object(self.prog, self.prog.void_type())) self.assertIdentical(m.type, self.prog.void_type()) self.assertIsNone(m.name) self.assertEqual(m.bit_offset, 0) self.assertEqual(m.offset, 0) self.assertIsNone(m.bit_field_size) m = TypeMember(Object(self.prog, self.prog.void_type()), "foo") self.assertIdentical(m.object, Object(self.prog, self.prog.void_type())) self.assertIdentical(m.type, self.prog.void_type()) self.assertEqual(m.name, "foo") self.assertEqual(m.bit_offset, 0) self.assertEqual(m.offset, 0) self.assertIsNone(m.bit_field_size) m = TypeMember(self.prog.void_type(), "foo", 8) self.assertIdentical(m.object, Object(self.prog, self.prog.void_type())) self.assertIdentical(m.type, self.prog.void_type()) self.assertEqual(m.name, "foo") self.assertEqual(m.bit_offset, 8) self.assertEqual(m.offset, 1) self.assertIsNone(m.bit_field_size) self.assertRaises(TypeError, TypeMember, None) self.assertRaises(TypeError, TypeMember, self.prog.void_type(), 1) self.assertRaises(TypeError, TypeMember, self.prog.void_type(), "foo", None)
def test_dir(self): obj = Object(self.prog, "int", value=0) self.assertEqual(dir(obj), sorted(object.__dir__(obj))) obj = Object(self.prog, self.point_type, address=0xFFFF0000) self.assertEqual(dir(obj), sorted(object.__dir__(obj) + ["x", "y"])) self.assertEqual(dir(obj.address_of_()), dir(obj))
def flow_table2(name, table): print("\nflow table name: %s\nflow table id: %x leve: %x, type: %x (FS_FT_FDB: %d, FS_FT_NIC_RX: %d)" % \ (name, table.id.value_(), table.level.value_(), table.type, prog['FS_FT_FDB'], prog['FS_FT_NIC_RX'])) print("mlx5_flow_table %lx" % table.address_of_()) # print("flow table address") # print("%lx" % table.value_()) fs_node = Object(prog, 'struct fs_node', address=table.address_of_()) # print("%lx" % fs_node.address_of_()) # print(fs_node) group_addr = fs_node.address_of_() # print("fs_node address") # print("%lx" % group_addr.value_()) group_addr = fs_node.children.address_of_() # print(group_addr) for group in list_for_each_entry('struct fs_node', group_addr, 'list'): print("mlx5_flow_group %lx" % group) fte_addr = group.children.address_of_() for fte in list_for_each_entry('struct fs_node', fte_addr, 'list'): fs_fte = Object(prog, 'struct fs_fte', address=fte.value_()) print_match(fs_fte) dest_addr = fte.children.address_of_() for dest in list_for_each_entry('struct fs_node', dest_addr, 'list'): rule = Object(prog, 'struct mlx5_flow_rule', address=dest.value_()) print_dest(rule)
def test_init(self): p = TypeTemplateParameter(self.prog.void_type()) self.assertIdentical(p.argument, self.prog.void_type()) self.assertIsNone(p.name) self.assertFalse(p.is_default) p = TypeTemplateParameter( Object(self.prog, self.prog.int_type("int", 4, True), 5), "foo", True) self.assertIdentical( p.argument, Object(self.prog, self.prog.int_type("int", 4, True), 5)) self.assertEqual(p.name, "foo") self.assertTrue(p.is_default) self.assertRaises(TypeError, TypeTemplateParameter, None) self.assertRaisesRegex( ValueError, "must not be absent Object", TypeTemplateParameter, Object(self.prog, "int"), ) self.assertRaises(TypeError, TypeTemplateParameter, self.prog.void_type(), 1) self.assertRaises(TypeError, TypeTemplateParameter, self.prog.void_type(), None, None)
def test_overflow(self): Object(self.prog, "char", address=0xFFFFFFFFFFFFFFFF) Object( self.prog, "char", address=0xFFFFFFFFFFFFFFFF, bit_field_size=1, bit_offset=7, )
def test_len(self): self.assertEqual(len(Object(self.prog, "int [0]", address=0)), 0) self.assertEqual(len(Object(self.prog, "int [10]", address=0)), 10) self.assertRaisesRegex( TypeError, "'int' has no len()", len, Object(self.prog, "int", address=0) ) self.assertRaisesRegex( TypeError, r"'int \[\]' has no len()", len, Object(self.prog, "int []", address=0), )
def test_int(self): self.assertEqual(int(Object(self.prog, "int", value=-1)), -1) self.assertEqual(int(Object(self.prog, "unsigned int", value=1)), 1) self.assertEqual(int(Object(self.prog, "double", value=9.99)), 9) self.assertEqual(int(Object(self.prog, "int *", value=0)), 0) self.assertRaisesRegex( TypeError, r"cannot convert 'int \[\]' to int", int, Object(self.prog, "int []", address=0), )
def test_array(self): segment = bytearray() for i in range(10): segment.extend(i.to_bytes(4, "little")) self.add_memory_segment(segment, virt_addr=0xFFFF0000) obj = Object(self.prog, "int [5]", address=0xFFFF0000) self.assertEqual(obj.value_(), [0, 1, 2, 3, 4]) self.assertEqual(sizeof(obj), 20) obj = Object(self.prog, "int [2][5]", address=0xFFFF0000) self.assertEqual(obj.value_(), [[0, 1, 2, 3, 4], [5, 6, 7, 8, 9]]) obj = Object(self.prog, "int [2][2][2]", address=0xFFFF0000) self.assertEqual(obj.value_(), [[[0, 1], [2, 3]], [[4, 5], [6, 7]]])
def test_iter(self): obj = Object(self.prog, "int [4]", value=[0, 1, 2, 3]) for i, element in enumerate(obj): self.assertIdentical(element, Object(self.prog, "int", value=i)) self.assertEqual(operator.length_hint(iter(obj)), 4) self.assertRaisesRegex( TypeError, "'int' is not iterable", iter, Object(self.prog, "int", value=0) ) self.assertRaisesRegex( TypeError, r"'int \[\]' is not iterable", iter, Object(self.prog, "int []", address=0), )
def test_string(self): self.add_memory_segment( b"\x00\x00\xff\xff\x00\x00\x00\x00", virt_addr=0xFFFEFFF8 ) self.add_memory_segment(b"hello\0world\0", virt_addr=0xFFFF0000) strings = [ (Object(self.prog, "char *", address=0xFFFEFFF8), b"hello"), (Object(self.prog, "char [2]", address=0xFFFF0000), b"he"), (Object(self.prog, "char [8]", address=0xFFFF0000), b"hello"), ] for obj, expected in strings: with self.subTest(obj=obj): self.assertEqual(obj.string_(), expected) self.assertEqual(obj.read_().string_(), expected) strings = [ Object(self.prog, "char []", address=0xFFFF0000), Object(self.prog, "int []", address=0xFFFF0000), Object(self.prog, "int [2]", address=0xFFFF0000), Object(self.prog, "int *", value=0xFFFF0000), ] for obj in strings: self.assertEqual(obj.string_(), b"hello") self.assertRaisesRegex( TypeError, "must be an array or pointer", Object(self.prog, "int", value=1).string_, )
def test_callable(self): m = TypeMember(self.prog.void_type) self.assertIdentical(m.object, Object(self.prog, self.prog.void_type())) self.assertIdentical(m.type, self.prog.void_type()) m = TypeMember( lambda: Object(self.prog, self.prog.int_type("int", 4, True))) self.assertIdentical( m.object, Object(self.prog, self.prog.int_type("int", 4, True))) self.assertIdentical(m.type, self.prog.int_type("int", 4, True)) m = TypeMember(lambda: None) self.assertRaises(TypeError, getattr, m, "type")
def test_callable(self): p = TypeTemplateParameter(self.prog.void_type) self.assertIdentical(p.argument, self.prog.void_type()) p = TypeTemplateParameter( lambda: Object(self.prog, self.prog.int_type("int", 4, True), 5)) self.assertIdentical( p.argument, Object(self.prog, self.prog.int_type("int", 4, True), 5)) p = TypeTemplateParameter(lambda: None) self.assertRaises(TypeError, getattr, p, "argument") p = TypeTemplateParameter(lambda: Object(self.prog, "int")) self.assertRaisesRegex(ValueError, "must not return absent Object", getattr, p, "argument")
def test_reinterpret_reference(self): obj = Object(self.prog, "int", address=0xFFFF0000) self.assertIdentical(reinterpret("int", obj), obj) self.assertIdentical( reinterpret(self.prog.int_type("int", 4, True, "big"), obj), Object( self.prog, self.prog.int_type("int", 4, True, "big"), address=0xFFFF0000 ), ) obj = Object(self.prog, "int []", address=0xFFFF0000) self.assertIdentical( reinterpret("int [4]", obj), Object(self.prog, "int [4]", address=0xFFFF0000), )
def test_basic(self): for obj in [ Object(self.prog, "int"), Object(self.prog, "int", value=None, address=None), ]: self.assertIs(obj.prog_, self.prog) self.assertIdentical(obj.type_, self.prog.type("int")) self.assertTrue(obj.absent_) self.assertIsNone(obj.address_) self.assertIsNone(obj.bit_offset_) self.assertIsNone(obj.bit_field_size_) self.assertRaises(ObjectAbsentError, obj.value_) self.assertEqual(repr(obj), "Object(prog, 'int')") self.assertRaises(ObjectAbsentError, obj.read_)
def test_callable(self): p = TypeParameter(self.prog.void_type) self.assertIdentical(p.default_argument, Object(self.prog, self.prog.void_type())) self.assertIdentical(p.type, self.prog.void_type()) p = TypeParameter( lambda: Object(self.prog, self.prog.int_type("int", 4, True))) self.assertIdentical( p.default_argument, Object(self.prog, self.prog.int_type("int", 4, True))) self.assertIdentical(p.type, self.prog.int_type("int", 4, True)) p = TypeParameter(lambda: None) self.assertRaises(TypeError, getattr, p, "type")
def get_veth_netdev(veth_name): devs = [] for x, dev in enumerate(get_netdevs()): name = dev.name.string_().decode() if name == veth_name: veth_addr = dev.value_() + prog.type('struct net_device').size veth = Object(prog, 'struct veth_priv', address=veth_addr) devs.append(dev) dev_peer = veth.peer veth_addr = dev_peer.value_() + prog.type('struct net_device').size veth = Object(prog, 'struct veth_priv', address=veth_addr) devs.append(dev) return devs
def test_operators(self): absent = Object(self.prog, "int") obj = Object(self.prog, "int", 1) for op in [ operator.lt, operator.le, operator.eq, operator.ge, operator.gt, operator.add, operator.and_, operator.lshift, operator.mod, operator.mul, operator.or_, operator.rshift, operator.sub, operator.truediv, operator.xor, ]: self.assertRaises(ObjectAbsentError, op, absent, obj) self.assertRaises(ObjectAbsentError, op, obj, absent) for op in [ operator.not_, operator.truth, operator.index, operator.inv, operator.neg, operator.pos, round, math.trunc, math.floor, math.ceil, ]: self.assertRaises(ObjectAbsentError, op, absent) self.assertRaises(ObjectAbsentError, absent.address_of_) self.assertRaises( ObjectAbsentError, operator.getitem, Object(self.prog, "int [2]"), 0, ) self.assertRaises(ObjectAbsentError, Object(self.prog, "char [16]").string_) self.assertRaises(ObjectAbsentError, Object(self.prog, "char *").string_)
def print_flow_act(acts): nlattr = acts.actions[0] nla_type = nlattr.nla_type if nla_type == prog['OVS_ACTION_ATTR_OUTPUT']: addr = nlattr.address_of_().value_() + prog.type('struct nlattr').size port = Object(prog, 'int', address=addr) print("\toutput port: %d" % port.value_())
def _vmemmap(prog): try: # KASAN return cast('struct page *', prog['vmemmap_base']) except KeyError: # x86-64 return Object(prog, 'struct page *', value=0xffffea0000000000)
def test_for_each_set_bit(self): bitmap = Object(self.prog, "unsigned long [2]", self.BITMAP) self.assertEqual(list(for_each_set_bit(bitmap, 128)), self.SET_BITS) self.assertEqual( list(for_each_set_bit(bitmap, 101)), [bit for bit in self.SET_BITS if bit < 101], )
def test_member_out_of_bounds(self): obj = Object( self.prog, self.prog.struct_type("foo", 4, self.point_type.members), address=0xFFFF0000, ).read_() self.assertRaisesRegex(OutOfBoundsError, "out of bounds", getattr, obj, "y")
def test_read_float(self): pi32 = struct.unpack("f", struct.pack("f", math.pi))[0] for bit_size in [32, 64]: for bit_offset in range(8): for byteorder in ["little", "big"]: if bit_size == 64: fmt = "<d" expected = math.pi else: fmt = "<f" expected = pi32 tmp = int.from_bytes(struct.pack(fmt, math.pi), "little") if byteorder == "little": tmp <<= bit_offset else: tmp <<= (8 - bit_size - bit_offset) % 8 buf = tmp.to_bytes((bit_size + bit_offset + 7) // 8, byteorder) prog = mock_program(segments=[MockMemorySegment(buf, 0)]) obj = Object( prog, prog.float_type( "double" if bit_size == 64 else "float", bit_size // 8, byteorder, ), address=0, bit_offset=bit_offset, ) self.assertEqual(obj.value_(), expected)
def _vmemmap(prog): try: # KASAN return cast("struct page *", prog["vmemmap_base"]) except KeyError: # x86-64 return Object(prog, "struct page *", value=0xFFFFEA0000000000)
def print_files(files, n): for i in range(n): file = files[i] print("%2d" % i, end='\t') if file.f_op.value_() == eventpoll_fops: print_eventpoll(file) elif file.f_op.value_() == socket_file_ops: sock = Object(prog, "struct socket", address=file.private_data) sk = sock.sk if sock.ops.value_() == netlink_ops: netlink_sock = cast('struct netlink_sock *', sk) print_netlink_sock(netlink_sock) elif sock.ops.value_() == inet_dgram_ops: print_udp_sock(sk) else: print('') elif file.f_op.value_() == pipefifo_fops: print('pipefifo_fops') elif file.f_op.value_() == null_fops: print('null_fops') elif file.f_op.value_() == xfs_file_operations: print('xfs_file_operations') elif file.f_op.value_() == shmem_file_operations: print('shmem_file_operations') else: print(file.f_op)
def print_mlx5_vport(priv): mlx5_eswitch = mlx5e_priv.mdev.priv.eswitch vports = mlx5_eswitch.vports total_vports = mlx5_eswitch.total_vports enabled_vports = mlx5_eswitch.enabled_vports print("total_vports: %d" % total_vports) print("enabled_vports: %d" % enabled_vports) uplink_idx = total_vports - 1 # uplink_vport = vports[uplink_idx] # print(vports) def print_vport(vport): group = vport.qos.group if group.value_() == 0: return print("mlx5_vport %x" % vport.address_of_(), end=' ') print("vport: %4x, %4d, metadata: %4x" % (vport.vport, vport.vport, vport.metadata), end=' ') print_mac(vport.info.mac) print("\tdevlink_port %18x" % vport.dl_port.value_(), end=' ') print("vport: %5x" % vport.vport, end=' ') print("enabled: %x" % vport.enabled, end=' ') print(vport.qos) print('') for node in radix_tree_for_each(vports.address_of_()): mlx5_vport = Object(prog, 'struct mlx5_vport', address=node[1].value_()) # if mlx5_vport.vport < 4: print_vport(mlx5_vport)
def print_fib(fib): trie = fib.tb_data print(fib) trie = Object(prog, 'struct trie', address=trie) print(trie) kv = trie.kv print(kv) print("key_vector %lx" % kv.address_of_()) print("key_vector %lx" % kv[0].tnode[0].value_()) print(type(kv)) for i in range(32): if IS_TRIE(kv[i]): print("kv[%d] is TRIE" % i) if IS_TNODE(kv[i]): print("kv[%d] is TNODE" % i) print(kv[i]) print("key[%d]: %x, ip: %s" % (i, kv[i].key, lib.ipv4(socket.ntohl(kv[i].key.value_())))) break if IS_LEAF(kv[i]): print("kv[%d] is LEAF" % i) for n in hlist_for_each_entry('struct fib_alias', leaf.address_of_(), 'fa_list'): print(n)
def get_mlx5_ib_dev(): mlx5e_priv = get_mlx5_pf0() # struct mlx5_esw_offload offloads = mlx5e_priv.mdev.priv.eswitch.offloads total_vports = mlx5e_priv.mdev.priv.eswitch.total_vports.value_() # print("total_vports: %d" % total_vports) # struct mlx5_eswitch_rep if kernel("4.20.16+") or kernel("4.20.0-rc1+"): mlx5_eswitch_rep = offloads.vport_reps[0] else: mlx5_eswitch_rep = offloads.vport_reps[total_vports - 1] # print(mlx5_eswitch_rep) # for i in range(total_vports): # print("%lx" % offloads.vport_reps[i].address_of_()) # print("%lx" % vport.address_of_()) # struct mlx5_eswitch_rep_if rep_if = mlx5_eswitch_rep.rep_if # struct mlx5e_rep_priv priv = rep_if[prog['REP_IB']].priv # print("priv: %lx" % priv.value_()) mlx5_ib_dev = Object(prog, 'struct mlx5_ib_dev', address=priv.value_()) return mlx5_ib_dev