OpenvSwitch 解读

OpenvSwitch 解读

报文匹配流程参考下图

 

 

调用流程(内核):

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

packet接收处理

  继续上面所说的,当接收包将会发生如下代码流:

    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 }

 

posted @ 2018-12-29 15:50  salami_china  阅读(665)  评论(0编辑  收藏  举报