dpvs icon indicating copy to clipboard operation
dpvs copied to clipboard

linux_set_if_mac: fail to set kni0's MAC address: Timer expired

Open hulinfan opened this issue 4 years ago • 1 comments

【现象描述】
使用dpdk 18.11的dpvs,在网口初始化流程netif_port_init中,网口初始化完成后添加kni_dev,并设置kni的MAC地址使其和物理口的一致。实际发现设置kni的MAC地址的时候总是超时,提示 "linux_set_if_mac: fail to set kni0's MAC address: Timer expired"。

【原因分析】
设置MAC地址的linux_set_if_mac是通过ioctl(..., SIOCSIFHWADDR, ...)实现的,系统调用最终会执行kni内核模块的ndo_set_mac_address,也即kni_net_set_mac,其中的kni_net_process_request,会把MAC地址的变动作为request放到kni fifo队列,并等待用户态从kni fifo队列取走request,用户态处理完毕回一个reply到kni fifo队列,此后kni内核模块的等待队列被唤醒,整个流程走完:

ioctl --> ndo_set_mac_address --> kni_net_set_mac --> kni_net_process_request --> kni_fifo_put(req) --> wait_event_interruptible_timeout -> kni_fifo_get(resp)  

问题出现在网口初始化的时候用户态没有执行kni_process_on_master响应kni内核模块的请求,导致wait event超时,ioctl返回'Timer expired'。事实上kni_process_on_master是在所有初始化完成后master线程的while循环里执行的,因此在网口初始化流程里企图改变kni口的一些信息如MAC地址、MTU等都会发生超时。以下回调凡是用了kni_net_process_request都会有这个问题:

static const struct net_device_ops kni_net_netdev_ops = {
	.ndo_open = kni_net_open,
	.ndo_stop = kni_net_release,
	.ndo_set_config = kni_net_config,
	.ndo_change_rx_flags = kni_net_set_promiscusity,
	.ndo_start_xmit = kni_net_tx,
	.ndo_change_mtu = kni_net_change_mtu,
	.ndo_do_ioctl = kni_net_ioctl,
	.ndo_set_rx_mode = kni_net_set_rx_mode,
	.ndo_get_stats = kni_net_stats,
	.ndo_tx_timeout = kni_net_tx_timeout,
	.ndo_set_mac_address = kni_net_set_mac,
#ifdef HAVE_CHANGE_CARRIER_CB
	.ndo_change_carrier = kni_net_change_carrier,
#endif
};

【影响范围】
影响程序启动的时间,每个port初始化都会3秒超时,程序启动将会拖长 3 * nr_ports 秒的时间。
不影响MAC地址的设置,kni口MAC地址仍能配置成功。

【为什么dpdk 17.11没有这个问题】
dpdk 17.11 的回调 kni_net_set_mac没有wait event的操作:

static int
kni_net_set_mac(struct net_device *netdev, void *p)
{
	struct sockaddr *addr = p;

	if (!is_valid_ether_addr((unsigned char *)(addr->sa_data)))
		return -EADDRNOTAVAIL;
	memcpy(netdev->dev_addr, addr->sa_data, netdev->addr_len);
	return 0;
}

【解决办法】
这个问题似乎是无解的,除非使用异步的方式设置MAC地址。

hulinfan avatar Nov 27 '19 09:11 hulinfan

用了18.11.10 dpdk也遇到上面的问题 第一次用17.11.2 编译遇到错误 看到有人说这是个bug 然后重新去官网下载了18.11.10 然后又碰到楼上的错误 目前的环境是KVM虚拟机

00:00.0 Host bridge: Intel Corporation 440FX - 82441FX PMC [Natoma] (rev 02) 00:01.0 ISA bridge: Intel Corporation 82371SB PIIX3 ISA [Natoma/Triton II] 00:01.1 IDE interface: Intel Corporation 82371SB PIIX3 IDE [Natoma/Triton II] 00:01.2 USB controller: Intel Corporation 82371SB PIIX3 USB [Natoma/Triton II] (rev 01) 00:01.3 Bridge: Intel Corporation 82371AB/EB/MB PIIX4 ACPI (rev 03) 00:02.0 VGA compatible controller: Cirrus Logic GD 5446 00:03.0 Ethernet controller: Red Hat, Inc. Virtio network device 00:04.0 USB controller: Intel Corporation 82801DB/DBM (ICH4/ICH4-M) USB2 EHCI Controller (rev 10) 00:05.0 USB controller: NEC Corporation uPD720200 USB 3.0 Host Controller (rev 03) 00:06.0 USB controller: Intel Corporation 82801DB/DBM (ICH4/ICH4-M) USB2 EHCI Controller (rev 10) 00:07.0 USB controller: NEC Corporation uPD720200 USB 3.0 Host Controller (rev 03) 00:08.0 SCSI storage controller: Red Hat, Inc. Virtio SCSI 00:09.0 Communication controller: Red Hat, Inc. Virtio console 00:0a.0 SCSI storage controller: Red Hat, Inc. Virtio block device 00:0b.0 Unclassified device [00ff]: Red Hat, Inc. Virtio memory balloon

tianya1993 avatar Nov 06 '20 15:11 tianya1993