Skip to content

Commit

Permalink
Supporting BGP/MPLS L3VPNs with Frrouting Zebra API 6
Browse files Browse the repository at this point in the history
 - This commit aims to solve reported problem on issues osrg#1611, osrg#1648 and osrg#1912
 - Partial changes of this commit duplicate with changes on PR osrg#1587 (not merged) and PR osrg#1766 (not merged and already closed)
 - This commit is tested with only FRRouting version 6.0.2 (which uses Zebra API 6)
 - This commit fixes lack of LABEL_MANAGER_CONNECT_ASYNC for ZAPI6.
   (This bug is introduced on commit 2bdb76f "Supporting Zebra API version 6 which is used in FRRouting version 6")
  • Loading branch information
irino committed Mar 2, 2019
1 parent 259d9b5 commit 90eeb5d
Showing 14 changed files with 1,099 additions and 556 deletions.
990 changes: 500 additions & 490 deletions api/gobgp.pb.go

Large diffs are not rendered by default.

1 change: 1 addition & 0 deletions api/gobgp.proto
Original file line number Diff line number Diff line change
@@ -414,6 +414,7 @@ message EnableZebraRequest {
uint32 version = 3;
bool nexthop_trigger_enable = 4;
uint32 nexthop_trigger_delay = 5;
uint32 mpls_label_range_size = 6;
}

message EnableMrtRequest {
1 change: 1 addition & 0 deletions cmd/gobgpd/main.go
Original file line number Diff line number Diff line change
@@ -241,6 +241,7 @@ func main() {
Version: uint32(c.Zebra.Config.Version),
NexthopTriggerEnable: c.Zebra.Config.NexthopTriggerEnable,
NexthopTriggerDelay: uint32(c.Zebra.Config.NexthopTriggerDelay),
MplsLabelRangeSize: uint32(c.Zebra.Config.MplsLabelRangeSize),
}); err != nil {
log.Fatalf("failed to set zebra config: %s", err)
}
17 changes: 15 additions & 2 deletions internal/pkg/config/bgp_configs.go
Original file line number Diff line number Diff line change
@@ -1121,13 +1121,18 @@ type ZebraState struct {
// original -> gobgp:redistribute-route-type
RedistributeRouteTypeList []string `mapstructure:"redistribute-route-type-list" json:"redistribute-route-type-list,omitempty"`
// original -> gobgp:version
// Configure version of zebra protocol. Default is 2. Supported up to 3.
// Configure version of zebra protocol. Default is 2.
// Supported version are 2 or 3 for Quagga and 4, 5 or 6 for FRRouting.
Version uint8 `mapstructure:"version" json:"version,omitempty"`
// original -> gobgp:nexthop-trigger-enable
// gobgp:nexthop-trigger-enable's original type is boolean.
NexthopTriggerEnable bool `mapstructure:"nexthop-trigger-enable" json:"nexthop-trigger-enable,omitempty"`
// original -> gobgp:nexthop-trigger-delay
NexthopTriggerDelay uint8 `mapstructure:"nexthop-trigger-delay" json:"nexthop-trigger-delay,omitempty"`
// original -> gobgp:mpls-label-range-size
// Configure MPLS label range size which will be requested to
// FRR/Zebra.
MplsLabelRangeSize uint32 `mapstructure:"mpls-label-range-size" json:"mpls-label-range-size,omitempty"`
}

// struct for container gobgp:config.
@@ -1142,13 +1147,18 @@ type ZebraConfig struct {
// original -> gobgp:redistribute-route-type
RedistributeRouteTypeList []string `mapstructure:"redistribute-route-type-list" json:"redistribute-route-type-list,omitempty"`
// original -> gobgp:version
// Configure version of zebra protocol. Default is 2. Supported up to 3.
// Configure version of zebra protocol. Default is 2.
// Supported version are 2 or 3 for Quagga and 4, 5 or 6 for FRRouting.
Version uint8 `mapstructure:"version" json:"version,omitempty"`
// original -> gobgp:nexthop-trigger-enable
// gobgp:nexthop-trigger-enable's original type is boolean.
NexthopTriggerEnable bool `mapstructure:"nexthop-trigger-enable" json:"nexthop-trigger-enable,omitempty"`
// original -> gobgp:nexthop-trigger-delay
NexthopTriggerDelay uint8 `mapstructure:"nexthop-trigger-delay" json:"nexthop-trigger-delay,omitempty"`
// original -> gobgp:mpls-label-range-size
// Configure MPLS label range size which will be requested to
// FRR/Zebra.
MplsLabelRangeSize uint32 `mapstructure:"mpls-label-range-size" json:"mpls-label-range-size,omitempty"`
}

func (lhs *ZebraConfig) Equal(rhs *ZebraConfig) bool {
@@ -1178,6 +1188,9 @@ func (lhs *ZebraConfig) Equal(rhs *ZebraConfig) bool {
if lhs.NexthopTriggerDelay != rhs.NexthopTriggerDelay {
return false
}
if lhs.MplsLabelRangeSize != rhs.MplsLabelRangeSize {
return false
}
return true
}

38 changes: 25 additions & 13 deletions internal/pkg/table/path.go
Original file line number Diff line number Diff line change
@@ -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,13 +334,21 @@ 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{
parent: 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
}

76 changes: 68 additions & 8 deletions internal/pkg/table/table_manager.go
Original file line number Diff line number Diff line change
@@ -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)...)
22 changes: 12 additions & 10 deletions internal/pkg/table/vrf.go
Original file line number Diff line number Diff line change
@@ -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,
}
}

4 changes: 2 additions & 2 deletions internal/pkg/zebra/api_type_string.go

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

16 changes: 16 additions & 0 deletions internal/pkg/zebra/lsp_type_string.go

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

4 changes: 2 additions & 2 deletions internal/pkg/zebra/safi_string.go

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

Loading

0 comments on commit 90eeb5d

Please sign in to comment.