Blame SOURCES/redhat-bugzilla-2003956.patch

689f35
commit 14ffcd934e1c5099b471f4e73da32d1b32bac7e6
689f35
Author: Andreas Gerstmayr <agerstmayr@redhat.com>
689f35
Date:   Mon Dec 13 20:10:40 2021 +0100
689f35
689f35
    pmdabcc: sync bcc PMDA modules with upstream bcc tools
689f35
689f35
diff --git a/src/pmdas/bcc/modules/execsnoop.bpf b/src/pmdas/bcc/modules/execsnoop.bpf
689f35
index f69200773..aa755b3a1 100644
689f35
--- a/src/pmdas/bcc/modules/execsnoop.bpf
689f35
+++ b/src/pmdas/bcc/modules/execsnoop.bpf
689f35
@@ -4,40 +4,57 @@
689f35
 #include <uapi/linux/ptrace.h>
689f35
 #include <linux/sched.h>
689f35
 #include <linux/fs.h>
689f35
+
689f35
 #define ARGSIZE  128
689f35
+
689f35
 enum event_type {
689f35
     EVENT_ARG,
689f35
     EVENT_RET,
689f35
 };
689f35
+
689f35
 struct data_t {
689f35
     u32 pid;  // PID as in the userspace term (i.e. task->tgid in kernel)
689f35
     u32 ppid; // Parent PID as in the userspace term (i.e task->real_parent->tgid in kernel)
689f35
+    u32 uid;
689f35
     char comm[TASK_COMM_LEN];
689f35
     enum event_type type;
689f35
     char argv[ARGSIZE];
689f35
     int retval;
689f35
 };
689f35
+
689f35
 BPF_PERF_OUTPUT(events);
689f35
+
689f35
 static int __submit_arg(struct pt_regs *ctx, void *ptr, struct data_t *data)
689f35
 {
689f35
-    bpf_probe_read(data->argv, sizeof(data->argv), ptr);
689f35
+    bpf_probe_read_user(data->argv, sizeof(data->argv), ptr);
689f35
     events.perf_submit(ctx, data, sizeof(struct data_t));
689f35
     return 1;
689f35
 }
689f35
+
689f35
 static int submit_arg(struct pt_regs *ctx, void *ptr, struct data_t *data)
689f35
 {
689f35
     const char *argp = NULL;
689f35
-    bpf_probe_read(&argp, sizeof(argp), ptr);
689f35
+    bpf_probe_read_user(&argp, sizeof(argp), ptr);
689f35
     if (argp) {
689f35
         return __submit_arg(ctx, (void *)(argp), data);
689f35
     }
689f35
     return 0;
689f35
 }
689f35
+
689f35
 int syscall__execve(struct pt_regs *ctx,
689f35
     const char __user *filename,
689f35
     const char __user *const __user *__argv,
689f35
     const char __user *const __user *__envp)
689f35
 {
689f35
+
689f35
+    u32 uid = bpf_get_current_uid_gid() & 0xffffffff;
689f35
+
689f35
+    UID_FILTER
689f35
+
689f35
+    if (container_should_be_filtered()) {
689f35
+        return 0;
689f35
+    }
689f35
+
689f35
     // create data here and pass to submit_arg to save stack space (#555)
689f35
     struct data_t data = {};
689f35
     struct task_struct *task;
689f35
@@ -52,25 +69,37 @@ int syscall__execve(struct pt_regs *ctx,
689f35
 
689f35
     bpf_get_current_comm(&data.comm, sizeof(data.comm));
689f35
     data.type = EVENT_ARG;
689f35
+
689f35
     __submit_arg(ctx, (void *)filename, &data);
689f35
+
689f35
     // skip first arg, as we submitted filename
689f35
     #pragma unroll
689f35
     for (int i = 1; i < MAXARG; i++) {
689f35
         if (submit_arg(ctx, (void *)&__argv[i], &data) == 0)
689f35
              goto out;
689f35
     }
689f35
+
689f35
     // handle truncated argument list
689f35
     char ellipsis[] = "...";
689f35
     __submit_arg(ctx, (void *)ellipsis, &data);
689f35
 out:
689f35
     return 0;
689f35
 }
689f35
+
689f35
 int do_ret_sys_execve(struct pt_regs *ctx)
689f35
 {
689f35
+    if (container_should_be_filtered()) {
689f35
+        return 0;
689f35
+    }
689f35
+
689f35
     struct data_t data = {};
689f35
     struct task_struct *task;
689f35
 
689f35
+    u32 uid = bpf_get_current_uid_gid() & 0xffffffff;
689f35
+    UID_FILTER
689f35
+
689f35
     data.pid = bpf_get_current_pid_tgid() >> 32;
689f35
+    data.uid = uid;
689f35
 
689f35
     task = (struct task_struct *)bpf_get_current_task();
689f35
     // Some kernels, like Ubuntu 4.13.0-generic, return 0
689f35
@@ -82,5 +111,6 @@ int do_ret_sys_execve(struct pt_regs *ctx)
689f35
     data.type = EVENT_RET;
689f35
     data.retval = PT_REGS_RC(ctx);
689f35
     events.perf_submit(ctx, &data, sizeof(data));
689f35
+
689f35
     return 0;
689f35
 }
689f35
diff --git a/src/pmdas/bcc/modules/execsnoop.python b/src/pmdas/bcc/modules/execsnoop.python
689f35
index 54382fa9b..1127cc471 100644
689f35
--- a/src/pmdas/bcc/modules/execsnoop.python
689f35
+++ b/src/pmdas/bcc/modules/execsnoop.python
689f35
@@ -44,20 +44,6 @@ MODULE = 'execsnoop'
689f35
 BASENS = 'proc.exec.'
689f35
 units_none = pmUnits(0, 0, 0, 0, 0, 0)
689f35
 
689f35
-TASK_COMM_LEN = 16      # linux/sched.h
689f35
-ARGSIZE = 128           # should match #define in execsnoop.bpf
689f35
-
689f35
-class Data(ct.Structure):
689f35
-    """ execsnoop data struct """
689f35
-    _fields_ = [
689f35
-        ("pid", ct.c_uint),
689f35
-        ("ppid", ct.c_uint),
689f35
-        ("comm", ct.c_char * TASK_COMM_LEN),
689f35
-        ("type", ct.c_int),
689f35
-        ("argv", ct.c_char * ARGSIZE),
689f35
-        ("retval", ct.c_int),
689f35
-    ]
689f35
-
689f35
 class EventType(object):
689f35
     """ Event type """
689f35
     EVENT_ARG = 0
689f35
@@ -137,7 +123,7 @@ class PCPBCCModule(PCPBCCBase):
689f35
 
689f35
     def handle_event(self, _cpu, data, _size):
689f35
         """ Event handler """
689f35
-        event = ct.cast(data, ct.POINTER(Data)).contents
689f35
+        event = self.bpf["events"].event(data)
689f35
         skip = False
689f35
 
689f35
         if event.type == EventType.EVENT_ARG:
689f35
@@ -145,9 +131,9 @@ class PCPBCCModule(PCPBCCBase):
689f35
         elif event.type == EventType.EVENT_RET:
689f35
             if event.retval != 0 and not self.include_failed:
689f35
                 skip = True
689f35
-            if self.command and not re.search(self.command, event.comm):
689f35
+            if self.command and not re.search(bytes(self.command), event.comm):
689f35
                 skip = True
689f35
-            if self.args and not re.search(self.args, b" ".join(self.argv_cache[event.pid])):
689f35
+            if self.args and not re.search(bytes(self.args), b" ".join(self.argv_cache[event.pid])):
689f35
                 skip = True
689f35
 
689f35
             if not skip:
689f35
@@ -177,10 +163,14 @@ class PCPBCCModule(PCPBCCBase):
689f35
 
689f35
                 self.bpf_text = self.bpf_text.replace("MAXARG", str(self.max_args))
689f35
 
689f35
+            bpf_text = self.bpf_text
689f35
+            bpf_text = bpf_text.replace('UID_FILTER', '')
689f35
+            bpf_text = bpf_text.replace('container_should_be_filtered()', '0')
689f35
+
689f35
             if self.debug:
689f35
-                self.log("BPF to be compiled:\n" + self.bpf_text.strip())
689f35
+                self.log("BPF to be compiled:\n" + bpf_text.strip())
689f35
 
689f35
-            self.bpf = BPF(text=self.bpf_text)
689f35
+            self.bpf = BPF(text=bpf_text)
689f35
             execve_fnname = self.get_syscall_fnname("execve")
689f35
             self.bpf.attach_kprobe(event=execve_fnname, fn_name="syscall__execve")
689f35
             self.bpf.attach_kretprobe(event=execve_fnname, fn_name="do_ret_sys_execve")
689f35
diff --git a/src/pmdas/bcc/modules/pcpbcc.python b/src/pmdas/bcc/modules/pcpbcc.python
689f35
index 0555dc33f..62783b7fc 100644
689f35
--- a/src/pmdas/bcc/modules/pcpbcc.python
689f35
+++ b/src/pmdas/bcc/modules/pcpbcc.python
689f35
@@ -14,6 +14,7 @@
689f35
 """ PCP BCC PMDA module base class """
689f35
 
689f35
 import re
689f35
+import platform
689f35
 import ctypes as ct
689f35
 from os import kill, listdir, path
689f35
 from collections import OrderedDict
689f35
@@ -348,6 +349,16 @@ class PCPBCCBase(object):
689f35
         """ Returns BCC version as an int tuple (for comparisons) """
689f35
         return tuple(map(int, PCPBCCBase.bcc_version().split('.')))
689f35
 
689f35
+    @staticmethod
689f35
+    def kernel_version():
689f35
+        """Returns the kernel version"""
689f35
+        version_str = platform.release()
689f35
+        m = re.match(r'^(\d+)\.(\d+)\.(\d+)', version_str)
689f35
+        if m:
689f35
+            return tuple(map(int, m.groups()))
689f35
+        else:
689f35
+            return (0, 0, 0)
689f35
+
689f35
     def perf_buffer_poller(self):
689f35
         """ BPF poller """
689f35
         try:
689f35
diff --git a/src/pmdas/bcc/modules/runqlat.python b/src/pmdas/bcc/modules/runqlat.python
689f35
index 27007c7e5..1c6c6b4b0 100644
689f35
--- a/src/pmdas/bcc/modules/runqlat.python
689f35
+++ b/src/pmdas/bcc/modules/runqlat.python
689f35
@@ -30,7 +30,11 @@ from modules.pcpbcc import PCPBCCBase
689f35
 #
689f35
 # BPF program
689f35
 #
689f35
-bpf_src = "modules/runqlat.bpf"
689f35
+is_support_raw_tp = BPF.support_raw_tracepoint()
689f35
+if is_support_raw_tp:
689f35
+    bpf_src = "modules/runqlat_tp.bpf"
689f35
+else:
689f35
+    bpf_src = "modules/runqlat_kp.bpf"
689f35
 
689f35
 #
689f35
 # PCP BCC PMDA constants
689f35
@@ -59,6 +63,7 @@ class PCPBCCModule(PCPBCCBase):
689f35
                 self.proc_filter = self.config.get(MODULE, opt)
689f35
                 self.update_pids(self.get_proc_info(self.proc_filter))
689f35
 
689f35
+        self.log("Using BPF source file %s." % bpf_src)
689f35
         self.log("Initialized.")
689f35
 
689f35
     def metrics(self):
689f35
@@ -89,7 +94,23 @@ class PCPBCCModule(PCPBCCBase):
689f35
                 with open(path.dirname(__file__) + '/../' + bpf_src) as src:
689f35
                     self.bpf_text = src.read()
689f35
 
689f35
+                # BPF.kernel_struct_has_field requires BCC v0.23.0
689f35
+                # use kernel version check as alternative
689f35
+                # pylint: disable=no-member
689f35
+                if (
689f35
+                    hasattr(BPF, "kernel_struct_has_field")
689f35
+                    and BPF.kernel_struct_has_field(b"task_struct", b"__state") == 1
689f35
+                ) or self.kernel_version() >= (5, 14, 0):
689f35
+                    self.bpf_text = self.bpf_text.replace('STATE_FIELD', '__state')
689f35
+                else:
689f35
+                    self.bpf_text = self.bpf_text.replace('STATE_FIELD', 'state')
689f35
+
689f35
                 self.bpf_text = self.bpf_text.replace("FILTER", "PID_CHECK")
689f35
+                self.bpf_text = self.bpf_text.replace('FACTOR', 'delta /= 1000;')
689f35
+
689f35
+                self.bpf_text = self.bpf_text.replace('STORAGE', 'BPF_HISTOGRAM(dist);')
689f35
+                self.bpf_text = self.bpf_text.replace('STORE',
689f35
+                    'dist.increment(bpf_log2l(delta));')
689f35
 
689f35
             if not self.pids and self.proc_filter and self.proc_refresh:
689f35
                 self.log("No process to attach found, activation postponed.")
689f35
@@ -102,9 +123,11 @@ class PCPBCCModule(PCPBCCBase):
689f35
 
689f35
             self.reset_cache()
689f35
             self.bpf = BPF(text=bpf_text)
689f35
-            self.bpf.attach_kprobe(event="ttwu_do_wakeup", fn_name="trace_ttwu_do_wakeup")
689f35
-            self.bpf.attach_kprobe(event="wake_up_new_task", fn_name="trace_wake_up_new_task")
689f35
-            self.bpf.attach_kprobe(event_re=r"^finish_task_switch$|^finish_task_switch\.isra\.\d$", fn_name="trace_run")
689f35
+            if not is_support_raw_tp:
689f35
+                self.bpf.attach_kprobe(event="ttwu_do_wakeup", fn_name="trace_ttwu_do_wakeup")
689f35
+                self.bpf.attach_kprobe(event="wake_up_new_task", fn_name="trace_wake_up_new_task")
689f35
+                self.bpf.attach_kprobe(event_re=r"^finish_task_switch$|^finish_task_switch\.isra\.\d$",
689f35
+                                       fn_name="trace_run")
689f35
             self.log("Compiled.")
689f35
         except Exception as error: # pylint: disable=broad-except
689f35
             self.bpf = None
689f35
diff --git a/src/pmdas/bcc/modules/runqlat.bpf b/src/pmdas/bcc/modules/runqlat_kp.bpf
689f35
similarity index 54%
689f35
rename from src/pmdas/bcc/modules/runqlat.bpf
689f35
rename to src/pmdas/bcc/modules/runqlat_kp.bpf
689f35
index a3664a035..dd643d600 100644
689f35
--- a/src/pmdas/bcc/modules/runqlat.bpf
689f35
+++ b/src/pmdas/bcc/modules/runqlat_kp.bpf
689f35
@@ -5,6 +5,7 @@
689f35
 #include <linux/sched.h>
689f35
 #include <linux/nsproxy.h>
689f35
 #include <linux/pid_namespace.h>
689f35
+#include <linux/init_task.h>
689f35
 
689f35
 typedef struct pid_key {
689f35
     u64 id;    // work around
689f35
@@ -17,7 +18,7 @@ typedef struct pidns_key {
689f35
 } pidns_key_t;
689f35
 
689f35
 BPF_HASH(start, u32);
689f35
-BPF_HISTOGRAM(dist);
689f35
+STORAGE
689f35
 
689f35
 struct rq;
689f35
 
689f35
@@ -31,6 +32,45 @@ static int trace_enqueue(u32 tgid, u32 pid)
689f35
     return 0;
689f35
 }
689f35
 
689f35
+static __always_inline unsigned int pid_namespace(struct task_struct *task)
689f35
+{
689f35
+
689f35
+/* pids[] was removed from task_struct since commit 2c4704756cab7cfa031ada4dab361562f0e357c0
689f35
+ * Using the macro INIT_PID_LINK as a conditional judgment.
689f35
+ */
689f35
+#ifdef INIT_PID_LINK
689f35
+    struct pid_link pids;
689f35
+    unsigned int level;
689f35
+    struct upid upid;
689f35
+    struct ns_common ns;
689f35
+
689f35
+    /*  get the pid namespace by following task_active_pid_ns(),
689f35
+     *  pid->numbers[pid->level].ns
689f35
+     */
689f35
+    bpf_probe_read_kernel(&pids, sizeof(pids), &task->pids[PIDTYPE_PID]);
689f35
+    bpf_probe_read_kernel(&level, sizeof(level), &pids.pid->level);
689f35
+    bpf_probe_read_kernel(&upid, sizeof(upid), &pids.pid->numbers[level]);
689f35
+    bpf_probe_read_kernel(&ns, sizeof(ns), &upid.ns->ns);
689f35
+
689f35
+    return ns.inum;
689f35
+#else
689f35
+    struct pid *pid;
689f35
+    unsigned int level;
689f35
+    struct upid upid;
689f35
+    struct ns_common ns;
689f35
+
689f35
+    /*  get the pid namespace by following task_active_pid_ns(),
689f35
+     *  pid->numbers[pid->level].ns
689f35
+     */
689f35
+    bpf_probe_read_kernel(&pid, sizeof(pid), &task->thread_pid);
689f35
+    bpf_probe_read_kernel(&level, sizeof(level), &pid->level);
689f35
+    bpf_probe_read_kernel(&upid, sizeof(upid), &pid->numbers[level]);
689f35
+    bpf_probe_read_kernel(&ns, sizeof(ns), &upid.ns->ns);
689f35
+
689f35
+    return ns.inum;
689f35
+#endif
689f35
+}
689f35
+
689f35
 int trace_wake_up_new_task(struct pt_regs *ctx, struct task_struct *p)
689f35
 {
689f35
     return trace_enqueue(p->tgid, p->pid);
689f35
@@ -48,7 +88,7 @@ int trace_run(struct pt_regs *ctx, struct task_struct *prev)
689f35
     u32 pid, tgid;
689f35
 
689f35
     // ivcsw: treat like an enqueue event and store timestamp
689f35
-    if (prev->state == TASK_RUNNING) {
689f35
+    if (prev->STATE_FIELD == TASK_RUNNING) {
689f35
         tgid = prev->tgid;
689f35
         pid = prev->pid;
689f35
         if (!(FILTER || pid == 0)) {
689f35
@@ -69,10 +109,10 @@ int trace_run(struct pt_regs *ctx, struct task_struct *prev)
689f35
         return 0;   // missed enqueue
689f35
     }
689f35
     delta = bpf_ktime_get_ns() - *tsp;
689f35
-    delta /= 1000;
689f35
+    FACTOR
689f35
 
689f35
     // store as histogram
689f35
-    dist.increment(bpf_log2l(delta));
689f35
+    STORE
689f35
 
689f35
     start.delete(&pid;;
689f35
     return 0;
689f35
diff --git a/src/pmdas/bcc/modules/runqlat_tp.bpf b/src/pmdas/bcc/modules/runqlat_tp.bpf
689f35
new file mode 100644
689f35
index 000000000..f0e9ce69b
689f35
--- /dev/null
689f35
+++ b/src/pmdas/bcc/modules/runqlat_tp.bpf
689f35
@@ -0,0 +1,124 @@
689f35
+// Copyright 2016 Netflix, Inc.
689f35
+// Licensed under the Apache License, Version 2.0 (the "License")
689f35
+
689f35
+#include <uapi/linux/ptrace.h>
689f35
+#include <linux/sched.h>
689f35
+#include <linux/nsproxy.h>
689f35
+#include <linux/pid_namespace.h>
689f35
+#include <linux/init_task.h>
689f35
+
689f35
+typedef struct pid_key {
689f35
+    u64 id;    // work around
689f35
+    u64 slot;
689f35
+} pid_key_t;
689f35
+
689f35
+typedef struct pidns_key {
689f35
+    u64 id;    // work around
689f35
+    u64 slot;
689f35
+} pidns_key_t;
689f35
+
689f35
+BPF_HASH(start, u32);
689f35
+STORAGE
689f35
+
689f35
+struct rq;
689f35
+
689f35
+// record enqueue timestamp
689f35
+static int trace_enqueue(u32 tgid, u32 pid)
689f35
+{
689f35
+    if (FILTER || pid == 0)
689f35
+        return 0;
689f35
+    u64 ts = bpf_ktime_get_ns();
689f35
+    start.update(&pid, &ts);
689f35
+    return 0;
689f35
+}
689f35
+
689f35
+static __always_inline unsigned int pid_namespace(struct task_struct *task)
689f35
+{
689f35
+
689f35
+/* pids[] was removed from task_struct since commit 2c4704756cab7cfa031ada4dab361562f0e357c0
689f35
+ * Using the macro INIT_PID_LINK as a conditional judgment.
689f35
+ */
689f35
+#ifdef INIT_PID_LINK
689f35
+    struct pid_link pids;
689f35
+    unsigned int level;
689f35
+    struct upid upid;
689f35
+    struct ns_common ns;
689f35
+
689f35
+    /*  get the pid namespace by following task_active_pid_ns(),
689f35
+     *  pid->numbers[pid->level].ns
689f35
+     */
689f35
+    bpf_probe_read_kernel(&pids, sizeof(pids), &task->pids[PIDTYPE_PID]);
689f35
+    bpf_probe_read_kernel(&level, sizeof(level), &pids.pid->level);
689f35
+    bpf_probe_read_kernel(&upid, sizeof(upid), &pids.pid->numbers[level]);
689f35
+    bpf_probe_read_kernel(&ns, sizeof(ns), &upid.ns->ns);
689f35
+
689f35
+    return ns.inum;
689f35
+#else
689f35
+    struct pid *pid;
689f35
+    unsigned int level;
689f35
+    struct upid upid;
689f35
+    struct ns_common ns;
689f35
+
689f35
+    /*  get the pid namespace by following task_active_pid_ns(),
689f35
+     *  pid->numbers[pid->level].ns
689f35
+     */
689f35
+    bpf_probe_read_kernel(&pid, sizeof(pid), &task->thread_pid);
689f35
+    bpf_probe_read_kernel(&level, sizeof(level), &pid->level);
689f35
+    bpf_probe_read_kernel(&upid, sizeof(upid), &pid->numbers[level]);
689f35
+    bpf_probe_read_kernel(&ns, sizeof(ns), &upid.ns->ns);
689f35
+
689f35
+    return ns.inum;
689f35
+#endif
689f35
+}
689f35
+
689f35
+RAW_TRACEPOINT_PROBE(sched_wakeup)
689f35
+{
689f35
+    // TP_PROTO(struct task_struct *p)
689f35
+    struct task_struct *p = (struct task_struct *)ctx->args[0];
689f35
+    return trace_enqueue(p->tgid, p->pid);
689f35
+}
689f35
+
689f35
+RAW_TRACEPOINT_PROBE(sched_wakeup_new)
689f35
+{
689f35
+    // TP_PROTO(struct task_struct *p)
689f35
+    struct task_struct *p = (struct task_struct *)ctx->args[0];
689f35
+    return trace_enqueue(p->tgid, p->pid);
689f35
+}
689f35
+
689f35
+RAW_TRACEPOINT_PROBE(sched_switch)
689f35
+{
689f35
+    // TP_PROTO(bool preempt, struct task_struct *prev, struct task_struct *next)
689f35
+    struct task_struct *prev = (struct task_struct *)ctx->args[1];
689f35
+    struct task_struct *next = (struct task_struct *)ctx->args[2];
689f35
+    u32 pid, tgid;
689f35
+
689f35
+    // ivcsw: treat like an enqueue event and store timestamp
689f35
+    if (prev->STATE_FIELD == TASK_RUNNING) {
689f35
+        tgid = prev->tgid;
689f35
+        pid = prev->pid;
689f35
+        if (!(FILTER || pid == 0)) {
689f35
+            u64 ts = bpf_ktime_get_ns();
689f35
+            start.update(&pid, &ts);
689f35
+        }
689f35
+    }
689f35
+
689f35
+    tgid = next->tgid;
689f35
+    pid = next->pid;
689f35
+    if (FILTER || pid == 0)
689f35
+        return 0;
689f35
+    u64 *tsp, delta;
689f35
+
689f35
+    // fetch timestamp and calculate delta
689f35
+    tsp = start.lookup(&pid;;
689f35
+    if (tsp == 0) {
689f35
+        return 0;   // missed enqueue
689f35
+    }
689f35
+    delta = bpf_ktime_get_ns() - *tsp;
689f35
+    FACTOR
689f35
+
689f35
+    // store as histogram
689f35
+    STORE
689f35
+
689f35
+    start.delete(&pid;;
689f35
+    return 0;
689f35
+}
689f35
diff --git a/src/pmdas/bcc/modules/tcplife.python b/src/pmdas/bcc/modules/tcplife.python
689f35
index 0c6f17c36..02c693a6a 100644
689f35
--- a/src/pmdas/bcc/modules/tcplife.python
689f35
+++ b/src/pmdas/bcc/modules/tcplife.python
689f35
@@ -37,16 +37,11 @@ from modules.pcpbcc import PCPBCCBase
689f35
 #
689f35
 # BPF program
689f35
 #
689f35
-bpf_src = "modules/tcplife.bpf"
689f35
-# Compat with kernel < 4.16, bcc < 0.6
689f35
-TRACEFS = "/sys/kernel/debug/tracing"
689f35
-bpf_src_old_tp = "modules/tcplife_old_tp.bpf"
689f35
-bpf_src_old_kb = "modules/tcplife_old_kb.bpf"
689f35
-if not path.exists(TRACEFS + "/events/sock/inet_sock_set_state"):
689f35
-    if path.exists(TRACEFS + "/events/tcp/tcp_set_state"):
689f35
-        bpf_src = bpf_src_old_tp
689f35
-    else:
689f35
-        bpf_src = bpf_src_old_kb
689f35
+if BPF.tracepoint_exists("sock", "inet_sock_set_state"):
689f35
+    bpf_src = "modules/tcplife_tp.bpf"
689f35
+else:
689f35
+    bpf_src = "modules/tcplife_kp.bpf"
689f35
+
689f35
 
689f35
 #
689f35
 # PCP BCC PMDA constants
689f35
@@ -57,35 +52,6 @@ units_bytes = pmUnits(1, 0, 0, PM_SPACE_BYTE, 0, 0)
689f35
 units_usecs = pmUnits(0, 1, 0, 0, PM_TIME_USEC, 0)
689f35
 units_none = pmUnits(0, 0, 0, 0, 0, 0)
689f35
 
689f35
-TASK_COMM_LEN = 16      # linux/sched.h
689f35
-
689f35
-class Data_ipv4(ct.Structure):
689f35
-    """ IPv4 data struct """
689f35
-    _fields_ = [
689f35
-        ("ts_us", ct.c_ulonglong),
689f35
-        ("pid", ct.c_ulonglong),
689f35
-        ("saddr", ct.c_ulonglong),
689f35
-        ("daddr", ct.c_ulonglong),
689f35
-        ("ports", ct.c_ulonglong),
689f35
-        ("rx_b", ct.c_ulonglong),
689f35
-        ("tx_b", ct.c_ulonglong),
689f35
-        ("span_us", ct.c_ulonglong),
689f35
-        ("task", ct.c_char * TASK_COMM_LEN)
689f35
-    ]
689f35
-
689f35
-class Data_ipv6(ct.Structure):
689f35
-    """ IPv6 data struct """
689f35
-    _fields_ = [
689f35
-        ("ts_us", ct.c_ulonglong),
689f35
-        ("pid", ct.c_ulonglong),
689f35
-        ("saddr", (ct.c_ulonglong * 2)),
689f35
-        ("daddr", (ct.c_ulonglong * 2)),
689f35
-        ("ports", ct.c_ulonglong),
689f35
-        ("rx_b", ct.c_ulonglong),
689f35
-        ("tx_b", ct.c_ulonglong),
689f35
-        ("span_us", ct.c_ulonglong),
689f35
-        ("task", ct.c_char * TASK_COMM_LEN)
689f35
-    ]
689f35
 
689f35
 #
689f35
 # PCP BCC Module
689f35
@@ -129,24 +95,22 @@ class PCPBCCModule(PCPBCCBase):
689f35
         self.lock = Lock()
689f35
         self.thread = None
689f35
 
689f35
-        # Compat with kernel < 4.16
689f35
         self.log("Using BPF source file %s." % bpf_src)
689f35
 
689f35
         # Exit hard if impossible to continue
689f35
-        if self.bcc_version() == "0.6.1" and bpf_src == bpf_src_old_kb:
689f35
-            raise RuntimeError("BCC 0.6.1 bug makes it incompatible with this module "
689f35
-                               "on kernel < 4.15.")
689f35
+        if self.bcc_version_tuple() < (0, 6, 1):
689f35
+            raise RuntimeError("BCC 0.6.1+ is required for this module.")
689f35
 
689f35
         self.log("Initialized.")
689f35
 
689f35
     def handle_ip_event(self, data, version):
689f35
         """ IP event handler """
689f35
         if version == 4:
689f35
-            event = ct.cast(data, ct.POINTER(Data_ipv4)).contents
689f35
+            event = self.bpf["ipv4_events"].event(data)
689f35
             laddr = inet_ntop(AF_INET, pack("I", event.saddr))
689f35
             daddr = inet_ntop(AF_INET, pack("I", event.daddr))
689f35
         else:
689f35
-            event = ct.cast(data, ct.POINTER(Data_ipv6)).contents
689f35
+            event = self.bpf["ipv6_events"].event(data)
689f35
             laddr = inet_ntop(AF_INET6, event.saddr)
689f35
             daddr = inet_ntop(AF_INET6, event.daddr)
689f35
 
689f35
@@ -205,31 +169,25 @@ class PCPBCCModule(PCPBCCBase):
689f35
             if not self.bpf_text:
689f35
                 with open(path.dirname(__file__) + '/../' + bpf_src) as src:
689f35
                     self.bpf_text = src.read()
689f35
-                # Compat with bcc < 0.6
689f35
-                self.log("Testing BCC compatilibility, possible errors below are safe to ignore.")
689f35
-                try:
689f35
-                    test_txt = self.bpf_text.replace("// NEW: ", "").replace("FILTER_PID", "")
689f35
-                    test_bpf = BPF(text=test_txt)
689f35
-                    test_bpf.cleanup()
689f35
-                    self.bpf_text = self.bpf_text.replace("// NEW: ", "")
689f35
-                except Exception: # pylint: disable=broad-except
689f35
-                    self.bpf_text = self.bpf_text.replace("// OLD: ", "")
689f35
-                self.log("Tested BCC compatilibility, possible errors above are safe to ignore.")
689f35
 
689f35
                 if self.dports:
689f35
                     filterp = " && ".join(["dport != %d" % port for port in self.dports])
689f35
                     filter_txt = "if (%s) { birth.delete(&sk;; return 0; }" % filterp
689f35
-                    self.bpf_text = self.bpf_text.replace("//FILTER_DPORT", filter_txt)
689f35
+                    self.bpf_text = self.bpf_text.replace("FILTER_DPORT", filter_txt)
689f35
                 if self.lports:
689f35
                     filterp = " && ".join(["lport != %d" % port for port in self.lports])
689f35
                     filter_txt = "if (%s) { birth.delete(&sk;; return 0; }" % filterp
689f35
-                    self.bpf_text = self.bpf_text.replace("//FILTER_LPORT", filter_txt)
689f35
+                    self.bpf_text = self.bpf_text.replace("FILTER_LPORT", filter_txt)
689f35
 
689f35
             if not self.pids and self.proc_filter and self.proc_refresh:
689f35
                 self.log("No process to attach found, activation postponed.")
689f35
                 return
689f35
 
689f35
             bpf_text = self.apply_pid_filter(self.bpf_text, self.pids, False)
689f35
+            bpf_text = bpf_text.replace('FILTER_PID', '')
689f35
+            bpf_text = bpf_text.replace('FILTER_DPORT', '')
689f35
+            bpf_text = bpf_text.replace('FILTER_LPORT', '')
689f35
+            bpf_text = bpf_text.replace('FILTER_FAMILY', '')
689f35
 
689f35
             if self.debug:
689f35
                 self.log("BPF to be compiled:\n" + bpf_text.strip())
689f35
diff --git a/src/pmdas/bcc/modules/tcplife_old_kb.bpf b/src/pmdas/bcc/modules/tcplife_kp.bpf
689f35
similarity index 81%
689f35
rename from src/pmdas/bcc/modules/tcplife_old_kb.bpf
689f35
rename to src/pmdas/bcc/modules/tcplife_kp.bpf
689f35
index eed01941a..5486c6a37 100644
689f35
--- a/src/pmdas/bcc/modules/tcplife_old_kb.bpf
689f35
+++ b/src/pmdas/bcc/modules/tcplife_kp.bpf
689f35
@@ -2,7 +2,6 @@
689f35
 // Licensed under the Apache License, Version 2.0 (the "License")
689f35
 
689f35
 #include <uapi/linux/ptrace.h>
689f35
-#define KBUILD_MODNAME "pcpbcctcplife"
689f35
 #include <linux/tcp.h>
689f35
 #include <net/sock.h>
689f35
 #include <bcc/proto.h>
689f35
@@ -11,11 +10,10 @@ BPF_HASH(birth, struct sock *, u64);
689f35
 
689f35
 // separate data structs for ipv4 and ipv6
689f35
 struct ipv4_data_t {
689f35
-    // XXX: switch some to u32's when supported
689f35
     u64 ts_us;
689f35
-    u64 pid;
689f35
-    u64 saddr;
689f35
-    u64 daddr;
689f35
+    u32 pid;
689f35
+    u32 saddr;
689f35
+    u32 daddr;
689f35
     u64 ports;
689f35
     u64 rx_b;
689f35
     u64 tx_b;
689f35
@@ -26,7 +24,7 @@ BPF_PERF_OUTPUT(ipv4_events);
689f35
 
689f35
 struct ipv6_data_t {
689f35
     u64 ts_us;
689f35
-    u64 pid;
689f35
+    u32 pid;
689f35
     unsigned __int128 saddr;
689f35
     unsigned __int128 daddr;
689f35
     u64 ports;
689f35
@@ -49,12 +47,12 @@ int kprobe__tcp_set_state(struct pt_regs *ctx, struct sock *sk, int state)
689f35
 
689f35
     // lport is either used in a filter here, or later
689f35
     u16 lport = sk->__sk_common.skc_num;
689f35
-    //FILTER_LPORT
689f35
+    FILTER_LPORT
689f35
 
689f35
     // dport is either used in a filter here, or later
689f35
     u16 dport = sk->__sk_common.skc_dport;
689f35
     dport = ntohs(dport);
689f35
-    //FILTER_DPORT
689f35
+    FILTER_DPORT
689f35
 
689f35
     /*
689f35
      * This tool includes PID and comm context. It's best effort, and may
689f35
@@ -74,6 +72,9 @@ int kprobe__tcp_set_state(struct pt_regs *ctx, struct sock *sk, int state)
689f35
          * sets ESTABLISHED without a tcp_set_state() call. Until we know
689f35
          * that for sure, match all early states to increase chances a
689f35
          * timestamp is set.
689f35
+         * Note that this needs to be set before the PID filter later on,
689f35
+         * since the PID isn't reliable for these early stages, so we must
689f35
+         * save all timestamps and do the PID filter later when we can.
689f35
          */
689f35
         u64 ts = bpf_ktime_get_ns();
689f35
         birth.update(&sk, &ts);
689f35
@@ -101,7 +102,7 @@ int kprobe__tcp_set_state(struct pt_regs *ctx, struct sock *sk, int state)
689f35
     delta_us = (bpf_ktime_get_ns() - *tsp) / 1000;
689f35
     birth.delete(&sk;;
689f35
 
689f35
-    // fetch possible cached data
689f35
+    // fetch possible cached data, and filter
689f35
     struct id_t *mep;
689f35
     mep = whoami.lookup(&sk;;
689f35
     if (mep != 0)
689f35
@@ -116,9 +117,13 @@ int kprobe__tcp_set_state(struct pt_regs *ctx, struct sock *sk, int state)
689f35
 
689f35
     u16 family = sk->__sk_common.skc_family;
689f35
 
689f35
+    FILTER_FAMILY
689f35
+
689f35
     if (family == AF_INET) {
689f35
-        struct ipv4_data_t data4 = {.span_us = delta_us,
689f35
-            .rx_b = rx_b, .tx_b = tx_b};
689f35
+        struct ipv4_data_t data4 = {};
689f35
+        data4.span_us = delta_us;
689f35
+        data4.rx_b = rx_b;
689f35
+        data4.tx_b = tx_b;
689f35
         data4.ts_us = bpf_ktime_get_ns() / 1000;
689f35
         data4.saddr = sk->__sk_common.skc_rcv_saddr;
689f35
         data4.daddr = sk->__sk_common.skc_daddr;
689f35
@@ -128,17 +133,19 @@ int kprobe__tcp_set_state(struct pt_regs *ctx, struct sock *sk, int state)
689f35
         if (mep == 0) {
689f35
             bpf_get_current_comm(&data4.task, sizeof(data4.task));
689f35
         } else {
689f35
-            bpf_probe_read(&data4.task, sizeof(data4.task), (void *)mep->task);
689f35
+            bpf_probe_read_kernel(&data4.task, sizeof(data4.task), (void *)mep->task);
689f35
         }
689f35
         ipv4_events.perf_submit(ctx, &data4, sizeof(data4));
689f35
 
689f35
     } else /* 6 */ {
689f35
-        struct ipv6_data_t data6 = {.span_us = delta_us,
689f35
-            .rx_b = rx_b, .tx_b = tx_b};
689f35
+        struct ipv6_data_t data6 = {};
689f35
+        data6.span_us = delta_us;
689f35
+        data6.rx_b = rx_b;
689f35
+        data6.tx_b = tx_b;
689f35
         data6.ts_us = bpf_ktime_get_ns() / 1000;
689f35
-        bpf_probe_read(&data6.saddr, sizeof(data6.saddr),
689f35
+        bpf_probe_read_kernel(&data6.saddr, sizeof(data6.saddr),
689f35
             sk->__sk_common.skc_v6_rcv_saddr.in6_u.u6_addr32);
689f35
-        bpf_probe_read(&data6.daddr, sizeof(data6.daddr),
689f35
+        bpf_probe_read_kernel(&data6.daddr, sizeof(data6.daddr),
689f35
             sk->__sk_common.skc_v6_daddr.in6_u.u6_addr32);
689f35
         // a workaround until data6 compiles with separate lport/dport
689f35
         data6.ports = dport + ((0ULL + lport) << 32);
689f35
@@ -146,7 +153,7 @@ int kprobe__tcp_set_state(struct pt_regs *ctx, struct sock *sk, int state)
689f35
         if (mep == 0) {
689f35
             bpf_get_current_comm(&data6.task, sizeof(data6.task));
689f35
         } else {
689f35
-            bpf_probe_read(&data6.task, sizeof(data6.task), (void *)mep->task);
689f35
+            bpf_probe_read_kernel(&data6.task, sizeof(data6.task), (void *)mep->task);
689f35
         }
689f35
         ipv6_events.perf_submit(ctx, &data6, sizeof(data6));
689f35
     }
689f35
diff --git a/src/pmdas/bcc/modules/tcplife_old_tp.bpf b/src/pmdas/bcc/modules/tcplife_old_tp.bpf
689f35
deleted file mode 100644
689f35
index a7c9c625c..000000000
689f35
--- a/src/pmdas/bcc/modules/tcplife_old_tp.bpf
689f35
+++ /dev/null
689f35
@@ -1,166 +0,0 @@
689f35
-// Copyright 2016 Netflix, Inc.
689f35
-// Licensed under the Apache License, Version 2.0 (the "License")
689f35
-
689f35
-#include <uapi/linux/ptrace.h>
689f35
-#define KBUILD_MODNAME "pcpbcctcplife"
689f35
-#include <linux/tcp.h>
689f35
-#include <net/sock.h>
689f35
-#include <bcc/proto.h>
689f35
-
689f35
-BPF_HASH(birth, struct sock *, u64);
689f35
-
689f35
-// separate data structs for ipv4 and ipv6
689f35
-struct ipv4_data_t {
689f35
-    // XXX: switch some to u32's when supported
689f35
-    u64 ts_us;
689f35
-    u64 pid;
689f35
-    u64 saddr;
689f35
-    u64 daddr;
689f35
-    u64 ports;
689f35
-    u64 rx_b;
689f35
-    u64 tx_b;
689f35
-    u64 span_us;
689f35
-    char task[TASK_COMM_LEN];
689f35
-};
689f35
-BPF_PERF_OUTPUT(ipv4_events);
689f35
-
689f35
-struct ipv6_data_t {
689f35
-    u64 ts_us;
689f35
-    u64 pid;
689f35
-    unsigned __int128 saddr;
689f35
-    unsigned __int128 daddr;
689f35
-    u64 ports;
689f35
-    u64 rx_b;
689f35
-    u64 tx_b;
689f35
-    u64 span_us;
689f35
-    char task[TASK_COMM_LEN];
689f35
-};
689f35
-BPF_PERF_OUTPUT(ipv6_events);
689f35
-
689f35
-struct id_t {
689f35
-    u32 pid;
689f35
-    char task[TASK_COMM_LEN];
689f35
-};
689f35
-BPF_HASH(whoami, struct sock *, struct id_t);
689f35
-
689f35
-TRACEPOINT_PROBE(tcp, tcp_set_state)
689f35
-{
689f35
-    u32 pid = bpf_get_current_pid_tgid() >> 32;
689f35
-    // sk is mostly used as a UUID, once for skc_family, and two tcp stats:
689f35
-    struct sock *sk = (struct sock *)args->skaddr;
689f35
-
689f35
-    // lport is either used in a filter here, or later
689f35
-    u16 lport = args->sport;
689f35
-    //FILTER_LPORT
689f35
-
689f35
-    // dport is either used in a filter here, or later
689f35
-    u16 dport = args->dport;
689f35
-    //FILTER_DPORT
689f35
-
689f35
-    /*
689f35
-     * This tool includes PID and comm context. It's best effort, and may
689f35
-     * be wrong in some situations. It currently works like this:
689f35
-     * - record timestamp on any state < TCP_FIN_WAIT1
689f35
-     * - cache task context on:
689f35
-     *       TCP_SYN_SENT: tracing from client
689f35
-     *       TCP_LAST_ACK: client-closed from server
689f35
-     * - do output on TCP_CLOSE:
689f35
-     *       fetch task context if cached, or use current task
689f35
-     */
689f35
-
689f35
-    // capture birth time
689f35
-    if (args->newstate < TCP_FIN_WAIT1) {
689f35
-        /*
689f35
-         * Matching just ESTABLISHED may be sufficient, provided no code-path
689f35
-         * sets ESTABLISHED without a tcp_set_state() call. Until we know
689f35
-         * that for sure, match all early states to increase chances a
689f35
-         * timestamp is set.
689f35
-         * Note that this needs to be set before the PID filter later on,
689f35
-         * since the PID isn't reliable for these early stages, so we must
689f35
-         * save all timestamps and do the PID filter later when we can.
689f35
-         */
689f35
-        u64 ts = bpf_ktime_get_ns();
689f35
-        birth.update(&sk, &ts);
689f35
-    }
689f35
-
689f35
-    // record PID & comm on SYN_SENT
689f35
-    if (args->newstate == TCP_SYN_SENT || args->newstate == TCP_LAST_ACK) {
689f35
-        // now we can PID filter, both here and a little later on for CLOSE
689f35
-        FILTER_PID
689f35
-        struct id_t me = {.pid = pid};
689f35
-        bpf_get_current_comm(&me.task, sizeof(me.task));
689f35
-        whoami.update(&sk, &me);
689f35
-    }
689f35
-
689f35
-    if (args->newstate != TCP_CLOSE)
689f35
-        return 0;
689f35
-
689f35
-    // calculate lifespan
689f35
-    u64 *tsp, delta_us;
689f35
-    tsp = birth.lookup(&sk;;
689f35
-    if (tsp == 0) {
689f35
-        whoami.delete(&sk;;     // may not exist
689f35
-        return 0;               // missed create
689f35
-    }
689f35
-    delta_us = (bpf_ktime_get_ns() - *tsp) / 1000;
689f35
-    birth.delete(&sk;;
689f35
-
689f35
-    // fetch possible cached data, and filter
689f35
-    struct id_t *mep;
689f35
-    mep = whoami.lookup(&sk;;
689f35
-    if (mep != 0)
689f35
-        pid = mep->pid;
689f35
-    FILTER_PID
689f35
-
689f35
-    // get throughput stats. see tcp_get_info().
689f35
-    u64 rx_b = 0, tx_b = 0, sport = 0;
689f35
-    struct tcp_sock *tp = (struct tcp_sock *)sk;
689f35
-    // OLD: bpf_probe_read(&rx_b, sizeof(rx_b), &tp->bytes_received);
689f35
-    // OLD: bpf_probe_read(&tx_b, sizeof(tx_b), &tp->bytes_acked);
689f35
-    // NEW: rx_b = tp->bytes_received;
689f35
-    // NEW: tx_b = tp->bytes_acked;
689f35
-
689f35
-    u16 family = 0;
689f35
-    // OLD: bpf_probe_read(&family, sizeof(family), &sk->__sk_common.skc_family);
689f35
-    // NEW: family = sk->__sk_common.skc_family;
689f35
-
689f35
-    if (family == AF_INET) {
689f35
-
689f35
-        struct ipv4_data_t data4 = {.span_us = delta_us,
689f35
-            .rx_b = rx_b, .tx_b = tx_b};
689f35
-        data4.ts_us = bpf_ktime_get_ns() / 1000;
689f35
-        bpf_probe_read(&data4.saddr, sizeof(u32), args->saddr);
689f35
-        bpf_probe_read(&data4.daddr, sizeof(u32), args->daddr);
689f35
-        // a workaround until data4 compiles with separate lport/dport
689f35
-        data4.ports = dport + ((0ULL + lport) << 32);
689f35
-        data4.pid = pid;
689f35
-
689f35
-        if (mep == 0) {
689f35
-            bpf_get_current_comm(&data4.task, sizeof(data4.task));
689f35
-        } else {
689f35
-            bpf_probe_read(&data4.task, sizeof(data4.task), (void *)mep->task);
689f35
-        }
689f35
-        ipv4_events.perf_submit(args, &data4, sizeof(data4));
689f35
-
689f35
-    } else /* 6 */ {
689f35
-        struct ipv6_data_t data6 = {.span_us = delta_us,
689f35
-            .rx_b = rx_b, .tx_b = tx_b};
689f35
-        data6.ts_us = bpf_ktime_get_ns() / 1000;
689f35
-        bpf_probe_read(&data6.saddr, sizeof(data6.saddr), args->saddr_v6);
689f35
-        bpf_probe_read(&data6.daddr, sizeof(data6.daddr), args->saddr_v6);
689f35
-        // a workaround until data6 compiles with separate lport/dport
689f35
-        data6.ports = dport + ((0ULL + lport) << 32);
689f35
-        data6.pid = pid;
689f35
-        if (mep == 0) {
689f35
-            bpf_get_current_comm(&data6.task, sizeof(data6.task));
689f35
-        } else {
689f35
-            bpf_probe_read(&data6.task, sizeof(data6.task), (void *)mep->task);
689f35
-        }
689f35
-        ipv6_events.perf_submit(args, &data6, sizeof(data6));
689f35
-    }
689f35
-
689f35
-    if (mep != 0)
689f35
-        whoami.delete(&sk;;
689f35
-
689f35
-    return 0;
689f35
-}
689f35
diff --git a/src/pmdas/bcc/modules/tcplife.bpf b/src/pmdas/bcc/modules/tcplife_tp.bpf
689f35
similarity index 80%
689f35
rename from src/pmdas/bcc/modules/tcplife.bpf
689f35
rename to src/pmdas/bcc/modules/tcplife_tp.bpf
689f35
index 19ca8d740..2b16b98e7 100644
689f35
--- a/src/pmdas/bcc/modules/tcplife.bpf
689f35
+++ b/src/pmdas/bcc/modules/tcplife_tp.bpf
689f35
@@ -2,7 +2,6 @@
689f35
 // Licensed under the Apache License, Version 2.0 (the "License")
689f35
 
689f35
 #include <uapi/linux/ptrace.h>
689f35
-#define KBUILD_MODNAME "pcpbcctcplife"
689f35
 #include <linux/tcp.h>
689f35
 #include <net/sock.h>
689f35
 #include <bcc/proto.h>
689f35
@@ -11,11 +10,10 @@ BPF_HASH(birth, struct sock *, u64);
689f35
 
689f35
 // separate data structs for ipv4 and ipv6
689f35
 struct ipv4_data_t {
689f35
-    // XXX: switch some to u32's when supported
689f35
     u64 ts_us;
689f35
-    u64 pid;
689f35
-    u64 saddr;
689f35
-    u64 daddr;
689f35
+    u32 pid;
689f35
+    u32 saddr;
689f35
+    u32 daddr;
689f35
     u64 ports;
689f35
     u64 rx_b;
689f35
     u64 tx_b;
689f35
@@ -26,7 +24,7 @@ BPF_PERF_OUTPUT(ipv4_events);
689f35
 
689f35
 struct ipv6_data_t {
689f35
     u64 ts_us;
689f35
-    u64 pid;
689f35
+    u32 pid;
689f35
     unsigned __int128 saddr;
689f35
     unsigned __int128 daddr;
689f35
     u64 ports;
689f35
@@ -54,11 +52,11 @@ TRACEPOINT_PROBE(sock, inet_sock_set_state)
689f35
 
689f35
     // lport is either used in a filter here, or later
689f35
     u16 lport = args->sport;
689f35
-    //FILTER_LPORT
689f35
+    FILTER_LPORT
689f35
 
689f35
     // dport is either used in a filter here, or later
689f35
     u16 dport = args->dport;
689f35
-    //FILTER_DPORT
689f35
+    FILTER_DPORT
689f35
 
689f35
     /*
689f35
      * This tool includes PID and comm context. It's best effort, and may
689f35
@@ -115,20 +113,23 @@ TRACEPOINT_PROBE(sock, inet_sock_set_state)
689f35
         pid = mep->pid;
689f35
     FILTER_PID
689f35
 
689f35
+    u16 family = args->family;
689f35
+    FILTER_FAMILY
689f35
+
689f35
     // get throughput stats. see tcp_get_info().
689f35
     u64 rx_b = 0, tx_b = 0, sport = 0;
689f35
     struct tcp_sock *tp = (struct tcp_sock *)sk;
689f35
-    // OLD: bpf_probe_read(&rx_b, sizeof(rx_b), &tp->bytes_received);
689f35
-    // OLD: bpf_probe_read(&tx_b, sizeof(tx_b), &tp->bytes_acked);
689f35
-    // NEW: rx_b = tp->bytes_received;
689f35
-    // NEW: tx_b = tp->bytes_acked;
689f35
+    rx_b = tp->bytes_received;
689f35
+    tx_b = tp->bytes_acked;
689f35
 
689f35
     if (args->family == AF_INET) {
689f35
-        struct ipv4_data_t data4 = {.span_us = delta_us,
689f35
-            .rx_b = rx_b, .tx_b = tx_b};
689f35
+        struct ipv4_data_t data4 = {};
689f35
+        data4.span_us = delta_us;
689f35
+        data4.rx_b = rx_b;
689f35
+        data4.tx_b = tx_b;
689f35
         data4.ts_us = bpf_ktime_get_ns() / 1000;
689f35
-        bpf_probe_read(&data4.saddr, sizeof(u32), args->saddr);
689f35
-        bpf_probe_read(&data4.daddr, sizeof(u32), args->daddr);
689f35
+        __builtin_memcpy(&data4.saddr, args->saddr, sizeof(data4.saddr));
689f35
+        __builtin_memcpy(&data4.daddr, args->daddr, sizeof(data4.daddr));
689f35
         // a workaround until data4 compiles with separate lport/dport
689f35
         data4.ports = dport + ((0ULL + lport) << 32);
689f35
         data4.pid = pid;
689f35
@@ -136,23 +137,25 @@ TRACEPOINT_PROBE(sock, inet_sock_set_state)
689f35
         if (mep == 0) {
689f35
             bpf_get_current_comm(&data4.task, sizeof(data4.task));
689f35
         } else {
689f35
-            bpf_probe_read(&data4.task, sizeof(data4.task), (void *)mep->task);
689f35
+            bpf_probe_read_kernel(&data4.task, sizeof(data4.task), (void *)mep->task);
689f35
         }
689f35
         ipv4_events.perf_submit(args, &data4, sizeof(data4));
689f35
 
689f35
     } else /* 6 */ {
689f35
-        struct ipv6_data_t data6 = {.span_us = delta_us,
689f35
-            .rx_b = rx_b, .tx_b = tx_b};
689f35
+        struct ipv6_data_t data6 = {};
689f35
+        data6.span_us = delta_us;
689f35
+        data6.rx_b = rx_b;
689f35
+        data6.tx_b = tx_b;
689f35
         data6.ts_us = bpf_ktime_get_ns() / 1000;
689f35
-        bpf_probe_read(&data6.saddr, sizeof(data6.saddr), args->saddr_v6);
689f35
-        bpf_probe_read(&data6.daddr, sizeof(data6.daddr), args->saddr_v6);
689f35
+        __builtin_memcpy(&data6.saddr, args->saddr_v6, sizeof(data6.saddr));
689f35
+        __builtin_memcpy(&data6.daddr, args->daddr_v6, sizeof(data6.daddr));
689f35
         // a workaround until data6 compiles with separate lport/dport
689f35
         data6.ports = dport + ((0ULL + lport) << 32);
689f35
         data6.pid = pid;
689f35
         if (mep == 0) {
689f35
             bpf_get_current_comm(&data6.task, sizeof(data6.task));
689f35
         } else {
689f35
-            bpf_probe_read(&data6.task, sizeof(data6.task), (void *)mep->task);
689f35
+            bpf_probe_read_kernel(&data6.task, sizeof(data6.task), (void *)mep->task);
689f35
         }
689f35
         ipv6_events.perf_submit(args, &data6, sizeof(data6));
689f35
     }
689f35
diff --git a/src/pmdas/bcc/modules/tcpperpid.python b/src/pmdas/bcc/modules/tcpperpid.python
689f35
index 3cb2cfcfd..0096929a6 100644
689f35
--- a/src/pmdas/bcc/modules/tcpperpid.python
689f35
+++ b/src/pmdas/bcc/modules/tcpperpid.python
689f35
@@ -32,16 +32,10 @@ from modules.pcpbcc import PCPBCCBase
689f35
 #
689f35
 # BPF program
689f35
 #
689f35
-bpf_src = "modules/tcplife.bpf"
689f35
-# Compat with kernel < 4.16, bcc < 0.6
689f35
-TRACEFS = "/sys/kernel/debug/tracing"
689f35
-bpf_src_old_tp = "modules/tcplife_old_tp.bpf"
689f35
-bpf_src_old_kb = "modules/tcplife_old_kb.bpf"
689f35
-if not path.exists(TRACEFS + "/events/sock/inet_sock_set_state"):
689f35
-    if path.exists(TRACEFS + "/events/tcp/tcp_set_state"):
689f35
-        bpf_src = bpf_src_old_tp
689f35
-    else:
689f35
-        bpf_src = bpf_src_old_kb
689f35
+if BPF.tracepoint_exists("sock", "inet_sock_set_state"):
689f35
+    bpf_src = "modules/tcplife_tp.bpf"
689f35
+else:
689f35
+    bpf_src = "modules/tcplife_kp.bpf"
689f35
 
689f35
 # Alternative, "high resolution" BPF
689f35
 bpf_highres = "modules/tcptop.bpf"
689f35
@@ -53,36 +47,6 @@ MODULE = 'tcpperpid'
689f35
 BASENS = 'proc.io.net.total.'
689f35
 units_bytes = pmUnits(1, 0, 0, PM_SPACE_BYTE, 0, 0)
689f35
 
689f35
-TASK_COMM_LEN = 16      # linux/sched.h
689f35
-
689f35
-class Data_ipv4(ct.Structure):
689f35
-    """ IPv4 data struct """
689f35
-    _fields_ = [
689f35
-        ("ts_us", ct.c_ulonglong),
689f35
-        ("pid", ct.c_ulonglong),
689f35
-        ("saddr", ct.c_ulonglong),
689f35
-        ("daddr", ct.c_ulonglong),
689f35
-        ("ports", ct.c_ulonglong),
689f35
-        ("rx_b", ct.c_ulonglong),
689f35
-        ("tx_b", ct.c_ulonglong),
689f35
-        ("span_us", ct.c_ulonglong),
689f35
-        ("task", ct.c_char * TASK_COMM_LEN)
689f35
-    ]
689f35
-
689f35
-class Data_ipv6(ct.Structure):
689f35
-    """ IPv6 data struct """
689f35
-    _fields_ = [
689f35
-        ("ts_us", ct.c_ulonglong),
689f35
-        ("pid", ct.c_ulonglong),
689f35
-        ("saddr", (ct.c_ulonglong * 2)),
689f35
-        ("daddr", (ct.c_ulonglong * 2)),
689f35
-        ("ports", ct.c_ulonglong),
689f35
-        ("rx_b", ct.c_ulonglong),
689f35
-        ("tx_b", ct.c_ulonglong),
689f35
-        ("span_us", ct.c_ulonglong),
689f35
-        ("task", ct.c_char * TASK_COMM_LEN)
689f35
-    ]
689f35
-
689f35
 #
689f35
 # PCP BCC Module
689f35
 #
689f35
@@ -133,15 +97,14 @@ class PCPBCCModule(PCPBCCBase):
689f35
         self.log("Using BPF source file %s." % src)
689f35
 
689f35
         # Exit hard if impossible to continue
689f35
-        if self.bcc_version() == "0.6.1" and src == bpf_src_old_kb and not self.highres:
689f35
-            raise RuntimeError("BCC 0.6.1 bug makes it incompatible with this module "
689f35
-                               "on kernel < 4.15 in non-highres mode.")
689f35
+        if self.bcc_version_tuple() < (0, 6, 1) and not self.highres:
689f35
+            raise RuntimeError("BCC 0.6.1+ is required for this module in non-highres mode.")
689f35
 
689f35
         self.log("Initialized.")
689f35
 
689f35
     def handle_ipv4_event(self, _cpu, data, _size):
689f35
         """ IPv4 event handler """
689f35
-        event = ct.cast(data, ct.POINTER(Data_ipv4)).contents
689f35
+        event = self.bpf["ipv4_events"].event(data)
689f35
         pid = str(event.pid).zfill(6)
689f35
         self.lock.acquire()
689f35
         if pid not in self.ipv4_stats:
689f35
@@ -153,7 +116,7 @@ class PCPBCCModule(PCPBCCBase):
689f35
 
689f35
     def handle_ipv6_event(self, _cpu, data, _size):
689f35
         """ IPv6 event handler """
689f35
-        event = ct.cast(data, ct.POINTER(Data_ipv6)).contents
689f35
+        event = self.bpf["ipv6_events"].event(data)
689f35
         pid = str(event.pid).zfill(6)
689f35
         self.lock.acquire()
689f35
         if pid not in self.ipv6_stats:
689f35
@@ -199,31 +162,25 @@ class PCPBCCModule(PCPBCCBase):
689f35
                     self.bpf_text = src.read()
689f35
                 if self.highres:
689f35
                     self.bpf_text = self.bpf_text.replace("FILTER", "FILTER_PID")
689f35
-                # Compat with bcc < 0.6
689f35
-                self.log("Testing BCC compatilibility, possible errors below are safe to ignore.")
689f35
-                try:
689f35
-                    test_txt = self.bpf_text.replace("// NEW: ", "").replace("FILTER_PID", "")
689f35
-                    test_bpf = BPF(text=test_txt)
689f35
-                    test_bpf.cleanup()
689f35
-                    self.bpf_text = self.bpf_text.replace("// NEW: ", "")
689f35
-                except Exception: # pylint: disable=broad-except
689f35
-                    self.bpf_text = self.bpf_text.replace("// OLD: ", "")
689f35
-                self.log("Tested BCC compatilibility, possible errors above are safe to ignore.")
689f35
 
689f35
                 if self.dports:
689f35
                     filterp = " && ".join(["dport != %d" % port for port in self.dports])
689f35
                     filter_txt = "if (%s) { birth.delete(&sk;; return 0; }" % filterp
689f35
-                    self.bpf_text = self.bpf_text.replace("//FILTER_DPORT", filter_txt)
689f35
+                    self.bpf_text = self.bpf_text.replace("FILTER_DPORT", filter_txt)
689f35
                 if self.lports:
689f35
                     filterp = " && ".join(["lport != %d" % port for port in self.lports])
689f35
                     filter_txt = "if (%s) { birth.delete(&sk;; return 0; }" % filterp
689f35
-                    self.bpf_text = self.bpf_text.replace("//FILTER_LPORT", filter_txt)
689f35
+                    self.bpf_text = self.bpf_text.replace("FILTER_LPORT", filter_txt)
689f35
 
689f35
             if not self.pids and self.proc_filter and self.proc_refresh:
689f35
                 self.log("No process to attach found, activation postponed.")
689f35
                 return
689f35
 
689f35
             bpf_text = self.apply_pid_filter(self.bpf_text, self.pids, False)
689f35
+            bpf_text = bpf_text.replace('FILTER_PID', '')
689f35
+            bpf_text = bpf_text.replace('FILTER_DPORT', '')
689f35
+            bpf_text = bpf_text.replace('FILTER_LPORT', '')
689f35
+            bpf_text = bpf_text.replace('FILTER_FAMILY', '')
689f35
 
689f35
             if self.debug:
689f35
                 self.log("BPF to be compiled:\n" + bpf_text.strip())
689f35
diff --git a/src/pmdas/bcc/modules/tcptop.bpf b/src/pmdas/bcc/modules/tcptop.bpf
689f35
index 349ee1529..c1fed7aef 100644
689f35
--- a/src/pmdas/bcc/modules/tcptop.bpf
689f35
+++ b/src/pmdas/bcc/modules/tcptop.bpf
689f35
@@ -4,6 +4,7 @@
689f35
 #include <uapi/linux/ptrace.h>
689f35
 #include <net/sock.h>
689f35
 #include <bcc/proto.h>
689f35
+
689f35
 struct ipv4_key_t {
689f35
     u32 pid;
689f35
     u32 saddr;
689f35
@@ -13,25 +14,32 @@ struct ipv4_key_t {
689f35
 };
689f35
 BPF_HASH(ipv4_send_bytes, struct ipv4_key_t);
689f35
 BPF_HASH(ipv4_recv_bytes, struct ipv4_key_t);
689f35
+
689f35
 struct ipv6_key_t {
689f35
+    unsigned __int128 saddr;
689f35
+    unsigned __int128 daddr;
689f35
     u32 pid;
689f35
-    // workaround until unsigned __int128 support:
689f35
-    u64 saddr0;
689f35
-    u64 saddr1;
689f35
-    u64 daddr0;
689f35
-    u64 daddr1;
689f35
     u16 lport;
689f35
     u16 dport;
689f35
+    u64 __pad__;
689f35
 };
689f35
 BPF_HASH(ipv6_send_bytes, struct ipv6_key_t);
689f35
 BPF_HASH(ipv6_recv_bytes, struct ipv6_key_t);
689f35
+
689f35
 int kprobe__tcp_sendmsg(struct pt_regs *ctx, struct sock *sk,
689f35
     struct msghdr *msg, size_t size)
689f35
 {
689f35
-    u32 pid = bpf_get_current_pid_tgid();
689f35
-    FILTER
689f35
+    if (container_should_be_filtered()) {
689f35
+        return 0;
689f35
+    }
689f35
+
689f35
+    u32 pid = bpf_get_current_pid_tgid() >> 32;
689f35
+    FILTER_PID
689f35
+
689f35
     u16 dport = 0, family = sk->__sk_common.skc_family;
689f35
-    u64 *val, zero = 0;
689f35
+
689f35
+    FILTER_FAMILY
689f35
+
689f35
     if (family == AF_INET) {
689f35
         struct ipv4_key_t ipv4_key = {.pid = pid};
689f35
         ipv4_key.saddr = sk->__sk_common.skc_rcv_saddr;
689f35
@@ -39,31 +47,24 @@ int kprobe__tcp_sendmsg(struct pt_regs *ctx, struct sock *sk,
689f35
         ipv4_key.lport = sk->__sk_common.skc_num;
689f35
         dport = sk->__sk_common.skc_dport;
689f35
         ipv4_key.dport = ntohs(dport);
689f35
-        val = ipv4_send_bytes.lookup_or_init(&ipv4_key, &zero);
689f35
-        if (val) {
689f35
-            (*val) += size;
689f35
-        }
689f35
+        ipv4_send_bytes.increment(ipv4_key, size);
689f35
+
689f35
     } else if (family == AF_INET6) {
689f35
         struct ipv6_key_t ipv6_key = {.pid = pid};
689f35
-        bpf_probe_read(&ipv6_key.saddr0, sizeof(ipv6_key.saddr0),
689f35
-            &sk->__sk_common.skc_v6_rcv_saddr.in6_u.u6_addr32[0]);
689f35
-        bpf_probe_read(&ipv6_key.saddr1, sizeof(ipv6_key.saddr1),
689f35
-            &sk->__sk_common.skc_v6_rcv_saddr.in6_u.u6_addr32[2]);
689f35
-        bpf_probe_read(&ipv6_key.daddr0, sizeof(ipv6_key.daddr0),
689f35
-            &sk->__sk_common.skc_v6_daddr.in6_u.u6_addr32[0]);
689f35
-        bpf_probe_read(&ipv6_key.daddr1, sizeof(ipv6_key.daddr1),
689f35
-            &sk->__sk_common.skc_v6_daddr.in6_u.u6_addr32[2]);
689f35
+        bpf_probe_read_kernel(&ipv6_key.saddr, sizeof(ipv6_key.saddr),
689f35
+            &sk->__sk_common.skc_v6_rcv_saddr.in6_u.u6_addr32);
689f35
+        bpf_probe_read_kernel(&ipv6_key.daddr, sizeof(ipv6_key.daddr),
689f35
+            &sk->__sk_common.skc_v6_daddr.in6_u.u6_addr32);
689f35
         ipv6_key.lport = sk->__sk_common.skc_num;
689f35
         dport = sk->__sk_common.skc_dport;
689f35
         ipv6_key.dport = ntohs(dport);
689f35
-        val = ipv6_send_bytes.lookup_or_init(&ipv6_key, &zero);
689f35
-        if (val) {
689f35
-            (*val) += size;
689f35
-        }
689f35
+        ipv6_send_bytes.increment(ipv6_key, size);
689f35
     }
689f35
     // else drop
689f35
+
689f35
     return 0;
689f35
 }
689f35
+
689f35
 /*
689f35
  * tcp_recvmsg() would be obvious to trace, but is less suitable because:
689f35
  * - we'd need to trace both entry and return, to have both sock and size
689f35
@@ -72,12 +73,21 @@ int kprobe__tcp_sendmsg(struct pt_regs *ctx, struct sock *sk,
689f35
  */
689f35
 int kprobe__tcp_cleanup_rbuf(struct pt_regs *ctx, struct sock *sk, int copied)
689f35
 {
689f35
-    u32 pid = bpf_get_current_pid_tgid();
689f35
-    FILTER
689f35
+    if (container_should_be_filtered()) {
689f35
+        return 0;
689f35
+    }
689f35
+
689f35
+    u32 pid = bpf_get_current_pid_tgid() >> 32;
689f35
+    FILTER_PID
689f35
+
689f35
     u16 dport = 0, family = sk->__sk_common.skc_family;
689f35
     u64 *val, zero = 0;
689f35
+
689f35
     if (copied <= 0)
689f35
         return 0;
689f35
+
689f35
+    FILTER_FAMILY
689f35
+
689f35
     if (family == AF_INET) {
689f35
         struct ipv4_key_t ipv4_key = {.pid = pid};
689f35
         ipv4_key.saddr = sk->__sk_common.skc_rcv_saddr;
689f35
@@ -85,28 +95,20 @@ int kprobe__tcp_cleanup_rbuf(struct pt_regs *ctx, struct sock *sk, int copied)
689f35
         ipv4_key.lport = sk->__sk_common.skc_num;
689f35
         dport = sk->__sk_common.skc_dport;
689f35
         ipv4_key.dport = ntohs(dport);
689f35
-        val = ipv4_recv_bytes.lookup_or_init(&ipv4_key, &zero);
689f35
-        if (val) {
689f35
-            (*val) += copied;
689f35
-        }
689f35
+        ipv4_recv_bytes.increment(ipv4_key, copied);
689f35
+
689f35
     } else if (family == AF_INET6) {
689f35
         struct ipv6_key_t ipv6_key = {.pid = pid};
689f35
-        bpf_probe_read(&ipv6_key.saddr0, sizeof(ipv6_key.saddr0),
689f35
-            &sk->__sk_common.skc_v6_rcv_saddr.in6_u.u6_addr32[0]);
689f35
-        bpf_probe_read(&ipv6_key.saddr1, sizeof(ipv6_key.saddr1),
689f35
-            &sk->__sk_common.skc_v6_rcv_saddr.in6_u.u6_addr32[2]);
689f35
-        bpf_probe_read(&ipv6_key.daddr0, sizeof(ipv6_key.daddr0),
689f35
-            &sk->__sk_common.skc_v6_daddr.in6_u.u6_addr32[0]);
689f35
-        bpf_probe_read(&ipv6_key.daddr1, sizeof(ipv6_key.daddr1),
689f35
-            &sk->__sk_common.skc_v6_daddr.in6_u.u6_addr32[2]);
689f35
+        bpf_probe_read_kernel(&ipv6_key.saddr, sizeof(ipv6_key.saddr),
689f35
+            &sk->__sk_common.skc_v6_rcv_saddr.in6_u.u6_addr32);
689f35
+        bpf_probe_read_kernel(&ipv6_key.daddr, sizeof(ipv6_key.daddr),
689f35
+            &sk->__sk_common.skc_v6_daddr.in6_u.u6_addr32);
689f35
         ipv6_key.lport = sk->__sk_common.skc_num;
689f35
         dport = sk->__sk_common.skc_dport;
689f35
         ipv6_key.dport = ntohs(dport);
689f35
-        val = ipv6_recv_bytes.lookup_or_init(&ipv6_key, &zero);
689f35
-        if (val) {
689f35
-            (*val) += copied;
689f35
-        }
689f35
+        ipv6_recv_bytes.increment(ipv6_key, copied);
689f35
     }
689f35
     // else drop
689f35
+
689f35
     return 0;
689f35
 }
689f35
diff --git a/src/pmdas/bcc/modules/tcptop.python b/src/pmdas/bcc/modules/tcptop.python
689f35
index 45063dff3..db1c1da15 100644
689f35
--- a/src/pmdas/bcc/modules/tcptop.python
689f35
+++ b/src/pmdas/bcc/modules/tcptop.python
689f35
@@ -120,13 +120,14 @@ class PCPBCCModule(PCPBCCBase):
689f35
                 with open(path.dirname(__file__) + '/../' + bpf_src) as src:
689f35
                     self.bpf_text = src.read()
689f35
 
689f35
-                self.bpf_text = self.bpf_text.replace("FILTER", "FILTER_PID")
689f35
-
689f35
             if not self.pids and self.proc_filter and self.proc_refresh:
689f35
                 self.log("No process to attach found, activation postponed.")
689f35
                 return
689f35
 
689f35
             bpf_text = self.apply_pid_filter(self.bpf_text, self.pids, False)
689f35
+            bpf_text = bpf_text.replace('FILTER_PID', '')
689f35
+            bpf_text = bpf_text.replace('FILTER_FAMILY', '')
689f35
+            bpf_text = bpf_text.replace('container_should_be_filtered()', '0')
689f35
 
689f35
             if self.debug:
689f35
                 self.log("BPF to be compiled:\n" + bpf_text.strip())
689f35
@@ -155,21 +156,31 @@ class PCPBCCModule(PCPBCCBase):
689f35
 
689f35
     @staticmethod
689f35
     def ipv4_table_to_dict(table):
689f35
-        """ Build hashable dict from IPv4 BPF table """
689f35
-        return {TCPSessionKey(pid=k.pid,
689f35
-                              laddr=inet_ntop(AF_INET, pack("I", k.saddr)),
689f35
-                              lport=k.lport,
689f35
-                              daddr=inet_ntop(AF_INET, pack("I", k.daddr)),
689f35
-                              dport=k.dport):v.value for k, v in table.items()}
689f35
+        """Build hashable dict from IPv4 BPF table"""
689f35
+        return {
689f35
+            TCPSessionKey(
689f35
+                pid=k.pid,
689f35
+                laddr=inet_ntop(AF_INET, pack("I", k.saddr)),
689f35
+                lport=k.lport,
689f35
+                daddr=inet_ntop(AF_INET, pack("I", k.daddr)),
689f35
+                dport=k.dport,
689f35
+            ): v.value
689f35
+            for k, v in table.items()
689f35
+        }
689f35
 
689f35
     @staticmethod
689f35
     def ipv6_table_to_dict(table):
689f35
-        """ Build hashable dict from IPv6 BPF table """
689f35
-        return {TCPSessionKey(pid=k.pid,
689f35
-                              laddr=inet_ntop(AF_INET6, pack("QQ", k.saddr0, k.saddr1)),
689f35
-                              lport=k.lport,
689f35
-                              daddr=inet_ntop(AF_INET6, pack("QQ", k.daddr0, k.daddr1)),
689f35
-                              dport=k.dport):v.value for k, v in table.items()}
689f35
+        """Build hashable dict from IPv6 BPF table"""
689f35
+        return {
689f35
+            TCPSessionKey(
689f35
+                pid=k.pid,
689f35
+                laddr=inet_ntop(AF_INET6, k.saddr),
689f35
+                lport=k.lport,
689f35
+                daddr=inet_ntop(AF_INET6, k.daddr),
689f35
+                dport=k.dport,
689f35
+            ): v.value
689f35
+            for k, v in table.items()
689f35
+        }
689f35
 
689f35
     def refresh_stats(self):
689f35
         """ Refresh statistics from BPF table """
689f35
commit d45ce8e85035cc95ba897cd19967fad6d5d741be (cherry-picked)
689f35
Author: Andreas Gerstmayr <agerstmayr@redhat.com>
689f35
Date:   Wed Dec 15 08:03:40 2021 +0100
689f35
689f35
    qa: update qa/1118 to add new log output of runqlat bcc module
689f35
689f35
diff --git a/qa/1118 b/qa/1118
689f35
index 4123495b5..bcaec0a0d 100755
689f35
--- a/qa/1118
689f35
+++ b/qa/1118
689f35
@@ -21,12 +21,19 @@ _label_filter()
689f35
     grep '"0-1"' | grep '"statistic":"histogram"' | grep '"lower_bound":0' | grep 'upper_bound":1' > /dev/null && echo 'OK'
689f35
 }
689f35
 
689f35
+_install_filter()
689f35
+{
689f35
+    sed \
689f35
+    -e "s/Using BPF source file .\+/Using BPF source file X/g" \
689f35
+    #end
689f35
+}
689f35
+
689f35
 _prepare_pmda bcc
689f35
 trap "_pmdabcc_cleanup; exit \$status" 0 1 2 3 15
689f35
 _stop_auto_restart pmcd
689f35
 
689f35
 # real QA test starts here
689f35
-cat <
689f35
+cat <
689f35
 # Installed by PCP QA test $seq on `date`
689f35
 [pmda]
689f35
 modules = runqlat
689f35
diff --git a/qa/1118.out b/qa/1118.out
689f35
index 16a9fa4b4..e74f97964 100644
689f35
--- a/qa/1118.out
689f35
+++ b/qa/1118.out
689f35
@@ -9,6 +9,7 @@ Info: runqlat
689f35
 Info: Modules configured.
689f35
 Info: Initializing modules:
689f35
 Info: runqlat
689f35
+Info: runqlat: Using BPF source file X
689f35
 Info: runqlat: Initialized.
689f35
 Info: Modules initialized.
689f35
 Info: Registering metrics:
689f35
@@ -25,6 +26,7 @@ Info: runqlat
689f35
 Info: Modules configured.
689f35
 Info: Initializing modules:
689f35
 Info: runqlat
689f35
+Info: runqlat: Using BPF source file X
689f35
 Info: runqlat: Initialized.
689f35
 Info: Modules initialized.
689f35
 Info: Registering metrics: