wip: ping handler per backend (#426)

This commit is contained in:
Christoph Haas
2025-06-01 09:50:46 +02:00
parent ea6da4114f
commit c612b5bbb1
6 changed files with 171 additions and 30 deletions

View File

@@ -10,7 +10,9 @@ import (
"os"
"os/exec"
"strings"
"time"
probing "github.com/prometheus-community/pro-bing"
"github.com/vishvananda/netlink"
"golang.org/x/sys/unix"
"golang.zx2c4.com/wireguard/wgctrl"
@@ -812,3 +814,34 @@ func (c LocalController) DeleteRouteRules(_ context.Context, rules []domain.Rout
}
// endregion routing-related
// region statistics-related
func (c LocalController) PingAddresses(
ctx context.Context,
addr string,
) (*domain.PingerResult, error) {
pinger, err := probing.NewPinger(addr)
if err != nil {
return nil, fmt.Errorf("failed to instantiate pinger for %s: %w", addr, err)
}
checkCount := 1
pinger.SetPrivileged(!c.cfg.Statistics.PingUnprivileged)
pinger.Count = checkCount
pinger.Timeout = 2 * time.Second
err = pinger.RunWithContext(ctx) // Blocks until finished.
if err != nil {
return nil, fmt.Errorf("failed to ping %s: %w", addr, err)
}
stats := pinger.Statistics()
return &domain.PingerResult{
PacketsRecv: stats.PacketsRecv,
PacketsSent: stats.PacketsSent,
Rtts: stats.Rtts,
}, nil
}
// endregion statistics-related

View File

@@ -336,3 +336,40 @@ func (c MikrotikController) DeleteRouteRules(_ context.Context, rules []domain.R
}
// endregion routing-related
// region statistics-related
func (c MikrotikController) PingAddresses(
ctx context.Context,
addr string,
) (*domain.PingerResult, error) {
wgReply := c.client.ExecList(ctx, "/tool/ping",
// limit to 1 packet with a max running time of 2 seconds
lowlevel.GenericJsonObject{"address": addr, "count": 1, "interval": "00:00:02"},
)
if wgReply.Status != lowlevel.MikrotikApiStatusOk {
return nil, fmt.Errorf("failed to ping %s: %v", addr, wgReply.Error)
}
var result domain.PingerResult
for _, item := range wgReply.Data {
result.PacketsRecv += item.GetInt("received")
result.PacketsSent += item.GetInt("sent")
rttStr := item.GetString("avg-rtt")
if rttStr != "" {
rtt, err := time.ParseDuration(rttStr)
if err == nil {
result.Rtts = append(result.Rtts, rtt)
} else {
// use a high value to indicate failure or timeout
result.Rtts = append(result.Rtts, 999999*time.Millisecond)
}
}
}
return &result, nil
}
// endregion statistics-related