Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Dedicated RIB option #2662

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3,824 changes: 1,966 additions & 1,858 deletions api/gobgp.pb.go

Large diffs are not rendered by default.

8 changes: 8 additions & 0 deletions api/gobgp.proto
Original file line number Diff line number Diff line change
Expand Up @@ -229,6 +229,7 @@ message AddPathRequest {
TableType table_type = 1;
string vrf_id = 2;
Path path = 3;
string peer_rib = 4;
}

message AddPathResponse { bytes uuid = 1; }
Expand All @@ -239,6 +240,7 @@ message DeletePathRequest {
Family family = 3;
Path path = 4;
bytes uuid = 5;
string peer_rib = 6;
}

// API representation of table.LookupPrefix
Expand Down Expand Up @@ -555,6 +557,7 @@ message Peer {
GracefulRestart graceful_restart = 9;
repeated AfiSafi afi_safis = 10;
TtlSecurity ttl_security = 11;
DedicatedRib dedicated_rib = 12;
}

message PeerGroup {
Expand All @@ -569,6 +572,7 @@ message PeerGroup {
GracefulRestart graceful_restart = 9;
repeated AfiSafi afi_safis = 10;
TtlSecurity ttl_security = 11;
DedicatedRib dedicated_rib = 12;
}

message DynamicNeighbor {
Expand Down Expand Up @@ -1118,3 +1122,7 @@ message SetLogLevelRequest {
}
Level level = 1;
}

message DedicatedRib {
bool enabled = 1;
}
55 changes: 55 additions & 0 deletions internal/pkg/config/bgp_configs.go

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

6 changes: 6 additions & 0 deletions pkg/server/grpc_server.go
Original file line number Diff line number Diff line change
Expand Up @@ -737,6 +737,9 @@ func newNeighborFromAPIStruct(a *api.Peer) (*config.Neighbor, error) {
pconf.TtlSecurity.Config.Enabled = a.TtlSecurity.Enabled
pconf.TtlSecurity.Config.TtlMin = uint8(a.TtlSecurity.TtlMin)
}
if a.DedicatedRib != nil {
pconf.DedicatedRib.Config.Enabled = a.DedicatedRib.Enabled
}
if a.State != nil {
pconf.State.SessionState = config.SessionState(strings.ToUpper(string(a.State.SessionState)))
pconf.State.AdminState = config.IntToAdminStateMap[int(a.State.AdminState)]
Expand Down Expand Up @@ -845,6 +848,9 @@ func newPeerGroupFromAPIStruct(a *api.PeerGroup) (*config.PeerGroup, error) {
pconf.TtlSecurity.Config.Enabled = a.TtlSecurity.Enabled
pconf.TtlSecurity.Config.TtlMin = uint8(a.TtlSecurity.TtlMin)
}
if a.DedicatedRib != nil {
pconf.DedicatedRib.Config.Enabled = a.DedicatedRib.Enabled
}
if a.Info != nil {
pconf.State.TotalPaths = a.Info.TotalPaths
pconf.State.TotalPrefixes = a.Info.TotalPrefixes
Expand Down
8 changes: 7 additions & 1 deletion pkg/server/peer.go
Original file line number Diff line number Diff line change
Expand Up @@ -114,7 +114,7 @@ func newPeer(g *config.Global, conf *config.Neighbor, loc *table.TableManager, p
fsm: newFSM(g, conf, logger),
prefixLimitWarned: make(map[bgp.RouteFamily]bool),
}
if peer.isRouteServerClient() {
if peer.isRouteServerClient() || peer.hasDedicatedRib() {
peer.tableId = conf.State.NeighborAddress
} else {
peer.tableId = table.GLOBAL_RIB_NAME
Expand Down Expand Up @@ -161,6 +161,12 @@ func (peer *peer) isRouteServerClient() bool {
return peer.fsm.pConf.RouteServer.Config.RouteServerClient
}

func (peer *peer) hasDedicatedRib() bool {
peer.fsm.lock.RLock()
defer peer.fsm.lock.RUnlock()
return peer.fsm.pConf.DedicatedRib.Config.Enabled
}

func (peer *peer) isSecondaryRouteEnabled() bool {
peer.fsm.lock.RLock()
defer peer.fsm.lock.RUnlock()
Expand Down
96 changes: 80 additions & 16 deletions pkg/server/server.go
Original file line number Diff line number Diff line change
Expand Up @@ -167,6 +167,7 @@ type BgpServer struct {
peerGroupMap map[string]*peerGroup
globalRib *table.TableManager
rsRib *table.TableManager
dedicatedRib map[string]*table.TableManager
roaManager *roaManager
shutdownWG *sync.WaitGroup
watcherMap map[watchEventType][]*watcher
Expand Down Expand Up @@ -1146,12 +1147,7 @@ func (s *BgpServer) handleRouteRefresh(peer *peer, e *fsmMsg) []*table.Path {

func (s *BgpServer) propagateUpdate(peer *peer, pathList []*table.Path) {
rs := peer != nil && peer.isRouteServerClient()
vrf := false
if peer != nil {
peer.fsm.lock.RLock()
vrf = !rs && peer.fsm.pConf.Config.Vrf != ""
peer.fsm.lock.RUnlock()
}
dedicated := peer != nil && peer.hasDedicatedRib()

tableId := table.GLOBAL_RIB_NAME
rib := s.globalRib
Expand All @@ -1160,6 +1156,23 @@ func (s *BgpServer) propagateUpdate(peer *peer, pathList []*table.Path) {
rib = s.rsRib
}

if dedicated {
tableId = peer.TableID()
rib = s.dedicatedRib[tableId]
}

s.propagateRibUpdate(peer, tableId, rib, pathList)
}

func (s *BgpServer) propagateRibUpdate(peer *peer, tableId string, rib *table.TableManager, pathList []*table.Path) {
rs := peer != nil && peer.isRouteServerClient()
vrf := false
if peer != nil {
peer.fsm.lock.RLock()
vrf = !rs && peer.fsm.pConf.Config.Vrf != ""
peer.fsm.lock.RUnlock()
}

for _, path := range pathList {
if vrf {
peer.fsm.lock.RLock()
Expand Down Expand Up @@ -1252,7 +1265,7 @@ func (s *BgpServer) propagateUpdate(peer *peer, pathList []*table.Path) {
}

if dsts := rib.Update(path); len(dsts) > 0 {
s.propagateUpdateToNeighbors(peer, path, dsts, true)
s.propagateUpdateToNeighbors(tableId, peer, path, dsts, true)
}
}
}
Expand All @@ -1273,19 +1286,21 @@ func dstsToPaths(id string, as uint32, dsts []*table.Update) ([]*table.Path, []*
return bestList, oldList, mpathList
}

func (s *BgpServer) propagateUpdateToNeighbors(source *peer, newPath *table.Path, dsts []*table.Update, needOld bool) {
func (s *BgpServer) propagateUpdateToNeighbors(tableId string, source *peer, newPath *table.Path, dsts []*table.Update, needOld bool) {
if table.SelectionOptions.DisableBestPathSelection {
return
}
var gBestList, gOldList, bestList, oldList []*table.Path
var mpathList [][]*table.Path
if source == nil || !source.isRouteServerClient() {
gBestList, gOldList, mpathList = dstsToPaths(table.GLOBAL_RIB_NAME, 0, dsts)
gBestList, gOldList, mpathList = dstsToPaths(tableId, 0, dsts)
s.notifyBestWatcher(gBestList, mpathList)
}
family := newPath.GetRouteFamily()
for _, targetPeer := range s.neighborMap {
if (source == nil && targetPeer.isRouteServerClient()) || (source != nil && source.isRouteServerClient() != targetPeer.isRouteServerClient()) {
if (source == nil && targetPeer.isRouteServerClient()) ||
(source != nil && source.isRouteServerClient() != targetPeer.isRouteServerClient()) ||
(source == nil && !targetPeer.isRouteServerClient() && tableId != targetPeer.tableId) {
continue
}
f := func() bgp.RouteFamily {
Expand Down Expand Up @@ -2117,6 +2132,18 @@ func (s *BgpServer) addPathList(vrfId string, pathList []*table.Path) error {
return err
}

func (s *BgpServer) addRibPathList(vrfId string, peerRib string, pathList []*table.Path) error {
err := s.fixupApiPath(vrfId, pathList)
if err == nil {
rib, ok := s.dedicatedRib[peerRib]
if !ok {
return fmt.Errorf("rib %s is unknown", peerRib)
}
s.propagateRibUpdate(nil, peerRib, rib, pathList)
}
return err
}

func (s *BgpServer) addPathStream(vrfId string, pathList []*table.Path) error {
err := s.mgmtOperation(func() error {
return s.addPathList(vrfId, pathList)
Expand All @@ -2139,7 +2166,11 @@ func (s *BgpServer) AddPath(ctx context.Context, r *api.AddPathRequest) (*api.Ad
if err != nil {
return err
}
err = s.addPathList(r.VrfId, []*table.Path{path})
if r.PeerRib == "" {
err = s.addPathList(r.VrfId, []*table.Path{path})
} else {
err = s.addRibPathList(r.VrfId, r.PeerRib, []*table.Path{path})
}
if err != nil {
return err
}
Expand Down Expand Up @@ -2211,7 +2242,15 @@ func (s *BgpServer) DeletePath(ctx context.Context, r *api.DeletePathRequest) er
delete(s.uuidMap, pathTokey(p))
}
}
s.propagateUpdate(nil, deletePathList)
if r.PeerRib != "" {
rib, ok := s.dedicatedRib[r.PeerRib]
if !ok {
return fmt.Errorf("rib %s is unknown", r.PeerRib)
}
s.propagateRibUpdate(nil, r.PeerRib, rib, deletePathList)
} else {
s.propagateUpdate(nil, deletePathList)
}
return nil
}, true)
}
Expand Down Expand Up @@ -2257,6 +2296,7 @@ func (s *BgpServer) StartBgp(ctx context.Context, r *api.StartBgpRequest) error
rfs, _ := config.AfiSafis(c.AfiSafis).ToRfList()
s.globalRib = table.NewTableManager(s.logger, rfs)
s.rsRib = table.NewTableManager(s.logger, rfs)
s.dedicatedRib = make(map[string]*table.TableManager)

if err := s.policy.Initialize(); err != nil {
return err
Expand Down Expand Up @@ -2718,12 +2758,16 @@ func (s *BgpServer) getRibInfo(addr string, family bgp.RouteFamily) (info *table
if !ok {
return fmt.Errorf("neighbor that has %v doesn't exist", addr)
}
if !peer.isRouteServerClient() {
if !peer.isRouteServerClient() && !peer.hasDedicatedRib() {
return fmt.Errorf("neighbor %v doesn't have local rib", addr)
}
id = peer.ID()
as = peer.AS()
m = s.rsRib
if peer.isRouteServerClient() {
m = s.rsRib
} else if peer.hasDedicatedRib() {
m = s.dedicatedRib[id]
}
}

af := bgp.RouteFamily(family)
Expand Down Expand Up @@ -3030,6 +3074,12 @@ func (s *BgpServer) addNeighbor(c *config.Neighbor) error {
if c.RouteServer.Config.RouteServerClient && c.RouteReflector.Config.RouteReflectorClient {
return fmt.Errorf("can't be both route-server-client and route-reflector-client")
}
if c.DedicatedRib.Config.Enabled && c.RouteReflector.Config.RouteReflectorClient {
return fmt.Errorf("can't be both dedicated-client and route-reflector-client")
}
if c.DedicatedRib.Config.Enabled && c.RouteServer.Config.RouteServerClient {
return fmt.Errorf("can't be both dedicated-client and route-server-client")
}

if s.bgpConfig.Global.Config.Port > 0 {
for _, l := range s.listListeners(addr) {
Expand All @@ -3052,7 +3102,14 @@ func (s *BgpServer) addNeighbor(c *config.Neighbor) error {
rib := s.globalRib
if c.RouteServer.Config.RouteServerClient {
rib = s.rsRib
} else if c.DedicatedRib.Config.Enabled {
families, _ := config.AfiSafis(c.AfiSafis).ToRfList()
if _, ok := s.dedicatedRib[addr]; !ok {
s.dedicatedRib[addr] = table.NewTableManager(s.logger, families)
}
rib = s.dedicatedRib[addr]
}

peer := newPeer(&s.bgpConfig.Global, c, rib, s.policy, s.logger)
s.addIncoming(peer.fsm.incomingCh)
s.policy.SetPeerPolicy(peer.ID(), c.ApplyPolicy)
Expand Down Expand Up @@ -3165,6 +3222,9 @@ func (s *BgpServer) deleteNeighbor(c *config.Neighbor, code, subcode uint8) erro

delete(s.neighborMap, addr)
s.propagateUpdate(n, n.DropAll(n.configuredRFlist()))
if c.DedicatedRib.Config.Enabled {
delete(s.dedicatedRib, addr)
}
return nil
}

Expand Down Expand Up @@ -4339,12 +4399,16 @@ func (w *watcher) Generate(t watchEventType) error {
if !ok {
return fmt.Errorf("neighbor that has %v doesn't exist", w.opts.tableName)
}
if !peer.isRouteServerClient() {
if !peer.isRouteServerClient() && !peer.hasDedicatedRib() {
return fmt.Errorf("neighbor %v doesn't have local rib", w.opts.tableName)
}
id = peer.ID()
as = peer.AS()
rib = w.s.rsRib
if peer.isRouteServerClient() {
rib = w.s.rsRib
} else if peer.hasDedicatedRib() {
rib = w.s.dedicatedRib[id]
}
}

pathList := func() map[string][]*table.Path {
Expand Down