C rewrite: phase out std::chrono
This commit is contained in:
parent
3f4e5ee227
commit
99f14b84c1
9 changed files with 98 additions and 52 deletions
25
UdpVpn.cpp
25
UdpVpn.cpp
|
@ -1,6 +1,5 @@
|
||||||
#include "UdpVpn.hpp"
|
#include "UdpVpn.hpp"
|
||||||
|
|
||||||
#include <chrono>
|
|
||||||
#include <sys/types.h>
|
#include <sys/types.h>
|
||||||
#include <sys/socket.h>
|
#include <sys/socket.h>
|
||||||
#include <netinet/in.h>
|
#include <netinet/in.h>
|
||||||
|
@ -19,8 +18,10 @@ UdpVpn::UdpVpn()
|
||||||
: _stopped(false), _dump_requested(false), _vpn_mtu(VPN_MTU),
|
: _stopped(false), _dump_requested(false), _vpn_mtu(VPN_MTU),
|
||||||
_tun_dev("cvpn%d"), _peer(nullptr)
|
_tun_dev("cvpn%d"), _peer(nullptr)
|
||||||
{
|
{
|
||||||
_last_tick = _last_control_sent =
|
clock_gettime(CLOCK_MONOTONIC, &_last_tick);
|
||||||
std::chrono::steady_clock::now() - std::chrono::seconds(1);
|
_last_tick.tv_sec--;
|
||||||
|
memcpy(&_last_control_sent, &_last_tick, sizeof(struct timespec));
|
||||||
|
|
||||||
_tun_dev.set_mtu(VpnPacket::get_tunnelled_mtu(_vpn_mtu));
|
_tun_dev.set_mtu(VpnPacket::get_tunnelled_mtu(_vpn_mtu));
|
||||||
_socket = socket(AF_INET6, SOCK_DGRAM, 0);
|
_socket = socket(AF_INET6, SOCK_DGRAM, 0);
|
||||||
if(_socket < 0)
|
if(_socket < 0)
|
||||||
|
@ -63,17 +64,13 @@ void UdpVpn::run() {
|
||||||
|
|
||||||
// ## Check periodic actions
|
// ## Check periodic actions
|
||||||
if(_peer) {
|
if(_peer) {
|
||||||
if(std::chrono::steady_clock::now() - _last_control_sent
|
if(timespec_us_ellapsed(_last_control_sent) > 1000*1000) {
|
||||||
> std::chrono::milliseconds(100))
|
|
||||||
{
|
|
||||||
if(_peer->send_control_packet())
|
if(_peer->send_control_packet())
|
||||||
_last_control_sent = std::chrono::steady_clock::now();
|
clock_gettime(CLOCK_MONOTONIC, &_last_control_sent);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if(std::chrono::steady_clock::now() - _last_tick
|
if(timespec_us_ellapsed(_last_tick) > 50*1000) {
|
||||||
> std::chrono::milliseconds(50))
|
clock_gettime(CLOCK_MONOTONIC, &_last_tick);
|
||||||
{
|
|
||||||
_last_tick = std::chrono::steady_clock::now();
|
|
||||||
if(_peer)
|
if(_peer)
|
||||||
_peer->tick();
|
_peer->tick();
|
||||||
}
|
}
|
||||||
|
@ -257,12 +254,10 @@ void UdpVpn::dump_state() const {
|
||||||
round(_peer->get_loss_logger().get_loss_rate() * 100));
|
round(_peer->get_loss_logger().get_loss_rate() * 100));
|
||||||
printf("Packet loss rate (outbound): %.0lf%%\n",
|
printf("Packet loss rate (outbound): %.0lf%%\n",
|
||||||
round(_peer->get_loss_reports().loss_rate() * 100));
|
round(_peer->get_loss_reports().loss_rate() * 100));
|
||||||
printf("RTT: %.02lf ms avg, %.02lf ms last [last updated: %lu ms ago]\n",
|
printf("RTT: %.02lf ms avg, %.02lf ms last [last updated: %u ms ago]\n",
|
||||||
(double)_peer->get_rtt().avg_rtt() / 1e3,
|
(double)_peer->get_rtt().avg_rtt() / 1e3,
|
||||||
(double)_peer->get_rtt().cur_rtt() / 1e3,
|
(double)_peer->get_rtt().cur_rtt() / 1e3,
|
||||||
std::chrono::duration_cast<std::chrono::milliseconds>(
|
timespec_us_ellapsed(_peer->get_rtt().get_last_update()) / 1000
|
||||||
std::chrono::steady_clock::now()
|
|
||||||
- _peer->get_rtt().get_last_update()).count()
|
|
||||||
);
|
);
|
||||||
printf("Total bytes transmitted: %s\n",
|
printf("Total bytes transmitted: %s\n",
|
||||||
human_readable_unit(_peer->get_tot_bytes_sent(), "B"));
|
human_readable_unit(_peer->get_tot_bytes_sent(), "B"));
|
||||||
|
|
|
@ -2,6 +2,7 @@
|
||||||
|
|
||||||
#include <sys/socket.h>
|
#include <sys/socket.h>
|
||||||
#include <netinet/in.h>
|
#include <netinet/in.h>
|
||||||
|
#include <time.h>
|
||||||
|
|
||||||
#include "util.hpp"
|
#include "util.hpp"
|
||||||
#include "TunDevice.hpp"
|
#include "TunDevice.hpp"
|
||||||
|
@ -73,7 +74,7 @@ class UdpVpn {
|
||||||
TunDevice _tun_dev;
|
TunDevice _tun_dev;
|
||||||
std::unique_ptr<VpnPeer> _peer;
|
std::unique_ptr<VpnPeer> _peer;
|
||||||
|
|
||||||
std::chrono::steady_clock::time_point
|
struct timespec
|
||||||
_last_control_sent, /**< A control is offered to be sent approx.
|
_last_control_sent, /**< A control is offered to be sent approx.
|
||||||
every 100ms */
|
every 100ms */
|
||||||
_last_tick /**< A tick occurs approx. each 50ms */;
|
_last_tick /**< A tick occurs approx. each 50ms */;
|
||||||
|
|
|
@ -1,7 +1,6 @@
|
||||||
#include "VpnPacket.hpp"
|
#include "VpnPacket.hpp"
|
||||||
#include "VpnPeer.hpp"
|
#include "VpnPeer.hpp"
|
||||||
|
|
||||||
#include <chrono>
|
|
||||||
#include <cstring>
|
#include <cstring>
|
||||||
|
|
||||||
const size_t VpnPacket::VPN_HEADER_BYTES = 8;
|
const size_t VpnPacket::VPN_HEADER_BYTES = 8;
|
||||||
|
@ -70,19 +69,11 @@ void VpnPacket::prepare_for_sending() {
|
||||||
uint32_t* ts_field = (uint32_t*) (_data.get() + DATA_TIMESTAMP_POS);
|
uint32_t* ts_field = (uint32_t*) (_data.get() + DATA_TIMESTAMP_POS);
|
||||||
*ts_field &= htonl(0x80000000UL);
|
*ts_field &= htonl(0x80000000UL);
|
||||||
*(uint32_t*)(_data.get() + DATA_SEQNO_POS) = htonl(next_seqno());
|
*(uint32_t*)(_data.get() + DATA_SEQNO_POS) = htonl(next_seqno());
|
||||||
*ts_field |=
|
*ts_field |= htonl(to_us_timestamp(current_us_timestamp()));
|
||||||
htonl(to_us_timestamp(
|
|
||||||
std::chrono::time_point_cast<std::chrono::microseconds>(
|
|
||||||
std::chrono::steady_clock::now()
|
|
||||||
).time_since_epoch().count())
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void VpnPacket::upon_reception() {
|
void VpnPacket::upon_reception() {
|
||||||
_reception_timestamp = to_us_timestamp(
|
_reception_timestamp = to_us_timestamp(current_us_timestamp());
|
||||||
std::chrono::time_point_cast<std::chrono::microseconds>(
|
|
||||||
std::chrono::steady_clock::now()
|
|
||||||
).time_since_epoch().count());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
uint32_t VpnPacket::next_seqno() {
|
uint32_t VpnPacket::next_seqno() {
|
||||||
|
|
22
VpnPeer.cpp
22
VpnPeer.cpp
|
@ -14,7 +14,7 @@ VpnPeer::VpnPeer(UdpVpn* vpn, const sockaddr_in6& ext_addr,
|
||||||
_tot_bytes_sent(0), _prev_tot_bytes_sent(0),
|
_tot_bytes_sent(0), _prev_tot_bytes_sent(0),
|
||||||
_congestion_controller(*this)
|
_congestion_controller(*this)
|
||||||
{
|
{
|
||||||
_prev_tick_time = std::chrono::steady_clock::now();
|
clock_gettime(CLOCK_MONOTONIC, &_prev_tick_time);
|
||||||
cycle_next_control();
|
cycle_next_control();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -35,13 +35,13 @@ void VpnPeer::set_int_addr(const in6_addr& int_addr) {
|
||||||
}
|
}
|
||||||
|
|
||||||
void VpnPeer::tick() {
|
void VpnPeer::tick() {
|
||||||
auto cur_time = std::chrono::steady_clock::now();
|
struct timespec cur_time;
|
||||||
|
clock_gettime(CLOCK_MONOTONIC, &cur_time);
|
||||||
|
|
||||||
// Compute byte rate
|
// Compute byte rate
|
||||||
_outbound_byte_rate = /* byte per second */
|
_outbound_byte_rate = /* byte per second */
|
||||||
(double)(_tot_bytes_sent - _prev_tot_bytes_sent)
|
(double)(_tot_bytes_sent - _prev_tot_bytes_sent)
|
||||||
/ (double)(std::chrono::duration_cast<std::chrono::microseconds>(
|
/ timespec_us_diff(cur_time, _prev_tick_time)
|
||||||
cur_time - _prev_tick_time).count())
|
|
||||||
* 1e6;
|
* 1e6;
|
||||||
|
|
||||||
_prev_tot_bytes_sent = _tot_bytes_sent;
|
_prev_tot_bytes_sent = _tot_bytes_sent;
|
||||||
|
@ -153,12 +153,9 @@ void PacketLossLogger::maybe_start_window(int offs) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
RTTLogger::RTTLogger() :
|
RTTLogger::RTTLogger() : _avg_rtt(0), _cur_rtt(0) {
|
||||||
_avg_rtt(0), _cur_rtt(0),
|
clock_gettime(CLOCK_MONOTONIC, &_last_update);
|
||||||
_last_update(std::chrono::steady_clock::time_point::min())
|
_last_update.tv_sec--;
|
||||||
{
|
|
||||||
_last_update =
|
|
||||||
std::chrono::steady_clock::now() - std::chrono::seconds(1);
|
|
||||||
// This avoids situations where both peers try to renew their RTT at the
|
// This avoids situations where both peers try to renew their RTT at the
|
||||||
// same time.
|
// same time.
|
||||||
_update_delay = BASE_UPDATE_DELAY + rand() % 100 - 50;
|
_update_delay = BASE_UPDATE_DELAY + rand() % 100 - 50;
|
||||||
|
@ -177,12 +174,11 @@ void RTTLogger::log(const VpnTlvRTTA& rtt_answer) {
|
||||||
_avg_rtt = (1 - EXP_AVG_FACTOR) * _avg_rtt
|
_avg_rtt = (1 - EXP_AVG_FACTOR) * _avg_rtt
|
||||||
+ EXP_AVG_FACTOR * _cur_rtt;
|
+ EXP_AVG_FACTOR * _cur_rtt;
|
||||||
|
|
||||||
_last_update = std::chrono::steady_clock::now();
|
clock_gettime(CLOCK_MONOTONIC, &_last_update);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool RTTLogger::update_due(bool soon) const {
|
bool RTTLogger::update_due(bool soon) const {
|
||||||
unsigned int ms_since_last_update =
|
unsigned int ms_since_last_update =
|
||||||
std::chrono::duration_cast<std::chrono::milliseconds>(
|
timespec_us_ellapsed(_last_update) / 1000;
|
||||||
std::chrono::steady_clock::now() - _last_update).count();
|
|
||||||
return ms_since_last_update >= (soon ? _update_delay/2 : _update_delay);
|
return ms_since_last_update >= (soon ? _update_delay/2 : _update_delay);
|
||||||
}
|
}
|
||||||
|
|
|
@ -4,7 +4,7 @@
|
||||||
|
|
||||||
#include <netinet/in.h>
|
#include <netinet/in.h>
|
||||||
#include <bitset>
|
#include <bitset>
|
||||||
#include <chrono>
|
#include <time.h>
|
||||||
#include "util.hpp"
|
#include "util.hpp"
|
||||||
#include "VpnPacket.hpp"
|
#include "VpnPacket.hpp"
|
||||||
#include "congestion_control.hpp"
|
#include "congestion_control.hpp"
|
||||||
|
@ -47,7 +47,7 @@ class RTTLogger {
|
||||||
RTTLogger();
|
RTTLogger();
|
||||||
uint32_t avg_rtt() const { return _avg_rtt; }
|
uint32_t avg_rtt() const { return _avg_rtt; }
|
||||||
uint32_t cur_rtt() const { return _cur_rtt; }
|
uint32_t cur_rtt() const { return _cur_rtt; }
|
||||||
std::chrono::steady_clock::time_point get_last_update() const {
|
struct timespec get_last_update() const {
|
||||||
return _last_update;
|
return _last_update;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -64,7 +64,7 @@ class RTTLogger {
|
||||||
|
|
||||||
unsigned int _update_delay; // in ms
|
unsigned int _update_delay; // in ms
|
||||||
static const unsigned int BASE_UPDATE_DELAY; // in ms
|
static const unsigned int BASE_UPDATE_DELAY; // in ms
|
||||||
std::chrono::steady_clock::time_point _last_update;
|
struct timespec _last_update;
|
||||||
};
|
};
|
||||||
|
|
||||||
class VpnPeer {
|
class VpnPeer {
|
||||||
|
@ -139,7 +139,7 @@ class VpnPeer {
|
||||||
uint64_t _tot_bytes_sent, _prev_tot_bytes_sent;
|
uint64_t _tot_bytes_sent, _prev_tot_bytes_sent;
|
||||||
double _outbound_byte_rate;
|
double _outbound_byte_rate;
|
||||||
|
|
||||||
std::chrono::steady_clock::time_point _prev_tick_time;
|
struct timespec _prev_tick_time;
|
||||||
|
|
||||||
PacketLossLogger _packet_loss;
|
PacketLossLogger _packet_loss;
|
||||||
LossReports _loss_reports;
|
LossReports _loss_reports;
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
#include "congestion_control.hpp"
|
#include "congestion_control.hpp"
|
||||||
#include "VpnPeer.hpp"
|
#include "VpnPeer.hpp"
|
||||||
|
#include "util.hpp"
|
||||||
|
|
||||||
CongestionController::CongestionController(const VpnPeer& peer):
|
CongestionController::CongestionController(const VpnPeer& peer):
|
||||||
_peer(peer)
|
_peer(peer)
|
||||||
|
@ -7,8 +8,8 @@ CongestionController::CongestionController(const VpnPeer& peer):
|
||||||
_last_seqno = _peer.get_loss_logger().get_cur_seqno();
|
_last_seqno = _peer.get_loss_logger().get_cur_seqno();
|
||||||
_loss_based.bandwidth = 3e5; // 300kBps seems a good value to start with
|
_loss_based.bandwidth = 3e5; // 300kBps seems a good value to start with
|
||||||
_loss_based.prev_tot_sent = _peer.get_tot_bytes_sent();
|
_loss_based.prev_tot_sent = _peer.get_tot_bytes_sent();
|
||||||
_last_bucket_update = _loss_based.prev_time =
|
clock_gettime(CLOCK_MONOTONIC, &_last_bucket_update);
|
||||||
std::chrono::steady_clock::now();
|
clock_gettime(CLOCK_MONOTONIC, &_loss_based.prev_time);
|
||||||
update_params();
|
update_params();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -20,12 +21,14 @@ void CongestionController::update_lossbased() {
|
||||||
|
|
||||||
double loss_rate = (double)delta_losses / (double)delta_seqno;
|
double loss_rate = (double)delta_losses / (double)delta_seqno;
|
||||||
|
|
||||||
auto cur_time = std::chrono::steady_clock::now();
|
struct timespec cur_time;
|
||||||
|
clock_gettime(CLOCK_MONOTONIC, &cur_time);
|
||||||
|
|
||||||
uint64_t cur_sent = _peer.get_tot_bytes_sent();
|
uint64_t cur_sent = _peer.get_tot_bytes_sent();
|
||||||
|
|
||||||
double instant_bandwidth = /* byte per second */
|
double instant_bandwidth = /* byte per second */
|
||||||
(double)(cur_sent - _loss_based.prev_tot_sent)
|
(double)(cur_sent - _loss_based.prev_tot_sent)
|
||||||
/ (double)(std::chrono::duration_cast<std::chrono::microseconds>(
|
/ (double)(timespec_us_diff(cur_time, _loss_based.prev_time))
|
||||||
cur_time - _loss_based.prev_time).count())
|
|
||||||
* 1e6;
|
* 1e6;
|
||||||
|
|
||||||
_loss_based.prev_time = cur_time;
|
_loss_based.prev_time = cur_time;
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
#pragma once
|
#pragma once
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
#include <chrono>
|
#include <time.h>
|
||||||
|
|
||||||
class VpnPeer;
|
class VpnPeer;
|
||||||
|
|
||||||
|
@ -9,7 +9,7 @@ class CongestionController {
|
||||||
struct LossBased {
|
struct LossBased {
|
||||||
uint64_t bandwidth; // bytes per second
|
uint64_t bandwidth; // bytes per second
|
||||||
uint64_t prev_tot_sent; // tot bytes sent during last update
|
uint64_t prev_tot_sent; // tot bytes sent during last update
|
||||||
std::chrono::steady_clock::time_point prev_time; // last update time
|
struct timespec prev_time; // last update time
|
||||||
};
|
};
|
||||||
|
|
||||||
CongestionController(const VpnPeer& peer);
|
CongestionController(const VpnPeer& peer);
|
||||||
|
@ -34,6 +34,6 @@ class CongestionController {
|
||||||
|
|
||||||
uint64_t _bucket_level, ///< implements a leaky bucket
|
uint64_t _bucket_level, ///< implements a leaky bucket
|
||||||
_bucket_max_level; // bandwidth * RTT
|
_bucket_max_level; // bandwidth * RTT
|
||||||
std::chrono::steady_clock::time_point _last_bucket_update;
|
struct timespec _last_bucket_update;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
36
util.cpp
36
util.cpp
|
@ -53,6 +53,42 @@ human_readable_unit(double value, const char* unit) {
|
||||||
return buf[cur_buf];
|
return buf[cur_buf];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
timespec_diff(const struct timespec t1, const struct timespec t2,
|
||||||
|
struct timespec* result)
|
||||||
|
{
|
||||||
|
result->tv_nsec = t1.tv_nsec - t2.tv_nsec;
|
||||||
|
result->tv_sec = t1.tv_sec - t2.tv_sec;
|
||||||
|
if(result->tv_nsec < 0) {
|
||||||
|
result->tv_nsec += 1000*1000*1000;
|
||||||
|
result->tv_sec--;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32_t timespec_us_diff(const struct timespec t1, const struct timespec t2) {
|
||||||
|
long nsec_diff = t1.tv_nsec - t2.tv_nsec;
|
||||||
|
time_t sec_diff = t1.tv_sec - t2.tv_sec;
|
||||||
|
if(nsec_diff < 0) {
|
||||||
|
nsec_diff += 1000*1000*1000;
|
||||||
|
sec_diff--;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(sec_diff > MAX_USEC_DIFF)
|
||||||
|
sec_diff = MAX_USEC_DIFF;
|
||||||
|
return (nsec_diff / 1000) + (sec_diff * 1000*1000);
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32_t timespec_us_ellapsed(const struct timespec ref) {
|
||||||
|
struct timespec now;
|
||||||
|
clock_gettime(CLOCK_MONOTONIC, &now);
|
||||||
|
return timespec_us_diff(now, ref);
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32_t current_us_timestamp() {
|
||||||
|
struct timespec now;
|
||||||
|
clock_gettime(CLOCK_MONOTONIC, &now);
|
||||||
|
return (now.tv_sec * 1000*1000) + (now.tv_nsec / 1000);
|
||||||
|
}
|
||||||
|
|
||||||
namespace std {
|
namespace std {
|
||||||
size_t hash<in6_addr>::operator() (const in6_addr& addr) const {
|
size_t hash<in6_addr>::operator() (const in6_addr& addr) const {
|
||||||
|
|
24
util.hpp
24
util.hpp
|
@ -58,6 +58,30 @@ inline uint32_t to_us_timestamp(uint32_t clock_output) {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/** Max seconds that can be be represented in a microseconds timestamp, on 31
|
||||||
|
* bits. */
|
||||||
|
const uint32_t MAX_USEC_DIFF = ((1U<<31) - 1) / (1000*1000) - 1;
|
||||||
|
|
||||||
|
|
||||||
|
/** Get a `struct timespec` difference, ie `t1 - t2`, as a new `struct
|
||||||
|
* timespec`. Assumes `t1 >= t2`. */
|
||||||
|
void timespec_diff(
|
||||||
|
const struct timespec t1, const struct timespec t2,
|
||||||
|
struct timespec* result);
|
||||||
|
|
||||||
|
/** Get a `struct timespec` difference, ie `t1 - t2`, expressed in
|
||||||
|
* microseconds. Assumes `t1 >= t2`. Capped to MAX_USEC_DIFF seconds. */
|
||||||
|
uint32_t timespec_us_diff(const struct timespec t1, const struct timespec t2);
|
||||||
|
|
||||||
|
/** Get the number of microseconds ellapsed since a `struct timespec`, based on
|
||||||
|
* the monotonic clock */
|
||||||
|
uint32_t timespec_us_ellapsed(const struct timespec ref);
|
||||||
|
|
||||||
|
/** Get the current timestamp, in microseconds */
|
||||||
|
uint32_t current_us_timestamp();
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/** in6_addr hash & equality */
|
/** in6_addr hash & equality */
|
||||||
namespace std {
|
namespace std {
|
||||||
template<>
|
template<>
|
||||||
|
|
Loading…
Reference in a new issue