]>
Commit | Line | Data |
---|---|---|
aea03ad6 QY |
1 | /* |
2 | * Debugging utilities. | |
3 | * Copyright (C) 2018 Cumulus Networks, Inc. | |
4 | * Quentin Young | |
5 | * | |
6 | * This program is free software; you can redistribute it and/or modify it | |
7 | * under the terms of the GNU General Public License as published by the Free | |
8 | * Software Foundation; either version 2 of the License, or (at your option) | |
9 | * any later version. | |
10 | * | |
11 | * This program is distributed in the hope that it will be useful, but WITHOUT | |
12 | * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or | |
13 | * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for | |
14 | * more details. | |
15 | * | |
16 | * You should have received a copy of the GNU General Public License along | |
17 | * with this program; see the file COPYING; if not, write to the Free Software | |
18 | * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA | |
19 | */ | |
20 | #ifndef _FRRDEBUG_H | |
21 | #define _FRRDEBUG_H | |
22 | ||
23 | #include <zebra.h> | |
24 | #include "command.h" | |
25 | #include "frratomic.h" | |
26 | ||
5e244469 RW |
27 | #ifdef __cplusplus |
28 | extern "C" { | |
29 | #endif | |
30 | ||
aea03ad6 QY |
31 | /* |
32 | * Debugging modes. | |
33 | * | |
34 | * FRR's convention is that a debug statement issued under the vty CONFIG_NODE | |
35 | * persists to the config file, whereas the same debug statement issued from | |
36 | * the ENABLE_NODE only persists for the current session. These are mapped to | |
37 | * DEBUG_MODE_CONF and DEBUG_MODE_TERM respectively. | |
38 | * | |
39 | * They are not mutually exclusive and are placed in the MSB of the flags | |
40 | * field in a debugging record. | |
41 | */ | |
42 | #define DEBUG_MODE_TERM 0x01000000 | |
43 | #define DEBUG_MODE_CONF 0x02000000 | |
44 | #define DEBUG_MODE_ALL (DEBUG_MODE_TERM | DEBUG_MODE_CONF) | |
45 | #define DEBUG_MODE_NONE 0x00000000 | |
46 | #define DEBUG_OPT_ALL 0x00FFFFFF | |
47 | #define DEBUG_OPT_NONE 0x00000000 | |
48 | ||
49 | ||
50 | /* | |
51 | * Debugging record. | |
52 | * | |
53 | * All operations on this record exposed in this header are MT-safe. | |
54 | * | |
55 | * flags | |
56 | * A bitfield with the following format (bytes high to low) | |
57 | * - [0] Debugging mode field (MSB) | Mode | |
58 | * - [1] Arbitrary flag field | Option | |
59 | * - [2] Arbitrary flag field | Option | |
60 | * - [3] Arbitrary flag field (LSB) | Option | |
61 | * | |
62 | * ALL THESE BYTES ARE YOURS - EXCEPT MODE. | |
63 | * ATTEMPT NO BIT OPS THERE. | |
64 | * | |
65 | * The MSB of this field determines the debug mode, Use the DEBUG_MODE* | |
66 | * macros to manipulate this byte. | |
67 | * | |
68 | * The low 3 bytes of this field may be used to store arbitrary information. | |
69 | * Usually they are used to store flags that tune how detailed the logging | |
70 | * for a particular debug record is. Use the DEBUG_OPT* macros to manipulate | |
71 | * those bytes. | |
72 | * | |
73 | * All operations performed on this field should be done using the macros | |
74 | * later in this header file. They are guaranteed to be atomic operations | |
75 | * with respect to this field. Using anything except the macros to | |
76 | * manipulate the flags field in a multithreaded environment results in | |
77 | * undefined behavior. | |
78 | * | |
79 | * desc | |
80 | * Human-readable description of this debugging record. | |
81 | */ | |
82 | struct debug { | |
c8a65463 | 83 | atomic_uint_fast32_t flags; |
aea03ad6 QY |
84 | const char *desc; |
85 | }; | |
86 | ||
960b9a53 | 87 | PREDECL_LIST(debug_cb_list); |
aea03ad6 QY |
88 | /* |
89 | * Callback set for debugging code. | |
90 | * | |
91 | * debug_set_all | |
92 | * Function pointer to call when the user requests that all debugs have a | |
93 | * mode set. | |
94 | */ | |
95 | struct debug_callbacks { | |
f756a869 DS |
96 | /* |
97 | * Linked list of Callbacks to call | |
98 | */ | |
99 | struct debug_cb_list_item item; | |
100 | ||
aea03ad6 QY |
101 | /* |
102 | * flags | |
103 | * flags to set on debug flag fields | |
104 | * | |
105 | * set | |
106 | * true: set flags | |
107 | * false: unset flags | |
108 | */ | |
109 | void (*debug_set_all)(uint32_t flags, bool set); | |
110 | }; | |
111 | ||
112 | /* | |
113 | * Check if a mode is set for a debug. | |
114 | * | |
115 | * MT-Safe | |
116 | */ | |
68881884 QY |
117 | #define DEBUG_MODE_CHECK(name, mode) \ |
118 | CHECK_FLAG_ATOMIC(&(name)->flags, (mode)&DEBUG_MODE_ALL) | |
aea03ad6 QY |
119 | |
120 | /* | |
121 | * Check if an option bit is set for a debug. | |
122 | * | |
123 | * MT-Safe | |
124 | */ | |
68881884 QY |
125 | #define DEBUG_OPT_CHECK(name, opt) \ |
126 | CHECK_FLAG_ATOMIC(&(name)->flags, (opt)&DEBUG_OPT_ALL) | |
aea03ad6 QY |
127 | |
128 | /* | |
129 | * Check if bits are set for a debug. | |
130 | * | |
131 | * MT-Safe | |
132 | */ | |
68881884 | 133 | #define DEBUG_FLAGS_CHECK(name, fl) CHECK_FLAG_ATOMIC(&(name)->flags, (fl)) |
aea03ad6 QY |
134 | |
135 | /* | |
136 | * Set modes on a debug. | |
137 | * | |
138 | * MT-Safe | |
139 | */ | |
68881884 QY |
140 | #define DEBUG_MODE_SET(name, mode, onoff) \ |
141 | do { \ | |
142 | if (onoff) \ | |
143 | SET_FLAG_ATOMIC(&(name)->flags, \ | |
144 | (mode)&DEBUG_MODE_ALL); \ | |
145 | else \ | |
146 | UNSET_FLAG_ATOMIC(&(name)->flags, \ | |
147 | (mode)&DEBUG_MODE_ALL); \ | |
148 | } while (0) | |
aea03ad6 | 149 | |
68881884 QY |
150 | /* Convenience macros for specific set operations. */ |
151 | #define DEBUG_MODE_ON(name, mode) DEBUG_MODE_SET(name, mode, true) | |
152 | #define DEBUG_MODE_OFF(name, mode) DEBUG_MODE_SET(name, mode, false) | |
aea03ad6 QY |
153 | |
154 | /* | |
155 | * Set options on a debug. | |
156 | * | |
157 | * MT-Safe | |
158 | */ | |
68881884 QY |
159 | #define DEBUG_OPT_SET(name, opt, onoff) \ |
160 | do { \ | |
161 | if (onoff) \ | |
162 | SET_FLAG_ATOMIC(&(name)->flags, (opt)&DEBUG_OPT_ALL); \ | |
163 | else \ | |
164 | UNSET_FLAG_ATOMIC(&(name)->flags, \ | |
165 | (opt)&DEBUG_OPT_ALL); \ | |
166 | } while (0) | |
aea03ad6 | 167 | |
68881884 QY |
168 | /* Convenience macros for specific set operations. */ |
169 | #define DEBUG_OPT_ON(name, opt) DEBUG_OPT_SET(name, opt, true) | |
170 | #define DEBUG_OPT_OFF(name, opt) DEBUG_OPT_SET(name, opt, true) | |
aea03ad6 QY |
171 | |
172 | /* | |
173 | * Set bits on a debug. | |
174 | * | |
175 | * MT-Safe | |
176 | */ | |
68881884 QY |
177 | #define DEBUG_FLAGS_SET(name, fl, onoff) \ |
178 | do { \ | |
179 | if (onoff) \ | |
180 | SET_FLAG_ATOMIC(&(name)->flags, (fl)); \ | |
181 | else \ | |
182 | UNSET_FLAG_ATOMIC(&(name)->flags, (fl)); \ | |
183 | } while (0) | |
aea03ad6 | 184 | |
68881884 QY |
185 | /* Convenience macros for specific set operations. */ |
186 | #define DEBUG_FLAGS_ON(name, fl) DEBUG_FLAGS_SET(&(name)->flags, (type), true) | |
187 | #define DEBUG_FLAGS_OFF(name, fl) DEBUG_FLAGS_SET(&(name)->flags, (type), false) | |
aea03ad6 QY |
188 | |
189 | /* | |
190 | * Unset all modes and options on a debug. | |
191 | * | |
192 | * MT-Safe | |
193 | */ | |
194 | #define DEBUG_CLEAR(name) RESET_FLAG_ATOMIC(&(name)->flags) | |
195 | ||
196 | /* | |
197 | * Set all modes and options on a debug. | |
198 | * | |
199 | * MT-Safe | |
200 | */ | |
201 | #define DEBUG_ON(name) \ | |
202 | SET_FLAG_ATOMIC(&(name)->flags, DEBUG_MODE_ALL | DEBUG_OPT_ALL) | |
203 | ||
204 | /* | |
205 | * Map a vty node to the correct debugging mode flags. FRR behaves such that a | |
206 | * debug statement issued under the config node persists to the config file, | |
207 | * whereas the same debug statement issued from the enable node only persists | |
208 | * for the current session. | |
209 | * | |
210 | * MT-Safe | |
211 | */ | |
212 | #define DEBUG_NODE2MODE(vtynode) \ | |
213 | (((vtynode) == CONFIG_NODE) ? DEBUG_MODE_ALL : DEBUG_MODE_TERM) | |
214 | ||
68881884 QY |
215 | /* |
216 | * Debug at the given level to the default logging destination. | |
217 | * | |
218 | * MT-Safe | |
219 | */ | |
220 | #define DEBUG(level, name, fmt, ...) \ | |
221 | do { \ | |
222 | if (DEBUG_MODE_CHECK(name, DEBUG_MODE_ALL)) \ | |
223 | zlog_##level(fmt, ##__VA_ARGS__); \ | |
224 | } while (0) | |
225 | ||
226 | /* Convenience macros for the various levels. */ | |
227 | #define DEBUGE(name, fmt, ...) DEBUG(err, name, fmt, ##__VA_ARGS__) | |
228 | #define DEBUGW(name, fmt, ...) DEBUG(warn, name, fmt, ##__VA_ARGS__) | |
229 | #define DEBUGI(name, fmt, ...) DEBUG(info, name, fmt, ##__VA_ARGS__) | |
230 | #define DEBUGN(name, fmt, ...) DEBUG(notice, name, fmt, ##__VA_ARGS__) | |
231 | #define DEBUGD(name, fmt, ...) DEBUG(debug, name, fmt, ##__VA_ARGS__) | |
aea03ad6 QY |
232 | |
233 | /* | |
234 | * Optional initializer for debugging. Highly recommended. | |
235 | * | |
236 | * This function installs common debugging commands and allows the caller to | |
237 | * specify callbacks to take when these commands are issued, allowing the | |
238 | * caller to respond to events such as a request to turn off all debugs. | |
239 | * | |
240 | * MT-Safe | |
241 | */ | |
f756a869 | 242 | void debug_init(struct debug_callbacks *cb); |
aea03ad6 | 243 | |
ae0994f6 DS |
244 | /* |
245 | * Turn on the cli to turn on/off debugs. | |
246 | * Should only be called by libfrr | |
247 | */ | |
248 | void debug_init_cli(void); | |
249 | ||
5e244469 RW |
250 | #ifdef __cplusplus |
251 | } | |
252 | #endif | |
253 | ||
aea03ad6 | 254 | #endif /* _FRRDEBUG_H */ |