]> git.proxmox.com Git - mirror_ovs.git/blob - lib/vlog.c
ovsdb-idl: Fix iteration over tracked rows with no actual data.
[mirror_ovs.git] / lib / vlog.c
1 /*
2 * Copyright (c) 2008, 2009, 2010, 2011, 2012, 2013, 2015, 2016 Nicira, Inc.
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at:
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17 #include <config.h>
18 #include "openvswitch/vlog.h"
19 #include <assert.h>
20 #include <ctype.h>
21 #include <errno.h>
22 #include <fcntl.h>
23 #include <stdarg.h>
24 #include <stdlib.h>
25 #include <string.h>
26 #include <sys/stat.h>
27 #include <sys/types.h>
28 #include <syslog.h>
29 #include <time.h>
30 #include <unistd.h>
31 #include "async-append.h"
32 #include "coverage.h"
33 #include "dirs.h"
34 #include "openvswitch/dynamic-string.h"
35 #include "openvswitch/ofpbuf.h"
36 #include "ovs-thread.h"
37 #include "sat-math.h"
38 #include "socket-util.h"
39 #include "svec.h"
40 #include "syslog-direct.h"
41 #include "syslog-libc.h"
42 #include "syslog-null.h"
43 #include "syslog-provider.h"
44 #include "timeval.h"
45 #include "unixctl.h"
46 #include "util.h"
47
48 VLOG_DEFINE_THIS_MODULE(vlog);
49
50 /* ovs_assert() logs the assertion message, so using ovs_assert() in this
51 * source file could cause recursion. */
52 #undef ovs_assert
53 #define ovs_assert use_assert_instead_of_ovs_assert_in_this_module
54
55 /* Name for each logging level. */
56 static const char *const level_names[VLL_N_LEVELS] = {
57 #define VLOG_LEVEL(NAME, SYSLOG_LEVEL, RFC5424) #NAME,
58 VLOG_LEVELS
59 #undef VLOG_LEVEL
60 };
61
62 /* Syslog value for each logging level. */
63 static const int syslog_levels[VLL_N_LEVELS] = {
64 #define VLOG_LEVEL(NAME, SYSLOG_LEVEL, RFC5424) SYSLOG_LEVEL,
65 VLOG_LEVELS
66 #undef VLOG_LEVEL
67 };
68
69 /* RFC 5424 defines specific values for each syslog level. Normally LOG_* use
70 * the same values. Verify that in fact they're the same. If we get assertion
71 * failures here then we need to define a separate rfc5424_levels[] array. */
72 #define VLOG_LEVEL(NAME, SYSLOG_LEVEL, RFC5424) \
73 BUILD_ASSERT_DECL(SYSLOG_LEVEL == RFC5424);
74 VLOG_LEVELS
75 #undef VLOG_LEVELS
76
77 /* Similarly, RFC 5424 defines the local0 facility with the value ordinarily
78 * used for LOG_LOCAL0. */
79 BUILD_ASSERT_DECL(LOG_LOCAL0 == (16 << 3));
80
81 /* Protects the 'pattern' in all "struct destination"s, so that a race between
82 * changing and reading the pattern does not cause an access to freed
83 * memory. */
84 static struct ovs_rwlock pattern_rwlock = OVS_RWLOCK_INITIALIZER;
85
86 /* Information about each destination. */
87 struct destination {
88 const char *name; /* Name. */
89 char *pattern OVS_GUARDED_BY(pattern_rwlock); /* Current pattern. */
90 bool default_pattern; /* Whether current pattern is the default. */
91 };
92 static struct destination destinations[VLF_N_DESTINATIONS] = {
93 #define VLOG_DESTINATION(NAME, PATTERN) {#NAME, PATTERN, true},
94 VLOG_DESTINATIONS
95 #undef VLOG_DESTINATION
96 };
97
98 /* Sequence number for the message currently being composed. */
99 DEFINE_STATIC_PER_THREAD_DATA(unsigned int, msg_num, 0);
100
101 /* VLF_FILE configuration.
102 *
103 * All of the following is protected by 'log_file_mutex', which nests inside
104 * pattern_rwlock. */
105 static struct ovs_mutex log_file_mutex OVS_ACQ_AFTER(pattern_rwlock)
106 = OVS_MUTEX_INITIALIZER;
107 static char *log_file_name OVS_GUARDED_BY(log_file_mutex) = NULL;
108 static int log_fd OVS_GUARDED_BY(log_file_mutex) = -1;
109 static struct async_append *log_writer OVS_GUARDED_BY(log_file_mutex);
110 static bool log_async OVS_GUARDED_BY(log_file_mutex);
111 static struct syslogger *syslogger = NULL;
112
113 /* The log modules. */
114 static struct ovs_list vlog_modules OVS_GUARDED_BY(log_file_mutex)
115 = OVS_LIST_INITIALIZER(&vlog_modules);
116
117 /* Syslog export configuration. */
118 static int syslog_fd OVS_GUARDED_BY(pattern_rwlock) = -1;
119
120 /* Log facility configuration. */
121 static atomic_int log_facility = ATOMIC_VAR_INIT(0);
122
123 /* Facility name and its value. */
124 struct vlog_facility {
125 char *name; /* Name. */
126 unsigned int value; /* Facility associated with 'name'. */
127 };
128 static struct vlog_facility vlog_facilities[] = {
129 {"kern", LOG_KERN},
130 {"user", LOG_USER},
131 {"mail", LOG_MAIL},
132 {"daemon", LOG_DAEMON},
133 {"auth", LOG_AUTH},
134 {"syslog", LOG_SYSLOG},
135 {"lpr", LOG_LPR},
136 {"news", LOG_NEWS},
137 {"uucp", LOG_UUCP},
138 {"clock", LOG_CRON},
139 {"ftp", LOG_FTP},
140 {"ntp", 12<<3},
141 {"audit", 13<<3},
142 {"alert", 14<<3},
143 {"clock2", 15<<3},
144 {"local0", LOG_LOCAL0},
145 {"local1", LOG_LOCAL1},
146 {"local2", LOG_LOCAL2},
147 {"local3", LOG_LOCAL3},
148 {"local4", LOG_LOCAL4},
149 {"local5", LOG_LOCAL5},
150 {"local6", LOG_LOCAL6},
151 {"local7", LOG_LOCAL7}
152 };
153 static bool vlog_facility_exists(const char* facility, int *value);
154
155 static void format_log_message(const struct vlog_module *, enum vlog_level,
156 const char *pattern,
157 const char *message, va_list, struct ds *)
158 OVS_PRINTF_FORMAT(4, 0);
159
160 /* Searches the 'n_names' in 'names'. Returns the index of a match for
161 * 'target', or 'n_names' if no name matches. */
162 static size_t
163 search_name_array(const char *target, const char *const *names, size_t n_names)
164 {
165 size_t i;
166
167 for (i = 0; i < n_names; i++) {
168 assert(names[i]);
169 if (!strcasecmp(names[i], target)) {
170 break;
171 }
172 }
173 return i;
174 }
175
176 /* Returns the name for logging level 'level'. */
177 const char *
178 vlog_get_level_name(enum vlog_level level)
179 {
180 assert(level < VLL_N_LEVELS);
181 return level_names[level];
182 }
183
184 /* Returns the logging level with the given 'name', or VLL_N_LEVELS if 'name'
185 * is not the name of a logging level. */
186 enum vlog_level
187 vlog_get_level_val(const char *name)
188 {
189 return search_name_array(name, level_names, ARRAY_SIZE(level_names));
190 }
191
192 /* Returns the name for logging destination 'destination'. */
193 const char *
194 vlog_get_destination_name(enum vlog_destination destination)
195 {
196 assert(destination < VLF_N_DESTINATIONS);
197 return destinations[destination].name;
198 }
199
200 /* Returns the logging destination named 'name', or VLF_N_DESTINATIONS if
201 * 'name' is not the name of a logging destination. */
202 enum vlog_destination
203 vlog_get_destination_val(const char *name)
204 {
205 size_t i;
206
207 for (i = 0; i < VLF_N_DESTINATIONS; i++) {
208 if (!strcasecmp(destinations[i].name, name)) {
209 break;
210 }
211 }
212 return i;
213 }
214
215 void
216 vlog_insert_module(struct ovs_list *vlog)
217 {
218 ovs_mutex_lock(&log_file_mutex);
219 ovs_list_insert(&vlog_modules, vlog);
220 ovs_mutex_unlock(&log_file_mutex);
221 }
222
223 /* Returns the name for logging module 'module'. */
224 const char *
225 vlog_get_module_name(const struct vlog_module *module)
226 {
227 return module->name;
228 }
229
230 /* Returns the logging module named 'name', or NULL if 'name' is not the name
231 * of a logging module. */
232 struct vlog_module *
233 vlog_module_from_name(const char *name)
234 {
235 struct vlog_module *mp;
236
237 ovs_mutex_lock(&log_file_mutex);
238 LIST_FOR_EACH (mp, list, &vlog_modules) {
239 if (!strcasecmp(name, mp->name)) {
240 ovs_mutex_unlock(&log_file_mutex);
241 return mp;
242 }
243 }
244 ovs_mutex_unlock(&log_file_mutex);
245
246 return NULL;
247 }
248
249 /* Returns the current logging level for the given 'module' and
250 * 'destination'. */
251 enum vlog_level
252 vlog_get_level(const struct vlog_module *module,
253 enum vlog_destination destination)
254 {
255 assert(destination < VLF_N_DESTINATIONS);
256 return module->levels[destination];
257 }
258
259 static void
260 update_min_level(struct vlog_module *module) OVS_REQUIRES(log_file_mutex)
261 {
262 enum vlog_destination destination;
263
264 module->min_level = VLL_OFF;
265 for (destination = 0; destination < VLF_N_DESTINATIONS; destination++) {
266 if (log_fd >= 0 || destination != VLF_FILE) {
267 enum vlog_level level = module->levels[destination];
268 if (level > module->min_level) {
269 module->min_level = level;
270 }
271 }
272 }
273 }
274
275 static void
276 set_destination_level(enum vlog_destination destination,
277 struct vlog_module *module, enum vlog_level level)
278 {
279 assert(destination >= 0 && destination < VLF_N_DESTINATIONS);
280 assert(level < VLL_N_LEVELS);
281
282 ovs_mutex_lock(&log_file_mutex);
283 if (!module) {
284 struct vlog_module *mp;
285 LIST_FOR_EACH (mp, list, &vlog_modules) {
286 mp->levels[destination] = level;
287 update_min_level(mp);
288 }
289 } else {
290 module->levels[destination] = level;
291 update_min_level(module);
292 }
293 ovs_mutex_unlock(&log_file_mutex);
294 }
295
296 /* Sets the logging level for the given 'module' and 'destination' to 'level'.
297 * A null 'module' or a 'destination' of VLF_ANY_DESTINATION is treated as a
298 * wildcard across all modules or destinations, respectively. */
299 void
300 vlog_set_levels(struct vlog_module *module, enum vlog_destination destination,
301 enum vlog_level level)
302 {
303 assert(destination < VLF_N_DESTINATIONS ||
304 destination == VLF_ANY_DESTINATION);
305 if (destination == VLF_ANY_DESTINATION) {
306 for (destination = 0; destination < VLF_N_DESTINATIONS;
307 destination++) {
308 set_destination_level(destination, module, level);
309 }
310 } else {
311 set_destination_level(destination, module, level);
312 }
313 }
314
315 static void
316 do_set_pattern(enum vlog_destination destination, const char *pattern)
317 {
318 struct destination *f = &destinations[destination];
319
320 ovs_rwlock_wrlock(&pattern_rwlock);
321 if (!f->default_pattern) {
322 free(f->pattern);
323 } else {
324 f->default_pattern = false;
325 }
326 f->pattern = xstrdup(pattern);
327 ovs_rwlock_unlock(&pattern_rwlock);
328 }
329
330 /* Sets the pattern for the given 'destination' to 'pattern'. */
331 void
332 vlog_set_pattern(enum vlog_destination destination, const char *pattern)
333 {
334 assert(destination < VLF_N_DESTINATIONS ||
335 destination == VLF_ANY_DESTINATION);
336 if (destination == VLF_ANY_DESTINATION) {
337 for (destination = 0; destination < VLF_N_DESTINATIONS;
338 destination++) {
339 do_set_pattern(destination, pattern);
340 }
341 } else {
342 do_set_pattern(destination, pattern);
343 }
344 }
345
346 /* Sets the name of the log file used by VLF_FILE to 'file_name', or to the
347 * default file name if 'file_name' is null. Returns 0 if successful,
348 * otherwise a positive errno value. */
349 int
350 vlog_set_log_file(const char *file_name)
351 {
352 char *new_log_file_name;
353 struct vlog_module *mp;
354 struct stat old_stat;
355 struct stat new_stat;
356 int new_log_fd;
357 bool same_file;
358 bool log_close;
359
360 /* Open new log file. */
361 new_log_file_name = (file_name
362 ? xstrdup(file_name)
363 : xasprintf("%s/%s.log", ovs_logdir(), program_name));
364 new_log_fd = open(new_log_file_name, O_WRONLY | O_CREAT | O_APPEND, 0660);
365 if (new_log_fd < 0) {
366 VLOG_WARN("failed to open %s for logging: %s",
367 new_log_file_name, ovs_strerror(errno));
368 free(new_log_file_name);
369 return errno;
370 }
371
372 /* If the new log file is the same one we already have open, bail out. */
373 ovs_mutex_lock(&log_file_mutex);
374 same_file = (log_fd >= 0
375 && new_log_fd >= 0
376 && !fstat(log_fd, &old_stat)
377 && !fstat(new_log_fd, &new_stat)
378 && old_stat.st_dev == new_stat.st_dev
379 && old_stat.st_ino == new_stat.st_ino);
380 ovs_mutex_unlock(&log_file_mutex);
381 if (same_file) {
382 close(new_log_fd);
383 free(new_log_file_name);
384 return 0;
385 }
386
387 /* Log closing old log file (we can't log while holding log_file_mutex). */
388 ovs_mutex_lock(&log_file_mutex);
389 log_close = log_fd >= 0;
390 ovs_mutex_unlock(&log_file_mutex);
391 if (log_close) {
392 VLOG_INFO("closing log file");
393 }
394
395 /* Close old log file, if any, and install new one. */
396 ovs_mutex_lock(&log_file_mutex);
397 if (log_fd >= 0) {
398 close(log_fd);
399 async_append_destroy(log_writer);
400 }
401
402 free(log_file_name);
403 log_file_name = xstrdup(new_log_file_name);
404 log_fd = new_log_fd;
405 if (log_async) {
406 log_writer = async_append_create(new_log_fd);
407 }
408
409 LIST_FOR_EACH (mp, list, &vlog_modules) {
410 update_min_level(mp);
411 }
412 ovs_mutex_unlock(&log_file_mutex);
413
414 /* Log opening new log file (we can't log while holding log_file_mutex). */
415 VLOG_INFO("opened log file %s", new_log_file_name);
416 free(new_log_file_name);
417
418 return 0;
419 }
420
421 /* Closes and then attempts to re-open the current log file. (This is useful
422 * just after log rotation, to ensure that the new log file starts being used.)
423 * Returns 0 if successful, otherwise a positive errno value. */
424 int
425 vlog_reopen_log_file(void)
426 {
427 char *fn;
428
429 ovs_mutex_lock(&log_file_mutex);
430 fn = nullable_xstrdup(log_file_name);
431 ovs_mutex_unlock(&log_file_mutex);
432
433 if (fn) {
434 int error = vlog_set_log_file(fn);
435 free(fn);
436 return error;
437 } else {
438 return 0;
439 }
440 }
441
442 #ifndef _WIN32
443 /* In case a log file exists, change its owner to new 'user' and 'group'.
444 *
445 * This is useful for handling cases where the --log-file option is
446 * specified ahead of the --user option. */
447 void
448 vlog_change_owner_unix(uid_t user, gid_t group)
449 {
450 struct ds err = DS_EMPTY_INITIALIZER;
451 int error;
452
453 ovs_mutex_lock(&log_file_mutex);
454 error = log_file_name ? chown(log_file_name, user, group) : 0;
455 if (error) {
456 /* Build the error message. We can not call VLOG_FATAL directly
457 * here because VLOG_FATAL() will try again to to acquire
458 * 'log_file_mutex' lock, causing deadlock.
459 */
460 ds_put_format(&err, "Failed to change %s ownership: %s.",
461 log_file_name, ovs_strerror(errno));
462 }
463 ovs_mutex_unlock(&log_file_mutex);
464
465 if (error) {
466 VLOG_FATAL("%s", ds_steal_cstr(&err));
467 }
468 }
469 #endif
470
471 /* Set debugging levels. Returns null if successful, otherwise an error
472 * message that the caller must free(). */
473 char *
474 vlog_set_levels_from_string(const char *s_)
475 {
476 char *s = xstrdup(s_);
477 char *save_ptr = NULL;
478 char *msg = NULL;
479 char *word;
480
481 word = strtok_r(s, " ,:\t", &save_ptr);
482 if (word && !strcasecmp(word, "PATTERN")) {
483 enum vlog_destination destination;
484
485 word = strtok_r(NULL, " ,:\t", &save_ptr);
486 if (!word) {
487 msg = xstrdup("missing destination");
488 goto exit;
489 }
490
491 destination = (!strcasecmp(word, "ANY")
492 ? VLF_ANY_DESTINATION
493 : vlog_get_destination_val(word));
494 if (destination == VLF_N_DESTINATIONS) {
495 msg = xasprintf("unknown destination \"%s\"", word);
496 goto exit;
497 }
498 vlog_set_pattern(destination, save_ptr);
499 } else if (word && !strcasecmp(word, "FACILITY")) {
500 int value;
501
502 if (!vlog_facility_exists(save_ptr, &value)) {
503 msg = xstrdup("invalid facility");
504 goto exit;
505 }
506 atomic_store_explicit(&log_facility, value, memory_order_relaxed);
507 } else {
508 struct vlog_module *module = NULL;
509 enum vlog_level level = VLL_N_LEVELS;
510 enum vlog_destination destination = VLF_N_DESTINATIONS;
511
512 for (; word != NULL; word = strtok_r(NULL, " ,:\t", &save_ptr)) {
513 if (!strcasecmp(word, "ANY")) {
514 continue;
515 } else if (vlog_get_destination_val(word) != VLF_N_DESTINATIONS) {
516 if (destination != VLF_N_DESTINATIONS) {
517 msg = xstrdup("cannot specify multiple destinations");
518 goto exit;
519 }
520 destination = vlog_get_destination_val(word);
521 } else if (vlog_get_level_val(word) != VLL_N_LEVELS) {
522 if (level != VLL_N_LEVELS) {
523 msg = xstrdup("cannot specify multiple levels");
524 goto exit;
525 }
526 level = vlog_get_level_val(word);
527 } else if (vlog_module_from_name(word)) {
528 if (module) {
529 msg = xstrdup("cannot specify multiple modules");
530 goto exit;
531 }
532 module = vlog_module_from_name(word);
533 } else {
534 msg = xasprintf("no destination, level, or module \"%s\"",
535 word);
536 goto exit;
537 }
538 }
539
540 if (destination == VLF_N_DESTINATIONS) {
541 destination = VLF_ANY_DESTINATION;
542 }
543 if (level == VLL_N_LEVELS) {
544 level = VLL_DBG;
545 }
546 vlog_set_levels(module, destination, level);
547 }
548
549 exit:
550 free(s);
551 return msg;
552 }
553
554 /* Set debugging levels. Abort with an error message if 's' is invalid. */
555 void
556 vlog_set_levels_from_string_assert(const char *s)
557 {
558 char *error = vlog_set_levels_from_string(s);
559 if (error) {
560 ovs_fatal(0, "%s", error);
561 }
562 }
563
564 /* If 'arg' is null, configure maximum verbosity. Otherwise, sets
565 * configuration according to 'arg' (see vlog_set_levels_from_string()). */
566 void
567 vlog_set_verbosity(const char *arg)
568 {
569 if (arg) {
570 char *msg = vlog_set_levels_from_string(arg);
571 if (msg) {
572 ovs_fatal(0, "processing \"%s\": %s", arg, msg);
573 }
574 } else {
575 vlog_set_levels(NULL, VLF_ANY_DESTINATION, VLL_DBG);
576 }
577 }
578
579 void
580 vlog_set_syslog_method(const char *method)
581 {
582 if (syslogger) {
583 /* Set syslogger only, if one is not already set. This effectively
584 * means that only the first --syslog-method argument is honored. */
585 return;
586 }
587
588 if (!strcmp(method, "null")) {
589 syslogger = syslog_null_create();
590 } else if (!strcmp(method, "libc")) {
591 syslogger = syslog_libc_create();
592 } else if (!strncmp(method, "udp:", 4) || !strncmp(method, "unix:", 5)) {
593 syslogger = syslog_direct_create(method);
594 } else {
595 ovs_fatal(0, "unsupported syslog method '%s'", method);
596 }
597 }
598
599 /* Set the vlog udp syslog target. */
600 void
601 vlog_set_syslog_target(const char *target)
602 {
603 int new_fd;
604
605 inet_open_active(SOCK_DGRAM, target, -1, NULL, &new_fd, 0);
606
607 ovs_rwlock_wrlock(&pattern_rwlock);
608 if (syslog_fd >= 0) {
609 close(syslog_fd);
610 }
611 syslog_fd = new_fd;
612 ovs_rwlock_unlock(&pattern_rwlock);
613 }
614
615 /*
616 * This function writes directly to log file without using async writer or
617 * taking a lock. Caller must hold 'log_file_mutex' or be sure that it's
618 * not necessary. Could be used in exceptional cases like dumping of backtrace
619 * on fatal signals.
620 */
621 void
622 vlog_direct_write_to_log_file_unsafe(const char *s)
623 OVS_NO_THREAD_SAFETY_ANALYSIS
624 {
625 if (log_fd >= 0) {
626 ignore(write(log_fd, s, strlen(s)));
627 }
628 }
629
630 /* Returns 'false' if 'facility' is not a valid string. If 'facility'
631 * is a valid string, sets 'value' with the integer value of 'facility'
632 * and returns 'true'. */
633 static bool
634 vlog_facility_exists(const char* facility, int *value)
635 {
636 size_t i;
637 for (i = 0; i < ARRAY_SIZE(vlog_facilities); i++) {
638 if (!strcasecmp(vlog_facilities[i].name, facility)) {
639 *value = vlog_facilities[i].value;
640 return true;
641 }
642 }
643 return false;
644 }
645
646 static void
647 vlog_unixctl_set(struct unixctl_conn *conn, int argc, const char *argv[],
648 void *aux OVS_UNUSED)
649 {
650 int i;
651
652 /* With no argument, set all destinations and modules to "dbg". */
653 if (argc == 1) {
654 vlog_set_levels(NULL, VLF_ANY_DESTINATION, VLL_DBG);
655 }
656 for (i = 1; i < argc; i++) {
657 char *msg = vlog_set_levels_from_string(argv[i]);
658 if (msg) {
659 unixctl_command_reply_error(conn, msg);
660 free(msg);
661 return;
662 }
663 }
664 unixctl_command_reply(conn, NULL);
665 }
666
667 static void
668 vlog_unixctl_list(struct unixctl_conn *conn, int argc OVS_UNUSED,
669 const char *argv[] OVS_UNUSED, void *aux OVS_UNUSED)
670 {
671 char *msg = vlog_get_levels();
672 unixctl_command_reply(conn, msg);
673 free(msg);
674 }
675
676 static void
677 vlog_unixctl_list_pattern(struct unixctl_conn *conn, int argc OVS_UNUSED,
678 const char *argv[] OVS_UNUSED, void *aux OVS_UNUSED)
679 {
680 char *msg;
681
682 msg = vlog_get_patterns();
683 unixctl_command_reply(conn, msg);
684 free(msg);
685 }
686
687 static void
688 vlog_unixctl_reopen(struct unixctl_conn *conn, int argc OVS_UNUSED,
689 const char *argv[] OVS_UNUSED, void *aux OVS_UNUSED)
690 {
691 bool has_log_file;
692
693 ovs_mutex_lock(&log_file_mutex);
694 has_log_file = log_file_name != NULL;
695 ovs_mutex_unlock(&log_file_mutex);
696
697 if (has_log_file) {
698 int error = vlog_reopen_log_file();
699 if (error) {
700 unixctl_command_reply_error(conn, ovs_strerror(errno));
701 } else {
702 unixctl_command_reply(conn, NULL);
703 }
704 } else {
705 unixctl_command_reply_error(conn, "Logging to file not configured");
706 }
707 }
708
709 static void
710 vlog_unixctl_close(struct unixctl_conn *conn, int argc OVS_UNUSED,
711 const char *argv[] OVS_UNUSED, void *aux OVS_UNUSED)
712 {
713 ovs_mutex_lock(&log_file_mutex);
714 if (log_fd >= 0) {
715 close(log_fd);
716 log_fd = -1;
717
718 async_append_destroy(log_writer);
719 log_writer = NULL;
720
721 struct vlog_module *mp;
722 LIST_FOR_EACH (mp, list, &vlog_modules) {
723 update_min_level(mp);
724 }
725 }
726 ovs_mutex_unlock(&log_file_mutex);
727
728 unixctl_command_reply(conn, NULL);
729 }
730
731 static void
732 set_all_rate_limits(bool enable)
733 {
734 struct vlog_module *mp;
735
736 ovs_mutex_lock(&log_file_mutex);
737 LIST_FOR_EACH (mp, list, &vlog_modules) {
738 mp->honor_rate_limits = enable;
739 }
740 ovs_mutex_unlock(&log_file_mutex);
741 }
742
743 static void
744 set_rate_limits(struct unixctl_conn *conn, int argc,
745 const char *argv[], bool enable)
746 {
747 if (argc > 1) {
748 int i;
749
750 for (i = 1; i < argc; i++) {
751 if (!strcasecmp(argv[i], "ANY")) {
752 set_all_rate_limits(enable);
753 } else {
754 struct vlog_module *module = vlog_module_from_name(argv[i]);
755 if (!module) {
756 unixctl_command_reply_error(conn, "unknown module");
757 return;
758 }
759 module->honor_rate_limits = enable;
760 }
761 }
762 } else {
763 set_all_rate_limits(enable);
764 }
765 unixctl_command_reply(conn, NULL);
766 }
767
768 static void
769 vlog_enable_rate_limit(struct unixctl_conn *conn, int argc,
770 const char *argv[], void *aux OVS_UNUSED)
771 {
772 set_rate_limits(conn, argc, argv, true);
773 }
774
775 static void
776 vlog_disable_rate_limit(struct unixctl_conn *conn, int argc,
777 const char *argv[], void *aux OVS_UNUSED)
778 {
779 set_rate_limits(conn, argc, argv, false);
780 }
781
782 /* Initializes the logging subsystem and registers its unixctl server
783 * commands. */
784 void
785 vlog_init(void)
786 {
787 static struct ovsthread_once once = OVSTHREAD_ONCE_INITIALIZER;
788
789 if (ovsthread_once_start(&once)) {
790 long long int now;
791 int facility;
792 bool print_syslog_target_deprecation;
793
794 /* Do initialization work that needs to be done before any logging
795 * occurs. We want to keep this really minimal because any attempt to
796 * log anything before calling ovsthread_once_done() will deadlock. */
797 atomic_read_explicit(&log_facility, &facility, memory_order_relaxed);
798 if (!syslogger) {
799 char *env = getenv("OVS_SYSLOG_METHOD");
800 if (env && env[0]) {
801 vlog_set_syslog_method(env);
802 } else {
803 syslogger = syslog_libc_create();
804 }
805 }
806 syslogger->class->openlog(syslogger, facility ? facility : LOG_DAEMON);
807 ovsthread_once_done(&once);
808
809 /* Now do anything that we want to happen only once but doesn't have to
810 * finish before we start logging. */
811
812 now = time_wall_msec();
813 if (now < 0) {
814 char *s = xastrftime_msec("%a, %d %b %Y %H:%M:%S", now, true);
815 VLOG_ERR("current time is negative: %s (%lld)", s, now);
816 free(s);
817 }
818
819 unixctl_command_register(
820 "vlog/set", "{spec | PATTERN:destination:pattern}",
821 0, INT_MAX, vlog_unixctl_set, NULL);
822 unixctl_command_register("vlog/list", "", 0, 0, vlog_unixctl_list,
823 NULL);
824 unixctl_command_register("vlog/list-pattern", "", 0, 0,
825 vlog_unixctl_list_pattern, NULL);
826 unixctl_command_register("vlog/enable-rate-limit", "[module]...",
827 0, INT_MAX, vlog_enable_rate_limit, NULL);
828 unixctl_command_register("vlog/disable-rate-limit", "[module]...",
829 0, INT_MAX, vlog_disable_rate_limit, NULL);
830 unixctl_command_register("vlog/reopen", "", 0, 0,
831 vlog_unixctl_reopen, NULL);
832 unixctl_command_register("vlog/close", "", 0, 0,
833 vlog_unixctl_close, NULL);
834
835 ovs_rwlock_rdlock(&pattern_rwlock);
836 print_syslog_target_deprecation = syslog_fd >= 0;
837 ovs_rwlock_unlock(&pattern_rwlock);
838
839 if (print_syslog_target_deprecation) {
840 VLOG_WARN("--syslog-target flag is deprecated, use "
841 "--syslog-method instead");
842 }
843 }
844 }
845
846 /* Enables VLF_FILE log output to be written asynchronously to disk.
847 * Asynchronous file writes avoid blocking the process in the case of a busy
848 * disk, but on the other hand they are less robust: there is a chance that the
849 * write will not make it to the log file if the process crashes soon after the
850 * log call. */
851 void
852 vlog_enable_async(void)
853 {
854 ovs_mutex_lock(&log_file_mutex);
855 log_async = true;
856 if (log_fd >= 0 && !log_writer) {
857 log_writer = async_append_create(log_fd);
858 }
859 ovs_mutex_unlock(&log_file_mutex);
860 }
861
862 void
863 vlog_disable_async(void)
864 {
865 ovs_mutex_lock(&log_file_mutex);
866 log_async = false;
867 async_append_destroy(log_writer);
868 log_writer = NULL;
869 ovs_mutex_unlock(&log_file_mutex);
870 }
871
872 /* Print the current logging level for each module. */
873 char *
874 vlog_get_levels(void)
875 {
876 struct ds s = DS_EMPTY_INITIALIZER;
877 struct vlog_module *mp;
878 struct svec lines = SVEC_EMPTY_INITIALIZER;
879 size_t i;
880
881 ds_put_format(&s, " console syslog file\n");
882 ds_put_format(&s, " ------- ------ ------\n");
883
884 ovs_mutex_lock(&log_file_mutex);
885 LIST_FOR_EACH (mp, list, &vlog_modules) {
886 struct ds line;
887
888 ds_init(&line);
889 ds_put_format(&line, "%-16s %4s %4s %4s",
890 vlog_get_module_name(mp),
891 vlog_get_level_name(vlog_get_level(mp, VLF_CONSOLE)),
892 vlog_get_level_name(vlog_get_level(mp, VLF_SYSLOG)),
893 vlog_get_level_name(vlog_get_level(mp, VLF_FILE)));
894 if (!mp->honor_rate_limits) {
895 ds_put_cstr(&line, " (rate limiting disabled)");
896 }
897 ds_put_char(&line, '\n');
898
899 svec_add_nocopy(&lines, ds_steal_cstr(&line));
900 }
901 ovs_mutex_unlock(&log_file_mutex);
902
903 svec_sort(&lines);
904
905 char *line;
906 SVEC_FOR_EACH (i, line, &lines) {
907 ds_put_cstr(&s, line);
908 }
909 svec_destroy(&lines);
910
911 return ds_cstr(&s);
912 }
913
914 /* Returns as a string current logging patterns for each destination.
915 * This string must be released by caller. */
916 char *
917 vlog_get_patterns(void)
918 {
919 struct ds ds = DS_EMPTY_INITIALIZER;
920 enum vlog_destination destination;
921
922 ovs_rwlock_rdlock(&pattern_rwlock);
923 ds_put_format(&ds, " prefix format\n");
924 ds_put_format(&ds, " ------ ------\n");
925
926 for (destination = 0; destination < VLF_N_DESTINATIONS; destination++) {
927 struct destination *f = &destinations[destination];
928 const char *prefix = "none";
929
930 if (destination == VLF_SYSLOG && syslogger) {
931 prefix = syslog_get_prefix(syslogger);
932 }
933 ds_put_format(&ds, "%-7s %-32s %s\n", f->name, prefix, f->pattern);
934 }
935 ovs_rwlock_unlock(&pattern_rwlock);
936
937 return ds_cstr(&ds);
938 }
939
940 /* Returns true if a log message emitted for the given 'module' and 'level'
941 * would cause some log output, false if that module and level are completely
942 * disabled. */
943 bool
944 vlog_is_enabled(const struct vlog_module *module, enum vlog_level level)
945 {
946 return module->min_level >= level;
947 }
948
949 static const char *
950 fetch_braces(const char *p, const char *def, char *out, size_t out_size)
951 {
952 if (*p == '{') {
953 size_t n = strcspn(p + 1, "}");
954 size_t n_copy = MIN(n, out_size - 1);
955 memcpy(out, p + 1, n_copy);
956 out[n_copy] = '\0';
957 p += n + 2;
958 } else {
959 ovs_strlcpy(out, def, out_size);
960 }
961 return p;
962 }
963
964 static void
965 format_log_message(const struct vlog_module *module, enum vlog_level level,
966 const char *pattern, const char *message,
967 va_list args_, struct ds *s)
968 {
969 char tmp[128];
970 va_list args;
971 const char *p;
972 int facility;
973
974 ds_clear(s);
975 for (p = pattern; *p != '\0'; ) {
976 const char *subprogram_name;
977 enum { LEFT, RIGHT } justify = RIGHT;
978 int pad = ' ';
979 size_t length, field, used;
980
981 if (*p != '%') {
982 ds_put_char(s, *p++);
983 continue;
984 }
985
986 p++;
987 if (*p == '-') {
988 justify = LEFT;
989 p++;
990 }
991 if (*p == '0') {
992 pad = '0';
993 p++;
994 }
995 field = 0;
996 while (isdigit((unsigned char)*p)) {
997 field = (field * 10) + (*p - '0');
998 p++;
999 }
1000
1001 length = s->length;
1002 switch (*p++) {
1003 case 'A':
1004 ds_put_cstr(s, program_name);
1005 break;
1006 case 'B':
1007 atomic_read_explicit(&log_facility, &facility,
1008 memory_order_relaxed);
1009 facility = facility ? facility : LOG_LOCAL0;
1010 ds_put_format(s, "%d", facility + syslog_levels[level]);
1011 break;
1012 case 'c':
1013 p = fetch_braces(p, "", tmp, sizeof tmp);
1014 ds_put_cstr(s, vlog_get_module_name(module));
1015 break;
1016 case 'd':
1017 p = fetch_braces(p, "%Y-%m-%d %H:%M:%S.###", tmp, sizeof tmp);
1018 ds_put_strftime_msec(s, tmp, time_wall_msec(), false);
1019 break;
1020 case 'D':
1021 p = fetch_braces(p, "%Y-%m-%d %H:%M:%S.###", tmp, sizeof tmp);
1022 ds_put_strftime_msec(s, tmp, time_wall_msec(), true);
1023 break;
1024 case 'E':
1025 gethostname(tmp, sizeof tmp);
1026 tmp[sizeof tmp - 1] = '\0';
1027 ds_put_cstr(s, tmp);
1028 break;
1029 case 'm':
1030 /* Format user-supplied log message and trim trailing new-lines. */
1031 length = s->length;
1032 va_copy(args, args_);
1033 ds_put_format_valist(s, message, args);
1034 va_end(args);
1035 while (s->length > length && s->string[s->length - 1] == '\n') {
1036 s->length--;
1037 }
1038 break;
1039 case 'N':
1040 ds_put_format(s, "%u", *msg_num_get_unsafe());
1041 break;
1042 case 'n':
1043 ds_put_char(s, '\n');
1044 break;
1045 case 'p':
1046 ds_put_cstr(s, vlog_get_level_name(level));
1047 break;
1048 case 'P':
1049 ds_put_format(s, "%ld", (long int) getpid());
1050 break;
1051 case 'r':
1052 ds_put_format(s, "%lld", time_msec() - time_boot_msec());
1053 break;
1054 case 't':
1055 subprogram_name = get_subprogram_name();
1056 ds_put_cstr(s, subprogram_name[0] ? subprogram_name : "main");
1057 break;
1058 case 'T':
1059 subprogram_name = get_subprogram_name();
1060 if (subprogram_name[0]) {
1061 ds_put_format(s, "(%s)", subprogram_name);
1062 }
1063 break;
1064 default:
1065 ds_put_char(s, p[-1]);
1066 break;
1067 }
1068 used = s->length - length;
1069 if (used < field) {
1070 size_t n_pad = field - used;
1071 if (justify == RIGHT) {
1072 ds_put_uninit(s, n_pad);
1073 memmove(&s->string[length + n_pad], &s->string[length], used);
1074 memset(&s->string[length], pad, n_pad);
1075 } else {
1076 ds_put_char_multiple(s, pad, n_pad);
1077 }
1078 }
1079 }
1080 }
1081
1082 /* Exports the given 'syslog_message' to the configured udp syslog sink. */
1083 static void
1084 send_to_syslog_fd(const char *s, size_t length)
1085 OVS_REQ_RDLOCK(pattern_rwlock)
1086 {
1087 static size_t max_length = SIZE_MAX;
1088 size_t send_len = MIN(length, max_length);
1089
1090 while (write(syslog_fd, s, send_len) < 0 && errno == EMSGSIZE) {
1091 send_len -= send_len / 20;
1092 max_length = send_len;
1093 }
1094 }
1095
1096 /* Writes 'message' to the log at the given 'level' and as coming from the
1097 * given 'module'.
1098 *
1099 * Guaranteed to preserve errno. */
1100 void
1101 vlog_valist(const struct vlog_module *module, enum vlog_level level,
1102 const char *message, va_list args)
1103 {
1104 bool log_to_console = module->levels[VLF_CONSOLE] >= level;
1105 bool log_to_syslog = module->levels[VLF_SYSLOG] >= level;
1106 bool log_to_file = module->levels[VLF_FILE] >= level;
1107
1108 if (!(log_to_console || log_to_syslog || log_to_file)) {
1109 /* fast path - all logging levels specify no logging, no
1110 * need to hog the log mutex
1111 */
1112 return;
1113 }
1114
1115 ovs_mutex_lock(&log_file_mutex);
1116 log_to_file &= (log_fd >= 0);
1117 ovs_mutex_unlock(&log_file_mutex);
1118 if (log_to_console || log_to_syslog || log_to_file) {
1119 int save_errno = errno;
1120 struct ds s;
1121
1122 vlog_init();
1123
1124 ds_init(&s);
1125 ds_reserve(&s, 1024);
1126 ++*msg_num_get();
1127
1128 ovs_rwlock_rdlock(&pattern_rwlock);
1129 if (log_to_console) {
1130 format_log_message(module, level,
1131 destinations[VLF_CONSOLE].pattern, message,
1132 args, &s);
1133 ds_put_char(&s, '\n');
1134 fputs(ds_cstr(&s), stderr);
1135 }
1136
1137 if (log_to_syslog) {
1138 int syslog_level = syslog_levels[level];
1139 char *save_ptr = NULL;
1140 char *line;
1141 int facility;
1142
1143 format_log_message(module, level, destinations[VLF_SYSLOG].pattern,
1144 message, args, &s);
1145 for (line = strtok_r(s.string, "\n", &save_ptr); line;
1146 line = strtok_r(NULL, "\n", &save_ptr)) {
1147 atomic_read_explicit(&log_facility, &facility,
1148 memory_order_relaxed);
1149 syslogger->class->syslog(syslogger, syslog_level|facility, line);
1150 }
1151
1152 if (syslog_fd >= 0) {
1153 format_log_message(module, level,
1154 "<%B>1 %D{%Y-%m-%dT%H:%M:%S.###Z} "
1155 "%E %A %P %c - \xef\xbb\xbf%m",
1156 message, args, &s);
1157 send_to_syslog_fd(ds_cstr(&s), s.length);
1158 }
1159 }
1160
1161 if (log_to_file) {
1162 format_log_message(module, level, destinations[VLF_FILE].pattern,
1163 message, args, &s);
1164 ds_put_char(&s, '\n');
1165
1166 ovs_mutex_lock(&log_file_mutex);
1167 if (log_fd >= 0) {
1168 if (log_writer) {
1169 async_append_write(log_writer, s.string, s.length);
1170 if (level == VLL_EMER) {
1171 async_append_flush(log_writer);
1172 }
1173 } else {
1174 ignore(write(log_fd, s.string, s.length));
1175 }
1176 }
1177 ovs_mutex_unlock(&log_file_mutex);
1178 }
1179 ovs_rwlock_unlock(&pattern_rwlock);
1180
1181 ds_destroy(&s);
1182 errno = save_errno;
1183 }
1184 }
1185
1186 void
1187 vlog(const struct vlog_module *module, enum vlog_level level,
1188 const char *message, ...)
1189 {
1190 va_list args;
1191
1192 va_start(args, message);
1193 vlog_valist(module, level, message, args);
1194 va_end(args);
1195 }
1196
1197 /* Logs 'message' to 'module' at maximum verbosity, then exits with a failure
1198 * exit code. Always writes the message to stderr, even if the console
1199 * destination is disabled.
1200 *
1201 * Choose this function instead of vlog_abort_valist() if the daemon monitoring
1202 * facility shouldn't automatically restart the current daemon. */
1203 void
1204 vlog_fatal_valist(const struct vlog_module *module_,
1205 const char *message, va_list args)
1206 {
1207 struct vlog_module *module = CONST_CAST(struct vlog_module *, module_);
1208
1209 /* Don't log this message to the console to avoid redundancy with the
1210 * message written by the later ovs_fatal_valist(). */
1211 module->levels[VLF_CONSOLE] = VLL_OFF;
1212
1213 vlog_valist(module, VLL_EMER, message, args);
1214 ovs_fatal_valist(0, message, args);
1215 }
1216
1217 /* Logs 'message' to 'module' at maximum verbosity, then exits with a failure
1218 * exit code. Always writes the message to stderr, even if the console
1219 * destination is disabled.
1220 *
1221 * Choose this function instead of vlog_abort() if the daemon monitoring
1222 * facility shouldn't automatically restart the current daemon. */
1223 void
1224 vlog_fatal(const struct vlog_module *module, const char *message, ...)
1225 {
1226 va_list args;
1227
1228 va_start(args, message);
1229 vlog_fatal_valist(module, message, args);
1230 va_end(args);
1231 }
1232
1233 /* Logs 'message' to 'module' at maximum verbosity, then calls abort(). Always
1234 * writes the message to stderr, even if the console destination is disabled.
1235 *
1236 * Choose this function instead of vlog_fatal_valist() if the daemon monitoring
1237 * facility should automatically restart the current daemon. */
1238 void
1239 vlog_abort_valist(const struct vlog_module *module_,
1240 const char *message, va_list args)
1241 {
1242 struct vlog_module *module = (struct vlog_module *) module_;
1243
1244 /* Don't log this message to the console to avoid redundancy with the
1245 * message written by the later ovs_abort_valist(). */
1246 module->levels[VLF_CONSOLE] = VLL_OFF;
1247
1248 vlog_valist(module, VLL_EMER, message, args);
1249 ovs_abort_valist(0, message, args);
1250 }
1251
1252 /* Logs 'message' to 'module' at maximum verbosity, then calls abort(). Always
1253 * writes the message to stderr, even if the console destination is disabled.
1254 *
1255 * Choose this function instead of vlog_fatal() if the daemon monitoring
1256 * facility should automatically restart the current daemon. */
1257 void
1258 vlog_abort(const struct vlog_module *module, const char *message, ...)
1259 {
1260 va_list args;
1261
1262 va_start(args, message);
1263 vlog_abort_valist(module, message, args);
1264 va_end(args);
1265 }
1266
1267 bool
1268 vlog_should_drop(const struct vlog_module *module, enum vlog_level level,
1269 struct vlog_rate_limit *rl)
1270 {
1271 if (!module->honor_rate_limits) {
1272 return false;
1273 }
1274
1275 if (!vlog_is_enabled(module, level)) {
1276 return true;
1277 }
1278
1279 ovs_mutex_lock(&rl->mutex);
1280 if (!token_bucket_withdraw(&rl->token_bucket, VLOG_MSG_TOKENS)) {
1281 time_t now = time_now();
1282 if (!rl->n_dropped) {
1283 rl->first_dropped = now;
1284 }
1285 rl->last_dropped = now;
1286 rl->n_dropped++;
1287 ovs_mutex_unlock(&rl->mutex);
1288 return true;
1289 }
1290
1291 if (!rl->n_dropped) {
1292 ovs_mutex_unlock(&rl->mutex);
1293 } else {
1294 time_t now = time_now();
1295 unsigned int n_dropped = rl->n_dropped;
1296 unsigned int first_dropped_elapsed = now - rl->first_dropped;
1297 unsigned int last_dropped_elapsed = now - rl->last_dropped;
1298 rl->n_dropped = 0;
1299 ovs_mutex_unlock(&rl->mutex);
1300
1301 vlog(module, level,
1302 "Dropped %u log messages in last %u seconds (most recently, "
1303 "%u seconds ago) due to excessive rate",
1304 n_dropped, first_dropped_elapsed, last_dropped_elapsed);
1305 }
1306
1307 return false;
1308 }
1309
1310 void
1311 vlog_rate_limit(const struct vlog_module *module, enum vlog_level level,
1312 struct vlog_rate_limit *rl, const char *message, ...)
1313 {
1314 if (!vlog_should_drop(module, level, rl)) {
1315 va_list args;
1316
1317 va_start(args, message);
1318 vlog_valist(module, level, message, args);
1319 va_end(args);
1320 }
1321 }
1322
1323 void
1324 vlog_usage(void)
1325 {
1326 printf("\n\
1327 Logging options:\n\
1328 -vSPEC, --verbose=SPEC set logging levels\n\
1329 -v, --verbose set maximum verbosity level\n\
1330 --log-file[=FILE] enable logging to specified FILE\n\
1331 (default: %s/%s.log)\n\
1332 --syslog-method=(libc|unix:file|udp:ip:port)\n\
1333 specify how to send messages to syslog daemon\n\
1334 --syslog-target=HOST:PORT also send syslog msgs to HOST:PORT via UDP\n",
1335 ovs_logdir(), program_name);
1336 }