]>
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" | |
e6211adc | 29 | #include "openvswitch/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); | |
5f383751 | 37 | static const struct ovs_cmdl_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 | ||
d5460484 | 48 | vlog_set_levels(&VLM_reconnect, VLF_ANY_DESTINATION, 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)) { | |
1636c761 RB |
70 | struct ovs_cmdl_context ctx = { |
71 | .argc = args.n, | |
72 | .argv = args.names, | |
73 | }; | |
74 | ovs_cmdl_run_command(&ctx, get_all_commands()); | |
3ed497fc BP |
75 | } |
76 | svec_destroy(&args); | |
77 | ||
78 | if (old_time != now) { | |
79 | printf("\n### t=%d ###\n", now); | |
3ed497fc BP |
80 | } |
81 | ||
82 | reconnect_get_stats(reconnect, now, &cur); | |
5eda645e | 83 | diff_stats(&prev, &cur, now - old_time); |
3ed497fc | 84 | prev = cur; |
a85c0bbc BP |
85 | if (reconnect_get_max_tries(reconnect) != old_max_tries) { |
86 | old_max_tries = reconnect_get_max_tries(reconnect); | |
87 | printf(" %u tries left\n", old_max_tries); | |
88 | } | |
5eda645e AE |
89 | |
90 | old_time = now; | |
3ed497fc | 91 | } |
3ed497fc BP |
92 | } |
93 | ||
94 | static void | |
1636c761 | 95 | do_enable(struct ovs_cmdl_context *ctx OVS_UNUSED) |
3ed497fc BP |
96 | { |
97 | reconnect_enable(reconnect, now); | |
98 | } | |
99 | ||
100 | static void | |
1636c761 | 101 | do_disable(struct ovs_cmdl_context *ctx OVS_UNUSED) |
3ed497fc BP |
102 | { |
103 | reconnect_disable(reconnect, now); | |
104 | } | |
105 | ||
106 | static void | |
1636c761 | 107 | do_force_reconnect(struct ovs_cmdl_context *ctx OVS_UNUSED) |
3ed497fc BP |
108 | { |
109 | reconnect_force_reconnect(reconnect, now); | |
110 | } | |
111 | ||
112 | static int | |
113 | error_from_string(const char *s) | |
114 | { | |
115 | if (!s) { | |
116 | return 0; | |
117 | } else if (!strcmp(s, "ECONNREFUSED")) { | |
118 | return ECONNREFUSED; | |
119 | } else if (!strcmp(s, "EOF")) { | |
120 | return EOF; | |
121 | } else { | |
122 | ovs_fatal(0, "unknown error '%s'", s); | |
123 | } | |
124 | } | |
125 | ||
126 | static void | |
1636c761 | 127 | do_disconnected(struct ovs_cmdl_context *ctx) |
3ed497fc | 128 | { |
1636c761 | 129 | reconnect_disconnected(reconnect, now, error_from_string(ctx->argv[1])); |
3ed497fc BP |
130 | } |
131 | ||
132 | static void | |
1636c761 | 133 | do_connecting(struct ovs_cmdl_context *ctx OVS_UNUSED) |
3ed497fc BP |
134 | { |
135 | reconnect_connecting(reconnect, now); | |
136 | } | |
137 | ||
138 | static void | |
1636c761 | 139 | do_connect_failed(struct ovs_cmdl_context *ctx) |
3ed497fc | 140 | { |
1636c761 | 141 | reconnect_connect_failed(reconnect, now, error_from_string(ctx->argv[1])); |
3ed497fc BP |
142 | } |
143 | ||
144 | static void | |
1636c761 | 145 | do_connected(struct ovs_cmdl_context *ctx OVS_UNUSED) |
3ed497fc BP |
146 | { |
147 | reconnect_connected(reconnect, now); | |
148 | } | |
149 | ||
150 | static void | |
1636c761 | 151 | do_activity(struct ovs_cmdl_context *ctx OVS_UNUSED) |
3ed497fc | 152 | { |
a6f639f8 | 153 | reconnect_activity(reconnect, now); |
3ed497fc BP |
154 | } |
155 | ||
156 | static void | |
1636c761 | 157 | do_run(struct ovs_cmdl_context *ctx) |
3ed497fc BP |
158 | { |
159 | enum reconnect_action action; | |
160 | ||
1636c761 RB |
161 | if (ctx->argc > 1) { |
162 | now += atoi(ctx->argv[1]); | |
3ed497fc BP |
163 | } |
164 | ||
165 | action = reconnect_run(reconnect, now); | |
166 | switch (action) { | |
167 | default: | |
168 | if (action != 0) { | |
428b2edd | 169 | OVS_NOT_REACHED(); |
3ed497fc BP |
170 | } |
171 | break; | |
172 | ||
173 | case RECONNECT_CONNECT: | |
174 | printf(" should connect\n"); | |
175 | break; | |
176 | ||
177 | case RECONNECT_DISCONNECT: | |
178 | printf(" should disconnect\n"); | |
179 | break; | |
180 | ||
181 | case RECONNECT_PROBE: | |
182 | printf(" should send probe\n"); | |
183 | break; | |
184 | } | |
185 | } | |
186 | ||
187 | static void | |
1636c761 | 188 | do_advance(struct ovs_cmdl_context *ctx) |
3ed497fc | 189 | { |
1636c761 | 190 | now += atoi(ctx->argv[1]); |
3ed497fc BP |
191 | } |
192 | ||
193 | static void | |
1636c761 | 194 | do_timeout(struct ovs_cmdl_context *ctx OVS_UNUSED) |
3ed497fc BP |
195 | { |
196 | int timeout = reconnect_timeout(reconnect, now); | |
197 | if (timeout >= 0) { | |
198 | printf(" advance %d ms\n", timeout); | |
199 | now += timeout; | |
200 | } else { | |
201 | printf(" no timeout\n"); | |
202 | } | |
203 | } | |
204 | ||
a85c0bbc | 205 | static void |
1636c761 | 206 | do_set_max_tries(struct ovs_cmdl_context *ctx) |
a85c0bbc | 207 | { |
1636c761 | 208 | reconnect_set_max_tries(reconnect, atoi(ctx->argv[1])); |
a85c0bbc BP |
209 | } |
210 | ||
3ed497fc BP |
211 | static void |
212 | diff_stats(const struct reconnect_stats *old, | |
5eda645e AE |
213 | const struct reconnect_stats *new, |
214 | int delta) | |
3ed497fc BP |
215 | { |
216 | if (old->state != new->state | |
217 | || old->state_elapsed != new->state_elapsed | |
218 | || old->backoff != new->backoff) { | |
219 | printf(" in %s for %u ms (%d ms backoff)\n", | |
220 | new->state, new->state_elapsed, new->backoff); | |
221 | } | |
222 | if (old->creation_time != new->creation_time | |
a6f639f8 | 223 | || old->last_activity != new->last_activity |
3ed497fc | 224 | || old->last_connected != new->last_connected) { |
a6f639f8 BP |
225 | printf(" created %lld, last activity %lld, last connected %lld\n", |
226 | new->creation_time, new->last_activity, new->last_connected); | |
3ed497fc BP |
227 | } |
228 | if (old->n_successful_connections != new->n_successful_connections | |
229 | || old->n_attempted_connections != new->n_attempted_connections | |
230 | || old->seqno != new->seqno) { | |
231 | printf(" %u successful connections out of %u attempts, seqno %u\n", | |
232 | new->n_successful_connections, new->n_attempted_connections, | |
233 | new->seqno); | |
234 | } | |
5eda645e AE |
235 | if (old->is_connected != new->is_connected) { |
236 | printf(" %sconnected\n", new->is_connected ? "" : "dis"); | |
3ed497fc | 237 | } |
5eda645e AE |
238 | if (old->last_connected != new->last_connected |
239 | || (old->msec_since_connect != new->msec_since_connect - delta | |
240 | && !(old->msec_since_connect == UINT_MAX | |
241 | && new->msec_since_connect == UINT_MAX)) | |
242 | || (old->total_connected_duration != new->total_connected_duration - delta | |
243 | && !(old->total_connected_duration == 0 | |
244 | && new->total_connected_duration == 0))) { | |
245 | printf(" last connected %u ms ago, connected %u ms total\n", | |
246 | new->msec_since_connect, new->total_connected_duration); | |
eba18f00 | 247 | } |
5eda645e AE |
248 | if (old->last_disconnected != new->last_disconnected |
249 | || (old->msec_since_disconnect != new->msec_since_disconnect - delta | |
250 | && !(old->msec_since_disconnect == UINT_MAX | |
251 | && new->msec_since_disconnect == UINT_MAX))) { | |
252 | printf(" disconnected at %llu ms (%u ms ago)\n", | |
253 | new->last_disconnected, new->msec_since_disconnect); | |
eba18f00 | 254 | } |
3ed497fc BP |
255 | } |
256 | ||
19df7f51 | 257 | static void |
1636c761 | 258 | do_set_passive(struct ovs_cmdl_context *ctx OVS_UNUSED) |
19df7f51 BP |
259 | { |
260 | reconnect_set_passive(reconnect, true, now); | |
261 | } | |
262 | ||
263 | static void | |
1636c761 | 264 | do_listening(struct ovs_cmdl_context *ctx OVS_UNUSED) |
19df7f51 BP |
265 | { |
266 | reconnect_listening(reconnect, now); | |
267 | } | |
268 | ||
269 | static void | |
1636c761 | 270 | do_listen_error(struct ovs_cmdl_context *ctx) |
19df7f51 | 271 | { |
1636c761 | 272 | reconnect_listen_error(reconnect, now, atoi(ctx->argv[1])); |
19df7f51 BP |
273 | } |
274 | ||
5f383751 | 275 | static const struct ovs_cmdl_command all_commands[] = { |
451de37e AW |
276 | { "enable", NULL, 0, 0, do_enable }, |
277 | { "disable", NULL, 0, 0, do_disable }, | |
278 | { "force-reconnect", NULL, 0, 0, do_force_reconnect }, | |
279 | { "disconnected", NULL, 0, 1, do_disconnected }, | |
280 | { "connecting", NULL, 0, 0, do_connecting }, | |
281 | { "connect-failed", NULL, 0, 1, do_connect_failed }, | |
282 | { "connected", NULL, 0, 0, do_connected }, | |
283 | { "activity", NULL, 0, 0, do_activity }, | |
284 | { "run", NULL, 0, 1, do_run }, | |
285 | { "advance", NULL, 1, 1, do_advance }, | |
286 | { "timeout", NULL, 0, 0, do_timeout }, | |
287 | { "set-max-tries", NULL, 1, 1, do_set_max_tries }, | |
288 | { "passive", NULL, 0, 0, do_set_passive }, | |
289 | { "listening", NULL, 0, 0, do_listening }, | |
290 | { "listen-error", NULL, 1, 1, do_listen_error }, | |
291 | { NULL, NULL, 0, 0, NULL }, | |
3ed497fc | 292 | }; |
eadd1644 | 293 | |
5f383751 | 294 | static const struct ovs_cmdl_command * |
d2586fce GS |
295 | get_all_commands(void) |
296 | { | |
297 | return all_commands; | |
298 | } | |
299 | ||
eadd1644 | 300 | OVSTEST_REGISTER("test-reconnect", test_reconnect_main); |