Retry reading routing table (bsd) (#1914)

* Retry reading routing table (bsd)

Similar to #1817, BSD base OSes will return "cannot allocate memory"
errors when routing table is expanding.
This commit is contained in:
Carlos Hernandez 2024-05-07 01:51:43 -06:00 committed by GitHub
parent 7357a9954c
commit f309b120cd
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194

View File

@ -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: