Архитектура uBPF

image_print

PDF

Приведенный ниже включаемый файл (include) с переведенными на русский язык комментариями содержит определения пакета ubpf в одноименной модели. Файл ubpf.p4 размещается в каталоге p4include пакета p4c и доступен по ссылке.

/*
Copyright 2019 Orange

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

    http://www.apache.org/licenses/LICENSE-2.0 

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/

#ifndef _UBPF_MODEL_P4_
#define _UBPF_MODEL_P4_

#include <core.p4>

/*
 * Платформа uBPF в настоящее время позволяет пропускать (pass) или отбрасывать 
 * (drop) пакеты. По умолчанию пакеты пропускаются. Можно использовать 
 * внешнюю функцию mark_to_drop(), чтобы пометить пакет для отбрасывания. 
 * Функция mark_to_drop() меняет лишь состояние, скрытое от  пользовательской
 * программы P4 и вызывать ее следует лишь из элемента управления pipe.
 */
extern void mark_to_drop();

/*
 * Платформа uBPF в настоящее время позволяет пропускать (pass) или отбрасывать 
 * (drop) пакеты. По умолчанию пакеты пропускаются. Можно использовать 
 * внешнюю функцию mark_to_pass() чтобы пометить пакет для пропускания (это
 * отменяет предшествующее действие mark_to_drop()). Функция mark_to_drop()
 * меняет лишь состояние, скрытое от  пользовательской программы P4 
 * и вызывать ее следует лишь из элемента управления pipe.
 */
extern void mark_to_pass();


extern Register<T, S> {
  /***
   * Объект Register создается вызовом его конструктора. При вызове нужно
   * указать размер Register, определяющий максимальное число записей в
   * регистре. После создания объекта Register его можно применять в
   * действиях и блоках apply. При создании Register не инициализируется.
   */
  Register(bit<32> size);

  /***
   * Метод read() считывает состояние (T) из массива регистров по заданному
   * индексу S и возвращает значение в параметре result.
   *
   * @param index Индекс элемента массива регистров для считывания. Обычно
   *              из диапазона [0, size-1].
   * @return Возвращает результат типа T (в настоящее время только bit<W>).
   *         Если индекс находится в диапазоне, result получает значение 
   *         элемента массива регистров. При index >= size результат 
   *         становится неопределенным и его следует игнорировать.
   */
  T read  (in S index);

  void write (in S index, in T value);
}

/*
 * Функция возвращает метку текущего времени в наносекундах.
 */
extern bit<48> ubpf_time_get_ns();

enum HashAlgorithm {
    lookup3
}

/***
 * Рассчитывает хэш-функцию от значения, заданного параметром data. В силу 
 * ограничений uBPF максимальный размер data составляет bit<64>.
 *
 * Отметим, что типы всех параметров могут быть одинаковыми или разными.
 * Во втором случае их битовые размеры могут различаться.
 *
 * Результат всегда имеет размер bit<32>.
 *
 * @param D    Должен иметь тип tuple, состоящий из битовых полей (type bit<W>, int<W>) 
 *             или varbit. Максимальный размер D составляет 64 бита (ограничение uBPF).
 */
extern void hash<D>(out bit<32> result, in HashAlgorithm algo, in D data);

/***
 * Расчет контрольной суммы с помощью инкрементального обновления (RFC 1624).
 * Функция реализует расчет контрольной суммы для 16-битовых полей.
 */
extern bit<16> csum_replace2(in bit<16> csum,  // Текущая контрольная сумма.
                             in bit<16> old,   // Старое значение поля.
                             in bit<16> new);

/***
 * Расчет контрольной суммы с помощью инкрементального обновления (RFC 1624).
 * Функция реализует расчет контрольной суммы для 32-битовых полей.
 */
extern bit<16> csum_replace4(in bit<16> csum,
                             in bit<32> old,
                             in bit<32> new);

/*
 * Архитектура
 *
 * Параметр M должен иметь тип struct.
 *
 * Параметр H должен иметь тип struct, а каждый элемент структуры должен
 * быть заголовком, стеком или объединением заголовков (header_union).
 */

parser parse<H, M>(packet_in packet, out H headers, inout M meta);
control pipeline<H, M>(inout H headers, inout M meta);

/*
 * В теле сборщика (deparser) допускается лишь вызов метода packet_out.emit().
 */
@deparser
control deparser<H>(packet_out b, in H headers);

package ubpf<H, M>(parse<H, M> prs,
                pipeline<H, M> p,
                deparser<H> dprs);

#endif /* _UBPF_MODEL_P4_ */

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

nmalykh@protocols.ru

Рубрика: SDN, Сетевое программирование | Комментарии к записи Архитектура uBPF отключены

Базовая библиотека P4 – core.p4

image_print

PDF

В спецификации языка P416 часть базовых функций была вынесена в отдельную библиотеку core.p4, содержащую базовые определения и функции языка и используемую в качестве включаемого файла (директива #include) программами P4. Ниже представлен вариант этого файла с переведенными на русский язык комментариями. Исходный файл доступен в каталоге p4includes пакета p4c или по ссылке.

/*
Copyright 2013-present Barefoot Networks, Inc.

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

    http://www.apache.org/licenses/LICENSE-2.0 

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/

/* Базовая библиотека P4-16, где объявлены некоторые встроенные элементы языка P4 
     для использования в программах P4 */

#ifndef _CORE_P4_
#define _CORE_P4_

/// Стандартные коды ошибок. Пользователи могут добавлять свои коды.
error {
    NoError,           /// Нет ошибок.
    PacketTooShort,    /// В пакете недостаточно битов для извлечения.
    NoMatch,           /// В выражении select не найдено соответствия.
    StackOutOfBounds,  /// Ссылка на недействительный элемент стека заголовков.
    HeaderTooShort,    /// Извлекается слишком много битов заголовка в поле varbit.
    ParserTimeout,     /// Превышено время выполнения кода синтаксического анализатора.
    ParserInvalidArgument  /// Операция анализатора была вызвана с неподдерживаемым
                           /// реализацией значением.
}

extern packet_in {
    /// Считывает заголовок пакета в заголовок фиксированного размера и перемещает указатель.
    /// Может приводить к ошибке PacketTooShort или StackOutOfBounds.
    /// Параметр @T должен иметь тип заголовка фиксированного размера.
    void extract<T>(out T hdr);
    /// Считывает биты из заголовка пакета в заголовок @variableSizeHeader с переменным размером
    /// и перемещает указатель.
    /// Параметр @T должен быть заголовком, содержащим в точности 1 поле 1.
    /// Может приводить к ошибке 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 {
    /// Записывает заголовок @hdr в выходной пакет, перемещая указатель.
    /// @T может иметь тип заголовка, стека или объединения заголовков, а также структурой с 
    /// такими полями.
    void emit<T>(in T hdr);
}

// В будущих версиях следует исключить приведенное ниже из файла, преобразовав в built-in

/// Проверяет предикат @check в синтаксическом анализаторе. При значении true не делает ничего,
/// в противном случае устанавливает ошибку анализатора в @toSignal и переходит в состояние reject.
extern void verify(in bool check, in error toSignal);

/// Встроенная пустая операция.
@noWarn("unused")
action NoAction() {}

/// Стандартные типы сопоставления для ключей таблиц.
/// Отдельные типы могут не поддерживаться архитектурой.
/// Архитектура может добавлять типы сопоставления.
match_kind {
    /// Точное совпадение битов
    exact,
    /// Троичное сопоставление с использованием маски.
    ternary,
    /// Наибольший совпадающий префикс.
    lpm
}

#endif  /* _CORE_P4_ */

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

nmalykh@protocols.ru

Рубрика: SDN, Сетевое программирование | Комментарии к записи Базовая библиотека P4 – core.p4 отключены

Архитектура v1model

image_print

PDF

Приведенный ниже включаемый файл (include) с переведенными на русский язык комментариями содержит определения пакета V1Switch для архитектуры v1model и платформы BMV2. Файл v1model.p4 размещается в каталоге p4include пакета p4c (https://github.com/p4lang/p4c/blob/master/p4include/v1model.p4).

Этот файл включается в программы P4, работающие с прототипом коммутатора simple_switch на основе BMV2, включая тестовые примеры из пакета p4c (https://github.com/p4lang/p4c/tree/master/testdata).

/*
Copyright 2013-present Barefoot Networks, Inc.

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

    http://www.apache.org/licenses/LICENSE-2.0 

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/

/* Объявление P4-16 для модели коммутатора P4 v1.0 */

/* Примечание 1. Более подробное описание архитектуры v1model доступно
 * по приведенной ниже ссылке.
 *
 * https://github.com/p4lang/behavioral-model/blob/master/docs/simple_switch.md1 
 *
 * Примечание 2. В начале 2019 г. в рабочей группе P4 несколько раз
 * обсуждались способы вызова операций resubmit, recirculate и clone3
 * из соответствующих элементов управления (control), но значениями 
 * сохраняемых полей будут значения на момент завершения вызова
 * элемента управления. Так эти операции определены в P4_14. См.
 * https://github.com/p4lang/behavioral-model/blob/master/docs/simple_switch.md#restrictions-on-recirculate-resubmit-and-clone-operations1 
 *
 * Примечание 3. Имеются реализации P4_14, где вызов операции
 * generate_digest в field_list приводит к созданию сообщения для
 * плоскости управления, содержащего значения этих полей при завершении
 * работы элемента управления ingress, которые могут отличаться от
 * значений этих же полей в момент вызова из программы операции
 * generate_digest, если значения этих полей меняются при вызове 
 * элемента управления P4_14 ingress.
 *
 * Реализации P4_16 с моделью v1model всегда следует создавать 
 * сообщения digest, содержащие значения указанных полей на момент вызова
 * внешней функции digest. Программа P4_14 с описанным выше поведением,
 * скомпилированная с использованием p4c, может вести себя иначе.
 */

#ifndef _V1_MODEL_P4_
#define _V1_MODEL_P4_

#include "core.p4"

#ifndef V1MODEL_VERSION
#define V1MODEL_VERSION 20180101
#endif

match_kind {
    range,
    // Точное или шаблонное (соответствует любому) совпадение.
    optional,
    // Служит для реализации dynamic_action_selection.
    selector
}

const bit<32> __v1model_version = V1MODEL_VERSION;

#if V1MODEL_VERSION >= 20200408
typedef bit<9>  PortId_t;       // Не должно иметь постоянный размер?
#endif

@metadata @name("standard_metadata")
struct standard_metadata_t {
#if V1MODEL_VERSION >= 20200408
    PortId_t    ingress_port;
    PortId_t    egress_spec;
    PortId_t    egress_port;
#else
    bit<9>      ingress_port;
    bit<9>      egress_spec;
    bit<9>      egress_port;
#endif
    bit<32>     instance_type;
    bit<32>     packet_length;
    //
    // @alias служит для создания раздела field_alias в файле BMV2 JSON.
    // Псевдоним поля создает отображение имени метаданных в программе P4
    // на внутреннее имя метаданных в модели поведения (bmv2). Здесь это
    // служит для раскрытия всех метаданных, поддерживаемых simple_switch, 
    // для пользователя через standard_metadata_t.
    //
    // «Сглаживающие» поля из bmv2-ss для запроса метаданных.
    @alias("queueing_metadata.enq_timestamp")
    bit<32> enq_timestamp;
    @alias("queueing_metadata.enq_qdepth")
    bit<19> enq_qdepth;
    @alias("queueing_metadata.deq_timedelta")
    bit<32> deq_timedelta;
    /// Глубина очереди в момент извлечения пакета из нее.
    @alias("queueing_metadata.deq_qdepth")
    bit<19> deq_qdepth;

    // Внутренние метаданные
    @alias("intrinsic_metadata.ingress_global_timestamp")
    bit<48> ingress_global_timestamp;
    @alias("intrinsic_metadata.egress_global_timestamp")
    bit<48> egress_global_timestamp;
    /// Идентификатор multicast-группы (ключ для таблицы репликации mcast)
    @alias("intrinsic_metadata.mcast_grp")
    bit<16> mcast_grp;
    /// Идентификатор репликации для multicast
    @alias("intrinsic_metadata.egress_rid")
    bit<16> egress_rid;
    /// Указывает отрицательный результат verify_checksum().
    /// 1 при ошибке контрольной суммы, иначе 0.
    bit<1>  checksum_error;
    /// Ошибка при синтаксическом анализе.
    error parser_error;
    /// Задание приоритета для пакета.
    @alias("intrinsic_metadata.priority")
    bit<3> priority;
}

enum CounterType {
    packets,
    bytes,
    packets_and_bytes
}

enum MeterType {
    packets,
    bytes
}

extern counter
#if V1MODEL_VERSION >= 20200408
<I>
#endif
{
    /***
     * Объект counter (счетчик) создается вызовом конструктора. При 
     * этом создается массив состояний счетчика с набором состояний,
     * заданным параметром size. Индексы массива имеют значения  
     * [0, size-1].
     *
     * Нужно указать, будут ли учитываться только пакеты 
     * (CounterType.packets), только байты (CounterType.bytes) или
     * то и другое (CounterType.packets_and_bytes).
     *
     * Счетчики могут обновляться из программы P4, но для чтения 
     * доступны лишь плоскости управления. Если требуется чтение и 
     * запись из программы P4, следует использовать регистры.
     */
    counter(bit<32> size, CounterType type);
    /* FIXME - Аргумент size должен иметь тип int, но это нарушает
     * проверку типов
     */
 
    /***
     * count() вызывает для указанного индексом состояния считывание,
     * изменение и запись обратно в виде неделимого (atomic) блока
     * относительно обработки других пакетов. Обновление счетчиков 
     * пакетов, байтов или обоих зависит от CounterType экземпляра
     * счетчика при вызове для него конструктора.
     *
     * @param index Индекс обновляемого состояния счетчика в массиве.
     *              Обычно это значение из диапазона [0, size-1].
     *              Если index >= size, состояние счетчика не меняется.
     */
#if V1MODEL_VERSION >= 20200408
    void count(in I index);
#else
    void count(in bit<32> index);
#endif
}

extern direct_counter {
    /***
     * Объект direct_counter создается вызовом его конструктора. Нужно
     * указать подсчет только пакетов (CounterType.packets), только
     * байтов (CounterType.bytes) или обоих (CounterType.packets_and_bytes).
     * После создания объекта его можно связать с одной таблицей, добавляя
     * в ее определение указанное ниже свойство
     *     counters = <object_name>;
     *
     * Счетчики могут обновляться из программы P4, но для чтения 
     * доступны лишь плоскости управления. Если требуется чтение и 
     * запись из программы P4, следует использовать регистры.
     */
    direct_counter(CounterType type);
    /***
     * Метод count() реально не требуется в архитектуре v1model. 
     * Это связано с тем, что после привязки объекта direct_counter к
     * таблице, как описано в документации конструктора direct_counter,
     * при каждом обращении к таблице с возвратом подходящей записи
     * состояние счетчика, связанного с этой записью, считывается, 
     * изменяется и записывается обратно неделимым блоком относительно 
     * обработки других пакетов независимо от вызова метода count() из
     * тела данного действия.
     */
    void count();
}

#define V1MODEL_METER_COLOR_GREEN  0
#define V1MODEL_METER_COLOR_YELLOW 1
#define V1MODEL_METER_COLOR_RED    2

extern meter
#if V1MODEL_VERSION >= 20200408
<I>
#endif
{
    /***
     * Объект meter создается вызовом его конструктора. При этом 
     * создается массив состояний, число которых определяется параметром
     * size. Индексы массива лежат в диапазоне [0, size-1]. Например,
     * при наличии в системе 128 «потоков» с номерами от 0 до 127 и 
     * желании независимо измерять каждый из них, можно создать 
     * измеритель с size=128.
     *
     * Нужно указать для измерителя учет пакетов независимо от размера
     * (MeterType.packets) или числа байтов в пакетах (MeterType.bytes).
     */
    meter(bit<32> size, MeterType type);
    /* FIXME - Аргумент size должен иметь тип int, но это нарушает
     * проверку типов
     */

    /***
     * execute_meter() вызывает для указанного состояния считывание, 
     * изменение и запись обратно в виде неделимого блока относительно
     * обработки других пакетов и представление одним из цветов 
     * (green, yellow, red) в параметре out.
     *
     * @param index Индекс обновляемого состояния в массиве. Обычно из
     *              диапазона [0, size-1]. Если index >= size, состояние
     *              не обновляется.
     * @param result Тип T должен быть bit<W> с W >= 2. Если индекс
     *              находится в диапазоне, будет указано значение 0 для
     *              GREEN, 1 - для YELLOW и 2 - для RED (см. RFC 2697 и 
     *              RFC 2698). Если индекс выходит за пределы диапазона,
     *              результат становится неопределенным и его следует
     *              игнорировать вызывающему.
     */
#if V1MODEL_VERSION >= 20200408
    void execute_meter<T>(in I index, out T result);
#else
    void execute_meter<T>(in bit<32> index, out T result);
#endif
}

extern direct_meter<T> {
    /***
     * Объект direct_meter создается вызовом его конструктора. Нужно
     * указать учет пакетов независимо от размера (MeterType.packets)
     * или числа байтов в пакетах (MeterType.bytes). Созданный объект
     * можно связать с одной таблицей, добавляя в ее определение
     * приведенное ниже свойство
     *     meters = <object_name>;
     */
    direct_meter(MeterType type);
    /***
     * После привязки объекта direct_meter к таблице, как описано в 
     * документации конструктора direct_meter, при каждом нахождении
     * в таблице совпадающей записи значение связанного с этой записью
     * измерителя считывается, обновляется и записывается обратно в 
     * форме неделимого блока относительно обработки других пакетов
     * независимо от вызова метода read() из тела данного действия.
     *
     * Метод read() можно вызывать лишь внутри действия, выполняемого в
     * результате совпадения записи в таблице, с которой связан объект 
     * direct_meter. Результатом вызова read() будет численное 
     * представление цвета (green, yellow, red) в параметре out.
     *
     * @param result Тип T должен быть bit<W> с W >= 2. Указывается 
     *              значение 0 для GREEN, 1 - для YELLOW и 2 - для RED 
     *              (см. RFC 2697 и RFC 2698). 
     */
    void read(out T result);
}

#if V1MODEL_VERSION >= 20200408
extern register<T, I>
#else
extern register<T>
#endif
{
    /***
     * Объект register создается вызовом его конструктора. При этом
     * создается массив из size идентичных элементов типа T с индексами
     * из диапазона [0, size-1]. Например, вызов
     *     register<bit<32>>(512) my_reg;
     * выделит место для 512 значений типа bit<32>.
     */
    register(bit<32> size);
    /* FIXME - Аргумент size должен иметь тип int, но это нарушает
     * проверку типов
     */
    /***
     * Метод read() считывает из массива регистров указанное индексом 
     * состояние и возвращает его значение в параметре result.
     *
     * @param index Индекс элемента в массиве регистров для чтения.
     *              Обычно лежит в диапазоне [0, size-1].
     * @param result Поддерживаются лишь типы bit<W>. Когда индекс
     *              находится в диапазоне, result получает значение
     *              указанного элемента массива. Если index >= size, 
     *              результат будет неопределенным и его следует 
     *              игнорировать вызывающему.
     */
    @noSideEffects
#if V1MODEL_VERSION >= 20200408
    void read(out T result, in I index);
#else
    void read(out T result, in bit<32> index);
#endif
    /***
     * Метод write() записывает значение параметра value в массив 
     * регистров по указанному индексу.
     *
     * Если нужно выполнить read(), а затем write() для одного
     * элемента массива регистров и хочется сделать блок 
     * read-modify-write неделимым относительно обработки других пакетов
     * (параллельное выполнение в архитектуре v1model) требуется 
     * указать блок P4_16 с аннотацией @atomic (см. спецификацию P4_16).
     *
     * @param index Индекс элмента массива регистров для записи. Обычно
     *              из диапазона [0, size-1]. Если index >= size, состояние
     *              регистров не изменяется.
     * @param value Поддерживаются лишь типы bit<W>. Когда индекс
     *              находится в диапазоне, значение value записывается
     *              в указанный индексом элемент массива регистров.
     */
#if V1MODEL_VERSION >= 20200408
    void write(in I index, in T value);
#else
    void write(in bit<32> index, in T value);
#endif
}

// Служит атрибутом реализации таблицы
extern action_profile {
    action_profile(bit<32> size);
}

/***
 * Генерирует случайное значение из диапазона [lo..hi] и записывает
 * его в параметр result. Значение result становится неопределенным,
 * если lo > hi.
 *
 * @param T          Должно иметь тип bit<W>
 */
extern void random<T>(out T result, in T lo, in T hi);

/***
 * Вызов digest вызывает передачу сообщения, содержащего значения,
 * указанные в параметре data, программе плоскости управления. Это
 * похоже на отправку клона пакета плоскости управления, но может
 * быть более эффективным за счет того, что сообщения обычно меньше
 * пакета и можно собрать несколько таких сообщений в блок для 
 * одновременной отправки программе плоскости управления.
 *
 * Значениями полей, передаваемых в сообщении плоскости управления, 
 * будут соответствующие значения в момент вызова digest, даже если
 * эти поля позднее будут изменены элементом управления ingress 
 * (см. Примечание 3).
 *
 * Вызов digest поддерживается лишь из элемента управления ingress. 
 * После вызова метода нельзя отказаться от производимого им эффекта.
 *
 * Если тип T является именованной структурой, имя служит для генерации 
 * API плоскости управления.
 *
 * Реализация архитектуры v1model в BMv2 игнорирует значение параметра
 * receiver.
 */
extern void digest<T>(in bit<32> receiver, in T data);

enum HashAlgorithm {
    crc32,
    crc32_custom,
    crc16,
    crc16_custom,
    random,
    identity,
    csum16,
    xor16
}

@deprecated("Please use mark_to_drop(standard_metadata) instead.")
extern void mark_to_drop();

/***
 * mark_to_drop(standard_metadata) является примитивом действия, меняющим 
 * standard_metadata.egress_spec на зависимое от реализации специальное
 * значение, что в некоторых случаях ведет к отбрасывают пакета в конце
 * входной или выходной обработки. Кстанавливается также значение 0 для
 * standard_metadata.mcast_grp. Любое из этих полей метаданных может быть
 * изменено кодом P4 после вызова mark_to_drop(), что может поменять для
 * пакета поведение на отличное от его отбрасывания (drop).
 *
 * В параграфе «Pseudocode for what happens at the end of ingress and 
 * egress processing» документа
 * https://github.com/p4lang/behavioral-model/blob/master/docs/simple_switch.md2 
 * описан относительный приоритет возможных действий применительно к пакету
 * по завершении входной и выходной обработки.
 */
@pure
extern void mark_to_drop(inout standard_metadata_t standard_metadata);

/***
 * Расчет хэш-функции для значения, указанного параметром data. Результат,
 * записываемый в параметр out с именем result, всегда будет находиться в
 * диапазоне [base, base+max-1], если max >= 1. При max=0 будет записано base.
 *
 * Отметим, что типы параметров могут быть одинаковыми или разными и битовые
 * размеры могут различаться.
 *
 * @param O   Должен иметь тип bit<W>
 * @param D   Должен иметь тип tuple, где все поля являются битовыми (bit<W> или int<W>) или varbit.
 * @param T   Должен иметь тип bit<W>
 * @param M   Должен иметь тип bit<W>
 */
@pure
extern void hash<O, T, D, M>(out O result, in HashAlgorithm algo, in T base, in D data, in M max);

extern action_selector {
    action_selector(HashAlgorithm algorithm, bit<32> size, bit<32> outputWidth);
}

enum CloneType {
    I2E,
    E2E
}

@deprecated("Please use verify_checksum/update_checksum instead.")
extern Checksum16 {
    Checksum16();
    bit<16> get<D>(in D data);
}

/***
 * Проверяет контрольную сумму представленных данных. При обнаружении
 * несоответствия поле standard_metadata checksum_error будет иметь 
 * в начале входной обработки значение 1.
 *
 * Вызов verify_checksum поддерживается лишь из элемента VerifyChecksum.
 *
 * @param T          Должен иметь тип tuple, все элементы которого имеют
 *                   тип bit<W>, int<W> или ,varbit<W>. Одщий размер полей
 *                   должен быть кратным выходному размеру.
 * @param O          Тип контрольной суммы (bit<X>).
 * @param condition  Значение false, задает совпадение при любом результате.
 * @param data       Данные для проверки контрольной суммы.
 * @param checksum   Ожидаемая контрольная сумма (должно быть l-value).
 * @param algo       Алгоритм расчета контрольной суммы (могут поддерживаться
 *                   не все алгоритмы), должен быть известной при компиляции
 *                   константой.
 */
extern void verify_checksum<T, O>(in bool condition, in T data, in O checksum, HashAlgorithm algo);

/***
 * Рассчитывает контрльную сумму представленных данных и записывает ее в 
 * параметр checksum.
 *
 * Вызов update_checksum поддерживается лишь из элементов управления 
 * ComputeChecksum.
 *
 * @param T          Должен иметь тип tuple, все элементы которого имеют
 *                   тип bit<W>, int<W> или ,varbit<W>. Одщий размер полей
 *                   должен быть кратным выходному размеру.
 * @param O          Тип контрольной суммы (bit<X>).
 * @param condition  При значении false параметр checksum не изменяется.
 * @param data       Данные для расчета контрольной суммы.
 * @param checksum   Контрольная сумма данных.
 * @param algo       Алгоритм расчета контрольной суммы (могут поддерживаться
 *                   не все алгоритмы), должен быть известной при компиляции
 *                   константой.
 */
@pure
extern void update_checksum<T, O>(in bool condition, in T data, inout O checksum, HashAlgorithm algo);

/***
 * verify_checksum_with_payload идентичен verify_checksum, но учитывает
 * при расчете контрольной суммы данные из пакета (все байты, которые не 
 * разбираются синтаксическим анализатором).
 *
 * Вызов verify_checksum_with_payload поддерживается лишь из элемента
 * управления VerifyChecksum.
 */
extern void verify_checksum_with_payload<T, O>(in bool condition, in T data, in O checksum, HashAlgorithm algo);

/**
 * update_checksum_with_payload идентичен update_checksum, но учитывает
 * при расчете контрольной суммы данные из пакета (все байты, которые не 
 * разбираются синтаксическим анализатором).
 *
 * Вызов update_checksum_with_payload поддерживается лишь из элемента
 * управления ComputeChecksum.
 */
@noSideEffects
extern void update_checksum_with_payload<T, O>(in bool condition, in T data, inout O checksum, HashAlgorithm algo);

/***
 * Вызов resubmit в процессе выполнения элемента ingress будет при 
 * некоторых документированных условиях приводить к повторному 
 * представлению пакета, т. е. пакет будет заново обработан анализатором
 * с тем же содержимым, которое было при предыдущей обработке. Различие
 * состоит лишь в значении поля standard_metadata instance_type и 
 * заданных пользователем полей метаданных, которые операция resubmit 
 * будет сохранять.
 *
 * Значения пользовательских метаданных, сохраняемых при повторном 
 * представлении пакетов, являются значениями в конце входной обработки,
 * а не значениями в момент вызова resubmit (см. Примечание 2).
 *
 * Вызов resubmit поддерживается лишь из элемента управления ingress. 
 * Отменить воздействие этого вызова невозможно. При неоднократном вызове
 * resubmit в одном процессе выполнения элемента ingress повторно 
 * представляется лишь один пакет и сохраняются данные лишь для последнего
 * вызова (см. Примечание 1).
 */
extern void resubmit<T>(in T data);

/***
 * Вызов recirculate в процессе выполнения элемента ingress будет при 
 * некоторых документированных условиях приводить к повторной обработке 
 * пакета, начиная с синтаксического анализа пакета, созданного сборщиком
 * (deparser). Рециркулирующие пакеты могут при входной обработке 
 * различаться с новыми пакетами значением поля standard_metadata
 * instance_type. Вызывающий может запросить сохранение некоторых 
 * полей пользовательских метаданных при рециркуляции пакета.
 *
 * Значения пользовательских метаданных, сохраняемых при рециркуляции 
 * пакетов, являются значениями в конце выходной обработки,
 * а не значениями в момент вызова recirculate (см. Примечание 2).
 *
 * Вызов recirculate поддерживается лишь из элемента управления egress. 
 * Отменить воздействие этого вызова невозможно. При неоднократном вызове
 * recirculate в одном процессе выполнения элемента egress рециркулирует 
 * лишь один пакет и сохраняются данные лишь для последнего
 * вызова (см. Примечание 1).
 */
extern void recirculate<T>(in T data);

/***
 * Операция clone почти идентична clone3 и отличается лишь тем, что
 * никогда не сохраняет поля пользовательских метаданных в клонах пакетов.
 * Она эквивалентна вызову clone3 с теми же параметрами type и session, но
 * с пустым параметром data.
 */
extern void clone(in CloneType type, in bit<32> session);

/***
 * Вызов clone3 при выполнении элемента управления ingress или egress
 * приводит к созданию клонов пакета (иногда называют отражением). 
 * Т. е. могут создаваться копии пакета, каждая из которых затем 
 * подвергается выходной обработке как независимый пакет. Для исходного
 * пакета продолжается обычная обработка независимо от клонов.
 *
 * Целочисленный параметр session содержит идентификатор сеанса клонирования
 * (иногда называется идентификатором сеанса отражения). Программы плоскости
 * управления должны настроить конфигурацию каждой сессии, которую планируется
 * использовать. Без этого клонирования происходить не будет. Обычно такая 
 * настройка включает задание плоскостью управления выходного порта, куда 
 * будет передаваться клон или списка пар (port, egress_rid), для которых 
 * следует создавать клоны подобно групповым пакетам.
 *
 * Клонированные пакеты можно различать по значениям поля 
 * standard_metadata instance_type.
 *
 * Вызывающий может запросить сохранение некоторых полей пользовательских 
 * метаданных исходного пакета при клонировании. Сохраняться будут значения
 * в конце входной или выходной обработки, а не в момент вызова clone3
 * (см. Примечание 2).
 *
 * При вызове clone3 во время входной обработки первым параметром должен быть
 * CloneType.I2E, для вызова при выходной обработке - CloneType.E2E.
 *
 * Отменить воздействие этого вызова невозможно. При неоднократном вызове
 * clone3 и/или clone в одном процессе входной или выходной обработки 
 * используется лишь последняя сессия клонирования и данные (см. Примечание 1).
 */
extern void clone3<T>(in CloneType type, in bit<32> session, in T data);

extern void truncate(in bit<32> length);

/***
 * Вызов assert с аргументом, имеющим значение true не дает эффекта, за 
 * исключением тех, которые может давать вычисление аргумента (см. ниже).
 * Если аргумент имеет значение false, поведение зависит от целевой платформы,
 * но цель заключается в записи или выводе информации об отказавшем операторе 
 * assert и возможно дополнительных данных об отказе.
 *
 * Например, на платформе simple_switch выполнение оператора assert с
 * аргументом false вызывает сообщение с именем файла и номером строки с
 * оператором assert, после чего процесс simple_switch завершается.
 *
 * Если была задана опция --ndebug в командной строке p4c при компиляции,
 * скомпилированная программа ведет себя как при отсутствии операторов 
 * assert в исходном коде.
 *
 * Настоятельно рекомендуется избегать выражений в качестве аргумента 
 * assert, поскольку это может приводить к побочным эффектам, например,
 * вызову внешнего метода или функции с побочным эффектом. Компилятор p4c 
 * позволяет это, не выдавая предупреждений. Это рекомендуется потому, что
 * программа будет вести себя так же, как при удалении операторов assert.
 */
extern void assert(in bool check);

/***
 * Для целей компиляции и запуска программ P4 на целевом устройстве
 * операторы assert и assume являются идентичными, включая использование
 * опции --ndebug компилятор p4c для их исключения. См. описание assert.
 *
 * Причиной использования assume как отдельной функции является допущение 
 * о ее специальной трактовке инструментами формальной проверки. Для 
 * некоторых таких инструментов цель состоит в попытке найти примеры 
 * пакетов и установленных записей таблиц, где условие оператора assert
 * имеет значение false.
 *
 * Предположим, что такой инструмент запускается для программы и примером 
 * служит пакет MPLS, где hdr.ethernet.etherType == 0x8847. При рассмотрении
 * примера видно, что условие assert имеет значение false. Однако планируется 
 * развертывание программы P4 в сети, где нет пакетов MPLS. Можно добавить
 * в программу P4 дополнительные условия для корректной обработки пакетов без
 * отказов assert, но проще сказать инструменту, что «такие экземпляры пакетов
 * не применимы и не нужно их показывать» путем добавления оператора
 *     assume(hdr.ethernet.etherType != 0x8847);
 * в подходящее место программы. Тогда формальный инструмент не будет показывать 
 * такие примеры, ограничиваясь лишь теми, которые дают условие true.
 *
 * Причина одинакового поведения операторов assume и assert при компиляции для
 * целевого устройства заключается в том, что значение false при оценке 
 * условия во время работы в сети может говорить об ошибочности допущения 
 * и необходимости его проверки.
 */
extern void assume(in bool check);

/*
 * Вывод заданного пользователем сообщения.
 * Например, log_msg("User defined message");
 * или log_msg("Value1 = {}, Value2 = {}",{value1, value2});
 */
extern void log_msg(string msg);
extern void log_msg<T>(string msg, in T data);

// Имя standard_metadata является зарезервированным.

/*
 * Архитектура.
 *
 * M должно иметь тип struct.
 *
 * H должно иметь тип struct, где каждый из элементов является заголовком,
 * стеком или объединением заголовков.
 */

parser Parser<H, M>(packet_in b,
                    out H parsedHdr,
                    inout M meta,
                    inout standard_metadata_t standard_metadata);

/*
 * В теле элемента управления VerifyChecksum допускаются лишь операторы 
 * блока, вызовы методов verify_checksum и verify_checksum_with_payload, 
 * а также операторы return.
 */
control VerifyChecksum<H, M>(inout H hdr,
                             inout M meta);
@pipeline
control Ingress<H, M>(inout H hdr,
                      inout M meta,
                      inout standard_metadata_t standard_metadata);
@pipeline
control Egress<H, M>(inout H hdr,
                     inout M meta,
                     inout standard_metadata_t standard_metadata);

/*
 * В теле элемента управления ComputeChecksum допускаются лишь операторы 
 * блока, вызовы методов update_checksum и update_checksum_with_payload, 
 * а также операторы return.
 */
control ComputeChecksum<H, M>(inout H hdr,
                              inout M meta);

/*
 * В теле элемента управления Deparser допускается лишь метод packet_out.emit().
 */
@deparser
control Deparser<H>(packet_out b, in H hdr);

package V1Switch<H, M>(Parser<H, M> p,
                       VerifyChecksum<H, M> vr,
                       Ingress<H, M> ig,
                       Egress<H, M> eg,
                       ComputeChecksum<H, M> ck,
                       Deparser<H> dep
                       );

#endif  /* _V1_MODEL_P4_ */

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

nmalykh@protocols.ru

1Имеется перевод документа на русский язык.

2Параграф «Псевдокод для завершения входной и выходной обработки» в переводе.

Рубрика: SDN, Сетевое программирование | Комментарии к записи Архитектура v1model отключены

Параметры simple_switch

image_print

PDF

Синтаксис

simple_switch [опции] <путь к JSON-файлу конфигурации коммутатора>

Опции

-h [ –help ]

Выводит справочную информацию и на этом завершает работу.

-i [ –interface ] arg <port-num>@<interface-name>

Привязывает сетевой интерфейс <interface-name> в качестве порта с номером <port-num> при запуске программы. Опция может использоваться в команде многократно.

–pcap [=arg(=.)]

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

–use-files arg

Считывает пакеты из файлов или записывает в файлы (интерфейсу X соответствуют файлы X_in.pcap и X_out.pcap). Аргумент задает время ожидания (в секундах) перед началом обработки файлов с пакетами.

–packet-in arg

Включает прием пакетов на этом (nanomsg) сокете. В этом случае опция –interface будет игнорироваться.

–thrift-port arg

Порт TCP на котором будет работать сервер интерфейса управления Thrift.

–device-id arg

Идентификатор, указывающий устройство в сообщениях IPC. По умолчанию 0.

–nanolog arg

Сокет IPC для использования с журналами nanomsg pub/sub. По умолчанию журналы nanomsg не ведутся.

–log-console

Включает вывод журнальной информации на устройство stdout.

–log-file arg

Включает вывод журнала в указанный файл.

-L [ –log-level ] arg

Задает уровень детализации при выводе журнала работы и может принимать значение trace, debug, info, warn, error или off. По умолчанию используется уровень trace.

–log-flush

При использовании с опцией –log-file задает сброс журнала на диск после каждого сообщения.

–notifications-addr arg

Указывает адрес nanomsg для уведомлений (обучение, старения и т. п.), по умолчанию ipc:///tmp/bmv2-<device-id>-notifications.ipc

–restore-state arg

Задает восстановление состояния из файла.

–dump-packet-data arg

Задает число байтов для дампа принимаемых и передаваемых пакетов. Дамп выводится с уровнем info, поэтому следует убедиться, что при выводе этот уровень не исключается. По умолчанию установлено значение 0 и не выводится ничего.

-v [ –version ]

Выводит информацию о версии программы.

–json-version

Выводит максимальную поддерживаемую версию bmv2 JSON в формате <major>.<minor>. Должны поддерживаться все версии bmv2 JSON с совпадающим значением <major>.

–no-p4

Позволяет запустить коммутатор без файла конфигурации.

–max-port-count arg (=512)

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

Платформа имеет также свой анализатор команд и нужно отделять опции платформы от опций bmv2 двумя дефисами (–).

Опции платформы

–load-modules arg

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

–enable-swap

Включает файл подкачки JSON в процессе работы.

–drop-port arg

Задает номер порта drop (по умолчанию 511).

Рубрика: SDN, Сетевое программирование | Комментарии к записи Параметры simple_switch отключены

Компилятор P4C (драйвер компиляции)

image_print

PDF

Синтаксис

p4c [-h] [-V] [-v] [-###] [-Xpreprocessor <arg>] [-Xp4c <arg>] 
    [-Xassembler <arg>] [-Xlinker <arg>] [-b TARGET] [-a ARCH] [-c] 
    [-D PREPROCESSOR_DEFINES] [-E] [-e] [-g] [-I SEARCH_PATH] [-o PATH] 
    [--p4runtime-file P4RUNTIME_FILE] 
    [--p4runtime-files P4RUNTIME_FILES] 
    [--p4runtime-format {binary,json,text}] [--help-pragmas] 
    [--help-targets] [--disable-annotations DISABLED_ANNOS] [-S] 
    [--std {p4-14,p4_14,p4-16,p4_16}] [--ndebug] 
    [source_file]

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

Опции

Остальные аргументы команды являются необязательными (опции) и служат для управления компиляцией исходного кода P4. Многие опции доступны в краткой и длинной форме (с префиксом –)

-h, –help

Выводит справку о параметрах команды и завершает работу.

-V, –version

Выводит номер версии программы и завершает работу.

-v, –debug

Задает подробный вывод программы.

-###, –test-only

Выводит команды на консоль без из реального выполнения.

-Xpreprocessor <arg>

Задает передачу аргумента <arg> препроцессору компилятора.

-Xp4c <arg>

Задает аргумент, передаваемый компилятору.

-Xassembler <arg>

Задает передачу аргумента <arg> ассемблеру.

-Xlinker <arg>

Задает передачу аргумента <arg> компоновщику.

-b TARGET, –target TARGET

Задает целевое устройство (платформу).

-a ARCH, –arch ARCH

Задает целевую архитектуру.

-c, –compile

Задает выполнение лишь этапов предварительной обработки, компиляции и сборки.

-D PREPROCESSOR_DEFINES

Определяет макрос, используемый препроцессором.

-E

Задает выполнение только препроцессора.

-e

Задает пропуск препроцессора.

-g

Задает генерацию отладочной информации.

-I SEARCH_PATH

Задает каталог для поиска включаемых файлов.

-o PATH, –output PATH

Задает каталог для записи вывода.

–p4runtime-file P4RUNTIME_FILE

Задает вывод описания P4Runtime (API плоскости управления) в указанный файл. Опция устарела и взамен следует использовать –p4runtime-files.

–p4runtime-files P4RUNTIME_FILES

Задает вывод описания P4Runtime (P4Info, API плоскости управления) в указанные через запятые файлы. Формат файлов задают указанные расширения имен (суффиксы) .txt, .json, .bin.

–p4runtime-format {binary,json,text}

Задает выходной формат для описания P4Runtime API (по умолчанию .bin). Опция устарела и взамен следует использовать –p4runtime-files.

–help-pragmas, –pragma-help, –pragmas-help, –help-annotations, –annotation-help, –annotations-help

Выводит документацию поддерживаемых annotation и pragma, после чего завершает работу.

–help-targets, –target-help, –targets-help

Выводит связанные с целевой платформой опции команд.

–disable-annotations DISABLED_ANNOS, –disable-annotation DISABLED_ANNOS …

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

-S

Задает выполнение лишь этапов предварительной обработки и компиляции.

–std {p4-14,p4_14,p4-16,p4_16}, -x {p4-14,p4_14,p4-16,p4_16}

Указывает вариант языка во входных файлах.

–ndebug

Задает компиляцию программы без отладочной информации.

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

nmalykh@protocols.ru

Рубрика: SDN, Сетевое программирование | Комментарии к записи Компилятор P4C (драйвер компиляции) отключены

Промежуточные представления компилятора P4C

image_print

Оригинал

PDF

Введение

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

Новизна заключается в возможности всегда вернуться к более ранней версии IR (обратное прохождение) или использовать множество потоков при работе с IR, что позволяет реализовать разные стратегии при поиске окончательного результата. Поддержка ветвления и возврата является центральным моментом IR и преобразования. Задачей IR является представление программы в виде дерева или DAG2 с одним корневым узлом и остальными узлами, указывающими лишь своих потомков. Преобразования выполняются путем создания новых узлов IR, являющихся «мелкими» копиями имеющихся узлов, и последующего создания для них новых родительских узлов вплоть до корня IR. Внутреннее представления реализовано на C++ в форме одной иерархии наследования объектов с основным базовым узлом типа Node, используемым всеми субклассами. Этот базовый класс Node поддерживает функциональность, требуемую для преобразований – клонирование, проверку эквивалентности, диспетчеризацию субклассов.

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

IR может быть деревом или DAG, но разрешение ссылок «вперед-назад» (back/up) в IR (циклах) сводит на нет большинство преимуществ неизменного IR. Если циклы (например, узлы-листья для имен напрямую ссылающиеся на именованный объект) разрешены, практически любое преобразование будет приводить к клонированию всего графа IR, поскольку изменение листа включает клонирование содержащего его объекта, а затем (рекурсивно) любого объекта, указывающего на этот объект.

Проходы Visitor и Transform

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

    /* псевдокод базового преобразования */
    visit(node, context=ROOT, visited={}) {
        if (node in visited) {
                if (visited[node] == INVALID)
                        throw loop_detected
                if (VisitDagOnce)
                        return visited[node] }
        visited[node] = INVALID
        copy = shallow_clone(node)
        if (VisitDagOnce)
                forward_children(copy, visited)
        copy = preorder(copy, context) // переопределен в субклассе Transform
        visit_children(copy, {copy, context}, visited)
        copy = postorder(copy, context) // переопределен в субклассе Transform
        if (*copy == *node) {
                visited[node] = node
                return node
        } else {
                visited[node] = copy
                return copy }
    }
    forward_children(node, visited) {
        for (child in children(node))
                if (child in visited)
                        child = visited[child]
    }
    visit_children(node, context, visited) {
        for (child in children(node))
                child = visit(child, context, visited)
    }

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

Имеется несколько субклассов Visitor, описывающих разные типы посетителей.

Субкласс

Описание

Inspector

Простой посетитель, собирающий информацию, но не меняющий узлы.

Modifier

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

Transform

Полное преобразование узла

PassManager

Комбинация нескольких типов, выполняемых последовательно.

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

Интерфейс

Описание

ControlFlowVisitor

Посещение узлов в порядке потока управления, расщепление (клонирование) посетителя по условию и слияние клонов в точке соединения.

Backtrack

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

ControlFlowVisitor

Для поддержки анализа потока управления имеется специальный интерфейс ControlFlowVisitor,
который
понимают определенные субклассы
IR, инкапсулирующие поток управления, и применяют для управления порядком посещения узлов-потомков и состоянием посетителя, передаваемым его подпрограммам preorder/postorder для анализа потока управления.

Базовая идея заключается в том, что узлы потока управления в IR при посещении своих потомков создают клоны объектов ControlFlowVisitor для посещения различных потомков после ветвления и вызывают функцию flow_merge в точке соединения для слияния состояний посетителя. Базовый класс Visitor и интерфейс ControlFlowVisitor определяют две виртуальные функции – flow_clone и flow_merge решающие эти задачи. В базовом классе Visitor (используется всеми посетителями, не наследующими из интерфейса ControlFlowVisitor), где функции реализованы в виде no-ops, функция flow_clone просто возвращает тот же объект, а flow_merge не делает ничего. В интерфейсе ControlFlowVisitor функция flow_clone вызывает функцию clone (которая должна быть реализована классом leaf), а flow_merge является абстрактной виртуальной функцией, которая должна быть реализована в классе leaf.

В качестве примера использования в программах посетителя IR рассмотрим класс IR::If, имеющих 3 дочерних элемента для посещения – утверждение (predicate) и два следствия (consequent), причем значение утверждения определяет, какое из следствий выполняется. Дочерний посетитель для IR::If имеет вид

    visitor.visit(predicate);
    clone = visitor.flow_clone();
    visitor.visit(ifTrue);
    clone.visit(ifFalse);
    visitor.flow_merge(clone);

Таким образом оба следствия посещаются с состоянием посетителя, соответствующим потоку управления, сразу после оценки утверждения, а затем состояния потока управления после обоих посещений объединяются.

Для использования этой функциональности субклассу Visitor нужно лишь наследовать от интерфейса ControlFlowVisitor и реализовать функции clone и flow_merge. Другим классам Visitor не нужно делать ничего, но они могут реализовать clone по иным причинам.

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

Поток в целом

Поток компиляции можно грубо разделить на три части – frontend, mid-end и backend. Интерфейсная часть (frontend) выполняет в основном не связанные с целевой платформой преобразования, предназначенные для очистки IR и приведения в каноническую форму. Средняя часть (middleend) выполняет зависящие от целевой платформы преобразования IR. Последняя часть (backend) принимает решения о выделении ресурсов. Поскольку этот этап может завершаться отказом по причине имеющихся ограничений, может потребоваться возврат к mid-end для проверки иной конфигурации. Возврата к начальному этапу (frontend) не предполагается. Разделение на этапы Front/Middle/Back достаточно произвольно и некоторые проходы могут перемещаться между этапами, если в этом будет смысл.

Frontend

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

Mid-end

На этапе mid-end выполняются преобразования, в той или иной степени зависящие от целевой платформы, но не связанные с выделением конкретных ресурсов. В какой-то части этих преобразований представление IR преобразуется в фрому, соответствующую возможностям целевой платформы.

Управление проходами

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

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

    interface Backtrack {        bool backtrack(trigger);     }

Метод backtrack вызывается при возникновении необходимости возврата и возвращает значение true, если в повторном проходе можно проверить применимый вариант. В противном случае (вариантов нет) возвращается false для поиска иной точки возврата.

Использование исключений

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

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

  • CompilerBug используется при внутренних ошибках компилятора. Взамен непосредственного вызова служит макрос BUG().

Классы IR

Чтобы упростить управление и расширений для классов IR, они определяются файлах .def, которые обрабатываются программой ir-generator, создающей код IR C++. По сути, файлы .def являются просто определениями классов C++ с удаленным шаблоном, который вставляет программа ir-generator, расщепляя также определение каждого класса на файлы .h и .cpp по мере необходимости.

Основная часть «нормального» IR определяется в каталоге ir, при этом некоторые frontend и backend используют свои расширения имен для IR, определяемых в их подкаталогах внутри ir. Программа ir-generator считывает все файлы .def в дереве и создает по одному файлу .h и .cpp, которые содержат весь код определения класса IR.

Все ссылки на объекты класса IR из объектов других классов IR должны быть указателями const, чтобы поддерживать инварианты, открытые лишь для записи (write-only). Когда это слишком обременительно, можно встраивать классы IR непосредственно в другие объекты IR, вместо использования ссылок. При таком встраивании объектов IR они становятся доступными для изменения посетителями Modifier
и
Transform при посещении содержащего объект узла, а сами объекты непосредственно посещаться не будут.

Программа ir-generator понимает оба эти механизма. Любое поле, объявленное в классе IR с другим классом IR в качестве типа, будет преобразовано в указатель const, если у него нет встроенного модификатора (в данном случае это будет встроенный напрямую субобъект).

Программа ir-generator понимает множество «стандартных» методов для классов IR – visit_children, operator==, dbprint, toString, apply. Эти методы можно объявлять без аргументов и типов возврата (т. е. просто указывать имя метода с блоком кода в фигурных скобках – {}), при этом будет синтезировано стандартное объявление. Если метод не объявлен в файле .def, создается стандартное определение (наоснове объявленных в классе полей). Таким способом большинство классов могут избежать включения этого шаблонного кода в файл .def.

IR::Node

Это основной абстрактный класс для всех узлов IR, содержащий лишь небольшое количество данных для информирования об ошибках и отладки. В общем случае эти данные никогда не сравниваются на предмет равенства (субклассам никогда не следует вызывать Node::operator==`), поскольку узлы (Node), различающиеся лишь этой информацией следует считать эквивалентными и не требовать для них клонирования или дерева IR.

IR::Vector<T>

Этот шаблонный класс содержит вектор указателей (const) на узлы конкретного субкласса IR::Node.

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

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

nmalykh@protocols.ru

1Intermediate representation.

2Directed acyclic graph – ориентированный ациклический граф (орграф), в котором отсутствуют направленные циклы, но могут быть «параллельные» пути, выходящие из одного узла и разными путями приходящие в конечный узел.

Рубрика: SDN, Сетевое программирование | Комментарии к записи Промежуточные представления компилятора P4C отключены

RFC 8875 Working Group GitHub Administration

image_print
Internet Engineering Task Force (IETF)                         A. Cooper
Request for Comments: 8875                                         Cisco
Category: Informational                                       P. Hoffman
ISSN: 2070-1721                                                    ICANN
                                                             August 2020

Working Group GitHub Administration

Администрирование рабочих групп GitHub

PDF

Аннотация

Использование GitHub в рабочих группах (WG) IETF возрастает. Этот документ описывает использование и соглашения для рабочих групп, начинающих пользоваться GitHub. Документ не задает обязательных процессов и не требует изменения работы существующих и будущих групп, которые не пользуются GitHub.

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

Документ не содержит какой-либо спецификации (Internet Standards Track) и публикуется с информационными целями.

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

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

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

Copyright (c) 2020. Авторские права принадлежат 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).

Оглавление

Исключено в варианте HTML.

1. Введение

Многие рабочие группы и участники процессов IETF используют GitHub разными способами в своей работе над документами IETF. Некоторые люди заинтересованы в использовании GitHub их рабочими группами, но не знают, с чего начать или каким соглашениям следовать. Некоторые рабочие группы используют или планируют применять другие репозитории кода, такие как GitLab и Bitbucket, свойства которых отличаются от GitHub.

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

2. Административный процесс и соглашения

В этом разделе описан административный процесс и соглашения для поддержки создания и управления организацией в GitHub для рабочих групп и хранилищ отдельных документов единообразным способом. Эти действия можно выполнить вручную через секретариат IETF или автоматизированным путем. Примеры автоматизированных решений доступны по ссылкам https://github.com/richsalz/ietf-gh-scripts и https://github.com/martinthomson/i-d-template.

В этом документе вопрос выбора ручного или автоматизированного процесса намеренно не рассматривается, поскольку эти детали будут рассмотрены в IETF Secretariat и Tools Team.

Большинство приведенных ниже соглашений взяты из [RFC8874].

2.1. Создание организации в GitHub

Этот документ указывает, что интерфейс IETF Datatracker позволяет руководителям направлений (area director – AD) или рабочих групп запрашивать создание в GitHub организации для конкретной рабочей группы. В идеале эта возможность должна присутствовать как часть пользовательского интерфейса (UI) создания рабочей группы и ее страницы.

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

  1. Для рабочей группы создается организация GitHub.

  2. Имя организации имеет формат ietf-wg-<wgname>…

  3. Организация инициализируется путем указания IETF Secretariat и руководителей направления в качестве владельцев области данной группы. Если ответственный AD для рабочей группы работает в другом направлении (area), этот AD также будет владельцем.

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

После создания организации ее URL добавляется на страницу рабочей группы в Datatracker.

Этапы 3 и 4 подразумевают, что идентификаторы владельцев и администраторов известны GitHub. Запись идентификаторов GitHub в Datatracker (см. https://trac.tools.ietf.org/tools/ietfdb/ticket/2548) будет облегчать это. Лицо, запрашивающее создание организации о недоступности идентификаторов GitHub для любого из указанных в качестве владельцев и администраторов.

2.2. Перенос существующих организаций

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

2.3. Изменение персонала

При смене персонала для направления или рабочей группы эти изменения будут отражаться в организации GitHub. В Datatracker следует обеспечить возможность отслеживания смены персонала.

2.4. Закрытие рабочей группы

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

2.5. Создание репозитория документов

Имеется много вариантов и конфигураций, в которых может быть полезно использование автоматизации или административных соглашения для репозиториев в рамках организации WG:

  • создание нового репозитория для отдельного чернового документа (по решению руководителя WG);

  • создание нового репозитория для уже принятого рабочей группой проекта (draft);

  • перенос имеющегося репозиория документов в организацию WG;

  • создание нового репозитория с множеством черновых документов.

В качестве этапа процесса этот документ указывает наличие в интерфейсе Datatracker инструмента, позволяющего администратору организации ietf-wg-<wgname> запросить создание нового репозитория для одного документа внутри этой организации. Авторы этого документа будут указаны как участники работы, а репозиторий получит имя чернового документа. В идеале репозиторий должен быть настроен с шаблоном чернового документа, файлами CONTRIBUTING, LICENSE и README, а также с поддержкой непрерывной интеграции в стиле https://github.com/martinthomson/i-d-template. Выполнение этого этапа будет автоматически информировать IETF Secretariat о необходимости создать резерную копию репозитория в соответствии с параграфом 3.2.

2.6. Список связанных репозиториев

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

3. Рабочий процесс

В [RFC8874] рассмотрены разные варианты использования GitHub рабочими группами и множество решений для реализации этого. В этом разделе указаны базовые административные правила для рабочих групп и описана административная поддержка этих правил.

3.1. Участники работы

Каждый репозиторий, созданный в организации WG, должен как минимум включать в свой файл CONTRIBUTING шаблонный текст https://trustee.ietf.org/license-for-open-source-repositories.html из файла лицензии IETF для репозиториев с открытым кодом. Этот файл может включать и другую информацию (см., например, https://github.com/ietf/repo-files/tree/master/contributing-samples).

Будет полезно указывать в пользовательских данных Datatracker как минимум список учетные данные пользователей GitHub, чтобы упростить отслеживание их вклада в работу.

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

3.2. Резервные копии и архивы содержимого GitHub

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

Информация рабочей группы в GitHub также должна архивироваться с обеспечением публичного доступа к архивам. Этот документ задает использование для решения этих задач протокола Git [git-protocol].

Репозиторий каждой рабочей группы IETF в GitHub будет иметь одноименный репозиторий (зеркало) на сервере, поддерживаемом секретариатом IETF. Каждый час служба будет использовать команду git fetch для всех отслеживаемых репозиториев GitHub. Зеркало репозитория будет обеспечивать доступ для всех.

Отметим, что эта система не делает резервных копий и запросов на вытягивание (pull). Резервные копии следует делать и GitHub API позволяет это. Секретариату IETF следует делать резерные копии зеркала одновременно с созданием резерных копий репозиториев GitHub.

Шаги, описанные в параграфе 2.5, информируют IETF Secretariat о репозиториях, для которых следует создать резервные копии. Руководителям рабочих групп и направлений следует аткже иметь возможность запрашивать у секретариата IETF резервное копирование других репозиториев и связанных рабочих IETF.

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

Злоумышленник может изменить содержимое Internet-Drafts, особенно на финальных этапах работы и внести незаметные изменения в протоколы, которые могут быть в коненом итоге приняты.

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

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

Этот документ не требует действий IANA.

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

[git-protocol] Chacon, S. and B. Straub, “Git on the Server – The Protocols”, in Pro Git, 2014, <https://git-scm.com/book/en/v2/Git-on-the-Server-The-Protocols#The-Git-Protocol>.

[RFC8874] Thomson, M. and B. Stark, “Working Group GitHub Usage Guidance”, RFC 8874, DOI 10.17487/RFC8874, August 2020, <https://www.rfc-editor.org/info/rfc8874>.

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

Alissa Cooper

Cisco

Email: alcoop@cisco.com

Paul Hoffman

ICANN

Email: paul.hoffman@icann.org

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

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

nmalykh@protocols.ru

1Internet Engineering Task Force.

2Internet Engineering Steering Group.

Рубрика: RFC | Комментарии к записи RFC 8875 Working Group GitHub Administration отключены

simple_switch_CLI

image_print

Консольный интерфейс simple_switch_CLI

PDF

Версия 1.0

24.09.2020

Оглавление

Исключено в варианте HTML

Программы runtime_CLI и simple_switch_CLI служат для управления программными коммутаторами и маршрутизаторами из пакета BMv2, распространяемого в исходных кодах. Эти программы, по сути, представляют собой прототип плоскости управления (control-plane), полнофункциональной реализацией которой в SDN служит контроллер (например, P4Runtime).

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

Большая часть описанных здесь команд работает в runtime_CLI и simple_switch_CLI, несколько команд применимы лишь в simple_switch_CLI и помечены как [simple_switch_CLI].

Управление программными реализациями прототипов устройств BMv2 выполняется через встроенный в эти реализации сервер Thrift. Интерфейс управления в настоящее время имеет достаточно ограниченную функциональность и позволяет выполнять лишь небольшой набор операций управления коммутатором:

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

По умолчанию сервер управления коммутатором доступен через порт 9090. При необходимости номер порта можно изменить с помощью опции –thrift-port в командной строке simple_switch (плоскость данных) и simple_switch_CLI (плоскость управления).

Команды управления портами

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

show_ports

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

port_add

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

port_add <iface_name> <port_num> [pcap_path]

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

port_remove

Удаляет порт из коммутатора. Результат удаления зависит от используемого менеджера устройств. Команда принимает в качестве параметра номер удаляемого порта.

port_remove <port_num>

Команды управления профилями действий

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

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

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

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

Ниже представлено определение профиля действий в формате BNF.

action_profile_declaration ::=
	action_profile action_profile_name {
		action_specification
		[ size : const_expr ; ]
		[ dynamic_action_selection : selector_name ; ]
	}
action_specification ::=
	actions { [ action_name ; ] + }
action_selector_declaration ::=
	action_selector selector_name {
		selection_key : field_list_calculation_name ;
}

Профили действий задаются и применяются в соответствии с приведенным ниже соглашением.

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

Далее описаны поддерживаемые в simple_switch_CLI команды для работы с профилями действий в таблицах сопоставления программ P4.

act_prof_add_member_to_group

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

act_prof_add_member_to_group <action profile name> <member handle> <group handle>

act_prof_create_group

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

act_prof_create_group <action profile name>

act_prof_create_member

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

act_prof_create_member <action profile name> <action_name> [action parameters]

act_prof_delete_group

Удаляет группу из профиля действия (операции). Параметрами команды служат имя профиля действия и идентификатор удаляемой группы.

act_prof_delete_group <action profile name> <group handle>

act_prof_delete_member

Удаляет элемент из профиля действия (операции). Параметрами команды служат имя профиля действия и идентификатор удаляемого элемента.

act_prof_delete_member <action profile name> <member handle>

act_prof_dump

Выводит список записей в профиле действия (операции). Параметром команды служит имя профиля действия.

act_prof_dump <action profile name>

act_prof_dump_group

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

act_prof_dump_group <action profile name> <group handle>

act_prof_dump_member

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

act_prof_dump_member <action profile name> <member handle>

act_prof_modify_member

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

act_prof_modify_member <action profile name> <action_name> <member_handle> [action parameters]

act_prof_remove_member_from_group

Удаляет элемент из группы в профиле действия (операции). Параметрами команды служат имя профиля действия, идентификатор удаляемого элемента и идентификатор группы.

act_prof_remove_member_from_group <action profile name> <member handle> <group handle>

show_actions

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

Команды для работы с таблицами

table_add

Добавляет действие в указанную именем таблицу.

RuntimeCmd: help table_add Add entry to a match table: table_add <table name> <action name> <match fields> => <action parameters> [priority]

Можно увидеть список имен всех таблиц и действий с помощью команд show_tables и show_actions. Если не используется аннотация @name в программе P4, принятое по умолчанию имя зачастую является иерархическим и начинается с имени элемента управления, в котором определена таблица или действие.

Поля сопоставления должны указываться в том же порядке, в котором заданы поля ключей поиска в программе P4, но без имен. Вывод команды show_tables показывает имена, типы сопоставления (ternary, range, lpm, exact) и размер в битах для каждой таблицы после строки mk=. Поля с типом сопоставления optional представляются как ternary в файле BMv2 JSON, а в simple_switch_CLI всегда идентичны ternary.

Числовые значения можно задавать в десятичном или шестнадцатеричном формате (префикс 0x).

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

  • 32-битовые значения можно указывать в формате адресов IPv4 (например, 10.1.2.3);
  • 128-битовые значения можно задавать подобно адресам IPv6 в нотации IETF (например, FEDC:BA98:7654:3210:FEDC:BA98:7654:3210 или 1080::8:800:200C:417A) как описано в RFC 2732;
  • 48-битовые значения можно задавать подобно адресам Ethernet MAC с парами шестнадцатеричных цифр, разделенными двоеточиями (например, 00:12:34:56:78:9a).

Поля ключей поиска в таблице с типом сопоставления lpm должны иметь значение, за которым указан символ / и размер префикса (например, 0x0a010203/24). Размер префикса должен указываться десятичным числом. Может указываться префикс с размером 0 и такие записи будут соответствовать любому значению искомого поля.

Поля ключей поиска в таблице с типом сопоставления ternary задаются численным значением, за которым следует &&& и численная маска без пробелов между числами и &&&. Биты маски со значением 1 задают совпадение битов, а биты со значением маски 0 не рассматриваются при сопоставлении. Т. е. запись value&&&mask будет соответствовать ключу поиска k, если (k & mask) == (value & mask), где операция & выполняется для каждого бита, как в P4. Для соответствия любому значению при троичном поиске можно задать 0&&&0.

Поля ключей поиска в таблице с типом сопоставления optional в исходном коде P4 задаются так же, как поля с типом сопоставления ternary. Отметим, что CLI при работе не проверяет наличие в маске только нулей или только 1, что позволяет задавать произвольные ternary-маски, даже если это не следует разрешать. Было бы хорошо ограничить задание сопоставления типа optional, но это потребует внесений существенных изменений в код behavioral-model.

Поля ключей поиска в таблице с типом сопоставления range задаются минимальным значением, за которым без пробела следует -> и максимальное значение (без пробела). Для соответствия любому значению из диапазона можно указать 0->255 для 8-битового поля, 0->0xffffffff для 32-битового и т. п.

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

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

table_clear

Удаляет все записи в таблице сопоставления (прямого или опосредованного), указанной именем, оставляя лишь запись default.

table_clear <table name>

table_delete

Удаляет из указанной именем таблицы заданную идентификатором запись.

table_delete <table name> <entry handle>

table_dump

Выводит дамп указанной именем таблицы.

table_dump MyIngress.ipv4_lpm 
========== 
TABLE ENTRIES 
========== 
Dumping default entry 
Action entry: MyIngress.drop -  
==========

table_dump_entry, table_dump_entry_from_key

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

table_dump_entry <table name> <entry handle>
table_dump_entry_from_key <table name> <match fields> [priority]

table_dump_group, table_dump_member

Выводит информацию (дамп) о группе или элементе из указанной именем таблицы. Группа или элемент задаются идентификатором.

table_dump_group <table name> <group handle>
table_dump_member <table name> <member handle>

table_indirect_add

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

table_indirect_add <table name> <match fields> => <member handle> [priority]

table_indirect_add_member_to_group

Заменена командой act_prof_add_member_to_group.

table_indirect_add_with_group

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

table_indirect_add <table name> <match fields> => <group handle> [priority]

table_indirect_create_group

Заменена командой act_prof_create_group.

table_indirect_create_member

Заменена командой act_prof_create_member.

table_indirect_delete

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

table_indirect_delete <table name> <entry handle>

table_indirect_delete_group

Заменена командой act_prof_delete_group.

table_indirect_delete_member

Заменена командой act_prof_delete_member.

table_indirect_modify_member

Заменена командой act_prof_modify_member.

table_indirect_remove_member_from_group

Заменена командой act_prof_remove_member_from_group.

table_indirect_reset_default, table_indirect_set_default

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

table_indirect_reset_default <table name>
table_indirect_set_default <table name> <member handle>

table_indirect_set_default_with_group

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

table_indirect_set_default <table name> <group handle>

table_info

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

table_info <table name>

table_modify

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

table_modify <table name> <action name> <entry handle> [action parameters]

table_num_entries

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

table_num_entries <table name>

table_reset_default

RuntimeCmd: help table_reset_default Reset default entry for a match table: table_reset_default <table name>

Меняет действие, выполняемое в таблице при отсутствии соответствующей ключу поиска записи на исходное значение, заданное в программе P4. Если в программе такое действие не задано, используется «пустая операция» – no-op (иногда ее называют NoAction).

table_set_default

RuntimeCmd: help table_set_default Set default action for a match table: table_set_default <table name> <action name> <action parameters>

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

Задание параметров действия рассмотрено в описании команды table_add.

table_set_timeout

Устанавливает время ожидания (тайм-аут) для указанной идентификатором записи в заданной именем таблице. Время ожидания указывается в миллисекундах.

table_set_timeout <table_name> <entry handle> <timeout>

show_tables

Команда без параметров. Для каждой таблицы в загруженной программе P4 выводит имя, реализацию (часто None, но может выводиться профиль или селектор действия для таблиц, созданных с этими опциями) и список полей поиска в таблице (ключей) с указанием для каждого поля имени, типа соответствия (например, exact, lpm, ternary, range) и размера в битах. Поля с типом соответствия optional в коде P4 представляются в файле BMv2 JSON как ternary.

table_show_actions

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

RuntimeCmd: table_show_actions MyIngress.ipv4_lpm 
MyIngress.drop                 [] 
MyIngress.ipv4_forward         [dstAddr(48),    port(9)] 
NoAction

Команды управления синтаксическим анализатором

pvs_add, pvs_clear, pvs_get, pvs_remove

Эти команды служат для управления экземпляром набора значений синтаксического анализатора P4. Команда pvs_add добавляет запись в набор значений, pvs_remove удаляет запись, pvs_clear удаляет все записи, а pvs_get служит для просмотра имеющихся записей.

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

struct vsk_t { bit<16> f1; bit<7> f2; } value_set<vsk_t>(4) pvs; select (<X>) { pvs: accept; _: reject; }

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

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

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

Реализация наборов значений в bmv2 при сопоставлении поддерживает лишь точное совпадение (exact).

show_pvs

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

Команды для работы с групповыми пакетами

mc_dump, mc_mgrp_create, mc_mgrp_destroy, mc_node_associate, mc_node_create, mc_node_destroy, mc_node_dissociate

При завершении входной обработки в архитектуре v1model входной код P4 может устанавливать значения нескольких полей в standard_metadata, контролирующих отбрасывание пакетов, передаваемых индивидуально (unicast) в один выходной порт, или групповых пакетов, реплицированных в список (возможно пустой) выходных портов. Более подробное описание приведено в разделе «Псевдокод для завершения входной и выходной обработки» описания bmv2.

Буфер пакетов содержит машину репликации PRE1.

В v1model.p4 standard_metadata поле mcast_grp задает один из 65535 идентификаторов multicast-групп из диапазона [1, 65535]. Значение mcast_grp = 0 задает отсутствие групповой репликации пакетов. Коммутатор simple_switch может использовать большее число идентификаторов групп и указанный диапазон задан определением поля mcast_grp в standard_metadata (файл v1model.p4) с типом bit<16>.

Для реплицируемых пакетов PRE находит в таблице значение mcast_grp и по нему получает (возможно пустой) список пар (egress_port, egress_rid), для которых создаются копии пакета. Для каждой копии позднее выполняется выходная обработка с двумя полями standard_metadata, инициализированными значениями найденной в таблице пары.

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

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

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

  • каждая multicast-группа является множеством узлов;
  • каждый создаваемый узел групповой рассылки имеет одно значение egress_rid и набор egress_port, в котором не может быть дубликатов.

Предположим, что нужно настроить simple_switch так, чтобы пакеты для группы с mcast_grp = 1113 рассылались в приведенный ниже список пар (egress_port, egress_rid):

  • (egress_port=0, egress_rid=5);
  • (egress_port=7, egress_rid=10);
  • (egress_port=3, egress_rid=5).

Первая и последняя запись имеют общее значение egress_rid = 5, поэтому они могут находится в одном multicast-узле, который мы хотим создать в этом примере. Делается это командой mc_node_create, как показано ниже.

RuntimeCmd: help mc_node_create Create multicast node: mc_node_create <rid> <space-separated port list> [ | <space-separated lag list> ]

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

RuntimeCmd: mc_node_create 5 0 3 Creating node with rid 5 , port map 1001 and lag map node was created with handle 0

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

Создадим другой узел для копирования пакетов с egress_rid = 10, в нашем примере включающий лишь порт 7

RuntimeCmd: mc_node_create 10 7 Creating node with rid 10 , port map 10000000 and lag map node was created with handle 1

Вывод показывает, что этому узлу был назначен дескриптор 1.

Далее создадим группу с идентификатором 1113 командой mc_mgrp_create.

RuntimeCmd: help mc_mgrp_create Create multicast group: mc_mgrp_create <group id>

Справка говорит, что команда имеет единственный параметр – идентификатор группы.

RuntimeCmd: mc_mgrp_create 1113 Creating multicast group 1113

Здесь не используются специальные дескрипторы. Группы всегда именуются по заданным для них идентификаторам (1113 в этом примере).

После этого можно посмотреть созданные группы с помощью команды mc_dump.

RuntimeCmd: mc_dump ========== MC ENTRIES ********** mgrp(1113) ========== LAGS ==========

Вывод показывает наличие группы 1113, с которой не связано никаких узлов. В последующих примерах будут показаны группы с multicast-узлами. В текущей конфигурации simple_switch, передача пакета для репликации с mcast_grp = 1113 будет создавать 0 копий пакета, что равносильно его отбрасыванию (drop).

Для добавления multicast-узла в группу служит команда mc_node_associate.

RuntimeCmd: help mc_node_associate Associate node to multicast group: mc_node_associate <group handle> <node handle>

Команда принимает два параметра, один из которых задает идентификатор группы, другой – узла.

RuntimeCmd: mc_node_associate 1113 0 Associating node 0 to multicast group 1113

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

RuntimeCmd: mc_dump ========== MC ENTRIES ********** mgrp(1113)   -> (L1h=0, rid=5) -> (ports=[0, 3], lags=[]) ========== LAGS ==========

Видно, что группа 1113 имеет один узел. L1h является сокращением для записей L1 handle, которые можно увидеть в системном журнале simple_switch (это просто идентификатор узла). Показано значение rid = 5 (rid – сокращение для egress_rid), и список портов 0 и 3.

В текущей конфигурации simple_switch передача пакета для репликации с mcast_grp = 1113 будет создавать 2 копии пакета с парами:

  • (egress_port=0, egress_rid=5);
  • (egress_port=3, egress_rid=5).

Добавим в группу 1113 второй узел, упомянутый выше.

RuntimeCmd: mc_node_associate 1113 1 Associating node 1 to multicast group 1113

Группа после этого будет иметь вид

RuntimeCmd: mc_dump ========== MC ENTRIES ********** mgrp(1113)   -> (L1h=0, rid=5) -> (ports=[0, 3], lags=[])   -> (L1h=1, rid=10) -> (ports=[7], lags=[]) ========== LAGS ==========

В текущей конфигурации simple_switch передача пакета для репликации с mcast_grp = 1113 приведет к созданию трех копий с парами:

  • (egress_port=0, egress_rid=5);
  • (egress_port=3, egress_rid=5);
  • (egress_port=7, egress_rid=10).

Можно исключить узел из группы с помощью команды mc_node_dissociate.

RuntimeCmd: help mc_node_dissociate Dissociate node from multicast group: mc_node_associate <group handle> <node handle>

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

RuntimeCmd: mc_node_dissociate 1113 0 Dissociating node 0 from multicast group 1113

Группа после исключения узла будет иметь вид

RuntimeCmd: mc_dump ========== MC ENTRIES ********** mgrp(1113)   -> (L1h=1, rid=10) -> (ports=[7], lags=[]) ========== LAGS ==========

В этой конфигурации simple_switch передача пакета для репликации с mcast_grp = 1113 будет создавать 1 копию с (egress_port=7, egress_rid=10).

При исключении узла 1 из группы 1113, она вернется в исходное состояние и групповые пакеты будут отбрасываться.

RuntimeCmd: mc_node_dissociate 1113 1 Dissociating node 1 from multicast group 1113 RuntimeCmd: mc_dump ========== MC ENTRIES ********** mgrp(1113) ========== LAGS ==========

Можно удалить группу с помощью команды mc_mgrp_destroy.

RuntimeCmd: help mc_mgrp_destroy Destroy multicast group: mc_mgrp_destroy <group id>

Единственным параметром команды является идентификатор группы.

RuntimeCmd: mc_mgrp_destroy 1113 Destroying multicast group 1113

После этого команда просмотра групп будет давать пустой вывод.

RuntimeCmd: mc_dump ========== MC ENTRIES ========== LAGS ==========

Для описанных операций есть ряд ограничений.

  • Для привязки узла к группе нужно сначала создать то и другое. Порядок создания не имеет значения.
  • Коммутатор simple_switch позволяет связать узел лишь с одной группой. Для привязки узла к другой группе его нужно сначала отсоединить от текущей группы.
  • При удалении группы рекомендуется сначала удалить привязки узлов к ней.
  • В одном узле значение egress_port не может повторяться. Если нужно отправить в порт несколько копий, следует создать дополнительные узлы. Использование разных egress_rid для этих узлов позволяет коду P4 различать копии и по разному обрабатывать их.

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

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

mc_node_update

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

mc_node_update <node handle> <space-separated port list> [ | <space-separated lag list> ]

mc_set_lag_membership

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

mc_set_lag_membership <lag index> <space-separated port list>

Программы управления клонированием пакетов

mirroring_add, mirroring_add_mc, mirroring_delete, mirroring_get

[simple_switch_CLI]

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

  • программа с архитектурой P416 v1model вызывает внешнюю функцию clone или clone3 при входной или выходной обработке и на этом соответствующая обработка завершается;
  • программа P414 вызывает clone_ingress_pkt_to_egress при входной обработке, которая на этом завершается;
  • программа P414 вызывает clone_egress_pkt_to_egress при выходной обработке, которая на этом завершается.

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

В simple_switch поддерживается до 32768 независимых сессий клонирования с номерами от 0 до 32767, которые называют также сессиями отражения (mirroring session). При клонировании пакета указывается желаемая сессия для вызова из программы P4 операции клонирования.

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

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

RuntimeCmd: help mirroring_add Add mirroring session to unicast port: mirroring_add <mirror_id> <egress_port>

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

RuntimeCmd: mirroring_add 5 7 RuntimeCmd: mirroring_get 5 MirroringSessionConfig(mgid=None, port=7)

Можно задать в конфигурации сессии клонирование пакетов в multicast-группу.

RuntimeCmd: help mirroring_add_mc Add mirroring session to multicast group: mirroring_add_mc <mirror_id> <mgrp>

Команда mirroring_add_mc 5 22 изменит конфигурацию сессии 5 так, что последующие операции клонирования для этой сессии будут выполнять множественное клонирование для multicast-группы 22. Команда mc_mgrp_create и другие команды работы с группами описаны выше.

RuntimeCmd: mirroring_add_mc 5 22 RuntimeCmd: mirroring_get 5 MirroringSessionConfig(mgid=22, port=None)

Можно сбросить состояние настроенной сессии клонирования по ее идентификатору.

RuntimeCmd: help mirroring_delete Delete mirroring session: mirroring_delete <mirror_id>

Команда mirroring_delete 5 возвращает сессию 5 в исходное (ненастроенное) состояние.

RuntimeCmd: mirroring_delete 5

С помощью команды mirroring_get можно увидеть состояние указанной идентификатором сессии клонирования. Например, для сброшенной предыдущей командой сессии 5 вывод будет иметь вид

RuntimeCmd: mirroring_get 5 Invalid mirroring operation (SESSION_NOT_FOUND)

Команды для работы с измерителями

meter_array_set_rates

Задает скорости для всего массива измерителей, принимая в качестве параметров имя, а также набор значений скоростей и пиков.

meter_array_set_rates <name> <rate_1>:<burst_1> <rate_2>:<burst_2> ...

meter_get_rates

Возвращает параметры измерителя по имени и индексу.

meter_get_rates <name> <index>

meter_set_rates

Синтаксис команды в CLI приведен ниже.

RuntimeCmd: help meter_set_rates Configure rates for a meter: meter_set_rates <name> <index> <rate_1>:<burst_1> <rate_2>:<burst_2> ...

Поведение измерителя соответствует RFC 2697 и RFC 2698.

Пользователь задает скорость для измерителя в байтах за микросекунду и burst_size в байтах. Для измерителей, учитывающих пакеты, скорость задается числом пакетов за микросекунду, burst_size – числом пакетов.

Команды для работы со счетчиками

counter_read, counter_reset, counter_write

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

Команды для работы с регистрами

register_read, register_write

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

register_reset

Сбрасывает в 0 все ячейки массива регистров, указанного именем.

register_reset <name>

Команды управления очередями

set_queue_depth

[simple_switch_CLI]

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

set_queue_depth <nb_pkts> [<egress_port>]

set_queue_rate

[simple_switch_CLI]

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

set_queue_rate <rate_pps> [<egress_port>]

Прочие команды

help

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

RuntimeCmd: help help 
List available commands with "help" or detailed help with "help cmd". RuntimeCmd: help show_tables 
List tables defined in the P4 program: show_tables

switch_info

Выводит базовую информацию о коммутаторе.

switch_info 
device_id                : 0 
thrift_port              : 9090 
notifications_socket     : ipc:///tmp/bmv2-0-notifications.ipc 
elogger_socket           : None 
debugger_socket          : None

serialize_state

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

reset_state

Сбрасывает все состояния коммутатора (таблицы, регистры и т. п.), сохраняя конфигурацию P4. Команда не имеет параметров.

get_time_elapsed, get_time_since_epoch

[simple_switch_CLI]

Возвращает время, прошедшее с момента запуска коммутатора или с начала «эпохи» в микросекундах. Команда не имеет параметров.

set_crc16_parameters, set_crc32_parameters

Задает параметры вычисления контрольных сумм crc16 или crc32.

set_crc16_parameters <name> <polynomial> <initial remainder> <final xor value> <reflect data?> <reflect remainder?>
set_crc32_parameters <name> <polynomial> <initial remainder> <final xor value> <reflect data?> <reflect remainder?>

load_new_config_file

Загружает конфигурацию коммутатора из заданного параметром файла JSON. Для активизации этой конфигурации служит команда Ошибка: источник перекрёстной ссылки не найден.

swap_configs

Меняет конфигурацию, используя файл, загруженный ранее командой load_new_config_file.

write_config_to_file

Считывает конфигурацию из используемого в данный момент файла JSON и записывает ее в указанный пользователем файл на станции управления, где запущена программа simple_switch_CLI или runtime_CLI. Если файл задан без абсолютного пути, он будет сохранен в каталоге, из которого была запущена программа.

shell

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

shell <command>

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

nmalykh@protocols.ru

1Packet Replication “Engine” – «машина» репликации пакетов.

Рубрика: SDN, Сетевое программирование | Комментарии к записи simple_switch_CLI отключены

RFC 8802 The Quality for Service (Q4S) Protocol

image_print

Опубликована спецификация протокола Q4S

В документе описан  протокол прикладного уровня для сквозной передачи информации о соответствии QoS с использованием протоколов HTTP и SDP. Протокол Q4S предоставляет механизм согласования и отслеживания задержек, их вариаций, полосы пропускания и потери пакетов, а также для оповещения в случае нарушения одного из согласованных условий.

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

Документ доступен по ссылке.

Рубрика: RFC, Новости | Комментарии к записи RFC 8802 The Quality for Service (Q4S) Protocol отключены

Ограниченные домены и протоколы Internet

image_print

RFC 8799

Limited Domains and Internet Protocols

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

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

Текст документа доступен по ссылке, перевод доступен здесь.

Рубрика: RFC, Новости | Комментарии к записи Ограниченные домены и протоколы Internet отключены