File: fcoemon_utils.h

package info (click to toggle)
fcoe-utils 1.0.31%2Bgit20160622.5dfd3e4-5
  • links: PTS, VCS
  • area: main
  • in suites: buster
  • size: 1,060 kB
  • sloc: ansic: 11,919; sh: 1,298; makefile: 81
file content (401 lines) | stat: -rw-r--r-- 11,509 bytes parent folder | download | duplicates (4)
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
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
/*
 * Copyright(c) 2009 Intel Corporation. All rights reserved.
 *
 * This program is free software; you can redistribute it and/or modify it
 * under the terms and conditions of the GNU General Public License,
 * version 2, as published by the Free Software Foundation.
 *
 * This program is distributed in the hope it will be useful, but WITHOUT
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
 * more details.
 *
 * You should have received a copy of the GNU General Public License along with
 * this program; if not, write to the Free Software Foundation, Inc.,
 * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
 *
 * Maintained at www.Open-FCoE.org
 */

#ifndef _FCOEMON_UTILS_H_
#define _FCOEMON_UTILS_H_

#include <sys/types.h>
#include <sys/time.h>
#include <sys/socket.h>
#include <sys/queue.h>
#include <malloc.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <time.h>
#include <stdarg.h>
#include <ctype.h>
#include <time.h>
#include <unistd.h>
#include <signal.h>
#include <errno.h>
#include <syslog.h>
#include <dirent.h>

#include "fc_types.h"

#define ARRAY_SIZE(a)	(sizeof(a) / sizeof((a)[0]))

__attribute__((__format__(__printf__, 1, 2)))
void sa_log(const char *format, ...);
__attribute__((__format__(__printf__, 1, 2)))
void sa_log_debug(const char *format, ...);
__attribute__((__format__(__printf__, 3, 4)))
void sa_log_err(int, const char *func, const char *format, ...);

/*
 * These functions can be provided outside of libsa for those environments
 * that want to redirect them.
 */
void sa_log_output(const char *);	/* log message */
void sa_log_abort(const char *);	/* log message and abort */

#define __SA_STRING(x)  #x

/*
 * Logging options.
 */
#define SA_LOGF_TIME    0x0001      /* include timestamp in message */
#define SA_LOGF_DELTA   0x0002      /* include time since last message */

extern u_int sa_log_flags;          /* timestamp and other option flags */
extern int sa_log_time_delta_min;   /* minimum diff to print in millisec */
extern char *sa_log_prefix;         /* string to print before any message */

__attribute__((__format__(__printf__, 1, 2)))
extern void assert_failed(const char *s, ...);

#ifndef UNLIKELY
#define UNLIKELY(_x) (_x)
#endif /* UNLIKELY */

/*
 * ASSERT macros
 *
 * ASSERT(expr) - this calls assert_failed() if expr is false.  This variant
 * is not present in production code or if DEBUG_ASSERTS is not defined.
 * Be careful not to rely on expr being evaluated.
 */
#if defined(DEBUG_ASSERTS)
#define ASSERT(_x) do {							\
		if (UNLIKELY(!(_x))) {					\
			assert_failed("ASSERT FAILED (%s) @ %s:%d\n",	\
				"" #_x, __FILE__, __LINE__);		\
		}							\
	} while (0)
#else
#define ASSERT(_x)
#endif /* DEBUG_ASSERTS */

/*
 * ASSERT_NOTIMPL(expr) - this calls assert_failed() if expr is false.
 * The implication is that the condition is not handled by the current
 * implementation, and work should be done eventually to handle this.
 */
#define ASSERT_NOTIMPL(_x) do {						\
		if (UNLIKELY(!(_x))) {					\
			assert_failed("ASSERT (NOT IMPL) "		\
				"(%s) @ %s:%d\n",			\
				"" #_x, __FILE__, __LINE__);		\
		}							\
	} while (0)

/*
 * ASSERT_NOTREACHED - this is the same as ASSERT_NOTIMPL(0).
 */
#define ASSERT_NOTREACHED do {						\
		assert_failed("ASSERT (NOT REACHED) @ %s:%d\n",		\
			__FILE__, __LINE__);				\
	} while (0)

/*
 * ASSERT_BUG(bugno, expr).  This variant is used when a bug number has
 * been assigned to any one of the other assertion failures.  It is always
 * present in code.  It gives the bug number which helps locate
 * documentation and helps prevent duplicate bug filings.
 */
#define ASSERT_BUG(_bugNr, _x) do {					\
		if (UNLIKELY(!(_x))) {					\
			assert_failed("ASSERT (BUG %d) (%s) @ %s:%d\n", \
				(_bugNr), #_x, __FILE__, __LINE__);	\
		}                                                       \
	} while (0)

#ifndef LIBSA_USE_DANGEROUS_ROUTINES
#define strcpy DONT_USE_strcpy
#define strcat DONT_USE_strcat
#define gets   DONT_USE_gets
#endif /* LIBSA_USE_DANGEROUS_ROUTINES */

char *sa_strncpy_safe(char *dest, size_t len, const char *src, size_t src_len);

/*
 * Structure for tables encoding and decoding name-value pairs such as enums.
 */
struct sa_nameval {
	char      *nv_name;
	u_int32_t nv_val;
};

const char *sa_enum_decode(char *, size_t, const struct sa_nameval *, u_int);
int sa_enum_encode(const struct sa_nameval *tp, const char *, u_int *);
const char *sa_flags_decode(char *, size_t, const struct sa_nameval *, u_int);

/*
 * Timer facility.
 */

struct sa_timer {
	struct sa_timer	*tm_next;
	u_int64_t	tm_nsec;	/* relative time to event (nSec) */
	void		(*tm_handler)(void *arg);
	void		*tm_handler_arg;
	struct sa_timer **timer_head;
};


#define SA_TIMER_UNITS  (1000 * 1000UL)	/* number of timer ticks per second */

/*
 * Initialize a pre-allocated timer structure.
 */
void sa_timer_init(struct sa_timer *, void (*handler)(void *), void *arg);

/*
 * Test whether the timer is active.
 */
static inline int sa_timer_active(struct sa_timer *tm)
{
	return tm->tm_nsec != 0;
}

/*
 * Allocate a timer structure.  Set handler.
 */
struct sa_timer *sa_timer_alloc(void (*)(void *arg), void *arg);

/*
 * Set timer to fire.   Delta is in microseconds from now.
 */
void sa_timer_set(struct sa_timer *, u_long delta);

/*
 * Cancel timer.
 */
void sa_timer_cancel(struct sa_timer *);

/*
 * Free (and cancel) timer.
 */
void sa_timer_free(struct sa_timer *);


/*
 * Handle timer checks.  Called from select loop or other periodic function.
 *
 * The struct timeval passed in indicates how much time has passed since
 * the last call, and is set before returning to the maximum amount of time
 * that should elapse before the next call.
 *
 * Returns 1 if any timer handlers were invoked, 0 otherwise.
 */
int sa_timer_check(struct timeval *);

/*
 * Get time in nanoseconds since some arbitrary time.
 */
u_int64_t sa_timer_get(void);

/*
 * Get time in seconds since some arbitrary time.
 */
u_int sa_timer_get_secs(void);

/*
 * sa_select - Server Array select facility.
 *
 * This is a thin layer to poll files with a select loop.
 */

/*
 * Enter the polling loop which never exits.
 */
int sa_select_loop(void);

/*
 * Set callback for every time through the select loop.
 */
void sa_select_set_callback(void (*)(void));

/*
 * Add a callback to handle files which are ready for receive, transmit,
 * or to handle exceptions.
 */
void sa_select_add_fd(int fd, void (*rx_handler)(void *),
			void (*tx_handler)(void *),
			void (*ex_handler)(void *), void *arg);

/*
 * Change a single callback for a descriptor that's already been added.
 */
void sa_select_set_rx(int fd, void (*handler)(void *));
void sa_select_set_tx(int fd, void (*handler)(void *));
void sa_select_set_ex(int fd, void (*handler)(void *));

/*
 * Remove all callbacks for a file descriptor.
 */
void sa_select_rem_fd(int fd);

/*
 * Cause select loop to return.
 */
void sa_select_exit(int sig);

/*
 * Convert 48-bit IEEE MAC address to 64-bit FC WWN.
 */
extern fc_wwn_t
fc_wwn_from_mac(u_int64_t, u_int32_t scheme, u_int32_t port);

extern int hex2int(char *b);

extern int use_syslog;
void enable_syslog(int);
void enable_debug_log(int);

/*
 * Table and sysfs helpers
 */

/*
 * Structure for integer-indexed tables that can grow.
 */
struct sa_table {
	u_int32_t   st_size;        /* number of entries in table */
	u_int32_t   st_limit;       /* end of valid entries in table (public) */
	void        **st_table;     /* re-allocatable array of pointers */
};

/*
 * Function prototypes
 */
extern int sa_sys_read_line(const char *, const char *, char *, size_t);
extern int sa_sys_write_line(const char *, const char *, const char *);
extern int sa_sys_read_int(const char *, const char *, int *);
extern int sa_sys_read_u32(const char *, const char *, u_int32_t *);
extern int sa_sys_read_u64(const char *, const char *, u_int64_t *);
extern int sa_dir_read(char *, int (*)(struct dirent *, void *), void *);
extern char *sa_strncpy_safe(char *dest, size_t len,
			     const char *src, size_t src_len);
extern const char *sa_enum_decode(char *, size_t,
				  const struct sa_nameval *, u_int32_t);
extern int sa_enum_encode(const struct sa_nameval *tp,
			const char *, u_int32_t *);
extern const char *sa_flags_decode(char *, size_t,
				   const struct sa_nameval *, u_int32_t);
extern int sa_table_grow(struct sa_table *, u_int32_t index);
extern void sa_table_destroy_all(struct sa_table *);
extern void sa_table_destroy(struct sa_table *);
extern void sa_table_iterate(struct sa_table *tp,
			void (*handler)(void *ep, void *arg), void *arg);
extern void *sa_table_search(struct sa_table *tp,
			void *(*match)(void *ep, void *arg), void *arg);

/** sa_table_init(tp) - initialize a table.
 * @param tp table pointer.
 *
 * This just clears a table structure that was allocated by the caller.
 */
static inline void sa_table_init(struct sa_table *tp)
{
	memset(tp, 0, sizeof(*tp));
}

/** sa_table_lookup(tp, index) - lookup an entry in the table.
 * @param tp table pointer.
 * @param index the index in the table to access
 * @returns the entry, or NULL if the index wasn't valid.
 */
static inline void *sa_table_lookup(const struct sa_table *tp, u_int32_t index)
{
	void *ep = NULL;

	if (index < tp->st_limit)
		ep = tp->st_table[index];
	return ep;
}

/** sa_table_lookup_n(tp, n) - find Nth non-empty entry in a table.
 * @param tp table pointer.
 * @param n is the entry number, the first non-empty entry is 0.
 * @returns the entry, or NULL if the end of the table reached first.
 */
static inline void *sa_table_lookup_n(const struct sa_table *tp, u_int32_t n)
{
	void *ep = NULL;
	u_int32_t   i;

	for (i = 0; i < tp->st_limit; i++) {
		ep = tp->st_table[i];
		if (ep != NULL && n-- == 0)
			return ep;
	}
	return NULL;
}

/** sa_table_insert(tp, index, ep) - Replace or insert an entry in the table.
 * @param tp table pointer.
 * @param index the index for the new entry.
 * @param ep entry pointer.
 * @returns index on success, or -1 if the insert failed.
 *
 * Note: if the table has never been used, and is still all zero, this works.
 *
 * Note: perhaps not safe for multithreading.  Caller can lock the table
 * externally, but reallocation can take a while, during which time the
 * caller may not wish to hold the lock.
 */
static inline int sa_table_insert(struct sa_table *tp,
				  u_int32_t index, void *ep)
{
	if (index >= tp->st_limit && sa_table_grow(tp, index) < 0)
		return -1;
	tp->st_table[index] = ep;
	return index;
}

/** sa_table_append(tp, ep) - add entry to table and return index.
 *
 * @param tp pointer to sa_table structure.
 * @param ep pointer to new entry, to be added at the end of the table.
 * @returns new index, or -1 if table couldn't be grown.
 *
 * See notes on sa_table_insert().
 */
static inline int
sa_table_append(struct sa_table *tp, void *ep)
{
	return sa_table_insert(tp, tp->st_limit, ep);
}

/** sa_table_sort(tp, compare) - sort table in place
 *
 * @param tp pointer to sa_table structure.
 * @param compare function to compare two entries.  It is called with pointers
 * to the pointers to the entries to be compared.  See qsort(3).
 */
static inline void
sa_table_sort(struct sa_table *tp, int (*compare)(const void **, const void **))
{
	qsort(tp->st_table, tp->st_limit, sizeof(void *),
		(int (*)(const void *, const void *)) compare);
}

#endif /* _FCOEMON_UTILS_H_ */