最近遇到了一个关于缓存的坑,所以需要查看代码整理一下哪些情况下会有缓存报文,啥时候不会丢,啥时候会丢,OVS版本2.7.0,DPDK16.11.1版本。

我们知道报文需要缓存一般就是不知道如何转发时,这个就涉及到常见的几个点了,最终结果就是哪都不缓存报文,全是全量报文往上给和往下发。

  • datapath层如果EMC和megaflow没有匹配时,DPDK版是直接查找上一级表,直到找到匹配的流表,然后转发,不会缓存
  • kernel版datapath则需要通过netlink上报,这时候0拷贝一个新的报文上报,源报文释放了,而生成的流表会带着报文一起根据netlink下发过来,最终新生成一个报文,根据流表转发。
  • ofproto classifier层的话,常见的一个点是依然没有匹配的流表,需要packet in到controller的时候,报文也是全量上传给controller,所以buffer_id一直都是全f,这个就是ovs的实现。controller下发流表的时候不会带着报文,所以除了下发flow_mod,需要额外的packet_out才能保证首包下发。
  • 目前已知的另一个点是dpdk版的datapath的时候,tnl封装后,需要用到ovs的arp表时,arp相关信息不存在时,则不下发流表和报文,所以也不涉及缓存的问题。

DPDK版


datapath层

pmd_thread_main-->dp_netdev_process_rxq_port-->dp_netdev_input-->dp_netdev_input__-->fast_path_processing-->handle_packet_upcall中就是直接调用dp_netdev_upcall去查找匹配的流表,这个时候因为大家都处在userspace层,所以就直接API调用,找到流表后安装,接着执行action即可,是一个串行的处理流程,所以不需要有报文缓存。

ofproto classifier层

handle_packet_upcall-->dp_netdev_upcall-->upcall_cb-->process_upcall-->upcall_xlate-->xlate_actions-->do_xlate_actions列出来我们关注的点

  • 首先会根据arp的回复拿到ip对应的mac地址,然后存入arp缓存中,老化时间默认15分钟
  • 如果匹配到controller的流表,并且需要封装报文的时候,会查询arp缓存,查不到就不生成流表,报文也就销毁了。
  • 没有匹配,则调用execute_controller_action生成packet_in相关信息的报文,然后通过ofproto_dpif_send_async_msg将信息放入ofproto

main-->bridge_run-->bridge_run__-->ofproto_type_run-->dpif_run-->run-->connmgr_send_async_msg-->ofputil_encode_packet_in_private-->ofputil_encode_ofp12_packet_in会从ofproto拿到信息然后封装为packet_in报文,然后buffer_id都是-1,报文全部上传,所以就不存在缓存报文的问题了。

main-->bridge_run-->bridge_run__-->ofproto_run-->handle_openflow-->handle_openflow__是处理openflow消息的操作,我们关注几点

  • packet_out的buffer_id如果不是-1,就会报错,意思是packet_out要么自己生成报文,然后给到ovs进行发送,比如ovn中需要发送免费arp时就是调用的packet_out,要么就是之前packet_in上传过来的报文。配合上面的意思就是老子packet_in的时候不缓存报文,你也表骗老子去找缓存,想发包就拿全量包过来。
  • flow_mod不关心buffer_id,因为之前没有缓存报文,所以不涉及openflow协议中涉及的缓存报文的处理,只负责下发流表,所以需要packet_out配合。

kernel版


datapath层

netdev_frame_hook-->netdev_port_receive-->ovs_vport_receive-->ovs_dp_process_packet首先调用ovs_flow_tbl_lookup_stats查找流表,查找不到则需要调用ovs_dp_upcall上报一个新生成的报文,但是0拷贝了skb的数据。

接下来是接收用户态的netlink报文后的操作。
ovs_packet_cmd_execute-->ovs_execute_actions中会重新创建一个skb,然后讲内容从netlink的数据中拷贝报文数据,所以相当于没有缓存。最后根据flow信息将报文转发。

ofproto classifier层

udpif_start_threads-->udpif_upcall_handler-->recv_upcalls-->process_upcall-->upcall_xlate-->xlate_actions-->do_xlate_actions-->execute_controller_action参照上面。

udpif_start_threads-->udpif_upcall_handler-->recv_upcalls-->handle_upcalls-->dpif_operate-->dpif_netlink_operate-->dpif_netlink_operate__-->dpif_netlink_encode_execute-->nl_msg_put_genlmsghdr下发netlink报文。

最后修改:2021 年 08 月 18 日
如果觉得我的文章对你有用,请随意赞赏