omni/internal/pkg/siderolink/wireguard.go
Artem Chernyshev 7f58ea4713
fix: allow adding machines to Omni at higher speed
Introduce a buffer for `PeerEvents` channel, to not block adding new
machines when SideroLink is processing new peers.

Fixes: https://github.com/siderolabs/omni/issues/120

Signed-off-by: Artem Chernyshev <artem.chernyshev@talos-systems.com>
2024-04-25 17:30:12 +03:00

108 lines
3.0 KiB
Go

// Copyright (c) 2024 Sidero Labs, Inc.
//
// Use of this software is governed by the Business Source License
// included in the LICENSE file.
package siderolink
import (
"context"
"fmt"
"net/netip"
"github.com/siderolabs/gen/channel"
"github.com/siderolabs/go-pointer"
"github.com/siderolabs/siderolink/pkg/wireguard"
"go.uber.org/zap"
"golang.zx2c4.com/wireguard/wgctrl/wgtypes"
"github.com/siderolabs/omni/client/api/omni/specs"
)
// WireguardHandler abstraction around peer handler and wgDevice.
type WireguardHandler interface {
SetupDevice(wireguard.DeviceConfig) error
Shutdown() error
Run(context.Context, *zap.Logger) error
PeerEvent(context.Context, *specs.SiderolinkSpec, bool) error
Peers() ([]wgtypes.Peer, error)
}
// PhysicalWireguardHandler implements WireguardHandler interface.
type PhysicalWireguardHandler struct {
wgDevice *wireguard.Device
events chan wireguard.PeerEvent
}
// DefaultWireguardHandler is a default wireguard handler to be used with the siderolink manager.
var DefaultWireguardHandler = &PhysicalWireguardHandler{events: make(chan wireguard.PeerEvent, 500)}
// PeerEvent implements WireguardHandler.
func (handler *PhysicalWireguardHandler) PeerEvent(ctx context.Context, spec *specs.SiderolinkSpec, deleted bool) error {
address, err := netip.ParsePrefix(spec.NodeSubnet)
if err != nil {
return err
}
pubKey, err := wgtypes.ParseKey(spec.NodePublicKey)
if err != nil {
return err
}
var virtualAddrPort netip.AddrPort
if spec.VirtualAddrport != "" {
virtualAddrPort, err = netip.ParseAddrPort(spec.VirtualAddrport)
if err != nil {
return err
}
}
channel.SendWithContext(ctx, handler.events, wireguard.PeerEvent{
PubKey: pubKey,
Remove: deleted,
Endpoint: spec.LastEndpoint,
Address: address.Addr(),
PersistentKeepAliveInterval: pointer.To(wireguard.RecommendedPersistentKeepAliveInterval),
VirtualAddr: virtualAddrPort.Addr(),
})
return nil
}
// EventCh implements the wireguard.PeerSource interface.
func (handler *PhysicalWireguardHandler) EventCh() <-chan wireguard.PeerEvent {
return handler.events
}
// SetupDevice implements WireguardHandler.
func (handler *PhysicalWireguardHandler) SetupDevice(cfg wireguard.DeviceConfig) error {
var err error
handler.wgDevice, err = wireguard.NewDevice(cfg)
if err != nil {
return fmt.Errorf("error initializing wgDevice: %w", err)
}
return nil
}
// Shutdown implements WireguardHandler.
func (handler *PhysicalWireguardHandler) Shutdown() error {
return handler.wgDevice.Close()
}
// Run implements WireguardHandler.
func (handler *PhysicalWireguardHandler) Run(ctx context.Context, logger *zap.Logger) error {
return handler.wgDevice.Run(ctx, logger, handler)
}
// Peers implements WireguardHandler.
func (handler *PhysicalWireguardHandler) Peers() ([]wgtypes.Peer, error) {
if handler.wgDevice == nil {
return []wgtypes.Peer{}, nil
}
return handler.wgDevice.Peers()
}