Bindings
I am generating bindings for ethtool.h
.
#include <linux/ethtool.h>
Actual Results
I am getting erroneous results while trying to deal with __IncompleteArray
.
This is the struct generated by bindgen
:
pub struct ethtool_sset_info {
pub cmd: __u32,
pub reserved: __u32,
pub sset_mask: __u64,
pub data: __IncompleteArrayField<__u32>,
}
My code:
fn gsset_info(&self) -> Result<usize, Errno> {
let mut sset_info = ethtool_sset_info {
cmd: ETHTOOL_GSSET_INFO,
reserved: 1,
sset_mask: 1 << ETH_SS_STATS,
data: __IncompleteArrayField::<u32>::new(),
};
// https://github.com/mmynk/rust-ethtool/blob/44189de0d9c6f79fd48a6c30e5a5d58d57342992/src/ethtool.rs#L42-L60
match _ioctl(
&self.sock_fd,
self.if_name,
&mut sset_info as *mut ethtool_sset_info as usize,
) {
Ok(_) => {
let data = unsafe { sset_info.data.as_ptr().read() } as usize;
println!("length={}", data);
Ok(data)
},
Err(errno) => Err(errno),
}
}
It works where sset_info.data
has some non-zero value but returns garbage when the value should be zero. The same code when I use this struct. I am guessing the issue is with how I'm reading the value sset_info.data.as_ptr().read()
but I am not sure.
Similarly, struct generated by bindgen
:
pub struct ethtool_gstrings {
pub cmd: __u32,
pub string_set: __u32,
pub len: __u32,
pub data: __IncompleteArrayField<__u8>,
}
My code:
fn gstrings(&self, length: usize) -> Result<Vec<String>, Error> {
let mut gstrings = ethtool_gstrings {
cmd: ETHTOOL_GSTRINGS,
string_set: ETH_SS_STATS,
len: length as u32,
data: __IncompleteArrayField::<u8>::new(),
};
match _ioctl(
&self.sock_fd,
self.if_name,
&mut gstrings as *mut ethtool_gstrings as usize,
) {
Ok(_) => {
let data = unsafe { gstrings.data.as_slice(length) };
let some_data = unsafe { gstrings.data.as_ptr().read() };
let data_ptr = gstrings.data.as_ptr();
for i in 0..length {
print!("debug: ");
for j in 0..ETH_GSTRINGS_LEN {
print!("{} ", unsafe { data_ptr.add(i * ETH_GSTRINGS_LEN + j).read() });
}
println!();
}
// https://github.com/mmynk/rust-ethtool/blob/44189de0d9c6f79fd48a6c30e5a5d58d57342992/src/ethtool.rs#L62-L83
return parse_names(data, length)
},
Err(errno) => Err(Error::GStringsReadError(errno)),
}
}
The data array is quite different from what I'd expect while having expected values at certain positions. The data also has arbitrary null values which makes parsing it impossible. Again, the issue could be with how I'm reading the data but I'm not sure: let data = unsafe { gstrings.data.as_slice(length) };
.
I also get (signal: 11, SIGSEGV: invalid memory reference)
errors while trying to parse which could again indicate issue with my code.
Expected Results
Example of working code with custom structs: https://github.com/mmynk/rust-ethtool/blob/main/src/ethtool.rs