pxe boot 多网卡dhcp fail 分析及修复详解
Posted hello-Will
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了pxe boot 多网卡dhcp fail 分析及修复详解相关的知识,希望对你有一定的参考价值。
今天在调试linux启动的过程中发现 双网启动时候竟然只有一个网卡dhcp分配了ip
[2020-08-05 00:51:43.416382] root@atragon:~# ifconfig
[2020-08-05 00:51:44.167357] eth0 Link encap:Ethernet HWaddr xxxxxxxxxx:40
[2020-08-05 00:51:44.167357] Scope:Link
[2020-08-05 00:51:44.167357] UP BROADCAST RUNNING MULTICAST MTU:1500 Metric:1
[2020-08-05 00:51:44.167357] RX packets:1280 errors:0 dropped:0 overruns:0 frame:0
[2020-08-05 00:51:44.167357] TX packets:243 errors:0 dropped:0 overruns:0 carrier:0
[2020-08-05 00:51:44.167357] collisions:0 txqueuelen:1000
[2020-08-05 00:51:44.167357] RX bytes:105878 (103.3 KiB) TX bytes:16342 (15.9 KiB)
[2020-08-05 00:51:44.167357] Interrupt:16
[2020-08-05 00:51:44.167357]
[2020-08-05 00:51:44.167357] eth1 Link encap:Ethernet HWaddr xxxxxxxxx:41
[2020-08-05 00:51:44.167357] inet addr:192.168.1.84 Bcast:192.168.1.255 Mask:255.255.255.0
[2020-08-05 00:51:44.167357] Scope:Link
[2020-08-05 00:51:44.167357] UP BROADCAST RUNNING MULTICAST MTU:1500 Metric:1
[2020-08-05 00:51:44.167357] RX packets:174908 errors:0 dropped:0 overruns:0 frame:0
[2020-08-05 00:51:44.167357] TX packets:3893 errors:0 dropped:0 overruns:0 carrier:0
[2020-08-05 00:51:44.167357] collisions:0 txqueuelen:1000
[2020-08-05 00:51:44.167357] RX bytes:259647682 (247.6 MiB) TX bytes:251665 (245.7 KiB)
[2020-08-05 00:51:44.167357] Interrupt:17
查看启动log发现 eth0 eth1 都发起了dhcp ,但是其中一个超时了,只有一个dhcp成功,发现重启很多次,现象仍然一样,下面我们来debug一下。
[2020-08-05 00:42:15.481503] IP-Config: eth1 hardware address 00:60:48:57:b1:41 mtu 1500 DHCP RARP
[2020-08-05 00:42:52.274776] IP-Config: eth0 hardware address 00:60:48:57:b1:40 mtu 1500 DHCP RARP
[2020-08-05 00:42:52.274776] IP-Config: no response after 2 secs - giving up
[2020-08-05 00:42:52.274776] IP-Config: eth1 hardware address 00:60:48:57:b1:41 mtu 1500 DHCP RARP
[2020-08-05 00:42:52.274776] IP-Config: eth0 hardware address 00:60:48:57:b1:40 mtu 1500 DHCP RARP
[2020-08-05 00:42:52.274776] IP-Config: eth1 complete (dhcp from 192.168.1.3):
[2020-08-05 00:42:52.274776] address: 192.168.1.84 broadcast: 192.168.1.255 netmask: 255.255.255.0
[2020-08-05 00:42:52.274776] gateway: 192.168.1.1 dns0 : 0.0.0.0 dns1 : 0.0.0.0
[2020-08-05 00:42:52.274776] rootserver: 192.168.1.3 rootpath:
[2020-08-05 00:42:52.274776] filename : pxelinux.0
[2020-08-05 00:42:52.274776] TFTP server is at 192.168.1.3
现场重现
1:reboot重启机器,我们的dhcp server端是个linux 系统,于是我们开启了tcpdump抓包,制定端口抓包数,过滤udp 67 68 dhcp client/server
sudo tcpdump -i eth0 -c 6555 -s 0 'udp and port 67 and port 68' -vvv
抓包结果如下:
问题分析
不了解dhcp可以科普文章: http://www.023wg.com/message/message/cd_feature_dhcp_message_format.html
这篇文章有个小问题,一会我们进行纠正。
从tcpdump 的信息看到尾数分别为40 , 41的两个网卡,41网卡dhcp成功,而40网卡没有,40发出了dhcpdiscover 然后dhcpserver发出了dhcpoffer报文,后面就没有了40网卡dhcp的进一步消息,这里就是启动时候那个timeout的原因。
我们带着这样的一位为什么dhcpoffer以后就没有消息呢?
我们有两种思路
1:猜测验证法,client没收到offer? client 没发出request?
2:发现异常对比法,对比dhcp log发现其中的异常点为出发点查看?
如果我们修改文件系统,让系统启动后可以手动调试,在client抓取对应网卡的报文,我们会发现对应网卡没有收到offer, 而另外一个网卡却收到了不属于他的offer,而且报文是单播的。我们根据一下内容知道dhcp回复的报文 client是可以选择单播还是广播的,由于之前一个网卡已经分配了ip地址,而且是同一个网段的,所以在网络内形成了相应的路由转发表,单播报文按照第一个网卡的路径进行转发了,导致第二个网卡再去申请ip的时候到达不了对应的网卡,这里明确一点,同一台机器上的网卡默认情况下是不通的,所以不会互相转发。你可以用ping -I 指定端口做测试。到这里,我们似乎知道了怎么修复问题,修改标志位,设置成广播。
flags 2字节
此字段在BOOTP中保留未用,在DHCP中表示标志字段。
只有标志字段的最高位才有意义,其余的位均被置为0。
最左边的字段被解释为广播响应标志位,内容如下所示:
0:客户端请求服务器以单播形式发送响应报文
1:客户端请求服务器以广播形式发送响应报文
bug修复
那为什么都是klibc 的ipconfig 会有这个问题呢,怎么修复呢?
我们下载klibc的代码,搜索对应log信息发现再ipconfig 目录下的main.c有timeout 的报错信息,沿着这条线,我们找到了dhcp_proto.c 文件
static int dhcp_send(struct netdev *dev, struct iovec *vec)
struct bootp_hdr bootp;
char dhcp_hostname[SYS_NMLN+2];
int i = 4;
memset(&bootp, 0, sizeof(struct bootp_hdr));
bootp.op = BOOTP_REQUEST;
bootp.htype = dev->hwtype;
bootp.hlen = dev->hwlen;
bootp.xid = dev->bootp.xid;
bootp.ciaddr = INADDR_ANY;
# 源头在下面这行指定了具体地址,而且下面没有设置flag,默认单播
bootp.yiaddr = dev->ip_addr;
bootp.giaddr = INADDR_ANY;
bootp.secs = htons(time(NULL) - dev->open_time);
memcpy(bootp.chaddr, dev->hwaddr, 16);
修改方式
static int dhcp_send(struct netdev *dev, struct iovec *vec)
...
- bootp.yiaddr = dev->ip_addr;
+ bootp.yiaddr = INADDR_ANY;
+ bootp.flags = htons(0x800);
...
修改目前自己的ip 地址应该是没确定的,让server改动广播方式发送。
重启编译klic,打包文件系统,启动系统,两个网卡都能分配到ip了。
通过这个我们熟悉了网络的debug过程和对协议的更深的理解。
举一反三:上面是客户端多网卡申请同一个网段的ip的问题,那dhcp server多网卡会不会有什么问题呢? 大家可以自己调试看看。
以上是关于pxe boot 多网卡dhcp fail 分析及修复详解的主要内容,如果未能解决你的问题,请参考以下文章