diff options
author | Yves-Alexis Perez <corsac@debian.org> | 2015-04-11 22:03:59 +0200 |
---|---|---|
committer | Yves-Alexis Perez <corsac@debian.org> | 2015-04-11 22:30:17 +0200 |
commit | 8404fb0212f9fb77bc53b23004b829b488430700 (patch) | |
tree | 23876c7540d138f58a6a7d90793ccf9004f6afd2 /src/libhydra/plugins/kernel_netlink/suites | |
parent | 1b7c683a32c62b6e08ad7bf5af39b9f4edd634f3 (diff) | |
download | vyos-strongswan-8404fb0212f9fb77bc53b23004b829b488430700.tar.gz vyos-strongswan-8404fb0212f9fb77bc53b23004b829b488430700.zip |
Imported Upstream version 5.3.0
Diffstat (limited to 'src/libhydra/plugins/kernel_netlink/suites')
-rw-r--r-- | src/libhydra/plugins/kernel_netlink/suites/test_socket.c | 302 |
1 files changed, 302 insertions, 0 deletions
diff --git a/src/libhydra/plugins/kernel_netlink/suites/test_socket.c b/src/libhydra/plugins/kernel_netlink/suites/test_socket.c new file mode 100644 index 000000000..3e8facd0a --- /dev/null +++ b/src/libhydra/plugins/kernel_netlink/suites/test_socket.c @@ -0,0 +1,302 @@ +/* + * Copyright (C) 2014 Martin Willi + * Copyright (C) 2014 revosec AG + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * for more details. + */ + +#include <test_suite.h> + +#include <threading/thread.h> + +#include "../kernel_netlink_shared.h" + +/** + * Netlink message drop configuration + */ +static int drop_interval = 0; + +/** + * Netlink message drop hook + */ +bool netlink_msg_loss(struct nlmsghdr *hdr) +{ + static refcount_t i; + + if (drop_interval) + { + return ref_get(&i) % drop_interval == drop_interval - 1; + } + return FALSE; +} + +START_TEST(test_echo) +{ + netlink_socket_t *s; + struct nlmsghdr *out; + struct rtmsg *msg; + char dst[] = { + 127,0,0,1 + }; + size_t len; + netlink_buf_t request = { + .hdr = { + .nlmsg_len = NLMSG_LENGTH(sizeof(struct rtmsg)), + .nlmsg_flags = NLM_F_REQUEST, + .nlmsg_type = RTM_GETROUTE, + }, + }; + + msg = NLMSG_DATA(&request.hdr); + msg->rtm_family = AF_INET; + netlink_add_attribute(&request.hdr, RTA_DST, + chunk_from_thing(dst), sizeof(request)); + + s = netlink_socket_create(NETLINK_ROUTE, NULL, _i != 0); + + ck_assert(s->send(s, &request.hdr, &out, &len) == SUCCESS); + ck_assert_int_eq(out->nlmsg_type, RTM_NEWROUTE); + free(out); + s->destroy(s); +} +END_TEST + +START_TEST(test_echo_dump) +{ + netlink_socket_t *s; + struct nlmsghdr *out, *current; + struct rtgenmsg *msg; + size_t len; + netlink_buf_t request = { + .hdr = { + .nlmsg_len = NLMSG_LENGTH(sizeof(struct rtgenmsg)), + .nlmsg_flags = NLM_F_REQUEST | NLM_F_MATCH | NLM_F_ROOT, + .nlmsg_type = RTM_GETLINK, + }, + }; + + s = netlink_socket_create(NETLINK_ROUTE, NULL, _i != 0); + msg = NLMSG_DATA(&request.hdr); + msg->rtgen_family = AF_UNSPEC; + + ck_assert(s->send(s, &request.hdr, &out, &len) == SUCCESS); + current = out; + while (TRUE) + { + ck_assert(NLMSG_OK(current, len)); + if (current->nlmsg_type == NLMSG_DONE) + { + break; + } + ck_assert_int_eq(current->nlmsg_type, RTM_NEWLINK); + current = NLMSG_NEXT(current, len); + } + free(out); + s->destroy(s); +} +END_TEST + +CALLBACK(stress, void*, + netlink_socket_t *s) +{ + struct nlmsghdr *out; + struct rtmsg *msg; + char dst[] = { + 127,0,0,1 + }; + size_t len; + int i; + netlink_buf_t request = { + .hdr = { + .nlmsg_len = NLMSG_LENGTH(sizeof(struct rtmsg)), + .nlmsg_flags = NLM_F_REQUEST, + .nlmsg_type = RTM_GETROUTE, + }, + }; + + for (i = 0; i < 10; i++) + { + msg = NLMSG_DATA(&request.hdr); + msg->rtm_family = AF_INET; + netlink_add_attribute(&request.hdr, RTA_DST, + chunk_from_thing(dst), sizeof(request)); + + ck_assert(s->send(s, &request.hdr, &out, &len) == SUCCESS); + ck_assert_int_eq(out->nlmsg_type, RTM_NEWROUTE); + free(out); + } + return NULL; +} + +CALLBACK(stress_dump, void*, + netlink_socket_t *s) +{ + struct nlmsghdr *out, *current; + struct rtgenmsg *msg; + size_t len; + int i; + netlink_buf_t request = { + .hdr = { + .nlmsg_len = NLMSG_LENGTH(sizeof(struct rtgenmsg)), + .nlmsg_flags = NLM_F_REQUEST | NLM_F_MATCH | NLM_F_ROOT, + .nlmsg_type = RTM_GETLINK, + }, + }; + + msg = NLMSG_DATA(&request.hdr); + msg->rtgen_family = AF_UNSPEC; + + for (i = 0; i < 10; i++) + { + ck_assert(s->send(s, &request.hdr, &out, &len) == SUCCESS); + current = out; + while (TRUE) + { + ck_assert(NLMSG_OK(current, len)); + if (current->nlmsg_type == NLMSG_DONE) + { + break; + } + ck_assert_int_eq(current->nlmsg_type, RTM_NEWLINK); + current = NLMSG_NEXT(current, len); + } + free(out); + } + return NULL; +} + +START_TEST(test_stress) +{ + thread_t *threads[10]; + netlink_socket_t *s; + int i; + + s = netlink_socket_create(NETLINK_ROUTE, NULL, _i != 0); + for (i = 0; i < countof(threads); i++) + { + threads[i] = thread_create(stress, s); + } + for (i = 0; i < countof(threads); i++) + { + threads[i]->join(threads[i]); + } + s->destroy(s); +} +END_TEST + +START_TEST(test_stress_dump) +{ + thread_t *threads[10]; + netlink_socket_t *s; + int i; + + s = netlink_socket_create(NETLINK_ROUTE, NULL, _i != 0); + for (i = 0; i < countof(threads); i++) + { + threads[i] = thread_create(stress_dump, s); + } + for (i = 0; i < countof(threads); i++) + { + threads[i]->join(threads[i]); + } + s->destroy(s); +} +END_TEST + +START_TEST(test_retransmit_success) +{ + netlink_socket_t *s; + struct nlmsghdr *out; + struct rtgenmsg *msg; + size_t len; + netlink_buf_t request = { + .hdr = { + .nlmsg_len = NLMSG_LENGTH(sizeof(struct rtgenmsg)), + .nlmsg_flags = NLM_F_REQUEST | NLM_F_MATCH | NLM_F_ROOT, + .nlmsg_type = RTM_GETLINK, + }, + }; + + drop_interval = 2; + + lib->settings->set_int(lib->settings, + "%s.plugins.kernel-netlink.timeout", 100, lib->ns); + lib->settings->set_int(lib->settings, + "%s.plugins.kernel-netlink.retries", 1, lib->ns); + + s = netlink_socket_create(NETLINK_ROUTE, NULL, _i != 0); + msg = NLMSG_DATA(&request.hdr); + msg->rtgen_family = AF_UNSPEC; + + ck_assert(s->send(s, &request.hdr, &out, &len) == SUCCESS); + free(out); + s->destroy(s); + + drop_interval = 0; +} +END_TEST + +START_TEST(test_retransmit_fail) +{ + netlink_socket_t *s; + struct nlmsghdr *out; + struct rtgenmsg *msg; + size_t len; + netlink_buf_t request = { + .hdr = { + .nlmsg_len = NLMSG_LENGTH(sizeof(struct rtgenmsg)), + .nlmsg_flags = NLM_F_REQUEST | NLM_F_MATCH | NLM_F_ROOT, + .nlmsg_type = RTM_GETLINK, + }, + }; + + drop_interval = 1; + + lib->settings->set_int(lib->settings, + "%s.plugins.kernel-netlink.timeout", 50, lib->ns); + lib->settings->set_int(lib->settings, + "%s.plugins.kernel-netlink.retries", 3, lib->ns); + + s = netlink_socket_create(NETLINK_ROUTE, NULL, _i != 0); + msg = NLMSG_DATA(&request.hdr); + msg->rtgen_family = AF_UNSPEC; + + ck_assert(s->send(s, &request.hdr, &out, &len) == OUT_OF_RES); + s->destroy(s); + + drop_interval = 0; +} +END_TEST + +Suite *socket_suite_create() +{ + Suite *s; + TCase *tc; + + s = suite_create("netlink socket"); + + tc = tcase_create("echo"); + tcase_add_loop_test(tc, test_echo, 0, 2); + tcase_add_loop_test(tc, test_echo_dump, 0, 2); + suite_add_tcase(s, tc); + + tc = tcase_create("stress"); + tcase_add_loop_test(tc, test_stress, 0, 2); + tcase_add_loop_test(tc, test_stress_dump, 0, 2); + suite_add_tcase(s, tc); + + tc = tcase_create("retransmit"); + tcase_add_loop_test(tc, test_retransmit_success, 0, 2); + tcase_add_loop_test(tc, test_retransmit_fail, 0, 2); + suite_add_tcase(s, tc); + + return s; +} |