diff --git a/client/internal/routemanager/systemops_bsd.go b/client/internal/routemanager/systemops_bsd.go index cadb1515b..f8f76ed45 100644 --- a/client/internal/routemanager/systemops_bsd.go +++ b/client/internal/routemanager/systemops_bsd.go @@ -6,15 +6,19 @@ import ( "fmt" "net" "net/netip" + "errors" "syscall" + "time" + "github.com/cenkalti/backoff/v4" log "github.com/sirupsen/logrus" "golang.org/x/net/route" ) +// TODO: fix here with retry and backoff func getRoutesFromTable() ([]netip.Prefix, error) { - tab, err := route.FetchRIB(syscall.AF_UNSPEC, route.RIBTypeRoute, 0) + tab, err := retryFetchRIB() if err != nil { return nil, err } @@ -65,6 +69,32 @@ func getRoutesFromTable() ([]netip.Prefix, error) { return prefixList, nil } +func retryFetchRIB() ([]byte, error) { + var out []byte + operation := func() error { + var err error + out, err = route.FetchRIB(syscall.AF_UNSPEC, route.RIBTypeRoute, 0) + if errors.Is(err, syscall.ENOMEM) { + log.Debug("retrying fetchRIB due to 'cannot allocate memory' error") + return err + } else if err != nil { + return backoff.Permanent(err) + } + return nil + } + + expBackOff := backoff.NewExponentialBackOff() + expBackOff.InitialInterval = 50 * time.Millisecond + expBackOff.MaxInterval = 500 * time.Millisecond + expBackOff.MaxElapsedTime = 1 * time.Second + + err := backoff.Retry(operation, expBackOff) + if err != nil { + return nil, fmt.Errorf("failed to fetch routing information: %w", err) + } + return out, nil +} + func toNetIPAddr(a route.Addr) (netip.Addr, bool) { switch t := a.(type) { case *route.Inet4Addr: