]>
Commit | Line | Data |
---|---|---|
6bab3798 | 1 | /* |
62d7cc84 | 2 | * Copyright (c) 2008, 2009, 2010, 2011, 2013, 2014 Nicira, Inc. |
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" | |
81e2083f | 27 | #include "sset.h" |
6bab3798 | 28 | #include "util.h" |
e6211adc | 29 | #include "openvswitch/vlog.h" |
6bab3798 | 30 | |
d98e6007 | 31 | VLOG_DEFINE_THIS_MODULE(collectors); |
5136ce49 | 32 | |
6bab3798 BP |
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 | |
81e2083f | 50 | * '*collectorsp' is null, if 'target's is an empty sset. */ |
6bab3798 | 51 | int |
81e2083f | 52 | collectors_create(const struct sset *targets, uint16_t default_port, |
6bab3798 BP |
53 | struct collectors **collectorsp) |
54 | { | |
55 | struct collectors *c; | |
81e2083f | 56 | const char *name; |
6bab3798 | 57 | int retval = 0; |
6bab3798 BP |
58 | |
59 | c = xmalloc(sizeof *c); | |
81e2083f | 60 | c->fds = xmalloc(sizeof *c->fds * sset_count(targets)); |
6bab3798 | 61 | c->n_fds = 0; |
81e2083f | 62 | SSET_FOR_EACH (name, targets) { |
6bab3798 BP |
63 | int error; |
64 | int fd; | |
65 | ||
ef8a3d14 | 66 | error = inet_open_active(SOCK_DGRAM, name, default_port, NULL, &fd, 0); |
6bab3798 BP |
67 | if (fd >= 0) { |
68 | c->fds[c->n_fds++] = fd; | |
69 | } else { | |
70 | static struct vlog_rate_limit rl = VLOG_RATE_LIMIT_INIT(1, 5); | |
71 | ||
72 | VLOG_WARN_RL(&rl, "couldn't open connection to collector %s (%s)", | |
10a89ef0 | 73 | name, ovs_strerror(error)); |
6bab3798 BP |
74 | if (!retval) { |
75 | retval = error; | |
76 | } | |
77 | } | |
78 | } | |
6bab3798 BP |
79 | |
80 | if (c->n_fds) { | |
81 | *collectorsp = c; | |
82 | } else { | |
83 | collectors_destroy(c); | |
84 | *collectorsp = NULL; | |
85 | } | |
86 | ||
87 | return retval; | |
88 | } | |
89 | ||
90 | /* Destroys 'c'. */ | |
91 | void | |
92 | collectors_destroy(struct collectors *c) | |
93 | { | |
94 | if (c) { | |
95 | size_t i; | |
96 | ||
97 | for (i = 0; i < c->n_fds; i++) { | |
6767b5ec | 98 | closesocket(c->fds[i]); |
6bab3798 BP |
99 | } |
100 | free(c->fds); | |
101 | free(c); | |
102 | } | |
103 | } | |
104 | ||
fb8f22c1 BY |
105 | /* Sends the 'n'-byte 'payload' to each of the collectors in 'c'. |
106 | * Return the number of IPFIX packets which were sent unsuccessfully*/ | |
107 | size_t | |
6bab3798 BP |
108 | collectors_send(const struct collectors *c, const void *payload, size_t n) |
109 | { | |
fb8f22c1 BY |
110 | size_t errors = 0; |
111 | ||
8ff9b354 JG |
112 | if (c) { |
113 | size_t i; | |
6bab3798 | 114 | |
8ff9b354 JG |
115 | for (i = 0; i < c->n_fds; i++) { |
116 | static struct vlog_rate_limit rl = VLOG_RATE_LIMIT_INIT(1, 5); | |
117 | if (send(c->fds[i], payload, n, 0) == -1) { | |
62d7cc84 BP |
118 | char *s = describe_fd(c->fds[i]); |
119 | VLOG_WARN_RL(&rl, "%s: sending to collector failed (%s)", | |
120 | s, ovs_strerror(errno)); | |
121 | free(s); | |
fb8f22c1 | 122 | errors++; |
8ff9b354 | 123 | } |
6bab3798 BP |
124 | } |
125 | } | |
fb8f22c1 BY |
126 | |
127 | return errors; | |
6bab3798 | 128 | } |
72b06300 BP |
129 | |
130 | int | |
131 | collectors_count(const struct collectors *c) | |
132 | { | |
8ff9b354 | 133 | return c ? c->n_fds : 0; |
72b06300 | 134 | } |