======Обработка по быстрому маршруту====== Упрощенная картинка обработки пакета по быстрому маршруту //(кликабельно)//: {{doc:mk:1923kx028:1923kx028_flowfast.png}} =====Блок EMAC===== Блок EMAC принимает пакет от внешнего PHY и передает в блок GPI. Параметры EMAC: * Поддерживаются интерфейсы MII/GMII/SGMII. * Блок имеет FIFO размером 128 х 32bit, что помогает при ретрансляции при плотном трафике. * Имеет счетчики статистики - сколько чего принято/передано, ошибки и т.д. =====Блок GPI===== Каждый блок EMAC работает в паре со своим блоком GPI. Параметры GPI: * 64 - битная шина доступа к периферии * Независимые RX и TX каналы * FIFO_RX и FIFO_TX //(Возможно FIFO имеют достаточную длину для размещения пакета максимальной стандартной длины. Т.к. в спецификации написано, что GPI при отправке сохраняет пакет в своем FIFO, затем освобождает буферы LMEM, и только затем выдает пакет в EMAC для отправки через PHY. Но данное поведение не относится к Jambo фреймам, которые очевидно в FIFO не влезут, и поэтому пакет будет подкачиваться на лету из LMEM в FIFO по мере выдачи пакета в линию. Вероятно с частью RX поведение аналогичное.)// UPD: По некоторым данным, длина FIFO_RX составляет 2Кбайта. ====GPI_RX==== * Принимает пакет из связки "PHY - EMAC_FIFO" в свое FIFO_RX. * Начинает передавать пакет в буферы LMEM когда: * В FIFO находится весь пакет, или * Заполненность FIFO превысила порог, заданный регистром GPI_DRX_FIFO * Записывает пакет в цепочку буферов LMEM: * Запрашивает буферы у BMU для размещения пакета в памяти LMEM * Формирует цепочки буферов * Программирует смещения в буферах * По окончании записи пакета в буферы, в заголовок первого буфера записывает RX_STATUS: * Длину пакета * Статус переполнения FIFO при работе GPI. * Статус периферии (ARC Hit, MCAST, BCAST etc.) * Указатель на следующий буфер. * PORT_SRC - Номер MAC с которого пришел пакет. (Используется классификатором для обновления соответствия "//МАС источника// - //Порт//" в таблице маршрутизации МАС.) * Адрес первого буфера записывается во входную очередь Classifier для обработки. * GPI готов к приему следующего пакета. Если в памяти LMEM нет свободных буферов и BMU не может вернуть адрес свободного буфера, то GPI некуда передать данные из своего FIFO. Тогда GPI выдерживает паузу прежде чем запросить новый буфер. Ожидается, что за это время буфер может освободиться - его освободит GPI от другого ЕМАС порта. Пауза задается в количествах тактов частоты ядра в регистре GPI_RX_CONFIG, поле csr_alloc_retry_cycles [25:16]. Если трафик очень высокий, то может возникнуть переполнение FIFO. Данные фрейма в таком случае являются утерянными. Адрес буфера такого пакета все-равно передается в классификатор. Классификатор поймет, что пакет не полный по полю //"Статус переполнения FIFO"// в расширенном заголовке. //(Предположительно, классификатор по полям фрейма МАС и прочим, сможет обновить таблицу маршрутизации, но не будет дальше пересылать пакет. Количество отброшенных пакетов можно узнать чтением регистра GPI_CSR_OVERRUN_DROPCNT.)// =====Блок BMU===== Блок "разделяет" сплошную память LMEM на буферы определенной длины, по умолчанию 128 байт. Память под пакеты выделяется и освобождается такими буферами. С содержимым буферов работают прочие блоки. Например, блок GPI разделяет каждый буфер на заголовок и область под данные. В заголовке указывается указатель на следующий буфер и дополнительная информация. Таким образом буферы образуют цепь и могут хранить большие фреймы, например Jumbo фреймы. Но BMU про это ничего не знает, область его ответственности - это выделить буфер 128 байт и освободить буфер. =====Блок Classifier===== * Классификатор получает адрес первого буфера пакета в LMEM * Блок QB (Queuing) считывает первый буфер из LMEM в свою внутреннюю память. * Первый буфер пакета освобождается * Обработка пакета: * Классификация * Модификация пакета. По спецификации это: * //пометка QoS// * //L2 NAT, openvswitch, ebtables// * //организация цепочек сессий// * //вставка SNAP (предназначено для реализации шифрования LAN<-> WLAN)// * //реализация различных высокоскоростных протоколов хоста// * //PTP: IEEE 1588, 802.1AS// * //CFM: 802.1ag// * Обновление счетчика производительности * Блок RO (Re-Order) записывает пакет из внутренней памяти во второй буфер в LMEM * Адрес второго буфера записывается в блок TMU для отправки в соответствии с приоритетом Необходимо обратить внимание, что заголовок первого буфера в 48 байт используется для передачи RX_STATUS от GPI в классификатор. Поэтому только в этих блоках есть регистр AXI_GPI_HDR_SIZE, который определяет этот размер заголовка. Для всех последующих буферов заголовок составляет 16 байт и задается регистром LMEM_DATA_OFFSET, что говорит с какого смещения начинаются данные пакета после заголовка. Классификатор используется этот первый заголовок в 48 байт для обработки пакета. Классификатор может внести изменение в пакет, например снять или вставить тег VLAN. Поэтому GPI при сохранении пакета в память резервирует второй буфер для того, чтобы классификатор смог положить туда модифицированный пакет. Соответственно, после того как классификатор отработал, то первый буфер становится не нужен, поэтому классификатор сразу освобождает первый буфер. Отсюда следует то, что: * GPI_RX записывает в регистр INQ_PKTPTR классификатора адрес **первого буфера** (обозначен на картинке **FA**, FirstAddress) * Классификатор записывает в регистр INQ_PKTPTR блока TMU адрес **второго буфера** (обозначен на картинке **SA**, SecondAddress). TMU записывает в GPI_TX тоже SA. Модификации пакета, указанные в спецификации: * пометка QoS * модификация фрейма, предназначенная для L2 NAT, openvswitch, ebtables; * организация цепочек сессий; * вставка SNAP (предназначено для реализации шифрования LAN<-> WLAN); * реализация различных высокоскоростных протоколов хоста: * PTP: IEEE 1588, 802.1AS; * CFM: 802.1ag. Поскольку первый буфер был освобожден, то значение длины пакета, которое раньше хранилось в RX_STATUS, теперь передается классификатором в блок TMU через регистр TMU_PHY_INQ_PKTINFO. О содержимом заголовков буферов нет детальной информации. Но о некоторых составляющих можно судить по логу, полученному при инжекции пакета от Host процессора: {{doc:mk:1923kx028:kx028_hif_toport0.png}} По логу видно, что второй буфер тоже имеет заголовок в 48 байт, а кроме этого содержит заголовок описанный в п. 5.9.5 спецификации - //"Структура передаваемого пакета"//. ====Маршрутизация по таблицам МАС и VLAN==== Для обслуживания таблиц маршрутизации нужен внешний "Процессорный модуль" (PE - Processing Engine), далее называется Хост. Только Хост может добавлять/удалять/обновлять записи в данных таблицах. Сама микросхема 1928KX028 таблицы редактировать никак не может. В качестве Хоста, может выступать: * РС или процессор с драйвером под Linux, подключенный через PCIe (режим Mode1) * Микроконтроллер, подключенный через SPI (режим Mode2 - SlaveSPI) Чтобы Хост мог обслуживать таблицы, входящие пакеты должны пересылаться на хост - это называется PUNT. Пересылку пакетов на Хост назначает классификатор когда для этого есть причины. Причины по которым происходит захват пакета на Хост: * PUNT_MGMT - control frame from local host * PUNT_L2_SPECIAL - L2 protocol frame (e.g. STP BPDU) * PUNT_SA_MISS - SA miss in the MAC table, need to learn MAC * PUNT_SA_RELEARN - SA found on different port, need to relearn MAC * PUNT_SA_IS_ACTIVE - SA is active, need to set Fresh bit to zero * PUNT_SNOOP_UPPER - upper layer protocol snoop * PUNT_REQUESTED - action in MAC/BD table entry requested a punt //(**SA** -это Source MAC Address, **DA** - это Destination MAC Address)// Когда классификатор вычитывает в свою локальную память первый буфер с пакетом, то он проверяет наличие записей в таблицах маршрутизации для полей MAC_SRC и MAC_DEST данного пакета. ===Поиск по МАС_SRC:=== ^ Наличие МАС_SRC ^ PORT_SRC в PortList ^ Fresh bit ^ Реакция Классификатора ^ | + | + | 0 | Действий не требуется | | ::: | ::: | 1 | Требуется обновление записи, PUNT_SA_IS_ACTIVE | | + | - | x | Требуется переобучение, PUNT_SA_RELEARN | | - | х | x | Требуется обучение, PUNT_SA_MISS | //(х - значение не имеет влияния)// Очевидно, что если МАС источника нет в таблице МАС, то Хост должен добавить в таблицу запись о том, на каком порте находится данный МАС адрес. Если порт сменился, то данную запись необходимо обновить. Если же МАС запись в таблице уже есть и порт совпадает, то происходит проверка **устаревания фрейма**. Обработка устаревания производится программным обеспечением Хоста. Хост периодически, например раз в 5 минут, читает все активные записи в МАС таблице и далее: * Если бит Fresh не установлен, то бит Fresh устанавливается. Теперь, если за следующие 5 минут, не придет фрейма соответствующего данной записи, то алгоритм старения удалит запись. А если фрейм придет, то он будет послан на хост с признаком PUNT_SA_IS_ACTIVE и фунция обучения снимет бит Fresh. * Если бит Fresh установлен - то запись из таблице удаляется, т.е. снимается бит isActive. Значит за прошедшие 5 минут не пришло ни одного фрейма соответствующего записи таблицы. Иначе бы функция обучения в драйвере хоста сняла бит Fresh в записи при получении фрейма с признаком PUNT_SA_IS_ACTIVE. ===Поиск по МАС_DEST:=== Чаще всего, поиск по МАС_DEST необходим чтобы найти порты, на которые следует переслать пакет. Но помимо пересылки фрейма, можно настроить прочие действия с фреймом. Действия с фреймом задаются полями внутри записи в таблицах. Если же для фрейма нет записей в таблицах, то берется действие по умолчанию, которое настраивается в регистрах CLASS_GLOBAL_CFG[31:1] и CLASS_GLOBAL_CFG1[23:0]. ^ Наличие МАС_DEST ^ Наличие VLAN ^ Источник действий ^ | + | + | поле ActionFields таблицы МАС | | - | + | поле ACTIONS таблицы VLAN | | - | - | регистры CLASS_GLOBAL_CFG и CLASS_GLOBAL_CFG1 | Поле действие занимает 3 бита, значения в поле могут быть такие: ^ Значение поля ^ Описание ^ | 0: ACT_FORWARD | Пересылка пакета согласно Forward_list из записи в таблице MAC / VLAN / CLASS_GLOBAL_CFG | | 1: ACT_FLOOD | Рассылка (unicast) пакета согласно Forward_list из записи в таблице VLAN / CLASS_GLOBAL_CFG | | 2: ACT_PUNT | Пересылка пакета на Хост для обработки | | 3: ACT_DISCARD | Отбросить пакет | | 4: ACT_OVERRIDE | Действие берется из поля UNICAST_HIT_ACT записи таблицы VLAN / CLASS_GLOBAL_CFG1 | | 5: ACT_FWD_MASK | Пересылка в MAC Forward_list & VLAN Forward_list | | 6: ACT_COS_DISCARD | Сравнивается (1 << VLAN_PCP & CLASS_NPU_CTRL[31:24].csr_discard_cos_n ): | | ::: | ≠ 1 - Пакет рассылается согласно Forward_list из записи в таблице VLAN / CLASS_GLOBAL_CFG | | ::: | = 0 - Пакет отбрасывается (flood supression) | //(Здесь VLAN_PCP - это поле PCP внутри тэга VLAN обрабатываемого пакета. Пересылка по Forward_list исключает пересылку на порт, с которого принят фрейм.)// Поиск MAC_DEST и выбор действия для обработки пакета происходит по такому сценарию: {{doc:mk:1923kx028:1923kx028_actionstree.png}} Работая с таблицами, Хост сам задает необходимую реакцию на обработку фреймов. Это позволяет получить от микросхемы то, или иное поведение. Все что делает с таблицами Хост также может быть выполнено в режиме Mode2 внешним контроллером, подключенным по интерфейсу SPI. ===== MAC Table ===== На картинке показан случай, когда два фрейма имеют разные поля МАС и/или VLAN, но при этом функция вычисления HASH выдает одинаковый результат. В результате, при приходе нового фрейма с МАСх и VLANx, по вдресу Хэша в таблице маршрутизации МАС лежит не совпадающая с МАСх и VLANx запись. Поэтому аппаратура проверяет валидность флага коллизий и переходит по адресу в поле коллизий. В области коллизий поиск происходит по связному списку, пока не будет найдена запись со значениями МАСх и VLANx. * Если запись найдена, то происходит пересылка фрейма в список портов, указанных в записи. * Если запись не найдена, то запускается поиск по таблице VLAN Чтобы новая запись появилась в таблицах, ее должен туда прописать HOST контроллер (Драйвер РС через PCIe в режиме MODE_0 / Микроконтроллер через Slave-SPI в режиме MODE_2). {{doc:mk:1923kx028:1923kx028_tablemac_forwarding.png}} При инициализации таблицы все поля коллизий равны нулю. Связный список в поле коллизий должен прописать HOST контроллер перед началом работы! Флаги: * **isActive** - запись активна (1) / свободна (0) * **isValidCollision** - поле указателя коллизии валидно, можно переходить для поиска в область коллизий (1) / значение записи в области коллизии еще не назначено (0). * **isFresh** - запись устарела, была сброшена алгоритмом устаревания (1) / Запись активна, приход фрейма от источника с данными МАС и VLAN сбрасывают счетчик старения (0). * **isStatic** - запись активна всегда, на нее не действует счетчик старения (1) / Динамическая запись с устареванием (0). * **TC** //(Traffic Control)// - выбор маппирования для режима MACDA2TC (планирование очередей CoS - Class of Service). * **ActionFields** - действия с пакетом ACT_FORWARD .. ACT_COS_DISCARD * **ForwPortList** - выбор портов маской, куда пересылать пакет. В простейшем случае, это маска порта откуда пришел данный МАС. * //CutThrough - Некий режим модификации типа фрейма. Не используется.// * //rxPort - Вероятно, наследие прошлых версий. Не используется.// ===== VLAN Table ===== Поиск по VLAN таблице происходит аналогично поиску по MAC таблице. По сравнению с МАС таблицей, здесь другие поля в разделе Actions и отсутствует поле МАС адреса. {{https://startmilandr.ru/lib/exe/fetch.php/doc:mk:1923kx028:1923kx028_tablevlan.png}} Поля: * Forward list – список портов, которые входят в данный VLAN; битовая маска, в которой позиция бита соответствует номеру порта * Untag list – список портов, для которых с тегированных пакетов требуется снять VLAN тег; битовая маска, в которой позиция бита соответствует номеру порта * UnicastHit – действие, которое требуется выполнить с unicast пакетом, если адрес назначения найден в таблице MAC * UnicastMiss - действие, которое требуется выполнить с unicast пакетом, если адрес назначения не найден в таблице MAC * MulticastHit – действие, которое требуется выполнить с multicast пакетом, если адрес назначения найден в таблице MAC * MulticastMiss – действие, которое требуется выполнить с multicast пакетом, если адрес назначения не найден в таблице MAC * Mstp – действие, которое требуется выполнить с MSTP пакетом //(Действия здесь, это значение из ACT_FORWARD .. ACT_COS_DISCARD, описано выше.)// =====HIF трансфер из HOST в коммутатор===== При чтении схемы трафика между приложением и хостом надо смотреть на номера в подписях. Например, цифры в надписях "1Т Request ...", "2Т TX BD ..." и т.д. показывают очередность обработки трафика передачи, Transmit. Надписи с R, показывают очередность приема, Receive. {{doc:mk:1923kx028:kx028_host2app_e.png}} Слева на данной картинке сигналы идут к контроллеру PCIe. Справа находится HGPI и ядро коммутатора. =====Пакеты в памяти LMEM===== Всего памяти LMEM в коммутаторе 512КБ. Это два блока по 256КБ - LMEM0 и LMEM4, для каждого классификатора по своему блоку памяти. На картинке ниже представлено расположение принятого пакета в памяти LMEM при обращении за обучением к хосту. По полям CTRL и Size хост узнает по какой причине пакет отправлен на хост и какой длины этот фрейм (плюс заголовок). Это первый буфер, поэтому у него заголовок составляет 48 байт. Со второго буфера заголовок имеет длину 16 байт, остальное место отдано под данные пакета. {{doc:mk:1923kx028:kx028_framepantedtolearn.png}} =====Планировщики и формирователи TMU (TLITE)===== {{doc:mk:1923kx028:kx028_sched_shaper_ex.png}} Алгоритмы работы планировков: * PQ - Priority Queue * DWRR - Deficit Weighted Round Robin * RR - Round Robin * WRR - Weighted Round Robin =====HIF Transfer===== Упрощенное представление обмена дескрипторами между блоком HIF и сетевым драйвером. {{doc:mk:1923kx028:kx028_hif_transfer.png}} Краткое пояснение: - Когда по сетевому стеку в драйвер спускается фрейм на отправку (в виде SKB буфера), то в самом skb, в поле **skb->dev** указывается каким сетевым устройсвом данный skb следует передать. - Когда сетевое устройство регистрировалось в системе, оно выдало системе стек функций **struct net_device_ops**, через которые система работает с данным устройством. В данном стеке функций есть поле ndo_start_xmit, в котором хранится указатель на функцию реализующую отправку фрейма. Соответственно, skb передается в данную функцию **ndo_start_xmit(skb)** для отправки. - В драйвере 1923КХ028 фрейм модицируется необходимым заголовком и записывается в один или несколько буферов (несколько - в случае посылки jumbo фрейма). Для этого в кольцевом буфере дескрипторов BD ищется свободный дескриптов, а данные из SKB копируются в буфер ассоциированный с данным дескриптором. Дескриптор помечается активным, т.е. выставляется бит DESC_EN в поле CTRL дескриптора. - HIF интерфейс через механизм DMA постоянно вычитывает дескрипторы и проверяет наличие бита DESC_EN. Когда такой дескриптор встречается, то вычитывается его буфер данных - т.е. фрейм. Далее фрейм через интерфейс HGPI копируется в память LMEM микросхемы и далее обрабатывается микросхемой. * Если фрейм с битом инжекции, то он сразу отправляется в назначеный порт инжекции. * Если фрейм без инжекции, то он пропускается через классификатор, который уже решает куда фрейм следует отправить. - По окончании приема фрейма, HIF записывает в текущий WriteBack буфер (BDWB) сколько данных он принял и выставляет в нем seq_num от обработанного BD. После этого генерируется PCI прерывание TXPKT_INT. - Получив прерывание, драйвер видит причину прерывания - TXPKT_INT в регистре INT_SRC и обрабатывает буфер BDWB. Фрейм считается переданным, а в дескрипторе BD снимается бит DESC_EN. Т.е. дескриптор BD становится свободным для следующего использования. HIF состоит из 4-х каналов, в каждом канале есть кольцевой буфер дескрипторов для приема данных из PC и кольцевой буфер для передачи данных в РС. Каждый из этих кольцевых буферов опрашивается интерфейсом HIF. Когда микросхема отправляет на Хост фрейм, то: - Она находит свободный BD в кольце на передачу данных в РС. - Копирует данные в буфер ассоциированный с BD посредством DMA. - Указывает в WriteBack дестрипторе сколько данных передал в РС и записывает seq_num от BD. - Генерирует прерывание RXPKT_INT на шине PCI - Драйвер, получив прерывание, обрабатывает все дескрипторы BD, для которых активны дескрипторы WriteBack. Он аллоцирует объекты skb и копирует в них данные из буферов BD. skb передаются наверх в сетевой стек. ИТОГО: - BD (Дескриптор Буфера) записывается драйвером и читается HIF блоком микросхемы. - BUFF (буфер в памяти РС) пишется драйвером, если BD в кольце передачи данных в микросхему. И читается драйвером, если BD в кольце чтения данных из микросхемы. - BDWB (Обратный дескриптор) пишется блоком HIF микросхемы и читается драйвером.