diff options
author | Hitoshi Irino <irino@sfc.wide.ad.jp> | 2020-04-25 22:06:21 +0900 |
---|---|---|
committer | Hitoshi Irino <irino@sfc.wide.ad.jp> | 2020-04-26 07:43:50 +0900 |
commit | cf572bc5fc4647ea675c8a3482d80d181f62c66c (patch) | |
tree | b50bc6a682c801062ffe19a198b05ddc743a84ee | |
parent | f11b9c7afb198dd6bfea9a167f41a62569f24756 (diff) |
Refactoring Zebra and supporting frr7.3
- Change const values to camel case from snake case to make zero golint's warnigns
- Introduce convert functions (toEach, toCommon) between the newest version to older versions
- Merge code about decode nexthop to reduce lines of code
- Add frr7.3 statemet in allowable software for config
- Rename and Update generated file by stringer
26 files changed, 2958 insertions, 3081 deletions
diff --git a/internal/pkg/config/default.go b/internal/pkg/config/default.go index bf8b0791..7727bf78 100644 --- a/internal/pkg/config/default.go +++ b/internal/pkg/config/default.go @@ -422,7 +422,7 @@ func setDefaultConfigValuesWithViper(v *viper.Viper, b *BgpConfigSet) error { } //SoftwareName for Zebra - allowableZebraSoftwareName := []string{"", "quagga", "frr3", "frr4", "frr5", "frr6", "frr7", "frr7.1", "frr7.2", "cumulus"} + 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 { diff --git a/internal/pkg/zebra/afi_string.go b/internal/pkg/zebra/afi_string.go index 6a4278a3..1cda4d15 100644 --- a/internal/pkg/zebra/afi_string.go +++ b/internal/pkg/zebra/afi_string.go @@ -1,17 +1,27 @@ -// Code generated by "stringer -type=AFI"; DO NOT EDIT. +// Code generated by "stringer -type=afi"; DO NOT EDIT. package zebra import "strconv" -const _AFI_name = "AFI_IPAFI_IP6AFI_ETHERAFI_MAX" +func _() { + // An "invalid array index" compiler error signifies that the constant values have changed. + // Re-run the stringer command to generate them again. + var x [1]struct{} + _ = x[afiIP-1] + _ = x[afiIP6-2] + _ = x[afiEther-3] + _ = x[afiMax-4] +} + +const _afi_name = "afiIPafiIP6afiEtherafiMax" -var _AFI_index = [...]uint8{0, 6, 13, 22, 29} +var _afi_index = [...]uint8{0, 5, 11, 19, 25} -func (i AFI) String() string { +func (i afi) String() string { i -= 1 - if i >= AFI(len(_AFI_index)-1) { - return "AFI(" + strconv.FormatInt(int64(i+1), 10) + ")" + if i >= afi(len(_afi_index)-1) { + return "afi(" + strconv.FormatInt(int64(i+1), 10) + ")" } - return _AFI_name[_AFI_index[i]:_AFI_index[i+1]] + return _afi_name[_afi_index[i]:_afi_index[i+1]] } diff --git a/internal/pkg/zebra/api_type_string.go b/internal/pkg/zebra/api_type_string.go deleted file mode 100644 index 2c280533..00000000 --- a/internal/pkg/zebra/api_type_string.go +++ /dev/null @@ -1,16 +0,0 @@ -// Code generated by "stringer -type=API_TYPE"; DO NOT EDIT. - -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_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, 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) { - return "API_TYPE(" + strconv.FormatInt(int64(i), 10) + ")" - } - return _API_TYPE_name[_API_TYPE_index[i]:_API_TYPE_index[i+1]] -} diff --git a/internal/pkg/zebra/apitype_string.go b/internal/pkg/zebra/apitype_string.go new file mode 100644 index 00000000..52e4af81 --- /dev/null +++ b/internal/pkg/zebra/apitype_string.go @@ -0,0 +1,223 @@ +// Code generated by "stringer -type=APIType"; DO NOT EDIT. + +package zebra + +import "strconv" + +func _() { + // An "invalid array index" compiler error signifies that the constant values have changed. + // Re-run the stringer command to generate them again. + var x [1]struct{} + _ = x[interfaceAdd-0] + _ = x[interfaceDelete-1] + _ = x[interfaceAddressAdd-2] + _ = x[interfaceAddressDelete-3] + _ = x[interfaceUp-4] + _ = x[interfaceDown-5] + _ = x[_interfaceSetMaster-6] + _ = x[_interfaceSetProtoDown-7] + _ = x[RouteAdd-8] + _ = x[RouteDelete-9] + _ = x[_routeNotifyOwner-10] + _ = x[redistributeAdd-11] + _ = x[_redistributeDelete-12] + _ = x[_redistributeDefaultAdd-13] + _ = x[_redistributeDefaultDelete-14] + _ = x[routerIDAdd-15] + _ = x[_routerIDDelete-16] + _ = x[routerIDUpdate-17] + _ = x[hello-18] + _ = x[_capabilities-19] + _ = x[nexthopRegister-20] + _ = x[nexthopUnregister-21] + _ = x[nexthopUpdate-22] + _ = x[_interfaceNBRAddressAdd-23] + _ = x[_interfaceNBRAddressDelete-24] + _ = x[_interfaceBFDDestUpdate-25] + _ = x[_importRouteRegister-26] + _ = x[_importRouteUnregister-27] + _ = x[_importCheckUpdate-28] + _ = x[_bfdDestRegister-29] + _ = x[_bfdDestDeregister-30] + _ = x[_bfdDestUpdate-31] + _ = x[_bfdDestReplay-32] + _ = x[redistributeRouteAdd-33] + _ = x[redistributeRouteDel-34] + _ = x[_vrfUnregister-35] + _ = x[_vrfAdd-36] + _ = x[_vrfDelete-37] + _ = x[vrfLabel-38] + _ = x[_interfaceVRFUpdate-39] + _ = x[_bfdClientRegister-40] + _ = x[_bfdClientDeregister-41] + _ = x[_interfaceEnableRADV-42] + _ = x[_interfaceDisableRADV-43] + _ = x[ipv4NexthopLookupMRIB-44] + _ = x[_interfaceLinkParams-45] + _ = 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[BackwardIPv6RouteAdd-106] + _ = x[BackwardIPv6RouteDelete-107] + _ = x[zapi6Frr7dot2MinDifferentAPIType-48] + _ = x[zapi5ClMinDifferentAPIType-19] + _ = x[zapi5MinDifferentAPIType-7] + _ = x[zapi4MinDifferentAPIType-6] + _ = x[zapi3MinDifferentAPIType-0] + _ = x[zapi6Frr7dot2LabelManagerConnect-49] + _ = x[zapi6Frr7dot2LabelManagerConnectAsync-50] + _ = x[zapi6Frr7dot2GetLabelChunk-51] + _ = x[zapi6Frr7dot2ReleaseLabelChunk-52] + _ = x[zapi6Frr7RouteAdd-7] + _ = x[zapi6Frr7RouteDelete-8] + _ = x[zapi6Frr7RedistributAdd-10] + _ = x[zapi6Frr7RouterIDAdd-14] + _ = x[zapi6Frr7RouterIDUpdate-16] + _ = x[zapi6Frr7Hello-17] + _ = x[zapi6Frr7NexthopRegister-19] + _ = x[zapi6Frr7NexthopUnregister-20] + _ = x[zapi6Frr7NexthopUpdate-21] + _ = x[zapi6Frr7RedistributeRouteAdd-32] + _ = x[zapi6Frr7RedistributeRouteDel-33] + _ = x[zapi6Frr7VrfLabel-37] + _ = x[zapi6Frr7Ipv4NexthopLookupMRIB-43] + _ = x[zapi6Frr7LabelManagerConnect-48] + _ = x[zapi6Frr7LabelManagerConnectAsync-49] + _ = x[zapi6Frr7GetLabelChunk-50] + _ = x[zapi6Frr7ReleaseLabelChunk-51] + _ = x[zapi5ClIpv4NexthopLookupMRIB-42] + _ = x[zapi5ClLabelManagerConnect-47] + _ = x[zapi5ClGetLabelChunk-48] + _ = x[zapi5ClReleaseLabelChunk-49] + _ = x[zapi5RedistributAdd-14] + _ = x[zapi5RouterIDAdd-18] + _ = x[zapi5RouterIDUpdate-20] + _ = x[zapi5Hello-21] + _ = x[zapi5Frr5NexthopRegister-23] + _ = x[zapi5Frr5NexthopUnregister-24] + _ = x[zapi5Frr5NexthopUpdate-25] + _ = x[zapi5Frr5RedistributeRouteAdd-37] + _ = x[zapi5Frr5RedistributeRouteDel-38] + _ = x[zapi5Frr5VrfLabel-42] + _ = x[zapi5Frr5Ipv4NexthopLookupMRIB-47] + _ = x[zapi5Frr5LabelManagerConnect-52] + _ = x[zapi5Frr5LabelManagerConnectAsync-53] + _ = x[zapi5Frr5GetLabelChunk-54] + _ = x[zapi5Frr5ReleaseLabelChunk-55] + _ = x[zapi5Frr4NexthopRegister-22] + _ = x[zapi5Frr4NexthopUnregister-23] + _ = x[zapi5Frr4NexthopUpdate-24] + _ = x[zapi5Frr4RedistributeRouteAdd-36] + _ = x[zapi5Frr4RedistributeRouteDel-37] + _ = x[zapi5Frr4Ipv4NexthopLookupMRIB-45] + _ = x[zapi5Frr4LabelManagerConnect-50] + _ = x[zapi5Frr4GetLabelChunk-51] + _ = x[zapi5Frr4ReleaseLabelChunk-52] + _ = x[zapi4IPv4RouteAdd-6] + _ = x[zapi4IPv4RouteDelete-7] + _ = x[zapi4IPv6RouteAdd-8] + _ = x[zapi4IPv6RouteDelete-9] + _ = x[zapi4RedistributAdd-10] + _ = x[zapi4RouterIDAdd-14] + _ = x[zapi4RouterIDUpdate-16] + _ = x[zapi4Hello-17] + _ = x[zapi4NexthopRegister-18] + _ = x[zapi4NexthopUnregister-19] + _ = x[zapi4NexthopUpdate-20] + _ = x[zapi4RedistributeIPv4Add-32] + _ = x[zapi4RedistributeIPv4Del-33] + _ = x[zapi4RedistributeIPv6Add-34] + _ = x[zapi4RedistributeIPv6Del-35] + _ = x[zapi4LabelManagerConnect-52] + _ = x[zapi4GetLabelChunk-53] + _ = x[zapi4ReleaseLabelChunk-54] + _ = x[zapi3InterfaceAdd-1] + _ = x[zapi3InterfaceDelete-2] + _ = x[zapi3InterfaceAddressAdd-3] + _ = x[zapi3InterfaceAddressDelete-4] + _ = x[zapi3InterfaceUp-5] + _ = x[zapi3InterfaceDown-6] + _ = x[zapi3IPv4RouteAdd-7] + _ = x[zapi3IPv4RouteDelete-8] + _ = x[zapi3IPv6RouteAdd-9] + _ = x[zapi3IPv6RouteDelete-10] + _ = x[zapi3RedistributeAdd-11] + _ = x[zapi3IPv4NexthopLookup-15] + _ = x[zapi3IPv6NexthopLookup-16] + _ = x[zapi3IPv4ImportLookup-17] + _ = x[zapi3RouterIDAdd-20] + _ = x[zapi3RouterIDUpdate-22] + _ = x[zapi3Hello-23] + _ = x[zapi3Ipv4NexthopLookupMRIB-24] + _ = x[zapi3NexthopRegister-27] + _ = x[zapi3NexthopUnregister-28] + _ = 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" + +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} + +func (i APIType) String() string { + if i >= APIType(len(_APIType_index)-1) { + return "APIType(" + strconv.FormatInt(int64(i), 10) + ")" + } + return _APIType_name[_APIType_index[i]:_APIType_index[i+1]] +} diff --git a/internal/pkg/zebra/link_type_string.go b/internal/pkg/zebra/link_type_string.go deleted file mode 100644 index f04a24ce..00000000 --- a/internal/pkg/zebra/link_type_string.go +++ /dev/null @@ -1,16 +0,0 @@ -// Code generated by "stringer -type=LINK_TYPE"; DO NOT EDIT. - -package zebra - -import "strconv" - -const _LINK_TYPE_name = "LINK_TYPE_UNKNOWNLINK_TYPE_ETHERLINK_TYPE_EETHERLINK_TYPE_AX25LINK_TYPE_PRONETLINK_TYPE_IEEE802LINK_TYPE_ARCNETLINK_TYPE_APPLETLKLINK_TYPE_DLCILINK_TYPE_ATMLINK_TYPE_METRICOMLINK_TYPE_IEEE1394LINK_TYPE_EUI64LINK_TYPE_INFINIBANDLINK_TYPE_SLIPLINK_TYPE_CSLIPLINK_TYPE_SLIP6LINK_TYPE_CSLIP6LINK_TYPE_RSRVDLINK_TYPE_ADAPTLINK_TYPE_ROSELINK_TYPE_X25LINK_TYPE_PPPLINK_TYPE_CHDLCLINK_TYPE_LAPBLINK_TYPE_RAWHDLCLINK_TYPE_IPIPLINK_TYPE_IPIP6LINK_TYPE_FRADLINK_TYPE_SKIPLINK_TYPE_LOOPBACKLINK_TYPE_LOCALTLKLINK_TYPE_FDDILINK_TYPE_SITLINK_TYPE_IPDDPLINK_TYPE_IPGRELINK_TYPE_IP6GRELINK_TYPE_PIMREGLINK_TYPE_HIPPILINK_TYPE_ECONETLINK_TYPE_IRDALINK_TYPE_FCPPLINK_TYPE_FCALLINK_TYPE_FCPLLINK_TYPE_FCFABRICLINK_TYPE_IEEE802_TRLINK_TYPE_IEEE80211LINK_TYPE_IEEE80211_RADIOTAPLINK_TYPE_IEEE802154LINK_TYPE_IEEE802154_PHY" - -var _LINK_TYPE_index = [...]uint16{0, 17, 32, 48, 62, 78, 95, 111, 129, 143, 156, 174, 192, 207, 227, 241, 256, 271, 287, 302, 317, 331, 344, 357, 372, 386, 403, 417, 432, 446, 460, 478, 496, 510, 523, 538, 553, 569, 585, 600, 616, 630, 644, 658, 672, 690, 710, 729, 757, 777, 801} - -func (i LINK_TYPE) String() string { - if i >= LINK_TYPE(len(_LINK_TYPE_index)-1) { - return "LINK_TYPE(" + strconv.FormatInt(int64(i), 10) + ")" - } - return _LINK_TYPE_name[_LINK_TYPE_index[i]:_LINK_TYPE_index[i+1]] -} diff --git a/internal/pkg/zebra/linktype_string.go b/internal/pkg/zebra/linktype_string.go new file mode 100644 index 00000000..89e42b1c --- /dev/null +++ b/internal/pkg/zebra/linktype_string.go @@ -0,0 +1,72 @@ +// Code generated by "stringer -type=linkType"; DO NOT EDIT. + +package zebra + +import "strconv" + +func _() { + // An "invalid array index" compiler error signifies that the constant values have changed. + // Re-run the stringer command to generate them again. + var x [1]struct{} + _ = x[linkTypeUnknown-0] + _ = x[linkTypeEther-1] + _ = x[linkTypeEEther-2] + _ = x[linkTypeAX25-3] + _ = x[linkTypePRONET-4] + _ = x[linkTypeIeee802-5] + _ = x[linkTypeARCNET-6] + _ = x[linkTypeAPPLETLK-7] + _ = x[linkTypeDLCI-8] + _ = x[linkTypeATM-9] + _ = x[linkTypeMetricOM-10] + _ = x[linkTypeIeee1394-11] + _ = x[linkTypeEUI64-12] + _ = x[linkTypeINFINIBAND-13] + _ = x[linkTypeSLIP-14] + _ = x[linkTypeCSLIP-15] + _ = x[linkTypeSLIP6-16] + _ = x[linkTypeCSLIP6-17] + _ = x[linkTypeRSRVD-18] + _ = x[linkTypeADAPT-19] + _ = x[linkTypeROSE-20] + _ = x[linkTypeX25-21] + _ = x[linkTypePPP-22] + _ = x[linkTypeCHDLC-23] + _ = x[linkTypeLAPB-24] + _ = x[linkTypeRAWHDLC-25] + _ = x[linkTypeIPIP-26] + _ = x[linkTypeIPIP6-27] + _ = x[linkTypeFRAD-28] + _ = x[linkTypeSKIP-29] + _ = x[linkTypeLOOPBACK-30] + _ = x[linkTypeLOCALTLK-31] + _ = x[linkTypeFDDI-32] + _ = x[linkTypeSIT-33] + _ = x[linkTypeIPDDP-34] + _ = x[linkTypeIPGRE-35] + _ = x[linkTypeIP6GRE-36] + _ = x[linkTypePIMREG-37] + _ = x[linkTypeHIPPI-38] + _ = x[linkTypeECONET-39] + _ = x[linkTypeIRDA-40] + _ = x[linkTypeFCPP-41] + _ = x[linkTypeFCAL-42] + _ = x[linkTypeFCPL-43] + _ = x[linkTypeFCFABRIC-44] + _ = x[linkTypeIeee802Tr-45] + _ = x[linkTypeIeee80211-46] + _ = x[linkTypeIeee80211RadioTap-47] + _ = x[linkTypeIeee802154-48] + _ = x[linkTypeIeee802154Phy-49] +} + +const _linkType_name = "linkTypeUnknownlinkTypeEtherlinkTypeEEtherlinkTypeAX25linkTypePRONETlinkTypeIeee802linkTypeARCNETlinkTypeAPPLETLKlinkTypeDLCIlinkTypeATMlinkTypeMetricOMlinkTypeIeee1394linkTypeEUI64linkTypeINFINIBANDlinkTypeSLIPlinkTypeCSLIPlinkTypeSLIP6linkTypeCSLIP6linkTypeRSRVDlinkTypeADAPTlinkTypeROSElinkTypeX25linkTypePPPlinkTypeCHDLClinkTypeLAPBlinkTypeRAWHDLClinkTypeIPIPlinkTypeIPIP6linkTypeFRADlinkTypeSKIPlinkTypeLOOPBACKlinkTypeLOCALTLKlinkTypeFDDIlinkTypeSITlinkTypeIPDDPlinkTypeIPGRElinkTypeIP6GRElinkTypePIMREGlinkTypeHIPPIlinkTypeECONETlinkTypeIRDAlinkTypeFCPPlinkTypeFCALlinkTypeFCPLlinkTypeFCFABRIClinkTypeIeee802TrlinkTypeIeee80211linkTypeIeee80211RadioTaplinkTypeIeee802154linkTypeIeee802154Phy" + +var _linkType_index = [...]uint16{0, 15, 28, 42, 54, 68, 83, 97, 113, 125, 136, 152, 168, 181, 199, 211, 224, 237, 251, 264, 277, 289, 300, 311, 324, 336, 351, 363, 376, 388, 400, 416, 432, 444, 455, 468, 481, 495, 509, 522, 536, 548, 560, 572, 584, 600, 617, 634, 659, 677, 698} + +func (i linkType) String() string { + if i >= linkType(len(_linkType_index)-1) { + return "linkType(" + strconv.FormatInt(int64(i), 10) + ")" + } + return _linkType_name[_linkType_index[i]:_linkType_index[i+1]] +} diff --git a/internal/pkg/zebra/lsp_type_string.go b/internal/pkg/zebra/lsp_type_string.go deleted file mode 100644 index 318c4800..00000000 --- a/internal/pkg/zebra/lsp_type_string.go +++ /dev/null @@ -1,16 +0,0 @@ -// 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/lsptype_string.go b/internal/pkg/zebra/lsptype_string.go new file mode 100644 index 00000000..5b959180 --- /dev/null +++ b/internal/pkg/zebra/lsptype_string.go @@ -0,0 +1,28 @@ +// Code generated by "stringer -type=lspTYPE"; DO NOT EDIT. + +package zebra + +import "strconv" + +func _() { + // An "invalid array index" compiler error signifies that the constant values have changed. + // Re-run the stringer command to generate them again. + var x [1]struct{} + _ = x[lspNone-0] + _ = x[lspStatic-1] + _ = x[lspLDP-2] + _ = x[lspBGP-3] + _ = x[lspSR-4] + _ = x[lspSHARP-5] +} + +const _lspTYPE_name = "lspNonelspStaticlspLDPlspBGPlspSRlspSHARP" + +var _lspTYPE_index = [...]uint8{0, 7, 16, 22, 28, 33, 41} + +func (i lspTYPE) String() string { + if i >= lspTYPE(len(_lspTYPE_index)-1) { + return "lspTYPE(" + strconv.FormatInt(int64(i), 10) + ")" + } + return _lspTYPE_name[_lspTYPE_index[i]:_lspTYPE_index[i+1]] +} diff --git a/internal/pkg/zebra/nexthop_flag_string.go b/internal/pkg/zebra/nexthop_flag_string.go deleted file mode 100644 index 1ec9d6ac..00000000 --- a/internal/pkg/zebra/nexthop_flag_string.go +++ /dev/null @@ -1,41 +0,0 @@ -// Code generated by "stringer -type=NEXTHOP_FLAG"; DO NOT EDIT. - -package zebra - -import "strconv" - -const ( - _NEXTHOP_FLAG_name_0 = "NEXTHOP_FLAG_ACTIVENEXTHOP_FLAG_FIB" - _NEXTHOP_FLAG_name_1 = "NEXTHOP_FLAG_RECURSIVE" - _NEXTHOP_FLAG_name_2 = "NEXTHOP_FLAG_ONLINK" - _NEXTHOP_FLAG_name_3 = "NEXTHOP_FLAG_MATCHED" - _NEXTHOP_FLAG_name_4 = "NEXTHOP_FLAG_FILTERED" - _NEXTHOP_FLAG_name_5 = "NEXTHOP_FLAG_DUPLICATE" - _NEXTHOP_FLAG_name_6 = "NEXTHOP_FLAG_EVPN_RVTEP" -) - -var ( - _NEXTHOP_FLAG_index_0 = [...]uint8{0, 19, 35} -) - -func (i NEXTHOP_FLAG) String() string { - switch { - case 1 <= i && i <= 2: - i -= 1 - return _NEXTHOP_FLAG_name_0[_NEXTHOP_FLAG_index_0[i]:_NEXTHOP_FLAG_index_0[i+1]] - case i == 4: - return _NEXTHOP_FLAG_name_1 - case i == 8: - return _NEXTHOP_FLAG_name_2 - case i == 16: - return _NEXTHOP_FLAG_name_3 - case i == 32: - return _NEXTHOP_FLAG_name_4 - case i == 64: - return _NEXTHOP_FLAG_name_5 - case i == 128: - return _NEXTHOP_FLAG_name_6 - default: - return "NEXTHOP_FLAG(" + strconv.FormatInt(int64(i), 10) + ")" - } -} diff --git a/internal/pkg/zebra/nexthop_type_string.go b/internal/pkg/zebra/nexthop_type_string.go deleted file mode 100644 index adfc73f8..00000000 --- a/internal/pkg/zebra/nexthop_type_string.go +++ /dev/null @@ -1,17 +0,0 @@ -// Code generated by "stringer -type=NEXTHOP_TYPE"; DO NOT EDIT. - -package zebra - -import "strconv" - -const _NEXTHOP_TYPE_name = "FRR_NEXTHOP_TYPE_IFINDEXFRR_NEXTHOP_TYPE_IPV4FRR_NEXTHOP_TYPE_IPV4_IFINDEXFRR_NEXTHOP_TYPE_IPV6FRR_NEXTHOP_TYPE_IPV6_IFINDEXFRR_NEXTHOP_TYPE_BLACKHOLENEXTHOP_TYPE_IPV6_IFINDEXNEXTHOP_TYPE_IPV6_IFNAMENEXTHOP_TYPE_BLACKHOLE" - -var _NEXTHOP_TYPE_index = [...]uint8{0, 24, 45, 74, 95, 124, 150, 175, 199, 221} - -func (i NEXTHOP_TYPE) String() string { - i -= 1 - if i >= NEXTHOP_TYPE(len(_NEXTHOP_TYPE_index)-1) { - return "NEXTHOP_TYPE(" + strconv.FormatInt(int64(i+1), 10) + ")" - } - return _NEXTHOP_TYPE_name[_NEXTHOP_TYPE_index[i]:_NEXTHOP_TYPE_index[i+1]] -} diff --git a/internal/pkg/zebra/nexthopflag_string.go b/internal/pkg/zebra/nexthopflag_string.go new file mode 100644 index 00000000..50a39629 --- /dev/null +++ b/internal/pkg/zebra/nexthopflag_string.go @@ -0,0 +1,55 @@ +// Code generated by "stringer -type=nexthopFlag"; DO NOT EDIT. + +package zebra + +import "strconv" + +func _() { + // An "invalid array index" compiler error signifies that the constant values have changed. + // Re-run the stringer command to generate them again. + var x [1]struct{} + _ = x[nexthopFlagActive-1] + _ = x[nexthopFlagFIB-2] + _ = x[nexthopFlagRecursive-4] + _ = x[nexthopFlagOnlink-8] + _ = x[nexthopFlagMatched-16] + _ = x[nexthopFlagFiltered-32] + _ = x[nexthopFlagDuplicate-64] + _ = x[nexthopFlagEvpnRvtep-128] +} + +const ( + _nexthopFlag_name_0 = "nexthopFlagActivenexthopFlagFIB" + _nexthopFlag_name_1 = "nexthopFlagRecursive" + _nexthopFlag_name_2 = "nexthopFlagOnlink" + _nexthopFlag_name_3 = "nexthopFlagMatched" + _nexthopFlag_name_4 = "nexthopFlagFiltered" + _nexthopFlag_name_5 = "nexthopFlagDuplicate" + _nexthopFlag_name_6 = "nexthopFlagEvpnRvtep" +) + +var ( + _nexthopFlag_index_0 = [...]uint8{0, 17, 31} +) + +func (i nexthopFlag) String() string { + switch { + case 1 <= i && i <= 2: + i -= 1 + return _nexthopFlag_name_0[_nexthopFlag_index_0[i]:_nexthopFlag_index_0[i+1]] + case i == 4: + return _nexthopFlag_name_1 + case i == 8: + return _nexthopFlag_name_2 + case i == 16: + return _nexthopFlag_name_3 + case i == 32: + return _nexthopFlag_name_4 + case i == 64: + return _nexthopFlag_name_5 + case i == 128: + return _nexthopFlag_name_6 + default: + return "nexthopFlag(" + strconv.FormatInt(int64(i), 10) + ")" + } +} diff --git a/internal/pkg/zebra/nexthoptype_string.go b/internal/pkg/zebra/nexthoptype_string.go new file mode 100644 index 00000000..0c1c1a28 --- /dev/null +++ b/internal/pkg/zebra/nexthoptype_string.go @@ -0,0 +1,37 @@ +// Code generated by "stringer -type=nexthopType"; DO NOT EDIT. + +package zebra + +import "strconv" + +func _() { + // An "invalid array index" compiler error signifies that the constant values have changed. + // Re-run the stringer command to generate them again. + var x [1]struct{} + _ = x[nexthopTypeIFIndex-1] + _ = x[nexthopTypeIPv4-2] + _ = x[nexthopTypeIPv4IFIndex-3] + _ = x[nexthopTypeIPv6-4] + _ = x[nexthopTypeIPv6IFIndex-5] + _ = x[nexthopTypeBlackhole-6] + _ = x[nexthopTypeIFName-2] + _ = x[backwardNexthopTypeIPv4-3] + _ = x[backwardNexthopTypeIPv4IFIndex-4] + _ = x[nexthopTypeIPv4IFName-5] + _ = x[backwardNexthopTypeIPv6-6] + _ = x[backwardNexthopTypeIPv6IFIndex-7] + _ = x[nexthopTypeIPv6IFName-8] + _ = x[backwardNexthopTypeBlackhole-9] +} + +const _nexthopType_name = "nexthopTypeIFIndexnexthopTypeIPv4nexthopTypeIPv4IFIndexnexthopTypeIPv6nexthopTypeIPv6IFIndexnexthopTypeBlackholebackwardNexthopTypeIPv6IFIndexnexthopTypeIPv6IFNamebackwardNexthopTypeBlackhole" + +var _nexthopType_index = [...]uint8{0, 18, 33, 55, 70, 92, 112, 142, 163, 191} + +func (i nexthopType) String() string { + i -= 1 + if i >= nexthopType(len(_nexthopType_index)-1) { + return "nexthopType(" + strconv.FormatInt(int64(i+1), 10) + ")" + } + return _nexthopType_name[_nexthopType_index[i]:_nexthopType_index[i+1]] +} diff --git a/internal/pkg/zebra/ptm_enable_string.go b/internal/pkg/zebra/ptm_enable_string.go deleted file mode 100644 index e9d829fa..00000000 --- a/internal/pkg/zebra/ptm_enable_string.go +++ /dev/null @@ -1,16 +0,0 @@ -// Code generated by "stringer -type=PTM_ENABLE"; DO NOT EDIT. - -package zebra - -import "strconv" - -const _PTM_ENABLE_name = "PTM_ENABLE_OFFPTM_ENABLE_ONPTM_ENABLE_UNSPEC" - -var _PTM_ENABLE_index = [...]uint8{0, 14, 27, 44} - -func (i PTM_ENABLE) String() string { - if i >= PTM_ENABLE(len(_PTM_ENABLE_index)-1) { - return "PTM_ENABLE(" + strconv.FormatInt(int64(i), 10) + ")" - } - return _PTM_ENABLE_name[_PTM_ENABLE_index[i]:_PTM_ENABLE_index[i+1]] -} diff --git a/internal/pkg/zebra/ptm_status_string.go b/internal/pkg/zebra/ptm_status_string.go deleted file mode 100644 index 031e7c01..00000000 --- a/internal/pkg/zebra/ptm_status_string.go +++ /dev/null @@ -1,16 +0,0 @@ -// Code generated by "stringer -type=PTM_STATUS"; DO NOT EDIT. - -package zebra - -import "strconv" - -const _PTM_STATUS_name = "PTM_STATUS_DOWNPTM_STATUS_UPPTM_STATUS_UNKNOWN" - -var _PTM_STATUS_index = [...]uint8{0, 15, 28, 46} - -func (i PTM_STATUS) String() string { - if i >= PTM_STATUS(len(_PTM_STATUS_index)-1) { - return "PTM_STATUS(" + strconv.FormatInt(int64(i), 10) + ")" - } - return _PTM_STATUS_name[_PTM_STATUS_index[i]:_PTM_STATUS_index[i+1]] -} diff --git a/internal/pkg/zebra/ptmenable_string.go b/internal/pkg/zebra/ptmenable_string.go new file mode 100644 index 00000000..03830b0c --- /dev/null +++ b/internal/pkg/zebra/ptmenable_string.go @@ -0,0 +1,25 @@ +// Code generated by "stringer -type=ptmEnable"; DO NOT EDIT. + +package zebra + +import "strconv" + +func _() { + // An "invalid array index" compiler error signifies that the constant values have changed. + // Re-run the stringer command to generate them again. + var x [1]struct{} + _ = x[ptmEnableOff-0] + _ = x[ptmEnableOn-1] + _ = x[ptmEnableUnspec-2] +} + +const _ptmEnable_name = "ptmEnableOffptmEnableOnptmEnableUnspec" + +var _ptmEnable_index = [...]uint8{0, 12, 23, 38} + +func (i ptmEnable) String() string { + if i >= ptmEnable(len(_ptmEnable_index)-1) { + return "ptmEnable(" + strconv.FormatInt(int64(i), 10) + ")" + } + return _ptmEnable_name[_ptmEnable_index[i]:_ptmEnable_index[i+1]] +} diff --git a/internal/pkg/zebra/ptmstatus_string.go b/internal/pkg/zebra/ptmstatus_string.go new file mode 100644 index 00000000..b6ce519c --- /dev/null +++ b/internal/pkg/zebra/ptmstatus_string.go @@ -0,0 +1,25 @@ +// Code generated by "stringer -type=ptmStatus"; DO NOT EDIT. + +package zebra + +import "strconv" + +func _() { + // An "invalid array index" compiler error signifies that the constant values have changed. + // Re-run the stringer command to generate them again. + var x [1]struct{} + _ = x[ptmStatusDown-0] + _ = x[ptmStatusUp-1] + _ = x[ptmStatusUnknown-2] +} + +const _ptmStatus_name = "ptmStatusDownptmStatusUpptmStatusUnknown" + +var _ptmStatus_index = [...]uint8{0, 13, 24, 40} + +func (i ptmStatus) String() string { + if i >= ptmStatus(len(_ptmStatus_index)-1) { + return "ptmStatus(" + strconv.FormatInt(int64(i), 10) + ")" + } + return _ptmStatus_name[_ptmStatus_index[i]:_ptmStatus_index[i+1]] +} diff --git a/internal/pkg/zebra/route_type_string.go b/internal/pkg/zebra/route_type_string.go deleted file mode 100644 index 74d56a17..00000000 --- a/internal/pkg/zebra/route_type_string.go +++ /dev/null @@ -1,16 +0,0 @@ -// Code generated by "stringer -type=ROUTE_TYPE"; DO NOT EDIT. - -package zebra - -import "strconv" - -const _ROUTE_TYPE_name = "FRR_ZAPI6_ROUTE_SYSTEMFRR_ZAPI6_ROUTE_KERNELFRR_ZAPI6_ROUTE_CONNECTFRR_ZAPI6_ROUTE_STATICFRR_ZAPI6_ROUTE_RIPFRR_ZAPI6_ROUTE_RIPNGFRR_ZAPI6_ROUTE_OSPFFRR_ZAPI6_ROUTE_OSPF6FRR_ZAPI6_ROUTE_ISISFRR_ZAPI6_ROUTE_BGPFRR_ZAPI6_ROUTE_PIMFRR_ZAPI6_ROUTE_EIGRPFRR_ZAPI6_ROUTE_NHRPFRR_ZAPI6_ROUTE_HSLSFRR_ZAPI6_ROUTE_OLSRFRR_ZAPI6_ROUTE_TABLEFRR_ZAPI6_ROUTE_LDPFRR_ZAPI6_ROUTE_VNCFRR_ZAPI6_ROUTE_VNC_DIRECTFRR_ZAPI6_ROUTE_VNC_DIRECT_RHFRR_ZAPI6_ROUTE_BGP_DIRECTFRR_ZAPI6_ROUTE_BGP_DIRECT_EXTFRR_ZAPI6_ROUTE_BABELFRR_ZAPI6_ROUTE_SHARPFRR_ZAPI6_ROUTE_PBRFRR_ZAPI6_ROUTE_BFDFRR_ZAPI6_ROUTE_ALLFRR_ZAPI6_ROUTE_MAX" - -var _ROUTE_TYPE_index = [...]uint16{0, 22, 44, 67, 89, 108, 129, 149, 170, 190, 209, 228, 249, 269, 289, 309, 330, 349, 368, 394, 423, 449, 479, 500, 521, 540, 559, 578, 597} - -func (i ROUTE_TYPE) String() string { - if i >= ROUTE_TYPE(len(_ROUTE_TYPE_index)-1) { - return "ROUTE_TYPE(" + strconv.FormatInt(int64(i), 10) + ")" - } - return _ROUTE_TYPE_name[_ROUTE_TYPE_index[i]:_ROUTE_TYPE_index[i+1]] -} diff --git a/internal/pkg/zebra/routetype_string.go b/internal/pkg/zebra/routetype_string.go new file mode 100644 index 00000000..4016b586 --- /dev/null +++ b/internal/pkg/zebra/routetype_string.go @@ -0,0 +1,73 @@ +// Code generated by "stringer -type=RouteType"; DO NOT EDIT. + +package zebra + +import "strconv" + +func _() { + // An "invalid array index" compiler error signifies that the constant values have changed. + // Re-run the stringer command to generate them again. + var x [1]struct{} + _ = x[routeSystem-0] + _ = x[routeKernel-1] + _ = x[routeConnect-2] + _ = x[RouteStatic-3] + _ = x[routeRIP-4] + _ = x[routeRIPNG-5] + _ = x[routeOSPF-6] + _ = x[routeOSPF6-7] + _ = x[routeISIS-8] + _ = x[RouteBGP-9] + _ = x[routePIM-10] + _ = x[routeEIGRP-11] + _ = x[routeNHRP-12] + _ = x[routeHSLS-13] + _ = x[routeOLSR-14] + _ = x[routeTABLE-15] + _ = x[routeLDP-16] + _ = x[routeVNC-17] + _ = x[routeVNCDirect-18] + _ = x[routeVNCDirectRH-19] + _ = x[routeBGPDirect-20] + _ = x[routeBGPDirectEXT-21] + _ = x[routeBABEL-22] + _ = x[routeSHARP-23] + _ = x[routePBR-24] + _ = x[routeBFD-25] + _ = x[routeOpenfabric-26] + _ = x[routeVRRP-27] + _ = x[routeNHG-28] + _ = x[routeAll-29] + _ = x[routeMax-30] + _ = x[zapi5Frr4RouteAll-24] + _ = x[zapi5Frr5RouteAll-25] + _ = x[zapi6Frr6RouteAll-26] + _ = x[zapi6Frr7RouteAll-27] + _ = x[zapi6Frr7dot2RouteAll-28] + _ = x[zapi4RouteNHRP-11] + _ = x[zapi4RouteHSLS-12] + _ = x[zapi4RouteOLSR-13] + _ = x[zapi4RouteTABLE-14] + _ = x[zapi4RouteLDP-15] + _ = x[zapi4RouteVNC-16] + _ = x[zapi4RouteVNCDirect-17] + _ = x[zapi4RouteVNCDirectRH-18] + _ = x[zapi4RouteBGPDixrect-19] + _ = x[zapi4RouteBGPDirectEXT-20] + _ = x[zapi4RouteAll-21] + _ = x[zapi3RouteHSLS-11] + _ = x[zapi3RouteOLSR-12] + _ = x[zapi3RouteBABEL-13] + _ = x[zapi3RouteNHRP-14] +} + +const _RouteType_name = "routeSystemrouteKernelrouteConnectRouteStaticrouteRIProuteRIPNGrouteOSPFrouteOSPF6routeISISRouteBGProutePIMrouteEIGRProuteNHRProuteHSLSrouteOLSRrouteTABLErouteLDProuteVNCrouteVNCDirectrouteVNCDirectRHrouteBGPDirectrouteBGPDirectEXTrouteBABELrouteSHARProutePBRrouteBFDrouteOpenfabricrouteVRRProuteNHGrouteAllrouteMax" + +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} + +func (i RouteType) String() string { + if i >= RouteType(len(_RouteType_index)-1) { + return "RouteType(" + strconv.FormatInt(int64(i), 10) + ")" + } + return _RouteType_name[_RouteType_index[i]:_RouteType_index[i+1]] +} diff --git a/internal/pkg/zebra/safi_string.go b/internal/pkg/zebra/safi_string.go index c8d469e4..9adc4ac5 100644 --- a/internal/pkg/zebra/safi_string.go +++ b/internal/pkg/zebra/safi_string.go @@ -1,17 +1,36 @@ -// Code generated by "stringer -type=SAFI"; DO NOT EDIT. +// Code generated by "stringer -type=Safi"; DO NOT EDIT. package zebra import "strconv" -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" +func _() { + // An "invalid array index" compiler error signifies that the constant values have changed. + // Re-run the stringer command to generate them again. + var x [1]struct{} + _ = x[safiUnspec-0] + _ = x[SafiUnicast-1] + _ = x[safiMulticast-2] + _ = x[safiMplsVpn-3] + _ = x[safiEncap-4] + _ = x[safiEvpn-5] + _ = x[safiLabeledUnicast-6] + _ = x[safiFlowspec-7] + _ = x[safiMax-8] + _ = x[zapi4SafiMplsVpn-3] + _ = x[zapi3SafiMplsVpn-4] + _ = x[zapi4SafiEncap-5] + _ = x[zapi4SafiEvpn-6] + _ = x[zapi3SafiEncap-7] +} + +const _Safi_name = "safiUnspecSafiUnicastsafiMulticastsafiMplsVpnsafiEncapsafiEvpnsafiLabeledUnicastsafiFlowspecsafiMax" -var _SAFI_index = [...]uint8{0, 22, 46, 69, 89, 108, 138, 161, 179} +var _Safi_index = [...]uint8{0, 10, 21, 34, 45, 54, 62, 80, 92, 99} -func (i SAFI) String() string { - i -= 1 - if i >= SAFI(len(_SAFI_index)-1) { - return "SAFI(" + strconv.FormatInt(int64(i+1), 10) + ")" +func (i Safi) String() string { + if i >= Safi(len(_Safi_index)-1) { + return "Safi(" + strconv.FormatInt(int64(i), 10) + ")" } - return _SAFI_name[_SAFI_index[i]:_SAFI_index[i+1]] + return _Safi_name[_Safi_index[i]:_Safi_index[i+1]] } diff --git a/internal/pkg/zebra/zapi.go b/internal/pkg/zebra/zapi.go index cbae40f0..eb4d243a 100644 --- a/internal/pkg/zebra/zapi.go +++ b/internal/pkg/zebra/zapi.go @@ -19,761 +19,856 @@ import ( "encoding/binary" "errors" "fmt" + "github.com/osrg/gobgp/pkg/packet/bgp" + log "github.com/sirupsen/logrus" "io" "math" "net" "strings" "syscall" - - log "github.com/sirupsen/logrus" - - "github.com/osrg/gobgp/pkg/packet/bgp" ) const ( - HEADER_MARKER uint8 = 255 - FRR_HEADER_MARKER uint8 = 254 - INTERFACE_NAMSIZ = 20 + // MinZapiVer is minimum zebra api version which is referred in zclient + MinZapiVer uint8 = 2 + // MaxZapiVer is maximum zebra api version which is referredd in zclient + MaxZapiVer uint8 = 6 + // DefaultVrf is default vrf id is referredd in zclient and server + DefaultVrf = 0 ) const ( - MinZapiVer uint8 = 2 - MaxZapiVer uint8 = 6 + headerMarker uint8 = 255 + frrHeaderMarker uint8 = 254 + interfaceNameSize = 20 + maxPathNum = 64 + maxMplsLabel = 16 ) // Internal Interface Status. -type INTERFACE_STATUS uint8 +type interfaceStatus uint8 const ( - INTERFACE_ACTIVE INTERFACE_STATUS = 0x01 - INTERFACE_SUB INTERFACE_STATUS = 0x02 - INTERFACE_LINKDETECTION INTERFACE_STATUS = 0x04 - INTERFACE_VRF_LOOPBACK INTERFACE_STATUS = 0x08 + interfaceActive interfaceStatus = 0x01 + interfaceSub interfaceStatus = 0x02 + interfaceLinkDetection interfaceStatus = 0x04 + interfaceVrfLoopback interfaceStatus = 0x08 ) // Interface Link Layer Types. -//go:generate stringer -type=LINK_TYPE -type LINK_TYPE uint32 +//go:generate stringer -type=linkType +type linkType uint32 const ( - LINK_TYPE_UNKNOWN LINK_TYPE = iota - LINK_TYPE_ETHER - LINK_TYPE_EETHER - LINK_TYPE_AX25 - LINK_TYPE_PRONET - LINK_TYPE_IEEE802 - LINK_TYPE_ARCNET - LINK_TYPE_APPLETLK - LINK_TYPE_DLCI - LINK_TYPE_ATM - LINK_TYPE_METRICOM - LINK_TYPE_IEEE1394 - LINK_TYPE_EUI64 - LINK_TYPE_INFINIBAND - LINK_TYPE_SLIP - LINK_TYPE_CSLIP - LINK_TYPE_SLIP6 - LINK_TYPE_CSLIP6 - LINK_TYPE_RSRVD - LINK_TYPE_ADAPT - LINK_TYPE_ROSE - LINK_TYPE_X25 - LINK_TYPE_PPP - LINK_TYPE_CHDLC - LINK_TYPE_LAPB - LINK_TYPE_RAWHDLC - LINK_TYPE_IPIP - LINK_TYPE_IPIP6 - LINK_TYPE_FRAD - LINK_TYPE_SKIP - LINK_TYPE_LOOPBACK - LINK_TYPE_LOCALTLK - LINK_TYPE_FDDI - LINK_TYPE_SIT - LINK_TYPE_IPDDP - LINK_TYPE_IPGRE - LINK_TYPE_IP6GRE - LINK_TYPE_PIMREG - LINK_TYPE_HIPPI - LINK_TYPE_ECONET - LINK_TYPE_IRDA - LINK_TYPE_FCPP - LINK_TYPE_FCAL - LINK_TYPE_FCPL - LINK_TYPE_FCFABRIC - LINK_TYPE_IEEE802_TR - LINK_TYPE_IEEE80211 - LINK_TYPE_IEEE80211_RADIOTAP - LINK_TYPE_IEEE802154 - LINK_TYPE_IEEE802154_PHY + linkTypeUnknown linkType = iota + linkTypeEther + linkTypeEEther + linkTypeAX25 + linkTypePRONET + linkTypeIeee802 + linkTypeARCNET + linkTypeAPPLETLK + linkTypeDLCI + linkTypeATM + linkTypeMetricOM + linkTypeIeee1394 + linkTypeEUI64 + linkTypeINFINIBAND + linkTypeSLIP + linkTypeCSLIP + linkTypeSLIP6 + linkTypeCSLIP6 + linkTypeRSRVD + linkTypeADAPT + linkTypeROSE + linkTypeX25 + linkTypePPP + linkTypeCHDLC + linkTypeLAPB + linkTypeRAWHDLC + linkTypeIPIP + linkTypeIPIP6 + linkTypeFRAD + linkTypeSKIP + linkTypeLOOPBACK + linkTypeLOCALTLK + linkTypeFDDI + linkTypeSIT + linkTypeIPDDP + linkTypeIPGRE + linkTypeIP6GRE + linkTypePIMREG + linkTypeHIPPI + linkTypeECONET + linkTypeIRDA + linkTypeFCPP + linkTypeFCAL + linkTypeFCPL + linkTypeFCFABRIC + linkTypeIeee802Tr + linkTypeIeee80211 + linkTypeIeee80211RadioTap + linkTypeIeee802154 + linkTypeIeee802154Phy ) -const VRF_DEFAULT = 0 -const MAXPATH_NUM = 64 -const MPLS_MAX_LABEL = 16 - +// HeaderSize returns suitable header size from version func HeaderSize(version uint8) uint16 { switch version { case 3, 4: return 8 case 5, 6: return 10 - default: - return 6 } + return 6 // version == 2 } -func (t INTERFACE_STATUS) String() string { +// HeaderMarker returns suitable header marker from version +func HeaderMarker(version uint8) uint8 { + if version > 3 { + return frrHeaderMarker + } + return headerMarker +} + +func (t interfaceStatus) String() string { ss := make([]string, 0, 3) - if t&INTERFACE_ACTIVE > 0 { - ss = append(ss, "ACTIVE") + if t&interfaceActive > 0 { + ss = append(ss, "Active") } - if t&INTERFACE_SUB > 0 { - ss = append(ss, "SUB") + if t&interfaceSub > 0 { + ss = append(ss, "Sub") } - if t&INTERFACE_LINKDETECTION > 0 { - ss = append(ss, "LINKDETECTION") + if t&interfaceLinkDetection > 0 { + ss = append(ss, "LinkDetection") } - if t&INTERFACE_VRF_LOOPBACK > 0 { - ss = append(ss, "VRF_LOOPBACK") + if t&interfaceVrfLoopback > 0 { + ss = append(ss, "VrfLoopback") } return strings.Join(ss, "|") } // Interface Connected Address Flags -type INTERFACE_ADDRESS_FLAG uint8 +type interfaceAddressFlag uint8 const ( - INTERFACE_ADDRESS_SECONDARY INTERFACE_ADDRESS_FLAG = 0x01 - INTERFACE_ADDRESS_PEER INTERFACE_ADDRESS_FLAG = 0x02 - INTERFACE_ADDRESS_UNNUMBERED INTERFACE_ADDRESS_FLAG = 0x04 + interfaceAddressSecondary interfaceAddressFlag = 0x01 + interfaceAddressPeer interfaceAddressFlag = 0x02 + interfaceAddressUnnumbered interfaceAddressFlag = 0x04 ) -func (t INTERFACE_ADDRESS_FLAG) String() string { +func (t interfaceAddressFlag) String() string { ss := make([]string, 0, 3) - if t&INTERFACE_ADDRESS_SECONDARY > 0 { + if t&interfaceAddressSecondary > 0 { ss = append(ss, "SECONDARY") } - if t&INTERFACE_ADDRESS_PEER > 0 { + if t&interfaceAddressPeer > 0 { ss = append(ss, "PEER") } - if t&INTERFACE_ADDRESS_UNNUMBERED > 0 { + if t&interfaceAddressUnnumbered > 0 { ss = append(ss, "UNNUMBERED") } return strings.Join(ss, "|") } -// Address Family Identifier. -//go:generate stringer -type=AFI -type AFI uint8 +// Address Family IDentifier. +//go:generate stringer -type=afi +type afi uint8 const ( - AFI_IP AFI = 1 - AFI_IP6 AFI = 2 - AFI_ETHER AFI = 3 - AFI_MAX AFI = 4 + afiIP afi = 1 + afiIP6 afi = 2 + afiEther afi = 3 + afiMax afi = 4 ) -// Subsequent Address Family Identifier. -//go:generate stringer -type=SAFI -type SAFI uint8 +// Safi is Subsequent Address Family IDentifier. +//go:generate stringer -type=Safi +type Safi uint8 -// SAFI definition in Zebra of FRRouting 4.x, 5.x, 6.x +// Safi definition in Zebra of FRRouting 4.x, 5.x, 6.x, and 7.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 + safiUnspec Safi = iota // add in FRRouting version 7.2 (Zapi 6) + SafiUnicast + safiMulticast + safiMplsVpn + safiEncap + safiEvpn + safiLabeledUnicast + safiFlowspec // add in FRRouting version 5 (Zapi 5) + safiMax ) -// SAFI definition in Zebra of Quagga and FRRouting 3.x +// Safi definition in Zebra of Quagga and FRRouting 3.x const ( - _ SAFI = iota - SAFI_UNICAST - SAFI_MULTICAST - 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 + zapi4SafiMplsVpn Safi = iota + safiMulticast + 1 // SafiRESERVED_3 in quagga + zapi3SafiMplsVpn // SafiRESERVED_4 in FRRouting 3.x + zapi4SafiEncap + zapi4SafiEvpn + zapi3SafiEncap // SafiMax in FRRouting 3.x ) -// API Types. -//go:generate stringer -type=API_TYPE -type API_TYPE uint16 - -// For FRRouting version 7. (ZAPI version 6) +var zapi3SafiMap = map[Safi]Safi{ + zapi3SafiMplsVpn: safiMplsVpn, + zapi3SafiEncap: safiEncap, +} +var zapi4SafiMap = map[Safi]Safi{ + zapi4SafiMplsVpn: safiMplsVpn, + zapi4SafiEncap: safiEncap, + zapi4SafiEvpn: safiEvpn, +} +var safiRouteFamilyIPv4Map = map[Safi]bgp.RouteFamily{ + safiUnspec: bgp.RF_OPAQUE, + SafiUnicast: bgp.RF_IPv4_UC, + safiMulticast: bgp.RF_IPv4_MC, + safiMplsVpn: bgp.RF_IPv4_VPN, + safiEncap: bgp.RF_IPv4_ENCAP, + safiLabeledUnicast: bgp.RF_IPv4_MPLS, + safiFlowspec: bgp.RF_FS_IPv4_UC, +} +var safiRouteFamilyIPv6Map = map[Safi]bgp.RouteFamily{ + safiUnspec: bgp.RF_OPAQUE, + SafiUnicast: bgp.RF_IPv6_UC, + safiMulticast: bgp.RF_IPv6_MC, + safiMplsVpn: bgp.RF_IPv6_VPN, + safiEncap: bgp.RF_IPv6_ENCAP, + safiLabeledUnicast: bgp.RF_IPv6_MPLS, + safiFlowspec: bgp.RF_FS_IPv6_UC, +} + +// APIType is referred in zclient_test. +//go:generate stringer -type=APIType +type APIType uint16 + +// For FRRouting version 7.3 (ZAPI version 6) const ( - FRR_ZAPI6_INTERFACE_ADD API_TYPE = iota - FRR_ZAPI6_INTERFACE_DELETE - FRR_ZAPI6_INTERFACE_ADDRESS_ADD - FRR_ZAPI6_INTERFACE_ADDRESS_DELETE - FRR_ZAPI6_INTERFACE_UP - FRR_ZAPI6_INTERFACE_DOWN - FRR_ZAPI6_INTERFACE_SET_MASTER - //FRR_ZAPI6_INTERFACE_SET_PROTODOWN // Add Frr 7.2 - FRR_ZAPI6_ROUTE_ADD - FRR_ZAPI6_ROUTE_DELETE - FRR_ZAPI6_ROUTE_NOTIFY_OWNER - FRR_ZAPI6_REDISTRIBUTE_ADD - FRR_ZAPI6_REDISTRIBUTE_DELETE - FRR_ZAPI6_REDISTRIBUTE_DEFAULT_ADD - FRR_ZAPI6_REDISTRIBUTE_DEFAULT_DELETE - FRR_ZAPI6_ROUTER_ID_ADD - FRR_ZAPI6_ROUTER_ID_DELETE - FRR_ZAPI6_ROUTER_ID_UPDATE - FRR_ZAPI6_HELLO - FRR_ZAPI6_CAPABILITIES - FRR_ZAPI6_NEXTHOP_REGISTER - FRR_ZAPI6_NEXTHOP_UNREGISTER - FRR_ZAPI6_NEXTHOP_UPDATE - FRR_ZAPI6_INTERFACE_NBR_ADDRESS_ADD - FRR_ZAPI6_INTERFACE_NBR_ADDRESS_DELETE - FRR_ZAPI6_INTERFACE_BFD_DEST_UPDATE - FRR_ZAPI6_IMPORT_ROUTE_REGISTER - FRR_ZAPI6_IMPORT_ROUTE_UNREGISTER - FRR_ZAPI6_IMPORT_CHECK_UPDATE - FRR_ZAPI6_BFD_DEST_REGISTER - FRR_ZAPI6_BFD_DEST_DEREGISTER - FRR_ZAPI6_BFD_DEST_UPDATE - FRR_ZAPI6_BFD_DEST_REPLAY - FRR_ZAPI6_REDISTRIBUTE_ROUTE_ADD - FRR_ZAPI6_REDISTRIBUTE_ROUTE_DEL - FRR_ZAPI6_VRF_UNREGISTER - FRR_ZAPI6_VRF_ADD - FRR_ZAPI6_VRF_DELETE - FRR_ZAPI6_VRF_LABEL - FRR_ZAPI6_INTERFACE_VRF_UPDATE - FRR_ZAPI6_BFD_CLIENT_REGISTER - FRR_ZAPI6_BFD_CLIENT_DEREGISTER - FRR_ZAPI6_INTERFACE_ENABLE_RADV - FRR_ZAPI6_INTERFACE_DISABLE_RADV - FRR_ZAPI6_IPV4_NEXTHOP_LOOKUP_MRIB - FRR_ZAPI6_INTERFACE_LINK_PARAMS - FRR_ZAPI6_MPLS_LABELS_ADD - 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 - FRR_ZAPI6_FEC_UNREGISTER - FRR_ZAPI6_FEC_UPDATE - FRR_ZAPI6_ADVERTISE_DEFAULT_GW - FRR_ZAPI6_ADVERTISE_SUBNET - FRR_ZAPI6_ADVERTISE_ALL_VNI - FRR_ZAPI6_LOCAL_ES_ADD - FRR_ZAPI6_LOCAL_ES_DEL - FRR_ZAPI6_VNI_ADD - FRR_ZAPI6_VNI_DEL - FRR_ZAPI6_L3VNI_ADD - FRR_ZAPI6_L3VNI_DEL - FRR_ZAPI6_REMOTE_VTEP_ADD - FRR_ZAPI6_REMOTE_VTEP_DEL - FRR_ZAPI6_MACIP_ADD - FRR_ZAPI6_MACIP_DEL - FRR_ZAPI6_IP_PREFIX_ROUTE_ADD - FRR_ZAPI6_IP_PREFIX_ROUTE_DEL - FRR_ZAPI6_REMOTE_MACIP_ADD - FRR_ZAPI6_REMOTE_MACIP_DEL - FRR_ZAPI6_DUPLICATE_ADDR_DETECTION - FRR_ZAPI6_PW_ADD - FRR_ZAPI6_PW_DELETE - FRR_ZAPI6_PW_SET - FRR_ZAPI6_PW_UNSET - FRR_ZAPI6_PW_STATUS_UPDATE - FRR_ZAPI6_RULE_ADD - FRR_ZAPI6_RULE_DELETE - FRR_ZAPI6_RULE_NOTIFY_OWNER - FRR_ZAPI6_TABLE_MANAGER_CONNECT - FRR_ZAPI6_GET_TABLE_CHUNK - FRR_ZAPI6_RELEASE_TABLE_CHUNK - FRR_ZAPI6_IPSET_CREATE - FRR_ZAPI6_IPSET_DESTROY - FRR_ZAPI6_IPSET_ENTRY_ADD - FRR_ZAPI6_IPSET_ENTRY_DELETE - FRR_ZAPI6_IPSET_NOTIFY_OWNER - FRR_ZAPI6_IPSET_ENTRY_NOTIFY_OWNER - FRR_ZAPI6_IPTABLE_ADD - FRR_ZAPI6_IPTABLE_DELETE - FRR_ZAPI6_IPTABLE_NOTIFY_OWNER - FRR_ZAPI6_VXLAN_FLOOD_CONTROL + interfaceAdd APIType = iota // 0 // same ID in frr3, 4, 5, 6, 7.0, 7.1. 7.2. 7.3 + interfaceDelete // same ID in frr3, 4, 5, 6, 7.0, 7.1. 7.2. 7.3 + interfaceAddressAdd // same ID in frr3, 4, 5, 6, 7.0, 7.1. 7.2. 7.3 + interfaceAddressDelete // same ID in frr3, 4, 5, 6, 7.0, 7.1. 7.2. 7.3 + interfaceUp // same ID in frr3, 4, 5, 6, 7.0, 7.1. 7.2. 7.3 + interfaceDown // same ID in frr3, 4, 5, 6, 7.0, 7.1. 7.2. 7.3 + _interfaceSetMaster + _interfaceSetProtoDown // Add in frr 7.2 + RouteAdd // RouteAdd is referred in zclient_test + RouteDelete // RouteDelete is referred in zclient_test + _routeNotifyOwner // 10 + redistributeAdd + _redistributeDelete + _redistributeDefaultAdd + _redistributeDefaultDelete + routerIDAdd + _routerIDDelete + routerIDUpdate + hello + _capabilities // add in frr5 + nexthopRegister // 20 + nexthopUnregister + nexthopUpdate + _interfaceNBRAddressAdd + _interfaceNBRAddressDelete + _interfaceBFDDestUpdate + _importRouteRegister + _importRouteUnregister + _importCheckUpdate + _bfdDestRegister + _bfdDestDeregister // 30 + _bfdDestUpdate + _bfdDestReplay + redistributeRouteAdd + redistributeRouteDel + _vrfUnregister + _vrfAdd + _vrfDelete + vrfLabel // add in frr5 + _interfaceVRFUpdate + _bfdClientRegister // 40 + _bfdClientDeregister + _interfaceEnableRADV + _interfaceDisableRADV + ipv4NexthopLookupMRIB + _interfaceLinkParams + _mplsLabelsAdd + _mplsLabelsDelete + _mplsLabelsReplace // add in frr7.3 + _ipmrRouteStats + labelManagerConnect // 50 + labelManagerConnectAsync // add in frr5 + getLabelChunk + releaseLabelChunk + _fecRegister + _fecUnregister + _fecUpdate + _advertiseDefaultGW + _advertiseSviMACIP // add in frr7.1 + _advertiseSubnet + _advertiseAllVNI // 60 + _localESAdd + _localESDel + _vniAdd + _vniDel + _l3VNIAdd + _l3VNIDel + _remoteVTEPAdd + _remoteVTEPDel + _macIPAdd + _macIPDel // 70 + _ipPrefixRouteAdd + _ipPrefixRouteDel + _remoteMACIPAdd + _remoteMACIPDel + _duplicateAddrDetection + _pwAdd + _pwDelete + _pwSet + _pwUnset + _pwStatusUpdate // 80 + _ruleAdd + _ruleDelete + _ruleNotifyOwner + _tableManagerConnect + _getTableChunk + _releaseTableChunk + _ipSetCreate + _ipSetDestroy + _ipSetEntryAdd + _ipSetEntryDelete // 90 + _ipSetNotifyOwner + _ipSetEntryNotifyOwner + _ipTableAdd + _ipTableDelete + _ipTableNotifyOwner + _vxlanFloodControl + _vxlanSgAdd + _vxlanSgDel + _vxlanSgReplay + _mlagProcessUp // 100 // add in frr7.3 + _mlagProcessDown // add in frr7.3 + _mlagClientRegister // add in frr7.3 + _mlagClientUnregister // add in frr7.3 + _mlagClientForwardMsg // add in frr7.3 + zebraError // add in frr7.3 + // BackwardIPv6RouteAdd is referred in zclient_test + BackwardIPv6RouteAdd // quagga, frr3, frr4, frr5 + // BackwardIPv6RouteDelete is referred in zclient_test + BackwardIPv6RouteDelete // quagga, frr3, frr4, frr5 ) - -// For FRRouting 5. (ZAPI version 5) const ( - FRR_ZAPI5_INTERFACE_ADD API_TYPE = iota - FRR_ZAPI5_INTERFACE_DELETE - FRR_ZAPI5_INTERFACE_ADDRESS_ADD - FRR_ZAPI5_INTERFACE_ADDRESS_DELETE - FRR_ZAPI5_INTERFACE_UP - FRR_ZAPI5_INTERFACE_DOWN - FRR_ZAPI5_INTERFACE_SET_MASTER - FRR_ZAPI5_ROUTE_ADD - FRR_ZAPI5_ROUTE_DELETE - FRR_ZAPI5_ROUTE_NOTIFY_OWNER - FRR_ZAPI5_IPV4_ROUTE_ADD - FRR_ZAPI5_IPV4_ROUTE_DELETE - FRR_ZAPI5_IPV6_ROUTE_ADD - FRR_ZAPI5_IPV6_ROUTE_DELETE - FRR_ZAPI5_REDISTRIBUTE_ADD - FRR_ZAPI5_REDISTRIBUTE_DELETE - FRR_ZAPI5_REDISTRIBUTE_DEFAULT_ADD - FRR_ZAPI5_REDISTRIBUTE_DEFAULT_DELETE - FRR_ZAPI5_ROUTER_ID_ADD - FRR_ZAPI5_ROUTER_ID_DELETE - FRR_ZAPI5_ROUTER_ID_UPDATE - FRR_ZAPI5_HELLO - FRR_ZAPI5_CAPABILITIES - FRR_ZAPI5_NEXTHOP_REGISTER - FRR_ZAPI5_NEXTHOP_UNREGISTER - FRR_ZAPI5_NEXTHOP_UPDATE - FRR_ZAPI5_INTERFACE_NBR_ADDRESS_ADD - FRR_ZAPI5_INTERFACE_NBR_ADDRESS_DELETE - FRR_ZAPI5_INTERFACE_BFD_DEST_UPDATE - FRR_ZAPI5_IMPORT_ROUTE_REGISTER - FRR_ZAPI5_IMPORT_ROUTE_UNREGISTER - FRR_ZAPI5_IMPORT_CHECK_UPDATE - FRR_ZAPI5_IPV4_ROUTE_IPV6_NEXTHOP_ADD - FRR_ZAPI5_BFD_DEST_REGISTER - FRR_ZAPI5_BFD_DEST_DEREGISTER - FRR_ZAPI5_BFD_DEST_UPDATE - FRR_ZAPI5_BFD_DEST_REPLAY - FRR_ZAPI5_REDISTRIBUTE_ROUTE_ADD - FRR_ZAPI5_REDISTRIBUTE_ROUTE_DEL - FRR_ZAPI5_VRF_UNREGISTER - FRR_ZAPI5_VRF_ADD - FRR_ZAPI5_VRF_DELETE - FRR_ZAPI5_VRF_LABEL - FRR_ZAPI5_INTERFACE_VRF_UPDATE - FRR_ZAPI5_BFD_CLIENT_REGISTER - FRR_ZAPI5_INTERFACE_ENABLE_RADV - FRR_ZAPI5_INTERFACE_DISABLE_RADV - FRR_ZAPI5_IPV4_NEXTHOP_LOOKUP_MRIB - FRR_ZAPI5_INTERFACE_LINK_PARAMS - FRR_ZAPI5_MPLS_LABELS_ADD - FRR_ZAPI5_MPLS_LABELS_DELETE - FRR_ZAPI5_IPMR_ROUTE_STATS - FRR_ZAPI5_LABEL_MANAGER_CONNECT - FRR_ZAPI5_LABEL_MANAGER_CONNECT_ASYNC - FRR_ZAPI5_GET_LABEL_CHUNK - FRR_ZAPI5_RELEASE_LABEL_CHUNK - FRR_ZAPI5_FEC_REGISTER - FRR_ZAPI5_FEC_UNREGISTER - FRR_ZAPI5_FEC_UPDATE - FRR_ZAPI5_ADVERTISE_DEFAULT_GW - FRR_ZAPI5_ADVERTISE_SUBNET - FRR_ZAPI5_ADVERTISE_ALL_VNI - FRR_ZAPI5_VNI_ADD - FRR_ZAPI5_VNI_DEL - FRR_ZAPI5_L3VNI_ADD - FRR_ZAPI5_L3VNI_DEL - FRR_ZAPI5_REMOTE_VTEP_ADD - FRR_ZAPI5_REMOTE_VTEP_DEL - FRR_ZAPI5_MACIP_ADD - FRR_ZAPI5_MACIP_DEL - FRR_ZAPI5_IP_PREFIX_ROUTE_ADD - FRR_ZAPI5_IP_PREFIX_ROUTE_DEL - FRR_ZAPI5_REMOTE_MACIP_ADD - FRR_ZAPI5_REMOTE_MACIP_DEL - FRR_ZAPI5_PW_ADD - FRR_ZAPI5_PW_DELETE - FRR_ZAPI5_PW_SET - FRR_ZAPI5_PW_UNSET - FRR_ZAPI5_PW_STATUS_UPDATE - FRR_ZAPI5_RULE_ADD - FRR_ZAPI5_RULE_DELETE - FRR_ZAPI5_RULE_NOTIFY_OWNER - FRR_ZAPI5_TABLE_MANAGER_CONNECT - FRR_ZAPI5_GET_TABLE_CHUNK - FRR_ZAPI5_RELEASE_TABLE_CHUNK - FRR_ZAPI5_IPSET_CREATE - FRR_ZAPI5_IPSET_DESTROY - FRR_ZAPI5_IPSET_ENTRY_ADD - FRR_ZAPI5_IPSET_ENTRY_DELETE - FRR_ZAPI5_IPSET_NOTIFY_OWNER - FRR_ZAPI5_IPSET_ENTRY_NOTIFY_OWNER - FRR_ZAPI5_IPTABLE_ADD - FRR_ZAPI5_IPTABLE_DELETE - FRR_ZAPI5_IPTABLE_NOTIFY_OWNER + 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) + zapi4MinDifferentAPIType APIType = 6 + zapi3MinDifferentAPIType APIType = 0 ) -// For FRRouting version 3. (ZAPI version 4) +func minDifferentAPIType(version uint8, softwareName string) APIType { + if version < 4 { + return zapi3MinDifferentAPIType + } else if version == 4 { + return zapi4MinDifferentAPIType + } else if version == 5 && softwareName == "cumulus" { + return zapi5ClMinDifferentAPIType + } else if version == 5 || + (version == 6 && (softwareName == "frr6" || softwareName == "frr7" || softwareName == "frr7.1")) { + return zapi5MinDifferentAPIType + } + return zapi6Frr7dot2MinDifferentAPIType +} + const ( - FRR_INTERFACE_ADD API_TYPE = iota - FRR_INTERFACE_DELETE - FRR_INTERFACE_ADDRESS_ADD - FRR_INTERFACE_ADDRESS_DELETE - FRR_INTERFACE_UP - FRR_INTERFACE_DOWN - FRR_IPV4_ROUTE_ADD - FRR_IPV4_ROUTE_DELETE - FRR_IPV6_ROUTE_ADD - FRR_IPV6_ROUTE_DELETE - FRR_REDISTRIBUTE_ADD - FRR_REDISTRIBUTE_DELETE - FRR_REDISTRIBUTE_DEFAULT_ADD - FRR_REDISTRIBUTE_DEFAULT_DELETE - FRR_ROUTER_ID_ADD - FRR_ROUTER_ID_DELETE - FRR_ROUTER_ID_UPDATE - FRR_HELLO - FRR_NEXTHOP_REGISTER - FRR_NEXTHOP_UNREGISTER - FRR_NEXTHOP_UPDATE - FRR_INTERFACE_NBR_ADDRESS_ADD - FRR_INTERFACE_NBR_ADDRESS_DELETE - FRR_INTERFACE_BFD_DEST_UPDATE - FRR_IMPORT_ROUTE_REGISTER - FRR_IMPORT_ROUTE_UNREGISTER - FRR_IMPORT_CHECK_UPDATE - FRR_IPV4_ROUTE_IPV6_NEXTHOP_ADD - FRR_BFD_DEST_REGISTER - FRR_BFD_DEST_DEREGISTER - FRR_BFD_DEST_UPDATE - FRR_BFD_DEST_REPLAY - FRR_REDISTRIBUTE_IPV4_ADD - FRR_REDISTRIBUTE_IPV4_DEL - FRR_REDISTRIBUTE_IPV6_ADD - FRR_REDISTRIBUTE_IPV6_DEL - FRR_VRF_UNREGISTER - FRR_VRF_ADD - FRR_VRF_DELETE - FRR_INTERFACE_VRF_UPDATE - FRR_BFD_CLIENT_REGISTER - FRR_INTERFACE_ENABLE_RADV - FRR_INTERFACE_DISABLE_RADV - FRR_IPV4_NEXTHOP_LOOKUP_MRIB - FRR_INTERFACE_LINK_PARAMS - FRR_MPLS_LABELS_ADD - FRR_MPLS_LABELS_DELETE - FRR_IPV4_NEXTHOP_ADD - FRR_IPV4_NEXTHOP_DELETE - FRR_IPV6_NEXTHOP_ADD - FRR_IPV6_NEXTHOP_DELETE - FRR_IPMR_ROUTE_STATS - FRR_LABEL_MANAGER_CONNECT - FRR_GET_LABEL_CHUNK - FRR_RELEASE_LABEL_CHUNK - FRR_PW_ADD - FRR_PW_DELETE - FRR_PW_SET - FRR_PW_UNSET - FRR_PW_STATUS_UPDATE + 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 ) -// For Quagga. -const ( - _ API_TYPE = iota - INTERFACE_ADD - INTERFACE_DELETE - INTERFACE_ADDRESS_ADD - INTERFACE_ADDRESS_DELETE - INTERFACE_UP - INTERFACE_DOWN - IPV4_ROUTE_ADD - IPV4_ROUTE_DELETE - IPV6_ROUTE_ADD - IPV6_ROUTE_DELETE - REDISTRIBUTE_ADD - REDISTRIBUTE_DELETE - REDISTRIBUTE_DEFAULT_ADD - REDISTRIBUTE_DEFAULT_DELETE - IPV4_NEXTHOP_LOOKUP - IPV6_NEXTHOP_LOOKUP - IPV4_IMPORT_LOOKUP - IPV6_IMPORT_LOOKUP - INTERFACE_RENAME - ROUTER_ID_ADD - ROUTER_ID_DELETE - ROUTER_ID_UPDATE - HELLO - IPV4_NEXTHOP_LOOKUP_MRIB - VRF_UNREGISTER - INTERFACE_LINK_PARAMS - NEXTHOP_REGISTER - NEXTHOP_UNREGISTER - NEXTHOP_UPDATE - MESSAGE_MAX +var apiTypeZapi6Frr7dot2Map = map[APIType]APIType{ + labelManagerConnect: zapi6Frr7dot2LabelManagerConnect, + labelManagerConnectAsync: zapi6Frr7dot2LabelManagerConnectAsync, + getLabelChunk: zapi6Frr7dot2GetLabelChunk, + releaseLabelChunk: zapi6Frr7dot2ReleaseLabelChunk, +} + +const ( // frr7.0, 7.1 + zapi6Frr7RouteAdd APIType = 7 + zapi6Frr7RouteDelete APIType = 8 + zapi6Frr7RedistributAdd APIType = 10 + zapi6Frr7RouterIDAdd APIType = 14 + zapi6Frr7RouterIDUpdate APIType = 16 + zapi6Frr7Hello APIType = 17 + zapi6Frr7NexthopRegister APIType = 19 + zapi6Frr7NexthopUnregister APIType = 20 + zapi6Frr7NexthopUpdate APIType = 21 + zapi6Frr7RedistributeRouteAdd APIType = 32 + zapi6Frr7RedistributeRouteDel APIType = 33 + zapi6Frr7VrfLabel APIType = 37 + zapi6Frr7Ipv4NexthopLookupMRIB APIType = 43 + zapi6Frr7LabelManagerConnect APIType = 48 + zapi6Frr7LabelManagerConnectAsync APIType = 49 + zapi6Frr7GetLabelChunk APIType = 50 + zapi6Frr7ReleaseLabelChunk APIType = 51 +) + +var apiTypeZapi6Frr7Map = map[APIType]APIType{ // frr7.0, 7.1 + RouteAdd: zapi6Frr7RouteAdd, + RouteDelete: zapi6Frr7RouteDelete, + redistributeAdd: zapi6Frr7RedistributAdd, + routerIDAdd: zapi6Frr7RouterIDAdd, + routerIDUpdate: zapi6Frr7RouterIDUpdate, + hello: zapi6Frr7Hello, + nexthopRegister: zapi6Frr7NexthopRegister, + nexthopUnregister: zapi6Frr7NexthopUnregister, + nexthopUpdate: zapi6Frr7NexthopUpdate, + redistributeRouteAdd: zapi6Frr7RedistributeRouteAdd, + redistributeRouteDel: zapi6Frr7RedistributeRouteDel, + vrfLabel: zapi6Frr7VrfLabel, + ipv4NexthopLookupMRIB: zapi6Frr7Ipv4NexthopLookupMRIB, + labelManagerConnect: zapi6Frr7LabelManagerConnect, + labelManagerConnectAsync: zapi6Frr7LabelManagerConnectAsync, + getLabelChunk: zapi6Frr7GetLabelChunk, + releaseLabelChunk: zapi6Frr7ReleaseLabelChunk, +} + +var apiTypeZapi6Frr6Map = map[APIType]APIType{ + RouteAdd: zapi6Frr7RouteAdd, // same as frr7.0&7.1 + RouteDelete: zapi6Frr7RouteDelete, // same as frr7.0&7.1 + redistributeAdd: zapi6Frr7RedistributAdd, // same as frr7.0&7.1 + routerIDAdd: zapi6Frr7RouterIDAdd, // same as frr7.0&7.1 + routerIDUpdate: zapi6Frr7RouterIDUpdate, // same as frr7.0&7.1 + hello: zapi6Frr7Hello, // same as frr7.0&7.1 + nexthopRegister: zapi6Frr7NexthopRegister, // same as frr7.0&7.1 + nexthopUnregister: zapi6Frr7NexthopUnregister, // same as frr7.0&7.1 + nexthopUpdate: zapi6Frr7NexthopUpdate, // same as frr7.0&7.1 + redistributeRouteAdd: redistributeRouteAdd, // same as frr7.2&7.3 + redistributeRouteDel: redistributeRouteDel, // same as frr7.2&7.3 + vrfLabel: vrfLabel, // same as frr7.2&7.3 + ipv4NexthopLookupMRIB: ipv4NexthopLookupMRIB, // same as frr7.2&7.3 + labelManagerConnect: zapi6Frr7dot2LabelManagerConnect, // same as frr7.2 + labelManagerConnectAsync: zapi6Frr7dot2LabelManagerConnectAsync, // same as frr7.2 + getLabelChunk: zapi6Frr7dot2GetLabelChunk, // same as frr7.2 + releaseLabelChunk: zapi6Frr7dot2ReleaseLabelChunk, // same as frr7.2 +} + +const ( // For Cumulus Linux 3.7.7, zebra 4.0+cl3u13 (ZAPI version 5) + zapi5ClIpv4NexthopLookupMRIB APIType = 42 + zapi5ClLabelManagerConnect APIType = 47 + zapi5ClGetLabelChunk APIType = 48 + zapi5ClReleaseLabelChunk APIType = 49 ) -// Route Types. -//go:generate stringer -type=ROUTE_TYPE -type ROUTE_TYPE uint8 +var apiTypeZapi5ClMap = map[APIType]APIType{ + nexthopRegister: zapi6Frr7NexthopRegister, // same as frr7.0&7.1 + nexthopUnregister: zapi6Frr7NexthopUnregister, // same as frr7.0&7.1 + nexthopUpdate: zapi6Frr7NexthopUpdate, // same as frr7.0&7.1 + redistributeRouteAdd: zapi6Frr7RedistributeRouteAdd, // same as frr7.0&7.1 + redistributeRouteDel: zapi6Frr7RedistributeRouteDel, // same as frr7.0&7.1 + vrfLabel: zapi6Frr7VrfLabel, // same as frr7.0&7.1 + labelManagerConnect: zapi5ClLabelManagerConnect, + getLabelChunk: zapi5ClGetLabelChunk, + releaseLabelChunk: zapi5ClReleaseLabelChunk, +} -// For FRRouting version 7 (ZAPI version 6). const ( - FRR_ZAPI6_ROUTE_SYSTEM ROUTE_TYPE = iota - FRR_ZAPI6_ROUTE_KERNEL - FRR_ZAPI6_ROUTE_CONNECT - FRR_ZAPI6_ROUTE_STATIC - FRR_ZAPI6_ROUTE_RIP - FRR_ZAPI6_ROUTE_RIPNG - FRR_ZAPI6_ROUTE_OSPF - FRR_ZAPI6_ROUTE_OSPF6 - FRR_ZAPI6_ROUTE_ISIS - FRR_ZAPI6_ROUTE_BGP - FRR_ZAPI6_ROUTE_PIM - FRR_ZAPI6_ROUTE_EIGRP - FRR_ZAPI6_ROUTE_NHRP - FRR_ZAPI6_ROUTE_HSLS - FRR_ZAPI6_ROUTE_OLSR - FRR_ZAPI6_ROUTE_TABLE - FRR_ZAPI6_ROUTE_LDP - FRR_ZAPI6_ROUTE_VNC - FRR_ZAPI6_ROUTE_VNC_DIRECT - FRR_ZAPI6_ROUTE_VNC_DIRECT_RH - FRR_ZAPI6_ROUTE_BGP_DIRECT - FRR_ZAPI6_ROUTE_BGP_DIRECT_EXT - FRR_ZAPI6_ROUTE_BABEL - FRR_ZAPI6_ROUTE_SHARP - FRR_ZAPI6_ROUTE_PBR - FRR_ZAPI6_ROUTE_BFD - FRR_ZAPI6_ROUTE_OPENFABRIC // FRRRouting version 7 adds. - FRR_ZAPI6_ROUTE_VRRP // FRRRouting version 7.2 adds. - FRR_ZAPI6_ROUTE_ALL - FRR_ZAPI6_ROUTE_MAX + zapi5RedistributAdd APIType = 14 + zapi5RouterIDAdd APIType = 18 + zapi5RouterIDUpdate APIType = 20 + zapi5Hello APIType = 21 + zapi5Frr5NexthopRegister APIType = 23 + zapi5Frr5NexthopUnregister APIType = 24 + zapi5Frr5NexthopUpdate APIType = 25 + zapi5Frr5RedistributeRouteAdd APIType = 37 + zapi5Frr5RedistributeRouteDel APIType = 38 + zapi5Frr5VrfLabel APIType = 42 + zapi5Frr5Ipv4NexthopLookupMRIB APIType = 47 + zapi5Frr5LabelManagerConnect APIType = 52 + zapi5Frr5LabelManagerConnectAsync APIType = 53 + zapi5Frr5GetLabelChunk APIType = 54 + zapi5Frr5ReleaseLabelChunk APIType = 55 ) -// For FRRouting version 5 (ZAPI version 5). +var apiTypeZapi5Frr5Map = map[APIType]APIType{ + RouteAdd: zapi6Frr7RouteAdd, // same as frr7.0&7.1 + RouteDelete: zapi6Frr7RouteDelete, // same as frr7.0&7.1 + redistributeAdd: zapi5RedistributAdd, + routerIDAdd: zapi5RouterIDAdd, + routerIDUpdate: zapi5RouterIDUpdate, + hello: zapi5Hello, + nexthopRegister: zapi5Frr5NexthopRegister, + nexthopUnregister: zapi5Frr5NexthopUnregister, + nexthopUpdate: zapi5Frr5NexthopUpdate, + redistributeRouteAdd: zapi5Frr5RedistributeRouteAdd, + redistributeRouteDel: zapi5Frr5RedistributeRouteDel, + vrfLabel: zapi5Frr5VrfLabel, + ipv4NexthopLookupMRIB: zapi5Frr5Ipv4NexthopLookupMRIB, + labelManagerConnect: zapi5Frr5LabelManagerConnect, + labelManagerConnectAsync: zapi5Frr5LabelManagerConnectAsync, + getLabelChunk: zapi5Frr5GetLabelChunk, + releaseLabelChunk: zapi5Frr5ReleaseLabelChunk, +} + const ( - FRR_ZAPI5_ROUTE_SYSTEM ROUTE_TYPE = iota - FRR_ZAPI5_ROUTE_KERNEL - FRR_ZAPI5_ROUTE_CONNECT - FRR_ZAPI5_ROUTE_STATIC - FRR_ZAPI5_ROUTE_RIP - FRR_ZAPI5_ROUTE_RIPNG - FRR_ZAPI5_ROUTE_OSPF - FRR_ZAPI5_ROUTE_OSPF6 - FRR_ZAPI5_ROUTE_ISIS - FRR_ZAPI5_ROUTE_BGP - FRR_ZAPI5_ROUTE_PIM - FRR_ZAPI5_ROUTE_EIGRP - FRR_ZAPI5_ROUTE_NHRP - FRR_ZAPI5_ROUTE_HSLS - FRR_ZAPI5_ROUTE_OLSR - FRR_ZAPI5_ROUTE_TABLE - FRR_ZAPI5_ROUTE_LDP - FRR_ZAPI5_ROUTE_VNC - FRR_ZAPI5_ROUTE_VNC_DIRECT - FRR_ZAPI5_ROUTE_VNC_DIRECT_RH - FRR_ZAPI5_ROUTE_BGP_DIRECT - FRR_ZAPI5_ROUTE_BGP_DIRECT_EXT - FRR_ZAPI5_ROUTE_BABEL - FRR_ZAPI5_ROUTE_SHARP - FRR_ZAPI5_ROUTE_PBR // FRRRouting version 5 adds. - FRR_ZAPI5_ROUTE_ALL - FRR_ZAPI5_ROUTE_MAX + zapi5Frr4NexthopRegister APIType = 22 + zapi5Frr4NexthopUnregister APIType = 23 + zapi5Frr4NexthopUpdate APIType = 24 + zapi5Frr4RedistributeRouteAdd APIType = 36 + zapi5Frr4RedistributeRouteDel APIType = 37 + zapi5Frr4Ipv4NexthopLookupMRIB APIType = 45 + zapi5Frr4LabelManagerConnect APIType = 50 + zapi5Frr4GetLabelChunk APIType = 51 + zapi5Frr4ReleaseLabelChunk APIType = 52 ) -// For FRRouting. +var apiTypeZapi5Frr4Map = map[APIType]APIType{ + RouteAdd: zapi6Frr7RouteAdd, // same as frr7.0&7.1 + RouteDelete: zapi6Frr7RouteDelete, // same as frr7.0&7.1 + redistributeAdd: zapi5RedistributAdd, + routerIDAdd: zapi5RouterIDAdd, + routerIDUpdate: zapi5RouterIDUpdate, + hello: zapi5Hello, + nexthopRegister: zapi5Frr4NexthopRegister, + nexthopUnregister: zapi5Frr4NexthopUnregister, + nexthopUpdate: zapi5Frr4NexthopUpdate, + redistributeRouteAdd: zapi5Frr4RedistributeRouteAdd, + redistributeRouteDel: zapi5Frr4RedistributeRouteDel, + ipv4NexthopLookupMRIB: zapi5Frr4Ipv4NexthopLookupMRIB, + labelManagerConnect: zapi5Frr4LabelManagerConnect, + getLabelChunk: zapi5Frr4GetLabelChunk, + releaseLabelChunk: zapi5Frr4ReleaseLabelChunk, +} + const ( - FRR_ROUTE_SYSTEM ROUTE_TYPE = iota - FRR_ROUTE_KERNEL - FRR_ROUTE_CONNECT - FRR_ROUTE_STATIC - FRR_ROUTE_RIP - FRR_ROUTE_RIPNG - FRR_ROUTE_OSPF - FRR_ROUTE_OSPF6 - FRR_ROUTE_ISIS - FRR_ROUTE_BGP - FRR_ROUTE_PIM - FRR_ROUTE_HSLS - FRR_ROUTE_OLSR - FRR_ROUTE_TABLE - FRR_ROUTE_LDP - FRR_ROUTE_VNC - FRR_ROUTE_VNC_DIRECT - FRR_ROUTE_VNC_DIRECT_RH - FRR_ROUTE_BGP_DIRECT - FRR_ROUTE_BGP_DIRECT_EXT - FRR_ROUTE_ALL - FRR_ROUTE_MAX + zapi4IPv4RouteAdd APIType = 6 // deleted in zapi6 + zapi4IPv4RouteDelete APIType = 7 // deleted in zapi6 + zapi4IPv6RouteAdd APIType = 8 // deleted in zapi6 + zapi4IPv6RouteDelete APIType = 9 // deleted in zapi6 + zapi4RedistributAdd APIType = 10 + zapi4RouterIDAdd APIType = 14 + zapi4RouterIDUpdate APIType = 16 + zapi4Hello APIType = 17 + zapi4NexthopRegister APIType = 18 + zapi4NexthopUnregister APIType = 19 + zapi4NexthopUpdate APIType = 20 + zapi4RedistributeIPv4Add APIType = 32 // deleted in zapi6 + zapi4RedistributeIPv4Del APIType = 33 // deleted in zapi6 + zapi4RedistributeIPv6Add APIType = 34 // deleted in zapi6 + zapi4RedistributeIPv6Del APIType = 35 // deleted in zapi6 + zapi4LabelManagerConnect APIType = 52 + zapi4GetLabelChunk APIType = 53 + zapi4ReleaseLabelChunk APIType = 54 ) -// For Quagga. +var apiTypeZapi4Map = map[APIType]APIType{ + RouteAdd: zapi4IPv4RouteAdd, // deleted in zapi5 + RouteDelete: zapi4IPv4RouteDelete, // deleted in zapi5 + redistributeAdd: zapi4RedistributAdd, + routerIDAdd: zapi4RouterIDAdd, + routerIDUpdate: zapi4RouterIDUpdate, + hello: zapi4Hello, + nexthopRegister: zapi4NexthopRegister, + nexthopUnregister: zapi4NexthopUnregister, + nexthopUpdate: zapi4NexthopUpdate, + redistributeRouteAdd: zapi4RedistributeIPv4Add, // deleted in zapi5 + redistributeRouteDel: zapi4RedistributeIPv4Del, // deleted in zapi5 + ipv4NexthopLookupMRIB: zapi6Frr7Ipv4NexthopLookupMRIB, // same as frr7.0&7.1 + labelManagerConnect: zapi4LabelManagerConnect, + getLabelChunk: zapi4GetLabelChunk, + releaseLabelChunk: zapi4ReleaseLabelChunk, + BackwardIPv6RouteAdd: zapi4IPv6RouteAdd, + BackwardIPv6RouteDelete: zapi4IPv6RouteDelete, +} + const ( - ROUTE_SYSTEM ROUTE_TYPE = iota - ROUTE_KERNEL - ROUTE_CONNECT - ROUTE_STATIC - ROUTE_RIP - ROUTE_RIPNG - ROUTE_OSPF - ROUTE_OSPF6 - ROUTE_ISIS - ROUTE_BGP - ROUTE_PIM - ROUTE_HSLS - ROUTE_OLSR - ROUTE_BABEL - ROUTE_NHRP // quagga 1.2.4 - ROUTE_MAX + zapi3InterfaceAdd APIType = 1 + zapi3InterfaceDelete APIType = 2 + zapi3InterfaceAddressAdd APIType = 3 + zapi3InterfaceAddressDelete APIType = 4 + zapi3InterfaceUp APIType = 5 + zapi3InterfaceDown APIType = 6 + zapi3IPv4RouteAdd APIType = 7 // deleted in zapi5 + zapi3IPv4RouteDelete APIType = 8 // deleted in zapi5 + zapi3IPv6RouteAdd APIType = 9 // deleted in zapi5 + zapi3IPv6RouteDelete APIType = 10 // deleted in zapi5 + zapi3RedistributeAdd APIType = 11 + zapi3IPv4NexthopLookup APIType = 15 // zapi3(quagga) only + zapi3IPv6NexthopLookup APIType = 16 // zapi3(quagga) only + zapi3IPv4ImportLookup APIType = 17 // zapi3(quagga) only + zapi3RouterIDAdd APIType = 20 + zapi3RouterIDUpdate APIType = 22 + zapi3Hello APIType = 23 + zapi3Ipv4NexthopLookupMRIB APIType = 24 + zapi3NexthopRegister APIType = 27 + zapi3NexthopUnregister APIType = 28 + zapi3NexthopUpdate APIType = 29 ) -var routeTypeValueMapFrrZapi6 = map[string]ROUTE_TYPE{ - "system": FRR_ZAPI6_ROUTE_SYSTEM, - "kernel": FRR_ZAPI6_ROUTE_KERNEL, - "connect": FRR_ZAPI6_ROUTE_CONNECT, // hack for backward compatibility - "directly-connected": FRR_ZAPI6_ROUTE_CONNECT, - "static": FRR_ZAPI6_ROUTE_STATIC, - "rip": FRR_ZAPI6_ROUTE_RIP, - "ripng": FRR_ZAPI6_ROUTE_RIPNG, - "ospf": FRR_ZAPI6_ROUTE_OSPF, - "ospf3": FRR_ZAPI6_ROUTE_OSPF6, - "isis": FRR_ZAPI6_ROUTE_ISIS, - "bgp": FRR_ZAPI6_ROUTE_BGP, - "pim": FRR_ZAPI6_ROUTE_PIM, - "eigrp": FRR_ZAPI6_ROUTE_EIGRP, - "nhrp": FRR_ZAPI6_ROUTE_EIGRP, - "hsls": FRR_ZAPI6_ROUTE_HSLS, - "olsr": FRR_ZAPI6_ROUTE_OLSR, - "table": FRR_ZAPI6_ROUTE_TABLE, - "ldp": FRR_ZAPI6_ROUTE_LDP, - "vnc": FRR_ZAPI6_ROUTE_VNC, - "vnc-direct": FRR_ZAPI6_ROUTE_VNC_DIRECT, - "vnc-direct-rh": FRR_ZAPI6_ROUTE_VNC_DIRECT_RH, - "bgp-direct": FRR_ZAPI6_ROUTE_BGP_DIRECT, - "bgp-direct-ext": FRR_ZAPI6_ROUTE_BGP_DIRECT_EXT, - "babel": FRR_ZAPI6_ROUTE_BABEL, - "sharp": FRR_ZAPI6_ROUTE_SHARP, - "pbr": FRR_ZAPI6_ROUTE_PBR, - "bfd": FRR_ZAPI6_ROUTE_BFD, - "openfabric": FRR_ZAPI6_ROUTE_OPENFABRIC, - "vrrp": FRR_ZAPI6_ROUTE_VRRP, - "all": FRR_ZAPI6_ROUTE_ALL, -} - -var routeTypeValueMapFrrZapi5 = map[string]ROUTE_TYPE{ - "system": FRR_ZAPI5_ROUTE_SYSTEM, - "kernel": FRR_ZAPI5_ROUTE_KERNEL, - "connect": FRR_ZAPI5_ROUTE_CONNECT, // hack for backward compatibility - "directly-connected": FRR_ZAPI5_ROUTE_CONNECT, - "static": FRR_ZAPI5_ROUTE_STATIC, - "rip": FRR_ZAPI5_ROUTE_RIP, - "ripng": FRR_ZAPI5_ROUTE_RIPNG, - "ospf": FRR_ZAPI5_ROUTE_OSPF, - "ospf3": FRR_ZAPI5_ROUTE_OSPF6, - "isis": FRR_ZAPI5_ROUTE_ISIS, - "bgp": FRR_ZAPI5_ROUTE_BGP, - "pim": FRR_ZAPI5_ROUTE_PIM, - "eigrp": FRR_ZAPI5_ROUTE_EIGRP, - "nhrp": FRR_ZAPI5_ROUTE_EIGRP, - "hsls": FRR_ZAPI5_ROUTE_HSLS, - "olsr": FRR_ZAPI5_ROUTE_OLSR, - "table": FRR_ZAPI5_ROUTE_TABLE, - "ldp": FRR_ZAPI5_ROUTE_LDP, - "vnc": FRR_ZAPI5_ROUTE_VNC, - "vnc-direct": FRR_ZAPI5_ROUTE_VNC_DIRECT, - "vnc-direct-rh": FRR_ZAPI5_ROUTE_VNC_DIRECT_RH, - "bgp-direct": FRR_ZAPI5_ROUTE_BGP_DIRECT, - "bgp-direct-ext": FRR_ZAPI5_ROUTE_BGP_DIRECT_EXT, - "babel": FRR_ZAPI5_ROUTE_BABEL, - "sharp": FRR_ZAPI5_ROUTE_SHARP, - "pbr": FRR_ZAPI5_ROUTE_PBR, - "all": FRR_ZAPI5_ROUTE_ALL, -} - -var routeTypeValueMapFrr = map[string]ROUTE_TYPE{ - "system": FRR_ROUTE_SYSTEM, - "kernel": FRR_ROUTE_KERNEL, - "connect": FRR_ROUTE_CONNECT, // hack for backward compatibility - "directly-connected": FRR_ROUTE_CONNECT, - "static": FRR_ROUTE_STATIC, - "rip": FRR_ROUTE_RIP, - "ripng": FRR_ROUTE_RIPNG, - "ospf": FRR_ROUTE_OSPF, - "ospf3": FRR_ROUTE_OSPF6, - "isis": FRR_ROUTE_ISIS, - "bgp": FRR_ROUTE_BGP, - "pim": FRR_ROUTE_PIM, - "hsls": FRR_ROUTE_HSLS, - "olsr": FRR_ROUTE_OLSR, - "table": FRR_ROUTE_TABLE, - "ldp": FRR_ROUTE_LDP, - "vnc": FRR_ROUTE_VNC, - "vnc-direct": FRR_ROUTE_VNC_DIRECT, - "vnc-direct-rh": FRR_ROUTE_VNC_DIRECT_RH, - "bgp-direct": FRR_ROUTE_BGP_DIRECT, - "bgp-direct-ext": FRR_ROUTE_BGP_DIRECT_EXT, - "all": FRR_ROUTE_ALL, -} - -var routeTypeValueMap = map[string]ROUTE_TYPE{ - "system": ROUTE_SYSTEM, - "kernel": ROUTE_KERNEL, - "connect": ROUTE_CONNECT, // hack for backward compatibility - "directly-connected": ROUTE_CONNECT, - "static": ROUTE_STATIC, - "rip": ROUTE_RIP, - "ripng": ROUTE_RIPNG, - "ospf": ROUTE_OSPF, - "ospf3": ROUTE_OSPF6, - "isis": ROUTE_ISIS, - "bgp": ROUTE_BGP, - "pim": ROUTE_PIM, - "hsls": ROUTE_HSLS, - "olsr": ROUTE_OLSR, - "babel": ROUTE_BABEL, - "nhrp": ROUTE_NHRP, -} - -func RouteTypeFromString(typ string, version uint8, softwareName string) (ROUTE_TYPE, error) { - delegateRouteTypeValueMap := routeTypeValueMap - if version == 4 { - delegateRouteTypeValueMap = routeTypeValueMapFrr +var apiTypeZapi3Map = map[APIType]APIType{ + interfaceAdd: zapi3InterfaceAdd, + interfaceDelete: zapi3InterfaceDelete, + interfaceAddressAdd: zapi3InterfaceAddressAdd, + interfaceAddressDelete: zapi3InterfaceAddressDelete, + interfaceUp: zapi3InterfaceUp, + interfaceDown: zapi3InterfaceDown, + RouteAdd: zapi3IPv4RouteAdd, // deleted in zapi5 + RouteDelete: zapi3IPv4RouteDelete, // deleted in zapi5 + redistributeAdd: zapi3RedistributeAdd, + routerIDAdd: zapi3RouterIDAdd, + routerIDUpdate: zapi3RouterIDUpdate, + hello: zapi3Hello, + nexthopRegister: zapi3NexthopRegister, + nexthopUnregister: zapi3NexthopUnregister, + nexthopUpdate: zapi3NexthopUpdate, + BackwardIPv6RouteAdd: zapi3IPv6RouteAdd, + BackwardIPv6RouteDelete: zapi3IPv6RouteDelete, +} + +func (t APIType) doesNeedConversion(version uint8, softwareName string) bool { + if (version == 6 && (softwareName == "frr7.3" || 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") { + return apiTypeZapi6Frr7Map + } else if version == 6 && softwareName == "frr6" { + return apiTypeZapi6Frr6Map } else if version == 5 { - delegateRouteTypeValueMap = routeTypeValueMapFrrZapi5 - } else if version >= 6 { - delegateRouteTypeValueMap = routeTypeValueMapFrrZapi6 + if softwareName == "frr4" { + return apiTypeZapi5Frr4Map + } else if softwareName == "cumulus" { + return apiTypeZapi5ClMap + } + return apiTypeZapi5Frr5Map + } else if version == 4 { + return apiTypeZapi4Map + } else if version < 4 { + return apiTypeZapi3Map + } + return apiTypeZapi6Frr7dot2Map +} + +// ToEach is referred in zclient_test +func (t APIType) ToEach(version uint8, softwareName string) APIType { + if !t.doesNeedConversion(version, softwareName) { + return t } - t, ok := delegateRouteTypeValueMap[typ] - if (version == 5 && softwareName == "frr4" && t == FRR_ZAPI5_ROUTE_PBR) || - (version == 6 && softwareName == "frr6" && t == FRR_ZAPI6_ROUTE_OPENFABRIC) || - (version == 6 && softwareName != "frr7.2" && t == FRR_ZAPI6_ROUTE_VRRP) { - ok = false + apiMap := apiTypeMap(version, softwareName) + backward, ok := apiMap[t] + if !ok { + backward = zebraError // fail to convert and error value } - if ok { - return t, nil + log.WithFields(log.Fields{ + "Topic": "Zebra", + }).Debugf("zebra ToEach converts APIType: %d(%s) -> %d (version: %d, software: %s)", + t, t.String(), backward, version, softwareName) + return backward // success to convert +} +func (t APIType) toCommon(version uint8, softwareName string) APIType { + if !t.doesNeedConversion(version, softwareName) { + return t + } + apiMap := apiTypeMap(version, softwareName) + for common, backward := range apiMap { + if backward == t { + log.WithFields(log.Fields{ + "Topic": "Zebra", + }).Debugf("zebra toCommon converts APIType: %d -> %d(%s) (version: %d, software: %s)", + t, common, common.String(), version, softwareName) + return common // success to convert + } } - return t, fmt.Errorf("unknown route type: %s in version: %d (%s)", typ, version, softwareName) + return zebraError // fail to convert and error value } -func addressFamilyFromApi(Api API_TYPE, version uint8) uint8 { - //ZEBRA_IPV4_NEXTHOP_LOOKUP_MRIB is not implemented. - if version <= 3 { - switch Api { - case IPV4_ROUTE_ADD, IPV4_ROUTE_DELETE, IPV4_NEXTHOP_LOOKUP, IPV4_IMPORT_LOOKUP: - return syscall.AF_INET - case IPV6_ROUTE_ADD, IPV6_ROUTE_DELETE, IPV6_NEXTHOP_LOOKUP, IPV6_IMPORT_LOOKUP: - return syscall.AF_INET6 - } - } else if version == 4 { - switch Api { - case FRR_REDISTRIBUTE_IPV4_ADD, FRR_REDISTRIBUTE_IPV4_DEL, FRR_IPV4_ROUTE_ADD, FRR_IPV4_ROUTE_DELETE, FRR_IPV4_NEXTHOP_LOOKUP_MRIB: +func (t APIType) addressFamily(version uint8) uint8 { + if version == 4 { + switch t { + case zapi4IPv4RouteAdd, zapi4IPv4RouteDelete, zapi4RedistributeIPv4Add, zapi4RedistributeIPv4Del, zapi6Frr7Ipv4NexthopLookupMRIB: return syscall.AF_INET - case FRR_REDISTRIBUTE_IPV6_ADD, FRR_REDISTRIBUTE_IPV6_DEL, FRR_IPV6_ROUTE_ADD, FRR_IPV6_ROUTE_DELETE: + case zapi4IPv6RouteAdd, zapi4IPv6RouteDelete, zapi4RedistributeIPv6Add, zapi4RedistributeIPv6Del: return syscall.AF_INET6 } - } else if version == 5 { - switch Api { - case FRR_ZAPI5_IPV4_ROUTE_ADD, FRR_ZAPI5_IPV4_ROUTE_DELETE: + } else if version < 4 { + switch t { + case zapi3IPv4RouteAdd, zapi3IPv4RouteDelete, zapi3IPv4NexthopLookup, zapi3IPv4ImportLookup, zapi3Ipv4NexthopLookupMRIB: return syscall.AF_INET - case FRR_ZAPI5_IPV6_ROUTE_ADD, FRR_ZAPI5_IPV6_ROUTE_DELETE: + case zapi3IPv6RouteAdd, zapi3IPv6RouteDelete, zapi3IPv6NexthopLookup: return syscall.AF_INET6 } } return syscall.AF_UNSPEC } +// RouteType is referred in zclient. +//go:generate stringer -type=RouteType +type RouteType uint8 + +// For FRRouting version 7 (ZAPI version 6). +const ( + routeSystem RouteType = iota //0 + routeKernel + routeConnect + RouteStatic + routeRIP + routeRIPNG + routeOSPF + routeOSPF6 + routeISIS + RouteBGP + routePIM // 10 + routeEIGRP // FRRRouting version 4 (Zapi5) adds. + routeNHRP + routeHSLS + routeOLSR + routeTABLE + routeLDP + routeVNC + routeVNCDirect + routeVNCDirectRH + routeBGPDirect + routeBGPDirectEXT + routeBABEL + routeSHARP + routePBR // FRRRouting version 5 (Zapi5) adds. + routeBFD // FRRRouting version 6 (Zapi6) adds. + routeOpenfabric // FRRRouting version 7 (Zapi6) adds. + routeVRRP // FRRRouting version 7.2 (Zapi6) adds. + routeNHG // FRRRouting version 7.3 (Zapi6) adds. + routeAll + routeMax // max value for error +) +const ( + zapi5Frr4RouteAll RouteType = 24 + zapi5Frr5RouteAll RouteType = 25 + zapi6Frr6RouteAll RouteType = 26 + zapi6Frr7RouteAll RouteType = 27 + zapi6Frr7dot2RouteAll RouteType = 28 +) + +func getRouteAll(version uint8, softwareName string) RouteType { + if version == 5 { + if softwareName == "frr4" { + return zapi5Frr4RouteAll + } + return zapi5Frr5RouteAll + } else if version == 6 { + if softwareName == "frr6" { + return zapi6Frr6RouteAll + } else if softwareName == "frr7" || softwareName == "frr7.1" { + return zapi6Frr7RouteAll + } else if softwareName == "frr7.2" { + return zapi6Frr7dot2RouteAll + } + } + return routeAll +} + +// For FRRouting version 3.0 except common route type. +const ( + zapi4RouteNHRP RouteType = iota + routePIM + 1 + zapi4RouteHSLS + zapi4RouteOLSR + zapi4RouteTABLE + zapi4RouteLDP + zapi4RouteVNC + zapi4RouteVNCDirect + zapi4RouteVNCDirectRH + zapi4RouteBGPDixrect + zapi4RouteBGPDirectEXT + zapi4RouteAll +) + +var routeTypeZapi4Map = map[RouteType]RouteType{ + routeNHRP: zapi4RouteNHRP, + routeHSLS: zapi4RouteHSLS, + routeOLSR: zapi4RouteOLSR, + routeTABLE: zapi4RouteTABLE, + routeLDP: zapi4RouteLDP, + routeVNC: zapi4RouteVNC, + routeVNCDirect: zapi4RouteVNCDirect, + routeVNCDirectRH: zapi4RouteVNCDirectRH, + routeBGPDirect: zapi4RouteBGPDixrect, + routeBGPDirectEXT: zapi4RouteBGPDirectEXT, + routeAll: zapi4RouteAll, +} + +// For Quagga except common route type. +const ( + zapi3RouteHSLS RouteType = iota + routePIM + 1 + zapi3RouteOLSR + zapi3RouteBABEL + zapi3RouteNHRP // quagga 1.2.4 +) + +var routeTypeZapi3Map = map[RouteType]RouteType{ + routeHSLS: zapi3RouteHSLS, + routeOLSR: zapi3RouteOLSR, + routeBABEL: zapi3RouteBABEL, + routeNHRP: zapi3RouteNHRP, +} + +func (t RouteType) toEach(version uint8, softwareName string) RouteType { + if t <= routePIM || version > 4 { // not need to convert + return t + } + routeTypeMap := routeTypeZapi4Map + if version < 4 { + routeTypeMap = routeTypeZapi3Map + } + backward, ok := routeTypeMap[t] + if ok { + return backward // success to convert + } + return routeMax // fail to convert and error value +} + +var routeTypeValueMap = map[string]RouteType{ + "system": routeSystem, + "kernel": routeKernel, + "connect": routeConnect, // hack for backward compatibility + "directly-connected": routeConnect, + "static": RouteStatic, + "rip": routeRIP, + "ripng": routeRIPNG, + "ospf": routeOSPF, + "ospf3": routeOSPF6, + "isis": routeISIS, + "bgp": RouteBGP, + "pim": routePIM, + "eigrp": routeEIGRP, // add in frr4(zapi5) + "nhrp": routeNHRP, + "hsls": routeHSLS, + "olsr": routeOLSR, + "table": routeTABLE, + "ldp": routeLDP, + "vnc": routeVNC, + "vnc-direct": routeVNCDirect, + "vnc-rn": routeVNCDirectRH, + "bgp-direct": routeBGPDirect, + "bgp-direct-to-nve-groups": routeBGPDirectEXT, + "babel": routeBABEL, + "sharp": routeSHARP, + "pbr": routePBR, + "bfd": routeBFD, + "openfabric": routeOpenfabric, // add in frr7.0(zapi6) + "vrrp": routeVRRP, // add in frr7.2(zapi6) + "nhg": routeNHG, // add in frr7.3(zapi6) + "wildcard": routeAll, +} + +// RouteTypeFromString converts from string to route type +func RouteTypeFromString(typ string, version uint8, softwareName string) (RouteType, error) { + t, ok := routeTypeValueMap[typ] + if !ok { // failed to lookup RouteType from string + return t, fmt.Errorf("unknown route type: %s in version: %d (%s)", typ, version, softwareName) + } + t = t.toEach(version, softwareName) //when lookup failes return routeMax + if t > getRouteAll(version, softwareName) { + return t, fmt.Errorf("unknown route type: %d in version: %d (%s)", t, version, softwareName) + } + return t, nil // Success +} + func addressByteLength(family uint8) (int, error) { switch family { case syscall.AF_INET: @@ -794,265 +889,294 @@ func ipFromFamily(family uint8, buf []byte) net.IP { return nil } -// API Message Flags. -type MESSAGE_FLAG uint8 - -// For FRRouting version 4, 5 and 6 (ZAPI version 5 and 6). -const ( - FRR_ZAPI5_MESSAGE_NEXTHOP MESSAGE_FLAG = 0x01 - FRR_ZAPI5_MESSAGE_DISTANCE MESSAGE_FLAG = 0x02 - FRR_ZAPI5_MESSAGE_METRIC MESSAGE_FLAG = 0x04 - FRR_ZAPI5_MESSAGE_TAG MESSAGE_FLAG = 0x08 - FRR_ZAPI5_MESSAGE_MTU MESSAGE_FLAG = 0x10 - FRR_ZAPI5_MESSAGE_SRCPFX MESSAGE_FLAG = 0x20 - FRR_ZAPI5_MESSAGE_LABEL MESSAGE_FLAG = 0x40 - FRR_ZAPI5_MESSAGE_TABLEID MESSAGE_FLAG = 0x80 +// MessageFlag is the type of API Message Flags. +type MessageFlag uint8 + +const ( // For FRRouting version 4, 5 and 6 (ZAPI version 5 and 6). + // MessageNexthop is referred in zclient + MessageNexthop MessageFlag = 0x01 + // MessageDistance is referred in zclient_test + MessageDistance MessageFlag = 0x02 + // MessageMetric is referred in zclient + MessageMetric MessageFlag = 0x04 + messageTag MessageFlag = 0x08 + // MessageMTU is referred in zclient_test + MessageMTU MessageFlag = 0x10 + messageSRCPFX MessageFlag = 0x20 + // MessageLabel is referred in zclient + MessageLabel MessageFlag = 0x40 // deleted in frr7.3 + messageTableID MessageFlag = 0x80 // introduced in frr5 ) -// For FRRouting. -const ( - FRR_MESSAGE_NEXTHOP MESSAGE_FLAG = 0x01 - FRR_MESSAGE_IFINDEX MESSAGE_FLAG = 0x02 - FRR_MESSAGE_DISTANCE MESSAGE_FLAG = 0x04 - FRR_MESSAGE_METRIC MESSAGE_FLAG = 0x08 - FRR_MESSAGE_TAG MESSAGE_FLAG = 0x10 - FRR_MESSAGE_MTU MESSAGE_FLAG = 0x20 - FRR_MESSAGE_SRCPFX MESSAGE_FLAG = 0x40 +const ( // For FRRouting. + messageIFIndex MessageFlag = 0x02 + zapi4MessageDistance MessageFlag = 0x04 + zapi4MessageMetric MessageFlag = 0x08 + zapi4MessageTag MessageFlag = 0x10 + zapi4MessageMTU MessageFlag = 0x20 + zapi4MessageSRCPFX MessageFlag = 0x40 ) -// For Quagga. -const ( - MESSAGE_NEXTHOP MESSAGE_FLAG = 0x01 - MESSAGE_IFINDEX MESSAGE_FLAG = 0x02 - MESSAGE_DISTANCE MESSAGE_FLAG = 0x04 - MESSAGE_METRIC MESSAGE_FLAG = 0x08 - MESSAGE_MTU MESSAGE_FLAG = 0x10 - MESSAGE_TAG MESSAGE_FLAG = 0x20 +const ( // For Quagga. + zapi3MessageMTU MessageFlag = 0x10 + zapi3MessageTag MessageFlag = 0x20 ) -func (t MESSAGE_FLAG) String(version uint8) string { +// ToEach is referred in zclient +func (f MessageFlag) ToEach(version uint8) MessageFlag { + if version > 4 { //zapi version 5, 6 + return f + } + if version < 4 { //zapi version 3, 2 + switch f { + case MessageMTU: + return zapi3MessageMTU + case messageTag: + return zapi3MessageTag + } + } + switch f { //zapi version 4 + case MessageDistance, MessageMetric, messageTag, MessageMTU, messageSRCPFX: + return f << 1 + } + return f +} +func (f MessageFlag) string(version uint8) string { var ss []string - if (version <= 3 && t&MESSAGE_NEXTHOP > 0) || - (version == 4 && t&FRR_MESSAGE_NEXTHOP > 0) || - (version >= 5 && t&FRR_ZAPI5_MESSAGE_NEXTHOP > 0) { + if f&MessageNexthop > 0 { ss = append(ss, "NEXTHOP") } - if (version <= 3 && t&MESSAGE_IFINDEX > 0) || (version == 4 && t&FRR_MESSAGE_IFINDEX > 0) { + if version < 4 && f&messageIFIndex > 0 { ss = append(ss, "IFINDEX") } - if (version <= 3 && t&MESSAGE_DISTANCE > 0) || - (version == 4 && t&FRR_MESSAGE_DISTANCE > 0) || - (version >= 5 && t&FRR_ZAPI5_MESSAGE_DISTANCE > 0) { + if f&MessageDistance.ToEach(version) > 0 { ss = append(ss, "DISTANCE") } - if (version <= 3 && t&MESSAGE_METRIC > 0) || - (version == 4 && t&FRR_MESSAGE_METRIC > 0) || - (version >= 5 && t&FRR_ZAPI5_MESSAGE_METRIC > 0) { + if f&MessageMetric.ToEach(version) > 0 { ss = append(ss, "METRIC") } - if (version <= 3 && t&MESSAGE_MTU > 0) || (version == 4 && t&FRR_MESSAGE_MTU > 0) || - (version >= 5 && t&FRR_ZAPI5_MESSAGE_MTU > 0) { + if f&MessageMTU.ToEach(version) > 0 { ss = append(ss, "MTU") } - if (version <= 3 && t&MESSAGE_TAG > 0) || (version == 4 && t&FRR_MESSAGE_TAG > 0) || - (version >= 5 && t&FRR_ZAPI5_MESSAGE_TAG > 0) { + if f&messageTag.ToEach(version) > 0 { ss = append(ss, "TAG") } - if (version == 4 && t&FRR_MESSAGE_SRCPFX > 0) || - (version >= 5 && t&FRR_ZAPI5_MESSAGE_SRCPFX > 0) { + if version > 3 && f&messageSRCPFX.ToEach(version) > 0 { ss = append(ss, "SRCPFX") } - if version >= 5 && t&FRR_ZAPI5_MESSAGE_LABEL > 0 { + if version > 4 && f&MessageLabel > 0 { ss = append(ss, "LABEL") } - + if version > 5 && f&messageTableID > 0 { + ss = append(ss, "TABLEID") + } return strings.Join(ss, "|") } -// Message Flags -type FLAG uint64 - -// For FRRouting version 7 (zebra API version 6) -const ( - FRR_ZAPI6_FLAG_ALLOW_RECURSION FLAG = 0x01 - FRR_ZAPI6_FLAG_SELFROUTE FLAG = 0x02 - FRR_ZAPI6_FLAG_IBGP FLAG = 0x04 - FRR_ZAPI6_FLAG_SELECTED FLAG = 0x08 - FRR_ZAPI6_FLAG_FIB_OVERRIDE FLAG = 0x10 - FRR_ZAPI6_FLAG_EVPN_ROUTE FLAG = 0x20 - FRR_ZAPI6_FLAG_RR_USE_DISTANCE FLAG = 0x40 - FRR_ZAPI6_FLAG_ONLINk FLAG = 0x40 +// Flag is Message Flag which is referred in zclient +type Flag uint64 + +const ( // For FRRouting version 7 (zebra API version 6) + // FlagAllowRecursion is referred in zclient, and it is renamed from ZEBRA_FLAG_INTERNAL (https://github.com/FRRouting/frr/commit/4e8b02f4df5d6bcfde6390955b8feda2a17dc9bd) + FlagAllowRecursion Flag = 0x01 // quagga, frr3, frr4, frr5, frr6, frr7 + flagSelfRoute Flag = 0x02 // quagga, frr3, frr4, frr5, frr6, frr7 + // FlagIBGP is referred in zclient + FlagIBGP Flag = 0x04 + // FlagSelected referred in zclient_test + FlagSelected Flag = 0x08 + flagFIBOverride Flag = 0x10 + flagEvpnRoute Flag = 0x20 + flagRRUseDistance Flag = 0x40 + flagOnlink Flag = 0x80 // frr7.0 only, this vale is deleted in frr7.1 ) -// For Quagga (ZAPI v2, v3), FRR v3 (ZAPI v4), FRR v4, v5 (ZAPI v5), FRR v6 (ZAPI v6) +// For Quagga (ZAPI v2, v3), FRR v3 (ZAPI v4), FRR v4, v5 (ZAPI v5), FRR v6 (ZAPI v6) for backward compatibility const ( - // Rename ZEBRA_FLAG_INTERNAL -> ZEBRA_FLAG_ALLOW_RECURSION - // https://github.com/FRRouting/frr/commit/4e8b02f4df5d6bcfde6390955b8feda2a17dc9bd - FLAG_ALLOW_RECURSION FLAG = 0x01 - FLAG_SELFROUTE FLAG = 0x02 - FLAG_BLACKHOLE FLAG = 0x04 // quagga, frr3 - FLAG_IBGP FLAG = 0x08 - FLAG_SELECTED FLAG = 0x10 - FLAG_CHANGED FLAG = 0x20 - FLAG_STATIC FLAG = 0x40 - FLAG_REJECT FLAG = 0x80 // quagga, frr3 - FLAG_SCOPE_LINK FLAG = 0x100 - FLAG_FIB_OVERRIDE FLAG = 0x200 - FLAG_EVPN_ROUTE FLAG = 0x400 - FLAG_RR_USE_DISTANCE FLAG = 0x800 + flagBlackhole Flag = 0x04 // quagga, frr3 + flagStatic Flag = 0x40 // quagga, frr3, frr4, frr5, frr6 + flagReject Flag = 0x80 // quagga, frr3 + flagScopeLink Flag = 0x100 // frr4, frr5, frr6 ) -func (t FLAG) String(version uint8, softwareName string) string { - if version == 6 && softwareName != "frr6" { - return t.stringFrrZapi6() +// ToEach is referred in zclient +func (f Flag) ToEach(version uint8, softwareName string) Flag { + if (version == 6 && softwareName != "frr6") || (f < FlagIBGP) || f > flagRRUseDistance { + return f + } + switch f { + case FlagIBGP, FlagSelected: // 0x04->0x08,0x08->0x10(quagga, frr3,4,5,6) + return f << 1 + case flagEvpnRoute, flagRRUseDistance: // 0x20->0x400,0x40->0x800(frr4,5,6) + return f << 5 + case flagFIBOverride: + if version < 4 { + return f << 1 // 0x10->0x20(quagga) + } + return f << 5 // 0x10->0x200(frr3, frr4, frr5, frr6) } - return t.string() + return f } -func (t FLAG) string() string { +// String is referred in zclient +func (f Flag) String(version uint8, softwareName string) string { var ss []string - if t&FLAG_ALLOW_RECURSION > 0 { + // common flag + if f&FlagAllowRecursion > 0 { ss = append(ss, "FLAG_ALLOW_RECURSION") } - if t&FLAG_SELFROUTE > 0 { + if f&flagSelfRoute > 0 { ss = append(ss, "FLAG_SELFROUTE") } - if t&FLAG_BLACKHOLE > 0 { - ss = append(ss, "FLAG_BLACKHOLE") - } - if t&FLAG_IBGP > 0 { + if f&FlagIBGP.ToEach(version, softwareName) > 0 { ss = append(ss, "FLAG_IBGP") } - if t&FLAG_SELECTED > 0 { + if f&FlagSelected.ToEach(version, softwareName) > 0 { ss = append(ss, "FLAG_SELECTED") } - if t&FLAG_CHANGED > 0 { - ss = append(ss, "FLAG_CHANGED") - } - if t&FLAG_STATIC > 0 { - ss = append(ss, "FLAG_STATIC") - } - if t&FLAG_REJECT > 0 { - ss = append(ss, "FLAG_REJECT") - } - if t&FLAG_SCOPE_LINK > 0 { - ss = append(ss, "FLAG_SCOPE_LINK") - } - if t&FLAG_FIB_OVERRIDE > 0 { - ss = append(ss, "FLAG_FIB_OVERRIDE") - } - if t&FLAG_EVPN_ROUTE > 0 { + if f&flagEvpnRoute.ToEach(version, softwareName) > 0 { ss = append(ss, "FLAG_EVPN_ROUTE") } - if t&FLAG_RR_USE_DISTANCE > 0 { + if f&flagRRUseDistance.ToEach(version, softwareName) > 0 { ss = append(ss, "FLAG_RR_USE_DISTANCE") } - - return strings.Join(ss, "|") -} -func (t FLAG) stringFrrZapi6() string { - var ss []string - if t&FRR_ZAPI6_FLAG_ALLOW_RECURSION > 0 { - ss = append(ss, "FLAG_ALLOW_RECURSION") - } - if t&FRR_ZAPI6_FLAG_SELFROUTE > 0 { - ss = append(ss, "FLAG_SELFROUTE") - } - if t&FRR_ZAPI6_FLAG_IBGP > 0 { - ss = append(ss, "FLAG_IBGP") + if f&flagFIBOverride.ToEach(version, softwareName) > 0 { + ss = append(ss, "FLAG_FIB_OVERRIDE") } - if t&FRR_ZAPI6_FLAG_SELECTED > 0 { - ss = append(ss, "FLAG_SELECTED") + if version == 6 && softwareName == "frr7" && f&flagOnlink > 0 { // frr7.0 only + ss = append(ss, "FLAG_ONLINK") } - if t&FRR_ZAPI6_FLAG_FIB_OVERRIDE > 0 { - ss = append(ss, "FLAG_FIB_OVERRIDE") + if (version < 6 || (version == 6 && softwareName == "frr6")) && f&flagStatic > 0 { + ss = append(ss, "FLAG_STATIC") // quagga, frr3, frr4, frr5, frr6 } - if t&FRR_ZAPI6_FLAG_EVPN_ROUTE > 0 { - ss = append(ss, "FLAG_EVPN_ROUTE") + if version < 5 && f&flagBlackhole > 0 { // quagga, frr3 + ss = append(ss, "FLAG_BLACKHOLE") } - if t&FRR_ZAPI6_FLAG_RR_USE_DISTANCE > 0 { - ss = append(ss, "FLAG_RR_USE_DISTANCE") + if version < 5 && f&flagReject > 0 { // quagga, frr3 + ss = append(ss, "FLAG_REJECT") } - if t&FRR_ZAPI6_FLAG_ONLINk > 0 { - ss = append(ss, "FLAG_ONLINK") + if (version == 5 || (version == 6 && softwareName == "frr6")) && f&flagScopeLink > 0 { + ss = append(ss, "FLAG_SCOPE_LINK") // frr4, frr5, frr6 } return strings.Join(ss, "|") } // Nexthop Types. -//go:generate stringer -type=NEXTHOP_TYPE -type NEXTHOP_TYPE uint8 +//go:generate stringer -type=nexthopType +type nexthopType uint8 // For FRRouting. const ( - _ NEXTHOP_TYPE = iota - FRR_NEXTHOP_TYPE_IFINDEX - FRR_NEXTHOP_TYPE_IPV4 - FRR_NEXTHOP_TYPE_IPV4_IFINDEX - FRR_NEXTHOP_TYPE_IPV6 - FRR_NEXTHOP_TYPE_IPV6_IFINDEX - FRR_NEXTHOP_TYPE_BLACKHOLE + _ nexthopType = iota + nexthopTypeIFIndex // 1 + nexthopTypeIPv4 // 2 + nexthopTypeIPv4IFIndex // 3 + nexthopTypeIPv6 // 4 + nexthopTypeIPv6IFIndex // 5 + nexthopTypeBlackhole // 6 ) // For Quagga. const ( - _ NEXTHOP_TYPE = iota - NEXTHOP_TYPE_IFINDEX - NEXTHOP_TYPE_IFNAME - NEXTHOP_TYPE_IPV4 - NEXTHOP_TYPE_IPV4_IFINDEX - NEXTHOP_TYPE_IPV4_IFNAME - NEXTHOP_TYPE_IPV6 - NEXTHOP_TYPE_IPV6_IFINDEX - NEXTHOP_TYPE_IPV6_IFNAME - NEXTHOP_TYPE_BLACKHOLE + nexthopTypeIFName nexthopType = iota + 2 // 2 + backwardNexthopTypeIPv4 // 3 + backwardNexthopTypeIPv4IFIndex // 4 + nexthopTypeIPv4IFName // 5 + backwardNexthopTypeIPv6 // 6 + backwardNexthopTypeIPv6IFIndex // 7 + nexthopTypeIPv6IFName // 8 + backwardNexthopTypeBlackhole // 9 ) +var nexthopTypeMap = map[nexthopType]nexthopType{ + nexthopTypeIPv4: backwardNexthopTypeIPv4, // 2 -> 3 + nexthopTypeIPv4IFIndex: backwardNexthopTypeIPv4IFIndex, // 3 -> 4 + nexthopTypeIPv6: backwardNexthopTypeIPv6, // 4 -> 6 + nexthopTypeIPv6IFIndex: backwardNexthopTypeIPv6IFIndex, // 5 -> 7 + nexthopTypeBlackhole: backwardNexthopTypeBlackhole, // 6 -> 9 +} + +func (t nexthopType) toEach(version uint8) nexthopType { + if version > 3 { // frr + return t + } + if t == nexthopTypeIFIndex || t > nexthopTypeBlackhole { // 1 (common), 7, 8, 9 (out of map range) + return t + } + backward, ok := nexthopTypeMap[t] + if ok { + return backward // converted value + } + return nexthopType(0) // error for conversion +} + +func (t nexthopType) ipToIPIFIndex() nexthopType { + // process of nexthopTypeIPv[4|6] is same as nexthopTypeIPv[4|6]IFIndex + // in IPRouteBode of frr7.3 and NexthoUpdate of frr + if t == nexthopTypeIPv4 { + return nexthopTypeIPv4IFIndex + } else if t == nexthopTypeIPv6 { + return nexthopTypeIPv6IFIndex + } + return t +} +func (t nexthopType) ifNameToIFIndex() nexthopType { // quagga + if t == nexthopTypeIFName { + return nexthopTypeIFIndex + } else if t == nexthopTypeIPv4IFName { + return backwardNexthopTypeIPv4IFIndex + } else if t == nexthopTypeIPv6IFName { + return backwardNexthopTypeIPv6IFIndex + } + return t +} + // Nexthop Flags. -//go:generate stringer -type=NEXTHOP_FLAG -type NEXTHOP_FLAG uint8 +//go:generate stringer -type=nexthopFlag +type nexthopFlag uint8 const ( - NEXTHOP_FLAG_ACTIVE NEXTHOP_FLAG = 0x01 // This nexthop is alive. - NEXTHOP_FLAG_FIB NEXTHOP_FLAG = 0x02 // FIB nexthop. - NEXTHOP_FLAG_RECURSIVE NEXTHOP_FLAG = 0x04 // Recursive nexthop. - NEXTHOP_FLAG_ONLINK NEXTHOP_FLAG = 0x08 // Nexthop should be installed onlink. - NEXTHOP_FLAG_MATCHED NEXTHOP_FLAG = 0x10 // Already matched vs a nexthop - NEXTHOP_FLAG_FILTERED NEXTHOP_FLAG = 0x20 // rmap filtered (version >= 4) - NEXTHOP_FLAG_DUPLICATE NEXTHOP_FLAG = 0x40 // nexthop duplicates (version >= 5) - NEXTHOP_FLAG_EVPN_RVTEP NEXTHOP_FLAG = 0x80 // EVPN remote vtep nexthop (version >= 5) + nexthopFlagActive nexthopFlag = 0x01 // This nexthop is alive. + nexthopFlagFIB nexthopFlag = 0x02 // FIB nexthop. + nexthopFlagRecursive nexthopFlag = 0x04 // Recursive nexthop. + nexthopFlagOnlink nexthopFlag = 0x08 // Nexthop should be installed onlink. + nexthopFlagMatched nexthopFlag = 0x10 // Already matched vs a nexthop + nexthopFlagFiltered nexthopFlag = 0x20 // rmap filtered (version >= 4) + nexthopFlagDuplicate nexthopFlag = 0x40 // nexthop duplicates (version >= 5) + nexthopFlagEvpnRvtep nexthopFlag = 0x80 // Evpn remote vtep nexthop (version >= 5) ) // Interface PTM Enable Configuration. -//go:generate stringer -type=PTM_ENABLE -type PTM_ENABLE uint8 +//go:generate stringer -type=ptmEnable +type ptmEnable uint8 const ( - PTM_ENABLE_OFF PTM_ENABLE = 0 - PTM_ENABLE_ON PTM_ENABLE = 1 - PTM_ENABLE_UNSPEC PTM_ENABLE = 2 + ptmEnableOff ptmEnable = 0 + ptmEnableOn ptmEnable = 1 + ptmEnableUnspec ptmEnable = 2 ) // PTM Status. -//go:generate stringer -type=PTM_STATUS -type PTM_STATUS uint8 +//go:generate stringer -type=ptmStatus +type ptmStatus uint8 const ( - PTM_STATUS_DOWN PTM_STATUS = 0 - PTM_STATUS_UP PTM_STATUS = 1 - PTM_STATUS_UNKNOWN PTM_STATUS = 2 + ptmStatusDown ptmStatus = 0 + ptmStatusUp ptmStatus = 1 + ptmStatusUnknown ptmStatus = 2 ) +// Client is zebra client which is referred in zclient type Client struct { outgoing chan *Message incoming chan *Message - redistDefault ROUTE_TYPE + redistDefault RouteType conn net.Conn Version uint8 SoftwareName string } -func NewClient(network, address string, typ ROUTE_TYPE, version uint8, software string) (*Client, error) { +// NewClient returns a Client instance (Client constructor) +func NewClient(network, address string, typ RouteType, version uint8, software string, mplsLabelRangeSize uint32) (*Client, error) { conn, err := net.Dial(network, address) if err != nil { return nil, err @@ -1069,7 +1193,7 @@ func NewClient(network, address string, typ ROUTE_TYPE, version uint8, software 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") { + (version == 6 && software != "" && software != "frr6" && software != "frr7" && software != "frr7.1" && software != "frr7.2" && software != "frr7.3") { isAllowableSoftware = false } if !isAllowableSoftware { @@ -1092,7 +1216,7 @@ func NewClient(network, address string, typ ROUTE_TYPE, version uint8, software for { m, more := <-outgoing if more { - b, err := m.Serialize(software) + b, err := m.serialize(software) if err != nil { log.WithFields(log.Fields{ "Topic": "Zebra", @@ -1115,13 +1239,12 @@ func NewClient(network, address string, typ ROUTE_TYPE, version uint8, software } }() - // Send HELLO/ROUTER_ID_ADD messages to negotiate the Zebra message version. + // Send Hello/RouterIDAdd messages to negotiate the Zebra message version. c.SendHello() c.SendRouterIDAdd() - // ZAPIv5 has ZEBRA_LABEL_MANAGER_CONNECT_ASYNC, however frr4 (ZAPIv5) doesn't have it. - if version > 4 && software != "frr4" { - c.SendLabelManagerConnectAsync() + if mplsLabelRangeSize > 0 && c.SupportMpls() { + c.sendLabelManagerConnect(true) } receiveSingleMsg := func() (*Message, error) { @@ -1135,7 +1258,7 @@ func NewClient(network, address string, typ ROUTE_TYPE, version uint8, software } hd := &Header{} - err = hd.DecodeFromBytes(headerBuf) + err = hd.decodeFromBytes(headerBuf) if c.Version != hd.Version { log.WithFields(log.Fields{ "Topic": "Zebra", @@ -1161,11 +1284,10 @@ func NewClient(network, address string, typ ROUTE_TYPE, version uint8, software return nil, err } - m, err := ParseMessage(hd, bodyBuf, software) + m, err := parseMessage(hd, bodyBuf, software) if err != nil { // Just outputting warnings (not error message) and ignore this - // error considering the case that body parser is not implemented - // yet. + // error considering the case that body parser is not implemented yet. log.WithFields(log.Fields{ "Topic": "Zebra", "Header": hd, @@ -1184,7 +1306,7 @@ func NewClient(network, address string, typ ROUTE_TYPE, version uint8, software // Try to receive the first message from Zebra. if m, err := receiveSingleMsg(); err != nil { - c.Close() + c.close() // Return error explicitly in order to retry connection. return nil, err } else if m != nil { @@ -1212,11 +1334,12 @@ func readAll(conn net.Conn, length int) ([]byte, error) { return buf, err } +// Receive return incoming channel message func (c *Client) Receive() chan *Message { return c.incoming } -func (c *Client) Send(m *Message) { +func (c *Client) send(m *Message) { defer func() { if err := recover(); err != nil { log.WithFields(log.Fields{ @@ -1232,292 +1355,152 @@ func (c *Client) Send(m *Message) { c.outgoing <- m } -func (c *Client) SendCommand(command API_TYPE, vrfId uint32, body Body) error { - marker := HEADER_MARKER - if c.Version >= 4 { - marker = FRR_HEADER_MARKER - } - if c.Version == 6 && c.SoftwareName == "frr6" { - if frr6Command, err := frr6Zapi6Command(command, c.SoftwareName, false); err == nil { - command = frr6Command - } else { - return err - } - } else if c.Version == 6 && c.SoftwareName == "frr7.2" { - // frr7.2 adds INTERFACE_SET_PROTODOWN between INTERFACE_SET_MASTER(6) and ROUTE_ADD - if command >= FRR_ZAPI6_ROUTE_ADD { - command++ - } - } else if c.Version == 5 && c.SoftwareName == "frr4" { - if frr4Command, err := frr4Zapi5Command(command, c.SoftwareName, false); err == nil { - command = frr4Command - } else { - return err - } - } else if c.Version == 5 && c.SoftwareName == "cumulus" { - if cumulusCommand, err := cumulusZapi5Command(command, c.SoftwareName, false); err == nil { - command = cumulusCommand - } else { - return err - } - } +func (c *Client) sendCommand(command APIType, vrfID uint32, body Body) error { m := &Message{ Header: Header{ Len: HeaderSize(c.Version), - Marker: marker, + Marker: HeaderMarker(c.Version), Version: c.Version, - VrfId: vrfId, - Command: command, + VrfID: vrfID, + Command: command.ToEach(c.Version, c.SoftwareName), }, Body: body, } - c.Send(m) + c.send(m) return nil } +// SendHello sends HELLO message to zebra daemon. func (c *Client) SendHello() error { if c.redistDefault > 0 { - command := HELLO - if c.Version == 4 { - command = FRR_HELLO - } else if c.Version == 5 { - command = FRR_ZAPI5_HELLO - } else if c.Version >= 6 { - command = FRR_ZAPI6_HELLO + body := &helloBody{ + redistDefault: c.redistDefault, + instance: 0, } - body := &HelloBody{ - RedistDefault: c.redistDefault, - Instance: 0, - } - return c.SendCommand(command, VRF_DEFAULT, body) + return c.sendCommand(hello, DefaultVrf, body) } return nil } +// SendRouterIDAdd sends ROUTER_ID_ADD message to zebra daemon. func (c *Client) SendRouterIDAdd() error { - command := ROUTER_ID_ADD - if c.Version == 4 { - command = FRR_ROUTER_ID_ADD - } else if c.Version == 5 { - command = FRR_ZAPI5_ROUTER_ID_ADD - } else if c.Version >= 6 { - command = FRR_ZAPI6_ROUTER_ID_ADD - } - return c.SendCommand(command, VRF_DEFAULT, nil) + return c.sendCommand(routerIDAdd, DefaultVrf, nil) } +// SendInterfaceAdd sends INTERFACE_ADD message to zebra daemon. func (c *Client) SendInterfaceAdd() error { - command := INTERFACE_ADD - if c.Version == 4 { - command = FRR_INTERFACE_ADD - } else if c.Version >= 5 { - command = FRR_ZAPI5_INTERFACE_ADD - } - return c.SendCommand(command, VRF_DEFAULT, nil) + return c.sendCommand(interfaceAdd, DefaultVrf, nil) } -func (c *Client) SendRedistribute(t ROUTE_TYPE, vrfId uint32) error { - command := REDISTRIBUTE_ADD +// SendRedistribute sends REDISTRIBUTE message to zebra daemon. +func (c *Client) SendRedistribute(t RouteType, vrfID uint32) error { + if c.redistDefault != t { - bodies := make([]*RedistributeBody, 0) + bodies := make([]*redistributeBody, 0) if c.Version <= 3 { - bodies = append(bodies, &RedistributeBody{ - Redist: t, + bodies = append(bodies, &redistributeBody{ + redist: t, }) - } else { // version >= 4 - command = FRR_REDISTRIBUTE_ADD - if c.Version == 5 { - command = FRR_ZAPI5_REDISTRIBUTE_ADD - } else if c.Version >= 6 { - command = FRR_ZAPI6_REDISTRIBUTE_ADD - } - for _, afi := range []AFI{AFI_IP, AFI_IP6} { - bodies = append(bodies, &RedistributeBody{ - Afi: afi, - Redist: t, - Instance: 0, + } else { // Version >= 4 + for _, afi := range []afi{afiIP, afiIP6} { + bodies = append(bodies, &redistributeBody{ + afi: afi, + redist: t, + instance: 0, }) } } for _, body := range bodies { - return c.SendCommand(command, vrfId, body) + return c.sendCommand(redistributeAdd, vrfID, body) } } - return nil } -func (c *Client) SendRedistributeDelete(t ROUTE_TYPE) error { - if t < ROUTE_MAX { - command := REDISTRIBUTE_DELETE - if c.Version == 4 { - command = FRR_REDISTRIBUTE_DELETE - } else if c.Version == 5 { - command = FRR_ZAPI5_REDISTRIBUTE_DELETE - } else if c.Version >= 6 { - command = FRR_ZAPI6_REDISTRIBUTE_DELETE - } - body := &RedistributeBody{ - Redist: t, - } - return c.SendCommand(command, VRF_DEFAULT, body) - } else { - return fmt.Errorf("unknown route type: %d", t) +// SendIPRoute sends ROUTE message to zebra daemon. +func (c *Client) SendIPRoute(vrfID uint32, body *IPRouteBody, isWithdraw bool) error { + routeFamily := body.RouteFamily(c.Version, c.SoftwareName) + if vrfID == DefaultVrf && (routeFamily == bgp.RF_IPv4_VPN || routeFamily == bgp.RF_IPv6_VPN) { + return fmt.Errorf("RF_IPv4_VPN or RF_IPv6_VPN are not suitable for Default VRF (default forwarding table)") } -} - -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 := RouteAdd + if isWithdraw { + command = RouteDelete } - command := IPV4_ROUTE_ADD - if c.Version <= 3 { - if body.Prefix.Prefix.To4() != nil { - if isWithdraw { - command = IPV4_ROUTE_DELETE - } - } else { - if isWithdraw { - command = IPV6_ROUTE_DELETE - } else { - command = IPV6_ROUTE_ADD - } - } - } else if c.Version == 4 { // version >= 4 - if body.Prefix.Prefix.To4() != nil { - if isWithdraw { - command = FRR_IPV4_ROUTE_DELETE - } else { - command = FRR_IPV4_ROUTE_ADD - } - } else { - if isWithdraw { - command = FRR_IPV6_ROUTE_DELETE - } else { - command = FRR_IPV6_ROUTE_ADD - } - } - } else { // version >= 5 (version 6 uses the same value as version 5) + if c.Version < 5 && familyFromPrefix(body.Prefix.Prefix) == syscall.AF_INET6 { + command = BackwardIPv6RouteAdd if isWithdraw { - command = FRR_ZAPI5_ROUTE_DELETE - } else { - command = FRR_ZAPI5_ROUTE_ADD + command = BackwardIPv6RouteDelete } } - return c.SendCommand(command, vrfId, body) + return c.sendCommand(command, vrfID, body) } -func (c *Client) SendNexthopRegister(vrfId uint32, body *NexthopRegisterBody, isWithdraw bool) error { - // Note: NEXTHOP_REGISTER and NEXTHOP_UNREGISTER messages are not +// SendNexthopRegister sends NEXTHOP_REGISTER message to zebra daemon. +func (c *Client) SendNexthopRegister(vrfID uint32, body *NexthopRegisterBody, isWithdraw bool) error { + // Note: NexthopRegister and NexthopUnregister messages are not // supported in Zebra protocol version<3. if c.Version < 3 { - return fmt.Errorf("NEXTHOP_REGISTER/NEXTHOP_UNREGISTER are not supported in version: %d", c.Version) + return fmt.Errorf("NexthopRegister/NexthopUnregister are not supported in version: %d", c.Version) } - command := NEXTHOP_REGISTER - if c.Version == 3 { - if isWithdraw { - command = NEXTHOP_UNREGISTER - } - } else if c.Version == 4 { // version == 4 - if isWithdraw { - command = FRR_NEXTHOP_UNREGISTER - } else { - command = FRR_NEXTHOP_REGISTER - } - } else if c.Version == 5 { // version == 5 - if isWithdraw { - command = FRR_ZAPI5_NEXTHOP_UNREGISTER - } else { - command = FRR_ZAPI5_NEXTHOP_REGISTER - } - } else { // version >= 6 - if isWithdraw { - command = FRR_ZAPI6_NEXTHOP_UNREGISTER - } else { - command = FRR_ZAPI6_NEXTHOP_REGISTER - } + command := nexthopRegister + if isWithdraw { + command = nexthopUnregister } - return c.SendCommand(command, vrfId, body) + 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 zebra API 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, - }) +// SupportMpls is referred in zclient. It returns bool value. +func (c *Client) SupportMpls() bool { + // Note: frr3&4 have LABEL_MANAGER_CONNECT& GET_LABEL_CHUNK. However + // Routes will not be installed via zebra of frr3&4 after call these APIs. + if c.Version < 5 || c.SoftwareName == "frr4" { + return false // if frr4 or ealier are used + } + return true // if frr5 or later are used } -// 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) SendLabelManagerConnectAsync() error { - if c.Version < 5 { - return fmt.Errorf("LABEL_MANAGER_CONNECT_ASYNC is not supported in zebra API version: %d", c.Version) - } - // ZAPIv5 has ZEBRA_LABEL_MANAGER_CONNECT_ASYNC, however frr4 (ZAPIv5) doesn't have it. - if c.SoftwareName == "frr4" { - return fmt.Errorf("LABEL_MANAGER_CONNECT_ASYNC is not supported in software: %s", c.SoftwareName) +// Ref: zread_label_manager_connect in zebra/zserv.c of FRR3 (ZAPI4) +// Ref: zread_label_manager_connect in zebra/zapi_msg.c of FRR5&6 (ZAPI5&6) +func (c *Client) sendLabelManagerConnect(async bool) error { + if c.Version < 4 { + return fmt.Errorf("LabelManagerConnect is not supported in zebra API version: %d", c.Version) } - command := FRR_ZAPI5_LABEL_MANAGER_CONNECT_ASYNC - proto := FRR_ZAPI5_ROUTE_BGP - if c.Version == 6 { - command = FRR_ZAPI6_LABEL_MANAGER_CONNECT_ASYNC - proto = FRR_ZAPI6_ROUTE_BGP + command := labelManagerConnectAsync + if !async || c.Version == 4 || (c.Version == 5 && c.SoftwareName == "frr4") { + command = labelManagerConnect } - return c.SendCommand( + return c.sendCommand( command, 0, - &LabelManagerConnectBody{ - RedistDefault: proto, - Instance: 0, + &labelManagerConnectBody{ + redistDefault: RouteBGP, + instance: 0, }) } +// SendGetLabelChunk sends GET_LABEL_CHUNK message to zebra daemon. 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) + return fmt.Errorf("GetLabelChunk 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) + body.instance = 0 + body.proto = uint8(RouteBGP) + return c.sendCommand(getLabelChunk, 0, body) } -func (c *Client) SendVrfLabel(label uint32, vrfId uint32) error { - body := &VrfLabelBody{ - Label: label, - Afi: AFI_IP, - LabelType: LSP_BGP, +// SendVrfLabel sends VRF_LABEL message to zebra daemon. +func (c *Client) SendVrfLabel(label uint32, vrfID uint32) error { + // ZAPIv5 has ZEBRA_VRF_LABEL, however frr4 (ZAPIv5) doesn't have it. + if c.Version < 5 || (c.Version == 5 && c.SoftwareName == "frr4") { + return fmt.Errorf("VrfLabel is not supported in zebra API version: %d software: %s", c.Version, c.SoftwareName) } - command := FRR_ZAPI5_VRF_LABEL - if c.Version == 6 { - command = FRR_ZAPI6_VRF_LABEL + body := &vrfLabelBody{ + label: label, + afi: afiIP, + labelType: lspBGP, } - return c.SendCommand(command, vrfId, body) + return c.sendCommand(vrfLabel, vrfID, body) } // for avoiding double close @@ -1533,20 +1516,30 @@ func closeChannel(ch chan *Message) bool { return false } -func (c *Client) Close() error { +func (c *Client) close() error { closeChannel(c.outgoing) return c.conn.Close() } +// 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 == "") { + nexthop.flags |= zapiNexthopFlagLabel + } else if c.Version > 4 { + *msgFlags |= MessageLabel + } +} + +// Header is header of zebra message. type Header struct { Len uint16 Marker uint8 Version uint8 - VrfId uint32 // ZAPI v4: 16bits, v5: 32bits - Command API_TYPE + VrfID uint32 // ZAPI v4: 16bits, v5: 32bits + Command APIType } -func (h *Header) Serialize() ([]byte, error) { +func (h *Header) serialize() ([]byte, error) { buf := make([]byte, HeaderSize(h.Version)) binary.BigEndian.PutUint16(buf[0:2], h.Len) buf[2] = h.Marker @@ -1555,10 +1548,10 @@ func (h *Header) Serialize() ([]byte, error) { case 2: binary.BigEndian.PutUint16(buf[4:6], uint16(h.Command)) case 3, 4: - binary.BigEndian.PutUint16(buf[4:6], uint16(h.VrfId)) + binary.BigEndian.PutUint16(buf[4:6], uint16(h.VrfID)) binary.BigEndian.PutUint16(buf[6:8], uint16(h.Command)) case 5, 6: - binary.BigEndian.PutUint32(buf[4:8], uint32(h.VrfId)) + binary.BigEndian.PutUint32(buf[4:8], uint32(h.VrfID)) binary.BigEndian.PutUint16(buf[8:10], uint16(h.Command)) default: return nil, fmt.Errorf("unsupported ZAPI version: %d", h.Version) @@ -1566,7 +1559,7 @@ func (h *Header) Serialize() ([]byte, error) { return buf, nil } -func (h *Header) DecodeFromBytes(data []byte) error { +func (h *Header) decodeFromBytes(data []byte) error { if uint16(len(data)) < 4 { return fmt.Errorf("not all ZAPI message header") } @@ -1578,202 +1571,193 @@ func (h *Header) DecodeFromBytes(data []byte) error { } switch h.Version { case 2: - h.Command = API_TYPE(binary.BigEndian.Uint16(data[4:6])) + h.Command = APIType(binary.BigEndian.Uint16(data[4:6])) case 3, 4: - h.VrfId = uint32(binary.BigEndian.Uint16(data[4:6])) - h.Command = API_TYPE(binary.BigEndian.Uint16(data[6:8])) + h.VrfID = uint32(binary.BigEndian.Uint16(data[4:6])) + h.Command = APIType(binary.BigEndian.Uint16(data[6:8])) case 5, 6: - h.VrfId = binary.BigEndian.Uint32(data[4:8]) - h.Command = API_TYPE(binary.BigEndian.Uint16(data[8:10])) + h.VrfID = binary.BigEndian.Uint32(data[4:8]) + h.Command = APIType(binary.BigEndian.Uint16(data[8:10])) default: return fmt.Errorf("unsupported ZAPI version: %d", h.Version) } return nil } +// Body is an interface for zebra messages. type Body interface { - DecodeFromBytes([]byte, uint8, string) error - Serialize(uint8, string) ([]byte, error) - String(uint8, string) string + decodeFromBytes([]byte, uint8, string) error + serialize(uint8, string) ([]byte, error) + string(uint8, string) string } -type UnknownBody struct { +type unknownBody struct { Data []byte } -func (b *UnknownBody) DecodeFromBytes(data []byte, version uint8, softwareName string) error { +func (b *unknownBody) decodeFromBytes(data []byte, version uint8, softwareName string) error { b.Data = data return nil } -func (b *UnknownBody) Serialize(version uint8, softwareName string) ([]byte, error) { +func (b *unknownBody) serialize(version uint8, softwareName string) ([]byte, error) { return b.Data, nil } -func (b *UnknownBody) String(version uint8, softwareName string) string { +func (b *unknownBody) string(version uint8, softwareName string) string { return fmt.Sprintf("data: %v", b.Data) } -type HelloBody struct { - RedistDefault ROUTE_TYPE - Instance uint16 - ReceiveNotify uint8 +type helloBody struct { + redistDefault RouteType + instance uint16 + receiveNotify uint8 } -// Reference: zread_hello function in zebra/zserv.c of Quagga1.2.x (ZAPI3) -// Reference: zread_hello function in zebra/zserv.c of FRR3.x (ZAPI4) -// Reference: zread_hello function in zebra/zapi_msg.c of FRR5.x (ZAPI5) -func (b *HelloBody) DecodeFromBytes(data []byte, version uint8, softwareName string) error { - b.RedistDefault = ROUTE_TYPE(data[0]) +// 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 { - b.Instance = binary.BigEndian.Uint16(data[1:3]) + b.instance = binary.BigEndian.Uint16(data[1:3]) if version >= 5 { - b.ReceiveNotify = data[3] + b.receiveNotify = data[3] } } return nil } -// Reference: zebra_hello_send function in lib/zclient.c of Quagga1.2.x (ZAPI3) -// Reference: zebra_hello_send function in lib/zclient.c of FRR3.x (ZAPI4) -// Reference: zebra_hello_send function in lib/zclient.c of FRR5.x (ZAPI5) -func (b *HelloBody) Serialize(version uint8, softwareName string) ([]byte, error) { - if version <= 3 { - return []byte{uint8(b.RedistDefault)}, nil - } else { // version >= 4 - var buf []byte - if version == 4 { - buf = make([]byte, 3) - } else if version >= 5 { - buf = make([]byte, 4) - } - buf[0] = uint8(b.RedistDefault) - binary.BigEndian.PutUint16(buf[1:3], b.Instance) - if version >= 5 { - buf[3] = b.ReceiveNotify - } - return buf, nil +// Ref: zebra_hello_send in lib/zclient.c of Quagga1.2&FRR3&FRR5 (ZAPI3&4&5) +func (b *helloBody) serialize(version uint8, softwareName string) ([]byte, error) { + if version < 4 { + return []byte{uint8(b.redistDefault)}, nil + } + var buf []byte + if version == 4 { + buf = make([]byte, 3) + } else if version > 4 { + buf = make([]byte, 4) } + buf[0] = uint8(b.redistDefault) + binary.BigEndian.PutUint16(buf[1:3], b.instance) + if version > 4 { + buf[3] = b.receiveNotify + } + return buf, nil } -func (b *HelloBody) String(version uint8, softwareName string) string { +func (b *helloBody) string(version uint8, softwareName string) string { return fmt.Sprintf( "route_type: %s, instance :%d", - b.RedistDefault.String(), b.Instance) + b.redistDefault.String(), b.instance) } -type RedistributeBody struct { - Afi AFI - Redist ROUTE_TYPE - Instance uint16 +type redistributeBody struct { + afi afi + redist RouteType + instance uint16 } -// Reference: zebra_redistribute_add function in zebra/redistribute.c of Quagga1.2.x (ZAPI3) -// Reference: zebra_redistribute_add function in zebra/redistribute.c of FRR3.x (ZAPI4) -// Reference: zebra_redistribute_add function in zebra/redistribute.c of FRR5.x (ZAPI5) -func (b *RedistributeBody) DecodeFromBytes(data []byte, version uint8, softwareName string) error { +// Ref: zebra_redistribute_add in zebra/redistribute.c of Quagga1.2&FRR3&FRR5 (ZAPI3&4&5) +func (b *redistributeBody) decodeFromBytes(data []byte, version uint8, softwareName string) error { if version <= 3 { - b.Redist = ROUTE_TYPE(data[0]) + b.redist = RouteType(data[0]) } else { // version >= 4 - b.Afi = AFI(data[0]) - b.Redist = ROUTE_TYPE(data[1]) - b.Instance = binary.BigEndian.Uint16(data[2:4]) + b.afi = afi(data[0]) + b.redist = RouteType(data[1]) + b.instance = binary.BigEndian.Uint16(data[2:4]) } return nil } -// Reference: zebra_redistribute_send function in lib/zclient.c of Quagga1.2.x (ZAPI3) -// Reference: zebra_redistribute_send function in lib/zclient.c of FRR3.x (ZAPI4) -// Reference: zebra_redistribute_send function in lib/zclient.c of FRR5.x (ZAPI5) -func (b *RedistributeBody) Serialize(version uint8, softwareName string) ([]byte, error) { - if version <= 3 { - return []byte{uint8(b.Redist)}, nil - } else { // version >= 4 - buf := make([]byte, 4) - buf[0] = uint8(b.Afi) - buf[1] = uint8(b.Redist) - binary.BigEndian.PutUint16(buf[2:4], b.Instance) - return buf, nil +// Ref: zebra_redistribute_send in lib/zclient.c of Quagga1.2&FRR3&FRR5 (ZAPI3&4&5) +func (b *redistributeBody) serialize(version uint8, softwareName string) ([]byte, error) { + if version < 4 { + return []byte{uint8(b.redist)}, nil } + buf := make([]byte, 4) + buf[0] = uint8(b.afi) + buf[1] = uint8(b.redist) + binary.BigEndian.PutUint16(buf[2:4], b.instance) + return buf, nil } -func (b *RedistributeBody) String(version uint8, softwareName string) string { +func (b *redistributeBody) string(version uint8, softwareName string) string { return fmt.Sprintf( "afi: %s, route_type: %s, instance :%d", - b.Afi.String(), b.Redist.String(), b.Instance) -} - -type LinkParam struct { - Status uint32 - TeMetric uint32 - MaxBw float32 - MaxRsvBw float32 - UnrsvBw [8]float32 - BwClassNum uint32 - AdminGroup uint32 - RemoteAS uint32 - RemoteIP net.IP - AveDelay uint32 - MinDelay uint32 - MaxDelay uint32 - DelayVar uint32 - PktLoss float32 - ResidualBw float32 - AvailableBw float32 - UseBw float32 -} - -type InterfaceUpdateBody struct { - Name string - Index uint32 - Status INTERFACE_STATUS - Flags uint64 - PTMEnable PTM_ENABLE - PTMStatus PTM_STATUS - Metric uint32 - Speed uint32 - MTU uint32 - MTU6 uint32 - Bandwidth uint32 - LinkIfindex uint32 - Linktype LINK_TYPE - HardwareAddr net.HardwareAddr - LinkParam LinkParam -} - -// Reference: zebra_interface_if_set_value function in lib/zclient.c of Quagga1.2.x (ZAPI4) -// Reference: zebra_interface_if_set_value function in lib/zclient.c of FRR3.x (ZAPI4) -// Reference: zebra_interface_if_set_value function in lib/zclient.c of FRR5.x (ZAPI5) -func (b *InterfaceUpdateBody) DecodeFromBytes(data []byte, version uint8, softwareName string) error { - if len(data) < INTERFACE_NAMSIZ+33 { - return fmt.Errorf("lack of bytes. need %d but %d", INTERFACE_NAMSIZ+29, len(data)) - } - - b.Name = strings.Trim(string(data[:INTERFACE_NAMSIZ]), "\u0000") - data = data[INTERFACE_NAMSIZ:] - b.Index = binary.BigEndian.Uint32(data[0:4]) - b.Status = INTERFACE_STATUS(data[4]) - b.Flags = binary.BigEndian.Uint64(data[5:13]) - if version >= 4 { - b.PTMEnable = PTM_ENABLE(data[13]) - b.PTMStatus = PTM_STATUS(data[14]) - b.Metric = binary.BigEndian.Uint32(data[15:19]) - b.Speed = binary.BigEndian.Uint32(data[19:23]) + b.afi.String(), b.redist.String(), b.instance) +} + +type linkParam struct { + status uint32 + teMetric uint32 + maxBw float32 + maxRsvBw float32 + unrsvBw [8]float32 + bwClassNum uint32 + adminGroup uint32 + remoteAS uint32 + remoteIP net.IP + aveDelay uint32 + minDelay uint32 + maxDelay uint32 + delayVar uint32 + pktLoss float32 + residualBw float32 + availableBw float32 + useBw float32 +} + +type interfaceUpdateBody struct { + name string + index uint32 + status interfaceStatus + flags uint64 + ptmEnable ptmEnable + ptmStatus ptmStatus + metric uint32 + speed uint32 + mtu uint32 + mtu6 uint32 + bandwidth uint32 + linkIfindex uint32 + linktype linkType + hardwareAddr net.HardwareAddr + linkParam linkParam +} + +// Ref: zebra_interface_if_set_value in lib/zclient.c of Quagga1.2&FRR3&FRR5 (ZAPI3&4&5) +func (b *interfaceUpdateBody) decodeFromBytes(data []byte, version uint8, softwareName string) error { + if len(data) < interfaceNameSize+33 { + return fmt.Errorf("lack of bytes. need %d but %d", interfaceNameSize+29, len(data)) + } + + b.name = strings.Trim(string(data[:interfaceNameSize]), "\u0000") + data = data[interfaceNameSize:] + b.index = binary.BigEndian.Uint32(data[0:4]) + b.status = interfaceStatus(data[4]) + b.flags = binary.BigEndian.Uint64(data[5:13]) + if version > 3 { + b.ptmEnable = ptmEnable(data[13]) + b.ptmStatus = ptmStatus(data[14]) + b.metric = binary.BigEndian.Uint32(data[15:19]) + b.speed = binary.BigEndian.Uint32(data[19:23]) data = data[23:] } else { - b.Metric = binary.BigEndian.Uint32(data[13:17]) + b.metric = binary.BigEndian.Uint32(data[13:17]) data = data[17:] } - b.MTU = binary.BigEndian.Uint32(data[0:4]) - b.MTU6 = binary.BigEndian.Uint32(data[4:8]) - b.Bandwidth = binary.BigEndian.Uint32(data[8:12]) + b.mtu = binary.BigEndian.Uint32(data[0:4]) + 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" { - b.LinkIfindex = binary.BigEndian.Uint32(data[:4]) + if version == 6 && + (softwareName == "frr7.2" || softwareName == "frr7.3" || softwareName == "") { //link Ifindex + b.linkIfindex = binary.BigEndian.Uint32(data[:4]) data = data[4:] } - if version >= 3 { - b.Linktype = LINK_TYPE(binary.BigEndian.Uint32(data[:4])) + if version > 2 { + b.linktype = linkType(binary.BigEndian.Uint32(data[:4])) data = data[4:] } l := binary.BigEndian.Uint32(data[:4]) @@ -1781,287 +1765,457 @@ func (b *InterfaceUpdateBody) DecodeFromBytes(data []byte, version uint8, softwa if len(data) < 4+int(l) { return fmt.Errorf("lack of bytes in remain data. need %d but %d", 4+l, len(data)) } - b.HardwareAddr = data[4 : 4+l] + b.hardwareAddr = data[4 : 4+l] } - if version >= 3 { - LinkParam := data[4+l] - if LinkParam > 0 { + if version > 2 { + linkParam := data[4+l] + if linkParam > 0 { data = data[5+l:] - b.LinkParam.Status = binary.BigEndian.Uint32(data[0:4]) - b.LinkParam.TeMetric = binary.BigEndian.Uint32(data[4:8]) - b.LinkParam.MaxBw = math.Float32frombits(binary.BigEndian.Uint32(data[8:12])) - b.LinkParam.MaxRsvBw = math.Float32frombits(binary.BigEndian.Uint32(data[12:16])) - b.LinkParam.BwClassNum = binary.BigEndian.Uint32(data[16:20]) - for i := uint32(0); i < b.LinkParam.BwClassNum; i++ { - b.LinkParam.UnrsvBw[i] = math.Float32frombits(binary.BigEndian.Uint32(data[20+i*4 : 24+i*4])) + b.linkParam.status = binary.BigEndian.Uint32(data[0:4]) + b.linkParam.teMetric = binary.BigEndian.Uint32(data[4:8]) + b.linkParam.maxBw = math.Float32frombits(binary.BigEndian.Uint32(data[8:12])) + b.linkParam.maxRsvBw = math.Float32frombits(binary.BigEndian.Uint32(data[12:16])) + b.linkParam.bwClassNum = binary.BigEndian.Uint32(data[16:20]) + for i := uint32(0); i < b.linkParam.bwClassNum; i++ { + b.linkParam.unrsvBw[i] = math.Float32frombits(binary.BigEndian.Uint32(data[20+i*4 : 24+i*4])) } - data = data[20+b.LinkParam.BwClassNum*4:] - b.LinkParam.AdminGroup = binary.BigEndian.Uint32(data[0:4]) - b.LinkParam.RemoteAS = binary.BigEndian.Uint32(data[4:8]) - b.LinkParam.RemoteIP = data[8:12] - b.LinkParam.AveDelay = binary.BigEndian.Uint32(data[12:16]) - b.LinkParam.MinDelay = binary.BigEndian.Uint32(data[16:20]) - b.LinkParam.MaxDelay = binary.BigEndian.Uint32(data[20:24]) - b.LinkParam.DelayVar = binary.BigEndian.Uint32(data[24:28]) - b.LinkParam.PktLoss = math.Float32frombits(binary.BigEndian.Uint32(data[28:32])) - b.LinkParam.ResidualBw = math.Float32frombits(binary.BigEndian.Uint32(data[32:36])) - b.LinkParam.AvailableBw = math.Float32frombits(binary.BigEndian.Uint32(data[36:40])) - b.LinkParam.UseBw = math.Float32frombits(binary.BigEndian.Uint32(data[40:44])) + data = data[20+b.linkParam.bwClassNum*4:] + b.linkParam.adminGroup = binary.BigEndian.Uint32(data[0:4]) + b.linkParam.remoteAS = binary.BigEndian.Uint32(data[4:8]) + b.linkParam.remoteIP = data[8:12] + b.linkParam.aveDelay = binary.BigEndian.Uint32(data[12:16]) + b.linkParam.minDelay = binary.BigEndian.Uint32(data[16:20]) + b.linkParam.maxDelay = binary.BigEndian.Uint32(data[20:24]) + b.linkParam.delayVar = binary.BigEndian.Uint32(data[24:28]) + b.linkParam.pktLoss = math.Float32frombits(binary.BigEndian.Uint32(data[28:32])) + b.linkParam.residualBw = math.Float32frombits(binary.BigEndian.Uint32(data[32:36])) + b.linkParam.availableBw = math.Float32frombits(binary.BigEndian.Uint32(data[36:40])) + b.linkParam.useBw = math.Float32frombits(binary.BigEndian.Uint32(data[40:44])) } } return nil } -func (b *InterfaceUpdateBody) Serialize(version uint8, softwareName string) ([]byte, error) { +func (b *interfaceUpdateBody) serialize(version uint8, softwareName string) ([]byte, error) { return []byte{}, nil } -func (b *InterfaceUpdateBody) String(version uint8, softwareName string) string { +func (b *interfaceUpdateBody) string(version uint8, softwareName string) string { s := fmt.Sprintf( "name: %s, idx: %d, status: %s, flags: %s, ptm_enable: %s, ptm_status: %s, metric: %d, speed: %d, mtu: %d, mtu6: %d, bandwidth: %d, linktype: %s", - b.Name, b.Index, b.Status.String(), intfflag2string(b.Flags), b.PTMEnable.String(), b.PTMStatus.String(), b.Metric, b.Speed, b.MTU, b.MTU6, b.Bandwidth, b.Linktype.String()) - if len(b.HardwareAddr) > 0 { - return s + fmt.Sprintf(", mac: %s", b.HardwareAddr.String()) + b.name, b.index, b.status.String(), intfflag2string(b.flags), b.ptmEnable.String(), b.ptmStatus.String(), b.metric, b.speed, b.mtu, b.mtu6, b.bandwidth, b.linktype.String()) + if len(b.hardwareAddr) > 0 { + return s + fmt.Sprintf(", mac: %s", b.hardwareAddr.String()) } return s } -type InterfaceAddressUpdateBody struct { - Index uint32 - Flags INTERFACE_ADDRESS_FLAG - Prefix net.IP - Length uint8 - Destination net.IP +type interfaceAddressUpdateBody struct { + index uint32 + flags interfaceAddressFlag + prefix net.IP + length uint8 + destination net.IP } -// Reference: zebra_interface_address_read function in lib/zclient.c of Quagga1.2.x (ZAPI4) -// Reference: zebra_interface_address_read function in lib/zclient.c of FRR3.x (ZAPI4) -// Reference: zebra_interface_address_read function in lib/zclient.c of FRR5.x (ZAPI5) -func (b *InterfaceAddressUpdateBody) DecodeFromBytes(data []byte, version uint8, softwareName string) error { - b.Index = binary.BigEndian.Uint32(data[:4]) - b.Flags = INTERFACE_ADDRESS_FLAG(data[4]) +// Ref: zebra_interface_address_read in lib/zclient.c of Quagga1.2&FRR3&FRR5 (ZAPI3&4&5) +func (b *interfaceAddressUpdateBody) decodeFromBytes(data []byte, version uint8, softwareName string) error { + b.index = binary.BigEndian.Uint32(data[:4]) + b.flags = interfaceAddressFlag(data[4]) family := data[5] addrlen, err := addressByteLength(family) if err != nil { return err } - b.Prefix = data[6 : 6+addrlen] - b.Length = data[6+addrlen] - b.Destination = data[7+addrlen : 7+addrlen*2] + b.prefix = data[6 : 6+addrlen] + b.length = data[6+addrlen] + b.destination = data[7+addrlen : 7+addrlen*2] return nil } -func (b *InterfaceAddressUpdateBody) Serialize(version uint8, softwareName string) ([]byte, error) { +func (b *interfaceAddressUpdateBody) serialize(version uint8, softwareName string) ([]byte, error) { return []byte{}, nil } -func (b *InterfaceAddressUpdateBody) String(version uint8, softwareName string) string { +func (b *interfaceAddressUpdateBody) string(version uint8, softwareName string) string { return fmt.Sprintf( "idx: %d, flags: %s, addr: %s/%d", - b.Index, b.Flags.String(), b.Prefix.String(), b.Length) + b.index, b.flags.String(), b.prefix.String(), b.length) } -type RouterIDUpdateBody struct { - Length uint8 - Prefix net.IP +type routerIDUpdateBody struct { + length uint8 + prefix net.IP } -// Reference: zebra_router_id_update_read function in lib/zclient.c of Quagga1.2.x (ZAPI4) -// Reference: zebra_router_id_update_read function in lib/zclient.c of FRR3.x (ZAPI4) -// Reference: zebra_router_id_update_read function in lib/zclient.c of FRR5.x (ZAPI5) -func (b *RouterIDUpdateBody) DecodeFromBytes(data []byte, version uint8, softwareName string) error { +// Ref: zebra_router_id_update_read in lib/zclient.c of Quagga1.2&FRR3&FRR5 (ZAPI3&4&5) +func (b *routerIDUpdateBody) decodeFromBytes(data []byte, version uint8, softwareName string) error { family := data[0] addrlen, err := addressByteLength(family) if err != nil { return err } - b.Prefix = data[1 : 1+addrlen] - b.Length = data[1+addrlen] + b.prefix = data[1 : 1+addrlen] + b.length = data[1+addrlen] return nil } -func (b *RouterIDUpdateBody) Serialize(version uint8, softwareName string) ([]byte, error) { +func (b *routerIDUpdateBody) serialize(version uint8, softwareName string) ([]byte, error) { return []byte{}, nil } -func (b *RouterIDUpdateBody) String(version uint8, softwareName string) string { - return fmt.Sprintf("id: %s/%d", b.Prefix.String(), b.Length) +func (b *routerIDUpdateBody) string(version uint8, softwareName string) string { + return fmt.Sprintf("id: %s/%d", b.prefix.String(), b.length) } -/* - Reference: struct zapi_nexthop in lib/zclient.h of FRR5.x (ZAPI5) -*/ +const ( + zapiNexthopFlagOnlink uint8 = 0x01 // frr7.1, 7.2, 7.3 + zapiNexthopFlagLabel uint8 = 0x02 // frr7.3 + zapiNexthopFlagWeight uint8 = 0x04 // frr7.3 +) + +// Flag for nexthop processing. It is gobgp's internal flag. +type nexthopProcessFlag uint8 + +const ( + nexthopHasType nexthopProcessFlag = 0x01 + nexthopHasVrfID nexthopProcessFlag = 0x02 + nexthopHasFlag nexthopProcessFlag = 0x04 + nexthopHasOnlink nexthopProcessFlag = 0x08 + nexthopProcessIPToIPIFindex nexthopProcessFlag = 0x10 + nexthopProcessIFnameToIFindex nexthopProcessFlag = 0x20 // for quagga +) + +func nexthopProcessFlagForIPRouteBody(version uint8, softwareName string, isDecode bool) nexthopProcessFlag { + if version < 5 { + if isDecode { + return nexthopProcessFlag(0) // frr3&quagga don't have type&vrfid + } + return nexthopHasType // frr3&quagga need type for encode(serialize) + } + processFlag := (nexthopHasVrfID | nexthopHasType) // frr4, 5, 6, 7 + if version == 6 { + switch softwareName { + case "frr7.3", "": + processFlag |= (nexthopHasFlag | nexthopProcessIPToIPIFindex) + case "frr7.2", "frr7.1", "frr7.0": + processFlag |= nexthopHasOnlink + } + } + return processFlag +} + +// Nexthop is referred in zclient (Ref: struct zapi_nexthop in lib/zclient.h of FRR5.x (ZAPI5)) type Nexthop struct { - Type NEXTHOP_TYPE - VrfId uint32 - Ifindex uint32 + Type nexthopType + VrfID uint32 + Ifindex uint32 // Ifindex is referred in zclient_test Gate net.IP - BlackholeType uint8 + flags uint8 + blackholeType uint8 LabelNum uint8 MplsLabels []uint32 - Onlink uint8 + weight uint32 + rmac [6]byte } -func (n *Nexthop) String() string { +func (n Nexthop) string() string { s := make([]string, 0) s = append(s, fmt.Sprintf( "type: %s, gate: %s, ifindex: %d, vrf_id: %d, label_num: %d", - n.Type.String(), n.Gate.String(), n.Ifindex, n.VrfId, n.LabelNum)) + n.Type.String(), n.Gate.String(), n.Ifindex, n.VrfID, n.LabelNum)) for i := uint8(0); i < n.LabelNum; i++ { s = append(s, fmt.Sprintf("label: %d", n.MplsLabels[i])) } return strings.Join(s, ", ") } +func (n Nexthop) gateToType(version uint8) nexthopType { + if n.Gate.To4() != nil { + if version > 4 && n.Ifindex > 0 { + return nexthopTypeIPv4IFIndex + } + return nexthopTypeIPv4.toEach(version) + } else if n.Gate.To16() != nil { + if version > 4 && n.Ifindex > 0 { + return nexthopTypeIPv6IFIndex + } + return nexthopTypeIPv6.toEach(version) + } else if n.Ifindex > 0 { + return nexthopTypeIFIndex.toEach(version) + } else if version > 4 { + return nexthopTypeBlackhole + } + return nexthopType(0) +} +// Ref: zapi_nexthop_encode in lib/zclient.h of FRR7.3 +func (n Nexthop) encode(version uint8, softwareName string, processFlag nexthopProcessFlag, message MessageFlag, apiFlag Flag) []byte { + var buf []byte + if processFlag&nexthopHasVrfID > 0 { + tmpbuf := make([]byte, 4) + binary.BigEndian.PutUint32(tmpbuf, n.VrfID) + buf = append(buf, tmpbuf...) + } + if processFlag&nexthopHasType > 0 { + if n.Type == nexthopType(0) { + n.Type = n.gateToType(version) + } + buf = append(buf, uint8(n.Type)) + } + if processFlag&nexthopHasFlag > 0 { + if n.LabelNum > 0 { + n.flags |= zapiNexthopFlagLabel + } + if n.weight > 0 { + n.flags |= zapiNexthopFlagWeight + } + } + if processFlag&nexthopHasFlag > 0 || processFlag&nexthopHasOnlink > 0 { + buf = append(buf, n.flags) // frr7.1, 7.2 has onlink, 7.3 has flag + } + + nhType := n.Type + if processFlag&nexthopProcessIPToIPIFindex > 0 { + nhType = nhType.ipToIPIFIndex() + } + if processFlag&nexthopProcessIFnameToIFindex > 0 { + nhType = nhType.ifNameToIFIndex() + } + if nhType == nexthopTypeIPv4.toEach(version) || + nhType == nexthopTypeIPv4IFIndex.toEach(version) { + buf = append(buf, n.Gate.To4()...) + } else if nhType == nexthopTypeIPv6.toEach(version) || + nhType == nexthopTypeIPv6IFIndex.toEach(version) { + buf = append(buf, n.Gate.To16()...) + } + if nhType == nexthopTypeIFIndex || + nhType == nexthopTypeIPv4IFIndex.toEach(version) || + nhType == nexthopTypeIPv6IFIndex.toEach(version) { + tmpbuf := make([]byte, 4) + binary.BigEndian.PutUint32(tmpbuf, n.Ifindex) + buf = append(buf, tmpbuf...) + } + if nhType == nexthopTypeBlackhole.toEach(version) { + buf = append(buf, uint8(n.blackholeType)) + } + if n.flags&zapiNexthopFlagLabel > 0 || message&MessageLabel > 0 { + tmpbuf := make([]byte, 1+4*n.LabelNum) + tmpbuf[0] = n.LabelNum + 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]) + } + 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...) + } + if apiFlag&flagEvpnRoute.ToEach(version, softwareName) > 0 { + buf = append(buf, n.rmac[:]...) + } + return buf +} + +// Ref: zapi_nexthop_decode in lib/zclient.h of FRR7.3 +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 { + 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]) + offset++ + } + + n.flags = uint8(0) + if processFlag&nexthopHasFlag > 0 || processFlag&nexthopHasOnlink > 0 { + n.flags = uint8(data[offset]) + offset++ + } + + nhType = n.Type + if processFlag&nexthopProcessIPToIPIFindex > 0 { + nhType = nhType.ipToIPIFIndex() + } + if processFlag&nexthopProcessIFnameToIFindex > 0 { + nhType = nhType.ifNameToIFIndex() + } + if family == syscall.AF_INET { + n.Gate = net.ParseIP("0.0.0.0") + } else if family == syscall.AF_INET6 { + n.Gate = net.ParseIP("::") + } + if nhType == nexthopTypeIPv4.toEach(version) || + nhType == nexthopTypeIPv4IFIndex.toEach(version) { + n.Gate = net.IP(data[offset : offset+4]).To4() + offset += 4 + } else if nhType == nexthopTypeIPv6.toEach(version) || + nhType == nexthopTypeIPv6IFIndex.toEach(version) { + n.Gate = net.IP(data[offset : offset+16]).To16() + offset += 16 + } + if nhType == nexthopTypeIFIndex || + nhType == nexthopTypeIPv4IFIndex.toEach(version) || + nhType == nexthopTypeIPv6IFIndex.toEach(version) { + n.Ifindex = binary.BigEndian.Uint32(data[offset : offset+4]) + offset += 4 + } + if nhType == nexthopTypeBlackhole.toEach(version) { + n.blackholeType = data[offset] + offset++ + } + if n.flags&zapiNexthopFlagLabel > 0 || message&MessageLabel > 0 { + n.LabelNum = uint8(data[offset]) + offset++ + if n.LabelNum > maxMplsLabel { + n.LabelNum = maxMplsLabel + } + if n.LabelNum > 0 { + n.MplsLabels = make([]uint32, n.LabelNum) + 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. + n.MplsLabels[i] = binary.LittleEndian.Uint32(data[offset : offset+4]) + offset += 4 + } + } + } + if n.flags&zapiNexthopFlagWeight > 0 { + n.weight = binary.BigEndian.Uint32(data[offset:]) + } + if apiFlag&flagEvpnRoute.ToEach(version, softwareName) > 0 { + copy(n.rmac[0:], data[offset:offset+6]) + } + return offset, nil +} + +// Ref: zapi_nexthop_update_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 + *nexthops = make([]Nexthop, numNexthop) + for i := uint16(0); i < numNexthop; i++ { + size, err := (&((*nexthops)[i])).decode(data[offset:], version, softwareName, family, processFlag, message, apiFlag, nhType) + if err != nil { + return offset, err + } + offset += size + } + return offset, nil +} + +// Prefix referred in zclient is struct for network prefix and relate information type Prefix struct { Family uint8 PrefixLen uint8 Prefix net.IP } +func familyFromPrefix(prefix net.IP) uint8 { + if prefix.To4() != nil { + return syscall.AF_INET + } else if prefix.To16() != nil { + return syscall.AF_INET6 + } + return syscall.AF_UNSPEC +} + +// IPRouteBody is struct for IPRotue (zapi_route) type IPRouteBody struct { - Type ROUTE_TYPE - Instance uint16 - Flags FLAG - Message MESSAGE_FLAG - SAFI SAFI + Type RouteType + instance uint16 + Flags Flag + Message MessageFlag + Safi Safi Prefix Prefix - SrcPrefix Prefix + srcPrefix Prefix Nexthops []Nexthop Distance uint8 Metric uint32 Mtu uint32 - Tag uint32 - Rmac [6]byte - Api API_TYPE + 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 + } + if b.Safi <= safiMulticast || version > 4 { // not need to convert + return b.Safi + } + safiMap := zapi4SafiMap + if version < 4 { + safiMap = zapi3SafiMap + } + safi, ok := safiMap[b.Safi] + if !ok { + safi = safiUnspec // failed to convert + } + log.WithFields(log.Fields{ + "Topic": "Zebra", + "Body": b, + }).Debugf("zebra converts safi: %s -> %s", b.Safi.String(), safi.String()) + return safi // success to convert } -func (b *IPRouteBody) RouteFamily(version uint8) bgp.RouteFamily { +// RouteFamily is referred in zclient +func (b *IPRouteBody) RouteFamily(version uint8, softwareName string) bgp.RouteFamily { if b == nil { - return bgp.RF_OPAQUE + return bgp.RF_OPAQUE // fail } - family := addressFamilyFromApi(b.Api, version) + safi := b.safi(version, softwareName) + if safi == safiEvpn { + return bgp.RF_EVPN // sucess + } + family := b.Prefix.Family if family == syscall.AF_UNSPEC { - if b.Prefix.Prefix.To4() != nil { - family = syscall.AF_INET - } else if b.Prefix.Prefix.To16() != nil { - family = syscall.AF_INET6 - } + family = familyFromPrefix(b.Prefix.Prefix) } - 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 - default: - return bgp.RF_IPv4_UC - } - 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: - return bgp.RF_IPv6_UC - } - 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 - default: - return bgp.RF_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: - return bgp.RF_IPv6_UC - } - default: - switch b.SAFI { - case FRR_ZAPI5_SAFI_EVPN: - return bgp.RF_EVPN - default: - return bgp.RF_OPAQUE - } - } + if family == syscall.AF_UNSPEC { // familyFromPrefix returs AF_UNSPEC + return bgp.RF_OPAQUE // fail + } + safiRouteFamilyMap := safiRouteFamilyIPv4Map // syscall.AF_INET + if family == syscall.AF_INET6 { + safiRouteFamilyMap = safiRouteFamilyIPv6Map + } + rf, ok := safiRouteFamilyMap[safi] + if !ok { + return bgp.RF_OPAQUE // fail } + log.WithFields(log.Fields{ + "Topic": "Zebra", + "Body": b, + }).Debugf("zebra converts safi:%s -> rf: %s", safi.String(), rf.String()) + return rf // sucess } -func (b *IPRouteBody) IsWithdraw(version uint8) bool { - if version <= 3 { - switch b.Api { - case IPV4_ROUTE_DELETE, IPV6_ROUTE_DELETE: - return true - } - } else if version == 4 { - switch b.Api { - case FRR_IPV4_ROUTE_DELETE, FRR_IPV6_ROUTE_DELETE, FRR_REDISTRIBUTE_IPV4_DEL, FRR_REDISTRIBUTE_IPV6_DEL: - return true - } - } else if version == 5 { - switch b.Api { - case FRR_ZAPI5_ROUTE_DELETE, FRR_ZAPI5_IPV4_ROUTE_DELETE, FRR_ZAPI5_IPV6_ROUTE_DELETE, FRR_ZAPI5_REDISTRIBUTE_ROUTE_DEL: - return true - } - } else if version >= 6 { - switch b.Api { - case FRR_ZAPI6_ROUTE_DELETE, FRR_ZAPI6_REDISTRIBUTE_ROUTE_DEL: - return true - } +// IsWithdraw is referred in zclient +func (b *IPRouteBody) IsWithdraw(version uint8, softwareName string) bool { + api := b.API.toCommon(version, softwareName) + switch api { + case RouteDelete, redistributeRouteDel, BackwardIPv6RouteDelete: + return true + } + if version == 4 && b.API == zapi4RedistributeIPv6Del { + return true } return false } -// Reference: zapi_ipv4_route function in lib/zclient.c of Quagga1.2.x (ZAPI3) -// Reference: zapi_ipv4_route function in lib/zclient.c of FRR3.x (ZAPI4) -// Reference: zapi_route_encode function in lib/zclient.c of FRR5.x (ZAPI5) -func (b *IPRouteBody) Serialize(version uint8, softwareName string) ([]byte, error) { +// Ref: zapi_ipv4_route in lib/zclient.c of Quagga1.2.x&FRR3.x(ZAPI3&4) +// Ref: zapi_route_encode in lib/zclient.c of FRR5.x (ZAPI5) +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 { @@ -2070,28 +2224,24 @@ func (b *IPRouteBody) Serialize(version uint8, softwareName string) ([]byte, err buf = make([]byte, 9) } buf[0] = uint8(b.Type) - if version <= 3 { + if version < 4 { buf[1] = uint8(b.Flags) buf[2] = uint8(b.Message) - binary.BigEndian.PutUint16(buf[3:5], uint16(b.SAFI)) + binary.BigEndian.PutUint16(buf[3:5], uint16(b.Safi)) } else { // version >= 4 - binary.BigEndian.PutUint16(buf[1:3], uint16(b.Instance)) + binary.BigEndian.PutUint16(buf[1:3], uint16(b.instance)) binary.BigEndian.PutUint32(buf[3:7], uint32(b.Flags)) buf[7] = uint8(b.Message) if version == 4 { - binary.BigEndian.PutUint16(buf[8:10], uint16(b.SAFI)) + binary.BigEndian.PutUint16(buf[8:10], uint16(b.Safi)) } else { // version >= 5 - buf[8] = uint8(b.SAFI) - if b.Flags&FLAG_EVPN_ROUTE > 0 { + buf[8] = uint8(b.Safi) + 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.Rmac[:6]...) + buf = append(buf, b.Nexthops[numNexthop-1].rmac[:6]...) } if b.Prefix.Family == syscall.AF_UNSPEC { - if b.Prefix.Prefix.To4() != nil { - b.Prefix.Family = syscall.AF_INET - } else if b.Prefix.Prefix.To16() != nil { - b.Prefix.Family = syscall.AF_INET6 - } + b.Prefix.Family = familyFromPrefix(b.Prefix.Prefix) } buf = append(buf, b.Prefix.Family) } @@ -2100,165 +2250,75 @@ func (b *IPRouteBody) Serialize(version uint8, softwareName string) ([]byte, err buf = append(buf, b.Prefix.PrefixLen) buf = append(buf, b.Prefix.Prefix[:byteLen]...) - if (version == 4 && b.Message&FRR_MESSAGE_SRCPFX > 0) || - (version >= 5 && b.Message&FRR_ZAPI5_MESSAGE_SRCPFX > 0) { - byteLen = (int(b.SrcPrefix.PrefixLen) + 7) / 8 - buf = append(buf, b.SrcPrefix.PrefixLen) - buf = append(buf, b.SrcPrefix.Prefix[:byteLen]...) + if version > 3 && b.Message&messageSRCPFX.ToEach(version) > 0 { + byteLen = (int(b.srcPrefix.PrefixLen) + 7) / 8 + buf = append(buf, b.srcPrefix.PrefixLen) + buf = append(buf, b.srcPrefix.Prefix[:byteLen]...) } - if (version <= 3 && b.Message&MESSAGE_NEXTHOP > 0) || - (version == 4 && b.Message&FRR_MESSAGE_NEXTHOP > 0) || - (version >= 5 && b.Message&FRR_ZAPI5_MESSAGE_NEXTHOP > 0) { + if b.Message&MessageNexthop > 0 { + processFlag := nexthopProcessFlagForIPRouteBody(version, softwareName, false) if version < 5 { - if b.Flags&FLAG_BLACKHOLE > 0 { - buf = append(buf, []byte{1, uint8(NEXTHOP_TYPE_BLACKHOLE)}...) + if b.Flags&flagBlackhole > 0 { + buf = append(buf, []byte{1, uint8(nexthopTypeBlackhole.toEach(version))}...) } else { - buf = append(buf, uint8(len(b.Nexthops))) + buf = append(buf, uint8(numNexthop)) } } else { // version >= 5 - bbuf := make([]byte, 2) - binary.BigEndian.PutUint16(bbuf, uint16(len(b.Nexthops))) - buf = append(buf, bbuf...) + tmpbuf := make([]byte, 2) + binary.BigEndian.PutUint16(tmpbuf, uint16(numNexthop)) + buf = append(buf, tmpbuf...) } for _, nexthop := range b.Nexthops { - if version >= 5 { - bbuf := make([]byte, 4) - binary.BigEndian.PutUint32(bbuf, nexthop.VrfId) - buf = append(buf, bbuf...) - } - - if nexthop.Type == NEXTHOP_TYPE(0) { - if nexthop.Gate.To4() != nil { - if version <= 3 { - nexthop.Type = NEXTHOP_TYPE_IPV4 - } else { - nexthop.Type = FRR_NEXTHOP_TYPE_IPV4 - } - if version >= 5 && nexthop.Ifindex > 0 { - nexthop.Type = FRR_NEXTHOP_TYPE_IPV4_IFINDEX - } - } else if nexthop.Gate.To16() != nil { - if version <= 3 { - nexthop.Type = NEXTHOP_TYPE_IPV6 - } else { - nexthop.Type = FRR_NEXTHOP_TYPE_IPV6 - } - if version >= 5 && nexthop.Ifindex > 0 { - nexthop.Type = FRR_NEXTHOP_TYPE_IPV6_IFINDEX - } - } else if nexthop.Ifindex > 0 { - if version <= 3 { - nexthop.Type = NEXTHOP_TYPE_IFINDEX - } else { - nexthop.Type = FRR_NEXTHOP_TYPE_IFINDEX - } - } else if version >= 5 { - nexthop.Type = FRR_NEXTHOP_TYPE_BLACKHOLE - } - } - - buf = append(buf, uint8(nexthop.Type)) - - if version == 6 && (softwareName == "frr7.1" || softwareName == "frr7.2") { - buf = append(buf, nexthop.Onlink) - } - if (version <= 3 && nexthop.Type == NEXTHOP_TYPE_IPV4) || - (version >= 4 && nexthop.Type == FRR_NEXTHOP_TYPE_IPV4) { - buf = append(buf, nexthop.Gate.To4()...) - } else if (version <= 3 && nexthop.Type == NEXTHOP_TYPE_IPV6) || - (version >= 4 && nexthop.Type == FRR_NEXTHOP_TYPE_IPV6) { - buf = append(buf, nexthop.Gate.To16()...) - } else if (version <= 3 && nexthop.Type == NEXTHOP_TYPE_IFINDEX) || - (version >= 4 && nexthop.Type == FRR_NEXTHOP_TYPE_IFINDEX) { - bbuf := make([]byte, 4) - binary.BigEndian.PutUint32(bbuf, nexthop.Ifindex) - buf = append(buf, bbuf...) - } else if version >= 5 && nexthop.Type == FRR_NEXTHOP_TYPE_IPV4_IFINDEX { - buf = append(buf, nexthop.Gate.To4()...) - bbuf := make([]byte, 4) - binary.BigEndian.PutUint32(bbuf, nexthop.Ifindex) - buf = append(buf, bbuf...) - } else if version >= 5 && nexthop.Type == FRR_NEXTHOP_TYPE_IPV6_IFINDEX { - buf = append(buf, nexthop.Gate.To16()...) - bbuf := make([]byte, 4) - binary.BigEndian.PutUint32(bbuf, nexthop.Ifindex) - buf = append(buf, bbuf...) - } else if version >= 5 && nexthop.Type == FRR_NEXTHOP_TYPE_BLACKHOLE { - buf = append(buf, uint8(nexthop.BlackholeType)) - } - if version >= 5 && b.Message&FRR_ZAPI5_MESSAGE_LABEL > 0 { - buf = append(buf, nexthop.LabelNum) - 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) || - (version == 4 && b.Message&FRR_MESSAGE_DISTANCE > 0) || - (version >= 5 && b.Message&FRR_ZAPI5_MESSAGE_DISTANCE > 0) { - buf = append(buf, b.Distance) - } - if (version <= 3 && b.Message&MESSAGE_METRIC > 0) || - (version == 4 && b.Message&FRR_MESSAGE_METRIC > 0) || - (version >= 5 && b.Message&FRR_ZAPI5_MESSAGE_METRIC > 0) { - bbuf := make([]byte, 4) - binary.BigEndian.PutUint32(bbuf, b.Metric) - buf = append(buf, bbuf...) - } - if (version <= 3 && b.Message&MESSAGE_MTU > 0) || - (version == 4 && b.Message&FRR_MESSAGE_MTU > 0) || - (version >= 5 && b.Message&FRR_ZAPI5_MESSAGE_MTU > 0) { - bbuf := make([]byte, 4) - binary.BigEndian.PutUint32(bbuf, b.Mtu) - buf = append(buf, bbuf...) - } - if (version <= 3 && b.Message&MESSAGE_TAG > 0) || - (version == 4 && b.Message&FRR_MESSAGE_TAG > 0) || - (version >= 5 && b.Message&FRR_ZAPI5_MESSAGE_TAG > 0) { - bbuf := make([]byte, 4) - binary.BigEndian.PutUint32(bbuf, b.Tag) - buf = append(buf, bbuf...) + buf = append(buf, nexthop.encode(version, softwareName, processFlag, b.Message, b.Flags)...) } } + if b.Message&MessageDistance.ToEach(version) > 0 { + buf = append(buf, b.Distance) + } + if b.Message&MessageMetric.ToEach(version) > 0 { + tmpbuf := make([]byte, 4) + binary.BigEndian.PutUint32(tmpbuf, b.Metric) + 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 { + tmpbuf := make([]byte, 4) + binary.BigEndian.PutUint32(tmpbuf, b.tag) + buf = append(buf, tmpbuf...) + } return buf, nil } -// Reference: zebra_read_ipv4 function in bgpd/bgp_zebra.c of Quagga1.2.x (ZAPI3) -// Reference: zebra_read_ipv4 function in bgpd/bgp_zebra.c of FRR4.x (ZAPI4) -// Reference: zapi_route_decode function in lib/zclient.c of FRR5.x (ZAPI5) -func (b *IPRouteBody) DecodeFromBytes(data []byte, version uint8, softwareName string) error { +// 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") } - b.Prefix.Family = addressFamilyFromApi(b.Api, version) - /* REDSTRIBUTE_IPV4_ADD|DEL and REDSITRBUTE_IPV6_ADD|DEL have merged to - REDISTRIBUTE_ROUTE_ADD|DEL in ZAPI version 5. - Therefore it can not judge the protocol famiiy from API. */ - - b.Type = ROUTE_TYPE(data[0]) + b.Type = RouteType(data[0]) if version <= 3 { - b.Flags = FLAG(data[1]) + b.Flags = Flag(data[1]) data = data[2:] } else { // version >= 4 - b.Instance = binary.BigEndian.Uint16(data[1:3]) - b.Flags = FLAG(binary.BigEndian.Uint32(data[3:7])) + b.instance = binary.BigEndian.Uint16(data[1:3]) + b.Flags = Flag(binary.BigEndian.Uint32(data[3:7])) data = data[7:] } - b.Message = MESSAGE_FLAG(data[0]) - b.SAFI = SAFI(SAFI_UNICAST) - if version >= 5 { - b.SAFI = SAFI(data[1]) + b.Message = MessageFlag(data[0]) + 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]) data = data[2:] - if b.Flags&FLAG_EVPN_ROUTE > 0 { + if version == 5 && b.Flags&flagEvpnRoute.ToEach(version, softwareName) > 0 { // size of struct ethaddr is 6 octets defined by ETH_ALEN - copy(b.Rmac[0:6], data[0:6]) + copy(evpnNexthop.rmac[0:6], data[0:6]) data = data[6:] } b.Prefix.Family = data[0] @@ -2287,426 +2347,222 @@ 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 == 4 && b.Message&FRR_MESSAGE_SRCPFX > 0) || - (version >= 5 && b.Message&FRR_ZAPI5_MESSAGE_SRCPFX > 0) { + if version > 3 && b.Message&messageSRCPFX.ToEach(version) > 0 { if pos+1 > rest { - return fmt.Errorf("MESSAGE_SRCPFX message length invalid pos:%d rest:%d", pos, rest) + return fmt.Errorf("MessageSRCPFX message length invalid pos:%d rest:%d", pos, rest) } - b.SrcPrefix.PrefixLen = data[pos] - if b.SrcPrefix.PrefixLen > addrBitLen { + b.srcPrefix.PrefixLen = data[pos] + if b.srcPrefix.PrefixLen > addrBitLen { return fmt.Errorf("prefix length is greater than %d", addrByteLen*8) } - pos += 1 + pos++ buf = make([]byte, addrByteLen) - byteLen = int((b.SrcPrefix.PrefixLen + 7) / 8) + byteLen = int((b.srcPrefix.PrefixLen + 7) / 8) if pos+byteLen > rest { - return fmt.Errorf("MESSAGE_SRCPFX message length invalid pos:%d rest:%d", pos, rest) + return fmt.Errorf("MessageSRCPFX message length invalid pos:%d rest:%d", pos, rest) } copy(buf, data[pos:pos+byteLen]) - b.SrcPrefix.Prefix = ipFromFamily(b.Prefix.Family, buf) + b.srcPrefix.Prefix = ipFromFamily(b.Prefix.Family, buf) pos += byteLen } b.Nexthops = []Nexthop{} - if (version <= 3 && b.Message&MESSAGE_NEXTHOP > 0) || - (version == 4 && b.Message&FRR_MESSAGE_NEXTHOP > 0) || - (version >= 5 && b.Message&FRR_ZAPI5_MESSAGE_NEXTHOP > 0) { - var numNexthop uint16 - if version <= 4 { - if pos+1 > rest { - return fmt.Errorf("MESSAGE_NEXTHOP message length invalid pos:%d rest:%d", pos, rest) - } - numNexthop = uint16(data[pos]) - pos += 1 - } else { // version >= 5 - if pos+2 > rest { - return fmt.Errorf("MESSAGE_NEXTHOP message length invalid pos:%d rest:%d", pos, rest) + 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]) - pos += 2 + } else if numNexthopDataSize == 1 { + numNexthop = uint16(data[pos]) } - for i := 0; i < int(numNexthop); i++ { - var nexthop Nexthop - if version <= 3 { - if b.Prefix.Family == syscall.AF_INET { - nexthop.Type = NEXTHOP_TYPE_IPV4 - } else if b.Prefix.Family == syscall.AF_INET6 { - nexthop.Type = NEXTHOP_TYPE_IPV6 - } - } else if version == 4 { - if b.Prefix.Family == syscall.AF_INET { - nexthop.Type = FRR_NEXTHOP_TYPE_IPV4 - } else if b.Prefix.Family == syscall.AF_INET6 { - nexthop.Type = FRR_NEXTHOP_TYPE_IPV6 - } - } else { // version >= 5 - if pos+5 > rest { - return fmt.Errorf("MESSAGE_NEXTHOP message length invalid pos:%d rest:%d", pos, rest) - } - nexthop.VrfId = binary.BigEndian.Uint32(data[pos : pos+4]) - nexthop.Type = NEXTHOP_TYPE(data[pos+4]) - pos += 5 - if softwareName == "frr7.1" || softwareName == "frr7.2" { - nexthop.Onlink = uint8(data[pos]) - pos += 1 - } - } + pos += numNexthopDataSize - if (version <= 3 && nexthop.Type == NEXTHOP_TYPE_IPV4) || - (version >= 4 && nexthop.Type == FRR_NEXTHOP_TYPE_IPV4) { - if pos+4 > rest { - return fmt.Errorf("MESSAGE_NEXTHOP NEXTHOP_TYPE_IPV4 message length invalid pos:%d rest:%d", pos, rest) - } - addr := data[pos : pos+4] - nexthop.Gate = net.IP(addr).To4() - pos += 4 - } else if (version <= 3 && nexthop.Type == NEXTHOP_TYPE_IPV6) || - (version >= 4 && nexthop.Type == FRR_NEXTHOP_TYPE_IPV6) { - if pos+16 > rest { - return fmt.Errorf("MESSAGE_NEXTHOP NEXTHOP_TYPE_IPV6 message length invalid pos:%d rest:%d", pos, rest) - } - addr := data[pos : pos+16] - nexthop.Gate = net.IP(addr).To16() - pos += 16 - } else if version >= 5 && nexthop.Type == FRR_NEXTHOP_TYPE_IFINDEX { - if pos+4 > rest { - return fmt.Errorf("MESSAGE_NEXTHOP NEXTHOP_TYPE_IFINDEX message length invalid pos:%d rest:%d", pos, rest) - } - nexthop.Ifindex = binary.BigEndian.Uint32(data[pos : pos+4]) - pos += 4 - // barkward compatibility - if b.Prefix.Family == syscall.AF_INET { - nexthop.Gate = net.ParseIP("0.0.0.0") - } else if b.Prefix.Family == syscall.AF_INET6 { - nexthop.Gate = net.ParseIP("::") - } - } else if version >= 5 && nexthop.Type == FRR_NEXTHOP_TYPE_IPV4_IFINDEX { - if pos+8 > rest { - return fmt.Errorf("MESSAGE_NEXTHOP NEXTHOP_TYPE_IPV4_IFINDEX message length invalid pos:%d rest:%d", pos, rest) - } - addr := data[pos : pos+4] - nexthop.Gate = net.IP(addr).To4() - nexthop.Ifindex = binary.BigEndian.Uint32(data[pos+4 : pos+8]) - pos += 8 - } else if version >= 5 && nexthop.Type == FRR_NEXTHOP_TYPE_IPV6_IFINDEX { - if pos+20 > rest { - return fmt.Errorf("MESSAGE_NEXTHOP NEXTHOP_TYPE_IPV6_IFINDEX message length invalid pos:%d rest:%d", pos, rest) - } - addr := data[pos : pos+16] - nexthop.Gate = net.IP(addr).To16() - nexthop.Ifindex = binary.BigEndian.Uint32(data[pos+16 : pos+20]) - pos += 20 - } else if version >= 5 && nexthop.Type == FRR_NEXTHOP_TYPE_BLACKHOLE { - if pos+1 > rest { - return fmt.Errorf("MESSAGE_NEXTHOP NEXTHOP_TYPE_BLACKHOLE message length invalid pos:%d rest:%d", pos, rest) - } - nexthop.BlackholeType = data[pos] - pos += 1 - } - b.Nexthops = append(b.Nexthops, nexthop) + 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 + } + if version == 5 && b.Flags&flagEvpnRoute.ToEach(version, softwareName) > 0 { + b.Nexthops = append(b.Nexthops, evpnNexthop) } - if (version <= 3 && b.Message&MESSAGE_IFINDEX > 0) || - (version == 4 && b.Message&FRR_MESSAGE_IFINDEX > 0) { + if version < 5 && b.Message&messageIFIndex > 0 { if pos+1 > rest { - return fmt.Errorf("MESSAGE_IFINDEX message length invalid pos:%d rest:%d", pos, rest) + return fmt.Errorf("MessageIFIndex message length invalid pos:%d rest:%d", pos, rest) } numIfIndex := uint8(data[pos]) - pos += 1 + pos++ for i := 0; i < int(numIfIndex); i++ { if pos+4 > rest { - return fmt.Errorf("MESSAGE_IFINDEX message length invalid pos:%d rest:%d", pos, rest) + return fmt.Errorf("MessageIFIndex message length invalid pos:%d rest:%d", pos, rest) } var nexthop Nexthop nexthop.Ifindex = binary.BigEndian.Uint32(data[pos : pos+4]) - if version <= 3 { - nexthop.Type = NEXTHOP_TYPE_IFINDEX - } else if version == 4 { - nexthop.Type = FRR_NEXTHOP_TYPE_IFINDEX - } + nexthop.Type = nexthopTypeIFIndex b.Nexthops = append(b.Nexthops, nexthop) pos += 4 } } - if (version <= 3 && b.Message&MESSAGE_DISTANCE > 0) || - (version == 4 && b.Message&FRR_MESSAGE_DISTANCE > 0) || - (version >= 5 && b.Message&FRR_ZAPI5_MESSAGE_DISTANCE > 0) { + if b.Message&MessageDistance.ToEach(version) > 0 { if pos+1 > rest { - return fmt.Errorf("MESSAGE_DISTANCE message length invalid pos:%d rest:%d", pos, rest) + return fmt.Errorf("MessageDistance message length invalid pos:%d rest:%d", pos, rest) } b.Distance = data[pos] - pos += 1 + pos++ } - if (version <= 3 && b.Message&MESSAGE_METRIC > 0) || - (version == 4 && b.Message&FRR_MESSAGE_METRIC > 0) || - (version >= 5 && b.Message&FRR_ZAPI5_MESSAGE_METRIC > 0) { + if b.Message&MessageMetric.ToEach(version) > 0 { if pos+4 > rest { - return fmt.Errorf("MESSAGE_METRIC message length invalid pos:%d rest:%d", pos, rest) + return fmt.Errorf("MessageMetric message length invalid pos:%d rest:%d", pos, rest) } b.Metric = binary.BigEndian.Uint32(data[pos : pos+4]) pos += 4 } - if (version <= 3 && b.Message&MESSAGE_MTU > 0) || - (version == 4 && b.Message&FRR_MESSAGE_MTU > 0) || - (version >= 5 && b.Message&FRR_ZAPI5_MESSAGE_MTU > 0) { + if b.Message&MessageMTU.ToEach(version) > 0 { if pos+4 > rest { - return fmt.Errorf("MESSAGE_MTU message length invalid pos:%d rest:%d", pos, rest) + return fmt.Errorf("MessageMTU message length invalid pos:%d rest:%d", pos, rest) } b.Mtu = binary.BigEndian.Uint32(data[pos : pos+4]) pos += 4 } - if (version <= 3 && b.Message&MESSAGE_TAG > 0) || - (version == 4 && b.Message&FRR_MESSAGE_TAG > 0) || - (version >= 5 && b.Message&FRR_ZAPI5_MESSAGE_TAG > 0) { + if b.Message&messageTag.ToEach(version) > 0 { if pos+4 > rest { - return fmt.Errorf("MESSAGE_TAG message length invalid pos:%d rest:%d", pos, rest) + return fmt.Errorf("MessageTag message length invalid pos:%d rest:%d", pos, rest) } - b.Tag = binary.BigEndian.Uint32(data[pos : pos+4]) + b.tag = binary.BigEndian.Uint32(data[pos : pos+4]) pos += 4 } if pos != rest { - return fmt.Errorf("message length invalid pos:%d rest:%d", pos, rest) + return fmt.Errorf("message length invalid (last) pos:%d rest:%d, message:%#x", pos, rest, b.Message) } return nil } -func (b *IPRouteBody) String(version uint8, softwareName string) string { +func (b *IPRouteBody) string(version uint8, softwareName string) string { s := fmt.Sprintf( - "type: %s, instance: %d, flags: %s, message: %d, safi: %s, prefix: %s/%d, src_prefix: %s/%d", - b.Type.String(), b.Instance, b.Flags.String(version, softwareName), b.Message, b.SAFI.String(), b.Prefix.Prefix.String(), b.Prefix.PrefixLen, b.SrcPrefix.Prefix.String(), b.SrcPrefix.PrefixLen) + "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) for i, nh := range b.Nexthops { - s += fmt.Sprintf(", nexthops[%d]: %s", i, nh.String()) + s += fmt.Sprintf(", nexthops[%d]: %s", i, nh.string()) } return s + fmt.Sprintf( ", distance: %d, metric: %d, mtu: %d, tag: %d", - b.Distance, b.Metric, b.Mtu, b.Tag) + b.Distance, b.Metric, b.Mtu, b.tag) } -func decodeNexthopsFromBytes(nexthops *[]Nexthop, data []byte, family uint8, version uint8) (int, error) { - addrByteLen, err := addressByteLength(family) - if err != nil { - return 0, err - } - - numNexthop := int(data[0]) - offset := 1 - - for i := 0; i < numNexthop; i++ { - nexthop := Nexthop{} - nexthop.Type = NEXTHOP_TYPE(data[offset]) - offset += 1 - - // On Quagga, NEXTHOP_TYPE_IFNAME is same as NEXTHOP_TYPE_IFINDEX, - // NEXTHOP_TYPE_IPV4_IFNAME is same as NEXTHOP_TYPE_IPV4_IFINDEX, - // NEXTHOP_TYPE_IPV6_IFNAME is same as NEXTHOP_TYPE_IPV6_IFINDEX - - // On FRRouting version 3.0 or later, NEXTHOP_TYPE_IPV4 and NEXTHOP_TYPE_IPV6 have - // the same structure with NEXTHOP_TYPE_IPV4_IFINDEX and NEXTHOP_TYPE_IPV6_IFINDEX. - - if (version <= 3 && (nexthop.Type == NEXTHOP_TYPE_IFINDEX || nexthop.Type == NEXTHOP_TYPE_IFNAME)) || - (version >= 4 && nexthop.Type == FRR_NEXTHOP_TYPE_IFINDEX) { - nexthop.Ifindex = binary.BigEndian.Uint32(data[offset : offset+4]) - offset += 4 - } else if version <= 3 && nexthop.Type == NEXTHOP_TYPE_IPV4 { - nexthop.Gate = net.IP(data[offset : offset+addrByteLen]).To4() - offset += addrByteLen - } else if version <= 3 && nexthop.Type == NEXTHOP_TYPE_IPV6 { - nexthop.Gate = net.IP(data[offset : offset+addrByteLen]).To16() - offset += addrByteLen - } else if (version <= 3 && (nexthop.Type == NEXTHOP_TYPE_IPV4_IFINDEX || nexthop.Type == NEXTHOP_TYPE_IPV4_IFNAME)) || - (version >= 4 && (nexthop.Type == FRR_NEXTHOP_TYPE_IPV4 || nexthop.Type == FRR_NEXTHOP_TYPE_IPV4_IFINDEX)) { - nexthop.Gate = net.IP(data[offset : offset+addrByteLen]).To4() - offset += addrByteLen - nexthop.Ifindex = binary.BigEndian.Uint32(data[offset : offset+4]) - offset += 4 - } else if (version <= 3 && (nexthop.Type == NEXTHOP_TYPE_IPV6_IFINDEX || nexthop.Type == NEXTHOP_TYPE_IPV6_IFNAME)) || - (version >= 4 && (nexthop.Type == FRR_NEXTHOP_TYPE_IPV6 || nexthop.Type == FRR_NEXTHOP_TYPE_IPV6_IFINDEX)) { - nexthop.Gate = net.IP(data[offset : offset+addrByteLen]).To16() - offset += addrByteLen - nexthop.Ifindex = binary.BigEndian.Uint32(data[offset : offset+4]) - offset += 4 - } - if version >= 5 { - nexthop.LabelNum = uint8(data[offset]) - offset += 1 - if nexthop.LabelNum > MPLS_MAX_LABEL { - nexthop.LabelNum = MPLS_MAX_LABEL - } - if nexthop.LabelNum > 0 { - nexthop.MplsLabels = make([]uint32, nexthop.LabelNum) - for n := uint8(0); n < nexthop.LabelNum; n++ { - /* 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 - } - } - } - *nexthops = append(*nexthops, nexthop) - } - - return offset, nil +// lookupBody is combination of nexthopLookupBody and imporetLookupBody +type lookupBody struct { + api APIType + prefixLength uint8 // importLookup serialize only + addr net.IP //it is same as prefix (it is deleted from importLookup) + distance uint8 // nexthopIPv4LookupMRIB only + metric uint32 + nexthops []Nexthop } -type NexthopLookupBody struct { - Api API_TYPE - Addr net.IP - Distance uint8 - Metric uint32 - Nexthops []Nexthop -} - -// Quagga only. Reference: zread_ipv[4|6]_nexthop_lookup in zebra/zserv.c of Quagga1.2.x (ZAPI3) -func (b *NexthopLookupBody) Serialize(version uint8, softwareName string) ([]byte, error) { - family := addressFamilyFromApi(b.Api, version) +// Quagga only. Ref: zread_ipv4_(nexthop|import_lookup) in zebra/zserv.c +func (b *lookupBody) serialize(version uint8, softwareName string) ([]byte, error) { buf := make([]byte, 0) - - if family == syscall.AF_INET { - buf = append(buf, b.Addr.To4()...) - } else if family == syscall.AF_INET6 { - buf = append(buf, b.Addr.To16()...) + if b.api == zapi3IPv4ImportLookup { + buf = append(buf, b.prefixLength) + } + switch b.api { + case ipv4NexthopLookupMRIB, zapi3IPv4NexthopLookup, zapi3IPv4ImportLookup: + buf = append(buf, b.addr.To4()...) + case zapi3IPv6NexthopLookup: + buf = append(buf, b.addr.To16()...) } return buf, nil } -// Quagga only. Reference: zsend_ipv[4|6]_nexthop_lookup in zebra/zserv.c of Quagga1.2.x (ZAPI3) -func (b *NexthopLookupBody) DecodeFromBytes(data []byte, version uint8, softwareName string) error { - family := addressFamilyFromApi(b.Api, version) - addrByteLen, err := addressByteLength(family) - if err != nil { - return err +// Quagga only(except ipv4NexthopLookupMRIB). +// Ref: zsend_ipv[4|6]_(nexthop|import)_lookup in zebra/zserv.c +func (b *lookupBody) decodeFromBytes(data []byte, version uint8, softwareName string) error { + family := uint8(syscall.AF_INET) + if b.api == zapi3IPv6NexthopLookup { + family = syscall.AF_INET6 } - - if len(data) < addrByteLen { + addrByteLen, _ := addressByteLength(family) + requiredLen := 5 //metric(4), numNexthop(1) + hasDistance := false + if b.api == ipv4NexthopLookupMRIB.ToEach(version, softwareName) { + requiredLen++ //distance + hasDistance = true + } + if len(data) < addrByteLen+requiredLen { return fmt.Errorf("message length invalid") } - buf := make([]byte, addrByteLen) copy(buf, data[0:addrByteLen]) pos := addrByteLen - b.Addr = ipFromFamily(family, buf) - - if version >= 4 { - b.Distance = data[pos] + b.addr = ipFromFamily(family, buf) + if hasDistance { + b.distance = data[pos] pos++ } - - if len(data[pos:]) > int(1+addrByteLen) { - b.Metric = binary.BigEndian.Uint32(data[pos : pos+4]) - pos += 4 - b.Nexthops = []Nexthop{} - if nexthopsByteLen, err := decodeNexthopsFromBytes(&b.Nexthops, data[pos:], family, version); err != nil { - return err - } else { - pos += nexthopsByteLen - } - } - - return nil -} - -func (b *NexthopLookupBody) String(version uint8, softwareName string) string { - s := fmt.Sprintf( - "addr: %s, distance:%d, metric: %d", - b.Addr.String(), b.Distance, b.Metric) - if len(b.Nexthops) > 0 { - for _, nh := range b.Nexthops { - s = s + fmt.Sprintf(", nexthop:{%s}", nh.String()) - } - } - return s -} - -type ImportLookupBody struct { - Api API_TYPE - PrefixLength uint8 - Prefix net.IP - Addr net.IP - Metric uint32 - Nexthops []Nexthop -} - -// Quagga only. Reference: zread_ipv4_import_lookup in zebra/zserv.c of Quagga1.2.x (ZAPI3) -func (b *ImportLookupBody) Serialize(version uint8, softwareName string) ([]byte, error) { - buf := make([]byte, 1) - buf[0] = b.PrefixLength - buf = append(buf, b.Addr.To4()...) - return buf, nil -} - -// Quagga only. Reference: zsend_ipv4_import_lookup in zebra/zserv.c of Quagga1.2.x (ZAPI3) -func (b *ImportLookupBody) DecodeFromBytes(data []byte, version uint8, softwareName string) error { - family := addressFamilyFromApi(b.Api, version) - addrByteLen, err := addressByteLength(family) + b.metric = binary.BigEndian.Uint32(data[pos : pos+4]) + pos += 4 + numNexthop := uint16(data[pos]) + pos++ + b.nexthops = []Nexthop{} + processFlag := nexthopHasType | nexthopProcessIFnameToIFindex + nexthopsByteLen, err := decodeNexthops(&b.nexthops, data[pos:], version, softwareName, family, numNexthop, processFlag, MessageFlag(0), Flag(0), nexthopType(0)) if err != nil { return err } - - if len(data) < addrByteLen { - return fmt.Errorf("message length invalid") - } - - buf := make([]byte, addrByteLen) - copy(buf, data[0:addrByteLen]) - pos := addrByteLen - - b.Addr = net.IP(buf).To4() - - if len(data[pos:]) > int(1+addrByteLen) { - b.Metric = binary.BigEndian.Uint32(data[pos : pos+4]) - pos += 4 - b.Nexthops = []Nexthop{} - if nexthopsByteLen, err := decodeNexthopsFromBytes(&b.Nexthops, data[pos:], family, version); err != nil { - return err - } else { - pos += nexthopsByteLen - } - } - + pos += nexthopsByteLen return nil } - -func (b *ImportLookupBody) String(version uint8, softwareName string) string { +func (b *lookupBody) string(version uint8, softwareName string) string { s := fmt.Sprintf( - "prefix: %s/%d, addr: %s, metric: %d", - b.Prefix.String(), b.PrefixLength, b.Addr.String(), b.Metric) - if len(b.Nexthops) > 0 { - for _, nh := range b.Nexthops { - s = s + fmt.Sprintf(", nexthop:{%s}", nh.String()) + "addr/prefixLength: %s/%d, distance:%d, metric: %d", + b.addr.String(), b.prefixLength, b.distance, b.metric) + if len(b.nexthops) > 0 { + for _, nh := range b.nexthops { + s = s + fmt.Sprintf(", nexthop:{%s}", nh.string()) } } return s } +// RegisteredNexthop is referred in zclient type RegisteredNexthop struct { - Connected uint8 + connected uint8 Family uint16 - // Note: Ignores PrefixLength (uint8), - // because this field should be always: + // Note: Ignores PrefixLength (uint8), because this field should be always: // - 32 if Address Family is AF_INET // - 128 if Address Family is AF_INET6 Prefix net.IP } -func (n *RegisteredNexthop) Len() int { +func (n *RegisteredNexthop) len() int { // Connected (1 byte) + Address Family (2 bytes) + Prefix Length (1 byte) + Prefix (variable) if n.Family == uint16(syscall.AF_INET) { return 4 + net.IPv4len - } else { - return 4 + net.IPv6len } + return 4 + net.IPv6len } -// Reference: sendmsg_nexthop in bgpd/bgp_nht.c of Quagga1.2.x (ZAPI3) -// Reference: sendmsg_zebra_rnh in bgpd/bgp_nht.c of FRR3.x (ZAPI4) -// Reference: zclient_send_rnh function in lib/zclient.c of FRR5.x (ZAPI5) -func (n *RegisteredNexthop) Serialize() ([]byte, error) { +// Ref: sendmsg_nexthop in bgpd/bgp_nht.c of Quagga1.2.x (ZAPI3) +// Ref: sendmsg_zebra_rnh in bgpd/bgp_nht.c of FRR3.x (ZAPI4) +// Ref: zclient_send_rnh in lib/zclient.c of FRR5.x (ZAPI5) +func (n *RegisteredNexthop) serialize() ([]byte, error) { // Connected (1 byte) buf := make([]byte, 4) - buf[0] = byte(n.Connected) + buf[0] = byte(n.connected) // Address Family (2 bytes) binary.BigEndian.PutUint16(buf[1:3], n.Family) @@ -2730,12 +2586,12 @@ func (n *RegisteredNexthop) Serialize() ([]byte, error) { return buf, nil } -// Reference: zserv_nexthop_register in zebra/zserv.c of Quagga1.2.x (ZAPI3) -// Reference: zserv_rnh_register in zebra/zserv.c of FRR3.x (ZAPI4) -// Reference: zread_rnh_register in zebra/zapi_msg.c of FRR5.x (ZAPI5) -func (n *RegisteredNexthop) DecodeFromBytes(data []byte, softwareName string) error { +// Ref: zserv_nexthop_register in zebra/zserv.c of Quagga1.2.x (ZAPI3) +// Ref: zserv_rnh_register in zebra/zserv.c of FRR3.x (ZAPI4) +// Ref: zread_rnh_register in zebra/zapi_msg.c of FRR5.x (ZAPI5) +func (n *RegisteredNexthop) decodeFromBytes(data []byte, softwareName string) error { // Connected (1 byte) - n.Connected = uint8(data[0]) + n.connected = uint8(data[0]) // Address Family (2 bytes) n.Family = binary.BigEndian.Uint16(data[1:3]) // Note: Ignores Prefix Length (1 byte) @@ -2746,26 +2602,27 @@ func (n *RegisteredNexthop) DecodeFromBytes(data []byte, softwareName string) er return nil } -func (n *RegisteredNexthop) String(version uint8, softwareName string) string { +func (n *RegisteredNexthop) string(version uint8, softwareName string) string { return fmt.Sprintf( "connected: %d, family: %d, prefix: %s", - n.Connected, n.Family, n.Prefix.String()) + n.connected, n.Family, n.Prefix.String()) } +// NexthopRegisterBody us referred in zclient type NexthopRegisterBody struct { - Api API_TYPE + api APIType Nexthops []*RegisteredNexthop } -// Reference: sendmsg_nexthop in bgpd/bgp_nht.c of Quagga1.2.x (ZAPI3) -// Reference: sendmsg_zebra_rnh in bgpd/bgp_nht.c of FRR3.x (ZAPI4) -// Reference: zclient_send_rnh function in lib/zclient.c of FRR5.x (ZAPI5) -func (b *NexthopRegisterBody) Serialize(version uint8, softwareName string) ([]byte, error) { +// Ref: sendmsg_nexthop in bgpd/bgp_nht.c of Quagga1.2.x (ZAPI3) +// Ref: sendmsg_zebra_rnh in bgpd/bgp_nht.c of FRR3.x (ZAPI4) +// Ref: zclient_send_rnh in lib/zclient.c of FRR5.x (ZAPI5) +func (b *NexthopRegisterBody) serialize(version uint8, softwareName string) ([]byte, error) { buf := make([]byte, 0) // List of Registered Nexthops for _, nh := range b.Nexthops { - nhBuf, err := nh.Serialize() + nhBuf, err := nh.serialize() if err != nil { return nil, err } @@ -2775,47 +2632,42 @@ func (b *NexthopRegisterBody) Serialize(version uint8, softwareName string) ([]b return buf, nil } -// Reference: zserv_nexthop_register in zebra/zserv.c of Quagga1.2.x (ZAPI3) -// Reference: zserv_rnh_register in zebra/zserv.c of FRR3.x (ZAPI4) -// Reference: zread_rnh_register in zebra/zapi_msg.c of FRR5.x (ZAPI5) -func (b *NexthopRegisterBody) DecodeFromBytes(data []byte, version uint8, softwareName string) error { +// Ref: zserv_nexthop_register in zebra/zserv.c of Quagga1.2.x (ZAPI3) +// Ref: zserv_rnh_register in zebra/zserv.c of FRR3.x (ZAPI4) +// Ref: zread_rnh_register in zebra/zapi_msg.c of FRR5.x (ZAPI5) +func (b *NexthopRegisterBody) decodeFromBytes(data []byte, version uint8, softwareName string) error { offset := 0 - // List of Registered Nexthops b.Nexthops = []*RegisteredNexthop{} for len(data[offset:]) > 0 { nh := new(RegisteredNexthop) - err := nh.DecodeFromBytes(data[offset:], softwareName) + err := nh.decodeFromBytes(data[offset:], softwareName) if err != nil { return err } b.Nexthops = append(b.Nexthops, nh) - offset += nh.Len() + offset += nh.len() if len(data) < offset { break } } - return nil } -func (b *NexthopRegisterBody) String(version uint8, softwareName string) string { +func (b *NexthopRegisterBody) string(version uint8, softwareName string) string { s := make([]string, 0) for _, nh := range b.Nexthops { - s = append(s, fmt.Sprintf("nexthop:{%s}", nh.String(version, softwareName))) + s = append(s, fmt.Sprintf("nexthop:{%s}", nh.string(version, softwareName))) } return strings.Join(s, ", ") } -/* NEXTHOP_UPDATE message uses same data structure as IPRoute (zapi_route) - in FRR version 4, 5 (ZApi version 5) */ +// NexthopUpdateBody uses same data structure as IPRoute (zapi_route) after frr4 (Zapi5) type NexthopUpdateBody IPRouteBody -// Reference: send_client function in zebra/zebra_rnh.c of Quagga1.2.x (ZAPI3) -// Reference: send_client function in zebra/zebra_rnh.c of FRR3.x (ZAPI4) -// Reference: send_client function in zebra/zebra_rnh.c of FRR5.x (ZAPI5) -func (b *NexthopUpdateBody) Serialize(version uint8, softwareName string) ([]byte, error) { +// Ref: send_client in zebra/zebra_rnh.c of Quagga1.2&FRR3&FRR5(ZAPI3&4$5) +func (b *NexthopUpdateBody) serialize(version uint8, softwareName string) ([]byte, error) { // Address Family (2 bytes) buf := make([]byte, 3) binary.BigEndian.PutUint16(buf, uint16(b.Prefix.Family)) @@ -2836,31 +2688,29 @@ func (b *NexthopUpdateBody) Serialize(version uint8, softwareName string) ([]byt } if version >= 5 { // Type (1 byte) (if version>=5) - // Instance (2 bytes) (if version>=5) + // instance (2 bytes) (if version>=5) buf = append(buf, byte(b.Type)) - bbuf := make([]byte, 2) - binary.BigEndian.PutUint16(bbuf, b.Instance) - buf = append(buf, bbuf...) + tmpbuf := make([]byte, 2) + binary.BigEndian.PutUint16(tmpbuf, b.instance) + buf = append(buf, tmpbuf...) } if version >= 4 { // Distance (1 byte) (if version>=4) buf = append(buf, b.Distance) } // Metric (4 bytes) - bbuf := make([]byte, 4) - binary.BigEndian.PutUint32(bbuf, b.Metric) - buf = append(buf, bbuf...) + tmpbuf := make([]byte, 4) + binary.BigEndian.PutUint32(tmpbuf, b.Metric) + buf = append(buf, tmpbuf...) // Number of Nexthops (1 byte) buf = append(buf, uint8(0)) // Temporary code // ToDo Processing Route Entry - return buf, nil } -// Reference: bgp_parse_nexthop_update function in bgpd/bgp_nht.c of Quagga1.2.x (ZAPI3) -// Reference: bgp_parse_nexthop_update function in bgpd/bgp_nht.c of FRR3.x (ZAPI4) -// Reference: zapi_nexthop_update_decode function in lib/zclient.c of FRR5.x (ZAPI5) -func (b *NexthopUpdateBody) DecodeFromBytes(data []byte, version uint8, softwareName string) error { +// 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 { // Address Family (2 bytes) prefixFamily := binary.BigEndian.Uint16(data[0:2]) b.Prefix.Family = uint8(prefixFamily) @@ -2875,505 +2725,310 @@ func (b *NexthopUpdateBody) DecodeFromBytes(data []byte, version uint8, software b.Prefix.Prefix = ipFromFamily(b.Prefix.Family, data[offset:offset+addrByteLen]) offset += addrByteLen - if version >= 5 { - b.Type = ROUTE_TYPE(data[offset]) - b.Instance = binary.BigEndian.Uint16(data[offset+1 : offset+3]) + if version > 4 { + b.Type = RouteType(data[offset]) + b.instance = binary.BigEndian.Uint16(data[offset+1 : offset+3]) offset += 3 } // Distance (1 byte) (if version>=4) - if version >= 4 { + if version > 3 { b.Distance = data[offset] - offset += 1 + offset++ } - // Metric (4 bytes) - // Number of Nexthops (1 byte) + // Metric (4 bytes) & Number of Nexthops (1 byte) if len(data[offset:]) < 5 { return fmt.Errorf("invalid message length: missing metric(4 bytes) or nexthops(1 byte): %d<5", len(data[offset:])) } b.Metric = binary.BigEndian.Uint32(data[offset : offset+4]) offset += 4 + numNexthop := uint16(data[offset]) + offset++ // List of Nexthops b.Nexthops = []Nexthop{} - if nexthopsByteLen, err := decodeNexthopsFromBytes(&b.Nexthops, data[offset:], b.Prefix.Family, version); err != nil { + + processFlag := nexthopProcessFlag(nexthopHasType) + if version == 6 { + switch softwareName { + case "frr7.3", "": + processFlag |= (nexthopHasVrfID | nexthopHasFlag | nexthopProcessIPToIPIFindex) + case "frr7.0", "frr7.1", "frr7.2": + processFlag |= (nexthopHasVrfID | nexthopProcessIPToIPIFindex) + case "frr6": + processFlag |= nexthopProcessIPToIPIFindex + } + } else if version == 5 { + switch softwareName { + case "frr5", "": + processFlag |= nexthopProcessIPToIPIFindex + } + } else if version < 4 { // quagga + processFlag |= nexthopProcessIFnameToIFindex + } + + message := MessageFlag(0) + if (version == 6 && !(softwareName == "frr7.3" || softwareName == "")) || + (version == 5 && (softwareName == "frr5" || softwareName == "")) { + message |= MessageLabel + } + + nexthopsByteLen, err := decodeNexthops(&b.Nexthops, data[offset:], version, softwareName, b.Prefix.Family, numNexthop, processFlag, message, Flag(0), nexthopType(0)) + if err != nil { return err - } else { - offset += nexthopsByteLen } + offset += nexthopsByteLen return nil } -func (b *NexthopUpdateBody) String(version uint8, softwareName string) string { +func (b *NexthopUpdateBody) string(version uint8, softwareName string) string { s := fmt.Sprintf( "family: %d, prefix: %s, distance: %d, metric: %d", b.Prefix.Family, b.Prefix.Prefix.String(), b.Distance, b.Metric) for _, nh := range b.Nexthops { - s = s + fmt.Sprintf(", nexthop:{%s}", nh.String()) + s = s + fmt.Sprintf(", nexthop:{%s}", nh.string()) } return s } -type LabelManagerConnectBody struct { - RedistDefault ROUTE_TYPE - Instance uint16 +type labelManagerConnectBody struct { + redistDefault RouteType + instance uint16 // The followings are used in response from Zebra - Result uint8 // 0 means success + result uint8 // 0 means success } -// Reference: lm_label_manager_connect in lib/zclient.c of FRR -func (b *LabelManagerConnectBody) Serialize(version uint8, softwareName string) ([]byte, error) { +// Ref: lm_label_manager_connect in lib/zclient.c of FRR +func (b *labelManagerConnectBody) serialize(version uint8, softwareName string) ([]byte, error) { buf := make([]byte, 3) - buf[0] = uint8(b.RedistDefault) - binary.BigEndian.PutUint16(buf[1:3], b.Instance) + buf[0] = uint8(b.redistDefault) + binary.BigEndian.PutUint16(buf[1:3], b.instance) return buf, nil } -func (b *LabelManagerConnectBody) DecodeFromBytes(data []byte, version uint8, softwareName string) error { +func (b *labelManagerConnectBody) decodeFromBytes(data []byte, version uint8, softwareName string) error { size := 1 - // FRR v4 may work incorrectly. It returns result only although it uses ZAPI v5. - if version >= 4 { + if version > 4 && softwareName != "frr4" { // FRR4 returns result only. size = 4 } if len(data) < size { - return fmt.Errorf("invalid message length for LABEL_MANAGER_CONNECT response: %d<%d", + return fmt.Errorf("invalid message length for LabelManagerConnect response: %d<%d", len(data), size) } - if version > 4 { - b.RedistDefault = ROUTE_TYPE(data[0]) - b.Instance = binary.BigEndian.Uint16(data[1:3]) + if version > 4 && softwareName != "frr4" { + b.redistDefault = RouteType(data[0]) + b.instance = binary.BigEndian.Uint16(data[1:3]) data = data[3:] } - b.Result = data[0] + b.result = data[0] return nil } -func (b *LabelManagerConnectBody) String(version uint8, softwareName string) string { +func (b *labelManagerConnectBody) string(version uint8, softwareName string) string { return fmt.Sprintf( "route_type: %s, instance: %d, result: %d", - b.RedistDefault.String(), b.Instance, b.Result) + 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 +// GetLabelChunkBody is referred in zclient (Ref: zsend_assign_label_chunk_response) 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 + 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 + Start uint32 // The followings are used in response from Zebra + End uint32 + base uint32 // it is added in FRR7.2 } -// 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, softwareName string) ([]byte, error) { - buf := make([]byte, 8) +// Ref: zread_get_label_chunk in zebra/zserv.c of FRR3.x +// Ref: zread_get_label_chunk in zebra/zapi_msg.c of FRR5.x and 6.x +func (b *GetLabelChunkBody) serialize(version uint8, softwareName string) ([]byte, error) { + buf := make([]byte, 12) pos := 0 - if version > 4 { - buf[pos] = b.Proto - binary.BigEndian.PutUint16(buf[pos+1:pos+3], b.Instance) + b.base = 0 + if version > 4 && softwareName != "frr4" { + buf[pos] = b.proto + binary.BigEndian.PutUint16(buf[pos+1:pos+3], b.instance) pos += 3 } - buf[pos] = b.Keep + 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 == "") { + binary.BigEndian.PutUint32(buf[pos:pos+4], b.base) + pos += 4 + } 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, softwareName string) error { +// Ref: zsend_assign_label_chunk_response in zebra/zserv.c of FRR3.x +// Ref: zsend_assign_label_chunk_response in zebra/zapi_msg.c of FRR5.x and 6.x +func (b *GetLabelChunkBody) decodeFromBytes(data []byte, version uint8, softwareName string) error { size := 9 - if version > 4 { + if version > 4 && softwareName != "frr4" { size = 12 } if len(data) < size { - return fmt.Errorf("invalid message length for GET_LABEL_CHUNK response: %d<%d", + return fmt.Errorf("invalid message length for GetLabelChunk response: %d<%d", len(data), size) } - if version > 4 { - b.Proto = data[0] - b.Instance = binary.BigEndian.Uint16(data[1:3]) + if version > 4 && softwareName != "frr4" { + b.proto = data[0] + b.instance = binary.BigEndian.Uint16(data[1:3]) data = data[3:] } - b.Keep = data[0] + 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(version uint8, softwareName string) string { +func (b *GetLabelChunkBody) string(version uint8, softwareName string) string { return fmt.Sprintf( "keep: %d, chunk_size: %d, start: %d, end: %d", - b.Keep, b.ChunkSize, b.Start, b.End) + 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 +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, softwareName string) ([]byte, error) { +func (b *releaseLabelChunkBody) serialize(version uint8, softwareName string) ([]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) + if version > 4 && softwareName != "frr4" { + 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) + 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, softwareName string) error { - // No response from Zebra - return nil +func (b *releaseLabelChunkBody) decodeFromBytes(data []byte, version uint8, softwareName string) error { + return nil // No response from Zebra } -func (b *ReleaseLabelChunkBody) String(version uint8, softwareName string) string { - return fmt.Sprintf( - "start: %d, end: %d", - b.Start, b.End) +func (b *releaseLabelChunkBody) string(version uint8, softwareName string) string { + return fmt.Sprintf("start: %d, end: %d", b.start, b.end) } -//go:generate stringer -type=LSP_TYPE -type LSP_TYPE uint8 +//go:generate stringer -type=lspTYPE +type lspTYPE 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 + lspNone lspTYPE = iota //defined in FRR3 and over + lspStatic //defined in FRR3 and over + lspLDP //defined in FRR3 and over + lspBGP //defined in FRR4 and over + lspSR //defined in FRR4 and over + lspSHARP //defined in FRR5 and over ) -type VrfLabelBody struct { - Label uint32 - Afi AFI - LabelType LSP_TYPE +type vrfLabelBody struct { + label uint32 + afi afi + labelType lspTYPE } -// Reference: zclient_send_vrf_label in lib/zclient.c of FRR 5.x and 6.x -func (b *VrfLabelBody) Serialize(version uint8, softwareName string) ([]byte, error) { +// Ref: zclient_send_vrf_label in lib/zclient.c of FRR 5.x and 6.x +func (b *vrfLabelBody) serialize(version uint8, softwareName string) ([]byte, error) { buf := make([]byte, 6) - binary.BigEndian.PutUint32(buf[0:4], b.Label) - buf[4] = uint8(b.Afi) - buf[5] = uint8(b.LabelType) + 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, softwareName string) error { +// Ref: zread_vrf_label in zebra/zapi_msg.c of FRR 5.x and 6.x +func (b *vrfLabelBody) decodeFromBytes(data []byte, version uint8, softwareName string) error { if len(data) < 6 { - return fmt.Errorf("invalid message length for VRF_LABEL message: %d<6", len(data)) + return fmt.Errorf("invalid message length for VRFLabel message: %d<6", len(data)) } - b.Label = binary.BigEndian.Uint32(data[0:4]) - b.Afi = AFI(data[4]) - b.LabelType = LSP_TYPE(data[5]) + b.label = binary.BigEndian.Uint32(data[0:4]) + b.afi = afi(data[4]) + b.labelType = lspTYPE(data[5]) return nil } -func (b *VrfLabelBody) String(version uint8, softwareName string) string { +func (b *vrfLabelBody) string(version uint8, softwareName string) string { return fmt.Sprintf( - "label: %d, AFI: %s LSP_type: %s", - b.Label, b.Afi, b.LabelType) + "label: %d, afi: %s LSP type: %s", + b.label, b.afi, b.labelType) } +// Message is referred in zclient type Message struct { Header Header Body Body } -func (m *Message) Serialize(software string) ([]byte, error) { +func (m *Message) serialize(software string) ([]byte, error) { var body []byte if m.Body != nil { var err error - body, err = m.Body.Serialize(m.Header.Version, software) + body, err = m.Body.serialize(m.Header.Version, software) if err != nil { return nil, err } } m.Header.Len = uint16(len(body)) + HeaderSize(m.Header.Version) - hdr, err := m.Header.Serialize() + hdr, err := m.Header.serialize() if err != nil { return nil, err } return append(hdr, body...), nil } -func (m *Message) parseMessage(data []byte, software string) error { - switch m.Header.Command { - case INTERFACE_ADD, INTERFACE_DELETE, INTERFACE_UP, INTERFACE_DOWN: - m.Body = &InterfaceUpdateBody{} - case INTERFACE_ADDRESS_ADD, INTERFACE_ADDRESS_DELETE: - m.Body = &InterfaceAddressUpdateBody{} - case ROUTER_ID_UPDATE: - m.Body = &RouterIDUpdateBody{} - case IPV4_ROUTE_ADD, IPV6_ROUTE_ADD, IPV4_ROUTE_DELETE, IPV6_ROUTE_DELETE: - m.Body = &IPRouteBody{Api: m.Header.Command} - case IPV4_NEXTHOP_LOOKUP, IPV6_NEXTHOP_LOOKUP: - m.Body = &NexthopLookupBody{Api: m.Header.Command} - case IPV4_IMPORT_LOOKUP: - m.Body = &ImportLookupBody{Api: m.Header.Command} - case NEXTHOP_UPDATE: - m.Body = &NexthopUpdateBody{Api: m.Header.Command} - default: - m.Body = &UnknownBody{} - } - return m.Body.DecodeFromBytes(data, m.Header.Version, software) -} - -func (m *Message) parseFrrMessage(data []byte, software string) error { - switch m.Header.Command { - case FRR_INTERFACE_ADD, FRR_INTERFACE_DELETE, FRR_INTERFACE_UP, FRR_INTERFACE_DOWN: - m.Body = &InterfaceUpdateBody{} - case FRR_INTERFACE_ADDRESS_ADD, FRR_INTERFACE_ADDRESS_DELETE: - m.Body = &InterfaceAddressUpdateBody{} - case FRR_ROUTER_ID_UPDATE: - m.Body = &RouterIDUpdateBody{} - case FRR_NEXTHOP_UPDATE: - m.Body = &NexthopUpdateBody{} - case FRR_INTERFACE_NBR_ADDRESS_ADD, FRR_INTERFACE_NBR_ADDRESS_DELETE: - // TODO - m.Body = &UnknownBody{} - case FRR_INTERFACE_BFD_DEST_UPDATE: - // TODO - m.Body = &UnknownBody{} - case FRR_IMPORT_CHECK_UPDATE: - // TODO - m.Body = &UnknownBody{} - case FRR_BFD_DEST_REPLAY: - // TODO - m.Body = &UnknownBody{} - case FRR_REDISTRIBUTE_IPV4_ADD, FRR_REDISTRIBUTE_IPV4_DEL, FRR_REDISTRIBUTE_IPV6_ADD, FRR_REDISTRIBUTE_IPV6_DEL: - m.Body = &IPRouteBody{Api: m.Header.Command} - case FRR_INTERFACE_VRF_UPDATE: - // TODO - m.Body = &UnknownBody{} - case FRR_INTERFACE_LINK_PARAMS: - // TODO - m.Body = &UnknownBody{} - 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{} - } - return m.Body.DecodeFromBytes(data, m.Header.Version, software) -} - -func (m *Message) parseFrrZapi5Message(data []byte, software string) error { - command := m.Header.Command - if software == "frr4" { - if c, err := frr4Zapi5Command(command, software, true); err == nil { - command = c - } else { - return err - } - } else if software == "cumulus" { - if c, err := cumulusZapi5Command(command, software, true); err == nil { - command = c - } else { - return err - } - } +func parseMessage(hdr *Header, data []byte, software string) (m *Message, err error) { + m = &Message{Header: *hdr} + /* TODO: + InterfaceNBRAddressAdd, InterfaceNBRAddressDelete, + InterfaceBFDDestUpdate, ImportCheckUpdate, BFDDestReplay, + InterfaceVRFUpdate, InterfaceLinkParams, PWStatusUpdate + */ + command := m.Header.Command.toCommon(m.Header.Version, software) switch command { - case FRR_ZAPI5_INTERFACE_ADD, FRR_ZAPI5_INTERFACE_DELETE, FRR_ZAPI5_INTERFACE_UP, FRR_ZAPI5_INTERFACE_DOWN: - m.Body = &InterfaceUpdateBody{} - case FRR_ZAPI5_INTERFACE_ADDRESS_ADD, FRR_ZAPI5_INTERFACE_ADDRESS_DELETE: - m.Body = &InterfaceAddressUpdateBody{} - case FRR_ZAPI5_ROUTER_ID_UPDATE: - m.Body = &RouterIDUpdateBody{} - case FRR_ZAPI5_NEXTHOP_UPDATE: + case interfaceAdd, interfaceDelete, interfaceUp, interfaceDown: + m.Body = &interfaceUpdateBody{} + case interfaceAddressAdd, interfaceAddressDelete: + m.Body = &interfaceAddressUpdateBody{} + case routerIDUpdate: + m.Body = &routerIDUpdateBody{} + case nexthopUpdate: m.Body = &NexthopUpdateBody{} - case FRR_ZAPI5_INTERFACE_NBR_ADDRESS_ADD, FRR_ZAPI5_INTERFACE_NBR_ADDRESS_DELETE: - // TODO - m.Body = &UnknownBody{} - case FRR_ZAPI5_INTERFACE_BFD_DEST_UPDATE: - // TODO - m.Body = &UnknownBody{} - case FRR_ZAPI5_IMPORT_CHECK_UPDATE: - // TODO - m.Body = &UnknownBody{} - case FRR_ZAPI5_BFD_DEST_REPLAY: - // TODO - m.Body = &UnknownBody{} - case FRR_ZAPI5_REDISTRIBUTE_ROUTE_ADD, FRR_ZAPI5_REDISTRIBUTE_ROUTE_DEL: - m.Body = &IPRouteBody{Api: m.Header.Command} - case FRR_ZAPI5_INTERFACE_VRF_UPDATE: - // TODO - m.Body = &UnknownBody{} - case FRR_ZAPI5_INTERFACE_LINK_PARAMS: - // TODO - m.Body = &UnknownBody{} - 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 + case redistributeRouteAdd, redistributeRouteDel: // for frr + m.Body = &IPRouteBody{API: m.Header.Command} + case labelManagerConnect: // Note: Synchronous message + m.Body = &labelManagerConnectBody{} + case getLabelChunk: // 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{} + case releaseLabelChunk: // Note: Synchronous message + m.Body = &releaseLabelChunkBody{} + case vrfLabel: + m.Body = &vrfLabelBody{} + case RouteAdd, RouteDelete, BackwardIPv6RouteAdd, BackwardIPv6RouteDelete: // for quagga + m.Body = &IPRouteBody{API: m.Header.Command} + case ipv4NexthopLookupMRIB: + m.Body = &lookupBody{api: m.Header.Command} default: - m.Body = &UnknownBody{} - } - return m.Body.DecodeFromBytes(data, m.Header.Version, software) -} - -func (m *Message) parseFrrZapi6Message(data []byte, software string) error { - command := m.Header.Command - if software == "frr6" { - if c, err := frr6Zapi6Command(command, software, true); err == nil { - command = c - } else { - return err - } - } else if software == "frr7.2" { - // frr7.2 adds INTERFACE_SET_PROTODOWN between INTERFACE_SET_MASTER(6) and ROUTE_ADD - if command >= FRR_ZAPI6_ROUTE_ADD { - command-- + m.Body = &unknownBody{} + if m.Header.Version == 4 { + switch m.Header.Command { + case zapi4RedistributeIPv6Add, zapi4RedistributeIPv6Del: // for frr3 + m.Body = &IPRouteBody{API: m.Header.Command} + } + } else if m.Header.Version < 4 { + switch m.Header.Command { + case zapi3IPv4NexthopLookup, zapi3IPv6NexthopLookup, zapi3IPv4ImportLookup: + m.Body = &lookupBody{api: m.Header.Command} + } } } - switch command { - case FRR_ZAPI6_INTERFACE_ADD, FRR_ZAPI6_INTERFACE_DELETE, FRR_ZAPI6_INTERFACE_UP, FRR_ZAPI6_INTERFACE_DOWN: - m.Body = &InterfaceUpdateBody{} - case FRR_ZAPI6_INTERFACE_ADDRESS_ADD, FRR_ZAPI6_INTERFACE_ADDRESS_DELETE: - m.Body = &InterfaceAddressUpdateBody{} - case FRR_ZAPI6_ROUTER_ID_UPDATE: - m.Body = &RouterIDUpdateBody{} - case FRR_ZAPI6_NEXTHOP_UPDATE: - m.Body = &NexthopUpdateBody{} - case FRR_ZAPI6_INTERFACE_NBR_ADDRESS_ADD, FRR_ZAPI6_INTERFACE_NBR_ADDRESS_DELETE: - // TODO - m.Body = &UnknownBody{} - case FRR_ZAPI6_INTERFACE_BFD_DEST_UPDATE: - // TODO - m.Body = &UnknownBody{} - case FRR_ZAPI6_IMPORT_CHECK_UPDATE: - // TODO - m.Body = &UnknownBody{} - case FRR_ZAPI6_BFD_DEST_REPLAY: - // TODO - m.Body = &UnknownBody{} - case FRR_ZAPI6_REDISTRIBUTE_ROUTE_ADD, FRR_ZAPI6_REDISTRIBUTE_ROUTE_DEL: - m.Body = &IPRouteBody{Api: command} - case FRR_ZAPI6_INTERFACE_VRF_UPDATE: - // TODO - m.Body = &UnknownBody{} - case FRR_ZAPI6_INTERFACE_LINK_PARAMS: - // TODO - m.Body = &UnknownBody{} - 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{} - } - return m.Body.DecodeFromBytes(data, m.Header.Version, software) -} - -func ParseMessage(hdr *Header, data []byte, software string) (m *Message, err error) { - m = &Message{Header: *hdr} - if m.Header.Version == 4 { - err = m.parseFrrMessage(data, software) - } else if m.Header.Version == 5 { - err = m.parseFrrZapi5Message(data, software) - } else if m.Header.Version == 6 { - err = m.parseFrrZapi6Message(data, software) - } else { - err = m.parseMessage(data, software) - } - if err != nil { - return nil, err - } - return m, nil -} - -// frr6Zapi6Command adjust command (API_TYPE) between Frr6 Zebra and frr7 Zapi6 -func frr6Zapi6Command(command API_TYPE, softwareName string, from bool) (API_TYPE, error) { - if softwareName != "frr6" { - return command, fmt.Errorf("softwareName %s is not supported", softwareName) - } - // frr6 has ZEBRA_IPV4_ROUTE_IPV6_NEXTHOP_ADD (ID:28), frr7 removes it. - // frr7 adds ZEBRA_DUPLICATE_ADDR_DETECTION (ID:72). - if from && FRR_ZAPI6_BFD_DEST_REGISTER < command && command < FRR_ZAPI6_PW_ADD { - // if true, command will be converted from Frr6 Zebra to Frr7 Zapi6 (for parsing) - return command - 1, nil - } else if !from && FRR_ZAPI6_IMPORT_CHECK_UPDATE < command && command < FRR_ZAPI6_DUPLICATE_ADDR_DETECTION { - // if false, command will be converted from Frr7 Zapi6 to Frr6 Zebra (for send) - return command + 1, nil - } - return command, nil -} - -// frr4Zapi5Command adjust command (API_TYPE) between Frr4 Zebra and latest Zapi5 -func frr4Zapi5Command(command API_TYPE, softwareName string, from bool) (API_TYPE, error) { - if softwareName != "frr4" { - return command, fmt.Errorf("softwareName %s is not supported", softwareName) - } - // if from is true, command will be converted from Frr4 Zebra to latest Zapi5 (for parsing) - // if from is false, command will be converted from latest Zapi5 to Frr4 Zebra (for send) - sign := 1 - if !from { - sign = -1 - } - /* - frr5 adds ZEBRA_CAPABILITIES (ID:22), ZEBRA_VRF_LABEL (ID:42), - ZEBRA_LABEL_MANAGER_CONNECT_ASYNC (ID:53), ZEBRA_ADVERTISE_SUBNET (ID:60), - ZEBRA_IP_PREFIX_ROUTE_ADD (ID:70), ZEBRA_IP_PREFIX_ROUTE_DEL (ID:71) and - from ZEBRA_RULE_ADD (ID:79) and ZEBRA_IPTABLE_NOTIFY_OWNER (ID:93) - */ - if FRR_ZAPI5_HELLO < command { // ZEBRA_HELLO: ID:21 in frr4, ID:21 in frr5 - command = API_TYPE(int(command) + sign) - } - if FRR_ZAPI5_VRF_DELETE < command { // ZEBRA_VRF_DELETE: ID:40 in frr4, ID:41 in frr5 - command = API_TYPE(int(command) + sign) - } - // ZEBRA_LABEL_MANAGER_CONNECT : ID:50 in frr4, ID:52 in frr5 - if FRR_ZAPI5_LABEL_MANAGER_CONNECT < command { - command = API_TYPE(int(command) + sign) - } - // ZEBRA_ADVERTISE_DEFAULT_GW : ID:56 in frr4, ID:59 in frr5 - if FRR_ZAPI5_ADVERTISE_DEFAULT_GW < command { - command = API_TYPE(int(command) + sign) - } - // ZEBRA_MACIP_DEL : ID:64 in frr4, ID:69 in frr5 - if FRR_ZAPI5_MACIP_DEL < command { - command = API_TYPE(int(command) + (2 * sign)) - } - // ZBRA_PW_SATUS_UPDATE: ID:72 in frr4, ID:78 in frr5 - if FRR_ZAPI5_PW_STATUS_UPDATE < command { - return command, fmt.Errorf("unsupported command") - } - return command, nil + return m, m.Body.decodeFromBytes(data, m.Header.Version, software) } diff --git a/internal/pkg/zebra/zapi_cumulus.go b/internal/pkg/zebra/zapi_cumulus.go deleted file mode 100644 index ac2a9657..00000000 --- a/internal/pkg/zebra/zapi_cumulus.go +++ /dev/null @@ -1,200 +0,0 @@ -// Copyright (C) 2014, 2015 Nippon Telegraph and Telephone Corporation. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or -// implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -package zebra - -import ( - "fmt" -) - -// For Cumulus Linux 3.7.7, zebra 4.0+cl3u13 (ZAPI version 5) -const ( - FRR_ZAPI5_CL_INTERFACE_ADD API_TYPE = iota - FRR_ZAPI5_CL_INTERFACE_DELETE - FRR_ZAPI5_CL_INTERFACE_ADDRESS_ADD - FRR_ZAPI5_CL_INTERFACE_ADDRESS_DELETE - FRR_ZAPI5_CL_INTERFACE_UP - FRR_ZAPI5_CL_INTERFACE_DOWN - FRR_ZAPI5_CL_INTERFACE_SET_MASTER - FRR_ZAPI5_CL_INTERFACE_SET_PROTODOWN - FRR_ZAPI5_CL_ROUTE_ADD - FRR_ZAPI5_CL_ROUTE_DELETE - FRR_ZAPI5_CL_ROUTE_NOTIFY_OWNER - FRR_ZAPI5_CL_REDISTRIBUTE_ADD - FRR_ZAPI5_CL_REDISTRIBUTE_DELETE - FRR_ZAPI5_CL_REDISTRIBUTE_DEFAULT_ADD - FRR_ZAPI5_CL_REDISTRIBUTE_DEFAULT_DELETE - FRR_ZAPI5_CL_ROUTER_ID_ADD - FRR_ZAPI5_CL_ROUTER_ID_DELETE - FRR_ZAPI5_CL_ROUTER_ID_UPDATE - FRR_ZAPI5_CL_HELLO - FRR_ZAPI5_CL_NEXTHOP_REGISTER - FRR_ZAPI5_CL_NEXTHOP_UNREGISTER - FRR_ZAPI5_CL_NEXTHOP_UPDATE - FRR_ZAPI5_CL_INTERFACE_NBR_ADDRESS_ADD - FRR_ZAPI5_CL_INTERFACE_NBR_ADDRESS_DELETE - FRR_ZAPI5_CL_INTERFACE_BFD_DEST_UPDATE - FRR_ZAPI5_CL_IMPORT_ROUTE_REGISTER - FRR_ZAPI5_CL_IMPORT_ROUTE_UNREGISTER - FRR_ZAPI5_CL_IMPORT_CHECK_UPDATE - FRR_ZAPI5_CL_BFD_DEST_REGISTER - FRR_ZAPI5_CL_BFD_DEST_DEREGISTER - FRR_ZAPI5_CL_BFD_DEST_UPDATE - FRR_ZAPI5_CL_BFD_DEST_REPLAY - FRR_ZAPI5_CL_REDISTRIBUTE_ROUTE_ADD - FRR_ZAPI5_CL_REDISTRIBUTE_ROUTE_DEL - FRR_ZAPI5_CL_VRF_UNREGISTER - FRR_ZAPI5_CL_VRF_ADD - FRR_ZAPI5_CL_VRF_DELETE - FRR_ZAPI5_CL_VRF_LABEL - FRR_ZAPI5_CL_INTERFACE_VRF_UPDATE - FRR_ZAPI5_CL_BFD_CLIENT_REGISTER - FRR_ZAPI5_CL_INTERFACE_ENABLE_RADV - FRR_ZAPI5_CL_INTERFACE_DISABLE_RADV - FRR_ZAPI5_CL_IPV4_NEXTHOP_LOOKUP_MRIB - FRR_ZAPI5_CL_INTERFACE_LINK_PARAMS - FRR_ZAPI5_CL_MPLS_LABELS_ADD - FRR_ZAPI5_CL_MPLS_LABELS_DELETE - FRR_ZAPI5_CL_IPMR_ROUTE_STATS - FRR_ZAPI5_CL_LABEL_MANAGER_CONNECT - FRR_ZAPI5_CL_GET_LABEL_CHUNK - FRR_ZAPI5_CL_RELEASE_LABEL_CHUNK - FRR_ZAPI5_CL_FEC_REGISTER - FRR_ZAPI5_CL_FEC_UNREGISTER - FRR_ZAPI5_CL_FEC_UPDATE - FRR_ZAPI5_CL_ADVERTISE_SVI_MACSTUFF - FRR_ZAPI5_CL_ADVERTISE_DEFAULT_GW - FRR_ZAPI5_CL_ADVERTISE_SUBNET - FRR_ZAPI5_CL_ADVERTISE_ALL_VNI - FRR_ZAPI5_CL_VNI_ADD - FRR_ZAPI5_CL_VNI_DEL - FRR_ZAPI5_CL_L3VNI_ADD - FRR_ZAPI5_CL_L3VNI_DEL - FRR_ZAPI5_CL_REMOTE_VTEP_ADD - FRR_ZAPI5_CL_REMOTE_VTEP_DEL - FRR_ZAPI5_CL_MACIP_ADD - FRR_ZAPI5_CL_MACIP_DEL - FRR_ZAPI5_CL_DAD_STUFF - FRR_ZAPI5_CL_IP_PREFIX_ROUTE_ADD - FRR_ZAPI5_CL_IP_PREFIX_ROUTE_DEL - FRR_ZAPI5_CL_REMOTE_MACIP_ADD - FRR_ZAPI5_CL_REMOTE_MACIP_DEL - FRR_ZAPI5_CL_PW_ADD - FRR_ZAPI5_CL_PW_DELETE - FRR_ZAPI5_CL_PW_SET - FRR_ZAPI5_CL_PW_UNSET - FRR_ZAPI5_CL_PW_STATUS_UPDATE - FRR_ZAPI5_CL_RULE_ADD - FRR_ZAPI5_CL_RULE_DELETE - FRR_ZAPI5_CL_RULE_NOTIFY_OWNER - FRR_ZAPI5_CL_VXLAN_FLOODINATOR -) - -var cumulusZapi5CommandMap = map[API_TYPE]API_TYPE{ - FRR_ZAPI5_CL_INTERFACE_ADD: FRR_ZAPI5_INTERFACE_ADD, - FRR_ZAPI5_CL_INTERFACE_DELETE: FRR_ZAPI5_INTERFACE_DELETE, - FRR_ZAPI5_CL_INTERFACE_ADDRESS_ADD: FRR_ZAPI5_INTERFACE_ADDRESS_ADD, - FRR_ZAPI5_CL_INTERFACE_ADDRESS_DELETE: FRR_ZAPI5_INTERFACE_ADDRESS_DELETE, - FRR_ZAPI5_CL_INTERFACE_UP: FRR_ZAPI5_INTERFACE_UP, - FRR_ZAPI5_CL_INTERFACE_DOWN: FRR_ZAPI5_INTERFACE_DOWN, - FRR_ZAPI5_CL_INTERFACE_SET_MASTER: FRR_ZAPI5_INTERFACE_SET_MASTER, - FRR_ZAPI5_CL_ROUTE_ADD: FRR_ZAPI5_ROUTE_ADD, - FRR_ZAPI5_CL_ROUTE_DELETE: FRR_ZAPI5_ROUTE_DELETE, - FRR_ZAPI5_CL_ROUTE_NOTIFY_OWNER: FRR_ZAPI5_ROUTE_NOTIFY_OWNER, - FRR_ZAPI5_CL_REDISTRIBUTE_ADD: FRR_ZAPI5_REDISTRIBUTE_ADD, - FRR_ZAPI5_CL_REDISTRIBUTE_DELETE: FRR_ZAPI5_REDISTRIBUTE_DELETE, - FRR_ZAPI5_CL_REDISTRIBUTE_DEFAULT_ADD: FRR_ZAPI5_REDISTRIBUTE_DEFAULT_ADD, - FRR_ZAPI5_CL_REDISTRIBUTE_DEFAULT_DELETE: FRR_ZAPI5_REDISTRIBUTE_DEFAULT_DELETE, - FRR_ZAPI5_CL_ROUTER_ID_ADD: FRR_ZAPI5_ROUTER_ID_ADD, - FRR_ZAPI5_CL_ROUTER_ID_DELETE: FRR_ZAPI5_ROUTER_ID_DELETE, - FRR_ZAPI5_CL_ROUTER_ID_UPDATE: FRR_ZAPI5_ROUTER_ID_UPDATE, - FRR_ZAPI5_CL_HELLO: FRR_ZAPI5_HELLO, - FRR_ZAPI5_CL_NEXTHOP_REGISTER: FRR_ZAPI5_NEXTHOP_REGISTER, - FRR_ZAPI5_CL_NEXTHOP_UNREGISTER: FRR_ZAPI5_NEXTHOP_UNREGISTER, - FRR_ZAPI5_CL_NEXTHOP_UPDATE: FRR_ZAPI5_NEXTHOP_UPDATE, - FRR_ZAPI5_CL_INTERFACE_NBR_ADDRESS_ADD: FRR_ZAPI5_INTERFACE_NBR_ADDRESS_ADD, - FRR_ZAPI5_CL_INTERFACE_NBR_ADDRESS_DELETE: FRR_ZAPI5_INTERFACE_NBR_ADDRESS_DELETE, - FRR_ZAPI5_CL_INTERFACE_BFD_DEST_UPDATE: FRR_ZAPI5_INTERFACE_BFD_DEST_UPDATE, - FRR_ZAPI5_CL_IMPORT_ROUTE_REGISTER: FRR_ZAPI5_IMPORT_ROUTE_REGISTER, - FRR_ZAPI5_CL_IMPORT_ROUTE_UNREGISTER: FRR_ZAPI5_IMPORT_ROUTE_REGISTER, - FRR_ZAPI5_CL_IMPORT_CHECK_UPDATE: FRR_ZAPI5_IMPORT_CHECK_UPDATE, - FRR_ZAPI5_CL_BFD_DEST_REGISTER: FRR_ZAPI5_BFD_DEST_REGISTER, - FRR_ZAPI5_CL_BFD_DEST_DEREGISTER: FRR_ZAPI5_BFD_DEST_DEREGISTER, - FRR_ZAPI5_CL_BFD_DEST_UPDATE: FRR_ZAPI5_BFD_DEST_UPDATE, - FRR_ZAPI5_CL_BFD_DEST_REPLAY: FRR_ZAPI5_BFD_DEST_REPLAY, - FRR_ZAPI5_CL_REDISTRIBUTE_ROUTE_ADD: FRR_ZAPI5_REDISTRIBUTE_ROUTE_ADD, - FRR_ZAPI5_CL_REDISTRIBUTE_ROUTE_DEL: FRR_ZAPI5_REDISTRIBUTE_ROUTE_DEL, - FRR_ZAPI5_CL_VRF_UNREGISTER: FRR_ZAPI5_VRF_UNREGISTER, - FRR_ZAPI5_CL_VRF_ADD: FRR_ZAPI5_VRF_ADD, - FRR_ZAPI5_CL_VRF_DELETE: FRR_ZAPI5_VRF_DELETE, - FRR_ZAPI5_CL_VRF_LABEL: FRR_ZAPI5_VRF_LABEL, - FRR_ZAPI5_CL_INTERFACE_VRF_UPDATE: FRR_ZAPI5_INTERFACE_VRF_UPDATE, - FRR_ZAPI5_CL_BFD_CLIENT_REGISTER: FRR_ZAPI5_BFD_CLIENT_REGISTER, - FRR_ZAPI5_CL_INTERFACE_ENABLE_RADV: FRR_ZAPI5_INTERFACE_ENABLE_RADV, - FRR_ZAPI5_CL_INTERFACE_DISABLE_RADV: FRR_ZAPI5_INTERFACE_DISABLE_RADV, - FRR_ZAPI5_CL_IPV4_NEXTHOP_LOOKUP_MRIB: FRR_ZAPI5_IPV4_NEXTHOP_LOOKUP_MRIB, - FRR_ZAPI5_CL_INTERFACE_LINK_PARAMS: FRR_ZAPI5_INTERFACE_LINK_PARAMS, - FRR_ZAPI5_CL_MPLS_LABELS_ADD: FRR_ZAPI5_MPLS_LABELS_ADD, - FRR_ZAPI5_CL_MPLS_LABELS_DELETE: FRR_ZAPI5_MPLS_LABELS_DELETE, - FRR_ZAPI5_CL_IPMR_ROUTE_STATS: FRR_ZAPI5_IPMR_ROUTE_STATS, - FRR_ZAPI5_CL_LABEL_MANAGER_CONNECT: FRR_ZAPI5_LABEL_MANAGER_CONNECT, - FRR_ZAPI5_CL_GET_LABEL_CHUNK: FRR_ZAPI5_GET_LABEL_CHUNK, - FRR_ZAPI5_CL_RELEASE_LABEL_CHUNK: FRR_ZAPI5_RELEASE_LABEL_CHUNK, - FRR_ZAPI5_CL_FEC_REGISTER: FRR_ZAPI5_FEC_REGISTER, - FRR_ZAPI5_CL_FEC_UNREGISTER: FRR_ZAPI5_FEC_UNREGISTER, - FRR_ZAPI5_CL_FEC_UPDATE: FRR_ZAPI5_FEC_UPDATE, - FRR_ZAPI5_CL_ADVERTISE_DEFAULT_GW: FRR_ZAPI5_ADVERTISE_DEFAULT_GW, - FRR_ZAPI5_CL_ADVERTISE_SUBNET: FRR_ZAPI5_ADVERTISE_SUBNET, - FRR_ZAPI5_CL_ADVERTISE_ALL_VNI: FRR_ZAPI5_ADVERTISE_ALL_VNI, - FRR_ZAPI5_CL_VNI_ADD: FRR_ZAPI5_VNI_ADD, - FRR_ZAPI5_CL_VNI_DEL: FRR_ZAPI5_VNI_DEL, - FRR_ZAPI5_CL_L3VNI_ADD: FRR_ZAPI5_L3VNI_ADD, - FRR_ZAPI5_CL_L3VNI_DEL: FRR_ZAPI5_L3VNI_DEL, - FRR_ZAPI5_CL_REMOTE_VTEP_ADD: FRR_ZAPI5_REMOTE_VTEP_ADD, - FRR_ZAPI5_CL_REMOTE_VTEP_DEL: FRR_ZAPI5_REMOTE_VTEP_DEL, - FRR_ZAPI5_CL_MACIP_ADD: FRR_ZAPI5_MACIP_ADD, - FRR_ZAPI5_CL_MACIP_DEL: FRR_ZAPI5_MACIP_DEL, - FRR_ZAPI5_CL_IP_PREFIX_ROUTE_ADD: FRR_ZAPI5_IP_PREFIX_ROUTE_ADD, - FRR_ZAPI5_CL_IP_PREFIX_ROUTE_DEL: FRR_ZAPI5_IP_PREFIX_ROUTE_DEL, - FRR_ZAPI5_CL_REMOTE_MACIP_ADD: FRR_ZAPI5_REMOTE_MACIP_ADD, - FRR_ZAPI5_CL_REMOTE_MACIP_DEL: FRR_ZAPI5_REMOTE_MACIP_DEL, - FRR_ZAPI5_CL_PW_ADD: FRR_ZAPI5_PW_ADD, - FRR_ZAPI5_CL_PW_DELETE: FRR_ZAPI5_PW_DELETE, - FRR_ZAPI5_CL_PW_SET: FRR_ZAPI5_PW_SET, - FRR_ZAPI5_CL_PW_UNSET: FRR_ZAPI5_PW_UNSET, - FRR_ZAPI5_CL_PW_STATUS_UPDATE: FRR_ZAPI5_PW_STATUS_UPDATE, - FRR_ZAPI5_CL_RULE_ADD: FRR_ZAPI5_RULE_ADD, - FRR_ZAPI5_CL_RULE_DELETE: FRR_ZAPI5_RULE_DELETE, - FRR_ZAPI5_CL_RULE_NOTIFY_OWNER: FRR_ZAPI5_RULE_NOTIFY_OWNER, -} - -// cumulusZapi5Command adjust command (API_TYPE) between cumulus Zebra and latest Zapi5 -func cumulusZapi5Command(command API_TYPE, softwareName string, from bool) (API_TYPE, error) { - if softwareName != "cumulus" { - return command, fmt.Errorf("softwareName %s is not supported", softwareName) - } - // if from is true, command will be converted from cumulus Zebra to latest Zapi5 (for parsing) - // if from is false, command will be converted from latest Zapi5 to cumulus Zebra (for send) - if from { - return cumulusZapi5CommandMap[command], nil - } else { - for k, v := range cumulusZapi5CommandMap { - if v == command { - return k, nil - } - } - } - return command, fmt.Errorf("unsupported command") -} diff --git a/internal/pkg/zebra/zapi_test.go b/internal/pkg/zebra/zapi_test.go index b75421c2..1f877d46 100644 --- a/internal/pkg/zebra/zapi_test.go +++ b/internal/pkg/zebra/zapi_test.go @@ -17,32 +17,30 @@ package zebra import ( "encoding/binary" + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" "net" "syscall" "testing" - - "github.com/stretchr/testify/require" - - "github.com/stretchr/testify/assert" ) func Test_Header(t *testing.T) { assert := assert.New(t) - command := map[uint8]API_TYPE{ - 2: IPV4_ROUTE_ADD, - 3: IPV4_ROUTE_ADD, - 4: FRR_IPV4_ROUTE_ADD, - 5: FRR_ZAPI5_IPV4_ROUTE_ADD, - 6: FRR_ZAPI6_ROUTE_ADD, + command := map[uint8]APIType{ + 2: zapi3IPv4RouteAdd, + 3: zapi3IPv4RouteAdd, + 4: zapi4IPv4RouteAdd, + 5: zapi6Frr7RouteAdd, + 6: zapi6Frr7RouteAdd, } for v := MinZapiVer; v <= MaxZapiVer; v++ { - //DecodeFromBytes + //decodeFromBytes buf := make([]byte, HeaderSize(v)) binary.BigEndian.PutUint16(buf[0:], HeaderSize(v)) - buf[2] = HEADER_MARKER + buf[2] = headerMarker if v >= 4 { - buf[2] = FRR_HEADER_MARKER + buf[2] = frrHeaderMarker } buf[3] = v switch v { @@ -56,50 +54,50 @@ func Test_Header(t *testing.T) { binary.BigEndian.PutUint16(buf[8:], uint16(command[v])) } h := &Header{} - err := h.DecodeFromBytes(buf) + err := h.decodeFromBytes(buf) assert.Equal(nil, err) - //Serialize - buf, err = h.Serialize() + //serialize + buf, err = h.serialize() assert.Equal(nil, err) h2 := &Header{} - err = h2.DecodeFromBytes(buf) + err = h2.decodeFromBytes(buf) assert.Equal(nil, err) assert.Equal(h, h2) // header_size mismatch buf = make([]byte, HeaderSize(v)-1) // mismatch value binary.BigEndian.PutUint16(buf[0:], HeaderSize(v)) - buf[2] = HEADER_MARKER + buf[2] = headerMarker if v >= 4 { - buf[2] = FRR_HEADER_MARKER + buf[2] = frrHeaderMarker } buf[3] = v h3 := &Header{} - err = h3.DecodeFromBytes(buf) + err = h3.decodeFromBytes(buf) assert.NotEqual(nil, err, "err should be nil") } } -func Test_InterfaceUpdateBody(t *testing.T) { +func Test_interfaceUpdateBody(t *testing.T) { assert := assert.New(t) - addSize := map[uint8]uint8{2: 39, 3: 44, 4: 50, 5: 50, 6: 50} + addSize := map[uint8]uint8{2: 39, 3: 44, 4: 50, 5: 50, 6: 54} for v := MinZapiVer; v <= MaxZapiVer; v++ { - //DecodeFromBytes - buf := make([]byte, INTERFACE_NAMSIZ+addSize[v]) - pos := INTERFACE_NAMSIZ + //decodeFromBytes + buf := make([]byte, interfaceNameSize+addSize[v]) + pos := interfaceNameSize binary.BigEndian.PutUint32(buf[pos:], 1) //Index pos += 4 - buf[pos] = byte(INTERFACE_ACTIVE) //Status - pos += 1 + buf[pos] = byte(interfaceActive) //Status + pos++ binary.BigEndian.PutUint64(buf[pos:], 1) pos += 8 // flags if v > 3 { - buf[pos] = byte(PTM_ENABLE_OFF) // ptm enable - pos += 1 - buf[pos] = byte(PTM_STATUS_UNKNOWN) // ptm status - pos += 1 + buf[pos] = byte(ptmEnableOff) // ptm enable + pos++ + buf[pos] = byte(ptmStatusUnknown) // ptm status + pos++ } binary.BigEndian.PutUint32(buf[pos:], 1) pos += 4 // metric @@ -112,9 +110,13 @@ func Test_InterfaceUpdateBody(t *testing.T) { binary.BigEndian.PutUint32(buf[pos:], 1500) pos += 4 // MTU6 binary.BigEndian.PutUint32(buf[pos:], 200) - pos += 4 // bandwidth + pos += 4 // bandwidth + if v == 6 { // "frr7.2", "frr7.3", "" + binary.BigEndian.PutUint32(buf[pos:], 1) + pos += 4 // link Ifindex + } if v > 2 { - binary.BigEndian.PutUint32(buf[pos:], uint32(LINK_TYPE_ETHER)) + binary.BigEndian.PutUint32(buf[pos:], uint32(linkTypeEther)) pos += 4 // Linktype } binary.BigEndian.PutUint32(buf[pos:], 6) @@ -124,84 +126,84 @@ func Test_InterfaceUpdateBody(t *testing.T) { pos += 6 if v > 2 { buf[pos] = byte(0) // link param - pos += 1 + pos++ } - b := &InterfaceUpdateBody{} - err := b.DecodeFromBytes(buf, v, "") + b := &interfaceUpdateBody{} + err := b.decodeFromBytes(buf, v, "") assert.Equal(nil, err) - assert.Equal("01:23:45:67:89:ab", b.HardwareAddr.String()) - buf = make([]byte, INTERFACE_NAMSIZ+32) //size mismatch - b = &InterfaceUpdateBody{} - err = b.DecodeFromBytes(buf, v, "") + assert.Equal("01:23:45:67:89:ab", b.hardwareAddr.String()) + buf = make([]byte, interfaceNameSize+32) //size mismatch + b = &interfaceUpdateBody{} + err = b.decodeFromBytes(buf, v, "") assert.NotEqual(nil, err) } } -func Test_InterfaceAddressUpdateBody(t *testing.T) { +func Test_interfaceAddressUpdateBody(t *testing.T) { assert := assert.New(t) for v := MinZapiVer; v <= MaxZapiVer; v++ { - //DecodeFromBytes + //decodeFromBytes buf := make([]byte, 15) pos := 0 binary.BigEndian.PutUint32(buf[pos:], 0) // index pos += 4 buf[pos] = 0x01 // flags - pos += 1 + pos++ buf[pos] = 0x2 // family - pos += 1 + pos++ ip := net.ParseIP("192.168.100.1").To4() // prefix copy(buf[pos:pos+4], []byte(ip)) pos += 4 buf[pos] = byte(24) // prefix len - pos += 1 + pos++ dst := net.ParseIP("192.168.100.255").To4() // destination copy(buf[pos:pos+4], []byte(dst)) - b := &InterfaceAddressUpdateBody{} - err := b.DecodeFromBytes(buf, v, "") + b := &interfaceAddressUpdateBody{} + err := b.decodeFromBytes(buf, v, "") require.NoError(t, err) - assert.Equal(uint32(0), b.Index) - assert.Equal(INTERFACE_ADDRESS_FLAG(1), b.Flags) - assert.Equal("192.168.100.1", b.Prefix.String()) - assert.Equal(uint8(24), b.Length) - assert.Equal("192.168.100.255", b.Destination.String()) + assert.Equal(uint32(0), b.index) + assert.Equal(interfaceAddressFlag(1), b.flags) + assert.Equal("192.168.100.1", b.prefix.String()) + assert.Equal(uint8(24), b.length) + assert.Equal("192.168.100.255", b.destination.String()) // af invalid buf[5] = 0x4 - pos += 1 - b = &InterfaceAddressUpdateBody{} - err = b.DecodeFromBytes(buf, v, "") + pos++ + b = &interfaceAddressUpdateBody{} + err = b.decodeFromBytes(buf, v, "") assert.NotEqual(nil, err) } } -func Test_RouterIDUpdateBody(t *testing.T) { +func Test_routerIDUpdateBody(t *testing.T) { assert := assert.New(t) for v := MinZapiVer; v <= MaxZapiVer; v++ { - //DecodeFromBytes + //decodeFromBytes buf := make([]byte, 6) pos := 0 buf[pos] = 0x2 - pos += 1 + pos++ ip := net.ParseIP("192.168.100.1").To4() copy(buf[pos:pos+4], []byte(ip)) pos += 4 buf[pos] = byte(32) - b := &RouterIDUpdateBody{} - err := b.DecodeFromBytes(buf, v, "") + b := &routerIDUpdateBody{} + err := b.decodeFromBytes(buf, v, "") assert.Equal(nil, err) - assert.Equal("192.168.100.1", b.Prefix.String()) - assert.Equal(uint8(32), b.Length) + assert.Equal("192.168.100.1", b.prefix.String()) + assert.Equal(uint8(32), b.length) // af invalid buf[0] = 0x4 - pos += 1 - b = &RouterIDUpdateBody{} - err = b.DecodeFromBytes(buf, v, "") + pos++ + b = &routerIDUpdateBody{} + err = b.decodeFromBytes(buf, v, "") assert.NotEqual(nil, err) } } @@ -209,92 +211,91 @@ 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: 38} - command := map[uint8]API_TYPE{ - 2: IPV4_ROUTE_ADD, - 3: IPV4_ROUTE_ADD, - 4: FRR_IPV4_ROUTE_ADD, - 5: FRR_ZAPI5_IPV4_ROUTE_ADD, - 6: FRR_ZAPI6_ROUTE_ADD, - } - routeType := map[uint8]ROUTE_TYPE{ - 2: ROUTE_CONNECT, - 3: ROUTE_CONNECT, - 4: FRR_ROUTE_CONNECT, - 5: FRR_ZAPI5_ROUTE_CONNECT, - 6: FRR_ZAPI6_ROUTE_CONNECT, + size := map[uint8]uint8{2: 26, 3: 26, 4: 31, 5: 38, 6: 39} + command := map[uint8]APIType{ + 2: zapi3IPv4RouteAdd, + 3: zapi3IPv4RouteAdd, + 4: zapi4IPv4RouteAdd, + 5: zapi6Frr7RouteAdd, + 6: zapi6Frr7RouteAdd, } - message := map[uint8]MESSAGE_FLAG{ - 2: MESSAGE_NEXTHOP | MESSAGE_IFINDEX | MESSAGE_DISTANCE | MESSAGE_METRIC | MESSAGE_MTU, - 3: MESSAGE_NEXTHOP | MESSAGE_IFINDEX | MESSAGE_DISTANCE | MESSAGE_METRIC | MESSAGE_MTU, - 4: FRR_MESSAGE_NEXTHOP | FRR_MESSAGE_IFINDEX | FRR_MESSAGE_DISTANCE | FRR_MESSAGE_METRIC | FRR_MESSAGE_MTU, - 5: FRR_ZAPI5_MESSAGE_NEXTHOP | FRR_ZAPI5_MESSAGE_DISTANCE | FRR_ZAPI5_MESSAGE_METRIC | FRR_ZAPI5_MESSAGE_MTU, - 6: FRR_ZAPI5_MESSAGE_NEXTHOP | FRR_ZAPI5_MESSAGE_DISTANCE | FRR_ZAPI5_MESSAGE_METRIC | FRR_ZAPI5_MESSAGE_MTU, + routeType := routeConnect + message := map[uint8]MessageFlag{ + 2: MessageNexthop | messageIFIndex | zapi4MessageDistance | zapi4MessageMetric | zapi3MessageMTU, + 3: MessageNexthop | messageIFIndex | zapi4MessageDistance | zapi4MessageMetric | zapi3MessageMTU, + 4: MessageNexthop | messageIFIndex | zapi4MessageDistance | zapi4MessageMetric | zapi4MessageMTU, + 5: MessageNexthop | MessageDistance | MessageMetric | MessageMTU, + 6: MessageNexthop | MessageDistance | MessageMetric | MessageMTU, } - messageWithoutNexthop := map[uint8]MESSAGE_FLAG{ - 2: MESSAGE_DISTANCE | MESSAGE_METRIC, - 3: MESSAGE_DISTANCE | MESSAGE_METRIC, - 4: FRR_MESSAGE_DISTANCE | FRR_MESSAGE_METRIC, - 5: FRR_ZAPI5_MESSAGE_DISTANCE | FRR_ZAPI5_MESSAGE_METRIC, - 6: FRR_ZAPI5_MESSAGE_DISTANCE | FRR_ZAPI5_MESSAGE_METRIC, + messageWithoutNexthop := map[uint8]MessageFlag{ + 2: zapi4MessageDistance | zapi4MessageMetric, + 3: zapi4MessageDistance | zapi4MessageMetric, + 4: zapi4MessageDistance | zapi4MessageMetric, + 5: MessageDistance | MessageMetric, + 6: MessageDistance | MessageMetric, } for v := MinZapiVer; v <= MaxZapiVer; v++ { - //DecodeFromBytes IPV4_ROUTE + //decodeFromBytes IPV4_ROUTE buf := make([]byte, size[v]) - buf[0] = byte(routeType[v]) + //buf[0] = byte(routeType[v]) + buf[0] = byte(routeType) pos := 1 switch v { case 2, 3: - buf[pos] = byte(FLAG_SELECTED) - pos += 1 + buf[pos] = byte(FlagSelected.ToEach(v, "")) + pos++ case 4, 5, 6: binary.BigEndian.PutUint16(buf[pos:], 0) //Instance pos += 2 - binary.BigEndian.PutUint32(buf[pos:], uint32(FLAG_SELECTED)) + binary.BigEndian.PutUint32(buf[pos:], uint32(FlagSelected.ToEach(v, ""))) pos += 4 } buf[pos] = byte(message[v]) - pos += 1 + pos++ if v > 4 { - buf[pos] = byte(FRR_ZAPI5_SAFI_UNICAST) //SAFI - pos += 1 + buf[pos] = byte(SafiUnicast) //SAFI + pos++ buf[pos] = byte(syscall.AF_INET) //Family - pos += 1 + pos++ } buf[pos] = 24 // PrefixLen - pos += 1 + pos++ ip := net.ParseIP("192.168.100.0").To4() copy(buf[pos:pos+3], []byte(ip)) pos += 3 switch v { case 2, 3, 4: buf[pos] = byte(1) // Number of Nexthops - pos += 1 + pos++ case 5, 6: binary.BigEndian.PutUint16(buf[pos:], 1) // Number of Nexthops pos += 2 binary.BigEndian.PutUint32(buf[pos:], 0) // vrfid pos += 4 - buf[pos] = byte(FRR_NEXTHOP_TYPE_IPV4_IFINDEX) - pos += 1 + buf[pos] = byte(nexthopTypeIPv4IFIndex) + pos++ + } + if v == 6 { //onlink (frr7,1, 7.2, 7.3) + buf[pos] = 1 + pos++ } nexthop := net.ParseIP("0.0.0.0").To4() copy(buf[pos:pos+4], []byte(nexthop)) pos += 4 if v < 5 { - buf[pos] = 1 // Number of ifindex - pos += 1 + buf[pos] = 1 // Number of Ifindex + pos++ } - binary.BigEndian.PutUint32(buf[pos:], 1) // ifindex + binary.BigEndian.PutUint32(buf[pos:], 1) // Ifindex pos += 4 buf[pos] = 0 // distance - pos += 1 + pos++ binary.BigEndian.PutUint32(buf[pos:], 1) // metric pos += 4 binary.BigEndian.PutUint32(buf[pos:], 1) // mtu pos += 4 - r := &IPRouteBody{Api: command[v]} - err := r.DecodeFromBytes(buf, v, "") + r := &IPRouteBody{API: command[v]} + err := r.decodeFromBytes(buf, v, "") assert.Equal(nil, err) assert.Equal("192.168.100.0", r.Prefix.Prefix.String()) assert.Equal(uint8(0x18), r.Prefix.PrefixLen) @@ -310,15 +311,16 @@ func Test_IPRouteBody_IPv4(t *testing.T) { assert.Equal(uint32(1), r.Metric) assert.Equal(uint32(1), r.Mtu) - //Serialize - buf, err = r.Serialize(v, "") + //serialize + buf, err = r.serialize(v, "") assert.Equal(nil, err) switch v { case 2, 3: assert.Equal([]byte{0x2, 0x10, byte(message[v])}, buf[0:3]) pos = 3 case 4, 5, 6: - assert.Equal([]byte{0x2, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, byte(message[v])}, buf[0:8]) + tmpFlag := byte(0xff & FlagSelected.ToEach(v, "")) + assert.Equal([]byte{0x2, 0x00, 0x00, 0x00, 0x00, 0x00, tmpFlag, byte(message[v])}, buf[0:8]) pos = 8 } switch v { @@ -327,20 +329,20 @@ func Test_IPRouteBody_IPv4(t *testing.T) { pos += 2 case 5, 6: assert.Equal(byte(0x1), buf[pos]) // SAFI - pos += 1 + pos++ assert.Equal(byte(0x2), buf[pos]) // Family - pos += 1 + pos++ } assert.Equal(byte(24), buf[pos]) - pos += 1 + pos++ ip = net.ParseIP("192.168.100.0").To4() assert.Equal([]byte(ip)[0:3], buf[pos:pos+3]) pos += 3 switch v { case 2, 3, 4: assert.Equal(byte(2), buf[pos]) // number of nexthop - pos += 1 + pos++ case 5, 6: assert.Equal([]byte{0x0, 0x1}, buf[pos:pos+2]) // number of nexthop pos += 2 @@ -349,17 +351,21 @@ func Test_IPRouteBody_IPv4(t *testing.T) { } switch v { case 2, 3: - assert.Equal(byte(NEXTHOP_TYPE_IPV4), buf[pos]) - assert.Equal(byte(NEXTHOP_TYPE_IFINDEX), buf[pos+5]) + assert.Equal(byte(backwardNexthopTypeIPv4), buf[pos]) + assert.Equal(byte(nexthopTypeIFIndex), buf[pos+5]) pos += 10 case 4: - assert.Equal(byte(FRR_NEXTHOP_TYPE_IPV4), buf[pos]) - assert.Equal(byte(FRR_NEXTHOP_TYPE_IFINDEX), buf[pos+5]) + assert.Equal(byte(nexthopTypeIPv4), buf[pos]) + assert.Equal(byte(nexthopTypeIFIndex), buf[pos+5]) pos += 10 case 5, 6: - assert.Equal(byte(FRR_NEXTHOP_TYPE_IPV4_IFINDEX), buf[pos]) + assert.Equal(byte(nexthopTypeIPv4IFIndex), buf[pos]) pos += 9 } + if v == 6 { //onlink (frr7,1, 7.2, 7.3) + assert.Equal(byte(0x1), buf[pos]) + pos++ + } assert.Equal(byte(0x0), buf[pos]) // distance bi := make([]byte, 4) binary.BigEndian.PutUint32(bi, 1) @@ -368,199 +374,206 @@ func Test_IPRouteBody_IPv4(t *testing.T) { // length invalid buf = make([]byte, size[v]-8) - buf[0] = byte(routeType[v]) + //buf[0] = byte(routeType[v]) + buf[0] = byte(routeConnect) pos = 1 switch v { case 2, 3: - buf[pos] = byte(FLAG_SELECTED) - pos += 1 + buf[pos] = byte(FlagSelected.ToEach(v, "")) + pos++ case 4, 5, 6: binary.BigEndian.PutUint16(buf[pos:], 0) //Instance pos += 2 - binary.BigEndian.PutUint32(buf[pos:], uint32(FLAG_SELECTED)) + binary.BigEndian.PutUint32(buf[pos:], uint32(FlagSelected.ToEach(v, ""))) pos += 4 } buf[pos] = byte(message[v]) - pos += 1 + pos++ if v > 4 { - buf[pos] = byte(FRR_ZAPI5_SAFI_UNICAST) //SAFI - pos += 1 + buf[pos] = byte(SafiUnicast) //SAFI + pos++ buf[pos] = byte(syscall.AF_INET) //Family - pos += 1 + pos++ } buf[pos] = 24 // PrefixLen - pos += 1 + pos++ ip = net.ParseIP("192.168.100.0").To4() copy(buf[pos:pos+3], []byte(ip)) pos += 3 switch v { case 2, 3, 4: buf[pos] = byte(1) // Number of Nexthops - pos += 1 + pos++ case 5, 6: binary.BigEndian.PutUint16(buf[pos:], 1) // Number of Nexthops pos += 2 binary.BigEndian.PutUint32(buf[pos:], 0) // vrfid pos += 4 - buf[pos] = byte(FRR_NEXTHOP_TYPE_IPV4_IFINDEX) - pos += 1 + buf[pos] = byte(nexthopTypeIPv4IFIndex) + pos++ + } + if v == 6 { //onlink (frr7,1, 7.2, 7.3) + buf[pos] = 1 + pos++ } nexthop = net.ParseIP("0.0.0.0").To4() copy(buf[pos:pos+4], []byte(nexthop)) pos += 4 if v < 5 { - buf[pos] = 1 // Number of ifindex - pos += 1 + buf[pos] = 1 // Number of Ifindex + pos++ } - binary.BigEndian.PutUint32(buf[pos:], 1) // ifindex + binary.BigEndian.PutUint32(buf[pos:], 1) // Ifindex pos += 4 - r = &IPRouteBody{Api: command[v]} - err = r.DecodeFromBytes(buf, v, "") + r = &IPRouteBody{API: command[v]} + err = r.decodeFromBytes(buf, v, "") switch v { case 2, 3, 4: - assert.Equal("MESSAGE_METRIC message length invalid pos:14 rest:14", err.Error()) - case 5, 6: - assert.Equal("MESSAGE_METRIC message length invalid pos:19 rest:19", err.Error()) + assert.Equal("MessageMetric message length invalid pos:14 rest:14", err.Error()) + case 5: + assert.Equal("MessageMetric message length invalid pos:19 rest:19", err.Error()) + case 6: + assert.Equal("MessageMetric message length invalid pos:20 rest:20", err.Error()) } // no nexthop switch v { case 2, 3, 4: buf = make([]byte, size[v]-14) - case 5, 6: + case 5: buf = make([]byte, size[v]-19) + case 6: + buf = make([]byte, size[v]-20) } - buf[0] = byte(routeType[v]) + buf[0] = byte(routeType) pos = 1 switch v { case 2, 3: - buf[pos] = byte(FLAG_SELECTED) - pos += 1 + buf[pos] = byte(FlagSelected.ToEach(v, "")) + pos++ case 4, 5, 6: binary.BigEndian.PutUint16(buf[pos:], 0) //Instance pos += 2 - binary.BigEndian.PutUint32(buf[pos:], uint32(FLAG_SELECTED)) + binary.BigEndian.PutUint32(buf[pos:], uint32(FlagSelected.ToEach(v, ""))) pos += 4 } buf[pos] = byte(messageWithoutNexthop[v]) - pos += 1 + pos++ if v > 4 { - buf[pos] = byte(FRR_ZAPI5_SAFI_UNICAST) //SAFI - pos += 1 + buf[pos] = byte(SafiUnicast) //SAFI + pos++ buf[pos] = byte(syscall.AF_INET) //Family - pos += 1 + pos++ } buf[pos] = 24 // PrefixLen - pos += 1 + pos++ ip = net.ParseIP("192.168.100.0").To4() copy(buf[pos:pos+3], []byte(ip)) pos += 3 buf[pos] = 1 // distance - pos += 1 + pos++ binary.BigEndian.PutUint32(buf[pos:], 0) //metric pos += 4 - r = &IPRouteBody{Api: command[v]} - err = r.DecodeFromBytes(buf, v, "") + r = &IPRouteBody{API: command[v]} + err = r.decodeFromBytes(buf, v, "") assert.Equal(nil, err) } } func Test_IPRouteBody_IPv6(t *testing.T) { assert := assert.New(t) - size := map[uint8]uint8{2: 43, 3: 43, 4: 48, 5: 55, 6: 55} - command := map[uint8]API_TYPE{ - 2: IPV6_ROUTE_ADD, - 3: IPV6_ROUTE_ADD, - 4: FRR_IPV6_ROUTE_ADD, - 5: FRR_ZAPI5_IPV6_ROUTE_ADD, - 6: FRR_ZAPI6_ROUTE_ADD, - } - routeType := map[uint8]ROUTE_TYPE{ - 2: ROUTE_CONNECT, - 3: ROUTE_CONNECT, - 4: FRR_ROUTE_CONNECT, - 5: FRR_ZAPI5_ROUTE_CONNECT, - 6: FRR_ZAPI6_ROUTE_CONNECT, + size := map[uint8]uint8{2: 43, 3: 43, 4: 48, 5: 55, 6: 56} + command := map[uint8]APIType{ + 2: zapi3IPv6RouteAdd, + 3: zapi3IPv6RouteAdd, + 4: zapi4IPv6RouteAdd, + 5: zapi6Frr7RouteAdd, + 6: zapi6Frr7RouteAdd, } - message := map[uint8]MESSAGE_FLAG{ - 2: MESSAGE_NEXTHOP | MESSAGE_IFINDEX | MESSAGE_DISTANCE | MESSAGE_METRIC | MESSAGE_MTU, - 3: MESSAGE_NEXTHOP | MESSAGE_IFINDEX | MESSAGE_DISTANCE | MESSAGE_METRIC | MESSAGE_MTU, - 4: FRR_MESSAGE_NEXTHOP | FRR_MESSAGE_IFINDEX | FRR_MESSAGE_DISTANCE | FRR_MESSAGE_METRIC | FRR_MESSAGE_MTU, - 5: FRR_ZAPI5_MESSAGE_NEXTHOP | FRR_ZAPI5_MESSAGE_DISTANCE | FRR_ZAPI5_MESSAGE_METRIC | FRR_ZAPI5_MESSAGE_MTU, - 6: FRR_ZAPI5_MESSAGE_NEXTHOP | FRR_ZAPI5_MESSAGE_DISTANCE | FRR_ZAPI5_MESSAGE_METRIC | FRR_ZAPI5_MESSAGE_MTU, + routeType := routeConnect + message := map[uint8]MessageFlag{ + 2: MessageNexthop | messageIFIndex | zapi4MessageDistance | zapi4MessageMetric | zapi3MessageMTU, + 3: MessageNexthop | messageIFIndex | zapi4MessageDistance | zapi4MessageMetric | zapi3MessageMTU, + 4: MessageNexthop | messageIFIndex | zapi4MessageDistance | zapi4MessageMetric | zapi4MessageMTU, + 5: MessageNexthop | MessageDistance | MessageMetric | MessageMTU, + 6: MessageNexthop | MessageDistance | MessageMetric | MessageMTU, } - nexthopType := map[uint8]NEXTHOP_TYPE{ - 2: NEXTHOP_TYPE_IPV6, - 3: NEXTHOP_TYPE_IPV6, - 4: FRR_NEXTHOP_TYPE_IPV6, - 5: FRR_NEXTHOP_TYPE_IPV6_IFINDEX, - 6: FRR_NEXTHOP_TYPE_IPV6_IFINDEX, + nexthopType := map[uint8]nexthopType{ + 2: backwardNexthopTypeIPv6, + 3: backwardNexthopTypeIPv6, + 4: nexthopTypeIPv6, + 5: nexthopTypeIPv6IFIndex, + 6: nexthopTypeIPv6IFIndex, } - messageWithoutNexthop := map[uint8]MESSAGE_FLAG{ - 2: MESSAGE_DISTANCE | MESSAGE_METRIC, - 3: MESSAGE_DISTANCE | MESSAGE_METRIC, - 4: FRR_MESSAGE_DISTANCE | FRR_MESSAGE_METRIC, - 5: FRR_ZAPI5_MESSAGE_DISTANCE | FRR_ZAPI5_MESSAGE_METRIC, - 6: FRR_ZAPI5_MESSAGE_DISTANCE | FRR_ZAPI5_MESSAGE_METRIC, + messageWithoutNexthop := map[uint8]MessageFlag{ + 2: zapi4MessageDistance | zapi4MessageMetric, + 3: zapi4MessageDistance | zapi4MessageMetric, + 4: zapi4MessageDistance | zapi4MessageMetric, + 5: MessageDistance | MessageMetric, + 6: MessageDistance | MessageMetric, } for v := MinZapiVer; v <= MaxZapiVer; v++ { - //DecodeFromBytes IPV6_ROUTE + //decodeFromBytes IPV6_ROUTE buf := make([]byte, size[v]) - buf[0] = byte(routeType[v]) + buf[0] = byte(routeType) pos := 1 switch v { case 2, 3: - buf[pos] = byte(FLAG_SELECTED) - pos += 1 + buf[pos] = byte(FlagSelected.ToEach(v, "")) + pos++ case 4, 5, 6: binary.BigEndian.PutUint16(buf[pos:], 0) //Instance pos += 2 - binary.BigEndian.PutUint32(buf[pos:], uint32(FLAG_SELECTED)) + binary.BigEndian.PutUint32(buf[pos:], uint32(FlagSelected.ToEach(v, ""))) pos += 4 } buf[pos] = byte(message[v]) - pos += 1 + pos++ if v > 4 { - buf[pos] = byte(FRR_ZAPI5_SAFI_UNICAST) //SAFI - pos += 1 + buf[pos] = byte(SafiUnicast) //SAFI + pos++ buf[pos] = byte(syscall.AF_INET6) //Family - pos += 1 + pos++ } buf[pos] = 64 // prefixLen - pos += 1 + pos++ ip := net.ParseIP("2001:db8:0:f101::").To16() copy(buf[pos:pos+8], []byte(ip)) pos += 8 switch v { case 2, 3, 4: buf[pos] = byte(1) // Number of Nexthops - pos += 1 + pos++ case 5, 6: binary.BigEndian.PutUint16(buf[pos:], 1) // Number of Nexthops pos += 2 binary.BigEndian.PutUint32(buf[pos:], 0) // vrfid pos += 4 - buf[pos] = byte(FRR_NEXTHOP_TYPE_IPV6_IFINDEX) - pos += 1 + buf[pos] = byte(nexthopTypeIPv6IFIndex) + pos++ + } + if v == 6 { //onlink (frr7,1, 7.2, 7.3) + buf[pos] = 1 + pos++ } nexthop := net.ParseIP("::").To16() copy(buf[pos:pos+16], []byte(nexthop)) pos += 16 if v < 5 { - buf[pos] = 1 // Number of ifindex - pos += 1 + buf[pos] = 1 // Number of Ifindex + pos++ } - binary.BigEndian.PutUint32(buf[pos:], 1) // ifindex + binary.BigEndian.PutUint32(buf[pos:], 1) // Ifindex pos += 4 buf[pos] = 0 // distance - pos += 1 + pos++ binary.BigEndian.PutUint32(buf[pos:], 1) // metric pos += 4 binary.BigEndian.PutUint32(buf[pos:], 1) // mtu pos += 4 - r := &IPRouteBody{Api: command[v]} - err := r.DecodeFromBytes(buf, v, "") + r := &IPRouteBody{API: command[v]} + err := r.decodeFromBytes(buf, v, "") assert.Equal(nil, err) assert.Equal("2001:db8:0:f101::", r.Prefix.Prefix.String()) assert.Equal(uint8(64), r.Prefix.PrefixLen) @@ -576,15 +589,16 @@ func Test_IPRouteBody_IPv6(t *testing.T) { assert.Equal(uint32(1), r.Metric) assert.Equal(uint32(1), r.Mtu) - //Serialize - buf, err = r.Serialize(v, "") + //serialize + buf, err = r.serialize(v, "") assert.Equal(nil, err) switch v { case 2, 3: assert.Equal([]byte{0x2, 0x10, byte(message[v])}, buf[0:3]) pos = 3 case 4, 5, 6: - assert.Equal([]byte{0x2, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, byte(message[v])}, buf[0:8]) + tmpFlag := byte(0xff & FlagSelected.ToEach(v, "")) + assert.Equal([]byte{0x2, 0x00, 0x00, 0x00, 0x00, 0x00, tmpFlag, byte(message[v])}, buf[0:8]) pos = 8 } switch v { @@ -593,19 +607,19 @@ func Test_IPRouteBody_IPv6(t *testing.T) { pos += 2 case 5, 6: assert.Equal(byte(0x1), buf[pos]) // SAFI - pos += 1 + pos++ assert.Equal(byte(syscall.AF_INET6), buf[pos]) // Family - pos += 1 + pos++ } assert.Equal(byte(64), buf[pos]) - pos += 1 + pos++ ip = net.ParseIP("2001:db8:0:f101::").To16() assert.Equal([]byte(ip)[0:8], buf[pos:pos+8]) pos += 8 switch v { case 2, 3, 4: assert.Equal(byte(2), buf[pos]) // number of nexthop - pos += 1 + pos++ case 5, 6: assert.Equal([]byte{0x0, 0x1}, buf[pos:pos+2]) // number of nexthop pos += 2 @@ -613,21 +627,25 @@ func Test_IPRouteBody_IPv6(t *testing.T) { pos += 4 } assert.Equal(byte(nexthopType[v]), buf[pos]) - pos += 1 + pos++ + if v == 6 { //onlink (frr7,1, 7.2, 7.3) + assert.Equal(byte(0x1), buf[pos]) + pos++ + } ip = net.ParseIP("::").To16() assert.Equal([]byte(ip), buf[pos:pos+16]) pos += 16 switch v { // Only Quagga (ZAPI version 2,3) and FRR 3.x (ZAPI version 4) case 2, 3: - assert.Equal(byte(NEXTHOP_TYPE_IFINDEX), buf[pos]) - pos += 1 + assert.Equal(byte(nexthopTypeIFIndex), buf[pos]) + pos++ case 4: - assert.Equal(byte(FRR_NEXTHOP_TYPE_IFINDEX), buf[pos]) - pos += 1 + assert.Equal(byte(nexthopTypeIFIndex), buf[pos]) + pos++ } bi := make([]byte, 4) binary.BigEndian.PutUint32(bi, 1) - assert.Equal(bi, buf[pos:pos+4]) // ifindex + assert.Equal(bi, buf[pos:pos+4]) // Ifindex pos += 4 assert.Equal(byte(0x0), buf[pos]) // distance assert.Equal(bi, buf[pos+1:pos+5]) //metric @@ -635,147 +653,159 @@ func Test_IPRouteBody_IPv6(t *testing.T) { // length invalid buf = make([]byte, size[v]+7) - buf[0] = byte(routeType[v]) + buf[0] = byte(routeType) pos = 1 switch v { case 2, 3: - buf[pos] = byte(FLAG_SELECTED) - pos += 1 + buf[pos] = byte(FlagSelected.ToEach(v, "")) + pos++ case 4, 5, 6: binary.BigEndian.PutUint16(buf[pos:], 0) //Instance pos += 2 - binary.BigEndian.PutUint32(buf[pos:], uint32(FLAG_SELECTED)) + binary.BigEndian.PutUint32(buf[pos:], uint32(FlagSelected.ToEach(v, ""))) pos += 4 } buf[pos] = byte(message[v]) - pos += 1 + pos++ if v > 4 { - buf[pos] = byte(FRR_ZAPI5_SAFI_UNICAST) //SAFI - pos += 1 + buf[pos] = byte(SafiUnicast) //SAFI + pos++ buf[pos] = byte(syscall.AF_INET6) //Family - pos += 1 + pos++ } buf[pos] = 64 // prefixLen - pos += 1 + pos++ ip = net.ParseIP("2001:db8:0:f101::").To16() copy(buf[pos:pos+8], []byte(ip)) pos += 8 switch v { case 2, 3, 4: buf[pos] = byte(1) // Number of Nexthops - pos += 1 + pos++ case 5, 6: binary.BigEndian.PutUint16(buf[pos:], 1) // Number of Nexthops pos += 2 binary.BigEndian.PutUint32(buf[pos:], 0) // vrfid pos += 4 - buf[pos] = byte(FRR_NEXTHOP_TYPE_IPV6_IFINDEX) - pos += 1 + buf[pos] = byte(nexthopTypeIPv6IFIndex) + pos++ + } + if v == 6 { //onlink (frr7,1, 7.2, 7.3) + buf[pos] = 1 + pos++ } nexthop = net.ParseIP("::").To16() copy(buf[pos:pos+16], []byte(nexthop)) pos += 16 if v < 5 { - buf[pos] = 1 // Number of ifindex - pos += 1 + buf[pos] = 1 // Number of Ifindex + pos++ } - binary.BigEndian.PutUint32(buf[pos:], 1) // ifindex + binary.BigEndian.PutUint32(buf[pos:], 1) // Ifindex pos += 4 - r = &IPRouteBody{Api: command[v]} - err = r.DecodeFromBytes(buf, v, "") + r = &IPRouteBody{API: command[v]} + err = r.decodeFromBytes(buf, v, "") switch v { - case 2, 3, 4: - assert.Equal("message length invalid pos:39 rest:46", err.Error()) - case 5, 6: - assert.Equal("message length invalid pos:44 rest:51", err.Error()) + case 2, 3: + assert.Equal("message length invalid (last) pos:39 rest:46, message:0x1f", err.Error()) + case 4: + assert.Equal("message length invalid (last) pos:39 rest:46, message:0x2f", err.Error()) + case 5: + assert.Equal("message length invalid (last) pos:44 rest:51, message:0x17", err.Error()) + case 6: + assert.Equal("message length invalid (last) pos:45 rest:52, message:0x17", err.Error()) } // no nexthop switch v { case 2, 3, 4: buf = make([]byte, size[v]-32) - case 5, 6: + case 5: buf = make([]byte, size[v]-37) + case 6: + buf = make([]byte, size[v]-38) } - buf[0] = byte(routeType[v]) + buf[0] = byte(routeType) pos = 1 switch v { case 2, 3: - buf[pos] = byte(FLAG_SELECTED) - pos += 1 + buf[pos] = byte(FlagSelected.ToEach(v, "")) + pos++ case 4, 5, 6: binary.BigEndian.PutUint16(buf[pos:], 0) //Instance pos += 2 - binary.BigEndian.PutUint32(buf[pos:], uint32(FLAG_SELECTED)) + binary.BigEndian.PutUint32(buf[pos:], uint32(FlagSelected.ToEach(v, ""))) pos += 4 } buf[pos] = byte(messageWithoutNexthop[v]) - pos += 1 + pos++ if v > 4 { - buf[pos] = byte(FRR_ZAPI5_SAFI_UNICAST) //SAFI - pos += 1 + buf[pos] = byte(SafiUnicast) //SAFI + pos++ buf[pos] = byte(syscall.AF_INET) //Family - pos += 1 + pos++ } buf[pos] = 16 // PrefixLen - pos += 1 + pos++ ip = net.ParseIP("2501::").To16() copy(buf[pos:pos+2], []byte(ip)) pos += 2 buf[pos] = 1 //distance binary.BigEndian.PutUint32(buf[pos:], 0) //metic - r = &IPRouteBody{Api: command[v]} - err = r.DecodeFromBytes(buf, v, "") + r = &IPRouteBody{API: command[v]} + err = r.decodeFromBytes(buf, v, "") assert.Equal(nil, err) } } // NexthopLookup exists in only quagga (zebra API version 2 and 3) -func Test_NexthopLookupBody(t *testing.T) { +func Test_nexthopLookupBody(t *testing.T) { assert := assert.New(t) //ipv4 - //DecodeFromBytes + //decodeFromBytes pos := 0 buf := make([]byte, 18) ip := net.ParseIP("192.168.50.0").To4() - copy(buf[0:4], []byte(ip)) + copy(buf[0:4], []byte(ip)) // addr pos += 4 - binary.BigEndian.PutUint32(buf[pos:], 10) + binary.BigEndian.PutUint32(buf[pos:], 10) // metric pos += 4 - buf[pos] = byte(1) - pos += 1 + buf[pos] = byte(1) // numNexthop + pos++ buf[pos] = byte(4) - pos += 1 + pos++ ip = net.ParseIP("172.16.1.101").To4() copy(buf[pos:pos+4], []byte(ip)) pos += 4 binary.BigEndian.PutUint32(buf[pos:], 3) - b := &NexthopLookupBody{Api: IPV4_NEXTHOP_LOOKUP} - err := b.DecodeFromBytes(buf, 2, "") + //b := &nexthopLookupBody{api: zapi3IPv4NexthopLookup} + b := &lookupBody{api: zapi3IPv4NexthopLookup} + err := b.decodeFromBytes(buf, 2, "") assert.Equal(nil, err) - assert.Equal("192.168.50.0", b.Addr.String()) - assert.Equal(uint32(10), b.Metric) - assert.Equal(uint32(3), b.Nexthops[0].Ifindex) - assert.Equal(NEXTHOP_TYPE(4), b.Nexthops[0].Type) - assert.Equal("172.16.1.101", b.Nexthops[0].Gate.String()) - - //Serialize - buf, err = b.Serialize(2, "") + assert.Equal("192.168.50.0", b.addr.String()) + assert.Equal(uint32(10), b.metric) + assert.Equal(uint32(3), b.nexthops[0].Ifindex) + assert.Equal(nexthopType(4), b.nexthops[0].Type) + assert.Equal("172.16.1.101", b.nexthops[0].Gate.String()) + + //serialize + buf, err = b.serialize(2, "") ip = net.ParseIP("192.168.50.0").To4() assert.Equal(nil, err) assert.Equal([]byte(ip)[0:4], buf[0:4]) // length invalid buf = make([]byte, 3) - b = &NexthopLookupBody{Api: IPV4_NEXTHOP_LOOKUP} - err = b.DecodeFromBytes(buf, 2, "") + //b = &nexthopLookupBody{api: zapi3IPv4NexthopLookup} + b = &lookupBody{api: zapi3IPv4NexthopLookup} + err = b.decodeFromBytes(buf, 2, "") assert.NotEqual(nil, err) //ipv6 - //DecodeFromBytes + //decodeFromBytes pos = 0 buf = make([]byte, 46) ip = net.ParseIP("2001:db8:0:f101::").To16() @@ -784,41 +814,41 @@ func Test_NexthopLookupBody(t *testing.T) { binary.BigEndian.PutUint32(buf[pos:], 10) pos += 4 buf[pos] = byte(1) - pos += 1 + pos++ buf[pos] = byte(7) - pos += 1 + pos++ ip = net.ParseIP("2001:db8:0:1111::1").To16() copy(buf[pos:pos+16], []byte(ip)) pos += 16 binary.BigEndian.PutUint32(buf[pos:], 3) - b = &NexthopLookupBody{Api: IPV6_NEXTHOP_LOOKUP} - err = b.DecodeFromBytes(buf, 2, "") + b = &lookupBody{api: zapi3IPv6NexthopLookup} + err = b.decodeFromBytes(buf, 2, "") assert.Equal(nil, err) - assert.Equal("2001:db8:0:f101::", b.Addr.String()) - assert.Equal(uint32(10), b.Metric) - assert.Equal(uint32(3), b.Nexthops[0].Ifindex) - assert.Equal(NEXTHOP_TYPE(7), b.Nexthops[0].Type) - assert.Equal("2001:db8:0:1111::1", b.Nexthops[0].Gate.String()) - - //Serialize - buf, err = b.Serialize(2, "") + assert.Equal("2001:db8:0:f101::", b.addr.String()) + assert.Equal(uint32(10), b.metric) + assert.Equal(uint32(3), b.nexthops[0].Ifindex) + assert.Equal(nexthopType(7), b.nexthops[0].Type) + assert.Equal("2001:db8:0:1111::1", b.nexthops[0].Gate.String()) + + //serialize + buf, err = b.serialize(2, "") ip = net.ParseIP("2001:db8:0:f101::").To16() assert.Equal(nil, err) assert.Equal([]byte(ip)[0:16], buf[0:16]) // length invalid buf = make([]byte, 15) - b = &NexthopLookupBody{Api: IPV6_NEXTHOP_LOOKUP} - err = b.DecodeFromBytes(buf, 2, "") + b = &lookupBody{api: zapi3IPv6NexthopLookup} + err = b.decodeFromBytes(buf, 2, "") assert.NotEqual(nil, err) } // ImportLookup exists in only quagga (zebra API version 2 and 3) -func Test_ImportLookupBody(t *testing.T) { +func Test_importLookupBody(t *testing.T) { assert := assert.New(t) - //DecodeFromBytes + //decodeFromBytes pos := 0 buf := make([]byte, 18) ip := net.ParseIP("192.168.50.0").To4() @@ -827,26 +857,26 @@ func Test_ImportLookupBody(t *testing.T) { binary.BigEndian.PutUint32(buf[pos:], 10) pos += 4 buf[pos] = byte(1) - pos += 1 + pos++ buf[pos] = byte(4) - pos += 1 + pos++ ip = net.ParseIP("172.16.1.101").To4() copy(buf[pos:pos+4], []byte(ip)) pos += 4 binary.BigEndian.PutUint32(buf[pos:], 3) - b := &ImportLookupBody{Api: IPV4_IMPORT_LOOKUP} - err := b.DecodeFromBytes(buf, 2, "") + b := &lookupBody{api: zapi3IPv4ImportLookup} + err := b.decodeFromBytes(buf, 2, "") assert.Equal(nil, err) - assert.Equal("192.168.50.0", b.Addr.String()) - assert.Equal(uint32(10), b.Metric) - assert.Equal(uint32(3), b.Nexthops[0].Ifindex) - assert.Equal(NEXTHOP_TYPE(4), b.Nexthops[0].Type) - assert.Equal("172.16.1.101", b.Nexthops[0].Gate.String()) - - //Serialize - b.PrefixLength = uint8(24) - buf, err = b.Serialize(2, "") + assert.Equal("192.168.50.0", b.addr.String()) + assert.Equal(uint32(10), b.metric) + assert.Equal(uint32(3), b.nexthops[0].Ifindex) + assert.Equal(nexthopType(4), b.nexthops[0].Type) + assert.Equal("172.16.1.101", b.nexthops[0].Gate.String()) + + //serialize + b.prefixLength = uint8(24) + buf, err = b.serialize(2, "") ip = net.ParseIP("192.168.50.0").To4() assert.Equal(nil, err) assert.Equal(uint8(24), buf[0]) @@ -854,8 +884,8 @@ func Test_ImportLookupBody(t *testing.T) { // length invalid buf = make([]byte, 3) - b = &ImportLookupBody{Api: IPV4_IMPORT_LOOKUP} - err = b.DecodeFromBytes(buf, 2, "") + b = &lookupBody{api: zapi3IPv4ImportLookup} + err = b.decodeFromBytes(buf, 2, "") assert.NotEqual(nil, err) } @@ -872,29 +902,29 @@ func Test_NexthopRegisterBody(t *testing.T) { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, } - command := map[uint8]API_TYPE{ - 2: NEXTHOP_REGISTER, - 3: NEXTHOP_REGISTER, - 4: FRR_NEXTHOP_REGISTER, - 5: FRR_ZAPI5_NEXTHOP_REGISTER, - 6: FRR_ZAPI6_NEXTHOP_REGISTER, + command := map[uint8]APIType{ + 2: zapi3NexthopRegister, + 3: zapi3NexthopRegister, + 4: zapi4NexthopRegister, + 5: zapi5Frr5NexthopRegister, + 6: nexthopRegister, } for v := MinZapiVer; v <= MaxZapiVer; v++ { - // Test DecodeFromBytes() - b := &NexthopRegisterBody{Api: command[v]} - err := b.DecodeFromBytes(bufIn, v, "") + // Test decodeFromBytes() + b := &NexthopRegisterBody{api: command[v].toCommon(v, "")} + err := b.decodeFromBytes(bufIn, v, "") assert.Nil(err) // Test decoded values - assert.Equal(uint8(1), b.Nexthops[0].Connected) + assert.Equal(uint8(1), b.Nexthops[0].connected) assert.Equal(uint16(syscall.AF_INET), b.Nexthops[0].Family) assert.Equal(net.ParseIP("192.168.1.1").To4(), b.Nexthops[0].Prefix) - assert.Equal(uint8(0), b.Nexthops[1].Connected) + assert.Equal(uint8(0), b.Nexthops[1].connected) assert.Equal(uint16(syscall.AF_INET6), b.Nexthops[1].Family) assert.Equal(net.ParseIP("2001:db8:1:1::1").To16(), b.Nexthops[1].Prefix) - // Test Serialize() - bufOut, err := b.Serialize(v, "") + // Test serialize() + bufOut, err := b.serialize(v, "") assert.Nil(err) // Test serialised value @@ -905,20 +935,20 @@ 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: 26} - command := map[uint8]API_TYPE{ - 2: NEXTHOP_UPDATE, - 3: NEXTHOP_UPDATE, - 4: FRR_NEXTHOP_UPDATE, - 5: FRR_ZAPI5_NEXTHOP_UPDATE, - 6: FRR_ZAPI6_NEXTHOP_UPDATE, + size := map[uint8]uint8{2: 21, 3: 21, 4: 22, 5: 26, 6: 30} + command := map[uint8]APIType{ + 2: zapi3NexthopUpdate, + 3: zapi3NexthopUpdate, + 4: zapi4NexthopUpdate, + 5: zapi5Frr5NexthopUpdate, + 6: nexthopUpdate, } - nexthopType := map[uint8]NEXTHOP_TYPE{ - 2: NEXTHOP_TYPE_IPV4_IFINDEX, - 3: NEXTHOP_TYPE_IPV4_IFINDEX, - 4: FRR_NEXTHOP_TYPE_IPV4_IFINDEX, - 5: FRR_NEXTHOP_TYPE_IPV4_IFINDEX, - 6: FRR_NEXTHOP_TYPE_IPV4_IFINDEX, + nexthopType := map[uint8]nexthopType{ + 2: backwardNexthopTypeIPv4IFIndex, + 3: backwardNexthopTypeIPv4IFIndex, + 4: nexthopTypeIPv4IFIndex, + 5: nexthopTypeIPv4IFIndex, + 6: nexthopTypeIPv4IFIndex, } for v := MinZapiVer; v <= MaxZapiVer; v++ { @@ -928,29 +958,37 @@ func Test_NexthopUpdateBody(t *testing.T) { copy(bufIn[0: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(FRR_ZAPI5_ROUTE_CONNECT), 0x00, 0x00}) + copy(bufIn[pos:pos+3], []byte{byte(routeConnect), 0x00, 0x00}) pos += 3 } if v > 3 { // Distance bufIn[pos] = 0 - pos += 1 + pos++ } // metric(4 bytes)=1, number of nexthops(1 byte)=1 copy(bufIn[pos:pos+5], []byte{0x00, 0x00, 0x00, 0x01, 0x01}) pos += 5 + if v == 6 { // version == 6 and not frr6 + binary.BigEndian.PutUint32(bufIn[pos:], 0) //vrfid + pos += 4 + } bufIn[pos] = byte(nexthopType[v]) - pos += 1 - // nexthop_ip(4 bytes)="192.168.0.1", nexthop_ifindex(4 byte)=2 + pos++ + if v == 6 { // frr7.3 and after + 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 > 4 { + if v == 5 { // frr7.3(latest software of zapi v6) depends on nexthop flag bufIn[pos] = byte(0) // label num - pos += 1 + pos++ } - // Test DecodeFromBytes() - b := &NexthopUpdateBody{Api: command[v]} - err := b.DecodeFromBytes(bufIn, v, "") + // Test decodeFromBytes() + b := &NexthopUpdateBody{API: command[v].toCommon(v, "")} + err := b.decodeFromBytes(bufIn, v, "") assert.Nil(err) // Test decoded values @@ -971,46 +1009,46 @@ func Test_GetLabelChunkBody(t *testing.T) { assert := assert.New(t) // Test only with ZAPI version 5 and 6 - routeType := map[uint8]ROUTE_TYPE{5: FRR_ZAPI5_ROUTE_BGP, 6: FRR_ZAPI6_ROUTE_BGP} + routeType := RouteBGP for v := uint8(5); v <= MaxZapiVer; v++ { - //DecodeFromBytes + //decodeFromBytes buf := make([]byte, 12) - buf[0] = byte(routeType[v]) // Route Type + buf[0] = byte(routeType) // Route Type binary.BigEndian.PutUint16(buf[1:], 0) //Instance buf[3] = 0 //Keep binary.BigEndian.PutUint32(buf[4:], 80) //Start binary.BigEndian.PutUint32(buf[8:], 89) //End b := &GetLabelChunkBody{} - err := b.DecodeFromBytes(buf, v, "") + err := b.decodeFromBytes(buf, v, "") assert.Equal(nil, err) - //Serialize + //serialize b.ChunkSize = 10 - buf, err = b.Serialize(v, "") + buf, err = b.serialize(v, "") assert.Equal(nil, err) - assert.Equal(byte(routeType[v]), buf[0]) + assert.Equal(byte(routeType), buf[0]) bi := make([]byte, 4) binary.BigEndian.PutUint32(bi, 10) assert.Equal(bi, buf[4:8]) // Chunksize } } -func Test_VrfLabelBody(t *testing.T) { +func Test_vrfLabelBody(t *testing.T) { assert := assert.New(t) // Test only with ZAPI version 5 and 6 for v := uint8(5); v <= MaxZapiVer; v++ { - //DecodeFromBytes + //decodeFromBytes bufIn := make([]byte, 6) binary.BigEndian.PutUint32(bufIn[0:], 80) //label - bufIn[4] = byte(AFI_IP) - bufIn[5] = byte(LSP_BGP) - b := &VrfLabelBody{} - err := b.DecodeFromBytes(bufIn, v, "") + bufIn[4] = byte(afiIP) + bufIn[5] = byte(lspBGP) + b := &vrfLabelBody{} + err := b.decodeFromBytes(bufIn, v, "") assert.Equal(nil, err) - //Serialize + //serialize var bufOut []byte - bufOut, err = b.Serialize(v, "") + bufOut, err = b.serialize(v, "") assert.Equal(nil, err) assert.Equal(bufIn, bufOut) } diff --git a/pkg/server/server.go b/pkg/server/server.go index a2c3dfbd..2ee49ec8 100644 --- a/pkg/server/server.go +++ b/pkg/server/server.go @@ -710,7 +710,7 @@ func (s *BgpServer) setPathVrfIdMap(paths []*table.Path, m map[uint32]bool) { } } default: - m[zebra.VRF_DEFAULT] = true + m[zebra.DefaultVrf] = true } } } diff --git a/pkg/server/zclient.go b/pkg/server/zclient.go index c002851a..5dac2a30 100644 --- a/pkg/server/zclient.go +++ b/pkg/server/zclient.go @@ -116,11 +116,10 @@ func filterOutExternalPath(paths []*table.Path) []*table.Path { return filteredPaths } -func addMessageLabelToIPRouteBody(path *table.Path, vrfId uint32, z *zebraClient, msgFlags *zebra.MESSAGE_FLAG, nexthop *zebra.Nexthop) { - v := z.client.Version +func addLabelToNexthop(path *table.Path, z *zebraClient, msgFlags *zebra.MessageFlag, nexthop *zebra.Nexthop) { rf := path.GetRouteFamily() - if v > 4 && (rf == bgp.RF_IPv4_VPN || rf == bgp.RF_IPv6_VPN) { - *msgFlags |= zebra.FRR_ZAPI5_MESSAGE_LABEL + if rf == bgp.RF_IPv4_VPN || rf == bgp.RF_IPv6_VPN { + z.client.SetLabelFlag(msgFlags, nexthop) switch rf { case bgp.RF_IPv4_VPN: for _, label := range path.GetNlri().(*bgp.LabeledVPNIPAddrPrefix).Labels.Labels { @@ -136,7 +135,7 @@ func addMessageLabelToIPRouteBody(path *table.Path, vrfId uint32, z *zebraClient } } -func newIPRouteBody(dst []*table.Path, vrfId uint32, z *zebraClient) (body *zebra.IPRouteBody, isWithdraw bool) { +func newIPRouteBody(dst []*table.Path, vrfID uint32, z *zebraClient) (body *zebra.IPRouteBody, isWithdraw bool) { version := z.client.Version paths := filterOutExternalPath(dst) if len(paths) == 0 { @@ -148,7 +147,7 @@ func newIPRouteBody(dst []*table.Path, vrfId uint32, z *zebraClient) (body *zebr var prefix net.IP var nexthop zebra.Nexthop nexthops := make([]zebra.Nexthop, 0, len(paths)) - msgFlags := zebra.MESSAGE_NEXTHOP + msgFlags := zebra.MessageNexthop switch path.GetRouteFamily() { case bgp.RF_IPv4_UC: prefix = path.GetNlri().(*bgp.IPAddrPrefix).IPAddrPrefixDefault.Prefix.To4() @@ -161,10 +160,10 @@ func newIPRouteBody(dst []*table.Path, vrfId uint32, z *zebraClient) (body *zebr default: return nil, false } - nhVrfId := uint32(zebra.VRF_DEFAULT) - for vrfPath, pathVrfId := range z.pathVrfMap { + nhVrfID := uint32(zebra.DefaultVrf) + for vrfPath, pathVrfID := range z.pathVrfMap { if path.Equal(vrfPath) { - nhVrfId = pathVrfId + nhVrfID = pathVrfID break } else { continue @@ -172,34 +171,27 @@ func newIPRouteBody(dst []*table.Path, vrfId uint32, z *zebraClient) (body *zebr } for _, p := range paths { nexthop.Gate = p.GetNexthop() - nexthop.VrfId = nhVrfId - if nhVrfId != vrfId { - addMessageLabelToIPRouteBody(path, vrfId, z, &msgFlags, &nexthop) + nexthop.VrfID = nhVrfID + if nhVrfID != vrfID { + addLabelToNexthop(path, z, &msgFlags, &nexthop) } nexthops = append(nexthops, nexthop) } plen, _ := strconv.ParseUint(l[1], 10, 8) med, err := path.GetMed() if err == nil { - if version < 5 { - msgFlags |= zebra.MESSAGE_METRIC - } else { - msgFlags |= zebra.FRR_ZAPI5_MESSAGE_METRIC - } + msgFlags |= zebra.MessageMetric.ToEach(version) } - var flags zebra.FLAG + var flags zebra.Flag if path.IsIBGP() { - flags = zebra.FLAG_IBGP | zebra.FLAG_ALLOW_RECURSION // 0x08|0x01 - if z.client.Version == 6 && z.client.SoftwareName != "frr6" { - flags = zebra.FRR_ZAPI6_FLAG_IBGP | zebra.FRR_ZAPI6_FLAG_ALLOW_RECURSION //0x04|0x01 - } + flags = zebra.FlagIBGP.ToEach(z.client.Version, z.client.SoftwareName) | zebra.FlagAllowRecursion } else if path.GetSource().MultihopTtl > 0 { - flags = zebra.FLAG_ALLOW_RECURSION // 0x01, FRR_ZAPI6_FLAG_ALLOW_RECURSION is same. + flags = zebra.FlagAllowRecursion // 0x01 } return &zebra.IPRouteBody{ - Type: zebra.ROUTE_BGP, + Type: zebra.RouteBGP, Flags: flags, - SAFI: zebra.SAFI_UNICAST, + Safi: zebra.SafiUnicast, Message: msgFlags, Prefix: zebra.Prefix{ Prefix: prefix, @@ -262,8 +254,8 @@ func newNexthopUnregisterBody(family uint16, prefix net.IP) *zebra.NexthopRegist func newPathFromIPRouteMessage(m *zebra.Message, version uint8, software string) *table.Path { header := m.Header body := m.Body.(*zebra.IPRouteBody) - family := body.RouteFamily(version) - isWithdraw := body.IsWithdraw(version) + family := body.RouteFamily(version, software) + isWithdraw := body.IsWithdraw(version, software) var nlri bgp.AddrPrefixInterface pattr := make([]bgp.PathAttributeInterface, 0) @@ -314,9 +306,9 @@ func newPathFromIPRouteMessage(m *zebra.Message, version uint8, software string) } type mplsLabelParameter struct { - rangeSize uint32 - maps map[uint64]*table.Bitmap - unassinedVrf []*table.Vrf //Vrfs which are not assigned MPLS label + rangeSize uint32 + maps map[uint64]*table.Bitmap + unassignedVrf []*table.Vrf //Vrfs which are not assigned MPLS label } type zebraClient struct { @@ -403,17 +395,27 @@ func (z *zebraClient) loop() { if len(paths) == 0 { // If there is no path bound for the given nexthop, send // NEXTHOP_UNREGISTER message. - z.client.SendNexthopRegister(msg.Header.VrfId, newNexthopUnregisterBody(uint16(body.Prefix.Family), body.Prefix.Prefix), true) + z.client.SendNexthopRegister(msg.Header.VrfID, newNexthopUnregisterBody(uint16(body.Prefix.Family), body.Prefix.Prefix), true) delete(z.nexthopCache, body.Prefix.Prefix.String()) } z.updatePathByNexthopCache(paths) case *zebra.GetLabelChunkBody: + log.WithFields(log.Fields{ + "Topic": "Zebra", + "Start": body.Start, + "End": body.End, + }).Debugf("zebra GetLabelChunkBody is received") startEnd := uint64(body.Start)<<32 | uint64(body.End) z.mplsLabel.maps[startEnd] = table.NewBitmap(int(body.End - body.Start + 1)) - for _, vrf := range z.mplsLabel.unassinedVrf { - z.assignAndSendVrfMplsLabel(vrf) + for _, vrf := range z.mplsLabel.unassignedVrf { + if err := z.assignAndSendVrfMplsLabel(vrf); err != nil { + log.WithFields(log.Fields{ + "Topic": "Zebra", + "Error": err, + }).Error("zebra failed to assign and send vrf mpls label") + } } - z.mplsLabel.unassinedVrf = nil + z.mplsLabel.unassignedVrf = nil } case ev := <-w.Event(): switch msg := ev.(type) { @@ -479,7 +481,7 @@ func newZebraClient(s *BgpServer, url string, protos []string, version uint8, nh ver++ } for elem, ver := range zapivers { - cli, err = zebra.NewClient(l[0], l[1], zebra.ROUTE_BGP, ver, softwareName) + cli, err = zebra.NewClient(l[0], l[1], zebra.RouteBGP, ver, softwareName, mplsLabelRangeSize) if cli != nil && err == nil { usingVersion = ver break @@ -511,7 +513,7 @@ func newZebraClient(s *BgpServer, url string, protos []string, version uint8, nh if err != nil { return nil, err } - cli.SendRedistribute(t, zebra.VRF_DEFAULT) + cli.SendRedistribute(t, zebra.DefaultVrf) } w := &zebraClient{ client: cli, @@ -525,7 +527,7 @@ func newZebraClient(s *BgpServer, url string, protos []string, version uint8, nh dead: make(chan struct{}), } go w.loop() - if mplsLabelRangeSize > 0 { + if mplsLabelRangeSize > 0 && cli.SupportMpls() { if err = cli.SendGetLabelChunk(&zebra.GetLabelChunkBody{ChunkSize: mplsLabelRangeSize}); err != nil { return nil, err } @@ -560,7 +562,7 @@ func (z *zebraClient) assignAndSendVrfMplsLabel(vrf *table.Vrf) error { return err } } else if vrf.MplsLabel == 0 { // GetLabelChunk is not performed - z.mplsLabel.unassinedVrf = append(z.mplsLabel.unassinedVrf, vrf) + z.mplsLabel.unassignedVrf = append(z.mplsLabel.unassignedVrf, vrf) } return err } diff --git a/pkg/server/zclient_test.go b/pkg/server/zclient_test.go index b9681e93..fbd189d6 100644 --- a/pkg/server/zclient_test.go +++ b/pkg/server/zclient_test.go @@ -28,65 +28,22 @@ import ( func Test_newPathFromIPRouteMessage(t *testing.T) { assert := assert.New(t) - - ipv4RouteAddCommand := map[uint8]zebra.API_TYPE{ - 2: zebra.IPV4_ROUTE_ADD, - 3: zebra.IPV4_ROUTE_ADD, - 4: zebra.FRR_IPV4_ROUTE_ADD, - 5: zebra.FRR_ZAPI5_IPV4_ROUTE_ADD, - 6: zebra.FRR_ZAPI6_ROUTE_ADD, - } - ipv4RouteDeleteCommand := map[uint8]zebra.API_TYPE{ - 2: zebra.IPV4_ROUTE_DELETE, - 3: zebra.IPV4_ROUTE_DELETE, - 4: zebra.FRR_IPV4_ROUTE_DELETE, - 5: zebra.FRR_ZAPI5_IPV4_ROUTE_DELETE, - 6: zebra.FRR_ZAPI6_ROUTE_DELETE, - } - ipv6RouteAddCommand := map[uint8]zebra.API_TYPE{ - 2: zebra.IPV6_ROUTE_ADD, - 3: zebra.IPV6_ROUTE_ADD, - 4: zebra.FRR_IPV6_ROUTE_ADD, - 5: zebra.FRR_ZAPI5_IPV6_ROUTE_ADD, - 6: zebra.FRR_ZAPI6_ROUTE_ADD, - } - ipv6RouteDeleteCommand := map[uint8]zebra.API_TYPE{ - 2: zebra.IPV6_ROUTE_DELETE, - 3: zebra.IPV6_ROUTE_DELETE, - 4: zebra.FRR_IPV6_ROUTE_DELETE, - 5: zebra.FRR_ZAPI5_IPV6_ROUTE_DELETE, - 6: zebra.FRR_ZAPI6_ROUTE_DELETE, - } - message := map[uint8]zebra.MESSAGE_FLAG{ - 2: zebra.MESSAGE_NEXTHOP | zebra.MESSAGE_DISTANCE | zebra.MESSAGE_METRIC | zebra.MESSAGE_MTU, - 3: zebra.MESSAGE_NEXTHOP | zebra.MESSAGE_DISTANCE | zebra.MESSAGE_METRIC | zebra.MESSAGE_MTU, - 4: zebra.FRR_MESSAGE_NEXTHOP | zebra.FRR_MESSAGE_DISTANCE | zebra.FRR_MESSAGE_METRIC | zebra.FRR_MESSAGE_MTU, - 5: zebra.FRR_ZAPI5_MESSAGE_NEXTHOP | zebra.FRR_ZAPI5_MESSAGE_DISTANCE | zebra.FRR_ZAPI5_MESSAGE_METRIC | zebra.FRR_ZAPI5_MESSAGE_MTU, - 6: zebra.FRR_ZAPI5_MESSAGE_NEXTHOP | zebra.FRR_ZAPI5_MESSAGE_DISTANCE | zebra.FRR_ZAPI5_MESSAGE_METRIC | zebra.FRR_ZAPI5_MESSAGE_MTU, - } - for v := zebra.MinZapiVer; v <= zebra.MaxZapiVer; v++ { // IPv4 Route Add m := &zebra.Message{} - marker := zebra.HEADER_MARKER - if v > 3 { - marker = zebra.FRR_HEADER_MARKER - } - flag := zebra.FLAG_SELECTED - if v > 5 { - flag = zebra.FRR_ZAPI6_FLAG_SELECTED - } + flag := zebra.FlagSelected.ToEach(v, "") + message := zebra.MessageNexthop | zebra.MessageDistance.ToEach(v) | zebra.MessageMetric.ToEach(v) | zebra.MessageMTU.ToEach(v) h := &zebra.Header{ Len: zebra.HeaderSize(v), - Marker: marker, + Marker: zebra.HeaderMarker(v), Version: v, - Command: ipv4RouteAddCommand[v], + Command: zebra.RouteAdd.ToEach(v, ""), } b := &zebra.IPRouteBody{ - Type: zebra.ROUTE_TYPE(zebra.ROUTE_STATIC), + Type: zebra.RouteType(zebra.RouteStatic), Flags: flag, - Message: message[v], - SAFI: zebra.SAFI(zebra.SAFI_UNICAST), // 1, FRR_ZAPI5_SAFI_UNICAST is same + Message: message, + Safi: zebra.Safi(zebra.SafiUnicast), // 1, FRR_ZAPI5_SAFI_UNICAST is same Prefix: zebra.Prefix{ Prefix: net.ParseIP("192.168.100.0"), PrefixLen: uint8(24), @@ -102,11 +59,11 @@ func Test_newPathFromIPRouteMessage(t *testing.T) { Distance: uint8(0), Metric: uint32(100), Mtu: uint32(0), - Api: zebra.API_TYPE(ipv4RouteAddCommand[v]), + API: zebra.APIType(zebra.RouteAdd.ToEach(v, "")), } m.Header = *h m.Body = b - + zebra.BackwardIPv6RouteDelete.ToEach(v, "") path := newPathFromIPRouteMessage(m, v, "") pp := table.NewPath(nil, path.GetNlri(), path.IsWithdraw, path.GetPathAttrs(), time.Now(), false) pp.SetIsFromExternal(path.IsFromExternal()) @@ -116,8 +73,8 @@ func Test_newPathFromIPRouteMessage(t *testing.T) { assert.False(pp.IsWithdraw) // IPv4 Route Delete - h.Command = ipv4RouteDeleteCommand[v] - b.Api = ipv4RouteDeleteCommand[v] + h.Command = zebra.RouteDelete.ToEach(v, "") + b.API = zebra.RouteDelete.ToEach(v, "") m.Header = *h m.Body = b @@ -132,8 +89,14 @@ func Test_newPathFromIPRouteMessage(t *testing.T) { assert.True(pp.IsWithdraw) // IPv6 Route Add - h.Command = ipv6RouteAddCommand[v] - b.Api = ipv6RouteAddCommand[v] + h.Command = zebra.RouteAdd.ToEach(v, "") + if v < 5 { + h.Command = zebra.BackwardIPv6RouteAdd.ToEach(v, "") + } + b.API = zebra.RouteAdd.ToEach(v, "") + if v < 5 { + b.API = zebra.BackwardIPv6RouteAdd.ToEach(v, "") + } b.Prefix.Prefix = net.ParseIP("2001:db8:0:f101::") b.Prefix.PrefixLen = uint8(64) b.Nexthops = []zebra.Nexthop{{Gate: net.ParseIP("::")}} @@ -151,8 +114,14 @@ func Test_newPathFromIPRouteMessage(t *testing.T) { assert.False(pp.IsWithdraw) // IPv6 Route Delete - h.Command = ipv6RouteDeleteCommand[v] - b.Api = ipv6RouteDeleteCommand[v] + h.Command = zebra.RouteDelete.ToEach(v, "") + if v < 5 { + h.Command = zebra.BackwardIPv6RouteDelete.ToEach(v, "") + } + b.API = zebra.RouteDelete.ToEach(v, "") + if v < 5 { + b.API = zebra.BackwardIPv6RouteDelete.ToEach(v, "") + } m.Header = *h m.Body = b diff --git a/tools/pyang_plugins/gobgp.yang b/tools/pyang_plugins/gobgp.yang index a4a2dc64..414dbf17 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 and frr7.2 can be used."; + quagga, frr3, frr4, frr5, frr6, frr7, frr7.1, frr7.2, and frr7.3 can be used."; } } |