diff options
author | Patrik Flykt <patrik.flykt@linux.intel.com> | 2017-05-19 16:22:47 +0300 |
---|---|---|
committer | Patrik Flykt <patrik.flykt@linux.intel.com> | 2017-05-30 10:34:15 +0300 |
commit | 5a67ed2403cae2632e71a5bbeb883ff077c44186 (patch) | |
tree | 6c2f91cad31dbe73c3fc1bb20e56e9cb43cc5e15 /src/libsystemd-network/test-ndisc-rs.c | |
parent | e82a19cb1833c64604c11f307a84cf998f4aeffe (diff) | |
download | systemd-5a67ed2403cae2632e71a5bbeb883ff077c44186.tar.gz |
test-ndisc-rs.c: Test Router Solicitation timer computation
Test ICMPv6 Router Solicitation exponential backoff timer by
computing the minimum and maximum values according to RFC 7559,
Section 2 and the algorithm itself described in RFC 3315, Section
14. Reset the sd_ndisc timer to trigger after a zero second delay,
which causes the ndisc timeout to be triggered immediately once
the caller of the "sending" function returns to the main loop.
Diffstat (limited to 'src/libsystemd-network/test-ndisc-rs.c')
-rw-r--r-- | src/libsystemd-network/test-ndisc-rs.c | 100 |
1 files changed, 100 insertions, 0 deletions
diff --git a/src/libsystemd-network/test-ndisc-rs.c b/src/libsystemd-network/test-ndisc-rs.c index b4a6539599..c3e1a8e340 100644 --- a/src/libsystemd-network/test-ndisc-rs.c +++ b/src/libsystemd-network/test-ndisc-rs.c @@ -27,6 +27,7 @@ #include "icmp6-util.h" #include "socket-util.h" #include "strv.h" +#include "ndisc-internal.h" static struct ether_addr mac_addr = { .ether_addr_octet = {'A', 'B', 'C', '1', '2', '3'} @@ -35,6 +36,7 @@ static struct ether_addr mac_addr = { static bool verbose = false; static sd_event_source *test_hangcheck; static int test_fd[2]; +static sd_ndisc *test_timeout_nd; typedef int (*send_ra_t)(uint8_t flags); static send_ra_t send_ra_function; @@ -237,6 +239,9 @@ static int send_ra(uint8_t flags) { } int icmp6_send_router_solicitation(int s, const struct ether_addr *ether_addr) { + if (!send_ra_function) + return 0; + return send_ra_function(0); } @@ -320,6 +325,100 @@ static void test_rs(void) { sd_event_unref(e); } +static int test_timeout_value(uint8_t flags) { + static int count = 0; + static usec_t last = 0; + sd_ndisc *nd = test_timeout_nd; + usec_t min, max; + char time_string_min[FORMAT_TIMESPAN_MAX]; + char time_string_nd[FORMAT_TIMESPAN_MAX]; + char time_string_max[FORMAT_TIMESPAN_MAX]; + + assert_se(nd); + assert_se(nd->event); + + if (++count >= 20) + sd_event_exit(nd->event, 0); + + if (last == 0) { + /* initial RT = IRT + RAND*IRT */ + min = NDISC_ROUTER_SOLICITATION_INTERVAL - + NDISC_ROUTER_SOLICITATION_INTERVAL / 10; + max = NDISC_ROUTER_SOLICITATION_INTERVAL + + NDISC_ROUTER_SOLICITATION_INTERVAL / 10; + } else { + /* next RT = 2*RTprev + RAND*RTprev */ + min = 2 * last - last / 10; + max = 2 * last + last / 10; + } + + /* final RT > MRT */ + if (last * 2 > NDISC_MAX_ROUTER_SOLICITATION_INTERVAL) { + min = NDISC_MAX_ROUTER_SOLICITATION_INTERVAL - + NDISC_MAX_ROUTER_SOLICITATION_INTERVAL / 10; + max = NDISC_MAX_ROUTER_SOLICITATION_INTERVAL + + NDISC_MAX_ROUTER_SOLICITATION_INTERVAL / 10; + } + + format_timespan(time_string_min, FORMAT_TIMESPAN_MAX, + min, USEC_PER_MSEC); + format_timespan(time_string_nd, FORMAT_TIMESPAN_MAX, + nd->retransmit_time, USEC_PER_MSEC); + format_timespan(time_string_max, FORMAT_TIMESPAN_MAX, + max, USEC_PER_MSEC); + + log_info("backoff timeout interval %2d %s%s <= %s <= %s", + count, + (last * 2 > NDISC_MAX_ROUTER_SOLICITATION_INTERVAL)? "(max) ": "", + time_string_min, time_string_nd, time_string_max); + + assert_se(min <= nd->retransmit_time); + assert_se(max >= nd->retransmit_time); + + last = nd->retransmit_time; + + assert_se(sd_event_source_set_time(nd->timeout_event_source, 0) >= 0); + + return 0; +} + +static void test_timeout(void) { + sd_event *e; + sd_ndisc *nd; + usec_t time_now = now(clock_boottime_or_monotonic()); + + if (verbose) + printf("* %s\n", __FUNCTION__); + + send_ra_function = test_timeout_value; + + assert_se(sd_event_new(&e) >= 0); + + assert_se(sd_ndisc_new(&nd) >= 0); + assert_se(nd); + + test_timeout_nd = nd; + + assert_se(sd_ndisc_attach_event(nd, e, 0) >= 0); + + assert_se(sd_ndisc_set_ifindex(nd, 42) >= 0); + assert_se(sd_ndisc_set_mac(nd, &mac_addr) >= 0); + + assert_se(sd_event_add_time(e, &test_hangcheck, clock_boottime_or_monotonic(), + time_now + 2U * USEC_PER_SEC, 0, + test_rs_hangcheck, NULL) >= 0); + + assert_se(sd_ndisc_start(nd) >= 0); + + sd_event_loop(e); + + test_hangcheck = sd_event_source_unref(test_hangcheck); + + nd = sd_ndisc_unref(nd); + + sd_event_unref(e); +} + int main(int argc, char *argv[]) { log_set_max_level(LOG_DEBUG); @@ -327,6 +426,7 @@ int main(int argc, char *argv[]) { log_open(); test_rs(); + test_timeout(); return 0; } |