summaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorHitoshi Irino <irino@sfc.wide.ad.jp>2020-07-26 22:37:04 +0900
committerHitoshi Irino <irino@sfc.wide.ad.jp>2020-07-26 22:37:04 +0900
commitefeb8c51fbab58d378c7c5a8cb29099e9ae89449 (patch)
tree6cd2002518341f81ef149285921b2540e6ade00e
parent6178fc524f320a7fcd72f634659bb00eac6477a6 (diff)
zebra: refactoring and fix bug and add processing messageBackupNexthop (added in frr7.4)
- Move function for checking softwareName from internal/pkg/config/default.go to internal/pkg/zebra/zapi.go. - Delete support for frr7.1. - Fix bug by inverse processing MessageMTU and messageTag, and add messageTableId in decodeFromBytes and serialize of IPRouteBody. - Add processing messageBackupNexthop (which is added in frr7.4) in decodeFromBytes and serialize of IPRouteBody. - Update document.
-rw-r--r--docs/sources/zebra.md45
-rw-r--r--internal/pkg/config/default.go11
-rw-r--r--internal/pkg/zebra/apitype_string.go9
-rw-r--r--internal/pkg/zebra/zapi.go332
-rw-r--r--internal/pkg/zebra/zapi_test.go18
-rw-r--r--tools/pyang_plugins/gobgp.yang2
6 files changed, 272 insertions, 145 deletions
diff --git a/docs/sources/zebra.md b/docs/sources/zebra.md
index f2ee25a0..22f0cc39 100644
--- a/docs/sources/zebra.md
+++ b/docs/sources/zebra.md
@@ -11,15 +11,9 @@ Assume you finished [Getting Started](getting-started.md)
and installing Quagga or FRRouting on the same host with GoBGP.
**Note:** For the integration with FRRouting, version 3.0.x (Zebra API
-version 4), 5.0.x (Zebra API version 5), and 7.0.x (Zebra API version
-6) are supported as default. FRRouting version 5.0.x changes zebra
-message and it doesn't keep backward compatibility for FRRouting
-version 4.0.x although FRRouting version 4.0.x and 5.0.x use Zebra API
-version 5. Also, FRRouting version 7.0.x and 7.1.x changes zebra
-message and it doesn't keep backward compatibility for FRRouting
-version 6.0.x although FRRouting version 6.0.x, 7.0.x, 7.1.x and 7.2.x
-use Zebra API version 6. If you need to integrate with FRRouting
-version 4.0.x or 6.0x, please use `software-name` configuration.
+version 4), 5.0.x (Zebra API version 5), and 7.3.x (Zebra API version
+6) are supported as default. If you need to integrate with other
+version of FRRouting, please use `software-name` configuration.
## Contents
@@ -56,7 +50,7 @@ You need to enable the zebra feature in the Global configuration as follows.
To enable the Next-Hop Tracking features, please specify `3` or later.
For connecting to FRRouting 3.0.x, please specify `4`.
For connecting to FRRouting 5.0.x, please specify `5`.
- For connecting to FRRouting 7.0.x, please specify `6`.
+ For connecting to FRRouting 7.3.x, please specify `6`.
- `mpls-label-range-size` specifies mpls label range size for
requesting to Zebra. It works with FRRouting 5.0.x, FRRouting 6.0.x,
@@ -66,14 +60,29 @@ You need to enable the zebra feature in the Global configuration as follows.
configuration cannot specify software uniquely. This configuration
is used with 'version' configuration. For connecting to FRRouting
7.2.x, please specify `6` as `version` and `frr7.2` as
- `software-name`. For connecting to FRRouting 7.1.x, please specify
- `6` as `version` and `frr7.1` as `software-name`. For connecting to
- FRRouting 6.0.x, please specify `6` as `version` and `frr6` as
- `software-name`. For connecting to FRRouting 4.0.x, please specify
- `5` as `version` and `frr4` as `software-name`. For connecting to
- Cumulus Linux please specify `5` as `version` and `cumulus` as
- `software-name`. GoBGP is tested with Cumulus Linux VX 3.7.7 whose
- zebra version is 4.0+cl3u13 and its Zebra API version is 5.
+ `software-name`. For connecting to FRRouting 7.1.x and 7.0.x, please
+ specify `6` as `version` and `frr7` as `software-name`. For
+ connecting to FRRouting 6.0.x, please specify `6` as `version` and
+ `frr6` as `software-name`. For connecting to FRRouting 4.0.x,
+ please specify `5` as `version` and `frr4` as `software-name`. For
+ connecting to Cumulus Linux please specify `5` as `version` and
+ `cumulus` as `software-name`. GoBGP is tested with Cumulus Linux VX
+ 3.7.7 whose zebra version is 4.0+cl3u13 and its Zebra API version is
+ 5.
+
+### Summary of combination of version and software-name configrations
+|version|software-name|software |remarks |
+|-------|-------------|-------------------------|---------------------|
+|2 | |quagga |Ubuntu 16.04, CentOS7|
+|3 | |quagga |Ubuntu 18.04 |
+|4 | |FRRouting 3.0.x | |
+|5 | |FRRouting 5.0.x | |
+|5 |cumulus |Cumulus Linux VX 3.7.7 | |
+|5 |frr4 |FRRouting 4.0.x | |
+|6 | |FRRouting 7.3.x and 7.4.x|stable version of frr|
+|6 |frr7.2 |FRRouting 7.2.x |Ubuntu 20.04 |
+|6 |frr7 |FRRouting 7.0.x and 7.1.x|CentOS8 |
+|6 |frr6 |FRRouting 6.0.x | |
## Check Routes from zebra
diff --git a/internal/pkg/config/default.go b/internal/pkg/config/default.go
index 7727bf78..3d723cd9 100644
--- a/internal/pkg/config/default.go
+++ b/internal/pkg/config/default.go
@@ -421,16 +421,7 @@ func setDefaultConfigValuesWithViper(v *viper.Viper, b *BgpConfigSet) error {
b.Zebra.Config.NexthopTriggerDelay = 5
}
- //SoftwareName for Zebra
- allowableZebraSoftwareName := []string{"", "quagga", "frr3", "frr4", "frr5", "frr6", "frr7", "frr7.1", "frr7.2", "frr7.3", "cumulus"}
- isAllowable := false
- for _, allowable := range allowableZebraSoftwareName {
- if b.Zebra.Config.SoftwareName == allowable {
- isAllowable = true
- break
- }
- }
- if !isAllowable {
+ if !zebra.IsAllowableSoftwareName(b.Zebra.Config.Version, b.Zebra.Config.SoftwareName) {
b.Zebra.Config.SoftwareName = ""
}
diff --git a/internal/pkg/zebra/apitype_string.go b/internal/pkg/zebra/apitype_string.go
index 52e4af81..8e517bd7 100644
--- a/internal/pkg/zebra/apitype_string.go
+++ b/internal/pkg/zebra/apitype_string.go
@@ -114,8 +114,9 @@ func _() {
_ = x[_mlagClientUnregister-103]
_ = x[_mlagClientForwardMsg-104]
_ = x[zebraError-105]
- _ = x[BackwardIPv6RouteAdd-106]
- _ = x[BackwardIPv6RouteDelete-107]
+ _ = x[_clientCapabilities-106]
+ _ = x[BackwardIPv6RouteAdd-107]
+ _ = x[BackwardIPv6RouteDelete-108]
_ = x[zapi6Frr7dot2MinDifferentAPIType-48]
_ = x[zapi5ClMinDifferentAPIType-19]
_ = x[zapi5MinDifferentAPIType-7]
@@ -211,9 +212,9 @@ func _() {
_ = x[zapi3NexthopUpdate-29]
}
-const _APIType_name = "interfaceAddinterfaceDeleteinterfaceAddressAddinterfaceAddressDeleteinterfaceUpinterfaceDown_interfaceSetMaster_interfaceSetProtoDownRouteAddRouteDelete_routeNotifyOwnerredistributeAdd_redistributeDelete_redistributeDefaultAdd_redistributeDefaultDeleterouterIDAdd_routerIDDeleterouterIDUpdatehello_capabilitiesnexthopRegisternexthopUnregisternexthopUpdate_interfaceNBRAddressAdd_interfaceNBRAddressDelete_interfaceBFDDestUpdate_importRouteRegister_importRouteUnregister_importCheckUpdate_bfdDestRegister_bfdDestDeregister_bfdDestUpdate_bfdDestReplayredistributeRouteAddredistributeRouteDel_vrfUnregister_vrfAdd_vrfDeletevrfLabel_interfaceVRFUpdate_bfdClientRegister_bfdClientDeregister_interfaceEnableRADV_interfaceDisableRADVipv4NexthopLookupMRIB_interfaceLinkParams_mplsLabelsAdd_mplsLabelsDelete_mplsLabelsReplace_ipmrRouteStatslabelManagerConnectlabelManagerConnectAsyncgetLabelChunkreleaseLabelChunk_fecRegister_fecUnregister_fecUpdate_advertiseDefaultGW_advertiseSviMACIP_advertiseSubnet_advertiseAllVNI_localESAdd_localESDel_vniAdd_vniDel_l3VNIAdd_l3VNIDel_remoteVTEPAdd_remoteVTEPDel_macIPAdd_macIPDel_ipPrefixRouteAdd_ipPrefixRouteDel_remoteMACIPAdd_remoteMACIPDel_duplicateAddrDetection_pwAdd_pwDelete_pwSet_pwUnset_pwStatusUpdate_ruleAdd_ruleDelete_ruleNotifyOwner_tableManagerConnect_getTableChunk_releaseTableChunk_ipSetCreate_ipSetDestroy_ipSetEntryAdd_ipSetEntryDelete_ipSetNotifyOwner_ipSetEntryNotifyOwner_ipTableAdd_ipTableDelete_ipTableNotifyOwner_vxlanFloodControl_vxlanSgAdd_vxlanSgDel_vxlanSgReplay_mlagProcessUp_mlagProcessDown_mlagClientRegister_mlagClientUnregister_mlagClientForwardMsgzebraErrorBackwardIPv6RouteAddBackwardIPv6RouteDelete"
+const _APIType_name = "interfaceAddinterfaceDeleteinterfaceAddressAddinterfaceAddressDeleteinterfaceUpinterfaceDown_interfaceSetMaster_interfaceSetProtoDownRouteAddRouteDelete_routeNotifyOwnerredistributeAdd_redistributeDelete_redistributeDefaultAdd_redistributeDefaultDeleterouterIDAdd_routerIDDeleterouterIDUpdatehello_capabilitiesnexthopRegisternexthopUnregisternexthopUpdate_interfaceNBRAddressAdd_interfaceNBRAddressDelete_interfaceBFDDestUpdate_importRouteRegister_importRouteUnregister_importCheckUpdate_bfdDestRegister_bfdDestDeregister_bfdDestUpdate_bfdDestReplayredistributeRouteAddredistributeRouteDel_vrfUnregister_vrfAdd_vrfDeletevrfLabel_interfaceVRFUpdate_bfdClientRegister_bfdClientDeregister_interfaceEnableRADV_interfaceDisableRADVipv4NexthopLookupMRIB_interfaceLinkParams_mplsLabelsAdd_mplsLabelsDelete_mplsLabelsReplace_ipmrRouteStatslabelManagerConnectlabelManagerConnectAsyncgetLabelChunkreleaseLabelChunk_fecRegister_fecUnregister_fecUpdate_advertiseDefaultGW_advertiseSviMACIP_advertiseSubnet_advertiseAllVNI_localESAdd_localESDel_vniAdd_vniDel_l3VNIAdd_l3VNIDel_remoteVTEPAdd_remoteVTEPDel_macIPAdd_macIPDel_ipPrefixRouteAdd_ipPrefixRouteDel_remoteMACIPAdd_remoteMACIPDel_duplicateAddrDetection_pwAdd_pwDelete_pwSet_pwUnset_pwStatusUpdate_ruleAdd_ruleDelete_ruleNotifyOwner_tableManagerConnect_getTableChunk_releaseTableChunk_ipSetCreate_ipSetDestroy_ipSetEntryAdd_ipSetEntryDelete_ipSetNotifyOwner_ipSetEntryNotifyOwner_ipTableAdd_ipTableDelete_ipTableNotifyOwner_vxlanFloodControl_vxlanSgAdd_vxlanSgDel_vxlanSgReplay_mlagProcessUp_mlagProcessDown_mlagClientRegister_mlagClientUnregister_mlagClientForwardMsgzebraError_clientCapabilitiesBackwardIPv6RouteAddBackwardIPv6RouteDelete"
-var _APIType_index = [...]uint16{0, 12, 27, 46, 68, 79, 92, 111, 133, 141, 152, 169, 184, 203, 226, 252, 263, 278, 292, 297, 310, 325, 342, 355, 378, 404, 427, 447, 469, 487, 503, 521, 535, 549, 569, 589, 603, 610, 620, 628, 647, 665, 685, 705, 726, 747, 767, 781, 798, 816, 831, 850, 874, 887, 904, 916, 930, 940, 959, 977, 993, 1009, 1020, 1031, 1038, 1045, 1054, 1063, 1077, 1091, 1100, 1109, 1126, 1143, 1158, 1173, 1196, 1202, 1211, 1217, 1225, 1240, 1248, 1259, 1275, 1295, 1309, 1327, 1339, 1352, 1366, 1383, 1400, 1422, 1433, 1447, 1466, 1484, 1495, 1506, 1520, 1534, 1550, 1569, 1590, 1611, 1621, 1641, 1664}
+var _APIType_index = [...]uint16{0, 12, 27, 46, 68, 79, 92, 111, 133, 141, 152, 169, 184, 203, 226, 252, 263, 278, 292, 297, 310, 325, 342, 355, 378, 404, 427, 447, 469, 487, 503, 521, 535, 549, 569, 589, 603, 610, 620, 628, 647, 665, 685, 705, 726, 747, 767, 781, 798, 816, 831, 850, 874, 887, 904, 916, 930, 940, 959, 977, 993, 1009, 1020, 1031, 1038, 1045, 1054, 1063, 1077, 1091, 1100, 1109, 1126, 1143, 1158, 1173, 1196, 1202, 1211, 1217, 1225, 1240, 1248, 1259, 1275, 1295, 1309, 1327, 1339, 1352, 1366, 1383, 1400, 1422, 1433, 1447, 1466, 1484, 1495, 1506, 1520, 1534, 1550, 1569, 1590, 1611, 1621, 1640, 1660, 1683}
func (i APIType) String() string {
if i >= APIType(len(_APIType_index)-1) {
diff --git a/internal/pkg/zebra/zapi.go b/internal/pkg/zebra/zapi.go
index eb4d243a..32e9d8d2 100644
--- a/internal/pkg/zebra/zapi.go
+++ b/internal/pkg/zebra/zapi.go
@@ -112,6 +112,33 @@ const (
linkTypeIeee802154Phy
)
+const softwareNameMinimumVersion uint8 = 5
+
+var allowableSoftwareNameArrays = [][]string{
+ {"frr4", "cumulus"}, //version:5
+ {"frr7.2", "frr7", "frr6"}, //version:6
+}
+
+// IsAllowableSoftwareName returns bool from version number and softwareName
+func IsAllowableSoftwareName(version uint8, softwareName string) bool {
+ if softwareName == "" {
+ return true
+ } else if version < softwareNameMinimumVersion { //version is less than 5
+ return false
+ }
+ for i, allowableSoftwareNames := range allowableSoftwareNameArrays {
+ if version != uint8(i)+softwareNameMinimumVersion {
+ continue
+ }
+ for _, allowableSoftwareName := range allowableSoftwareNames {
+ if softwareName == allowableSoftwareName {
+ return true
+ }
+ }
+ }
+ return false
+}
+
// HeaderSize returns suitable header size from version
func HeaderSize(version uint8) uint16 {
switch version {
@@ -348,6 +375,7 @@ const (
_mlagClientUnregister // add in frr7.3
_mlagClientForwardMsg // add in frr7.3
zebraError // add in frr7.3
+ _clientCapabilities // add in frr7.4
// BackwardIPv6RouteAdd is referred in zclient_test
BackwardIPv6RouteAdd // quagga, frr3, frr4, frr5
// BackwardIPv6RouteDelete is referred in zclient_test
@@ -369,7 +397,7 @@ func minDifferentAPIType(version uint8, softwareName string) APIType {
} else if version == 5 && softwareName == "cumulus" {
return zapi5ClMinDifferentAPIType
} else if version == 5 ||
- (version == 6 && (softwareName == "frr6" || softwareName == "frr7" || softwareName == "frr7.1")) {
+ (version == 6 && (softwareName == "frr6" || softwareName == "frr7")) {
return zapi5MinDifferentAPIType
}
return zapi6Frr7dot2MinDifferentAPIType
@@ -622,13 +650,13 @@ var apiTypeZapi3Map = map[APIType]APIType{
}
func (t APIType) doesNeedConversion(version uint8, softwareName string) bool {
- if (version == 6 && (softwareName == "frr7.3" || softwareName == "")) || t < minDifferentAPIType(version, softwareName) {
+ if (version == 6 && softwareName == "") || t < minDifferentAPIType(version, softwareName) {
return false
}
return true
}
func apiTypeMap(version uint8, softwareName string) map[APIType]APIType {
- if version == 6 && (softwareName == "frr7" || softwareName == "frr7.1") {
+ if version == 6 && softwareName == "frr7" {
return apiTypeZapi6Frr7Map
} else if version == 6 && softwareName == "frr6" {
return apiTypeZapi6Frr6Map
@@ -754,7 +782,7 @@ func getRouteAll(version uint8, softwareName string) RouteType {
} else if version == 6 {
if softwareName == "frr6" {
return zapi6Frr6RouteAll
- } else if softwareName == "frr7" || softwareName == "frr7.1" {
+ } else if softwareName == "frr7" {
return zapi6Frr7RouteAll
} else if softwareName == "frr7.2" {
return zapi6Frr7dot2RouteAll
@@ -904,8 +932,9 @@ const ( // For FRRouting version 4, 5 and 6 (ZAPI version 5 and 6).
MessageMTU MessageFlag = 0x10
messageSRCPFX MessageFlag = 0x20
// MessageLabel is referred in zclient
- MessageLabel MessageFlag = 0x40 // deleted in frr7.3
- messageTableID MessageFlag = 0x80 // introduced in frr5
+ MessageLabel MessageFlag = 0x40 // deleted in frr7.3
+ messageBackupNexthops MessageFlag = 0x40 // added in frr7.4
+ messageTableID MessageFlag = 0x80 // introduced in frr5
)
const ( // For FRRouting.
@@ -941,7 +970,7 @@ func (f MessageFlag) ToEach(version uint8) MessageFlag {
}
return f
}
-func (f MessageFlag) string(version uint8) string {
+func (f MessageFlag) string(version uint8, softwareName string) string {
var ss []string
if f&MessageNexthop > 0 {
ss = append(ss, "NEXTHOP")
@@ -964,7 +993,9 @@ func (f MessageFlag) string(version uint8) string {
if version > 3 && f&messageSRCPFX.ToEach(version) > 0 {
ss = append(ss, "SRCPFX")
}
- if version > 4 && f&MessageLabel > 0 {
+ if version == 6 && softwareName == "" && f&messageBackupNexthops > 0 { // added in frr7.4
+ ss = append(ss, "BACKUP_NEXTHOPS")
+ } else if version > 4 && f&MessageLabel > 0 {
ss = append(ss, "LABEL")
}
if version > 5 && f&messageTableID > 0 {
@@ -1188,15 +1219,7 @@ func NewClient(network, address string, typ RouteType, version uint8, software s
} else if version > MaxZapiVer {
version = MaxZapiVer
}
- isAllowableSoftware := true
-
- if ((version == 2 || version == 3) && software != "" && software != "quagga") ||
- (version == 4 && software != "" && software != "frr3") ||
- (version == 5 && software != "" && software != "frr4" && software != "frr5" && software != "cumulus") ||
- (version == 6 && software != "" && software != "frr6" && software != "frr7" && software != "frr7.1" && software != "frr7.2" && software != "frr7.3") {
- isAllowableSoftware = false
- }
- if !isAllowableSoftware {
+ if !IsAllowableSoftwareName(version, software) {
log.WithFields(log.Fields{
"Topic": "Zebra",
}).Warnf("softwareName %s cannot be used with version %d.", software, version)
@@ -1523,7 +1546,7 @@ func (c *Client) close() error {
// SetLabelFlag is referred in zclient, this func sets label flag
func (c Client) SetLabelFlag(msgFlags *MessageFlag, nexthop *Nexthop) {
- if c.Version == 6 && (c.SoftwareName == "frr7.3" || c.SoftwareName == "") {
+ if c.Version == 6 && c.SoftwareName == "" {
nexthop.flags |= zapiNexthopFlagLabel
} else if c.Version > 4 {
*msgFlags |= MessageLabel
@@ -1751,8 +1774,9 @@ func (b *interfaceUpdateBody) decodeFromBytes(data []byte, version uint8, softwa
b.mtu6 = binary.BigEndian.Uint32(data[4:8])
b.bandwidth = binary.BigEndian.Uint32(data[8:12])
data = data[12:]
- if version == 6 &&
- (softwareName == "frr7.2" || softwareName == "frr7.3" || softwareName == "") { //link Ifindex
+
+ //frr 7.2 and later versions have link Ifindex
+ if version == 6 && !(softwareName == "frr7" || softwareName == "frr6") {
b.linkIfindex = binary.BigEndian.Uint32(data[:4])
data = data[4:]
}
@@ -1870,9 +1894,9 @@ func (b *routerIDUpdateBody) string(version uint8, softwareName string) string {
}
const (
- zapiNexthopFlagOnlink uint8 = 0x01 // frr7.1, 7.2, 7.3
- zapiNexthopFlagLabel uint8 = 0x02 // frr7.3
- zapiNexthopFlagWeight uint8 = 0x04 // frr7.3
+ zapiNexthopFlagOnlink uint8 = 0x01 // frr7.1, 7.2, 7.3, 7.4
+ zapiNexthopFlagLabel uint8 = 0x02 // frr7.3, 7.4
+ zapiNexthopFlagWeight uint8 = 0x04 // frr7.3, 7.4
)
// Flag for nexthop processing. It is gobgp's internal flag.
@@ -1897,9 +1921,9 @@ func nexthopProcessFlagForIPRouteBody(version uint8, softwareName string, isDeco
processFlag := (nexthopHasVrfID | nexthopHasType) // frr4, 5, 6, 7
if version == 6 {
switch softwareName {
- case "frr7.3", "":
+ case "":
processFlag |= (nexthopHasFlag | nexthopProcessIPToIPIFindex)
- case "frr7.2", "frr7.1", "frr7.0":
+ case "frr7.2", "frr7.0":
processFlag |= nexthopHasOnlink
}
}
@@ -1955,13 +1979,13 @@ func (n Nexthop) encode(version uint8, softwareName string, processFlag nexthopP
if processFlag&nexthopHasVrfID > 0 {
tmpbuf := make([]byte, 4)
binary.BigEndian.PutUint32(tmpbuf, n.VrfID)
- buf = append(buf, tmpbuf...)
+ buf = append(buf, tmpbuf...) //frr: stream_putl(s, api_nh->vrf_id);
}
if processFlag&nexthopHasType > 0 {
if n.Type == nexthopType(0) {
n.Type = n.gateToType(version)
}
- buf = append(buf, uint8(n.Type))
+ buf = append(buf, uint8(n.Type)) //frr: stream_putc(s, api_nh->type);
}
if processFlag&nexthopHasFlag > 0 {
if n.LabelNum > 0 {
@@ -1972,7 +1996,8 @@ func (n Nexthop) encode(version uint8, softwareName string, processFlag nexthopP
}
}
if processFlag&nexthopHasFlag > 0 || processFlag&nexthopHasOnlink > 0 {
- buf = append(buf, n.flags) // frr7.1, 7.2 has onlink, 7.3 has flag
+ // frr7.1, 7.2 has onlink, 7.3 has flag
+ buf = append(buf, n.flags) //frr: stream_putc(s, nh_flags);
}
nhType := n.Type
@@ -1984,9 +2009,11 @@ func (n Nexthop) encode(version uint8, softwareName string, processFlag nexthopP
}
if nhType == nexthopTypeIPv4.toEach(version) ||
nhType == nexthopTypeIPv4IFIndex.toEach(version) {
+ //frr: stream_put_in_addr(s, &api_nh->gate.ipv4);
buf = append(buf, n.Gate.To4()...)
} else if nhType == nexthopTypeIPv6.toEach(version) ||
nhType == nexthopTypeIPv6IFIndex.toEach(version) {
+ //frr: stream_write(s, (uint8_t *)&api_nh->gate.ipv6, 16);
buf = append(buf, n.Gate.To16()...)
}
if nhType == nexthopTypeIFIndex ||
@@ -1994,28 +2021,34 @@ func (n Nexthop) encode(version uint8, softwareName string, processFlag nexthopP
nhType == nexthopTypeIPv6IFIndex.toEach(version) {
tmpbuf := make([]byte, 4)
binary.BigEndian.PutUint32(tmpbuf, n.Ifindex)
- buf = append(buf, tmpbuf...)
+ buf = append(buf, tmpbuf...) //frr: stream_putl(s, api_nh->ifindex);
}
if nhType == nexthopTypeBlackhole.toEach(version) {
+ //frr: stream_putc(s, api_nh->bh_type);
buf = append(buf, uint8(n.blackholeType))
}
- if n.flags&zapiNexthopFlagLabel > 0 || message&MessageLabel > 0 {
+ if n.flags&zapiNexthopFlagLabel > 0 || (message&MessageLabel > 0 &&
+ (version == 5 || version == 6 &&
+ (softwareName == "frr6" || softwareName == "frr7" ||
+ softwareName == "frr7.2"))) {
tmpbuf := make([]byte, 1+4*n.LabelNum)
- tmpbuf[0] = n.LabelNum
+ tmpbuf[0] = n.LabelNum //frr: stream_putc(s, api_nh->label_num);
for i := uint8(0); i < n.LabelNum; i++ {
// 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(tmpbuf[i*4+1:], n.MplsLabels[i])
}
+ //frr: stream_put(s, &api_nh->labels[0], api_nh->label_num * sizeof(mpls_label_t));
buf = append(buf, tmpbuf...)
}
if n.flags&zapiNexthopFlagWeight > 0 && n.weight > 0 {
tmpbuf := make([]byte, 4)
binary.BigEndian.PutUint32(tmpbuf, uint32(n.weight))
- buf = append(buf, tmpbuf...)
+ buf = append(buf, tmpbuf...) //frr: stream_putl(s, api_nh->weight);
}
if apiFlag&flagEvpnRoute.ToEach(version, softwareName) > 0 {
+ //frr: stream_put(s, &(api_nh->rmac), sizeof(struct ethaddr));
buf = append(buf, n.rmac[:]...)
}
return buf
@@ -2025,19 +2058,20 @@ func (n Nexthop) encode(version uint8, softwareName string, processFlag nexthopP
func (n *Nexthop) decode(data []byte, version uint8, softwareName string, family uint8, processFlag nexthopProcessFlag, message MessageFlag, apiFlag Flag, nhType nexthopType) (int, error) {
offset := 0
if processFlag&nexthopHasVrfID > 0 {
+ //frr: STREAM_GETL(s, api_nh->vrf_id);
n.VrfID = binary.BigEndian.Uint32(data[offset : offset+4])
offset += 4
}
n.Type = nhType // data does not have nexthop type
if processFlag&nexthopHasType > 0 {
- n.Type = nexthopType(data[offset])
+ n.Type = nexthopType(data[offset]) //frr: STREAM_GETC(s, api_nh->type);
offset++
}
n.flags = uint8(0)
if processFlag&nexthopHasFlag > 0 || processFlag&nexthopHasOnlink > 0 {
- n.flags = uint8(data[offset])
+ n.flags = uint8(data[offset]) //frr: STREAM_GETC(s, api_nh->flags);
offset++
}
@@ -2055,25 +2089,28 @@ func (n *Nexthop) decode(data []byte, version uint8, softwareName string, family
}
if nhType == nexthopTypeIPv4.toEach(version) ||
nhType == nexthopTypeIPv4IFIndex.toEach(version) {
+ //frr: STREAM_GET(&api_nh->gate.ipv4.s_addr, s, IPV4_MAX_BYTELEN);
n.Gate = net.IP(data[offset : offset+4]).To4()
offset += 4
} else if nhType == nexthopTypeIPv6.toEach(version) ||
nhType == nexthopTypeIPv6IFIndex.toEach(version) {
+ //frr: STREAM_GET(&api_nh->gate.ipv6, s, 16);
n.Gate = net.IP(data[offset : offset+16]).To16()
offset += 16
}
if nhType == nexthopTypeIFIndex ||
nhType == nexthopTypeIPv4IFIndex.toEach(version) ||
nhType == nexthopTypeIPv6IFIndex.toEach(version) {
+ //frr: STREAM_GETL(s, api_nh->ifindex);
n.Ifindex = binary.BigEndian.Uint32(data[offset : offset+4])
offset += 4
}
if nhType == nexthopTypeBlackhole.toEach(version) {
- n.blackholeType = data[offset]
+ n.blackholeType = data[offset] //frr: STREAM_GETC(s, api_nh->bh_type);
offset++
}
if n.flags&zapiNexthopFlagLabel > 0 || message&MessageLabel > 0 {
- n.LabelNum = uint8(data[offset])
+ n.LabelNum = uint8(data[offset]) //frr: STREAM_GETC(s, api_nh->label_num);
offset++
if n.LabelNum > maxMplsLabel {
n.LabelNum = maxMplsLabel
@@ -2083,21 +2120,26 @@ func (n *Nexthop) decode(data []byte, version uint8, softwareName string, family
for i := uint8(0); i < n.LabelNum; i++ {
// frr uses stream_put which is unaware of byteorder for mpls label array.
// Therefore LittleEndian is used instead of BigEndian.
+ //frr: STREAM_GET(&api_nh->labels[0], s, api_nh->label_num * sizeof(mpls_label_t));
n.MplsLabels[i] = binary.LittleEndian.Uint32(data[offset : offset+4])
offset += 4
}
}
}
if n.flags&zapiNexthopFlagWeight > 0 {
+ //frr: STREAM_GETL(s, api_nh->weight);
n.weight = binary.BigEndian.Uint32(data[offset:])
+ offset += 4
}
if apiFlag&flagEvpnRoute.ToEach(version, softwareName) > 0 {
+ //frr: STREAM_GET(&(api_nh->rmac), s, sizeof(struct ethaddr));
copy(n.rmac[0:], data[offset:offset+6])
+ offset += 6
}
return offset, nil
}
-// Ref: zapi_nexthop_update_decode in lib/zclient.h
+// Ref: zapi_nexthop_decode in lib/zclient.h
// decodeNexthops is referred from decodeFromBytes of NexthopUpdateBody and IPRouteBody
func decodeNexthops(nexthops *[]Nexthop, data []byte, version uint8, softwareName string, family uint8, numNexthop uint16, processFlag nexthopProcessFlag, message MessageFlag, apiFlag Flag, nhType nexthopType) (int, error) {
offset := 0
@@ -2130,24 +2172,27 @@ func familyFromPrefix(prefix net.IP) uint8 {
// IPRouteBody is struct for IPRotue (zapi_route)
type IPRouteBody struct {
- Type RouteType
- instance uint16
- Flags Flag
- Message MessageFlag
- Safi Safi
- Prefix Prefix
- srcPrefix Prefix
- Nexthops []Nexthop
- Distance uint8
- Metric uint32
- Mtu uint32
- tag uint32
- API APIType // API is referred in zclient_test
-}
-
-func (b *IPRouteBody) safi(version uint8, sw string) Safi {
- if b.Safi == safiUnspec && (version < 6 || sw == "frr6" || sw == "frr7" || sw == "frr7.1") {
- return SafiUnicast // older versions don't have safiUnspec
+ Type RouteType
+ instance uint16
+ Flags Flag
+ Message MessageFlag
+ Safi Safi
+ Prefix Prefix
+ srcPrefix Prefix
+ Nexthops []Nexthop
+ backupNexthops []Nexthop // added in frr7.4
+ Distance uint8
+ Metric uint32
+ Mtu uint32
+ tag uint32
+ tableID uint32
+ API APIType // API is referred in zclient_test
+}
+
+func (b *IPRouteBody) safi(version uint8, software string) Safi {
+ // frr 7.2 and later versions have safiUnspec, older versions don't have safiUnspec
+ if b.Safi == safiUnspec && (version < 6 || software == "frr6" || software == "frr7") {
+ return SafiUnicast //safiUnspec is regarded as safiUnicast in older versions
}
if b.Safi <= safiMulticast || version > 4 { // not need to convert
return b.Safi
@@ -2221,42 +2266,54 @@ func (b *IPRouteBody) serialize(version uint8, softwareName string) ([]byte, err
} else if version == 4 {
buf = make([]byte, 10)
} else { // version >= 5
- buf = make([]byte, 9)
+ buf = make([]byte, 9) //type(1)+instance(2)+flags(4)+message(1)+safi(1)
}
- buf[0] = uint8(b.Type)
+ buf[0] = uint8(b.Type.toEach(version, softwareName)) //frr: stream_putc(s, api->type);
if version < 4 {
buf[1] = uint8(b.Flags)
buf[2] = uint8(b.Message)
binary.BigEndian.PutUint16(buf[3:5], uint16(b.Safi))
} else { // version >= 4
+ //frr: stream_putw(s, api->instance);
binary.BigEndian.PutUint16(buf[1:3], uint16(b.instance))
+ //frr: stream_putl(s, api->flags);
binary.BigEndian.PutUint32(buf[3:7], uint32(b.Flags))
+ //frr: stream_putc(s, api->message);
buf[7] = uint8(b.Message)
if version == 4 {
binary.BigEndian.PutUint16(buf[8:10], uint16(b.Safi))
} else { // version >= 5
+ //frr: stream_putc(s, api->safi);
buf[8] = uint8(b.Safi)
+
+ // only zapi version 5 (frr4.0.x) have evpn routes
if version == 5 && b.Flags&flagEvpnRoute.ToEach(version, softwareName) > 0 {
// size of struct ethaddr is 6 octets defined by ETH_ALEN
buf = append(buf, b.Nexthops[numNexthop-1].rmac[:6]...)
}
+
if b.Prefix.Family == syscall.AF_UNSPEC {
b.Prefix.Family = familyFromPrefix(b.Prefix.Prefix)
}
+ //frr: stream_putc(s, api->prefix.family);
buf = append(buf, b.Prefix.Family)
}
}
byteLen := (int(b.Prefix.PrefixLen) + 7) / 8
- buf = append(buf, b.Prefix.PrefixLen)
+ buf = append(buf, b.Prefix.PrefixLen) //frr: stream_putc(s, api->prefix.prefixlen);
+ //frr: stream_write(s, (uint8_t *)&api->prefix.u.prefix, psize);
buf = append(buf, b.Prefix.Prefix[:byteLen]...)
if version > 3 && b.Message&messageSRCPFX.ToEach(version) > 0 {
byteLen = (int(b.srcPrefix.PrefixLen) + 7) / 8
+ //frr: stream_putc(s, api->src_prefix.prefixlen);
buf = append(buf, b.srcPrefix.PrefixLen)
+ //frr: stream_write(s, (uint8_t *)&api->prefix.u.prefix, psize);
buf = append(buf, b.srcPrefix.Prefix[:byteLen]...)
}
+
+ processFlag := nexthopProcessFlagForIPRouteBody(version, softwareName, false)
if b.Message&MessageNexthop > 0 {
- processFlag := nexthopProcessFlagForIPRouteBody(version, softwareName, false)
if version < 5 {
if b.Flags&flagBlackhole > 0 {
buf = append(buf, []byte{1, uint8(nexthopTypeBlackhole.toEach(version))}...)
@@ -2266,12 +2323,20 @@ func (b *IPRouteBody) serialize(version uint8, softwareName string) ([]byte, err
} else { // version >= 5
tmpbuf := make([]byte, 2)
binary.BigEndian.PutUint16(tmpbuf, uint16(numNexthop))
- buf = append(buf, tmpbuf...)
+ buf = append(buf, tmpbuf...) //frr: stream_putw(s, api->nexthop_num);
}
for _, nexthop := range b.Nexthops {
buf = append(buf, nexthop.encode(version, softwareName, processFlag, b.Message, b.Flags)...)
}
}
+ if b.Message&messageBackupNexthops > 0 { // added in frr7.4
+ tmpbuf := make([]byte, 2)
+ binary.BigEndian.PutUint16(tmpbuf, uint16(len(b.backupNexthops)))
+ buf = append(buf, tmpbuf...) //frr: stream_putw(s, api->nexthop_num);
+ for _, nexthop := range b.backupNexthops {
+ buf = append(buf, nexthop.encode(version, softwareName, processFlag, b.Message, b.Flags)...)
+ }
+ }
if b.Message&MessageDistance.ToEach(version) > 0 {
buf = append(buf, b.Distance)
}
@@ -2280,48 +2345,109 @@ func (b *IPRouteBody) serialize(version uint8, softwareName string) ([]byte, err
binary.BigEndian.PutUint32(tmpbuf, b.Metric)
buf = append(buf, tmpbuf...)
}
+ if b.Message&messageTag.ToEach(version) > 0 {
+ tmpbuf := make([]byte, 4)
+ binary.BigEndian.PutUint32(tmpbuf, b.tag)
+ buf = append(buf, tmpbuf...)
+ }
if b.Message&MessageMTU.ToEach(version) > 0 {
tmpbuf := make([]byte, 4)
binary.BigEndian.PutUint32(tmpbuf, b.Mtu)
buf = append(buf, tmpbuf...)
}
- if b.Message&messageTag.ToEach(version) > 0 {
+ if b.Message&messageTableID.ToEach(version) > 0 {
tmpbuf := make([]byte, 4)
- binary.BigEndian.PutUint32(tmpbuf, b.tag)
+ binary.BigEndian.PutUint32(tmpbuf, b.tableID)
buf = append(buf, tmpbuf...)
}
return buf, nil
}
+func (b *IPRouteBody) decodeMessageNexthopFromBytes(data []byte, version uint8, softwareName string, isBackup bool) (int, error) {
+ pos := 0
+ rest := len(data)
+ message := MessageNexthop
+ nexthops := &b.Nexthops
+ messageString := "MessageNexthop"
+ if isBackup {
+ message = messageBackupNexthops
+ nexthops = &b.backupNexthops
+ messageString = "messageBackupNexthops"
+ }
+ if b.Message&message > 0 {
+ numNexthop := uint16(0)
+ numNexthopDataSize := 2
+ processFlag := nexthopProcessFlagForIPRouteBody(version, softwareName, true)
+ nhType := nexthopType(0)
+ if message == MessageNexthop && version < 5 { // frr3 and quagga
+ numNexthopDataSize = 1
+ nhType = nexthopTypeIPv4.toEach(version)
+ if b.Prefix.Family == syscall.AF_INET6 {
+ nhType = nexthopTypeIPv6.toEach(version)
+ }
+ }
+ if pos+numNexthopDataSize > rest {
+ return pos, fmt.Errorf("%s message length invalid pos:%d rest:%d", messageString, pos, rest)
+ }
+ if numNexthopDataSize == 2 {
+ //frr: STREAM_GETW(s, api->nexthop_num);
+ numNexthop = binary.BigEndian.Uint16(data[pos : pos+2])
+ } else if message == MessageNexthop && numNexthopDataSize == 1 {
+ numNexthop = uint16(data[pos])
+ }
+ pos += numNexthopDataSize
+
+ nexthopsByteLen, err := decodeNexthops(nexthops, data[pos:], version, softwareName, b.Prefix.Family, numNexthop, processFlag, b.Message, b.Flags, nhType)
+ if err != nil {
+ return pos, err
+ }
+ pos += nexthopsByteLen
+ }
+ return pos, nil
+}
+
// Ref: zebra_read_ipv4 in bgpd/bgp_zebra.c of Quagga1.2.x&FRR3.x(ZAPI3&4)
// Ref: zapi_route_decode in lib/zclient.c of FRR5.x (ZAPI5)
func (b *IPRouteBody) decodeFromBytes(data []byte, version uint8, softwareName string) error {
if b == nil {
return fmt.Errorf("IPRouteBody is nil")
}
+ //frr: STREAM_GETC(s, api->type);
b.Type = RouteType(data[0])
+ if b.Type > getRouteAll(version, softwareName) { //ver5 and later work, fix for older
+ return fmt.Errorf("unknown route type: %d in version: %d (%s)", b.Type, version, softwareName)
+ }
+
if version <= 3 {
b.Flags = Flag(data[1])
data = data[2:]
} else { // version >= 4
+ //frr: STREAM_GETW(s, api->instance);
b.instance = binary.BigEndian.Uint16(data[1:3])
+ //frr: STREAM_GETL(s, api->flags);
b.Flags = Flag(binary.BigEndian.Uint32(data[3:7]))
data = data[7:]
}
- b.Message = MessageFlag(data[0])
+ b.Message = MessageFlag(data[0]) //frr: STREAM_GETC(s, api->message);
b.Safi = Safi(SafiUnicast)
b.Prefix.Family = b.API.addressFamily(version) // return AF_UNSPEC if version > 4
var evpnNexthop Nexthop
if version > 4 {
- b.Safi = Safi(data[1])
+ b.Safi = Safi(data[1]) //frr: STREAM_GETC(s, api->safi);
+ if b.Safi > safiMax { //frr5 and later work, ToDo: fix for older version
+ return fmt.Errorf("unknown safi type: %d in version: %d (%s)", b.Type, version, softwareName)
+ }
data = data[2:]
+
+ // zapi version 5 only
if version == 5 && b.Flags&flagEvpnRoute.ToEach(version, softwareName) > 0 {
// size of struct ethaddr is 6 octets defined by ETH_ALEN
copy(evpnNexthop.rmac[0:6], data[0:6])
data = data[6:]
}
- b.Prefix.Family = data[0]
+
+ b.Prefix.Family = data[0] //frr: STREAM_GETC(s, api->prefix.family);
}
addrByteLen, err := addressByteLength(b.Prefix.Family)
@@ -2331,7 +2457,7 @@ func (b *IPRouteBody) decodeFromBytes(data []byte, version uint8, softwareName s
addrBitLen := uint8(addrByteLen * 8)
- b.Prefix.PrefixLen = data[1]
+ b.Prefix.PrefixLen = data[1] //frr: STREAM_GETC(s, api->prefix.prefixlen);
if b.Prefix.PrefixLen > addrBitLen {
return fmt.Errorf("prefix length %d is greater than %d", b.Prefix.PrefixLen, addrBitLen)
}
@@ -2344,6 +2470,7 @@ func (b *IPRouteBody) decodeFromBytes(data []byte, version uint8, softwareName s
if pos+byteLen > rest {
return fmt.Errorf("message length invalid pos:%d rest:%d", pos, rest)
}
+ //frr: STREAM_GET(&api->prefix.u.prefix, s, PSIZE(api->prefix.prefixlen));
copy(buf, data[pos:pos+byteLen])
b.Prefix.Prefix = ipFromFamily(b.Prefix.Family, buf)
pos += byteLen
@@ -2351,6 +2478,7 @@ func (b *IPRouteBody) decodeFromBytes(data []byte, version uint8, softwareName s
if pos+1 > rest {
return fmt.Errorf("MessageSRCPFX message length invalid pos:%d rest:%d", pos, rest)
}
+ //frr: STREAM_GETC(s, api->src_prefix.prefixlen);
b.srcPrefix.PrefixLen = data[pos]
if b.srcPrefix.PrefixLen > addrBitLen {
return fmt.Errorf("prefix length is greater than %d", addrByteLen*8)
@@ -2361,45 +2489,29 @@ func (b *IPRouteBody) decodeFromBytes(data []byte, version uint8, softwareName s
if pos+byteLen > rest {
return fmt.Errorf("MessageSRCPFX message length invalid pos:%d rest:%d", pos, rest)
}
+ //frr: STREAM_GET(&api->src_prefix.prefix, s, PSIZE(api->src_prefix.prefixlen));
copy(buf, data[pos:pos+byteLen])
b.srcPrefix.Prefix = ipFromFamily(b.Prefix.Family, buf)
pos += byteLen
}
b.Nexthops = []Nexthop{}
- if b.Message&MessageNexthop > 0 {
- numNexthop := uint16(0)
- numNexthopDataSize := 2
- processFlag := nexthopProcessFlagForIPRouteBody(version, softwareName, true)
- nhType := nexthopType(0)
- if version < 5 { // frr3 and quagga
- numNexthopDataSize = 1
- nhType = nexthopTypeIPv4.toEach(version)
- if b.Prefix.Family == syscall.AF_INET6 {
- nhType = nexthopTypeIPv6.toEach(version)
- }
- }
- if pos+numNexthopDataSize > rest {
- return fmt.Errorf("MessageNexthop message length invalid pos:%d rest:%d", pos, rest)
- }
- if numNexthopDataSize == 2 {
- numNexthop = binary.BigEndian.Uint16(data[pos : pos+2])
- } else if numNexthopDataSize == 1 {
- numNexthop = uint16(data[pos])
- }
- pos += numNexthopDataSize
-
- nexthopsByteLen, err := decodeNexthops(&b.Nexthops, data[pos:], version, softwareName, b.Prefix.Family, numNexthop, processFlag, b.Message, b.Flags, nhType)
- if err != nil {
- return err
- }
- pos += nexthopsByteLen
+ offset, err := b.decodeMessageNexthopFromBytes(data[pos:], version, softwareName, false)
+ if err != nil {
+ return err
+ }
+ pos += offset
+ b.backupNexthops = []Nexthop{} // backupNexthops is added in frr7.4
+ offset, err = b.decodeMessageNexthopFromBytes(data[pos:], version, softwareName, true)
+ if err != nil {
+ return err
}
+ pos += offset
+ // version 5 only, In version 6, EvpnRoute is processed in MessageNexthop
if version == 5 && b.Flags&flagEvpnRoute.ToEach(version, softwareName) > 0 {
b.Nexthops = append(b.Nexthops, evpnNexthop)
}
-
- if version < 5 && b.Message&messageIFIndex > 0 {
+ if version < 5 && b.Message&messageIFIndex > 0 { // version 4, 3, 2
if pos+1 > rest {
return fmt.Errorf("MessageIFIndex message length invalid pos:%d rest:%d", pos, rest)
}
@@ -2421,30 +2533,44 @@ func (b *IPRouteBody) decodeFromBytes(data []byte, version uint8, softwareName s
if pos+1 > rest {
return fmt.Errorf("MessageDistance message length invalid pos:%d rest:%d", pos, rest)
}
- b.Distance = data[pos]
+ b.Distance = data[pos] //frr: STREAM_GETC(s, api->distance);
pos++
}
if b.Message&MessageMetric.ToEach(version) > 0 {
if pos+4 > rest {
return fmt.Errorf("MessageMetric message length invalid pos:%d rest:%d", pos, rest)
}
+ //frr: STREAM_GETL(s, api->metric);
b.Metric = binary.BigEndian.Uint32(data[pos : pos+4])
pos += 4
}
+ if b.Message&messageTag.ToEach(version) > 0 {
+ if pos+4 > rest {
+ return fmt.Errorf("MessageTag message length invalid pos:%d rest:%d", pos, rest)
+ }
+ //frr: STREAM_GETL(s, api->tag);
+ b.tag = binary.BigEndian.Uint32(data[pos : pos+4])
+ pos += 4
+ }
+ //frr3 and quagga does not have MESSAGE_MTU
if b.Message&MessageMTU.ToEach(version) > 0 {
if pos+4 > rest {
return fmt.Errorf("MessageMTU message length invalid pos:%d rest:%d", pos, rest)
}
+ //frr: STREAM_GETL(s, api->mtu);
b.Mtu = binary.BigEndian.Uint32(data[pos : pos+4])
pos += 4
}
- if b.Message&messageTag.ToEach(version) > 0 {
+ //frr5 and later version have MESSAGE_TABLEID
+ if b.Message&messageTableID.ToEach(version) > 0 {
if pos+4 > rest {
- return fmt.Errorf("MessageTag message length invalid pos:%d rest:%d", pos, rest)
+ return fmt.Errorf("MessageTableID message length invalid pos:%d rest:%d", pos, rest)
}
- b.tag = binary.BigEndian.Uint32(data[pos : pos+4])
+ //frr: STREAM_GETL(s, api->mtu);
+ b.Mtu = binary.BigEndian.Uint32(data[pos : pos+4])
pos += 4
}
+
if pos != rest {
return fmt.Errorf("message length invalid (last) pos:%d rest:%d, message:%#x", pos, rest, b.Message)
}
@@ -2454,7 +2580,7 @@ func (b *IPRouteBody) decodeFromBytes(data []byte, version uint8, softwareName s
func (b *IPRouteBody) string(version uint8, softwareName string) string {
s := fmt.Sprintf(
"type: %s, instance: %d, flags: %s, message: %d(%s), safi: %s, prefix: %s/%d, src_prefix: %s/%d",
- b.Type.String(), b.instance, b.Flags.String(version, softwareName), b.Message, b.Message.string(version), b.Safi.String(), b.Prefix.Prefix.String(), b.Prefix.PrefixLen, b.srcPrefix.Prefix.String(), b.srcPrefix.PrefixLen)
+ b.Type.String(), b.instance, b.Flags.String(version, softwareName), b.Message, b.Message.string(version, softwareName), b.Safi.String(), b.Prefix.Prefix.String(), b.Prefix.PrefixLen, b.srcPrefix.Prefix.String(), b.srcPrefix.PrefixLen)
for i, nh := range b.Nexthops {
s += fmt.Sprintf(", nexthops[%d]: %s", i, nh.string())
}
@@ -2750,9 +2876,9 @@ func (b *NexthopUpdateBody) decodeFromBytes(data []byte, version uint8, software
processFlag := nexthopProcessFlag(nexthopHasType)
if version == 6 {
switch softwareName {
- case "frr7.3", "":
+ case "":
processFlag |= (nexthopHasVrfID | nexthopHasFlag | nexthopProcessIPToIPIFindex)
- case "frr7.0", "frr7.1", "frr7.2":
+ case "frr7.0", "frr7.2":
processFlag |= (nexthopHasVrfID | nexthopProcessIPToIPIFindex)
case "frr6":
processFlag |= nexthopProcessIPToIPIFindex
@@ -2854,7 +2980,7 @@ func (b *GetLabelChunkBody) serialize(version uint8, softwareName string) ([]byt
buf[pos] = b.keep
binary.BigEndian.PutUint32(buf[pos+1:pos+5], b.ChunkSize)
pos += 5
- if version == 6 && (softwareName == "frr7.2" || softwareName == "frr7.3" || softwareName == "") {
+ if version == 6 && !(softwareName == "frr6" || softwareName == "frr7") {
binary.BigEndian.PutUint32(buf[pos:pos+4], b.base)
pos += 4
}
diff --git a/internal/pkg/zebra/zapi_test.go b/internal/pkg/zebra/zapi_test.go
index 1f877d46..61ccf94b 100644
--- a/internal/pkg/zebra/zapi_test.go
+++ b/internal/pkg/zebra/zapi_test.go
@@ -111,7 +111,7 @@ func Test_interfaceUpdateBody(t *testing.T) {
pos += 4 // MTU6
binary.BigEndian.PutUint32(buf[pos:], 200)
pos += 4 // bandwidth
- if v == 6 { // "frr7.2", "frr7.3", ""
+ if v == 6 { // "frr7.2", ""
binary.BigEndian.PutUint32(buf[pos:], 1)
pos += 4 // link Ifindex
}
@@ -275,7 +275,7 @@ func Test_IPRouteBody_IPv4(t *testing.T) {
buf[pos] = byte(nexthopTypeIPv4IFIndex)
pos++
}
- if v == 6 { //onlink (frr7,1, 7.2, 7.3)
+ if v == 6 { //onlink (frr7,1, 7.2, 7.3, 7.4)
buf[pos] = 1
pos++
}
@@ -362,7 +362,7 @@ func Test_IPRouteBody_IPv4(t *testing.T) {
assert.Equal(byte(nexthopTypeIPv4IFIndex), buf[pos])
pos += 9
}
- if v == 6 { //onlink (frr7,1, 7.2, 7.3)
+ if v == 6 { //onlink (frr7,1, 7.2, 7.3, 7.4)
assert.Equal(byte(0x1), buf[pos])
pos++
}
@@ -412,7 +412,7 @@ func Test_IPRouteBody_IPv4(t *testing.T) {
buf[pos] = byte(nexthopTypeIPv4IFIndex)
pos++
}
- if v == 6 { //onlink (frr7,1, 7.2, 7.3)
+ if v == 6 { //onlink (frr7,1, 7.2, 7.3, 7.4)
buf[pos] = 1
pos++
}
@@ -553,7 +553,7 @@ func Test_IPRouteBody_IPv6(t *testing.T) {
buf[pos] = byte(nexthopTypeIPv6IFIndex)
pos++
}
- if v == 6 { //onlink (frr7,1, 7.2, 7.3)
+ if v == 6 { //onlink (frr7,1, 7.2, 7.3, 7.4)
buf[pos] = 1
pos++
}
@@ -628,7 +628,7 @@ func Test_IPRouteBody_IPv6(t *testing.T) {
}
assert.Equal(byte(nexthopType[v]), buf[pos])
pos++
- if v == 6 { //onlink (frr7,1, 7.2, 7.3)
+ if v == 6 { //onlink (frr7,1, 7.2, 7.3, 7.4)
assert.Equal(byte(0x1), buf[pos])
pos++
}
@@ -690,7 +690,7 @@ func Test_IPRouteBody_IPv6(t *testing.T) {
buf[pos] = byte(nexthopTypeIPv6IFIndex)
pos++
}
- if v == 6 { //onlink (frr7,1, 7.2, 7.3)
+ if v == 6 { //onlink (frr7,1, 7.2, 7.3, 7.4)
buf[pos] = 1
pos++
}
@@ -974,14 +974,14 @@ func Test_NexthopUpdateBody(t *testing.T) {
}
bufIn[pos] = byte(nexthopType[v])
pos++
- if v == 6 { // frr7.3 and after
+ if v == 6 { // frr7.3 and later
bufIn[pos] = byte(0) // nexthop flag
pos++
}
// nexthop_ip(4 bytes)="192.168.0.1", nexthop_Ifindex(4 byte)=2
copy(bufIn[pos:pos+8], []byte{0xc0, 0xa8, 0x01, 0x01, 0x00, 0x00, 0x00, 0x02})
pos += 8
- if v == 5 { // frr7.3(latest software of zapi v6) depends on nexthop flag
+ if v == 5 { // frr7.3&7.4 (latest software of zapi v6) depends on nexthop flag
bufIn[pos] = byte(0) // label num
pos++
}
diff --git a/tools/pyang_plugins/gobgp.yang b/tools/pyang_plugins/gobgp.yang
index 414dbf17..eeda0aa6 100644
--- a/tools/pyang_plugins/gobgp.yang
+++ b/tools/pyang_plugins/gobgp.yang
@@ -1248,7 +1248,7 @@ module gobgp {
type string;
description
"Configure zebra software name.
- quagga, frr3, frr4, frr5, frr6, frr7, frr7.1, frr7.2, and frr7.3 can be used.";
+ frr4, cumulus, frr6, frr7, and frr7.2 can be used.";
}
}