]> git.proxmox.com Git - ovs.git/blame - tests/test-netflow.c
Fix ovs-dpctl-top by removing 3 wrong hunks in py3-compat.patch.
[ovs.git] / tests / test-netflow.c
CommitLineData
17f7f7e0 1/*
fd13c6b5 2 * Copyright (c) 2011, 2012, 2013, 2014, 2015, 2017 Nicira, Inc.
17f7f7e0
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>
3f636c7e
JR
18#undef NDEBUG
19#include "netflow.h"
17f7f7e0
BP
20#include <errno.h>
21#include <getopt.h>
22#include <signal.h>
23#include <stdlib.h>
24#include <unistd.h>
17f7f7e0
BP
25#include "command-line.h"
26#include "daemon.h"
3e8a2ad1 27#include "openvswitch/dynamic-string.h"
64c96779 28#include "openvswitch/ofpbuf.h"
3f636c7e 29#include "ovstest.h"
17f7f7e0 30#include "packets.h"
fd016ae3 31#include "openvswitch/poll-loop.h"
17f7f7e0
BP
32#include "socket-util.h"
33#include "unixctl.h"
34#include "util.h"
e6211adc 35#include "openvswitch/vlog.h"
17f7f7e0 36
cab50449 37OVS_NO_RETURN static void usage(void);
17f7f7e0
BP
38static void parse_options(int argc, char *argv[]);
39
40static unixctl_cb_func test_netflow_exit;
41
42static void
43print_netflow(struct ofpbuf *buf)
44{
45 const struct netflow_v5_header *hdr;
46 int i;
47
48 hdr = ofpbuf_try_pull(buf, sizeof *hdr);
49 if (!hdr) {
50 printf("truncated NetFlow packet header\n");
51 return;
52 }
53 printf("header: v%"PRIu16", "
54 "uptime %"PRIu32", "
55 "now %"PRIu32".%09"PRIu32", "
56 "seq %"PRIu32", "
57 "engine %"PRIu8",%"PRIu8,
58 ntohs(hdr->version),
59 ntohl(hdr->sysuptime),
60 ntohl(hdr->unix_secs), ntohl(hdr->unix_nsecs),
61 ntohl(hdr->flow_seq),
62 hdr->engine_type, hdr->engine_id);
63 if (hdr->sampling_interval != htons(0)) {
64 printf(", interval %"PRIu16, ntohs(hdr->sampling_interval));
65 }
66 putchar('\n');
67
68 for (i = 0; i < ntohs(hdr->count); i++) {
69 struct netflow_v5_record *rec;
70
71 rec = ofpbuf_try_pull(buf, sizeof *rec);
72 if (!rec) {
73 printf("truncated NetFlow records\n");
74 return;
75 }
76
52440c19 77 printf("seq %"PRIu32": "IP_FMT" > "IP_FMT, ntohl(hdr->flow_seq),
ed36537e 78 IP_ARGS(rec->src_addr), IP_ARGS(rec->dst_addr));
17f7f7e0
BP
79
80 printf(", if %"PRIu16" > %"PRIu16,
81 ntohs(rec->input), ntohs(rec->output));
82
83 printf(", %"PRIu32" pkts, %"PRIu32" bytes",
84 ntohl(rec->packet_count), ntohl(rec->byte_count));
85
86 switch (rec->ip_proto) {
87 case IPPROTO_TCP:
88 printf(", TCP %"PRIu16" > %"PRIu16,
89 ntohs(rec->src_port), ntohs(rec->dst_port));
90 if (rec->tcp_flags) {
7393104d
BP
91 struct ds s = DS_EMPTY_INITIALIZER;
92 packet_format_tcp_flags(&s, rec->tcp_flags);
93 printf(" %s", ds_cstr(&s));
94 ds_destroy(&s);
17f7f7e0
BP
95 }
96 break;
97
98 case IPPROTO_UDP:
99 printf(", UDP %"PRIu16" > %"PRIu16,
100 ntohs(rec->src_port), ntohs(rec->dst_port));
101 break;
102
0d56eaf2
JS
103 case IPPROTO_SCTP:
104 printf(", SCTP %"PRIu16" > %"PRIu16,
105 ntohs(rec->src_port), ntohs(rec->dst_port));
106 break;
107
17f7f7e0 108 case IPPROTO_ICMP:
fd13c6b5 109 printf(", ICMP %u:%u",
17f7f7e0
BP
110 ntohs(rec->dst_port) >> 8,
111 ntohs(rec->dst_port) & 0xff);
112 if (rec->src_port != htons(0)) {
113 printf(", src_port=%"PRIu16, ntohs(rec->src_port));
114 }
115 break;
116
117 default:
118 printf(", proto %"PRIu8, rec->ip_proto);
119 break;
120 }
121
122 if (rec->ip_proto != IPPROTO_TCP && rec->tcp_flags != 0) {
123 printf(", flags %"PRIx8, rec->tcp_flags);
124 }
125
126 if (rec->ip_proto != IPPROTO_TCP &&
127 rec->ip_proto != IPPROTO_UDP &&
0d56eaf2 128 rec->ip_proto != IPPROTO_SCTP &&
17f7f7e0
BP
129 rec->ip_proto != IPPROTO_ICMP) {
130 if (rec->src_port != htons(0)) {
131 printf(", src_port %"PRIu16, ntohs(rec->src_port));
132 }
133 if (rec->dst_port != htons(0)) {
134 printf(", dst_port %"PRIu16, ntohs(rec->dst_port));
135 }
136 }
137
138 if (rec->ip_tos) {
139 printf(", TOS %"PRIx8, rec->ip_tos);
140 }
141
142 printf(", time %"PRIu32"...%"PRIu32,
143 ntohl(rec->init_time), ntohl(rec->used_time));
144
145 if (rec->nexthop != htonl(0)) {
ed36537e 146 printf(", nexthop "IP_FMT, IP_ARGS(rec->nexthop));
17f7f7e0
BP
147 }
148 if (rec->src_as != htons(0) || rec->dst_as != htons(0)) {
149 printf(", AS %"PRIu16" > %"PRIu16,
150 ntohs(rec->src_as), ntohs(rec->dst_as));
151 }
152 if (rec->src_mask != 0 || rec->dst_mask != 0) {
153 printf(", mask %"PRIu8" > %"PRIu8, rec->src_mask, rec->dst_mask);
154 }
155 if (rec->pad1) {
156 printf(", pad1 %"PRIu8, rec->pad1);
157 }
158 if (rec->pad[0] || rec->pad[1]) {
159 printf(", pad %"PRIu8", %"PRIu8, rec->pad[0], rec->pad[1]);
160 }
161 putchar('\n');
162 }
163
6fd6ed71
PS
164 if (buf->size) {
165 printf("%"PRIu32" extra bytes after last record\n", buf->size);
17f7f7e0
BP
166 }
167}
168
eadd1644
AZ
169static void
170test_netflow_main(int argc, char *argv[])
17f7f7e0
BP
171{
172 struct unixctl_server *server;
173 enum { MAX_RECV = 1500 };
174 const char *target;
175 struct ofpbuf buf;
176 bool exiting = false;
177 int error;
178 int sock;
17f7f7e0
BP
179 int n;
180
5f383751 181 ovs_cmdl_proctitle_init(argc, argv);
17f7f7e0 182 set_program_name(argv[0]);
8f26aeb9 183 service_start(&argc, &argv);
17f7f7e0
BP
184 parse_options(argc, argv);
185
186 if (argc - optind != 1) {
187 ovs_fatal(0, "exactly one non-option argument required "
188 "(use --help for help)");
189 }
190 target = argv[optind];
191
b52ecd96 192 sock = inet_open_passive(SOCK_DGRAM, target, 0, NULL, 0, true);
17f7f7e0 193 if (sock < 0) {
10a89ef0 194 ovs_fatal(0, "%s: failed to open (%s)", argv[1], ovs_strerror(-sock));
17f7f7e0
BP
195 }
196
7d0c5973 197 daemon_save_fd(STDOUT_FILENO);
e91b927d 198 daemonize_start(false);
17f7f7e0
BP
199
200 error = unixctl_server_create(NULL, &server);
201 if (error) {
202 ovs_fatal(error, "failed to create unixctl server");
203 }
204 unixctl_command_register("exit", "", 0, 0, test_netflow_exit, &exiting);
205
206 daemonize_complete();
207
17f7f7e0
BP
208 ofpbuf_init(&buf, MAX_RECV);
209 n = 0;
210 for (;;) {
211 int retval;
212
213 unixctl_server_run(server);
214
215 ofpbuf_clear(&buf);
216 do {
6fd6ed71 217 retval = recv(sock, buf.data, buf.allocated, 0);
17f7f7e0
BP
218 } while (retval < 0 && errno == EINTR);
219 if (retval > 0) {
220 ofpbuf_put_uninit(&buf, retval);
221 if (n++ > 0) {
222 putchar('\n');
223 }
224 print_netflow(&buf);
225 fflush(stdout);
226 }
227
228 if (exiting) {
229 break;
230 }
231
232 poll_fd_wait(sock, POLLIN);
233 unixctl_server_wait(server);
234 poll_block();
235 }
952ba185
WT
236
237 ofpbuf_uninit(&buf);
238 unixctl_server_destroy(server);
17f7f7e0
BP
239}
240
241static void
242parse_options(int argc, char *argv[])
243{
244 enum {
977529e4
BP
245 DAEMON_OPTION_ENUMS,
246 VLOG_OPTION_ENUMS
17f7f7e0 247 };
07fc4ed3 248 static const struct option long_options[] = {
17f7f7e0
BP
249 {"help", no_argument, NULL, 'h'},
250 DAEMON_LONG_OPTIONS,
977529e4 251 VLOG_LONG_OPTIONS,
17f7f7e0
BP
252 {NULL, 0, NULL, 0},
253 };
5f383751 254 char *short_options = ovs_cmdl_long_options_to_short_options(long_options);
17f7f7e0
BP
255
256 for (;;) {
257 int c = getopt_long(argc, argv, short_options, long_options, NULL);
258 if (c == -1) {
259 break;
260 }
261
262 switch (c) {
263 case 'h':
264 usage();
265
17f7f7e0 266 DAEMON_OPTION_HANDLERS
977529e4 267 VLOG_OPTION_HANDLERS
17f7f7e0
BP
268
269 case '?':
270 exit(EXIT_FAILURE);
271
272 default:
273 abort();
274 }
275 }
276 free(short_options);
277}
278
279static void
280usage(void)
281{
282 printf("%s: netflow collector test utility\n"
283 "usage: %s [OPTIONS] PORT[:IP]\n"
284 "where PORT is the UDP port to listen on and IP is optionally\n"
285 "the IP address to listen on.\n",
286 program_name, program_name);
287 daemon_usage();
288 vlog_usage();
289 printf("\nOther options:\n"
290 " -h, --help display this help message\n");
291 exit(EXIT_SUCCESS);
292}
293
294static void
295test_netflow_exit(struct unixctl_conn *conn,
296 int argc OVS_UNUSED, const char *argv[] OVS_UNUSED,
297 void *exiting_)
298{
299 bool *exiting = exiting_;
300 *exiting = true;
bde9f75d 301 unixctl_command_reply(conn, NULL);
17f7f7e0 302}
eadd1644
AZ
303
304OVSTEST_REGISTER("test-netflow", test_netflow_main);