From dcb48db5fe64a3b25554830676bfdd3b0b0d5d7c Mon Sep 17 00:00:00 2001 From: Jeff Date: Tue, 27 Oct 2020 17:34:09 -0400 Subject: [PATCH] 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 --- llarp/config/config.cpp | 2 +- llarp/dns/server.cpp | 11 ++--- llarp/dns/unbound_resolver.cpp | 64 +++++++-------------------- llarp/dns/unbound_resolver.hpp | 10 +---- llarp/ev/ev_libuv.cpp | 11 ++++- llarp/net/sock_addr.cpp | 45 ++++++++++++------- llarp/net/sock_addr.hpp | 2 + llarp/path/pathbuilder.cpp | 2 +- llarp/profiling.cpp | 37 +++++++++++++--- llarp/profiling.hpp | 4 ++ vendor/libtuntap-master/tuntap-unix.c | 36 --------------- 11 files changed, 100 insertions(+), 124 deletions(-) diff --git a/llarp/config/config.cpp b/llarp/config/config.cpp index c52b36c53..171bf01a6 100644 --- a/llarp/config/config.cpp +++ b/llarp/config/config.cpp @@ -255,7 +255,7 @@ namespace llarp { (void)params; - static constexpr Default ProfilingValueDefault{false}; + static constexpr Default ProfilingValueDefault{true}; static constexpr Default ReachableDefault{true}; static constexpr Default HopsDefault{4}; static constexpr Default PathsDefault{6}; diff --git a/llarp/dns/server.cpp b/llarp/dns/server.cpp index ae7b6abd7..2cceb95d2 100644 --- a/llarp/dns/server.cpp +++ b/llarp/dns/server.cpp @@ -66,11 +66,8 @@ namespace llarp Proxy::HandleUDPRecv_server(llarp_udp_io* u, const SockAddr& from, ManagedBuffer buf) { Buffer_t msgbuf = CopyBuffer(buf.underlying); - auto self = static_cast(u->user)->shared_from_this(); - // yes we use the server loop here because if the server loop is not the - // client loop we'll crash again - LogicCall( - self->m_ServerLogic, [self, from, msgbuf]() { self->HandlePktServer(from, msgbuf); }); + auto self = static_cast(u->user); + self->HandlePktServer(from, msgbuf); } void @@ -140,7 +137,8 @@ namespace llarp void 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 @@ -244,7 +242,6 @@ namespace llarp return; } - TX tx = {hdr.id, from}; Message msg(hdr); if (!msg.Decode(&pkt)) { diff --git a/llarp/dns/unbound_resolver.cpp b/llarp/dns/unbound_resolver.cpp index 112cb0700..fb3bb897e 100644 --- a/llarp/dns/unbound_resolver.cpp +++ b/llarp/dns/unbound_resolver.cpp @@ -16,58 +16,28 @@ namespace llarp::dns UnboundResolver::Reset() { started = false; + if (runner) + { + runner->join(); + runner.reset(); + } if (unboundContext) { - DeregisterPollFD(); ub_ctx_delete(unboundContext); } 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([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) : unboundContext(nullptr) , started(false) , eventLoop(loop) -#ifdef _WIN32 - // on win32 we use another thread for io because LOL windows , replyFunc([loop, reply](auto source, auto buf) { loop->call_soon([source, buf, reply]() { reply(source, buf); }); }) , failFunc([loop, fail](auto source, auto message) { loop->call_soon([source, message, fail]() { fail(source, message); }); }) -#else - , replyFunc(reply) - , failFunc(fail) -#endif {} // static callback @@ -88,10 +58,9 @@ namespace llarp::dns ub_resolve_free(result); return; } - - llarp_buffer_t buf; - buf.base = buf.cur = static_cast(result->answer_packet); - buf.sz = result->answer_len; + std::vector pkt(result->answer_len); + std::copy_n(static_cast(result->answer_packet), pkt.size(), pkt.data()); + llarp_buffer_t buf(pkt); MessageHeader hdr; hdr.Decode(&buf); @@ -100,10 +69,7 @@ namespace llarp::dns buf.cur = buf.base; hdr.Encode(&buf); - std::vector buf_copy(buf.sz); - std::copy_n(buf.base, buf.sz, buf_copy.begin()); - - this_ptr->replyFunc(lookup->source, std::move(buf_copy)); + this_ptr->replyFunc(lookup->source, std::move(pkt)); ub_resolve_free(result); } @@ -123,12 +89,16 @@ namespace llarp::dns return false; } -#ifdef _WIN32 ub_ctx_async(unboundContext, 1); -#endif - + runner = std::make_unique([&]() { + while (started) + { + if (unboundContext) + ub_wait(unboundContext); + std::this_thread::sleep_for(25ms); + } + }); started = true; - RegisterPollFD(); return true; } diff --git a/llarp/dns/unbound_resolver.hpp b/llarp/dns/unbound_resolver.hpp index 5e2f0b086..db98a3d88 100644 --- a/llarp/dns/unbound_resolver.hpp +++ b/llarp/dns/unbound_resolver.hpp @@ -24,12 +24,9 @@ namespace llarp::dns { private: ub_ctx* unboundContext; -#ifdef _WIN32 - /// windows needs to run as blocking in another thread to work at all becuase LOL windows - std::unique_ptr runnerThread; -#endif std::atomic started; + std::unique_ptr runner; llarp_ev_loop_ptr eventLoop; ReplyFunction replyFunc; @@ -38,11 +35,6 @@ namespace llarp::dns void Reset(); - void - DeregisterPollFD(); - void - RegisterPollFD(); - public: UnboundResolver(llarp_ev_loop_ptr eventLoop, ReplyFunction replyFunc, FailFunction failFunc); diff --git a/llarp/ev/ev_libuv.cpp b/llarp/ev/ev_libuv.cpp index b5cef28d6..5ef9f47ad 100644 --- a/llarp/ev/ev_libuv.cpp +++ b/llarp/ev/ev_libuv.cpp @@ -474,13 +474,20 @@ namespace libuv if (self == nullptr) return -1; 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(to)); + if (ret < 0) + { + llarp::LogError("udp sendto failed: ", uv_strerror(ret)); + } + return ret; } bool Bind() { - auto ret = uv_udp_bind(&m_Handle, m_Addr, 0); + auto ret = + uv_udp_bind(&m_Handle, (const sockaddr*)static_cast(m_Addr), 0); if (ret) { llarp::LogError("failed to bind to ", m_Addr, " ", uv_strerror(ret)); diff --git a/llarp/net/sock_addr.cpp b/llarp/net/sock_addr.cpp index 41008f6fa..042a665a6 100644 --- a/llarp/net/sock_addr.cpp +++ b/llarp/net/sock_addr.cpp @@ -1,5 +1,5 @@ #include - +#include #include #include #include @@ -12,10 +12,15 @@ namespace llarp /// shared utility functions /// + constexpr auto addrIsV4 = [](const in6_addr& addr) -> bool { + return addr.s6_addr[10] == 0xff and addr.s6_addr[11] == 0xff; + }; + void SockAddr::init() { llarp::Zero(&m_addr, sizeof(m_addr)); + llarp::Zero(&m_addr4, sizeof(m_addr4)); } void @@ -96,7 +101,8 @@ namespace llarp // avoid byte order conversion (this is NBO -> NBO) memcpy(m_addr.sin6_addr.s6_addr + 12, &other.sin_addr.s_addr, sizeof(in_addr)); 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; return *this; @@ -113,7 +119,13 @@ namespace llarp init(); 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; return *this; @@ -130,7 +142,8 @@ namespace llarp init(); 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; return *this; @@ -141,6 +154,11 @@ namespace llarp return (sockaddr*)&m_addr; } + SockAddr::operator const sockaddr_in*() const + { + return &m_addr4; + } + SockAddr::operator const sockaddr_in6*() const { return &m_addr; @@ -244,15 +262,9 @@ namespace llarp // treat SIIT like IPv4 constexpr auto MaxIPv4PlusPortStringSize = 22; str.reserve(MaxIPv4PlusPortStringSize); - - // TODO: ensure these don't each incur a memory allocation - str.append(std::to_string(ip6[12])); - 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])); + char buf[128] = {0x0}; + inet_ntop(AF_INET, &m_addr4.sin_addr.s_addr, buf, sizeof(buf)); + str.append(buf); } else { @@ -281,7 +293,7 @@ namespace llarp void 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; llarp::Zero(ip6, sizeof(m_addr.sin6_addr.s6_addr)); @@ -292,7 +304,9 @@ namespace llarp ip6[13] = b; ip6[14] = c; 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; } @@ -300,6 +314,7 @@ namespace llarp SockAddr::setPort(uint16_t port) { m_addr.sin6_port = htons(port); + m_addr4.sin_port = htons(port); } uint16_t diff --git a/llarp/net/sock_addr.hpp b/llarp/net/sock_addr.hpp index 09ab1ff9e..4589271f0 100644 --- a/llarp/net/sock_addr.hpp +++ b/llarp/net/sock_addr.hpp @@ -49,6 +49,7 @@ namespace llarp operator=(const in6_addr& addr); operator const sockaddr*() const; + operator const sockaddr_in*() const; operator const sockaddr_in6*() const; bool @@ -82,6 +83,7 @@ namespace llarp private: bool m_empty = true; sockaddr_in6 m_addr; + sockaddr_in m_addr4; void init(); diff --git a/llarp/path/pathbuilder.cpp b/llarp/path/pathbuilder.cpp index 07bfddf76..88b5cd26d 100644 --- a/llarp/path/pathbuilder.cpp +++ b/llarp/path/pathbuilder.cpp @@ -476,7 +476,7 @@ namespace llarp void Builder::HandlePathBuildTimeout(Path_ptr p) { - m_router->routerProfiling().MarkPathFail(p.get()); + m_router->routerProfiling().MarkPathTimeout(p.get()); PathSet::HandlePathBuildTimeout(p); DoPathBuildBackoff(); } diff --git a/llarp/profiling.cpp b/llarp/profiling.cpp index e866cc62d..154eba367 100644 --- a/llarp/profiling.cpp +++ b/llarp/profiling.cpp @@ -15,6 +15,8 @@ namespace llarp return false; if (!BEncodeWriteDictInt("p", pathSuccessCount, buf)) return false; + if (!BEncodeWriteDictInt("q", pathTimeoutCount, buf)) + return false; if (!BEncodeWriteDictInt("s", pathFailCount, buf)) return false; if (!BEncodeWriteDictInt("t", connectTimeoutCount, buf)) @@ -43,6 +45,8 @@ namespace llarp return false; if (!BEncodeMaybeReadDictInt("p", pathSuccessCount, read, k, buf)) return false; + if (!BEncodeMaybeReadDictInt("q", pathTimeoutCount, read, k, buf)) + return false; return read; } @@ -53,14 +57,14 @@ namespace llarp connectTimeoutCount /= 2; pathSuccessCount /= 2; pathFailCount /= 2; + pathTimeoutCount /= 2; lastDecay = llarp::time_now_ms(); } void RouterProfile::Tick() { - // 15 seconds - static constexpr auto updateInterval = 15s; + static constexpr auto updateInterval = 30min; const auto now = llarp::time_now_ms(); if (lastDecay < now && now - lastDecay > updateInterval) Decay(); @@ -92,7 +96,8 @@ namespace llarp bool 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) @@ -119,7 +124,7 @@ namespace llarp auto itr = m_Profiles.find(r); if (itr == m_Profiles.end()) return false; - return !itr->second.IsGoodForConnect(chances); + return not itr->second.IsGoodForConnect(chances); } bool @@ -131,7 +136,7 @@ namespace llarp auto itr = m_Profiles.find(r); if (itr == m_Profiles.end()) return false; - return !itr->second.IsGoodForPath(chances); + return not itr->second.IsGoodForPath(chances); } bool @@ -143,7 +148,7 @@ namespace llarp auto itr = m_Profiles.find(r); if (itr == m_Profiles.end()) return false; - return !itr->second.IsGood(chances); + return not itr->second.IsGood(chances); } 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 Profiling::MarkPathSuccess(path::Path* p) { @@ -208,6 +229,10 @@ namespace llarp const auto sz = p->hops.size(); 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].lastUpdated = llarp::time_now_ms(); } diff --git a/llarp/profiling.hpp b/llarp/profiling.hpp index 13b52ab0d..a4fc656a0 100644 --- a/llarp/profiling.hpp +++ b/llarp/profiling.hpp @@ -18,6 +18,7 @@ namespace llarp uint64_t connectGoodCount = 0; uint64_t pathSuccessCount = 0; uint64_t pathFailCount = 0; + uint64_t pathTimeoutCount = 0; llarp_time_t lastUpdated = 0s; llarp_time_t lastDecay = 0s; uint64_t version = LLARP_PROTO_VERSION; @@ -68,6 +69,9 @@ namespace llarp void MarkConnectSuccess(const RouterID& r) EXCLUDES(m_ProfilesMutex); + void + MarkPathTimeout(path::Path* p) EXCLUDES(m_ProfilesMutex); + void MarkPathFail(path::Path* p) EXCLUDES(m_ProfilesMutex); diff --git a/vendor/libtuntap-master/tuntap-unix.c b/vendor/libtuntap-master/tuntap-unix.c index 564f935ae..535bc8817 100644 --- a/vendor/libtuntap-master/tuntap-unix.c +++ b/vendor/libtuntap-master/tuntap-unix.c @@ -100,7 +100,6 @@ tuntap_start(struct device *dev, int mode, int tun) } dev->tun_fd = fd; - tuntap_set_debug(dev, 0); return 0; clean: @@ -370,38 +369,3 @@ tuntap_set_nonblocking(struct device *dev, int set) } 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 -}