私は自分の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_types
をrx_filters
持っています。
so_timestamping
同じインタフェース例を使用すると、値は0x5f
、またはです0101 1111
。一度見てnet_tstamp.h
確認するこれは予想できる兆候です。
しかし、私の問題はtx_types
sum値を解釈することですrx_filters
。私が仮定する値はtx_types
次のとおりです0x3
(0011
ここで、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_info
tsCapsFilters_t
so_timestamping
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は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];
};
これは、あなたのプログラムが3番目のint(具体的には)以上の値を抽出することを意味します。取引タイプそしてrx_filtersあなたが興味を持っているのは)あなたが報告したように…無意味。
これ(構成つまり、能力ではありません)取引タイプそしてrx_filtersifr.ifr_dataアドレスから始めて、それぞれ2番目と3番目のintから取得する必要があります。
この場合、構成値は望ましくなく、ioctl-ing(SIOCGHWTSTAMP)は適切なアプローチではありません。