From b954a831a72514324d3ab2a8c6b6260ce19aa709 Mon Sep 17 00:00:00 2001 From: Cong Wang Date: Sat, 1 Jun 2019 17:16:54 -0700 Subject: [PATCH] Add devlink filter and net_dev_xmit_timeout Signed-off-by: Cong Wang --- ras-devlink-handler.c | 58 +++++++++++++++++++++++++++++++++++++++++++ ras-devlink-handler.h | 4 +++ ras-events.c | 51 ++++++++++++++++++++++++++++++------- ras-events.h | 2 ++ ras-record.h | 2 +- 5 files changed, 107 insertions(+), 10 deletions(-) diff --git a/ras-devlink-handler.c b/ras-devlink-handler.c index 0fe46d2..2699291 100644 --- a/ras-devlink-handler.c +++ b/ras-devlink-handler.c @@ -15,6 +15,7 @@ * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ +#define _GNU_SOURCE #include #include #include @@ -25,6 +26,61 @@ #include "ras-logger.h" #include "ras-report.h" +int ras_net_xmit_timeout_handler(struct trace_seq *s, + struct pevent_record *record, + struct event_format *event, void *context) +{ + unsigned long long val; + int len; + struct ras_events *ras = context; + time_t now; + struct tm *tm; + struct devlink_event ev; + + if (ras->use_uptime) + now = record->ts/user_hz + ras->uptime_diff; + else + now = time(NULL); + + tm = localtime(&now); + if (tm) + strftime(ev.timestamp, sizeof(ev.timestamp), + "%Y-%m-%d %H:%M:%S %z", tm); + trace_seq_printf(s, "%s ", ev.timestamp); + + ev.bus_name = ""; + ev.reporter_name = ""; + + ev.dev_name = pevent_get_field_raw(s, event, "name", + record, &len, 1); + if (!ev.dev_name) + return -1; + + ev.driver_name = pevent_get_field_raw(s, event, "driver", + record, &len, 1); + if (!ev.driver_name) + return -1; + + if (pevent_get_field_val(s, event, "queue_index", record, &val, 1) < 0) + return -1; + if (asprintf(&ev.msg, "TX timeout on queue: %d\n", (int)val) < 0) + return -1; + + /* Insert data into the SGBD */ +#ifdef HAVE_SQLITE3 + ras_store_devlink_event(ras, &ev); +#endif + +#ifdef HAVE_ABRT_REPORT + /* Report event to ABRT */ + ras_report_devlink_event(ras, &ev); +#endif + + free(ev.msg); + return 0; + +} + int ras_devlink_event_handler(struct trace_seq *s, struct pevent_record *record, struct event_format *event, void *context) @@ -35,6 +91,8 @@ int ras_devlink_event_handler(struct trace_seq *s, struct tm *tm; struct devlink_event ev; + if (ras->filter && pevent_filter_match(ras->filter, record) == FILTER_MATCH) + return 0; /* * Newer kernels (3.10-rc1 or upper) provide an uptime clock. * On previous kernels, the way to properly generate an event would diff --git a/ras-devlink-handler.h b/ras-devlink-handler.h index 29b64f7..ca9a1b7 100644 --- a/ras-devlink-handler.h +++ b/ras-devlink-handler.h @@ -22,6 +22,10 @@ #include "ras-events.h" #include "libtrace/event-parse.h" +int ras_net_xmit_timeout_handler(struct trace_seq *s, + struct pevent_record *record, + struct event_format *event, void *context); + int ras_devlink_event_handler(struct trace_seq *s, struct pevent_record *record, struct event_format *event, void *context); diff --git a/ras-events.c b/ras-events.c index a75f979..4e7b815 100644 --- a/ras-events.c +++ b/ras-events.c @@ -570,10 +570,11 @@ static int select_tracing_timestamp(struct ras_events *ras) static int add_event_handler(struct ras_events *ras, struct pevent *pevent, unsigned page_size, char *group, char *event, - pevent_event_handler_func func) + pevent_event_handler_func func, char *filter_str) { int fd, size, rc; char *page, fname[MAX_PATH + 1]; + struct event_filter * filter = NULL; snprintf(fname, sizeof(fname), "events/%s/%s/format", group, event); @@ -618,6 +619,28 @@ static int add_event_handler(struct ras_events *ras, struct pevent *pevent, return EINVAL; } + if (filter_str) { + char *error; + + filter = pevent_filter_alloc(pevent); + if (!filter) { + log(TERM, LOG_ERR, + "Failed to allocate filter for %s/%s.\n", group, event); + free(page); + return EINVAL; + } + rc = pevent_filter_add_filter_str(filter, filter_str, &error); + if (rc) { + log(TERM, LOG_ERR, + "Failed to install filter for %s/%s: %s\n", group, event, error); + pevent_filter_free(filter); + free(page); + return rc; + } + } + + ras->filter = filter; + /* Enable RAS events */ rc = __toggle_ras_mc_event(ras, group, event, 1); if (rc < 0) { @@ -641,6 +664,7 @@ int handle_ras_events(int record_events) struct pevent *pevent = NULL; struct pthread_data *data = NULL; struct ras_events *ras = NULL; + char *filter_str = NULL; ras = calloc(1, sizeof(*ras)); if (!ras) { @@ -674,7 +698,7 @@ int handle_ras_events(int record_events) ras->record_events = record_events; rc = add_event_handler(ras, pevent, page_size, "ras", "mc_event", - ras_mc_event_handler); + ras_mc_event_handler, NULL); if (!rc) num_events++; else @@ -683,7 +707,7 @@ int handle_ras_events(int record_events) #ifdef HAVE_AER rc = add_event_handler(ras, pevent, page_size, "ras", "aer_event", - ras_aer_event_handler); + ras_aer_event_handler, NULL); if (!rc) num_events++; else @@ -693,7 +717,7 @@ int handle_ras_events(int record_events) #ifdef HAVE_NON_STANDARD rc = add_event_handler(ras, pevent, page_size, "ras", "non_standard_event", - ras_non_standard_event_handler); + ras_non_standard_event_handler, NULL); if (!rc) num_events++; else @@ -703,7 +727,7 @@ int handle_ras_events(int record_events) #ifdef HAVE_ARM rc = add_event_handler(ras, pevent, page_size, "ras", "arm_event", - ras_arm_event_handler); + ras_arm_event_handler, NULL); if (!rc) num_events++; else @@ -720,7 +744,7 @@ int handle_ras_events(int record_events) if (ras->mce_priv) { rc = add_event_handler(ras, pevent, page_size, "mce", "mce_record", - ras_mce_event_handler); + ras_mce_event_handler, NULL); if (!rc) num_events++; else @@ -731,7 +755,7 @@ int handle_ras_events(int record_events) #ifdef HAVE_EXTLOG rc = add_event_handler(ras, pevent, page_size, "ras", "extlog_mem_event", - ras_extlog_mem_event_handler); + ras_extlog_mem_event_handler, NULL); if (!rc) { /* tell kernel we are listening, so don't printk to console */ (void)open("/sys/kernel/debug/ras/daemon_active", 0); @@ -742,9 +766,15 @@ int handle_ras_events(int record_events) #endif #ifdef HAVE_DEVLINK + rc = add_event_handler(ras, pevent, page_size, "net", + "net_dev_xmit_timeout", + ras_net_xmit_timeout_handler, NULL); + if (!rc) + filter_str = "devlink/devlink_health_report:msg=~\'TX timeout*\'"; + rc = add_event_handler(ras, pevent, page_size, "devlink", "devlink_health_report", - ras_devlink_event_handler); + ras_devlink_event_handler, filter_str); if (!rc) num_events++; else @@ -801,8 +831,11 @@ err: if (pevent) pevent_free(pevent); - if (ras) + if (ras) { + if (ras->filter) + pevent_filter_free(ras->filter); free(ras); + } return rc; } diff --git a/ras-events.h b/ras-events.h index 1a78390..2fae2f1 100644 --- a/ras-events.h +++ b/ras-events.h @@ -50,6 +50,8 @@ struct ras_events { /* For ABRT socket*/ int socketfd; + + struct event_filter *filter; }; struct pthread_data { diff --git a/ras-record.h b/ras-record.h index f230ed2..2183167 100644 --- a/ras-record.h +++ b/ras-record.h @@ -81,7 +81,7 @@ struct devlink_event { const char *dev_name; const char *driver_name; const char *reporter_name; - const char *msg; + char *msg; }; struct ras_mc_event; -- 2.50.1