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

x/sys/unix: support for AF_ALG sockets #19033

Closed
mdlayher opened this issue Feb 11, 2017 · 6 comments
Closed

x/sys/unix: support for AF_ALG sockets #19033

mdlayher opened this issue Feb 11, 2017 · 6 comments

Comments

@mdlayher
Copy link
Member

During my recent netlink adventures, I learned of AF_ALG sockets on Linux. It appears these aren't currently exposed via x/sys/unix, and it'd be nice if they were.

I plan on using @elliotmr's work on adding AF_CAN sockets as reference, as discussed in #16188.

I'll give this a go, but if someone is already working on this, feel free to ping and we can collaborate!

@bradfitz
Copy link
Contributor

Actually there was a discussion some time ago about trying to use this in the core for accelerated crypto on Linux without needing our own assembly.

One discussion is #4299 (comment) but that's not the one I'm thinking of. And I can't find it in my gmail either.

I'd be interested in reviewing!

I remember @agl was curious about the results/speed as well.

@mdlayher
Copy link
Member Author

Good news: I got it working. One hangup is that I can't figure out why unix.Accept won't play nice with it, but doing syscall.Syscall(syscall.SYS_ACCEPT ...) works just fine. I am sure someone with more insight on x/sys/unix than me could probably help out with that.

Here's a quick and dirty prototype I did with it:

package main

import (
        "encoding/hex"
        "fmt"
        "io"
        "log"
        "os"
        "syscall"

        "golang.org/x/sys/unix"
)

func main() {
        log.SetFlags(log.Lshortfile)

        s, err := unix.Socket(unix.AF_ALG, unix.SOCK_SEQPACKET, 0)
        if err != nil {
                log.Fatal(err)
        }

        err = unix.Bind(s, &unix.SockaddrALG{
                Type: "hash",
                Name: "sha1",
        })
        if err != nil {
                log.Fatal(err)
        }

        nfd, _, e := syscall.Syscall(syscall.SYS_ACCEPT, uintptr(s), 0, 0)
        if e != 0 {
                log.Fatalf("errno:", e)
        }

        f := os.NewFile(nfd, "alg")
        io.Copy(f, os.Stdin)

        b := make([]byte, 20)
        if _, err := f.Read(b); err != nil {
                log.Fatal("read:", err)
        }

        fmt.Println(hex.EncodeToString(b))
}

Results:

$ echo "foo" | sha1sum                                                                                                                             
f1d2d2f924e986ac86fdf7b36c94bcdf32beec15  -
$ echo "foo" | ./afalg 
f1d2d2f924e986ac86fdf7b36c94bcdf32beec15

I can submit what I have now though and maybe someone will have some more insight on the matter.

@minux
Copy link
Member

minux commented Feb 11, 2017 via email

@gopherbot
Copy link

CL https://golang.org/cl/36805 mentions this issue.

@mdlayher
Copy link
Member Author

Unless a large quantity of data is involved (or we just splice(2) data
without redundant copy?), crossing the user/kernel boundary will very
likely kill much of the performance benefit.

Yep, this is my understanding and assumption as well. I just wanted to give this a try to see what could be done with it in Go.

@mdlayher
Copy link
Member Author

mdlayher commented Feb 11, 2017

Just for my own curiosity, I hacked up a quick and dirty SHA1 hash.Hash using AF_ALG. Each test opens and reads a kernel tarball I have saved locally. Here's some rough benchmarks:

$ du -h ~/tmp/linux-4.10-rc7.tar.xz 
90M     /home/matt/tmp/linux-4.10-rc7.tar.xz
$ sha1sum ~/tmp/linux-4.10-rc7.tar.xz 
85cdcad0c06eef66f805ecce353bec9accbeecc5  /home/matt/tmp/linux-4.10-rc7.tar.xz
$ go test -v -bench=.
=== RUN   TestSHA1Equal
result: 85cdcad0c06eef66f805ecce353bec9accbeecc5
--- PASS: TestSHA1Equal (0.33s)
BenchmarkCryptoSHA1-4             200000              8012 ns/op
BenchmarkAFALGSHA1-4              200000              8786 ns/op
PASS
ok      github.com/mdlayher/afalg       7.653s

Perhaps my naive benchmarks are flawed, but honestly, I'm pretty impressed to see that AF_ALG is anywhere close to the stdlib's optimized assembly implementation for linux/amd64.

Maybe this could be useful on other architectures outside of amd64? We can open another issue to look into it if needed. Just figured I would share since my curiosity got the best of me.

@golang golang locked and limited conversation to collaborators Feb 13, 2018
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Projects
None yet
Development

No branches or pull requests

4 participants