Skip to content
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

Avoid cgo in lib/overlay/conn to simplify cross-compilation #3064

Merged
merged 5 commits into from
Sep 4, 2019

Conversation

matzf
Copy link
Contributor

@matzf matzf commented Aug 29, 2019

cgo was only required to get a portable struct timespec.
The syscall.Timespec struct seems to provide this type just as well, without requiring cgo.


This change is Reviewable

@matzf
Copy link
Contributor Author

matzf commented Aug 29, 2019

@kormat asked for documentation that unsafe.Sizeof(syscall.Timespec) is guaranteed to be the same as what C considers.

I could not find any actual documentation (I find golang documentation to be rather lackluster). Still, this seems rather safe. Looking at the various syscall/types_xxx.go source files (see https://golang.org/src/syscall), Timespec is defined as type Timespec C.struct_timespec on most platforms. It's explicitly defined for windows, plan9 and nacl.

This is the complete list of unsafe.Sizeof(syscall.Timespec) for all supported GOOS/GOARCH combinations:

darwin/386: 8
darwin/amd64: 16
dragonfly/amd64: 16
freebsd/386: 8
freebsd/amd64: 16
freebsd/arm: 16
linux/386: 8
linux/amd64: 16
linux/arm: 8
linux/arm64: 16
linux/ppc64: 16
linux/ppc64le: 16
linux/mips: 8
linux/mipsle: 8
linux/mips64: 16
linux/mips64le: 16
linux/s390x: 16
nacl/386: 12
nacl/amd64p32: 16
nacl/arm: 12
netbsd/386: 12
netbsd/amd64: 16
netbsd/arm: 16
openbsd/386: 12
openbsd/amd64: 16
openbsd/arm: 16
plan9/386: 8
plan9/amd64: 8
plan9/arm: 8
solaris/amd64: 16
windows/386: 16
windows/amd64: 16

This corresponds to sizeof(struct timespec) in C for all platforms that I could check: see this compiler comparison on godbolt: https://godbolt.org/z/Lo3ekb

Copy link
Contributor

@kormat kormat left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm still not 100% comfortable. For example:

Reviewable status: 0 of 3 files reviewed, all discussions resolved

@matzf
Copy link
Contributor Author

matzf commented Sep 2, 2019

It seems unlikely to me that this could be an issue as timespec is a particularly simple data type.
The issue you refer to with zero-length struct members really seems different; the cgo documentation (now) explicitly mentions that this isn't supported.

Regardless, as the in our case the sizeof is only used to allocate a big enough buffer, maybe a compromise could be to explicitly use a constant size that can be expected to be >= sizeof(struct timespec) on any platform? Like, e.g. 16?

Btw. looking at the documentation for SO_RXQ_OVFL (the other value that is requested into/read from the oob), the value is defined as a 32-bit integer but it's currently read as a golang int. Is that intentional or a typo?

@scrye scrye added i/needs investigation Issues/proposals that need to be confirmed/explored feature New feature or request labels Sep 2, 2019
Copy link
Contributor

@kormat kormat left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for the work you've done looking into this. <3

I've been doing some research, and discovered some interesting things

So, yeah, i'm happy to go with your approach.

Btw. looking at the documentation for SO_RXQ_OVFL (the other value that is requested into/read from the oob), the value is defined as a 32-bit integer but it's currently read as a golang int. Is that intentional or a typo?

That's definitely my mistake. If you could fix that in this PR too, that would be great.

(I even double-checked the kernel source, because the docs for the option also say that it's:

the number of packets dropped by the socket between the last received packet and this received packet

which is incorrect. The counter is never reset)

Reviewed 2 of 3 files at r1, 1 of 1 files at r2.
Reviewable status: all files reviewed, 1 unresolved discussion (waiting on @matzf)


go/lib/overlay/conn/conn.go, line 42 at r2 (raw file):

const ReceiveBufferSize = 1 << 20

var sizeOfInt64 = int(unsafe.Sizeof(int64(0)))

Proposal:
const sizeOfRxOverflow = 4 // Defined to be uint32

@matzf matzf force-pushed the no-cgo branch 2 times, most recently from 2bd4f5c to 8c7c47d Compare September 2, 2019 20:38
Copy link
Contributor Author

@matzf matzf left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That's definitely my mistake. If you could fix that in this PR too, that would be great.

Done.

  • struct timespec isn't uniformly a struct containing two same-sized ints
    I was surprised by that too, but then it actually makes a lot of sense (on 32-bit systems anyway), as the number of nanoseconds per second is somewhat fixed ;)

Reviewable status: 2 of 4 files reviewed, 1 unresolved discussion (waiting on @kormat)


go/lib/overlay/conn/conn.go, line 42 at r2 (raw file):

Previously, kormat (Stephen Shirley) wrote…

Proposal:
const sizeOfRxOverflow = 4 // Defined to be uint32

Done.

Copy link
Contributor

@kormat kormat left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

:lgtm:

Reviewed 2 of 2 files at r3.
Reviewable status: :shipit: complete! all files reviewed, all discussions resolved

cgo was only required to get a portable struct timespec.
The `syscall.Timespec` struct seems to provide this type just as well,
without requiring cgo.
Value returned is defined to be an uint32.
Propagate uint32 type to RcvOvfl member of ReadMeta, as uint32 value can
overflow int on 32-bit platforms.
Gracefully handle (unlikely) wrap-around of counter values in
diagnostics messages.
Copy link
Contributor

@kormat kormat left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Reviewed 1 of 1 files at r4.
Reviewable status: :shipit: complete! all files reviewed, all discussions resolved

@kormat kormat merged commit 3a9e4dc into scionproto:master Sep 4, 2019
juagargi pushed a commit to netsec-ethz/scion that referenced this pull request Sep 9, 2019
…to#3064)

cgo was only required to get a portable struct timespec.
The `syscall.Timespec` struct to provides this type just as well,
without requiring cgo.

Also:
- Fix SO_RXQ_OVFL to be uint32 as it is defined, and handle wrap-around of the value.
@matzf matzf deleted the no-cgo branch December 19, 2019 07:37
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
feature New feature or request i/needs investigation Issues/proposals that need to be confirmed/explored
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants