http://blog.csdn.net/alex0/article/details/8871711
版本:OVS 1.7.1
简称:dp->datapath, of->OpenFlow, sw->switch
背景:
- 报文匹配的流程可以说是对一个switch效率影响最大的地方,现在已经有很多厂家(包括一些研究院)说可以做到比OVS效率高十倍的流表匹配。
- 当然这是有可能的,毕竟都是纯软件,非常容易创新。而ovs也没有做多级流表,跟of标准上不一定比得过别人。我们接下来就分析一下OVS的匹配流程。
- 整体的匹配逻辑很简单,都是OpenFlow规定好的。
- 报文通过dp时先查找精确匹配表(facet),如果找不到,那么进行upcall,上送到用户态。
- 在用户态会查找模糊匹配表(table),这个地方可以说是较没有效率的地方。下面我们看一看具体的代码。
调用流程(内核):
调用流程(用户态):ovs_vport_receive->ovs_dp_process_received_packet->ovs_flow_tbl_lookup->ovs_dp_upcall->queue_userspace_packet
handle_miss_upcalls->handle_flow_miss->rule_dpif_lookup->rule_dpif_lookup__->classifier_lookup->find_match
- 在handle_miss_upcalls里解析了报文,生成了报文的精确匹配项,如果我们把它遮盖掉(mask)一部分,那么它就是一个模糊匹配的flow了。实际上ovs也就是这么做的。
- 注意到每个flow table拥有一个cls,一个cls拥有多个cls_table,cls_table中拥有mask完全一致的flow。
- 而在find_match中,ovs将精确匹配项对应cls_table的mask位置0,然后通过hash查找是否有匹配的flow。
关键代码:
- /* 在'cls'中取出优先级最高的匹配'flow'.
- * 如果'cls'中无匹配'flow'则返回空指针. 如果多条rule
- * 匹配'flow'且优先级相同, 随便拿一条. */
- struct cls_rule *
- classifier_lookup(const struct classifier *cls, const struct flow *flow)
- {
- struct cls_table *table;
- struct cls_rule *best;
- best = NULL;
- HMAP_FOR_EACH (table, hmap_node, &cls->tables) {
- struct cls_rule *rule = find_match(table, flow);
- if (rule && (!best || rule->priority > best->priority)) {
- best = rule;
- }
- }
- return best;
- }
- static struct cls_rule *
- find_match(const struct cls_table *table, const struct flow *flow)
- {
- struct cls_rule *rule;
- //如果cls_table是获取所有流的(掩码全0),那么直接尝试匹配
- if (table->is_catchall) {
- HMAP_FOR_EACH (rule, hmap_node, &table->rules) {
- return rule;
- }
- } else {
- struct flow f;
- f = *flow;
- //将table掩码对应的flow位置0(相当于被mask了)
- flow_zero_wildcards(&f, &table->wc);
- //取出hash一致的flow进行迭代
- HMAP_FOR_EACH_WITH_HASH (rule, hmap_node, flow_hash(&f, 0),
- &table->rules) {
- //尝试匹配hash对得上的flow,效率不高(里面就是memcmp)
- if (flow_equal(&f, &rule->flow)) {
- return rule;
- }
- }
- }
- return NULL;
- }
报文匹配流程图: