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
netif_receive_skb
netif_receive_skb(struct sk_buff *skb)
從網絡中接收數據,它是主要的接收數據處理函數,老是成功,這個buffer在擁塞處理或協議層的時候可能被丟棄。這個函數只能從軟中斷環境(softirq context)中調用,而且中斷容許。返回值NET_RX_SUCCESS
表示沒有擁塞,NET_RX_DROP
包丟棄。netdev_frame_hook()
其調用netdev_port_receive()
netdev_port_receive()
函數netdev_port_receive()
首先檢查是否skb被共享,如果則獲得一個packet的拷貝。 其調用ovs_vport_receive()
。檢查包的校驗和,而後交付給咱們的vport通用層來處理。ovs_vport_receive()
將收到的packet傳給datapath處理。 其調用ovs_dp_process_received_packet()
。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 }