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