diff options
author | Hitoshi Irino <irino@sfc.wide.ad.jp> | 2020-11-29 12:23:28 +0900 |
---|---|---|
committer | Hitoshi Irino <irino@sfc.wide.ad.jp> | 2020-11-29 12:23:28 +0900 |
commit | b55c32ce65c9b6e0c9f4620e6acb27e0e49f238d (patch) | |
tree | 18b790097b5a5ea41bfdf0e29826875353b350fb /internal | |
parent | c5dcfb72a847899e188ab5a77dd8e31a05a15be7 (diff) |
Support of FRR7.5
This commit works with FRR7.5 when "version = 6" is specified in zebra.config
- Changes Zebra internal API commands to FRR7.5 which is incompatible with older version.
- Changes SendHello() to include AFI
- Changes SendRouteIDAdd() to include AFI
- Changes decodeFromBytes/serialize of IPRouteBody and NexthopUpdateBody, because size of MESSAGE_FALG is changed.
Diffstat (limited to 'internal')
-rw-r--r-- | internal/pkg/config/bgp_configs.go | 4 | ||||
-rw-r--r-- | internal/pkg/zebra/apitype_string.go | 140 | ||||
-rw-r--r-- | internal/pkg/zebra/routetype_string.go | 10 | ||||
-rw-r--r-- | internal/pkg/zebra/zapi.go | 351 | ||||
-rw-r--r-- | internal/pkg/zebra/zapi_test.go | 97 |
5 files changed, 421 insertions, 181 deletions
diff --git a/internal/pkg/config/bgp_configs.go b/internal/pkg/config/bgp_configs.go index 6d8fd26c..7777cacb 100644 --- a/internal/pkg/config/bgp_configs.go +++ b/internal/pkg/config/bgp_configs.go @@ -1141,7 +1141,7 @@ type ZebraState struct { MplsLabelRangeSize uint32 `mapstructure:"mpls-label-range-size" json:"mpls-label-range-size,omitempty"` // original -> gobgp:software-name // Configure zebra software name. - // frr4, cumulus, frr6, frr7, and frr7.2 can be used. + // frr4, cumulus, frr6, frr7, frr7.2, and frr7.3 can be used. SoftwareName string `mapstructure:"software-name" json:"software-name,omitempty"` } @@ -1171,7 +1171,7 @@ type ZebraConfig struct { MplsLabelRangeSize uint32 `mapstructure:"mpls-label-range-size" json:"mpls-label-range-size,omitempty"` // original -> gobgp:software-name // Configure zebra software name. - // frr4, cumulus, frr6, frr7, and frr7.2 can be used. + // frr4, cumulus, frr6, frr7, frr7.2, and frr7.3 can be used. SoftwareName string `mapstructure:"software-name" json:"software-name,omitempty"` } diff --git a/internal/pkg/zebra/apitype_string.go b/internal/pkg/zebra/apitype_string.go index 8e517bd7..5ebeabd2 100644 --- a/internal/pkg/zebra/apitype_string.go +++ b/internal/pkg/zebra/apitype_string.go @@ -57,71 +57,87 @@ func _() { _ = x[_mplsLabelsAdd-46] _ = x[_mplsLabelsDelete-47] _ = x[_mplsLabelsReplace-48] - _ = x[_ipmrRouteStats-49] - _ = x[labelManagerConnect-50] - _ = x[labelManagerConnectAsync-51] - _ = x[getLabelChunk-52] - _ = x[releaseLabelChunk-53] - _ = x[_fecRegister-54] - _ = x[_fecUnregister-55] - _ = x[_fecUpdate-56] - _ = x[_advertiseDefaultGW-57] - _ = x[_advertiseSviMACIP-58] - _ = x[_advertiseSubnet-59] - _ = x[_advertiseAllVNI-60] - _ = x[_localESAdd-61] - _ = x[_localESDel-62] - _ = x[_vniAdd-63] - _ = x[_vniDel-64] - _ = x[_l3VNIAdd-65] - _ = x[_l3VNIDel-66] - _ = x[_remoteVTEPAdd-67] - _ = x[_remoteVTEPDel-68] - _ = x[_macIPAdd-69] - _ = x[_macIPDel-70] - _ = x[_ipPrefixRouteAdd-71] - _ = x[_ipPrefixRouteDel-72] - _ = x[_remoteMACIPAdd-73] - _ = x[_remoteMACIPDel-74] - _ = x[_duplicateAddrDetection-75] - _ = x[_pwAdd-76] - _ = x[_pwDelete-77] - _ = x[_pwSet-78] - _ = x[_pwUnset-79] - _ = x[_pwStatusUpdate-80] - _ = x[_ruleAdd-81] - _ = x[_ruleDelete-82] - _ = x[_ruleNotifyOwner-83] - _ = x[_tableManagerConnect-84] - _ = x[_getTableChunk-85] - _ = x[_releaseTableChunk-86] - _ = x[_ipSetCreate-87] - _ = x[_ipSetDestroy-88] - _ = x[_ipSetEntryAdd-89] - _ = x[_ipSetEntryDelete-90] - _ = x[_ipSetNotifyOwner-91] - _ = x[_ipSetEntryNotifyOwner-92] - _ = x[_ipTableAdd-93] - _ = x[_ipTableDelete-94] - _ = x[_ipTableNotifyOwner-95] - _ = x[_vxlanFloodControl-96] - _ = x[_vxlanSgAdd-97] - _ = x[_vxlanSgDel-98] - _ = x[_vxlanSgReplay-99] - _ = x[_mlagProcessUp-100] - _ = x[_mlagProcessDown-101] - _ = x[_mlagClientRegister-102] - _ = x[_mlagClientUnregister-103] - _ = x[_mlagClientForwardMsg-104] - _ = x[zebraError-105] - _ = x[_clientCapabilities-106] - _ = x[BackwardIPv6RouteAdd-107] - _ = x[BackwardIPv6RouteDelete-108] + _ = x[_srPolicySet-49] + _ = x[_srPolicyDelete-50] + _ = x[_srPolicyNotifyStatus-51] + _ = x[_ipmrRouteStats-52] + _ = x[labelManagerConnect-53] + _ = x[labelManagerConnectAsync-54] + _ = x[getLabelChunk-55] + _ = x[releaseLabelChunk-56] + _ = x[_fecRegister-57] + _ = x[_fecUnregister-58] + _ = x[_fecUpdate-59] + _ = x[_advertiseDefaultGW-60] + _ = x[_advertiseSviMACIP-61] + _ = x[_advertiseSubnet-62] + _ = x[_advertiseAllVNI-63] + _ = x[_localESAdd-64] + _ = x[_localESDel-65] + _ = x[_remoteESVTEPAdd-66] + _ = x[_remoteESVTEPDel-67] + _ = x[_localESEVIAdd-68] + _ = x[_localESEVIDel-69] + _ = x[_vniAdd-70] + _ = x[_vniDel-71] + _ = x[_l3VNIAdd-72] + _ = x[_l3VNIDel-73] + _ = x[_remoteVTEPAdd-74] + _ = x[_remoteVTEPDel-75] + _ = x[_macIPAdd-76] + _ = x[_macIPDel-77] + _ = x[_ipPrefixRouteAdd-78] + _ = x[_ipPrefixRouteDel-79] + _ = x[_remoteMACIPAdd-80] + _ = x[_remoteMACIPDel-81] + _ = x[_duplicateAddrDetection-82] + _ = x[_pwAdd-83] + _ = x[_pwDelete-84] + _ = x[_pwSet-85] + _ = x[_pwUnset-86] + _ = x[_pwStatusUpdate-87] + _ = x[_ruleAdd-88] + _ = x[_ruleDelete-89] + _ = x[_ruleNotifyOwner-90] + _ = x[_tableManagerConnect-91] + _ = x[_getTableChunk-92] + _ = x[_releaseTableChunk-93] + _ = x[_ipSetCreate-94] + _ = x[_ipSetDestroy-95] + _ = x[_ipSetEntryAdd-96] + _ = x[_ipSetEntryDelete-97] + _ = x[_ipSetNotifyOwner-98] + _ = x[_ipSetEntryNotifyOwner-99] + _ = x[_ipTableAdd-100] + _ = x[_ipTableDelete-101] + _ = x[_ipTableNotifyOwner-102] + _ = x[_vxlanFloodControl-103] + _ = x[_vxlanSgAdd-104] + _ = x[_vxlanSgDel-105] + _ = x[_vxlanSgReplay-106] + _ = x[_mlagProcessUp-107] + _ = x[_mlagProcessDown-108] + _ = x[_mlagClientRegister-109] + _ = x[_mlagClientUnregister-110] + _ = x[_mlagClientForwardMsg-111] + _ = x[zebraError-112] + _ = x[_clientCapabilities-113] + _ = x[_opaqueMessage-114] + _ = x[_opaqueRegister-115] + _ = x[_opaqueUnregister-116] + _ = x[_neighDiscover-117] + _ = x[BackwardIPv6RouteAdd-118] + _ = x[BackwardIPv6RouteDelete-119] + _ = x[zapi6Frr7dot3MinDifferentAPIType-49] _ = x[zapi6Frr7dot2MinDifferentAPIType-48] _ = x[zapi5ClMinDifferentAPIType-19] _ = x[zapi5MinDifferentAPIType-7] _ = x[zapi4MinDifferentAPIType-6] _ = x[zapi3MinDifferentAPIType-0] + _ = x[zapi6Frr7dot3LabelManagerConnect-50] + _ = x[zapi6Frr7dot3LabelManagerConnectAsync-51] + _ = x[zapi6Frr7dot3GetLabelChunk-52] + _ = x[zapi6Frr7dot3ReleaseLabelChunk-53] _ = x[zapi6Frr7dot2LabelManagerConnect-49] _ = x[zapi6Frr7dot2LabelManagerConnectAsync-50] _ = x[zapi6Frr7dot2GetLabelChunk-51] @@ -212,9 +228,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_mlagClientForwardMsgzebraError_clientCapabilitiesBackwardIPv6RouteAddBackwardIPv6RouteDelete" +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_srPolicySet_srPolicyDelete_srPolicyNotifyStatus_ipmrRouteStatslabelManagerConnectlabelManagerConnectAsyncgetLabelChunkreleaseLabelChunk_fecRegister_fecUnregister_fecUpdate_advertiseDefaultGW_advertiseSviMACIP_advertiseSubnet_advertiseAllVNI_localESAdd_localESDel_remoteESVTEPAdd_remoteESVTEPDel_localESEVIAdd_localESEVIDel_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_clientCapabilities_opaqueMessage_opaqueRegister_opaqueUnregister_neighDiscoverBackwardIPv6RouteAddBackwardIPv6RouteDelete" -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} +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, 828, 843, 864, 879, 898, 922, 935, 952, 964, 978, 988, 1007, 1025, 1041, 1057, 1068, 1079, 1095, 1111, 1125, 1139, 1146, 1153, 1162, 1171, 1185, 1199, 1208, 1217, 1234, 1251, 1266, 1281, 1304, 1310, 1319, 1325, 1333, 1348, 1356, 1367, 1383, 1403, 1417, 1435, 1447, 1460, 1474, 1491, 1508, 1530, 1541, 1555, 1574, 1592, 1603, 1614, 1628, 1642, 1658, 1677, 1698, 1719, 1729, 1748, 1762, 1777, 1794, 1808, 1828, 1851} func (i APIType) String() string { if i >= APIType(len(_APIType_index)-1) { diff --git a/internal/pkg/zebra/routetype_string.go b/internal/pkg/zebra/routetype_string.go index 4016b586..ee15413f 100644 --- a/internal/pkg/zebra/routetype_string.go +++ b/internal/pkg/zebra/routetype_string.go @@ -37,13 +37,15 @@ func _() { _ = x[routeOpenfabric-26] _ = x[routeVRRP-27] _ = x[routeNHG-28] - _ = x[routeAll-29] - _ = x[routeMax-30] + _ = x[routeSRTE-29] + _ = x[routeAll-30] + _ = x[routeMax-31] _ = x[zapi5Frr4RouteAll-24] _ = x[zapi5Frr5RouteAll-25] _ = x[zapi6Frr6RouteAll-26] _ = x[zapi6Frr7RouteAll-27] _ = x[zapi6Frr7dot2RouteAll-28] + _ = x[zapi6Frr7dot3RouteAll-29] _ = x[zapi4RouteNHRP-11] _ = x[zapi4RouteHSLS-12] _ = x[zapi4RouteOLSR-13] @@ -61,9 +63,9 @@ func _() { _ = x[zapi3RouteNHRP-14] } -const _RouteType_name = "routeSystemrouteKernelrouteConnectRouteStaticrouteRIProuteRIPNGrouteOSPFrouteOSPF6routeISISRouteBGProutePIMrouteEIGRProuteNHRProuteHSLSrouteOLSRrouteTABLErouteLDProuteVNCrouteVNCDirectrouteVNCDirectRHrouteBGPDirectrouteBGPDirectEXTrouteBABELrouteSHARProutePBRrouteBFDrouteOpenfabricrouteVRRProuteNHGrouteAllrouteMax" +const _RouteType_name = "routeSystemrouteKernelrouteConnectRouteStaticrouteRIProuteRIPNGrouteOSPFrouteOSPF6routeISISRouteBGProutePIMrouteEIGRProuteNHRProuteHSLSrouteOLSRrouteTABLErouteLDProuteVNCrouteVNCDirectrouteVNCDirectRHrouteBGPDirectrouteBGPDirectEXTrouteBABELrouteSHARProutePBRrouteBFDrouteOpenfabricrouteVRRProuteNHGrouteSRTErouteAllrouteMax" -var _RouteType_index = [...]uint16{0, 11, 22, 34, 45, 53, 63, 72, 82, 91, 99, 107, 117, 126, 135, 144, 154, 162, 170, 184, 200, 214, 231, 241, 251, 259, 267, 282, 291, 299, 307, 315} +var _RouteType_index = [...]uint16{0, 11, 22, 34, 45, 53, 63, 72, 82, 91, 99, 107, 117, 126, 135, 144, 154, 162, 170, 184, 200, 214, 231, 241, 251, 259, 267, 282, 291, 299, 308, 316, 324} func (i RouteType) String() string { if i >= RouteType(len(_RouteType_index)-1) { diff --git a/internal/pkg/zebra/zapi.go b/internal/pkg/zebra/zapi.go index 32e9d8d2..9cc78107 100644 --- a/internal/pkg/zebra/zapi.go +++ b/internal/pkg/zebra/zapi.go @@ -115,8 +115,8 @@ const ( const softwareNameMinimumVersion uint8 = 5 var allowableSoftwareNameArrays = [][]string{ - {"frr4", "cumulus"}, //version:5 - {"frr7.2", "frr7", "frr6"}, //version:6 + {"frr4", "cumulus"}, //version:5 + {"frr7.3", "frr7.2", "frr7", "frr6"}, //version:6 } // IsAllowableSoftwareName returns bool from version number and softwareName @@ -317,71 +317,83 @@ const ( _interfaceLinkParams _mplsLabelsAdd _mplsLabelsDelete - _mplsLabelsReplace // add in frr7.3 + _mplsLabelsReplace // add in frr7.3 + _srPolicySet // add in frr7.5 + _srPolicyDelete // 50 // add in frr7.5 + _srPolicyNotifyStatus // add in frr7.5 _ipmrRouteStats - labelManagerConnect // 50 + labelManagerConnect // 53 labelManagerConnectAsync // add in frr5 getLabelChunk releaseLabelChunk _fecRegister _fecUnregister _fecUpdate - _advertiseDefaultGW - _advertiseSviMACIP // add in frr7.1 + _advertiseDefaultGW // 60 + _advertiseSviMACIP // add in frr7.1 _advertiseSubnet - _advertiseAllVNI // 60 + _advertiseAllVNI // 63 _localESAdd - _localESDel - _vniAdd + _localESDel // 65 + _remoteESVTEPAdd // add in frr7.5 + _remoteESVTEPDel // add in frr7.5 + _localESEVIAdd // add in frr7.5 + _localESEVIDel // add in frr7.5 + _vniAdd // 70 _vniDel _l3VNIAdd _l3VNIDel _remoteVTEPAdd _remoteVTEPDel _macIPAdd - _macIPDel // 70 + _macIPDel // 77 _ipPrefixRouteAdd _ipPrefixRouteDel - _remoteMACIPAdd + _remoteMACIPAdd // 80 _remoteMACIPDel _duplicateAddrDetection _pwAdd _pwDelete _pwSet _pwUnset - _pwStatusUpdate // 80 + _pwStatusUpdate // 87 _ruleAdd _ruleDelete - _ruleNotifyOwner + _ruleNotifyOwner // 90 _tableManagerConnect _getTableChunk _releaseTableChunk _ipSetCreate _ipSetDestroy _ipSetEntryAdd - _ipSetEntryDelete // 90 + _ipSetEntryDelete // 97 _ipSetNotifyOwner _ipSetEntryNotifyOwner - _ipTableAdd + _ipTableAdd // 100 _ipTableDelete _ipTableNotifyOwner _vxlanFloodControl _vxlanSgAdd _vxlanSgDel _vxlanSgReplay - _mlagProcessUp // 100 // add in frr7.3 + _mlagProcessUp // 107 // add in frr7.3 _mlagProcessDown // add in frr7.3 _mlagClientRegister // add in frr7.3 - _mlagClientUnregister // add in frr7.3 + _mlagClientUnregister // 110 // add in frr7.3 _mlagClientForwardMsg // add in frr7.3 zebraError // add in frr7.3 _clientCapabilities // add in frr7.4 + _opaqueMessage // add in frr7.5 + _opaqueRegister // add in frr7.5 + _opaqueUnregister // add in frr7.5 + _neighDiscover // 117 // add in frr7.5 // BackwardIPv6RouteAdd is referred in zclient_test BackwardIPv6RouteAdd // quagga, frr3, frr4, frr5 // BackwardIPv6RouteDelete is referred in zclient_test BackwardIPv6RouteDelete // quagga, frr3, frr4, frr5 ) const ( + zapi6Frr7dot3MinDifferentAPIType APIType = 49 //frr7.3(zapi6) zapi6Frr7dot2MinDifferentAPIType APIType = 48 //frr7.2(zapi6) zapi5ClMinDifferentAPIType APIType = 19 //cumuluslinux3.7.7, zebra4.0+cl3u13(zapi5) zapi5MinDifferentAPIType APIType = 7 //frr4&5(zapi5), frr6&7.0&7.1(zapi6) @@ -399,15 +411,31 @@ func minDifferentAPIType(version uint8, softwareName string) APIType { } else if version == 5 || (version == 6 && (softwareName == "frr6" || softwareName == "frr7")) { return zapi5MinDifferentAPIType + } else if version == 6 && softwareName == "frr7.2" { + return zapi6Frr7dot2MinDifferentAPIType } - return zapi6Frr7dot2MinDifferentAPIType + return zapi6Frr7dot3MinDifferentAPIType } const ( - zapi6Frr7dot2LabelManagerConnect APIType = 49 // difference from frr7.3 - zapi6Frr7dot2LabelManagerConnectAsync APIType = 50 // difference from frr7.3 - zapi6Frr7dot2GetLabelChunk APIType = 51 // difference from frr7.3 - zapi6Frr7dot2ReleaseLabelChunk APIType = 52 // difference from frr7.3 + zapi6Frr7dot3LabelManagerConnect APIType = 50 // difference from frr7.5 + zapi6Frr7dot3LabelManagerConnectAsync APIType = 51 // difference from frr7.5 + zapi6Frr7dot3GetLabelChunk APIType = 52 // difference from frr7.5 + zapi6Frr7dot3ReleaseLabelChunk APIType = 53 // difference from frr7.5 +) + +var apiTypeZapi6Frr7dot3Map = map[APIType]APIType{ + labelManagerConnect: zapi6Frr7dot3LabelManagerConnect, + labelManagerConnectAsync: zapi6Frr7dot3LabelManagerConnectAsync, + getLabelChunk: zapi6Frr7dot3GetLabelChunk, + releaseLabelChunk: zapi6Frr7dot3ReleaseLabelChunk, +} + +const ( + zapi6Frr7dot2LabelManagerConnect APIType = 49 // difference from frr7.5 + zapi6Frr7dot2LabelManagerConnectAsync APIType = 50 // difference from frr7.5 + zapi6Frr7dot2GetLabelChunk APIType = 51 // difference from frr7.5 + zapi6Frr7dot2ReleaseLabelChunk APIType = 52 // difference from frr7.5 ) var apiTypeZapi6Frr7dot2Map = map[APIType]APIType{ @@ -656,7 +684,9 @@ func (t APIType) doesNeedConversion(version uint8, softwareName string) bool { return true } func apiTypeMap(version uint8, softwareName string) map[APIType]APIType { - if version == 6 && softwareName == "frr7" { + if version == 6 && softwareName == "frr7.2" { + return apiTypeZapi6Frr7dot2Map + } else if version == 6 && softwareName == "frr7" { return apiTypeZapi6Frr7Map } else if version == 6 && softwareName == "frr6" { return apiTypeZapi6Frr6Map @@ -672,7 +702,7 @@ func apiTypeMap(version uint8, softwareName string) map[APIType]APIType { } else if version < 4 { return apiTypeZapi3Map } - return apiTypeZapi6Frr7dot2Map + return apiTypeZapi6Frr7dot3Map } // ToEach is referred in zclient_test @@ -762,6 +792,7 @@ const ( routeOpenfabric // FRRRouting version 7 (Zapi6) adds. routeVRRP // FRRRouting version 7.2 (Zapi6) adds. routeNHG // FRRRouting version 7.3 (Zapi6) adds. + routeSRTE // FRRRouting version 7.5 (Zapi6) adds. routeAll routeMax // max value for error ) @@ -771,6 +802,7 @@ const ( zapi6Frr6RouteAll RouteType = 26 zapi6Frr7RouteAll RouteType = 27 zapi6Frr7dot2RouteAll RouteType = 28 + zapi6Frr7dot3RouteAll RouteType = 29 ) func getRouteAll(version uint8, softwareName string) RouteType { @@ -786,6 +818,8 @@ func getRouteAll(version uint8, softwareName string) RouteType { return zapi6Frr7RouteAll } else if softwareName == "frr7.2" { return zapi6Frr7dot2RouteAll + } else if softwareName == "frr7.3" { + return zapi6Frr7dot3RouteAll } } return routeAll @@ -881,6 +915,7 @@ var routeTypeValueMap = map[string]RouteType{ "openfabric": routeOpenfabric, // add in frr7.0(zapi6) "vrrp": routeVRRP, // add in frr7.2(zapi6) "nhg": routeNHG, // add in frr7.3(zapi6) + "srte": routeSRTE, // add in frr7.5(zapi6) "wildcard": routeAll, } @@ -918,7 +953,7 @@ func ipFromFamily(family uint8, buf []byte) net.IP { } // MessageFlag is the type of API Message Flags. -type MessageFlag uint8 +type MessageFlag uint32 // MESSAGE_FLAG is 32bit after frr7.5, 8bit before frr7.4 const ( // For FRRouting version 4, 5 and 6 (ZAPI version 5 and 6). // MessageNexthop is referred in zclient @@ -932,9 +967,10 @@ 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 - messageBackupNexthops MessageFlag = 0x40 // added in frr7.4 - 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 + messageSRTE MessageFlag = 0x100 // introduced in frr7.5 ) const ( // For FRRouting. @@ -993,7 +1029,7 @@ func (f MessageFlag) string(version uint8, softwareName string) string { if version > 3 && f&messageSRCPFX.ToEach(version) > 0 { ss = append(ss, "SRCPFX") } - if version == 6 && softwareName == "" && f&messageBackupNexthops > 0 { // added in frr7.4 + if version == 6 && softwareName == "" && f&messageBackupNexthops > 0 { // added in frr7.4, frr7.5 ss = append(ss, "BACKUP_NEXTHOPS") } else if version > 4 && f&MessageLabel > 0 { ss = append(ss, "LABEL") @@ -1001,6 +1037,9 @@ func (f MessageFlag) string(version uint8, softwareName string) string { if version > 5 && f&messageTableID > 0 { ss = append(ss, "TABLEID") } + if version == 6 && softwareName == "" && f&messageSRTE > 0 { // added in frr7.5 + ss = append(ss, "SRTE") + } return strings.Join(ss, "|") } @@ -1407,7 +1446,16 @@ func (c *Client) SendHello() error { // SendRouterIDAdd sends ROUTER_ID_ADD message to zebra daemon. func (c *Client) SendRouterIDAdd() error { - return c.sendCommand(routerIDAdd, DefaultVrf, nil) + bodies := make([]*routerIDUpdateBody, 0) + for _, afi := range []afi{afiIP, afiIP6} { + bodies = append(bodies, &routerIDUpdateBody{ + afi: afi, + }) + } + for _, body := range bodies { + c.sendCommand(routerIDAdd, DefaultVrf, body) + } + return nil } // SendInterfaceAdd sends INTERFACE_ADD message to zebra daemon. @@ -1417,7 +1465,6 @@ func (c *Client) SendInterfaceAdd() error { // SendRedistribute sends REDISTRIBUTE message to zebra daemon. func (c *Client) SendRedistribute(t RouteType, vrfID uint32) error { - if c.redistDefault != t { bodies := make([]*redistributeBody, 0) if c.Version <= 3 { @@ -1435,7 +1482,7 @@ func (c *Client) SendRedistribute(t RouteType, vrfID uint32) error { } for _, body := range bodies { - return c.sendCommand(redistributeAdd, vrfID, body) + c.sendCommand(redistributeAdd, vrfID, body) } } return nil @@ -1634,16 +1681,22 @@ func (b *unknownBody) string(version uint8, softwareName string) string { type helloBody struct { redistDefault RouteType instance uint16 + sessionID uint32 // frr7.4, frr7.5 receiveNotify uint8 + synchronous uint8 // frr7.4, frr7.5 } // Ref: zread_hello in zebra/zserv.c of Quagga1.2&FRR3 (ZAPI3&4) // Ref: zread_hello in zebra/zapi_msg.c of FRR5 (ZAPI5) func (b *helloBody) decodeFromBytes(data []byte, version uint8, softwareName string) error { b.redistDefault = RouteType(data[0]) - if version >= 4 { + if version > 3 { //frr b.instance = binary.BigEndian.Uint16(data[1:3]) - if version >= 5 { + if version == 6 && softwareName == "" { // frr7.5 + b.sessionID = binary.BigEndian.Uint32(data[3:7]) + b.receiveNotify = data[7] + b.synchronous = data[8] + } else if version > 4 { b.receiveNotify = data[3] } } @@ -1656,14 +1709,20 @@ func (b *helloBody) serialize(version uint8, softwareName string) ([]byte, error return []byte{uint8(b.redistDefault)}, nil } var buf []byte - if version == 4 { - buf = make([]byte, 3) + if version == 6 && softwareName == "" { // frr7.5 + buf = make([]byte, 9) } else if version > 4 { buf = make([]byte, 4) + } else if version == 4 { + buf = make([]byte, 3) } buf[0] = uint8(b.redistDefault) binary.BigEndian.PutUint16(buf[1:3], b.instance) - if version > 4 { + if version == 6 && softwareName == "" { // frr7.5 + binary.BigEndian.PutUint32(buf[3:7], b.sessionID) + buf[7] = b.receiveNotify + buf[8] = b.synchronous + } else if version > 4 { buf[3] = b.receiveNotify } return buf, nil @@ -1870,6 +1929,7 @@ func (b *interfaceAddressUpdateBody) string(version uint8, softwareName string) type routerIDUpdateBody struct { length uint8 prefix net.IP + afi afi } // Ref: zebra_router_id_update_read in lib/zclient.c of Quagga1.2&FRR3&FRR5 (ZAPI3&4&5) @@ -1885,7 +1945,12 @@ func (b *routerIDUpdateBody) decodeFromBytes(data []byte, version uint8, softwar return nil } +// Ref: zclient_send_router_id_update in lib/zclient.c of FRR7.5 func (b *routerIDUpdateBody) serialize(version uint8, softwareName string) ([]byte, error) { + if version == 6 && softwareName == "" { + //stream_putw(s, afi); + return []byte{0x00, uint8(b.afi)}, nil + } return []byte{}, nil } @@ -1894,9 +1959,11 @@ func (b *routerIDUpdateBody) string(version uint8, softwareName string) string { } const ( - 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 + zapiNexthopFlagOnlink uint8 = 0x01 // frr7.1, 7.2, 7.3, 7.4, 7.5 + zapiNexthopFlagLabel uint8 = 0x02 // frr7.3, 7.4, 7.5 + zapiNexthopFlagWeight uint8 = 0x04 // frr7.3, 7.4, 7.5 + zapiNexthopFlagHasBackup uint8 = 0x08 // frr7.4, 7.5 + ) // Flag for nexthop processing. It is gobgp's internal flag. @@ -1921,7 +1988,7 @@ func nexthopProcessFlagForIPRouteBody(version uint8, softwareName string, isDeco processFlag := (nexthopHasVrfID | nexthopHasType) // frr4, 5, 6, 7 if version == 6 { switch softwareName { - case "": + case "", "frr7.3": processFlag |= (nexthopHasFlag | nexthopProcessIPToIPIFindex) case "frr7.2", "frr7.0": processFlag |= nexthopHasOnlink @@ -1942,6 +2009,9 @@ type Nexthop struct { MplsLabels []uint32 weight uint32 rmac [6]byte + srteColor uint32 + backupNum uint8 + backupIndex []uint8 } func (n Nexthop) string() string { @@ -1994,6 +2064,9 @@ func (n Nexthop) encode(version uint8, softwareName string, processFlag nexthopP if n.weight > 0 { n.flags |= zapiNexthopFlagWeight } + if n.backupNum > 0 { + n.flags |= zapiNexthopFlagHasBackup + } } if processFlag&nexthopHasFlag > 0 || processFlag&nexthopHasOnlink > 0 { // frr7.1, 7.2 has onlink, 7.3 has flag @@ -2051,6 +2124,20 @@ func (n Nexthop) encode(version uint8, softwareName string, processFlag nexthopP //frr: stream_put(s, &(api_nh->rmac), sizeof(struct ethaddr)); buf = append(buf, n.rmac[:]...) } + // added in frr7.5 (Color for Segment Routing TE.) + if message&messageSRTE > 0 && (version == 6 && softwareName == "") { + tmpbuf := make([]byte, 4) + binary.BigEndian.PutUint32(tmpbuf, uint32(n.srteColor)) + buf = append(buf, tmpbuf...) //frr: stream_putl(s, api_nh->srte_color); + } + if n.flags&zapiNexthopFlagHasBackup > 0 { + tmpbuf := make([]byte, 1+1*n.backupNum) + tmpbuf[0] = n.backupNum //frr: stream_putc(s, api_nh->backup_num); + for i := uint8(0); i < n.backupNum; i++ { + tmpbuf[i+1] = n.backupIndex[i] + } + buf = append(buf, tmpbuf...) + } return buf } @@ -2109,7 +2196,10 @@ func (n *Nexthop) decode(data []byte, version uint8, softwareName string, family n.blackholeType = data[offset] //frr: STREAM_GETC(s, api_nh->bh_type); offset++ } - 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"))) { n.LabelNum = uint8(data[offset]) //frr: STREAM_GETC(s, api_nh->label_num); offset++ if n.LabelNum > maxMplsLabel { @@ -2136,6 +2226,25 @@ func (n *Nexthop) decode(data []byte, version uint8, softwareName string, family copy(n.rmac[0:], data[offset:offset+6]) offset += 6 } + // added in frr7.5 (Color for Segment Routing TE.) + if message&messageSRTE > 0 && (version == 6 && softwareName == "") { + //STREAM_GETL(s, api_nh->srte_color); + n.srteColor = binary.BigEndian.Uint32(data[offset:]) + offset += 4 + } + // added in frr7.4 (Index of backup nexthop) + if n.flags&zapiNexthopFlagHasBackup > 0 { + n.backupNum = data[offset] //frr: STREAM_GETC(s, api_nh->backup_num); + offset++ + if n.backupNum > 0 { + n.backupIndex = make([]uint8, n.backupNum) + for i := uint8(0); i < n.backupNum; i++ { + //frr STREAM_GETC(s, api_nh->backup_idx[i]); + n.backupIndex[i] = data[offset] + offset++ + } + } + } return offset, nil } @@ -2186,6 +2295,7 @@ type IPRouteBody struct { Mtu uint32 tag uint32 tableID uint32 + srteColor uint32 API APIType // API is referred in zclient_test } @@ -2261,13 +2371,25 @@ func (b *IPRouteBody) IsWithdraw(version uint8, softwareName string) bool { func (b *IPRouteBody) serialize(version uint8, softwareName string) ([]byte, error) { var buf []byte numNexthop := len(b.Nexthops) - if version <= 3 { - buf = make([]byte, 5) - } else if version == 4 { - buf = make([]byte, 10) - } else { // version >= 5 - buf = make([]byte, 9) //type(1)+instance(2)+flags(4)+message(1)+safi(1) + + bufInitSize := 12 + switch version { + case 2, 3: + bufInitSize = 5 + case 4: + bufInitSize = 10 + case 5: + bufInitSize = 9 //type(1)+instance(2)+flags(4)+message(1)+safi(1) + case 6: + switch softwareName { + case "frr6", "frr7", "frr7.2", "frr7.3": + bufInitSize = 9 //type(1)+instance(2)+flags(4)+message(1)+safi(1) + default: + bufInitSize = 12 //type(1)+instance(2)+flags(4)+message(4)+safi(1) + } } + buf = make([]byte, bufInitSize) + buf[0] = uint8(b.Type.toEach(version, softwareName)) //frr: stream_putc(s, api->type); if version < 4 { buf[1] = uint8(b.Flags) @@ -2278,27 +2400,33 @@ func (b *IPRouteBody) serialize(version uint8, softwareName string) ([]byte, err 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) + if version == 6 && softwareName == "" { + //frr7.5: stream_putl(s, api->message); + binary.BigEndian.PutUint32(buf[7:11], uint32(b.Message)) + buf[11] = uint8(b.Safi) + } else { + //before frr7.4: stream_putc(s, api->message); + buf[7] = uint8(b.Message) + if version > 4 { + //frr: stream_putc(s, api->safi); + buf[8] = uint8(b.Safi) + } else { // version 2,3 and 4 (quagga, frr3) + binary.BigEndian.PutUint16(buf[8:10], uint16(b.Safi)) } - //frr: stream_putc(s, api->prefix.family); - buf = append(buf, b.Prefix.Family) } } + // 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 version > 4 { // version 5, 6 (after frr4) + 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) //frr: stream_putc(s, api->prefix.prefixlen); //frr: stream_write(s, (uint8_t *)&api->prefix.u.prefix, psize); @@ -2329,7 +2457,8 @@ func (b *IPRouteBody) serialize(version uint8, softwareName string) ([]byte, err buf = append(buf, nexthop.encode(version, softwareName, processFlag, b.Message, b.Flags)...) } } - if b.Message&messageBackupNexthops > 0 { // added in frr7.4 + // MESSAGE_BACKUP_NEXTHOPS is added in frr7.4 + if version == 6 && softwareName == "" && b.Message&messageBackupNexthops > 0 { tmpbuf := make([]byte, 2) binary.BigEndian.PutUint16(tmpbuf, uint16(len(b.backupNexthops))) buf = append(buf, tmpbuf...) //frr: stream_putw(s, api->nexthop_num); @@ -2428,17 +2557,23 @@ func (b *IPRouteBody) decodeFromBytes(data []byte, version uint8, softwareName s b.Flags = Flag(binary.BigEndian.Uint32(data[3:7])) data = data[7:] } - - b.Message = MessageFlag(data[0]) //frr: STREAM_GETC(s, api->message); + if version == 6 && softwareName == "" { + //frr7.5: STREAM_GETL(s, api->message); + b.Message = MessageFlag(binary.BigEndian.Uint32(data[0:4])) + data = data[4:] + } else { + b.Message = MessageFlag(data[0]) //frr: STREAM_GETC(s, api->message); + data = data[1:] + } 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]) //frr: STREAM_GETC(s, api->safi); + b.Safi = Safi(data[0]) //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:] + data = data[1:] // zapi version 5 only if version == 5 && b.Flags&flagEvpnRoute.ToEach(version, softwareName) > 0 { @@ -2448,6 +2583,7 @@ func (b *IPRouteBody) decodeFromBytes(data []byte, version uint8, softwareName s } b.Prefix.Family = data[0] //frr: STREAM_GETC(s, api->prefix.family); + data = data[1:] } addrByteLen, err := addressByteLength(b.Prefix.Family) @@ -2457,11 +2593,11 @@ func (b *IPRouteBody) decodeFromBytes(data []byte, version uint8, softwareName s addrBitLen := uint8(addrByteLen * 8) - b.Prefix.PrefixLen = data[1] //frr: STREAM_GETC(s, api->prefix.prefixlen); + b.Prefix.PrefixLen = data[0] //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) } - data = data[2:] + data = data[1:] pos := 0 rest := len(data) @@ -2474,6 +2610,7 @@ func (b *IPRouteBody) decodeFromBytes(data []byte, version uint8, softwareName s copy(buf, data[pos:pos+byteLen]) b.Prefix.Prefix = ipFromFamily(b.Prefix.Family, buf) pos += byteLen + if version > 3 && b.Message&messageSRCPFX.ToEach(version) > 0 { if pos+1 > rest { return fmt.Errorf("MessageSRCPFX message length invalid pos:%d rest:%d", pos, rest) @@ -2496,21 +2633,28 @@ func (b *IPRouteBody) decodeFromBytes(data []byte, version uint8, softwareName s } b.Nexthops = []Nexthop{} - offset, err := b.decodeMessageNexthopFromBytes(data[pos:], version, softwareName, false) - if err != nil { - return err + if b.Message&MessageNexthop.ToEach(version) > 0 { + offset, err := b.decodeMessageNexthopFromBytes(data[pos:], version, softwareName, false) + if err != nil { + return err + } + pos += offset } - 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 + if b.Message&messageBackupNexthops.ToEach(version) > 0 { + offset, err := b.decodeMessageNexthopFromBytes(data[pos:], version, softwareName, true) + if err != nil { + return err + } + pos += offset } - 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 { // version 4, 3, 2 if pos+1 > rest { return fmt.Errorf("MessageIFIndex message length invalid pos:%d rest:%d", pos, rest) @@ -2792,17 +2936,27 @@ func (b *NexthopRegisterBody) string(version uint8, softwareName string) string // NexthopUpdateBody uses same data structure as IPRoute (zapi_route) after frr4 (Zapi5) type NexthopUpdateBody IPRouteBody -// Ref: send_client in zebra/zebra_rnh.c of Quagga1.2&FRR3&FRR5(ZAPI3&4$5) +// Ref: send_client in zebra/zebra_rnh.c of Quagga1.2&FRR3&FRR5(ZAPI3&4$5) and befre FRR7.4 +// Ref: zebra_send_rnh_update zebra/zebra_rnh.c of FRR7.5 func (b *NexthopUpdateBody) serialize(version uint8, softwareName string) ([]byte, error) { + var buf []byte + offset := 0 + if version == 6 && softwareName == "" { // after frr7.5 + buf = make([]byte, 7) + binary.BigEndian.PutUint32(buf, uint32(b.Message)) + offset += 4 + } else { // before frr7.4 + buf = make([]byte, 3) + } + // Address Family (2 bytes) - buf := make([]byte, 3) - binary.BigEndian.PutUint16(buf, uint16(b.Prefix.Family)) + binary.BigEndian.PutUint16(buf[offset:], uint16(b.Prefix.Family)) addrByteLen, err := addressByteLength(b.Prefix.Family) if err != nil { return nil, err } - buf[2] = byte(addrByteLen * 8) + buf[offset+2] = byte(addrByteLen * 8) // Prefix Length (1 byte) + Prefix (variable) switch b.Prefix.Family { case syscall.AF_INET: @@ -2812,6 +2966,11 @@ func (b *NexthopUpdateBody) serialize(version uint8, softwareName string) ([]byt default: return nil, fmt.Errorf("invalid address family: %d", b.Prefix.Family) } + if b.Message&messageSRTE > 0 { // frr 7.5 + tmpbuf := make([]byte, 4) + binary.BigEndian.PutUint32(tmpbuf, b.srteColor) + buf = append(buf, tmpbuf...) + } if version >= 5 { // Type (1 byte) (if version>=5) // instance (2 bytes) (if version>=5) @@ -2837,6 +2996,11 @@ func (b *NexthopUpdateBody) serialize(version uint8, softwareName string) ([]byt // Ref: bgp_parse_nexthop_update in bgpd/bgp_nht.c of Quagga1.2&FRR3 (ZAPI3&4) // Ref: zapi_nexthop_update_decode in lib/zclient.c of FRR5.x (ZAPI5) func (b *NexthopUpdateBody) decodeFromBytes(data []byte, version uint8, softwareName string) error { + if version == 6 && softwareName == "" { // frr7.5 + //frr7.5: STREAM_GETL(s, nhr->message); + b.Message = MessageFlag(binary.BigEndian.Uint32(data[0:4])) + data = data[4:] + } // Address Family (2 bytes) prefixFamily := binary.BigEndian.Uint16(data[0:2]) b.Prefix.Family = uint8(prefixFamily) @@ -2851,6 +3015,11 @@ func (b *NexthopUpdateBody) decodeFromBytes(data []byte, version uint8, software b.Prefix.Prefix = ipFromFamily(b.Prefix.Family, data[offset:offset+addrByteLen]) offset += addrByteLen + if b.Message&messageSRTE > 0 { // frr 7.5 + b.srteColor = binary.BigEndian.Uint32(data[offset : offset+4]) + offset += 4 + } + if version > 4 { b.Type = RouteType(data[offset]) b.instance = binary.BigEndian.Uint16(data[offset+1 : offset+3]) @@ -2876,7 +3045,7 @@ func (b *NexthopUpdateBody) decodeFromBytes(data []byte, version uint8, software processFlag := nexthopProcessFlag(nexthopHasType) if version == 6 { switch softwareName { - case "": + case "", "frr7.3": processFlag |= (nexthopHasVrfID | nexthopHasFlag | nexthopProcessIPToIPIFindex) case "frr7.0", "frr7.2": processFlag |= (nexthopHasVrfID | nexthopProcessIPToIPIFindex) @@ -2885,20 +3054,20 @@ func (b *NexthopUpdateBody) decodeFromBytes(data []byte, version uint8, software } } else if version == 5 { switch softwareName { - case "frr5", "": + case "": processFlag |= nexthopProcessIPToIPIFindex } } else if version < 4 { // quagga processFlag |= nexthopProcessIFnameToIFindex } - message := MessageFlag(0) + // after frr7.3, MessageLabel is deleted if (version == 6 && !(softwareName == "frr7.3" || softwareName == "")) || - (version == 5 && (softwareName == "frr5" || softwareName == "")) { - message |= MessageLabel + (version == 5 && softwareName == "") { + b.Message |= MessageLabel } - nexthopsByteLen, err := decodeNexthops(&b.Nexthops, data[offset:], version, softwareName, b.Prefix.Family, numNexthop, processFlag, message, Flag(0), nexthopType(0)) + nexthopsByteLen, err := decodeNexthops(&b.Nexthops, data[offset:], version, softwareName, b.Prefix.Family, numNexthop, processFlag, b.Message, Flag(0), nexthopType(0)) if err != nil { return err } diff --git a/internal/pkg/zebra/zapi_test.go b/internal/pkg/zebra/zapi_test.go index 61ccf94b..b110b4ff 100644 --- a/internal/pkg/zebra/zapi_test.go +++ b/internal/pkg/zebra/zapi_test.go @@ -211,13 +211,13 @@ func Test_routerIDUpdateBody(t *testing.T) { func Test_IPRouteBody_IPv4(t *testing.T) { assert := assert.New(t) - size := map[uint8]uint8{2: 26, 3: 26, 4: 31, 5: 38, 6: 39} + size := map[uint8]uint8{2: 26, 3: 26, 4: 31, 5: 38, 6: 42} command := map[uint8]APIType{ 2: zapi3IPv4RouteAdd, 3: zapi3IPv4RouteAdd, 4: zapi4IPv4RouteAdd, 5: zapi6Frr7RouteAdd, - 6: zapi6Frr7RouteAdd, + 6: RouteAdd, } routeType := routeConnect message := map[uint8]MessageFlag{ @@ -237,7 +237,6 @@ func Test_IPRouteBody_IPv4(t *testing.T) { for v := MinZapiVer; v <= MaxZapiVer; v++ { //decodeFromBytes IPV4_ROUTE buf := make([]byte, size[v]) - //buf[0] = byte(routeType[v]) buf[0] = byte(routeType) pos := 1 switch v { @@ -250,8 +249,13 @@ func Test_IPRouteBody_IPv4(t *testing.T) { binary.BigEndian.PutUint32(buf[pos:], uint32(FlagSelected.ToEach(v, ""))) pos += 4 } - buf[pos] = byte(message[v]) - pos++ + if v == 6 { + binary.BigEndian.PutUint32(buf[pos:], uint32(message[v])) // frr7.5: 32bit + pos += 4 + } else { + buf[pos] = uint8(message[v]) // before frr7.4: 8bit + pos++ + } if v > 4 { buf[pos] = byte(SafiUnicast) //SAFI pos++ @@ -318,10 +322,14 @@ func Test_IPRouteBody_IPv4(t *testing.T) { case 2, 3: assert.Equal([]byte{0x2, 0x10, byte(message[v])}, buf[0:3]) pos = 3 - case 4, 5, 6: + case 4, 5: tmpFlag := byte(0xff & FlagSelected.ToEach(v, "")) assert.Equal([]byte{0x2, 0x00, 0x00, 0x00, 0x00, 0x00, tmpFlag, byte(message[v])}, buf[0:8]) pos = 8 + case 6: // frr 7.5: MessageFlag: 32bit + tmpFlag := byte(0xff & FlagSelected.ToEach(v, "")) + assert.Equal([]byte{0x2, 0x00, 0x00, 0x00, 0x00, 0x00, tmpFlag, 0x00, 0x00, 0x00, byte(message[v])}, buf[0:11]) + pos = 11 } switch v { case 2, 3, 4: @@ -334,6 +342,7 @@ func Test_IPRouteBody_IPv4(t *testing.T) { pos++ } + assert.Equal(byte(24), buf[pos]) pos++ ip = net.ParseIP("192.168.100.0").To4() @@ -374,7 +383,6 @@ func Test_IPRouteBody_IPv4(t *testing.T) { // length invalid buf = make([]byte, size[v]-8) - //buf[0] = byte(routeType[v]) buf[0] = byte(routeConnect) pos = 1 switch v { @@ -387,8 +395,14 @@ func Test_IPRouteBody_IPv4(t *testing.T) { binary.BigEndian.PutUint32(buf[pos:], uint32(FlagSelected.ToEach(v, ""))) pos += 4 } - buf[pos] = byte(message[v]) - pos++ + if v == 6 { + binary.BigEndian.PutUint32(buf[pos:], uint32(message[v])) // frr7.5: 32bit + pos += 4 + } else { + buf[pos] = uint8(message[v]) // before frr7.4: 8bit + pos++ + } + if v > 4 { buf[pos] = byte(SafiUnicast) //SAFI pos++ @@ -458,8 +472,15 @@ func Test_IPRouteBody_IPv4(t *testing.T) { binary.BigEndian.PutUint32(buf[pos:], uint32(FlagSelected.ToEach(v, ""))) pos += 4 } - buf[pos] = byte(messageWithoutNexthop[v]) - pos++ + + if v == 6 { + binary.BigEndian.PutUint32(buf[pos:], uint32(messageWithoutNexthop[v])) // frr7.5: 32bit + pos += 4 + } else { + buf[pos] = byte(messageWithoutNexthop[v]) // before frr7.4: 8bit + pos++ + } + if v > 4 { buf[pos] = byte(SafiUnicast) //SAFI pos++ @@ -483,7 +504,7 @@ func Test_IPRouteBody_IPv4(t *testing.T) { func Test_IPRouteBody_IPv6(t *testing.T) { assert := assert.New(t) - size := map[uint8]uint8{2: 43, 3: 43, 4: 48, 5: 55, 6: 56} + size := map[uint8]uint8{2: 43, 3: 43, 4: 48, 5: 55, 6: 59} command := map[uint8]APIType{ 2: zapi3IPv6RouteAdd, 3: zapi3IPv6RouteAdd, @@ -528,8 +549,15 @@ func Test_IPRouteBody_IPv6(t *testing.T) { binary.BigEndian.PutUint32(buf[pos:], uint32(FlagSelected.ToEach(v, ""))) pos += 4 } - buf[pos] = byte(message[v]) - pos++ + + if v == 6 { + binary.BigEndian.PutUint32(buf[pos:], uint32(message[v])) // frr7.5: 32bit + pos += 4 + } else { + buf[pos] = uint8(message[v]) // before frr7.4: 8bit + pos++ + } + if v > 4 { buf[pos] = byte(SafiUnicast) //SAFI pos++ @@ -596,10 +624,14 @@ func Test_IPRouteBody_IPv6(t *testing.T) { case 2, 3: assert.Equal([]byte{0x2, 0x10, byte(message[v])}, buf[0:3]) pos = 3 - case 4, 5, 6: + case 4, 5: tmpFlag := byte(0xff & FlagSelected.ToEach(v, "")) assert.Equal([]byte{0x2, 0x00, 0x00, 0x00, 0x00, 0x00, tmpFlag, byte(message[v])}, buf[0:8]) pos = 8 + case 6: // frr 7.5: MessageFlag: 32bit + tmpFlag := byte(0xff & FlagSelected.ToEach(v, "")) + assert.Equal([]byte{0x2, 0x00, 0x00, 0x00, 0x00, 0x00, tmpFlag, 0x00, 0x00, 0x00, byte(message[v])}, buf[0:11]) + pos = 11 } switch v { case 2, 3, 4: @@ -665,8 +697,15 @@ func Test_IPRouteBody_IPv6(t *testing.T) { binary.BigEndian.PutUint32(buf[pos:], uint32(FlagSelected.ToEach(v, ""))) pos += 4 } - buf[pos] = byte(message[v]) - pos++ + + if v == 6 { + binary.BigEndian.PutUint32(buf[pos:], uint32(message[v])) // frr7.5: 32bit + pos += 4 + } else { + buf[pos] = uint8(message[v]) // before frr7.4: 8bit + pos++ + } + if v > 4 { buf[pos] = byte(SafiUnicast) //SAFI pos++ @@ -738,8 +777,15 @@ func Test_IPRouteBody_IPv6(t *testing.T) { binary.BigEndian.PutUint32(buf[pos:], uint32(FlagSelected.ToEach(v, ""))) pos += 4 } - buf[pos] = byte(messageWithoutNexthop[v]) - pos++ + + if v == 6 { + binary.BigEndian.PutUint32(buf[pos:], uint32(messageWithoutNexthop[v])) // frr7.5: 32bit + pos += 4 + } else { + buf[pos] = byte(messageWithoutNexthop[v]) // before frr7.4: 8bit + pos++ + } + if v > 4 { buf[pos] = byte(SafiUnicast) //SAFI pos++ @@ -935,7 +981,7 @@ func Test_NexthopRegisterBody(t *testing.T) { func Test_NexthopUpdateBody(t *testing.T) { assert := assert.New(t) - size := map[uint8]uint8{2: 21, 3: 21, 4: 22, 5: 26, 6: 30} + size := map[uint8]uint8{2: 21, 3: 21, 4: 22, 5: 26, 6: 34} command := map[uint8]APIType{ 2: zapi3NexthopUpdate, 3: zapi3NexthopUpdate, @@ -954,9 +1000,16 @@ func Test_NexthopUpdateBody(t *testing.T) { for v := MinZapiVer; v <= MaxZapiVer; v++ { // Input binary bufIn := make([]byte, size[v]) + pos := 0 + if v == 6 { // frr7.5 + // message flag + copy(bufIn[pos:pos+4], []byte{0x00, 0x00, 0x00, 0x00}) + pos += 4 + } // afi(2 bytes)=AF_INET, prefix_len(1 byte)=32, prefix(4 bytes)="192.168.1.1" - copy(bufIn[0:7], []byte{0x00, 0x02, 0x20, 0xc0, 0xa8, 0x01, 0x01}) - pos := 7 + copy(bufIn[pos:pos+7], []byte{0x00, 0x02, 0x20, 0xc0, 0xa8, 0x01, 0x01}) + pos += 7 + if v > 4 { // Type(1byte), Instance(2byte) copy(bufIn[pos:pos+3], []byte{byte(routeConnect), 0x00, 0x00}) pos += 3 |