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

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