LinuxカーネルはどのようにハードウェアTXとRXフィルタリングモードを保存しますか?

LinuxカーネルはどのようにハードウェアTXとRXフィルタリングモードを保存しますか?

私は自分のethtoolバージョンと同様に、特定のネットワークインターフェイスのタイムスタンプ情報を取得するCプログラムを作業しています。私の目標は情報を印刷することです$ 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_timestampingフィールドtx_typesrx_filters持っています。

so_timestamping同じインタフェース例を使用すると、値は0x5f、またはです0101 1111。一度見てnet_tstamp.h 確認するこれは予想できる兆候です。

しかし、私の問題はtx_typessum値を解釈することですrx_filters。私が仮定する値はtx_types次のとおりです0x30011ここで、3番目のビットはHWTSTAMP_TX_ON、4番目のビットは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_typesしかし、私が犯した間違いは、構造体(私の関数の内部)rx_filtersから構造体(ユーザーに提供されている)にコピーするのを忘れたことです。したがって、私のプログラムはすべてのフィールドを正しく取得しますが、3つの値をすべて返す必要がある場合にのみ関数を返します。ethtool_ts_infotsCapsFilters_tso_timestamping

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

私が言ったように、厄介です。私は賞金を試してみて、将来的に私の構造にもっと注意します。

おすすめ記事