mirror of
https://github.com/tailscale/tailscale.git
synced 2024-11-25 19:15:34 +00:00
f7ad04bea4
Consistently interning the NodePublic's throughout DERP, particularly inside the maps reduces memory usage and reduces lookup costs in the associated data structures. It is not clear exactly how efficient the weak pointers will be in practice, but estimating this using derpstress with 10k conns pushing 40kpps in each direction, this is patch grows heap at approximately half the rate vs. the old code and has fewer instances of long stalls that trigger i/o timeouts for the clients. Updates tailscale/corp#24485 Signed-off-by: James Tucker <james@tailscale.com>
77 lines
2.1 KiB
Go
77 lines
2.1 KiB
Go
// Copyright (c) Tailscale Inc & AUTHORS
|
|
// SPDX-License-Identifier: BSD-3-Clause
|
|
|
|
package main
|
|
|
|
import (
|
|
"context"
|
|
"errors"
|
|
"fmt"
|
|
"log"
|
|
"net"
|
|
"strings"
|
|
"time"
|
|
|
|
"tailscale.com/derp"
|
|
"tailscale.com/derp/derphttp"
|
|
"tailscale.com/net/netmon"
|
|
"tailscale.com/types/logger"
|
|
)
|
|
|
|
func startMesh(s *derp.Server) error {
|
|
if *meshWith == "" {
|
|
return nil
|
|
}
|
|
if !s.HasMeshKey() {
|
|
return errors.New("--mesh-with requires --mesh-psk-file")
|
|
}
|
|
for _, host := range strings.Split(*meshWith, ",") {
|
|
if err := startMeshWithHost(s, host); err != nil {
|
|
return err
|
|
}
|
|
}
|
|
return nil
|
|
}
|
|
|
|
func startMeshWithHost(s *derp.Server, host string) error {
|
|
logf := logger.WithPrefix(log.Printf, fmt.Sprintf("mesh(%q): ", host))
|
|
netMon := netmon.NewStatic() // good enough for cmd/derper; no need for netns fanciness
|
|
c, err := derphttp.NewClient(s.PrivateKey(), "https://"+host+"/derp", logf, netMon)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
c.MeshKey = s.MeshKey()
|
|
c.WatchConnectionChanges = true
|
|
|
|
// For meshed peers within a region, connect via VPC addresses.
|
|
c.SetURLDialer(func(ctx context.Context, network, addr string) (net.Conn, error) {
|
|
host, port, err := net.SplitHostPort(addr)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
var d net.Dialer
|
|
var r net.Resolver
|
|
if base, ok := strings.CutSuffix(host, ".tailscale.com"); ok && port == "443" {
|
|
subCtx, cancel := context.WithTimeout(ctx, 2*time.Second)
|
|
defer cancel()
|
|
vpcHost := base + "-vpc.tailscale.com"
|
|
ips, _ := r.LookupIP(subCtx, "ip", vpcHost)
|
|
if len(ips) > 0 {
|
|
vpcAddr := net.JoinHostPort(ips[0].String(), port)
|
|
c, err := d.DialContext(subCtx, network, vpcAddr)
|
|
if err == nil {
|
|
log.Printf("connected to %v (%v) instead of %v", vpcHost, ips[0], base)
|
|
return c, nil
|
|
}
|
|
log.Printf("failed to connect to %v (%v): %v; trying non-VPC route", vpcHost, ips[0], err)
|
|
}
|
|
}
|
|
return d.DialContext(ctx, network, addr)
|
|
})
|
|
|
|
add := func(m derp.PeerPresentMessage) { s.AddPacketForwarder(m.Key.Handle(), c) }
|
|
remove := func(m derp.PeerGoneMessage) { s.RemovePacketForwarder(m.Peer.Handle(), c) }
|
|
go c.RunWatchConnectionLoop(context.Background(), s.PublicKey(), logf, add, remove)
|
|
return nil
|
|
}
|