Delete old/v1.0 directory

This commit is contained in:
Robert Chacón
2023-03-22 15:45:21 -06:00
committed by GitHub
parent 2bf244e0d8
commit 39bbcd739c
9 changed files with 0 additions and 500 deletions

View File

@@ -1,9 +0,0 @@
AP,Max Download,Max Upload,Parent Site
AP1,250,60,Site1
AP2,250,60,Site2
AP3,250,60,Site3
AP4,250,60,Site4
AP5,250,60,Site1
AP6,250,60,Site2
AP7,250,60,Site3
AP8,250,60,Site4
1 AP Max Download Max Upload Parent Site
2 AP1 250 60 Site1
3 AP2 250 60 Site2
4 AP3 250 60 Site3
5 AP4 250 60 Site4
6 AP5 250 60 Site1
7 AP6 250 60 Site2
8 AP7 250 60 Site3
9 AP8 250 60 Site4

View File

@@ -1,83 +0,0 @@
import requests
import csv
from ispConfig.py import UISPbaseURL, uispAuthToken, shapeRouterOrStation
stationModels = ['LBE-5AC-Gen2', 'LBE-5AC-Gen2', 'LBE-5AC-LR', 'AF-LTU5', 'AFLTULR', 'AFLTUPro', 'LTU-LITE']
routerModels = ['ACB-AC', 'ACB-ISP']
def pullShapedDevices():
devices = []
uispSitesToImport = []
url = UISPbaseURL + "/nms/api/v2.1/sites?type=client&ucrm=true&ucrmDetails=true"
headers = {'accept':'application/json', 'x-auth-token': uispAuthToken}
r = requests.get(url, headers=headers)
jsonData = r.json()
uispDevicesToImport = []
for uispClientSite in jsonData:
if (uispClientSite['identification']['status'] == 'active'):
if (uispClientSite['qos']['downloadSpeed']) and (uispClientSite['qos']['uploadSpeed']):
downloadSpeedMbps = int(round(uispClientSite['qos']['downloadSpeed']/1000000))
uploadSpeedMbps = int(round(uispClientSite['qos']['uploadSpeed']/1000000))
address = uispClientSite['description']['address']
uispClientSiteID = uispClientSite['id']
devicesInUISPsite = getUISPdevicesAtClientSite(uispClientSiteID)
UCRMclientID = uispClientSite['ucrm']['client']['id']
AP = 'none'
thisSiteDevices = []
#Look for station devices, use those to find AP name
for device in devicesInUISPsite:
deviceName = device['identification']['name']
deviceRole = device['identification']['role']
deviceModel = device['identification']['model']
deviceModelName = device['identification']['modelName']
if (deviceRole == 'station') or (deviceModel in stationModels):
if device['attributes']['apDevice']:
AP = device['attributes']['apDevice']['name']
if shapeRouterOrStation == 'router':
#Look for router devices, use those as shaped CPE
for device in devicesInUISPsite:
deviceName = device['identification']['name']
deviceRole = device['identification']['role']
deviceMAC = device['identification']['mac']
deviceIPstring = device['ipAddress']
if '/' in deviceIPstring:
deviceIPstring = deviceIPstring.split("/")[0]
deviceModel = device['identification']['model']
deviceModelName = device['identification']['modelName']
if (deviceRole == 'router') or (deviceModel in routerModels):
print("Added " + ":\t" + deviceName)
devices.append((UCRMclientID, AP,deviceMAC, deviceName, deviceIPstring,'', str(downloadSpeedMbps/4), str(uploadSpeedMbps/4), str(downloadSpeedMbps),str(uploadSpeedMbps)))
elif shapeRouterOrStation == 'station':
#Look for station devices, use those as shaped CPE
for device in devicesInUISPsite:
deviceName = device['identification']['name']
deviceRole = device['identification']['role']
deviceMAC = device['identification']['mac']
deviceIPstring = device['ipAddress']
if '/' in deviceIPstring:
deviceIPstring = deviceIPstring.split("/")[0]
deviceModel = device['identification']['model']
deviceModelName = device['identification']['modelName']
if (deviceRole == 'station') or (deviceModel in stationModels):
print("Added " + ":\t" + deviceName)
devices.append((UCRMclientID, AP,deviceMAC, deviceName, deviceIPstring,'', str(downloadSpeedMbps/4), str(uploadSpeedMbps/4), str(downloadSpeedMbps),str(uploadSpeedMbps)))
uispSitesToImport.append(thisSiteDevices)
print("Imported " + address)
else:
print("Failed to import devices from " + uispClientSite['description']['address'] + ". Missing QoS.")
return devices
def getUISPdevicesAtClientSite(siteID):
url = UISPbaseURL + "/nms/api/v2.1/devices?siteId=" + siteID
headers = {'accept':'application/json', 'x-auth-token': uispAuthToken}
r = requests.get(url, headers=headers)
return (r.json())
if __name__ == '__main__':
devicesList = pullShapedDevices()
with open('Shaper.csv', 'w') as csvfile:
wr = csv.writer(csvfile, quoting=csv.QUOTE_ALL)
wr.writerow(['ID', 'AP', 'MAC', 'Hostname', 'IPv4', 'IPv6', 'Download Min', 'Upload Min', 'Download Max', 'Upload Max'])
for device in devicesList:
wr.writerow(device)

View File

@@ -1,327 +0,0 @@
# Copyright (C) 2020-2021 Robert Chacón
# This file is part of LibreQoS.
#
# LibreQoS is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 2 of the License, or
# (at your option) any later version.
#
# LibreQoS is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with LibreQoS. If not, see <http://www.gnu.org/licenses/>.
#
# _ _ _ ___ ____
# | | (_) |__ _ __ ___ / _ \ ___/ ___|
# | | | | '_ \| '__/ _ \ | | |/ _ \___ \
# | |___| | |_) | | | __/ |_| | (_) |__) |
# |_____|_|_.__/|_| \___|\__\_\\___/____/
# v.1.0-stable
#
import random
import logging
import os
import io
import json
import csv
import subprocess
from subprocess import PIPE
import ipaddress
from ipaddress import IPv4Address, IPv6Address
import time
from datetime import date, datetime
from ispConfig import fqOrCAKE, upstreamBandwidthCapacityDownloadMbps, upstreamBandwidthCapacityUploadMbps, defaultClassCapacityDownloadMbps, defaultClassCapacityUploadMbps, interfaceA, interfaceB, shapeBySite, enableActualShellCommands, runShellCommandsAsSudo
import collections
def shell(command):
if enableActualShellCommands:
if runShellCommandsAsSudo:
command = 'sudo ' + command
commands = command.split(' ')
print(command)
proc = subprocess.Popen(commands, stdout=subprocess.PIPE)
for line in io.TextIOWrapper(proc.stdout, encoding="utf-8"): # or another encoding
print(line)
else:
print(command)
def clearPriorSettings(interfaceA, interfaceB):
shell('tc filter delete dev ' + interfaceA)
shell('tc filter delete dev ' + interfaceA + ' root')
shell('tc qdisc delete dev ' + interfaceA + ' root')
shell('tc qdisc delete dev ' + interfaceA)
shell('tc filter delete dev ' + interfaceB)
shell('tc filter delete dev ' + interfaceB + ' root')
shell('tc qdisc delete dev ' + interfaceB + ' root')
shell('tc qdisc delete dev ' + interfaceB)
if runShellCommandsAsSudo:
clearMemoryCache()
def refreshShapers():
tcpOverheadFactor = 1.09
accessPointDownloadMbps = {}
accessPointUploadMbps = {}
# Load Devices
devices = []
with open('Shaper.csv') as csv_file:
csv_reader = csv.reader(csv_file, delimiter=',')
next(csv_reader)
for row in csv_reader:
deviceID, AP, mac, hostname,ipv4, ipv6, downloadMin, uploadMin, downloadMax, uploadMax = row
ipv4 = ipv4.strip()
ipv6 = ipv6.strip()
if AP == "":
AP = "none"
AP = AP.strip()
thisDevice = {
"id": deviceID,
"mac": mac,
"AP": AP,
"hostname": hostname,
"ipv4": ipv4,
"ipv6": ipv6,
"downloadMin": round(int(downloadMin)*tcpOverheadFactor),
"uploadMin": round(int(uploadMin)*tcpOverheadFactor),
"downloadMax": round(int(downloadMax)*tcpOverheadFactor),
"uploadMax": round(int(uploadMax)*tcpOverheadFactor),
"qdisc": '',
}
devices.append(thisDevice)
# Load Access Points
accessPoints = []
accessPointNamesOnly = []
with open('AccessPoints.csv') as csv_file:
csv_reader = csv.reader(csv_file, delimiter=',')
next(csv_reader)
for row in csv_reader:
APname, apDownload, apUpload, parentSite = row
accessPointDownloadMbps[AP] = int(apDownload)*tcpOverheadFactor
accessPointUploadMbps[AP] = int(apUpload)*tcpOverheadFactor
accessPointNamesOnly.append(APname)
apDownload = round(int(apDownload)*tcpOverheadFactor)
apUpload = round(int(apUpload)*tcpOverheadFactor)
devicesForThisAP = []
for device in devices:
if APname == device['AP']:
devicesForThisAP.append(device)
accessPoints.append((APname, apDownload, apUpload, parentSite, devicesForThisAP))
# Sort devices into bins by AP, for scenario shapeBySite = False
result = collections.defaultdict(list)
for d in devices:
result[d['AP']].append(d)
devicesByAP = list(result.values())
# 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
# If an AP is specified for a device in Shaper.csv, but AP is not listed in AccessPoints.csv, raise exception
for device in devices:
if (device['AP'] not in accessPointNamesOnly):
print(device['AP'])
raise ValueError('AP for device ' + device['hostname'] + ' not listed in AccessPoints.csv')
# Load Sites
sites = []
with open('Sites.csv') as csv_file:
csv_reader = csv.reader(csv_file, delimiter=',')
next(csv_reader)
for row in csv_reader:
siteName, download, upload = row
siteDownloadMbps = int(download)
siteUploadMbps = int(upload)
apsForThisSite = []
for AP in accessPoints:
APname, apDownload, apUpload, parentSite, devicesForThisAP = AP
if parentSite == siteName:
apsForThisSite.append((APname, apDownload, apUpload, parentSite, devicesForThisAP))
sites.append((siteName, siteDownloadMbps, siteUploadMbps, apsForThisSite))
#Clear Prior Settings
clearPriorSettings(interfaceA, interfaceB)
# XDP-CPUMAP-TC
shell('./xdp-cpumap-tc/bin/xps_setup.sh -d ' + interfaceA + ' --default --disable')
shell('./xdp-cpumap-tc/bin/xps_setup.sh -d ' + interfaceB + ' --default --disable')
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)
# 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):
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 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
# Only 1/4 of defaultClassCapacity is guarenteed (to prevent hitting ceiling of upstream), for the most part it serves as an "up to" ceiling.
# Default class can use up to defaultClassCapacityDownloadMbps when that bandwidth isn't used by known hosts.
shell('tc class add dev ' + thisInterface + ' parent ' + str(queue+1) + ':1 classid ' + str(queue+1) + ':2 htb rate ' + str(defaultClassCapacityDownloadMbps/4) + '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 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.
# Only 1/4 of defaultClassCapacity is guarenteed (to prevent hitting ceiling of upstream), for the most part it serves as an "up to" ceiling.
# Default class can use up to defaultClassCapacityUploadMbps when that bandwidth isn't used by known hosts.
shell('tc class add dev ' + thisInterface + ' parent ' + str(queue+1) + ':1 classid ' + str(queue+1) + ':2 htb rate ' + str(defaultClassCapacityUploadMbps/4) + 'mbit ceil ' + str(defaultClassCapacityUploadMbps) + 'mbit prio 5')
shell('tc qdisc add dev ' + thisInterface + ' parent ' + str(queue+1) + ':2 ' + fqOrCAKE)
print()
#If shapeBySite == True, Shape by Site, AP and Client
if shapeBySite:
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+1] = 3
for site in sites:
siteName, siteDownloadMbps, siteUploadMbps, apsForThisSite = site
print("Adding site " + siteName)
major = currentQueueCounter
minor = queueMinorCounterDict[currentQueueCounter]
thisSiteclassID = str(currentQueueCounter) + ':' + str(minor)
# HTB + qdisc for each Site
# Guarentee Site gets at least 1/4 of its capacity, allow up to its max capacity when network not at peak load
shell('tc class add dev ' + interfaceA + ' parent ' + str(major) + ':1 classid ' + str(minor) + ' htb rate '+ str(round(siteDownloadMbps/4)) + 'mbit ceil '+ str(round(siteDownloadMbps)) + 'mbit prio 3')
shell('tc qdisc add dev ' + interfaceA + ' parent ' + str(major) + ':' + str(minor) + ' ' + fqOrCAKE)
shell('tc class add dev ' + interfaceB + ' parent ' + str(major) + ':1 classid ' + str(minor) + ' htb rate '+ str(round(siteUploadMbps/4)) + 'mbit ceil '+ str(round(siteUploadMbps)) + 'mbit prio 3')
shell('tc qdisc add dev ' + interfaceB + ' parent ' + str(major) + ':' + str(minor) + ' ' + fqOrCAKE)
minor += 1
print()
for AP in apsForThisSite:
APname, apDownload, apUpload, parentSite, devicesForThisAP = AP
print("Adding AP " + APname)
# HTB + qdisc for each AP
# Guarentee AP gets at least 1/4 of its capacity, allow up to its max capacity when network not at peak load
shell('tc class add dev ' + interfaceA + ' parent ' + thisSiteclassID + ' classid ' + str(minor) + ' htb rate '+ str(round(apDownload/4)) + 'mbit ceil '+ str(round(apDownload)) + 'mbit prio 3')
shell('tc qdisc add dev ' + interfaceA + ' parent ' + str(major) + ':' + str(minor) + ' ' + fqOrCAKE)
shell('tc class add dev ' + interfaceB + ' parent ' + thisSiteclassID + ' classid ' + str(minor) + ' htb rate '+ str(round(apUpload/4)) + 'mbit ceil '+ str(round(apUpload)) + 'mbit prio 3')
shell('tc qdisc add dev ' + interfaceB + ' parent ' + str(major) + ':' + str(minor) + ' ' + fqOrCAKE)
thisAPclassID = str(currentQueueCounter) + ':' + str(minor)
minor += 1
print()
for device in devicesForThisAP:
print("Adding device " + device['hostname'])
#HTB + qdisc for each device
shell('tc class add dev ' + interfaceA + ' parent ' + thisAPclassID + ' 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 ' + thisAPclassID + ' 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)
if '/' in device['ipv4']:
hosts = list(ipaddress.ip_network(device['ipv4']).hosts())
for host in hosts:
shell('./xdp-cpumap-tc/src/xdp_iphash_to_cpu_cmdline --add --ip ' + str(host) + ' --cpu ' + str(currentQueueCounter-1) + ' --classid ' + flowIDstring)
else:
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
queueMinorCounterDict[currentQueueCounter] = minor
currentQueueCounter += 1
if currentQueueCounter > queuesAvailable:
currentQueueCounter = 1
#If shapeBySite == False, shape by AP and Client only, not by Site
else:
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+1] = 3
for AP in devicesByAP:
currentAPname = AP[0]['AP']
thisAPdownload = accessPointDownloadMbps[currentAPname]
thisAPupload = accessPointUploadMbps[currentAPname]
major = currentQueueCounter
minor = queueMinorCounterDict[currentQueueCounter]
thisAPclassID = str(currentQueueCounter) + ':' + str(minor)
# HTB + qdisc for each AP
# 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(major) + ':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(major) + ':' + 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:
#HTB + qdisc for each device
shell('tc class add dev ' + interfaceA + ' parent ' + thisAPclassID + ' 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 ' + thisAPclassID + ' 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)
if '/' in device['ipv4']:
hosts = list(ipaddress.ip_network(device['ipv4']).hosts())
for host in hosts:
shell('./xdp-cpumap-tc/src/xdp_iphash_to_cpu_cmdline --add --ip ' + str(host) + ' --cpu ' + str(currentQueueCounter-1) + ' --classid ' + flowIDstring)
else:
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
queueMinorCounterDict[currentQueueCounter] = minor
currentQueueCounter += 1
if currentQueueCounter > queuesAvailable:
currentQueueCounter = 1
# Save devices to file to allow for statistics runs
with open('devices.json', 'w') as outfile:
json.dump(devices, outfile)
# Done
currentTimeString = datetime.now().strftime("%d/%m/%Y %H:%M:%S")
print("Successful run completed on " + currentTimeString)
if __name__ == '__main__':
refreshShapers()
print("Program complete")

View File

@@ -1,22 +0,0 @@
# v1.0 (IPv4) (Stable)
Released: 11 Dec 2021
## Installation Guide
- 📄 [LibreQoS v1.0 Installation & Usage Guide Physical Server and Ubuntu 21.10](https://github.com/rchac/LibreQoS/wiki/LibreQoS-v1.0-Installation-&-Usage-Guide---Physical-Server-and-Ubuntu-21.10)
## Features
Can now shape by Site, in addition to by AP and by Client
## Considerations
If you shape by Site, each site is tied to a queue and CPU core. Sites are evenly distributed across CPUs. Since each CPU can usually only accommodate up to 4Gbps, ensure any single Site will not require more than 4Gbps throughput.
If you shape by Acess Point, each Access Point is tied to a queue and CPU core. Access Points are evenly distributed across CPUs. Since each CPU can usually only accommodate up to 4Gbps, ensure any single Access Point will not require more than 4Gbps throughput.
## Limitations
As with 0.9, not yet dual stack, clients can only be shaped by IPv4 address until IPv6 support is added to XDP-CPUMAP-TC. Once that happens we can then shape IPv6 as well.
XDP's cpumap-redirect achieves higher throughput on a server with direct access to the NIC (XDP offloading possible) vs as a VM with bridges (generic XDP).

View File

@@ -1,6 +0,0 @@
ID,AP,MAC,Hostname,IPv4,IPv6,Download Min,Upload Min,Download Max,Upload Max
3001,AP1,32:3B:FE:B0:92:C1,CPE-Customer1,100.126.0.77,2001:495:1f0f:58a::4/64,25,8,115,18
3002,AP2,AE:EC:D3:70:DD:36,CPE-Customer2,100.126.0.78,2001:495:1f0f:58a::8/64,25,8,115,18
3003,AP3,1C:1E:60:69:88:9A,CPE-Customer3,100.126.0.79,2001:495:1f0f:58a::12/64,25,8,115,18
3004,AP4,11:B1:63:C4:DA:4C,CPE-Customer4,100.126.0.80,2001:495:1f0f:58a::16/64,25,8,115,18
3005,AP5,46:2F:B5:C2:0B:15,CPE-Customer5,100.126.0.81,2001:495:1f0f:58a::20/64,25,8,115,18
1 ID AP MAC Hostname IPv4 IPv6 Download Min Upload Min Download Max Upload Max
2 3001 AP1 32:3B:FE:B0:92:C1 CPE-Customer1 100.126.0.77 2001:495:1f0f:58a::4/64 25 8 115 18
3 3002 AP2 AE:EC:D3:70:DD:36 CPE-Customer2 100.126.0.78 2001:495:1f0f:58a::8/64 25 8 115 18
4 3003 AP3 1C:1E:60:69:88:9A CPE-Customer3 100.126.0.79 2001:495:1f0f:58a::12/64 25 8 115 18
5 3004 AP4 11:B1:63:C4:DA:4C CPE-Customer4 100.126.0.80 2001:495:1f0f:58a::16/64 25 8 115 18
6 3005 AP5 46:2F:B5:C2:0B:15 CPE-Customer5 100.126.0.81 2001:495:1f0f:58a::20/64 25 8 115 18

View File

@@ -1,5 +0,0 @@
Site,Max Download,Max Upload
Site1,920,920
Site2,920,920
Site3,200,30
Site4,100,15
1 Site Max Download Max Upload
2 Site1 920 920
3 Site2 920 920
4 Site3 200 30
5 Site4 100 15

View File

@@ -1,36 +0,0 @@
#'fq_codel' or 'cake diffserv4'
#'cake diffserv4' is recommended
#fqOrCAKE = 'fq_codel'
fqOrCAKE = 'cake diffserv4'
# How many Mbps are available to the edge of this network
upstreamBandwidthCapacityDownloadMbps = 1000
upstreamBandwidthCapacityUploadMbps = 1000
# Traffic from devices not specified in Shaper.csv will be rate limited by an HTB of this many Mbps
defaultClassCapacityDownloadMbps = 500
defaultClassCapacityUploadMbps = 500
# Interface connected to core router
interfaceA = 'eth1'
# Interface connected to edge router
interfaceB = 'eth2'
# Shape by Site in addition to by AP and Client
shapeBySite = True
# Allow shell commands. False causes commands print to console only without being executed. MUST BE ENABLED FOR PROGRAM TO FUNCTION
enableActualShellCommands = True
# Add 'sudo' before execution of any shell commands. May be required depending on distribution and environment.
runShellCommandsAsSudo = False
# Optional UISP integration
# Everything before /nms/ on your UISP instance
UISPbaseURL = 'https://examplesite.com'
# UISP Auth Token
uispAuthToken = ''
# UISP | Whether to shape router at customer premises, or instead shape the station radio. When station radio is in router mode, use 'station'. Otherwise, use 'router'.
shapeRouterOrStation = 'router'

View File

@@ -1,11 +0,0 @@
import time
import schedule
from datetime import date
from LibreQoS import refreshShapers
if __name__ == '__main__':
refreshShapers()
schedule.every().day.at("04:00").do(refreshShapers)
while True:
schedule.run_pending()
time.sleep(60) # wait one minute