Кодирование на физическом уровне Ethernet PHY
Электроника как Хобби, 9 мар 2020 Владимир Кисиль
Так уж получилось, что мы не можем просто передать двоичный сигнал по витой паре… хотя передать-то мы можем, а вот получить на другом конце нет. Банально потому что невозможно отличить несколько логических единиц или нулей подряд от отсутствия сигнала. Поэтому на физическом уровне двоичный сигнал кодируется, а затем модулируется.
Чтобы проверить это утверждение подключимся осциллографом к нашему роутеру и настроим соединение.
При соединении двух устройств по ethernt соединение начинает работать со скоростью самого медленного устройства. А так как мы условились рассматривать только 10Base-T, то для начала эксперимента нужно настроить скорость интерфейсов. В *nix системах это делается одной командой в консоли
# ethtool -s enp0s25 speed 10 autoneg off
Далее нам нужно как-то увидеть передаваемый сигнал на осциллографе. Для этого я снял изоляцию с витой пары, нашел в ней оранжевый и бело-оранжевый провод, и снял изоляцию с них. Провода оказались многожильными. Чтобы в таком виде витая пара прослужила дольше, провода были залужены.
- подключение осциллографа
В Ethernet используется дифференциальные сигналы. Это означает, что земли в витой паре как таковой нет. Сигнал передается по паре проводов. По одному проводу идет некий сигнал, а во второму — обратный к нему, инвертированный сигнал. Помимо прочего, такой способ передачи информации обеспечивает повышенную устойчивость к помехам.
Есть и некоторая сложность в наблюдении дифференциальных сигналов так как нельзя подключить один щуп осциллографа к одной линии, а второй — к другой, потому что мы получим короткое замыкание между линиями. Для измерения таких сигналов используют специальные дифференциальные пробники, как на фото ниже.
- активный высоковольтный дифференциальный пробник HDP50
Стоимость таких пробников приближается к стоимости самого осциллографа, поэтому есть определенный резон сделать его самому, чем мы и займемся в ближайшем будущем.
Фазовая манипуляция
Внимание на осциллограмму, это реальный сигнал 10Base-T, но без нагрузки и помех соответственно, поэтому форму сигнала можно считать почти идеальной.
Измеренный дифференциальный случайный сигнал 10Base-T без нагрузки
Видите эти «полочки» ? Это изменение фазы сигнала, или фазовая манипуляция.
По «научному» она называется BPSK или двоичная фазовая манипуляция с частотой несущей 10МГц или периодом 100 наносекунд.
- пример манипуляции BPSK
BPSK это одна из самых простых PSK фазовых манипуляций, где модуляция осуществляется смещением несущего сигнала на π, а значит имеет всего два возможных перехода π и 2π, и передает всего один бит на символ : 0 или 1.
Поколдуем в графическом редакторе, теперь наша осциллограмма приобретает читаемый вид, и может быть преобразована к двоичному коду. Но это еще не всё, такой двоичный сигнал нужно еще декодировать, чтобы извлечь исходную информацию.
Манчестерское кодирование
Для кодирования информации в Ethernet используется алгоритм разработанный в университете Манчестера и впервые использованный на практике в 1949 для кодирования информации для вычислительной машины Манчестерский Марк I. То есть он реально старый и все еще востребованный из-за своей простоты и эффективности
В отличии от обычных логических уровней кодирующих единички и нолики высоким и низким напряжением, в манчестерском кодировании используется не напряжение, а восходящие и нисходящие фронты сигнала. Помимо прочего, такой подход интересен тем, что он не нуждается в отдельном проводе для передачи тактового сигнала. Все, что нужно для синхронизации передающей и принимающей стороны, содержится в самом сигнале, то есть он является самосинхронизируемым.
Существует несколько вариантов кода манчестера:
Вариант № 1 (по Томасу): логический ноль кодируется перепадом напряжения с низкого уровня на верхний уровень, а логическая единица кодируется перепадом напряжения с верхнего уровня на нижний.
Вариант № 2 (стандарт IEEE 802.4, стандарт IEEE 802.3): логический ноль кодируется перепадом напряжения с верхнего уровня на нижний, а логическая единица кодируется перепадом напряжения с низкого уровня на верхний уровень. Непосредственно используется в Ethernet.
Вариант № 3 (дифференциальное манчестерское кодирование, разностное манчестерское кодирование, IEEE 802.5): логический ноль кодируется изменением состояния в начале значащего интервала, а логическая единица кодируется сохранением предыдущего уровня.
Обратите внимание, что единички и нолики передаются с фиксированной скоростью.
Поскольку искать единички и нолики на осциллограмме довольно утомительно, я поискал и нашел скрипт для выгрузок с осциллографов Rigol, делающий за нас эту рутинную работу. Вам потребуется установить среду интерпретатора python для их запуска.
Благодаря скрипту мы можем увидеть весь Ethernet-фрейм в бинарном виде:
# Преамбула занимает 8 байт. Помимо прочего, она может быть # использована для калибровки часов на принимающей стороне. 10101010 10101010 10101010 10101010 10101010 10101010 10101010 10101011 # MAC-адрес получателя: E4:95:6E:43:42:7F # Важно! Используется порядок бит lsb-first. 00100111 10101001 01110110 11000010 01000010 11111110 # MAC-адрес отправителя: 0E:18:77:10:72:DC 00000111 00011000 11101110 00001000 01001110 00111011 # Тип пакета: 08 00, означает IPv4 # https://en.wikipedia.org/wiki/EtherType#Examples 00010000 00000000 # Полезная нагрузка: от 46 до 1500 байт, # в данном случае - 84 байта. 10100010 00000000 00000000 00101010 # ... и так далее, см payload.dat # Контрольная сумма фрейма: 00010001 # 0x88 10100110 # 0x65 00101001 # 0x94 00000111 # 0xE0
Контрольная сумма является самым обыкновенным CRC32 и вычисляется от всего фрейма за исключением преамбулы и, понятно, самой контрольной суммы. Скрипт сохраняет соответствующие данные в отдельном бинарном файле, благодаря чему контрольную сумму очень легко проверить:
$ crc32 frame.date 0946588
Как видите, контрольная сумма сходится, только порядок байт в Ethernet используется обратный.
Также скрипт сохраняет в отдельном файле полезную нагрузку фрейма. Его при желании можно открыть в Wireshark. Для этого полезную нагрузку нужно перевести из бинарного формата в текстовый:
$ od -Ax -tx1 -v payload.dat > payload.hex
а затем воспользоваться диалогом File → Import from Hex Dump. В выпадающем списке Encapsulation type выбираем Raw IPv4.
У нас получилась чертовски насыщенная информацией статья, которую мы в скором времени проверим на практике. Надеюсь она вас не утомила