/* Connects to a fake_pvconn with vconn_open(), accepts that connection and * closes it immediately, and verifies that vconn_connect() reports * 'expected_error'. */ static void test_accept_then_close(struct ovs_cmdl_context *ctx) { const char *type = ctx->argv[1]; struct fake_pvconn fpv; struct vconn *vconn; int error; fpv_create(type, &fpv); CHECK_ERRNO(vconn_open(fpv.vconn_name, 0, DSCP_DEFAULT, &vconn), 0); vconn_run(vconn); stream_close(fpv_accept(&fpv)); fpv_close(&fpv); error = vconn_connect_block(vconn); if (!strcmp(type, "tcp") || !strcmp(type, "unix")) { if (error != ECONNRESET && error != EPIPE #ifdef _WIN32 && error != WSAECONNRESET #endif ) { ovs_fatal(0, "unexpected vconn_connect() return value %d (%s)", error, ovs_strerror(error)); } } else { CHECK_ERRNO(error, EPROTO); } vconn_close(vconn); fpv_destroy(&fpv); }
/* Connects to a fake_pvconn with vconn_open(), accepts that connection and * reads the hello message from it, then closes the connection and verifies * that vconn_connect() reports 'expected_error'. */ static void test_read_hello(struct ovs_cmdl_context *ctx) { const char *type = ctx->argv[1]; struct fake_pvconn fpv; struct vconn *vconn; struct stream *stream; int error; fpv_create(type, &fpv); CHECK_ERRNO(vconn_open(fpv.vconn_name, 0, DSCP_DEFAULT, &vconn), 0); vconn_run(vconn); stream = fpv_accept(&fpv); fpv_destroy(&fpv); for (;;) { struct ofp_header hello; int retval; retval = stream_recv(stream, &hello, sizeof hello); if (retval == sizeof hello) { enum ofpraw raw; CHECK(hello.version, OFP13_VERSION); CHECK(ofpraw_decode_partial(&raw, &hello, sizeof hello), 0); CHECK(raw, OFPRAW_OFPT_HELLO); CHECK(ntohs(hello.length), sizeof hello); break; } else { CHECK_ERRNO(retval, -EAGAIN); } vconn_run(vconn); CHECK_ERRNO(vconn_connect(vconn), EAGAIN); vconn_run_wait(vconn); vconn_connect_wait(vconn); stream_recv_wait(stream); poll_block(); } stream_close(stream); error = vconn_connect_block(vconn); if (error != ECONNRESET && error != EPIPE) { ovs_fatal(0, "unexpected vconn_connect() return value %d (%s)", error, ovs_strerror(error)); } vconn_close(vconn); }
/* Connects to a fake_pvconn with vconn_open(), then closes the listener and * verifies that vconn_connect() reports 'expected_error'. */ static void test_refuse_connection(int argc OVS_UNUSED, char *argv[]) { const char *type = argv[1]; int expected_error; struct fake_pvconn fpv; struct vconn *vconn; expected_error = (!strcmp(type, "unix") ? EPIPE : !strcmp(type, "tcp") ? ECONNRESET : EPROTO); fpv_create(type, &fpv); CHECK_ERRNO(vconn_open(fpv.vconn_name, OFP_VERSION, &vconn), 0); fpv_close(&fpv); vconn_run(vconn); CHECK_ERRNO(vconn_connect(vconn), expected_error); vconn_close(vconn); fpv_destroy(&fpv); }
/* Connects to a fake_pvconn with vconn_open(), then closes the listener and * verifies that vconn_connect() reports 'expected_error'. */ static void test_refuse_connection(struct ovs_cmdl_context *ctx) { const char *type = ctx->argv[1]; struct fake_pvconn fpv; struct vconn *vconn; int error; fpv_create(type, &fpv); CHECK_ERRNO(vconn_open(fpv.vconn_name, 0, DSCP_DEFAULT, &vconn), 0); fpv_close(&fpv); vconn_run(vconn); error = vconn_connect_block(vconn); if (!strcmp(type, "tcp")) { if (error != ECONNRESET && error != EPIPE #ifdef _WIN32 && error != WSAECONNRESET #endif ) { ovs_fatal(0, "unexpected vconn_connect() return value %d (%s)", error, ovs_strerror(error)); } } else if (!strcmp(type, "unix")) { #ifndef _WIN32 CHECK_ERRNO(error, EPIPE); #else CHECK_ERRNO(error, WSAECONNRESET); #endif } else if (!strcmp(type, "ssl")) { if (error != EPROTO && error != ECONNRESET) { ovs_fatal(0, "unexpected vconn_connect() return value %d (%s)", error, ovs_strerror(error)); } } else { ovs_fatal(0, "invalid connection type %s", type); } vconn_close(vconn); fpv_destroy(&fpv); }
/* Connects to a fake_pvconn with vconn_open(), accepts that connection and * reads the hello message from it, then closes the connection and verifies * that vconn_connect() reports 'expected_error'. */ static void test_read_hello(int argc OVS_UNUSED, char *argv[]) { const char *type = argv[1]; struct fake_pvconn fpv; struct vconn *vconn; struct stream *stream; fpv_create(type, &fpv); CHECK_ERRNO(vconn_open(fpv.vconn_name, OFP10_VERSION, &vconn, DSCP_DEFAULT), 0); vconn_run(vconn); stream = fpv_accept(&fpv); fpv_destroy(&fpv); for (;;) { struct ofp_header hello; int retval; retval = stream_recv(stream, &hello, sizeof hello); if (retval == sizeof hello) { CHECK(hello.version, OFP10_VERSION); CHECK(hello.type, OFPT_HELLO); CHECK(ntohs(hello.length), sizeof hello); break; } else { CHECK_ERRNO(retval, -EAGAIN); } vconn_run(vconn); CHECK_ERRNO(vconn_connect(vconn), EAGAIN); vconn_run_wait(vconn); vconn_connect_wait(vconn); stream_recv_wait(stream); poll_block(); } stream_close(stream); CHECK_ERRNO(vconn_connect(vconn), ECONNRESET); vconn_close(vconn); }
/* Connects to a fake_pvconn with vconn_open(), accepts that connection and * sends the 'out' bytes in 'out_size' to it (presumably an OFPT_HELLO * message), then verifies that vconn_connect() reports * 'expect_connect_error'. */ static void test_send_hello(const char *type, const void *out, size_t out_size, int expect_connect_error) { struct fake_pvconn fpv; struct vconn *vconn; bool read_hello, connected; struct ofpbuf *msg; struct stream *stream; size_t n_sent; fpv_create(type, &fpv); CHECK_ERRNO(vconn_open(fpv.vconn_name, 0, DSCP_DEFAULT, &vconn), 0); vconn_run(vconn); stream = fpv_accept(&fpv); fpv_destroy(&fpv); n_sent = 0; while (n_sent < out_size) { int retval; retval = stream_send(stream, (char *) out + n_sent, out_size - n_sent); if (retval > 0) { n_sent += retval; } else if (retval == -EAGAIN) { stream_run(stream); vconn_run(vconn); stream_recv_wait(stream); vconn_connect_wait(vconn); vconn_run_wait(vconn); poll_block(); } else { ovs_fatal(0, "stream_send returned unexpected value %d", retval); } } read_hello = connected = false; for (;;) { if (!read_hello) { struct ofp_header hello; int retval = stream_recv(stream, &hello, sizeof hello); if (retval == sizeof hello) { enum ofpraw raw; CHECK(hello.version, OFP13_VERSION); CHECK(ofpraw_decode_partial(&raw, &hello, sizeof hello), 0); CHECK(raw, OFPRAW_OFPT_HELLO); CHECK(ntohs(hello.length), sizeof hello); read_hello = true; } else { CHECK_ERRNO(retval, -EAGAIN); } } vconn_run(vconn); if (!connected) { int error = vconn_connect(vconn); if (error == expect_connect_error) { if (!error) { connected = true; } else { stream_close(stream); vconn_close(vconn); return; } } else { CHECK_ERRNO(error, EAGAIN); } } if (read_hello && connected) { break; } vconn_run_wait(vconn); if (!connected) { vconn_connect_wait(vconn); } if (!read_hello) { stream_recv_wait(stream); } poll_block(); } stream_close(stream); CHECK_ERRNO(vconn_recv_block(vconn, &msg), EOF); vconn_close(vconn); }