转载请注明出处,谢谢。
支持dpdk结构
ovs-dpdk的vswitchd进程
ovs的dpdk网卡结构:
支持三种类型:物理网卡/vhostuser/vhostuserclient
对于ovs使用dpdk 需要在启动ovs的时候需要配置一些参数 other_config
dpdk-init
指定ovs是否初始化和支持dpdk端口。
dpdk-lcore-mask
指明dpdk使用的逻辑核。同dpdk的-c参数。
dpdk-socket-mem
指明不同numa节点提前申请的大页内存。同dpdk的--socket-mem参数。
dpdk-hugepage-dir
大页文件系统mount的目录。同dpdk的--huge-dir参数。
vhost-sock-dir
设置vhost-user 套接字的路径。
dpdk-extra
其他的dpdk配置参数。
dpdk初始化
主要包括:
1) dpdk eal初始化。
2) 启动dpdk接口状态监控线程(使用dpdk的库函数),如果状态发送变化,则更新netdev设备的变化标记。
3) 注册dpdk类型的netdev class。其中包括dpdk设备类型,ring类型、vhost、vhost client类型。
pmd线程
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–> reconfigure_datapath-> reconfigure_pmd_threads –>pmd_thread_main
如果已经添加了dpdk端口,启动的时候也会触发创建pmd线程的操作。
bridge_run->bridge_run__->ofproto_run->dpif_netdev_run–> reconfigure_datapath–> pmd_thread_main
重新配置cmask的时候也会触发pmd线程的操作
dpif_netdev_set_config->dp_netdev_request_reconfigure-> reconfigure_datapath-> reconfigure_pmd_threads–>pmd_thread_main
dp_netdev_process_rxq_port接口负责接收报文,然后调用接口dp_netdev_input–>dp_netdev_input__负责查表,然后调用packet_batch_execute–>dp_netdev_execute_actions执行actions操作。
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根据流表来操作报文。
dfc_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更新统计信息。
PMD线程在其轮询列表中持续轮询输入端口,在每一个端口上最多可同时收32个包(NETDEV_MAX_BURST),根据激活的流规则可将每一个收包进行分类。分类的目的是为了找到一个流,从而对包进行恰当的处理。包根据流进行分组,并且每一个分组将执行特定的动作。