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