Сети для самых маленьких. Часть 2: Ethernet
В первой части мы разобрали, что сетевой стек — матрёшка из заголовков, и что самый внешний слой в ней, канальный, доставляет данные соседу по кабелю. Сегодня — о самом распространённом канальном протоколе: Ethernet. По нему работают и домашняя розетка, и порт коммутатора в стойке, и 400-гигабитные линки между дата-центрами, и даже Wi-Fi притворяется им перед операционной системой.
Ethernet придумал Роберт Меткалф в Xerox PARC в 1973 году для сети из одного толстого коаксиального кабеля, к которому подключались все машины офиса. С тех пор сменилось всё: кабель, скорость, топология, электроника. Не изменился только формат кадра, и это самое поучительное в его истории.
Кадр
Кадр Ethernet в том виде, в каком его видит tcpdump, выглядит так:
байты: 6 6 2 46…1500 4
┌────────────┬──────────┬────────┬───────────────┬─────┐
│ MAC │ MAC │ Ether │ данные │ FCS │
│ получателя │ отправи- │ Type │ (IP-пакет, │ │
│ │ теля │ │ ARP, …) │ │
└────────────┴──────────┴────────┴───────────────┴─────┘
└───── заголовок, 14 байт ───────┘
Перед кадром в кабель уходят ещё 8 байт, которых программы никогда не видят: преамбула — семь байт 10101010, по которым приёмник подстраивает тактовую частоту, и разделитель начала кадра (SFD) 10101011, последняя единица которого говорит «дальше заголовок». После кадра — межкадровый интервал (IFG) в 96 битовых интервалов, то есть пауза длиной в 12 байт, чтобы приёмник успел обработать принятое. На гигабите это 96 наносекунд.
По полям:
- MAC получателя — первым, чтобы сетевая карта и коммутатор могли отбросить чужой кадр, не дочитывая его до конца.
- MAC отправителя — его коммутатор использует для обучения, об этом ниже.
- EtherType — то самое поле «что внутри» из первой части:
0x0800— пакет IPv4 и0x86DD— пакет IPv6, два поколения сетевого уровня (части 5–6 и 13);0x0806— ARP, запрос «какой MAC у этого IP-адреса» (часть 7);0x8100— тег VLAN с номером виртуальной сети (часть 17);0x8863/0x8864— PPPoE, сессия абонента у провайдера (часть 4). Есть тонкость: если значение меньше или равно0x05DC(1500), это не тип, а длина данных, и перед нами кадр старого формата IEEE 802.3 с заголовком LLC внутри. Сегодня в таком формате ходят разве что служебные кадры STP. Всё остальное — Ethernet II с EtherType, который начинается с0x0600. - Данные — от 46 до 1500 байт. Если IP-пакет короче 46 байт (а SYN без опций — это 40), сетевая карта дописывает нули до 46. Отсюда в
tcpdumpпоявляются кадры длиной 60 байт для пакетов, которым хватило бы 54: это паддинг. Верхняя граница 1500 — это и есть MTU Ethernet, о который мы будем спотыкаться всю серию. - FCS — контрольная сумма CRC-32 по всему кадру от заголовка до данных. Считает и проверяет сетевая карта. Если не сошлась, кадр молча выбрасывается: Ethernet не сообщает отправителю об ошибках и ничего не повторяет. Повторять — работа TCP, восемью частями позже. Единственный след — счётчик
rx_crc_errorsв статистике интерфейса; его стоит смотреть, когда «сеть работает, но медленно».
Итого минимальный кадр — 64 байта (14 + 46 + 4), максимальный — 1518 (14 + 1500 + 4). С VLAN-тегом, который вставляется между MAC отправителя и EtherType, на четыре байта больше. Некоторые сети разрешают jumbo-кадры с данными до 9000 байт, но это не стандарт, а договорённость: все устройства на пути должны быть настроены одинаково, иначе кадр пропадёт без следа.
Запомните число 64: ниже станет понятно, откуда оно взялось.
MAC-адрес
Шесть байт, записываются в шестнадцатеричном виде через двоеточие или дефис: 3c:52:82:1a:2b:3c. Адрес прошит в сетевую карту производителем и должен быть уникальным в мире, хотя на самом деле операционная система может подставить любой.
Первые три байта — OUI (Organizationally Unique Identifier), код производителя, который тот покупает у IEEE: 3c:52:82 — Hewlett Packard, 00:50:56 — VMware, b8:27:eb — Raspberry Pi. По OUI Wireshark пишет рядом с адресом имя производителя, а по нему же можно понять, что за устройство появилось в сети. Оставшиеся три байта производитель раздаёт сам.
Два младших бита первого байта имеют особый смысл:
первый байт адреса: x x x x x x U I
│ │
│ └── I/G: 0 — индивидуальный, 1 — групповой
└──── U/L: 0 — глобальный (от производителя), 1 — локальный
- I/G. Если младший бит 1, это групповой адрес, и кадр предназначен не одной карте, а всем, кто подписан. Частный случай — широковещательный
ff:ff:ff:ff:ff:ff: его принимают все. Групповые адреса IPv4-multicast начинаются с01:00:5e, IPv6 — с33:33; с ними встретимся в частях про ARP и Neighbor Discovery. - U/L. Если второй бит 1, адрес назначен локально, а не производителем. На практике это значит, что вторая шестнадцатеричная цифра —
2,6,aилиe:02:42:ac:11:00:02— контейнер Docker,52:54:00:…— виртуальная машина QEMU, а телефоны и ноутбуки со случайным MAC-адресом в Wi-Fi тоже ставят этот бит.
У каждого интерфейса машины свой MAC-адрес. Посмотреть: ip link на Linux, ipconfig /all на Windows. Сменить на Linux можно одной командой, ip link set eth0 address 02:00:00:00:00:01, и это законный приём, например, когда провайдер привязал услугу к MAC-адресу старого роутера.
Откуда взялись 64 байта: разделяемая среда и коллизии
Исходный Ethernet — один коаксиальный кабель на всех. Передаёт одна станция, слышат все, и две станции одновременно передавать не могут: сигналы наложатся и получится мусор. Нужен способ делить кабель. Он называется CSMA/CD — Carrier Sense Multiple Access with Collision Detection, и работает так:
- Хочешь передавать — послушай кабель. Занят — жди, пока освободится, плюс межкадровый интервал.
- Свободен — передавай и продолжай слушать. Если принимаешь не то, что передаёшь, значит, кто-то начал одновременно с тобой: коллизия.
- Заметив коллизию, передай ещё 32 бита мусора (jam), чтобы её наверняка заметили все, и прекрати.
- Подожди случайное время и повтори с шага 1. Случайное время — это
rслот-таймов, гдеrвыбирается от 0 до 2ⁿ − 1,n— номер попытки (не больше 10). После 16 попыток кадр выбрасывается. Это называется экспоненциальной отсрочкой: чем больше столкновений, тем шире разброс и тем меньше шанс столкнуться снова.
А теперь главное. Коллизию можно заметить, только пока ты ещё передаёшь. Если станция A на одном конце кабеля закончила передавать кадр раньше, чем до неё дошёл сигнал станции B с другого конца, A решит, что всё прошло удачно, а кадр на самом деле испорчен. Значит, передача должна длиться не меньше, чем сигнал идёт до самого дальнего конца кабеля и обратно.
Для Ethernet на 10 Мбит/с максимальный диаметр сети с повторителями задали около 2500 метров, двойной пробег сигнала с задержками на электронике уложили в 512 битовых интервалов, это и есть слот-тайм, 51,2 микросекунды. 512 бит — 64 байта. Кадр короче 64 байт дополняется нулями не из любви к круглым числам, а чтобы отправитель гарантированно успел заметить коллизию.
На 100 Мбит/с битовый интервал в десять раз короче, и диаметр сети пришлось сократить до ~200 метров. На гигабите в полудуплексе кадр пришлось бы растягивать до 512 байт, поэтому гигабитный полудуплекс не прижился совсем. Сегодня коллизий не существует нигде, кроме старого оборудования, и всё же число 64 живёт во всех стандартах Ethernet, потому что менять формат кадра дороже, чем носить с собой историю.
Хабы, которые ещё можно встретить в старых шкафах, — это тот же общий кабель в коробке: сигнал с одного порта повторяется на все остальные. Все устройства за хабом — один домен коллизий.
Коммутатор
Коммутатор (switch) заменил общий кабель. Каждый порт — отдельный кабель до одного устройства, и коммутатор пересылает кадр только туда, куда нужно. Чтобы знать, куда нужно, он ведёт таблицу MAC-адресов: соответствие адреса и порта, за которым этот адрес видели.
Алгоритм помещается в четыре правила:
- Обучение. Пришёл кадр на порт — запомнить: MAC-адрес отправителя живёт за этим портом. Запись живёт по умолчанию 300 секунд с последнего кадра от этого адреса, потом удаляется (aging).
- Пересылка. Посмотреть MAC получателя в таблице. Нашёлся — отправить кадр в тот порт, и только в него.
- Флуд. Не нашёлся (unknown unicast), или адрес широковещательный, или групповой — отправить во все порты, кроме того, с которого кадр пришёл.
- Фильтрация. Если адрес получателя живёт за тем же портом, с которого кадр пришёл, не пересылать никуда.
Проследим на примере. Три машины подключены к портам 1, 2 и 3, таблица пуста, коммутатор только что включён.
┌─────────────────┐
A aa:…:01 ── 1 ────┤ ├──── 3 ── C cc:…:03
│ коммутатор │
B bb:…:02 ── 2 ────┤ │
└─────────────────┘
| Шаг | Событие | Таблица после | Куда ушёл кадр |
|---|---|---|---|
| 1 | A шлёт кадр для C | aa:…:01 → порт 1 |
адрес C неизвестен: флуд в порты 2 и 3 |
| 2 | C отвечает A | aa:…:01 → 1, cc:…:03 → 3 |
адрес A известен: только в порт 1 |
| 3 | A снова шлёт C | без изменений | только в порт 3 |
| 4 | B шлёт широковещательный кадр | добавлен bb:…:02 → 2 |
во все порты, кроме 2 |
Машина B на шаге 1 получила чужой кадр, а на шаге 3 — уже нет. Это и даёт коммутатору его главные свойства: каждый порт — свой домен коллизий, два разговора между разными парами портов идут одновременно, и чужой unicast-трафик на порт не приходит. А широковещание по-прежнему приходит всем: коммутатор не делит домен широковещания, этим занимаются роутеры и VLAN (часть 17).
Пара технических деталей, которые пригодятся:
- Коммутатор, который принимает кадр целиком, проверяет FCS и только потом пересылает, называется store-and-forward; это норма. Cut-through начинает пересылать, прочитав только MAC получателя: быстрее на доли микросекунды, но пропускает битые кадры дальше.
- Таблица MAC-адресов конечна: от нескольких тысяч записей в домашних устройствах до сотен тысяч в стоечных. Если её переполнить (старая атака MAC flooding — засыпать коммутатор кадрами с случайными адресами отправителя), коммутатор перестаёт обучаться и флудит всё подряд, то есть превращается в хаб.
- Коммутатор не меняет в кадре ничего. Ни MAC-адреса, ни EtherType, ни данные. Это главное отличие от роутера, который снимает заголовок Ethernet целиком.
На Linux коммутатор есть в ядре, это bridge, и его таблицу можно посмотреть:
$ bridge fdb show br br0
3c:52:82:1a:2b:3c dev eth0 master br0
02:42:ac:11:00:02 dev veth1 master br0
33:33:00:00:00:01 dev eth0 self permanent
Записи permanent — адреса самого моста и групповые адреса, которые он обязан принимать. На Cisco то же самое — show mac address-table, на MikroTik — /interface bridge host print.
Дуплекс и автосогласование
Витая пара, пришедшая на смену коаксиалу, решила проблему коллизий радикально: в кабеле есть отдельные пары проводов для передачи и приёма. У 10BASE-T и 100BASE-TX их две (контакты 1–2 передают, 3–6 принимают), и если на другом конце не хаб, а коммутатор или вторая машина, обе стороны могут передавать одновременно. Это полный дуплекс: CSMA/CD выключен, коллизий нет по построению, скорость в каждую сторону полная.
Но у 100-мегабитных карт есть и полудуплекс, для совместимости с хабами, и обе стороны линка должны договориться. Для этого есть автосогласование: при поднятии линка каждая сторона посылает пачки импульсов (FLP, fast link pulses), в которых закодировано, что она умеет: 10 или 100 Мбит/с, полу- или полный дуплекс. Выбирается лучший общий вариант.
Классическая ошибка, которую стоит знать даже сегодня, — duplex mismatch. Админ прибил на коммутаторе порт жёстко в 100/full, а сервер оставил в auto. Сервер не получает FLP, по форме сигнала определяет скорость 100 Мбит/с (parallel detection), а вот дуплекс узнать ему неоткуда, и стандарт велит в этом случае выбирать полудуплекс. Линк поднимается, ping ходит, а под нагрузкой сервер видит коллизии там, где их быть не может, обрывает передачу, коммутатор получает обрубки кадров и считает их ошибками CRC. Симптомы: скорость в десятки раз ниже ожидаемой, растут late collisions на одной стороне и CRC errors/runts на другой. Лечение одно: либо auto с обеих сторон, либо жёстко с обеих.
Гигабит эту историю закрыл: в 1000BASE-T автосогласование обязательно, полудуплекс практически не реализуют, и ethtool покажет такую картину:
$ ethtool eth0
Settings for eth0:
Supported link modes: 10baseT/Half 10baseT/Full
100baseT/Half 100baseT/Full
1000baseT/Full
Speed: 1000Mb/s
Duplex: Full
Auto-negotiation: on
Link detected: yes
Если здесь неожиданно Speed: 100Mb/s на гигабитной карте, это чаще всего кабель: для гигабита нужны все четыре пары, и достаточно одного плохого контакта в разъёме, чтобы автосогласование откатилось на 100 Мбит/с по двум парам.
В полном дуплексе есть свой механизм притормаживания — flow control: приёмник, не успевающий разгребать буфер, шлёт кадр PAUSE на групповой адрес 01:80:c2:00:00:01 с EtherType 0x8808 и временем, на которое отправитель должен замолчать. Домашние коммутаторы обычно включают его по умолчанию, в дата-центрах чаще выключают: пауза останавливает весь порт, а не одно соединение, и один медленный получатель тормозит всех.
Физика: что в кабеле
Чтобы ориентироваться в названиях. Формат имени — <скорость>BASE-<среда>: BASE означает передачу в основной полосе без модуляции на несущую, буквы после дефиса — среда.
| Стандарт | Среда | Пары | Дальность | Как кодируется |
|---|---|---|---|---|
| 10BASE-T | витая пара Cat3 | 2 | 100 м | манчестерский код, 1 бит = 1 переход |
| 100BASE-TX | Cat5 | 2 | 100 м | 4B/5B + MLT-3, три уровня сигнала |
| 1000BASE-T | Cat5e | 4, обе стороны по каждой | 100 м | PAM-5, пять уровней, 250 Мбит/с на пару |
| 2.5G/5GBASE-T | Cat5e/Cat6 | 4 | 100 м | как 10GBASE-T на меньшей частоте |
| 10GBASE-T | Cat6a | 4 | 100 м | PAM-16, кодирование LDPC |
| 1000BASE-SX / 10GBASE-SR | многомодовое волокно | — | 300–550 м | лазер 850 нм |
| 1000BASE-LX / 10GBASE-LR | одномодовое волокно | — | 10 км | лазер 1310 нм |
На гигабите интересный трюк: все четыре пары передают в обе стороны одновременно, и каждая сторона вычитает из принятого сигнала свой собственный (эхоподавление). Поэтому для гигабита нужен весь кабель, а для 100 Мбит/с хватало половины — именно на этом держались старые «разветвители на два компьютера из одного кабеля».
Второй трюк гигабита — auto MDI-X: порт сам определяет, какие пары у соседа передающие, и при необходимости меняет их местами. Перекрёстные кабели (crossover) для соединения двух компьютеров напрямую ушли в прошлое вместе со 100 Мбит/с.
Оптика в коммутаторах живёт в сменных модулях SFP (1 Гбит/с), SFP+ (10), SFP28 (25), QSFP28 (100): в порт можно вставить модуль под нужное волокно и расстояние, и Ethernet от этого не меняется. Для дома и офиса достаточно знать: витая пара до 100 метров, дальше или оптика, или ещё один коммутатор.
Петли и STP
Соедините два порта одного коммутатора кабелем. Или два коммутатора — двумя кабелями «для надёжности». Первый же широковещательный кадр уйдёт в оба кабеля, вернётся через второй, снова уйдёт в оба, и так до бесконечности: у Ethernet нет поля TTL, и кадр, попавший в петлю, будет ходить по ней, пока не выдернут кабель. Через секунду в петле крутятся тысячи копий, порты светятся сплошным светом, а таблица MAC-адресов сходит с ума: один и тот же адрес отправителя видят то на одном порту, то на другом (MAC flapping). Сеть лежит целиком. Это называется широковещательный шторм, и это самый простой способ уронить офис одним кабелем.
Защита от петель — протокол STP (Spanning Tree Protocol, 802.1D) и его быстрая версия RSTP (802.1w). Коммутаторы обмениваются служебными кадрами BPDU раз в две секунды (те самые кадры формата 802.3 с LLC), выбирают корневой коммутатор с наименьшим идентификатором, вычисляют кратчайший путь от каждого коммутатора до корня и блокируют все остальные порты между коммутаторами. Получается дерево без циклов; если рабочий линк падает, заблокированный порт открывается, у STP на это уходит 30–50 секунд, у RSTP — секунды. Резервные кабели между коммутаторами — это нормально, но только когда STP включён и настроен; на домашних коммутаторах без управления его обычно нет, и там петля — просто петля.
Смотрим руками
Статистика интерфейса, в том числе счётчики ошибок:
$ ip -s link show eth0
2: eth0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc fq_codel state UP mode DEFAULT group default qlen 1000
link/ether 3c:52:82:1a:2b:3c brd ff:ff:ff:ff:ff:ff
RX: bytes packets errors dropped missed mcast
9876543210 8765432 0 0 0 123456
TX: bytes packets errors dropped carrier collsns
1234567890 2345678 0 0 0 0
Ненулевые errors на приёме, collsns на передаче на полнодуплексном линке или растущие rx_crc_errors в ethtool -S eth0 — повод смотреть на кабель, разъём и настройки дуплекса.
Кадры с заголовком Ethernet:
$ sudo tcpdump -i eth0 -n -e -c 3
12:00:00.000001 3c:52:82:1a:2b:3c > ff:ff:ff:ff:ff:ff, ethertype ARP (0x0806), length 42: Request who-has 192.168.1.1 tell 192.168.1.10, length 28
12:00:00.000250 d8:47:32:0a:0b:0c > 3c:52:82:1a:2b:3c, ethertype ARP (0x0806), length 60: Reply 192.168.1.1 is-at d8:47:32:0a:0b:0c, length 46
12:00:00.000300 3c:52:82:1a:2b:3c > d8:47:32:0a:0b:0c, ethertype IPv4 (0x0800), length 74: 192.168.1.10.51234 > 203.0.113.10.443: Flags [S], ...
Здесь всё, о чём была статья: широковещательный адрес получателя в первом кадре, EtherType, который говорит «внутри ARP», и длина 60 во втором кадре — это паддинг до минимальных 64 байт (tcpdump не считает FCS, поэтому показывает 60). Первый кадр показан длиной 42, потому что захвачен на отправителе до того, как сетевая карта дописала нули.
В Wireshark раскройте строку Ethernet II любого кадра: там адреса с именами производителей по OUI, биты I/G и U/L прямо в разборе адреса и EtherType с расшифровкой.
Что запомнить
- Кадр: 14 байт заголовка (два MAC-адреса и EtherType), 46–1500 байт данных, 4 байта CRC. Минимум 64 байта, максимум 1518. Данные больше 1500 — MTU — в кадр не помещаются.
- MAC-адрес: 3 байта производителя и 3 байта номера; младший бит первого байта отличает групповой адрес, следующий — локально назначенный.
ff:ff:ff:ff:ff:ffпринимают все. - 64 байта — наследие общего кабеля и CSMA/CD: кадр должен длиться дольше двойного пробега сигнала, чтобы заметить коллизию.
- Коммутатор учит таблицу по адресам отправителей, пересылает по адресам получателей, флудит неизвестное и широковещание, не меняет в кадре ни байта.
- Полный дуплекс убрал коллизии; duplex mismatch — когда одна сторона в auto, другая жёстко.
- Петля без STP кладёт сеть: у кадра нет TTL.
Дальше — Wi-Fi: почему радио не может работать как Ethernet, CSMA/CA и подтверждения, каналы и помехи, как клиент подключается к точке и что происходит при четырёхстороннем рукопожатии WPA2.
Оставить комментарий могут только зарегистрированные пользователи.
Войдите на сайт или зарегистрируйтесь, чтобы оставить комментарий.