def lookup(self, key): if not isinstance(key, self.KEY_TYPE): raise TypeError('key {} is not instance of key_type {}'.format( repr(key), repr(self.KEY_TYPE))) key_p = ctypes.cast(ctypes.pointer(key), ctypes.c_char_p) value = self.VALUE_TYPE() value_p = ctypes.cast(ctypes.pointer(value), ctypes.c_char_p) attr = _BpfAttrMapElem( map_fd=self.fd, key=key_p, value_or_next_key=value_p, flags=0, ) attr_p = ctypes.pointer(attr) ret = _syscall.bpf(_MapCmd.LOOKUP_ELEM, attr_p, ctypes.sizeof(attr)) if ret == 0: return value eno = _syscall._get_errno() if eno == errno.ENOENT: raise KeyError(key) raise OSError(eno, 'Failed to lookup bpf map: {}'.format(os.strerror(eno)))
def get_next_key(self, last_key): if not isinstance(last_key, self.KEY_TYPE): raise TypeError('key {} is not instance of key_type {}'.format( repr(last_key), repr(self.KEY_TYPE))) key_p = ctypes.cast(ctypes.pointer(last_key), ctypes.c_char_p) next_key = self.KEY_TYPE() next_key_p = ctypes.cast(ctypes.pointer(next_key), ctypes.c_char_p) attr = _BpfAttrMapElem( map_fd=self.fd, key=key_p, value_or_next_key=next_key_p, flags=0, ) attr_p = ctypes.pointer(attr) ret = _syscall.bpf(_MapCmd.GET_NEXT_KEY, attr_p, ctypes.sizeof(attr)) if ret == 0: return next_key eno = _syscall._get_errno() if eno == errno.ENOENT: return None raise OSError(eno, 'Failed to get next key: {}'.format(os.strerror(eno)))
def perf_event_open(attr, pid=-1, cpu=-1, group_fd=-1, flags=0): _NR_perf_event_open = 298 ret = _syscall.syscall(_NR_perf_event_open, ctypes.byref(attr), pid, cpu, group_fd, flags) if ret < 0: eno = _syscall._get_errno() raise OSError(eno, 'Failed to open perf event: {}'.format(os.strerror(eno))) return ret
def _map_create(map_type, key_size, value_size, max_entries): attr = _BpfAttrMapCreate(map_type=map_type, key_size=key_size, value_size=value_size, max_entries=max_entries, map_flags=0) fd = _syscall.bpf(_MapCmd.CREATE, ctypes.pointer(attr), ctypes.sizeof(attr)) if fd < 0: eno = _syscall._get_errno() raise OSError(eno, 'Failed to create bpf map: {}'.format(os.strerror(eno))) return fd
def _update_elem(fd, key, value): key_p = ctypes.cast(ctypes.pointer(key), ctypes.c_char_p) value_p = ctypes.cast(ctypes.pointer(value), ctypes.c_char_p) attr = _BpfAttrMapElem( map_fd=fd, key=key_p, value_or_next_key=value_p, flags=0, ) attr_p = ctypes.pointer(attr) if _syscall.bpf(_MapCmd.UPDATE_ELEM, attr_p, ctypes.sizeof(attr)) != 0: eno = _syscall._get_errno() raise OSError(eno, 'Failed to update bpf map: {}'.format(os.strerror(eno)))
def __init__(self, data_type, cpu, num_pages=9): self.mm_fd = -1 self.data_type = data_type self.num_pages = num_pages try: attr = pe.PerfEventAttr() attr.type = pe.PERF_TYPE_SOFTWARE attr.config = pe.PERF_COUNT_SW_BPF_OUTPUT attr.sample_type = pe.PERF_SAMPLE_RAW self.mm_fd = pe.perf_event_open(attr, cpu=cpu) if self.mm_fd < 0: eno = _syscall._get_errno() raise OSError( eno, 'Failed to create perf event: {}'.format(os.strerror(eno))) fcntl.ioctl(self.mm_fd, pe.PERF_EVENT_IOC_ENABLE, 0) self.pagesz = resource.getpagesize() self.mm = mmap.mmap(self.mm_fd, self.num_pages * self.pagesz) except Exception: self.close() raise
def _load_prog(prog_type, insns_arr, insns_to_info): log = ctypes.create_string_buffer(2**20) attr = BpfAttrLoadProg( prog_type=prog_type, insn_cnt=len(insns_arr), insns=ctypes.cast(ctypes.byref(insns_arr), ctypes.c_char_p), license=ctypes.c_char_p('GPL'.encode()), log_level=100, log_size=ctypes.sizeof(log), log_buf=ctypes.addressof(log), kern_version=_get_kern_version(), ) fd = _syscall.bpf(BpfCmd.PROG_LOAD, ctypes.pointer(attr), ctypes.sizeof(attr)) if fd < 0: eno = _syscall._get_errno() last_num = None for l in log.value.decode().splitlines(): m = re.match('^(\d+): .*', l) if m is not None: num = int(m.group(1)) if last_num != num and num in insns_to_info: last_num = num if num > 0: print(file=sys.stderr) print(insns_to_info[num], file=sys.stderr) print('', l, file=sys.stderr) print(file=sys.stderr) raise OSError(eno, 'Failed to load bpf prog: {}'.format(os.strerror(eno))) return fd, log.value.decode()