Skip to content

Commit 529c5a3

Browse files
committed
fix: bgp probe fail with port reused
1 parent 9993c5a commit 529c5a3

File tree

2 files changed

+135
-99
lines changed

2 files changed

+135
-99
lines changed

backend/graph/fetch/bgp/bgp.go

Lines changed: 131 additions & 95 deletions
Original file line numberDiff line numberDiff line change
@@ -4,26 +4,22 @@ import (
44
"context"
55
"fmt"
66
"github.com/BaiMeow/NetworkMonitor/graph/fetch"
7+
"github.com/BaiMeow/NetworkMonitor/utils"
78
apipb "github.com/osrg/gobgp/v3/api"
89
gobgplog "github.com/osrg/gobgp/v3/pkg/log"
910
"github.com/osrg/gobgp/v3/pkg/server"
1011
"github.com/pkg/errors"
1112
"log"
12-
"math"
1313
"net/netip"
1414
"time"
1515
)
1616

1717
func init() {
1818
fetch.Register("bgp", func(m map[string]any) (fetch.Fetcher, error) {
19-
asnRaw, ok := m["asn"].(int)
20-
if !ok {
21-
return nil, fmt.Errorf("asn is not int")
22-
}
23-
if asnRaw > math.MaxUint32 || asnRaw < 0 {
24-
return nil, fmt.Errorf("invalid asn number: %d", asnRaw)
19+
asn, err := utils.MustASN(m["asn"])
20+
if err != nil {
21+
return nil, fmt.Errorf("asn is not valid asn: %v", err)
2522
}
26-
asn := uint32(asnRaw)
2723

2824
routerIdRaw, ok := m["router-id"].(string)
2925
if !ok {
@@ -58,107 +54,141 @@ func init() {
5854
logger := gobgplog.NewDefaultLogger()
5955
logger.SetLevel(gobgplog.ErrorLevel)
6056
bgpServer := server.NewBgpServer(server.LoggerOption(logger))
61-
go bgpServer.Serve()
62-
if err := bgpServer.StartBgp(context.Background(), &apipb.StartBgpRequest{
63-
Global: &apipb.Global{
64-
Asn: asn,
65-
RouterId: routerIdRaw,
66-
ListenPort: int32(port),
67-
UseMultiplePaths: true,
68-
},
69-
}); err != nil {
70-
return nil, err
57+
ctx, cancel := context.WithCancel(context.Background())
58+
bgp := &BGP{
59+
s: bgpServer,
60+
cancel: cancel,
7161
}
72-
73-
if mode == "listen" {
74-
if err := bgpServer.AddPeerGroup(context.Background(), &apipb.AddPeerGroupRequest{
75-
PeerGroup: &apipb.PeerGroup{
76-
Conf: &apipb.PeerGroupConf{
77-
PeerGroupName: "route-collector",
78-
LocalAsn: asn,
79-
},
80-
EbgpMultihop: &apipb.EbgpMultihop{
81-
Enabled: true,
62+
go bgpServer.Serve()
63+
go func() {
64+
for {
65+
select {
66+
case <-ctx.Done():
67+
return
68+
default:
69+
}
70+
if err := bgpServer.StartBgp(ctx, &apipb.StartBgpRequest{
71+
Global: &apipb.Global{
72+
Asn: asn,
73+
RouterId: routerIdRaw,
74+
ListenPort: int32(port),
75+
UseMultiplePaths: true,
8276
},
83-
AfiSafis: []*apipb.AfiSafi{{
84-
Config: &apipb.AfiSafiConfig{
85-
Family: &apipb.Family{
86-
Afi: apipb.Family_AFI_IP,
87-
Safi: apipb.Family_SAFI_UNICAST,
88-
},
89-
},
90-
AddPaths: &apipb.AddPaths{
91-
Config: &apipb.AddPathsConfig{
92-
Receive: true,
93-
},
94-
},
95-
}},
96-
},
97-
}); err != nil {
98-
return nil, err
99-
}
100-
if err := bgpServer.AddDynamicNeighbor(context.Background(), &apipb.AddDynamicNeighborRequest{
101-
DynamicNeighbor: &apipb.DynamicNeighbor{
102-
Prefix: "0.0.0.0/0",
103-
PeerGroup: "route-collector",
104-
},
105-
}); err != nil {
106-
return nil, err
107-
}
108-
} else {
109-
peerASN, ok := m["peer-asn"].(int)
110-
if !ok {
111-
return nil, fmt.Errorf("peer-asn is not int")
112-
}
113-
if peerASN > math.MaxUint32 || peerASN < 0 {
114-
return nil, fmt.Errorf("invalid peer-asn number: %d", asnRaw)
115-
}
116-
117-
neighborAddr, ok := m["neighbor-addr"].(string)
118-
if !ok {
119-
return nil, fmt.Errorf("neighbor-addr is not string")
120-
}
121-
if _, err := netip.ParseAddr(neighborAddr); err != nil {
122-
return nil, fmt.Errorf("invalid neighbor-addr: %s", neighborAddr)
77+
}); err != nil {
78+
log.Printf("start bgp fail: %v", err)
79+
time.Sleep(time.Second * 3)
80+
continue
81+
}
82+
break
12383
}
12484

125-
if err := bgpServer.AddPeer(context.Background(), &apipb.AddPeerRequest{
126-
Peer: &apipb.Peer{
127-
Conf: &apipb.PeerConf{
128-
PeerAsn: uint32(peerASN),
129-
NeighborAddress: neighborAddr,
85+
if mode == "listen" {
86+
if err := bgpServer.AddPeerGroup(context.Background(), &apipb.AddPeerGroupRequest{
87+
PeerGroup: &apipb.PeerGroup{
88+
Conf: &apipb.PeerGroupConf{
89+
PeerGroupName: "route-collector",
90+
LocalAsn: asn,
91+
},
92+
EbgpMultihop: &apipb.EbgpMultihop{
93+
Enabled: true,
94+
},
95+
AfiSafis: []*apipb.AfiSafi{{
96+
Config: &apipb.AfiSafiConfig{
97+
Family: &apipb.Family{
98+
Afi: apipb.Family_AFI_IP,
99+
Safi: apipb.Family_SAFI_UNICAST,
100+
},
101+
},
102+
AddPaths: &apipb.AddPaths{
103+
Config: &apipb.AddPathsConfig{
104+
Receive: true,
105+
},
106+
},
107+
}},
130108
},
131-
EbgpMultihop: &apipb.EbgpMultihop{
132-
Enabled: true,
109+
}); err != nil {
110+
log.Printf("add peer group fail: %v", err)
111+
if err := bgp.CleanUp(); err != nil {
112+
log.Printf("cleaup: %v", err)
113+
}
114+
return
115+
}
116+
if err := bgpServer.AddDynamicNeighbor(context.Background(), &apipb.AddDynamicNeighborRequest{
117+
DynamicNeighbor: &apipb.DynamicNeighbor{
118+
Prefix: "0.0.0.0/0",
119+
PeerGroup: "route-collector",
133120
},
134-
AfiSafis: []*apipb.AfiSafi{{
135-
Config: &apipb.AfiSafiConfig{
136-
Family: &apipb.Family{
137-
Afi: apipb.Family_AFI_IP,
138-
Safi: apipb.Family_SAFI_UNICAST,
139-
},
121+
}); err != nil {
122+
log.Printf("add dyn neighbor: %v", err)
123+
if err := bgp.CleanUp(); err != nil {
124+
log.Printf("cleaup: %v", err)
125+
}
126+
return
127+
}
128+
} else {
129+
peerASN, err := utils.MustASN(m["peer-asn"])
130+
if err != nil {
131+
log.Printf("peer-asn is not valid asn: %v", err)
132+
if err := bgp.CleanUp(); err != nil {
133+
log.Printf("cleaup: %v", err)
134+
}
135+
return
136+
}
137+
neighborAddr, ok := m["neighbor-addr"].(string)
138+
if !ok {
139+
log.Printf("neighbor-addr is not string")
140+
if err := bgp.CleanUp(); err != nil {
141+
log.Printf("cleaup: %v", err)
142+
}
143+
return
144+
}
145+
if _, err := netip.ParseAddr(neighborAddr); err != nil {
146+
log.Printf("invalid neighbor-addr: %s", neighborAddr)
147+
if err := bgp.CleanUp(); err != nil {
148+
log.Printf("cleaup: %v", err)
149+
}
150+
return
151+
}
152+
if err := bgpServer.AddPeer(context.Background(), &apipb.AddPeerRequest{
153+
Peer: &apipb.Peer{
154+
Conf: &apipb.PeerConf{
155+
PeerAsn: uint32(peerASN),
156+
NeighborAddress: neighborAddr,
140157
},
141-
AddPaths: &apipb.AddPaths{
142-
Config: &apipb.AddPathsConfig{
143-
Receive: true,
144-
},
158+
EbgpMultihop: &apipb.EbgpMultihop{
159+
Enabled: true,
145160
},
146-
}},
147-
},
148-
}); err != nil {
149-
return nil, err
161+
AfiSafis: []*apipb.AfiSafi{{
162+
Config: &apipb.AfiSafiConfig{
163+
Family: &apipb.Family{
164+
Afi: apipb.Family_AFI_IP,
165+
Safi: apipb.Family_SAFI_UNICAST,
166+
},
167+
},
168+
AddPaths: &apipb.AddPaths{
169+
Config: &apipb.AddPathsConfig{
170+
Receive: true,
171+
},
172+
},
173+
}},
174+
},
175+
}); err != nil {
176+
log.Printf("add peer fail: %s", neighborAddr)
177+
if err := bgp.CleanUp(); err != nil {
178+
log.Printf("cleaup: %v", err)
179+
}
180+
}
150181
}
151-
}
182+
}()
152183

153-
return &BGP{
154-
s: bgpServer,
155-
}, nil
184+
return bgp, nil
156185
})
157186
}
158187

159188
type BGP struct {
160189
fetch.Base
161-
s *server.BgpServer
190+
s *server.BgpServer
191+
cancel context.CancelFunc
162192
}
163193

164194
func (f *BGP) GetData() (any, error) {
@@ -201,7 +231,13 @@ func (f *BGP) GetData() (any, error) {
201231
}
202232

203233
func (f *BGP) CleanUp() error {
204-
f.s.StopBgp(context.Background(), nil)
234+
if f.cancel != nil {
235+
f.cancel()
236+
}
237+
err := f.s.StopBgp(context.Background(), &apipb.StopBgpRequest{})
238+
if err != nil {
239+
log.Printf("stop bgp: %v", err)
240+
}
205241
f.s.Stop()
206242
return nil
207243
}

backend/graph/fetch/bgp/bgp_test.go

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -11,10 +11,10 @@ import (
1111
func TestBGPDial(t *testing.T) {
1212
bgp, err := fetch.Spawn["bgp"](map[string]any{
1313
"mode": "dial",
14-
"asn": 4211110102,
15-
"router-id": "172.16.4.100",
14+
"asn": 2,
15+
"router-id": "172.16.4.102",
1616
"peer-asn": 4211110101,
17-
"neighbor-addr": "172.16.4.6",
17+
"neighbor-addr": "172.16.4.4",
1818
})
1919
if err != nil {
2020
t.Error(err)
@@ -31,7 +31,7 @@ func TestBGPDial(t *testing.T) {
3131
func TestBGPListen(t *testing.T) {
3232
bgp, err := fetch.Spawn["bgp"](map[string]any{
3333
"mode": "listen",
34-
"asn": 4211110102,
34+
"asn": 2,
3535
"router-id": "172.16.4.100",
3636
})
3737
if err != nil {

0 commit comments

Comments
 (0)