mirror of
https://github.com/LibreQoE/LibreQoS.git
synced 2025-02-25 18:55:32 -06:00
Add monitorOnlyMode. Note: only latency is tracked in monitorOnlyMode
This commit is contained in:
parent
c9e07e33a8
commit
afcf7c8b70
@ -1,5 +1,4 @@
|
|||||||
#!/usr/bin/python3
|
#!/usr/bin/python3
|
||||||
#!/usr/bin/python3
|
|
||||||
# v1.3
|
# v1.3
|
||||||
|
|
||||||
import csv
|
import csv
|
||||||
@ -20,7 +19,7 @@ import shutil
|
|||||||
import binpacking
|
import binpacking
|
||||||
|
|
||||||
from ispConfig import fqOrCAKE, upstreamBandwidthCapacityDownloadMbps, upstreamBandwidthCapacityUploadMbps, \
|
from ispConfig import fqOrCAKE, upstreamBandwidthCapacityDownloadMbps, upstreamBandwidthCapacityUploadMbps, \
|
||||||
interfaceA, interfaceB, enableActualShellCommands, useBinPackingToBalanceCPU, \
|
interfaceA, interfaceB, enableActualShellCommands, useBinPackingToBalanceCPU, monitorOnlyMode, \
|
||||||
runShellCommandsAsSudo, generatedPNDownloadMbps, generatedPNUploadMbps, queuesAvailableOverride
|
runShellCommandsAsSudo, generatedPNDownloadMbps, generatedPNUploadMbps, queuesAvailableOverride
|
||||||
|
|
||||||
# Automatically account for TCP overhead of plans. For example a 100Mbps plan needs to be set to 109Mbps for the user to ever see that result on a speed test
|
# Automatically account for TCP overhead of plans. For example a 100Mbps plan needs to be set to 109Mbps for the user to ever see that result on a speed test
|
||||||
@ -265,6 +264,12 @@ def loadSubscriberCircuits(shapedDevicesFile):
|
|||||||
commentsRemoved.pop(0)
|
commentsRemoved.pop(0)
|
||||||
for row in commentsRemoved:
|
for row in commentsRemoved:
|
||||||
circuitID, circuitName, deviceID, deviceName, ParentNode, mac, ipv4_input, ipv6_input, downloadMin, uploadMin, downloadMax, uploadMax, comment = row
|
circuitID, circuitName, deviceID, deviceName, ParentNode, mac, ipv4_input, ipv6_input, downloadMin, uploadMin, downloadMax, uploadMax, comment = row
|
||||||
|
# If in monitorOnlyMode, override bandwidth rates to where no shaping will actually occur
|
||||||
|
if monitorOnlyMode == True:
|
||||||
|
downloadMin = 10000
|
||||||
|
uploadMin = 10000
|
||||||
|
downloadMax = 10000
|
||||||
|
uploadMax = 10000
|
||||||
ipv4_subnets_and_hosts = []
|
ipv4_subnets_and_hosts = []
|
||||||
# Each entry in ShapedDevices.csv can have multiple IPv4s or IPv6s seperated by commas. Split them up and parse each
|
# Each entry in ShapedDevices.csv can have multiple IPv4s or IPv6s seperated by commas. Split them up and parse each
|
||||||
if ipv4_input != "":
|
if ipv4_input != "":
|
||||||
@ -294,6 +299,8 @@ def loadSubscriberCircuits(shapedDevicesFile):
|
|||||||
if circuit['ParentNode'] != ParentNode:
|
if circuit['ParentNode'] != ParentNode:
|
||||||
errorMessageString = "Device " + deviceName + " with deviceID " + deviceID + " had different Parent Node from other devices of circuit ID #" + circuitID
|
errorMessageString = "Device " + deviceName + " with deviceID " + deviceID + " had different Parent Node from other devices of circuit ID #" + circuitID
|
||||||
raise ValueError(errorMessageString)
|
raise ValueError(errorMessageString)
|
||||||
|
# Check if bandwidth parameters match other cdevices of this same circuit ID, but only check if monitorOnlyMode is Off
|
||||||
|
if monitorOnlyMode == False:
|
||||||
if ((circuit['minDownload'] != round(int(downloadMin)*tcpOverheadFactor))
|
if ((circuit['minDownload'] != round(int(downloadMin)*tcpOverheadFactor))
|
||||||
or (circuit['minUpload'] != round(int(uploadMin)*tcpOverheadFactor))
|
or (circuit['minUpload'] != round(int(uploadMin)*tcpOverheadFactor))
|
||||||
or (circuit['maxDownload'] != round(int(downloadMax)*tcpOverheadFactor))
|
or (circuit['maxDownload'] != round(int(downloadMax)*tcpOverheadFactor))
|
||||||
@ -388,6 +395,9 @@ def refreshShapers():
|
|||||||
# Warn user if enableActualShellCommands is False, because that would mean no actual commands are executing
|
# Warn user if enableActualShellCommands is False, because that would mean no actual commands are executing
|
||||||
if enableActualShellCommands == False:
|
if enableActualShellCommands == False:
|
||||||
warnings.warn("enableActualShellCommands is set to False. None of the commands below will actually be executed. Simulated run.", stacklevel=2)
|
warnings.warn("enableActualShellCommands is set to False. None of the commands below will actually be executed. Simulated run.", stacklevel=2)
|
||||||
|
# Warn user if monitorOnlyMode is True, because that would mean no actual shaping is happening
|
||||||
|
if monitorOnlyMode == True:
|
||||||
|
warnings.warn("monitorOnlyMode is set to True. Shaping will not occur.", stacklevel=2)
|
||||||
|
|
||||||
|
|
||||||
# Check if first run since boot
|
# Check if first run since boot
|
||||||
@ -431,6 +441,17 @@ def refreshShapers():
|
|||||||
# Pull rx/tx queues / CPU cores available
|
# Pull rx/tx queues / CPU cores available
|
||||||
queuesAvailable = findQueuesAvailable()
|
queuesAvailable = findQueuesAvailable()
|
||||||
|
|
||||||
|
|
||||||
|
# If in monitorOnlyMode, override network.json bandwidth rates to where no shaping will actually occur
|
||||||
|
if monitorOnlyMode == True:
|
||||||
|
def overrideNetworkBandwidths(data):
|
||||||
|
for elem in data:
|
||||||
|
if 'children' in data[elem]:
|
||||||
|
overrideNetworkBandwidths(data[elem]['children'])
|
||||||
|
data[elem]['downloadBandwidthMbpsMin'] = 10000
|
||||||
|
data[elem]['uploadBandwidthMbpsMin'] = 10000
|
||||||
|
overrideNetworkBandwidths(network)
|
||||||
|
|
||||||
# Generate Parent Nodes. Spread ShapedDevices.csv which lack defined ParentNode across these (balance across CPUs)
|
# Generate Parent Nodes. Spread ShapedDevices.csv which lack defined ParentNode across these (balance across CPUs)
|
||||||
print("Generating parent nodes")
|
print("Generating parent nodes")
|
||||||
existingPNs = 0
|
existingPNs = 0
|
||||||
@ -438,11 +459,18 @@ def refreshShapers():
|
|||||||
existingPNs += 1
|
existingPNs += 1
|
||||||
generatedPNs = []
|
generatedPNs = []
|
||||||
numberOfGeneratedPNs = queuesAvailable-existingPNs
|
numberOfGeneratedPNs = queuesAvailable-existingPNs
|
||||||
|
# If in monitorOnlyMode, override bandwidth rates to where no shaping will actually occur
|
||||||
|
if monitorOnlyMode == True:
|
||||||
|
chosenDownloadMbps = 10000
|
||||||
|
chosenUploadMbps = 10000
|
||||||
|
else:
|
||||||
|
chosenDownloadMbps = generatedPNDownloadMbps
|
||||||
|
chosenUploadMbps = generatedPNDownloadMbps
|
||||||
for x in range(numberOfGeneratedPNs):
|
for x in range(numberOfGeneratedPNs):
|
||||||
genPNname = "Generated_PN_" + str(x+1)
|
genPNname = "Generated_PN_" + str(x+1)
|
||||||
network[genPNname] = {
|
network[genPNname] = {
|
||||||
"downloadBandwidthMbps":generatedPNDownloadMbps,
|
"downloadBandwidthMbps": chosenDownloadMbps,
|
||||||
"uploadBandwidthMbps":generatedPNUploadMbps
|
"uploadBandwidthMbps": chosenUploadMbps
|
||||||
}
|
}
|
||||||
generatedPNs.append(genPNname)
|
generatedPNs.append(genPNname)
|
||||||
if useBinPackingToBalanceCPU:
|
if useBinPackingToBalanceCPU:
|
||||||
@ -507,6 +535,12 @@ def refreshShapers():
|
|||||||
if depth == 0:
|
if depth == 0:
|
||||||
parentClassID = hex(major) + ':'
|
parentClassID = hex(major) + ':'
|
||||||
data[node]['parentClassID'] = parentClassID
|
data[node]['parentClassID'] = parentClassID
|
||||||
|
# If in monitorOnlyMode, override bandwidth rates to where no shaping will actually occur
|
||||||
|
if monitorOnlyMode == True:
|
||||||
|
data[node]['downloadBandwidthMbps'] = 10000
|
||||||
|
data[node]['uploadBandwidthMbps'] = 10000
|
||||||
|
# If not in monitorOnlyMode
|
||||||
|
else:
|
||||||
# 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
|
||||||
data[node]['downloadBandwidthMbps'] = min(data[node]['downloadBandwidthMbps'],parentMaxDL)
|
data[node]['downloadBandwidthMbps'] = min(data[node]['downloadBandwidthMbps'],parentMaxDL)
|
||||||
data[node]['uploadBandwidthMbps'] = min(data[node]['uploadBandwidthMbps'],parentMaxUL)
|
data[node]['uploadBandwidthMbps'] = min(data[node]['uploadBandwidthMbps'],parentMaxUL)
|
||||||
@ -515,6 +549,7 @@ def refreshShapers():
|
|||||||
# Here we override the rate as 95% of ceil.
|
# Here we override the rate as 95% of ceil.
|
||||||
data[node]['downloadBandwidthMbpsMin'] = round(data[node]['downloadBandwidthMbps']*.95)
|
data[node]['downloadBandwidthMbpsMin'] = round(data[node]['downloadBandwidthMbps']*.95)
|
||||||
data[node]['uploadBandwidthMbpsMin'] = round(data[node]['uploadBandwidthMbps']*.95)
|
data[node]['uploadBandwidthMbpsMin'] = round(data[node]['uploadBandwidthMbps']*.95)
|
||||||
|
|
||||||
data[node]['classMajor'] = hex(major)
|
data[node]['classMajor'] = hex(major)
|
||||||
data[node]['classMinor'] = hex(minorByCPU[queue])
|
data[node]['classMinor'] = hex(minorByCPU[queue])
|
||||||
data[node]['cpuNum'] = hex(queue-1)
|
data[node]['cpuNum'] = hex(queue-1)
|
||||||
@ -529,6 +564,7 @@ def refreshShapers():
|
|||||||
for circuit in subscriberCircuits:
|
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 a device from ShapedDevices.csv lists this node as its Parent Node, attach it as a leaf to this node HTB
|
||||||
if node == circuit['ParentNode']:
|
if node == circuit['ParentNode']:
|
||||||
|
if monitorOnlyMode == False:
|
||||||
if circuit['maxDownload'] > data[node]['downloadBandwidthMbps']:
|
if circuit['maxDownload'] > data[node]['downloadBandwidthMbps']:
|
||||||
warnings.warn("downloadMax of Circuit ID [" + circuit['circuitID'] + "] exceeded that of its parent node. Reducing to that of its parent node now.", stacklevel=2)
|
warnings.warn("downloadMax of Circuit ID [" + circuit['circuitID'] + "] exceeded that of its parent node. Reducing to that of its parent node now.", stacklevel=2)
|
||||||
if circuit['maxUpload'] > data[node]['uploadBandwidthMbps']:
|
if circuit['maxUpload'] > data[node]['uploadBandwidthMbps']:
|
||||||
@ -642,10 +678,14 @@ def refreshShapers():
|
|||||||
comment = comment + '| Comment: ' + circuit['devices'][0]['comment']
|
comment = comment + '| Comment: ' + circuit['devices'][0]['comment']
|
||||||
command = 'class add dev ' + interfaceA + ' parent ' + data[node]['classid'] + ' classid ' + circuit['classMinor'] + ' htb rate '+ str(circuit['minDownload']) + 'mbit ceil '+ str(circuit['maxDownload']) + 'mbit prio 3'
|
command = 'class add dev ' + interfaceA + ' parent ' + data[node]['classid'] + ' classid ' + circuit['classMinor'] + ' htb rate '+ str(circuit['minDownload']) + 'mbit ceil '+ str(circuit['maxDownload']) + 'mbit prio 3'
|
||||||
linuxTCcommands.append(command)
|
linuxTCcommands.append(command)
|
||||||
|
# Only add CAKE / fq_codel qdisc if monitorOnlyMode is Off
|
||||||
|
if monitorOnlyMode == False:
|
||||||
command = 'qdisc add dev ' + interfaceA + ' parent ' + circuit['classMajor'] + ':' + circuit['classMinor'] + ' ' + fqOrCAKE
|
command = 'qdisc add dev ' + interfaceA + ' parent ' + circuit['classMajor'] + ':' + circuit['classMinor'] + ' ' + fqOrCAKE
|
||||||
linuxTCcommands.append(command)
|
linuxTCcommands.append(command)
|
||||||
command = 'class add dev ' + interfaceB + ' parent ' + data[node]['classid'] + ' classid ' + circuit['classMinor'] + ' htb rate '+ str(circuit['minUpload']) + 'mbit ceil '+ str(circuit['maxUpload']) + 'mbit prio 3'
|
command = 'class add dev ' + interfaceB + ' parent ' + data[node]['classid'] + ' classid ' + circuit['classMinor'] + ' htb rate '+ str(circuit['minUpload']) + 'mbit ceil '+ str(circuit['maxUpload']) + 'mbit prio 3'
|
||||||
linuxTCcommands.append(command)
|
linuxTCcommands.append(command)
|
||||||
|
# Only add CAKE / fq_codel qdisc if monitorOnlyMode is Off
|
||||||
|
if monitorOnlyMode == False:
|
||||||
command = 'qdisc add dev ' + interfaceB + ' parent ' + circuit['classMajor'] + ':' + circuit['classMinor'] + ' ' + fqOrCAKE
|
command = 'qdisc add dev ' + interfaceB + ' parent ' + circuit['classMajor'] + ':' + circuit['classMinor'] + ' ' + fqOrCAKE
|
||||||
linuxTCcommands.append(command)
|
linuxTCcommands.append(command)
|
||||||
for device in circuit['devices']:
|
for device in circuit['devices']:
|
||||||
@ -959,6 +999,8 @@ def refreshShapersUpdateOnly():
|
|||||||
command = 'tc class add dev ' + interface + ' parent ' + parentNodeClassID + ' classid ' + minor + ' htb rate ' + rate + 'Mbit ceil ' + ceil + 'Mbit'
|
command = 'tc class add dev ' + interface + ' parent ' + parentNodeClassID + ' classid ' + minor + ' htb rate ' + rate + 'Mbit ceil ' + ceil + 'Mbit'
|
||||||
print(command)
|
print(command)
|
||||||
shell(command)
|
shell(command)
|
||||||
|
# Only add CAKE / fq_codel qdisc if monitorOnlyMode is Off
|
||||||
|
if monitorOnlyMode == False:
|
||||||
command = 'tc qdisc add dev ' + interface + ' parent ' + classID + ' ' + fqOrCAKE
|
command = 'tc qdisc add dev ' + interface + ' parent ' + classID + ' ' + fqOrCAKE
|
||||||
print(command)
|
print(command)
|
||||||
shell(command)
|
shell(command)
|
||||||
|
Loading…
Reference in New Issue
Block a user