mirror of
https://github.com/LibreQoE/LibreQoS.git
synced 2025-02-25 18:55:32 -06:00
Generate parent nodes to spread ShapedDevices.csv entries across CPU cores if ParentNode not defined
This commit is contained in:
parent
7d3212d28a
commit
e60f3f4ffd
@ -13,7 +13,7 @@ import warnings
|
|||||||
|
|
||||||
from ispConfig import fqOrCAKE, upstreamBandwidthCapacityDownloadMbps, upstreamBandwidthCapacityUploadMbps, \
|
from ispConfig import fqOrCAKE, upstreamBandwidthCapacityDownloadMbps, upstreamBandwidthCapacityUploadMbps, \
|
||||||
defaultClassCapacityDownloadMbps, defaultClassCapacityUploadMbps, interfaceA, interfaceB, enableActualShellCommands, \
|
defaultClassCapacityDownloadMbps, defaultClassCapacityUploadMbps, interfaceA, interfaceB, enableActualShellCommands, \
|
||||||
runShellCommandsAsSudo
|
runShellCommandsAsSudo, generatedPNDownloadMbps, generatedPNUploadMbps
|
||||||
|
|
||||||
|
|
||||||
def shell(command):
|
def shell(command):
|
||||||
@ -170,9 +170,10 @@ def refreshShapers():
|
|||||||
if circuitID in knownCircuitIDs:
|
if circuitID in knownCircuitIDs:
|
||||||
for circuit in subscriberCircuits:
|
for circuit in subscriberCircuits:
|
||||||
if circuit['circuitID'] == circuitID:
|
if circuit['circuitID'] == circuitID:
|
||||||
if circuit['ParentNode'] != ParentNode:
|
if circuit['ParentNode'] != "none":
|
||||||
errorMessageString = "Device " + deviceName + " with deviceID " + deviceID + " had different Parent Node from other devices of circuit ID #" + circuitID
|
if circuit['ParentNode'] != ParentNode:
|
||||||
raise ValueError(errorMessageString)
|
errorMessageString = "Device " + deviceName + " with deviceID " + deviceID + " had different Parent Node from other devices of circuit ID #" + circuitID
|
||||||
|
raise ValueError(errorMessageString)
|
||||||
if ((circuit['downloadMin'] != round(int(downloadMin)*tcpOverheadFactor))
|
if ((circuit['downloadMin'] != round(int(downloadMin)*tcpOverheadFactor))
|
||||||
or (circuit['uploadMin'] != round(int(uploadMin)*tcpOverheadFactor))
|
or (circuit['uploadMin'] != round(int(uploadMin)*tcpOverheadFactor))
|
||||||
or (circuit['downloadMax'] != round(int(downloadMax)*tcpOverheadFactor))
|
or (circuit['downloadMax'] != round(int(downloadMax)*tcpOverheadFactor))
|
||||||
@ -254,6 +255,36 @@ def refreshShapers():
|
|||||||
#Load network heirarchy
|
#Load network heirarchy
|
||||||
with open('network.json', 'r') as j:
|
with open('network.json', 'r') as j:
|
||||||
network = json.loads(j.read())
|
network = json.loads(j.read())
|
||||||
|
|
||||||
|
# Find queues and CPU cores available. Use min between those two as queuesAvailable
|
||||||
|
queuesAvailable = 0
|
||||||
|
path = '/sys/class/net/' + interfaceA + '/queues/'
|
||||||
|
directory_contents = os.listdir(path)
|
||||||
|
for item in directory_contents:
|
||||||
|
if "tx-" in str(item):
|
||||||
|
queuesAvailable += 1
|
||||||
|
|
||||||
|
print("NIC queues:\t" + str(queuesAvailable))
|
||||||
|
cpuCount = multiprocessing.cpu_count()
|
||||||
|
print("CPU cores:\t" + str(cpuCount))
|
||||||
|
queuesAvailable = min(queuesAvailable,cpuCount)
|
||||||
|
|
||||||
|
#Generate Parent Nodes. Spread ShapedDevices.csv which lack defined ParentNode across these (balance across CPUs)
|
||||||
|
generatedPNs = []
|
||||||
|
for x in range(queuesAvailable):
|
||||||
|
genPNname = "Generated_PN_" + str(x+1)
|
||||||
|
network[genPNname] = {
|
||||||
|
"downloadBandwidthMbps":generatedPNDownloadMbps,
|
||||||
|
"uploadBandwidthMbps":generatedPNUploadMbps
|
||||||
|
}
|
||||||
|
generatedPNs.append(genPNname)
|
||||||
|
genPNcounter = 0
|
||||||
|
for circuit in subscriberCircuits:
|
||||||
|
if circuit['ParentNode'] == 'none':
|
||||||
|
circuit['ParentNode'] = generatedPNs[genPNcounter]
|
||||||
|
genPNcounter += 1
|
||||||
|
if genPNcounter >= queuesAvailable:
|
||||||
|
genPNcounter = 0
|
||||||
|
|
||||||
#Find the bandwidth minimums for each node by combining mimimums of devices lower in that node's heirarchy
|
#Find the bandwidth minimums for each node by combining mimimums of devices lower in that node's heirarchy
|
||||||
def findBandwidthMins(data, depth):
|
def findBandwidthMins(data, depth):
|
||||||
@ -275,20 +306,7 @@ def refreshShapers():
|
|||||||
|
|
||||||
minDownload, minUpload = findBandwidthMins(network, 0)
|
minDownload, minUpload = findBandwidthMins(network, 0)
|
||||||
|
|
||||||
# Find queues and CPU cores available. Use min between those two as queuesAvailable
|
#Parse network structure. For each tier, create corresponding HTB and leaf classes. Prepare for execution later
|
||||||
queuesAvailable = 0
|
|
||||||
path = '/sys/class/net/' + interfaceA + '/queues/'
|
|
||||||
directory_contents = os.listdir(path)
|
|
||||||
for item in directory_contents:
|
|
||||||
if "tx-" in str(item):
|
|
||||||
queuesAvailable += 1
|
|
||||||
|
|
||||||
print("NIC queues:\t" + str(queuesAvailable))
|
|
||||||
cpuCount = multiprocessing.cpu_count()
|
|
||||||
print("CPU cores:\t" + str(cpuCount))
|
|
||||||
queuesAvailable = min(queuesAvailable,cpuCount)
|
|
||||||
|
|
||||||
#Parse network.json. For each tier, create corresponding HTB and leaf classes. Prepare for execution later
|
|
||||||
linuxTCcommands = []
|
linuxTCcommands = []
|
||||||
xdpCPUmapCommands = []
|
xdpCPUmapCommands = []
|
||||||
devicesShaped = []
|
devicesShaped = []
|
||||||
@ -296,7 +314,7 @@ def refreshShapers():
|
|||||||
def traverseNetwork(data, depth, major, minor, queue, parentClassID, parentMaxDL, parentMaxUL):
|
def traverseNetwork(data, depth, major, minor, queue, parentClassID, parentMaxDL, parentMaxUL):
|
||||||
tabs = ' ' * depth
|
tabs = ' ' * depth
|
||||||
for elem in data:
|
for elem in data:
|
||||||
print(tabs + elem)
|
#print(tabs + elem)
|
||||||
elemClassID = hex(major) + ':' + hex(minor)
|
elemClassID = hex(major) + ':' + hex(minor)
|
||||||
#Cap based on this node's max bandwidth, or parent node's max bandwidth, whichever is lower
|
#Cap based on this node's max bandwidth, or parent node's max bandwidth, whichever is lower
|
||||||
elemDownloadMax = min(data[elem]['downloadBandwidthMbps'],parentMaxDL)
|
elemDownloadMax = min(data[elem]['downloadBandwidthMbps'],parentMaxDL)
|
||||||
@ -348,7 +366,7 @@ def refreshShapers():
|
|||||||
xdpCPUmapCommands.append('./xdp-cpumap-tc/src/xdp_iphash_to_cpu_cmdline --add --ip ' + str(ipv4) + ' --cpu ' + hex(queue-1) + ' --classid ' + flowIDstring)
|
xdpCPUmapCommands.append('./xdp-cpumap-tc/src/xdp_iphash_to_cpu_cmdline --add --ip ' + str(ipv4) + ' --cpu ' + hex(queue-1) + ' --classid ' + flowIDstring)
|
||||||
if device['deviceName'] not in devicesShaped:
|
if device['deviceName'] not in devicesShaped:
|
||||||
devicesShaped.append(device['deviceName'])
|
devicesShaped.append(device['deviceName'])
|
||||||
print()
|
#print()
|
||||||
minor += 1
|
minor += 1
|
||||||
#Recursive call this function for children nodes attached to this node
|
#Recursive call this function for children nodes attached to this node
|
||||||
if 'children' in data[elem]:
|
if 'children' in data[elem]:
|
||||||
@ -403,11 +421,12 @@ def refreshShapers():
|
|||||||
# Default class can use up to defaultClassCapacityUploadMbps when that bandwidth isn't used by known hosts.
|
# Default class can use up to defaultClassCapacityUploadMbps when that bandwidth isn't used by known hosts.
|
||||||
shell('tc class add dev ' + thisInterface + ' parent ' + hex(queue+1) + ':1 classid ' + hex(queue+1) + ':2 htb rate ' + str(defaultClassCapacityUploadMbps/4) + 'mbit ceil ' + str(defaultClassCapacityUploadMbps) + 'mbit prio 5')
|
shell('tc class add dev ' + thisInterface + ' parent ' + hex(queue+1) + ':1 classid ' + hex(queue+1) + ':2 htb rate ' + str(defaultClassCapacityUploadMbps/4) + 'mbit ceil ' + str(defaultClassCapacityUploadMbps) + 'mbit prio 5')
|
||||||
shell('tc qdisc add dev ' + thisInterface + ' parent ' + hex(queue+1) + ':2 ' + fqOrCAKE)
|
shell('tc qdisc add dev ' + thisInterface + ' parent ' + hex(queue+1) + ':2 ' + fqOrCAKE)
|
||||||
print()
|
#print()
|
||||||
|
|
||||||
#Execute actual Linux TC and XDP-CPUMAP-TC filter commands
|
#Execute actual Linux TC and XDP-CPUMAP-TC filter commands
|
||||||
with open('linux_tc.txt', 'w') as f:
|
with open('linux_tc.txt', 'w') as f:
|
||||||
for line in linuxTCcommands:
|
for line in linuxTCcommands:
|
||||||
|
print(line)
|
||||||
f.write(f"{line}\n")
|
f.write(f"{line}\n")
|
||||||
|
|
||||||
shell("/sbin/tc -f -b linux_tc.txt")
|
shell("/sbin/tc -f -b linux_tc.txt")
|
||||||
|
Loading…
Reference in New Issue
Block a user