ip dontfrag linux,Linux内核源码处理ICMP packet too big与DF

本文解析了ICMP packet too big的处理过程,重点关注TCP和UDP在MTU更新上的区别,探讨了TCP MSS、MTU和窗口大小的关系,并揭示了DF位的默认设置。文章还介绍了Linux内核中ICMP报文处理及DF标志的控制机制,以及系统配置对MTU发现的影响。
部署运行你感兴趣的模型镜像

RFC 1191

man 7 ip

结论ICMP packet too big

对ICMP packet too big的处理,TCP/UDP最终都对对应路由条目进行MTU更新。而TCP的MTU、MSS、窗口大小和最终段大小的关系比较复杂,目前没有看明白。

Don’t fragment

DF位的默认配置,受系统配置控制,Ubuntu 14.04默认开启MTU发现功能。推断结果:UDP大报文默认未置上,而TCP大报文默认置上。

Linux内核如何处理ICMP Packet too big

ICMP流程

报文类型:

1

223#define ICMP_DEST_UNREACH 3 /* Destination Unreachable */

43#define ICMP_FRAG_NEEDED 4 /* Fragmentation Needed/DF set */

icmp_rcv(struct sk_buff *skb),根据ICMP类型处理skb:

1icmp_pointers[icmph->type].handler(skb);

icmp_pointers的定义显示,ICMP_DEST_UNRAECH的handler为icmp_unreach,后者获取出ICMP头部的mtu后,投递给icmp_socket_deliver(skb, mtu)。

icmp_socket_deliver最终将skb和mtu值投递给ipprot->err_handler(skb, info);

TCP流程

更新路由的MTU,inet_csk_update_pmtu(struct sock *sk, u32 mtu)

找到路由inet_csk_rebuild_route(sk, &inet->cork.fl);

更新路由MTUdst->ops->update_pmtu(dst, sk, NULL, mtu);

tcp_v4_err,如果MTU变小,且可分片,则会tcp_sync_mss(struct sock *sk, u32 pmtu)。关于TCP的MSS与MTU相关的内容很多:

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

221274/* This function synchronize snd mss to current pmtu/exthdr set.

1275

1276 tp->rx_opt.user_mss is mss set by user by TCP_MAXSEG. It does NOT counts

1277 for TCP options, but includes only bare TCP header.

1278

1279 tp->rx_opt.mss_clamp is mss negotiated at connection setup.

1280 It is minimum of user_mss and mss received with SYN.

1281 It also does not include TCP options.

1282

1283 inet_csk(sk)->icsk_pmtu_cookie is last pmtu, seen by this function.

1284

1285 tp->mss_cache is current effective sending mss, including

1286 all tcp options except for SACKs. It is evaluated,

1287 taking into account current pmtu, but never exceeds

1288 tp->rx_opt.mss_clamp.

1289

1290 NOTE1. rfc1122 clearly states that advertised MSS

1291 DOES NOT include either tcp or ip options.

1292

1293 NOTE2. inet_csk(sk)->icsk_pmtu_cookie and tp->mss_cache

1294 are READ ONLY outside this function. --ANK (980731)

1295 */

处理TCP MSS

未看懂。

UDP流程

ping报文的处理也是类似,见ping_err。

Linux内核对DF的默认处理

经阅读代码,发现控制DF标志的地方主要有两处:

inet_sock.pmtudisc

sk_buff.local_df

以关键字pmtudisc和local_df做全局字符串搜索,发现对pmtudisc和local_df有赋值的地方很少。如下各小节分析。

另附:IP MTU DISCOVER相关宏

1

2

3

4

590/* IP_MTU_DISCOVER values */

91#define IP_PMTUDISC_DONT 0 /* Never send DF frames */

92#define IP_PMTUDISC_WANT 1 /* Use per route hints */

93#define IP_PMTUDISC_DO 2 /* Always DF */

94#define IP_PMTUDISC_PROBE 3 /* Ignore dst pmtu */

IP报文发送出口1

2

3

4

5

6

7

8

9

10

11382 if (ip_dont_fragment(sk, &rt->dst) && !skb->local_df)

383 iph->frag_off = htons(IP_DF);

384 else

385 iph->frag_off = 0;

248int ip_dont_fragment(struct sock *sk, struct dst_entry *dst)

249{

250 return inet_sk(sk)->pmtudisc == IP_PMTUDISC_DO ||

251 (inet_sk(sk)->pmtudisc == IP_PMTUDISC_WANT &&

252 !(dst_metric_locked(dst, RTAX_MTU)));

253}

AF_INET协议族

inet_create,依赖ipv4_config配置。该配置体现在/proc/sys/net/ipv4/ip_no_pmtu_disc,目前Ubuntu 14.04上默认ip_no_pmtu_disc=0,即由每个路由确定。

1

2

3

4374 if (ipv4_config.no_pmtu_disc)

375 inet->pmtudisc = IP_PMTUDISC_DONT;

376 else

377 inet->pmtudisc = IP_PMTUDISC_WANT;

系统配置

可用sysctl命令配置,或通过/etc/sysctl.conf配置文件配置ip_no_pmtu_disc值,最终体现在/proc/sys/net/ipv4/ip_no_pmtu_disc。源码链接。

ICMP报文

PS:ICMP报文不超过576字节的限制在icmp_send接口中有体现。

您可能感兴趣的与本文相关的镜像

Yolo-v8.3

Yolo-v8.3

Yolo

YOLO(You Only Look Once)是一种流行的物体检测和图像分割模型,由华盛顿大学的Joseph Redmon 和Ali Farhadi 开发。 YOLO 于2015 年推出,因其高速和高精度而广受欢迎

评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符  | 博主筛选后可见
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值