blob: 52fcccb95c73f45e8ae42f754b2a32e7a12582d4 [file] [log] [blame]
* Copyright 2016 Google Inc. All rights reserved.
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* See the License for the specific language governing permissions and
* limitations under the License.
#ifndef ISOPING_H
#define ISOPING_H
#include <stdint.h>
// Layout of the UDP packets exchanged between client and server.
// All integers are in network byte order.
// Packets have exactly the same structure in both directions.
struct Packet {
uint32_t magic; // magic number to reject bogus packets
uint32_t id; // sequential packet id number
uint32_t txtime; // transmitter's monotonic time when pkt was sent
uint32_t clockdiff; // estimate of (transmitter's clk) - (receiver's clk)
uint32_t usec_per_pkt; // microseconds of delay between packets
uint32_t num_lost; // number of pkts transmitter expected to get but didn't
uint32_t first_ack; // starting index in acks[] circular buffer
struct {
// txtime==0 for empty elements in this array.
uint32_t id; // id field from a received packet
uint32_t rxtime; // receiver's monotonic time when pkt arrived
} acks[64];
// Data we track per session.
struct Session {
Session(uint32_t now);
int32_t usec_per_pkt;
int32_t usec_per_print;
// WARNING: lots of math below relies on well-defined uint32/int32
// arithmetic overflow behaviour, plus the fact that when we subtract
// two successive timestamps (for example) they will be less than 2^31
// microseconds apart. It would be safer to just use 64-bit values
// everywhere, but that would cut the number of acks-per-packet in half,
// which would be unfortunate.
uint32_t next_tx_id; // id field for next transmit
uint32_t next_rx_id; // expected id field for next receive
uint32_t next_rxack_id; // expected field in next received ack
uint32_t start_rtxtime; // remote's txtime at startup
uint32_t start_rxtime; // local rxtime at startup
uint32_t last_rxtime; // local rxtime of last received packet
int32_t min_cycle_rxdiff; // smallest packet delay seen this cycle
uint32_t next_cycle; // time when next cycle begins
uint32_t next_send; // time when we'll send next pkt
uint32_t num_lost; // number of rx packets not received
int next_txack_index; // next array item to fill in tx.acks
struct Packet tx, rx; // transmit and received packet buffers
char last_ackinfo[128]; // human readable format of latest ack
uint32_t last_print; // time of last packet printout
// Packet statistics counters for transmit and receive directions.
long long lat_tx, lat_tx_min, lat_tx_max,
lat_tx_count, lat_tx_sum, lat_tx_var_sum;
long long lat_rx, lat_rx_min, lat_rx_max,
lat_rx_count, lat_rx_sum, lat_rx_var_sum;
// Process the Session's incoming packet, from s->rx.
void handle_packet(struct Session *s, uint32_t now);
// Sets all the elements of s->tx to be ready to be sent to the other side.
void prepare_tx_packet(struct Session *s);
// Parses arguments and runs the main loop. Distinct from main() for unit test
// purposes.
int isoping_main(int argc, char **argv);