Маршрутизація multicast в linux

У сучасних реаліях, швидше за все, немає сенсу займатися маршрутизацією (реплікацією) multicast-трафіку за допомогою софтроутеров (будь то ядро ​​Linux або щось інше). Причина досить проста - навіть дешеві свитчи вміють L2 / L3-multicast (хоч і з обмеженнями за кількістю груп / маршрутів, але все ж це робиться в asic-ах). Однак, існує ряд завдань, які можуть бути не вирішені в "залозі" (немає підтримки з боку ПО / неможливо реалізувати через можливостей asic), наприклад ренамберінг (зміна destination ip), внесення випадкових затримок (перемішування), відправка multicast в тунель, резервування джерела за довільним критерієм.

Внести випадкову затримку (reordering) або втрати може знадобитися для перевірки поведінки використовуваних STB / soft-плеєрів. Наприклад, вам цікаво, як буде виглядати картинка, якщо десь на мережі мультикаст пройде через per-packet балансування і не зависне чи плеєр при наявності втрати пакетів, чи будуть видаватися неприємні скрипучі звуки або ж просто квадратики і тиша.

При написанні цієї замітки використовувався Ubuntu Linux 14.04 LTS (ядро 3.13.0-24-generic), але може бути застосовано для більшості сучасних дистрибутивів, проте необхідно перевірити підтримку IPv4 multicast в ядрі:

На відміну від unicast роутінга, утиліти ip недостатньо навіть для статичної (S, G) маршрутизації, не кажучи вже про динамічну. Для формування таблиці мультикаст-реплікації потрібні "сторонні" userspace-утиліти. Наприклад, для статичних маршрутів це smcroute, для побудови таблиці по igmp-запитам з даунлінков-інтерфейсів - igmpproxy (маршрут додається в ядро ​​тоді, коли "знизу" приходить igmp-запит), для роботи з PIM-SM сигналізацією - pimd (потрібна підтримка PIMSM_V2 з боку ядра).

Статична маршрутизація multicast

Розглянемо наступну задачу: здійснити реплікацію мультикаст-трафіку (*, 233.251.240.1) з інтерфейсу eth1 на інтерфейси eth2 і eth3, при цьому на eth1 ця група приходить тільки по igmpv2-замовлення.

Конфігурація інтерфейсів виглядати наступним чином:

Нажаль, smcroute в ubuntu 14.04 не підтримує (*, G) -форму, тому доведеться скомпілювати з вихідних:

Перш ніж запускати маршрутизацію (інсталювати маршрути в ядро), потрібно відключити RPF на інтерфейсі eth1 (оскільки за умовою задачі вважаємо, що source ip multicast-групи може бути довільним):

Крім того, встановлюємо явно режим роботи igmp на інтерфейсі eth1:

Тепер переходимо до конфігурації smcroute (/etc/smcroute.conf):

(Необхідний новий рядок в кінці конфігурації)
Перший рядок - підключити групу з протоколу igmp (залити цю інформацію в ядро), друга - власне мультикаст-маршрут.
Запускаємо smcroute:

(Логи пишуться в syslog)
Перевіряємо таблицю igmp:

Все вірно, 01F0FBE9 це наша група 233.251.240.1.

До того, як в eth1 поллється мультикаст, таблиця маршрутизації в ядрі буде виглядати таким чином:

Потім прийме такий вигляд:

Перевіряємо роботу реплікації:

Ренамберінг мультикаст груп

Для того, щоб змінити IP multicast групи використовуємо DNAT. Наприклад, ми хочемо змінити 233.251.240.1 на 233.251.250.5:

/etc/smcroute.conf буде виглядати наступним чином:

Далі, чистимо conntrack (командою "conntrack -F") і перевіряємо:

Як неважко здогадатися, щоб підмінити ще й source ip, будемо використовувати SNAT:

Знову чистимо conntrack ( "conntrack -F") і перевіряємо:

За допомогою iptables і tc можна ще що-небудь зробити з трафіком (внести затримки і втрати, наприклад). При бажанні, можна організувати резервування ТВ-каналу шляхом перемикання джерела мовлення за допомогою скриптів (smcroute-му можна управляти "ззовні"), придумавши довільні критерії вибору кращого джерела (подібні рішення для операторів існують і коштують великих грошей)

Схожі статті