MTU导致通信不正常问题

其实这个问题一看到题目就知道了,但是分析起来还是有点绕弯弯,虽然是一个貌似很常见的问题,但是职业生涯还是第一次遇到,记录一下。

下午业务跟网络的同学反馈,某云主机访问自建IDC个别服务不正常,拿过一份抓包文件看了下,看到有重传,但是并没有特别的明显标示,于是建议两端转包,然后拿到了如下两份抓包结果:

服务端:

客户端:

从图上看出,服务器收到客户端的get请求之后,回应了两个个2962+140的包,当然,因为打开了网卡拆分tcp选项,所以2962的包到网络必然会被拆成两个包,但是从对方来看,并没有收到2962的包内容,然后客户端回了一个dup ack,表示中间丢包了,服务器端连续发了7个包,客户端都未收到,然后客户端在1分钟后发送keep alive信息,服务端发送rst,会话终止,注意其中服务端发送的多个包,客户端未收到,总结下来,看起来较大的包,客户端都没收到,怀疑是MTU问题,拿到云上环境其他主机看了下,确实MTU是1400,比我方的1500小,但是注意截图中红框的部分,客户端TCP通告的MTU是1460,那么说明对方服务器配置的MTU可能仍然是1500,因为MSS通常是 网卡MTU-ip包头20-tcp包头20算出来的,登录上对方的服务器检查,发现MTU确实跟其他机器不一致,是1500。

那么,对方正常云主机MTU配置都是1400,应当是有依据的,因为linux默认是1500,应该是对方基础网络设备上的限制,必须要1400,大一些的可能通不过部分网络设备,所以,即使对方服务器配置1500,通告到我方之后,我方按较大的报文发送,到了对方网络环境当中某些节点,可能还是会被丢弃,这就是问题的原因。跟对方运维负责人沟通后,也验证了这一问题。

发表在 好玩的linux, 网络 | 留下评论

linux intel KPTi 补丁对性能影响

2018年最火的是什么,当然是intel的漏洞大礼包了,几十年来cpu全部中招,rhel也马上推出了补丁,补丁对性能的影响,大家也是看法不一,有的说2%,有的说20%到30%之间,那么具体的影响有多少,为什么性能影响上有很大分歧呢,这里简要的介绍一下。

根据漏洞描述,此补丁影响的是linux syscall跟进程切换的开销,如果是纯计算型的应用,基本不受影响,正好sysbench有一个线程创建的测试,我们通过如下命令:

sysbench --test=threads --num-threads=32 --thread-yields=100000 --thread-locks=80 run

同样的命令,在打过补丁跟没打过补丁的场景来看,打过补丁的机器需要80s跑完,而没打过补丁的场景,只需要30s即可跑完,那么从这个场景来看,性能的损失,大约有60%,大概算是影响较大的一个场景了,虽然正常的应用,不应该有很频繁的切换跟调用,但是,补丁对于这个切换跟调用下的性能影响,绝对不容小觑。

 

发表在 好玩的linux | 留下评论

systemtap查看udp rcvbuf满导致丢包

折腾了老半天,被atomic_t坑惨啦,匿名结构体必须要用cast转换类型,然后再访问成员,用来排查udp buffer满,导致丢失日志的场景

#!/usr/bin/env stap

probe kernel.statement("udp_queue_rcv_skb@net/ipv4/udp.c")
{
    printf("rmem_alloc:%d rcv_buf:%d drops:%d\n", @cast(&$sk->sk_backlog->rmem_alloc, "atomic_t", "kernel<linux/types.h>")->counter,  $sk->sk_rcvbuf, @cast(&$sk->sk_drops, "atomic_t", "kernel<linux/types.h>")->counter)
}

 

发表在 debug, 好玩的linux | 留下评论

systemtap查看socket 信息

通过systemtap查看socket信息的脚本,跟踪在sendmsg跟recvmsg,示例中只有sndbuf跟rcvbuf,实际上可以拓展到任意的结构体成员,比较方便

#! /usr/bin/env stap
%{
#include <linux/version.h>
#include <net/sock.h>
#include <net/tcp.h>
#include <linux/tcp.h>
#include <net/inet_sock.h>
#include <net/ip.h>
#include <linux/skbuff.h>
%}

probe kernel.statement ("sock_sendmsg"),
      kernel.statement ("sock_recvmsg")
{
  printf ("%s:%d<->%s:%d\n", ip_ntop($sock->sk->__sk_common->skc_daddr), ntohs(@cast($sock->sk, "struct inet_sock")->inet_sport), ip_ntop($sock->sk->__sk_common->skc_rcv_saddr), ntohs($sock->sk->__sk_common->skc_dport) )
  printf ("%s(%d) %s : sock_flags:%d sndbuf:%d rcvbuf:%d\n",
    execname(), pid(), probefunc(), $sock->flags, $sock->sk->sk_sndbuf, $sock->sk->sk_rcvbuf)
}

 

 

发表在 好玩的linux | 留下评论

systemtap查看free_skb的场景

目前的dropwatch仅能查看丢包发生在哪个环节,不能看到丢包的内容,于是七拼八凑,拼了一个脚本,可以看到ip层的信息了,哈哈哈,tcp层的还是要做解析,不过如果不是tcp包的话,还要做一些判断逻辑,所以,先看到ip层信息就可以了。脚本如下:

#! /usr/bin/env stap
%{
#include <linux/version.h>
#include <net/sock.h>
#include <net/tcp.h>
#include <net/ip.h>
#include <linux/skbuff.h>
%}


# Note when we turn the monitor on and off
probe begin { printf("Monitoring for dropped packets\n") }
probe end { printf("Stopping dropped packet monitor\n") }

probe kernel.statement("kfree_skb") {
        iphdr = __get_skb_iphdr($skb)
        family = %{ AF_INET %}
        saddr = format_ipaddr(__ip_skb_saddr(iphdr), %{ AF_INET %})
        daddr = format_ipaddr(__ip_skb_daddr(iphdr), %{ AF_INET %})
        protocol = __ip_skb_proto(iphdr)
  printf("%s->%s\n",saddr,daddr)
}

发现ping包最后都会走到kfree_skb的逻辑去。所以拿kfree_skb衡量丢包不太准确啊

后续:dropwatch跟这个脚本跟踪的都是kfree_skb函数被调用的时机,但是其实这个函数也是正常包被释放的时候会被调用的,所以,这个根本不是衡量丢包的,请注意

发表在 好玩的linux | 留下评论