1 /*
2  * Copyright (c) 2015-2016, Cisco Systems, Inc. All rights reserved.
3  * Copyright (c) 2015, Intel Corp., Inc.  All rights reserved.
4  *
5  * This software is available to you under a choice of one of two
6  * licenses.  You may choose to be licensed under the terms of the GNU
7  * General Public License (GPL) Version 2, available from the file
8  * COPYING in the main directory of this source tree, or the
9  * BSD license below:
10  *
11  *     Redistribution and use in source and binary forms, with or
12  *     without modification, are permitted provided that the following
13  *     conditions are met:
14  *
15  *      - Redistributions of source code must retain the above
16  *        copyright notice, this list of conditions and the following
17  *        disclaimer.
18  *
19  *      - Redistributions in binary form must reproduce the above
20  *        copyright notice, this list of conditions and the following
21  *        disclaimer in the documentation and/or other materials
22  *        provided with the distribution.
23  *
24  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
25  * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
26  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
27  * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
28  * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
29  * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
30  * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
31  * SOFTWARE.
32  *
33  */
34 
35 #include <stdarg.h>
36 #include <stdio.h>
37 #include <stdlib.h>
38 
39 #include <rdma/fi_errno.h>
40 
41 #include "ofi.h"
42 
43 
44 static const char * const log_subsys[] = {
45 	[FI_LOG_CORE] = "core",
46 	[FI_LOG_FABRIC] = "fabric",
47 	[FI_LOG_DOMAIN] = "domain",
48 	[FI_LOG_EP_CTRL] = "ep_ctrl",
49 	[FI_LOG_EP_DATA] = "ep_data",
50 	[FI_LOG_AV] = "av",
51 	[FI_LOG_CQ] = "cq",
52 	[FI_LOG_EQ] = "eq",
53 	[FI_LOG_MR] = "mr",
54 	[FI_LOG_CNTR] = "cntr",
55 	[FI_LOG_SUBSYS_MAX] = NULL
56 };
57 
58 static const char * const log_levels[] = {
59 	[FI_LOG_WARN] = "warn",
60 	[FI_LOG_TRACE] = "trace",
61 	[FI_LOG_INFO] = "info",
62 	[FI_LOG_DEBUG] = "debug",
63 	[FI_LOG_MAX] = NULL
64 };
65 
66 enum {
67 	FI_LOG_SUBSYS_OFFSET	= FI_LOG_MAX,
68 	FI_LOG_PROV_OFFSET	= FI_LOG_SUBSYS_OFFSET + FI_LOG_SUBSYS_MAX,
69 	FI_LOG_LEVEL_MASK	= ((1 << FI_LOG_MAX) - 1),
70 	FI_LOG_SUBSYS_MASK	= (((1 << FI_LOG_SUBSYS_MAX) - 1) <<
71 				   FI_LOG_SUBSYS_OFFSET),
72 //	FI_LOG_PROV_MASK	= (((1 << (64 - FI_LOG_PROV_OFFSET)) - 1) <<
73 //				   FI_LOG_PROV_OFFSET)
74 };
75 
76 #define FI_LOG_TAG(prov, level, subsys) \
77 	(((uint64_t) prov << FI_LOG_PROV_OFFSET) | \
78 	 ((uint64_t) (1 << (subsys + FI_LOG_SUBSYS_OFFSET))) | \
79 	 ((uint64_t) (1 << level)))
80 
81 uint64_t log_mask;
82 struct fi_filter prov_log_filter;
83 
84 static pid_t pid;
85 
fi_convert_log_str(const char * value)86 static int fi_convert_log_str(const char *value)
87 {
88 	int i;
89 
90 	if (!value)
91 		return -1;
92 
93 	for (i = 0; log_levels[i]; i++) {
94 		if (!strcasecmp(value, log_levels[i]))
95 			return i;
96 	}
97 	return 0;
98 }
99 
fi_log_init(void)100 void fi_log_init(void)
101 {
102 	struct fi_filter subsys_filter;
103 	int level, i;
104 	char *levelstr = NULL, *provstr = NULL, *subsysstr = NULL;
105 
106 	fi_param_define(NULL, "log_level", FI_PARAM_STRING,
107 			"Specify logging level: warn, trace, info, debug (default: warn)");
108 	fi_param_get_str(NULL, "log_level", &levelstr);
109 	level = fi_convert_log_str(levelstr);
110 	if (level >= 0)
111 		log_mask = ((1 << (level + 1)) - 1);
112 
113 	fi_param_define(NULL, "log_prov", FI_PARAM_STRING,
114 			"Specify specific provider to log (default: all)");
115 	fi_param_get_str(NULL, "log_prov", &provstr);
116 	ofi_create_filter(&prov_log_filter, provstr);
117 
118 	fi_param_define(NULL, "log_subsys", FI_PARAM_STRING,
119 			"Specify specific subsystem to log (default: all)");
120 	fi_param_get_str(NULL, "log_subsys", &subsysstr);
121 	ofi_create_filter(&subsys_filter, subsysstr);
122 	for (i = 0; i < FI_LOG_SUBSYS_MAX; i++) {
123 		if (!ofi_apply_filter(&subsys_filter, log_subsys[i]))
124 			log_mask |= (1ULL << (i + FI_LOG_SUBSYS_OFFSET));
125 	}
126 	ofi_free_filter(&subsys_filter);
127 	pid = getpid();
128 }
129 
fi_log_fini(void)130 void fi_log_fini(void)
131 {
132 	ofi_free_filter(&prov_log_filter);
133 }
134 
135 __attribute__((visibility ("default"),EXTERNALLY_VISIBLE))
DEFAULT_SYMVER_PRE(fi_log_enabled)136 int DEFAULT_SYMVER_PRE(fi_log_enabled)(const struct fi_provider *prov,
137 		enum fi_log_level level,
138 		enum fi_log_subsys subsys)
139 {
140 	struct fi_prov_context *ctx;
141 
142 	ctx = (struct fi_prov_context *) &prov->context;
143 	return ((FI_LOG_TAG(ctx->disable_logging, level, subsys) & log_mask) ==
144 		FI_LOG_TAG(ctx->disable_logging, level, subsys));
145 }
146 DEFAULT_SYMVER(fi_log_enabled_, fi_log_enabled, FABRIC_1.0);
147 
148 __attribute__((visibility ("default"),EXTERNALLY_VISIBLE))
DEFAULT_SYMVER_PRE(fi_log)149 void DEFAULT_SYMVER_PRE(fi_log)(const struct fi_provider *prov, enum fi_log_level level,
150 		enum fi_log_subsys subsys, const char *func, int line,
151 		const char *fmt, ...)
152 {
153 	char buf[1024];
154 	int size;
155 
156 	va_list vargs;
157 
158 	size = snprintf(buf, sizeof(buf), "%s:%d:%s:%s:%s():%d<%s> ", PACKAGE,
159 			pid, prov->name, log_subsys[subsys], func, line,
160 			log_levels[level]);
161 
162 	va_start(vargs, fmt);
163 	vsnprintf(buf + size, sizeof(buf) - size, fmt, vargs);
164 	va_end(vargs);
165 
166 	fprintf(stderr, "%s", buf);
167 }
168 DEFAULT_SYMVER(fi_log_, fi_log, FABRIC_1.0);
169