
igor@0: \section{Программный мост в Linux}
igor@0: 
igor@0: \textbf{Бридж} (англ. \textit{bridge}, мост) — это способ соединения двух сегментов Ethernet на канальном уровне, т.е. без использования протоколов более высокого уровня, таких как IP. Пакеты передаются на основе Ethernet-адресов, а не IP-адресов (как в маршрутизаторе). Поскольку передача выполняется на канальном уровне (уровень 2 модели OSI), все протоколы более высокого уровня прозрачно проходят через мост.
igor@0: 
igor@0: Термины коммутатор, мост и бридж могут использоваться на данной странице как взаимознаменяемые.
igor@0: 
igor@0: Код bridge в Linux является частичной реализацией стандарта  \htmladdnormallinkfoot{ANSI/IEEE 802.1d}{http://standards.ieee.org/getieee802/}.
igor@0: Впервые бриджинг в Linux появился в 2.2, затем код был переписан
igor@0: Леннертом Буйтенхеком (Lennert Buytenhek).
igor@0: Код bridge интегрирован в ядра серий 2.4 и 2.6.
igor@0: 
igor@0: \subsection{Коммутация и фильтрация}
igor@0: Linux-мосты более мощные чем простые аппаратные мосты и коммутаторы,
igor@0: поскольку они могут ещё фильтровать и регулировать трафик.
igor@0: Комбинация коммутатора и брандмауэра выполняется с помощью
igor@0: родственного проекта
igor@0: ebtables.
igor@0: 
igor@0: \subsection{Состояние}
igor@0: Код обновляется как часть ядра Linux 2.4 и 2.6, доступного на kernel.org.
igor@0: 
igor@0: Возможные будущие усовершенствования:
igor@0: \begin{itemize}
igor@0: \item  Описать фильтрацию STP
igor@0: \item  Использовать Netlink interface для управление бриджами (прототип в 2.6.18)
igor@0: \item  Добавить поддержку в user space
igor@0: \item  Сделать поддержку RSTP и других расширений 802.1d STP
igor@0: \end{itemize}
igor@0: 
igor@0: \subsection{Скачивание}
igor@0: Поддержка бриджинга есть в текущих ядрах 2.4 и 2.6
igor@0: всех основных дистрибутивов Linux. Требуемый комплект утилит для администрирования 
igor@0: \textit{bridge-utils} есть практически во всех дистрибутивах.
igor@0: 
igor@0: Инсталляция утилит выполняется стандартным для дистрибутива способом.
igor@0: Например, в Debian GNU/Linux:
igor@0: \begin{verbatim}
igor@0:  # apt-get install bridge-utils
igor@0: \end{verbatim}
igor@0: 
igor@0: Исходный код последнего релиза утилит можно получить со \htmladdnormallinkfoot{этой}{http://sourceforge.net/project/showfiles.php?group\_id=26089} страницы.
igor@0: 
igor@0: Как вариант можно сделать свою самую последнюю сборку кода 
igor@0: с kernel.org
igor@0: и собрать утилиты bridge-utils из GIT-репозитория.
igor@0: 
igor@0: \begin{verbatim}
igor@0:  $ git clone git://git.kernel.org/pub/scm/linux/kernel/git/shemminger/bridge-utils.git
igor@0:  $ cd bridge-utils
igor@0:  $ autoconf
igor@0:  $ ./configure
igor@0: \end{verbatim}
igor@0: 
igor@0: \subsection{Ручная конфигурация}
igor@0: \subsubsection{Сетевые карты}
igor@0: Перед тем как вы приступите к настройке коммутатора, убедитесь, 
igor@0: что сетевые карты работают нормально.
igor@0: Не устанавливайте на них IP-адресов, и не позволяйте начальным скриптам
igor@0: выполнять DHCP-запрос с них.
igor@0: IP-адреса должны устанавливаться уже после того как бридж сконфигурирован.
igor@0: 
igor@0: Команда ifconfig должна показывать обе (или больше, если их больше) сетевые карты, и они должны быть выключены, т.е. находиться в состоянии DOWN
igor@0: (это на момент начала настройки, дальше они будут переведены в UP).
igor@0: 
igor@0: \subsubsection{Загрузка модуля}
igor@0: В большинстве случаев код коммутатора оформляется в виде модуля.
igor@0: Если модуль сконфигурирован и установлен корректно,
igor@0: он автоматически загружается при первом вызове команды \textbf{brctl}.
igor@0: 
igor@0: Если ваши утилиты bridge-utilities корректно установлены,
igor@0: и ядро и его модуль bridge в порядке, вызовом команды \textbf{brctl}
igor@0: можно будет просмотреть маленькую сводку о синтаксисе команды:
igor@0: \begin{verbatim}
igor@0: # brctl
igor@0: # commands:
igor@0:     addbr           <bridge>                add bridge
igor@0:     delbr           <bridge>                delete bridge
igor@0:     addif           <bridge> <device>       add interface to bridge
igor@0:     delif           <bridge> <device>       delete interface from bridge
igor@0:     setageing       <bridge> <time>         set ageing time
igor@0:     setbridgeprio   <bridge> <prio>         set bridge priority
igor@0:     setfd           <bridge> <time>         set bridge forward delay
igor@0:     sethello        <bridge> <time>         set hello time
igor@0:     setmaxage       <bridge> <time>         set max message age
igor@0:     setpathcost     <bridge> <port> <cost>  set path cost
igor@0:     setportprio     <bridge> <port> <prio>  set port priority
igor@0:     show                                    show a list of bridges
igor@0:     showmacs        <bridge>                show a list of mac addrs
igor@0:     showstp         <bridge>                show bridge stp info
igor@0:     stp             <bridge> <state>        turn stp on/off
igor@0: \end{verbatim}
igor@0: 
igor@0: \subsubsection{Создание и удаление коммутатора}
igor@0: Команда
igor@0: \begin{verbatim}
igor@0:  brctl addbr bridgename
igor@0: \end{verbatim}
igor@0: 
igor@0: создаёт экземпляр логического коммутатора с именем \textit{bridgename}.
igor@0: Для того чтобы выполнять коммутацию пакетов, нужно создать хотя бы один коммутатор .
igor@0: Можно воспринимать логический бридж как контейнер интерфейсов, 
igor@0: принимающих участие в коммутации.
igor@0: Каждый экземпляр коммутатора представлен новым сетевым интерфейсом.
igor@0: 
igor@0: Соответствующая команда для удаления коммутатора:
igor@0: \begin{verbatim}
igor@0:  brctl delbr bridgename
igor@0: \end{verbatim}
igor@0: 
igor@0: \subsubsection{Включение устройства в коммутатор}
igor@0: Команда
igor@0: \begin{verbatim}
igor@0:  brctl addif bridgename device
igor@0: \end{verbatim}
igor@0: \noindent включает сетевое устройство \textit{device}
igor@0: в коммутатор с именем \textit{bridgename}.
igor@0: Все устройства, включенные в один бридж работают как одна большая сеть.
igor@0: Нельзя добавить устройство в несколько бриджей одновременно, 
igor@0: поскольку это не имеет никакого смысла.
igor@0: Коммутатору потребуется небольшое время после того как устройство
igor@0: подключено, для того чтобы узнать его Ethernet-адрес, а затем
igor@0: он начинает делать перенаправление (forward).
igor@0: 
igor@0: Соответствующая команда для выключения устройства из коммутатора:
igor@0: \begin{verbatim}
igor@0:  brctl delif  bridgename device
igor@0: \end{verbatim}
igor@0: 
igor@0: \subsubsection{Просмотр устройств}
igor@0: Команда \textbf{brctl} \verb|show| показывает состояние всех работающих коммутаторов:
igor@0: \begin{verbatim}
igor@0:  # brctl addbr br549
igor@0:  # brctl addif br549 eth0
igor@0:  # brctl addif br549 eth1
igor@0:  # brctl show
igor@0:  bridge name     bridge id               STP enabled     interfaces
igor@0:  br549           8000.00004c9f0bd2       no              eth0
igor@0:                                                          eth1
igor@0: \end{verbatim}
igor@0: Если выполнить команду \textbf{brctl} \verb|showmacs|,
igor@0: будет показана информация о сетевых адресах 
igor@0: источников трафика, прошедшего через коммутатор
igor@0: (и самого коммутатора тоже):
igor@0: 
igor@0: \begin{verbatim}
igor@0:  # brctl showmacs br549
igor@0:  port no mac addr                is local?       ageing timer
igor@0:    1     00:00:4c:9f:0b:ae       no                17.84
igor@0:    1     00:00:4c:9f:0b:d2       yes                0.00
igor@0:    2     00:00:4c:9f:0b:d3       yes                0.00
igor@0:    1     00:02:55:1a:35:09       no                53.84
igor@0:    1     00:02:55:1a:82:87       no                11.53
igor@0:   ...
igor@0: \end{verbatim}
igor@0: 
igor@0: Время жизни (aging time) -- это количество секунд, которое
igor@0: MAC-адрес будет находится в таблице forwarding database
igor@0: после получения пакета с этим адресом.
igor@0: Записи в таблице периодически удаляются по тайм-ауту,
igor@0: для того чтобы не получилось, что они будут находиться там вечно.
igor@0: В нормальной ситуации, не понадобится менять данные параметры,
igor@0: но это сделать можно (время указывается в секундах)
igor@0: 
igor@0: \begin{verbatim}
igor@0:   # brctl setageing ''bridgename'' ''time''
igor@0: \end{verbatim}
igor@0: 
igor@0: Если установить время в ноль, запись становится постоянной.
igor@0: 
igor@0: \subsubsection{Spanning Tree Protocol}
igor@0: Если используется несколько коммутаторов, для того чтобы избежать петель коммутации, нужно включить поддержку протокола
igor@0: Spanning Tree Protocol (Протокол остовного дерева).
igor@0: 
igor@0: \begin{verbatim}
igor@0:  # brctl stp br549 on
igor@0: \end{verbatim}
igor@0: 
igor@0: Посмотреть параметры STP можно так:
igor@0: 
igor@0: \begin{verbatim}
igor@0:  # brctl showstp br549
igor@0:  br549
igor@0:   bridge id              8000.00004c9f0bd2
igor@0:   designated root        0000.000480295a00
igor@0:   root port                 1                    path cost                104
igor@0:   max age                  20.00                 bridge max age           200.00
igor@0:   hello time                2.00                 bridge hello time         20.00
igor@0:   forward delay           150.00                 bridge forward delay      15.00
igor@0:   ageing time             300.00                 gc interval                0.00
igor@0:   hello timer               0.00                 tcn timer                  0.00
igor@0:   topology change timer     0.00                 gc timer                   0.33
igor@0:   flags
igor@0:  
igor@0:  eth0 (1)
igor@0:   port id                8001                    state                   forwarding
igor@0:   designated root        0000.000480295a00       path cost                100
igor@0:   designated bridge      001e.00048026b901       message age timer         17.84
igor@0:   designated port        80c1                    forward delay timer        0.00
igor@0:   designated cost           4                    hold timer                 0.00
igor@0:   flags
igor@0:  
igor@0:  eth1 (2)
igor@0:   port id                8002                    state                   disabled
igor@0:   designated root        8000.00004c9f0bd2       path cost                100
igor@0:   designated bridge      8000.00004c9f0bd2       message age timer          0.00
igor@0:   designated port        8002                    forward delay timer        0.00
igor@0:   designated cost           0                    hold timer                 0.00
igor@0:   flags
igor@0: \end{verbatim}
igor@0: 
igor@0: \paragraph{Настройка STP}
igor@0: Конфигурироваться может несколько параметров, имеющих  отношение к Spanning Tree Protocol.
igor@0: Код автоматически определяет скорость соединения и другие параметры, 
igor@0: поэтому, как правило, вручную их менять не нужно.
igor@0: 
igor@0: \paragraph{Приоритет коммутатора}
igor@0: У каждого коммутатора есть относительный приоритет (priority) и стоимость (cost).
igor@0: Каждый интерфейс коммутатора ассоциируется с номером порта в коде STP. У каждого есть приоритет и стоимость, на основе которых принимается решение о том, какой путь для передчи пакета является кратчайшим. Всегда используется путь с наимеьшей стоимостью (за исключением случая, когда этот путь разорван).
igor@0: Если у вас несколько коммутаторов и интерфейсов,
igor@0: может понадобиться отрегулировать приоритеты, чтобы достичь максимальной
igor@0: производительности.
igor@0: 
igor@0: \begin{verbatim}
igor@0:   # brctl setbridgeprio ''bridgename'' ''priority''
igor@0: \end{verbatim}
igor@0: 
igor@0: Бридж с наименьшим приоритетом избирается как \textit{корневой}. 
igor@0: Корневой бридж является центром остовного дерева (spanning tree) 
igor@0: коммутационных связей.
igor@0: 
igor@0: \paragraph{Приоритет и стоимость}
igor@0: У каждого интерфейса моста может быть своя собственная скорость, и её значение
igor@0: используется при выборе какое соединение должно использоваться.
igor@0: У более быстрых интерфейсов должна быть более низкая стоимость.
igor@0: 
igor@0: \begin{verbatim}
igor@0:  # brctl ''setpathcost bridge port cost''
igor@0: \end{verbatim}
igor@0: 
igor@0: Для разных портов, имеющих одинаковую стоимость
igor@0: существует ещё \textit{приоритет}.
igor@0: 
igor@0: \paragraph{Задержка передачи (Forwarding delay)}
igor@0: Задержка передачи (forwarding delay) это время
igor@0: в течение которого порт находится в состояниях
igor@0: Listening и Learning, прежде чем перейти в состояние Forwarding.
igor@0: Это время нужно для того чтобы мост, когда он включается в
igor@0: сеть, сначала должен ознакомиться с трафиком, прежде чем включаться
igor@0: в работу.
igor@0: 
igor@0: \begin{verbatim}
igor@0:  #  brctl setfd ''bridgename'' ''time''
igor@0: \end{verbatim}
igor@0: 
igor@0: \paragraph{Время Hello}
igor@0: Время от времени 
igor@0: корневой мост (Root Bridge)
igor@0: и выделенные мосты (Designated Bridges)
igor@0: отправляют пакет \textit{hello}. 
igor@0: Пакеты hello нужны для обмена информацией
igor@0: о топологии все коммутироемой локальной сети.
igor@0: 
igor@0: \begin{verbatim}
igor@0:  # brctl sethello ''bridgename'' ''time''
igor@0: \end{verbatim}
igor@0: 
igor@0: \paragraph{max age -- таймаут hello}
igor@0: Если другой коммутатор в дереве spanning tree не отправляет пакет hello 
igor@0: в течение долгого времени, считается, что он не в порядке (dead).
igor@0: Таймаут устанавливается командой:
igor@0: \begin{verbatim}
igor@0:  # brctl maxage  ''bridgename'' ''time''
igor@0: \end{verbatim}
igor@0: 
igor@0: \subsubsection{Пример настройки}
igor@0: Базовая настройка моста выполняется так:
igor@0: 
igor@0: \begin{verbatim}
igor@0:  # ifconfig eth0 0.0.0.0
igor@0:  # ifconfig eth1 0.0.0.0
igor@0:  # brctl addbr mybridge
igor@0:  # brctl addif mybridge eth0
igor@0:  # brctl addif mybridge eth1 
igor@0:  # ifconfig mybridge up
igor@0: \end{verbatim}
igor@0: 
igor@0: Хост настраивается как обычный мост.
igor@0: У него самого нет IP-адреса, поэтому к нему 
igor@0: нельзя получить доступ (или взломать) удалённо
igor@0: по TCP/IP.
igor@0: 
igor@0: Опционально можно настроить виртуальный интерфейс \textit{mybridge}
igor@0: на доступ по локальной сети.
igor@0: Он будет работать как обычный интерфейс -- как сетевая карта.
igor@0: Процесс настройки полностью совпадает с вышеописанным, 
igor@0: за тем исключением, что нужно заменить 
igor@0: последнюю команду на такую:
igor@0: 
igor@0: \begin{verbatim}
igor@0:  # ifconfig mybridge 192.168.100.5 netmask 255.255.255.0
igor@0: \end{verbatim}
igor@0: 
igor@0: Если вы хотите чтобы мост автоматически получал IP-адрес
igor@0: у ADSL-модема по DHCP (или в другой похожей ситуации),
igor@0: сделайте так:
igor@0: 
igor@0: \begin{verbatim}
igor@0:  # ifconfig eth0 0.0.0.0
igor@0:  # ifconfig eth1 0.0.0.0
igor@0:  # brctl addbr mybridge
igor@0:  # brctl addif mybridge eth0
igor@0:  # brctl addif mybridge eth1 
igor@0:  # dhclient mybridge
igor@0: \end{verbatim}
igor@0: 
igor@0: Если делать это много раз, процессов \textbf{dhclient} может расплодиться великое множество. Или безжалостно убейте их, или почитайте об \textbf{omshell}.
igor@0: 
igor@0: \subsection{Конфигурирование через /etc/net}
igor@0: Сначала в \texttt{/etc/net} настраиваются два ethernet-устройства port0 и port1:
igor@0: \begin{verbatim}
igor@0:  # cat >> /etc/net/iftab
igor@0:  port0 mac 00:13:46:66:01:5e
igor@0:  port1 mac 00:13:46:66:01:5f
igor@0:  ^D
igor@0:  # mkdir /etc/net/ifaces/port0
igor@0:  # cat > /etc/net/ifaces/port0/options
igor@0:  TYPE=eth
igor@0:  MODULE=via-rhine
igor@0:  # mkdir /etc/net/ifaces/port1
igor@0:  # cat > /etc/net/ifaces/port1/options
igor@0:  TYPE=eth
igor@0:  MODULE=via-rhine
igor@0:  ^D
igor@0: \end{verbatim}
igor@0: После этого описывается мост:
igor@0: \begin{verbatim}
igor@0:  # mkdir /etc/net/ifaces/mybridge
igor@0:  # cat > /etc/net/ifaces/mybridge/options
igor@0:  TYPE=bri
igor@0:  HOST='port0 port1'
igor@0:  ^D
igor@0:  # cat > /etc/net/ifaces/mybridge/brctl
igor@0:  stp AUTO on
igor@0:  ^D
igor@0: \end{verbatim}
igor@0: После этого можно поднять бридж командой \textbf{ifup} \texttt{mybridge}. Устройства port0 и port1 поднимутся автоматически.
igor@0: 
igor@0: \subsection{FAQ}
igor@0: \subsubsection{Что делает мост/коммутатор?}
igor@0: Мост прозрачно пересылает трафик между несколькими сетевыми интерфейсами.
igor@0: На простом языке это означает, что коммутатор соединяет два или более интерфейсов Ethernet между собой, для того чтобы получилась большая Ethernet-сеть.
igor@0: 
igor@0: \subsubsection{Это как-то зависит от используемых протоколов?}
igor@0: Нет. Коммутатор ничего не знает о протоколах высокого уровня, он только видит кадры Ethernet. Поэтому функциональность моста является протоколонезависимой и проблем с передачей протоколов таких как IPX, NetBEUI, IP, IPv6 и других быть не должно.
igor@0: 
igor@0: \subsubsection{Чем этот код лучше чем аппаратный коммутатор?}
igor@0: Пожалуйста, имейте в виду, что этот код не писался
igor@0: с целью заменить Linux-боксами выделенное сетевое оборудование.
igor@0: Не надо воспринимать Linux с этим кодом как замену аппаратным коммутаторам.
igor@0: Это скорее расширение сетевых возможностей Linux. Как бывает, что Linux-маршрутизатор лучше чем аппаратный маршрутизатор (и наоборот),
igor@0: есть ситуации, когда Linux-мост лучше чем выделенный мост (и наоборот).
igor@0: 
igor@0: Основная сила кода моста Linux это его гибкость.
igor@0: И так есть уже огромнейшее количество всяких интересных 
igor@0: вещей, которые можно делать с Linux (см. например, Linux Advanced Routing and Traffic Control), и мосты -- ещё одно добавление к этой гремучей смеси.
igor@0: 
igor@0: Одним из главных преимуществ решения, базирующегося на Linux,
igor@0: в сравнении с выделенным коммутатором
igor@0: являются разнообразные возможности по фильтрации трафика.
igor@0: Можно использовать всю функциональность netfilter (iptables) в комбинации 
igor@0: с мостами, что даёт больший функционал, чем проприетарные решения.
igor@0: 
igor@0: \subsubsection{Чем этот код хуже чем аппаратный коммутатор?}
igor@0: Для того чтобы работать в качестве моста, 
igor@0: устройство должно быть переведено в неразборчивый (promiscuous)
igor@0: режим, в котором оно получает весь трафик, приходящий на интерфейс.
igor@0: В действительно загруженных сетях, это может занять значительную часть
igor@0: процессора, замедляя работу системы.
igor@0: Выход -- или использовать выделенную Linux-систему в качестве моста
igor@0: или использовать аппаратный коммутатор.
igor@0: 
igor@0: \subsubsection{Какова производительность моста?}
igor@0: Производительность ограничивается используеммыми сетевыми картами и процессором.
igor@0: Джеймс Ю (James Yu) из университета DePaul провёл исследование, 
igor@0: в котором выполнил сравнение Linux моста и коммутатора Catalyst
igor@0: Yu-Linux-TSM2004.pdf
igor@0: 
igor@0: \subsubsection{Моего моста не видно в трассе traceroute\rq{}а!}
igor@0: И не должно быть видно.
igor@0: Работа моста является полностью прозрачной для сети (по крайней мере должна);
igor@0: сети, которые мост соединяет между собой должны видеться как одна большая сеть.
igor@0: Именно поэтому мост и не виден в traceroute; пакеты и не думают о том, что они пересекают границы подсети.
igor@0: 
igor@0: Дополнительная информация об этом в книгах по сетям TCP/IP.
igor@0: 
igor@0: \subsubsection{Ничего не работает!}
igor@0: Когда я пытаюсь добавить мост, система говорит: \dq{}br\_add\_bridge: bad address\dq{}!
igor@0: 
igor@0: Или ваше ядро слишком старое (2.2 или более ранее), или вы забыли включить поддержку бриджей в ядро.
igor@0: 
igor@0: \subsubsection{Работает ли бриджинг на ядре 2.2?}
igor@0: Изначально разработка велась на 2.2, есть патчи для этого ядра.
igor@0: Но сейчас эти патчи уже не поддерживаются и не развиваются.
igor@0: 
igor@0: \subsubsection{Есть ли в планах поддержка RSTP (802.1w)?}
igor@0: Да. Ведётся работа по включению поддержки RSTP в будущий релиз для ядра 2.6. Код делался для ядра 2.4 и нуждается в доработке, тестировании и обновлении.
igor@0: 
igor@0: \subsubsection{Что можно соединять с помощью моста?}
igor@0: Мосты Linux очень гибкие; можно соединять
igor@0: как традиционные ethernet-устройства, так и псевдоустройства такие
igor@0: как PPP, VPN или VLAN\rq{}ы.
igor@0: 
igor@0: Ограничения, которые накладываются на соединяемые устройства:
igor@0: \begin{itemize}
igor@0: \item  У всех должен быть одинаковый максимальный размер пакета (MTU). Мост не выполняет фрагментирование пакетов.
igor@0: \item  Устройства должны выглядеть как Ethernet, т.е. у них должны быть 6-байтные адреса отправителя и получателя.
igor@0: \item  Должен поддерживаться неразборчивый (promiscuous) режим. Мост должен получать не только трафик, адресованный ему, но и весь сетевой трафик.
igor@0: \item  Должен быть разрешён спуфинг адресов. У моста должна быть возможность отправлять данные по сети, как если бы они пришли от другого хоста.
igor@0: \end{itemize}
igor@0: 
igor@0: \subsubsection{Можно ли выполнять коммутацию в сочетании с netfilter/iptables?}
igor@0: Да. Соответствующий код включен в большинство ядер. Смотрите проект ebtables.
igor@0: 
igor@0: \subsubsection{Работает ли он с Token Ring, FDDI и Firewire?}
igor@0: Нет. У этих протоколов отличается адресация и размер кадра.
igor@0: 
igor@0: \subsubsection{Я продолжаю получать сообщение \dq{}retransmitting tcn bpdu\dq{}!}
igor@0: Это означает, что ваш Linux-мост ретранслирует сообщение
igor@0: Topology Change Notification Bridge Protocol Data Unit
igor@0: Это означает что где-то есть коммутатор (или другой Linux-мост),
igor@0: который не согласен с правилами STP.
igor@0: 
igor@0: В каждой коммутируемой сети есть один \dq{}главный коммутатор\dq{},
igor@0: который также называется \textit{корневым} (root).
igor@0: Какой именно мост является корневым можно узнать с помощью \textbf{brctl}.
igor@0: 
igor@0: Когда топология коммутируемой сети меняется (например, кто-то выдернул
igor@0: кабель между коммутаторами), коммутатор, который это обнаружил, 
igor@0: отправляет сообщение корневому коммутатору.
igor@0: Корневой коммутатор устанавливает бит \rq{}topology changed\rq{}
igor@0: в пакеты hello, которые будут отправляеться в течение следующих X секунд 
igor@0: (обычно X равно 30). В результате все мосты узнают об изменении топологии,
igor@0: и они могут работать с учётом этого -- например удалить устаревшие MAC-записи.
igor@0: 
igor@0: После того как коммутатор отправляет сообщение об изменении топологии, 
igor@0: он ждёт что в hello-сообщении будет установлени бит \rq{}\dq{}topology changed\dq{}.
igor@0: Если его нет (бит в данном случае играет роль подтверждения получения информации
igor@0: о смене топологии), коммутатор решает, что сообщение было потеряно.
igor@0: Поэтому пересылает сообщение повторно.
igor@0: Однако, в некоторых коммутаторах реализациия
igor@0: STP немного недоделанная, и они не отправляют подтверждение 
igor@0: получения сообщения об изменении топологии.
igor@0: Если один из таких коммутаторов у вас корневой, 
igor@0: все остальные коммутаторы будут постоянно повторно пересылать
igor@0: информацию об изменении топологии.
igor@0: В результате чего и будут появляеться такие сообщения.
igor@0: 
igor@0: Список вещей, которые можно сделать:
igor@0: \begin{itemize}
igor@0: \item  Найти какой коммутатор является корневым, где он находится и под управлением какого программного обеспечения работает. Пожалуйста, сообщите о таком коммутаторе в список рассылки, чтобы можно было его добавить в blacklist.
igor@0: \item  Заставить Linux-мост быть корневым. Найдите какой приоритет у коммутатора, который сейчас является корневым, и с помощью команды \textbf{brctl} \verb|setbridgeprio| установите приоритет линуксового моста на 1 меньше (Мост с наименьшим приоритеом всегда становится корневым).
igor@0: \item  Вообще отключите STP на Linux-мосте. Только смотрите чтобы не появилось петель коммутации! Если у вас есть петли, и не работает STP, пакеты зациклятся и будут гулять по сети вечно, что сделает её нерабочей.
igor@0: \end{itemize}
igor@0: 
igor@0: \subsubsection{Оно не работает с моей обычной ethernet-карточкой!}
igor@0: К сожалению, у некоторых сетевых карт глючные драйверы,
igor@0: которые сбоят во время загрузки.
igor@0: Ситуация улучшается, поэтому может помочь установка текущего ядра и сетевых драйверов. Ещё можно попробовать устройства другого производителя.
igor@0: 
igor@0: Пожалуйста, сообщайте обо всех проблемах
igor@0: в список рассылки \dq{}Bridge mailing list\dq{}: bridge@osdl.org.
igor@0: Если ваша сетевая карта не работает даже без бриджинга,
igor@0: попробуйте обратиться в список рассылки  
igor@0: \dq{}Linux networking mailing list\dq{} linux-net@vger.kernel.org.
igor@0: 
igor@0: \subsubsection{Оно не работает с моей wireless-карточкой!}
igor@0: Это известная проблема, и она не связана с кодом моста.
igor@0: Большое количество wireless-карт не позволяет делать подмену (spoofing) 
igor@0: адреса источника. В некоторых чипсетах это ограничение на уровне прошивки (firmware).
igor@0: Дополнительная информация может быть найдена в архивах списков рассылки.
igor@0: 
igor@0: Удалось ли кому-нибудь обойти проблему связанную с тем, 
igor@0: что Wavelan не позволяет использовать никакие MAC-адреса за исключением
igor@0: своего собственного?
igor@0: 
igor@0: \textit{(Отвечает Michael Renzmann, mrenzmann at compulan.de)}
igor@0: 
igor@0: 99\% пользователей никогда не смогут избавиться от этой проблемы.
igor@0: Для такой функции нужна специальная прошивка. Её нужно загрузить
igor@0: в память WaveLAN-карточки и тогда карточка сможет выполнять бриджинг.
igor@0: Но нет общедоступной документации интерфейса.
igor@0: Единственный выход -- иметь полную версию библиотеки hcf,
igor@0: которая контролирует все действия карты, и в частности, 
igor@0: доступ к памяти карты.
igor@0: Для получения этой библиотеки нужно убедить компанию Lucent, 
igor@0: что это ей будет выгодно и помимо этого подписать NDA.
igor@0: Поэтому, скорее всего, пока Lucent не передумает, 
igor@0: вам не удастся получить доступ к коду (а в том, что Lucent передумает
igor@0: есть большие сомнения).
igor@0: 
igor@0: Если вам срочно нужна wireless-карта которая может работать в мосте,
igor@0: нужно использовать те, что построены на базе чипсета \textit{prism}
igor@0: (изготавливает Harris Intersil).
igor@0: Драйверы для этой карты есть на www.linux-wlan.com
igor@0: (веб-сайт от Absoval), и в одном из сообщений говорится, 
igor@0: что общедоступна необходимая прошивка и программа для загрузки для Linux.
igor@0: Если вам нужны какие-то дополнительные возможности, нужно разговаривать
igor@0: с Absoval.
igor@0: 
igor@0: \subsubsection{И всё же я не понимаю!!}
igor@0: Полноценный мост для беспроводных сетей (802.11) требует поддержки WDS.
igor@0: В текущей реализации её нет.
igor@0: 
igor@0: Можно сделать ограниченную функциональность с некоторыми драйверами.
igor@0: Для этого обязательно чтобы устройство поддерживало 
igor@0: разные адреса отправителя и получателя. Что и обеспечивает WDS.
igor@0: 
igor@0: Есть способы добиться чтобы оно заработало, но они достаточно запутанные,
igor@0: и их сложно понять без досконального знания 802.11, режимов его работы и формата загловка кадра.
igor@0: 
igor@0: \subsubsection{Я получаю ошибку \rq{}too much work in interrupt\rq{}}
igor@0: Это связано с тем, что сетевая карта теряет пакеты.
igor@0: Можно попробовать несколько вещей. Во-первых, собрать 
igor@0: драйвер с поддержкой NAPI (если он по умолчанию, не включен).
igor@0: NAPI делает так чтобы получал управление по программному прерыванию, 
igor@0: не по прерыванию низкого уровня.
igor@0: 
igor@0: Если драйвер не поддерживает NAPI, можно попробовать 
igor@0: увеличить объём работы, который драйвер может делать 
igor@0: в течение обработки прерывания.
igor@0: Для 3c59x это делается с помощью опции \verb|max_interrupt_work| (поэтому нужно добавить опцию \verb|options 3c59x max_interrupt_work=10000| в файл \texttt{/etc/modules.conf}).
igor@0: У других сетевых карт похожие опции.
igor@0: 
igor@0: \subsubsection{Работает ли DHCP через/поверх моста?}
igor@0: Мост передаёт DHCP-трафик (широковещательный) и ответы на него. 
igor@0: Также можно использовать DHCP для установки локального IP-адреса на псевдо-интерфейс моста.
igor@0: 
igor@0: Одна из распространённых ошибок при использовании DHCP является установка задержки передачи (forwarding delay) на порту коммутатора равной 30 секунд.
igor@0: При такой задержке интерфейс когда он подключился к мосту не может посылать
igor@0: через него данные в течении первых 30 секунд. Причина в том, что при использовании моста в сложной топологии он должен сначала обнаружить остальные мосты дабы не создавать петель. Проблема была одной из причин создания протокола  
igor@0: Rapid Spanning Tree Protocol (RSTP).
igor@0: 
igor@0: Если мост используется в одиночку (т.е. поблизости нет мостов)
igor@0: можно спокойно отключить задержку передачи (установить её равной 0)
igor@0: перед тем как подключать интерфейс к мосту.
igor@0: После этого сразу же можно вызывать dhclient:
igor@0: 
igor@0: \begin{verbatim}
igor@0:  # brctl setfd br0 0
igor@0:  # brctl addif br0 eth0
igor@0:  # dhclient eth0
igor@0: \end{verbatim}
igor@0: 
igor@0: \subsection{Дополнительная информация}
igor@0: \begin{itemize}
igor@0: \item \htmladdnormallinkfoot{Linux Bridge}{http://xgu.ru/wiki/Linux\_Bridge} (рус.)
igor@0: \item \htmladdnormallinkfoot{Ethernet VPN bridging}{http://openvpn.sourceforge.net/bridge.html}
igor@0: \item \htmladdnormallinkfoot{Ebtables firewalling}{http://ebtables.sourceforge.net}
igor@0: \item \htmladdnormallinkfoot{Ethernet-bridge + netfilter HOWTO}{http://www.tldp.org/HOWTO/Ethernet-Bridge-netfilter-HOWTO.html}
igor@0: \item \htmladdnormallinkfoot{Linux-bridge STP HOWTO}{http://www.tldp.org/HOWTO/BRIDGE-STP-HOWTO/index.html}
igor@0: \item \htmladdnormallinkfoot{Spanning Tree Protocol}{http://en.wikipedia.org/wiki/Spanning\_tree\_protocol} на Wikipedia
igor@0: \end{itemize}
igor@0: 




