Skip to content

Commit

Permalink
BGP: Make TCP listener VRF aware
Browse files Browse the repository at this point in the history
  • Loading branch information
taktv6 committed Jan 7, 2023
1 parent 8269abc commit 8848101
Show file tree
Hide file tree
Showing 14 changed files with 332 additions and 163 deletions.
32 changes: 17 additions & 15 deletions cmd/bio-rd/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -61,12 +61,17 @@ func main() {
os.Exit(1)
}

bgpSrv = bgpserver.NewBGPServer(
startCfg.RoutingOptions.RouterIDUint32,
[]string{
listenAddrsByVRF := map[string][]string{
vrf.DefaultVRFName: {
"[::]:179",
"0.0.0.0:179",
},
}

bgpSrv = bgpserver.NewBGPServer(
startCfg.RoutingOptions.RouterIDUint32,
vrfReg.CreateVRFIfNotExists(vrf.DefaultVRFName, 0),
listenAddrsByVRF,
)

err = bgpSrv.Start()
Expand All @@ -75,13 +80,11 @@ func main() {
os.Exit(1)
}

vrfReg.CreateVRFIfNotExists(vrf.DefaultVRFName, 0)

go configReloader()
sigHUP <- syscall.SIGHUP
installSignalHandler()

s := bgpserver.NewBGPAPIServer(bgpSrv)
s := bgpserver.NewBGPAPIServer(bgpSrv, vrfReg)
isisAPISrv := isisserver.NewISISAPIServer(isisSrv)
unaryInterceptors := []grpc.UnaryServerInterceptor{}
streamInterceptors := []grpc.StreamServerInterceptor{}
Expand Down Expand Up @@ -135,7 +138,6 @@ func configReloader() {
}

func loadConfig(cfg *config.Config) error {

for _, ri := range cfg.RoutingInstances {
err := configureRoutingInstance(ri)
_ = err
Expand Down Expand Up @@ -167,41 +169,41 @@ func configureProtocolsBGP(bgp *config.BGP) error {
found := false
for _, g := range bgp.Groups {
for _, n := range g.Neighbors {
if n.PeerAddressIP == p {
if n.PeerAddressIP == p.Addr() && p.VRF() == bgpSrv.GetDefaultVRF() {
found = true
break
}
}
}

if !found {
bgpSrv.DisposePeer(p)
bgpSrv.DisposePeer(bgpSrv.GetDefaultVRF(), p.Addr())
}
}

// Tear down peers that need new sessions as they changed too significantly
for _, g := range bgp.Groups {
for _, n := range g.Neighbors {
newCfg := BGPPeerConfig(n, vrfReg.GetVRFByName(vrf.DefaultVRFName))
oldCfg := bgpSrv.GetPeerConfig(n.PeerAddressIP)
newCfg := BGPPeerConfig(n, bgpSrv.GetDefaultVRF())
oldCfg := bgpSrv.GetPeerConfig(bgpSrv.GetDefaultVRF(), n.PeerAddressIP)
if oldCfg == nil {
continue
}

if !oldCfg.NeedsRestart(newCfg) {
bgpSrv.ReplaceImportFilterChain(n.PeerAddressIP, newCfg.IPv4.ImportFilterChain)
bgpSrv.ReplaceExportFilterChain(n.PeerAddressIP, newCfg.IPv4.ExportFilterChain)
bgpSrv.ReplaceImportFilterChain(bgpSrv.GetDefaultVRF(), n.PeerAddressIP, newCfg.IPv4.ImportFilterChain)
bgpSrv.ReplaceExportFilterChain(bgpSrv.GetDefaultVRF(), n.PeerAddressIP, newCfg.IPv4.ExportFilterChain)
continue
}

bgpSrv.DisposePeer(oldCfg.PeerAddress)
bgpSrv.DisposePeer(bgpSrv.GetDefaultVRF(), oldCfg.PeerAddress)
}
}

// Turn up all sessions that are missing
for _, g := range bgp.Groups {
for _, n := range g.Neighbors {
if bgpSrv.GetPeerConfig(n.PeerAddressIP) != nil {
if bgpSrv.GetPeerConfig(bgpSrv.GetDefaultVRF(), n.PeerAddressIP) != nil {
continue
}

Expand Down
11 changes: 6 additions & 5 deletions examples/bgp/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -35,14 +35,15 @@ func main() {
listen = append(listen, "[::]:179")
}

b := server.NewBGPServer(0, listen)
v, err := vrf.New("master", 0)
v, err := vrf.New(vrf.DefaultVRFName, 0)
if err != nil {
logrus.Fatal(err)
}

b := server.NewBGPServer(0, v, map[string][]string{vrf.DefaultVRFName: listen})

go startMetricsEndpoint(b)
go startAPIEndpoint(b)
go startAPIEndpoint(b, vrf.GetGlobalRegistry())

if err := b.Start(); err != nil {
log.Fatalf("Unable to start BGP server: %v", err)
Expand All @@ -69,8 +70,8 @@ func startMetricsEndpoint(server server.BGPServer) {
logrus.Error(http.ListenAndServe(":8080", nil))
}

func startAPIEndpoint(b server.BGPServer) {
apiSrv := server.NewBGPAPIServer(b)
func startAPIEndpoint(b server.BGPServer, vrfReg *vrf.VRFRegistry) {
apiSrv := server.NewBGPAPIServer(b, vrfReg)

lis, err := net.Listen("tcp", ":1337")
if err != nil {
Expand Down
11 changes: 10 additions & 1 deletion net/tcp/listen.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import (
"fmt"
"net"

"github.com/bio-routing/bio-rd/routingtable/vrf"
"golang.org/x/sys/unix"
)

Expand All @@ -14,7 +15,7 @@ type Listener struct {
}

// Listen starts a TCPListener
func Listen(laddr *net.TCPAddr, ttl uint8) (*Listener, error) {
func Listen(v *vrf.VRF, laddr *net.TCPAddr, ttl uint8) (*Listener, error) {
l := &Listener{
laddr: laddr,
}
Expand Down Expand Up @@ -52,6 +53,14 @@ func Listen(laddr *net.TCPAddr, ttl uint8) (*Listener, error) {
}
}

if v.Name() != vrf.DefaultVRFName {
err = unix.SetsockoptString(fd, SOL_IP, unix.SO_BINDTODEVICE, v.Name())
if err != nil {
unix.Close(fd)
return nil, fmt.Errorf("unable to set SO_BINDTODEVICE (%s): %v", v.Name(), err)
}
}

if laddr.IP.To4() != nil {
err = unix.Bind(fd, &unix.SockaddrInet4{
Port: laddr.Port,
Expand Down
53 changes: 31 additions & 22 deletions protocols/bgp/api/bgp.pb.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions protocols/bgp/api/bgp.proto
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ message DumpRIBRequest {
bio.net.IP peer = 1;
uint32 afi = 2;
uint32 safi = 3;
string vrf_name = 4;
}

service BgpService {
Expand Down
31 changes: 26 additions & 5 deletions protocols/bgp/server/bgp_api.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,19 +5,22 @@ import (
"fmt"

"github.com/bio-routing/bio-rd/protocols/bgp/api"
"github.com/bio-routing/bio-rd/routingtable/vrf"

bnet "github.com/bio-routing/bio-rd/net"
)

type BGPAPIServer struct {
api.UnimplementedBgpServiceServer
srv BGPServer
srv BGPServer
vrfReg *vrf.VRFRegistry
}

// NewBGPAPIServer creates a new BGP API Server
func NewBGPAPIServer(s BGPServer) *BGPAPIServer {
func NewBGPAPIServer(s BGPServer, vrfReg *vrf.VRFRegistry) *BGPAPIServer {
return &BGPAPIServer{
srv: s,
srv: s,
vrfReg: vrfReg,
}
}

Expand All @@ -27,7 +30,12 @@ func (s *BGPAPIServer) ListSessions(ctx context.Context, in *api.ListSessionsReq

// DumpRIBIn dumps the RIB in of a peer for a given AFI/SAFI
func (s *BGPAPIServer) DumpRIBIn(in *api.DumpRIBRequest, stream api.BgpService_DumpRIBInServer) error {
r := s.srv.GetRIBIn(bnet.IPFromProtoIP(in.Peer).Ptr(), uint16(in.Afi), uint8(in.Safi))
v := s.getVRF(in)
if v == nil {
return fmt.Errorf("unable to find vrf %q", in.VrfName)
}

r := s.srv.GetRIBIn(v, bnet.IPFromProtoIP(in.Peer).Ptr(), uint16(in.Afi), uint8(in.Safi))
if r == nil {
return fmt.Errorf("unable to get AdjRIBIn")
}
Expand All @@ -45,7 +53,12 @@ func (s *BGPAPIServer) DumpRIBIn(in *api.DumpRIBRequest, stream api.BgpService_D

// DumpRIBOut dumps the RIB out of a peer for a given AFI/SAFI
func (s *BGPAPIServer) DumpRIBOut(in *api.DumpRIBRequest, stream api.BgpService_DumpRIBOutServer) error {
r := s.srv.GetRIBOut(bnet.IPFromProtoIP(in.Peer).Ptr(), uint16(in.Afi), uint8(in.Safi))
v := s.getVRF(in)
if v == nil {
return fmt.Errorf("unable to find vrf %q", in.VrfName)
}

r := s.srv.GetRIBOut(v, bnet.IPFromProtoIP(in.Peer).Ptr(), uint16(in.Afi), uint8(in.Safi))
if r == nil {
return fmt.Errorf("unable to get AdjRIBOut")
}
Expand All @@ -60,3 +73,11 @@ func (s *BGPAPIServer) DumpRIBOut(in *api.DumpRIBRequest, stream api.BgpService_

return nil
}

func (s *BGPAPIServer) getVRF(in *api.DumpRIBRequest) *vrf.VRF {
if in.VrfName == "" {
in.VrfName = vrf.DefaultVRFName
}

return s.vrfReg.GetVRFByName(in.VrfName)
}
Loading

0 comments on commit 8848101

Please sign in to comment.