X-Git-Url: http://git.onelab.eu/?a=blobdiff_plain;f=tests%2Ftest-vconn.c;h=ec66f862890b432387e8aba6823c38d0522691a3;hb=6dc5374435cc25bc4051b27bd52635e609a8872a;hp=948f30ad1f52cdbda359947662cc3eefb8693c57;hpb=dc68127607513267a2a3c732de55ffdecbc90757;p=sliver-openvswitch.git diff --git a/tests/test-vconn.c b/tests/test-vconn.c index 948f30ad1..ec66f8628 100644 --- a/tests/test-vconn.c +++ b/tests/test-vconn.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2009, 2010 Nicira Networks. + * Copyright (c) 2009, 2010, 2011, 2012, 2013, 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. @@ -21,6 +21,12 @@ #include #include #include +#include "command-line.h" +#include "fatal-signal.h" +#include "ofp-msgs.h" +#include "ofp-util.h" +#include "ofpbuf.h" +#include "openflow/openflow.h" #include "poll-loop.h" #include "socket-util.h" #include "stream.h" @@ -28,6 +34,7 @@ #include "timeval.h" #include "util.h" #include "vlog.h" +#include "ovstest.h" #undef NDEBUG #include @@ -54,8 +61,9 @@ static void check_errno(int a, int b, const char *as, const char *file, int line) { if (a != b) { + char *str_b = strdup(ovs_strerror(abs(b))); ovs_fatal(0, "%s:%d: %s is %d (%s) but should be %d (%s)", - file, line, as, a, strerror(abs(a)), b, strerror(abs(b))); + file, line, as, a, ovs_strerror(abs(a)), b, str_b); } } @@ -64,6 +72,14 @@ check_errno(int a, int b, const char *as, const char *file, int line) static void fpv_create(const char *type, struct fake_pvconn *fpv) { +#ifdef HAVE_OPENSSL + if (!strcmp(type, "ssl")) { + stream_ssl_set_private_key_file("testpki-privkey.pem"); + stream_ssl_set_certificate_file("testpki-cert.pem"); + stream_ssl_set_ca_cert_file("testpki-cacert.pem", false); + } +#endif + fpv->type = type; if (!strcmp(type, "unix")) { static int unix_count = 0; @@ -72,18 +88,19 @@ fpv_create(const char *type, struct fake_pvconn *fpv) bind_path = xasprintf("fake-pvconn.%d", unix_count++); fpv->pvconn_name = xasprintf("punix:%s", bind_path); fpv->vconn_name = xasprintf("unix:%s", bind_path); - CHECK_ERRNO(pstream_open(fpv->pvconn_name, &fpv->pstream), 0); + CHECK_ERRNO(pstream_open(fpv->pvconn_name, &fpv->pstream, + DSCP_DEFAULT), 0); free(bind_path); } else if (!strcmp(type, "tcp") || !strcmp(type, "ssl")) { - char *s, *method, *port, *save_ptr = NULL; + char *s, *port, *save_ptr = NULL; char *open_name; open_name = xasprintf("p%s:0:127.0.0.1", type); - CHECK_ERRNO(pstream_open(open_name, &fpv->pstream), 0); + CHECK_ERRNO(pstream_open(open_name, &fpv->pstream, DSCP_DEFAULT), 0); /* Extract bound port number from pstream name. */ s = xstrdup(pstream_get_name(fpv->pstream)); - method = strtok_r(s, ":", &save_ptr); + strtok_r(s, ":", &save_ptr); port = strtok_r(NULL, ":", &save_ptr); /* Save info. */ @@ -125,16 +142,35 @@ fpv_destroy(struct fake_pvconn *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(const char *type, int expected_error) +test_refuse_connection(int argc OVS_UNUSED, char *argv[]) { + const char *type = argv[1]; struct fake_pvconn fpv; struct vconn *vconn; + int error; fpv_create(type, &fpv); - CHECK_ERRNO(vconn_open(fpv.vconn_name, OFP_VERSION, &vconn), 0); + CHECK_ERRNO(vconn_open(fpv.vconn_name, 0, DSCP_DEFAULT, &vconn), 0); fpv_close(&fpv); vconn_run(vconn); - CHECK_ERRNO(vconn_connect(vconn), expected_error); + + error = vconn_connect_block(vconn); + if (!strcmp(type, "tcp")) { + if (error != ECONNRESET && error != EPIPE) { + ovs_fatal(0, "unexpected vconn_connect() return value %d (%s)", + error, ovs_strerror(error)); + } + } else if (!strcmp(type, "unix")) { + CHECK_ERRNO(error, EPIPE); + } 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); } @@ -143,17 +179,29 @@ test_refuse_connection(const char *type, int expected_error) * closes it immediately, and verifies that vconn_connect() reports * 'expected_error'. */ static void -test_accept_then_close(const char *type, int expected_error) +test_accept_then_close(int argc OVS_UNUSED, char *argv[]) { + const char *type = argv[1]; struct fake_pvconn fpv; struct vconn *vconn; + int error; fpv_create(type, &fpv); - CHECK_ERRNO(vconn_open(fpv.vconn_name, OFP_VERSION, &vconn), 0); + CHECK_ERRNO(vconn_open(fpv.vconn_name, 0, DSCP_DEFAULT, &vconn), 0); vconn_run(vconn); stream_close(fpv_accept(&fpv)); fpv_close(&fpv); - CHECK_ERRNO(vconn_connect(vconn), expected_error); + + error = vconn_connect_block(vconn); + if (!strcmp(type, "tcp") || !strcmp(type, "unix")) { + if (error != ECONNRESET && error != EPIPE) { + 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); } @@ -162,14 +210,16 @@ test_accept_then_close(const char *type, int expected_error) * reads the hello message from it, then closes the connection and verifies * that vconn_connect() reports 'expected_error'. */ static void -test_read_hello(const char *type, int expected_error) +test_read_hello(int argc OVS_UNUSED, char *argv[]) { + const char *type = 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, OFP_VERSION, &vconn), 0); + CHECK_ERRNO(vconn_open(fpv.vconn_name, 0, DSCP_DEFAULT, &vconn), 0); vconn_run(vconn); stream = fpv_accept(&fpv); fpv_destroy(&fpv); @@ -179,9 +229,12 @@ test_read_hello(const char *type, int expected_error) retval = stream_recv(stream, &hello, sizeof hello); if (retval == sizeof hello) { - CHECK(hello.version, OFP_VERSION); - CHECK(hello.type, OFPT_HELLO); - CHECK(hello.length, htons(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); @@ -195,7 +248,11 @@ test_read_hello(const char *type, int expected_error) poll_block(); } stream_close(stream); - CHECK_ERRNO(vconn_connect(vconn), expected_error); + 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); } @@ -215,7 +272,7 @@ test_send_hello(const char *type, const void *out, size_t out_size, size_t n_sent; fpv_create(type, &fpv); - CHECK_ERRNO(vconn_open(fpv.vconn_name, OFP_VERSION, &vconn), 0); + CHECK_ERRNO(vconn_open(fpv.vconn_name, 0, DSCP_DEFAULT, &vconn), 0); vconn_run(vconn); stream = fpv_accept(&fpv); fpv_destroy(&fpv); @@ -245,9 +302,12 @@ test_send_hello(const char *type, const void *out, size_t out_size, struct ofp_header hello; int retval = stream_recv(stream, &hello, sizeof hello); if (retval == sizeof hello) { - CHECK(hello.version, OFP_VERSION); - CHECK(hello.type, OFPT_HELLO); - CHECK(hello.length, htons(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); @@ -284,60 +344,61 @@ test_send_hello(const char *type, const void *out, size_t out_size, poll_block(); } stream_close(stream); - CHECK_ERRNO(vconn_recv(vconn, &msg), EOF); + CHECK_ERRNO(vconn_recv_block(vconn, &msg), EOF); vconn_close(vconn); } /* Try connecting and sending a normal hello, which should succeed. */ static void -test_send_plain_hello(const char *type) +test_send_plain_hello(int argc OVS_UNUSED, char *argv[]) { - struct ofp_header hello; + const char *type = argv[1]; + struct ofpbuf *hello; - hello.version = OFP_VERSION; - hello.type = OFPT_HELLO; - hello.length = htons(sizeof hello); - hello.xid = htonl(0x12345678); - test_send_hello(type, &hello, sizeof hello, 0); + hello = ofpraw_alloc_xid(OFPRAW_OFPT_HELLO, OFP13_VERSION, + htonl(0x12345678), 0); + test_send_hello(type, ofpbuf_data(hello), ofpbuf_size(hello), 0); + ofpbuf_delete(hello); } /* Try connecting and sending an extra-long hello, which should succeed (since * the specification says that implementations must accept and ignore extra * data). */ static void -test_send_long_hello(const char *type) +test_send_long_hello(int argc OVS_UNUSED, char *argv[]) { - struct ofp_header hello; - char buffer[sizeof hello * 2]; - - hello.version = OFP_VERSION; - hello.type = OFPT_HELLO; - hello.length = htons(sizeof buffer); - hello.xid = htonl(0x12345678); - memset(buffer, 0, sizeof buffer); - memcpy(buffer, &hello, sizeof hello); - test_send_hello(type, buffer, sizeof buffer, 0); + const char *type = argv[1]; + struct ofpbuf *hello; + enum { EXTRA_BYTES = 8 }; + + hello = ofpraw_alloc_xid(OFPRAW_OFPT_HELLO, OFP13_VERSION, + htonl(0x12345678), EXTRA_BYTES); + ofpbuf_put_zeros(hello, EXTRA_BYTES); + ofpmsg_update_length(hello); + test_send_hello(type, ofpbuf_data(hello), ofpbuf_size(hello), 0); + ofpbuf_delete(hello); } /* Try connecting and sending an echo request instead of a hello, which should * fail with EPROTO. */ static void -test_send_echo_hello(const char *type) +test_send_echo_hello(int argc OVS_UNUSED, char *argv[]) { - struct ofp_header echo; + const char *type = argv[1]; + struct ofpbuf *echo; - echo.version = OFP_VERSION; - echo.type = OFPT_ECHO_REQUEST; - echo.length = htons(sizeof echo); - echo.xid = htonl(0x89abcdef); - test_send_hello(type, &echo, sizeof echo, EPROTO); + echo = ofpraw_alloc_xid(OFPRAW_OFPT_ECHO_REQUEST, OFP13_VERSION, + htonl(0x12345678), 0); + test_send_hello(type, ofpbuf_data(echo), ofpbuf_size(echo), EPROTO); + ofpbuf_delete(echo); } /* Try connecting and sending a hello packet that has its length field as 0, * which should fail with EPROTO. */ static void -test_send_short_hello(const char *type) +test_send_short_hello(int argc OVS_UNUSED, char *argv[]) { + const char *type = argv[1]; struct ofp_header hello; memset(&hello, 0, sizeof hello); @@ -347,59 +408,41 @@ test_send_short_hello(const char *type) /* Try connecting and sending a hello packet that has a bad version, which * should fail with EPROTO. */ static void -test_send_invalid_version_hello(const char *type) +test_send_invalid_version_hello(int argc OVS_UNUSED, char *argv[]) { - struct ofp_header hello; - - hello.version = OFP_VERSION - 1; - hello.type = OFPT_HELLO; - hello.length = htons(sizeof hello); - hello.xid = htonl(0x12345678); - test_send_hello(type, &hello, sizeof hello, EPROTO); + const char *type = argv[1]; + struct ofpbuf *hello; + + hello = ofpraw_alloc_xid(OFPRAW_OFPT_HELLO, OFP13_VERSION, + htonl(0x12345678), 0); + ((struct ofp_header *) ofpbuf_data(hello))->version = 0; + test_send_hello(type, ofpbuf_data(hello), ofpbuf_size(hello), EPROTO); + ofpbuf_delete(hello); } -int -main(int argc UNUSED, char *argv[]) +static const struct command commands[] = { + {"refuse-connection", 1, 1, test_refuse_connection}, + {"accept-then-close", 1, 1, test_accept_then_close}, + {"read-hello", 1, 1, test_read_hello}, + {"send-plain-hello", 1, 1, test_send_plain_hello}, + {"send-long-hello", 1, 1, test_send_long_hello}, + {"send-echo-hello", 1, 1, test_send_echo_hello}, + {"send-short-hello", 1, 1, test_send_short_hello}, + {"send-invalid-version-hello", 1, 1, test_send_invalid_version_hello}, + {NULL, 0, 0, NULL}, +}; + +static void +test_vconn_main(int argc, char *argv[]) { set_program_name(argv[0]); - time_init(); - vlog_init(); - signal(SIGPIPE, SIG_IGN); + vlog_set_levels(NULL, VLF_ANY_FACILITY, VLL_EMER); + vlog_set_levels(NULL, VLF_CONSOLE, VLL_DBG); + fatal_ignore_sigpipe(); time_alarm(10); - test_refuse_connection("unix", EPIPE); - test_accept_then_close("unix", EPIPE); - test_read_hello("unix", ECONNRESET); - test_send_plain_hello("unix"); - test_send_long_hello("unix"); - test_send_echo_hello("unix"); - test_send_short_hello("unix"); - test_send_invalid_version_hello("unix"); - - test_accept_then_close("tcp", ECONNRESET); - test_refuse_connection("tcp", ECONNRESET); - test_read_hello("tcp", ECONNRESET); - test_send_plain_hello("tcp"); - test_send_long_hello("tcp"); - test_send_echo_hello("tcp"); - test_send_short_hello("tcp"); - test_send_invalid_version_hello("tcp"); - -#ifdef HAVE_OPENSSL - stream_ssl_set_private_key_file("testpki-privkey.pem"); - stream_ssl_set_certificate_file("testpki-cert.pem"); - stream_ssl_set_ca_cert_file("testpki-cacert.pem", false); - - test_accept_then_close("ssl", EPROTO); - test_refuse_connection("ssl", ECONNRESET); - test_read_hello("ssl", ECONNRESET); - test_send_plain_hello("ssl"); - test_send_long_hello("ssl"); - test_send_echo_hello("ssl"); - test_send_short_hello("ssl"); - test_send_invalid_version_hello("ssl"); -#endif /* HAVE_OPENSSL */ - - return 0; + run_command(argc - 1, argv + 1, commands); } + +OVSTEST_REGISTER("test-vconn", test_vconn_main);