table 中静态 LPM 条目的 P4 语法
P4 syntax for a static LPM entry in a table
这是一个关于 P4 语言的问题,该语言用于在网络中对数据平面进行编程。
假设我有以下简单的 header:
header ipv4_header_t {
bit<8> ttl;
bit<32> dst_addr;
}
struct headers_t {
ipv4_header_t ipv4_header;
}
想象一下我有一个简单的 table 可以对目标地址进行最长前缀匹配 (LPM) 查找。
table ipv4_fib {
key = {
headers.ipv4_header.dst_addr: lpm;
}
actions = {
act_miss;
act_hit;
}
const default_action = act_miss();
}
向 table 添加一些静态 LPM 条目的 P4 语法是什么?
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
}
以下答案由 Vladimir Gurevich 提供,他在 P4 slack 频道的对话中回答了这个问题(参见讨论 https://p4-lang.slack.com/archives/C8ZR5EN3F/p1587830767153100)
要将静态条目添加到最长前缀匹配 (lpm) table,您必须使用与三元条目相同的语法,使用 &&& 语法提供值和掩码:
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 (1) 和紧接着一系列连续的零 (0) 组成。
在某些(但不是所有)平台上,最长前缀匹配实际上是作为三元匹配实现的 "under the hood"。
注意 1:当您在 table 中提供静态条目时,条目必须是常量,因此软件不再可能向 [=35] 添加或从中删除动态条目=].由于 lpm tables 最常用于动态转发 tables,因此很少看到带有静态条目的 lpm table。
注意 2:我听说某些平台使用 lpm table 中条目的顺序作为匹配条目的优先顺序。因此,重要的是将更具体的整体(例如 10.1.0.0/16)放在不太具体的聚合条目(例如 10.0.0.0/8)之前。从技术上讲,这可以被认为是 "bug",因为在 lpm table 中,必须始终首选最长的前缀匹配。这种行为是由于在某些平台上 lpm table 实际上是作为三元 table 在后台实现的。我还被告知开源 v1model 确实匹配最长前缀(最具体)键,无论 table 中条目的顺序如何(即它没有 "bug")。
注意 3:如果您尝试添加带有全零掩码的默认条目(如下示例),您将收到错误消息(也在下面给出)。请改用 default_action。但是,table 中的默认条目和默认操作之间存在细微差别:在前一种情况下,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
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
这是一个关于 P4 语言的问题,该语言用于在网络中对数据平面进行编程。
假设我有以下简单的 header:
header ipv4_header_t {
bit<8> ttl;
bit<32> dst_addr;
}
struct headers_t {
ipv4_header_t ipv4_header;
}
想象一下我有一个简单的 table 可以对目标地址进行最长前缀匹配 (LPM) 查找。
table ipv4_fib {
key = {
headers.ipv4_header.dst_addr: lpm;
}
actions = {
act_miss;
act_hit;
}
const default_action = act_miss();
}
向 table 添加一些静态 LPM 条目的 P4 语法是什么?
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
}
以下答案由 Vladimir Gurevich 提供,他在 P4 slack 频道的对话中回答了这个问题(参见讨论 https://p4-lang.slack.com/archives/C8ZR5EN3F/p1587830767153100)
要将静态条目添加到最长前缀匹配 (lpm) table,您必须使用与三元条目相同的语法,使用 &&& 语法提供值和掩码:
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 (1) 和紧接着一系列连续的零 (0) 组成。
在某些(但不是所有)平台上,最长前缀匹配实际上是作为三元匹配实现的 "under the hood"。
注意 1:当您在 table 中提供静态条目时,条目必须是常量,因此软件不再可能向 [=35] 添加或从中删除动态条目=].由于 lpm tables 最常用于动态转发 tables,因此很少看到带有静态条目的 lpm table。
注意 2:我听说某些平台使用 lpm table 中条目的顺序作为匹配条目的优先顺序。因此,重要的是将更具体的整体(例如 10.1.0.0/16)放在不太具体的聚合条目(例如 10.0.0.0/8)之前。从技术上讲,这可以被认为是 "bug",因为在 lpm table 中,必须始终首选最长的前缀匹配。这种行为是由于在某些平台上 lpm table 实际上是作为三元 table 在后台实现的。我还被告知开源 v1model 确实匹配最长前缀(最具体)键,无论 table 中条目的顺序如何(即它没有 "bug")。
注意 3:如果您尝试添加带有全零掩码的默认条目(如下示例),您将收到错误消息(也在下面给出)。请改用 default_action。但是,table 中的默认条目和默认操作之间存在细微差别:在前一种情况下,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
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^