rt-thread icon indicating copy to clipboard operation
rt-thread copied to clipboard

netif->name与netdev的网卡名称的问题

Open windsgo opened this issue 2 years ago • 14 comments

芯片: STM32F407IGT6 RT-Thread版本: 4.0.3 lwip版本: 2.0.2(RT-Thread自带) 工具链: RT-Thread Studio 2.2.6 202211231640

  • 问题描述:

我在我的板子上有两个网口,一个使用STM32F407默认的网卡+DM9161的PHY芯片,使用RT-Thread提供的物理层驱动注册网卡;另一个使用FSMC+DM9000A的方案,自己写了个DM9000的物理层驱动,最后调用eth_device_init()函数完成初始化。

实际使用时,两个网卡分别插网线,都能实现dhcp自动分配ip地址,并完成通信。

目前的问题是,串口终端输入ifconfig命令时,并不能准确的打印出netdev网卡模块中的设备信息,描述如下:

  1. 我将两个网卡分别(上述顺序)在eth_device_init()函数中注册为"e0"和"e1"两个名字
  2. 在ifconfig中只能显示出"e0"的正确ip等信息,"e1"网卡虽有该条目,但ip等信息均为0.0.0.0等空信息 效果如下
msh />ifconfig
network interface device: e0
MTU: 1500
MAC: 00 80 e1 15 41 51
FLAGS: UP LINK_UP INTERNET_DOWN DHCP_ENABLE ETHARP BROADCAST IGMP
ip address: 192.168.50.198
gw address: 192.168.50.1
net mask  : 255.255.255.0
dns server #0: 192.168.50.1
dns server #1: 0.0.0.0

network interface device: e1 (Default)
MTU: 1500
MAC: 02 ab cd ef a3 3e
FLAGS: DOWN LINK_DOWN INTERNET_DOWN DHCP_ENABLE
ip address: 0.0.0.0
gw address: 0.0.0.0
net mask  : 0.0.0.0
dns server #0: 0.0.0.0
dns server #1: 0.0.0.0

但此时网卡e1是可以被ping通的,(ip是从netif和dhcp调试打印中获知的)

  1. 经过对lwip和netdev的代码加入打印和调试,发现问题出在lwip/src/core/netif.c中的void netif_set_ipaddr(struct netif *netif, const ip4_addr_t *ipaddr)函数中的最后
#ifdef RT_USING_NETDEV
    /* rt-thread sal network interface device set IP address operations */
    rt_kprintf("netif->name:%s, find_res:%s\n", netif->name, netdev_get_by_name(netif->name)->name);
    netdev_low_level_set_ipaddr(netdev_get_by_name(netif->name), &netif->ip_addr);
#endif /* RT_USING_NETDEV */

在这里打印时,网卡"e0"可以被找到,但网卡”e1“在调用netdev_get_by_name(netif->name)时返回空指针,阅读代码后发现,netif->name的定义是char[2],而netdev_get_by_name()函数中使用了rt_strncmp来查找网卡名称,netdev本身是使用const char*来存储网卡名称的,这两者存在name上的差异,导致可能由于netif的name没有\0结尾而导致查找失败。

  • 可能的解决方案
  1. 网卡名称只用一个字符
  2. 在netif中用name查找netdev设备时,对name进行一下转化
  3. 或者还有我没考虑到的问题,请大佬指正

windsgo avatar Aug 02 '23 03:08 windsgo

这里只展示了ip显示错误的原因,其他条目,包括FLAGS中的打印也是如此原因

windsgo avatar Aug 02 '23 03:08 windsgo

将第二块网卡改名为长度为1的字符串"d"后,打印就正常了,如下:

msh />ifconfig
network interface device: e0 (Default)
MTU: 1500
MAC: 00 80 e1 15 41 51
FLAGS: UP LINK_DOWN INTERNET_DOWN DHCP_ENABLE ETHARP BROADCAST IGMP
ip address: 0.0.0.0
gw address: 0.0.0.0
net mask  : 0.0.0.0
dns server #0: 192.168.50.1
dns server #1: 0.0.0.0

network interface device: d
MTU: 1500
MAC: 02 ab cd ef a3 3e
FLAGS: UP LINK_UP INTERNET_DOWN DHCP_ENABLE ETHARP BROADCAST IGMP
ip address: 192.168.50.186
gw address: 192.168.50.1
net mask  : 255.255.255.0
dns server #0: 192.168.50.1
dns server #1: 0.0.0.0

备注:上述打印时网口1未插网线,但插了网线第二块网卡也是正常的

windsgo avatar Aug 02 '23 03:08 windsgo

ncmp传入的长度参数是1还是2?如果是2,此时应该会忽略第2个字符之后的内容的吧?

可以单步调下ncmp里面。或改用strncmp对比下

aozima avatar Aug 02 '23 03:08 aozima

ncmp传入的长度参数是1还是2?如果是2,此时应该会忽略第2个字符之后的内容的吧?

可以单步调下ncmp里面。或改用strncmp对比下

请教一下ncmp是在哪里看,我感觉问题应该就是这个查找netdev的时候没考虑到netif的name属性不是一个标准的字符串?

windsgo avatar Aug 02 '23 03:08 windsgo

没考虑到netif的name属性不是一个标准的字符串?

所以这里用了ncmp,而不是直接strcmp。 代码在这 https://github.com/RT-Thread/rt-thread/blob/f5fe1a5d7b9117339ffce00035fd58a2c0ff3f3a/src/kservice.c#L563

多网口在多个项目中用过,所以你这里我感觉是第2个网卡的名称及配置信息与netdev中不同步,而非名称对比不成功,毕竟第1个成功了,且你第2个网卡虽然显示为0却实际有IP还能ping通。

aozima avatar Aug 02 '23 04:08 aozima

没考虑到netif的name属性不是一个标准的字符串?

所以这里用了ncmp,而不是直接strcmp。 代码在这

https://github.com/RT-Thread/rt-thread/blob/f5fe1a5d7b9117339ffce00035fd58a2c0ff3f3a/src/kservice.c#L563

多网口在多个项目中用过,所以你这里我感觉是第2个网卡的名称及配置信息与netdev中不同步,而非名称对比不成功,毕竟第1个成功了,且你第2个网卡虽然显示为0却实际有IP还能ping通。

我用e1时,用netif->name查询netdev会失败,此时netif->name可以被正确printf出来是e1。用常量字符串"e1"查询netdev却可以查询成功

windsgo avatar Aug 02 '23 04:08 windsgo

ncmp传入的长度参数是1还是2?如果是2,此时应该会忽略第2个字符之后的内容的吧?

可以单步调下ncmp里面。或改用strncmp对比下

ncmp传入的貌似是netdev中定义的一个最大名字长度的宏

windsgo avatar Aug 02 '23 04:08 windsgo

没考虑到netif的name属性不是一个标准的字符串?

所以这里用了ncmp,而不是直接strcmp。 代码在这 https://github.com/RT-Thread/rt-thread/blob/f5fe1a5d7b9117339ffce00035fd58a2c0ff3f3a/src/kservice.c#L563

多网口在多个项目中用过,所以你这里我感觉是第2个网卡的名称及配置信息与netdev中不同步,而非名称对比不成功,毕竟第1个成功了,且你第2个网卡虽然显示为0却实际有IP还能ping通。

我用e1时,用netif->name查询netdev会失败,此时netif->name可以被正确printf出来是e1。用常量字符串"e1"查询netdev却可以查询成功

我曾经试过把第一块网卡直接不初始化,系统中只有一块网卡,第二块网卡一样的初始化流程,命名为e1,最后ifconfig出来是正确的

windsgo avatar Aug 02 '23 04:08 windsgo

/> > 没考虑到netif的name属性不是一个标准的字符串?

所以这里用了ncmp,而不是直接strcmp。 代码在这

https://github.com/RT-Thread/rt-thread/blob/f5fe1a5d7b9117339ffce00035fd58a2c0ff3f3a/src/kservice.c#L563

多网口在多个项目中用过,所以你这里我感觉是第2个网卡的名称及配置信息与netdev中不同步,而非名称对比不成功,毕竟第1个成功了,且你第2个网卡虽然显示为0却实际有IP还能ping通。

单步调试进入netdev_get_by_name中发现,传入的netif->name变成了如下图: image

传入参数的地址是没有错的,但是传入参数后貌似出现了问题

传入前,netif->name查看如下: image

作为对比,传入常量字符串"e1"进行查询时,进入netdev_get_by_name中的name如下: image

windsgo avatar Aug 02 '23 04:08 windsgo

ncmp传入的长度参数是1还是2?如果是2,此时应该会忽略第2个字符之后的内容的吧?

可以单步调下ncmp里面。或改用strncmp对比下

所以我觉得对于netif中要操作netdev的地方,查找网卡是不是单独写一个用netif->name查找netdev的函数,比netdev的那个按名称查找函数的通用方法要更合适,这个地方估计就是因为没用终止符导致查找错误的,再加上第二块网卡会把netif->name后一个netif->num从0变成1,如图: image

所以导致了字符串识别失败了 @aozima

windsgo avatar Aug 02 '23 05:08 windsgo

/我测试了一下,实际再netif.c中加入如下代码就一切正常了

static struct netdev* netif_get_netdev_by_netifname(const char* netifname)
{
    char temp[3] = {0};
    rt_strncpy(temp, netifname, 2);
    return netdev_get_by_name(temp);
}
#define netdev_get_by_name netif_get_netdev_by_netifname

输出如下:

msh />ifconfig
network interface device: e0
MTU: 1500
MAC: 00 80 e1 15 41 51
FLAGS: UP LINK_DOWN INTERNET_DOWN DHCP_ENABLE ETHARP BROADCAST IGMP
ip address: 192.168.50.198
gw address: 192.168.50.1
net mask  : 255.255.255.0
dns server #0: 192.168.50.1
dns server #1: 0.0.0.0

network interface device: e1 (Default)
MTU: 1500
MAC: 02 ab cd ef a3 3e
FLAGS: UP LINK_UP INTERNET_UP DHCP_ENABLE
ip address: 192.168.50.186
gw address: 192.168.50.1
net mask  : 255.255.255.0
dns server #0: 0.0.0.0
dns server #1: 0.0.0.0

@aozima 您觉得这能解释我所说的问题吗,以及这属于一个bug吗还是这是我的板子或者开发环境特有的原因导致的。这个如果是一个bug可以提一个pr吗?

windsgo avatar Aug 02 '23 05:08 windsgo

将第二块网卡改名为长度为1的字符串"d"后,打印就正常了,如下:

msh />ifconfig
network interface device: e0 (Default)
MTU: 1500
MAC: 00 80 e1 15 41 51
FLAGS: UP LINK_DOWN INTERNET_DOWN DHCP_ENABLE ETHARP BROADCAST IGMP
ip address: 0.0.0.0
gw address: 0.0.0.0
net mask  : 0.0.0.0
dns server #0: 192.168.50.1
dns server #1: 0.0.0.0

network interface device: d
MTU: 1500
MAC: 02 ab cd ef a3 3e
FLAGS: UP LINK_UP INTERNET_DOWN DHCP_ENABLE ETHARP BROADCAST IGMP
ip address: 192.168.50.186
gw address: 192.168.50.1
net mask  : 255.255.255.0
dns server #0: 192.168.50.1
dns server #1: 0.0.0.0

备注:上述打印时网口1未插网线,但插了网线第二块网卡也是正常的

这个感觉是存在问题的,欢迎PR (可能需要注意下,需要考虑到多种情况)

BernardXiong avatar Oct 08 '23 07:10 BernardXiong

将第二块网卡改名为长度为1的字符串"d"后,打印就正常了,如下:

msh />ifconfig
network interface device: e0 (Default)
MTU: 1500
MAC: 00 80 e1 15 41 51
FLAGS: UP LINK_DOWN INTERNET_DOWN DHCP_ENABLE ETHARP BROADCAST IGMP
ip address: 0.0.0.0
gw address: 0.0.0.0
net mask  : 0.0.0.0
dns server #0: 192.168.50.1
dns server #1: 0.0.0.0

network interface device: d
MTU: 1500
MAC: 02 ab cd ef a3 3e
FLAGS: UP LINK_UP INTERNET_DOWN DHCP_ENABLE ETHARP BROADCAST IGMP
ip address: 192.168.50.186
gw address: 192.168.50.1
net mask  : 255.255.255.0
dns server #0: 192.168.50.1
dns server #1: 0.0.0.0

备注:上述打印时网口1未插网线,但插了网线第二块网卡也是正常的

这个感觉是存在问题的,欢迎PR (可能需要注意下,需要考虑到多种情况)

您好,请问PR的目标分支选择哪一个分支;lwip在master分支下有多个版本,是否多个版本均要进行修复?

windsgo avatar Oct 30 '23 01:10 windsgo

将第二块网卡改名为长度为1的字符串"d"后,打印就正常了,如下:

msh />ifconfig
network interface device: e0 (Default)
MTU: 1500
MAC: 00 80 e1 15 41 51
FLAGS: UP LINK_DOWN INTERNET_DOWN DHCP_ENABLE ETHARP BROADCAST IGMP
ip address: 0.0.0.0
gw address: 0.0.0.0
net mask  : 0.0.0.0
dns server #0: 192.168.50.1
dns server #1: 0.0.0.0

network interface device: d
MTU: 1500
MAC: 02 ab cd ef a3 3e
FLAGS: UP LINK_UP INTERNET_DOWN DHCP_ENABLE ETHARP BROADCAST IGMP
ip address: 192.168.50.186
gw address: 192.168.50.1
net mask  : 255.255.255.0
dns server #0: 192.168.50.1
dns server #1: 0.0.0.0

备注:上述打印时网口1未插网线,但插了网线第二块网卡也是正常的

这个感觉是存在问题的,欢迎PR (可能需要注意下,需要考虑到多种情况)

已提交一个PR,PR

windsgo avatar Oct 30 '23 03:10 windsgo