Привет, Хабр! Возвращаюсь с продолжением нашей детективной истории про Петра, у которого не загружались картинки с котиками. В прошлом тексте, ссылку на который вы найдете в статье, мы выяснили, что проблема скрывается в коммутаторе. Теперь мы с вами погрузимся в глубь его программного устройства и будем по одному отметать версии о подозреваемых источниках проблем.
Когда введен десяток команд, сложно сказать, какая из них повлияла на прохождение трафика. Поэтому мы начнем вводить команды по одной и проверять правильность конфигурации. Так и поступим: «занулим» конфигурацию и будем контролировать выполнение команды на разных уровнях коммутатора.
Настраиваем L3-интерфейс
Для каждого действия я буду указывать уровень погружения внутрь коммутатора. Напомню их сверху вниз: CLI, Linux, SAI, SDK. И картинка из первой части — для освежения памяти.

Уровень CLI
Введем команду на создание L3-интерфейса:
switch1# configure terminal
switch1(config)# interface Ethernet 1 
switch1(conf-if-Ethernet1)# ip address 10.1.1.1/24И проверим direct-connected маршрут:
switch1# show ip route
	Destination		Gateway	Interface	Dist/Metric	Uptime
------------------------------------------------------------------------------------------------------------  
C>* 10.1.1.0/24		Direct	Ethernet1	0/0		    00:07Посмотрим, как конфигурация зашла на Linux.
Уровень Linux
У нас есть интерфейс с IP- и MAC-адресами.
# ip a show Ethernet1
Ethernet1: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 9100 qdisc fq_codel state UP group default qlen 1000
	link/ether 98:19:2c:9b:58:49 brd ff:ff:ff:ff:ff:ff
	inet 10.1.1.1/24 brd 10.1.1.255 scope global Ethernet1Еще у интерфейса есть direct-connected маршрут.
# ip route list
10.1.1.0/24 dev Ethernet1 proto kernel scope link src 10.1.1.1
...
Как вы помните, конфигурация Linux и ASIC должна быть синхронизирована. Поэтому то же самое мы должны отправить через SAI в ASIC.
Если мир сетевого оборудования вам «абсолютно понятен», присоединяйтесь к нашей команде разработки коммутатора KORNFELD. Возможно, вас заинтересуют эти вакансии:
→ Сетевой инженер по автоматизации (Python)
→ Ведущий инженер группы аналитики и комплексного тестирования
Уровень SAI
Мы говорим коммутатору: «Создай, пожалуйста, в Virtual router интерфейс и добавь ему два маршрута. Если это маршрут с 32-й маской, то есть коммутатору, подними его на CPU-порт. А если это маршрут в «первую» сеть, отправь сразу на физический порт, не нужно поднимать его на CPU».

Уровень ASIC
Чтобы следующая часть была понятнее , нужно немного прояснить внутреннее устройство портов коммутатора. У каждого физического порта в ASIC есть два конвейера (пайплайна):
Ingress — на прием пакетов.
Egress — на передачу пакетов.
Пакет попадает на порт, проходит через ingress-пайплайн, откуда попадает в routing или в switching. На выходе пакет проходит через egress-пайплайн:

Теперь вернемся к нашей конфигурации. Она состоит из нескольких частей, в числе которых:
- L3-интерфейс, принадлежащий определенному VRF. 
- ingress-интерфейс, принадлежащий L3-интерфейсу. 
- egress-интерфейс, принадлежащий L3-интерфейсу. 
- Маршруты, доступные через определенные egress-интерфейсы. Маршруты также принадлежат определенному VRF. 
По команде, которую мы передали через SAI, в ASIC был создан L3-интерфейс с номером 4097, в VRF по умолчанию. Важным параметром L3-интерфейса является src MAC-адрес, который будет выставлен пакету при отправке. L3 ingress-интерфейс использует этот MAC-адрес для проверки, что пакет предназначен именно этому устройству.
drivshell>l3 intf show
Unit  Intf      VRF   Group   VLAN    Source MAC          MTU    TTL   InnerVlan  NATRealm 
---------------------------------------------------------------------------------------------------------------------------      
0     4096      -3      0     1       98:19:2c:9b:58:49   9100    0    0         0
0     4097       0      0     4095    98:19:2c:9b:58:49   9100    0    0         0Внимательный читатель наверняка обратил внимание на служебный VLAN 4095, в который помещен интерфейс. Выделение в служебный предотвратит «переливание» маршрутизируемого трафика во VLAN, созданный на коммутаторе.
С L3-интерфейсом 4097 связан ingress-интерфейс с номером 16383, который в свою очередь привязан к физическому порту. Пакеты, поступающие на физический порт, будут попадать на ingress-интерфейс 16383, а через него — на L3-интерфейс.

Дальше создадим egress-интерфейс для CPU с номером 132769. Egress-интерфейс тоже привязан к физическому порту, и все, что уходит через него, обязательно будет передано через физический порт. Функции, выполняемые выходным конвейером, иногда называют «последним приготовлением пакета перед отправкой».
Поскольку мы говорим о маршрутизации, то при переходе в следующий сегмент Ethernet должны подмениться src и dst MAC-адреса. Dst MAC-адрес является параметром именно egress-интерфейса, изменение этого поля заголовка происходит в выходном конвейере. В листинге ниже, 98:19:2c:9b:58:49 является MAC-адресом Control Plane
drivshell>l3 egress show
Entry   Mac                  Vlan   INTF    PORT  MOD  MPLS_LABEL   ToCpu   Drop  Ref Count
132768  98:19:2c:9b:58:49    1      4096    0     0    -1           no      yes   2    no
132769  98:19:2c:9b:58:49    0      16383   0     0    -1           no      no    4    no
Далее, согласно нашей конфигурации, создаются два маршрута: с 32-й и 24-й масками.
Отмечу, что таблица маршрутизации поделена на две части:
- fast routing — это все с 32-й маской. 
- routing — все с остальными масками, включая 24-ую. 
Fast routing содержит маршруты с 32-й маской, фактически хосты, и их можно посмотреть с помощью SDK-команды l3table, представленной в листинге ниже. Можно привести аналогию с таблицей neighbors в Linux. В соответствии с механизмом longest prefix match, dst IP-адрес в пакете ищется сперва в fast routing. Если подходящая запись не найдена, поиск переходит в routing.
Таблица routing содержит адреса подсетей, их можно посмотреть SDK-командой defip, представленной в листинге ниже.
drivshell>l3 defip show  
#     VRF     Net addr       Next Hop Mac       INTF     MODID PORT PRIO CLASS HIT
8     0       10.1.1.0/24    00:00:00:00:00:00  132769   0     0     0    2    n
1     0       0.0.0.0/0      00:00:00:00:00:00  132768   0     0     0    0    n
drivshell>l3 l3table show
Entry VRF IP address    Mac Address        INTF    MOD PORT    CLASS HIT    H/W Index
1     0   10.1.1.1    	00:00:00:00:00:00  132769  0    0       1    n      3224 	Оба маршрута смотрят на egress-интерфейс 132769, который связан с CPU-портом.
Это может показаться странным. Адрес 10.1.1.1 принадлежит самому коммутатору, и пакеты, которые содержат этот dst IP-адрес, должны передаваться через CPU-порт. Однако, так как у нас еще нет ни одного next-hop в сети 10.1.1.0/24, то весь трафик для этой сети мы поднимаем на CPU. Чтобы процессор разобрался, что делать с трафиком.

Конфигурация целиком. Посмотрим, как выглядит наша текущая конфигурация на схеме. Для удобства восприятия я нарисовал CPU-порт и слева, и справа, но это один и тот же порт. Трафик заходит в порт, проходит через ingress pipeline, заходит в routing и выходит через egress pipeline. Сейчас у нас сконфигурирован только CPU, поэтому все маршруты указывают на CPU-порт и весь трафик оказывается в пространстве ядра.

Интерфейс настроен, можем поставить первую галочку в списке необходимых для работы L3 вещей:
- Интерфейс✅
- CoPP 
- Доступный next-hop 
- Маршрут 
Отладка проблемы: настраиваем Control Place policing
Вроде бы пользовательский трафик Петра с фотографиями котиков должен начать ходить. Запустим ping от router1 до switch1:

switch1# ping 10.1.1.1
PING 10.1.1.1 (10.2.1.1) 56(84) bytes of data.
From 10.1.1.2 icmp_seq=1 Destination Host Unreachable 
From 10.1.1.2 icmp_seq=2 Destination Host Unreachable 
From 10.1.1.2 icmp_seq=3 Destination Host Unreachable К сожалению, трафик по-прежнему не идет. Попробуем разобрать коммутатор еще глубже.
Как коммутатор обрабатывает пакеты
Посмотрим верхнеуровнево на архитектуру обработки пакетов в коммутаторе:

Сначала пакет попадает в ingress pipeline. Этот конвейер обрабатывает входящие пакеты. На этом этапе пакет может быть отброшен. Например, если адрес, указанный в заголовке пакета, попадает под запрещающие ACL-правила, то пакет дропается (на схеме это отмечено серым). Если все нормально, то при прохождении ingress pipeline к пакету добавляется метаинформация. Она содержит сведения про:
- физический порт, с которого был принят пакет, 
- распарсенные заголовки, 
- VLAN, который будет обрабатывать пакет, 
- другую информацию, в зависимости от найстройки. 
После входного контейнера пакеты попадают в Memory Management Unit (MMU). Эта память хранит все пакеты и по очереди отправляет их на egress pipeline.
В egress pipeline происходит маршрутизация и последние приготовления перед отправкой. На выходе пакету нужно переехать в другой сегмент Ethernet, то есть должен измениться его MAC-адрес. При прохождении пакетом egress pipeline:
- Destination меняется на source. 
- Вместо изначального destination подставляется next-hope. 
- При необходимости добавляется VLAN tag и другие изменения в заголовках. 
После этих изменений пакет покидает коммутатор.
Как устроен MMU
Memory Management Unit (MMU) — это память, распределенная на ячейки фиксированного размера в 256B. Попадая в MMU, пакет делится на ячейки и записывается туда, где есть свободные места. Адрес первой ячейки, куда попал пакет, — это указатель, с которым мы работаем дальше.
Указатели помещаются в очереди и, в зависимости от алгоритма, будут обработаны. Пакет может направляется в несколько портов — например, при мультикастном трафике или зеркалировании. После передачи пакета его указатель удаляется из очереди. Когда указатель удален из всех очередей, пакет считается переданным — память можно использовать для других пакетов.

Как устроен ingress pipeline
Ingress pipeline парсит, аккуратно складывает и обрабатывает все заголовки входящего пакета. Каждый пакет проходит внутри пайплайна через несколько блоков, которые мы активируем при конфигурации порта:
- FDB — forwarding database, активен только на уровне L2. 
- Field processor. 
- FIB — forwarding information base. 
- ACL и другие дополнительные блоки. 
Данные пакета обрабатываются отдельно — они сразу попадают в ASIC:

FDB, Field processor и FIB — это так называемые CAM- или TCAM-таблицы. Они представляют собой соединенные друг с другом логические элементы. Чтобы понять, как таблицы работают, представим, что у нас есть IP-адрес на входе. За один такт он загружается в регистр, значения проходят через логические элементы, и за тот же один такт мы получаем результат. В данном случае результат — это hash, по которому мы можем пройти в RAM память и получить все значения, которые нужны для передачи пакета.

Получаем ARP
Теперь мы знаем чуть больше об обработке пакетов и можем вернуться к нашей конфигурации.
Уровень ASIC. Мы хотим запустить ping. Ping состоит из ARP-пакета, за которым идет ICMP-пакет. Наша задача — перехватить из трафика ARP-пакет и отправить его на обработку в Control Plane. С ней поможет Field processor. Он работает с полями заголовков и смещениями, для этого ему можно задать значение или маску. ARP-пакет можно однозначно определить по значению поля EtherType 0x0806:
// ARP- (RARP-) запись в Field processor
EID 0x00000011: gid=0x1,
DstMac
   Part:0 Offset0: 64 Width0:  16
   Part:0 Offset1: 36 Width1:   4
   Part:0 Offset2: 40 Width2:   4
   ...
   DATA=0x00009819 2c9b5849
InPorts
   ...
EtherType
   Part:1 Offset0: 64 Width0:  16
   DATA=0x00000806
IpType
   Part:0 Offset0: 154 Width0:   2
   Part:0 Offset1: 156 Width1:   2
   Part:1 Offset2: 158 Width2:   1
   DATA=0x00000008
action={act=CopyToCpu, ...}Field processor можно представить в виде таблицы, в которой описаны значения полей заголовков и поле действие (action). Если пакет совпадает с указанными значениями (в примере ниже это dst MAC-адрес, порт, EtherType, IpType), то к нему применяется заданный action, в нашем случае это CopyToCpu:

CopyToCpu означает, что ARP будет поднят на ControlPlane и обработан конвейерами — отправлен на все порты в пределах VLAN, кроме того, что его принял. Также в качестве action часто используются MoveToCpu (пакет изымается из конвейера и направляется на ControlPlane), Drop (для отбрасывания пакета) и другие действия.
Field processor — это группа правил. Предположим, мы зашли в него и увидели, что наш ARP подпадает под какое-то правило, которое находится выше. В этом и заключается проблема, но как от нее избавиться? Давайте попробуем подняться на уровень SAI и посмотреть, какая команда приходит на конфигурирование Field processor.
Уровень SAI
Когда мы хотим перехватить ARP- или RARP-трафик, то создаем Trap group. Этой Trap group мы говорим, с каким приоритетом тот или иной трафик будет подниматься на CPU.

Trap срабатывает до того, как пакет попадает в уровень L3:

Возможно, вы уже узнали в Trap group функционал policer. Производители называют его по-разному, мы привыкли к названию CoPP — Control Plane Policing. Администраторы могут трогать его по соображениям безопасности, для оптимизации трафика или работы коммутатора.
В CoPP указывается протокол, приоритет и очередь, в которую его нужно передать. Давайте сконфигурируем.
Уровень CLI
// Конфигурация через CoPP
switch1# show running-configuration
!
copp-action queue4_group2
set trap-action copy
set trap-queue 4
set trap-priority 4
...
!
class arp priority 0
 set copp-action queue4_group2
...Предположим, проблема, с которой столкнулся Пётр, была именно в конфигурации CoPP. Ее случайно удалил его коллега в целях оптимизации или по иным причинам. Мы нашли и исправили проблему — к нам пришел ARP. Можем поставить вторую галочку в списке необходимых для работы L3 вещей:
- Интерфейс✅
- CoPP✅
- Доступный next-hop 
- Маршрут 
Но трафик все же не проходит, котики все еще не загружаются. Давайте рассмотрим оставшуюся часть конфигурации.
Добавляем neighbour в Data Plane
Уровень Linux
Внутри Linux пакет тоже проходит через пайплайн, который состоит из трех блоков:
- маршруты, 
- таблица neighbors, которая заканчивается интерфейсом и MAC-адресом, 
- интерфейс, в который нужно отдать пакет. 

После наших действий в Linux появилась ARP-запись, она же запись о соседях, мы ее видим:
// Запись о соседе
# ip neighbor
10.1.1.2 dev Ethernet1 lladdr 00:e0:4b:6d:97:cb REACHABLEВ ASIC аналогичной записи о neighbor изначально нет, ее добавляет исполнительная подсистема. Давайте проследим процесс ее добавления до Data Plane.
Уровень SAI
Исполнительная подсистема отслеживает изменения в сетевой подсистеме Linux через netlink. После появления neighbor будет выработана команда для SAI:
- Создать соседа. 
- Создать внутри Virtual router next-hope, который привязан к интерфейсу, за которым находится сосед. 
В принципе очень похоже на то, что мы видели в Linux:

Уровень SDK
В ASIC добавился egress-интерфейс 132770 с MAC-адресом neighbour, то есть мы создали выходную точку.
drivshell>l3 egress show
Entry     Mac                 Vlan   INTF    PORT  MOD  MPLS_LABEL  ToCpu  Drop  RefCount
132768    98:19:2c:9b:58:49   1      4096    0     0    -1          no     yes   2
132769    98:19:2c:9b:58:49   0      16383   0     0    -1          no     no    4
132770    00:e0:4b:6d:97:cb   4095   4097    3     0    -1          no     no    1
Далее будет создан маршрут с 32-й маской, который смотрит в egress-интерфейс 132770.
drivshell>l3 l3table show
Entry   VRF   IP address   Mac Address        INTF      MOD  PORT  CLASS  HIT   H/W Index
1       0     10.1.1.1     00:00:00:00:00:00  132769    0    0     1      y     3224
2       0     10.1.1.2     00:00:00:00:00:00  132770    0    0     0      y     5272Посмотрим на картину отправки APR reply в целом. Трафик уходит вниз, попадает в CPU-порт, проходит через запись 10.1.1.2, которая только что добавилась в таблицу fast routes, и уходит через egress-интерфейс 132770.

Трафик ушел, а значит, должен появиться пинг. Проверяем:
//От router1 до switch1
switch1# ping 10.1.1.1
PING 10.1.1.1 (10.2.1.1) 56(84) bytes of data.
64 bytes from 10.2.1.1: icmp_seq=1 ttl=102 time=2.32 ms
64 bytes from 10.2.1.1: icmp_seq=2 ttl=102 time=2.13 ms
64 bytes from 10.2.1.1: icmp_seq=3 ttl=102 time=2.39 msPing ходит, все отлично. Ставим галочку, что у нас есть доступный next-hope:
- Интерфейс✅
- CoPP✅
- Доступный next-hop✅
- Маршрут 
Остался лишь один пункт в нашем списке.
Создаем маршрут
Уровень CLI
Через новый доступный next-hop в командной строке нужно создать маршрут в сеть 10.2.2.0 через маршрутизатор 10.1.1.2:
switch1(config)# ip route 10.2.2.0/24 10.1.1.2 interface Ethernet 1Проверяем в show-команде, что все получилось:
switch1# show ip route
      Destination    Gateway    	Interface    	Dist/Metric    	Uptime   	
------------------------------------------------------------------------------------------
S>*   10.2.2.0/24    via 10.1.1.2	Ethernet1    	1/0            	00:00:08 	
C>*   10.1.1.0/24    Direct         Ethernet1    	0/0             03:25:31 	Успех! Посмотрим, все ли получилось в подсистемах коммутатора.
Уровень Linux
В Linux появился маршрут в сеть 10.2.2.0/24 с next-hop 10.1.1.2.
//Neighbor уже известен
# ip neighbor
10.1.1.2 dev Ethernet1 lladdr 00:e0:4b:6d:97:cb REACHABLE//Добавлен маршрут через neighbor
# ip route
10.2.2.0/24 nhid 12 via 10.1.1.2 dev Ethernet1 proto 196 metric 20 
10.1.1.0/24 dev Ethernet1 proto kernel scope link src 10.1.1.1Ранее на коммутатор приходили ARP-ответы от 10.1.1.2, по этим ответам были созданы записи в таблице neighbors, и эти записи еще не протухли. Если бы на момент создания маршрута в таблице neighbors отсутствовала запись об 10.1.1.2, то ядро Linux само бы сгенерировало ARP-запрос и по ответу создало этот neighbour.

Уровень SAI
Команда SAI говорит о том, что такая-то подсеть доступна через такой-то next-hope и через такой-то RIF.

Уровень SDK
Появилась запись с 10.2.2.0/24 в таблице маршрутов через egress-интерфейс 132770, который был создан раньше.
drivshell>l3 defip show  
Unit 0, Total Number of DEFIP entries: 98256
#     VRF     Net addr         Next Hop Mac        INTF    MODID PORT PRIO CLASS HIT
8     0       10.2.2.0/24      00:00:00:00:00:00   132770  0     0     0    0    y
8     0       10.1.1.0/24      00:00:00:00:00:00   132769  0     0     0    2    n
1     0       0.0.0.0/0        00:00:00:00:00:00   132768  0     0     0    0    n
Проверяем, что количество ссылок на egress-интерфейс равно двум и все необходимые маршруты смотрят в egress-интерфейс.
drivshell>l3 egress show 	
Entry  Mac                 Vlan INTF PORT MOD MPLS_LABEL ToCpu Drop RefCount
132770 00:e0:4b:6d:97:cb   4095 4097 3    0   -1         no    no    2 Теперь у нас есть все, чтобы передавать трафик:
- Интерфейс✅
- CoPP✅
- Доступный next-hop✅
- Маршрут✅
Посмотрим на картину в целом. Визуально убеждаемся, что конфигурация в Linux и ASIC синхронизированы:
- Маршрут в сеть 10.2.2.0/24 (за маршрутизатором) через 10.1.1.2 (маршрутизатор). 
- Присутствует neighbor 10.1.1.2, известен его MAC-адрес и порт, через который он доступен. В ASIC он выглядит как маршрут 10.1.1.2 в таблице fast routes через egress-интерфейс. 
- Адрес 10.1.1.1 настроен на интерфейсе в Linux, а в ASIC присутствует маршрут 10.1.1.1 через CPU-порт. 

Проверяем пинг:
//От pc1 до сети 10.2.2.0/24
switch1# ping 10.2.2.1
PING 10.2.2.1 (10.2.2.1) 56(84) bytes of data.
64 bytes from 10.2.2.1: icmp_seq=1 ttl=102 time=2.56 ms 
64 bytes from 10.2.2.1: icmp_seq=2 ttl=102 time=2.02 ms 
64 bytes from 10.2.2.1: icmp_seq=3 ttl=102 time=2.15 ms
Котики загружаются! Пётр доволен — все хорошо.
Отладка проблемы: поддерживаем neighbour активным
Но не будем расслабляться. Если мы немного подождем, то заметим следующую картину: раньше трафика не было, потом он опять появился. Есть какой-то провал:
//От pc1 до сети 10.2.2.0/24
switch1# ping 10.2.2.1
PING 10.2.2.1 (10.2.2.1) 56(84) bytes of data.
From 10.10.10.11 icmp_seq=1 Destination Host Unreachable 
From 10.10.10.11 icmp_seq=1 Destination Host Unreachable
From 10.10.10.11 icmp_seq=1 Destination Host Unreachable 
64 bytes from 10.2.2.1: icmp_seq=1 ttl=102 time=2.56 ms 
64 bytes from 10.2.2.1: icmp_seq=2 ttl=102 time=2.02 msПровал вызван тем, что какое-то количество входящих пакетов было потеряно. Потом операционная система сгенерировала ARP-запрос, он прошел весь путь, и трафик снова пошел. Это проблема. Но в чем дело?
Дело в том, что, пока трафика не было, neighbor не использовался. Он был помечен как неактивный и был удален — специалисты еще говорят, что он «протух». Обычно в Linux это происходит за 300 секунд:
//Было REACHABLE стало STALE
# ip neighbor
10.1.1.2 dev Ethernet1 lladdr 00:e0:4b:6d:97:cb STALEЧтобы избежать подобных проблем, нужны механизмы, которые будут поддерживать активное состояние нашего neighbour. Существует три распространенных механизма проверки его доступности при долгом отсутствии трафика:
- ARP до next-hop при «протухании». 
- ARP до next-hop по таймеру. 
- Привязка Bidirectional Forwarding Detection-сессии к маршруту. 
ARP до next-hop при «протухании». Самый простой механизм — это сделать триггер. Как только у нас протухла запись, мы генерируем запрос, проверяем у neighbour, жив ли он. Он нам ARP reply отвечает: «Да, я жив». Мы помечаем, что запись жива и все нормально. Но если вдруг neighbour перестал быть доступным, а запись еще какое-то время будет активной, то и в таблице маршрутов запись будет активной — трафик будет теряться. Поэтому я не рекомендую использовать такой механизм.
ARP до next-hop по таймеру. Интуитивно понятный вариант — завести таймер и периодически отсылать ARP-запрос, чтобы убеждаться в доступности соседнего узла. Но у этого подхода есть некоторые недостатки. Если делать интервал слишком длинным, то недоступность узла можно заметить не сразу — и вот, мы возвращаемся к вышеописанной проблеме с триггером. Если интервал будет коротким, то мы нагружаем сеть лишним служебным трафиком.
Привязка BFD-сессии к маршруту. BFD-протокол — это обмен hello-сообщениями между соседями по заданному интервалу, обычно задается от 300 мс до 3000 мс. BFD-сессию можно привязать к маршруту, к статическому тоже — об этом надо помнить. После дополнительных настроек недоступных neighbour больше нет.
Проблема с котиками окончательно решена!
Саммари: в чем была проблема
Чтобы собрать в кучку все, что я описал выше, выделю проблемы, «спрятанные» в рассматриваемой ситуации:
→ Трафик не проходил — следствием стало отсутствие ARP-записи.
→ ARP-запись, в свою очередь, отсутствовала из-за удаленного правила CoPP, человеческий фактор. Чтобы докопаться до этой проблемы, мы проделали небольшой сюжетный «крюк» по подсистемам.
→ Когда всплыла вторая проблема с «протуханием» ARP-записи, мы смогли быстро ее выявить.
На практике часто за какой-то одной проблемой может прятаться несколько подпроблем. Очень важно сперва их выявить, а затем решать по отдельности.
Заключение
Закончу небольшим списком советов. Что делать, если вы столкнулись с проблемами в работе коммутатора:
- Проверьте логи на предмет ошибок. 
- «Занулите» конфигурацию и введите команды по одной, убеждаясь, что она правильно применилась и в CPU, и в ASIC. 
- Рассматривая проблемы с маршрутизацией, проверьте L3-интерфейс, доступность next-hop и маршрутов, правили ACL, политики Control Plane. 
Я надеюсь, что эта и предыдущая статьи приоткрыли для вас завесу тайны вокруг внутреннего устройства коммутаторов. И это поможет вам в повседневной работе или, быть может, вызовет интерес к более глубокому изучению сетевых устройств и их разработке.
Если вам больше по душе видеоформат, c этой темой я выступал на Linkmeetup. Вот ссылка на YouTube (и Rutube).
 
           
 
Brak0del
Если не секрет, почему выбрали TCAM для реализации FIB?
MikhailShpak
tcam - еще с древних времен стандарт, в той же Cisco
atcam - смотрится тоже интересно
но у коллег по цеху - может быть своя логика для Sonic по выбору реализации)
Brak0del
Ясно, спасибо.
yadro_team
Заметили верно. «Чистый» FIB не подразумевает TCAM. Но TCAM позволяет добавить в строку с MAC-адресом дополнительные поля.
andrewz13
в разных ASIC по разному реализуется. SAI это надстройка над vendor SDK.