RFC 8186 Support of the IEEE 1588 Timestamp Format in a Two-Way Active Measurement Protocol (TWAMP)

Internet Engineering Task Force (IETF)                         G. Mirsky
Request for Comments: 8186                                     ZTE Corp.
Category: Standards Track                                      I. Meilik
ISSN: 2070-1721                                                 Broadcom
                                                               June 2017

Support of the IEEE 1588 Timestamp Format in a Two-Way Active Measurement Protocol (TWAMP)

Поддержка меток формата IEEE 1588 в протоколе TWAMP

PDF

Аннотация

В этом документе описана необязательная функция для протокола активных измерения, позволяющая применять метки времени в формате протокола точного времени (Precision Time Protocol), определённом в IEEE 1588v2 в качестве альтернативы используемым в настоящее врямя меткам протокола сетевого времени (Network Time Protocol).

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

Документ относится к категории Internet Standards Track.

Документ является результатом работы IETF1 и представляет согласованный взгляд сообщества IETF. Документ прошёл открытое обсуждение и был одобрен для публикации IESG2. Дополнительную информацию о стандартах Internet можно найти в разделе 2 в RFC 7841.

Информацию о текущем статусе документа, ошибках и способах обратной связи можно найти по ссылке http://www.rfc-editor.org/info/rfc8186.

Авторские права

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

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

1. Введение

Протокол односторонних активных измерений (One-Way Active Measurement Protocol или OWAMP) [RFC4656] задаёт лишь формат меток времени NTP [RFC5905] для применения в протоколе OWAMP-Test. Протокол двухсторонних активных измерений (Two-Way Active Measurement Protocol или TWAMP) [RFC5357] принял формат пакетов OWAMP-Test и дополнил его форматом отражённых тестовых пакетов. Предполагается, что метки времени в пакетах отправителя и рефлектора используют 64-битовый формат NTP [RFC5905]. Протокол NTP при использовании в Internet обычно обеспечивает точность от 5 до 100 мсек. Проведённые недавно исследования показали, что 90% устройств обеспечивают точность лучше 100 мсек и 99% — лучше 1 сек. Следует отметить, что NTP синхронизирует часы плоскости управления, а не плоскости данных. Распределение времени внутри узла может поддерживаться независимым доменом NTP или через обмен между процессами в многопроцессорной распределённой системе. Любое из этих решений подвержено влиянию дополнительных задержек в очередях, негативно влияющих на точность часов в плоскости данных.

Протокол точного времени (Precision Time Protocol или PTP) [IEEE.1588] получил широкую поддержку с момента разработки OWAMP и TWAMP. В PTP использует поддержку в пути и другие механизмы, обеспечивающие точность в доли микросекунд. Протокол PTP сейчас поддерживается во многих реализациях скоростных машин пересылки, таким образом, точность PTP является точностью часов в плоскости данных. Возможность использовать более точные часы в качестве источника временных меток при измерении производительности IP является одним из преимуществ этой спецификации. Другое преимущество реализуется за счёт упрощения аппаратной части в плоскости данных. Для поддержки OWAMP или TWAMP метки времени тестового протокола должны быть преобразованы из формата PTP в NTP. Для этого нужны ресурсы, применение микрокода или дополнительных элементов обработки, что всегда ограничено. Для решения проблемы этот документ предлагает расширения протоколов Control и Test, поддерживающие использование формата IEEE 1588v2 как необязательной альтернативы формату меток NTP.

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

1.1. Используемые соглашения

1.1.1. Сокращения

NTP

Network Time Protocol — протокол сетевого времени

PTP

Precision Time Protocol — протокол точного времени.

TWAMP

Two-Way Active Measurement Protocol — двухсторонний протокол активных измерений.

OWAMP

One-Way Active Measurement Protocol — односторонний протокол активных измерений.

1.1.2. Уровни требований

Ключевые слова необходимо (MUST), недопустимо (MUST NOT), требуется (REQUIRED), нужно (SHALL), не следует (SHALL NOT), следует (SHOULD), не нужно (SHOULD NOT), рекомендуется (RECOMMENDED), не рекомендуется (NOT RECOMMENDED), возможно (MAY), необязательно (OPTIONAL) в данном документе интерпретируются в соответствии с BCP 14 [RFC2119] [RFC8174] тогда и только тогда, когда они выделены шрифтом, как показано здесь.

2. Расширения OWAMP и TWAMP

Соединения OWAMP организуются по процедуре, заданной в параграфе 3.1 [RFC4656], а в TWAMP применяются дополнительные шаги, описанные в параграфе 3.1 [RFC5357]. В этих процедурах поле Modes служит для идентификации и выбора конкретных свойств связи. В то же время поле Modes признается и применяется как механизм расширения [RFC6038]. Новой функции требуется 1 битовая позиция для Server и Control-Client, чтобы согласовать формат меток времени, используемый в некоторых или всех тестовых сессиях, вызванных из этого управляющего соединения. Конечная точка соединения — Session-Sender и Session-Receiver (OWAMP) или Session-Reflector (TWAMP), — поддерживающая это расширения, должна быть способна интерпретировать форматы меток времени NTP и PTPv2. Если конечная точка не поддерживает это расширения, флаг PTPv2 Timestamp должен быть сброшен (0), поскольку он размещается в поле Must Be Zero. Если флаг PTPv2 Timestamp имеет значение 0, анонсирующий узел может использовать и интерпретировать лишь метки формата NTP. Реализации OWAMP и/или TWAMP могут включать элемент настройки для обхода процесса согласования и использования вместо него локально настроенных значений.

Использование флагов PTPv2 Timestamp рассматривается в последующих параграфах. Детали выделенных значений и битовые позиции описаны в разделе 3.

2.1. Согласование формата меток при организации соединения OWAMP

В OWAMP-Test [RFC4656] элементы Session-Receiver и/или Fetch-Client интерпретируют собранные метки времени. Таким образом, Server использует поле Modes для указания форматов, которые способен интерпретировать Session-Receiver. Control-Client проверяет значения, заданные сервером для форматов меток времени и устанавливает значения в поле Modes сообщения Set-Up-Response в соответствии с форматами меток, которые может использовать Session-Sender. Правила установки флагов временных меток в поле Modes сообщений Server Greeting и Set-Up-Response и их интерпретации приведены ниже.

  • Если Session-Receiver поддерживает это расширения, то Server, организующий тестовую сессиюю от его имени, должен установить (1) флаг PTPv2 Timestamp в сообщении Server Greeting в соответствии с требованиями, приведёнными в параграфе 2. Расширения OWAMP и TWAMP. В ином случае флаг PTPv2 Timestamp сбрасывается (0) для индикации того, что Session-Receiver интерпретирует лишь формат NTP.

  • Если Control-Client получает приветственное сообщение (greeting) со сброшенным флагом PTPv2 Timestamp, Session-Sender должен использовать для меток в тестовой сессии формат NTP, а клиенту Control-Client следует установить для флага PTPv2 Timestamp значение 0 в соответствие с [RFC4656]. Если Session-Sender не может использовать метки NTP, клиенту Control-Client следует закрыть соединение TCP, связанное с сессией OWAMP-Control.

  • Если Control-Client получает приветственное сообщение с установленным флагом PTPv2 Timestamp и Session-Sender может создавать метки формата PTPv2, клиент Control-Client должен установить (1) флаг PTPv2 Timestamp в поле Modes сообщения Set-Up-Response, Session-Sender должен использовать формат PTPv2.

  • Если Session-Sender не поддерживает это расширение и может создавать метки только в формате NTP, флаг PTPv2 Timestamp в поле Modes сообщения Set-Up-Response будет сбрасываться (0) как часть поля Must Be Zero и Session-Sender будет использовать формат NTP.

Если OWAMP-Control использует команды Fetch-Session, выбор и использование формата меток времени определяется локальным решением Session-Sender и Session-Receiver.

2.2. Согласование формата меток при организации соединения TWAMP

В TWAMP-Test [RFC5357] отправитель Session-Sender интерпретирует собранные метки времени. Поэтому в поле Modes сервер анонсирует форматы меток, которые Session-Reflector может использовать в сообщении TWAMP-Test. Выбор формата меток для использования Session-Sender определяется локальным решением. Control-Client проверяет поле Modes и устанавливает флаги меток для индикации формата, который будет использовать Session-Reflector. Правила установки и интерпретации флагов указаны ниже.

  • Сервер должен установить (1) флаг PTPv2 Timestamp в приветственном сообщении, если Session-Reflector может создавать метки в формате PTPv2. В ином случая флаг PTPv2 Timestamp должен сбрасываться (0).

  • Если флаг PTPv2 Timestamp в принятом сообщении Server Greeting сброшен (0), Session-Reflector не поддерживает это расширение и будет использовать формат NTP. Клиенту Control-Client следует сбросить (0) флаг PTPv2 Timestamp в сообщении Set-Up-Response в соответствии с [RFC4656].

  • Control-Client должен установить (1) флаг PTPv2 Timestamp в поле Modes сообщения Set-Up-Response, если Server указал, что Session-Reflector может применять метки формата PTPv2. В противном случае флаг должен быть сброшен (0).

  • Если флаг PTPv2 Timestamp в сообщении Set-Up-Response сброшен (0), это значит, что Session-Sender может интерпретировать лишь метки NTP, поэтому Session-Reflector должен использовать формат NTP. Если Session-Reflector не поддерживает формат NTP, сервер должен закрыть соединение TCP, связанное с сессией TWAMP-Control.

2.3. Обновления OWAMP-Test и TWAMP-Test

Участники тестовой сессии должны указать, какой формат меток времени они будут применять. В настоящее время для этого служит поле Z в Error Estimate, определённое в параграфе 4.1.2 [RFC4656]. Однако этот документ расширяет Error Estimate для указания формата собираемых меток в дополнение к оценке ошибки синхронизации. Эта спецификация также меняет семантику бита Z (поле между S и Scale fields) для указания формата Timestamp. Поле должно иметь значение 0 для 64-битового формата NTP и 1 для усечённого формата PTPv2.

Поэтому значение поля Z из Error Estimate, Sender Error Estimate (TWAMP) или Send Error Estimate (OWAMP) и Receive Error Estimate не следует игнорировать и оно должно использоваться при расчёте показателей задержки и её вариаций на основе собранных меток времени.

2.3.1. Режим TWAMP Light

Этот документ не задаёт способ информирования Session-Sender и Session-Reflector в режиме TWAMP Light об используемом формате меток времени. Предполагается, что может применяться, например, конфигурация, направляющая Session-Sender и Session-Reflector на использование формата меток в соответствии с их возможностями и правилами из параграфа 2.2.

3. Взаимодействие с IANA

Агентство IANA зарегистрировало PTPv2 Timestamp в реестре TWAMP-Modes [RFC5618].

Таблица 1. Новая возможность временных меток.

Битовая позиция

Описание

Семантика

Документ

9

PTPv2 Timestamp Capability

Раздел 2

RFC 8186 (этот документ)

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

Использование определённого формата меток времени в тестовой сессии не создаёт дополнительной угрозы безопасности для хостов, взаимодействующих с OWAMP и/или TWAMP, как определено в [RFC4656] и [RFC5357], соответственно. Соображения безопасности, применимые к любому активному измерению в работающей сети, уместны и здесь. См. разделы «Вопросы безопасности» в [RFC4656] и [RFC5357].

5. Нормативные документы

[IEEE.1588] IEEE, «IEEE Standard for a Precision Clock Synchronization Protocol for Networked Measurement and Control Systems», IEEE Std 1588-2008, DOI 10.1109/IEEESTD.2008.4579760.

[RFC2119] Bradner, S., «Key words for use in RFCs to Indicate Requirement Levels», BCP 14, RFC 2119, DOI 10.17487/RFC2119, March 1997, <http://www.rfc-editor.org/info/rfc2119>.

[RFC4656] Shalunov, S., Teitelbaum, B., Karp, A., Boote, J., and M. Zekauskas, «A One-way Active Measurement Protocol (OWAMP)», RFC 4656, DOI 10.17487/RFC4656, September 2006, <http://www.rfc-editor.org/info/rfc4656>.

[RFC5357] Hedayat, K., Krzanowski, R., Morton, A., Yum, K., and J. Babiarz, «A Two-Way Active Measurement Protocol (TWAMP)», RFC 5357, DOI 10.17487/RFC5357, October 2008, <http://www.rfc-editor.org/info/rfc5357>.

[RFC5618] Morton, A. and K. Hedayat, «Mixed Security Mode for the Two-Way Active Measurement Protocol (TWAMP)», RFC 5618, DOI 10.17487/RFC5618, August 2009, <http://www.rfc-editor.org/info/rfc5618>.

[RFC5905] Mills, D., Martin, J., Ed., Burbank, J., and W. Kasch, «Network Time Protocol Version 4: Protocol and Algorithms Specification», RFC 5905, DOI 10.17487/RFC5905, June 2010, <http://www.rfc-editor.org/info/rfc5905>.

[RFC6038] Morton, A. and L. Ciavattone, «Two-Way Active Measurement Protocol (TWAMP) Reflect Octets and Symmetrical Size Features», RFC 6038, DOI 10.17487/RFC6038, October 2010, <http://www.rfc-editor.org/info/rfc6038>.

[RFC8174] Leiba, B., «Ambiguity of Uppercase vs Lowercase in RFC 2119 Key Words», BCP 14, RFC 8174, DOI 10.17487/RFC8174, May 2017, <http://www.rfc-editor.org/info/rfc8174>.

Благодарности

Авторы признательны Ramanathan Lakshmikanthan и Suchit Bansal за дельные предложения. Спасибо также David Allan за тщательное рецензирование и вдумчивые комментарии.

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

Greg Mirsky

ZTE Corp.

Email: gregimirsky@gmail.com

Israel Meilik

Broadcom

Email: israel@broadcom.com


Перевод на русский язык

Николай Малых

nmalykh@protokols.ru

1Internet Engineering Task Force — комиссия по решению инженерных задач Internet.

2Internet Engineering Steering Group — комиссия по инженерным разработкам Internet.

Рубрика: RFC | Оставить комментарий

RFC 8126 Guidelines for Writing an IANA Considerations Section in RFCs

Internet Engineering Task Force (IETF)                         M. Cotton
Request for Comments: 8126                                           PTI
BCP: 26                                                         B. Leiba
Obsoletes: 5226                                      Huawei Technologies
Category: Best Current Practice                                T. Narten
ISSN: 2070-1721                                          IBM Corporation
                                                               June 2017

Рекомендации по написанию раздела «Взаимодействие с IANA» в RFC

Guidelines for Writing an IANA Considerations Section in RFCs

PDF

Аннотация

Многие протоколы используют идентификаторы, представляющие собой константы и другие общеизвестные (well-known) значения. Однако после определения протокола и начала его развертывания может потребоваться выделение новых значений (например, для нового типа опций DHCP, нового алгоритма шифрования или аутентификации для IPSec). Для того, чтобы такие параметры имели согласованные значения и интерпретацию в разных реализациях протоколов, требуется централизованное управление выделением значений. Для протоколов IETF функции управления возложены на агентство IANA1.

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

Этот документ служит заменой RFC RFC 5226.

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

Этот документ относится к категории обмена опытом (Internet Best Current Practices)

Документ является результатом работы IETF2 и представляет согласованный взгляд сообщества IETF. Документ прошел открытое обсуждение и был одобрен для публикации IESG3. Дополнительную информацию о BCP можно найти в разделе 2 в RFC 7841.

Информацию о текущем статусе документа, ошибках и способах обратной связи можно найти по ссылке http://www.rfc-editor.org/info/rfc8126.

Авторские права

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

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

1. Введение

Многие протоколы используют точки расширения, которые применяют константы для идентификации разных протокольных параметров. Чтобы гарантировать непротиворечивость значений этих полей и возможность взаимодействие, выделение значений полей зачастую требует координации и централизованного хранения выделенных значений. Поле Protocol в заголовке IP [RFC791] и типы MIME [RFC6838] служат примерами такой координации.

IETF выбирает оператора IFO4 для параметров протокола, определяемого IETF. В соглашении между IETF и текущим IFO (ICANN), это называется оператором услуг протокольных параметров (IPPSO5). Для совместимости с прежней практикой IFO и IPPSO в этом документе обозначаются аббревиатурой IANA [RFC2860].

В этом документе мы будем называть наборы возможных значений полей «пространством имен» (namespace). Привязка или связывание конкретного значения из пространства имен с определенными целями называется выделение (назначением). Используются также термины assigned number (назначенное число), assigned value (назначенное значение), code point (код), protocol constant (протокольная константа), protocol parameter (параметр протокола). Акт назначения называется регистрацией и выполняется в контексте реестра. Термины «назначение» и «регистрация» чередуются в этом документе.

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

Обычно такая информация представляется в специальном разделе IANA Considerations (Взаимодействие с IANA).

1.1. Раздел IANA Considerations предназначен для IANA

Цель создания отдельного раздела IANA Considerations (Взаимодействие с IANA) заключается сбор в одном месте четкой и краткой информации, а также инструкций для IANA. Техническую информацию следует размещать в других частях документа, а в разделе IANA Considerations следует указывать только ссылки на эту информацию (если нужно). При рассмотрении связанных с IANA вопросов в технической части документа будет скрывать ее от целевой аудитории документа и помещает IANA четко увидеть требуемые действия.

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

Действия IANA обычно указываются в виде запросов к IANA (например, «агентство IANA просят выделить значение TBD1 из реестра Frobozz …»), а редактор RFC будет менять текст с учетом предпринятых действий («Агентство IANA выделило значение 83 из реестра Frobozz …»).

1.2. Обновление информации

IANA поддерживает web-страницу с дополнительными разъяснениями помимо предоставленных здесь, такими как незначительные обновления и краткое руководство. Авторам документов следует прочесть эту страницу. Все существенные обновления принятой практики будут вноситься в обновления BCP 26 (данный документ), который является определяющим.

<https://iana.org/help/protocol-registration>

1.3. Краткий контрольный список

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

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

  1. Указать всю информацию, которую нужно знать IANA в разделе «IANA Considerations» вашего документа (см. параграф 1.1).

  2. В этот раздел следует помещать лишь информацию для IANA и назначенных рецензентов. Важные технические сведения нужно размещать в соответствующих разделах документа (см. параграф 1.1).

  3. Отметим, что IESG имеет полномочия разрешения споров, связанных с регистрацией в IANA. При возникновении каких-либо вопросов или проблем следует получить консультацию у куратора вашего документа и/или руководителя рабочей группы, который может при необходимости привлечь руководителя направления — Area Director (см. параграф 3.3).

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

  1. Дать реестру описательное имя и представить краткое описание его применения (см. параграф 2.2).

  2. Определить группу, в которую реестр следует включить (см. параграф 2.1).

  3. Четко указать информацию, которая требуется для регистрации новых значений (см. параграф 2.2). Обязательно указать типы данных, размеры и допустимые значения полей.

  4. Задать начальный набор записей реестра, если они имеются (см. параграф 2.2).

  5. Убедиться, что правила внесения изменений понятны IANA на случай необходимости изменения формата или правил в будущем (см. параграф 2.3 и 9.5).

  6. Указать политику (или набор политик) регистрации для добавления записей в реестр (см. параграф 4 и обратите внимание на примечания в параграфах 4.11 и 4.12).

  7. При использовании политики, требующей назначения экспертов (Expert Review или Specification Required) разобраться с разделом 5 и предоставить рекомендации по рецензированию для экспертов (см. параграф 5.3).

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

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

  1. Четко указать реестр по его имени, возможно дополнив ссылкой (см. параграф 3.1).

  2. Если реестр имеет множество диапазонов для выделения значений, следует четко указать нужный диапазон (см. параграф 3.1).

  3. Следует избегать использования конкретных значений чисел и битов, оставив IANA выбор подходящего на момент регистрации значения (см. параграф 3.1). Это позволит избежать конфликтов между регистрациями.

  4. В полях reference следует указывать документ, который обеспечивает лучшую и наиболее актуальную документацию для регистрируемого элемента. Следует указывать номера разделов, чтобы читателям было легче найти соответствующую документацию (см. параграфы 3.1 и 7).

  5. Следует определить (из справочного документа реестра), какая информация нужна для реестра и четко укажите всю требуемую информацию (см. параграф 3.1).

  6. Следует определить (из справочного документа реестра) все специальные правила или процедуры, которые могут применяться для реестра, такие как публикация в определенном списке рассылки для получения комментариев, и выполнить соответствующие требования (см. параграф 3.1).

  7. Если правила регистрации еще не задают политику внесения изменений, следует убедиться, что IANA точно понимает правила внесения изменений на случай такой потребности в будущем (см. параграф 9.5).

Если создается документ «bis» или иным путем отменяется устаревший документ, следует обратиться к разделу 8.

Если нужна ранняя регистрация (например, для поддержки тестовых реализаций) до завершения документа, следует обратиться к [RFC7120].

Если нужно изменить формат/содержимое или правила для имеющегося реестра, см. параграф 2.4.

Если нужно обновить имеющуюся регистрацию, см. параграф 3.2.

Если нужно закрыть реестр за ненадобностью, см. параграф 9.6.

2. Создание и пересмотр реестров

Определение реестра включает описание создаваемых пространство имен, список начальных значений (если они имеются) и рекомендации по процедуре выделения новых значений.

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

2.1. Организация реестров

Все реестры IANA доступны на странице Protocol Registries по ссылке <https://www.iana.org/protocols>.

На этой странице перечислены реестры, сгруппированные по категориям протоколов, которые объединяют связанные протоколы и упрощают пользователям поиск нужно информации. Ссылки на названия реестров на странице IANA Protocol Registries ведут читателя к страницам с подробным описанием соответствующих реестров.

К сожалению здесь имеется некоторая непоследовательность в именовании. Имена групп называют «protocol category groups» (группы категорий протоколов), «groups» (группы), «top-level registries» (реестры верхнего уровня) или просто «registries» (реестры). Реестры более низкого уровня называют «registries» или «sub-registries» (субреестры).

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

2.2. Документация, требуемая для реестров

Документы, которые создают новое пространство имен (или меняют имеющееся) и предполагают участие IANA в поддержке этого пространства (в качестве репозитория для зарегистрированных значений), должны содержать четкие инструкции для пространства имен в разделе IANA Considerations (Взаимодействие с IANA) или указанных в этом разделе документах.

В частности, такие инструкции должны содержать перечисленные ниже сведения.

Название (имя) реестра

Это имя будет указываться на web-странице IANA и в будущих документах, которым нужны значения из нового пространства. Следует указать полное имя и сокращения, если оно есть. Весьма желательно выбирать имена, которые не будут вносить путаницы с названиями других реестров.

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

Предоставление URL для точного указания реестра поможет IANA понять запрос. Такие URL могут удаляться из RFC при окончательной публикации или сохраняться в документе. Если включен URL iana.org, IANA при необходимости будет корректировать ссылку.

Информация, требуемая для регистрации

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

Применимая политика регистрации

Правила, которые будут применяться для всех будущих регистрационных запросов. См. Раздел 4.

Размер, формат и синтаксис записей реестра

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

Предполагается указание строк в кодировке ASCII и следует четко указать, принимается ли во внимание регистр символов (например, все строки следует задавать в верхнем или нижнем регистре).

Строки, представляющие параметры протокола, редко (или никогда) будут использовать символы, отличные от ASCII. Если такие символы действительно нужны, следует четко указать их допустимость и требование представлять символы не-ASCII в кодировке Unicode с использованием соглашения (U+XXXX). При создании реестра нужно тщательно обдумать вопрос применения символов других языков и рассмотреть рекомендации (например, раздел 10 в [RFC7564]).

Начальное выделение и резервирование

Должны быть указаны все начальные назначения или регистрации. Кроме того, следует указать все значения, для приватного использования (Private Use), а также Reserved, Unassigned и т. п. (см. параграф 6).

Ниже приведен пример раздела IANA Considerations в документе, создающем новый реестр.

—————————————————————

X. Взаимодействие с IANA

Этот документ определяет новую опцию DHCP, названную FooBar (см. раздел y) и выделяет значение TBD1 из пространства имен DHCP Option <https://www.iana.org/assignments/bootp-dhcp-parameters> [RFC2132] [RFC2939].

Тег

Имя

Размер данных

Смысл

TBD1

FooBar

N

Сервер FooBar

Опция FooBar также определяет 8-битовое поле FooType, для которого агенство IANA создает и поддерживает новый реестр «Значения FooType», используемый опцией FooBar. Начальные значения для реестра DHCP FooBar FooType приведены ниже, выделение новых значений будет происходить по процедуре Expert Review [BCP26]. Назначение включает имя DHCP FooBar FooType и связанное с ним значение.

Значение

Имя DHCP FooBar FooType

Определение

0

Резерв

1

Frobnitz

RFCXXXX, параграф y.1

2

NitzFrob

RFCXXXX, параграф y.1

3-254

Не выделены

255

Резерв

Примеры документов, создающих реестры, можно найти в [RFC3575], [RFC3968], [RFC4520].

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

2.3. Указание контроля изменений для реестра

Определения реестров и регистрации в них часто приходится менять после создания. Процесс внесения таких изменений усложняется при отсутствии четкого указания полномочий на изменения. Для реестров, созданных RFC в потоке IETF контроль изменений по умолчанию выполняется IETF через IESG. Это верно и для значений, зарегистрированных RFC из потока IETF.

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

Поэтому рекомендуется создавать все реестры с четким указанием правил изменения и полномочий на это. Для реестров, позволяющих регистрацию вне потока IETF, следует для каждого значения указывать контролера. Если определение или ссылку на зарегистрированное значение когда-либо придется менять, IANA важно знать, кто уполномочен вносить изменения. Например, реестр Media Types [RFC6838] включает поле Change Controller в шаблон регистрации. См. Также параграф 9.5.

2.4. Пересмотр имеющихся реестров

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

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

Такие документы обычно обрабатываются с тем же статусом, что и создавший реестр документ. При некоторых обстоятельствах, таких как явно требуемое прямое изменение (например, добавление колонки status) или исправления предшествующей ошибки, IESG может одобрить обновление реестра без представления нового документа.

Примеры документов с рекомендациями для обновления имеющихся реестров можно найти в [RFC6895], [RFC3228], [RFC3575].

3. Регистрация новых значений в имеющемся реестре

3.1. Требования к документации для регистрации

Часто документы запрашивают выделение в имеющемся реестре (созданном ранее опубликованным документом).

Такие документы должны четко указывать реестр, в котором регистрируется значение. Используется точное имя реестра с web-страницы IANA и указывается, где определен реестр. При ссылке на имеющийся реестр полезно указывать URL для точной идентификации реестра (см. параграф 2.2).

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

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

Обычно численные значения выбираются IANA при утверждении документа и в проектах не следует указывать окончательные значения. Вместо этого в документе следует указывать заменители, такие как TBD1 и TBD2, указывая для каждого элемента свой заменитель. В разделе IANA Considerations следует попросить редактора RFC заменить эти значения назначенными IANA. Когда в проекте нужно указать значения для тестов или предварительных реализаций, нужно запрашивать раннее выделение (см. параграф 3.4) или использовать значения, которые уже были выделены для тестов и экспериментов (если соответствующий реестр позволяет это без явного назначения). Важно не назначать значений в проектах, чтобы агентство IANA не выделило такое значение другому документу. В проекте можно запросить конкретное значение в разделе «Взаимодействие с IANA» и IANA будет учитывать такие запросы, когда это возможно, но предложенное значение может быть выделено для иного применения, пока документ проходит утверждение.

Предлагаемые значения текстовых строк обычно указываются в документе, поскольку конфликты для них менее вероятны. При возникновении конфликта IANA будет обращаться к авторам для согласования иных значений. Когда в проекте нужно указать строковые значения для тестов или ранних реализаций, иногда используется предполагаемое окончательное значение. Однако зачастую лучше использовать черновое значение, возможно включающее номер версии чернового документа. Это позволит отличить ранние реализации от решений, использующих окончательную версию. В документе, предполагающем окончательное значение foobar, можно использовать, например, foobar-testing-draft-05 для версии проекта -05.

Для некоторых реестров существует давняя политика, запрещающая выделять имена или коды случайные по названиям организаций или выражающие гордыню (vanity). Например, коды могут всегда назначаться последовательно, если нет веских причин для исключения. Данный документ не меняет таких правил и не препятствует их дальнейшему применению.

Например, приведенный ниже текст можно использовать для запроса номера опции DHCPv6.

IANA предлагается назначить значение кода TBD1 для опции DNS Recursive Name Server и TBD2 — для Domain Search List из пространства номеров опций DHCP, определенного в параграфе 24.3 RFC 3315.

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

При запросе множества значений обычно полезно включать сводную таблицу добавлений/изменений. Полезно указывать такую таблицу в формате, применяемом на web-сайте IANA. Пример такой таблицы приведен ниже.

Значение

Описание

Ссылка

TBD1

Foobar

Данный RFC, параграф 3.2

TBD2

Gumbo

Данный RFC, параграф 3.3

TBD3

Banana

Данный RFC, параграф 3.4

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

3.2. Обновление имеющихся записей

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

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

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

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

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

  • Назначение IESG, указанного эксперта или иного лица, имеющим право менять регистратора, связанного с данной регистрацией и все требования или условия, связанные с такой заменой. Это в основном позволяет решить проблему недоступности владельца для внесения требуемых изменений.

3.3. Переопределение процедур регистрации

Опыт показал что документированное взаимодействие с IANA для отдельных протоколов не всегда адекватно отражает реальное использование реестра и не всегда достаточно четко. Кроме того, документированное взаимодействие с IANA иной раз оказывается излишне строгим, чтобы даже документы рабочих групп (для которых имеется полное согласие) не могут выполнить регистрацию до реальной публикации RFC.

Чтобы разрешить назначение для таких случаев, IESG предоставлены полномочия переопределять процедуры регистрации и утверждать назначение для конкретного документа.

Это сделано для того, чтобы не переопределять документированные процедуры и не отменять для протоколов необходимость тщательного документирования взаимодействия с IANA. Скорее это разрешает назначение для исключительных случаев, когда необходимость назначения очевидна, а обновить процесс IANA заранее слишком обременительно.

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

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

3.4. Раннее выделение значений

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

IANA имеет механизм для обработки раннего назначения в некоторых случаях (см. [RFC7120]). Обычно не требуется указывать в реестре возможность раннего распределения, поскольку будут применяться общие правила.

4. Выбор политики регистрации и общеизвестные правила

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

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

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

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

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

Возможно самым важным является то, что непроверенные расширения могут препятствовать взаимодействию и снижать уровень безопасности (см. [RFC6709]).

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

Когда это не так, требуется некоторый уровень обзора. Однако важно сбалансировать адекватность обзора и простоту регистрации. Во многих случаях регистраторы не участвуют в IETF, запросы часто приходят от органов стандартизации, а также от организаций, не связанных напрямую с разработкой стандартов, от специализированных работ сообщества (например, проекты с открытым кодом) и т. п. Регистрация не должна быть чересчур сложной, неоправданно затратной (по времени и другим ресурсам) и не должна сталкиваться с необоснованными отказами.

Хотя иногда нужно ограничивать то, что регистрируется (например, для ограниченных ресурсов, таких как биты в байте или элементы, где неподдерживаемые значения могут нарушать работу протокола), во многих случаях наличие в реестре реально применяемых значений важнее. Чрезмерно строгие критерии и издержки (время и усилия) не позволяют людям попытаться зарегистрировать значения. Если реестр не отражает реально используемых элементов протокола, это может отрицательно влиять на развертывание протоколов в Internet и снижать ценность реестра.

Поэтому важно думать конкретно о политике регистрации, а не просто выбирать ее произвольно или копировать текст из другого документа. Рабочим группам и другим разработчикам документов следует осторожно выбирать правила регистрации, когда их документы создают реестры. Следует выбирать наименее строгую политику, которая соответствует потребностям реестра и искать конкретные обоснования для правил, требующих значительного участия сообщества (более строгих, чем обзор экспертов или требование спецификации, если говорить об общеизвестных процедурах). Требования будут меняться от реестра к реестру и со временем этот BCP утратит актуальность.

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

  1. Private Use — приватное использование.

  2. Experimental Use — экспериментальное использование.

  3. Hierarchical Allocation — иерархическое выделение.

  4. First Come First Served — назначение в порядке очереди.

  5. Expert Review — рецензия эксперта.

  6. Specification Required — требование спецификации.

  7. RFC Required — требование публикации RFC.

  8. IETF Review — рецензия IETF.

  9. Standards Action — стандартизация.

  10. IESG Approval — одобрение IESG.

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

Точно так же бывает полезно задать несколько правил, применяемых «параллельно» в зависимости от обстоятельств. Этот вопрос более подробно рассмотрен в параграфе 4.12.

Ниже приведены примеры RFC, где задано несколько «параллельных» правил выделения значений:

LDAP [RFC4520];

идентификаторы TLS ClientCertificateType [RFC5246] (см. ниже);

реестр MPLS Pseudowire Types [RFC4446].

4.1. Приватное использование

Только для частного или локального использования в соответствии с потребностями и целями локального сайта. Не предпринимается попыток предотвращения использования разными сайтами одних и тех же значений с разными (и несовместимыми) целями. Для IANA нет необходимости рассматривать такие назначения и обычно они не важны зрения взаимодействия. Сайт самостоятельно отвечает за использование значений из диапазона Private Use и предотвращение конфликтов (в пределах своей зоны влияния).

Примеры:

специфические для сайта опции DHCP [RFC2939];

реестр Fibre Channel Port Type [RFC4044];

идентификаторы TLS ClientCertificateType из диапазона 224-255 [RFC5246].

4.2. Экспериментальное использование

Похожи на значения для приватного или локального применения, но предназначены для выполнения экспериментов. Более подробную информацию можно найти в [RFC3692]. IANA не записывает назначения из реестров и диапазонов этой категории (поэтому для них не нужен обзор IANA) и такие назначения обычно не важны с точки зрения глобальной совместимости. Если реестр явно не разрешает этого, для документов недопустимо выбирать явные значения из реестров или диапазонов на основе этой политики. Конкретные эксперименты выбирают для себя значения, применяемые в процессе экспериментирования.

Когда коды отведены для экспериментального использования, важно разъяснить предполагаемые ограничения сферы охвата для эксперимента. Например, можно указать, допустимы ли эксперименты с этими значениями в открытой сети Internet или их следует ограничивать замкнутыми средами. Пример этого можно найти в [RFC6994].

Пример:

экспериментальные значения в заголовках IPv4, IPv6, ICMPv4, ICMPv6, UDP и TCP [RFC4727].

4.3. Иерархическое распределение

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

Примеры.

  • Имена DNS — IANA администрирует домены верхнего уровня (TLD6) и, как сказано в [RFC1591]:

    «Для каждого TLD может быть создана иерархия имен. Обычно в TLD общего назначения структура достаточно плоская, т. е. многие организации регистрируются непосредственно в TLD и сами создают структуру нижележащих уровней».

  • Идентификаторы объектов, определенные в ITU-T X.208. В соответствии с <http://www.alvestrand.no/objectid/>, реестры включают:

    • IANA — назначение OID в ветви Private Enterprises (частные предприятия);

    • ANSI — назначение OID в ветви US Organizations;

    • BSI — назначение OID в ветви UK Organizations.

  • Пространства имен URN — IANA регистрирует идентификаторы URN для пространств имен (NID7 [RFC8141]), а получившая NID организация отвечает за назначение URN в своем пространстве имен.

4.4. Назначение в порядке очереди

Кто угодно может получить нужные значения в порядке подачи запросов. Здесь не требуется какого-либо рецензирования, за исключением проверки формальной корректности запроса и отсутствия дублирования. Запрос должен содержать минимальный объем информации, включающий сведения о контактах (в частности, адрес электронной почты) и краткое описание предполагаемого использования запрашиваемых значений. Также должна быть предоставлена дополнительная информация, специфичная для запрашиваемого типа, в соответствии с описанием пространства имен. Для чисел IANA обычно выделяет следующее по порядку значение, но могут быть запрошены и выделены иные значения при наличии смягчающих обстоятельств. Для текстовых строк запрашиваемые значения обычно указываются при запросе.

При создании нового реестра с политикой регистрации First Come First Served помимо поля или ссылки с контактными данными в реестр следует включать поле для контролера изменений. Наличие контролера для каждой записи этого типа делает полномочия внесения изменений в будущем более ясными (см. параграф 2.3).

Важно, чтобы изменения в регистрации кода с политикой First Come First Served сохраняли совместимость с назначенным ранее значением, поэтому вносить изменения нужно с осторожностью. В большинстве случаев контролеру изменений не следует запрашивать несовместимые изменения или менять цели использования выделенного значения (см. параграфы 9.4 и 9.5).

Рабочая группа или иная организация, разрабатывающая протоколы с использованием кодов, назначенных по процедуре First Come First Served, должна быть очень осторожной, чтобы сохранить совместимость кодов в линии с уже выделенными кодами. Если это невозможно, новой работе следует перейти на использование иного кода (и зарегистрировать его использование в нужный момент).

Важно понимать, что процедура First Come First Served не имеет фильтрации и все корректно сформированные запросы выполняются.

Примеры:

имена механизмов SASL [RFC4422];

механизмы протокола LDAP и синтаксис LDAP [RFC4520].

4.5. Рецензия эксперта

Требуется рецензия и одобрение назначенного эксперта (см. раздел 5). Хотя формальное документирование этого не требуется, необходимо представить запрос для назначения эксперта, который оценит работу. В определении реестра нужно четко указать регистраторам, какая информация необходима. Фактический процесс запросов на регистрацию администрирует IANA (см. параграф 1.2).

Эта процедура в предыдущих версиях называлась Designated Expert, а текущее название — Expert Review.

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

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

Хорошие примеры рекомендаций для назначенных экспертов приведены ниже.

Протокол EAP8 [RFC3748], раздел 6 и параграф 7.2

North-Bound Distribution of Link-State and TE Information Using BGP [RFC7752], параграф 5.1

При создании нового реестра с политикой Expert Review помимо поля или ссылки с контактными данными в реестр следует включать поле для контролера изменений. Наличие контролера для каждой записи этого типа делает полномочия внесения изменений в будущем более ясными (см. параграф 2.3).

Примеры:

EAP Method Types [RFC3748];

версии алгоритма HTTP Digest AKA [RFC4169];

схемы URI [RFC7595];

типы GEOPRIV Location [RFC4589].

4.6. Требование наличия спецификации

Для процедуры Specification Required требуется рецензия и одобрение назначенного эксперта (см. раздел 5), а значения и их трактовки должны быть документированы в постоянно и легко доступных публикациях с достаточным уровнем детализации для обеспечения совместимости независимых реализаций. Эта процедура совпадает с рецензированием экспертами (Expert Review), дополненным требованием выпуска спецификации. В дополнение к обычному обзору документа назначенный эксперт будет рецензировать открытую спецификацию, оценивая ее стабильность и доступность, а также четкость и техническую обоснованность для обеспечения совместимости независимых реализаций.

Слова «постоянно и легко доступны» означают, что документ можно будет найти и получить в течение достаточно продолжительного срока после того, как IANA выделит запрошенные значения. Публикация RFC является идеальным способом выполнения этих требований, однако процедура Specification Required может применяться не только к документам, опубликованным в форме RFC.

Для публикации RFC по-прежнему требуется формальная рецензия назначенного эксперта, но предполагается, что обычный процесс обзора RFC обеспечит необходимый уровень совместимости. Рецензия назначенного эксперта остается важной, но не менее важно отметить, что при наличии согласия IETF эксперт может быть чисто формальным (in the rough — см. также последний абзац параграфа 5.4).

Как и для процедуры Expert Review (параграф 4.5) следует предоставить четкие рекомендации для эксперта при определении реестра и важно разобраться с разделом 5.

При указании этой политики просто используется термин Specification Required. В некоторых спецификациях указывается «Expert Review with Specification Required» и это лишь вызывает путаницу.

Примеры:

идентификаторы Diffserv-aware TE Bandwidth Constraints Model [RFC4124];

идентификаторы TLS ClientCertificateType из диапазона 64-223 [RFC5246];

идентификаторы ROHC Profile [RFC5795].

4.7. Требование публикации RFC

Для политики RFC Required запрос регистрации и связанная с ним документация должны быть опубликованы в виде RFC. RFC не обязательно быть из потока IETF, это может быть любой поток RFC (в настоящее время IETF, IRTF, IAB, Independent Submission [RFC5742]).

Если не указано иное, подойдет RFC любого типа (например, Standards Track, BCP, Informational, Experimental, Historic).

Примеры:

номера алгоритмов DNSSEC DNS Security [RFC6014];

реестры Media Control Channel Framework [RFC6230];

использование сертификатов DANE TLSA [RFC6698].

4.8. Рецензия IETF

(Эта процедура называлась IETF Consensus в первой версии документа). В соответствии с политикой IETF Review новые значения выделяются только через RFC из потока IETF Stream, прошедших через IESG как AD-Sponsored или документы рабочих групп IETF [RFC2026] [RFC5378], прошедших процедуру IETF Last Call и одобренных IESG как имеющих согласие IETF.

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

Если не указано иное, подойдет RFC любого типа (например, Standards Track, BCP, Informational, Experimental, Historic).

Примеры:

типы алгоритмов IPSECKEY [RFC4025];

типы расширений TLS [RFC5246].

4.9. Стандартизация

Для политики Standards Action значения выделяются только через публикацию RFC серии Standards Track или Best Current Practice в потоке IETF.

Примеры:

типы сообщений BGP [RFC4271];

типы опций Mobile Node Identifier [RFC4283];

идентификаторы TLS ClientCertificateType из диапазона I0-63 [RFC5246];

типы пакетов DCCP [RFC4340].

4.10. Одобрение IESG

Новые назначения могут быть одобрены IESG. Хотя здесь отсутствует требование документирования запроса в RFC, IESG во своему усмотрению время от времени запрашивает документы или другие материалы в поддержку запроса.

Процедура IESG Approval не предназначена для частого использования или «общей практики», она применяется достаточно редко. Ее назначение заключается скорее в обеспечении совместно с другими процедурами запасного механизма на случай невозможности своевременно воспользоваться иной процедурой или при возникновении иных сложностей. Процедура IESG Approval не предназначена для обхода общественного рассмотрения, требуемого другими процедурами, для конкретного назначения. Однако эта процедура подойдет для тех случаев, когда желательна целесообразность и имеется согласованное мнение о выделении запрошенных значений (например, согласие рабочей группы).

До одобрения запроса IESG может провести консультации с сообществом путем запроса комментариев (call for comments), обеспечивающие как можно больше информации о запросе.

Примеры:

назначение адресов IPv4 Multicast [RFC5771];

значения типов и кодов IPv4 IGMP [RFC3228];

значения типов и опций заголовков Mobile IPv6 Mobility [RFC6275].

4.11. Использование общеизвестных правил регистрации

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

Допустимо также указать одну или несколько общеизвестных политик и включить дополнительные рекомендации, что следует учитывать при обзоре.

Например для регистрации типов носителей [RFC6838] учитывается множество разных ситуаций, которые включают процедуры IETF Review и Specification Required, а также имеются дополнительные критерии, которые следует принимать во внимание эксперту. Это предназначено не для представления процедуры регистрации, а в качестве примера того, что можно сделать при необходимости учесть другие обстоятельства.

Общеизвестные процедуры от «First Come First Served» до «Standards Action» задают диапазон правил с возрастающим уровнем сложности (указаны номера из полного списка в начале раздела 4).

4. First Come First Served

Без рецензирования с минимальной документацией.

5 и 6 (равносильны).

5. Expert Review

Рецензия эксперта с документацией, достаточной для рецензирования.

6. Specification Required

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

7. RFC Required

Публикация любого RFC (не обязательно в потоке IETF).

8. IETF Review

Публикация RFC в потоке IETF, но не обязательно Standards Track.

9. Standards Action

Публикация RFC в потоке IETF со статусом Standards Track или BCP.

Ниже приведены примеры ситуаций, когда может потребоваться процедура IETF Review или Standards Action.

  • Ограниченный ресурс, такой как биты в байте (или в двух, четырех) или ограниченный диапазон чисел. В таких случаях регистрация без внимательного рецензирования, которая не была рассмотрена и согласована сообществом может привести к скорой нехватке значений.

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

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

При рассмотрении документов, запрашивающих у IANA создание нового реестра или изменении политики регистрации на более строгую, чем Expert Review или Specification Required, IESG следует запросить обоснование, позволяющее понять, были ли рассмотрены более мягкие процедуры и обоснована ли предложенная строгость.

Соответственно, разработчики документов должны предвидеть это и документировать свои соображения по выбору казанной политики (идеально сделать это в самом документе или в записке куратора работы). Куратор должен убедиться в обоснованности предлагаемой политики до передачи документа в IESG.

При пересмотре спецификации политику регистрации следует следует пересмотреть с учетом опыта применения существующей политики.

4.12. Использование комбинации нескольких процедур

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

Таким образом, конкретный реестр может захотеть иногда применять процедуру RFC Required или IETF Review, а в других случаях назначенный эксперт использует Specification Required.

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

Это можно указать в разделе IANA Considerations при описании создания реестра, как показано ниже.

У IANA запрашивается создание реестра «Fruit Access Flags» в группе «Fruit Parameters». Новые регистрации будут выполняться по процедуре IETF Review или Specification Required [BCP26]. Второй вариант следует применять лишь для регистраций, запрошенных SDO вне IETF. Регистрации, запрошенные в документах IETF обрабатываются по процедуре IETF review.

Такие комбинации обычно используют одну из процедур {Standards Action, IETF Review, RFC Required} вместе с одной из {Specification Required, Expert Review}. Следует предоставить рекомендации о применении каждой процедуры как в приведенном выше примере.

4.13. Временная регистрация

Политики некоторых имеющихся реестров разрешают временную регистрацию (см. схемы URI [RFC7595] и поля Email Header [RFC3864]). Регистрации, обозначенные как временные, обычно определяются как более легко создаваемые, изменяемые, переназначаемые или переводимые в другой статус. Схемы URI, например, позволяют выполнять временную регистрацию с неполной информацией.

Разрешение временной регистрации гарантирует, что основная цель реестра — предотвращение конфликтов между семантически несовместимыми значениями — достигается без побочных эффектов «одобрения» протокольных механизмов, использующих временное значение. Временная регистрация для кодов, которые в конечном итоге стандартизуются, может быть переведена в постоянную. Критерии перевода временной регистрации в постоянную будут, вероятно, более строгими, нежели для временной регистрации.

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

5. Назначенные эксперты

5.1. Выбор экспертов

Обсуждение в почтовой конференции может обеспечить полезную техническую информацию, мнения участников могут существенно расходиться и дискуссия может продолжаться в течение продолжительного времени без результатов. Кроме того, IANA не может принимать участие во всех подобных конференциях и поэтому, не может определить наличие согласия среди участников дискуссии. Следовательно, IANA будет опираться на мнение эксперта по соответствующему вопросу. Назначенный эксперт — это конкретный человек, который отвечает за подобающую оценку и подготовку рекомендации для IANA.

Следует отметить, что ключевым мотивом использования назначенных экспертов для IETF является предоставление IANA специалистов, которым могут быть переданы полномочия по оценке. IANA пересылает запросы на выделение экспертам для оценки и эксперт (после проведения оценки) информирует IANA, следует или не следует выполнять запрошенное выделение или регистрацию. В большинстве случаев регистраторы не работают напрямую с назначенными экспертами. Список экспертов для реестра приводится в самом реестре.

Зачастую полезно использовать назначенного эксперта лишь в качестве дополнения к другим процессам. Дополнительное рассмотрение этого вопроса приведено в параграфе 4.12.

5.2. Роль назначенного эксперта

Назначенный эксперт отвечает за инициирование и координацию подходящего обзора запроса на выделение. Широта обзора определяется ситуацией и мнением назначенного эксперта. Обзор может быть широким или узким в зависимости от ситуации и решения назначенного эксперта. Обзор может включать консультации с техническими специалистами, обсуждение в публичном списке рассылки, консультации с рабочей группой (или обсуждение в списке рассылки группы, если она уже распущена) и т. п. В идеальном случае назначенный эксперт следует конкретным критериям , документированным для протокола, который создает или будет использовать пространство имен. Примеры таких критериев можно найти в разделах «Согласование с IANA» (IANA Considerations) [RFC3748] и [RFC3575].

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

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

При отсутствии согласия между экспертами, они отвечают за выработку единых четких рекомендация для IANA. Разрешение споров между экспертами неприемлемо для IANA. В экстремальных (тупиковых) ситуациях для решения проблемы могут потребоваться действия IESG. В реестрах с множеством экспертов зачастую имеется председатель, отвечающих за то, как запросы назначаются экспертам и рецензируются ими. В других случаях IANA может передавать запросы отдельным членам в последовательном или приблизительно случайном порядке. Определяющий реестр документ может, если это подходит для ситуации, указать, как группе следует работать, например, может оказаться оправданным указание примерного уровня согласия в списке рассылки, в рамках связанной с вопросом рабочей группы или среди назначенных экспертов.

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

Если у назначенного эксперта имеется конфликт интересов для конкретного обзора (например, он является автором или апологетом спецификации, связанной с рассматриваемой регистрацией), эксперту следует заявить самоотвод. Если между всеми назначенными экспертами возникает конфликт, им следует попросить назначить временного эксперта для разбора этого конфликта. Руководитель направления (AD9) отвечает за назначение эксперта или сам выполняет его функцию.

Этот документ определяет механизм для назначенных экспертов лишь для документов потока IETF. Если документ из другого потока хочет использовать процедуру регистрации, требующую назначенных экспертов, эти потоки (или их документы) определяют назначение экспертов и управление ими. Описанный ниже процесс под управлением IESG применим лишь к потоку IETF.

5.2.1. Управление назначенными экспертами в IETF

Эксперты для реестров, созданных IETF, назначаются IESG обычно по рекомендации соответствующего руководителя направления. Они могут быть назначены в момент одобрения IESG создания документа или обновления реестра, а также позднее при получении первого запроса на регистрацию. Поскольку назначенные изначально эксперты могут оказаться недоступными, IESG при необходимости назначает им замену. IESG может по своему усмотрению исключать ранее назначенных экспертов.

При возникновении конфликтов, связанных с назначенной группой экспертов применяется обычная процедура апелляции, описанная в параграфе 6.5.1 [RFC2026]. В таком случае назначенная группа экспертов считается рабочей группой.

5.3. Рецензии назначенных экспертов

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

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

  • Если назначенный эксперт не отвечает на запрос IANA в разумные сроки готовой рецензией или разумным объяснением причин задержки (например, сложность запроса) и это повторяется неоднократно, агентство IANA должно обозначить эту проблему в IESG. По причине проблем, вызываемых задержкой оценки и выделения значений, IESG следует принять адекватные меры, обеспечивающие гарантии понимания и принятия экспертом своей ответственности, или назначить другого эксперта.

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

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

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

  • Документация не позволяет должным образом оценить или обеспечить функциональную совместимость.

  • Значения требуются для расширения протокола, но это расширение не согласуется с документированной (или понятной всем) архитектурой расширяемого базового протокола и будет мешать работе протокола при широком распространении. Несоответствия не являются «непреднамеренными», указывающими незначительные различия «на уровне личных предпочтений», и оказывают существенное влияние на безопасность, предполагают изменение семантики существующих типов сообщений или операций, требуют внесения необоснованных изменений в развернутые системы (по сравнению с другими путями достижения такого же результата) и т. п.

  • Расширения будут вызывать проблемы в работе развернутых систем.

  • Расширение будет конфликтовать с другим расширением, которое активно разрабатывается IETF, и его принятие принесет больше вреда, чем пользы в плане функциональной совместимости.

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

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

5.4. Рецензии экспертов и жизненный цикл документа

Рецензирование назначенным экспертом выполняется в определенный момент и представляет обзор конкретной версии документа. Хотя рецензирование обычно выполняется во время IETF Last Call, решение вопроса о времени рецензирования определяется здравым смыслом. В процессе рецензирования эксперт может узнать о существенном изменении документации для регистрируемого элемента и это требует внимательного и осторожного рассмотрения.

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

Для регистрация из документов Standards Track часто требуется одобрение эксперта (политика регистрации) в дополнение к согласию IETF (для утверждения Standards Track RFC). В таких случаях рецензия назначенного эксперта должна быть своевременной и поданной до оценки документа в IESG. Как правило, IESG не следует задерживать документ в ожидании запоздалого рецензирования. Кроме того, рецензия эксперта не предназначена для изменения решения IETF, поэтому IESG следует основываться на своей оценке, как это делается для других обзоров Last Call.

6. Терминология для общеизвестных правил

Ниже приведены значения статуса для регистрации значений или диапазонов.

Private Use — приватное использование

Использование только в замкнутых средах (без выделения значений), как описано в параграфе 4.1.

Experimental — эксперимент

Доступно для экспериментальных приложений, как описано в [RFC3692]. IANA не фиксирует выделение значений для каких-либо конкретных приложений.

Unassigned — не выделено

Не выделено и доступно для распределения в соответствии с документированными процедурами. Хотя обычно ясно, что любые не зарегистрированные и не выделенные значения доступны для распределения, иногда полезно явно указывать это. Отметим, что этот статус существенно отличается от Reserved.

Reserved — резерв

Не распределено и недоступно для распределения. Резервные значения сохраняются для специальных целей типа расширения пространства имен по мере его исчерпания. Статус Reserved иногда применяется для значений, которые были выделены, но перестали использоваться, сохраняя их отложенными, пока имеются не распределенные значения. Отметим, что этот статус существенно отличается от Unassigned.

Резервные значения могут быть освобождены для распределения контролером изменений в реестре (это зачастую IESG для реестров, созданных RFC из потока IETF).

Known Unregistered Use — известное незарегистрированное применение

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

7. Ссылки на документы в реестрах IANA

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

  • Если документ регистрирует элемент, определенный и описанный в другом месте, регистрируемой ссылке следует указывать документ с определением, а не документ, задающий регистрацию.

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

  • Если регистрируемый элемент описан большей частью в конкретном разделе документа, полезно указать этот раздел (например, параграф 3.2 в [RFC4637], а не просто [RFC4637]).

  • При документировании нового реестра в ссылке следует предоставлять информацию о самом реестре, а не просто указатель на его создание. Полезна будет информация о назначении реестра, мотивах его создания, документации о процессе и правилах регистрации, рекомендации для заявителей или назначенных экспертов и т. п. Однако следует отметить, что, несмотря на важность такой информации, ее не требуется полностью включать в раздел IANA Considerations (см. параграф 1.1).

8. Что нужно делать в документах «bis»

Время от времени выпускаются RFC, отменяющие предыдущую версию того же документа. Иногда их называют документами bis, например, как RFC 4637, отмененный документом draft-ietf-foo-rfc4637bis. Если в исходном документе был создан реестр и/или записи в реестре, возникает вопрос по части обработки раздела IANA Considerations в документе bis.

Если при регистрации исходный документ был указан в ссылке, регистрацию следует обновить с указанием текущего (не отмененного) документа для соответствующих элементов. Обычно это будет ссылка на документ bis.

Бывают также случаи, когда один документ обновляет другой, не отменяя того и определяющая ссылка меняется для одних элементов, но сохраняется для других. Здесь следует обеспечивать корректность ссылок на действующий документ для каждого элемента.

Например, если RFC 4637 регистрирует флаг BANANA в реестре Fruit Access Flags и документация для этого флага приведена в параграфе 3.2, текущий реестр может иметь вид

Значение

Описание

Ссылка

BANANA

Флаг для banana

[RFC4637], параграф 3.2

Если draft-ietf-foo-rfc4637bis отменяет RFC 4637 и в результате редактирования описание флага перенесено в параграф 4.1.2, раздел IANA Considerations документа bis может содержать текст вида:

У IANA запрашивается изменение регистрационной информации для флага BANANA в реестре Fruit Access Flags, как показано ниже.

Значение

Описание

Ссылка

BANANA

Флаг для banana

Данный RFC, параграф 4.1.2

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

Поскольку этот документ отменяет RFC 4637, у IANA запрашивается замена всех регистрационных записей, указывающих на [RFC4637], записями со ссылкой на [[данный RFC]].

Если информация о зарегистрированных элементах была или будет перенесена в другие документы, регистрационную информацию следует обновить с указанием этих документов. В большинстве случаев не следует оставлять ссылки на устаревший документ для реестров или зарегистрированных элементов, которые продолжают действовать. Для реестров и зарегистрированных элементов, которые больше не применяются, обычно имеет смысл сохранять ссылки на старый документ (последнюю действующую ссылку для устаревшего элемента). Основная задача состоит в том, чтобы ссылки были полезны и актуальны, насколько это разумно, и авторам следует учитывать это при подготовке раздела IANA Considerations в новом документе. Как всегда, следует поступать разумно и для этого достаточно гибкости.

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

9. Прочие вопросы

9.1. Когда участия IANA не требуется

До публикации документа Internet-Draft как RFC агентству IANA нужно знать, какие действия (если они есть) потребуются от него. Опыт показывает, что не всегда очевидно, нужны ли какие-то действия без детального обзора документа. Чтобы можно было четко видеть, что от IANA не требуется каких-либо действий (и автор осознает это), в документ следует включать раздел IANA Considerations (согласование с IANA), содержащий фразу:

This document has no IANA actions10.

IANA предпочитает сохранять такие «пустые» разделы IANA в документах для фиксации того, что в документе явно указано отсутствие требуемых от IANA действий (а не просто забыли их указать). Это отличается от прежней практики запроса удаления таких разделов редакторами RFC и авторам предлагается учитывать данное изменение.

9.2. Пространства имен без документированного руководства

Для всех имеющихся RFC, которые явно или неявно полагаются на IANA для присвоения значений без указания точной процедуры, IANA будет консультироваться с IESG для выбора подходящей процедуры. Смены установленной процедуры всегда можно инициировать через обычный процесс согласования с IETF или, при необходимости, IESG.

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

9.3. Регистрация «постфактум»

В некоторых случаях IETF становится известно об использовании не распределенных значений из пространства имен в сети Internet или об использовании выделенных значений с иными целями. IETF не оставляет такие факты без внимания и в этом случае должны применяться процедуры описанных в этом документе типов, однако не всегда возможно формально выделить желаемое значение. Если не задано иное, значение могут быть переназначены для другого применения только с согласия исходного правообладателя (если это возможно) и с подобающим учетом влияния такого переназначения. В случаях вероятного противоречия рекомендуется консультация с IESG.

Это является одной из причин включения в параграф 3.1 рекомендации об использовании значений-заменителей (таких как TBD1) в процессе разработки документов. Проблемы зачастую возникают в результате открытого использования незарегистрированных значения после результатов успешных ранних реализаций, которые сохранили применявшиеся при разработке значения, не назначенные IANA.

9.4. Повторное заявление выделенных значений

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

  • Следует предпринять попытку установления контакта с лицом, для которого значения были выделены изначально, чтобы определить, использовались ли выделенные значения и насколько широко (возможны ситуации, когда продукция, для которой были выделены значения, никогда не поставлялась или давно не применяется, а в иных случаях выделенные значения могли не использоваться совсем).

  • Повторное распределение не следует выполнять без согласия исходно запросившего значения лица. Возврат значений следует осуществлять только в тех случаях, когда ясно, что значения не получили широкого распространения и необходимость отзыва оправдывает связанные с этим издержки. В любом случае для этого требуется одобрение IESG (IESG Approval).

  • Может оказаться целесообразным описать предлагаемые меры и запросить их оценку в соответствующем сообществе пользователей. В некоторых случаях может оказаться целесообразной подготовка соответствующего RFC и прохождение формальных процедур IETF (включая IETF Last Call), как было сделано при отзыве некоторых опций DHCP из числа зарезервированных для приватного использования (Private Use) [RFC3942].

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

9.5. Контактное лицо, правообладатель или владелец

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

Это важно, поскольку со временем человек может поменять работу или роль. Возможно, с ним уже нельзя связаться для обновления регистрации. IANA не имеет возможности узнать, какой компании, организации или человеку следует разрешить принять регистрацию. Для регистраций, основанных на RFC, владелец потока (такой как IESG или IAB) может принять решение о замене. Но в иных случаях некуда обратиться за помощью.

Реестры могут включать в дополнение к полю Contact поле Assignee (правообладатель) или Owner (владелец, которого называют также контролером изменений — Change Controller), которое может помочь при решении этой проблемы, давая IANA четкую информацию о фактическом владельце регистрации. Это настоятельно рекомендуется, особенно для регистраций, не требующих RFC для поддержки информации (т. е. для реестров с политикой First Come First Served — параграф 4.4, Expert Review — параграф 4.5 и Specification Required — параграф 4.6). Как вариант, организации могут указать себя в поле Contact, чтобы указать свое владение регистрацией.

9.6. Закрытие и отмена реестров и регистраций

Иногда возникают запросы на «закрытие» реестра для дальнейшей регистрации. В закрытых реестрах регистрация прекращается. Информация в реестре сохраняет свое действие и зарегистрированные ранее записи продолжают обновляться.

Закрытый реестр может быть помечен как устаревший (obsolete) для указания того, что информация из данного реестра больше не применяется.

Конкретные записи реестра могут быть помечены как устаревшие (obsolete) и не используемые или как отмененные (deprecated), применение которых не рекомендуется.

К таким реестрам и зарегистрированным значениям применяется обычный контроль изменений (см. параграф 2.3). Любое закрытие, отмена или устаревание служит для аннотирования состояния реестра, а сам реестр сохраняется для информационных и исторических целей.

10. Апелляции

Апелляции на регистрационные решения IANA можно подавать с использованием обычной процедуры апелляции IETF, описанной в параграфе 6.5 [RFC2026]. Т. е. апелляции следует направлять в IESG, а затем (при необходимости) в IAB.

11. Списки рассылки

Все списки рассылок IETF, связанные с оценкой или обсуждением запросов на выделение значений, как описано в этом документе, управляются в соответствии с правилами и методами, определенными в действующих документах BCP11 или решениях IESG.

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

Информация, связанная с созданием или обновлением регистрационных запросов должна проходить аутентификацию и проверку полномочий. IANA обновляет реестры в соответствии с инструкциями, опубликованными в RFC или полученными от IESG. Могут приниматься также разъяснения от авторов, руководителей соответствующих рабочих групп, назначенных экспертов и участников почтовых конференций.

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

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

Анализ вопросов безопасности в общем случае требуется для всех протоколов, применяющих параметры (типы данных, коды операций, ключевые слова и т. п.), документированные в протоколах IETF или зарегистрированные IANA. Обсуждение вопросов безопасности обычно включается в протокольные документы [BCP72]. Ответственность за обеспечение рассмотрения вопросов безопасности (если таковые имеются) при выделении новых значений и рецензирование такого рассмотрения ложится на IANA при рассмотрении соответствующих вопросов выделения значений.

13. Взаимодействие с IANA

Агентство IANA заменило все ссылки на RFC 5226 ссылками на этот документ.

14. Отличия от прежних версий BCP 26

14.1. 2016 — отличия этого документа от RFC 5226

Ниже перечислены существенные дополнения, внесенные в новую версию.

  • Удалены ключевые слова, шаблоны и ссылка на RFC 2119. Это простой текст, а не спецификация протокола.

  • Добавлен параграф 1.1. Раздел IANA Considerations предназначен для IANA.

  • Добавлен параграф 1.2. Обновление информации.

  • Добавлен параграф 2.1. Организация реестров.

  • Добавлено обобщение опыта для выбора подходящей политики в раздел 4.

  • Добавлен параграф 4.12. Использование комбинации нескольких процедур.

  • Добавлен параграф 2.3. Указание контроля изменений для реестра.

  • Добавлен параграф 3.4. Раннее выделение значений.

  • Все общеизвестные правила перенесены в отдельные параграфы раздела 4.

  • Добавлен параграф 5.4. Рецензии экспертов и жизненный цикл документа.

  • Добавлен раздел 7. Ссылки на документы в реестрах IANA.

  • Добавлен раздел 8. Что нужно делать в документах «bis».

  • Добавлен параграф 9.5. Контактное лицо, правообладатель или владелец.

  • Добавлен параграф 9.6. Закрытие и отмена реестров и регистраций.

Внесены разъяснения и иные правки:

  • некоторые части текста перемещены для ясности и удобочитаемости;

  • добавлены разъяснения по поводу указания реестров IANA с использованием URL;

  • разъяснены различия между Unassigned и Reserved;

  • в параграф 4.5. Рецензия эксперта внесены разъяснения по поводу инструкций для эксперта;

  • в параграф 4.6. Требование наличия спецификации внесены разъяснения по части объявления политики;

  • внесены разъяснения и незначительные правки по всему тексту.

14.2. 2008 — отличия RFC 5226 от RFC 2434

Ниже перечислены основные изменения, внесенные в RFC 5226.

  • Существенное изменение текста с целью расширения описаний и улучшения группировки тем (например, «обновление реестров» и «создание новых реестров») для упрощения авторам поиска наиболее применимых к их задачам тем.

  • Многочисленные редакторские правки для удобочитаемости.

  • Название процедуры IETF Consensus (согласие IETF) заменено на IETF Review (рецензия IETF) и приведены дополнительные разъяснения. Опыт показывает, что люди, увидев слова IETF Consensus (и не глядя на определение этой процедуры) делают некорректное допущение о значении их в контексте IANA Consideration.

  • В список определенных правил добавлено RFC Required (требуется публикация RFC).

  • Существенно более явные указания и примеры того, что «следует включать в RFC».

  • Правило Specification Required (требуется спецификация) сейчас предполагает использование назначенных экспертов (Designated Expert) для оценки ясности спецификаций.

  • Добавлено описание временных регистраций.

  • Существенно изменено содержание раздела «Назначенные эксперты». Основной целью изменений служило указание того, что рецензенты несут ответственность перед сообществом, а также предоставление некоторых рекомендаций по критериям рецензирования в типичных случаях.

  • Изменен текст с целью удаления каких-либо специальных путей для апелляций. Используется описанный в RFC 2026 путь апеллирования.

  • Изменен текст с целью удаления каких-либо специальных путей для апелляций. Используется описанный в RFC 2026 путь апеллирования.

  • Добавлен раздел об отзыве неиспользуемых значений.

  • Добавлен параграф «Регистрация постфактум».

  • Добавлен раздел, указывающий, что почтовые рассылки, используемые для оценки возможности выделения значений (например, назначенным экспертом), подчиняются обычным правилам IETF.

15. Литература

15.1. Нормативные документы

[RFC2026] Bradner, S., «The Internet Standards Process — Revision 3», BCP 9, RFC 2026, DOI 10.17487/RFC2026, October 1996, <http://www.rfc-editor.org/info/rfc2026>.

15.2. Дополнительная литература

[BCP72] Rescorla, E. and B. Korver, «Guidelines for Writing RFC Text on Security Considerations», BCP 72, RFC 3552, July 2003, <http://www.rfc-editor.org/info/bcp72>.

[RFC791] Postel, J., «Internet Protocol», STD 5, RFC 791, DOI 10.17487/RFC0791, September 1981, <http://www.rfc-editor.org/info/rfc791>.

[RFC1591] Postel, J., «Domain Name System Structure and Delegation», RFC 1591, DOI 10.17487/RFC1591, March 1994, <http://www.rfc-editor.org/info/rfc1591>.

[RFC2434] Narten, T. and H. Alvestrand, «Guidelines for Writing an IANA Considerations Section in RFCs», RFC 2434, DOI 10.17487/RFC2434, October 1998, <http://www.rfc-editor.org/info/rfc2434>.

[RFC2860] Carpenter, B., Baker, F., and M. Roberts, «Memorandum of Understanding Concerning the Technical Work of the Internet Assigned Numbers Authority», RFC 2860, DOI 10.17487/RFC2860, June 2000, <http://www.rfc-editor.org/info/rfc2860>.

[RFC2939] Droms, R., «Procedures and IANA Guidelines for Definition of New DHCP Options and Message Types», BCP 43, RFC 2939, DOI 10.17487/RFC2939, September 2000, <http://www.rfc-editor.org/info/rfc2939>.

[RFC3228] Fenner, B., «IANA Considerations for IPv4 Internet Group Management Protocol (IGMP)», BCP 57, RFC 3228, DOI 10.17487/RFC3228, February 2002, <http://www.rfc-editor.org/info/rfc3228>.

[RFC3575] Aboba, B., «IANA Considerations for RADIUS (Remote Authentication Dial In User Service)», RFC 3575, DOI 10.17487/RFC3575, July 2003, <http://www.rfc-editor.org/info/rfc3575>.

[RFC3692] Narten, T., «Assigning Experimental and Testing Numbers Considered Useful», BCP 82, RFC 3692, DOI 10.17487/RFC3692, January 2004, <http://www.rfc-editor.org/info/rfc3692>.

[RFC3748] Aboba, B., Blunk, L., Vollbrecht, J., Carlson, J., and H. Levkowetz, Ed., «Extensible Authentication Protocol (EAP)», RFC 3748, DOI 10.17487/RFC3748, June 2004, <http://www.rfc-editor.org/info/rfc3748>.

[RFC3864] Klyne, G., Nottingham, M., and J. Mogul, «Registration Procedures for Message Header Fields», BCP 90, RFC 3864, DOI 10.17487/RFC3864, September 2004, <http://www.rfc-editor.org/info/rfc3864>.

[RFC3942] Volz, B., «Reclassifying Dynamic Host Configuration Protocol version 4 (DHCPv4) Options», RFC 3942, DOI 10.17487/RFC3942, November 2004, <http://www.rfc-editor.org/info/rfc3942>.

[RFC3968] Camarillo, G., «The Internet Assigned Number Authority (IANA) Header Field Parameter Registry for the Session Initiation Protocol (SIP)», BCP 98, RFC 3968, DOI 10.17487/RFC3968, December 2004, <http://www.rfc-editor.org/info/rfc3968>.

[RFC4025] Richardson, M., «A Method for Storing IPsec Keying Material in DNS», RFC 4025, DOI 10.17487/RFC4025, March 2005, <http://www.rfc-editor.org/info/rfc4025>.

[RFC4044] McCloghrie, K., «Fibre Channel Management MIB», RFC 4044, DOI 10.17487/RFC4044, May 2005, <http://www.rfc-editor.org/info/rfc4044>.

[RFC4124] Le Faucheur, F., Ed., «Protocol Extensions for Support of Diffserv-aware MPLS Traffic Engineering», RFC 4124, DOI 10.17487/RFC4124, June 2005, <http://www.rfc-editor.org/info/rfc4124>.

[RFC4169] Torvinen, V., Arkko, J., and M. Naslund, «Hypertext Transfer Protocol (HTTP) Digest Authentication Using Authentication and Key Agreement (AKA) Version-2», RFC 4169, DOI 10.17487/RFC4169, November 2005, <http://www.rfc-editor.org/info/rfc4169>.

[RFC4271] Rekhter, Y., Ed., Li, T., Ed., and S. Hares, Ed., «A Border Gateway Protocol 4 (BGP-4)», RFC 4271, DOI 10.17487/RFC4271, January 2006, <http://www.rfc-editor.org/info/rfc4271>.

[RFC4283] Patel, A., Leung, K., Khalil, M., Akhtar, H., and K. Chowdhury, «Mobile Node Identifier Option for Mobile IPv6 (MIPv6)», RFC 4283, DOI 10.17487/RFC4283, November 2005, <http://www.rfc-editor.org/info/rfc4283>.

[RFC4340] Kohler, E., Handley, M., and S. Floyd, «Datagram Congestion Control Protocol (DCCP)», RFC 4340, DOI 10.17487/RFC4340, March 2006, <http://www.rfc-editor.org/info/rfc4340>.

[RFC4422] Melnikov, A., Ed. and K. Zeilenga, Ed., «Simple Authentication and Security Layer (SASL)», RFC 4422, DOI 10.17487/RFC4422, June 2006, <http://www.rfc-editor.org/info/rfc4422>.

[RFC4446] Martini, L., «IANA Allocations for Pseudowire Edge to Edge Emulation (PWE3)», BCP 116, RFC 4446, DOI 10.17487/RFC4446, April 2006, <http://www.rfc-editor.org/info/rfc4446>.

[RFC4520] Zeilenga, K., «Internet Assigned Numbers Authority (IANA) Considerations for the Lightweight Directory Access Protocol (LDAP)», BCP 64, RFC 4520, DOI 10.17487/RFC4520, June 2006, <http://www.rfc-editor.org/info/rfc4520>.

[RFC4589] Schulzrinne, H. and H. Tschofenig, «Location Types Registry», RFC 4589, DOI 10.17487/RFC4589, July 2006, <http://www.rfc-editor.org/info/rfc4589>.

[RFC4727] Fenner, B., «Experimental Values In IPv4, IPv6, ICMPv4, ICMPv6, UDP, and TCP Headers», RFC 4727, DOI 10.17487/RFC4727, November 2006, <http://www.rfc-editor.org/info/rfc4727>.

[RFC5246] Dierks, T. and E. Rescorla, «The Transport Layer Security (TLS) Protocol Version 1.2», RFC 5246, DOI 10.17487/RFC5246, August 2008, <http://www.rfc-editor.org/info/rfc5246>.

[RFC5378] Bradner, S., Ed. and J. Contreras, Ed., «Rights Contributors Provide to the IETF Trust», BCP 78, RFC 5378, DOI 10.17487/RFC5378, November 2008, <http://www.rfc-editor.org/info/rfc5378>.

[RFC5742] Alvestrand, H. and R. Housley, «IESG Procedures for Handling of Independent and IRTF Stream Submissions», BCP 92, RFC 5742, DOI 10.17487/RFC5742, December 2009, <http://www.rfc-editor.org/info/rfc5742>.

[RFC5771] Cotton, M., Vegoda, L., and D. Meyer, «IANA Guidelines for IPv4 Multicast Address Assignments», BCP 51, RFC 5771, DOI 10.17487/RFC5771, March 2010, <http://www.rfc-editor.org/info/rfc5771>.

[RFC5795] Sandlund, K., Pelletier, G., and L-E. Jonsson, «The Robust Header Compression (ROHC) Framework», RFC 5795, DOI 10.17487/RFC5795, March 2010, <http://www.rfc-editor.org/info/rfc5795>.

[RFC6014] Hoffman, P., «Cryptographic Algorithm Identifier Allocation for DNSSEC», RFC 6014, DOI 10.17487/RFC6014, November 2010, <http://www.rfc-editor.org/info/rfc6014>.

[RFC6230] Boulton, C., Melanchuk, T., and S. McGlashan, «Media Control Channel Framework», RFC 6230, DOI 10.17487/RFC6230, May 2011, <http://www.rfc-editor.org/info/rfc6230>.

[RFC6275] Perkins, C., Ed., Johnson, D., and J. Arkko, «Mobility Support in IPv6», RFC 6275, DOI 10.17487/RFC6275, July 2011, <http://www.rfc-editor.org/info/rfc6275>.

[RFC6698] Hoffman, P. and J. Schlyter, «The DNS-Based Authentication of Named Entities (DANE) Transport Layer Security (TLS) Protocol: TLSA», RFC 6698, DOI 10.17487/RFC6698, August 2012, <http://www.rfc-editor.org/info/rfc6698>.

[RFC6709] Carpenter, B., Aboba, B., Ed., and S. Cheshire, «Design Considerations for Protocol Extensions», RFC 6709, DOI 10.17487/RFC6709, September 2012, <http://www.rfc-editor.org/info/rfc6709>.

[RFC6838] Freed, N., Klensin, J., and T. Hansen, «Media Type Specifications and Registration Procedures», BCP 13, RFC 6838, DOI 10.17487/RFC6838, January 2013, <http://www.rfc-editor.org/info/rfc6838>.

[RFC6895] Eastlake 3rd, D., «Domain Name System (DNS) IANA Considerations», BCP 42, RFC 6895, DOI 10.17487/RFC6895, April 2013, <http://www.rfc-editor.org/info/rfc6895>.

[RFC6994] Touch, J., «Shared Use of Experimental TCP Options», RFC 6994, DOI 10.17487/RFC6994, August 2013, <http://www.rfc-editor.org/info/rfc6994>.

[RFC7120] Cotton, M., «Early IANA Allocation of Standards Track Code Points», BCP 100, RFC 7120, DOI 10.17487/RFC7120, January 2014, <http://www.rfc-editor.org/info/rfc7120>.

[RFC7564] Saint-Andre, P. and M. Blanchet, «PRECIS Framework: Preparation, Enforcement, and Comparison of Internationalized Strings in Application Protocols», RFC 7564, DOI 10.17487/RFC7564, May 2015, <http://www.rfc-editor.org/info/rfc7564>.

[RFC7595] Thaler, D., Ed., Hansen, T., and T. Hardie, «Guidelines and Registration Procedures for URI Schemes», BCP 35, RFC 7595, DOI 10.17487/RFC7595, June 2015, <http://www.rfc-editor.org/info/rfc7595>.

[RFC7752] Gredler, H., Ed., Medved, J., Previdi, S., Farrel, A., and S. Ray, «North-Bound Distribution of Link-State and Traffic Engineering (TE) Information Using BGP», RFC 7752, DOI 10.17487/RFC7752, March 2016, <http://www.rfc-editor.org/info/rfc7752>.

[RFC8141] Saint-Andre, P. and J. Klensin, «Uniform Resource Names (URNs)», RFC 8141, DOI 10.17487/RFC8141, April 2017, <http://www.rfc-editor.org/info/rfc8141>.

Благодарности за этот документ (2017)

Thomas Narten и Harald Tveit Alvestrand редактировали две первых версии этого документа (RFC 2434 и RFC 5226), а Thomas продолжил эту работу и с данной версией. Значительная часть текста RFC 5226 сохранена в этом издании.

Спасибо Amanda Baber и Pearl Liang за их многочисленные рецензии и предложения, сделавшие документ лучше.

Для документа были полезны внимательные обзоры и комментарии многих людей, включая Benoit Claise, Alissa Cooper, Adrian Farrel, Stephen Farrell, Tony Hansen, John Klensin, Kathleen Moriarty, Mark Nottingham, Pete Resnick и Joe Touch.

Отдельная благодарность Mark Nottingham за реорганизацию части текста в плане удобочитаемости, Tony Hansen за присмотр, а также Brian Haberman и Terry Manderson за спонсорство.

Благодарности из второго издания (2008)

Ниже приведен раздел благодарностей из RFC 5226.

В этот документ внесли существенный вклад отклики Jari Arkko, Marcelo Bagnulo Braun, Brian Carpenter, Michelle Cotton, Spencer Dawkins, Barbara Denny, Miguel Garcia, Paul Hoffman, Russ Housley, John Klensin, Allison Mankin, Blake Ramsdell, Mark Townsley, Magnus Westerlund, Bert Wijnen.

Благодарности из первого издания (1998)

Ниже приведен раздел благодарностей из RFC 2434.

Jon Postel и Joyce K. Reynolds подробно объяснили, что требуется IANA для эффективного управления распределением значений и терпеливо комментировали многочисленные варианты этого документа. Brian Carpenter внес полезные комментарии к ранним версиям документа. Один абзац раздела «Вопросы безопасности» был заимствован из RFC 204812.

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

Michelle Cotton

PTI, an affiliate of ICANN

12025 Waterfront Drive, Suite 300

Los Angeles, CA 90094-2536

United States of America

Phone: +1-424-254-5300

Email: michelle.cotton@iana.org

URI: https://www.iana.org/

Barry Leiba

Huawei Technologies

Phone: +1 646 827 0648

Email: barryleiba@computer.org

URI: http://internetmessagingtechnology.org/

Thomas Narten

IBM Corporation

3039 Cornwallis Ave., PO Box 12195 — BRQA/502

Research Triangle Park, NC 27709-2195

United States of America

Phone: +1 919 254 7798

Email: narten@us.ibm.com


Перевод на русский язык

Николай Малых

nmalykh@gmail.com

1Internet Assigned Numbers Authority.

2Internet Engineering Task Force.

3Internet Engineering Steering Group.

4IANA Functions Operator — оператор функций IANA.

5IANA PROTOCOL PARAMETER SERVICES Operator.

6Top-level domain.

7Namespace ID.

8Extensible Authentication Protocol — расширяемый протокол аутентификации.

9Area Director.

10Для этого документа не требуется действий IANA.

11Best Current Practice — обмен опытом.

12В оригинале ошибочно указан RFC 4288. См. https://www.rfc-editor.org/errata/eid5772. Прим. перев.

Рубрика: RFC | Комментарии к записи RFC 8126 Guidelines for Writing an IANA Considerations Section in RFCs отключены

RFC 8164 Opportunistic Security for HTTP/2

Internet Engineering Task Force (IETF)                     M. Nottingham
Request for Comments: 8164
Category: Experimental                                        M. Thomson
ISSN: 2070-1721                                                  Mozilla
                                                                May 2017

Подходящая защита для HTTP/2

Opportunistic Security for HTTP/2

PDF

Аннотация

В этом документе описано, как можно обеспечить доступ к http URI с использованием защищенного транспорта TLS1 и HTTP/2 для подавления всеобъемлющего мониторинга. Этот механизм не является заменой https URI и уязвим для активных атак.

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

Документ не является спецификацией проекта стандарта Internet и публикуется для проверки, экспериментальной реализации и оценки протокола.

Документ определяет экспериментальный протокол (Experimental Protocol) для сообщества Internet. Документ является результатом работы IETF2 и представляет согласованный взгляд сообщества IETF. Документ прошел открытое обсуждение и был одобрен для публикации IESG3. Не все одобренные IESG документы претендуют на статус Internet Standard (см. раздел 2 в RFC 7841).

Информацию о текущем статусе документа, ошибках и способах обратной связи можно найти по ссылке http://www.rfc-editor.org/info/rfc8164.

Авторские права

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

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

1. Введение

Документ описывает применение дополнительных служб HTTP [RFC7838] для отвязывания схемы URI от использования и настройки шифрования на нижележащих уровнях. Он обеспечивает возможность доступа к http URI [RFC7230] с использованием HTTP/2 и TLS [RFC5246] с Opportunistic Security [RFC7435].

В этом документе описана модель, посредством которой сайты могут обслуживать http URI через TLS, избегая проблемы обслуживания «смешанного содержимого (Mixed Content), описанной в [W3C.CR-mixed-content-20160802], с сохранением защиты от пассивных атак.

Модель «подходящей (уместной) защиты» (OS4) не обеспечивает таких же гарантий, как использование TLS с https URI, поскольку она уязвима к активным атакам, и не меняет контекста защиты соединения. Обычно пользователи просто не будут замечать ее применение (не будет значка блокировки — lock icon).

1.1. Цели

Непосредственной целью является повышение устойчивости HTTP к всеобъемлющему пассивному мониторингу [RFC7258].

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

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

1.2. Уровни требований

Ключевые слова необходимо (MUST), недопустимо (MUST NOT), требуется (REQUIRED), нужно (SHALL), не нужно (SHALL NOT), следует (SHOULD), не следует (SHOULD NOT), рекомендуется (RECOMMENDED), возможно (MAY), необязательно (OPTIONAL) в данном документе должны интерпретироваться в соответствии с [RFC2119].

2. Использование HTTP URI «поверх» TLS

Сервер-источник, поддерживающий преобразование http URI, может указать поддержку данной спецификации, путем анонсирования дополнительных услуг [RFC7838] для идентификатора протокола, который использует TLS (например, h2 [RFC7540]). Такой протокол должен включать явную индикацию схемы для ресурса. Это исключает HTTP/1.1 — клиентам HTTP/запрещено включать абсолютную форму URI в запросы к серверам-источникам (см. параграф 5.3.1 в [RFC7230]).

Клиент, получивший такой анонс, может делать будущие запросы к соответствующему источнику [RFC6454] с учетом этого сервиса (как указано в [RFC7838]), при условии выбора дополнительной услуги в соответствии с параграфом 2.1.

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

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

Клиентские сертификаты не имеют смысла для URL в схеме http, следовательно, клиентам, организующим новые соединения TLS с дополнительными службами в соответствии с данной спецификацией, недопустимо представлять эти сертификаты. Серверы, которые поддерживают ресурсы https на том же порту, могут запросить сертификат в процессе согласования TLS, но им недопустимо прерывать согласование, если клиент не представил сертификат.

2.1. Выбор дополнительного сервера

По разным причинам сервер может перепутать в запрашиваемом URL схемы http и https (см. параграф 4.4). Для гарантии того, что дополнительные будут предлагаться при обработке http URL с использованием TLS, клиенты должны выполнять дополнительные проверки до отправки запросов http.

Клиентам недопустимо передавать запросы http через защищенные соединения, пока выбранный дополнительный сервис не представил корректный сертификат источника, как определено в [RFC2818]. Использование аутентифицированного дополнительного сервиса обеспечивает «разумные гарантии» для целей [RFC7838]. В дополнение к аутентификации сервера клиент должен иметь действительный отклик http-opportunistic от источника (как указано в параграфе 2.3), полученный с использованием аутентифицированного соединения. Исключение для последнего правила делается для запросов http-opportunistic от общеизвестных URI.

Предположим, например, что запрос выполняется через соединение TLS, которое аутентифицировано для этого источника. В этом случае можно передать запросы и отклики для источников http://www.example.com и http://example.com через защищенное соединение.

   HEADERS
     + END_STREAM
     + END_HEADERS
       :method = GET
       :scheme = http
       :authority = example.com
       :path = /.well-known/http-opportunistic

   HEADERS
       :status = 200
       content-type = application/json
   DATA
     + END_STREAM
   [ "http://www.example.com", "http://example.com" ]

В этом документе для удобства указывается несколько источников. Только запрос, выполненный для источника (через аутентифицированное соединение) может использоваться для получения ресурса http-opportunistic от этого источника. Таким образом, для нашего примера запрос к http://example.com не позволяет предполагать представления ресурса http-opportunistic также для http://www.example.com.

2.2. Взаимодействие с https URI

Клиентам недопустимо передавать запросы http и https через одно соединение. Аналогично, клиентам недопустимо передавать через одно соединение запросы http для разных источников.

2.3. Общеизвестные http-opportunistic URI

Данная спецификация определяет общеизвестные http-opportunistic URI [RFC5785]. Клиент может считать, что у него имеется приемлемый отклик http-opportunistic для данного источника, при выполнении перечисленных ниже условий.

  • Клиент запросил общеизвестный URI у источника через аутентифицированное соединение и получил отклик с кодом 200 (OK);

  • этот отклик является свежим [RFC7234] (возможно через повторную проверку [RFC7232]);

  • отклик имеет тип среды application/json;

  • данные отклика при разборе как JSON [RFC7159] содержат массив в качестве корня;

  • массив содержит строку, которая с учетом регистра посимвольно совпадает с запрашиваемым источником при последовательном представлении в кодировке Unicode, как описано в параграфе 6.1 [RFC6454].

Клиент может трактовать ресурс http-opportunistic, как неприемлемый, если его значения отличны от строк.

Этот документ не определяет семантики ресурсов http-opportunistic на источниках https и в тех случаях, когда ресурс содержит источники https.

Разрешение клиентам кэшировать ресурс http-opportunistic означает, что все дополнительные службы должны быть способны отвечать на запросы для ресурсов http. Клиентам разрешено использовать использовать дополнительный сервис без «приобретения» ресурса http-opportunistic от этого сервиса.

Клиентам недопустимо использовать какую-либо кэшированную копию ресурса http-opportunistic, который был обретен (или заново проверен) через соединение без аутентификации. Во избежание возможных ошибок клиент может запросить или проверить заново ресурс http-opportunistic перед использованием любого соединения с дополнительным сервисом.

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

3. Согласование с IANA

Данная спецификация регистрирует перечисленные ниже общеизвестные (well-known) URI [RFC5785]:

  • URI Suffix: http-opportunistic

  • Change Controller: IETF

  • Specification Document(s): Section 2.3 of RFC 8164

  • Related Information:

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

4.1. Индикаторы защиты

Пользовательским агентам недопустимо выводить какие-либо специальные индикаторы защищенности, когда ресурс http «обретен» с использованием TLS. В частности, недопустимо использовать такие же индикаторы защищенности (например, lock device), как для https.

4.2. Атаки со снижением требований

Возможны атаки, нацеленные на снижение требований при согласовании TLS.

Например, поскольку поле заголовка Alt-Svc [RFC7838] скорей всего будет присутствовать в неаутентифицированном и нешифрованном канале, оно может использоваться для атак. В простейшем варианте атакующий, который пытается принудить к организации нешифрованного соединения, может просто удалить из откликов поле заголовка Alt-Svc.

4.3. Вопросы приватности

Кэшированные дополнительные службы могут применяться для отслеживания клиентов (например, по указанному пользователем имени). Очистка кэша снижает возможности отслеживания клиентов серверами, поэтому клиенты должны очищать кэш информации о дополнительных службах при сбрасывании других состояний, связанных с источником (например, cookie).

4.4. Возможная путаница со схемой запроса

В реализациях и приложениях HTTP иногда применяются внешние сигналы для определения запросов, относящихся к ресурсам https (например, поиск TLS в стеке или порта 443 на сервере).

Это может быть связано с ожидаемыми ограничениями протокола (наиболее распространенные запросы HTTP/1.1 не включают явной индикации схемы URI, а ресурс может быть разработан, исходя из HTTP/1.1) или способом реализации сервера и приложения (зачастую это два разных объекта, между которыми могут использоваться самые разные интерфейсы).

Любые защитные решения, основанные на этой информации, могут быть введены в заблуждение в результате внедрения данной спецификации, поскольку она не соответствует допущению о том, что использование TLS (или порта 443) означает, что клиент обращается к HTTPS URI и работает в защищенном контексте, обеспечиваемом HTTPS.

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

4.5. Управление сервером

Данная спецификация требует, чтобы сервер передавал анонс дополнительных услуг в общеизвестное место для того, чтобы можно было передавать запросы HTTP через TLS. Серверам следует принять надлежащие меры по обеспечению контроля за содержимым общеизвестных ресурсов. Аналогично, в результате применения поля заголовка Alt-Svc для описания политики источника в целом, серверам не следует разрешать пользователю устанавливать или изменять значение этого заголовка.

5. Литература

5.1. Нормативные документы

[RFC2119] Bradner, S., «Key words for use in RFCs to Indicate Requirement Levels», BCP 14, RFC2119, DOI 10.17487/RFC 2119, March 1997, <http://www.rfc-editor.org/info/rfc2119>.

[RFC2818] Rescorla, E., «HTTP Over TLS», RFC 2818, DOI 10.17487/RFC2818, May 2000, <http://www.rfc-editor.org/info/rfc2818>.

[RFC5246] Dierks, T. and E. Rescorla, «The Transport Layer Security (TLS) Protocol Version 1.2», RFC 5246, DOI 10.17487/RFC5246, August 2008, <http://www.rfc-editor.org/info/rfc5246>.

[RFC5785] Nottingham, M. and E. Hammer-Lahav, «Defining Well-Known Uniform Resource Identifiers (URIs)», RFC 5785, DOI 10.17487/RFC5785, April 2010, <http://www.rfc-editor.org/info/rfc5785>.

[RFC6454] Barth, A., «The Web Origin Concept», RFC 6454, DOI 10.17487/RFC6454, December 2011, <http://www.rfc-editor.org/info/rfc6454>.

[RFC7159] Bray, T., Ed., «The JavaScript Object Notation (JSON) Data Interchange Format», RFC 7159, DOI 10.17487/RFC7159, March 2014, <http://www.rfc-editor.org/info/rfc7159>.

[RFC7230] Fielding, R., Ed. and J. Reschke, Ed., «Hypertext Transfer Protocol (HTTP/1.1): Message Syntax and Routing», RFC 7230, DOI 10.17487/RFC7230, June 2014, <http://www.rfc-editor.org/info/rfc7230>.

[RFC7232] Fielding, R., Ed. and J. Reschke, Ed., «Hypertext Transfer Protocol (HTTP/1.1): Conditional Requests», RFC 7232, DOI 10.17487/RFC7232, June 2014, <http://www.rfc-editor.org/info/rfc7232>.

[RFC7234] Fielding, R., Ed., Nottingham, M., Ed., and J. Reschke, Ed., «Hypertext Transfer Protocol (HTTP/1.1): Caching», RFC 7234, DOI 10.17487/RFC7234, June 2014, <http://www.rfc-editor.org/info/rfc7234>.

[RFC7540] Belshe, M., Peon, R., and M. Thomson, Ed., «Hypertext Transfer Protocol Version 2 (HTTP/2)», RFC 7540, DOI 10.17487/RFC7540, May 2015, <http://www.rfc-editor.org/info/rfc7540>.

[RFC7838] Nottingham, M., McManus, P., and J. Reschke, «HTTP Alternative Services», RFC 7838, DOI 10.17487/RFC7838, April 2016, <http://www.rfc-editor.org/info/rfc7838>.

5.2. Дополнительная литература

[RFC7258] Farrell, S. and H. Tschofenig, «Pervasive Monitoring Is an Attack», BCP 188, RFC7258, DOI 10.17487/RFC 7258, May 2014, <http://www.rfc-editor.org/info/rfc7258>.

[RFC7435] Dukhovni, V., «Opportunistic Security: Some Protection Most of the Time», RFC 7435, DOI 10.17487/RFC7435, December 2014, <http://www.rfc-editor.org/info/rfc7435>.

[W3C.CR-mixed-content-20160802] West, M., «Mixed Content», World Wide Web Consortium CR CR-mixed-content-20160802, August 2016, <https://www.w3.org/TR/2016/CR-mixed-content-20160802>.

Благодарности

Mike Bishop предоставил текст существенной части этого документа.

Спасибо Patrick McManus, Stefan Eissing, Eliot Lear, Stephen Farrell, Guy Podjarny, Stephen Ludin, Erik Nygren, Paul Hoffman, Adam Langley, Eric Rescorla, Julian Reschke, Kari Hurtta и Richard Barnes за их отклики и предложения.

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

Mark Nottingham

Email: mnot@mnot.net

URI: https://www.mnot.net/

Martin Thomson

Mozilla

Email: martin.thomson@gmail.com


Перевод на русский язык

Николай Малых

nmalykh@gmail.com

1Transport Layer Security — защита транспортного уровня.

2Internet Engineering Task Force.

3Internet Engineering Steering Group.

4Opportunistic Security.

5Man-in-the-middle – перехват данных в возможностью их изменения при участии человека.

Рубрика: RFC | Комментарии к записи RFC 8164 Opportunistic Security for HTTP/2 отключены

Спецификация языка версии P4_16 v1.0.0

Спецификация языка версии P416 1.0.0

P416 Language Specification

version 1.0.0

The P4 Language Consortium

2017-05-22

PDF

Аннотация

P4 является языком для программирования уровня данных (data plane) сетевых устройств. В этом документе приведено точное определение языка P416, который является пересмотренным в 2016 году вариантом языка P4 (http://p4.org).

Этот документ адресован разработчикам, создающим компиляторы, модели, среды разработки (IDE) и отладчики для программ P4. Документ может также заинтересовать программистов, которые хотят глубже разобраться в синтаксисе и семантике языка P4.

1. Назначение языка

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

Документ не определяет:

  • механизмов компиляции, загрузки и исполнения программ P4 в системах обработки пакетов;

  • механизмов получения данных одной системой обработки пакетов и их доставки другой системе;

  • механизмов, с помощью которых уровень управления (control plane) поддерживает таблицы «сопоставление-действие» и другие связанные с состоянием объекты, определяемые программами P4;

  • минимальных требований к системам обработки пакетов, способным обеспечить реализацию.

2. Термины, определения и символы

Ниже приведены определения используемых в документе терминов.

Architecture — архитектура

Набор программируемых с помощью P4 компонент и интерфейсов уровня данных (data plane) между ними.

Control plane – уровень (плоскость) управления

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

Data plane – уровень (плоскость) данных

Класс алгоритмов, описывающих преобразования пакетов в системах обработки.

Metadata — метаданные

Промежуточные данные, создаваемые в процессе выполнения программы P4.

Packet — пакет

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

Packet header – заголовок пакета

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

Packet payload – данные пакета

Данные пакета, следующие после заголовков.

Packet-processing system – система обработки пакетов

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

Target – целевая платформа, платформа

Система обработки пакетов, способная выполнять программы P4.

Все явно определенные в этом документе термины не следует трактовать как неявные ссылки на похожие термины, определенные в других местах. И наоборот, не определенные явно в данном документе термины следует трактовать в соответствии с общепризнанными документами, где они были определены (например, IETF RFC).

3. Обзор

Язык P4 служит для представления обработки пакетов уровнем данных в программируемых элементах сети типа аппаратных и программных коммутаторов, сетевых интерфейсных плат, маршрутизаторов или специализированных сетевых платформ. Имя P4 происходит от оригинальной публикации, в которой язык был предложен — «Programming Protocol-independent Packet Processors» (https://arxiv.org/pdf/1312.1719.pdf). Хотя P4 исходно был предназначен для программируемых коммутаторов, область его применения шире и охватывает различные устройства. Далее в документе для всех таких устройств используется общий термин «платформа» (target). Многие платформы реализуют уровни данных и управления. P4 предназначен только для работы с уровнем данных таких платформ. Программы P4 также частично определяют интерфейс, через который взаимодействуют уровни данных и управления, но P4 не может служить для описания функциональности уровня управления. Далее в документе при обсуждении использования P4 для «программирования платформы» всегда имеется в виду «программирование уровня данных платформы».

В качестве примера платформы на рисунке 1 показано различие между традиционным коммутатором с фиксированной функциональностью и программируемым на базе P4 коммутатором. В традиционном коммутаторе производитель полностью определяет функциональность уровня данных. Уровень управления контролирует уровень данных путем задания таблиц (например, таблица маршрутизации), настройки специализированных объектов (например, измерителей) и обработки управляющих пакетов (например, пакеты протоколов маршрутизации) или асинхронных событий типа изменения состояния каналов или уведомлений о получении новой информации (learning).

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

  • Функциональность уровня данных не фиксирована заранее, а определяется программой P4. Уровень данных настраивается во время инициализации функциональности, описанной программой P4 (длинная красная стрелка на рисунке 1), и не знает заранее о существующих сетевых протоколах.

  • Уровень управления взаимодействует с уровнем данных по таким же каналам, что и в традиционном коммутаторе, но набор таблиц и других объектов уровня данных не фиксирован, поскольку он определяется программой P4. Компилятор P4 генерирует интерфейс API, используемый уровнем управления для взаимодействия с уровнем данных.

Рисунок 1. Сравнение традиционных и программируемых коммутаторов.


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

Ниже перечислены основные абстракции, обеспечиваемые языком программирования P4.

  • Типы заголовков описывают формат (набор полей и их размеры) каждого заголовка в пакете.

  • Анализаторы (parser) описывают разрешенные последовательности заголовков в принятых пакетах, способы идентификации последовательностей заголовков, а также заголовки и поля, извлекаемые из пакетов.

  • Таблицы связывают заданные пользователем ключи с операциями. Таблицы P4 обобщают таблицы традиционных коммутаторов и могут служить для реализации таблиц поиска потоков, маршрутизации, списков управления доступом и других определяемых пользователем таблиц, включая комплексные решения на основе множества переменных.

  • Действия являются фрагментами кода, которые описывают манипуляции с полями заголовков и метаданными. Действия могут включать данные, получаемые в процессе работы от уровня управления.

  • Блоки «сопоставление-действие» выполняют приведенную ниже последовательность операций:

    • создание ключей поиска из полей пакета и рассчитанных метаданных;

    • поиск в таблицах с использованием созданных ключей и выбор действия (включая связанные данные);

    • выполнение выбранного действия.

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

  • Внешние объекты являются зависящими от архитектуры конструкциями, которыми могут манипулировать программы P4 с помощью четко определенных API. Внутреннее поведение таких объектов задано жестко (например, блоками контрольных сумм) и поэтому они не могут программироваться с помощью P4.

  • Определяемые пользователем метаданные — структуры данных, связанные с каждым пакетом.

  • Внутренние метаданные — связанные с каждым пакетом данные, предоставляемые архитектурой (например, входной порт, через который был принят пакет).

На рисунке 2 показан типичный поток операций при программировании платформы с использованием языка P4.

Рисунок 2. Программирование движка с помощью P4.

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

Компиляция пакета программ P4 создает два объекта:

  • конфигурацию уровня данных, которая реализует логику пересылки, описанную в программе;

  • API для управления состояниями объектов уровня данных со стороны уровня управления.

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

В предположении фиксированной «стоимости» операций поиска в таблицах и взаимодействия с внешними объектами, все программы P4 (т. е. анализаторы и элементы управления) выполняют постоянное число операций для каждого байта принятого и проанализированного пакета. Хотя анализаторы могут включать циклы, обеспечивающие извлечение данных из одного заголовка в каждом цикле, сам пакет задает границы для полного анализа. Иными словами, при таких допущениях расчетная сложность программы P4 линейно растет с ростом общего размера заголовков и никогда не зависит от размера состояния, созданного в процессе обработки данных (например, число потоков или общее число обработанных пакетов). Эти гарантии необходимы (но не достаточны) для обеспечения быстрой обработки пакетов на широком спектре платформ.

Соответствие платформы требованиям P4 определяется следующим образом — если конкретная платформа T поддерживает лишь подмножество языка P4 (пусть это будет, P4T), программы, написанные в рамках P4T при выполнении на этой платформе должны обеспечивать в точности такое же поведение, какое описано в данном документе. Отметим, что соответствующие P4 платформы могут обеспечивать произвольные расширения языка P4 и внешних элементов.

3.1. Преимущества P4

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

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

  • Выразительность — P4 может выражать сложные аппаратно-независимые алгоритмы обработки пакетов, использующие только операции общего назначения и поиск в таблицах. Такие программы переносимы на разные аппаратные платформы, реализующие одну и ту же архитектуру (при наличии достаточных ресурсов).

  • Отображение ресурсов и управление ими — программы P4 абстрактно описывают ресурсы хранения (например, адреса отправителей IPv4), компиляторы отображают описанные пользователем поля на доступные аппаратные ресурсы и управляют ими на нижнем уровне (например, распределение и планирование).

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

  • Библиотеки компонент, поставляемые производителями, могут использоваться для встраивания аппаратно-зависимых функций в переносимые конструкции верхнего уровня P4.

  • Независимое развитие программных и аппаратных компонент — производители платформ могут использовать абстрактную архитектуру для дальнейшего разделения деталей архитектуры на нижних уровнях и обработки на верхних.

  • Отладка — производители могут предоставить программные модели архитектуры, помогающие при разработке и отлаживании программ P4.

3.2. Развитие языка P4 — сравнение с предыдущими версиями (P4 v1.0/v1.1)

По сравнению с более ранней версией P414 язык P416 вносит множество значимых и не совместимых с прежними версиями изменений в синтаксис и семантику. Переход от предыдущей версии (P414) к текущей (P416) показан на рисунке 3. В частности, из языка было изъято и перемещено в библиотеки множество функций, включая счетчики, блоки контрольных сумм, измерители и т. п.

Рисунок 3. Эволюция языка от P414 (версии 1.0 и 1.1) до P416.

Язык был преобразован из сложного (более 70 ключевых слов) в сравнительно простой (менее 40 ключевых слов, описанных в Приложении A), сопровождающийся библиотекой базовых конструкции, которые нужны в большинстве программ P4.

В версии 1.1 языка P4 была введена конструкция extern, которая может служить для описания элементов библиотеки. Многие конструкции, определенные в спецификации v1, были преобразованы в библиотечные элементы (с том числе исключенные из языка конструкции типа счетчиков и измерителей). Некоторые из таких внешних (extern) объектов могут быть стандартизованы и они остаются в области действия будущего документа, описывающего стандартную библиотеку элементов P4. В этом документе представлено несколько примеров конструкций extern. В P416 также добавлены или переопределены некоторые языковые конструкции v1.1 для описания программируемых частей архитектуры. Эти конструкции включают parser (анализатор), state (состояние), control (элемент управления) и package (программный пакет).

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

4. Модель архитектуры

Архитектура P4 задает программируемые на языке P4 блоки (например, анализатор, входной и выходной поток управления и т. п.) и их интерфейсы уровня данных.

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

 Рисунок 4. Программные интерфейсы P4.

На рисунке 4 показаны интерфейсы уровня данных между программируемыми на языке P4 блоками. Платформа имеет два программируемых блока (#1 и #2), каждый из которых задается отдельным фрагментом кода P4. Платформа взаимодействует с программами P4 через набор управляющих регистров или сигналов. Входные элементы управления предоставляют информацию программам P4 (например, порт, принявший пакет), а выходные могут задаваться программами P4 для влияния на поведение платформы (например, выбор выходного порта для пакета). Регистры управления и сигналы представляются в P4 как внутренние метаданные. Программы P4 могут также хранить и обрабатывать относящиеся к каждому пакету метаданные, определяемые пользователем.

 
Рисунок 5. Вызов программой P4 службы объекта с фиксированными функциями.

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

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

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

4.1. Стандартные модели архитектуры

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

4.2. Интерфейсы уровня данных

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

control MatchActionPipe<H>(in bit<4> inputPort,
				inout H parsedHeaders,
				out bit<4> outputPort);

Этот тип объявления описывает блок MatchActionPipe, который можно запрограммировать с помощью зависящей от данных последовательности вызовов блоков «сопоставление-действие» (далее СД) и других обязательных конструкций, указанных ключевым словом control. Интерфейс между блоком MatchActionPipe и другими компонентами архитектуры можно определить из объявления блока.

  • Первым параметром служит 4-битовое значение inputPort. Направление in говорит, что параметр является входным и не может быть изменен.

  • Вторым параметром является объект типа H с именем parsedHeaders, где H — переменная типа, представляющая заголовки (будет определена ниже). Направление inout говорит, что параметр является входным и выходным.

  • Третьим параметром является 4-битовое значение outputPort. Направление out говорит, что параметр является выходным и его значение, заданное изначально, может быть изменено.

4.3. Внешние объекты и функции

Программы P4 могут взаимодействовать с объектами и функциями, обеспечиваемыми архитектурой. Такие объекты описываются с помощью конструкции extern, которая задает интерфейсы, раскрываемые объектом уровню данных.

Объект extern описывает набор методов, реализуемых этим объектом, но не сами реализации (подобно абстрактным классам в объектно-ориетированных языках). Например, приведенная ниже конструкция может служить для описания операций блока инкрементного расчета контрольных сумм.

extern Checksum16 {
	Checksum16();			// конструктор
	void clear();			// подготовка блока к расчету
	void update<T>(in T data);	// добавление данных в контрольную сумму
	void remove<T>(in T data);	// исключение данных из имеющейся контрольной суммы
	bit<16> get(); 		// получение контрольной суммы для данных, добавленных 
					// с момента последней очистки
}

5. Пример очень простого коммутатора

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

 
Рисунок 6. Архитектура очень простого коммутатора.

Назовем эту архитектуру VSS1 (смс рисунок 6). В VSS нет ничего особенного — это всего лишь дидактический пример, иллюстрирующий описание и программирование коммутатора с помощью языка P4. VSS имеет множество фиксированных функциональных блоков (на рисунке показаны светло-синим цветом), поведение которых описано в параграфе 5.2. Белые блоки на рисунке программируются с помощью P4.

VSS принимает пакеты через один из 8 входных портов Ethernet, канал рециркуляции или порт, напрямую подключенный к процессору CPU. VSS имеет один синтаксический анализатор, результаты которого передаются в единственный конвейер СД, а за ним следует единственный синтезатор (deparser). После выхода из синтезатора пакет передается в один из 8 выходных портов Ethernet или 3 портов специального назначения:

  • порт CPU для передачи на уровень управления;

  • порт Drop для отбрасывания пакета;

  • порт рециркуляции (Recirculate) для последующего возврата в коммутатор через специальный входной порт.

Белые блоки на рисунке являются программируемыми и пользователь должен предоставить соответствующую программу P4 для задания поведения такого блока. Красные стрелки показывают поток определенных пользователем данных. Синие блоки являются компонентами с фиксированной функциональностью. Зеленые стрелки являются интерфейсами уровня данных, используемыми для обмена информацией между фиксированными функциональными блоками и программой P4 в форме внутренних метаданных.

5.1. Архитектура очень простого коммутатора

Приведенная ниже программа P4 содержит объявление VSS в P4, представленное производителем VSS. Объявление включает несколько объявлений типов и трех программируемых блоков (в коде используется цветовое выделение). Программируемые блоки описываются их типами, реализация этих блоков обеспечивается программистами.

// Файл very_simple_switch_model.p4
// Объявление очень простого коммутатора VSS P4

// Библиотека ядра, требуемая для определений packet_in и packet_out
# include <core.p4>

/* Объявления констант и структур */
/* Порты указываются 4-битовыми значениями */
typedef bit<4> PortId;

/* Только 8 портов являются физическими */
const PortId REAL_PORT_COUNT = 4w8;	// 4w8 представляет 4-битовое число 8

/* Метаданные, сопровождающие входной пакет */
struct InControl {
	PortId inputPort;
}

/* Входные порты специального назначения */
const PortId RECIRCULATE_IN_PORT = 0xD;
const PortId CPU_IN_PORT = 0xE;

/* Метаданные, которые нужно рассчитать для выходных пакетов */
struct OutControl {
	PortId outputPort;
}

/* Выходные порты специального назначения для исходящих пакетов */
const PortId DROP_PORT = 0xF;
const PortId CPU_OUT_PORT = 0xE;
const PortId RECIRCULATE_OUT_PORT = 0xD;

/* Прототипы для всех программируемых блоков */
/**
* Программируемый синтаксический анализатор.
* @param <H> - тип заголовков, указываемый пользователем;
* @param b - входной пакет;
* @param parsedHeaders заголовки, созданные анализатором.
*/
parser Parser<H>(packet_in b,out H parsedHeaders);

/**
* Конвейер «сопоставление-действие» (СД)
* @param <H> - тип входных и выходных заголовков;
* @param headers - заголовки, получаемые от анализатора и передаваемые синтезатору;
* @param parseError - ошибка, которая могла возникнуть в процессе анализа;
* @param inCtrl - информация от архитектуры, сопровождающая входной пакет;
* @param outCtrl - информация от архитектуры, сопровождающая выходной пакет.
*/
control Pipe<H>(inout H headers,
						in error parseError,		// ошибка анализатора
					in InControl inCtrl,		// входной порт
					out OutControl outCtrl); 	// выходной порт


/**
* Синтезатор (deparser) VSS.
* @param <H> - тип заголовков, указываемый пользователем;
* @param b - выходной пакет;
* @param outputHeaders - заголовки для выходного пакета.
*/
control Deparser<H>(inout H outputHeaders, packet_out b);

/**
* Объявление верхнего уровня для программы (экземпляр должен быть создан пользователем).
* Аргументы программы указывают блоки, экземпляры которых нужно создать пользователю.
* @param <H> - определенный пользователем тип обрабатываемых заголовков.
*/
package VSS<H>(Parser<H> p,
					Pipe<H> map,
					Deparser<H> d);

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

// Блок контрольных сумм.
extern Checksum16 {
	Checksum16();				// конструктор
	void clear();				// подготовка блока к расчетам
	void update<T>(in T data);	// добавление данных в контрольную сумму
	void remove<T>(in T data);	// исключение данных из имеющейся контрольной суммы
	bit<16> get(); 				// получение контрольной суммы для данных, добавленных
								// с момента последней очистки
}

Далее описаны некоторые из элементов.

  • Включаемый файл core.p4 более подробно рассмотрен в Приложении B. Он определяет некоторые стандартные типы данных и коды ошибок.

  • bit<4> — битовая строка из 4 битов.

  • Синтаксис 4w0xF показывает значение 15, представленное 4 битами. Другим вариантом записи является 4w15. Во многих случаях размер можно опустить, просто указав 15.

  • error — это встроенный тип P4 для передачи кодов ошибок.

  • Далее следует объявление анализатора

			parser Parser<H>(packet_in b,out H parsedHeaders);

Это объявление описывает интерфейс анализатора, но не его реализацию, которая будет задана программистом. Анализатор считывает свои входные данные из packet_in (предопределенный внешний объект P4, представляющий входящий пакет и описанный в библиотеке core.p4). Анализатор записывает свои результаты (ключевое слово out) в аргумент parsedHeaders. Типом этого аргумента является H, который еще не известен и будет предоставлен программистом.

  • Объявление

    control Pipe<H>(inout H headers,
    						in error parseError,		// ошибка анализатора
    					in InControl inCtrl,		// входной порт
    					out OutControl outCtrl); 	// выходной порт
    

    описывает интерфейс с конвейером СД, названным Pipe.

    Конвейер принимает 3 входных параметра — заголовки headers, код ошибок при анализе parseError и данные управления inCtrl. На рисунке 6 показаны разные источники этих частей информации. Конвейер записывает свои результаты в outCtrl и должен обновить заголовки, которые будут переданы синтезатору (deparser).

  • Программа верхнего уровня называется VSS. Для программирования коммутатора VSS пользователь будет создавать экземпляр программы этого типа (см. следующий параграф). Объявление программы верхнего уровня также зависит от типа переменной H

	package VSS<H>

Тип переменной еще не известен и должен быть представлен пользователем позднее. В данном случае H является типом из набора заголовков, которые пользовательская программа будет обрабатывать. Анализатор будет разбирать эти заголовки, а конвейер СД — обновлять входные заголовки для создания выходных.

  • Объявление программы VSS включает три комплексных параметра типов Parser, Pipe и Deparser, которые точно соответствуют описанным выше объявлениям. Для программирования платформы нужно будет представить значения этих трех параметров.

  • В этой программе структуры inCtrl и outCtrl представляют регистры управления. Содержимое структуры headers сохраняется в регистрах общего назначения.

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

5.2. Описание архитектуры VSS

Чтобы полностью понять поведение коммутатора VSS и написать для него осмысленные программы P4, а также реализовать уровень управления, потребуется также полное описание поведения фиксированных функциональных блоков. В этом параграфе рассматривается простой пример, показывающий все детали, которые нужно учитывать при описании архитектуры. Язык P4 не предназначен для описания всех таких функциональных блоков, он может описать лишь интерфейсы между программируемыми блоками и архитектурой. Для нашей программы этот интерфейс задается объявлениями Parser, Pipe и Deparser. На практике предполагается полное описание архитектуры в форме исполняемой программы и/или рисунков и текста, а данный документ дает лишь неформальное текстовое описание.

5.2.1. Блок арбитража

Входной блок арбитража выполняет перечисленные ниже функции.

  • Прием пакетов от одного из физических портов Ethernet, уровня управления или входного порта рециркуляции.

  • Для пакетов из портов Ethernet блок рассчитывает и проверяет контрольную сумму трейлера и при несоответствии отбрасывает пакет. Если контрольная сумма верна, она удаляется из данных пакета.

  • При получении пакетов включается алгоритм арбитража, если доступно множество пакетов одновременно.

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

  • После приема пакета блок арбитража устанавливает значение inCtrl.inputPort, которое служит входными данными для анализатора, указывая порт, через который был получен пакет. Физические порты Ethernet имеют номера от 0 до 7, входной порт рециркуляции имеет номер 13, а порт процессора — 14.

5.2.2. Блок анализатора

Блок parser runtime работает вместе с блоком синтаксического анализатора и предоставляет код ошибки конвейеру СД на основе действий анализатора, а также информацию о данных (payload) пакета (например, размер оставшейся части данных) блоку демультиплексирования (demux). По завершении обработки пакета анализатором в процесс вовлекается конвейер СД, принимая на вход метаданные (заголовки пакета и заданные пользователем метаданные).

5.2.3. Блок демультиплексирования

Основной функциональностью блока demux является получение заголовков для выходных пакетов от синтезатора и данных пакета от анализатора для сборки из них нового пакета и отправки результата в нужный выходной порт, который задается значением outCtrl.ouputPort, устанавливаемым конвейером СД.

  • Передача пакета в порт drop приводит к исчезновению пакета.

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

  • Передача пакета в выходной порт CPU приводит к пересылке этого пакета уровню управления. В этом случае процессору CPU передается исходный пакет, а не пакет, полученный от синтезатора (он отбрасывается2).

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

  • Если outputPort имеет недопустимое значение (например, 9), пакет отбрасывается.

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

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

Зеленая стрелка на рисунке 5 от блока parser runtime к блоку demux представляет дополнительный поток информации от анализатора к демультиплексору — обрабатываемый пакет, а также смещение в пакете, на котором был закончен анализ (т. е. начало данных пакета).

5.2.4. Доступные внешние блоки

Архитектура VSS поддерживает внешний блок инкрементного расчета контрольных сумм Checksum16. Блок контрольных сумм включает конструктор и четыре метода.

  • clear() — подготовка блока к новому расчету.

  • update<T>(in T data) — добавление данных к учитываемым в контрольной сумме. Данные должны быть строкой битов, типом заголовка или конструкцией из этих двух типов. Поля в заголовке/структуре объединяются (конкатенация) в порядке их указания в определении типа.

  • get() — возвращает 16-битовую контрольную сумму с дополнением до 1. При вызове этой функции контрольная сумма должна учитывать целое число байтов данных.

  • remove<T>(in T data) — в предположении, что некие данные были учтены в контрольной сумме удаляет их из расчета.

5.3. Полная программа VSS

Здесь представлена полная программа P4, которая реализует базовую пересылку пакетов IPv4 на основе архитектуры VSS. Эта программа не использует всех функций, обеспечиваемых архитектурой (например, рециркуляция), но применяет директивы препроцессора #include (см. параграф 6.2).

 Рисунок 7. Конвейер таблиц СД программы VSS P4.

Анализатор пытается распознать заголовок Ethernet, за которым следует заголовок IPv4. При отсутствии любого из этих заголовков возникает ошибка. В остальных случаях информация из заголовков передается в структуру Parsed_packet. Конвейер СД, показанный на рисунке 7, состоит из 4 блоков, обозначенных именами таблиц P4.

  • При возникновении ошибки анализатора пакет отбрасывается путем установки outputPort = DROP_PORT.

  • Первая таблица использует адрес получателя IPv4 для определения outputPort и адреса IPv4 следующего маршрутизатора (next hop). Если поиск не дал результата, пакет отбрасывается. Таблица также декрементирует значение IPv4 ttl.

  • Вторая таблица проверяет значение ttl и при ttl=0 пакет пересылается на уровень управления через порт CPU.

  • Третья таблица использует адрес IPv4 следующего маршрутизатора (его дает первая таблица) для определения адреса Ethernet следующего маршрутизатора.

  • Последняя таблица использует outputPort для идентификации адреса отправителя Ethernet в текущем коммутаторе, который будет указан в выходном пакете.

Синтезатор создает исходящий пакет, собирая заголовки Ethernet и IPv4, рассчитанные конвейером.

// Включение библиотеки ядра P4
# include <core.p4>

// Включение файла с объявлениями архитектуры VSS.
# include "very_simple_switch_model.p4"

// Эта программа обрабатывает пакеты, включающие заголовки Ethernet и IPv4,
// и пересылает их по IP-адресу получателя.
typedef bit<48>	EthernetAddress;
typedef bit<32>	IPv4Address;

// Стандартный заголовок Ethernet
header Ethernet_h {
	EthernetAddress dstAddr;
	EthernetAddress srcAddr;
	bit<16>	etherType;
}

// Заголовок IPv4 (без опций)
header IPv4_h {
	bit<4>			version;
	bit<4>			ihl;
	bit<8> 			diffserv;
	bit<16>			totalLen;
	bit<16>			identification;
	bit<3> 			flags;
	bit<13>			fragOffset;
	bit<8> 			ttl;
	bit<8> 			protocol;
	bit<16>			hdrChecksum;
	IPv4Address	srcAddr;
	IPv4Address	dstAddr;
}

// Структура разобранных заголовков
struct Parsed_packet {
	Ethernet_h 	ethernet;
	IPv4_h			ip;
}
// Раздел анализатора

// Определенные пользователем ошибки, которые могут возникать при анализе
error {
	IPv4OptionsNotSupported,
	IPv4IncorrectVersion,
	IPv4ChecksumError
}

parser TopParser(packet_in b, out Parsed_packet p) {
	Checksum16() ck;		// Создание экземпляра блока контрольных сумм
	state start {
		b.extract(p.ethernet);
		transition select(p.ethernet.etherType) {
			0x0800: parse_ipv4;
			// Нет принятого по умолчанию правила, все остальные пакеты отвергаются
		}
	}
}

state parse_ipv4 {
	b.extract(p.ip);
	verify(p.ip.version == 4w4, error.IPv4IncorrectVersion);
	verify(p.ip.ihl == 4w5, error.IPv4OptionsNotSupported);
	ck.clear();
	ck.update(p.ip);
	// Проверка того, что контрольная сумма пакета равна 0
	verify(ck.get() == 16w0, error.IPv4ChecksumError);
	transition accept;
}

// Раздел конвейера СД
control TopPipe(inout Parsed_packet headers,
						in error parseError,	// Ошибка анализатора
						in InControl inCtrl,	// Входной порт
						out OutControl outCtrl) {
		IPv4Address nextHop;					// Локальная переменная
		
		/**
		* Указывает, что пакет отбрасывается путем установки 
		* выходного порта DROP_PORT
		*/
		action Drop_action() {
			outCtrl.outputPort = DROP_PORT;
		}

		/**
		* Устанавливает next hop и выходной порт.
		* Декрементирует поле ipv4 ttl.
		* @param ivp4_dest - адрес ipv4 следующего маршрутизатора;
		* @param port - выходной порт
		*/
		action Set_nhop(IPv4Address ipv4_dest, PortId port) {
			nextHop = ipv4_dest;
			headers.ip.ttl = headers.ip.ttl - 1;
			outCtrl.outputPort = port;
		}

		/**
		* Определяет адрес IPv4 следующего маршрутизатора и выходной порт
		* на основе адреса получателя IPv4 в текущем пакет.
		* Декрементирует IPv4 TTL в пакете.
		* @param nextHop - адрес IPv4 следующего маршрутиазатора.
		*/
		table ipv4_match {
			key = { headers.ip.dstAddr: lpm; }	// Максимальное совпадение префиксов
			actions = {
				Drop_action;
				Set_nhop;
			}
			size = 1024;
			default_action = Drop_action;
		}


		/** Передача пакета в порт CPU */
		action Send_to_cpu() {
			outCtrl.outputPort = CPU_OUT_PORT;
		}

		/** Проверка TTL и отправка CPU устаревших пакетов. */
		table check_ttl {
			key = { headers.ip.ttl: exact; }
			actions = { Send_to_cpu; NoAction; }
			const default_action = NoAction; 	// Определено в core.p4
		}

		/**
		* Установка MAC-адреса получателя в пакет
		* @param dmac - MAC-адрес получателя.
		*/
		action Set_dmac(EthernetAddress dmac) {
			headers.ethernet.dstAddr = dmac;
		}

		/**
		* Установка Ethernet адреса получателя пакета 
		* на основе IP-адреса следующего маршрутизатора.
		* @param nextHop - адрес IPv4 следующего маршрутизатора.
		*/
		table dmac {
			key = { nextHop: exact; }
			actions = {
				Drop_action;
				Set_dmac;
			}
			size = 1024;
			default_action = Drop_action;
		}	

		/** 
		* Установка MAC-адреса отправитедя.
		* @param smac - используемый MAC-адрес отправителя
		*/
		action Set_smac(EthernetAddress smac) {
		headers.ethernet.srcAddr = smac;
	}

	/** Установка MAC-адреса отправителя по выходному порту. */
	table smac {
		key = { outCtrl.outputPort: exact; }
		actions = {
			Drop_action;
			Set_smac;
		}
		size = 16;
		default_action = Drop_action;
	}
	apply {
		if (parseError != error.NoError) {
			Drop_action();		// Прямой вызов операции отбрасывания
			return;
		}
		ipv4_match.apply(); 	// Результат сопоставления будет давать nextHop
		if (outCtrl.outputPort == DROP_PORT) return;
		check_ttl.apply();
		if (outCtrl.outputPort == CPU_OUT_PORT) return;
		dmac.apply();
		if (outCtrl.outputPort == DROP_PORT) return;
		smac.apply();
	}
}

// Раздел синтезатора
control TopDeparser(inout Parsed_packet p, packet_out b) {
	Checksum16() ck;
	apply {
		b.emit(p.ethernet);
		if (p.ip.isValid()) {
			ck.clear();						// Подготовка блока контрольных сумм
			p.ip.hdrChecksum = 16w0; 	// Очистка контрольной суммы
			ck.update(p.ip);				// Расчет новой контрольной суммы
			p.ip.hdrChecksum = ck.get();
		}
		b.emit(p.ip);
	}
}

// Экземпляр программы VSS верхнего уровня
VSS(TopParser(),
	TopPipe(),
	TopDeparser()) main;

6. Определение языка P4

Язык P4 можно рассматривать как несколько отдельных компонент, перечисленных ниже.

  • Ядро, включающее типы, переменные, область действия, объявления, операторы, выражения и т. п.

  • Субязык для анализаторов на основе конечного автомата состояний (раздел 11).

  • Субязык для расчетов, использующих блоки СД на основе традиционного императивного потока управления (раздел 12).

  • Субязык для описания архитектуры (раздел 15).

6.1. Синтаксис и семантика

6.1.1. Грамматика

Полная грамматика P416 представлена в Приложении E с использованием языка описания грамматики Yacc/Bison. Приведенный здесь текст основан на той же грамматике. При описании используются указанные ниже стандартные соглашения:

  • символы ВЕРХНЕГО регистра означают терминалы3 грамматики;

  • выдержки из грамматики используют нотацию BNF, как показано ниже.

p4program
	: /* Пусто */
	| p4program declaration
	| p4program ';'
	;

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

ParserModel.verify(bool condition, error err) {
	if (condition == false) {
		ParserModel.parserError = err;
		goto reject;
	}
}

6.1.2. Семантика и абстрактные машины P4

Мы описываем семантику P4 в терминах абстрактных машин, выполняющих традиционный императивный код. Имеется абстрактная машина для каждого субязыка P4 (анализатор, элемент управления). Абстрактные машины описываются с помощью псевдокода.

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

  • поведение ввода и вывода всех блоков P4;

  • состояние, поддерживаемое внешними блоками.

6.2. Предварительная обработка

Для обеспечения сборки программ из множества исходных файлов компиляторам P4 следует поддерживать функциональность перечисленных ниже директив препроцессора C:

	#define для определения макросов (без аргументов)
	#undef
	#if #else #endif #ifdef #ifndef #elif
	#include

Препроцессору также следует удалять последовательности символов \ и перевода строки (коды ASCII 92, 10) для объединения многочисленных строк, созданных при форматировании текста программ для удобства восприятия.

Могут поддерживаться также дополнительные возможности препроцессоров C (например, макросы с аргументами), но это не гарантируется. Подобно принятой в C практике, директива #include может задавать имена файлов в двойных кавычках или в угловых скобках <>.

# include <системный файл>
# include "пользовательский файл"

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

Компиляторам P4 следует корректно обрабатывать директивы #line, которые могут создаваться в процессе предварительной обработки. Эта функциональность позволяет собирать программы P4 из множества исходных файлов, которые могли создаваться разными программистами в разное время, включая:

  • библиотеку ядра P4, определенную в этом документе;

  • архитектуру, определяющую интерфейсы уровня данных и внешние блоки;

  • пользовательские библиотеки компонент (например, определения заголовков стандартных протоколов);

  • программы P4, задающие поведение каждого программируемого блока.

6.2.1. Библиотека ядра P4

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

# include <core.p4>

6.3. Лексические конструкции

Во всех ключевых словах P4 используются только символы ASCII. Все идентификаторы P4 должны использовать только символы ASCII. Компиляторам P4 следует корректно обрабатывать строки с 8-битовыми символами в комментариях и строковых литералах. Строчные и прописные буквы в P4 различаются. Пробельные символы, включая перевод строки, считаются разделителями. Отступы от начала строки не регламентируются, однако в P4 используются похожие на C конструкции блоков и во всех примерах используются принятые в C отступы. Символы табуляции трактуются как пробелы.

Лексический анализатор (lexer) распознает следующие типы терминалов:

  • IDENTIFIER (идентификатор) — начинается с буквы или символа подчеркивания и может содержать буквы, цифры и символы подчеркивания;

  • TYPE (тип) — идентификатор названия типа;

  • INTEGER (целое число) — целочисленные литералы;

  • DONTCARE — одиночный символ подчеркивания;

  • ключевые слова типа RETURN — по соглашению каждый терминал ключевого слова соответствует ключевому слову языка, набранному символами нижнего регистра (например, терминал RETURN соответствует ключевому слову return).

6.3.1. Идентификаторы

Идентификаторы P4 могут включать лишь буквы, цифры и символы подчеркивания (_), а начинаться должны с буквы или символа подчеркивания. Специальный идентификатор, включающий лишь символа подчеркивания (_), указывает значение don’t care (не важно), тип которого может зависеть от контекста. Некоторые ключевые слова (например, apply) могут использоваться в качестве идентификаторов, если не возникает неоднозначности с учетом контекста.

nonTypeName
	: IDENTIFIER
	| APPLY
	| KEY
	| ACTIONS
	| STATE
	;
name
	: nonTypeName
	| TYPE
	;

6.3.2. Комментарии

Язык P4 поддерживает несколько типов комментариев:

  • однострочный комментарий, начинающийся с символов // и продолжающийся до конца строки;

  • многострочный комментарии, заключенный между символами /* и */;

  • вложенные многострочные комментарии не поддерживаются;

  • комментарии в стиле Javadoc, начинающиеся символами /** и заканчивающиеся */

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

P4 трактует комментарии как разделители, поэтому не допускается включение комментариев в маркеры (например, bi/**/t будет трактоваться как два маркера bi и t, , не bit).

6.3.3. Константы

6.3.3.1. Логические константы

Для логического типа Boolean имеется две константы — true и false.

6.3.3.2. Целочисленные константы

Целочисленные константы указываются положительными4 целыми числами с произвольной разрядностью (arbitrary-precision). По умолчанию литералы используют десятичное представление. Для других оснований в константах приняты префиксы:

  • 0x или 0X указывает шестнадцатеричные числа (основание 16);

  • 0o или 0O указывает восьмеричные числа (основание 8);

  • 0b или 0B указывает двоичные числа (основание 2).

Размер числовых констант в битах (разрядность) может быть указан целым числом без знака, за которым следует идентификатор наличия знака у самой константы:

  • w указывает целое число без знака;

  • s указывает целое число со знаком.

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

32w0xFF		// 32-битовое целое число без знака со значением 255
32s0xFF		// 32-битовое целое число со знаком и значением 255
8w0b10101010		// 8-битовое целое число без знака со значением 0xAA
8w0b_1010_1010 	// 8-битовое целое число без знака со значением 0xAA
8w170			// 8-битовое целое число без знака со значением 0xAA
8s0b1010_1010		// 8-битовое целое число со знаком и значением -86
16w0377		// 16-битовое целое число без знака со значением 377 (не 255!)
16w0o377		// 16-битовое целое число без знака со значением 255 (основание 8)
6.3.3.3. Строковые литералы

Строковые литералы (символьные константы) представляют собой произвольные последовательности 8-битовых символов, заключенных в двойные кавычки » (код ASCII 34). Строка начинается с символа » и продолжается до первого символа «, перед которым нет нечетного количества символов обратной дробной черты \ (код ASCII 92). P4 не проверяет корректность символьных строк (т. е. не проверяет корректность кодировки UTF-8).

Поскольку P4 не выполняет каких-либо операций со строками, строковые литералы обычно передаются компилятором P4 без изменения другим инструментам или компиляторам, включая сохранение кавычек. Эти инструменты могут определять свою трактовку escape-последовательностей (например, для задания символов Unicode или обработки не печатаемых символов ASCII).

Ниже приведены три примера строковых литералов.

	"simple string"
	"string \" with \" embedded \" quotes"
	"string with embedded line terminator"

6.4. Соглашения об именовании

P4 поддерживает множество типов. Базовые типа включают битовые строки (bit-string), целые числа (number) и ошибки (error). Имеются также встроенные типы для представления конструкций типа анализаторов (parser), конвейеров (pipeline), действий (action) и таблиц (table). Пользователи могут создавать новые типы с применением структур (structure), перечислений (enum), заголовков (header), стеков заголовков (header_stack), объединений заголовокв (header_union) и т. п.

В этом документе применяются следующие соглашения:

  • встроенные типы указываются символами нижнего регистра (например, int<20>);

  • в пользовательских типах применяются заглавные буквы (например, IPv4Address);

  • переменные типов всегда указываются заглавными буквами (например, parser P<H, IH>(…));

  • в именах переменных заглавные буквы не применяются (например, ipv4header);

  • имена констант указываются заглавными буквами (например, CPU_PORT);

  • ошибки и перечисляемые (enum) указываются в «верблюжьем» стиле (например, PacketTooShort).

6.5. Программы P4

Программа P4 представляет собой список объявлений:

p4program
	: /* Пусто */
	| p4program declaration
	| p4program ';'	/* Пустое объявление */
	;
declaration
	: constantDeclaration
	| externDeclaration
	| actionDeclaration
	| parserDeclaration
	| typeDeclaration
	| controlDeclaration
	| instantiation
	| errorDeclaration
	| matchKindDeclaration
	;

Пустые объявления указываются одним символом точки с запятой (;). Это учитывает привычки программистов C/C++ и Java (например, в некоторых конструкциях типа struct не требуется указывать точку с запятой в конце).

6.5.1. Области действия

Некоторые конструкции P4 выступают в качестве пространства имен с локальной значимостью, которое включает:

  • объявления производных типов (struct, header, header_union, enum);

  • операторы блоков, которые ограничивают локальную область действия;

  • блоки parser, table, action и control с локальной значимостью;

  • объявления с типами переменных, которые задают новую область действия для этих переменных; например, приведенное ниже объявление extern задает область действия переменной типа H до конца объявления

	extern E<H>(...) { ... } // Область действия H заканчивается здесь.

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

6.5.2. Элементы с внутренними состояниями

Большинство конструкций P4 не имеет состояний (stateless) — при некой входной информации они выдают результат, определяемый исключительно этой информацией. Имеется лишь две конструкции которые могут сохранять информацию о состоянии:

  • table — таблицы доступны уровню данных только для чтения, но их элементы могут изменять уровень управления;

  • объекты extern — многие из таких объектов имеют состояние, которое поддерживает чтение и запись со стороны уровней данных и управления. Все конструкции языка P414, которые инкапсулируют состояние (например, счетчики, измерители, регистры) представляются в P416 с использованием объектов extern.

В P4 все элементы с внутренними состояниями (stateful) должны явно выделяться во время компиляции с помощью процесса создания экземпляра (instantiation).

Кроме того, анализаторы, блоки управления и программы могут включать создание экземпляров элементов с внутренними состояниями. Таким образом, они также считаются элементами с внутренним состоянием (даже если они не показывают наличие этого состояния) и их экземпляры должны явно создаваться до начала использования. Однако таблицы, хотя они и имеют внутренние состояния, ведут себя иначе — экземпляр таблицы создается при явном объявлении этой таблицы. Для тонкого контроля над созданием экземпляров таблиц программист может объявлять их внутри элементов управления.

В примере из параграфа 5.3 TopParser, TopPipe, TopDeparser, Checksum16 и Switch являются типами. Имеется два экземпляра Checksum16 (один в TopParser, другой в TopDeparser), обозначенные ck. Экземпляры TopParser, TopDeparser, TopPipe и Switch создаются в конце программы при объявлении основного объекта (main), который является экземпляром типа Switch (программа).

6.6. L-значения

L-value представляет собой выражение, которое может присутствовать в левой части операций присваивания или в качестве аргумента, соответствующего параметрам функции out или inout. Эти значения представляют ссылки на хранилища. Приведенные ниже выражения являются допустимыми l-значениями.

prefixedNonTypeName
	: nonTypeName
	| dotPrefix nonTypeName
	;
lvalue
	: prefixedNonTypeName
	| lvalue '.' member
	| lvalue '[' expression ']'
	| lvalue '[' expression ':' expression ']'
	;
  • идентификаторы базового или производного типа;

  • операции доступа к полям структуры, заголовка или объединения заголовков (нотация с точками);

  • ссылки на элементы стека заголовков (параграф 8.15), индекс или указание последнего (last) или следующего (next);

  • результат выборки битов[m:l].

Примером допустимого l-значения может служить headers.stack[4].field. Отметим, что вызовы методов и функций не могут возвращать l-значений.

6.7. Соглашения о вызовах — copy in/copy out

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

  • Именованные и типизованные параметры.

  • Создание новой области действия для параметров и локальных переменных.

  • Возможность передачи аргументов путем их привязки к параметрам.

Вызовы выполняются с использованием семантики copy-in/copy-out.

С каждым параметром может быть связана метка направления, как описано ниже.

  • Параметры in предназначены только для чтения. Будет ошибкой использование параметра in в левой части оператора присваивания или его передача вызываемому в качестве аргумента не in. Параметры in создаются путем копирования значения соответствующего аргумента при вызове.

  • Параметры out не инициализируются (параметры типа header или header_union устанавливаются «непригодными») и трактуются как l-значения (параграф 6.6) внутри метода или функции. Аргументы, передаваемые в качестве параметров out, должны быть l-значениями. После выполнения вызова значение параметра копируется в соответствующее место хранилища для данного l-значения.

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

  • Отсутствие направления говорит от том, что параметр является одним из перечисленных:

    • значение, известное в момент компиляции;

    • параметр действия, который может быть установлен только уровнем управления;

    • параметр действия, который может быть напрямую установлен другим вызываемым действием (в этом случае он ведет себя как параметр in).

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

extern void f(inout bit x, in bit y);
extern bit g(inout bit z);
bit a;
f(a, g(a));

Обратите внимание, что оценка g может изменить его аргумент a, поэтому компилятор должен убедиться, что значение, переданное f в качестве первого параметра, не изменилось при оценке второго аргумента. Семантика оценки вызова функции использует приведенный ниже алгоритм (реализации могут отличаться, если они обеспечивают такой же результат).

  1. Аргументы оцениваются слева направо в порядке их указания в вызывающем функцию выражении.

  2. Для каждого параметра out и inout соответствующее l-значение сохраняется (поэтому оно не может измениться в результате оценки следующих аргументов). Это важно, если аргументы включают операции индексирования в стеке заголовков.

  3. Значение каждого аргумента сохраняется во временной области.

  4. Функция вызывается со значениями из временной области в качестве аргументов. Мы гарантируем, что сохраненные во временной области значения не являются псевдонимами, поэтому вызов функции может быть реализован с использованием «вызова по ссылке» (call-by-reference), если архитектура позволяет это.

  5. При завершении работы функции (возврате) значения из временной области, соответствующие аргументам out и inout, копируются слева направо в l-значения, сохраненные в п. 2.

В соответствии с этим алгоритмом вызов предыдущей функции эквивалентен приведенной ниже последовательности операторов.

bit tmp1 = a;		// Оценка a, запись результата
bit tmp2 = g(a);	// Оценка g(a), запись результата, изменение a
f(tmp1, tmp2);	// Оценка f, изменение tmp1
a = tmp1;		// Копирование результата inout обратно в a

Чтобы понять важность этапа 2 в приведенном выше алгоритме, рассмотрим пример

header H { bit z; }
H[2] s;
f(s[a].z, g(a));

Оценка этого вызова будет эквивалентна приведенной ниже последовательности операторов.

bit tmp1 = a;			// Запись значения a
bit tmp2 = s[tmp1].z;	// Оценка первого аргумента
bit tmp3 = g(a);		// Оценка второго аргумента; изменение a
f(tmp2, tmp3);		// Оценка f, изменение tmp2
s[tmp1].z = tmp2;		// Копирование результата inout обратно - это не s[a].z

При использовании объектов extern в качестве аргументов их можно передавать лишь без указания направления (см. пример коммутатора VSS).

6.7.1. Обоснование

Основная причина использования семантики copy-in/copy-out (вместо более распространенной семантики call-by-reference) заключается в контроле побочных эффектов использования внешних функций и методов. Функции и методы extern являются основным механизмом, с помощью которого программа P4 взаимодействует со своим окружением. Семантика copy-in/copy-out не позволяет внешним функциям ссылаться на программные объекты P4 и это позволяет компилятору ограничивать побочные эффекты, которые внешние функции могут создавать для программ P4 в пространстве (нет возможности воздействовать на параметры) и времени (побочные эффекты возможны только во время вызова).

В общем случае возможности внешних функций не ограничены — они могут хранить информацию в глобальном хранилище, создавать отдельные потоки, группироваться для совместного использования информации, но не имеют доступа к переменным внутри программ P4. С помощью семантики copy-in/copy-out компилятор может передавать информацию между программами P4 и функциями extern.

Ниже перечислены дополнительные преимущества, обеспечиваемые семантикой copy-in copy-out.

  • Возможность компилировать программы P4 для архитектуры, не поддерживающей ссылок (например, содержащих данные в именованных регистрах). Такая архитектура может требовать доступности индексов стека заголовков, которые появляются в программе, в момент компиляции.

  • Упрощение анализа для некоторых компиляторов, поскольку параметры функции никогда не будут псевдонимами друг друга внутри функции.

parameterList
	: /* Пусто */
	| nonEmptyParameterList
	;
nonEmptyParameterList
	: parameter
	| nonEmptyParameterList ',' parameter
	;
parameter
	: optAnnotations direction typeRef name
	;
direction
	: IN
	| OUT
	| INOUT
	| /* Пусто */
	;

Ниже кратко перечислены ограничения, связанные с направлением для параметров.

  • При использовании объектов extern в качестве параметров они могут передаваться лишь без направления.

  • Все параметры конструктора оцениваются во время компиляции и по этой причине они не могут иметь направления (не могут быть in, out или inout) — это применимо к объектам package, control, parser и extern. Значения этих параметров должны быть заданы во время компиляции и должны оцениваться по известным в момент компиляции значениям (см. раздел 13).

  • Для действий все параметры без направления должны размещаться в конце списка параметров. Когда действие появляется в списке действий таблицы, требуется привязка лишь для параметров с направлениям (см. параграф 12.1).

  • Действия могут также вызываться явно с использованием синтаксиса вызова функций из блока управления или другого действия. В таких случаях значения всех параметров действия должны быть представлены явно, включая значения параметров без направления. Параметры без направления в этом случае ведут себя подобно параметрам in (см. параграф 12.1.1).

6.8. Преобразование имен

Объекты P4, создающие пространства имен, организованы иерархически. Имеется безымянное пространство верхнего уровня, содержащее все объявления этого уровня.

Идентификаторы, имеющие префикс в виде точки, всегда преобразуются в пространство имен верхнего уровня.

const bit<32> x = 2;
control c() {
	int<32> x = 0;
	apply {
		x = x + (int<32>).x;	// x - локальная переменная int<32>,
						// .x - переменная верхнего уровня bit<32>
	}
}

Ссылки при преобразовании идентификаторов применяются в направлении изнутри наружу, начиная с текущей области действия и далее во все лексически охватывающие области. Компилятор может выдавать предупреждение, если для одного имени возможно несколько преобразований (затенение имен).

const bit<4> x = 1;
control p() {
	const bit<8> x = 8;		// Объявление x скрывает глобальную переменную x
	const bit<4> y = .x;	// Ссылка на x верхнего уровня
	const bit<8> z = x;		// Ссылка на локальную переменную x функции p
	apply {}
}

6.9. Видимость

Идентификаторы, определенные в пространстве верхнего уровня, имеют глобальную видимость. Объявления внутри parser или control являются «приватными» и на них невозможны ссылки извне охватывающего анализатора или элемента управления.

7. Типы данных P4

Язык P416 является статически типизованным. Программы, которые не проходят проверку типов, считаются недействительными и отвергаются компилятором. P4 поддерживает множество базовых типов, а также операторы типа для создания производных типов. Некоторые значения преобразуются в другой тип с помощью cast. Однако для того, чтобы намерения пользователя оставались понятными, неявные преобразования разрешаются лишь в редких случаях, а диапазон доступных преобразований осознанно ограничен.

7.1. Базовые типы

Ниже перечислены базовые типы языка P4.

  • Тип void не имеет значений и может использоваться лишь в нескольких случаях.

  • Тип error служит для передачи информации об ошибках, определяемой компилятором в зависимости от платформы.

  • Тип match_kind служит для описания реализации поиска в таблицах.

  • Тип bool представляет логические значения (Boolean)

  • Битовые строки фиксированного размера обозначаются bit<>

  • Целые числа со знаком фиксированной разрядности представляемые в форме дополнения до двух — int<>.

  • Битовые строки с динамически определяемым максимальным размером — varbit<>

baseType
	: BOOL
	| ERROR
	| BIT
	| BIT '<' INTEGER '>'
	| INT '<' INTEGER '>'
	| VARBIT '<' INTEGER '>'
	;

7.1.1. Тип void

Тип void является пустым и не имеет значений. Он не включен в правило baseType, поскольку может появляться лишь в ограниченных случаях.

7.1.2. Тип error

Тип error type содержит коды, которые могут использоваться для сигнализации ошибок. Новые константы типа error определяются с использованием показанного ниже синтаксиса.

errorDeclaration
	: ERROR '{' identifierList '}'
	;

Все константы типа error помещаются в пространство ошибок, независимо от места определения этой константы. Тип error похож на перечисляемые (enum) типы в других языках. Программа может включать множество объявлений типа error, которые компилятор будет собирать вместе. Если один и тот же идентификатор типа error объявлен в разных местах, это вызывает ошибку. Выражения типа error описаны в параграфе 8.2.

Приведенное ниже объявление создает две константы типа error (эти ошибки объявлены в библиотеке ядра P4).

error { ParseError, PacketTooShort }

Представление ошибок зависит от платформы.

7.1.3. Тип match_kind

Тип match_kind очень похож на тип error и применяется для объявления набора имен, которые могут использоваться в свойствах ключей таблиц (см. параграф 12.2.1). Все идентификаторы помещаются в пространство имен верхнего уровня. Объявление одного и того же идентификатора match_kind несколько раз является ошибкой.

matchKindDeclaration
	: MATCH_KIND '{' identifierList '}'
	;

Библиотека ядра P4 содержит приведенное ниже объявление

match_kind {
	exact,
	ternary,
	lpm
}

Архитектура может поддерживать различные match_kind. Объявления новых match_kinds могут включаться только в файлы описания модели, программисты P4 не могут объявлять новые виды сопоставлений.

7.1.4. Тип bool

Логический тип bool включает два значения — false и true. Логические значения не относятся к integer или bit-string.

7.1.5. Строки

P4 не поддерживает обработку строк. Единственным типом строк, которые могут присутствовать в программах P4, являются строковые константы, описанные в параграфе 6.3.3.3. Эти константы могут применяться лишь в аннотациях (раздел 17). Например, приведенная ниже аннотация указывает, что конкретное имя должно использоваться для таблицы при генерации API уровня управления.

@name("acl") table t1 { ...}

7.1.6. Целые числа

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

  • Подобие языку C. Типизация целых чисел основана на подходах языка C, расширенных для работы со значениями произвольного фиксированного размера. В частности, тип результата выражения зависит лишь от операндов этого выражения, а не от способа использования (потребления) этого результата.

  • Отсутствие неопределенности в поведении. P4 пытается избежать многих особенностей поведения C, включая размер целочисленных переменных (int), которые могли приводить к переполнению, а также неожиданным результатам для некоторых комбинаций входных данных (например, смещение на отрицательную величину, переполнение для целых чисел со знаком и т. п.). Комбинации целых чисел в P4 не приводят к неопределенному поведению.

  • Отсутствие сюрпризов. Правила типизации P4 выбраны так, чтобы поведение программ было максимально близко к поведению хорошо работающих программ C.

  • Запрет вместо сюрпризов. В тех случаях, где могли возникать неожиданные результаты (например, сравнение целых чисел со знаком и без знака в C), было принято решение о запрете выражений с неоднозначной интерпретацией. Например, P4 не разрешает двоичные операции с комбинацией целых чисел со знаком и без знака.

Приоритет арифметических операций аналогичен принятому в C (например, умножение выполняется до сложения).

7.1.6.1. Переносимость

Ни одна платформа (target) P4 не может поддерживать все возможные типы и операции. Например, тип bit<23132312> разрешен в P4, но его поддержка в реальных платформах крайне маловероятна. Каждая платформа может вносить ограничения в набор поддерживаемых типов, которые могут включать:

  • максимальный поддерживаемый размер;

  • требования к выравниванию и заполнению (например, арифметические выражения могут поддерживаться лишь для значений, образованных целым числом байтов);

  • ограничения на поддерживаемые операции (например, архитектура может поддерживать умножение только для небольших констант или сдвиг только на небольшие значения).

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

7.1.6.2. Целые числа без знака (битовые строки)

Целые числа без знака (которые называют также битовыми строками — bit-string) имеют произвольный размер, указываемый в битах. Битовая строка размера W объявляется как bit<W>. Значение W должно быть известно в момент компиляции (см. параграф 16.1) и оцениваться положительным целым числом.

Биты в bit-string нумеруются от 0 до W-1, бит 0 является младшим, W-1 — старшим.

Например, тип bit<128> означает битовую строку из 128 битов с номерами от 0 до 127, где бит 127 является старшим.

Обозначение bit является сокращением для bit<1>.

Архитектуры P4 могут вносить свои ограничения для типов bit, например, может ограничиваться максимальный размер или некоторые арифметические операции будут возможны лишь для некоторых размером (например, 16, 32 и 64).

Операции, которые могут быть выполнены над целыми числами без знака, описаны в параграфе 8.5.

7.1.6.3. Целые числа со знаком

Целые числа со знаком представляются в форме дополнения до 2. Целое число размером W битов объявляется как int<W>. Значение W должно быть известно в момент компиляции и оцениваться положительным целым числом больше 1.

Биты целого числа нумеруются от 0 до W-1, бит 0 является младшим, бит W-1 — старшим.

Например, int<64> описывает целочисленный тип размером 64 бита, где биты нумеруются от 0 до 63 и бит 63 является старшим (знаком).

Архитектуры P4 могут вносить свои ограничения для целых чисел со знаком, например, может ограничиваться максимальный размер или некоторые арифметические операции будут возможны лишь для некоторых размером (например, 16, 32 и 64).

Операции, которые могут быть выполнены над целыми числами без знака, описаны в параграфе 8.6.

7.1.6.4. Битовые строки с динамическим размером

Некоторые сетевые протоколы используют поля, размер которых можно определить лишь в процессе работы (например, опции IPv4). Для поддержки ограниченных манипуляция такими полями P4 обеспечивает специальный тип битовых строк, размер которых определяется во время работы — varbit.

Тип varbit<W> обозначает битовую строку размером не более W, где значение W должно быть известно во время компиляции. Например, тип varbit<120> означает битовую строку, которая может иметь размер от 0 до 120 битов. Большинство операций, применимых к битовым строкам фиксированного размера (целые числа без знака), не пригодны для динамических битовых строк. Архитектуры P4 могут вносить дополнительные ограничения для типов varbit, например, ограничивая максимальный размер или всегда требуя в процессе работы для таких типов размера, кратного целому числу байтов.

Операции для типа varbit описаны в параграфе 8.8.

7.1.6.5. Целые числа с неограниченной разрядностью

Тип данных с неограниченной разрядностью (infinite-precision) описывает целые числа, размер которых не ограничивается. Этот тип обозначается int.

Этот тип зарезервирован для целочисленных литералов (констант) и выражений, содержащих только константы. Во время выполнения программы P4 значения не могут иметь тип int, в процессе компиляции все значения этого типа преобразуются в типы фиксированного размера в соответствии с описанными ниже правилами.

Операции для типа int описаны в параграфе 8.7.

7.1.6.6. Типы целочисленных констант

Типы целочисленных литералов (констант) перечислены ниже.

  • Простые константы типа int.

  • Положительные целые размера N с префиксом w типа bit<N>.

  • Целые числа размера N с префиксом s типа int<N>.

В таблице приведено несколько примеров целочисленных констант указанных типов. Дополнительные примеры литералов даны в параграфе 6.3.3.

Константа

Интерпретация

10

Тип int, значение 10

8w10

Тип bit<8>, значение 10

8s10

Тип int<10>, значение 10

2s3

Тип int<2>, значение -1 (2 последних бита), предупреждение о переполнении

1w10

Тип bit<1>, значение 0 (последний бит), предупреждение о переполнении

1s10

Ошибка — 1-битовый тип по знаком недопустим

7.2. Производные типы

P4 поддерживает множество конструкций, которые можно использовать для создания производных типов:

  • enum

  • header

  • стеки заголовков

  • struct

  • header_union

  • tuple

  • специализация типа

  • extern

  • parser

  • control

  • package

Типы header, header_union, enum, struct, extern, parser, control и package можно использовать только в объявлениях типов, где они задают новое имя для типа, которое позднее можно применять в качестве идентификатора этого типа.

Другие типы не могут быть объявлены, но синтезируются компилятором для представления типов некоторых конструкций языка. Эти типы описаны в параграфе 7.2.8 и включают set и function. Например, программист не может объявить переменную с типом set, но может создать выражение, которое будет оцениваться как тип set. Эти типы используются при проверке типов.

typeDeclaration
	: derivedTypeDeclaration
	| typedefDeclaration
	| parserTypeDeclaration ';'
	| controlTypeDeclaration ';'
	| packageTypeDeclaration ';'
	;
derivedTypeDeclaration
	: headerTypeDeclaration
	| headerUnionDeclaration
	| structTypeDeclaration
	| headerUnionDeclaration
	| enumDeclaration
	;
typeRef
	: baseType
	| typeName
	| specializedType
	| headerStackType
	| tupleType
	;
prefixedType
	: TYPE
	| dotPrefix TYPE
	;
typeName
	: prefixedType
	;

7.2.1. Перечисляемые типы

Перечисляемый тип enum определяется с помощью показанного ниже синтаксиса.

enumDeclaration
	: optAnnotations ENUM name '{' identifierList '}'
	;
identifierList
	: name
	| identifierList ',' name
	;

Например, объявление

	enum Suits { Clubs, Diamonds, Hearths, Spades }

создает новый перечисляемый тип, содержащий 4 константы (например, Suits.Clubs). Объявление enum создает новый идентификатор в текущей области действия для именования созданного типа. Базовое представление таких значений не задается, поэтому из «размер» в битах не определен (он зависит от платформы).

Аннотации, представленные нетерминальными optAnnotations, описаны в разделе 17.

Операции над значениями enum описаны в параграфе 8.3.

7.2.2. Типы заголовков

Для объявления типа заголовка служит приведенный ниже синтаксис.

headerTypeDeclaration
	: optAnnotations HEADER name '{' structFieldList '}'
	;
structFieldList
	: /* Пусто */
	| structFieldList structField
	;
structField
	: optAnnotations typeRef name ';'
	;

где каждый typeRef может указывать битовую строку (фиксированного или переменного размера) или целочисленный тип. Это объявление создает новый идентификатор в текущей области действия, имя которого может служить для указания данного типа. Заголовки похожи на структуры в C, содержащие все указанные поля. Однако заголовок дополнительно включает скрытое логическое поле validity. Когда флаг validity имеет значение true, заголовок считается подходящим. При создании заголовка автоматически устанавливается validity = false. Для манипуляций с битом пригодности используются методы типа header — isValid(), setValid() и setInvalid(), описанные в параграфе 8.14.

Типы заголовков могут быть пустыми

	header Empty_h { }

Отметим, что бит validity имеется и у пустых заголовков.

Заголовки, не включающие полей varbit имеют фиксированный размер, в противном случае размер будет переменным. Размер фиксированного заголовка (в битах) является постоянным и определяется суммой размеров всех включенных в заголовок полей (без учета бита validity). Выравнивания или заполнения для полей заголовка не используется. Архитектура может задавать дополнительные ограничения для типов заголовков (например, ограничение возможного размера целым числом байтов).

Ниже в качестве примера приведено объявление для типичного заголовка Ethernet.

header Ethernet_h {
	bit<48> dstAddr;
	bit<48> srcAddr;
	bit<16> etherType;
}

Приведенный ниже фрагмент объявляет переменную нового типа Ethernet_h.

	Ethernet_h ethernetHeader;

Анализатор P4 обеспечивает способы извлечения полей заголовка из пакетов, как описано в параграфе 11.8. При успешном выполнении операции извлечения заголовков для бита validity устанавливается значение true.

Ниже приведен пример заголовка IPv4 с опциями переменного размера.

header IPv4_h {
	bit<4>		version;
	bit<4>		ihl;
	bit<8>		diffserv;
	bit<16>	totalLen;
	bit<16>	identification;
	bit<3>		flags;
	bit<13>	fragOffset;
	bit<8>		ttl;
	bit<8>		protocol;
	bit<16>	hdrChecksum;
	bit<32>	srcAddr;
	bit<32>	dstAddr;
	varbit<320>	options;
}

Как описано в параграфе 8.11, заголовки с полями переменного размера могут потребовать анализа в несколько проходов путем его разбиения на несколько заголовков.

7.2.3. Стеки заголовков

Стек заголовков представляет собой массив заголовков. Определение типа приведено ниже.

headerStackType
	: typeName '[' expression ']'
	;

Здесь typeName указывает имя типа заголовков. Для стека hs[n] параметр n задает максимальный размер и должен быть положительны целым числом, известным в момент компиляции. Вложенные стеки заголовков не поддерживаются. Во время выполнения программы стек содержит n значений типа typeName, из который пригодными может быть только часть. Выражения для теков заголовков рассмотрены в параграфе 8.15.

Например, определение

header Mpls_h {
	bit<20> 	label;
	bit<3>		tc;
	bit		bos;
	bit<8>		ttl;
}
Mpls_h[10] mpls;

создает стек заголовков с именем mpls, содержащий 10 элементов типа Mpls_h.

7.2.4. Объединения заголовков

Объединение заголовков представляет собой варианты разных заголовков, из которых может быть выбрано не более одного. Такое объединение можно использовать для представления опций а протоколах типа TCP и IP. Это также говорит компилятору P4 о присутствии лишь одного варианта и позволяет сэкономить ресурсы хранилища.

Объединение заголовков определяется, как показано ниже.

headerUnionDeclaration
	: optAnnotations HEADER_UNION name '{' structFieldList '}'
	;

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

Например, показанный ниже тип Ip_h представляет объединение заголовков IPv4 и IPv6.

header_union IP_h {
	IPv4_h v4;
	IPv6_h v6;
}

Объединение заголовков не считается типом фиксированного размера.

7.2.5. Структурированные типы

Структурные типы P4 определяются с помощью показанного ниже синтаксиса.

structTypeDeclaration
	: optAnnotations STRUCT name '{' structFieldList '}'
	;

Это объявление вводит в текущей области новый тип с указанным именем. Список элементов может быть пустым. Например, показанная ниже структура Parsed_headers содержит заголовки, распознанные одним анализатором.

header Tcp_h { ... }
header Udp_h { ... }
struct Parsed_headers {
	Ethernet_h 	ethernet;
	Ip_h		ip;
	Tcp_h		tcp;
	Udp_h		udp;
}

7.2.6. Кортежи

Кортеж (tuple) похож на структуру тем, что содержит множество значений. Однако элементы кортежа не являются именованными полями в отличие от элементов структуры. Тип кортежа с n компонентами типов T1,…,Tn записывается как tuple<T1,…,Tn>

tupleType
	: TUPLE '<' typeArgumentList '>'
	;

Операции над кортежами описаны в параграфах 8.10 и 8.12.

7.2.7. Правила для вложенных типов

В таблице указаны все типы, которые могут присутствовать в header, header_union, struct и tuple. Напомним, что int означает целое число неограниченной разрядности без указания размера.

Тип элемента

Тип контейнера

header

header_union

struct или tuple

bit<W>

разрешено

ошибка

разрешено

int<W>

разрешено

ошибка

разрешено

varbit<W>

разрешено

ошибка

разрешено

int

ошибка

ошибка

ошибка

void

ошибка

ошибка

ошибка

error

ошибка

ошибка

разрешено

match_kind

ошибка

ошибка

ошибка

bool

ошибка

ошибка

разрешено

enum

ошибка

ошибка

разрешено

header

ошибка

разрешено

разрешено

Стек заголовков

ошибка

ошибка

разрешено

header_union

ошибка

ошибка

разрешено

struct

ошибка

ошибка

разрешено

tuple

ошибка

ошибка

разрешено

Обоснование. Тип int не имеет точного размера в отличие от bit<> и int<>. Значения match_kind бесполезно сохранять в переменных, поскольку они служат лишь для указания, как сопоставлять поля с ключами поиска в таблице, а это выполняется в момент компиляции. Тип void бесполезен в какой-либо структуре данных. Заголовки должны иметь точно определенные форматы (как последовательность битов), чтобы их можно было анализировать и собирать.

Отметим, что метод извлечения с двумя аргументами (параграф 11.8.2) для пакетов поддерживается только в полях заголовка varbit.

7.2.8. Синтезированные типы данных

Для проверки типов компилятор P4 может синтезировать некоторые типы представления, которые не могут быть непосредственно выражены пользователем. Эти типы set и function описаны ниже.

7.2.8.1. Типы set

Тип set<T> описывает множество значений типа T и может присутствовать только в ограниченных случаях контекста программ P4. Например, диапазон 8w5 .. 8w8 описывает множество 8-битовых целых чисел 5, 6, 7 и 8, следовательно его типом будет set<bit<8>>;. Это выражение можно использовать в качестве метки в выбранном выражении (см. параграф 11.6), соответствующей любому значению из диапазона. Типы set не могут быть именованными и программисты P4 не могут объявлять их, поскольку эти типы синтезируются компилятором и используются для проверки типов. Выражения с типами set описаны в параграфе 8.12.

7.2.8.2. Типы function

В настоящее время типы function не могут явно создаваться в программах P4 и синтезируются компилятором для представления типов функций, процедур и методов в процессе проверки типов. Тип функции называется также ее сигнатурой. Библиотеки могут содержать определения внешних (extern) функций.

Например, объявление

extern void random(in bit<5> logRange, out bit<32> value);

описывает объект random, которые имеет тип function и представляет следующую информацию:

  • результат имеет тип void;

  • функция имеет два входных параметра;

  • первый параметр имеет направление in, тип bit<5> и имя logRange;

  • второй параметр имеет направление out, тип bit<32> и имя value.

7.2.9. Внешние типы

P4 поддерживает объявления внешних (extern) объектов и функций с использованием приведенного ниже синтаксиса.

externDeclaration
	: optAnnotations EXTERN nonTypeName optTypeParameters '{' methodPrototypes '}'
	| optAnnotations EXTERN functionPrototype ';'
	;
7.2.9.1. Внешние функции

Объявление функции extern описывает имя и тип сигнатуры функции, но не ее реализацию.

functionPrototype
	: typeOrVoid name optTypeParameters '(' parameterList ')'
	;

Пример объявления функции extern приведен в параграфе 7.2.8.2.

7.2.9.2. Внешние объекты

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

methodPrototypes
	: /* Пусто */
	| methodPrototypes methodPrototype
	;
methodPrototype
	: functionPrototype ';'
	| TYPE '(' parameterList ')' ';' // Конструктор
	;
typeOrVoid
	: typeRef
	| VOID
	| nonTypeName
	;	// Может быть переменной типа
optTypeParameters
	: /* Пусто */
	| '<' typeParameterList '>'
	;
typeParameterList
	: nonTypeName
	| typeParameterList ',' nonTypeName
	;

Например, библиотека ядра P4 определяет два extern-объекта packet_in и packet_out, используемых для манипуляций с пакетами (см. параграф 11.8 и раздел 14). Ниже приведен пример вызова методов этого объекта для пакета.

extern packet_out { 	void emit<T>(in T hdr); }
control d(packet_out b, in Hdr h) {
	apply {
		b.emit(h.ipv4);	// Запись заголовка ipv4 в выходной пакет 
	}				// путем вызова метода emit
}

Из числа конструкций P4 только функции и методы поддерживают множественный запуск. В одной области действия может существовать множество методов с одним именем, но даже в этом случае две функции (или метода внешнего объекта) могут использовать одно имя лишь при наличии у них разного числа .

7.2.10. Специализация типа

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

specializedType
	: prefixedType '<' typeArgumentList '>'
	;

Например, приведенное ниже объявление extern описывает базовый блок регистров, где типы элементов, хранящихся в каждом регистре, являются произвольными T.

extern Register<T> {
	Register(bit<32> size);
	T read(bit<32> index);
	void write(bit<32> index, T value);
}

Тип T задается при создании экземпляра набора регистров путем указания типа Register

Register<bit<32>>(128) registerBank;

Создание экземпляра registerBank выполняется с использованием типа Register, специализированного привязкой bit<32> к аргументу типа T.

7.2.11. Типы анализаторов и управляющих блоков

Типы анализаторов и блоков управления похожи на типы функций и описывают сигнатуры анализаторов и блоков управления. Такие функции не возвращают значений. Объявления анализаторов и блоков управления в архитектуре могут быть тазовыми (т. е. включать параметры типа).

Типы parser, control и package не могут служить типами аргументов для методов, анализаторов, элементов управления, таблиц и действий. Они могут применяться в качестве типов аргументов, передаваемых конструкторам (см. раздел 13).

7.2.11.1. Объявление типа анализатора

Объявление типа parser описывает сигнатуру анализатора. Анализатору следует иметь хотя бы один аргумент типа packet_in, представляющий обрабатываемый пакет.

parserTypeDeclaration
	: optAnnotations PARSER name optTypeParameters '(' parameterList ')'
	;

Например, приведенное ниже объявление типа анализатора с именем P параметризовано переменной типа H. Анализатор получает в качестве входного packet_in значение b и дает на выходе два значения:

  • значение определенного пользователем типа H;

  • значение предопределенного типа Counters.

struct Counters { ... }
parser P<H>(packet_in b,
	out H packetHeaders,
	out Counters counters);
7.2.11.2. Объявления типа элемента управления

Объявление типа control описывает сигнатуру блока управления.

controlTypeDeclaration
	: optAnnotations CONTROL name optTypeParameters '(' parameterList ')'
	;

Объявления типа control похожи на объявления типа parser.

7.2.12. Типы программ

Объявление типа package описывает сигнатуру программы.

packageTypeDeclaration
	: optAnnotations PACKAGE name optTypeParameters '(' parameterList ')'
	;

Все параметры программы оцениваются во время компиляции и поэтому они не должны иметь направления (т. е., in, out или inout). В остальном объявление типов package очень похоже на объявление parser. Для программ могут лишь создаваться экземпляры, другого поведения во время работы с ними не связывается.

7.2.13. Типы _

Тип don’t care (_) может использоваться в некоторых случаях. Его следует указывать лишь в позициях, где может быть переменная привязанного типа. Подчеркивание можно использовать для упрощения кода в тех случаях, когда привязка переменной типа не важна (при унификации типа этот тип может быть объединен с любым другим типом). Пример использования этого типа приведен в параграфе 15.1.

7.3. typedef

Объявление typedef может служить для задания другого имени имеющегося типа.

typedefDeclaration
	: TYPEDEF typeRef name ';'
	| TYPEDEF derivedTypeDeclaration name ';'
	| annotations TYPEDEF typeRef name ';'
	| annotations TYPEDEF derivedTypeDeclaration name ';'
	;
typedef bit<32> u32;
typedef struct Point { int<32> x; int<32> y; } Pt;
typedef Empty_h[32] HeaderStack;

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

8. Выражения

В этом разделе описаны все выражения, которые могут применяться в P4, сгруппированные по типу результата.

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

expression
	: INTEGER
	| TRUE
	| FALSE
	| STRING_LITERAL
	| nonTypeName
	| '.' nonTypeName
	| expression '[' expression ']'
	| expression '[' expression ':' expression ']'
	| '{' expressionList '}'
	| '(' expression ')'
	| '!' expression
	| '~' expression
	| '-' expression
	| '+' expression
	| typeName '.' member
	| ERROR '.' member
	| expression '.' member
	| expression '*' expression
	| expression '/' expression
	| expression '%' expression
	| expression '+' expression
	| expression '-' expression
	| expression SHL expression	// SHL это «сдвиг влево» <<
	| expression '>''>' expression	// проверка непрерывности >>
	| expression LE expression		// LE это «меньше или равно» <=
	| expression GE expression
	| expression '<' expression
	| expression '>' expression
	| expression NE expression		// NE это «не равно» !=
	| expression EQ expression		// EQ это «равно» ==
	| expression '&' expression
	| expression '^' expression
	| expression '|' expression
	| expression PP expression		// PP это «конкатенация» ++
	| expression AND expression	// AND это &&
	| expression OR expression		// OR это ||
	| expression '?' expression ':' expression
	| expression '<' typeArgumentList '>' '(' argumentList ')'
	| expression '(' argumentList ')'
	| typeRef '(' argumentList ')'
	| '(' typeRef ')' expression
	;
expressionList
	: /* Пусто */
	| expression
	| expressionList ',' expression
	;
member
	: name
	;
argumentList
	: /* Пусто */
	| nonEmptyArgList
	;
nonEmptyArgList
	: argument
	| nonEmptyArgList ',' argument
	;
argument
	: expression
	;
typeArg
	: DONTCARE
	| typeRef
	;
typeArgumentList
	: typeArg
	| typeArgumentList ',' typeArg
	;

Полная грамматика P4 приведена в Приложении E.

Эта грамматика не показывает приоритет различных операторов, поскольку их порядок в точности соответствует принятому в C. Конкатенация (++) имеет такой же приоритет, как сложение. Битовая выборка a[m:l] имеет такой же приоритет, как индексирование массива (a[i]). Требуется дополнительная семантическая проверка для сдвига вправо, чтобы убедиться в отсутствии пробелов между двумя последовательными символами >>. Это правило требуется для возможности анализа операторов сдвига вправо и специализированных типов, как в function<bit<32>>.

Кроме этих выражений P4 поддерживает также выражения для выбора (параграф 11.6), которые могут применяться только в анализаторах.

8.1. Порядок вычисления выражений

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

  • Логические операции && и || используют метод «короткого замыкания» (short-circuit), т. е. вторая операция выполняется только при необходимости.

  • Для условного оператора e1 ? e2 : e3 сначала вычисляется e1, затем e2 или e3.

  • Все прочие выражения вычисляются слева направо, как они указаны в тексте программы.

  • Оценка вызовов методов и функций выполняется в соответствии с параграфом 6.7.

8.2. Операции над типом error

Символьные имена, объявляемые для типа error относятся к пространству имен ошибок. Для типа error поддерживаются только сравнения в виде равенства (==) и неравенства (!=). Результатом такого сравнения является логическое значение.

Ниже приведен пример проверки наличия ошибок.

error errorFromParser;
...
if (errorFromParser != error.NoError) { ... }

8.3. Операции над типом enum

Символьные имена, объявляемые для типа enum относятся к пространству имен этого типа, а не к пространству имен верхнего уровня.

enum X { v1, v2, v3 }
X.v1	// Ссылка на v1
v1	// Ошибка - v1 не относится к пространству имен верхнего уровня

Подобно error, для enum поддерживаются только сравнения в виде равенства (==) и неравенства (!=). Выражения типа enum не могут быть приведены к какому-либо иному типу и наоборот.

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

8.4. Логические выражения

Для логических выражений поддерживаются операции И (And) — &&, ИЛИ (Or) — ||, НЕ — !, равно — == и не равно — !=.

Порядок действий аналогичен принятому в C, используется сокращение (short-circuit evaluation).

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

if (x) ...

(где x имеет целочисленный тип) должны в P4 иметь вид

if (x != 0) ...

Проверка таких выражений описана в параграфе 8.9.2.

8.4.1. Условный оператор

Условные выражения вида e1 ? e2 : e3 ведут себя так же, как аналогичные выражения C. Как описано выше, сначала оценивается выражение e1, затем, в зависимости от результата, — e2 или e3.

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

8.5. Операции над типом bit (целые числа без знака)

В этом параграфе описаны операции, которые могут быть выполнены над выражениями типа bit<W> для некого размера W, называемого также битовыми строками.

Арифметические операции выполняются с отбрасыванием старших битов, выходящих за пределы размера, подобно операциям с целыми числами без знака в языке C (т. е., представление значений, выходящих за пределы размера W лишь младшими W битами). В частности, P4 не имеет арифметических исключений — результат арифметической операции определен при всех возможных входных значениях.

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

  • Проверка равенства битовых строк одного размера ==, дающая в результате логическое значение.

  • Проверка неравенства битовых строк одного размера !=, дающая в результате логическое значение.

  • Сравнение беззнаковых значений <, >, <=, >=, оба операнда которого должны иметь одинаковый размер, дающее в результате логическое значение.

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

  • Отрицание (-), результатом которого является результат вычитания значения из 2W. Результат является беззнаковым и имеет такой же размер, как входное значение. Семантика операции совпадает с принятой в языке C для целых чисел без знака.

  • Унарный плюс (+) — эта операции эквивалентна отсутствию операций.

  • Сложение (+). Ассоциативная операция, результат которой рассчитывается путем отсечения старших битов суммы, выходящих за пределы размера строки битов (подобно C).

  • Вычитание (-). Результат операции не имеет знака и его тип совпадает с типом операндов. Значение определяется сложением первого операнда с отрицанием второго (подобно C).

  • Умножение (*). Размер результата совпадает с размерами операндов и вычисляется путем отбрасывания старших битов произведения, выходящих за пределы размера. Архитектуры P4 могут вносить дополнительные ограничения (например, возможность умножения только на степени 2).

  • Побитовая операция И для операндов одного размера (&).

  • Побитовая операция ИЛИ для операндов одного размера (|).

  • Побитовое «дополнение» для одной битовой строки (~).

  • Побитовая операция Исключительное-ИЛИ (XOR) для операндов одного размера (^).

Для битовых строк также поддерживаются перечисленные ниже операции.

  • Конкатенация двух битовых строк, обозначаемая ++. Результатом является битовая строка, размер которой равен сумме размеров операндов, а старшие биты принимаются из левого (первого) операнда.

  • Извлечение набора последовательных битов, называемого также «выборкой» (slice), обозначаемое [m:l], где m и l — положительные целые числа, которые известны во время компиляции и m >= l. Результатом является битовая строка размером m — l + 1, включающая биты с номерами от l (младший бит результата) до m (старший бит результата) из исходного операнда. Условия 0 <= l < W и l <= m < W проверяются статически (W — размер исходной битовой строки). Отметим, что обе конечные точки включаются в выборку. Границы выборки должны быть известны в момент компиляции, чтобы размер результата можно было определить во время компиляции. Выборки также являются l-значениями, что говорит о поддержке в P4 операторов присваивания e[m:l] = x . Результатом этого выражения является установка битов от m от l в битовой строке e в соответствии с битами x и сохранение неизменными остальных битов e.

  • Логический сдвиг влево и вправо на известное во время работы значение, обозначаемый << и >>, соответственно. В операциях сдвига левый операнд является целым числом без знака, а правых должен быть выражением типа bit<S> или неотрицательной целочисленной константой. Тип результата совпадает с типом левого операнда. Сдвиг на величину, превышающую размер левого операнда, приводит к установке 0 во всех битах результата.

8.6. Операции над целыми числами фиксированного размера со знаком

В этом параграфе описаны все операции, которые могут быть выполнены в выражениях типа int<W> для некого размера W. Напомним, что int<W> означает целое число со знаком размером W битов, представленное в форме дополнения до 2.

В общем случае арифметические операции P4 не обнаруживают «опустошения» (underflow) или переполнения (overflow) и просто «циклическая арифметика» (wrap around), подобно операциям с целыми числами без знака в языке C. Поэтому попытка представить значение, размер которого выходит за пределы W, будет приводить к потере старших битов сверх W.

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

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

Отметим, что побитовые операции над целыми числами со знаком, определены корректно, поскольку представление определяется дополнением до 2.

Тип int<W> поддерживает перечисленные ниже операции и для всех бинарных операций оба операнда должны быть одного типа. Результат во всех случаях будет иметь результат, размер которого совпадает с размером левого операнда.

  • Отрицание, обозначаемое -.

  • Унарный плюс (+) — эта операции эквивалентна отсутствию операций.

  • Сложение (+).

  • Вычитание (-).

  • Проверка равенства и неравенства (== и !=, соответственно), дающая в результате логическое значение.

  • Численное сравнение <, <=, >, и >=, дающее в результате логическое значение.

  • Умножение (*). Размер результата совпадает с размерами операндов и вычисляется путем отбрасывания старших битов произведения, выходящих за пределы размера. Архитектуры P4 могут вносить дополнительные ограничения (например, возможность умножения только на степени 2).

  • Арифметический влево и вправо (<< и >>, соответственно). Левый операнд имеет знак, а правый должен быть целым числом без знака типа bit<S> или неотрицательной целочисленной константой. Тип результата совпадает с типом левого операнда. Сдвиг на величину, превышающую размер левого операнда, приводит к установке 0 во всех битах результата.

8.6.1. Замечания о сдвигах

Сдвиг (для значений со знаком и без знака) требует специального рассмотрения по приведенным ниже причинам.

  • Сдвиг вправо ведет себя по-разному для значений со знаком и без знака — в первом случае он является арифметическим.

  • Сдвиг на отрицательное значение не имеет четкой семантики — система типов P4 не допускает сдвига на отрицательные значения.

  • В отличие от C сдвиг на величину, превышающую размер операнда, дает определенный результат.

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

Рассмотрим пример

bit<8> x;
bit<16> y;
... y << x ...
... y << 1024 ...

Как отмечено выше, P4 дает определенный результат при сдвиге на значение, превышающее размер левого операнда (в отличие от C).

Платформы P4 могут вносить дополнительные ограничения на операции сдвига типа запрета сдвига на величину, определяемую не константой (выражение с переменным результатом), или на результат выражения, выходящий за некоторые границы. Например, платформа может запрещать сдвиг 8-битового значения на непостоянную величину, размер которой превышает 3 бита.

8.7. Операции над целыми числами произвольной разрядности

Тип int означает целые числа произвольной разрядности. В P4 все выражения типа int должны иметь известные в момент компиляции значения. Ниже перечислены операции для типа int.

  • Отрицание, обозначаемое -.

  • Унарный плюс (+) — эта операции эквивалентна отсутствию операций.

  • Сложение (+).

  • Вычитание (-).

  • Проверка равенства и неравенства (== и !=, соответственно), дающая в результате логическое значение.

  • Численное сравнение <, <=, >, и >=, дающее в результате логическое значение.

  • Умножение (*).

  • Целочисленное деление для положительных значений с отбрасыванием остатка (/).

  • Деление по модулю для положительных значений (%).

  • Арифметический влево и вправо (<< и >>, соответственно). Результат имеет тип int. Правый операнд должен быть положительным. Выражение a << b эквивалентно a × 2b, а a >> b — ⌊a/2b ⌋.

Все операнды, участвующие в этих операциях, должны иметь тип int. Ни одну из этих операций, за исключением сдвига, нельзя использовать для комбинирования значений типа int со значениями фиксированного размера. Однако компилятор автоматически будет добавлять приведение типов для преобразования int в тип фиксированного размера в случаях, описанных в параграфе 8.9.

Все вычисления значений int выполняются без потери информации. Например, перемножение двух 1024-битовых значений может давать 2048-битовый результат (отметим, что конкретное представление значений int не задается). Значения int могут быть приведены к типам bit<w> и int<w>. Приведение значений int к типу с фиксированным размером будет сохранять младшие биты. Если отсечка по размеру будет приводить к потере старших битов, компилятор должен выдавать предупреждение.

Примечание. Побитовые операции (|, &, ^, ~) не определены для выражений типа int. Кроме того, недопустимо использовать деление и деление по модулю для отрицательных значений.

8.8. Операции над битовыми типами переменного размера

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

Для битовых строк переменного размера поддерживается ограниченный набор операций.

  • Извлечение анализатором данных в строку переменного размера с помощью двухаргументного метода внешнего объекта packet_in extern (см. параграф 11.8.3). Эта операция устанавливает динамический размер поля.

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

  • Метод emit внешнего объекта packet_out, который вставляет битовую строку переменного размера с известным динамическим размером в создаваемый пакет (см. раздел 14).

8.9. Приведение типов

P4 поддерживает ограниченный набор преобразований (приведения) типов (cast). Приведение типа записывается в форме (t) e, где t указывает тип, а e — выражение. Приведение разрешено лишь между базовыми типами. Это создает некоторые проблемы для программистов, но и обеспечивает некоторые преимущества:

  • делает намерения пользователя однозначными;

  • делает явными приведения типов связанные с преобразованием числовых значений (реализация некоторых преобразований включает знаки и это требует на некоторых платформах значительных ресурсов);

  • уменьшает число вариантов, принимаемых во внимание спецификацией P4 (некоторые платформы могут поддерживать не все преобразования типов).

8.9.1. Явные преобразования

Перечисленные ниже приведения типов являются допустимыми в P4.

  • bit<1> <-> bool — преобразует 0 в false, 1 в true и обратно.

  • int<W> -> bit<W> — сохраняет все биты неизменными, интерпретируя отрицательные значения как положительные.

  • bit<W> -> int<W> — сохраняет все биты неизменными, интерпретируя значения с установленным старшим битом как отрицательные.

  • bit<W> -> bit<X> — отсекает старшие биты, если W > X и заполняет их нулями в противном случае (W <= X).

  • int<W> -> int<X> — отсекает старшие биты, если W > X и перемещает бит знака в противном случае (W < X).

  • int -> bit<W> — преобразует целочисленное значение в достаточно большую битовую строку с дополнением до 2 для предотвращения потери информации, а затем отсекает старшие биты до размера W. Компилятору следует выдавать предупреждение при переполнении или преобразовании отрицательного значения.

  • int -> int<W> — преобразует целочисленное значение в достаточно большую битовую строку с дополнением до 2 для предотвращения потери информации, а затем отсекает старшие биты до размера W. Компилятору следует выдавать предупреждение при переполнении

  • Преобразования между двумя типами, созданными typedef, эквивалентные одной из приведенных выше комбинаций.

8.9.2. Неявные преобразования

Для сохранения простоты языка и предотвращения скрытых издержек в P4 неявное приведение типа используется лишь для типов с фиксированной шириной. В частности применение бинарной операции к выражениям типа int и типа с фиксированным размером будут неявно приводить тип int к типу второго выражения.

Например для выражений

bit<8>		x;
bit<16>	y;
int<8>		z;

компилятор будет добавлять неявные приведения типа:

  • x + 1 становится x + (bit<8>)1;

  • z < 0 становится z < (int<8>)0;

  • x << 13 становится 0; предупреждение о переполнении;

  • x | 0xFFF становится x | (bit<8>)0xFFF; предупреждение о переполнении.

8.9.3. Недопустимые арифметические выражения

Многие арифметические выражения, разрешенные в других языках, будут недопустимыми в P4. Для иллюстрации рассмотрим следующие выражения:

bit<8>		x;
bit<16>	y;
int<8>		z;

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

Выражение

В чем ошибка

Варианты

x + y

Разные размеры

bit<16>)x + y
x + (bit<8>)y
x + z

Разные знаки

(int<8>)x + z
x + (bit<8>)z
(int<8>)y

Нельзя изменить сразу знак и размер

(int<8>)(bit<8>)y
(int<8>)(int<16>)y
y + z

Разные знаки и размеры

(int<8>)(bit<8>)y + z
y + (bit<16>)(bit<8>)z
(bit<8>)y + (bit<8>)z
(int<16>)y + (int<16>)z
x << z

RHS для сдвига не может иметь знака

x << (bit<8>)z
x < z

Разные знаки

X < (bit<8>)z
(int<8>)x < z
1 << x

Размер 1 не известен

32w1 << x
~1

Битовая операция с целым числом

~32w1
5 & -3

Битовая операция с целым числом

32w5 & -3

8.10. Операции над кортежами

Значения типа «кортеж» (tuple) могут назначаться другим кортежам того же типа, передаваться в качестве аргументов функции или возвращаться функцией, а также могут инициализироваться списком выражений.

tuple<bit<32>, bool> x = { 10, false };

8.11. Операции над списками

Список задается с использованием фигурных скобок, элементы разделяются запятыми.

expression ...
	| '{' expressionList '}'
expressionList
	: /* Пусто */
	| expression
	| expressionList ',' expression
	;

Тип списка — кортеж (параграф 7.2.8). Списки могут назначаться в качестве значений выражениям типа tuple, struct или header, а также передаваться методам в качестве аргументов. Списки могут быть вложенными. Однако списки не являются l-значениями.

Например, в приведенном ниже фрагменте используется выражение-список для передачи нескольких полей заголовков одновременно внешней функции LearningProvider

extern LearningProvider {
	void learn<T>(in T data);
}
LearningProvider() lp;
lp.learn( { hdr.ethernet.srcAddr, hdr.ipv4.src } );

Список можно использовать для инициализации структуры, если список имеет количество элементов, совпадающее с числом полей структуры. Результатом будет присвоение значения i-го элемента списку i-му полю структуры.

struct S {
	bit<32> a;
	bit<32> b;
}
const S x = { 10, 20 };	// a = 10, b = 20

Списки можно также использовать для инициализации переменных типа tuple.

tuple<bit<32>, bool> x = { 10, false };

8.12. Операции над множествами

Некоторые выражения P4 обозначают наборы значений (set<T> для некого типа T, см. параграф 7.2.8.1). Такие выражения могут появляться лишь в некоторых анализаторах контекста и константах в таблицах. Например, выражение select (см. параграф 11.6) имеет показанную ниже структуру.

select (expression) {
	set1: state1;
	set2: state2;
	...
}

Здесь выражения set1, set2 и т. п. оцениваются набором значений и select проверяет, относится ли значение к множествам, использованным в качестве меток.

keysetExpression
	: tupleKeysetExpression
	| simpleKeysetExpression
	;
tupleKeysetExpression
	: '(' simpleKeysetExpression ',' simpleExpressionList ')'
	;
simpleExpressionList
	: simpleKeysetExpression
	| simpleExpressionList ',' simpleKeysetExpression
	;
simpleKeysetExpression
	: expression
	| DEFAULT
	| DONTCARE
	| expression MASK expression
	| expression RANGE expression
	;

Операторы маскирования (&&&) и диапазона (..) имеют одинаковый приоритет, который непосредственно выше &.

8.12.1. Одноэлементные множества

В контексте множества выражение означает множество с одним элементом. Например, в приведенном ниже фрагменте программы

select (hdr.ipv4.version) {
	4: continue;
}

Метка 4 означает одноэлементное множество, содержащее значение 4.

8.12.2. Универсальное множество

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

select (hdr.ipv4.version) {
	4: continue;
	_: reject;
}

8.12.3. Маски

Инфиксный оператор &&& принимает два аргумента типа bit<W> и создает значение типа set<bit<W>>. Правый операнд используется в качестве «маски», в которой нулевое значение бита указывает, что соответствующий бит первого операнда не имеет значения (don’t care). Формально множество a &&& b определяется как

a &&& b = { c типа bit<W>, где a & b = c & b }

Например,

8w0x0A &&& 8w0x0F

означает множество, содержащее 16 различных 8-битовых значений, имеющих битовый шаблон XXXX1010, где X указывает любое значение бита. Отметим, что возможно множество способов выразить набор ключей с использованием оператора маскирования (например, 8w0xFA &&& 8w0x0F означает то же, что и выражение выше).

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

8.12.4. Диапазоны

Инфиксный оператор .. принимает два аргумента одного типа T, где T может быть bit<W> или int<W> и дает в результате значение типа set<T>. Множество содержит все значения из числового интервала между первым и вторым операндом, включительно. Например,

4w5 .. 4w8

означает набор значений 4w5, 4w6, 4w7 и 4w8.

8.12.5. Произведения

Несколько множеств можно объединить с помощью декартова произведения

select(hdr.ipv4.ihl, hdr.ipv4.protocol) {
	(4w0x5, 8w0x1): parse_icmp;
	(4w0x5, 8w0x6): parse_tcp;
	(4w0x5, 8w0x11): parse_udp;
	(_, _): accept; }

Типом произведения множеств будет множество кортежей (tuple).

8.13. Операции над структурированными типами

Единственной операцией для выражений типа struct является доступ к полям, указываемым с помощью точки (.) типа s.field. Если s — l-значение, то s.field тоже будет l-значением. P4 также позволяет копировать структуры с использованием операций присваивания, где источник и назначение имеют одинаковый тип. Структуры могут также инициализироваться списочным выражением, как описано в параграфе 8.11.

8.14. Операции над заголовками

Для заголовков поддерживаются такие же операции, как для структур. При операциях присваивания между заголовками копируется также бит validity.

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

  • isValid() возвращает значение бита validity в заголовке;

  • setValid() устанавливает в заголовке для бита validity значение true (это применимо только к l-значению);

  • setInvalid() устанавливает в заголовке для бита validity значение false (это применимо только к l-значению).

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

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

header H { bit<32> x; bit<32> y; }
H h;
h = { 10, 12 };	// Это также делает заголовок h действительным

8.15. Операции над стеками заголовков

Стек заголовков представляет собой массив фиксированного размера из заголовков одного типа. Подходящие элементы стека заголовков не обязаны быть непрерывными. P4 обеспечивает набор расчетов для манипуляций со стеками заголовков. Стек hs типа h[n] можно рассматривать в терминах приведенного ниже псевдокода.

// Объявление типа
struct hs_t {
	bit<32> nextIndex;
	bit<32> size;
	h[n] data;		// Обычный массив
}
// Экземпляр объявления и инициализация
hs_t hs;
hs.nextIndex = 0;
hs.size = n;

Интуитивно стек заголовков можно рассматривать как структуру, содержащую обычный массив заголовков hs и счетчик nextIndex, который можно использовать для упрощения анализаторов стеков заголовков, как описано ниже. Счетчик nextIndex инициализируется значением 0.

Для стека заголовков hs размером n приведенные ниже выражения являются допустимыми.

  • hs[index] указывает ссылку на заголовок в указанной позиции стека. Если hs является l-значением, результат также будет l-значением. Заголовок может быть непригодным. Некоторые архитектуры могут требовать, чтобы значение выражения index было известно во время компиляции. Обращение к стеку заголовков с индексом меньше 0 или больше hs.size приводит к неопределенному результату.

  • hs.size указывает 32-битовое целое число без знака, которое возвращает размер стека заголовков (постоянная величина в момент компиляции).

  • Присваивание заголовка из стека hs в заголовок другого стека с такими же типами и размерами. Копируются все компоненты hs, включая элементы и биты validity, а также nextIndex.

Чтобы помочь программистам в создании анализаторов стеков, P4 также обеспечивает расчеты, автоматически выполняемые при разборе элементов стека.

  • hs.next указывает ссылку на элемент с индексом hs.nextIndex в стеке и может использоваться только в заголовках. Если счетчик nextIndex не меньше размера стека, оценка выражения приводит к отказу и установке ошибки в error.StackOutOfBounds. Если hs является l-значением, hs.next тоже будет l-значением.

  • hs.last указывает ссылку на элемент с индексом hs.nextIndex — 1 в стеке, если такой элемент существует и может использоваться только в анализаторах. Если счетчик nextIndex меньше 1 или больше размера стека, оценка выражения приводит к отказу и установке ошибки в error.StackOutOfBounds. Если hs является l-значением, hs.next тоже будет l-значением.

  • hs.lastIndex — 32-битовое целое число без знака, которое представляет индекс hs.nextIndex — 1 и может использоваться только в анализаторах. Если счетчик nextIndex = 0, оценка выражения дает неопределенное значение.

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

  • hs.push_front(int count) сдвигает hs «вправо» на величину count. Первые count элементов становятся недействительными. Последние count элементов стека отбрасываются. Счетчик hs.nextIndex инкрементируется на величину count. Аргумент count должен быть положительным целым числом, значение которого известно в момент компиляции. Возвращаемое значение имеет тип void.

  • hs.pop_front(int count) сдвигает hs «влево» на величину count (т. е. элемент с индексом count перемещается в стеке в позицию 0). Последние count элементов становятся недействительными. Счетчик hs.nextIndex декрементируется на величину count. Аргумент count должен быть положительным целым числом, значение которого известно в момент компиляции. Возвращаемое значение имеет тип void.

Приведенный ниже псевдокод определяет поведение push_front и pop_front.

void push_front(int count) {
	for (int i = this.size-1; i >= 0; i -= 1) {
		if (i >= count) {
			this[i] = this[i-count];
		} else {
			this[i].setInvalid();
		}
	}
	this.nextIndex = this.nextIndex + count;
	if (this.nextIndex > this.size) this.nextIndex = this.size;
	// Примечание. В this.last, this.next и this.lastIndex устанавливается this.nextIndex
}
void pop_front(int count) {
	for (int i = 0; i < this.size; i++) {
		if (i+count < this.size) {
			this[i] = this[i+count];
		} else {
			this[i].setInvalid();
		}
	}
	if (this.nextIndex >= count) {
		this.nextIndex = this.nextIndex - count;
	} else {
		this.nextIndex = 0;
	}
	// Примечание. В this.last, this.next и this.lastIndex устанавливается this.nextIndex
}

8.16. Операции над объединениями заголовков

Переменная, объявленная с типом union изначально непригодна. Например,

header H1 {
	bit<8> f;
}
header H2 {
	bit<16> g;
}
header_union U {
	H1 h1;
	H2 h2;
}
U u; // u не пригодно

Это также означает, что заголовки от h1 до hn в объединении заголовков также непригодны. В отличие от заголовков объединение не инициализируется. Однако объединение заголовков можно сделать пригодным, присваивая действительный заголовок одному из элементов объединения.

U u;
H1 my_h1 = { 8w0 };	// my_h1 пригодно
u.h1 = my_h1;		// u и u.h1 не пригодны

Можно также присвоить список элементу объединения заголовков.

U u;
u.h2 = { 16w1 };	// u и u.h2 не пригодны

или установить в них биты validity напрямую.

U u;
u.h1.setValid();	// u и u.h1 пригодны
H1 my_h1 = u.h1;	// my_h1 пригодно, но содержит неопределенное значение

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

Более формально, если u — выражение, типом которого служит объединение заголовков U с полями, упорядоченными по hi, для манипуляций u можно использовать перечисленные ниже операции.

  • u.hi.setValid() устанавливает validity = true в заголовке hi и false — в остальных заголовках (в результате считывание этих заголовков будет давать неопределенное значение).

  • u.hi.setInvalid() устанавливает validity = false в любом элементе u, если ранее там было установлено значение true и это приводит к тому, что считывание любого заголовка из u будет давать неопределенный результат.

Можно воспринимать присваивание заголовку

u.hi = e

как эквивалент

u.hi.setValid();
u.hi = e;

если e действительно и

u.hi.setInvalid();

в противном случае.

Присваивания между переменными одного типа объединения заголовков разрешены. Присваивание u1 = u2 полностью копирует состояние объединения u2 в u1. Если u2 действительно, в нем присутствует некий заголовок u2.hi, который является действительным. Присваивание ведет себя так же, как u1.hi = u2.hi. Если u2 не действительно, u1 также становится недействительным (т. е., все действительные заголовки u1 становятся недействительными).

Метод u.isValid() возвращает true, если любой элемент объединения заголовков u является действительным. В противном случае возвращается false. Методы setValid() и setInvalid() не определены для объединений заголовков.

Представление выражения типа объединения заголовков на выдачу (to emit) просто приводит к выдаче одного действительного заголовка, если такой имеется.

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

header_union IP {
	IPv4 ipv4;
	IPv6 ipv6;
}
struct Parsed_packet {
	Ethernet ethernet;
	IP ip;
}
parser top(packet_in b, out Parsed_packet p) {
	state start {
		b.extract(p.ethernet);
		transition select(p.ethernet.etherType) {
			16w0x0800 : parse_ipv4;
			16w0x86DD : parse_ipv6;
		}
	}
	state parse_ipv4 {
		b.extract(p.ip.ipv4);
		transition accept;
	}
	state parse_ipv6 {
		b.extract(p.ip.ipv6);
		transition accept;
	}
}

В другом примере объединение заголовков используется для анализа (отдельных) опций TCP.

header Tcp_option_end_h {
	bit<8> kind;
}
header Tcp_option_nop_h {
	bit<8> kind;
}
header Tcp_option_ss_h {
	bit<8>	kind;
	bit<32> maxSegmentSize;
}
header Tcp_option_s_h {
	bit<8>	kind;
	bit<24> scale;
}
header Tcp_option_sack_h {
	bit<8>		kind;
	bit<8>		length;
	varbit<256>	sack;
}
header_union Tcp_option_h {
	Tcp_option_end_h	end;
	Tcp_option_nop_h	nop;
	Tcp_option_ss_h	ss;
	Tcp_option_s_h	s;
	Tcp_option_sack_h 	sack;
}
typedef Tcp_option_h[10] Tcp_option_stack;
struct Tcp_option_sack_top {
	bit<8> kind;
	bit<8> length;
}
parser Tcp_option_parser(packet_in b, out Tcp_option_stack vec) {
	state start {
		transition select(b.lookahead<bit<8>>()) {
			8w0x0 : parse_tcp_option_end;
			8w0x1 : parse_tcp_option_nop;
			8w0x2 : parse_tcp_option_ss;
			8w0x3 : parse_tcp_option_s;
			8w0x5 : parse_tcp_option_sack;
		}
	}
	state parse_tcp_option_end {
		b.extract(vec.next.end);
		transition accept;
	}
	state parse_tcp_option_nop {
		b.extract(vec.next.nop);
		transition start;
	}
	state parse_tcp_option_ss {
		b.extract(vec.next.ss);
		transition start;
	}
	state parse_tcp_option_s {
		b.extract(vec.next.s);
		transition start;
	}
	state parse_tcp_option_sack {
		bit<32> n = (bit<32>)b.lookahead<Tcp_option_sack_top>().length;
		b.extract(vec.next.sack, n);
		transition start;
	}
}

8.17. Вызовы методов и функций

Для вызова методов и функций используется показанный ниже стандартный синтаксис.

expression
	: ...
	| expression '<' typeArgumentList '>' '(' argumentList ')'
	| expression '(' argumentList ')'
argumentList
	: /* Пусто */
	| nonEmptyArgList
	;
nonEmptyArgList
	: argument
	| nonEmptyArgList ',' argument
	;
argument
	: expression
	;
typeArgumentList
	: typeRef
	| typeArgumentList ',' typeRef
	;

Аргументы функций оцениваются по порядку слева направо перед реальным вызовом функции. При вызовах используются соглашения copy-in/copy-out (параграф 6.7). Для базовых функций аргументы типа могут быть явно заданы при вызове. Компилятор не добавляет неявных преобразований типа для аргументов методов или функций, типы этих аргументов должны точно соответствовать типам параметров.

При использовании функции в качестве оператора возвращенный функцией результат отбрасывается.

8.18. Вызовы конструкторов

Несколько конструкций P4 обозначают ресурсы, выделяемые во время компиляции:

  • внешние объекты;

  • анализаторы;

  • блоки управления;

  • программы.

Выделение таких объектов может выполняться двумя способами:

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

  • путем создания экземпляра, как описано в параграфе 9.3.

Синтаксис вызова конструктора похож на вызов функции. Конструкторы целиком оцениваются в момент компиляции (см. параграф 16). Поэтому все аргументы конструктора должны быть выражениями, которые могут быть оценены во время компиляции.

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

extern ActionProfile {
	ActionProfile(bit<32> size);	// Конструктор
}
table tbl {
	actions = { ... }
	implementation = ActionProfile(1024);	// Вызов конструктора
}

9.Объявления констант и переменных

9.1. Константы

Синтаксис определения постоянных значений (констант) приведен ниже.

constantDeclaration
	: optAnnotations CONST typeRef name '=' initializer ';'
	;
initializer
	: expression
	;

Такое определение вводит константу со значением заданного типа. Ниже приведены примеры корректного определения констант.

const bit<32> COUNTER = 32w0x0;
struct Version {
	bit<32> major;
	bit<32> minor;
}
const Version version = { 32w0, 32w0 };

Значение (инициализатор) константы должно быть известно в момент компиляции.

9.2. Переменные

Локальные переменные объявляются с указанием типа и имени, а также может указываться инициализатор (начальное значение) и аннотация.

variableDeclaration
	: annotations typeRef name optInitializer ';'
	| typeRef name optInitializer ';'
	;
optInitializer
	: /* Пусто */
	| '=' initializer
	;

Переменные, объявленные без инициализатора, являются неинициализированными (за исключением стеков заголовков, в которых счетчик nextIndex инициализируется значением 0, как описано в параграфе 8.15). Язык вносит некоторые ограничения на типы переменных — можно использовать большинство типов P4, которые могут быть записаны явно (например, базовые типы, struct, header, header_stack, tuple). Однако невозможно объявить переменные типов, которые могут лишь синтезироваться компилятором (например, set). Кроме того, переменные типа parser, control, package и extern должны декларироваться с помощью создания экземпляров (см. параграф 9.3).

Считывание значения переменной, которая не была инициализирована, дает неопределенный результат. Компилятору следует следует пытаться обнаруживать такие события и выдавать предупреждения. Объявления переменных могут встречаться в разных местах программ P4:

  • в операторах блоков;

  • в состоянии parser;

  • в теле action;

  • в блоке применения блока control;

  • в списке локальных объявлений parser;

  • в списке локальных объявлений control.

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

9.3. Создание экземпляров

Создание экземпляра похоже на объявление переменной, но зарезервировано для типов с конструктором (объекты extern, блоки управления, parser, package):

instantiation
	: typeRef '(' argumentList ')' name ';'
	| annotations typeRef '(' argumentList ')' name ';'
	;

Создание экземпляра записывается как вызов конструктора, за которым следует имя. Создание экземпляров всегда происходит во время компиляции (параграф 16.1). В результате создается объект с указанным именем, которое привязывается к результату вызова конструктора.

Например, гипотетический набор объектов Counter может быть создан с помощью приведенного ниже фрагмента.

// Из библиотеки платформы
enum CounterType {
	Packets,
	Bytes,
	Both
}
extern Counter {
	Counter(bit<32> size, CounterType type);
	void increment(in bit<32> index);
}
// Пользовательская программа
control c(...) {
	Counter(32w1024, CounterType.Both) ctr;	// Создание экземпляра
	apply { ... }
}

9.3.1. Ограничения на создание экземпляров верхнего уровня

Программа P4 не может инициализировать элементы управления и анализаторы на верхнем уровне программы (package). Это ограничение предназначено для того, чтобы большинство состояний относилось к самой архитектуре или было локальным для анализатора или элемента управления. Например, приведенная ниже программа не будет корректной

// Программа
control c(...) { ... }
c() c1;	// Недопустимое создание экземпляра верхнего уровня

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

10. Операторы

Каждый оператор P4 (за исключением операторов блока) должен завершаться символом ; (точка с запятой). Операторы могут появляться в нескольких местах программ:

  • внутри состояний parser;

  • внутри блока control;

  • внутри action.

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

statement
	: assignmentOrMethodCallStatement
	| conditionalStatement
	| emptyStatement
	| blockStatement
	| exitStatement
	| returnStatement
	| switchStatement
	;
assignmentOrMethodCallStatement
	: lvalue '(' argumentList ')' ';'
	| lvalue '<' typeArgumentList '>' '(' argumentList ')' ';'
	| lvalue '=' expression ';'
	;

Кроме того, анализаторы поддерживают оператор transition (параграф 11.5).

10.1. Оператор присваивания

Оператор присваивания обозначается знаком равенства (=) и сначала его левая часть оценивается в l-значение, затем правая оценивается в значение, которое после этого копируется в l-value. Производные типы (например, структуры) копируются рекурсивно, копируются все компоненты заголовков, включая биты validity. Присваивание не определено для внешних значений.

10.2. Пустой оператор

Пустой оператор указывается одним символом ; (точка с запятой) и означает отсутствие операций.

emptyStatement
	: ';'
	;

10.3. Оператор блока

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

blockStatement
	: optAnnotations '{' statOrDeclList '}'
	;
statOrDeclList
	: /* Пусто */
	| statOrDeclList statementOrDeclaration
	;
statementOrDeclaration
	: variableDeclaration
	| constantDeclaration
	| statement
	| instantiation
	;

10.4. Оператор возврата

Оператор возврата return незамедлительно прерывает исполнение включающего его действия или элемента управления. Операторы return не допускаются внутри parser.

returnStatement
	: RETURN ';'
	;

10.5. Оператор выхода

Оператор выхода exit незамедлительно прерывает исполнение всех выполняющихся в данный момент блоков — текущего действия (при вызове из action), текущего элемента управления (control) и всех их вызовов. Операторы exit не допускаются внутри parser.

exitStatement
	: EXIT ';'
	;

10.6. Оператор условия

Условный оператор использует стандартный синтаксис и семантику, похожие на другие языки программирования. Однако условное выражение в P4 должно иметь логический тип (а не целочисленный). Условные операторы не допускаются внутри parser.

conditionalStatement
	: IF '(' expression ')' statement
	| IF '(' expression ')' statement ELSE statement
	;

При использовании вложенных операторов if субоператор else относится в внешнему if, у которого нет else.

10.7. Оператор вариантов

Оператор switch можно применять только в блоках управления.

switchStatement
	: SWITCH '(' expression ')' '{' switchCases '}'
	;
switchCases
	: /* Пусто */
	| switchCases switchCase
	;
switchCase
	: switchLabel ':' blockStatement
	| switchLabel ':'	// Пройти к следующему варианту.
	;
switchLabel
	: name
	| DEFAULT
	;

Выражения в операторах switch ограничены теми, результатом которых является вызов таблицы (см. параграф 12.2.2).

Если за меткой в операторе switch не следует оператор блока, выполняется переход к следующей метке, а при наличии оператора блоков он выполняется без перехода к следующей метке. Отметим, что это отличается от языка C, где требуется оператор break для предотвращения перехода к следующему варианту. Допускается отсутствие в некоторых действиях какого-либо совпадающего варианта, а также отсутствие используемой по умолчанию метки. Если во время работы соответствующего варианта не найдено, просто продолжится выполнение программы. Следует отметить, что не допускается включение одной и той же метки несколько раз в одном операторе switch.

switch (t.apply().action_run) {
	action1:	// Переход к следующему варианту (action2:).
	action2: { ...}
	action3: { ...}
 	// В action2 - action3 нет переходов к следующей метке.
}

Отметим, что принятая по умолчанию метка оператора switch применяется независимо от того, было ли найдено соответствие. Принятая по умолчанию метка не означает отсутствия (table miss) и выполняется default_action.

11. Анализ пакета

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

11.1. Состояния анализатора

Анализатор P4 описывает машину состояний с одним стартовым и двумя финальными состояниями. Стартовое состояние называется start, финальные — accept (успешный анализ) и reject (отказ при анализе). Состояние start является частью анализатора, а состояния accept и reject не задаются пользователем и логически не являются частями анализатора. На рисунке 8 представлена общая структура машины состояний синтаксического анализатора.

Рисунок 8. Структура FSM анализатора.

11.2. Объявления анализаторов

Объявление анализатора состоит из имени, списка параметров, необязательного списка параметров конструктора, локальных элементов и состояний анализатора (а также необязательных аннотаций).

parserTypeDeclaration
	: optAnnotations PARSER name optTypeParameters
	'(' parameterList ')'
	;
parserDeclaration
	: parserTypeDeclaration optConstructorParameters
	'{' parserLocalElements parserStates '}'
	;
parserLocalElements
	: /* Пусто */
	| parserLocalElements parserLocalElement
	;
parserStates
	: parserState
	| parserStates parserState
	;

Описание параметров конструктора optConstructorParameters, которые полезны для создания параметризуемых анализаторов, приведено в разделе 13.

В отличие от объявлений типа parser объявления анализаторов не могут быть базовыми (generic), т. е. приведенное ниже определение является недопустимым.

parser P<H>(inout H data) { ... }

Поэтому используемому в контексте parserDeclaration правилу parserTypeDeclaration не следует приводить параметры типа.

В анализаторе должно присутствовать по крайней мере одно состояние — start. Анализатор не может определять два состояния с одним именем. Недопустимо также явное определение состояний accept и reject, поскольку эти состояния логически отделены от состояний анализатора, определяемых программистом.

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

parserLocalElement
	: constantDeclaration
	| variableDeclaration
	| instantiation
	;

Пример полного объявления анализатора представлен в параграфе 5.3.

11.3. Абстрактная машина анализа

Семантику анализатора P4 можно описать в терминах абстрактной машины, которая манипулирует структурой данных ParserModel. В этом параграфе абстрактная машина описана с использованием псевдокода.

Анализатор начинает работу в состоянии start и завершает процесс при достижении состояния reject или accept.

ParserModel {
	error	parseError;
	onPacketArrival(packet p) {
		ParserModel.parseError = error.NoError;
		goto start;
	}
}

Архитектура должна задавать поведение при переходе анализатора в состояние accept и reject. Например, архитектура может задать для всех пакетов, достигших состояния reject, отбрасывание без дальнейшей обработки. Другим вариантом может служить передача таких пакетов в блок, следующий за анализатором, вместе с внутренними метаданными, показывающими, что анализатор достиг состояния reject и информацией об ошибке.

11.4. Состояния анализатора

Состояние анализатора объявляется с использованием приведенного ниже синтаксиса.

parserState
	: optAnnotations STATE name
	'{' parserStatements transitionStatement '}'
	;

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

  • объявления локальных переменных;

  • операторы присваивания;

  • вызовы методов:

    • вызовы функций (например, использование verify для проверки пригодности проанализированных данных);

    • вызовы методов (например, извлечение данных или расчет контрольных сумм) и других анализаторов (см. параграф 11.10);

  • переходы в другие состояния (см. параграф 11.5).

Грамматические правила для операторов parser приведены ниже.

parserStatements
	: /* Пусто */
	| parserStatements parserStatement
	;
parserStatement
	: assignmentOrMethodCallStatement
	| variableDeclaration
	| constantDeclaration
	| parserBlockStatement
	;
parserBlockStatement
	: optAnnotations '{' parserStatements '}'
	;

Архитектуры могут вносить ограничения на выражения и операторы, которые могут применяться в анализаторах (например, они могут запрещать использование операций типа умножения или ограничивать число используемых локальных переменных).

В терминах ParserModel набор операторов в состоянии выполняется последовательно.

11.5. Операторы переходов

Последним в состоянии анализатора является необязательный оператор transition, который передает управления другому состоянию (возможно accept или reject). Синтаксис оператора transition показан ниже.

transitionStatement
	: /* Пусто */
	| TRANSITION stateExpression
	;
stateExpression
	: name ';'
	| selectExpression
	;

Выполнение оператора перехода вызывает оценку выражения stateExpression и передачу управления результирующему состоянию.

В терминах ParserModel семантику оператора transition можно выразить, как

	goto eval(stateExpression)

Например, оператор

	transition accept;

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

Если тело блока состояния не заканчивается оператором transition, предполагается оператор

	transition reject;

11.6. Выражения для выбора

Результатом выражения select является состояние. Синтаксис выражения select показан ниже.

selectExpression
	: SELECT '(' expressionList ')' '{' selectCaseList '}'
	;
selectCaseList
	: /* Пусто */
	| selectCaseList selectCase
	;
selectCase
	: keysetExpression ':' name ';'
	;

Если expressionList в выражении select имеет тип tuple<T>, каждое выражение keysetExpression должно иметь тип set<tuple<T>>.

В терминах ParserModel смысл выражения select

select(e) {
	ks[0]: s[0];
	ks[1]: s[1];
	...
	ks[n-2]: s[n-1];
	_ : sd;	// ks[n-1] используется по умолчанию
}

определяется псевдокодом

key = eval(e);
for (int i=0; i < n; i++) {
	keyset = eval(ks[i]);
	if (keyset.contains(key)) return s[i];
}
verify(false, error.NoMatch);

Некоторые платформы могут требовать, чтобы все выражения keyset внутри оператора select были известны в момент компиляции. Выражения оцениваются по порядку сверху вниз, как показано в приведенном выше псевдокоде. Первый ключ, который содержит значение, соответствующее аргументу select, определяет результирующее состояние. Если совпадений не найдено, выполнение в процессе работы завершается генерацией ошибки со стандартным кодом error.NoMatch.

Отметим, что это предполагает недоступность всех вариантов, расположенных после метки default или _ и компилятору следует выдавать предупреждение в случае обнаружения недоступных меток. Это является важным отличием между выражениями select и операторами switch, используемыми во многих языках программирования, поскольку keyset в выражении select могут «перекрываться».

Типичным примером использования выражения select является сравнение значения недавно извлеченного поля заголовка с набором постоянных значений, как показано ниже.

header IPv4_h { ... bit<8> protocol; ... }
struct P { ... IPv4_h ipv4; ... }
P headers;
select (headers.ipv4.protocol) {
	8w6	: parse_tcp;
	8w17 	: parse_udp;
	_	: accept;
}

Например, для обнаружения зарезервированных портов TCP (номер < 1024) можно задать выражение

select (p.tcp.port) {
	16w0 &&& 16w0xFC00: well_known_port;
	_: other_port;
}

Выражение 16w0 &&& 16w0xFC00 описывает набор 16-битовых значений, в которых шесть старших битов имеют значение 0.

11.7. Оператор проверки

Оператор verify обеспечивает простую форму обработки ошибок и может вызываться только внутри parser. Синтаксически оператор используется как показанная ниже внешняя функция.

extern void verify(in bool condition, in error err);

Если первый аргумент имеет значение true, выполнение оператора происходит без побочных эффектов. Однако в случае значения первого аргумента false оператор вызывает незамедлительный переход в состояние reject с прерыванием процесса анализа, а для parserError этого анализатора устанавливается значение второго аргумента.

В терминах ParserModel семантика оператора может быть представлена в виде

ParserModel.verify(bool condition, error err) {
	if (condition == false) {
		ParserModel.parserError = err;
		goto reject;
	}
}

11.8. Извлечение данных

Библиотека ядра P4 содержит приведенное ниже объявление встроенного внешнего (extern) типа packet_in, который представляет входящие сетевые пакеты. Тип packet_in является специальным и пользователь не может явно создавать экземпляры этого типа. Вместо этого архитектура предоставляет отдельный экземпляр для каждого аргумента packet_in при создании экземпляра анализатора.

extern packet_in {
	void extract<T>(out T headerLvalue);
	void extract<T>(out T variableSizeHeader, in bit<32> varFieldSizeBits);
	T lookahead<T>();
	bit<32> length();	// Этот метод может быть не доступен в некоторых архитектурах.
	void advance(bit<32> bits);
}

Для извлечения данных из пакета, представленного аргументом b типа packet_in, анализатор вызывает методы извлечения данных b. Есть два варианта методов извлечения — вариант с одним аргументом для работы с заголовками фиксированного размера и вариант с двумя аргументами для заголовков переменного размера. Поскольку эти операции могут приводить к отказам при проверках во время работы (см. ниже), эти методы могут вызываться только внутри анализаторов.

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

Некоторые платформы могут обрабатывать пакеты «на лету» (cut-through), т. е. обработка начинается еще до того, как станет известен размер пакета. На таких платформах вызов метода packet_in.length() не может быть реализован и попытки таких вызовов следует помечать как ошибки (во время компиляции или при попытке загрузки скомпилированной программы P4 в целевую платформу, которая не поддерживает данный метод).

В терминах ParserModel семантику packet_in можно представить с использованием показанной ниже модели абстрактного пакета.

packet_in {
	unsigned nextBitIndex;
	byte[] data;
	unsigned lengthInBits;
	void initialize(byte[] data) {
		this.data = data;
		this.nextBitIndex = 0;
		this.lengthInBits = data.sizeInBytes * 8;
	}
	bit<32> length() { return this.lengthInBits / 8; }
}

11.8.1. Извлечение полей фиксированного размера

Метод извлечения с одним аргументом используется для заголовков фиксированного размерами и объявляется в P4, как показано ниже.

void extract<T>(out T headerLeftValue);

Выражение headerLeftValue должно оцениваться в l-значение (см. параграф 6.6) типа header с фиксированным размером. При успешном выполнении этого метода headerLvalue заполняется данными из пакета него устанавливается validity = true. Метод может давать отказы по разным причинам (например, при нехватке в пакете битов для заполнения соответствующего заголовка).

Например, приведенный ниже фрагмент кода извлекает заголовок Ethernet.

struct Result { ... Ethernet_h ethernet; ... }
parser P(packet_in b, out Result r) {
	state start {
		b.extract(r.ethernet);
	}
}

В терминах ParserModel семантика извлечения с одним аргументом задается приведенным ниже псевдокодом с использованием данных из класса пакета, определенного выше. Специальный идентификатор valid$ служит для указания скрытого бита пригодности в заголовке, isNext$ для указания того, что l-значение получено с использованием next, а nextIndex$ для указания соответствующих свойств стека заголовков.

void packet_in.extract<T>(out T headerLValue) {
	bitsToExtract = sizeofInBits(headerLValue);
	lastBitNeeded = this.nextBitIndex + bitsToExtract;
	ParserModel.verify(this.lengthInBits >= lastBitNeeded, error.PacketTooShort);
	headerLValue = this.data.extractBits(this.nextBitIndex, bitsToExtract);
	headerLValue.valid$ = true;
	if headerLValue.isNext$ {
		verify(headerLValue.nextIndex$ < headerLValue.size, error.StackOutOfBounds);
		headerLValue.nextIndex$ = headerLValue.nextIndex$ + 1;
	}
	this.nextBitIndex += bitsToExtract;
}

11.8.2. Извлечение полей переменного размера

Двухаргументное извлечение предназначено для заголовков переменного размера и декларируется в P4 как показано ниже.

void extract<T>(out T headerLvalue, in bit<32> variableFieldSize);

Выражение headerLvalue должно быть l-значением, представляющим заголовок с одним полем varbit. Выражение variableFieldSize должно оцениваться в значение bit<32>, которое указывает число битов, извлекаемых в уникальное поле varbit данного заголовка (это значение указывает размер поля varbit, а не всего заголовка).

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

void packet_in.extract<T>(out T headerLvalue, in bit<32> variableFieldSize) {
	bitsToExtract = sizeOfFixedPart(headerLvalue) + variableFieldSize;
	lastBitNeeded = this.nextBitIndex + bitsToExtract;
	ParserModel.verify(this.lengthInBits >= lastBitNeeded, error.PacketTooShort);
	ParserModel.verify(bitsToExtract <= headerLvalue.maxSize, error.HeaderTooShort);
	headerLvalue = this.data.extractBits(this.nextBitIndex, bitsToExtract);
	headerLvalue.varbitField.size = variableFieldSize;
	headerLvalue.valid$ = true;
	if headerLValue.isNext$ {
		verify(headerLValue.nextIndex$ < headerLValue.size, error.StackOutOfBounds);
		headerLValue.nextIndex$ = headerLValue.nextIndex$ + 1;
	}
	this.nextBitIndex += bitsToExtract;
}

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

// Заголовок IPv4 без опций
header IPv4_no_options_h {
	bit<4>		version;
	bit<4>		ihl;
	bit<8>		diffserv;
	bit<16>	totalLen;
	bit<16>	identification;
	bit<3>		flags;
	bit<13>	fragOffset;
	bit<8>		ttl;
	bit<8>		protocol;
	bit<16>	hdrChecksum;
	bit<32>	srcAddr;
	bit<32>	dstAddr;
}
header IPv4_options_h { varbit<320> options; }
struct Parsed_headers {
	...
	IPv4_no_options_h 	ipv4;
	IPv4_options_h	ipv4options;
}
error { InvalidIPv4Header }
parser Top(packet_in b, out Parsed_headers headers) {
	...
	state parse_ipv4 {
		b.extract(headers.ipv4);
		verify(headers.ipv4.ihl >= 5, error.InvalidIPv4Header);
		transition select (headers.ipv4.ihl) {
			5: dispatch_on_protocol;
			_: parse_ipv4_options;
		}
	}
	state parse_ipv4_options {
		// Используется информация из заголовка ipv4 для определения
		// числа извлекаемых битов.
		b.extract(headers.ipv4options,
				(bit<32>)(((bit<16>)headers.ipv4.ihl - 5) * 32));
		transition dispatch_on_protocol;
	}
}

11.8.3. Взгляд вперед

Метод lookahead, обеспечиваемый абстракцией пакета packet_in, оценивает набор битов без перемещения указателя nextBitIndex. Подобно извлечению, этот метод будет приводить к переходу в состояние reject и возврату ошибки, если в пакете нет достаточного числа битов. Вызов метода lookahead показан ниже.

	b.lookahead<T>()

T должен быть типом с фиксированным размером. При успешном выполнении результат lookahead передается в значении типа T.

В терминах ParserModel семантика lookahead представляется приведенным ниже псевдокодом.

T packet_in.lookahead<T>() {
	bitsToExtract = sizeof(T);
	lastBitNeeded = this.nextBitIndex + bitsToExtract;
	ParserModel.verify(this.lengthInBits >= lastBitNeeded, error.PacketTooShort);
	T tmp = this.data.extractBits(this.nextBitIndex, bitsToExtract);
	return tmp;
}

Пример с опциями TCP из параграфа 8.16 также иллюстрирует использование метода lookahead.

state start {
	transition select(b.lookahead<bit<8>>()) {
		0: parse_tcp_option_end;
		1: parse_tcp_option_nop;
		2: parse_tcp_option_ss;
		3: parse_tcp_option_s;
		5: parse_tcp_option_sack;
	}
}
...
state parse_tcp_option_sack {
	bit<32> n = (bit<32>)b.lookahead<Tcp_option_sack_top>().length;
	b.extract(vec.next.sack, n);
	transition start;
}

11.8.4. Пропуск битов

P4 обеспечивает два способа пропуска некоторого числа битов входящего пакета без их передачи в заголовок.

Первым способом является передача в переменную _ с явно заданным типом данных.

	b.extract<T>(_)

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

void packet_in.advance(bit<32> bits) {
	lastBitNeeded = this.nextBitIndex + bits;
	ParserModel.verify(this.lengthInBits >= lastBitNeeded, error.PacketTooShort);
	this.nextBitIndex += bits;
}

11.9. Стеки заголовков

Стек заголовков имеет два свойства — next и last, которые можно использовать при анализе. Рассмотрим приведенное ниже определение стека для представления заголовков пакета, содержащего до 10 заголовков MPLS.

header Mpls_h {
	bit<20> 	label;
	bit<3>		tc;
	bit		bos;
	bit<8>		ttl;
}
Mpls_h[10] mpls;

Выражение mpls.next представляет l-значение типа Mpls_h, которое представляет один элемент стека MPLS. Изначально mpls.next указывает на первый элемент стека и автоматически перемещается на следующий элемент при каждом успешном вызове для извлечения данных. Свойство mpls.last указывает на элемент, непосредственно предшествующий элементу next, если тот существует. Попытка доступа к элементу mpls.next, когда значение счетчика nextIndex в стеке не меньше размера этого стека, вызывает переход в состояние reject и установке ошибки error.StackOutOfBounds. Аналогично, попытка доступа к mpls.last при nextIndex = 0 вызывает переход в состояние reject и установку ошибки error.StackOutOfBounds.

Ниже приведен пример упрощенного анализатора для разбора MPLS.

struct Pkthdr {
	Ethernet_h ethernet;
	Mpls_h[3] mpls;
	// Другие заголовки опущены
}
parser P(packet_in b, out Pkthdr p) {
	state start {
		b.extract(p.ethernet);
		transition select(p.ethernet.etherType) {
			0x8847: parse_mpls;
			0x0800: parse_ipv4;
		}
	}
	state parse_mpls {
		b.extract(p.mpls.next);
		transition select(p.mpls.last.bos) {
			0: parse_mpls; // Это создает цикл
			1: parse_ipv4;
		}
	}
	// Остальные состояния опущены
}

11.10. Субанализаторы

P4 позволяет анализаторам пользоваться услугами других анализаторов подобно вызову подпрограмм. Для обращения к другому анализатору сначала требуется создать его экземпляр, а затем обращаться к нему с помощью метода apply.

Ниже приведен пример вызова субанализатора.

parser callee(packet_in packet, out IPv4 ipv4) { ...}
parser caller(packet_in packet, out Headers h) {
	callee() subparser;	// Экземпляр вызываемого анализатора
	state subroutine {
		subparser.apply(packet, h.ipv4);	// Вызов субанализатора
	}
}

Семантика вызова субанализатора показана ниже.

  • Состояние вызывающего анализатора делится на два полусостояния в операторе вызова анализатора.

  • Верхнее полусостояние включает переход в состояние start субанализатора.

  • Состояние accept субанализатора отождествляется с нижней половиной текущего состояния.

  • Состояние reject субанализатора отождествляется с состоянием reject текущего анализатора.

Диаграмма этого процесса представлена на рисунке 9.

Поскольку P4 требует объявления до использования, создание рекурсивных (или взаимно рекурсивных) анализаторов невозможно.

Рисунок 9. Семантика вызова субанализатора — наверху исходная программа, внизу — эквивалент.

Архитектуры могут вносить (статические или динамические) ограничения на число состояний, через которые анализатор может проходить при обработке каждого пакета. Например, компилятор для конкретной платформы может отвергать анализаторы, содержащие петли, которые не могут быть развернуты в момент компиляции или содержат циклы, не перемещающие указатель. Если анализатор прерывает выполнение динамически по причине завершения отведенного на разбор времени, анализатору следует перейти в состояние reject и установить стандартную ошибку error.ParserTimeout.

12. Блоки управления

Анализаторы P4 отвечают за извлечение битов из пакетов в заголовки. Этими заголовками (и другими метаданными) можно манипулировать в блоках управления. Тело блока управления похоже на традиционную императивную программу. Внутри тела могут вызываться элементы «сопоставление-действие» (СД) для выполнения требуемых преобразований. Элементы СД представляются в P4 конструкциями, которые называют таблицами.

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

controlDeclaration
	: controlTypeDeclaration optConstructorParameters
	/* controlTypeDeclaration не может содержать параметры типа */
	'{' controlLocalDeclarations APPLY controlBody '}'
	;
controlLocalDeclarations
	: /* Пусто */
	| controlLocalDeclarations controlLocalDeclaration
	;
controlLocalDeclaration
	: constantDeclaration
	| variableDeclaration
	| actionDeclaration
	| tableDeclaration
	| instantiation
	;
controlBody
	: blockStatement
	;

Внутри блока управления можно создать экземпляр анализатора. Описание параметров optConstructorParameters, которые могут использоваться для построения параметризованного блока управления, дано в разделе 13.

В отличие от объявления типа элемента управления объявление элемента управления не может быть базовым (generic). Поэтому приведенное ниже объявление будет некорректным.

control C<H>(inout H data) { ... }

P4 не поддерживает исключительных потоков управления внутри блока управления. Единственным оператором, который оказывает нелокальное воздействие на поток управления, является оператор exit, вызывающий незамедлительное прерывания выполнения включающего его блока управления. Т. е. здесь нет эквивалента оператора verify или состояния reject от анализаторов. Поэтому вся обработка ошибок должны явно выполняться программистом.

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

12.1. Действия

Действие (action) представляет собой фрагмент кода, который может считывать и записывать обрабатываемые данные. Действие может включать элементы данных, которые будут записываться уровнем управления и считываться уровнем данных. Действия являются основным средством динамического влияния уровня управления на поведение уровня данных. Абстрактная модель действия представлена на рисунке 10.

actionDeclaration
	: optAnnotations ACTION name '(' parameterList ')' blockStatement
	;

Синтаксически действие представляет собой функцию, которая не возвращает значения. Действия могут объявляться внутри блока управления и в этом случае такие действия могут применяться только внутри экземпляров этого блока.

Рисунок 10. Действия содержат код и данные. Код является программой P4, а данные устанавливаются уровнем управления. Привязка параметров выполняется уровнем данных.

Ниже приведен пример объявления действия.

action Forward_a(out bit<9> outputPort, bit<9> port) {
	outputPort = port;
}

Параметры действия могут иметь тип extern. Параметры без направления (например, port в предыдущем примере) указывают «данные действия». Все такие параметры должны указываться в конце списка параметров. При использовании в таблице СД (см. параграф 12.2.1.2) эти параметры будут предоставляться уровнем управления.

Тело действия состоит из последовательности операторов и объявлений. Операторы switch не разрешены внутри действий — грамматика разрешает их, но семантическая проверка должна отвергать. Некоторые платформы могут вносить дополнительные ограничения для тела действий (например, разрешать только линейный код без условных операторов и выражений).

12.1.1. Вызовы операций

Действия могут выполняться двумя способами, описанными ниже.

  • Неявно в процессе обработки таблиц СД.

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

12.2. Таблицы

Таблица описывает элемент СД, структура которого показана на рисунке 11. Обработка пакета с использованием таблицы СД включает следующие этапы:

  • создание ключа;

  • поиск ключа в таблице (сопоставление), результат которого определяет действие;

  • выполнение действия (действие) над входными данными, приводящее к их изменениям.

Объявление таблицы создает один экземпляр таблицы. Для получения множества экземпляров они должны быть объявлены внутри блока управления, который сам создается во множестве экземпляров.

Таблица поиска (look-up table) представляет собой конечное отображение, содержимым которого асинхронно манипулирует (чтение-запись) уровень управления целевой платформы через отдельный интерфейс API уровня управления (см. рисунок 11). Следует подчеркнуть, что термин «таблица» обозначает табличные объекты в программах P4, а также внутренние таблицы поиска в целевых платформах. Для четкого разделения этих случаев при необходимости будет использоваться термин «элемент СД».

Рисунок 11. Поток данных блока СД.

Синтаксически таблица определяется в терминах набора свойств «ключ-значение». Некоторые из этих свойств являются «стандартными», но набор в целом может быть расширен специфическими для целевой платформы компиляторами.

tableDeclaration
	: optAnnotations TABLE name '{' tablePropertyList '}'
	;
tablePropertyList
	: tableProperty
	| tablePropertyList tableProperty
	;
tableProperty
	: KEY '=' '{' keyElementList '}'
	| ACTIONS '=' '{' actionList '}'
	| CONST ENTRIES '=' '{' entriesList '}' /* Неизменные записи */
	| optAnnotations CONST IDENTIFIER '=' initializer ';'
	| optAnnotations IDENTIFIER '=' initializer ';'
	;

Стандартные свойства таблицы включают:

  • ключ (key) — выражение, определяющее как вычисляется ключ для поиска в таблице;

  • действия (actions) — список действий, которые могут быть найдены в таблице;

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

Компилятор может устанавливать default_action = NoAction (а также помещать его в список действий) для таблиц, в которых не определено свойство default_action. Это согласуется с семантикой, приведенной в параграфе 12.2.1.3. В данном документе предполагается применение такого преобразования, поэтому все таблицы имеют свойство default_action.

Дополнительно таблица может включать определяемые архитектурой свойства (см. параграф 12.2.1.5). Свойства, помеченные как постоянные (const) не могут динамически изменяться уровнем управления. Свойства key и actions постоянные всегда, поэтому ключевое слово const для них не используется.

12.2.1. Свойства таблиц

12.2.1.1. Ключи

Ключ (key) является свойством таблицы, которое задает значения уровня данных, которые следует использовать при поиске записи в таблице. Ключ представляет собой список пар вида (e : m), где выражение e описывает данные для сопоставления с таблицей, а константа m указывает тип сопоставления match_kind, определяющий алгоритм поиска в таблице (см. параграф 7.1.3).

keyElementList
	: /* Пусто */
	| keyElementList keyElement
	;
keyElement
	: expression ':' name optAnnotations ';'
	;

В качестве примера рассмотрим фрагмент программы

table Fwd {
	key = {
		ipv4header.dstAddress 	: ternary;
		ipv4header.version		: exact;
	}
	...
}

Здесь ключ состоит из двух полей заголовка ipv4header — dstAddress и version. Константа match_kind служит 3 целям:

  • задает алгоритм, используемый для сопоставления значений уровня данных с записями таблицы;

  • используется в API уровня управления для заполнения таблицы во время работы;

  • используется компилятором при выделении ресурсов для таблицы.

Библиотека ядра P4 содержит три предопределенных идентификатора match_kind.

match_kind {
	exact,
	ternary,
	lpm
}

Эти идентификаторы соответствуют одноименным типам сопоставления в P414. Семантика этих аннотаций не требуется для описания поведения абстрактной машины P4, а способ их использования влияет лишь на API уровня управления и реализацию таблицы поиска. С точки зрения программы P4 таблица просмотра является абстрактным конечным отображением, которое позволяет по данному ключу определить действие или «пропуск» (miss), как описано в параграфе 12.2.3.

Если таблица не имеет свойства key, она будет не таблицей поиска, а просто принятым по умолчанию действием (т. е., связанная таблица поиска будет просто пустым отображением).

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

12.2.1.2. Действия

Таблица должна объявлять все возможные действия, которые могут появляться в связанной таблице просмотра или принятом по умолчанию действии. Это выполняется с помощью свойства actions, значением которого всегда является список actionList.

actionList
	: actionRef ';'
	| actionList actionRef ';'
	;
actionRef
	: optAnnotations name
	| optAnnotations name '(' argumentList ')'
	;

Для иллюстрации вернемся к программе VSS из параграфа 5.3:

action Drop_action() {
	outCtrl.outputPort = DROP_PORT;
}
action Rewrite_smac(EthernetAddress sourceMac) {
	headers.ethernet.srcAddr = sourceMac;
}
table smac {
	key = { outCtrl.outputPort : exact; }
	actions = {
		Drop_action;
		Rewrite_smac;
	}
}
  • Записи в таблице smac могут содержать два разных действия — Drop_action и Rewrite_mac.

  • Действие Rewrite_smac имеет один параметр sourceMac, который задается уровнем управления.

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

action a() {}
control c() {
	action a() {}
	// Недопустимая таблица - два действия имеют одинаковые имена
	table t { actions = { a; .a; } }
}

Каждый параметр действия, имеющий направление (in, inout, out) должен быть привязана в спецификации списка действий и наоборот, параметры без направления не могут иметь привязки. Выражения, представленные в качестве аргументов действия, не оцениваются до вызова этого действия.

action a(in bit<32> x) { ...}
bit<32> z;
action b(inout bit<32> x, bit<8> data) { ...}
table t {
	actions = {
		// a; - недопустимо, параметр x должен быть привязан
		a(5);	// Привязка в a параметра x к значению 5
		b(z);	// Привязка в b параметра x к значению z
		// b(z, 3); - недопустимая привязка параметр данных без направления
		// b(); - недопустимо, параметр x должен быть привязан
	}
}
12.2.1.3. Действие по умолчанию

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

При наличии свойства default_action оно должно указываться после свойства action и может быть объявлено как постоянное (const), которое уровень управления не может динамически изменять. Используемое по умолчанию действие должно быть одним из включенных в список действий. В частности, выражения, передаваемые в качестве параметров in, out или inout, должны быть синтаксически идентичны выражениям, используемым в одном из элементов списка действий.

Например, для приведенной выше таблицы можно установить по умолчанию приведенное ниже действие (помеченное как постоянное).

	const default_action = Rewrite_smac(48w0xAA_BB_CC_DD_EE_FF);

Отметим, что выбранное для использования по умолчанию действие должно предоставлять аргументы для привязки параметров уровня управления (т. е. параметров без направления), поскольку действие синтезируется в момент компиляции. Выражения, представленные в качестве аргументов для параметров с направлением (in, inout, out) оцениваются при вызове действия, тогда как оценка выражений, представленных в качестве аргументов для параметров без направления, выполняется при компиляции.

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

default_action = a(5); // OK - нет параметров уровня управления
// default_action = a(z); - недопустимо, в a параметр x уже привязан к значению 5
default_action = b(z,8w8); // OK - привязка параметра данных в b к значению 8w8
// default_action = b(z); - недопустимо, в b параметр данных не привязан
// default_action = b(x, 3); - недопустимо, в b параметр x привязан к x вместо z

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

12.2.1.4. Записи таблицы

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

Синтаксис определения записей таблицы показан ниже.

tableProperty
	: const ENTRIES '=' '{' entriesLlist '}' /* Неизменные записи */
entriesList
	: entry
	| entryList entry
entry
	: keysetExpression ':' actionRef optAnnotations ';'

Записи таблицы являются неизменными (const), т. е. уровень управления может лишь считывать их, не имея возможности менять или удалять. Это позволяет сохранить неизменными записи таблицы, заданные в исходном коде P4. Это решение оказывает существенное влияние на работу программ P4, поскольку им не требуется отслеживать разные типы (изменяемые или неизменные) записей в таблице. В будущих версиях P4 может появиться возможность включения в одну таблицу изменяемых и неизменных записей путем объявления дополнительных свойств записей без ключевого слова const.

Компонента keysetExpression в записи таблицы представляет собой кортеж (tuple), который должен обеспечивать поле для каждого ключа таблицы (см. параграф 12.2.1). Тип ключа должен соответствовать типу элемента в наборе. Элемент ActionRef должен быть действием, которое присутствует в списке действий таблицы, с привязкой всех аргументов.

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

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

Для иллюстрации рассмотрим приведенный ниже пример.

header hdr {
	bit<8>		e;
	bit<16> 	t;
	bit<8>		l;
	bit<8>		r;
	bit<1>		v;
}
struct Header_t {
	hdr h;
}
struct Meta_t {}
control ingress(inout Header_t h, inout Meta_t m,
			inout standard_metadata_t standard_meta) {
	action a() { standard_meta.egress_spec = 0; }
	action a_with_control_params(bit<9> x) { standard_meta.egress_spec = x; }
	table t_exact_ternary {
		key = {
			h.h.e : exact;
			h.h.t : ternary;
		}
		actions = {
			a;
			a_with_control_params;
		}
		default_action = a;
		const entries = {
			(0x01, 0x1111 &&& 0xF) 	: a_with_control_params(1);
			(0x02, 0x1181) 		: a_with_control_params(2);
			(0x03, 0x1111 &&& 0xF000) 	: a_with_control_params(3);
			(0x04, 0x1211 &&& 0x02F0) 	: a_with_control_params(4);
			(0x04, 0x1311 &&& 0x02F0) 	: a_with_control_params(5);
			(0x06, _) 			: a_with_control_params(6);
		}
	}
}

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

12.2.1.5. Дополнительные свойства

Объявление таблицы определяет важные интерфейсы уровней управления и данных — ключи и действия. Однако лучший способ реализации таблицы на деле может зависеть от природы записей, которые будут установлены во время работы (например, таблицы могут быть плотно- или малозаселенными, реализованными как хэш-таблицы, ассоциативная память, дерево и т. п.). Кроме того, некоторые архитектуры могут поддерживать дополнительные свойства таблиц, семантика которых выходит за рамки этой спецификации. Например, архитектуры со статическим распределением ресурсов могут требовать от программиста заранее определять размер таблиц, который будет использоваться при компиляции для выделения требуемых ресурсов хранения. Однако такие зависимые от архитектуры свойства не могут менять семантику поиска в таблицах, который всегда завершается обнаружением (hit) и действием или отсутствием (miss), и могут лишь менять способы интерпретации этих результатов в состояние уровня данных. Такое ограничение нужно для того, чтобы можно было понимать поведение таблиц во время компиляции.

Другой пример свойства реализации может использоваться для передачи дополнительной информации компилятору back-end. Значением этого свойства может быть экземпляр внешнего блока, выбранный из подходящей библиотеки компонент. Например, базовая функциональность конструкций P414 может быть реализована для архитектуры, поддерживающей эту возможность, с помощью конструкции, подобной приведенной ниже.

extern ActionProfile {
	ActionProfile(bit<32> size); // Число ожидаемых различных действий
}
table t {
	key = { ...}
	size = 1024;
	implementation = ActionProfile(32);	// Вызов конструктора
}

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

12.2.2. Вызов элемента СД

К таблице можно обратиться путем вызова метода apply. Вызов этого метода для экземпляра table возвращает значение типа struct с двумя полями. Эта структура синтезируется компилятором автоматически. Для каждой таблицы T компилятор создает enum и struct, показанные ниже псевдокодом.

enum action_list(T) {
	// Одно поле для каждого действия из списка операций таблицы T
}
struct apply_result(T) {
	bool hit;
	action_list(T) action_run;
}

Выполнение метода apply устанавливает в поле hit значение true, если при поиске в таблице было найдено соответствие. Этот флаг может использоваться для ведения потока управления в вызвавшем таблицу блоке управления.

if (ipv4_match.apply().hit) {
	// Совпадение
} else {
	// Отсутствие совпадений
}

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

switch (dmac.apply().action_run) {
	Drop_action: { return; }
}

12.2.3. Семантика выполнения блока «сопоставление-действие»

Семантика оператора вызова таблицы приведена ниже.

m.apply();

Это можно представить псевдокодом (см. также рисунок 11).

apply_result(m) m.apply() {
	apply_result(m) result;
}
var lookupKey = m.buildKey(m.key); 	// Использование блока ключей
action RA = m.table.lookup(lookupKey);
if (RA == null) {				// Нет совпадений в таблице
	result.hit = false;
	RA = m.default_action;		// Использование принятого по умолчанию действия
} else {
	result.hit = true;
}
result.action_run = action_type(RA);
evaluate_and_copy_in_RA_args(RA);
execute(RA);
copy_out_RA_args(RA);
return result;

12.3. Абстрактная машина конвейера «сопоставление-действие»

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

  • Во время работы операторы внутри блока выполняются в порядке их размещения в блоке управления.

  • Выполнение оператора return ведет к незамедлительному прерыванию исполнения текущего блока управления и возврату в точку вызова.

  • Выполнение оператора exit ведет к незамедлительному прерыванию исполнения текущего блока управления и всех включающих его блоков управления, которые участвовали в вызове.

  • Выполнение таблицы ведет к исполнению соответствующего блока СД, как описано выше.

12.4. Вызовы элементов управления

P4 позволяет элементам управления обращаться к услугам других элементов управления, подобно вызову подпрограмм. Для обращения к другому блоку управления нужно сначала создать его экземпляр, а затем услуги этого элемента вызываются с помощью его метода apply.

Ниже приведен пример вызова элемента управления.

control Callee(inout IPv4 ipv4) { ...}
control Caller(inout Headers h) {
	Callee() instance;			// Экземпляр вызываемого
	apply {
		instance.apply(h.ipv4);	// Вызов элемента управления
	}
}

13. Параметризация

Для поддержки библиотек полезных компонент P4 анализаторы и блоки управления можно дополнительно параметризовать с помощью параметров конструктора.

Рассмотрим еще раз синтаксис объявления анализатора.

parserDeclaration
	: parserTypeDeclaration optConstructorParameters
	'{' parserLocalElements parserStates '}'
	;
optConstructorParameters
	: /* Пусто */
	| '(' parameterList ')'
	;

Из приведенного фрагмента видно, что объявление анализатора может включать два набора параметров:

  • рабочие параметры (parameterList);

  • необязательные параметры конструктора (optConstructorParameters).

Параметры конструктора должны указываться без направления (они не могут быть in, out или inout) и при создании экземпляра анализатора должна быть возможность полностью оценить выражения, представленные для этих параметров во время компиляции.

Рассмотрим пример.

parser GenericParser(packet_in b, out Packet_header p)
				(bool udpSupport) {	// Параметры конструктора
	state start {
		b.extract(p.ethernet);
		transition select(p.ethernet.etherType) {
			16w0x0800: ipv4;
		}
	}
	state ipv4 {
		b.extract(p.ipv4);
		transition select(p.ipv4.protocol) {
			6: tcp;
			17: tryudp;
		}
	}
	state tryudp {
		transition select(udpSupport) {
			false: accept;
			true : udp;
		}
	}
	state udp {
		...
	}
}

При создании экземпляра GenericParser требуется представить значение параметра udpSupport, как показано ниже.

// topParser является GenericParser, где udpSupport = false
GenericParser(false) topParser;

13.1. Непосредственный вызов типа

Экземпляры элементов управления и анализаторов зачастую создаются лишь однократно. В целях упрощения объявления анализаторов и элементов управления без параметров конструктора могут применяться непосредственно, как будто это уже экземпляр. Это равносильно созданию и применению локального экземпляра данного типа.

control Callee( ... ) { ... }
control Caller( ... )( ... ) {
	apply {
		Callee.apply( ... ); // Callee считается экземпляром
	}
}

Определение Caller эквивалентно приведенному ниже

control Caller( ... )( ... ) {
	@name("Callee") Callee() Callee_inst; // Локальный экземпляр Callee
	apply {
		Callee_inst.apply( ... );	// Применение Callee_inst
	}
}

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

  • Прямой вызов типа в разных областях действия будет создавать разные локальные экземпляры с различающимися полными именами элементов управления.

  • В одной области действия прямой вызов типа будет приводить к разным локальным экземплярам для каждого вызова, однако экземпляры одного типа будут иметь одно глобальное имя за счет аннотации @name. Если тип содержит контролируемые элементы, непосредственный вызов такого типа более одного раза не допустим, поскольку это будет создавать множество контролируемых элементов с совпадающими полными именами.

Аннотации @name описаны в параграфе 16.3.2.

14. Сборка

Процесс, обратный по отношению к анализу (parsing), называется сборкой (deparsing) или созданием пакета. P4 не включает отдельного языка для сборки пакетов и такая сборка выполняется в блоке управления, имеющем хотя бы один параметр типа packet_out.

Например, приведенный ниже фрагмент кода записывает сначала заголовок Ethernet, а затем заголовок IPv4 в packet_out.

control TopDeparser(inout Parsed_packet p, packet_out b) {
	apply {
		b.emit(p.ethernet);
		b.emit(p.ip);
	}
}

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

14.1. Вставка данных в пакеты

Тип данных packet_out datatype определен в библиотеке ядра P4 и воспроизведен здесь. Он обеспечивает метод добавления данных в конец выходного пакета, называемый emit.

extern packet_out {
	void emit<T>(in T data);
}

Метод emit поддерживает добавление в конец исходящего пакета данных из заголовка, стека заголовков, структуры или объединения заголовков.

  • При использовании метода для заголовка emit добавляет данные из заголовка в конец пакета, если это допустимо. В противном случае не делается ничего (no-op).

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

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

Метод emit корректно вызывать в выражениях базового типа, а также типов enum или error.

Метод emit можно представить приведенным ниже псевдокодом.

packet_out {
	byte[] data;
	unsigned lengthInBits;
	void initializeForWriting() {
		this.data.clear();
		this.lengthInBits = 0;
	}
	/// Добавление данных в конец пакета. Тип T должен быть заголовком, стеком или 
	/// объединением заголовков, структурой, рекурсивно созданной из этих типов.
	void emit<T>(T data) {
		if (isHeader(T))
			if(data.valid$) {
				this.data.append(data);
				this.lengthInBits += data.lengthInBits;
			} 
		else if (isHeaderStack(T))
			for (e : data)
				emit(e);
		else if (isHeaderUnion(T) || isStruct(T))
			for (f : data.fields$)
				emit(e.f)
		// Другие варианты для T недопустимы.
	}
}

Здесь использован специальный идентификатор valid$ для скрытого бита validity в заголовках и fields$ для указания списка полей структуры или объединения заголовков. Использована также стандартная нотация для обозначения итераций по элементам стека (e : data) и спискам полей для стеков и объединений заголовков (f : data.fields$).

15. Описание архитектуры

Описание архитектуры должно предоставляться производителем платформ в форме исходного кода библиотеки P4, содержащего по крайней мере одно объявление для программы (package), экземпляр которой должен быть создан пользователем при создании программы для этой платформы. В качестве примера можно рассмотреть объявление VSS из параграфа 5.1.

Файл описания архитектуры может определять типы данных, константы, реализации вспомогательных пакетов (helper package) и ошибки. Он должен также объявлять типы программируемых блоков анализа и управления, которые будут использоваться платформой. Программируемые блоки можно группировать в пакеты (package), которые могут быть вложенными.

Поскольку некоторые компоненты платформы могут манипулировать пользовательскими типами, которые еще не известны в момент объявления платформы, эти типы описываются с использованием переменных типа, которые должны параметрически использоваться в программе (т. е. переменные типа проверяются подобно Java generic, а не шаблонам C++).

15.1. Пример описания архитектуры

Приведенный ниже пример описывает коммутатор с использованием двух программ (package), каждая из которых содержит анализатор, конвейер СД и сборщик (deparser).

parser Parser<IH>(packet_in b, out IH parsedHeaders);
// Входной конвейер СД
control IPipe<T, IH, OH>(in IH inputHeaders,
				in InControl inCtrl,
				out OH outputHeaders,
				out T toEgress,
				out OutControl outCtrl);
// Выходной конвейер СД
control EPipe<T, IH, OH>(in IH inputHeaders,
				in InControl inCtrl,
				in T fromIngress,
				out OH outputHeaders,
				out OutControl outCtrl);
control Deparser<OH>(in OH outputHeaders, packet_out b);
package Ingress<T, IH, OH>(Parser<IH> p,
				IPipe<_, IH, OH> map,
				Deparser<OH> d);
package Egress<T, IH, OH>(Parser<IH> p, Port
				EPipe<_, IH, OH> map,
				Deparser<OH> d);
package Switch<T>( // Оператор switch верхнего уровня содержит две программы (package).
	// Типы Ingress.IH и Egress.IH могут быть разными.
	Ingress<T, _, _> ingress,
	Egress<T, _, _> egress
);

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

 
Рисунок 12. Фрагмент архитектуры коммутатора, предполагаемый приведенным выше набором объявлений.

Коммутатор содержит две отдельных программы (package) — Ingress и Egress.

  • Модули Parser, Ipipe и Deparser в пакете Ingress соединены в упорядоченную цепочку. Блок Ingress.IPipe получает данные типа Ingress.IH, которые являются выходом блока Ingress.Parser.

  • Аналогично блоки Parser, Epipe и Deparser соединены в цепочку программы Egress.

  • Блок Ingress.IPipe соединен с Egress.EPipe, поскольку первый выдает значения типа T, служащие входными для второго.

  • Отметим, что типы Ingress IH и Egress IH не зависят один от другого. Если мы хотим показать, что они относятся к одному типу, следует вместо объявления IH и OH объявить на уровне коммутатора package Switch<IH, OH, T>.

Отметим, что эта архитектура моделирует коммутатор, который содержит два отдельных канала между входным и выходным конвейером.

  • Канал, напрямую передающий данные через аргумент типа T (на программной платформе с общей памятью входного и выходного контроллера это можно реализовать путем прямой передачи указателя; на платформах без общей памяти компилятору предположительно потребуется автоматически создавать код упорядочения).

  • Канал опосредованной передачи данных с использованием анализатора и сборщика, которые преобразуют данные в пакет и обратно.

15.2. Пример архитектурной программы

Чтобы создать программу для архитектуры, программа P4 должна создать экземпляр верхнего уровня для package путем передачи значений всех аргументов через переменную main в пространстве имен верхнего уровня. Типы аргументов должны соответствовать типам параметров после подобающей подстановки для переменных типа. Подстановка типов может быть выражена явно с использованием специализации типа или выведена компилятором с использованием алгоритма унификации типа Hindley-Milner.

В качестве примера рассмотрим объявления типов

parser Prs<T>(packet_in b, out T result);
control Pipe<T>(in T data);
package Switch<T>(Prs<T> p, Pipe<T> map);

и следующие объявления

parser P(packet_in b, out bit<32> index) { ... }
control Pipe1(in bit<32> data) { ... }
control Pipe2(in bit<8> data) { ... }

Ниже приведено допустимое объявления для платформы верхнего уровня.

Switch(P(), Pipe1()) main;

Следующее объявление является некорректным.

Switch(P(), Pipe2()) main;

Некорректность этого объявления заключается в том, что анализатору P требуется T типа bit<32>, а Pipe2 требует для T тип bit<8>.

Пользователь может также явно указать значения для переменных типа (иначе компьютер будет сам выводить эти значения).

Switch<bit<32>>(P(), Pipe1()) main;

15.3. Модель фильтра пакетов

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

Рисунок 13. Анализатор вычисляет логическое значение для принятия решения об отбрасывании пакета.

Эта модель может использоваться для создания программы фильтрации пакетов в ядре Linux. Например, можно заменить язык tcpdump более мощным языком P4, который способен поддерживать новые протоколы, обеспечивая полную «безопасность типа» (type safety) в процессе обработки пакетов. Для такой платформы компилятор P4 может генерировать программу eBPF5, которая помещается утилитой tcpdump в ядро Linux и выполняется компилятором EBPF во время работы.

В этом случае целевой платформой является ядро Linux, а архитектурной моделью — фильтр пакетов.

Объявления для этой архитектуры будут иметь вид

parser Parser<H>(packet_in packet, out H headers);
control Filter<H>(inout H headers, out bool accept);
package Program<H>(Parser<H> p, Filter<H> f);

16. Абстрактная машина P4 — оценка

Оценка для программы P4 выполняется в два этапа:

  • статическая оценка выполняется во время компиляции путем анализа программы P4 и создания экземпляров всех блоков, имеющих состояния;

  • динамическая оценка — во время работы каждый функциональный блок P4 выполняется целиком (неделимо) в изоляции от других при передаче ему управления от архитектуры.

16.1. Известные при компиляции значения

Ниже перечисляются значения, известные в момент компиляции:

  • целочисленные, логические и строковые литералы;

  • идентификаторы, объявленные в error, enum или match_kind;

  • используемый по умолчанию идентификатор;

  • поле размера значения с типом header_stack;

  • идентификатор _ при использовании в качестве метки в операторе select;

  • идентификаторы, которые представляют объявленные типы, действия, таблицы, анализаторы, элементы управления и программы;

  • списочные выражения, для которых все компоненты известны при компиляции;

  • экземпляры, созданные путем объявления (параграф 9.3) или вызова конструктора;

  • выражения (+, -, *, / , %, cast, !, &, |, &&, ||, << , >> , ~ , >, <, ==, !=, <=, >=, ++, [:]), когда все их операнды известны во время компиляции;

  • идентификаторы, объявленные как константы с помощью ключевого слова const.

16.2. Оценка во время компиляции

Оценка выполняется в порядке объявления, начиная с пространства имен верхнего уровня.

  • Все объявления (например, анализаторы, элементы управления, типы, константы) оценивают себя.

  • Каждая таблица оценивает свои экземпляры.

  • Для вызовов конструкторов оцениваются объекты соответствующего типа, сохраняющие состояние. Для этого все аргументы конструкторов оцениваются рекурсивно и привязываются к параметрам конструктора. Аргументы конструктора должны иметь известные при компиляции значения. Порядок оценки аргументов конструктора не должен иметь значения и при любом порядке результаты должны совпадать.

  • Оценивается создание экземпляров объектов, сохраняющих состояние.

  • При создании экземпляров анализаторов и блоков управления рекурсивно оцениваются все экземпляры в этом блоке, сохраняющие состояние.

  • Результатом оценки программы является значение переменной верхнего уровня main.

Отметим, что экземпляры всех значений, сохраняющих состояние, создаются во время компиляции.

В качестве примера рассмотрим приведенный ниже фрагмент программы.

// Объявление архитектуры
parser P(...);
control C(...);
control D(...);
package Switch(P prs, C ctrl, D dep);
extern Checksum16 { ...}
// Пользовательский код
Checksum16() ck16; // Экземпляр блока контрольных сумм
parser TopParser(...)(Checksum16 unit) { ...}
control Pipe(...) { ...}
control TopDeparser(...)(Checksum16 unit) { ...}
Switch(TopParser(ck16),
	Pipe(),
	TopDeparser(ck16))main;

Оценка этой программы описана ниже.

  1. Оцениваются объявления P, C, D, Switch и Checksum16.

  2. Экземпляр Checksum16() ck16 оценивается и создается объект с именем ck16 и типом Checksum16.

  3. Оцениваются объявления TopParser, Pipe и TopDeparser.

  4. Оценивается экземпляр переменной main:

    1. рекурсивно оцениваются аргументы конструктора;

    2. TopParser(ck16) является вызовом конструктора;

    3. его аргументы оцениваются рекурсивно и дают в результате объект ck16;

    4. конструктор оценивает сам себя и это ведет к созданию экземпляра объекта типа TopParser;

    5. аналогично оцениваются Pipe() и TopDeparser(ck16) как вызовы конструкторов;

    6. все аргументы конструктора программы (package) Switch были оценены (это экземпляры TopParser, Pipe и TopDeparser). Их сигнатуры соответствуют объявлению Switch;

    7. в заключение может быть оценен конструктор Switch и результатом этого будет экземпляр программы Switch (который содержит анализатор TopParser, названный prs в первом параметре Switch, Pipe с именем ctrl и TopDeparser с именем dep).

  5. Результатом оценки программы является значение переменной main, которая является экземпляром Switch.

На рисунке 14 показан результат оценки в графической форме. Таким результатом всегда служит граф экземпляров. Имеется один экземпляр Checksum16 с именем ck16, совместно используемый TopParser и TopDeparser. Возможность совместного использования зависит от архитектуры. Компиляторы для конкретных платформ могут требовать использования разных модулей расчета контрольных сумм для разных блоков.

Рисунок 14. Результат оценки.

16.3. Имена для уровня управления

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

  • таблицы;

  • ключи;

  • действия;

  • экземпляры extern.

Полное имя состоит из локального имени управляемого элемента с префиксом (prepend) в виде полного имени содержащего элемент пространства имен. Поэтому перечисленные ниже программные конструкции, которые включают управляемые элементы, сами должные иметь уникальные полные имена:

  • экземпляры элементов управления (control);

  • экземпляры анализаторов.

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

16.3.1. Создание имен для управления

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

16.3.1.1. Таблицы

Для таблиц синтаксическое имя является локальным именем таблицы. Например, таблица

control c(...)() {
	table t { ... }
}

будет иметь локальное имя t.

16.3.1.2. Ключи

Синтаксически ключи таблицы являются выражениями. Для простых выражений локальное имя может быть создано из самого выражения. В приведенном ниже примере таблица t имеет ключи с именами data.f1 и hdrs[3].f2.

table t {
	keys = { data.f1 : exact; }
	hdrs[3].f2 : exact;
}
actions = { ... }

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

Вид

Пример

Имя

Метод isValid()

h.isValid()
"h.isValid()"

Доступ к массивам

header_stack[1]
"header_stack[1]"

Константы

1
"1"

Проекции полей

data.f1
"data.f1"

Срезы (slice) данных

f1[3:0]
"f1[3:0]"

Остальные типы выражений должны аннотироваться с @name (параграф 17.1.2) как в приведенном ниже примере.

table t {
	keys = { data.f1 + 1 : exact @name("f1_mask"); }
	actions = { ... }
}

Здесь аннотация @name(«f1_mask») назначает для ключа локальное имя «f1_mask».

16.3.1.3. Действия

Для каждой конструкции action синтаксическое имя является локальным именем. Например,

control c(...)() {
	action a(...) { ... }
}

создает действие с локальным именем a.

16.3.1.4. Экземпляры

Локальные имена для экземпляров extern, parser и control выводятся из способа использования экземпляра. Если экземпляр привязан к имени, это имя становится локальным именем для уровня управления. Например, если элемент управления C объявлен как

control C(...)() { ... }

и создан его экземпляр

C() c_inst;

локальным именем экземпляра будет c_inst.

Если же экземпляр создается как аргумент, его локальным именем будет имя формального параметра, к которому привязан аргумент. Например, если extern E и control C объявлены как

extern E { ... }
control C( ... )(E e_in) { ... }

и создан экземпляр

C(E()) c_inst;

локальным именем экземпляра extern будет e_in.

Если создаваемый экземпляр конструкции передается в качестве аргумента программе (package), имя экземпляра выводится из представленного пользователем определения типа, когда это возможно. В приведенном ниже примере локальным именем экземпляра MyC будет c, а локальным именем extern — e2, а не e1.

extern E { ... }
control ArchC(E e1);
package Arch(ArchC c);
control MyC(E e2)() { ... }
Arch(MyC()) main;

Отметим, что в этом примере архитектура будет представлять экземпляр extern, когда она применяет экземпляр MyC, переданный программе Arch. Полным именем этого экземпляра будет main.c.e2.

Далее рассмотрим пример, показывающий создание имени при наличии множества экземпляров.

control Callee() {
	table t { ... }
	apply { t.apply(); }
}
control Caller() {
	Callee() c1;
	Callee() c2;
	apply {
		c1.apply();
		c2.apply();
	}
}
control Simple();
package Top(Simple s);
Top(Caller()) main;


Рисунок 15. Оценка программы, создающей несколько экземпляров одного элемента.

Оценка этой программы во время компиляции создает структуру, показанную на рисунке 15. Обратите внимание на наличие двух экземпляров таблицы t. Оба эти экземпляра должны быть видны уровню управления. Для именования объектов в этой иерархии используется путь, образованный именами, содержащими экземпляры. В данном случае таблицы имеют имена s.c1.t и s.c2.t, где s — имя аргумента при создании экземпляра программы, которое выводится из имени соответствующего формального параметра.

16.3.2. Аннотации для имен управляемых элементов

Связанные с уровнем управления аннотации (параграф 17.1.2) могут менять имена, предоставляемые уровню управления, несколькими способами.

  • Аннотация @hidden скрывает управляемый элемент от уровня управления. Это единственный случай, когда управляемый элемент не обязан иметь уникальное полное имя.

  • Аннотация @name может служить для изменения локального имени управляемого элемента.

  • Аннотация @globalname может служить для изменения глобального имени управляемого элемента.

Программы, дающие одно полное имя двум разным управляемым элементам, не допустимы. В частности, следует осторожно использовать аннотации @globalname. Если тип содержит аннотацию @globalname и созданы два его экземпляра, они получат одно полное имя.

16.3.3. Рекомендации

Уровень управления может указывать контролируемый элемент по суффиксу его полного имени, если это обеспечивает уникальность имен в данном контексте. Рассмотрим пример.

control c( ... )() {
	action a ( ... ) { ... }
	table t {
		keys = { ... }
		actions = { a; }
	}
}
c() c_inst;

Программы уровня управления могут ссылаться на действие c_inst.a при вставке правил в таблицу c_inst.t, поскольку из определения таблицы ясно, о каком действии идет речь.

Не все однозначные сокращения могут быть рекомендованы. Рассмотрим первый пример из параграфа 16.3. Может возникнуть соблазн указывать s.c1 просто как c1, поскольку в программе нет других экземпляров с именем c1. Однако это осложнит изменение программы в будущем, поскольку не позволит создавать экземпляры с именем c1 или включать библиотеки P4, содержащие экземпляры с таким именем.

16.4. Динамическая оценка

Динамическая оценка программы P4 организуется архитектурной моделью. Каждая модель архитектуры должна задавать порядок и условия, при которых динамически выполняются различные программные компоненты P4. Например, поток исполнения VSS из параграфа 5.1 имеет вид Parser->Pipe->Deparser.

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

16.4.1. Модель одновременной обработки

Типичной системе обработки пакетов требуется одновременно выполнять множество логических потоков (thread). имеется по меньшей мере поток уровня управления, который может менять содержимое таблиц. Архитектурным спецификациям следует подробно описывать взаимодействия между уровнями управления и данных. Уровень данных может обмениваться информацией с уровнем управления путем вызова внешних функций и методов. Кроме того, высокопроизводительные системы могут одновременно обрабатывать большое число пакетов (например, в конвейере) или одновременно анализировать один пакет и выполнять операции СД для другого. В этом параграфе описана семантика программ P4 в части одновременного выполнения операций.

Каждый анализатор или блок управления верхнего уровня выполняется в виде отдельного потока (thread). Все параметры блока и все локальные переменные привязаны к этому потоку, т. е. каждый поток имеет свою копию этих ресурсов. Это относится к параметрам packet_in и packet_out анализаторов и сборщиков.

Поскольку блок P4 использует лишь локальное хранилище потока (например, метаданные, заголовки, локальные переменные), его поведение при параллельной работе не отличается от поведения изолированного блока, так как произвольное чередование операторов из разных потоков должно всегда давать неизменный результат.

Внешние блоки, экземпляры которых созданы программой P4Ю являются глобальными и совместно используются всеми потоками. Если блоки extern служат для доступа к состоянию (например, счетчики, регистры) и методы внешнего блока могут считывать и записывать состояние, операции с учетом состояния становятся состязательными. P4 в таких случаях диктует определенное поведение.

  • Выполнение операции является неделимым (atomic), т. е. другие потоки могут «видеть» состояние, которое было до начала выполнения операции или после ее завершения.

  • Вызов метода для экземпляра extern является неделимым.

Чтобы пользователь мог задать неделимое выполнение более крупного блока кода, P4 поддерживает аннотацию @atomic, которая может быть применена к блоку операторов, состояниям анализатора, блокам управления или анализатору в целом.

Рассмотрим пример

extern Register { ... }
control Ingress() {
	Register() r;
	table flowlet { /* Чтение состояния r в действии */ }
	table new_flowlet { /* Запись состояния r в действии */ }
	apply {
		@atomic { flowlet.apply(); }
}}
if (ingress_metadata.flow_ipg > FLOWLET_INACTIVE_TIMEOUT)
	new_flowlet.apply();

Эта программа обращается к внешнему объекту r типа Register в операциях, вызываемых из таблиц flowlet (чтение) и new_flowlet (запись). Без аннотации @atomic эти две операции не будут неделимыми и для второго пакета состояние r может быть прочитано до того, как первый сможет его изменить.

Компилятор (backend) должен отклонить программу с блоками @atomic, если он не поддерживает неделимого выполнения последовательности инструкций. Для таких случаев компилятору следует поддерживать диагностику.

17. Аннотации

Аннотации похожи на атрибуты C# и аннотации Java и обеспечивают простой механизм некоторого расширения языка P4 без изменения его грамматики. В каком-то смысле это походе на C #pragma. Аннотации могут добавляться к типам, полям, переменным и т. д. с использованием синтаксиса @ (как показано явно в грамматике P4).

optAnnotations
	: /* Пусто */
	| annotations
	;
annotations
	: annotation
	| annotations annotation
	;
annotation
	: '@' name
	| '@' name '(' expressionList ')'
	;

17.1. Предопределенные аннотации

Аннотации, имена которых начинаются со строчных букв, зарезервированы для стандартной библиотеки и архитектуры, «стандартные» аннотации определены в этом документе и их список может расширяться. Для фирменных архитектур предлагается определять аннотации, начинающиеся с префикса производителя (например, организация X может использовать аннотации вида @X_annotation).

17.1.1. Аннотации списка действий таблицы

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

  • @tableonly — действия с такой аннотацией могут быть лишь в таблице и не могут применяться по умолчанию.

  • @defaultonly — действия с такой аннотацией могут лишь применяться по умолчанию и не могут быть в таблице.

table t {
	actions = {
		a,			// Может присутствовать где угодно
		@tableonly b,		// Может присутствовать только в таблице
		@defaultonly c,	// Может присутствовать в принятом по умолчанию действии
	}
	...
}

17.1.2. Аннотации API уровня управления

Аннотация @name говорит компилятору, что нужно использовать другое локальное имя при генерации внешних API, используемых для манипуляций с элементами языка с уровня управления. Аннотация может иметь аргумент в виде строкового литерала. В приведенном ниже примере полное имя таблицы будет c_inst.t1.

control c( ... )() {
	@name("t1") table t { ... }
	apply { ... }
}
c() c_inst;

Аннотация @globalname похожа на @name, но меняет полное имя (а не только локальное) элемента. В приведенном примере полным именем таблицы будет foo.bar.

control c( ... )() {
	@globalname("foo.bar") table t { ... }
	apply { ... }
}
c() c_inst;

Аннотация @hidden скрывает управляемый элемент (table, key, action, extern) от уровня управления и не имеет аргументов. Операция эффективно скрывает полное имя элемента (параграф 16.3).

17.1.2.1. Ограничения

Каждый элемент может использовать не более одной аннотации @name, @globalname или @hidden и каждое имя на уровне управления должно указывать не более одного управляемого элемента. Для аннотации @globalname имеется особый случай — если она используется дважды, одно глобальное имя будет указывать на два управляемых объекта.

control noargs();
package top(noargs c1, noargs c2);
control c() {
	@globalname("foo.bar") table t { ... }
	apply { ... }
}
top(c(), c()) main;

Без аннотации @globalname программа будет создавать два управляемых элемента с полными именами main.c1.t и main.c2.t. Однако аннотация @globalname(«foo.bar») меняет имя таблиц t в обоих экземплярах на foo.bar и имена управляемых объектов становятся непригодными.

17.1.3. Аннотации управления параллельной работой

Аннотация @atomic, описанная в параграфе 16.4.1, может служить для задания неделимого исполнения блока кода.

17.2. Специфические для платформы аннотации

Каждая реализация компилятора P4 может определять дополнительные аннотации, относящиеся к целевой платформе компилятора. Синтаксис таких аннотаций должен соответствовать приведенному выше описанию. Семантика этих аннотаций будет зависеть от платформы. Аннотации могут применяться как pragma в других языках.

Компиляторам P4 следует поддерживать перечисленные ниже уведомления.

  • Ошибки при некорректном использовании аннотаций (например, для аннотации задан параметр, но она используется без него или с недопустимым типом параметра).

  • Предупреждения при неизвестных аннотациях.

Приложение A. Зарезервированные слова P4

В таблице перечислены все зарезервированные слова P4. Некоторые идентификаторы считаются ключевыми словами лишь в определенном контексте (например, actions).

action
apply
bit
bool
const
control
default
else
enum
error
extern
exit
false
header
header_union
if
in
inout
int
match_kind
package
parser
out
return
select
state
struct
switch
table
transition
true
tuple
typedef
varbit
verify
void

Приложение B. Библиотека ядра P4

Библиотека ядра P4 содержит объявления, которые могут использоваться большинством программ.

Например, библиотека ядра включает объявления предопределенных внешних объектов packet_in и packet_out, используемых в анализаторах и сборщиках для доступа к данным пакета.

/// Стандартные коды ошибок. Пользователи могут добавлять свои коды.
error {
	NoError,			/// Нет ошибок.
	PacketTooShort,		/// В пакете недостаточно битов для извлечения.
	NoMatch,			/// Выражение select не имеет совпадений.
	StackOutOfBounds, /// Ссылка на недействительный элемент в стеке заголовков.
	HeaderTooShort, 	/// Извлечение слишком большого числа битов в поле varbit.
	ParserTimeout			/// Истекло время работы анализатора.
}
extern packet_in {
	/// Читает заголовок из пакета в поле типа header @hdr с фиксированным размером
	/// и перемещает указатель.
	/// Может вызывать ошибку PacketTooShort или StackOutOfBounds.
	/// @T должно иметь тип header фиксированного размера.
	void extract<T>(out T hdr);
	/// Читает биты из пакета в поле типа header @variableSizeHeader с переменным
	/// размером и перемещает указатель.
	/// @T должно быть заголовком, содержащим в точности 1 поле varbit.
	/// Может вызывать ошибку PacketTooShort, StackOutOfBounds или HeaderTooShort.
	void extract<T>(out T variableSizeHeader, in bit<32> variableFieldSizeInBits);
	/// Читает биты из пакета без перемещения указателя.
	/// @returns - прочитанные из пакета биты.
	/// T может иметь произвольный тип с фиксированным размером.
	T lookahead<T>();
	/// Перемещает указатель на заданной число битов.
	void advance(in bit<32> sizeInBits);
	/// @return - размер пакета в байтах. Этот метод доступен не в каждой архитектуре.
	bit<32> length();
}
extern packet_out {
	/// Запись @data в выходной пакет, пропуск некорректных заголовков и сдвиг указателя.
	/// @T может иметь тип header, header_stack, a header_union или struct с этими типами.
	void emit<T>(in T data);
}
action NoAction() {}
	/// Стандартный типы сопоставления для полей таблицы.
	/// Некоторые архитектуры могут не поддерживать эти сопоставления.
	/// Архитектура может объявлять свои сопоставления.
match_kind {
	/// Точное совпадение битов.
	exact,
	/// Тройное сопоставление с использованием маски.
	ternary,
	/// Самый длинный из совпадающих префиксов.
	lpm
}

Приложение C. Контрольные суммы

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

Например, можно предоставить модуль инкрементного расчета контрольных сумм Checksum16 (см. описание VSS в параграфе 5.2.4) для расчета 16-битовый дополнений до 1 с использованием внешнего объекта с сигнатурой типа

extern Checksum16 {
	Checksum16();			// Конструктор
	void clear();			// Подготовка модуля к расчету.
	void update<T>(in T data);	// Добавление данных в контрольную сумму.
	void remove<T>(in T data);	// Исключение данных их контрольной суммы.
	bit<16> get();		// Получение контрольной суммы для данных, добавленных после 					// последнего сброса
}

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

ck16.clear();			// Подготовка блока контрольных сумм
ck16.update(header.ipv4); // Запись заголовка
verify(ck16.get() == 16w0, error.IPv4ChecksumError); // Проверка контрольной суммы 0

Генерация контрольной суммы IP может быть выполнена, как показано ниже.

header.ipv4.hdrChecksum = 16w0;
ck16.clear();
ck16.update(header.ipv4);
header.ipv4.hdrChecksum = ck16.get();

Кроме того, некоторые архитектуры коммутаторов не выполняют проверку контрольных сумм и лишь делают инкрементное обновление с учетом изменения пакета. Это можно сделать с помощью приведенного фрагмента P4.

ck16.clear();
ck16.update(header.ipv4.hdrChecksum); 	// Исходная контрольная сумма
ck16.remove( { header.ipv4.ttl, header.ipv4.proto } );
header.ipv4.ttl = header.ipv4.ttl - 1;
ck16.update( { header.ipv4.ttl, header.ipv4.proto } );
header.ipv4.hdrChecksum = ck16.get();

Приложение D. Нерешенные вопросы

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

D.1. Переносимая архитектура коммутатора

Переносимость и композитность имеют важное значение для долгосрочного успеха P4. Композитность означает возможность реализации различных функций типа сетевой телеметрии по основному каналу (INT6), виртуализации сетей, и балансировки нагрузки в разных программах P4, написанных для PSA7, с взаимодействием, управляемым из программ верхнего уровня. Переносимость означает работу реализации некой функции (типа INT) в P4 на разных архитектурах, поддерживающих PSA. С этой целью рабочая группа по архитектуре разрабатывает спецификацию, которая позволит создавать программы P4 для работы на разных платформах.

D.2. Обобщение оператора switch

P416 включает операторы switch (параграф 10.7) и выражения select (параграф 11.6). В текущей версии они реально различаются и операторы должны оцениваться в значение состояния.

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

switch(e1,...,en) {
	pat_1 : stmt1;
	...
	pat_m : stmtm;
}

Здесь проверяемое значение задано кортежем (e1,…,en), а варианты указаны выражениями-шаблонами, которые обозначают наборы значений. Значение соответствует варианту, если оно попадает заданный шаблоном набор. В отличие от C и C++, здесь нет оператора break и просмотр вариантов не завершается при обнаружении соответствия, если только нет специального оператора «выхода», связанного с данным вариантом.

Это предназначено для фиксации стандартной семантики операторов switch, а также общей идиомы в анализаторах P4, где эти операторы применяются для управления переходами между различными состояниями анализатора в зависимости от значения одного или множества уже проанализированных полей. Используя операторы switch, можно также обобщить устройство анализаторов, избавляясь от выбора и ослабляя большинство ограничений для типов операторов, разрешенных в состоянии. В частности, разрешено использование условных операторов и select с произвольным уровнем вложенности. Данный язык можно транслировать в более ограниченные версии, где тело каждого состояния образовано последовательностью объявлений переменных, присваиваний значений и вызовов методов, завершающейся одним оператором transition для перехода в новое состояние.

Мы также упрощаем обработку hit/miss в таблицах и действий в блоках управления за счет генерации неявных типов для действий и результатов.

Контраргументом для этого предложения может служить то, что семантика select в анализаторе существенно отличается от семантики switch, а кроме того эти конструкции уже знакомы программистам и обычно уже эффективно используются для разных платформ.

D.3. Неопределенное поведение

Возможность неопределенного поведения вызывает множество проблем в языках типа C и HTML, включая ошибки и серьезные уязвимости защиты. Есть несколько случаев когда оценка программы P4 может приводить к неопределенному поведению — параметры out, неинициализированные переменные, обращение к полям непригодных заголовков, выход индекса стека заголовков за допустимые пределы. Мы считаем, что нужно делать все необходимое для предотвращения неопределенного поведения в P416 поэтому предлагается усиливать формулировки спецификации, чтобы по умолчанию программы с неопределенным поведением были исключены. Принимая во внимание вопросы производительности, предлагается определить флаги компилятора и/или операторы pragma, которые могут отменять безопасное поведение. Тем не менее, мы надеемся, что программисты будут работать над созданием безопасных программ и призываем их к этому.

D.4. Структурированные итерации

Добавление конструкции типа foreach для работы со стеками заголовков смягчает необходимость использования директив препроцессора C для задания размера стека заголовков. Например,

foreach hdr in hdrs {
	... операции над HDR ...
}

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

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

Приложение E. Грамматика P4

В этом приложении грамматика P416 описана с использованием языка YACC/bison. Грамматика не задает приоритет для операций.

Эта грамматика не однозначна, поэтому лексический (lexer) и синтаксический (parser) анализаторы должны взаимодействовать при анализе. В частности, лексический анализатор должен различать два типа идентификаторов:

  • ранее введенные имена типов (маркеры TYPE);

  • обычные идентификаторы (маркер IDENTIFIER).

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

typedef bit<4> t;
struct s { ...}
t x;
parser p(bit<8> b) { ... }

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

t - TYPE
s - TYPE
x - IDENTIFIER
p - TYPE
b - IDENTIFIER

На эту грамматику сильно повлияли ограничений инструмента для генерации синтаксических анализаторов Bison.

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

SHL это <<
LE это <=
GE это >=
NE это !=
EQ это ==
PP это ++
AND это &&
OR это ||
MASK это &&&
RANGE это ..
DONTCARE это _

Маркер STRING_LITERAL соответствует строковому литералу в двойных кавычках, как описано в параграфе 6.3.3.3.

Все остальные терминалы являются написанием соответствующих ключевых слов заглавными буквами. Например, RETURN будет терминалом, возвращаемым лексическим анализатором при разборе ключевого слова return.

p4program
	: /* Пусто */
	| p4program declaration
	| p4program ';'	/* Пустое объявление */
	;

declaration
	: constantDeclaration
	| externDeclaration
	| actionDeclaration
	| parserDeclaration
	| typeDeclaration
	| controlDeclaration
	| instantiation
	| errorDeclaration
	| matchKindDeclaration
	;

nonTypeName
	: IDENTIFIER
	| APPLY
	| KEY
	| ACTIONS
	| STATE
	;

name
	: nonTypeName
	| TYPE
	| ERROR
	;

optAnnotations
	: /* Пусто */
	| annotations
	;

annotations
	: annotation
	| annotations annotation
	;

annotation
	: '@' name
	| '@' name '(' expressionList ')'
	;

parameterList
	: /* Пусто */
	| nonEmptyParameterList
	;

nonEmptyParameterList
	: parameter
	| nonEmptyParameterList ',' parameter
	;

parameter
	: optAnnotations direction typeRef name
	;

direction
	: IN
	| OUT
	| INOUT
	| /* Пусто */
	;

packageTypeDeclaration
	: optAnnotations PACKAGE name optTypeParameters '(' parameterList ')'
	;

instantiation
	: typeRef '(' argumentList ')' name ';'
	: annotations typeRef '(' argumentList ')' name ';'
	;

optConstructorParameters
	: /* Пусто */
	| '(' parameterList ')'
	;

dotPrefix
	: '.'
	;

/**************************** Анализатор ******************************/
parserDeclaration
	: parserTypeDeclaration optConstructorParameters '{' parserLocalElements parserStates '}'
	  	/* Нет параметров типа, разрешенных в parserTypeDeclaration */
	;

parserLocalElements
	: /* Пусто */
	| parserLocalElements parserLocalElement
	;

parserLocalElement
	: constantDeclaration
	| variableDeclaration
	| instantiation
	;

parserTypeDeclaration
	: optAnnotations PARSER name optTypeParameters '(' parameterList ')'
	;

parserStates
	: parserState
	| parserStates parserState
	;

parserState
	: optAnnotations STATE name '{' parserStatements transitionStatement '}'
	;

parserStatements
	: /* Пусто */
	| parserStatements parserStatement
	;

parserStatement
	: assignmentOrMethodCallStatement
	| directApplication
	| parserBlockStatement
	| constantDeclaration
	| variableDeclaration
	;

parserBlockStatement
	: optAnnotations '{' parserStatements '}'
	;

transitionStatement
	: /* Пусто */
	| TRANSITION stateExpression
	;

stateExpression
	: name ';'
	| selectExpression
	;

selectExpression
	: SELECT '(' expressionList ')' '{' selectCaseList '}'
	;

selectCaseList
	: /* Пусто */
	| selectCaseList selectCase
	;

selectCase
	: keysetExpression ':' name ';'
	;

keysetExpression
	: tupleKeysetExpression
	| simpleKeysetExpression
	;

tupleKeysetExpression
	: '(' simpleKeysetExpression ',' simpleExpressionList ')'
	;

simpleExpressionList
	: simpleKeysetExpression
	| simpleExpressionList ',' simpleKeysetExpression
	;

simpleKeysetExpression
	: expression
	| DEFAULT
	| DONTCARE
	| expression MASK expression
	| expression RANGE expression
	;

/*************************** Элементы управления ************************/
controlDeclaration
	: controlTypeDeclaration optConstructorParameters
		/* нет параметров типа, разрешенных в controlTypeDeclaration */
		'{' controlLocalDeclarations APPLY controlBody '}'
	;

controlTypeDeclaration
	: optAnnotations CONTROL name optTypeParameters '(' parameterList ')'
	;

controlLocalDeclarations
	: /* Пусто */
	| controlLocalDeclarations controlLocalDeclaration
	;

controlLocalDeclaration
	: constantDeclaration
	| actionDeclaration
	| tableDeclaration
	| instantiation
	| variableDeclaration
	;

controlBody
	: blockStatement
	;

/*************************** Внешние объекты *************************/
externDeclaration
	: optAnnotations EXTERN nonTypeName optTypeParameters '{' methodPrototypes '}'
	| optAnnotations EXTERN functionPrototype ';'
	;

methodPrototypes
	: /* Пусто */
	| methodPrototypes methodPrototype
	;

functionPrototype
	: typeOrVoid name optTypeParameters '(' parameterList ')'
	;

methodPrototype
	: functionPrototype ';'
	| TYPE '(' parameterList ')' ';'
	;

/************************** Типы ****************************/
typeRef
	: baseType
	| typeName
	| specializedType
	| headerStackType
	;

prefixedType
	: TYPE
	| dotPrefix TYPE
	;

typeName
	: prefixedType
	;

tupleType
	: TUPLE '<' typeArgumentList '>'
	;

headerStackType
	: typeName '[' expression ']'
	;

specializedType
	: prefixedTYpe '<' typeArgumentList '>'
	;

baseType
	: BOOL
	| ERROR
	| BIT
	| BIT '<' INTEGER '>'
	| INT '<' INTEGER '>'
	| VARBIT '<' INTEGER '>'
	;

typeOrVoid
	: typeRef
	| VOID
	| nonTypeName		// Может быть переменной типа
	;
	
optTypeParameters
	: /* Пусто */
	| '<' typeParameterList '>'
	;

typeParameterList
	: nonTypeName
	| typeParameterList ',' nonTypeName
	;

typeArg
	: DONTCARE
	| typeRef
	;

typeArgumentList
	: typeArg
	| typeArgumentList ',' typeArg
	;

typeDeclaration
	: derivedTypeDeclaration
	| typedefDeclaration
	| parserTypeDeclaration ';'
	| controlTypeDeclaration ';'
	| packageTypeDeclaration ';'
	;

derivedTypeDeclaration
	: headerTypeDeclaration
	| headerUnionDeclaration
	| structTypeDeclaration
	| enumDeclaration
	;

headerTypeDeclaration
	: optAnnotations HEADER name '{' structFieldList '}'
	;

headerUnionDeclaration
	: optAnnotations HEADER_UNION name { structure.declareType(*$3); }
		'{' structFieldList '}'
		 { $$ = new IR::Type_Union(@3, *$3, $1, *$6); }
	;

structTypeDeclaration
	: optAnnotations STRUCT name '{' structFieldList '}'
	;

structFieldList
	: /* Пусто */
	| structFieldList structField
	;

structField
	: optAnnotations typeRef name ';'
	;

enumDeclaration
	: optAnnotations ENUM name '{' identifierList '}'
	;

errorDeclaration
	: ERROR '{' identifierList '}'
	;

matchKindDeclaration
	: MATCH_KIND '{' identifierList '}'
	;

identifierList
	: name
	| identifierList ',' name
	;

typedefDeclaration
	: annotations TYPEDEF typeRef name ';'
	| TYPEDEF typeRef name ';'
	| annotations TYPEDEF derivedTypeDeclaration name ';'
	| TYPEDEF derivedTypeDeclarationame ';'
	;

/*************************** Операторы *************************/
assignmentOrMethodCallStatement
	: lvalue '(' argumentList ')' ';'
	| lvalue '<' typeArgumentList '>' '(' argumentList ')' ';'
	| lvalue '=' expression ';'
	;

emptyStatement
	: ';'
	;

returnStatement
	: RETURN ';'
	;

exitStatement
	: EXIT ';'
	;

conditionalStatement
	: IF '(' expression ')' statement
	| IF '(' expression ')' statement ELSE statement
	;

// Для поддержки прямого вызова элемента управления или анализатора без создания экземпляра
directApplication
	: typeName '.' APPLY '(' argumentList ')' ';'

statement
	: assignmentOrMethodCallStatement
	| directApplication
	| conditionalStatement
	| emptyStatement
	| blockStatement
	| exitStatement
	| returnStatement
	| switchStatement
	;

blockStatement
	: optAnnotations '{' statOrDeclList '}'
	;

statOrDeclList
	: /* Пусто */
	| statOrDeclList statementOrDeclaration
	;

switchStatement
	: SWITCH '(' expression ')' '{' switchCases '}'
	;

switchCases
	: /* Пусто */
	| switchCases switchCase
	;

switchCase
	: switchLabel ':' blockStatement
	| switchLabel ':'
	;

switchLabel
	: name
	| DEFAULT
	;

statementOrDeclaration
	: variableDeclaration
	| constantDeclaration
	| statement
	| instantiation
	;

/************ Таблицы *************/
tableDeclaration
	: optAnnotations TABLE name '{' tablePropertyList '}'
	;

tablePropertyList
	: tableProperty
	| tablePropertyList tableProperty
	;

tableProperty
	: KEY '=' '{' keyElementList '}'
	| ACTIONS '=' '{' actionList '}'
	| CONST ENTRIES '=' '{' entriesList '}' /* неизменные записи */
	| optAnnotations CONST IDENTIFIER '=' initializer ';'
	| optAnnotations IDENTIFIER '=' initializer ';'
	;

keyElementList
	: /* Пусто */
	| keyElementList keyElement
	;

keyElement
	: expression ':' name optAnnotations ';'
	;

actionList
	: actionRef ';'
	| actionList actionRef ';'
	;

entriesList
	: entry
	| entryList entry

entry
	: optAnnotations keysetExpression ':' actionRef ';'

actionRef
	: optAnnotations name
	| optAnnotations name '(' argumentList ')'
	;

/************************* Действие ********************************/
actionDeclaration
	: optAnnotations ACTION name '(' parameterList ')' blockStatement
	;

/************************* Переменные *****************************/
variableDeclaration
	: annotations typeRef name optInitializer ';'
	| typeRef name optInitializer ';'
	;

constantDeclaration
	: optAnnotations CONST typeRef name '=' initializer ';'
	;

optInitializer
	: /* Пусто */
	| '=' initializer
	;

initializer
	: expression
	;

/************************* Выражения ****************************/
argumentList
	: /* Пусто */
	| nonEmptyArgList
	;

nonEmptyArgList
	: argument
	| nonEmptyArgList ',' argument
	;

argument
	: expression
	;

expressionList
	: /* Пусто */
	| expression
	| expressionList ',' expression
	;

member
	: name
	;

prefixedNonTypeName
	: nonTypeName
	| dotPrefix nonTypeName
	;

lvalue
	: prefixedNonTypeName
	| lvalue '.' member
	| lvalue '[' expression ']'
	| lvalue '[' expression ':' expression ']'
	;

%left ','
%nonassoc '?'
%nonassoc ':'
%left OR
%left AND
%left '|'
%left '^'
%left '&'
%left EQ NE
%left '<' '>' LE GE
%left SHL
%left PP '+' '-'
%left '*' '/' '%'
%right PREFIX
%nonassoc ']' '(' '['
%left '.'

// Требуется задать дополнительные предпочтения
expression
	: INTEGER
	| TRUE
	| FALSE
	| STRING_LITERAL
	| nonTypeName
	| '.' nonTypeName
	| expression '[' expression ']'
	| expression '[' expression ':' expression ']'
	| '{' expressionList '}'
	| '(' expression ')'
	| '!' expression
	| '~' expression
	| '-' expression
	| '+' expression
	| typeName '.' member
	| ERROR '.' member
	| expression '.' member
	| expression '*' expression
	| expression '/' expression
	| expression '%' expression
	| expression '+' expression
	| expression '-' expression
	| expression SHL expression		// <<
	| expression '>''>' expression		// Проверка того, что символы >> смежны
	| expression LE expression		// <=
	| expression GE expression		// >=
	| expression '<' expression
	| expression '>' expression
	| expression NE expression		// !=
	| expression EQ expression		// ==
	| expression '&' expression
	| expression '^' expression
	| expression '|' expression
	| expression PP expression		// ++
	| expression AND expression		// &&
	| expression OR expression		// ||
	| expression '?' expression ':' expression
	| expression '<' typeArgumentList '>' '(' argumentList ')'
	| expression '(' argumentList ')'
	| typeRef '(' argumentList ')'
	| '(' typeRef ')' expression
	;

Перевод на русский язык

Николай Малых

nmalykh@protokols.ru

1Very Simple Switch — очень простой коммутатор.

2В простейшем случае коммутатора VSS это верно, но в реальности пакет может сохраняться и обрабатываться дальше с передачей в обычный выходной порт или порт рециркуляции. Прим. перев.

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

4Это означает отсутствие знака «-» перед записью константы, но не препятствует заданию отрицательных чисел. Наличие знака у константы определяется префиксом w или s, а сам знак — старшим битом константы. Прим. перев.

5Extended Berkeley Packet Filter — расширенный фильтр пакетов Беркли.

6In-band Network Telemetry.

7Portable Switch Architecture — переносимая архитектура коммутатора.

Рубрика: Сетевое программирование | Комментарии к записи Спецификация языка версии P4_16 v1.0.0 отключены

RFC 8174 Ambiguity of Uppercase vs Lowercase in RFC 2119 Key Words

Internet Engineering Task Force (IETF)                          B. Leiba
Request for Comments: 8174                           Huawei Technologies
BCP: 14                                                         May 2017
Updates: 2119
Category: Best Current Practice
ISSN: 2070-1721

Неоднозначность использования заглавных букв в ключевых словах RFC 2119

Ambiguity of Uppercase vs Lowercase in RFC 2119 Key Words

PDF

Аннотация

В RFC 2119 указаны ключевые слова общего назначения, которые могут применяться в спецификациях протоколов. Целью этого документа является устранение неоднозначности за счет прояснения необходимости использования заглавных букв1 для того, чтобы ключевые слова имели указанное специальное значение.

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

Этот документ относится к категории Internet Best Current Practice.

Документ является результатом работы IETF2 и представляет согласованный взгляд сообщества IETF. Документ прошел открытое обсуждение и был одобрен для публикации IESG3. Не все одобренные IESG документы претендуют на статус Internet Standard (см. раздел 2 в RFC 7841).

Информацию о текущем статусе документа, ошибках и способах обратной связи можно найти по ссылке http://www.rfc-editor.org/info/rfc8174.

Авторские права

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

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

1. Введение

В RFC 2119 указаны ключевые слова общего назначения типа MUST, SHOULD и MAY, которые могут применяться в спецификациях протоколов. Там сказано, что ключевые слова «часто выделяются заглавными буквами» и это приводило к неоднозначности трактовки слов типа must и should без заглавных букв.

Данный документ обновляет RFC 2119, разъясняя, что только слова, набранные заглавными буквами, имеют указанное в документе значение. Документ является частью BCP 14.

2. Разъяснение по использованию заглавных букв в ключевых словах

Ниже показаны изменения, вносимые в [RFC2119]:

=== Старый текст ===

Во многих документах, описывающих стандарты, используются модальные глаголы для обозначения уровня требований. Такие слова часто выделяются заглавными буквами4. В данном документе определяется толкование этих глаголов и производных от них слов в документах IETF. Авторам документов, следующих приведенным здесь требованиям, рекомендуется помещать в начале документов приведенный ниже текст:

The key words «MUST», «MUST NOT», «REQUIRED», «SHALL», «SHALL NOT», «SHOULD», «SHOULD NOT», «RECOMMENDED», «MAY», and «OPTIONAL» in this document are to be interpreted as described in RFC 21195.

=== Новый текст ===

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

  • Такие слова могут использоваться в соответствии с приведенными здесь определениями, но такое использование не является обязательным. В частности, не требуется применения этих слов в нормативных текстах. Эти слова применяются для четкости и согласованности, когда это нужно, но во многих нормативных документах использование такого специального значение слов не требуется.

  • Слова имеют указанные здесь значения только в случае их набора полностью заглавными буквами.

  • Если слова не набраны полностью заглавными буквами, для них используется обычная в английском языке трактовка и данный документ не оказывает на это влияния.

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

The key words «MUST», «MUST NOT», «REQUIRED», «SHALL», «SHALL NOT», «SHOULD», «SHOULD NOT», «RECOMMENDED», «NOT RECOMMENDED», «MAY», and «OPTIONAL» in this document are to be interpreted as described in BCP 14 [RFC2119] [RFC8174] when, and only when, they appear in all capitals, as shown here6.

=== Конец изменений ===

3. Согласование с IANA

Этот документ не требует каких-либо действий IANA.

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

Документ является полностью процедурным и с ним не связано каких-либо вопросов безопасности.

5. Нормативные документы

[RFC2119] Bradner, S., «Key words for use in RFCs to Indicate Requirement Levels», BCP 14, RFC 2119, DOI 10.17487/RFC2119, March 1997, <http://www.rfc-editor.org/info/rfc2119>.

Адрес автора

Barry Leiba

Huawei Technologies

Phone: +1 646 827 0648

Email: barryleiba@computer.org

URI: http://internetmessagingtechnology.org/


Перевод на русский язык

Николай Малых

nmalykh@gmail.com

1В опубликованных на этом сайте переводах RFC вместо заглавных букв используется выделение полужирным шрифтом. Прим. перев.

2Internet Engineering Task Force.

3Internet Engineering Steering Group.

4В переводах на сайте www.protokols.ru используется выделение жирным шрифтом. Прим. перев.

5Ключевые слова необходимо, недопустимо, требуется, нужно, не нужно, следует, не следует, рекомендуется, не рекомендуется, возможно, необязательно в данном документе должны интерпретироваться в соответствии с требованиями RFC 2119.

6Ключевые слова необходимо, недопустимо, требуется, нужно, не нужно, следует, не следует, рекомендуется, не рекомендуется, возможно, необязательно в данном документе должны интерпретироваться в соответствии с требованиями BCP 14 [RFC2119] [RFC8174] тогда и только тогда, когда они полностью набраны заглавными буквами, как показано здесь.

Рубрика: RFC | Комментарии к записи RFC 8174 Ambiguity of Uppercase vs Lowercase in RFC 2119 Key Words отключены

RFC 8085 UDP Usage Guidelines

Internet Engineering Task Force (IETF)                         L. Eggert
Request for Comments: 8085                                        NetApp
BCP: 145                                                    G. Fairhurst
Obsoletes: 5405                                   University of Aberdeen
Category: Best Current Practice                              G. Shepherd
ISSN: 2070-1721                                            Cisco Systems
                                                              March 2017

UDP Usage Guidelines

Рекомендации по использованию UDP

PDF

Аннотация

Протокол пользовательских дейтаграмм (User Datagram Protocol или UDP) обеспечивает минимальный транспорт передачи сообщений, не наследующий механизмов контроля перегрузок. В этом документе даны рекомендации по применению UDP для разработчиков приложений, туннелей и других протоколов на основе UDP. Основной внимание уделено контролю насыщения (перегрузки), но документ включает также рекомендации по другим вопросам, включая размер сообщений, гарантии доставки, контрольные суммы, прохождение через промежуточные устройства, использование явных уведомлений о перегрузке (Explicit Congestion Notification или ECN), коды дифференцированного обслуживания (Differentiated Services Code Point или DSCP) и порты.

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

Некоторые рекомендации связаны с устройством других протоколов (например, протоколов, работающих непосредственно по IP или через туннели IP), особенно в случаях, когда эти протоколы сами не обеспечивают контроля перегрузок.

Этот документ отменяет RFC 5405 и добавляет рекомендации по групповой адресации в UDP.

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

Документ относится к категории обмена опытом (Best Current Practice).

Документ является результатом работы IETF1 и представляет согласованный взгляд сообщества IETF. Документ прошел открытое обсуждение и был одобрен для публикации IESG2. Дополнительную информацию о стандартах Internet можно найти в разделе 2 в RFC 7841.

Информация о текущем статусе документа, найденных ошибках и способах обратной связи доступна по ссылке http://www.rfc-editor.org/info/rfc8085.

Авторские права

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

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

1. Введение

Протокол UDP [RFC768] предоставляет минимальные транспортные услуги без гарантии доставки в стиле best-effort (как получится) для сообщений от приложения или другого протокола (например, туннельного) на основе протокола IP. В оставшейся части документа приложения и протоколы, использующие транспорт, называются просто приложениями.

По сравнению с другими транспортными протоколами UDP и его вариант UDP-Lite [RFC3828] уникальны с том, что не организуют сквозного соединения между взаимодействующими системами. Поэтому с коммуникациями UDP не связаны издержки на организацию и завершение соединений и связь с состояниями конечных систем минимальна. В результате UDP предлагает очень эффективный транспорт для некоторых приложений.

Второй уникальной характеристикой UDP является отсутствие встроенных механизмов контроля перегрузок. На многих платформах приложения могут передавать дейтаграммы UDP с скоростью линии (среды) канального интерфейса платформы, которая часто значительно превышает доступную пропускную способность сквозного пути и это вносит вклад в перегрузку на пути. В [RFC2914] описан опыт контроля перегрузок в Internet. Документ указывает две основных причины важности механизмов контроля перегрузок для стабильной работы Internet.

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

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

Поскольку UDP не обеспечивает контроля перегрузок, приложения, применющие UDP для Internet-коммуникаций, реализуют подходящие механизмы предотвращения перегрузочного коллапса и обеспечения беспристрастности. В [RFC2309] рассматривается опасность не отвечающих на перегрузку потоков и отмечено, что «все потоковым приложениям на основе UDP следует включать эффективный механизм предотвращения перегрузок». [RFC7567] подтверждает это заявление. Это требование важно даже для приложений, не применяющих UDP для передачи потоков. Кроме того, транспортировка с контролем перегрузок обеспечивает преимущества самим приложениям, поскольку может снижать самоиндуцированную потерю пакетов, минимизировать повторы передачи и в результате снизить задержки. Контроль перегрузок важен даже при сравнительно низкой скорости передачи. Например, приложение, создающее 5 дейтаграмм UDP по 1500 байтов в секунду, может уже выйти за пределы пропускной способности пути 56 Кбит/с. Для более скоростных приложений, возможно с неограниченной скоростью, контроль перегрузок становится жизненно важным для предотвращения коллапса насыщения и обеспечения той или иной беспристрастности. В разделе 3 приведено множество простых рекомендация для разработчиков таких приложений.

Дейтаграмма UDP передается в одном пакете IP и поэтому ограничена в размере 65507 байтами поля данных в IPv4 и 65527 байтами в IPv6. Передача больших пакетов IP обычно требует фрагментации на уровне IP, что снижает надежность и эффективность коммуникаций, поэтому ее следует избегать. IPv6 обеспечивает опцию для передачи больших пакетов (jumbogram) без фрагментации когда все канальные уровни на пути поддерживают это [RFC2675]. Некоторые из рекомендаций раздела 3 описывают способ определения подходящего для приложения размера сообщений. В других разделах документа даны рекомендации по обеспечению надежности доставки, контрольным суммам, прохождению через промежуточные устройства и использованию групповой адресации.

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

[RFC5405] был предназначен в качестве рекомендации лишь для unicast-приложений, тогда как этот документ содержит рекомендации, позволяющие потокам UDP использовать групповую адресацию IP, anycast и широковещание а также рекомендации для приложений, применяющих туннели UDP для потоков IP.

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

2. Уровни требований

Ключевые слова необходимо (MUST), недопустимо (MUST NOT), требуется (REQUIRED), нужно (SHALL), не нужно (SHALL NOT), следует (SHOULD), не следует (SHOULD NOT), рекомендуется (RECOMMENDED), возможно (MAY), необязательно (OPTIONAL) в данном документе должны интерпретироваться в соответствии с [RFC2119].

3. Рекомендации по использованию UDP

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

Эти механизмы сложно реализовать корректно. Для большинства приложений применение одного из имеющихся транспортных протоколов IETF является простейшим вариантом обретения нужных механизмов. Это позволяет избежать проблем, с которыми сталкиваются новые протоколы на основе IP, разрабатываемые для Internet, где могут встречаться промежуточные устройства, поддерживающие лишь транспорт TCP и UDP. Поэтому альтернативой описанному в этом документе использованию протокола UDP рекомендуется выбирать один из транспортных протоколов IETF, такой как TCP [RFC793], SCTP3 [RFC4960], SCTP-PR4 [RFC3758], DCCP5 [RFC4340] с их разными типами контроля перегрузок [RFC4341][RFC4342][RFC5622] или транспортные протоколы, которые будут разработаны в IETF. SCTP с инкапсуляцией в UDP [RFC6951] и DCCP [RFC6773] могут обеспечивать поддержку работы через межсетевые экраны и другие промежуточные устройства, где естественный протокол не поддерживается.

При корректном использовании эти полнофункциональные протоколы не являются столь «тяжеловесными» как часто утверждают. Например, алгоритмы TCP непрерывно совершенствовались десятки лет и достигли высокого уровня эффективности и корректности, который трудно получить в специализированных механизмах прикладного уровня. Кроме того, многие реализации TCP позволяют приложению настроить соединения в соответствии со своими потребностями. Например, можно отключить алгоритм Nagle [RFC1122], сократив задержки за счет более частой (но контролируемой в части перегрузок) передачи пакетов. Другим примером является механизм TCP SYN cookie [RFC4987], доступный на многих платформах. TCP с SYN cookie не требует от сервера поддержки состояния на уровне соединения до организации соединения. TCP также требует от закрывающей соединение стороны поддерживать состояние TIME-WAIT, которое предотвращает конфликты задержанных сегментов соединения с сегментами нового экземпляра. Приложения, которые знают о таком поведении и разработаны для него, могут менять поддержку состояния TIME-WAIT для экономии ресурсов, выбирая сторону, закрывающую соединение TCP [FABER]. Встроенная функция TCP для проверки пропускной способности и определения размера максимального передаваемого блока, поддерживаемого на пути (PMTU) обеспечивает эффективную передачу данных с быстрой компенсацией задержки организации соединения в случаях обменов данными, не ограничивающихся несколькими сегментами.

3.1. Рекомендации по контролю перегрузок

Если приложение или протокол отказывается от применения транспортного протокола с контролем перегрузок, ему следует контролировать скорость передачи дейтаграмм UDP хосту-получателю, чтобы выполнить требования [RFC2914]. Важно подчеркнуть, что приложению следует выполнять контроль перегрузки для всего трафика UDP, отправляемого адресату, независимо от способа генерации этого трафика. Например, приложению, использующему процесс с множественным ветвлением или иной вариант с множеством сокетов для генерации трафика UDP, следует реализовать контроль перегрузок для всего агрегата трафика.

Некоторые подходы к контролю перегрузок рассмотрены ниже в этом разделе. Здесь рассматриваются базовые вопросы с акцентом на индивидуальную и anycast-адресацию [RFC1546]. Не все описанные ниже подходы подходят для каждого приложения, передающего дейтаграммы UDP. В параграфе 3.1.2 рассматриваются опции контроля перегрузок для приложений с большим объемом передаваемых по протоколу UDP данных. Такие приложения могут использовать схемы, которые выбирают путь за несколько интервалов кругового обхода (round-trip) при обмене данными, где определяется скорость передачи, которую путь может поддерживать при текущей загрузке. В параграфе 3.1.3 рассмотрены варианты контроля перегрузок для приложения с небольшим объемом передаваемых данных. Поскольку в таких случаях сложно определить приемлемую скорость передачи итеративным методом (мало данных), нужен иной механизм контроля перегрузок. В параграфе 3.1.11 рассматривается контроль перегрузки при использовании протокола UDP для туннелирования. В разделе 4 даны дополнительные рекомендации для широковещательного и группового трафика.

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

В прошлом в рамках IETF исследовались интегрированные механизмы контроля перегрузок, которые работали с агрегатами трафика между парой хостов, т. е. такие схемы, как менеджер перегрузок [RFC3124], где активные сессии могли использовать общую информацию о насыщении независимым от транспортного протокола способом. Такие механизмы не получили распространения, но они могут упростить разработку механизмов контроля перегрузок для сессий UDP в соответствии с требованиями [RFC2914].

3.1.1. Рекомендации по таймерам

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

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

Рекомендации даны с точки зрения задержки и времени кругового обхода, поскольку в некоторых случаях нужно характеризовать лишь задержку в сети (например, TFRC6 [RFC5348]), а в других требуется включение времени, которое нужно конечной точке для предоставления отклика (например, определение момента повторной передачи сообщения).

Задержка между конечными точками обычно является динамическим свойством, поэтому в оценках следует представлять то или иное усреднение множества недавних измерений для учета вариаций. Применение усреднения EWMA7 доказало свою пользу для таких задач (например, в TCP [RFC6298] и TFRC [RFC5348]).

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

Выборку задержек недопустимо делать из неоднозначных транзакций. Каноническим примером служит протокол, который повторно передает данные, но затем не может определить, какая из копий была подтверждена. Такие неоднозначности делают корректный расчет задержки проблематичным (см. обсуждение алгоритма Karn в [RFC6298]). Это требование обеспечивает надежную оценку задержки отправителем без некорректных измерений.

Когда оценка задержки служит для установки таймера, обеспечивающего обнаружение потерь (с повтором или без него) завершение отсчета таймера должно считаться индикацией перегрузки в сети, вызывающим приспосабливать скорость передачи к безопасному умеренному значению (например, TCP снижает размер окна перегрузки до одного сегмента [RFC5681]).

Некоторым приложениям нужна предварительная оценка задержки перед тем, как можно будет эмпирически определить задержку между конечными точками. Например, при первом запуске таймера повторной передачи нужно задать начальное значение для защиты сообщений, переданных между конечными точками до того, как они определят задержку. Это начальное значение обычно следует устанавливать как можно большим для данного приложения. Например, при отсутствии каких-либо сведений о задержке в пути TCP требует установки для параметра RTO8 значения не меньше 1 секунды 1 [RFC6298]. Приложениям UDP следует использовать аналогичную начальную оценку задержки (1 сек.). Меньшие значения могут создавать проблемы (см. анализ данных в Приложении к [RFC6298]).

3.1.2. Приложения с большим объемом данных

Приложениям, передающим партнеру большой объем данных (более нескольких дейтаграмм за RTT) по протоколу UDP, следует реализовать механизм TFRC [RFC5348] — похожий на TCP контроль перегрузок на основе окна — или обеспечить соответствие принципам контроля перегрузок иным способом.

Механизм TFRC разработан для обеспечения контроля перегрузок и беспристрастности совместимым с другими транспортными протоколами IETF способом. Если приложение реализует TFRC, ему не нужно следовать остальным рекомендациям этого параграфа, поскольку они уже выполнены в TFRC, но следует выполнять рекомендации последующих параграфов раздела 3.

Приложениям с большим объемом данных, отказавшимся от реализации TFRC или использования окна в стиле TCP, следует реализовать схему контроля перегрузок, обеспечивающую использование пропускной способности (емкости), беспристрастно разделяемой с TCP (по порядку значений). В разделе 2 [RFC3551] отмечено, что приложениям следует контролировать скорость потери пакетов, чтобы она находилась в допустимых пределах. Потеря пакетов считается приемлемой, если поток TCP по тому же пути через сеть и при таких же условиях будет достигать средней пропускной способности не меньше чем у потока UDP при измерении в разумный интервал времени. Сравнение с TCP невозможно задать точно и оно предназначено для оценки порядка значений по интервалу времени и пропускной способности. Применимы также рекомендации параграфа 3.1.1 для таймеров.

Некоторые приложения с большим объемом данных могут отказаться от использования механизмов контроля перегрузок, полагаясь на передачу по пути с зарезервированной пропускной способностью (см. параграф 3.1.9). Это может быть приемлемо для некоторого подмножества сетевых сред, но не подходит в качестве безопасной практики работы в Internet. Когда трафик UDP от таких приложений попадает на пути Internet без резервирования пропускной способности, это может существенно влиять на остальной трафик в том же пути и даже вызывать коллапс перегрузки. Приложениям, поддерживающим неконтролируемое и неадаптивное поведение, не следует использовать его по умолчанию, а следует требовать от пользователя явно включать такой режим работы, а также следует проверять резервирование для приложения пропускной способности пути.

3.1.3. Приложения с малым объемом данных

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

Приложениям с небольшим объемом данных UDP следует сохранять контроль за своей передачей, не отправляя получателю в среднем более одной дейтаграммы UDP в течение интервала RTT. Подобно рекомендациям [RFC1536], приложению следует поддерживать оценку RTT для любого адресата, с которым он взаимодействует, используя методы, указанные в параграфе 3.1.1.

Некоторые приложения не могут поддерживать надежную оценку RTT до адресата. Для таких приложений не нужно или невозможно использование протокольных таймеров для измерения RTT (параграф 3.1.1). Следует рассмотреть два случая, описанных ниже.

  1. Число дейтаграмм UDP между приложениями слишком мало для статистически точной оценки RTT, но можно отслеживать надежность доставки (параграф 3.3). Такие приложения могут использовать предопределенный интервал передачи, который экспоненциально увеличивается в случае потери пакетов. TCP задает начальный интервал в 1 секунду [RFC6298] и это значение рекомендуется как начальное для приложений UDP. Некоторые приложения с очень малым объемом данных (такие как SIP [RFC3261] и GIST9 [RFC5971]) используют интервал в 500 мсек и меньше, что во многих случаях может быть проблематичным. Как и в предыдущем случае начальный интервал не является максимально возможным тайм-аутом (параграф 3.1.1).

  2. Приложение не может поддерживать оценку RTT для адресата, поскольку тот не передает пакетов. Таким приложениям не следует передавать более 1 дейтаграммы UDP каждые 3 секунды и следует по возможности передавать еще реже, поскольку сокращение интервала во многих случаях будет создавать проблемы. Отметим, что скорость передачи здесь должна быть более умеренной, нежели в предыдущих случаях, поскольку отсутствие возвратного трафика не позволяет детектировать потерю пакетов (т. е. перегрузку) и приложение не может снижать экспоненциально скорость отправки.

3.1.4. Приложения с двухсторонними коммуникациями

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

3.1.5. Влияние RTT и учета потерь на контроль перегрузок

Транспорт, подобный TCP, SCTP и DCCP, обеспечивает своевременное обнаружение перегрузки, что ведет к незамедлительному снижению максимальной скорости передачи в случае перегрузки. Эта реакция обычно наблюдается в интервале 1-2 RTT после обнаружения потери или перегрузки. Приложениям UDP следует реализовать схему контроля перегрузок, обеспечивающую быструю реакцию на сигналы перегрузки (например, снижением скорости в следующем интервале RTT после сигнала).

Работа алгоритмов контроля перегрузок для UDP может существенно отличаться от TCP. Это включает элементы контроля перегрузки, реагирующие на временные рамки, соответствующие приложению, которые не могут эффективно работать в модели TCP с изменением скорости в каждом интервале RTT.

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

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

Контролю перегрузок, разработанному для UDP, следует как можно быстрее реагировать на индикацию перегрузки, а также следует учитывать при выборе новой скорости частоту потерь и время отклика. Реализованной схеме контроля перегрузок следует обеспечивать использование пропускной способности (емкости), сравнимое по порядку величины с TCP, чтобы не истощать другие потоки на том же пути с узким местом.

3.1.6. Синхронизация и снижение пиков

Приложениям UDP следует поддерживать механизм регулировки пиков при передаче пакетов приложения в сеть. Многие реализации TCP и SCTP обеспечивают механизмы, препятствующие создание отправителем продолжительных пиков передачи со скоростью линии, поскольку это вызывает преждевременные потери в приложениях, трафик которых проходит через те же узкие места в сети. Показано, что использование синхронизации с TCP [ALLMAN] улучшает сосуществование потоков TCP с другими потоками. Необходимость избегать чрезмерных пиков при передаче следует также отмечать в спецификации приложений (например, [RFC7143]).

Даже небольшие потоки UDP могут выигрывать от синхронизации пакетов. Например, приложению, передающему 3 копии пакета для отказоустойчивости, рекомендуется отправлять эти пакеты за несколько интервалов RTT для снижения вероятности потери всех трех в одном случае перегрузки (или иного события, такого как сильный пик).

3.1.7. Явный контроль перегрузок

Приложения Internet могут использовать явный контроль перегрузки (ECN) [RFC3168] для улучшения поддерживаемых ими услуг [RFC8087]. Транспорт Internet, такой как TCP, поддерживает множество механизмов, потребных для использования ECN. Для работы ECN применяются специальные коды ECT(0) или ECT(1) в заголовках IP передаваемых пакетов. Это указывает поддерживающим ECN сетевым устройствам (маршрутизаторы и пр.), что они могут помечать (устанавливать код CE10) пакеты IP вместо их отбрасывания для сигнализации о наступающей перегрузке.

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

  • Отправитель должен обеспечить метод определения (например, согласование) способности соответствующего приложения обеспечивать отклики ECN для используемого с совместимым методом ECN.

  • Получатель, разрешающий использование ECN для порта UDP, должен проверять поле ECN для каждой принятой на этом порту дейтаграммы UDP.

  • Принимающее приложение должно обеспечивать отклики на перегрузку передающему приложению. Оно должно сообщать о наличии дейтаграмм, принятых с маркировкой CE с помощью механизма, помещающего эти сведения о перегрузке в пакеты для передающего приложения. Отклики могут также сообщать о наличии пакетов ECT(1) и ECT(0)/не-ECT [RFC7560]. Методы для TCP заданы в [RFC3168] и [RFC7560].

  • Передающее дейтаграммы с поддержкой ECN приложение должно обеспечивать должную реакцию на получение откликов, указывающий возникновение перегрузки. Это должно вызывать снижение скорости передачи механизмом контроля перегрузок UDP (параграф 3.1) не слабее реакции TCP в таких же условиях.

  • Отправителю следует детектировать сетевые пути без корректной поддержки поля ECN и при их обнаружении умеренно реагировать на перегрузку или даже отказываться от применения ECN [RFC8087]. Метод должен быть устойчив к изменениям на сетевых путях, которые могут происходить в течение сессии.

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

В [RFC6679] даны рекомендации и пример такой поддержки в описании метода, позволяющего использовать ECN для приложений UDP, применяющих протокол RTP (Real-Time Protocol). Приложениям, не способным обеспечить такой набор механизмов, но желающим воспользоваться преимуществами ECN, настоятельно рекомендуется использовать транспортный протокол с поддержкой ECN (например, TCP).

3.1.8. Модель дифференцированных услуг

Приложение UDP может применять модель качества обслуживания (Quality of Service или QoS) с дифференцированными услугами (DiffServ). Для включения дифференцированной обработки отправитель UDP устанавливает код в поле DSCP [RFC2475] передаваемых в сеть пакетов. Обычно пара портов отправителя и получателя UDP будет задавать одно значение DSCP для всех пакетов потока, но можно использовать несколько DSCP, как описано ниже. Значение DSCP может выбираться из небольшого набора фиксированных значений (коды селекторов класса), из рекомендуемых спецификацией поэтапного поведения (Per Hop Behavior или PHB) значений или из локального набора, имеющего смысл в сети с поддержкой DiffServ. В общем случае пакеты могут проходить через множество сетей между отправителем и получателем.

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

В [RFC7657] описано влияние использования DSCP и даны рекомендации по применению разных кодов DSCP в одном кортеже (five-tuple) с адресами и номерами портов отправителя и получателя, а также используемым транспортном протоколом (в данном случае UDP или UDP-Lite). В частности, рассмотрено влияние транспортного протокола с контролем перегрузок и гарантиями доставки (повтор передачи, восстановление порядка). Использование нескольких DSCP может приводить к нарушению порядка за счет расширения набора ресурсов пересылки, используемых отправителем. Это может также повысить вероятность истощения ресурсов или отказов.

3.1.9. QoS, заранее предоставленная или зарезервированная полоса

IETF обычно определяет протоколы для использования в модели Best Effort General Internet. Иногда уместно задавать протоколы с иной применимостью. Приложение UDP может использовать схему QoS с интеграцией услуг, которая обычно доступна в контролируемых средах (например, внутри административного домена или между согласованными доменами). Предназначенным для Internet приложениям не следует предполагать поддержку механизмов QoS в используемых сетях и поэтому нужно обеспечивать контроль перегрузок, восстановление при ошибках и т. п. В случаях, когда путь через сеть не обеспечивает нужного сервиса.

Для некоторых приложений UDP предполагается использование лишь на путях, обеспечивающих заранее выделенную или резервируемую динамически (например, с помощью протокола RSVP11) пропускную способность. Групповые приложения тоже используют выделенную заранее емкость (например, развертывание IPTV в сети доступа). Эти приложения могут отказаться от реализации механизмов контроля перегрузок, передавая трафик лишь по путям, где обеспечивается для них достаточная пропускная способность. Это может подходить для ограниченного множества сетевых сред, но не обеспечивает безопасного применения в Internet. Приложениям, выбравшим такой подход, следует подробно и аккуратно описывать процедуры обеспечения и управления, которые обеспечивают нужное поведение.

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

Приложения, разработанные для контролируемых сред (см. параграф 3.6) могут быть способны использовать функции управления сетью для детектирования вызванной ими перегрузки и подобающей реакции на это. Если трафик таких приложений выходит на пути Internet без обеспечения пропускной способности, это может существенно снизить производительность других приложений, использующих тот же путь, и даже вызывать коллапс насыщения. Протоколам, разработанным для таких сетей, следует поддерживать на периметре сети механизмы, предотвращающие выход трафика на пути Internet без обеспечения (см., например, [RFC7510]). Для защиты других приложений, использующих тот же путь, следует также реализовать подходящий «выключатель», как описано в параграфе 3.1.10.

Предполагается, что спецификации IETF, предназначенные для контролируемых сред, будут включать заявление о применимости, ограничивающее сферу применения (см. параграф 3.6).

3.1.10. Механизмы выключателей

Транспортный «выключатель» (circuit breaker) — это автоматический механизм, применяемый для оценки вызываемой потоком перегрузки и прерывания (или значительного снижения скорости) потока при обнаружении чрезмерного насыщения [RFC8084]. Это служит мерой защиты от коллапса насыщения (истощение ресурсов, доступных другим потокам) особенно для неоднородной среды Internet с трудно предсказуемым трафиком.

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

В [RFC8084] приведены рекомендации и примеры использования выключателей, а в [RFC8083] описаны выключатели для RTP.

Приложениям, используемым в Internet, следует реализовать транспортные выключатели, если в них нет механизмов контроля перегрузок или объем передаваемых данных достаточно велик (см. параграф 3.6). Транспортные выключатели могут реализовать все приложения [RFC8084] и рекомендуется рассматривать реализацию по крайней мере медленно действующего выключателя для защиты в крайних ситуациях.

3.1.11. Туннели UDP

Растет популярность использования UDP как туннельного протокола [INT-TUNNELS], где конечные точки туннеля инкапсулируют пакеты других протоколов в дейтаграммы UDP и передают в другую конечную точку туннеля, которая декапсулирует дейтаграммы UDP и пересылает содержащиеся в них исходные пакеты. Одним из примеров такого протокола является Teredo [RFC4380]. Туннели создают виртуальные каналы, которые представляются прямым соединением между физически разнесенными точка топологии Internet, и могут служит для создания виртуальных (частных) сетей. Применение UDP как туннельного протокола привлекательно в случаях, когда исходный протокол не поддерживается промежуточными устройствами на пути через сеть, поскольку многие промежуточные устройства обеспечивают передачу UDP.

Хорошо реализованные туннели обычно не видны конечным точкам, которые передают трафик по путям с туннельными каналами. С другой стороны, для маршрутизаторов на пути туннеля UDP (т. е. между конечными точками туннеля) трафик туннеля является обычным потоком UDP, а точки инкапсуляции и декапсуляции выглядят как обычные приложения UDP. Поэтому другие потоки могут разделять путь с одним или несколькими туннелями UDP и нужно учитывать контроль перегрузок.

Необходимость развертывания для туннеля UDP определенного механизма контроля перегрузок определяют два фактора — применение для передачи туннельного трафика протокола IP и соответствие объема трафика UDP, создаваемого схемой туннелирования общему объему трафика в туннеле.

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

Однако, если известно об отсутствии контроля перегрузок для туннельного трафика IP, рекомендуется ограничивать влияние этого трафика на другие потоки, использующие тот же путь. Рассмотрение туннелей с групповым трафиком IP приведено в параграфе 4.1.

Ниже более подробно описаны возможные варианты.

  1. Туннель создает трафик UDP, объем которого соответствует объему полезного трафика (payload) IP, для которого обеспечивается контроль перегрузки.

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

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

  2. Туннель создает трафик UDP, объем которого соответствует объему полезного трафика (payload), для которого не обеспечивается контроль перегрузки.

    Это может возникать, например, при инкапсуляции в UDP некоторых протоколов канального уровня (не все такие протоколы имеют контроль перегрузок). Поскольку неизвестна реакция на потери пакетов не относящегося к IP туннельного трафика, туннелю UDP следует реализовать подходящий механизм контроля перегрузок или механизм автоматического выключения для туннельного трафика. Поскольку туннели обычно служат для передачи больших объемов трафика и включают промежуточные маршрутизаторы, применимы рекомендации параграфа 3.1.2.

  3. Туннель создает трафик UDP, объем которого не соответствует объему полезного трафика (payload).

    Примерами могут служить туннели UDP, передающие данные с постоянной скоростью, увеличивая ее в результате потери при упреждающей корректировке ошибок (Forward Error Correction) или используя иные варианты контроля передачи. Такое специализированное применение UDP для туннелирования выходит за рамки общих рекомендаций этого документа. При создании таких специализированных туннелей следует внимательно относится к контролю перегрузок, а также следует рассмотреть применение механизмов выключателей.

Тип инкапсулированных данных может быть указан портом UDP, EtherType или номером протокола IP. Туннелям следует поддерживать механизмы ограничения типов потоков, которые могут передаваться через туннель. Например, туннелю UDP, предназначенному для трафика IP, следует отфильтровывать на входе пакеты иных протоколов. Это особенно важно при использовании базовой инкапсуляции (например, с использованием EtherType). Для таких туннелей следует обеспечивать механизм ограничения типов трафика, которые разрешено инкапсулировать в данный туннель (см. [INT-TUNNELS]).

Разработка механизмов туннелирования требует значительно больше опыта, нежели для других приложений UDP, поскольку туннели обычно должны быть прозрачны для передающих через них данные конечных точек, поэтому туннель должен корректно эмулировать поведение канала IP [INT-TUNNELS]. Например:

  • требования по переносу или инкапсуляции кодов ECN [RFC6040];

  • использование поля IP DSCP конечными точками туннеля [RFC2983];

  • учет инкапсуляции при проектировании туннелей [ENCAP];

  • использование сообщений ICMP [INT-TUNNELS];

  • обработка фрагментации и размера пакетов для туннелей [INT-TUNNELS];

  • использование порта отправителя в туннелях, рассчитанных на маршрутизацию ECMP12 (параграф 5.1.1);

  • потребность в рекомендациях по защите заголовков [INT-TUNNELS] и использованию контрольных сумм для туннелей IPv6 (параграф 3.4.1);

  • поддержка эксплуатации и обслуживания [INT-TUNNELS].

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

3.2. Рекомендации по размеру сообщений

Фрагментация IP снижает эффективность и надежность коммуникаций в Internet. Потеря одного фрагмента ведет к утрате всего фрагментированного пакета, поскольку даже при получении всех остальных фрагментов собрать и доставить исходный пакет невозможно. Эта проблема фрагментации присуща как IPv4, так и IPv6.

Кроме того, некоторые трансляторы адресов (network address translator или NAT) и межсетевые экраны отбрасывают фрагменты IP. Трансляция сетевых адресов в NAT возможна лишь для полных пакетов IP, а правила некоторых межсетевых экранов требуют проверки пакетов IP целиком. Некоторые устройства NAT и межсетевые экраны просто не включают требуемых для сборки фрагментов средств и поэтому отбрасывают фрагменты. В [RFC4963] рассмотрены также другие проблемы, связанные с фрагментацией IPv4.

В силу отмеченных выше причин приложению не следует передавать дейтаграммы UDP, которые приводят в пакетам IP размером больше MTU13 на пути к получателю. Поэтому приложению следует использовать данные о MTU на пути от уровня IP или самостоятельно реализовать определение MTU на пути (Path MTU Discovery или PMTUD) [RFC1191] [RFC1981] [RFC4821] для определения возможности передачи сообщений без фрагментации.

Однако сообщения ICMP, служащие для определения MTU на пути, активно фильтруются промежуточными устройствами (включая межсетевые экраны) [RFC4890]. Когда путь включает туннели, некоторые устройства на входе туннеля отбрасывают сообщения ICMP от сетевых устройств, через которые проходит туннель, препятствуя их доставке в конечную точку UDP.

Механизм PLPMTUD14 [RFC4821] не опирается на поддержку в сети сообщений ICMP и более устойчив к отказам, нежели PMTUD. Он также не чувствителен к «черным дырам» ICMP. Для работы PLPMTUD требуется изменение способа использования транспорта как для передачи пробных пакетов, так и для учета потери или успешного прохождения проб. Это не только меняет алгоритм PMTU, но и влияет на восстановление потерь, контроль перегрузки и т. п. Эти обновленные механизмы могут быть реализованы в ориентированном на соединения транспорте (например, TCP, SCTP, DCCP), не не являются частью UDP. Данный тип обратной связи обычно отсутствует в однонаправленных приложениях.

Поэтому PLPMTUD вносит дополнительные требования к приложениям UDP, желающим применять этот метод. Особенно важно это для туннелей UDP, поскольку связанные с передачей пробных пакетов издержки должны учитываться и могут потребовать в туннеле дополнительного механизма контроля перегрузок (параграф 3.1.11), а также усложнения пути данных в декапсуляторе туннеля.

Приложениям, не мспользующим PMTU или PLPMTUD, следует избегать отправки дейтаграмм UDP, которые будут приводить к передаче пакетов IP, размер которых превысит MTU. Поскольку реальное значение MTU для пути не известно, таким приложениям следует передавать сообщения, которые короче принятого по умолчанию эффективного значения MTU для передачи (EMTU_S в [RFC1122]). Для IPv4 EMTU_S будет меньшим из значение 576 байтов и MTU первого этапа пересылки [RFC1122], для IPv6 EMTU_S будет 1280 байтов [RFC2460]. Эффективное значение PMTU для подключенного напрямую адресата (без маршрутизаторов на пути) будет определяться заданным для интерфейса значением MTU, которое может быть меньше разрешенного на канале максимума. Передача дейтаграмм UDP минимального размера не эффективна для путей, поддерживающих большие PMTU, и это служит другой причиной реализации определения PMTU.

Для определения подходящего размера данных UDP приложения должны вычесть размер заголовка IP (вместе с необязательными заголовками IPv4 или заголовками расширения IPv6), а также размер заголовка UDP (8 байтов) из значения PMTU. Этот размер, называемый максимальным размером сегмента (Maximum Segment Size или MSS), можно получить от стека TCP/IP [RFC1122].

Приложения, не передающие сообщений размером больше эффективного PMTU для IPv4 или IPv6, могут не реализовать описанные выше механизмы. Отметим, что наличие туннелей может дополнительно снизить эффективное значение PMTU [INT-TUNNELS], поэтому реализация определения PMTU является предпочтительным решением.

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

3.3. Рекомендации по надежной доставке

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

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

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

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

Важно отметить, что интервал, в котором меняется порядок пакетов или могут поступать дубликаты, может быть очень большим. Еще важнее отсутствие четкой верхней границы для таких интервалов. В [RFC793] задана максимальная задержка, возможная для сегмента TCP — максимальный срок жизни сегмента (Maximum Segment Lifetime или MSL) — 2 минуты. RFC, определяющих MSL для других транспортных протоколов или IP, не существует. Значение MSL для TCP достаточно консервативно, чтобы его следовало применять в других протоколах, включая UDP. Поэтому приложениям следует быть устойчивыми к приему задержанных пакетов и дубликатов в течение двухминутного интервала.

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

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

3.4. Рекомендации по контрольным суммам

Заголовок UDP включает необязательное 16-битовое поле контрольной суммы с дополнением до 1, которое служит для контроля целостности. Эти проверки не являются строгими с точки зрения кодирования или криптографии и не предназначены для обнаружения ошибок на физическом уровне или умышленного изменения дейтаграмм [RFC3819]. Разработчиками приложений, где важна целостность, следует реализовать дополнительные проверки, например с использованием CRC15 или криптографического хэш-кода (с ключом или без него), включаемого в данные для контроля целостности всего объекта или файла, передаваемого с помощью транспорта UDP.

Контрольная сумма UDP предоставляет статистическую гарантию отсутствия повреждений данных в процессе передачи. Это также позволяет получателю убедиться, что пакет предназначен именно ему, поскольку в контрольной сумме учитывается адрес IP, номер порта и протокола, а также подтверждается отсутствие дополнений или отсечки данных, поскольку размер учитывается в контрольной сумме. Поэтому контрольная сумма защищает приложение от получения поврежденных или дополненных в процессе передачи данных. Более подробное описание проверок на основании поля контрольной суммы приведено в параграфе 3.1 [RFC6396].

Приложениям следует включать контрольные суммы UDP [RFC1122]. Для IPv4 [RFC768] имеется опция запрета контрольной суммы с установкой в поле заголовка значения 0. Приложениям разрешено отвергать дейтаграммы UDP с нулевым значением контрольной суммы [RFC1122].

При использовании UDP с протоколом IPv6 контрольная сумма UDP служит для защиты заголовков IPv6 и UDP (в заголовке IPv6 нет контрольной суммы) и должна использоваться в соответствии с [RFC2460]. В определенных условиях приложениям UDP разрешается использовать режим с нулевой контрольной суммой (UDP zero-checksum) в протоколах туннелирования (см. параграф 3.4.1).

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

3.4.1. Нулевая контрольная сумма UDP для IPv6

В [RFC6935] задан метод, позволяющий использовать нулевую контрольную сумму UDP с туннельными протоколами при условии соблюдения требований [RFC6936]. Приложение должно реализовать механизмы и/или ограничения на использование при включении этого режима. Это включает задание сферы действия и мер по предотвращению утечки трафика в другие приложения UDP (см. Приложение A и параграф 3.6). Эти дополнительные требования к использованию нулевых контрольных сумм IPv6 UDP отсутствуют в IPv4, поскольку заголовок IPv4 проверяет информацию, не защищенную в пакетах IPv6. Основные требования перечислены ниже.

  • Использование контрольной суммы UDP с IPv6 должно быть включено по умолчанию во всех реализациях [RFC6935]. Принимающая сторона должна разрешать использование режима UDP zero-checksum для IPv6 лишь на портах UDP, где это специально разрешено.

  • Приложение, поддерживающее контрольную сумму, отличную от [RFC2460], должно выполнять все требования к реализации из раздела 4 в [RFC6936] и требования к использованию из раздела 5 в [RFC6936].

  • Приложение UDP должно проверять действительность адресов IPv6 для отправителя и получателя по всех пакетах с нулевой контрольной суммой UDP и должно отбрасывать пакеты при несоответствии адресов. Для защиты от ошибочной доставки в новые схемы инкапсуляции следует включать контроль целостности на транспортном уровне с проверкой по меньшей мере заголовков IPv6 и UDP, а также промежуточного заголовка инкапсуляции при его наличии [RFC6936].

  • Одним из способов, помогающих выполнить требования [RFC6936], может быть ограничение использования таких туннелей, например, путем ограничения трафика в сети оператора, как описано в параграфе 3.6. Инкапсуляция, заданная для MPLS в UDP [RFC7510], использует такой подход.

Как и в IPv4, приложениям IPv6, выключившим контрольную сумму UDP, недопустимо предполагать корректность принятых данных и они должны обеспечивать корректное поведение при получении чужих или поврежденных дейтаграмм.

Дейтаграммы IPv6 с нулевой контрольной суммой UDP не будут пропускаться промежуточными устройствами, проверяющими контрольную сумму в соответствии с [RFC2460] или обновляющими поле контрольной суммы UDP (например, трансляторами NAT и межсетевыми экранами). Для смены такого поведения потребуется обновление промежуточных устройств с целью корректной обработки дейтаграмм с нулевой контрольной суммой UDP. Для обеспечения сквозной отказоустойчивости приложения, которые могут работать через Internet, должны обеспечивать возможность работы с контрольными суммами при изменении пути с перенаправлением на участки, где промежуточные устройства отбрасывают дейтаграммы IPv6 с нулевой контрольной суммой UDP.

3.4.2. UDP-Lite

Особый класс приложений может получать преимущество в результате доставки частично поврежденных данных вместо их отбрасывания при работе по каналам с большим числом ошибок. Такие приложения устойчивы к повреждению данных и могут выбрать облегченный протокол UDP-Lite (Lightweight User Datagram Protocol) [RFC3828] вместо базового UDP. Таким приложениям следует выполнять рекомендации по контролю перегрузок и другие рекомендации раздела 3.

UDP-Lite меняет поле размера данных UDP (payload length) на область покрытия контрольной суммой (checksum coverage length), а в остальном протоколы семантически идентичны. Интерфейс UDP-Lite отличается от интерфейса UDP добавлением одной опции, указывающей область покрытия контрольной суммы. На стороне отправителя это задает учитываемые в контрольной сумме данные (остальная часть считается нечувствительной к ошибкам — error-insensitive part). По умолчанию контрольная сумма UDP-Lite учитывает всю дейтаграмму, но приложение может динамически менять размер учитываемой области, например, для повышенной защиты некоторых сообщений. UDP-Lite всегда проверяет доставку нужному получателю, т. е. всегда проверяется корректность полей заголовка. Ошибки в нечувствительной части не будут вызывать отбрасывания дейтаграммы получателем. Поэтому приложениям UDP-Lite недопустимо предполагать корректность данных в нечувствительной к ошибкам части дейтаграмм UDP-Lite.

Отправителю UDP-Lite следует выбирать минимальное покрытие контрольной суммой, охватывающее все чувствительные к ошибкам области данных. Например, приложения, использующие протокол RTP [RFC3550], очевидно захотят защитить от повреждений заголовок RTP. По-возможности приложения должны также вводить свои подходящие проверки для протокольной информации, передаваемой в незащищенной части данных UDP-Lite (например, встраивать CRC).

Получатель UDP-Lite должен задать порог минимального покрытия для входящих пакетов, который должен быть не меньше минимального покрытия, используемого отправителем [RFC3828]. Получателю следует выбирать достаточно высокий порог для блокирования пакетов со слишком малым покрытием контрольной суммы. Это может быть фиксированное или согласуемое приложением значение. UDP-Lite не поддерживает механизмов согласования области покрытия для контрольной суммы между отправителем и получателем, поэтому приложение должно делать это самостоятельно.

Приложения, использующие UDP-Lite, также могут сталкиваться с потерей пакетов. Улучшения, предлагаемые UDP-Lite, основаны на том, что канал может «перехватывать» заголовок UDP-Lite для корректной идентификации требуемого частичного покрытия. При использовании туннелей и/или шифрования это может приводить к тому, что дейтаграммы UDP-Lite будут обрабатываться так же, как дейтаграммы UDP, т. е. пакеты будут теряться. Фрагментация IP также может препятствовать особой обработке дейтаграмм UDP-Lite и это является еще одним основанием для предотвращения фрагментации IP (параграф 3.2).

UDP-Lite поддерживается в протокольных стеках некоторых конечных точек. Текущая поддержка в промежуточных устройствах достаточно слаба, поскольку UDP-Lite использует свой номер протокола в IPv4 и значение IPv6 next header (отличные от UDP). В результате лишь немногие промежуточные устройства способны интерпретировать UDP-Lite и выполнять требуемые действия при пересылке пакетов. Это делает протокол UDP-Lite менее подходящим для работы через Internet, пока не будет обеспечена достаточная поддержка UDP-Lite в промежуточных устройствах.

3.5. Рекомендации по работе с промежуточными устройствами

Трансляторы NAT и межсетевые экраны являются примерами промежуточных устройств (middlebox), которые могут присутствовать на сквозном пути. Промежуточные устройства обычно выполняют функции, требуемые для поддержки состояний на уровне потока. Для ориентированных на соединения протоколов (таких как TCP) , промежуточные устройства отслеживают и анализируют данные управления соединениями, а также создают и уничтожают должным образом состояния на уровне потока. Для протоколов без явных соединений, таких как UDP, такой подход невозможен. Поэтому промежуточные устройства могут создавать состояния на уровне потока, когда они видят пакет, соответствующий (по локальным критериям) новому потоку, и удаляют состояние по истечении некоторого времени в течение которого не наблюдается пакетов, относящихся к тому же потоку.

В зависимости от конкретных функций, выполняемых промежуточным устройством, оно может вносить временные зависимости, ограничивающие типы обмена трафиком UDP через это устройство. Например, трансляторы NAT и межсетевые экраны обычно задают часть пути на одной стороне как внутреннюю для обслуживаемого домена, а другую — как внешнюю. Состояние на уровне потока обычно создается при прохождении первого пакета изнутри наружу и при наличии такого состояния трансляторы NAT и межсетевые экраны будут пересылать трафик. Обратный трафик, поступающий после завершения срока действия потока, будет отбрасываться, как и другой трафик извне.

Многие приложения, использующие UDP, работают через промежуточные устройства без использования дополнительных механизмов. Одним из примеров является система доменных имен (Domain Name System или DNS), которая использует строгую модель «запрос-отклик», где операция обычно длится несколько секунд.

В других приложениях могут возникать отказы, когда промежуточные устройства будут разрушать состояние, связанное с сессией приложения, если приложение какое-то время не передает трафика UDP. Приложениям следует аккуратно обрабатывать такие отказы и реализовать механизмы восстановления состояний и сессий прикладного уровня. Для некоторых приложений, таких как media-потоки, очень нежелательна такая ресинхронизация, поскольку она может вызывать заметные для пользователя проблемы воспроизведения. Такие специализированные приложения могут периодически передавать сообщения keep-alive для обновления состояний на промежуточных устройствах (например, [RFC7675]). Важно отметить, что сообщения keep-alive не рекомендуются в общем случае, поскольку они не нужны для большинства приложений и могут потреблять заметный объем системных и сетевых ресурсов.

Приложению, которому нужно реализовать сообщения keep-alive для поддержки нужного сервиса UDP через промежуточные устройства, не следует передавать эти сообщения чаще 1 раза за 15 секунд и по-возможности следует использовать больший интервал. Для тайм-аута состояний на уровне потока UDP для произвольных промежуточных устройств общего значения не задано. Трансляторам NAT требуется тайм-аут в 2 минуты или больше [RFC4787]. Однако эмпирические данные показывают, что значительная часть развернутых промежуточных устройств использует более короткий тайм-аут. Протокол интерактивной организации соединений ICE (Interactive Connectivity Establishment) [RFC5245] использует значение 15 секунд. При развертывании приложения в контролируемой среде разработчикам следует изучить возможности целевой среды в плане использования более длинных интервалов и наличия механизмов явного управления тайм-аутами на промежуточных устройствах, например с помощью протокола управления портами PCP (Port Control Protocol) [RFC6887], MIDCOM (Middlebox Communications) [RFC3303], NSIS (Next Steps in Signaling) [RFC5973] или UpnP (Universal Plug and Play) [UPnP]. Приложениям рекомендуется вносить небольшие случайные вариации (jitter) для интервала передачи сообщений keep-alive с целью предотвращения ненужной синхронизации между сообщениями keep-alive от разных хостов [RFC7675].

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

Сообщения keep-alive не рекомендуются для общего применения, они не требуются для многих приложений и могут поглощать много ресурсов. Например, когда устройству с батарейным питанием нужно в течение длительного времени поддерживать соединение с незначительным трафиком, частота отправки сообщений keep-alive может стать определяющим фактором энергопотребления в зависимости от базовой сетевой технологии.

Поскольку многие промежуточные устройства требуют передачи сообщений keep-alive для соединений TCP с частотой много ниже, нежели нужно для UDP, это часто служит основанием для отказа от UDP в пользу TCP. С другой стороны, имеются сведения о том, что прямые коммуникации через промежуточные устройства, например, с применением ICE [RFC5245], реже бывают успешными для TCP, нежели для UDP. Компромиссы при выборе транспортного протокола, особенно при наличии промежуточных устройств, требуют тщательного анализа.

Приложения UDP, которые могут быть развернуты в Internet, должны проектироваться с учетом многочисленных вариантов поведения промежуточных устройств и, хотя UDP не организует прямых соединений, промежуточные устройства часто поддерживают состояние для каждого потока UDP. При наличии множества потоков UDP для таких состояний могут потребоваться значительные ресурсы и этом может менять поведение промежуточного устройства при обработке последующих пакетов (для защиты внутренних ресурсов или предотвращения злоупотреблений). Вероятность отказов в пути может возрастать при использовании приложением множества параллельных потоков UDP (см. рекомендации параграфа 5.1.2 для работы через множество портов).

3.6. Ограничение применимости и контролируемые среды

Для спецификаций приложений IETF, использующих протокол UDP, выделено 2 варианта работы, описанных ниже.

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

Контролируемая среда. Протокол, инкапсуляция или туннель может быть разработан для применения только внутри контролируемой среды. Например, это может быть приложение, созданное для использования в сети оператора, которое развертывается в сети одного оператора или нескольких взаимодействующих смежных операторов. Трафик таких приложений может быть управляемым для предотвращения перегрузок без использования встроенных механизмов, которые нужны при работе через Internet. Приложения, рассчитанные на ограниченное применение, могут использовать преимущества определенного оборудования (например, операторского) или свойства базовых протоколов в подсети, где приложение применяется.

Спецификациям, предназначенным для ограниченного применения или контролируемых сред, следует как в ограниченном развертывании обеспечивается защита, эквивалентная защите протоколов, предназначенных для работы в Internet (например, реализация на основе обширного опыта развертывания конкретных методов, обеспечивающих свойства, которых нельзя ожидать от обычного оборудования Internet, и устойчивости MPLS к повреждению заголовков, помогающие использовать дополнительную проверку целостности UDP [RFC7510]).

В спецификациях IETF, нацеленных на контролируемую среду, предполагаются наличие заявления о применимости, которое ограничивает трафик приложения контролируемой средой, и предполагается описание методов предотвращения выхода поврежденных пакетов за пределы контролируемой среды (см., например, раздел 5 в [RFC7510]).

4. Рекомендации по групповой адресации в UDP

Этот раздел дополняет предыдущий рекомендациями, связанными с групповой и широковещательной адресацией в UDP.

Групповая и широковещательная передача [RFC1112] обычно использует транспорт UDP, хотя возможно применение и других транспортных протоколов, например, UDP-Lite.

В настоящее время имеются две модели групповой доставки — Any-Source Multicast (ASM) [RFC1112] и Source-Specific Multicast (SSM) [RFC4607]. Члены групп ASM будут получать все данные, переданные в группу любым отправителем, тогда как SSM ограничивает дерево распространения единственным источником.

Специальные классы приложений также применяют UDP для групповой и широковещательной рассылки IP [RFC919]. Устройство таких приложений требует опыта, выходящего за пределы простых рекомендаций для индивидуальной передачи, поскольку такие отправители могут передавать пакеты очень большому числу адресатов по весьма разнородным путям, что значительно усложняет механизмы контроля перегрузок, управления потоками и гарантированной доставки.

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

В IETF определена схема гарантированной групповой доставки [RFC3048] и несколько «строительных блоков» в помощью разработчикам групповых приложений, например, [RFC3738] и [RFC4654].

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

Большинство туннелей UDP, передающих групповой трафик IP, используют туннельную инкапсуляцию с индивидуальным адресом получателя, например, Automatic Multicast Tunneling [RFC7450]. Они должны выполнять те же требования, которые предъявляются к туннелям с индивидуальным трафиком (см. параграф 3.1.11). Имеются варианты развертывания и решения, где внешний заголовок туннеля UDP содержит групповой адрес получателя [RFC6513]. Такие решения обычно развертываются в контролируемых средах внутри одного административного домена или между доменами с согласованной пропускной способностью путей, поэтому контроль перегрузок является необязательным, но рекомендуется применять выключатели (circuit breaker) для обеспечения того или иного уровня обслуживания в случае выхода за пределы зарезервированной пропускной способности (например, в результате ошибки при настройке).

4.1. Рекомендации по контролю перегрузок

Механизмы контроля перегрузок для индивидуального трафика зачастую не подходят для групповых услуг или просто не могут работать с большими multicast-деревьями, поскольку им нужна двухсторонняя связь и скорость приспосабливается к условиям пути через сеть к одному получателю. Деревья группового распространения могут включать большое число адресатов, что ограничивает возможности каналов возврата в основной полосе для контроля скорости передачи. А отношения «один со многими» в деревьях группового распространения препятствуют адаптации скорсоти к требованиям отдельных получателей. По это причине генерация совместимых с TCP агрегированных потоков данных для групповой передачи через Internet в естественной форме или через туннель, лежит в зоне ответственности приложения, реализующего контроль перегрузок.

Групповым приложениям следует поддерживать подобающий контроль перегрузок, который должен быть реализован с использованием механизмов, устойчивых к возможным неоднородностям дерева группового распространения и входящих в группу получателей. Неоднородность может проявляться в разном уровне потерь, разных задержках и/или возможностях реагировать на возникновение перегрузки в сети. Контроль перегрузок особенно важен для любой групповой сессии, где часть дерева распространения проходит через сеть доступа (например, домовый шлюз). В RFC определено для стиля контроля перегрузок, указанных ниже.

  • Контроль перегрузки на основе обратной связи, где отправитель получает от адресатов групповые или индивидуальные сообщения UDP, позволяющие оценить уровень перегрузки и скорректировать скорость отправки (например, [RFC5740],[RFC4654]). Групповые методы могут работать в более продолжительном временном масштабе, нежели индивидуальные (например, по причине большего значения группового RTT в неоднородной группе). Метод управления может отказаться от снижения скорости для всей multicast-группы в ответ на управляющее сообщение от одного получателя (например, отправитель может установить минимальную скорость и предложить связанному с перегрузкой получателю покинуть группу или выбрать для связанных с перегрузкой получателей передачу с меньшей скоростью и применением обычного (unicast) контроля перегрузки).

  • Управляемый получателем контроль перегрузок, который не требует передавать явных управляющих сообщений UDP (например, [RFC3738], [RFC5775]), а вместо этого отправитель распространяет данные через множество групп IP (например, используя каналы {S,G}). Каждый получатель определяет свой уровень перегрузки и контролирует скорость приема, используя лишь сообщения по включении и выходе из группы (join/leave) отправляемые на уровне управления сетью. Этот метод расширяется для больших групп.

Любой получатель с поддержкой групп может присоединиться к любой группе и получать ее трафик. Это может предполагать ограничение скорости для отдельных получателей или агрегата групповых услуг. Отметим, что на транспортном уровне нет способа предотвратить распространение сообщений о включении в группу (join) маршрутизатору следующего этапа пересылки.

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

4.1.1. Групповые приложения с большим объемом данных

Приложениям с большим объемом передачи данных (больше нескольких дейтаграмм UDP в интервале RTT) через групповое дерево распространения следует реализовать метод контроля перегрузок. В настоящее время рекомендуются методы IETF ALC16 [RFC5775], TFMCC17 [RFC4654], WEBRC18 [RFC3738], транспортный протокол NORM19 [RFC5740], FLUTE20 [RFC6726], RTP/RTCP21 [RFC3550].

Приложение может дополнительно реализовать другую схему контроля перегрузок, следуя рекомендациям [RFC2887] и используя схему [RFC3048]. Приложениям с большим объемом передачи, отказавшимся от реализации [RFC4654], [RFC5775], [RFC3738], [RFC5740], [RFC6726], [RFC3550], следует реализовать схему контроля перегрузок, которая обеспечит беспристрастность использования пропускной способности близкую к TCP по порядку значений.

В разделе 2 [RFC3551] сказано, что приложениям multimedia следует контролировать потерю пакетов для обеспечения приемлемых параметров. Потеря считается приемлемой, если поток TCP по тому же пути и с теми же условиями обеспечивает среднюю пропускную способность в разумном масштабе времени не ниже пропускной способности для потока UDP. Сравнение с TCP нельзя выполнить точно, но предполагается одинаковый порядок значений для временного интервала и пропускной способности.

4.1.2. Групповые приложения с небольшим объемом данных

Все рекомендации параграфа 3.1.3 применимы к групповым приложениям с небольшим объемом данных.

4.2. Рекомендации по размеру групповых сообщений

Групповому приложению не следует передавать дейтаграммы UDP, приводящие к пакетам IP, размер которых превышает эффективное значение MTU, как указано в разделе 3 [RFC6807]. Поэтому приложению следует использовать эффективные данные MTU от PIM22 [RFC6807] или реализовать самостоятельно механизм определения MTU на пути (см. параграф 3.2) для проверки поддержки нужного размера сообщений на пути к каждому получателю.

5. Рекомендации по программированию

Фактическим стандартом API для приложений TCP/является интерфейс сокетов [POSIX]. Некоторые платформы также предлагают приложениям возможность напрямую собирать и передавать пакеты IP через необрабатываемые сокеты (raw socket) или похожие средства. Это второй и более громоздкий метод использования UDP. Рекомендации этого документа охватывают методы, с помощью которых приложение может использовать UDP. Поскольку API сокетов применяется более широко, далее в этом разделе этот метод рассматривается более подробно.

Хотя API разработаны для UNIX в начале 1980-х годов, позднее появилось множество реализация для других ОС, поддерживающих протоколы IPv4 и IPv6 [RFC3493]. API сокетов UDP отличается от TCP в нескольких важных аспектах. Поскольку программистам приложений обычно лучше известны API сокетов TCP, в этом параграфе рассмотрены некоторые различия. В [STEVENS] приведены примеры использования API сокетов UDP.

Дейтаграммы UDP можно передавать и принимать напрямую без организации явного соединения. Используя API сокетов, приложения могут получать пакеты с разных IP-адресов через один сокет UDP. Некоторые серверы применяют это для одновременного обмена данными с несколькими удаленными хостами через один сокет. Многим приложениям требуется обеспечить прием пакетов с определенного адреса отправителя и такие приложения должны применять соответствующие проверки на прикладном уровне или явно запрашивать у операционной системы фильтрацию пакетов.

Многие операционные системы позволяют подключить сокет UDP, т. е. связать его с конкретной парой адресов и портов. Это похоже на соответствующую функциональность API сокетов TCP, однако в UDP эта операция локальна и служит лишь для упрощения локальных функций приема и передачи, а также фильтрации трафика для конкретных адресов и портов. Привязка сокета UDP не организует соединения и UDP не уведомляет удаленную сторону о привязке локального сокета UDP. Привязка сокета также помогает в настройке опций, влияющих на уровень UDP или IP, например, использование контрольной суммы UDP или опции IP Timestamp. В некоторых стеках привязка сокета также позволяет приложению получать уведомления при получении сообщения ICMP об ошибках для переданных через сокет пакетов [RFC1122].

Если приложение «клиент-сервер» выполняется на хосте с несколькими интерфесами IP, ему следует передавать все отклики UDP с IP-адресом отправителя, соответствующим адресу получателя в запросе ([RFC1122], параграф 4.1.3.5). Многие промежуточные устройства предполагают такое поведение и отбрасывают отклики, переданных с других адресов IP, как разъяснено в параграфе 3.5.

Получатель UDP может принять корректную дейтаграмму UDP без данных (payload). Отметим, что это отличается от возврата значения 0 из функции сокета read(), что в TCP указывает завершение соединения.

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

Когда приложение закрывает сокет TCP, SCTP или DCCP, транспортный протокол принимающего хоста возвращается в состояние TIME-WAIT. Это предотвращает ошибочную привязку задержанных пакетов закрытого соединения с последующим экземпляром соединения, использующего тот же адрес IP и порт. В протоколе UDP такой механизм не реализован, поэтому приложениям UDP требуется устойчивость к изменению порядка и задержке пакетов. Приложение может закрыть сокет или завершить работу, после чего другое приложение может принимать пакеты через тот же порт. В результате это приложение может получить «чужие» пакеты, задержанная в сети.

5.1. Использование портов UDP

Правила и процедуры поддержки реестра Service Name and Transport Protocol Port Number заданы в [RFC6335]. Рекомендации по использованию портов UDP приведены в [RFC7605].

Отправителю UDP не следует использовать выходной порт 0. Номер выходного порта, который нельзя определить по адресу или типу данных, обеспечивает защиту приемной стороны от атак со вставкой данных со стороны устройств, не находящихся на пути (off-path). Получателю UDP не следует привязываться к порту 0.

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

Приложениям следует включать проверки, обеспечивающие защиту от вставки данных со стороны устройств, не находящихся на пути, которая может исходить от неуполномоченных сторон. Стек TCP обычно использует случайный номер выходного порта для такой защиты [RFC6056] и приложениям UDP следует применять такой же подход. Промежуточные устройства и конечные системы часто используют допущения о номерах системных или пользовательских портов, поэтому рекомендуется применять случайные номера из диапазона Dynamic and/or Private Port. Установка «случайного» выходного порта также повышает уверенность в том, что полученные сообщения ICMP об ошибках исходят от систем на пути потока данных. Некоторые приложения (включая групповые) UDP используют предопределенное значение выходного порта, поэтому им нужен другой метод. Защита от атак off-path может также обеспечиваться с помощью случайных начальных значений полей протокола в области данных (payload) и проверкой их пригодности на приемной стороне (например, в RTP применяется случайный начальный номер и случайные смещения временных меток [RFC3550]).

При использовании групповой адресации маршрутизаторы IP выполняют проверку пересылки по обратному пути (reverse-path forwarding или RPF) для каждого группового пакета. Это обеспечивает защиту от вставки данных off-path, ограничивая возможности подмены адреса отправителя. При подключении получателя к группе и фильтрации по адресам отправителя проверяется IP-адрес источника. Это происходит всегда при использовании канала SSM {S,G}.

5.1.1. Использование UDP для энтропии выходного порта и метки потока IPv6

Некоторые приложения используют заголовки дейтаграмм UDP в качестве источника энтропии для сетевых устройств, реализующих ECMP [RFC6438]. Туннельные приложения UDP, нацеленные на такое использование, инкапсулируют внутренний заголовок с помощью UDP, где выходной порт UDP образует часть энтропии, которая может служить для балансирования пересылки сетевого трафика устройствами ECMP. Передающая сторона туннеля выбирает значение выходного порта в дейтаграммах UDP на основе информации внутреннего потока (например, заголовков инкапсулированных пакетов). Для обеспечения достаточной энтропии передающая сторона туннеля отображает инкапсулируемый трафик на диапазон выходных портов UDP. Значение следует выбирать из диапазона «эфемерных» портов 49152 — 65535, где два старших бита номера имеют значение 1. Доступная энтропия номера порта составляет 14 битов (диапазон «эфемерных» портов) с добавлением внешних адресов IP представляется достаточной для большинства приложений ECMP [ENCAP].

Для предотвращения изменения порядка в потоке IP следует использовать один выходной порт UDP для всех пакетов инкапсулированного потока (например, используя хэш относящихся к потоку заголовков). Отображение энтропии для потока может меняться в течение срока действия инкапсулированного потока [ENCAP]. Например, это может применяться для ослабления DoS-атак23 или эффективной маршрутизации через сеть ECMP. Однако выходной порт для потока не следует менять чаще 1 раза в 30 секунд (например, как в [RFC8086]).

При использовании выходного порта как источника энтропии возникает ряд побочных эффектов.

  • Может возрасти вероятность ошибочной доставки поврежденных пакетов, повышающая потребность в использовании контрольной суммы или эквивалентного механизма для защиты других приложений UDP от ошибочной доставки (параграф 3.4).

  • Предполагается снижение вероятности успешного прохождения через промежуточные устройства (параграф 3.5). Такое использование выходного порта часто не подходит для приложений, развертываемых в Internet.

  • Может препятствовать использованию поля для защиты от атак off-path (параграф 5.1). Разработчикам следует рассмотреть иные механизмы для обеспечения эквивалентной защиты (например, ограничиваться применением в контролируемых средах [RFC7510], см. параграф 3.6).

Поле выходного порта UDP также может служить для создания энтропии в IPv6. Однако в IPv6 для создания энтропии при балансировке [RFC6438] можно использовать также метки потоков [RFC6437]. Применение метки потока для балансировки совместимо с определением этого поля, хотя нужны дополнительные разъяснения в части согласованного использования поля. Поэтому было определено использование обновленных меток потоков IPv6 [RFC6437] и маршрутизации ECMP [RFC6438].

Для обеспечения будущего применения меток потоков приложениям UDP следует устанавливать поле Flow Label, даже в тех случаях, когда энтропия уже задана выходным портом (например, конечная точка туннеля IPv6 может копировать значение энтропии выходного порта в поле метки потока IPv6 [RFC8086]). Производители маршрутизаторов призываются к использованию метки потока IPv6 как части хэш-значения для потока с целью обеспечения ECMP на уровне IP без необходимости применения UDP. Сквозное применение меток потоков для балансировки нагрузки является долгосрочным решением. Даже при разъяснении использования меток потоков сохранится переходный период до того, как существенная часть конечных точек начнет назначать эффективные значения меток для создаваемых потоков. Балансировка нагрузки с помощью полей транспортных заголовков очевидно будет продолжаться до широкого внедрения работы с метками потоков.

5.1.2. Приложения, использующие несколько портов UDP

Одно приложение может обмениваться несколькими типами данных и в некоторых случаях это может требовать множества портов UDP (например, несколько наборов потоков, идентифицируемых квинтетами). [RFC6335] рекомендует разработчикам приложений не применять несколько общеизвестных (системных или пользовательских), выделенных IANA. В документе не рассматривается использование нескольких потоков с одним общеизвестным портом или парами динамических портов (например, определяемых именем службы или сигнальным протоколом).

Использование множества потоков может оказывать несколько типов влияния на сеть.

  • Начало серии последовательных соединений может увеличить число привязок состояний в промежуточных устройствах (например, NAPT или МСЭ) на пути через сеть. Прохождение UDP через такие устройства обычно основано на тайм-аутах для удаления старых состояний, поскольку промежуточные устройства не знают, когда приложение прекращает использование потока.

  • Одновременное использование нескольких потоков может приводить к разным характеристикам для каждого потока. Нельзя предполагать, что все потоки пойдут по одному пути (например, при использовании ECMP трафик преднамеренно распределяется по разным параллельным путям на основе номеров портов).

  • Использование нескольких потоков может также повысить заполнение таблиц поиска и привязки в промежуточных устройствах (например, NAPT или МСЭ), что может заставить устройство изменить способ поддержки состояний потоков.

  • Кроме того, использование избыточного числа потоков может снизить возможности контроля перегрузок для индивидуального трафика, если состояния контроля перегрузки не являются общими для всех потоков в сессии. Выполняемый получателем контроль перегрузок для группового трафика требует от передающего приложения распространять данные по нескольким multicast-группам IP, и для каждого получателя предполагается получение трафика от небольшого числа активных одновременно портов UDP.

Следовательно, приложениям недопустимо предполагать согласованное поведение промежуточных устройств при использовании множества потоков UDP. Многие устройства могут по-разному реагировать на увеличение числа применяемых портов. Множество потоков с разными требованиями QoS требует от приложения проверять обеспечение ожидаемой производительности для каждого отдельного потока, как указано в параграфе 3.1.9.

5.2. Рекомендации для ICMP

Приложения могут использовать сведения сообщений ICMP об ошибках, которые уровень UDP передает «вверх» с разными целями [RFC1122]. Приложениям следует должным образом проверять содержимое сообщений ICMP, на предмет соответствия переданному трафику (например, сообщения об ошибках для фактически переданных приложением дейтаграмм UDP). Для этого нужен контекст, такой как локальное состояние экземпляров коммуникаций для каждого адресата, что не всегда доступно в приложениях UDP, хотя и поддерживается протоколами на основе соединений. Отметим, что не на всех платформах имеются API для таких проверок, а некоторые платформы сами выполняют проверки до передачи данных ICMP приложению.

Все откликам приложений на сообщения ICMP об ошибках следует быть устойчивыми к временным отказам маршрутизации (иногда их называют «мягкими ошибками»). Например, временные сообщения ICMP о недоступности не должны вести к прерыванию связи.

Сообщения ICMP активно фильтруются промежуточными устройствами, поэтому приложениям UDP недопустимо полагаться на их доставку для корректной и безопасной работы.

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

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

Приложениям UDP следует поддерживать защиту от атак со вставкой данных извне путем использования случайного номера выходного порта или эквивалентного метода (параграф 5.1).

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

Одним из вариантов защиты коммуникаций UDP является использование IPsec [RFC4301], где возможна проверка подлинности потока пакетов IP с помощью заголовков аутентификации (Authentication Header или AH) [RFC4302], а также шифрование и/или аутентификация ESP24 [RFC4303]. Приложения используют обмен ключами (Internet Key Exchange или IKE) [RFC7296] для настройки IPsec в своих сессиях. В зависимости от настройки IPsec для потока можно проверять подлинность и шифровать заголовки и данные UDP. Если приложению нужна лишь проверка подлинности, ESP без шифрования но с аутентификации часто бывает эффективней AH, поскольку ESP может работать через промежуточные устройства. Приложению, использующему IPsec, нужна ОС, реализующая стек протоколов IPsec, и путь в сети, поддерживающий трафик IKE и IPsec. Это может оказаться проще для реализаций IPv6 [RFC6092].

Хотя использование IPsec для защиты коммуникаций UDP возможно, не все ОС поддерживают IPsec и позволяют приложениям легко настроить защиту для их потоков. Другим вариантом защиты коммуникаций UDP является DTLS25 [RFC6347][RFC7525], где обеспечивается защита конфиденциальности путем шифрования данных UDP без защиты заголвков UDP. Приложения могут реализовать DTLS без поддержки со стороны ОС.

Имеется много других вариантов аутентификации и шифрования трафика UDP. Например, можно применить модель GSS-API [RFC2743] или синтаксис криптографических сообщений (Cryptographic Message Syntax или CMS) [RFC5652]. Есть множество вариантов защиты RTP [RFC3550] при работе по протоколу UDP, в частности, для управления ключами [RFC7201]. Эти опции охватывают разные варианты применения, включая канала «точка-точка» и централизованные групповые коммуникации, а также групповую адресацию. В некоторых приложениях лучшим решением является защита больших автономных объектов, таких как файлы или сообщения, а не данных в отдельном пакете UDP. В таких случаях можно применять CMS [RFC5652], S/MIME [RFC5751] или OpenPGP [RFC4880]. Имеется также много протоколов защиты, разработанных вне IETF.

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

Механизм защиты с обобщенным TTL (Generalized TTL Security Mechanism или GTSM) [RFC5082] можно применять с приложениями UDP, когда целевая конечная точка подключена к тому же каналу. Этот облегченный механизм позволяет получателю фильтровать нежелательные пакеты.

В части контроля перегрузок [RFC2309] и [RFC2914] рассматривают опасность не реагирующих на перегрузку потоков для сети Internet. В [RFC8084] описаны методы, которые можно использовать для установки диапазона производительности, что может помочь для предотвращения коллапса насыщения или при некорректной реакции системы контроля перегрузок на факты насыщения. Этот документ содержит рекомендации для разработчиков приложений UDP по контролю перегрузок и не создает новых проблем безопасности.

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

Приложение UDP с долгосрочной связью между отправителем и получателем должно позволять отправителю периодически проверять согласие получателя на прием данных, если для этого не используются явные подтверждения [RFC7675]. Приложения, которым нужна двухсторонняя связь для реализации функций протокола (таких как гарантии доставки или контроль перегрузок), потребуется независимая проверка в обоих направлениях, и может потребоваться дополнительный обмен сообщениями keep-alive для работы через промежуточные устройства (параграф 3.5).

7. Заключение

В этом разделе приведена сводка основных рекомендаций разделов 3 — 6 в форме таблицы (таблица 1) для удобства.

Таблица 1. Сводка рекомендаций.

Рекомендация

Параграф

Должна поддерживаться работа по широкому диапазону путей Internet.
Следует применять полнофункциональный транспорт (например, TCP)

3

Следует контролировать скорость передачи
Следует контролировать перегрузки для всего трафика

3.1

Для передачи больших объемов данных
следует рассмотреть реализацию TFRC, в противном случае
следует иным способом использовать пропускную способность по аналогии с TCP

3.1.2

Для передачи небольших объемов данных

3.1.3

Следует измерять RTT и передавать не более 1 дейтаграммы за интервал RTT,
иначе следует передавать не более 1 дейтаграммы за 3 секунды.
Следует восстанавливать (back-off) таймеры повтора после потери пакетов

3.1.1

Следует поддерживать механизмы для контроля пиков передачи

3.1.6

Можно реализовать ECN, при этом будет требоваться определенный набор механизмов в приложении, если применяется ECN.

3.1.7

Для DiffServ не следует опираться на реализацию PHB

3.1.8

Для путей с поддержкой QoS можно отказаться от использования CC

3.1.9

Не следует опираться лишь на QoS для пропускной способности
Для потоков без управления следует реализовать транспортные выключатели
Можно реализовать транспортные выключатели для других приложений

3.1.10

Для туннелей с трафиком IP
не следует применять контроль перегрузок
и должно корректно обрабатываться поле IP ECN

3.1.11

Для туннелей не-IP или не задаваемой трафиком скорости
следует выполнять CC или применять выключатель,
следует ограничивать типы трафика, доставляемого через туннель

3.1.11

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

3.2

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

3.3

Следует включать контрольную сумму UDP для IPv4

3.4

Следует включать контрольную сумму UDP для IPv6; требуются конкретные механизмы для нулевой контрольной суммы UDP

3.4.1

Следует поддерживать механизм защиты от атак извне пути,

5.1

иначе можно применять UDP-Lite с подходящим покрытием контрольной суммы

3.4.2

Не следует всегда передавать сообщения keep-alive для промежуточных устройств
При необходимости можно использовать keep-alive с интервалом не менее 15 секунд

3.5

Приложениям с ограниченным применением (или контролируемой средой) следует указывать эквивалентные механизмы и описывать их применение

3.6

Групповым приложениям с большим трафиком следует реализовать контроль перегрузок

4.1.1

Групповым приложениям с небольшим трафиком следует реализовать контроль перегрузок

4.1.2

Групповым приложениям следует применять безопасное значение PMTU

4.2

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

5.1.2

Следует проверять данные в сообщениях ICMP

5.2

Следует использовать случайный выходной порт или эквивалентный метод, а для приложений «клиент-сервер» следует передавать отклики с адреса, соответствующего запросу

6

При необходимости следует использовать стандартные протоколы защиты IETF

6

8. Литература

8.1. Нормативные документы

[RFC768] Postel, J., «User Datagram Protocol», STD 6, RFC 768, DOI 10.17487/RFC0768, August 1980, <http://www.rfc-editor.org/info/rfc768>.

[RFC793] Postel, J., «Transmission Control Protocol», STD 7, RFC 793, DOI 10.17487/RFC0793, September 1981, <http://www.rfc-editor.org/info/rfc793>.

[RFC1122] Braden, R., Ed., «Requirements for Internet Hosts — Communication Layers», STD 3, RFC 1122, DOI 10.17487/RFC1122, October 1989, <http://www.rfc-editor.org/info/rfc1122>.

[RFC1191] Mogul, J. and S. Deering, «Path MTU discovery», RFC 1191, DOI 10.17487/RFC1191, November 1990, <http://www.rfc-editor.org/info/rfc1191>.

[RFC1981] McCann, J., Deering, S., and J. Mogul, «Path MTU Discovery for IP version 6», RFC 1981, DOI 10.17487/RFC1981, August 1996, <http://www.rfc-editor.org/info/rfc1981>.

[RFC2119] Bradner, S., «Key words for use in RFCs to Indicate Requirement Levels», BCP 14, RFC 2119, DOI 10.17487/RFC2119, March 1997, <http://www.rfc-editor.org/info/rfc2119>.

[RFC2460] Deering, S. and R. Hinden, «Internet Protocol, Version 6 (IPv6) Specification», RFC 2460, DOI 10.17487/RFC2460, December 1998, <http://www.rfc-editor.org/info/rfc2460>.

[RFC2914] Floyd, S., «Congestion Control Principles», BCP 41, RFC 2914, DOI 10.17487/RFC2914, September 2000, <http://www.rfc-editor.org/info/rfc2914>.

[RFC3828] Larzon, L-A., Degermark, M., Pink, S., Jonsson, L-E., Ed., and G. Fairhurst, Ed., «The Lightweight User Datagram Protocol (UDP-Lite)», RFC 3828, DOI 10.17487/RFC3828, July 2004, <http://www.rfc-editor.org/info/rfc3828>.

[RFC4787] Audet, F., Ed. and C. Jennings, «Network Address Translation (NAT) Behavioral Requirements for Unicast UDP», BCP 127, RFC 4787, DOI 10.17487/RFC4787, January 2007, <http://www.rfc-editor.org/info/rfc4787>.

[RFC4821] Mathis, M. and J. Heffner, «Packetization Layer Path MTU Discovery», RFC 4821, DOI 10.17487/RFC4821, March 2007, <http://www.rfc-editor.org/info/rfc4821>.

[RFC5348] Floyd, S., Handley, M., Padhye, J., and J. Widmer, «TCP Friendly Rate Control (TFRC): Protocol Specification», RFC 5348, DOI 10.17487/RFC5348, September 2008, <http://www.rfc-editor.org/info/rfc5348>.

[RFC5405] Eggert, L. and G. Fairhurst, «Unicast UDP Usage Guidelines for Application Designers», BCP 145, RFC 5405, DOI 10.17487/RFC5405, November 2008, <http://www.rfc-editor.org/info/rfc5405>.

[RFC6040] Briscoe, B., «Tunnelling of Explicit Congestion Notification», RFC 6040, DOI 10.17487/RFC6040, November 2010, <http://www.rfc-editor.org/info/rfc6040>.

[RFC6298] Paxson, V., Allman, M., Chu, J., and M. Sargent, «Computing TCP’s Retransmission Timer», RFC 6298, DOI 10.17487/RFC6298, June 2011, <http://www.rfc-editor.org/info/rfc6298>.

[RFC8084] Fairhurst, G., «Network Transport Circuit Breakers», BCP 208, RFC 8084, DOI 10.17487/RFC8084, March 2017, <http://www.rfc-editor.org/info/rfc8084>.

8.2. Дополнительная литература

[ALLMAN] Allman, M. and E. Blanton, «Notes on burst mitigation for transport protocols», March 2005.

[BEHAVE-APP] Ford, B., «Application Design Guidelines for Traversal through Network Address Translators», Work in Progress, draft-ford-behave-app-05, March 2007.

[ENCAP] Nordmark, E., Ed., Tian, A., Gross, J., Hudson, J., Kreeger, L., Garg, P., Thaler, P., and T. Herbert, «Encapsulation Considerations», Work in Progress, draft-ietf-rtgwg-dt-encap-02, October 2016.

[FABER] Faber, T., Touch, J., and W. Yue, «The TIME-WAIT State in TCP and Its Effect on Busy Servers», Proc. IEEE Infocom, March 1999.

[INT-TUNNELS] Touch, J. and W. Townsley, «IP Tunnels in the Internet Architecture», Work in Progress, draft-ietf-intarea-tunnels-03, July 2016.

[POSIX] IEEE Std. 1003.1-2001, , «Standard for Information Technology — Portable Operating System Interface (POSIX)», Open Group Technical Standard: Base Specifications Issue 6, ISO/IEC 9945:2002, December 2001.

[RFC919] Mogul, J., «Broadcasting Internet Datagrams», STD 5, RFC 919, DOI 10.17487/RFC0919, October 1984, <http://www.rfc-editor.org/info/rfc919>.

[RFC1112] Deering, S., «Host extensions for IP multicasting», STD 5, RFC 1112, DOI 10.17487/RFC1112, August 1989, <http://www.rfc-editor.org/info/rfc1112>.

[RFC1536] Kumar, A., Postel, J., Neuman, C., Danzig, P., and S. Miller, «Common DNS Implementation Errors and Suggested Fixes», RFC 1536, DOI 10.17487/RFC1536, October 1993, <http://www.rfc-editor.org/info/rfc1536>.

[RFC1546] Partridge, C., Mendez, T., and W. Milliken, «Host Anycasting Service», RFC 1546, DOI 10.17487/RFC1546, November 1993, <http://www.rfc-editor.org/info/rfc1546>.

[RFC2309] Braden, B., Clark, D., Crowcroft, J., Davie, B., Deering, S., Estrin, D., Floyd, S., Jacobson, V., Minshall, G., Partridge, C., Peterson, L., Ramakrishnan, K., Shenker, S., Wroclawski, J., and L. Zhang, «Recommendations on Queue Management and Congestion Avoidance in the Internet», RFC 2309, DOI 10.17487/RFC2309, April 1998, <http://www.rfc-editor.org/info/rfc2309>.

[RFC2475] Blake, S., Black, D., Carlson, M., Davies, E., Wang, Z., and W. Weiss, «An Architecture for Differentiated Services», RFC 2475, DOI 10.17487/RFC2475, December 1998, <http://www.rfc-editor.org/info/rfc2475>.

[RFC2675] Borman, D., Deering, S., and R. Hinden, «IPv6 Jumbograms», RFC 2675, DOI 10.17487/RFC2675, August 1999, <http://www.rfc-editor.org/info/rfc2675>.

[RFC2743] Linn, J., «Generic Security Service Application Program Interface Version 2, Update 1», RFC 2743, DOI 10.17487/RFC2743, January 2000, <http://www.rfc-editor.org/info/rfc2743>.

[RFC2887] Handley, M., Floyd, S., Whetten, B., Kermode, R., Vicisano, L., and M. Luby, «The Reliable Multicast Design Space for Bulk Data Transfer», RFC 2887, DOI 10.17487/RFC2887, August 2000, <http://www.rfc-editor.org/info/rfc2887>.

[RFC2983] Black, D., «Differentiated Services and Tunnels», RFC 2983, DOI 10.17487/RFC2983, October 2000, <http://www.rfc-editor.org/info/rfc2983>.

[RFC3048] Whetten, B., Vicisano, L., Kermode, R., Handley, M., Floyd, S., and M. Luby, «Reliable Multicast Transport Building Blocks for One-to-Many Bulk-Data Transfer», RFC 3048, DOI 10.17487/RFC3048, January 2001, <http://www.rfc-editor.org/info/rfc3048>.

[RFC3124] Balakrishnan, H. and S. Seshan, «The Congestion Manager», RFC 3124, DOI 10.17487/RFC3124, June 2001, <http://www.rfc-editor.org/info/rfc3124>.

[RFC3168] Ramakrishnan, K., Floyd, S., and D. Black, «The Addition of Explicit Congestion Notification (ECN) to IP», RFC 3168, DOI 10.17487/RFC3168, September 2001, <http://www.rfc-editor.org/info/rfc3168>.

[RFC3261] Rosenberg, J., Schulzrinne, H., Camarillo, G., Johnston, A., Peterson, J., Sparks, R., Handley, M., and E. Schooler, «SIP: Session Initiation Protocol», RFC 3261, DOI 10.17487/RFC3261, June 2002, <http://www.rfc-editor.org/info/rfc3261>.

[RFC3303] Srisuresh, P., Kuthan, J., Rosenberg, J., Molitor, A., and A. Rayhan, «Middlebox communication architecture and framework», RFC 3303, DOI 10.17487/RFC3303, August 2002, <http://www.rfc-editor.org/info/rfc3303>.

[RFC3493] Gilligan, R., Thomson, S., Bound, J., McCann, J., and W. Stevens, «Basic Socket Interface Extensions for IPv6», RFC 3493, DOI 10.17487/RFC3493, February 2003, <http://www.rfc-editor.org/info/rfc3493>.

[RFC3550] Schulzrinne, H., Casner, S., Frederick, R., and V. Jacobson, «RTP: A Transport Protocol for Real-Time Applications», STD 64, RFC 3550, DOI 10.17487/RFC3550, July 2003, <http://www.rfc-editor.org/info/rfc3550>.

[RFC3551] Schulzrinne, H. and S. Casner, «RTP Profile for Audio and Video Conferences with Minimal Control», STD 65, RFC 3551, DOI 10.17487/RFC3551, July 2003, <http://www.rfc-editor.org/info/rfc3551>.

[RFC3738] Luby, M. and V. Goyal, «Wave and Equation Based Rate Control (WEBRC) Building Block», RFC 3738, DOI 10.17487/RFC3738, April 2004, <http://www.rfc-editor.org/info/rfc3738>.

[RFC3758] Stewart, R., Ramalho, M., Xie, Q., Tuexen, M., and P. Conrad, «Stream Control Transmission Protocol (SCTP) Partial Reliability Extension», RFC 3758, DOI 10.17487/RFC3758, May 2004, <http://www.rfc-editor.org/info/rfc3758>.

[RFC3819] Karn, P., Ed., Bormann, C., Fairhurst, G., Grossman, D., Ludwig, R., Mahdavi, J., Montenegro, G., Touch, J., and L. Wood, «Advice for Internet Subnetwork Designers», BCP 89, RFC 3819, DOI 10.17487/RFC3819, July 2004, <http://www.rfc-editor.org/info/rfc3819>.

[RFC4301] Kent, S. and K. Seo, «Security Architecture for the Internet Protocol», RFC 4301, DOI 10.17487/RFC4301, December 2005, <http://www.rfc-editor.org/info/rfc4301>.

[RFC4302] Kent, S., «IP Authentication Header», RFC 4302, DOI 10.17487/RFC4302, December 2005, <http://www.rfc-editor.org/info/rfc4302>.

[RFC4303] Kent, S., «IP Encapsulating Security Payload (ESP)», RFC 4303, DOI 10.17487/RFC4303, December 2005, <http://www.rfc-editor.org/info/rfc4303>.

[RFC4340] Kohler, E., Handley, M., and S. Floyd, «Datagram Congestion Control Protocol (DCCP)», RFC 4340, DOI 10.17487/RFC4340, March 2006, <http://www.rfc-editor.org/info/rfc4340>.

[RFC4341] Floyd, S. and E. Kohler, «Profile for Datagram Congestion Control Protocol (DCCP) Congestion Control ID 2: TCP-like Congestion Control», RFC 4341, DOI 10.17487/RFC4341, March 2006, <http://www.rfc-editor.org/info/rfc4341>.

[RFC4342] Floyd, S., Kohler, E., and J. Padhye, «Profile for Datagram Congestion Control Protocol (DCCP) Congestion Control ID 3: TCP-Friendly Rate Control (TFRC)», RFC 4342, DOI 10.17487/RFC4342, March 2006, <http://www.rfc-editor.org/info/rfc4342>.

[RFC4380] Huitema, C., «Teredo: Tunneling IPv6 over UDP through Network Address Translations (NATs)», RFC 4380, DOI 10.17487/RFC4380, February 2006, <http://www.rfc-editor.org/info/rfc4380>.

[RFC4607] Holbrook, H. and B. Cain, «Source-Specific Multicast for IP», RFC 4607, DOI 10.17487/RFC4607, August 2006, <http://www.rfc-editor.org/info/rfc4607>.

[RFC4654] Widmer, J. and M. Handley, «TCP-Friendly Multicast Congestion Control (TFMCC): Protocol Specification», RFC 4654, DOI 10.17487/RFC4654, August 2006, <http://www.rfc-editor.org/info/rfc4654>.

[RFC4880] Callas, J., Donnerhacke, L., Finney, H., Shaw, D., and R. Thayer, «OpenPGP Message Format», RFC 4880, DOI 10.17487/RFC4880, November 2007, <http://www.rfc-editor.org/info/rfc4880>.

[RFC4890] Davies, E. and J. Mohacsi, «Recommendations for Filtering ICMPv6 Messages in Firewalls», RFC 4890, DOI 10.17487/RFC4890, May 2007, <http://www.rfc-editor.org/info/rfc4890>.

[RFC4960] Stewart, R., Ed., «Stream Control Transmission Protocol», RFC 4960, DOI 10.17487/RFC4960, September 2007, <http://www.rfc-editor.org/info/rfc4960>.

[RFC4963] Heffner, J., Mathis, M., and B. Chandler, «IPv4 Reassembly Errors at High Data Rates», RFC 4963, DOI 10.17487/RFC4963, July 2007, <http://www.rfc-editor.org/info/rfc4963>.

[RFC4987] Eddy, W., «TCP SYN Flooding Attacks and Common Mitigations», RFC 4987, DOI 10.17487/RFC4987, August 2007, <http://www.rfc-editor.org/info/rfc4987>.

[RFC5082] Gill, V., Heasley, J., Meyer, D., Savola, P., Ed., and C. Pignataro, «The Generalized TTL Security Mechanism (GTSM)», RFC 5082, DOI 10.17487/RFC5082, October 2007, <http://www.rfc-editor.org/info/rfc5082>.

[RFC5245] Rosenberg, J., «Interactive Connectivity Establishment (ICE): A Protocol for Network Address Translator (NAT) Traversal for Offer/Answer Protocols», RFC 5245, DOI 10.17487/RFC5245, April 2010, <http://www.rfc-editor.org/info/rfc5245>.

[RFC5622] Floyd, S. and E. Kohler, «Profile for Datagram Congestion Control Protocol (DCCP) Congestion ID 4: TCP-Friendly Rate Control for Small Packets (TFRC-SP)», RFC 5622, DOI 10.17487/RFC5622, August 2009, <http://www.rfc-editor.org/info/rfc5622>.

[RFC5652] Housley, R., «Cryptographic Message Syntax (CMS)», STD 70, RFC 5652, DOI 10.17487/RFC5652, September 2009, <http://www.rfc-editor.org/info/rfc5652>.

[RFC5681] Allman, M., Paxson, V., and E. Blanton, «TCP Congestion Control», RFC 5681, DOI 10.17487/RFC5681, September 2009, <http://www.rfc-editor.org/info/rfc5681>.

[RFC5740] Adamson, B., Bormann, C., Handley, M., and J. Macker, «NACK-Oriented Reliable Multicast (NORM) Transport Protocol», RFC 5740, DOI 10.17487/RFC5740, November 2009, <http://www.rfc-editor.org/info/rfc5740>.

[RFC5751] Ramsdell, B. and S. Turner, «Secure/Multipurpose Internet Mail Extensions (S/MIME) Version 3.2 Message Specification», RFC 5751, DOI 10.17487/RFC5751, January 2010, <http://www.rfc-editor.org/info/rfc5751>.

[RFC5775] Luby, M., Watson, M., and L. Vicisano, «Asynchronous Layered Coding (ALC) Protocol Instantiation», RFC 5775, DOI 10.17487/RFC5775, April 2010, <http://www.rfc-editor.org/info/rfc5775>.

[RFC5971] Schulzrinne, H. and R. Hancock, «GIST: General Internet Signalling Transport», RFC 5971, DOI 10.17487/RFC5971, October 2010, <http://www.rfc-editor.org/info/rfc5971>.

[RFC5973] Stiemerling, M., Tschofenig, H., Aoun, C., and E. Davies, «NAT/Firewall NSIS Signaling Layer Protocol (NSLP)», RFC 5973, DOI 10.17487/RFC5973, October 2010, <http://www.rfc-editor.org/info/rfc5973>.

[RFC6056] Larsen, M. and F. Gont, «Recommendations for Transport-Protocol Port Randomization», BCP 156, RFC 6056, DOI 10.17487/RFC6056, January 2011, <http://www.rfc-editor.org/info/rfc6056>.

[RFC6092] Woodyatt, J., Ed., «Recommended Simple Security Capabilities in Customer Premises Equipment (CPE) for Providing Residential IPv6 Internet Service», RFC 6092, DOI 10.17487/RFC6092, January 2011, <http://www.rfc-editor.org/info/rfc6092>.

[RFC6335] Cotton, M., Eggert, L., Touch, J., Westerlund, M., and S. Cheshire, «Internet Assigned Numbers Authority (IANA) Procedures for the Management of the Service Name and Transport Protocol Port Number Registry», BCP 165, RFC 6335, DOI 10.17487/RFC6335, August 2011, <http://www.rfc-editor.org/info/rfc6335>.

[RFC6347] Rescorla, E. and N. Modadugu, «Datagram Transport Layer Security Version 1.2», RFC 6347, DOI 10.17487/RFC6347, January 2012, <http://www.rfc-editor.org/info/rfc6347>.

[RFC6396] Blunk, L., Karir, M., and C. Labovitz, «Multi-Threaded Routing Toolkit (MRT) Routing Information Export Format», RFC 6396, DOI 10.17487/RFC6396, October 2011, <http://www.rfc-editor.org/info/rfc6396>.

[RFC6437] Amante, S., Carpenter, B., Jiang, S., and J. Rajahalme, «IPv6 Flow Label Specification», RFC 6437, DOI 10.17487/RFC6437, November 2011, <http://www.rfc-editor.org/info/rfc6437>.

[RFC6438] Carpenter, B. and S. Amante, «Using the IPv6 Flow Label for Equal Cost Multipath Routing and Link Aggregation in Tunnels», RFC 6438, DOI 10.17487/RFC6438, November 2011, <http://www.rfc-editor.org/info/rfc6438>.

[RFC6513] Rosen, E., Ed. and R. Aggarwal, Ed., «Multicast in MPLS/BGP IP VPNs», RFC 6513, DOI 10.17487/RFC6513, February 2012, <http://www.rfc-editor.org/info/rfc6513>.

[RFC6679] Westerlund, M., Johansson, I., Perkins, C., O’Hanlon, P., and K. Carlberg, «Explicit Congestion Notification (ECN) for RTP over UDP», RFC 6679, DOI 10.17487/RFC6679, August 2012, <http://www.rfc-editor.org/info/rfc6679>.

[RFC6726] Paila, T., Walsh, R., Luby, M., Roca, V., and R. Lehtonen, «FLUTE — File Delivery over Unidirectional Transport», RFC 6726, DOI 10.17487/RFC6726, November 2012, <http://www.rfc-editor.org/info/rfc6726>.

[RFC6773] Phelan, T., Fairhurst, G., and C. Perkins, «DCCP-UDP: A Datagram Congestion Control Protocol UDP Encapsulation for NAT Traversal», RFC 6773, DOI 10.17487/RFC6773, November 2012, <http://www.rfc-editor.org/info/rfc6773>.

[RFC6807] Farinacci, D., Shepherd, G., Venaas, S., and Y. Cai, «Population Count Extensions to Protocol Independent Multicast (PIM)», RFC 6807, DOI 10.17487/RFC6807, December 2012, <http://www.rfc-editor.org/info/rfc6807>.

[RFC6887] Wing, D., Ed., Cheshire, S., Boucadair, M., Penno, R., and P. Selkirk, «Port Control Protocol (PCP)», RFC 6887, DOI 10.17487/RFC6887, April 2013, <http://www.rfc-editor.org/info/rfc6887>.

[RFC6935] Eubanks, M., Chimento, P., and M. Westerlund, «IPv6 and UDP Checksums for Tunneled Packets», RFC 6935, DOI 10.17487/RFC6935, April 2013, <http://www.rfc-editor.org/info/rfc6935>.

[RFC6936] Fairhurst, G. and M. Westerlund, «Applicability Statement for the Use of IPv6 UDP Datagrams with Zero Checksums», RFC 6936, DOI 10.17487/RFC6936, April 2013, <http://www.rfc-editor.org/info/rfc6936>.

[RFC6951] Tuexen, M. and R. Stewart, «UDP Encapsulation of Stream Control Transmission Protocol (SCTP) Packets for End-Host to End-Host Communication», RFC 6951, DOI 10.17487/RFC6951, May 2013, <http://www.rfc-editor.org/info/rfc6951>.

[RFC7143] Chadalapaka, M., Satran, J., Meth, K., and D. Black, «Internet Small Computer System Interface (iSCSI) Protocol (Consolidated)», RFC 7143, DOI 10.17487/RFC7143, April 2014, <http://www.rfc-editor.org/info/rfc7143>.

[RFC7201] Westerlund, M. and C. Perkins, «Options for Securing RTP Sessions», RFC 7201, DOI 10.17487/RFC7201, April 2014, <http://www.rfc-editor.org/info/rfc7201>.

[RFC7296] Kaufman, C., Hoffman, P., Nir, Y., Eronen, P., and T. Kivinen, «Internet Key Exchange Protocol Version 2 (IKEv2)», STD 79, RFC 7296, DOI 10.17487/RFC7296, October 2014, <http://www.rfc-editor.org/info/rfc7296>.

[RFC7450] Bumgardner, G., «Automatic Multicast Tunneling», RFC 7450, DOI 10.17487/RFC7450, February 2015, <http://www.rfc-editor.org/info/rfc7450>.

[RFC7510] Xu, X., Sheth, N., Yong, L., Callon, R., and D. Black, «Encapsulating MPLS in UDP», RFC 7510, DOI 10.17487/RFC7510, April 2015, <http://www.rfc-editor.org/info/rfc7510>.

[RFC7525] Sheffer, Y., Holz, R., and P. Saint-Andre, «Recommendations for Secure Use of Transport Layer Security (TLS) and Datagram Transport Layer Security (DTLS)», BCP 195, RFC 7525, DOI 10.17487/RFC7525, May 2015, <http://www.rfc-editor.org/info/rfc7525>.

[RFC7560] Kuehlewind, M., Ed., Scheffenegger, R., and B. Briscoe, «Problem Statement and Requirements for Increased Accuracy in Explicit Congestion Notification (ECN) Feedback», RFC 7560, DOI 10.17487/RFC7560, August 2015, <http://www.rfc-editor.org/info/rfc7560>.

[RFC7567] Baker, F., Ed. and G. Fairhurst, Ed., «IETF Recommendations Regarding Active Queue Management», BCP 197, RFC 7567, DOI 10.17487/RFC7567, July 2015, <http://www.rfc-editor.org/info/rfc7567>.

[RFC7605] Touch, J., «Recommendations on Using Assigned Transport Port Numbers», BCP 165, RFC 7605, DOI 10.17487/RFC7605, August 2015, <http://www.rfc-editor.org/info/rfc7605>.

[RFC7657] Black, D., Ed. and P. Jones, «Differentiated Services (Diffserv) and Real-Time Communication», RFC 7657, DOI 10.17487/RFC7657, November 2015, <http://www.rfc-editor.org/info/rfc7657>.

[RFC7675] Perumal, M., Wing, D., Ravindranath, R., Reddy, T., and M. Thomson, «Session Traversal Utilities for NAT (STUN) Usage for Consent Freshness», RFC 7675, DOI 10.17487/RFC7675, October 2015, <http://www.rfc-editor.org/info/rfc7675>.

[RFC8083] Perkins, C. and V. Singh, «Multimedia Congestion Control: Circuit Breakers for Unicast RTP Sessions», RFC 8083, DOI 10.17487/RFC8083, March 2017, <http://www.rfc-editor.org/info/rfc8083>.

[RFC8086] Yong, L., Ed., Crabbe, E., Xu, X., and T. Herbert, «GRE-in-UDP Encapsulation», RFC 8086, DOI 10.17487/RFC8086, March 2017, <http://www.rfc-editor.org/info/rfc8086>.

[RFC8087] Fairhurst, G. and M. Welzl, «The Benefits of Using Explicit Congestion Notification (ECN)», RFC 8087, DOI 10.17487/RFC8087, March 2017, <http://www.rfc-editor.org/info/rfc8087>.

[STEVENS] Stevens, W., Fenner, B., and A. Rudoff, «UNIX Network Programming, The sockets Networking API», Addison-Wesley, 2004.

[UPnP] UPnP Forum, , «Internet Gateway Device (IGD) Standardized Device Control Protocol V 1.0», November 2001.

Приложение A. Пример использования режима IPv6 UDP Zero-Checksum

В этом приложении дан краткий обзор MPLS-in-UDP в качестве примера туннельной инкапсуляции UDP. Цель приложения состоит в предоставлении конкретного примера безопасного использования режима UDP zero-checksum для туннелей MPLS-in-UDP по протоколу IPv6. По умолчанию UDP требует использования контрольных сумм с IPv6. Задана опция, позволяющая использовать нулевую контрольную сумму дейтаграмм UDP в IPv6 для работы в определенных средах, указанных в [RFC7510], и определен набор ограничений для работы в этом режиме.

Туннели или инкапсуляцию UDP с использованием нулевой контрольной суммы в IPv6 можно разворачивать лишь в сети одного оператора или в смежных сетях взаимодействующих операторов с контролем перегрузки, а не через Internet, где требуется контроль перегрузок. Решение MPLS-in-UDP было разработано для сетей с единым администрирование (таких, как сеть одного оператора), где известно (возможно из сведений о типах оборудования и проверках нижележащих уровней), что повреждения пакетов очень редки и оператор готов принять риск повреждения незащищенных пакетов.

Инкапсулятору туннеля следует выбирать разные адреса IPv6 для каждого туннеля с нулевой контрольной суммой UDP, независимо от декапсулятора и строгости проверки им адресов отправителей IPv6 (один групповой или индивидуальный адрес отправителя IPv6 не следует использовать для разных получателей). Применение MPLS-in-UDP можно расширить на смежные сети взаимодействующих операторов с согласованным администрированием (сети, где операторы согласны взаимодействовать для предоставления общего набора услуг) [RFC7510].

Требования к конечным точкам MPLS-in-UDP проверять адрес отправителя IPv6 в дополнение к адресу получателя и строгая рекомендация не применять один адрес отправителя IPv6 для разных туннелей MPLS-in-UDP обеспечивают некоторую компенсацию отсутствия контрольной суммы UDP в заголовке IPv6. Кроме того, плоскость данных MPLS пересылает лишь пакеты с действительными метками (т. е. метками, распространенными выходными LSR26 туннелей), что обеспечивает дополнительные возможности обнаружения ошибочно доставленных пакетов MPLS-in-UDP, если те содержат недействительную метку для пересылки на принимающем LSR. Ожидаемый результат для IPv6 с нулевой контрольной суммой UDP для MPLS-in-UDP заключается в том, что повреждение адреса получателя IPv6 обычно будет приводить к отбрасыванию пакетов.

Дополнительную уверенность обеспечивают ограничения приведенных выше исключений, позволяющие применять режим IPv6 UDP zero-checksum лишь в хорошо управляемых сетях, где повреждения пакетов MPLS не создают практических проблем. Поэтому MPLS-in-UDP подходит для передачи через нижние уровни в хорошо управляемых сетях, разрешенных отмеченными выше исключениями, где не ожидается рост частоты повреждения внутренних пакетов IP по сравнению с трафиком MPLS без инкапсуляции UDP. Упомянутые причины позволяют отказаться в MPLS-in-UDP от дополнительной проверки целостности в режиме с нулевой контрольной суммой UDP для IPv6 и счесть это решение соответствующим требованиям 2, 3 и 5 раздела 5 в [RFC6936].

Инкапсуляция MPLS-in-UDP не включает механизма безопасного возврата к использованию контрольных сумм при изменении пути, перенаправляющем туннель на участки с промежуточными устройствами, которые отбрасывают дейтаграммы IPv6 с нулевой контрольной суммой UDP. В этом случае промежуточное устройство делает туннель MPLS-in-UDP «черной дырой». Рекомендации, позволяющие МСЭ, трансляторам NAT и другим промежуточным устройствам поддерживать использование IPv6 с нулевой контрольной суммой UDP, приведены в разделе 5 [RFC6936]. MPLS не аккумулирует некорректное состояние в результате повреждения стека меток. Поврежденная метка MPLS ведет к отбрасыванию пакета или его пересылки (и забвению) без накопления состояния протокола MPLS. Требуется активный мониторинг ошибок в трафике MPLS-in-UDP, поскольку возникновение ошибки приведет к некоторому накоплению данных об ошибках за пределами протокола MPLS для целей эксплуатации и управления. Это соответствует требованию 4 из раздела 5 в [RFC6936]. Кроме того, оператор сети должен активно отслеживать наличие ошибок в трафике IPv6 с нулевой контрольной суммой.

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

Благодарности

Рекомендации по работе через промежуточные устройства в параграфе 3.5 включают идеи из раздела 5 работы [BEHAVE-APP] Bryan Ford, Pyda Srisuresh, Dan Kegel. Рекомендации по таймерам протокола в параграфе 3.1.1 в значительной степени представлены Mark Allman.

G. Fairhurst получил финансирование в рамках программы Европейского союза Horizon 2020 и инновационной программы 2014-2018 по гранту 644334 (NEAT). Lars Eggert получил финансирование в рамках программы Европейского союза Horizon 2020 и инновационной программы 2014-2018 по гранту 644866 (SSICLOPS). Этот документ отражает лишь точку зрения авторов и Европейская комиссия не несет ответственности за любое использование содержащейся в документе информации.

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

Lars Eggert

NetApp

Sonnenallee 1

Kirchheim 85551

Germany

Phone: +49 151 120 55791

Email: lars@netapp.com

URI: https://eggert.org/

Godred Fairhurst

University of Aberdeen

Department of Engineering

Fraser Noble Building

Aberdeen AB24 3UE

Scotland

Email: gorry@erg.abdn.ac.uk

URI: http://www.erg.abdn.ac.uk/

Greg Shepherd

Cisco Systems

Tasman Drive

San Jose

United States of America

Email: gjshep@gmail.com

Перевод на русский язык

Николай Малых

nmalykh@protokols.ru

1Internet Engineering Task Force.

2Internet Engineering Steering Group.

3Stream Control Transmission Protocol — протокол управления потоковой передачей.

4SCTP Partial Reliability Extension — SCTP с частичными гарантиями доставки.

5Datagram Congestion Control Protocol — протокол дейтаграмм с контролем перегрузок.

6TCP-Friendly Rate Control — дружественный к TCP контроль скорости.

7Exponentially Weighted Moving Average — экспоненциально взвешенное скользящее среднее значение.

8Retransmission Timeout — тайм-аут повторной передачи.

9General Internet Signaling Transport — сигнальный транспорт общего назначения в Internet.

10Congestion Experience — наблюдается насыщение.

11Resource Reservation Protocol — протокол резервирования ресурсов.

12Equal cost multipath — множество равноценных путей.

13Maximum Transmission Unit — максимальный передаваемый блок.

14Packetization Layer Path MTU Discovery — определение Path MTU на уровне пакетизации.

15Cyclic Redundancy Check — циклическая контрольная сумма с избыточностью.

16Asynchronous Layered Coding — асинхронное многоуровневое кодирование.

17TCP-Friendly Multicast Congestion Control — дружественный к TCP контроль перегрузок для группового трафика.

18Wave and Equation Based Rate Control — контроль скорости на основе волн и уравнений.

19NACK-Oriented Reliable Multicast — ориентированная на негативные подтверждения групповая передача.

20File Delivery over Unidirectional Transport — доставка файлов через односторонний транспорт.

21Real Time Protocol/Control Protocol — протоколы работы и управления в реальном масштабе времени.

22Population Count Extensions to Protocol Independent Multicast — расширения для учета числа участников в независимых от протокола групповых приложениях.

23Denial of Service — отказ в обслуживании.

24Encapsulating Security Payload — инкапсуляция защищенных данных.

25Datagram Transport Layer Security — защита транспортного уровня дейтаграмм.

26Label Switched Router — маршрутизатор с коммутацией по меткам.

Рубрика: RFC | Комментарии к записи RFC 8085 UDP Usage Guidelines отключены

RFC 8109 Initializing a DNS Resolver with Priming Queries

Internet Engineering Task Force (IETF)                           P. Koch
Request for Comments: 8109                                      DENIC eG
BCP: 209                                                       M. Larson
Category: Best Current Practice                               P. Hoffman
ISSN: 2070-1721                                                    ICANN
                                                              March 2017

Initializing a DNS Resolver with Priming Queries

Инициализация распознавателя DNS с подготовительными запросами

PDF

Аннотация

В этом документе описаны запросы, которые распознавателю DNS следует выдавать (emit) для инициализации своего кэша. В результате этого распознаватель получает как текущий набор записей ресурсов NS (Resource Record Set или RRset) для корневой зоны, так и требуемые адресные сведения для достижения корневых серверов.

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

Документ относится к категории Internet Best Current Practice.

Документ является результатом работы IETF1 и представляет согласованный взгляд сообщества IETF. Документ прошёл открытое обсуждение и был одобрен для публикации IESG2. Дополнительную информацию о документах BCP можно найти в разделе 2 в RFC 7841.

Информацию о текущем статусе документа, ошибках и способах обратной связи можно найти по ссылке http://www.rfc-editor.org/info/rfc8109.

Авторские права

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

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

1. Введение

Рекурсивным распознавателям DNS нужна отправная точка для распознавания по запросам. В [RFC1034] описан базовый сценарий для рекурсивных распознавателей — они начинают с пустого кэша и некой конфигурации для нахождения имён и адресов корневых серверов DNS. Эта конфигурация описана в [RFC1034] как список серверов, которые будут давать полномочные ответы на запросы о корне. Это стало распространённым вариантом реализации рекурсивных распознавателей и является темой этого документа. В этом документе описаны шаги, требуемые для этого варианта реализации. Отметим, что это не единственный способ запуска рекурсивного сервера имён с пустым кэшем, но в [RFC1034] описан только он. Некоторые разработчики выбрали иные варианты, часть которых работает хорошо, а другие сталкиваются с отказами (иногда катастрофическими) при некоторых условиях. Например, реализация, получающая адреса корневых серверов только из конфигурации, а не от DNS (как описано в этом документе) будет иметь устаревшие данные, что может замедлить распознавание.

Ключевые слова необходимо (MUST), недопустимо (MUST NOT), требуется (REQUIRED), нужно (SHALL), не следует (SHALL NOT), следует (SHOULD), не нужно (SHOULD NOT), рекомендуется (RECOMMENDED), не рекомендуется (NOT RECOMMENDED), возможно (MAY), необязательно (OPTIONAL) в данном документе интерпретируются в соответствии с [RFC2119].

В этом документе рассматриваются только рекурсивные серверы имён (рекурсивные распознаватели, распознаватели) для класса IN.

2. Описание подготовки

Подготовка (priming) — это поиск списка корневых серверов по конфигурации, где указаны все или некоторые предполагаемые адреса IP корневых серверов. Рекурсивный распознаватель начинает с отсутствия сведений о корневых серверах, а заканчивает списком их имён и адресов. Подготовка описана в параграфах 5.3.2 и 5.3.3 [RFC1034]. В описании использован сценарий, где рекурсивный сервер является также полномочным, что не очень распространено.

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

Список операторов корневых серверов и доменных имён, связанных с каждым из них, не меняется с 1997 г. Однако в настоящее некоторые адреса (IPv4 и IPv6) для доменных имён корневых серверов изменились. Тем не менее, исследования показывают, что после такой замены некоторые распознаватели не получили новых адресов. Поэтому важно, чтобы распознаватели могли справиться с изменениями даже без смены конфигурации их операторами. Смена корневых серверов является основной причиной, по которой распознаватели для получения полного списка корневых серверов должны выполнять подготовку, а не просто обращаться к настроенному списку.

3. Подготовительные запросы

Подготовительным считается запрос DNS, служащий для получения сведений о корневом сервере в распознавателе. Запрос содержит QNAME «.», QTYPE NS и передаётся по одному из адресов, заданных в конфигурации рекурсивного распознавателя. Подготовительный запрос может передаваться по протоколу UDP или TCP. При передаче через UDP порт отправителя следует выбирать случайно (см. [RFC5452]). Бит желательности рекурсии (Recursion Desired или RD) может иметь значение 0 или 1, хотя значение 1 не определено для подготовительных запросов.

Рекурсивному распознавателю следует использовать EDNS(0) [RFC6891] для подготовительных запросов, а также следует анонсировать и обслуживать размер сборки не менее 1024 октетов [RFC3226]. Это разрешает отклики величиной до полного размера подготовительного отклика (см. параграф 4.2) для текущего набора корневых серверов. Установка бита DNSSEC OK (DO), определённого в [RFC4033], обсуждается в параграфе 3.3.

3.1. Повторение подготовительных запросов

Рекурсивному распознавателю следует передавать подготовительный запрос лишь тогда, когда это необходимо, например при старте распознавателя с пустым кэшем или при завершении срока действия NS RRset для корневой зоны. Поскольку записи NS для корня не являются особыми, срок их действия у рекурсивного распознавателя истекает в соответствии со значениями TTL в них (отметим, что рекурсивный распознаватель может заранее извлечь NS RRset до завершения срока действия прежнего набора.)

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

3.2. Выбор цели

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

3.3. DNSSEC с подготовительными запросами

Распознаватель может установить бит DNSSEC OK (DO). На момент публикации не было большого смысла проверять DNSSEC для подготовительного запроса. В настоящее время все имена корневых серверов заканчиваются на root-servers.net, а RRset AAAA и A размещаются в зоне root-servers.net. Все корневые серверы являются полномочными для этой зоны, что позволяет включать в подготовительные отклики RRset AAAA и A подходящего корневого сервера имён. Однако зона root-servers.net в настоящее время не подписывается, поэтому RRset невозможно проверить.

Атака с участием человека (man-in-the-middle) на подготовительный запрос может направить распознаватель на поддельный (rogue) корневой сервер. Однако проверяющий распознаватель не будет воспринимать отклики от поддельных серверов имён, если они отличаются от реальных откликов, поскольку у распознавателя имеется привязка доверия для корня и отклики от корня подписываются. Таким образом, такая атака на подготовительный запрос будет приводить лишь к отказу в обслуживании, но не к восприятию распознавателем поддельных откликов.

Если зона root-servers.net впоследствии будет подписываться или корневые серверы будут указываться в иной зоне, которая подписана, проверка DNSSEC для подготовительных запросов может стать полезной.

4. Отклики при подготовке

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

4.1. Ожидаемые свойства откликов

Предполагается, что подготовительный отклик будет иметь RCODE NOERROR, а бит полномочного отклика (Authoritative Answer или AA) будет установлен (1). Также предполагается наличие NS RRset в разделе Answer (поскольку NS RRset исходит из корневой зоны) и пустой раздел Authority (NS RRset уже имеется в разделе Answer). В отклике будет раздел Additional с RRset A и/или AAAA для корневых серверов имён, указанных NS RRset.

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

4.2. Полнота откликов

В настоящее время имеется 13 корневых серверов, каждый из которых имеет 1 адрес IPv4 и 1 адрес IPv6. Даже без учета NS RRset, суммарный размер записей A и AAAA превышает 512-октетный предел, заданный в [RFC1035].

При получении отклика, где в разделе Additional отсутствуют адреса некоторых корневых серверов, повторный подготовительный запрос не поможет, если отвечающие корневые серверы используют фиксированный порядок адресов в разделе Additional. Вместо этого рекурсивному распознавателю нужно делать прямые запросы для RRset A и AAAA оставшихся имён. В настоящее время эти RRset полномочно представляются корневыми серверами имён.

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

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

Злоумышленник на пути, который видит подготовительные запросы от распознавателя, может внедрить ложные отклики до того, как корневой сервер сможет передать верный ответ. Если отклик атакующего будет воспринят, это может открыть возможность давать ложные отклики на последующие запросы к распознавателю. Ложные отклики для корневых серверов боле опасны, чем, например, ложные отклики для доменов верхнего уровня Top-Level Domain или TLD), поскольку корень является верхним уровнем DNS (см. параграф 3.3).

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

6. Взаимодействие с IANA

Этот документ не требует действий IANA.

7. Нормативные документы

[RFC1034] Mockapetris, P., «Domain names — concepts and facilities», STD 13, RFC 1034, DOI 10.17487/RFC1034, November 1987, <http://www.rfc-editor.org/info/rfc1034>.

[RFC1035] Mockapetris, P., «Domain names — implementation and specification», STD 13, RFC 1035, DOI 10.17487/RFC1035, November 1987, <http://www.rfc-editor.org/info/rfc1035>.

[RFC2119] Bradner, S., «Key words for use in RFCs to Indicate Requirement Levels», BCP 14, RFC 2119, DOI 10.17487/RFC2119, March 1997, <http://www.rfc-editor.org/info/rfc2119>.

[RFC3226] Gudmundsson, O., «DNSSEC and IPv6 A6 aware server/resolver message size requirements», RFC 3226, DOI 10.17487/RFC3226, December 2001, <http://www.rfc-editor.org/info/rfc3226>.

[RFC4033] Arends, R., Austein, R., Larson, M., Massey, D., and S. Rose, «DNS Security Introduction and Requirements», RFC 4033, DOI 10.17487/RFC4033, March 2005, <http://www.rfc-editor.org/info/rfc4033>.

[RFC5452] Hubert, A. and R. van Mook, «Measures for Making DNS More Resilient against Forged Answers», RFC 5452, DOI 10.17487/RFC5452, January 2009, <http://www.rfc-editor.org/info/rfc5452>.

[RFC6891] Damas, J., Graff, M., and P. Vixie, «Extension Mechanisms for DNS (EDNS(0))», STD 75, RFC 6891, DOI 10.17487/RFC6891, April 2013, <http://www.rfc-editor.org/info/rfc6891>.

Благодарности

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

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

Peter Koch
DENIC eG
Kaiserstrasse 75-77
Frankfurt 60329
Germany
Phone: +49 69 27235 0
Email: pk@DENIC.DE
 
Matt Larson
ICANN
Email: matt.larson@icann.org
 
Paul Hoffman
ICANN
Email: paul.hoffman@icann.org

Перевод на русский язык

nmalykh@protokols.ru


1Internet Engineering Task Force — комиссия по решению инженерных задач Internet.

2Internet Engineering Steering Group — комиссия по инженерным разработкам Internet.

Рубрика: RFC | Оставить комментарий

RFC 8084 Network Transport Circuit Breakers

Internet Engineering Task Force (IETF)                      G. Fairhurst
Request for Comments: 8084                        University of Aberdeen
BCP: 208                                                      March 2017
Category: Best Current Practice
ISSN: 2070-1721

Network Transport Circuit Breakers

Автоматические выключатели сетевого транспорта

PDF

Аннотация

В этом документе разъясняется термин «автоматический выключатель сетевого транспорта» (network transport Circuit Breaker). Описана необходимость автоматических выключателей (Circuit Breaker или CB) для сетевых туннелей и приложений при использовании трафика без контроля перегрузок и указано, где CB нужны и где не нужны. Заданы также требования к созданию CB и описаны ожидаемые результаты применения CB в Internet.

Документ относится к категории Internet Best Current Practice.

Документ является результатом работы IETF1 и представляет согласованный взгляд сообщества IETF. Документ прошел открытое обсуждение и был одобрен для публикации IESG2. Дополнительную информацию о документах BCP можно найти в разделе 2 в RFC 7841.

Информацию о текущем статусе документа, ошибках и способах обратной связи можно найти по ссылке http://www.rfc-editor.org/info/rfc8084.

Авторские права

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

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

1. Введение

Термин «автоматический выключатель» (Circuit Breaker или CB) происходит из систем электроснабжения и никак не связан с сетевыми или виртуальными устройствами. В электроснабжении CB предназначены для защиты в крайних случаях. При нормальных условиях CB не должны срабатывать, они предназначены для защиты сети питания и подключённого оборудования от перегрузок. Люди не ожидают срабатывания CB (или предохранителя) в своём доме, за исключением случаев неисправностей в проводке или проблем с электроприборами.

В сетях принцип CB может использоваться как защитный механизм для крайних случаев, чтобы избежать сохраняющейся перегрузки, влияющей на другие потоки, использующие ту же сеть. Постоянные перегрузки были частыми на ранних этапах Internet в 1980 гг и приводили к тому, что избыточный трафик лишал другие соединения доступа в Internet. Этому противостояло требование использовать контроль перегрузок (congestion control или CC) в протоколе управления передачей (Transmission Control Protocol или TCP) [Jacobson88]. Эти механизмы работают на хостах Internet, вызывая «отключение» соединений TCP при перегрузке. Добавление контроля перегрузки в TCP (документировано в [RFC5681]) обеспечило стабильность Internet за счёт обнаружения и своевременного реагирования на перегрузки. Это было эффективно в Internet, где большинство потоков TCP были долгоживущими (это позволяло обнаруживать перегрузки и реагировать на них до прерывания потока). Хотя трафик TCP до сих пор был доминирующим, картина меняется и трафик без контроля перегрузки, включая трафик многих приложений на основе протокола пользовательских дейтаграмм (User Datagram Protocol или UDP), может составлять значительную часть общего трафика на канале. Для предотвращения сохраняющейся перегрузки в современной сети Internet требуется рассмотрение способов пересылки трафика без контроля перегрузок.

CB для сетевого транспорта — это автоматический механизм, служащий для постоянного отслеживания потока или агрегата потоков. Механизм стремится обнаружить сохраняющуюся чрезмерную нагрузку в потоках. При обнаружении перегрузки CB прерывает поток (или существенно снижает его скорость). Это является безопасной мерой предотвращения истощения сетевых ресурсов, препятствующего доступу других потоков в Internet. Такие меры необходимы для гетерогенной сети Internet и трафика, который сложно предвидеть заранее. Предотвращение сохраняющейся перегрузки важно для снижения вероятности «коллапса перегрузки» (Congestion Collapse) [RFC2914].

Имеются важные различия между транспортным CB и методом контроля перегрузок. Контроль перегрузки (реализованный в TCP, SCTP3 и DCCP4) работает в масштабе времени порядка интервала кругового обхода (Round-Trip Time или RTT) — времени передачи пакета от отправителя к адресату и обратно. Перегрузку на сетевом канале можно обнаружить с использованием явных уведомлений о перегрузке (Explicit Congestion Notification или ECN) [RFC3168], позволяющих сети указывать перегрузку путём установки в пакетах с поддержкой ECN маркеров перегрузки (Congestion Experienced или CE). Потери или получение пакетов с маркером CE считаются индикацией перегрузки. Методы контроля перегрузок способны реагировать на такие события, постоянно адаптируясь для снижения скорости передачи. Цель обычно состоит в ограничении скорости передачи до максимального значения, отражающего беспристрастное использование доступной на сетевом пути пропускной способности. Эти методы обычно работают на уровне отдельного потока трафика (задаётся квинтетом из адресов IP, протокола и портов).

CB рекомендуются для потоков Internet без контроля перегрузок, например, для трафика, передаваемого с использованием сетевого туннеля. Они работают в масштабе времени, многократно превыщающем RTT, и срабатывают при аномальной (чрезмерной) перегрузке. Люди часто применяли то, что в этом документе называется CB, в качестве специализированных мер защиты трафика Internet. Этот документ даёт рекомендации по развёртывания и использованию таких механизмов. В последующих параграфах приведены примеры, где CB могут быть или не быть желательны.

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

Триггер CB часто использует серию последовательных измерений в точке входа и точке выхода (любая из которых может быть конечной точкой транспорта). Триггер должен работать в масштабе времени, многократно превышающем RTT (например, от единиц до многих десятков секунд). Длительный период нужен для обеспечения достаточного времени для работы транспортного контроля перегрузки или приложения с целью корректировки скорости при возникновении перегрузки, а также для стабилизации сети после корректировки. Перегрузки могут быть обычным явлением, когда транспорт с контролем перегрузки используется через канал, занятый почти полностью. Каждое событие перегрузки ведёт к снижению скорости транспортного потока, столкнувшегося с перегрузкой. Более длинный период позволяет избавиться от ненужных срабатываний CB после 1 или даже нескольких событий перегрузки.

При срабатывании CB должен обеспечить функцию управления (реакция), которая исключает трафик из сети путём запрета потока или существенного снижения уровня трафика. Такая реакция обеспечивает защиту и предотвращает сохраняющуюся перегрузку для других потоков, проходящих (частично) по тому же пути через сеть.

В разделе 4 приведены требования к построению CB.

Рабочие условия, вызывающие срабатывание CB, следует считать аномальными. Примеры ситуаций, которые могут вызывать срабатывание CB включают:

  • аномальный трафик, превышающий предоставленную пропускную способность (или имеющий характеристики, превышающие порог, настроенный для CB);

  • трафик, генерируемый приложением в то время, когда выделенная пропускная способность используется для других целей;

  • изменение маршрутизации, вызывающее передачу дополнительного трафика по пути, отслеживаемому CB;

  • некорректная настройка службы или сетевого устройства, когда доступной пропускной способности не хватает для поддержки текущего агрегата трафика;

  • некорректная настройка контроллера доступа или ограничителя трафика, позволяющая передавать больше трафика, чем ожидалось на пути, отслеживаемом CB.

Сетевым операторам могут быть доступны иные механизмы обнаружения перегрузки (например, избыточная загрузка порта на сетевом устройстве). Используя такие сведения, операционные механизмы могут реагировать, снижая сетевую нагрузку на время меньше, чем у транспортного CB. Роль CB на таких путях остаётся крайней мерой. Поскольку CB работает с более долгими интервалами, ему следует срабатывать лишь при отказе иных мер реагирования на перегрузку.

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

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

1.1. Типы CB

Имеются разные формы CB для сетевого транспорта, различающиеся в основном временем срабатывания, а также предоставляемой защитой.

Fast-Trip CB — CB с быстрым переключением

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

Slow-Trip CB — CB с медленным переключением

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

Managed CB — управляемые CB

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

Примеры всех типов CB представлены в разделе 4.

2. Уровни требований

Ключевые слова должно (MUST), недопустимо (MUST NOT), требуется (REQUIRED), нужно (SHALL), не следует (SHALL NOT), следует (SHOULD), не нужно (SHOULD NOT), рекомендуется (RECOMMENDED), не рекомендуется (NOT RECOMMENDED), возможно (MAY), необязательно (OPTIONAL) в данном документе интерпретируются в соответствии с [RFC2119].

3. Устройство CB

Хотя CB много лет обсуждались в IETF, до сих пор не было рекомендаций по применению и устройству CB. В этом документе предпринята попытка обсудить эти вопросы.

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

Этот документ задаёт требования к устройству CB и содержит примеры конструкций. В спецификациях протоколов и туннельной инкапсуляции нужно указывать детали протокольных механизмов, требуемых для реализации CB. В параграфе 3.1 указаны функциональные компоненты CB, а в параграфе 3.2 заданы требования к реализации CB.

3.1. Функциональные компоненты

 +--------+                                                   +--------+
 |Endpoint|                                                   |Endpoint|
 +--+-----+                 >>> Трафик CB >>>                 +--+-----+
    |                                                            |
    | +-+  +-+  +---------+  +-+  +-+  +-+  +--------+  +-+  +-+ |
    +-+R+--+R+->+  Вход   +--+R+--+R+--+R+--+ Выход  |--+R+--+R+-+
      +++  +-+  +------+--+  +-+  +-+  +-+  +-----+--+  +++  +-+
       |         ^     |                          |      |
       |         |  +--+------+            +------+--+   |
       |         |  | Входной |            | Выходной|   |
       |         |  | измерит.|            | измерит.|   |
       |         |  +----+----+            +----+----+   |
       |         |       |                      |        |
  +-+  |         |  +----+----+                 |        |  +-+
  |R+--+         |  |  Мера   +<----------------+        +--+R|
  +++            |  +----+----+      Отчёт о                +++
   |             |       |           выходном                |
   |             |  +----+----+      измерении               |
+--+-----+       |  | Триггер +                           +--+-----+
|Endpoint|       |  +----+----+                           |Endpoint|
+--------+       |       |                                +--------+
                 +---<---+
                  Реакция

Рисунок 1. CB, контролирующий часть сквозного пути между точками входа и выхода. В некоторых случаях функции триггера и измерений могут размещаться в других местах (например, в операционном центре сети).


Базовая конструкция CB включает связь между точками входа (отправитель) и выхода (получатель) сетевого потока или набора потоков. Простая иллюстрация работы приведена на рисунке 1, где показан набор маршрутизаторов (R), соединяющих множество конечных точек (Endpoint).

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

В контексте CB входные и выходные функции могут быть реализованы в разных местах. Например, они могут размещаться в сетевых устройствах на входе и выходе туннеля. В некоторых случаях они могут размещаться на одной или обеих конечных точках сети (Рисунок 2) и могут быть реализованы как компоненты транспортного протокола.

+----------+                 +----------+
| Входная  |  +-+  +-+  +-+  | Выходная |
| точка    +->+R+--+R+--+R+--+ точка    |
+--+----+--+  +-+  +-+  +-+  +----+-----+
   ^    |                         |
   | +--+------+             +----+----+
   | | Входной |             | Выходной|
   | | измерит.|             | измерит.|
   | +----+----+             +----+----+
   |      |                       |
   | +--- +----+                  |
   | |  Мера   +<-----------------+
   | +----+----+      Отчёт о
   |      |           выходном
   | +----+----+      измерении
   | | Триггер |
   | +----+----+
   |      |
   +---<--+
   Реакция

Рисунок 2. CB конечной точки, реализованный у отправителя и получателя.


Ниже указаны компоненты, требуемые для реализации CB.

  1. Входной измеритель (у отправителя или на входе туннеля), записывающий число пакетов/байтов, переданных в каждом интервале измерения. Это указывает сетевую нагрузку для потока или набора потоков трафика. Например, интервал измерения может составлять много секунд (измерение каждые несколько десятков секунд или серия коротких последовательных измерений, объединяемых функцией измерения CB).

  2. Выходной измеритель (у получателя или на выходе туннеля), записывающий число пакетов/байтов, полученных в каждом интервале измерения. Он указывает поддерживаемую нагрузку для потока или набора потоков и может использовать другие сигналы обнаружения перегрузки (например, потери или маркировку [RFC3168] на пути). Измерения на выходе могут синхронизироваться (включая смещение для времени прохождения данных или привязку измерений к конкретному пакету), чтобы все счётчики относились к одному диапазону пакетов.

  3. Метод передачи измеренных на входе и выходе значений функции CB Measurement. Для этого можно применять несколько методов, включая передачу откликов на пакеты измерений (управляющих сообщений) от получателя для запуска функции у отправителя, реализацию с использованием OAM5, передачу сигнальных дейтаграмм по основному каналу. Можно также реализовать это полностью как функцию плоскости управления, например, с использованием контроллера программно-определяемой сети.

  4. Функция измерения, объединяющая входные и выходные измерения для оценки текущего уровня перегрузки сети (например, частота потерь в каждом интервале измерения может быть выведена из разности значений входных и выходных счётчиков). Отметим, что метод не требует высокой точности для измерительного интервала (и для измеренных значений, поскольку изолированные и редкие потери нужно игнорировать).

  5. Функция триггера, которая определяет, указывают ли измерения сохраняющуюся перегрузку. Эта функция задаёт подходящий порог для определения наличия сохраняющейся перегрузки между входом и выходом. При этом предпочтительно учитывать скорость или отношение, а не абсолютное значение (например, потери выше 10% или иные значения, основанные на скорости передачи и частоте потерь). CB переключается, когда порог превышен в течение нескольких интервалов измерения (например, при 3 последовательных измерениях). Функция должна быть надёжной, чтобы отдельные или ложные события не вызывали реакции.

  6. Реакция, применяемая на входе в случае переключения CB. Реакция стремится автоматически исключить трафик, вызвавший сохраняющуюся перегрузку.

  7. Механизм управления с обратной связью, который срабатывает при недоступности входных или выходных измерений, поскольку это может указывать потерю пакетов управления (признак сильной перегрузки или неспособности управлять нагрузкой).

3.2. Другие топологии сетей

CB могут применяться в сетях с топологией, отличающейся от показанной на рисунках 1 и 2. В этом параграфе приведены примеры такого использования и указаны возможные места реализации функций.

3.2.1. Использование с групповым протоколом управления/маршрутизации

На рисунке 3 показан пример реализации группового (multicast) CB на паре групповых конечных точек (например, для реализации Fast-Trip CB, см. параграф 5.1). Входная конечная точка (отправитель группового трафика) измеряет нагрузку на входе, генерирует результаты измерений (например, записывает счётчики пакетов с временными метками) и передаёт их в multicast-группу вместе с измеряемым трафиком.

Маршрутизаторы на групповом пути пересылают multicast-трафик (включая входные измерения) всем активным получателям в конечных точках. Каждый маршрутизатор последнего интервала (last hop, выход) пересылает трафик одной или нескольким выходным конечным точкам.

+----------+                 +--------+  +----------+
| Входная  |  +-+  +-+  +-+  |Выходной|  | Выходная |
| точка    +->+R+--+R+--+R+--+маршрут.|--+ точка    +->+
+----+-----+  +-+  +-+  +-+  +---+--+-+  +----+-----+  |
     ^         ^    ^    ^       |  ^         |        |
     |         |    |    |       |  |         |        |
+----+----+    + - - - < - - - - +  |    +----+----+   | Отчёт о
| Входной |    Групп. сообщ. Prune  |    |Выходной |   | входном
| измерит.|                         |    |измерит. |   | измерении
+---------+                         |    +----+----+   |
                                    |         |        |
                                    |    +----+----+   |
                                    |    |  Мера   +<--+
                                    |    +----+----+
                                    |         |
                                    |    +----+----+
                          Групповое |    | Триггер |
                          сообщение |    +----+----+
                          Leave     |         |
                                    +----<----+

Рисунок 3. Пример группового CB, контролирующего сквозной путь между входом и выходом.


На рисунке 3 каждая конечная точка включает измеритель для локальной выходной нагрузки. Конечная точка также извлекает из трафика полученные входные измерения и сравнивает входные и выходные значения для определения необходимости переключения CB. Эти измерения должны быть устойчивы к потерям (см. предыдущий параграф). При переключении CB генерируется групповое сообщение Leave (выход из группы) для выходов (например, передаётся сообщение IGMP или MLD маршрутизатору last-hop), которое заставляет маршрутизатор восходящего направления прервать пересылку трафика выходной конечной точке [RFC1112].

Групповые маршрутизаторы, не имеющие активных получателей для конкретной группы, будут пересылать своему маршрутизатору восходящего направления сообщение Prune (обрезка). Это запускает процесс освобождения пропускной способности, используемой трафиком, являющийся стандартной функцией групповой маршрутизации (например, использование протокола PIM-SM6 [RFC7761]). Каждый выход работает автономно и «реакция» CB происходит в групповой плоскости управления (например, через PIM), не требуя явных сигналов от CB по пути, используемому для управляющих сообщений. Отметим, что прямой связи со входом нет, поэтому переключение CB влияет лишь на нисходящий трафик первого группового маршрутизатора (first-hop multicast). Переключение не останавливает трафик от источника к маршрутизатору first-hop, это обычная практика для групповой передачи.

Метод подходит также для групповых туннелей или подсетей (см., например, параграфы 5.2, 5.3), где измеритель на входе генерирует дополнительные управляющие сообщения, переносящие данные измерений в сторону выхода, где реализовано выходное измерение.

3.2.2. Использование с протоколами управления, поддерживающими полосу

Некоторые пути предоставляются с использованием протокола управления, например, потоки, предоставляемые службами многопротокольной коммутации по меткам (Multiprotocol Label Switching или MPLS), пути, предоставляемые с использованием протокола резервирования ресурсов (Resource Reservation Protocol или RSVP), сети, использующие функции SDN7, или дифференцированные услуги (Differentiated Service) с контролем доступа. На рисунке 1 показан один из ожидаемых вариантов использования, где для измерения и переключения может применяться отдельное устройство. Реакция, вызываемая триггером может быть сообщением управления сетью, передаваемым на вход и/или другим элементам сети, для выполнения соответствующих действий по сигналу CB. Примеры этого варианта применения представлены в параграфе 5.3. Управляемые CB.

3.2.3. Однонаправленные CB на контролируемых путях

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

4. Требования к CB для сетевого транспорта

Ниже приведены требования к реализации CB.

  1. Нужен коммуникационный путь для управляющих сообщений с данными измерения от входного и выходного измерителя в точку измерения (требования 16-18 относятся к передаче управляющих сообщений).

  2. CB требует определить период измерения, в течение которого функция CB Measurement определяет уровень перегрузки или потерь. Этот метод не обнаруживает потери отдельных пакетов, но должен иметь способ о потере и/или маркировке пакетов из потока трафика.

  3. Измеритель может считать маркеры ECN [RFC3168] CE для измерения перегрузки, но в этом случае должны измеряться и потери для полного представления об уровне перегрузки. Для туннелей в [CONGESTION-FEEDBACK] описан способ учёта потерь и маркеров ECN, такие измерения могут применяться на сравнительно коротких интервалах времени для управления реакцией контроля перегрузок и/или агрегирования за больший интервал с более высоким порогом срабатывания CB. В последующих пунктах обсуждается необходимость использовать более длинные интервалы и более высокие пороги триггера.

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

  5. При необходимости CB может объединять последовательные выборки со входа и выхода, чтобы получить усреднённое значение за достаточно долгий интервал. Отметим, что при необходимости объединять выборки комбинация должна отражать сумму отдельных значений выборок, делённую на общее время (объем) измерений. Выборки из разных интервалов нельзя объединять напрямую для получения среднего значения.

  6. Устройство CB должно предотвращать срабатывание при слабой или прерывистой перегрузке (см. 7 — 9).

  7. От CB требуется установка порога для определения события чрезмерной перегрузки.

  8. От CB требуется установка интервала переключения, задающая период в течение которого триггер использует собранные измерения. CB должны срабатывать на достаточно долгое время для предотвращения дополнительного «наказания» для потоков с большим значением RTT на пути.

  9. CB должен быть устойчив к многочисленным событиям перегрузки. Обычно это определяет число наблюдаемых событий сохраняющейся перегрузки в течение периода срабатывания. Например, CB может комбинировать результаты нескольких периодов измерения для определения срабатывания CB (например, срабатывание лишь в случае сохраняющейся перегрузки, обнаруженной при трёх измерениях в интервале срабатывания, когда было собрано более 3 измерений).

  10. При нормальной реакции на триггер следует отключать весь трафик, вызывающий перегрузку (иначе 11 и 12).

  11. Реакция должна быть намного более жёсткой, чем у алгоритма контроля перегрузок (такого как алгоритм контроля перегрузок TCP [RFC5681] или TFRC8 [RFC5348]), поскольку CB реагирует на более длительную перегрузку и работает в большем масштабе времени (т. е. перегрузка сохраняется дольше перед срабатыванием CB).

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

  13. Реакция на срабатывание CB должна сохраняться в течение времени не меньше интервала срабатывания. Обычно для восстановления трафика требуется вмешательство оператора. Если нужен автоматизированный отклик для сброса триггера, он не обязан быть незамедлительным. Автоматизированный механизм сброса следует делать достаточно консервативным, чтобы он не влиял на другие механизмы (включая другие алгоритмы CB, контролирующие трафик по общему пути). Не следует выполнять автоматизированный сброс при наличии признаков продолжающейся перегрузки.

  14. Срабатывание триггера CB следует считать аномальным сетевым событием, которое следует записывать в журнал (log). Измерения, ведущие к срабатыванию CB, также следует записывать в журнал.

  15. Управляющие коммуникации должны передавать измерения (п. 1), а в некоторых случаях нужна передача сообщений триггера на вход. Эти коммуникации могут работать по основному или отдельному каналу. Связь по основному каналу рекомендуется, когда возможен любой вариант устройства. Предпочтительным устройством CB является срабатывание при невозможности получить отчёты об измерениях, показывающие отсутствие перегрузки, в отличие от успешной передачи сигнала о перегрузке отправителю (этот сигнал может быть потерян при перегрузке).

    In Band — по основному каналу

    При управлении по основному каналу следует считать потерю управляющего сообщения индикацией возможной перегрузки на пути, а повторяющиеся потери должны вызывать срабатывание CB. Это решение обеспечивает «общую судьбу» для потоков трафика и управляющих сообщений. Эта общность ослабевает если весь или часть измеренного трафика передаётся по пути, отличающемуся от пути трафика управления (например, разные пути задаёт маршрутизация по множеству равноценных путей, организация трафика или туннели для определённых типов трафика).

    Out of Band — по отдельному каналу

    При управлении по отдельному каналу не следует вызывать реакцию CB при потере управляющих сообщений (например, измерений). Это предотвратит усиление/распространение отказов при независимых отказах на путях измерения и данных. Отказ на отдельном канале следует считать аномальным событием в сети и соответственно обрабатывать. Например, такие события следует записывать в журнал и оператор может выполнять дополнительные действия в зависимости от сети и вовлечённого трафика.
  16. Передача управляющих сообщений должна быть устойчива к потере пакетов. Управляющие сообщения могут теряться при отказе в пути и это ожидается при перегрузке на пути. Это не предполагает желательность гарантированной доставки (например, через TCP), поскольку это может вносить дополнительную задержку при откликах на перегрузку. Подходящим механизмом может быть дублирование управляющих сообщений для повышения устойчивости к потерям и/или отказ от управляющего трафика как индикации продолжающейся перегрузки [RFC8085]. Если управляющие сообщения передаются по общему пути, рекомендуется приоритизировать этот трафик для снижения вероятности потерь при перегрузке. Трафик управления следует также учитывать при приоритизации сети, использующей CB.

  17. Имеются требования к защите управляющих сообщений между конечными точками и/или сетевыми устройствами (раздел 7). Подлинность источника и целостность управляющих сообщений (измерения и триггеры) должны защищаться от атак извне пути. При наличии риска атак в пути рекомендуется применять механизм криптографической аутентификации для всех сообщений управления и измерений.

5. Примеры CB

Имеется множество типов CB, которые могут применяться в разных вариантах развёртывания. В некоторых случаях поток может контролироваться несколькими CB (например, трафик сквозного потока, передаваемый через туннель в сети). В этом разделе представлены примеры разных типов CB.

5.1. Быстрый CB

В [RFC2309] обсуждается опасность не реагирующих на перегрузку потоков и сказано: «во все потоковые приложения UDP следует включать эффективные механизмы предотвращения перегрузок». Некоторые приложения не применяют полнофункциональный транспорт (TCP, SCTP, DCCP) и они (например, при использовании UDP или UDP-Lite) должны обеспечивать надлежащее предотвращение перегрузки. Рекомендации для приложений, не использующих транспорт с контролем перегрузок, приведены в [RFC8085]. Механизмы могут быть устроены так, чтобы реагировать в более коротком масштабе времени, чем CB, где контролируется лишь огибающая трафика (envelope). Методы контроля перегрузок могут взаимодействовать с приложением для более эффективного управления скоростью передачи.

Fast-trip CB является наиболее быстродействующим вариантом CB и обеспечивает время отклика, лишь незначительно превышающее время изменения контролируемого трафика. Метод подходит для трафика с понятными характеристиками (и может включать одну или несколько триггерных функций, адаптированных к типу трафика). Метод не подходит для произвольного сетевого трафика и может не подходить для агрегатов трафика, поскольку может срабатывать преждевременно (например, когда сочетание трафика нескольких потоков с контролем перегрузок вызывает кратковременную перегрузку).

Хотя механизм может быть реализован в сетевых устройствах с поддержкой RTP, он подходит и для реализации в конечных точках (например, как часть транспортной системы), где он может дополнять методы сквозного контроля перегрузок. Быстрый отклик позволяет таким CB переключаться быстрее других вариантов (например, CB, работающих с агрегатами трафика в точках сетевого пути).

5.1.1. Быстрый CB для RTP

Был определён набор методов Fast-Trip CB для использования с потоками протокола доставки в реальном масштабе времени (Real-time Transport Protocol или RTP), использующими профиль RTP/AVP [RFC8083]. Предполагается, что при отсутствии значительной перегрузки все приложения RTP работающие в сетях IP best-effort могту работать без переключения таких CB. Поэтому RTP Fast-Trip CB реализован для устойчивости к отказам (fail-safe) и срабатывание ведёт к прерыванию трафика RTP.

Конечная точка отслеживает получение по основному каналу блоков с отчётами протокола управления RTP (RTP Control Protocol или RTCP), содержащихся в пакетах отчётов отправителя (sender report или SR) или получателя (receiver report или RR), которые обеспечивают обратную связь для качества приёма. Это служит для измерения потерь (перегрузка), возможно, в сочетании с ECN [RFC6679].

Действие CB (остановка потока) вызывается при выполнении любого из указанных ниже условий.

  1. RTP CB срабатывает при отчёте об отсутствии «продвижения» (progress).

  2. RTP CB срабатывает при отсутствии принятых отчётов от получателя.

  3. RTP CB срабатывает, когда долгосрочная пропускная способность RTP (за множество RTT) превышает жёстко заданный верхний порог, определяемый методом, напоминающим TFRC.

  4. RTP CB включает понятие пригодности среды (Media Usability) и срабатывает при снижении качества среды передачи ниже некого минимально допустимого уровня.

5.2. Медленный CB

Slow-Trip CB можно реализовать на конечной точке или сетевом устройстве. Этот тип CB гораздо медленней реагирует на перегрузку, нежели Fast-Trip CB. Предполагается, что он будет применяться более часто.

Одним из случаев, когда требуется Slow-Trip CB, является использованием потоком или агрегатом потоков туннеля или инкапсуляции, при этом не все потоки в туннеле поддерживают контроль перегрузок в стиле TCP (например, TCP, SCTP, TFRC), см. параграф 3.1.3 в [RFC8085]. Это может возникать при развёртывании туннелей в сети Internet (а не в «контролируемой среде» провайдера Internet или корпоративной сети), особенно при прохождении туннеля через клиентский маршрутизатор доступа.

5.3. Управляемые CB

Управляемые CB реализуются в сигнальном протоколе или плоскости управления, связанных с контролируемым агрегатом трафика. Этот тип CB обычно применяется в «контролируемых средах».

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

Можно использовать управляющие сообщения, передаваемые по основному или дополнительному каналу.

5.3.1. Управляемый CB для псевдопроводов SAToP

В разделе 8 [RFC4553] SAToP Pseudowire Emulation Edge-to-Edge (PWE3) описан пример управляемого CB для изохронных потоков. Если такой поток идёт через заранее подготовленную инфраструктуру (например, MPLS), можно предполагать, что в PW не будет возникать перегрузок, поскольку ожидается, что скорость потока не будет расти или снижаться. Если же трафик PW мультиплексируется с другим трафиком в Internet, перегрузки могут возникать. В [RFC4553] сказано: «Если SAToP PW работают через PSN с услугами best-effort, им следует отслеживать потери пакетов для обнаружения серьёзных перегрузок.» В настоящее время рекомендуемый интервал измерения составляет 1 сек. и триггер срабатывает при наблюдении не менее трёх SES9 в интервале измерения. В [RFC4553] также отмечено, что: «при обнаружении таких условий SAToP PW должен на некоторое время отключаться в обоих направлениях …». Идея состояла в том, чтобы при превышении коэффициентом потери пакетов (packet-loss ratio, перегрузка) заданного порога PW по умолчанию отключался. Этот вариант применения рассматривал передачу с фиксированной скоростью, когда у PW нет разумного способа сбросить нагрузку.

Триггер должен устанавливаться на частоту, при которой PW очевидно сталкивается с серьёзной перегрузкой, которая может делать обслуживание неприемлемым. В этот момент срабатывание CB удалит трафик, предотвращая неприемлемое влияние на трафик, реагирующий на перегрузки (например, TCP). Частично обоснование заключалось в том, что высокие потери обычно указывали на какую-либо «поломку» и должны были приводить к вмешательству оператора, поэтому нужно инициировать такое вмешательство.

Вовлечение оператора при срабатывании CB даёт возможность выполнить иные действия по восстановления качества обслуживания (например, отключение другой нагрузки или добавление пропускной способности) или сознательно не реагировать на срабатывание, пока не найдено инженерное решение проблемы. Это может потребовать от триггерной функции передачи управляющего сигнала третьей стороне, например, в центр управления сетью (network operations center или NOC), отвечающей за работу входа в туннель, а не за сам этот вход.

5.3.2. Управляемый CB для псевдопроводов

Псевдопровода (pseudowire или PW) [RFC3985] стали распространённым механизмом туннелирования трафика и могут конкурировать за сетевые ресурсы с другими PW и прочим (не PW) трафиком, таким как потоки TCP/IP.

В [RFC7893] рассмотрены условия перегрузки, которые могут возникать при конкурировании PW с эластичным (т. е. реагирующим на перегрузки) трафиком (например, TCP). Эластичные PW, передающие трафик IP (см.[RFC4448]) не вызывают серьёзных проблем, поскольку вовлечённый в них трафик реагирует на перегрузки в сети снижением скорости передачи.

Неэластичные PW (например, TDM10 [RFC4553] [RFC5086] [RFC5087] с фиксированной пропускной способностью) могут препятствовать реагирующему на перегрузки трафику или способствовать перегрузке, поскольку они не меняют свою скорость в ответ на перегрузки. В [RFC7893] проанализированы TDM PW и сделан вывод, что TDM PW, работающие с уровнем потерь, который может создавать связанные с перегрузками проблемы, будут сталкиваться с неприемлемым качеством работы служб TDM. Поэтому данный документ предполагает, что управляемый CB, отключающий PW при сохраняющейся невозможности предоставить приемлемые услуги TDM, может быть полезным способом решения проблемы перегрузок (см. Приложение A к [RFC7893]).

6. Примеры, где CB могут не требоваться

CB не требуется для одиночного потока с контролем перегрузок, использующего TCP, SCTP, TFRC и т. п. В этих случаях методы контроля перегрузок уже предотвращают сохраняющиеся перегрузки.

6.1. CB на путях с заранее предоставленной полосой

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

Внедрение CB не снизит производительность потоков, но при возникновении сохраняющейся перегрузки это защитит сетевой трафик, использующий общую полосу с перегружающими сеть потоками. Это также защитит сетевой трафик от отказов, когда трафик CB (пере)маршрутизируется, создавая дополнительную сетевую нагрузку на непредусмотренном пути.

6.2. CB в туннелях для трафика с контролем перегрузок

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

Предполагается, что трафик TCP (и SCTP) в туннеле будет снижать свою скорость передачи при обнаружении перегрузки. Другой транспорт (например, UDP) может реализовать механизмы, достаточные для решения проблемы перегрузок на пути [RFC8085]. Однако даже при реализации в каждом потоке, проходящем через туннель, механизма контроля перегрузок общий трафик агрегата потоков все равно может столкнуться с перегрузкой. Например, большинству механизмов контроля перегрузок требуются долгосрочные потоки для реагирования путём снижения скорости. В агрегате может быть много краткосрочных потоков, завершающихся до возникновения перегрузки.

Зачастую поставщик туннельных услуг не знает, что туннель включает лишь трафик с контролем перегрузки (например, проверка заголовков пакетов может быть невозможна). Некоторые приложения IP могут не реализовать адекватных механизмов для решения проблемы перегрузок. Важно отметить, что если агрегат трафика не создаёт сохраняющейся перегрузки (влияющей на другие потоки), CB не будет срабатывать. Это предполагается в данном контексте, поэтому реализация CB не должна снижать производительность туннеля, но при возникновении сохраняющейся перегрузки CB защитит остальной трафик сети, использующий общую пропускную способность с туннельным трафиком.

6.3. CB с односторонним трафиком без пути управления

Односторонний путь пересылки может не иметь связанного пути для пересылки управляющих сообщений, поэтому его нельзя контролировать с помощью CB (сравн. с 3.2.3. Однонаправленные CB на контролируемых путях).

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

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

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

Злоумышленник может воспользоваться CB для организации DoS11-атак на трафик, контролируемый CB. Поэтому нужны механизмы предотвращения атак на данные управления сетью, которые могут вести к DoS-атаке.

Подлинность источника и целостность сообщений протокола (измерения и триггеры) должны защищаться от атак извне пути. Без такой защиты злоумышленник легко может внедрить поддельные или изменённые сообщения контроля и/или измерений (например, указать высокий уровень потерь), вынуждающие CB срабатывать, что позволяет организовать DoS-атаки нарушающие потоки.

Простую защиту можно обеспечить за счёт использования случайного порта источника или эквивалентного поля в заголовке пакетов (например, RTP SSRC или порядковый номер RTP), которые считаются неизвестными атакующему извне пути. Более сильную защиту можно обеспечить с помощью защищённого протокола аутентификации.

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

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

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

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

8. Литература

8.1. Нормативные документы

[RFC2119] Bradner, S., «Key words for use in RFCs to Indicate Requirement Levels», BCP 14, RFC 2119, DOI 10.17487/RFC2119, March 1997, <http://www.rfc-editor.org/info/rfc2119>.

[RFC3168] Ramakrishnan, K., Floyd, S., and D. Black, «The Addition of Explicit Congestion Notification (ECN) to IP», RFC 3168, DOI 10.17487/RFC3168, September 2001, <http://www.rfc-editor.org/info/rfc3168>.

[RFC8085] Eggert, L., Fairhurst, G., and G. Shepherd, «UDP Usage Guidelines», BCP 145, RFC 8085, DOI 10.17487/RFC8085, March 2017, <http://www.rfc-editor.org/info/rfc8085>.

8.2. Дополнительная литература

[CONGESTION-FEEDBACK] Wei, X., Zhu, L., and L. Deng, «Tunnel Congestion Feedback», Work in Progress, draft-ietf-tsvwg-tunnel-congestion-feedback-04, January 2017.

[Jacobson88] Jacobson, V., «Congestion Avoidance and Control», SIGCOMM Symposium proceedings on Communications architectures and protocols, August 1988.

[RFC1112] Deering, S., «Host extensions for IP multicasting», STD 5, RFC 1112, DOI 10.17487/RFC1112, August 1989, <http://www.rfc-editor.org/info/rfc1112>.

[RFC2309] Braden, B., Clark, D., Crowcroft, J., Davie, B., Deering, S., Estrin, D., Floyd, S., Jacobson, V., Minshall, G., Partridge, C., Peterson, L., Ramakrishnan, K., Shenker, S., Wroclawski, J., and L. Zhang, «Recommendations on Queue Management and Congestion Avoidance in the Internet», RFC 2309, DOI 10.17487/RFC2309, April 1998, <http://www.rfc-editor.org/info/rfc2309>.

[RFC2914] Floyd, S., «Congestion Control Principles», BCP 41, RFC 2914, DOI 10.17487/RFC2914, September 2000, <http://www.rfc-editor.org/info/rfc2914>.

[RFC3985] Bryant, S., Ed. and P. Pate, Ed., «Pseudo Wire Emulation Edge-to-Edge (PWE3) Architecture», RFC 3985, DOI 10.17487/RFC3985, March 2005, <http://www.rfc-editor.org/info/rfc3985>.

[RFC4448] Martini, L., Ed., Rosen, E., El-Aawar, N., and G. Heron, «Encapsulation Methods for Transport of Ethernet over MPLS Networks», RFC 4448, DOI 10.17487/RFC4448, April 2006, <http://www.rfc-editor.org/info/rfc4448>.

[RFC4553] Vainshtein, A., Ed. and YJ. Stein, Ed., «Structure-Agnostic Time Division Multiplexing (TDM) over Packet (SAToP)», RFC 4553, DOI 10.17487/RFC4553, June 2006, <http://www.rfc-editor.org/info/rfc4553>.

[RFC5086] Vainshtein, A., Ed., Sasson, I., Metz, E., Frost, T., and P. Pate, «Structure-Aware Time Division Multiplexed (TDM) Circuit Emulation Service over Packet Switched Network (CESoPSN)», RFC 5086, DOI 10.17487/RFC5086, December 2007, <http://www.rfc-editor.org/info/rfc5086>.

[RFC5087] Stein, Y(J)., Shashoua, R., Insler, R., and M. Anavi, «Time Division Multiplexing over IP (TDMoIP)», RFC 5087, DOI 10.17487/RFC5087, December 2007, <http://www.rfc-editor.org/info/rfc5087>.

[RFC5348] Floyd, S., Handley, M., Padhye, J., and J. Widmer, «TCP Friendly Rate Control (TFRC): Protocol Specification», RFC 5348, DOI 10.17487/RFC5348, September 2008, <http://www.rfc-editor.org/info/rfc5348>.

[RFC5681] Allman, M., Paxson, V., and E. Blanton, «TCP Congestion Control», RFC 5681, DOI 10.17487/RFC5681, September 2009, <http://www.rfc-editor.org/info/rfc5681>.

[RFC6679] Westerlund, M., Johansson, I., Perkins, C., O’Hanlon, P., and K. Carlberg, «Explicit Congestion Notification (ECN) for RTP over UDP», RFC 6679, DOI 10.17487/RFC6679, August 2012, <http://www.rfc-editor.org/info/rfc6679>.

[RFC7761] Fenner, B., Handley, M., Holbrook, H., Kouvelas, I., Parekh, R., Zhang, Z., and L. Zheng, «Protocol Independent Multicast — Sparse Mode (PIM-SM): Protocol Specification (Revised)», STD 83, RFC 7761, DOI 10.17487/RFC7761, March 2016, <http://www.rfc-editor.org/info/rfc7761>.

[RFC7893] Stein, Y(J)., Black, D., and B. Briscoe, «Pseudowire Congestion Considerations», RFC 7893, DOI 10.17487/RFC7893, June 2016, <http://www.rfc-editor.org/info/rfc7893>.

[RFC8083] Perkins, C. and V. Singh, «Multimedia Congestion Control: Circuit Breakers for Unicast RTP Sessions», RFC 8083, DOI 10.17487/RFC8083, March 2017, <http://www.rfc-editor.org/info/rfc8083>.

Благодарности

Много людей обсуждало и описывало проблемы, ставшие мотивами этого документа. Вклад и комментарии представили Lars Eggert, Colin Perkins, David Black, Matt Mathis, Andrew McGregor, Bob Briscoe, Eliot Lear. Эта работа частично финансировалась Европейской комиссией по программе Seventh Framework в рамках проекта Reducing Internet Transport Latency (RITE) (ICT-317700).

Адрес автора

Godred Fairhurst
University of Aberdeen
School of Engineering
Fraser Noble Building
Aberdeen, Scotland AB24 3UE
United Kingdom
Email: gorry@erg.abdn.ac.uk
URI: http://www.erg.abdn.ac.uk

Перевод на русский язык

Николай Малых

nmalykh@protokols.ru

1Internet Engineering Task Force — комиссия по решению инженерных задач Internet.

2Internet Engineering Steering Group — комиссия по инженерным разработкам Internet.

3Stream Control Transmission Protocol — протокол управления потоковой передачей.

4Datagram Congestion Control Protocol — протокол контроля перегрузки для дейтаграмм.

5Operations, Administration and Management — операции, администрирование, управление.

6Protocol Independent Multicast — Sparse Mode — независимая от протокола групповая передача — разреженный режим.

7Software-Defined Network — программно-определяемая сеть.

8TCP-Friendly Rate Control — дружественный к TCP контроль скорости.

9Severely Errored Second — секунда со значительным числом ошибок.

10Time Division Multiplex — мультиплексирование с разделением по времени.

11Denial-of-Service — отказ в обслуживании.

Рубрика: RFC | Оставить комментарий

RFC 8060 LISP Canonical Address Format (LCAF)

Internet Engineering Task Force (IETF)                      D. Farinacci
Request for Comments: 8060                                   lispers.net
Category: Experimental                                          D. Meyer
ISSN: 2070-1721                                                  Brocade
                                                             J. Snijders
                                                                     NTT
                                                           February 2017

LISP Canonical Address Format (LCAF)

Канонический формат адресов LISP (LCAF)

PDF

Аннотация

Этот документ определяет канонический формат кодирования адресов, используемых в управляющих сообщениях протокола LISP, и кодирования ключей поиска для системы сопоставления LISP (Mapping Database System).

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

Документ не содержит стандарта Internet и публикуется для проверки, экспериментальной реализации и оценки.

Документ определяет экспериментальный протокол для сообщества Internet. Документ является результатом работы IETF1 и представляет согласованный взгляд сообщества IETF. Документ прошёл открытое обсуждение и был одобрен для публикации IESG2. Не все документы, одобренные IESG претендуют на статус Internet Standard. Дополнительную информацию о стандартах Internet можно найти в разделе 2 в RFC 7841.

Информация о текущем статусе документа, найденных ошибках и способах обратной связи доступна по ссылке http://www.rfc-editor.org/info/rfc8060.

Авторские права

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

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

1. Введение

Архитектура и протокол LISP [RFC6830] добавили два новых пространства номеров — идентификаторы конечных точек (Endpoint Identifier или EID) и локаторы маршрутизации (Routing Locator — RLOC). Для обеспечения гибкости имеющимся и будущим приложениям эти значения могут кодироваться в управляющих сообщениях LISP с использованием базового синтаксиса, включающего идентификатор семейства адресов (Address Family Identifier или AFI), размер и значение.

В настоящее время AFI включают адреса IPv4 и IPv6, форматируемые в соответствии с кодом из реестра Address Family Numbers [AFN], как показано ниже.

IPv4

    0                   1                   2                   3
    0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
   |            AFI = 1            |       IPv4 Address ...        |
   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
   |     ...  IPv4 Address         |
   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+

IPv6

    0                   1                   2                   3
    0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
   |            AFI = 2            |       IPv6 Address ...        |
   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
   |                     ...  IPv6 Address  ...                    |
   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
   |                     ...  IPv6 Address  ...                    |
   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
   |                     ...  IPv6 Address  ...                    |
   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
   |     ...  IPv6 Address         |
   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+

В этом документе описаны определённые к настоящему моменту AFI, которые в LISP используются вместе с их кодами, и введён канонический формат адреса LISP (LISP Canonical Address Format или LCAF), который может служить для определения специфичных для LISP кодировок произвольных AFI.

Конкретные детали применения типов LCAF, определённых в этом документе, могут быть представлены в документах по реализующим их вариантам применения. Один и тот же LCAF Type может использоваться в нескольких документах о вариантах применения. Как экспериментальная спецификация, эта работа по определению не полна.

Типы LCAF, определённые в этом документе предназначены для поддержки экспериментов и осторожного применения в автономных средах во поддержку соответствующих документов о применении. Документ назначает исходный набор утвержденных LCAF Type (зарегистрированных в IANA) и дополнительных, ещё не одобренных LCAF Type [RFC6830]. Неодобренное кодирование LCAF задано для поддержки дальнейших исследований и экспериментов.

2. Терминология

2.1. Уровни требований

Ключевые слова необходимо (MUST), недопустимо (MUST NOT), требуется (REQUIRED), нужно (SHALL), не следует (SHALL NOT), следует (SHOULD), не нужно (SHOULD NOT), рекомендуется (RECOMMENDED), не рекомендуется (NOT RECOMMENDED), возможно (MAY), необязательно (OPTIONAL) в данном документе интерпретируются в соответствии с [RFC2119].

2.2. Определения терминов

Address Family Identifier (AFI) — идентификатор семейства адресов

Термин, применяемый для описания кодирования адреса в пакете. Семейства адресов определены для IPv4 и IPv6. Подробности приведены в [AFN] и [RFC3232]. Резервное значение AFI = 0 служит в этой спецификации для указания незаданного кодирования, где адрес имеет нулевой размер (нет адреса).

Unspecified Address Format — незаданный формат адреса

    0                   1                   2                   3
    0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
   |            AFI = 0            |      <нет адреса>
   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+

Endpoint ID (EID) — идентификатор конечной точки

32-битовое (IPv4) или 128-битовое (IPv6) значение, используемое в полях адресов отправителя и получателя в первом (внутреннем) заголовке LISP в пакете. Хост получает EID адресата так же, как это делается сегодня, например, через запрос DNS или обмен SIP. EID источника получается через имеющиеся механизмы, применяемые для установки «локального» IP-адреса хоста. EID выделяется хосту из префикса EID, связанного с сайтом, где размещается хост. EID может использоваться хостом для указания другого хоста.

Routing Locator (RLOC) — локатор маршрутизации

Адрес IPv4 или IPv6 выходного маршрутизатора туннеля (Egress Tunnel Router или ETR). Это результат поиска в сопоставлении EID с RLOC. EID отображается на один или несколько локаторов RLOC. Обычно RLOC выделяются из топологически агрегируемых блоков, выделенных сайту в каждой точке присоединения к глобальной сети Internet. Топология определяется связностью сетей провайдеров и RLOC можно считать выделенными провайдером (Provider-Assigned или PA) адресами. Одному или нескольким устройствам ETR на сайте может быть выделено множество RLOC.

3. Каноническое кодирование адресов в LISP

Агентство IANA выделило значение AFI = 16387 (0x4003) для формата LCAF. Эта спецификация задаёт формат кодирования канонических адресов LISP (LISP Canonical Address или LCA). В этом параграфе определены все типы, для которых запрошено исходное назначение в реестре LISP-LCAF. Список типов представлен в разделе 7. Взаимодействие с IANA.

Определения AFI в [AFN] лишь назначают коды для самих значений AFI. Размер адреса или следующего за ним элемента не задан и предполагается основанным на общепринятом опыте. Для использования в LISP определений LCAF из этого документа размер основанного на AFI адреса задан в документе. При задании новых определений LCAF в других документах по применению размер основанного на AFI адреса для новых адресов с кодированием AFI следует задавать в таких документах.

За первыми 6 байтами LCA следует переменное число полей переменного размера, как показано на рисунке.

    0                   1                   2                   3
    0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
   |           AFI = 16387         |     Rsvd1     |     Flags     |
   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
   |    Type       |     Rsvd2     |            Length             |
   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
   |                             . . .                             |
   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+

Rsvd1/Rsvd2

Эти 8-битовые поля зарезервированы на будущее и должны содержать значение 0 при передаче, а при получении — игнорироваться.

Flags

Это 8-битовое поле рассчитано на будущее. В настоящее время устанавливается в 0 при передаче и игнорируется при получении.

Type

Это 8-битовое поле относится к кодированию LCAF. Ниже указаны обобренные и не одобренные значения типов. Дополнительные сведения приведены в разделе 5. Экспериментальное использование канонических адресов LISP.
Type 0: Null Body
Type 1: AFI List
Type 2: Instance ID
Type 3: AS Number
Type 4: Application Data (не утверждён, см. 5. Экспериментальное использование канонических адресов LISP)
Type 5: Geo-Coordinates
Type 6: Opaque Key (не утверждён, см. 5. Экспериментальное использование канонических адресов LISP)
Type 7: NAT-Traversal
Type 8: Nonce Locator (не утверждён, см. 5. Экспериментальное использование канонических адресов LISP)
Type 9: Multicast Info
Type 10: Explicit Locator Path
Type 11: Security Key
Type 12: Source/Dest Key
Type 13: Replication List Entry
Type 14: JSON Data Model (не утверждён, см. 5. Экспериментальное использование канонических адресов LISP)
Type 15: Key/Value Address Pair (не утверждён, см. раздел 5)
Type 16: Encapsulation Format (не утверждён, см. раздел 5)

Length

Это 16-битовое поле указывает размер в байтах всего содержимого LCA, после поля Length. При использовании AFI минимальный размер адреса в кодировке LCAF составляет 8 байтов и Length = 0. Эти 8 байтов включают поля AFI, Flags, Type, Rsvd1, Rsvd2, Length. Когда AFI нет вместе с закодированным адресом в управляющем сообщении, минимальный размер адреса составляет 6 байтов и Length = 0. Эти 6 байтов включают поля Flags, Type, Rsvd1, Rsvd2, Length.

В [RFC6830] указано, что записи RLOC, основанные на адресе IP, сортируются при кодировании в управляющих сообщениях, поэтому набор локаторов (locator-set) имеет согласованный порядок во всех xTR для данного EID. Порядок сортировки определяется ключом {afi, адрес RLOC}. При кодировании RLOC на основе адреса IP в LCAF ключом сортировки является {afi, LCAF-Type}. Поэтому при смешении в locator-set записей AFI и LCAF они упорядочиваются по AFI (от меньшего к большему).

4. Применение канонических адресов LISP

В следующих параграфах даны определения LCAF для одобренных значений Type исходного набора.

4.1. Сегментация с использованием LISP

Когда несколько организаций на сайте LISP использует приватные адреса [RFC1918] как префиксы EID, адресные пространства организаций должны быть разделены по причине возможного дублирования адресов. Поле Instance ID в кодировании адреса позволяет сделать весь адрес на основе AFI уникальным.

Другим применением Instance ID в LCAF является создание нескольких сегментированных VPN внутри сайта LISP, когда желательно сохранить подсети, основанные на префиксах EID.

Instance ID LCAF

    0                   1                   2                   3
    0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
   |           AFI = 16387         |     Rsvd1     |     Flags     |
   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
   |   Type = 2    | IID mask-len  |            Length             |
   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
   |                         Instance ID                           |
   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
   |              AFI = x          |         Address  ...          |
   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+

IID mask-len

Если AFI = 0, этот формат не кодирует расширенный префикс EID, а представляет лишь диапазон Instance ID, где IID mask-len указывает число старших битов в поле Instance ID для диапазона. Младшие биты Instance ID должны иметь значение 0.

Length

Размер в байтах, начиная с байта сразу после этого поля Length.

Instance ID

Младшие 24 бита, которые могут войти в заголовок данных LISP, когда установлен бит I (см. [RFC6830]). Причина разницы в размере заключается в том, что максимальное число экземпляров, поддерживаемых системой отображения, составляет 232, а место в заголовке данных LISP экономится. С этим связано ограничение максимального числа экземпляров на xTR значением 224. Если на xTR настроено множество Instance ID с совпадающими старшими 8 битами, младшие 24 бита должны быть уникальными.

AFI = x

x может быть любым значением AFI из [AFN].

Тип LCA можно применять для кодирования адресов EID и RLOC.

При использовании в качестве ключа поиска EID рассматривается в системе сопоставления как extended-EID. Это кодирование применяется в записях EID сообщений Map-Request, Map-Reply, Map-Register, Map-Notify. При использовании дерева делегированных баз данных (LISP Delegated Database Tree или LISP-DDT) [LISP-DDT] в качестве механизма системы сопоставления в сообщениях Map-Referral применяются расширенные EID.

4.2. Передача номеров AS в базе сопоставлений

При сохранении номера автономной системы (Autonomous System или AS) в базе данных системы сопоставления LISP (Mapping Database System) для политики или документирования его можно закодировать в LCA.

AS Number LCAF

    0                   1                   2                   3
    0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
   |           AFI = 16387         |     Rsvd1     |     Flags     |
   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
   |   Type = 3    |     Rsvd2     |             Length            |
   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
   |                           AS Number                           |
   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
   |              AFI = x          |         Address  ...          |
   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+

Length

Размер в байтах, начиная с байта сразу после этого поля Length.

AS Number

32-битовый номер AS, который выделен для последующего EID или RLOC.

AFI = x

x может быть любым значением AFI из [AFN].

Тип AS Number LCAF можно применять для кодирования адресов EID и RLOC. Первый служит для описания номера AS LISP-ALT префикса EID сайта для которого запись передаётся. Второй применяется для описания AS, которая содержит префиксы на основе RLOC в базовой системе маршрутизации.

Это кодирование может применяться в записях EID или RLOC сообщений Map-Request, Map-Reply, Map-Register, Map-Notify. При использовании LISP-DDT [LISP-DDT] в качестве механизма системы сопоставления в сообщениях Map-Referral применяются расширенные EID.

4.3. Назначение географических координат адресам локаторов

Если ETR хочет передать сообщение Map-Reply, описывающее географические координаты (Geo-Coordinates) для каждого локатора в своём locator-set, он может использовать тип Geo-Coordinates LCAF для передачи сведений о физическом местоположении. Координаты задаются с использованием эталонной системы WGS 84 (World Geodetic System 1984) [WGS-84].

Geo-Coordinates LCAF

    0                   1                   2                   3
    0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
   |           AFI = 16387         |     Rsvd1     |     Flags     |
   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
   |   Type = 5    |     Rsvd2     |            Length             |
   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
   |N|     Latitude Degrees        |    Minutes    |    Seconds    |
   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
   |E|     Longitude Degrees       |    Minutes    |    Seconds    |
   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
   |                            Altitude                           |
   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
   |              AFI = x          |         Address  ...          |
   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+

Length

Размер в байтах, начиная с байта сразу после этого поля Length.

N

1 означает север, все остальное — юг.

Latitude Degrees

Значение широты в градусах (0 — 90) относительно экватора (северная или южная полусфера).

Latitude Minutes

Минуты широты (0 — 59).

Latitude Seconds

Секунды широты (0 — 59).

E

1 означает восток, все остальное — запад.

Longitude Degrees

Значение долготы в градусах (0 — 180) относительно нулевого меридиана (Prime Meridian).

Longitude Minutes

Минуты долготы (0 — 59).

Longitude Seconds

Секунды долготы (0 — 59).

Altitude

Высота над уровнем моря в метрах, указанная целочисленным дополнением до 2 со знаком. Значение 0x7fffffff указывает неизвестную высоту.

AFI = x

x может быть любым значением AFI из [AFN].

Тип Geo-Coordinates LCAF может применяться для кодирования адресов EID и RLOC. При использовании для EID можно указать физическое местоположение EID вместе с топологическим размещением, наблюдая locator-set.

Это кодирование может применяться в записях EID или RLOC сообщений Map-Request, Map-Reply, Map-Register, Map-Notify. При использовании LISP-DDT [LISP-DDT] в качестве механизма системы сопоставления в сообщениях Map-Referral применяются расширенные EID.

Использование кодирования Geo-Coordinates LCAF может вызывать проблемы приватности, поскольку сведения о расположении могут быть приватными, например при размещении устройства в жилище. Поэтому такое кодирование не следует применять, пока оно не требуется для работы развёртывания LISP. До принятия решения о применении кодирования следует убедиться, что EID использует подходящие правила для контроля передаваемой информации.

4.4. Варианты работы через NAT

Когда система LISP передаёт сведения о глобальном адресе и отображённом порте через устройство NAT, применяется тис NAT-Traversal LCAF (см. [NAT-LISP]).

NAT-Traversal LCAF

    0                   1                   2                   3
    0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
   |           AFI = 16387         |     Rsvd1     |     Flags     |
   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
   |   Type = 7    |     Rsvd2     |             Length            |
   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
   |       MS UDP Port Number      |      ETR UDP Port Number      |
   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
   |              AFI = x          |  Global ETR RLOC Address  ... |
   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
   |              AFI = x          |       MS RLOC Address  ...    |
   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
   |              AFI = x          | Private ETR RLOC Address  ... |
   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
   |              AFI = x          |      RTR RLOC Address 1 ...   |
   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
   |              AFI = x          |      RTR RLOC Address k ...   |
   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+

Length

Размер в байтах, начиная с байта сразу после этого поля Length.

MS UDP Port Number

Номер порта UDP на Map-Server (4342).

ETR UDP Port Number

Номер порта, возвращённый системе LISP, который был скопирован из порта источника в пакете, прошедшем NAT.

AFI = x

x может быть любым значением AFI из [AFN].

Global ETR RLOC Address

Заведомо уникальный в глобальном масштабе адрес, созданный функциональность работы через NAT в маршрутизаторе LISP.

MS RLOC Address

Адрес Map-Server, используемый в RLOC получателя пакета, прошедшего через NAT.

Private ETR RLOC Address

Заведомо приватный адрес, помещённый в LCAF маршрутизатором LISP на приватной стороне устройства NAT.

RTR RLOC Address

Адрес инкапсуляции, применяемый ITR или PITR3, находящимся за NAT. Известно, что для этого адреса имеется состояние NAT, чтобы пакеты могли проходить с этого адреса маршрутизатору LISP ETR, расположенному за NAT. В этом наборе полей может указываться один или несколько адресов маршрутизаторов NAT RTR4 [NAT-LISP]. Число RTR определяется при разборе каждого поля. Если RTR не указаны, поля RTR можно опустить и отразить в поле размера LCAF или можно использовать AFI = 0 для указания отсутствия RTR.

Это кодирование может применяться в сообщениях Info-Request и Info-Reply. Система сопоставления не хранить эти сведения, их используют xTR и Map-Server для передачи приватного и публичного адреса при работе через NAT или межсетевые экраны.

Следует позаботиться о защите приватности от неправомерного использования глобального или приватного адреса ETR RLOC, обеспечив правила контроля и применения регистраций EID, использующих этот тип LCAF в записях RLOC. Дополнительные сведения можно найти в документах по применению.

4.5. Сведения о принадлежности к Multicast-группе

Сведения о Multicast-группах могут публиковаться в базе сопоставлений. Поиск по групповому адресу EID может возвращать список групповых или индивидуальных адресов RLOC для репликации. Назначение этого типа индивидуальной репликации состоит в доставке пакетов множеству ETR на сайтах LISP групповых получателей. Кодирование locator-set для типа EID-record может быть списком ETR, когда каждый из них регистрируется с семантикой слияния (Merge Semantics). Кодирование может быть типовым адресом локатора в кодировке AFI. При регистрации списка RTR (с несколькими уровнями в соответствии с [LISP-RE]) для кодирования локатора применяется тип Replication List Entry LCAF.

Это кодирование LCAF можно применять для передачи групповых пакетов все члена в подсети, когда EID находится за пределами домашней подсети.

Multicast Info LCAF

    0                   1                   2                   3
    0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
   |           AFI = 16387         |     Rsvd1     |     Flags     |
   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
   |   Type = 9    |     Rsvd2     |             Length            |
   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
   |                         Instance ID                           |
   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
   |            Reserved           | Source MaskLen| Group MaskLen |
   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
   |              AFI = x          |   Source/Subnet Address  ...  |
   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
   |              AFI = x          |       Group Address  ...      |
   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+

Length

Размер в байтах, начиная с байта сразу после этого поля Length.

Reserved

Должно устанавливаться в 0 при передаче и игнорироваться при получении.

Instance ID

Младшие 24 бита, которые могут войти в заголовок данных LISP, когда установлен бит I (см. [RFC6830]). Использование Instance ID в этом типе LCAF заключается в связывании записи групповой пересылки для данной сети VPN. Instance ID описывает VPN и регистрируется в системе сопоставления как триплет (Instance ID, S-prefix, G-prefix).

Source MaskLen

Размер маски в последующем префиксе (число установленных старших битов маски).

Group MaskLen

Размер маски в последующем групповом префиксе (число установленных старших битов маски).

AFI = x

x может быть любым значением AFI из [AFN]. Когда конкретное семейство адресов имеет семантику группового адреса, это поле должно содержать адрес группы или широковещательный адрес.

Source/Subnet Address

Адрес или префикс источника для кодирования групповой записи (S,G).

Group Address

Групповой адрес или префикс для кодирования групповых записей (S,G) или (*,G).

Это кодирование может применяться в записях EID сообщений Map-Request, Map-Reply, Map-Register, Map-Notify. При использовании LISP-DDT [LISP-DDT] в качестве механизма системы сопоставления в сообщениях Map-Referral применяются расширенные EID.

4.6. Организация трафика (TE) с повторной инкапсуляцией туннелей

При поиске данного EID в базе сопоставления может возвращаться этот формат LCAF для предоставления списка локаторов на явном пути с повторной инкапсуляцией (см. [LISP-TE]).

Explicit Locator Path (ELP) LCAF

    0                   1                   2                   3
    0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
   |           AFI = 16387         |     Rsvd1     |     Flags     |
   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
   |   Type = 10   |     Rsvd2     |            Length             |
   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
   |           Rsvd3         |L|P|S|           AFI = x             |
   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
   |                         Reencap Hop 1  ...                    |
   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
   |           Rsvd3         |L|P|S|           AFI = x             |
   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
   |                         Reencap Hop k  ...                    |
   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+

Length

Размер в байтах, начиная с байта сразу после этого поля Length.

Rsvd3

Должно устанавливаться в 0 при передаче и игнорироваться при получении.

Lookup bit (L)

Бит поиска (Lookup) служащий для указания пользователю ELP не применять этот адрес при инкапсуляции, а искать его в базе сопоставлений для получения инкапсулирующего адреса RLOC.

RLOC Probe bit (P)

Это бит зонда RLOC Probe, означающий, что Reencap Hop разрешает передавать ему сообщения RLOC-probe. При сброшенном (0) бите P передавать RLOC-probe недопустимо. Когда Reencap Hop указывает anycast-адрес, несколько физических Reencap Hop используют один адрес RLOC. В этом случае RLOC-probe не нужны, поскольку при недоступности ближайшего адреса RLOC будет использован другой.

Strict bit (S)

Бит строгости (Strict), указывающий необходимость использования связанного Reencap Hop. При сброшенном (0) бите реинкапсулятор может пропустить этот Reencap и перейти к следующему в списке.

AFI = x

x может быть любым значением AFI из [AFN]. Когда AFI имеет семантику кодирования группового адреса, это поле должно содержать адрес группы или широковещательный адрес.

Это кодирование может применяться в записях RLOC сообщений Map-Request, Map-Reply, Map-Register, Map-Notify. Это кодирование не требуется понимать системе сопоставления для поиска в базе данных, поскольку этот тип LCAF не является ключом поиска.

4.7. Сохранение данных защиты в системе сопоставления

Когда локатор в locator-set имеет связанный ключ защиты, этот тип LCAF служит для кодирования ключевого материала (см. [LISP-DDT]).

Security Key LCAF

    0                   1                   2                   3
    0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
   |           AFI = 16387         |     Rsvd1     |     Flags     |
   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
   |   Type = 11   |      Rsvd2    |             Length            |
   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
   |   Key Count   |      Rsvd3    | Key Algorithm |   Rsvd4     |R|
   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
   |           Key Length          |       Key Material ...        |
   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
   |                        ... Key Material                       |
   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
   |              AFI = x          |       Locator Address ...     |
   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+

Length

Размер в байтах, начиная с байта сразу после этого поля Length.

Key Count

Число разделов Key (Key Length и Key Material) в LCAF.

Rsvd3

Должно устанавливаться в 0 при передаче и игнорироваться при получении.

Key Algorithm

Указывает криптографический алгоритм ключа и задаёт формат поля Public Key. Примеры использования определений для этого поля даны в [LISP-DDT] и [RFC8061].

Rsvd4

Должно устанавливаться в 0 при передаче и игнорироваться при получении.

R bit

Бит отзыва (Revoke), установка которого указывает отзыв ключа.

Key Length

Размер поля Key Material в байтах.

Key Material

Ключевой материал, формат хранения которого зависит от поля Key Algorithm.

AFI = x

x может быть любым значением AFI из [AFN]. Это адрес локатора, владеющего закодированным ключом защиты.

Это кодирование может применяться в записях EID или RLOC сообщений Map-Request, Map-Reply, Map-Register, Map-Notify. При использовании LISP-DDT [LISP-DDT] в качестве механизма системы сопоставления в сообщениях Map-Referral применяются расширенные EID.

4.8. Поиск по парам отправитель-получатель

Когда адреса отправителя и получателя в потоке требуют рассмотрения разных locator-set, эта пара служит ключом для поска в полях EID управляющих сообщений LISP. Когда ключ Source/Dest зарегистрирован в базе сопоставлений, он будет кодироваться как префиксы отправителя и получателя. При использовании Source/Dest в качестве ключа при поиске в базе сопоставления источник и получатель берутся из пакета данных.

Source/Dest Key LCAF

    0                   1                   2                   3
    0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
   |           AFI = 16387         |     Rsvd1     |     Flags     |
   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
   |   Type = 12   |     Rsvd2     |             Length            |
   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
   |            Reserved           |   Source-ML   |    Dest-ML    |
   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
   |              AFI = x          |         Source-Prefix ...     |
   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
   |              AFI = y          |     Destination-Prefix ...    |
   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+

Length

Размер в байтах, начиная с байта сразу после этого поля Length.

Reserved

Должно устанавливаться в 0 при передаче и игнорироваться при получении.

Source-ML

Размер маски последующего префикса источника (число установленных старших битов маски).

Dest-ML

Размер маски последующего префикса получателя (число установленных старших битов маски).

AFI = x

x может быть любым значением AFI из [AFN].

AFI = y

y может быть любым значением AFI из [AFN]. Когда AFI имеет семантику кодирования группового адреса, это поле должно содержать адрес группы или широковещательный адрес.

Это кодирование может применяться в записях EID сообщений Map-Request, Map-Reply, Map-Register, Map-Notify. При использовании LISP-DDT [LISP-DDT] в качестве механизма системы сопоставления в сообщениях Map-Referral применяются расширенные EID. Детали применения этого типа LCAF приведены в [LISP-TE].

4.9. Записи списка репликации для групповой пересылки

Тип Replication List Entry LCAF — это кодирование локатора, который будет применяться для индивидуальной репликации в соответствии с [LISP-RE]. Это кодирование указывает тип Multicast Info LCAF и оно регистрируется маршрутизаторами RTR, участвующими в нароженном дереве распространения. Каждый маршрутизатор RTR регистрирует свой адрес RLOC и заданный в дереве растространения уровень.

Replication List Entry LCAF

    0                   1                   2                   3
    0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
   |           AFI = 16387         |     Rsvd1     |     Flags     |
   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
   |   Type = 13   |    Rsvd2      |             Length            |
   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
   |              Rsvd3            |     Rsvd4     |  Level Value  |
   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
   |              AFI = x          |           RTR/ETR #1 ...      |
   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
   |              Rsvd3            |     Rsvd4     |  Level Value  |
   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
   |              AFI = x          |           RTR/ETR  #n ...     |
   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+

Length

Размер в байтах, начиная с байта сразу после этого поля Length.

Rsvd3/Rsvd4

Должно устанавливаться в 0 при передаче и игнорироваться при получении.

Level Value

Значение, связанное с уровнем в иерархии дерева распространения, к которой относится RTR. Значения уровня упорядочиваются от меньших, которые ближе всего к ITR (ITR реплицируют в RTR уровня 0), к большим, расположенным ближе к ETR сайта группового получателя.

AFI = x

x может быть любым значением AFI из [AFN]. Когда AFI имеет семантику кодирования группового адреса, это поле должно содержать адрес группы или широковещательный адрес. В целях эффективности все записи RTR/ETR для одного уровня серверу Map-Server следует объединять для предотвращения поиска по всему многоуровневому списку локаторов в сообщении Map-Reply.

Это кодирование может применяться в записях RLOC сообщений Map-Request, Map-Reply, Map-Register, Map-Notify.

4.10. Применение типа AFI List LCAF

4.10.1. Связывание адресов IPv4 и IPv6

Когда желательна трансляция между адресами IPv4 и IPv6, можно применять канонический адрес LISP типа AFI List LCAF для передачи переменного числа AFI в одном LCAF AFI.

Address Binding LCAF

    0                   1                   2                   3
    0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
   |           AFI = 16387         |     Rsvd1     |     Flags     |
   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
   |   Type = 1    |     Rsvd2     |            Length             |
   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
   |            AFI = 1            |       IPv4 Address ...        |
   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
   |     ...  IPv4 Address         |            AFI = 2            |
   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
   |                          IPv6 Address ...                     |
   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
   |                     ...  IPv6 Address  ...                    |
   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
   |                     ...  IPv6 Address  ...                    |
   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
   |                     ...  IPv6 Address                         |
   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+

Length

Размер в байтах, начиная с байта сразу после этого поля Length.

Этот тип формата может быть включён в Map-Request, когда адрес применяется в качестве EID, но поиск адресата в системе сопоставления LISP может использовать только адреса IPv4. Это связано с тем, что транспортная система службы сопоставления, такая как LISP-ALT [RFC6836], может применять адрес получателя Map-Request для маршрутизации управляющего сообщения на желаемый сайт LISP.

Применение. Это кодирование может применяться в записях EID или RLOC сообщений Map-Request, Map-Reply, Map-Register, Map-Notify. Примеры использования представления в других параграфах этого раздела.

4.10.2. L2 VPN

При хранении в системе сопоставления LISP адресов MAC (Media Access Control), можно применять тип AFI List LCAF для передачи AFI 6.

MAC Address LCAF

    0                   1                   2                   3
    0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
   |           AFI = 16387         |     Rsvd1     |     Flags     |
   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
   |   Type = 1    |     Rsvd2     |             Length            |
   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
   |             AFI = 6           |    Layer 2 MAC Address  ...   |
   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
   |                    ... Layer 2 MAC Address                    |
   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+

Length

Размер в байтах, начиная с байта сразу после этого поля Length.

Этот формат адреса может применяться при соединении доменов L2 с использованием LISP через ядро IPv4 или IPv6 для создания L2 VPN. В этом случае MAC-адрес выступает как EID, а locator-set с которым сопоставляется EID, может быть RLOC IPv4 или IPv6 и даже MAC-адресом,применяемым как RLOC. В [EID-MOBILITY] описана работа L2 VPN при мобильности EID.

Следует принять меры защиты приватности от неправомерного использования адреса L2 MAC, обеспечив применение правил при регистрации EID, использующих кодирование с AFI=6 в записях RLOC. Дополнительные сведения представлены в документах об использовании.

4.10.3. Имена ASCII в базе сопоставлений

Если в базе сопоставления LISP хранятся имена DNS [RFC1035] или URI [RFC3986], можно применять тип AFI List LCAF для передачи строк ASCII.

ASCII LCAF

    0                   1                   2                   3
    0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
   |           AFI = 16387         |     Rsvd1     |     Flags     |
   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
   |   Type = 1    |     Rsvd2     |            Length             |
   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
   |             AFI = 17          |      DNS Name or URI  ...     |
   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+

Length

Размер в байтах, начиная с байта сразу после этого поля Length.

Примером использования имён DNS является случай, когда ETR регистрирует сопоставления в записью EID в форме (AFI=1, 10.0.0.0/8) и записью RLOC (AFI=17, «router.abc.com»).

4.10.4. Использование рекурсивного кодирования канонических адресов LISP

Когда желательна любая комбинация перечисленного выше, значение AFI List LCAF Type может переносить внутри LCAF AFI другой LCAF AFI (например, Application-Specific Data из 5.1. Передача специфических данных приложения).

Recursive LCAF

    0                   1                   2                   3
    0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
   |           AFI = 16387         |     Rsvd1     |     Flags     |
   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
   |   Type = 1    |     Rsvd2     |            Length             |
   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
   |           AFI = 16387         |     Rsvd1     |     Flags     |
   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
   |   Type = 4    |     Rsvd2     |            Length2            |
   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
   |   IP TOS, IPv6 TC или Flow Label              |    Protocol   |
   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
   |    Local Port (младшие биты)  |    Local Port (старшие биты)  |
   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
   |   Remote Port (младшие биты)  |   Remote Port (старшие биты)  |
   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
   |            AFI = 1            |       IPv4 Address ...        |
   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
   |     ...  IPv4 Address         |
   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+

Length

Размер в байтах, начиная с байта сразу после этого поля Length.

Length2

Размер в байтах, начиная с байта сразу после этого поля Length2.

Этот формат может применяться транспортной системой службы картографической базы данных (Mapping Database Service Transport System), такой как LISP-ALT [RFC6836], Где адрес AFI=1 IPv4 применяется как EID и помещается в адрес получателя Map-Request передающей системой LISP. Система ALT может доставить Map-Request на целевой сайт LISP независимо от значений данных Application Data LCAF Type AFI. При обработке AFI целевым сайтом LISP он будет возвращать разные наборы локаторов в зависимости от запрошенного типа приложения или уровня сервиса.

4.10.5. Пример использования режима совместимости

Система LISP может использовать формат AFI List LCAF Type при передаче системам LISP, которые не поддерживают конкретный тип LCAF, используемый для кодирования локаторов. Это даёт принимающей системе возможность разобрать адрес локатора для целей инкапсуляции. Список AFI в AFI List LCAF Type не имеет семантического упорядочения и получателю следует разбирать каждый элемент AFI независимо от их порядка.

Compatibility Mode LCAF

    0                   1                   2                   3
    0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
   |           AFI = 16387         |     Rsvd1     |     Flags     |
   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
   |   Type = 1    |     Rsvd2     |           Length              |
   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
   |           AFI = 16387         |     Rsvd1     |     Flags     |
   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
   |   Type = 5    |     Rsvd2     |           Length2             |
   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
   |N|     Latitude Degrees        |    Minutes    |    Seconds    |
   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
   |E|     Longitude Degrees       |    Minutes    |    Seconds    |
   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
   |                            Altitude                           |
   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
   |              AFI = 0          |           AFI = 1             |
   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
   |                          IPv4 Address                         |
   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+

Length

Размер в байтах, начиная с байта сразу после этого поля Length.

Length2

Размер в байтах, начиная с байта сразу после этого поля Length2.

Если система не распознаёт Geo-Coordinates LCAF Type, сопровождающий адрес локатора, кодировщик может включить Geo-Coordinates LCAF Type, встроенный в AFI List LCAF Type, где AFI в Geo-Coordinates LCAF Type имеет значение 0, а следующий AFI в списке кодируется с допустимым значением AFI для идентификации адреса локатора.

Для использования этой процедуры система LISP должна поддерживать AFI List LCAF Type. Пропускается более 10 байтов Geo-Coordinates LCAF Type для получения кодирования адреса локатора (адрес локатора IPv4). Система LISP, не поддерживающая Geo-Coordinates LCAF Type может поддерживать синтаксический анализ адреса локатора внутри кодировки Geo-Coordinates LCAF Type или следующее кодирование локатора в AFI List LCAF Type.

5. Экспериментальное использование канонических адресов LISP

В последующих параграфах описано экспериментальное кодирование LCAF. Эти типы LCAF не утверждены (т. е. не запрошены в IANA). Включение такого кодирования в документ предназначено для дальнейшего изучения и экспериментов по проверке функциональности кодирования, спроса на такие варианты применения, а также лучшего понимания вопросов внедрения. Как отмечено выше, эти типы LCAF ограничены аккуратным применением в автономных средах в поддержку соответствующих документов по вариантам применения.

5.1. Передача специфических данных приложения

Когда нужно передать набор локаторов (locator-set) на основе типа приложения или поэтапного поведения пакета (Per-Hop Behavior или PHB), можно использовать Application Data LCAF Type.

Application Data LCAF

    0                   1                   2                   3
    0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
   |           AFI = 16387         |     Rsvd1     |     Flags     |
   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
   |   Type = 4    |     Rsvd2     |            Length             |
   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
   |       IP TOS, IPv6 TC или Flow Label          |    Protocol   |
   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
   |   Local Port (младший номер)  |   Local Port (старший номер)  |
   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
   |  Remote Port (младший номер)  |  Remote Port (старший номер)  |
   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
   |              AFI = x          |         Address  ...          |
   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+

Length

Размер в байтах, начиная с байта сразу после этого поля Length.

IP TOS, IPv6 TC, Flow Label

8-битовое поле IPv4 TOS из заголовка IPv4, 8-битовое поле IPv6 Traffic Class или Flow Label из заголовка IPv6.

Local Port/Remote Port Ranges

Это поля из транспортного заголовка TCP, UDP или SCTP5. Можно указать диапазон портов двумя значениями. При указании одного номера диапазон включает единственный порт.

AFI = x

x может быть любым значением AFI из [AFN].

Application Data LCAF Type применяется для кодирования EID, когда ITR нужен набор локаторов для конкретного приложения. При использовании для кодирования RLOC значение ETR представляет locator-set для каждого конкретного приложения, настроенного для анонсирования.

Это кодирование может применяться в записях EID или RLOC сообщений Map-Request, Map-Reply, Map-Register, Map-Notify. При использовании LISP-DDT [LISP-DDT] в качестве механизма системы сопоставления в сообщениях Map-Referral применяются расширенные EID. Этот тип LCAF применяется как ключ поиска в системах отображения, которые могут возвращать точное или наиболее длинное совпадение.

5.2. Базовый поиск в базе отображений

Когда LISP Mapping Database System содержит сведения, доступные по ключу с базовым (generic) форматированием (ключ не является обычным адресом IPv4 или IPv6), может быть желательным неинтерпретируемый (opaque) ключ.

Opaque Key LCAF

    0                   1                   2                   3
    0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
   |           AFI = 16387         |     Rsvd1     |     Flags     |
   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
   |   Type = 6    |     Rsvd2     |             Length            |
   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
   | Key Field Num |      Key Wildcard Fields      |   Key . . .   |
   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
   |                       . . . Key                               |
   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+

Length

Размер в байтах, начиная с байта сразу после этого поля Length.

Key Field Num

Значение этого поля равно числу субполей Key за вычетом 1, поле Key может быть разделено на части. Значение 0 в этом поле говорит, что поле Key имеет одну часть. Размер субполей ключа фиксирован. Если ключ имеет размер 8 байтов, поле Key Field Num имеет значение 3, можно использовать 4 субполя по 2 байта. С учётом разумного числа разделителей субполей 16 это поле может иметь значение от 0 до 15.

Key Wildcard Fields

Указывает, какие поля ключа не применяются для поиска. Шаблон кодируется как битовое поле, бит 0 (младший) соответствует первому (младшему) полю ключа, бит 1 — второму и т. д. Установленный бит указывает, что соответствующая часть ключа не используется при поиске. Если все 16 битов шаблона имеют значение 0, для поиска применяются все биты ключа.

Key

Ключ переменного размера, для поиска в LISP Mapping Database System. Размер ключа определяет поле Length.

Это экспериментальный тип, применение которого ещё не определено.

5.3. Функциональность контроля доступа PETR

Когда общедоступное устройство PETR6 хочет узнать, кто инкапсулирует в него, он может проверить значение nonce в пакете с инкапсуляцией LISP. Для передачи nonce в ITR или PITR применяется описанный ниже тип LCAF в записи локатора Map-Register или Map-Reply.

Nonce LCAF

    0                   1                   2                   3
    0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
   |           AFI = 16387         |     Rsvd1     |     Flags     |
   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
   |   Type = 8    |     Rsvd2     |             Length            |
   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
   |   Reserved    |                  Nonce                        |
   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
   |              AFI = x          |         Address  ...          |
   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+

Length

Размер в байтах, начиная с байта сразу после этого поля Length.

Reserved

Должно устанавливаться в 0 при передаче и игнорироваться при получении.

Nonce

Значение nonce, возвращаемое ETR в записи локатора Map-Reply для применения ITR или PITR при инкапсуляции в адрес локатора, закодированный в поле AFI этого типа LCAF. Значение nonce вставляется в поле nonce заголовка инкапсуляции LISP.

AFI = x

x может быть любым значением AFI из [AFN].

Это экспериментальный тип, применение которого ещё не определено.

5.4. Кодирование модели данных

Этот тип позволяет кодировать модель данных JSON как EID или RLOC.

JSON Data Model Type LCAF

    0                   1                   2                   3
    0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
   |           AFI = 16387         |     Rsvd1     |     Flags     |
   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
   |   Type = 14   |    Rsvd2    |B|            Length             |
   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
   |           JSON length         | JSON binary/text encoding ... |
   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
   |              AFI = x          |       Optional Address ...    |
   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+

Length

Размер в байтах, начиная с байта сразу после этого поля Length.

B

Значение 1 указывает, что поле JSON имеет двоичное кодирование в соответствии с [JSON-BINARY], в ином случае кодирование является текстовым в соответствии с [RFC7159].

JSON length

Число октетов в следующем поле JSON binary/text encoding.

JSON binary/text encoding

Поле переменного размера в двоичном или текстовом представлении.

AFI = x

x может быть любым значением AFI из [AFN]. Конкретные AFI имеют своё кодирование индивидуального или группового адреса локатора. Все записи RTR/ETR для одного уровня следует объединять серверу Map-Server для предотвращения поиска по всему многоуровневому списку записей локаторов в сообщении Map-Reply.

Это экспериментальный тип, применение которого ещё не определено. Примером отображения является запись EID, закодированная как отличительное имя cpe-router, и запись RLOC, закодированная как строка JSON { «router-address» : «1.1.1.1», «router-mask» : «8» }.

5.5. Кодирование адресных пар ключ-значение

Пары ключ-значение полезны, например, для присоединения атрибутов к другим элементам пакетов LISP, таким как EID или RLOC. При присоединении атрибутов к EID или RLOC требуется различать элементы, которые следует применять как EID или RLOC (следовательно, как ключи поиска и дополнительные атрибуты). Это особенно актуально в случае, когда различие невозможно провести по типам элементов, например, при использовании двух адресов IP.

Key/Value Address Pair LCAF

    0                   1                   2                   3
    0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
   |           AFI = 16387         |     Rsvd1     |     Flags     |
   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
   |   Type = 15   |     Rsvd2     |            Length             |
   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
   |              AFI = x          |       Address as Key ...      |
   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
   |              AFI = y          |       Address as Value ...    |
   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+

Length

Размер в байтах, начиная с байта сразу после этого поля Length.

AFI = x

x — это AFI «Address as Key», который может иметь любое значение из [AFN]. Конкретные AFI имеют своё кодирование индивидуального или группового адреса локатора. Все записи RTR/ETR для одного уровня следует объединять серверу Map-Server для предотвращения поиска по всему многоуровневому списку записей локаторов в сообщении Map-Reply.

Address as Key

Закодированный в AFI адрес, к которому могут быть прикреплены атрибуты из следующего поля Address as Value.

AFI = y

y — это AFI «Address of Value», который может иметь любое значение из [AFN]. [AFN]. Конкретные AFI имеют своё кодирование индивидуального или группового адреса локатора. Все записи RTR/ETR для одного уровня следует объединять серверу Map-Server для предотвращения поиска по всему многоуровневому списку записей локаторов в сообщении Map-Reply.

Address as Value

Закодированный в AFI адрес, к которому могут быть прикреплены атрибуты из предыдущего поля Address as Key.

Это экспериментальный тип, применение которого ещё не определено.

5.6. Несколько плоскостей данных

Наложения становятся все более популярными во многих частях сети, что привело к взрывному росту заголовков инкапсуляции в плоскости данных. Поскольку система отображения LISP может содержать много типов формата адресов, она может также представлять формат инкапсуляции, поддерживаемый RLOC. Когда инкапсулятор получает Map-Reply с типом Encapsulation Format LCAF в записи RLOC, он может выбрать поддерживаемый формат инкапсуляции любого протокола, для которого установлен (1) бит в этом типе LCAF.

Encapsulation LCAF

    0                   1                   2                   3
    0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
   |           AFI = 16387         |     Rsvd1     |     Flags     |
   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
   |   Type = 16   |     Rsvd2     |             Length            |
   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
   |        Reserved-for-Future-Encapsulations       |U|G|N|v|V|l|L|
   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
   |              AFI = x          |          Address ...          |
   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+

Length

Размер в байтах, начиная с байта сразу после этого поля Length.

Reserved-for-Future-Encapsulations

Должно устанавливаться в 0 при передаче и игнорироваться при получении. Это поле резервирует биты для будущих типов инкапсуляции.

U

RLOC, указанные в адресах с кодированием AFI в следующем длинном слове (longword), могут воспринимать базовую инкапсуляцию UDP (Generic UDP Encapsulation или GUE) с портом назначения UDP 6080 [GUE].

G

RLOC, указанные в адресах с кодированием AFI в следующем длинном слове, могут воспринимать инкапсуляцию Geneve с портом назначения UDP 6081 [GENEVE].

N

RLOC, указанные в адресах с кодированием AFI в следующем длинном слове, могут воспринимать инкапсуляцию NV-GRE (Network Virtualization — Generic Routing Encapsulation), используя протокол IPv4/IPv6 номер 47 [RFC7637].

v

RLOC, указанные в адресах с кодированием AFI в следующем длинном слове, могут воспринимать инкапсуляцию VXLAN-GPE (Generic Protocol Extension) с портом назначения UDP 4790 [GPE-VXLAN].

V

RLOC, указанные в адресах с кодированием AFI в следующем длинном слове, могут воспринимать инкапсуляцию Virtual eXtensible Local Area Network (VXLAN) с портом назначения UDP 4789 [RFC7348].

l

RLOC, указанные в адресах с кодированием AFI в следующем длинном слове, могут воспринимать инкапсуляцию L2 LISP с портом назначения UDP 8472 [LISP-L2].

L

RLOC, указанные в адресах с кодированием AFI в следующем длинном слове, могут воспринимать инкапсуляцию L3 LISP с портом назначения UDP 4341 [RFC6830].

Это кодирование может применяться в записях RLOC сообщений Map-Request, Map-Reply, Map-Register, Map-Notify.

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

Этот документ относится к категории экспериментальных (Experimental). Кодирование LCAF, заданное здесь, предназначено для использования в соответствующих случаях и автономных средах. Пользователям следует тщательно рассмотреть применимость модели угроз [LISP-SEC] в их варианте применения.

При использовании типа Geo-Coordinates LCAF Type могут возникать проблемы приватности и следует соблюдать осторожность при настройке системы отображения с конкретными параметрами политики, чтобы сведения о географическом положении не раздавались просто так. Для всех документов, задающих применение Geo-Coordinates LCAF рекомендуется рассмотреть применимость RFC 6280 (BCP 160) [RFC6280] для защиты приватности.

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

7. Взаимодействие с IANA

Этот документ задаёт кодирование канонического формата адреса, применяемое в управляющих сообщениях LISP и для ключей поиска в LISP Mapping Database System. Этот формат адресов основан на фиксированном AFI (16387) и поле LISP LCAF Type.

8-битовое поле LISP LCAF Type зависит от кодирования LISP Canonical Address Format. Агентство IANA создало новый реестр (в соответствии с [RFC5226]), названный LISP Canonical Address Format (LCAF) Types. Исходные значения этого реестра приведены в таблице 1. Будущие назначения будут выполняться по процедуре Specification Required [RFC5226]. Назначение включает LISP LCAF Type Name и связанное с ним значение (Таблица 1).

Таблица 1. Исходные значения реестра LISP Canonical Address Format (LCAF) Types.

 

Значение

Имя типа LISP LCAF

Ссылка

0

Null Body

Раздел 3

1

AFI List

Раздел 3

2

Instance ID

Раздел 3

3

AS Number

Раздел 3

5

Geo-Coordinates

Раздел 3

7

NAT-Traversal

Раздел 3

9

Multicast Info

Раздел 3

10

Explicit Locator Path

Раздел 3

11

Security Key

Раздел 3

12

Source/Dest Key

Раздел 3

13

Replication List Entry

Раздел 3

 

8. Литература

8.1. Нормативные документы

[RFC1035] Mockapetris, P., «Domain names — implementation and specification», STD 13, RFC 1035, DOI 10.17487/RFC1035, November 1987, <http://www.rfc-editor.org/info/rfc1035>.

[RFC1918] Rekhter, Y., Moskowitz, B., Karrenberg, D., de Groot, G. J., and E. Lear, «Address Allocation for Private Internets», BCP 5, RFC 1918, DOI 10.17487/RFC1918, February 1996, <https://www.rfc-editor.org/info/rfc1918>.

[RFC2119] Bradner, S., «Key words for use in RFCs to Indicate Requirement Levels», BCP 14, RFC 2119, DOI 10.17487/RFC2119, March 1997, <http://www.rfc-editor.org/info/rfc2119>.

[RFC3232] Reynolds, J., Ed., «Assigned Numbers: RFC 1700 is Replaced by an On-line Database», RFC 3232, DOI 10.17487/RFC3232, January 2002, <http://www.rfc-editor.org/info/rfc3232>.

[RFC3986] Berners-Lee, T., Fielding, R., and L. Masinter, «Uniform Resource Identifier (URI): Generic Syntax», STD 66, RFC 3986, DOI 10.17487/RFC3986, January 2005, <http://www.rfc-editor.org/info/rfc3986>.

[RFC5226] Narten, T. and H. Alvestrand, «Guidelines for Writing an IANA Considerations Section in RFCs», BCP 26, RFC 5226, DOI 10.17487/RFC5226, May 2008, <http://www.rfc-editor.org/info/rfc5226>.

[RFC6280] Barnes, R., Lepinski, M., Cooper, A., Morris, J., Tschofenig, H., and H. Schulzrinne, «An Architecture for Location and Location Privacy in Internet Applications», BCP 160, RFC 6280, DOI 10.17487/RFC6280, July 2011, <http://www.rfc-editor.org/info/rfc6280>.

[RFC6830] Farinacci, D., Fuller, V., Meyer, D., and D. Lewis, «The Locator/ID Separation Protocol (LISP)», RFC 6830, DOI 10.17487/RFC6830, January 2013, <http://www.rfc-editor.org/info/rfc6830>.

[RFC6836] Fuller, V., Farinacci, D., Meyer, D., and D. Lewis, «Locator/ID Separation Protocol Alternative Logical Topology (LISP+ALT)», RFC 6836, DOI 10.17487/RFC6836, January 2013, <http://www.rfc-editor.org/info/rfc6836>.

[RFC7159] Bray, T., Ed., «The JavaScript Object Notation (JSON) Data Interchange Format», RFC 7159, DOI 10.17487/RFC7159, March 2014, <http://www.rfc-editor.org/info/rfc7159>.

[RFC7348] Mahalingam, M., Dutt, D., Duda, K., Agarwal, P., Kreeger, L., Sridhar, T., Bursell, M., and C. Wright, «Virtual eXtensible Local Area Network (VXLAN): A Framework for Overlaying Virtualized Layer 2 Networks over Layer 3 Networks», RFC 7348, DOI 10.17487/RFC7348, August 2014, <http://www.rfc-editor.org/info/rfc7348>.

[RFC7637] Garg, P., Ed. and Y. Wang, Ed., «NVGRE: Network Virtualization Using Generic Routing Encapsulation», RFC 7637, DOI 10.17487/RFC7637, September 2015, <http://www.rfc-editor.org/info/rfc7637>.

8.2. Дополнительная литература

[AFN] IANA, «Address Family Numbers», <http://www.iana.org/assignments/address-family-numbers/>.

[EID-MOBILITY] Portoles-Comeras, M., Ashtaputre, V., Moreno, V., Maino, F., and D. Farinacci, «LISP L2/L3 EID Mobility Using a Unified Control Plane», Work in Progress, draft-portoles-lisp-eid-mobility-01, October 2016.

[GENEVE] Gross, J., Ganga, I., and T. Sridhar, «Geneve: Generic Network Virtualization Encapsulation», Work in Progress7, draft-ietf-nvo3-geneve-03, September 2016.

[GPE-VXLAN] Maino, F., Kreeger, L., and U. Elzur, «Generic Protocol Extension for VXLAN», Work in Progress, draft-ietf-nvo3-vxlan-gpe-03, October 2016.

[GUE] Herbert, T., Yong, L., and O. Zia, «Generic UDP Encapsulation», Work in Progress, draft-ietf-nvo3-gue-05, October 2016.

[JSON-BINARY] «Universal Binary JSON Specification», <http://ubjson.org>.

[LISP-DDT] Fuller, V., Lewis, D., Ermagan, V., Jain, A., and A. Smirnov, «LISP Delegated Database Tree», Work in Progress8, draft-ietf-lisp-ddt-09, January 2017.

[LISP-L2] Smith, M., Dutt, D., Farinacci, D., and F. Maino, «Layer 2 (L2) LISP Encapsulation Format», Work in Progress, draft-smith-lisp-layer2-03, September 2013.

[LISP-RE] Coras, F., Cabellos-Aparicio, A., Domingo-Pascual, J., Maino, F., and D. Farinacci, «LISP Replication Engineering», Work in Progress, draft-coras-lisp-re-08, November 2015.

[LISP-SEC] Maino, F., Ermagan, V., Cabellos, A., and D. Saucez, «LISP-Security (LISP-SEC)», Work in Progress9, draft-ietf-lisp-sec-12, November 2016.

[LISP-TE] Farinacci, D., Kowal, M., and P. Lahiri, «LISP Traffic Engineering Use-Cases», Work in Progress, draft-farinacci-lisp-te-11, September 2016.

[NAT-LISP] Ermagan, V., Farinacci, D., Lewis, D., Skriver, J., Maino, F., and C. White, «NAT traversal for LISP», Work in Progress, draft-ermagan-lisp-nat-traversal-11, August 2016.

[RFC8061] Farinacci, D. and B. Weis, «Locator/ID Separation Protocol (LISP) Data-Plane Confidentiality», RFC 8061, DOI 10.17487/RFC8061, February 2017, <http://www.rfc-editor.org/info/rfc8061>.

[WGS-84] National Imagery and Mapping Agency, «Department of Defense World Geodetic System 1984», NIMA TR8350.2, January 2000, <http://earth-info.nga.mil/GandG/publications/tr8350.2/wgs84fin.pdf>.

Благодарности

Авторы благодарны Vince Fuller, Gregg Schudel, Jesper Skriver, Luigi Iannone, Isidor Kouvelas, and Sander Steffann за технические и редакторские комментарии.

Спасибо Victor Moreno за обсуждения, которые привели к определению типа Multicast Info LCAF.

Спасибо Parantap Lahiri и Michael Kowalза обсуждения, которые привели к определению типа Explicit Locator Path (ELP) LCAF.

Спасибо Fabio Maino и Vina Ermaganза обсуждения, которые привели к определению типа Security Key LCAF.

Спасибо Albert Cabellos-Aparicio и Florin Corasза обсуждения, которые привели к определению типа Replication List Entry LCAF.

Спасибо Michiel Blokzijl и Alberto Rodriguez-Natal за предложение новых типов LCAF.

Спасибо Terry Manderson за помощь при получении LISP AFI от IANA.

Авторы благодарны Stephen Farrell (руководитель направления Security) и Deborah Brungard (руководитель направления Routing) за предложенный текст для прохождения документа через рецензирование IESG.

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

Dino Farinacci
lispers.net
San Jose, CA
United States of America
Email: farinacci@gmail.com
 
Dave Meyer
Brocade
San Jose, CA
United States of America
Email: dmm@1-4-5.net
 
Job Snijders
NTT Communications
Theodorus Majofskistraat 100
Amsterdam 1065 SZ
The Netherlands
Email: job@ntt.net

Перевод на русский язык

Николай Малых

nmalykh@protokols.ru


1Internet Engineering Task Force — комиссия по решению инженерных задач Internet.

2Internet Engineering Steering Group — комиссия по инженерным разработкам Internet.

3Proxy Ingress Tunnel Router — маршрутизатор-посредник на входе туннеля.

4Re-encapsulating Tunnel Router — маршрутизатор, выполняющий повторную инкапсуляцию для туннеля (с удалением имеющейся).

5Stream Control Transmission Protocol — протокол управления потоковой передачей.

6Proxy Egress Tunnel Router — маршрутизатор-посредник на выходе туннеля.

7Опубликовано в RFC 8926. Прим. перев.

8Опубликовано в RFC 8111. Прим. перев.

9Опубликовано в RFC 9303. Прим. перев.

Рубрика: RFC | Оставить комментарий

RFC 8061 Locator/ID Separation Protocol (LISP) Data-Plane Confidentiality

Internet Engineering Task Force (IETF)                      D. Farinacci
Request for Comments: 8061                                   lispers.net
Category: Experimental                                           B. Weis
ISSN: 2070-1721                                            Cisco Systems
                                                           February 2017

Locator/ID Separation Protocol (LISP) Data-Plane Confidentiality

Конфиденциальность плоскости данных протокола LISP

PDF

Аннотация

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

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

Этот документ не является спецификацией Track и публикуется для проверки, экспериментальной реализации и оценки.

Документ определяет экспериментальный протокол для сообщества Internet. Документ является результатом работы IETF2 и представляет согласованный взгляд сообщества IETF. Документ прошёл открытое обсуждение и был одобрен для публикации IESG3. Дополнительную информацию о стандартах Internet можно найти в разделе 2 в RFC 7841.

Информация о текущем статусе документа, найденных ошибках и способах обратной связи доступна по ссылке http://www.rfc-editor.org/info/rfc8061.

Авторские права

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

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

1. Введение

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

Протокол LISP [RFC6830] определяет набор функций, позволяющих маршрутизаторам обмениваться информацией, применяемой для сопоставления немаршрутизируемых идентификаторов конечных точек (Endpoint Identifier или EID) с маршрутизируемыми локаторами (Routing Locator или RLOC). Входные маршрутизаторы туннелей LISP (Ingress Tunnel Router или ITR) и входные маршрутизаторы-посредники (Proxy Ingress Tunnel Router PITR) инкапсулируют пакеты для выходных маршрутизаторов туннелей (Egress Tunnel Router или ETR) и повторно инкапсулирующих маршрутизаторов туннелей (Re-encapsulating Tunnel Router или RTR). Пакеты, приходящие на ITR или PITR, могут быть нешифрованными, что обозначает отсутствие защиты и приватности. Если хост-источник шифрует поток данных, протоколу LISP не требуется шифровать инкапсулируемые пакеты. Однако при передаче хостами нешифрованных (plaintext) пакетов эта схема позволяет зашифровать пользовательские данные для сохранения приватности на пути между инкапсулятором (ITR или PITR) и декапсулятором (ETR или RTR). Шифрованные пакеты являются однонаправленными, а для обратного трафика применяются такие же процедуры, но с другими ключами тех же или иных (при асимметричном пути) xTRs.

Этот документ предъявляет к пространству решений общие требования из [RFC6973], а также указанное ниже.

  • Не требуется отдельная инфраструктура открытых ключей (Public Key Infrastructure или PKI), выходящая за рамки архитектуры плоскости управления LISP.

  • Обмен ключами должен выполняться за один интервал кругового обхода (round-trip), т. е. в обмене могут участвовать лишь 2 пакета.

  • Симметричное шифрование в плоскости данных LISP для ускорения.

  • По возможности отказ от сторонних привязок доверия.

  • Смена ключей при компрометации секретного ключа.

  • Поддержка аутентифицированного шифрования с проверкой целостности пакетов.

  • Поддержка нескольких шифров с возможностью простого добавления новых алгоритмов.

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

  • Отказ от PKI сокращает эксплуатационные издержки на поддержание защищённой сети. Управление ключами распределено и не зависит от другой инфраструктуры.

  • Доставка пакетов оптимизирована благодаря меньшему числу заголовков. Потери пакетов сокращаются благодаря более эффективному обмену ключами.

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

2. Уровни требований

Ключевые слова должно (MUST), недопустимо (MUST NOT), требуется (REQUIRED), нужно (SHALL), не следует (SHALL NOT), следует (SHOULD), не нужно (SHOULD NOT), рекомендуется (RECOMMENDED), не рекомендуется (NOT RECOMMENDED), возможно (MAY), необязательно (OPTIONAL) в данном документе интерпретируются в соответствии с [RFC2119].

3. Определения терминов

AEAD

Authenticated Encryption with Associated Data [RFC5116] — аутентифицированное шифрование со связанными данными.

ICV

Integrity Check Value — значение для проверки целостности.

LCAF

LISP Canonical Address Format [RFC8060] — канонический формат адреса LISP.

xTR

Общее обозначение для маршрутизаторов ITR, ETR, RTR, PxTR

4. Обзор

Предложенный в этом документе подход не полагается на систему отображения LISP (или иную инфраструктуру ключей) для хранения секретных ключей, обеспечивая более простой и защищённый механизм. Секретный ключ соглауется между ITR и ETR в сообщениях Map-Request и Map-Reply. Когда ITR нужно получить RLOC от ETR, он получит ключевой материал для расчёта общего с ETR секретного ключа.

ITR может рассчитать 3 общих секрета с ETR, для которого ITR выполняет инкапсуляцию. Когда ITR шифрует пакет перед инкапсуляцией, он указывает используемый ключ, чтобы маршрутизатор ETR, знающий этот ключ, мог расшифровать пакет после декапсуляции. С помощью идентификаторов ключей в заголовках LISP можно легко менять ключи.

Описанное в этом документе управление ключами является однонаправленным — от ITR (инкапсулятор) к ETR (декапсулятор).

5. Обмен ключами Diffie-Hellman

LISP использует процесс обмена ключами и расчёты Diffie-Hellman [RFC2631] для вычисления общего секрета. Параметры Diffie-Hellman передаются кодами Cipher Suite в сообщениях Map-Request и Map-Reply. Ниже приведено краткое описание процесса.

Параметры p и g должны иметь одинаковые значения на маршрутизаторах ITR и ETR. Маршрутизатор ITR рассчитывает открытый ключ I и передаёт его в пакете Map-Request. ETR при получении Map-Request использует параметры p и g для расчёта своего открытого ключа E и передаёт этот клю в сообщении Map-Reply. В этот момент у ETR достаточно сведений для расчёта секретного ключа s с использованием I в качестве основания и своего секретного ключа e в качестве показателя степени. Когда ITR получает Map-Reply, он использует открытый ключ E и свой секретный ключ i для расчёта того же общего секрета, который даст расчёт ETR. Значение p служит модулем при создании общего секрета s (6. Кодирование и передача ключевого материала).

+----------------------------+---------+----------------------------+
|              ITR           |         |           ETR              |
+------+--------+------------+---------+------------+---------------+
|Secret| Public |   Расчёт   |Передача |   Расчёт   | Public |Secret|
+------|--------|------------|---------|------------|--------|------+
|  i   |  p,g   |            | p,g --> |            |        |  e   |
+------|--------|------------|---------|------------|--------|------+
|  i   | p,g,I  |g^i mod p=I |  I -->  |            | p,g,I  |  e   |
+------|--------|------------|---------|------------|--------|------+
|  i   | p,g,I  |            |  <-- E  |g^e mod p=E |  p,g   |  e   |
+------|--------|------------|---------|------------|--------|------+
| i,s  |p,g,I,E |E^i mod p=s |         |I^e mod p=s |p,g,I,E | e,s  |
+------|--------|------------|---------|------------|--------|------+

Обмен открытыми ключами для создания общего секретного ключа.


6. Кодирование и передача ключевого материала

Ключевой материал Diffie-Hellman (DH) передаётся в сообщениях Map-Request и Map-Reply, параметры Diffie-Hellman кодируются в LISP Security Key LCAF Type [RFC8060].

 0                   1                   2                   3
 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|           AFI = 16387         |     Rsvd1     |     Flags     |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|   Type = 11   |      Rsvd2    |             6 + n             |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|   Key Count   |      Rsvd3    | Cipher Suite  |   Rsvd4     |R|
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|           Key Length          |     Public Key Material ...   |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|                    ... Public Key Material                    |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|              AFI = x          |       Адрес локатора ...      |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+


Поле Cipher Suite указывает функции обмена ключами DH, шифрования и хэширования.

В поле Key Count указывается число полей {Key-Length, Key-Material}, включённых в LCAF. Максимальное число таких полей — 3 и они указываются как key-id 1, key-id 2 и key-id 3. Бит R не используется в этом варианте применения Security Key LCAF Type и зарезервирован для [LISP-DDT]. Поэтому бит R следует сбрасывать (0) при отправке, а при получении он должен игнорироваться.

  Шифр 0
    Резерв

  Шифр 1 (LISP_2048MODP_AES128_CBC_SHA256):
    Группа DH: 2048 битов MODP [RFC3526]
    Шифрование:  AES со 128-битовыми ключами в режиме CBC [AES-CBC]
    Целостность: интеграция с AEAD_AES_128_CBC_HMAC_SHA_256 [AES-CBC]
    Размер IV:   16 байтов
    KDF:         HMAC-SHA-256

  Шифр 2 (LISP_EC25519_AES128_CBC_SHA256):
    Группа DH: 256 битов Elliptic-Curve 25519 [CURVE25519]
    Шифрование:  AES со 128-битовыми ключами в режиме CBC [AES-CBC]
    Целостность: интеграция с AEAD_AES_128_CBC_HMAC_SHA_256 [AES-CBC]
    Размер IV:   16 байтов
    KDF:         HMAC-SHA-256

  Шифр 3 (LISP_2048MODP_AES128_GCM):
    Группа DH: 2048 битов MODP [RFC3526]
    Шифрование:  AES со 128-битовыми ключами в режиме GCM [RFC5116]
    Целостность: интеграция с AEAD_AES_128_GCM [RFC5116]
    Размер IV:   12 байтов
    KDF:         HMAC-SHA-256

  Шифр 4 (LISP_3072MODP_AES128_GCM):
    Группа DH: 3072 бита MODP [RFC3526]
    Шифрование:  AES со 128-битовыми ключами в режиме GCM [RFC5116]
    Целостность: интеграция с AEAD_AES_128_GCM [RFC5116]
    Размер IV:   12 байтов
    KDF:         HMAC-SHA-256

  Шифр 5 (LISP_256_EC25519_AES128_GCM):
    Группа DH: 256 битов Elliptic-Curve 25519 [CURVE25519]
    Шифрование:  со 128-битовыми ключами в режиме GCM [RFC5116]
    Целостность: интеграция с AEAD_AES_128_GCM [RFC5116]
    Размер IV:   12 байтов
    KDF:         HMAC-SHA-256

  Шифр 6 (LISP_256_EC25519_CHACHA20_POLY1305):
    Группа DH: 256 битов Elliptic-Curve 25519 [CURVE25519]
    Шифрование: Chacha20-Poly1305 [CHACHA-POLY] [RFC7539]
    Целостность: интеграция с AEAD_CHACHA20_POLY1305 [CHACHA-POLY]
    Размер IV:  8 байтов
    KDF:        HMAC-SHA-256

Поле Public Key Material содержит открытый ключ, созданный одним из указанных выше шифров (Cipher Suite). Размер ключа в октетах указывает поле Key Length.

Когда ITR, PITR или RTR передаёт Map-Request, он кодирует свой RLOC в формате Security Key LCAF Type в поле ITR-RLOC. Когда ETR или RTR передаёт Map-Reply, он кодирует свои RLOCs в формате Security Key LCAF Type в поле RLOC-record каждой представляемой записи EID-record.

Если ITR, PITR или RTR передаёт Map-Request с Security Key LCAF Type, а ETR или RTR не хочет получать инкапсулированный трафик с шифрованием, он возвращает Map-Reply без записей RLOC в формате Security Key LCAF Type. Это указывает ITR, PITR или RTR, что шифровать трафик не нужно (маршрутизатор и не сможет его шифровать, поскольку открытый ключ ETR не был получен).

Если ITR или PITR хочет включить несколько key-id в Map-Request, а ETR или RTR хочет использовать лишь часть их, возвращается Map-Reply лишь с этими желаемыми key-id.

7. Общие ключи для плоскости данных

Когда маршрутизатор ITR или PITR получит Map-Reply с воспринятием Cipher Suite, переданного в Map-Request, он готов к созданию ключей плоскости данных, равно как ETR или RTR, возвративший Map-Reply.

Первым шагом является создание общего секрета с использованием предоставленного партнёром открытого ключевого материала DH в сочетании со своим секретным ключевым материалом, как указано в разделе 5. Используемые параметры DH заданы в Cipher Suite, преданном в Map-Request и скопированном в Map-Reply. Полученный общий секрет используется для расчёта ключей AEAD для алгоритмов, заданных в Cipher Suite. Для генерации ключей плоскости данных используется функция вывода ключей (Key Derivation Function или KDF) в режиме счётчика, как указано в [NIST-SP800-108]. Количество выводимого ключевого материала зависит от алгоритмов в Cipher Suite.

Входные данные для KDF указаны ниже.

  • Функция KDF — в данном документе это HMAC-SHA-256, но в общем случае задаётся для каждого Cipher Suite.

  • Ключ для функции KDF — рассчитанный по методу DH общий секрет.

  • Контекст, привязывающий использование ключей плоскости данных к этой сессии. Контекст образуют указанные ниже поля, которые объединяются (конкатенация) и представляются как данные для функции KDF:

    • двухоктетный счётчик с сетевым порядком байтов;

    • строка lisp-crypto с null-символом в конце;

    • значение nonce от ITR из сообщения Map-Request, где был указан Cipher Suite;

    • число требуемых битов ключевого материала (L) в виде двухоктетного значения с сетевым порядком байтов.

Для счётчика в контексте сначала устанавливается значение 1. Когда запрошенный объем ключевого материала превышает размер вывода функции KDF, эта функция вызывается снова и значение счётчика при каждом вызове увеличивается на 1. При получении нужного объёма ключевого материала выполняется его конкатенация и материал используется для создания ключей. Например, для AES со 128-битовыми ключами нужно 16 октетов (128 битов) ключевого материала и HMAC-SHA1-96 требует ещё 16 октетов (128 битов) для поддержки согласованной 128-битовой защиты. Поскольку требуется 32 октета (256 битов) ключевого материала, а функция KDF HMAC-SHA-256 возвращает 256 битов, достаточно одного вызова функции

   key-material = HMAC-SHA-256(dh-shared-secret, context)

где context = 0x0001 || «lisp-crypto» || <itr-nonce> || 0x0100

Значение Cipher Suite, указывающее AES с 256-битовыми ключами требует 32 октета (256 битов) ключевого материала и HMAC-SHA256-128 требует ещё 32 октета (256 битов) для поддержки согласованной 256-битовой защиты. Поскольку нужны 64 октета (512 битов) ключевого материала, а функция KDF HMAC-SHA-256 возвращает 256 битов, нужны 2 вызова

   key-material-1 = HMAC-SHA-256(dh-shared-secret, context)

где context = 0x0001 || «lisp-crypto» || <itr-nonce> || 0x0200

   key-material-2 = HMAC-SHA-256(dh-shared-secret, context)

где context = 0x0002 || «lisp-crypto» || <itr-nonce> || 0x0200

   key-material = key-material-1 || key-material-2

Если размер key-material больше требуемого числа битов (L), используются лишь L старших битов результата.

Из полученного key-material шифры AEAD используют 256 старших битов для AEAD-key. 256-битовый ключ AEAD-key делится на 128-битовый ключ шифрования и 128-битовый ключ проверки целостности в шифре, используемом ITR.

8. Операции плоскости данных

Заголовок инкапсуляции LISP [RFC6830] требуется изменить для кодирования в key-id ключа, применяемого при шифровании.

     0                   1                   2                   3
     0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
    +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
  / |       Source Port = xxxx      |       Dest Port = 4341        |
UDP +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
  \ |           UDP Length          |        UDP Checksum           |
    +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
L / |N|L|E|V|I|R|K|K|            Nonce/Map-Version                  |\ \
I   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ ||
S \ |                 Instance ID/Locator-Status-Bits               | |A
P   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ |D
    |                   Initialization Vector (IV)                  | I/
E   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ C
n / |                                                               | V
c   |                                                               | |
r   |              Содержимое пакета с заголовком EID ...           | |
y   |                                                               | |
p \ |                                                               |/
t   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+

Биты KK указывают, когда пакет зашифрован и какой ключ применяется.


Когда биты KK имеют значение 00, инкапсулируемый пакет не шифруется. Значения поля KK 1, 2 или 3 указывают key-id секретных ключей, рассчитанных в процессе обмена DH через сообщения Map-Request и Map-Reply. При отличном от 0 поле KK перед данными (payload) помещается вектор инициализации (Initialization Vector или IV), размер которого определяет используемый шифр Cipher Suite. Все заданные этим документом шифры используют AEAD и поле контроля целостности ICV может не включаться в пакет, так как оно указано в шифрованных данных (ciphertext). Дополнительные данные (Additional Data или AD), используемые для ICV, показаны на рисунке и включают заголовок LISP, поле IV и данные пакета (payload).

Когда ITR или PITR получает пакет для инкапсуляции, он сначала выбирает ключ для применения, помещает key-id в заголовок LISP и использует ключ для шифрования всех данных пакета, размещаемых после заголовка LISP. Внешний заголовок, а также заголовки UDP и LISP не шифруются.

На момент создания этого документа существовала открытая рабочая группа для обсуждения необходимости изменения заголовка инкапсуляции данных для шифрования и новых приложений. Этот документ вносит изменения в имеющийся заголовок, чтобы можно было продолжить эксперименты без существенных изменений в плоскости данных. Документ выделяет два не использованных ранее бита (бит R остаётся резервным, как указано в [RFC6830]) для поля KK.

9. Процедуры шифрования и расшифровки

Когда ITR, PITR или RTR инкапсулирует пакет, уже имея рассчитанный ключ AEAD-key (7. Общие ключи для плоскости данных), связанный с RLOC получателя, выполняются указанные ниже процедуры шифрования и инкапсуляции.

  1. Инкапсулятор создаёт IV и помещает его перед инкапсулируемым пакетом. Для шифров GCM и ChaCha20 значение IV инкрементируется в каждом пакете (начиная с 1 в первом пакете) и пакет передаётся по RLOC получателя. Для шифров CBC значение IV является случайным для каждого пакета, передаваемого по RLOC получателя. Для шифра ChaCha20 значение IV является 8-байтовым случайным числом, добавляемым в конце 4-байтового счётчика, инкрементируемого в каждом пакете (начиная с 1 в первом пакете).

  2. Затем выполняется шифрование с помощью функци AES или ChaCha20 с использованием AEAD-key для содержимого пакета (payload) в соответствии со спецификацией AEAD для шифра Cipher Suite. Шифрование не включает IV, поскольку значение IV должно передаваться в открытом виде, чтобы его можно было использовать при расшифровке. Шифруемое содержимое следует дополнять по размеру до целого числа октетов, которое может потребовать блочный шифр. Результат операции AEAD может включать поле ICV, размер которого определяется соответствующей спецификацией AEAD. Отметим, что AD (т. е. заголовок LISP, в точности совпадающий с добавляемым на следующем этапе, и поле IV) должны предоставляться функции шифрования AEAD как аргумент «associated data».

  3. В начало добавляется заголовок LISP. В поле key-id этого заголовка указывается идентификатор ключа, соответствующий использованному при шифровании ключу.

  4. В заключение перед шифрованным пакетом добавляется заголовок UDP и внешний заголовок IP и пакет передаётся по RLOC получателя.

Когда ETR, PETR или RTR получает инкапсулированный пакет, выполняются операции декапсуляции и расшифровки.

  1. Внешний заголовок IP, а также заголовоки UDP и LISP и поле IV вырезаются из начала пакета. Заголовок LISP и IV сохраняются и передаются операции расшифровки AEAD как аргумент «associated data».

  2. Пакет расшифровывается с применением ключа AEAD-key и IV из пакета. Ключ AEAD-key берётся из локального кэша по значению key-id в заголовке LISP. Результатом расшифровки являются открытые данные (plaintext payload), если шифр вернул проверенное значение ICV. В ином случае пакет считается недействительным и отбрасывается. Если спецификация AEAD включает ICV, функция арсшифровки AEAD будет находить значение ICV в шифротексте и сравнивать его с ICV, рассчитанным функцией расшифровки AEAD. Если эти значения ICV не совпадают, пакет считается поделанным.

  3. Если пакет не является поддельным, он пересылается после расшифровки по EID получателя.

10. Динамическая смена ключей

Поскольку в сообщениях управления и данных можно указать несколько ключей, ITR может инкапсулировать и шифровать пакеты с использованием конкретного ключа, согласуя с тем же ETR другие ключи. Как только ETR или RTR передаст сообщение Map-Reply, он будет готов к декапсуляции и расшифровке с использованием новых ключей, выведенных с параметрами DH, полученными в Map-Request и возвращенными в Map-Reply.

ITR может в любой момент использовать RLOC-probing для смены ключей или Cipher Suite. При отправке начального Map-Request для заполнения кэша отображений в ITR сообщение Map-Request проходит через систему отображения, где будет отвечать 1 ETR из набора RLOC-set в Map-Reply. Если ITR решит пользоваться другими RLOC из RLOC-set, он должен передать Map-Request напрямую для согласования параметров защиты с ETR. Этот процесс можно использовать для проверки доступности ETR для маршрутизатора ITR при первом добавлении записи map-cache, поэтому ITR может получить сразу статус доступности и ключи в одном обмене Map-Request/Map-Reply.

Событие смены ключей определяется как факт замены маршрутизатором ITR или PITR шифра Cipher Suite или открытого ключа в Map-Request. ETR или RTR сравнивают полученные Cipher Suite и открытый ключ с предоставленными ITR ранее и при наличии изменений рассчитывают новый открытй ключ и Cipher Suite по запросу ITR из Map-Request и возвращают их в Map-Reply. Новый общий секрет можно после этого применять для key-id при шифровании в ITR и расшифровке в ETR. Когда ITR или PITR начинает процесс согласования нового ключа, ему недопустимо применять соответствующий key-id в инкапсулируемых пакетах, пока не получено сообщение Map-Reply от ETR с ожидаемым Cipher Suite (из Map-Request).

Отметим, что при продолжающемся использовании RLOC-probing для проверки доступности RLOC и нежелательности смены ключей ITR или RTR межет отказаться от включения Security Key LCAF Type в Map-Request или указать прежний ключевой материал, полученный в последнем Map-Reply от ETR или RTR. Это указывает ETR или RTR, что смена ключей не требуется.

11. Продолжение работы

По соображениям производительности можно использовать более новые группы Elliptic-Curve Diffie-Hellman (ECDH), как указано в [RFC4492] и [RFC6090] для снижения числа операций CPU при расчёте общих секретных ключей.

Для улучшения защиты а также ускорения программных реализаций будут исследоваться и тестироваться новые подходы к методам шифрования и проверки подлинности. Примерами являются ChaCha20 и Poly1305 [CHACHA-POLY] [RFC7539].

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

12.1. Поддержка от SAAG

Рабочая группа LISP получила рекомендации по защите от консультативной группы по безопасности (Security Area Advisory Group или SAAG). Группа SAAG участвовала в ранних этапах разработки и её отзывы и предложения включены в документ. Комментарии SAAG приведены ниже.

  1. Отказ от использования асимметричных шифров в плоскости данных.

  2. Добавление групп ECDH на ранних этапах проектирования.

  3. Добавление поля Cipher Suite, поскольку шифры создаются чаще, чем применяющие их протоколы.

  4. Рассмотрение новой технологии AEAD для аутентификации и шифрования.

12.2. Угрозы безопасности LISP-Crypto

Поскольку ITR и ETR обмениваются ключами через незащищённые сети общего пользования, атаки с участием человека (man in the middle или MITM) могут обходить обмен ключами и нарушать конфиденциальность плоскости данных. Это может происходить, когда MITM выступает в качестве отправителя Map-Reply и предоставляет свой открытый ключ маршрутизатору ITR, что ведёт его к созданию общего с MITM секретного ключа. Если MITM размещается на пути между ITR и ETR, этот общий секретный ключ можно использовать для расшифровки данных ITR.

Поскольку LISP позволяет защитить сообщения Map-Reply с помощью процесса аутентификации, описанного в [LISP-SEC], ITR может обнаружить подписание MITM сообщения Map-Reply для EID-prefix без полномочий на это. Когда ITR сталкивается с отказом при проверке подписи, он отбрасывает и больше не применяет параметры обмена ключами, избегает использования ETR при инкапсуляции и вносит в системный журнал соответствующую запись для администратора сети. Кроме того, ITR может передать сообщения RLOC-probe по скомпрометированным RLOC для определения доступности полномочного ETR. После успешной проверки подписи в Map-Reply маршрутизатор ITR может начать шифрования и инкапсуляцию пакетов для RLOC этого ETR.

13. Взаимодействие с IANA

В этом документе описан механизм шифрования пакетов с инкапсуляцией LISP на основе процедур обмена ключами Diffie-Hellman. В процессе обмена устройства согласуют используемый Cipher Suite (т. е. функции шифрования э хэширования, служашие для шифрования и расшифровки, а также подписи и проверки пакетов). Для этого зарезервировано 8-битовое поле Cipher Suite в разделе ключевого материала сообщений Map-Request и Map-Reply.

Агентство IANA создало новый реестр (как указано в [RFC5226]) LISP Crypto Cipher Suite. Исходное содержимое реестра приведено в таблице ниже, а новые значения выделяются по процедуре First Come, First Served [RFC5226].

Шифры LISP Crypto.

 

Значение

Шифр

Описание

0

Резерв

Раздел 6

1

LISP_2048MODP_AES128_CBC_SHA256

Раздел 6

2

LISP_EC25519_AES128_CBC_SHA256

Раздел 6

3

LISP_2048MODP_AES128_GCM

Раздел 6

4

LISP_3072MODP_AES128_GCM

Раздел 6

5

LISP_256_EC25519_AES128_GCM

Раздел 6

6

LISP_256_EC25519_CHACHA20_POLY1305

Раздел 6

 

14. Литература

14.1. Нормативные документы

[NIST-SP800-108] National Institute of Standards and Technology, «Recommendation for Key Derivation Using Pseudorandom Functions», NIST Special Publication SP 800-108, DOI 10.6028/NIST.SP.800-108, October 2009.

[RFC2119] Bradner, S., «Key words for use in RFCs to Indicate Requirement Levels», BCP 14, RFC 2119, DOI 10.17487/RFC2119, March 1997, <http://www.rfc-editor.org/info/rfc2119>.

[RFC2631] Rescorla, E., «Diffie-Hellman Key Agreement Method», RFC 2631, DOI 10.17487/RFC2631, June 1999, <http://www.rfc-editor.org/info/rfc2631>.

[RFC3526] Kivinen, T. and M. Kojo, «More Modular Exponential (MODP) Diffie-Hellman groups for Internet Key Exchange (IKE)», RFC 3526, DOI 10.17487/RFC3526, May 2003, <http://www.rfc-editor.org/info/rfc3526>.

[RFC4492] Blake-Wilson, S., Bolyard, N., Gupta, V., Hawk, C., and B. Moeller, «Elliptic Curve Cryptography (ECC) Cipher Suites for Transport Layer Security (TLS)», RFC 4492, DOI 10.17487/RFC4492, May 2006, <http://www.rfc-editor.org/info/rfc4492>.

[RFC5116] McGrew, D., «An Interface and Algorithms for Authenticated Encryption», RFC 5116, DOI 10.17487/RFC5116, January 2008, <http://www.rfc-editor.org/info/rfc5116>.

[RFC5226] Narten, T. and H. Alvestrand, «Guidelines for Writing an IANA Considerations Section in RFCs», BCP 26, RFC 5226, DOI 10.17487/RFC5226, May 2008, <http://www.rfc-editor.org/info/rfc5226>.

[RFC6090] McGrew, D., Igoe, K., and M. Salter, «Fundamental Elliptic Curve Cryptography Algorithms», RFC 6090, DOI 10.17487/RFC6090, February 2011, <http://www.rfc-editor.org/info/rfc6090>.

[RFC6830] Farinacci, D., Fuller, V., Meyer, D., and D. Lewis, «The Locator/ID Separation Protocol (LISP)», RFC 6830, DOI 10.17487/RFC6830, January 2013, <http://www.rfc-editor.org/info/rfc6830>.

[RFC6973] Cooper, A., Tschofenig, H., Aboba, B., Peterson, J., Morris, J., Hansen, M., and R. Smith, «Privacy Considerations for Internet Protocols», RFC 6973, DOI 10.17487/RFC6973, July 2013, <http://www.rfc-editor.org/info/rfc6973>.

[RFC7539] Nir, Y. and A. Langley, «ChaCha20 and Poly1305 for IETF Protocols», RFC 7539, DOI 10.17487/RFC7539, May 2015, <http://www.rfc-editor.org/info/rfc7539>.

[RFC8060] Farinacci, D., Meyer, D., and J. Snijders, «LISP Canonical Address Format (LCAF)», RFC 8060, DOI 10.17487/RFC8060, February 2017, <http://www.rfc-editor.org/info/rfc8060>.

14.2. Дополнительная литература

[AES-CBC] McGrew, D., Foley, J., and K. Paterson, «Authenticated Encryption with AES-CBC and HMAC-SHA», Work in Progress, draft-mcgrew-aead-aes-cbc-hmac-sha2-05, July 2014.

[CHACHA-POLY] Langley, A. and W. Chang, «ChaCha20 and Poly1305 based Cipher Suites for TLS», Work in Progress, draft-agl-tls-chacha20poly1305-04, November 2013.

[CURVE25519] Bernstein, D., «Curve25519: new Diffie-Hellman speed records», DOI 10.1007/11745853_14, <http://www.iacr.org/cryptodb/archive/2006/PKC/3351/3351.pdf>.

[DH] Wikipedia, «Diffie-Hellman key exchange», January 2017, <https://en.wikipedia.org/w/index.php?title=Diffie%E2%80%93Hellman_key_exchange&oldid=759611604>.

[LISP-DDT] Fuller, V., Lewis, D., Ermagan, V., Jain, A., and A. Smirnov, «LISP Delegated Database Tree», Work in Progress4, draft-ietf-lisp-ddt-08, September 2016.

[LISP-SEC] Maino, F., Ermagan, V., Cabellos, A., and D. Saucez, «LISP-Security (LISP-SEC)», Work in Progress5, draft-ietf-lisp-sec-12, November 2016.

Благодарности

Авторы благодарны Dan Harkins, Joel Halpern, Fabio Maino, Ed Lopez, Roger Jorgensen, Watson Ladd за проявленный интерес, предложения и дискуссии по защите плоскости данных LISP. Отдельная блегодарность руководителю рабочей группы LISP за поддержку этого документа и вклад в раздел «Взаимодействие в IANA».

Авторы выражают особую благодарность Ilari Liusvaara за комментарии и обсуждения. Он поделился своим опытом в части защиты, чтобы сделать lisp-crypto столь защищённым, как это позволяет современная криптография.

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

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

Dino Farinacci
lispers.net
San Jose, California 95120
United States of America
Phone: 408-718-2001
Email: farinacci@gmail.com
 
Brian Weis
Cisco Systems
170 West Tasman Drive
San Jose, California 95124-1706
United States of America
Phone: 408-526-4796
Email: bew@cisco.com

Перевод на русский язык

Николай Малых

nmalykh@protokols.ru


1Locator/ID Separation Protocol — протокол разделения идентификаторов и локаторов.

2Internet Engineering Task Force — комиссия по решению инженерных задач Internet.

3Internet Engineering Steering Group — комиссия по инженерным разработкам Internet.

4Опубликовано в RFC 8111. Прим. перев.

5Опубликовано в RFC 9303. Прим. перев.

Рубрика: RFC, Безопасность | Оставить комментарий