docker的跨主机解决方案weave----遇到的坑(2)

5710阅读 0评论2016-12-02 frankzfz
分类:云计算

  在使用weave时遇到的问题:在新的内核版本中 CentOS Linux (3.10.0-327.10.1.el7.x86_64) 7 (Core) ,在MTU1450的主机上,weavefast data path路径不可用,该功能是在weave 1.2.0上引入的。启动后一直为sleeve模式。该问题和内核的版本相关,
 问题分析:
  Weavefast data path路径使用到了odp技术,也就是内核中的OVS模块,在Container中直接发送数据包到ovs模块,由ovs模块进行封装后发送。fast data path需要内核中的openvswitch.ko模块的支持。在启动Weave时,会自动选择使用sleeve模式还是fastdp模式,这里通过发送心跳包来决定的,在云主机上通过 docker logs weave的日志可以看到,下面的信息,其中:fastdp timed out waiting for vxlan heartbeat
 这个heartbeat的数据包,是一个UDP包,目的端口号为6784主机上接口的MTU值为1450,但是在发送UDPheartbeat数据包时,发送的还是1474字节,这样就会对报文在IP层进行分片,但在主机上发现心跳报文发送不出,在MTU的值修改为1500后,就可以发送出去,在MTU1450的情况下,会出现下面的ICMP的错误报文。

发送icmp报文是在ip_fragment函数中做的

点击(此处)折叠或打开

  1. if (unlikely(((iph->frag_off & htons(IP_DF)) && !skb->ignore_df) ||
  2.          (IPCB(skb)->frag_max_size &&
  3.          IPCB(skb)->frag_max_size > mtu))) {
  4.         IP_INC_STATS(dev_net(dev), IPSTATS_MIB_FRAGFAILS);
  5.         icmp_send(skb, ICMP_DEST_UNREACH, ICMP_FRAG_NEEDED,
  6.              htonl(mtu));
  7.         kfree_skb(skb);
  8.         return -EMSGSIZE;
  9.     }
  在上面的代码中,iph->frag_off & htons(IP_DF)) && !skb->ignore_df 条件成立,,skb->ignore_df的值为0。报文中iph->frag_off & htons(IP_DF))的值成立。
在net/openvswitch/vport-vxlan.c文件中对报文中的iph->frag_off进行了设置

点击(此处)折叠或打开

  1. df = tun_key->tun_flags & TUNNEL_DONT_FRAGMENT ?
  2.         htons(IP_DF) : 0;
  3.        skb->ignore_df = 1;

  在iptunnel_xmit 函数中把iph->frag_off      =       df;赋值给了frag_off。但是skb->ignore_dfiptunnel_xmit函数中调用skb_scrub_packet进行了清除。

点击(此处)折叠或打开

  1. void skb_scrub_packet(struct sk_buff *skb, bool xnet)
  2. {
  3.     if (xnet)
  4.         skb_orphan(skb);
  5.     skb->tstamp.tv64 = 0;
  6.     skb->pkt_type = PACKET_HOST;
  7.     skb->skb_iif = 0;
  8.     skb->ignore_df = 0;
  9.     skb_dst_drop(skb);
  10.     skb->mark = 0;
  11.     secpath_reset(skb);
  12.     nf_reset(skb);
  13.     nf_reset_trace(skb);
  14. }

  所以在ip_fragment中的判断skb->ignore_df0。但在新的内核中

点击(此处)折叠或打开

  1. int iptunnel_xmit(struct net *net, struct rtable *rt,
  2.                   struct sk_buff *skb,
  3.                   __be32 src, __be32 dst, __u8 proto,
  4.                   __u8 tos, __u8 ttl, __be16 df)
  5. {
  6.         int pkt_len = skb->len;
  7.         struct iphdr *iph;
  8.         int err;

  9.         nf_reset(skb);
  10.         secpath_reset(skb);/*调用的该函数,该函数并没有对skb->ignore_df 进行清除。
  11. 在static inline void
  12. secpath_reset(struct sk_buff *skb)
  13. {
  14. #ifdef CONFIG_XFRM
  15.         secpath_put(skb->sp);
  16.         skb->sp = NULL;
  17. #endif
  18. } */
  19.         skb_clear_hash(skb);
  20.         skb_dst_drop(skb);
   所以在MTU小于1500时,会造成weave无法使用fastdp模式。
上一篇:docker的跨主机解决方案weave----遇到的坑(1)
下一篇:LVS 内核实现分析(1)