diff --git a/includes/internal/ping/handlers.h b/includes/internal/ping/handlers.h new file mode 100644 index 0000000..ba1bc9c --- /dev/null +++ b/includes/internal/ping/handlers.h @@ -0,0 +1,12 @@ +#ifndef PING_HANDLERS_H +#define PING_HANDLERS_H + +#include "icmp.h" +#include "internal/ping/ping_state.h" + +void ping_handle_echo_reply(struct ping_state *state, + const icmp_reply_t *reply); +void ping_handle_icmp_error(struct ping_state *state, + const icmp_reply_t *reply); + +#endif diff --git a/includes/internal/ping/output.h b/includes/internal/ping/output.h index 4c13923..8a49dc7 100644 --- a/includes/internal/ping/output.h +++ b/includes/internal/ping/output.h @@ -10,7 +10,8 @@ void ping_output_start(const struct ping_config *config, struct destinations *dest, size_t payload_bytes); void ping_output_packet(const icmp_reply_t *reply, uint16_t seq, - int64_t rtt_ns, size_t payload_bytes, const struct ping_config *config); + int64_t rtt_ns, size_t payload_bytes, const struct ping_config *config, + int is_dup); void ping_output_error(const icmp_reply_t *reply, const icmp_offending_packet_t *offending, uint16_t seq, const struct ping_config *config); diff --git a/includes/internal/ping/ping_state.h b/includes/internal/ping/ping_state.h index f2725a5..b2c4b57 100644 --- a/includes/internal/ping/ping_state.h +++ b/includes/internal/ping/ping_state.h @@ -23,6 +23,7 @@ struct ping_state { volatile sig_atomic_t send_flag; volatile sig_atomic_t stop_flag; size_t nb_errors; + int ts_in_payload; }; #endif diff --git a/includes/internal/ping/tracker.h b/includes/internal/ping/tracker.h index dd0e49a..be2d82b 100644 --- a/includes/internal/ping/tracker.h +++ b/includes/internal/ping/tracker.h @@ -3,28 +3,16 @@ #include #include -#include - -#include "internal/ping/tracker_flags.h" - -#define PING_TRACKER_SLOTS 128 - -struct ping_tracker_slot { - struct timespec ts; - uint8_t flags; -}; struct ping_tracker { - struct ping_tracker_slot slots[PING_TRACKER_SLOTS]; - size_t nb_sent; - size_t nb_recv; + uint8_t rcvd[UINT16_MAX / 8]; + size_t nb_sent; + size_t nb_recv; + size_t nb_dup; }; -void ping_tracker_init(struct ping_tracker *t); -void ping_tracker_record_send(struct ping_tracker *t, uint16_t seq, const - struct timespec *ts); -int64_t ping_tracker_record_recv(struct ping_tracker *t, uint16_t seq, - const struct timespec *ts); - +void ping_tracker_init(struct ping_tracker *t); +void ping_tracker_record_send(struct ping_tracker *t, uint16_t seq); +int ping_tracker_record_recv(struct ping_tracker *t, uint16_t seq); #endif diff --git a/includes/ping/ft_ping_const.h b/includes/ping/ft_ping_const.h index 9ff04f8..b722d4d 100644 --- a/includes/ping/ft_ping_const.h +++ b/includes/ping/ft_ping_const.h @@ -1,6 +1,8 @@ #ifndef FT_PING_CONST #define FT_PING_CONST +#include + /* Default configuration values */ #define DEFAULT_COUNT 0 #define DEFAULT_PRELOAD 1 @@ -13,4 +15,7 @@ #define MAX_PACKET_SIZE 65507 #define MAX_TTL 255 +/* Minimum payload size to embed a send timestamp */ +#define PING_TIMESTAMP_SIZE ((size_t)sizeof(struct timespec)) + #endif diff --git a/src/ping/Makefile.am b/src/ping/Makefile.am index 12f6b1d..6506e55 100644 --- a/src/ping/Makefile.am +++ b/src/ping/Makefile.am @@ -69,6 +69,8 @@ libping_core_la_SOURCES = \ core/loop.c \ core/send.c \ core/callback.c \ + core/reply.c \ + core/error.c \ tracker/init.c \ tracker/record_send.c \ tracker/record_recv.c \ diff --git a/src/ping/core/callback.c b/src/ping/core/callback.c index a97c454..1bc67f8 100644 --- a/src/ping/core/callback.c +++ b/src/ping/core/callback.c @@ -1,17 +1,5 @@ #include "icmp_types.h" -#include "ping/ft_ping_flags.h" -#include "internal/ping/output.h" - -/* Forward declarations */ -static int extract_our_echo(const icmp_reply_t *reply, uint16_t our_id, - struct in_addr dest, uint16_t *seq_out); -static void handle_echo_reply(struct ping_state *state, - const icmp_reply_t *reply); -static int extract_our_error(const icmp_reply_t *reply, uint16_t our_id, - struct in_addr dest, icmp_offending_packet_t *out, uint16_t *seq_out); -static void handle_icmp_error(struct ping_state *state, - const icmp_reply_t *reply); -/* -------------------- */ +#include "internal/ping/handlers.h" void ping_callback(const icmp_reply_t *reply, void *userdata) @@ -20,69 +8,8 @@ ping_callback(const icmp_reply_t *reply, void *userdata) state = (struct ping_state *)userdata; if (ICMP_TYPE_ECHO_REPLY == reply->type) - handle_echo_reply(state, reply); + ping_handle_echo_reply(state, reply); else if (ICMP_TYPE_TIME_EXCEEDED == reply->type || ICMP_TYPE_DEST_UNREACHABLE == reply->type) - handle_icmp_error(state, reply); -} - -static int -extract_our_echo(const icmp_reply_t *reply, uint16_t our_id, - struct in_addr dest, uint16_t *seq_out) -{ - uint16_t id; - uint16_t seq; - - if (0 > icmp_reply_id_seq(reply, &id, &seq)) - return 0; - if (our_id != id || reply->from.s_addr != dest.s_addr) - return 0; - *seq_out = seq; - return 1; -} - -static void -handle_echo_reply(struct ping_state *state, const icmp_reply_t *reply) -{ - uint16_t seq; - int64_t rtt; - - if (0 == extract_our_echo(reply, state->id, state->dest, &seq)) - return; - rtt = ping_tracker_record_recv(state->tracker, seq, &reply->timestamp); - if (0 > rtt) - return; - ping_stats_update(state->stats, rtt); - if (HAS_FLAG(state->config->flags, FLAG_FLOOD)) - ping_output_flood_erase(); - else - ping_output_packet(reply, seq, rtt, state->config->packet_size, - state->config); -} - -static int -extract_our_error(const icmp_reply_t *reply, uint16_t our_id, - struct in_addr dest, icmp_offending_packet_t *out, uint16_t *seq_out) -{ - if ((0 > icmp_error_extract_offending(reply, out)) - || ICMP_TYPE_ECHO_REQUEST != out->icmp_type - || our_id != out->rest.echo.id || out->dst.s_addr != dest.s_addr) - return 0; - *seq_out = out->rest.echo.seq; - return 1; -} - -static void -handle_icmp_error(struct ping_state *state, const icmp_reply_t *reply) -{ - icmp_offending_packet_t offending; - uint16_t seq; - - if (0 == extract_our_error(reply, state->id, state->dest, &offending, &seq)) - return; - if (0 > ping_tracker_record_recv(state->tracker, seq, &reply->timestamp)) - return; - state->nb_errors++; - if (!HAS_FLAG(state->config->flags, FLAG_QUIET)) - ping_output_error(reply, &offending, seq, state->config); + ping_handle_icmp_error(state, reply); } diff --git a/src/ping/core/error.c b/src/ping/core/error.c new file mode 100644 index 0000000..b929750 --- /dev/null +++ b/src/ping/core/error.c @@ -0,0 +1,37 @@ +#include "icmp.h" +#include "icmp_types.h" +#include "ping/ft_ping_flags.h" +#include "internal/ping/handlers.h" +#include "internal/ping/output.h" + +/* Forward declarations */ +static int extract_our_error(const icmp_reply_t *reply, uint16_t our_id, + struct in_addr dest, icmp_offending_packet_t *out, uint16_t *seq_out); +/* -------------------- */ + +void +ping_handle_icmp_error(struct ping_state *state, const icmp_reply_t *reply) +{ + icmp_offending_packet_t offending; + uint16_t seq; + + if (0 == extract_our_error(reply, state->id, state->dest, &offending, &seq)) + return; + if (0 == ping_tracker_record_recv(state->tracker, seq)) + return; + state->nb_errors++; + if (!HAS_FLAG(state->config->flags, FLAG_QUIET)) + ping_output_error(reply, &offending, seq, state->config); +} + +static int +extract_our_error(const icmp_reply_t *reply, uint16_t our_id, + struct in_addr dest, icmp_offending_packet_t *out, uint16_t *seq_out) +{ + if ((0 > icmp_error_extract_offending(reply, out)) + || ICMP_TYPE_ECHO_REQUEST != out->icmp_type + || our_id != out->rest.echo.id || out->dst.s_addr != dest.s_addr) + return 0; + *seq_out = out->rest.echo.seq; + return 1; +} diff --git a/src/ping/core/ping.c b/src/ping/core/ping.c index 1fbf6a7..9c0d34b 100644 --- a/src/ping/core/ping.c +++ b/src/ping/core/ping.c @@ -3,6 +3,7 @@ #include #include "version_gen.h" +#include "ping/ft_ping_const.h" #include "ping/ft_ping_flags.h" #include "internal/ping/output.h" #include "internal/ping/scheduler.h" @@ -108,6 +109,7 @@ ping_init_state(struct ping_state *state, struct ping_stats *stats, state->tracker = tracker; state->stats = stats; state->handle = handle; + state->ts_in_payload = (config->packet_size >= PING_TIMESTAMP_SIZE); icmp_get_time(&state->start_time); } diff --git a/src/ping/core/reply.c b/src/ping/core/reply.c new file mode 100644 index 0000000..9b2e255 --- /dev/null +++ b/src/ping/core/reply.c @@ -0,0 +1,56 @@ +#include + +#include "icmp.h" +#include "ping/ft_ping_const.h" +#include "ping/ft_ping_flags.h" +#include "internal/ping/handlers.h" +#include "internal/ping/output.h" + +/* Forward declarations */ +static int extract_our_echo(const icmp_reply_t *reply, uint16_t our_id, + struct in_addr dest, uint16_t *seq_out); +/* -------------------- */ + +void +ping_handle_echo_reply(struct ping_state *state, const icmp_reply_t *reply) +{ + uint16_t seq; + int is_new; + int64_t rtt_ns; + struct timespec send_ts; + + if (0 == extract_our_echo(reply, state->id, state->dest, &seq)) + return; + is_new = ping_tracker_record_recv(state->tracker, seq); + rtt_ns = -1; + if (state->ts_in_payload && reply->payload_len >= PING_TIMESTAMP_SIZE) + { + memcpy(&send_ts, reply->payload, sizeof(send_ts)); + rtt_ns = icmp_time_diff_ns(&send_ts, &reply->timestamp); + if (is_new) + ping_stats_update(state->stats, rtt_ns); + } + if (HAS_FLAG(state->config->flags, FLAG_FLOOD)) + { + if (is_new) + ping_output_flood_erase(); + return; + } + ping_output_packet(reply, seq, rtt_ns, state->config->packet_size, + state->config, !is_new); +} + +static int +extract_our_echo(const icmp_reply_t *reply, uint16_t our_id, + struct in_addr dest, uint16_t *seq_out) +{ + uint16_t id; + uint16_t seq; + + if (0 > icmp_reply_id_seq(reply, &id, &seq)) + return 0; + if (our_id != id || reply->from.s_addr != dest.s_addr) + return 0; + *seq_out = seq; + return 1; +} diff --git a/src/ping/core/send.c b/src/ping/core/send.c index 3aeb7d0..c112d7b 100644 --- a/src/ping/core/send.c +++ b/src/ping/core/send.c @@ -12,10 +12,10 @@ #include "ping/ft_ping_flags.h" /* Forward declarations */ -static inline void fill_payload(uint8_t *payload, size_t len, const struct - ping_config *config); +static inline void fill_payload(uint8_t *payload, size_t len, + const struct ping_config *config, int ts_in_payload); static int ping_send_one(struct ping_state *state, uint16_t seq, - const uint8_t *payload, size_t payload_len, struct timespec *ts); + uint8_t *payload, size_t payload_len, struct timespec *ts); /* -------------------- */ void @@ -26,14 +26,14 @@ do_send(struct ping_state *state, size_t payload_len) int ret; state->send_flag = 0; - fill_payload(payload, payload_len, state->config); + fill_payload(payload, payload_len, state->config, state->ts_in_payload); ret = ping_send_one(state, state->seq, payload, payload_len, &ts); if (-1 == ret) dprintf(STDERR_FILENO, "%s: %s\n", g_prog_name, icmp_strerror(state->handle)); else if (0 == ret) { - ping_tracker_record_send(state->tracker, state->seq, &ts); + ping_tracker_record_send(state->tracker, state->seq); state->seq++; } @@ -49,12 +49,14 @@ do_send(struct ping_state *state, size_t payload_len) static int ping_send_one(struct ping_state *state, uint16_t seq, - const uint8_t *payload, size_t payload_len, struct timespec *ts) + uint8_t *payload, size_t payload_len, struct timespec *ts) { int ret; if (0 != icmp_get_time(ts)) return -1; + if (state->ts_in_payload) + memcpy(payload, ts, sizeof(*ts)); ret = icmp_send_echo(state->handle, state->dest, state->id, @@ -69,16 +71,21 @@ ping_send_one(struct ping_state *state, uint16_t seq, } static inline void -fill_payload(uint8_t *payload, size_t len, const struct ping_config *config) +fill_payload(uint8_t *payload, size_t len, const struct ping_config *config, + int ts_in_payload) { + size_t offset; + size_t i; + + offset = ts_in_payload ? PING_TIMESTAMP_SIZE : 0; if (0 == config->pattern_len) { - for (size_t i = 0; i < len; ++i) - payload[i] = (uint8_t)('a' + (i % 26)); + for (i = offset; i < len; ++i) + payload[i] = (uint8_t)('a' + ((i - offset) % 26)); } else { - for (size_t i = 0; i < len; ++i) - payload[i] = config->pattern[i % config->pattern_len]; + for (i = offset; i < len; ++i) + payload[i] = config->pattern[(i - offset) % config->pattern_len]; } } diff --git a/src/ping/output/packet.c b/src/ping/output/packet.c index 36568a1..1c7322e 100644 --- a/src/ping/output/packet.c +++ b/src/ping/output/packet.c @@ -6,17 +6,27 @@ void ping_output_packet(const icmp_reply_t *reply, uint16_t seq, - int64_t rtt_ns, size_t payload_bytes, const struct ping_config *config) + int64_t rtt_ns, size_t payload_bytes, const struct ping_config *config, + int is_dup) { char from_str[INET_ADDRSTRLEN]; if (HAS_FLAG(config->flags, FLAG_QUIET | FLAG_FLOOD)) return; inet_ntop(AF_INET, &reply->from, from_str, sizeof(from_str)); - printf("%zu bytes from %s: icmp_seq=%u ttl=%u time=%.3f ms\n", - payload_bytes + 8, - from_str, - (unsigned int)seq, - (unsigned int)reply->ttl, - (double)rtt_ns / 1e6); + if (0 <= rtt_ns) + printf("%zu bytes from %s: icmp_seq=%u ttl=%u time=%.3f ms%s\n", + payload_bytes + 8, + from_str, + (unsigned int)seq, + (unsigned int)reply->ttl, + (double)rtt_ns / 1e6, + is_dup ? " (DUP!)" : ""); + else + printf("%zu bytes from %s: icmp_seq=%u ttl=%u%s\n", + payload_bytes + 8, + from_str, + (unsigned int)seq, + (unsigned int)reply->ttl, + is_dup ? " (DUP!)" : ""); } diff --git a/src/ping/output/summary.c b/src/ping/output/summary.c index cac4b87..6161409 100644 --- a/src/ping/output/summary.c +++ b/src/ping/output/summary.c @@ -22,7 +22,7 @@ ping_output_summary(const struct ping_state *state, ok_recv = state->tracker->nb_recv - errors; printf("--- %s ping statistics ---\n", dest->dom); print_loss_line(sent, ok_recv, errors); - if (0 < ok_recv) + if (0 < state->stats->count) print_rtt_line(state->stats); } diff --git a/src/ping/tracker/record_recv.c b/src/ping/tracker/record_recv.c index f8e9974..be6b4a9 100644 --- a/src/ping/tracker/record_recv.c +++ b/src/ping/tracker/record_recv.c @@ -1,17 +1,19 @@ -#include "icmp.h" #include "internal/ping/tracker.h" -int64_t -ping_tracker_record_recv(struct ping_tracker *t, uint16_t seq, - const struct timespec *ts) +int +ping_tracker_record_recv(struct ping_tracker *t, uint16_t seq) { - struct ping_tracker_slot *slot; + uint8_t *byte; + uint8_t bit; - slot = &t->slots[seq % PING_TRACKER_SLOTS]; - if ((slot->flags & (TRACKER_SLOT_USED | TRACKER_SLOT_ACKED)) - != TRACKER_SLOT_USED) - return (-1); - slot->flags |= TRACKER_SLOT_ACKED; + byte = &t->rcvd[seq >> 3]; + bit = (uint8_t)(1u << (seq & 7u)); /* 7 == 0b111 */ + if (*byte & bit) + { + t->nb_dup++; + return (0); + } + *byte |= bit; t->nb_recv++; - return (icmp_time_diff_ns(&slot->ts, ts)); + return (1); } diff --git a/src/ping/tracker/record_send.c b/src/ping/tracker/record_send.c index f0ea2d4..33d35cd 100644 --- a/src/ping/tracker/record_send.c +++ b/src/ping/tracker/record_send.c @@ -1,13 +1,8 @@ +#include "compiler.h" #include "internal/ping/tracker.h" void -ping_tracker_record_send(struct ping_tracker *t, uint16_t seq, - const struct timespec *ts) +ping_tracker_record_send(struct ping_tracker *t, uint16_t seq __unused) { - struct ping_tracker_slot *slot; - - slot = &t->slots[seq % PING_TRACKER_SLOTS]; - slot->ts = *ts; - slot->flags = TRACKER_SLOT_USED; t->nb_sent++; } diff --git a/tests/ping/tracker/test_tracker.c b/tests/ping/tracker/test_tracker.c index f205cb7..974e1f3 100644 --- a/tests/ping/tracker/test_tracker.c +++ b/tests/ping/tracker/test_tracker.c @@ -2,99 +2,65 @@ #include #include "internal/ping/tracker.h" -static struct timespec -make_ts(long sec, long nsec) -{ - struct timespec ts; - - ts.tv_sec = sec; - ts.tv_nsec = nsec; - return (ts); -} - Test(ping_tracker, init) { - struct ping_tracker t; + struct ping_tracker t; ping_tracker_init(&t); cr_assert_eq(t.nb_sent, (size_t)0); cr_assert_eq(t.nb_recv, (size_t)0); + cr_assert_eq(t.nb_dup, (size_t)0); } Test(ping_tracker, basic_send_recv) { struct ping_tracker t; - struct timespec ts_send; - struct timespec ts_recv; - int64_t rtt; + int accepted; ping_tracker_init(&t); - ts_send = make_ts(1, 0); - ts_recv = make_ts(1, 10000000); /* 10 ms later */ - ping_tracker_record_send(&t, 1, &ts_send); - rtt = ping_tracker_record_recv(&t, 1, &ts_recv); - cr_assert_eq(rtt, (int64_t)10000000, "Expected RTT of 10ms in ns"); + ping_tracker_record_send(&t, 1); + accepted = ping_tracker_record_recv(&t, 1); + cr_assert_eq(accepted, 1); cr_assert_eq(t.nb_sent, (size_t)1); cr_assert_eq(t.nb_recv, (size_t)1); + cr_assert_eq(t.nb_dup, (size_t)0); } -Test(ping_tracker, double_recv_ignored) +Test(ping_tracker, double_recv_is_dup) { struct ping_tracker t; - struct timespec ts_send; - struct timespec ts_recv; - int64_t rtt; + int accepted; ping_tracker_init(&t); - ts_send = make_ts(0, 0); - ts_recv = make_ts(0, 5000000); - ping_tracker_record_send(&t, 5, &ts_send); - rtt = ping_tracker_record_recv(&t, 5, &ts_recv); - cr_assert(rtt >= 0, "First recv should succeed"); - rtt = ping_tracker_record_recv(&t, 5, &ts_recv); - cr_assert_eq(rtt, (int64_t)-1, "Duplicate recv should return -1"); + ping_tracker_record_send(&t, 5); + accepted = ping_tracker_record_recv(&t, 5); + cr_assert_eq(accepted, 1, "First recv should be accepted"); + accepted = ping_tracker_record_recv(&t, 5); + cr_assert_eq(accepted, 0, "Duplicate recv should return 0"); cr_assert_eq(t.nb_recv, (size_t)1); + cr_assert_eq(t.nb_dup, (size_t)1); } -Test(ping_tracker, unknown_seq_returns_minus_one) +Test(ping_tracker, unknown_seq_accepted) { struct ping_tracker t; - struct timespec ts; - int64_t rtt; + int accepted; ping_tracker_init(&t); - ts = make_ts(0, 0); - rtt = ping_tracker_record_recv(&t, 42, &ts); - cr_assert_eq(rtt, (int64_t)-1); -} - -Test(ping_tracker, wraparound_seq) -{ - struct ping_tracker t; - struct timespec ts_send; - struct timespec ts_recv; - int64_t rtt; - - ping_tracker_init(&t); - ts_send = make_ts(0, 0); - ts_recv = make_ts(0, 1000000); - /* seq 128 maps to slot 0 */ - ping_tracker_record_send(&t, 128, &ts_send); - rtt = ping_tracker_record_recv(&t, 128, &ts_recv); - cr_assert_eq(rtt, (int64_t)1000000); + accepted = ping_tracker_record_recv(&t, 42); + cr_assert_eq(accepted, 1); + cr_assert_eq(t.nb_recv, (size_t)1); } Test(ping_tracker, lost_count) { struct ping_tracker t; - struct timespec ts; ping_tracker_init(&t); - ts = make_ts(0, 0); - ping_tracker_record_send(&t, 1, &ts); - ping_tracker_record_send(&t, 2, &ts); - ping_tracker_record_send(&t, 3, &ts); - ping_tracker_record_recv(&t, 2, &ts); + ping_tracker_record_send(&t, 1); + ping_tracker_record_send(&t, 2); + ping_tracker_record_send(&t, 3); + ping_tracker_record_recv(&t, 2); cr_assert_eq(t.nb_sent, (size_t)3); cr_assert_eq(t.nb_recv, (size_t)1); cr_assert_eq(t.nb_sent - t.nb_recv, (size_t)2); @@ -103,63 +69,36 @@ Test(ping_tracker, lost_count) Test(ping_tracker, sent_count_increments) { struct ping_tracker t; - struct timespec ts; ping_tracker_init(&t); - ts = make_ts(0, 0); - ping_tracker_record_send(&t, 1, &ts); - ping_tracker_record_send(&t, 2, &ts); - ping_tracker_record_send(&t, 3, &ts); + ping_tracker_record_send(&t, 1); + ping_tracker_record_send(&t, 2); + ping_tracker_record_send(&t, 3); cr_assert_eq(t.nb_sent, (size_t)3); } -Test(ping_tracker, recv_rtt_positive) +Test(ping_tracker, no_slot_collision_at_256) { struct ping_tracker t; - struct timespec ts_send; - struct timespec ts_recv; - int64_t rtt; - - ping_tracker_init(&t); - ts_send = make_ts(1, 0); - ts_recv = make_ts(1, 10000000); /* 10 ms later */ - ping_tracker_record_send(&t, 7, &ts_send); - rtt = ping_tracker_record_recv(&t, 7, &ts_recv); - cr_assert(rtt > 0, "RTT should be positive"); -} - -Test(ping_tracker, slot_reuse_after_wraparound) -{ - struct ping_tracker t; - struct timespec ts_send; - struct timespec ts_recv; - int64_t rtt; - - ping_tracker_init(&t); - ts_send = make_ts(0, 0); - ts_recv = make_ts(0, 1000000); - /* seq=1 -> slot 1 */ - ping_tracker_record_send(&t, 1, &ts_send); - rtt = ping_tracker_record_recv(&t, 1, &ts_recv); - cr_assert(rtt >= 0, "First round RTT should be >= 0"); - /* seq=129 -> slot 129 % 128 = 1, same slot */ - ping_tracker_record_send(&t, 129, &ts_send); - rtt = ping_tracker_record_recv(&t, 129, &ts_recv); - cr_assert(rtt >= 0, "Second round RTT should be >= 0"); - cr_assert_eq(t.nb_sent, (size_t)2); - cr_assert_eq(t.nb_recv, (size_t)2); -} - -Test(ping_tracker, full_buffer) -{ - struct ping_tracker t; - struct timespec ts; uint16_t seq; ping_tracker_init(&t); - ts = make_ts(0, 0); - for (seq = 1; seq <= 128; seq++) - ping_tracker_record_send(&t, seq, &ts); - cr_assert_eq(t.nb_sent, (size_t)128); - cr_assert_eq(t.nb_recv, (size_t)0); + for (seq = 0; seq < 256; seq++) + { + ping_tracker_record_send(&t, seq); + cr_assert_eq(ping_tracker_record_recv(&t, seq), 1, + "seq %u should be accepted", (unsigned)seq); + } + cr_assert_eq(t.nb_recv, (size_t)256); +} + +Test(ping_tracker, full_seq_space) +{ + struct ping_tracker t; + uint32_t seq; + + ping_tracker_init(&t); + for (seq = 0; seq < 65536; seq++) + ping_tracker_record_send(&t, (uint16_t)seq); + cr_assert_eq(t.nb_sent, (size_t)65536); } diff --git a/tests/send/test_do_send.c b/tests/send/test_do_send.c index b9bfa1d..4ddfa8a 100644 --- a/tests/send/test_do_send.c +++ b/tests/send/test_do_send.c @@ -9,6 +9,7 @@ #include "internal/ping/ping_state.h" #include "internal/ping/tracker.h" #include "ping/ping.h" +#include "ping/ft_ping_const.h" /* Controllable mock state */ int g_mock_send_ret; @@ -104,3 +105,23 @@ Test(do_send, eagain_then_success_uses_same_seq, .init = setup) cr_assert_eq(g_state.seq, (uint16_t)1); cr_assert_eq(g_tracker.nb_sent, (size_t)1); } + +Test(do_send, ts_in_payload_increments_seq, .init = setup) +{ + g_mock_send_ret = 0; + g_state.ts_in_payload = 1; + do_send(&g_state, PING_TIMESTAMP_SIZE); + cr_assert_eq(g_state.seq, (uint16_t)1); + cr_assert_eq(g_tracker.nb_sent, (size_t)1); +} + +Test(do_send, ts_in_payload_multiple_sends, .init = setup) +{ + g_mock_send_ret = 0; + g_state.ts_in_payload = 1; + do_send(&g_state, PING_TIMESTAMP_SIZE); + do_send(&g_state, PING_TIMESTAMP_SIZE); + do_send(&g_state, PING_TIMESTAMP_SIZE); + cr_assert_eq(g_state.seq, (uint16_t)3); + cr_assert_eq(g_tracker.nb_sent, (size_t)3); +}