From e33077f95bf3919a1ac50150ca36923da1622784 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Robert=20Chac=C3=B3n?= Date: Fri, 2 Jul 2021 22:18:07 -0600 Subject: [PATCH] Add files via upload --- v0.9/LibreQoS.py | 127 ++++++++++++++++++++--------------------------- 1 file changed, 54 insertions(+), 73 deletions(-) diff --git a/v0.9/LibreQoS.py b/v0.9/LibreQoS.py index 04125a34..479979f1 100644 --- a/v0.9/LibreQoS.py +++ b/v0.9/LibreQoS.py @@ -100,126 +100,107 @@ def refreshShapers(): # If an AP is specified for a device in Shaper.csv, but AP is not listed in AccessPoints.csv, raise exception if (AP != "none") and (AP not in accessPointDownloadMbps): raise ValueError('AP ' + AP + ' not listed in AccessPoints.csv') - devices.append(thisDevice) - + devices.append(thisDevice) # If no AP is specified for a device in Shaper.csv, it is placed under this 'default' AP shaper, set to bandwidth max at edge accessPointDownloadMbps['none'] = upstreamBandwidthCapacityDownloadMbps accessPointUploadMbps['none'] = upstreamBandwidthCapacityUploadMbps - #Sort into bins by AP result = collections.defaultdict(list) - for d in devices: result[d['AP']].append(d) - devicesByAP = list(result.values()) - clearPriorSettings(interfaceA, interfaceB) - #XDP-CPUMAP-TC shell('./xdp-cpumap-tc/bin/xps_setup.sh -d ' + interfaceA + ' --default') shell('./xdp-cpumap-tc/bin/xps_setup.sh -d ' + interfaceB + ' --default') - shell('./xdp-cpumap-tc/src/xdp_iphash_to_cpu --dev ' + interfaceA + ' --lan') shell('./xdp-cpumap-tc/src/xdp_iphash_to_cpu --dev ' + interfaceB + ' --wan') shell('./xdp-cpumap-tc/src/xdp_iphash_to_cpu_cmdline --clear') - shell('./xdp-cpumap-tc/src/tc_classify --dev-egress ' + interfaceA) shell('./xdp-cpumap-tc/src/tc_classify --dev-egress ' + interfaceB) - - #Create MQ - cpusAvailable = 0 - + #Find queues available + queuesAvailable = 0 path = '/sys/class/net/' + interfaceA + '/queues/' directory_contents = os.listdir(path) print(directory_contents) for item in directory_contents: if "tx-" in str(item): - cpusAvailable += 1 + queuesAvailable += 1 + #For VMs, must reduce queues if more than 9, for some reason + if queuesAvailable > 9: + command = 'grep -q ^flags.*\ hypervisor\ /proc/cpuinfo && echo "This machine is a VM"' + try: + output = subprocess.check_output(command, stderr=subprocess.STDOUT, shell=True).decode() + success = True + except subprocess.CalledProcessError as e: + output = e.output.decode() + success = False + if "This machine is a VM" in output: + queuesAvailable = 9 + #Create MQ thisInterface = interfaceA shell('tc qdisc replace dev ' + thisInterface + ' root handle 7FFF: mq') - for cpu in range(cpusAvailable): - shell('tc qdisc add dev ' + thisInterface + ' parent 7FFF:' + str(cpu+1) + ' handle ' + str(cpu+1) + ': htb default 2') - shell('tc class add dev ' + thisInterface + ' parent ' + str(cpu+1) + ': classid ' + str(cpu+1) + ':1 htb rate '+ str(upstreamBandwidthCapacityDownloadMbps) + 'mbit ceil ' + str(upstreamBandwidthCapacityDownloadMbps) + 'mbit') - shell('tc qdisc add dev ' + thisInterface + ' parent ' + str(cpu+1) + ':1 ' + fqOrCAKE) - #Default class - traffic gets passed through this limiter if not otherwise classified by the Shaper.csv - shell('tc class add dev ' + thisInterface + ' parent ' + str(cpu+1) + ':1 classid ' + str(cpu+1) + ':2 htb rate ' + str(defaultClassCapacityDownloadMbps) + 'mbit ceil ' + str(defaultClassCapacityDownloadMbps) + 'mbit prio 5') - shell('tc qdisc add dev ' + thisInterface + ' parent ' + str(cpu+1) + ':2 ' + fqOrCAKE) + for queue in range(queuesAvailable): + shell('tc qdisc add dev ' + thisInterface + ' parent 7FFF:' + str(queue+1) + ' handle ' + str(queue+1) + ': htb default 2') + shell('tc class add dev ' + thisInterface + ' parent ' + str(queue+1) + ': classid ' + str(queue+1) + ':1 htb rate '+ str(upstreamBandwidthCapacityDownloadMbps) + 'mbit ceil ' + str(upstreamBandwidthCapacityDownloadMbps) + 'mbit') + shell('tc qdisc add dev ' + thisInterface + ' parent ' + str(queue+1) + ':1 ' + fqOrCAKE) + #Default class - traffic gets passed through this limiter with lower priority if not otherwise classified by the Shaper.csv + shell('tc class add dev ' + thisInterface + ' parent ' + str(queue+1) + ':1 classid ' + str(queue+1) + ':2 htb rate ' + str(defaultClassCapacityDownloadMbps) + 'mbit ceil ' + str(defaultClassCapacityDownloadMbps) + 'mbit prio 5') + shell('tc qdisc add dev ' + thisInterface + ' parent ' + str(queue+1) + ':2 ' + fqOrCAKE) thisInterface = interfaceB shell('tc qdisc replace dev ' + thisInterface + ' root handle 7FFF: mq') - for cpu in range(cpusAvailable): - shell('tc qdisc add dev ' + thisInterface + ' parent 7FFF:' + str(cpu+1) + ' handle ' + str(cpu+1) + ': htb default 2') - shell('tc class add dev ' + thisInterface + ' parent ' + str(cpu+1) + ': classid ' + str(cpu+1) + ':1 htb rate '+ str(upstreamBandwidthCapacityDownloadMbps) + 'mbit ceil ' + str(upstreamBandwidthCapacityDownloadMbps) + 'mbit') - shell('tc qdisc add dev ' + thisInterface + ' parent ' + str(cpu+1) + ':1 ' + fqOrCAKE) - #Default class - traffic gets passed through this limiter if not otherwise classified by the Shaper.csv - shell('tc class add dev ' + thisInterface + ' parent ' + str(cpu+1) + ':1 classid ' + str(cpu+1) + ':2 htb rate ' + str(defaultClassCapacityDownloadMbps) + 'mbit ceil ' + str(defaultClassCapacityDownloadMbps) + 'mbit prio 5') - shell('tc qdisc add dev ' + thisInterface + ' parent ' + str(cpu+1) + ':2 ' + fqOrCAKE) + for queue in range(queuesAvailable): + shell('tc qdisc add dev ' + thisInterface + ' parent 7FFF:' + str(queue+1) + ' handle ' + str(queue+1) + ': htb default 2') + shell('tc class add dev ' + thisInterface + ' parent ' + str(queue+1) + ': classid ' + str(queue+1) + ':1 htb rate '+ str(upstreamBandwidthCapacityUploadMbps) + 'mbit ceil ' + str(upstreamBandwidthCapacityUploadMbps) + 'mbit') + shell('tc qdisc add dev ' + thisInterface + ' parent ' + str(queue+1) + ':1 ' + fqOrCAKE) + #Default class - traffic gets passed through this limiter with lower priority if not otherwise classified by the Shaper.csv + shell('tc class add dev ' + thisInterface + ' parent ' + str(queue+1) + ':1 classid ' + str(queue+1) + ':2 htb rate ' + str(defaultClassCapacityUploadMbps) + 'mbit ceil ' + str(defaultClassCapacityUploadMbps) + 'mbit prio 5') + shell('tc qdisc add dev ' + thisInterface + ' parent ' + str(queue+1) + ':2 ' + fqOrCAKE) - currentCPUcounter = 1 - ipv4Filters = [] - ipv6Filters = [] - - cpuMinorCounterDict = {} - - for cpu in range(cpusAvailable): - cpuMinorCounterDict[cpu] = 3 + currentQueueCounter = 1 + queueMinorCounterDict = {} + # :1 and :2 are used for root and default classes, so start each counter at :3 + for queueNum in range(queuesAvailable): + queueMinorCounterDict[queueNum] = 3 for AP in devicesByAP: #Create HTBs by AP currentAPname = AP[0]['AP'] thisAPdownload = accessPointDownloadMbps[currentAPname] thisAPupload = accessPointUploadMbps[currentAPname] - - major = currentCPUcounter - minor = cpuMinorCounterDict[currentCPUcounter] + major = currentQueueCounter + minor = queueMinorCounterDict[currentQueueCounter] #HTBs for each AP - thisHTBclassID = str(currentCPUcounter) + ':' + str(minor) - # Guarentee AP gets at least 1/2 of its radio capacity, allow up to its max radio capacity when network not at peak load - shell('tc class add dev ' + interfaceA + ' parent ' + str(currentCPUcounter) + ':1 classid ' + str(minor) + ' htb rate '+ str(round(thisAPdownload/2)) + 'mbit ceil '+ str(round(thisAPdownload)) + 'mbit prio 3') - shell('tc qdisc add dev ' + interfaceA + ' parent ' + str(currentCPUcounter) + ':' + str(minor) + ' ' + fqOrCAKE) - shell('tc class add dev ' + interfaceB + ' parent ' + str(major) + ':1 classid ' + str(minor) + ' htb rate '+ str(round(thisAPupload/2)) + 'mbit ceil '+ str(round(thisAPupload)) + 'mbit prio 3') + thisHTBclassID = str(currentQueueCounter) + ':' + str(minor) + # Guarentee AP gets at least 1/4 of its radio capacity, allow up to its max radio capacity when network not at peak load + shell('tc class add dev ' + interfaceA + ' parent ' + str(currentQueueCounter) + ':1 classid ' + str(minor) + ' htb rate '+ str(round(thisAPdownload/4)) + 'mbit ceil '+ str(round(thisAPdownload)) + 'mbit prio 3') + shell('tc qdisc add dev ' + interfaceA + ' parent ' + str(currentQueueCounter) + ':' + str(minor) + ' ' + fqOrCAKE) + shell('tc class add dev ' + interfaceB + ' parent ' + str(major) + ':1 classid ' + str(minor) + ' htb rate '+ str(round(thisAPupload/4)) + 'mbit ceil '+ str(round(thisAPupload)) + 'mbit prio 3') shell('tc qdisc add dev ' + interfaceB + ' parent ' + str(major) + ':' + str(minor) + ' ' + fqOrCAKE) minor += 1 for device in AP: #QDiscs for each AP - downloadMin = device['downloadMin'] - downloadMax = device['downloadMax'] - uploadMin = device['uploadMin'] - uploadMax = device['uploadMax'] - shell('tc class add dev ' + interfaceA + ' parent ' + thisHTBclassID + ' classid ' + str(minor) + ' htb rate '+ str(downloadMin) + 'mbit ceil '+ str(downloadMax) + 'mbit prio 3') + shell('tc class add dev ' + interfaceA + ' parent ' + thisHTBclassID + ' classid ' + str(minor) + ' htb rate '+ str(device['downloadMin']) + 'mbit ceil '+ str(device['downloadMax']) + 'mbit prio 3') shell('tc qdisc add dev ' + interfaceA + ' parent ' + str(major) + ':' + str(minor) + ' ' + fqOrCAKE) - shell('tc class add dev ' + interfaceB + ' parent ' + thisHTBclassID + ' classid ' + str(minor) + ' htb rate '+ str(uploadMin) + 'mbit ceil '+ str(uploadMax) + 'mbit prio 3') + shell('tc class add dev ' + interfaceB + ' parent ' + thisHTBclassID + ' classid ' + str(minor) + ' htb rate '+ str(device['uploadMin']) + 'mbit ceil '+ str(device['uploadMax']) + 'mbit prio 3') shell('tc qdisc add dev ' + interfaceB + ' parent ' + str(major) + ':' + str(minor) + ' ' + fqOrCAKE) if device['ipv4']: parentString = str(major) + ':' flowIDstring = str(major) + ':' + str(minor) - ipv4Filters.append((device['ipv4'], parentString, flowIDstring, currentCPUcounter)) - if device['ipv6']: - parentString = str(major) + ':' - flowIDstring = str(major) + ':' + str(minor) - ipv6Filters.append((device['ipv6'], parentString, flowIDstring, currentCPUcounter)) - deviceQDiscID = str(major) + ':' + str(minor) + shell('./xdp-cpumap-tc/src/xdp_iphash_to_cpu_cmdline --add --ip ' + device['ipv4'] + ' --cpu ' + str(currentQueueCounter-1) + ' --classid ' + flowIDstring) + #Once XDP-CPUMAP-TC handles IPv6, this can be added + #if device['ipv6']: + # parentString = str(major) + ':' + # flowIDstring = str(major) + ':' + str(minor) + # shell('./xdp-cpumap-tc/src/xdp_iphash_to_cpu_cmdline --add --ip ' + device['ipv6'] + ' --cpu ' + str(currentQueueCounter-1) + ' --classid ' + flowIDstring) device['qdisc'] = str(major) + ':' + str(minor) minor += 1 - cpuMinorCounterDict[currentCPUcounter] = minor + queueMinorCounterDict[currentQueueCounter] = minor - currentCPUcounter += 1 - if currentCPUcounter > cpusAvailable: - currentCPUcounter = 1 - - #IPv4 Filters - hashTableCounter = 3 + cpusAvailable - for cpu in range(cpusAvailable): - for ipv4Filter in ipv4Filters: - ipv4, parent, classid, filterCpuNum = ipv4Filter - if filterCpuNum is cpu: - #if '/' in ipv4: - # ipv4 = ipv4.split('/')[0] - filterHandle = hex(filterHandleCounter) - shell('./xdp-cpumap-tc/src/xdp_iphash_to_cpu_cmdline --add --ip ' + ipv4 + ' --cpu ' + str(filterCpuNum-1) + ' --classid ' + classid) - filterHandleCounter += 1 - filterHandleCounter += 1 + currentQueueCounter += 1 + if currentQueueCounter > queuesAvailable: + currentQueueCounter = 1 #Save devices to file to allow for statistics runs with open('devices.json', 'w') as outfile: