我们知道OVS在内核态收到一个包后,如果在内核中没有对应的规则,这个包会被送到用户态查询,看有没有相应的规则。
如果没有的话,默认的action就是normal,也就是正常转发。如果我们添加下面的flow,在OVS中是如何存储的呢?
# ovs-ofctl add-flow $br 'dl_dst=24:8a:07:88:27:9a table=0,priority=10,action=normal'
我们可以通过下面的gdb函数来查看相应的规则在内存中是如何存储的。
set $ofproto = all_ofprotos.one
define print-ofproto
echo struct ofproto\t
# p $ofproto
# p *(struct ofproto*)$ofproto
set $tables = (*(struct ofproto*)$ofproto).tables
# echo struct oftable\t
# p $tables
# p/x *(struct oftable*) $tables
set $cls = (*(struct ofproto*)$ofproto).tables->cls
# echo struct classifier\t
# p/s $cls
# p/x *(struct classifier*) $cls
set $subtables = (*(struct ofproto*)$ofproto).tables->cls.subtables.impl.p
# echo struct subtable\t
# p $subtables
# p/x *(struct pvector_impl*) $subtables
set $size = (*(struct pvector_impl*) $subtables).size
p/x $size
set $vector = (*(struct pvector_impl*) $subtables).vector
p/x $vector
set $i = 0
while $i != $size
set $i = $i + 1
p/x *(struct pvector_entry*) $vector
set $cls_subtable = (*(struct pvector_entry*) $vector).ptr
# echo struct cls_subtable\t
# p/x $cls_subtable
# p/x *(struct cls_subtable*) $cls_subtable
set $rules = (*(struct cls_subtable*)$cls_subtable).rules.impl.p
p/x $rules
x (*(struct cls_subtable*)$cls_subtable).rules_list.prev
set $rules_list = $_
echo cls_rule\t
p/x $rules_list
p/x *(struct cls_rule*) $rules_list
set $o = &((struct rule*)0)->cr
# 8 bytes
set $rule_dpif = $rules_list - 2
echo rule_dpif\t
p/x $rule_dpif
p/x *(struct rule_dpif*) $rule_dpif
set $rule_actions = (*(struct rule_dpif*) $rule_dpif)->up.actions
echo rule_actions\t
p/x $rule_actions
p/x *(struct rule_actions*)$rule_actions
set $ofpacts = (*(struct rule_actions*)$rule_actions)->ofpacts
echo ofpacts\t
p/x $ofpacts
p/x *(struct ofpact_output*)$ofpacts
set $miniflow = (*(struct cls_rule*)$rules_list)->match.flow
x/50 $miniflow
set $cls_match = (*(struct cls_rule*)$rules_list)->cls_match.p
echo cls_match\t
p/x $i
p/x $cls_match
p/x *(struct cls_match*) $cls_match
# echo cmap_impl\n
# p/x *(struct cmap_impl*) $rules
set $vector = $vector + 1
# p/x $vector
end
# p/x (*(struct ofproto_dpif *)$dpif)->netflow
end
gdb会dump出如下信息:
rule_actions $159 = 0x1f4da80
$160 = {
has_meter = 0x0,
has_learn_with_delete = 0x0,
has_groups = 0x0,
ofpacts_len = 0x10,
ofpacts = 0x1f4da88
}
ofpacts $161 = 0x1f4da88
$162 = {
ofpact = {
type = 0x0,
raw = 0xff,
len = 0x10
},
port = 0xfffa,
max_len = 0x0
}
0x1f94c60: 0x00000000 0x04400000 0x00000000 0x00000000
0x1f94c70: 0x00000000 0x00000000 0x88078a24 0x00009a27
0x1f94c80: 0x00000000 0x04400000 0x00000000 0x00000000
0x1f94c90: 0x00000000 0xffffffff 0xffffffff 0x0000ffff
0x1f94ca0: 0x00000050 0x00000000 0x00000151 0x00000000
0x1f94cb0: 0x01f4dce0 0x00000000 0x00000030 0x00000000
0x1f94cc0: 0x01f94c30 0x00000000 0x00000000 0x00000000
0x1f94cd0: 0x01f94ca0 0x00000000 0x00000030 0x00000000
0x1f94ce0: 0x01f94c50 0x00000000 0x00000111 0x00000000
0x1f94cf0: 0x01f8bfd0 0x00000000 0xa9078c78 0x00007f3e
0x1f94d00: 0x00000020 0x00000000 0x00000030 0x00000000
0x1f94d10: 0x01f94c60 0x00000000 0x00000000 0x00000000
action对应的port是0xfffa,也就是normal的意思。如果action是drop,ofpacts_len就是0,表示没有action。
#define OFPP_NORMAL OFP_PORT_C(0xfffa) /* Process with normal L2/L3. */
flow在存储的时候并没有存完整的flow,而是存了一个miniflow,ptype /o只有在最新的gdb中才有,目前用的是gdb 8.0.50,gdb竟然一直没有直接查看结构体大小的功能。
(gdb) ptype /o struct miniflow
/* offset | size */ type = struct miniflow {
/* 0 | 16 */ struct flowmap {
/* 0 | 16 */ map_t bits[2];
/* total size (bytes): 16 */
} map;
/* total size (bytes): 16 */
}
这是一个16字节的bitmap,每位对应flow中的8个字节,是1的话,miniflow后面才存对应的内容。我们可以在miniflow中查找到对应的mac地址24:8a:07:88:27:9a。