Setting tag sliver-openvswitch-2.2.90-1
[sliver-openvswitch.git] / tests / test-reconnect.c
1 /*
2  * Copyright (c) 2009, 2010, 2011, 2012, 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 "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 #include "ovstest.h"
32
33 static struct reconnect *reconnect;
34 static int now;
35
36 static void diff_stats(const struct reconnect_stats *old,
37                        const struct reconnect_stats *new,
38                        int delta);
39 static const struct command *get_all_commands(void);
40
41 static void
42 test_reconnect_main(int argc OVS_UNUSED, char *argv[] OVS_UNUSED)
43 {
44     extern struct vlog_module VLM_reconnect;
45     struct reconnect_stats prev;
46     unsigned int old_max_tries;
47     int old_time;
48     char line[128];
49
50     vlog_set_levels(&VLM_reconnect, VLF_ANY_FACILITY, VLL_OFF);
51
52     now = 1000;
53     reconnect = reconnect_create(now);
54     reconnect_set_name(reconnect, "remote");
55     reconnect_get_stats(reconnect, now, &prev);
56     printf("### t=%d ###\n", now);
57     old_time = now;
58     old_max_tries = reconnect_get_max_tries(reconnect);
59     while (fgets(line, sizeof line, stdin)) {
60         struct reconnect_stats cur;
61         struct svec args;
62
63         fputs(line, stdout);
64         if (line[0] == '#') {
65             continue;
66         }
67
68         svec_init(&args);
69         svec_parse_words(&args, line);
70         svec_terminate(&args);
71         if (!svec_is_empty(&args)) {
72             run_command(args.n, args.names, get_all_commands());
73         }
74         svec_destroy(&args);
75
76         if (old_time != now) {
77             printf("\n### t=%d ###\n", now);
78         }
79
80         reconnect_get_stats(reconnect, now, &cur);
81         diff_stats(&prev, &cur, now - old_time);
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         old_time = now;
89     }
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_activity(int argc OVS_UNUSED, char *argv[] OVS_UNUSED)
150 {
151     reconnect_activity(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             OVS_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            int delta)
213 {
214     if (old->state != new->state
215         || old->state_elapsed != new->state_elapsed
216         || old->backoff != new->backoff) {
217         printf("  in %s for %u ms (%d ms backoff)\n",
218                new->state, new->state_elapsed, new->backoff);
219     }
220     if (old->creation_time != new->creation_time
221         || old->last_activity != new->last_activity
222         || old->last_connected != new->last_connected) {
223         printf("  created %lld, last activity %lld, last connected %lld\n",
224                new->creation_time, new->last_activity, new->last_connected);
225     }
226     if (old->n_successful_connections != new->n_successful_connections
227         || old->n_attempted_connections != new->n_attempted_connections
228         || old->seqno != new->seqno) {
229         printf("  %u successful connections out of %u attempts, seqno %u\n",
230                new->n_successful_connections, new->n_attempted_connections,
231                new->seqno);
232     }
233     if (old->is_connected != new->is_connected) {
234         printf("  %sconnected\n", new->is_connected ? "" : "dis");
235     }
236     if (old->last_connected != new->last_connected
237         || (old->msec_since_connect != new->msec_since_connect - delta
238             && !(old->msec_since_connect == UINT_MAX
239                  && new->msec_since_connect == UINT_MAX))
240         || (old->total_connected_duration != new->total_connected_duration - delta
241             && !(old->total_connected_duration == 0
242                  && new->total_connected_duration == 0))) {
243         printf("  last connected %u ms ago, connected %u ms total\n",
244                new->msec_since_connect, new->total_connected_duration);
245     }
246     if (old->last_disconnected != new->last_disconnected
247         || (old->msec_since_disconnect != new->msec_since_disconnect - delta
248             && !(old->msec_since_disconnect == UINT_MAX
249                  && new->msec_since_disconnect == UINT_MAX))) {
250         printf("  disconnected at %llu ms (%u ms ago)\n",
251                new->last_disconnected, new->msec_since_disconnect);
252     }
253 }
254
255 static void
256 do_set_passive(int argc OVS_UNUSED, char *argv[] OVS_UNUSED)
257 {
258     reconnect_set_passive(reconnect, true, now);
259 }
260
261 static void
262 do_listening(int argc OVS_UNUSED, char *argv[] OVS_UNUSED)
263 {
264     reconnect_listening(reconnect, now);
265 }
266
267 static void
268 do_listen_error(int argc OVS_UNUSED, char *argv[])
269 {
270     reconnect_listen_error(reconnect, now, atoi(argv[1]));
271 }
272
273 static const struct command all_commands[] = {
274     { "enable", 0, 0, do_enable },
275     { "disable", 0, 0, do_disable },
276     { "force-reconnect", 0, 0, do_force_reconnect },
277     { "disconnected", 0, 1, do_disconnected },
278     { "connecting", 0, 0, do_connecting },
279     { "connect-failed", 0, 1, do_connect_failed },
280     { "connected", 0, 0, do_connected },
281     { "activity", 0, 0, do_activity },
282     { "run", 0, 1, do_run },
283     { "advance", 1, 1, do_advance },
284     { "timeout", 0, 0, do_timeout },
285     { "set-max-tries", 1, 1, do_set_max_tries },
286     { "passive", 0, 0, do_set_passive },
287     { "listening", 0, 0, do_listening },
288     { "listen-error", 1, 1, do_listen_error },
289     { NULL, 0, 0, NULL },
290 };
291
292 static const struct command *
293 get_all_commands(void)
294 {
295     return all_commands;
296 }
297
298 OVSTEST_REGISTER("test-reconnect", test_reconnect_main);