OpenStack Neutron Floating Ip
TL;DR
Краткий список команд
Как трафик попадает из внешнего мира на VM в OpenStack
Этот документ описывает как трафик из внешнего мира доходит до виртуальных машин в OpenStack (один из возможных вариантов реализации).
Описание окружения
Окружение с установленным OpenStack состоит из 3 Control Nodes и они же совмещают роль Network Node, и одной Compute Node (минимально-возможное количество)
Для получения трафика из-вне используется интерфейс с именем floating
(имя может быть выбрано произвольно)
Исследование пути трафика
В окружении (для простоты) запущен один единственный инстанс, у которого Floating IP 10.72.10.124
os server list
+--------------------------------------+--------------------------+--------+----------------------------------------+------------+--------------------+ | ID | Name | Status | Networks | Image | Flavor | +--------------------------------------+--------------------------+--------+----------------------------------------+------------+--------------------+ | 795dc7f8-15b4-4b5d-9f8d-c40f178467f7 | test-cirros-vm-on-nvme-1 | ACTIVE | lb-mgmt-net=10.255.4.184, 10.72.10.124 | Cirros-5.1 | m1.nano.vm-on-nvme | +--------------------------------------+--------------------------+--------+----------------------------------------+------------+--------------------+
Сеть для floating Ips (10.72.10.0/24) настроена на маршрутизаторе в Vlan 729, и этот Vlan приходит в интерфейс с именем floating
на каждой из Controller/Network nodes
Шлюзом для Floating сети выступает внешний по отношению к OpenStack маршрутизатор.
С тестового ноутбука до виртуальной машины маршрут выглядит так:
Keys: Help Display mode Restart statistics Order of fields quit Packets Pings Host Loss% Snt Last Avg Best Wrst StDev 1. 192.168.33.1 0.0% 6 2.0 1.7 1.5 2.0 0.2 2. 10.72.10.124 0.0% 5 2.2 2.1 1.7 2.4 0.3
Определени через какую Network (Control/Network) ноду пойдет трафик
Из маршрута можно сделать следующие выводы:
- так как 192.168.33.1 -это адрес шлюза по-умолчанию для ноутбука с которого делается трассировка маршрута, а адрес VM
10.72.10.124
уже следующий в трассировке, то можно предположить что этот маршрутизатор и выступает шлюзом для floating сеть 10.72.10.0/24 - Если это утверждение верно, то изучив таблицу arp-записей на маршрутизаторе, возможно узнать мак-адрес VM (точнее, мак-адрес с которого уходит трафик от этой VM, этот адрес будет отличаться от того который можно посмотреть командой
ip link show
на самой VM.
В реальной жизни в окружении клиента доступа на роутеры и коммутаторы может не быть и тогда единственный способ понять через какую Compute/Network ноду идет трафик - это использовать tcpdump
Просмотр таблицы arp
на маршрутизаторе
В качестве маршрутизатора в этом (тестовом!) окружении выступает устройство Mikrotik RB4011iGS+5HacQ2HnD (RouterOS 7.4)
(это не типичная инсталляция, для других случаев маршрутизатор скорее всего окажется другого производителя)
Просматриваем таблицу arp-записей (с поиском по ip=10.72.10.124)
[admin@RB4011iGS+5HacQ2HnD] > /ip/arp/print where address=10.72.10.124
Flags: D, P - PUBLISHED; C - COMPLETE Columns: ADDRESS, MAC-ADDRESS, INTERFACE # ADDRESS MAC-ADDRESS INTERFACE 0 DC 10.72.10.124 FA:16:3E:40:32:D5 bridge-mosk-vlan-729-ch-os-fl
Из этого вывода можно видеть что
- мак-адрес хоста <cod>10.72.10.124 известен роутеру:
FA:16:3E:40:32:D5
- этот адрес изучен на физическом интерфейсе
bridge-mosk-vlan-729-ch-os-fl
- этот интерфейс (
bridge-mosk-vlan-729-ch-os-fl
) и является шлюзом для floating сети, на нем назначен первый адрес 10.72.10.1/24 из этого ( 10.72.10.0/24) диапазона
/ip/address/print where interface=bridge-mosk-vlan-729-ch-os-fl
Columns: ADDRESS, NETWORK, INTERFACE # ADDRESS NETWORK INTERFACE 0 10.72.10.1/24 10.72.10.0 bridge-mosk-vlan-729-ch-os-fl
- Проверить какие еще адреса имеют мак такой же как и у адреса с которого отвечает VM:
[admin@RB4011iGS+5HacQ2HnD] > /ip/arp/print where mac-address=FA:16:3E:40:32:D5
Flags: D, P - PUBLISHED; C - COMPLETE Columns: ADDRESS, MAC-ADDRESS, INTERFACE # ADDRESS MAC-ADDRESS INTERFACE 0 DC 10.72.10.124 FA:16:3E:40:32:D5 bridge-mosk-vlan-729-ch-os-fl 1 DC 10.72.10.27 FA:16:3E:40:32:D5 bridge-mosk-vlan-729-ch-os-fl
Тут видно что есть еще один IP с таким же маком - можно предположить что это или еще одна виртуальная машина, которая выходит через тот же роутер, или собственно адрес самого роутера.
В нашем простейшем случае, очевидно что это не может быть адресом виртуальной машины, так как в клауде запущена всего одна виртуальная машина с адресом 10.72.10.124
Просмотреть роутеры можно командой openstack router list
+--------------------------------------+------+--------+-------+----------------------------------+-------------+-------+ | ID | Name | Status | State | Project | Distributed | HA | +--------------------------------------+------+--------+-------+----------------------------------+-------------+-------+ | 54550846-33f2-4954-8649-3233a49cedb4 | r2 | ACTIVE | UP | 93900840d7804fd2adfe9bfd452263c7 | False | False | | 6cf2a3cc-5242-42b5-8c57-3ee78b0d0983 | r1 | ACTIVE | UP | 10510c89d63d490b967f90511cdc902d | True | False | +--------------------------------------+------+--------+-------+----------------------------------+-------------+-------+
А подробно информацию о роутере:
openstack router show 54550846-33f2-4954-8649-3233a49cedb4
(вывод команды немного отформатирован для лучшей читаемости)
+-------------------------+------------------------------------------------------------------- | Field | Value +-------------------------+------------------------------------------------------------------- | admin_state_up | UP | availability_zone_hints | | availability_zones | nova | created_at | 2023-02-27T14:15:39Z | description | router_for_nat | distributed | False | external_gateway_info | {"network_id": "5b1a5b04-b5ed-4ced-a097-585f40b0a5fd", | "external_fixed_ips": [ | {"subnet_id": "32d92f06-a3c7-42f1-9dbc-0eee02aa47c1", "ip_address": "10.72.10.27"} | ], | "enable_snat": false} | flavor_id | None | ha | False | id | 54550846-33f2-4954-8649-3233a49cedb4 | interfaces_info | [ | {"port_id": "e02600f1-cd39-4f1d-b1bc-c619602087b0", | "ip_address": "10.255.0.1", | "subnet_id": "4383ea14-91b6-49f9-98fa-8d6993012da2"} | ] | name | r2 | project_id | 93900840d7804fd2adfe9bfd452263c7 | revision_number | 10 | routes | | status | ACTIVE | tags | | updated_at | 2023-02-28T13:10:28Z +-------------------------+---------------------------------------
Сам по себе роутер в OpenStack это НЕ виртуальная машина, а network namespace
(сущность ядра Linux на Network Node)
Просмотр таблицы коммутации на top-of-rack switch
Зная мак-адрес целевой виртуальной машины, можно определить с какого порта коммутатора "виден" мак (правильно говорить: на каком порту коммутатора был изучен этот мак, но тут и далее я пользуюсь чаще сленговыми терминами)
В этой инсталляции в качестве коммутатора для всех нод используется Cisco Сatalyst WS-C3750E-48PD
Просмотреть с какого порта был изучен мак-адрес можно следующей командой:
c3750e-lab#show mac address-table address fa16.3e40.32d5
(Обратите внимания, что формат показа мак-адресов у различных вендоров может отличаться, и следует это учитывать.)
Mac Address Table ------------------------------------------- Vlan Mac Address Type Ports ---- ----------- -------- ----- 729 fa16.3e40.32d5 DYNAMIC Gi1/0/7
Из вывода команды можно видеть что
- Мак-адрес изучен с 7-го порта (Gi1/0/7)
- Мак-адерс находится в 729 Vlan (это было понятно еще на роутере по имени интерфейса
bridge-mosk-vlan-729-ch-os-fl
, так как в его имени содержится информация vlan: 729 os: OpenStack, fl: floatiung network, но в общем случае такой информации не будет, и этот сетап - исключение, так как при настройке заведомо предполагалось упрощение дебага.
Зная номер порта, можно обратится к документации по клауду, и определить какой сервер подключен в какой порт.
(если документация недоступна то можно попробовать определить по тому какие еще мак-адреса присутствуют на порту, в других Vlan)
В этой инсталляции (где документация есть) определяем что в порт подключен к Control/Network Node c адресом 10.72.5.11
Прохождение тарфика внутри Compute Node
В этом сетапе - это нода 10.72.5.11
kaas-node-b4d3a72a-abe6-4dba-9547-30915084c409
Vlan 729 заходит в интерфейс с именем floating
- это имя дано специально, в общем случае имя может отличаться
- на этом интерфейсе уже нет никаких тегов - они снимаются раньше, другими словами tcpdump -i floating -n -ee не покажет тегированного трафика,
для данного случая не принципиально как именно снимается тег
- на этом интерфейсе нет ip адреса
<code>ip addr show dev floating</code> 7: floating: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc fq_codel master ovs-system state UP group default qlen 1000 link/ether 52:54:15:ac:ac:16 brd ff:ff:ff:ff:ff:ff inet6 fe80::5054:15ff:feac:ac16/64 scope link valid_lft forever preferred_lft forever
Изначально на этом интерфейсе присутствовал ip адрес - это в целом не мешало работе виртуальных машин, однако они не были доступны с этой ноды (но были доступны из сети).
Это была ошибка конфигурации, в целом назначать адреса на порты бриджа не правильно.
- Детальная информация по интерфейсу:
ip -d link show dev floating
7: floating: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc fq_codel master ovs-system state UP mode DEFAULT group default qlen 1000 link/ether 52:54:15:ac:ac:16 brd ff:ff:ff:ff:ff:ff promiscuity 1 minmtu 68 maxmtu 65535 openvswitch_slave addrgenmode eui64 numtxqueues 1 numrxqueues 1 gso_max_size 65536 gso_max_segs 65535
Тут важно что этот интерфейс включен как порт OpenVSwitch (что видно из строки openvswitch_slave ) и, соответвенно трафик попавший в этот интерфейс попадает в openvswitch
Прохождение трафика внутри OpenVSwitch
OpenVSwitch представляет собой программную реализацию OpenFlow коммутатора, (точнее в пределах одной Linux ноды можно создать несколько независимо работающих OpenFlow коммутаторов)
В этой инсталляции процессы openvswitch работают внутри docker-контейнера, по этой причине все команды для работы с openvswitch нужно запускать оттуда:
docker exec -ti 1d8e520565ba ovs-vsctl show
однако для простоты в дальнейшем я буду опускать docker exec ...
Выяснить в какой виртуальный свитч попадает трафик
Выша было выяснено, что трафик уходит в недра OpenVSwitch, однако теперь предстоит выяснить в какой именно виртуальный коммутатора попадает трафик
Для этого просмотрим все виртуальные коммутаторы:
ovs-vsctl show
Часть вывода команды скрыта, полный вывод см ниже, тут оставлена только значимая часть
Bridge br-ch-os-fl Controller "tcp:127.0.0.1:6633" is_connected: true fail_mode: secure datapath_type: system Port br-ch-os-fl Interface br-ch-os-fl type: internal Port phy-br-ch-os-fl Interface phy-br-ch-os-fl type: patch options: {peer=int-br-ch-os-fl} Port floating Interface floating
Тут ключевые моменты такие
- Виртуальный коммутатор
br-ch-os-fl
, одним из портов (Port floating
) которого и является интерфейсInterface floating
является тем коммутатором куда попадает трафик - Этот коммутатор подключен к контроллеру,
is_connected: true
- Кроме порта через который в него попадает внешний трафик (
floating
), у него есть еще 2 порта:Port phy-br-ch-os-fl
Это порт имеет типtype: internal
что означает что он виден в системе и на него можно назначить адрес (прочитать подробнее можно тут: https://arthurchiao.art/blog/ovs-deep-dive-6-internal-port/
Port br-ch-os-fl
Этот порт имеет тип type: patch и предназначен для соединения нескольких виртуальных коммутаторов между собой, второй конец этого виртуального патч-корда имеет имяint-br-ch-os-fl
. В целом, это напоминает работу интерфейсаveth
Прохождение трафика через виртуальный коммутатор br-ch-os-fl
Итак, трафик попал в виртуальный коммутатор br-ch-os-fl
через физический интерфейс floating
(он же порт коммутатора с таким же именем floating
)
В отличии от "классических" коммутаторов, которые осуществляют пересылку пакетов основываясь на изученной таблице мак-адресов,
OpenFlow-коммутаторы (которыми и является виртуальный коммутатор br-ch-os-fl
)
используют для определения порта назначения OpenFlow-правила
Для просмотра правил в случае OpenVSwitch можно использовать команду ovs-ofctl dump-flows br-ch-os-fl
br-ch-os-fl
- это имя виртуального коммутатора, которых может быть более чем один на одной Linux-ноде.
Результат работы команды
cookie=0x2d19cd3395437eb3, duration=691002.184s, table=0, n_packets=106295, n_bytes=10732118, priority=2,in_port="phy-br-ch-os-fl" actions=resubmit(,1) cookie=0x2d19cd3395437eb3, duration=691222.458s, table=0, n_packets=186, n_bytes=11672, priority=0 actions=NORMAL cookie=0x2d19cd3395437eb3, duration=691002.076s, table=0, n_packets=777807, n_bytes=48652600, priority=1 actions=resubmit(,3) cookie=0x2d19cd3395437eb3, duration=691001.975s, table=1, n_packets=106295, n_bytes=10732118, priority=0 actions=resubmit(,2) cookie=0x2d19cd3395437eb3, duration=690851.627s, table=2, n_packets=105853, n_bytes=10694426, priority=4,in_port="phy-br-ch-os-fl",dl_vlan=2 actions=strip_vlan,NORMAL cookie=0x2d19cd3395437eb3, duration=691001.628s, table=2, n_packets=442, n_bytes=37692, priority=2,in_port="phy-br-ch-os-fl" actions=drop cookie=0x2d19cd3395437eb3, duration=690999.407s, table=3, n_packets=0, n_bytes=0, priority=2,dl_src=fa:16:3f:0e:d7:45 actions=output:"phy-br-ch-os-fl" cookie=0x2d19cd3395437eb3, duration=690999.335s, table=3, n_packets=0, n_bytes=0, priority=2,dl_src=fa:16:3f:64:4e:1f actions=output:"phy-br-ch-os-fl" cookie=0x2d19cd3395437eb3, duration=690999.291s, table=3, n_packets=0, n_bytes=0, priority=2,dl_src=fa:16:3f:96:cd:a5 actions=output:"phy-br-ch-os-fl" cookie=0x2d19cd3395437eb3, duration=690999.111s, table=3, n_packets=0, n_bytes=0, priority=2,dl_src=fa:16:3f:a0:1e:1b actions=output:"phy-br-ch-os-fl" cookie=0x2d19cd3395437eb3, duration=690998.887s, table=3, n_packets=0, n_bytes=0, priority=2,dl_src=fa:16:3f:f9:d4:00 actions=output:"phy-br-ch-os-fl" cookie=0x2d19cd3395437eb3, duration=691001.561s, table=3, n_packets=777807, n_bytes=48652600, priority=1 actions=NORMAL
Правила просамтриваются в следующем порядке
- таблицы по номерам, от меньшего к большему (первая таблица - с номером 0)
- Правила внутри таблицы просматриваются в порядке приоритетов, от большего к меньшему, первое правило с номером 65535
- При равном приортете правила просматриваются в том порядке в котором добавлены (c верху вниз)
Для лучшего понимания, отсортируем правила в то порядке в котором они будут работать
(с верху вниз, верхнее - первое)
Таблица 0
cookie=0x2d19cd3395437eb3, duration=691002.184s, table=0, n_packets=106295, n_bytes=10732118, priority=2,in_port="phy-br-ch-os-fl" actions=resubmit(,1) cookie=0x2d19cd3395437eb3, duration=691002.076s, table=0, n_packets=777807, n_bytes=48652600, priority=1 actions=resubmit(,3) cookie=0x2d19cd3395437eb3, duration=691222.458s, table=0, n_packets=186, n_bytes=11672, priority=0 actions=NORMAL
Таблица 1
cookie=0x2d19cd3395437eb3, duration=691001.975s, table=1, n_packets=106295, n_bytes=10732118, priority=0 actions=resubmit(,2)
Таблица 2
cookie=0x2d19cd3395437eb3, duration=690851.627s, table=2, n_packets=105853, n_bytes=10694426, priority=4,in_port="phy-br-ch-os-fl",dl_vlan=2 actions=strip_vlan,NORMAL cookie=0x2d19cd3395437eb3, duration=691001.628s, table=2, n_packets=442, n_bytes=37692, priority=2,in_port="phy-br-ch-os-fl" actions=drop
Таблица 3
cookie=0x2d19cd3395437eb3, duration=690999.407s, table=3, n_packets=0, n_bytes=0, priority=2,dl_src=fa:16:3f:0e:d7:45 actions=output:"phy-br-ch-os-fl" cookie=0x2d19cd3395437eb3, duration=690999.335s, table=3, n_packets=0, n_bytes=0, priority=2,dl_src=fa:16:3f:64:4e:1f actions=output:"phy-br-ch-os-fl" cookie=0x2d19cd3395437eb3, duration=690999.291s, table=3, n_packets=0, n_bytes=0, priority=2,dl_src=fa:16:3f:96:cd:a5 actions=output:"phy-br-ch-os-fl" cookie=0x2d19cd3395437eb3, duration=690999.111s, table=3, n_packets=0, n_bytes=0, priority=2,dl_src=fa:16:3f:a0:1e:1b actions=output:"phy-br-ch-os-fl" cookie=0x2d19cd3395437eb3, duration=690998.887s, table=3, n_packets=0, n_bytes=0, priority=2,dl_src=fa:16:3f:f9:d4:00 actions=output:"phy-br-ch-os-fl" cookie=0x2d19cd3395437eb3, duration=691001.561s, table=3, n_packets=777807, n_bytes=48652600, priority=1 actions=NORMAL
table 0
коммутатора br-ch-os-fl
Правила table 0
table=0, priority=2,in_port="phy-br-ch-os-fl" actions=resubmit(,1)
- Правило означает: все пакеты с порта
phy-br-ch-os-fl
, исследуемый трафик в это правило не попадает так как приходит с портаfloating
cookie=0x2d19cd3395437eb3, duration=691002.184s, table=0, n_packets=106295, n_bytes=10732118, priority=2,in_port="phy-br-ch-os-fl" actions=resubmit(,1)
table=0, priority=1 actions=resubmit(,3)
- Правило означает: все пакеты (так как не указано никакое условие) и именно оно будет применено к исследуемому трафику, действие в нет - перейти в таблицу 3, это действие описывает
actions=resubmit(,3)
cookie=0x2d19cd3395437eb3, duration=691002.076s, table=0, n_packets=777807, n_bytes=48652600, priority=1 actions=resubmit(,3)
table=0, priority=0 actions=NORMAL
- Это правило никогда не сработает, но если по какой-то причине предыдущее правило будет отсутствовать, то это правило заставит сделать коммутацию как классический свитч, используя таблицу ма-адресов.
cookie=0x2d19cd3395437eb3, duration=691222.458s, table=0, n_packets=186, n_bytes=11672, priority=0 actions=NORMAL
table 3
коммутатора br-ch-os-fl
Согласно правилу в таблице 0, исследуемый трафик отправлен в таблицу 3
В этой таблице много похожих правил, все они означают что при совпадении мак-адресов отправить пакет в порт phy-br-ch-os-fl
и ни один из мак-адресов не является мак-адресом трафика адресованного виртуальной машине
В случае когда трафик к виртуальной машине идет из-за пределов OpenStack (это и есть рассматриваемый случай), то мак-адресом отправителя таких пакетов будет мак-адрес маршрутизатора,
того интерфейса который смотрит в floating сеть (в этом сетапе это VLAN729)
Просмотреть мак-адрес в случае микротика можно в настройках интерфейса
/interface/bridge/print where name=bridge-mosk-vlan-729-ch-os-fl Flags: X - disabled, R - running 9 R name="bridge-mosk-vlan-729-ch-os-fl" mtu=auto actual-mtu=1500 l2mtu=1588 arp=enabled arp-timeout=auto mac-address=00:02:2D:AA:BB:02 protocol-mode=none fast-forward=yes igmp-snooping=no auto-mac=no admin-mac=00:02:2D:AA:BB:02 ageing-time=5m vlan-filtering=no dhcp-snooping=no
и тут видно что admin-mac=00:02:2D:AA:BB:02
не совпадает ни с одним из правил (все кроме первого правила спрятаны под спойлер), из чего делаем вывод что отрабатывает только последнее правило.
cookie=0x2d19cd3395437eb3, duration=690999.407s, table=3, n_packets=0, n_bytes=0, priority=2,dl_src=fa:16:3f:0e:d7:45 actions=output:"phy-br-ch-os-fl"
Последнее правило имеет actions=NORMAL
, это значит что дальнейшая коммутация будет осуществляться классическим способом, используя таблицу коммутации по мак-адресам,
и значит нужно проверить содержание этой таблицы.
cookie=0x2d19cd3395437eb3, duration=691001.561s, table=3, n_packets=777807, n_bytes=48652600, priority=1 actions=NORMAL
Forwarding Database
(таблица мак-адресов) коммутатора br-ch-os-fl
Таблицу Forwarding Database (FDB, таблица мак-адресов) на OpenVSwitch можно просмотреть командой:
ovs-appctl fdb/show br-ch-os-fl
port VLAN MAC Age 1 0 6a:7a:ba:bc:8b:26 219 1 0 d4:ca:6d:7c:a6:5c 199 1 0 52:54:15:aa:aa:16 24 1 0 52:54:15:ff:ff:16 23 1 0 00:02:2d:aa:bb:02 1 2 0 fa:16:3e:40:32:d5 1
Из этой таблицы видно, что целевой мак (fa:16:3e:40:32:d5
) в ней присутствует и изучен с порта номер 2,
а все остальные маки изучены с порта номер 1 (в том числе и мак маршрутизатора, 00:02:2d:aa:bb:02
)
Однако, вывод ovs-vsctl show
не дает информации о номерах портов, а только их имена:
Bridge br-ch-os-fl Controller "tcp:127.0.0.1:6633" is_connected: true fail_mode: secure datapath_type: system Port br-ch-os-fl Interface br-ch-os-fl type: internal Port phy-br-ch-os-fl Interface phy-br-ch-os-fl type: patch options: {peer=int-br-ch-os-fl} Port floating Interface floating
Далее требуется сопоставить номера портов виртуального коммутатора br-ch-os-fl
и их имена
Сопоставление номеров и имен портов для виртуального коммутатора br-ch-os-fl
Просмотреть нумерацию портов (внутри одного из многих коммутаторов!) можно командой
ovs-ofctl -OOpenFlow13 show br-ch-os-fl
br-ch-os-fl
- имя коммутатора, для которого хочется посмотреть порты
OFPT_FEATURES_REPLY (OF1.3) (xid=0x2): dpid:0000ba2f0edece4e n_tables:254, n_buffers:0 capabilities: FLOW_STATS TABLE_STATS PORT_STATS GROUP_STATS QUEUE_STATS OFPST_PORT_DESC reply (OF1.3) (xid=0x3): 1(floating): addr:52:54:15:ac:ac:16 config: 0 state: LIVE speed: 0 Mbps now, 0 Mbps max 2(phy-br-ch-os-fl): addr:96:e8:e7:04:ec:d9 config: 0 state: LIVE speed: 0 Mbps now, 0 Mbps max LOCAL(br-ch-os-fl): addr:ba:2f:0e:de:ce:4e config: PORT_DOWN state: LINK_DOWN speed: 0 Mbps now, 0 Mbps max OFPT_GET_CONFIG_REPLY (OF1.3) (xid=0x9): frags=normal miss_send_len=0
Из вывода команды видно, что порт номер 2 это порт phy-br-ch-os-fl
, который имеет состояние LIVE
из вывода команды ovs-vsctl show
(оставлена только значимая часть) можно видеть что порт 2, он же phy-br-ch-os-fl
,
имеет тип type: patch
, и второй конец "виртуального патч-корда" имеет имя int-br-ch-os-fl
(options: {peer=int-br-ch-os-fl}
)
... Port phy-br-ch-os-fl Interface phy-br-ch-os-fl type: patch options: {peer=int-br-ch-os-fl} ...
TODO (открытые вопросы):
Пока не ясно для чего служит
LOCAL(br-ch-os-fl): addr:ba:2f:0e:de:ce:4e config: PORT_DOWN state: LINK_DOWN speed: 0 Mbps now, 0 Mbps max
Этот же интерфейс, с таким же маком (ba:2f:0e:de:ce:4e
) и состоянием ( LINK_DOWN
) виден в системе:
ip link show dev br-ch-os-fl
77: br-ch-os-fl: <BROADCAST,MULTICAST> mtu 1500 qdisc noop state DOWN mode DEFAULT group default qlen 1000 link/ether ba:2f:0e:de:ce:4e brd ff:ff:ff:ff:ff:ff
Определение куда попадает трафик через виртуальный патчк-корд phy-br-ch-os-fl
Для того что бы понть куда трафик попадает через виртуальный патч-корд phy-br-ch-os-fl
, нужно
вернуться назад к выводу команды ovs-vsctl show
В части вывода, касающейся коммутатора br-int
можно видеть, что вторая часть патч-корда (peer=int-br-ch-os-fl
) является портом коммутатора br-int
Bridge br-int Controller "tcp:127.0.0.1:6633" is_connected: true fail_mode: secure datapath_type: system Port patch-tun Interface patch-tun type: patch options: {peer=patch-int} Port qr-e02600f1-cd tag: 1 Interface qr-e02600f1-cd type: internal Port int-br-ch-os-fl Interface int-br-ch-os-fl type: patch options: {peer=phy-br-ch-os-fl} Port qg-aefc8a2e-98 tag: 2 Interface qg-aefc8a2e-98 type: internal Port br-int Interface br-int type: internal Port qg-932d2f98-d2 tag: 2 Interface qg-932d2f98-d2 type: internal Port o-hm0 tag: 1 Interface o-hm0 type: internal Port fg-ecf7bdaf-ff tag: 2 Interface fg-ecf7bdaf-ff type: internal
Вот описание порта через который трафик попадет в коммутатор br-int
- это (ожидаемо) виртуальный патч-корд, второй конец которого - phy-br-ch-os-fl
включен в коммутатор br-ch-os-fl
Port int-br-ch-os-fl Interface int-br-ch-os-fl type: patch options: {peer=phy-br-ch-os-fl}
Прохождение трафика через виртуальный коммутатор br-int
Как выяснили, трафик попадает в коммутатор br-int
через порт int-br-ch-os-fl
Port int-br-ch-os-fl Interface int-br-ch-os-fl type: patch options: {peer=phy-br-ch-os-fl}
Так-как коммутатор br-int
так же являетя OpenFlow коммутатором, то для понимания пути прохождения трафика нужно просмотреть правила OpenFlow
Просмотреть правила можно командой:
ovs-ofctl dump-flows br-int
Полный вывод достаточно большой, скрыт под спойлер, для анализа используем сокращенный вывод.
В целом логика такая же как и при прохождении трафика br-ch-os-fl
Напомню, чтот правила просматриваются по таблицам, сначала таблица 0, потом 1 и т.д, а правила внутри таблицы просматриваются в порядке приоритета, от большего к меньшему
Далее везде используется вывод уже отсортированный для удобства просмотра.
Поля
cookie
,
duration
,
n_packets
n_bytes
удалены для удобства, они не влияют на результат работы правила.
table 0
коммутатора br-int
table=0 priority=65535,dl_vlan=4095
Этому правилу (ниже) соответствует трафик с VLAN_ID=4095, рассматриваемый сейчас трафик тэга не имеет, значит правило не срабатывает на него.
table=0 priority=65535,dl_vlan=4095 actions=drop
table=0 priority=200,reg3=0
Это правило (ниже) вызывает у меня затруднение, reg3=0
это обращение к 3-му регистру, но я пока не могу точно сказать как работает это расширение протокола OpenFlow
Судя по всему, это правило следует читать так
Если у пакета регистр3=0 (что касается всех пакетов, так как этот регистр - это внутреннее свойство пакета, а не поле по какому-либо смещению, и не существует за пределами OpenVSwitch), то:
set_queue:0,load
Установить очередь 0 (TODO: Добавить пояснения)0x1->NXM_NX_REG3[0]
Установить (загрузить в регистр) значение 0x1 в 0 байт регистра 3resubmit(,0)
Перенаправить пакет на вход таблицы 0
При повторном прохождении пакета это правило более не срабатывает, так как reg3 не равен более 0, а равен 0x1
table=0 priority=200,reg3=0 actions=set_queue:0,load:0x1->NXM_NX_REG3[0],resubmit(,0)
table=0 priority=5,in_port="int-br-ch-os-fl",dl_dst=fa:16:3f:e0:b7:4b actions=resubmit(,4)
Это правило (ниже) не срабатывает так-как не совпадает мак получателя (мак получателя FA:16:3E:40:32:D5
не совпадает с маком fa:16:3f:e0:b7:4b
из правила)
table=0 priority=5,in_port="int-br-ch-os-fl",dl_dst=fa:16:3f:e0:b7:4b actions=resubmit(,4)
Остальные не сработавшие но полностью аналогичные правила спрятаны под спойлер, мак-адреса тоже не совпадают.
table=0 priority=3,in_port="int-br-ch-os-fl",vlan_tci=0x0000/0x1fff actions=mod_vlan_vid:2,resubmit(,60)
Это правило следует читать как
- Пакеты с порта
int-br-ch-os-fl
- У которых не установлен VlanID
Чуть подробнее остановлюсь на условии vlan_tci=0x0000/0x1fff
Прочитать можно тут: ovs-fields.7.txt
Правило читается так:
- взять поле
vlan_tci
(это внутренняя структура у OpenVSwitchи других OpenFlow свитчей, а не поле в пакете!) - наложить на него битовую маску
0x1fff
(что в двоичной форме соответствует0001111111111111
- результат сравнить с 0x0000
Накладывание битовой маски - по сути операция умножения, другим словами это означает что первые три бита в исходном пакет могут быть любыми (после умножения на 0 они будут равны 0),
а остальные должны уже быть равны нулю в исходном пакете (умножение на 1 не изменяет их значения)
В описании поля vlan_tci
видно, что первые 3 бита отведены под PCP (Priority Control Point)
NXM_VLAN_TCI <----------> 3 1 12 +----+--+----+ |PCP |P |VID | +----+--+----+
Другими словами, это правило означает что
- Бит присутствия VLAN (CFI, Canonical Format Indicator) должен быть выставлен в 0
- Поле VLAN ID выставлено в 0 (все биты установлены в 0)
- значение поля приоритета игнорируетс
В сумме это правило значит "нетэгированный пакет с порта int-br-ch-os-fl
" куда и попадает искомый трафик - и он далее передается в таблицу 60 после того как на него будет добавлен тег 2 (mod_vlan_vid:2
)
table=0 priority=3,in_port="int-br-ch-os-fl",vlan_tci=0x0000/0x1fff actions=mod_vlan_vid:2,resubmit(,60)
table=0 priority=2,in_port="int-br-ch-os-fl" actions=drop
Это правило значит что все что не попало под предыдущее правило (другими словами пакеты с тегом) нужно дропнуть
table=0 priority=2,in_port="int-br-ch-os-fl" actions=drop
table=0 priority=0 actions=resubmit(,60)
Это правило безусловно все остальные пакеты передаст в таблицу 60, не модифицируя их
table=0 priority=0 actions=resubmit(,60)
table 60
коммутатора br-int
Полный список правил (вывод не содержит не значазих полей)
table=60 priority=100,in_port="o-hm0" actions=load:0x3->NXM_NX_REG5[],load:0x1->NXM_NX_REG6[],resubmit(,71) table=60 priority=100,in_port="qg-aefc8a2e-98" actions=load:0x6->NXM_NX_REG5[],load:0x2->NXM_NX_REG6[],resubmit(,73) table=60 priority=100,in_port="qg-932d2f98-d2" actions=load:0x7->NXM_NX_REG5[],load:0x2->NXM_NX_REG6[],resubmit(,73) table=60 priority=100,in_port="fg-ecf7bdaf-ff" actions=load:0x5->NXM_NX_REG5[],load:0x2->NXM_NX_REG6[],resubmit(,73) table=60 priority=100,in_port="qr-e02600f1-cd" actions=load:0x4->NXM_NX_REG5[],load:0x1->NXM_NX_REG6[],resubmit(,73) table=60 priority=90,dl_vlan=1,dl_dst=fa:16:3e:0c:e4:73 actions=load:0x3->NXM_NX_REG5[],load:0x1->NXM_NX_REG6[],strip_vlan,resubmit(,81) table=60 priority=3 actions=NORMAL
Тут видно что все правила, кроме последнего, имеют условия не соответствующие исследуемому трафику - отличия в поле in_port
, vlan или мак
Соответственно срабатывает третье правило (actions=NORMAL
) и далее для коммутации трафика используется классическаая таблица мак-адресов
Таблица мак-адресов коммутатора br-int
Далее для проверки куда отправить пакет с маком назначения fa:16:3e:40:32:d5
нужно проверить содержимое таблицы коммутации (FDB, Forwarding Database)
ovs-appctl fdb/show br-int
port VLAN MAC Age 1 2 52:54:15:aa:aa:16 119 1 2 52:54:15:ff:ff:16 38 1 2 00:02:2d:aa:bb:02 0 5 2 fa:16:3e:40:32:d5 0
Тут видно что мак fa:16:3e:40:32:d5
изучен с порта номер 5
Для того что бы выяснить какой именно порт имеет номер 5, просмотреть номера портов
ovs-ofctl -OOpenFlow13 show br-int
OFPT_FEATURES_REPLY (OF1.3) (xid=0x2): dpid:0000ae845ebd9a43 n_tables:254, n_buffers:0 capabilities: FLOW_STATS TABLE_STATS PORT_STATS GROUP_STATS QUEUE_STATS OFPST_PORT_DESC reply (OF1.3) (xid=0x3): 1(int-br-ch-os-fl): addr:f6:69:e1:c0:39:3c config: 0 state: LIVE speed: 0 Mbps now, 0 Mbps max 2(patch-tun): addr:16:6a:e5:70:65:5c config: 0 state: LIVE speed: 0 Mbps now, 0 Mbps max 3(o-hm0): addr:fa:16:3e:42:68:31 config: 0 state: LIVE speed: 0 Mbps now, 0 Mbps max 4(qr-e02600f1-cd): addr:00:00:00:00:00:00 config: PORT_DOWN state: LINK_DOWN speed: 0 Mbps now, 0 Mbps max 5(qg-aefc8a2e-98): addr:00:00:00:00:00:00 config: PORT_DOWN state: LINK_DOWN speed: 0 Mbps now, 0 Mbps max 6(fg-deee2f23-09): addr:00:00:00:00:00:00 config: PORT_DOWN state: LINK_DOWN speed: 0 Mbps now, 0 Mbps max 7(qg-932d2f98-d2): addr:00:00:00:00:00:00 config: PORT_DOWN state: LINK_DOWN speed: 0 Mbps now, 0 Mbps max 8(tapb9b0014b-e1): addr:00:00:00:00:00:00 config: PORT_DOWN state: LINK_DOWN speed: 0 Mbps now, 0 Mbps max LOCAL(br-int): addr:ae:84:5e:bd:9a:43 config: PORT_DOWN state: LINK_DOWN speed: 0 Mbps now, 0 Mbps max OFPT_GET_CONFIG_REPLY (OF1.3) (xid=0x9): frags=normal miss_send_len=0
Тут видно что номеру 5 соответствует интерфейс qg-aefc8a2e-98
5(qg-aefc8a2e-98): addr:00:00:00:00:00:00 config: PORT_DOWN state: LINK_DOWN speed: 0 Mbps now, 0 Mbps max
ovs-vsctl show
показывает что
- это интерфейс типа
internal
и это означает что он должен быть виден в системе командойip link show ...
- этот интерфейс имеет VLAN (
tag: 2
), что (предположительно) соответствует access port 2, при отправки на этот порт будет снят тег, а при получении - добавлен тег 2 - тег 2 совпадает с тегом которым тегирован исследуемый трафик
Port qg-932d2f98-d2 tag: 2 Interface qg-932d2f98-d2 type: internal </code> Однако "в лоб" интерфейс в системе не виден <BR> <code>ip link show dev qg-aefc8a2e-98</code> <PRE> Device "qg-aefc8a2e-98" does not exist.
Это связано с тем что он находится внутри network namespace
Дальнейшим прохождением трафика занимается уже не OpenVSwitch, а сетевая подсистема Linux
Можно было увидеть: config: PORT_DOWN
, state: LINK_DOWN
5(qg-aefc8a2e-98): addr:00:00:00:00:00:00 config: PORT_DOWN state: LINK_DOWN speed: 0 Mbps now, 0 Mbps max
Могу предположить что OpenVSWitch не может определить статус интерфейса, если он находится в network namespace отличном от "умолчального" (в терминах Cisco это называется VRF Global)
Прохождение трафика внутри Network Node
Первым делом следует определить в какой именно network namespace помещен интерфейс (qg-aefc8a2e-98
- имя интерфейса и оно же имя порта openvswitch)
Определение Network Namespace в который попадает трафик
ip netns list
qdhcp-bd7e52d9-e09c-4d43-8816-db1be731a761 (id: 50) fip-5b1a5b04-b5ed-4ced-a097-585f40b0a5fd (id: 29) snat-6cf2a3cc-5242-42b5-8c57-3ee78b0d0983 (id: 49) qrouter-6cf2a3cc-5242-42b5-8c57-3ee78b0d0983 qrouter-54550846-33f2-4954-8649-3233a49cedb4 (id: 14)
Для того что бы не перебирать все неймспейсы руками:
for NET_NS_NAME in $(ip netns list | awk '{print $1}'); do ip netns exec ${NET_NS_NAME} ip -s -d link show dev qg-aefc8a2e-98 2>/dev/null && echo ${NET_NS_NAME} && break; done
83: qg-aefc8a2e-98: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1480 qdisc noqueue state UNKNOWN mode DEFAULT group default qlen 1000 link/ether fa:16:3e:40:32:d5 brd ff:ff:ff:ff:ff:ff promiscuity 1 minmtu 68 maxmtu 65535 openvswitch addrgenmode eui64 numtxqueues 1 numrxqueues 1 gso_max_size 65536 gso_max_segs 65535 RX: bytes packets errors dropped overrun mcast 373294 7318 0 0 0 0 TX: bytes packets errors dropped carrier collsns 198624 1955 0 0 0 0 qrouter-54550846-33f2-4954-8649-3233a49cedb4
Из вывода видно, что интерфейс это порт openvswitch
,
а искомый Network Namespace - qrouter-54550846-33f2-4954-8649-3233a49cedb4
На самом деле можно было предположить что это какой-то роутер
openstack router list
+--------------------------------------+------+--------+-------+----------------------------------+-------------+-------+ | ID | Name | Status | State | Project | Distributed | HA | +--------------------------------------+------+--------+-------+----------------------------------+-------------+-------+ | 54550846-33f2-4954-8649-3233a49cedb4 | r2 | ACTIVE | UP | 93900840d7804fd2adfe9bfd452263c7 | False | False | ...
и тут видно что ID роутера совпадает с именем неймспейса
Конечно когда роутеров много - все может оказаться сложнее