2
0
mirror of https://github.com/openvswitch/ovs synced 2025-10-21 14:49:41 +00:00
Files
openvswitch/tests/test-reconnect.c
Russell Bryant 1636c76112 command-line: add ovs_cmdl_context
I started working on a new command line utility that used this shared
code.  I wanted the ability to pass some data from common
initialization code to all of the commands.  You can find a similar
pattern in ovs-vsctl.

This patch updates the command handler to take a new struct,
ovs_cmdl_context, instead of argc and argv directly.  It includes argc
and argv, but also includes an opaque type (void *), where the user of
this API can attach its custom data it wants passed along to command
handlers.

This patch affected the ovstest sub-programs, as well.  The patch
includes a bit of an odd hack to OVSTEST_REGISTER() to avoid making
the main() function of the sub-programs take a ovs_cmdl_context.
The test main() functions still receive argc and argv directly, as
that seems more natural.  The test-subprograms themselves are able to
make use of a context internally, though.

Signed-off-by: Russell Bryant <rbryant@redhat.com>
Signed-off-by: Ben Pfaff <blp@nicira.com>
2015-03-17 08:15:57 -07:00

301 lines
8.3 KiB
C

/*
* Copyright (c) 2009, 2010, 2011, 2012, 2014 Nicira, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at:
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include <config.h>
#undef NDEBUG
#include "reconnect.h"
#include <errno.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "command-line.h"
#include "compiler.h"
#include "ovstest.h"
#include "svec.h"
#include "util.h"
#include "openvswitch/vlog.h"
static struct reconnect *reconnect;
static int now;
static void diff_stats(const struct reconnect_stats *old,
const struct reconnect_stats *new,
int delta);
static const struct ovs_cmdl_command *get_all_commands(void);
static void
test_reconnect_main(int argc OVS_UNUSED, char *argv[] OVS_UNUSED)
{
extern struct vlog_module VLM_reconnect;
struct reconnect_stats prev;
unsigned int old_max_tries;
int old_time;
char line[128];
vlog_set_levels(&VLM_reconnect, VLF_ANY_DESTINATION, VLL_OFF);
now = 1000;
reconnect = reconnect_create(now);
reconnect_set_name(reconnect, "remote");
reconnect_get_stats(reconnect, now, &prev);
printf("### t=%d ###\n", now);
old_time = now;
old_max_tries = reconnect_get_max_tries(reconnect);
while (fgets(line, sizeof line, stdin)) {
struct reconnect_stats cur;
struct svec args;
fputs(line, stdout);
if (line[0] == '#') {
continue;
}
svec_init(&args);
svec_parse_words(&args, line);
svec_terminate(&args);
if (!svec_is_empty(&args)) {
struct ovs_cmdl_context ctx = {
.argc = args.n,
.argv = args.names,
};
ovs_cmdl_run_command(&ctx, get_all_commands());
}
svec_destroy(&args);
if (old_time != now) {
printf("\n### t=%d ###\n", now);
}
reconnect_get_stats(reconnect, now, &cur);
diff_stats(&prev, &cur, now - old_time);
prev = cur;
if (reconnect_get_max_tries(reconnect) != old_max_tries) {
old_max_tries = reconnect_get_max_tries(reconnect);
printf(" %u tries left\n", old_max_tries);
}
old_time = now;
}
}
static void
do_enable(struct ovs_cmdl_context *ctx OVS_UNUSED)
{
reconnect_enable(reconnect, now);
}
static void
do_disable(struct ovs_cmdl_context *ctx OVS_UNUSED)
{
reconnect_disable(reconnect, now);
}
static void
do_force_reconnect(struct ovs_cmdl_context *ctx OVS_UNUSED)
{
reconnect_force_reconnect(reconnect, now);
}
static int
error_from_string(const char *s)
{
if (!s) {
return 0;
} else if (!strcmp(s, "ECONNREFUSED")) {
return ECONNREFUSED;
} else if (!strcmp(s, "EOF")) {
return EOF;
} else {
ovs_fatal(0, "unknown error '%s'", s);
}
}
static void
do_disconnected(struct ovs_cmdl_context *ctx)
{
reconnect_disconnected(reconnect, now, error_from_string(ctx->argv[1]));
}
static void
do_connecting(struct ovs_cmdl_context *ctx OVS_UNUSED)
{
reconnect_connecting(reconnect, now);
}
static void
do_connect_failed(struct ovs_cmdl_context *ctx)
{
reconnect_connect_failed(reconnect, now, error_from_string(ctx->argv[1]));
}
static void
do_connected(struct ovs_cmdl_context *ctx OVS_UNUSED)
{
reconnect_connected(reconnect, now);
}
static void
do_activity(struct ovs_cmdl_context *ctx OVS_UNUSED)
{
reconnect_activity(reconnect, now);
}
static void
do_run(struct ovs_cmdl_context *ctx)
{
enum reconnect_action action;
if (ctx->argc > 1) {
now += atoi(ctx->argv[1]);
}
action = reconnect_run(reconnect, now);
switch (action) {
default:
if (action != 0) {
OVS_NOT_REACHED();
}
break;
case RECONNECT_CONNECT:
printf(" should connect\n");
break;
case RECONNECT_DISCONNECT:
printf(" should disconnect\n");
break;
case RECONNECT_PROBE:
printf(" should send probe\n");
break;
}
}
static void
do_advance(struct ovs_cmdl_context *ctx)
{
now += atoi(ctx->argv[1]);
}
static void
do_timeout(struct ovs_cmdl_context *ctx OVS_UNUSED)
{
int timeout = reconnect_timeout(reconnect, now);
if (timeout >= 0) {
printf(" advance %d ms\n", timeout);
now += timeout;
} else {
printf(" no timeout\n");
}
}
static void
do_set_max_tries(struct ovs_cmdl_context *ctx)
{
reconnect_set_max_tries(reconnect, atoi(ctx->argv[1]));
}
static void
diff_stats(const struct reconnect_stats *old,
const struct reconnect_stats *new,
int delta)
{
if (old->state != new->state
|| old->state_elapsed != new->state_elapsed
|| old->backoff != new->backoff) {
printf(" in %s for %u ms (%d ms backoff)\n",
new->state, new->state_elapsed, new->backoff);
}
if (old->creation_time != new->creation_time
|| old->last_activity != new->last_activity
|| old->last_connected != new->last_connected) {
printf(" created %lld, last activity %lld, last connected %lld\n",
new->creation_time, new->last_activity, new->last_connected);
}
if (old->n_successful_connections != new->n_successful_connections
|| old->n_attempted_connections != new->n_attempted_connections
|| old->seqno != new->seqno) {
printf(" %u successful connections out of %u attempts, seqno %u\n",
new->n_successful_connections, new->n_attempted_connections,
new->seqno);
}
if (old->is_connected != new->is_connected) {
printf(" %sconnected\n", new->is_connected ? "" : "dis");
}
if (old->last_connected != new->last_connected
|| (old->msec_since_connect != new->msec_since_connect - delta
&& !(old->msec_since_connect == UINT_MAX
&& new->msec_since_connect == UINT_MAX))
|| (old->total_connected_duration != new->total_connected_duration - delta
&& !(old->total_connected_duration == 0
&& new->total_connected_duration == 0))) {
printf(" last connected %u ms ago, connected %u ms total\n",
new->msec_since_connect, new->total_connected_duration);
}
if (old->last_disconnected != new->last_disconnected
|| (old->msec_since_disconnect != new->msec_since_disconnect - delta
&& !(old->msec_since_disconnect == UINT_MAX
&& new->msec_since_disconnect == UINT_MAX))) {
printf(" disconnected at %llu ms (%u ms ago)\n",
new->last_disconnected, new->msec_since_disconnect);
}
}
static void
do_set_passive(struct ovs_cmdl_context *ctx OVS_UNUSED)
{
reconnect_set_passive(reconnect, true, now);
}
static void
do_listening(struct ovs_cmdl_context *ctx OVS_UNUSED)
{
reconnect_listening(reconnect, now);
}
static void
do_listen_error(struct ovs_cmdl_context *ctx)
{
reconnect_listen_error(reconnect, now, atoi(ctx->argv[1]));
}
static const struct ovs_cmdl_command all_commands[] = {
{ "enable", NULL, 0, 0, do_enable },
{ "disable", NULL, 0, 0, do_disable },
{ "force-reconnect", NULL, 0, 0, do_force_reconnect },
{ "disconnected", NULL, 0, 1, do_disconnected },
{ "connecting", NULL, 0, 0, do_connecting },
{ "connect-failed", NULL, 0, 1, do_connect_failed },
{ "connected", NULL, 0, 0, do_connected },
{ "activity", NULL, 0, 0, do_activity },
{ "run", NULL, 0, 1, do_run },
{ "advance", NULL, 1, 1, do_advance },
{ "timeout", NULL, 0, 0, do_timeout },
{ "set-max-tries", NULL, 1, 1, do_set_max_tries },
{ "passive", NULL, 0, 0, do_set_passive },
{ "listening", NULL, 0, 0, do_listening },
{ "listen-error", NULL, 1, 1, do_listen_error },
{ NULL, NULL, 0, 0, NULL },
};
static const struct ovs_cmdl_command *
get_all_commands(void)
{
return all_commands;
}
OVSTEST_REGISTER("test-reconnect", test_reconnect_main);