summaryrefslogtreecommitdiff
path: root/indra/llmessage/llpacketring.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'indra/llmessage/llpacketring.cpp')
-rw-r--r--indra/llmessage/llpacketring.cpp315
1 files changed, 46 insertions, 269 deletions
diff --git a/indra/llmessage/llpacketring.cpp b/indra/llmessage/llpacketring.cpp
index b8284334ea..bade413e61 100644
--- a/indra/llmessage/llpacketring.cpp
+++ b/indra/llmessage/llpacketring.cpp
@@ -28,344 +28,121 @@
#include "llpacketring.h"
-#if LL_WINDOWS
- #include <winsock2.h>
-#else
- #include <sys/socket.h>
- #include <netinet/in.h>
-#endif
-
-// linden library includes
#include "llerror.h"
-#include "lltimer.h"
-#include "llproxy.h"
-#include "llrand.h"
-#include "message.h"
-#include "u64.h"
-constexpr S16 MAX_BUFFER_RING_SIZE = 1024;
+constexpr S16 MAX_BUFFER_RING_SIZE = 8192;
+
+// DANGER: don't adjust DEFAULT_BUFFER_RING_SIZE unless you know what
+// you're doing. Its value affects the "buffer load rate" which is used
+// to supply backpressure to an overloaded nework queue.
constexpr S16 DEFAULT_BUFFER_RING_SIZE = 256;
-LLPacketRing::LLPacketRing ()
- : mPacketRing(DEFAULT_BUFFER_RING_SIZE, nullptr)
+LLPacketRing::LLPacketRing()
+ : mRing(DEFAULT_BUFFER_RING_SIZE, nullptr)
{
LLHost invalid_host;
- for (size_t i = 0; i < mPacketRing.size(); ++i)
+ for (size_t i = 0; i < mRing.size(); ++i)
{
- mPacketRing[i] = new LLPacketBuffer(invalid_host, nullptr, 0);
+ mRing[i] = new LLPacketBuffer(invalid_host, nullptr, 0);
}
}
-LLPacketRing::~LLPacketRing ()
+LLPacketRing::~LLPacketRing()
{
- for (auto packet : mPacketRing)
+ for (auto* packet : mRing)
{
delete packet;
}
- mPacketRing.clear();
+ mRing.clear();
mNumBufferedPackets = 0;
mNumBufferedBytes = 0;
mHeadIndex = 0;
}
-S32 LLPacketRing::receivePacket (S32 socket, char *datap)
-{
- bool drop = computeDrop();
- return (mNumBufferedPackets > 0) ?
- receiveOrDropBufferedPacket(datap, drop) :
- receiveOrDropPacket(socket, datap, drop);
-}
-
-bool send_packet_helper(int socket, const char * datap, S32 data_size, LLHost host)
-{
- if (!LLProxy::isSOCKSProxyEnabled())
- {
- return send_packet(socket, datap, data_size, host.getAddress(), host.getPort());
- }
-
- char headered_send_buffer[NET_BUFFER_SIZE + SOCKS_HEADER_SIZE];
-
- proxywrap_t *socks_header = static_cast<proxywrap_t*>(static_cast<void*>(&headered_send_buffer));
- socks_header->rsv = 0;
- socks_header->addr = host.getAddress();
- socks_header->port = htons(host.getPort());
- socks_header->atype = ADDRESS_IPV4;
- socks_header->frag = 0;
-
- memcpy(headered_send_buffer + SOCKS_HEADER_SIZE, datap, data_size);
-
- return send_packet( socket,
- headered_send_buffer,
- data_size + SOCKS_HEADER_SIZE,
- LLProxy::getInstance()->getUDPProxy().getAddress(),
- LLProxy::getInstance()->getUDPProxy().getPort());
-}
-
-bool LLPacketRing::sendPacket(int socket, const char * datap, S32 data_size, LLHost host)
+void LLPacketRing::pushPacket(const LLPacketBuffer& packet)
{
- mActualBytesOut += data_size;
- return send_packet_helper(socket, datap, data_size, host);
-}
-
-void LLPacketRing::dropPackets (U32 num_to_drop)
-{
- mPacketsToDrop += num_to_drop;
-}
-
-void LLPacketRing::setDropPercentage (F32 percent_to_drop)
-{
- mDropPercentage = percent_to_drop;
-}
-
-bool LLPacketRing::computeDrop()
-{
- bool drop= (mDropPercentage > 0.0f && (ll_frand(100.f) < mDropPercentage));
- if (drop)
- {
- ++mPacketsToDrop;
- }
- if (mPacketsToDrop > 0)
- {
- --mPacketsToDrop;
- drop = true;
- }
- return drop;
-}
-
-S32 LLPacketRing::receiveOrDropPacket(S32 socket, char *datap, bool drop)
-{
- S32 packet_size = 0;
-
- // pull straight from socket
- if (LLProxy::isSOCKSProxyEnabled())
+ S16 ring_size = (S16)mRing.size();
+ if (mNumBufferedPackets >= ring_size && ring_size < MAX_BUFFER_RING_SIZE)
{
- char buffer[NET_BUFFER_SIZE + SOCKS_HEADER_SIZE]; /* Flawfinder ignore */
- packet_size = receive_packet(socket, buffer);
- if (packet_size > 0)
- {
- mActualBytesIn += packet_size;
- }
-
- if (packet_size > SOCKS_HEADER_SIZE)
- {
- if (drop)
- {
- packet_size = 0;
- }
- else
- {
- // *FIX We are assuming ATYP is 0x01 (IPv4), not 0x03 (hostname) or 0x04 (IPv6)
- packet_size -= SOCKS_HEADER_SIZE; // The unwrapped packet size
- memcpy(datap, buffer + SOCKS_HEADER_SIZE, packet_size);
- proxywrap_t * header = static_cast<proxywrap_t*>(static_cast<void*>(buffer));
- mLastSender.setAddress(header->addr);
- mLastSender.setPort(ntohs(header->port));
- mLastReceivingIF = ::get_receiving_interface();
- }
- }
- else
- {
- packet_size = 0;
- }
- }
- else
- {
- packet_size = receive_packet(socket, datap);
- if (packet_size > 0)
- {
- mActualBytesIn += packet_size;
- if (drop)
- {
- packet_size = 0;
- }
- else
- {
- mLastSender = ::get_sender();
- mLastReceivingIF = ::get_receiving_interface();
- }
- }
+ expandRing();
+ ring_size = (S16)mRing.size();
}
- return packet_size;
-}
-S32 LLPacketRing::receiveOrDropBufferedPacket(char *datap, bool drop)
-{
- assert(mNumBufferedPackets > 0);
- S32 packet_size = 0;
+ LLPacketBuffer* slot = mRing[mHeadIndex];
+ S32 old_size = slot->getSize();
- S16 ring_size = (S16)(mPacketRing.size());
- S16 packet_index = (mHeadIndex + ring_size - mNumBufferedPackets) % ring_size;
- LLPacketBuffer* packet = mPacketRing[packet_index];
- packet_size = packet->getSize();
- mLastSender = packet->getHost();
- mLastReceivingIF = packet->getReceivingInterface();
+ *slot = packet;
- --mNumBufferedPackets;
- mNumBufferedBytes -= packet_size;
- if (mNumBufferedPackets == 0)
- {
- assert(mNumBufferedBytes == 0);
- }
+ mHeadIndex = (mHeadIndex + 1) % ring_size;
- if (!drop)
+ if (mNumBufferedPackets < ring_size)
{
- if (packet_size > 0)
- {
- memcpy(datap, packet->getData(), packet_size);
- }
- else
- {
- assert(false);
- }
+ ++mNumBufferedPackets;
+ mNumBufferedBytes += packet.getSize();
}
else
{
- packet_size = 0;
+ // Ring is at maximum capacity; oldest packet was overwritten.
+ // This is VERY BAD because we've already ACKed the packet we're loosing
+ // (if it was "reliable").
+ LL_WARNS("PacketRing") << "buffer overflow at " << mNumBufferedPackets << " packets" << LL_ENDL;
+ mNumBufferedBytes += packet.getSize() - old_size;
}
- return packet_size;
}
-S32 LLPacketRing::bufferInboundPacket(S32 socket)
+bool LLPacketRing::popPacket(LLPacketBuffer& packet)
{
- if (mNumBufferedPackets == mPacketRing.size() && mNumBufferedPackets < MAX_BUFFER_RING_SIZE)
+ if (mNumBufferedPackets <= 0)
{
- expandRing();
+ return false;
}
- LLPacketBuffer* packet = mPacketRing[mHeadIndex];
- S32 old_packet_size = packet->getSize();
- S32 packet_size = 0;
- if (LLProxy::isSOCKSProxyEnabled())
- {
- char buffer[NET_BUFFER_SIZE + SOCKS_HEADER_SIZE]; /* Flawfinder ignore */
- packet_size = receive_packet(socket, buffer);
- if (packet_size > 0)
- {
- mActualBytesIn += packet_size;
- if (packet_size > SOCKS_HEADER_SIZE)
- {
- // *FIX We are assuming ATYP is 0x01 (IPv4), not 0x03 (hostname) or 0x04 (IPv6)
+ S16 ring_size = (S16)mRing.size();
+ S16 tail_index = (mHeadIndex + ring_size - mNumBufferedPackets) % ring_size;
- proxywrap_t * header = static_cast<proxywrap_t*>(static_cast<void*>(buffer));
- LLHost sender;
- sender.setAddress(header->addr);
- sender.setPort(ntohs(header->port));
+ LLPacketBuffer* slot = mRing[tail_index];
+ S32 packet_size = slot->getSize();
- packet_size -= SOCKS_HEADER_SIZE; // The unwrapped packet size
- packet->init(buffer + SOCKS_HEADER_SIZE, packet_size, sender);
+ packet = *slot;
- mHeadIndex = (mHeadIndex + 1) % (S16)(mPacketRing.size());
- if (mNumBufferedPackets < MAX_BUFFER_RING_SIZE)
- {
- ++mNumBufferedPackets;
- mNumBufferedBytes += packet_size;
- }
- else
- {
- // we overwrote an older packet
- mNumBufferedBytes += packet_size - old_packet_size;
- }
- }
- else
- {
- packet_size = 0;
- }
- }
- }
- else
- {
- packet->init(socket);
- packet_size = packet->getSize();
- if (packet_size > 0)
- {
- mActualBytesIn += packet_size;
+ --mNumBufferedPackets;
+ mNumBufferedBytes -= packet_size;
- mHeadIndex = (mHeadIndex + 1) % (S16)(mPacketRing.size());
- if (mNumBufferedPackets < MAX_BUFFER_RING_SIZE)
- {
- ++mNumBufferedPackets;
- mNumBufferedBytes += packet_size;
- }
- else
- {
- // we overwrote an older packet
- mNumBufferedBytes += packet_size - old_packet_size;
- }
- }
- }
- return packet_size;
-}
+ llassert(mNumBufferedPackets > 0 || mNumBufferedBytes == 0);
-S32 LLPacketRing::drainSocket(S32 socket)
-{
- // drain into buffer
- S32 packet_size = 1;
- S32 num_loops = 0;
- S32 old_num_packets = mNumBufferedPackets;
- while (packet_size > 0)
- {
- packet_size = bufferInboundPacket(socket);
- ++num_loops;
- }
- S32 num_dropped_packets = (num_loops - 1 + old_num_packets) - mNumBufferedPackets;
- if (num_dropped_packets > 0)
- {
- // It will eventually be accounted by mDroppedPackets
- // and mPacketsLost, but track it here for logging purposes.
- mNumDroppedPackets += num_dropped_packets;
- }
- return (S32)(mNumBufferedPackets);
+ return true;
}
bool LLPacketRing::expandRing()
{
- // compute larger size
- constexpr S16 BUFFER_RING_EXPANSION = 256;
- S16 old_size = (S16)(mPacketRing.size());
+ constexpr S16 BUFFER_RING_EXPANSION = 512;
+ S16 old_size = (S16)mRing.size();
S16 new_size = llmin(old_size + BUFFER_RING_EXPANSION, MAX_BUFFER_RING_SIZE);
if (new_size == old_size)
{
- // mPacketRing is already maxed out
return false;
}
- // make a larger ring and copy packet pointers
+ // Lay existing entries out linearly in FIFO order starting at index 0.
std::vector<LLPacketBuffer*> new_ring(new_size, nullptr);
for (S16 i = 0; i < old_size; ++i)
{
S16 j = (mHeadIndex + i) % old_size;
- new_ring[i] = mPacketRing[j];
+ new_ring[i] = mRing[j];
}
- // allocate new packets for the remainder of new_ring
LLHost invalid_host;
for (S16 i = old_size; i < new_size; ++i)
{
new_ring[i] = new LLPacketBuffer(invalid_host, nullptr, 0);
}
- // swap the rings and reset mHeadIndex
- mPacketRing.swap(new_ring);
+ mRing.swap(new_ring);
mHeadIndex = mNumBufferedPackets;
return true;
}
F32 LLPacketRing::getBufferLoadRate() const
{
- // goes up to MAX_BUFFER_RING_SIZE
return (F32)mNumBufferedPackets / (F32)DEFAULT_BUFFER_RING_SIZE;
}
-
-void LLPacketRing::dumpPacketRingStats()
-{
- mNumDroppedPacketsTotal += mNumDroppedPackets;
- LL_INFOS("Messaging") << "Packet ring stats: " << std::endl
- << "Buffered packets: " << mNumBufferedPackets << std::endl
- << "Buffered bytes: " << mNumBufferedBytes << std::endl
- << "Dropped packets current: " << mNumDroppedPackets << std::endl
- << "Dropped packets total: " << mNumDroppedPacketsTotal << std::endl
- << "Dropped packets percentage: " << mDropPercentage << "%" << std::endl
- << "Actual in bytes: " << mActualBytesIn << std::endl
- << "Actual out bytes: " << mActualBytesOut << LL_ENDL;
- mNumDroppedPackets = 0;
-}