From fd28bef285957d8a4fd53b092e7a095ee3162170 Mon Sep 17 00:00:00 2001 From: "lijindong (C)" <2220386943@qq.com> Date: Thu, 25 Jul 2024 16:23:41 +0800 Subject: [PATCH] add TracePointerHelp --- python/modules/kperf/trace_pointer.py | 181 +++++++++++++++++++++++++- python/tests/test_sampling.py | 27 ++++ 2 files changed, 207 insertions(+), 1 deletion(-) diff --git a/python/modules/kperf/trace_pointer.py b/python/modules/kperf/trace_pointer.py index 34f64ac..b45a583 100644 --- a/python/modules/kperf/trace_pointer.py +++ b/python/modules/kperf/trace_pointer.py @@ -12,6 +12,185 @@ Author: Mr.Li Create: 2024-07-16 Description: kperf trace pointer field obtain """ +from typing import Any +import _libkperf +import ctypes +from .pmu import get_field, get_field_exp, SampleRawField + +SHORT_SIZE = 2 +INT_SIZE = 4 +LONG_SIZE = 8 +LONG_LONG_SIZE = 16 +DATA_LOC_SIZE = 128 +UTF_8 = "utf-8" + + +class TracePointerException(Exception): + def __init__(self, message): + super().__init__(message) + self.message = message + + +class Field: + def __init__(self, pmu_data: _libkperf.ImplPmuData, field_exp: SampleRawField, field_name: str): + self.pmu_data = pmu_data + self.field_name = field_name + self.field_str = field_exp.field_str + self.size = field_exp.size + self.offset = field_exp.offset + self.is_signed = field_exp.is_signed + self.field_type = None + self.field_pointer = None + + def is_this_type(self) -> bool: + pass + + def generate_field_pointer(self): + pass + + def get_result_value(self) -> Any: + return self.field_type.value + + def get_field_value(self) -> Any: + self.generate_field_pointer() + rt = get_field(self.pmu_data, self.field_name, self.field_pointer) + if rt != 0: + raise TracePointerException("Failed to parse field!") + return self.get_result_value() + + +class StrField(Field): + def is_this_type(self) -> bool: + if "data_loc" in self.field_str: + return True + if "char" in self.field_str and self.size > 1: + return True + if "u8" in self.field_str and self.size > 1: + return True + + def generate_field_pointer(self): + """ + create string pointer + """ + self.field_type = ctypes.create_string_buffer(DATA_LOC_SIZE) + self.field_pointer = self.field_type + + def get_result_value(self) -> Any: + return self.field_pointer.value.decode(UTF_8) + + +class IntField(Field): + def is_this_type(self) -> bool: + if self.size != INT_SIZE: + return False + if "u32" in self.field_str: + return True + if "int" in self.field_str: + return True + + def generate_field_pointer(self): + """ + create int pointer + """ + if not self.is_signed: + self.field_type = ctypes.c_uint(0) + else: + self.field_type = ctypes.c_int(0) + self.field_pointer = ctypes.pointer(self.field_type) + + +class ShortField(Field): + def is_this_type(self) -> bool: + if self.size != SHORT_SIZE: + return False + if "u16" in self.field_str or "unsigned short" in self.field_str: + return True + return False + + def generate_field_pointer(self): + """ + create short pointer + """ + if not self.is_signed: + self.field_type = ctypes.c_ushort(0) + else: + self.field_type = ctypes.c_short(0) + self.field_pointer = ctypes.pointer(self.field_type) + + +class ByteField(Field): + def is_this_type(self) -> bool: + if self.size != 1: + return False + if "u8" in self.field_str or "unsigned char" in self.field_str: + return True + return False + + def generate_field_pointer(self): + """ + create byte pointer + """ + if not self.is_signed: + self.field_type = ctypes.c_ubyte(0) + else: + self.field_type = ctypes.c_byte(0) + self.field_pointer = ctypes.pointer(self.field_type) + + +class BoolField(Field): + def is_this_type(self) -> bool: + if self.size != 1: + return False + if "bool" in self.field_str: + return True + return False + + def generate_field_pointer(self): + """ + create bool pointer + """ + self.field_type = ctypes.c_bool(False) + self.field_pointer = ctypes.pointer(self.field_type) + + +class VoidField(Field): + def is_this_type(self) -> bool: + if "void" in self.field_str: + return True + return False + + def generate_field_pointer(self): + """ + create long pointer + """ + if self.size == LONG_SIZE: + self.field_type = ctypes.c_ulong(0x0) + if self.size == LONG_LONG_SIZE: + self.field_type = ctypes.c_ulonglong(0x0) + self.field_pointer = ctypes.pointer(self.field_type) + + def get_result_value(self) -> Any: + return hex(self.field_type.value) + + +FIELD_LIST = [StrField, IntField, ShortField, ByteField, BoolField, VoidField] + + +class TracePointerHelp: + def __init__(self, pmu_data: _libkperf.ImplPmuData): + self.pmu_data = pmu_data + + def get_field(self, field_name: str) -> Any: + field_exp = get_field_exp(self.pmu_data, field_name) + if field_exp is None: + raise TracePointerException("Can not find the field named {}".format(field_name)) + for field in FIELD_LIST: + object_field = field(self.pmu_data, field_exp, field_name) + if not object_field.is_this_type(): + continue + return object_field.get_field_value() + + class PointerCommData: common_type = "common_type" common_flags = "common_flags" @@ -64,4 +243,4 @@ class PointerEvt: SkebSkbCopyDatagramIovec = SkebSkbCopyDatagramIovec -__all__ = ['PointerEvt'] +__all__ = ['PointerEvt', 'TracePointerHelp'] diff --git a/python/tests/test_sampling.py b/python/tests/test_sampling.py index 17f7b82..8d70cda 100644 --- a/python/tests/test_sampling.py +++ b/python/tests/test_sampling.py @@ -26,6 +26,7 @@ class TraceEvt: self.pd = kperf.open(kperf.PmuTaskType.SAMPLING, pmu_attr) if self.pd == -1: print(kperf.error()) + print(kperf.errorno()) err = kperf.enable(self.pd) if err != 0: print(kperf.error()) @@ -117,8 +118,34 @@ class NetNAPIExp(TraceEvt): .format(field.field_name, field.field_str, field.size, field.offset, field.is_signed)) +class NetNAPIHelp(TraceEvt): + def __init__(self): + super().__init__(evt.NetApiGroReceiveEntry.event_name) + + def do_read_field(self, data): + tp_help = kperf.TracePointerHelp(data) + name = tp_help.get_field(evt.NetApiGroReceiveEntry.name) + print("name={}".format(name)) + + napi_id = tp_help.get_field(evt.NetApiGroReceiveEntry.napi_id) + print("napi_id={}".format(napi_id)) + + nr_frags = tp_help.get_field(evt.NetApiGroReceiveEntry.nr_frags) + print("nr_frags={}".format(nr_frags)) + + mac_header_valid = tp_help.get_field(evt.NetApiGroReceiveEntry.mac_header_valid) + print("mac_header_valid={}".format(mac_header_valid)) + + gso_type = tp_help.get_field(evt.NetApiGroReceiveEntry.gso_type) + print("gso_type={}".format(gso_type)) + + skbaddr = tp_help.get_field(evt.NetApiGroReceiveEntry.skbaddr) + print("skbaddr={}".format(skbaddr)) + + if __name__ == '__main__': NetRx().sample() NetSkebCopy().sample() NetNAPI().sample() NetNAPIExp().sample() + NetNAPIHelp().sample() -- Gitee