网络管理常见问题指南
更新时间:2025/10/15
在Gitcode上查看源码

BMC 网络管理介绍

bmc_network组件主要完成网口的IPv4及IPv6地址配置,保障BMC的正常网络通信;涉及的主要有网口配置、网口切换、VLAN配置、LLDP、ARP、ICMPv6、DHCP及DHCPv6等处理。

1.1 网络常见信息

常见信息查询:

  • ifconfig -a:查询网卡驱动创建的设备节点

  • route -n:查询IPv4路由信息

  • route -A inet6:查询IPv6路由信息

  • ip neigh:查询邻居表

  • iptables -t filter -nvL:查询过滤规则

  • iptables -t nat -nvL:查询转换规则

1.2 网络常用命令

  • 配置为DHCP模式:ipmcset -d ipmode -v dhcp
  • 配置IPv4静态地址:busctl --user call bmc.kepler.bmc_network /bmc/kepler/Managers/1/EthernetInterfaces/Ipv4 bmc.kepler.Managers.EthernetInterfaces.Ipv4 SetIpMaskGateway a{ss}sss 1 a a 192.168.2.100 255.255.255.0 192.168.2.1
  • 配置IPv6静态地址:busctl --user call bmc.kepler.bmc_network /bmc/kepler/Managers/1/EthernetInterfaces/Ipv6 bmc.kepler.Managers.EthernetInterfaces.Ipv6 SetIpv6PrefixGateway a{ss}sis 3 Interface a UserName a ClientAddr a xxxx:xx:xxxx::x:xxxx 112 xxxx:xx:xxxx::x:xxxx
  • 切换到NCSI网口的第一个port:ipmcset -d ac -v 2 1
  • 切换到专用网口:ipmcset -d activeport -v 0
  • 日志级别设置为debug:busctl --user set-property bmc.kepler.bmc_network /bmc/kepler/bmc_network/MicroComponent bmc.kepler.MicroComponent.Debug DlogLevel 's' debug

1.3 网络常用协议

1.3.1 ARP协议

ARP(Address Resolution Protocol,地址解析协议)是根据IP地址获取物理地址的一个TCP/IP协议。

主机发送信息时将包含目标IP地址的ARP请求广播到局域网络上的所有主机,并接收返回消息,以此确定目标的物理地址;收到返回消息后将该IP地址和物理地址存入本机ARP缓存中并保留一定时间,下次请求时直接查询ARP缓存以节约资源。

1.3.2 DHCP协议

DHCP(Dynamic Host Configuration Protocol,动态主机配置协议),前身是BOOTP协议,是一个局域网的网络协议,使用UDP协议工作,统一使用两个IANA分配的端口:67(服务器端),68(客户端)。

DHCP通常被用于局域网环境,主要作用是集中的管理、分配IP地址,使client动态的获得IP地址、Gateway地址、DNS服务器地址等信息,并能够提升地址的使用率。

1.3.3 ICMPv6协议

ICMPv6(Internet Control Message Protocol for the IPv6)是IPv6的基础协议之一,定义在RFC2463中,协议类型号,IPv6 Next Header = 58。

  • 用于向源节点传递报文转发的信息或者错误
  • 广泛地应用于其它协议中,包括:邻居发现(Neighbor Discovery)、PathMTU发现机制等
  • 合并了IPv4中的ICMP(控制报文协议)、IGMP(组成员协议)、ARP(地址解析协议)、RARP(反向地址解析协议)和RA(路由广播)等多个协议的功能
  • ICMPv6协议控制着IPv6网络中的地址生成、地址解析、路由选择、以及差错控制等关键环节

BMC 网络管理常见问题

2.1 ssh登录BMC失败

  1. 执行ping操作,如果能ping通,联系技术支持定位ssh的问题
  2. 如果不能ping通,参考2.2定位步骤

2.2 PC执行到BMC的ping测试失败

  1. 串口登录参考1.1查询关键信息,比如网口、路由是否存在等
  2. wireshark抓包 ./tcpdump -i eth2 -s 0 -v -w caps_eth2.pcap,查看报文是否到达网口
  3. 查看iptables规则:报文是否被拦截等

2.3 ping BMC环境或用ssh登录BMC环境,时通时不通

  1. 原因:MAC地址冲突,在OS修改MAC地址解决
bash
ipmitool raw 0x30 0x90 0x44 0x02 0x20 0x22 0x01 0x90 0x85 0x3b

历史问题定位

3.1 环境存在PCIe口,自适应模式下,down掉eth2的网口,环境网口未切换到NCSI网口

  1. 自适应模式下,eth2为up状态时,并在专用口:

  1. 执行命令 ipmcset -t main -d ethlink -v eth2 disable,down掉网口eth2,预期eth2链接状态为down,实际为up:

  1. 执行命令 echo "0x3" > /proc/rsm/chknetdev,开启rtos网口监控:

  1. dmesg查看内核日志:

从中可以看到专用口eth2被down后,又被重新拉起来,且拉起它的进程PID为61776,此时通过ps命令查找对应进程为bmc_network

  1. 查找代码中执行eth_up的调用点,发现问题是清除网口信息时调用设置地址函数set_ip_address,且设置时会调用eth_up对网口进行up

3.2 将设备网口IPv4的mask清除后,外网ping依然能通

  1. 本地一直ping设备A的IP地址:

  1. 设备A后台执行 iptables -nvL,查看报文统计:

截图中accept报文一直没增加,证明报文没有到这个设备

  1. 从设备B上ping设备A并抓包:

可以看到回复设备的MAC地址

  1. 设备A后台查看MAC地址:

  1. 从步骤3中报文回复的MAC地址与设备A的MAC地址比对,发现是不一致的

结论: 响应ping包的设备不是设备A,环境中存在相同IP的其他设备

3.3 Redfish查询网络信息,概率性存在响应超时的现象

  1. 找到对应的redfish接口:

  1. 根据ProcessingFlow处理流程:拆分其中的步骤,定位是哪步有问题:

  1. 根据步骤的处理,后台通过命令验证:
bash
busctl --user get-property bmc.kepler.ddns /bmc/kepler/Managers/1/EthernetInterfaces/eth2/DNS bmc.kepler.Managers.EthernetInterfaces.DNS BackupNameServer

发现是该资源树访问超时,联系对应组件定位。

  1. 找到属性的路径及接口配置:ddns/mds/model.json

3.4 PC直连BMC管理口,IPv6本地链路地址不通

  1. 查看当前使用网口为专用口:

  1. 直连访问本地链路地址,查询IPv6路由:

  1. 查询IPv6邻居表:

  1. 切换到dhcp后,设备重启后,查询IPv6路由:

发现fe80::/64 dev eth2这条路由被删除,从而导致直连访问本地链路地址不通

  1. 手动增加路由后,能ping通:
bash
ip -6 addr del fe80::/128 dev eth2
  1. 发现是脚本default6_ip.script中执行命令 ip -6 route flush dev eth2 将路由清除掉:

3.5 使用iperf工具测试专用网口带宽速率,V3(28.8 MBytes/sec)低于V2(66MBytes/sec)一倍

定位指导参考《BMC性能问题定位》文档。

3.6 NCSI网口下,web升级BMC时间大于性能基线时间

  1. 问题背景:

自动化用例web升级BMC版本,耗时超过性能基线300s,导致用例失败

  1. 问题分析:

V2、V3及VPN速率对比测试:

  1. 分析结论:

从对比测试可以看出:

  • 不管是专用口还是NCSI口,经过VPN后性能下降幅度大,因为过VPN后数据包处理节点增加,导致处理时长增加,从而导致转发性能下降,符合预期
  • 测试性能规格,网络、ipmi、Redfish、web、snmp等,都是不能经过VPN的
  • 当前V3升级使用的是装备包比release包大10-20M,同样会导致传输时间加长

3.7 down掉网口导致bmc_network组件重启

  1. down网口:

  1. 查看framework.log日志,可见bmc_network消息队列持续增加:

  1. 排查思路:
  • 消息队列持续增加,说明消息一直得不到处理,CPU被某个流程一直占用
  • 排查与网口相关流程,重点是循环处理
  • 通过排查找到怀疑点:解析lldp报文时,启动的worker存在循环处理
  1. 结论分析:
  • worker中处理是收到lldp报文时,才会执行休眠处理
  • 当网口down时,判断网口状态为link_down,不会创建socket接收lldp报文,导致worker循环处理没有休眠处理
  • worker循环不休眠,CPU被完全占用,则其他的消息均无法处理,因此bmc_network的消息队列持续增加
  1. 解决方案:worker循环中休眠1秒让出CPU,避免CPU资源被完全占用

3.8 配置导出再导入,IP能ping通,web和ssh连不上

定位思路:

  1. 先查看iptables是否配置了端口转发规则

命令:iptables -t nat -nvL

若无以上规则,则不是bmc_network的问题,需联系nsm组件的owner进一步定位

  1. 发现有转发规则,查看文件:/proc/sys/net/ipv4/conf/%s/route_localnet

该文件为0则web和ssh不能连,进一步排查app.log,发现bmc_network有重启网络,清除旧网口的操作会导致该值变为0,日志关键字"clear_old_eth_info : old_eth_name ="

  1. 根因分析:导入时有切换网口的操作,代码中未做设置前后网口是否一样的判断,导致网络重启,清除旧网口,route_localnet文件被修改为0

  2. 解决方案:增加切换网口时设置前后网口是否一样的判断,若一样则不执行重启网络的操作

3.9 getifaddrs函数导致coredump

  1. 基本coredump问题定位:参考《coredump问题定位方法介绍》文档

  2. coredump文件解析:

  1. 网页搜索getifaddrs () from /lib64/libc.so.6:

https://blog.csdn.net/yetyongjin/article/details/130325590

得出问题原因可能与多个进程同时调用getifaddrs函数,导致访问已释放的fd产生crash

  1. 分析代码:多个进程可能同时调用

  2. 分析函数在bmc_network的作用,是获取IPv6的SLAAC地址

  3. 协议规定SLAAC地址是从RA报文来的,主要是前缀的获取,宏定义为NDISC_ROUTER_ADVERTISEMENT=134,在内核代码中搜索宏定义

  4. 查看代码中前缀的处理:

addrconf_prefix_rcv->addrconf_prefix_rcv_add_addr

注册文件处理,地址会写到该文件中:

  1. 参考文件内容,有需要的SLAAC地址:

结论: 将获取地址从调用getifaddrs函数改为读取文件的方式,降低与其他进程使用文件描述符的冲突

3.10 执行完平台的网络脚本后,ssh服务无法连接

  1. 问题定位思路:

查看iptables规则,input链和nat是否有ssh的端口(22)转发规则

排查规则中第一条是将22端口的包被drop掉了

  1. 问题分析:

iptables规则的配置是在iptables_cfg.sh脚本中统一配置,理论上不存在drop规则在最前面,排查调用脚本的地方,发现如果连续两次较快的调用脚本,脚本中既有删除又有添加的操作,导致最终规则乱序,存在并发的风险

  1. 问题解决:

将调用脚本的地方改成队列调用,保证串行

3.11 BIOS同时设置IP、掩码、网关,掩码和网关设置失败问题

问题分析过程:

  1. 查看日志发现有掩码、网关设置失败的日志

此处报错是socket创建失败导致的,怀疑是同时下发3条命令,socket并发创建,上一个socket还未释放又创建socket,导致后面创建socket创建失败,排查尝试加入socket重试创建机制,结果发现问题仍然存在

  1. 进一步排查代码增加日志,发现设置IP时fork的协程是在设置掩码中fork的协程后面执行的,导致设置IP时读到了数据库的旧掩码,又重新将旧掩码设置回去了

解决方案:

在设置IP的协程中重新读一下当前掩码、网关再设置,保证读到数据库最新的值

总结: 注意并发时对数据库的操作,保证时序不会影响最终结果

3.12 PC直连专用网口,IPv4地址ping不通

定位思路:

  1. 先排查网口上IP、掩码是否设置成功(命令:ifconfig

  1. 查看iptables规则是否正常,filter表是否配置该IP的规则或者有异常的drop规则(命令:iptables -nvL

  1. 查看 /proc/sys/net/ipv4/conf/eth2(此处是专用网口对应的网口名)/route_localnet是否为1,1才能通,0不能通

  1. 查看网络链路状态是否为linkup(命令:ipmcget -d eth

  1. 检查PC配置的IP是否和BMC的IP同网段

  2. 以上排查都没问题的话,考虑抓包分析,先抓PC上是否有ping包发出去,如果没有,则是PC问题(关闭防火墙);如果有ping包发出,BMC端未接收到ping包,考虑是驱动、硬件问题,交由下游端处理

3.13 带内通过veth发送接收IPMI命令,veth口能正常接收,但回包失败

  1. 发送命令,查看映射规则是否匹配成功

发送命令:

查看映射匹配成功:

  1. 抓取veth网口报文,可以看到只有收到从OS发送过来的报文,没有发出去的报文

  1. 查看邻居表

发送命令前:

发送命令后:

对比发现,发送命令后,会存在一条尝试eth2与OS的IPv6地址的链路层地址解析的数据,后面也会解析失败

  1. 为什么会出现eth2与OS的IPv6地址的链路层地址解析?

a. 原因是IPMI的响应报文,选择了从eth2口出去,而不是veth。因为eth2之前没有与OS的IPv6地址建立连接,没有地址表项,所以需要重新解析

b. 因为eth2与OS的网口没有硬件通路,肯定是不通的,这一点可以在发送IPMI命令时,抓eth2口的报文,可以看到从eth2发送了NS报文(地址解析),但是没有收到回复,所以第3点的链路地址会解析失败

  1. 为什么会选择从eth2出去?

a. rmcpd那边的代码收发包绑定的地址都是[::2]的环回地址,没有将收发报的socket分开,发包应该绑定veth网口的

b. 发包的源地址是[::2],那内核处理就会根据路由表进行网口的选择转发,当路由距离Metric相等时,就是根据路由表顺序选择

可以看到发送到fe80::/64的报文有3条路由,Metric都相等(可能没用),而eth2的路由在前面,则选择了从eth2口发送出去

  1. 修改路由表顺序后,IPMI命令正常:

3.14 NCSI网口下重启BMC后,port1与port2相互切换时,IPv6地址不通

  1. 查看ifconfig,网口上有IP地址

  2. 查看内核日志dmesg,有提示该IPv6地址冲突,并且冲突的MAC地址还是自身

  3. 为什么会收到自身发出的冲突检测?

  4. 抓包分析,发现有收到自己发出去的NA报文,导致内核认为此IPv6地址冲突,该地址失效

冲突检测机制: 内核设置IPv6地址时,会先发送NS报文,一秒内如果收到从该地址发送的NA报文则认为该地址冲突

  1. 为什么会收到自身发出的NA报文?

分析代码发现设置IPv6地址时,我们代码会主动发送NA报文,并且BMC初始化起来后,NCSI网口的port1和port2的RX都是打开的(都可以接收报文),导致从port1发送出去的NA组播报文被自身port2收回来了

  1. 解决方案:

设置IPv6地址时延时3s发送NA报文,避开冲突检测的1s

3.15 带外IPMI升级BMC成功后,BMC不通,查看IP变化为初始192.168.2.100;https不通、ssl证书丢失、数据库字段丢失

  1. 查看数据库,部分数据库表丢失,所以IP变为默认值192.168.2.100

  2. 查看linux_kernel_log文件(对应一键收集日志dump_info/LogDump/linux_kernel_log),经定位根因是环境升级前设置了datafs_reset标志,触发了深度还原导致分区数据全部丢失

  1. 深度还原执行操作方法,可参考文档《使用串口切换分区/恢复出厂》

常见用法避雷

4.1 select函数的timeout用法

timeout是select的超时时间,这个参数至关重要,它可以使select处于三种状态:

第一,若将NULL以形参传入,即不传入时间结构,就是将select置于阻塞状态,一定等到监视文件描述符集合中某个文件描述符发生变化为止;

第二,若将时间值设为0秒0毫秒,就变成一个纯粹的非阻塞函数,不管文件描述符是否有变化,都立刻返回继续执行,文件无变化返回0,有变化返回一个正值;

第三,timeout的值大于0,这就是等待的超时时间,即select在timeout时间内阻塞,超时时间之内有事件到来就返回了,否则在超时后不管怎样一定返回,返回值同上述。

select的超时机制与循环结合使用时,对于timeout,每次都要初始化其值,否则timeout会减去上一次超时时间,例如初始化时设置了超时时间为3s,第一次2s收到了报文,则下一次进入循环后超时时间会变成1s,与实际想要实现的超时机制不符,出现业务错误。

例如以下这段代码必须要在while循环内重新初始化超时时间,才能达到每次超时时间为固定值的效果:

c
//使用select函数的示例(程序段):
int Read(int fd, char *readbuf, int BUFSIZE)
{
  int len = 0;
  int nfds,select_ret;
  struct timeval timeout;
  fd_set readfds;
  FD_ZERO(&readfds);
  FD_SET(fd, &readfds); 
  nfds=fd+1;
  timeout.tv_sec = 1;
  timeout.tv_usec = 500000;
  while ((select_ret = select(nfds, &readfds, NULL, NULL, &timeout)) > 0)
  {
    len += read(fd, readbuf + len, BUFSIZE);
    FD_ZERO(&readfds);
    FD_SET(fd, &readfds); 
    nfds=fd+1;
    timeout.tv_sec = 0;
    timeout.tv_usec = 500000;
  }
  readbuf[len]='\0';

  return len;
}