ovs upcall处理:缓存流表生成

Posted fsz304203330

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了ovs upcall处理:缓存流表生成相关的知识,希望对你有一定的参考价值。

参考资料:https://www.sdnlab.com/16171.html    //upcall流程解析

                  https://www.sdnlab.com/15713.html     //ovs内核态查表详细流程  

     https://zhuanlan.zhihu.com/p/66321252 //OpenVSwitch实现浅谈(二)  有对megaflow的讲解

     https://www.jqhtml.com/43252.html?wpfpaction=add&postid=43252  //dpcls,这一级的包分类器其实就是[这篇论文]描述的TSS分类器介绍,这里讲了最长匹配策略,和匹配存储过程,非常重要

 

技术图片

 

 

miss和flow作用: OVS将具有相同key的upcall归为一类,管理映射到同一个miss中。这样就完成了相似packet的分类工作,便于后期统一匹配处理,提高效率。

对应关系:一个报文生成一个upcall,一个upcall包含一个用于域匹配生成流表的flow结构;

                  具有相同的key值得upcall归类为一个miss,后续匹配生成缓存流表的时候统一处理; 

 

1.相关结构体:

    struct flow *flow = &flows[n_upcalls]; //存储用于由key翻译过来的flow信息;将传递上的原始key信息,翻译成后续可以和域匹配的flow结构,就是一次映射                  

                     //flow就是前面讲解到的用户层用于表示匹配域的结构体,就是提取出的报文需要用于和用户态的Openflow协议匹配的数据结构体;

                     //upcall->flow = flow; 在upcall_receive中以指指针形式传给了upcall       flow和flow归属的upcall这样联系在一起;

    struct rule {        //用户态流表规则存储形式,配置的normal流表等最后都会以rule的形式存储

2. upacll用户态 接收upcall数据后处理流程

  recv_upcalls  //总体口

    dpif_recv                            //从netlik获取了原始的upcall数据,并且已经解析除了key值,packet和userdata 存储在了dpupcall中 

    ----------阶段一-------------  

    upcall->fitness = odp_flow_key_to_flow(dupcall->key, dupcall->key_len,flow, NULL); //将key值内容转换为flow的函数,结果存储在flow里,只通过key生成flow没有含有skb信息,通过指针传递给了upcall,返回值

                                                                                                                                                     //upcall->fitness 代表的是key的数据翻译成flow的匹配度

                                          //将key中一定长度的netlink attribute解析到flow结构体中,这里并没有拿packet作为参数,

                                         //因为现在理解的OVS_KEY_ATTR_*属性都不需要包数据。现在我们总是可以通过底层协议相关的属性来推断出其他的attributes,比如说,如果在    

                                         //OVS_KEY_ATTR_IPV4或 OVS_KEY_ATTR_IPV6中的协议值是IPPROTO_TCP,那么就会出现属性OVS_KEY_ATTR_TCP。        

    error = upcall_receive(upcall, udpif->backer, &dupcall->packet,dupcall->type, dupcall->userdata, flow, mru,&dupcall->ufid, PMD_ID_NULL);//这里upcall->ukey 初始化为NULL

    pkt_metadata_from_flow(&dupcall->packet.md, flow); //将flow里面的一些内容赋给报文的metadata部分, metadata     upcall->packet 也是通过指针形式传给upcall,所以这个函数也是完善upcall

 

    flow_extract(&dupcall->packet, flow); //根据报文和metadata的数据,生成一条新的miniflow,然后拷贝miniflow的内容到flow,不是特别懂!!!这样新的flow比之前多了一些skb的信息。

       miniflow_extract(packet, &m.mf);//该函数用于将报文内容提取出来构建miniflow结构。

       miniflow_expand(&m.mf, flow);// 函数用于将miniflow还原成flow    链接:https://segmentfault.com/a/1190000020454413    这样一来一去flow里就含有了skb相关信息

       //到这里upcall已经准备好了

 

    ----------阶段二-----------------   

    error = process_upcall(udpif, upcall,&upcall->odp_actions, &upcall->wc);       

        case SLOW_PATH_UPCALL:   //待确认是否走这个分支,但是后续的ukey赋值只有这里进去
           upcall_xlate(udpif, upcall, odp_actions, wc);                                                                                     //参考:https://blog.csdn.net/chen739481102/article/details/85988215   

              xlate_in_init(&xin, upcall->ofproto,ofproto_dpif_get_tables_version(upcall->ofproto),upcall->flow, upcall->ofp_in_port, NULL,stats.tcp_flags, upcall->packet, wc, odp_actions);

                                 //生成xin  其中 xin->flow = *flow;      *flow 是第四个参数upcall->flow   这样upcall的flow就和xin->flow指向了

              xerr = xlate_actions(&xin, &upcall->xout); //这个函数里面,会在flow table里面查找rule      //参考:https://www.dazhuanlan.com/2020/01/06/5e12aa7c48b37/   详细匹配过程 

                                                             

                    ctx.rule = rule_dpif_lookup_from_table(ctx.xbridge->ofproto, ctx.xin->tables_version, flow, ctx.wc,ctx.xin->resubmit_stats, &ctx.table_id,flow->in_port.ofp_port, true, true, ctx.xin->xcache);  

                                            //这个是实际从Look up ‘flow‘ in ‘ofproto‘‘s classifier version ‘version‘查找 规则的函数。 配置不用用户态流表,同样的upall在这里应该返回不同      

                                                                                                                                             //normal流表和三层流表同样的upcall 下发的流表不同,需要在这里跟进打印,看是否寻找到的rule不同!!!

                     do_xlate_actions(ofpacts, ofpacts_len, &ctx, true, false);//在这个函数里面,根据action的不同,修改flow的内容,这里把修改后的flow内容打印出来,特别是ufid  和l3规则

                                                                                                                                                                        //找到的流表规则rule通过 &ctx 传入

                                     upcall->ukey = ukey_create_from_upcall(upcall, wc);//在这里对ukey进行了赋值

                          ukey_create__                      //ukey的实际创建函数  ,在这里可以打印ufid等信息,这里是处理完后的数据了!!!!!

    ----------阶段三-----------------

     handle_upcalls(handler->udpif, upcalls, n_upcalls);

      

以上是关于ovs upcall处理:缓存流表生成的主要内容,如果未能解决你的问题,请参考以下文章

Open vSwitch(OVS)介绍编译安装与原理

Openvswitch原理与代码分析:用户态流表flow table的操作

ovs源码阅读--流表查询原理

OpenvSwitch 流表转换

openVswitch(OVS)源代码分析之工作流程(数据包处理)

OVS中的key解析