N/RFCNET
← Карточка документаEnglish original ↗

RFC 9002 · май 2021

Обнаружение потерь и управление перегрузкой в QUIC

Редакторы: J. Iyengar, Fastly; I. Swett, Google. Категория: стандарт. Май 2021.

Аннотация

Этот документ описывает механизмы обнаружения потерь и управления перегрузкой для QUIC.

Статус документа

Этот документ относится к стандартам Интернета.

Документ подготовлен Инженерной группой Интернета (IETF) и отражает консенсус её сообщества. Он прошёл публичное рассмотрение и одобрен к публикации Руководящей группой по инженерным вопросам Интернета (IESG). Дополнительные сведения о стандартах Интернета приведены в разделе 2 RFC 7841.

Сведения о текущем статусе документа, исправлениях и способах обратной связи можно получить по адресу https://www.rfc-editor.org/info/rfc9002.

Уведомление об авторских правах

Copyright (c) 2021 IETF Trust и лица, указанные в качестве авторов документа. Все права защищены.

На документ распространяются BCP 78 и Правовые положения IETF Trust, относящиеся к документам IETF (https://trustee.ietf.org/license-info), действовавшие на дату публикации. Внимательно ознакомьтесь с ними: они описывают ваши права и ограничения. Компоненты программного кода, извлечённые из документа, должны включать текст упрощённой лицензии BSD, как указано в разделе 4.e Правовых положений IETF Trust, и предоставляются без гарантий согласно этой лицензии.

1. Введение

QUIC — безопасный транспортный протокол общего назначения, описанный в [QUIC-TRANSPORT]. Этот документ описывает механизмы обнаружения потерь и управления перегрузкой для QUIC.

2. Соглашения и определения

Ключевые слова MUST, MUST NOT, REQUIRED, SHALL, SHALL NOT, SHOULD, SHOULD NOT, RECOMMENDED, NOT RECOMMENDED, MAY и OPTIONAL следует понимать в соответствии с BCP 14 [RFC2119] [RFC8174] тогда и только тогда, когда в оригинале они написаны прописными буквами, как здесь. В переводе они передаются соответственно контексту словами ДОЛЖЕН, НЕ ДОЛЖЕН, ОБЯЗАТЕЛЬНО, СЛЕДУЕТ, НЕ СЛЕДУЕТ, РЕКОМЕНДУЕТСЯ, НЕ РЕКОМЕНДУЕТСЯ, МОЖЕТ и НЕОБЯЗАТЕЛЬНО.

В документе используются следующие определения.

Кадры, вызывающие подтверждение (ack-eliciting): все кадры, кроме ACK, PADDING и CONNECTION_CLOSE.

Пакеты, вызывающие подтверждение: пакеты, содержащие такие кадры; они вызывают отправку получателем ACK в пределах максимальной задержки подтверждения.

Пакеты в пути (in flight): отправленные пакеты, которые вызывают подтверждение или содержат кадр PADDING и при этом ещё не подтверждены, не объявлены потерянными и не отброшены вместе со старыми ключами.

3. Устройство механизма передачи QUIC

Все передачи QUIC отправляются с заголовком на уровне пакета, который указывает уровень шифрования и содержит порядковый номер пакета (далее — номер пакета). Уровень шифрования определяет пространство номеров пакетов, как описано в разделе 12.3 [QUIC-TRANSPORT]. В течение соединения номера не повторяются внутри одного пространства. Они отправляются в монотонно возрастающем порядке внутри пространства, что исключает неоднозначность. Некоторые номера могут намеренно не использоваться, оставляя промежутки.

Такая конструкция устраняет необходимость различать первоначальную и повторную передачи; это значительно упрощает применение QUIC механизмов обнаружения потерь TCP.

Пакеты QUIC могут содержать несколько кадров разных типов. Механизмы восстановления обеспечивают подтверждение данных и кадров, требующих надёжной доставки, или объявление их потерянными и при необходимости отправку в новых пакетах. Типы кадров влияют на логику восстановления и управления перегрузкой:

4. Существенные различия между QUIC и TCP

Читатели, знакомые с обнаружением потерь и управлением перегрузкой TCP, найдут здесь алгоритмы, аналогичные известным алгоритмам TCP. Однако различия протоколов QUIC и TCP приводят к различиям алгоритмов. Ниже эти различия кратко описаны.

4.1. Отдельные пространства номеров пакетов

QUIC использует отдельные пространства номеров пакетов для каждого уровня шифрования, за исключением 0-RTT и всех поколений ключей 1-RTT, использующих одно общее пространство. Это гарантирует, что подтверждение пакетов, отправленных на одном уровне шифрования, не вызовет ложной повторной передачи пакетов, отправленных на другом уровне. Управление перегрузкой и измерение времени кругового обхода (RTT) едины для всех пространств номеров.

4.2. Монотонно возрастающие номера пакетов

TCP объединяет порядок передачи отправителем с порядком доставки получателю, что порождает неоднозначность повторных передач [RETRANSMISSION]. QUIC разделяет их: номера пакетов показывают порядок отправки, а порядок доставки определяется смещениями потока в кадрах STREAM.

Номер пакета QUIC строго возрастает в пределах пространства номеров и непосредственно отражает порядок отправки: больший номер означает более позднюю отправку, меньший — более раннюю. При обнаружении потери пакета с кадрами, вызывающими подтверждение, QUIC помещает нужные кадры в новый пакет с новым номером. Это устраняет неоднозначность при определении подтверждённого пакета после получения ACK. В результате можно точнее измерять RTT, легко выявлять ложные повторные передачи и универсально применять механизмы вроде быстрой повторной передачи, опираясь только на номер пакета.

Это решение значительно упрощает обнаружение потерь QUIC. Большинство механизмов TCP неявно пытаются вывести порядок передачи из порядковых номеров TCP — задача нетривиальная, особенно без временных меток TCP.

4.3. Более чёткий период потерь

QUIC начинает период потерь при потере пакета и завершает его при подтверждении любого пакета, отправленного после начала периода. TCP ожидает заполнения пропуска в пространстве порядковых номеров; поэтому при многократной потере сегмента период потерь может длиться несколько круговых обходов. Поскольку оба протокола должны уменьшать окно перегрузки только один раз за период, QUIC уменьшает его один раз за каждый круговой обход с потерями, тогда как TCP может уменьшить его лишь однажды за несколько обходов.

4.4. Отсутствие отзыва подтверждений

Кадры ACK QUIC содержат сведения, подобные выборочным подтверждениям TCP SACK [RFC2018]. Однако QUIC не допускает отзыва подтверждения пакета, что значительно упрощает реализации на обеих сторонах и снижает нагрузку на память отправителя.

4.5. Больше диапазонов ACK

QUIC поддерживает множество диапазонов ACK, в отличие от трёх диапазонов SACK TCP. При значительных потерях это ускоряет восстановление, уменьшает число ложных повторных передач и обеспечивает продвижение без опоры на тайм-ауты.

4.6. Явная поправка на задержанные подтверждения

Конечные точки QUIC измеряют задержку между получением пакета и отправкой соответствующего подтверждения, что позволяет другой стороне точнее оценивать RTT; см. раздел 13.2 [QUIC-TRANSPORT].

4.7. Пробный тайм-аут вместо RTO и TLP

QUIC использует пробный тайм-аут PTO (раздел 6.2) с таймером на основе вычисления тайм-аута повторной передачи TCP RTO [RFC6298]. Вместо фиксированного минимального тайм-аута PTO QUIC включает максимальную ожидаемую задержку подтверждения другой стороны.

Как и алгоритм обнаружения потерь TCP RACK-TLP [RFC8985], QUIC не схлопывает окно перегрузки при истечении PTO, поскольку потеря одного последнего пакета не указывает на устойчивую перегрузку. Окно схлопывается при объявлении устойчивой перегрузки (раздел 7.6). Это позволяет избежать ненужных сокращений окна и устраняет потребность в корректирующих механизмах вроде Forward RTO-Recovery (F-RTO) [RFC5682]. Поскольку окно при истечении PTO не схлопывается, отправитель QUIC может отправлять дополнительные пакеты в путь, если окно ещё позволяет это. Такое происходит, когда скорость отправки ограничена приложением и истекает PTO. При ограничении приложением это агрессивнее RTO TCP; без такого ограничения поведение совпадает.

При каждом истечении таймера QUIC допускает временное превышение окна перегрузки пробными пакетами.

4.8. Минимальное окно перегрузки — два пакета

TCP использует минимальное окно перегрузки в один пакет. Но потеря этого единственного пакета означает ожидание PTO для восстановления (раздел 6.2), которое может быть намного дольше RTT. Отправка единственного пакета, вызывающего подтверждение, также повышает вероятность дополнительной задержки, если получатель откладывает подтверждение.

Поэтому QUIC рекомендует минимальное окно перегрузки в два пакета. Хотя это увеличивает нагрузку на сеть, такой подход считается безопасным, поскольку отправитель всё равно будет экспоненциально снижать скорость при устойчивой перегрузке (раздел 6.2).

4.9. Пакеты рукопожатия не являются исключением

TCP считает потерю пакета SYN или SYN-ACK устойчивой перегрузкой и уменьшает окно до одного пакета [RFC5681]. QUIC обрабатывает потерю пакета с данными рукопожатия так же, как другие потери.

5. Оценка времени кругового обхода

В общем случае конечная точка измеряет время от отправки пакета до его подтверждения как отсчёт RTT. Используя отсчёты RTT и сообщаемые другой стороной задержки хоста (раздел 13.2 [QUIC-TRANSPORT]), она формирует статистическое описание RTT сетевого пути. Для каждого пути вычисляются три значения: минимальное за некоторый период (min_rtt), экспоненциально взвешенное скользящее среднее (smoothed_rtt) и среднее отклонение наблюдаемых отсчётов RTT (rttvar), далее называемое вариацией.

5.1. Получение отсчётов RTT

Конечная точка получает отсчёт RTT при получении кадра ACK, удовлетворяющего двум условиям:

Отсчёт RTT latest_rtt равен времени с отправки пакета с наибольшим подтверждённым номером:

latest_rtt = ack_time − send_time_of_largest_acked

Для отсчёта используется только пакет с наибольшим номером, подтверждённым полученным кадром ACK: другая сторона сообщает задержку подтверждения только для него. Сама задержка не используется при измерении отсчёта, но учитывается при последующих вычислениях smoothed_rtt и rttvar (раздел 5.3).

Чтобы не получать несколько отсчётов RTT для одного пакета, кадр ACK НЕ СЛЕДУЕТ использовать для обновления оценок RTT, если он не подтверждает впервые пакет с наибольшим подтверждённым номером.

Отсчёт RTT НЕ ДОЛЖЕН создаваться при получении ACK, который не подтверждает впервые хотя бы один пакет, вызывающий подтверждение. Обычно сторона не отправляет ACK при получении только пакетов, не вызывающих подтверждение. Поэтому ACK, подтверждающий только такие пакеты, может содержать сколь угодно большое значение ACK Delay. Игнорирование этих кадров устраняет осложнения при последующем вычислении smoothed_rtt и rttvar.

Отправитель может получить несколько отсчётов RTT за один RTT, если за это время получено несколько кадров ACK. Как отмечается в [RFC6298], это может привести к недостаточному учёту истории в smoothed_rtt и rttvar. Обеспечение достаточной истории оценок RTT остаётся открытым исследовательским вопросом.

5.2. Оценка min_rtt

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

При первом отсчёте RTT min_rtt ДОЛЖЕН устанавливаться равным latest_rtt. Для всех остальных отсчётов min_rtt ДОЛЖЕН устанавливаться равным меньшему из min_rtt и latest_rtt (раздел 5.1).

При вычислении min_rtt конечная точка использует только локально наблюдаемые времена и не учитывает сообщаемую другой стороной задержку подтверждения. Это позволяет установить нижнюю границу smoothed_rtt исключительно на основе собственных наблюдений (раздел 5.3) и ограничить возможное занижение из-за неверно сообщённых задержек.

RTT пути может меняться со временем. Если фактический RTT уменьшается, min_rtt адаптируется сразу при первом малом отсчёте. Если фактический RTT увеличивается, min_rtt не приспосабливается к этому, позволяя включать в smoothed_rtt будущие отсчёты меньше нового RTT.

После установления устойчивой перегрузки конечным точкам СЛЕДУЕТ устанавливать min_rtt равным последнему отсчёту RTT. Это предотвращает повторное объявление устойчивой перегрузки при увеличении RTT, а также позволяет соединению сбросить оценки min_rtt и smoothed_rtt после серьёзного нарушения работы сети; см. раздел 5.3.

Конечные точки МОГУТ переустанавливать min_rtt в другие моменты соединения, например при небольшом объёме трафика и получении подтверждения с малой задержкой. Реализациям НЕ СЛЕДУЕТ обновлять min_rtt слишком часто, поскольку истинный минимальный RTT пути наблюдается нечасто.

5.3. Оценка smoothed_rtt и rttvar

smoothed_rtt — экспоненциально взвешенное скользящее среднее отсчётов RTT конечной точки; rttvar оценивает их разброс по среднему отклонению.

Для вычисления smoothed_rtt отсчёты RTT корректируются с учётом задержек подтверждения. Эти задержки декодируются из поля ACK Delay кадров ACK, как описано в разделе 19.3 [QUIC-TRANSPORT].

Во время рукопожатия другая сторона может сообщить задержку подтверждения, превышающую её max_ack_delay (раздел 13.2.1 [QUIC-TRANSPORT]). Поэтому конечной точке СЛЕДУЕТ игнорировать max_ack_delay до подтверждения рукопожатия согласно разделу 4.1.2 [QUIC-TLS]. Такие большие задержки, вероятно, не повторяются и ограничены временем рукопожатия. Следовательно, их можно учитывать без ограничения max_ack_delay, избегая ненужного завышения оценки RTT.

Большая задержка подтверждения может существенно завысить smoothed_rtt, если другая сторона ошибочно сообщает задержку либо конечная точка неверно оценила min_rtt. Поэтому до подтверждения рукопожатия конечная точка МОЖЕТ игнорировать отсчёты RTT, если после вычитания задержки подтверждения отсчёт становится меньше min_rtt.

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

Таким образом, при корректировке отсчёта RTT по сообщённой задержке подтверждения конечная точка:

Кроме того, конечная точка может откладывать обработку подтверждений, если соответствующие ключи расшифрования доступны не сразу. Например, клиент может получить подтверждение пакета 0-RTT, которое не может расшифровать, поскольку ключи защиты пакетов 1-RTT ещё недоступны. В таких случаях до подтверждения рукопожатия конечной точке СЛЕДУЕТ вычитать такие локальные задержки из отсчёта RTT.

Подобно [RFC6298], smoothed_rtt и rttvar вычисляются следующим образом.

Конечная точка инициализирует оценку RTT при установлении соединения и при её сбросе во время миграции соединения; см. раздел 9.4 [QUIC-TRANSPORT]. До получения отсчётов RTT для нового пути или после сброса оценка инициализируется начальным RTT; см. раздел 6.2.2.

Начальные значения, где kInitialRtt содержит начальный RTT:

Отсчёты RTT сетевого пути записываются в latest_rtt; см. раздел 5.1. При первом отсчёте после инициализации оценка сбрасывается на его основе, чтобы в ней не сохранялась история прежних отсчётов. Пакеты, отправленные по другим путям, не дают отсчётов RTT для текущего пути, как описано в разделе 9.4 [QUIC-TRANSPORT].

При первом отсчёте после инициализации:

При последующих отсчётах значения изменяются следующим образом:

6. Обнаружение потерь

Отправители QUIC используют подтверждения для обнаружения потерянных пакетов и PTO для обеспечения получения подтверждений; см. раздел 6.2. В этом разделе описаны соответствующие алгоритмы.

При потере пакета транспорт QUIC должен восстановиться, например повторно передав данные, отправив обновлённый кадр или отбросив кадр. Подробнее см. раздел 13.3 [QUIC-TRANSPORT].

В отличие от измерения RTT и управления перегрузкой, обнаружение потерь выполняется отдельно для каждого пространства номеров пакетов: RTT и перегрузка являются свойствами пути, тогда как обнаружение потерь также зависит от доступности ключей.

6.1. Обнаружение на основе подтверждений

Обнаружение потерь по подтверждениям реализует идеи TCP Fast Retransmit [RFC5681], Early Retransmit [RFC5827], Forward Acknowledgment [FACK], восстановления потерь по SACK [RFC6675] и RACK-TLP [RFC8985]. Далее дан обзор реализации этих алгоритмов в QUIC.

Пакет объявляется потерянным, если выполняются все условия:

Подтверждение показывает, что пакет, отправленный позднее, доставлен, а пороги по пакетам и времени обеспечивают некоторую устойчивость к перестановке.

Ошибочное объявление пакетов потерянными приводит к ненужным повторным передачам и может ухудшить производительность из-за действий управления перегрузкой после обнаружения потери. Реализации могут обнаруживать ложные повторные передачи и увеличивать порог перестановки по пакетам или времени, уменьшая число ложных повторных передач и событий потери в будущем. Реализации с адаптивными временными порогами МОГУТ начинать с меньших порогов перестановки, чтобы сократить задержку восстановления.

6.1.1. Порог по пакетам

РЕКОМЕНДУЕМОЕ начальное значение порога перестановки пакетов kPacketThreshold равно 3 на основе устоявшейся практики обнаружения потерь TCP [RFC5681] [RFC6675]. Для сохранения сходства с TCP реализациям НЕ СЛЕДУЕТ использовать порог менее 3; см. [RFC5681].

В некоторых сетях перестановка пакетов может быть сильнее, что вызывает ложное обнаружение потерь отправителем. Кроме того, перестановка может встречаться в QUIC чаще, чем в TCP, поскольку сетевые элементы, способные наблюдать и переупорядочивать пакеты TCP, не могут делать это для QUIC, а номера пакетов QUIC зашифрованы. Алгоритмы, повышающие порог перестановки после ложного обнаружения потери, например RACK [RFC8985], доказали полезность в TCP и предположительно будут не менее полезны в QUIC.

6.1.2. Временной порог

После подтверждения более позднего пакета в том же пространстве номеров конечной точке СЛЕДУЕТ объявить более ранний пакет потерянным, если с его отправки прошло пороговое время. Чтобы не объявлять потери слишком рано, временной порог ДОЛЖЕН составлять не менее разрешения локального таймера, заданного константой kGranularity:

max(kTimeThreshold * max(smoothed_rtt, latest_rtt), kGranularity)

Если пакеты, отправленные до пакета с наибольшим подтверждённым номером, ещё нельзя объявить потерянными, СЛЕДУЕТ установить таймер на оставшееся время.

Использование max(smoothed_rtt, latest_rtt) защищает от двух случаев:

РЕКОМЕНДУЕМЫЙ временной порог kTimeThreshold как множитель RTT равен 9/8. РЕКОМЕНДУЕМОЕ разрешение таймера kGranularity — 1 миллисекунда.

Примечание. TCP RACK [RFC8985] для аналогичной цели задаёт несколько больший порог, эквивалентный 5/4. Опыт QUIC показывает, что 9/8 работает хорошо.

Реализации МОГУТ экспериментировать с абсолютными порогами, порогами предыдущих соединений, адаптивными порогами или учётом вариации RTT. Меньшие пороги снижают устойчивость к перестановке и увеличивают число ложных повторных передач; большие увеличивают задержку обнаружения потерь.

6.2. Пробный тайм-аут

Пробный тайм-аут PTO вызывает отправку одной или двух пробных дейтаграмм, когда пакеты, вызывающие подтверждение, не подтверждены за ожидаемое время либо сервер, возможно, ещё не проверил адрес клиента. PTO позволяет соединению восстановиться после потери последних пакетов или подтверждений.

Как и обнаружение потерь, PTO задаётся отдельно для каждого пространства номеров пакетов: значение PTO вычисляется для каждого пространства.

Истечение таймера PTO не означает потерю пакета и НЕ ДОЛЖНО приводить к пометке ранее не подтверждённых пакетов как потерянных. Когда полученное подтверждение впервые подтверждает пакеты, обнаружение потерь выполняется по порогам пакетов и времени; см. раздел 6.1.

Алгоритм PTO в QUIC реализует функции надёжности TCP-алгоритмов Tail Loss Probe [RFC8985], RTO [RFC5681] и F-RTO [RFC5682]. Вычисление тайм-аута основано на периоде RTO TCP [RFC6298].

6.2.1. Вычисление PTO

При передаче пакета, вызывающего подтверждение, отправитель устанавливает таймер на период PTO:

PTO = smoothed_rtt + max(4*rttvar, kGranularity) + max_ack_delay

Период PTO — время, которое отправителю следует ожидать подтверждения отправленного пакета. Оно включает оценку сетевого RTT smoothed_rtt, разброс оценки 4*rttvar и max_ack_delay, учитывающий максимальную задержку отправки подтверждения получателем.

При установке PTO для пространств номеров Initial или Handshake в расчёте max_ack_delay принимается равным нулю, поскольку не ожидается, что другая сторона намеренно задерживает такие пакеты; см. раздел 13.2.1 [QUIC-TRANSPORT].

Период PTO ДОЛЖЕН быть не меньше kGranularity, чтобы таймер не истекал немедленно.

Если в нескольких пространствах номеров находятся в пути пакеты, вызывающие подтверждение, таймер ДОЛЖЕН устанавливаться на более раннее значение пространств Initial и Handshake.

Конечная точка НЕ ДОЛЖНА устанавливать таймер PTO для пространства Application Data до подтверждения рукопожатия. Это предотвращает повторную передачу информации в пакетах, когда другая сторона ещё не имеет ключей для их обработки либо сама точка ещё не имеет ключей для обработки подтверждений. Например, клиент может отправлять серверу пакеты 0-RTT, не зная, сможет ли сервер их расшифровать. Аналогично сервер может отправлять пакеты 1-RTT до подтверждения, что клиент проверил сертификат сервера и может читать эти пакеты.

Отправителю СЛЕДУЕТ перезапускать таймер PTO при каждой отправке или подтверждении пакета, вызывающего подтверждение, а также при отбрасывании ключей Initial или Handshake (раздел 4.9 [QUIC-TLS]). Это обеспечивает установку PTO по последней оценке RTT и для правильного пакета среди пространств номеров.

При истечении таймера PTO коэффициент увеличения PTO ДОЛЖЕН возрастать, удваивая текущий период PTO. Он сбрасывается при получении подтверждения, кроме следующего случая. Во время рукопожатия сервер может отвечать медленнее обычного. Чтобы защитить его от повторных проб клиента, клиент, ещё не уверенный в завершении проверки своего адреса сервером, не сбрасывает коэффициент увеличения PTO. То есть клиент не сбрасывает его при получении подтверждений в пакетах Initial.

Такое экспоненциальное снижение скорости отправителя важно, поскольку последовательные PTO могут быть вызваны потерей пакетов или подтверждений из-за серьёзной перегрузки. Даже если пакеты, вызывающие подтверждение, находятся в пути в нескольких пространствах, экспоненциальное увеличение PTO распространяется на все пространства, предотвращая избыточную нагрузку на сеть. Например, тайм-аут в пространстве Initial удваивает длительность тайм-аута в пространстве Handshake.

Общая продолжительность последовательных истечений PTO ограничена тайм-аутом бездействия.

Таймер PTO НЕ ДОЛЖЕН устанавливаться, если установлен таймер обнаружения потерь по временному порогу; см. раздел 6.1.2. В большинстве случаев такой таймер истечёт раньше PTO и с меньшей вероятностью вызовет ложную повторную передачу данных.

6.2.2. Рукопожатия и новые пути

Возобновлённые соединения в той же сети МОГУТ использовать конечное значение сглаженного RTT предыдущего соединения как начальный RTT. Если прежнее значение недоступно, начальный RTT СЛЕДУЕТ установить в 333 миллисекунды. Тогда начальный PTO рукопожатия составит одну секунду, как рекомендовано для начального RTO TCP; см. раздел 2 [RFC6298].

Соединение МОЖЕТ использовать задержку между отправкой PATH_CHALLENGE и получением PATH_RESPONSE для установки начального RTT нового пути (kInitialRtt в приложении A.2), но эту задержку НЕ СЛЕДУЕТ считать отсчётом RTT.

Когда ключи Initial и Handshake отброшены (раздел 6.4), соответствующие пакеты больше не могут быть подтверждены и удаляются из числа байтов в пути. При отбрасывании ключей Initial или Handshake таймеры PTO и обнаружения потерь ДОЛЖНЫ сбрасываться: отбрасывание ключей указывает на продвижение, а таймер обнаружения потерь мог быть установлен для уже отброшенного пространства номеров.

6.2.2.1. До проверки адреса

Пока сервер не проверил адрес клиента на пути, объём отправляемых им данных ограничен трёхкратным объёмом полученных данных согласно разделу 8.1 [QUIC-TRANSPORT]. Если дополнительные данные отправить нельзя, таймер PTO сервера НЕ ДОЛЖЕН запускаться до получения от клиента дейтаграмм, поскольку пакеты, отправленные по PTO, учитываются в ограничении усиления.

При получении дейтаграммы клиента лимит усиления увеличивается и сервер сбрасывает таймер PTO. Если после этого таймер установлен на уже прошедшее время, он срабатывает немедленно. Это предотвращает отправку новых пакетов 1-RTT раньше пакетов, критичных для завершения рукопожатия. В частности, такое возможно, если 0-RTT принят, но сервер не смог проверить адрес клиента.

Поскольку сервер может быть заблокирован до получения дополнительных дейтаграмм от клиента, клиент отвечает за отправку пакетов, разблокирующих сервер, пока не убедится, что проверка адреса завершена (раздел 8 [QUIC-TRANSPORT]). То есть клиент ДОЛЖЕН установить PTO, если не получил подтверждение ни одного своего пакета Handshake и рукопожатие не подтверждено (раздел 4.1.2 [QUIC-TLS]), даже когда пакетов в пути нет. При срабатывании PTO клиент ДОЛЖЕН отправить пакет Handshake, если у него есть ключи Handshake; иначе он ДОЛЖЕН отправить пакет Initial в дейтаграмме UDP с полезной нагрузкой не менее 1200 байтов.

6.2.3. Ускорение завершения рукопожатия

Когда сервер получает пакет Initial с дублирующимися данными CRYPTO, он может предположить, что клиент получил не все данные CRYPTO, отправленные сервером в пакетах Initial, либо что оценка RTT клиента слишком мала. Когда клиент получает пакеты Handshake или 1-RTT до получения ключей Handshake, он может предположить потерю некоторых или всех пакетов Initial сервера.

Чтобы ускорить завершение рукопожатия в этих условиях, конечная точка МОЖЕТ ограниченное число раз за соединение отправить пакет с неподтверждёнными данными CRYPTO до истечения PTO при соблюдении ограничений проверки адреса из раздела 8.1 [QUIC-TRANSPORT]. Для быстрого восстановления после потери одного пакета достаточно сделать это не более одного раза за соединение. Конечная точка, всегда повторно отправляющая пакеты в ответ на те, которые она не может обработать, рискует вызвать бесконечный обмен пакетами.

Конечные точки также могут объединять пакеты (раздел 12.2 [QUIC-TRANSPORT]), чтобы каждая дейтаграмма вызывала хотя бы одно подтверждение. Например, клиент может объединить пакет Initial с кадрами PING и PADDING с пакетом данных 0-RTT, а сервер — пакет Initial с кадром PING с одним или несколькими пакетами своей первой посылки.

6.2.4. Отправка пробных пакетов

При истечении таймера PTO отправитель ДОЛЖЕН отправить в соответствующем пространстве номеров как минимум один пробный пакет, вызывающий подтверждение. Конечная точка МОЖЕТ отправить до двух полноразмерных дейтаграмм с такими пакетами, чтобы избежать дорогостоящего последовательного истечения PTO из-за потери одной дейтаграммы или передать данные из нескольких пространств номеров. Все пробные пакеты, отправленные по PTO, ДОЛЖНЫ вызывать подтверждение.

Помимо отправки данных в пространстве, для которого истёк таймер, отправителю СЛЕДУЕТ отправить вызывающие подтверждение пакеты из других пространств с данными в пути, по возможности объединив их. Это особенно полезно, когда у сервера в пути есть данные Initial и Handshake, а у клиента — Handshake и Application Data: другая сторона может иметь ключи приёма только для одного из двух пространств.

Если отправитель хочет получить подтверждение быстрее при PTO, он может пропустить номер пакета, устранив задержку подтверждения.

В пакеты, отправляемые при истечении PTO, конечной точке СЛЕДУЕТ включать новые данные. Если новых данных для отправки нет, МОГУТ отправляться ранее переданные данные. Реализации МОГУТ применять иные стратегии выбора содержимого пробных пакетов, в том числе выбирать новые или повторно передаваемые данные по приоритетам приложения.

У отправителя может не быть ни новых, ни ранее отправленных данных для передачи. Например, новые данные приложения отправлены в кадре STREAM, признаны потерянными, повторно отправлены в новом пакете, а затем первоначальная передача подтверждена. Если данных нет, отправителю СЛЕДУЕТ отправить PING или другой вызывающий подтверждение кадр в одном пакете, заново запустив таймер PTO.

В качестве альтернативы отправитель МОЖЕТ вместо отправки такого пакета пометить любые оставшиеся в пути пакеты как потерянные. Это позволяет не отправлять дополнительный пакет, но повышает риск слишком агрессивного объявления потери и ненужного снижения скорости механизмом управления перегрузкой.

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

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

6.3. Обработка пакетов Retry

Пакет Retry заставляет клиент отправить ещё один пакет Initial, фактически начиная процесс соединения заново. Retry указывает, что пакет Initial был получен, но не обработан. Считать Retry подтверждением нельзя, поскольку он не указывает на обработку пакета и не содержит его номера.

Получив Retry, клиент сбрасывает состояние управления перегрузкой и восстановления потерь, включая ожидающие таймеры. Остальное состояние соединения, особенно сообщения криптографического рукопожатия, сохраняется; см. раздел 17.2.5 [QUIC-TRANSPORT].

Клиент МОЖЕТ оценить RTT до сервера как время между отправкой первого Initial и получением Retry или пакета согласования версии. Это значение МОЖЕТ использоваться вместо начальной оценки RTT по умолчанию.

6.4. Отбрасывание ключей и состояния пакетов

Когда ключи защиты пакетов Initial и Handshake отброшены (раздел 4.9 [QUIC-TLS]), отправленные с ними пакеты больше нельзя подтвердить, поскольку их подтверждения невозможно обработать. Отправитель ДОЛЖЕН отбросить всё состояние восстановления, связанное с этими пакетами, и ДОЛЖЕН удалить их из числа байтов в пути.

Конечные точки прекращают отправлять и принимать пакеты Initial после начала обмена пакетами Handshake; см. раздел 17.2.2.1 [QUIC-TRANSPORT]. В этот момент состояние восстановления всех находящихся в пути пакетов Initial отбрасывается.

Если 0-RTT отклонён, состояние восстановления всех находящихся в пути пакетов 0-RTT отбрасывается.

Если сервер принимает 0-RTT, но не буферизует пакеты 0-RTT, приходящие раньше Initial, ранние пакеты 0-RTT будут объявлены потерянными, однако ожидается, что это случается нечасто.

Ожидается, что ключи отбрасываются спустя некоторое время после подтверждения или объявления потерянными пакетов, зашифрованных ими. Однако секреты Initial и Handshake отбрасываются сразу после подтверждения доступности ключей Handshake и 1-RTT клиенту и серверу; см. раздел 4.9.1 [QUIC-TLS].

7. Управление перегрузкой

Этот документ определяет механизм управления перегрузкой QUIC на стороне отправителя, аналогичный TCP NewReno [RFC6582].

Сигналы QUIC для управления перегрузкой имеют общий характер и предназначены для поддержки различных алгоритмов отправителя. Отправитель может в одностороннем порядке выбрать другой алгоритм, например CUBIC [RFC8312].

Если используется иной механизм, выбранный алгоритм ДОЛЖЕН соответствовать рекомендациям по управлению перегрузкой из раздела 3.1 [RFC8085].

Как и в TCP, пакеты только с кадрами ACK не учитываются в числе байтов в пути и не регулируются управлением перегрузкой. В отличие от TCP, QUIC способен обнаружить их потерю и МОЖЕТ использовать эти сведения для изменения механизма управления перегрузкой или частоты отправки пакетов только с ACK, однако этот документ такой механизм не описывает.

Управление перегрузкой ведётся отдельно для каждого пути, поэтому пакеты, отправленные другими путями, не меняют состояние текущего пути, как описано в разделе 9.4 [QUIC-TRANSPORT].

Алгоритм этого документа определяет и использует окно перегрузки в байтах.

Конечная точка НЕ ДОЛЖНА отправлять пакет, если это приведёт к превышению значения bytes_in_flight над окном перегрузки (приложение B.2), кроме отправки при истечении PTO (раздел 6.2) или при входе в восстановление (раздел 7.3.2).

7.1. Явное уведомление о перегрузке

Если подтверждено, что путь поддерживает явное уведомление о перегрузке ECN [RFC3168] [RFC8311], QUIC считает кодовую точку Congestion Experienced (CE) в заголовке IP сигналом перегрузки. Документ определяет реакцию конечной точки на увеличение сообщённого другой стороной счётчика ECN-CE; см. раздел 13.4.2 [QUIC-TRANSPORT].

7.2. Начальное и минимальное окно перегрузки

QUIC начинает каждое соединение в состоянии медленного старта с начальным окном перегрузки. Конечным точкам СЛЕДУЕТ использовать начальное окно в десять максимальных размеров дейтаграммы max_datagram_size, ограничивая его большим из значений 14 720 байтов и удвоенного максимального размера дейтаграммы. Это следует анализу и рекомендациям [RFC6928], увеличивая предел в байтах с учётом меньших накладных расходов UDP — 8 байтов против 20 у TCP.

Если максимальный размер дейтаграммы меняется во время соединения, начальное окно СЛЕДУЕТ пересчитать. Если размер уменьшается для завершения рукопожатия, окно перегрузки СЛЕДУЕТ установить равным новому начальному окну.

До проверки адреса клиента сервер может дополнительно ограничиваться пределом усиления из раздела 8.1 [QUIC-TRANSPORT]. Хотя этот предел может мешать полному использованию окна и тем самым замедлять его рост, непосредственно на окно он не влияет.

Минимальное окно перегрузки — наименьшее значение, которое окно может принять в ответ на потерю, увеличение сообщённого другой стороной счётчика ECN-CE или устойчивую перегрузку. РЕКОМЕНДУЕМОЕ значение — 2 * max_datagram_size.

7.3. Состояния управления перегрузкой

Механизм NewReno, описанный в этом документе, имеет три состояния. Новый путь или устойчивая перегрузка приводят в состояние медленного старта. Потеря или увеличение ECN-CE переводит медленный старт либо предотвращение перегрузки в восстановление. Подтверждение пакета, отправленного во время восстановления, переводит механизм в предотвращение перегрузки. Эти состояния и переходы описаны далее.

7.3.1. Медленный старт

Отправитель NewReno находится в состоянии медленного старта, когда окно перегрузки меньше порога медленного старта. Отправитель начинает с этого состояния, поскольку порог изначально равен бесконечности.

При обработке каждого подтверждения в состоянии медленного старта окно перегрузки увеличивается на число подтверждённых байтов. Это приводит к экспоненциальному росту окна.

Отправитель ДОЛЖЕН выйти из медленного старта и перейти в период восстановления при потере пакета или увеличении сообщённого другой стороной счётчика ECN-CE.

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

7.3.2. Восстановление

Отправитель NewReno входит в период восстановления при обнаружении потери пакета или увеличении сообщённого другой стороной счётчика ECN-CE. Отправитель, уже находящийся в восстановлении, остаётся в нём и не входит повторно.

При входе в восстановление отправитель ДОЛЖЕН установить порог медленного старта равным половине окна перегрузки на момент обнаружения потери. До выхода из восстановления окно перегрузки ДОЛЖНО быть установлено равным уменьшенному порогу медленного старта.

Реализации МОГУТ уменьшать окно немедленно при входе в восстановление либо использовать другие механизмы, например пропорциональное снижение скорости [PRR], чтобы уменьшать его постепенно. При немедленном уменьшении до него можно отправить один пакет. Это ускоряет восстановление, если данные потерянного пакета передаются повторно, и аналогично TCP из раздела 5 [RFC6675].

Период восстановления призван ограничить уменьшение окна одним разом за круговой обход. Поэтому во время восстановления окно не меняется в ответ на новые потери или увеличение ECN-CE.

Период восстановления заканчивается и отправитель переходит к предотвращению перегрузки, когда подтверждён пакет, отправленный во время восстановления. Это несколько отличается от определения TCP, где восстановление заканчивается подтверждением потерянного сегмента, вызвавшего его начало [RFC5681].

7.3.3. Предотвращение перегрузки

Отправитель NewReno находится в состоянии предотвращения перегрузки, когда окно равно порогу медленного старта или превышает его и период восстановления не идёт.

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

При потере пакета или увеличении сообщённого другой стороной ECN-CE отправитель выходит из предотвращения перегрузки и переходит в восстановление.

7.4. Игнорирование потери нерасшифровываемых пакетов

Во время рукопожатия некоторые ключи защиты пакетов могут быть недоступны при поступлении пакета, и получатель может отбросить его. В частности, пакеты Handshake и 0-RTT нельзя обработать до поступления Initial, а пакеты 1-RTT — до завершения рукопожатия. Конечные точки МОГУТ игнорировать потерю пакетов Handshake, 0-RTT и 1-RTT, которые могли прибыть до получения другой стороной ключей для их обработки. Конечные точки НЕ ДОЛЖНЫ игнорировать потерю пакетов, отправленных после самого раннего подтверждённого пакета данного пространства номеров.

7.5. Пробный тайм-аут

Пробные пакеты НЕ ДОЛЖНЫ блокироваться механизмом управления перегрузкой. Однако отправитель ДОЛЖЕН учитывать их как дополнительные пакеты в пути, поскольку они увеличивают нагрузку на сеть без установления потери. Отправка пробных пакетов может привести к превышению байтами в пути окна перегрузки до получения подтверждения, устанавливающего потерю или доставку пакетов.

7.6. Устойчивая перегрузка

Когда отправитель устанавливает потерю всех пакетов, отправленных за достаточно продолжительный период, считается, что сеть испытывает устойчивую перегрузку.

7.6.1. Продолжительность

Продолжительность устойчивой перегрузки вычисляется так:

В отличие от расчёта PTO в разделе 6.2, эта продолжительность включает max_ack_delay независимо от пространств номеров, в которых установлены потери.

Это время позволяет отправителю до установления устойчивой перегрузки отправить столько же пакетов, включая некоторые в ответ на истечение PTO, сколько TCP с пробами Tail Loss Probe [RFC8985] и RTO [RFC5681].

Большие значения kPersistentCongestionThreshold снижают скорость реакции отправителя на устойчивую перегрузку и могут приводить к агрессивной отправке в перегруженную сеть. Слишком малое значение может вызвать ненужное объявление устойчивой перегрузки и снижение пропускной способности отправителя.

РЕКОМЕНДУЕМОЕ значение kPersistentCongestionThreshold — 3. Оно даёт поведение, приблизительно эквивалентное объявлению отправителем TCP RTO после двух TLP.

Эта конструкция не использует последовательные события PTO для установления устойчивой перегрузки, поскольку на истечение PTO влияет характер работы приложения. Например, отправитель небольших объёмов данных с паузами между ними каждый раз перезапускает таймер PTO и может долго не дать ему истечь даже без получения подтверждений. Использование продолжительности позволяет установить устойчивую перегрузку независимо от истечения PTO.

7.6.2. Установление устойчивой перегрузки

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

Оба пакета ДОЛЖНЫ вызывать подтверждение, поскольку получатель обязан подтверждать в пределах максимальной задержки только такие пакеты; см. раздел 13.2 [QUIC-TRANSPORT].

Период устойчивой перегрузки НЕ СЛЕДУЕТ начинать до получения хотя бы одного отсчёта RTT. До первого отсчёта отправитель устанавливает PTO по начальному RTT (раздел 6.2.2), который может значительно превышать фактический. Требование предыдущего отсчёта предотвращает установление устойчивой перегрузки при потенциально недостаточном числе проб.

Поскольку перегрузка сети не зависит от пространств номеров, при установлении устойчивой перегрузки СЛЕДУЕТ учитывать пакеты из разных пространств. Отправитель без состояния всех пространств или реализация, не способная сравнивать время отправки между ними, МОЖЕТ использовать состояние только подтверждённого пространства. Это может привести к ошибочному объявлению устойчивой перегрузки, но не к пропуску её обнаружения.

При объявлении устойчивой перегрузки окно отправителя ДОЛЖНО уменьшаться до минимального kMinimumWindow, аналогично реакции TCP на RTO [RFC5681].

7.6.3. Пример

Пример показывает, как отправитель может установить устойчивую перегрузку. Предположим:

Последовательность событий:

Таблица 1

Пакеты со 2-го по 8-й объявляются потерянными при получении подтверждения пакета 9 в момент t = 12,2.

Период перегрузки вычисляется как время между самым ранним и самым поздним потерянными пакетами: 8 − 1 = 7. Продолжительность устойчивой перегрузки равна 2 × 3 = 6. Поскольку порог достигнут и ни один пакет между самым ранним и самым поздним потерянными не подтверждён, считается, что сеть испытывала устойчивую перегрузку.

Хотя в примере PTO истекает, для установления устойчивой перегрузки это не обязательно.

7.7. Равномерная отправка

Отправителю СЛЕДУЕТ распределять по времени отправку всех пакетов в пути на основе данных механизма управления перегрузкой.

Отправка нескольких пакетов без задержки создаёт всплеск, способный вызвать кратковременную перегрузку и потери. Отправители ДОЛЖНЫ либо распределять отправку по времени, либо ограничивать такие всплески. Им СЛЕДУЕТ ограничивать всплески начальным окном перегрузки (раздел 7.2). Отправитель, знающий, что путь к получателю способен поглотить большие всплески, МОЖЕТ установить более высокий предел.

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

Своевременная доставка ACK важна для эффективного восстановления потерь. Чтобы не задерживать их доставку другой стороне, отправку пакетов только с ACK СЛЕДУЕТ не распределять по времени.

Конечные точки могут реализовать распределение по своему усмотрению. Идеальный отправитель размещает пакеты во времени точно равномерно. Для управления перегрузкой на основе окна, как в этом документе, скорость можно вычислить, усреднив окно по RTT. В байтах за единицу времени, когда congestion_window задано в байтах:

rate = N * congestion_window / smoothed_rtt

Или как интервал между пакетами:

interval = (smoothed_rtt * packet_size / congestion_window) / N

Небольшое значение N не меньше 1, например 1,25, гарантирует, что изменения RTT не приведут к неполному использованию окна перегрузки.

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

Одна возможная стратегия использует алгоритм дырявого ведра: ёмкость ведра ограничена максимальным размером всплеска, а скорость наполнения определяется приведённой функцией.

7.8. Неполное использование окна перегрузки

Если число байтов в пути меньше окна перегрузки и отправка не ограничена распределением по времени, окно используется не полностью. Это может происходить из-за недостатка данных приложения или ограничений управления потоком. В таком случае окно НЕ СЛЕДУЕТ увеличивать ни при медленном старте, ни при предотвращении перегрузки.

Отправитель, распределяющий пакеты по времени (раздел 7.7), может задерживать их и поэтому не использовать окно полностью. Ему НЕ СЛЕДУЕТ считать себя ограниченным приложением, если без этой задержки окно использовалось бы полностью.

Отправитель МОЖЕТ реализовать другие механизмы обновления окна после периодов неполного использования, например предложенные для TCP в [RFC7661].

8. Вопросы безопасности

8.1. Сигналы потери и перегрузки

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

8.2. Анализ трафика

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

8.3. Неверное сообщение меток ECN

Получатель может неверно сообщать метки ECN, изменяя реакцию отправителя на перегрузку. Сокрытие меток ECN-CE может заставить отправителя повысить скорость, что способно вызвать перегрузку и потери.

Отправитель может обнаруживать сокрытие, время от времени маркируя отправляемые пакеты ECN-CE. Если при подтверждении такого пакета не сообщается, что он был помечен CE, отправитель может отключить ECN для пути, перестав устанавливать кодовые точки ECN-Capable Transport (ECT) в последующих пакетах этого пути [RFC3168].

Сообщение дополнительных меток ECN-CE заставит отправителя снизить скорость. По эффекту это похоже на объявление меньших ограничений управления потоком соединения, поэтому преимуществ не даёт.

Конечные точки сами выбирают механизм управления перегрузкой. Он реагирует на сообщения ECN-CE снижением скорости, но конкретная реакция может различаться. Метки можно считать эквивалентными потерям [RFC3168], однако возможны и другие варианты реакции, например [RFC8511] или [RFC8311].

9. Ссылки

9.1. Нормативные ссылки

9.2. Информационные ссылки

Приложение A. Псевдокод восстановления после потерь

Далее описан пример реализации механизмов обнаружения потерь из раздела 6. Фрагменты псевдокода в этом разделе лицензируются как компоненты кода; см. уведомление об авторских правах.

A.1. Отслеживание отправленных пакетов

Для правильной реализации управления перегрузкой отправитель QUIC отслеживает каждый пакет, вызывающий подтверждение, пока тот не будет подтверждён или объявлен потерянным. Предполагается, что реализации способны обращаться к этим сведениям по номеру пакета и криптографическому контексту и хранить поля пакетов (приложение A.1.1) для восстановления потерь и управления перегрузкой.

После объявления пакета потерянным конечная точка может некоторое время сохранять его состояние с учётом возможной перестановки пакетов; см. раздел 13.3 [QUIC-TRANSPORT]. Это позволяет обнаруживать ложные повторные передачи.

Отправленные пакеты отслеживаются отдельно для каждого пространства номеров, а обработка ACK применяется только к одному пространству.

A.1.1. Поля отправленного пакета

packet_number — номер отправленного пакета.

ack_eliciting — логическое значение, указывающее, вызывает ли пакет подтверждение. Если да, ожидается подтверждение, хотя другая сторона может задержать отправку содержащего его ACK на время до max_ack_delay.

in_flight — логическое значение, указывающее, учитывается ли пакет в числе байтов в пути.

sent_bytes — число байтов, отправленных в пакете, без накладных расходов UDP и IP, но с накладными расходами формирования пакета QUIC.

time_sent — время отправки пакета.

A.2. Основные константы

Константы восстановления потерь основаны на RFC, научных работах и общепринятой практике.

kPacketThreshold — максимальная перестановка в пакетах, после которой механизм обнаружения по порогу пакетов считает пакет потерянным. В разделе 6.1.1 рекомендовано значение 3.

kTimeThreshold — максимальная перестановка по времени, после которой механизм обнаружения по временному порогу считает пакет потерянным. Выражается множителем RTT. В разделе 6.1.2 рекомендовано 9/8.

kGranularity — разрешение таймера. Значение зависит от системы; раздел 6.1.2 рекомендует 1 мс.

kInitialRtt — RTT, используемый до получения отсчёта. В разделе 6.2.2 рекомендовано 333 мс.

kPacketNumberSpace — перечисление трёх пространств номеров:

A.3. Основные переменные

В этом разделе описаны переменные, необходимые для реализации механизмов управления перегрузкой.

latest_rtt — последнее измерение RTT при получении подтверждения ранее неподтверждённого пакета.

smoothed_rtt — сглаженный RTT соединения, вычисляемый согласно разделу 5.3.

rttvar — вариация RTT, вычисляемая согласно разделу 5.3.

min_rtt — минимальный RTT, наблюдавшийся за некоторый период без учёта задержки подтверждения, как описано в разделе 5.2.

first_rtt_sample — время получения первого отсчёта RTT.

max_ack_delay — максимальное время, на которое получатель намерен задерживать подтверждения пакетов пространства Application Data, определённое одноимённым транспортным параметром (раздел 18.2 [QUIC-TRANSPORT]). Фактическое ack_delay в полученном ACK может быть больше из-за запоздалого срабатывания таймеров, перестановки или потери.

loss_detection_timer — многорежимный таймер обнаружения потерь.

pto_count — число отправок по PTO без получения подтверждения.

time_of_last_ack_eliciting_packet[kPacketNumberSpace] — время отправки последнего пакета, вызывающего подтверждение.

largest_acked_packet[kPacketNumberSpace] — наибольший номер пакета, подтверждённый к текущему моменту в данном пространстве.

loss_time[kPacketNumberSpace] — время, когда следующий пакет пространства можно считать потерянным по превышению временного окна перестановки.

sent_packets[kPacketNumberSpace] — соответствие между номерами пакетов пространства и сведениями о них; подробнее см. приложение A.1.

A.4. Инициализация

В начале соединения переменные обнаружения потерь инициализируются следующим образом:

A.5. При отправке пакета

После отправки пакета сведения о нём сохраняются. Параметры OnPacketSent подробно описаны в приложении A.1.1. Ниже приведён псевдокод OnPacketSent:

A.6. При получении дейтаграммы

Если сервер заблокирован ограничением усиления, получение дейтаграммы разблокирует его, даже когда ни один пакет в ней успешно не обработан. В таком случае таймер PTO необходимо запустить заново.

Псевдокод OnDatagramReceived:

A.7. При получении подтверждения

Полученный кадр ACK может впервые подтвердить любое число пакетов. Ниже приведён псевдокод OnAckReceived и UpdateRtt:

A.8. Установка таймера обнаружения потерь

Обнаружение потерь QUIC использует один таймер для всех случаев обнаружения потерь по тайм-ауту. Его длительность зависит от режима, устанавливаемого в описанных ниже событиях пакетов и таймеров. Функция SetLossDetectionTimer показывает, как устанавливается единый таймер.

Этот алгоритм может установить таймер на время в прошлом, особенно при запоздалом пробуждении таймеров. Таймеры, установленные в прошлом, срабатывают немедленно.

Псевдокод SetLossDetectionTimer; оператор ^ обозначает возведение в степень:

A.9. При истечении таймера

Когда таймер обнаружения потерь истекает, выполняемое действие определяется его режимом. Псевдокод OnLossDetectionTimeout:

A.10. Обнаружение потерянных пакетов

DetectAndRemoveLostPackets вызывается при каждом получении ACK или истечении таймера обнаружения по временному порогу. Функция работает с sent_packets соответствующего пространства номеров и возвращает список пакетов, которые только что обнаружены как потерянные.

Псевдокод DetectAndRemoveLostPackets:

A.11. При отбрасывании ключей Initial или Handshake

При отбрасывании ключей Initial или Handshake пакеты соответствующего пространства отбрасываются, а состояние обнаружения потерь обновляется. Псевдокод OnPacketNumberSpaceDiscarded:

Приложение B. Псевдокод управления перегрузкой

Далее описан пример реализации механизма управления перегрузкой из раздела 7. Фрагменты псевдокода в этом разделе лицензируются как компоненты кода; см. уведомление об авторских правах.

B.1. Основные константы

Константы управления перегрузкой основаны на RFC, научных работах и общепринятой практике.

kInitialWindow — ограничение начального числа байтов в пути по умолчанию, как описано в разделе 7.2.

kMinimumWindow — минимальное окно перегрузки в байтах согласно разделу 7.2.

kLossReductionFactor — множитель, уменьшающий окно перегрузки при обнаружении нового события потери. Раздел 7 рекомендует значение 0,5.

kPersistentCongestionThreshold — время до установления устойчивой перегрузки, выраженное множителем PTO. Раздел 7.6 рекомендует значение 3.

B.2. Основные переменные

В этом разделе описаны переменные, необходимые для реализации механизмов управления перегрузкой.

max_datagram_size — текущий максимальный размер полезной нагрузки отправителя без накладных расходов UDP и IP; используется для вычисления окна перегрузки. Конечная точка устанавливает значение на основе максимального размера единицы передачи пути PMTU (раздел 14.2 [QUIC-TRANSPORT]); минимум — 1200 байтов.

ecn_ce_counters[kPacketNumberSpace] — наибольшее значение счётчика ECN-CE в данном пространстве номеров, сообщённое другой стороной в ACK. Используется для обнаружения роста счётчика.

bytes_in_flight — сумма размеров в байтах всех отправленных пакетов, содержащих хотя бы один кадр, вызывающий подтверждение, или PADDING, которые ещё не подтверждены и не объявлены потерянными. Размер не включает накладные расходы IP и UDP, но включает заголовок QUIC и расходы аутентифицированного шифрования с присоединёнными данными AEAD. Пакеты только с ACK не учитываются в bytes_in_flight, чтобы управление перегрузкой не препятствовало обратной связи о перегрузке.

congestion_window — максимальное число байтов, которым разрешено находиться в пути.

congestion_recovery_start_time — время начала текущего восстановления вследствие обнаружения потери или ECN. При подтверждении пакета, отправленного после этого времени, QUIC выходит из восстановления.

ssthresh — порог медленного старта в байтах. Когда окно меньше ssthresh, действует медленный старт и окно растёт на число подтверждённых байтов.

Псевдокод управления перегрузкой также обращается к некоторым переменным псевдокода восстановления после потерь.

B.3. Инициализация

В начале соединения переменные управления перегрузкой инициализируются следующим образом:

B.4. При отправке пакета

При отправке пакета, содержащего кадры, отличные от ACK, этот пакет увеличивает bytes_in_flight:

B.5. При подтверждении пакета

Функция вызывается из OnAckReceived обнаружения потерь и получает только что подтверждённые acked_packets из sent_packets.

При предотвращении перегрузки разработчикам, использующим целочисленное представление congestion_window, следует осторожно выполнять деление; они могут использовать альтернативный подход, предложенный в разделе 2.1 [RFC3465].

B.6. При новом событии перегрузки

Функция вызывается из ProcessECN и OnPacketsLost при обнаружении нового события перегрузки. Если восстановление ещё не идёт, она начинает его и немедленно уменьшает порог медленного старта и окно перегрузки.

B.7. Обработка информации ECN

Функция вызывается при получении от другой стороны кадра ACK с секцией ECN.

B.8. При потере пакетов

Функция вызывается, когда DetectAndRemoveLostPackets считает пакеты потерянными.

B.9. Удаление отброшенных пакетов из числа байтов в пути

При отбрасывании ключей Initial или Handshake отправленные в этом пространстве пакеты больше не учитываются в числе байтов в пути. Псевдокод RemoveFromBytesInFlight:

Участники

Рабочая группа IETF QUIC получила огромную поддержку множества людей. Существенный вклад в этот документ внесли Alessandro Ghedini, Benjamin Saunders, Gorry Fairhurst, 山本和彦 (Kazu Yamamoto), 奥 一穂 (Kazuho Oku), Lars Eggert, Magnus Westerlund, Marten Seemann, Martin Duke, Martin Thomson, Mirja Kühlewind, Nick Banks и Praveen Balasubramanian.

Адреса авторов

Перевод: RFCNET · rfcnet.ru

Original copyright notice

Неофициальный перевод. При расхождениях см. оригинал.