vswitchd: Fix "updelay" configuration for bonds.
[sliver-openvswitch.git] / tests / test-reconnect.c
1 /*
2  * Copyright (c) 2009, 2010 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 "reconnect.h"
20
21 #include <errno.h>
22 #include <stdio.h>
23 #include <stdlib.h>
24 #include <string.h>
25
26 #include "command-line.h"
27 #include "compiler.h"
28 #include "svec.h"
29 #include "util.h"
30 #include "vlog.h"
31
32 static struct reconnect *reconnect;
33 static int now;
34
35 static const struct command commands[];
36
37 static void diff_stats(const struct reconnect_stats *old,
38                        const struct reconnect_stats *new);
39
40 int
41 main(void)
42 {
43     extern struct vlog_module VLM_reconnect;
44     struct reconnect_stats prev;
45     unsigned int old_max_tries;
46     int old_time;
47     char line[128];
48
49     vlog_set_levels(&VLM_reconnect, VLF_ANY_FACILITY, VLL_EMER);
50
51     now = 1000;
52     reconnect = reconnect_create(now);
53     reconnect_set_name(reconnect, "remote");
54     reconnect_get_stats(reconnect, now, &prev);
55     printf("### t=%d ###\n", now);
56     old_time = now;
57     old_max_tries = reconnect_get_max_tries(reconnect);
58     while (fgets(line, sizeof line, stdin)) {
59         struct reconnect_stats cur;
60         struct svec args;
61
62         fputs(line, stdout);
63         if (line[0] == '#') {
64             continue;
65         }
66
67         svec_init(&args);
68         svec_parse_words(&args, line);
69         svec_terminate(&args);
70         if (!svec_is_empty(&args)) {
71             run_command(args.n, args.names, commands);
72         }
73         svec_destroy(&args);
74
75         if (old_time != now) {
76             printf("\n### t=%d ###\n", now);
77             old_time = now;
78         }
79
80         reconnect_get_stats(reconnect, now, &cur);
81         diff_stats(&prev, &cur);
82         prev = cur;
83         if (reconnect_get_max_tries(reconnect) != old_max_tries) {
84             old_max_tries = reconnect_get_max_tries(reconnect);
85             printf("  %u tries left\n", old_max_tries);
86         }
87     }
88
89     return 0;
90 }
91
92 static void
93 do_enable(int argc OVS_UNUSED, char *argv[] OVS_UNUSED)
94 {
95     reconnect_enable(reconnect, now);
96 }
97
98 static void
99 do_disable(int argc OVS_UNUSED, char *argv[] OVS_UNUSED)
100 {
101     reconnect_disable(reconnect, now);
102 }
103
104 static void
105 do_force_reconnect(int argc OVS_UNUSED, char *argv[] OVS_UNUSED)
106 {
107     reconnect_force_reconnect(reconnect, now);
108 }
109
110 static int
111 error_from_string(const char *s)
112 {
113     if (!s) {
114         return 0;
115     } else if (!strcmp(s, "ECONNREFUSED")) {
116         return ECONNREFUSED;
117     } else if (!strcmp(s, "EOF")) {
118         return EOF;
119     } else {
120         ovs_fatal(0, "unknown error '%s'", s);
121     }
122 }
123
124 static void
125 do_disconnected(int argc OVS_UNUSED, char *argv[])
126 {
127     reconnect_disconnected(reconnect, now, error_from_string(argv[1]));
128 }
129
130 static void
131 do_connecting(int argc OVS_UNUSED, char *argv[] OVS_UNUSED)
132 {
133     reconnect_connecting(reconnect, now);
134 }
135
136 static void
137 do_connect_failed(int argc OVS_UNUSED, char *argv[])
138 {
139     reconnect_connect_failed(reconnect, now, error_from_string(argv[1]));
140 }
141
142 static void
143 do_connected(int argc OVS_UNUSED, char *argv[] OVS_UNUSED)
144 {
145     reconnect_connected(reconnect, now);
146 }
147
148 static void
149 do_received(int argc OVS_UNUSED, char *argv[] OVS_UNUSED)
150 {
151     reconnect_received(reconnect, now);
152 }
153
154 static void
155 do_run(int argc, char *argv[])
156 {
157     enum reconnect_action action;
158
159     if (argc > 1) {
160         now += atoi(argv[1]);
161     }
162
163     action = reconnect_run(reconnect, now);
164     switch (action) {
165     default:
166         if (action != 0) {
167             NOT_REACHED();
168         }
169         break;
170
171     case RECONNECT_CONNECT:
172         printf("  should connect\n");
173         break;
174
175     case RECONNECT_DISCONNECT:
176         printf("  should disconnect\n");
177         break;
178
179     case RECONNECT_PROBE:
180         printf("  should send probe\n");
181         break;
182     }
183 }
184
185 static void
186 do_advance(int argc OVS_UNUSED, char *argv[])
187 {
188     now += atoi(argv[1]);
189 }
190
191 static void
192 do_timeout(int argc OVS_UNUSED, char *argv[] OVS_UNUSED)
193 {
194     int timeout = reconnect_timeout(reconnect, now);
195     if (timeout >= 0) {
196         printf("  advance %d ms\n", timeout);
197         now += timeout;
198     } else {
199         printf("  no timeout\n");
200     }
201 }
202
203 static void
204 do_set_max_tries(int argc OVS_UNUSED, char *argv[])
205 {
206     reconnect_set_max_tries(reconnect, atoi(argv[1]));
207 }
208
209 static void
210 diff_stats(const struct reconnect_stats *old,
211            const struct reconnect_stats *new)
212 {
213     if (old->state != new->state
214         || old->state_elapsed != new->state_elapsed
215         || old->backoff != new->backoff) {
216         printf("  in %s for %u ms (%d ms backoff)\n",
217                new->state, new->state_elapsed, new->backoff);
218     }
219     if (old->creation_time != new->creation_time
220         || old->last_received != new->last_received
221         || old->last_connected != new->last_connected) {
222         printf("  created %lld, last received %lld, last connected %lld\n",
223                new->creation_time, new->last_received, new->last_connected);
224     }
225     if (old->n_successful_connections != new->n_successful_connections
226         || old->n_attempted_connections != new->n_attempted_connections
227         || old->seqno != new->seqno) {
228         printf("  %u successful connections out of %u attempts, seqno %u\n",
229                new->n_successful_connections, new->n_attempted_connections,
230                new->seqno);
231     }
232     if (old->is_connected != new->is_connected
233         || old->current_connection_duration != new->current_connection_duration
234         || old->total_connected_duration != new->total_connected_duration) {
235         printf("  %sconnected (%u ms), total %u ms connected\n",
236                new->is_connected ? "" : "not ",
237                new->current_connection_duration,
238                new->total_connected_duration);
239     }
240 }
241
242 static void
243 do_set_passive(int argc OVS_UNUSED, char *argv[] OVS_UNUSED)
244 {
245     reconnect_set_passive(reconnect, true, now);
246 }
247
248 static void
249 do_listening(int argc OVS_UNUSED, char *argv[] OVS_UNUSED)
250 {
251     reconnect_listening(reconnect, now);
252 }
253
254 static void
255 do_listen_error(int argc OVS_UNUSED, char *argv[])
256 {
257     reconnect_listen_error(reconnect, now, atoi(argv[1]));
258 }
259
260 static const struct command commands[] = {
261     { "enable", 0, 0, do_enable },
262     { "disable", 0, 0, do_disable },
263     { "force-reconnect", 0, 0, do_force_reconnect },
264     { "disconnected", 0, 1, do_disconnected },
265     { "connecting", 0, 0, do_connecting },
266     { "connect-failed", 0, 1, do_connect_failed },
267     { "connected", 0, 0, do_connected },
268     { "received", 0, 0, do_received },
269     { "run", 0, 1, do_run },
270     { "advance", 1, 1, do_advance },
271     { "timeout", 0, 0, do_timeout },
272     { "set-max-tries", 1, 1, do_set_max_tries },
273     { "passive", 0, 0, do_set_passive },
274     { "listening", 0, 0, do_listening },
275     { "listen-error", 1, 1, do_listen_error },
276     { NULL, 0, 0, NULL },
277 };
278