/// <summary> /// Default constructor /// </summary> /// <param name="parent">Parent bucket if this is a child bucket, or /// null if this is a root bucket</param> /// <param name="maxBurst">Maximum size of the bucket in bytes, or /// zero if this bucket has no maximum capacity</param> /// <param name="dripRate">Rate that the bucket fills, in bytes per /// second. If zero, the bucket always remains full</param> public TokenBucket(TokenBucket parent, int maxBurst, int dripRate) { this.parent = parent; MaxBurst = maxBurst; DripRate = dripRate; lastDrip = Environment.TickCount & Int32.MaxValue; }
/// <summary> /// Register drip rate requested by a child of this throttle. Pass the /// changes up the hierarchy. /// </summary> public void RegisterRequest(TokenBucket child, Int64 request) { lock (m_children) { m_children[child] = request; TotalDripRequest = 0; foreach (KeyValuePair <TokenBucket, Int64> cref in m_children) { TotalDripRequest += cref.Value; } } // Pass the new values up to the parent if (Parent != null) { Int64 effectiveDripRate; if (RequestedDripRate > 0) { effectiveDripRate = Math.Min(RequestedDripRate, TotalDripRequest); } else { effectiveDripRate = TotalDripRequest; } Parent.RegisterRequest(this, effectiveDripRate); } }
/// <summary> /// Default constructor /// </summary> /// <param name="identifier">Identifier for this token bucket</param> /// <param name="parent">Parent bucket if this is a child bucket, or /// null if this is a root bucket</param> /// <param name="requestedDripRate"> /// Requested rate that the bucket fills, in bytes per /// second. If zero, the bucket always remains full. /// </param> public TokenBucket(string identifier, TokenBucket parent, Int64 requestedDripRate, Int64 maxDripRate) { Identifier = identifier; Parent = parent; RequestedDripRate = requestedDripRate; MaxDripRate = maxDripRate; m_lastDrip = Util.EnvironmentTickCount(); }
/// <summary> /// Default constructor /// </summary> /// <param name="identifier">Identifier for this token bucket</param> /// <param name="parent">Parent bucket if this is a child bucket, or /// null if this is a root bucket</param> /// <param name="maxBurst">Maximum size of the bucket in bytes, or /// zero if this bucket has no maximum capacity</param> /// <param name="dripRate">Rate that the bucket fills, in bytes per /// second. If zero, the bucket always remains full</param> public TokenBucket(TokenBucket parent, float dripRate, float MaxBurst) { m_counter++; Parent = parent; RequestedDripRate = dripRate; RequestedBurst = MaxBurst; m_lastDrip = Util.GetTimeStampMS() + 100000.0; // skip first drip }
/// <summary> /// Default constructor /// </summary> /// <param name="parent">Parent bucket if this is a child bucket, or /// null if this is a root bucket</param> /// <param name="maxBurst">Maximum size of the bucket in bytes, or /// zero if this bucket has no maximum capacity</param> /// <param name="dripRate">Rate that the bucket fills, in bytes per /// second. If zero, the bucket always remains full</param> public TokenBucket(TokenBucket parent, Int64 dripRate) { m_identifier = m_counter++; Parent = parent; RequestedDripRate = dripRate; // TotalDripRequest = dripRate; // this will be overwritten when a child node registers // MaxBurst = (Int64)((double)dripRate * m_quantumsPerBurst); m_lastDrip = Util.EnvironmentTickCount(); }
// <summary> // // </summary> public AdaptiveTokenBucket(TokenBucket parent, Int64 maxDripRate, bool enabled) : base(parent, maxDripRate) { Enabled = enabled; if (Enabled) { // m_log.DebugFormat("[TOKENBUCKET] Adaptive throttle enabled"); MaxDripRate = maxDripRate; AdjustedDripRate = m_minimumFlow; } }
// <summary> // // </summary> public AdaptiveTokenBucket(TokenBucket parent, float maxDripRate, float maxBurst, bool enabled) : base(parent, maxDripRate, maxBurst) { m_enabled = enabled; MaxDripRate = maxDripRate; if (enabled) AdjustedDripRate = m_maxDripRate * .5f; else AdjustedDripRate = m_maxDripRate; }
/// <summary> /// Constructor for the AdaptiveTokenBucket class /// <param name="identifier">Unique identifier for the client</param> /// <param name="parent">Parent bucket in the hierarchy</param> /// <param name="requestedDripRate"></param> /// <param name="maxDripRate">The ceiling rate for adaptation</param> /// <param name="minDripRate">The floor rate for adaptation</param> /// </summary> public AdaptiveTokenBucket(string identifier, TokenBucket parent, Int64 requestedDripRate, Int64 maxDripRate, Int64 minDripRate, bool enabled) : base(identifier, parent, requestedDripRate, maxDripRate) { AdaptiveEnabled = enabled; if (AdaptiveEnabled) { // m_log.DebugFormat("[TOKENBUCKET]: Adaptive throttle enabled"); m_minimumFlow = minDripRate; TargetDripRate = m_minimumFlow; AdjustedDripRate = m_minimumFlow; } }
public int GetCatBytesCanSend(ThrottleOutPacketType cat, int timeMS) { int icat = (int)cat; if (icat > 0 && icat < THROTTLE_CATEGORY_COUNT) { TokenBucket bucket = m_throttleCategories[icat]; return(bucket.GetCatBytesCanSend(timeMS)); } else { return(0); } }
// <summary> // // </summary> public AdaptiveTokenBucket(TokenBucket parent, float maxDripRate, float maxBurst, bool enabled) : base(parent, maxDripRate, maxBurst) { m_enabled = enabled; MaxDripRate = maxDripRate; if (enabled) { AdjustedDripRate = m_maxDripRate * .5f; } else { AdjustedDripRate = m_maxDripRate; } }
/// <summary> /// Default constructor /// </summary> /// <param name = "server">Reference to the UDP server this client is connected to</param> /// <param name = "rates">Default throttling rates and maximum throttle limits</param> /// <param name = "parentThrottle">Parent HTB (hierarchical token bucket) /// that the child throttles will be governed by</param> /// <param name = "circuitCode">Circuit code for this connection</param> /// <param name = "agentID">AgentID for the connected agent</param> /// <param name = "remoteEndPoint">Remote endpoint for this connection</param> /// <param name="defaultRTO"></param> /// <param name="maxRTO"></param> public LLUDPClient(LLUDPServer server, ThrottleRates rates, TokenBucket parentThrottle, uint circuitCode, UUID agentID, IPEndPoint remoteEndPoint, int defaultRTO, int maxRTO) { AgentID = agentID; RemoteEndPoint = remoteEndPoint; CircuitCode = circuitCode; m_udpServer = server; if (defaultRTO != 0) { m_defaultRTO = defaultRTO; } if (maxRTO != 0) { m_maxRTO = maxRTO; } // Create a token bucket throttle for this client that has the scene token bucket as a parent m_throttle = new TokenBucket(parentThrottle, rates.TotalLimit, 0); // remember the rates the client requested Rates = new int[(int)ThrottleOutPacketType.Count]; for (int i = 0; i < (int)ThrottleOutPacketType.Count; i++) { PacketsCounts[i] = 0; } //Set the priorities for the different packet types //Higher is more important MapCatsToPriority[(int)ThrottleOutPacketType.Resend] = 7; MapCatsToPriority[(int)ThrottleOutPacketType.Land] = 1; MapCatsToPriority[(int)ThrottleOutPacketType.Wind] = 0; MapCatsToPriority[(int)ThrottleOutPacketType.Cloud] = 0; MapCatsToPriority[(int)ThrottleOutPacketType.Task] = 4; MapCatsToPriority[(int)ThrottleOutPacketType.Texture] = 2; MapCatsToPriority[(int)ThrottleOutPacketType.Asset] = 3; MapCatsToPriority[(int)ThrottleOutPacketType.Transfer] = 5; MapCatsToPriority[(int)ThrottleOutPacketType.State] = 5; MapCatsToPriority[(int)ThrottleOutPacketType.AvatarInfo] = 6; MapCatsToPriority[(int)ThrottleOutPacketType.OutBand] = 7; // Default the retransmission timeout to one second RTO = m_defaultRTO; // Initialize this to a sane value to prevent early disconnects TickLastPacketReceived = Environment.TickCount & Int32.MaxValue; }
/// <summary> /// Remove the rate requested by a child of this throttle. Pass the /// changes up the hierarchy. /// </summary> public void UnregisterRequest(TokenBucket child) { m_children.Remove(child); // m_totalDripRequest = m_children.Values.Sum(); m_totalDripRequest = 0; foreach (KeyValuePair <TokenBucket, Int64> cref in m_children) { m_totalDripRequest += cref.Value; } // Pass the new values up to the parent if (m_parent != null) { m_parent.RegisterRequest(this, Math.Min(RequestedDripRate, TotalDripRequest)); } }
/// <summary> /// Default constructor /// </summary> /// <param name="server">Reference to the UDP server this client is connected to</param> /// <param name="rates">Default throttling rates and maximum throttle limits</param> /// <param name="parentThrottle">Parent HTB (hierarchical token bucket) /// that the child throttles will be governed by</param> /// <param name="circuitCode">Circuit code for this connection</param> /// <param name="agentID">AgentID for the connected agent</param> /// <param name="remoteEndPoint">Remote endpoint for this connection</param> /// <param name="defaultRTO"> /// Default retransmission timeout for unacked packets. The RTO will never drop /// beyond this number. /// </param> /// <param name="maxRTO"> /// The maximum retransmission timeout for unacked packets. The RTO will never exceed this number. /// </param> public LLUDPClient( LLUDPServer server, ThrottleRates rates, TokenBucket parentThrottle, uint circuitCode, UUID agentID, IPEndPoint remoteEndPoint, int defaultRTO, int maxRTO) { AgentID = agentID; RemoteEndPoint = remoteEndPoint; CircuitCode = circuitCode; m_udpServer = server; if (defaultRTO != 0) { m_defaultRTO = defaultRTO; } if (maxRTO != 0) { m_maxRTO = maxRTO; } m_burstTime = rates.BurstTime; m_maxRate = rates.ClientMaxRate; // Create a token bucket throttle for this client that has the scene token bucket as a parent m_throttleClient = new AdaptiveTokenBucket(parentThrottle, m_maxRate, m_maxRate * m_burstTime, rates.AdaptiveThrottlesEnabled); // Create an array of token buckets for this clients different throttle categories m_throttleCategories = new TokenBucket[THROTTLE_CATEGORY_COUNT]; for (int i = 0; i < THROTTLE_CATEGORY_COUNT; i++) { ThrottleOutPacketType type = (ThrottleOutPacketType)i; // Initialize the packet outboxes, where packets sit while they are waiting for tokens m_packetOutboxes[i] = new DoubleLocklessQueue <OutgoingPacket>(); // Initialize the token buckets that control the throttling for each category float rate = rates.GetRate(type); float burst = rate * m_burstTime; m_throttleCategories[i] = new TokenBucket(m_throttleClient, rate, burst); } m_RTO = m_defaultRTO; // Initialize this to a sane value to prevent early disconnects TickLastPacketReceived = Environment.TickCount & Int32.MaxValue; m_pingMS = 20; // so filter doesnt start at 0; }
/// <summary> /// Register drip rate requested by a child of this throttle. Pass the /// changes up the hierarchy. /// </summary> public void RegisterRequest(TokenBucket child, float request) { lock (m_children) { m_children[child] = request; m_totalDripRequest = 0; foreach (KeyValuePair <TokenBucket, float> cref in m_children) { m_totalDripRequest += cref.Value; } } // Pass the new values up to the parent if (m_parent != null) { m_parent.RegisterRequest(this, Math.Min(RequestedDripRate, TotalDripRequest)); } }
/// <summary> /// Default constructor /// </summary> /// <param name="server">Reference to the UDP server this client is connected to</param> /// <param name="rates">Default throttling rates and maximum throttle limits</param> /// <param name="parentThrottle">Parent HTB (hierarchical token bucket) /// that the child throttles will be governed by</param> /// <param name="circuitCode">Circuit code for this connection</param> /// <param name="agentID">AgentID for the connected agent</param> /// <param name="remoteEndPoint">Remote endpoint for this connection</param> /// <param name="defaultRTO"> /// Default retransmission timeout for unacked packets. The RTO will never drop /// beyond this number. /// </param> /// <param name="maxRTO"> /// The maximum retransmission timeout for unacked packets. The RTO will never exceed this number. /// </param> public LLUDPClient( LLUDPServer server, ThrottleRates rates, TokenBucket parentThrottle, uint circuitCode, UUID agentID, IPEndPoint remoteEndPoint, int defaultRTO, int maxRTO) { AgentID = agentID; RemoteEndPoint = remoteEndPoint; CircuitCode = circuitCode; m_udpServer = server; if (defaultRTO != 0) { m_defaultRTO = defaultRTO; } if (maxRTO != 0) { m_maxRTO = maxRTO; } // Create a token bucket throttle for this client that has the scene token bucket as a parent m_throttleClient = new AdaptiveTokenBucket(parentThrottle, rates.Total, rates.AdaptiveThrottlesEnabled); // Create a token bucket throttle for the total categary with the client bucket as a throttle m_throttleCategory = new TokenBucket(m_throttleClient, 0); // Create an array of token buckets for this clients different throttle categories m_throttleCategories = new TokenBucket[THROTTLE_CATEGORY_COUNT]; m_cannibalrate = rates.CannibalizeTextureRate; for (int i = 0; i < THROTTLE_CATEGORY_COUNT; i++) { ThrottleOutPacketType type = (ThrottleOutPacketType)i; // Initialize the packet outboxes, where packets sit while they are waiting for tokens m_packetOutboxes[i] = new OpenSim.Framework.LocklessQueue <OutgoingPacket>(); // Initialize the token buckets that control the throttling for each category m_throttleCategories[i] = new TokenBucket(m_throttleCategory, rates.GetRate(type)); } // Default the retransmission timeout to one second RTO = m_defaultRTO; // Initialize this to a sane value to prevent early disconnects TickLastPacketReceived = Environment.TickCount & Int32.MaxValue; }
// <summary> // // </summary> public AdaptiveTokenBucket(TokenBucket parent, float maxDripRate, float maxBurst, bool enabled) : base(parent, maxDripRate, maxBurst) { m_enabled = enabled; m_maxDripRate = (maxDripRate == 0 ? m_totalDripRequest : Math.Max(maxDripRate, m_minimumFlow)); if (enabled) { m_dripRate = m_maxDripRate * .5f; } else { m_dripRate = m_maxDripRate; } if (m_parent != null) { m_parent.RegisterRequest(this, m_dripRate); } }
/// <summary> /// Queue an outgoing packet if appropriate. /// </summary> /// <param name="packet"></param> /// <param name="forceQueue">Always queue the packet if at all possible.</param> /// <returns> /// true if the packet has been queued, /// false if the packet has not been queued and should be sent immediately. /// </returns> public bool EnqueueOutgoing(OutgoingPacket packet, bool forceQueue) { int category = (int)packet.Category; if (category >= 0 && category < m_packetOutboxes.Length) { ThreadedClasses.NonblockingQueue <OutgoingPacket> queue = m_packetOutboxes[category]; TokenBucket bucket = m_throttleCategories[category]; // Don't send this packet if there is already a packet waiting in the queue // even if we have the tokens to send it, tokens should go to the already // queued packets if (queue.Count > 0) { queue.Enqueue(packet); return(true); } if (!forceQueue && bucket.RemoveTokens(packet.Buffer.DataLength)) { // Enough tokens were removed from the bucket, the packet will not be queued return(false); } else { // Force queue specified or not enough tokens in the bucket, queue this packet queue.Enqueue(packet); return(true); } } else { // We don't have a token bucket for this category, so it will not be queued return(false); } }
/// <summary> /// Register drip rate requested by a child of this throttle. Pass the /// changes up the hierarchy. /// </summary> public void RegisterRequest(TokenBucket child, Int64 request) { lock (m_children) { m_children[child] = request; TotalDripRequest = 0; foreach (KeyValuePair<TokenBucket, Int64> cref in m_children) TotalDripRequest += cref.Value; } // Pass the new values up to the parent if (Parent != null) { Int64 effectiveDripRate; if (RequestedDripRate > 0) effectiveDripRate = Math.Min(RequestedDripRate, TotalDripRequest); else effectiveDripRate = TotalDripRequest; Parent.RegisterRequest(this, effectiveDripRate); } }
// <summary> // // </summary> public AdaptiveTokenBucket(TokenBucket parent, Int64 maxDripRate, bool enabled) : base(parent,maxDripRate) { m_enabled = enabled; if (m_enabled) { // m_log.DebugFormat("[TOKENBUCKET] Adaptive throttle enabled"); MaxDripRate = maxDripRate; AdjustedDripRate = m_minimumFlow; } }
/// <summary> /// Default constructor /// </summary> /// <param name="parent">Parent bucket if this is a child bucket, or /// null if this is a root bucket</param> /// <param name="maxBurst">Maximum size of the bucket in bytes, or /// zero if this bucket has no maximum capacity</param> /// <param name="dripRate">Rate that the bucket fills, in bytes per /// second. If zero, the bucket always remains full</param> public TokenBucket(TokenBucket parent, Int64 dripRate) { // m_identifier = m_counter++; m_counter++; Parent = parent; RequestedDripRate = dripRate; // TotalDripRequest = dripRate; // this will be overwritten when a child node registers // MaxBurst = (Int64)((double)dripRate * m_quantumsPerBurst); m_lastDrip = Util.EnvironmentTickCount(); }
/// <summary> /// Remove the rate requested by a child of this throttle. Pass the /// changes up the hierarchy. /// </summary> public void UnregisterRequest(TokenBucket child) { lock (m_children) { m_children.Remove(child); // m_totalDripRequest = m_children.Values.Sum(); m_totalDripRequest = 0; foreach (KeyValuePair<TokenBucket, Int64> cref in m_children) m_totalDripRequest += cref.Value; } // Pass the new values up to the parent if (m_parent != null) m_parent.RegisterRequest(this,Math.Min(RequestedDripRate, TotalDripRequest)); }
public void SetThrottles(byte[] throttleData) { byte[] adjData; int pos = 0; if (!BitConverter.IsLittleEndian) { byte[] newData = new byte[7 * 4]; Buffer.BlockCopy(throttleData, 0, newData, 0, 7 * 4); for (int i = 0; i < 7; i++) { Array.Reverse(newData, i * 4, 4); } adjData = newData; } else { adjData = throttleData; } // 0.125f converts from bits to bytes int resend = (int)(BitConverter.ToSingle(adjData, pos) * 0.125f); pos += 4; int land = (int)(BitConverter.ToSingle(adjData, pos) * 0.125f); pos += 4; int wind = (int)(BitConverter.ToSingle(adjData, pos) * 0.125f); pos += 4; int cloud = (int)(BitConverter.ToSingle(adjData, pos) * 0.125f); pos += 4; int task = (int)(BitConverter.ToSingle(adjData, pos) * 0.125f); pos += 4; int texture = (int)(BitConverter.ToSingle(adjData, pos) * 0.125f); pos += 4; int asset = (int)(BitConverter.ToSingle(adjData, pos) * 0.125f); int total = resend + land + wind + cloud + task + texture + asset; // These are subcategories of task that we allocate a percentage to int state = (int)(task * STATE_TASK_PERCENTAGE); task -= state; int transfer = (int)(asset * TRANSFER_ASSET_PERCENTAGE); asset -= transfer; // avatar info cames out from state int avatarinfo = (int)(state * AVATAR_INFO_STATE_PERCENTAGE); state -= avatarinfo; // int total = resend + land + wind + cloud + task + texture + asset + state + avatarinfo; // Make sure none of the throttles are set below our packet MTU, // otherwise a throttle could become permanently clogged Rates[(int)ThrottleOutPacketType.Resend] = resend; Rates[(int)ThrottleOutPacketType.Land] = land; Rates[(int)ThrottleOutPacketType.Wind] = wind; Rates[(int)ThrottleOutPacketType.Cloud] = cloud; Rates[(int)ThrottleOutPacketType.Task] = task + state + avatarinfo; Rates[(int)ThrottleOutPacketType.Texture] = texture; Rates[(int)ThrottleOutPacketType.Asset] = asset + transfer; Rates[(int)ThrottleOutPacketType.State] = state; TotalRateRequested = total; TotalRateMin = (int)(total * 0.1); if (TotalRateMin < MINPERCLIENTRATE) { TotalRateMin = MINPERCLIENTRATE; } total = TotalRateMin; // let it grow slowlly //MainConsole.Instance.WarnFormat("[LLUDPCLIENT]: {0} is setting throttles. Resend={1}, Land={2}, Wind={3}, Cloud={4}, Task={5}, Texture={6}, Asset={7}, State={8}, AvatarInfo={9}, Transfer={10}, TaskFull={11}, Total={12}", // AgentID, resend, land, wind, cloud, task, texture, asset, state, avatarinfo, transfer, task + state + avatarinfo, total); // Update the token buckets with new throttle values TokenBucket bucket = m_throttle; bucket.DripRate = total; bucket.MaxBurst = total; // Reset the packed throttles cached data m_packedThrottles = null; }
/// <summary> /// Default constructor /// </summary> /// <param name="identifier">Identifier for this token bucket</param> /// <param name="parent">Parent bucket if this is a child bucket, or /// null if this is a root bucket</param> /// <param name="maxBurst">Maximum size of the bucket in bytes, or /// zero if this bucket has no maximum capacity</param> /// <param name="dripRate">Rate that the bucket fills, in bytes per /// second. If zero, the bucket always remains full</param> public TokenBucket(TokenBucket parent, float dripRate, float MaxBurst) { m_counter++; Parent = parent; RequestedDripRate = dripRate; RequestedBurst = MaxBurst; // TotalDripRequest = dripRate; // this will be overwritten when a child node registers // MaxBurst = (Int64)((double)dripRate * m_quantumsPerBurst); m_lastDrip = Util.EnvironmentTickCount() + 100000; }