赵占旭的博客

OpenvSwitch ovs-dpdk 报文处理流程

启动


vswitchd/ovs-vswitchd.c启动main-->netdev_run-->netdev_initialize-->netdev_dpdk_register-->netdev_register_provider注册dpdk_vhost_user_class

添加dpdk端口的时候,会触发创建pmd线程的操作。
dpif_netdev_port_add-->do_add_port-->dp_netdev_set_pmds_on_numa-->pmd_thread_main

如果已经添加了dpdk端口,启动的时候也会触发创建pmd的线程的操作。
dpif_netdev_pmd_set-->dp_netdev_reset_pmd_threads-->dp_netdev_set_pmds_on_numa-->pmd_thread_main

dp_netdev_process_rxq_port接口负责接收报文,然后调用接口dp_netdev_input-->dp_netdev_input__负责查表然后调用packet_batch_execute-->dp_netdev_execute_actions执行actions操作。

poll mode线程


pmd_thread_main

  • pmd_thread_setaffinity_cpu设置线程绑定的lcore。
  • for无限循环
  • for循环各个端口,执行dp_netdev_process_rxq_port处理端口。
  • 循环中间会根据变动重新加载端口和队列信息。

dp_netdev_process_rxq_port

  • 调用netdev_rxq_recv接收报文,前后都有计时。
  • 调用dp_netdev_input将报文传输给flow,并且发送报文,前后都有计时。

netdev_rxq_recv=>netdev_dpdk_vhost_rxq_recv

  • 调用dpdk接口rte_vhost_dequeue_burst接收报文。
  • 调用netdev_dpdk_vhost_update_rx_counters更新统计信息。

dp_netdev_input=>dp_netdev_input__

  • emc_processing主要是将收到的几个报文解析key值,并且从cache中查找流表,匹配的报文放入流表;返回不匹配的报文个数。
  • 如果存在不匹配的报文,调用fast_path_processing则继续查找全部表项,找到则将流表放入cache,不匹配则上报到controller。
  • 调用packet_batch_execute根据流表来操作报文。

emc_processing

  • 调用miniflow_extract将报文解析到key值。
  • 调用emc_lookup,从hash表中查找,并且进行key值比较。
  • 如果匹配,调用dp_netdev_queue_batches将报文添加在flow->batches中。
  • 不匹配将不匹配的报文当前排。
  • 调用dp_netdev_count_packet统计匹配的报文数。

fast_path_processing

  • dpcls_lookup通过classifier查找子流表,如果所有的报文都找到了匹配的子流表,将流表插入缓存中,并且将报文加入flow->batches
  • 如果不匹配,则上报到controller,没细看。
  • 统计匹配、不匹配和丢失。

packet_batch_per_flow_execute

  • 调用dp_netdev_flow_get_actions获取flow对应的actions。
  • dp_netdev_execute_actions执行对应的actions。

actions操作


dp_netdev_execute_actions=>odp_execute_actions

  • 如果是一些基本操作的话,调用接口dp_execute_cb

dp_execute_cb

  • 如果是OVS_ACTION_ATTR_OUTPUT,调用dp_netdev_lookup_port查找端口,然后调用netdev_send进行报文发送。
  • 如果是OVS_ACTION_ATTR_TUNNEL_PUSH,调用push_tnl_action进行tunnel封装,然后调用dp_netdev_recirculate-->dp_netdev_input__重新查表操作。
  • 如果是OVS_ACTION_ATTR_TUNNEL_POP,调用netdev_pop_header解封装,然后调用dp_netdev_recirculate-->dp_netdev_input__重新查表操作。

netdev_send=>netdev_dpdk_vhost_send=>__netdev_dpdk_vhost_send

  • 循环调用dpdk接口rte_vhost_enqueue_burst发送报文。
  • 调用netdev_dpdk_vhost_update_tx_counters更新统计信息。

dpdk接收报文的接口


rte_vhost_dequeue_burst涉及到一次数据拷贝

dpdk发送报文的接口


rte_vhost_enqueue_burst-->virtio_dev_rx

  • 预取vhost_virtqueue的信息。
  • 根据发送报文数count,将报文放入ring当中。此处涉及到一次数据拷贝。
  • 内存屏障进行同步。
  • 如果对方支持中断,通过eventfd_write通知对方有报文了,一般是对方virtio有中断,virtio-user无中断。

注意:所有文章非特别说明皆为原创。为保证信息与源同步,转载时请务必注明文章出处!谢谢合作 :-)

原始链接:http://zhaozhanxu.com/2016/09/08/SDN/OVS/2016-09-08-ovs-dpdk-pkts-flow/

许可协议: "署名-非商用-相同方式共享 4.0" 转载请保留原文链接及作者。