Linux 内核如何存储硬件 TX 和 RX 过滤模式?

Linux 内核如何存储硬件 TX 和 RX 过滤模式?

我正在开发一个 C 程序,它获取给定网络接口的时间戳信息,就像我自己的 ethtool 版本一样。我的目标是获得打印的信息$ ethtool -T myNetIf。就像是:

Time stamping parameters for myNetIf:
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)

由于我不想只抓取命令行输出,因此我发现可以使用调用ioctl从 ethtool 查询此信息,并将我的标志作为无符号整数取回。

struct ifreq ifr;
memset(&ifr, 0, sizeof(struct ifreq));
struct ethtool_ts_info etsi;
memset(&etsi, 0, sizeof(struct ethtool_ts_info));

etsi.cmd = ETHTOOL_GET_TS_INFO;
strncpy(ifr.ifr_name, dev, sizeof(ifr.ifr_name)); // dev is read from stdin
ifr.ifr_data = (void *)&etsi;

ioctl(sock, SIOCETHTOOL, &ifr); // sock is an AF_INET socket

ethtool_ts_info(我相信)包含我想要的数据的结构已定义这里。具体来说,我抓取so_timestampingtx_typesrx_filters字段。

so_timestamping使用相同的示例界面,的值为0x5f, 或0101 1111。一看net_tstamp.h 证实这些是预期的标志。

然而,我的问题是解释tx_types和的值rx_filters。我假设 的值tx_types类似于0x3( 0011,其中第三位是 HWTSTAMP_TX_ON,第四位是 HWTSTAMP_TX_OFF)。或者,由于可能的传输模式定义在一个枚举如果有 4 个值,结果可能是0100,其中每个int枚举值都是 2 位。

不是这种情况。tx_types的实际值为0x7fdd。我究竟应该如何从 获得“HW_TX_OFF 和 ON” 0x7fdd?我发现rx_filters更令人困惑的价值。应该是什么0x664758eb意思?

除了内核源代码本身之外,我还没有找到太多有用的信息。我认为我做的一切都是正确的,我只是需要一些帮助来理解我的结果。

答案1

这很尴尬:我检查了我的代码,发现我确实未能正确初始化结构,只是与我预期的方式不同。我也没有提供解决问题所需的完整上下文,因为我认为我已经排除了分配之前留下的垃圾值的可能性。

我发布的示例代码是函数的一部分,该函数填充我定义的包含ethtool_ts_info.

typedef struct {
    unsigned int soTimestamping;
    unsigned int txTypes;
    unsigned int rxFilters;
} tsCapsFilters_t;

函数的用户自己初始化这个结构,函数只是填充它。所以预期的用法如下:

tsCapsFilters_t tsInfo; // struct full of junk
if(getTsInfo(nameOfNetIf, &tsInfo, errMsgBuf, ERR_BUF_SZ) < 0) {
    // handle errors in here
}
printf("%x\n", tsInfo.soTimestamping); // struct filled out by getTsInfo

然而,我犯的错误是我忘记将tx_typesandrx_filtersethtool_ts_info结构(我的函数内部)复制到tsCapsFilters_t结构(提供给用户)。所以我的程序很好地获取了所有字段,但它只so_timestamping在应该返回所有 3 个值时才返回功能。

printf("%x\n", tsInfo.soTimestamping); // printed the expected values
printf("%x\n", tsInfo.txTypes); // printed junk
printf("%x\n", tsInfo.rxFilters); // printed junk

就像我说的,尴尬。我将给予赏金,并在未来更加小心我的结构。

答案2

struct ethtool_ts_info etsi;

ifr.ifr_data = (void *)&etsi;

来自网络时间戳的内核文档,我知道您的程序调用的 ioctl(SIOCSHWTSTAMP) 应该填充该类型的某些结构hwtstamp_config

struct hwtstamp_config定义为:

struct hwtstamp_config {
    int flags;  /* no flags defined right now, must be zero */
    int tx_type;    /* HWTSTAMP_TX_* */
    int rx_filter;  /* HWTSTAMP_FILTER_* */
};

通过使用指向 struct ifreq 的指针调用 ioctl(SIOCSHWTSTAMP),将所需的行为传递到内核和特定设备其 ifr_data 指向 struct hwtstamp_config...任何进程都可以通过以相同的方式将此结构传递给 ioctl(SIOCGHWTSTAMP) 来读取实际配置。

当您的程序使用返回的数据时,就好像它被struct ethtool_ts_info定义为:

struct ethtool_ts_info {
    __u32   cmd;
    __u32   so_timestamping;
    __s32   phc_index;
    __u32   tx_types;
    __u32   tx_reserved[3];
    __u32   rx_filters;
    __u32   rx_reserved[3];
};

这意味着您的程序将提取超出第三个 int 的值(特别是交易类型rx_filters您感兴趣的)只是,正如您所报告的那样,……无意义的
这 (配置即不是能力)值交易类型rx_filters应分别从 ifr.ifr_data 地址开始在第二个和第三个 int 处获取。

在这种情况下,配置值不是您想要的,ioctl-ing(SIOCGHWTSTAMP) 不是合适的方法。

相关内容