Skip to content

Commit

Permalink
Track Route Reflection Cluster IDs within the VRF scope
Browse files Browse the repository at this point in the history
  To make sure we don't have any Cluster list loops we need to check all the
  Cluster IDs used by all sessions within a VRF as in theory there could be
  multiple iBGP sessions with different cluster IDs set.

Signed-off-by: Maximilian Wilhelm <max@sdn.clinic>
  • Loading branch information
BarbarossaTM committed Jan 9, 2023
1 parent 7621c8a commit d98fea0
Show file tree
Hide file tree
Showing 4 changed files with 40 additions and 14 deletions.
7 changes: 7 additions & 0 deletions protocols/bgp/server/fsm_address_family.go
Original file line number Diff line number Diff line change
Expand Up @@ -95,6 +95,9 @@ func (f *fsmAddressFamily) init() {

f.adjRIBIn = f.fsm.peer.adjRIBInFactory.New(f.importFilterChain, f.fsm.peer.vrf, sessionAttrs)
f.fsm.peer.vrf.AddContributingASN(f.fsm.peer.localASN)
if f.fsm.peer.routeReflectorClient {
f.fsm.peer.vrf.AddContributingClusterID(f.fsm.peer.clusterID)
}

f.adjRIBIn.Register(f.rib)

Expand Down Expand Up @@ -163,6 +166,10 @@ func (f *fsmAddressFamily) dispose() {
}

f.fsm.peer.vrf.RemoveContributingASN(f.fsm.peer.localASN)
if f.fsm.peer.routeReflectorClient {
f.fsm.peer.vrf.RemoveContributingClusterID(f.fsm.peer.clusterID)
}

f.adjRIBIn.Unregister(f.rib)
f.rib.Unregister(f.adjRIBOut)
f.adjRIBOut.Unregister(f.updateSender)
Expand Down
4 changes: 2 additions & 2 deletions routingtable/adjRIBIn/adj_rib_in.go
Original file line number Diff line number Diff line change
Expand Up @@ -296,10 +296,10 @@ func (a *AdjRIBIn) validatePath(p *route.Path) uint8 {
return route.HiddenReasonOurOriginatorID
}

// RFC4456 Sect. 8: Ignore routes which contain our ClusterID in their ClusterList
// RFC4456 Sect. 8: Ignore routes which contains any ClusterID used within this VRF in their ClusterList
if p.BGPPath.ClusterList != nil && len(*p.BGPPath.ClusterList) > 0 {
for _, cid := range *p.BGPPath.ClusterList {
if cid == a.sessionAttrs.ClusterID {
if a.vrf.IsContributingClusterID(cid) {
return route.HiddenReasonClusterLoop
}
}
Expand Down
4 changes: 3 additions & 1 deletion routingtable/adjRIBIn/adj_rib_in_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -266,7 +266,9 @@ func TestAddPath(t *testing.T) {
ClusterID: clusterID,
AddPathRX: test.addPath,
}
adjRIBIn := New(filter.NewAcceptAllFilterChain(), vrf.NewUntrackedVRF("vrf0", 0), sessionAttrs)
vrf := vrf.NewUntrackedVRF("vrf0", 0)
vrf.AddContributingClusterID(clusterID)
adjRIBIn := New(filter.NewAcceptAllFilterChain(), vrf, sessionAttrs)
mc := routingtable.NewRTMockClient()
adjRIBIn.clientManager.RegisterWithOptions(mc, routingtable.ClientOptions{BestOnly: true})

Expand Down
39 changes: 28 additions & 11 deletions routingtable/vrf/vrf.go
Original file line number Diff line number Diff line change
Expand Up @@ -25,12 +25,13 @@ type addressFamily struct {

// VRF a list of RIBs for different address families building a routing instance
type VRF struct {
name string
routeDistinguisher uint64
ribs map[addressFamily]*locRIB.LocRIB
mu sync.Mutex
ribNames map[string]*locRIB.LocRIB
contributingASNs *refcounter.RefcounterUint32
name string
routeDistinguisher uint64
ribs map[addressFamily]*locRIB.LocRIB
mu sync.Mutex
ribNames map[string]*locRIB.LocRIB
contributingASNs *refcounter.RefcounterUint32
contributingClusterIDs *refcounter.RefcounterUint32
}

// New creates a new VRF. The VRF is registered automatically to the global VRF registry.
Expand All @@ -49,11 +50,12 @@ func New(name string, rd uint64) (*VRF, error) {

func NewUntrackedVRF(name string, rd uint64) *VRF {
return &VRF{
name: name,
routeDistinguisher: rd,
ribs: make(map[addressFamily]*locRIB.LocRIB),
ribNames: make(map[string]*locRIB.LocRIB),
contributingASNs: refcounter.NewRefCounterUint32(),
name: name,
routeDistinguisher: rd,
ribs: make(map[addressFamily]*locRIB.LocRIB),
ribNames: make(map[string]*locRIB.LocRIB),
contributingASNs: refcounter.NewRefCounterUint32(),
contributingClusterIDs: refcounter.NewRefCounterUint32(),
}
}

Expand Down Expand Up @@ -139,6 +141,21 @@ func (v *VRF) IsContributingASN(asn uint32) bool {
return v.contributingASNs.IsPresent(asn)
}

// AddContributingASN adds the given ClusterID to the list of ClusterIDs is used by this BGP speaker somewhere within this VRF
func (v *VRF) AddContributingClusterID(cid uint32) {
v.contributingClusterIDs.Add(cid)
}

// RemoveContributingASN removes the given ClusterID from the list of ClusterIDs is used by this BGP speaker somewhere within this VRF
func (v *VRF) RemoveContributingClusterID(cid uint32) {
v.contributingClusterIDs.Remove(cid)
}

// IsContributingASN returns wether the given ClusterID is used by this BGP speaker somewhere within this VRF
func (v *VRF) IsContributingClusterID(cid uint32) bool {
return v.contributingClusterIDs.IsPresent(cid)
}

func (v *VRF) nameForRIB(rib *locRIB.LocRIB) string {
for name, r := range v.ribNames {
if r == rib {
Expand Down

0 comments on commit d98fea0

Please sign in to comment.