~ubuntu-branches/ubuntu/wily/openvswitch/wily

« back to all changes in this revision

Viewing changes to lib/vlog.c

  • Committer: Package Import Robot
  • Author(s): James Page
  • Date: 2015-08-10 11:35:15 UTC
  • mfrom: (1.1.30)
  • Revision ID: package-import@ubuntu.com-20150810113515-575vj06oq29emxsn
Tags: 2.4.0~git20150810.97bab95-0ubuntu1
* New upstream snapshot from 2.4 branch:
  - d/*: Align any relevant packaging changes with upstream.
* d/*: wrap-and-sort.
* d/openvswitch-{common,vswitch}.install: Correct install location for
  bash completion files.
* d/tests/openflow.py: Explicitly use ovs-testcontroller as provided
  by 2.4.0 release.

Show diffs side-by-side

added added

removed removed

Lines of Context:
15
15
 */
16
16
 
17
17
#include <config.h>
18
 
#include "vlog.h"
 
18
#include "openvswitch/vlog.h"
19
19
#include <assert.h>
20
20
#include <ctype.h>
21
21
#include <errno.h>
37
37
#include "sat-math.h"
38
38
#include "socket-util.h"
39
39
#include "svec.h"
 
40
#include "syslog-direct.h"
 
41
#include "syslog-libc.h"
 
42
#include "syslog-provider.h"
40
43
#include "timeval.h"
41
44
#include "unixctl.h"
42
45
#include "util.h"
75
78
BUILD_ASSERT_DECL(LOG_LOCAL0 == (16 << 3));
76
79
 
77
80
/* The log modules. */
78
 
struct list vlog_modules = LIST_INITIALIZER(&vlog_modules);
 
81
struct ovs_list vlog_modules = OVS_LIST_INITIALIZER(&vlog_modules);
79
82
 
80
 
/* Protects the 'pattern' in all "struct facility"s, so that a race between
 
83
/* Protects the 'pattern' in all "struct destination"s, so that a race between
81
84
 * changing and reading the pattern does not cause an access to freed
82
85
 * memory. */
83
86
static struct ovs_rwlock pattern_rwlock = OVS_RWLOCK_INITIALIZER;
84
87
 
85
 
/* Information about each facility. */
86
 
struct facility {
 
88
/* Information about each destination. */
 
89
struct destination {
87
90
    const char *name;           /* Name. */
88
91
    char *pattern OVS_GUARDED_BY(pattern_rwlock); /* Current pattern. */
89
92
    bool default_pattern;       /* Whether current pattern is the default. */
90
93
};
91
 
static struct facility facilities[VLF_N_FACILITIES] = {
92
 
#define VLOG_FACILITY(NAME, PATTERN) {#NAME, PATTERN, true},
93
 
    VLOG_FACILITIES
94
 
#undef VLOG_FACILITY
 
94
static struct destination destinations[VLF_N_DESTINATIONS] = {
 
95
#define VLOG_DESTINATION(NAME, PATTERN) {#NAME, PATTERN, true},
 
96
    VLOG_DESTINATIONS
 
97
#undef VLOG_DESTINATION
95
98
};
96
99
 
97
100
/* Sequence number for the message currently being composed. */
106
109
static int log_fd OVS_GUARDED_BY(log_file_mutex) = -1;
107
110
static struct async_append *log_writer OVS_GUARDED_BY(log_file_mutex);
108
111
static bool log_async OVS_GUARDED_BY(log_file_mutex);
 
112
static struct syslogger *syslogger = NULL;
109
113
 
110
114
/* Syslog export configuration. */
111
115
static int syslog_fd OVS_GUARDED_BY(pattern_rwlock) = -1;
112
116
 
 
117
/* Log facility configuration. */
 
118
static atomic_int log_facility = ATOMIC_VAR_INIT(0);
 
119
 
 
120
/* Facility name and its value. */
 
121
struct vlog_facility {
 
122
    char *name;           /* Name. */
 
123
    unsigned int value;   /* Facility associated with 'name'. */
 
124
};
 
125
static struct vlog_facility vlog_facilities[] = {
 
126
    {"kern", LOG_KERN},
 
127
    {"user", LOG_USER},
 
128
    {"mail", LOG_MAIL},
 
129
    {"daemon", LOG_DAEMON},
 
130
    {"auth", LOG_AUTH},
 
131
    {"syslog", LOG_SYSLOG},
 
132
    {"lpr", LOG_LPR},
 
133
    {"news", LOG_NEWS},
 
134
    {"uucp", LOG_UUCP},
 
135
    {"clock", LOG_CRON},
 
136
    {"ftp", LOG_FTP},
 
137
    {"ntp", 12<<3},
 
138
    {"audit", 13<<3},
 
139
    {"alert", 14<<3},
 
140
    {"clock2", 15<<3},
 
141
    {"local0", LOG_LOCAL0},
 
142
    {"local1", LOG_LOCAL1},
 
143
    {"local2", LOG_LOCAL2},
 
144
    {"local3", LOG_LOCAL3},
 
145
    {"local4", LOG_LOCAL4},
 
146
    {"local5", LOG_LOCAL5},
 
147
    {"local6", LOG_LOCAL6},
 
148
    {"local7", LOG_LOCAL7}
 
149
};
 
150
static bool vlog_facility_exists(const char* facility, int *value);
 
151
 
113
152
static void format_log_message(const struct vlog_module *, enum vlog_level,
114
153
                               const char *pattern,
115
154
                               const char *message, va_list, struct ds *)
116
 
    PRINTF_FORMAT(4, 0);
 
155
    OVS_PRINTF_FORMAT(4, 0);
117
156
 
118
157
/* Searches the 'n_names' in 'names'.  Returns the index of a match for
119
158
 * 'target', or 'n_names' if no name matches. */
147
186
    return search_name_array(name, level_names, ARRAY_SIZE(level_names));
148
187
}
149
188
 
150
 
/* Returns the name for logging facility 'facility'. */
 
189
/* Returns the name for logging destination 'destination'. */
151
190
const char *
152
 
vlog_get_facility_name(enum vlog_facility facility)
 
191
vlog_get_destination_name(enum vlog_destination destination)
153
192
{
154
 
    assert(facility < VLF_N_FACILITIES);
155
 
    return facilities[facility].name;
 
193
    assert(destination < VLF_N_DESTINATIONS);
 
194
    return destinations[destination].name;
156
195
}
157
196
 
158
 
/* Returns the logging facility named 'name', or VLF_N_FACILITIES if 'name' is
159
 
 * not the name of a logging facility. */
160
 
enum vlog_facility
161
 
vlog_get_facility_val(const char *name)
 
197
/* Returns the logging destination named 'name', or VLF_N_DESTINATIONS if
 
198
 * 'name' is not the name of a logging destination. */
 
199
enum vlog_destination
 
200
vlog_get_destination_val(const char *name)
162
201
{
163
202
    size_t i;
164
203
 
165
 
    for (i = 0; i < VLF_N_FACILITIES; i++) {
166
 
        if (!strcasecmp(facilities[i].name, name)) {
 
204
    for (i = 0; i < VLF_N_DESTINATIONS; i++) {
 
205
        if (!strcasecmp(destinations[i].name, name)) {
167
206
            break;
168
207
        }
169
208
    }
170
209
    return i;
171
210
}
172
211
 
 
212
void vlog_insert_module(struct ovs_list *vlog)
 
213
{
 
214
    list_insert(&vlog_modules, vlog);
 
215
}
 
216
 
173
217
/* Returns the name for logging module 'module'. */
174
218
const char *
175
219
vlog_get_module_name(const struct vlog_module *module)
193
237
    return NULL;
194
238
}
195
239
 
196
 
/* Returns the current logging level for the given 'module' and 'facility'. */
 
240
/* Returns the current logging level for the given 'module' and
 
241
 * 'destination'. */
197
242
enum vlog_level
198
 
vlog_get_level(const struct vlog_module *module, enum vlog_facility facility)
 
243
vlog_get_level(const struct vlog_module *module,
 
244
               enum vlog_destination destination)
199
245
{
200
 
    assert(facility < VLF_N_FACILITIES);
201
 
    return module->levels[facility];
 
246
    assert(destination < VLF_N_DESTINATIONS);
 
247
    return module->levels[destination];
202
248
}
203
249
 
204
250
static void
205
251
update_min_level(struct vlog_module *module) OVS_REQUIRES(&log_file_mutex)
206
252
{
207
 
    enum vlog_facility facility;
 
253
    enum vlog_destination destination;
208
254
 
209
255
    module->min_level = VLL_OFF;
210
 
    for (facility = 0; facility < VLF_N_FACILITIES; facility++) {
211
 
        if (log_fd >= 0 || facility != VLF_FILE) {
212
 
            enum vlog_level level = module->levels[facility];
 
256
    for (destination = 0; destination < VLF_N_DESTINATIONS; destination++) {
 
257
        if (log_fd >= 0 || destination != VLF_FILE) {
 
258
            enum vlog_level level = module->levels[destination];
213
259
            if (level > module->min_level) {
214
260
                module->min_level = level;
215
261
            }
218
264
}
219
265
 
220
266
static void
221
 
set_facility_level(enum vlog_facility facility, struct vlog_module *module,
222
 
                   enum vlog_level level)
 
267
set_destination_level(enum vlog_destination destination,
 
268
                      struct vlog_module *module, enum vlog_level level)
223
269
{
224
 
    assert(facility >= 0 && facility < VLF_N_FACILITIES);
 
270
    assert(destination >= 0 && destination < VLF_N_DESTINATIONS);
225
271
    assert(level < VLL_N_LEVELS);
226
272
 
227
273
    ovs_mutex_lock(&log_file_mutex);
228
274
    if (!module) {
229
275
        struct vlog_module *mp;
230
276
        LIST_FOR_EACH (mp, list, &vlog_modules) {
231
 
            mp->levels[facility] = level;
 
277
            mp->levels[destination] = level;
232
278
            update_min_level(mp);
233
279
        }
234
280
    } else {
235
 
        module->levels[facility] = level;
 
281
        module->levels[destination] = level;
236
282
        update_min_level(module);
237
283
    }
238
284
    ovs_mutex_unlock(&log_file_mutex);
239
285
}
240
286
 
241
 
/* Sets the logging level for the given 'module' and 'facility' to 'level'.  A
242
 
 * null 'module' or a 'facility' of VLF_ANY_FACILITY is treated as a wildcard
243
 
 * across all modules or facilities, respectively. */
 
287
/* Sets the logging level for the given 'module' and 'destination' to 'level'.
 
288
 * A null 'module' or a 'destination' of VLF_ANY_DESTINATION is treated as a
 
289
 * wildcard across all modules or destinations, respectively. */
244
290
void
245
 
vlog_set_levels(struct vlog_module *module, enum vlog_facility facility,
 
291
vlog_set_levels(struct vlog_module *module, enum vlog_destination destination,
246
292
                enum vlog_level level)
247
293
{
248
 
    assert(facility < VLF_N_FACILITIES || facility == VLF_ANY_FACILITY);
249
 
    if (facility == VLF_ANY_FACILITY) {
250
 
        for (facility = 0; facility < VLF_N_FACILITIES; facility++) {
251
 
            set_facility_level(facility, module, level);
 
294
    assert(destination < VLF_N_DESTINATIONS ||
 
295
           destination == VLF_ANY_DESTINATION);
 
296
    if (destination == VLF_ANY_DESTINATION) {
 
297
        for (destination = 0; destination < VLF_N_DESTINATIONS;
 
298
             destination++) {
 
299
            set_destination_level(destination, module, level);
252
300
        }
253
301
    } else {
254
 
        set_facility_level(facility, module, level);
 
302
        set_destination_level(destination, module, level);
255
303
    }
256
304
}
257
305
 
258
306
static void
259
 
do_set_pattern(enum vlog_facility facility, const char *pattern)
 
307
do_set_pattern(enum vlog_destination destination, const char *pattern)
260
308
{
261
 
    struct facility *f = &facilities[facility];
 
309
    struct destination *f = &destinations[destination];
262
310
 
263
311
    ovs_rwlock_wrlock(&pattern_rwlock);
264
312
    if (!f->default_pattern) {
270
318
    ovs_rwlock_unlock(&pattern_rwlock);
271
319
}
272
320
 
273
 
/* Sets the pattern for the given 'facility' to 'pattern'. */
 
321
/* Sets the pattern for the given 'destination' to 'pattern'. */
274
322
void
275
 
vlog_set_pattern(enum vlog_facility facility, const char *pattern)
 
323
vlog_set_pattern(enum vlog_destination destination, const char *pattern)
276
324
{
277
 
    assert(facility < VLF_N_FACILITIES || facility == VLF_ANY_FACILITY);
278
 
    if (facility == VLF_ANY_FACILITY) {
279
 
        for (facility = 0; facility < VLF_N_FACILITIES; facility++) {
280
 
            do_set_pattern(facility, pattern);
 
325
    assert(destination < VLF_N_DESTINATIONS ||
 
326
           destination == VLF_ANY_DESTINATION);
 
327
    if (destination == VLF_ANY_DESTINATION) {
 
328
        for (destination = 0; destination < VLF_N_DESTINATIONS;
 
329
             destination++) {
 
330
            do_set_pattern(destination, pattern);
281
331
        }
282
332
    } else {
283
 
        do_set_pattern(facility, pattern);
 
333
        do_set_pattern(destination, pattern);
284
334
    }
285
335
}
286
336
 
392
442
 
393
443
    word = strtok_r(s, " ,:\t", &save_ptr);
394
444
    if (word && !strcasecmp(word, "PATTERN")) {
395
 
        enum vlog_facility facility;
 
445
        enum vlog_destination destination;
396
446
 
397
447
        word = strtok_r(NULL, " ,:\t", &save_ptr);
398
448
        if (!word) {
399
 
            msg = xstrdup("missing facility");
400
 
            goto exit;
401
 
        }
402
 
 
403
 
        facility = (!strcasecmp(word, "ANY")
404
 
                    ? VLF_ANY_FACILITY
405
 
                    : vlog_get_facility_val(word));
406
 
        if (facility == VLF_N_FACILITIES) {
407
 
            msg = xasprintf("unknown facility \"%s\"", word);
408
 
            goto exit;
409
 
        }
410
 
        vlog_set_pattern(facility, save_ptr);
 
449
            msg = xstrdup("missing destination");
 
450
            goto exit;
 
451
        }
 
452
 
 
453
        destination = (!strcasecmp(word, "ANY")
 
454
                       ? VLF_ANY_DESTINATION
 
455
                       : vlog_get_destination_val(word));
 
456
        if (destination == VLF_N_DESTINATIONS) {
 
457
            msg = xasprintf("unknown destination \"%s\"", word);
 
458
            goto exit;
 
459
        }
 
460
        vlog_set_pattern(destination, save_ptr);
 
461
    } else if (word && !strcasecmp(word, "FACILITY")) {
 
462
        int value;
 
463
 
 
464
        if (!vlog_facility_exists(save_ptr, &value)) {
 
465
            msg = xstrdup("invalid facility");
 
466
            goto exit;
 
467
        }
 
468
        atomic_store_explicit(&log_facility, value, memory_order_relaxed);
411
469
    } else {
412
470
        struct vlog_module *module = NULL;
413
471
        enum vlog_level level = VLL_N_LEVELS;
414
 
        enum vlog_facility facility = VLF_N_FACILITIES;
 
472
        enum vlog_destination destination = VLF_N_DESTINATIONS;
415
473
 
416
474
        for (; word != NULL; word = strtok_r(NULL, " ,:\t", &save_ptr)) {
417
475
            if (!strcasecmp(word, "ANY")) {
418
476
                continue;
419
 
            } else if (vlog_get_facility_val(word) != VLF_N_FACILITIES) {
420
 
                if (facility != VLF_N_FACILITIES) {
421
 
                    msg = xstrdup("cannot specify multiple facilities");
 
477
            } else if (vlog_get_destination_val(word) != VLF_N_DESTINATIONS) {
 
478
                if (destination != VLF_N_DESTINATIONS) {
 
479
                    msg = xstrdup("cannot specify multiple destinations");
422
480
                    goto exit;
423
481
                }
424
 
                facility = vlog_get_facility_val(word);
 
482
                destination = vlog_get_destination_val(word);
425
483
            } else if (vlog_get_level_val(word) != VLL_N_LEVELS) {
426
484
                if (level != VLL_N_LEVELS) {
427
485
                    msg = xstrdup("cannot specify multiple levels");
435
493
                }
436
494
                module = vlog_module_from_name(word);
437
495
            } else {
438
 
                msg = xasprintf("no facility, level, or module \"%s\"", word);
 
496
                msg = xasprintf("no destination, level, or module \"%s\"",
 
497
                                word);
439
498
                goto exit;
440
499
            }
441
500
        }
442
501
 
443
 
        if (facility == VLF_N_FACILITIES) {
444
 
            facility = VLF_ANY_FACILITY;
 
502
        if (destination == VLF_N_DESTINATIONS) {
 
503
            destination = VLF_ANY_DESTINATION;
445
504
        }
446
505
        if (level == VLL_N_LEVELS) {
447
506
            level = VLL_DBG;
448
507
        }
449
 
        vlog_set_levels(module, facility, level);
 
508
        vlog_set_levels(module, destination, level);
450
509
    }
451
510
 
452
511
exit:
475
534
            ovs_fatal(0, "processing \"%s\": %s", arg, msg);
476
535
        }
477
536
    } else {
478
 
        vlog_set_levels(NULL, VLF_ANY_FACILITY, VLL_DBG);
 
537
        vlog_set_levels(NULL, VLF_ANY_DESTINATION, VLL_DBG);
 
538
    }
 
539
}
 
540
 
 
541
void
 
542
vlog_set_syslog_method(const char *method)
 
543
{
 
544
    if (syslogger) {
 
545
        /* Set syslogger only, if one is not already set.  This effectively
 
546
         * means that only the first --syslog-method argument is honored. */
 
547
        return;
 
548
    }
 
549
 
 
550
    if (!strcmp(method, "libc")) {
 
551
        syslogger = syslog_libc_create();
 
552
    } else if (!strncmp(method, "udp:", 4) || !strncmp(method, "unix:", 5)) {
 
553
        syslogger = syslog_direct_create(method);
 
554
    } else {
 
555
        ovs_fatal(0, "unsupported syslog method '%s'", method);
479
556
    }
480
557
}
481
558
 
495
572
    ovs_rwlock_unlock(&pattern_rwlock);
496
573
}
497
574
 
 
575
/* Returns 'false' if 'facility' is not a valid string. If 'facility'
 
576
 * is a valid string, sets 'value' with the integer value of 'facility'
 
577
 * and returns 'true'. */
 
578
static bool
 
579
vlog_facility_exists(const char* facility, int *value)
 
580
{
 
581
    size_t i;
 
582
    for (i = 0; i < ARRAY_SIZE(vlog_facilities); i++) {
 
583
        if (!strcasecmp(vlog_facilities[i].name, facility)) {
 
584
            *value = vlog_facilities[i].value;
 
585
            return true;
 
586
        }
 
587
    }
 
588
    return false;
 
589
}
 
590
 
498
591
static void
499
592
vlog_unixctl_set(struct unixctl_conn *conn, int argc, const char *argv[],
500
593
                 void *aux OVS_UNUSED)
522
615
}
523
616
 
524
617
static void
 
618
vlog_unixctl_list_pattern(struct unixctl_conn *conn, int argc OVS_UNUSED,
 
619
                          const char *argv[] OVS_UNUSED, void *aux OVS_UNUSED)
 
620
{
 
621
    char *msg;
 
622
 
 
623
    msg = vlog_get_patterns();
 
624
    unixctl_command_reply(conn, msg);
 
625
    free(msg);
 
626
}
 
627
 
 
628
static void
525
629
vlog_unixctl_reopen(struct unixctl_conn *conn, int argc OVS_UNUSED,
526
630
                    const char *argv[] OVS_UNUSED, void *aux OVS_UNUSED)
527
631
{
600
704
    static struct ovsthread_once once = OVSTHREAD_ONCE_INITIALIZER;
601
705
 
602
706
    if (ovsthread_once_start(&once)) {
603
 
        static char *program_name_copy;
604
707
        long long int now;
 
708
        int facility;
605
709
 
606
710
        /* Do initialization work that needs to be done before any logging
607
711
         * occurs.  We want to keep this really minimal because any attempt to
608
712
         * log anything before calling ovsthread_once_done() will deadlock. */
609
 
 
610
 
        /* openlog() is allowed to keep the pointer passed in, without making a
611
 
         * copy.  The daemonize code sometimes frees and replaces
612
 
         * 'program_name', so make a private copy just for openlog().  (We keep
613
 
         * a pointer to the private copy to suppress memory leak warnings in
614
 
         * case openlog() does make its own copy.) */
615
 
        program_name_copy = program_name ? xstrdup(program_name) : NULL;
616
 
        openlog(program_name_copy, LOG_NDELAY, LOG_DAEMON);
 
713
        atomic_read_explicit(&log_facility, &facility, memory_order_relaxed);
 
714
        if (!syslogger) {
 
715
            syslogger = syslog_libc_create();
 
716
        }
 
717
        syslogger->class->openlog(syslogger, facility ? facility : LOG_DAEMON);
617
718
        ovsthread_once_done(&once);
618
719
 
619
720
        /* Now do anything that we want to happen only once but doesn't have to
627
728
        }
628
729
 
629
730
        unixctl_command_register(
630
 
            "vlog/set", "{spec | PATTERN:facility:pattern}",
 
731
            "vlog/set", "{spec | PATTERN:destination:pattern}",
631
732
            1, INT_MAX, vlog_unixctl_set, NULL);
632
733
        unixctl_command_register("vlog/list", "", 0, 0, vlog_unixctl_list,
633
734
                                 NULL);
 
735
        unixctl_command_register("vlog/list-pattern", "", 0, 0,
 
736
                                 vlog_unixctl_list_pattern, NULL);
634
737
        unixctl_command_register("vlog/enable-rate-limit", "[module]...",
635
738
                                 0, INT_MAX, vlog_enable_rate_limit, NULL);
636
739
        unixctl_command_register("vlog/disable-rate-limit", "[module]...",
695
798
    return ds_cstr(&s);
696
799
}
697
800
 
 
801
/* Returns as a string current logging patterns for each destination.
 
802
 * This string must be released by caller. */
 
803
char *
 
804
vlog_get_patterns(void)
 
805
{
 
806
    struct ds ds = DS_EMPTY_INITIALIZER;
 
807
    enum vlog_destination destination;
 
808
 
 
809
    ovs_rwlock_rdlock(&pattern_rwlock);
 
810
    ds_put_format(&ds, "         prefix                            format\n");
 
811
    ds_put_format(&ds, "         ------                            ------\n");
 
812
 
 
813
    for (destination = 0; destination < VLF_N_DESTINATIONS; destination++) {
 
814
        struct destination *f = &destinations[destination];;
 
815
        const char *prefix = "none";
 
816
 
 
817
        if (destination == VLF_SYSLOG && syslogger) {
 
818
            prefix = syslog_get_prefix(syslogger);
 
819
        }
 
820
        ds_put_format(&ds, "%-7s  %-32s  %s\n", f->name, prefix, f->pattern);
 
821
    }
 
822
    ovs_rwlock_unlock(&pattern_rwlock);
 
823
 
 
824
    return ds_cstr(&ds);
 
825
}
 
826
 
698
827
/* Returns true if a log message emitted for the given 'module' and 'level'
699
828
 * would cause some log output, false if that module and level are completely
700
829
 * disabled. */
727
856
    char tmp[128];
728
857
    va_list args;
729
858
    const char *p;
 
859
    int facility;
730
860
 
731
861
    ds_clear(s);
732
862
    for (p = pattern; *p != '\0'; ) {
761
891
            ds_put_cstr(s, program_name);
762
892
            break;
763
893
        case 'B':
764
 
            ds_put_format(s, "%d", LOG_LOCAL0 + syslog_levels[level]);
 
894
            atomic_read_explicit(&log_facility, &facility,
 
895
                                 memory_order_relaxed);
 
896
            facility = facility ? facility : LOG_LOCAL0;
 
897
            ds_put_format(s, "%d", facility + syslog_levels[level]);
765
898
            break;
766
899
        case 'c':
767
900
            p = fetch_braces(p, "", tmp, sizeof tmp);
874
1007
 
875
1008
        ovs_rwlock_rdlock(&pattern_rwlock);
876
1009
        if (log_to_console) {
877
 
            format_log_message(module, level, facilities[VLF_CONSOLE].pattern,
878
 
                               message, args, &s);
 
1010
            format_log_message(module, level,
 
1011
                               destinations[VLF_CONSOLE].pattern, message,
 
1012
                               args, &s);
879
1013
            ds_put_char(&s, '\n');
880
1014
            fputs(ds_cstr(&s), stderr);
881
1015
        }
884
1018
            int syslog_level = syslog_levels[level];
885
1019
            char *save_ptr = NULL;
886
1020
            char *line;
 
1021
            int facility;
887
1022
 
888
 
            format_log_message(module, level, facilities[VLF_SYSLOG].pattern,
 
1023
            format_log_message(module, level, destinations[VLF_SYSLOG].pattern,
889
1024
                               message, args, &s);
890
1025
            for (line = strtok_r(s.string, "\n", &save_ptr); line;
891
1026
                 line = strtok_r(NULL, "\n", &save_ptr)) {
892
 
                syslog(syslog_level, "%s", line);
 
1027
                atomic_read_explicit(&log_facility, &facility,
 
1028
                                     memory_order_relaxed);
 
1029
                syslogger->class->syslog(syslogger, syslog_level|facility, line);
893
1030
            }
894
1031
 
895
1032
            if (syslog_fd >= 0) {
902
1039
        }
903
1040
 
904
1041
        if (log_to_file) {
905
 
            format_log_message(module, level, facilities[VLF_FILE].pattern,
 
1042
            format_log_message(module, level, destinations[VLF_FILE].pattern,
906
1043
                               message, args, &s);
907
1044
            ds_put_char(&s, '\n');
908
1045
 
939
1076
 
940
1077
/* Logs 'message' to 'module' at maximum verbosity, then exits with a failure
941
1078
 * exit code.  Always writes the message to stderr, even if the console
942
 
 * facility is disabled.
 
1079
 * destination is disabled.
943
1080
 *
944
1081
 * Choose this function instead of vlog_abort_valist() if the daemon monitoring
945
1082
 * facility shouldn't automatically restart the current daemon.  */
959
1096
 
960
1097
/* Logs 'message' to 'module' at maximum verbosity, then exits with a failure
961
1098
 * exit code.  Always writes the message to stderr, even if the console
962
 
 * facility is disabled.
 
1099
 * destination is disabled.
963
1100
 *
964
1101
 * Choose this function instead of vlog_abort() if the daemon monitoring
965
1102
 * facility shouldn't automatically restart the current daemon.  */
974
1111
}
975
1112
 
976
1113
/* Logs 'message' to 'module' at maximum verbosity, then calls abort().  Always
977
 
 * writes the message to stderr, even if the console facility is disabled.
 
1114
 * writes the message to stderr, even if the console destination is disabled.
978
1115
 *
979
1116
 * Choose this function instead of vlog_fatal_valist() if the daemon monitoring
980
1117
 * facility should automatically restart the current daemon.  */
993
1130
}
994
1131
 
995
1132
/* Logs 'message' to 'module' at maximum verbosity, then calls abort().  Always
996
 
 * writes the message to stderr, even if the console facility is disabled.
 
1133
 * writes the message to stderr, even if the console destination is disabled.
997
1134
 *
998
1135
 * Choose this function instead of vlog_fatal() if the daemon monitoring
999
1136
 * facility should automatically restart the current daemon.  */
1072
1209
  -v, --verbose            set maximum verbosity level\n\
1073
1210
  --log-file[=FILE]        enable logging to specified FILE\n\
1074
1211
                           (default: %s/%s.log)\n\
 
1212
  --syslog-method=(libc|unix:file|udp:ip:port)\n\
 
1213
                           specify how to send messages to syslog daemon\n\
1075
1214
  --syslog-target=HOST:PORT  also send syslog msgs to HOST:PORT via UDP\n",
1076
1215
           ovs_logdir(), program_name);
1077
1216
}