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