From 3d0ded051c0fdcd6a269ad0b4b8ca1405a045701 Mon Sep 17 00:00:00 2001 From: "Justin Clark-Casey (justincc)" Date: Wed, 21 Jan 2015 20:31:42 +0000 Subject: [PATCH] Add debug ability to ignore reliably sent packets that are not acknowledged. This is controlled via the console command "debug lludp client set process-unacked-sends true [ ]" For debug purposes to see if this process for very bad connections is causing general outbound udp processing delays. Relates to http://opensimulator.org/mantis/view.php?id=7393 --- .../ClientStack/Linden/UDP/LLUDPClient.cs | 9 ++ .../ClientStack/Linden/UDP/LLUDPServer.cs | 51 +++++----- .../Linden/UDP/LLUDPServerCommands.cs | 93 +++++++++++++++++++ 3 files changed, 131 insertions(+), 22 deletions(-) diff --git a/OpenSim/Region/ClientStack/Linden/UDP/LLUDPClient.cs b/OpenSim/Region/ClientStack/Linden/UDP/LLUDPClient.cs index ce6e3eee57..0394e54197 100644 --- a/OpenSim/Region/ClientStack/Linden/UDP/LLUDPClient.cs +++ b/OpenSim/Region/ClientStack/Linden/UDP/LLUDPClient.cs @@ -119,8 +119,15 @@ namespace OpenSim.Region.ClientStack.LindenUDP public readonly uint CircuitCode; /// Sequence numbers of packets we've received (for duplicate checking) public readonly IncomingPacketHistoryCollection PacketArchive = new IncomingPacketHistoryCollection(200); + + /// + /// If true then we take action in response to unacked reliably sent packets such as resending the packet. + /// + public bool ProcessUnackedSends { get; set; } + /// Packets we have sent that need to be ACKed by the client public readonly UnackedPacketCollection NeedAcks = new UnackedPacketCollection(); + /// ACKs that are queued up, waiting to be sent to the client public readonly OpenSim.Framework.LocklessQueue PendingAcks = new OpenSim.Framework.LocklessQueue(); @@ -225,6 +232,8 @@ namespace OpenSim.Region.ClientStack.LindenUDP if (maxRTO != 0) m_maxRTO = maxRTO; + ProcessUnackedSends = true; + // Create a token bucket throttle for this client that has the scene token bucket as a parent m_throttleClient = new AdaptiveTokenBucket( diff --git a/OpenSim/Region/ClientStack/Linden/UDP/LLUDPServer.cs b/OpenSim/Region/ClientStack/Linden/UDP/LLUDPServer.cs index 4fec91fa3a..ad83b4265b 100644 --- a/OpenSim/Region/ClientStack/Linden/UDP/LLUDPServer.cs +++ b/OpenSim/Region/ClientStack/Linden/UDP/LLUDPServer.cs @@ -1137,7 +1137,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP Utils.UIntToBytesBig(sequenceNumber, buffer.Data, 1); outgoingPacket.SequenceNumber = sequenceNumber; - if (isReliable) + if (udpClient.ProcessUnackedSends && isReliable) { // Add this packet to the list of ACK responses we are waiting on from the server udpClient.NeedAcks.Add(outgoingPacket); @@ -1325,30 +1325,37 @@ namespace OpenSim.Region.ClientStack.LindenUDP #region ACK Receiving - // Handle appended ACKs - if (packet.Header.AppendedAcks && packet.Header.AckList != null) + if (udpClient.ProcessUnackedSends) { -// m_log.DebugFormat( -// "[LLUDPSERVER]: Handling {0} appended acks from {1} in {2}", -// packet.Header.AckList.Length, client.Name, m_scene.Name); + // Handle appended ACKs + if (packet.Header.AppendedAcks && packet.Header.AckList != null) + { + // m_log.DebugFormat( + // "[LLUDPSERVER]: Handling {0} appended acks from {1} in {2}", + // packet.Header.AckList.Length, client.Name, m_scene.Name); - for (int i = 0; i < packet.Header.AckList.Length; i++) - udpClient.NeedAcks.Acknowledge(packet.Header.AckList[i], now, packet.Header.Resent); + for (int i = 0; i < packet.Header.AckList.Length; i++) + udpClient.NeedAcks.Acknowledge(packet.Header.AckList[i], now, packet.Header.Resent); + } + + // Handle PacketAck packets + if (packet.Type == PacketType.PacketAck) + { + PacketAckPacket ackPacket = (PacketAckPacket)packet; + + // m_log.DebugFormat( + // "[LLUDPSERVER]: Handling {0} packet acks for {1} in {2}", + // ackPacket.Packets.Length, client.Name, m_scene.Name); + + for (int i = 0; i < ackPacket.Packets.Length; i++) + udpClient.NeedAcks.Acknowledge(ackPacket.Packets[i].ID, now, packet.Header.Resent); + + // We don't need to do anything else with PacketAck packets + return; + } } - - // Handle PacketAck packets - if (packet.Type == PacketType.PacketAck) + else if (packet.Type == PacketType.PacketAck) { - PacketAckPacket ackPacket = (PacketAckPacket)packet; - -// m_log.DebugFormat( -// "[LLUDPSERVER]: Handling {0} packet acks for {1} in {2}", -// ackPacket.Packets.Length, client.Name, m_scene.Name); - - for (int i = 0; i < ackPacket.Packets.Length; i++) - udpClient.NeedAcks.Acknowledge(ackPacket.Packets[i].ID, now, packet.Header.Resent); - - // We don't need to do anything else with PacketAck packets return; } @@ -2011,7 +2018,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP if (udpClient.IsConnected) { - if (m_resendUnacked) + if (udpClient.ProcessUnackedSends && m_resendUnacked) HandleUnacked(llClient); if (m_sendAcks) diff --git a/OpenSim/Region/ClientStack/Linden/UDP/LLUDPServerCommands.cs b/OpenSim/Region/ClientStack/Linden/UDP/LLUDPServerCommands.cs index 17a394d8e7..ac6c0b4251 100644 --- a/OpenSim/Region/ClientStack/Linden/UDP/LLUDPServerCommands.cs +++ b/OpenSim/Region/ClientStack/Linden/UDP/LLUDPServerCommands.cs @@ -195,6 +195,24 @@ namespace OpenSim.Region.ClientStack.LindenUDP "Start, stop or get status of OutgoingQueueRefillEngine.", "If stopped then refill requests are processed directly via the threadpool.", HandleOqreCommand); + + m_console.Commands.AddCommand( + "Debug", + false, + "debug lludp client get", + "debug lludp client get [ ]", + "Get debug parameters for the client. If no name is given then all client information is returned.", + "process-unacked-sends - Do we take action if a sent reliable packet has not been acked.", + HandleClientGetCommand); + + m_console.Commands.AddCommand( + "Debug", + false, + "debug lludp client set", + "debug lludp client set [ ]", + "Set a debug parameter for a particular client. If no name is given then the value is set on all clients.", + "process-unacked-sends - Do we take action if a sent reliable packet has not been acked.", + HandleClientSetCommand); } private void HandleShowServerThrottlesCommand(string module, string[] args) @@ -538,6 +556,81 @@ namespace OpenSim.Region.ClientStack.LindenUDP m_console.OutputFormat("{0} set to {1} in {2}", param, rawValue, m_udpServer.Scene.Name); } + private void HandleClientGetCommand(string module, string[] args) + { + if (SceneManager.Instance.CurrentScene != null && SceneManager.Instance.CurrentScene != m_udpServer.Scene) + return; + + if (args.Length != 4 && args.Length != 6) + { + MainConsole.Instance.OutputFormat("Usage: debug lludp client get [ ]"); + return; + } + + string name = null; + + if (args.Length == 6) + name = string.Format("{0} {1}", args[4], args[5]); + + m_udpServer.Scene.ForEachScenePresence( + sp => + { + if ((name == null || sp.Name == name) && sp.ControllingClient is LLClientView) + { + LLUDPClient udpClient = ((LLClientView)sp.ControllingClient).UDPClient; + + m_console.OutputFormat( + "Client debug parameters for {0} ({1}) in {2}", + sp.Name, sp.IsChildAgent ? "child" : "root", m_udpServer.Scene.Name); + + ConsoleDisplayList cdl = new ConsoleDisplayList(); + cdl.AddRow("process-unacked-sends", udpClient.ProcessUnackedSends); + + m_console.Output(cdl.ToString()); + } + }); + } + + private void HandleClientSetCommand(string module, string[] args) + { + if (SceneManager.Instance.CurrentScene != null && SceneManager.Instance.CurrentScene != m_udpServer.Scene) + return; + + if (args.Length != 6 && args.Length != 8) + { + MainConsole.Instance.OutputFormat("Usage: debug lludp client set [ ]"); + return; + } + + string param = args[4]; + string rawValue = args[5]; + + string name = null; + + if (args.Length == 8) + name = string.Format("{0} {1}", args[6], args[7]); + + if (param == "process-unacked-sends") + { + bool newValue; + + if (!ConsoleUtil.TryParseConsoleBool(MainConsole.Instance, rawValue, out newValue)) + return; + + m_udpServer.Scene.ForEachScenePresence( + sp => + { + if ((name == null || sp.Name == name) && sp.ControllingClient is LLClientView) + { + LLUDPClient udpClient = ((LLClientView)sp.ControllingClient).UDPClient; + udpClient.ProcessUnackedSends = newValue; + + m_console.OutputFormat("{0} set to {1} for {2} in {3}", param, newValue, sp.Name, m_udpServer.Scene.Name); + } + }); + } + } + private void HandlePacketCommand(string module, string[] args) { if (SceneManager.Instance.CurrentScene != null && SceneManager.Instance.CurrentScene != m_udpServer.Scene)