Синтаксис P4 для записи stati c LPM в таблице - PullRequest
0 голосов
/ 25 апреля 2020

Это вопрос о языке P4, языке для программирования плоскости данных в сетях.

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

header ipv4_header_t {
    bit<8> ttl;
    bit<32> dst_addr;
}

struct headers_t {
    ipv4_header_t ipv4_header;
}

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

table ipv4_fib {
    key = {
        headers.ipv4_header.dst_addr: lpm;
    }
    actions = {
        act_miss;
        act_hit;
    }
    const default_action = act_miss();
}

Каков синтаксис P4 для добавления некоторых записей stati c LPM в таблицу?

    entries = {
        ????: act_hit();    // Want entry for 0.0.0.0/0
        ????: act_hit();    // Want entry for 10.0.0.0/8
        ????: act_hit();    // Want entry for 10.1.2.3/32
    }

1 Ответ

0 голосов
/ 25 апреля 2020

Следующий ответ любезно предоставлен Владимиром Гуревичем, который ответил на вопрос в беседе на слабом канале P4 (см. Обсуждение https://p4-lang.slack.com/archives/C8ZR5EN3F/p1587830767153100)

Чтобы добавить stati c записей в таблица с самым длинным соответствием префикса (lpm), вы должны использовать тот же синтаксис, что и троичная запись, используя синтаксис &&& для предоставления значения и маски:

table ipv4_fib {
    key = {
        headers.ipv4_header.dst_addr: lpm;
    }
    actions = {
        act_miss;
        act_hit;
    }
    const default_action = act_miss();
    const entries = {
        32w0x0a010203 &&& 32w0xffffffff: act_hit(1);   // 10.1.2.3/32 -> 1
        32w0x0a010200 &&& 32w0xffffff00: act_hit(2);   // 10.1.2.0/24 -> 2
        32w0x0a010000 &&& 32w0xffff0000: act_hit(3);   // 10.1.0.0/16 -> 3
        32w0x0a000000 &&& 32w0xff000000: act_hit(4);   // 10.0.0.0/8 -> 4
    }
}

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

На некоторых (но не на всех) платформах сопоставление с самым длинным префиксом фактически реализован как троичное совпадение «под капотом».

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

Примечание 2. Мне сказали, что некоторые платформы используют порядок записей в таблице lpm как порядок приоритета для соответствия записей. Таким образом, важно поместить более конкретные c записи (например, 10.1.0.0/16) перед менее конкретными c совокупными записями (например, 10.0.0.0/8). Технически это можно считать «ошибкой», потому что в таблице lpm всегда должно быть предпочтение наибольшего совпадения префикса. Такое поведение связано с тем, что на некоторых платформах таблица lpm фактически реализована под капотом как троичная таблица. Мне также сказали, что v1model с открытым исходным кодом действительно соответствует ключу с самым длинным префиксом (наиболее конкретным c), независимо от порядка записей в таблице (т. Е. У него нет «ошибки»).

Примечание 3: если вы попытаетесь добавить запись по умолчанию с маской со всеми нулями (пример ниже), вы получите ошибку (также приведенную ниже). Вместо этого используйте default_action. Однако есть небольшая разница между записью по умолчанию в таблице и действием по умолчанию: в первом случае table.apply () будет указывать на попадание результата, а во втором - на пропуск. Альтернативный подход заключается в использовании ключа _. Тот факт, что запись по умолчанию вызывает ошибку, может считаться ошибкой, и если да, то эта ошибка может быть исправлена ​​в более поздней версии компилятора P4:

    const entries = {
        32w0x0a010203 &&& 32w0xffffffff: act_hit(1);   // 10.1.2.3/32 -> 1
        32w0x0a000000 &&& 32w0xff000000: act_hit(2);   // 10.0.0.0/8 -> 2
        32w0x00000000 &&& 32w0x00000000: act_hit(3);   // 0.0.0.0/0 -> 3
    }
}

Ошибка:

$ p4c complex.p4
./complex.p4i(838): [--Werror=invalid] error: &&&: Invalid mask for LPM key
            32w0x00000000 &&& 32w0x00000000: act_hit(3); // 0.0.0.0/0 -> 3
            ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
...