summaryrefslogtreecommitdiffhomepage
path: root/internal/pkg
diff options
context:
space:
mode:
Diffstat (limited to 'internal/pkg')
-rw-r--r--internal/pkg/config/bgp_configs.go17
-rw-r--r--internal/pkg/table/path.go38
-rw-r--r--internal/pkg/table/table_manager.go76
-rw-r--r--internal/pkg/table/vrf.go22
-rw-r--r--internal/pkg/zebra/api_type_string.go4
-rw-r--r--internal/pkg/zebra/lsp_type_string.go16
-rw-r--r--internal/pkg/zebra/safi_string.go4
-rw-r--r--internal/pkg/zebra/zapi.go376
8 files changed, 505 insertions, 48 deletions
diff --git a/internal/pkg/config/bgp_configs.go b/internal/pkg/config/bgp_configs.go
index 7a533b56..d8b575b0 100644
--- a/internal/pkg/config/bgp_configs.go
+++ b/internal/pkg/config/bgp_configs.go
@@ -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
}
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,
}
}
diff --git a/internal/pkg/zebra/api_type_string.go b/internal/pkg/zebra/api_type_string.go
index af16317b..2c280533 100644
--- a/internal/pkg/zebra/api_type_string.go
+++ b/internal/pkg/zebra/api_type_string.go
@@ -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) {
diff --git a/internal/pkg/zebra/lsp_type_string.go b/internal/pkg/zebra/lsp_type_string.go
new file mode 100644
index 00000000..318c4800
--- /dev/null
+++ b/internal/pkg/zebra/lsp_type_string.go
@@ -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]]
+}
diff --git a/internal/pkg/zebra/safi_string.go b/internal/pkg/zebra/safi_string.go
index 8199a0e3..c8d469e4 100644
--- a/internal/pkg/zebra/safi_string.go
+++ b/internal/pkg/zebra/safi_string.go
@@ -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
diff --git a/internal/pkg/zebra/zapi.go b/internal/pkg/zebra/zapi.go
index 6bbe6a06..9659fa97 100644
--- a/internal/pkg/zebra/zapi.go
+++ b/internal/pkg/zebra/zapi.go
@@ -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{}
}