OVS源码--datapath的分片与重组流程(九)

非VXLAN的收发包调用栈

netdev_frame_hook()
     netdev_port_receive()
          ovs_vport_receive()
               ovs_dp_process_packet()
                    (在查表失败后,对于带gso标记的大包,会分片进行upcall)
                    ovs_dp_upcall()                                                        
                    ovs_execute_actions()
                         output: do_output()
                              (通常情况下OVS_CB(skb)->mru为0,直接发送)
                              ovs_vport_send()                                             
                              (OVS_CB(skb)->mru不为0(即在output之前还经历了ct,且ct流程进行了分片重组。)且小于出端口的mtu的情况下,进入分片流程)
                              ovs_fragment()                                               
                                   (执行分片)
                                   ip_do_fragment(net, skb->sk, skb, ovs_vport_output);    
                                        (发包,这里代码写的比较绕)
                                        ovs_vport_output()                                 
                                             ovs_vport_send()
                         ct    : ovs_ct_execute()
                              (在进行conntrack的commit或lookup之前,会对分片进行重组,并会设置OVS_CB(skb)->mru的值不为0,为分片中最大的分片的尺寸)
                              handle_fragments()                                           
                              ovs_ct_commit() / ovs_ct_lookup()
 
          ovs_vport_send()
               vport->ops->send(skb) == dev_queue_xmit(skb) == rpl_dev_queue_xmit(skb)
                    (检查包的gso标记,需要分片的情况下进行分片,然后再递归调用dev_queue_xmit()发送分片)
                    skb_gso_segment              

总结:

非VXLAN组网,逻辑基本如下:
     1. 收到多个分片
          1.1. datapath查表失败
               分片各自上送至用户态,走upcall流程
          1.2. datapath查表成功,或从upcall流程下来
               开始执行actions
                    while(1)
                         ct               会对分片进行重组,重组后的大包的OVS_CB(skb)->mru会被设置成一个非0ovs_vport_send()
                         output           如果没有经过ct,则分片直接被转发,如果经过了ct,则大包还要进行分片操作
                              ovs_fragment() -> ip_do_fragment() -> ovs_vport_output() -> ovs_vport_send()
               
     2. 收到带gso标记的大包
          2.1. datapath查表失败
               先进行分片,然后把分片各自upcall
          2.2. datapath查表成功
               开始执行actions
                    while(1)
                         ct               直接ct,没有额外操作
                         output           由于OVS_CB(skb)->mru为0,所以直接进入ovs_vport_send()
                              ovs_vport_send()
                                   在这里检查包的gso标记,然后进行分片,再对各个分片递归调用dev_queue_xmit()发送分片
                                   vport->ops->send == dev_queue_xmit() == rpl_dev_queue_xmit()  

VXLAN组网,逻辑基本如下:
     1:首先是Kernel收到udp报文,走以下流程解封装
          udp_rcv -> __udp4_lib_rcv -> udp_queue_rcv_skb -> encap_rcv -> vxlan_rcv
     2:最终调用 netdev_port_receive -> ovs_vport_receive -> ovs_dp_process_packet
    
     也就是说,VXLAN收包终结之后,不存在分片与重组,而在终结之前的ip报文是否需要重组,则是由kernel负责,不是ovs的责任
     接下来的处理流程都与非VXLAN组网一致了,直至发包
     在VXLAN组网中,发包最终调到 ovs_vport_send() 函数时,vport->ops->send 指针实际调用的函数是 vxlan_xmit

     vxlan_xmit -> rpl_vxlan_xmit -> vxlan_xmit_one -> udp_tunnel_xmit_skb -> iptunnel_xmit == rpl_iptunnel_xmit -> ip_local_out == rpl_ip_local_out
     
     在 rpl_ip_local_out 中,类似于 rpl_dev_queue_xmit(),会检查gso标记,如果有gso标记,会将这个ip报文分片然后各片各自发送

原文链接:https://www.cnblogs.com/neooelric/p/6905185.html

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章