1. bcmgenet_ethtool_ops 分析
static const struct ethtool_ops bcmgenet_ethtool_ops = {
.begin = bcmgenet_begin,
.complete = bcmgenet_complete,
.get_strings = bcmgenet_get_strings,
.get_sset_count = bcmgenet_get_sset_count,
.get_ethtool_stats = bcmgenet_get_ethtool_stats,
.get_drvinfo = bcmgenet_get_drvinfo,
.get_link = ethtool_op_get_link,
.get_msglevel = bcmgenet_get_msglevel,
.set_msglevel = bcmgenet_set_msglevel,
.get_wol = bcmgenet_get_wol,
.set_wol = bcmgenet_set_wol,
.get_eee = bcmgenet_get_eee,
.set_eee = bcmgenet_set_eee,
.nway_reset = phy_ethtool_nway_reset,
.get_coalesce = bcmgenet_get_coalesce,
.set_coalesce = bcmgenet_set_coalesce,
.get_link_ksettings = bcmgenet_get_link_ksettings,
.set_link_ksettings = bcmgenet_set_link_ksettings,
};
2.核心转换层
net/core/ethtool.c
int dev_ethtool(struct net *net, struct ifreq *ifr)
int dev_ethtool(struct net *net, struct ifreq *ifr)
{
struct net_device *dev = __dev_get_by_name(net, ifr->ifr_name);
void __user *useraddr = ifr->ifr_data;
u32 ethcmd, sub_cmd;
switch (ethcmd) {
.....
case ETHTOOL_GEEE:
rc = ethtool_get_eee(dev, useraddr);
break;
....
}
if (dev->ethtool_ops->complete)
dev->ethtool_ops->complete(dev);
if (old_features != dev->features)
netdev_features_change(dev);
return rc;
}
3. ethtool源码=>确定cmd
static int do_geee(struct cmd_context *ctx)
{
struct ethtool_eee eeecmd;
if (ctx->argc != 0)
exit_bad_args();
eeecmd.cmd = ETHTOOL_GEEE;
if (send_ioctl(ctx, &eeecmd)) {
perror("Cannot get EEE settings");
return 1;
}
fprintf(stdout, "EEE Settings for %s:\n", ctx->devname);
dump_eeecmd(&eeecmd);
return 0;
}
static const struct option {
const char *opts;
int want_device;
int (*func)(struct cmd_context *);
char *help;
char *opthelp;
} args[] = {
...
{ "--show-eee", 1, do_geee, "Show EEE settings"},
}
4. ethtool调用分析实战
root@raspberrypi:/home/niyu# ethtool --show-eee eth0
EEE Settings for eth0:
EEE status: disabled
Tx LPI: disabled
Supported EEE link modes: 100baseT/Full
1000baseT/Full
Advertised EEE link modes: 100baseT/Full
1000baseT/Full
Link partner advertised EEE link modes: Not reported
root@raspberrypi:/home/niyu# dmesg
[ 2379.731178] bcmgenet fd580000.genet eth0: Link is Up - 1Gbps/Full - flow control rx/tx
[ 2395.556547] CPU: 0 PID: 812 Comm: ethtool Not tainted 4.19.127-v8+ #38
[ 2395.556561] Hardware name: Raspberry Pi 4 Model B Rev 1.5 (DT)
[ 2395.556569] Call trace:
[ 2395.556590] dump_backtrace+0x0/0x178
[ 2395.556600] show_stack+0x28/0x34
[ 2395.556612] __dump_stack+0x20/0x28
[ 2395.556621] dump_stack+0x88/0xc4
[ 2395.556646] bcmgenet_get_eee+0x24/0x88 [genet] //结束
[ 2395.556657] ethtool_get_eee+0x5c/0xe8
[ 2395.556666] dev_ethtool+0x2a8/0x75c
[ 2395.556675] dev_ioctl+0xf8/0x288 //开始
[ 2395.556686] sock_do_ioctl+0xf8/0x284
[ 2395.556696] sock_ioctl+0x320/0x484
[ 2395.556708] vfs_ioctl+0x44/0x74
[ 2395.556717] do_vfs_ioctl+0x2d0/0x304
[ 2395.556726] ksys_ioctl+0x54/0x88
[ 2395.556735] __se_sys_ioctl+0x38/0x4c
[ 2395.556744] __arm64_sys_ioctl+0x2c/0x38
[ 2395.556753] __invoke_syscall+0x28/0x34
[ 2395.556761] invoke_syscall+0x58/0x7c
[ 2395.556769] el0_svc_common+0x74/0xec
[ 2395.556777] el0_svc_handler+0x70/0x94
[ 2395.556786] el0_svc+0x8/0xc
5 补充
struct cmd_context {
const char *devname; /* net device name */
int fd; /* socket suitable for ethtool ioctl */
struct ifreq ifr; /* ifreq suitable for ethtool ioctl */
int argc; /* number of arguments to the sub-command */
char **argp; /* arguments to the sub-command */
};
struct ifreq
{
# define IFHWADDRLEN 6
# define IFNAMSIZ IF_NAMESIZE
union
{
char ifrn_name[IFNAMSIZ]; /* Interface name, e.g. "en0". */
} ifr_ifrn;
union
{
struct sockaddr ifru_addr;
struct sockaddr ifru_dstaddr;
struct sockaddr ifru_broadaddr;
struct sockaddr ifru_netmask;
struct sockaddr ifru_hwaddr;
short int ifru_flags;
int ifru_ivalue;
int ifru_mtu;
struct ifmap ifru_map;
char ifru_slave[IFNAMSIZ];
char ifru_newname[IFNAMSIZ];
__caddr_t ifru_data; //填充cmd
} ifr_ifru;
};