Пользователь
0,0
рейтинг
25 марта 2013 в 13:38

Администрирование → А вы хорошо знаете статическую маршрутизацию?

Статический маршрут — первое, с чем сталкивается любой человек при изучении понятия маршрутизации IP пакетов. Считается, что это — наиболее простая тема из всех, в ней всё просто и очевидно. Я же постараюсь показать, что даже настолько примитивная технология может содержать в себе множество нюансов.

Оговорка. При написании топика я исхожу из того, что читатель знаком с концепцией маршрутизации, умеет делать статические маршруты и не считает слово «ARP» ругательным. Впрочем, даже бывалые связисты наверняка найдут тут что-то новое.
Все примеры были проверены на IOS линейки 15.2M. Поведение других ОС может различаться.
И никакого динамического роутинга тут не будет.


Мы работаем со следующей топологией:


Как появляется статический маршрут?


Для начала, выполним команду, которую знает каждый, и посмотрим дебагами, что произойдет:
R00(config)#ip route 3.1.1.0 255.255.255.0 10.0.0.3

IP-ST(default): updating same distance on 3.1.1.0/24
IP-ST(default):  3.1.1.0/24 [1], 10.0.0.3 Path = 8, no change, not active state
IP-ST(default):  3.1.1.0/24 [1], 10.0.0.3 Path = 2 3 7
RT: updating static 3.1.1.0/24 (0x0):
    via 10.0.0.3
RT: add 3.1.1.0/24 via 10.0.0.3, static metric [1/0], add succeed, active state
IP ARP: creating incomplete entry for IP address: 10.0.0.3 interface GigabitEthernet0/1
IP ARP: sent req src 10.0.0.1 30e4.db16.7791,
                 dst 10.0.0.3 0000.0000.0000 GigabitEthernet0/1
IP ARP: rcvd rep src 10.0.0.3 0019.aad6.ae10, dst 10.0.0.1 GigabitEthernet0/1

IOS создал маршрут, и сразу послал arp запрос в поисках next hop, который у нас – 10.0.0.3. И сразу вопрос: откуда роутер узнал, что запрос надо слать в интерфейс Gi0/1? Наверняка кто-то скажет «из списка локальных интерфейсов», и жестоко ошибется. Маршрутизация так не работает. На самом деле, IOS сделал рекурсивный запрос к таблице маршрутизации, чтобы узнать, как добраться до next hop:
R00#show ip route 10.0.0.3
Routing entry for 10.0.0.0/24
  Known via "connected", distance 0, metric 0 (connected, via interface)
  Routing Descriptor Blocks:
  * directly connected, via GigabitEthernet0/1
      Route metric is 0, traffic share count is 1

И вот он, наш Gi0/1. IOS узнает, что с рекурсивными запросами к RIB надо заканчивать, как только находит маршрут с флагом «directly connected». Но что если ему в ответ на изначальный запрос к 10.0.0.3 вернется вовсе не connected маршрут, а промежуточный, ссылающийся на другой next hop? Вернемся к этому чуть позже, а пока вспомним, что такое CEF.

Примерно во всей документации, ориентированной на начинающих, говорится, что каждый пакет перемещается в соответствии с таблицей маршрутизации. На самом деле на всех более-менее современных платформах это уже не так, ведь таблица маршрутизации (далее – RIB) вовсе не оптимизирована для быстрой передачи данных. Оценить масштаб бедствия позволяет эта таблица (хотя у process switching’а множество недостатков помимо неоптимальных запросов – например, постоянное переключение шедулера CPU между контекстами, что весьма затратно). CEF является серьезной оптимизацией. В современной реализации он строит две таблицы – FIB (Forwarding Information Base, таблица передачи пакетов, в основе нее – связный граф со страшным названием 256-way mtrie) и adjacency table (таблица соседств). Первая из них строится на основе таблицы маршрутизации и за один проход позволяет получить всю нужную информацию. Строится она заранее, еще до того, как появится первый соответствующий ей пакет.

Вернемся к нашему статическому маршруту. Вот запись в таблице маршрутизации:
R00#show ip route 3.1.1.0
Routing entry for 3.1.1.0/24
  Known via "static", distance 1, metric 0
  Routing Descriptor Blocks:
  * 10.0.0.3
      Route metric is 0, traffic share count is 1

Куда слать пакет? Где искать 10.0.0.3? Непонятно. Надо еще раз запросить таблицу маршрутизации, на этот раз по поводу 10.0.0.3, и, если надо, выполнить еще несколько итераций, пока не выясним connected интерфейс. И вот примерно таким образом мы фактически в несколько раз снижаем производительность маршрутизатора.

А вот что говорит CEF:
R00#show ip cef 3.1.1.0 detail
3.1.1.0/24, epoch 0
  recursive via 10.0.0.3
    attached to GigabitEthernet0/1

Просто и лаконично. Есть интерфейс, есть next hop, к которому надо слать пакет. Что там говорилось про adjacency table?
R00#show adjacency 10.0.0.3 detail
Protocol Interface                 Address
IP       GigabitEthernet0/1        10.0.0.3(10)
                                   0 packets, 0 bytes
                                   epoch 0
                                   sourced in sev-epoch 2
                                   Encap length 14
                                   0019AAD6AE1030E4DB1677910800
                                   ARP

Обратим внимание на какую-то длинную последовательность в предпоследней строке. Что-то это напоминает… Смотрим mac 10.0.0.3:
R00#show arp | in 10.0.0.3
Internet  10.0.0.3                1   0019.aad6.ae10  ARPA   GigabitEthernet0/1

Смотрим свой mac адрес на gi0/1:
R00#show int gi0/1
GigabitEthernet0/1 is up, line protocol is up
  Hardware is CN Gigabit Ethernet, address is 30e4.db16.7791 (bia 30e4.db16.7791)

Ага. Та страшная строка – всего лишь два мака, которые надо подставить в заголовок Ethernet на этапе инкапсуляции, и ethertype 0x0800, т.е. банальный IPv4. И в двух таблицах CEF есть абсолютно вся информация, какая нужна для успешной отправки пакета дальше по цепочке.

Если у кого-то возникнет вопрос, зачем железке держать сразу две таблицы вместо одной, то дам очевидный ответ: обычно у маршрутизатора мало интерфейсов (а заодно и соседей) и много маршрутов. Какой смысл тысячи раз дублировать одни и те же маки в FIB? Памяти много не бывает, особенно на аппаратных платформах, будь то новомодные ASR’ы или даже L3 свитчи линейки Catalyst. Все они задействуют CEF при передаче пакетов.

И кстати, вернемся на минутку к изначальному дебагу. Отключим CEF командой no ip cef (никогда так не делайте) и сравним результат:
IP-ST(default): updating same distance on 3.1.1.0/24
IP-ST(default):  3.1.1.0/24 [1], 10.0.0.100 Path = 8, no change, not active state
IP-ST(default):  3.1.1.0/24 [1], 10.0.0.100 Path = 2 3 7
RT: updating static 3.1.1.0/24 (0x0):
    via 10.0.0.100
RT: add 3.1.1.0/24 via 10.0.0.100, static metric [1/0], add succeed, active state

Маршрут добавлен. Arp запроса не было. И правильно – зачем RIB сдался mac адрес? Если пустить пинг до, к примеру, 3.1.1.1, то скорее всего будет так:
R00#ping 3.1.1.1
Type escape sequence to abort.
Sending 5, 100-byte ICMP Echos to 3.1.1.1, timeout is 2 seconds:
.!!!!
Success rate is 80 percent (4/5), round-trip min/avg/max = 1/1/4 ms

Первый пакет отбрасывается, и роутер посылает arp запрос с целью узнать mac адрес 10.0.0.3, если он ранее не был известен. CEF же всегда заранее узнает mac адрес next hop'а.

С этим разобрались. Теперь вернемся к вопросу, что будет, если next hop статического маршрута вовсе не на directly connected интерфейсе. Поступим просто:
R00(config)#ip route 10.0.0.3 255.255.255.255 100.100.100.101

, где Gi0/2 имеет адрес 100.100.100.100/24.
R00#show ip cef 3.1.1.0 detail
3.1.1.0/24, epoch 0
  recursive via 10.0.0.3
    recursive via 100.100.100.101
      recursive via 100.100.100.0/24
        attached to GigabitEthernet0/2

Как все плохо-то… А что если у нас есть маршрут на целую суперсеть?
R00(config)#no ip route 10.0.0.3 255.255.255.255 100.100.100.101
R00(config)#ip route 10.0.0.0 255.0.0.0 100.100.100.101

R00#show ip cef 3.1.1.0 detail
3.1.1.0/24, epoch 0
  recursive via 10.0.0.3
    attached to GigabitEthernet0/1

Сейчас наша таблица маршрутизации выглядит так:
R00#show ip route
      10.0.0.0/8 is variably subnetted, 2 subnets, 3 masks
S        10.0.0.0/8 [1/0] via 100.100.100.101
C        10.0.0.0/24 is directly connected, GigabitEthernet0/1
L        10.0.0.1/32 is directly connected, GigabitEthernet0/1
      100.0.0.0/8 is variably subnetted, 2 subnets, 2 masks
C        100.100.100.0/24 is directly connected, GigabitEthernet0/2
L        100.100.100.100/32 is directly connected, GigabitEthernet0/2

Вроде хорошо. Новый маршрут на 100.100.100.101 не применяется для 10.0.0.3, так как его маска /8 намного короче, чем /24 у connected интерфейса. Но вдруг Gi0/1, содержавший next hop для 3.1.1.0/24, по какой-то непонятной причине ушел в down, и его connected маршрут пропал из RIB.
%LINK-5-CHANGED: Interface GigabitEthernet0/1, changed state to administratively down
%LINEPROTO-5-UPDOWN: Line protocol on Interface GigabitEthernet0/1, changed state to down
RT: interface GigabitEthernet0/1 removed from routing table
RT: del 10.0.0.0 via 0.0.0.0, connected metric [0/0]
RT: delete subnet route to 10.0.0.0/24
RT: del 10.0.0.1 via 0.0.0.0, connected metric [0/0]
RT: delete subnet route to 10.0.0.1/32
IP-ST(default):  updating GigabitEthernet0/1

Вот что стало:
R00#show ip cef 3.1.1.0 detail
3.1.1.0/24, epoch 0
  recursive via 10.0.0.3
    recursive via 10.0.0.0/8
      recursive via 100.100.100.101
        recursive via 100.100.100.0/24
          attached to GigabitEthernet0/2

Ой. Теперь пакеты на сеть 3.1.1.0/24 идут куда-то не туда. Я не могу представить себе сценарий, когда ожидаемое поведение статического маршрута – переключение на другой интерфейс. Если за тем интерфейсом находится резервный путь, то все-таки надо создавать еще один статический маршрут…

Что делать? Указывать сразу в маршруте интерфейс. Пересоздадим маршрут:
R00(config)#no ip route 3.1.1.0 255.255.255.0 10.0.0.3
R00(config)#ip route 3.1.1.0 255.255.255.0 Gi0/1 10.0.0.3

Поднимаем Gi0/1. Смотрим, куда теперь ведет маршрут на 3.1.1.0/24:
R00#show ip route 3.1.1.0
Routing entry for 3.1.1.0/24
  Known via "static", distance 1, metric 0
  Routing Descriptor Blocks:
  * 10.0.0.3, via GigabitEthernet0/1
      Route metric is 0, traffic share count is 1

Тут уже указан интерфейс. Поэтому не будет рекурсивных запросов к таблице маршрутизации. Проверяем FIB:
R00#show ip cef 3.1.1.0
3.1.1.0/24
  nexthop 10.0.0.3 GigabitEthernet0/1

Да, никакого «recursive». А если снова погасить gi0/1? Маршрут исчез.
R00#show ip route 3.1.1.0
% Network not in table

R00#show ip cef 3.1.1.0
0.0.0.0/0
  no route

И это притом, что маршрут до 10.0.0.3 все еще был:
R00#show ip cef 10.0.0.3
10.0.0.0/8
  nexthop 100.100.100.101 GigabitEthernet0/2

А что будет, если путь к next hop даст маршрут по умолчанию, а маршрут на 3.1.1.0/24 не ссылается на интерфейс?
R00(config)#no ip route 10.0.0.0 255.0.0.0 100.100.100.101
R00(config)#ip route 0.0.0.0 0.0.0.0 100.100.100.101
R00(config)#no ip route 3.1.1.0 255.255.255.0 Gi0/1 10.0.0.3
R00(config)#ip route 3.1.1.0 255.255.255.0 10.0.0.3
R00#show ip route 3.1.1.0
% Network not in table
R00#show ip cef 3.1.1.0 detail
0.0.0.0/0, epoch 0, flags default route
  recursive via 100.100.100.101
    recursive via 100.100.100.0/24
      attached to GigabitEthernet0/2

Обратите внимание, что первой строкой после «show ip cef» идет «0.0.0.0/0», а не «3.1.1.0/24». Несмотря на то, что next hop формально есть, по факту все итерации опроса таблицы маршрутизации (кроме первой) игнорируют маршрут по умолчанию, что логично, иначе любой запрос к таблице маршрутизации почти всегда бы резолвился (под «резолвиться» понимается нахождение интерфейса, в который нужно отправить пакет). Поэтому наш статический маршрут отсутствует, но пакеты все равно улетают к Gi0/2. Вроде бы все то же самое, что и без явного указания интерфейса? Не совсем. Допустим, протоколу маршрутизации сказали «redistribute static». Если статический маршрут пропал, то анонс тоже отзывается. А если нет, то маршрутизатор продолжит говорить всем «туда идти через меня», и это почти наверняка обернется L3 кольцом для префикса 3.1.1.0/24, который мог бы быть доступен откуда-нибудь еще. Но стоп, мы договаривались не трогать динамический роутинг…

А что если в статическом маршруте указать интерфейс, но не указывать IP адрес следующего хопа? Ответ: в случае Ethernet, если на next hop не отключен proxy arp, связность не нарушится, но роутеру может ОЧЕНЬ поплохеть. Подробнее. Если сказать «ip route 3.1.1.0 255.255.255.0 gi0/1», то ничего особо страшного не случится, даже пару сотен записей в arp таблице любой роутер переварит (и существуют сценарии-workaround’ы, в которых оптимальным решением является именно такой костыль), но вот «ip route 0.0.0.0 0.0.0.0 gi0/1» на пограничном маршрутизаторе наверняка убьет его. Потому запомните общее правило: если создается статический маршрут с next hop’ом на Ethernet интерфейсе, то его IP адрес должен указываться всегда. Исключения – только когда вы очень хорошо представляете себе, что делаете, зачем делаете и почему нельзя сделать иначе.

И напоследок, сделаем одну очень нехорошую штуку.
R00(config)# ip route 3.1.1.0 255.255.255.0 10.0.0.3
R00(config)#ip route 10.0.0.3 255.255.255.255 3.1.1.1

Первый маршрут в порядке, сто раз протестирован. А вот второй странный – он ведет через первый. А первый теперь ссылается на второй, и у нас бесконечная рекурсия. Вот что произошло:
IP-ST(default): updating same distance on 3.1.1.0/24
IP-ST(default):  3.1.1.0/24 [1], 10.0.0.3 Path = 8, no change, not active state
IP-ST(default):  3.1.1.0/24 [1], 10.0.0.3 Path = 2 3 7
RT: updating static 3.1.1.0/24 (0x0):
    via 10.0.0.3
RT: add 3.1.1.0/24 via 10.0.0.3, static metric [1/0], add succeed, active state
IP-ST(default): updating same distance on 10.0.0.3/32
IP-ST(default):  10.0.0.3/32 [1], 3.1.1.1 Path = 8, no change, not active state
IP-ST(default):  10.0.0.3/32 [1], 3.1.1.1 Path = 2 3 7
RT: updating static 10.0.0.3/32 (0x0):
    via 3.1.1.1
RT: add 10.0.0.3/32 via 3.1.1.1, static metric [1/0], add succeed, active state

Добавилось успешно. Но затем в дебагах высветилось:
RT: recursion error routing 3.1.1.1 - probable routing loop
RT: recursion error routing 10.0.0.3 - probable routing loop

И появилась запись в лог с severity 3:
%IPRT-3-RIB_LOOP: Resolution loop formed by routes in RIB

R00#show ip cef 10.0.0.3 detail
10.0.0.3/32, epoch 0
  Adj source: IP adj out of GigabitEthernet0/1, addr 10.0.0.3 359503C0
   Dependent covered prefix type adjfib cover 10.0.0.0/24
  1 RR source [no flags]
  recursive via 3.1.1.1, unresolved
  recursive-looped

R00#show ip cef 3.1.1.0 detail
3.1.1.0/24, epoch 0, flags cover dependents
  Covered dependent prefixes: 1
    notify cover updated: 1
  recursive via 10.0.0.3, unresolved
  recursive-looped

Однако, RIB никакого криминала не видит:
Routing entry for 3.1.1.0/24
  Known via "static", distance 1, metric 0
  Routing Descriptor Blocks:
  * 10.0.0.3
      Route metric is 0, traffic share count is 1

R00#show ip route 10.0.0.3
Routing entry for 10.0.0.3/32
  Known via "static", distance 1, metric 0
  Routing Descriptor Blocks:
  * 3.1.1.1
      Route metric is 0, traffic share count is 1

Вывод – никогда так не делайте.

Почему статический маршрут может не попасть в таблицу маршрутизации?


Любой сетевик должен сходу дать одно из объяснений, касающееся любого источника маршрутов в IOS: существует другой маршрут на тот же самый префикс, но с меньшим AD (все помнят Administrative Distance?). Маршрут, источник которого – “connected”, всегда имеет AD=0, и ни один другой источник маршрутов не может привнести ничего ниже, чем «1», даже статический маршрут с явным указанием интерфейса. Пример connected:
R00# show ip route
C        10.0.0.0/24 is directly connected, GigabitEthernet0/1

Т.е. пока интерфейс Gi0/1 находится в состоянии up и имеет адрес из подсети 10.0.0.0/24, ни один статический маршрут на этот префикс в таблице маршрутизации не появится.

Еще есть вариант «разные источники маршрутов добавляют маршруты на один и тот же префикс с одинаковым AD». Поведение IOS в данном случае не документировано, общая рекомендация – «никогда так делайте».

Но посмотрим другие, менее очевидные примеры. Например, статические маршруты можно создать со словом «permanent», которое переводится как «постоянный», и тогда они будут всегда висеть в таблице маршрутизации. Правильно? Нет.

Добавляем его и смотрим:
R00(config)#ip route 3.1.1.0 255.255.255.0 10.0.0.3 permanent
R00#show ip cef 3.1.1.0
3.1.1.0/24
  nexthop 10.0.0.3 GigabitEthernet0/1

Кладем Gi0/1, и видим:
R00#show ip cef 3.1.1.0
3.1.1.0/24
  unresolved via 10.0.0.3

В RIB он есть, и другие протоколы маршрутизации могут его использовать:
R00#show ip route 3.1.1.0
Routing entry for 3.1.1.0/24
  Known via "static", distance 1, metric 0
  Routing Descriptor Blocks:
  * 10.0.0.3, permanent
      Route metric is 0, traffic share count is 1

А теперь, не поднимая Gi0/1:
R00(config)#no ip route 3.1.1.0 255.255.255.0 10.0.0.3 permanent
R00(config)#ip route 3.1.1.0 255.255.255.0 10.0.0.3 permanent

Просто пересоздали его, ничего не меняя. И вот что произошло:
IP-ST(default): updating same distance on 3.1.1.0/24
IP-ST(default):  3.1.1.0/24 [1], 10.0.0.3 Path = 8, no change, not active state
IP-ST(default): cannot delete, PERMANENT

R00#show ip route 3.1.1.0
% Network not in table
R00#show ip cef 3.1.1.0
0.0.0.0/0
  no route

Постоянный, говорите? Нет. Есть один маленький нюанс: чтобы перманентный маршрут навеки вписался в таблицу маршрутизации, нужно, чтобы он хотя бы на долю секунды резолвился. Хотя какое еще «навеки»? Когда он остался висеть в воздухе без резолвящегося интерфейса, достаточно сказать «clear ip route *» или тем более «reload», чтобы он исчез из RIB.

Но продолжим. Сделаем вот так:
R00(config)#ip route 3.1.1.0 255.255.255.0 Gi0/1 10.0.0.3
R00(config)#ip route 3.1.1.10 255.255.255.255 3.1.1.1

Вроде нормальные маршруты. Что произойдет? Со вторым – ровным счетом ничего.
IP-ST(default):  3.1.1.10/32 [1], 3.1.1.1 Path = 8, no change, not active state
IP-ST(default):  3.1.1.10/32 [1], 3.1.1.1 Path = 2 3 6 8, no change, not active state

Суть вот в чем. Допустим, есть маршрут на X.X.X.X через Y.Y.Y.Y. Мы добавляем маршрут на X1.X1.X1.X1 (этот префикс полностью покрывается X.X.X.X) через X2.X2.X2.X2 (а он тоже покрывается X.X.X.X). IOS делает закономерный вывод: второй маршрут не несет в себе никакой новой информации и совершенно бесполезен, поэтому его можно не устанавливать в RIB.

А теперь финт ушами.
R00(config)#no ip route 3.1.1.10 255.255.255.255 3.1.1.1
R00(config)#ip route 3.1.1.10 255.255.255.255 Gi0/1 3.1.1.1

IP-ST(default): updating same distance on 3.1.1.10/32
IP-ST(default):  3.1.1.10/32 [1], GigabitEthernet0/1 Path = 1
RT: updating static 3.1.1.10/32 (0x0):
    via 3.1.1.1 Gi0/1
RT: network 3.0.0.0 is now variably masked
RT: add 3.1.1.10/32 via 3.1.1.1, static metric [1/0], add succeed, active state
IP ARP: creating incomplete entry for IP address: 3.1.1.1 interface GigabitEthernet0/1
IP ARP: sent req src 10.0.0.1 30e4.db16.7791,
                 dst 3.1.1.1 0000.0000.0000 GigabitEthernet0/1

R00#show ip cef 3.1.1.10
3.1.1.10/32
  nexthop 3.1.1.1 GigabitEthernet0/1

И вот это подводит нас к еще одному важному моменту. Указание интерфейса в статическом маршруте позволяет обойти многие проверки, так как статическому маршруту больше не требуется выполнять рекурсивные запросы к RIB в поисках пути до next hop, и при своем добавлении он не заденет триггеры на других маршрутах. Но это не отменяет главного требования: next hop обязан резолвиться в конкретный интерфейс, а тот интерфейс обязан быть в up. Тот факт, что рекурсивных запросов к RIB больше не будет, означает, что указанный IP адрес next hop’а находится прямо за интерфейсом, и наверняка отзовется на arp запрос (с точки зрения роутера). Если у соседнего по Gi0/1 роутера включен proxy arp, то он в ответ на arp запрос наверняка вернет свой mac адрес, и всё будет хорошо. Разве что лишняя запись в arp таблице…

Но все равно так делать не стоит.

Необходимо упомянуть и о еще одном важном моменте. Статический маршрут должен по идее исчезнуть из таблицы маршрутизации, как только он перестанет резолвиться. Но на практике есть множество ситуаций, когда next hop пропадает, но при этом статический маршрут на какое-то время остается. К примеру, когда next hop резолвится через маршрут, полученный от протокола динамической маршрутизации. Все дело в том, что процесс, отслеживающий наличие next hop в RIB, не всегда может получить уведомление об исчезновении маршрута, и он вынужден периодически (раз в 60 секунд по умолчанию) перепроверять, все ли хорошо. Это вызовет заметную задержку сходимости сети.

Поменять интервал проверки, к примеру, на 10 секунд можно с помощью команды:
ip route static adjust-time 10
Дмитрий @JDima
карма
9,0
рейтинг 0,0
Реклама помогает поддерживать и развивать наши сервисы

Подробнее
Спецпроект

Самое читаемое Администрирование

Комментарии (53)

  • 0
    Спасибо, много интересных вещей для себя нашел.
  • 0
    Спасибо за интересную статью. Теперь я понял, что не все знаю про статическую маршрутизацию, есть над чем подумать.
  • 0
    Спасибо, очень познавательно про CEF.

    Ещё интересные вещи происходят с обычной десктопной Windows (пусть будет 7):
    1. ПК имеет одно подключение к интернету, дефолт через шлюз, других маршрутов нету (кроме коннектед). Если подключиться к VPN и VPN сервер отдаст дефолт через тоннель, то новый маршрут запишется в таблицу с меньшей метрикой, чем основной, но при этом связь не пропадёт и VPN будет работать, а вот все остальные соединения отвалятся. VPN тоже может отвалиться через какое-то время, потом установится заново.
    Я не особо разбирал эту тему, но, скорее всего, в винде используется некое подобие fast switching и при отправке первого пакета создаётся запись с указанием правильного исходящего интерфейса, со временем эта запись устаревает.
    Вывод — в push route (в cisco называется split tunneling) не отдавать дефолт.
    2. Практический случай случай: отвалился интернет в филиале, на месте есть человек, который может подключиться к местной сети, воткнуть в ноут 3g модем и дать удалёнку. Если он сначала подключится по 3g и запустит Teamviewer и после этого подключится к местному вайфаю, то новый дефолт (через неработающий шлюз) также станет приоритетным, но существующее соединение не оборвётся.

    Вообще Windows в таких случаях считает новый маршрут более приоритетным (если смотреть на метрику). Но может отправлять пакеты совершенно непредсказуемо, например, в случае 2 может ничего не сработать, если сначала подключаться к сети без выхода в интернет. А может и сработать.

    У Mikrotik есть такая вещь, как pseudobridge. Частично иммитируется функционал бриджинга, но без объединения в единый бродкаст домен, фактически это взаимодействие на L3.
    Девайс за таким «бриджем» посылает arp в поисках шлюза, микротик ему отдаёт свой мак и делает для этого девайса запись ip-mac. При отправке трафика во «внешний» бродкаст-домен подставляет свой мак, для обратного трафика смотрит в сделанную запись и меняет dst-mac на нужный. А чтоб послать первый пакет из «внешнего» бродкаст домена во «внутренний», надо прописать статическую arp запись с указанным IP микротика.
    • +1
      Если подключиться к VPN и VPN сервер отдаст дефолт через тоннель

      Винда запоминает, через что началось соединение, и будет до упора держать его. Но не стоит сильно полагаться на этот механизм…
      У Mikrotik есть такая вещь, как pseudobridge.

      Похоже на proxy arp у циски. Если получен arp запрос на адрес, который есть в таблице маршрутизации, то возвращаем запрашивавшему свой мак и маршрутизируем дальнейшие пакеты по FIB. Правда, никаких дополнительных записей не создается (зачем?).
      • 0
        Несколько подзабыл — pseudobridge используется в беспроводной сети, так можно подключить сегмент сети по беспроводному аплинку.
    • 0
      Про Микротик — подозрительно похоже на proxy arp.

      Damn, опередили)
  • +1
    Недавно наткнулся на описание работы маршрутизации в современных версиях Windows, тоже довольно интересно и расходится со старыми учебниками:
    blogs.technet.com/b/networking/archive/2009/04/24/source-ip-address-selection-on-a-multi-homed-windows-computer.aspx
  • 0
    Качественно написано, пОлно. Да, CEF надо понимать, иначе будет много сюрпризов. debug ip packet например при включенном CEF ничего или почти ничего не покажет.
    • 0
      Как тогда с включенным CEF дебажить пакеты?
      • 0
        1) Локальный capture. Есть под CEF на всех ISR и Catalyst платформах.

        2) Сделать ACL вида:
        10 permit host A host B log
        20 permit ip any any
        Это process switch'ит попавший под первую запись пакет, и там, где локальный capture не работает с CEF (Nexus например), трафик посниффить удастся.

        Да и вообще, debug ip packet — самый унылый способ анализа трафика из всех.

        Ах да — локальный трафик у железки всегда process switch'ится, так что ему CEF не помеха.
  • +1
    Начал читать статью и понял кто автор…
    спасибо.
    • 0
      Аналогично, с первых строк)
      И в отличие от других случаев, эта фраза — комплимент автору.
  • 0
    Те неточности, что я увидел
    «Наверняка кто-то скажет «из списка локальных интерфейсов», и жестоко ошибется. Маршрутизация так не работает.»

    На мой взгляд, человеческая логика так не работает. На основании чего можно брать из списка локальных интерфейсов? Я вот не представляю. Здесь напрашивается только один вывод — запрос к таблице маршутизации — и потом послать arp запрос в соответсвии с ответом

    "(хотя у process switching’а множество недостатков помимо неоптимальных запросов – например, постоянное переключение шедулера CPU между контекстами, что весьма затратно)"

    Насколько я помню, в IOS платформе нет вытесняющей многозадачности. И нет постоянного переключения CPU между контекстами. Основкым преимуществом CEF была особая структура данных (mtrie), которая позволяет быстро давать нужный ответ — куда пихать пакет (что позволяет в обработчике прерывания обрабатывать пакеты), а process switching — такой структуры нет, и таблица маршрутизации не оптимизирована — то есть на каждый пакет выясняется в какой адрес интерфейс пихать, какие L3 и/или L2 заголовки применять и т.д. и т.п.

    • 0
      На основании чего можно брать из списка локальных интерфейсов?

      Я сам не знаю. Но нередко слышал такое мнение. И людей реально удивляет, что на самом деле там речь про рекурсивные запросы к тому же самому RIB!
      Насколько я помню, в IOS платформе нет вытесняющей многозадачности. И нет постоянного переключения CPU между контекстами.

      Я даже специально нашел цитату из книги «Cisco IP Routing: Packet Forwarding and Intra-domain Routing Protocols», автор на тот момент работал инженером эскалации TAC, и явно знает матчасть :) Книжка старая, но не думаю, что с тех времен архитектура IOS стала примитивнее.
      Скрытый текст
      Why so many switching methods? Why not just go with process switching? We could, if we were not interested in router performance. The main problem with process switching is that the structure of the main routing table in Cisco IOS is not very optimal for fast forwarding—although very convenient for routing protocol operations—and that the packet-processing flow includes too many steps. Consider the following rough outline of events when a packet is received and forwarded by the IP switching process.

      1. The I/O controller buffers the frame and sends an IRQ to the CPU.
      2. The CPU interrupts the currently running process, changes the execution context, and passes control to the interrupt handler.
      3. The interrupt handler takes the buffer from the controller, performs basic checks of the frame, identifies the network protocol, stores the buffer in the corresponding processing queue, and returns control to the interrupted code.
      4. The CPU gives control back to the interrupted process.
      5. The next time it checks the queue of the pending processes, the IOS scheduler changes the execution context and gives control to the IP switching process, which takes the buffer out of the queue.
      6. The IP switching process performs such functions as IpInput(), IpForward(), and IpOutput() and checks the state of the interface output queue. If it is free and the output controller's TX queue is not full, the buffer is submitted directly to the controller; otherwise, it is enqueued into the interface output queue.
      7. If the packet has been enqueued into the interface output queue, the router waits for an interrupt from the controller and submits the buffer on it.

      In multitasking operating systems, a very expensive task is changing the execution context, whether it is a software or hardware interrupt or process scheduling. The reason is when control is given to another task, a huge number of instructions are carried out to preserve all registers, load the new task's context, and so on. In addition, the CPU memory cache is most probably invalidated. Because of the significant overhead, forwarding packets at the interrupt level when they have just been received might sound reasonable, but the functions used at the process level cannot be just cut and pasted into the code of the interrupt handler. The interrupt handling routines are a special type of code, which needs to be very fast and compact in order to minimize the possibility of nested and lost interrupts, as well as to leave enough time for other tasks. To achieve these characteristics, interrupt handlers are usually coded in a low-level programming language, such as assembler. In addition, performance is increased through use of sophisticated data-processing methods that store and find information more efficiently: information caching, hash functions, radix trees, and so on.
      • 0
        Хотя есть одна мысль про «На основании чего можно брать из списка локальных интерфейсов?».
        Возможно, человеческая логика цепляется за «интерфейс уходит в down, маршрут пропадает — следовательно, маршрут завязывается на интерфейс». Многие ведь действительно не сталкивались с тем, что железка может внезапно найти next hop где-то на стороне.
        • 0
          Вот тут и непонятно — как маршрут может завязываться на интерфейс, когда интерфейс вот в таком случае, например, невидно: ip route 10.0.0.0 255.255.255.0 10.1.1.1
          И тут логика должна судорожно начать работать, выясняя — каким образом, зная только 10.1.1.1 можно выяснить в какой интерфейс бросить arp запрос. (или уж во все бросать — что уж мелочиться)
          • 0
            Логика-то должна, но не всегда какие-то детали вызывают срабатывание триггера под названием «почему это так?» :)
            К написанию этой статьи меня сподвиг данный топик. По словам автора, многие были удивлены тем, что указание ethernet интерфейса без адреса в качестве next hop может быть смертельно опасно…
            Более того, даже гуру временами совершают идиотские ошибки.

            Так что… Для вас очевидно, что интерфейс получается из рекурсивного запроса к RIB. Для меня тоже. Но поспрашивать сетевиков, многие наверняка в недоумении вытаращатся на вас, они просто никогда не задумывались над тем, откуда берется интерфейс.
            Проведите эксперимент, попытайтесь получить точный ответ на вопрос «почему area 0 в OSPF должна быть непрерывной», на уровне обработки LSA ABR'ом. Потом уточните, какое условие должно выполняться, чтобы роутер считал себя ABR. Наверняка тоже удивитесь.
            • 0
              А, кстати, почему зона 0 должна быть непрерывной? В RFC про это не сказано.
              Рискну предположить, что ABR отбрасывает LSA 3 типа и выше, если не имеет LSA 1 про Advertising Router.

              Насчёт условия считания себя ABR в RFC написано, что просто должен принадлежать нескольким зонам. Хотя в Cisco надпись «It is an area border router» не появится, пока не дашь ему ещё и интерфейс в 0 зоне.
              • 0
                А, кстати, почему зона 0 должна быть непрерывной?

                Потому что в ином случае что-то наверняка не будет работать как надо.
                ABR отбрасывает LSA 3 типа и выше, если не имеет LSA 1 про Advertising Router.

                Нет. Думайте дальше :)
                Насчёт условия считания себя ABR

                Я немного криво сформулировал вопрос… Перефразирую: при каком условии роутер ведет себя так, что что-то ломает в предыдущем вопросе?
              • 0
                И еще: В RFC2328 как раз сказано «The backbone must be contiguous».
                • 0
                  Разумеется, как и в 100500 других источников, которые можно нагуглить. Только вот почему — не написано.
                  • +1
                    А ответ дан в blog.ine.com/wp-content/uploads/2011/01/Loop-Prevention-in-OSPF.pdf.
                    Если у роутера есть интерфейс в area 0 (да хоть лупбек), он начинает генерировать LSA 3.
                    Если у роутера есть поднятое соседство в area 0, он начинает игнорировать LSA 3, пришедшие не от соседей по area 0.
                    То есть если есть два островка area 0, в каждом из которых хотя бы пара роутеров, и между островками другая area — они не будут обмениваться LSA 3. Но наличие лупбека в area 0 ничего сломать не должно.
                    Вот и весь ответ :)

                    Вообще, читайте blog.ine.com, там море бесценной информации.
                    • 0
                      О, классная pdfка, не натыкался на неё там.
                      Спасибо!
                      • 0
                        О да. Лопухов — убергик, и пишет прекрасные вещи.

                        pavelsh, вот видите? Судя по огромному количеству правильных ответов на вроде бы простой вопрос — никто даже не задумывался над тем, что конкретно мешает нарушить «аксиому» о непрерывности area 0. Хотя по идее этим надо было заинтересоваться сразу же, как только узнаешь, что OSPF может работать в нескольких областях.
                    • 0
                      у меня только один вопрос — а зачем это может понадобиться? зачем это делать именно так? =)
                      p.s. да вы просто мастер в вопросах: как сломать циску и чтобы не сразу было понятно в чем тут дело =) Хотя, конечно, при внимательном изучении такой конфигурации у человека появиться вопрос — а зачем было располагать магистральную зону на островке, когда как тупиковая зона была бы куда логичнее.
                      • 0
                        1) Если вы не понимаете шестеренки, благодаря которым работает протокол, вы время от времени будете косячить, а также не сможете выдумывать простые и эффективные решения. Например, есть две довольно крупные области, между ними надо гонять трафик, и они пересекаются на одном из роутеров, который не принадлежит к area 0 (а еще и на ABR само собой). И по каким-то причинам нельзя подтащить area 0 поближе к точке их пересечения. Как оптимизировать передачу данных между ними, чтобы пакеты не делали крюк? Ответ — просто создать лупбек и поместить его в area 0.
                        2) Backbone может развалиться и в результате несчастного случая. Надо точно понимать, чем именно это чревато, а не просто слепо следовать «так делать нельзя, фу-фу-фу».
                        • 0
                          пока еще не читал пдф, нет времени. Но в сложных случаях предпочитаю использовать ibgp, там больше свободы, хоть и немного сложнее.
                          • 0
                            iBGP действительно усложнит конфигурацию. И это не отменяет необходимость понимать IGP. Что может быть базовее, чем «почему area 0 должна быть непрерывной»? Ведь вроде простейший вопрос, верно? :)

                            Я предпочитаю считать, что сетевик должен уметь не только нажимать кнопки строго по инструкции, но и понимать, что у технологии под капотом.
                            • 0
                              Я и не спорил, что человек не должен понимать принципы и алгоритмы, но зачастую от вендора к вендору еще и добавляются разные тонкости реализации, что в итоге несет свои нюансы, желательно все же придерживаться простой и понятной схемы. Ведь даже статическую маршрутизацию умудрились обвязать еще каким-то CEF, ну что за кровавый энтерпрайз?
                              • 0
                                Если человек работает в многовендорной среде, то он обязан понимать нюансы реализации одного и того же на всём железе всех вендоров.
                                «Строго по стандарту» — это обычно значит «убого». Любой вендор стремится разработать что-то своё, лучшее, чем стандарт. Хотя бы потому, что это усложняет жизнь клиенту, решившему перейти на другого вендора.
                                • +2
                                  Понимать то он обязан, но порой он об этих нюансах(я про недокументированные) узнает в процессе эксплуатации, что не всегда хорошо.
                                  image
      • 0
        Да, согласен с вышеприведенной цитатой. Ничего в ней не противоречит моему знанию классической Cisco IOS. Это я не подумал, что прием каждого пакета порождает прерывание само по себе.
        Только смотря на те процессоры, что стоят в старых циско, кажется мне что там не все так драматично, как в современных (вот в современных процессорах переключение контекста — действительно операция мощная). Ну тактов 300-400 на переключение контекста тратиться то точно.
        • 0
          Ну ISRы никогда особо не отличались высокой производительностью… Для гигабитов трафика все равно берут хардварные платформы, где в нормальной ситуации никакой транзитный трафик ни при каких обстоятельствах не заденет ЦП, и уж тем более не будет пунтиться в process switching.
          • 0
            Я не буду говорить про новые аппаратные платформы, но в 3550 когда выжиралась внутренняя память ASIC-а, те маршруты (и/или) ACL падали на процессор, который тут же умирал под трафиком.

            • 0
              То же самое в 3560 и 3750. Ресурс называется TCAM. В логах при этом что-то вроде (случай, когда tcam выжрали аксесс листы)

              %ACLMGR-4-ACLTCAMFULL: ACL TCAM Full. Software Forwarding packets on Output label 10 on L3 L2

              Ну и есть вещи, которые реализованы изначально только софтверно. Например, на 3560 можно замутить gre тунель. Он даже будет работать, но примерно мегабит через него убьет девайс, если память не изменяет. Убьет в смысле управления и тех вещей, что работают софтверно (icmp, arp).
              • 0
                Убьет в смысле управления

                Перегруженный CPU на каталисте — это очень печально по той причине, что на том CPU живут и STP, и протоколы маршрутизации. Может начаться расколбас, когда у железки не останется сил слать кипалайвы.
                • 0
                  Вообще же, если говорить про азы маршрутизации, у других вендоров может быть радикально иной взгляд даже на базовые вещи.

                  Из мануала на телесин (преференс у телесина это та же дистанция для циски — AD).

                  1. The router inspects the preference value of each candidate route and selects
                  the route with the lowest preference value.

                  2. If multiple routes share the lowest preference value, then the router inspects
                  the metric value of each of these routes and selects the route with the lowest
                  metric.

                  3. If multiple routes share the lowest preference and metric values, then the
                  router inspects the mask of each of these routes and selects the route with
                  the longest mask.

                  Т. е. более специфичный статический маршрут (более узкая маска) не перекороет более широкий, но с лучшей дистанцией. Для циски же это будет просто маршрут на другую сеть.
                  Большой был в свое время сюрприз и неприятный в смысле последствий неверной настройки.
                  • 0
                    Само собой я писал только про поведение IOS, причем конкретного IOS, и я наверняка много интересного пропустил (просто такие детали обычно не публикуют и часто меняют). Можно написать по аналогичного размера топику про реализацию той же статики у любого другого вендора.
                    Ну и да, Cisco, конечно, создает «стандарты», но кто-то их игнорирует, потому надобно тщательно изучать документацию прежде, чем начинать работать с новой железкой.
  • 0
    Эта статья была нужна! Теперь мне есть на что сослаться в следующем выпуске СДСМ.
    • 0
      Рад помочь :)
  • 0
    Топик надо было назвать: особенности статической маршрутизации в Cisco, все же циско — хоть и законодатель моды, но далеко не единственная фирма, выпускающая сетевое оборудование. Да и CEF — это чисто цискинная фича. Или еще можно было топик назвать как: как можно сломать циске мозг при включенном cef =)
    Кстати ASR 1к — это разве не софт роутеры?
    Больше всего меня волновало в аппаратных платформах циски — это в каких случаях внесение изменений в конфигурацию требует еще каких-либо действий. Например при изменении содержимого некоторых ACL — требуется его убрать с интерфейса и снова добавить, а лучше создать новый ACL и навесить его, а старый удалить. Это из самого простого… Бывалого инженера этим не удивишь, а вот новичка легко в панику бросает, особенно забавно, когда в конфигурацию добавляешь одно, а при чтении конфигурации — видишь совершенно другое (те же активные ACL в isg на 7200, к примеру)… Это так, мысли вслух, вдруг кто захочет статью написать =)
    • 0
      Топик надо было назвать

      Наверное, да… Хотя вроде я ясно дал понять, что статья моновендорная.
      Кстати ASR 1к — это разве не софт роутеры?

      Нет. Там отдельная логика отвечает за передачу пакетов.
      Это так, мысли вслух, вдруг кто захочет статью написать

      Вряд ли… 7200 EOL. Современные аппаратные платформы с точки зрения конфигурирования по мере сил унифицируют с программными, они стали очень похожи.
  • 0
    Еще есть вариант «разные источники маршрутов добавляют маршруты на один и тот же префикс с одинаковым AD». Поведение IOS в данном случае не документировано, общая рекомендация – «никогда так делайте».

    насколько я помню, если 2 процесса с измененным AD (на одинаковое значение) борются за попадание в таблицу маршрутизации, то IOS смотрит на AD до изменения…
    • 0
      И впрямь, документировано. Не под IOS, но все же.
      You can change the administrative distances for routes discovered by or redistributed into a routing protocol. If two routes from two different routing protocols have the same administrative distance, then the route with the lower default administrative distance is entered into the routing table. In the case of EIGRP and OSPF routes, if the EIGRP route and the OSPF route have the same administrative distance, then the EIGRP route is chosen by default.

      А если два процесса OSPF или два процесса EIGRP предлагают один и тот же префикс? Говорят, что в случае OSPF выигрывает тот, кто раньше влез в RIB, а у EIGRP — тот, у кого ниже номер AS. Только тут я не видел официального подтверждения.
      • 0
        несправедливо, однако :)
        • 0
          Почему?
          Есть очень серьезные и вполне объективные причины, по которым у distance vector протокола должно быть максимально низкое AD. Ну ладно, на RIP всем плевать, но EIGRP и сейчас считается чем-то серьезным.
          • 0
            я про то, что у OSPF остается тот кто раньше пришел, а у EIGRP по номеру AS.
  • 0
    Еще есть интересный corner case в случае когда маршрут бывает 'connected' и с AD=1. Вроде в статье была оговорка про это. Но на всякий случай если будет интересно статья от конкурентов INE:
    blog.ipexpert.com/2012/07/09/old-ccie-myths-static-route-to-the-interface/
  • 0
    IOS создал маршрут, и сразу послал arp запрос в поисках next hop, который у нас – 10.0.0.3.


    Первый пакет отбрасывается, и роутер посылает arp запрос с целью узнать mac адрес 10.0.0.3, если он ранее не был известен. CEF же всегда заранее узнает mac адрес next hop'а.


    Тащемта дела обстоят так только в 15 IOS, сделайте уж сносочку, что в 12 при добавлении маршрута создаётся запись в FIB с ссылкой на valid glean adjacency (некст хоп указан, но не разрезолвен), затем если под этот префикс попадает пакет, резолвиться next-hop и создаётся valid cached adjacency, которая уже будет висеть, грубо говоря, до скончания веков.
    Другое дело если вы до этого nex-hop уже разрезолвили (пинговали или ещё как — случайным бродкастом), то у него уже будет adjacency на момент добавления маршрута, и запись в FIB уже создаться со ссылкой на имеющуюся adjacency.

    Что касаемо,
    Я не могу представить себе сценарий, когда ожидаемое поведение статического маршрута – переключение на другой интерфейс
    — вы же сами далее пишите, что стат маршрут может ссылаться на nex-hop получаемый через IGP. Довольно элегантный вариант, на мой взгляд, при ряде условий, и может вылиться как раз в переключение на другой интерфейс. Пример — отсутвие доступа к удаленному маршрутизатору для добавления сети находящейся за ним в анонс IGP.
    • 0
      Тащемта дела обстоят так только в 15 IOS

      По-моему, и в 12-х ветках уже немало времени было такое же поведение (если мы говорим о каталистах). Но проверю.
      Говорить о поведении 12-х веток для роутеров в рамках этой статьи было бы странно, из продакшна они уже потихоньку начинают исчезать. И я не ставил себе целью рассказать о CEF глубже чем по самым верхам (кроме меня про существование CEF вообще никто из авторов статей не вспоминал).
      Да и в начале я написал "… на IOS линейки 15.2M. Поведение других ОС может различаться".
      Пример — отсутвие доступа к удаленному маршрутизатору для добавления сети находящейся за ним в анонс IGP.

      Это как раз из разряда «я не могу представить себе такой сценарий». В академических целях пример остроумный, на практике — если на роутере сломали aaa, то новая сеть обождет, есть более важная проблема
      [из подвала раздаются вопли того, кто внес изменение в настройки aaa, не проверив сразу же его корректность в отдельной сессии]
      • 0
        Говорить о поведении 12-х веток для роутеров в рамках этой статьи было бы странно, из продакшна они уже потихоньку начинают исчезать.

        Ну до исчезания ещё лет 5, я думаю, многие еще 15 и не щупали, и это оправданно по крайней мере с точки зрения затрат на переход.

        И я не ставил себе целью рассказать о CEF глубже чем по самым верхам (кроме меня про существование CEF вообще никто из авторов статей не вспоминал).

        Ну ставили не ставили, а по факту утверждаете, что вот оно отличие CEF`а, хотя по факту это отличие 15ого IOS`а.

        если на роутере сломали aaa, то новая сеть обождет, есть более важная проблема

        Ну нет же. Скорее, в dualhomed/multihomed BGP когда uplink провайдеры анонсируют вам дефолт и directed connected AS, а вам хотелось бы добавить ещё и маршрут на сеть находящуюся за directed connected AS (за два хопа от вас), что бы соптимизировать роутинг.
        • 0
          в dualhomed/multihomed BGP когда uplink провайдеры анонсируют вам дефолт и directed connected AS

          Такого не встречал. Обычно дают просто дефолт, хотя, наверное, договориться можно. Если есть и другие, уникальные для каждого провайдера префиксы, то можно создать по статике с треками, отслеживающими наличие каждого из префиксов. Чуть больше конфигурации, но зато более прозрачная схема.
          • 0
            Можно и с треками, но с next-hop через IGP элегантней :-)

Только зарегистрированные пользователи могут оставлять комментарии. Войдите, пожалуйста.