* 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 <stdio.h>
#include <stdlib.h>
#include <string.h>
#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)
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
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);
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) {
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) {
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
#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
#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
#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
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
#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);
#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
if (pevent)
pevent_free(pevent);
- if (ras)
+ if (ras) {
+ if (ras->filter)
+ pevent_filter_free(ras->filter);
free(ras);
+ }
return rc;
}