diff --git a/libc-test/build.rs b/libc-test/build.rs index b7608eedb5fc..8dab618bf1b1 100644 --- a/libc-test/build.rs +++ b/libc-test/build.rs @@ -2105,6 +2105,8 @@ fn test_android(target: &str) { (struct_ == "sigaction" && field == "sa_sigaction") || // signalfd had SIGSYS fields added in Android 4.19, but CI does not have that version yet. (struct_ == "signalfd_siginfo" && field == "ssi_call_addr") || + // FIXME: `h_proto` is of type __be16 big endian version of __u16 + (struct_ == "ethhdr" && field == "h_proto") || // FIXME: Seems the type has been changed on NDK r26b (struct_ == "flock64" && (field == "l_start" || field == "l_len")) }); @@ -3680,6 +3682,10 @@ fn test_linux(target: &str) { if sparc64 && (ty == "Elf32_Rela" || ty == "Elf64_Rela") { return true; } + // FIXME: alignment issue with this arch + if loongarch64 && ty == "ethhdr" { + return true; + } match ty { // FIXME: `sighandler_t` type is incorrect, see: // https://github.com/rust-lang/libc/issues/1359 @@ -4386,6 +4392,8 @@ fn test_linux(target: &str) { (struct_ == "ptp_perout_request" && field == "anonymous_1") || // `anonymous_2` is an anonymous union (struct_ == "ptp_perout_request" && field == "anonymous_2") || + // FIXME: `h_proto` is of type __be16 big endian version of __u16 + (struct_ == "ethhdr" && field == "h_proto") || // FIXME(linux): `adjust_phase` requires >= 5.7 kernel headers // FIXME(linux): `max_phase_adj` requires >= 5.19 kernel headers // the rsv field shrunk when those fields got added, so is omitted too diff --git a/libc-test/semver/android.txt b/libc-test/semver/android.txt index e11711384677..78637c8389c8 100644 --- a/libc-test/semver/android.txt +++ b/libc-test/semver/android.txt @@ -3230,6 +3230,7 @@ epoll_create1 epoll_ctl epoll_event epoll_wait +ethhdr eventfd eventfd_read eventfd_write diff --git a/src/unix/linux_like/android/mod.rs b/src/unix/linux_like/android/mod.rs index 0fe5117ae5a9..bb5fb989ccf9 100644 --- a/src/unix/linux_like/android/mod.rs +++ b/src/unix/linux_like/android/mod.rs @@ -517,6 +517,11 @@ s! { pub ifr6_prefixlen: u32, pub ifr6_ifindex: c_int, } + + // is __be16 __bitwise __u16 + pub struct __c_anonymous___be16 { + __priv: [crate::__u8; 2], + } } s_no_extra_traits! { @@ -638,6 +643,15 @@ s_no_extra_traits! { pub ifc_len: c_int, pub ifc_ifcu: __c_anonymous_ifc_ifcu, } + + // linux/if_ether.h + + #[repr(C, align(1))] + pub struct ethhdr { + pub h_dest: [c_uchar; crate::ETH_ALEN as usize], + pub h_source: [c_uchar; crate::ETH_ALEN as usize], + pub h_proto: __c_anonymous___be16, + } } cfg_if! { @@ -1020,6 +1034,31 @@ cfg_if! { .finish() } } + + impl Eq for ethhdr {} + + impl PartialEq for ethhdr { + fn eq(&self, other: ðhdr) -> bool { + self.h_dest + .iter() + .zip(other.h_dest.iter()) + .all(|(a, b)| a == b) + && self + .h_source + .iter() + .zip(other.h_source.iter()) + .all(|(a, b)| a == b) + } + } + + impl fmt::Debug for ethhdr { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + f.debug_struct("ethhdr") + .field("h_dest", &self.h_dest) + .field("h_source", &self.h_source) + .finish() + } + } } } diff --git a/src/unix/linux_like/linux/mod.rs b/src/unix/linux_like/linux/mod.rs index f17245dfaf43..1c18cdd5ca77 100644 --- a/src/unix/linux_like/linux/mod.rs +++ b/src/unix/linux_like/linux/mod.rs @@ -1319,6 +1319,11 @@ s! { pub propagation: crate::__u64, pub userns_fd: crate::__u64, } + + // is __be16 __bitwise __u16 + pub struct __c_anonymous___be16 { + __priv: [crate::__u8; 2], + } } cfg_if! { @@ -1784,6 +1789,16 @@ s_no_extra_traits! { pub request: xsk_tx_metadata_request, pub completion: xsk_tx_metadata_completion, } + + // linux/if_ether.h + + #[cfg(not(target_arch = "loongarch64"))] + #[repr(C, align(1))] + pub struct ethhdr { + pub h_dest: [c_uchar; crate::ETH_ALEN as usize], + pub h_source: [c_uchar; crate::ETH_ALEN as usize], + pub h_proto: __c_anonymous___be16, + } } cfg_if! { @@ -2211,6 +2226,34 @@ cfg_if! { .finish() } } + + #[cfg(not(target_arch = "loongarch64"))] + impl Eq for ethhdr {} + + #[cfg(not(target_arch = "loongarch64"))] + impl PartialEq for ethhdr { + fn eq(&self, other: ðhdr) -> bool { + self.h_dest + .iter() + .zip(other.h_dest.iter()) + .all(|(a, b)| a == b) + && self + .h_source + .iter() + .zip(other.h_source.iter()) + .all(|(a, b)| a == b) + } + } + + #[cfg(not(target_arch = "loongarch64"))] + impl fmt::Debug for ethhdr { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + f.debug_struct("ethhdr") + .field("h_dest", &self.h_dest) + .field("h_source", &self.h_source) + .finish() + } + } } }