赵占旭的博客

OpenvSwitch中的分片与重组

最近遇到了分片导致的一系列问题,所以在这里盘点一下OVS中都有哪些已经做了分片和重组的地方,以及还有哪些地方需要做。版本还是基于2.7.0。并且datapath的时候会分别分析OVS和OVS-DPDK两块的处理。

分片的处理


up到userspace的时候

OVS部分

netdev_frame_hook-->netdev_port_receive-->ovs_vport_receive-->ovs_dp_process_packet-->ovs_dp_upcall主要是判定是否是带了GSO标志,如果带了,则需要将报文进行分片上报。

OVS-DPDK部分

pmd_thread_main-->dp_netdev_process_rxq_port-->dp_netdev_input-->dp_netdev_input__-->fast_path_processing这里不会对报文进行判定,因为目前OVS-DPDK还不支持GSO。其实个人觉得这里也没必要进行分片,因为此处报文不涉及到从kernel上报到userspace的流程。

出端口之前

OVS部分

此处的分片分为两种,一种是之前因为过conntrack的时候进行了重组,那么在出口之前就要进行分片。

netdev_frame_hook-->netdev_port_receive-->ovs_vport_receive-->ovs_dp_process_packet-->ovs_execute_actions-->do_execute_actions-->do_output这里会根据dev的mtu和报文的mru比较需要不需要分片,通常情况下报文的mru是0,不需要分片,但是因为重组函数handle_fragments重组时设置了报文的mru,所以分片时也根据此项来判定。调用ovs_fragment分片完成之后会调用ovs_vport_send-->dev_queue_xmit-->dev_hard_start_xmit-->ops->ndo_start_xmit-->bond_start_xmit进行报文发送。

另一种的报文分片是VM中设置了TSO、GSO、UFO等features,导致报文比较大,这个时候需要根据标志判定是否需要分片。

netdev_frame_hook-->netdev_port_receive-->ovs_vport_receive-->ovs_dp_process_packet-->ovs_execute_actions-->do_execute_actions-->do_output-->ovs_vport_send-->dev_queue_xmit-->dev_hard_start_xmit这里会根据gso进行分片,分片完成后继续调用ops->ndo_start_xmit-->bond_start_xmit进行报文发送。其实此处也会根据其他的一些特性来判定,一般比如带了TSO之类的需要网卡去分片。

OVS-DPDK部分

pmd_thread_main-->dp_netdev_process_rxq_port-->dp_netdev_input-->dp_netdev_input__-->packet_batch_per_flow_execute-->dp_netdev_execute_actions-->dp_execute_cb-->netdev_send-->netdev_dpdk_eth_send一般会根据网卡的特性来判定是不是分片。

封装之前

OVS部分

此处的分片也分为两种,一种是之前因为过conntrack的时候进行了重组,那么在出口之前就要进行分片。

netdev_frame_hook-->netdev_port_receive-->ovs_vport_receive-->ovs_dp_process_packet-->ovs_execute_actions-->do_execute_actions-->do_output这里会根据dev的mtu和报文的mru比较需要不需要分片,通常情况下报文的mru是0,不需要分片,但是因为重组函数handle_fragments重组时设置了报文的mru,所以分片时也根据此项来判定。调用ovs_fragment分片完成之后调用ovs_vport_send-->vxlan_xmit-->dev_queue_xmit-->dev_hard_start_xmit-->ops->ndo_start_xmit-->vxlan_xmit进行报文封装。

另一种的报文分片是VM中设置了TSO、GSO、UFO等features,导致报文比较大,这个时候需要根据标志判定是否需要分片。

netdev_frame_hook-->netdev_port_receive-->ovs_vport_receive-->ovs_dp_process_packet-->ovs_execute_actions-->do_execute_actions-->do_output-->ovs_vport_send-->vxlan_xmit-->dev_queue_xmit-->dev_hard_start_xmit这里会根据gso进行分片,分片完成后继续调用ops->ndo_start_xmit-->vxlan_xmit进行封装。

OVS-DPDK部分

pmd_thread_main-->dp_netdev_process_rxq_port-->dp_netdev_input-->dp_netdev_input__-->packet_batch_per_flow_execute-->dp_netdev_execute_actions-->dp_execute_cb

  • OVS_ACTION_ATTR_TUNNEL_PUSH的情况下会进行报文封装,调用接口push_tnl_action-->netdev_push_header-->netdev_tnl_push_udp_header进行封装,需要分片的话需要在该接口之前。
  • 调用dp_netdev_recirculate重新查表。

重组的处理


conntrack的时候

OVS部分

netdev_frame_hook-->netdev_port_receive-->ovs_vport_receive-->ovs_dp_process_packet-->ovs_execute_actions-->do_execute_actions-->ovs_ct_execute中会判定报文是否分片报文,是的话调用函数handle_fragments进行重组,如果没有分片直接进行conntrack处理。

OVS-DPDK部分

pmd_thread_main-->dp_netdev_process_rxq_port-->dp_netdev_input-->dp_netdev_input__-->packet_batch_per_flow_execute-->dp_netdev_execute_actions-->odp_execute_actions-->conntrack_execute没有对报文分片的判定,直接进行conntrack的处理。

解封装之后

OVS部分

首先是Linux Kernel接收报文,然后最终调用udp_rcv-->__udp4_lib_rcv-->udp_queue_rcv_skb-->encap_rcv会调用vxlan_rcv进行报文解封装,最终调用netdev_port_receive-->ovs_vport_receive-->ovs_dp_process_packet进行查表和转发,需要注意的是这块根本没有分片和重组。

OVS-DPDK部分

pmd_thread_main-->dp_netdev_process_rxq_port-->dp_netdev_input-->dp_netdev_input__-->packet_batch_per_flow_execute-->dp_netdev_execute_actions-->dp_execute_cb

  • OVS_ACTION_ATTR_TUNNEL_POP的情况下会进行报文解封装,调用接口netdev_pop_header-->netdev_vxlan_pop_header进行解封装,需要重组的话需要在该接口之后进行。
  • 调用dp_netdev_recirculate重新查表。

匹配流表的之前

bridge_run-->bridge_reconfigure-->ofproto_create会设置默认的分片配置。一般是normal,表示分片的源、目的端口为0。
bridge_run-->bridge_run__-->ofproto_run-->handle_openflow-->handle_openflow__-->handle_set_config-->set_frag_handling主要是设置分片相关的配置,目前有normal、drop、reassemable、nx_match等,但是目前reassemable功能还不支持,需要我们来完成。
rule_dpif_lookup_from_table根据不同的模式下发不同的流表。
由以上信息可以得知,支持reassemable的话首先是不是所有的报文都进行重组,但是我们并不是所有的报文都需要重组,只有需要匹配L4的匹配项时才需要,都进行重组的话相当消耗性能,第二就是查找流表的时候还要保证分片的首包先进行流表下拉,如果不是首个分片先到,那这个报文要先缓存等待重组才行。

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

原始链接:http://zhaozhanxu.com/2017/04/10/SDN/OVS/2017-04-10-ovs-fragment-reassemble/

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