enable profiling on clients by default (#1421)

* enable client relay profiling by default

* macos dns fixes

* improve peer profiling algorithm to track timeouts vs failures

* remove debug ioctl call in tuntap code

* use ub_wait instead of ub_process as that was what was there before

* const correctness

* DRY out checking for SIIT

* typofix

* correct name
pull/1433/head
Jeff 4 years ago committed by GitHub
parent 32f4287df6
commit dcb48db5fe
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

@ -255,7 +255,7 @@ namespace llarp
{ {
(void)params; (void)params;
static constexpr Default ProfilingValueDefault{false}; static constexpr Default ProfilingValueDefault{true};
static constexpr Default ReachableDefault{true}; static constexpr Default ReachableDefault{true};
static constexpr Default HopsDefault{4}; static constexpr Default HopsDefault{4};
static constexpr Default PathsDefault{6}; static constexpr Default PathsDefault{6};

@ -66,11 +66,8 @@ namespace llarp
Proxy::HandleUDPRecv_server(llarp_udp_io* u, const SockAddr& from, ManagedBuffer buf) Proxy::HandleUDPRecv_server(llarp_udp_io* u, const SockAddr& from, ManagedBuffer buf)
{ {
Buffer_t msgbuf = CopyBuffer(buf.underlying); Buffer_t msgbuf = CopyBuffer(buf.underlying);
auto self = static_cast<Proxy*>(u->user)->shared_from_this(); auto self = static_cast<Proxy*>(u->user);
// yes we use the server loop here because if the server loop is not the self->HandlePktServer(from, msgbuf);
// client loop we'll crash again
LogicCall(
self->m_ServerLogic, [self, from, msgbuf]() { self->HandlePktServer(from, msgbuf); });
} }
void void
@ -140,7 +137,8 @@ namespace llarp
void void
Proxy::SendServerMessageBufferTo(const SockAddr& to, const llarp_buffer_t& buf) Proxy::SendServerMessageBufferTo(const SockAddr& to, const llarp_buffer_t& buf)
{ {
llarp_ev_udp_sendto(&m_Server, to, buf); if (llarp_ev_udp_sendto(&m_Server, to, buf) < 0)
llarp::LogError("dns reply failed");
} }
void void
@ -244,7 +242,6 @@ namespace llarp
return; return;
} }
TX tx = {hdr.id, from};
Message msg(hdr); Message msg(hdr);
if (!msg.Decode(&pkt)) if (!msg.Decode(&pkt))
{ {

@ -16,58 +16,28 @@ namespace llarp::dns
UnboundResolver::Reset() UnboundResolver::Reset()
{ {
started = false; started = false;
if (runner)
{
runner->join();
runner.reset();
}
if (unboundContext) if (unboundContext)
{ {
DeregisterPollFD();
ub_ctx_delete(unboundContext); ub_ctx_delete(unboundContext);
} }
unboundContext = nullptr; unboundContext = nullptr;
} }
void
UnboundResolver::DeregisterPollFD()
{
#ifdef _WIN32
runnerThread->join();
#else
eventLoop->deregister_poll_fd_readable(ub_fd(unboundContext));
#endif
}
void
UnboundResolver::RegisterPollFD()
{
#ifdef _WIN32
runnerThread = std::make_unique<std::thread>([self = shared_from_this()]() {
while (self->started)
{
using namespace std::chrono_literals;
std::this_thread::sleep_for(20ms);
ub_wait(self->unboundContext);
}
});
#else
eventLoop->register_poll_fd_readable(
ub_fd(unboundContext), [=]() { ub_process(unboundContext); });
#endif
}
UnboundResolver::UnboundResolver(llarp_ev_loop_ptr loop, ReplyFunction reply, FailFunction fail) UnboundResolver::UnboundResolver(llarp_ev_loop_ptr loop, ReplyFunction reply, FailFunction fail)
: unboundContext(nullptr) : unboundContext(nullptr)
, started(false) , started(false)
, eventLoop(loop) , eventLoop(loop)
#ifdef _WIN32
// on win32 we use another thread for io because LOL windows
, replyFunc([loop, reply](auto source, auto buf) { , replyFunc([loop, reply](auto source, auto buf) {
loop->call_soon([source, buf, reply]() { reply(source, buf); }); loop->call_soon([source, buf, reply]() { reply(source, buf); });
}) })
, failFunc([loop, fail](auto source, auto message) { , failFunc([loop, fail](auto source, auto message) {
loop->call_soon([source, message, fail]() { fail(source, message); }); loop->call_soon([source, message, fail]() { fail(source, message); });
}) })
#else
, replyFunc(reply)
, failFunc(fail)
#endif
{} {}
// static callback // static callback
@ -88,10 +58,9 @@ namespace llarp::dns
ub_resolve_free(result); ub_resolve_free(result);
return; return;
} }
std::vector<byte_t> pkt(result->answer_len);
llarp_buffer_t buf; std::copy_n(static_cast<byte_t*>(result->answer_packet), pkt.size(), pkt.data());
buf.base = buf.cur = static_cast<byte_t*>(result->answer_packet); llarp_buffer_t buf(pkt);
buf.sz = result->answer_len;
MessageHeader hdr; MessageHeader hdr;
hdr.Decode(&buf); hdr.Decode(&buf);
@ -100,10 +69,7 @@ namespace llarp::dns
buf.cur = buf.base; buf.cur = buf.base;
hdr.Encode(&buf); hdr.Encode(&buf);
std::vector<byte_t> buf_copy(buf.sz); this_ptr->replyFunc(lookup->source, std::move(pkt));
std::copy_n(buf.base, buf.sz, buf_copy.begin());
this_ptr->replyFunc(lookup->source, std::move(buf_copy));
ub_resolve_free(result); ub_resolve_free(result);
} }
@ -123,12 +89,16 @@ namespace llarp::dns
return false; return false;
} }
#ifdef _WIN32
ub_ctx_async(unboundContext, 1); ub_ctx_async(unboundContext, 1);
#endif runner = std::make_unique<std::thread>([&]() {
while (started)
{
if (unboundContext)
ub_wait(unboundContext);
std::this_thread::sleep_for(25ms);
}
});
started = true; started = true;
RegisterPollFD();
return true; return true;
} }

@ -24,12 +24,9 @@ namespace llarp::dns
{ {
private: private:
ub_ctx* unboundContext; ub_ctx* unboundContext;
#ifdef _WIN32
/// windows needs to run as blocking in another thread to work at all becuase LOL windows
std::unique_ptr<std::thread> runnerThread;
#endif
std::atomic<bool> started; std::atomic<bool> started;
std::unique_ptr<std::thread> runner;
llarp_ev_loop_ptr eventLoop; llarp_ev_loop_ptr eventLoop;
ReplyFunction replyFunc; ReplyFunction replyFunc;
@ -38,11 +35,6 @@ namespace llarp::dns
void void
Reset(); Reset();
void
DeregisterPollFD();
void
RegisterPollFD();
public: public:
UnboundResolver(llarp_ev_loop_ptr eventLoop, ReplyFunction replyFunc, FailFunction failFunc); UnboundResolver(llarp_ev_loop_ptr eventLoop, ReplyFunction replyFunc, FailFunction failFunc);

@ -474,13 +474,20 @@ namespace libuv
if (self == nullptr) if (self == nullptr)
return -1; return -1;
auto buf = uv_buf_init((char*)ptr, sz); auto buf = uv_buf_init((char*)ptr, sz);
return uv_udp_try_send(&self->m_Handle, &buf, 1, to); auto ret = uv_udp_try_send(
&self->m_Handle, &buf, 1, (const sockaddr*)static_cast<const sockaddr_in*>(to));
if (ret < 0)
{
llarp::LogError("udp sendto failed: ", uv_strerror(ret));
}
return ret;
} }
bool bool
Bind() Bind()
{ {
auto ret = uv_udp_bind(&m_Handle, m_Addr, 0); auto ret =
uv_udp_bind(&m_Handle, (const sockaddr*)static_cast<const sockaddr_in*>(m_Addr), 0);
if (ret) if (ret)
{ {
llarp::LogError("failed to bind to ", m_Addr, " ", uv_strerror(ret)); llarp::LogError("failed to bind to ", m_Addr, " ", uv_strerror(ret));

@ -1,5 +1,5 @@
#include <net/sock_addr.hpp> #include <net/sock_addr.hpp>
#include <net/net_bits.hpp>
#include <util/str.hpp> #include <util/str.hpp>
#include <util/logging/logger.hpp> #include <util/logging/logger.hpp>
#include <util/mem.hpp> #include <util/mem.hpp>
@ -12,10 +12,15 @@ namespace llarp
/// shared utility functions /// shared utility functions
/// ///
constexpr auto addrIsV4 = [](const in6_addr& addr) -> bool {
return addr.s6_addr[10] == 0xff and addr.s6_addr[11] == 0xff;
};
void void
SockAddr::init() SockAddr::init()
{ {
llarp::Zero(&m_addr, sizeof(m_addr)); llarp::Zero(&m_addr, sizeof(m_addr));
llarp::Zero(&m_addr4, sizeof(m_addr4));
} }
void void
@ -96,7 +101,8 @@ namespace llarp
// avoid byte order conversion (this is NBO -> NBO) // avoid byte order conversion (this is NBO -> NBO)
memcpy(m_addr.sin6_addr.s6_addr + 12, &other.sin_addr.s_addr, sizeof(in_addr)); memcpy(m_addr.sin6_addr.s6_addr + 12, &other.sin_addr.s_addr, sizeof(in_addr));
m_addr.sin6_port = other.sin_port; m_addr.sin6_port = other.sin_port;
m_addr4.sin_addr.s_addr = other.sin_addr.s_addr;
m_addr4.sin_port = other.sin_port;
m_empty = false; m_empty = false;
return *this; return *this;
@ -113,7 +119,13 @@ namespace llarp
init(); init();
memcpy(&m_addr, &other, sizeof(sockaddr_in6)); memcpy(&m_addr, &other, sizeof(sockaddr_in6));
if (addrIsV4(other.sin6_addr))
setIPv4(
other.sin6_addr.s6_addr[12],
other.sin6_addr.s6_addr[13],
other.sin6_addr.s6_addr[14],
other.sin6_addr.s6_addr[15]);
setPort(ntohs(other.sin6_port));
m_empty = false; m_empty = false;
return *this; return *this;
@ -130,7 +142,8 @@ namespace llarp
init(); init();
memcpy(&m_addr.sin6_addr.s6_addr, &other.s6_addr, sizeof(m_addr.sin6_addr.s6_addr)); memcpy(&m_addr.sin6_addr.s6_addr, &other.s6_addr, sizeof(m_addr.sin6_addr.s6_addr));
if (addrIsV4(other))
setIPv4(other.s6_addr[12], other.s6_addr[13], other.s6_addr[14], other.s6_addr[15]);
m_empty = false; m_empty = false;
return *this; return *this;
@ -141,6 +154,11 @@ namespace llarp
return (sockaddr*)&m_addr; return (sockaddr*)&m_addr;
} }
SockAddr::operator const sockaddr_in*() const
{
return &m_addr4;
}
SockAddr::operator const sockaddr_in6*() const SockAddr::operator const sockaddr_in6*() const
{ {
return &m_addr; return &m_addr;
@ -244,15 +262,9 @@ namespace llarp
// treat SIIT like IPv4 // treat SIIT like IPv4
constexpr auto MaxIPv4PlusPortStringSize = 22; constexpr auto MaxIPv4PlusPortStringSize = 22;
str.reserve(MaxIPv4PlusPortStringSize); str.reserve(MaxIPv4PlusPortStringSize);
char buf[128] = {0x0};
// TODO: ensure these don't each incur a memory allocation inet_ntop(AF_INET, &m_addr4.sin_addr.s_addr, buf, sizeof(buf));
str.append(std::to_string(ip6[12])); str.append(buf);
str.append(1, '.');
str.append(std::to_string(ip6[13]));
str.append(1, '.');
str.append(std::to_string(ip6[14]));
str.append(1, '.');
str.append(std::to_string(ip6[15]));
} }
else else
{ {
@ -281,7 +293,7 @@ namespace llarp
void void
SockAddr::setIPv4(uint8_t a, uint8_t b, uint8_t c, uint8_t d) SockAddr::setIPv4(uint8_t a, uint8_t b, uint8_t c, uint8_t d)
{ {
m_addr.sin6_family = AF_INET6; m_addr.sin6_family = AF_INET;
uint8_t* ip6 = m_addr.sin6_addr.s6_addr; uint8_t* ip6 = m_addr.sin6_addr.s6_addr;
llarp::Zero(ip6, sizeof(m_addr.sin6_addr.s6_addr)); llarp::Zero(ip6, sizeof(m_addr.sin6_addr.s6_addr));
@ -292,7 +304,9 @@ namespace llarp
ip6[13] = b; ip6[13] = b;
ip6[14] = c; ip6[14] = c;
ip6[15] = d; ip6[15] = d;
const auto ip = ipaddr_ipv4_bits(a, b, c, d);
m_addr4.sin_addr.s_addr = htonl(ip.h);
m_addr4.sin_family = AF_INET;
m_empty = false; m_empty = false;
} }
@ -300,6 +314,7 @@ namespace llarp
SockAddr::setPort(uint16_t port) SockAddr::setPort(uint16_t port)
{ {
m_addr.sin6_port = htons(port); m_addr.sin6_port = htons(port);
m_addr4.sin_port = htons(port);
} }
uint16_t uint16_t

@ -49,6 +49,7 @@ namespace llarp
operator=(const in6_addr& addr); operator=(const in6_addr& addr);
operator const sockaddr*() const; operator const sockaddr*() const;
operator const sockaddr_in*() const;
operator const sockaddr_in6*() const; operator const sockaddr_in6*() const;
bool bool
@ -82,6 +83,7 @@ namespace llarp
private: private:
bool m_empty = true; bool m_empty = true;
sockaddr_in6 m_addr; sockaddr_in6 m_addr;
sockaddr_in m_addr4;
void void
init(); init();

@ -476,7 +476,7 @@ namespace llarp
void void
Builder::HandlePathBuildTimeout(Path_ptr p) Builder::HandlePathBuildTimeout(Path_ptr p)
{ {
m_router->routerProfiling().MarkPathFail(p.get()); m_router->routerProfiling().MarkPathTimeout(p.get());
PathSet::HandlePathBuildTimeout(p); PathSet::HandlePathBuildTimeout(p);
DoPathBuildBackoff(); DoPathBuildBackoff();
} }

@ -15,6 +15,8 @@ namespace llarp
return false; return false;
if (!BEncodeWriteDictInt("p", pathSuccessCount, buf)) if (!BEncodeWriteDictInt("p", pathSuccessCount, buf))
return false; return false;
if (!BEncodeWriteDictInt("q", pathTimeoutCount, buf))
return false;
if (!BEncodeWriteDictInt("s", pathFailCount, buf)) if (!BEncodeWriteDictInt("s", pathFailCount, buf))
return false; return false;
if (!BEncodeWriteDictInt("t", connectTimeoutCount, buf)) if (!BEncodeWriteDictInt("t", connectTimeoutCount, buf))
@ -43,6 +45,8 @@ namespace llarp
return false; return false;
if (!BEncodeMaybeReadDictInt("p", pathSuccessCount, read, k, buf)) if (!BEncodeMaybeReadDictInt("p", pathSuccessCount, read, k, buf))
return false; return false;
if (!BEncodeMaybeReadDictInt("q", pathTimeoutCount, read, k, buf))
return false;
return read; return read;
} }
@ -53,14 +57,14 @@ namespace llarp
connectTimeoutCount /= 2; connectTimeoutCount /= 2;
pathSuccessCount /= 2; pathSuccessCount /= 2;
pathFailCount /= 2; pathFailCount /= 2;
pathTimeoutCount /= 2;
lastDecay = llarp::time_now_ms(); lastDecay = llarp::time_now_ms();
} }
void void
RouterProfile::Tick() RouterProfile::Tick()
{ {
// 15 seconds static constexpr auto updateInterval = 30min;
static constexpr auto updateInterval = 15s;
const auto now = llarp::time_now_ms(); const auto now = llarp::time_now_ms();
if (lastDecay < now && now - lastDecay > updateInterval) if (lastDecay < now && now - lastDecay > updateInterval)
Decay(); Decay();
@ -92,7 +96,8 @@ namespace llarp
bool bool
RouterProfile::IsGoodForPath(uint64_t chances) const RouterProfile::IsGoodForPath(uint64_t chances) const
{ {
return checkIsGood(pathFailCount, pathSuccessCount, chances); return checkIsGood(pathFailCount, pathSuccessCount, chances)
and checkIsGood(pathTimeoutCount, pathSuccessCount, chances);
} }
Profiling::Profiling() : m_DisableProfiling(false) Profiling::Profiling() : m_DisableProfiling(false)
@ -119,7 +124,7 @@ namespace llarp
auto itr = m_Profiles.find(r); auto itr = m_Profiles.find(r);
if (itr == m_Profiles.end()) if (itr == m_Profiles.end())
return false; return false;
return !itr->second.IsGoodForConnect(chances); return not itr->second.IsGoodForConnect(chances);
} }
bool bool
@ -131,7 +136,7 @@ namespace llarp
auto itr = m_Profiles.find(r); auto itr = m_Profiles.find(r);
if (itr == m_Profiles.end()) if (itr == m_Profiles.end())
return false; return false;
return !itr->second.IsGoodForPath(chances); return not itr->second.IsGoodForPath(chances);
} }
bool bool
@ -143,7 +148,7 @@ namespace llarp
auto itr = m_Profiles.find(r); auto itr = m_Profiles.find(r);
if (itr == m_Profiles.end()) if (itr == m_Profiles.end())
return false; return false;
return !itr->second.IsGood(chances); return not itr->second.IsGood(chances);
} }
void void
@ -201,6 +206,22 @@ namespace llarp
} }
} }
void
Profiling::MarkPathTimeout(path::Path* p)
{
util::Lock lock(m_ProfilesMutex);
size_t idx = 0;
for (const auto& hop : p->hops)
{
if (idx)
{
m_Profiles[hop.rc.pubkey].pathTimeoutCount += 1;
m_Profiles[hop.rc.pubkey].lastUpdated = llarp::time_now_ms();
}
++idx;
}
}
void void
Profiling::MarkPathSuccess(path::Path* p) Profiling::MarkPathSuccess(path::Path* p)
{ {
@ -208,6 +229,10 @@ namespace llarp
const auto sz = p->hops.size(); const auto sz = p->hops.size();
for (const auto& hop : p->hops) for (const auto& hop : p->hops)
{ {
// redeem previous fails by halfing the fail count and setting timeout to zero
m_Profiles[hop.rc.pubkey].pathFailCount /= 2;
m_Profiles[hop.rc.pubkey].pathTimeoutCount = 0;
// mark success at hop
m_Profiles[hop.rc.pubkey].pathSuccessCount += sz; m_Profiles[hop.rc.pubkey].pathSuccessCount += sz;
m_Profiles[hop.rc.pubkey].lastUpdated = llarp::time_now_ms(); m_Profiles[hop.rc.pubkey].lastUpdated = llarp::time_now_ms();
} }

@ -18,6 +18,7 @@ namespace llarp
uint64_t connectGoodCount = 0; uint64_t connectGoodCount = 0;
uint64_t pathSuccessCount = 0; uint64_t pathSuccessCount = 0;
uint64_t pathFailCount = 0; uint64_t pathFailCount = 0;
uint64_t pathTimeoutCount = 0;
llarp_time_t lastUpdated = 0s; llarp_time_t lastUpdated = 0s;
llarp_time_t lastDecay = 0s; llarp_time_t lastDecay = 0s;
uint64_t version = LLARP_PROTO_VERSION; uint64_t version = LLARP_PROTO_VERSION;
@ -68,6 +69,9 @@ namespace llarp
void void
MarkConnectSuccess(const RouterID& r) EXCLUDES(m_ProfilesMutex); MarkConnectSuccess(const RouterID& r) EXCLUDES(m_ProfilesMutex);
void
MarkPathTimeout(path::Path* p) EXCLUDES(m_ProfilesMutex);
void void
MarkPathFail(path::Path* p) EXCLUDES(m_ProfilesMutex); MarkPathFail(path::Path* p) EXCLUDES(m_ProfilesMutex);

@ -100,7 +100,6 @@ tuntap_start(struct device *dev, int mode, int tun)
} }
dev->tun_fd = fd; dev->tun_fd = fd;
tuntap_set_debug(dev, 0);
return 0; return 0;
clean: clean:
@ -370,38 +369,3 @@ tuntap_set_nonblocking(struct device *dev, int set)
} }
return 0; return 0;
} }
int
tuntap_set_debug(struct device *dev, int set)
{
/* Only accept started device */
if(dev->tun_fd == -1)
{
tuntap_log(TUNTAP_LOG_NOTICE, "Device is not started");
return 0;
}
#if defined(__linux__)
if(ioctl(dev->tun_fd, TUNSETDEBUG, &set) == -1)
{
switch(set)
{
case 0:
tuntap_log(TUNTAP_LOG_WARN, "Can't unset debug");
break;
case 1:
tuntap_log(TUNTAP_LOG_WARN, "Can't set debug");
break;
default:
tuntap_log(TUNTAP_LOG_ERR, "Invalid parameter 'set'");
}
return -1;
}
return 0;
#else
(void)set;
tuntap_log(TUNTAP_LOG_NOTICE,
"Your system does not support tuntap_set_debug()");
return -1;
#endif
}

Loading…
Cancel
Save