82599ES 光口無法通過大包的問題記錄

問題

參考 DPDK 例子程序 ip_fragment.c 來實現分片。

無論 I350 電口 還是 82599ES 光口,小包都是可以通過的。
但是在大包的時候,82599ES 光口就有問題。

場景 I350 電口 82599ES 光口
啓用 tx checksum offload 小包可以通過 小包可以通過
啓用 tx checksum offload 小包可以通過 小包可以通過
啓用 tx checksum offload 大包可以通過 大包不可以通過
不用 tx checksum offload,CPU 填充 checksum 大包可以通過 大包不可以通過

分析

由於使用了 CPU 填充 checksum 也有問題。所以排除 tx checksum offload 的問題。
因爲 DPDK 後的報文,會由多個 segment 組成,所以懷疑 82599ES 光口 的發包函數不支持 多 segment 的 報文發送。
所以要查看發包函數。

查看驅動類型

# get 82599ES pci address 
lspci | grep Eth
>	08:00.1 Ethernet controller: Intel Corporation 82599ES 10-Gigabit SFI/SFP+ Network Connection (rev 01)	

# get 82599ES device id
cat  /sys/bus/pci/devices/0000:08:00.0/device
>	0x10fb

從 0x10fb 得出 82599ES 的 設置類型爲 IXGBE_DEV_ID_82599_SFP,所以 82599ES 使用的是 ixgbe 的驅動。

查看發包函數

ixgbe 的驅動的 發包函數有三個。

發包函數 描述
ixgbe_xmit_pkts_vec 萬兆 Rx Vector enabled
ixgbe_xmit_pkts_simple 萬兆 Tx simple
ixgbe_xmit_pkts 萬兆 默認發包函數

使用 gdb 對以上函數來打斷點。確認當前的是 ixgbe_xmit_pkts_vec 發包函數。

發包函數的設置

查看驅動的 ixgbe_set_tx_function 函數的代碼。發現不同發包函數原來是有區別的:

ixgbe_set_tx_function(struct rte_eth_dev *dev, struct ixgbe_tx_queue *txq)
{
	/* Use a simple Tx queue (no offloads, no multi segs) if possible */		// <-- no offloads, no multi segs supports
	if (((txq->txq_flags & IXGBE_SIMPLE_FLAGS) == IXGBE_SIMPLE_FLAGS)
			&& (txq->tx_rs_thresh >= RTE_PMD_IXGBE_TX_MAX_BURST)) {
		PMD_INIT_LOG(DEBUG, "Using simple tx code path");
#ifdef RTE_IXGBE_INC_VECTOR
		if (txq->tx_rs_thresh <= RTE_IXGBE_TX_MAX_FREE_BUF_SZ &&
				(rte_eal_process_type() != RTE_PROC_PRIMARY ||
					ixgbe_txq_vec_setup(txq) == 0)) {
			PMD_INIT_LOG(DEBUG, "Vector tx enabled.");
			dev->tx_pkt_burst = ixgbe_xmit_pkts_vec;							// <-- DON'T WORK 
		} else
#endif
		dev->tx_pkt_burst = ixgbe_xmit_pkts_simple;								// <-- DON'T WORK
	} else {
		PMD_INIT_LOG(DEBUG, "Using full-featured tx code path");				// <-- offloads, multi segs supports
		PMD_INIT_LOG(DEBUG,
				" - txq_flags = %lx " "[IXGBE_SIMPLE_FLAGS=%lx]",
				(unsigned long)txq->txq_flags,
				(unsigned long)IXGBE_SIMPLE_FLAGS);
		PMD_INIT_LOG(DEBUG,
				" - tx_rs_thresh = %lu " "[RTE_PMD_IXGBE_TX_MAX_BURST=%lu]",
				(unsigned long)txq->tx_rs_thresh,
				(unsigned long)RTE_PMD_IXGBE_TX_MAX_BURST);
		dev->tx_pkt_burst = ixgbe_xmit_pkts;									// <-- WORK
	}
}

總結一下,可以得出不同發包函數的區別如下:

發包函數 是否支持offload, 和 多 segment 的 報文
ixgbe_xmit_pkts_vec
ixgbe_xmit_pkts_simple
ixgbe_xmit_pkts 是(全功能)

看來 82599ES 需要使用 ixgbe_xmit_pkts 才支持offload, 和 多 segment。

修改方法

參考 DPDK 例子程序 ip_fragment.c 的代碼。
設置 txq_flags 爲 0,使用 ixgbe_xmit_pkts 發包函數,就可以支持 offload 和 多 segment 的 報文 發送。

ip_fragment.c 的代碼:

main()
{
	/* ... */

		/* init one TX queue per couple (lcore,port) */
		for (lcore_id = 0; lcore_id < RTE_MAX_LCORE; lcore_id++) {
			if (rte_lcore_is_enabled(lcore_id) == 0)
				continue;

			socket = (int) rte_lcore_to_socket_id(lcore_id);

			/* set txq_flags to ZERO, 
			 *   to use defualt tx function (ixgbe_xmit_pkts), 
			 *   which support multi-segment and offload for ixgbe driver 
			 *   with NIC 82599ES (device: IXGBE_DEV_ID_82599_SFP). 
			 *   reference: example of ip_fragmentation.c, DPDK. 
			 */
			rte_eth_dev_info_get(portid, &dev_info);
			txconf = &dev_info.default_txconf;
			txconf->txq_flags = 0;				/* <-- use defualt tx function */
			ret = rte_eth_tx_queue_setup(portid, queueid, nb_txd,
						     socket, txconf);
			if (ret < 0) {
				printf("\n");
				rte_exit(EXIT_FAILURE, "rte_eth_tx_queue_setup: "
					"err=%d, port=%d\n", ret, portid);
			}
		}

	/* ... */
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章