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 }
相关文章
相关标签/搜索