ethtool 支持 dump x710 网卡寄存器

23 篇文章 1 订阅

ethtool 支持 dump i40e 网卡的寄存器

最新版 ethtool 支持如下网卡的 dump:

static const struct {
	const char *name;
	int (*func)(struct ethtool_drvinfo *info, struct ethtool_regs *regs);

} driver_list[] = {
#ifdef ETHTOOL_ENABLE_PRETTY_DUMP
	{ "8139cp", realtek_dump_regs },
	{ "8139too", realtek_dump_regs },
	{ "r8169", realtek_dump_regs },
	{ "de2104x", de2104x_dump_regs },
	{ "e1000", e1000_dump_regs },
	{ "e1000e", e1000_dump_regs },
	{ "igb", igb_dump_regs },
	{ "ixgb", ixgb_dump_regs },
	{ "ixgbe", ixgbe_dump_regs },
	{ "ixgbevf", ixgbevf_dump_regs },
	{ "natsemi", natsemi_dump_regs },
	{ "e100", e100_dump_regs },
	{ "amd8111e", amd8111e_dump_regs },
	{ "pcnet32", pcnet32_dump_regs },
	{ "fec_8xx", fec_8xx_dump_regs },
	{ "ibm_emac", ibm_emac_dump_regs },
	{ "tg3", tg3_dump_regs },
	{ "skge", skge_dump_regs },
	{ "sky2", sky2_dump_regs },
	{ "vioc", vioc_dump_regs },
	{ "smsc911x", smsc911x_dump_regs },
	{ "at76c50x-usb", at76c50x_usb_dump_regs },
	{ "sfc", sfc_dump_regs },
	{ "st_mac100", st_mac100_dump_regs },
	{ "st_gmac", st_gmac_dump_regs },
	{ "et131x", et131x_dump_regs },
	{ "altera_tse", altera_tse_dump_regs },
	{ "vmxnet3", vmxnet3_dump_regs },
	{ "fjes", fjes_dump_regs },
	{ "lan78xx", lan78xx_dump_regs },
	{ "dsa", dsa_dump_regs },
	{ "fec", fec_dump_regs },
#endif
};

可以看到列表中没有 i40e 网卡,这意味着我们要 dump i40e 驱动支持的网卡需要自己编写单独的解析函数并注册到上述列表中。

ethtool dump 网卡寄存器的主要工作原理

  1. ethtool 中首先通过 ioctl 调用底层驱动实现的 get_regs_len 函数,获取到 dump 寄存器的大小
  2. ethtool 使用获取到的寄存器空间大小申请内存空间
  3. 调用驱动中实现的 get_regs 函数来读取寄存器信息,并填充到之前申请的内存空间中
  4. 最后 在ethtool 中调用适配的不同网卡驱动的 dump_regs 函数来解析并打印读取到的寄存器值

ethtool.c 中解析获取到的寄存器值的函数

ethtool.c 中的 dump_regs 函数完成解析 dump 出来的寄存器信息的功能。

对于 gregs_dump_hex 为 0 的情况,它会遍历 driver_list 列表,这就是上面我列出来的那个很长的表喽,它会用 info->driver 中的驱动名称****匹配 driver_list,匹配到了一个则调用相应的 func 函数来完成寄存器解析工作,因为可能存在嵌套的 regs 结构体内容,这个过程会不断的递归执行

对于这种没有单独的解析函数的网卡,ethtool 中将会调用 dump_hex 以十六进制格式进行输出。

dump_regs 函数源码如下:

static int dump_regs(int gregs_dump_raw, int gregs_dump_hex,
		     struct ethtool_drvinfo *info, struct ethtool_regs *regs)
{
	int i;

	if (gregs_dump_raw) {
		fwrite(regs->data, regs->len, 1, stdout);
		goto nested;
	}

	if (!gregs_dump_hex)
		for (i = 0; i < ARRAY_SIZE(driver_list); i++)
			if (!strncmp(driver_list[i].name, info->driver,
				     ETHTOOL_BUSINFO_LEN)) {
				if (driver_list[i].func(info, regs) == 0)
					goto nested;
				/* This version (or some other
				 * variation in the dump format) is
				 * not handled; fall back to hex
				 */
				break;
			}

	dump_hex(stdout, regs->data, regs->len, 0);

nested:
	/* Recurse dump if some drvinfo and regs structures are nested */
	if (info->regdump_len > regs->len + sizeof(*info) + sizeof(*regs)) {
		info = (struct ethtool_drvinfo *)(&regs->data[0] + regs->len);
		regs = (struct ethtool_regs *)(&regs->data[0] + regs->len + sizeof(*info));

		return dump_regs(gregs_dump_raw, gregs_dump_hex, info, regs);
	}

	return 0;
}

ethtool 支持 dump i40e 网卡寄存器需要修改的文件

  1. 修改内核中的 i40e 源码添加 get_regs_len 与 get_regs 函数

    参考 i40e_register.h 头文件中的寄存器定义来搞

  2. 修改 ethtool 命令的源码

    增加一个 i40e.c,其中编写 i40e 寄存器内容的解析函数

    同时在 ethtool driver_list 中添加一个 i40e driver 表项

  3. 修改 ethtool 命令的编译脚本

ixgbe 内核态驱动中 dump 寄存器的实现参考

ixgbe 内核态驱动中 ixgbe_get_regs 函数的部分实现如下:

static void ixgbe_get_regs(struct net_device *netdev, struct ethtool_regs *regs,
			   void *p)
{
	struct ixgbe_adapter *adapter = netdev_priv(netdev);
	struct ixgbe_hw *hw = &adapter->hw;
	u32 *regs_buff = p;
	u8 i;
	
	memset(p, 0, IXGBE_REGS_LEN * sizeof(u32));

	regs->version = (1 << 24) | hw->revision_id << 16 | hw->device_id;

	/* General Registers */
	regs_buff[0] = IXGBE_READ_REG(hw, IXGBE_CTRL);
	//printk(KERN_DEBUG "ixgbe_get_regs_3\n");
	regs_buff[1] = IXGBE_READ_REG(hw, IXGBE_STATUS);
	regs_buff[2] = IXGBE_READ_REG(hw, IXGBE_CTRL_EXT);
	regs_buff[3] = IXGBE_READ_REG(hw, IXGBE_ESDP);
	regs_buff[4] = IXGBE_READ_REG(hw, IXGBE_EODSDP);
	regs_buff[5] = IXGBE_READ_REG(hw, IXGBE_LEDCTL);
	regs_buff[6] = IXGBE_READ_REG(hw, IXGBE_FRTIMER);

可以看到,上述代码的主要逻辑在于不断调用 IXGBE_READ_REG 来读取不同偏移量代表的寄存器的值并存储到相应的 buf 中,其实没有啥技术含量,不过要细心一点。

i40e 网卡的特别之处

i40e 网卡内部实现了一个 admin queue,一部分读写寄存器的操作被建议通过调用 i40e_asq_send_command 来发送一个相应的命令来获取,其实也可以直接读取寄存器的值。

最终的方案

dump i40e 寄存器的功能写了一些,发现了 ethregs 这个命令,发现它可以直接 dump x710 网卡的寄存器,就使用这个工具来搞了。

关于 ethregs 工具,可以从我的 ethregs dump Intel 网卡寄存器工具 这篇文章中获取相关的信息。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值