我们知道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。