]>
Commit | Line | Data |
---|---|---|
6bab3798 BP |
1 | /* |
2 | * Copyright (c) 2008, 2009 Nicira Networks. | |
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 | ||
19 | #include "collectors.h" | |
20 | ||
21 | #include <errno.h> | |
22 | #include <stdlib.h> | |
23 | #include <unistd.h> | |
24 | ||
25 | #include "socket-util.h" | |
26 | #include "svec.h" | |
27 | #include "util.h" | |
28 | ||
29 | #define THIS_MODULE VLM_collectors | |
30 | #include "vlog.h" | |
31 | ||
32 | struct collectors { | |
33 | int *fds; /* Sockets. */ | |
34 | size_t n_fds; /* Number of sockets. */ | |
35 | }; | |
36 | ||
37 | /* Opens the targets specified in 'targets' for sending UDP packets. This is | |
38 | * useful for e.g. sending NetFlow or sFlow packets. Returns 0 if successful, | |
39 | * otherwise a positive errno value if opening at least one collector failed. | |
40 | * | |
41 | * Each target in 'targets' should be a string in the format "<host>[:<port>]". | |
42 | * <port> may be omitted if 'default_port' is nonzero, in which case it | |
43 | * defaults to 'default_port'. | |
44 | * | |
45 | * '*collectorsp' is set to a null pointer if no targets were successfully | |
46 | * added, otherwise to a new collectors object if at least one was successfully | |
47 | * added. Thus, even on a failure return, it is possible that '*collectorsp' | |
48 | * is nonnull, and even on a successful return, it is possible that | |
49 | * '*collectorsp' is null, if 'target's is an empty svec. */ | |
50 | int | |
51 | collectors_create(const struct svec *targets_, uint16_t default_port, | |
52 | struct collectors **collectorsp) | |
53 | { | |
54 | struct collectors *c; | |
55 | struct svec targets; | |
56 | int retval = 0; | |
57 | size_t i; | |
58 | ||
59 | svec_clone(&targets, targets_); | |
60 | svec_sort_unique(&targets); | |
61 | ||
62 | c = xmalloc(sizeof *c); | |
63 | c->fds = xmalloc(sizeof *c->fds * targets.n); | |
64 | c->n_fds = 0; | |
65 | for (i = 0; i < targets.n; i++) { | |
66 | const char *name = targets.names[i]; | |
67 | int error; | |
68 | int fd; | |
69 | ||
70 | error = inet_open_active(SOCK_DGRAM, name, default_port, NULL, &fd); | |
71 | if (fd >= 0) { | |
72 | c->fds[c->n_fds++] = fd; | |
73 | } else { | |
74 | static struct vlog_rate_limit rl = VLOG_RATE_LIMIT_INIT(1, 5); | |
75 | ||
76 | VLOG_WARN_RL(&rl, "couldn't open connection to collector %s (%s)", | |
77 | name, strerror(error)); | |
78 | if (!retval) { | |
79 | retval = error; | |
80 | } | |
81 | } | |
82 | } | |
83 | svec_destroy(&targets); | |
84 | ||
85 | if (c->n_fds) { | |
86 | *collectorsp = c; | |
87 | } else { | |
88 | collectors_destroy(c); | |
89 | *collectorsp = NULL; | |
90 | } | |
91 | ||
92 | return retval; | |
93 | } | |
94 | ||
95 | /* Destroys 'c'. */ | |
96 | void | |
97 | collectors_destroy(struct collectors *c) | |
98 | { | |
99 | if (c) { | |
100 | size_t i; | |
101 | ||
102 | for (i = 0; i < c->n_fds; i++) { | |
103 | close(c->fds[i]); | |
104 | } | |
105 | free(c->fds); | |
106 | free(c); | |
107 | } | |
108 | } | |
109 | ||
110 | /* Sends the 'n'-byte 'payload' to each of the collectors in 'c'. */ | |
111 | void | |
112 | collectors_send(const struct collectors *c, const void *payload, size_t n) | |
113 | { | |
114 | size_t i; | |
115 | ||
116 | for (i = 0; i < c->n_fds; i++) { | |
117 | static struct vlog_rate_limit rl = VLOG_RATE_LIMIT_INIT(1, 5); | |
118 | if (send(c->fds[i], payload, n, 0) == -1) { | |
119 | VLOG_WARN_RL(&rl, "sending to collector failed: %s", | |
120 | strerror(errno)); | |
121 | } | |
122 | } | |
123 | } |