天天看点

使用 netmap 提升 ixgbe 性能(续)

书接上回  使用 netmap 提升 ixgbe 性能

上次打算通过 get_channels( )方法来获取队列的个数,不过我使用的内核的版本中,ethtool_ops 下并没有 get_channels( ) 方法。。。

那肿么办,如何获取网卡队列?

上次强制改过 RX 的个数为网卡中 RX 的个数,可惜行不通,还是找其他方法吧。

翻了翻我使用内核版本的源码,发现有 get_channels( ) 方法,不过并不在 ethtool_ops 中,而是作为扩展在struct ethtool_ops_ext 中:

struct ethtool_ops_ext {
	size_t  size;
	u32 (*get_rxfh_indir_size)(struct net_device *);
	int (*get_rxfh_indir)(struct net_device *, u32 *);
	int (*set_rxfh_indir)(struct net_device *, const u32 *);
	void (*get_channels)(struct net_device *, struct ethtool_channels *);  // 在这里
	int	(*set_channels)(struct net_device *, struct ethtool_channels *);
	int	(*get_dump_flag)(struct net_device *, struct ethtool_dump *);
	int	(*get_dump_data)(struct net_device *, struct ethtool_dump *, void *);
	int	(*set_dump)(struct net_device *, struct ethtool_dump *);
	int	(*get_module_info)(struct net_device *, struct ethtool_modinfo *);
	int	(*get_module_eeprom)(struct net_device *, struct ethtool_eeprom *, u8 *);
	int	(*set_phys_id)(struct net_device *, enum ethtool_phys_id_state);
	int	(*reset)(struct net_device *, u32 *);
	int	(*get_eee)(struct net_device *, struct ethtool_eee *);
	int	(*set_eee)(struct net_device *, struct ethtool_eee *);
	int	(*get_ts_info)(struct net_device *, struct ethtool_ts_info *);
};
           

ixgbe 是这么设置的:

static const struct ethtool_ops_ext ixgbe_ethtool_ops_ext = {
	.size			= sizeof(struct ethtool_ops_ext),
	.get_channels		= ixgbe_get_channels,
	.set_channels		= ixgbe_set_channels,
	.get_ts_info		= ixgbe_get_ts_info,
	.get_module_info	= ixgbe_get_module_info,
	.get_module_eeprom	= ixgbe_get_module_eeprom,
};

void ixgbe_set_ethtool_ops(struct net_device *netdev)
{
	SET_ETHTOOL_OPS(netdev, &ixgbe_ethtool_ops);  // ixgbe_ethtool_ops 是 ethtool_ops
	set_ethtool_ops_ext(netdev, &ixgbe_ethtool_ops_ext);  // ixgbe_ethtool_ops_ext 里面有我们要的 get_channels
}
           

那好,我们改动 netmap 关于通过 net_device 设置网卡收发队列的部分,加入  struct ethtool_ops_ext 的支持:

void nm_os_generic_find_num_queues(struct ifnet *ifp, u_int *txq, u_int *rxq)
{
#ifdef NETMAP_LINUX_HAVE_SET_CHANNELS
	struct ethtool_channels ch;
	memset(&ch, 0, sizeof(ch));
	if ((ifp->ethtool_ops && ifp->ethtool_ops->get_channels) ||
        (get_ethtool_ops_ext(ifp) && get_ethtool_ops_ext(ifp)->get_channels)) {  // 这里添加 get_ethtool_ops_ext
        if (ifp->ethtool_ops->get_channels) {
		    ifp->ethtool_ops->get_channels(ifp, &ch);
        } else if (get_ethtool_ops_ext(ifp)->get_channels) {  // 分支判断是否支持 ethtool_opt 的扩展
		    get_ethtool_ops_ext(ifp)->get_channels(ifp, &ch);
        }
		*txq = ch.tx_count ? ch.tx_count : ch.combined_count;
		*rxq = ch.rx_count ? ch.rx_count : ch.combined_count;
	} else
#endif /* HAVE_SET_CHANNELS */
	{
		*txq = ifp->real_num_tx_queues;
#if defined(NETMAP_LINUX_HAVE_REAL_NUM_RX_QUEUES)
		*rxq = ifp->real_num_rx_queues;
#else
		*rxq = 1;
#endif /* HAVE_REAL_NUM_RX_QUEUES */
	}
}
           

重新编译源码,加载模块运行,嗯嗯,可以设置 RX 为 8 队列了,这回可以使用 8 队列收包了。^_^