diff options
Diffstat (limited to 'internal/pkg/zebra')
-rw-r--r-- | internal/pkg/zebra/api_type_string.go | 4 | ||||
-rw-r--r-- | internal/pkg/zebra/lsp_type_string.go | 16 | ||||
-rw-r--r-- | internal/pkg/zebra/safi_string.go | 4 | ||||
-rw-r--r-- | internal/pkg/zebra/zapi.go | 376 |
4 files changed, 385 insertions, 15 deletions
diff --git a/internal/pkg/zebra/api_type_string.go b/internal/pkg/zebra/api_type_string.go index af16317b..2c280533 100644 --- a/internal/pkg/zebra/api_type_string.go +++ b/internal/pkg/zebra/api_type_string.go @@ -4,9 +4,9 @@ package zebra import "strconv" -const _API_TYPE_name = "FRR_ZAPI6_INTERFACE_ADDFRR_ZAPI6_INTERFACE_DELETEFRR_ZAPI6_INTERFACE_ADDRESS_ADDFRR_ZAPI6_INTERFACE_ADDRESS_DELETEFRR_ZAPI6_INTERFACE_UPFRR_ZAPI6_INTERFACE_DOWNFRR_ZAPI6_INTERFACE_SET_MASTERFRR_ZAPI6_ROUTE_ADDFRR_ZAPI6_ROUTE_DELETEFRR_ZAPI6_ROUTE_NOTIFY_OWNERFRR_ZAPI6_REDISTRIBUTE_ADDFRR_ZAPI6_REDISTRIBUTE_DELETEFRR_ZAPI6_REDISTRIBUTE_DEFAULT_ADDFRR_ZAPI6_REDISTRIBUTE_DEFAULT_DELETEFRR_ZAPI6_ROUTER_ID_ADDFRR_ZAPI6_ROUTER_ID_DELETEFRR_ZAPI6_ROUTER_ID_UPDATEFRR_ZAPI6_HELLOFRR_ZAPI6_CAPABILITIESFRR_ZAPI6_NEXTHOP_REGISTERFRR_ZAPI6_NEXTHOP_UNREGISTERFRR_ZAPI6_NEXTHOP_UPDATEFRR_ZAPI6_INTERFACE_NBR_ADDRESS_ADDFRR_ZAPI6_INTERFACE_NBR_ADDRESS_DELETEFRR_ZAPI6_INTERFACE_BFD_DEST_UPDATEFRR_ZAPI6_IMPORT_ROUTE_REGISTERFRR_ZAPI6_IMPORT_ROUTE_UNREGISTERFRR_ZAPI6_IMPORT_CHECK_UPDATEFRR_ZAPI6_IPV4_ROUTE_IPV6_NEXTHOP_ADDFRR_ZAPI6_BFD_DEST_REGISTERFRR_ZAPI6_BFD_DEST_DEREGISTERFRR_ZAPI6_BFD_DEST_UPDATEFRR_ZAPI6_BFD_DEST_REPLAYFRR_ZAPI6_REDISTRIBUTE_ROUTE_ADDFRR_ZAPI6_REDISTRIBUTE_ROUTE_DELFRR_ZAPI6_VRF_UNREGISTERFRR_ZAPI6_VRF_ADDFRR_ZAPI6_VRF_DELETEFRR_ZAPI6_VRF_LABELFRR_ZAPI6_INTERFACE_VRF_UPDATEFRR_ZAPI6_BFD_CLIENT_REGISTERFRR_ZAPI6_BFD_CLIENT_DEREGISTERFRR_ZAPI6_INTERFACE_ENABLE_RADVFRR_ZAPI6_INTERFACE_DISABLE_RADVFRR_ZAPI6_IPV4_NEXTHOP_LOOKUP_MRIBFRR_ZAPI6_INTERFACE_LINK_PARAMSFRR_ZAPI6_MPLS_LABELS_ADDFRR_ZAPI6_MPLS_LABELS_DELETEFRR_ZAPI6_IPMR_ROUTE_STATSFRR_ZAPI6_LABEL_MANAGER_CONNECTFRR_ZAPI6_GET_LABEL_CHUNKFRR_ZAPI6_RELEASE_LABEL_CHUNKFRR_ZAPI6_FEC_REGISTERFRR_ZAPI6_FEC_UNREGISTERFRR_ZAPI6_FEC_UPDATEFRR_ZAPI6_ADVERTISE_DEFAULT_GWFRR_ZAPI6_ADVERTISE_SUBNETFRR_ZAPI6_ADVERTISE_ALL_VNIFRR_ZAPI6_LOCAL_ES_ADDFRR_ZAPI6_LOCAL_ES_DELFRR_ZAPI6_VNI_ADDFRR_ZAPI6_VNI_DELFRR_ZAPI6_L3VNI_ADDFRR_ZAPI6_L3VNI_DELFRR_ZAPI6_REMOTE_VTEP_ADDFRR_ZAPI6_REMOTE_VTEP_DELFRR_ZAPI6_MACIP_ADDFRR_ZAPI6_MACIP_DELFRR_ZAPI6_IP_PREFIX_ROUTE_ADDFRR_ZAPI6_IP_PREFIX_ROUTE_DELFRR_ZAPI6_REMOTE_MACIP_ADDFRR_ZAPI6_REMOTE_MACIP_DELFRR_ZAPI6_PW_ADDFRR_ZAPI6_PW_DELETEFRR_ZAPI6_PW_SETFRR_ZAPI6_PW_UNSETFRR_ZAPI6_PW_STATUS_UPDATEFRR_ZAPI6_RULE_ADDFRR_ZAPI6_RULE_DELETEFRR_ZAPI6_RULE_NOTIFY_OWNERFRR_ZAPI6_TABLE_MANAGER_CONNECTFRR_ZAPI6_GET_TABLE_CHUNKFRR_ZAPI6_RELEASE_TABLE_CHUNKFRR_ZAPI6_IPSET_CREATEFRR_ZAPI6_IPSET_DESTROYFRR_ZAPI6_IPSET_ENTRY_ADDFRR_ZAPI6_IPSET_ENTRY_DELETEFRR_ZAPI6_IPSET_NOTIFY_OWNERFRR_ZAPI6_IPSET_ENTRY_NOTIFY_OWNERFRR_ZAPI6_IPTABLE_ADDFRR_ZAPI6_IPTABLE_DELETEFRR_ZAPI6_IPTABLE_NOTIFY_OWNERFRR_ZAPI5_IPTABLE_DELETEFRR_ZAPI5_IPTABLE_NOTIFY_OWNER" +const _API_TYPE_name = "FRR_ZAPI6_INTERFACE_ADDFRR_ZAPI6_INTERFACE_DELETEFRR_ZAPI6_INTERFACE_ADDRESS_ADDFRR_ZAPI6_INTERFACE_ADDRESS_DELETEFRR_ZAPI6_INTERFACE_UPFRR_ZAPI6_INTERFACE_DOWNFRR_ZAPI6_INTERFACE_SET_MASTERFRR_ZAPI6_ROUTE_ADDFRR_ZAPI6_ROUTE_DELETEFRR_ZAPI6_ROUTE_NOTIFY_OWNERFRR_ZAPI6_REDISTRIBUTE_ADDFRR_ZAPI6_REDISTRIBUTE_DELETEFRR_ZAPI6_REDISTRIBUTE_DEFAULT_ADDFRR_ZAPI6_REDISTRIBUTE_DEFAULT_DELETEFRR_ZAPI6_ROUTER_ID_ADDFRR_ZAPI6_ROUTER_ID_DELETEFRR_ZAPI6_ROUTER_ID_UPDATEFRR_ZAPI6_HELLOFRR_ZAPI6_CAPABILITIESFRR_ZAPI6_NEXTHOP_REGISTERFRR_ZAPI6_NEXTHOP_UNREGISTERFRR_ZAPI6_NEXTHOP_UPDATEFRR_ZAPI6_INTERFACE_NBR_ADDRESS_ADDFRR_ZAPI6_INTERFACE_NBR_ADDRESS_DELETEFRR_ZAPI6_INTERFACE_BFD_DEST_UPDATEFRR_ZAPI6_IMPORT_ROUTE_REGISTERFRR_ZAPI6_IMPORT_ROUTE_UNREGISTERFRR_ZAPI6_IMPORT_CHECK_UPDATEFRR_ZAPI6_IPV4_ROUTE_IPV6_NEXTHOP_ADDFRR_ZAPI6_BFD_DEST_REGISTERFRR_ZAPI6_BFD_DEST_DEREGISTERFRR_ZAPI6_BFD_DEST_UPDATEFRR_ZAPI6_BFD_DEST_REPLAYFRR_ZAPI6_REDISTRIBUTE_ROUTE_ADDFRR_ZAPI6_REDISTRIBUTE_ROUTE_DELFRR_ZAPI6_VRF_UNREGISTERFRR_ZAPI6_VRF_ADDFRR_ZAPI6_VRF_DELETEFRR_ZAPI6_VRF_LABELFRR_ZAPI6_INTERFACE_VRF_UPDATEFRR_ZAPI6_BFD_CLIENT_REGISTERFRR_ZAPI6_BFD_CLIENT_DEREGISTERFRR_ZAPI6_INTERFACE_ENABLE_RADVFRR_ZAPI6_INTERFACE_DISABLE_RADVFRR_ZAPI6_IPV4_NEXTHOP_LOOKUP_MRIBFRR_ZAPI6_INTERFACE_LINK_PARAMSFRR_ZAPI6_MPLS_LABELS_ADDFRR_ZAPI6_MPLS_LABELS_DELETEFRR_ZAPI6_IPMR_ROUTE_STATSFRR_ZAPI6_LABEL_MANAGER_CONNECTFRR_ZAPI6_LABEL_MANAGER_CONNECT_ASYNCFRR_ZAPI6_GET_LABEL_CHUNKFRR_ZAPI6_RELEASE_LABEL_CHUNKFRR_ZAPI6_FEC_REGISTERFRR_ZAPI6_FEC_UNREGISTERFRR_ZAPI6_FEC_UPDATEFRR_ZAPI6_ADVERTISE_DEFAULT_GWFRR_ZAPI6_ADVERTISE_SUBNETFRR_ZAPI6_ADVERTISE_ALL_VNIFRR_ZAPI6_LOCAL_ES_ADDFRR_ZAPI6_LOCAL_ES_DELFRR_ZAPI6_VNI_ADDFRR_ZAPI6_VNI_DELFRR_ZAPI6_L3VNI_ADDFRR_ZAPI6_L3VNI_DELFRR_ZAPI6_REMOTE_VTEP_ADDFRR_ZAPI6_REMOTE_VTEP_DELFRR_ZAPI6_MACIP_ADDFRR_ZAPI6_MACIP_DELFRR_ZAPI6_IP_PREFIX_ROUTE_ADDFRR_ZAPI6_IP_PREFIX_ROUTE_DELFRR_ZAPI6_REMOTE_MACIP_ADDFRR_ZAPI6_REMOTE_MACIP_DELFRR_ZAPI6_PW_ADDFRR_ZAPI6_PW_DELETEFRR_ZAPI6_PW_SETFRR_ZAPI6_PW_UNSETFRR_ZAPI6_PW_STATUS_UPDATEFRR_ZAPI6_RULE_ADDFRR_ZAPI6_RULE_DELETEFRR_ZAPI6_RULE_NOTIFY_OWNERFRR_ZAPI6_TABLE_MANAGER_CONNECTFRR_ZAPI6_GET_TABLE_CHUNKFRR_ZAPI6_RELEASE_TABLE_CHUNKFRR_ZAPI6_IPSET_CREATEFRR_ZAPI6_IPSET_DESTROYFRR_ZAPI6_IPSET_ENTRY_ADDFRR_ZAPI6_IPSET_ENTRY_DELETEFRR_ZAPI6_IPSET_NOTIFY_OWNERFRR_ZAPI6_IPSET_ENTRY_NOTIFY_OWNERFRR_ZAPI6_IPTABLE_ADDFRR_ZAPI6_IPTABLE_DELETEFRR_ZAPI6_IPTABLE_NOTIFY_OWNERFRR_ZAPI5_IPTABLE_NOTIFY_OWNER" -var _API_TYPE_index = [...]uint16{0, 23, 49, 80, 114, 136, 160, 190, 209, 231, 259, 285, 314, 348, 385, 408, 434, 460, 475, 497, 523, 551, 575, 610, 648, 683, 714, 747, 776, 813, 840, 869, 894, 919, 951, 983, 1007, 1024, 1044, 1063, 1093, 1122, 1153, 1184, 1216, 1250, 1281, 1306, 1334, 1360, 1391, 1416, 1445, 1467, 1491, 1511, 1541, 1567, 1594, 1616, 1638, 1655, 1672, 1691, 1710, 1735, 1760, 1779, 1798, 1827, 1856, 1882, 1908, 1924, 1943, 1959, 1977, 2003, 2021, 2042, 2069, 2100, 2125, 2154, 2176, 2199, 2224, 2252, 2280, 2314, 2335, 2359, 2389, 2413, 2443} +var _API_TYPE_index = [...]uint16{0, 23, 49, 80, 114, 136, 160, 190, 209, 231, 259, 285, 314, 348, 385, 408, 434, 460, 475, 497, 523, 551, 575, 610, 648, 683, 714, 747, 776, 813, 840, 869, 894, 919, 951, 983, 1007, 1024, 1044, 1063, 1093, 1122, 1153, 1184, 1216, 1250, 1281, 1306, 1334, 1360, 1391, 1428, 1453, 1482, 1504, 1528, 1548, 1578, 1604, 1631, 1653, 1675, 1692, 1709, 1728, 1747, 1772, 1797, 1816, 1835, 1864, 1893, 1919, 1945, 1961, 1980, 1996, 2014, 2040, 2058, 2079, 2106, 2137, 2162, 2191, 2213, 2236, 2261, 2289, 2317, 2351, 2372, 2396, 2426, 2456} func (i API_TYPE) String() string { if i >= API_TYPE(len(_API_TYPE_index)-1) { diff --git a/internal/pkg/zebra/lsp_type_string.go b/internal/pkg/zebra/lsp_type_string.go new file mode 100644 index 00000000..318c4800 --- /dev/null +++ b/internal/pkg/zebra/lsp_type_string.go @@ -0,0 +1,16 @@ +// Code generated by "stringer -type=LSP_TYPE"; DO NOT EDIT. + +package zebra + +import "strconv" + +const _LSP_TYPE_name = "LSP_NONELSP_STATICLSP_LDPLSP_BGPLSP_SRLSP_SHARP" + +var _LSP_TYPE_index = [...]uint8{0, 8, 18, 25, 32, 38, 47} + +func (i LSP_TYPE) String() string { + if i >= LSP_TYPE(len(_LSP_TYPE_index)-1) { + return "LSP_TYPE(" + strconv.FormatInt(int64(i), 10) + ")" + } + return _LSP_TYPE_name[_LSP_TYPE_index[i]:_LSP_TYPE_index[i+1]] +} diff --git a/internal/pkg/zebra/safi_string.go b/internal/pkg/zebra/safi_string.go index 8199a0e3..c8d469e4 100644 --- a/internal/pkg/zebra/safi_string.go +++ b/internal/pkg/zebra/safi_string.go @@ -4,9 +4,9 @@ package zebra import "strconv" -const _SAFI_name = "SAFI_UNICASTSAFI_MULTICASTSAFI_RESERVED_3SAFI_MPLS_VPNSAFI_MAX" +const _SAFI_name = "FRR_ZAPI5_SAFI_UNICASTFRR_ZAPI5_SAFI_MULTICASTFRR_ZAPI5_SAFI_MPLS_VPNFRR_ZAPI5_SAFI_ENCAPFRR_ZAPI5_SAFI_EVPNFRR_ZAPI5_SAFI_LABELED_UNICASTFRR_ZAPI5_SAFI_FLOWSPECFRR_ZAPI5_SAFI_MAX" -var _SAFI_index = [...]uint8{0, 12, 26, 41, 54, 62} +var _SAFI_index = [...]uint8{0, 22, 46, 69, 89, 108, 138, 161, 179} func (i SAFI) String() string { i -= 1 diff --git a/internal/pkg/zebra/zapi.go b/internal/pkg/zebra/zapi.go index 6bbe6a06..9659fa97 100644 --- a/internal/pkg/zebra/zapi.go +++ b/internal/pkg/zebra/zapi.go @@ -178,12 +178,29 @@ const ( //go:generate stringer -type=SAFI type SAFI uint8 +// SAFI definition in Zebra of FRRouting 4.x, 5.x, 6.x +const ( + _ SAFI = iota + FRR_ZAPI5_SAFI_UNICAST + FRR_ZAPI5_SAFI_MULTICAST + FRR_ZAPI5_SAFI_MPLS_VPN + FRR_ZAPI5_SAFI_ENCAP + FRR_ZAPI5_SAFI_EVPN + FRR_ZAPI5_SAFI_LABELED_UNICAST + FRR_ZAPI5_SAFI_FLOWSPEC + FRR_ZAPI5_SAFI_MAX +) + +// SAFI definition in Zebra of Quagga and FRRouting 3.x const ( _ SAFI = iota SAFI_UNICAST SAFI_MULTICAST - SAFI_RESERVED_3 - SAFI_MPLS_VPN + FRR_SAFI_MPLS_VPN // SAFI_RESERVED_3 in quagga + SAFI_MPLS_VPN // SAFI_RESERVED_4 in FRRouting 3.x + FRR_SAFI_ENCAP + FRR_SAFI_EVPN + SAFI_ENCAP // SAFI_MAX in FRRouting 3.x SAFI_MAX ) @@ -243,6 +260,7 @@ const ( FRR_ZAPI6_MPLS_LABELS_DELETE FRR_ZAPI6_IPMR_ROUTE_STATS FRR_ZAPI6_LABEL_MANAGER_CONNECT + FRR_ZAPI6_LABEL_MANAGER_CONNECT_ASYNC FRR_ZAPI6_GET_LABEL_CHUNK FRR_ZAPI6_RELEASE_LABEL_CHUNK FRR_ZAPI6_FEC_REGISTER @@ -1020,6 +1038,9 @@ func NewClient(network, address string, typ ROUTE_TYPE, version uint8) (*Client, // Send HELLO/ROUTER_ID_ADD messages to negotiate the Zebra message version. c.SendHello() c.SendRouterIDAdd() + if version >= 4 { + c.SendLabelManagerConnect() + } receiveSingleMsg := func() (*Message, error) { headerBuf, err := readAll(conn, int(HeaderSize(version))) @@ -1241,6 +1262,10 @@ func (c *Client) SendRedistributeDelete(t ROUTE_TYPE) error { } func (c *Client) SendIPRoute(vrfId uint32, body *IPRouteBody, isWithdraw bool) error { + routeFamily := body.RouteFamily(c.Version) + if vrfId == VRF_DEFAULT && (routeFamily == bgp.RF_IPv4_VPN || routeFamily == bgp.RF_IPv6_VPN) { + return fmt.Errorf("RF_IPv4_VPN or RF_IPv6_VPN are not suitable for VPN_DEFAULT(default forwarding table).") + } command := IPV4_ROUTE_ADD if c.Version <= 3 { if body.Prefix.Prefix.To4() != nil { @@ -1311,6 +1336,58 @@ func (c *Client) SendNexthopRegister(vrfId uint32, body *NexthopRegisterBody, is return c.SendCommand(command, vrfId, body) } +// Reference: zread_label_manager_connect function in zebra/zserv.c of FRR3.x (ZAPI) +// Reference: zread_label_manager_connect function in zebra/zapi_msg.c of FRR5.x and 6.x (ZAPI5 and 6) + +func (c *Client) SendLabelManagerConnect() error { + if c.Version < 4 { + return fmt.Errorf("LABEL_MANAGER_CONNECT is not supported in version: %d", c.Version) + } + command := FRR_LABEL_MANAGER_CONNECT + proto := FRR_ROUTE_BGP + if c.Version == 5 { + command = FRR_ZAPI5_LABEL_MANAGER_CONNECT + proto = FRR_ZAPI5_ROUTE_BGP + } else if c.Version == 6 { + command = FRR_ZAPI6_LABEL_MANAGER_CONNECT + proto = FRR_ZAPI6_ROUTE_BGP + } + return c.SendCommand( + command, 0, + &LabelManagerConnectBody{ + RedistDefault: proto, + Instance: 0, + }) +} +func (c *Client) SendGetLabelChunk(body *GetLabelChunkBody) error { + if c.Version < 4 { + return fmt.Errorf("GET_LABEL_CHUNK is not supported in version: %d", c.Version) + } + command := FRR_GET_LABEL_CHUNK + body.Instance = 0 + if c.Version == 5 { + body.Proto = uint8(FRR_ZAPI5_ROUTE_BGP) + command = FRR_ZAPI5_GET_LABEL_CHUNK + } else if c.Version == 6 { + body.Proto = uint8(FRR_ZAPI6_ROUTE_BGP) + command = FRR_ZAPI6_GET_LABEL_CHUNK + } + return c.SendCommand(command, 0, body) +} + +func (c *Client) SendVrfLabel(label uint32, vrfId uint32) error { + body := &VrfLabelBody{ + Label: label, + Afi: AFI_IP, + LabelType: LSP_BGP, + } + command := FRR_ZAPI5_VRF_LABEL + if c.Version == 6 { + command = FRR_ZAPI6_VRF_LABEL + } + return c.SendCommand(command, vrfId, body) +} + // for avoiding double close func ChannelClose(ch chan *Message) bool { select { @@ -1735,11 +1812,78 @@ func (b *IPRouteBody) RouteFamily(version uint8) bgp.RouteFamily { family = syscall.AF_INET6 } } - switch family { - case syscall.AF_INET: - return bgp.RF_IPv4_UC - case syscall.AF_INET6: - return bgp.RF_IPv6_UC + if version < 5 { + switch family { + case syscall.AF_INET: + switch b.SAFI { + case SAFI_UNICAST: + return bgp.RF_IPv4_UC + case SAFI_MULTICAST: + return bgp.RF_IPv4_MC + case SAFI_MPLS_VPN, FRR_SAFI_MPLS_VPN: + return bgp.RF_IPv4_VPN + case FRR_SAFI_ENCAP, SAFI_ENCAP: + return bgp.RF_IPv4_ENCAP + } + case syscall.AF_INET6: + switch b.SAFI { + case SAFI_UNICAST: + return bgp.RF_IPv6_UC + case SAFI_MULTICAST: + return bgp.RF_IPv6_MC + case SAFI_MPLS_VPN, FRR_SAFI_MPLS_VPN: + return bgp.RF_IPv6_VPN + case FRR_SAFI_ENCAP, SAFI_ENCAP: + return bgp.RF_IPv6_ENCAP + } + default: + switch b.SAFI { + case FRR_SAFI_EVPN: + return bgp.RF_EVPN + default: + return bgp.RF_OPAQUE + } + } + } else { + switch family { + case syscall.AF_INET: + switch b.SAFI { + case FRR_ZAPI5_SAFI_UNICAST: + return bgp.RF_IPv4_UC + case FRR_ZAPI5_SAFI_MULTICAST: + return bgp.RF_IPv4_MC + case FRR_ZAPI5_SAFI_MPLS_VPN: + return bgp.RF_IPv4_VPN + case FRR_ZAPI5_SAFI_ENCAP: + return bgp.RF_IPv4_ENCAP + case FRR_ZAPI5_SAFI_LABELED_UNICAST: + return bgp.RF_IPv4_MPLS + case FRR_ZAPI5_SAFI_FLOWSPEC: + return bgp.RF_FS_IPv4_UC + } + case syscall.AF_INET6: + switch b.SAFI { + case FRR_ZAPI5_SAFI_UNICAST: + return bgp.RF_IPv6_UC + case FRR_ZAPI5_SAFI_MULTICAST: + return bgp.RF_IPv6_MC + case FRR_ZAPI5_SAFI_MPLS_VPN: + return bgp.RF_IPv6_VPN + case FRR_ZAPI5_SAFI_ENCAP: + return bgp.RF_IPv6_ENCAP + case FRR_ZAPI5_SAFI_LABELED_UNICAST: + return bgp.RF_IPv6_MPLS + case FRR_ZAPI5_SAFI_FLOWSPEC: + return bgp.RF_FS_IPv6_UC + } + default: + switch b.SAFI { + case FRR_ZAPI5_SAFI_EVPN: + return bgp.RF_EVPN + default: + return bgp.RF_OPAQUE + } + } } return bgp.RF_OPAQUE } @@ -1897,9 +2041,15 @@ func (b *IPRouteBody) Serialize(version uint8) ([]byte, error) { } if version >= 5 && b.Message&FRR_ZAPI5_MESSAGE_LABEL > 0 { buf = append(buf, nexthop.LabelNum) - bbuf := make([]byte, 4) - binary.BigEndian.PutUint32(bbuf, nexthop.MplsLabels[0]) - buf = append(buf, bbuf...) + for i := uint8(0); i < nexthop.LabelNum; i++ { + bbuf := make([]byte, 4) + /* Frr uses stream_put for mpls label array. + stream_put is unaware of byteorder coversion. + Therefore LittleEndian is used instead of BigEndian. */ + binary.LittleEndian.PutUint32(bbuf, nexthop.MplsLabels[i]) + buf = append(buf, bbuf...) + + } } } if (version <= 3 && b.Message&MESSAGE_DISTANCE > 0) || @@ -2240,7 +2390,10 @@ func decodeNexthopsFromBytes(nexthops *[]Nexthop, data []byte, family uint8, ver } nexthop.MplsLabels = make([]uint32, nexthop.LabelNum) for n := uint8(0); n < nexthop.LabelNum; n++ { - nexthop.MplsLabels[n] = binary.BigEndian.Uint32(data[offset : offset+4]) + /* Frr uses stream_put for mpls label array. + stream_put is unaware of byteorder coversion. + Therefore LittleEndian is used instead of BigEndian. */ + nexthop.MplsLabels[n] = binary.LittleEndian.Uint32(data[offset : offset+4]) offset += 4 } } @@ -2612,6 +2765,177 @@ func (b *NexthopUpdateBody) String() string { return s } +type LabelManagerConnectBody struct { + RedistDefault ROUTE_TYPE + Instance uint16 + // The followings are used in response from Zebra + Result uint8 // 0 means success +} + +// Reference: lm_label_manager_connect in lib/zclient.c of FRR +func (b *LabelManagerConnectBody) Serialize(version uint8) ([]byte, error) { + buf := make([]byte, 3) + buf[0] = uint8(b.RedistDefault) + binary.BigEndian.PutUint16(buf[1:3], b.Instance) + return buf, nil +} + +func (b *LabelManagerConnectBody) DecodeFromBytes(data []byte, version uint8) error { + size := 1 + // FRR v4 may work incorrectly. It returns result only although it uses ZAPI v5. + if version >= 4 { + size = 4 + } + if len(data) < size { + return fmt.Errorf("invalid message length for LABEL_MANAGER_CONNECT response: %d<%d", + len(data), size) + } + if version > 4 { + b.RedistDefault = ROUTE_TYPE(data[0]) + b.Instance = binary.BigEndian.Uint16(data[1:3]) + data = data[3:] + } + b.Result = data[0] + return nil +} + +func (b *LabelManagerConnectBody) String() string { + return fmt.Sprintf( + "route_type: %s, instance: %d, result: %d", + b.RedistDefault.String(), b.Instance, b.Result) +} + +// Reference: zsend_assign_label_chunk_response in zebra/zserv.c of FRR3.x +// Reference: zsend_assign_label_chunk_response in zebra/zapi_msg.c of FRR5.x and 6.x +type GetLabelChunkBody struct { + Proto uint8 // it is appeared in FRR5.x and 6.x + Instance uint16 // it is appeared in FRR5.x and 6.x + Keep uint8 + ChunkSize uint32 + // The followings are used in response from Zebra + Start uint32 + End uint32 +} + +// Reference: zread_get_label_chunk in zebra/zserv.c of FRR3.x +// Reference: zread_get_label_chunk in zebra/zapi_msg.c of FRR5.x and 6.x +func (b *GetLabelChunkBody) Serialize(version uint8) ([]byte, error) { + buf := make([]byte, 8) + pos := 0 + if version > 4 { + buf[pos] = b.Proto + binary.BigEndian.PutUint16(buf[pos+1:pos+3], b.Instance) + pos += 3 + } + buf[pos] = b.Keep + binary.BigEndian.PutUint32(buf[pos+1:pos+5], b.ChunkSize) + pos += 5 + return buf[0:pos], nil +} + +// Reference: zsend_assign_label_chunk_response in zebra/zserv.c of FRR3.x +// Reference: zsend_assign_label_chunk_response in zebra/zapi_msg.c of FRR5.x and 6.x +func (b *GetLabelChunkBody) DecodeFromBytes(data []byte, version uint8) error { + size := 9 + if version > 4 { + size = 12 + } + if len(data) < size { + return fmt.Errorf("invalid message length for GET_LABEL_CHUNK response: %d<%d", + len(data), size) + } + if version > 4 { + b.Proto = data[0] + b.Instance = binary.BigEndian.Uint16(data[1:3]) + data = data[3:] + } + b.Keep = data[0] + b.Start = binary.BigEndian.Uint32(data[1:5]) + b.End = binary.BigEndian.Uint32(data[5:9]) + return nil +} + +func (b *GetLabelChunkBody) String() string { + return fmt.Sprintf( + "keep: %d, chunk_size: %d, start: %d, end: %d", + b.Keep, b.ChunkSize, b.Start, b.End) +} + +type ReleaseLabelChunkBody struct { + Proto uint8 // it is appeared in FRR5.x and 6.x + Instance uint16 // it is appeared in FRR5.x and 6.x + Start uint32 + End uint32 +} + +func (b *ReleaseLabelChunkBody) Serialize(version uint8) ([]byte, error) { + buf := make([]byte, 11) + pos := 0 + if version > 4 { + buf[pos] = b.Proto + binary.BigEndian.PutUint16(buf[pos+1:pos+3], b.Instance) + pos += 3 + } + binary.BigEndian.PutUint32(buf[pos:pos+4], b.Start) + binary.BigEndian.PutUint32(buf[pos+4:pos+8], b.End) + pos += 8 + return buf[0:pos], nil +} + +func (b *ReleaseLabelChunkBody) DecodeFromBytes(data []byte, version uint8) error { + // No response from Zebra + return nil +} + +func (b *ReleaseLabelChunkBody) String() string { + return fmt.Sprintf( + "start: %d, end: %d", + b.Start, b.End) +} + +//go:generate stringer -type=LSP_TYPE +type LSP_TYPE uint8 + +const ( + LSP_NONE LSP_TYPE = iota //defined in FRR3 and over + LSP_STATIC //defined in FRR3 and over + LSP_LDP //defined in FRR3 and over + LSP_BGP //defined in FRR4 and over + LSP_SR //defined in FRR4 and over + LSP_SHARP //defined in FRR5 and over +) + +type VrfLabelBody struct { + Label uint32 + Afi AFI + LabelType LSP_TYPE +} + +// Reference: zclient_send_vrf_label in lib/zclient.c of FRR 5.x and 6.x +func (b *VrfLabelBody) Serialize(version uint8) ([]byte, error) { + buf := make([]byte, 6) + binary.BigEndian.PutUint32(buf[0:4], b.Label) + buf[4] = uint8(b.Afi) + buf[5] = uint8(b.LabelType) + return buf, nil +} + +func (b *VrfLabelBody) DecodeFromBytes(data []byte, version uint8) error { + if len(data) < 6 { + return fmt.Errorf("invalid message length for VRF_LABEL message: %d<6", len(data)) + } + b.Label = binary.BigEndian.Uint32(data[0:4]) + b.Afi = AFI(data[4]) + b.LabelType = LSP_TYPE(data[5]) + return nil +} + +func (b *VrfLabelBody) String() string { + return fmt.Sprintf( + "label: %d, AFI: %s LSP_type: %s", + b.Label, b.Afi, b.LabelType) +} + type Message struct { Header Header Body Body @@ -2689,6 +3013,15 @@ func (m *Message) parseFrrMessage(data []byte) error { case FRR_PW_STATUS_UPDATE: // TODO m.Body = &UnknownBody{} + case FRR_LABEL_MANAGER_CONNECT: + // Note: Synchronous message + m.Body = &LabelManagerConnectBody{} + case FRR_GET_LABEL_CHUNK: + // Note: Synchronous message + m.Body = &GetLabelChunkBody{} + case FRR_RELEASE_LABEL_CHUNK: + // Note: Synchronous message + m.Body = &ReleaseLabelChunkBody{} default: m.Body = &UnknownBody{} } @@ -2728,6 +3061,17 @@ func (m *Message) parseFrrZapi5Message(data []byte) error { case FRR_ZAPI5_PW_STATUS_UPDATE: // TODO m.Body = &UnknownBody{} + case FRR_ZAPI5_LABEL_MANAGER_CONNECT: + // Note: Synchronous message + m.Body = &LabelManagerConnectBody{} + case FRR_ZAPI5_GET_LABEL_CHUNK: + // Note: Synchronous message + m.Body = &GetLabelChunkBody{} + case FRR_ZAPI5_RELEASE_LABEL_CHUNK: + // Note: Synchronous message + m.Body = &ReleaseLabelChunkBody{} + case FRR_ZAPI5_VRF_LABEL: + m.Body = &VrfLabelBody{} default: m.Body = &UnknownBody{} } @@ -2767,6 +3111,16 @@ func (m *Message) parseFrrZapi6Message(data []byte) error { case FRR_ZAPI6_PW_STATUS_UPDATE: // TODO m.Body = &UnknownBody{} + case FRR_ZAPI6_LABEL_MANAGER_CONNECT: + // Note: Synchronous message + m.Body = &LabelManagerConnectBody{} + case FRR_ZAPI6_GET_LABEL_CHUNK: + // Note: Synchronous message + m.Body = &GetLabelChunkBody{} + case FRR_ZAPI6_RELEASE_LABEL_CHUNK: + // Note: Synchronous message + case FRR_ZAPI6_VRF_LABEL: + m.Body = &VrfLabelBody{} default: m.Body = &UnknownBody{} } |