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