ipn/{ipnlocal,localapi},net/netkernelconf,client/tailscale,cmd/containerboot: optionally enable UDP GRO forwarding for containers (#12410)
Add a new TS_EXPERIMENTAL_ENABLE_FORWARDING_OPTIMIZATIONS env var that can be set for tailscale/tailscale container running as a subnet router or exit node to enable UDP GRO forwarding for improved performance. See https://tailscale.com/kb/1320/performance-best-practices#linux-optimizations-for-subnet-routers-and-exit-nodes This is currently considered an experimental approach; the configuration support is partially to allow further experimentation with containerized environments to evaluate the performance improvements. Updates tailscale/tailscale#12295 Signed-off-by: Irbe Krumina <irbe@tailscale.com>
This commit is contained in:
@@ -5537,6 +5537,38 @@ func (b *LocalBackend) CheckUDPGROForwarding() error {
|
||||
return warn
|
||||
}
|
||||
|
||||
// SetUDPGROForwarding enables UDP GRO forwarding for the default network
|
||||
// interface of this machine. It can be done to improve performance for nodes
|
||||
// acting as Tailscale subnet routers or exit nodes. Currently (9/5/2024) this
|
||||
// functionality is considered experimental and only safe to use via explicit
|
||||
// user opt-in for ephemeral devices, such as containers.
|
||||
// https://tailscale.com/kb/1320/performance-best-practices#linux-optimizations-for-subnet-routers-and-exit-nodes
|
||||
func (b *LocalBackend) SetUDPGROForwarding() error {
|
||||
if b.sys.IsNetstackRouter() {
|
||||
return errors.New("UDP GRO forwarding cannot be enabled in userspace mode")
|
||||
}
|
||||
tunSys, ok := b.sys.Tun.GetOK()
|
||||
if !ok {
|
||||
return errors.New("[unexpected] unable to retrieve tun device configuration")
|
||||
}
|
||||
tunInterface, err := tunSys.Name()
|
||||
if err != nil {
|
||||
return errors.New("[unexpected] unable to determine name of the tun device")
|
||||
}
|
||||
netmonSys, ok := b.sys.NetMon.GetOK()
|
||||
if !ok {
|
||||
return errors.New("[unexpected] unable to retrieve tailscale netmon configuration")
|
||||
}
|
||||
state := netmonSys.InterfaceState()
|
||||
if state == nil {
|
||||
return errors.New("[unexpected] unable to retrieve machine's network interface state")
|
||||
}
|
||||
if err := netkernelconf.SetUDPGROForwarding(tunInterface, state.DefaultRouteInterface); err != nil {
|
||||
return fmt.Errorf("error enabling UDP GRO forwarding: %w", err)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// DERPMap returns the current DERPMap in use, or nil if not connected.
|
||||
func (b *LocalBackend) DERPMap() *tailcfg.DERPMap {
|
||||
b.mu.Lock()
|
||||
|
||||
@@ -119,6 +119,7 @@ var handler = map[string]localAPIHandler{
|
||||
"set-expiry-sooner": (*Handler).serveSetExpirySooner,
|
||||
"set-gui-visible": (*Handler).serveSetGUIVisible,
|
||||
"set-push-device-token": (*Handler).serveSetPushDeviceToken,
|
||||
"set-udp-gro-forwarding": (*Handler).serveSetUDPGROForwarding,
|
||||
"set-use-exit-node-enabled": (*Handler).serveSetUseExitNodeEnabled,
|
||||
"start": (*Handler).serveStart,
|
||||
"status": (*Handler).serveStatus,
|
||||
@@ -1182,6 +1183,23 @@ func (h *Handler) serveCheckUDPGROForwarding(w http.ResponseWriter, r *http.Requ
|
||||
})
|
||||
}
|
||||
|
||||
func (h *Handler) serveSetUDPGROForwarding(w http.ResponseWriter, r *http.Request) {
|
||||
if !h.PermitWrite {
|
||||
http.Error(w, "UDP GRO forwarding set access denied", http.StatusForbidden)
|
||||
return
|
||||
}
|
||||
var warning string
|
||||
if err := h.b.SetUDPGROForwarding(); err != nil {
|
||||
warning = err.Error()
|
||||
}
|
||||
w.Header().Set("Content-Type", "application/json")
|
||||
json.NewEncoder(w).Encode(struct {
|
||||
Warning string
|
||||
}{
|
||||
Warning: warning,
|
||||
})
|
||||
}
|
||||
|
||||
func (h *Handler) serveStatus(w http.ResponseWriter, r *http.Request) {
|
||||
if !h.PermitRead {
|
||||
http.Error(w, "status access denied", http.StatusForbidden)
|
||||
|
||||
Reference in New Issue
Block a user