Кратко

  • Вызов cm_request сообщал о желании приложения передавать, но не передавал Congestion Manager буфер; cmapp_send выдавал ограниченный объём, обычно до PMTU, и на короткий срок.
  • Разрешение не доказывало ни постановку пакета в очередь, ни доставку. Приложение выбирало или переупаковывало данные, сообщало локально отправленные байты через cm_notify, а сведения получателя передавало отдельно через cm_update.

Один узел заново изучал один и тот же путь

В начале 2000-х браузер, аудио- и видеопрограммы могли одновременно держать несколько потоков к одной цели. Каждый сам оценивал RTT, замечал потери и менял скорость. Новое соединение не обязательно знало то, что соседнее соединение измерило минуту назад. Узкое место было общим, но память о нём оставалась раздробленной.

RFC 2140 уже описывала обмен отдельными элементами состояния TCP между соединениями пары узлов. RFC 3124, опубликованная в Standards Track в июне 2001 года, предложила более широкий модуль конечной системы. Congestion Manager, или CM, объединял потоки в macroflow, делил между ними состояние и алгоритмы управления перегрузкой и предоставлял интерфейс приложениям, включая не-TCP программы.

Это не была единая очередь всех данных. Архитектура разделяла два знания: CM видел окно перегрузки и конкурирующие запросы, а приложение знало, какое сообщение или кадр сохраняет ценность именно сейчас.

Запрос не содержал пакет

При cm_request приложение объявляло спрос, но не отдавало CM буфер на хранение. Менеджер не держал payload, не анализировал его смысл и не обещал позже передать конкретное сообщение.

Когда контроллер и планировщик разрешали отправку, CM вызывал cmapp_send. Callback задавал предел, обычно один path MTU. Только тогда приложение выбирало данные. Видеокодер мог отбросить устаревший кадр, снизить качество или изменить пакетирование под доступный объём.

Поздний выбор соединял разные компетенции. Общий сервис распоряжался редкой возможностью, не понимая семантики медиа. Приложение сохраняло смысловой выбор, не присваивая общую оценку пути. Обычная очередь зафиксировала бы содержимое слишком рано.

Поэтому callback не был квитанцией об отправке. После него ещё требовалось создать пакет, передать его IP и вывести через интерфейс. Приложение могло не воспользоваться разрешением или обработать его после истечения срока.

Разрешение истекало и требовало отчёта

Срок определялся большим из RTT и заданного реализацией порога. Просроченный callback использовать было нельзя. Возможность, основанная на старом состоянии перегрузки, не превращалась в бессрочный кредит.

После попытки cm_notify(nsent) сообщал число байтов, фактически поданных на IP output. Если передача не состоялась, приложение должно было указать ноль и вернуть возможность. Запрос, разрешение и использование становились отдельными проводками.

Спецификация учитывала сбои: процесс мог завершиться, не отправив нулевое уведомление. CM должен был восстановиться, чтобы не остановить остальные запросы. Но устойчивость не давала права превращать каждый callback в вымышленную передачу.

nsent означал данные, выпущенные узлом, а не полученные peer. Обратная связь приходила через cm_update, где различались получение, потеря, явное уведомление о перегрузке и отсутствие ответа. Разрешение, локальное действие и удалённое наблюдение имели разные источники.

Macroflow оставался гипотезой о пути

Потоки одного macroflow делили состояние и scheduling. Приложение могло влиять на группировку, поскольку знало связи своих сессий. Но общий идентификатор не доказывал общий bottleneck. Маршрут мог измениться, интерфейсов могло быть несколько, а правило группировки — слишком широким.

Для проверки нужно хранить macroflow key вместе с маршрутом, интерфейсом, назначением и измерениями того же времени. Без них группа фиксирует локальное решение программы, а не физическую идентичность пути.

RFC 2581, RFC 2861 и поздняя RFC 5681 описывают аспекты TCP congestion behavior; RFC 9040 снова рассматривает общие transport metrics. Особенность RFC 3124 состояла в обращённой к приложениям последовательности request–grant–notify и общем планировщике, а не только в кеше TCP-метрик.

«Хорошее поведение» зависело от сотрудничества

Документ называл well-behaved приложение, которое передавало только с согласия CM и точно сообщало все отправленные данные. Это было обязательство участника, а не технический барьер для любого процесса на узле.

RFC прямо отмечала: CM не принуждал все приложения к нужному поведению и не защищал сеть от скомпрометированного узла. Host policing или router enforcement были бы другими механизмами вне области спецификации. Вредоносная или неинтегрированная программа могла обойти API.

Наличие модуля поэтому не доказывает, что ему подчинялся весь трафик. Вызовы одного приложения не исключают параллельный обход. Даже правильная последовательность вызовов не подтверждает, что пакеты прошли путём, предполагаемым macroflow.

Участие было добровольным. Выбрав CM, приложение должно было соблюдать контракт, но статус Standards Track не является данными о внедрении или успехе.

Неизвестное не превращалось в ноль

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

Неизвестность и измеренный ноль требуют разных решений. То же относится к истории: отсутствие свидетельства внедрения не доказывает провал, а текст стандарта не доказывает принятие. RFC 2914 объясняет принципы congestion control, RFC 2481 — ранний контекст ECN, RFC 1191 — PMTU, RFC 8085 — последующие обязанности UDP. Ни одна не является квитанцией о работе RFC 3124 в конкретном продукте.

Для одной передачи требовалось несколько квитанций

Полная трасса включала бы время cm_request, flow и macroflow, состояние scheduler, время и предел callback, PMTU, RTT и расчёт истечения. Затем — выбранные данные, cm_notify на IP output, интерфейс, маршрут и каждый cm_update. Пользовательский результат потребовал бы ещё более поздних наблюдений.

Запрос доказывает объявленную потребность. Callback доказывает временную возможность. Положительное уведомление доказывает локальный отчёт об отправке. Feedback сообщает о последующей части пути. Ни один документ не заменяет остальные.

Долговечный урок RFC 3124 именно в этом разделении. Она пыталась разделить знание о перегрузке, не передавая контроллеру власть над данными. Разрешение упорядочивало время; оно не было ни пакетом, ни его прибытием.

Источники

  1. https://www.rfc-editor.org/rfc/rfc3124.txt
  2. https://www.rfc-editor.org/info/rfc3124
  3. https://datatracker.ietf.org/doc/rfc3124/
  4. https://www.rfc-editor.org/rfc/rfc2140.txt
  5. https://www.rfc-editor.org/rfc/rfc2914.txt
  6. https://www.rfc-editor.org/rfc/rfc2581.txt
  7. https://www.rfc-editor.org/rfc/rfc2861.txt
  8. https://www.rfc-editor.org/rfc/rfc2481.txt
  9. https://www.rfc-editor.org/rfc/rfc1191.txt
  10. https://www.rfc-editor.org/rfc/rfc5681.txt
  11. https://www.rfc-editor.org/rfc/rfc8085.txt
  12. https://www.rfc-editor.org/rfc/rfc9040.txt