Supporting BGP/MPLS L3VPNs with Frrouting Zebra API 6

- This commit aims to solve reported problem on issues #1611, #1648 and #1912
 - Partial changes of this commit duplicate with changes on PR #1587 (not merged) and PR #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 2bdb76f2dc "Supporting Zebra API version 6 which is used in FRRouting version 6")
This commit is contained in:
Hitoshi Irino
2019-03-14 21:20:31 +09:00
committed by FUJITA Tomonori
parent dc4d9c6d1b
commit 3a79ad3fdc
14 changed files with 1099 additions and 556 deletions
+500 -490
View File
File diff suppressed because it is too large Load Diff
+1
View File
@@ -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
View File
@@ -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)
}
+15 -2
View File
@@ -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
}
+25 -13
View File
@@ -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
}
+68 -8
View File
@@ -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)...)
+12 -10
View File
@@ -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,
}
}
+2 -2
View File
@@ -4,9 +4,9 @@ package zebra
import "strconv"
const _API_TYPE_name = "FRR_ZAPI6_INTERFACE_ADDFRR_ZAPI6_INTERFACE_DELETEFRR_ZAPI6_INTERFACE_ADDRESS_ADDFRR_ZAPI6_INTERFACE_ADDRESS_DELETEFRR_ZAPI6_INTERFACE_UPFRR_ZAPI6_INTERFACE_DOWNFRR_ZAPI6_INTERFACE_SET_MASTERFRR_ZAPI6_ROUTE_ADDFRR_ZAPI6_ROUTE_DELETEFRR_ZAPI6_ROUTE_NOTIFY_OWNERFRR_ZAPI6_REDISTRIBUTE_ADDFRR_ZAPI6_REDISTRIBUTE_DELETEFRR_ZAPI6_REDISTRIBUTE_DEFAULT_ADDFRR_ZAPI6_REDISTRIBUTE_DEFAULT_DELETEFRR_ZAPI6_ROUTER_ID_ADDFRR_ZAPI6_ROUTER_ID_DELETEFRR_ZAPI6_ROUTER_ID_UPDATEFRR_ZAPI6_HELLOFRR_ZAPI6_CAPABILITIESFRR_ZAPI6_NEXTHOP_REGISTERFRR_ZAPI6_NEXTHOP_UNREGISTERFRR_ZAPI6_NEXTHOP_UPDATEFRR_ZAPI6_INTERFACE_NBR_ADDRESS_ADDFRR_ZAPI6_INTERFACE_NBR_ADDRESS_DELETEFRR_ZAPI6_INTERFACE_BFD_DEST_UPDATEFRR_ZAPI6_IMPORT_ROUTE_REGISTERFRR_ZAPI6_IMPORT_ROUTE_UNREGISTERFRR_ZAPI6_IMPORT_CHECK_UPDATEFRR_ZAPI6_IPV4_ROUTE_IPV6_NEXTHOP_ADDFRR_ZAPI6_BFD_DEST_REGISTERFRR_ZAPI6_BFD_DEST_DEREGISTERFRR_ZAPI6_BFD_DEST_UPDATEFRR_ZAPI6_BFD_DEST_REPLAYFRR_ZAPI6_REDISTRIBUTE_ROUTE_ADDFRR_ZAPI6_REDISTRIBUTE_ROUTE_DELFRR_ZAPI6_VRF_UNREGISTERFRR_ZAPI6_VRF_ADDFRR_ZAPI6_VRF_DELETEFRR_ZAPI6_VRF_LABELFRR_ZAPI6_INTERFACE_VRF_UPDATEFRR_ZAPI6_BFD_CLIENT_REGISTERFRR_ZAPI6_BFD_CLIENT_DEREGISTERFRR_ZAPI6_INTERFACE_ENABLE_RADVFRR_ZAPI6_INTERFACE_DISABLE_RADVFRR_ZAPI6_IPV4_NEXTHOP_LOOKUP_MRIBFRR_ZAPI6_INTERFACE_LINK_PARAMSFRR_ZAPI6_MPLS_LABELS_ADDFRR_ZAPI6_MPLS_LABELS_DELETEFRR_ZAPI6_IPMR_ROUTE_STATSFRR_ZAPI6_LABEL_MANAGER_CONNECTFRR_ZAPI6_GET_LABEL_CHUNKFRR_ZAPI6_RELEASE_LABEL_CHUNKFRR_ZAPI6_FEC_REGISTERFRR_ZAPI6_FEC_UNREGISTERFRR_ZAPI6_FEC_UPDATEFRR_ZAPI6_ADVERTISE_DEFAULT_GWFRR_ZAPI6_ADVERTISE_SUBNETFRR_ZAPI6_ADVERTISE_ALL_VNIFRR_ZAPI6_LOCAL_ES_ADDFRR_ZAPI6_LOCAL_ES_DELFRR_ZAPI6_VNI_ADDFRR_ZAPI6_VNI_DELFRR_ZAPI6_L3VNI_ADDFRR_ZAPI6_L3VNI_DELFRR_ZAPI6_REMOTE_VTEP_ADDFRR_ZAPI6_REMOTE_VTEP_DELFRR_ZAPI6_MACIP_ADDFRR_ZAPI6_MACIP_DELFRR_ZAPI6_IP_PREFIX_ROUTE_ADDFRR_ZAPI6_IP_PREFIX_ROUTE_DELFRR_ZAPI6_REMOTE_MACIP_ADDFRR_ZAPI6_REMOTE_MACIP_DELFRR_ZAPI6_PW_ADDFRR_ZAPI6_PW_DELETEFRR_ZAPI6_PW_SETFRR_ZAPI6_PW_UNSETFRR_ZAPI6_PW_STATUS_UPDATEFRR_ZAPI6_RULE_ADDFRR_ZAPI6_RULE_DELETEFRR_ZAPI6_RULE_NOTIFY_OWNERFRR_ZAPI6_TABLE_MANAGER_CONNECTFRR_ZAPI6_GET_TABLE_CHUNKFRR_ZAPI6_RELEASE_TABLE_CHUNKFRR_ZAPI6_IPSET_CREATEFRR_ZAPI6_IPSET_DESTROYFRR_ZAPI6_IPSET_ENTRY_ADDFRR_ZAPI6_IPSET_ENTRY_DELETEFRR_ZAPI6_IPSET_NOTIFY_OWNERFRR_ZAPI6_IPSET_ENTRY_NOTIFY_OWNERFRR_ZAPI6_IPTABLE_ADDFRR_ZAPI6_IPTABLE_DELETEFRR_ZAPI6_IPTABLE_NOTIFY_OWNERFRR_ZAPI5_IPTABLE_DELETEFRR_ZAPI5_IPTABLE_NOTIFY_OWNER"
const _API_TYPE_name = "FRR_ZAPI6_INTERFACE_ADDFRR_ZAPI6_INTERFACE_DELETEFRR_ZAPI6_INTERFACE_ADDRESS_ADDFRR_ZAPI6_INTERFACE_ADDRESS_DELETEFRR_ZAPI6_INTERFACE_UPFRR_ZAPI6_INTERFACE_DOWNFRR_ZAPI6_INTERFACE_SET_MASTERFRR_ZAPI6_ROUTE_ADDFRR_ZAPI6_ROUTE_DELETEFRR_ZAPI6_ROUTE_NOTIFY_OWNERFRR_ZAPI6_REDISTRIBUTE_ADDFRR_ZAPI6_REDISTRIBUTE_DELETEFRR_ZAPI6_REDISTRIBUTE_DEFAULT_ADDFRR_ZAPI6_REDISTRIBUTE_DEFAULT_DELETEFRR_ZAPI6_ROUTER_ID_ADDFRR_ZAPI6_ROUTER_ID_DELETEFRR_ZAPI6_ROUTER_ID_UPDATEFRR_ZAPI6_HELLOFRR_ZAPI6_CAPABILITIESFRR_ZAPI6_NEXTHOP_REGISTERFRR_ZAPI6_NEXTHOP_UNREGISTERFRR_ZAPI6_NEXTHOP_UPDATEFRR_ZAPI6_INTERFACE_NBR_ADDRESS_ADDFRR_ZAPI6_INTERFACE_NBR_ADDRESS_DELETEFRR_ZAPI6_INTERFACE_BFD_DEST_UPDATEFRR_ZAPI6_IMPORT_ROUTE_REGISTERFRR_ZAPI6_IMPORT_ROUTE_UNREGISTERFRR_ZAPI6_IMPORT_CHECK_UPDATEFRR_ZAPI6_IPV4_ROUTE_IPV6_NEXTHOP_ADDFRR_ZAPI6_BFD_DEST_REGISTERFRR_ZAPI6_BFD_DEST_DEREGISTERFRR_ZAPI6_BFD_DEST_UPDATEFRR_ZAPI6_BFD_DEST_REPLAYFRR_ZAPI6_REDISTRIBUTE_ROUTE_ADDFRR_ZAPI6_REDISTRIBUTE_ROUTE_DELFRR_ZAPI6_VRF_UNREGISTERFRR_ZAPI6_VRF_ADDFRR_ZAPI6_VRF_DELETEFRR_ZAPI6_VRF_LABELFRR_ZAPI6_INTERFACE_VRF_UPDATEFRR_ZAPI6_BFD_CLIENT_REGISTERFRR_ZAPI6_BFD_CLIENT_DEREGISTERFRR_ZAPI6_INTERFACE_ENABLE_RADVFRR_ZAPI6_INTERFACE_DISABLE_RADVFRR_ZAPI6_IPV4_NEXTHOP_LOOKUP_MRIBFRR_ZAPI6_INTERFACE_LINK_PARAMSFRR_ZAPI6_MPLS_LABELS_ADDFRR_ZAPI6_MPLS_LABELS_DELETEFRR_ZAPI6_IPMR_ROUTE_STATSFRR_ZAPI6_LABEL_MANAGER_CONNECTFRR_ZAPI6_LABEL_MANAGER_CONNECT_ASYNCFRR_ZAPI6_GET_LABEL_CHUNKFRR_ZAPI6_RELEASE_LABEL_CHUNKFRR_ZAPI6_FEC_REGISTERFRR_ZAPI6_FEC_UNREGISTERFRR_ZAPI6_FEC_UPDATEFRR_ZAPI6_ADVERTISE_DEFAULT_GWFRR_ZAPI6_ADVERTISE_SUBNETFRR_ZAPI6_ADVERTISE_ALL_VNIFRR_ZAPI6_LOCAL_ES_ADDFRR_ZAPI6_LOCAL_ES_DELFRR_ZAPI6_VNI_ADDFRR_ZAPI6_VNI_DELFRR_ZAPI6_L3VNI_ADDFRR_ZAPI6_L3VNI_DELFRR_ZAPI6_REMOTE_VTEP_ADDFRR_ZAPI6_REMOTE_VTEP_DELFRR_ZAPI6_MACIP_ADDFRR_ZAPI6_MACIP_DELFRR_ZAPI6_IP_PREFIX_ROUTE_ADDFRR_ZAPI6_IP_PREFIX_ROUTE_DELFRR_ZAPI6_REMOTE_MACIP_ADDFRR_ZAPI6_REMOTE_MACIP_DELFRR_ZAPI6_PW_ADDFRR_ZAPI6_PW_DELETEFRR_ZAPI6_PW_SETFRR_ZAPI6_PW_UNSETFRR_ZAPI6_PW_STATUS_UPDATEFRR_ZAPI6_RULE_ADDFRR_ZAPI6_RULE_DELETEFRR_ZAPI6_RULE_NOTIFY_OWNERFRR_ZAPI6_TABLE_MANAGER_CONNECTFRR_ZAPI6_GET_TABLE_CHUNKFRR_ZAPI6_RELEASE_TABLE_CHUNKFRR_ZAPI6_IPSET_CREATEFRR_ZAPI6_IPSET_DESTROYFRR_ZAPI6_IPSET_ENTRY_ADDFRR_ZAPI6_IPSET_ENTRY_DELETEFRR_ZAPI6_IPSET_NOTIFY_OWNERFRR_ZAPI6_IPSET_ENTRY_NOTIFY_OWNERFRR_ZAPI6_IPTABLE_ADDFRR_ZAPI6_IPTABLE_DELETEFRR_ZAPI6_IPTABLE_NOTIFY_OWNERFRR_ZAPI5_IPTABLE_NOTIFY_OWNER"
var _API_TYPE_index = [...]uint16{0, 23, 49, 80, 114, 136, 160, 190, 209, 231, 259, 285, 314, 348, 385, 408, 434, 460, 475, 497, 523, 551, 575, 610, 648, 683, 714, 747, 776, 813, 840, 869, 894, 919, 951, 983, 1007, 1024, 1044, 1063, 1093, 1122, 1153, 1184, 1216, 1250, 1281, 1306, 1334, 1360, 1391, 1416, 1445, 1467, 1491, 1511, 1541, 1567, 1594, 1616, 1638, 1655, 1672, 1691, 1710, 1735, 1760, 1779, 1798, 1827, 1856, 1882, 1908, 1924, 1943, 1959, 1977, 2003, 2021, 2042, 2069, 2100, 2125, 2154, 2176, 2199, 2224, 2252, 2280, 2314, 2335, 2359, 2389, 2413, 2443}
var _API_TYPE_index = [...]uint16{0, 23, 49, 80, 114, 136, 160, 190, 209, 231, 259, 285, 314, 348, 385, 408, 434, 460, 475, 497, 523, 551, 575, 610, 648, 683, 714, 747, 776, 813, 840, 869, 894, 919, 951, 983, 1007, 1024, 1044, 1063, 1093, 1122, 1153, 1184, 1216, 1250, 1281, 1306, 1334, 1360, 1391, 1428, 1453, 1482, 1504, 1528, 1548, 1578, 1604, 1631, 1653, 1675, 1692, 1709, 1728, 1747, 1772, 1797, 1816, 1835, 1864, 1893, 1919, 1945, 1961, 1980, 1996, 2014, 2040, 2058, 2079, 2106, 2137, 2162, 2191, 2213, 2236, 2261, 2289, 2317, 2351, 2372, 2396, 2426, 2456}
func (i API_TYPE) String() string {
if i >= API_TYPE(len(_API_TYPE_index)-1) {
+16
View File
@@ -0,0 +1,16 @@
// Code generated by "stringer -type=LSP_TYPE"; DO NOT EDIT.
package zebra
import "strconv"
const _LSP_TYPE_name = "LSP_NONELSP_STATICLSP_LDPLSP_BGPLSP_SRLSP_SHARP"
var _LSP_TYPE_index = [...]uint8{0, 8, 18, 25, 32, 38, 47}
func (i LSP_TYPE) String() string {
if i >= LSP_TYPE(len(_LSP_TYPE_index)-1) {
return "LSP_TYPE(" + strconv.FormatInt(int64(i), 10) + ")"
}
return _LSP_TYPE_name[_LSP_TYPE_index[i]:_LSP_TYPE_index[i+1]]
}
+2 -2
View File
@@ -4,9 +4,9 @@ package zebra
import "strconv"
const _SAFI_name = "SAFI_UNICASTSAFI_MULTICASTSAFI_RESERVED_3SAFI_MPLS_VPNSAFI_MAX"
const _SAFI_name = "FRR_ZAPI5_SAFI_UNICASTFRR_ZAPI5_SAFI_MULTICASTFRR_ZAPI5_SAFI_MPLS_VPNFRR_ZAPI5_SAFI_ENCAPFRR_ZAPI5_SAFI_EVPNFRR_ZAPI5_SAFI_LABELED_UNICASTFRR_ZAPI5_SAFI_FLOWSPECFRR_ZAPI5_SAFI_MAX"
var _SAFI_index = [...]uint8{0, 12, 26, 41, 54, 62}
var _SAFI_index = [...]uint8{0, 22, 46, 69, 89, 108, 138, 161, 179}
func (i SAFI) String() string {
i -= 1
+365 -11
View File
@@ -178,12 +178,29 @@ const (
//go:generate stringer -type=SAFI
type SAFI uint8
// SAFI definition in Zebra of FRRouting 4.x, 5.x, 6.x
const (
_ SAFI = iota
FRR_ZAPI5_SAFI_UNICAST
FRR_ZAPI5_SAFI_MULTICAST
FRR_ZAPI5_SAFI_MPLS_VPN
FRR_ZAPI5_SAFI_ENCAP
FRR_ZAPI5_SAFI_EVPN
FRR_ZAPI5_SAFI_LABELED_UNICAST
FRR_ZAPI5_SAFI_FLOWSPEC
FRR_ZAPI5_SAFI_MAX
)
// SAFI definition in Zebra of Quagga and FRRouting 3.x
const (
_ SAFI = iota
SAFI_UNICAST
SAFI_MULTICAST
SAFI_RESERVED_3
SAFI_MPLS_VPN
FRR_SAFI_MPLS_VPN // SAFI_RESERVED_3 in quagga
SAFI_MPLS_VPN // SAFI_RESERVED_4 in FRRouting 3.x
FRR_SAFI_ENCAP
FRR_SAFI_EVPN
SAFI_ENCAP // SAFI_MAX in FRRouting 3.x
SAFI_MAX
)
@@ -243,6 +260,7 @@ const (
FRR_ZAPI6_MPLS_LABELS_DELETE
FRR_ZAPI6_IPMR_ROUTE_STATS
FRR_ZAPI6_LABEL_MANAGER_CONNECT
FRR_ZAPI6_LABEL_MANAGER_CONNECT_ASYNC
FRR_ZAPI6_GET_LABEL_CHUNK
FRR_ZAPI6_RELEASE_LABEL_CHUNK
FRR_ZAPI6_FEC_REGISTER
@@ -1020,6 +1038,9 @@ func NewClient(network, address string, typ ROUTE_TYPE, version uint8) (*Client,
// Send HELLO/ROUTER_ID_ADD messages to negotiate the Zebra message version.
c.SendHello()
c.SendRouterIDAdd()
if version >= 4 {
c.SendLabelManagerConnect()
}
receiveSingleMsg := func() (*Message, error) {
headerBuf, err := readAll(conn, int(HeaderSize(version)))
@@ -1241,6 +1262,10 @@ func (c *Client) SendRedistributeDelete(t ROUTE_TYPE) error {
}
func (c *Client) SendIPRoute(vrfId uint32, body *IPRouteBody, isWithdraw bool) error {
routeFamily := body.RouteFamily(c.Version)
if vrfId == VRF_DEFAULT && (routeFamily == bgp.RF_IPv4_VPN || routeFamily == bgp.RF_IPv6_VPN) {
return fmt.Errorf("RF_IPv4_VPN or RF_IPv6_VPN are not suitable for VPN_DEFAULT(default forwarding table).")
}
command := IPV4_ROUTE_ADD
if c.Version <= 3 {
if body.Prefix.Prefix.To4() != nil {
@@ -1311,6 +1336,58 @@ func (c *Client) SendNexthopRegister(vrfId uint32, body *NexthopRegisterBody, is
return c.SendCommand(command, vrfId, body)
}
// Reference: zread_label_manager_connect function in zebra/zserv.c of FRR3.x (ZAPI)
// Reference: zread_label_manager_connect function in zebra/zapi_msg.c of FRR5.x and 6.x (ZAPI5 and 6)
func (c *Client) SendLabelManagerConnect() error {
if c.Version < 4 {
return fmt.Errorf("LABEL_MANAGER_CONNECT is not supported in version: %d", c.Version)
}
command := FRR_LABEL_MANAGER_CONNECT
proto := FRR_ROUTE_BGP
if c.Version == 5 {
command = FRR_ZAPI5_LABEL_MANAGER_CONNECT
proto = FRR_ZAPI5_ROUTE_BGP
} else if c.Version == 6 {
command = FRR_ZAPI6_LABEL_MANAGER_CONNECT
proto = FRR_ZAPI6_ROUTE_BGP
}
return c.SendCommand(
command, 0,
&LabelManagerConnectBody{
RedistDefault: proto,
Instance: 0,
})
}
func (c *Client) SendGetLabelChunk(body *GetLabelChunkBody) error {
if c.Version < 4 {
return fmt.Errorf("GET_LABEL_CHUNK is not supported in version: %d", c.Version)
}
command := FRR_GET_LABEL_CHUNK
body.Instance = 0
if c.Version == 5 {
body.Proto = uint8(FRR_ZAPI5_ROUTE_BGP)
command = FRR_ZAPI5_GET_LABEL_CHUNK
} else if c.Version == 6 {
body.Proto = uint8(FRR_ZAPI6_ROUTE_BGP)
command = FRR_ZAPI6_GET_LABEL_CHUNK
}
return c.SendCommand(command, 0, body)
}
func (c *Client) SendVrfLabel(label uint32, vrfId uint32) error {
body := &VrfLabelBody{
Label: label,
Afi: AFI_IP,
LabelType: LSP_BGP,
}
command := FRR_ZAPI5_VRF_LABEL
if c.Version == 6 {
command = FRR_ZAPI6_VRF_LABEL
}
return c.SendCommand(command, vrfId, body)
}
// for avoiding double close
func ChannelClose(ch chan *Message) bool {
select {
@@ -1735,11 +1812,78 @@ func (b *IPRouteBody) RouteFamily(version uint8) bgp.RouteFamily {
family = syscall.AF_INET6
}
}
switch family {
case syscall.AF_INET:
return bgp.RF_IPv4_UC
case syscall.AF_INET6:
return bgp.RF_IPv6_UC
if version < 5 {
switch family {
case syscall.AF_INET:
switch b.SAFI {
case SAFI_UNICAST:
return bgp.RF_IPv4_UC
case SAFI_MULTICAST:
return bgp.RF_IPv4_MC
case SAFI_MPLS_VPN, FRR_SAFI_MPLS_VPN:
return bgp.RF_IPv4_VPN
case FRR_SAFI_ENCAP, SAFI_ENCAP:
return bgp.RF_IPv4_ENCAP
}
case syscall.AF_INET6:
switch b.SAFI {
case SAFI_UNICAST:
return bgp.RF_IPv6_UC
case SAFI_MULTICAST:
return bgp.RF_IPv6_MC
case SAFI_MPLS_VPN, FRR_SAFI_MPLS_VPN:
return bgp.RF_IPv6_VPN
case FRR_SAFI_ENCAP, SAFI_ENCAP:
return bgp.RF_IPv6_ENCAP
}
default:
switch b.SAFI {
case FRR_SAFI_EVPN:
return bgp.RF_EVPN
default:
return bgp.RF_OPAQUE
}
}
} else {
switch family {
case syscall.AF_INET:
switch b.SAFI {
case FRR_ZAPI5_SAFI_UNICAST:
return bgp.RF_IPv4_UC
case FRR_ZAPI5_SAFI_MULTICAST:
return bgp.RF_IPv4_MC
case FRR_ZAPI5_SAFI_MPLS_VPN:
return bgp.RF_IPv4_VPN
case FRR_ZAPI5_SAFI_ENCAP:
return bgp.RF_IPv4_ENCAP
case FRR_ZAPI5_SAFI_LABELED_UNICAST:
return bgp.RF_IPv4_MPLS
case FRR_ZAPI5_SAFI_FLOWSPEC:
return bgp.RF_FS_IPv4_UC
}
case syscall.AF_INET6:
switch b.SAFI {
case FRR_ZAPI5_SAFI_UNICAST:
return bgp.RF_IPv6_UC
case FRR_ZAPI5_SAFI_MULTICAST:
return bgp.RF_IPv6_MC
case FRR_ZAPI5_SAFI_MPLS_VPN:
return bgp.RF_IPv6_VPN
case FRR_ZAPI5_SAFI_ENCAP:
return bgp.RF_IPv6_ENCAP
case FRR_ZAPI5_SAFI_LABELED_UNICAST:
return bgp.RF_IPv6_MPLS
case FRR_ZAPI5_SAFI_FLOWSPEC:
return bgp.RF_FS_IPv6_UC
}
default:
switch b.SAFI {
case FRR_ZAPI5_SAFI_EVPN:
return bgp.RF_EVPN
default:
return bgp.RF_OPAQUE
}
}
}
return bgp.RF_OPAQUE
}
@@ -1897,9 +2041,15 @@ func (b *IPRouteBody) Serialize(version uint8) ([]byte, error) {
}
if version >= 5 && b.Message&FRR_ZAPI5_MESSAGE_LABEL > 0 {
buf = append(buf, nexthop.LabelNum)
bbuf := make([]byte, 4)
binary.BigEndian.PutUint32(bbuf, nexthop.MplsLabels[0])
buf = append(buf, bbuf...)
for i := uint8(0); i < nexthop.LabelNum; i++ {
bbuf := make([]byte, 4)
/* Frr uses stream_put for mpls label array.
stream_put is unaware of byteorder coversion.
Therefore LittleEndian is used instead of BigEndian. */
binary.LittleEndian.PutUint32(bbuf, nexthop.MplsLabels[i])
buf = append(buf, bbuf...)
}
}
}
if (version <= 3 && b.Message&MESSAGE_DISTANCE > 0) ||
@@ -2240,7 +2390,10 @@ func decodeNexthopsFromBytes(nexthops *[]Nexthop, data []byte, family uint8, ver
}
nexthop.MplsLabels = make([]uint32, nexthop.LabelNum)
for n := uint8(0); n < nexthop.LabelNum; n++ {
nexthop.MplsLabels[n] = binary.BigEndian.Uint32(data[offset : offset+4])
/* Frr uses stream_put for mpls label array.
stream_put is unaware of byteorder coversion.
Therefore LittleEndian is used instead of BigEndian. */
nexthop.MplsLabels[n] = binary.LittleEndian.Uint32(data[offset : offset+4])
offset += 4
}
}
@@ -2612,6 +2765,177 @@ func (b *NexthopUpdateBody) String() string {
return s
}
type LabelManagerConnectBody struct {
RedistDefault ROUTE_TYPE
Instance uint16
// The followings are used in response from Zebra
Result uint8 // 0 means success
}
// Reference: lm_label_manager_connect in lib/zclient.c of FRR
func (b *LabelManagerConnectBody) Serialize(version uint8) ([]byte, error) {
buf := make([]byte, 3)
buf[0] = uint8(b.RedistDefault)
binary.BigEndian.PutUint16(buf[1:3], b.Instance)
return buf, nil
}
func (b *LabelManagerConnectBody) DecodeFromBytes(data []byte, version uint8) error {
size := 1
// FRR v4 may work incorrectly. It returns result only although it uses ZAPI v5.
if version >= 4 {
size = 4
}
if len(data) < size {
return fmt.Errorf("invalid message length for LABEL_MANAGER_CONNECT response: %d<%d",
len(data), size)
}
if version > 4 {
b.RedistDefault = ROUTE_TYPE(data[0])
b.Instance = binary.BigEndian.Uint16(data[1:3])
data = data[3:]
}
b.Result = data[0]
return nil
}
func (b *LabelManagerConnectBody) String() string {
return fmt.Sprintf(
"route_type: %s, instance: %d, result: %d",
b.RedistDefault.String(), b.Instance, b.Result)
}
// Reference: zsend_assign_label_chunk_response in zebra/zserv.c of FRR3.x
// Reference: zsend_assign_label_chunk_response in zebra/zapi_msg.c of FRR5.x and 6.x
type GetLabelChunkBody struct {
Proto uint8 // it is appeared in FRR5.x and 6.x
Instance uint16 // it is appeared in FRR5.x and 6.x
Keep uint8
ChunkSize uint32
// The followings are used in response from Zebra
Start uint32
End uint32
}
// Reference: zread_get_label_chunk in zebra/zserv.c of FRR3.x
// Reference: zread_get_label_chunk in zebra/zapi_msg.c of FRR5.x and 6.x
func (b *GetLabelChunkBody) Serialize(version uint8) ([]byte, error) {
buf := make([]byte, 8)
pos := 0
if version > 4 {
buf[pos] = b.Proto
binary.BigEndian.PutUint16(buf[pos+1:pos+3], b.Instance)
pos += 3
}
buf[pos] = b.Keep
binary.BigEndian.PutUint32(buf[pos+1:pos+5], b.ChunkSize)
pos += 5
return buf[0:pos], nil
}
// Reference: zsend_assign_label_chunk_response in zebra/zserv.c of FRR3.x
// Reference: zsend_assign_label_chunk_response in zebra/zapi_msg.c of FRR5.x and 6.x
func (b *GetLabelChunkBody) DecodeFromBytes(data []byte, version uint8) error {
size := 9
if version > 4 {
size = 12
}
if len(data) < size {
return fmt.Errorf("invalid message length for GET_LABEL_CHUNK response: %d<%d",
len(data), size)
}
if version > 4 {
b.Proto = data[0]
b.Instance = binary.BigEndian.Uint16(data[1:3])
data = data[3:]
}
b.Keep = data[0]
b.Start = binary.BigEndian.Uint32(data[1:5])
b.End = binary.BigEndian.Uint32(data[5:9])
return nil
}
func (b *GetLabelChunkBody) String() string {
return fmt.Sprintf(
"keep: %d, chunk_size: %d, start: %d, end: %d",
b.Keep, b.ChunkSize, b.Start, b.End)
}
type ReleaseLabelChunkBody struct {
Proto uint8 // it is appeared in FRR5.x and 6.x
Instance uint16 // it is appeared in FRR5.x and 6.x
Start uint32
End uint32
}
func (b *ReleaseLabelChunkBody) Serialize(version uint8) ([]byte, error) {
buf := make([]byte, 11)
pos := 0
if version > 4 {
buf[pos] = b.Proto
binary.BigEndian.PutUint16(buf[pos+1:pos+3], b.Instance)
pos += 3
}
binary.BigEndian.PutUint32(buf[pos:pos+4], b.Start)
binary.BigEndian.PutUint32(buf[pos+4:pos+8], b.End)
pos += 8
return buf[0:pos], nil
}
func (b *ReleaseLabelChunkBody) DecodeFromBytes(data []byte, version uint8) error {
// No response from Zebra
return nil
}
func (b *ReleaseLabelChunkBody) String() string {
return fmt.Sprintf(
"start: %d, end: %d",
b.Start, b.End)
}
//go:generate stringer -type=LSP_TYPE
type LSP_TYPE uint8
const (
LSP_NONE LSP_TYPE = iota //defined in FRR3 and over
LSP_STATIC //defined in FRR3 and over
LSP_LDP //defined in FRR3 and over
LSP_BGP //defined in FRR4 and over
LSP_SR //defined in FRR4 and over
LSP_SHARP //defined in FRR5 and over
)
type VrfLabelBody struct {
Label uint32
Afi AFI
LabelType LSP_TYPE
}
// Reference: zclient_send_vrf_label in lib/zclient.c of FRR 5.x and 6.x
func (b *VrfLabelBody) Serialize(version uint8) ([]byte, error) {
buf := make([]byte, 6)
binary.BigEndian.PutUint32(buf[0:4], b.Label)
buf[4] = uint8(b.Afi)
buf[5] = uint8(b.LabelType)
return buf, nil
}
func (b *VrfLabelBody) DecodeFromBytes(data []byte, version uint8) error {
if len(data) < 6 {
return fmt.Errorf("invalid message length for VRF_LABEL message: %d<6", len(data))
}
b.Label = binary.BigEndian.Uint32(data[0:4])
b.Afi = AFI(data[4])
b.LabelType = LSP_TYPE(data[5])
return nil
}
func (b *VrfLabelBody) String() string {
return fmt.Sprintf(
"label: %d, AFI: %s LSP_type: %s",
b.Label, b.Afi, b.LabelType)
}
type Message struct {
Header Header
Body Body
@@ -2689,6 +3013,15 @@ func (m *Message) parseFrrMessage(data []byte) error {
case FRR_PW_STATUS_UPDATE:
// TODO
m.Body = &UnknownBody{}
case FRR_LABEL_MANAGER_CONNECT:
// Note: Synchronous message
m.Body = &LabelManagerConnectBody{}
case FRR_GET_LABEL_CHUNK:
// Note: Synchronous message
m.Body = &GetLabelChunkBody{}
case FRR_RELEASE_LABEL_CHUNK:
// Note: Synchronous message
m.Body = &ReleaseLabelChunkBody{}
default:
m.Body = &UnknownBody{}
}
@@ -2728,6 +3061,17 @@ func (m *Message) parseFrrZapi5Message(data []byte) error {
case FRR_ZAPI5_PW_STATUS_UPDATE:
// TODO
m.Body = &UnknownBody{}
case FRR_ZAPI5_LABEL_MANAGER_CONNECT:
// Note: Synchronous message
m.Body = &LabelManagerConnectBody{}
case FRR_ZAPI5_GET_LABEL_CHUNK:
// Note: Synchronous message
m.Body = &GetLabelChunkBody{}
case FRR_ZAPI5_RELEASE_LABEL_CHUNK:
// Note: Synchronous message
m.Body = &ReleaseLabelChunkBody{}
case FRR_ZAPI5_VRF_LABEL:
m.Body = &VrfLabelBody{}
default:
m.Body = &UnknownBody{}
}
@@ -2767,6 +3111,16 @@ func (m *Message) parseFrrZapi6Message(data []byte) error {
case FRR_ZAPI6_PW_STATUS_UPDATE:
// TODO
m.Body = &UnknownBody{}
case FRR_ZAPI6_LABEL_MANAGER_CONNECT:
// Note: Synchronous message
m.Body = &LabelManagerConnectBody{}
case FRR_ZAPI6_GET_LABEL_CHUNK:
// Note: Synchronous message
m.Body = &GetLabelChunkBody{}
case FRR_ZAPI6_RELEASE_LABEL_CHUNK:
// Note: Synchronous message
case FRR_ZAPI6_VRF_LABEL:
m.Body = &VrfLabelBody{}
default:
m.Body = &UnknownBody{}
}
+31 -1
View File
@@ -958,6 +958,7 @@ func (s *BgpServer) propagateUpdate(peer *peer, pathList []*table.Path) {
peer.fsm.lock.RLock()
peerVrf := peer.fsm.pConf.Config.Vrf
peer.fsm.lock.RUnlock()
path.SetReceiveVrfId(rib.Vrfs[peerVrf].Id)
path = path.ToGlobal(rib.Vrfs[peerVrf])
}
@@ -1590,7 +1591,10 @@ func (s *BgpServer) EnableZebra(ctx context.Context, r *api.EnableZebraRequest)
protos = append(protos, string(p))
}
var err error
s.zclient, err = newZebraClient(s, r.Url, protos, uint8(r.Version), r.NexthopTriggerEnable, uint8(r.NexthopTriggerDelay))
s.zclient, err = newZebraClient(s, r.Url, protos, uint8(r.Version), r.NexthopTriggerEnable, uint8(r.NexthopTriggerDelay), r.MplsLabelRangeSize)
if err == nil && s.globalRib != nil && s.zclient.client.Version >= 4 && r.MplsLabelRangeSize > 0 {
err = s.globalRib.EnableMplsLabelAllocation()
}
return err
}, false)
}
@@ -2029,6 +2033,26 @@ func (s *BgpServer) ListVrf(ctx context.Context, _ *api.ListVrfRequest, fn func(
return nil
}
func assignMplsLabel(s *BgpServer, vrf *table.Vrf) error {
var mplsLabel uint32
var err error
for mplsLabel, err = s.globalRib.AssignMplsLabel(); err != nil; mplsLabel, err = s.globalRib.AssignMplsLabel() {
if err = s.zclient.client.SendGetLabelChunk(&zebra.GetLabelChunkBody{ChunkSize: s.zclient.mplsLabelRangeSize}); err != nil {
return err
}
labels := <-s.zclient.mplsLabelRangeCh
if err = s.globalRib.AllocateMplsLabelRange(labels[0], labels[1]); err != nil {
return err
}
}
vrf.MplsLabel = mplsLabel
err = s.zclient.client.SendVrfLabel(vrf.MplsLabel, vrf.Id)
if err != nil {
return err
}
return nil
}
func (s *BgpServer) AddVrf(ctx context.Context, r *api.AddVrfRequest) error {
return s.mgmtOperation(func() error {
if r == nil || r.Vrf == nil {
@@ -2055,11 +2079,17 @@ func (s *BgpServer) AddVrf(ctx context.Context, r *api.AddVrfRequest) error {
AS: s.bgpConfig.Global.Config.As,
LocalID: net.ParseIP(s.bgpConfig.Global.Config.RouterId).To4(),
}
if pathList, err := s.globalRib.AddVrf(name, id, rd, im, ex, pi); err != nil {
return err
} else if len(pathList) > 0 {
s.propagateUpdate(nil, pathList)
}
if vrf, ok := s.globalRib.Vrfs[name]; ok {
if s.zclient.mplsLabelRangeSize > 0 {
go assignMplsLabel(s, vrf)
}
}
return nil
}, true)
}
+53 -16
View File
@@ -116,18 +116,19 @@ func filterOutExternalPath(paths []*table.Path) []*table.Path {
return filteredPaths
}
func newIPRouteBody(dst []*table.Path) (body *zebra.IPRouteBody, isWithdraw bool) {
func newIPRouteBody(dst []*table.Path, vrfId uint32, version uint8) (body *zebra.IPRouteBody, isWithdraw bool) {
paths := filterOutExternalPath(dst)
if len(paths) == 0 {
return nil, false
}
path := paths[0]
receiveVrfId := path.ReceiveVrfId()
l := strings.SplitN(path.GetNlri().String(), "/", 2)
var prefix net.IP
//nexthops := make([]net.IP, 0, len(paths))
var nexthop zebra.Nexthop
nexthops := make([]zebra.Nexthop, 0, len(paths))
msgFlags := zebra.MESSAGE_NEXTHOP
switch path.GetRouteFamily() {
case bgp.RF_IPv4_UC, bgp.RF_IPv4_VPN:
if path.GetRouteFamily() == bgp.RF_IPv4_UC {
@@ -137,6 +138,14 @@ func newIPRouteBody(dst []*table.Path) (body *zebra.IPRouteBody, isWithdraw bool
}
for _, p := range paths {
nexthop.Gate = p.GetNexthop().To4()
nexthop.VrfId = receiveVrfId
if version > 4 && path.GetRouteFamily() == bgp.RF_IPv4_VPN && receiveVrfId != vrfId {
msgFlags |= zebra.FRR_ZAPI5_MESSAGE_LABEL
for _, label := range path.GetNlri().(*bgp.LabeledVPNIPAddrPrefix).Labels.Labels {
nexthop.LabelNum++
nexthop.MplsLabels = append(nexthop.MplsLabels, label)
}
}
nexthops = append(nexthops, nexthop)
}
case bgp.RF_IPv6_UC, bgp.RF_IPv6_VPN:
@@ -147,16 +156,27 @@ func newIPRouteBody(dst []*table.Path) (body *zebra.IPRouteBody, isWithdraw bool
}
for _, p := range paths {
nexthop.Gate = p.GetNexthop().To16()
nexthop.VrfId = receiveVrfId
if version > 4 && path.GetRouteFamily() == bgp.RF_IPv6_VPN && receiveVrfId != vrfId {
msgFlags |= zebra.FRR_ZAPI5_MESSAGE_LABEL
for _, label := range path.GetNlri().(*bgp.LabeledVPNIPAddrPrefix).Labels.Labels {
nexthop.LabelNum++
nexthop.MplsLabels = append(nexthop.MplsLabels, label)
}
}
nexthops = append(nexthops, nexthop)
}
default:
return nil, false
}
msgFlags := zebra.MESSAGE_NEXTHOP
plen, _ := strconv.ParseUint(l[1], 10, 8)
med, err := path.GetMed()
if err == nil {
msgFlags |= zebra.MESSAGE_METRIC
if version < 5 {
msgFlags |= zebra.MESSAGE_METRIC
} else {
msgFlags |= zebra.FRR_ZAPI5_MESSAGE_METRIC
}
}
var flags zebra.FLAG
if path.IsIBGP() {
@@ -282,10 +302,12 @@ func newPathFromIPRouteMessage(m *zebra.Message, version uint8) *table.Path {
}
type zebraClient struct {
client *zebra.Client
server *BgpServer
nexthopCache nexthopStateCache
dead chan struct{}
client *zebra.Client
server *BgpServer
nexthopCache nexthopStateCache
mplsLabelRangeCh chan [2]uint32 // {start, end}
mplsLabelRangeSize uint32
dead chan struct{}
}
func (z *zebraClient) getPathListWithNexthopUpdate(body *zebra.NexthopUpdateBody) []*table.Path {
@@ -336,6 +358,10 @@ func (z *zebraClient) loop() {
}...)
defer w.Stop()
if z.mplsLabelRangeSize > 0 {
defer close(z.mplsLabelRangeCh)
}
for {
select {
case <-z.dead:
@@ -367,6 +393,8 @@ func (z *zebraClient) loop() {
delete(z.nexthopCache, body.Prefix.Prefix.String())
}
z.updatePathByNexthopCache(paths)
case *zebra.GetLabelChunkBody:
z.mplsLabelRangeCh <- [2]uint32{body.Start, body.End}
}
case ev := <-w.Event():
switch msg := ev.(type) {
@@ -374,7 +402,7 @@ func (z *zebraClient) loop() {
if table.UseMultiplePaths.Enabled {
for _, paths := range msg.MultiPathList {
z.updatePathByNexthopCache(paths)
if body, isWithdraw := newIPRouteBody(paths); body != nil {
if body, isWithdraw := newIPRouteBody(paths, 0, z.client.Version); body != nil {
z.client.SendIPRoute(0, body, isWithdraw)
}
if body := newNexthopRegisterBody(paths, z.nexthopCache); body != nil {
@@ -391,8 +419,15 @@ func (z *zebraClient) loop() {
}
}
for _, i := range vrfs {
if body, isWithdraw := newIPRouteBody([]*table.Path{path}); body != nil {
z.client.SendIPRoute(i, body, isWithdraw)
routeFamily := path.GetRouteFamily()
if i == zebra.VRF_DEFAULT && (routeFamily == bgp.RF_IPv4_VPN || routeFamily == bgp.RF_IPv6_VPN) {
continue
}
if body, isWithdraw := newIPRouteBody([]*table.Path{path}, i, z.client.Version); body != nil {
err := z.client.SendIPRoute(i, body, isWithdraw)
if err != nil {
continue
}
}
if body := newNexthopRegisterBody([]*table.Path{path}, z.nexthopCache); body != nil {
z.client.SendNexthopRegister(i, body, false)
@@ -415,7 +450,7 @@ func (z *zebraClient) loop() {
}
}
func newZebraClient(s *BgpServer, url string, protos []string, version uint8, nhtEnable bool, nhtDelay uint8) (*zebraClient, error) {
func newZebraClient(s *BgpServer, url string, protos []string, version uint8, nhtEnable bool, nhtDelay uint8, mplsLabelRangeSize uint32) (*zebraClient, error) {
l := strings.SplitN(url, ":", 2)
if len(l) != 2 {
return nil, fmt.Errorf("unsupported url: %s", url)
@@ -468,10 +503,12 @@ func newZebraClient(s *BgpServer, url string, protos []string, version uint8, nh
cli.SendRedistribute(t, zebra.VRF_DEFAULT)
}
w := &zebraClient{
client: cli,
server: s,
nexthopCache: make(nexthopStateCache),
dead: make(chan struct{}),
client: cli,
server: s,
nexthopCache: make(nexthopStateCache),
mplsLabelRangeSize: mplsLabelRangeSize,
dead: make(chan struct{}),
mplsLabelRangeCh: make(chan [2]uint32),
}
go w.loop()
return w, nil
+8 -1
View File
@@ -1203,7 +1203,8 @@ module gobgp {
leaf version {
type uint8;
description
"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.";
}
leaf nexthop-trigger-enable {
type boolean;
@@ -1211,6 +1212,12 @@ module gobgp {
leaf nexthop-trigger-delay {
type uint8;
}
leaf mpls-label-range-size {
type uint32;
description
"Configure MPLS label range size which will be requested to
FRR/Zebra.";
}
}
grouping zebra-set {