Fair Bandwidth Sharing for simple queues

Z Wiki UnArt Slavičín
Skočit na navigaciSkočit na vyhledávání
  • Úkolem tohoto skriptu je pomoc správci s nastavení QoS na jeho APčku.
  • Tento skript ale neřeší vše - pouze dělá tu nejhorší práci - tj nastavuje pravidla pro jednotlivé členy tak, aby všichni měli stejnou garantovanou rychlost.
  • Jediné, co je potřeba ve skriptu změnit, než ho nasadíte na své APčko, je proměnná usersParent - místo "Ostatni" tam napište jméno přímé rodičovské fronty (třídy), pod kterou máte všechny členy.
  • Než skript spustíte, nastavte si správně hodnoty limit-at a max-limit u všech rodičovských front (tříd). Nastavení rodičovksých front (tříd) musí splňovat následující pravidla:
  1. Základní věc: na AP musí existovat jediná kořenová fronta, která je rodičem všech ostatních. U ní musí být max-limit=limit-at=90% maximální propustnosti spoje do zbytku sítě. Maximální propustnost spoje je různá pro různé stroje, musíte si ji změřit experimentálně (např.: připojte se na ethernet toho AP a zkuste stáhnout něco z FTP, které je co nejblíž místu, kde končí druhá strana spoje). Bacha! Pokud je vaše AP připojeno na nějaké jiné AP, jehož správce vám "skřípne" konektivitu, pak vám QoS také přestane fungovat (packety se nebudou řadit do front a spravedlivě zahazovat na vašem APčku, ale na tom, která vás omezuje, tam ale už "nespravedlivě"). Propustnost ovlivňuje i výkon CPU - jestliž máte RB532, tak tento stroj asi neudělá 10M upload+10M download - je tam hodně slabé CPU. Realisticky odhaduji tak 12M up+down (záleží to na počtu pravidel ve frontách a ve firewallu). Teďka je otázka co s tím - Simple Queues totiž neumí udělat up+down. Tohle je ten rozdíl od Queue Trees - QueueTrees mají JENOM JEDEN údaj společný pro up+down, Simple Queues mají up a down rozděleno. Moje návrhy:
    1. možnost: místo 10M upload+10download dát např. 3M upload a 9M download (hodnoty je potřeba ověřit experimentálně - pokud dáte víc, nebude QoS fungovat vůbec). Nevýhoda - zbytečně omezujeme upload i donwload
    2. možnost: předělat všechny AP, které jsou WiFi (ethernetových routerů se to netýká, ethernet je plně duplexní tj. tam zas jedině Simple Queues), na Queue Trees, aby měly up+down dohromady. Nevýhoda: Kromě záznamů v Queue Trees se bude muset vytvářet záznam i ve firewallu (mangle) - víc práce pro správce, navíc to asi dost podstatně zvětší zátěž CPU - možná ale ne, chtělo by to vyzkoušet (na živém AP vyzkoušet nelze!).
  2. Pokud má APčko více karet/antén, pak pro každou kartu musíte mít frontu, jejíž rodičem bude rodičovská fronta z bodu 1.
  3. Součet hodnot limit-at všech "dětí" musí být roven hodnotě limit-at rodičovské fronty. Abyste to splnili, muselo by limit-at u front všech členů být vypočítáno jako limit-at rodičovské fronty/počet členských front. A při připojení každého člověka byste museli proklikat všechny ostatní členy a limit-at upravit. Jinak řečeno, tohle je nereálně dělat ručně, a k tomu právě slouží následující skript:
  1. Script name: "Fair Bandwidth Sharing" for simple queues
#Author: Tomas Dulik
#Date: Feb 2008
#Description: This script distributes the value of limit-at of a parent queue equally among all its children 
########## Tuto promennou nastav - misto "Ostatni" napis jmeno primo nadrazene (parent) fronty vsech uzivatelu!
:local usersParent "APStaraSkola"
### nasledujici 2 promenne definuji hodnotu "max-limit", ktera se nastavi vsem uzivatelum
## Pokud je promenna $userDownloadMaxLimit nebo $userUploadLimit = 0, pouzijeme hodnotu max-limit rodicovske fronty 
## (hodnoty muzes ale zadat (v bits/sekundu) tak jak na nasledujicich radcich: 
:local userDownloadMaxLimit 4000000
:local userUploadMaxLimit 1000000
:local burstLimit 2000000/5000000
:local burstThreshold 900000/2500000
:local burstTime 20s/20s
########## Tady zacina skript - pokud tomu nerozumis, radsi do ne nerypej
:local usersParentMaxLimit [/queue simple get $usersParent max-limit]
:local slashPosition [:find $usersParentMaxLimit /]
## Pokud neni nastavena promenna $userDownloadMaxLimit, nastavime ji na max-limit rodicovske fronty
:if ($userDownloadMaxLimit=0) do={
  :log info "max-limit for users' download was not set, using the max-limit of their parent queue..."
##z usersParentMaxLimit musime pomoci ":pick" vysekat max-limit pro download
  :set userDownloadMaxLimit [:pick $usersParentMaxLimit ($slashPosition+1) [:len $usersParentMaxLimit]]
}
## Pokud neni nastavena promenna $userUploadMaxLimit, nastavime ji na max-limit rodicovske fronty
:if ($userUploadMaxLimit=0) do={
  :log info "max-limit for users' upload was not set, using the max-limit of their parent queue..."
  :set userUploadMaxLimit [:pick $usersParentMaxLimit 0 $slashPosition]
}
##usersParentLimitAt bude retezec napr. 1000000/4000000 (tj. upload/download)
:local usersParentLimitAt [/queue simple get $usersParent limit-at]
##z usersParentLimitAt musime vysekat limit-at pro upload:
:set slashPosition [:find $usersParentLimitAt /]
:local usersParentUploadLimitAt [:pick $usersParentLimitAt 0 $slashPosition]
##a take limit-at pro download:
:local usersParentDownloadLimitAt [:pick $usersParentLimitAt ($slashPosition+1) [:len $usersParentLimitAt]]
#### A ted uz zbyva nastavit spravne limit-at a max-limit pro vsechny uzivatele:
### Sestavime si seznam front vsech uzivatelu  (maji parent-a zadaneho prvnim radkem tohoto skriptu]
:local usersQueues [/queue simple find parent=$usersParent]
## spocitame, kolik tech uzivatelu mame:
:local usersCount [:len $usersQueues]
##a vypocitame, jak velky ma byt limit-at pro jednotlive uzivatele:
:local userDownloadLimitAt ($usersParentDownloadLimitAt/$usersCount)
:local userUploadLimitAt ($usersParentUploadLimitAt/$usersCount)
#a tady uz to vsem uzivatelum nastavime:
:foreach queue in=$usersQueues do={
  /queue simple set $queue limit-at ($userUploadLimitAt . "/" . $userDownloadLimitAt) \
  max-limit ($userUploadMaxLimit . "/" . $userDownloadMaxLimit) \
  burst-limit $burstLimit burst-threshold $burstThreshold burst-time $burstTime \
  direction both
}
  1. Autor: Michal Kliment
  2. Datum: unor 2011
  3. Popis: Skript nastavuje vsem polozkam patriciho do zadaneho parentu zadane hodnoty
  1. jmeno parentu, ktery budeme nastavovat
global usersParent "Sidliste MIR"
  1. jmeno interfacu, ktery se nastavi vsem polozkam z parentu
global usersInterface "all"
  1. hodnota burst-limit, ktera se nastavi vsem polozkam z parentu
global usersBurstLimit 0/0
  1. hodnota burst-threshold, ktera se nastavi vsem polozkam z parentu
global usersBurstThreshold 0/0
  1. hodnota burst-time, ktera se nastavi vsem polozkam z parentu
global usersBurstTime 0/0
  1. hodnota max-limit, ktera se nastavi vsem polozkam z parentu
global usersMaxLimit 10M/10M
  1. hodnoty max-limit a limit-at, ktera se nastavi "ostatnim" = posledni polozce z parentu
global othersMaxLimit 256k/512k
global othersLimitAt 64k/128k
  1. pomocna promenna pro ulozeni id polozky "ostatni"
global lastId

/queue simple

  1. zjistime limit-at parentu
global usersParentLimitAt [get $usersParent limit-at]
  1. najdeme pozici lomitka
global slashPosition [:find $usersParentLimitAt /]
  1. zjistime hodnoty download a upload limit-at
global usersParentLimitAtDownload [:pick $usersParentLimitAt ($slashPosition+1) [:len $usersParentLimitAt]]
global usersParentLimitAtUpload [:pick $usersParentLimitAt 0 $slashPosition]
  1. je nutne pretypovat download a upload limit-at parentu na cislo (je to retezec)
  1. posledni znak je M (je zadan v megabytech, napr. 100M
if ([:pick $usersParentLimitAtDownload ([:len $usersParentLimitAtDownload]-1)]="M") do={
  1. prevedeme ho tedy na byty (cast pred znakem M vynasobime 1048576)

:set usersParentLimitAtDownload ([:pick $usersParentLimitAtDownload 0 ([:len $usersParentLimitAtDownload]-1)]*1048576) } else={

  1. posledni znak je k (je zadan v kilobytech, napr. 100k)

:if ([:pick $usersParentLimitAtDownload ([:len $usersParentLimitAtDownload]-1)]="k") do={

  1. prevedeme ho tedy na byty (cast pred znakem k vynasobime 1024)

:set usersParentLimitAtDownload ([:pick $usersParentLimitAtDownload 0 ([:len $usersParentLimitAtDownload]-1)]*1024) } else={

  1. posledni znak neni M ani k, retezec obsahuje pouze cisla => jenom pretypujeme na typ cislo

:set usersParentLimitAtDownload [:tonum $usersParentLimitAtDownload] } }

  1. posledni znak je M (je zadan v megabytech, napr. 100M
if ([:pick $usersParentLimitAtUpload ([:len $usersParentLimitAtUpload]-1)]="M") do={
  1. prevedeme ho tedy na byty (cast pred znakem M vynasobime 1048576)

:set usersParentLimitAtUpload ([:pick $usersParentLimitAtUpload 0 ([:len $usersParentLimitAtUpload]-1)]*1048576) } else={

  1. posledni znak je k (je zadan v kilobytech, napr. 100k)

:if ([:pick $usersParentLimitAtUpload ([:len $usersParentLimitAtUpload]-1)]="k") do={

  1. prevedeme ho tedy na byty (cast pred znakem k vynasobime 1024)

:set usersParentLimitAtUpload ([:pick $usersParentLimitAtUpload 0 ([:len $usersParentLimitAtUpload]-1)]*1024) } else={

  1. posledni znak neni M ani k, retezec obsahuje pouze cisla => jenom pretypujeme na typ cislo

:set usersParentLimitAtUpload [:tonum $usersParentLimitAtUpload] } }

  1. zjistime pocet vsech polozek v parentu
global usersCount [:len [find parent=$usersParent]]
  1. uz jenom vypocitame limit-at pro kazdou polozku = vydelime limit-at parentu poctem polozek
global usersLimitAtDownload ($usersParentLimitAtDownload/$usersCount)
global usersLimitAtUpload ($usersParentLimitAtUpload/$usersCount)
  1. kazde polozce nastavime hodnoty
foreach i in=[find parent=$usersParent] do={

set $i interface=$usersInterface set $i burst-limit=$usersBurstLimit set $i burst-threshold=$usersBurstThreshold set $i burst-time=$usersBurstTime set $i max-limit=$usersMaxLimit set $i limit-at ($usersLimitAtUpload . "/" . $usersLimitAtDownload) :set lastId $i }

  1. nakonec uz jenom nastavime max-limit a limit-at pro polozku "ostatni"

set $lastId max-limit=$othersMaxLimit set $lastId limit-at=$othersLimitAt