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