GRO checksum在tcpdump中incorrect的问题
tcpdump -i $link src 192.168.1.14 and port 4000 and greater 100 -v -nn
当rx-checksumming打开的时候,skb->csum里面是硬件计算的tcp checksum,但是不包括伪头。
dev_gro_receive()
{
...
/* Setup for GRO checksum validation */
switch (skb->ip_summed) {
case CHECKSUM_COMPLETE:
NAPI_GRO_CB(skb)->csum = skb->csum;
NAPI_GRO_CB(skb)->csum_valid = 1;
NAPI_GRO_CB(skb)->csum_cnt = 0;
break;
...
}
tcp4_gro_receive()被调到的时候skb_gro_checksum_validate会根据NAPI_GRO_CB(skb)->csum和伪头
(inet_gro_compute_pseudo是用来计算伪头的)算出tcp checksum。如果是0xffff,就是正确的。这时line 2733会返回0
2728 static inline __sum16 __skb_gro_checksum_validate_complete(struct sk_buff *skb,
2729 __wsum psum)
2730 {
2731 if (NAPI_GRO_CB(skb)->csum_valid &&
2732 !csum_fold(csum_add(psum, NAPI_GRO_CB(skb)->csum)))
2733 return 0;
2734
2735 NAPI_GRO_CB(skb)->csum = psum;
2736
2737 return __skb_gro_checksum_complete(skb);
2738 }
否则的话,__skb_gro_checksum_complete会用软件的方式计算checksum,如果用软件算出的checksum是正确的,
netdev_rx_csum_fault()会被调到,并且打印如下错误信息:
pr_err("%s: hw csum failure\n", dev ? dev->name : "<unknown>");
在kernel中打上如下patch
diff --git a/include/linux/netdevice.h b/include/linux/netdevice.h
index f9a9067d038d..e9de4431acf6 100644
--- a/include/linux/netdevice.h
+++ b/include/linux/netdevice.h
@@ -2725,29 +2725,57 @@ static inline bool __skb_gro_checksum_validate_needed(struct sk_buff *skb,(!zero_okay || check));}+struct tcphdr2 {
+ __be16 source;
+ __be16 dest;
+};
+static inline __sum16 __skb_gro_checksum_validate_complete(struct sk_buff *skb,__wsum psum){
+ struct tcphdr2 *tcph;
+ __be16 dest;
+
+ tcph = (struct tcphdr2 *)(skb->head + skb->mac_header + 34);
+ dest = ntohs(tcph->dest);
+if (NAPI_GRO_CB(skb)->csum_valid &&
- !csum_fold(csum_add(psum, NAPI_GRO_CB(skb)->csum)))
+ !csum_fold(csum_add(psum, NAPI_GRO_CB(skb)->csum))) {
+ if (dest == 4000)
+ pr_info("%s: return 0\n", __func__);return 0;
+ }NAPI_GRO_CB(skb)->csum = psum;
+ if (dest == 4000)
+ pr_info("%s: csum: %x\n", __func__, psum);return __skb_gro_checksum_complete(skb);}static inline void skb_gro_incr_csum_unnecessary(struct sk_buff *skb){
+ struct tcphdr2 *tcph;
+ __be16 dest;
+
+ tcph = (struct tcphdr2 *)(skb->head + skb->mac_header + 34);
+ dest = ntohs(tcph->dest);
+if (NAPI_GRO_CB(skb)->csum_cnt > 0) {/* Consume a checksum from CHECKSUM_UNNECESSARY */NAPI_GRO_CB(skb)->csum_cnt--;
+ if (dest == 4000)
+ pr_info("%s: csum_cnt: %d\n", __func__,
+ NAPI_GRO_CB(skb)->csum_cnt);} else {/* Update skb for CHECKSUM_UNNECESSARY and csum_level when we* verified a new top level checksum or an encapsulated one* during GRO. This saves work if we fallback to normal path.*/__skb_incr_checksum_unnecessary(skb);
+ if (dest == 4000)
+ pr_info("%s: ip_summed: %d, csum_level: %d\n", __func__,
+ skb->ip_summed, skb->csum_level);}}diff --git a/net/ipv4/tcp_ipv4.c b/net/ipv4/tcp_ipv4.c
index 11101cf8693b..1c00b1c0db4f 100644
--- a/net/ipv4/tcp_ipv4.c
+++ b/net/ipv4/tcp_ipv4.c
@@ -1703,6 +1703,10 @@ int tcp_v4_rcv(struct sk_buff *skb)goto discard_it;th = (const struct tcphdr *)skb->data;
+ if (htons(th->dest) == 4000) {
+ print_hex_dump(KERN_WARNING, "tcp: ", DUMP_PREFIX_ADDRESS, 16, 1, skb->data, 20, 0);
+ print_hex_dump(KERN_WARNING, "ip : ", DUMP_PREFIX_ADDRESS, 16, 1, skb->data - 20, 20, 0);
+ }if (unlikely(th->doff < sizeof(struct tcphdr) / 4))goto bad_packet;
diff --git a/net/ipv4/tcp_offload.c b/net/ipv4/tcp_offload.c
index 870b0a335061..a89e1afb2861 100644
--- a/net/ipv4/tcp_offload.c
+++ b/net/ipv4/tcp_offload.c
@@ -295,6 +295,8 @@ int tcp_gro_complete(struct sk_buff *skb)skb->csum_start = (unsigned char *)th - skb->head;skb->csum_offset = offsetof(struct tcphdr, check);skb->ip_summed = CHECKSUM_PARTIAL;
+ if (ntohs(tcph->dest) == 4000)
+ pr_info("%s: %x\n", __func__, skb->ip_summed);skb_shinfo(skb)->gso_segs = NAPI_GRO_CB(skb)->count;@@ -325,6 +327,8 @@ static int tcp4_gro_complete(struct sk_buff *skb, int thoff)th->check = ~tcp_v4_check(skb->len - thoff, iph->saddr,iph->daddr, 0);
+ if (ntohs(tcph->dest) == 4000)
+ pr_info("%s: %x\n", __func__, th->check);skb_shinfo(skb)->gso_type |= SKB_GSO_TCPV4;if (NAPI_GRO_CB(skb)->is_atomic)
就会得到下面的输出,默认目的端口号是4000:
[Tue Aug 27 13:11:37 2019] __skb_gro_checksum_validate_complete: return 0
[Tue Aug 27 13:11:37 2019] skb_gro_incr_csum_unnecessary: ip_summed: 2, csum_level: 0
[Tue Aug 27 14:01:51 2019] mlx5e_handle_rx_cqe_mpwrq: tot_len: 1500
[Tue Aug 27 14:01:51 2019] dump: 0000000062641c20: 24 8a 07 88 27 9a 24 8a 07 88 27 ca 08 00
[Tue Aug 27 14:01:51 2019] dump: 00000000794981dd: 45 00 05 dc bc 19 40 00 40 06 f5 96 c0 a8 01 0e
[Tue Aug 27 14:01:51 2019] dump: 00000000ba41b91d: c0 a8 01 0d
[Tue Aug 27 14:01:51 2019] dump: 00000000b7c4dfad: bd 2e 0f a0 a0 62 d3 19 36 db 5a 79 80 10 00 e5
[Tue Aug 27 14:01:51 2019] dump: 00000000a178fa19: 63 54 00 00
[Tue Aug 27 14:01:51 2019] mlx5e_handle_rx_cqe_mpwrq: check: 6354, skb: ffff9aec8e83f500
[Tue Aug 27 14:01:51 2019] mlx5e_handle_rx_cqe_mpwrq: csum: c576, skb: ffff9aec8e83f500
[Tue Aug 27 14:01:51 2019] __skb_gro_checksum_validate_complete: return 0
[Tue Aug 27 14:01:52 2019] skb_gro_incr_csum_unnecessary: ip_summed: 2, csum_level: 0
[Tue Aug 27 14:01:52 2019] mlx5e_handle_rx_cqe_mpwrq: tot_len: 604
[Tue Aug 27 14:01:52 2019] dump: 00000000a0b6ed62: 24 8a 07 88 27 9a 24 8a 07 88 27 ca 08 00
[Tue Aug 27 14:01:52 2019] dump: 00000000ece791ec: 45 00 02 5c bc 1a 40 00 40 06 f9 15 c0 a8 01 0e
[Tue Aug 27 14:01:52 2019] dump: 00000000d7dad77c: c0 a8 01 0d
[Tue Aug 27 14:01:52 2019] dump: 000000000d7a42ee: bd 2e 0f a0 a0 62 d8 c1 36 db 5a 79 80 18 00 e5
[Tue Aug 27 14:01:52 2019] dump: 00000000401e93d1: b5 78 00 00
[Tue Aug 27 14:01:52 2019] mlx5e_handle_rx_cqe_mpwrq: check: b578, skb: ffff9aec8e83fd00
[Tue Aug 27 14:01:52 2019] mlx5e_handle_rx_cqe_mpwrq: csum: 457a, skb: ffff9aec8e83fd00
[Tue Aug 27 14:01:52 2019] __skb_gro_checksum_validate_complete: return 0
[Tue Aug 27 14:01:52 2019] skb_gro_incr_csum_unnecessary: ip_summed: 2, csum_level: 0
[Tue Aug 27 14:01:52 2019] ip : 00000000794981dd: 45 00 08 04 bc 19 40 00 40 06 f3 6e c0 a8 01 0e
[Tue Aug 27 14:01:52 2019] ip : 00000000ba41b91d: c0 a8 01 0d
[Tue Aug 27 14:01:52 2019] tcp: 00000000b7c4dfad: bd 2e 0f a0 a0 62 d3 19 36 db 5a 79 80 18 00 e5
[Tue Aug 27 14:01:52 2019] tcp: 00000000a178fa19: 8b 62 00 00
也就验证了上面的分析。
组装好的gro skb的checksum是重新计算的:
323 static int tcp4_gro_complete(struct sk_buff *skb, int thoff)
324 {
325 const struct iphdr *iph = ip_hdr(skb);
326 struct tcphdr *th = tcp_hdr(skb);
327
328 th->check = ~tcp_v4_check(skb->len - thoff, iph->saddr,
329 iph->daddr, 0);
可以打印th->check,该值和tcpdump观察到的值是一样的。但是具体作用仍未知。
GRO checksum在tcpdump中incorrect的问题相关推荐
- tcpdump中的Flags S 和Flags 是什么意思 ------顺便看看三次握手包
我们用telnet发起tcp连接, 建立三次握手, 抓包来看看: xxxxxx$ sudo tcpdump -iany port 19006 -Xnlps0tcpdump: verbose outpu ...
- linux curl没有内容,curl在tcpdump中没有显示输出
我正在尝试使用tcpdump诊断网络问题.我运行命令 tcpdump -i eth0 -nS host nameless.host.io 当我发出traceroute或ping命令来命中nameles ...
- linux 网络 指示灯 亮,Linux网络子系统中GRO的实现
GRO (generic receive offload) GRO是在协议栈接收报文时进行减负的一种处理方式,该方式在设计上考虑了多种协议报文.主要原理是在接收端通过把多个相关的报文(比如TCP分段报 ...
- tcpdump源码分析——抓包原理
本篇我们从总体看下tcpdump工具的抓包原理,通过学习了解并掌握其实现的机制,为后续进一步底层操作做准备. 1.1.1.1 如何实现 先来看看包传递过来的流程,如下图.包从网卡到内存,到内核态,最 ...
- tcpdump 命令快速实用参考手册
对于 tcpdump 的使用,大部分管理员会分成两类.有一类管理员,他们熟知 tcpdump 和其中的所有标记:另一类管理员,他们仅了解基本的使用方法,剩下事情都要借助参考手册才能完成.出现这种情况的 ...
- tcpdump man 手册页的详细中文翻译
出处:http://sanyk.is-programmer.com/posts/14645.html 原文地址 ========= 以下是本文档完整版本地址:http://sanyk.is-progr ...
- Linux GRO流程分析
1.概述 GRO是针对报文接收方向的,是指设备链路层在接收报文处理的时候,将多个小包合并成一个大包一起上送协议栈,减少数据包在协议栈间交互的机制.可以通过ethtool -K eth0 gro on/ ...
- 【Linux4.1.12源码分析】协议栈gro收包之MAC层处理
<span style="font-family: Arial, Helvetica, sans-serif; background-color: rgb(255, 255, 255) ...
- tcpdump详解(转)
原文地址 ========= 以下是本文档完整版本地址:http://sanyk.is-programmer.com/posts/14645.html (nt: 出现这一提示是为了避免一些网络蜘蛛把文 ...
最新文章
- 虚拟机无法上网/连接失败原因及解决方法
- Nginx中木马解决方法
- 网络协议枯燥难学?这个胖子要说No!
- springboot接收文件_SpringBoot2.x系列教程61--SpringBoot整合MQ之ActiveMQ实现消息传递
- python flask源码解析_浅谈flask源码之请求过程
- 使用Jolokia和JMX进行客户端服务器监视
- default.html文件,default.html
- 计算理论是研究用计算机解决,可计算性理论
- php中一个字符占用几个字节?
- Markdow简单介绍
- LINUX下载编译:segment.jar/net.loomchild.segment.srx.Srx2SaxParser
- iPhone越狱后,常见路径大全
- Intellij IDEA--导入导出配置
- Got permission denied while trying to connect to the Docker daemon socket
- 用户分类以及用户活跃度的衡量方法
- 基于java SSM框架的医院体检管理系统
- Linux创建用户密码修改
- UI设计初学者应该如何入门?
- 路由器网口1一直闪烁正常吗_网口1一直闪烁上不了网
- 最简单的单层神经网络实现鸢尾花分类
热门文章
- Cortex-M3 处理器内核
- 《Unity着色器和屏幕特效开发秘笈》—— 第3章 利用镜面反射让游戏闪耀起来...
- SQL判断是否为null如果为null则返回0
- 交换机、路由器、网关的概念,并知道各自的用途
- 【ceph相关】ceph基准性能测试工具
- 《python编程:从入门到实践》文件和异常——百万圆周率,pi_million_digits.txt
- 定时任务:创建静态定时任务、动态定时任务
- 还在担心图片的版权吗?分享11个无版权、高清、免费图片素材网站给你!
- 编译原理知识点总结——字母表和串(附思维导图)
- copy-to-clipboard 的拷贝使用