mirror of
https://github.com/netbirdio/netbird.git
synced 2026-10-06 13:39:07 +02:00
Add peer conn profile code
This commit is contained in:
@@ -0,0 +1,7 @@
|
||||
package connprofile
|
||||
|
||||
import "github.com/netbirdio/netbird/client/iface/configurer"
|
||||
|
||||
type wgIface interface {
|
||||
GetAllStat() (map[string]configurer.WGStats, error)
|
||||
}
|
||||
@@ -0,0 +1,160 @@
|
||||
package connprofile
|
||||
|
||||
import (
|
||||
"sync"
|
||||
"time"
|
||||
|
||||
log "github.com/sirupsen/logrus"
|
||||
|
||||
"github.com/netbirdio/netbird/management/proto"
|
||||
)
|
||||
|
||||
type Profile struct {
|
||||
NetworkMapUpdate time.Time
|
||||
OfferSent time.Time
|
||||
OfferReceived time.Time
|
||||
WireGuardConfigured time.Time
|
||||
WireGuardConnected time.Time
|
||||
}
|
||||
|
||||
type ConnProfiler struct {
|
||||
profiles map[string]*Profile
|
||||
profilesMu sync.Mutex
|
||||
wgIface wgIface
|
||||
wgMu sync.Mutex
|
||||
}
|
||||
|
||||
func NewConnProfiler() *ConnProfiler {
|
||||
return &ConnProfiler{
|
||||
profiles: make(map[string]*Profile),
|
||||
}
|
||||
}
|
||||
|
||||
func (p *ConnProfiler) GetProfiles() map[string]Profile {
|
||||
p.profilesMu.Lock()
|
||||
defer p.profilesMu.Unlock()
|
||||
|
||||
copiedProfiles := make(map[string]Profile)
|
||||
for key, profile := range p.profiles {
|
||||
copiedProfiles[key] = Profile{
|
||||
NetworkMapUpdate: profile.NetworkMapUpdate,
|
||||
OfferSent: profile.OfferSent,
|
||||
OfferReceived: profile.OfferReceived,
|
||||
WireGuardConfigured: profile.WireGuardConfigured,
|
||||
WireGuardConnected: profile.WireGuardConnected,
|
||||
}
|
||||
}
|
||||
return copiedProfiles
|
||||
}
|
||||
|
||||
func (p *ConnProfiler) WGInterfaceUP(wgInterface wgIface) {
|
||||
p.wgMu.Lock()
|
||||
defer p.wgMu.Unlock()
|
||||
|
||||
if p.wgIface != nil {
|
||||
return
|
||||
}
|
||||
|
||||
p.wgIface = wgInterface
|
||||
go p.watchHandshakes()
|
||||
}
|
||||
|
||||
func (p *ConnProfiler) NetworkMapUpdate(peerConfigs []*proto.RemotePeerConfig) {
|
||||
p.profilesMu.Lock()
|
||||
defer p.profilesMu.Unlock()
|
||||
|
||||
for _, peerConfig := range peerConfigs {
|
||||
profile, ok := p.profiles[peerConfig.WgPubKey]
|
||||
if ok {
|
||||
continue
|
||||
}
|
||||
profile = &Profile{
|
||||
NetworkMapUpdate: time.Now(),
|
||||
}
|
||||
p.profiles[peerConfig.WgPubKey] = profile
|
||||
}
|
||||
}
|
||||
|
||||
func (p *ConnProfiler) OfferSent(peerID string) {
|
||||
p.profilesMu.Lock()
|
||||
defer p.profilesMu.Unlock()
|
||||
|
||||
profile, ok := p.profiles[peerID]
|
||||
if !ok {
|
||||
log.Warnf("OfferSent: profile not found for peer %s", peerID)
|
||||
return
|
||||
}
|
||||
|
||||
if !profile.OfferSent.IsZero() {
|
||||
return
|
||||
}
|
||||
profile.OfferSent = time.Now()
|
||||
}
|
||||
|
||||
func (p *ConnProfiler) OfferAnswerReceived(peerID string) {
|
||||
p.profilesMu.Lock()
|
||||
defer p.profilesMu.Unlock()
|
||||
|
||||
profile, ok := p.profiles[peerID]
|
||||
if !ok {
|
||||
log.Warnf("OfferSent: profile not found for peer %s", peerID)
|
||||
return
|
||||
}
|
||||
|
||||
if !profile.OfferReceived.IsZero() {
|
||||
return
|
||||
}
|
||||
profile.OfferReceived = time.Now()
|
||||
}
|
||||
|
||||
func (p *ConnProfiler) WireGuardConfigured(peerID string) {
|
||||
p.profilesMu.Lock()
|
||||
defer p.profilesMu.Unlock()
|
||||
|
||||
profile, ok := p.profiles[peerID]
|
||||
if !ok {
|
||||
log.Warnf("OfferSent: profile not found for peer %s", peerID)
|
||||
return
|
||||
}
|
||||
|
||||
if !profile.WireGuardConfigured.IsZero() {
|
||||
return
|
||||
}
|
||||
profile.WireGuardConfigured = time.Now()
|
||||
}
|
||||
|
||||
func (p *ConnProfiler) watchHandshakes() {
|
||||
ticker := time.NewTicker(300 * time.Millisecond)
|
||||
for {
|
||||
select {
|
||||
case _ = <-ticker.C:
|
||||
p.checkHandshakes()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func (p *ConnProfiler) checkHandshakes() {
|
||||
stats, err := p.wgIface.GetAllStat()
|
||||
if err != nil {
|
||||
log.Errorf("watchHandshakes: %v", err)
|
||||
return
|
||||
}
|
||||
|
||||
p.profilesMu.Lock()
|
||||
for peerID, profile := range p.profiles {
|
||||
if !profile.WireGuardConnected.IsZero() {
|
||||
continue
|
||||
}
|
||||
|
||||
stat, ok := stats[peerID]
|
||||
if !ok {
|
||||
continue
|
||||
}
|
||||
|
||||
if stat.LastHandshake.IsZero() {
|
||||
continue
|
||||
}
|
||||
profile.WireGuardConnected = stat.LastHandshake
|
||||
}
|
||||
p.profilesMu.Unlock()
|
||||
}
|
||||
@@ -0,0 +1,46 @@
|
||||
package connprofile
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"time"
|
||||
|
||||
log "github.com/sirupsen/logrus"
|
||||
)
|
||||
|
||||
type Report struct {
|
||||
NetworkMapUpdate time.Time
|
||||
OfferSent float64
|
||||
OfferReceived float64
|
||||
WireGuardConfigured float64
|
||||
WireGuardConnected float64
|
||||
}
|
||||
|
||||
func report() {
|
||||
ticker := time.NewTicker(5 * time.Second)
|
||||
for {
|
||||
select {
|
||||
case _ = <-ticker.C:
|
||||
printJson()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func printJson() {
|
||||
profiles := Profiler.GetProfiles()
|
||||
reports := make(map[string]Report)
|
||||
for key, profile := range profiles {
|
||||
reports[key] = Report{
|
||||
NetworkMapUpdate: profile.NetworkMapUpdate,
|
||||
OfferSent: profile.OfferSent.Sub(profile.NetworkMapUpdate).Seconds(),
|
||||
OfferReceived: profile.OfferReceived.Sub(profile.OfferSent).Seconds(),
|
||||
WireGuardConfigured: profile.WireGuardConfigured.Sub(profile.OfferReceived).Seconds(),
|
||||
WireGuardConnected: profile.WireGuardConnected.Sub(profile.WireGuardConfigured).Seconds(),
|
||||
}
|
||||
}
|
||||
jsonData, err := json.MarshalIndent(reports, "", " ")
|
||||
if err != nil {
|
||||
log.Errorf("failed to marshal profiles: %v", err)
|
||||
}
|
||||
|
||||
log.Infof("profiles: %s", jsonData)
|
||||
}
|
||||
@@ -0,0 +1,10 @@
|
||||
package connprofile
|
||||
|
||||
var (
|
||||
Profiler *ConnProfiler
|
||||
)
|
||||
|
||||
func init() {
|
||||
Profiler = NewConnProfiler()
|
||||
go report()
|
||||
}
|
||||
Reference in New Issue
Block a user