-
Notifications
You must be signed in to change notification settings - Fork 673
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Support EtherAddr
and impl Debug
for InterfaceAddress/SockAddr
#813
Conversation
This is a lot of changes, and the commits don't really tell me what has happened here. Each discrete change should really be a separate commit with a description that provides context as to why it's a desired change. I can't really follow what all is being changed here easily, so I'd ask you split this up into separate commits that can evaluated individually. |
@Susurrus could you review again ? thx. |
You have 2 commits with identical names and one commit with no name. Neither of which have a description. Please break off the |
src/sys/socket/addr.rs
Outdated
@@ -886,6 +916,20 @@ impl fmt::Display for SockAddr { | |||
} | |||
} | |||
|
|||
impl fmt::Debug for SockAddr { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why can't you just #[derive(Debug)]
instead on line 692?
src/sys/socket/addr.rs
Outdated
|
||
impl fmt::Debug for EtherAddr { | ||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { | ||
write!(f, "EtherAddr({})", self) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why is this implemented differently than the others?
src/sys/socket/ffi.rs
Outdated
// Will be unsafe | ||
// when sdl_nlen > 40. | ||
#[cfg(any(target_os = "freebsd", target_os = "macos"))] | ||
pub struct sockaddr_dl { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Please read the CONTRIBUTING.md
document. Structs should not be declared here, but instead in libc
directly.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It's likely fine to add to libc
. libc
has been including types that aren't strictly in libc
for a while now as long as they're included in system headers. You can make an issue about it in that repo first if you'd like to make sure, but it's likely fine to include. Also note that this will need to work on more than just these 2 platforms for this to get merged.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
okay, see rust-lang/libc#866
So it looks like there are a lot less changes now, so not sure what happened there. |
src/sys/socket/addr.rs
Outdated
} | ||
} | ||
|
||
#[derive(PartialEq, Eq, Clone, Copy, Hash)] |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
These should be sorted alphabetically.
src/sys/socket/addr.rs
Outdated
} | ||
} | ||
} | ||
|
||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Please remove this extra newline
src/sys/socket/addr.rs
Outdated
@@ -782,6 +871,9 @@ impl PartialEq for SockAddr { | |||
(SockAddr::Netlink(ref a), SockAddr::Netlink(ref b)) => { | |||
a == b | |||
} | |||
(SockAddr::Ether(ref a), SockAddr::Ether(ref b)) => { | |||
a == b |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This isn't properly indented, see the block above.
src/sys/socket/addr.rs
Outdated
#[cfg(any(target_os = "android", target_os = "linux"))] | ||
SockAddr::Ether(..) => AddressFamily::Packet, | ||
#[cfg(any(target_os = "dragonfly", | ||
target_os = "freebsd", |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
These aren't aligned properly, the target_os
part should all be vertically aligned.
src/sys/socket/addr.rs
Outdated
@@ -712,6 +754,10 @@ impl SockAddr { | |||
SysControlAddr::from_name(sockfd, name, unit).map(|a| SockAddr::SysControl(a)) | |||
} | |||
|
|||
pub fn new_ether(addr: EtherAddr) -> SockAddr { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't think we need this helper function.
src/sys/socket/addr.rs
Outdated
pub enum SockAddr { | ||
Inet(InetAddr), | ||
Unix(UnixAddr), | ||
#[cfg(any(target_os = "android", target_os = "linux"))] | ||
Netlink(NetlinkAddr), | ||
#[cfg(any(target_os = "ios", target_os = "macos"))] | ||
SysControl(SysControlAddr), | ||
Ether(EtherAddr) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Please put a comma at the end of this line and this should also have doccomments. It'd be very much appreciated if you could provide doc comments for the other variants here as well.
src/sys/socket/addr.rs
Outdated
#[cfg(any(target_os = "android", target_os = "linux"))] | ||
libc::AF_PACKET => Some(AddressFamily::Packet), | ||
#[cfg(any(target_os = "dragonfly", | ||
target_os = "freebsd", |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Also improperly indended.
@Susurrus this PR rust-lang/libc#866 has merged on so i will remove struct and cloud i rebase all change into one commit ? |
The goal with the commits is to have changes that are as small and self-contained as possible while still being readable. So in this case I'd like to see two commits: 1) implement Debug for all the types and 2) add the I'd also appreciate any tests or example code that could be easily written. This will give us a sense of how this API ends up being used and make sure we don't break anything during major refactorings. |
@Susurrus ping ... |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
And please squash your commits down from the 13 that they currently are into 2: the first that implements debug and the 2nd that does everything else. There should also not be any Merge commits, please rebase when you sync with HEAD.
src/sys/socket/addr.rs
Outdated
} | ||
|
||
#[derive(Clone, Copy, Eq, Hash, PartialEq)] | ||
pub struct EtherAddr(pub u8, pub u8, pub u8, pub u8, pub u8, pub u8); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This should be a newtype around either sockaddr_dl
or sockaddr_ll
depending on the platform.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
so ?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
So what?
src/sys/socket/addr.rs
Outdated
#[derive(Clone, Copy, Eq, Hash, PartialEq)] | ||
pub struct EtherAddr(pub u8, pub u8, pub u8, pub u8, pub u8, pub u8); | ||
|
||
impl EtherAddr { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This should have some getters probably to extract the desired info across platforms. Like for your specific use case extracting the address.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
extracting the address from EtherAddr
, that's easy:
let mac_addr = EtherAddr::new(20,20,20, 20,20,20);
let a = mac_addr.0;
let b = mac_addr.1;
let c = mac_addr.2;
// ...
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This relates to my point above how the data should not be stored as a tuple, but the backing data store should be a sockaddr_ll
or sockaddr_dl
struct. Since this backing store will vary across platforms, having a method on EtherAddr
that will return just the mac address would be useful.
src/sys/socket/addr.rs
Outdated
// #[cfg(any(target_os = "android", target_os = "linux"))] | ||
#[cfg(target_os = "linux")] | ||
Some(AddressFamily::Packet) => { | ||
let sll: *const libc::sockaddr_ll = mem::transmute(addr); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This should work the same way as the other variants and not use mem::transmute()
.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
okay
src/sys/socket/addr.rs
Outdated
@@ -748,6 +798,53 @@ impl SockAddr { | |||
#[cfg(any(target_os = "ios", target_os = "macos"))] | |||
Some(AddressFamily::System) => Some(SockAddr::SysControl( | |||
SysControlAddr(*(addr as *const sys_control::sockaddr_ctl)))), | |||
// FIXME: android is same ? |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Please resolve this FIXME.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
okay
src/sys/socket/addr.rs
Outdated
Some(SockAddr::Ether(mac)) | ||
}, | ||
#[cfg(any(target_os = "dragonfly", | ||
target_os = "freebsd", |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Please indent so target_os
is always vertically aligned. There are other places in this document you can reference for the specific style.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
okay
easy merge: git merge 4e7a6ecd2b6fbbb7e0e6de40b93e9da7ccb8a034 # impl `Debug` for all sockaddr types
git merge 640e2fe5fadd4c28a497248f98fd0c7aece6c700 # Impl EtherAddr(MAC Addr)
git merge c3d3ea6062a415da75901d70709dc6d7d43ee618 # Add example for list interfaces |
You should be rebasing on top of master, squashing your commits to just 3 as you do, and then force-push into this branch. So it'd be something like:
And on the commits you want to squash, change the Given where you're at, you'll likely want to |
@Susurrus wow, that's magic 👍 thank you! |
Awesome, nicely done! Git can be tricky to use, and even harder to explain, I'm surprised what I said helped! Anyways, let's remove that last commit as that example isn't very useful. And this will also need a CHANGELOG entry. |
src/sys/socket/addr.rs
Outdated
@@ -206,7 +206,7 @@ impl AddressFamily { | |||
/// Create a new `AddressFamily` from an integer value retrieved from `libc`, usually from | |||
/// the `sa_family` field of a `sockaddr`. | |||
/// | |||
/// Currently only supports these address families: Unix, Inet (v4 & v6), Netlink | |||
/// Currently only supports these address families: Unix, Inet (v4 & v6), Netlink, Link |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Doesn't it support Packet as well?
src/sys/socket/addr.rs
Outdated
} | ||
|
||
#[derive(Clone, Copy, Eq, Hash, PartialEq)] | ||
pub struct EtherAddr { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This should be a new type around the underlying libc types, not a custom strict. See how the other types are declared for what time talking about. You'll just have to make them different definitions for the two different platforms types since the libc types are different.
d8cbaae
to
925cd87
Compare
src/sys/socket/addr.rs
Outdated
|
||
|
||
#[derive(Clone, Copy, Eq, Hash, PartialEq)] | ||
pub struct EtherAddr { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why didn't you make this a newtype around the underlying libc
type as I asked? You add a lot of types that I don't think are necessary.
cfg_if! {
if #[cfg(any(target_os = "android", target_os = "linux"))] {
pub struct EtherAddr(libc::sockaddr_ll);
else if #[cfg(any(target_os = "dragonfly",
target_os = "freebsd",
target_os = "ios",
target_os = "macos",
target_os = "netbsd",
target_os = "openbsd"))] {
pub struct EtherAddr(libc::sockaddr_dl);
}
Then to access the MAC address, you can implement a EtherAddr.mac()
or something like that. You can defer on all the other struct contents and just implement the MAC address part for now.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Code:
#[cfg(any(target_os = "android", target_os = "linux"))]
pub struct EtherAddr(libc::sockaddr_ll);
#[cfg(any(target_os = "dragonfly",
target_os = "freebsd",
target_os = "ios",
target_os = "macos",
target_os = "netbsd",
target_os = "openbsd"))]
pub struct EtherAddr(libc::sockaddr_dl);
impl EtherAddr {
pub fn addr(&self) -> [u8; 6];
}
is that ok ?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes, that's more what I was thinking. Is there any other data in there that's common across platforms that we could expose besides addr()?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
just hwaddr ([u8; 6]
) . no more other data.
i hope u know i havn't english skill.
sry for that.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@LuoZijun No worries about your language skills, we seem to be communicating just fine! And then that's fine if that's the only data there, I think we're on the right track for a nice API here!
b9fda8b
to
cfacb5b
Compare
@Susurrus hi, need any changes ? |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There's a ton of #[cfg...]
statements around. There's a common idiom of creating a new module for the different platforms that has a single #[cfg..]
for it and then you can just pub use ...
depending on the platform. This results in a lot less #[cfg...]
throughout the code. I'd suggest refactoring to use this approach (see the const
module in sys/ioctl/platform/linux.rs
)
src/sys/socket/addr.rs
Outdated
target_os = "netbsd", | ||
target_os = "openbsd", | ||
target_os = "linux", | ||
target_os = "android"))] |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
These all need to be alphabetized.
src/sys/socket/addr.rs
Outdated
target_os = "openbsd", | ||
target_os = "linux", | ||
target_os = "android"))] | ||
SockAddr::Ether(_) => unimplemented!() |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm not positive what as_ffi_pair()
is used for, but why can't this be implemented for Ether
? It needs a comment here explaining why it's unimplemented.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@Susurrus libc::sockaddr
and libc::sockaddr_dl
/libc::sockaddr_ll
has diffences size (mem::size_of
) . i think i can't implement.
src/sys/socket/addr.rs
Outdated
} | ||
|
||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Remove the extra blank line.
src/sys/socket/addr.rs
Outdated
#[cfg(any(target_os = "android", target_os = "linux"))] | ||
impl EtherAddr { | ||
pub fn new(sll: libc::sockaddr_ll) -> Option<EtherAddr> { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why do you even implement new()
? None of the other types implement it, so I suggest you drop it. You have this implemented to return an Option
and then just unwrap the option ever time anyways, so I think this function is useless.
src/sys/socket/addr.rs
Outdated
} | ||
|
||
pub fn is_empty(&self) -> bool { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Let's remove this as I don't know why it's implemented.
src/sys/socket/addr.rs
Outdated
let nlen = self.nlen(); | ||
|
||
[self.0.sdl_data[nlen ] as u8, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Please run rustfmt on this as this is an odd way to type this out.
src/sys/socket/addr.rs
Outdated
pub fn max_nlen(&self) -> usize { 46 } | ||
|
||
pub fn addr(&self) -> [u8; 6] { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Again, all pub
fn
s and types need doc comments.
src/sys/socket/addr.rs
Outdated
self.0.sdl_data[nlen + 5] as u8 ] | ||
} | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Remove this blank line.
src/sys/socket/addr.rs
Outdated
impl Eq for EtherAddr {} | ||
|
||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Remove this blank line
src/sys/socket/mod.rs
Outdated
target_os = "netbsd", | ||
target_os = "openbsd", | ||
target_os = "linux", | ||
target_os = "android"))] |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Again, please alphabetize this list.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is looking pretty good! A couple minor style issues and I still want to figure out what to do about as_ffi_pair
as I think it should be implemented.
And if you have any test code or examples that could be added that could at least provide compile-tests for this additional API, it'd be most appreciated!
src/sys/socket/addr.rs
Outdated
// Other address families are currently not supported and simply yield a None | ||
// entry instead of a proper conversion to a `SockAddr`. | ||
Some(_) | None => None, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Please leave this as-is.
src/sys/socket/addr.rs
Outdated
target_os = "macos", | ||
target_os = "netbsd", | ||
target_os = "openbsd"))] | ||
// `libc::sockaddr` and `libc::sockaddr_dl`/`libc::sockaddr_ll` has diffences size. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think it's still correct to cast the datatype to sockaddr
, though you'll need to do this differently for the sockaddr_dl
and sockaddr_ll
platforms. It looks like there are other libc
APIs that do this kind of thing, which is why the length is being thrown around. I think a better way to look at this is that it's really returning a void pointer rather than one for an actual datatype.
And since we're having this conversation, can you add doccomments to this function?
I'm also wondering if we should alter the return type here to be (*const libc::sockaddr, libc::socklen_t)
. I think it's more clear how unsafe this is if we leave it a pointer. @asomers any comment on this as you might understand this stuff better than me.
src/sys/socket/mod.rs
Outdated
@@ -27,6 +27,7 @@ pub use self::addr::{ | |||
IpAddr, | |||
Ipv4Addr, | |||
Ipv6Addr, | |||
EtherAddr |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Please add a comma at the end of this line.
src/sys/socket/addr.rs
Outdated
assert!(!self.is_empty()); | ||
|
||
let a = data[nlen] as u8; | ||
let b = data[nlen+1] as u8; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Pleas put a space around the +
for all of these.
03bce40
to
3636de9
Compare
@Susurrus updated. |
@LuoZijun This isn't passing CI. |
@Susurrus sorry for delay , i will fix that at tomorrow. |
@Susurrus updated. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This also needs a rebase now that another PR has landed.
src/sys/socket/addr.rs
Outdated
// Other address families are currently not supported and simply yield a None | ||
// entry instead of a proper conversion to a `SockAddr`. | ||
Some(_) | None => None, | ||
} | ||
} | ||
} | ||
|
||
/// Conversion SockAddr to a libc's sockaddr. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
"Conversion from nix
's SockAddr
type to the underlying libc
sockaddr
type.
This is useful for interfacing with other libc
functions that don't yet have nix
wrappers.
Returns a reference to the underlying data type (as a sockaddr
reference) along with the size of the actual data type. sockaddr
is commonly used as a proxy for a superclass as C doesn't support inheritance, so many functions that take a sockaddr *
need to take the size of the underlying type as well and then internally cast it back."
Please use my above comment instead, using backticks (`) around type and library names as I did here.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
okay, and how do u think rename EtherAddr
to LinkAddr
or HwAddr
?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think LinkAddr
would work nicely.
@Susurrus do u interesting one look here: https://github.com/LuoZijun/exodus/blob/master/netif/src/raw_socket.rs |
I don't see a reason why that couldn't be added as well, but let's defer that work to another PR. |
LGTM. bors r+ |
EtherAddr
.Debug
forInterfaceAddress
andSockAddr
.Closes #809