Branch data Line data Source code
1 : : /*
2 : : * Copyright (c) 2008, 2009, 2010, 2011, 2013, 2014 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 : :
19 : : #include "collectors.h"
20 : :
21 : : #include <errno.h>
22 : : #include <stdlib.h>
23 : : #include <sys/socket.h>
24 : : #include <unistd.h>
25 : :
26 : : #include "socket-util.h"
27 : : #include "sset.h"
28 : : #include "util.h"
29 : : #include "openvswitch/vlog.h"
30 : :
31 : 1288 : VLOG_DEFINE_THIS_MODULE(collectors);
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 sset. */
51 : : int
52 : 17 : collectors_create(const struct sset *targets, uint16_t default_port,
53 : : struct collectors **collectorsp)
54 : : {
55 : : struct collectors *c;
56 : : const char *name;
57 : 17 : int retval = 0;
58 : :
59 : 17 : c = xmalloc(sizeof *c);
60 : 17 : c->fds = xmalloc(sizeof *c->fds * sset_count(targets));
61 : 17 : c->n_fds = 0;
62 [ + - ][ - + ]: 34 : SSET_FOR_EACH (name, targets) {
[ + + ]
63 : : int error;
64 : : int fd;
65 : :
66 : 17 : error = inet_open_active(SOCK_DGRAM, name, default_port, NULL, &fd, 0);
67 [ + - ]: 17 : if (fd >= 0) {
68 : 17 : c->fds[c->n_fds++] = fd;
69 : : } else {
70 : : static struct vlog_rate_limit rl = VLOG_RATE_LIMIT_INIT(1, 5);
71 : :
72 [ # # ]: 0 : VLOG_WARN_RL(&rl, "couldn't open connection to collector %s (%s)",
73 : : name, ovs_strerror(error));
74 [ # # ]: 0 : if (!retval) {
75 : 0 : retval = error;
76 : : }
77 : : }
78 : : }
79 : :
80 [ + - ]: 17 : if (c->n_fds) {
81 : 17 : *collectorsp = c;
82 : : } else {
83 : 0 : collectors_destroy(c);
84 : 0 : *collectorsp = NULL;
85 : : }
86 : :
87 : 17 : return retval;
88 : : }
89 : :
90 : : /* Destroys 'c'. */
91 : : void
92 : 51 : collectors_destroy(struct collectors *c)
93 : : {
94 [ + + ]: 51 : if (c) {
95 : : size_t i;
96 : :
97 [ + + ]: 22 : for (i = 0; i < c->n_fds; i++) {
98 : 11 : closesocket(c->fds[i]);
99 : : }
100 : 11 : free(c->fds);
101 : 11 : free(c);
102 : : }
103 : 51 : }
104 : :
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
108 : 89 : collectors_send(const struct collectors *c, const void *payload, size_t n)
109 : : {
110 : 89 : size_t errors = 0;
111 : :
112 [ + - ]: 89 : if (c) {
113 : : size_t i;
114 : :
115 [ + + ]: 178 : for (i = 0; i < c->n_fds; i++) {
116 : : static struct vlog_rate_limit rl = VLOG_RATE_LIMIT_INIT(1, 5);
117 [ + + ]: 89 : if (send(c->fds[i], payload, n, 0) == -1) {
118 : 30 : char *s = describe_fd(c->fds[i]);
119 [ + - ]: 30 : VLOG_WARN_RL(&rl, "%s: sending to collector failed (%s)",
120 : : s, ovs_strerror(errno));
121 : 30 : free(s);
122 : 30 : errors++;
123 : : }
124 : : }
125 : : }
126 : :
127 : 89 : return errors;
128 : : }
129 : :
130 : : int
131 : 62 : collectors_count(const struct collectors *c)
132 : : {
133 [ + - ]: 62 : return c ? c->n_fds : 0;
134 : : }
|