2. История способов обработки трафика

Сейчас с Forwarding Plane всё отлично: 10 Гб/с, 100 Гб/с — не составляют труда — плати и пользуйся. Любые политики без влияния на производительность. Но так было не всегда. В чём сложности?

В первую очередь это вопрос организации вышеописанных трактов: что делать с электрическим импульсом из одного кабеля и как его передать в другой — правильный.

Для этого на сетевых устройствах есть букет разнообразных чипов.

Это пример интерфейсной платы Cisco

Так, например, микросхемы (ASIC, FPGA) выполняют простые операции, вроде АЦП/ЦАП, подсчёта контрольных сум, буферизации пакетов.

Ещё нужен модуль, который умеет парсить, анализировать и формировать заголовки пакетов. И модуль, который будет определять, куда, в какой интерфейс, пакет надо передать. Делать это нужно для каждого божьего пакета. Кто-то должен также следить и за тем, можно ли этот пакет пропускать вообще. То есть проверить его на предмет подпадания под ACL, контролировать скорость потока и отбросить, если она превышена.

Сюда же можно вписать и более комплексные функции трансляции адресов, файрвола, балансировки итд.

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

Чем это грозит понятно: производительность будет падать тем сильнее, чем больше трафика устройство должно перемалывать и чем больше функций мы будем вешать на него. Поэтому одна за другой большинство функций были делегированы на отдельные чипы. И из обычного x86-сервера маршрутизаторы превратились в специализированные сетевые коробки, набитые непонятными деталями и интерфейсами. А Ethernet-хабы переродились в интеллектуальные коммутаторы.

Функции по парсингу заголовков и их анализу, а также поиску выходного интерфейса взяли на себя ASIC, FPGA, Network Processor. Обработка в очередях, обеспечение QoS, управление перегрузками — тоже специализированные ASIC. Такие вещи, как стейтфул файрвол, остались на ЦПУ, потому что количество сессий несъедобное.

Другой вопрос: мы где-то должны хранить таблицы коммутации. В чём-то быстром. Первое, что приходит в голову — это классическая оперативная память. Проблема с ней в том, что обращение к ней идёт по адресу ячейки, а возвращает она уже её содержимое (или контент, не по-русски если). Однако входящий пакет несёт в себе никак не адрес ячейки памяти, а только MAC, IP, MPLS. Тогда бы нам пришлось иметь некий хэш алгоритм, который, задействуя CPU, высчитывал бы адрес ячейки и извлекал оттуда нужные данные. Вот только пропускная способность порта в 10 Гб/с означает, что CPU должен передавать 1 бит каждые 10 нс. И у него есть порядка 80 мкс, чтобы передать пакет размером в один килобайт.

Впрочем, вычисление хэша — алгоритм очень простой, и любой мало-мальски уважающий себя ASIC с этим справится. Инженерам был адресован вопрос — а что дальше делать с хэшем? Так появилась память CAM — Content Addressable Memory. Её адреса — это хэши значений. В своей ячейке CAM содержит или ответное значение (номер порта, например) или чаще адрес ячейки в обычной RAM.

То есть пришёл Ethernet-кадр, ASIC'и его разорвали на заголовки, вытащили DMAC — прогнали его через CAM и получили вожделенный исходящий интерфейс. Подробнее о CAM дальше.