一、背景

使用ping命令发现局域网内延迟大,且变化较大。需要分析耗时在那一层。

二、分析

上图可以看出,本机ping延时非常低。在本机网络 IO 的过程中,流程会有一些差别。有差异的地方总共有两个,分别是路由和驱动程序。

路由:

对于本机网络 IO 来说,特殊之处在于在 local 路由表中就能找到路由项,对应的设备都将使用 loopback 网卡,也就是我们常见的 lO。

驱动程序:

网络设备子系统的入口函数是 dev_queue_xmit。对于真的有队列的物理设备,在该函数中进行了一系列复杂的排队等处理以后,才调用 dev_hard_start_xmit,从这个函数再进入驱动程序来发送。

但是对于启动状态的回环设备来说(q->enqueue 判断为 false),就简单多了:没有队列的问题,直接进入 dev_hard_start_xmit。接着进入回环设备的“驱动”里的发送回调函数 loopback_xmit,将 skb “发送”出去。

因此,可以从上面两层入手,排查问题!

驱动:

监控icmp包发送和接受的时刻,看时间是否过大。

但有一个问题,链路上运行的不一定只有ICMP数据包。因此,我们需要在每一层对我们发送和接收的ICMP包进行过滤。

路由:

三、ICMP

ICMP报文包含在IP数据报中,IP报头在ICMP报文的最前面。一个ICMP报文包括IP报头(至少20字节)、ICMP报头(至少八字节)和ICMP报文(属于ICMP报文的数据部分)。当IP报头中的协议字段值为1时,就说明这是一个ICMP报文。ICMP报头如下图所示。

这里只讲解与ping有关的ICMP消息类型,主机发送回送消息(Type = 8),被请求主机回送响应消息(Type = 0),基本格式如下:
回送消息[ECHO]

回送响应消息[ECHO REPLY]

•CheckSum为校验和,重点注意从ICMP的头部(即Type开始),到data结束(即到整个数据包结束)
•Identifier为标识符,由主机设定,一般设置为进程号,回送响应消息与回送消息中identifier保持一致
•Sequence Number为序列号,由主机设定,一般设为由0递增的序列,回送响应消息与回送消息中Sequence Number保持一致
•data为数据,由主机设定,回送响应消息与回送消息中data保持一致

///include/uapi/linux/icmp.hstruct icmphdr {__u8     type;__u8       code;__sum16    checksum;union {struct {__be16  id;__be16   sequence;} echo;__be32  gateway;struct {__be16  __unused;__be16 mtu;} frag;__u8 reserved[4];} un;
};

四、实现

#ifndef _LINUX_IP_H
#define _LINUX_IP_H#include <linux/skbuff.h>
#include <uapi/linux/ip.h>static inline struct iphdr *ip_hdr(const struct sk_buff *skb)
{return (struct iphdr *)skb_network_header(skb);
}static inline struct iphdr *inner_ip_hdr(const struct sk_buff *skb)
{return (struct iphdr *)skb_inner_network_header(skb);
}static inline struct iphdr *ipip_hdr(const struct sk_buff *skb)
{return (struct iphdr *)skb_transport_header(skb);
}
#endif  /* _LINUX_IP_H */struct iphdr {
#if defined(__LITTLE_ENDIAN_BITFIELD)__u8   ihl:4,version:4;
#elif defined (__BIG_ENDIAN_BITFIELD)__u8   version:4,ihl:4;
#else
#error  "Please fix <asm/byteorder.h>"
#endif__u8  tos;__be16  tot_len;__be16  id;__be16   frag_off;__u8   ttl;__u8    protocol;__sum16    check;__be32    saddr;__be32    daddr;/*The options start here. */
};
///include/uapi/linux/in.henum {IPPROTO_IP = 0,     /* Dummy protocol for TCP       */
#define IPPROTO_IP      IPPROTO_IPIPPROTO_ICMP = 1,        /* Internet Control Message Protocol    */
#define IPPROTO_ICMP        IPPROTO_ICMPIPPROTO_IGMP = 2,      /* Internet Group Management Protocol   */
#define IPPROTO_IGMP        IPPROTO_IGMPIPPROTO_IPIP = 4,      /* IPIP tunnels (older KA9Q tunnels use 94) */
#define IPPROTO_IPIP        IPPROTO_IPIPIPPROTO_TCP = 6,       /* Transmission Control Protocol    */
#define IPPROTO_TCP     IPPROTO_TCPIPPROTO_EGP = 8,        /* Exterior Gateway Protocol        */
#define IPPROTO_EGP     IPPROTO_EGPIPPROTO_PUP = 12,       /* PUP protocol             */
#define IPPROTO_PUP     IPPROTO_PUPIPPROTO_UDP = 17,       /* User Datagram Protocol       */
#define IPPROTO_UDP     IPPROTO_UDPIPPROTO_IDP = 22,       /* XNS IDP protocol         */
#define IPPROTO_IDP     IPPROTO_IDPIPPROTO_TP = 29,        /* SO Transport Protocol Class 4    */
#define IPPROTO_TP      IPPROTO_TPIPPROTO_DCCP = 33,       /* Datagram Congestion Control Protocol */
#define IPPROTO_DCCP        IPPROTO_DCCPIPPROTO_IPV6 = 41,     /* IPv6-in-IPv4 tunnelling      */
#define IPPROTO_IPV6        IPPROTO_IPV6IPPROTO_RSVP = 46,     /* RSVP Protocol            */
#define IPPROTO_RSVP        IPPROTO_RSVPIPPROTO_GRE = 47,      /* Cisco GRE tunnels (rfc 1701,1702)    */
#define IPPROTO_GRE     IPPROTO_GREIPPROTO_ESP = 50,       /* Encapsulation Security Payload protocol */
#define IPPROTO_ESP     IPPROTO_ESPIPPROTO_AH = 51,        /* Authentication Header protocol   */
#define IPPROTO_AH      IPPROTO_AHIPPROTO_MTP = 92,        /* Multicast Transport Protocol     */
#define IPPROTO_MTP     IPPROTO_MTPIPPROTO_BEETPH = 94,        /* IP option pseudo header for BEET */
#define IPPROTO_BEETPH      IPPROTO_BEETPHIPPROTO_ENCAP = 98,      /* Encapsulation Header         */
#define IPPROTO_ENCAP       IPPROTO_ENCAPIPPROTO_PIM = 103,        /* Protocol Independent Multicast   */
#define IPPROTO_PIM     IPPROTO_PIMIPPROTO_COMP = 108,     /* Compression Header Protocol      */
#define IPPROTO_COMP        IPPROTO_COMPIPPROTO_SCTP = 132,        /* Stream Control Transport Protocol    */
#define IPPROTO_SCTP        IPPROTO_SCTPIPPROTO_UDPLITE = 136, /* UDP-Lite (RFC 3828)          */
#define IPPROTO_UDPLITE     IPPROTO_UDPLITEIPPROTO_MPLS = 137,     /* MPLS in IP (RFC 4023)        */
#define IPPROTO_MPLS        IPPROTO_MPLSIPPROTO_RAW = 255,     /* Raw IP packets           */
#define IPPROTO_RAW     IPPROTO_RAWIPPROTO_MAX
};

驱动层如何识别ICMP报文?

在.ndo_start_xmit = esp_hard_start_xmit,函数中,将邻居子系统传递下来的skb使用ip_hdr函数即可转换!

#include <linux/ip.h>
#include <linux/in.h>
#include <linux/icmp.h>struct iphdr *iph;
struct icmphdr *icmpph = NULL;iph = ip_hdr(skb);
​if(iph->protocol==IPPROTO_ICMP ) {//如果是ICMP报文icmpph = (struct icmphdr *) ((u8 *) iph + (iph->ihl << 2));printk("ESP type:%d, code:%d\n", icmpph->type, icmpph->code);if(icmpph->type==8 && icmpph->code==0) {//ping 请求printk(KERN_ERR "ping RQ:%d\n",icmpph->un.echo.sequence);}
}

ref:

不为人知的网络编程(十三):深入操作系统,彻底搞懂127.0.0.1本机网络通信 - 知乎

linux内核协议栈 icmp 报文收发流程_老王不让用的博客-CSDN博客

ping命令全链路分析(4) - 数据包内核态处理 - 知乎

Linux内核:从skb获取udp头,udp_hdr()获取到是错误的udp头_kanguolaikanguolaik的博客-CSDN博客

网络-ICMP协议、Ping命令实现与ICMP攻击_51CTO博客_icmp ping

ICMP协议之ping实现_yo-yo的博客-CSDN博客

使用ping命令定位网络延迟问题相关推荐

  1. 使用ping命令查看网络延迟--用Enki学Linux系列(7)

    使用ping命令查看网络延迟 Using ping To Measure Network Latency ping命令持续发送少量互联网流量到远程地址并报告收到回应的总时间.如果流量因为网络故障或者错 ...

  2. ping 延迟 linux,使用ping命令查看网络延迟--用Enki学Linux系列(7)

    使用ping命令查看网络延迟 Using ping To Measure Network Latency ping命令持续发送少量互联网流量到远程地址并报告收到回应的总时间.如果流量因为网络故障或者错 ...

  3. linux怎么用ping通测试连接,ping网络是否连通的步骤_使用ping命令检查网络连通性的方法-系统城...

    2015-03-23 10:34:59 浏览量:775 Ping属于一个通信协议,利用Ping命令可以检查网络是否连通,可以很好地帮助我们分析和判定网络故障,然而在WinXP系统​的局域网下我们如果要 ...

  4. 计算机不能上网怎么检查,电脑不能上网如何通过Ping命令检查网络

    电脑系统工作时间一长,就会不可避免地遇到网络故障;在排除网络故障之前,用户首先应该弄清楚在网络服务.网络设备.网络资源工作状态正常的情况下,究竟是什么样的表现形式,之后对照发生故障时的状态,分辨出网络 ...

  5. ping命令测试网络_如何执行计算机Ping测试命令以检查网络连接?

    ping命令测试网络 Computer networking provides a lot of features for remote usage. But remote access may ha ...

  6. 使用ping命令检查网络是否通畅或网络连接连接速度

    使用ping命令检查网络是否通畅或网络连接连接速度 Ping是Windows.Unix和Linux系统下的一个命令.ping也属于一个通信协议,是TCP/IP协议的一部分.利用ping命令可以检查网络 ...

  7. 使用C#调用外部Ping命令获取网络连接情况

    以前在玩Windows 98的时候,几台电脑连起来,需要测试网络连接是否正常,经常用的一个命令就是Ping.exe.感觉相当实用. 现在 .Net为我们提供了强大的功能来调用外部工具,并通过重定向输入 ...

  8. 如何使用ping命令检查网络故障

    如果网络不通,可以按照以下步骤来诊断网络状况:依次点击:开始-允许-输入CMD,进入DOS窗口后用ping命令来诊断网络连接的状况. ping是Windows系列自带的一个可执行命令.利用它可以检查网 ...

  9. linux使用ping命令ping本机,Linux下使用ping命令判断网络的好坏

    简介 在Linux系统里面如果想判断网络的好坏,脑海中蹦出的第一个命令就是ping了. ping命令基本是最常用的网络命令,它可以用来测试与目标主机的连通性. ping通过发送ICMP ECHO_RE ...

最新文章

  1. c#运行shell命令
  2. 在OpenCV中图像边界扩展 copyMakeBorder 的实现
  3. 《研磨设计模式》chap6 工厂模式factory(2)案例实现
  4. webpack4配置基础
  5. 全市场等权中位数_A股市场周内效应研究
  6. windows缺少dll文件检测dll文件
  7. jquery学习笔记之选择器
  8. Java中的class类和对象总结(思维导图)
  9. bootice添加linux_用BOOTICE工具在U盘上实现SYSLINUX与GRUB4DOS双启动 - 图文
  10. Java开发手册!java项目描述模板,挥泪整理面经
  11. 千住焊锡丝RMA98,ESC21参数解读:金属含量、焊剂成分、质保期、Lot No. 等
  12. Week1.3-金融会计指标案例分析
  13. 笔记本电脑网络服务无法使用,打开网络共享中心,一直卡在打开界面或者插入网线后右下角为红叉
  14. office钓鱼学习
  15. 基础测绘1:10000成果检验需注意的问题
  16. 杰里之. 输出 3 路 PMW【篇】
  17. 北洋大时代:大师们的理想国札记-随想篇
  18. 互联网公司招聘--奇虎360--技术类--2013年笔试题
  19. 一步一步搭建一个图片上传网站(后台服务器用nodejs)
  20. Windows 10 卸载 Qt 5.9.9

热门文章

  1. 后端文章 - 收藏集 - 掘金
  2. 中国移动提出的ABCDNETS和DSSN数联网技术介绍
  3. vue项目中,amr格式的音频播放
  4. proxy_set_header Host $host $proxy_port $http_host
  5. 阿里巴巴大数据之路读书笔记——用户画像的定义
  6. 基于Scrapy爬取伯乐在线网站
  7. 大数据必须框架-Azkaban
  8. django channels 使用总结
  9. 快递查询Api接口(快递鸟)
  10. 深度解析pos机,养卡人必看!