ethtool -T显示ptp过滤器信息源码分析
ptp过滤器
新设备使用ethtool -T显示ptp过滤器信息:
linux_cx7110:~# ethtool -T eth0
Time stamping parameters for eth0:
Capabilities:
hardware-transmit (SOF_TIMESTAMPING_TX_HARDWARE)
software-transmit (SOF_TIMESTAMPING_TX_SOFTWARE)
hardware-receive (SOF_TIMESTAMPING_RX_HARDWARE)
software-receive (SOF_TIMESTAMPING_RX_SOFTWARE)
software-system-clock (SOF_TIMESTAMPING_SOFTWARE)
hardware-raw-clock (SOF_TIMESTAMPING_RAW_HARDWARE)
PTP Hardware Clock: 0
Hardware Transmit Timestamp Modes:
off (HWTSTAMP_TX_OFF)
on (HWTSTAMP_TX_ON)
Hardware Receive Filter Modes:
none (HWTSTAMP_FILTER_NONE)
all (HWTSTAMP_FILTER_ALL)
ptpv1-l4-event (HWTSTAMP_FILTER_PTP_V1_L4_EVENT)
ptpv1-l4-sync (HWTSTAMP_FILTER_PTP_V1_L4_SYNC)
ptpv1-l4-delay-req (HWTSTAMP_FILTER_PTP_V1_L4_DELAY_REQ)
ptpv2-l4-event (HWTSTAMP_FILTER_PTP_V2_L4_EVENT)
ptpv2-l4-sync (HWTSTAMP_FILTER_PTP_V2_L4_SYNC)
ptpv2-l4-delay-req (HWTSTAMP_FILTER_PTP_V2_L4_DELAY_REQ)
ptpv2-event (HWTSTAMP_FILTER_PTP_V2_EVENT)
ptpv2-sync (HWTSTAMP_FILTER_PTP_V2_SYNC)
ptpv2-delay-req (HWTSTAMP_FILTER_PTP_V2_DELAY_REQ)
原来设备没有ptp过滤器信息:
root@imx6qsabresd_genvict:~# ethtool -T eth0
Time stamping parameters for eth0:
Capabilities:
hardware-transmit (SOF_TIMESTAMPING_TX_HARDWARE)
software-transmit (SOF_TIMESTAMPING_TX_SOFTWARE)
hardware-receive (SOF_TIMESTAMPING_RX_HARDWARE)
software-receive (SOF_TIMESTAMPING_RX_SOFTWARE)
software-system-clock (SOF_TIMESTAMPING_SOFTWARE)
hardware-raw-clock (SOF_TIMESTAMPING_RAW_HARDWARE)
PTP Hardware Clock: 0
Hardware Transmit Timestamp Modes:
off (HWTSTAMP_TX_OFF)
on (HWTSTAMP_TX_ON)
Hardware Receive Filter Modes:
none (HWTSTAMP_FILTER_NONE)
all (HWTSTAMP_FILTER_ALL)
linux_cx7101:~# ethtool -T eth0
Time stamping parameters for eth0:
Capabilities:
software-receive (SOF_TIMESTAMPING_RX_SOFTWARE)
software-system-clock (SOF_TIMESTAMPING_SOFTWARE)
PTP Hardware Clock: none
Hardware Transmit Timestamp Modes: none
Hardware Receive Filter Modes: none
代码流程
ethtool-4.15,最后系统调用:ioctl(ctx->fd, SIOCETHTOOL, &ctx->ifr);
{ "-T|--show-time-stamping", 1, do_tsinfo,
do_tsinfo
#define ETHTOOL_GET_TS_INFO 0x00000041 /* Get time stamping and PHC info */
fprintf(stdout, "Time stamping parameters for %s:\n", ctx->devname);
info.cmd = ETHTOOL_GET_TS_INFO;
if (send_ioctl(ctx, &info)) {
perror("Cannot get device time stamping settings");
return -1;
}
dump_tsinfo(&info);
#define SIOCETHTOOL 0x8946
int send_ioctl(struct cmd_context *ctx, void *cmd)
{
ctx->ifr.ifr_data = cmd;
return ioctl(ctx->fd, SIOCETHTOOL, &ctx->ifr);
}
static char *rx_filter_labels[N_RX_FILTERS] = {
"none (HWTSTAMP_FILTER_NONE)",
"all (HWTSTAMP_FILTER_ALL)",
"some (HWTSTAMP_FILTER_SOME)",
"ptpv1-l4-event (HWTSTAMP_FILTER_PTP_V1_L4_EVENT)",
"ptpv1-l4-sync (HWTSTAMP_FILTER_PTP_V1_L4_SYNC)",
"ptpv1-l4-delay-req (HWTSTAMP_FILTER_PTP_V1_L4_DELAY_REQ)",
"ptpv2-l4-event (HWTSTAMP_FILTER_PTP_V2_L4_EVENT)",
"ptpv2-l4-sync (HWTSTAMP_FILTER_PTP_V2_L4_SYNC)",
"ptpv2-l4-delay-req (HWTSTAMP_FILTER_PTP_V2_L4_DELAY_REQ)",
"ptpv2-l2-event (HWTSTAMP_FILTER_PTP_V2_L2_EVENT)",
"ptpv2-l2-sync (HWTSTAMP_FILTER_PTP_V2_L2_SYNC)",
"ptpv2-l2-delay-req (HWTSTAMP_FILTER_PTP_V2_L2_DELAY_REQ)",
"ptpv2-event (HWTSTAMP_FILTER_PTP_V2_EVENT)",
"ptpv2-sync (HWTSTAMP_FILTER_PTP_V2_SYNC)",
"ptpv2-delay-req (HWTSTAMP_FILTER_PTP_V2_DELAY_REQ)",
"ntp-all (HWTSTAMP_FILTER_NTP_ALL)",
};
dump_tsinfo
fprintf(stdout, "Hardware Receive Filter Modes:");
if (!info->rx_filters)
fprintf(stdout, " none\n");
else
fprintf(stdout, "\n");
for (i = 0; i < N_RX_FILTERS; i++) {
if (info->rx_filters & (1 << i))
fprintf(stdout, "\t%s\n", rx_filter_labels[i]);
}
网络驱动,调用网络通用层代码框架,最后调用设备驱动:get_ts_info
net/core/dev_ioctl.c +420
dev_ioctl(struct net *net, unsigned int cmd, struct ifreq *ifr, bool *need_copyout)
case SIOCETHTOOL:
dev_load(net, ifr->ifr_name);
rtnl_lock();
ret = dev_ethtool(net, ifr);
rtnl_unlock();
if (colon)
*colon = ':';
return ret;
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;【ETHTOOL_GET_TS_INFO】
case ETHTOOL_GET_TS_INFO:
rc = ethtool_get_ts_info(dev, useraddr);
break;
static int ethtool_get_ts_info(struct net_device *dev, void __user *useraddr)
{
int err = 0;
struct ethtool_ts_info info;
const struct ethtool_ops *ops = dev->ethtool_ops;
struct phy_device *phydev = dev->phydev;
memset(&info, 0, sizeof(info));
info.cmd = ETHTOOL_GET_TS_INFO;
if (phydev && phydev->drv && phydev->drv->ts_info) {
err = phydev->drv->ts_info(phydev, &info);
} else if (ops->get_ts_info) {
err = ops->get_ts_info(dev, &info);
} else {
info.so_timestamping =
SOF_TIMESTAMPING_RX_SOFTWARE |
SOF_TIMESTAMPING_SOFTWARE;
info.phc_index = -1;
}
if (err)
return err;
if (copy_to_user(useraddr, &info, sizeof(info)))
err = -EFAULT;
return err;
}
设备驱动,设备驱动如果支持time_stamp,就直接返回全部ptp过滤器信息,没有读取寄存器信息。
drivers/net/ethernet/stmicro/stmmac/stmmac_ethtool.c
static const struct ethtool_ops stmmac_ethtool_ops = {
.get_ts_info = stmmac_get_ts_info,
static int stmmac_get_ts_info(struct net_device *dev,
struct ethtool_ts_info *info)
{
struct stmmac_priv *priv = netdev_priv(dev);
if ((priv->dma_cap.time_stamp || priv->dma_cap.atime_stamp)) {
info->so_timestamping = SOF_TIMESTAMPING_TX_SOFTWARE |
SOF_TIMESTAMPING_TX_HARDWARE |
SOF_TIMESTAMPING_RX_SOFTWARE |
SOF_TIMESTAMPING_RX_HARDWARE |
SOF_TIMESTAMPING_SOFTWARE |
SOF_TIMESTAMPING_RAW_HARDWARE;
if (priv->ptp_clock)
info->phc_index = ptp_clock_index(priv->ptp_clock);
info->tx_types = (1 << HWTSTAMP_TX_OFF) | (1 << HWTSTAMP_TX_ON);
info->rx_filters = ((1 << HWTSTAMP_FILTER_NONE) |
(1 << HWTSTAMP_FILTER_PTP_V1_L4_EVENT) |【ethtool -T eth0执行这里获取信息】
(1 << HWTSTAMP_FILTER_PTP_V1_L4_SYNC) |
(1 << HWTSTAMP_FILTER_PTP_V1_L4_DELAY_REQ) |
(1 << HWTSTAMP_FILTER_PTP_V2_L4_EVENT) |
(1 << HWTSTAMP_FILTER_PTP_V2_L4_SYNC) |
(1 << HWTSTAMP_FILTER_PTP_V2_L4_DELAY_REQ) |
(1 << HWTSTAMP_FILTER_PTP_V2_EVENT) |
(1 << HWTSTAMP_FILTER_PTP_V2_SYNC) |
(1 << HWTSTAMP_FILTER_PTP_V2_DELAY_REQ) |
(1 << HWTSTAMP_FILTER_ALL));
return 0;
} else
return ethtool_op_get_ts_info(dev, info);
}
设备驱动支持设置ptp过滤器,但ethtool工具暂不支持:
static int stmmac_hwtstamp_ioctl(struct net_device *dev, struct ifreq *ifr)
if (priv->adv_ts) {
switch (config.rx_filter) {
case HWTSTAMP_FILTER_NONE:
/* time stamp no incoming packet at all */
config.rx_filter = HWTSTAMP_FILTER_NONE;
break;
case HWTSTAMP_FILTER_PTP_V1_L4_EVENT:【没有代码设置属性】
/* PTP v1, UDP, any kind of event packet */
config.rx_filter = HWTSTAMP_FILTER_PTP_V1_L4_EVENT;
/* take time stamp for all event messages */
if (xmac)
snap_type_sel = PTP_GMAC4_TCR_SNAPTYPSEL_1;
else
snap_type_sel = PTP_TCR_SNAPTYPSEL_1;
ptp_over_ipv4_udp = PTP_TCR_TSIPV4ENA;
ptp_over_ipv6_udp = PTP_TCR_TSIPV6ENA;
break;
static int stmmac_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
case SIOCSHWTSTAMP:
ret = stmmac_hwtstamp_ioctl(dev, rq);
static const struct net_device_ops stmmac_netdev_ops = {
.ndo_do_ioctl = stmmac_ioctl,
net/core/dev_ioctl.c
int dev_ioctl(struct net *net, unsigned int cmd, struct ifreq *ifr, bool *need_copyout)
case SIOCSIFNAME:
dev_load(net, ifr->ifr_name);
if (!ns_capable(net->user_ns, CAP_NET_ADMIN))
return -EPERM;
rtnl_lock();
ret = dev_ifsioc(net, ifr, cmd);
dev_ifsioc
cmd == SIOCSHWTSTAMP ||
cmd == SIOCGHWTSTAMP ||
cmd == SIOCWANDEV) {
err = -EOPNOTSUPP;
if (ops->ndo_do_ioctl) {
if (netif_device_present(dev))
err = ops->ndo_do_ioctl(dev, ifr, cmd);
总结
目前看ptp过滤器没有实际用到(暂不知如何使用),ptpd2工具发送的udp组播包也是能全部收到的。设备收到192.168.8.202主模式发送的udp包:
linux_genvict:~# tcpdump -i eth0
[10124.286185] {3}[20512:tcpdump]stmmac_get_ts_info,811,
[10124.288759] {3}[20512:tcpdump]stmmac_get_ts_info,826,
[10124.295198] {3}[20512:tcpdump]device eth0 entered promiscuous mode
tcpdump: verbose output suppressed, use -v or -vv for full protocol decode
listening on eth0, link-type EN10MB (Ethernet), capture size 262144 bytes
14:21:02.767206 IP 192.168.8.202.319 > 224.0.1.129.319: UDP, length 44
14:21:02.767279 IP 192.168.8.202.320 > 224.0.1.129.320: UDP, length 44
14:21:03.767224 IP 192.168.8.202.320 > 224.0.1.129.320: UDP, length 64
14:21:03.767297 IP 192.168.8.202.319 > 224.0.1.129.319: UDP, length 44
14:21:03.767323 IP 192.168.8.202.320 > 224.0.1.129.320: UDP, length 44
14:21:04.767240 IP 192.168.8.202.319 > 224.0.1.129.319: UDP, length 44
14:21:04.767313 IP 192.168.8.202.320 > 224.0.1.129.320: UDP, length 44
14:21:05.767137 IP 192.168.8.202.320 > 224.0.1.129.320: UDP, length 64
14:21:05.767221 IP 192.168.8.202.319 > 224.0.1.129.319: UDP, length 44
14:21:05.767251 IP 192.168.8.202.320 > 224.0.1.129.320: UDP, length 44
14:21:06.767151 IP 192.168.8.202.319 > 224.0.1.129.319: UDP, length 44
14:21:06.767239 IP 192.168.8.202.320 > 224.0.1.129.320: UDP, length 44
14:21:07.767173 IP 192.168.8.202.320 > 224.0.1.129.320: UDP, length 64
14:21:07.767265 IP 192.168.8.202.319 > 224.0.1.129.319: UDP, length 44
14:21:07.767290 IP 192.168.8.202.320 > 224.0.1.129.320: UDP, length 44
设备收到192.168.8.202从模式发送igmp包,
linux_genvict:~# tcpdump -i eth0
[10209.040651] {2}[22941:tcpdump]stmmac_get_ts_info,811,
[10209.043257] {2}[22941:tcpdump]stmmac_get_ts_info,826,
[10209.050286] {2}[22941:tcpdump]device eth0 entered promiscuous mode
tcpdump: verbose output suppressed, use -v or -vv for full protocol decode
listening on eth0, link-type EN10MB (Ethernet), capture size 262144 bytes
14:22:27.397521 IP 192.168.8.202 > 224.0.0.22: igmp v3 report, 2 group record(s)
14:22:36.297523 IP 192.168.8.202 > 224.0.0.22: igmp v3 report, 2 group record(s)
14:22:36.397373 IP 192.168.8.202 > 224.0.0.22: igmp v3 report, 2 group record(s)
14:22:44.767547 IP 192.168.8.202 > 224.0.0.22: igmp v3 report, 2 group record(s)