Введение
При отладке правил шейпинга столкнулся с необычным поведением самого скрипта htb.init. Часть правил с параметрами TIME, где время переходит через полночь, не отрабатывались при наступлении указанного времени.
Для примера возьмем описание правила для одного из классов — eth0-2:6:19.unlim:
TIME=08:00-19:00;2Kbit,50Mbit
TIME=19:00-08:00;2Kbit,70Mbit
RATE=2Kbit
CEIL=50Mbit
LEAF=sfq
PRIO=2
MARK=0x19
При наступлении 19 часов скорость для класса не переключалась с 50 на 70 мегабит, хотя подобные правила других классов отрабатывали.
Поиск
Так как у меня уже имеется опыт настройки шейпера, его такое поведение вызвало у меня бурю негодования. Начался процесс перечитывания документации и мануалов в поиске деталей, которых я, возможно, не учел или просто забыл. Ничего нового не обнаружив, решил покопаться в коде самого скрипта. Так как синтаксис правил был верен, сделал вывод, что нужно рассмотреть блок, где происходит обработка параметра TIME. Обработка этого параметра происходит при вызове скрипта с аргументом timecheck — выполняется изменение скорости передачи определенного класса в зависимости от периода времени. Все операции производятся в блоке switch в ветке timecheck.
Если более детально описать работу ветки: получение списка файлов с правилами для различных классов шейпинга из /etc/sysconfig/htb (путь по умолчанию). Затем в цикле просматриваем каждый файл по одному в поисках параметров TIME. Если параметр есть и текущее время попадает в указанные границы, то скорость для класса меняется. Все кажется вполне нормальным, но…
Катарсис
Заметил, что непонятное происходит, если промежуток времени проходит через полночь (как в приведенном мною выше примере): происходит модификация переменной TIME_ABS, содержащей значение текущего времени. Это было бы нормально, если эта переменная была только внутри цикла. Тогда ее изменения не повлияют на обработку правил других классов. А изменения этой переменной происходили в случае обработки правил, имеющих переход через полночь. Но она объявлена была вне цикла, поэтому аккумулировала значения предыдущих итераций. Вот здесь и была зарыта собака — часть правил с переходом через полночь отрабатывались, а часть — нет. «Текущее» время постепенно «убегало» и уже не попадало ни в какие границы, определенные параметрами TIME в правилах.
Вот та часть скрипта:
timecheck)
TIME_TMP=`date +%w/%k:%M`
TIME_DOW=${TIME_TMP%%/*}
TIME_NOW=${TIME_TMP##*/}
#TIME_ABS=`htb_time2abs $TIME_NOW`
### Check all classes (if configured)
for classfile in `htb_class_list`; do
TIME_ABS=`htb_time2abs $TIME_NOW`
........
htb_message "$TIME_NOW: change on $DEVICE:$CLASS ($RATE_NOW/$CEIL_NOW -> $NEW_RATE/$NEW_CEIL)"
done ### class file
;;
Как это исправить
Необходимо перенести объявление переменной TIME_ABS в цикл и закомментировать её вне цикла (как указано в коде выше). После внесения изменений скрипт будет отрабатывать множественные переходы через полночь как положено. Вариант без исправлений скрипта — всегда писать параметры TIME во всех классах таким образом, чтобы не было перехода через полночь.
P.S.
В Интернетах искал информацию о подобной проблеме, но ничего не нашел. Удивительно, что никто не сталкивался с этой проблемой, несмотря на широкое использование этого скрипта для шейпинга. Хотя, может, я плохо искал…
Автор: alexander_pnz