From 70b07bab4478e16380cf88410657c655edc00294 Mon Sep 17 00:00:00 2001 From: Jeff Date: Wed, 18 May 2022 17:06:32 -0400 Subject: [PATCH] clean up ip packet code --- llarp/handlers/exit.cpp | 17 +- llarp/handlers/exit.hpp | 11 +- llarp/handlers/tun.hpp | 8 - llarp/net/ip_packet.cpp | 1109 ++++++++++++++++++++------------------- llarp/net/ip_packet.hpp | 493 ++++++++--------- llarp/util/codel.hpp | 167 ------ 6 files changed, 789 insertions(+), 1016 deletions(-) delete mode 100644 llarp/util/codel.hpp diff --git a/llarp/handlers/exit.cpp b/llarp/handlers/exit.cpp index 7dc80f65a..73902ac04 100644 --- a/llarp/handlers/exit.cpp +++ b/llarp/handlers/exit.cpp @@ -23,8 +23,6 @@ namespace llarp , m_Name(std::move(name)) , m_LocalResolverAddr{"127.0.0.1:53"} , m_QUIC{std::make_shared(*this)} - , m_InetToNetwork(name + "_exit_rx", r->loop(), r->loop()) - { m_ShouldInitTun = true; m_QUIC = std::make_shared(*this); @@ -363,7 +361,11 @@ namespace llarp void ExitEndpoint::Flush() { - m_InetToNetwork.Process([&](Pkt_t& pkt) { + while (not m_InetToNetwork.empty()) + { + net::IPPacket pkt{m_InetToNetwork.top()}; + m_InetToNetwork.pop(); + PubKey pk; { auto itr = m_IPToKey.find(pkt.dstv6()); @@ -371,7 +373,7 @@ namespace llarp { // drop LogWarn(Name(), " dropping packet, has no session at ", pkt.dstv6()); - return; + continue; } pk = itr->second; } @@ -385,7 +387,7 @@ namespace llarp if (itr != m_SNodeSessions.end()) { itr->second->SendPacketToRemote(pkt.ConstBuffer(), service::ProtocolType::TrafficV4); - return; + continue; } } auto tryFlushingTraffic = [&](exit::Endpoint* const ep) -> bool { @@ -412,7 +414,8 @@ namespace llarp pk, " as we have no working endpoints"); } - }); + } + for (auto& [pubkey, endpoint] : m_ActiveExits) { if (!endpoint->Flush()) @@ -633,7 +636,7 @@ namespace llarp void ExitEndpoint::OnInetPacket(net::IPPacket pkt) { - m_InetToNetwork.Emplace(std::move(pkt)); + m_InetToNetwork.emplace(std::move(pkt)); } bool diff --git a/llarp/handlers/exit.hpp b/llarp/handlers/exit.hpp index d5053b8d2..5c2f3ec41 100644 --- a/llarp/handlers/exit.hpp +++ b/llarp/handlers/exit.hpp @@ -214,15 +214,8 @@ namespace llarp std::shared_ptr m_QUIC; - using Pkt_t = net::IPPacket; - using PacketQueue_t = util::CoDelQueue< - Pkt_t, - Pkt_t::GetTime, - Pkt_t::PutTime, - Pkt_t::CompareOrder, - Pkt_t::GetNow, - util::NullMutex, - util::NullLock>; + using PacketQueue_t = std:: + priority_queue, net::IPPacket::CompareOrder>; /// internet to llarp packet queue PacketQueue_t m_InetToNetwork; diff --git a/llarp/handlers/tun.hpp b/llarp/handlers/tun.hpp index fe93dfdae..74161754b 100644 --- a/llarp/handlers/tun.hpp +++ b/llarp/handlers/tun.hpp @@ -7,7 +7,6 @@ #include #include #include -#include #include #include @@ -174,13 +173,6 @@ namespace llarp ResetInternalState() override; protected: - using PacketQueue_t = llarp::util::CoDelQueue< - net::IPPacket, - net::IPPacket::GetTime, - net::IPPacket::PutTime, - net::IPPacket::CompareOrder, - net::IPPacket::GetNow>; - struct WritePacket { uint64_t seqno; diff --git a/llarp/net/ip_packet.cpp b/llarp/net/ip_packet.cpp index 5e287b6cd..d6e339ee5 100644 --- a/llarp/net/ip_packet.cpp +++ b/llarp/net/ip_packet.cpp @@ -13,642 +13,657 @@ #include #include -constexpr uint32_t ipv6_flowlabel_mask = 0b0000'0000'0000'1111'1111'1111'1111'1111; - -void -ipv6_header::FlowLabel(llarp::nuint32_t label) +namespace llarp::net { - // the ipv6 flow label is the last 20 bits in the first 32 bits of the header - preamble.flowlabel = - (htonl(ipv6_flowlabel_mask) & label.n) | (preamble.flowlabel & htonl(~ipv6_flowlabel_mask)); -} + constexpr uint32_t ipv6_flowlabel_mask = 0b0000'0000'0000'1111'1111'1111'1111'1111; -llarp::nuint32_t -ipv6_header::FlowLabel() const -{ - return llarp::nuint32_t{preamble.flowlabel & htonl(ipv6_flowlabel_mask)}; -} + template + struct ipv6_header_preamble + { + unsigned char pad_small : 4; + unsigned char version : 4; + uint8_t pad[3]; + }; -namespace llarp -{ - namespace net + template <> + struct ipv6_header_preamble { - std::string - IPProtocolName(IPProtocol proto) - { - if (const auto* ent = ::getprotobynumber(static_cast(proto))) - { - return ent->p_name; - } - throw std::invalid_argument{ - "cannot determine protocol name for ip proto '" + std::to_string(static_cast(proto)) - + "'"}; - } + unsigned char version : 4; + unsigned char pad_small : 4; + uint8_t pad[3]; + }; + + /// get 20 bit truncated flow label in network order + llarp::nuint32_t + ipv6_header::FlowLabel() const + { + return llarp::nuint32_t{preamble.flowlabel & htonl(ipv6_flowlabel_mask)}; + } + + /// put 20 bit truncated flow label network order + void + ipv6_header::FlowLabel(llarp::nuint32_t label) + { + // the ipv6 flow label is the last 20 bits in the first 32 bits of the header + preamble.flowlabel = + (htonl(ipv6_flowlabel_mask) & label.n) | (preamble.flowlabel & htonl(~ipv6_flowlabel_mask)); + }; - IPProtocol - ParseIPProtocol(std::string data) + std::string + IPProtocolName(IPProtocol proto) + { + if (const auto* ent = ::getprotobynumber(static_cast(proto))) { - if (const auto* ent = ::getprotobyname(data.c_str())) - { - return static_cast(ent->p_proto); - } - if (starts_with(data, "0x")) - { - if (const int intVal = std::stoi(data.substr(2), nullptr, 16); intVal > 0) - return static_cast(intVal); - } - throw std::invalid_argument{"no such ip protocol: '" + data + "'"}; + return ent->p_name; } + throw std::invalid_argument{ + "cannot determine protocol name for ip proto '" + std::to_string(static_cast(proto)) + + "'"}; + } - inline static uint32_t* - in6_uint32_ptr(in6_addr& addr) + IPProtocol + ParseIPProtocol(std::string data) + { + if (const auto* ent = ::getprotobyname(data.c_str())) { - return (uint32_t*)addr.s6_addr; + return static_cast(ent->p_proto); } - - inline static const uint32_t* - in6_uint32_ptr(const in6_addr& addr) + if (starts_with(data, "0x")) { - return (uint32_t*)addr.s6_addr; + if (const int intVal = std::stoi(data.substr(2), nullptr, 16); intVal > 0) + return static_cast(intVal); } + throw std::invalid_argument{"no such ip protocol: '" + data + "'"}; + } - huint128_t - IPPacket::srcv6() const - { - if (IsV6()) - return In6ToHUInt(HeaderV6()->srcaddr); + inline static uint32_t* + in6_uint32_ptr(in6_addr& addr) + { + return (uint32_t*)addr.s6_addr; + } - return ExpandV4(srcv4()); - } + inline static const uint32_t* + in6_uint32_ptr(const in6_addr& addr) + { + return (uint32_t*)addr.s6_addr; + } - huint128_t - IPPacket::dstv6() const - { - if (IsV6()) - return In6ToHUInt(HeaderV6()->dstaddr); + huint128_t + IPPacket::srcv6() const + { + if (IsV6()) + return In6ToHUInt(HeaderV6()->srcaddr); - return ExpandV4(dstv4()); - } + return ExpandV4(srcv4()); + } - bool - IPPacket::Load(const llarp_buffer_t& pkt) - { - if (pkt.sz > sizeof(buf) or pkt.sz == 0) - return false; - sz = pkt.sz; - std::copy_n(pkt.base, sz, buf); - return true; - } + huint128_t + IPPacket::dstv6() const + { + if (IsV6()) + return In6ToHUInt(HeaderV6()->dstaddr); - ManagedBuffer - IPPacket::ConstBuffer() const - { - const byte_t* ptr = buf; - llarp_buffer_t b(ptr, sz); - return ManagedBuffer(b); - } + return ExpandV4(dstv4()); + } - ManagedBuffer - IPPacket::Buffer() - { - byte_t* ptr = buf; - llarp_buffer_t b(ptr, sz); - return ManagedBuffer(b); - } + bool + IPPacket::Load(const llarp_buffer_t& pkt) + { + if (pkt.sz > sizeof(buf) or pkt.sz == 0) + return false; + sz = pkt.sz; + std::copy_n(pkt.base, sz, buf); + return true; + } + + ManagedBuffer + IPPacket::ConstBuffer() const + { + const byte_t* ptr = buf; + llarp_buffer_t b(ptr, sz); + return ManagedBuffer(b); + } - std::optional - IPPacket::DstPort() const - { - switch (IPProtocol{Header()->protocol}) - { - case IPProtocol::TCP: - case IPProtocol::UDP: - return nuint16_t{*reinterpret_cast(buf + (Header()->ihl * 4) + 2)}; - default: - return std::nullopt; - } - } + ManagedBuffer + IPPacket::Buffer() + { + byte_t* ptr = buf; + llarp_buffer_t b(ptr, sz); + return ManagedBuffer(b); + } - std::optional - IPPacket::SrcPort() const + std::optional + IPPacket::DstPort() const + { + switch (IPProtocol{Header()->protocol}) { - switch (IPProtocol{Header()->protocol}) - { - case IPProtocol::TCP: - case IPProtocol::UDP: - return nuint16_t{*reinterpret_cast(buf + (Header()->ihl * 4))}; - default: - return std::nullopt; - } + case IPProtocol::TCP: + case IPProtocol::UDP: + return nuint16_t{*reinterpret_cast(buf + (Header()->ihl * 4) + 2)}; + default: + return std::nullopt; } + } - huint32_t - IPPacket::srcv4() const + std::optional + IPPacket::SrcPort() const + { + switch (IPProtocol{Header()->protocol}) { - return huint32_t{ntohl(Header()->saddr)}; + case IPProtocol::TCP: + case IPProtocol::UDP: + return nuint16_t{*reinterpret_cast(buf + (Header()->ihl * 4))}; + default: + return std::nullopt; } + } - huint32_t - IPPacket::dstv4() const - { - return huint32_t{ntohl(Header()->daddr)}; - } + huint32_t + IPPacket::srcv4() const + { + return huint32_t{ntohl(Header()->saddr)}; + } - huint128_t - IPPacket::dst4to6() const - { - return ExpandV4(dstv4()); - } + huint32_t + IPPacket::dstv4() const + { + return huint32_t{ntohl(Header()->daddr)}; + } - huint128_t - IPPacket::src4to6() const - { - return ExpandV4(srcv4()); - } + huint128_t + IPPacket::dst4to6() const + { + return ExpandV4(dstv4()); + } - huint128_t - IPPacket::dst4to6Lan() const - { - return ExpandV4Lan(dstv4()); - } + huint128_t + IPPacket::src4to6() const + { + return ExpandV4(srcv4()); + } - huint128_t - IPPacket::src4to6Lan() const + huint128_t + IPPacket::dst4to6Lan() const + { + return ExpandV4Lan(dstv4()); + } + + huint128_t + IPPacket::src4to6Lan() const + { + return ExpandV4Lan(srcv4()); + } + + uint16_t + ipchksum(const byte_t* buf, size_t sz, uint32_t sum) + { + while (sz > 1) { - return ExpandV4Lan(srcv4()); + sum += *(const uint16_t*)buf; + sz -= sizeof(uint16_t); + buf += sizeof(uint16_t); } - - uint16_t - ipchksum(const byte_t* buf, size_t sz, uint32_t sum) + if (sz != 0) { - while (sz > 1) - { - sum += *(const uint16_t*)buf; - sz -= sizeof(uint16_t); - buf += sizeof(uint16_t); - } - if (sz != 0) - { - uint16_t x = 0; + uint16_t x = 0; - *(byte_t*)&x = *(const byte_t*)buf; - sum += x; - } + *(byte_t*)&x = *(const byte_t*)buf; + sum += x; + } - // only need to do it 2 times to be sure - // proof: 0xFFff + 0xFFff = 0x1FFfe -> 0xFFff - sum = (sum & 0xFFff) + (sum >> 16); - sum += sum >> 16; + // only need to do it 2 times to be sure + // proof: 0xFFff + 0xFFff = 0x1FFfe -> 0xFFff + sum = (sum & 0xFFff) + (sum >> 16); + sum += sum >> 16; - return uint16_t((~sum) & 0xFFff); - } + return uint16_t((~sum) & 0xFFff); + } #define ADD32CS(x) ((uint32_t)(x & 0xFFff) + (uint32_t)(x >> 16)) #define SUB32CS(x) ((uint32_t)((~x) & 0xFFff) + (uint32_t)((~x) >> 16)) - static nuint16_t - deltaIPv4Checksum( - nuint16_t old_sum, - nuint32_t old_src_ip, - nuint32_t old_dst_ip, - nuint32_t new_src_ip, - nuint32_t new_dst_ip) - { - uint32_t sum = uint32_t(old_sum.n) + ADD32CS(old_src_ip.n) + ADD32CS(old_dst_ip.n) - + SUB32CS(new_src_ip.n) + SUB32CS(new_dst_ip.n); - - // only need to do it 2 times to be sure - // proof: 0xFFff + 0xFFff = 0x1FFfe -> 0xFFff - sum = (sum & 0xFFff) + (sum >> 16); - sum += sum >> 16; - - return nuint16_t{uint16_t(sum & 0xFFff)}; - } - - static nuint16_t - deltaIPv6Checksum( - nuint16_t old_sum, - const uint32_t old_src_ip[4], - const uint32_t old_dst_ip[4], - const uint32_t new_src_ip[4], - const uint32_t new_dst_ip[4]) - { - /* we don't actually care in what way integers are arranged in memory - * internally */ - /* as long as uint16 pairs are swapped in correct direction, result will - * be correct (assuming there are no gaps in structure) */ - /* we represent 128bit stuff there as 4 32bit ints, that should be more or - * less correct */ - /* we could do 64bit ints too but then we couldn't reuse 32bit macros and - * that'd suck for 32bit cpus */ + static nuint16_t + deltaIPv4Checksum( + nuint16_t old_sum, + nuint32_t old_src_ip, + nuint32_t old_dst_ip, + nuint32_t new_src_ip, + nuint32_t new_dst_ip) + { + uint32_t sum = uint32_t(old_sum.n) + ADD32CS(old_src_ip.n) + ADD32CS(old_dst_ip.n) + + SUB32CS(new_src_ip.n) + SUB32CS(new_dst_ip.n); + + // only need to do it 2 times to be sure + // proof: 0xFFff + 0xFFff = 0x1FFfe -> 0xFFff + sum = (sum & 0xFFff) + (sum >> 16); + sum += sum >> 16; + + return nuint16_t{uint16_t(sum & 0xFFff)}; + } + + static nuint16_t + deltaIPv6Checksum( + nuint16_t old_sum, + const uint32_t old_src_ip[4], + const uint32_t old_dst_ip[4], + const uint32_t new_src_ip[4], + const uint32_t new_dst_ip[4]) + { + /* we don't actually care in what way integers are arranged in memory + * internally */ + /* as long as uint16 pairs are swapped in correct direction, result will + * be correct (assuming there are no gaps in structure) */ + /* we represent 128bit stuff there as 4 32bit ints, that should be more or + * less correct */ + /* we could do 64bit ints too but then we couldn't reuse 32bit macros and + * that'd suck for 32bit cpus */ #define ADDN128CS(x) (ADD32CS(x[0]) + ADD32CS(x[1]) + ADD32CS(x[2]) + ADD32CS(x[3])) #define SUBN128CS(x) (SUB32CS(x[0]) + SUB32CS(x[1]) + SUB32CS(x[2]) + SUB32CS(x[3])) - uint32_t sum = uint32_t(old_sum.n) + ADDN128CS(old_src_ip) + ADDN128CS(old_dst_ip) - + SUBN128CS(new_src_ip) + SUBN128CS(new_dst_ip); + uint32_t sum = uint32_t(old_sum.n) + ADDN128CS(old_src_ip) + ADDN128CS(old_dst_ip) + + SUBN128CS(new_src_ip) + SUBN128CS(new_dst_ip); #undef ADDN128CS #undef SUBN128CS - // only need to do it 2 times to be sure - // proof: 0xFFff + 0xFFff = 0x1FFfe -> 0xFFff - sum = (sum & 0xFFff) + (sum >> 16); - sum += sum >> 16; + // only need to do it 2 times to be sure + // proof: 0xFFff + 0xFFff = 0x1FFfe -> 0xFFff + sum = (sum & 0xFFff) + (sum >> 16); + sum += sum >> 16; - return nuint16_t{uint16_t(sum & 0xFFff)}; - } + return nuint16_t{uint16_t(sum & 0xFFff)}; + } #undef ADD32CS #undef SUB32CS - static void - deltaChecksumIPv4TCP( - byte_t* pld, - size_t psz, - size_t fragoff, - size_t chksumoff, - nuint32_t oSrcIP, - nuint32_t oDstIP, - nuint32_t nSrcIP, - nuint32_t nDstIP) - { - if (fragoff > chksumoff || psz < chksumoff - fragoff + 2) - return; - - auto check = (nuint16_t*)(pld + chksumoff - fragoff); - - *check = deltaIPv4Checksum(*check, oSrcIP, oDstIP, nSrcIP, nDstIP); - // usually, TCP checksum field cannot be 0xFFff, - // because one's complement addition cannot result in 0x0000, - // and there's inversion in the end; - // emulate that. - if (check->n == 0xFFff) - check->n = 0x0000; - } - - static void - deltaChecksumIPv6TCP( - byte_t* pld, - size_t psz, - size_t fragoff, - size_t chksumoff, - const uint32_t oSrcIP[4], - const uint32_t oDstIP[4], - const uint32_t nSrcIP[4], - const uint32_t nDstIP[4]) - { - if (fragoff > chksumoff || psz < chksumoff - fragoff + 2) - return; - - auto check = (nuint16_t*)(pld + chksumoff - fragoff); - - *check = deltaIPv6Checksum(*check, oSrcIP, oDstIP, nSrcIP, nDstIP); - // usually, TCP checksum field cannot be 0xFFff, - // because one's complement addition cannot result in 0x0000, - // and there's inversion in the end; - // emulate that. - if (check->n == 0xFFff) - check->n = 0x0000; - } + static void + deltaChecksumIPv4TCP( + byte_t* pld, + size_t psz, + size_t fragoff, + size_t chksumoff, + nuint32_t oSrcIP, + nuint32_t oDstIP, + nuint32_t nSrcIP, + nuint32_t nDstIP) + { + if (fragoff > chksumoff || psz < chksumoff - fragoff + 2) + return; + + auto check = (nuint16_t*)(pld + chksumoff - fragoff); + + *check = deltaIPv4Checksum(*check, oSrcIP, oDstIP, nSrcIP, nDstIP); + // usually, TCP checksum field cannot be 0xFFff, + // because one's complement addition cannot result in 0x0000, + // and there's inversion in the end; + // emulate that. + if (check->n == 0xFFff) + check->n = 0x0000; + } + + static void + deltaChecksumIPv6TCP( + byte_t* pld, + size_t psz, + size_t fragoff, + size_t chksumoff, + const uint32_t oSrcIP[4], + const uint32_t oDstIP[4], + const uint32_t nSrcIP[4], + const uint32_t nDstIP[4]) + { + if (fragoff > chksumoff || psz < chksumoff - fragoff + 2) + return; + + auto check = (nuint16_t*)(pld + chksumoff - fragoff); + + *check = deltaIPv6Checksum(*check, oSrcIP, oDstIP, nSrcIP, nDstIP); + // usually, TCP checksum field cannot be 0xFFff, + // because one's complement addition cannot result in 0x0000, + // and there's inversion in the end; + // emulate that. + if (check->n == 0xFFff) + check->n = 0x0000; + } + + static void + deltaChecksumIPv4UDP( + byte_t* pld, + size_t psz, + size_t fragoff, + nuint32_t oSrcIP, + nuint32_t oDstIP, + nuint32_t nSrcIP, + nuint32_t nDstIP) + { + if (fragoff > 6 || psz < 6 + 2) + return; + + auto check = (nuint16_t*)(pld + 6); + if (check->n == 0x0000) + return; // 0 is used to indicate "no checksum", don't change + + *check = deltaIPv4Checksum(*check, oSrcIP, oDstIP, nSrcIP, nDstIP); + // 0 is used to indicate "no checksum" + // 0xFFff and 0 are equivalent in one's complement math + // 0xFFff + 1 = 0x10000 -> 0x0001 (same as 0 + 1) + // infact it's impossible to get 0 with such addition, + // when starting from non-0 value. + // inside deltachksum we don't invert so it's safe to skip check there + // if(check->n == 0x0000) + // check->n = 0xFFff; + } + + static void + deltaChecksumIPv6UDP( + byte_t* pld, + size_t psz, + size_t fragoff, + const uint32_t oSrcIP[4], + const uint32_t oDstIP[4], + const uint32_t nSrcIP[4], + const uint32_t nDstIP[4]) + { + if (fragoff > 6 || psz < 6 + 2) + return; + + auto check = (nuint16_t*)(pld + 6); + // 0 is used to indicate "no checksum", don't change + // even tho this shouldn't happen for IPv6, handle it properly + // we actually should drop/log 0-checksum packets per spec + // but that should be done at upper level than this function + // it's better to do correct thing there regardless + // XXX or maybe we should change this function to be able to return error? + // either way that's not a priority + if (check->n == 0x0000) + return; + + *check = deltaIPv6Checksum(*check, oSrcIP, oDstIP, nSrcIP, nDstIP); + // 0 is used to indicate "no checksum" + // 0xFFff and 0 are equivalent in one's complement math + // 0xFFff + 1 = 0x10000 -> 0x0001 (same as 0 + 1) + // infact it's impossible to get 0 with such addition, + // when starting from non-0 value. + // inside deltachksum we don't invert so it's safe to skip check there + // if(check->n == 0x0000) + // check->n = 0xFFff; + } + + void + IPPacket::UpdateIPv4Address(nuint32_t nSrcIP, nuint32_t nDstIP) + { + llarp::LogDebug("set src=", nSrcIP, " dst=", nDstIP); - static void - deltaChecksumIPv4UDP( - byte_t* pld, - size_t psz, - size_t fragoff, - nuint32_t oSrcIP, - nuint32_t oDstIP, - nuint32_t nSrcIP, - nuint32_t nDstIP) - { - if (fragoff > 6 || psz < 6 + 2) - return; - - auto check = (nuint16_t*)(pld + 6); - if (check->n == 0x0000) - return; // 0 is used to indicate "no checksum", don't change - - *check = deltaIPv4Checksum(*check, oSrcIP, oDstIP, nSrcIP, nDstIP); - // 0 is used to indicate "no checksum" - // 0xFFff and 0 are equivalent in one's complement math - // 0xFFff + 1 = 0x10000 -> 0x0001 (same as 0 + 1) - // infact it's impossible to get 0 with such addition, - // when starting from non-0 value. - // inside deltachksum we don't invert so it's safe to skip check there - // if(check->n == 0x0000) - // check->n = 0xFFff; - } + auto hdr = Header(); - static void - deltaChecksumIPv6UDP( - byte_t* pld, - size_t psz, - size_t fragoff, - const uint32_t oSrcIP[4], - const uint32_t oDstIP[4], - const uint32_t nSrcIP[4], - const uint32_t nDstIP[4]) - { - if (fragoff > 6 || psz < 6 + 2) - return; - - auto check = (nuint16_t*)(pld + 6); - // 0 is used to indicate "no checksum", don't change - // even tho this shouldn't happen for IPv6, handle it properly - // we actually should drop/log 0-checksum packets per spec - // but that should be done at upper level than this function - // it's better to do correct thing there regardless - // XXX or maybe we should change this function to be able to return error? - // either way that's not a priority - if (check->n == 0x0000) - return; - - *check = deltaIPv6Checksum(*check, oSrcIP, oDstIP, nSrcIP, nDstIP); - // 0 is used to indicate "no checksum" - // 0xFFff and 0 are equivalent in one's complement math - // 0xFFff + 1 = 0x10000 -> 0x0001 (same as 0 + 1) - // infact it's impossible to get 0 with such addition, - // when starting from non-0 value. - // inside deltachksum we don't invert so it's safe to skip check there - // if(check->n == 0x0000) - // check->n = 0xFFff; - } + auto oSrcIP = nuint32_t{hdr->saddr}; + auto oDstIP = nuint32_t{hdr->daddr}; - void - IPPacket::UpdateIPv4Address(nuint32_t nSrcIP, nuint32_t nDstIP) + // L4 checksum + auto ihs = size_t(hdr->ihl * 4); + if (ihs <= sz) { - llarp::LogDebug("set src=", nSrcIP, " dst=", nDstIP); - - auto hdr = Header(); + auto pld = buf + ihs; + auto psz = sz - ihs; - auto oSrcIP = nuint32_t{hdr->saddr}; - auto oDstIP = nuint32_t{hdr->daddr}; + auto fragoff = size_t((ntohs(hdr->frag_off) & 0x1Fff) * 8); - // L4 checksum - auto ihs = size_t(hdr->ihl * 4); - if (ihs <= sz) + switch (hdr->protocol) { - auto pld = buf + ihs; - auto psz = sz - ihs; - - auto fragoff = size_t((ntohs(hdr->frag_off) & 0x1Fff) * 8); - - switch (hdr->protocol) - { - case 6: // TCP - deltaChecksumIPv4TCP(pld, psz, fragoff, 16, oSrcIP, oDstIP, nSrcIP, nDstIP); - break; - case 17: // UDP - case 136: // UDP-Lite - same checksum place, same 0->0xFFff condition - deltaChecksumIPv4UDP(pld, psz, fragoff, oSrcIP, oDstIP, nSrcIP, nDstIP); - break; - case 33: // DCCP - deltaChecksumIPv4TCP(pld, psz, fragoff, 6, oSrcIP, oDstIP, nSrcIP, nDstIP); - break; - } + case 6: // TCP + deltaChecksumIPv4TCP(pld, psz, fragoff, 16, oSrcIP, oDstIP, nSrcIP, nDstIP); + break; + case 17: // UDP + case 136: // UDP-Lite - same checksum place, same 0->0xFFff condition + deltaChecksumIPv4UDP(pld, psz, fragoff, oSrcIP, oDstIP, nSrcIP, nDstIP); + break; + case 33: // DCCP + deltaChecksumIPv4TCP(pld, psz, fragoff, 6, oSrcIP, oDstIP, nSrcIP, nDstIP); + break; } + } - // IPv4 checksum - auto v4chk = (nuint16_t*)&(hdr->check); - *v4chk = deltaIPv4Checksum(*v4chk, oSrcIP, oDstIP, nSrcIP, nDstIP); + // IPv4 checksum + auto v4chk = (nuint16_t*)&(hdr->check); + *v4chk = deltaIPv4Checksum(*v4chk, oSrcIP, oDstIP, nSrcIP, nDstIP); - // write new IP addresses - hdr->saddr = nSrcIP.n; - hdr->daddr = nDstIP.n; - } + // write new IP addresses + hdr->saddr = nSrcIP.n; + hdr->daddr = nDstIP.n; + } - void - IPPacket::UpdateIPv6Address(huint128_t src, huint128_t dst, std::optional flowlabel) - { - const size_t ihs = 4 + 4 + 16 + 16; + void + IPPacket::UpdateIPv6Address(huint128_t src, huint128_t dst, std::optional flowlabel) + { + const size_t ihs = 4 + 4 + 16 + 16; - // XXX should've been checked at upper level? - if (sz <= ihs) - return; + // XXX should've been checked at upper level? + if (sz <= ihs) + return; - auto hdr = HeaderV6(); - if (flowlabel.has_value()) - { - // set flow label if desired - hdr->FlowLabel(*flowlabel); - } + auto hdr = HeaderV6(); + if (flowlabel.has_value()) + { + // set flow label if desired + hdr->FlowLabel(*flowlabel); + } - const auto oldSrcIP = hdr->srcaddr; - const auto oldDstIP = hdr->dstaddr; - const uint32_t* oSrcIP = in6_uint32_ptr(oldSrcIP); - const uint32_t* oDstIP = in6_uint32_ptr(oldDstIP); + const auto oldSrcIP = hdr->srcaddr; + const auto oldDstIP = hdr->dstaddr; + const uint32_t* oSrcIP = in6_uint32_ptr(oldSrcIP); + const uint32_t* oDstIP = in6_uint32_ptr(oldDstIP); - // IPv6 address - hdr->srcaddr = HUIntToIn6(src); - hdr->dstaddr = HUIntToIn6(dst); - const uint32_t* nSrcIP = in6_uint32_ptr(hdr->srcaddr); - const uint32_t* nDstIP = in6_uint32_ptr(hdr->dstaddr); + // IPv6 address + hdr->srcaddr = HUIntToIn6(src); + hdr->dstaddr = HUIntToIn6(dst); + const uint32_t* nSrcIP = in6_uint32_ptr(hdr->srcaddr); + const uint32_t* nDstIP = in6_uint32_ptr(hdr->dstaddr); - // TODO IPv6 header options - auto pld = buf + ihs; - auto psz = sz - ihs; + // TODO IPv6 header options + auto pld = buf + ihs; + auto psz = sz - ihs; - size_t fragoff = 0; - auto nextproto = hdr->proto; - for (;;) + size_t fragoff = 0; + auto nextproto = hdr->proto; + for (;;) + { + switch (nextproto) { - switch (nextproto) + case 0: // Hop-by-Hop Options + case 43: // Routing Header + case 60: // Destination Options { - case 0: // Hop-by-Hop Options - case 43: // Routing Header - case 60: // Destination Options - { - nextproto = pld[0]; - auto addlen = (size_t(pld[1]) + 1) * 8; - if (psz < addlen) - return; - pld += addlen; - psz -= addlen; - break; - } - - case 44: // Fragment Header - /* - +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - | Next Header | Reserved | Fragment Offset |Res|M| - +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - | Identification | - +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - */ - nextproto = pld[0]; - fragoff = (uint16_t(pld[2]) << 8) | (uint16_t(pld[3]) & 0xFC); - if (psz < 8) - return; - pld += 8; - psz -= 8; - - // jump straight to payload processing - if (fragoff != 0) - goto endprotohdrs; - break; - - default: - goto endprotohdrs; + nextproto = pld[0]; + auto addlen = (size_t(pld[1]) + 1) * 8; + if (psz < addlen) + return; + pld += addlen; + psz -= addlen; + break; } - } - endprotohdrs: - switch (nextproto) - { - case 6: // TCP - deltaChecksumIPv6TCP(pld, psz, fragoff, 16, oSrcIP, oDstIP, nSrcIP, nDstIP); - break; - case 17: // UDP - case 136: // UDP-Lite - same checksum place, same 0->0xFFff condition - deltaChecksumIPv6UDP(pld, psz, fragoff, oSrcIP, oDstIP, nSrcIP, nDstIP); - break; - case 33: // DCCP - deltaChecksumIPv6TCP(pld, psz, fragoff, 6, oSrcIP, oDstIP, nSrcIP, nDstIP); + case 44: // Fragment Header + /* + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + | Next Header | Reserved | Fragment Offset |Res|M| + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + | Identification | + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + */ + nextproto = pld[0]; + fragoff = (uint16_t(pld[2]) << 8) | (uint16_t(pld[3]) & 0xFC); + if (psz < 8) + return; + pld += 8; + psz -= 8; + + // jump straight to payload processing + if (fragoff != 0) + goto endprotohdrs; break; + + default: + goto endprotohdrs; } } + endprotohdrs: - void - IPPacket::ZeroAddresses(std::optional flowlabel) + switch (nextproto) { - if (IsV4()) - { - UpdateIPv4Address({0}, {0}); - } - else if (IsV6()) - { - UpdateIPv6Address({0}, {0}, flowlabel); - } + case 6: // TCP + deltaChecksumIPv6TCP(pld, psz, fragoff, 16, oSrcIP, oDstIP, nSrcIP, nDstIP); + break; + case 17: // UDP + case 136: // UDP-Lite - same checksum place, same 0->0xFFff condition + deltaChecksumIPv6UDP(pld, psz, fragoff, oSrcIP, oDstIP, nSrcIP, nDstIP); + break; + case 33: // DCCP + deltaChecksumIPv6TCP(pld, psz, fragoff, 6, oSrcIP, oDstIP, nSrcIP, nDstIP); + break; } + } - void - IPPacket::ZeroSourceAddress(std::optional flowlabel) + void + IPPacket::ZeroAddresses(std::optional flowlabel) + { + if (IsV4()) { - if (IsV4()) - { - UpdateIPv4Address({0}, xhtonl(dstv4())); - } - else if (IsV6()) - { - UpdateIPv6Address({0}, dstv6(), flowlabel); - } + UpdateIPv4Address({0}, {0}); } - - std::optional - IPPacket::MakeICMPUnreachable() const + else if (IsV6()) { - if (IsV4()) - { - constexpr auto icmp_Header_size = 8; - constexpr auto ip_Header_size = 20; - net::IPPacket pkt{}; - auto* pkt_Header = pkt.Header(); - - pkt_Header->version = 4; - pkt_Header->ihl = 0x05; - pkt_Header->tos = 0; - pkt_Header->check = 0; - pkt_Header->tot_len = ntohs(icmp_Header_size + ip_Header_size); - pkt_Header->saddr = Header()->daddr; - pkt_Header->daddr = Header()->saddr; - pkt_Header->protocol = 1; // ICMP - pkt_Header->ttl = 1; - pkt_Header->frag_off = htons(0b0100000000000000); - // size pf ip header - const size_t l3_HeaderSize = Header()->ihl * 4; - // size of l4 packet to reflect back - const size_t l4_PacketSize = 8; - pkt_Header->tot_len += ntohs(l4_PacketSize + l3_HeaderSize); - - uint16_t* checksum; - uint8_t* itr = pkt.buf + (pkt_Header->ihl * 4); - uint8_t* icmp_begin = itr; // type 'destination unreachable' - *itr++ = 3; - // code 'Destination host unknown error' - *itr++ = 7; - // checksum + unused - oxenc::write_host_as_big(0, itr); - checksum = (uint16_t*)itr; - itr += 4; - // next hop mtu is ignored but let's put something here anyways just in case tm - oxenc::write_host_as_big(1500, itr); - itr += 2; - // copy ip header and first 8 bytes of datagram for icmp rject - std::copy_n(buf, l4_PacketSize + l3_HeaderSize, itr); - itr += l4_PacketSize + l3_HeaderSize; - // calculate checksum of ip header - pkt_Header->check = ipchksum(pkt.buf, pkt_Header->ihl * 4); - const auto icmp_size = std::distance(icmp_begin, itr); - // calculate icmp checksum - *checksum = ipchksum(icmp_begin, icmp_size); - pkt.sz = ntohs(pkt_Header->tot_len); - return pkt; - } - return std::nullopt; + UpdateIPv6Address({0}, {0}, flowlabel); } + } - std::optional> - IPPacket::L4Data() const + void + IPPacket::ZeroSourceAddress(std::optional flowlabel) + { + if (IsV4()) { - const auto* hdr = Header(); - size_t l4_HeaderSize = 0; - if (hdr->protocol == 0x11) - { - l4_HeaderSize = 8; - } - else - return std::nullopt; - - // check for invalid size - if (sz < (hdr->ihl * 4) + l4_HeaderSize) - return std::nullopt; + UpdateIPv4Address({0}, xhtonl(dstv4())); + } + else if (IsV6()) + { + UpdateIPv6Address({0}, dstv6(), flowlabel); + } + } - const uint8_t* ptr = buf + ((hdr->ihl * 4) + l4_HeaderSize); - return std::make_pair(reinterpret_cast(ptr), std::distance(ptr, buf + sz)); + std::optional + IPPacket::MakeICMPUnreachable() const + { + if (IsV4()) + { + constexpr auto icmp_Header_size = 8; + constexpr auto ip_Header_size = 20; + net::IPPacket pkt{}; + auto* pkt_Header = pkt.Header(); + + pkt_Header->version = 4; + pkt_Header->ihl = 0x05; + pkt_Header->tos = 0; + pkt_Header->check = 0; + pkt_Header->tot_len = ntohs(icmp_Header_size + ip_Header_size); + pkt_Header->saddr = Header()->daddr; + pkt_Header->daddr = Header()->saddr; + pkt_Header->protocol = 1; // ICMP + pkt_Header->ttl = 1; + pkt_Header->frag_off = htons(0b0100000000000000); + // size pf ip header + const size_t l3_HeaderSize = Header()->ihl * 4; + // size of l4 packet to reflect back + const size_t l4_PacketSize = 8; + pkt_Header->tot_len += ntohs(l4_PacketSize + l3_HeaderSize); + + uint16_t* checksum; + uint8_t* itr = pkt.buf + (pkt_Header->ihl * 4); + uint8_t* icmp_begin = itr; // type 'destination unreachable' + *itr++ = 3; + // code 'Destination host unknown error' + *itr++ = 7; + // checksum + unused + oxenc::write_host_as_big(0, itr); + checksum = (uint16_t*)itr; + itr += 4; + // next hop mtu is ignored but let's put something here anyways just in case tm + oxenc::write_host_as_big(1500, itr); + itr += 2; + // copy ip header and first 8 bytes of datagram for icmp rject + std::copy_n(buf, l4_PacketSize + l3_HeaderSize, itr); + itr += l4_PacketSize + l3_HeaderSize; + // calculate checksum of ip header + pkt_Header->check = ipchksum(pkt.buf, pkt_Header->ihl * 4); + const auto icmp_size = std::distance(icmp_begin, itr); + // calculate icmp checksum + *checksum = ipchksum(icmp_begin, icmp_size); + pkt.sz = ntohs(pkt_Header->tot_len); + return pkt; } + return std::nullopt; + } - IPPacket - IPPacket::UDP( - nuint32_t srcaddr, - nuint16_t srcport, - nuint32_t dstaddr, - nuint16_t dstport, - const llarp_buffer_t& buf) + std::optional> + IPPacket::L4Data() const + { + const auto* hdr = Header(); + size_t l4_HeaderSize = 0; + if (hdr->protocol == 0x11) { - net::IPPacket pkt; + l4_HeaderSize = 8; + } + else + return std::nullopt; - if (buf.sz + 28 > sizeof(pkt.buf)) - { - pkt.sz = 0; - return pkt; - } - auto* hdr = pkt.Header(); - pkt.buf[1] = 0; - hdr->version = 4; - hdr->ihl = 5; - hdr->tot_len = htons(buf.sz + 28); - hdr->protocol = 0x11; // udp - hdr->ttl = 64; - hdr->frag_off = htons(0b0100000000000000); - - hdr->saddr = srcaddr.n; - hdr->daddr = dstaddr.n; - - // make udp packet - uint8_t* ptr = pkt.buf + 20; - std::memcpy(ptr, &srcport.n, 2); - ptr += 2; - std::memcpy(ptr, &dstport.n, 2); - ptr += 2; - oxenc::write_host_as_big(static_cast(buf.sz + 8), ptr); - ptr += 2; - oxenc::write_host_as_big(uint16_t{0}, ptr); // checksum - ptr += 2; - std::copy_n(buf.base, buf.sz, ptr); - - hdr->check = 0; - hdr->check = net::ipchksum(pkt.buf, 20); - pkt.sz = 28 + buf.sz; + // check for invalid size + if (sz < (hdr->ihl * 4) + l4_HeaderSize) + return std::nullopt; + + const uint8_t* ptr = buf + ((hdr->ihl * 4) + l4_HeaderSize); + return std::make_pair(reinterpret_cast(ptr), std::distance(ptr, buf + sz)); + } + + IPPacket + IPPacket::UDP( + nuint32_t srcaddr, + nuint16_t srcport, + nuint32_t dstaddr, + nuint16_t dstport, + const llarp_buffer_t& buf) + { + net::IPPacket pkt; + + if (buf.sz + 28 > sizeof(pkt.buf)) + { + pkt.sz = 0; return pkt; } - - } // namespace net -} // namespace llarp + auto* hdr = pkt.Header(); + pkt.buf[1] = 0; + hdr->version = 4; + hdr->ihl = 5; + hdr->tot_len = htons(buf.sz + 28); + hdr->protocol = 0x11; // udp + hdr->ttl = 64; + hdr->frag_off = htons(0b0100000000000000); + + hdr->saddr = srcaddr.n; + hdr->daddr = dstaddr.n; + + // make udp packet + uint8_t* ptr = pkt.buf + 20; + std::memcpy(ptr, &srcport.n, 2); + ptr += 2; + std::memcpy(ptr, &dstport.n, 2); + ptr += 2; + oxenc::write_host_as_big(static_cast(buf.sz + 8), ptr); + ptr += 2; + oxenc::write_host_as_big(uint16_t{0}, ptr); // checksum + ptr += 2; + std::copy_n(buf.base, buf.sz, ptr); + + hdr->check = 0; + hdr->check = net::ipchksum(pkt.buf, 20); + pkt.sz = 28 + buf.sz; + return pkt; + } + +} // namespace llarp::net diff --git a/llarp/net/ip_packet.hpp b/llarp/net/ip_packet.hpp index b9e3c4ddd..f0cc63f94 100644 --- a/llarp/net/ip_packet.hpp +++ b/llarp/net/ip_packet.hpp @@ -4,324 +4,261 @@ #include "net.hpp" #include #include -#include // Guarantees __{LITTLE,BIG}_ENDIAN__ defines - -#ifndef _WIN32 -// unix, linux -#include // FreeBSD needs this for uchar for ip.h -#include -#include -// anything not win32 -struct ip_header -{ -#ifdef __LITTLE_ENDIAN__ - unsigned int ihl : 4; - unsigned int version : 4; -#else - unsigned int version : 4; - unsigned int ihl : 4; -#endif - -#if defined(__linux__) -#define ip_version version -#endif - uint8_t tos; - uint16_t tot_len; - uint16_t id; - uint16_t frag_off; - uint8_t ttl; - uint8_t protocol; - uint16_t check; - uint32_t saddr; - uint32_t daddr; -}; -#else -// windows nt -#include -typedef struct ip_hdr -{ - unsigned char ip_header_len : 4; // 4-bit header length (in 32-bit words) normally=5 - // (Means 20 Bytes may be 24 also) - unsigned char version : 4; // 4-bit IPv4 version - unsigned char ip_tos; // IP type of service - unsigned short ip_total_length; // Total length - unsigned short ip_id; // Unique identifier - - unsigned char ip_frag_offset : 5; // Fragment offset field - - unsigned char ip_more_fragment : 1; - unsigned char ip_dont_fragment : 1; - unsigned char ip_reserved_zero : 1; - - unsigned char ip_frag_offset1; // fragment offset - - unsigned char ip_ttl; // Time to live - unsigned char ip_protocol; // Protocol(TCP,UDP etc) - unsigned short ip_checksum; // IP checksum - unsigned int ip_srcaddr; // Source address - unsigned int ip_destaddr; // Source address -} IPV4_HDR; -#define ip_header IPV4_HDR -#define saddr ip_srcaddr -#define daddr ip_destaddr -#define check ip_checksum -#define ihl ip_header_len -#define protocol ip_protocol -#define frag_off ip_frag_offset -#define tos ip_tos -#define ttl ip_ttl -#define tot_len ip_total_length -#endif - -struct ipv6_header_preamble -{ - unsigned char version : 4; - unsigned char pad_small : 4; - uint8_t pad[3]; -}; - -struct ipv6_header -{ - union - { - ipv6_header_preamble preamble; - uint32_t flowlabel; - } preamble; - - uint16_t payload_len; - uint8_t proto; - uint8_t hoplimit; - in6_addr srcaddr; - in6_addr dstaddr; - - /// get 20 bit truncated flow label in network order - llarp::nuint32_t - FlowLabel() const; - - /// put 20 bit truncated flow label network order - void - FlowLabel(llarp::nuint32_t flowlabel); -}; - #include #include #include -namespace llarp +namespace llarp::net { - namespace net + template + struct ip_header_le { - /// "well known" ip protocols - /// TODO: extend this to non "well known values" - enum class IPProtocol : uint8_t - { - ICMP = 0x01, - IGMP = 0x02, - IPIP = 0x04, - TCP = 0x06, - UDP = 0x11, - GRE = 0x2F, - ICMP6 = 0x3A, - OSFP = 0x59, - PGM = 0x71, - }; - - /// get string representation of this protocol - /// throws std::invalid_argument if we don't know the name of this ip protocol - std::string - IPProtocolName(IPProtocol proto); + unsigned int ihl : 4; + unsigned int version : 4; + uint8_t tos; + uint16_t tot_len; + uint16_t id; + uint16_t frag_off; + uint8_t ttl; + uint8_t protocol; + uint16_t check; + uint32_t saddr; + uint32_t daddr; + }; + + template <> + struct ip_header_le + { + unsigned int version : 4; + unsigned int ihl : 4; + uint8_t tos; + uint16_t tot_len; + uint16_t id; + uint16_t frag_off; + uint8_t ttl; + uint8_t protocol; + uint16_t check; + uint32_t saddr; + uint32_t daddr; + }; + + using ip_header = ip_header_le; + + template + struct ipv6_header_preamble_le + { + unsigned char pad_small : 4; + unsigned char version : 4; + uint8_t pad[3]; + }; - /// parse a string to an ip protocol - /// throws std::invalid_argument if cannot be parsed - IPProtocol - ParseIPProtocol(std::string data); + template <> + struct ipv6_header_preamble_le + { + unsigned char version : 4; + unsigned char pad_small : 4; + uint8_t pad[3]; + }; - /// an Packet - struct IPPacket + struct ipv6_header + { + union { - static constexpr size_t MaxSize = 1500; - llarp_time_t timestamp; - size_t sz; - byte_t buf[MaxSize]; + ipv6_header_preamble_le preamble; + uint32_t flowlabel; + } preamble; + + uint16_t payload_len; + uint8_t proto; + uint8_t hoplimit; + in6_addr srcaddr; + in6_addr dstaddr; + llarp::nuint32_t + FlowLabel() const; + + /// put 20 bit truncated flow label network order + void + FlowLabel(llarp::nuint32_t label); + }; + + /// "well known" ip protocols + /// TODO: extend this to non "well known values" + enum class IPProtocol : uint8_t + { + ICMP = 0x01, + IGMP = 0x02, + IPIP = 0x04, + TCP = 0x06, + UDP = 0x11, + GRE = 0x2F, + ICMP6 = 0x3A, + OSFP = 0x59, + PGM = 0x71, + }; + + /// get string representation of this protocol + /// throws std::invalid_argument if we don't know the name of this ip protocol + std::string + IPProtocolName(IPProtocol proto); + + /// parse a string to an ip protocol + /// throws std::invalid_argument if cannot be parsed + IPProtocol + ParseIPProtocol(std::string data); + + /// an Packet + struct IPPacket + { + static constexpr size_t MaxSize = 1500; + llarp_time_t timestamp; + size_t sz; + byte_t buf[MaxSize]; - static IPPacket - UDP(nuint32_t srcaddr, - nuint16_t srcport, - nuint32_t dstaddr, - nuint16_t dstport, - const llarp_buffer_t& data); + static IPPacket + UDP(nuint32_t srcaddr, + nuint16_t srcport, + nuint32_t dstaddr, + nuint16_t dstport, + const llarp_buffer_t& data); - ManagedBuffer - Buffer(); + ManagedBuffer + Buffer(); - ManagedBuffer - ConstBuffer() const; + ManagedBuffer + ConstBuffer() const; - bool - Load(const llarp_buffer_t& buf); + bool + Load(const llarp_buffer_t& buf); - struct GetTime - { - llarp_time_t - operator()(const IPPacket& pkt) const - { - return pkt.timestamp; - } - }; - - struct PutTime - { - EventLoop_ptr loop; - PutTime(EventLoop_ptr evloop) : loop(std::move(evloop)) - {} - void - operator()(IPPacket& pkt) const - { - pkt.timestamp = loop->time_now(); - } - }; - - struct GetNow - { - EventLoop_ptr loop; - GetNow(EventLoop_ptr evloop) : loop(std::move(evloop)) - {} - llarp_time_t - operator()() const - { - return loop->time_now(); - } - }; - - struct CompareSize - { - bool - operator()(const IPPacket& left, const IPPacket& right) - { - return left.sz < right.sz; - } - }; - - struct CompareOrder - { - bool - operator()(const IPPacket& left, const IPPacket& right) - { - return left.timestamp < right.timestamp; - } - }; - - inline ip_header* - Header() + struct CompareSize + { + bool + operator()(const IPPacket& left, const IPPacket& right) { - return (ip_header*)&buf[0]; + return left.sz < right.sz; } + }; - inline const ip_header* - Header() const + struct CompareOrder + { + bool + operator()(const IPPacket& left, const IPPacket& right) { - return (ip_header*)&buf[0]; + return left.timestamp < right.timestamp; } + }; - inline ipv6_header* - HeaderV6() - { - return (ipv6_header*)&buf[0]; - } + inline ip_header* + Header() + { + return reinterpret_cast(&buf[0]); + } - inline const ipv6_header* - HeaderV6() const - { - return (ipv6_header*)&buf[0]; - } + inline const ip_header* + Header() const + { + return reinterpret_cast(&buf[0]); + } - inline int - Version() const - { - return Header()->version; - } + inline ipv6_header* + HeaderV6() + { + return reinterpret_cast(&buf[0]); + } - inline bool - IsV4() const - { - return Version() == 4; - } + inline const ipv6_header* + HeaderV6() const + { + return reinterpret_cast(&buf[0]); + } - inline bool - IsV6() const - { - return Version() == 6; - } + inline int + Version() const + { + return Header()->version; + } - inline service::ProtocolType - ServiceProtocol() const - { - if (IsV4()) - return service::ProtocolType::TrafficV4; - if (IsV6()) - return service::ProtocolType::TrafficV6; + inline bool + IsV4() const + { + return Version() == 4; + } - return service::ProtocolType::Control; - } + inline bool + IsV6() const + { + return Version() == 6; + } - huint128_t - srcv6() const; + inline service::ProtocolType + ServiceProtocol() const + { + if (IsV4()) + return service::ProtocolType::TrafficV4; + if (IsV6()) + return service::ProtocolType::TrafficV6; - huint128_t - dstv6() const; + return service::ProtocolType::Control; + } - huint32_t - srcv4() const; + huint128_t + srcv6() const; - huint32_t - dstv4() const; + huint128_t + dstv6() const; - huint128_t - src4to6() const; + huint32_t + srcv4() const; - huint128_t - dst4to6() const; + huint32_t + dstv4() const; - huint128_t - src4to6Lan() const; + huint128_t + src4to6() const; - huint128_t - dst4to6Lan() const; + huint128_t + dst4to6() const; - /// get destination port if applicable - std::optional - DstPort() const; + huint128_t + src4to6Lan() const; - /// get source port if applicable - std::optional - SrcPort() const; + huint128_t + dst4to6Lan() const; - /// get pointer and size of layer 4 data - std::optional> - L4Data() const; + /// get destination port if applicable + std::optional + DstPort() const; - void - UpdateIPv4Address(nuint32_t src, nuint32_t dst); + /// get source port if applicable + std::optional + SrcPort() const; - void - UpdateIPv6Address( - huint128_t src, huint128_t dst, std::optional flowlabel = std::nullopt); + /// get pointer and size of layer 4 data + std::optional> + L4Data() const; - /// set addresses to zero and recacluate checksums - void - ZeroAddresses(std::optional flowlabel = std::nullopt); + void + UpdateIPv4Address(nuint32_t src, nuint32_t dst); - /// zero out source address - void - ZeroSourceAddress(std::optional flowlabel = std::nullopt); + void + UpdateIPv6Address( + huint128_t src, huint128_t dst, std::optional flowlabel = std::nullopt); - /// make an icmp unreachable reply packet based of this ip packet - std::optional - MakeICMPUnreachable() const; - }; + /// set addresses to zero and recacluate checksums + void + ZeroAddresses(std::optional flowlabel = std::nullopt); + + /// zero out source address + void + ZeroSourceAddress(std::optional flowlabel = std::nullopt); + + /// make an icmp unreachable reply packet based of this ip packet + std::optional + MakeICMPUnreachable() const; + }; + + /// generate ip checksum + uint16_t + ipchksum(const byte_t* buf, size_t sz, uint32_t sum = 0); - /// generate ip checksum - uint16_t - ipchksum(const byte_t* buf, size_t sz, uint32_t sum = 0); - } // namespace net -} // namespace llarp +} // namespace llarp::net diff --git a/llarp/util/codel.hpp b/llarp/util/codel.hpp deleted file mode 100644 index a18be23c2..000000000 --- a/llarp/util/codel.hpp +++ /dev/null @@ -1,167 +0,0 @@ -#pragma once - -#include -#include "mem.hpp" -#include -#include "time.hpp" - -#include -#include -#include -#include -#include -#include - -namespace llarp -{ - namespace util - { - struct GetNowSyscall - { - llarp_time_t - operator()() const - { - return llarp::time_now_ms(); - } - }; - - template < - typename T, - typename GetTime, - typename PutTime, - typename Compare, - typename GetNow = GetNowSyscall, - typename Mutex_t = util::Mutex, - typename Lock_t = std::lock_guard, - size_t MaxSize = 1024> - struct CoDelQueue - { - CoDelQueue(std::string name, PutTime put, GetNow now) - : m_QueueIdx(0) - , m_name(std::move(name)) - , _putTime(std::move(put)) - , _getNow(std::move(now)) - {} - - size_t - Size() EXCLUDES(m_QueueMutex) - { - Lock_t lock(m_QueueMutex); - return m_QueueIdx; - } - - template - bool - EmplaceIf(std::function pred, Args&&... args) EXCLUDES(m_QueueMutex) - { - Lock_t lock(m_QueueMutex); - if (m_QueueIdx == MaxSize) - return false; - T* t = &m_Queue[m_QueueIdx]; - new (t) T(std::forward(args)...); - if (!pred(*t)) - { - t->~T(); - return false; - } - - _putTime(m_Queue[m_QueueIdx]); - if (firstPut == 0s) - firstPut = _getTime(m_Queue[m_QueueIdx]); - ++m_QueueIdx; - - return true; - } - - template - void - Emplace(Args&&... args) EXCLUDES(m_QueueMutex) - { - Lock_t lock(m_QueueMutex); - if (m_QueueIdx == MaxSize) - return; - T* t = &m_Queue[m_QueueIdx]; - new (t) T(std::forward(args)...); - _putTime(m_Queue[m_QueueIdx]); - if (firstPut == 0s) - firstPut = _getTime(m_Queue[m_QueueIdx]); - ++m_QueueIdx; - } - - template - void - Process(Visit v) - { - return Process(v, [](T&) -> bool { return false; }); - } - - template - void - Process(Visit visitor, Filter f) EXCLUDES(m_QueueMutex) - { - llarp_time_t lowest = std::numeric_limits::max(); - if (_getNow() < nextTickAt) - return; - // llarp::LogInfo("CoDelQueue::Process - start at ", start); - Lock_t lock(m_QueueMutex); - auto start = firstPut; - - if (m_QueueIdx == 1) - { - visitor(m_Queue[0]); - T* t = &m_Queue[0]; - t->~T(); - m_QueueIdx = 0; - firstPut = 0s; - return; - } - size_t idx = 0; - while (m_QueueIdx) - { - llarp::LogDebug(m_name, " - queue has ", m_QueueIdx); - T* item = &m_Queue[idx++]; - if (f(*item)) - break; - --m_QueueIdx; - const llarp_time_t dlt = start - _getTime(*item); - // llarp::LogInfo("CoDelQueue::Process - dlt ", dlt); - lowest = std::min(dlt, lowest); - if (m_QueueIdx == 0) - { - // llarp::LogInfo("CoDelQueue::Process - single item: lowest ", - // lowest, " dropMs: ", dropMs); - if (lowest > dropMs) - { - item->~T(); - nextTickInterval += initialIntervalMs / uint64_t(std::sqrt(++dropNum)); - firstPut = 0s; - nextTickAt = start + nextTickInterval; - return; - } - - nextTickInterval = initialIntervalMs; - dropNum = 0; - } - visitor(*item); - item->~T(); - } - firstPut = 0s; - nextTickAt = start + nextTickInterval; - } - - const llarp_time_t initialIntervalMs = 5ms; - const llarp_time_t dropMs = 100ms; - llarp_time_t firstPut = 0s; - size_t dropNum = 0; - llarp_time_t nextTickInterval = initialIntervalMs; - llarp_time_t nextTickAt = 0s; - Mutex_t m_QueueMutex; - size_t m_QueueIdx GUARDED_BY(m_QueueMutex); - std::array m_Queue GUARDED_BY(m_QueueMutex); - std::string m_name; - GetTime _getTime; - PutTime _putTime; - GetNow _getNow; - }; // namespace util - } // namespace util -} // namespace llarp