(old repo) Tool to fix (add, remove) your Go imports automatically.
littleboss: supervisor construction kit
crawshaw/iox 53
Go I/O utilities
experiments with animations and data formats. parts will be submitted to go.mobile if they work.
crawshaw/asm 31
amd64 (x86-64) assembler written in Go
crawshaw/fs 15
File system package that supports cancellation.
Android APK writer
Simple android app with a 3D spinning gopher
gofill is an experimental hinting service for text editors
PR opened tailscale/tailscale
I don't know how to get access to a real packet. Basing this commit entirely off:
+------------+--------------+------------------------------+
| Field Name | Field Type | Description |
+------------+--------------+------------------------------+
| NAME | domain name | MUST be 0 (root domain) |
| TYPE | u_int16_t | OPT (41) |
| CLASS | u_int16_t | requestor's UDP payload size |
| TTL | u_int32_t | extended RCODE and flags |
| RDLEN | u_int16_t | length of all RDATA |
| RDATA | octet stream | {attribute,value} pairs |
+------------+--------------+------------------------------+
From https://datatracker.ietf.org/doc/html/rfc6891#section-6.1.2
Signed-off-by: David Crawshaw [email protected]
pr created time in 9 hours
Pull request review commenttailscale/tailscale
net/tstun: buffer outbound channel
func Wrap(logf logger.Logf, tdev tun.Device) *Wrapper { // a goroutine should not block when setting it, even with no listeners. bufferConsumed: make(chan struct{}, 1), closed: make(chan struct{}),- outbound: make(chan tunReadResult),+ outbound: make(chan tunReadResult, 1),
This needs a comment saying that it can be unbuffered, but the buffer improves performance.
Did you try with other numbers, or is 1 all the protocol allows?
comment created time in 11 hours
Pull request review commenttailscale/tailscale
net/dnscache: make Dialer try all resolved IPs
func Dialer(fwd DialContextFunc, dnsCache *Resolver) DialContextFunc { // Return with original error return }- for _, ip := range ips {- dst := net.JoinHostPort(ip.String(), port)- if c, err := fwd(ctx, network, dst); err == nil {- retConn = c- ret = nil- return- }+ if c, err := raceDial(ctx, fwd, network, ips, port); err == nil {+ retConn = c+ ret = nil+ return } }() - ip, ip6, _, err := dnsCache.LookupIP(ctx, host)+ ip, ip6, allIPs, err := dnsCache.LookupIP(ctx, host) if err != nil { return nil, fmt.Errorf("failed to resolve %q: %w", host, err) }- dst := net.JoinHostPort(ip.String(), port)- if debug {- log.Printf("dnscache: dialing %s, %s for %s", network, dst, address)+ i4s := v4addrs(allIPs)+ if len(i4s) < 2 {
So if we serve exactly one ipv4 address, we try ipv4 and fall back to ipv6. If we serve multiple ipv4 addresses, we race ipv4 and ipv6 and take whichever comes back first. Does the fact we aren't favoring ipv4 in the latter case cause problems?
That is: are we happy treating ipv6 as an equal citizen on a dual stack system? Many systems in the past have favored the ipv4 connection on the theory that ipv6 is not as well maintained by dual stack ISPs and produces unexpected failures. Are those days behind us, as in, does chrome treat ipv6 equally?
comment created time in a day
Pull request review commenttailscale/tailscale
net/dnscache: make Dialer try all resolved IPs
func Dialer(fwd DialContextFunc, dnsCache *Resolver) DialContextFunc { // Return with original error return }- for _, ip := range ips {- dst := net.JoinHostPort(ip.String(), port)- if c, err := fwd(ctx, network, dst); err == nil {- retConn = c- ret = nil- return- }+ if c, err := raceDial(ctx, fwd, network, ips, port); err == nil {+ retConn = c+ ret = nil+ return } }() - ip, ip6, _, err := dnsCache.LookupIP(ctx, host)+ ip, ip6, allIPs, err := dnsCache.LookupIP(ctx, host) if err != nil { return nil, fmt.Errorf("failed to resolve %q: %w", host, err) }- dst := net.JoinHostPort(ip.String(), port)- if debug {- log.Printf("dnscache: dialing %s, %s for %s", network, dst, address)+ i4s := v4addrs(allIPs)+ if len(i4s) < 2 {+ dst := net.JoinHostPort(ip.String(), port)+ if debug {+ log.Printf("dnscache: dialing %s, %s for %s", network, dst, address)+ }+ c, err := fwd(ctx, network, dst)+ if err == nil || ctx.Err() != nil || ip6 == nil {+ return c, err+ }+ // Fall back to trying IPv6.+ dst = net.JoinHostPort(ip6.String(), port)+ return fwd(ctx, network, dst)+ }++ // Multiple IPv4 candidates, and 0+ IPv6.+ ipsToTry := append(i4s, v6addrs(allIPs)...)+ return raceDial(ctx, fwd, network, ipsToTry, port)+ }+}++// fallbackDelay is how long to wait between trying subsequent+// addresses when multiple options are available.+// 300ms is the same as Go's Happy Eyeballs fallbackDelay value.+const fallbackDelay = 300 * time.Millisecond++// raceDial tries to dial port on each ip in ips, starting a new race+// dial every 300ms apart, returning whichever completes first.
could s/300ms/fallbackDelay/ in the comments so there's less chance of them getting out of date in the future
comment created time in a day
Pull request review commenttailscale/tailscale
wgengine: re-set DNS config on Linux after a major link change
func (e *userspaceEngine) linkChange(changed bool, cur *interfaces.State) { health.SetAnyInterfaceUp(up) e.magicConn.SetNetworkUp(up) + // Hacky workaround for Linux DNS issue 2458: on+ // suspend/resumse or whenever NetworkManager is started, it+ // nukes all systemd-resolved configs. So reapply our DNS+ // config on major link change.+ if runtime.GOOS == "linux" && changed {
Elsewhere we have an issue suggesting we fsnotify resolv.conf and rewrite it on change, so we always win. I think that’s generally the right attitude: if we think we own it, own it.
comment created time in 2 days
push eventtailscale/sqlite
commit sha 7436ebf1c6760b2d01064943465bb27a61e0ec66
sqlite, etc: add tracing API Our expected use of this will be as an "event" API, not a tracing API. But for future users, I included a traceID, that could be used to retrofit one of those large trace/span systems onto the driver if you were so inclined. Minimal benchmark impact: Persist-24 1.93µs ± 1% 1.92µs ± 1% -0.51% (p=0.000 n=19+18) EmptyExec-24 386ns ± 0% 401ns ± 1% +3.85% (p=0.000 n=17+20) Signed-off-by: David Crawshaw <[email protected]>
push time in 6 days
PR merged tailscale/sqlite
Our expected use of this will be as an "event" API, not a tracing API. But for future users, I included a traceID, that could be used to retrofit one of those large trace/span systems onto the driver if you were so inclined.
Minimal benchmark impact:
Persist-24 1.93µs ± 1% 1.92µs ± 1% -0.51% (p=0.000 n=19+18)
EmptyExec-24 386ns ± 0% 401ns ± 1% +3.85% (p=0.000 n=17+20)
Signed-off-by: David Crawshaw [email protected]
pr closed time in 6 days
push eventtailscale/sqlite
commit sha 02bd521feb5322e0514833b67c0fa2fce3d11e98
sqlite: use sqliteh.OpenFlagsDefault Signed-off-by: David Crawshaw <[email protected]>
commit sha 3676a807c2e1a4b706bb0c26cb55327dff379c56
sqlite, etc: add BusyTimeout I am somewhat at a loss for why setting a busy timeout seems to be required for standard concurrent operation of writers. According to the documentation: https://sqlite.org/wal.html#sometimes_queries_return_sqlite_busy_in_wal_mode The conditions under which a WAL database should block committing transactions should be rare. None of the test cases I have written trigger those conditions. So why do I have to set a busy timeout to avoid almost all concurrent write transactions getting caught on SQLITE_BUSY? Anyway, it is a mystery that can be investigated slowly. The busy timeout does not inhibit good throughput, it is easy to reach 50k write transactions per second on a good SSD, with this busy timeout set. Signed-off-by: David Crawshaw <[email protected]>
commit sha e7f150aa8547c35888dc9d43da77f028c06d2112
sqlite: annotate more errors with details Found the hard way, trying to debug real programs. Signed-off-by: David Crawshaw <[email protected]>
commit sha 7b860b90c05d756095622fcea9dd30893c382558
cgosqlite: add .ignore file for ripgrep Signed-off-by: David Crawshaw <[email protected]>
commit sha fc0108c08c5bd0fb544e58c8c2ba8b1c82adfb8e
cgosqlite: import SQLite amalgamation v3.36.0 Signed-off-by: David Crawshaw <[email protected]>
commit sha 36ffd6c03a4e07c25384dba5f8fd54974a0e80e1
sqlite: update docs for in-memory mode in v3.36 Signed-off-by: David Crawshaw <[email protected]>
commit sha dbcdbc95f7845234b95868c2b64ab6f1b606f82b
sqlite, etc: add tracing API Our expected use of this will be as an "event" API, not a tracing API. But for future users, I included a traceID, that could be used to retrofit one of those large trace/span systems onto the driver if you were so inclined. Minimal benchmark impact: Persist-24 1.93µs ± 1% 1.92µs ± 1% -0.51% (p=0.000 n=19+18) EmptyExec-24 386ns ± 0% 401ns ± 1% +3.85% (p=0.000 n=17+20) Signed-off-by: David Crawshaw <[email protected]>
push time in 6 days
push eventtailscale/sqlite
commit sha 7ae51f5356cd302923c05d64c37d681efd62a40a
sqlite, etc: add tracing API Our expected use of this will be as an "event" API, not a tracing API. But for future users, I included a traceID, that could be used to retrofit one of those large trace/span systems onto the driver if you were so inclined. Minimal benchmark impact: Persist-24 1.93µs ± 1% 1.92µs ± 1% -0.51% (p=0.000 n=19+18) EmptyExec-24 386ns ± 0% 401ns ± 1% +3.85% (p=0.000 n=17+20) Signed-off-by: David Crawshaw <[email protected]>
push time in 7 days
Pull request review commenttailscale/sqlite
func (stmt *Stmt) ClearBindings() error { return errCode(C.sqlite3_clear_bindings(stmt.stmt)) } -func (stmt *Stmt) ResetAndClear() error {- return errCode(C.reset_and_clear(stmt.stmt))+func (stmt *Stmt) ResetAndClear() (time.Duration, error) {+ if stmt.start != (C.struct_timespec{}) {+ var d C.int64_t+ err := errCode(C.reset_and_clear(stmt.stmt, &stmt.start, &d))
Fixed by cheating, I put some scratch variables inside the *Stmt object that is already heap allocated. (Use of it is single-threaded.)
comment created time in 7 days
Pull request review commenttailscale/tailscale
wgengine/{monitor,router}: restore Linux ip rules when systemd deletes them
func newUserspaceRouterAdvanced(logf logger.Logf, tunname string, linkMon *monit ipt4: netfilter4, ipt6: netfilter6, cmd: cmd,- }, nil+ }++ return r, nil } func (r *linuxRouter) Up() error {+ if r.unregLinkMon == nil && r.linkMon != nil {+ r.unregLinkMon = r.linkMon.RegisterRuleDeleteCallback(func(table uint8, priority uint32) {+ if priority >= 5200 && priority < 5300 {
not checking the table?
comment created time in 7 days
Pull request review commenttailscale/tailscale
wgengine/{monitor,router}: restore Linux ip rules when systemd deletes them
func newUserspaceRouterAdvanced(logf logger.Logf, tunname string, linkMon *monit ipt4: netfilter4, ipt6: netfilter6, cmd: cmd,- }, nil+ }++ return r, nil } func (r *linuxRouter) Up() error {+ if r.unregLinkMon == nil && r.linkMon != nil {+ r.unregLinkMon = r.linkMon.RegisterRuleDeleteCallback(func(table uint8, priority uint32) {+ if priority >= 5200 && priority < 5300 {+ r.logf("somebody (systemd-networkd?) deleted Tailscale's ip rules; restoring")+ r.addIPRules()
is addIPRules robust when only some of the rules are deleted?
comment created time in 7 days
Pull request review commenttailscale/tailscale
wgengine/router: take a link monitor
ip route add throw 192.168.0.0/24 table 52` + basic, }, } + mon, err := monitor.New(logger.Discard)+ if err != nil {+ t.Fatal(err)+ }+ mon.Start()+ defer mon.Close()+ fake := NewFakeOS(t)- router, err := newUserspaceRouterAdvanced(t.Logf, "tailscale0", fake.netfilter4, fake.netfilter6, fake, true, true)+ router, err := newUserspaceRouterAdvanced(t.Logf, "tailscale0", mon, fake.netfilter4, fake.netfilter6, fake, true, true)
not going to cause test flakes when a linkchange comes through during the test?
comment created time in 7 days
Pull request review commenttailscale/tailscale
wgengine/router: take a link monitor
package router import (+ "fmt"+ "runtime"+ "golang.zx2c4.com/wireguard/tun" "tailscale.com/types/logger"+ "tailscale.com/wgengine/monitor" ) -func newUserspaceRouter(logf logger.Logf, tunname string, tunDev tun.Device, netChanged func()) Router {- return NewFakeRouter(logf, tunname, tunDev, netChanged)+func newUserspaceRouter(logf logger.Logf, tunname string, tunDev tun.Device, linkMon *monitor.Mon) Router {+ panic(fmt.Sprintf("unsupported OS %q", runtime.GOOS))
is there a netstack-only os this is going to break?
comment created time in 7 days