0001
0002
0003 #include <vmlinux.h>
0004 #include <bpf/bpf_helpers.h>
0005 #include <bpf/bpf_tracing.h>
0006
0007
0008 struct {
0009 __uint(type, BPF_MAP_TYPE_PERF_EVENT_ARRAY);
0010 __uint(key_size, sizeof(u32));
0011 __uint(value_size, sizeof(int));
0012 } events SEC(".maps");
0013
0014
0015 struct {
0016 __uint(type, BPF_MAP_TYPE_PERCPU_ARRAY);
0017 __uint(key_size, sizeof(u32));
0018 __uint(value_size, sizeof(struct bpf_perf_event_value));
0019 } fentry_readings SEC(".maps");
0020
0021
0022 struct {
0023 __uint(type, BPF_MAP_TYPE_PERCPU_ARRAY);
0024 __uint(key_size, sizeof(u32));
0025 __uint(value_size, sizeof(struct bpf_perf_event_value));
0026 } accum_readings SEC(".maps");
0027
0028
0029 struct {
0030 __uint(type, BPF_MAP_TYPE_PERCPU_ARRAY);
0031 __uint(key_size, sizeof(u32));
0032 __uint(value_size, sizeof(u64));
0033 } counts SEC(".maps");
0034
0035 const volatile __u32 num_cpu = 1;
0036 const volatile __u32 num_metric = 1;
0037 #define MAX_NUM_MATRICS 4
0038
0039 SEC("fentry/XXX")
0040 int BPF_PROG(fentry_XXX)
0041 {
0042 struct bpf_perf_event_value *ptrs[MAX_NUM_MATRICS];
0043 u32 key = bpf_get_smp_processor_id();
0044 u32 i;
0045
0046
0047 for (i = 0; i < num_metric && i < MAX_NUM_MATRICS; i++) {
0048 u32 flag = i;
0049
0050 ptrs[i] = bpf_map_lookup_elem(&fentry_readings, &flag);
0051 if (!ptrs[i])
0052 return 0;
0053 }
0054
0055 for (i = 0; i < num_metric && i < MAX_NUM_MATRICS; i++) {
0056 struct bpf_perf_event_value reading;
0057 int err;
0058
0059 err = bpf_perf_event_read_value(&events, key, &reading,
0060 sizeof(reading));
0061 if (err)
0062 return 0;
0063 *(ptrs[i]) = reading;
0064 key += num_cpu;
0065 }
0066
0067 return 0;
0068 }
0069
0070 static inline void
0071 fexit_update_maps(u32 id, struct bpf_perf_event_value *after)
0072 {
0073 struct bpf_perf_event_value *before, diff;
0074
0075 before = bpf_map_lookup_elem(&fentry_readings, &id);
0076
0077 if (before && before->counter) {
0078 struct bpf_perf_event_value *accum;
0079
0080 diff.counter = after->counter - before->counter;
0081 diff.enabled = after->enabled - before->enabled;
0082 diff.running = after->running - before->running;
0083
0084 accum = bpf_map_lookup_elem(&accum_readings, &id);
0085 if (accum) {
0086 accum->counter += diff.counter;
0087 accum->enabled += diff.enabled;
0088 accum->running += diff.running;
0089 }
0090 }
0091 }
0092
0093 SEC("fexit/XXX")
0094 int BPF_PROG(fexit_XXX)
0095 {
0096 struct bpf_perf_event_value readings[MAX_NUM_MATRICS];
0097 u32 cpu = bpf_get_smp_processor_id();
0098 u32 i, zero = 0;
0099 int err;
0100 u64 *count;
0101
0102
0103 for (i = 0; i < num_metric && i < MAX_NUM_MATRICS; i++) {
0104 err = bpf_perf_event_read_value(&events, cpu + i * num_cpu,
0105 readings + i, sizeof(*readings));
0106 if (err)
0107 return 0;
0108 }
0109 count = bpf_map_lookup_elem(&counts, &zero);
0110 if (count) {
0111 *count += 1;
0112 for (i = 0; i < num_metric && i < MAX_NUM_MATRICS; i++)
0113 fexit_update_maps(i, &readings[i]);
0114 }
0115 return 0;
0116 }
0117
0118 char LICENSE[] SEC("license") = "Dual BSD/GPL";