diff options
Diffstat (limited to 'internal/pkg/table')
-rw-r--r-- | internal/pkg/table/path.go | 38 | ||||
-rw-r--r-- | internal/pkg/table/table_manager.go | 76 | ||||
-rw-r--r-- | internal/pkg/table/vrf.go | 22 |
3 files changed, 105 insertions, 31 deletions
diff --git a/internal/pkg/table/path.go b/internal/pkg/table/path.go index eba0a6ec..bdeb6ff2 100644 --- a/internal/pkg/table/path.go +++ b/internal/pkg/table/path.go @@ -133,13 +133,14 @@ type Validation struct { } type Path struct { - info *originInfo - parent *Path - pathAttrs []bgp.PathAttributeInterface - dels []bgp.BGPAttrType - attrsHash uint32 - aslooped bool - reason BestPathReason + info *originInfo + parent *Path + pathAttrs []bgp.PathAttributeInterface + dels []bgp.BGPAttrType + attrsHash uint32 + aslooped bool + reason BestPathReason + receiveVrfId uint32 //VRF in which the path was received. // For BGP Nexthop Tracking, this field shows if nexthop is invalidated by IGP. IsNexthopInvalid bool @@ -167,8 +168,9 @@ func NewPath(source *PeerInfo, nlri bgp.AddrPrefixInterface, isWithdraw bool, pa timestamp: timestamp.Unix(), noImplicitWithdraw: noImplicitWithdraw, }, - IsWithdraw: isWithdraw, - pathAttrs: pattrs, + IsWithdraw: isWithdraw, + pathAttrs: pattrs, + receiveVrfId: 0, } } @@ -332,6 +334,13 @@ func (path *Path) IsIBGP() bool { return (as == path.GetSource().LocalAS) && as != 0 } +func (path *Path) ReceiveVrfId() uint32 { + return path.receiveVrfId +} +func (path *Path) SetReceiveVrfId(vrfId uint32) { + path.receiveVrfId = vrfId +} + // create new PathAttributes func (path *Path) Clone(isWithdraw bool) *Path { return &Path{ @@ -339,6 +348,7 @@ func (path *Path) Clone(isWithdraw bool) *Path { IsWithdraw: isWithdraw, IsNexthopInvalid: path.IsNexthopInvalid, attrsHash: path.attrsHash, + receiveVrfId: path.receiveVrfId, } } @@ -580,6 +590,7 @@ func (path *Path) String() string { if path.IsWithdraw { s.WriteString(", withdraw") } + s.WriteString(fmt.Sprintf(", receiveVrfId: %d", path.receiveVrfId)) s.WriteString(" }") return s.String() } @@ -1069,12 +1080,12 @@ func (v *Vrf) ToGlobalPath(path *Path) error { case bgp.RF_IPv4_UC: n := nlri.(*bgp.IPAddrPrefix) pathIdentifier := path.GetNlri().PathIdentifier() - path.OriginInfo().nlri = bgp.NewLabeledVPNIPAddrPrefix(n.Length, n.Prefix.String(), *bgp.NewMPLSLabelStack(0), v.Rd) + path.OriginInfo().nlri = bgp.NewLabeledVPNIPAddrPrefix(n.Length, n.Prefix.String(), *bgp.NewMPLSLabelStack(v.MplsLabel), v.Rd) path.GetNlri().SetPathIdentifier(pathIdentifier) case bgp.RF_IPv6_UC: n := nlri.(*bgp.IPv6AddrPrefix) pathIdentifier := path.GetNlri().PathIdentifier() - path.OriginInfo().nlri = bgp.NewLabeledVPNIPv6AddrPrefix(n.Length, n.Prefix.String(), *bgp.NewMPLSLabelStack(0), v.Rd) + path.OriginInfo().nlri = bgp.NewLabeledVPNIPv6AddrPrefix(n.Length, n.Prefix.String(), *bgp.NewMPLSLabelStack(v.MplsLabel), v.Rd) path.GetNlri().SetPathIdentifier(pathIdentifier) case bgp.RF_EVPN: n := nlri.(*bgp.EVPNNLRI) @@ -1098,11 +1109,11 @@ func (p *Path) ToGlobal(vrf *Vrf) *Path { switch rf := p.GetRouteFamily(); rf { case bgp.RF_IPv4_UC: n := nlri.(*bgp.IPAddrPrefix) - nlri = bgp.NewLabeledVPNIPAddrPrefix(n.Length, n.Prefix.String(), *bgp.NewMPLSLabelStack(0), vrf.Rd) + nlri = bgp.NewLabeledVPNIPAddrPrefix(n.Length, n.Prefix.String(), *bgp.NewMPLSLabelStack(vrf.MplsLabel), vrf.Rd) nlri.SetPathIdentifier(pathId) case bgp.RF_IPv6_UC: n := nlri.(*bgp.IPv6AddrPrefix) - nlri = bgp.NewLabeledVPNIPv6AddrPrefix(n.Length, n.Prefix.String(), *bgp.NewMPLSLabelStack(0), vrf.Rd) + nlri = bgp.NewLabeledVPNIPv6AddrPrefix(n.Length, n.Prefix.String(), *bgp.NewMPLSLabelStack(vrf.MplsLabel), vrf.Rd) nlri.SetPathIdentifier(pathId) case bgp.RF_EVPN: n := nlri.(*bgp.EVPNNLRI) @@ -1138,6 +1149,7 @@ func (p *Path) ToGlobal(vrf *Vrf) *Path { path.delPathAttr(bgp.BGP_ATTR_TYPE_NEXT_HOP) path.setPathAttr(bgp.NewPathAttributeMpReachNLRI(nh.String(), []bgp.AddrPrefixInterface{nlri})) path.IsNexthopInvalid = p.IsNexthopInvalid + path.receiveVrfId = p.receiveVrfId return path } diff --git a/internal/pkg/table/table_manager.go b/internal/pkg/table/table_manager.go index 58c09bf3..45698504 100644 --- a/internal/pkg/table/table_manager.go +++ b/internal/pkg/table/table_manager.go @@ -105,9 +105,10 @@ func ProcessMessage(m *bgp.BGPMessage, peerInfo *PeerInfo, timestamp time.Time) } type TableManager struct { - Tables map[bgp.RouteFamily]*Table - Vrfs map[string]*Vrf - rfList []bgp.RouteFamily + Tables map[bgp.RouteFamily]*Table + Vrfs map[string]*Vrf + rfList []bgp.RouteFamily + mplsLabelMaps map[uint64]*Bitmap } func NewTableManager(rfList []bgp.RouteFamily) *TableManager { @@ -122,6 +123,63 @@ func NewTableManager(rfList []bgp.RouteFamily) *TableManager { return t } +func (manager *TableManager) EnableMplsLabelAllocation() error { + if manager.mplsLabelMaps != nil { + return fmt.Errorf("label allocation already enabled") + } + manager.mplsLabelMaps = make(map[uint64]*Bitmap) + return nil +} + +func (manager *TableManager) AllocateMplsLabelRange(start, end uint32) error { + if manager.mplsLabelMaps == nil { + return fmt.Errorf("label allocation not yet enabled") + } + log.WithFields(log.Fields{ + "Topic": "Vrf", + "Start": start, + "End": end, + }).Debug("allocate new MPLS label range") + startEnd := uint64(start)<<32 | uint64(end) + manager.mplsLabelMaps[startEnd] = NewBitmap(int(end - start + 1)) + return nil +} + +func (manager *TableManager) AssignMplsLabel() (uint32, error) { + if manager.mplsLabelMaps == nil { + return 0, nil + } + var label uint32 + for startEnd, bitmap := range manager.mplsLabelMaps { + start := uint32(startEnd >> 32) + end := uint32(startEnd & 0xffffffff) + l, err := bitmap.FindandSetZeroBit() + if err == nil && start+uint32(l) <= end { + label = start + uint32(l) + break + } + } + if label == 0 { + return 0, fmt.Errorf("could not assign new MPLS label; need to allocate new MPLS label range") + } + return label, nil +} + +func (manager *TableManager) releaseMplsLabel(label uint32) { + if manager.mplsLabelMaps == nil { + return + } + for startEnd, bitmap := range manager.mplsLabelMaps { + start := uint32(startEnd >> 32) + end := uint32(startEnd & 0xffffffff) + if start <= label && label <= end { + bitmap.Unflag(uint(label - start)) + return + } + } + return +} + func (manager *TableManager) GetRFlist() []bgp.RouteFamily { return manager.rfList } @@ -166,12 +224,14 @@ func (manager *TableManager) DeleteVrf(name string) ([]*Path, error) { msgs = append(msgs, t.deletePathsByVrf(vrf)...) } log.WithFields(log.Fields{ - "Topic": "Vrf", - "Key": vrf.Name, - "Rd": vrf.Rd, - "ImportRt": vrf.ImportRt, - "ExportRt": vrf.ExportRt, + "Topic": "Vrf", + "Key": vrf.Name, + "Rd": vrf.Rd, + "ImportRt": vrf.ImportRt, + "ExportRt": vrf.ExportRt, + "MplsLabel": vrf.MplsLabel, }).Debugf("delete vrf") + manager.releaseMplsLabel(vrf.MplsLabel) delete(manager.Vrfs, name) rtcTable := manager.Tables[bgp.RF_RTC_UC] msgs = append(msgs, rtcTable.deleteRTCPathsByVrf(vrf, manager.Vrfs)...) diff --git a/internal/pkg/table/vrf.go b/internal/pkg/table/vrf.go index 053f85ce..dc98e57d 100644 --- a/internal/pkg/table/vrf.go +++ b/internal/pkg/table/vrf.go @@ -20,11 +20,12 @@ import ( ) type Vrf struct { - Name string - Id uint32 - Rd bgp.RouteDistinguisherInterface - ImportRt []bgp.ExtendedCommunityInterface - ExportRt []bgp.ExtendedCommunityInterface + Name string + Id uint32 + Rd bgp.RouteDistinguisherInterface + ImportRt []bgp.ExtendedCommunityInterface + ExportRt []bgp.ExtendedCommunityInterface + MplsLabel uint32 } func (v *Vrf) Clone() *Vrf { @@ -33,11 +34,12 @@ func (v *Vrf) Clone() *Vrf { return append(l, rt...) } return &Vrf{ - Name: v.Name, - Id: v.Id, - Rd: v.Rd, - ImportRt: f(v.ImportRt), - ExportRt: f(v.ExportRt), + Name: v.Name, + Id: v.Id, + Rd: v.Rd, + ImportRt: f(v.ImportRt), + ExportRt: f(v.ExportRt), + MplsLabel: v.MplsLabel, } } |