On 05/04/2018 03:37 AM, Jakub Kicinski wrote: > Users of BPF sooner or later discover perf_event_output() helpers > and BPF_MAP_TYPE_PERF_EVENT_ARRAY. Dumping this array type is > not possible, however, we can add simple reading of perf events. > Create a new event_pipe subcommand for maps, this sub command > will only work with BPF_MAP_TYPE_PERF_EVENT_ARRAY maps. > > Parts of the code from samples/bpf/trace_output_user.c. > > Signed-off-by: Jakub Kicinski <jakub.kicin...@netronome.com> > Reviewed-by: Quentin Monnet <quentin.mon...@netronome.com> [...]
One remark below: [...] > +static void > +print_bpf_output(struct event_ring_info *ring, struct perf_event_sample *e) > +{ > + struct { > + struct perf_event_header header; > + __u64 id; > + __u64 lost; > + } *lost = (void *)e; > + struct timespec ts; > + > + if (clock_gettime(CLOCK_MONOTONIC, &ts)) { > + perror("Can't read clock for timestamp"); > + return; > + } Instead of the timestamp above, probably better to pick it up via PERF_SAMPLE_TIME which needs to be added to sample_type so it also ends up in the RB. Given below you poll with 200 and you don't set a wakeup event for perf RB (it's probably fine not to here, but it can be done based on watermark or events), the clock_gettime() will be off compared to when it was actually put into the RB. > + if (json_output) { > + jsonw_start_object(json_wtr); > + jsonw_name(json_wtr, "timestamp"); > + jsonw_uint(json_wtr, ts.tv_sec * 1000000000ull + ts.tv_nsec); > + jsonw_name(json_wtr, "type"); > + jsonw_uint(json_wtr, e->header.type); > + jsonw_name(json_wtr, "cpu"); > + jsonw_uint(json_wtr, ring->cpu); > + jsonw_name(json_wtr, "index"); > + jsonw_uint(json_wtr, ring->key); > + if (e->header.type == PERF_RECORD_SAMPLE) { > + jsonw_name(json_wtr, "data"); > + print_data_json(e->data, e->size); > + } else if (e->header.type == PERF_RECORD_LOST) { > + jsonw_name(json_wtr, "lost"); > + jsonw_start_object(json_wtr); > + jsonw_name(json_wtr, "id"); > + jsonw_uint(json_wtr, lost->id); > + jsonw_name(json_wtr, "count"); > + jsonw_uint(json_wtr, lost->lost); > + jsonw_end_object(json_wtr); > + } > + jsonw_end_object(json_wtr); > + } else { > + if (e->header.type == PERF_RECORD_SAMPLE) { > + printf("== @%ld.%ld CPU: %d index: %d =====\n", > + (long)ts.tv_sec, ts.tv_nsec, > + ring->cpu, ring->key); > + fprint_hex(stdout, e->data, e->size, " "); > + printf("\n"); > + } else if (e->header.type == PERF_RECORD_LOST) { > + printf("lost %lld events\n", lost->lost); > + } else { > + printf("unknown event type=%d size=%d\n", > + e->header.type, e->header.size); > + }