OpenvSwitch 解讀

OpenvSwitch 解讀

報文匹配流程參考下圖segmentfault

 

 

調用流程(內核):網絡

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

this

packet接收處理

  繼續上面所說的,當接收包將會發生以下代碼流:spa

    1. netif_receive_skb 
      netif_receive_skb(struct sk_buff *skb)從網絡中接收數據,它是主要的接收數據處理函數,老是成功,這個buffer在擁塞處理或協議層的時候可能被丟棄。這個函數只能從軟中斷環境(softirq context)中調用,而且中斷容許。返回值NET_RX_SUCCESS表示沒有擁塞,NET_RX_DROP包丟棄。
    2. netdev_frame_hook() 
      其調用netdev_port_receive()
    3. netdev_port_receive() 
      函數netdev_port_receive()首先檢查是否skb被共享,如果則獲得一個packet的拷貝。 其調用ovs_vport_receive()。檢查包的校驗和,而後交付給咱們的vport通用層來處理。
    4. ovs_vport_receive() 
      將收到的packet傳給datapath處理。 其調用ovs_dp_process_received_packet()
    5. ovs_dp_process_received_packet() 
      在 ovs_dp_process_received_packet()(datapath/datapath.c)中進行復雜的包處理過程,進行流查表,查表後執行對應的行爲。當查找失敗時候,使用ovs_dp_upcall()發送 upcall到用戶空間(ovs-vswitchd)。此後處理過程交給 ovsd 處理。其將產生如下代碼流:ovs_dp_process_received_packet() => ovs_dp_upcall() => queue_userspace_packet()
      本步驟具體內容能夠參考個人另一篇博客:ovs中流表在內核空間與用戶空間的匹配過程
 1 /* Must be called with rcu_read_lock. */
 2 void ovs_dp_process_packet(struct sk_buff *skb, struct sw_flow_key *key)  3 {  4     const struct vport *p = OVS_CB(skb)->input_vport;  5     struct datapath *dp = p->dp;  6     struct sw_flow *flow;  7     struct sw_flow_actions *sf_acts;  8     struct dp_stats_percpu *stats;  9     u64 *stats_counter; 10  u32 n_mask_hit; 11 
12     stats = this_cpu_ptr(dp->stats_percpu); 13 
14     /* Look up flow. */
15     flow = ovs_flow_tbl_lookup_stats(&dp->table, key, skb_get_hash(skb), 16                      &n_mask_hit); 17     if (unlikely(!flow)) { 18  struct dp_upcall_info upcall; 19  int error; 20 
21         memset(&upcall, 0, sizeof(upcall)); 22         upcall.cmd = OVS_PACKET_CMD_MISS; 23         upcall.portid = ovs_vport_find_upcall_portid(p, skb); 24         upcall.mru = OVS_CB(skb)->mru; 25         error = ovs_dp_upcall(dp, skb, key, &upcall, 0); 26         if (unlikely(error)) 27  kfree_skb(skb); 28         else
29  consume_skb(skb); 30         stats_counter = &stats->n_missed; 31  goto out; 32  } 33 
34     ovs_flow_stats_update(flow, key->tp.flags, skb); 35     sf_acts = rcu_dereference(flow->sf_acts); 36  ovs_execute_actions(dp, skb, sf_acts, key); 37 
38     stats_counter = &stats->n_hit; 39 
40 out: 41     /* Update datapath statistics. */
42     u64_stats_update_begin(&stats->syncp); 43     (*stats_counter)++; 44     stats->n_mask_hit += n_mask_hit; 45     u64_stats_update_end(&stats->syncp); 46 }
相關文章
相關標籤/搜索