• UDP, bad length 1496 > 496


    1496是总个报文的长度
    [root@localhost ~]# tcpdump -i enp125s0f0 udp and host 10.10.16.81  -env 
    tcpdump: listening on enp125s0f0, link-type EN10MB (Ethernet), capture size 262144 bytes
    21:17:19.222749 48:57:02:64:ea:1b > b0:08:75:5f:b7:d9, ethertype IPv4 (0x0800), length 538: (tos 0x0, ttl 64, id 12345, offset 0, flags [+], proto UDP (17), length 524)
        10.10.16.81.vlsi-lm > 10.10.16.229.krb524: UDP, bad length 1496 > 496
    21:17:19.294418 48:57:02:64:ea:1b > b0:08:75:5f:b7:d9, ethertype IPv4 (0x0800), length 538: (tos 0x0, ttl 64, id 12345, offset 504, flags [+], proto UDP (17), length 524)
        10.10.16.81 > 10.10.16.229: ip-proto-17
    21:17:19.364260 48:57:02:64:ea:1b > b0:08:75:5f:b7:d9, ethertype IPv4 (0x0800), length 530: (tos 0x0, ttl 64, id 12345, offset 1008, flags [none], proto UDP (17), length 516)
        10.10.16.81 > 10.10.16.229: ip-proto-17
    21:17:47.252277 48:57:02:64:ea:1b > 01:00:5e:01:01:01, ethertype IPv4 (0x0800), length 120: (tos 0x0, ttl 1, id 43958, offset 0, flags [none], proto UDP (17), length 106)
        10.10.16.81.57013 > 239.1.1.1.4789: VXLAN, flags [I] (0x08), vni 100
    ba:d8:f4:bf:4f:f5 > 33:33:00:00:00:02, ethertype IPv6 (0x86dd), length 70: (hlim 255, next-header ICMPv6 (58) payload length: 16) fe80::b8d8:f4ff:febf:4ff5 > ff02::2: [icmp6 sum ok] ICMP6, router solicitation, length 16
              source link-address option (1), length 8 (1): ba:d8:f4:bf:4f:f5
    21:20:14.652961 48:57:02:64:ea:1b > b0:08:75:5f:b7:d9, ethertype IPv4 (0x0800), length 538: (tos 0x0, ttl 64, id 12345, offset 0, flags [+], proto UDP (17), length 524)
        10.10.16.81.vlsi-lm > 10.10.16.229.krb524: UDP, bad length 1496 > 496
    21:20:14.694614 48:57:02:64:ea:1b > b0:08:75:5f:b7:d9, ethertype IPv4 (0x0800), length 538: (tos 0x0, ttl 64, id 12345, offset 504, flags [+], proto UDP (17), length 524)
        10.10.16.81 > 10.10.16.229: ip-proto-17
    21:20:14.764480 48:57:02:64:ea:1b > b0:08:75:5f:b7:d9, ethertype IPv4 (0x0800), length 530: (tos 0x0, ttl 64, id 12345, offset 1008, flags [none], proto UDP (17), length 516)
        10.10.16.81 > 10.10.16.229: ip-proto-17

    二 问题分析

    2.1 基本分析

    程序同时发送到本地应用和远程应用的,虽然是不同的IP和端口,但是是同一个逻辑,所以程序的本身的问题可能性比较小,先测试下是否为网络问题:

    • 先用ping测试下,由于ping被禁止了,所以没有测试出什么来.
    • 利用nc -ul xxx 在远程机器新建一个udp监听端口,应用程序所在机器,通过nc -u x.x.x.x xxx 连接后,通过输入一些字符,来看看远程机器是否有屏显,结果本次测试正常,说明网络是通的.
    • 继续在远程的机器抓包,发现不是没有收到,而是收到的包相对来说比较小,大小为400多个字节左右,均是这种小于1千个字节的.
    • 在发送告警的机器通过tcpdump抓包: tcpdump -i eth1 udp port xxxx -A -nn 发现有类似于以下内容的告警:
    21:01:39.000550 IP (tos 0x0, ttl 64, id 63736, offset 0, flags [+], proto UDP (17), length 1500)
        xxx.xxx.xxx.xxx.59019 > xxx.xxx.xxx.xxx.documentum: UDP, bad length 6902 > 1472
    

    首先,我们来看下这个1472是怎么来的,在以太网环境中,以太网的帧的body大小为46字节到1500字节之间,本次是处于IPV4的环境,IP包头大小为20个字节,所以还剩下1480字节;UDP的协议的报文头长度为8个字节,所以剩下的udp的包体长度为1480-8 = 1472个字节,具体展示如下图:
    格式如下:


     
    协议格式
     
    UDP报文格式

    上述告警意思是因为我们环境下网卡的MTU设置为1500个字节,如下:

    [root@localhost ~]# ifconfig
    em1: flags=4163<UP,BROADCAST,RUNNING,MULTICAST>  mtu 1500
    

    因为发送的UDP报文长度大于可以传输的安全长度1472个字节,这不代表不能发送,只是因为大于了帧的最大传输长度,所以在IP层需要进行分包,一旦网络环境不好,分包产生了丢失问题,会造成IP的组包失败,从而导致UDP的报文丢失.

    不过鉴于Internet上的标准MTU值为576字节,所以建议在进行Internet的UDP编程时,最好将UDP的数据长度控制在 (576-8-20)548字节以内

    还可以通过netstat -su进行监控:

    [root@localhost ~]# netstat -su
    IcmpMsg:
        InType0: 141039
        InType3: 72945
        InType8: 1616
        InType13: 1
        OutType0: 1616
        OutType3: 777474
        OutType8: 141039
        OutType14: 1
    Udp:
        4039279 packets received
        123325 packets to unknown port received.
        67020 packet receive errors
        4229636 packets sent
        67020 receive buffer errors
        0 send buffer errors
    UdpLite:
    IpExt:
        InNoRoutes: 2
        InMcastPkts: 26
        InBcastPkts: 723113
        InOctets: 27500413848629
        OutOctets: 27491308862298
        InMcastOctets: 832
        InBcastOctets: 287040162
        InNoECTPkts: 126755848707
        InECT0Pkts: 16
    
    

    2.2 尝试解决

    既然MTU太小了,那么尝试修改下两端的MTU最大值,MTU是取整个路由的MTU最小值,我们尝试把两端的MTU增大下:

    ifconfig eth1 mtu 9000 up
    

    两端MTU增加后,仍然会报错,那么可能的原因是中间路由设备设置的MTU比较小,查看下,由于主机上没有traceroute命令来跟踪,尝试使用另外一个命令:

    tracepath xxx.xxx.xx.xx.xx
    

    类似于traceroute,可以追踪路由,结束后打印MTU值.
    还可以带个端口,测试这个UDP端口.

    [root@localhost ~]# tracepath 1xx.xx.xx.2xx/10001
     1?: [LOCALHOST]                                         pmtu 1500
     1:  xx.xx.xx.xx                                         0.502ms reached
     1:  xx.xx.xx.xx                                          0.323ms reached
         Resume: pmtu 1500 hops 1 back 1 
    

    在实际环境中,由于中间很多路由都看不到,而且让中间的所有路由都改MTU值不是太现实.

    在MTU为1500字节的情况下,如果发送的UDP报文大于MTU,比如发送8000个字节,如果包缓存足够,且分包按照正确的顺序到来,通过recvfrom(9000) 还是可以收到一个完整的UDP包的. 如果IP分片丢失,校验失败,包就会丢弃.recvfrom(9000)将阻塞.

    2.3 更改socket缓冲区大小

    为防止socket缓冲区溢出造成的问题,特意增加了socket的缓冲区.
    cat /proc/sys/net/core/rmem_defaultcat /proc/sys/net/core/rmem_max可以查看socket缓冲区的缺省值和最大值。
    可以通过echo xxx >/proc/sys/net/core/rmem_default的方法来临时修改,也通过更改/etc/sysctl.conf文件添加以下配置来修改:

    net.core.rmem_default=262144
    net.core.wmem_default=262144
    net.core.rmem_max=262144
    net.core.wmem_max=262144
    

    修改完成后记得运行以下命令来生效:

    sysctl -p
    

     
  • 相关阅读:
    VS 2017 没有工具栏中没有Report Viewer的解决方案
    数据类型和C#关系对应
    .NET CORE部署各种问题
    .NET CORE AutoMapper使用
    .NET CORE 配置Swagger文档
    window快捷登陆linux的的设置方式(设置ssh的config配置)
    linux安装mongodb并启动
    windows更改DNS设置
    scp的使用
    浏览器缓存机制
  • 原文地址:https://www.cnblogs.com/dream397/p/13748068.html
Copyright © 2020-2023  润新知