Skip to content

Commit

Permalink
Update LibreQoS.py
Browse files Browse the repository at this point in the history
  • Loading branch information
rchac authored Feb 19, 2025
1 parent 1793f45 commit 8de8556
Showing 1 changed file with 46 additions and 13 deletions.
59 changes: 46 additions & 13 deletions src/LibreQoS.py
Original file line number Diff line number Diff line change
Expand Up @@ -653,19 +653,28 @@ def flattenA(data, depth):

# Group circuits by parent node. Reduces runtime for section below this one.
circuits_by_parent_node = {}
circuit_min_down_combined_by_parent_node = {}
circuit_min_up_combined_by_parent_node = {}
for circuit in subscriberCircuits:
#If a device from ShapedDevices.csv lists this node as its Parent Node, attach it as a leaf to this node HTB
if circuit['ParentNode'] not in circuits_by_parent_node:
circuits_by_parent_node[circuit['ParentNode']] = []
temp = circuits_by_parent_node[circuit['ParentNode']]
temp.append(circuit)
circuits_by_parent_node[circuit['ParentNode']] = temp
if circuit['ParentNode'] not in circuit_min_down_combined_by_parent_node:
circuit_min_down_combined_by_parent_node[circuit['ParentNode']] = 0
circuit_min_down_combined_by_parent_node[circuit['ParentNode']] += circuit['minDownload']
if circuit['ParentNode'] not in circuit_min_up_combined_by_parent_node:
circuit_min_up_combined_by_parent_node[circuit['ParentNode']] = 0
circuit_min_up_combined_by_parent_node[circuit['ParentNode']] += circuit['minUpload']

# Parse network structure and add devices from ShapedDevices.csv
print("Parsing network structure and tallying devices")
parentNodes = []
minorByCPUpreloaded = {}
knownClassIDs = []
nodes_requiring_min_squashing = {}
# Track minor counter by CPU. This way we can have > 32000 hosts (htb has u16 limit to minor handle)
for x in range(queuesAvailable):
minorByCPUpreloaded[x+1] = 3
Expand Down Expand Up @@ -708,9 +717,7 @@ def traverseNetwork(data, depth, major, minorByCPU, queue, parentClassID, upPare
data[node]['uploadBandwidthMbps'] = min(data[node]['uploadBandwidthMbps'],parentMaxUL)
data[node]['downloadBandwidthMbpsMin'] = min(data[node]['downloadBandwidthMbpsMin'], data[node]['downloadBandwidthMbps'], parentMinDL)
data[node]['uploadBandwidthMbpsMin'] = min(data[node]['uploadBandwidthMbpsMin'], data[node]['uploadBandwidthMbps'], parentMinUL)
# Calculations used to be done in findBandwidthMins(), determine optimal HTB rates (mins) and ceils (maxs)
# For some reason that doesn't always yield the expected result, so it's better to play with ceil more than rate
# Here we override the rate as 95% of ceil, unless it's specified alreayd in network.json
# Calculations are done in findBandwidthMins() to determine optimal HTB rates (mins) and ceils (maxs)
data[node]['classMajor'] = hex(major)
data[node]['up_classMajor'] = hex(major + stickOffset)
data[node]['classMinor'] = hex(minorByCPU[queue])
Expand All @@ -724,8 +731,18 @@ def traverseNetwork(data, depth, major, minorByCPU, queue, parentClassID, upPare
}
parentNodes.append(thisParentNode)
minorByCPU[queue] = minorByCPU[queue] + 1
#If a device from ShapedDevices.csv lists this node as its Parent Node, attach it as a leaf to this node HTB
# If a device from ShapedDevices.csv lists this node as its Parent Node, attach it as a leaf to this node HTB
if node in circuits_by_parent_node:
# If mins of circuits combined exceed min of parent node - set to 1
override_min_down = None
override_min_up = None
if (circuit_min_down_combined_by_parent_node[node] > data[node]['downloadBandwidthMbpsMin']) or (circuit_min_up_combined_by_parent_node[node] > data[node]['uploadBandwidthMbpsMin']):
override_min_down = 1
override_min_up = 1
warnings.warn("The combined minimums of circuits in Parent Node [" + node + "] exceeded that of the parent node. Reducing these circuits' minimums to 1 now.", stacklevel=2)
if ((override_min_down * len(circuits_by_parent_node[node])) > data[node]['downloadBandwidthMbpsMin']) or ((override_min_up * len(circuits_by_parent_node[node])) > data[node]['uploadBandwidthMbpsMin']):
warnings.warn("Even with this change, minimums will exceed the min rate of the parent node. Using fq_codel for these circuits.", stacklevel=2)
nodes_requiring_min_squashing[node] = True
for circuit in circuits_by_parent_node[node]:
if node == circuit['ParentNode']:
if monitor_mode_only() == False:
Expand All @@ -742,6 +759,10 @@ def traverseNetwork(data, depth, major, minorByCPU, queue, parentClassID, upPare
# Create circuit dictionary to be added to network structure, eventually output as queuingStructure.json
maxDownload = min(circuit['maxDownload'],data[node]['downloadBandwidthMbps'])
maxUpload = min(circuit['maxUpload'],data[node]['uploadBandwidthMbps'])
if override_min_down:
circuit['minDownload'] = 1
if override_min_up:
circuit['minUpload'] = 1
minDownload = min(circuit['minDownload'],maxDownload)
minUpload = min(circuit['minUpload'],maxUpload)
thisNewCircuitItemForNetwork = {
Expand Down Expand Up @@ -898,11 +919,17 @@ def sqmFixupRate(rate:int, sqm:str) -> str:
linuxTCcommands.append(command)
if 'circuits' in data[node]:
for circuit in data[node]['circuits']:
# # Handle low min rates of 0 to mean 100 kbps
# if circuit['minDownload'] == 0:
# circuit['minDownload'] = 0.1
# if circuit['minUpload'] == 0:
# circuit['minUpload'] = 0.1
# If circuit mins exceed node mins - handle low min rates of 1 to mean 10 kbps and use fq_codel.
# Avoid changing minDownload or minUpload because they are used in queuingStructure.json, and must remain integers.
fq_override = False
min_down = circuit['minDownload']
min_up = circuit['minUpload']
if node in nodes_requiring_min_squashing:
if min_down == 1:
min_down = 0.01
if min_up == 1:
min_up = 0.01
fq_override = True
# Generate TC commands to be executed later
tcComment = " # CircuitID: " + circuit['circuitID'] + " DeviceIDs: "
for device in circuit['devices']:
Expand All @@ -911,20 +938,26 @@ def sqmFixupRate(rate:int, sqm:str) -> str:
if 'comment' in circuit['devices'][0]:
tcComment = '' # tcComment + '| Comment: ' + circuit['devices'][0]['comment']
tcComment = tcComment.replace("\n", "")
command = 'class add dev ' + interface_a() + ' parent ' + data[node]['classid'] + ' classid ' + circuit['classMinor'] + ' htb rate '+ str(circuit['minDownload']) + 'mbit ceil '+ str(circuit['maxDownload']) + 'mbit prio 3' + quantum(circuit['maxDownload']) + tcComment
command = 'class add dev ' + interface_a() + ' parent ' + data[node]['classid'] + ' classid ' + circuit['classMinor'] + ' htb rate '+ str(min_down) + 'mbit ceil '+ str(circuit['maxDownload']) + 'mbit prio 3' + quantum(circuit['maxDownload']) + tcComment
linuxTCcommands.append(command)
# Only add CAKE / fq_codel qdisc if monitorOnlyMode is Off
if monitor_mode_only() == False:
# SQM Fixup for lower rates
useSqm = sqmFixupRate(circuit['maxDownload'], sqm())
if fq_override:
useSqm = sqmFixupRate(circuit['maxDownload'], "fq_codel")
else:
useSqm = sqmFixupRate(circuit['maxDownload'], sqm())
command = 'qdisc add dev ' + interface_a() + ' parent ' + circuit['classMajor'] + ':' + circuit['classMinor'] + ' ' + useSqm
linuxTCcommands.append(command)
command = 'class add dev ' + interface_b() + ' parent ' + data[node]['up_classid'] + ' classid ' + circuit['classMinor'] + ' htb rate '+ str(circuit['minUpload']) + 'mbit ceil '+ str(circuit['maxUpload']) + 'mbit prio 3' + quantum(circuit['maxUpload'])
command = 'class add dev ' + interface_b() + ' parent ' + data[node]['up_classid'] + ' classid ' + circuit['classMinor'] + ' htb rate '+ str(min_up) + 'mbit ceil '+ str(circuit['maxUpload']) + 'mbit prio 3' + quantum(circuit['maxUpload'])
linuxTCcommands.append(command)
# Only add CAKE / fq_codel qdisc if monitorOnlyMode is Off
if monitor_mode_only() == False:
# SQM Fixup for lower rates
useSqm = sqmFixupRate(circuit['maxUpload'], sqm())
if fq_override:
useSqm = sqmFixupRate(circuit['maxUpload'], "fq_codel")
else:
useSqm = sqmFixupRate(circuit['maxUpload'], sqm())
command = 'qdisc add dev ' + interface_b() + ' parent ' + circuit['up_classMajor'] + ':' + circuit['classMinor'] + ' ' + useSqm
linuxTCcommands.append(command)
pass
Expand Down

0 comments on commit 8de8556

Please sign in to comment.