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 [<avatar-first-name> <avatar-last-name>]"
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
0.8.1-post-fixes
Justin Clark-Casey (justincc) 2015-01-21 20:31:42 +00:00
parent abf1836b81
commit 155da5aad2
3 changed files with 131 additions and 22 deletions

View File

@ -119,8 +119,15 @@ namespace OpenSim.Region.ClientStack.LindenUDP
public readonly uint CircuitCode; public readonly uint CircuitCode;
/// <summary>Sequence numbers of packets we've received (for duplicate checking)</summary> /// <summary>Sequence numbers of packets we've received (for duplicate checking)</summary>
public readonly IncomingPacketHistoryCollection PacketArchive = new IncomingPacketHistoryCollection(200); public readonly IncomingPacketHistoryCollection PacketArchive = new IncomingPacketHistoryCollection(200);
/// <summary>
/// If true then we take action in response to unacked reliably sent packets such as resending the packet.
/// </summary>
public bool ProcessUnackedSends { get; set; }
/// <summary>Packets we have sent that need to be ACKed by the client</summary> /// <summary>Packets we have sent that need to be ACKed by the client</summary>
public readonly UnackedPacketCollection NeedAcks = new UnackedPacketCollection(); public readonly UnackedPacketCollection NeedAcks = new UnackedPacketCollection();
/// <summary>ACKs that are queued up, waiting to be sent to the client</summary> /// <summary>ACKs that are queued up, waiting to be sent to the client</summary>
public readonly OpenSim.Framework.LocklessQueue<uint> PendingAcks = new OpenSim.Framework.LocklessQueue<uint>(); public readonly OpenSim.Framework.LocklessQueue<uint> PendingAcks = new OpenSim.Framework.LocklessQueue<uint>();
@ -225,6 +232,8 @@ namespace OpenSim.Region.ClientStack.LindenUDP
if (maxRTO != 0) if (maxRTO != 0)
m_maxRTO = maxRTO; m_maxRTO = maxRTO;
ProcessUnackedSends = true;
// Create a token bucket throttle for this client that has the scene token bucket as a parent // Create a token bucket throttle for this client that has the scene token bucket as a parent
m_throttleClient m_throttleClient
= new AdaptiveTokenBucket( = new AdaptiveTokenBucket(

View File

@ -1137,7 +1137,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
Utils.UIntToBytesBig(sequenceNumber, buffer.Data, 1); Utils.UIntToBytesBig(sequenceNumber, buffer.Data, 1);
outgoingPacket.SequenceNumber = sequenceNumber; 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 // Add this packet to the list of ACK responses we are waiting on from the server
udpClient.NeedAcks.Add(outgoingPacket); udpClient.NeedAcks.Add(outgoingPacket);
@ -1325,30 +1325,37 @@ namespace OpenSim.Region.ClientStack.LindenUDP
#region ACK Receiving #region ACK Receiving
// Handle appended ACKs if (udpClient.ProcessUnackedSends)
if (packet.Header.AppendedAcks && packet.Header.AckList != null)
{ {
// m_log.DebugFormat( // Handle appended ACKs
// "[LLUDPSERVER]: Handling {0} appended acks from {1} in {2}", if (packet.Header.AppendedAcks && packet.Header.AckList != null)
// packet.Header.AckList.Length, client.Name, m_scene.Name); {
// 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++) for (int i = 0; i < packet.Header.AckList.Length; i++)
udpClient.NeedAcks.Acknowledge(packet.Header.AckList[i], now, packet.Header.Resent); 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;
}
} }
else if (packet.Type == PacketType.PacketAck)
// 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; return;
} }
@ -2011,7 +2018,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
if (udpClient.IsConnected) if (udpClient.IsConnected)
{ {
if (m_resendUnacked) if (udpClient.ProcessUnackedSends && m_resendUnacked)
HandleUnacked(llClient); HandleUnacked(llClient);
if (m_sendAcks) if (m_sendAcks)

View File

@ -195,6 +195,24 @@ namespace OpenSim.Region.ClientStack.LindenUDP
"Start, stop or get status of OutgoingQueueRefillEngine.", "Start, stop or get status of OutgoingQueueRefillEngine.",
"If stopped then refill requests are processed directly via the threadpool.", "If stopped then refill requests are processed directly via the threadpool.",
HandleOqreCommand); HandleOqreCommand);
m_console.Commands.AddCommand(
"Debug",
false,
"debug lludp client get",
"debug lludp client get [<avatar-first-name> <avatar-last-name>]",
"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 <param> <value> [<avatar-first-name> <avatar-last-name>]",
"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) 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); 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 [<avatar-first-name> <avatar-last-name>]");
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 <param> <value> [<avatar-first-name> <avatar-last-name>]");
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) private void HandlePacketCommand(string module, string[] args)
{ {
if (SceneManager.Instance.CurrentScene != null && SceneManager.Instance.CurrentScene != m_udpServer.Scene) if (SceneManager.Instance.CurrentScene != null && SceneManager.Instance.CurrentScene != m_udpServer.Scene)