From 192480fc7127ce0f266407cecceb00703807bbca Mon Sep 17 00:00:00 2001 From: Artur Makutunowicz Date: Thu, 17 Jan 2019 10:28:23 -0800 Subject: Add experimental BGP-LS feature --- api/attribute.pb.go | 1121 +++++++++++-- api/attribute.proto | 139 ++ api/capability.pb.go | 3 +- api/gobgp.pb.go | 997 +++++------ api/gobgp.proto | 3 + cmd/gobgp/common.go | 6 + go.mod | 42 +- go.sum | 39 + internal/pkg/apiutil/attribute.go | 234 +++ internal/pkg/config/bgp_configs.go | 3 + pkg/packet/bgp/bgp.go | 3223 +++++++++++++++++++++++++++++++++++- pkg/packet/bgp/bgp_test.go | 1932 +++++++++++++++++++++ tools/pyang_plugins/gobgp.yang | 7 + tools/spell-check/dictionary.txt | 4 + 14 files changed, 7081 insertions(+), 672 deletions(-) diff --git a/api/attribute.pb.go b/api/attribute.pb.go index 48d820e9..fd8b4805 100644 --- a/api/attribute.pb.go +++ b/api/attribute.pb.go @@ -1,6 +1,5 @@ -// Code generated by protoc-gen-go. +// Code generated by protoc-gen-go. DO NOT EDIT. // source: attribute.proto -// DO NOT EDIT! package gobgpapi @@ -14,6 +13,37 @@ var _ = proto.Marshal var _ = fmt.Errorf var _ = math.Inf +// Based om RFC 7752, Table 1. +type LsNLRIType int32 + +const ( + LsNLRIType_LS_NLRI_UNKNOWN LsNLRIType = 0 + LsNLRIType_LS_NLRI_NODE LsNLRIType = 1 + LsNLRIType_LS_NLRI_LINK LsNLRIType = 2 + LsNLRIType_LS_NLRI_PREFIX_V4 LsNLRIType = 3 + LsNLRIType_LS_NLRI_PREFIX_V6 LsNLRIType = 4 +) + +var LsNLRIType_name = map[int32]string{ + 0: "LS_NLRI_UNKNOWN", + 1: "LS_NLRI_NODE", + 2: "LS_NLRI_LINK", + 3: "LS_NLRI_PREFIX_V4", + 4: "LS_NLRI_PREFIX_V6", +} +var LsNLRIType_value = map[string]int32{ + "LS_NLRI_UNKNOWN": 0, + "LS_NLRI_NODE": 1, + "LS_NLRI_LINK": 2, + "LS_NLRI_PREFIX_V4": 3, + "LS_NLRI_PREFIX_V6": 4, +} + +func (x LsNLRIType) String() string { + return proto.EnumName(LsNLRIType_name, int32(x)) +} +func (LsNLRIType) EnumDescriptor() ([]byte, []int) { return fileDescriptor1, []int{0} } + type OriginAttribute struct { Origin uint32 `protobuf:"varint,1,opt,name=origin" json:"origin,omitempty"` } @@ -909,6 +939,261 @@ func (m *OpaqueNLRI) GetValue() []byte { return nil } +type LsNodeDescriptor struct { + Asn uint32 `protobuf:"varint,1,opt,name=asn" json:"asn,omitempty"` + BgpLsId uint32 `protobuf:"varint,2,opt,name=bgp_ls_id,json=bgpLsId" json:"bgp_ls_id,omitempty"` + OspfAreaId uint32 `protobuf:"varint,3,opt,name=ospf_area_id,json=ospfAreaId" json:"ospf_area_id,omitempty"` + Pseudonode bool `protobuf:"varint,4,opt,name=pseudonode" json:"pseudonode,omitempty"` + IgpRouterId string `protobuf:"bytes,5,opt,name=igp_router_id,json=igpRouterId" json:"igp_router_id,omitempty"` +} + +func (m *LsNodeDescriptor) Reset() { *m = LsNodeDescriptor{} } +func (m *LsNodeDescriptor) String() string { return proto.CompactTextString(m) } +func (*LsNodeDescriptor) ProtoMessage() {} +func (*LsNodeDescriptor) Descriptor() ([]byte, []int) { return fileDescriptor1, []int{32} } + +func (m *LsNodeDescriptor) GetAsn() uint32 { + if m != nil { + return m.Asn + } + return 0 +} + +func (m *LsNodeDescriptor) GetBgpLsId() uint32 { + if m != nil { + return m.BgpLsId + } + return 0 +} + +func (m *LsNodeDescriptor) GetOspfAreaId() uint32 { + if m != nil { + return m.OspfAreaId + } + return 0 +} + +func (m *LsNodeDescriptor) GetPseudonode() bool { + if m != nil { + return m.Pseudonode + } + return false +} + +func (m *LsNodeDescriptor) GetIgpRouterId() string { + if m != nil { + return m.IgpRouterId + } + return "" +} + +type LsLinkDescriptor struct { + LinkLocalId uint32 `protobuf:"varint,1,opt,name=link_local_id,json=linkLocalId" json:"link_local_id,omitempty"` + LinkRemoteId uint32 `protobuf:"varint,2,opt,name=link_remote_id,json=linkRemoteId" json:"link_remote_id,omitempty"` + InterfaceAddrIpv4 string `protobuf:"bytes,3,opt,name=interface_addr_ipv4,json=interfaceAddrIpv4" json:"interface_addr_ipv4,omitempty"` + NeighborAddrIpv4 string `protobuf:"bytes,4,opt,name=neighbor_addr_ipv4,json=neighborAddrIpv4" json:"neighbor_addr_ipv4,omitempty"` + InterfaceAddrIpv6 string `protobuf:"bytes,5,opt,name=interface_addr_ipv6,json=interfaceAddrIpv6" json:"interface_addr_ipv6,omitempty"` + NeighborAddrIpv6 string `protobuf:"bytes,6,opt,name=neighbor_addr_ipv6,json=neighborAddrIpv6" json:"neighbor_addr_ipv6,omitempty"` +} + +func (m *LsLinkDescriptor) Reset() { *m = LsLinkDescriptor{} } +func (m *LsLinkDescriptor) String() string { return proto.CompactTextString(m) } +func (*LsLinkDescriptor) ProtoMessage() {} +func (*LsLinkDescriptor) Descriptor() ([]byte, []int) { return fileDescriptor1, []int{33} } + +func (m *LsLinkDescriptor) GetLinkLocalId() uint32 { + if m != nil { + return m.LinkLocalId + } + return 0 +} + +func (m *LsLinkDescriptor) GetLinkRemoteId() uint32 { + if m != nil { + return m.LinkRemoteId + } + return 0 +} + +func (m *LsLinkDescriptor) GetInterfaceAddrIpv4() string { + if m != nil { + return m.InterfaceAddrIpv4 + } + return "" +} + +func (m *LsLinkDescriptor) GetNeighborAddrIpv4() string { + if m != nil { + return m.NeighborAddrIpv4 + } + return "" +} + +func (m *LsLinkDescriptor) GetInterfaceAddrIpv6() string { + if m != nil { + return m.InterfaceAddrIpv6 + } + return "" +} + +func (m *LsLinkDescriptor) GetNeighborAddrIpv6() string { + if m != nil { + return m.NeighborAddrIpv6 + } + return "" +} + +type LsPrefixDescriptor struct { + IpReachability []string `protobuf:"bytes,1,rep,name=ip_reachability,json=ipReachability" json:"ip_reachability,omitempty"` + OspfRouteType string `protobuf:"bytes,2,opt,name=ospf_route_type,json=ospfRouteType" json:"ospf_route_type,omitempty"` +} + +func (m *LsPrefixDescriptor) Reset() { *m = LsPrefixDescriptor{} } +func (m *LsPrefixDescriptor) String() string { return proto.CompactTextString(m) } +func (*LsPrefixDescriptor) ProtoMessage() {} +func (*LsPrefixDescriptor) Descriptor() ([]byte, []int) { return fileDescriptor1, []int{34} } + +func (m *LsPrefixDescriptor) GetIpReachability() []string { + if m != nil { + return m.IpReachability + } + return nil +} + +func (m *LsPrefixDescriptor) GetOspfRouteType() string { + if m != nil { + return m.OspfRouteType + } + return "" +} + +type LsNodeNLRI struct { + LocalNode *LsNodeDescriptor `protobuf:"bytes,1,opt,name=local_node,json=localNode" json:"local_node,omitempty"` +} + +func (m *LsNodeNLRI) Reset() { *m = LsNodeNLRI{} } +func (m *LsNodeNLRI) String() string { return proto.CompactTextString(m) } +func (*LsNodeNLRI) ProtoMessage() {} +func (*LsNodeNLRI) Descriptor() ([]byte, []int) { return fileDescriptor1, []int{35} } + +func (m *LsNodeNLRI) GetLocalNode() *LsNodeDescriptor { + if m != nil { + return m.LocalNode + } + return nil +} + +type LsLinkNLRI struct { + LocalNode *LsNodeDescriptor `protobuf:"bytes,1,opt,name=local_node,json=localNode" json:"local_node,omitempty"` + RemoteNode *LsNodeDescriptor `protobuf:"bytes,2,opt,name=remote_node,json=remoteNode" json:"remote_node,omitempty"` + LinkDescriptor *LsLinkDescriptor `protobuf:"bytes,3,opt,name=link_descriptor,json=linkDescriptor" json:"link_descriptor,omitempty"` +} + +func (m *LsLinkNLRI) Reset() { *m = LsLinkNLRI{} } +func (m *LsLinkNLRI) String() string { return proto.CompactTextString(m) } +func (*LsLinkNLRI) ProtoMessage() {} +func (*LsLinkNLRI) Descriptor() ([]byte, []int) { return fileDescriptor1, []int{36} } + +func (m *LsLinkNLRI) GetLocalNode() *LsNodeDescriptor { + if m != nil { + return m.LocalNode + } + return nil +} + +func (m *LsLinkNLRI) GetRemoteNode() *LsNodeDescriptor { + if m != nil { + return m.RemoteNode + } + return nil +} + +func (m *LsLinkNLRI) GetLinkDescriptor() *LsLinkDescriptor { + if m != nil { + return m.LinkDescriptor + } + return nil +} + +type LsPrefixV4NLRI struct { + LocalNode *LsNodeDescriptor `protobuf:"bytes,1,opt,name=local_node,json=localNode" json:"local_node,omitempty"` + PrefixDescriptor *LsPrefixDescriptor `protobuf:"bytes,2,opt,name=prefix_descriptor,json=prefixDescriptor" json:"prefix_descriptor,omitempty"` +} + +func (m *LsPrefixV4NLRI) Reset() { *m = LsPrefixV4NLRI{} } +func (m *LsPrefixV4NLRI) String() string { return proto.CompactTextString(m) } +func (*LsPrefixV4NLRI) ProtoMessage() {} +func (*LsPrefixV4NLRI) Descriptor() ([]byte, []int) { return fileDescriptor1, []int{37} } + +func (m *LsPrefixV4NLRI) GetLocalNode() *LsNodeDescriptor { + if m != nil { + return m.LocalNode + } + return nil +} + +func (m *LsPrefixV4NLRI) GetPrefixDescriptor() *LsPrefixDescriptor { + if m != nil { + return m.PrefixDescriptor + } + return nil +} + +type LsPrefixV6NLRI struct { + LocalNode *LsNodeDescriptor `protobuf:"bytes,1,opt,name=local_node,json=localNode" json:"local_node,omitempty"` + PrefixDescriptor *LsPrefixDescriptor `protobuf:"bytes,2,opt,name=prefix_descriptor,json=prefixDescriptor" json:"prefix_descriptor,omitempty"` +} + +func (m *LsPrefixV6NLRI) Reset() { *m = LsPrefixV6NLRI{} } +func (m *LsPrefixV6NLRI) String() string { return proto.CompactTextString(m) } +func (*LsPrefixV6NLRI) ProtoMessage() {} +func (*LsPrefixV6NLRI) Descriptor() ([]byte, []int) { return fileDescriptor1, []int{38} } + +func (m *LsPrefixV6NLRI) GetLocalNode() *LsNodeDescriptor { + if m != nil { + return m.LocalNode + } + return nil +} + +func (m *LsPrefixV6NLRI) GetPrefixDescriptor() *LsPrefixDescriptor { + if m != nil { + return m.PrefixDescriptor + } + return nil +} + +// LsAddrPrefix represents the NLRI for: +// - AFI=16388, SAFI=71 +type LsAddrPrefix struct { + Type LsNLRIType `protobuf:"varint,1,opt,name=type,enum=gobgpapi.LsNLRIType" json:"type,omitempty"` + // One of: + // - LsNodeNLRI + // - LsLinkNLRI + // - LsPrefixV4NLRI + // - LsPrefixV6NLRI + Nlri *google_protobuf.Any `protobuf:"bytes,2,opt,name=nlri" json:"nlri,omitempty"` +} + +func (m *LsAddrPrefix) Reset() { *m = LsAddrPrefix{} } +func (m *LsAddrPrefix) String() string { return proto.CompactTextString(m) } +func (*LsAddrPrefix) ProtoMessage() {} +func (*LsAddrPrefix) Descriptor() ([]byte, []int) { return fileDescriptor1, []int{39} } + +func (m *LsAddrPrefix) GetType() LsNLRIType { + if m != nil { + return m.Type + } + return LsNLRIType_LS_NLRI_UNKNOWN +} + +func (m *LsAddrPrefix) GetNlri() *google_protobuf.Any { + if m != nil { + return m.Nlri + } + return nil +} + type MpReachNLRIAttribute struct { Family *Family `protobuf:"bytes,1,opt,name=family" json:"family,omitempty"` NextHops []string `protobuf:"bytes,2,rep,name=next_hops,json=nextHops" json:"next_hops,omitempty"` @@ -926,13 +1211,14 @@ type MpReachNLRIAttribute struct { // - FlowSpecNLRI // - VPNFlowSpecNLRI // - OpaqueNLRI + // - LsAddrPrefix Nlris []*google_protobuf.Any `protobuf:"bytes,3,rep,name=nlris" json:"nlris,omitempty"` } func (m *MpReachNLRIAttribute) Reset() { *m = MpReachNLRIAttribute{} } func (m *MpReachNLRIAttribute) String() string { return proto.CompactTextString(m) } func (*MpReachNLRIAttribute) ProtoMessage() {} -func (*MpReachNLRIAttribute) Descriptor() ([]byte, []int) { return fileDescriptor1, []int{32} } +func (*MpReachNLRIAttribute) Descriptor() ([]byte, []int) { return fileDescriptor1, []int{40} } func (m *MpReachNLRIAttribute) GetFamily() *Family { if m != nil { @@ -964,7 +1250,7 @@ type MpUnreachNLRIAttribute struct { func (m *MpUnreachNLRIAttribute) Reset() { *m = MpUnreachNLRIAttribute{} } func (m *MpUnreachNLRIAttribute) String() string { return proto.CompactTextString(m) } func (*MpUnreachNLRIAttribute) ProtoMessage() {} -func (*MpUnreachNLRIAttribute) Descriptor() ([]byte, []int) { return fileDescriptor1, []int{33} } +func (*MpUnreachNLRIAttribute) Descriptor() ([]byte, []int) { return fileDescriptor1, []int{41} } func (m *MpUnreachNLRIAttribute) GetFamily() *Family { if m != nil { @@ -990,7 +1276,7 @@ type TwoOctetAsSpecificExtended struct { func (m *TwoOctetAsSpecificExtended) Reset() { *m = TwoOctetAsSpecificExtended{} } func (m *TwoOctetAsSpecificExtended) String() string { return proto.CompactTextString(m) } func (*TwoOctetAsSpecificExtended) ProtoMessage() {} -func (*TwoOctetAsSpecificExtended) Descriptor() ([]byte, []int) { return fileDescriptor1, []int{34} } +func (*TwoOctetAsSpecificExtended) Descriptor() ([]byte, []int) { return fileDescriptor1, []int{42} } func (m *TwoOctetAsSpecificExtended) GetIsTransitive() bool { if m != nil { @@ -1030,7 +1316,7 @@ type IPv4AddressSpecificExtended struct { func (m *IPv4AddressSpecificExtended) Reset() { *m = IPv4AddressSpecificExtended{} } func (m *IPv4AddressSpecificExtended) String() string { return proto.CompactTextString(m) } func (*IPv4AddressSpecificExtended) ProtoMessage() {} -func (*IPv4AddressSpecificExtended) Descriptor() ([]byte, []int) { return fileDescriptor1, []int{35} } +func (*IPv4AddressSpecificExtended) Descriptor() ([]byte, []int) { return fileDescriptor1, []int{43} } func (m *IPv4AddressSpecificExtended) GetIsTransitive() bool { if m != nil { @@ -1070,7 +1356,7 @@ type FourOctetAsSpecificExtended struct { func (m *FourOctetAsSpecificExtended) Reset() { *m = FourOctetAsSpecificExtended{} } func (m *FourOctetAsSpecificExtended) String() string { return proto.CompactTextString(m) } func (*FourOctetAsSpecificExtended) ProtoMessage() {} -func (*FourOctetAsSpecificExtended) Descriptor() ([]byte, []int) { return fileDescriptor1, []int{36} } +func (*FourOctetAsSpecificExtended) Descriptor() ([]byte, []int) { return fileDescriptor1, []int{44} } func (m *FourOctetAsSpecificExtended) GetIsTransitive() bool { if m != nil { @@ -1107,7 +1393,7 @@ type ValidationExtended struct { func (m *ValidationExtended) Reset() { *m = ValidationExtended{} } func (m *ValidationExtended) String() string { return proto.CompactTextString(m) } func (*ValidationExtended) ProtoMessage() {} -func (*ValidationExtended) Descriptor() ([]byte, []int) { return fileDescriptor1, []int{37} } +func (*ValidationExtended) Descriptor() ([]byte, []int) { return fileDescriptor1, []int{45} } func (m *ValidationExtended) GetState() uint32 { if m != nil { @@ -1123,7 +1409,7 @@ type ColorExtended struct { func (m *ColorExtended) Reset() { *m = ColorExtended{} } func (m *ColorExtended) String() string { return proto.CompactTextString(m) } func (*ColorExtended) ProtoMessage() {} -func (*ColorExtended) Descriptor() ([]byte, []int) { return fileDescriptor1, []int{38} } +func (*ColorExtended) Descriptor() ([]byte, []int) { return fileDescriptor1, []int{46} } func (m *ColorExtended) GetColor() uint32 { if m != nil { @@ -1139,7 +1425,7 @@ type EncapExtended struct { func (m *EncapExtended) Reset() { *m = EncapExtended{} } func (m *EncapExtended) String() string { return proto.CompactTextString(m) } func (*EncapExtended) ProtoMessage() {} -func (*EncapExtended) Descriptor() ([]byte, []int) { return fileDescriptor1, []int{39} } +func (*EncapExtended) Descriptor() ([]byte, []int) { return fileDescriptor1, []int{47} } func (m *EncapExtended) GetTunnelType() uint32 { if m != nil { @@ -1154,7 +1440,7 @@ type DefaultGatewayExtended struct { func (m *DefaultGatewayExtended) Reset() { *m = DefaultGatewayExtended{} } func (m *DefaultGatewayExtended) String() string { return proto.CompactTextString(m) } func (*DefaultGatewayExtended) ProtoMessage() {} -func (*DefaultGatewayExtended) Descriptor() ([]byte, []int) { return fileDescriptor1, []int{40} } +func (*DefaultGatewayExtended) Descriptor() ([]byte, []int) { return fileDescriptor1, []int{48} } type OpaqueExtended struct { IsTransitive bool `protobuf:"varint,1,opt,name=is_transitive,json=isTransitive" json:"is_transitive,omitempty"` @@ -1164,7 +1450,7 @@ type OpaqueExtended struct { func (m *OpaqueExtended) Reset() { *m = OpaqueExtended{} } func (m *OpaqueExtended) String() string { return proto.CompactTextString(m) } func (*OpaqueExtended) ProtoMessage() {} -func (*OpaqueExtended) Descriptor() ([]byte, []int) { return fileDescriptor1, []int{41} } +func (*OpaqueExtended) Descriptor() ([]byte, []int) { return fileDescriptor1, []int{49} } func (m *OpaqueExtended) GetIsTransitive() bool { if m != nil { @@ -1188,7 +1474,7 @@ type ESILabelExtended struct { func (m *ESILabelExtended) Reset() { *m = ESILabelExtended{} } func (m *ESILabelExtended) String() string { return proto.CompactTextString(m) } func (*ESILabelExtended) ProtoMessage() {} -func (*ESILabelExtended) Descriptor() ([]byte, []int) { return fileDescriptor1, []int{42} } +func (*ESILabelExtended) Descriptor() ([]byte, []int) { return fileDescriptor1, []int{50} } func (m *ESILabelExtended) GetIsSingleActive() bool { if m != nil { @@ -1211,7 +1497,7 @@ type ESImportRouteTarget struct { func (m *ESImportRouteTarget) Reset() { *m = ESImportRouteTarget{} } func (m *ESImportRouteTarget) String() string { return proto.CompactTextString(m) } func (*ESImportRouteTarget) ProtoMessage() {} -func (*ESImportRouteTarget) Descriptor() ([]byte, []int) { return fileDescriptor1, []int{43} } +func (*ESImportRouteTarget) Descriptor() ([]byte, []int) { return fileDescriptor1, []int{51} } func (m *ESImportRouteTarget) GetEsImport() string { if m != nil { @@ -1228,7 +1514,7 @@ type MacMobilityExtended struct { func (m *MacMobilityExtended) Reset() { *m = MacMobilityExtended{} } func (m *MacMobilityExtended) String() string { return proto.CompactTextString(m) } func (*MacMobilityExtended) ProtoMessage() {} -func (*MacMobilityExtended) Descriptor() ([]byte, []int) { return fileDescriptor1, []int{44} } +func (*MacMobilityExtended) Descriptor() ([]byte, []int) { return fileDescriptor1, []int{52} } func (m *MacMobilityExtended) GetIsSticky() bool { if m != nil { @@ -1251,7 +1537,7 @@ type RouterMacExtended struct { func (m *RouterMacExtended) Reset() { *m = RouterMacExtended{} } func (m *RouterMacExtended) String() string { return proto.CompactTextString(m) } func (*RouterMacExtended) ProtoMessage() {} -func (*RouterMacExtended) Descriptor() ([]byte, []int) { return fileDescriptor1, []int{45} } +func (*RouterMacExtended) Descriptor() ([]byte, []int) { return fileDescriptor1, []int{53} } func (m *RouterMacExtended) GetMac() string { if m != nil { @@ -1268,7 +1554,7 @@ type TrafficRateExtended struct { func (m *TrafficRateExtended) Reset() { *m = TrafficRateExtended{} } func (m *TrafficRateExtended) String() string { return proto.CompactTextString(m) } func (*TrafficRateExtended) ProtoMessage() {} -func (*TrafficRateExtended) Descriptor() ([]byte, []int) { return fileDescriptor1, []int{46} } +func (*TrafficRateExtended) Descriptor() ([]byte, []int) { return fileDescriptor1, []int{54} } func (m *TrafficRateExtended) GetAs() uint32 { if m != nil { @@ -1292,7 +1578,7 @@ type TrafficActionExtended struct { func (m *TrafficActionExtended) Reset() { *m = TrafficActionExtended{} } func (m *TrafficActionExtended) String() string { return proto.CompactTextString(m) } func (*TrafficActionExtended) ProtoMessage() {} -func (*TrafficActionExtended) Descriptor() ([]byte, []int) { return fileDescriptor1, []int{47} } +func (*TrafficActionExtended) Descriptor() ([]byte, []int) { return fileDescriptor1, []int{55} } func (m *TrafficActionExtended) GetTerminal() bool { if m != nil { @@ -1317,7 +1603,7 @@ func (m *RedirectTwoOctetAsSpecificExtended) Reset() { *m = RedirectTwoO func (m *RedirectTwoOctetAsSpecificExtended) String() string { return proto.CompactTextString(m) } func (*RedirectTwoOctetAsSpecificExtended) ProtoMessage() {} func (*RedirectTwoOctetAsSpecificExtended) Descriptor() ([]byte, []int) { - return fileDescriptor1, []int{48} + return fileDescriptor1, []int{56} } func (m *RedirectTwoOctetAsSpecificExtended) GetAs() uint32 { @@ -1343,7 +1629,7 @@ func (m *RedirectIPv4AddressSpecificExtended) Reset() { *m = RedirectIPv func (m *RedirectIPv4AddressSpecificExtended) String() string { return proto.CompactTextString(m) } func (*RedirectIPv4AddressSpecificExtended) ProtoMessage() {} func (*RedirectIPv4AddressSpecificExtended) Descriptor() ([]byte, []int) { - return fileDescriptor1, []int{49} + return fileDescriptor1, []int{57} } func (m *RedirectIPv4AddressSpecificExtended) GetAddress() string { @@ -1369,7 +1655,7 @@ func (m *RedirectFourOctetAsSpecificExtended) Reset() { *m = RedirectFou func (m *RedirectFourOctetAsSpecificExtended) String() string { return proto.CompactTextString(m) } func (*RedirectFourOctetAsSpecificExtended) ProtoMessage() {} func (*RedirectFourOctetAsSpecificExtended) Descriptor() ([]byte, []int) { - return fileDescriptor1, []int{50} + return fileDescriptor1, []int{58} } func (m *RedirectFourOctetAsSpecificExtended) GetAs() uint32 { @@ -1393,7 +1679,7 @@ type TrafficRemarkExtended struct { func (m *TrafficRemarkExtended) Reset() { *m = TrafficRemarkExtended{} } func (m *TrafficRemarkExtended) String() string { return proto.CompactTextString(m) } func (*TrafficRemarkExtended) ProtoMessage() {} -func (*TrafficRemarkExtended) Descriptor() ([]byte, []int) { return fileDescriptor1, []int{51} } +func (*TrafficRemarkExtended) Descriptor() ([]byte, []int) { return fileDescriptor1, []int{59} } func (m *TrafficRemarkExtended) GetDscp() uint32 { if m != nil { @@ -1410,7 +1696,7 @@ type UnknownExtended struct { func (m *UnknownExtended) Reset() { *m = UnknownExtended{} } func (m *UnknownExtended) String() string { return proto.CompactTextString(m) } func (*UnknownExtended) ProtoMessage() {} -func (*UnknownExtended) Descriptor() ([]byte, []int) { return fileDescriptor1, []int{52} } +func (*UnknownExtended) Descriptor() ([]byte, []int) { return fileDescriptor1, []int{60} } func (m *UnknownExtended) GetType() uint32 { if m != nil { @@ -1448,7 +1734,7 @@ type ExtendedCommunitiesAttribute struct { func (m *ExtendedCommunitiesAttribute) Reset() { *m = ExtendedCommunitiesAttribute{} } func (m *ExtendedCommunitiesAttribute) String() string { return proto.CompactTextString(m) } func (*ExtendedCommunitiesAttribute) ProtoMessage() {} -func (*ExtendedCommunitiesAttribute) Descriptor() ([]byte, []int) { return fileDescriptor1, []int{53} } +func (*ExtendedCommunitiesAttribute) Descriptor() ([]byte, []int) { return fileDescriptor1, []int{61} } func (m *ExtendedCommunitiesAttribute) GetCommunities() []*google_protobuf.Any { if m != nil { @@ -1464,7 +1750,7 @@ type As4PathAttribute struct { func (m *As4PathAttribute) Reset() { *m = As4PathAttribute{} } func (m *As4PathAttribute) String() string { return proto.CompactTextString(m) } func (*As4PathAttribute) ProtoMessage() {} -func (*As4PathAttribute) Descriptor() ([]byte, []int) { return fileDescriptor1, []int{54} } +func (*As4PathAttribute) Descriptor() ([]byte, []int) { return fileDescriptor1, []int{62} } func (m *As4PathAttribute) GetSegments() []*AsSegment { if m != nil { @@ -1481,7 +1767,7 @@ type As4AggregatorAttribute struct { func (m *As4AggregatorAttribute) Reset() { *m = As4AggregatorAttribute{} } func (m *As4AggregatorAttribute) String() string { return proto.CompactTextString(m) } func (*As4AggregatorAttribute) ProtoMessage() {} -func (*As4AggregatorAttribute) Descriptor() ([]byte, []int) { return fileDescriptor1, []int{55} } +func (*As4AggregatorAttribute) Descriptor() ([]byte, []int) { return fileDescriptor1, []int{63} } func (m *As4AggregatorAttribute) GetAs() uint32 { if m != nil { @@ -1507,7 +1793,7 @@ type PmsiTunnelAttribute struct { func (m *PmsiTunnelAttribute) Reset() { *m = PmsiTunnelAttribute{} } func (m *PmsiTunnelAttribute) String() string { return proto.CompactTextString(m) } func (*PmsiTunnelAttribute) ProtoMessage() {} -func (*PmsiTunnelAttribute) Descriptor() ([]byte, []int) { return fileDescriptor1, []int{56} } +func (*PmsiTunnelAttribute) Descriptor() ([]byte, []int) { return fileDescriptor1, []int{64} } func (m *PmsiTunnelAttribute) GetFlags() uint32 { if m != nil { @@ -1545,7 +1831,7 @@ type TunnelEncapSubTLVEncapsulation struct { func (m *TunnelEncapSubTLVEncapsulation) Reset() { *m = TunnelEncapSubTLVEncapsulation{} } func (m *TunnelEncapSubTLVEncapsulation) String() string { return proto.CompactTextString(m) } func (*TunnelEncapSubTLVEncapsulation) ProtoMessage() {} -func (*TunnelEncapSubTLVEncapsulation) Descriptor() ([]byte, []int) { return fileDescriptor1, []int{57} } +func (*TunnelEncapSubTLVEncapsulation) Descriptor() ([]byte, []int) { return fileDescriptor1, []int{65} } func (m *TunnelEncapSubTLVEncapsulation) GetKey() uint32 { if m != nil { @@ -1568,7 +1854,7 @@ type TunnelEncapSubTLVProtocol struct { func (m *TunnelEncapSubTLVProtocol) Reset() { *m = TunnelEncapSubTLVProtocol{} } func (m *TunnelEncapSubTLVProtocol) String() string { return proto.CompactTextString(m) } func (*TunnelEncapSubTLVProtocol) ProtoMessage() {} -func (*TunnelEncapSubTLVProtocol) Descriptor() ([]byte, []int) { return fileDescriptor1, []int{58} } +func (*TunnelEncapSubTLVProtocol) Descriptor() ([]byte, []int) { return fileDescriptor1, []int{66} } func (m *TunnelEncapSubTLVProtocol) GetProtocol() uint32 { if m != nil { @@ -1584,7 +1870,7 @@ type TunnelEncapSubTLVColor struct { func (m *TunnelEncapSubTLVColor) Reset() { *m = TunnelEncapSubTLVColor{} } func (m *TunnelEncapSubTLVColor) String() string { return proto.CompactTextString(m) } func (*TunnelEncapSubTLVColor) ProtoMessage() {} -func (*TunnelEncapSubTLVColor) Descriptor() ([]byte, []int) { return fileDescriptor1, []int{59} } +func (*TunnelEncapSubTLVColor) Descriptor() ([]byte, []int) { return fileDescriptor1, []int{67} } func (m *TunnelEncapSubTLVColor) GetColor() uint32 { if m != nil { @@ -1601,7 +1887,7 @@ type TunnelEncapSubTLVUnknown struct { func (m *TunnelEncapSubTLVUnknown) Reset() { *m = TunnelEncapSubTLVUnknown{} } func (m *TunnelEncapSubTLVUnknown) String() string { return proto.CompactTextString(m) } func (*TunnelEncapSubTLVUnknown) ProtoMessage() {} -func (*TunnelEncapSubTLVUnknown) Descriptor() ([]byte, []int) { return fileDescriptor1, []int{60} } +func (*TunnelEncapSubTLVUnknown) Descriptor() ([]byte, []int) { return fileDescriptor1, []int{68} } func (m *TunnelEncapSubTLVUnknown) GetType() uint32 { if m != nil { @@ -1630,7 +1916,7 @@ type TunnelEncapTLV struct { func (m *TunnelEncapTLV) Reset() { *m = TunnelEncapTLV{} } func (m *TunnelEncapTLV) String() string { return proto.CompactTextString(m) } func (*TunnelEncapTLV) ProtoMessage() {} -func (*TunnelEncapTLV) Descriptor() ([]byte, []int) { return fileDescriptor1, []int{61} } +func (*TunnelEncapTLV) Descriptor() ([]byte, []int) { return fileDescriptor1, []int{69} } func (m *TunnelEncapTLV) GetType() uint32 { if m != nil { @@ -1653,7 +1939,7 @@ type TunnelEncapAttribute struct { func (m *TunnelEncapAttribute) Reset() { *m = TunnelEncapAttribute{} } func (m *TunnelEncapAttribute) String() string { return proto.CompactTextString(m) } func (*TunnelEncapAttribute) ProtoMessage() {} -func (*TunnelEncapAttribute) Descriptor() ([]byte, []int) { return fileDescriptor1, []int{62} } +func (*TunnelEncapAttribute) Descriptor() ([]byte, []int) { return fileDescriptor1, []int{70} } func (m *TunnelEncapAttribute) GetTlvs() []*TunnelEncapTLV { if m != nil { @@ -1672,7 +1958,7 @@ type IPv6AddressSpecificExtended struct { func (m *IPv6AddressSpecificExtended) Reset() { *m = IPv6AddressSpecificExtended{} } func (m *IPv6AddressSpecificExtended) String() string { return proto.CompactTextString(m) } func (*IPv6AddressSpecificExtended) ProtoMessage() {} -func (*IPv6AddressSpecificExtended) Descriptor() ([]byte, []int) { return fileDescriptor1, []int{63} } +func (*IPv6AddressSpecificExtended) Descriptor() ([]byte, []int) { return fileDescriptor1, []int{71} } func (m *IPv6AddressSpecificExtended) GetIsTransitive() bool { if m != nil { @@ -1711,7 +1997,7 @@ func (m *RedirectIPv6AddressSpecificExtended) Reset() { *m = RedirectIPv func (m *RedirectIPv6AddressSpecificExtended) String() string { return proto.CompactTextString(m) } func (*RedirectIPv6AddressSpecificExtended) ProtoMessage() {} func (*RedirectIPv6AddressSpecificExtended) Descriptor() ([]byte, []int) { - return fileDescriptor1, []int{64} + return fileDescriptor1, []int{72} } func (m *RedirectIPv6AddressSpecificExtended) GetAddress() string { @@ -1739,7 +2025,7 @@ func (m *IP6ExtendedCommunitiesAttribute) Reset() { *m = IP6ExtendedComm func (m *IP6ExtendedCommunitiesAttribute) String() string { return proto.CompactTextString(m) } func (*IP6ExtendedCommunitiesAttribute) ProtoMessage() {} func (*IP6ExtendedCommunitiesAttribute) Descriptor() ([]byte, []int) { - return fileDescriptor1, []int{65} + return fileDescriptor1, []int{73} } func (m *IP6ExtendedCommunitiesAttribute) GetCommunities() []*google_protobuf.Any { @@ -1756,7 +2042,7 @@ type AigpTLVIGPMetric struct { func (m *AigpTLVIGPMetric) Reset() { *m = AigpTLVIGPMetric{} } func (m *AigpTLVIGPMetric) String() string { return proto.CompactTextString(m) } func (*AigpTLVIGPMetric) ProtoMessage() {} -func (*AigpTLVIGPMetric) Descriptor() ([]byte, []int) { return fileDescriptor1, []int{66} } +func (*AigpTLVIGPMetric) Descriptor() ([]byte, []int) { return fileDescriptor1, []int{74} } func (m *AigpTLVIGPMetric) GetMetric() uint64 { if m != nil { @@ -1773,7 +2059,7 @@ type AigpTLVUnknown struct { func (m *AigpTLVUnknown) Reset() { *m = AigpTLVUnknown{} } func (m *AigpTLVUnknown) String() string { return proto.CompactTextString(m) } func (*AigpTLVUnknown) ProtoMessage() {} -func (*AigpTLVUnknown) Descriptor() ([]byte, []int) { return fileDescriptor1, []int{67} } +func (*AigpTLVUnknown) Descriptor() ([]byte, []int) { return fileDescriptor1, []int{75} } func (m *AigpTLVUnknown) GetType() uint32 { if m != nil { @@ -1799,7 +2085,7 @@ type AigpAttribute struct { func (m *AigpAttribute) Reset() { *m = AigpAttribute{} } func (m *AigpAttribute) String() string { return proto.CompactTextString(m) } func (*AigpAttribute) ProtoMessage() {} -func (*AigpAttribute) Descriptor() ([]byte, []int) { return fileDescriptor1, []int{68} } +func (*AigpAttribute) Descriptor() ([]byte, []int) { return fileDescriptor1, []int{76} } func (m *AigpAttribute) GetTlvs() []*google_protobuf.Any { if m != nil { @@ -1817,7 +2103,7 @@ type LargeCommunity struct { func (m *LargeCommunity) Reset() { *m = LargeCommunity{} } func (m *LargeCommunity) String() string { return proto.CompactTextString(m) } func (*LargeCommunity) ProtoMessage() {} -func (*LargeCommunity) Descriptor() ([]byte, []int) { return fileDescriptor1, []int{69} } +func (*LargeCommunity) Descriptor() ([]byte, []int) { return fileDescriptor1, []int{77} } func (m *LargeCommunity) GetGlobalAdmin() uint32 { if m != nil { @@ -1847,7 +2133,7 @@ type LargeCommunitiesAttribute struct { func (m *LargeCommunitiesAttribute) Reset() { *m = LargeCommunitiesAttribute{} } func (m *LargeCommunitiesAttribute) String() string { return proto.CompactTextString(m) } func (*LargeCommunitiesAttribute) ProtoMessage() {} -func (*LargeCommunitiesAttribute) Descriptor() ([]byte, []int) { return fileDescriptor1, []int{70} } +func (*LargeCommunitiesAttribute) Descriptor() ([]byte, []int) { return fileDescriptor1, []int{78} } func (m *LargeCommunitiesAttribute) GetCommunities() []*LargeCommunity { if m != nil { @@ -1856,6 +2142,430 @@ func (m *LargeCommunitiesAttribute) GetCommunities() []*LargeCommunity { return nil } +type LsNodeFlags struct { + Overload bool `protobuf:"varint,1,opt,name=overload" json:"overload,omitempty"` + Attached bool `protobuf:"varint,2,opt,name=attached" json:"attached,omitempty"` + External bool `protobuf:"varint,3,opt,name=external" json:"external,omitempty"` + Abr bool `protobuf:"varint,4,opt,name=abr" json:"abr,omitempty"` + Router bool `protobuf:"varint,5,opt,name=router" json:"router,omitempty"` + V6 bool `protobuf:"varint,6,opt,name=v6" json:"v6,omitempty"` +} + +func (m *LsNodeFlags) Reset() { *m = LsNodeFlags{} } +func (m *LsNodeFlags) String() string { return proto.CompactTextString(m) } +func (*LsNodeFlags) ProtoMessage() {} +func (*LsNodeFlags) Descriptor() ([]byte, []int) { return fileDescriptor1, []int{79} } + +func (m *LsNodeFlags) GetOverload() bool { + if m != nil { + return m.Overload + } + return false +} + +func (m *LsNodeFlags) GetAttached() bool { + if m != nil { + return m.Attached + } + return false +} + +func (m *LsNodeFlags) GetExternal() bool { + if m != nil { + return m.External + } + return false +} + +func (m *LsNodeFlags) GetAbr() bool { + if m != nil { + return m.Abr + } + return false +} + +func (m *LsNodeFlags) GetRouter() bool { + if m != nil { + return m.Router + } + return false +} + +func (m *LsNodeFlags) GetV6() bool { + if m != nil { + return m.V6 + } + return false +} + +type LsIGPFlags struct { + Down bool `protobuf:"varint,1,opt,name=down" json:"down,omitempty"` + NoUnicast bool `protobuf:"varint,2,opt,name=no_unicast,json=noUnicast" json:"no_unicast,omitempty"` + LocalAddress bool `protobuf:"varint,3,opt,name=local_address,json=localAddress" json:"local_address,omitempty"` + PropagateNssa bool `protobuf:"varint,4,opt,name=propagate_nssa,json=propagateNssa" json:"propagate_nssa,omitempty"` +} + +func (m *LsIGPFlags) Reset() { *m = LsIGPFlags{} } +func (m *LsIGPFlags) String() string { return proto.CompactTextString(m) } +func (*LsIGPFlags) ProtoMessage() {} +func (*LsIGPFlags) Descriptor() ([]byte, []int) { return fileDescriptor1, []int{80} } + +func (m *LsIGPFlags) GetDown() bool { + if m != nil { + return m.Down + } + return false +} + +func (m *LsIGPFlags) GetNoUnicast() bool { + if m != nil { + return m.NoUnicast + } + return false +} + +func (m *LsIGPFlags) GetLocalAddress() bool { + if m != nil { + return m.LocalAddress + } + return false +} + +func (m *LsIGPFlags) GetPropagateNssa() bool { + if m != nil { + return m.PropagateNssa + } + return false +} + +type LsSrRange struct { + Begin uint32 `protobuf:"varint,1,opt,name=begin" json:"begin,omitempty"` + End uint32 `protobuf:"varint,2,opt,name=end" json:"end,omitempty"` +} + +func (m *LsSrRange) Reset() { *m = LsSrRange{} } +func (m *LsSrRange) String() string { return proto.CompactTextString(m) } +func (*LsSrRange) ProtoMessage() {} +func (*LsSrRange) Descriptor() ([]byte, []int) { return fileDescriptor1, []int{81} } + +func (m *LsSrRange) GetBegin() uint32 { + if m != nil { + return m.Begin + } + return 0 +} + +func (m *LsSrRange) GetEnd() uint32 { + if m != nil { + return m.End + } + return 0 +} + +type LsSrCapabilities struct { + Ipv4Supported bool `protobuf:"varint,1,opt,name=ipv4_supported,json=ipv4Supported" json:"ipv4_supported,omitempty"` + Ipv6Supported bool `protobuf:"varint,2,opt,name=ipv6_supported,json=ipv6Supported" json:"ipv6_supported,omitempty"` + Ranges []*LsSrRange `protobuf:"bytes,3,rep,name=ranges" json:"ranges,omitempty"` +} + +func (m *LsSrCapabilities) Reset() { *m = LsSrCapabilities{} } +func (m *LsSrCapabilities) String() string { return proto.CompactTextString(m) } +func (*LsSrCapabilities) ProtoMessage() {} +func (*LsSrCapabilities) Descriptor() ([]byte, []int) { return fileDescriptor1, []int{82} } + +func (m *LsSrCapabilities) GetIpv4Supported() bool { + if m != nil { + return m.Ipv4Supported + } + return false +} + +func (m *LsSrCapabilities) GetIpv6Supported() bool { + if m != nil { + return m.Ipv6Supported + } + return false +} + +func (m *LsSrCapabilities) GetRanges() []*LsSrRange { + if m != nil { + return m.Ranges + } + return nil +} + +type LsSrLocalBlock struct { + Ranges []*LsSrRange `protobuf:"bytes,1,rep,name=ranges" json:"ranges,omitempty"` +} + +func (m *LsSrLocalBlock) Reset() { *m = LsSrLocalBlock{} } +func (m *LsSrLocalBlock) String() string { return proto.CompactTextString(m) } +func (*LsSrLocalBlock) ProtoMessage() {} +func (*LsSrLocalBlock) Descriptor() ([]byte, []int) { return fileDescriptor1, []int{83} } + +func (m *LsSrLocalBlock) GetRanges() []*LsSrRange { + if m != nil { + return m.Ranges + } + return nil +} + +type LsAttributeNode struct { + Name string `protobuf:"bytes,1,opt,name=name" json:"name,omitempty"` + Flags *LsNodeFlags `protobuf:"bytes,2,opt,name=flags" json:"flags,omitempty"` + LocalRouterId string `protobuf:"bytes,3,opt,name=local_router_id,json=localRouterId" json:"local_router_id,omitempty"` + LocalRouterIdV6 string `protobuf:"bytes,4,opt,name=local_router_id_v6,json=localRouterIdV6" json:"local_router_id_v6,omitempty"` + IsisArea []byte `protobuf:"bytes,5,opt,name=isis_area,json=isisArea,proto3" json:"isis_area,omitempty"` + Opaque []byte `protobuf:"bytes,6,opt,name=opaque,proto3" json:"opaque,omitempty"` + SrCapabilities *LsSrCapabilities `protobuf:"bytes,7,opt,name=sr_capabilities,json=srCapabilities" json:"sr_capabilities,omitempty"` + SrAlgorithms []byte `protobuf:"bytes,8,opt,name=sr_algorithms,json=srAlgorithms,proto3" json:"sr_algorithms,omitempty"` + SrLocalBlock *LsSrLocalBlock `protobuf:"bytes,9,opt,name=sr_local_block,json=srLocalBlock" json:"sr_local_block,omitempty"` +} + +func (m *LsAttributeNode) Reset() { *m = LsAttributeNode{} } +func (m *LsAttributeNode) String() string { return proto.CompactTextString(m) } +func (*LsAttributeNode) ProtoMessage() {} +func (*LsAttributeNode) Descriptor() ([]byte, []int) { return fileDescriptor1, []int{84} } + +func (m *LsAttributeNode) GetName() string { + if m != nil { + return m.Name + } + return "" +} + +func (m *LsAttributeNode) GetFlags() *LsNodeFlags { + if m != nil { + return m.Flags + } + return nil +} + +func (m *LsAttributeNode) GetLocalRouterId() string { + if m != nil { + return m.LocalRouterId + } + return "" +} + +func (m *LsAttributeNode) GetLocalRouterIdV6() string { + if m != nil { + return m.LocalRouterIdV6 + } + return "" +} + +func (m *LsAttributeNode) GetIsisArea() []byte { + if m != nil { + return m.IsisArea + } + return nil +} + +func (m *LsAttributeNode) GetOpaque() []byte { + if m != nil { + return m.Opaque + } + return nil +} + +func (m *LsAttributeNode) GetSrCapabilities() *LsSrCapabilities { + if m != nil { + return m.SrCapabilities + } + return nil +} + +func (m *LsAttributeNode) GetSrAlgorithms() []byte { + if m != nil { + return m.SrAlgorithms + } + return nil +} + +func (m *LsAttributeNode) GetSrLocalBlock() *LsSrLocalBlock { + if m != nil { + return m.SrLocalBlock + } + return nil +} + +type LsAttributeLink struct { + Name string `protobuf:"bytes,1,opt,name=name" json:"name,omitempty"` + LocalRouterId string `protobuf:"bytes,2,opt,name=local_router_id,json=localRouterId" json:"local_router_id,omitempty"` + LocalRouterIdV6 string `protobuf:"bytes,3,opt,name=local_router_id_v6,json=localRouterIdV6" json:"local_router_id_v6,omitempty"` + RemoteRouterId string `protobuf:"bytes,4,opt,name=remote_router_id,json=remoteRouterId" json:"remote_router_id,omitempty"` + RemoteRouterIdV6 string `protobuf:"bytes,5,opt,name=remote_router_id_v6,json=remoteRouterIdV6" json:"remote_router_id_v6,omitempty"` + AdminGroup uint32 `protobuf:"varint,6,opt,name=admin_group,json=adminGroup" json:"admin_group,omitempty"` + DefaultTeMetric uint32 `protobuf:"varint,7,opt,name=default_te_metric,json=defaultTeMetric" json:"default_te_metric,omitempty"` + IgpMetric uint32 `protobuf:"varint,8,opt,name=igp_metric,json=igpMetric" json:"igp_metric,omitempty"` + Opaque []byte `protobuf:"bytes,9,opt,name=opaque,proto3" json:"opaque,omitempty"` + Bandwidth float32 `protobuf:"fixed32,10,opt,name=bandwidth" json:"bandwidth,omitempty"` + ReservableBandwidth float32 `protobuf:"fixed32,11,opt,name=reservable_bandwidth,json=reservableBandwidth" json:"reservable_bandwidth,omitempty"` + UnreservedBandwidth []float32 `protobuf:"fixed32,12,rep,packed,name=unreserved_bandwidth,json=unreservedBandwidth" json:"unreserved_bandwidth,omitempty"` + SrAdjacencySid uint32 `protobuf:"varint,13,opt,name=sr_adjacency_sid,json=srAdjacencySid" json:"sr_adjacency_sid,omitempty"` +} + +func (m *LsAttributeLink) Reset() { *m = LsAttributeLink{} } +func (m *LsAttributeLink) String() string { return proto.CompactTextString(m) } +func (*LsAttributeLink) ProtoMessage() {} +func (*LsAttributeLink) Descriptor() ([]byte, []int) { return fileDescriptor1, []int{85} } + +func (m *LsAttributeLink) GetName() string { + if m != nil { + return m.Name + } + return "" +} + +func (m *LsAttributeLink) GetLocalRouterId() string { + if m != nil { + return m.LocalRouterId + } + return "" +} + +func (m *LsAttributeLink) GetLocalRouterIdV6() string { + if m != nil { + return m.LocalRouterIdV6 + } + return "" +} + +func (m *LsAttributeLink) GetRemoteRouterId() string { + if m != nil { + return m.RemoteRouterId + } + return "" +} + +func (m *LsAttributeLink) GetRemoteRouterIdV6() string { + if m != nil { + return m.RemoteRouterIdV6 + } + return "" +} + +func (m *LsAttributeLink) GetAdminGroup() uint32 { + if m != nil { + return m.AdminGroup + } + return 0 +} + +func (m *LsAttributeLink) GetDefaultTeMetric() uint32 { + if m != nil { + return m.DefaultTeMetric + } + return 0 +} + +func (m *LsAttributeLink) GetIgpMetric() uint32 { + if m != nil { + return m.IgpMetric + } + return 0 +} + +func (m *LsAttributeLink) GetOpaque() []byte { + if m != nil { + return m.Opaque + } + return nil +} + +func (m *LsAttributeLink) GetBandwidth() float32 { + if m != nil { + return m.Bandwidth + } + return 0 +} + +func (m *LsAttributeLink) GetReservableBandwidth() float32 { + if m != nil { + return m.ReservableBandwidth + } + return 0 +} + +func (m *LsAttributeLink) GetUnreservedBandwidth() []float32 { + if m != nil { + return m.UnreservedBandwidth + } + return nil +} + +func (m *LsAttributeLink) GetSrAdjacencySid() uint32 { + if m != nil { + return m.SrAdjacencySid + } + return 0 +} + +type LsAttributePrefix struct { + IgpFlags *LsIGPFlags `protobuf:"bytes,1,opt,name=igp_flags,json=igpFlags" json:"igp_flags,omitempty"` + Opaque []byte `protobuf:"bytes,2,opt,name=opaque,proto3" json:"opaque,omitempty"` + SrPrefixSid uint32 `protobuf:"varint,3,opt,name=sr_prefix_sid,json=srPrefixSid" json:"sr_prefix_sid,omitempty"` +} + +func (m *LsAttributePrefix) Reset() { *m = LsAttributePrefix{} } +func (m *LsAttributePrefix) String() string { return proto.CompactTextString(m) } +func (*LsAttributePrefix) ProtoMessage() {} +func (*LsAttributePrefix) Descriptor() ([]byte, []int) { return fileDescriptor1, []int{86} } + +func (m *LsAttributePrefix) GetIgpFlags() *LsIGPFlags { + if m != nil { + return m.IgpFlags + } + return nil +} + +func (m *LsAttributePrefix) GetOpaque() []byte { + if m != nil { + return m.Opaque + } + return nil +} + +func (m *LsAttributePrefix) GetSrPrefixSid() uint32 { + if m != nil { + return m.SrPrefixSid + } + return 0 +} + +type LsAttribute struct { + Node *LsAttributeNode `protobuf:"bytes,1,opt,name=node" json:"node,omitempty"` + Link *LsAttributeLink `protobuf:"bytes,2,opt,name=link" json:"link,omitempty"` + Prefix *LsAttributePrefix `protobuf:"bytes,3,opt,name=prefix" json:"prefix,omitempty"` +} + +func (m *LsAttribute) Reset() { *m = LsAttribute{} } +func (m *LsAttribute) String() string { return proto.CompactTextString(m) } +func (*LsAttribute) ProtoMessage() {} +func (*LsAttribute) Descriptor() ([]byte, []int) { return fileDescriptor1, []int{87} } + +func (m *LsAttribute) GetNode() *LsAttributeNode { + if m != nil { + return m.Node + } + return nil +} + +func (m *LsAttribute) GetLink() *LsAttributeLink { + if m != nil { + return m.Link + } + return nil +} + +func (m *LsAttribute) GetPrefix() *LsAttributePrefix { + if m != nil { + return m.Prefix + } + return nil +} + type UnknownAttribute struct { Flags uint32 `protobuf:"varint,1,opt,name=flags" json:"flags,omitempty"` Type uint32 `protobuf:"varint,2,opt,name=type" json:"type,omitempty"` @@ -1865,7 +2575,7 @@ type UnknownAttribute struct { func (m *UnknownAttribute) Reset() { *m = UnknownAttribute{} } func (m *UnknownAttribute) String() string { return proto.CompactTextString(m) } func (*UnknownAttribute) ProtoMessage() {} -func (*UnknownAttribute) Descriptor() ([]byte, []int) { return fileDescriptor1, []int{71} } +func (*UnknownAttribute) Descriptor() ([]byte, []int) { return fileDescriptor1, []int{88} } func (m *UnknownAttribute) GetFlags() uint32 { if m != nil { @@ -1921,6 +2631,14 @@ func init() { proto.RegisterType((*FlowSpecNLRI)(nil), "gobgpapi.FlowSpecNLRI") proto.RegisterType((*VPNFlowSpecNLRI)(nil), "gobgpapi.VPNFlowSpecNLRI") proto.RegisterType((*OpaqueNLRI)(nil), "gobgpapi.OpaqueNLRI") + proto.RegisterType((*LsNodeDescriptor)(nil), "gobgpapi.LsNodeDescriptor") + proto.RegisterType((*LsLinkDescriptor)(nil), "gobgpapi.LsLinkDescriptor") + proto.RegisterType((*LsPrefixDescriptor)(nil), "gobgpapi.LsPrefixDescriptor") + proto.RegisterType((*LsNodeNLRI)(nil), "gobgpapi.LsNodeNLRI") + proto.RegisterType((*LsLinkNLRI)(nil), "gobgpapi.LsLinkNLRI") + proto.RegisterType((*LsPrefixV4NLRI)(nil), "gobgpapi.LsPrefixV4NLRI") + proto.RegisterType((*LsPrefixV6NLRI)(nil), "gobgpapi.LsPrefixV6NLRI") + proto.RegisterType((*LsAddrPrefix)(nil), "gobgpapi.LsAddrPrefix") proto.RegisterType((*MpReachNLRIAttribute)(nil), "gobgpapi.MpReachNLRIAttribute") proto.RegisterType((*MpUnreachNLRIAttribute)(nil), "gobgpapi.MpUnreachNLRIAttribute") proto.RegisterType((*TwoOctetAsSpecificExtended)(nil), "gobgpapi.TwoOctetAsSpecificExtended") @@ -1960,129 +2678,210 @@ func init() { proto.RegisterType((*AigpAttribute)(nil), "gobgpapi.AigpAttribute") proto.RegisterType((*LargeCommunity)(nil), "gobgpapi.LargeCommunity") proto.RegisterType((*LargeCommunitiesAttribute)(nil), "gobgpapi.LargeCommunitiesAttribute") + proto.RegisterType((*LsNodeFlags)(nil), "gobgpapi.LsNodeFlags") + proto.RegisterType((*LsIGPFlags)(nil), "gobgpapi.LsIGPFlags") + proto.RegisterType((*LsSrRange)(nil), "gobgpapi.LsSrRange") + proto.RegisterType((*LsSrCapabilities)(nil), "gobgpapi.LsSrCapabilities") + proto.RegisterType((*LsSrLocalBlock)(nil), "gobgpapi.LsSrLocalBlock") + proto.RegisterType((*LsAttributeNode)(nil), "gobgpapi.LsAttributeNode") + proto.RegisterType((*LsAttributeLink)(nil), "gobgpapi.LsAttributeLink") + proto.RegisterType((*LsAttributePrefix)(nil), "gobgpapi.LsAttributePrefix") + proto.RegisterType((*LsAttribute)(nil), "gobgpapi.LsAttribute") proto.RegisterType((*UnknownAttribute)(nil), "gobgpapi.UnknownAttribute") + proto.RegisterEnum("gobgpapi.LsNLRIType", LsNLRIType_name, LsNLRIType_value) } func init() { proto.RegisterFile("attribute.proto", fileDescriptor1) } var fileDescriptor1 = []byte{ - // 1881 bytes of a gzipped FileDescriptorProto - 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xcc, 0x58, 0x4b, 0x73, 0x1b, 0xc7, - 0x11, 0x2e, 0x2c, 0x40, 0x0a, 0x68, 0x10, 0x24, 0x04, 0x52, 0x2c, 0x90, 0xb4, 0x4c, 0x65, 0x14, - 0x27, 0x8c, 0x12, 0x53, 0x09, 0x2d, 0x2b, 0x91, 0x5c, 0xa9, 0x14, 0x4c, 0xd2, 0x36, 0x62, 0x82, - 0x82, 0x97, 0x14, 0x53, 0xb9, 0x04, 0x19, 0xec, 0x0e, 0x96, 0x53, 0xdc, 0x97, 0x77, 0x66, 0xf9, - 0xf8, 0x09, 0x3e, 0x24, 0xa5, 0x53, 0x2a, 0xbf, 0x24, 0xff, 0x2c, 0xf7, 0xd4, 0xbc, 0xf6, 0x41, - 0xf0, 0x21, 0x4a, 0x51, 0x95, 0x6e, 0xdb, 0xb3, 0x3d, 0xdd, 0x3d, 0xdf, 0x74, 0x7f, 0xdd, 0xbb, - 0xb0, 0x80, 0x39, 0x4f, 0xe8, 0x38, 0xe5, 0x64, 0x33, 0x4e, 0x22, 0x1e, 0x75, 0xea, 0x5e, 0x34, - 0xf6, 0x62, 0x1c, 0xd3, 0xd5, 0x15, 0x2f, 0x8a, 0x3c, 0x9f, 0x3c, 0x95, 0xeb, 0xe3, 0x74, 0xf2, - 0x14, 0x87, 0x17, 0x4a, 0x69, 0xb5, 0x29, 0x95, 0x94, 0x80, 0x7e, 0x05, 0x0b, 0xaf, 0x12, 0xea, - 0xd1, 0xb0, 0x67, 0x4c, 0x75, 0x96, 0x61, 0x36, 0x92, 0x4b, 0xdd, 0xca, 0xa3, 0xca, 0x46, 0xcb, - 0xd6, 0x12, 0x7a, 0x01, 0x8d, 0x1e, 0x3b, 0x20, 0x5e, 0x40, 0x42, 0xde, 0xe9, 0x40, 0x8d, 0x5f, - 0xc4, 0x44, 0xab, 0xc8, 0xe7, 0x4e, 0x17, 0xee, 0x85, 0x69, 0x30, 0x26, 0x09, 0xeb, 0x5a, 0x8f, - 0xaa, 0x1b, 0x2d, 0xdb, 0x88, 0xe8, 0x6b, 0x58, 0xe8, 0xb1, 0x21, 0xe6, 0xc7, 0xb9, 0x97, 0xa7, - 0x50, 0x67, 0xca, 0x16, 0xeb, 0x56, 0x1e, 0x55, 0x37, 0x9a, 0x5b, 0x8b, 0x9b, 0x26, 0xfa, 0xcd, - 0xcc, 0x8f, 0x9d, 0x29, 0xa1, 0xcf, 0xa1, 0xbd, 0x4f, 0xce, 0xf9, 0x77, 0x51, 0x9c, 0x1b, 0x59, - 0x81, 0x7a, 0x48, 0xce, 0xf9, 0xe8, 0x38, 0x8a, 0x65, 0x24, 0x0d, 0xfb, 0x5e, 0xa8, 0x74, 0xd0, - 0x13, 0x58, 0x1e, 0xa4, 0x3e, 0xa7, 0xbb, 0xe7, 0x94, 0xef, 0x50, 0xe6, 0xe4, 0x9b, 0xda, 0x50, - 0x0d, 0x88, 0xab, 0x23, 0x17, 0x8f, 0xe8, 0x0b, 0xe8, 0xec, 0x45, 0x0e, 0xf6, 0x87, 0x09, 0x99, - 0xe4, 0x7a, 0x0f, 0x01, 0x7c, 0xb1, 0x3a, 0x8a, 0x13, 0x32, 0xd1, 0xea, 0x0d, 0xdf, 0xe8, 0xa1, - 0x55, 0xe8, 0xf6, 0x78, 0x14, 0x50, 0xa7, 0xe7, 0x79, 0x09, 0xf1, 0x30, 0x27, 0xd9, 0x56, 0xf4, - 0x27, 0x58, 0x34, 0xab, 0x51, 0x92, 0x5b, 0x9c, 0x07, 0x0b, 0x0b, 0x6c, 0x84, 0x25, 0x0b, 0x33, - 0x01, 0x18, 0x76, 0xdd, 0x84, 0x30, 0xd6, 0xad, 0xaa, 0xe8, 0xb5, 0x88, 0xfe, 0x00, 0x4b, 0xdb, - 0x51, 0x10, 0xa4, 0x21, 0xe5, 0x94, 0xb0, 0xdc, 0xc2, 0x23, 0x68, 0x3a, 0xf9, 0xba, 0x04, 0xae, - 0x65, 0x17, 0x97, 0xd0, 0x2f, 0xe1, 0x81, 0xba, 0x50, 0xe1, 0xba, 0xef, 0x96, 0x9c, 0x53, 0x57, - 0xa3, 0x64, 0x51, 0x17, 0x6d, 0xc0, 0xd2, 0xb6, 0x9f, 0x32, 0x4e, 0x92, 0x3d, 0xca, 0x78, 0x09, - 0x1e, 0xea, 0x2a, 0xd3, 0x0d, 0x5b, 0x3c, 0xa2, 0xef, 0x60, 0xa1, 0x3f, 0xec, 0xa9, 0xc8, 0xc4, - 0xd1, 0xe9, 0xb9, 0xc0, 0x26, 0x96, 0x4f, 0x23, 0x9f, 0x98, 0x3c, 0x69, 0xa8, 0x95, 0x3d, 0x12, - 0x8a, 0x14, 0x52, 0x82, 0x3c, 0x6c, 0xc3, 0xd6, 0x12, 0xf2, 0x60, 0x79, 0x0f, 0x8f, 0x89, 0x4f, - 0xdc, 0xcb, 0x06, 0x97, 0x61, 0xd6, 0x17, 0x6f, 0xcc, 0x99, 0xb4, 0x74, 0xc9, 0x91, 0x75, 0xbd, - 0xa3, 0x6a, 0xc9, 0xd1, 0xe7, 0x70, 0x7f, 0x37, 0x74, 0x70, 0xcc, 0x52, 0x1f, 0x73, 0x1a, 0x85, - 0xfb, 0x7b, 0x76, 0xbf, 0x08, 0x77, 0xa5, 0x0c, 0xf7, 0x10, 0x3e, 0xb1, 0xa3, 0x94, 0x93, 0x1d, - 0xca, 0x38, 0x0d, 0xbd, 0x94, 0xb2, 0x63, 0x92, 0x1c, 0x9e, 0x45, 0xaf, 0x1c, 0x4e, 0x78, 0xef, - 0xa0, 0xb3, 0x04, 0x33, 0xd8, 0x0d, 0xb2, 0x8a, 0x50, 0x42, 0x67, 0x15, 0xea, 0x98, 0x31, 0xea, - 0x85, 0xc4, 0xd5, 0x91, 0x65, 0x32, 0x7a, 0x05, 0x6b, 0xd3, 0x16, 0xb3, 0x43, 0x97, 0x0d, 0x36, - 0xde, 0xc6, 0xe0, 0x0f, 0xf0, 0x70, 0xda, 0xe0, 0x37, 0x51, 0x9a, 0xbc, 0x7b, 0x8c, 0xbb, 0xb0, - 0xb2, 0xcb, 0x8f, 0x49, 0x12, 0x12, 0xae, 0xcb, 0xad, 0xef, 0x92, 0x90, 0xd3, 0x09, 0x25, 0xc9, - 0x95, 0x05, 0xbe, 0x04, 0x33, 0xa7, 0xd8, 0x4f, 0x89, 0xb4, 0x34, 0x67, 0x2b, 0x01, 0xfd, 0xa7, - 0x02, 0x9f, 0xee, 0x1e, 0x0d, 0xf7, 0x8d, 0xad, 0x5e, 0xca, 0x23, 0x51, 0x71, 0xd1, 0x29, 0x49, - 0x2e, 0x64, 0xcc, 0x9d, 0x9f, 0x83, 0x95, 0xa8, 0xdc, 0x6b, 0x6e, 0x2d, 0x6d, 0x2a, 0x6a, 0xda, - 0x34, 0xd4, 0xb4, 0xd9, 0x0b, 0x2f, 0x6c, 0x2b, 0x71, 0x3b, 0x5f, 0x42, 0x95, 0x30, 0x2a, 0x8d, - 0x37, 0xb7, 0x1e, 0xe7, 0x6c, 0x70, 0x6d, 0x90, 0xb6, 0xd0, 0xef, 0xfc, 0x0c, 0xe6, 0x88, 0xd6, - 0x18, 0x71, 0xec, 0xc9, 0x4c, 0x68, 0xd9, 0x4d, 0xb3, 0x76, 0x88, 0x3d, 0x11, 0xb8, 0xcc, 0xa7, - 0x6e, 0x4d, 0x61, 0x23, 0x05, 0xf4, 0xdf, 0x0a, 0xac, 0x89, 0xc0, 0x07, 0xbd, 0x6d, 0x71, 0x33, - 0xa7, 0x24, 0xe1, 0x94, 0x11, 0x49, 0x3b, 0x1f, 0x45, 0xd4, 0xeb, 0xd0, 0x0c, 0xb0, 0x33, 0x32, - 0x39, 0x5b, 0x93, 0xa9, 0x02, 0x01, 0x76, 0x4c, 0x16, 0x3d, 0x04, 0xa0, 0x71, 0xf6, 0x7e, 0x46, - 0xbe, 0x6f, 0xd0, 0xd8, 0xbc, 0xce, 0x6b, 0x6a, 0xb6, 0x58, 0x53, 0xe8, 0x4d, 0x05, 0x7e, 0x21, - 0xce, 0xdd, 0x0f, 0x1d, 0x3f, 0x65, 0xf4, 0x94, 0x48, 0xa2, 0x74, 0x30, 0xe3, 0xbb, 0xb9, 0xf7, - 0xbb, 0x40, 0x70, 0xf9, 0x2c, 0xd6, 0xf4, 0x59, 0xca, 0xa1, 0x56, 0x2f, 0x85, 0x8a, 0xfe, 0x55, - 0x81, 0x6e, 0x31, 0x87, 0x0c, 0xfd, 0x7f, 0xf8, 0x7b, 0xb8, 0x25, 0xb0, 0x9f, 0x2c, 0xb8, 0x2f, - 0xb1, 0x1a, 0x2a, 0xa2, 0xfa, 0x38, 0x32, 0x63, 0x0d, 0x1a, 0x34, 0x1e, 0x69, 0xe6, 0x53, 0x79, - 0x51, 0xa7, 0xb1, 0xa6, 0x52, 0x04, 0xad, 0xec, 0xa5, 0x64, 0xcd, 0x19, 0x65, 0xc0, 0x28, 0x08, - 0xde, 0x7c, 0x08, 0xe0, 0x9d, 0x65, 0xa7, 0x9e, 0x55, 0xa7, 0xf6, 0xce, 0x0a, 0xf4, 0xa4, 0xea, - 0xe5, 0x5e, 0xb1, 0x5e, 0xde, 0x54, 0x60, 0x45, 0xd3, 0xb7, 0x44, 0xe4, 0xed, 0x18, 0x5c, 0x61, - 0x65, 0xdd, 0x82, 0x55, 0x99, 0xe7, 0xab, 0xd7, 0xf3, 0x7c, 0xad, 0xc4, 0xf3, 0x3f, 0xc0, 0x8a, - 0xbc, 0x91, 0x43, 0x9c, 0x78, 0x84, 0x0f, 0x88, 0x1c, 0x37, 0x8e, 0x69, 0x2c, 0xf9, 0x5e, 0xb5, - 0xdb, 0x4a, 0xd6, 0x6e, 0x45, 0x24, 0xfc, 0x96, 0x48, 0x38, 0x4a, 0xa1, 0xfd, 0x8d, 0x1f, 0x9d, - 0x1d, 0xc4, 0xc4, 0x31, 0x97, 0x7e, 0x25, 0x19, 0xbe, 0x5b, 0x67, 0x92, 0xd3, 0xd5, 0x64, 0xc2, - 0x08, 0xd7, 0x5c, 0xa4, 0x25, 0xf4, 0x15, 0x34, 0x8d, 0xdb, 0x41, 0x6f, 0xfb, 0xba, 0xf9, 0xca, - 0xdc, 0x98, 0x55, 0xee, 0x5f, 0x7f, 0x84, 0x07, 0x66, 0xf3, 0x76, 0x14, 0xc4, 0x51, 0x28, 0xd2, - 0x8a, 0x93, 0x40, 0x40, 0xa0, 0x47, 0xa3, 0x96, 0x6d, 0x45, 0x71, 0x99, 0xc1, 0x6b, 0x86, 0xc1, - 0xff, 0x06, 0xf7, 0xa7, 0xb6, 0x5f, 0x19, 0xc1, 0x97, 0x30, 0x43, 0x39, 0x09, 0xd4, 0x7c, 0xd7, - 0xdc, 0x5a, 0xcf, 0x73, 0xfa, 0x4a, 0xf7, 0xb6, 0xd2, 0x46, 0x2f, 0x61, 0xce, 0xbc, 0x97, 0x17, - 0xf3, 0x04, 0x66, 0x92, 0xd4, 0x27, 0x66, 0xf0, 0xbb, 0xfa, 0x2e, 0x94, 0x0a, 0x72, 0x60, 0xe1, - 0x68, 0xb8, 0x5f, 0xda, 0xfe, 0x76, 0xd5, 0x97, 0x39, 0xb1, 0x6e, 0x77, 0xf2, 0x0c, 0xe0, 0x55, - 0x8c, 0x7f, 0x4c, 0x89, 0xb4, 0xdf, 0x86, 0xea, 0x09, 0xb9, 0x90, 0x0e, 0xe6, 0x6c, 0xf1, 0x78, - 0x4d, 0xe3, 0xfb, 0xa9, 0x02, 0x4b, 0x83, 0xd8, 0x26, 0xd8, 0x39, 0x16, 0xfb, 0xf2, 0x11, 0x6a, - 0x03, 0x66, 0x27, 0x38, 0xa0, 0xfe, 0x85, 0x0e, 0xb2, 0x5d, 0xc0, 0x49, 0xae, 0xdb, 0xfa, 0xbd, - 0x28, 0x64, 0x33, 0xc0, 0xaa, 0x40, 0x1b, 0x76, 0x5d, 0x4f, 0xb0, 0x4c, 0x9c, 0x20, 0xf4, 0x13, - 0x2a, 0x58, 0xe9, 0x86, 0x13, 0x48, 0x15, 0x14, 0xc2, 0xf2, 0x20, 0x7e, 0x1d, 0x26, 0xef, 0x13, - 0xcc, 0x5d, 0xfc, 0xfd, 0xa3, 0x02, 0xab, 0xd9, 0x80, 0xc4, 0xc4, 0xd5, 0xd0, 0x09, 0x75, 0x76, - 0xcf, 0x39, 0x09, 0x5d, 0xe2, 0x76, 0x1e, 0x43, 0x8b, 0xb2, 0x11, 0x4f, 0x70, 0xc8, 0x28, 0xa7, - 0xa7, 0x2a, 0x8b, 0xea, 0xf6, 0x1c, 0x65, 0x87, 0xd9, 0x9a, 0x98, 0xde, 0x59, 0x3a, 0x1e, 0xc9, - 0x2c, 0x53, 0xf5, 0x73, 0x8f, 0xa5, 0xe3, 0x43, 0x91, 0x68, 0xaa, 0x74, 0xab, 0x59, 0xe9, 0xae, - 0x43, 0x53, 0xcd, 0xe2, 0x6a, 0xc4, 0x51, 0xa5, 0xa3, 0xc6, 0xf3, 0x9e, 0x58, 0x41, 0xff, 0xae, - 0xc0, 0x5a, 0x7f, 0x78, 0xfa, 0x4c, 0x73, 0xd2, 0xff, 0x3d, 0xa0, 0x6b, 0x47, 0xf5, 0xdb, 0x43, - 0xfb, 0x67, 0x05, 0xd6, 0xf2, 0x41, 0xed, 0x23, 0xc0, 0xea, 0x09, 0x74, 0x8e, 0xb0, 0x4f, 0x5d, - 0x39, 0x19, 0x67, 0x61, 0x2c, 0xc1, 0x0c, 0xe3, 0x98, 0x9b, 0x82, 0x57, 0x02, 0xfa, 0x0c, 0x5a, - 0xdb, 0x91, 0x1f, 0x25, 0x45, 0x35, 0x47, 0x2c, 0x18, 0x35, 0x29, 0xa0, 0xdf, 0x42, 0x4b, 0xce, - 0xdb, 0x99, 0xda, 0x3a, 0x34, 0x79, 0x1a, 0x86, 0xc4, 0x1f, 0x15, 0x48, 0x04, 0xd4, 0x92, 0x88, - 0x1a, 0x75, 0x61, 0x79, 0x87, 0x4c, 0x70, 0xea, 0xf3, 0x6f, 0x31, 0x27, 0x67, 0xf8, 0xc2, 0x6c, - 0x45, 0xdf, 0xc3, 0xbc, 0x2a, 0xc6, 0xbb, 0x21, 0x94, 0xd5, 0x68, 0xb5, 0x58, 0xa3, 0x36, 0xb4, - 0x77, 0x0f, 0xfa, 0xb2, 0x6b, 0x65, 0xe6, 0x36, 0xa0, 0x4d, 0xd9, 0x88, 0xd1, 0xd0, 0xf3, 0xc9, - 0x08, 0x3b, 0x05, 0x8b, 0xf3, 0x94, 0x1d, 0xc8, 0xe5, 0x9e, 0x63, 0x6c, 0xaa, 0x3e, 0x68, 0x15, - 0xfb, 0xe0, 0x16, 0x2c, 0xee, 0x1e, 0xf4, 0x83, 0x38, 0x4a, 0x78, 0xa1, 0xf9, 0x88, 0x5a, 0x26, - 0x6c, 0x44, 0xe5, 0xba, 0x9e, 0xeb, 0xeb, 0x84, 0x29, 0x3d, 0xf4, 0x1a, 0x16, 0x07, 0xd8, 0x19, - 0x44, 0x63, 0xea, 0x53, 0x9e, 0x9d, 0x55, 0x36, 0x72, 0x36, 0x62, 0x9c, 0x3a, 0x27, 0x17, 0x3a, - 0x86, 0x3a, 0x65, 0x07, 0x52, 0x16, 0x83, 0x00, 0x23, 0x3f, 0xa6, 0x24, 0x74, 0xc8, 0x28, 0x4c, - 0x03, 0x33, 0x56, 0x99, 0xb5, 0xfd, 0x34, 0x40, 0x9f, 0xc1, 0x7d, 0x19, 0x42, 0x32, 0xc0, 0x79, - 0x42, 0x89, 0x0f, 0x5c, 0xec, 0xe8, 0x10, 0xc4, 0x23, 0x7a, 0x01, 0x8b, 0x87, 0x09, 0x9e, 0x4c, - 0xa8, 0x63, 0x63, 0x9e, 0xe3, 0x7a, 0xb9, 0x41, 0x76, 0xa0, 0x96, 0x88, 0x0c, 0x10, 0x8e, 0x2c, - 0x5b, 0x3e, 0xa3, 0xef, 0xe1, 0x81, 0xde, 0x2a, 0x30, 0x29, 0xe4, 0xcb, 0x2a, 0xd4, 0x39, 0x49, - 0x02, 0x1a, 0x62, 0xdf, 0x44, 0x6e, 0x64, 0xd1, 0xe4, 0x18, 0x0e, 0x62, 0x5f, 0x99, 0xaa, 0xdb, - 0x5a, 0x42, 0xaf, 0x01, 0xd9, 0xc4, 0xa5, 0x09, 0x71, 0xf8, 0x0d, 0xe4, 0x71, 0x39, 0xac, 0x4b, - 0x09, 0x6d, 0x4d, 0x25, 0xf4, 0xdf, 0xe1, 0xb1, 0x31, 0x7b, 0x13, 0x07, 0x5c, 0xfb, 0xfd, 0x77, - 0xbb, 0x87, 0xa3, 0xdc, 0xc3, 0x4d, 0xa5, 0x7c, 0xe7, 0xc8, 0x7f, 0x9d, 0xa1, 0x6b, 0x93, 0x00, - 0x27, 0x27, 0x99, 0xa5, 0x0e, 0xd4, 0x5c, 0xe6, 0x98, 0xd6, 0x2d, 0x9f, 0xd1, 0x57, 0xb0, 0xf0, - 0x3a, 0x3c, 0x09, 0xa3, 0xb3, 0xb0, 0xa8, 0xf6, 0x96, 0x5f, 0x69, 0x47, 0xf0, 0x89, 0xd9, 0x75, - 0xe5, 0x9f, 0x85, 0xe7, 0xd3, 0x7f, 0x16, 0xae, 0x6b, 0x01, 0xa5, 0xff, 0x0d, 0xdb, 0xd0, 0xee, - 0xb1, 0x67, 0xef, 0xf9, 0x6f, 0xe7, 0x6b, 0x58, 0xee, 0xb1, 0x67, 0xef, 0xf7, 0xcb, 0x84, 0xc0, - 0xe2, 0x30, 0x60, 0xf4, 0x50, 0x52, 0x4c, 0x6e, 0x60, 0x09, 0x66, 0x26, 0x3e, 0xf6, 0xcc, 0xad, - 0x28, 0x21, 0xc3, 0xcd, 0x2a, 0xe3, 0xa6, 0x8a, 0xbd, 0x5a, 0x28, 0x76, 0xfd, 0xdb, 0xa4, 0x26, - 0xa1, 0xb4, 0xa8, 0x8b, 0xfe, 0x0c, 0x9f, 0x2a, 0x17, 0x92, 0xef, 0x0e, 0xd2, 0xf1, 0xe1, 0xde, - 0x51, 0xe9, 0x57, 0x43, 0x71, 0x7c, 0x68, 0xa9, 0xf1, 0x61, 0x19, 0x66, 0x9d, 0x28, 0x3a, 0xa1, - 0xe6, 0x4a, 0xb4, 0x84, 0x7e, 0x0f, 0x2b, 0x53, 0xb6, 0x86, 0x02, 0x69, 0x27, 0xf2, 0x45, 0x7d, - 0xc5, 0xfa, 0x59, 0xdb, 0xca, 0x64, 0xb4, 0x09, 0xcb, 0x53, 0x1b, 0x25, 0x4d, 0x5f, 0x43, 0xcf, - 0x3b, 0xd0, 0x9d, 0xd2, 0xd7, 0xa9, 0x74, 0x87, 0x14, 0xda, 0x87, 0xf9, 0x82, 0x95, 0xc3, 0xbd, - 0xa3, 0x2b, 0xf7, 0x6e, 0x40, 0x8d, 0xfb, 0xa7, 0x37, 0x8f, 0x5d, 0x52, 0x03, 0xed, 0xc0, 0x52, - 0xc1, 0x5e, 0x7e, 0x65, 0xbf, 0xd1, 0x16, 0x54, 0xea, 0x74, 0xf3, 0xd4, 0x29, 0x7b, 0xd7, 0x56, - 0x74, 0xe7, 0x7f, 0xfe, 0x11, 0x76, 0xfe, 0x32, 0x2f, 0x3d, 0xff, 0x00, 0xbc, 0xf4, 0x57, 0x58, - 0xef, 0x0f, 0x9f, 0x7f, 0x90, 0xc2, 0x7e, 0x02, 0xed, 0x1e, 0xf5, 0x04, 0xd0, 0xfd, 0x6f, 0x87, - 0x03, 0xc2, 0x13, 0xea, 0x88, 0x44, 0x0e, 0xe4, 0x93, 0x0c, 0xb4, 0x66, 0x6b, 0x09, 0xbd, 0x84, - 0x79, 0xad, 0x7b, 0xf7, 0xac, 0x7a, 0x01, 0x2d, 0xb1, 0xb7, 0x38, 0xb0, 0x16, 0xaf, 0xff, 0xa6, - 0x04, 0x4a, 0x61, 0x7e, 0x4f, 0xf4, 0x5e, 0x73, 0x6e, 0xd9, 0x32, 0x3d, 0x3f, 0x1a, 0x67, 0x88, - 0x29, 0xf7, 0x4d, 0xb5, 0x26, 0x21, 0xcb, 0x31, 0x75, 0x31, 0xc7, 0xbf, 0x2b, 0x61, 0xba, 0x23, - 0x56, 0xca, 0x0a, 0x5b, 0x9a, 0x0d, 0x72, 0x85, 0x2d, 0xf4, 0x17, 0xf1, 0x19, 0x5c, 0x70, 0x5b, - 0x82, 0xfb, 0xe5, 0x55, 0x70, 0x17, 0x72, 0xb8, 0x1c, 0x70, 0x19, 0x72, 0x1b, 0xda, 0x1a, 0xbf, - 0x77, 0xe4, 0xaf, 0xe9, 0x01, 0x68, 0x3c, 0x2b, 0x71, 0xfb, 0xe2, 0x7f, 0x01, 0x00, 0x00, 0xff, - 0xff, 0xc5, 0x72, 0x43, 0xec, 0x2c, 0x18, 0x00, 0x00, + // 3014 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xcc, 0x39, 0x4d, 0x73, 0x1b, 0xc7, + 0xb1, 0x0f, 0x00, 0x49, 0x01, 0x0d, 0x82, 0x00, 0x97, 0x14, 0x0b, 0xa4, 0x24, 0x4b, 0x6f, 0xe5, + 0x0f, 0x3e, 0xc9, 0xa2, 0x9f, 0x29, 0x1a, 0xef, 0xc9, 0x2e, 0x27, 0x05, 0x91, 0x94, 0x8c, 0x08, + 0xa4, 0xe8, 0x25, 0x45, 0x27, 0x97, 0x6c, 0x06, 0xbb, 0xc3, 0xe5, 0x84, 0x8b, 0xdd, 0xf5, 0xcc, + 0x80, 0x14, 0xaf, 0xa9, 0x4a, 0xaa, 0x5c, 0xa9, 0xa4, 0x7c, 0x4a, 0xb9, 0x2a, 0x97, 0x9c, 0xf2, + 0x13, 0xf2, 0x1f, 0xf2, 0x83, 0x72, 0x4f, 0xcd, 0xd7, 0x7e, 0x80, 0xa0, 0x28, 0x59, 0x71, 0x95, + 0x6e, 0xdb, 0x3d, 0x3d, 0x3d, 0x3d, 0xdd, 0x3d, 0xfd, 0xb5, 0xd0, 0x44, 0x9c, 0x53, 0x32, 0x18, + 0x71, 0xbc, 0x96, 0xd0, 0x98, 0xc7, 0x56, 0x35, 0x88, 0x07, 0x41, 0x82, 0x12, 0xb2, 0xb2, 0x1c, + 0xc4, 0x71, 0x10, 0xe2, 0x4f, 0x24, 0x7e, 0x30, 0x3a, 0xfa, 0x04, 0x45, 0xe7, 0x8a, 0x68, 0xa5, + 0x2e, 0x89, 0x14, 0x60, 0xff, 0x0f, 0x34, 0x9f, 0x53, 0x12, 0x90, 0xa8, 0x6b, 0x58, 0x59, 0x4b, + 0x30, 0x13, 0x4b, 0x54, 0xbb, 0x74, 0xa7, 0xb4, 0xda, 0x70, 0x34, 0x64, 0x3f, 0x82, 0x5a, 0x97, + 0xed, 0xe3, 0x60, 0x88, 0x23, 0x6e, 0x59, 0x30, 0xc5, 0xcf, 0x13, 0xac, 0x49, 0xe4, 0xb7, 0xd5, + 0x86, 0x6b, 0xd1, 0x68, 0x38, 0xc0, 0x94, 0xb5, 0xcb, 0x77, 0x2a, 0xab, 0x0d, 0xc7, 0x80, 0xf6, + 0x63, 0x68, 0x76, 0xd9, 0x1e, 0xe2, 0xc7, 0xd9, 0x29, 0x9f, 0x40, 0x95, 0x29, 0x5e, 0xac, 0x5d, + 0xba, 0x53, 0x59, 0xad, 0xaf, 0x2f, 0xac, 0x19, 0xe9, 0xd7, 0xd2, 0x73, 0x9c, 0x94, 0xc8, 0x7e, + 0x00, 0xad, 0x5d, 0xfc, 0x92, 0x7f, 0x15, 0x27, 0x19, 0x93, 0x65, 0xa8, 0x46, 0xf8, 0x25, 0x77, + 0x8f, 0xe3, 0x44, 0x4a, 0x52, 0x73, 0xae, 0x45, 0x8a, 0xc6, 0xbe, 0x07, 0x4b, 0x3b, 0xa3, 0x90, + 0x93, 0xed, 0x97, 0x84, 0x6f, 0x11, 0xe6, 0x65, 0x9b, 0x5a, 0x50, 0x19, 0x62, 0x5f, 0x4b, 0x2e, + 0x3e, 0xed, 0x87, 0x60, 0xf5, 0x63, 0x0f, 0x85, 0x7b, 0x14, 0x1f, 0x65, 0x74, 0xb7, 0x00, 0x42, + 0x81, 0x75, 0x13, 0x8a, 0x8f, 0x34, 0x79, 0x2d, 0x34, 0x74, 0xf6, 0x0a, 0xb4, 0xbb, 0x3c, 0x1e, + 0x12, 0xaf, 0x1b, 0x04, 0x14, 0x07, 0x88, 0xe3, 0x74, 0xab, 0xfd, 0x73, 0x58, 0x30, 0xd8, 0x98, + 0x66, 0x1c, 0xe7, 0xa0, 0x8c, 0x84, 0x6e, 0x04, 0xa7, 0x32, 0x62, 0x42, 0x61, 0xc8, 0xf7, 0x29, + 0x66, 0xac, 0x5d, 0x51, 0xd2, 0x6b, 0xd0, 0xfe, 0x7f, 0x58, 0xdc, 0x8c, 0x87, 0xc3, 0x51, 0x44, + 0x38, 0xc1, 0x2c, 0xe3, 0x70, 0x07, 0xea, 0x5e, 0x86, 0x97, 0x8a, 0x6b, 0x38, 0x79, 0x94, 0xfd, + 0x11, 0x5c, 0x57, 0x06, 0x15, 0x47, 0xf7, 0xfc, 0xc2, 0xe1, 0xc4, 0xd7, 0x5a, 0x2a, 0x13, 0xdf, + 0x5e, 0x85, 0xc5, 0xcd, 0x70, 0xc4, 0x38, 0xa6, 0x7d, 0xc2, 0x78, 0x41, 0x3d, 0xc4, 0x57, 0xac, + 0x6b, 0x8e, 0xf8, 0xb4, 0xbf, 0x82, 0x66, 0x6f, 0xaf, 0xab, 0x24, 0x13, 0x57, 0x27, 0x2f, 0x85, + 0x6e, 0x12, 0xf9, 0xe5, 0x86, 0xd8, 0xf8, 0x49, 0x4d, 0x61, 0xfa, 0x38, 0x12, 0x2e, 0xa4, 0x00, + 0x79, 0xd9, 0x9a, 0xa3, 0x21, 0x3b, 0x80, 0xa5, 0x3e, 0x1a, 0xe0, 0x10, 0xfb, 0xe3, 0x0c, 0x97, + 0x60, 0x26, 0x14, 0x2b, 0xe6, 0x4e, 0x1a, 0x1a, 0x3b, 0xa8, 0x7c, 0xf9, 0x41, 0x95, 0xc2, 0x41, + 0x0f, 0x60, 0x7e, 0x3b, 0xf2, 0x50, 0xc2, 0x46, 0x21, 0xe2, 0x24, 0x8e, 0x76, 0xfb, 0x4e, 0x2f, + 0xaf, 0xee, 0x52, 0x51, 0xdd, 0x7b, 0x70, 0xd3, 0x89, 0x47, 0x1c, 0x6f, 0x11, 0xc6, 0x49, 0x14, + 0x8c, 0x08, 0x3b, 0xc6, 0xf4, 0xe0, 0x2c, 0x7e, 0xee, 0x71, 0xcc, 0xbb, 0xfb, 0xd6, 0x22, 0x4c, + 0x23, 0x7f, 0x98, 0xbe, 0x08, 0x05, 0x58, 0x2b, 0x50, 0x45, 0x8c, 0x91, 0x20, 0xc2, 0xbe, 0x96, + 0x2c, 0x85, 0xed, 0xe7, 0x70, 0xe3, 0x22, 0xc7, 0xf4, 0xd2, 0x45, 0x86, 0xb5, 0xd7, 0x61, 0xf8, + 0x35, 0xdc, 0xba, 0xc8, 0xf0, 0x49, 0x3c, 0xa2, 0x3f, 0x5e, 0xc6, 0x6d, 0x58, 0xde, 0xe6, 0xc7, + 0x98, 0x46, 0x98, 0xeb, 0xe7, 0xd6, 0xf3, 0x71, 0xc4, 0xc9, 0x11, 0xc1, 0x74, 0xe2, 0x03, 0x5f, + 0x84, 0xe9, 0x53, 0x14, 0x8e, 0xb0, 0xe4, 0x34, 0xeb, 0x28, 0xc0, 0xfe, 0x47, 0x09, 0xde, 0xdb, + 0x3e, 0xdc, 0xdb, 0x35, 0xbc, 0xba, 0x23, 0x1e, 0x8b, 0x17, 0x17, 0x9f, 0x62, 0x7a, 0x2e, 0x65, + 0xb6, 0xde, 0x87, 0x32, 0x55, 0xbe, 0x57, 0x5f, 0x5f, 0x5c, 0x53, 0xa1, 0x69, 0xcd, 0x84, 0xa6, + 0xb5, 0x6e, 0x74, 0xee, 0x94, 0xa9, 0x6f, 0x7d, 0x06, 0x15, 0xcc, 0x88, 0x64, 0x5e, 0x5f, 0xbf, + 0x9b, 0x45, 0x83, 0x4b, 0x85, 0x74, 0x04, 0xbd, 0xf5, 0xdf, 0x30, 0x8b, 0x35, 0x85, 0xcb, 0x51, + 0x20, 0x3d, 0xa1, 0xe1, 0xd4, 0x0d, 0xee, 0x00, 0x05, 0x42, 0x70, 0xe9, 0x4f, 0xed, 0x29, 0xa5, + 0x1b, 0x09, 0xd8, 0xff, 0x2a, 0xc1, 0x0d, 0x21, 0xf8, 0x4e, 0x77, 0x53, 0x58, 0xe6, 0x14, 0x53, + 0x4e, 0x18, 0x96, 0x61, 0xe7, 0x9d, 0x90, 0xfa, 0x36, 0xd4, 0x87, 0xc8, 0x73, 0x8d, 0xcf, 0x4e, + 0x49, 0x57, 0x81, 0x21, 0xf2, 0x8c, 0x17, 0xdd, 0x02, 0x20, 0x49, 0xba, 0x3e, 0x2d, 0xd7, 0x6b, + 0x24, 0x31, 0xcb, 0xd9, 0x9b, 0x9a, 0xc9, 0xbf, 0x29, 0xfb, 0xfb, 0x12, 0x7c, 0x28, 0xee, 0xdd, + 0x8b, 0xbc, 0x70, 0xc4, 0xc8, 0x29, 0x96, 0x81, 0xd2, 0x43, 0x8c, 0x6f, 0x67, 0xa7, 0xbf, 0x89, + 0x0a, 0xc6, 0xef, 0x52, 0xbe, 0x78, 0x97, 0xa2, 0xa8, 0x95, 0x31, 0x51, 0xed, 0xbf, 0x94, 0xa0, + 0x9d, 0xf7, 0x21, 0x13, 0xfe, 0x7f, 0x7a, 0x3b, 0x5c, 0x21, 0xd8, 0x77, 0x65, 0x98, 0x97, 0xba, + 0xda, 0x53, 0x81, 0xea, 0xdd, 0xf0, 0x8c, 0x1b, 0x50, 0x23, 0x89, 0xab, 0x23, 0x9f, 0xf2, 0x8b, + 0x2a, 0x49, 0x74, 0x28, 0xb5, 0xa1, 0x91, 0x2e, 0xca, 0xa8, 0x39, 0xad, 0x18, 0x18, 0x02, 0x11, + 0x37, 0x6f, 0x01, 0x04, 0x67, 0xe9, 0xad, 0x67, 0xd4, 0xad, 0x83, 0xb3, 0x5c, 0x78, 0x52, 0xef, + 0xe5, 0x5a, 0xfe, 0xbd, 0x7c, 0x5f, 0x82, 0x65, 0x1d, 0xbe, 0xa5, 0x46, 0x5e, 0x2f, 0x82, 0x2b, + 0x5d, 0x95, 0xaf, 0xd0, 0x55, 0x31, 0xce, 0x57, 0x2e, 0x8f, 0xf3, 0x53, 0x85, 0x38, 0xff, 0x35, + 0x2c, 0x4b, 0x8b, 0x1c, 0x20, 0x1a, 0x60, 0xbe, 0x83, 0x65, 0xb9, 0x71, 0x4c, 0x12, 0x19, 0xef, + 0x55, 0xba, 0x2d, 0xa5, 0xe9, 0x56, 0x48, 0xc2, 0xaf, 0x90, 0x84, 0xdb, 0x23, 0x68, 0x3d, 0x09, + 0xe3, 0xb3, 0xfd, 0x04, 0x7b, 0xc6, 0xe8, 0x13, 0x83, 0xe1, 0x8f, 0xcb, 0x4c, 0xb2, 0xba, 0x3a, + 0x3a, 0x62, 0x98, 0xeb, 0x58, 0xa4, 0x21, 0xfb, 0x0b, 0xa8, 0x9b, 0x63, 0x77, 0xba, 0x9b, 0x97, + 0xd5, 0x57, 0xc6, 0x62, 0xe5, 0x62, 0xfe, 0xfa, 0x12, 0xae, 0x9b, 0xcd, 0x9b, 0xf1, 0x30, 0x89, + 0x23, 0xe1, 0x56, 0x1c, 0x0f, 0x85, 0x0a, 0x74, 0x69, 0xd4, 0x70, 0xca, 0x71, 0x52, 0x8c, 0xe0, + 0x53, 0x26, 0x82, 0xff, 0x1a, 0xe6, 0x2f, 0x6c, 0x9f, 0x28, 0xc1, 0x67, 0x30, 0x4d, 0x38, 0x1e, + 0xaa, 0xfa, 0xae, 0xbe, 0x7e, 0x3b, 0xf3, 0xe9, 0x89, 0xc7, 0x3b, 0x8a, 0xda, 0xfe, 0x1c, 0x66, + 0xcd, 0xba, 0x34, 0xcc, 0x3d, 0x98, 0xa6, 0xa3, 0x10, 0x9b, 0xc2, 0x6f, 0xb2, 0x2d, 0x14, 0x89, + 0xed, 0x41, 0xf3, 0x70, 0x6f, 0xb7, 0xb0, 0xfd, 0xf5, 0x5e, 0x5f, 0x7a, 0x48, 0xf9, 0xea, 0x43, + 0x36, 0x00, 0x9e, 0x27, 0xe8, 0xdb, 0x11, 0x96, 0xfc, 0x5b, 0x50, 0x39, 0xc1, 0xe7, 0xf2, 0x80, + 0x59, 0x47, 0x7c, 0x5e, 0x92, 0xf8, 0xfe, 0x5e, 0x82, 0x56, 0x9f, 0xed, 0xc6, 0x3e, 0xde, 0xc2, + 0xcc, 0xa3, 0x24, 0xe1, 0x31, 0x15, 0x9b, 0x11, 0x33, 0x49, 0x58, 0x7c, 0x5a, 0x2b, 0x50, 0x1b, + 0x04, 0x89, 0x1b, 0x32, 0x97, 0x98, 0x1c, 0x7c, 0x6d, 0x10, 0x24, 0x7d, 0xd6, 0xf3, 0xad, 0x3b, + 0x30, 0x1b, 0xb3, 0xe4, 0xc8, 0x45, 0x14, 0x23, 0xb1, 0xac, 0x1c, 0x1f, 0x04, 0xae, 0x4b, 0x31, + 0xea, 0xf9, 0xd6, 0x7b, 0x00, 0x09, 0xc3, 0x23, 0x3f, 0x8e, 0x62, 0x1f, 0x4b, 0x9f, 0xa9, 0x3a, + 0x39, 0x8c, 0x7c, 0xed, 0x41, 0xe2, 0x52, 0xf1, 0x0a, 0xa8, 0x60, 0xa1, 0xd2, 0x40, 0x9d, 0x04, + 0x89, 0x7c, 0x19, 0xb4, 0xe7, 0xdb, 0x3f, 0x94, 0x85, 0xa0, 0x7d, 0x12, 0x9d, 0xe4, 0x04, 0xb5, + 0xa1, 0x11, 0x92, 0xe8, 0xc4, 0x55, 0x35, 0x2e, 0x31, 0x05, 0x71, 0x5d, 0x20, 0x65, 0x35, 0xdc, + 0xf3, 0xad, 0xf7, 0x61, 0x4e, 0xd2, 0x50, 0x3c, 0x8c, 0x39, 0xce, 0xe4, 0x9f, 0x15, 0x58, 0x47, + 0x22, 0x7b, 0xbe, 0xb5, 0x06, 0x0b, 0x24, 0xe2, 0x98, 0x1e, 0x21, 0x0f, 0xcb, 0x98, 0xe2, 0x92, + 0xe4, 0x74, 0x43, 0xfb, 0xfd, 0x7c, 0xba, 0x24, 0xc2, 0x45, 0x2f, 0x39, 0xdd, 0xb0, 0x3e, 0x06, + 0x2b, 0xc2, 0x24, 0x38, 0x1e, 0xc4, 0x34, 0x47, 0xae, 0x1e, 0x76, 0xcb, 0xac, 0xa4, 0xd4, 0x13, + 0xb9, 0x77, 0xf4, 0x35, 0x2f, 0x70, 0xef, 0x4c, 0xe4, 0xde, 0xd1, 0x21, 0x6e, 0x9c, 0x7b, 0xc7, + 0xc6, 0x60, 0xf5, 0x75, 0x04, 0xcb, 0xe9, 0xe6, 0x23, 0x68, 0x92, 0xc4, 0xa5, 0x18, 0x79, 0xc7, + 0x68, 0x40, 0x42, 0xc2, 0xcf, 0x75, 0x3d, 0x3c, 0x47, 0x12, 0x27, 0x87, 0xb5, 0x3e, 0x84, 0xa6, + 0xb4, 0x9f, 0x54, 0xbf, 0x2b, 0xdf, 0x8b, 0x7a, 0x9a, 0x0d, 0x81, 0x56, 0xa1, 0xe9, 0x3c, 0xc1, + 0xf6, 0x53, 0x00, 0xe5, 0x29, 0xd2, 0xc1, 0x1e, 0x99, 0xce, 0x42, 0xda, 0x54, 0x39, 0xf2, 0x4a, + 0xf6, 0x96, 0xc6, 0x7d, 0x4a, 0x77, 0x1d, 0x02, 0x69, 0xff, 0xb3, 0x24, 0x38, 0x09, 0x53, 0xbe, + 0x25, 0x27, 0xeb, 0x0b, 0xa8, 0x6b, 0xb3, 0xca, 0xbd, 0xe5, 0x2b, 0xf7, 0x82, 0x22, 0x97, 0x9b, + 0x37, 0xa1, 0x29, 0x1d, 0xc3, 0x4f, 0x97, 0xa5, 0xb9, 0xc7, 0x18, 0x14, 0x3d, 0xce, 0x91, 0xbe, + 0x94, 0xc1, 0x22, 0xe9, 0xcf, 0x19, 0xe5, 0x1f, 0x6e, 0xbc, 0xed, 0x7d, 0x7a, 0x30, 0xaf, 0xe3, + 0x71, 0x4e, 0x28, 0x75, 0xab, 0x9b, 0x79, 0x0e, 0xe3, 0xc6, 0x76, 0x5a, 0xc9, 0x18, 0xa6, 0x28, + 0x58, 0xe7, 0x1d, 0x12, 0x6c, 0x00, 0xb3, 0x7d, 0x26, 0x7c, 0x57, 0xe7, 0xa5, 0xd5, 0x5c, 0x8c, + 0x9e, 0x93, 0x21, 0x2e, 0x93, 0xa7, 0xef, 0xf4, 0x84, 0xeb, 0xe9, 0xc8, 0xbd, 0x0a, 0x53, 0x51, + 0x48, 0xc9, 0x2b, 0xb3, 0x9f, 0xa4, 0xb0, 0xbf, 0x2b, 0xc1, 0xe2, 0x8e, 0xf2, 0x72, 0xc1, 0x23, + 0x6b, 0x0c, 0x57, 0x61, 0xe6, 0x08, 0x0d, 0x49, 0x78, 0xae, 0xaf, 0xdf, 0xca, 0x45, 0x7f, 0x89, + 0x77, 0xf4, 0xba, 0x28, 0x4f, 0x4c, 0x5b, 0xae, 0xc2, 0x6f, 0xcd, 0xa9, 0xea, 0xbe, 0x9c, 0x89, + 0xb8, 0x2c, 0xce, 0x11, 0xb5, 0xd6, 0x2b, 0xe2, 0xb2, 0x24, 0xb1, 0x23, 0x58, 0xda, 0x49, 0x5e, + 0x44, 0xf4, 0x6d, 0x84, 0x79, 0x93, 0xf3, 0xfe, 0x54, 0x82, 0x95, 0xb4, 0xed, 0x63, 0x22, 0xe1, + 0x90, 0x23, 0xe2, 0x6d, 0xbf, 0xe4, 0x38, 0xf2, 0xb1, 0x6f, 0xdd, 0x85, 0x06, 0x61, 0x2e, 0xa7, + 0x28, 0x62, 0x84, 0x93, 0x53, 0xa5, 0xf7, 0xaa, 0x33, 0x4b, 0xd8, 0x41, 0x8a, 0xb3, 0x96, 0xa1, + 0xca, 0x46, 0x83, 0x2c, 0x16, 0x34, 0x9c, 0x6b, 0x6c, 0x34, 0x10, 0xa6, 0xd0, 0x05, 0x49, 0x25, + 0x2d, 0x48, 0x6e, 0x43, 0x5d, 0x39, 0x95, 0x6a, 0xdc, 0x54, 0x41, 0xa0, 0xfc, 0xac, 0x2b, 0x30, + 0xf6, 0x0f, 0x25, 0xb8, 0xd1, 0xdb, 0x3b, 0xdd, 0xd0, 0x95, 0xd6, 0x7f, 0x5c, 0xa0, 0x4b, 0x07, + 0x10, 0x57, 0x8b, 0xf6, 0xe7, 0x12, 0xdc, 0xc8, 0xda, 0xcf, 0x77, 0x40, 0x57, 0xf7, 0xc0, 0x3a, + 0x44, 0x21, 0xf1, 0x65, 0xbf, 0x9f, 0x8a, 0xb1, 0x08, 0xd3, 0x8c, 0x23, 0x6e, 0xca, 0x18, 0x05, + 0xd8, 0x1f, 0x40, 0x63, 0x33, 0x0e, 0x63, 0x9a, 0x27, 0xf3, 0x04, 0xc2, 0x90, 0x49, 0xc0, 0xfe, + 0x5f, 0x68, 0xc8, 0x29, 0x42, 0x4a, 0x76, 0x1b, 0xea, 0x7c, 0x14, 0x45, 0x38, 0x74, 0x73, 0xa5, + 0x11, 0x28, 0x94, 0x8c, 0xf3, 0x6d, 0x58, 0xda, 0xc2, 0x47, 0x68, 0x14, 0xf2, 0xa7, 0x88, 0xe3, + 0x33, 0x74, 0x6e, 0xb6, 0xda, 0xcf, 0x60, 0x4e, 0x95, 0x18, 0x6f, 0xa6, 0xa1, 0xb4, 0xf2, 0xa8, + 0xe4, 0x2b, 0x0f, 0x07, 0x5a, 0xdb, 0xfb, 0x3d, 0x59, 0x8b, 0xa7, 0xec, 0x56, 0xa1, 0x45, 0x98, + 0xcb, 0x48, 0x14, 0x84, 0xd8, 0x45, 0x5e, 0x8e, 0xe3, 0x1c, 0x61, 0xfb, 0x12, 0xdd, 0xf5, 0x0c, + 0x4f, 0x55, 0xdd, 0x97, 0xf3, 0xd5, 0xfd, 0x3a, 0x2c, 0x6c, 0xef, 0xf7, 0x86, 0x49, 0x4c, 0x79, + 0xae, 0xa4, 0x16, 0x6f, 0x19, 0x33, 0x97, 0x48, 0xbc, 0x9e, 0x56, 0x54, 0x31, 0x53, 0x74, 0xf6, + 0x0b, 0x58, 0xd8, 0x41, 0xde, 0x4e, 0xac, 0xb2, 0x61, 0x2a, 0x8a, 0x68, 0x4f, 0x98, 0xcb, 0x38, + 0xf1, 0x4e, 0xce, 0xb5, 0x0c, 0x55, 0xc2, 0xf6, 0x25, 0x2c, 0xda, 0x1b, 0x86, 0xbf, 0x1d, 0xe1, + 0xc8, 0xc3, 0x6e, 0x34, 0x1a, 0x9a, 0x66, 0xd1, 0xe0, 0x76, 0x47, 0x43, 0xfb, 0x03, 0x98, 0x57, + 0xb5, 0xcb, 0x0e, 0xca, 0x1c, 0xaa, 0x05, 0x95, 0x21, 0xf2, 0xb4, 0x08, 0xe2, 0xd3, 0x7e, 0x04, + 0x0b, 0x07, 0x14, 0x1d, 0x1d, 0x11, 0xcf, 0x41, 0x3c, 0xd3, 0xeb, 0x78, 0xd9, 0x6f, 0xc1, 0x14, + 0x15, 0x1e, 0x20, 0x0e, 0x2a, 0x3b, 0xf2, 0xdb, 0x7e, 0x06, 0xd7, 0xf5, 0x56, 0xa1, 0x93, 0x9c, + 0xbf, 0xac, 0x40, 0x95, 0x63, 0x3a, 0x24, 0x11, 0x0a, 0x8d, 0xe4, 0x06, 0x16, 0xa5, 0x3b, 0x43, + 0xc3, 0x24, 0x54, 0xac, 0xaa, 0x8e, 0x86, 0xec, 0x17, 0x60, 0x3b, 0xd8, 0x27, 0x14, 0x7b, 0xfc, + 0x15, 0xc1, 0x63, 0x5c, 0xac, 0x31, 0x87, 0x2e, 0x5f, 0x70, 0xe8, 0xdf, 0xc0, 0x5d, 0xc3, 0xf6, + 0x55, 0x31, 0xe0, 0xd2, 0xa9, 0xd6, 0xd5, 0x27, 0x1c, 0x66, 0x27, 0xbc, 0xea, 0x29, 0xbf, 0xb1, + 0xe4, 0xf7, 0x53, 0xed, 0x3a, 0x78, 0x88, 0xe8, 0x49, 0xca, 0xc9, 0x82, 0x29, 0x9f, 0x79, 0xa6, + 0x21, 0x91, 0xdf, 0xf6, 0x17, 0xd0, 0x7c, 0x11, 0x9d, 0x44, 0xf1, 0x59, 0x94, 0x27, 0x7b, 0xcd, + 0xd9, 0xd3, 0x21, 0xdc, 0x34, 0xbb, 0x26, 0xce, 0x4b, 0x3b, 0x17, 0xe7, 0xa5, 0x97, 0xa5, 0x80, + 0xc2, 0x14, 0x75, 0x13, 0x5a, 0x5d, 0xb6, 0xf1, 0x96, 0x13, 0xeb, 0xc7, 0xb0, 0xd4, 0x65, 0x1b, + 0x6f, 0x37, 0x08, 0xc6, 0xb0, 0xb0, 0x37, 0x64, 0xe4, 0x40, 0x86, 0x98, 0x8c, 0xc1, 0x22, 0x4c, + 0x1f, 0x85, 0x28, 0x30, 0x56, 0x51, 0x40, 0xaa, 0xb7, 0x72, 0x51, 0x6f, 0xea, 0xb1, 0x57, 0x72, + 0x8f, 0x5d, 0x0f, 0x83, 0xa7, 0xa4, 0x2a, 0xcb, 0xc4, 0xb7, 0x7f, 0x01, 0xef, 0xa9, 0x23, 0x64, + 0xbc, 0xdb, 0x1f, 0x0d, 0x0e, 0xfa, 0x87, 0x85, 0x01, 0x6a, 0xbe, 0x29, 0x6a, 0xa8, 0xa6, 0x68, + 0x09, 0x66, 0xbc, 0x38, 0x3e, 0x21, 0xc6, 0x24, 0x1a, 0xb2, 0xff, 0x0f, 0x96, 0x2f, 0xf0, 0xda, + 0x13, 0x9a, 0xf6, 0xe2, 0x50, 0xbc, 0xaf, 0x44, 0x7f, 0x6b, 0x5e, 0x29, 0x6c, 0xaf, 0xc1, 0xd2, + 0x85, 0x8d, 0x32, 0x4c, 0x5f, 0x12, 0x9e, 0xb7, 0xa0, 0x7d, 0x81, 0x5e, 0xbb, 0xd2, 0x1b, 0xb8, + 0xd0, 0x2e, 0xcc, 0xe5, 0xb8, 0x1c, 0xf4, 0x0f, 0x27, 0xee, 0x15, 0x95, 0x56, 0x78, 0xfa, 0xea, + 0x66, 0x52, 0x52, 0xd8, 0x5b, 0xb0, 0x98, 0xe3, 0x97, 0x99, 0xec, 0x63, 0xcd, 0x41, 0xb9, 0x4e, + 0x3b, 0x73, 0x9d, 0xe2, 0xe9, 0x9a, 0x8b, 0xce, 0xfc, 0x9d, 0x77, 0x30, 0xf3, 0x17, 0xe3, 0x52, + 0xe7, 0x27, 0x88, 0x4b, 0xbf, 0x82, 0xdb, 0xbd, 0xbd, 0xce, 0x4f, 0xf2, 0xb0, 0xef, 0x41, 0xab, + 0x4b, 0x02, 0xa1, 0xe8, 0xde, 0xd3, 0xbd, 0x1d, 0xcc, 0x29, 0xf1, 0x84, 0x23, 0x0f, 0xe5, 0x97, + 0x14, 0x74, 0xca, 0xd1, 0x90, 0xfd, 0x39, 0xcc, 0x69, 0xda, 0x37, 0xf7, 0xaa, 0x47, 0xd0, 0x10, + 0x7b, 0xf3, 0x05, 0x6b, 0xde, 0xfc, 0xaf, 0x72, 0xa0, 0x11, 0xcc, 0xf5, 0x45, 0xee, 0x35, 0xf7, + 0x96, 0x29, 0x33, 0x08, 0xe3, 0x41, 0xaa, 0x31, 0xdd, 0xa9, 0x2b, 0x9c, 0x54, 0x59, 0xa6, 0x53, + 0x1f, 0x71, 0xf4, 0x69, 0x41, 0xa7, 0x5b, 0x02, 0x53, 0x24, 0x58, 0x37, 0x83, 0x86, 0x94, 0x60, + 0xdd, 0xfe, 0x06, 0x96, 0x0b, 0xc7, 0x16, 0xd4, 0xfd, 0xf9, 0x24, 0x75, 0xe7, 0x7c, 0xb8, 0x28, + 0x70, 0x51, 0xe5, 0x7f, 0x2d, 0x41, 0x5d, 0xf5, 0x47, 0x4f, 0x64, 0x94, 0x5a, 0x81, 0x6a, 0x7c, + 0x8a, 0x69, 0x18, 0x23, 0xdf, 0xa4, 0x58, 0x03, 0xcb, 0xdf, 0x15, 0x9c, 0x23, 0xef, 0x58, 0xff, + 0xae, 0xa8, 0x3a, 0x29, 0x2c, 0xd6, 0xf0, 0x4b, 0x8e, 0xa9, 0x48, 0xcd, 0x15, 0xb5, 0x66, 0x60, + 0x39, 0x75, 0x19, 0x50, 0x3d, 0x1e, 0x11, 0x9f, 0xc2, 0xa8, 0x6a, 0x26, 0x22, 0x27, 0x05, 0x55, + 0x47, 0x43, 0x22, 0xf2, 0xe9, 0x71, 0x40, 0xd5, 0x29, 0x9f, 0x76, 0xec, 0x3f, 0xca, 0x86, 0xba, + 0xf7, 0x74, 0xef, 0x89, 0x09, 0xa1, 0x7e, 0x7c, 0x16, 0x69, 0xc1, 0xe4, 0xb7, 0x75, 0x0b, 0x20, + 0x8a, 0xdd, 0x51, 0x24, 0x47, 0xe4, 0x5a, 0xac, 0x5a, 0x14, 0xbf, 0x50, 0x08, 0xf1, 0x14, 0x8d, + 0x3b, 0x67, 0x0f, 0xaa, 0xea, 0xcc, 0x6a, 0x87, 0x56, 0x3e, 0xff, 0x01, 0xcc, 0x25, 0x34, 0x4e, + 0x50, 0x80, 0x44, 0xc3, 0xcd, 0x18, 0xd2, 0xb2, 0x36, 0x52, 0xec, 0x2e, 0x63, 0xc8, 0x7e, 0x08, + 0xb5, 0x3e, 0xdb, 0xa7, 0x0e, 0x8a, 0x02, 0xe9, 0x59, 0x03, 0x9c, 0xfd, 0x87, 0x55, 0x80, 0xb8, + 0x2a, 0x8e, 0xcc, 0x20, 0x46, 0x7c, 0x8a, 0xae, 0xa5, 0x25, 0x76, 0x6d, 0xa2, 0x44, 0xcd, 0x25, + 0x08, 0x96, 0x07, 0x92, 0xe4, 0x74, 0xc3, 0x65, 0xa3, 0x44, 0x94, 0x6a, 0xd8, 0xe8, 0xba, 0x21, + 0xb0, 0xfb, 0x06, 0xa9, 0xc9, 0x3a, 0x39, 0xb2, 0x72, 0x4a, 0xd6, 0xc9, 0xc8, 0xee, 0xc3, 0x0c, + 0x15, 0x32, 0x99, 0x2e, 0x6a, 0x21, 0xdf, 0x6a, 0x6a, 0x79, 0x1d, 0x4d, 0x62, 0x7f, 0x29, 0xba, + 0xe7, 0x7d, 0x2a, 0x87, 0x48, 0x8f, 0xc3, 0xd8, 0x3b, 0xc9, 0x6d, 0x2f, 0x5d, 0xbd, 0xfd, 0x0f, + 0x15, 0x68, 0xf6, 0x33, 0xdf, 0x93, 0x3d, 0xb4, 0x05, 0x53, 0x11, 0x1a, 0x62, 0x1d, 0x49, 0xe4, + 0xb7, 0x75, 0xdf, 0xe4, 0x40, 0xd5, 0xd3, 0x5e, 0x1f, 0xef, 0xc6, 0xa5, 0x41, 0x4d, 0x6a, 0xfc, + 0x10, 0x9a, 0xca, 0x48, 0xd9, 0xa0, 0x4c, 0xc5, 0x3d, 0x65, 0x3b, 0x33, 0x2a, 0xb3, 0xee, 0x83, + 0x35, 0x46, 0xe7, 0x9e, 0x76, 0xf4, 0x6c, 0xaa, 0x59, 0x20, 0x3d, 0xec, 0xa8, 0x3a, 0x97, 0x30, + 0x39, 0xbd, 0x93, 0x6e, 0x36, 0x2b, 0xea, 0x5c, 0xc2, 0xba, 0x14, 0x23, 0x39, 0xe8, 0x95, 0x05, + 0xbf, 0x74, 0xb6, 0x59, 0x47, 0x43, 0xd6, 0x26, 0x34, 0x19, 0x75, 0xbd, 0x9c, 0xad, 0xe4, 0x94, + 0x7d, 0x6c, 0x9c, 0x50, 0xb4, 0xa6, 0x33, 0xc7, 0x8a, 0xd6, 0xbd, 0x0b, 0x0d, 0x46, 0x5d, 0x14, + 0x06, 0x31, 0x25, 0xfc, 0x78, 0xc8, 0xda, 0x55, 0x79, 0xc6, 0x2c, 0xa3, 0xdd, 0x14, 0x67, 0xfd, + 0x0c, 0xe6, 0x18, 0xd5, 0xf3, 0xbd, 0x81, 0xb0, 0x43, 0xbb, 0x26, 0x0f, 0x6a, 0x17, 0x0f, 0xca, + 0xec, 0x24, 0xf6, 0x67, 0x90, 0xfd, 0xfb, 0xa9, 0x82, 0x21, 0xfa, 0x24, 0x3a, 0x99, 0x68, 0x88, + 0x09, 0xba, 0x2d, 0xbf, 0xbe, 0x6e, 0x2b, 0x93, 0x75, 0xbb, 0x0a, 0x2d, 0x3d, 0x9e, 0xca, 0xb8, + 0x2a, 0x33, 0xcc, 0x29, 0x7c, 0xca, 0xf6, 0x01, 0x2c, 0x8c, 0x53, 0xba, 0xe9, 0x80, 0xb0, 0x55, + 0x24, 0x3e, 0xec, 0x88, 0x40, 0x28, 0xa3, 0xa8, 0x1b, 0xd0, 0x78, 0x94, 0x48, 0xe3, 0x34, 0x1c, + 0x90, 0xa8, 0xa7, 0x02, 0x63, 0xdd, 0x83, 0x79, 0x5f, 0xf5, 0x70, 0x2e, 0xc7, 0xae, 0xce, 0x0c, + 0xea, 0x47, 0x48, 0x53, 0x2f, 0x1c, 0x60, 0x9d, 0x3a, 0x6e, 0x01, 0x90, 0x20, 0x31, 0x44, 0x55, + 0xf5, 0x13, 0x80, 0x04, 0x49, 0x96, 0x59, 0xb4, 0x0f, 0xd4, 0x0a, 0x3e, 0x70, 0x13, 0x6a, 0x03, + 0x14, 0xf9, 0x67, 0xc4, 0xe7, 0xc7, 0x6d, 0x90, 0x7d, 0x49, 0x86, 0xb0, 0x3e, 0x85, 0x45, 0x8a, + 0x19, 0xa6, 0xa7, 0x68, 0x10, 0x62, 0x37, 0x23, 0xac, 0x4b, 0xc2, 0x85, 0x6c, 0xed, 0x71, 0x7e, + 0xcb, 0x28, 0x52, 0x0b, 0xd8, 0xcf, 0x6d, 0x99, 0xbd, 0x53, 0x11, 0x5b, 0xb2, 0xb5, 0x6c, 0xcb, + 0x2a, 0xb4, 0x84, 0x0b, 0xf9, 0xbf, 0x45, 0x1e, 0x8e, 0xbc, 0x73, 0x97, 0x11, 0xbf, 0xdd, 0x90, + 0x17, 0x98, 0x63, 0xb4, 0x6b, 0xd0, 0xfb, 0xc4, 0xb7, 0x7f, 0x57, 0x82, 0xf9, 0x9c, 0x1f, 0xe8, + 0xd9, 0xd3, 0xa7, 0x20, 0x2e, 0xea, 0x66, 0x65, 0x68, 0xbd, 0x38, 0x80, 0x32, 0x21, 0xd5, 0xa9, + 0x92, 0x20, 0x51, 0xc1, 0x35, 0x53, 0x47, 0xb9, 0xa0, 0x0e, 0x5b, 0x7a, 0xb3, 0x1e, 0x92, 0xb1, + 0x74, 0x0c, 0x5e, 0x67, 0x7a, 0xce, 0x25, 0x84, 0xf8, 0x9b, 0xcc, 0x22, 0x59, 0x46, 0x7a, 0x00, + 0x53, 0xb9, 0x51, 0xdc, 0x72, 0xfe, 0xe4, 0x42, 0xe8, 0x70, 0x24, 0x99, 0x20, 0x0f, 0x49, 0x74, + 0xa2, 0x63, 0xc5, 0x64, 0x72, 0xe1, 0xe0, 0x8e, 0x24, 0xb3, 0x1e, 0x16, 0xfe, 0xde, 0xd4, 0xd7, + 0x6f, 0x4c, 0xdc, 0xa0, 0x7f, 0x09, 0x9a, 0x9f, 0x51, 0x0e, 0xb4, 0x74, 0xa1, 0xf0, 0x23, 0x0b, + 0xf5, 0x8b, 0x9d, 0xfe, 0x3d, 0x26, 0x07, 0xc7, 0x7a, 0x96, 0x67, 0x2d, 0x40, 0xb3, 0xbf, 0xef, + 0x0a, 0xd0, 0x7d, 0xb1, 0xfb, 0x6c, 0xf7, 0xf9, 0x37, 0xbb, 0xad, 0xff, 0xb2, 0x5a, 0x30, 0x6b, + 0x90, 0xbb, 0xcf, 0xb7, 0xb6, 0x5b, 0xa5, 0x3c, 0xa6, 0xdf, 0xdb, 0x7d, 0xd6, 0x2a, 0x5b, 0xd7, + 0x61, 0xde, 0x60, 0xf6, 0x9c, 0xed, 0x27, 0xbd, 0x5f, 0xba, 0x87, 0x1b, 0xad, 0xca, 0x24, 0x74, + 0xa7, 0x35, 0x35, 0x98, 0x91, 0x55, 0xc9, 0xc3, 0x7f, 0x07, 0x00, 0x00, 0xff, 0xff, 0xe4, 0xfb, + 0xd9, 0x4c, 0x60, 0x24, 0x00, 0x00, } diff --git a/api/attribute.proto b/api/attribute.proto index c07ad05c..795cfb90 100644 --- a/api/attribute.proto +++ b/api/attribute.proto @@ -267,6 +267,69 @@ message OpaqueNLRI { bytes value = 2; } +message LsNodeDescriptor { + uint32 asn = 1; + uint32 bgp_ls_id = 2; + uint32 ospf_area_id = 3; + bool pseudonode = 4; + string igp_router_id = 5; +} + +message LsLinkDescriptor { + uint32 link_local_id = 1; + uint32 link_remote_id = 2; + string interface_addr_ipv4 = 3; + string neighbor_addr_ipv4 = 4; + string interface_addr_ipv6 = 5; + string neighbor_addr_ipv6 = 6; +} + +message LsPrefixDescriptor { + repeated string ip_reachability = 1; + string ospf_route_type = 2; +} + +message LsNodeNLRI { + LsNodeDescriptor local_node = 1; +} + +message LsLinkNLRI { + LsNodeDescriptor local_node = 1; + LsNodeDescriptor remote_node = 2; + LsLinkDescriptor link_descriptor = 3; +} + +message LsPrefixV4NLRI { + LsNodeDescriptor local_node = 1; + LsPrefixDescriptor prefix_descriptor = 2; +} + +message LsPrefixV6NLRI { + LsNodeDescriptor local_node = 1; + LsPrefixDescriptor prefix_descriptor = 2; +} + +// Based om RFC 7752, Table 1. +enum LsNLRIType { + LS_NLRI_UNKNOWN = 0; + LS_NLRI_NODE = 1; + LS_NLRI_LINK = 2; + LS_NLRI_PREFIX_V4 = 3; + LS_NLRI_PREFIX_V6 = 4; +} + +// LsAddrPrefix represents the NLRI for: +// - AFI=16388, SAFI=71 +message LsAddrPrefix { + LsNLRIType type = 1; + // One of: + // - LsNodeNLRI + // - LsLinkNLRI + // - LsPrefixV4NLRI + // - LsPrefixV6NLRI + google.protobuf.Any nlri = 2; +} + message MpReachNLRIAttribute { gobgpapi.Family family = 1; repeated string next_hops = 2; @@ -284,6 +347,7 @@ message MpReachNLRIAttribute { // - FlowSpecNLRI // - VPNFlowSpecNLRI // - OpaqueNLRI + // - LsAddrPrefix repeated google.protobuf.Any nlris = 3; } @@ -498,6 +562,81 @@ message LargeCommunitiesAttribute { repeated LargeCommunity communities = 1; } +message LsNodeFlags { + bool overload = 1; + bool attached = 2; + bool external = 3; + bool abr = 4; + bool router = 5; + bool v6 = 6; +} + +message LsIGPFlags { + bool down = 1; + bool no_unicast = 2; + bool local_address = 3; + bool propagate_nssa = 4; +} + +message LsSrRange { + uint32 begin = 1; + uint32 end = 2; +} + +message LsSrCapabilities { + bool ipv4_supported = 1; + bool ipv6_supported = 2; + repeated LsSrRange ranges = 3; +} + +message LsSrLocalBlock { + repeated LsSrRange ranges = 1; +} + +message LsAttributeNode { + string name = 1; + LsNodeFlags flags = 2; + string local_router_id = 3; + string local_router_id_v6 = 4; + bytes isis_area = 5; + bytes opaque = 6; + + LsSrCapabilities sr_capabilities = 7; + bytes sr_algorithms = 8; + LsSrLocalBlock sr_local_block = 9; +} + +message LsAttributeLink { + string name = 1; + string local_router_id = 2; + string local_router_id_v6 = 3; + string remote_router_id = 4; + string remote_router_id_v6 = 5; + uint32 admin_group = 6; + uint32 default_te_metric = 7; + uint32 igp_metric = 8; + bytes opaque = 9; + + float bandwidth = 10; + float reservable_bandwidth = 11; + repeated float unreserved_bandwidth = 12; + + uint32 sr_adjacency_sid = 13; +} + +message LsAttributePrefix { + LsIGPFlags igp_flags = 1; + bytes opaque = 2; + + uint32 sr_prefix_sid = 3; +} + +message LsAttribute { + LsAttributeNode node = 1; + LsAttributeLink link = 2; + LsAttributePrefix prefix = 3; +} + message UnknownAttribute { uint32 flags = 1; uint32 type = 2; diff --git a/api/capability.pb.go b/api/capability.pb.go index ddacc164..d3a61769 100644 --- a/api/capability.pb.go +++ b/api/capability.pb.go @@ -1,6 +1,5 @@ -// Code generated by protoc-gen-go. +// Code generated by protoc-gen-go. DO NOT EDIT. // source: capability.proto -// DO NOT EDIT! package gobgpapi diff --git a/api/gobgp.pb.go b/api/gobgp.pb.go index 43cefbcc..6f5cea03 100644 --- a/api/gobgp.pb.go +++ b/api/gobgp.pb.go @@ -1,6 +1,5 @@ -// Code generated by protoc-gen-go. +// Code generated by protoc-gen-go. DO NOT EDIT. // source: gobgp.proto -// DO NOT EDIT! /* Package gobgpapi is a generated protocol buffer package. @@ -185,6 +184,14 @@ It has these top-level messages: FlowSpecNLRI VPNFlowSpecNLRI OpaqueNLRI + LsNodeDescriptor + LsLinkDescriptor + LsPrefixDescriptor + LsNodeNLRI + LsLinkNLRI + LsPrefixV4NLRI + LsPrefixV6NLRI + LsAddrPrefix MpReachNLRIAttribute MpUnreachNLRIAttribute TwoOctetAsSpecificExtended @@ -224,6 +231,15 @@ It has these top-level messages: AigpAttribute LargeCommunity LargeCommunitiesAttribute + LsNodeFlags + LsIGPFlags + LsSrRange + LsSrCapabilities + LsSrLocalBlock + LsAttributeNode + LsAttributeLink + LsAttributePrefix + LsAttribute UnknownAttribute MultiProtocolCapability RouteRefreshCapability @@ -587,6 +603,7 @@ const ( Family_AFI_IP Family_Afi = 1 Family_AFI_IP6 Family_Afi = 2 Family_AFI_L2VPN Family_Afi = 25 + Family_AFI_LS Family_Afi = 16388 Family_AFI_OPAQUE Family_Afi = 16397 ) @@ -595,6 +612,7 @@ var Family_Afi_name = map[int32]string{ 1: "AFI_IP", 2: "AFI_IP6", 25: "AFI_L2VPN", + 16388: "AFI_LS", 16397: "AFI_OPAQUE", } var Family_Afi_value = map[string]int32{ @@ -602,6 +620,7 @@ var Family_Afi_value = map[string]int32{ "AFI_IP": 1, "AFI_IP6": 2, "AFI_L2VPN": 25, + "AFI_LS": 16388, "AFI_OPAQUE": 16397, } @@ -620,6 +639,7 @@ const ( Family_SAFI_ENCAPSULATION Family_Safi = 7 Family_SAFI_VPLS Family_Safi = 65 Family_SAFI_EVPN Family_Safi = 70 + Family_SAFI_LS Family_Safi = 71 Family_SAFI_MPLS_VPN Family_Safi = 128 Family_SAFI_MPLS_VPN_MULTICAST Family_Safi = 129 Family_SAFI_ROUTE_TARGET_CONSTRAINTS Family_Safi = 132 @@ -636,6 +656,7 @@ var Family_Safi_name = map[int32]string{ 7: "SAFI_ENCAPSULATION", 65: "SAFI_VPLS", 70: "SAFI_EVPN", + 71: "SAFI_LS", 128: "SAFI_MPLS_VPN", 129: "SAFI_MPLS_VPN_MULTICAST", 132: "SAFI_ROUTE_TARGET_CONSTRAINTS", @@ -651,6 +672,7 @@ var Family_Safi_value = map[string]int32{ "SAFI_ENCAPSULATION": 7, "SAFI_VPLS": 65, "SAFI_EVPN": 70, + "SAFI_LS": 71, "SAFI_MPLS_VPN": 128, "SAFI_MPLS_VPN_MULTICAST": 129, "SAFI_ROUTE_TARGET_CONSTRAINTS": 132, @@ -2486,6 +2508,7 @@ type Path struct { // - FlowSpecNLRI // - VPNFlowSpecNLRI // - OpaqueNLRI + // - LsAddrPrefix Nlri *google_protobuf.Any `protobuf:"bytes,1,opt,name=nlri" json:"nlri,omitempty"` // Each attribute must be one of *Attribute defined in // "api/attribute.proto". @@ -7956,491 +7979,493 @@ var _GobgpApi_serviceDesc = grpc.ServiceDesc{ func init() { proto.RegisterFile("gobgp.proto", fileDescriptor0) } var fileDescriptor0 = []byte{ - // 7776 bytes of a gzipped FileDescriptorProto + // 7794 bytes of a gzipped FileDescriptorProto 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xec, 0x7d, 0x4b, 0x6c, 0x1b, 0x59, 0xb6, 0x58, 0xf3, 0x23, 0x8a, 0x3c, 0x24, 0xc5, 0xd2, 0x95, 0x2c, 0x51, 0x72, 0xfb, 0xd3, 0x35, 0xdd, 0xb6, 0x5b, 0x6d, 0xbb, 0x6d, 0x77, 0x8f, 0xbb, 0xc7, 0x7e, 0xee, 0x6e, 0x5a, 0xa2, 0x65, - 0xb6, 0x29, 0x92, 0x5d, 0xa4, 0xdc, 0xee, 0x49, 0x1a, 0xf5, 0x4a, 0xac, 0x4b, 0xaa, 0xd2, 0x64, - 0x55, 0x75, 0x55, 0x51, 0x96, 0x56, 0x79, 0x99, 0x97, 0x4c, 0x16, 0x41, 0x80, 0x20, 0x59, 0xbc, - 0x45, 0x26, 0x48, 0xd6, 0x83, 0x64, 0x97, 0x2c, 0x82, 0x2c, 0x12, 0x04, 0x09, 0x10, 0x64, 0x80, - 0xac, 0x02, 0x04, 0xc8, 0x22, 0x01, 0x82, 0xac, 0x03, 0x24, 0x8b, 0x20, 0xcb, 0xe0, 0x7e, 0xaa, - 0xea, 0xd6, 0x87, 0x92, 0xfc, 0x99, 0x99, 0x37, 0xc0, 0xac, 0xc4, 0x7b, 0xce, 0xb9, 0xe7, 0xfe, - 0xce, 0x3d, 0x9f, 0x7b, 0x6f, 0x1d, 0x41, 0x79, 0x6c, 0x1d, 0x8c, 0xed, 0xdb, 0xb6, 0x63, 0x79, - 0x16, 0x2a, 0xd2, 0x82, 0x66, 0x1b, 0x9b, 0x1b, 0x63, 0xcb, 0x1a, 0x4f, 0xf0, 0xc7, 0x14, 0x7e, - 0x30, 0x1b, 0x7d, 0xac, 0x99, 0x27, 0x8c, 0x68, 0xf3, 0x62, 0x1c, 0x85, 0xa7, 0xb6, 0xe7, 0x23, - 0xaf, 0xc4, 0x91, 0x9e, 0x31, 0xc5, 0xae, 0xa7, 0x4d, 0x79, 0x13, 0xf2, 0x43, 0xa8, 0xf5, 0x3d, - 0xcd, 0xf1, 0x1e, 0x8f, 0x6d, 0x05, 0xff, 0x38, 0xc3, 0xae, 0x87, 0x6e, 0x40, 0x61, 0x3c, 0xb1, - 0x0e, 0xb4, 0x49, 0x3d, 0x73, 0x35, 0x73, 0xa3, 0x7c, 0x4f, 0xba, 0xed, 0x77, 0xe3, 0xf6, 0x2e, - 0x85, 0x2b, 0x1c, 0x2f, 0x4b, 0xb0, 0xd4, 0xf7, 0x2c, 0x3b, 0xac, 0x2b, 0xd7, 0xa0, 0xba, 0x8b, - 0x05, 0x66, 0xf2, 0x03, 0x58, 0xf2, 0x01, 0xae, 0x6d, 0x99, 0x2e, 0x7e, 0x05, 0xf6, 0x9f, 0xc2, - 0x52, 0x43, 0xd7, 0x7b, 0x18, 0x3b, 0x7e, 0xd7, 0x64, 0xc8, 0xdb, 0x18, 0x3b, 0xbc, 0xe6, 0x52, - 0x58, 0x93, 0x12, 0x51, 0x9c, 0xfc, 0x0c, 0x96, 0x77, 0xf0, 0x04, 0x7b, 0x58, 0xac, 0x58, 0x87, - 0x45, 0x4d, 0xd7, 0x1d, 0xec, 0xba, 0xb4, 0x6e, 0x49, 0xf1, 0x8b, 0xe8, 0x5d, 0x28, 0x19, 0xa6, - 0x87, 0x9d, 0x91, 0x36, 0xc4, 0xf5, 0x2c, 0xc5, 0x85, 0x00, 0xf9, 0x5b, 0xa8, 0xb5, 0x0d, 0xd7, - 0x3b, 0x1f, 0xab, 0x2d, 0x90, 0xb0, 0xa9, 0x1d, 0x4c, 0x70, 0x43, 0x3f, 0xc2, 0x8e, 0x67, 0xb8, - 0x58, 0xa7, 0x1c, 0x8b, 0x4a, 0x02, 0x2e, 0xdf, 0x07, 0x29, 0x64, 0xcc, 0x67, 0xe6, 0x3c, 0xa3, - 0xfb, 0x53, 0x58, 0xde, 0xb7, 0x75, 0x2d, 0x3a, 0xba, 0x73, 0x54, 0x44, 0xd7, 0x41, 0xd2, 0x2d, - 0xd5, 0xb5, 0x46, 0x9e, 0xea, 0x60, 0x17, 0x7b, 0xaa, 0x61, 0xf2, 0xce, 0x55, 0x75, 0xab, 0x6f, - 0x8d, 0x3c, 0x85, 0x40, 0x5b, 0xa6, 0xbc, 0x0d, 0x48, 0x6c, 0x81, 0xf7, 0xed, 0x16, 0xac, 0x98, - 0x18, 0xeb, 0x6e, 0x8c, 0x43, 0x86, 0x0d, 0x8f, 0xa2, 0x44, 0x26, 0xff, 0x33, 0x03, 0x12, 0xfd, - 0x7d, 0xbe, 0x99, 0x7b, 0x1f, 0xaa, 0x43, 0x6b, 0x3a, 0x9d, 0x99, 0xc6, 0x50, 0xf3, 0x0c, 0xcb, - 0xe4, 0x0b, 0x11, 0x05, 0x22, 0x04, 0x79, 0xd2, 0x7a, 0x3d, 0x47, 0x1b, 0xa5, 0xbf, 0xd1, 0x33, - 0x28, 0xe9, 0x86, 0x83, 0x87, 0xb4, 0x56, 0xfe, 0x6a, 0xe6, 0xc6, 0xd2, 0xbd, 0x5b, 0xe1, 0xf8, - 0xe3, 0x5d, 0xb8, 0x1d, 0xf4, 0x71, 0xc7, 0xaf, 0xa4, 0x84, 0xf5, 0xe5, 0x8f, 0x01, 0x25, 0x09, - 0x50, 0x01, 0xb2, 0xad, 0x8e, 0xf4, 0x0e, 0x5a, 0x84, 0x5c, 0x77, 0x7f, 0x20, 0x65, 0x50, 0x11, - 0xf2, 0x8f, 0xbb, 0x83, 0xa7, 0x52, 0x56, 0xde, 0x87, 0x95, 0xfe, 0xe1, 0xcc, 0xd3, 0xad, 0x97, - 0xe6, 0x5b, 0x1c, 0xa8, 0x7c, 0x0b, 0x96, 0x9b, 0x54, 0x60, 0xce, 0xc5, 0x54, 0x1e, 0x00, 0xda, - 0x31, 0xdc, 0x73, 0xd3, 0x9f, 0xb3, 0x13, 0x4f, 0x01, 0xed, 0x59, 0xa6, 0xe1, 0x59, 0xce, 0xf9, - 0xb8, 0xd6, 0x61, 0x71, 0x38, 0x73, 0x1c, 0x6c, 0x7a, 0x5c, 0xae, 0xfc, 0xa2, 0xfc, 0x33, 0x58, - 0x89, 0x70, 0x7a, 0x05, 0x71, 0x6f, 0xc1, 0x0a, 0x57, 0x01, 0xbb, 0x8e, 0x35, 0x0b, 0x54, 0xd4, - 0x3d, 0x00, 0x82, 0x56, 0xc7, 0x04, 0xc8, 0x19, 0xac, 0x44, 0x19, 0x30, 0xfa, 0x92, 0xed, 0xff, - 0x94, 0x6f, 0xc2, 0x5a, 0xa8, 0x17, 0x22, 0xdc, 0x10, 0xe4, 0x4d, 0x6d, 0x8a, 0xf9, 0x80, 0xe8, - 0x6f, 0x79, 0x06, 0x6b, 0xe1, 0x2e, 0x78, 0xd3, 0xb6, 0xcf, 0xbf, 0xf9, 0x9e, 0xc2, 0x7a, 0xa2, - 0xd9, 0xd7, 0xdb, 0x81, 0x1a, 0x6c, 0x34, 0x74, 0x7d, 0xe7, 0xc4, 0xd4, 0xa6, 0xc6, 0xb0, 0x83, - 0x8d, 0xf1, 0xe1, 0x81, 0x15, 0xac, 0xe2, 0x0e, 0x48, 0x3a, 0xc3, 0xa8, 0x26, 0x47, 0xf1, 0x91, - 0x6c, 0x84, 0x23, 0x89, 0xd7, 0xad, 0xe9, 0x51, 0x80, 0xfc, 0xd7, 0x99, 0x7e, 0xd6, 0xbc, 0x43, - 0x61, 0x6e, 0x3c, 0x22, 0x87, 0xaa, 0x77, 0x62, 0xb3, 0xf9, 0x5c, 0x12, 0xe7, 0x66, 0x40, 0x70, - 0x83, 0x13, 0x1b, 0x2b, 0x25, 0xcf, 0xff, 0x89, 0x2e, 0x40, 0xe1, 0xc8, 0x19, 0xa9, 0x86, 0xce, - 0xc5, 0x70, 0xe1, 0xc8, 0x19, 0xb5, 0x74, 0x2a, 0x1d, 0x9a, 0x77, 0x48, 0x37, 0x7b, 0x54, 0x3a, - 0x48, 0x7b, 0x14, 0x27, 0x7f, 0x00, 0xb5, 0xa0, 0x03, 0x7c, 0x96, 0x10, 0xe4, 0x67, 0x33, 0x43, - 0xa7, 0x6d, 0x57, 0x14, 0xfa, 0x5b, 0xfe, 0x37, 0x99, 0xc0, 0x24, 0xfc, 0x76, 0xfa, 0x7a, 0x03, - 0x0a, 0x23, 0x6d, 0x6a, 0x4c, 0x4e, 0x78, 0x6f, 0x05, 0x93, 0xf6, 0x84, 0xc2, 0x15, 0x8e, 0x0f, - 0x46, 0x95, 0x9f, 0x3f, 0xaa, 0x60, 0x08, 0x0b, 0xc2, 0x10, 0xfe, 0x71, 0x96, 0x1b, 0xa2, 0x37, - 0x1c, 0x80, 0x2f, 0xea, 0xd9, 0x50, 0xd4, 0x5f, 0xa1, 0xf7, 0x9f, 0x41, 0xd1, 0x76, 0xf0, 0xc8, - 0x38, 0xc6, 0x6e, 0x3d, 0x7f, 0x35, 0x77, 0xa3, 0x7c, 0xef, 0x62, 0xac, 0xbd, 0xb6, 0x65, 0xfd, - 0x30, 0xb3, 0x7b, 0x94, 0x48, 0x09, 0x88, 0xd1, 0x97, 0x50, 0x72, 0x2d, 0xc7, 0x63, 0x3d, 0x5d, - 0xa0, 0x3d, 0x95, 0xc3, 0x9a, 0xb1, 0x81, 0xdd, 0xee, 0x5b, 0x8e, 0x47, 0x3b, 0x5e, 0x74, 0xf9, - 0x2f, 0xf9, 0x2a, 0x14, 0x7d, 0x28, 0x51, 0xbf, 0x9d, 0x6e, 0xa7, 0x29, 0xbd, 0x83, 0x00, 0x0a, - 0x3d, 0xa5, 0xf9, 0xa4, 0xf5, 0x42, 0xca, 0xc8, 0xcf, 0xb8, 0x41, 0x15, 0x85, 0xe1, 0x33, 0x28, - 0xeb, 0xd8, 0xf5, 0x0c, 0x93, 0xa9, 0x39, 0x26, 0xe1, 0x17, 0x04, 0x09, 0x0f, 0x91, 0x8a, 0x48, - 0x29, 0xff, 0xed, 0x0c, 0xac, 0x72, 0xc9, 0xea, 0x7b, 0x0e, 0xd6, 0xa6, 0xbf, 0x05, 0xa1, 0x79, - 0x1f, 0x16, 0xc8, 0x72, 0xbb, 0xf5, 0x1c, 0x9d, 0xc9, 0xb8, 0x2c, 0x30, 0xa4, 0xfc, 0xe7, 0x19, - 0xa8, 0xed, 0x62, 0x8f, 0x32, 0x7e, 0x93, 0x4e, 0x84, 0x8b, 0x9c, 0x3d, 0x63, 0x91, 0x7d, 0x11, - 0xc9, 0x09, 0xda, 0xf0, 0x04, 0xa4, 0xb0, 0x13, 0x7c, 0x72, 0xaf, 0x43, 0xcd, 0x9c, 0x4d, 0xd5, - 0xf8, 0x04, 0xe7, 0x95, 0x25, 0x73, 0x36, 0x15, 0x66, 0x16, 0x6d, 0x40, 0x91, 0x10, 0x52, 0xb9, - 0xcf, 0x52, 0x8a, 0x45, 0x73, 0x36, 0x25, 0x83, 0x44, 0xef, 0x41, 0x85, 0xa0, 0xb4, 0xe1, 0x10, - 0xdb, 0x1e, 0xd6, 0x69, 0x9b, 0x79, 0xa5, 0x6c, 0xce, 0xa6, 0x0d, 0x0e, 0x92, 0xff, 0x6d, 0x26, - 0xb0, 0x1e, 0x6f, 0x3c, 0x09, 0x6f, 0x26, 0xfd, 0x82, 0x81, 0xcb, 0x47, 0x0c, 0x1c, 0xba, 0x02, - 0x65, 0xdb, 0x72, 0x3d, 0xd5, 0xb6, 0x26, 0xc6, 0xf0, 0x84, 0x0a, 0x78, 0x51, 0x01, 0x02, 0xea, - 0x51, 0x88, 0xfc, 0x00, 0x56, 0xa3, 0x63, 0x10, 0x4c, 0x20, 0x99, 0x96, 0xcc, 0x29, 0x4a, 0xee, - 0x0e, 0x54, 0x1b, 0xba, 0xfe, 0xdc, 0x19, 0xf9, 0x23, 0xbf, 0x02, 0xb9, 0x23, 0x67, 0xc4, 0xeb, - 0x54, 0xc3, 0x3a, 0x84, 0x84, 0x60, 0xe4, 0x6b, 0x20, 0x31, 0x75, 0x27, 0x54, 0x4a, 0xb3, 0x71, - 0xef, 0xc3, 0x12, 0xd9, 0x32, 0x67, 0x50, 0xdd, 0x63, 0x9a, 0x87, 0x52, 0xf1, 0x6e, 0x9f, 0xd9, - 0x83, 0x63, 0x90, 0xc8, 0xf6, 0xa1, 0x83, 0x17, 0xc2, 0x0a, 0x3e, 0x3f, 0x09, 0xbf, 0x9f, 0x13, - 0x72, 0x3c, 0x7a, 0x00, 0x1b, 0x0e, 0x1e, 0x61, 0x47, 0xc5, 0xc7, 0x06, 0x11, 0xa3, 0xb1, 0xea, - 0x7a, 0x9a, 0x87, 0xa7, 0xd8, 0xf4, 0x5c, 0x6e, 0x36, 0xd7, 0x29, 0x41, 0x93, 0xe3, 0xfb, 0x01, - 0x5a, 0xfe, 0x45, 0x06, 0x56, 0xb8, 0xae, 0x7f, 0xcd, 0xd6, 0x3f, 0x86, 0x15, 0x9b, 0x58, 0x57, - 0xe7, 0x08, 0x27, 0xdb, 0x45, 0x3e, 0x2a, 0x6c, 0x12, 0x49, 0x90, 0xd3, 0x26, 0x13, 0xee, 0x95, - 0x92, 0x9f, 0xf2, 0x75, 0x58, 0xa6, 0xba, 0x28, 0xd2, 0x83, 0xb4, 0xb9, 0xfd, 0x02, 0x90, 0x48, - 0x18, 0x46, 0x48, 0xe7, 0xeb, 0xab, 0xfc, 0x2f, 0x33, 0x80, 0xfa, 0x98, 0xd5, 0x37, 0xb0, 0xeb, - 0x37, 0xf5, 0x19, 0x54, 0x74, 0x3c, 0x32, 0x4c, 0xac, 0xab, 0x2e, 0xf6, 0x88, 0xa7, 0x46, 0x34, - 0xcc, 0xaa, 0xa8, 0xf8, 0x28, 0xb6, 0x8f, 0x3d, 0xa2, 0xf7, 0xfc, 0xdf, 0x2e, 0xba, 0x09, 0x45, - 0x9b, 0xf3, 0xaa, 0x67, 0x69, 0xa5, 0x64, 0xdb, 0x01, 0x05, 0xfa, 0x13, 0x28, 0x6b, 0xae, 0x6b, - 0x8c, 0x4d, 0x36, 0x43, 0x4c, 0x8f, 0x6d, 0xc6, 0x2b, 0x34, 0x02, 0x12, 0x45, 0x24, 0x97, 0xf7, - 0xa8, 0x8a, 0x15, 0x7a, 0xc2, 0x3b, 0xff, 0x53, 0x28, 0x0b, 0x9d, 0xe7, 0x53, 0x90, 0xde, 0x77, - 0x08, 0xfb, 0x2e, 0x1f, 0xc0, 0x3a, 0x5b, 0xf7, 0xb7, 0xc5, 0xd1, 0x5f, 0xd7, 0x6c, 0xb8, 0xae, - 0x18, 0x2e, 0x90, 0xe5, 0x4a, 0xb6, 0xf0, 0x79, 0x38, 0xe1, 0x82, 0x3a, 0xba, 0x90, 0x68, 0x82, - 0x2a, 0x24, 0xbf, 0x33, 0xf3, 0x54, 0x92, 0xdc, 0x85, 0xb5, 0x78, 0x33, 0x5c, 0x32, 0x5e, 0x73, - 0x6e, 0x9e, 0x52, 0x2f, 0x3a, 0x10, 0x59, 0xbf, 0xd7, 0x77, 0xa1, 0x14, 0x08, 0x78, 0xd2, 0x91, - 0x0d, 0xc9, 0x43, 0x2a, 0xf9, 0x7b, 0xdf, 0x89, 0x7e, 0x0b, 0xcc, 0x52, 0x26, 0x78, 0x0b, 0x56, - 0xc9, 0xc8, 0x13, 0xcc, 0xd3, 0xf6, 0xce, 0xd7, 0x6c, 0x31, 0x04, 0x5a, 0x3e, 0x49, 0xaf, 0x31, - 0xac, 0x17, 0xb0, 0x19, 0xe8, 0x2b, 0x41, 0x5e, 0x79, 0xeb, 0x0f, 0x00, 0x42, 0xc1, 0xe5, 0x1c, - 0x4f, 0x13, 0x73, 0x81, 0x5a, 0x9e, 0xc2, 0x25, 0x51, 0x1d, 0xbd, 0x55, 0xe6, 0x29, 0x13, 0xf8, - 0xd7, 0xe0, 0x62, 0xa8, 0x50, 0x92, 0x8d, 0xa5, 0xcc, 0x23, 0xfa, 0x4c, 0x8c, 0xa0, 0xb3, 0x54, - 0x70, 0x37, 0xe2, 0xed, 0xa7, 0x46, 0xcb, 0x3f, 0x87, 0x77, 0xd3, 0xdb, 0xe2, 0xeb, 0xf0, 0x26, - 0xd3, 0xf6, 0x02, 0x36, 0x7d, 0xbd, 0xf6, 0x96, 0x17, 0xe4, 0xe7, 0x34, 0x68, 0x51, 0xec, 0x1f, - 0x8c, 0xb3, 0x43, 0x5a, 0x04, 0x79, 0xdb, 0x72, 0x58, 0x3c, 0x5b, 0x55, 0xe8, 0x6f, 0xb4, 0x09, - 0xc5, 0x89, 0x31, 0xc2, 0x9e, 0xc1, 0x5d, 0xa4, 0x9c, 0x12, 0x94, 0xe5, 0x86, 0x1f, 0x67, 0xbc, - 0x36, 0x7b, 0xf9, 0x21, 0xb3, 0xb6, 0x22, 0x83, 0xd0, 0x43, 0xc9, 0x9c, 0xee, 0xa1, 0xc8, 0x0f, - 0x98, 0x0f, 0xcc, 0x2a, 0xf3, 0x55, 0xb8, 0x06, 0x05, 0x6a, 0xb0, 0x52, 0xe2, 0x6c, 0x4a, 0xc7, - 0xb1, 0xa4, 0xef, 0xec, 0xcc, 0xe1, 0xf5, 0xfb, 0xfe, 0x38, 0x38, 0x87, 0x78, 0x7d, 0x1e, 0x03, - 0x7e, 0x6e, 0xf4, 0xfa, 0x0b, 0x94, 0x72, 0x4a, 0x24, 0x7f, 0xc5, 0xf4, 0x0a, 0x61, 0x1a, 0x71, - 0x22, 0xcf, 0x3f, 0xb5, 0x9f, 0x33, 0x6d, 0x23, 0x70, 0x08, 0x7d, 0x21, 0xc7, 0xd2, 0x92, 0xbe, - 0x90, 0x62, 0x69, 0x0a, 0xc1, 0xc8, 0xbf, 0xc9, 0x00, 0x62, 0x33, 0xfb, 0x73, 0x7c, 0xe0, 0x68, - 0x7e, 0xd3, 0x12, 0xe4, 0x66, 0xce, 0x84, 0x0f, 0x88, 0xfc, 0x24, 0x5e, 0xa4, 0x63, 0xcd, 0x3c, - 0xe6, 0xd1, 0x32, 0xfb, 0x5b, 0x52, 0x80, 0x82, 0x88, 0xa9, 0xa0, 0x27, 0x2c, 0x47, 0xd8, 0x71, - 0xc9, 0x3e, 0xcd, 0xd1, 0x01, 0xfb, 0x45, 0xf4, 0x29, 0xac, 0x99, 0xf8, 0xd8, 0x3b, 0xb4, 0x6c, - 0xd5, 0x73, 0x8c, 0xf1, 0x98, 0xf8, 0x4e, 0xb4, 0x49, 0xee, 0xa9, 0xae, 0x72, 0xec, 0x80, 0x21, - 0x59, 0x77, 0xd0, 0x3d, 0xb8, 0x10, 0xaf, 0xa5, 0xe3, 0x89, 0xc6, 0x1c, 0xd8, 0xaa, 0xb2, 0x12, - 0xad, 0xb4, 0x43, 0x50, 0xf2, 0x3f, 0xca, 0x80, 0xc4, 0xaa, 0xef, 0x39, 0xc1, 0x7e, 0xbc, 0x08, - 0x25, 0x7d, 0x36, 0xb5, 0x43, 0xdb, 0xb7, 0xa0, 0x14, 0x09, 0x80, 0x5a, 0xb8, 0x4d, 0x28, 0x8e, - 0x8c, 0x09, 0x16, 0xac, 0x5c, 0x50, 0x46, 0x3f, 0x81, 0x2a, 0xad, 0x48, 0x0f, 0x5c, 0x8f, 0xb4, - 0x09, 0x0f, 0x00, 0x2a, 0x04, 0xd8, 0xe2, 0x30, 0xf4, 0x11, 0x2c, 0x3b, 0x96, 0x47, 0x63, 0x89, - 0x90, 0x30, 0x4f, 0x09, 0x25, 0x1f, 0xe1, 0x13, 0xcb, 0x2b, 0xb0, 0xcc, 0x65, 0x30, 0xec, 0x9f, - 0xfc, 0x7f, 0x32, 0xd4, 0x87, 0x7e, 0x3c, 0xb5, 0x5f, 0x4f, 0xa4, 0xbe, 0x0a, 0x1c, 0xb2, 0x1c, - 0xd5, 0x8f, 0x37, 0xc2, 0x65, 0x8e, 0xb0, 0xbd, 0xcd, 0x9d, 0x7c, 0xc3, 0x1c, 0xc7, 0x9c, 0xca, - 0x9b, 0xb0, 0x4c, 0x0c, 0x0f, 0x71, 0x57, 0x87, 0xee, 0xc0, 0x98, 0x62, 0x6b, 0xc6, 0xa2, 0x88, - 0x05, 0x25, 0x89, 0x90, 0xb7, 0x41, 0x8a, 0x73, 0x42, 0x8b, 0x90, 0xeb, 0x29, 0x24, 0xe8, 0x2d, - 0x42, 0xbe, 0xd7, 0xed, 0x47, 0xce, 0x21, 0x51, 0x09, 0x16, 0xda, 0xdd, 0xed, 0x46, 0x5b, 0xca, - 0x11, 0xba, 0x46, 0xbb, 0x2d, 0xe5, 0xe5, 0xaf, 0xfc, 0x28, 0xe0, 0x75, 0x87, 0x2d, 0xff, 0xd7, - 0x1c, 0x14, 0xd8, 0x36, 0x40, 0xd7, 0x20, 0xa7, 0x8d, 0x0c, 0xee, 0xd7, 0xac, 0xc6, 0x77, 0xc9, - 0xed, 0xc6, 0xc8, 0x50, 0x08, 0x01, 0xfa, 0x10, 0xf2, 0x2e, 0x21, 0xcc, 0xc6, 0x1d, 0x20, 0x4e, - 0xd8, 0xd7, 0x46, 0x86, 0x42, 0x49, 0xe4, 0x1e, 0xe4, 0x1a, 0x23, 0x03, 0xd5, 0xa0, 0xdc, 0x78, - 0xd2, 0x52, 0xf7, 0x3b, 0xcf, 0x3a, 0xdd, 0x6f, 0x3b, 0x2c, 0xa8, 0x27, 0x80, 0x56, 0x4f, 0xca, - 0xa0, 0x32, 0x2c, 0xb2, 0xdf, 0xf7, 0xa5, 0x2c, 0xaa, 0x42, 0x89, 0x14, 0xda, 0xf7, 0x9e, 0xf7, - 0x3a, 0xd2, 0x06, 0x92, 0x00, 0x48, 0xb1, 0xdb, 0x6b, 0x7c, 0xb3, 0xdf, 0x94, 0xfe, 0xee, 0x9f, - 0x65, 0xe4, 0x5f, 0x67, 0x21, 0x4f, 0x1a, 0x40, 0x12, 0x54, 0xfa, 0x51, 0xa6, 0x21, 0xa4, 0xb5, - 0xdd, 0xa0, 0x93, 0x87, 0x60, 0x89, 0x42, 0xf6, 0xf6, 0xdb, 0x03, 0x06, 0xcb, 0xa2, 0x15, 0xa8, - 0x31, 0x58, 0xaf, 0xdd, 0x57, 0xdb, 0x8d, 0xc7, 0xcd, 0xb6, 0x94, 0x47, 0x6b, 0x80, 0x28, 0xb0, - 0xd9, 0xd9, 0x6e, 0xf4, 0xfa, 0xfb, 0xed, 0xc6, 0xa0, 0xd5, 0xed, 0x48, 0x8b, 0xa4, 0x3b, 0x14, - 0xfe, 0xbc, 0xd7, 0xee, 0x4b, 0x8d, 0xa0, 0xd8, 0x24, 0xbd, 0x7b, 0x82, 0x10, 0x54, 0x43, 0x56, - 0x04, 0xf4, 0x67, 0x19, 0xf4, 0x2e, 0xac, 0x47, 0x60, 0x42, 0xdb, 0x7f, 0x23, 0x83, 0x64, 0xb8, - 0x44, 0xb1, 0x4a, 0x77, 0x7f, 0xd0, 0x54, 0x07, 0x0d, 0x65, 0xb7, 0x39, 0x50, 0xb7, 0xbb, 0x9d, - 0xfe, 0x40, 0x69, 0xb4, 0x3a, 0x83, 0xbe, 0xf4, 0x37, 0x33, 0xe8, 0x22, 0xac, 0x51, 0x9a, 0x27, - 0xed, 0xee, 0xb7, 0x6a, 0xbf, 0xd7, 0xdc, 0x0e, 0x06, 0xf4, 0xb7, 0x32, 0x68, 0x9d, 0x77, 0x34, - 0x44, 0x92, 0x76, 0x7f, 0x99, 0x41, 0x2b, 0x7c, 0xa8, 0xcf, 0x9a, 0xdf, 0xa9, 0xcf, 0x1b, 0xed, - 0xfd, 0xa6, 0xf4, 0xbf, 0x33, 0xf2, 0x5f, 0xe4, 0x00, 0x9e, 0x6b, 0x13, 0x43, 0x67, 0x41, 0xfa, - 0x1d, 0x58, 0xa0, 0xee, 0x10, 0x5f, 0x62, 0xc1, 0x9a, 0x86, 0x44, 0xcc, 0x77, 0x52, 0x18, 0x21, - 0xfa, 0x04, 0x0a, 0x0e, 0xd6, 0xdc, 0xc0, 0x69, 0xb8, 0x98, 0x5a, 0x45, 0xa1, 0x24, 0x0a, 0x27, - 0x45, 0xd7, 0x61, 0x71, 0xaa, 0x79, 0xc3, 0x43, 0x1a, 0xeb, 0xe7, 0x92, 0x1a, 0xd3, 0xc7, 0xa2, - 0x3b, 0x50, 0x99, 0x99, 0xbc, 0xa0, 0x6a, 0xfe, 0x71, 0x53, 0x8c, 0xba, 0x1c, 0x90, 0x34, 0x5c, - 0xf4, 0x39, 0x48, 0x61, 0x8d, 0x09, 0x36, 0xc7, 0xde, 0x61, 0x7d, 0x21, 0xad, 0x56, 0x2d, 0x20, - 0x6b, 0x53, 0x2a, 0xb9, 0x07, 0x0b, 0x74, 0x64, 0x68, 0x09, 0xa0, 0x3f, 0x68, 0x0c, 0x9a, 0x2a, - 0x3f, 0x5f, 0x22, 0xf2, 0xc0, 0xcb, 0x03, 0xf5, 0x49, 0x77, 0xbf, 0xb3, 0x23, 0x65, 0x88, 0xc0, - 0x32, 0xe0, 0xf3, 0x46, 0xbb, 0xb5, 0x23, 0x65, 0xd1, 0x32, 0x54, 0x19, 0xa0, 0xd5, 0x61, 0xa0, - 0x9c, 0xfc, 0x10, 0x0a, 0x6c, 0xe0, 0x84, 0x5a, 0x69, 0x36, 0xfa, 0xdd, 0x81, 0xcf, 0xb3, 0x0a, - 0x25, 0x0a, 0xe8, 0xa8, 0x8d, 0xbe, 0x94, 0x21, 0x95, 0x79, 0xb1, 0xdd, 0xec, 0xec, 0xd2, 0x4b, - 0x85, 0xff, 0xbe, 0x00, 0x79, 0x7a, 0x3a, 0x72, 0x03, 0xf2, 0xe6, 0xc4, 0x31, 0x04, 0x37, 0xdf, - 0x1a, 0x4f, 0xf0, 0x6d, 0xff, 0x2e, 0xef, 0x76, 0xc3, 0x3c, 0x51, 0x28, 0x05, 0xba, 0x09, 0x05, - 0x5b, 0xf3, 0x3c, 0xc7, 0x8f, 0xda, 0xd2, 0x69, 0x39, 0x0d, 0xba, 0x09, 0x39, 0x6d, 0x8c, 0xf9, - 0x79, 0xc7, 0x66, 0x82, 0x74, 0xe0, 0x5f, 0x11, 0x2a, 0x84, 0x8c, 0x68, 0x86, 0x03, 0xec, 0xfa, - 0x67, 0x1e, 0xf4, 0x37, 0x31, 0x55, 0x86, 0xab, 0xbe, 0x34, 0xbc, 0x43, 0xdd, 0xd1, 0x5e, 0xfa, - 0x07, 0x1e, 0x86, 0xfb, 0x2d, 0x87, 0xa0, 0x4f, 0x01, 0x8e, 0x02, 0x21, 0xa8, 0x2f, 0xc6, 0xe3, - 0x94, 0x50, 0x40, 0x14, 0x81, 0x0e, 0xdd, 0x81, 0x55, 0xd3, 0x52, 0x8d, 0xa9, 0x4d, 0x02, 0x4c, - 0x2f, 0xe4, 0x5f, 0x64, 0xb1, 0xb7, 0x69, 0xb5, 0x38, 0x2a, 0x68, 0x27, 0x34, 0xe0, 0xa5, 0x33, - 0x4e, 0x6f, 0x2e, 0x01, 0xb8, 0xd6, 0xcc, 0x19, 0x62, 0x55, 0x73, 0xcd, 0x3a, 0x50, 0x35, 0x57, - 0x62, 0x90, 0x86, 0x6b, 0x12, 0x13, 0xc6, 0xd1, 0x86, 0x5e, 0x2f, 0x33, 0x33, 0xc5, 0x00, 0x2d, - 0x9d, 0x9b, 0x30, 0x0f, 0x3b, 0x58, 0xaf, 0x57, 0x68, 0x5f, 0x82, 0x32, 0x5a, 0xa5, 0x1b, 0x67, - 0x82, 0xeb, 0x55, 0x8a, 0x60, 0x05, 0x74, 0x03, 0x24, 0xc3, 0x55, 0x47, 0x8e, 0x35, 0x55, 0xf1, - 0xb1, 0x87, 0x1d, 0x53, 0x9b, 0xd4, 0x97, 0x28, 0xc1, 0x92, 0xe1, 0x3e, 0x71, 0xac, 0x69, 0x93, - 0x43, 0xc9, 0x54, 0xfa, 0x47, 0xf0, 0xaa, 0x61, 0xd7, 0x6b, 0xb4, 0x69, 0xf0, 0x41, 0x2d, 0x3b, - 0x38, 0x0e, 0x96, 0xc2, 0xe3, 0x60, 0x74, 0x13, 0x90, 0xe1, 0xaa, 0xbe, 0xf1, 0x36, 0x4c, 0x3a, - 0x87, 0xf5, 0x65, 0x76, 0x15, 0x60, 0xb8, 0x1d, 0x86, 0x68, 0x31, 0x38, 0xba, 0x0c, 0x60, 0xe8, - 0xd8, 0xf4, 0x8c, 0x91, 0x81, 0x9d, 0x3a, 0xa2, 0x43, 0x17, 0x20, 0xe8, 0x43, 0x90, 0x26, 0xd6, - 0x50, 0x9b, 0xa8, 0x02, 0xd5, 0x0a, 0xa5, 0xaa, 0x51, 0x78, 0x2b, 0x24, 0x25, 0xbd, 0x9d, 0x38, - 0x86, 0x7a, 0x60, 0x98, 0x9a, 0x73, 0x52, 0x5f, 0xa5, 0x7d, 0x02, 0x02, 0x7a, 0x4c, 0x21, 0xc4, - 0xa2, 0x33, 0x29, 0xf3, 0x49, 0x2e, 0x5c, 0xcd, 0xdd, 0xa8, 0x28, 0x15, 0x06, 0x64, 0x44, 0xf2, - 0x33, 0x28, 0x8b, 0x07, 0x84, 0x6b, 0x50, 0x60, 0x27, 0xc5, 0xdc, 0x28, 0xf1, 0x52, 0x78, 0x42, - 0x9a, 0x3d, 0xed, 0x84, 0x74, 0x0a, 0xcb, 0x89, 0xa3, 0xe7, 0xb9, 0x2c, 0xbf, 0x82, 0xea, 0x84, - 0xd2, 0xa9, 0x96, 0x2d, 0x04, 0x3c, 0xe9, 0xc7, 0xd8, 0x5d, 0x4a, 0xa2, 0x54, 0x26, 0x42, 0x49, - 0xfe, 0x27, 0x79, 0xc8, 0xf7, 0x30, 0x76, 0x48, 0xcc, 0xaf, 0xd9, 0xf6, 0xe4, 0x44, 0x8d, 0x9c, - 0xd5, 0x08, 0x26, 0xaf, 0x41, 0xb0, 0xdc, 0x0f, 0x28, 0x6b, 0x61, 0x01, 0x5d, 0x83, 0xfc, 0xd0, - 0x32, 0x47, 0xfc, 0x24, 0x16, 0x45, 0xef, 0x8e, 0xb6, 0x2d, 0x73, 0xa4, 0x50, 0x3c, 0x7a, 0x08, - 0x55, 0x7c, 0x30, 0xb6, 0xd5, 0xe9, 0x6c, 0xe2, 0x19, 0x87, 0x96, 0xcd, 0x77, 0xec, 0x5a, 0x58, - 0xa1, 0x79, 0x30, 0xb6, 0xf7, 0x38, 0x56, 0xa9, 0x60, 0xa1, 0x84, 0x1a, 0x50, 0x63, 0xde, 0xa4, - 0x83, 0x47, 0x13, 0x3c, 0xf4, 0x2c, 0x87, 0x5f, 0x3a, 0xd4, 0x45, 0x6d, 0x38, 0xf3, 0xb0, 0xe2, - 0xe3, 0x95, 0x25, 0x27, 0x52, 0x46, 0x1f, 0xfa, 0x36, 0x61, 0x21, 0xed, 0x92, 0x2b, 0x62, 0x0c, - 0x6e, 0x40, 0x81, 0x44, 0x40, 0x8e, 0x5b, 0x2f, 0xc4, 0xf7, 0xe1, 0x80, 0xc2, 0x15, 0x8e, 0x27, - 0xd1, 0xb9, 0xe7, 0x68, 0xa6, 0x4b, 0xbd, 0x8d, 0xc5, 0x38, 0xe3, 0x81, 0x8f, 0x52, 0x42, 0x2a, - 0x32, 0xd3, 0x6c, 0x28, 0x3c, 0x90, 0x29, 0xc6, 0x67, 0x9a, 0x8e, 0xa3, 0x4f, 0x91, 0x0a, 0xf3, - 0xa1, 0x59, 0x01, 0xed, 0x80, 0x34, 0x76, 0xb4, 0x21, 0x1e, 0xcd, 0x26, 0xaa, 0x43, 0x94, 0x9a, - 0xe3, 0x71, 0x45, 0x21, 0x84, 0xb8, 0xbb, 0x9c, 0x42, 0x61, 0x04, 0x4a, 0x6d, 0x1c, 0x05, 0xa0, - 0xdb, 0x50, 0xd2, 0x46, 0x86, 0x4a, 0xbc, 0x16, 0xb7, 0x0e, 0x54, 0x16, 0x97, 0x85, 0x65, 0x1e, - 0x19, 0xd4, 0xab, 0x29, 0x6a, 0xec, 0x87, 0x2b, 0xff, 0xb3, 0x3c, 0x94, 0x82, 0xfb, 0xbb, 0x37, - 0x90, 0x93, 0x8f, 0x22, 0x72, 0xb2, 0x9e, 0x72, 0xc7, 0xf8, 0x97, 0x48, 0x58, 0x6e, 0x42, 0xde, - 0x30, 0x47, 0x16, 0x97, 0x95, 0x7a, 0x4a, 0x67, 0x99, 0xc0, 0x50, 0xaa, 0x3f, 0xca, 0x8b, 0x28, - 0x2f, 0x4f, 0xa1, 0x16, 0xbb, 0x6b, 0x9d, 0xab, 0xbf, 0x2e, 0x45, 0x2e, 0x9f, 0xf9, 0x73, 0x95, - 0xf0, 0x8e, 0xfb, 0x3f, 0x64, 0xa0, 0x2c, 0x88, 0x13, 0xfa, 0x0c, 0x4a, 0x86, 0x19, 0x15, 0xbc, - 0xd3, 0xce, 0x49, 0x8a, 0x86, 0xc9, 0x2b, 0x7e, 0x09, 0x55, 0x7c, 0x4c, 0x26, 0xd3, 0xaf, 0x9c, - 0x3d, 0xb3, 0x72, 0x85, 0x55, 0x08, 0x19, 0x18, 0x53, 0x91, 0x41, 0xee, 0x6c, 0x06, 0xac, 0x02, - 0xbf, 0x32, 0xf9, 0x7b, 0x19, 0x28, 0x33, 0x65, 0xde, 0x36, 0xa6, 0xc6, 0x2b, 0x84, 0xea, 0xe8, - 0x3d, 0xa8, 0x4c, 0xb5, 0x63, 0x35, 0xb8, 0xa9, 0x64, 0x21, 0x4d, 0x79, 0xaa, 0x1d, 0xf7, 0xfc, - 0xfb, 0xc8, 0x4f, 0x61, 0xcd, 0xe5, 0xef, 0x36, 0x54, 0xef, 0xd0, 0xc1, 0xee, 0xa1, 0x35, 0xd1, - 0x55, 0x7b, 0xe8, 0xf1, 0xc0, 0x7a, 0xd5, 0xc7, 0x0e, 0x7c, 0x64, 0x6f, 0xe8, 0xc9, 0xff, 0x2b, - 0x0f, 0x45, 0x5f, 0x45, 0x13, 0x43, 0xa7, 0xcd, 0xbc, 0x43, 0xd5, 0xd6, 0x5c, 0xf7, 0xa5, 0xe5, - 0xe8, 0x7c, 0xa1, 0x2a, 0x04, 0xd8, 0xe3, 0x30, 0x74, 0x95, 0x5e, 0x40, 0x0e, 0x1d, 0xc3, 0x16, - 0xde, 0x59, 0x88, 0x20, 0xb4, 0x01, 0x45, 0x66, 0x7b, 0x35, 0xd7, 0x0f, 0xea, 0x69, 0xb9, 0xe1, - 0x12, 0xb3, 0x1c, 0x78, 0x06, 0x7e, 0xd4, 0x96, 0xa7, 0x1c, 0x6a, 0x3e, 0xbc, 0xc1, 0xa3, 0xb7, - 0x75, 0x58, 0xa4, 0x62, 0xa1, 0xb9, 0x3c, 0x76, 0x2f, 0x90, 0x62, 0xc3, 0x8d, 0xc9, 0x4b, 0x21, - 0x26, 0x2f, 0xc4, 0xeb, 0xa1, 0x68, 0x1a, 0xb8, 0x2f, 0xd2, 0x9a, 0x45, 0x02, 0xa0, 0x81, 0x7b, - 0x07, 0x96, 0x1d, 0x3c, 0xb5, 0x8e, 0xb0, 0x6a, 0x3b, 0xc6, 0x91, 0xe6, 0x11, 0xcf, 0x89, 0xee, - 0xa5, 0xc8, 0xe5, 0xad, 0x3f, 0x21, 0xb7, 0x15, 0x4a, 0xdb, 0x63, 0xa4, 0x0d, 0x57, 0xa9, 0x39, - 0x51, 0x00, 0x71, 0x5a, 0xd8, 0xb6, 0x1c, 0x4d, 0x34, 0x5b, 0xd5, 0xb5, 0xa9, 0x6d, 0x98, 0x63, - 0xba, 0xbd, 0x8a, 0x24, 0x90, 0x9f, 0x79, 0xf8, 0xc9, 0x44, 0xb3, 0x77, 0x18, 0x1c, 0x7d, 0x00, - 0x4b, 0x2e, 0x36, 0x75, 0x95, 0x3f, 0x4a, 0xf1, 0x4e, 0xb8, 0xcf, 0x56, 0x25, 0xd0, 0x6d, 0x1f, - 0x88, 0x6e, 0x01, 0x0a, 0xdd, 0xa7, 0xe0, 0x1d, 0x17, 0x73, 0xe0, 0x96, 0x03, 0x2f, 0xca, 0x47, - 0x20, 0x89, 0xdd, 0x5c, 0x55, 0xd8, 0xa9, 0xcb, 0x91, 0x33, 0x42, 0x57, 0xa1, 0xa2, 0x4d, 0x26, - 0xd6, 0x4b, 0x95, 0xc8, 0x82, 0xe6, 0x52, 0x37, 0xae, 0xaa, 0x00, 0x85, 0x75, 0x5f, 0x9a, 0x0d, - 0x17, 0x5d, 0x83, 0x9a, 0x83, 0xed, 0x89, 0x36, 0xc4, 0xaa, 0x3f, 0xc9, 0xcc, 0x95, 0xab, 0x72, - 0x70, 0x2f, 0x98, 0x6b, 0x4d, 0x9f, 0x1a, 0xa6, 0x4a, 0x04, 0x87, 0x3a, 0x72, 0x45, 0xa5, 0x44, - 0x21, 0x3b, 0xd6, 0x4b, 0x53, 0xbe, 0x0b, 0xb5, 0xd8, 0x14, 0x09, 0x37, 0xd9, 0x3c, 0x6a, 0xa7, - 0x11, 0xaf, 0xd2, 0xec, 0xb5, 0x1b, 0xdb, 0x4d, 0x29, 0x2b, 0xff, 0xd3, 0x1c, 0x54, 0x23, 0xba, - 0xfe, 0x77, 0x20, 0x75, 0x82, 0x28, 0xe5, 0x23, 0xa2, 0x74, 0x0d, 0x6a, 0xa1, 0x28, 0xa9, 0xf4, - 0x38, 0x67, 0x81, 0xbd, 0x1b, 0x0a, 0xe4, 0xa9, 0xa3, 0x4d, 0x71, 0x54, 0xa6, 0x0a, 0x31, 0x99, - 0xea, 0xa7, 0xc9, 0xd4, 0x22, 0x95, 0xa9, 0xeb, 0x73, 0xec, 0xdb, 0xeb, 0x0a, 0x56, 0xf1, 0xdc, - 0x82, 0x55, 0x4a, 0x11, 0xac, 0xd7, 0x59, 0xae, 0xff, 0x9b, 0x83, 0xa5, 0xa8, 0xb5, 0xfb, 0x83, - 0x5f, 0xaf, 0xc1, 0xfc, 0xf5, 0xba, 0x31, 0xcf, 0xc4, 0xff, 0x7e, 0x16, 0x8c, 0x84, 0x26, 0x9e, - 0xe5, 0x69, 0x13, 0x95, 0xc5, 0x0c, 0x4c, 0x5b, 0x00, 0x05, 0x91, 0x70, 0xc1, 0x25, 0x7c, 0x38, - 0x81, 0x6f, 0x19, 0xca, 0x8c, 0x0f, 0xa3, 0xe1, 0xc0, 0xd7, 0x59, 0xf8, 0x67, 0x50, 0x11, 0x9d, - 0x2b, 0x54, 0x87, 0x45, 0x76, 0xfc, 0xaa, 0xf3, 0xe7, 0x59, 0x7e, 0x91, 0xda, 0x26, 0x4e, 0xa5, - 0x7a, 0xde, 0x24, 0xb0, 0x4d, 0x1c, 0x36, 0xf0, 0x26, 0xf2, 0x9f, 0x67, 0x60, 0x29, 0xea, 0x6b, - 0x11, 0x73, 0x15, 0x73, 0xcf, 0xd4, 0xe1, 0xc4, 0xf0, 0xef, 0x3e, 0x8a, 0xca, 0x6a, 0xd4, 0x17, - 0xdb, 0xa6, 0x38, 0xf4, 0x10, 0x36, 0x93, 0xb5, 0x66, 0xae, 0x87, 0x9d, 0xf0, 0x2d, 0xca, 0x7a, - 0xbc, 0x26, 0xc5, 0xb7, 0x74, 0xf9, 0x57, 0x8b, 0xcc, 0x87, 0xfd, 0x5d, 0x89, 0xf1, 0x6d, 0x28, - 0x4e, 0xb1, 0xeb, 0x6a, 0x63, 0xec, 0x72, 0xd7, 0x53, 0x88, 0x8b, 0xf6, 0x38, 0x46, 0x09, 0x68, - 0x52, 0x8d, 0xe3, 0xc2, 0x99, 0xc6, 0xb1, 0x70, 0x8a, 0x71, 0x5c, 0x3c, 0xd5, 0x38, 0x16, 0x63, - 0x1b, 0xe3, 0x06, 0x14, 0x7e, 0x9c, 0xe1, 0x19, 0x76, 0x93, 0x07, 0x0f, 0xdf, 0x50, 0xb8, 0xc2, - 0xf1, 0x68, 0x2b, 0x6d, 0x0b, 0x31, 0xe9, 0x3c, 0xe7, 0xc6, 0x28, 0x9f, 0x7b, 0x63, 0x54, 0xd2, - 0x36, 0x46, 0x13, 0xaa, 0x2e, 0x76, 0x5d, 0xc3, 0x32, 0xd9, 0x7b, 0x06, 0x6a, 0xe2, 0x96, 0xee, - 0x5d, 0x4d, 0x09, 0xe7, 0x6e, 0xf7, 0x19, 0x21, 0x73, 0xd5, 0x2b, 0xae, 0x50, 0x42, 0x5f, 0x42, - 0x99, 0x99, 0x37, 0xc6, 0xa4, 0x46, 0x99, 0x5c, 0x4e, 0x63, 0xd2, 0x20, 0x64, 0x8c, 0x05, 0xb3, - 0x88, 0x8c, 0xc1, 0x0a, 0x2c, 0x58, 0x33, 0x4f, 0xfd, 0x91, 0x9e, 0x64, 0x54, 0x95, 0xbc, 0x35, - 0xf3, 0xbe, 0x41, 0xab, 0xb0, 0x30, 0x9a, 0x58, 0xb6, 0x4b, 0x0f, 0x2f, 0xaa, 0x0a, 0x2b, 0xa0, - 0x4f, 0x00, 0xc8, 0xd4, 0x78, 0x58, 0x1d, 0x6a, 0x76, 0x1d, 0x9d, 0x72, 0xa6, 0x55, 0x62, 0x74, - 0xdb, 0x9a, 0x4d, 0x22, 0x05, 0x26, 0x5d, 0xa4, 0xce, 0xca, 0x29, 0x75, 0x98, 0x10, 0x92, 0x2a, - 0x17, 0xa1, 0x44, 0x67, 0x95, 0xee, 0x88, 0x55, 0x76, 0xea, 0xc3, 0x00, 0x2d, 0x5d, 0x36, 0xa1, - 0x22, 0x4e, 0x07, 0xd9, 0xf2, 0xe1, 0x81, 0x72, 0x11, 0xf2, 0xad, 0x9d, 0x76, 0x93, 0x69, 0x82, - 0xed, 0x6e, 0xa7, 0xd3, 0xdc, 0x1e, 0x48, 0x59, 0x7a, 0x78, 0xbd, 0x3d, 0x68, 0x3d, 0x6f, 0x4a, - 0x39, 0x54, 0x81, 0x62, 0xb7, 0xd7, 0xec, 0xf4, 0x9b, 0x9d, 0x81, 0x94, 0x47, 0x35, 0x28, 0x93, - 0xd2, 0x76, 0xb7, 0xf3, 0xa4, 0xa5, 0xec, 0x49, 0x0b, 0x04, 0xd0, 0xec, 0x0f, 0x1a, 0x8f, 0xdb, - 0xad, 0xfe, 0xd3, 0xe6, 0x8e, 0x54, 0x90, 0xb7, 0x00, 0xc2, 0x99, 0x43, 0x05, 0xc8, 0xee, 0xf7, - 0x58, 0x43, 0x3b, 0xa4, 0xc9, 0x0c, 0x7d, 0xed, 0xf6, 0xe4, 0x85, 0x4a, 0xda, 0x91, 0xff, 0x14, - 0x8a, 0xfe, 0xa6, 0x40, 0xb7, 0xa0, 0xe8, 0xe0, 0x21, 0x36, 0x8e, 0xb8, 0xba, 0x89, 0x44, 0x1b, - 0x9c, 0x4a, 0x09, 0x48, 0xd0, 0x07, 0x90, 0x77, 0xfd, 0x47, 0xba, 0xa9, 0xa4, 0x14, 0x2d, 0xff, - 0x45, 0x16, 0x16, 0x39, 0x04, 0xc9, 0x50, 0x31, 0x2d, 0xcf, 0x18, 0xf9, 0xef, 0x85, 0xd9, 0x3b, - 0xaf, 0x08, 0x8c, 0x44, 0x2c, 0x33, 0xfa, 0x72, 0x95, 0xbf, 0xf1, 0xe2, 0x25, 0x84, 0x20, 0x6f, - 0xd9, 0xd8, 0xe4, 0x37, 0x3b, 0xf4, 0x37, 0x7a, 0x17, 0x4a, 0x3f, 0x60, 0x6c, 0x6b, 0x13, 0xe3, - 0x08, 0xf3, 0x9b, 0x9c, 0x10, 0x40, 0xb4, 0xa7, 0x83, 0x47, 0xc4, 0xef, 0xa6, 0x3b, 0x3a, 0xaf, - 0xf8, 0x45, 0x52, 0x4f, 0x37, 0xdc, 0xa1, 0xe6, 0xe8, 0x58, 0xa7, 0x7b, 0x39, 0xaf, 0x84, 0x00, - 0x22, 0x4a, 0x54, 0x93, 0xd3, 0x9d, 0x9c, 0x57, 0x58, 0x01, 0x5d, 0x87, 0x9a, 0x7f, 0x8e, 0xa8, - 0xf2, 0x0e, 0x16, 0xd9, 0x33, 0x35, 0x1f, 0xcc, 0x1e, 0xdc, 0x46, 0x08, 0x79, 0xec, 0x55, 0x8a, - 0x12, 0x32, 0x13, 0x21, 0xdf, 0x87, 0x02, 0xdb, 0xe2, 0xa4, 0x45, 0xc3, 0xb4, 0x67, 0x4c, 0x0d, - 0x57, 0x15, 0x56, 0x20, 0x33, 0x61, 0xcd, 0x3c, 0x02, 0x66, 0xda, 0x9d, 0x97, 0x64, 0x0c, 0x05, - 0x16, 0xdb, 0xa2, 0xdb, 0x50, 0x20, 0x31, 0xbb, 0x31, 0xe6, 0xeb, 0xb5, 0x16, 0x8f, 0x7e, 0xb7, - 0x29, 0x56, 0xe1, 0x54, 0xe8, 0x23, 0xff, 0x20, 0x26, 0x1b, 0x8f, 0x64, 0x19, 0xb9, 0x78, 0x14, - 0x23, 0xff, 0xfb, 0x0c, 0x54, 0x44, 0x2e, 0x44, 0x79, 0x0f, 0x2d, 0xd3, 0xc4, 0x43, 0x4f, 0x75, - 0xb0, 0xe7, 0x9c, 0xf8, 0xcb, 0xc7, 0x81, 0x0a, 0x81, 0x91, 0x9d, 0x40, 0x63, 0x20, 0x7a, 0xaf, - 0xcd, 0x56, 0xb0, 0x48, 0x00, 0x84, 0x13, 0x71, 0xb2, 0x83, 0xe5, 0x89, 0xdf, 0xd5, 0x2d, 0x07, - 0x98, 0xe0, 0xc2, 0x6e, 0x07, 0x2e, 0x4f, 0x0d, 0xd3, 0x98, 0xce, 0xa6, 0xaa, 0xe6, 0x7f, 0xf1, - 0x40, 0x22, 0xbc, 0xf8, 0xed, 0xdd, 0xbb, 0x9c, 0xaa, 0x21, 0x12, 0x05, 0x37, 0x79, 0xff, 0x23, - 0x0b, 0x65, 0x61, 0x78, 0x7f, 0xa0, 0xc3, 0xa0, 0x67, 0xda, 0x78, 0x6c, 0x79, 0x86, 0xe6, 0x61, - 0x5d, 0x0d, 0x3b, 0xc7, 0x44, 0x1b, 0x85, 0xb8, 0xa7, 0x7e, 0x37, 0xef, 0x91, 0x9d, 0x44, 0x69, - 0x0a, 0x67, 0x9e, 0xd0, 0x73, 0x4a, 0x74, 0x1f, 0x8a, 0x24, 0xea, 0xa0, 0xb5, 0x16, 0xcf, 0xac, - 0x15, 0xd0, 0xca, 0xff, 0x2f, 0x03, 0xa5, 0xe0, 0x0c, 0x85, 0x4c, 0x31, 0xb7, 0xcf, 0x91, 0x4b, - 0xc2, 0x0a, 0x33, 0xd2, 0xdc, 0x9c, 0x5e, 0x02, 0x60, 0x44, 0xc2, 0x7d, 0x21, 0x53, 0xbc, 0x3d, - 0xce, 0x63, 0xea, 0xcd, 0x54, 0xb2, 0x2d, 0xad, 0x23, 0xec, 0x9c, 0xf0, 0x7b, 0xf8, 0xca, 0xd4, - 0x9b, 0xed, 0xf8, 0x30, 0xe2, 0x06, 0x11, 0x57, 0x82, 0xac, 0xc3, 0xd4, 0xd2, 0xfd, 0x5b, 0xea, - 0x32, 0x87, 0xed, 0x59, 0x3a, 0x26, 0xc6, 0x8d, 0x9b, 0x80, 0xa8, 0x79, 0xaf, 0x32, 0xa8, 0xdf, - 0x9b, 0x2b, 0x50, 0xe6, 0x64, 0xb4, 0x3b, 0xcc, 0xc0, 0x73, 0xe3, 0x41, 0xfb, 0xb3, 0x0e, 0x8b, - 0xde, 0xd0, 0x56, 0xa7, 0xae, 0xcb, 0x03, 0xdc, 0x82, 0x37, 0xb4, 0xf7, 0x5c, 0x57, 0x7e, 0x04, - 0x65, 0xe1, 0x1c, 0x08, 0xdd, 0x86, 0x15, 0xf1, 0xd0, 0x28, 0xea, 0x60, 0x2d, 0x0b, 0x87, 0x44, - 0xcc, 0xbb, 0x92, 0xff, 0x79, 0x0e, 0x6a, 0xb1, 0x93, 0xa0, 0xd3, 0xfd, 0x3e, 0x7e, 0x9e, 0x14, - 0x8a, 0x66, 0x55, 0x29, 0x73, 0x18, 0x5d, 0xf6, 0x2b, 0x50, 0x3e, 0xc4, 0x13, 0x1b, 0x3b, 0xaa, - 0x65, 0x4e, 0xfc, 0x69, 0x03, 0x06, 0xea, 0x9a, 0x13, 0x7a, 0xb4, 0xae, 0xe3, 0x11, 0x76, 0x1c, - 0x6d, 0xc2, 0x98, 0x30, 0x7f, 0xbf, 0xe2, 0x03, 0x29, 0x97, 0xbb, 0xb0, 0x2a, 0xaa, 0x65, 0xd5, - 0xef, 0x0f, 0xbb, 0xa2, 0x59, 0x11, 0x71, 0x4d, 0xde, 0xb7, 0x8f, 0x60, 0x79, 0x62, 0x99, 0x63, - 0x22, 0xfb, 0x7a, 0x40, 0x5f, 0x60, 0x3e, 0x47, 0x80, 0xf0, 0x89, 0xb7, 0x60, 0x99, 0xde, 0x70, - 0xa8, 0x74, 0x46, 0x5c, 0x35, 0x90, 0xb8, 0xaa, 0x52, 0xa3, 0x08, 0x3a, 0xa7, 0xf4, 0x26, 0x9b, - 0xd0, 0x52, 0x07, 0x2a, 0x32, 0x72, 0xe6, 0x48, 0xd1, 0xd0, 0x44, 0x11, 0x46, 0x7f, 0x9d, 0x47, - 0x2b, 0x9c, 0x36, 0x3c, 0x19, 0x58, 0x12, 0x28, 0x89, 0xd3, 0x13, 0x5c, 0x56, 0x08, 0x94, 0x40, - 0x29, 0xd9, 0x65, 0x85, 0x40, 0x8a, 0x20, 0x4f, 0xa5, 0x8b, 0x9d, 0x06, 0xd0, 0xdf, 0xf2, 0x27, - 0xb0, 0xbe, 0x67, 0xc7, 0xd6, 0x8d, 0xeb, 0xc9, 0xb9, 0xab, 0x27, 0xff, 0xbb, 0x0c, 0xac, 0x25, - 0x6a, 0x31, 0xad, 0x34, 0x7f, 0xc9, 0x37, 0x05, 0xb3, 0xcc, 0x5e, 0x68, 0x85, 0x36, 0xf8, 0x32, - 0x80, 0x16, 0x7e, 0x23, 0xc6, 0x97, 0x3a, 0x84, 0xa0, 0x5b, 0xb0, 0x42, 0x1c, 0x3b, 0x6b, 0xa4, - 0x3a, 0xc6, 0x81, 0x1a, 0xb0, 0xc9, 0xfb, 0x1f, 0x93, 0xe9, 0xdd, 0x91, 0x62, 0x1c, 0x28, 0xa1, - 0x49, 0xaf, 0x09, 0xe4, 0xd4, 0xba, 0xb3, 0xf5, 0xae, 0xf8, 0xa4, 0x7d, 0x22, 0xb2, 0xbf, 0xcc, - 0xc0, 0x72, 0x62, 0x18, 0xe8, 0x67, 0x31, 0x63, 0xf4, 0x9e, 0xe0, 0x11, 0xa4, 0xcf, 0x54, 0x60, - 0x97, 0xee, 0x47, 0xed, 0xd2, 0xd5, 0x53, 0x6a, 0x46, 0x4c, 0x54, 0x1f, 0xaa, 0xfc, 0x14, 0x94, - 0x4f, 0xfd, 0xf9, 0x0f, 0xf7, 0x84, 0xf9, 0xce, 0x46, 0x17, 0xe9, 0xd7, 0x19, 0xa8, 0x70, 0xae, - 0x7d, 0xff, 0x4e, 0xe2, 0x4d, 0x99, 0x46, 0x16, 0x91, 0x19, 0x8a, 0x70, 0x11, 0x37, 0xa1, 0x18, - 0x3c, 0x5c, 0x67, 0x96, 0x20, 0x28, 0xc7, 0x16, 0x98, 0xe9, 0x7a, 0x01, 0x22, 0xff, 0x83, 0x1c, - 0x5c, 0xe4, 0xda, 0x67, 0xc2, 0x9e, 0xd3, 0xb1, 0xeb, 0x25, 0xdf, 0x66, 0xdf, 0x04, 0xa4, 0x4d, - 0x5e, 0x6a, 0x27, 0x2e, 0x71, 0xee, 0x6d, 0xcd, 0xc1, 0xea, 0x34, 0x90, 0x30, 0x89, 0x61, 0xb6, - 0x19, 0x62, 0x0f, 0xeb, 0xe8, 0x2e, 0x5c, 0x30, 0xc6, 0xa6, 0xe5, 0x90, 0xd0, 0x82, 0x86, 0xbf, - 0xfe, 0xfd, 0x37, 0x7f, 0xb4, 0xcc, 0x90, 0x0d, 0x97, 0xc4, 0xc1, 0xec, 0xce, 0x9b, 0x04, 0x87, - 0xfe, 0xc5, 0x64, 0xd0, 0x44, 0xe8, 0x0a, 0x33, 0x89, 0x5c, 0xf7, 0x29, 0x78, 0x53, 0x0a, 0xf7, - 0x8c, 0xd1, 0x03, 0xd8, 0x08, 0xc6, 0xa2, 0x1a, 0xa6, 0x36, 0xf4, 0x88, 0x26, 0x67, 0x1a, 0x81, - 0x0b, 0xe9, 0x7a, 0x40, 0xd0, 0xe2, 0x78, 0xa6, 0x18, 0x88, 0x9a, 0x63, 0x93, 0xab, 0x6a, 0xc6, - 0xd8, 0xf6, 0xaf, 0x8e, 0xf9, 0xf7, 0x91, 0xc6, 0xd8, 0x46, 0x0f, 0x60, 0x93, 0x0f, 0xc6, 0xc4, - 0xc7, 0x9e, 0x4a, 0x2f, 0x38, 0xc7, 0xb6, 0x3a, 0xc5, 0x9e, 0x63, 0x0c, 0xb9, 0x5e, 0x5a, 0x63, - 0x14, 0x1d, 0x7c, 0xec, 0x3d, 0xb5, 0xec, 0xd6, 0xd8, 0xde, 0xa3, 0x58, 0xf4, 0x08, 0x2e, 0xea, - 0xec, 0xf5, 0x8f, 0x7a, 0x80, 0x5d, 0x8f, 0xcd, 0x85, 0xeb, 0x4f, 0x31, 0xd5, 0x53, 0x45, 0xa5, - 0xce, 0x49, 0x1e, 0x63, 0xf6, 0xb9, 0x48, 0xb0, 0x04, 0xf2, 0xdf, 0xcf, 0xc1, 0x66, 0xea, 0xaa, - 0x30, 0x81, 0xfa, 0xe3, 0xa2, 0xfc, 0x5e, 0x16, 0x25, 0x03, 0x17, 0x52, 0x17, 0x05, 0x3d, 0x8a, - 0x69, 0xae, 0x0f, 0x12, 0x37, 0x3c, 0x69, 0x7b, 0x2b, 0xd0, 0x5e, 0x0f, 0xa2, 0xda, 0xeb, 0xfd, - 0x33, 0x6a, 0x47, 0x34, 0xd8, 0x3d, 0x58, 0xdb, 0x77, 0x31, 0x3d, 0xf0, 0xb1, 0x27, 0xf4, 0xb3, - 0x32, 0xf7, 0x4c, 0x2b, 0x72, 0x17, 0x2e, 0xc4, 0xeb, 0x9c, 0x61, 0x43, 0xe4, 0xef, 0x01, 0x9a, - 0x07, 0x63, 0x9b, 0xb3, 0xde, 0x82, 0x65, 0x76, 0x54, 0x3d, 0xe5, 0x3c, 0x54, 0xcd, 0xe5, 0x35, - 0x6a, 0x14, 0xe1, 0xf3, 0x6e, 0xb8, 0xd4, 0x0d, 0xd3, 0x8e, 0xa9, 0xf3, 0xea, 0xdf, 0xa1, 0x53, - 0x67, 0x81, 0x03, 0x69, 0xeb, 0xf2, 0x5f, 0x85, 0x12, 0x61, 0xcf, 0x7a, 0xf1, 0xd6, 0xb9, 0xab, - 0x90, 0x27, 0xdc, 0xd1, 0xcd, 0xd8, 0x32, 0xad, 0x46, 0xaf, 0x24, 0x63, 0xab, 0xf2, 0x61, 0x74, - 0x55, 0x56, 0xa2, 0xc4, 0x91, 0x45, 0xb8, 0x0b, 0xd0, 0x0a, 0x67, 0x27, 0xd1, 0xa7, 0x4c, 0x4a, - 0x9f, 0xee, 0x40, 0xa9, 0x15, 0x8c, 0xf8, 0x5c, 0x35, 0x54, 0xc8, 0xb7, 0xce, 0x18, 0x45, 0xeb, - 0x55, 0x46, 0xd1, 0x8a, 0x8f, 0xe2, 0x37, 0x19, 0x90, 0xe2, 0x72, 0x81, 0x3e, 0x8f, 0xb5, 0x26, - 0x98, 0xd6, 0x74, 0xb9, 0x0b, 0x5a, 0xfe, 0x69, 0xb4, 0xe5, 0x2b, 0xf3, 0x2b, 0x46, 0x2e, 0xf0, - 0x65, 0xc8, 0xe3, 0x83, 0xb1, 0x9d, 0xfc, 0xdc, 0x92, 0xcc, 0xba, 0x42, 0x71, 0x84, 0xc6, 0x20, - 0x34, 0x89, 0x8f, 0x17, 0x5b, 0x94, 0x86, 0xe0, 0xe4, 0xc7, 0xdc, 0xae, 0x0d, 0x34, 0x67, 0x8c, - 0xbd, 0x3d, 0x3c, 0x3d, 0xc0, 0x8e, 0x7b, 0x68, 0x08, 0x8b, 0x14, 0xf5, 0x61, 0x33, 0x49, 0x1f, - 0x56, 0x6e, 0x70, 0x2d, 0x1c, 0xe7, 0x11, 0xac, 0xda, 0xd9, 0x2c, 0x02, 0xa5, 0x11, 0xe7, 0x71, - 0xa6, 0xd2, 0x48, 0xef, 0xf8, 0x79, 0x95, 0x46, 0x6a, 0x97, 0xfd, 0x95, 0xfe, 0x1e, 0x2e, 0xb7, - 0x2d, 0x73, 0xdc, 0x26, 0xde, 0xc3, 0x2b, 0xba, 0xa0, 0xe7, 0x08, 0x20, 0xe4, 0xff, 0x96, 0x81, - 0x4b, 0xf3, 0xf8, 0xff, 0x36, 0x9d, 0xd5, 0x54, 0x37, 0x3f, 0x9f, 0xee, 0xe6, 0x3f, 0x84, 0xcd, - 0x04, 0xad, 0xa3, 0xe2, 0x63, 0xdb, 0x70, 0x82, 0x20, 0x65, 0x3d, 0x56, 0xc9, 0x69, 0x32, 0xb4, - 0xfc, 0x0f, 0x33, 0x50, 0x9f, 0x37, 0x40, 0xf4, 0x55, 0x6c, 0x5d, 0x85, 0xeb, 0x89, 0xd3, 0x27, - 0x3d, 0x58, 0xda, 0x47, 0xd1, 0xa5, 0xbd, 0x7e, 0x36, 0x83, 0xc8, 0xea, 0xfe, 0xab, 0x05, 0x58, - 0xe4, 0xfe, 0x27, 0x7a, 0x06, 0x2b, 0x53, 0x5b, 0x4d, 0x3c, 0x25, 0x60, 0x3d, 0xbb, 0x78, 0x8a, - 0x9b, 0xac, 0x2c, 0x4f, 0x13, 0x0e, 0xfa, 0xc7, 0xc1, 0xc8, 0x12, 0x0f, 0x41, 0x22, 0x5e, 0x74, - 0x30, 0x90, 0x9b, 0xfe, 0x40, 0x12, 0x4f, 0x40, 0x44, 0xff, 0xd8, 0xdf, 0xf9, 0xf1, 0xf7, 0x29, - 0xf9, 0x73, 0xbf, 0x4f, 0xf9, 0x16, 0xd6, 0xfd, 0x90, 0x99, 0x9b, 0x4a, 0xfe, 0xaa, 0xca, 0xe5, - 0xaf, 0x40, 0xae, 0x9c, 0x61, 0x52, 0x95, 0x0b, 0x4e, 0xaa, 0x61, 0x7f, 0x0a, 0x68, 0xe6, 0xe2, - 0xd0, 0x10, 0x31, 0xed, 0x5c, 0x88, 0xbf, 0x20, 0x88, 0x2b, 0x34, 0x45, 0x9a, 0xc5, 0xf5, 0xe8, - 0x03, 0xa8, 0xb2, 0xb3, 0x3c, 0x75, 0x62, 0x4c, 0x0d, 0xcf, 0xe5, 0x87, 0x23, 0xc2, 0xe8, 0x84, - 0x37, 0x06, 0x4a, 0xc5, 0x0e, 0x0b, 0x6e, 0x38, 0x3c, 0x8f, 0x6e, 0x6a, 0x75, 0x1a, 0xec, 0x6a, - 0xfe, 0xa2, 0xe4, 0xca, 0x19, 0x9b, 0x9f, 0x0f, 0x2f, 0xa1, 0x82, 0x34, 0xb8, 0x48, 0xe2, 0x6a, - 0x95, 0x45, 0xdc, 0x73, 0x1e, 0x9c, 0xc8, 0x67, 0x8b, 0x9f, 0x52, 0x9f, 0xcc, 0xdb, 0x0d, 0x1f, - 0x43, 0x49, 0xd3, 0x75, 0xe1, 0x2a, 0x2c, 0x72, 0x9f, 0xc2, 0x3f, 0x6d, 0x76, 0x95, 0xa2, 0xc6, - 0x7f, 0xc9, 0xcd, 0xe0, 0x5b, 0x7e, 0xc1, 0x91, 0xe1, 0x2a, 0xc0, 0x57, 0x16, 0xbc, 0x88, 0x36, - 0xa0, 0x48, 0xef, 0x1d, 0xa6, 0xda, 0x31, 0xd7, 0x43, 0x8b, 0xa4, 0xbc, 0xa7, 0x1d, 0xcb, 0x3b, - 0xf4, 0xa1, 0x7d, 0xd4, 0xb7, 0x79, 0x75, 0x2e, 0x3f, 0x40, 0xd1, 0xe7, 0x82, 0xee, 0xc4, 0xf6, - 0x75, 0x3d, 0x39, 0x8c, 0x98, 0xf8, 0xdf, 0x8a, 0xee, 0xe3, 0xf5, 0x64, 0x85, 0xc8, 0xbe, 0x9d, - 0x41, 0x81, 0x3f, 0x1a, 0xbc, 0x08, 0x25, 0xc3, 0x56, 0x23, 0xef, 0x6e, 0x8a, 0x86, 0xff, 0xa2, - 0xf0, 0x1a, 0xd4, 0xa6, 0x9a, 0xfb, 0x03, 0x77, 0xe2, 0xd5, 0x29, 0xcf, 0xe0, 0x50, 0x55, 0xaa, - 0x04, 0xcc, 0x1c, 0xf8, 0x3d, 0xc3, 0x4c, 0xd0, 0x69, 0xc7, 0xfc, 0xaa, 0x4b, 0xa4, 0xd3, 0x8e, - 0xe5, 0x5f, 0x65, 0x00, 0xc2, 0xcf, 0xf5, 0xde, 0xee, 0x17, 0x84, 0x04, 0x36, 0x31, 0x5c, 0x8f, - 0xbe, 0xb1, 0x2e, 0x29, 0xf4, 0x37, 0xfd, 0xb6, 0x33, 0xfa, 0xf1, 0xbe, 0x14, 0xdf, 0x05, 0xe1, - 0x17, 0xfb, 0xb2, 0x02, 0xc5, 0x3d, 0xcd, 0x1b, 0x1e, 0x92, 0xbe, 0xdd, 0x03, 0xa0, 0x0f, 0xa6, - 0xe7, 0x7c, 0x6a, 0x4d, 0xe9, 0xd8, 0xa7, 0xd6, 0x53, 0xff, 0x67, 0xea, 0x77, 0x8d, 0x43, 0xa8, - 0xc4, 0xc2, 0x9d, 0x32, 0x9f, 0x25, 0x81, 0xb1, 0xb0, 0xbf, 0x45, 0x62, 0xca, 0x1f, 0x26, 0xc1, - 0x6f, 0xb4, 0x06, 0x05, 0x21, 0x9e, 0xaa, 0x2a, 0xbc, 0x24, 0xff, 0xc7, 0x05, 0x80, 0x6d, 0xcb, - 0xd4, 0x0d, 0xa6, 0x4a, 0xee, 0x02, 0x70, 0x05, 0x10, 0x7e, 0x30, 0x89, 0x62, 0x7d, 0xef, 0x63, - 0x4f, 0x29, 0x31, 0x2a, 0x32, 0xdc, 0x9f, 0x42, 0x25, 0xb8, 0x5a, 0x24, 0x95, 0xb2, 0x73, 0x2b, - 0x05, 0x2f, 0x77, 0x49, 0xb5, 0x3f, 0x81, 0xa5, 0x58, 0xa0, 0x97, 0x54, 0xbf, 0xc2, 0x80, 0x94, - 0x8a, 0x26, 0xce, 0xc5, 0x3d, 0x28, 0xfb, 0xb5, 0x49, 0x9b, 0xf9, 0xf9, 0x1d, 0x65, 0xd5, 0x48, - 0x8b, 0x9f, 0x05, 0x79, 0x5c, 0xbc, 0x13, 0x5a, 0x6b, 0x61, 0x6e, 0xad, 0x4a, 0x40, 0x48, 0x2a, - 0x7e, 0x01, 0xcb, 0x24, 0x8a, 0x8b, 0x56, 0x2e, 0xcc, 0xad, 0x5c, 0xc3, 0xc7, 0xde, 0xb6, 0x58, - 0xff, 0x0a, 0x94, 0x1d, 0xfb, 0x07, 0x83, 0x68, 0xac, 0xd9, 0x84, 0xbd, 0xca, 0x5b, 0x50, 0xc0, - 0x61, 0x9f, 0x9d, 0xcd, 0x26, 0x1e, 0x7a, 0x04, 0x10, 0x7e, 0xca, 0xc4, 0xdf, 0x0c, 0x09, 0x57, - 0x85, 0xe1, 0xfa, 0x70, 0xc5, 0x49, 0x85, 0x27, 0xf8, 0xd2, 0x09, 0x3d, 0x86, 0x95, 0x09, 0x51, - 0x9a, 0xb1, 0x1e, 0x96, 0xe6, 0xf6, 0x70, 0x99, 0x92, 0x47, 0xfa, 0x78, 0x1d, 0xa4, 0x30, 0x54, - 0x35, 0x55, 0xba, 0x1d, 0x80, 0x6e, 0x87, 0xaa, 0xc9, 0x23, 0x54, 0xb3, 0x4d, 0xf6, 0xc5, 0x1d, - 0x28, 0xfb, 0xaf, 0xf5, 0x54, 0xc3, 0xac, 0x97, 0xe3, 0x5b, 0x83, 0x9f, 0x15, 0x95, 0xf8, 0x73, - 0xbd, 0x96, 0x29, 0x1f, 0x42, 0x29, 0xe8, 0x36, 0x5a, 0x81, 0x1a, 0xff, 0x62, 0xe3, 0xbb, 0x5e, - 0xf0, 0xe1, 0xc0, 0x3a, 0xac, 0x08, 0xc0, 0x56, 0x67, 0xd0, 0x54, 0x3a, 0x8d, 0xb6, 0x94, 0x89, - 0x21, 0x9a, 0x2f, 0x38, 0x22, 0x8b, 0x56, 0x41, 0x12, 0x10, 0xfc, 0x63, 0x1e, 0xd9, 0x85, 0x5a, - 0x30, 0xa8, 0x06, 0xcb, 0x46, 0xf4, 0x05, 0x94, 0x35, 0x66, 0x6b, 0x85, 0x4d, 0x73, 0x49, 0x9c, - 0xdb, 0x08, 0x3d, 0xdb, 0x37, 0x5a, 0xf0, 0x1b, 0x5d, 0x85, 0xb2, 0x3f, 0xab, 0x46, 0xf0, 0x95, - 0x99, 0x08, 0x92, 0xff, 0x0a, 0x94, 0xf6, 0xb0, 0xce, 0x9b, 0xfb, 0x3c, 0xad, 0xb9, 0x75, 0xf1, - 0xd2, 0x50, 0x9f, 0xd3, 0xd0, 0x2a, 0x2c, 0x1c, 0x69, 0x93, 0x19, 0x53, 0x01, 0x39, 0x85, 0x15, - 0x64, 0x15, 0x6a, 0x0d, 0xb7, 0xe7, 0x60, 0x1b, 0x9b, 0x7e, 0x13, 0x12, 0xe4, 0x34, 0xd7, 0xe4, - 0x6e, 0x3c, 0xf9, 0x49, 0xf6, 0x36, 0xa1, 0xd0, 0x82, 0x1b, 0x34, 0x56, 0x42, 0x32, 0x54, 0x89, - 0x5f, 0x30, 0xc1, 0x23, 0x4f, 0x9d, 0x5a, 0xae, 0xff, 0x8d, 0x5f, 0x79, 0xe6, 0xe2, 0x36, 0x1e, - 0x79, 0x7b, 0x96, 0xeb, 0xc9, 0x8f, 0xa0, 0xca, 0x9f, 0xbf, 0x73, 0xf6, 0xa7, 0x7e, 0xf3, 0xe4, - 0xe2, 0xc9, 0x88, 0x3b, 0xbc, 0xf4, 0xb7, 0x7c, 0x1d, 0x6a, 0x6d, 0x7a, 0x97, 0xe1, 0xe0, 0x11, - 0x67, 0x10, 0x0c, 0x84, 0xdf, 0xf2, 0xb1, 0x81, 0xfc, 0xa7, 0x1c, 0x2c, 0x32, 0x02, 0x37, 0x7c, - 0x70, 0xca, 0x86, 0x9f, 0x54, 0xde, 0x54, 0x5c, 0x18, 0x35, 0x7f, 0x70, 0xca, 0x79, 0x7f, 0x06, - 0xa5, 0xf0, 0xf6, 0x3e, 0x1b, 0x7f, 0x69, 0x1a, 0x5b, 0x4b, 0x25, 0xa4, 0x45, 0x1f, 0x40, 0x6e, - 0xca, 0xbd, 0xf1, 0x48, 0x78, 0x19, 0xac, 0x87, 0x42, 0xf0, 0xe8, 0x73, 0x00, 0xa2, 0x56, 0xd8, - 0x7c, 0x73, 0xad, 0xb2, 0x11, 0x51, 0x48, 0xe2, 0x52, 0x50, 0xe5, 0xc2, 0x00, 0xe8, 0x0b, 0xa8, - 0x46, 0x74, 0x04, 0x57, 0x2e, 0xa7, 0xf4, 0xae, 0x22, 0xaa, 0x09, 0x74, 0x17, 0x16, 0xf9, 0xf7, - 0x09, 0x5c, 0xb3, 0x08, 0x42, 0x13, 0x59, 0x20, 0xc5, 0xa7, 0x23, 0x9d, 0xe5, 0x37, 0x4b, 0x0e, - 0x1e, 0x71, 0x4f, 0x6d, 0x43, 0x74, 0x83, 0x22, 0xeb, 0xe2, 0x5f, 0x3a, 0x39, 0x78, 0x84, 0x1e, - 0x43, 0x2d, 0xa6, 0x30, 0xb8, 0x8b, 0x76, 0x4a, 0x77, 0x97, 0xa2, 0x3a, 0x43, 0xfe, 0x45, 0x06, - 0x4a, 0xc1, 0xc7, 0xe1, 0xa9, 0x5f, 0x4a, 0x7f, 0x0a, 0x30, 0x0c, 0x34, 0x17, 0x5f, 0xad, 0xd5, - 0x34, 0xad, 0xa6, 0x08, 0x74, 0xe8, 0x23, 0x58, 0x64, 0x62, 0xe1, 0xf2, 0xd5, 0x12, 0xdf, 0x02, - 0x33, 0x84, 0xe2, 0x53, 0xc8, 0xdf, 0x40, 0x81, 0x3b, 0xd7, 0x69, 0x1d, 0xf8, 0x04, 0x20, 0x92, - 0x91, 0x22, 0x37, 0xef, 0xd3, 0x76, 0x81, 0x8c, 0x9e, 0x2f, 0xc4, 0xdf, 0xda, 0xbe, 0xd5, 0x0f, - 0xc1, 0x23, 0x59, 0x23, 0xf2, 0xe7, 0xc8, 0x1a, 0xb1, 0xa4, 0xe3, 0x91, 0x36, 0x9b, 0x78, 0xfe, - 0x76, 0x59, 0x38, 0x6d, 0xbb, 0x54, 0x39, 0x31, 0x2b, 0xca, 0x47, 0x50, 0x25, 0xd8, 0xf0, 0xbb, - 0xc8, 0xdf, 0x4d, 0xae, 0x0b, 0xf9, 0xef, 0x64, 0x20, 0xa7, 0x58, 0x1a, 0x5a, 0x82, 0xac, 0xe6, - 0x1f, 0x14, 0x65, 0x35, 0x9a, 0x3e, 0x90, 0x79, 0x0e, 0x13, 0xec, 0x3b, 0x84, 0x21, 0x80, 0x28, - 0xb2, 0xa9, 0x46, 0x51, 0xcc, 0x07, 0xe4, 0x25, 0xe1, 0x79, 0x77, 0x3e, 0xf2, 0xbc, 0xdb, 0xff, - 0x32, 0x24, 0x61, 0xc8, 0x95, 0xde, 0xb3, 0x56, 0xf8, 0xd8, 0x5f, 0xfe, 0x17, 0x19, 0xc8, 0x3d, - 0x77, 0x46, 0xa9, 0xcb, 0xf8, 0x3e, 0x64, 0x1d, 0x5d, 0x90, 0xce, 0xe4, 0xfb, 0x97, 0xac, 0xa3, - 0xa3, 0xbb, 0x50, 0xe2, 0xef, 0xb3, 0x1d, 0x8f, 0x7f, 0x8a, 0x37, 0xe7, 0xb1, 0x0c, 0x23, 0x53, - 0x68, 0x86, 0x07, 0xfe, 0x26, 0xdc, 0xf1, 0xf8, 0x3a, 0xcf, 0xa9, 0xc2, 0xc8, 0x14, 0x8f, 0xcc, - 0x16, 0x4f, 0x64, 0x55, 0x55, 0xb2, 0x86, 0x2e, 0xff, 0x32, 0x03, 0xab, 0x3b, 0x6c, 0x3d, 0xe9, - 0x1a, 0xef, 0x18, 0xae, 0xa7, 0x99, 0x43, 0x8c, 0xee, 0x43, 0x70, 0xae, 0xcd, 0x8e, 0xac, 0x55, - 0x9d, 0xa3, 0xf8, 0x5c, 0x5f, 0xf0, 0xd1, 0x89, 0x7a, 0xf4, 0x36, 0x3e, 0xa5, 0x1e, 0x5b, 0x8c, - 0x0b, 0x3e, 0x3a, 0x52, 0x4f, 0xfe, 0xd7, 0x79, 0x28, 0xb0, 0x6c, 0x93, 0x89, 0x15, 0x8d, 0xbc, - 0x09, 0xca, 0x46, 0xdf, 0x04, 0x11, 0xcf, 0x87, 0x78, 0x12, 0xd8, 0x64, 0xd7, 0xcd, 0x39, 0xe6, - 0xf9, 0x30, 0x10, 0xbd, 0x6e, 0xfe, 0x10, 0x24, 0x4e, 0xc0, 0xad, 0x0c, 0xdf, 0x13, 0x25, 0xa5, - 0xc6, 0xe0, 0x0d, 0x1f, 0x4c, 0xbf, 0x2a, 0x23, 0xbe, 0x05, 0x11, 0xc0, 0x85, 0xab, 0xb9, 0x1b, - 0x55, 0x25, 0x28, 0xa3, 0x9b, 0x73, 0x23, 0xe0, 0x62, 0x4a, 0x94, 0xfb, 0xfd, 0xfc, 0x40, 0x7c, - 0xf1, 0x55, 0x4e, 0xc6, 0xe7, 0x84, 0xe3, 0x03, 0x58, 0xf3, 0x77, 0x6c, 0x6c, 0x8e, 0x99, 0x92, - 0xbd, 0x1c, 0xd9, 0x6c, 0x89, 0xc5, 0x55, 0x56, 0xf5, 0xb4, 0x25, 0x7f, 0x44, 0xdf, 0x73, 0x8c, - 0xb0, 0x8e, 0x1d, 0xf6, 0xaa, 0xa8, 0x14, 0x37, 0x13, 0xdb, 0x22, 0x5a, 0x89, 0x52, 0xa7, 0x7e, - 0xaa, 0x01, 0xaf, 0xfc, 0xa9, 0x46, 0xfc, 0xf0, 0xa3, 0x7c, 0xde, 0xc3, 0x0f, 0xd9, 0x82, 0x6a, - 0xa4, 0x7f, 0xa7, 0x1c, 0xae, 0x45, 0xbf, 0xbf, 0xcb, 0x26, 0xbe, 0xbf, 0x7b, 0x1f, 0x96, 0xd8, - 0xd9, 0x82, 0xaa, 0xb9, 0x6a, 0x10, 0xb7, 0x55, 0x95, 0x0a, 0x83, 0x36, 0x5c, 0xe2, 0xa7, 0xca, - 0x4d, 0x28, 0xfa, 0x5a, 0xe0, 0x14, 0x9f, 0x26, 0xf6, 0x1e, 0x22, 0x1b, 0x7f, 0x0f, 0x21, 0xff, - 0xe7, 0x3c, 0x94, 0x08, 0x1f, 0x16, 0x9e, 0x87, 0x6f, 0x4d, 0x32, 0xaf, 0xf5, 0xd6, 0x24, 0x7b, - 0xfe, 0xb7, 0x26, 0x64, 0xa3, 0xcd, 0x6c, 0xee, 0xb2, 0x65, 0x67, 0x36, 0xeb, 0xea, 0xd0, 0x72, - 0x74, 0xd5, 0xb0, 0x8f, 0x3e, 0xe5, 0x27, 0x86, 0xc0, 0x40, 0x2d, 0xfb, 0xe8, 0xd3, 0x28, 0xc1, - 0x7d, 0xae, 0x46, 0x42, 0x82, 0xfb, 0x34, 0xef, 0x16, 0x0b, 0xee, 0x28, 0x07, 0xfe, 0xf8, 0x83, - 0x81, 0x7c, 0x0e, 0x21, 0xc1, 0x7d, 0xfe, 0x4e, 0x21, 0x24, 0xb8, 0x4f, 0x14, 0xb1, 0x8b, 0x1d, - 0x43, 0x9b, 0xf0, 0x77, 0x09, 0xbc, 0x84, 0x7e, 0x02, 0x55, 0xff, 0xfc, 0x93, 0xf1, 0x2e, 0x51, - 0x27, 0xb6, 0xe2, 0x03, 0x29, 0xf7, 0x18, 0xd1, 0x7d, 0x2a, 0x7f, 0x51, 0xa2, 0xfb, 0x84, 0x88, - 0xf1, 0x54, 0xe9, 0xdb, 0x0b, 0x26, 0x62, 0x39, 0xa5, 0xc2, 0x80, 0x1d, 0x0a, 0x23, 0xfd, 0x1c, - 0x6a, 0xc3, 0x43, 0xcc, 0xd2, 0x3a, 0xd2, 0x67, 0x9c, 0x39, 0x05, 0x28, 0x88, 0x66, 0xc3, 0x40, - 0x1f, 0xc0, 0x52, 0x40, 0x40, 0xf3, 0x4e, 0xd0, 0x47, 0x9c, 0x39, 0xa5, 0xea, 0xd3, 0xb0, 0x64, - 0x14, 0x97, 0xa1, 0xcc, 0x1f, 0x02, 0xe8, 0x9a, 0xa7, 0xd1, 0xcf, 0x14, 0x72, 0x4a, 0x89, 0x3e, - 0x02, 0xd8, 0xd1, 0x3c, 0x8d, 0xb8, 0xb2, 0xd8, 0x71, 0x2c, 0x87, 0xbe, 0xde, 0xcc, 0x29, 0xac, - 0x80, 0xde, 0x03, 0xde, 0x1b, 0xf5, 0xc7, 0x19, 0x76, 0x4e, 0xe8, 0xfb, 0xcc, 0x9c, 0x52, 0x66, - 0xb0, 0x6f, 0x08, 0x88, 0x2d, 0x85, 0x8b, 0x3d, 0x4e, 0xb1, 0xcc, 0x3a, 0x48, 0x41, 0x94, 0x40, - 0xfe, 0x0e, 0xf2, 0x8a, 0xfd, 0x83, 0x11, 0x58, 0xb0, 0xcc, 0xe9, 0x16, 0xec, 0x94, 0x0b, 0x92, - 0x40, 0x38, 0xf9, 0x01, 0xcd, 0xd6, 0x0e, 0x94, 0x82, 0x6c, 0x6e, 0x08, 0xa0, 0xb0, 0xdb, 0xee, - 0x3e, 0x6e, 0xb4, 0xa5, 0x77, 0xc2, 0xac, 0x07, 0xf4, 0x6d, 0x64, 0x63, 0xe7, 0x6b, 0xb5, 0xd5, - 0x91, 0xb2, 0x34, 0x69, 0xc0, 0xce, 0xd7, 0x6a, 0x77, 0x7f, 0xc0, 0xd2, 0x21, 0x3c, 0x57, 0x9e, - 0x48, 0xf9, 0xad, 0x76, 0xe4, 0x33, 0x51, 0xa6, 0xda, 0x90, 0x04, 0x95, 0x76, 0xb7, 0xfb, 0x6c, - 0xbf, 0xa7, 0x36, 0x5f, 0x34, 0xb6, 0x07, 0xd2, 0x3b, 0x68, 0x19, 0xaa, 0x1c, 0xd2, 0xee, 0x76, - 0x76, 0x9b, 0x0a, 0xcb, 0x14, 0xc0, 0x41, 0xfd, 0xa7, 0x5d, 0x65, 0xd0, 0x54, 0xa4, 0xec, 0xd6, - 0x2f, 0x32, 0x50, 0x16, 0x4e, 0x64, 0x84, 0x4c, 0x84, 0xef, 0xa0, 0x0a, 0x14, 0x3b, 0xcd, 0xd6, - 0xee, 0xd3, 0xc7, 0x5d, 0x52, 0x7b, 0x11, 0x72, 0x83, 0xc6, 0x2e, 0xef, 0x56, 0x5f, 0xed, 0x35, - 0x06, 0x4f, 0xa5, 0x1c, 0xaa, 0x42, 0x69, 0xbb, 0xbb, 0xb7, 0xb7, 0xdf, 0x69, 0x0d, 0xbe, 0x93, - 0xf2, 0xa4, 0xd5, 0xe6, 0x8b, 0x81, 0x1a, 0x82, 0x16, 0x48, 0x5c, 0xd9, 0x6e, 0x28, 0xbb, 0x4d, - 0x01, 0x58, 0x60, 0xac, 0x5f, 0x0c, 0xd4, 0xa7, 0xdd, 0x9e, 0xb4, 0xb8, 0xf5, 0x21, 0x94, 0x82, - 0xb3, 0x17, 0xfa, 0x32, 0xbd, 0xf3, 0x9d, 0xf8, 0x44, 0x1d, 0xa0, 0xd0, 0xea, 0x3c, 0x6f, 0x2a, - 0x03, 0x29, 0xbb, 0xb5, 0x05, 0x52, 0xfc, 0x34, 0x05, 0x15, 0x20, 0xdb, 0xfc, 0x46, 0x7a, 0x87, - 0xfc, 0xdd, 0x6d, 0x4a, 0x19, 0xf2, 0xb7, 0xdd, 0x94, 0xb2, 0x5b, 0x1f, 0xf3, 0x87, 0x51, 0x3c, - 0x44, 0x89, 0xa4, 0x5b, 0x6c, 0x6c, 0x6f, 0x37, 0x7b, 0x03, 0xc6, 0x5c, 0x69, 0x7e, 0x4d, 0x1f, - 0xbd, 0x6e, 0xed, 0xc3, 0x4a, 0x4a, 0xd4, 0x49, 0x06, 0x15, 0xf4, 0x5d, 0x6d, 0xec, 0xec, 0x48, - 0xef, 0x90, 0x28, 0x37, 0x04, 0x29, 0xcd, 0xbd, 0xee, 0x73, 0xd2, 0xf0, 0x05, 0x58, 0x16, 0xa1, - 0xfc, 0x55, 0xfd, 0xd6, 0x2d, 0xa8, 0x46, 0xa2, 0x4b, 0x32, 0x83, 0x7b, 0xcd, 0x1d, 0x75, 0xaf, - 0x4b, 0x58, 0xd5, 0xa0, 0x4c, 0x0a, 0x3e, 0x79, 0x66, 0xeb, 0x3e, 0xd4, 0x62, 0x3e, 0x6a, 0xf4, - 0xc5, 0x2e, 0x99, 0x8e, 0xbd, 0x5e, 0x57, 0xe1, 0xbd, 0x6f, 0xbe, 0xa0, 0xbf, 0xb3, 0xf7, 0xfe, - 0xcb, 0xbb, 0x50, 0xdc, 0x25, 0xc2, 0xd7, 0xb0, 0x0d, 0xf4, 0x08, 0x8a, 0x7e, 0x3a, 0x6c, 0xb4, - 0x11, 0xf1, 0xac, 0xc5, 0x14, 0xd9, 0x9b, 0x6b, 0x09, 0x85, 0xd7, 0x9c, 0xda, 0xde, 0x09, 0x7a, - 0x08, 0x8b, 0x3c, 0x21, 0x36, 0xaa, 0x8b, 0xb5, 0xc5, 0x1c, 0xd9, 0xa7, 0x54, 0x2e, 0xb0, 0x54, - 0xd9, 0x48, 0xb0, 0x81, 0x91, 0x6c, 0xda, 0x9b, 0xf5, 0x24, 0x82, 0xef, 0xfc, 0x87, 0xb0, 0xc8, - 0x13, 0xe5, 0xa2, 0xd8, 0x09, 0x69, 0x98, 0xbc, 0x77, 0x6e, 0xcb, 0x0d, 0x80, 0x30, 0x35, 0x2e, - 0xba, 0x28, 0x9a, 0xf3, 0x58, 0x22, 0xed, 0xb9, 0x2c, 0xb6, 0xa1, 0xe8, 0xe7, 0xb3, 0x16, 0x27, - 0x2e, 0x96, 0x3c, 0x7b, 0x73, 0x33, 0x0d, 0xc5, 0x86, 0x70, 0x27, 0x83, 0x76, 0x01, 0xc2, 0xec, - 0xb7, 0x62, 0x3f, 0x12, 0x29, 0xaf, 0x37, 0xdf, 0x4d, 0x47, 0xf2, 0xd9, 0xf8, 0x12, 0x4a, 0x41, - 0xea, 0x67, 0xb4, 0x39, 0x3f, 0x1f, 0xf4, 0xdc, 0xe1, 0x34, 0xa1, 0x22, 0x26, 0x76, 0x46, 0xc2, - 0x01, 0x4b, 0x4a, 0xc2, 0xe7, 0xd3, 0x26, 0x36, 0x4c, 0xe4, 0x2c, 0x0e, 0x28, 0x91, 0xde, 0xf9, - 0x94, 0x89, 0x2d, 0x0b, 0xc9, 0x9d, 0x91, 0x30, 0xee, 0x64, 0xce, 0xe7, 0xb9, 0x4c, 0xda, 0x50, - 0x16, 0x32, 0x30, 0x8b, 0x4c, 0x92, 0x29, 0x9e, 0x37, 0x2f, 0xcd, 0xc1, 0x06, 0xcb, 0xd4, 0x84, - 0x8a, 0x98, 0x94, 0x59, 0x9c, 0x9c, 0x94, 0x64, 0xcd, 0x73, 0x3b, 0xf5, 0x0c, 0x6a, 0xb1, 0x84, - 0xcc, 0xe8, 0x6a, 0x9a, 0xe8, 0x9d, 0x8b, 0xd9, 0x73, 0xa8, 0xc5, 0x12, 0x27, 0x8b, 0xcc, 0xd2, - 0x53, 0x39, 0x6f, 0xbe, 0x77, 0x0a, 0x05, 0x97, 0xa4, 0x6f, 0x00, 0x25, 0xd3, 0x28, 0xa3, 0x9f, - 0x44, 0x46, 0x9c, 0x9e, 0x64, 0x79, 0x6e, 0x57, 0xbf, 0x60, 0x5b, 0x55, 0xf3, 0x0e, 0x51, 0xf2, - 0x32, 0xc3, 0xaf, 0xbc, 0x91, 0x82, 0xe1, 0x5d, 0x0a, 0x77, 0x2b, 0x61, 0x91, 0xdc, 0xad, 0x02, - 0x97, 0xb3, 0x76, 0x2b, 0x61, 0xb0, 0x31, 0x37, 0x11, 0x6f, 0x62, 0xb7, 0x0a, 0xbd, 0xb8, 0x93, - 0x41, 0xad, 0xe0, 0xae, 0x87, 0xe5, 0xc8, 0x45, 0x97, 0x13, 0x7d, 0x8e, 0x24, 0xcf, 0x9d, 0xd7, - 0x9b, 0x1b, 0x19, 0xd4, 0x80, 0xa2, 0x9f, 0x5f, 0x56, 0xec, 0x4f, 0x2c, 0xf1, 0xad, 0xd8, 0x9f, - 0x44, 0x3a, 0xda, 0x2e, 0x54, 0xc4, 0x14, 0xab, 0x28, 0x29, 0xc5, 0x11, 0x56, 0x97, 0xe7, 0xa1, - 0x83, 0xe1, 0xfd, 0x0c, 0x0a, 0x2c, 0xef, 0x2a, 0x8a, 0xde, 0x20, 0x85, 0xe9, 0x52, 0xe7, 0x4e, - 0xef, 0x97, 0x50, 0x0a, 0x12, 0xb0, 0x8a, 0xea, 0x27, 0x9e, 0x95, 0x75, 0x2e, 0x83, 0xaf, 0x60, - 0x91, 0xe7, 0x5c, 0x15, 0x45, 0x24, 0x9a, 0xac, 0x75, 0x73, 0x23, 0x05, 0x13, 0xf4, 0xfe, 0x4b, - 0x28, 0x05, 0x19, 0x0d, 0xc5, 0x2e, 0xc4, 0xd3, 0xb2, 0x9e, 0xa6, 0x01, 0xc5, 0xc4, 0x85, 0xe2, - 0x7c, 0xa6, 0xe4, 0x57, 0x9d, 0xcb, 0xa6, 0x05, 0x10, 0x26, 0x09, 0x14, 0x85, 0x35, 0x91, 0x20, - 0x55, 0x54, 0xe9, 0xc9, 0xa4, 0xa8, 0x77, 0x32, 0x44, 0x13, 0x0a, 0xb9, 0x4e, 0x45, 0x25, 0x96, - 0x4c, 0x81, 0x3a, 0xb7, 0x3f, 0xbb, 0x54, 0x68, 0x85, 0x8b, 0xb7, 0xa8, 0xd0, 0x26, 0x52, 0x7b, - 0xce, 0x65, 0xb4, 0xe7, 0xa7, 0xd7, 0x12, 0x78, 0xbd, 0x17, 0x9f, 0xa3, 0xf3, 0xb3, 0xdb, 0x67, - 0xb9, 0x78, 0x05, 0x66, 0x57, 0xa2, 0xd3, 0x91, 0x64, 0x75, 0x75, 0x3e, 0x41, 0x4c, 0x55, 0x87, - 0xc7, 0x9a, 0x51, 0x55, 0x1d, 0xcf, 0xb3, 0x79, 0xb6, 0xaa, 0x0e, 0x39, 0x25, 0x54, 0xf5, 0xb9, - 0x99, 0x29, 0x50, 0x8d, 0x24, 0xee, 0x14, 0x97, 0x20, 0x2d, 0xfb, 0xe7, 0xe6, 0x95, 0xb9, 0xf8, - 0x60, 0x9c, 0x7d, 0xf6, 0x7f, 0x02, 0xe2, 0xc7, 0x9c, 0xef, 0xa7, 0x08, 0x7e, 0x22, 0x9d, 0xe4, - 0xdc, 0x8e, 0x7e, 0x17, 0xfc, 0xc7, 0x80, 0x38, 0xdf, 0xeb, 0xe9, 0x9b, 0xe1, 0xfc, 0xac, 0xc7, - 0x2c, 0x21, 0x61, 0x82, 0xf1, 0x07, 0x69, 0x7b, 0x20, 0xc9, 0xf6, 0xda, 0x59, 0x64, 0xe2, 0xc4, - 0xa4, 0x24, 0xd2, 0x14, 0x27, 0x66, 0x7e, 0x9e, 0xcd, 0xd3, 0xdc, 0x5c, 0x9e, 0x43, 0x33, 0x66, - 0xc1, 0x84, 0xac, 0x8d, 0x67, 0x3b, 0x9b, 0xb4, 0x7e, 0xc2, 0x7c, 0x9d, 0x87, 0x05, 0x37, 0x5f, - 0x94, 0x41, 0x4c, 0x0b, 0x8a, 0xd5, 0x37, 0xd3, 0x50, 0xc1, 0xcc, 0x04, 0xbe, 0x59, 0xbc, 0x1f, - 0x89, 0x34, 0x98, 0xe7, 0xf0, 0xcd, 0x28, 0x8f, 0xa4, 0x6f, 0x76, 0x1e, 0x26, 0xbe, 0xaf, 0x4a, - 0x59, 0xc4, 0x7d, 0xd5, 0xf3, 0x30, 0xe0, 0xfb, 0x29, 0x48, 0x4d, 0x19, 0xdf, 0x4f, 0xf1, 0xac, - 0x97, 0xf1, 0xfd, 0x94, 0xc8, 0x69, 0xc9, 0x74, 0xad, 0x90, 0xb3, 0x52, 0x1c, 0x59, 0x32, 0x95, - 0xe5, 0x69, 0x23, 0x0b, 0x52, 0x45, 0x8a, 0x23, 0x8b, 0xe7, 0x8f, 0x3c, 0x55, 0x54, 0x82, 0x64, - 0x8e, 0x11, 0x51, 0x89, 0xa7, 0x78, 0x9c, 0xcb, 0x82, 0x59, 0xf1, 0xc7, 0x53, 0x3b, 0x66, 0xc5, - 0xc3, 0xa4, 0x88, 0x67, 0x5b, 0x71, 0x52, 0x3b, 0x61, 0xc5, 0xcf, 0x66, 0x70, 0x50, 0xa0, 0xe5, - 0x4f, 0xfe, 0x7f, 0x00, 0x00, 0x00, 0xff, 0xff, 0xc5, 0x7d, 0xf2, 0xb4, 0xd4, 0x69, 0x00, 0x00, + 0xb6, 0x29, 0x92, 0x5d, 0xa4, 0xdc, 0xee, 0x49, 0x3a, 0xf5, 0x4a, 0xac, 0x4b, 0xaa, 0xd2, 0x64, + 0x55, 0x75, 0x55, 0x51, 0x96, 0x56, 0x99, 0xcc, 0x7b, 0x99, 0x2c, 0x82, 0x00, 0x41, 0xb2, 0x78, + 0x8b, 0xbc, 0x20, 0x59, 0x07, 0xc9, 0x2e, 0x41, 0x10, 0x64, 0x91, 0x20, 0x48, 0x80, 0x20, 0x03, + 0x64, 0x15, 0x20, 0xbb, 0x04, 0x08, 0xb2, 0x0e, 0x90, 0x00, 0x09, 0xb2, 0x0c, 0xee, 0xa7, 0xaa, + 0x6e, 0x7d, 0x28, 0xc9, 0x9f, 0x99, 0x79, 0x03, 0xcc, 0x4a, 0xbc, 0xe7, 0x9c, 0x7b, 0xee, 0xb9, + 0xf7, 0x9e, 0x7b, 0xce, 0xb9, 0x9f, 0x3a, 0x82, 0xf2, 0xd8, 0x3a, 0x18, 0xdb, 0xb7, 0x6d, 0xc7, + 0xf2, 0x2c, 0x54, 0xa4, 0x05, 0xcd, 0x36, 0x36, 0x37, 0xc6, 0x96, 0x35, 0x9e, 0xe0, 0x8f, 0x29, + 0xfc, 0x60, 0x36, 0xfa, 0x58, 0x33, 0x4f, 0x18, 0xd1, 0xe6, 0xc5, 0x38, 0x0a, 0x4f, 0x6d, 0xcf, + 0x47, 0x5e, 0x89, 0x23, 0x3d, 0x63, 0x8a, 0x5d, 0x4f, 0x9b, 0xf2, 0x26, 0xe4, 0x87, 0x50, 0xeb, + 0x7b, 0x9a, 0xe3, 0x3d, 0x1e, 0xdb, 0x0a, 0xfe, 0x71, 0x86, 0x5d, 0x0f, 0xdd, 0x80, 0xc2, 0x78, + 0x62, 0x1d, 0x68, 0x93, 0x7a, 0xe6, 0x6a, 0xe6, 0x46, 0xf9, 0x9e, 0x74, 0xdb, 0x17, 0xe3, 0xf6, + 0x2e, 0x85, 0x2b, 0x1c, 0x2f, 0x4b, 0xb0, 0xd4, 0xf7, 0x2c, 0x3b, 0xac, 0x2b, 0xd7, 0xa0, 0xba, + 0x8b, 0x05, 0x66, 0xf2, 0x03, 0x58, 0xf2, 0x01, 0xae, 0x6d, 0x99, 0x2e, 0x7e, 0x05, 0xf6, 0x9f, + 0xc2, 0x52, 0x43, 0xd7, 0x7b, 0x18, 0x3b, 0xbe, 0x68, 0x32, 0xe4, 0x6d, 0x8c, 0x1d, 0x5e, 0x73, + 0x29, 0xac, 0x49, 0x89, 0x28, 0x4e, 0x7e, 0x06, 0xcb, 0x3b, 0x78, 0x82, 0x3d, 0x2c, 0x56, 0xac, + 0xc3, 0xa2, 0xa6, 0xeb, 0x0e, 0x76, 0x5d, 0x5a, 0xb7, 0xa4, 0xf8, 0x45, 0xf4, 0x2e, 0x94, 0x0c, + 0xd3, 0xc3, 0xce, 0x48, 0x1b, 0xe2, 0x7a, 0x96, 0xe2, 0x42, 0x80, 0xfc, 0x2d, 0xd4, 0xda, 0x86, + 0xeb, 0x9d, 0x8f, 0xd5, 0x16, 0x48, 0xd8, 0xd4, 0x0e, 0x26, 0xb8, 0xa1, 0x1f, 0x61, 0xc7, 0x33, + 0x5c, 0xac, 0x53, 0x8e, 0x45, 0x25, 0x01, 0x97, 0xef, 0x83, 0x14, 0x32, 0xe6, 0x23, 0x73, 0x9e, + 0xde, 0xfd, 0x31, 0x2c, 0xef, 0xdb, 0xba, 0x16, 0xed, 0xdd, 0x39, 0x2a, 0xa2, 0xeb, 0x20, 0xe9, + 0x96, 0xea, 0x5a, 0x23, 0x4f, 0x75, 0xb0, 0x8b, 0x3d, 0xd5, 0x30, 0xb9, 0x70, 0x55, 0xdd, 0xea, + 0x5b, 0x23, 0x4f, 0x21, 0xd0, 0x96, 0x29, 0x6f, 0x03, 0x12, 0x5b, 0xe0, 0xb2, 0xdd, 0x82, 0x15, + 0x13, 0x63, 0xdd, 0x8d, 0x71, 0xc8, 0xb0, 0xee, 0x51, 0x94, 0xc8, 0xe4, 0x7f, 0x64, 0x40, 0xa2, + 0xbf, 0xcf, 0x37, 0x72, 0xef, 0x43, 0x75, 0x68, 0x4d, 0xa7, 0x33, 0xd3, 0x18, 0x6a, 0x9e, 0x61, + 0x99, 0x7c, 0x22, 0xa2, 0x40, 0x84, 0x20, 0x4f, 0x5a, 0xaf, 0xe7, 0x68, 0xa3, 0xf4, 0x37, 0x7a, + 0x06, 0x25, 0xdd, 0x70, 0xf0, 0x90, 0xd6, 0xca, 0x5f, 0xcd, 0xdc, 0x58, 0xba, 0x77, 0x2b, 0xec, + 0x7f, 0x5c, 0x84, 0xdb, 0x81, 0x8c, 0x3b, 0x7e, 0x25, 0x25, 0xac, 0x2f, 0x7f, 0x0c, 0x28, 0x49, + 0x80, 0x0a, 0x90, 0x6d, 0x75, 0xa4, 0x77, 0xd0, 0x22, 0xe4, 0xba, 0xfb, 0x03, 0x29, 0x83, 0x8a, + 0x90, 0x7f, 0xdc, 0x1d, 0x3c, 0x95, 0xb2, 0xf2, 0x3e, 0xac, 0xf4, 0x0f, 0x67, 0x9e, 0x6e, 0xbd, + 0x34, 0xdf, 0x62, 0x47, 0xe5, 0x5b, 0xb0, 0xdc, 0xa4, 0x0a, 0x73, 0x2e, 0xa6, 0xf2, 0x00, 0xd0, + 0x8e, 0xe1, 0x9e, 0x9b, 0xfe, 0x9c, 0x42, 0x3c, 0x05, 0xb4, 0x67, 0x99, 0x86, 0x67, 0x39, 0xe7, + 0xe3, 0x5a, 0x87, 0xc5, 0xe1, 0xcc, 0x71, 0xb0, 0xe9, 0x71, 0xbd, 0xf2, 0x8b, 0xf2, 0xcf, 0x60, + 0x25, 0xc2, 0xe9, 0x15, 0xd4, 0xbd, 0x05, 0x2b, 0xdc, 0x04, 0xec, 0x3a, 0xd6, 0x2c, 0x30, 0x51, + 0xf7, 0x00, 0x08, 0x5a, 0x1d, 0x13, 0x20, 0x67, 0xb0, 0x12, 0x65, 0xc0, 0xe8, 0x4b, 0xb6, 0xff, + 0x53, 0xbe, 0x09, 0x6b, 0xa1, 0x5d, 0x88, 0x70, 0x43, 0x90, 0x37, 0xb5, 0x29, 0xe6, 0x1d, 0xa2, + 0xbf, 0xe5, 0x19, 0xac, 0x85, 0xab, 0xe0, 0x4d, 0xdb, 0x3e, 0xff, 0xe2, 0x7b, 0x0a, 0xeb, 0x89, + 0x66, 0x5f, 0x6f, 0x05, 0x6a, 0xb0, 0xd1, 0xd0, 0xf5, 0x9d, 0x13, 0x53, 0x9b, 0x1a, 0xc3, 0x0e, + 0x36, 0xc6, 0x87, 0x07, 0x56, 0x30, 0x8b, 0x3b, 0x20, 0xe9, 0x0c, 0xa3, 0x9a, 0x1c, 0xc5, 0x7b, + 0xb2, 0x11, 0xf6, 0x24, 0x5e, 0xb7, 0xa6, 0x47, 0x01, 0xf2, 0x5f, 0x63, 0xf6, 0x59, 0xf3, 0x0e, + 0x85, 0xb1, 0xf1, 0x88, 0x1e, 0xaa, 0xde, 0x89, 0xcd, 0xc6, 0x73, 0x49, 0x1c, 0x9b, 0x01, 0xc1, + 0x0d, 0x4e, 0x6c, 0xac, 0x94, 0x3c, 0xff, 0x27, 0xba, 0x00, 0x85, 0x23, 0x67, 0xa4, 0x1a, 0x3a, + 0x57, 0xc3, 0x85, 0x23, 0x67, 0xd4, 0xd2, 0xa9, 0x76, 0x68, 0xde, 0x21, 0x5d, 0xec, 0x51, 0xed, + 0x20, 0xed, 0x51, 0x9c, 0xfc, 0x01, 0xd4, 0x02, 0x01, 0xf8, 0x28, 0x21, 0xc8, 0xcf, 0x66, 0x86, + 0x4e, 0xdb, 0xae, 0x28, 0xf4, 0xb7, 0xfc, 0x6f, 0x32, 0x81, 0x4b, 0xf8, 0xcd, 0xc8, 0x7a, 0x03, + 0x0a, 0x23, 0x6d, 0x6a, 0x4c, 0x4e, 0xb8, 0xb4, 0x82, 0x4b, 0x7b, 0x42, 0xe1, 0x0a, 0xc7, 0x07, + 0xbd, 0xca, 0xcf, 0xef, 0x55, 0xd0, 0x85, 0x05, 0xa1, 0x0b, 0xff, 0x30, 0xcb, 0x1d, 0xd1, 0x1b, + 0x76, 0xc0, 0x57, 0xf5, 0x6c, 0xa8, 0xea, 0xaf, 0x20, 0xfd, 0x67, 0x50, 0xb4, 0x1d, 0x3c, 0x32, + 0x8e, 0xb1, 0x5b, 0xcf, 0x5f, 0xcd, 0xdd, 0x28, 0xdf, 0xbb, 0x18, 0x6b, 0xaf, 0x6d, 0x59, 0x3f, + 0xcc, 0xec, 0x1e, 0x25, 0x52, 0x02, 0x62, 0xf4, 0x25, 0x94, 0x5c, 0xcb, 0xf1, 0x98, 0xa4, 0x0b, + 0x54, 0x52, 0x39, 0xac, 0x19, 0xeb, 0xd8, 0xed, 0xbe, 0xe5, 0x78, 0x54, 0xf0, 0xa2, 0xcb, 0x7f, + 0xc9, 0x57, 0xa1, 0xe8, 0x43, 0x89, 0xf9, 0xed, 0x74, 0x3b, 0x4d, 0xe9, 0x1d, 0x04, 0x50, 0xe8, + 0x29, 0xcd, 0x27, 0xad, 0x17, 0x52, 0x46, 0x7e, 0xc6, 0x1d, 0xaa, 0xa8, 0x0c, 0x9f, 0x41, 0x59, + 0xc7, 0xae, 0x67, 0x98, 0xcc, 0xcc, 0x31, 0x0d, 0xbf, 0x20, 0x68, 0x78, 0x88, 0x54, 0x44, 0x4a, + 0xf9, 0x6f, 0x66, 0x60, 0x95, 0x6b, 0x56, 0xdf, 0x73, 0xb0, 0x36, 0xfd, 0x0d, 0x28, 0xcd, 0xfb, + 0xb0, 0x40, 0xa6, 0xdb, 0xad, 0xe7, 0xe8, 0x48, 0xc6, 0x75, 0x81, 0x21, 0xe5, 0x3f, 0xc9, 0x40, + 0x6d, 0x17, 0x7b, 0x94, 0xf1, 0x9b, 0x08, 0x11, 0x4e, 0x72, 0xf6, 0x8c, 0x49, 0xf6, 0x55, 0x24, + 0x27, 0x58, 0xc3, 0x13, 0x90, 0x42, 0x21, 0xf8, 0xe0, 0x5e, 0x87, 0x9a, 0x39, 0x9b, 0xaa, 0xf1, + 0x01, 0xce, 0x2b, 0x4b, 0xe6, 0x6c, 0x2a, 0x8c, 0x2c, 0xda, 0x80, 0x22, 0x21, 0xa4, 0x7a, 0x9f, + 0xa5, 0x14, 0x8b, 0xe6, 0x6c, 0x4a, 0x3a, 0x89, 0xde, 0x83, 0x0a, 0x41, 0x69, 0xc3, 0x21, 0xb6, + 0x3d, 0xac, 0xd3, 0x36, 0xf3, 0x4a, 0xd9, 0x9c, 0x4d, 0x1b, 0x1c, 0x24, 0xff, 0xdb, 0x4c, 0xe0, + 0x3d, 0xde, 0x78, 0x10, 0xde, 0x4c, 0xfb, 0x05, 0x07, 0x97, 0x8f, 0x38, 0x38, 0x74, 0x05, 0xca, + 0xb6, 0xe5, 0x7a, 0xaa, 0x6d, 0x4d, 0x8c, 0xe1, 0x09, 0x55, 0xf0, 0xa2, 0x02, 0x04, 0xd4, 0xa3, + 0x10, 0xf9, 0x01, 0xac, 0x46, 0xfb, 0x20, 0xb8, 0x40, 0x32, 0x2c, 0x99, 0x53, 0x8c, 0xdc, 0x1d, + 0xa8, 0x36, 0x74, 0xfd, 0xb9, 0x33, 0xf2, 0x7b, 0x7e, 0x05, 0x72, 0x47, 0xce, 0x88, 0xd7, 0xa9, + 0x86, 0x75, 0x08, 0x09, 0xc1, 0xc8, 0xd7, 0x40, 0x62, 0xe6, 0x4e, 0xa8, 0x94, 0xe6, 0xe3, 0xde, + 0x87, 0x25, 0xb2, 0x64, 0xce, 0xa0, 0xba, 0xc7, 0x2c, 0x0f, 0xa5, 0xe2, 0x62, 0x9f, 0x29, 0xc1, + 0x31, 0x48, 0x64, 0xf9, 0xd0, 0xce, 0x0b, 0xdb, 0x0a, 0x3e, 0x3e, 0x89, 0xb8, 0x9f, 0x13, 0x72, + 0x3c, 0x7a, 0x00, 0x1b, 0x0e, 0x1e, 0x61, 0x47, 0xc5, 0xc7, 0x06, 0x51, 0xa3, 0xb1, 0xea, 0x7a, + 0x9a, 0x87, 0xa7, 0xd8, 0xf4, 0x5c, 0xee, 0x36, 0xd7, 0x29, 0x41, 0x93, 0xe3, 0xfb, 0x01, 0x5a, + 0xfe, 0x65, 0x06, 0x56, 0xb8, 0xad, 0x7f, 0xcd, 0xd6, 0x3f, 0x86, 0x15, 0x9b, 0x78, 0x57, 0xe7, + 0x08, 0x27, 0xdb, 0x45, 0x3e, 0x2a, 0x6c, 0x12, 0x49, 0x90, 0xd3, 0x26, 0x13, 0x1e, 0x95, 0x92, + 0x9f, 0xf2, 0x75, 0x58, 0xa6, 0xb6, 0x28, 0x22, 0x41, 0xda, 0xd8, 0x7e, 0x01, 0x48, 0x24, 0x0c, + 0x77, 0x48, 0xe7, 0x93, 0x55, 0xfe, 0x97, 0x19, 0x40, 0x7d, 0xcc, 0xea, 0x1b, 0xd8, 0xf5, 0x9b, + 0xfa, 0x0c, 0x2a, 0x3a, 0x1e, 0x19, 0x26, 0xd6, 0x55, 0x17, 0x7b, 0x24, 0x52, 0x23, 0x16, 0x66, + 0x55, 0x34, 0x7c, 0x14, 0xdb, 0xc7, 0x1e, 0xb1, 0x7b, 0xfe, 0x6f, 0x17, 0xdd, 0x84, 0xa2, 0xcd, + 0x79, 0xd5, 0xb3, 0xb4, 0x52, 0xb2, 0xed, 0x80, 0x02, 0xfd, 0x11, 0x94, 0x35, 0xd7, 0x35, 0xc6, + 0x26, 0x1b, 0x21, 0x66, 0xc7, 0x36, 0xe3, 0x15, 0x1a, 0x01, 0x89, 0x22, 0x92, 0xcb, 0x7b, 0xd4, + 0xc4, 0x0a, 0x92, 0x70, 0xe1, 0x7f, 0x0a, 0x65, 0x41, 0x78, 0x3e, 0x04, 0xe9, 0xb2, 0x43, 0x28, + 0xbb, 0x7c, 0x00, 0xeb, 0x6c, 0xde, 0xdf, 0x16, 0x47, 0x7f, 0x5e, 0xb3, 0xe1, 0xbc, 0x62, 0xb8, + 0x40, 0xa6, 0x2b, 0xd9, 0xc2, 0xe7, 0xe1, 0x80, 0x0b, 0xe6, 0xe8, 0x42, 0xa2, 0x09, 0x6a, 0x90, + 0x7c, 0x61, 0xe6, 0x99, 0x24, 0xb9, 0x0b, 0x6b, 0xf1, 0x66, 0xb8, 0x66, 0xbc, 0xe6, 0xd8, 0x3c, + 0xa5, 0x51, 0x74, 0xa0, 0xb2, 0xbe, 0xd4, 0x77, 0xa1, 0x14, 0x28, 0x78, 0x32, 0x90, 0x0d, 0xc9, + 0x43, 0x2a, 0xf9, 0x7b, 0x3f, 0x88, 0x7e, 0x0b, 0xcc, 0x52, 0x06, 0x78, 0x0b, 0x56, 0x49, 0xcf, + 0x13, 0xcc, 0xd3, 0xd6, 0xce, 0xd7, 0x6c, 0x32, 0x04, 0x5a, 0x3e, 0x48, 0xaf, 0xd1, 0xad, 0x17, + 0xb0, 0x19, 0xd8, 0x2b, 0x41, 0x5f, 0x79, 0xeb, 0x0f, 0x00, 0x42, 0xc5, 0xe5, 0x1c, 0x4f, 0x53, + 0x73, 0x81, 0x5a, 0x9e, 0xc2, 0x25, 0xd1, 0x1c, 0xbd, 0x55, 0xe6, 0x29, 0x03, 0xf8, 0x57, 0xe1, + 0x62, 0x68, 0x50, 0x92, 0x8d, 0xa5, 0x8c, 0x23, 0xfa, 0x4c, 0xdc, 0x41, 0x67, 0xa9, 0xe2, 0x6e, + 0xc4, 0xdb, 0x4f, 0xdd, 0x2d, 0xff, 0x1c, 0xde, 0x4d, 0x6f, 0x8b, 0xcf, 0xc3, 0x9b, 0x0c, 0xdb, + 0x0b, 0xd8, 0xf4, 0xed, 0xda, 0x5b, 0x9e, 0x90, 0x9f, 0xd3, 0x4d, 0x8b, 0x62, 0xff, 0x60, 0x9c, + 0xbd, 0xa5, 0x45, 0x90, 0xb7, 0x2d, 0x87, 0xed, 0x67, 0xab, 0x0a, 0xfd, 0x8d, 0x36, 0xa1, 0x38, + 0x31, 0x46, 0xd8, 0x33, 0x78, 0x88, 0x94, 0x53, 0x82, 0xb2, 0xdc, 0xf0, 0xf7, 0x19, 0xaf, 0xcd, + 0x5e, 0x7e, 0xc8, 0xbc, 0xad, 0xc8, 0x20, 0x8c, 0x50, 0x32, 0xa7, 0x47, 0x28, 0xf2, 0x03, 0x16, + 0x03, 0xb3, 0xca, 0x7c, 0x16, 0xae, 0x41, 0x81, 0x3a, 0xac, 0x94, 0x7d, 0x36, 0xa5, 0xe3, 0x58, + 0x22, 0x3b, 0x3b, 0x73, 0x78, 0x7d, 0xd9, 0x1f, 0x07, 0xe7, 0x10, 0xaf, 0xcf, 0x63, 0xc0, 0xcf, + 0x8d, 0x5e, 0x7f, 0x82, 0x52, 0x4e, 0x89, 0xe4, 0xaf, 0x98, 0x5d, 0x21, 0x4c, 0x23, 0x41, 0xe4, + 0xf9, 0x87, 0xf6, 0x73, 0x66, 0x6d, 0x04, 0x0e, 0x61, 0x2c, 0xe4, 0x58, 0x5a, 0x32, 0x16, 0x52, + 0x2c, 0x4d, 0x21, 0x18, 0xf9, 0xd7, 0x19, 0x40, 0x6c, 0x64, 0x7f, 0x8e, 0x0f, 0x1c, 0xcd, 0x6f, + 0x5a, 0x82, 0xdc, 0xcc, 0x99, 0xf0, 0x0e, 0x91, 0x9f, 0x24, 0x8a, 0x74, 0xac, 0x99, 0xc7, 0x22, + 0x5a, 0xe6, 0x7f, 0x4b, 0x0a, 0x50, 0x10, 0x71, 0x15, 0xf4, 0x84, 0xe5, 0x08, 0x3b, 0x2e, 0x59, + 0xa7, 0x39, 0xda, 0x61, 0xbf, 0x88, 0x3e, 0x85, 0x35, 0x13, 0x1f, 0x7b, 0x87, 0x96, 0xad, 0x7a, + 0x8e, 0x31, 0x1e, 0x93, 0xd8, 0x89, 0x36, 0xc9, 0x23, 0xd5, 0x55, 0x8e, 0x1d, 0x30, 0x24, 0x13, + 0x07, 0xdd, 0x83, 0x0b, 0xf1, 0x5a, 0x3a, 0x9e, 0x68, 0x2c, 0x80, 0xad, 0x2a, 0x2b, 0xd1, 0x4a, + 0x3b, 0x04, 0x25, 0xff, 0x83, 0x0c, 0x48, 0xac, 0xfa, 0x9e, 0x13, 0xac, 0xc7, 0x8b, 0x50, 0xd2, + 0x67, 0x53, 0x3b, 0xf4, 0x7d, 0x0b, 0x4a, 0x91, 0x00, 0xa8, 0x87, 0xdb, 0x84, 0xe2, 0xc8, 0x98, + 0x60, 0xc1, 0xcb, 0x05, 0x65, 0xf4, 0x13, 0xa8, 0xd2, 0x8a, 0xf4, 0xc0, 0xf5, 0x48, 0x9b, 0xf0, + 0x0d, 0x40, 0x85, 0x00, 0x5b, 0x1c, 0x86, 0x3e, 0x82, 0x65, 0xc7, 0xf2, 0xe8, 0x5e, 0x22, 0x24, + 0xcc, 0x53, 0x42, 0xc9, 0x47, 0xf8, 0xc4, 0xf2, 0x0a, 0x2c, 0x73, 0x1d, 0x0c, 0xe5, 0x93, 0xff, + 0x77, 0x86, 0xc6, 0xd0, 0x8f, 0xa7, 0xf6, 0xeb, 0xa9, 0xd4, 0x57, 0x41, 0x40, 0x96, 0xa3, 0xf6, + 0xf1, 0x46, 0x38, 0xcd, 0x11, 0xb6, 0xb7, 0x79, 0x90, 0x6f, 0x98, 0xe3, 0x58, 0x50, 0x79, 0x13, + 0x96, 0x89, 0xe3, 0x21, 0xe1, 0xea, 0xd0, 0x1d, 0x18, 0x53, 0x6c, 0xcd, 0xd8, 0x2e, 0x62, 0x41, + 0x49, 0x22, 0xe4, 0x6d, 0x90, 0xe2, 0x9c, 0xd0, 0x22, 0xe4, 0x7a, 0x0a, 0xd9, 0xf4, 0x16, 0x21, + 0xdf, 0xeb, 0xf6, 0x23, 0xe7, 0x90, 0xa8, 0x04, 0x0b, 0xed, 0xee, 0x76, 0xa3, 0x2d, 0xe5, 0x08, + 0x5d, 0xa3, 0xdd, 0x96, 0xf2, 0xf2, 0x57, 0xfe, 0x2e, 0xe0, 0x75, 0xbb, 0x2d, 0xff, 0x9f, 0x1c, + 0x14, 0xd8, 0x32, 0x40, 0xd7, 0x20, 0xa7, 0x8d, 0x0c, 0x1e, 0xd7, 0xac, 0xc6, 0x57, 0xc9, 0xed, + 0xc6, 0xc8, 0x50, 0x08, 0x01, 0xfa, 0x10, 0xf2, 0x2e, 0x21, 0xcc, 0xc6, 0x03, 0x20, 0x4e, 0xd8, + 0xd7, 0x46, 0x86, 0x42, 0x49, 0xe4, 0xbf, 0x02, 0xb9, 0xc6, 0xc8, 0x40, 0x35, 0x28, 0x37, 0x9e, + 0xb4, 0xd4, 0xfd, 0xce, 0xb3, 0x4e, 0xf7, 0xdb, 0x0e, 0xdb, 0xd4, 0x13, 0x40, 0xab, 0x27, 0x65, + 0x50, 0x19, 0x16, 0xd9, 0xef, 0xfb, 0x52, 0x16, 0x55, 0xa1, 0x44, 0x0a, 0xed, 0x7b, 0xcf, 0x7b, + 0x1d, 0x69, 0x03, 0x55, 0x18, 0x5d, 0xbb, 0x2f, 0xfd, 0xe9, 0x2f, 0x32, 0x48, 0x02, 0x20, 0xa5, + 0x6e, 0xaf, 0xf1, 0xcd, 0x7e, 0x53, 0xfa, 0xdb, 0xbf, 0xc8, 0xc8, 0xff, 0x22, 0x0b, 0x79, 0xd2, + 0x1c, 0x92, 0xa0, 0xd2, 0x8f, 0x36, 0x11, 0x42, 0x5a, 0xdb, 0x0d, 0x3a, 0x94, 0x08, 0x96, 0x28, + 0x64, 0x6f, 0xbf, 0x3d, 0x60, 0xb0, 0x2c, 0x5a, 0x81, 0x1a, 0x83, 0xf5, 0xda, 0x7d, 0xb5, 0xdd, + 0x78, 0xdc, 0x6c, 0x4b, 0x79, 0xb4, 0x06, 0x88, 0x02, 0x9b, 0x9d, 0xed, 0x46, 0xaf, 0xbf, 0xdf, + 0x6e, 0x0c, 0x5a, 0xdd, 0x8e, 0xb4, 0x48, 0x84, 0xa3, 0xf0, 0xe7, 0xbd, 0x76, 0x5f, 0x6a, 0x04, + 0xc5, 0x26, 0x91, 0xf5, 0x09, 0xe9, 0x47, 0x9f, 0x0b, 0xbb, 0x8b, 0x10, 0x54, 0x43, 0xbe, 0x04, + 0xff, 0x8b, 0x0c, 0x7a, 0x17, 0xd6, 0x23, 0x30, 0x41, 0x90, 0xbf, 0x9e, 0x41, 0x32, 0x5c, 0xa2, + 0x58, 0xa5, 0xbb, 0x3f, 0x68, 0xaa, 0x83, 0x86, 0xb2, 0xdb, 0x1c, 0xa8, 0xdb, 0xdd, 0x4e, 0x7f, + 0xa0, 0x34, 0x5a, 0x9d, 0x41, 0x5f, 0xfa, 0xd3, 0x0c, 0xba, 0x08, 0x6b, 0x94, 0xe6, 0x49, 0xbb, + 0xfb, 0xad, 0xda, 0xef, 0x35, 0xb7, 0x83, 0xde, 0xfd, 0x8d, 0x0c, 0x5a, 0xe7, 0x52, 0x87, 0x48, + 0xd2, 0xee, 0xaf, 0x32, 0x68, 0x85, 0xf7, 0xfb, 0x59, 0xf3, 0x3b, 0xf5, 0x79, 0xa3, 0xbd, 0xdf, + 0x94, 0xfe, 0x57, 0x46, 0xfe, 0xb3, 0x1c, 0xc0, 0x73, 0x6d, 0x62, 0xe8, 0x6c, 0xff, 0x7e, 0x07, + 0x16, 0x68, 0xa4, 0xc4, 0x67, 0x5f, 0x70, 0xb4, 0x21, 0x11, 0x0b, 0xab, 0x14, 0x46, 0x88, 0x3e, + 0x81, 0x82, 0x83, 0x35, 0x37, 0x88, 0x27, 0x2e, 0xa6, 0x56, 0x51, 0x28, 0x89, 0xc2, 0x49, 0xd1, + 0x75, 0x58, 0x9c, 0x6a, 0xde, 0xf0, 0x90, 0x1e, 0x03, 0xe4, 0x92, 0xc6, 0xd4, 0xc7, 0xa2, 0x3b, + 0x50, 0x99, 0x99, 0xbc, 0xa0, 0x6a, 0xfe, 0x49, 0x54, 0x8c, 0xba, 0x1c, 0x90, 0x34, 0x5c, 0xf4, + 0x39, 0x48, 0x61, 0x8d, 0x09, 0x36, 0xc7, 0xde, 0x61, 0x7d, 0x21, 0xad, 0x56, 0x2d, 0x20, 0x6b, + 0x53, 0x2a, 0xb9, 0x07, 0x0b, 0xb4, 0x67, 0x68, 0x09, 0xa0, 0x3f, 0x68, 0x0c, 0x9a, 0x2a, 0x3f, + 0x7a, 0x22, 0xca, 0xc1, 0xcb, 0x03, 0xf5, 0x49, 0x77, 0xbf, 0xb3, 0x23, 0x65, 0x88, 0x2e, 0x33, + 0xe0, 0xf3, 0x46, 0xbb, 0xb5, 0x23, 0x65, 0xd1, 0x32, 0x54, 0x19, 0xa0, 0xd5, 0x61, 0xa0, 0x9c, + 0xfc, 0x10, 0x0a, 0xac, 0xe3, 0x84, 0x5a, 0x69, 0x36, 0xfa, 0xdd, 0x81, 0xcf, 0xb3, 0x0a, 0x25, + 0x0a, 0xe8, 0xa8, 0x8d, 0xbe, 0x94, 0x21, 0x95, 0x79, 0xb1, 0xdd, 0xec, 0xec, 0xd2, 0xfb, 0x86, + 0xff, 0xb6, 0x00, 0x79, 0x7a, 0x70, 0x72, 0x03, 0xf2, 0xe6, 0xc4, 0x31, 0x84, 0x1d, 0x80, 0x35, + 0x9e, 0xe0, 0xdb, 0xfe, 0x35, 0xdf, 0xed, 0x86, 0x79, 0xa2, 0x50, 0x0a, 0x74, 0x13, 0x0a, 0xb6, + 0xe6, 0x79, 0x8e, 0xbf, 0xa1, 0x4b, 0xa7, 0xe5, 0x34, 0xe8, 0x26, 0xe4, 0xb4, 0x31, 0xe6, 0x47, + 0x21, 0x9b, 0x09, 0xd2, 0x81, 0x7f, 0x7b, 0xa8, 0x10, 0x32, 0x62, 0x34, 0x0e, 0xb0, 0xeb, 0x1f, + 0x87, 0xd0, 0xdf, 0xc4, 0x8b, 0x19, 0xae, 0xfa, 0xd2, 0xf0, 0x0e, 0x75, 0x47, 0x7b, 0xe9, 0x9f, + 0x85, 0x18, 0xee, 0xb7, 0x1c, 0x82, 0x3e, 0x05, 0x38, 0x0a, 0x94, 0xa0, 0xbe, 0x18, 0xdf, 0xc2, + 0x84, 0x0a, 0xa2, 0x08, 0x74, 0xe8, 0x0e, 0xac, 0x9a, 0x96, 0x6a, 0x4c, 0x6d, 0xb2, 0xf7, 0xf4, + 0x42, 0xfe, 0x45, 0xb6, 0x2d, 0x37, 0xad, 0x16, 0x47, 0x05, 0xed, 0x84, 0xbe, 0xbd, 0x74, 0xc6, + 0xc1, 0xce, 0x25, 0x00, 0xd7, 0x9a, 0x39, 0x43, 0xac, 0x6a, 0xae, 0x59, 0x07, 0x6a, 0x01, 0x4b, + 0x0c, 0xd2, 0x70, 0x4d, 0xe2, 0xdd, 0x38, 0xda, 0xd0, 0xeb, 0x65, 0xe6, 0xc1, 0x18, 0xa0, 0xa5, + 0x73, 0xef, 0xe6, 0x61, 0x07, 0xeb, 0xf5, 0x0a, 0x95, 0x25, 0x28, 0xa3, 0x55, 0xba, 0x70, 0x26, + 0xb8, 0x5e, 0xa5, 0x08, 0x56, 0x40, 0x37, 0x40, 0x32, 0x5c, 0x75, 0xe4, 0x58, 0x53, 0x15, 0x1f, + 0x7b, 0xd8, 0x31, 0xb5, 0x49, 0x7d, 0x89, 0x12, 0x2c, 0x19, 0xee, 0x13, 0xc7, 0x9a, 0x36, 0x39, + 0x94, 0x0c, 0xa5, 0x7f, 0x3a, 0xaf, 0x1a, 0x76, 0xbd, 0x46, 0x9b, 0x06, 0x1f, 0xd4, 0xb2, 0x83, + 0x93, 0x62, 0x29, 0x3c, 0x29, 0x46, 0x37, 0x01, 0x19, 0xae, 0xea, 0xfb, 0x75, 0xc3, 0xa4, 0x63, + 0x58, 0x5f, 0x66, 0xb7, 0x04, 0x86, 0xdb, 0x61, 0x88, 0x16, 0x83, 0xa3, 0xcb, 0x00, 0x86, 0x8e, + 0x4d, 0xcf, 0x18, 0x19, 0xd8, 0xa9, 0x23, 0xda, 0x75, 0x01, 0x82, 0x3e, 0x04, 0x69, 0x62, 0x0d, + 0xb5, 0x89, 0x2a, 0x50, 0xad, 0x50, 0xaa, 0x1a, 0x85, 0xb7, 0x42, 0x52, 0x22, 0xed, 0xc4, 0x31, + 0xd4, 0x03, 0xc3, 0xd4, 0x9c, 0x93, 0xfa, 0x2a, 0x95, 0x09, 0x08, 0xe8, 0x31, 0x85, 0x10, 0x67, + 0xcf, 0xb4, 0xcc, 0x27, 0xb9, 0x70, 0x35, 0x77, 0xa3, 0xa2, 0x54, 0x18, 0x90, 0x11, 0xc9, 0xcf, + 0xa0, 0x2c, 0x9e, 0x1d, 0xae, 0x41, 0x81, 0x1d, 0x22, 0x73, 0x7f, 0xc5, 0x4b, 0xe1, 0xe1, 0x69, + 0xf6, 0xb4, 0xc3, 0xd3, 0x29, 0x2c, 0x27, 0x4e, 0xa5, 0xe7, 0xb2, 0xfc, 0x0a, 0xaa, 0x13, 0x4a, + 0xa7, 0x5a, 0xb6, 0xb0, 0x17, 0x4a, 0x3f, 0xe1, 0xee, 0x52, 0x12, 0xa5, 0x32, 0x11, 0x4a, 0xf2, + 0x3f, 0xca, 0x43, 0xbe, 0x87, 0xb1, 0x83, 0x3e, 0x87, 0x8a, 0x66, 0xdb, 0x93, 0x13, 0x35, 0x72, + 0x8c, 0x23, 0x78, 0xc3, 0x06, 0xc1, 0xf2, 0x10, 0xa1, 0xac, 0x85, 0x05, 0x74, 0x0d, 0xf2, 0x43, + 0xcb, 0x1c, 0xf1, 0x43, 0x5a, 0x14, 0xbd, 0x56, 0xda, 0xb6, 0xcc, 0x91, 0x42, 0xf1, 0xe8, 0x21, + 0x54, 0xf1, 0xc1, 0xd8, 0x56, 0xa7, 0xb3, 0x89, 0x67, 0x1c, 0x5a, 0x36, 0x5f, 0xb1, 0x6b, 0x61, + 0x85, 0xe6, 0xc1, 0xd8, 0xde, 0xe3, 0x58, 0xa5, 0x82, 0x85, 0x12, 0x6a, 0x40, 0x8d, 0x05, 0x9a, + 0x0e, 0x1e, 0x4d, 0xf0, 0xd0, 0xb3, 0x1c, 0x7e, 0x1f, 0x51, 0x17, 0xad, 0xe1, 0xcc, 0xc3, 0x8a, + 0x8f, 0x57, 0x96, 0x9c, 0x48, 0x19, 0x7d, 0xe8, 0xfb, 0x84, 0x85, 0xb4, 0xfb, 0xaf, 0x88, 0x33, + 0xb8, 0x01, 0x05, 0xb2, 0x39, 0x72, 0xdc, 0x7a, 0x21, 0xbe, 0x0e, 0x07, 0x14, 0xae, 0x70, 0x3c, + 0xd9, 0xb8, 0x7b, 0x8e, 0x66, 0xba, 0x34, 0x10, 0x59, 0x8c, 0x33, 0x1e, 0xf8, 0x28, 0x25, 0xa4, + 0x22, 0x23, 0xcd, 0xba, 0xc2, 0xf7, 0x38, 0xc5, 0xf8, 0x48, 0xd3, 0x7e, 0xf4, 0x29, 0x52, 0x61, + 0xe1, 0x35, 0x2b, 0xa0, 0x1d, 0x90, 0xc6, 0x8e, 0x36, 0xc4, 0xa3, 0xd9, 0x44, 0x75, 0x88, 0x51, + 0x73, 0x3c, 0x6e, 0x28, 0x84, 0xdd, 0xef, 0x2e, 0xa7, 0x50, 0x18, 0x81, 0x52, 0x1b, 0x47, 0x01, + 0xe8, 0x36, 0x94, 0xb4, 0x91, 0xa1, 0x92, 0x80, 0xc6, 0xad, 0x03, 0xd5, 0xc5, 0x65, 0x61, 0x9a, + 0x47, 0x06, 0x0d, 0x78, 0x8a, 0x1a, 0xfb, 0xe1, 0xca, 0xff, 0x34, 0x0f, 0xa5, 0xe0, 0x6a, 0xef, + 0x0d, 0xf4, 0xe4, 0xa3, 0x88, 0x9e, 0xac, 0xa7, 0x5c, 0x3f, 0xfe, 0x05, 0x52, 0x96, 0x9b, 0x90, + 0x37, 0xcc, 0x91, 0xc5, 0x75, 0xa5, 0x9e, 0x22, 0x2c, 0x53, 0x18, 0x4a, 0xf5, 0x07, 0x7d, 0x11, + 0xf5, 0xe5, 0x29, 0xd4, 0x62, 0xd7, 0xb0, 0x73, 0xed, 0xd7, 0xa5, 0xc8, 0xbd, 0x34, 0x7f, 0xc9, + 0x12, 0x5e, 0x7f, 0xff, 0x87, 0x0c, 0x94, 0x05, 0x75, 0x42, 0x9f, 0x41, 0xc9, 0x30, 0xa3, 0x8a, + 0x77, 0xda, 0x11, 0x4a, 0xd1, 0x30, 0x79, 0xc5, 0x2f, 0xa1, 0x8a, 0x8f, 0xc9, 0x60, 0xfa, 0x95, + 0xb3, 0x67, 0x56, 0xae, 0xb0, 0x0a, 0x21, 0x03, 0x63, 0x2a, 0x32, 0xc8, 0x9d, 0xcd, 0x80, 0x55, + 0xe0, 0xb7, 0x29, 0x7f, 0x27, 0x03, 0x65, 0x66, 0xcc, 0xdb, 0xc6, 0xd4, 0x78, 0x85, 0x5d, 0x3c, + 0x7a, 0x0f, 0x2a, 0x53, 0xed, 0x58, 0x0d, 0x2e, 0x31, 0xd9, 0x6e, 0xa7, 0x3c, 0xd5, 0x8e, 0x7b, + 0xfe, 0x55, 0xe5, 0xa7, 0xb0, 0xe6, 0xf2, 0x27, 0x1d, 0xaa, 0x77, 0xe8, 0x60, 0xf7, 0xd0, 0x9a, + 0xe8, 0xaa, 0x3d, 0xf4, 0xf8, 0x9e, 0x7b, 0xd5, 0xc7, 0x0e, 0x7c, 0x64, 0x6f, 0xe8, 0xc9, 0xff, + 0x33, 0x0f, 0x45, 0xdf, 0x44, 0x13, 0x47, 0xa7, 0xcd, 0xbc, 0x43, 0xd5, 0xd6, 0x5c, 0xf7, 0xa5, + 0xe5, 0xe8, 0x7c, 0xa2, 0x2a, 0x04, 0xd8, 0xe3, 0x30, 0x74, 0x95, 0xde, 0x4d, 0x0e, 0x1d, 0xc3, + 0x16, 0x9e, 0x60, 0x88, 0x20, 0xb4, 0x01, 0x45, 0xe6, 0x7b, 0x35, 0xd7, 0xdf, 0xef, 0xd3, 0x72, + 0xc3, 0x25, 0x6e, 0x39, 0x88, 0x0c, 0xfc, 0x0d, 0x5d, 0x9e, 0x72, 0xa8, 0xf9, 0xf0, 0x06, 0xdf, + 0xd8, 0xad, 0xc3, 0x22, 0x55, 0x0b, 0xcd, 0xe5, 0xdb, 0xfa, 0x02, 0x29, 0x36, 0xdc, 0x98, 0xbe, + 0x14, 0x62, 0xfa, 0x42, 0xa2, 0x1e, 0x8a, 0xa6, 0x7b, 0xfa, 0x45, 0x5a, 0xb3, 0x48, 0x00, 0x74, + 0x4f, 0xdf, 0x81, 0x65, 0x07, 0x4f, 0xad, 0x23, 0xac, 0xda, 0x8e, 0x71, 0xa4, 0x79, 0x24, 0x72, + 0xa2, 0x6b, 0x29, 0x72, 0xaf, 0xeb, 0x0f, 0xc8, 0x6d, 0x85, 0xd2, 0xf6, 0x18, 0x69, 0xc3, 0x55, + 0x6a, 0x4e, 0x14, 0x40, 0x82, 0x16, 0xb6, 0x2c, 0x47, 0x13, 0xcd, 0x56, 0x75, 0x6d, 0x6a, 0x1b, + 0xe6, 0x98, 0x2e, 0xaf, 0x22, 0xd9, 0xe3, 0xcf, 0x3c, 0xfc, 0x64, 0xa2, 0xd9, 0x3b, 0x0c, 0x8e, + 0x3e, 0x80, 0x25, 0x17, 0x9b, 0xba, 0xca, 0xdf, 0xab, 0x78, 0x27, 0x3c, 0x66, 0xab, 0x12, 0xe8, + 0xb6, 0x0f, 0x44, 0xb7, 0x00, 0x85, 0xe1, 0x53, 0xf0, 0xc4, 0x8b, 0x05, 0x70, 0xcb, 0x41, 0x14, + 0xe5, 0x23, 0x90, 0xc4, 0x2e, 0xb5, 0x2a, 0xec, 0x40, 0xe6, 0xc8, 0x19, 0xa1, 0xab, 0x50, 0xd1, + 0x26, 0x13, 0xeb, 0xa5, 0x4a, 0x74, 0x41, 0x73, 0x69, 0x18, 0x57, 0x55, 0x80, 0xc2, 0xba, 0x2f, + 0xcd, 0x86, 0x8b, 0xae, 0x41, 0xcd, 0xc1, 0xf6, 0x44, 0x1b, 0x62, 0xd5, 0x1f, 0x64, 0x16, 0xca, + 0x55, 0x39, 0xb8, 0x17, 0x8c, 0xb5, 0xa6, 0x4f, 0x0d, 0x53, 0x25, 0x8a, 0x43, 0x03, 0xb9, 0xa2, + 0x52, 0xa2, 0x90, 0x1d, 0xeb, 0xa5, 0x29, 0xdf, 0x85, 0x5a, 0x6c, 0x88, 0x84, 0x4b, 0x6e, 0xbe, + 0xa1, 0xa7, 0x9b, 0x61, 0xa5, 0xd9, 0x6b, 0x37, 0xb6, 0x9b, 0x52, 0x56, 0xfe, 0x27, 0x39, 0xa8, + 0x46, 0x6c, 0xfd, 0x6f, 0x41, 0xeb, 0x04, 0x55, 0xca, 0x47, 0x54, 0xe9, 0x1a, 0xd4, 0x42, 0x55, + 0x52, 0xe9, 0x49, 0xcf, 0x02, 0x7b, 0x52, 0x14, 0xe8, 0x53, 0x47, 0x9b, 0xe2, 0xa8, 0x4e, 0x15, + 0x62, 0x3a, 0xd5, 0x4f, 0xd3, 0xa9, 0x45, 0xaa, 0x53, 0xd7, 0xe7, 0xf8, 0xb7, 0xd7, 0x55, 0xac, + 0xe2, 0xb9, 0x15, 0xab, 0x94, 0xa2, 0x58, 0xaf, 0x33, 0x5d, 0xff, 0x37, 0x07, 0x4b, 0x51, 0x6f, + 0xf7, 0x7b, 0x3f, 0x5f, 0x83, 0xf9, 0xf3, 0x75, 0x63, 0x9e, 0x8b, 0xff, 0xdd, 0x4c, 0x18, 0xd9, + 0x9a, 0x78, 0x96, 0xa7, 0x4d, 0x54, 0xb6, 0x67, 0x60, 0xd6, 0x02, 0x28, 0x88, 0x6c, 0x17, 0x5c, + 0xc2, 0x87, 0x13, 0xf8, 0x9e, 0xa1, 0xcc, 0xf8, 0x30, 0x1a, 0x0e, 0x7c, 0x9d, 0x89, 0x7f, 0x06, + 0x15, 0x31, 0xb8, 0x42, 0x75, 0x58, 0x64, 0x27, 0xb3, 0x3a, 0x7f, 0xb9, 0xe5, 0x17, 0xa9, 0x6f, + 0xe2, 0x54, 0xaa, 0xe7, 0x4d, 0x02, 0xdf, 0xc4, 0x61, 0x03, 0x6f, 0x22, 0xff, 0x49, 0x06, 0x96, + 0xa2, 0xb1, 0x16, 0x71, 0x57, 0xb1, 0xf0, 0x4c, 0x1d, 0x4e, 0x0c, 0xff, 0x5a, 0xa4, 0xa8, 0xac, + 0x46, 0x63, 0xb1, 0x6d, 0x8a, 0x43, 0x0f, 0x61, 0x33, 0x59, 0x6b, 0xe6, 0x7a, 0xd8, 0x09, 0x9f, + 0xa9, 0xac, 0xc7, 0x6b, 0x52, 0x7c, 0x4b, 0x97, 0xff, 0x7c, 0x91, 0xc5, 0xb0, 0xbf, 0x2d, 0x35, + 0xbe, 0x0d, 0xc5, 0x29, 0x76, 0x5d, 0x6d, 0x8c, 0x5d, 0x1e, 0x7a, 0x0a, 0xfb, 0xa2, 0x3d, 0x8e, + 0x51, 0x02, 0x9a, 0x54, 0xe7, 0xb8, 0x70, 0xa6, 0x73, 0x2c, 0x9c, 0xe2, 0x1c, 0x17, 0x4f, 0x75, + 0x8e, 0xc5, 0xd8, 0xc2, 0xb8, 0x01, 0x85, 0x1f, 0x67, 0x78, 0x86, 0xdd, 0xe4, 0xc1, 0xc3, 0x37, + 0x14, 0xae, 0x70, 0x3c, 0xda, 0x4a, 0x5b, 0x42, 0x4c, 0x3b, 0xcf, 0xb9, 0x30, 0xca, 0xe7, 0x5e, + 0x18, 0x95, 0xb4, 0x85, 0xd1, 0x84, 0xaa, 0x8b, 0x5d, 0xd7, 0xb0, 0x4c, 0xf6, 0xd4, 0x81, 0xba, + 0xb8, 0xa5, 0x7b, 0x57, 0x53, 0xb6, 0x73, 0xb7, 0xfb, 0x8c, 0x90, 0x85, 0xea, 0x15, 0x57, 0x28, + 0xa1, 0x2f, 0xa1, 0xcc, 0xdc, 0x1b, 0x63, 0x52, 0xa3, 0x4c, 0x2e, 0xa7, 0x31, 0x69, 0x10, 0x32, + 0xc6, 0x82, 0x79, 0x44, 0xc6, 0x60, 0x05, 0x16, 0xac, 0x99, 0xa7, 0xfe, 0x48, 0x4f, 0x32, 0xaa, + 0x4a, 0xde, 0x9a, 0x79, 0xdf, 0xa0, 0x55, 0x58, 0x18, 0x4d, 0x2c, 0xdb, 0xa5, 0x87, 0x17, 0x55, + 0x85, 0x15, 0xd0, 0x27, 0x00, 0x64, 0x68, 0x3c, 0xac, 0x0e, 0x35, 0xbb, 0x8e, 0x4e, 0x39, 0xd3, + 0x2a, 0x31, 0xba, 0x6d, 0xcd, 0x26, 0x3b, 0x05, 0xa6, 0x5d, 0xa4, 0xce, 0xca, 0x29, 0x75, 0x98, + 0x12, 0x92, 0x2a, 0x17, 0xa1, 0x44, 0x47, 0x95, 0xae, 0x88, 0x55, 0x76, 0xea, 0xc3, 0x00, 0x2d, + 0x5d, 0x36, 0xa1, 0x22, 0x0e, 0x07, 0x59, 0xf2, 0xe1, 0xe9, 0x72, 0x11, 0xf2, 0xad, 0x9d, 0x76, + 0x93, 0x59, 0x82, 0xed, 0x6e, 0xa7, 0xd3, 0xdc, 0x1e, 0x48, 0x59, 0x7a, 0xae, 0xbd, 0x3d, 0x68, + 0x3d, 0x6f, 0x4a, 0x39, 0x54, 0x81, 0x62, 0xb7, 0xd7, 0xec, 0xf4, 0x9b, 0x9d, 0x81, 0x94, 0x47, + 0x35, 0x28, 0x93, 0xd2, 0x76, 0xb7, 0xf3, 0xa4, 0xa5, 0xec, 0x49, 0x0b, 0x04, 0xd0, 0xec, 0x0f, + 0x1a, 0x8f, 0xdb, 0xad, 0xfe, 0xd3, 0xe6, 0x8e, 0x54, 0x90, 0xb7, 0x00, 0xc2, 0x91, 0x43, 0x05, + 0xc8, 0xee, 0xf7, 0x58, 0x43, 0x3b, 0xa4, 0xc9, 0x0c, 0x7d, 0x08, 0xf7, 0xe4, 0x85, 0x4a, 0xda, + 0x91, 0xff, 0x18, 0x8a, 0xfe, 0xa2, 0x40, 0xb7, 0xa0, 0xe8, 0xe0, 0x21, 0x36, 0x8e, 0xb8, 0xb9, + 0x89, 0xec, 0x36, 0x38, 0x95, 0x12, 0x90, 0xa0, 0x0f, 0x20, 0xef, 0xfa, 0xef, 0x77, 0x53, 0x49, + 0x29, 0x5a, 0xfe, 0xb3, 0x2c, 0x2c, 0x72, 0x08, 0x92, 0xa1, 0x62, 0x5a, 0x9e, 0x31, 0xf2, 0x9f, + 0x12, 0xb3, 0x27, 0x60, 0x11, 0x18, 0xd9, 0xb1, 0xcc, 0xe8, 0xa3, 0x56, 0xfe, 0xfc, 0x8b, 0x97, + 0x10, 0x82, 0xbc, 0x65, 0x63, 0x93, 0x5f, 0xfa, 0xd0, 0xdf, 0xe8, 0x5d, 0x28, 0xfd, 0x80, 0xb1, + 0xad, 0x4d, 0x8c, 0x23, 0xcc, 0x2f, 0x79, 0x42, 0x00, 0xb1, 0x9e, 0x0e, 0x1e, 0x91, 0xb8, 0x9b, + 0xae, 0xe8, 0xbc, 0xe2, 0x17, 0x49, 0x3d, 0xdd, 0x70, 0x87, 0x9a, 0xa3, 0x63, 0x9d, 0xae, 0xe5, + 0xbc, 0x12, 0x02, 0x88, 0x2a, 0x51, 0x4b, 0x4e, 0x57, 0x72, 0x5e, 0x61, 0x05, 0x74, 0x1d, 0x6a, + 0xfe, 0x39, 0xa2, 0xca, 0x05, 0x2c, 0xb2, 0x17, 0x6c, 0x3e, 0x98, 0xbd, 0xc5, 0x8d, 0x10, 0xf2, + 0xbd, 0x57, 0x29, 0x4a, 0xc8, 0x5c, 0x84, 0x7c, 0x1f, 0x0a, 0x6c, 0x89, 0x93, 0x16, 0x0d, 0xd3, + 0x9e, 0x31, 0x33, 0x5c, 0x55, 0x58, 0x81, 0x8c, 0x84, 0x35, 0xf3, 0x08, 0x98, 0x59, 0x77, 0x5e, + 0x92, 0x31, 0x14, 0xd8, 0xde, 0x16, 0xdd, 0x86, 0x02, 0xd9, 0xb3, 0x1b, 0x63, 0x3e, 0x5f, 0x6b, + 0xf1, 0xdd, 0xef, 0x36, 0xc5, 0x2a, 0x9c, 0x0a, 0x7d, 0xe4, 0x1f, 0xc4, 0x64, 0xe3, 0x3b, 0x59, + 0x46, 0x2e, 0x1e, 0xc5, 0xc8, 0xff, 0x3e, 0x03, 0x15, 0x91, 0x0b, 0x31, 0xde, 0x43, 0xcb, 0x34, + 0xf1, 0xd0, 0x53, 0x1d, 0xec, 0x39, 0x27, 0xfe, 0xf4, 0x71, 0xa0, 0x42, 0x60, 0x64, 0x25, 0xd0, + 0x3d, 0x10, 0xbd, 0xf2, 0x66, 0x33, 0x58, 0x24, 0x00, 0xc2, 0x89, 0x04, 0xd9, 0xc1, 0xf4, 0xc4, + 0xaf, 0xf1, 0x96, 0x03, 0x4c, 0x70, 0x97, 0xb7, 0x03, 0x97, 0xa7, 0x86, 0x69, 0x4c, 0x67, 0x53, + 0x55, 0xf3, 0x3f, 0x86, 0x20, 0x3b, 0xbc, 0xf8, 0xc5, 0xde, 0xbb, 0x9c, 0xaa, 0x21, 0x12, 0x05, + 0x97, 0x7c, 0xff, 0x3d, 0x0b, 0x65, 0xa1, 0x7b, 0xbf, 0xa7, 0xdd, 0xa0, 0x67, 0xda, 0x78, 0x6c, + 0x79, 0x86, 0xe6, 0x61, 0x5d, 0x0d, 0x85, 0x63, 0xaa, 0x8d, 0x42, 0xdc, 0x53, 0x5f, 0xcc, 0x7b, + 0x64, 0x25, 0x51, 0x9a, 0xc2, 0x99, 0x27, 0xf4, 0x9c, 0x12, 0xdd, 0x87, 0x22, 0xd9, 0x75, 0xd0, + 0x5a, 0x8b, 0x67, 0xd6, 0x0a, 0x68, 0xe5, 0xff, 0x97, 0x81, 0x52, 0x70, 0x86, 0x42, 0x86, 0x98, + 0xfb, 0xe7, 0xc8, 0xfd, 0x61, 0x85, 0x39, 0x69, 0xee, 0x4e, 0x2f, 0x01, 0x30, 0x22, 0xe1, 0x2a, + 0x91, 0x19, 0xde, 0x1e, 0xe7, 0x31, 0xf5, 0x66, 0x2a, 0x59, 0x96, 0xd6, 0x11, 0x76, 0x4e, 0xf8, + 0x15, 0x7d, 0x65, 0xea, 0xcd, 0x76, 0x7c, 0x18, 0x09, 0x83, 0x48, 0x28, 0x41, 0xe6, 0x61, 0x6a, + 0xe9, 0xfe, 0x05, 0x76, 0x99, 0xc3, 0xf6, 0x2c, 0x1d, 0x13, 0xe7, 0xc6, 0x5d, 0x40, 0xd4, 0xbd, + 0x57, 0x19, 0xd4, 0x97, 0xe6, 0x0a, 0x94, 0x39, 0x19, 0x15, 0x87, 0x39, 0x78, 0xee, 0x3c, 0xa8, + 0x3c, 0xeb, 0xb0, 0xe8, 0x0d, 0x6d, 0x75, 0xea, 0xba, 0x7c, 0x83, 0x5b, 0xf0, 0x86, 0xf6, 0x9e, + 0xeb, 0xca, 0x8f, 0xa0, 0x2c, 0x9c, 0x03, 0xa1, 0xdb, 0xb0, 0x22, 0x1e, 0x1a, 0x45, 0x03, 0xac, + 0x65, 0xe1, 0x90, 0x88, 0x45, 0x57, 0xf2, 0x3f, 0xcb, 0x41, 0x2d, 0x76, 0x12, 0x74, 0x7a, 0xdc, + 0xc7, 0xcf, 0x93, 0x42, 0xd5, 0xac, 0x2a, 0x65, 0x0e, 0xa3, 0xd3, 0x7e, 0x05, 0xca, 0x87, 0x78, + 0x62, 0x63, 0x47, 0xb5, 0xcc, 0x89, 0x3f, 0x6c, 0xc0, 0x40, 0x5d, 0x73, 0x42, 0x8f, 0xd6, 0x75, + 0x3c, 0xc2, 0x8e, 0xa3, 0x4d, 0x18, 0x13, 0x16, 0xef, 0x57, 0x7c, 0x20, 0xe5, 0x72, 0x17, 0x56, + 0x45, 0xb3, 0xac, 0xfa, 0xf2, 0xb0, 0x2b, 0x9a, 0x15, 0x11, 0xd7, 0xe4, 0xb2, 0x7d, 0x04, 0xcb, + 0x13, 0xcb, 0x1c, 0x13, 0xdd, 0xd7, 0x03, 0xfa, 0x02, 0x8b, 0x39, 0x02, 0x84, 0x4f, 0xbc, 0x05, + 0xcb, 0xf4, 0x86, 0x43, 0xa5, 0x23, 0xe2, 0xaa, 0x81, 0xc6, 0x55, 0x95, 0x1a, 0x45, 0xd0, 0x31, + 0xa5, 0x97, 0xdc, 0x84, 0x96, 0x06, 0x50, 0x91, 0x9e, 0xb3, 0x40, 0x8a, 0x6e, 0x4d, 0x14, 0xa1, + 0xf7, 0xd7, 0xf9, 0x6e, 0x85, 0xd3, 0x86, 0x27, 0x03, 0x4b, 0x02, 0x25, 0x09, 0x7a, 0x82, 0xcb, + 0x0a, 0x81, 0x12, 0x28, 0x25, 0xbb, 0xac, 0x10, 0x48, 0x11, 0xe4, 0xa9, 0x76, 0xb1, 0xd3, 0x00, + 0xfa, 0x5b, 0xfe, 0x04, 0xd6, 0xf7, 0xec, 0xd8, 0xbc, 0x71, 0x3b, 0x39, 0x77, 0xf6, 0xe4, 0x7f, + 0x97, 0x81, 0xb5, 0x44, 0x2d, 0x66, 0x95, 0xe6, 0x4f, 0xf9, 0xa6, 0xe0, 0x96, 0xd9, 0xe3, 0xad, + 0xd0, 0x07, 0x5f, 0x06, 0xd0, 0xc2, 0xcf, 0xc7, 0xf8, 0x54, 0x87, 0x10, 0x74, 0x0b, 0x56, 0x48, + 0x60, 0x67, 0x8d, 0x54, 0xc7, 0x38, 0x50, 0x03, 0x36, 0x79, 0xff, 0x3b, 0x33, 0xbd, 0x3b, 0x52, + 0x8c, 0x03, 0x25, 0x74, 0xe9, 0x35, 0x81, 0x9c, 0x7a, 0x77, 0x36, 0xdf, 0x15, 0x9f, 0xb4, 0x4f, + 0x54, 0xf6, 0x57, 0x19, 0x58, 0x4e, 0x74, 0x03, 0xfd, 0x2c, 0xe6, 0x8c, 0xde, 0x13, 0x22, 0x82, + 0xf4, 0x91, 0x0a, 0xfc, 0xd2, 0xfd, 0xa8, 0x5f, 0xba, 0x7a, 0x4a, 0xcd, 0x88, 0x8b, 0xea, 0x43, + 0x95, 0x9f, 0x82, 0xf2, 0xa1, 0x3f, 0xff, 0xe1, 0x9e, 0x30, 0xde, 0xd9, 0xe8, 0x24, 0xfd, 0xe3, + 0x0c, 0x54, 0x38, 0xd7, 0xbe, 0x7f, 0x27, 0xf1, 0xa6, 0x4c, 0x23, 0x93, 0xc8, 0x1c, 0x45, 0x38, + 0x89, 0x9b, 0x50, 0x0c, 0xde, 0xb4, 0x33, 0x4f, 0x10, 0x94, 0x63, 0x13, 0xcc, 0x6c, 0xbd, 0x00, + 0x91, 0xff, 0x5e, 0x0e, 0x2e, 0x72, 0xeb, 0x33, 0x61, 0x2f, 0xed, 0xd8, 0xf5, 0x92, 0xef, 0xb3, + 0x6f, 0x02, 0xd2, 0x26, 0x2f, 0xb5, 0x13, 0x97, 0x04, 0xf7, 0xb6, 0xe6, 0x60, 0x75, 0x1a, 0x68, + 0x98, 0xc4, 0x30, 0xdb, 0x0c, 0xb1, 0x87, 0x75, 0x74, 0x17, 0x2e, 0x18, 0x63, 0xd3, 0x72, 0xc8, + 0xd6, 0x82, 0x6e, 0x7f, 0xfd, 0xfb, 0x6f, 0xfe, 0x9e, 0x99, 0x21, 0x1b, 0x2e, 0xd9, 0x07, 0xb3, + 0x3b, 0x6f, 0xb2, 0x39, 0xf4, 0x2f, 0x26, 0x83, 0x26, 0xc2, 0x50, 0x98, 0x69, 0xe4, 0xba, 0x4f, + 0xc1, 0x9b, 0x52, 0x78, 0x64, 0x8c, 0x1e, 0xc0, 0x46, 0xd0, 0x17, 0xd5, 0x30, 0xb5, 0xa1, 0x47, + 0x2c, 0x39, 0xb3, 0x08, 0x5c, 0x49, 0xd7, 0x03, 0x82, 0x16, 0xc7, 0x33, 0xc3, 0x40, 0xcc, 0x1c, + 0x1b, 0x5c, 0x55, 0x33, 0xc6, 0xb6, 0x7f, 0x75, 0xcc, 0x3f, 0x9d, 0x34, 0xc6, 0x36, 0x7a, 0x00, + 0x9b, 0xbc, 0x33, 0x26, 0x3e, 0xf6, 0x54, 0x7a, 0xc1, 0x39, 0xb6, 0xd5, 0x29, 0xf6, 0x1c, 0x63, + 0xc8, 0xed, 0xd2, 0x1a, 0xa3, 0xe8, 0xe0, 0x63, 0xef, 0xa9, 0x65, 0xb7, 0xc6, 0xf6, 0x1e, 0xc5, + 0xa2, 0x47, 0x70, 0x51, 0x67, 0x0f, 0x83, 0xd4, 0x03, 0xec, 0x7a, 0x6c, 0x2c, 0x5c, 0x7f, 0x88, + 0xa9, 0x9d, 0x2a, 0x2a, 0x75, 0x4e, 0xf2, 0x18, 0xb3, 0x2f, 0x49, 0x82, 0x29, 0x90, 0xff, 0x6e, + 0x0e, 0x36, 0x53, 0x67, 0x85, 0x29, 0xd4, 0x1f, 0x26, 0xe5, 0x77, 0x32, 0x29, 0x19, 0xb8, 0x90, + 0x3a, 0x29, 0xe8, 0x51, 0xcc, 0x72, 0x7d, 0x90, 0xb8, 0xe1, 0x49, 0x5b, 0x5b, 0x81, 0xf5, 0x7a, + 0x10, 0xb5, 0x5e, 0xef, 0x9f, 0x51, 0x3b, 0x62, 0xc1, 0xee, 0xc1, 0xda, 0xbe, 0x8b, 0xe9, 0x81, + 0x8f, 0x3d, 0xa1, 0x5f, 0x9c, 0xb9, 0x67, 0x7a, 0x91, 0xbb, 0x70, 0x21, 0x5e, 0xe7, 0x0c, 0x1f, + 0x22, 0x7f, 0x0f, 0xd0, 0x3c, 0x18, 0xdb, 0x9c, 0xf5, 0x16, 0x2c, 0xb3, 0xa3, 0xea, 0x29, 0xe7, + 0xa1, 0x6a, 0x2e, 0xaf, 0x51, 0xa3, 0x08, 0x9f, 0x77, 0xc3, 0xa5, 0x61, 0x98, 0x76, 0x4c, 0x83, + 0x57, 0xff, 0x0e, 0x9d, 0x06, 0x0b, 0x1c, 0x48, 0x5b, 0x97, 0xff, 0x32, 0x94, 0x08, 0x7b, 0x26, + 0xc5, 0x5b, 0xe7, 0xae, 0x42, 0x9e, 0x70, 0x47, 0x37, 0x63, 0xd3, 0xb4, 0x1a, 0xbd, 0x92, 0x8c, + 0xcd, 0xca, 0x87, 0xd1, 0x59, 0x59, 0x89, 0x12, 0x47, 0x26, 0xe1, 0x2e, 0x40, 0x2b, 0x1c, 0x9d, + 0x84, 0x4c, 0x99, 0x14, 0x99, 0xee, 0x40, 0xa9, 0x15, 0xf4, 0xf8, 0x5c, 0x35, 0x54, 0xc8, 0xb7, + 0xce, 0xe8, 0x45, 0xeb, 0x55, 0x7a, 0xd1, 0x8a, 0xf7, 0xe2, 0xd7, 0x19, 0x90, 0xe2, 0x7a, 0x81, + 0x3e, 0x8f, 0xb5, 0x26, 0xb8, 0xd6, 0x74, 0xbd, 0x0b, 0x5a, 0xfe, 0x69, 0xb4, 0xe5, 0x2b, 0xf3, + 0x2b, 0x46, 0x2e, 0xf0, 0x65, 0xc8, 0xe3, 0x83, 0xb1, 0x9d, 0xfc, 0x12, 0x93, 0x8c, 0xba, 0x42, + 0x71, 0x84, 0xc6, 0x20, 0x34, 0x89, 0xef, 0x1a, 0x5b, 0x94, 0x86, 0xe0, 0xe4, 0xc7, 0xdc, 0xaf, + 0x0d, 0x34, 0x67, 0x8c, 0xbd, 0x3d, 0x3c, 0x3d, 0xc0, 0x8e, 0x7b, 0x68, 0x08, 0x93, 0x14, 0x8d, + 0x61, 0x33, 0xc9, 0x18, 0x56, 0x6e, 0x70, 0x2b, 0x1c, 0xe7, 0x11, 0xcc, 0xda, 0xd9, 0x2c, 0x02, + 0xa3, 0x11, 0xe7, 0x71, 0xa6, 0xd1, 0x48, 0x17, 0xfc, 0xbc, 0x46, 0x23, 0x55, 0x64, 0x7f, 0xa6, + 0xbf, 0x87, 0xcb, 0x6d, 0xcb, 0x1c, 0xb7, 0x49, 0xf4, 0xf0, 0x8a, 0x21, 0xe8, 0x39, 0x36, 0x10, + 0xf2, 0x7f, 0xcd, 0xc0, 0xa5, 0x79, 0xfc, 0x7f, 0x93, 0xc1, 0x6a, 0x6a, 0x98, 0x9f, 0x4f, 0x0f, + 0xf3, 0x1f, 0xc2, 0x66, 0x82, 0xd6, 0x51, 0xf1, 0xb1, 0x6d, 0x38, 0xc1, 0x26, 0x65, 0x3d, 0x56, + 0xc9, 0x69, 0x32, 0xb4, 0xfc, 0xf7, 0x33, 0x50, 0x9f, 0xd7, 0x41, 0xf4, 0x55, 0x6c, 0x5e, 0x85, + 0xeb, 0x89, 0xd3, 0x07, 0x3d, 0x98, 0xda, 0x47, 0xd1, 0xa9, 0xbd, 0x7e, 0x36, 0x83, 0xc8, 0xec, + 0xfe, 0xab, 0x05, 0x58, 0xe4, 0xf1, 0x27, 0x7a, 0x06, 0x2b, 0x53, 0x5b, 0x4d, 0x3c, 0x25, 0x60, + 0x92, 0x5d, 0x3c, 0x25, 0x4c, 0x56, 0x96, 0xa7, 0x89, 0x00, 0xfd, 0xe3, 0xa0, 0x67, 0x89, 0x87, + 0x20, 0x91, 0x28, 0x3a, 0xe8, 0xc8, 0x4d, 0xbf, 0x23, 0x89, 0x27, 0x20, 0x62, 0x7c, 0xec, 0xaf, + 0xfc, 0xf8, 0xfb, 0x94, 0xfc, 0xb9, 0xdf, 0xa7, 0x7c, 0x0b, 0xeb, 0xfe, 0x96, 0x99, 0xbb, 0x4a, + 0xfe, 0xaa, 0xca, 0xe5, 0xaf, 0x40, 0xae, 0x9c, 0xe1, 0x52, 0x95, 0x0b, 0x4e, 0xaa, 0x63, 0x7f, + 0x0a, 0x68, 0xe6, 0xe2, 0xd0, 0x11, 0x31, 0xeb, 0x5c, 0x88, 0xbf, 0x20, 0x88, 0x1b, 0x34, 0x45, + 0x9a, 0xc5, 0xed, 0xe8, 0x03, 0xa8, 0xb2, 0xb3, 0x3c, 0x75, 0x62, 0x4c, 0x0d, 0xcf, 0xe5, 0x87, + 0x23, 0x42, 0xef, 0x84, 0x37, 0x06, 0x4a, 0xc5, 0x0e, 0x0b, 0x6e, 0xd8, 0x3d, 0x8f, 0x2e, 0x6a, + 0x75, 0x1a, 0xac, 0x6a, 0xfe, 0xa2, 0xe4, 0xca, 0x19, 0x8b, 0x9f, 0x77, 0x2f, 0x61, 0x82, 0x34, + 0xb8, 0x48, 0xf6, 0xd5, 0x2a, 0xdb, 0x71, 0xcf, 0x79, 0x70, 0x22, 0x9f, 0xad, 0x7e, 0x4a, 0x7d, + 0x32, 0x6f, 0x35, 0x7c, 0x0c, 0x25, 0x4d, 0xd7, 0x85, 0xab, 0xb0, 0xc8, 0x7d, 0x0a, 0xff, 0xea, + 0xd9, 0x55, 0x8a, 0x1a, 0xff, 0x25, 0x37, 0x83, 0xcf, 0xfc, 0x85, 0x40, 0x86, 0x9b, 0x00, 0xdf, + 0x58, 0xf0, 0x22, 0xda, 0x80, 0x22, 0xbd, 0x77, 0x98, 0x6a, 0xc7, 0xdc, 0x0e, 0x2d, 0x92, 0xf2, + 0x9e, 0x76, 0x2c, 0xef, 0xd0, 0x37, 0xf8, 0xd1, 0xd8, 0xe6, 0xd5, 0xb9, 0xfc, 0x00, 0x45, 0x9f, + 0x0b, 0xba, 0x13, 0x5b, 0xd7, 0xf5, 0x64, 0x37, 0x62, 0xea, 0x7f, 0x2b, 0xba, 0x8e, 0xd7, 0x93, + 0x15, 0x22, 0xeb, 0x76, 0x06, 0x05, 0xfe, 0x68, 0xf0, 0x22, 0x94, 0x0c, 0x5b, 0x8d, 0xbc, 0xbb, + 0x29, 0x1a, 0xfe, 0x8b, 0xc2, 0x6b, 0x50, 0x9b, 0x6a, 0xee, 0x0f, 0x3c, 0x88, 0x57, 0xa7, 0x3c, + 0xb9, 0x43, 0x55, 0xa9, 0x12, 0x30, 0x0b, 0xe0, 0xf7, 0x0c, 0x33, 0x41, 0xa7, 0x1d, 0xf3, 0xab, + 0x2e, 0x91, 0x4e, 0x3b, 0x96, 0xff, 0x3c, 0x03, 0x10, 0x7e, 0xc9, 0xf7, 0x76, 0x3f, 0x2e, 0x24, + 0xb0, 0x89, 0xe1, 0x7a, 0xf4, 0x8d, 0x75, 0x49, 0xa1, 0xbf, 0xe9, 0x67, 0x9f, 0xd1, 0xef, 0xfa, + 0xa5, 0xf8, 0x2a, 0x08, 0x3f, 0xe6, 0x97, 0x15, 0x28, 0xee, 0x69, 0xde, 0xf0, 0x90, 0xc8, 0x76, + 0x0f, 0x80, 0x3e, 0x98, 0x9e, 0xf3, 0x15, 0x36, 0xa5, 0x63, 0x5f, 0x61, 0x4f, 0xfd, 0x9f, 0xa9, + 0x9f, 0x3c, 0x0e, 0xa1, 0x12, 0xdb, 0xee, 0x94, 0xf9, 0x28, 0x09, 0x8c, 0x85, 0xf5, 0x2d, 0x12, + 0x53, 0xfe, 0x30, 0x09, 0x7e, 0xa3, 0x35, 0x28, 0x08, 0xfb, 0xa9, 0xaa, 0xc2, 0x4b, 0xf2, 0x7f, + 0x5c, 0x00, 0xd8, 0xb6, 0x4c, 0xdd, 0x60, 0xa6, 0xe4, 0x2e, 0x00, 0x37, 0x00, 0xe1, 0xb7, 0x94, + 0x28, 0x26, 0x7b, 0x1f, 0x7b, 0x4a, 0x89, 0x51, 0x91, 0xee, 0xfe, 0x14, 0x2a, 0xc1, 0xd5, 0x22, + 0xa9, 0x94, 0x9d, 0x5b, 0x29, 0x78, 0xb9, 0x4b, 0xaa, 0xfd, 0x11, 0x2c, 0xc5, 0x36, 0x7a, 0x49, + 0xf3, 0x2b, 0x74, 0x48, 0xa9, 0x68, 0xe2, 0x58, 0xdc, 0x83, 0xb2, 0x5f, 0x9b, 0xb4, 0x99, 0x9f, + 0x2f, 0x28, 0xab, 0x46, 0x5a, 0xfc, 0x2c, 0x48, 0xf1, 0xe2, 0x9d, 0xd0, 0x5a, 0x0b, 0x73, 0x6b, + 0x55, 0x02, 0x42, 0x52, 0xf1, 0x0b, 0x58, 0x26, 0xbb, 0xb8, 0x68, 0xe5, 0xc2, 0xdc, 0xca, 0x35, + 0x7c, 0xec, 0x6d, 0x8b, 0xf5, 0xaf, 0x40, 0xd9, 0xb1, 0x7f, 0x30, 0x88, 0xc5, 0x9a, 0x4d, 0xd8, + 0xab, 0xbc, 0x05, 0x05, 0x1c, 0xf6, 0x45, 0xda, 0x6c, 0xe2, 0xa1, 0x47, 0x00, 0xe1, 0x57, 0x4e, + 0xfc, 0xcd, 0x90, 0x70, 0x55, 0x18, 0xce, 0x0f, 0x37, 0x9c, 0x54, 0x79, 0x82, 0x8f, 0xa0, 0xd0, + 0x63, 0x58, 0x99, 0x10, 0xa3, 0x19, 0x93, 0xb0, 0x34, 0x57, 0xc2, 0x65, 0x4a, 0x1e, 0x91, 0xf1, + 0x3a, 0x48, 0xe1, 0x56, 0xd5, 0x54, 0xe9, 0x72, 0x00, 0xba, 0x1c, 0xaa, 0x26, 0xdf, 0xa1, 0x9a, + 0x6d, 0xb2, 0x2e, 0xee, 0x40, 0xd9, 0x7f, 0xad, 0xa7, 0x1a, 0x66, 0xbd, 0x1c, 0x5f, 0x1a, 0xfc, + 0xac, 0xa8, 0xc4, 0x9f, 0xeb, 0xb5, 0x4c, 0xf9, 0x10, 0x4a, 0x81, 0xd8, 0x68, 0x05, 0x6a, 0xfc, + 0x8b, 0x8d, 0xef, 0x7a, 0xc1, 0x87, 0x03, 0xeb, 0xb0, 0x22, 0x00, 0x5b, 0x9d, 0x41, 0x53, 0xe9, + 0x34, 0xda, 0x52, 0x26, 0x86, 0x68, 0xbe, 0xe0, 0x88, 0x2c, 0x5a, 0x05, 0x49, 0x40, 0xf0, 0xef, + 0x7c, 0x64, 0x17, 0x6a, 0x41, 0xa7, 0x1a, 0x2c, 0x51, 0xd1, 0x17, 0x50, 0xd6, 0x98, 0xaf, 0x15, + 0x16, 0xcd, 0x25, 0x71, 0x6c, 0x23, 0xf4, 0x6c, 0xdd, 0x68, 0xc1, 0x6f, 0x74, 0x15, 0xca, 0xfe, + 0xa8, 0x1a, 0xc1, 0x07, 0x68, 0x22, 0x48, 0xfe, 0x4b, 0x50, 0xda, 0xc3, 0x3a, 0x6f, 0xee, 0xf3, + 0xb4, 0xe6, 0xd6, 0xc5, 0x4b, 0x43, 0x7d, 0x4e, 0x43, 0xab, 0xb0, 0x70, 0xa4, 0x4d, 0x66, 0xcc, + 0x04, 0xe4, 0x14, 0x56, 0x90, 0x55, 0xa8, 0x35, 0xdc, 0x9e, 0x83, 0x6d, 0x6c, 0xfa, 0x4d, 0x48, + 0x90, 0xd3, 0x5c, 0x93, 0x87, 0xf1, 0xe4, 0x27, 0x59, 0xdb, 0x84, 0x42, 0x0b, 0x6e, 0xd0, 0x58, + 0x09, 0xc9, 0x50, 0x25, 0x71, 0xc1, 0x04, 0x8f, 0x3c, 0x75, 0x6a, 0xb9, 0xfe, 0xe7, 0x7f, 0xe5, + 0x99, 0x8b, 0xdb, 0x78, 0xe4, 0xed, 0x59, 0xae, 0x27, 0x3f, 0x82, 0x2a, 0x7f, 0xfe, 0xce, 0xd9, + 0x9f, 0xfa, 0x39, 0x94, 0x8b, 0x27, 0x23, 0x1e, 0xf0, 0xd2, 0xdf, 0xf2, 0x75, 0xa8, 0xb5, 0xe9, + 0x5d, 0x86, 0x83, 0x47, 0x9c, 0x41, 0xd0, 0x11, 0x7e, 0xcb, 0xc7, 0x3a, 0xf2, 0x9f, 0x72, 0xb0, + 0xc8, 0x08, 0xdc, 0xf0, 0xc1, 0x29, 0xeb, 0x7e, 0xd2, 0x78, 0x53, 0x75, 0x61, 0xd4, 0xfc, 0xc1, + 0x29, 0xe7, 0xfd, 0x19, 0x94, 0xc2, 0xdb, 0xfb, 0x6c, 0xfc, 0xa5, 0x69, 0x6c, 0x2e, 0x95, 0x90, + 0x16, 0x7d, 0x00, 0xb9, 0x29, 0x8f, 0xc6, 0x23, 0xdb, 0xcb, 0x60, 0x3e, 0x14, 0x82, 0x47, 0x9f, + 0x03, 0x10, 0xb3, 0xc2, 0xc6, 0x9b, 0x5b, 0x95, 0x8d, 0x88, 0x41, 0x12, 0xa7, 0x82, 0x1a, 0x17, + 0x06, 0x40, 0x5f, 0x40, 0x35, 0x62, 0x23, 0xb8, 0x71, 0x39, 0x45, 0xba, 0x8a, 0x68, 0x26, 0xd0, + 0x5d, 0x58, 0xe4, 0xdf, 0x27, 0x70, 0xcb, 0x22, 0x28, 0x4d, 0x64, 0x82, 0x14, 0x9f, 0x8e, 0x08, + 0xcb, 0x6f, 0x96, 0x1c, 0x3c, 0xe2, 0x91, 0xda, 0x86, 0x18, 0x06, 0x45, 0xe6, 0xc5, 0xbf, 0x74, + 0x72, 0xf0, 0x08, 0x3d, 0x86, 0x5a, 0xcc, 0x60, 0xf0, 0x10, 0xed, 0x14, 0x71, 0x97, 0xa2, 0x36, + 0x43, 0xfe, 0x65, 0x06, 0x4a, 0xc1, 0x77, 0xe3, 0xa9, 0x1f, 0x51, 0x7f, 0x0a, 0x30, 0x0c, 0x2c, + 0x17, 0x9f, 0xad, 0xd5, 0x34, 0xab, 0xa6, 0x08, 0x74, 0xe8, 0x23, 0x58, 0x64, 0x6a, 0xe1, 0xf2, + 0xd9, 0x12, 0xdf, 0x02, 0x33, 0x84, 0xe2, 0x53, 0xc8, 0xdf, 0x40, 0x81, 0x07, 0xd7, 0x69, 0x02, + 0x7c, 0x02, 0x10, 0x49, 0x56, 0x91, 0x9b, 0xf7, 0xd5, 0xbb, 0x40, 0x46, 0xcf, 0x17, 0xe2, 0x6f, + 0x6d, 0xdf, 0xea, 0x37, 0xe2, 0x91, 0x84, 0x12, 0xf9, 0x73, 0x24, 0x94, 0x58, 0xd2, 0xf1, 0x48, + 0x9b, 0x4d, 0x3c, 0x7f, 0xb9, 0x2c, 0x9c, 0xb6, 0x5c, 0xaa, 0x9c, 0x98, 0x15, 0xe5, 0x23, 0xa8, + 0x12, 0x6c, 0xf8, 0xc9, 0xe4, 0x6f, 0x27, 0x0d, 0x86, 0xfc, 0xb7, 0x32, 0x90, 0x53, 0x2c, 0x0d, + 0x2d, 0x41, 0x56, 0xf3, 0x0f, 0x8a, 0xb2, 0x1a, 0xcd, 0x2c, 0xc8, 0x22, 0x87, 0x09, 0xf6, 0x03, + 0xc2, 0x10, 0x40, 0x0c, 0xd9, 0x54, 0xa3, 0x28, 0x16, 0x03, 0xf2, 0x92, 0xf0, 0xbc, 0x3b, 0x1f, + 0x79, 0xde, 0xed, 0x7f, 0x19, 0x92, 0x70, 0xe4, 0x4a, 0xef, 0x59, 0x2b, 0x7c, 0xec, 0x2f, 0xff, + 0xf3, 0x0c, 0xe4, 0x9e, 0x3b, 0xa3, 0xd4, 0x69, 0x7c, 0x1f, 0xb2, 0x8e, 0x2e, 0x68, 0x67, 0xf2, + 0xfd, 0x4b, 0xd6, 0xd1, 0xd1, 0x5d, 0x28, 0xf1, 0xf7, 0xd9, 0x8e, 0xc7, 0x3f, 0xc5, 0x9b, 0xf3, + 0x58, 0x86, 0x91, 0x29, 0x34, 0xf9, 0x03, 0x7f, 0x13, 0xee, 0x78, 0x7c, 0x9e, 0xe7, 0x54, 0x61, + 0x64, 0x8a, 0x47, 0x46, 0x8b, 0xe7, 0xb8, 0xaa, 0x2a, 0x59, 0x43, 0x97, 0x7f, 0x95, 0x81, 0xd5, + 0x1d, 0x36, 0x9f, 0x74, 0x8e, 0x77, 0x0c, 0xd7, 0xd3, 0xcc, 0x21, 0x46, 0xf7, 0x21, 0x38, 0xd7, + 0x66, 0x47, 0xd6, 0xaa, 0xce, 0x51, 0x7c, 0xac, 0x2f, 0xf8, 0xe8, 0x44, 0x3d, 0x7a, 0x1b, 0x9f, + 0x52, 0x8f, 0x4d, 0xc6, 0x05, 0x1f, 0x1d, 0xa9, 0x27, 0xff, 0xeb, 0x3c, 0x14, 0x58, 0x22, 0xca, + 0xc4, 0x8c, 0x46, 0xde, 0x04, 0x65, 0xa3, 0x6f, 0x82, 0x48, 0xe4, 0x43, 0x22, 0x09, 0x6c, 0xb2, + 0xeb, 0xe6, 0x1c, 0x8b, 0x7c, 0x18, 0x88, 0x5e, 0x37, 0x7f, 0x08, 0x12, 0x27, 0xe0, 0x5e, 0x86, + 0xaf, 0x89, 0x92, 0x52, 0x63, 0xf0, 0x86, 0x0f, 0xa6, 0x5f, 0x95, 0x91, 0xd8, 0x82, 0x28, 0xe0, + 0xc2, 0xd5, 0xdc, 0x8d, 0xaa, 0x12, 0x94, 0xd1, 0xcd, 0xb9, 0x3b, 0xe0, 0x62, 0xca, 0x2e, 0xf7, + 0xfb, 0xf9, 0x1b, 0xf1, 0xc5, 0x57, 0x39, 0x19, 0x9f, 0xb3, 0x1d, 0x1f, 0xc0, 0x9a, 0xbf, 0x62, + 0x63, 0x63, 0xcc, 0x8c, 0xec, 0xe5, 0xc8, 0x62, 0x4b, 0x4c, 0xae, 0xb2, 0xaa, 0xa7, 0x4d, 0xf9, + 0x23, 0xfa, 0x9e, 0x63, 0x84, 0x75, 0xec, 0xb0, 0x57, 0x45, 0xa5, 0xb8, 0x9b, 0xd8, 0x16, 0xd1, + 0x4a, 0x94, 0x3a, 0xf5, 0x53, 0x0d, 0x78, 0xe5, 0x4f, 0x35, 0xe2, 0x87, 0x1f, 0xe5, 0xf3, 0x1e, + 0x7e, 0xc8, 0x16, 0x54, 0x23, 0xf2, 0x9d, 0x72, 0xb8, 0x16, 0xfd, 0xfe, 0x2e, 0x9b, 0xf8, 0xfe, + 0xee, 0x7d, 0x58, 0x62, 0x67, 0x0b, 0xaa, 0xe6, 0xaa, 0xc1, 0xbe, 0xad, 0xaa, 0x54, 0x18, 0xb4, + 0xe1, 0x92, 0x38, 0x55, 0x6e, 0x42, 0xd1, 0xb7, 0x02, 0xa7, 0xc4, 0x34, 0xb1, 0xf7, 0x10, 0xd9, + 0xf8, 0x7b, 0x08, 0xf9, 0x3f, 0xe7, 0xa1, 0x44, 0xf8, 0xb0, 0xed, 0x79, 0xf8, 0xd6, 0x24, 0xf3, + 0x5a, 0x6f, 0x4d, 0xb2, 0xe7, 0x7f, 0x6b, 0x42, 0x16, 0xda, 0xcc, 0xe6, 0x21, 0x5b, 0x76, 0x66, + 0x33, 0x51, 0x87, 0x96, 0xa3, 0xab, 0x86, 0x7d, 0xf4, 0x29, 0x3f, 0x31, 0x04, 0x06, 0x6a, 0xd9, + 0x47, 0x9f, 0x46, 0x09, 0xee, 0x73, 0x33, 0x12, 0x12, 0xdc, 0xa7, 0x29, 0xb9, 0xd8, 0xe6, 0x8e, + 0x72, 0xe0, 0x8f, 0x3f, 0x18, 0xc8, 0xe7, 0x10, 0x12, 0xdc, 0xe7, 0xef, 0x14, 0x42, 0x82, 0xfb, + 0xc4, 0x10, 0xbb, 0xd8, 0x31, 0xb4, 0x09, 0x7f, 0x97, 0xc0, 0x4b, 0xe8, 0x27, 0x50, 0xf5, 0xcf, + 0x3f, 0x19, 0xef, 0x12, 0x0d, 0x62, 0x2b, 0x3e, 0x90, 0x72, 0x8f, 0x11, 0xdd, 0xa7, 0xfa, 0x17, + 0x25, 0xba, 0x4f, 0x88, 0x18, 0x4f, 0x95, 0xbe, 0xbd, 0x60, 0x2a, 0x96, 0x53, 0x2a, 0x0c, 0xd8, + 0xa1, 0x30, 0x22, 0xe7, 0x50, 0x1b, 0x1e, 0x62, 0x96, 0xf1, 0x91, 0x3e, 0xe3, 0xcc, 0x29, 0x40, + 0x41, 0x34, 0x51, 0x06, 0xfa, 0x00, 0x96, 0x02, 0x02, 0x9a, 0x92, 0x82, 0x3e, 0xe2, 0xcc, 0x29, + 0x55, 0x9f, 0x86, 0xe5, 0xa9, 0xb8, 0x0c, 0x65, 0xfe, 0x10, 0x40, 0xd7, 0x3c, 0x8d, 0x7e, 0xa6, + 0x90, 0x53, 0x4a, 0xf4, 0x11, 0xc0, 0x8e, 0xe6, 0x69, 0x24, 0x94, 0xc5, 0x8e, 0x63, 0x39, 0xf4, + 0xf5, 0x66, 0x4e, 0x61, 0x05, 0xf4, 0x1e, 0x70, 0x69, 0xd4, 0x1f, 0x67, 0xd8, 0x39, 0xa1, 0xef, + 0x33, 0x73, 0x4a, 0x99, 0xc1, 0xbe, 0x21, 0x20, 0x36, 0x15, 0x2e, 0xf6, 0x38, 0xc5, 0x32, 0x13, + 0x90, 0x82, 0x28, 0x81, 0xfc, 0x1d, 0xe4, 0x15, 0xfb, 0x07, 0x23, 0xf0, 0x60, 0x99, 0xd3, 0x3d, + 0xd8, 0x29, 0x17, 0x24, 0x81, 0x72, 0xf2, 0x03, 0x9a, 0xad, 0x1d, 0x28, 0x05, 0x89, 0xde, 0x10, + 0x40, 0x61, 0xb7, 0xdd, 0x7d, 0xdc, 0x68, 0x4b, 0xef, 0x84, 0x09, 0x11, 0xe8, 0xdb, 0xc8, 0xc6, + 0xce, 0xd7, 0x6a, 0xab, 0x23, 0x65, 0x69, 0x3e, 0x81, 0x9d, 0xaf, 0xd5, 0xee, 0xfe, 0x80, 0x65, + 0x4a, 0x78, 0xae, 0x3c, 0x91, 0xf2, 0x5b, 0xed, 0xc8, 0x67, 0xa2, 0xcc, 0xb4, 0x21, 0x09, 0x2a, + 0xed, 0x6e, 0xf7, 0xd9, 0x7e, 0x4f, 0x6d, 0xbe, 0x68, 0x6c, 0x0f, 0xa4, 0x77, 0xd0, 0x32, 0x54, + 0x39, 0xa4, 0xdd, 0xed, 0xec, 0x36, 0x15, 0x96, 0x36, 0x80, 0x83, 0xfa, 0x4f, 0xbb, 0xca, 0xa0, + 0xa9, 0x48, 0xd9, 0xad, 0x5f, 0x66, 0xa0, 0x2c, 0x9c, 0xc8, 0x08, 0x49, 0x0a, 0xdf, 0x41, 0x15, + 0x28, 0x76, 0x9a, 0xad, 0xdd, 0xa7, 0x8f, 0xbb, 0xa4, 0xf6, 0x22, 0xe4, 0x06, 0x8d, 0x5d, 0x2e, + 0x56, 0x5f, 0xed, 0x35, 0x06, 0x4f, 0xa5, 0x1c, 0xaa, 0x42, 0x69, 0xbb, 0xbb, 0xb7, 0xb7, 0xdf, + 0x69, 0x0d, 0xbe, 0x93, 0xf2, 0xa4, 0xd5, 0xe6, 0x8b, 0x81, 0x1a, 0x82, 0x16, 0xc8, 0xbe, 0xb2, + 0xdd, 0x50, 0x76, 0x9b, 0x02, 0xb0, 0xc0, 0x58, 0xbf, 0x18, 0xa8, 0x4f, 0xbb, 0x3d, 0x69, 0x71, + 0xeb, 0x43, 0x28, 0x05, 0x67, 0x2f, 0xf4, 0x65, 0x7a, 0xe7, 0x3b, 0xf1, 0x89, 0x3a, 0x40, 0xa1, + 0xd5, 0x79, 0xde, 0x54, 0x06, 0x52, 0x76, 0x6b, 0x0b, 0xa4, 0xf8, 0x69, 0x0a, 0x2a, 0x40, 0xb6, + 0xf9, 0x8d, 0xf4, 0x0e, 0xf9, 0xbb, 0xdb, 0x94, 0x32, 0xe4, 0x6f, 0xbb, 0x29, 0x65, 0xb7, 0x3e, + 0xe6, 0x0f, 0xa3, 0xf8, 0x16, 0x25, 0x92, 0x89, 0xb1, 0xb1, 0xbd, 0xdd, 0xec, 0x0d, 0x18, 0x73, + 0xa5, 0xf9, 0x35, 0x7d, 0xf4, 0xba, 0xb5, 0x0f, 0x2b, 0x29, 0xbb, 0x4e, 0xd2, 0xa9, 0x40, 0x76, + 0xb5, 0xb1, 0xb3, 0x23, 0xbd, 0x43, 0x76, 0xb9, 0x21, 0x48, 0x69, 0xee, 0x75, 0x9f, 0x93, 0x86, + 0x2f, 0xc0, 0xb2, 0x08, 0xe5, 0xaf, 0xea, 0xb7, 0x6e, 0x41, 0x35, 0xb2, 0xbb, 0x24, 0x23, 0xb8, + 0xd7, 0xdc, 0x51, 0xf7, 0xba, 0x84, 0x55, 0x0d, 0xca, 0xa4, 0xe0, 0x93, 0x67, 0xb6, 0xee, 0x43, + 0x2d, 0x16, 0xa3, 0x46, 0x5f, 0xec, 0x92, 0xe1, 0xd8, 0xeb, 0x75, 0x15, 0x2e, 0x7d, 0xf3, 0x05, + 0xfd, 0x9d, 0xbd, 0xf7, 0x5f, 0xde, 0x85, 0xe2, 0x2e, 0x51, 0xbe, 0x86, 0x6d, 0xa0, 0x47, 0x50, + 0xf4, 0x33, 0x65, 0xa3, 0x8d, 0x48, 0x64, 0x2d, 0x66, 0xcf, 0xde, 0x5c, 0x4b, 0x18, 0xbc, 0xe6, + 0xd4, 0xf6, 0x4e, 0xd0, 0x43, 0x58, 0xe4, 0xb9, 0xb2, 0x51, 0x5d, 0xac, 0x2d, 0xa6, 0xcf, 0x3e, + 0xa5, 0x72, 0x81, 0x65, 0xd1, 0x46, 0x82, 0x0f, 0x8c, 0x24, 0xda, 0xde, 0xac, 0x27, 0x11, 0x7c, + 0xe5, 0x3f, 0x84, 0x45, 0x9e, 0x43, 0x17, 0xc5, 0x4e, 0x48, 0xc3, 0xbc, 0xbe, 0x73, 0x5b, 0x6e, + 0x00, 0x84, 0x59, 0x73, 0xd1, 0x45, 0xd1, 0x9d, 0xc7, 0x72, 0x6c, 0xcf, 0x65, 0xb1, 0x0d, 0x45, + 0x3f, 0xd5, 0xb5, 0x38, 0x70, 0xb1, 0xbc, 0xda, 0x9b, 0x9b, 0x69, 0x28, 0xd6, 0x85, 0x3b, 0x19, + 0xb4, 0x0b, 0x10, 0x26, 0xc6, 0x15, 0xe5, 0x48, 0x64, 0xc3, 0xde, 0x7c, 0x37, 0x1d, 0xc9, 0x47, + 0xe3, 0x4b, 0x28, 0x05, 0x59, 0xa1, 0xd1, 0xe6, 0xfc, 0x54, 0xd1, 0x73, 0xbb, 0xd3, 0x84, 0x8a, + 0x98, 0xf3, 0x19, 0x09, 0x07, 0x2c, 0x29, 0xb9, 0xa0, 0x4f, 0x1b, 0xd8, 0x30, 0xc7, 0xb3, 0xd8, + 0xa1, 0x44, 0xe6, 0xe7, 0x53, 0x06, 0xb6, 0x2c, 0xe4, 0x7d, 0x46, 0x42, 0xbf, 0x93, 0xe9, 0xa0, + 0xe7, 0x32, 0x69, 0x43, 0x59, 0x48, 0xce, 0x2c, 0x32, 0x49, 0x66, 0x7f, 0xde, 0xbc, 0x34, 0x07, + 0x1b, 0x4c, 0x53, 0x13, 0x2a, 0x62, 0xbe, 0x66, 0x71, 0x70, 0x52, 0xf2, 0x38, 0xcf, 0x15, 0xea, + 0x19, 0xd4, 0x62, 0xb9, 0x9a, 0xd1, 0xd5, 0x34, 0xd5, 0x3b, 0x17, 0xb3, 0xe7, 0x50, 0x8b, 0xe5, + 0x54, 0x16, 0x99, 0xa5, 0x67, 0x79, 0xde, 0x7c, 0xef, 0x14, 0x0a, 0xae, 0x49, 0xdf, 0x00, 0x4a, + 0x66, 0x58, 0x46, 0x3f, 0x89, 0xf4, 0x38, 0x3d, 0xff, 0xf2, 0x5c, 0x51, 0xbf, 0x60, 0x4b, 0x55, + 0xf3, 0x0e, 0x51, 0xf2, 0x32, 0xc3, 0xaf, 0xbc, 0x91, 0x82, 0xe1, 0x22, 0x85, 0xab, 0x95, 0xb0, + 0x48, 0xae, 0x56, 0x81, 0xcb, 0x59, 0xab, 0x95, 0x30, 0xd8, 0x98, 0x9b, 0xa3, 0x37, 0xb1, 0x5a, + 0x05, 0x29, 0xee, 0x64, 0x50, 0x2b, 0xb8, 0xeb, 0x61, 0xe9, 0x73, 0xd1, 0xe5, 0x84, 0xcc, 0x91, + 0xbc, 0xba, 0xf3, 0xa4, 0xb9, 0x91, 0x41, 0x0d, 0x28, 0xfa, 0xa9, 0x67, 0x45, 0x79, 0x62, 0x39, + 0x71, 0x45, 0x79, 0x12, 0x99, 0x6a, 0xbb, 0x50, 0x11, 0xb3, 0xaf, 0xa2, 0xa4, 0x16, 0x47, 0x58, + 0x5d, 0x9e, 0x87, 0x0e, 0xba, 0xf7, 0x33, 0x28, 0xb0, 0x94, 0xac, 0x28, 0x7a, 0x83, 0x14, 0x66, + 0x52, 0x9d, 0x3b, 0xbc, 0x5f, 0x42, 0x29, 0xc8, 0xcd, 0x2a, 0x9a, 0x9f, 0x78, 0xc2, 0xd6, 0xb9, + 0x0c, 0xbe, 0x82, 0x45, 0x9e, 0x8e, 0x55, 0x54, 0x91, 0x68, 0x1e, 0xd7, 0xcd, 0x8d, 0x14, 0x4c, + 0x20, 0xfd, 0x97, 0x50, 0x0a, 0x92, 0x1d, 0x8a, 0x22, 0xc4, 0x33, 0xb6, 0x9e, 0x66, 0x01, 0xc5, + 0x9c, 0x86, 0xe2, 0x78, 0xa6, 0xa4, 0x5e, 0x9d, 0xcb, 0xa6, 0x05, 0x10, 0xe6, 0x0f, 0x14, 0x95, + 0x35, 0x91, 0x3b, 0x55, 0x34, 0xe9, 0xc9, 0x7c, 0xa9, 0x77, 0x32, 0xc4, 0x12, 0x0a, 0x69, 0x50, + 0x45, 0x23, 0x96, 0xcc, 0x8e, 0x3a, 0x57, 0x9e, 0x5d, 0xaa, 0xb4, 0xc2, 0xc5, 0x5b, 0x54, 0x69, + 0x13, 0x59, 0x3f, 0xe7, 0x32, 0xda, 0xf3, 0x33, 0x6f, 0x09, 0xbc, 0xde, 0x8b, 0x8f, 0xd1, 0xf9, + 0xd9, 0xed, 0xb3, 0x34, 0xbd, 0x02, 0xb3, 0x2b, 0xd1, 0xe1, 0x48, 0xb2, 0xba, 0x3a, 0x9f, 0x20, + 0x66, 0xaa, 0xc3, 0x63, 0xcd, 0xa8, 0xa9, 0x8e, 0xa7, 0xe0, 0x3c, 0xdb, 0x54, 0x87, 0x9c, 0x12, + 0xa6, 0xfa, 0xdc, 0xcc, 0x14, 0xa8, 0x46, 0x72, 0x7a, 0x8a, 0x53, 0x90, 0x96, 0x18, 0x74, 0xf3, + 0xca, 0x5c, 0x7c, 0xd0, 0xcf, 0x3e, 0xfb, 0x17, 0x02, 0xf1, 0x63, 0xce, 0xf7, 0x53, 0x14, 0x3f, + 0x91, 0x69, 0x72, 0xae, 0xa0, 0xdf, 0x05, 0xff, 0x4c, 0x20, 0xce, 0xf7, 0x7a, 0xfa, 0x62, 0x38, + 0x3f, 0xeb, 0x31, 0xcb, 0x55, 0x98, 0x60, 0xfc, 0x41, 0xda, 0x1a, 0x48, 0xb2, 0xbd, 0x76, 0x16, + 0x99, 0x38, 0x30, 0x29, 0x39, 0x36, 0xc5, 0x81, 0x99, 0x9f, 0x82, 0xf3, 0xb4, 0x30, 0x97, 0xa7, + 0xd7, 0x8c, 0x79, 0x30, 0x21, 0xa1, 0xe3, 0xd9, 0xc1, 0x26, 0xad, 0x9f, 0x70, 0x5f, 0xe7, 0x61, + 0xc1, 0xdd, 0x17, 0x65, 0x10, 0xb3, 0x82, 0x62, 0xf5, 0xcd, 0x34, 0x54, 0x30, 0x32, 0x41, 0x6c, + 0x16, 0x97, 0x23, 0x91, 0x21, 0xf3, 0x1c, 0xb1, 0x19, 0xe5, 0x91, 0x8c, 0xcd, 0xce, 0xc3, 0xc4, + 0x8f, 0x55, 0x29, 0x8b, 0x78, 0xac, 0x7a, 0x1e, 0x06, 0x7c, 0x3d, 0x05, 0x59, 0x2b, 0xe3, 0xeb, + 0x29, 0x9e, 0x10, 0x33, 0xbe, 0x9e, 0x12, 0xe9, 0x2e, 0x99, 0xad, 0x15, 0xd2, 0x59, 0x8a, 0x3d, + 0x4b, 0x66, 0xb9, 0x3c, 0xad, 0x67, 0x41, 0x16, 0x49, 0xb1, 0x67, 0xf1, 0xd4, 0x92, 0xa7, 0xaa, + 0x4a, 0x90, 0xe7, 0x31, 0xa2, 0x2a, 0xf1, 0xec, 0x8f, 0x73, 0x59, 0x30, 0x2f, 0xfe, 0x78, 0x6a, + 0xc7, 0xbc, 0x78, 0x98, 0x2f, 0xf1, 0x6c, 0x2f, 0x4e, 0x6a, 0x27, 0xbc, 0xf8, 0xd9, 0x0c, 0x0e, + 0x0a, 0xb4, 0xfc, 0xc9, 0xff, 0x0f, 0x00, 0x00, 0xff, 0xff, 0x0b, 0x9c, 0xe6, 0x32, 0xef, 0x69, + 0x00, 0x00, } diff --git a/api/gobgp.proto b/api/gobgp.proto index d1f49a4a..e17aacf8 100644 --- a/api/gobgp.proto +++ b/api/gobgp.proto @@ -451,6 +451,7 @@ message Family { AFI_IP = 1; AFI_IP6 = 2; AFI_L2VPN = 25; + AFI_LS = 16388; AFI_OPAQUE = 16397; } @@ -462,6 +463,7 @@ message Family { SAFI_ENCAPSULATION = 7; SAFI_VPLS = 65; SAFI_EVPN = 70; + SAFI_LS = 71; SAFI_MPLS_VPN = 128; SAFI_MPLS_VPN_MULTICAST = 129; SAFI_ROUTE_TARGET_CONSTRAINTS = 132; @@ -518,6 +520,7 @@ message Path { // - FlowSpecNLRI // - VPNFlowSpecNLRI // - OpaqueNLRI + // - LsAddrPrefix google.protobuf.Any nlri = 1; // Each attribute must be one of *Attribute defined in // "api/attribute.proto". diff --git a/cmd/gobgp/common.go b/cmd/gobgp/common.go index 8fa31fc8..066cc66c 100644 --- a/cmd/gobgp/common.go +++ b/cmd/gobgp/common.go @@ -292,6 +292,10 @@ var ( Afi: api.Family_AFI_OPAQUE, Safi: api.Family_SAFI_KEY_VALUE, } + ls = &api.Family{ + Afi: api.Family_AFI_LS, + Safi: api.Family_SAFI_LS, + } ) func checkAddressFamily(def *api.Family) (*api.Family, error) { @@ -330,6 +334,8 @@ func checkAddressFamily(def *api.Family) (*api.Family, error) { f = l2VPNflowspec case "opaque": f = opaque + case "ls", "linkstate", "bgpls": + f = ls case "": f = def default: diff --git a/go.mod b/go.mod index 67d2e6f7..bcb414b0 100644 --- a/go.mod +++ b/go.mod @@ -3,37 +3,39 @@ module github.com/osrg/gobgp require ( github.com/BurntSushi/toml v0.3.0 github.com/armon/go-radix v0.0.0-20170727155443-1fca145dffbc - github.com/davecgh/go-spew v1.1.0 + github.com/davecgh/go-spew v1.1.0 // indirect github.com/dgryski/go-farm v0.0.0-20171119141306-ac7624ea8da3 github.com/eapache/channels v1.1.0 - github.com/eapache/queue v1.0.2 - github.com/fsnotify/fsnotify v1.4.2 + github.com/eapache/queue v1.0.2 // indirect + github.com/fsnotify/fsnotify v1.4.2 // indirect github.com/golang/protobuf v0.0.0-20170726212829-748d386b5c1e - github.com/hashicorp/hcl v0.0.0-20170509225359-392dba7d905e - github.com/inconshreveable/mousetrap v1.0.0 + github.com/hashicorp/hcl v0.0.0-20170509225359-392dba7d905e // indirect + github.com/inconshreveable/mousetrap v1.0.0 // indirect github.com/jessevdk/go-flags v1.3.0 github.com/kr/pretty v0.0.0-20160823170715-cfb55aafdaf3 - github.com/kr/text v0.0.0-20160504234017-7cafcd837844 - github.com/magiconair/properties v1.7.3 - github.com/mitchellh/mapstructure v0.0.0-20170523030023-d0303fe80992 - github.com/pelletier/go-buffruneio v0.2.0 - github.com/pelletier/go-toml v1.0.0 - github.com/pmezard/go-difflib v1.0.0 + github.com/kr/text v0.0.0-20160504234017-7cafcd837844 // indirect + github.com/magiconair/properties v1.7.3 // indirect + github.com/mitchellh/mapstructure v0.0.0-20170523030023-d0303fe80992 // indirect + github.com/pelletier/go-buffruneio v0.2.0 // indirect + github.com/pelletier/go-toml v1.0.0 // indirect + github.com/pmezard/go-difflib v1.0.0 // indirect github.com/satori/go.uuid v0.0.0-20180103174451-36e9d2ebbde5 github.com/sirupsen/logrus v0.0.0-20170713114250-a3f95b5c4235 - github.com/spf13/afero v0.0.0-20170217164146-9be650865eab - github.com/spf13/cast v1.1.0 + github.com/spf13/afero v0.0.0-20170217164146-9be650865eab // indirect + github.com/spf13/cast v1.1.0 // indirect github.com/spf13/cobra v0.0.0-20170731170427-b26b538f6930 - github.com/spf13/jwalterweatherman v0.0.0-20170523133247-0efa5202c046 - github.com/spf13/pflag v1.0.0 + github.com/spf13/jwalterweatherman v0.0.0-20170523133247-0efa5202c046 // indirect + github.com/spf13/pflag v1.0.0 // indirect github.com/spf13/viper v1.0.0 github.com/stretchr/testify v1.1.4 github.com/vishvananda/netlink v0.0.0-20170802012344-a95659537721 - github.com/vishvananda/netns v0.0.0-20170707011535-86bef332bfc3 + github.com/vishvananda/netns v0.0.0-20170707011535-86bef332bfc3 // indirect golang.org/x/net v0.0.0-20170726083632-f5079bd7f6f7 - golang.org/x/sys v0.0.0-20170802141912-e312636bdaa2 - golang.org/x/text v0.0.0-20170730040918-3bd178b88a81 - google.golang.org/genproto v0.0.0-20170731182057-09f6ed296fc6 + golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4 // indirect + golang.org/x/sys v0.0.0-20170802141912-e312636bdaa2 // indirect + golang.org/x/text v0.0.0-20170730040918-3bd178b88a81 // indirect + google.golang.org/genproto v0.0.0-20170731182057-09f6ed296fc6 // indirect google.golang.org/grpc v1.5.1 - gopkg.in/yaml.v2 v2.0.0-20170721122051-25c4ec802a7d + gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127 // indirect + gopkg.in/yaml.v2 v2.0.0-20170721122051-25c4ec802a7d // indirect ) diff --git a/go.sum b/go.sum index d08cfe90..a43c5008 100644 --- a/go.sum +++ b/go.sum @@ -1,35 +1,74 @@ +github.com/BurntSushi/toml v0.3.0 h1:e1/Ivsx3Z0FVTV0NSOv/aVgbUWyQuzj7DDnFblkRvsY= github.com/BurntSushi/toml v0.3.0/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= +github.com/armon/go-radix v0.0.0-20170727155443-1fca145dffbc h1:/WQ8Tr5zbclKWAtvafIcAk/njNpW3gtd22TLLouv+6Q= github.com/armon/go-radix v0.0.0-20170727155443-1fca145dffbc/go.mod h1:ufUuZ+zHj4x4TnLV4JWEpy2hxWSpsRywHrMgIH9cCH8= +github.com/davecgh/go-spew v1.1.0 h1:ZDRjVQ15GmhC3fiQ8ni8+OwkZQO4DARzQgrnXU1Liz8= github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/dgryski/go-farm v0.0.0-20171119141306-ac7624ea8da3 h1:fU8XNPEWym5sd75euzRuQBGltQxHVY4gv6mqa2A2Cuo= github.com/dgryski/go-farm v0.0.0-20171119141306-ac7624ea8da3/go.mod h1:SqUrOPUnsFjfmXRMNPybcSiG0BgUW2AuFH8PAnS2iTw= +github.com/eapache/channels v1.1.0 h1:F1taHcn7/F0i8DYqKXJnyhJcVpp2kgFcNePxXtnyu4k= github.com/eapache/channels v1.1.0/go.mod h1:jMm2qB5Ubtg9zLd+inMZd2/NUvXgzmWXsDaLyQIGfH0= +github.com/eapache/queue v1.0.2 h1:jRJXCx6uciOfN69MfZCC9EZlGRqqHhwlyb6GBeNow+c= github.com/eapache/queue v1.0.2/go.mod h1:6eCeP0CKFpHLu8blIFXhExK/dRa7WDZfr6jVFPTqq+I= +github.com/fsnotify/fsnotify v1.4.2 h1:v5tKwtf2hNhBV24eNYfQ5UmvFOGlOCmRqk7/P1olxtk= github.com/fsnotify/fsnotify v1.4.2/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo= +github.com/golang/protobuf v0.0.0-20170726212829-748d386b5c1e h1:lDgkE81VC1S0yetyGVVGW923ICSIlj6zVU/WaOd9QJ0= github.com/golang/protobuf v0.0.0-20170726212829-748d386b5c1e/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= +github.com/hashicorp/hcl v0.0.0-20170509225359-392dba7d905e h1:KJWs1uTCkN3E/J5ofCH9Pf8KKsibTFc3fv0CA9+WsVo= github.com/hashicorp/hcl v0.0.0-20170509225359-392dba7d905e/go.mod h1:oZtUIOe8dh44I2q6ScRibXws4Ajl+d+nod3AaR9vL5w= +github.com/inconshreveable/mousetrap v1.0.0 h1:Z8tu5sraLXCXIcARxBp/8cbvlwVa7Z1NHg9XEKhtSvM= github.com/inconshreveable/mousetrap v1.0.0/go.mod h1:PxqpIevigyE2G7u3NXJIT2ANytuPF1OarO4DADm73n8= +github.com/jessevdk/go-flags v1.3.0 h1:QmKsgik/Z5fJ11ZtlcA8F+XW9dNybBNFQ1rngF3MmdU= github.com/jessevdk/go-flags v1.3.0/go.mod h1:4FA24M0QyGHXBuZZK/XkWh8h0e1EYbRYJSGM75WSRxI= +github.com/kr/pretty v0.0.0-20160823170715-cfb55aafdaf3 h1:dhwb1Ev84SKKVBfLuhR4bw/29yYHzwtTyTLUWWnvYxI= github.com/kr/pretty v0.0.0-20160823170715-cfb55aafdaf3/go.mod h1:Bvhd+E3laJ0AVkG0c9rmtZcnhV0HQ3+c3YxxqTvc/gA= +github.com/kr/text v0.0.0-20160504234017-7cafcd837844 h1:kpzneEBeC0dMewP3gr/fADv1OlblH9r1goWVwpOt3TU= github.com/kr/text v0.0.0-20160504234017-7cafcd837844/go.mod h1:sjUstKUATFIcff4qlB53Kml0wQPtJVc/3fWrmuUmcfA= +github.com/magiconair/properties v1.7.3 h1:6AOjgCKyZFMG/1yfReDPDz3CJZPxnYk7DGmj2HtyF24= github.com/magiconair/properties v1.7.3/go.mod h1:PppfXfuXeibc/6YijjN8zIbojt8czPbwD3XqdrwzmxQ= +github.com/mitchellh/mapstructure v0.0.0-20170523030023-d0303fe80992 h1:W7VHAEVflA5/eTyRvQ53Lz5j8bhRd1myHZlI/IZFvbU= github.com/mitchellh/mapstructure v0.0.0-20170523030023-d0303fe80992/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y= +github.com/pelletier/go-buffruneio v0.2.0 h1:U4t4R6YkofJ5xHm3dJzuRpPZ0mr5MMCoAWooScCR7aA= github.com/pelletier/go-buffruneio v0.2.0/go.mod h1:JkE26KsDizTr40EUHkXVtNPvgGtbSNq5BcowyYOWdKo= +github.com/pelletier/go-toml v1.0.0 h1:QFDlmAXZrfPXEF6c9+15fMqhQIS3O0pxszhnk936vg4= github.com/pelletier/go-toml v1.0.0/go.mod h1:5z9KED0ma1S8pY6P1sdut58dfprrGBbd/94hg7ilaic= +github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= +github.com/satori/go.uuid v0.0.0-20180103174451-36e9d2ebbde5 h1:tfcGHuraNSEY9xRb9ckCMqMD7xAjzrYI1WpD7DA+nz8= github.com/satori/go.uuid v0.0.0-20180103174451-36e9d2ebbde5/go.mod h1:dA0hQrYB0VpLJoorglMZABFdXlWrHn1NEOzdhQKdks0= +github.com/sirupsen/logrus v0.0.0-20170713114250-a3f95b5c4235 h1:a2XWU6egUZQhD52o2GEKr79zE+OuZmwLybyOQpoqhHQ= github.com/sirupsen/logrus v0.0.0-20170713114250-a3f95b5c4235/go.mod h1:pMByvHTf9Beacp5x1UXfOR9xyW/9antXMhjMPG0dEzc= +github.com/spf13/afero v0.0.0-20170217164146-9be650865eab h1:IVAbBHQR8rXL2Fc8Zba/lMF7KOnTi70lqdx91UTuAwQ= github.com/spf13/afero v0.0.0-20170217164146-9be650865eab/go.mod h1:j4pytiNVoe2o6bmDsKpLACNPDBIoEAkihy7loJ1B0CQ= +github.com/spf13/cast v1.1.0 h1:0Rhw4d6C8J9VPu6cjZLIhZ8+aAOHcDvGeKn+cq5Aq3k= github.com/spf13/cast v1.1.0/go.mod h1:r2rcYCSwa1IExKTDiTfzaxqT2FNHs8hODu4LnUfgKEg= +github.com/spf13/cobra v0.0.0-20170731170427-b26b538f6930 h1:uJND9FKkf5s8kdTQX1jDygtp/zV4BJQpYvOmXPCYWgc= github.com/spf13/cobra v0.0.0-20170731170427-b26b538f6930/go.mod h1:1l0Ry5zgKvJasoi3XT1TypsSe7PqH0Sj9dhYf7v3XqQ= +github.com/spf13/jwalterweatherman v0.0.0-20170523133247-0efa5202c046 h1:RpxSq53NruItMGgp6q5MsDYoZynisJgEpisQdWJ7PyM= github.com/spf13/jwalterweatherman v0.0.0-20170523133247-0efa5202c046/go.mod h1:cQK4TGJAtQXfYWX+Ddv3mKDzgVb68N+wFjFa4jdeBTo= +github.com/spf13/pflag v1.0.0 h1:oaPbdDe/x0UncahuwiPxW1GYJyilRAdsPnq3e1yaPcI= github.com/spf13/pflag v1.0.0/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4= +github.com/spf13/viper v1.0.0 h1:RUA/ghS2i64rlnn4ydTfblY8Og8QzcPtCcHvgMn+w/I= github.com/spf13/viper v1.0.0/go.mod h1:A8kyI5cUJhb8N+3pkfONlcEcZbueH6nhAm0Fq7SrnBM= +github.com/stretchr/testify v1.1.4 h1:ToftOQTytwshuOSj6bDSolVUa3GINfJP/fg3OkkOzQQ= github.com/stretchr/testify v1.1.4/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= +github.com/vishvananda/netlink v0.0.0-20170802012344-a95659537721 h1:GObIVSLotoj+Z0hI7oihMG7UG06/bxPw0HRR7hAuadY= github.com/vishvananda/netlink v0.0.0-20170802012344-a95659537721/go.mod h1:+SR5DhBJrl6ZM7CoCKvpw5BKroDKQ+PJqOg65H/2ktk= +github.com/vishvananda/netns v0.0.0-20170707011535-86bef332bfc3 h1:NcYCJC+LbOrfvuf/uHeM/kxh6vOmiuInC4GAWRdc+P0= github.com/vishvananda/netns v0.0.0-20170707011535-86bef332bfc3/go.mod h1:ZjcWmFBXmLKZu9Nxj3WKYEafiSqer2rnvPr0en9UNpI= +golang.org/x/net v0.0.0-20170726083632-f5079bd7f6f7 h1:1Pw+ZX4dmGORIwGkTwnUr7RFuMhfpCYHXRZNF04XPYs= golang.org/x/net v0.0.0-20170726083632-f5079bd7f6f7/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4 h1:YUO/7uOKsKeq9UokNS62b8FYywz3ker1l1vDZRCRefw= +golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sys v0.0.0-20170802141912-e312636bdaa2 h1:rn9VfHLpovNshEHhLAFADpPdWI+EUYgtyaUcQysy5P8= golang.org/x/sys v0.0.0-20170802141912-e312636bdaa2/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/text v0.0.0-20170730040918-3bd178b88a81 h1:7aXI3TQ9sZ4JdDoIDGjxL6G2mQxlsPy9dySnJaL6Bdk= golang.org/x/text v0.0.0-20170730040918-3bd178b88a81/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= +google.golang.org/genproto v0.0.0-20170731182057-09f6ed296fc6 h1:72GtwBPfq6av9X0Ru2HtAopsPW+d+vh1K1zaxanTdE8= google.golang.org/genproto v0.0.0-20170731182057-09f6ed296fc6/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc= +google.golang.org/grpc v1.5.1 h1:pDBahoEyjFOjJByiWlcl8lTzj3bqilmVSuaSv4ug0nk= google.golang.org/grpc v1.5.1/go.mod h1:yo6s7OP7yaDglbqo1J04qKzAhqBH6lvTonzMVmEdcZw= +gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127 h1:qIbj1fsPNlZgppZ+VLlY7N33q108Sa+fhmuc+sWQYwY= +gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/yaml.v2 v2.0.0-20170721122051-25c4ec802a7d h1:2DX7x6HUDGZUyuEDAhUsQQNqkb1zvDyKTjVoTdzaEzo= gopkg.in/yaml.v2 v2.0.0-20170721122051-25c4ec802a7d/go.mod h1:JAlM8MvJe8wmxCU4Bli9HhUf9+ttbYbLASfIpnQbh74= diff --git a/internal/pkg/apiutil/attribute.go b/internal/pkg/apiutil/attribute.go index 4d06419f..2915faa3 100644 --- a/internal/pkg/apiutil/attribute.go +++ b/internal/pkg/apiutil/attribute.go @@ -319,6 +319,88 @@ func UnmarshalFlowSpecRules(values []*any.Any) ([]bgp.FlowSpecComponentInterface return rules, nil } +func MarshalLsNodeDescriptor(d *bgp.LsNodeDescriptor) *api.LsNodeDescriptor { + return &api.LsNodeDescriptor{ + Asn: d.Asn, + BgpLsId: d.BGPLsID, + OspfAreaId: d.OspfAreaID, + Pseudonode: d.PseudoNode, + IgpRouterId: d.IGPRouterID, + } +} + +func MarshalLsLinkDescriptor(n *bgp.LsLinkDescriptor) *api.LsLinkDescriptor { + return &api.LsLinkDescriptor{ + LinkLocalId: uint32OrDefault(n.LinkLocalID), + LinkRemoteId: uint32OrDefault(n.LinkRemoteID), + InterfaceAddrIpv4: ipOrDefault(n.InterfaceAddrIPv4), + NeighborAddrIpv4: ipOrDefault(n.NeighborAddrIPv4), + InterfaceAddrIpv6: ipOrDefault(n.InterfaceAddrIPv6), + NeighborAddrIpv6: ipOrDefault(n.NeighborAddrIPv6), + } +} + +func MarshalLsPrefixDescriptor(d *bgp.LsPrefixDescriptor) *api.LsPrefixDescriptor { + p := &api.LsPrefixDescriptor{ + OspfRouteType: d.OSPFRouteType.String(), + } + + for _, ip := range d.IPReachability { + p.IpReachability = append(p.IpReachability, ip.String()) + } + + return p +} + +func MarshalLsNodeNLRI(n *bgp.LsNodeNLRI) *any.Any { + node := &api.LsNodeNLRI{ + LocalNode: MarshalLsNodeDescriptor(n.LocalNodeDesc.(*bgp.LsTLVNodeDescriptor).Extract()), + } + a, _ := ptypes.MarshalAny(node) + + return a +} + +func MarshalLsLinkNLRI(n *bgp.LsLinkNLRI) *any.Any { + desc := &bgp.LsLinkDescriptor{} + desc.ParseTLVs(n.LinkDesc) + + link := &api.LsLinkNLRI{ + LocalNode: MarshalLsNodeDescriptor(n.LocalNodeDesc.(*bgp.LsTLVNodeDescriptor).Extract()), + RemoteNode: MarshalLsNodeDescriptor(n.RemoteNodeDesc.(*bgp.LsTLVNodeDescriptor).Extract()), + LinkDescriptor: MarshalLsLinkDescriptor(desc), + } + a, _ := ptypes.MarshalAny(link) + + return a +} + +func MarshalLsPrefixV4NLRI(n *bgp.LsPrefixV4NLRI) *any.Any { + desc := &bgp.LsPrefixDescriptor{} + desc.ParseTLVs(n.PrefixDesc, false) + + prefix := &api.LsPrefixV4NLRI{ + LocalNode: MarshalLsNodeDescriptor(n.LocalNodeDesc.(*bgp.LsTLVNodeDescriptor).Extract()), + PrefixDescriptor: MarshalLsPrefixDescriptor(desc), + } + a, _ := ptypes.MarshalAny(prefix) + + return a +} + +func MarshalLsPrefixV6NLRI(n *bgp.LsPrefixV6NLRI) *any.Any { + desc := &bgp.LsPrefixDescriptor{} + desc.ParseTLVs(n.PrefixDesc, true) + + prefix := &api.LsPrefixV6NLRI{ + LocalNode: MarshalLsNodeDescriptor(n.LocalNodeDesc.(*bgp.LsTLVNodeDescriptor).Extract()), + PrefixDescriptor: MarshalLsPrefixDescriptor(desc), + } + a, _ := ptypes.MarshalAny(prefix) + + return a +} + func MarshalNLRI(value bgp.AddrPrefixInterface) *any.Any { var nlri proto.Message @@ -436,6 +518,32 @@ func MarshalNLRI(value bgp.AddrPrefixInterface) *any.Any { Rd: MarshalRD(v.RD()), Rules: MarshalFlowSpecRules(v.Value), } + case *bgp.LsAddrPrefix: + switch n := v.NLRI.(type) { + case *bgp.LsNodeNLRI: + nlri = &api.LsAddrPrefix{ + Type: api.LsNLRIType_LS_NLRI_NODE, + Nlri: MarshalLsNodeNLRI(n), + } + + case *bgp.LsLinkNLRI: + nlri = &api.LsAddrPrefix{ + Type: api.LsNLRIType_LS_NLRI_LINK, + Nlri: MarshalLsLinkNLRI(n), + } + + case *bgp.LsPrefixV4NLRI: + nlri = &api.LsAddrPrefix{ + Type: api.LsNLRIType_LS_NLRI_PREFIX_V4, + Nlri: MarshalLsPrefixV4NLRI(n), + } + + case *bgp.LsPrefixV6NLRI: + nlri = &api.LsAddrPrefix{ + Type: api.LsNLRIType_LS_NLRI_PREFIX_V6, + Nlri: MarshalLsPrefixV6NLRI(n), + } + } } an, _ := ptypes.MarshalAny(nlri) @@ -1011,6 +1119,129 @@ func NewLargeCommunitiesAttributeFromNative(a *bgp.PathAttributeLargeCommunities } } +func stringOrDefault(s *string) string { + if s == nil { + return "" + } + return *s +} + +func bytesOrDefault(b *[]byte) []byte { + if b == nil { + return []byte{} + } + return *b +} + +func ipOrDefault(ip *net.IP) string { + if ip == nil { + return "" + } + return ip.String() +} + +func uint32OrDefault(i *uint32) uint32 { + if i == nil { + return 0 + } + return *i +} + +func float32OrDefault(f *float32) float32 { + if f == nil { + return 0.0 + } + return *f +} + +func NewLsAttributeFromNative(a *bgp.PathAttributeLs) *api.LsAttribute { + attr := a.Extract() + + apiAttr := &api.LsAttribute{ + Node: &api.LsAttributeNode{ + Name: stringOrDefault(attr.Node.Name), + Opaque: bytesOrDefault(attr.Node.Opaque), + IsisArea: bytesOrDefault(attr.Node.IsisArea), + LocalRouterId: ipOrDefault(attr.Node.LocalRouterID), + LocalRouterIdV6: ipOrDefault(attr.Node.LocalRouterIDv6), + + SrAlgorithms: bytesOrDefault(attr.Node.SrAlgorithms), + }, + Link: &api.LsAttributeLink{ + Name: stringOrDefault(attr.Link.Name), + Opaque: bytesOrDefault(attr.Link.Opaque), + LocalRouterId: ipOrDefault(attr.Link.LocalRouterID), + LocalRouterIdV6: ipOrDefault(attr.Link.LocalRouterIDv6), + RemoteRouterId: ipOrDefault(attr.Link.RemoteRouterID), + RemoteRouterIdV6: ipOrDefault(attr.Link.RemoteRouterIDv6), + AdminGroup: uint32OrDefault(attr.Link.AdminGroup), + DefaultTeMetric: uint32OrDefault(attr.Link.DefaultTEMetric), + IgpMetric: uint32OrDefault(attr.Link.IGPMetric), + + Bandwidth: float32OrDefault(attr.Link.Bandwidth), + ReservableBandwidth: float32OrDefault(attr.Link.ReservableBandwidth), + SrAdjacencySid: uint32OrDefault(attr.Link.SrAdjacencySID), + }, + Prefix: &api.LsAttributePrefix{ + Opaque: bytesOrDefault(attr.Prefix.Opaque), + + SrPrefixSid: uint32OrDefault(attr.Prefix.SrPrefixSID), + }, + } + + if attr.Node.Flags != nil { + apiAttr.Node.Flags = &api.LsNodeFlags{ + Overload: attr.Node.Flags.Overload, + Attached: attr.Node.Flags.Attached, + External: attr.Node.Flags.External, + Abr: attr.Node.Flags.ABR, + Router: attr.Node.Flags.Router, + V6: attr.Node.Flags.V6, + } + } + + if attr.Node.SrCapabilties != nil { + apiAttr.Node.SrCapabilities = &api.LsSrCapabilities{ + Ipv4Supported: attr.Node.SrCapabilties.IPv4Supported, + Ipv6Supported: attr.Node.SrCapabilties.IPv6Supported, + } + + for _, r := range attr.Node.SrCapabilties.Ranges { + apiAttr.Node.SrCapabilities.Ranges = append(apiAttr.Node.SrCapabilities.Ranges, &api.LsSrRange{ + Begin: r.Begin, + End: r.End, + }) + } + } + + if attr.Node.SrLocalBlock != nil { + apiAttr.Node.SrLocalBlock = &api.LsSrLocalBlock{} + for _, r := range attr.Node.SrLocalBlock.Ranges { + apiAttr.Node.SrLocalBlock.Ranges = append(apiAttr.Node.SrLocalBlock.Ranges, &api.LsSrRange{ + Begin: r.Begin, + End: r.End, + }) + } + } + + if attr.Link.UnreservedBandwidth != nil { + for _, f := range attr.Link.UnreservedBandwidth { + apiAttr.Link.UnreservedBandwidth = append(apiAttr.Link.UnreservedBandwidth, f) + } + } + + if attr.Prefix.IGPFlags != nil { + apiAttr.Prefix.IgpFlags = &api.LsIGPFlags{ + Down: attr.Prefix.IGPFlags.Down, + NoUnicast: attr.Prefix.IGPFlags.NoUnicast, + LocalAddress: attr.Prefix.IGPFlags.LocalAddress, + PropagateNssa: attr.Prefix.IGPFlags.PropagateNSSA, + } + } + + return apiAttr +} + func NewUnknownAttributeFromNative(a *bgp.PathAttributeUnknown) *api.UnknownAttribute { return &api.UnknownAttribute{ Flags: uint32(a.Flags), @@ -1083,6 +1314,9 @@ func MarshalPathAttributes(attrList []bgp.PathAttributeInterface) []*any.Any { case *bgp.PathAttributeLargeCommunities: n, _ := ptypes.MarshalAny(NewLargeCommunitiesAttributeFromNative(a)) anyList = append(anyList, n) + case *bgp.PathAttributeLs: + n, _ := ptypes.MarshalAny(NewLsAttributeFromNative(a)) + anyList = append(anyList, n) case *bgp.PathAttributeUnknown: n, _ := ptypes.MarshalAny(NewUnknownAttributeFromNative(a)) anyList = append(anyList, n) diff --git a/internal/pkg/config/bgp_configs.go b/internal/pkg/config/bgp_configs.go index 0833e240..7a533b56 100644 --- a/internal/pkg/config/bgp_configs.go +++ b/internal/pkg/config/bgp_configs.go @@ -261,6 +261,7 @@ const ( AFI_SAFI_TYPE_L3VPN_IPV6_FLOWSPEC AfiSafiType = "l3vpn-ipv6-flowspec" AFI_SAFI_TYPE_L2VPN_FLOWSPEC AfiSafiType = "l2vpn-flowspec" AFI_SAFI_TYPE_OPAQUE AfiSafiType = "opaque" + AFI_SAFI_TYPE_LS AfiSafiType = "ls" ) var AfiSafiTypeToIntMap = map[AfiSafiType]int{ @@ -285,6 +286,7 @@ var AfiSafiTypeToIntMap = map[AfiSafiType]int{ AFI_SAFI_TYPE_L3VPN_IPV6_FLOWSPEC: 18, AFI_SAFI_TYPE_L2VPN_FLOWSPEC: 19, AFI_SAFI_TYPE_OPAQUE: 20, + AFI_SAFI_TYPE_LS: 21, } var IntToAfiSafiTypeMap = map[int]AfiSafiType{ @@ -309,6 +311,7 @@ var IntToAfiSafiTypeMap = map[int]AfiSafiType{ 18: AFI_SAFI_TYPE_L3VPN_IPV6_FLOWSPEC, 19: AFI_SAFI_TYPE_L2VPN_FLOWSPEC, 20: AFI_SAFI_TYPE_OPAQUE, + 21: AFI_SAFI_TYPE_LS, } func (v AfiSafiType) Validate() error { diff --git a/pkg/packet/bgp/bgp.go b/pkg/packet/bgp/bgp.go index dfedba9b..d78e04b6 100644 --- a/pkg/packet/bgp/bgp.go +++ b/pkg/packet/bgp/bgp.go @@ -53,6 +53,7 @@ const ( AFI_IP = 1 AFI_IP6 = 2 AFI_L2VPN = 25 + AFI_LS = 16388 AFI_OPAQUE = 16397 ) @@ -63,6 +64,7 @@ const ( SAFI_ENCAPSULATION = 7 SAFI_VPLS = 65 SAFI_EVPN = 70 + SAFI_LS = 71 SAFI_MPLS_VPN = 128 SAFI_MPLS_VPN_MULTICAST = 129 SAFI_ROUTE_TARGET_CONSTRAINTS = 132 @@ -4711,6 +4713,3210 @@ func NewOpaqueNLRI(key, value []byte) *OpaqueNLRI { } } +type LsNLRIType uint16 + +const ( + LS_NLRI_TYPE_UNKNOWN LsNLRIType = iota + LS_NLRI_TYPE_NODE + LS_NLRI_TYPE_LINK + LS_NLRI_TYPE_PREFIX_IPV4 + LS_NLRI_TYPE_PREFIX_IPV6 +) + +type LsNLRIInterface interface { + DecodeFromBytes([]byte) error + Serialize() ([]byte, error) + Len() int + Type() LsNLRIType + String() string +} + +type LsProtocolID uint8 + +const ( + LS_PROTOCOL_UNKNOWN = iota + LS_PROTOCOL_ISIS_L1 + LS_PROTOCOL_ISIS_L2 + LS_PROTOCOL_OSPF_V2 + LS_PROTOCOL_DIRECT + LS_PROTOCOL_STATIC + LS_PROTOCOL_OSPF_V3 +) + +func (l LsProtocolID) String() string { + switch l { + case LS_PROTOCOL_ISIS_L1: + return "ISIS-L1" + case LS_PROTOCOL_ISIS_L2: + return "ISIS-L2" + case LS_PROTOCOL_OSPF_V2: + return "OSPFv2" + case LS_PROTOCOL_DIRECT: + return "DIRECT" + case LS_PROTOCOL_STATIC: + return "STATIC" + case LS_PROTOCOL_OSPF_V3: + return "OSPFv3" + default: + return fmt.Sprintf("LsProtocolID(%d)", uint8(l)) + } +} + +type LsNLRI struct { + NLRIType LsNLRIType + Length uint16 + ProtocolID LsProtocolID + Identifier uint64 +} + +const lsNLRIHdrLen = 9 + +func (l *LsNLRI) DecodeFromBytes(data []byte) error { + if len(data) < lsNLRIHdrLen { + return malformedAttrListErr("Malformed NLRI") + } + + l.ProtocolID = LsProtocolID(data[0]) + l.Identifier = binary.BigEndian.Uint64(data[1:lsNLRIHdrLen]) + + return nil +} + +func (l *LsNLRI) Serialize(value []byte) ([]byte, error) { + buf := make([]byte, lsNLRIHdrLen) + buf[0] = uint8(l.ProtocolID) + binary.BigEndian.PutUint64(buf[1:], l.Identifier) + buf = append(buf, value...) + + return buf, nil +} + +func (l *LsNLRI) Len() int { + return int(l.Length) +} + +func (l *LsNLRI) Type() LsNLRIType { + return l.NLRIType +} + +type LsNodeNLRI struct { + LsNLRI + LocalNodeDesc LsTLVInterface +} + +func (l *LsNodeNLRI) DecodeFromBytes(data []byte) error { + if err := l.LsNLRI.DecodeFromBytes(data); err != nil { + return nil + } + + tlv := data[lsNLRIHdrLen:] + if len(tlv) < tlvHdrLen { + return malformedAttrListErr("Malformed Node NLRI") + } + + tlvType := LsTLVType(binary.BigEndian.Uint16(tlv[:2])) + if tlvType != LS_TLV_LOCAL_NODE_DESC { + return malformedAttrListErr("Mandatory TLV missing") + } + + l.LocalNodeDesc = &LsTLVNodeDescriptor{} + if err := l.LocalNodeDesc.DecodeFromBytes(tlv); err != nil { + return malformedAttrListErr(fmt.Sprintf("Malformed Node NLRI: %v", err)) + } + + return nil +} + +func (l *LsNodeNLRI) String() string { + if l.LocalNodeDesc == nil { + return "NODE { EMPTY }" + } + + local := l.LocalNodeDesc.(*LsTLVNodeDescriptor).Extract() + return fmt.Sprintf("NODE { AS:%v BGP-LS ID:%v %v %v:%v }", local.Asn, local.BGPLsID, local.IGPRouterID, l.ProtocolID.String(), l.Identifier) +} + +func (l *LsNodeNLRI) Serialize() ([]byte, error) { + if l.LocalNodeDesc == nil { + return nil, fmt.Errorf("local node descriptor missing") + } + ser, err := l.LocalNodeDesc.Serialize() + if err != nil { + return nil, err + } + + return l.LsNLRI.Serialize(ser) +} + +func (l *LsNodeNLRI) MarshalJSON() ([]byte, error) { + return json.Marshal(struct { + Type LsNLRIType `json:"type"` + LocalNode LsNodeDescriptor `json:"local_node_desc"` + }{ + Type: l.Type(), + LocalNode: *l.LocalNodeDesc.(*LsTLVNodeDescriptor).Extract(), + }) +} + +type LsLinkDescriptor struct { + LinkLocalID *uint32 + LinkRemoteID *uint32 + InterfaceAddrIPv4 *net.IP + NeighborAddrIPv4 *net.IP + InterfaceAddrIPv6 *net.IP + NeighborAddrIPv6 *net.IP +} + +func (l *LsLinkDescriptor) ParseTLVs(tlvs []LsTLVInterface) { + for _, tlv := range tlvs { + switch v := tlv.(type) { + case *LsTLVLinkID: + l.LinkLocalID = &v.Local + l.LinkRemoteID = &v.Remote + + case *LsTLVIPv4InterfaceAddr: + l.InterfaceAddrIPv4 = &v.IP + + case *LsTLVIPv4NeighborAddr: + l.NeighborAddrIPv4 = &v.IP + + case *LsTLVIPv6InterfaceAddr: + l.InterfaceAddrIPv6 = &v.IP + + case *LsTLVIPv6NeighborAddr: + l.NeighborAddrIPv6 = &v.IP + } + } +} + +func (l *LsLinkDescriptor) String() string { + if l.InterfaceAddrIPv4 != nil && l.NeighborAddrIPv4 != nil { + return fmt.Sprintf("%v->%v", l.InterfaceAddrIPv4, l.NeighborAddrIPv4) + } + + if l.InterfaceAddrIPv6 != nil && l.NeighborAddrIPv6 != nil { + return fmt.Sprintf("%v->%v", l.InterfaceAddrIPv6, l.NeighborAddrIPv6) + } + + if l.LinkLocalID != nil && l.LinkRemoteID != nil { + return fmt.Sprintf("%v->%v", *l.LinkLocalID, *l.LinkRemoteID) + } + + return "UNKNOWN" +} + +type LsLinkNLRI struct { + LsNLRI + LocalNodeDesc LsTLVInterface + RemoteNodeDesc LsTLVInterface + LinkDesc []LsTLVInterface +} + +func (l *LsLinkNLRI) String() string { + if l.LocalNodeDesc == nil || l.RemoteNodeDesc == nil { + return "LINK { EMPTY }" + } + + local := l.LocalNodeDesc.(*LsTLVNodeDescriptor).Extract() + remote := l.RemoteNodeDesc.(*LsTLVNodeDescriptor).Extract() + link := &LsLinkDescriptor{} + link.ParseTLVs(l.LinkDesc) + + return fmt.Sprintf("LINK { LOCAL_NODE: %v REMOTE_NODE: %v LINK: %v}", local.IGPRouterID, remote.IGPRouterID, link) +} + +func (l *LsLinkNLRI) DecodeFromBytes(data []byte) error { + if err := l.LsNLRI.DecodeFromBytes(data); err != nil { + return nil + } + + tlv := data[lsNLRIHdrLen:] + m := make(map[LsTLVType]bool) + + for len(tlv) >= tlvHdrLen { + sub := &LsTLV{} + _, err := sub.DecodeFromBytes(tlv) + if err != nil { + return err + } + m[sub.Type] = true + + var subTLV LsTLVInterface + switch sub.Type { + case LS_TLV_LOCAL_NODE_DESC, LS_TLV_REMOTE_NODE_DESC: + subTLV = &LsTLVNodeDescriptor{} + case LS_TLV_LINK_ID: + subTLV = &LsTLVLinkID{} + case LS_TLV_IPV4_INTERFACE_ADDR: + subTLV = &LsTLVIPv4InterfaceAddr{} + case LS_TLV_IPV4_NEIGHBOR_ADDR: + subTLV = &LsTLVIPv4NeighborAddr{} + case LS_TLV_IPV6_INTERFACE_ADDR: + subTLV = &LsTLVIPv6InterfaceAddr{} + case LS_TLV_IPV6_NEIGHBOR_ADDR: + subTLV = &LsTLVIPv6NeighborAddr{} + + default: + tlv = tlv[sub.Len():] + l.Length -= uint16(sub.Len()) + continue + } + + if err := subTLV.DecodeFromBytes(tlv); err != nil { + return err + } + tlv = tlv[subTLV.Len():] + + switch sub.Type { + case LS_TLV_LOCAL_NODE_DESC: + l.LocalNodeDesc = subTLV + case LS_TLV_REMOTE_NODE_DESC: + l.RemoteNodeDesc = subTLV + default: + l.LinkDesc = append(l.LinkDesc, subTLV) + } + } + + required := []LsTLVType{LS_TLV_LOCAL_NODE_DESC, LS_TLV_REMOTE_NODE_DESC} + for _, tlv := range required { + if _, ok := m[tlv]; !ok { + return malformedAttrListErr("Required TLV missing") + } + } + + return nil +} + +func (l *LsLinkNLRI) Serialize() ([]byte, error) { + if l.LocalNodeDesc == nil || l.RemoteNodeDesc == nil { + return nil, fmt.Errorf("required TLV missing") + } + + buf := make([]byte, 0) + s, err := l.LocalNodeDesc.Serialize() + if err != nil { + return nil, err + } + buf = append(buf, s...) + + s, err = l.RemoteNodeDesc.Serialize() + if err != nil { + return nil, err + } + buf = append(buf, s...) + + for _, tlv := range l.LinkDesc { + s, err := tlv.Serialize() + if err != nil { + return nil, err + } + buf = append(buf, s...) + } + + return l.LsNLRI.Serialize(buf) +} + +func (l *LsLinkNLRI) MarshalJSON() ([]byte, error) { + linkDesc := &LsLinkDescriptor{} + linkDesc.ParseTLVs(l.LinkDesc) + + return json.Marshal(struct { + Type LsNLRIType `json:"type"` + LocalNode LsNodeDescriptor `json:"local_node_desc"` + RemoteNode LsNodeDescriptor `json:"remote_node_desc"` + LinkDesc LsLinkDescriptor `json:"link_desc"` + }{ + Type: l.Type(), + LocalNode: *l.LocalNodeDesc.(*LsTLVNodeDescriptor).Extract(), + RemoteNode: *l.RemoteNodeDesc.(*LsTLVNodeDescriptor).Extract(), + LinkDesc: *linkDesc, + }) +} + +type LsPrefixDescriptor struct { + IPReachability []net.IPNet + OSPFRouteType LsOspfRouteType +} + +func (l *LsPrefixDescriptor) ParseTLVs(tlvs []LsTLVInterface, ipv6 bool) { + for _, tlv := range tlvs { + switch v := tlv.(type) { + case *LsTLVIPReachability: + l.IPReachability = append(l.IPReachability, v.ToIPNet(ipv6)) + + case *LsTLVOspfRouteType: + l.OSPFRouteType = v.RouteType + } + } +} + +type LsPrefixV4NLRI struct { + LsNLRI + LocalNodeDesc LsTLVInterface + PrefixDesc []LsTLVInterface +} + +func (l *LsPrefixV4NLRI) String() string { + if l.LocalNodeDesc == nil { + return "PREFIXv4 { EMPTY }" + } + + local := l.LocalNodeDesc.(*LsTLVNodeDescriptor).Extract() + prefix := &LsPrefixDescriptor{} + prefix.ParseTLVs(l.PrefixDesc, false) + ips := []string{} + for _, ip := range prefix.IPReachability { + ips = append(ips, ip.String()) + } + + ospf := "" + if prefix.OSPFRouteType != LS_OSPF_ROUTE_TYPE_UNKNOWN { + ospf = fmt.Sprintf("OSPF_ROUTE_TYPE:%v ", prefix.OSPFRouteType) + } + + return fmt.Sprintf("PREFIXv4 { LOCAL_NODE: %v PREFIX: %v %v}", local.IGPRouterID, ips, ospf) +} + +func (l *LsPrefixV4NLRI) DecodeFromBytes(data []byte) error { + if err := l.LsNLRI.DecodeFromBytes(data); err != nil { + return nil + } + + tlv := data[lsNLRIHdrLen:] + m := make(map[LsTLVType]bool) + + for len(tlv) >= tlvHdrLen { + sub := &LsTLV{} + _, err := sub.DecodeFromBytes(tlv) + if err != nil { + return err + } + m[sub.Type] = true + + var subTLV LsTLVInterface + switch sub.Type { + case LS_TLV_LOCAL_NODE_DESC: + subTLV = &LsTLVNodeDescriptor{} + case LS_TLV_OSPF_ROUTE_TYPE: + subTLV = &LsTLVOspfRouteType{} + case LS_TLV_IP_REACH_INFO: + subTLV = &LsTLVIPReachability{} + + default: + tlv = tlv[sub.Len():] + l.Length -= uint16(sub.Len()) + continue + } + + if err := subTLV.DecodeFromBytes(tlv); err != nil { + return err + } + tlv = tlv[subTLV.Len():] + + switch sub.Type { + case LS_TLV_LOCAL_NODE_DESC: + l.LocalNodeDesc = subTLV + default: + l.PrefixDesc = append(l.PrefixDesc, subTLV) + } + } + + required := []LsTLVType{LS_TLV_IP_REACH_INFO, LS_TLV_LOCAL_NODE_DESC} + for _, tlv := range required { + if _, ok := m[tlv]; !ok { + return malformedAttrListErr("Required TLV missing") + } + } + + for _, tlv := range l.PrefixDesc { + switch v := tlv.(type) { + case *LsTLVIPReachability: + if v.PrefixLength > 8*net.IPv4len { + return malformedAttrListErr("Unexpected IP Reachability info") + } + } + } + + return nil +} + +func (l *LsPrefixV4NLRI) Serialize() ([]byte, error) { + if l.LocalNodeDesc == nil { + return nil, fmt.Errorf("required TLV missing") + } + + buf := make([]byte, 0) + s, err := l.LocalNodeDesc.Serialize() + if err != nil { + return nil, err + } + buf = append(buf, s...) + + for _, tlv := range l.PrefixDesc { + s, err := tlv.Serialize() + if err != nil { + return nil, err + } + buf = append(buf, s...) + } + + return l.LsNLRI.Serialize(buf) +} + +func (l *LsPrefixV4NLRI) MarshalJSON() ([]byte, error) { + prefixDesc := &LsPrefixDescriptor{} + prefixDesc.ParseTLVs(l.PrefixDesc, false) + + return json.Marshal(struct { + Type LsNLRIType `json:"type"` + LocalNode LsNodeDescriptor `json:"local_node_desc"` + PrefixDesc LsPrefixDescriptor `json:"prefix_desc"` + }{ + Type: l.Type(), + LocalNode: *l.LocalNodeDesc.(*LsTLVNodeDescriptor).Extract(), + PrefixDesc: *prefixDesc, + }) +} + +type LsPrefixV6NLRI struct { + LsNLRI + LocalNodeDesc LsTLVInterface + PrefixDesc []LsTLVInterface +} + +func (l *LsPrefixV6NLRI) String() string { + if l.LocalNodeDesc == nil { + return "PREFIXv6 { EMPTY }" + } + + local := l.LocalNodeDesc.(*LsTLVNodeDescriptor).Extract() + prefix := &LsPrefixDescriptor{} + prefix.ParseTLVs(l.PrefixDesc, true) + ips := []string{} + for _, ip := range prefix.IPReachability { + ips = append(ips, ip.String()) + } + + ospf := "" + if prefix.OSPFRouteType != LS_OSPF_ROUTE_TYPE_UNKNOWN { + ospf = fmt.Sprintf("OSPF_ROUTE_TYPE:%v ", prefix.OSPFRouteType) + } + + return fmt.Sprintf("PREFIXv6 { LOCAL_NODE: %v PREFIX: %v %v}", local.IGPRouterID, ips, ospf) +} + +func (l *LsPrefixV6NLRI) DecodeFromBytes(data []byte) error { + if err := l.LsNLRI.DecodeFromBytes(data); err != nil { + return nil + } + + tlv := data[lsNLRIHdrLen:] + m := make(map[LsTLVType]bool) + + for len(tlv) >= tlvHdrLen { + sub := &LsTLV{} + _, err := sub.DecodeFromBytes(tlv) + if err != nil { + return err + } + m[sub.Type] = true + + var subTLV LsTLVInterface + switch sub.Type { + case LS_TLV_LOCAL_NODE_DESC: + subTLV = &LsTLVNodeDescriptor{} + case LS_TLV_OSPF_ROUTE_TYPE: + subTLV = &LsTLVOspfRouteType{} + case LS_TLV_IP_REACH_INFO: + subTLV = &LsTLVIPReachability{} + + default: + tlv = tlv[sub.Len():] + l.Length -= uint16(sub.Len()) + continue + } + + if err := subTLV.DecodeFromBytes(tlv); err != nil { + return err + } + tlv = tlv[subTLV.Len():] + + switch sub.Type { + case LS_TLV_LOCAL_NODE_DESC: + l.LocalNodeDesc = subTLV + default: + l.PrefixDesc = append(l.PrefixDesc, subTLV) + } + } + + required := []LsTLVType{LS_TLV_IP_REACH_INFO, LS_TLV_LOCAL_NODE_DESC} + for _, tlv := range required { + if _, ok := m[tlv]; !ok { + return malformedAttrListErr("Required TLV missing") + } + } + + return nil +} + +func (l *LsPrefixV6NLRI) Serialize() ([]byte, error) { + if l.LocalNodeDesc == nil { + return nil, fmt.Errorf("required TLV missing") + } + + buf := make([]byte, 0) + s, err := l.LocalNodeDesc.Serialize() + if err != nil { + return nil, err + } + buf = append(buf, s...) + + for _, tlv := range l.PrefixDesc { + s, err := tlv.Serialize() + if err != nil { + return nil, err + } + buf = append(buf, s...) + } + + return l.LsNLRI.Serialize(buf) +} + +func (l *LsPrefixV6NLRI) MarshalJSON() ([]byte, error) { + prefixDesc := &LsPrefixDescriptor{} + prefixDesc.ParseTLVs(l.PrefixDesc, true) + + return json.Marshal(struct { + Type LsNLRIType `json:"type"` + LocalNode LsNodeDescriptor `json:"local_node_desc"` + PrefixDesc LsPrefixDescriptor `json:"prefix_desc"` + }{ + Type: l.Type(), + LocalNode: *l.LocalNodeDesc.(*LsTLVNodeDescriptor).Extract(), + PrefixDesc: *prefixDesc, + }) +} + +type LsTLVType uint16 + +// Based on https://www.iana.org/assignments/bgp-ls-parameters/bgp-ls-parameters.xhtml +const ( + LS_TLV_UNKNOWN LsTLVType = iota + + LS_TLV_LOCAL_NODE_DESC = 256 + LS_TLV_REMOTE_NODE_DESC = 257 + LS_TLV_LINK_ID = 258 + LS_TLV_IPV4_INTERFACE_ADDR = 259 + LS_TLV_IPV4_NEIGHBOR_ADDR = 260 + LS_TLV_IPV6_INTERFACE_ADDR = 261 + LS_TLV_IPV6_NEIGHBOR_ADDR = 262 + LS_TLV_MULTI_TOPO_ID = 263 + LS_TLV_OSPF_ROUTE_TYPE = 264 + LS_TLV_IP_REACH_INFO = 265 + + LS_TLV_AS = 512 + LS_TLV_BGP_LS_ID = 513 + LS_TLV_OSPF_AREA = 514 + LS_TLV_IGP_ROUTER_ID = 515 + LS_TLV_BGP_ROUTER_ID = 516 // draft-ietf-idr-bgpls-segment-routing-epe, TODO + LS_TLV_BGP_CONFEDERATION_MEMBER = 517 // draft-ietf-idr-bgpls-segment-routing-epe, TODO + + LS_TLV_NODE_FLAG_BITS = 1024 + LS_TLV_OPAQUE_NODE_ATTR = 1025 + LS_TLV_NODE_NAME = 1026 + LS_TLV_ISIS_AREA = 1027 + LS_TLV_IPV4_LOCAL_ROUTER_ID = 1028 + LS_TLV_IPV6_LOCAL_ROUTER_ID = 1029 + LS_TLV_IPV4_REMOTE_ROUTER_ID = 1030 + LS_TLV_IPV6_REMOTE_ROUTER_ID = 1031 + + LS_TLV_SR_CAPABILITIES = 1034 // draft-ietf-idr-bgp-ls-segment-routing-ext + LS_TLV_SR_ALGORITHM = 1035 // draft-ietf-idr-bgp-ls-segment-routing-ext + LS_TLV_SR_LOCAL_BLOCK = 1036 // draft-ietf-idr-bgp-ls-segment-routing-ext + LS_TLV_SRMS_PREFERENCE = 1037 // draft-ietf-idr-bgp-ls-segment-routing-ext, TODO + + LS_TLV_ADMIN_GROUP = 1088 + LS_TLV_MAX_LINK_BANDWIDTH = 1089 + LS_TLV_MAX_RESERVABLE_BANDWIDTH = 1090 + LS_TLV_UNRESERVED_BANDWIDTH = 1091 + LS_TLV_TE_DEFAULT_METRIC = 1092 + LS_TLV_LINK_PROTECTION_TYPE = 1093 // TODO + LS_TLV_MPLS_PROTOCOL_MASK = 1094 // TODO + LS_TLV_IGP_METRIC = 1095 + LS_TLV_SRLG = 1096 // TODO + LS_TLV_OPAQUE_LINK_ATTR = 1097 + LS_TLV_LINK_NAME = 1098 + LS_TLV_ADJACENCY_SID = 1099 // draft-ietf-idr-bgp-ls-segment-routing-ext + LS_TLV_LAN_ADJACENCY_SID = 1100 // draft-ietf-idr-bgp-ls-segment-routing-ext, TODO + LS_TLV_PEER_NODE_SID = 1101 // draft-ietf-idr-bgpls-segment-routing-epe, TODO + LS_TLV_PEER_ADJACENCY_SID = 1102 // draft-ietf-idr-bgpls-segment-routing-epe, TODO + LS_TLV_PEER_SET_SID = 1103 // draft-ietf-idr-bgpls-segment-routing-epe, TODO + + LS_TLV_RTM_CAPABILITY = 1105 // RFC8169, TODO + + LS_TLV_IGP_FLAGS = 1152 + LS_TLV_IGP_ROUTE_TAG = 1153 // TODO + LS_TLV_EXTENDED_ROUTE_TAG = 1154 // TODO + LS_TLV_PREFIX_METRIC = 1155 // TODO + LS_TLV_OSPF_FORWARDING_ADDR = 1156 // TODO + LS_TLV_OPAQUE_PREFIX_ATTR = 1157 + LS_TLV_PREFIX_SID = 1158 // draft-ietf-idr-bgp-ls-segment-routing-ext + LS_TLV_RANGE = 1159 // draft-ietf-idr-bgp-ls-segment-routing-ext, TODO + LS_TLV_SID_LABEL_TLV = 1161 // draft-ietf-idr-bgp-ls-segment-routing-ext + LS_TLV_PREFIX_ATTRIBUTE_FLAGS = 1170 // draft-ietf-idr-bgp-ls-segment-routing-ext, TODO + LS_TLV_SOURCE_ROUTER_ID = 1171 // draft-ietf-idr-bgp-ls-segment-routing-ext, TODO + LS_TLV_L2_BUNDLE_MEMBER_TLV = 1172 // draft-ietf-idr-bgp-ls-segment-routing-ext, TODO +) + +type LsTLVInterface interface { + Len() int + DecodeFromBytes([]byte) error + Serialize() ([]byte, error) + String() string + MarshalJSON() ([]byte, error) +} + +type LsTLV struct { + Type LsTLVType + Length uint16 +} + +func malformedAttrListErr(s string) error { + return NewMessageError(BGP_ERROR_UPDATE_MESSAGE_ERROR, BGP_ERROR_SUB_MALFORMED_ATTRIBUTE_LIST, nil, s) +} + +const tlvHdrLen = 4 + +func (l *LsTLV) Len() int { + return int(l.Length) + tlvHdrLen +} + +func (l *LsTLV) Serialize(value []byte) ([]byte, error) { + if len(value) != int(l.Length) { + return nil, malformedAttrListErr("serialization failed: LS TLV malformed") + } + + buf := make([]byte, tlvHdrLen) + binary.BigEndian.PutUint16(buf[:2], uint16(l.Type)) + binary.BigEndian.PutUint16(buf[2:4], uint16(l.Length)) + buf = append(buf, value...) + + return buf, nil +} + +func (l *LsTLV) DecodeFromBytes(data []byte) ([]byte, error) { + if len(data) < tlvHdrLen { + return nil, malformedAttrListErr("decoding failed: LS TLV malformed") + } + l.Type = LsTLVType(binary.BigEndian.Uint16(data[:2])) + l.Length = binary.BigEndian.Uint16(data[2:4]) + + if len(data) < l.Len() { + return nil, malformedAttrListErr("decoding failed: LS TLV malformed") + } + + return data[tlvHdrLen:l.Len()], nil +} + +type LsTLVLinkID struct { + LsTLV + Local uint32 + Remote uint32 +} + +func (l *LsTLVLinkID) DecodeFromBytes(data []byte) error { + value, err := l.LsTLV.DecodeFromBytes(data) + if err != nil { + return err + } + + if l.Type != LS_TLV_LINK_ID { + return malformedAttrListErr("Unexpected TLV type") + } + + // https://tools.ietf.org/html/rfc5307#section-1.1 + if len(value) != 8 { + return malformedAttrListErr("Incorrect Link ID length") + } + + l.Local = binary.BigEndian.Uint32(value[:4]) + l.Remote = binary.BigEndian.Uint32(value[4:]) + + return nil +} + +func (l *LsTLVLinkID) Serialize() ([]byte, error) { + buf := make([]byte, 8) + binary.BigEndian.PutUint32(buf[:4], l.Local) + binary.BigEndian.PutUint32(buf[4:], l.Remote) + + return l.LsTLV.Serialize(buf) +} + +func (l *LsTLVLinkID) String() string { + return fmt.Sprintf("{Link ID Remote: %v Local: %v}", l.Local, l.Remote) +} + +func (l *LsTLVLinkID) MarshalJSON() ([]byte, error) { + return json.Marshal(struct { + Type LsTLVType `json:"type"` + Local uint32 `json:"local_link_id"` + Remote uint32 `json:"remote_link_id"` + }{ + Type: l.Type, + Local: l.Local, + Remote: l.Remote, + }) +} + +type LsTLVIPv4InterfaceAddr struct { + LsTLV + IP net.IP +} + +func (l *LsTLVIPv4InterfaceAddr) DecodeFromBytes(data []byte) error { + value, err := l.LsTLV.DecodeFromBytes(data) + if err != nil { + return err + } + + if l.Type != LS_TLV_IPV4_INTERFACE_ADDR { + return malformedAttrListErr("Unexpected TLV type") + } + + // https://tools.ietf.org/html/rfc5305#section-3.2 + if len(value) != 4 { + return malformedAttrListErr("Unexpected address size") + } + + l.IP = net.IP(value) + + return nil +} + +func (l *LsTLVIPv4InterfaceAddr) Serialize() ([]byte, error) { + return l.LsTLV.Serialize(l.IP) +} + +func (l *LsTLVIPv4InterfaceAddr) String() string { + return fmt.Sprintf("{IPv4 Interface Address: %v}", l.IP) +} + +func (l *LsTLVIPv4InterfaceAddr) MarshalJSON() ([]byte, error) { + return json.Marshal(struct { + Type LsTLVType `json:"type"` + Value string `json:"ipv4_interface_address"` + }{ + Type: l.Type, + Value: fmt.Sprintf("%v", l.IP), + }) +} + +type LsTLVIPv4NeighborAddr struct { + LsTLV + IP net.IP +} + +func (l *LsTLVIPv4NeighborAddr) DecodeFromBytes(data []byte) error { + value, err := l.LsTLV.DecodeFromBytes(data) + if err != nil { + return err + } + + if l.Type != LS_TLV_IPV4_NEIGHBOR_ADDR { + return malformedAttrListErr("Unexpected TLV type") + } + + // https://tools.ietf.org/html/rfc5305#section-3.3 + if len(value) != 4 { + return malformedAttrListErr("Unexpected address size") + } + + l.IP = net.IP(value) + + return nil +} + +func (l *LsTLVIPv4NeighborAddr) Serialize() ([]byte, error) { + return l.LsTLV.Serialize(l.IP) +} + +func (l *LsTLVIPv4NeighborAddr) String() string { + return fmt.Sprintf("{IPv4 Neighbor Address: %v}", l.IP) +} + +func (l *LsTLVIPv4NeighborAddr) MarshalJSON() ([]byte, error) { + return json.Marshal(struct { + Type LsTLVType `json:"type"` + Value string `json:"ipv4_neighbor_address"` + }{ + Type: l.Type, + Value: fmt.Sprintf("%v", l.IP), + }) +} + +type LsTLVIPv6InterfaceAddr struct { + LsTLV + IP net.IP +} + +func (l *LsTLVIPv6InterfaceAddr) DecodeFromBytes(data []byte) error { + value, err := l.LsTLV.DecodeFromBytes(data) + if err != nil { + return err + } + + if l.Type != LS_TLV_IPV6_INTERFACE_ADDR { + return malformedAttrListErr("Unexpected TLV type") + } + + // https://tools.ietf.org/html/rfc6119#section-4.2 + if len(value) != 16 { + return malformedAttrListErr("Unexpected address size") + } + + l.IP = net.IP(value) + + if l.IP.IsLinkLocalUnicast() { + return malformedAttrListErr("Unexpected link local address") + } + + return nil +} + +func (l *LsTLVIPv6InterfaceAddr) Serialize() ([]byte, error) { + return l.LsTLV.Serialize(l.IP) +} + +func (l *LsTLVIPv6InterfaceAddr) String() string { + return fmt.Sprintf("{IPv6 Interface Address: %v}", l.IP) +} + +func (l *LsTLVIPv6InterfaceAddr) MarshalJSON() ([]byte, error) { + return json.Marshal(struct { + Type LsTLVType `json:"type"` + Value string `json:"ipv6_interface_address"` + }{ + Type: l.Type, + Value: fmt.Sprintf("%v", l.IP), + }) +} + +type LsTLVIPv6NeighborAddr struct { + LsTLV + IP net.IP +} + +func (l *LsTLVIPv6NeighborAddr) DecodeFromBytes(data []byte) error { + value, err := l.LsTLV.DecodeFromBytes(data) + if err != nil { + return err + } + + if l.Type != LS_TLV_IPV6_NEIGHBOR_ADDR { + return malformedAttrListErr("Unexpected TLV type") + } + + // https://tools.ietf.org/html/rfc6119#section-4.3 + if len(value) != 16 { + return malformedAttrListErr("Unexpected address size") + } + + l.IP = net.IP(value) + + if l.IP.IsLinkLocalUnicast() { + return malformedAttrListErr("Unexpected link local address") + } + + return nil +} + +func (l *LsTLVIPv6NeighborAddr) Serialize() ([]byte, error) { + return l.LsTLV.Serialize(l.IP) +} + +func (l *LsTLVIPv6NeighborAddr) String() string { + return fmt.Sprintf("{IPv6 Neighbor Address: %v}", l.IP) +} + +func (l *LsTLVIPv6NeighborAddr) MarshalJSON() ([]byte, error) { + return json.Marshal(struct { + Type LsTLVType `json:"type"` + Value string `json:"ipv6_neighbor_address"` + }{ + Type: l.Type, + Value: fmt.Sprintf("%v", l.IP), + }) +} + +// https://tools.ietf.org/html/rfc7752#section-3.3.1.1 +type LsNodeFlags struct { + Overload bool `json:"overload"` + Attached bool `json:"attached"` + External bool `json:"external"` + ABR bool `json:"abr"` + Router bool `json:"router"` + V6 bool `json:"v6"` +} + +type LsTLVNodeFlagBits struct { + LsTLV + Flags uint8 +} + +func (l *LsTLVNodeFlagBits) Extract() *LsNodeFlags { + return &LsNodeFlags{ + Overload: (l.Flags & (1 << 7)) > 0, + Attached: (l.Flags & (1 << 6)) > 0, + External: (l.Flags & (1 << 5)) > 0, + ABR: (l.Flags & (1 << 4)) > 0, + Router: (l.Flags & (1 << 3)) > 0, + V6: (l.Flags & (1 << 2)) > 0, + } +} + +func (l *LsTLVNodeFlagBits) DecodeFromBytes(data []byte) error { + value, err := l.LsTLV.DecodeFromBytes(data) + if err != nil { + return err + } + + if l.Type != LS_TLV_NODE_FLAG_BITS { + return malformedAttrListErr("Unexpected TLV type") + } + + if l.Length != 1 { + return malformedAttrListErr("Node Flag Bits TLV malformed") + } + + l.Flags = value[0] + + return nil +} + +func (l *LsTLVNodeFlagBits) Serialize() ([]byte, error) { + return l.LsTLV.Serialize([]byte{l.Flags}) +} + +func (l *LsTLVNodeFlagBits) String() string { + flags := "XXVRBETO" + + var buf bytes.Buffer + + for i := 0; i < len(flags); i++ { + if l.Flags&(1< 0 { + buf.WriteString(flags[i : i+1]) + } else { + buf.WriteString("*") + } + } + + return fmt.Sprintf("{Node Flags: %s}", buf.String()) +} + +func (l *LsTLVNodeFlagBits) MarshalJSON() ([]byte, error) { + return json.Marshal(struct { + Type LsTLVType `json:"type"` + Flags string `json:"node_flags"` + }{ + Type: l.Type, + Flags: l.String(), + }) +} + +type LsTLVNodeName struct { + LsTLV + Name string +} + +func (l *LsTLVNodeName) DecodeFromBytes(data []byte) error { + value, err := l.LsTLV.DecodeFromBytes(data) + if err != nil { + return err + } + + if l.Type != LS_TLV_NODE_NAME { + return malformedAttrListErr("Unexpected TLV type") + } + + // RFC5301, section 3. + if l.Length < 1 || l.Length > 255 { + return malformedAttrListErr("Incorrect Node Name") + } + + l.Name = string(value) + + return nil +} + +func (l *LsTLVNodeName) Serialize() ([]byte, error) { + return l.LsTLV.Serialize([]byte(l.Name)) +} + +func (l *LsTLVNodeName) String() string { + return fmt.Sprintf("{Node Name: %s}", l.Name) +} + +func (l *LsTLVNodeName) MarshalJSON() ([]byte, error) { + return json.Marshal(struct { + Type LsTLVType `json:"type"` + Name string `json:"node_name"` + }{ + Type: l.Type, + Name: l.Name, + }) +} + +type LsTLVIsisArea struct { + LsTLV + Area []byte +} + +func (l *LsTLVIsisArea) DecodeFromBytes(data []byte) error { + value, err := l.LsTLV.DecodeFromBytes(data) + if err != nil { + return err + } + + if l.Type != LS_TLV_ISIS_AREA { + return malformedAttrListErr("Unexpected TLV type") + } + + if len(value) < 1 || len(value) > 13 { + return malformedAttrListErr("Incorrect ISIS Area size") + } + + l.Area = value + + return nil +} + +func (l *LsTLVIsisArea) Serialize() ([]byte, error) { + return l.LsTLV.Serialize(l.Area) +} + +func (l *LsTLVIsisArea) String() string { + return fmt.Sprintf("{ISIS Area ID: %v}", l.Area) +} + +func (l *LsTLVIsisArea) MarshalJSON() ([]byte, error) { + return json.Marshal(struct { + Type LsTLVType `json:"type"` + Area string `json:"isis_area_id"` + }{ + Type: l.Type, + Area: fmt.Sprintf("%v", l.Area), + }) +} + +type LsTLVLocalIPv4RouterID struct { + LsTLV + IP net.IP +} + +func (l *LsTLVLocalIPv4RouterID) DecodeFromBytes(data []byte) error { + value, err := l.LsTLV.DecodeFromBytes(data) + if err != nil { + return err + } + + if l.Type != LS_TLV_IPV4_LOCAL_ROUTER_ID { + return malformedAttrListErr("Unexpected TLV type") + } + + // https://tools.ietf.org/html/rfc5305#section-4.3 + if len(value) != 4 { + return malformedAttrListErr("Unexpected address size") + } + + l.IP = net.IP(value) + + return nil +} + +func (l *LsTLVLocalIPv4RouterID) Serialize() ([]byte, error) { + return l.LsTLV.Serialize(l.IP) +} + +func (l *LsTLVLocalIPv4RouterID) String() string { + return fmt.Sprintf("{Local RouterID IPv4: %v}", l.IP) +} + +func (l *LsTLVLocalIPv4RouterID) MarshalJSON() ([]byte, error) { + return json.Marshal(struct { + Type LsTLVType `json:"type"` + Value string `json:"node_local_router_id_ipv4"` + }{ + Type: l.Type, + Value: fmt.Sprintf("%v", l.IP), + }) +} + +type LsTLVRemoteIPv4RouterID struct { + LsTLV + IP net.IP +} + +func (l *LsTLVRemoteIPv4RouterID) DecodeFromBytes(data []byte) error { + value, err := l.LsTLV.DecodeFromBytes(data) + if err != nil { + return err + } + + if l.Type != LS_TLV_IPV4_REMOTE_ROUTER_ID { + return malformedAttrListErr("Unexpected TLV type") + } + + // https://tools.ietf.org/html/rfc5305#section-4.3 + if len(value) != 4 { + return malformedAttrListErr("Unexpected address size") + } + + l.IP = net.IP(value) + + return nil +} + +func (l *LsTLVRemoteIPv4RouterID) Serialize() ([]byte, error) { + return l.LsTLV.Serialize(l.IP) +} + +func (l *LsTLVRemoteIPv4RouterID) String() string { + return fmt.Sprintf("{Remote RouterID IPv4: %v}", l.IP) +} + +func (l *LsTLVRemoteIPv4RouterID) MarshalJSON() ([]byte, error) { + return json.Marshal(struct { + Type LsTLVType `json:"type"` + Value string `json:"node_remote_router_id_ipv4"` + }{ + Type: l.Type, + Value: fmt.Sprintf("%v", l.IP), + }) +} + +type LsTLVLocalIPv6RouterID struct { + LsTLV + IP net.IP +} + +func (l *LsTLVLocalIPv6RouterID) DecodeFromBytes(data []byte) error { + value, err := l.LsTLV.DecodeFromBytes(data) + if err != nil { + return err + } + + if l.Type != LS_TLV_IPV6_LOCAL_ROUTER_ID { + return malformedAttrListErr("Unexpected TLV type") + } + + // https://tools.ietf.org/html/rfc6119#section-4.1 + if len(value) != 16 { + return malformedAttrListErr("Unexpected address size") + } + + l.IP = net.IP(value) + + return nil +} + +func (l *LsTLVLocalIPv6RouterID) Serialize() ([]byte, error) { + return l.LsTLV.Serialize(l.IP) +} + +func (l *LsTLVLocalIPv6RouterID) String() string { + return fmt.Sprintf("{Local RouterID IPv6: %v}", l.IP) +} + +func (l *LsTLVLocalIPv6RouterID) MarshalJSON() ([]byte, error) { + return json.Marshal(struct { + Type LsTLVType `json:"type"` + Value string `json:"node_local_router_id_ipv6"` + }{ + Type: l.Type, + Value: fmt.Sprintf("%v", l.IP), + }) +} + +type LsTLVRemoteIPv6RouterID struct { + LsTLV + IP net.IP +} + +func (l *LsTLVRemoteIPv6RouterID) DecodeFromBytes(data []byte) error { + value, err := l.LsTLV.DecodeFromBytes(data) + if err != nil { + return err + } + + if l.Type != LS_TLV_IPV6_REMOTE_ROUTER_ID { + return malformedAttrListErr("Unexpected TLV type") + } + + // https://tools.ietf.org/html/rfc6119#section-4.1 + if len(value) != 16 { + return malformedAttrListErr("Unexpected address size") + } + + l.IP = net.IP(value) + + return nil +} + +func (l *LsTLVRemoteIPv6RouterID) Serialize() ([]byte, error) { + return l.LsTLV.Serialize(l.IP) +} + +func (l *LsTLVRemoteIPv6RouterID) String() string { + return fmt.Sprintf("{Remote RouterID IPv6: %v}", l.IP) +} + +func (l *LsTLVRemoteIPv6RouterID) MarshalJSON() ([]byte, error) { + return json.Marshal(struct { + Type LsTLVType `json:"type"` + Value string `json:"node_remote_router_id_ipv6"` + }{ + Type: l.Type, + Value: fmt.Sprintf("%v", l.IP), + }) +} + +type LsTLVOpaqueNodeAttr struct { + LsTLV + Attr []byte +} + +func (l *LsTLVOpaqueNodeAttr) DecodeFromBytes(data []byte) error { + value, err := l.LsTLV.DecodeFromBytes(data) + if err != nil { + return err + } + + if l.Type != LS_TLV_OPAQUE_NODE_ATTR { + return malformedAttrListErr("Unexpected TLV type") + } + + l.Attr = value + + return nil +} + +func (l *LsTLVOpaqueNodeAttr) Serialize() ([]byte, error) { + return l.LsTLV.Serialize(l.Attr) +} + +func (l *LsTLVOpaqueNodeAttr) String() string { + return fmt.Sprintf("{Opaque attribute: %v}", l.Attr) +} + +func (l *LsTLVOpaqueNodeAttr) MarshalJSON() ([]byte, error) { + return json.Marshal(struct { + Type LsTLVType `json:"type"` + Value string `json:"node_opaque_attribute"` + }{ + Type: l.Type, + Value: fmt.Sprintf("%v", l.Attr), + }) +} + +type LsTLVAutonomousSystem struct { + LsTLV + ASN uint32 +} + +func (l *LsTLVAutonomousSystem) DecodeFromBytes(data []byte) error { + value, err := l.LsTLV.DecodeFromBytes(data) + if err != nil { + return err + } + + if l.Type != LS_TLV_AS { + return malformedAttrListErr("Unexpected TLV type") + } + + // https://tools.ietf.org/html/rfc7752#section-3.2.1.4 + if len(value) != 4 { + return malformedAttrListErr("Incorrect AS length") + } + + l.ASN = binary.BigEndian.Uint32(value) + + return nil +} + +func (l *LsTLVAutonomousSystem) Serialize() ([]byte, error) { + buf := make([]byte, 4) + binary.BigEndian.PutUint32(buf, l.ASN) + + return l.LsTLV.Serialize(buf) +} + +func (l *LsTLVAutonomousSystem) String() string { + return fmt.Sprintf("{ASN: %d}", l.ASN) +} + +func (l *LsTLVAutonomousSystem) MarshalJSON() ([]byte, error) { + return json.Marshal(struct { + Type LsTLVType `json:"type"` + ASN uint32 `json:"asn"` + }{ + Type: l.Type, + ASN: l.ASN, + }) +} + +type LsTLVBgpLsID struct { + LsTLV + BGPLsID uint32 +} + +func (l *LsTLVBgpLsID) DecodeFromBytes(data []byte) error { + value, err := l.LsTLV.DecodeFromBytes(data) + if err != nil { + return err + } + + if l.Type != LS_TLV_BGP_LS_ID { + return malformedAttrListErr("Unexpected TLV type") + } + + // https://tools.ietf.org/html/rfc7752#section-3.2.1.4 + if len(value) != 4 { + return malformedAttrListErr("Incorrect BGP-LS ID length") + } + + l.BGPLsID = binary.BigEndian.Uint32(value) + + return nil +} + +func (l *LsTLVBgpLsID) Serialize() ([]byte, error) { + buf := make([]byte, 4) + binary.BigEndian.PutUint32(buf, l.BGPLsID) + + return l.LsTLV.Serialize(buf) +} + +func (l *LsTLVBgpLsID) String() string { + return fmt.Sprintf("{BGP LS ID: %d}", l.BGPLsID) +} + +func (l *LsTLVBgpLsID) MarshalJSON() ([]byte, error) { + return json.Marshal(struct { + Type LsTLVType `json:"type"` + BgpLsID uint32 `json:"bgp_ls_id"` + }{ + Type: l.Type, + BgpLsID: l.BGPLsID, + }) +} + +type LsTLVIgpRouterID struct { + LsTLV + RouterID []byte +} + +func (l *LsTLVIgpRouterID) DecodeFromBytes(data []byte) error { + value, err := l.LsTLV.DecodeFromBytes(data) + if err != nil { + return err + } + + if l.Type != LS_TLV_IGP_ROUTER_ID { + return malformedAttrListErr("Unexpected TLV type") + } + + // https://tools.ietf.org/html/rfc7752#section-3.2.1.4 + // 6, 7, and 8 are the only valid values. + if len(value) < 6 || len(value) > 8 { + return malformedAttrListErr("Incorrect IGP Router ID length") + } + + l.RouterID = value + + return nil +} + +func (l *LsTLVIgpRouterID) Serialize() ([]byte, error) { + return l.LsTLV.Serialize(l.RouterID) +} + +func (l *LsTLVIgpRouterID) String() string { + return fmt.Sprintf("{IGP Router ID: %v}", l.RouterID) +} + +func (l *LsTLVIgpRouterID) MarshalJSON() ([]byte, error) { + return json.Marshal(struct { + Type LsTLVType `json:"type"` + RouterID string `json:"igp_router_id"` + }{ + Type: l.Type, + RouterID: fmt.Sprintf("%v", l.RouterID), + }) +} + +type LsTLVOspfAreaID struct { + LsTLV + AreaID uint32 +} + +func (l *LsTLVOspfAreaID) DecodeFromBytes(data []byte) error { + value, err := l.LsTLV.DecodeFromBytes(data) + if err != nil { + return err + } + + if l.Type != LS_TLV_OSPF_AREA { + return malformedAttrListErr("Unexpected TLV type") + } + + // https://tools.ietf.org/html/rfc7752#section-3.2.1.4 + if len(value) != 4 { + return malformedAttrListErr("Incorrect OSPF Area ID length") + } + + l.AreaID = binary.BigEndian.Uint32(value) + + return nil +} + +func (l *LsTLVOspfAreaID) Serialize() ([]byte, error) { + buf := make([]byte, 4) + binary.BigEndian.PutUint32(buf, l.AreaID) + + return l.LsTLV.Serialize(buf) +} + +func (l *LsTLVOspfAreaID) String() string { + return fmt.Sprintf("{OSPF Area ID: %d}", l.AreaID) +} + +func (l *LsTLVOspfAreaID) MarshalJSON() ([]byte, error) { + return json.Marshal(struct { + Type LsTLVType `json:"type"` + AreaID uint32 `json:"ospf_area_id"` + }{ + Type: l.Type, + AreaID: l.AreaID, + }) +} + +type LsOspfRouteType uint8 + +const ( + LS_OSPF_ROUTE_TYPE_UNKNOWN = iota + LS_OSPF_ROUTE_TYPE_INTRA_AREA + LS_OSPF_ROUTE_TYPE_INTER_AREA + LS_OSPF_ROUTE_TYPE_EXTERNAL1 + LS_OSPF_ROUTE_TYPE_EXTERNAL2 + LS_OSPF_ROUTE_TYPE_NSSA1 + LS_OSPF_ROUTE_TYPE_NSSA2 +) + +func (l LsOspfRouteType) String() string { + switch l { + case LS_OSPF_ROUTE_TYPE_INTRA_AREA: + return "INTRA-AREA" + case LS_OSPF_ROUTE_TYPE_INTER_AREA: + return "INTER-AREA" + case LS_OSPF_ROUTE_TYPE_EXTERNAL1: + return "EXTERNAL1" + case LS_OSPF_ROUTE_TYPE_EXTERNAL2: + return "EXTERNAL2" + case LS_OSPF_ROUTE_TYPE_NSSA1: + return "NSSA1" + case LS_OSPF_ROUTE_TYPE_NSSA2: + return "NSSA2" + default: + return fmt.Sprintf("LsOspfRouteType(%d)", uint8(l)) + } +} + +type LsTLVOspfRouteType struct { + LsTLV + RouteType LsOspfRouteType +} + +func (l *LsTLVOspfRouteType) DecodeFromBytes(data []byte) error { + value, err := l.LsTLV.DecodeFromBytes(data) + if err != nil { + return err + } + + if l.Type != LS_TLV_OSPF_ROUTE_TYPE { + return malformedAttrListErr("Unexpected TLV type") + } + + // https://tools.ietf.org/html/rfc7752#section-3.2.3.1 + if len(value) != 1 { + return malformedAttrListErr("Incorrect OSPF Route type length") + } + + if value[0] < byte(LS_OSPF_ROUTE_TYPE_INTRA_AREA) || value[0] > LS_OSPF_ROUTE_TYPE_NSSA2 { + return malformedAttrListErr("Incorrect OSPF Route type") + } + + l.RouteType = LsOspfRouteType(value[0]) + + return nil +} + +func (l *LsTLVOspfRouteType) Serialize() ([]byte, error) { + buf := make([]byte, 1) + buf[0] = byte(l.RouteType) + + return l.LsTLV.Serialize(buf) +} + +func (l *LsTLVOspfRouteType) String() string { + return fmt.Sprintf("{OSPF Route Type: %v}", l.RouteType) +} + +func (l *LsTLVOspfRouteType) MarshalJSON() ([]byte, error) { + return json.Marshal(struct { + Type LsTLVType `json:"type"` + RouteType string `json:"ospf_route_type"` + }{ + Type: l.Type, + RouteType: l.RouteType.String(), + }) +} + +type LsTLVIPReachability struct { + LsTLV + PrefixLength uint8 + Prefix []byte +} + +func (l *LsTLVIPReachability) ToIPNet(ipv6 bool) net.IPNet { + b := make([]byte, 16) + for i := 0; i < int(((l.PrefixLength-1)/8)+1); i++ { + b[i] = l.Prefix[i] + } + + ip := net.IPv4(b[0], b[1], b[2], b[3]).To4() + if ipv6 { + ip = net.IP(b).To16() + } + + _, n, err := net.ParseCIDR(fmt.Sprintf("%v/%v", ip, l.PrefixLength)) + if err != nil { + return net.IPNet{} + } + + return *n +} + +func (l *LsTLVIPReachability) DecodeFromBytes(data []byte) error { + value, err := l.LsTLV.DecodeFromBytes(data) + if err != nil { + return err + } + + if l.Type != LS_TLV_IP_REACH_INFO { + return malformedAttrListErr("Unexpected TLV type") + } + + if len(value) < 2 { + return malformedAttrListErr("Incorrect IP reachability Info length") + } + + // https://tools.ietf.org/html/rfc7752#section-3.2.3.2 + if value[0] > 128 || value[0] == 0 { + return malformedAttrListErr("Incorrect IP prefix length") + } + + ll := int(((value[0] - 1) / 8) + 1) + if len(value[1:]) != ll { + return malformedAttrListErr("Malformed IP reachability TLV") + } + + l.PrefixLength = value[0] + l.Prefix = value[1 : 1+ll] + + return nil +} + +func (l *LsTLVIPReachability) Serialize() ([]byte, error) { + b := []byte{l.PrefixLength} + + return l.LsTLV.Serialize(append(b, l.Prefix...)) +} + +func (l *LsTLVIPReachability) String() string { + return fmt.Sprintf("{IP Reachability: %v/%v}", l.Prefix, l.PrefixLength) +} + +func (l *LsTLVIPReachability) MarshalJSON() ([]byte, error) { + return json.Marshal(struct { + Type LsTLVType `json:"type"` + PrefixLength uint8 `json:"prefix_length"` + Prefix string `json:"prefix"` + }{ + Type: l.Type, + PrefixLength: l.PrefixLength, + Prefix: fmt.Sprintf("%v", l.Prefix), + }) +} + +type LsTLVAdminGroup struct { + LsTLV + AdminGroup uint32 +} + +func (l *LsTLVAdminGroup) DecodeFromBytes(data []byte) error { + value, err := l.LsTLV.DecodeFromBytes(data) + if err != nil { + return err + } + + if l.Type != LS_TLV_ADMIN_GROUP { + return malformedAttrListErr("Unexpected TLV type") + } + + // https://tools.ietf.org/html/rfc5305#section-3.1 + if len(value) != 4 { + return malformedAttrListErr("Incorrect Admin Group length") + } + + l.AdminGroup = binary.BigEndian.Uint32(value) + + return nil +} + +func (l *LsTLVAdminGroup) Serialize() ([]byte, error) { + buf := make([]byte, 4) + binary.BigEndian.PutUint32(buf, l.AdminGroup) + + return l.LsTLV.Serialize(buf) +} + +func (l *LsTLVAdminGroup) String() string { + return fmt.Sprintf("{Admin Group: %08x}", l.AdminGroup) +} + +func (l *LsTLVAdminGroup) MarshalJSON() ([]byte, error) { + return json.Marshal(struct { + Type LsTLVType `json:"type"` + AdminGroup string `json:"admin_group"` + }{ + Type: l.Type, + AdminGroup: fmt.Sprintf("%08x", l.AdminGroup), + }) +} + +type LsTLVMaxLinkBw struct { + LsTLV + Bandwidth float32 +} + +func (l *LsTLVMaxLinkBw) DecodeFromBytes(data []byte) error { + value, err := l.LsTLV.DecodeFromBytes(data) + if err != nil { + return err + } + + if l.Type != LS_TLV_MAX_LINK_BANDWIDTH { + return malformedAttrListErr("Unexpected TLV type") + } + + // https://tools.ietf.org/html/rfc5305#section-3.4 + if len(value) != 4 { + return malformedAttrListErr("Incorrect maximum link bandwidth length") + } + + l.Bandwidth = math.Float32frombits(binary.BigEndian.Uint32(value)) + + if l.Bandwidth < 0 || math.IsNaN(float64(l.Bandwidth)) || math.IsInf(float64(l.Bandwidth), 0) { + return malformedAttrListErr("Incorrect maximum link bandwidth value") + } + + return nil +} + +func (l *LsTLVMaxLinkBw) Serialize() ([]byte, error) { + buf := make([]byte, 4) + binary.BigEndian.PutUint32(buf, math.Float32bits(l.Bandwidth)) + + return l.LsTLV.Serialize(buf) +} + +func (l *LsTLVMaxLinkBw) String() string { + return fmt.Sprintf("{Max Link BW: %v}", l.Bandwidth) +} + +func (l *LsTLVMaxLinkBw) MarshalJSON() ([]byte, error) { + return json.Marshal(struct { + Type LsTLVType `json:"type"` + Bandwidth float32 `json:"max_link_bw"` + }{ + Type: l.Type, + Bandwidth: l.Bandwidth, + }) +} + +type LsTLVMaxReservableLinkBw struct { + LsTLV + Bandwidth float32 +} + +func (l *LsTLVMaxReservableLinkBw) DecodeFromBytes(data []byte) error { + value, err := l.LsTLV.DecodeFromBytes(data) + if err != nil { + return err + } + + if l.Type != LS_TLV_MAX_RESERVABLE_BANDWIDTH { + return malformedAttrListErr("Unexpected TLV type") + } + + // https://tools.ietf.org/html/rfc5305#section-3.5 + if len(value) != 4 { + return malformedAttrListErr("Incorrect maximum reservable link bandwidth length") + } + + l.Bandwidth = math.Float32frombits(binary.BigEndian.Uint32(value)) + + if l.Bandwidth < 0 || math.IsNaN(float64(l.Bandwidth)) || math.IsInf(float64(l.Bandwidth), 0) { + return malformedAttrListErr("Incorrect maximum reservable link bandwidth value") + } + + return nil +} + +func (l *LsTLVMaxReservableLinkBw) Serialize() ([]byte, error) { + buf := make([]byte, 4) + binary.BigEndian.PutUint32(buf, math.Float32bits(l.Bandwidth)) + + return l.LsTLV.Serialize(buf) +} + +func (l *LsTLVMaxReservableLinkBw) String() string { + return fmt.Sprintf("{Max Reservable Link BW: %v}", l.Bandwidth) +} + +func (l *LsTLVMaxReservableLinkBw) MarshalJSON() ([]byte, error) { + return json.Marshal(struct { + Type LsTLVType `json:"type"` + Bandwidth float32 `json:"max_reservable_link_bw"` + }{ + Type: l.Type, + Bandwidth: l.Bandwidth, + }) +} + +type LsTLVUnreservedBw struct { + LsTLV + Bandwidth [8]float32 +} + +func (l *LsTLVUnreservedBw) DecodeFromBytes(data []byte) error { + value, err := l.LsTLV.DecodeFromBytes(data) + if err != nil { + return err + } + + if l.Type != LS_TLV_UNRESERVED_BANDWIDTH { + return malformedAttrListErr("Unexpected TLV type") + } + + // https://tools.ietf.org/html/rfc5305#section-3.6 + if len(value) != 32 { + return malformedAttrListErr("Incorrect unreserved bandwidth length") + } + + for i := 0; i < len(l.Bandwidth); i++ { + l.Bandwidth[i] = math.Float32frombits(binary.BigEndian.Uint32(value[:4])) + value = value[4:] + + if l.Bandwidth[i] < 0 || math.IsNaN(float64(l.Bandwidth[i])) || math.IsInf(float64(l.Bandwidth[i]), 0) { + return malformedAttrListErr("Incorrect unreserved bandwidth value") + } + } + + return nil +} + +func (l *LsTLVUnreservedBw) Serialize() ([]byte, error) { + buf := make([]byte, 0) + + for i := 0; i < len(l.Bandwidth); i++ { + b := make([]byte, 4) + binary.BigEndian.PutUint32(b, math.Float32bits(l.Bandwidth[i])) + buf = append(buf, b...) + } + + return l.LsTLV.Serialize(buf) +} + +func (l *LsTLVUnreservedBw) String() string { + return fmt.Sprintf("{Unreserved BW: %v}", l.Bandwidth) +} + +func (l *LsTLVUnreservedBw) MarshalJSON() ([]byte, error) { + return json.Marshal(struct { + Type LsTLVType `json:"type"` + Bandwidth [8]float32 `json:"unreserved_bw"` + }{ + Type: l.Type, + Bandwidth: l.Bandwidth, + }) +} + +type LsTLVTEDefaultMetric struct { + LsTLV + Metric uint32 +} + +func (l *LsTLVTEDefaultMetric) DecodeFromBytes(data []byte) error { + value, err := l.LsTLV.DecodeFromBytes(data) + if err != nil { + return err + } + + if l.Type != LS_TLV_TE_DEFAULT_METRIC { + return malformedAttrListErr("Unexpected TLV type") + } + + // https://tools.ietf.org/html/rfc7752#section-3.3.2.3 + if len(value) != 4 { + return malformedAttrListErr("Incorrect metric length length") + } + + l.Metric = binary.BigEndian.Uint32(value) + + return nil +} + +func (l *LsTLVTEDefaultMetric) Serialize() ([]byte, error) { + buf := make([]byte, 4) + binary.BigEndian.PutUint32(buf, l.Metric) + + return l.LsTLV.Serialize(buf) +} + +func (l *LsTLVTEDefaultMetric) String() string { + return fmt.Sprintf("{TE Default metric: %d}", l.Metric) +} + +func (l *LsTLVTEDefaultMetric) MarshalJSON() ([]byte, error) { + return json.Marshal(struct { + Type LsTLVType `json:"type"` + DefaultMetric uint32 `json:"te_default_metric"` + }{ + Type: l.Type, + DefaultMetric: l.Metric, + }) +} + +type LsTLVIGPMetric struct { + LsTLV + Metric uint32 +} + +func (l *LsTLVIGPMetric) DecodeFromBytes(data []byte) error { + value, err := l.LsTLV.DecodeFromBytes(data) + if err != nil { + return err + } + + if l.Type != LS_TLV_IGP_METRIC { + return malformedAttrListErr("Unexpected TLV type") + } + + // https://tools.ietf.org/html/rfc7752#section-3.3.2.4 + switch len(value) { + case 1: + l.Metric = uint32(value[0] & 0x3F) + + case 2: + l.Metric = uint32(binary.BigEndian.Uint16(value)) + + case 3: + l.Metric = binary.BigEndian.Uint32([]byte{0, value[0], value[1], value[2]}) + + default: + return malformedAttrListErr("Incorrect metric length") + } + + return nil +} + +func (l *LsTLVIGPMetric) Serialize() ([]byte, error) { + switch l.Length { + case 1: + return l.LsTLV.Serialize([]byte{uint8(l.Metric) & 0x3F}) + + case 2: + buf := make([]byte, 2) + binary.BigEndian.PutUint16(buf, uint16(l.Metric)) + return l.LsTLV.Serialize(buf) + + case 3: + buf := make([]byte, 4) + binary.BigEndian.PutUint32(buf, l.Metric) + return l.LsTLV.Serialize(buf[1:]) + + default: + return nil, malformedAttrListErr("Incorrect metric length") + } +} + +func (l *LsTLVIGPMetric) String() string { + return fmt.Sprintf("{IGP metric: %d}", l.Metric) +} + +func (l *LsTLVIGPMetric) MarshalJSON() ([]byte, error) { + return json.Marshal(struct { + Type LsTLVType `json:"type"` + Metric uint32 `json:"igp_metric"` + }{ + Type: l.Type, + Metric: l.Metric, + }) +} + +type LsTLVLinkName struct { + LsTLV + Name string +} + +func (l *LsTLVLinkName) DecodeFromBytes(data []byte) error { + value, err := l.LsTLV.DecodeFromBytes(data) + if err != nil { + return err + } + + if l.Type != LS_TLV_LINK_NAME { + return malformedAttrListErr("Unexpected TLV type") + } + + // https://tools.ietf.org/html/rfc7752#section-3.3.2.7 + if len(value) < 1 || len(value) > 255 { + return malformedAttrListErr("Incorrect Link Name") + } + + l.Name = string(value) + + return nil +} + +func (l *LsTLVLinkName) Serialize() ([]byte, error) { + return l.LsTLV.Serialize([]byte(l.Name)) +} + +func (l *LsTLVLinkName) String() string { + return fmt.Sprintf("{Link Name: %s}", l.Name) +} + +func (l *LsTLVLinkName) MarshalJSON() ([]byte, error) { + return json.Marshal(struct { + Type LsTLVType `json:"type"` + Name string `json:"link_name"` + }{ + Type: l.Type, + Name: l.Name, + }) +} + +type LsTLVSrAlgorithm struct { + LsTLV + Algorithm []byte +} + +func (l *LsTLVSrAlgorithm) DecodeFromBytes(data []byte) error { + value, err := l.LsTLV.DecodeFromBytes(data) + if err != nil { + return err + } + + if l.Type != LS_TLV_SR_ALGORITHM { + return malformedAttrListErr("Unexpected TLV type") + } + + if len(value) < 1 { + return malformedAttrListErr("Incorrect SR algorithm length") + } + + l.Algorithm = value + + return nil +} + +func (l *LsTLVSrAlgorithm) Serialize() ([]byte, error) { + return l.LsTLV.Serialize(l.Algorithm) +} + +func (l *LsTLVSrAlgorithm) String() string { + return fmt.Sprintf("{SR Algorithms: %v}", l.Algorithm) +} + +func (l *LsTLVSrAlgorithm) MarshalJSON() ([]byte, error) { + return json.Marshal(struct { + Type LsTLVType `json:"type"` + Algorithms string `json:"sr_algorithm"` + }{ + Type: l.Type, + Algorithms: fmt.Sprintf("%v", l.Algorithm), + }) +} + +type LsSrLabelRange struct { + Range uint32 + FirstLabel LsTLVSIDLabel +} + +type LsTLVSrCapabilities struct { + LsTLV + Flags uint8 + Ranges []LsSrLabelRange +} + +type LsSrRange struct { + Begin uint32 `json:"begin"` + End uint32 `json:"end"` +} + +type LsSrCapabilities struct { + IPv4Supported bool `json:"ipv4_supported"` + IPv6Supported bool `json:"ipv6_supported"` + Ranges []LsSrRange `json:"ranges"` +} + +func (l *LsTLVSrCapabilities) Extract() *LsSrCapabilities { + lsc := &LsSrCapabilities{ + IPv4Supported: (l.Flags & (1 << 0)) > 0, + IPv6Supported: (l.Flags & (1 << 1)) > 0, + } + + for _, r := range l.Ranges { + lsc.Ranges = append(lsc.Ranges, LsSrRange{ + Begin: r.FirstLabel.SID, + End: r.FirstLabel.SID + r.Range, + }) + } + + return lsc +} + +func (l *LsTLVSrCapabilities) DecodeFromBytes(data []byte) error { + value, err := l.LsTLV.DecodeFromBytes(data) + if err != nil { + return err + } + + if l.Type != LS_TLV_SR_CAPABILITIES { + return malformedAttrListErr("Unexpected TLV type") + } + + if len(value) < 2 { + return malformedAttrListErr("Incorrect SR Capabilities length") + } + l.Flags = value[0] + + // Skip two bytes: flags and reserved. + value = value[2:] + + // The value field should be at least eight bytes long. Three bytes + // for the range size and five or six bytes for the SID/Label TLV. + for len(value) > 8 { + // First, parse range size (3 bytes) + buf := []byte{0, 0, 0, 0} + for i := 1; i < len(buf); i++ { + buf[i] = value[i-1] + } + r := binary.BigEndian.Uint32(buf) + value = value[3:] + + // Second, parse SID/Label sub-TLV. + label := LsTLVSIDLabel{} + if err := label.DecodeFromBytes(value); err != nil { + return err + } + + l.Ranges = append(l.Ranges, LsSrLabelRange{ + Range: r, + FirstLabel: label, + }) + + value = value[label.Len():] + } + + if len(value) > 0 { + return malformedAttrListErr("Malformed SR Capabilities TLV") + } + + return nil +} + +func (l *LsTLVSrCapabilities) Serialize() ([]byte, error) { + buf := make([]byte, 0) + buf = append(buf, l.Flags) + buf = append(buf, 0) + + for _, r := range l.Ranges { + b := make([]byte, 4) + binary.BigEndian.PutUint32(b, r.Range) + buf = append(buf, b[1:]...) + ser, err := r.FirstLabel.Serialize() + if err != nil { + return nil, err + } + buf = append(buf, ser...) + } + + return l.LsTLV.Serialize(buf) +} + +func (l *LsTLVSrCapabilities) String() string { + var buf bytes.Buffer + + for _, r := range l.Ranges { + buf.WriteString(fmt.Sprintf("%v:%v ", r.FirstLabel.SID, r.FirstLabel.SID+r.Range)) + } + + return fmt.Sprintf("{SR Capabilities: Flags:%v SRGB Ranges: %v}", l.Flags, buf.String()) +} + +func (l *LsTLVSrCapabilities) MarshalJSON() ([]byte, error) { + return json.Marshal(struct { + Type LsTLVType `json:"type"` + Flags uint8 `json:"flags"` + Ranges []LsSrLabelRange `json:"ranges"` + }{ + Type: l.Type, + Flags: l.Flags, + Ranges: l.Ranges, + }) +} + +type LsTLVSrLocalBlock struct { + LsTLV + Flags uint8 + Ranges []LsSrLabelRange +} + +type LsSrLocalBlock struct { + Ranges []LsSrRange `json:"ranges"` +} + +func (l *LsTLVSrLocalBlock) Extract() *LsSrLocalBlock { + lb := &LsSrLocalBlock{} + + for _, r := range l.Ranges { + lb.Ranges = append(lb.Ranges, LsSrRange{ + Begin: r.FirstLabel.SID, + End: r.FirstLabel.SID + r.Range, + }) + } + + return lb +} + +func (l *LsTLVSrLocalBlock) DecodeFromBytes(data []byte) error { + value, err := l.LsTLV.DecodeFromBytes(data) + if err != nil { + return err + } + + if l.Type != LS_TLV_SR_LOCAL_BLOCK { + return malformedAttrListErr("Unexpected TLV type") + } + + if len(value) < 2 { + return malformedAttrListErr("Incorrect SR Local Block length") + } + l.Flags = value[0] + + // Skip two bytes: flags and reserved. + value = value[2:] + + // The value field should be at least eight bytes long. Three bytes + // for the range size and five or six bytes for the SID/Label TLV. + for len(value) > 8 { + // First, parse range size (3 bytes) + buf := []byte{0, 0, 0, 0} + for i := 1; i < len(buf); i++ { + buf[i] = value[i-1] + } + r := binary.BigEndian.Uint32(buf) + value = value[3:] + + // Second, parse SID/Label sub-TLV. + label := LsTLVSIDLabel{} + if err := label.DecodeFromBytes(value); err != nil { + return err + } + + l.Ranges = append(l.Ranges, LsSrLabelRange{ + Range: r, + FirstLabel: label, + }) + + value = value[label.Len():] + } + + if len(value) > 0 { + return malformedAttrListErr("Malformed SR Local Block TLV") + } + + return nil +} + +func (l *LsTLVSrLocalBlock) Serialize() ([]byte, error) { + buf := make([]byte, 0) + buf = append(buf, l.Flags) + buf = append(buf, 0) + + for _, r := range l.Ranges { + b := make([]byte, 4) + binary.BigEndian.PutUint32(b, r.Range) + buf = append(buf, b[1:]...) + ser, err := r.FirstLabel.Serialize() + if err != nil { + return nil, err + } + buf = append(buf, ser...) + } + + return l.LsTLV.Serialize(buf) +} + +func (l *LsTLVSrLocalBlock) String() string { + var buf bytes.Buffer + + for _, r := range l.Ranges { + buf.WriteString(fmt.Sprintf("%v:%v ", r.FirstLabel.SID, r.FirstLabel.SID+r.Range)) + } + + return fmt.Sprintf("{SR LocalBlock: Flags:%v SRGB Ranges: %v}", l.Flags, buf.String()) +} + +func (l *LsTLVSrLocalBlock) MarshalJSON() ([]byte, error) { + return json.Marshal(struct { + Type LsTLVType `json:"type"` + Flags uint8 `json:"flags"` + Ranges []LsSrLabelRange `json:"ranges"` + }{ + Type: l.Type, + Flags: l.Flags, + Ranges: l.Ranges, + }) +} + +type LsTLVAdjacencySID struct { + LsTLV + Flags uint8 + Weight uint8 + SID uint32 +} + +func (l *LsTLVAdjacencySID) DecodeFromBytes(data []byte) error { + value, err := l.LsTLV.DecodeFromBytes(data) + if err != nil { + return err + } + + if l.Type != LS_TLV_ADJACENCY_SID { + return malformedAttrListErr("Unexpected TLV type") + } + + // https://tools.ietf.org/html/draft-ietf-idr-bgp-ls-segment-routing-ext-08#section-2.2.1 + if len(value) != 7 && len(value) != 8 { + return malformedAttrListErr("Incorrect Adjacency SID length") + } + + l.Flags = value[0] + l.Weight = value[1] + + v := value[4:] + if len(v) == 4 { + l.SID = binary.BigEndian.Uint32(v) + } else { + buf := []byte{0, 0, 0, 0} + for i := 1; i < len(buf); i++ { + buf[i] = v[i-1] + } + // Label is represented by 20 rightmost bits. + l.SID = binary.BigEndian.Uint32(buf) & 0xfffff + } + + return nil +} + +func (l *LsTLVAdjacencySID) Serialize() ([]byte, error) { + buf := make([]byte, 0) + buf = append(buf, l.Flags) + buf = append(buf, l.Weight) + // Reserved + buf = append(buf, []byte{0, 0}...) + + b := make([]byte, 4) + binary.BigEndian.PutUint32(b, l.SID) + + if l.Length == 7 { + return l.LsTLV.Serialize(append(buf, b[1:]...)) + } + + return l.LsTLV.Serialize(append(buf, b...)) +} + +func (l *LsTLVAdjacencySID) String() string { + return fmt.Sprintf("{Adjacency SID: %v}", l.SID) +} + +func (l *LsTLVAdjacencySID) MarshalJSON() ([]byte, error) { + return json.Marshal(struct { + Type LsTLVType `json:"type"` + SID uint32 `json:"adjacency_sid"` + }{ + Type: l.Type, + SID: l.SID, + }) +} + +type LsTLVSIDLabel struct { + LsTLV + SID uint32 +} + +func (l *LsTLVSIDLabel) DecodeFromBytes(data []byte) error { + value, err := l.LsTLV.DecodeFromBytes(data) + if err != nil { + return err + } + + if l.Type != LS_TLV_SID_LABEL_TLV { + return malformedAttrListErr("Unexpected TLV type") + } + + // https://tools.ietf.org/html/draft-ietf-idr-bgp-ls-segment-routing-ext-08#section-2.1.1 + if len(value) != 4 && len(value) != 3 { + return malformedAttrListErr("Incorrect SID length") + } + + if len(value) == 4 { + l.SID = binary.BigEndian.Uint32(value) + } else { + buf := []byte{0, 0, 0, 0} + for i := 1; i < len(buf); i++ { + buf[i] = value[i-1] + } + // Label is represented by 20 rightmost bits. + l.SID = binary.BigEndian.Uint32(buf) & 0xfffff + } + + return nil +} + +func (l *LsTLVSIDLabel) Serialize() ([]byte, error) { + buf := make([]byte, 4) + binary.BigEndian.PutUint32(buf, l.SID) + + if l.Length == 3 { + return l.LsTLV.Serialize(buf[1:]) + } + + return l.LsTLV.Serialize(buf) +} + +func (l *LsTLVSIDLabel) String() string { + return fmt.Sprintf("{SID/Label: %v}", l.SID) +} + +func (l *LsTLVSIDLabel) MarshalJSON() ([]byte, error) { + return json.Marshal(struct { + Type LsTLVType `json:"type"` + SID uint32 `json:"sid_label"` + }{ + Type: l.Type, + SID: l.SID, + }) +} + +type LsTLVPrefixSID struct { + LsTLV + Flags uint8 + Algorithm uint8 + SID uint32 +} + +func (l *LsTLVPrefixSID) DecodeFromBytes(data []byte) error { + value, err := l.LsTLV.DecodeFromBytes(data) + if err != nil { + return err + } + + if l.Type != LS_TLV_PREFIX_SID { + return malformedAttrListErr("Unexpected TLV type") + } + + // https://tools.ietf.org/html/draft-ietf-idr-bgp-ls-segment-routing-ext-08#section-2.3.1 + if len(value) != 7 && len(value) != 8 { + return malformedAttrListErr("Incorrect Prefix SID length") + } + + l.Flags = value[0] + l.Algorithm = value[1] + + // Flags (1) + Algorithm (1) + Reserved (2) + v := value[4:] + if len(v) == 4 { + l.SID = binary.BigEndian.Uint32(v) + } else { + buf := []byte{0, 0, 0, 0} + for i := 1; i < len(buf); i++ { + buf[i] = v[i-1] + } + // Label is represented by 20 rightmost bits. + l.SID = binary.BigEndian.Uint32(buf) & 0xfffff + } + + return nil +} + +func (l *LsTLVPrefixSID) Serialize() ([]byte, error) { + buf := make([]byte, 0) + buf = append(buf, l.Flags) + buf = append(buf, l.Algorithm) + // Reserved + buf = append(buf, []byte{0, 0}...) + + b := make([]byte, 4) + binary.BigEndian.PutUint32(b, l.SID) + + if l.Length == 7 { + return l.LsTLV.Serialize(append(buf, b[1:]...)) + } + + return l.LsTLV.Serialize(append(buf, b...)) +} + +func (l *LsTLVPrefixSID) String() string { + return fmt.Sprintf("{Prefix SID: %v}", l.SID) +} + +func (l *LsTLVPrefixSID) MarshalJSON() ([]byte, error) { + return json.Marshal(struct { + Type LsTLVType `json:"type"` + SID uint32 `json:"prefix_sid"` + }{ + Type: l.Type, + SID: l.SID, + }) +} + +type LsTLVSourceRouterID struct { + LsTLV + RouterID []byte +} + +func (l *LsTLVSourceRouterID) DecodeFromBytes(data []byte) error { + value, err := l.LsTLV.DecodeFromBytes(data) + if err != nil { + return err + } + + if l.Type != LS_TLV_SOURCE_ROUTER_ID { + return malformedAttrListErr("Unexpected TLV type") + } + + // https://tools.ietf.org/html/draft-ietf-idr-bgp-ls-segment-routing-ext-08#section-2.3.3 + if len(value) != 4 && len(value) != 16 { + return malformedAttrListErr("Incorrect Source Router ID length") + } + + l.RouterID = value + + return nil +} + +func (l *LsTLVSourceRouterID) Serialize() ([]byte, error) { + return l.LsTLV.Serialize(l.RouterID) +} + +func (l *LsTLVSourceRouterID) String() string { + return fmt.Sprintf("{Source Router ID: %v}", net.IP(l.RouterID)) +} + +func (l *LsTLVSourceRouterID) MarshalJSON() ([]byte, error) { + return json.Marshal(struct { + Type LsTLVType `json:"type"` + RouterID string `json:"source_router_id"` + }{ + Type: l.Type, + RouterID: fmt.Sprintf("%v", net.IP(l.RouterID)), + }) +} + +type LsTLVOpaqueLinkAttr struct { + LsTLV + Attr []byte +} + +func (l *LsTLVOpaqueLinkAttr) DecodeFromBytes(data []byte) error { + value, err := l.LsTLV.DecodeFromBytes(data) + if err != nil { + return err + } + + if l.Type != LS_TLV_OPAQUE_LINK_ATTR { + return malformedAttrListErr("Unexpected TLV type") + } + + l.Attr = value + + return nil +} + +func (l *LsTLVOpaqueLinkAttr) Serialize() ([]byte, error) { + return l.LsTLV.Serialize(l.Attr) +} + +func (l *LsTLVOpaqueLinkAttr) String() string { + return fmt.Sprintf("{Opaque link attribute: %v}", l.Attr) +} + +func (l *LsTLVOpaqueLinkAttr) MarshalJSON() ([]byte, error) { + return json.Marshal(struct { + Type LsTLVType `json:"type"` + Value string `json:"link_opaque_attribute"` + }{ + Type: l.Type, + Value: fmt.Sprintf("%v", l.Attr), + }) +} + +type LsTLVIGPFlags struct { + LsTLV + Flags uint8 +} + +// https://tools.ietf.org/html/rfc7752#section-3.3.3.1 +type LsIGPFlags struct { + Down bool `json:"down"` + NoUnicast bool `json:"no_unicast"` + LocalAddress bool `json:"local_address"` + PropagateNSSA bool `json:"propagate_nssa"` +} + +func (l *LsTLVIGPFlags) Extract() *LsIGPFlags { + return &LsIGPFlags{ + Down: (l.Flags & (1 << 0)) > 0, + NoUnicast: (l.Flags & (1 << 1)) > 0, + LocalAddress: (l.Flags & (1 << 2)) > 0, + PropagateNSSA: (l.Flags & (1 << 3)) > 0, + } +} + +func (l *LsTLVIGPFlags) DecodeFromBytes(data []byte) error { + value, err := l.LsTLV.DecodeFromBytes(data) + if err != nil { + return err + } + + if l.Type != LS_TLV_IGP_FLAGS { + return malformedAttrListErr("Unexpected TLV type") + } + + if l.Length != 1 { + return malformedAttrListErr("Node Flag Bits TLV malformed") + } + + l.Flags = value[0] + + return nil +} + +func (l *LsTLVIGPFlags) Serialize() ([]byte, error) { + return l.LsTLV.Serialize([]byte{l.Flags}) +} + +func (l *LsTLVIGPFlags) String() string { + flags := "XXXXPLND" + + var buf bytes.Buffer + + for i := 0; i < len(flags); i++ { + if l.Flags&(1< 0 { + buf.WriteString(flags[i : i+1]) + } else { + buf.WriteString("*") + } + } + + return fmt.Sprintf("{IGP Flags: %s}", buf.String()) +} + +func (l *LsTLVIGPFlags) MarshalJSON() ([]byte, error) { + return json.Marshal(struct { + Type LsTLVType `json:"type"` + Flags string `json:"igp_flags"` + }{ + Type: l.Type, + Flags: l.String(), + }) +} + +type LsTLVOpaquePrefixAttr struct { + LsTLV + Attr []byte +} + +func (l *LsTLVOpaquePrefixAttr) DecodeFromBytes(data []byte) error { + value, err := l.LsTLV.DecodeFromBytes(data) + if err != nil { + return err + } + + if l.Type != LS_TLV_OPAQUE_PREFIX_ATTR { + return malformedAttrListErr("Unexpected TLV type") + } + + l.Attr = value + + return nil +} + +func (l *LsTLVOpaquePrefixAttr) Serialize() ([]byte, error) { + return l.LsTLV.Serialize(l.Attr) +} + +func (l *LsTLVOpaquePrefixAttr) String() string { + return fmt.Sprintf("{Prefix opaque attribute: %v}", l.Attr) +} + +func (l *LsTLVOpaquePrefixAttr) MarshalJSON() ([]byte, error) { + return json.Marshal(struct { + Type LsTLVType `json:"type"` + Value string `json:"prefix_opaque_attribute"` + }{ + Type: l.Type, + Value: fmt.Sprintf("%v", l.Attr), + }) +} + +type LsTLVNodeDescriptor struct { + LsTLV + SubTLVs []LsTLVInterface +} + +func (l *LsTLVNodeDescriptor) DecodeFromBytes(data []byte) error { + tlv, err := l.LsTLV.DecodeFromBytes(data) + if err != nil { + return err + } + + if l.Type != LS_TLV_LOCAL_NODE_DESC && l.Type != LS_TLV_REMOTE_NODE_DESC { + return malformedAttrListErr("Unexpected TLV type") + } + + // RFC7752, 3.2.1.4 + // There can be at most one instance of each sub-TLV type present in + // any Node Descriptor. The sub-TLVs within a Node Descriptor MUST + // be arranged in ascending order by sub-TLV type. + prevType := uint16(0) + m := make(map[LsTLVType]bool) + + for len(tlv) >= tlvHdrLen { + sub := &LsTLV{} + _, err := sub.DecodeFromBytes(tlv) + if err != nil { + return err + } + + if uint16(sub.Type) < prevType { + return malformedAttrListErr("Incorrect TLV order") + } + if _, ok := m[sub.Type]; ok { + return malformedAttrListErr("Duplicate TLV") + } + prevType = uint16(sub.Type) + m[sub.Type] = true + + var subTLV LsTLVInterface + switch sub.Type { + case LS_TLV_AS: + subTLV = &LsTLVAutonomousSystem{} + case LS_TLV_BGP_LS_ID: + subTLV = &LsTLVBgpLsID{} + case LS_TLV_OSPF_AREA: + subTLV = &LsTLVOspfAreaID{} + case LS_TLV_IGP_ROUTER_ID: + subTLV = &LsTLVIgpRouterID{} + + default: + tlv = tlv[sub.Len():] + l.Length -= uint16(sub.Len()) + continue + } + + if err := subTLV.DecodeFromBytes(tlv); err != nil { + return err + } + l.SubTLVs = append(l.SubTLVs, subTLV) + tlv = tlv[subTLV.Len():] + } + + if _, ok := m[LS_TLV_IGP_ROUTER_ID]; !ok { + return malformedAttrListErr("Required TLV missing") + } + + return nil +} + +func (l *LsTLVNodeDescriptor) Serialize() ([]byte, error) { + buf := []byte{} + for _, tlv := range l.SubTLVs { + ser, err := tlv.Serialize() + if err != nil { + return nil, err + } + + buf = append(buf, ser...) + } + + return l.LsTLV.Serialize(buf) +} + +func (l *LsTLVNodeDescriptor) String() string { + nd := l.Extract() + + return fmt.Sprintf("{ASN: %v, BGP LS ID: %v, OSPF AREA: %v, IGP ROUTER ID: %v}", nd.Asn, nd.BGPLsID, nd.OspfAreaID, nd.IGPRouterID) +} + +func (l *LsTLVNodeDescriptor) MarshalJSON() ([]byte, error) { + return json.Marshal(struct { + Type LsTLVType `json:"type"` + LsNodeDescriptor + }{ + l.Type, + *l.Extract(), + }) +} + +type LsNodeDescriptor struct { + Asn uint32 `json:"asn"` + BGPLsID uint32 `json:"bgp_ls_id"` + OspfAreaID uint32 `json:"ospf_area_id"` + PseudoNode bool `json:"pseudo_node"` + IGPRouterID string `json:"igp_router_id"` +} + +func parseIGPRouterID(id []byte) (string, bool) { + switch len(id) { + // OSPF or OSPFv3 non-pseudonode + case 4: + return net.IP(id).String(), false + + // ISIS non-pseudonode + case 6: + return fmt.Sprintf("%0.2x%0.2x.%0.2x%0.2x.%0.2x%0.2x", id[0], id[1], id[2], id[3], id[4], id[5]), false + + // ISIS pseudonode + case 7: + return fmt.Sprintf("%0.2x%0.2x.%0.2x%0.2x.%0.2x%0.2x-%0.2x", id[0], id[1], id[2], id[3], id[4], id[5], id[6]), true + + // OSPF or OSPFv3 pseudonode + case 8: + return fmt.Sprintf("%v:%v", net.IP(id[:4]).String(), net.IP(id[4:]).String()), true + + default: + return fmt.Sprintf("%v", id), false + } +} + +func (l *LsTLVNodeDescriptor) Extract() *LsNodeDescriptor { + nd := &LsNodeDescriptor{} + + for _, tlv := range l.SubTLVs { + switch v := tlv.(type) { + case *LsTLVAutonomousSystem: + nd.Asn = v.ASN + case *LsTLVBgpLsID: + nd.BGPLsID = v.BGPLsID + case *LsTLVOspfAreaID: + nd.OspfAreaID = v.AreaID + case *LsTLVIgpRouterID: + nd.IGPRouterID, nd.PseudoNode = parseIGPRouterID(v.RouterID) + } + } + + return nd +} + +type LsAddrPrefix struct { + PrefixDefault + Type LsNLRIType + Length uint16 + NLRI LsNLRIInterface +} + +func (l *LsAddrPrefix) AFI() uint16 { + return AFI_LS +} + +func (l *LsAddrPrefix) SAFI() uint8 { + return SAFI_LS +} + +func (l *LsAddrPrefix) Len(...*MarshallingOption) int { + return int(4 + l.Length) +} + +func (l *LsAddrPrefix) DecodeFromBytes(data []byte, options ...*MarshallingOption) error { + if len(data) < 4 { + return malformedAttrListErr("Malformed BGP-LS Address Prefix") + } + + l.Type = LsNLRIType(binary.BigEndian.Uint16(data[:2])) + l.Length = binary.BigEndian.Uint16(data[2:4]) + + switch l.Type { + case LS_NLRI_TYPE_NODE: + node := &LsNodeNLRI{} + node.Length = l.Length + node.NLRIType = LS_NLRI_TYPE_NODE + l.NLRI = node + + case LS_NLRI_TYPE_LINK: + link := &LsLinkNLRI{} + link.Length = l.Length + link.NLRIType = LS_NLRI_TYPE_LINK + l.NLRI = link + + case LS_NLRI_TYPE_PREFIX_IPV4: + prefixv4 := &LsPrefixV4NLRI{} + prefixv4.Length = l.Length + prefixv4.NLRIType = LS_NLRI_TYPE_PREFIX_IPV4 + l.NLRI = prefixv4 + + case LS_NLRI_TYPE_PREFIX_IPV6: + prefixv6 := &LsPrefixV6NLRI{} + prefixv6.Length = l.Length + prefixv6.NLRIType = LS_NLRI_TYPE_PREFIX_IPV4 + l.NLRI = prefixv6 + + default: + return malformedAttrListErr("Unsupported BGP-LS NLRI") + } + + if l.NLRI != nil { + return l.NLRI.DecodeFromBytes(data[4:]) + } + + return nil +} + +func (l *LsAddrPrefix) Serialize(options ...*MarshallingOption) ([]byte, error) { + if l.NLRI == nil { + return nil, fmt.Errorf("empty NLRI") + } + + buf := make([]byte, 4) + binary.BigEndian.PutUint16(buf, uint16(l.Type)) + binary.BigEndian.PutUint16(buf[2:], l.Length) + + ser, err := l.NLRI.Serialize() + if err != nil { + return nil, err + } + + return append(buf, ser...), nil +} + +func (l *LsAddrPrefix) MarshalJSON() ([]byte, error) { + return nil, nil +} + +func (l *LsAddrPrefix) String() string { + if l.NLRI == nil { + return fmt.Sprintf("NLRI: (nil)") + } + + return fmt.Sprintf("NLRI { %v }", l.NLRI.String()) +} + +func (l *LsAddrPrefix) Flat() map[string]string { + return map[string]string{} +} + +type LsAttributeNode struct { + Flags *LsNodeFlags `json:"flags,omitempty"` + Opaque *[]byte `json:"opaque,omitempty"` + Name *string `json:"name,omitempty"` + IsisArea *[]byte `json:"isis_area,omitempty"` + LocalRouterID *net.IP `json:"local_router_id_ipv4,omitempty"` + LocalRouterIDv6 *net.IP `json:"local_router_id_ipv6,omitempty"` + + // Segment Routing + SrCapabilties *LsSrCapabilities `json:"sr_capabilities,omitempty"` + SrAlgorithms *[]byte `json:"sr_algorithms,omitempty"` + SrLocalBlock *LsSrLocalBlock `json:"sr_local_block,omitempty"` +} + +type LsAttributeLink struct { + Name *string `json:"name,omitempty"` + LocalRouterID *net.IP `json:"local_router_id_ipv4,omitempty"` + LocalRouterIDv6 *net.IP `json:"local_router_id_ipv6,omitempty"` + RemoteRouterID *net.IP `json:"remote_router_id_ipv4,omitempty"` + RemoteRouterIDv6 *net.IP `json:"remote_router_id_ipv6,omitempty"` + AdminGroup *uint32 `json:"admin_group,omitempty"` + DefaultTEMetric *uint32 `json:"default_te_metric,omitempty"` + IGPMetric *uint32 `json:"igp_metric,omitempty"` + Opaque *[]byte `json:"opaque,omitempty"` + + // Bandwidth is expressed in bytes (not bits) per second. + Bandwidth *float32 `json:"bandwidth,omitempty"` + ReservableBandwidth *float32 `json:"reservable_bandwidth,omitempty"` + UnreservedBandwidth *[8]float32 `json:"unreserved_bandwidth,omitempty"` + + SrAdjacencySID *uint32 `json:"adjacency_sid,omitempty"` +} + +type LsAttributePrefix struct { + IGPFlags *LsIGPFlags `json:"igp_flags,omitempty"` + Opaque *[]byte `json:"opaque,omitempty"` + + SrPrefixSID *uint32 `json:"sr_prefix_sid,omitempty"` +} + +type LsAttribute struct { + Node LsAttributeNode `json:"node"` + Link LsAttributeLink `json:"link"` + Prefix LsAttributePrefix `json:"prefix"` +} + +type PathAttributeLs struct { + PathAttribute + TLVs []LsTLVInterface +} + +func (p *PathAttributeLs) Extract() *LsAttribute { + l := &LsAttribute{} + + for _, tlv := range p.TLVs { + switch v := tlv.(type) { + case *LsTLVNodeFlagBits: + l.Node.Flags = v.Extract() + + case *LsTLVOpaqueNodeAttr: + l.Node.Opaque = &v.Attr + + case *LsTLVNodeName: + l.Node.Name = &v.Name + + case *LsTLVIsisArea: + l.Node.IsisArea = &v.Area + + case *LsTLVLocalIPv4RouterID: + l.Node.LocalRouterID = &v.IP + l.Link.LocalRouterID = &v.IP + + case *LsTLVLocalIPv6RouterID: + l.Node.LocalRouterIDv6 = &v.IP + l.Link.LocalRouterIDv6 = &v.IP + + case *LsTLVSrCapabilities: + l.Node.SrCapabilties = v.Extract() + + case *LsTLVSrAlgorithm: + l.Node.SrAlgorithms = &v.Algorithm + + case *LsTLVSrLocalBlock: + l.Node.SrLocalBlock = v.Extract() + + case *LsTLVRemoteIPv4RouterID: + l.Link.RemoteRouterID = &v.IP + + case *LsTLVRemoteIPv6RouterID: + l.Link.RemoteRouterIDv6 = &v.IP + + case *LsTLVAdminGroup: + l.Link.AdminGroup = &v.AdminGroup + + case *LsTLVMaxLinkBw: + l.Link.Bandwidth = &v.Bandwidth + + case *LsTLVMaxReservableLinkBw: + l.Link.ReservableBandwidth = &v.Bandwidth + + case *LsTLVUnreservedBw: + l.Link.UnreservedBandwidth = &v.Bandwidth + + case *LsTLVTEDefaultMetric: + l.Link.DefaultTEMetric = &v.Metric + + case *LsTLVIGPMetric: + l.Link.IGPMetric = &v.Metric + + case *LsTLVOpaqueLinkAttr: + l.Link.Opaque = &v.Attr + + case *LsTLVLinkName: + l.Link.Name = &v.Name + + case *LsTLVAdjacencySID: + l.Link.SrAdjacencySID = &v.SID + + case *LsTLVIGPFlags: + l.Prefix.IGPFlags = v.Extract() + + case *LsTLVOpaquePrefixAttr: + l.Prefix.Opaque = &v.Attr + + case *LsTLVPrefixSID: + l.Prefix.SrPrefixSID = &v.SID + } + } + + return l +} + +func (p *PathAttributeLs) DecodeFromBytes(data []byte, options ...*MarshallingOption) error { + tlvs, err := p.PathAttribute.DecodeFromBytes(data) + if err != nil { + return err + } + + for len(tlvs) >= tlvHdrLen { + t := &LsTLV{} + _, err := t.DecodeFromBytes(tlvs) + if err != nil { + return err + } + + var tlv LsTLVInterface + switch t.Type { + // Node NLRI-related TLVs (https://tools.ietf.org/html/rfc7752#section-3.3.1) + case LS_TLV_NODE_FLAG_BITS: + tlv = &LsTLVNodeFlagBits{} + + case LS_TLV_OPAQUE_NODE_ATTR: + tlv = &LsTLVOpaqueNodeAttr{} + + case LS_TLV_NODE_NAME: + tlv = &LsTLVNodeName{} + + case LS_TLV_ISIS_AREA: + tlv = &LsTLVIsisArea{} + + // Used by Link NLRI as well. + case LS_TLV_IPV4_LOCAL_ROUTER_ID: + tlv = &LsTLVLocalIPv4RouterID{} + + // Used by Link NLRI as well. + case LS_TLV_IPV6_LOCAL_ROUTER_ID: + tlv = &LsTLVLocalIPv6RouterID{} + + // SR-related TLVs (draft-ietf-idr-bgp-ls-segment-routing-ext-08) for Node NLRI + case LS_TLV_SR_CAPABILITIES: + tlv = &LsTLVSrCapabilities{} + + case LS_TLV_SR_ALGORITHM: + tlv = &LsTLVSrAlgorithm{} + + case LS_TLV_SR_LOCAL_BLOCK: + tlv = &LsTLVSrLocalBlock{} + + // Link NLRI-related TLVs (https://tools.ietf.org/html/rfc7752#section-3.3.2) + case LS_TLV_IPV4_REMOTE_ROUTER_ID: + tlv = &LsTLVRemoteIPv4RouterID{} + + case LS_TLV_IPV6_REMOTE_ROUTER_ID: + tlv = &LsTLVRemoteIPv6RouterID{} + + case LS_TLV_ADMIN_GROUP: + tlv = &LsTLVAdminGroup{} + + case LS_TLV_MAX_LINK_BANDWIDTH: + tlv = &LsTLVMaxLinkBw{} + + case LS_TLV_MAX_RESERVABLE_BANDWIDTH: + tlv = &LsTLVMaxReservableLinkBw{} + + case LS_TLV_UNRESERVED_BANDWIDTH: + tlv = &LsTLVUnreservedBw{} + + case LS_TLV_TE_DEFAULT_METRIC: + tlv = &LsTLVTEDefaultMetric{} + + case LS_TLV_IGP_METRIC: + tlv = &LsTLVIGPMetric{} + + case LS_TLV_OPAQUE_LINK_ATTR: + tlv = &LsTLVOpaqueLinkAttr{} + + case LS_TLV_LINK_NAME: + tlv = &LsTLVLinkName{} + + // SR-related TLVs (draft-ietf-idr-bgp-ls-segment-routing-ext-08) for Link NLRI + case LS_TLV_ADJACENCY_SID: + tlv = &LsTLVAdjacencySID{} + + // Prefix NLRI-related TLVs (https://tools.ietf.org/html/rfc7752#section-3.3.3) + case LS_TLV_IGP_FLAGS: + tlv = &LsTLVIGPFlags{} + + case LS_TLV_OPAQUE_PREFIX_ATTR: + tlv = &LsTLVOpaquePrefixAttr{} + + // SR-related TLVs (draft-ietf-idr-bgp-ls-segment-routing-ext-08) for Prefix NLRI + case LS_TLV_PREFIX_SID: + tlv = &LsTLVPrefixSID{} + + default: + tlvs = tlvs[t.Len():] + continue + } + + if err := tlv.DecodeFromBytes(tlvs); err != nil { + return err + } + tlvs = tlvs[t.Len():] + + p.TLVs = append(p.TLVs, tlv) + } + + return nil +} + +func (p *PathAttributeLs) Serialize(options ...*MarshallingOption) ([]byte, error) { + buf := []byte{} + + for _, tlv := range p.TLVs { + s, err := tlv.Serialize() + if err != nil { + return nil, err + } + buf = append(buf, s...) + } + + return p.PathAttribute.Serialize(buf, options...) +} + +func (p *PathAttributeLs) String() string { + var buf bytes.Buffer + + for _, tlv := range p.TLVs { + buf.WriteString(fmt.Sprintf("%s ", tlv.String())) + } + + return fmt.Sprintf("{LsAttributes: %s}", buf.String()) +} + +func (p *PathAttributeLs) MarshalJSON() ([]byte, error) { + return json.Marshal(struct { + Type BGPAttrType `json:"type"` + Flags BGPAttrFlag `json:"flags"` + LsAttribute + }{ + p.GetType(), + p.GetFlags(), + *p.Extract(), + }) +} + func AfiSafiToRouteFamily(afi uint16, safi uint8) RouteFamily { return RouteFamily(int(afi)<<16 | int(safi)) } @@ -4750,6 +7956,7 @@ const ( RF_FS_IPv6_VPN RouteFamily = AFI_IP6<<16 | SAFI_FLOW_SPEC_VPN RF_FS_L2_VPN RouteFamily = AFI_L2VPN<<16 | SAFI_FLOW_SPEC_VPN RF_OPAQUE RouteFamily = AFI_OPAQUE<<16 | SAFI_KEY_VALUE + RF_LS RouteFamily = AFI_LS<<16 | SAFI_LS ) var AddressFamilyNameMap = map[RouteFamily]string{ @@ -4774,6 +7981,7 @@ var AddressFamilyNameMap = map[RouteFamily]string{ RF_FS_IPv6_VPN: "l3vpn-ipv6-flowspec", RF_FS_L2_VPN: "l2vpn-flowspec", RF_OPAQUE: "opaque", + RF_LS: "ls", } var AddressFamilyValueMap = map[string]RouteFamily{ @@ -4798,6 +8006,7 @@ var AddressFamilyValueMap = map[string]RouteFamily{ AddressFamilyNameMap[RF_FS_IPv6_VPN]: RF_FS_IPv6_VPN, AddressFamilyNameMap[RF_FS_L2_VPN]: RF_FS_L2_VPN, AddressFamilyNameMap[RF_OPAQUE]: RF_OPAQUE, + AddressFamilyNameMap[RF_LS]: RF_LS, } func GetRouteFamily(name string) (RouteFamily, error) { @@ -4861,6 +8070,8 @@ func NewPrefixFromRouteFamily(afi uint16, safi uint8, prefixStr ...string) (pref prefix = &FlowSpecL2VPN{FlowSpecNLRI{rf: RF_FS_L2_VPN}} case RF_OPAQUE: prefix = &OpaqueNLRI{} + case RF_LS: + prefix = &LsAddrPrefix{} default: err = fmt.Errorf("unknown route family. AFI: %d, SAFI: %d", afi, safi) } @@ -4921,9 +8132,12 @@ const ( BGP_ATTR_TYPE_PMSI_TUNNEL // = 22 BGP_ATTR_TYPE_TUNNEL_ENCAP _ - BGP_ATTR_TYPE_IP6_EXTENDED_COMMUNITIES // = 25 - BGP_ATTR_TYPE_AIGP // = 26 - BGP_ATTR_TYPE_LARGE_COMMUNITY BGPAttrType = 32 + BGP_ATTR_TYPE_IP6_EXTENDED_COMMUNITIES // = 25 + BGP_ATTR_TYPE_AIGP // = 26 + _ + _ + BGP_ATTR_TYPE_LS // = 29 + BGP_ATTR_TYPE_LARGE_COMMUNITY BGPAttrType = 32 ) // NOTIFICATION Error Code RFC 4271 4.5. @@ -5117,6 +8331,7 @@ var PathAttrFlags map[BGPAttrType]BGPAttrFlag = map[BGPAttrType]BGPAttrFlag{ BGP_ATTR_TYPE_IP6_EXTENDED_COMMUNITIES: BGP_ATTR_FLAG_TRANSITIVE | BGP_ATTR_FLAG_OPTIONAL, BGP_ATTR_TYPE_AIGP: BGP_ATTR_FLAG_OPTIONAL, BGP_ATTR_TYPE_LARGE_COMMUNITY: BGP_ATTR_FLAG_TRANSITIVE | BGP_ATTR_FLAG_OPTIONAL, + BGP_ATTR_TYPE_LS: BGP_ATTR_FLAG_OPTIONAL, } // getPathAttrFlags returns BGP Path Attribute flags value from its type and @@ -8999,6 +12214,8 @@ func GetPathAttribute(data []byte) (PathAttributeInterface, error) { return &PathAttributeAigp{}, nil case BGP_ATTR_TYPE_LARGE_COMMUNITY: return &PathAttributeLargeCommunities{}, nil + case BGP_ATTR_TYPE_LS: + return &PathAttributeLs{}, nil } return &PathAttributeUnknown{}, nil } diff --git a/pkg/packet/bgp/bgp_test.go b/pkg/packet/bgp/bgp_test.go index 6a2d5f12..43bf73a0 100644 --- a/pkg/packet/bgp/bgp_test.go +++ b/pkg/packet/bgp/bgp_test.go @@ -1203,3 +1203,1935 @@ func Test_PathAttributeNextHop(t *testing.T) { f("192.0.2.1") f("2001:db8::68") } + +func Test_LsTLVDecode(t *testing.T) { + assert := assert.New(t) + + var tests = []struct { + in []byte + t LsTLVType + l uint16 + v []byte + err bool + }{ + {[]byte{0x01, 0x09, 0x00, 0x1, 0xef}, LS_TLV_IP_REACH_INFO, 5, []byte{0xef}, false}, + {[]byte{0x01, 0x09, 0x00, 0x0}, LS_TLV_IP_REACH_INFO, 4, []byte{}, false}, + {[]byte{0x01, 0x09, 0x01, 0xff}, LS_TLV_IP_REACH_INFO, 0, []byte{}, true}, + {[]byte{0x01, 0x09, 0x01}, LS_TLV_L2_BUNDLE_MEMBER_TLV, 1, []byte{}, true}, + } + + for _, test := range tests { + tlv := &LsTLV{} + + got, err := tlv.DecodeFromBytes(test.in) + if test.err { + assert.Error(err) + continue + } else { + assert.NoError(err) + } + assert.Equal(tlv.Len(), int(test.l)) + assert.Equal(got, test.v) + } +} + +func Test_LsTLVSerialize(t *testing.T) { + assert := assert.New(t) + + var tests = []struct { + tlv LsTLV + val []byte + want []byte + err bool + }{ + {LsTLV{Type: LS_TLV_SID_LABEL_TLV, Length: 2}, []byte{0x11, 0x22}, []byte{0x04, 0x89, 0x00, 0x02, 0x11, 0x22}, false}, + {LsTLV{Type: LS_TLV_SID_LABEL_TLV, Length: 2}, []byte{0x11}, nil, true}, + {LsTLV{Type: LS_TLV_IGP_FLAGS, Length: 0}, []byte{}, []byte{0x04, 0x80, 0x00, 0x00}, false}, + } + + for _, test := range tests { + got, err := test.tlv.Serialize(test.val) + if test.err { + assert.Error(err) + } else { + assert.NoError(err) + } + + assert.Equal(got, test.want) + } +} + +func Test_LsTLVLinkID(t *testing.T) { + assert := assert.New(t) + + var tests = []struct { + in []byte + want string + serialize bool + err bool + }{ + {[]byte{0x01, 0x02, 0x00, 0x08, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x02}, `{"type":258,"local_link_id":1,"remote_link_id":2}`, true, false}, + {[]byte{0x01, 0x02, 0x00, 0x08, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x02, 0xFF}, `{"type":258,"local_link_id":1,"remote_link_id":2}`, false, false}, + {[]byte{0x01, 0x02, 0x00, 0x07, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00}, "", false, true}, + {[]byte{0xfe, 0xfe, 0x00, 0x00}, "", false, true}, + } + + for _, test := range tests { + tlv := LsTLVLinkID{} + if test.err { + assert.Error(tlv.DecodeFromBytes(test.in)) + continue + } else { + assert.NoError(tlv.DecodeFromBytes(test.in)) + } + + got, err := tlv.MarshalJSON() + assert.NoError(err) + assert.Equal(got, []byte(test.want)) + + if test.serialize { + s, err := tlv.Serialize() + assert.NoError(err) + assert.Equal(test.in, s) + } + } +} + +func Test_LsTLVIPv4InterfaceAddr(t *testing.T) { + assert := assert.New(t) + + var tests = []struct { + in []byte + want string + serialize bool + err bool + }{ + {[]byte{0x01, 0x03, 0x00, 0x04, 0x01, 0x01, 0x01, 0x01}, `{"type":259,"ipv4_interface_address":"1.1.1.1"}`, true, false}, + {[]byte{0x01, 0x03, 0x00, 0x04, 0x0a, 0x0a, 0x0a, 0x0a, 0x12}, `{"type":259,"ipv4_interface_address":"10.10.10.10"}`, false, false}, + {[]byte{0x01, 0x03, 0x00, 0x03, 0x00, 0x00, 0x00}, "", false, true}, + {[]byte{0xfe, 0xfe, 0x00, 0x00}, "", false, true}, + } + + for _, test := range tests { + tlv := LsTLVIPv4InterfaceAddr{} + if test.err { + assert.Error(tlv.DecodeFromBytes(test.in)) + continue + } else { + assert.NoError(tlv.DecodeFromBytes(test.in)) + } + + got, err := tlv.MarshalJSON() + assert.NoError(err) + assert.Equal(got, []byte(test.want)) + + if test.serialize { + s, err := tlv.Serialize() + assert.NoError(err) + assert.Equal(test.in, s) + } + } +} + +func Test_LsTLVIPv4NeighborAddr(t *testing.T) { + assert := assert.New(t) + + var tests = []struct { + in []byte + want string + serialize bool + err bool + }{ + {[]byte{0x01, 0x04, 0x00, 0x04, 0x01, 0x01, 0x01, 0x01}, `{"type":260,"ipv4_neighbor_address":"1.1.1.1"}`, true, false}, + {[]byte{0x01, 0x04, 0x00, 0x04, 0x0a, 0x0a, 0x0a, 0x0a, 0x12}, `{"type":260,"ipv4_neighbor_address":"10.10.10.10"}`, false, false}, + {[]byte{0x01, 0x04, 0x00, 0x03, 0x00, 0x00, 0x00}, "", false, true}, + {[]byte{0xfe, 0xfe, 0x00, 0x00}, "", false, true}, + } + + for _, test := range tests { + tlv := LsTLVIPv4NeighborAddr{} + if test.err { + assert.Error(tlv.DecodeFromBytes(test.in)) + continue + } else { + assert.NoError(tlv.DecodeFromBytes(test.in)) + } + + got, err := tlv.MarshalJSON() + assert.NoError(err) + assert.Equal(got, []byte(test.want)) + + if test.serialize { + s, err := tlv.Serialize() + assert.NoError(err) + assert.Equal(test.in, s) + } + } +} + +func Test_LsTLVIPv6InterfaceAddr(t *testing.T) { + assert := assert.New(t) + + var tests = []struct { + in []byte + want string + serialize bool + err bool + }{ + {[]byte{0x01, 0x05, 0x00, 0x10, 0x20, 0x01, 0x0d, 0xb8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xBE, 0xEF}, `{"type":261,"ipv6_interface_address":"2001:db8::beef"}`, true, false}, + {[]byte{0x01, 0x05, 0x00, 0x10, 0x20, 0x01, 0x0d, 0xb8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xBE, 0xEF, 0xFF}, `{"type":261,"ipv6_interface_address":"2001:db8::beef"}`, false, false}, + {[]byte{0x01, 0x05, 0x00, 0x10, 0xfe, 0x80, 0x0d, 0xb8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xBE, 0xEF}, "", false, true}, + {[]byte{0x01, 0x05, 0x00, 0x03, 0x00, 0x00, 0x00}, "", false, true}, + {[]byte{0xfe, 0xfe, 0x00, 0x00}, "", false, true}, + } + + for _, test := range tests { + tlv := LsTLVIPv6InterfaceAddr{} + if test.err { + assert.Error(tlv.DecodeFromBytes(test.in)) + continue + } else { + assert.NoError(tlv.DecodeFromBytes(test.in)) + } + + got, err := tlv.MarshalJSON() + assert.NoError(err) + assert.Equal(got, []byte(test.want)) + + if test.serialize { + s, err := tlv.Serialize() + assert.NoError(err) + assert.Equal(test.in, s) + } + } +} + +func Test_LsTLVIPv6NeighborAddr(t *testing.T) { + assert := assert.New(t) + + var tests = []struct { + in []byte + want string + serialize bool + err bool + }{ + {[]byte{0x01, 0x06, 0x00, 0x10, 0x20, 0x01, 0x0d, 0xb8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xBE, 0xEF}, `{"type":262,"ipv6_neighbor_address":"2001:db8::beef"}`, true, false}, + {[]byte{0x01, 0x06, 0x00, 0x10, 0x20, 0x01, 0x0d, 0xb8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xBE, 0xEF, 0xFF}, `{"type":262,"ipv6_neighbor_address":"2001:db8::beef"}`, false, false}, + {[]byte{0x01, 0x06, 0x00, 0x10, 0xfe, 0x81, 0x0d, 0xb8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xBE, 0xEF}, "", false, true}, + {[]byte{0x01, 0x06, 0x00, 0x03, 0x00, 0x00, 0x00}, "", false, true}, + {[]byte{0xfe, 0xfe, 0x00, 0x00}, "", false, true}, + } + + for _, test := range tests { + tlv := LsTLVIPv6NeighborAddr{} + if test.err { + assert.Error(tlv.DecodeFromBytes(test.in)) + continue + } else { + assert.NoError(tlv.DecodeFromBytes(test.in)) + } + + got, err := tlv.MarshalJSON() + assert.NoError(err) + assert.Equal(got, []byte(test.want)) + + if test.serialize { + s, err := tlv.Serialize() + assert.NoError(err) + assert.Equal(test.in, s) + } + } +} + +func Test_LsTLVNodeFlagBits(t *testing.T) { + assert := assert.New(t) + + var tests = []struct { + in []byte + want string + err bool + }{ + {[]byte{0x04, 0x00, 0x00, 0x01, 0xFF}, `{"type":1024,"node_flags":"{Node Flags: XXVRBETO}"}`, false}, + {[]byte{0x04, 0x00, 0x00, 0x01, 0x80}, `{"type":1024,"node_flags":"{Node Flags: *******O}"}`, false}, + {[]byte{0x04, 0x00, 0x00, 0x01, 0x80, 0xAA}, `{"type":1024,"node_flags":"{Node Flags: *******O}"}`, false}, + {[]byte{0x04, 0x00, 0x00, 0x02, 0x80, 0x44}, "", true}, + {[]byte{0xfe, 0xfe, 0x00, 0x00}, "", true}, + } + + for _, test := range tests { + tlv := LsTLVNodeFlagBits{} + if test.err { + assert.Error(tlv.DecodeFromBytes(test.in)) + continue + } else { + assert.NoError(tlv.DecodeFromBytes(test.in)) + } + + got, err := tlv.MarshalJSON() + assert.NoError(err) + assert.Equal(got, []byte(test.want)) + } +} + +func Test_LsTLVNodeName(t *testing.T) { + assert := assert.New(t) + + var tests = []struct { + in []byte + want string + err bool + }{ + {[]byte{0x04, 0x02, 0x00, 0x03, 0x72, 0x74, 0x72}, `{"type":1026,"node_name":"rtr"}`, false}, + {[]byte{0x04, 0x02, 0x00, 0x03, 0x72, 0x74, 0x72, 0x00}, `{"type":1026,"node_name":"rtr"}`, false}, + {[]byte{0x04, 0x02, 0x00, 0x00}, "", true}, + {[]byte{0xfe, 0xfe, 0x00, 0x00}, "", true}, + } + + for _, test := range tests { + tlv := LsTLVNodeName{} + if test.err { + assert.Error(tlv.DecodeFromBytes(test.in)) + continue + } else { + assert.NoError(tlv.DecodeFromBytes(test.in)) + } + + got, err := tlv.MarshalJSON() + assert.NoError(err) + assert.Equal(got, []byte(test.want)) + } +} + +func Test_LsTLVIsisArea(t *testing.T) { + assert := assert.New(t) + + var tests = []struct { + in []byte + want string + err bool + }{ + {[]byte{0x04, 0x03, 0x00, 0x03, 0x72, 0x74, 0x72}, `{"type":1027,"isis_area_id":"[114 116 114]"}`, false}, + {[]byte{0x04, 0x03, 0x00, 0x03, 0x72, 0x74, 0x72, 0x44}, `{"type":1027,"isis_area_id":"[114 116 114]"}`, false}, + {[]byte{0x04, 0x03, 0x00, 0x00}, "", true}, + {[]byte{0x04, 0x03, 0x00, 0x0E, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01}, "", true}, + {[]byte{0xfe, 0xfe, 0x00, 0x00}, "", true}, + } + + for _, test := range tests { + tlv := LsTLVIsisArea{} + if test.err { + assert.Error(tlv.DecodeFromBytes(test.in)) + continue + } else { + assert.NoError(tlv.DecodeFromBytes(test.in)) + } + + got, err := tlv.MarshalJSON() + assert.NoError(err) + assert.Equal(got, []byte(test.want)) + } +} + +func Test_LsTLVLocalIPv4RouterID(t *testing.T) { + assert := assert.New(t) + + var tests = []struct { + in []byte + want string + err bool + }{ + {[]byte{0x04, 0x04, 0x00, 0x04, 0x01, 0x01, 0x01, 0x01}, `{"type":1028,"node_local_router_id_ipv4":"1.1.1.1"}`, false}, + {[]byte{0x04, 0x04, 0x00, 0x04, 0x01, 0x01, 0x01, 0x01, 0x12}, `{"type":1028,"node_local_router_id_ipv4":"1.1.1.1"}`, false}, + {[]byte{0x04, 0x04, 0x00, 0x03, 0x00, 0x00, 0x00}, "", true}, + {[]byte{0xfe, 0xfe, 0x00, 0x00}, "", true}, + } + + for _, test := range tests { + tlv := LsTLVLocalIPv4RouterID{} + if test.err { + assert.Error(tlv.DecodeFromBytes(test.in)) + continue + } else { + assert.NoError(tlv.DecodeFromBytes(test.in)) + } + + got, err := tlv.MarshalJSON() + assert.NoError(err) + assert.Equal(got, []byte(test.want)) + } +} + +func Test_LsTLVRemoteIPv4RouterID(t *testing.T) { + assert := assert.New(t) + + var tests = []struct { + in []byte + want string + err bool + }{ + {[]byte{0x04, 0x06, 0x00, 0x04, 0x02, 0x02, 0x02, 0x02}, `{"type":1030,"node_remote_router_id_ipv4":"2.2.2.2"}`, false}, + {[]byte{0x04, 0x06, 0x00, 0x04, 0x02, 0x02, 0x02, 0x02, 0x44}, `{"type":1030,"node_remote_router_id_ipv4":"2.2.2.2"}`, false}, + {[]byte{0x04, 0x06, 0x00, 0x03, 0x00, 0x00, 0x00}, "", true}, + {[]byte{0xfe, 0xfe, 0x00, 0x00}, "", true}, + } + + for _, test := range tests { + tlv := LsTLVRemoteIPv4RouterID{} + if test.err { + assert.Error(tlv.DecodeFromBytes(test.in)) + continue + } else { + assert.NoError(tlv.DecodeFromBytes(test.in)) + } + + got, err := tlv.MarshalJSON() + assert.NoError(err) + assert.Equal(got, []byte(test.want)) + } +} + +func Test_LsTLVLocalIPv6RouterID(t *testing.T) { + assert := assert.New(t) + + var tests = []struct { + in []byte + want string + err bool + }{ + {[]byte{0x04, 0x05, 0x00, 0x10, 0x20, 0x01, 0x0d, 0xb8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xBE, 0xEF}, `{"type":1029,"node_local_router_id_ipv6":"2001:db8::beef"}`, false}, + {[]byte{0x04, 0x05, 0x00, 0x10, 0x20, 0x01, 0x0d, 0xb8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xBE, 0xEF, 0xFF}, `{"type":1029,"node_local_router_id_ipv6":"2001:db8::beef"}`, false}, + {[]byte{0x04, 0x05, 0x00, 0x01, 0x00}, "", true}, + {[]byte{0xfe, 0xfe, 0x00, 0x00}, "", true}, + } + + for _, test := range tests { + tlv := LsTLVLocalIPv6RouterID{} + if test.err { + assert.Error(tlv.DecodeFromBytes(test.in)) + continue + } else { + assert.NoError(tlv.DecodeFromBytes(test.in)) + } + + got, err := tlv.MarshalJSON() + assert.NoError(err) + assert.Equal(got, []byte(test.want)) + } +} + +func Test_LsTLVRemoteIPv6RouterID(t *testing.T) { + assert := assert.New(t) + + var tests = []struct { + in []byte + want string + err bool + }{ + {[]byte{0x04, 0x07, 0x00, 0x10, 0x20, 0x01, 0x0d, 0xb8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xBE, 0xEF}, `{"type":1031,"node_remote_router_id_ipv6":"2001:db8::beef"}`, false}, + {[]byte{0x04, 0x07, 0x00, 0x10, 0x20, 0x01, 0x0d, 0xb8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xBE, 0xEF, 0xFF}, `{"type":1031,"node_remote_router_id_ipv6":"2001:db8::beef"}`, false}, + {[]byte{0x04, 0x07, 0x00, 0x01, 0x00}, "", true}, + {[]byte{0xfe, 0xfe, 0x00, 0x00}, "", true}, + } + + for _, test := range tests { + tlv := LsTLVRemoteIPv6RouterID{} + if test.err { + assert.Error(tlv.DecodeFromBytes(test.in)) + continue + } else { + assert.NoError(tlv.DecodeFromBytes(test.in)) + } + + got, err := tlv.MarshalJSON() + assert.NoError(err) + assert.Equal(got, []byte(test.want)) + } +} + +func Test_LsTLVOpaqueNodeAttr(t *testing.T) { + assert := assert.New(t) + + var tests = []struct { + in []byte + want string + err bool + }{ + {[]byte{0x04, 0x01, 0x00, 0x03, 0x01, 0x02, 0x03}, `{"type":1025,"node_opaque_attribute":"[1 2 3]"}`, false}, + {[]byte{0x04, 0x01, 0x00, 0x03, 0x01, 0x02, 0x03, 0x04}, `{"type":1025,"node_opaque_attribute":"[1 2 3]"}`, false}, + {[]byte{0xfe, 0xfe, 0x00, 0x00}, "", true}, + } + + for _, test := range tests { + tlv := LsTLVOpaqueNodeAttr{} + if test.err { + assert.Error(tlv.DecodeFromBytes(test.in)) + continue + } else { + assert.NoError(tlv.DecodeFromBytes(test.in)) + } + + got, err := tlv.MarshalJSON() + assert.NoError(err) + assert.Equal(got, []byte(test.want)) + } +} + +func Test_LsTLVAutonomousSystem(t *testing.T) { + assert := assert.New(t) + + var tests = []struct { + in []byte + want string + err bool + }{ + {[]byte{0x02, 0x00, 0x00, 0x04, 0x07, 0x07, 0x07, 0x07}, `{"type":512,"asn":117901063}`, false}, + {[]byte{0x02, 0x00, 0x00, 0x04, 0x07, 0x07, 0x07, 0x07, 0xFF}, `{"type":512,"asn":117901063}`, false}, + {[]byte{0x02, 0x00, 0x00, 0x03, 0x07, 0x07, 0x07}, "", true}, + {[]byte{0xfe, 0xfe, 0x00, 0x00}, "", true}, + } + + for _, test := range tests { + tlv := LsTLVAutonomousSystem{} + if test.err { + assert.Error(tlv.DecodeFromBytes(test.in)) + continue + } else { + assert.NoError(tlv.DecodeFromBytes(test.in)) + } + + got, err := tlv.MarshalJSON() + assert.NoError(err) + assert.Equal(got, []byte(test.want)) + } +} + +func Test_LsTLVBgpLsID(t *testing.T) { + assert := assert.New(t) + + var tests = []struct { + in []byte + want string + err bool + }{ + {[]byte{0x02, 0x01, 0x00, 0x04, 0x07, 0x07, 0x07, 0x07}, `{"type":513,"bgp_ls_id":117901063}`, false}, + {[]byte{0x02, 0x01, 0x00, 0x04, 0x07, 0x07, 0x07, 0x07, 0xFF}, `{"type":513,"bgp_ls_id":117901063}`, false}, + {[]byte{0x02, 0x01, 0x00, 0x03, 0x07, 0x07, 0x07}, "", true}, + {[]byte{0xfe, 0xfe, 0x00, 0x00}, "", true}, + } + + for _, test := range tests { + tlv := LsTLVBgpLsID{} + if test.err { + assert.Error(tlv.DecodeFromBytes(test.in)) + continue + } else { + assert.NoError(tlv.DecodeFromBytes(test.in)) + } + + got, err := tlv.MarshalJSON() + assert.NoError(err) + assert.Equal(got, []byte(test.want)) + } +} + +func Test_LsTLVIgpRouterID(t *testing.T) { + assert := assert.New(t) + + var tests = []struct { + in []byte + want string + err bool + }{ + {[]byte{0x02, 0x03, 0x00, 0x06, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06}, `{"type":515,"igp_router_id":"[1 2 3 4 5 6]"}`, false}, + {[]byte{0x02, 0x03, 0x00, 0x07, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07}, `{"type":515,"igp_router_id":"[1 2 3 4 5 6 7]"}`, false}, + {[]byte{0x02, 0x03, 0x00, 0x08, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08}, `{"type":515,"igp_router_id":"[1 2 3 4 5 6 7 8]"}`, false}, + {[]byte{0x02, 0x03, 0x00, 0x05, 0x01, 0x02, 0x03, 0x04, 0x05}, "", true}, + {[]byte{0xfe, 0xfe, 0x00, 0x00}, "", true}, + } + + for _, test := range tests { + tlv := LsTLVIgpRouterID{} + if test.err { + assert.Error(tlv.DecodeFromBytes(test.in)) + continue + } else { + assert.NoError(tlv.DecodeFromBytes(test.in)) + } + + got, err := tlv.MarshalJSON() + assert.NoError(err) + assert.Equal(got, []byte(test.want)) + } +} + +func Test_LsTLVOspfAreaID(t *testing.T) { + assert := assert.New(t) + + var tests = []struct { + in []byte + want string + err bool + }{ + {[]byte{0x02, 0x02, 0x00, 0x04, 0x07, 0x07, 0x07, 0x07}, `{"type":514,"ospf_area_id":117901063}`, false}, + {[]byte{0x02, 0x02, 0x00, 0x04, 0x07, 0x07, 0x07, 0x07, 0xFF}, `{"type":514,"ospf_area_id":117901063}`, false}, + {[]byte{0x02, 0x02, 0x00, 0x03, 0x07, 0x07, 0x07}, "", true}, + {[]byte{0xfe, 0xfe, 0x00, 0x00}, "", true}, + } + + for _, test := range tests { + tlv := LsTLVOspfAreaID{} + if test.err { + assert.Error(tlv.DecodeFromBytes(test.in)) + continue + } else { + assert.NoError(tlv.DecodeFromBytes(test.in)) + } + + got, err := tlv.MarshalJSON() + assert.NoError(err) + assert.Equal(got, []byte(test.want)) + } +} + +func Test_LsTLVOspfRouteType(t *testing.T) { + assert := assert.New(t) + + var tests = []struct { + in []byte + want string + err bool + }{ + {[]byte{0x01, 0x08, 0x00, 0x01, 0x06}, `{"type":264,"ospf_route_type":"NSSA2"}`, false}, + {[]byte{0x01, 0x08, 0x00, 0x01, 0x01, 0xFF}, `{"type":264,"ospf_route_type":"INTRA-AREA"}`, false}, + {[]byte{0x01, 0x08, 0x00, 0x02, 0x01, 0x01}, "", true}, + {[]byte{0xfe, 0xfe, 0x00, 0x00}, "", true}, + } + + for _, test := range tests { + tlv := LsTLVOspfRouteType{} + if test.err { + assert.Error(tlv.DecodeFromBytes(test.in)) + continue + } else { + assert.NoError(tlv.DecodeFromBytes(test.in)) + } + + got, err := tlv.MarshalJSON() + assert.NoError(err) + assert.Equal(got, []byte(test.want)) + } +} + +func Test_LsTLVIPReachability(t *testing.T) { + assert := assert.New(t) + + var tests = []struct { + in []byte + want string + serialize bool + err bool + }{ + {[]byte{0x01, 0x09, 0x00, 0x02, 0x08, 0x0a}, `{"type":265,"prefix_length":8,"prefix":"[10]"}`, true, false}, + {[]byte{0x01, 0x09, 0x00, 0x03, 0x10, 0x0a, 0x0b, 0xFF}, `{"type":265,"prefix_length":16,"prefix":"[10 11]"}`, false, false}, + {[]byte{0x01, 0x09, 0x00, 0x02, 0x08}, ``, false, true}, + {[]byte{0x01, 0x09, 0x00, 0x01, 0x01}, "", false, true}, + {[]byte{0xfe, 0xfe, 0x00, 0x00}, "", false, true}, + } + + for _, test := range tests { + tlv := LsTLVIPReachability{} + if test.err { + assert.Error(tlv.DecodeFromBytes(test.in)) + continue + } else { + assert.NoError(tlv.DecodeFromBytes(test.in)) + } + + got, err := tlv.MarshalJSON() + assert.NoError(err) + assert.Equal(got, []byte(test.want)) + } +} + +func Test_LsTLVIPReachabilityToIPNet(t *testing.T) { + assert := assert.New(t) + + var tests = []struct { + tlv LsTLVIPReachability + ipv6 bool + want net.IPNet + }{ + { + tlv: LsTLVIPReachability{ + PrefixLength: 8, + Prefix: []byte{0x0a}, + }, + ipv6: false, + want: net.IPNet{ + IP: net.IPv4(10, 0, 0, 0), + Mask: net.CIDRMask(8, 32), + }, + }, + { + tlv: LsTLVIPReachability{ + PrefixLength: 4, + Prefix: []byte{0xaa}, + }, + ipv6: false, + want: net.IPNet{ + IP: net.IPv4(160, 0, 0, 0), + Mask: net.CIDRMask(4, 32), + }, + }, + { + tlv: LsTLVIPReachability{ + PrefixLength: 31, + Prefix: []byte{0x0a, 0x0a, 0x0a, 0xfe}, + }, + ipv6: false, + want: net.IPNet{ + IP: net.IPv4(10, 10, 10, 254), + Mask: net.CIDRMask(31, 32), + }, + }, + { + tlv: LsTLVIPReachability{ + PrefixLength: 16, + Prefix: []byte{0x20, 0x01}, + }, + ipv6: true, + want: net.IPNet{ + IP: net.ParseIP("2001::"), + Mask: net.CIDRMask(16, 128), + }, + }, + { + tlv: LsTLVIPReachability{ + PrefixLength: 24, + Prefix: []byte{0x20, 0x01, 0x0d}, + }, + ipv6: true, + want: net.IPNet{ + IP: net.ParseIP("2001:d00::"), + Mask: net.CIDRMask(24, 128), + }, + }, + } + + for _, test := range tests { + got := test.tlv.ToIPNet(test.ipv6) + assert.Equal(test.want.IP.String(), got.IP.String()) + assert.Equal(test.want.Mask.String(), got.Mask.String()) + } +} + +func Test_LsTLVAdminGroup(t *testing.T) { + assert := assert.New(t) + + var tests = []struct { + in []byte + want string + err bool + }{ + {[]byte{0x04, 0x40, 0x00, 0x04, 0x07, 0x07, 0x07, 0x07}, `{"type":1088,"admin_group":"07070707"}`, false}, + {[]byte{0x04, 0x40, 0x00, 0x04, 0xAE, 0xAE, 0xAE, 0xAE, 0xFF}, `{"type":1088,"admin_group":"aeaeaeae"}`, false}, + {[]byte{0x04, 0x40, 0x00, 0x03, 0x07, 0x07, 0x07}, "", true}, + {[]byte{0xfe, 0xfe, 0x00, 0x00}, "", true}, + } + + for _, test := range tests { + tlv := LsTLVAdminGroup{} + if test.err { + assert.Error(tlv.DecodeFromBytes(test.in)) + continue + } else { + assert.NoError(tlv.DecodeFromBytes(test.in)) + } + + got, err := tlv.MarshalJSON() + assert.NoError(err) + assert.Equal(got, []byte(test.want)) + } +} + +func Test_LsTLVMaxLinkBw(t *testing.T) { + assert := assert.New(t) + + var tests = []struct { + in []byte + want string + err bool + }{ + {[]byte{0x04, 0x41, 0x00, 0x04, 0x43, 0xA4, 0xB2, 0x00}, `{"type":1089,"max_link_bw":329.39062}`, false}, + {[]byte{0x04, 0x41, 0x00, 0x04, 0x43, 0xA4, 0xB2, 0x00, 0xFF}, `{"type":1089,"max_link_bw":329.39062}`, false}, + {[]byte{0x04, 0x41, 0x00, 0x03, 0x07, 0x07, 0x07}, "", true}, + {[]byte{0x04, 0x41, 0x00, 0x04, 0x7f, 0x80, 0x00, 0x00}, "", true}, // +Inf + {[]byte{0x04, 0x41, 0x00, 0x04, 0xff, 0x80, 0x00, 0x00}, "", true}, // -Inf + {[]byte{0x04, 0x41, 0x00, 0x04, 0xff, 0xbf, 0xff, 0xff}, "", true}, // NaN + {[]byte{0x04, 0x41, 0x00, 0x04, 0xc2, 0xc8, 0x00, 0x00}, "", true}, // -100 + {[]byte{0xfe, 0xfe, 0x00, 0x00}, "", true}, + } + + for _, test := range tests { + tlv := LsTLVMaxLinkBw{} + if test.err { + assert.Error(tlv.DecodeFromBytes(test.in)) + continue + } else { + assert.NoError(tlv.DecodeFromBytes(test.in)) + } + + got, err := tlv.MarshalJSON() + assert.NoError(err) + assert.Equal(got, []byte(test.want)) + } +} + +func Test_LsTLVMaxReservableLinkBw(t *testing.T) { + assert := assert.New(t) + + var tests = []struct { + in []byte + want string + err bool + }{ + {[]byte{0x04, 0x42, 0x00, 0x04, 0x43, 0xA4, 0xB2, 0x00}, `{"type":1090,"max_reservable_link_bw":329.39062}`, false}, + {[]byte{0x04, 0x42, 0x00, 0x04, 0x43, 0xA4, 0xB2, 0x00, 0xFF}, `{"type":1090,"max_reservable_link_bw":329.39062}`, false}, + {[]byte{0x04, 0x42, 0x00, 0x03, 0x07, 0x07, 0x07}, "", true}, + {[]byte{0x04, 0x42, 0x00, 0x04, 0x7f, 0x80, 0x00, 0x00}, "", true}, // +Inf + {[]byte{0x04, 0x42, 0x00, 0x04, 0xff, 0x80, 0x00, 0x00}, "", true}, // -Inf + {[]byte{0x04, 0x42, 0x00, 0x04, 0xff, 0xbf, 0xff, 0xff}, "", true}, // NaN + {[]byte{0x04, 0x42, 0x00, 0x04, 0xc2, 0xc8, 0x00, 0x00}, "", true}, // -100 + {[]byte{0xfe, 0xfe, 0x00, 0x00}, "", true}, + } + + for _, test := range tests { + tlv := LsTLVMaxReservableLinkBw{} + if test.err { + assert.Error(tlv.DecodeFromBytes(test.in)) + continue + } else { + assert.NoError(tlv.DecodeFromBytes(test.in)) + } + + got, err := tlv.MarshalJSON() + assert.NoError(err) + assert.Equal(got, []byte(test.want)) + } +} + +func Test_LsTLVUnreservedBw(t *testing.T) { + assert := assert.New(t) + + var tests = []struct { + in []byte + want string + err bool + }{ + {[]byte{0x04, 0x43, 0x00, 0x20, + 0x43, 0xA4, 0xB2, 0x00, + 0x43, 0xA4, 0xB2, 0x00, + 0x43, 0xA4, 0xB2, 0x00, + 0x43, 0xA4, 0xB2, 0x00, + 0x43, 0xA4, 0xB2, 0x00, + 0x43, 0xA4, 0xB2, 0x00, + 0x43, 0xA4, 0xB2, 0x00, + 0x43, 0xA4, 0xB3, 0x00}, + `{"type":1091,"unreserved_bw":[329.39062,329.39062,329.39062,329.39062,329.39062,329.39062,329.39062,329.39844]}`, false}, + {[]byte{0x04, 0x43, 0x00, 0x20, + 0x43, 0xA4, 0xB2, 0x00, + 0x43, 0xA4, 0xB2, 0x00, + 0x43, 0xA4, 0xB2, 0x00, + 0x43, 0xA4, 0xB2, 0x00, + 0x43, 0xA4, 0xB2, 0x00, + 0x43, 0xA4, 0xB2, 0x00, + 0x43, 0xA4, 0xB2, 0x00, + 0x43, 0xA4, 0xB2, 0x00, 0xff}, + `{"type":1091,"unreserved_bw":[329.39062,329.39062,329.39062,329.39062,329.39062,329.39062,329.39062,329.39062]}`, false}, + {[]byte{0x04, 0x43, 0x00, 0x20, + 0x7f, 0x80, 0x00, 0x00, + 0x43, 0xA4, 0xB2, 0x00, + 0x43, 0xA4, 0xB2, 0x00, + 0x43, 0xA4, 0xB2, 0x00, + 0x43, 0xA4, 0xB2, 0x00, + 0x43, 0xA4, 0xB2, 0x00, + 0x43, 0xA4, 0xB2, 0x00, + 0x43, 0xA4, 0xB3, 0x00}, + "", true}, + {[]byte{0x04, 0x43, 0x00, 0x20, + 0xff, 0x80, 0x00, 0x00, + 0x43, 0xA4, 0xB2, 0x00, + 0x43, 0xA4, 0xB2, 0x00, + 0x43, 0xA4, 0xB2, 0x00, + 0x43, 0xA4, 0xB2, 0x00, + 0x43, 0xA4, 0xB2, 0x00, + 0x43, 0xA4, 0xB2, 0x00, + 0x43, 0xA4, 0xB3, 0x00}, + "", true}, + {[]byte{0x04, 0x43, 0x00, 0x20, + 0x43, 0xA4, 0xB3, 0x00, + 0x43, 0xA4, 0xB2, 0x00, + 0x43, 0xA4, 0xB2, 0x00, + 0xff, 0xbf, 0xff, 0xff, + 0x43, 0xA4, 0xB2, 0x00, + 0x43, 0xA4, 0xB2, 0x00, + 0x43, 0xA4, 0xB2, 0x00, + 0x43, 0xA4, 0xB3, 0x00}, + "", true}, + {[]byte{0x04, 0x43, 0x00, 0x20, + 0x43, 0xA4, 0xB3, 0x00, + 0x43, 0xA4, 0xB2, 0x00, + 0x43, 0xA4, 0xB2, 0x00, + 0x43, 0xA4, 0xB3, 0x00, + 0x43, 0xA4, 0xB2, 0x00, + 0x43, 0xA4, 0xB2, 0x00, + 0x43, 0xA4, 0xB2, 0x00, + 0xc2, 0xc8, 0x00, 0x00}, + "", true}, + {[]byte{0x04, 0x43, 0x00, 0x03, 0x07, 0x07, 0x07}, "", true}, + {[]byte{0xfe, 0xfe, 0x00, 0x00}, "", true}, + } + + for _, test := range tests { + tlv := LsTLVUnreservedBw{} + if test.err { + assert.Error(tlv.DecodeFromBytes(test.in)) + continue + } else { + assert.NoError(tlv.DecodeFromBytes(test.in)) + } + + got, err := tlv.MarshalJSON() + assert.NoError(err) + assert.Equal(got, []byte(test.want)) + } +} + +func Test_LsTLVTEDefaultMetric(t *testing.T) { + assert := assert.New(t) + + var tests = []struct { + in []byte + want string + serialize bool + err bool + }{ + {[]byte{0x04, 0x44, 0x00, 0x04, 0x07, 0x07, 0x07, 0x07}, `{"type":1092,"te_default_metric":117901063}`, true, false}, + {[]byte{0x04, 0x44, 0x00, 0x04, 0x07, 0x07, 0x07, 0x07, 0xFF}, `{"type":1092,"te_default_metric":117901063}`, false, false}, + {[]byte{0x04, 0x44, 0x00, 0x03, 0x07, 0x07, 0x07}, "", false, true}, + {[]byte{0xfe, 0xfe, 0x00, 0x00}, "", false, true}, + } + + for _, test := range tests { + tlv := LsTLVTEDefaultMetric{} + if test.err { + assert.Error(tlv.DecodeFromBytes(test.in)) + continue + } else { + assert.NoError(tlv.DecodeFromBytes(test.in)) + } + + got, err := tlv.MarshalJSON() + assert.NoError(err) + assert.Equal(got, []byte(test.want)) + + if test.serialize { + got, err := tlv.Serialize() + assert.NoError(err) + assert.Equal(test.in, got) + } + } +} + +func Test_LsTLVIGPMetric(t *testing.T) { + assert := assert.New(t) + + var tests = []struct { + in []byte + want string + serialize bool + err bool + }{ + {[]byte{0x04, 0x47, 0x00, 0x01, 0x01}, `{"type":1095,"igp_metric":1}`, true, false}, + {[]byte{0x04, 0x47, 0x00, 0x01, 0x3F}, `{"type":1095,"igp_metric":63}`, true, false}, + {[]byte{0x04, 0x47, 0x00, 0x01, 0xFF}, `{"type":1095,"igp_metric":63}`, false, false}, + {[]byte{0x04, 0x47, 0x00, 0x02, 0x00, 0x01}, `{"type":1095,"igp_metric":1}`, true, false}, + {[]byte{0x04, 0x47, 0x00, 0x02, 0xff, 0xff}, `{"type":1095,"igp_metric":65535}`, true, false}, + {[]byte{0x04, 0x47, 0x00, 0x03, 0x00, 0x00, 0x01}, `{"type":1095,"igp_metric":1}`, true, false}, + {[]byte{0x04, 0x47, 0x00, 0x03, 0xff, 0xff, 0xff}, `{"type":1095,"igp_metric":16777215}`, true, false}, + {[]byte{0x04, 0x47, 0x00, 0x04, 0x07, 0x07, 0x07, 0x07}, "", false, true}, + {[]byte{0xfe, 0xfe, 0x00, 0x00}, "", false, true}, + } + + for _, test := range tests { + tlv := LsTLVIGPMetric{} + if test.err { + assert.Error(tlv.DecodeFromBytes(test.in)) + continue + } else { + assert.NoError(tlv.DecodeFromBytes(test.in)) + } + + got, err := tlv.MarshalJSON() + assert.NoError(err) + assert.Equal(got, []byte(test.want)) + + if test.serialize { + got, err := tlv.Serialize() + assert.NoError(err) + assert.Equal(test.in, got) + } + } +} + +func Test_LsTLVNLinkName(t *testing.T) { + assert := assert.New(t) + + var tests = []struct { + in []byte + want string + err bool + }{ + {[]byte{0x04, 0x4a, 0x00, 0x03, 0x72, 0x74, 0x72}, `{"type":1098,"link_name":"rtr"}`, false}, + {[]byte{0x04, 0x4a, 0x00, 0x03, 0x72, 0x74, 0x72, 0x00}, `{"type":1098,"link_name":"rtr"}`, false}, + {[]byte{0x04, 0x4a, 0x00, 0x00}, "", true}, + {[]byte{0xfe, 0xfe, 0x00, 0x00}, "", true}, + } + + for _, test := range tests { + tlv := LsTLVLinkName{} + if test.err { + assert.Error(tlv.DecodeFromBytes(test.in)) + continue + } else { + assert.NoError(tlv.DecodeFromBytes(test.in)) + } + + got, err := tlv.MarshalJSON() + assert.NoError(err) + assert.Equal(got, []byte(test.want)) + } +} + +func Test_LsTLVSrAlgorithm(t *testing.T) { + assert := assert.New(t) + + var tests = []struct { + in []byte + want string + err bool + }{ + {[]byte{0x04, 0x0b, 0x00, 0x03, 0x01, 0x02, 0x03}, `{"type":1035,"sr_algorithm":"[1 2 3]"}`, false}, + {[]byte{0x04, 0x0b, 0x00, 0x03, 0x01, 0x02, 0x03, 0x04}, `{"type":1035,"sr_algorithm":"[1 2 3]"}`, false}, + {[]byte{0x04, 0x0b, 0x00, 0x00}, "", true}, + {[]byte{0xfe, 0xfe, 0x00, 0x00}, "", true}, + } + + for _, test := range tests { + tlv := LsTLVSrAlgorithm{} + if test.err { + assert.Error(tlv.DecodeFromBytes(test.in)) + continue + } else { + assert.NoError(tlv.DecodeFromBytes(test.in)) + } + + got, err := tlv.MarshalJSON() + assert.NoError(err) + assert.Equal(got, []byte(test.want)) + } +} + +func Test_LsTLVSrCapabilities(t *testing.T) { + assert := assert.New(t) + + var tests = []struct { + in []byte + want string + serialize bool + err bool + }{ + { + []byte{ + 0x04, 0x0a, 0x00, 0x0c, // type 1034, length 12 + 0x00, 0x00, // flags and reserved + 0x00, 0x88, 0xb8, // range: 35000 + 0x04, 0x89, 0x00, 0x03, 0x01, 0x88, 0x94, // SID/Label TLV, SID: 100500 + }, + `{"type":1034,"flags":0,"ranges":[{"Range":35000,"FirstLabel":{"type":1161,"sid_label":100500}}]}`, + true, + false, + }, + { + []byte{ + 0x04, 0x0a, 0x00, 0x0d, // type 1034, length 13 + 0x00, 0x00, // flags and reserved + 0x00, 0x88, 0xb8, // range: 35000 + 0x04, 0x89, 0x00, 0x04, 0x04, 0x3B, 0x73, 0x49, // SID/Label TLV, SID: 71005001 + }, + `{"type":1034,"flags":0,"ranges":[{"Range":35000,"FirstLabel":{"type":1161,"sid_label":71005001}}]}`, + true, + false, + }, + { + []byte{ + 0x04, 0x0a, 0x00, 0x17, // type 1034, length 23 + 0x00, 0x00, // flags and reserved + 0x00, 0x88, 0xb8, // range: 35000 + 0x04, 0x89, 0x00, 0x04, 0x04, 0x3B, 0x73, 0x49, // SID/Label TLV, SID: 71005001 + 0x0f, 0x42, 0x40, // range: 1000000 + 0x04, 0x89, 0x00, 0x03, 0x01, 0x88, 0x94, // SID/Label TLV, SID: 100500 + }, + `{"type":1034,"flags":0,"ranges":[{"Range":35000,"FirstLabel":{"type":1161,"sid_label":71005001}},{"Range":1000000,"FirstLabel":{"type":1161,"sid_label":100500}}]}`, + true, + false, + }, + { + []byte{ + 0x04, 0x0a, 0x00, 0x17, // type 1034, length 23 + 0x00, 0x00, // flags and reserved + 0x00, 0x88, 0xb8, // range: 35000 + 0x04, 0x89, 0x00, 0x04, 0x04, 0x3B, 0x73, 0x49, // SID/Label TLV, SID: 71005001 + 0x0f, 0x42, 0x40, // range: 1000000 + 0x04, 0x89, 0x00, 0x03, 0x01, 0x88, 0x94, // SID/Label TLV, SID: 100500 + 0xff, 0xff, 0xff, // some random bytes - should be ignored + }, + `{"type":1034,"flags":0,"ranges":[{"Range":35000,"FirstLabel":{"type":1161,"sid_label":71005001}},{"Range":1000000,"FirstLabel":{"type":1161,"sid_label":100500}}]}`, + false, + false, + }, + { + []byte{ + 0x04, 0x0a, 0x00, 0xcc, // type 1034, length 204 (corrupted) + 0x00, 0x00, // flags and reserved + 0x00, 0x88, 0xb8, // range: 35000 + 0x04, 0x89, 0x00, 0x03, 0x01, 0x88, 0x94, // SID/Label TLV, SID: 100500 + }, + "", + false, + true, + }, + { + []byte{ + 0x04, 0x0a, 0x00, 0x11, // type 1034, length 23 + 0x00, 0x00, // flags and reserved + 0x00, 0x88, 0xb8, // range: 35000 + 0x04, 0x89, 0x00, 0x04, 0x04, 0x3B, 0x73, 0x49, // SID/Label TLV, SID: 71005001 + 0x0f, 0x42, 0x40, // range: 1000000 + 0x04, // No SID/Label sub-TLV + }, + "", + false, + true, + }, + } + + for _, test := range tests { + tlv := LsTLVSrCapabilities{} + if test.err { + assert.Error(tlv.DecodeFromBytes(test.in)) + continue + } else { + assert.NoError(tlv.DecodeFromBytes(test.in)) + } + + got, err := tlv.MarshalJSON() + assert.NoError(err) + assert.Equal(got, []byte(test.want)) + + if test.serialize { + s, err := tlv.Serialize() + assert.NoError(err) + assert.Equal(test.in, s) + } + } +} + +func Test_LsTLVLocalBlock(t *testing.T) { + assert := assert.New(t) + + var tests = []struct { + in []byte + want string + serialize bool + err bool + }{ + { + []byte{ + 0x04, 0x0c, 0x00, 0x0c, // type 1036, length 12 + 0x00, 0x00, // flags and reserved + 0x00, 0x88, 0xb8, // range: 35000 + 0x04, 0x89, 0x00, 0x03, 0x01, 0x88, 0x94, // SID/Label TLV, SID: 100500 + }, + `{"type":1036,"flags":0,"ranges":[{"Range":35000,"FirstLabel":{"type":1161,"sid_label":100500}}]}`, + true, + false, + }, + { + []byte{ + 0x04, 0x0c, 0x00, 0x0d, // type 1036, length 13 + 0x00, 0x00, // flags and reserved + 0x00, 0x88, 0xb8, // range: 35000 + 0x04, 0x89, 0x00, 0x04, 0x04, 0x3B, 0x73, 0x49, // SID/Label TLV, SID: 71005001 + }, + `{"type":1036,"flags":0,"ranges":[{"Range":35000,"FirstLabel":{"type":1161,"sid_label":71005001}}]}`, + true, + false, + }, + { + []byte{ + 0x04, 0x0c, 0x00, 0x17, // type 1036, length 23 + 0x00, 0x00, // flags and reserved + 0x00, 0x88, 0xb8, // range: 35000 + 0x04, 0x89, 0x00, 0x04, 0x04, 0x3B, 0x73, 0x49, // SID/Label TLV, SID: 71005001 + 0x0f, 0x42, 0x40, // range: 1000000 + 0x04, 0x89, 0x00, 0x03, 0x01, 0x88, 0x94, // SID/Label TLV, SID: 100500 + }, + `{"type":1036,"flags":0,"ranges":[{"Range":35000,"FirstLabel":{"type":1161,"sid_label":71005001}},{"Range":1000000,"FirstLabel":{"type":1161,"sid_label":100500}}]}`, + true, + false, + }, + { + []byte{ + 0x04, 0x0c, 0x00, 0x17, // type 1036, length 23 + 0x00, 0x00, // flags and reserved + 0x00, 0x88, 0xb8, // range: 35000 + 0x04, 0x89, 0x00, 0x04, 0x04, 0x3B, 0x73, 0x49, // SID/Label TLV, SID: 71005001 + 0x0f, 0x42, 0x40, // range: 1000000 + 0x04, 0x89, 0x00, 0x03, 0x01, 0x88, 0x94, // SID/Label TLV, SID: 100500 + 0xff, 0xff, 0xff, // some random bytes - should be ignored + }, + `{"type":1036,"flags":0,"ranges":[{"Range":35000,"FirstLabel":{"type":1161,"sid_label":71005001}},{"Range":1000000,"FirstLabel":{"type":1161,"sid_label":100500}}]}`, + false, + false, + }, + { + []byte{ + 0x04, 0x0c, 0x00, 0xcc, // type 1036, length 204 (corrupted) + 0x00, 0x00, // flags and reserved + 0x00, 0x88, 0xb8, // range: 35000 + 0x04, 0x89, 0x00, 0x03, 0x01, 0x88, 0x94, // SID/Label TLV, SID: 100500 + }, + "", + false, + true, + }, + { + []byte{ + 0x04, 0x0c, 0x00, 0x11, // type 1036, length 23 + 0x00, 0x00, // flags and reserved + 0x00, 0x88, 0xb8, // range: 35000 + 0x04, 0x89, 0x00, 0x04, 0x04, 0x3B, 0x73, 0x49, // SID/Label TLV, SID: 71005001 + 0x0f, 0x42, 0x40, // range: 1000000 + 0x04, // No SID/Label sub-TLV + }, + "", + false, + true, + }, + } + + for _, test := range tests { + tlv := LsTLVSrLocalBlock{} + if test.err { + assert.Error(tlv.DecodeFromBytes(test.in)) + continue + } else { + assert.NoError(tlv.DecodeFromBytes(test.in)) + } + + got, err := tlv.MarshalJSON() + assert.NoError(err) + assert.Equal(got, []byte(test.want)) + + if test.serialize { + s, err := tlv.Serialize() + assert.NoError(err) + assert.Equal(test.in, s) + } + } +} + +func Test_LsTLVAdjacencySID(t *testing.T) { + assert := assert.New(t) + + var tests = []struct { + in []byte + want string + serialize bool + err bool + }{ + {[]byte{0x04, 0x4b, 0x00, 0x07, 0x01, 0x01, 0x00, 0x00, 0x01, 0x88, 0x94}, `{"type":1099,"adjacency_sid":100500}`, true, false}, + {[]byte{0x04, 0x4b, 0x00, 0x07, 0x01, 0x01, 0x00, 0x00, 0xff, 0xff, 0xff}, `{"type":1099,"adjacency_sid":1048575}`, false, false}, + {[]byte{0x04, 0x4b, 0x00, 0x08, 0x01, 0x01, 0x00, 0x00, 0x04, 0x3B, 0x73, 0x49}, `{"type":1099,"adjacency_sid":71005001}`, true, false}, + {[]byte{0x04, 0x4b, 0x00, 0x06, 0x01, 0x02, 0x03, 0x04, 0x05, 0x11}, "", false, true}, + {[]byte{0xfe, 0xfe, 0x00, 0x07, 0x04, 0x3B, 0x73, 0x49, 0x05, 0x06, 0x07}, "", false, true}, + } + + for _, test := range tests { + tlv := LsTLVAdjacencySID{} + if test.err { + assert.Error(tlv.DecodeFromBytes(test.in)) + continue + } else { + assert.NoError(tlv.DecodeFromBytes(test.in)) + } + + got, err := tlv.MarshalJSON() + assert.NoError(err) + assert.Equal(got, []byte(test.want)) + + if test.serialize { + s, err := tlv.Serialize() + assert.NoError(err) + assert.Equal(test.in, s) + } + } +} + +func Test_LsTLVSIDLabel(t *testing.T) { + assert := assert.New(t) + + var tests = []struct { + in []byte + want string + serialize bool + err bool + }{ + {[]byte{0x04, 0x89, 0x00, 0x03, 0x01, 0x88, 0x94}, `{"type":1161,"sid_label":100500}`, true, false}, + {[]byte{0x04, 0x89, 0x00, 0x03, 0x0f, 0xff, 0xff}, `{"type":1161,"sid_label":1048575}`, true, false}, + {[]byte{0x04, 0x89, 0x00, 0x03, 0xff, 0xff, 0xff}, `{"type":1161,"sid_label":1048575}`, false, false}, + {[]byte{0x04, 0x89, 0x00, 0x04, 0x04, 0x3B, 0x73, 0x49}, `{"type":1161,"sid_label":71005001}`, false, false}, + {[]byte{0x04, 0x89, 0x00, 0x05, 0x01, 0x02, 0x03, 0x04, 0x05}, "", false, true}, + {[]byte{0xfe, 0xfe, 0x00, 0x04, 0x04, 0x3B, 0x73, 0x49}, "", false, true}, + } + + for _, test := range tests { + tlv := LsTLVSIDLabel{} + if test.err { + assert.Error(tlv.DecodeFromBytes(test.in)) + continue + } else { + assert.NoError(tlv.DecodeFromBytes(test.in)) + } + + got, err := tlv.MarshalJSON() + assert.NoError(err) + assert.Equal(got, []byte(test.want)) + + if test.serialize { + s, err := tlv.Serialize() + assert.NoError(err) + assert.Equal(test.in, s) + } + } +} + +func Test_LsTLVPrefixSID(t *testing.T) { + assert := assert.New(t) + + var tests = []struct { + in []byte + want string + serialize bool + err bool + }{ + {[]byte{0x04, 0x86, 0x00, 0x07, 0x01, 0x01, 0x00, 0x00, 0x01, 0x88, 0x94}, `{"type":1158,"prefix_sid":100500}`, true, false}, + {[]byte{0x04, 0x86, 0x00, 0x07, 0x01, 0x01, 0x00, 0x00, 0xff, 0xff, 0xff}, `{"type":1158,"prefix_sid":1048575}`, false, false}, + {[]byte{0x04, 0x86, 0x00, 0x08, 0x01, 0x01, 0x00, 0x00, 0x04, 0x3B, 0x73, 0x49}, `{"type":1158,"prefix_sid":71005001}`, true, false}, + {[]byte{0x04, 0x86, 0x00, 0x06, 0x01, 0x02, 0x03, 0x04, 0x05, 0x11}, "", false, true}, + {[]byte{0xfe, 0xfe, 0x00, 0x07, 0x04, 0x3B, 0x73, 0x49, 0x05, 0x06, 0x07}, "", false, true}, + } + + for _, test := range tests { + tlv := LsTLVPrefixSID{} + if test.err { + assert.Error(tlv.DecodeFromBytes(test.in)) + continue + } else { + assert.NoError(tlv.DecodeFromBytes(test.in)) + } + + got, err := tlv.MarshalJSON() + assert.NoError(err) + assert.Equal(got, []byte(test.want)) + + if test.serialize { + s, err := tlv.Serialize() + assert.NoError(err) + assert.Equal(test.in, s) + } + } +} + +func Test_LsTLVSourceRouterID(t *testing.T) { + assert := assert.New(t) + + var tests = []struct { + in []byte + want string + err bool + }{ + {[]byte{0x04, 0x93, 0x00, 0x04, 0x0a, 0x0a, 0x0a, 0x0a}, `{"type":1171,"source_router_id":"10.10.10.10"}`, false}, + {[]byte{0x04, 0x93, 0x00, 0x10, 0x20, 0x01, 0x0d, 0xb8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xBE, 0xEF}, `{"type":1171,"source_router_id":"2001:db8::beef"}`, false}, + {[]byte{0x04, 0x93, 0x00, 0x10, 0x20, 0x01, 0x0d, 0xb8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xBE, 0xEF, 0xFF}, `{"type":1171,"source_router_id":"2001:db8::beef"}`, false}, + {[]byte{0x04, 0x93, 0x00, 0x01, 0x00}, "", true}, + {[]byte{0xfe, 0xfe, 0x00, 0x00}, "", true}, + } + + for _, test := range tests { + tlv := LsTLVSourceRouterID{} + if test.err { + assert.Error(tlv.DecodeFromBytes(test.in)) + continue + } else { + assert.NoError(tlv.DecodeFromBytes(test.in)) + } + + got, err := tlv.MarshalJSON() + assert.NoError(err) + assert.Equal(got, []byte(test.want)) + } +} + +func Test_LsTLVOpaqueLinkAttr(t *testing.T) { + assert := assert.New(t) + + var tests = []struct { + in []byte + want string + err bool + }{ + {[]byte{0x04, 0x49, 0x00, 0x03, 0x01, 0x02, 0x03}, `{"type":1097,"link_opaque_attribute":"[1 2 3]"}`, false}, + {[]byte{0x04, 0x49, 0x00, 0x03, 0x01, 0x02, 0x03, 0x04}, `{"type":1097,"link_opaque_attribute":"[1 2 3]"}`, false}, + {[]byte{0xfe, 0xfe, 0x00, 0x00}, "", true}, + } + + for _, test := range tests { + tlv := LsTLVOpaqueLinkAttr{} + if test.err { + assert.Error(tlv.DecodeFromBytes(test.in)) + continue + } else { + assert.NoError(tlv.DecodeFromBytes(test.in)) + } + + got, err := tlv.MarshalJSON() + assert.NoError(err) + assert.Equal(got, []byte(test.want)) + } +} + +func Test_LsTLVIGPFlags(t *testing.T) { + assert := assert.New(t) + + var tests = []struct { + in []byte + want string + serialize bool + err bool + }{ + {[]byte{0x04, 0x80, 0x00, 0x01, 0xFF}, `{"type":1152,"igp_flags":"{IGP Flags: XXXXPLND}"}`, true, false}, + {[]byte{0x04, 0x80, 0x00, 0x01, 0x80}, `{"type":1152,"igp_flags":"{IGP Flags: *******D}"}`, true, false}, + {[]byte{0x04, 0x80, 0x00, 0x01, 0x80, 0xAA}, `{"type":1152,"igp_flags":"{IGP Flags: *******D}"}`, false, false}, + {[]byte{0x04, 0x80, 0x00, 0x02, 0x80, 0x44}, "", false, true}, + {[]byte{0xfe, 0xfe, 0x00, 0x00}, "", false, true}, + } + + for _, test := range tests { + tlv := LsTLVIGPFlags{} + if test.err { + assert.Error(tlv.DecodeFromBytes(test.in)) + } else { + assert.NoError(tlv.DecodeFromBytes(test.in)) + got, err := tlv.MarshalJSON() + assert.NoError(err) + assert.Equal(got, []byte(test.want)) + if test.serialize { + got, err := tlv.Serialize() + assert.NoError(err) + assert.Equal(test.in, got) + } + } + } +} + +func Test_LsTLVOpaquePrefixAttr(t *testing.T) { + assert := assert.New(t) + + var tests = []struct { + in []byte + want string + err bool + }{ + {[]byte{0x04, 0x85, 0x00, 0x03, 0x01, 0x02, 0x03}, `{"type":1157,"prefix_opaque_attribute":"[1 2 3]"}`, false}, + {[]byte{0x04, 0x85, 0x00, 0x03, 0x01, 0x02, 0x03, 0x04}, `{"type":1157,"prefix_opaque_attribute":"[1 2 3]"}`, false}, + {[]byte{0xfe, 0xfe, 0x00, 0x00}, "", true}, + } + + for _, test := range tests { + tlv := LsTLVOpaquePrefixAttr{} + if test.err { + assert.Error(tlv.DecodeFromBytes(test.in)) + continue + } else { + assert.NoError(tlv.DecodeFromBytes(test.in)) + } + + got, err := tlv.MarshalJSON() + assert.NoError(err) + assert.Equal(got, []byte(test.want)) + } +} + +func Test_parseIGPRouterID(t *testing.T) { + assert := assert.New(t) + + var tests = []struct { + in []byte + str string + pseudo bool + }{ + {[]byte{1, 2, 3, 4}, "1.2.3.4", false}, + {[]byte{1, 2, 3, 4, 5, 255}, "0102.0304.05ff", false}, + {[]byte{1, 2, 3, 4, 5, 255, 0}, "0102.0304.05ff-00", true}, + {[]byte{1, 2, 3, 4, 5, 6, 7, 8}, "1.2.3.4:5.6.7.8", true}, + } + + for _, test := range tests { + str, pseudo := parseIGPRouterID(test.in) + assert.Equal(test.str, str) + assert.Equal(test.pseudo, pseudo) + } +} + +func Test_LsNodeDescriptor(t *testing.T) { + assert := assert.New(t) + + var tests = []struct { + in []byte + str string + err bool + serialize bool + }{ + {[]byte{ + 0x01, 0x00, 0x00, 0x22, // Local Node Desc + 0x02, 0x00, 0x00, 0x04, 0x07, 0x07, 0x07, 0x07, // TLV ASN: 117901063 + 0x02, 0x01, 0x00, 0x04, 0x07, 0x07, 0x07, 0x07, // TLV BGP LS ID: 117901063 + 0x02, 0x02, 0x00, 0x04, 0x07, 0x07, 0x07, 0x07, // TLV OSPF Area ID: 117901063 + 0x02, 0x03, 0x00, 0x06, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, // TLV IGP Router ID: 0102.0304.0506 + }, "{ASN: 117901063, BGP LS ID: 117901063, OSPF AREA: 117901063, IGP ROUTER ID: 0102.0304.0506}", + false, true}, + {[]byte{ + 0x01, 0x01, 0x00, 0x22, // Remote Node Desc + 0x02, 0x00, 0x00, 0x04, 0x07, 0x07, 0x07, 0x07, // TLV ASN: 117901063 + 0x02, 0x01, 0x00, 0x04, 0x07, 0x07, 0x07, 0x07, // TLV BGP LS ID: 117901063 + 0x02, 0x02, 0x00, 0x04, 0x07, 0x07, 0x07, 0x07, // TLV OSPF Area ID: 117901063 + 0x02, 0x03, 0x00, 0x06, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, // TLV IGP Router ID: 0102.0304.0506 + }, "{ASN: 117901063, BGP LS ID: 117901063, OSPF AREA: 117901063, IGP ROUTER ID: 0102.0304.0506}", + false, true}, + {[]byte{ + 0x01, 0x00, 0x00, 0x21, // Truncated Length + 0x02, 0x00, 0x00, 0x04, 0x07, 0x07, 0x07, 0x07, // TLV ASN: 117901063 + 0x02, 0x01, 0x00, 0x04, 0x07, 0x07, 0x07, 0x07, // TLV BGP LS ID: 117901063 + 0x02, 0x02, 0x00, 0x04, 0x07, 0x07, 0x07, 0x07, // TLV OSPF Area ID: 117901063 + 0x02, 0x03, 0x00, 0x06, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, // TLV IGP Router ID: 0102.0304.0506 + }, "", true, false}, + {[]byte{ + 0x01, 0x00, 0x00, 0x22, // Missing mandatory TLV + 0x02, 0x00, 0x00, 0x04, 0x07, 0x07, 0x07, 0x07, // TLV ASN: 117901063 + 0x02, 0x01, 0x00, 0x04, 0x07, 0x07, 0x07, 0x07, // TLV BGP LS ID: 117901063 + 0x02, 0x02, 0x00, 0x04, 0x07, 0x07, 0x07, 0x07, // TLV OSPF Area ID: 117901063 + }, "", true, false}, + {[]byte{ + 0x01, 0x00, 0x00, 0x22, // Incorrect TLV order + 0x02, 0x00, 0x00, 0x04, 0x07, 0x07, 0x07, 0x07, // TLV ASN: 117901063 + 0x02, 0x02, 0x00, 0x04, 0x07, 0x07, 0x07, 0x07, // TLV OSPF Area ID: 117901063 + 0x02, 0x01, 0x00, 0x04, 0x07, 0x07, 0x07, 0x07, // TLV BGP LS ID: 117901063 + 0x02, 0x03, 0x00, 0x06, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, // TLV IGP Router ID: 0102.0304.0506 + }, "", true, false}, + {[]byte{ + 0x01, 0x00, 0x00, 0x26, // Unexpected TLV + 0x02, 0x00, 0x00, 0x04, 0x07, 0x07, 0x07, 0x07, // TLV ASN: 117901063 + 0x02, 0x01, 0x00, 0x04, 0x07, 0x07, 0x07, 0x07, // TLV BGP LS ID: 117901063 + 0x02, 0x02, 0x00, 0x04, 0x07, 0x07, 0x07, 0x07, // TLV OSPF Area ID: 117901063 + 0x02, 0x03, 0x00, 0x06, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, // TLV IGP Router ID: 0102.0304.0506 + 0xfe, 0x01, 0x00, 0x00, // Unsupported + }, "{ASN: 117901063, BGP LS ID: 117901063, OSPF AREA: 117901063, IGP ROUTER ID: 0102.0304.0506}", + false, false}, + {[]byte{ + 0x01, 0x00, 0x00, 0x0a, // Missing optional TLVs + 0x02, 0x03, 0x00, 0x06, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, // TLV IGP Router ID: 0102.0304.0506 + }, "{ASN: 0, BGP LS ID: 0, OSPF AREA: 0, IGP ROUTER ID: 0102.0304.0506}", false, true}, + } + + for _, test := range tests { + tlv := LsTLVNodeDescriptor{} + if test.err { + assert.Error(tlv.DecodeFromBytes(test.in)) + } else { + assert.NoError(tlv.DecodeFromBytes(test.in)) + assert.Equal(test.str, tlv.String()) + if test.serialize { + got, err := tlv.Serialize() + assert.NoError(err) + assert.Equal(test.in, got) + } + } + } +} + +func Test_LsAddrPrefix(t *testing.T) { + assert := assert.New(t) + + var tests = []struct { + in []byte + str string + err bool + serialize bool + }{ + {[]byte{ + 0x00, 0x01, 0x00, 0x2f, // Node NLRI, correct length + 0x02, // Protocol ISIS Level 2 + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // ID + 0x01, 0x00, 0x00, 0x22, // Local Node Desc + 0x02, 0x00, 0x00, 0x04, 0x07, 0x07, 0x07, 0x07, // TLV ASN: 117901063 + 0x02, 0x01, 0x00, 0x04, 0x07, 0x07, 0x07, 0x07, // TLV BGP LS ID: 117901063 + 0x02, 0x02, 0x00, 0x04, 0x07, 0x07, 0x07, 0x07, // TLV OSPF Area ID: 117901063 + 0x02, 0x03, 0x00, 0x06, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, // TLV IGP Router ID: 0102.0304.0506 + }, "NLRI { NODE { AS:117901063 BGP-LS ID:117901063 0102.0304.0506 ISIS-L2:0 } }", false, true}, + {[]byte{ + 0x00, 0x01, 0x00, 0x2e, // Node NLRI, truncated length + 0x02, // Protocol ISIS Level 2 + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // ID + 0x01, 0x00, 0x00, 0x22, // Local Node Desc + 0x02, 0x00, 0x00, 0x04, 0x07, 0x07, 0x07, 0x07, // TLV ASN: 117901063 + 0x02, 0x01, 0x00, 0x04, 0x07, 0x07, 0x07, 0x07, // TLV BGP LS ID: 117901063 + 0x02, 0x02, 0x00, 0x04, 0x07, 0x07, 0x07, 0x07, // TLV OSPF Area ID: 117901063 + 0x02, 0x03, 0x00, 0x06, 0x01, 0x02, 0x03, 0x04, 0x05, // TLV IGP Router ID: 0102.0304.05 + }, "", true, false}, + {[]byte{ + 0x00, 0x01, 0x00, 0x2f, // Node NLRI, correct length + 0x02, // Protocol ISIS Level 2 + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // ID + 0x01, 0x01, 0x00, 0x22, // Remote Node Desc (unexpected) + 0x02, 0x00, 0x00, 0x04, 0x07, 0x07, 0x07, 0x07, // TLV ASN: 117901063 + 0x02, 0x01, 0x00, 0x04, 0x07, 0x07, 0x07, 0x07, // TLV BGP LS ID: 117901063 + 0x02, 0x02, 0x00, 0x04, 0x07, 0x07, 0x07, 0x07, // TLV OSPF Area ID: 117901063 + 0x02, 0x03, 0x00, 0x06, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, // TLV IGP Router ID: 0102.0304.0506 + }, "", true, false}, + {[]byte{ + 0x00, 0x01, 0x00, 0x2d, // Node NLRI, correct length + 0x02, // Protocol ISIS Level 2 + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // ID + // Mandatory TLV missing + }, "", true, false}, + {[]byte{ + 0x00, 0x02, 0x00, 0x65, // Link NLRI, correct length + 0x02, // Protocol ISIS Level 2 + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // ID + 0x01, 0x00, 0x00, 0x22, // Local Node Desc + 0x02, 0x00, 0x00, 0x04, 0x07, 0x07, 0x07, 0x07, // TLV ASN: 117901063 + 0x02, 0x01, 0x00, 0x04, 0x07, 0x07, 0x07, 0x07, // TLV BGP LS ID: 117901063 + 0x02, 0x02, 0x00, 0x04, 0x07, 0x07, 0x07, 0x07, // TLV OSPF Area ID: 117901063 + 0x02, 0x03, 0x00, 0x06, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, // TLV IGP Router ID: 0102.0304.0506 + 0x01, 0x01, 0x00, 0x22, // Remote Node Desc + 0x02, 0x00, 0x00, 0x04, 0x07, 0x07, 0x07, 0x07, // TLV ASN: 117901063 + 0x02, 0x01, 0x00, 0x04, 0x07, 0x07, 0x07, 0x07, // TLV BGP LS ID: 117901063 + 0x02, 0x02, 0x00, 0x04, 0x07, 0x07, 0x07, 0x07, // TLV OSPF Area ID: 117901063 + 0x02, 0x03, 0x00, 0x06, 0x06, 0x05, 0x04, 0x03, 0x02, 0x01, // TLV IGP Router ID: 0605.0403.0201 + 0x01, 0x02, 0x00, 0x08, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x02, // LinkID TLV, Local: 1, Remote: 2 + }, "NLRI { LINK { LOCAL_NODE: 0102.0304.0506 REMOTE_NODE: 0605.0403.0201 LINK: 1->2} }", false, true}, + {[]byte{ + 0x00, 0x02, 0x00, 0x69, // Link NLRI, correct length + 0x02, // Protocol ISIS Level 2 + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // ID + 0x01, 0x00, 0x00, 0x22, // Local Node Desc + 0x02, 0x00, 0x00, 0x04, 0x07, 0x07, 0x07, 0x07, // TLV ASN: 117901063 + 0x02, 0x01, 0x00, 0x04, 0x07, 0x07, 0x07, 0x07, // TLV BGP LS ID: 117901063 + 0x02, 0x02, 0x00, 0x04, 0x07, 0x07, 0x07, 0x07, // TLV OSPF Area ID: 117901063 + 0x02, 0x03, 0x00, 0x06, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, // TLV IGP Router ID: 0102.0304.0506 + 0x01, 0x01, 0x00, 0x22, // Remote Node Desc + 0x02, 0x00, 0x00, 0x04, 0x07, 0x07, 0x07, 0x07, // TLV ASN: 117901063 + 0x02, 0x01, 0x00, 0x04, 0x07, 0x07, 0x07, 0x07, // TLV BGP LS ID: 117901063 + 0x02, 0x02, 0x00, 0x04, 0x07, 0x07, 0x07, 0x07, // TLV OSPF Area ID: 117901063 + 0x02, 0x03, 0x00, 0x06, 0x06, 0x05, 0x04, 0x03, 0x02, 0x01, // TLV IGP Router ID: 0605.0403.0201 + 0x01, 0x03, 0x00, 0x04, 0x01, 0x01, 0x01, 0x01, // IPv4 Interface Addr TLV: 1.1.1.1 + 0x01, 0x04, 0x00, 0x04, 0x02, 0x02, 0x02, 0x02, // IPv4 Neighbor Addr TLV: 2.2.2.2 + }, "NLRI { LINK { LOCAL_NODE: 0102.0304.0506 REMOTE_NODE: 0605.0403.0201 LINK: 1.1.1.1->2.2.2.2} }", false, true}, + {[]byte{ + 0x00, 0x02, 0x00, 0x81, // Link NLRI, correct length + 0x02, // Protocol ISIS Level 2 + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // ID + 0x01, 0x00, 0x00, 0x22, // Local Node Desc + 0x02, 0x00, 0x00, 0x04, 0x07, 0x07, 0x07, 0x07, // TLV ASN: 117901063 + 0x02, 0x01, 0x00, 0x04, 0x07, 0x07, 0x07, 0x07, // TLV BGP LS ID: 117901063 + 0x02, 0x02, 0x00, 0x04, 0x07, 0x07, 0x07, 0x07, // TLV OSPF Area ID: 117901063 + 0x02, 0x03, 0x00, 0x06, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, // TLV IGP Router ID: 0102.0304.0506 + 0x01, 0x01, 0x00, 0x22, // Remote Node Desc + 0x02, 0x00, 0x00, 0x04, 0x07, 0x07, 0x07, 0x07, // TLV ASN: 117901063 + 0x02, 0x01, 0x00, 0x04, 0x07, 0x07, 0x07, 0x07, // TLV BGP LS ID: 117901063 + 0x02, 0x02, 0x00, 0x04, 0x07, 0x07, 0x07, 0x07, // TLV OSPF Area ID: 117901063 + 0x02, 0x03, 0x00, 0x06, 0x06, 0x05, 0x04, 0x03, 0x02, 0x01, // TLV IGP Router ID: 0605.0403.0201 + 0x01, 0x05, 0x00, 0x10, 0x20, 0x01, 0x0d, 0xb8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xBE, 0xEF, // IPv6 Interface Addr TLV: 2001:db8::beef + 0x01, 0x06, 0x00, 0x10, 0x20, 0x01, 0x0d, 0xb8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xDE, 0xAD, // IPv6 Interface Addr TLV: 2001:db8::dead + }, "NLRI { LINK { LOCAL_NODE: 0102.0304.0506 REMOTE_NODE: 0605.0403.0201 LINK: 2001:db8::beef->2001:db8::dead} }", false, true}, + {[]byte{ + 0x00, 0x02, 0x00, 0x59, // Link NLRI, correct length + 0x02, // Protocol ISIS Level 2 + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // ID + 0x01, 0x00, 0x00, 0x22, // Local Node Desc + 0x02, 0x00, 0x00, 0x04, 0x07, 0x07, 0x07, 0x07, // TLV ASN: 117901063 + 0x02, 0x01, 0x00, 0x04, 0x07, 0x07, 0x07, 0x07, // TLV BGP LS ID: 117901063 + 0x02, 0x02, 0x00, 0x04, 0x07, 0x07, 0x07, 0x07, // TLV OSPF Area ID: 117901063 + 0x02, 0x03, 0x00, 0x06, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, // TLV IGP Router ID: 0102.0304.0506 + 0x01, 0x01, 0x00, 0x22, // Remote Node Desc + 0x02, 0x00, 0x00, 0x04, 0x07, 0x07, 0x07, 0x07, // TLV ASN: 117901063 + 0x02, 0x01, 0x00, 0x04, 0x07, 0x07, 0x07, 0x07, // TLV BGP LS ID: 117901063 + 0x02, 0x02, 0x00, 0x04, 0x07, 0x07, 0x07, 0x07, // TLV OSPF Area ID: 117901063 + 0x02, 0x03, 0x00, 0x06, 0x06, 0x05, 0x04, 0x03, 0x02, 0x01, // TLV IGP Router ID: 0605.0403.0201 + }, "NLRI { LINK { LOCAL_NODE: 0102.0304.0506 REMOTE_NODE: 0605.0403.0201 LINK: UNKNOWN} }", false, true}, + {[]byte{ + 0x00, 0x02, 0x00, 0x33, // Link NLRI, correct length + 0x02, // Protocol ISIS Level 2 + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // ID + 0x01, 0x00, 0x00, 0x22, // Local Node Desc + 0x02, 0x00, 0x00, 0x04, 0x07, 0x07, 0x07, 0x07, // TLV ASN: 117901063 + 0x02, 0x01, 0x00, 0x04, 0x07, 0x07, 0x07, 0x07, // TLV BGP LS ID: 117901063 + 0x02, 0x02, 0x00, 0x04, 0x07, 0x07, 0x07, 0x07, // TLV OSPF Area ID: 117901063 + 0x02, 0x03, 0x00, 0x06, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, // TLV IGP Router ID: 0102.0304.0506 + // Missing mandatory TLV + }, "", true, false}, + {[]byte{ + 0x00, 0x03, 0x00, 0x35, // Prefix IPv4 NLRI, correct length + 0x02, // Protocol ISIS Level 2 + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // ID + 0x01, 0x00, 0x00, 0x22, // Local Node Desc + 0x02, 0x00, 0x00, 0x04, 0x07, 0x07, 0x07, 0x07, // TLV ASN: 117901063 + 0x02, 0x01, 0x00, 0x04, 0x07, 0x07, 0x07, 0x07, // TLV BGP LS ID: 117901063 + 0x02, 0x02, 0x00, 0x04, 0x07, 0x07, 0x07, 0x07, // TLV OSPF Area ID: 117901063 + 0x02, 0x03, 0x00, 0x06, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, // TLV IGP Router ID: 0102.0304.0506 + 0x01, 0x09, 0x00, 0x02, 0x08, 0x0a, // IP ReachabilityInfo TLV, 10.0.0.0/8 + }, "NLRI { PREFIXv4 { LOCAL_NODE: 0102.0304.0506 PREFIX: [10.0.0.0/8] } }", false, true}, + {[]byte{ + 0x00, 0x03, 0x00, 0x43, // Prefix IPv4 NLRI, correct length + 0x02, // Protocol ISIS Level 2 + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // ID + 0x01, 0x00, 0x00, 0x22, // Local Node Desc + 0x02, 0x00, 0x00, 0x04, 0x07, 0x07, 0x07, 0x07, // TLV ASN: 117901063 + 0x02, 0x01, 0x00, 0x04, 0x07, 0x07, 0x07, 0x07, // TLV BGP LS ID: 117901063 + 0x02, 0x02, 0x00, 0x04, 0x07, 0x07, 0x07, 0x07, // TLV OSPF Area ID: 117901063 + 0x02, 0x03, 0x00, 0x06, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, // TLV IGP Router ID: 0102.0304.0506 + 0x01, 0x09, 0x00, 0x02, 0x08, 0x0a, // IP ReachabilityInfo TLV, 10.0.0.0/8 + 0x01, 0x09, 0x00, 0x05, 0x1f, 0xc0, 0xa8, 0x07, 0xfe, // IP ReachabilityInfo TLV, 192.168.7.254/31 + 0x01, 0x08, 0x00, 0x01, 0x06, // OSPF Route Type TLV (NSSA2) + }, "NLRI { PREFIXv4 { LOCAL_NODE: 0102.0304.0506 PREFIX: [10.0.0.0/8 192.168.7.254/31] OSPF_ROUTE_TYPE:NSSA2 } }", false, true}, + {[]byte{ + 0x00, 0x03, 0x00, 0x35, // Prefix IPv4 NLRI, correct length + 0x02, // Protocol ISIS Level 2 + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // ID + 0x01, 0x00, 0x00, 0x22, // Local Node Desc + 0x02, 0x00, 0x00, 0x04, 0x07, 0x07, 0x07, 0x07, // TLV ASN: 117901063 + 0x02, 0x01, 0x00, 0x04, 0x07, 0x07, 0x07, 0x07, // TLV BGP LS ID: 117901063 + 0x02, 0x02, 0x00, 0x04, 0x07, 0x07, 0x07, 0x07, // TLV OSPF Area ID: 117901063 + 0x02, 0x03, 0x00, 0x06, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, // TLV IGP Router ID: 0102.0304.0506 + 0x01, 0x09, 0x00, 0x02, 0x08, 0x0a, // IP ReachabilityInfo TLV, 10.0.0.0/8 + }, "NLRI { PREFIXv4 { LOCAL_NODE: 0102.0304.0506 PREFIX: [10.0.0.0/8] } }", false, true}, + {[]byte{ + 0x00, 0x03, 0x00, 0x2f, // Prefix IPv4 NLRI, correct length + 0x02, // Protocol ISIS Level 2 + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // ID + 0x01, 0x00, 0x00, 0x22, // Local Node Desc + 0x02, 0x00, 0x00, 0x04, 0x07, 0x07, 0x07, 0x07, // TLV ASN: 117901063 + 0x02, 0x01, 0x00, 0x04, 0x07, 0x07, 0x07, 0x07, // TLV BGP LS ID: 117901063 + 0x02, 0x02, 0x00, 0x04, 0x07, 0x07, 0x07, 0x07, // TLV OSPF Area ID: 117901063 + 0x02, 0x03, 0x00, 0x06, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, // TLV IGP Router ID: 0102.0304.0506 + // Missing mandatory TLV (IP Reachability info) + }, "", true, false}, + {[]byte{ + 0x00, 0x03, 0x00, 0x39, // Prefix IPv4 NLRI, correct length + 0x02, // Protocol ISIS Level 2 + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // ID + 0x01, 0x00, 0x00, 0x22, // Local Node Desc + 0x02, 0x00, 0x00, 0x04, 0x07, 0x07, 0x07, 0x07, // TLV ASN: 117901063 + 0x02, 0x01, 0x00, 0x04, 0x07, 0x07, 0x07, 0x07, // TLV BGP LS ID: 117901063 + 0x02, 0x02, 0x00, 0x04, 0x07, 0x07, 0x07, 0x07, // TLV OSPF Area ID: 117901063 + 0x02, 0x03, 0x00, 0x06, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, // TLV IGP Router ID: 0102.0304.0506 + // IPv6 IP Reachability info in v4 prefix + 0x01, 0x09, 0x00, 0x06, 0x40, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, + }, "", true, false}, + {[]byte{ + 0x00, 0x04, 0x00, 0x35, // Prefix IPv6 NLRI, correct length + 0x02, // Protocol ISIS Level 2 + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // ID + 0x01, 0x00, 0x00, 0x22, // Local Node Desc + 0x02, 0x00, 0x00, 0x04, 0x07, 0x07, 0x07, 0x07, // TLV ASN: 117901063 + 0x02, 0x01, 0x00, 0x04, 0x07, 0x07, 0x07, 0x07, // TLV BGP LS ID: 117901063 + 0x02, 0x02, 0x00, 0x04, 0x07, 0x07, 0x07, 0x07, // TLV OSPF Area ID: 117901063 + 0x02, 0x03, 0x00, 0x06, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, // TLV IGP Router ID: 0102.0304.0506 + 0x01, 0x09, 0x00, 0x02, 0x08, 0x0a, // IP ReachabilityInfo TLV, 10.0.0.0/8 + }, "NLRI { PREFIXv6 { LOCAL_NODE: 0102.0304.0506 PREFIX: [a00::/8] } }", false, true}, + {[]byte{ + 0x00, 0x04, 0x00, 0x43, // Prefix IPv6 NLRI, correct length + 0x02, // Protocol ISIS Level 2 + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // ID + 0x01, 0x00, 0x00, 0x22, // Local Node Desc + 0x02, 0x00, 0x00, 0x04, 0x07, 0x07, 0x07, 0x07, // TLV ASN: 117901063 + 0x02, 0x01, 0x00, 0x04, 0x07, 0x07, 0x07, 0x07, // TLV BGP LS ID: 117901063 + 0x02, 0x02, 0x00, 0x04, 0x07, 0x07, 0x07, 0x07, // TLV OSPF Area ID: 117901063 + 0x02, 0x03, 0x00, 0x06, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, // TLV IGP Router ID: 0102.0304.0506 + 0x01, 0x09, 0x00, 0x02, 0x08, 0x0a, // IP ReachabilityInfo TLV, 10.0.0.0/8 + 0x01, 0x09, 0x00, 0x05, 0x1f, 0xc0, 0xa8, 0x07, 0xfe, // IP ReachabilityInfo TLV, 192.168.7.254/31 + 0x01, 0x08, 0x00, 0x01, 0x06, // OSPF Route Type TLV (NSSA2) + }, "NLRI { PREFIXv6 { LOCAL_NODE: 0102.0304.0506 PREFIX: [a00::/8 c0a8:7fe::/31] OSPF_ROUTE_TYPE:NSSA2 } }", false, true}, + {[]byte{ + 0x00, 0x04, 0x00, 0x35, // Prefix IPv6 NLRI, correct length + 0x02, // Protocol ISIS Level 2 + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // ID + 0x01, 0x00, 0x00, 0x22, // Local Node Desc + 0x02, 0x00, 0x00, 0x04, 0x07, 0x07, 0x07, 0x07, // TLV ASN: 117901063 + 0x02, 0x01, 0x00, 0x04, 0x07, 0x07, 0x07, 0x07, // TLV BGP LS ID: 117901063 + 0x02, 0x02, 0x00, 0x04, 0x07, 0x07, 0x07, 0x07, // TLV OSPF Area ID: 117901063 + 0x02, 0x03, 0x00, 0x06, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, // TLV IGP Router ID: 0102.0304.0506 + 0x01, 0x09, 0x00, 0x02, 0x08, 0x0a, // IP ReachabilityInfo TLV, 10.0.0.0/8 + }, "NLRI { PREFIXv6 { LOCAL_NODE: 0102.0304.0506 PREFIX: [a00::/8] } }", false, true}, + {[]byte{ + 0x00, 0x04, 0x00, 0x2f, // Prefix IPv6 NLRI, correct length + 0x02, // Protocol ISIS Level 2 + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // ID + 0x01, 0x00, 0x00, 0x22, // Local Node Desc + 0x02, 0x00, 0x00, 0x04, 0x07, 0x07, 0x07, 0x07, // TLV ASN: 117901063 + 0x02, 0x01, 0x00, 0x04, 0x07, 0x07, 0x07, 0x07, // TLV BGP LS ID: 117901063 + 0x02, 0x02, 0x00, 0x04, 0x07, 0x07, 0x07, 0x07, // TLV OSPF Area ID: 117901063 + 0x02, 0x03, 0x00, 0x06, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, // TLV IGP Router ID: 0102.0304.0506 + // Missing mandatory TLV (IP Reachability info) + }, "", true, false}, + {[]byte{ + 0x00, 0x04, 0x00, 0x39, // Prefix IPv6 NLRI, correct length + 0x02, // Protocol ISIS Level 2 + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // ID + 0x01, 0x00, 0x00, 0x22, // Local Node Desc + 0x02, 0x00, 0x00, 0x04, 0x07, 0x07, 0x07, 0x07, // TLV ASN: 117901063 + 0x02, 0x01, 0x00, 0x04, 0x07, 0x07, 0x07, 0x07, // TLV BGP LS ID: 117901063 + 0x02, 0x02, 0x00, 0x04, 0x07, 0x07, 0x07, 0x07, // TLV OSPF Area ID: 117901063 + 0x02, 0x03, 0x00, 0x06, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, // TLV IGP Router ID: 0102.0304.0506 + // IPv6 IP Reachability info in v4 prefix + 0x01, 0x09, 0x00, 0x06, 0x40, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, + }, "", true, false}, + } + + for _, test := range tests { + nlri := LsAddrPrefix{} + if test.err { + assert.Error(nlri.DecodeFromBytes(test.in)) + } else { + assert.NoError(nlri.DecodeFromBytes(test.in)) + assert.Equal(test.str, nlri.String()) + if test.serialize { + got, err := nlri.Serialize() + assert.NoError(err) + assert.Equal(test.in, got) + } + } + } +} + +func Test_PathAttributeLs(t *testing.T) { + assert := assert.New(t) + + var tests = []struct { + in []byte + str string + json string + serialize bool + err bool + }{ + {[]byte{ + // LS Attribute with all Node-related TLVs. + 0x80, 0x29, 0x62, // Optional attribute, BGP_ATTR_TYPE_LS, correct length + 0x04, 0x00, 0x00, 0x01, 0xFF, // Node flags (all set) + 0x04, 0x01, 0x00, 0x03, 0x01, 0x02, 0x03, // Opaque Node Attr [1 2 3] + 0x04, 0x02, 0x00, 0x03, 0x72, 0x74, 0x72, // Node name: "rtr" + 0x04, 0x03, 0x00, 0x03, 0x72, 0x74, 0x72, // ISIS area: [114 116 114] + 0x04, 0x04, 0x00, 0x04, 0x01, 0x01, 0x01, 0x01, // Local RouterID 1.1.1.1 + 0x04, 0x05, 0x00, 0x10, 0x20, 0x01, 0x0d, 0xb8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xBE, 0xEF, // Local Router ID 2001:db8::beef + 0x04, 0x0a, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x88, 0xb8, 0x04, 0x89, 0x00, 0x03, 0x01, 0x88, 0x94, // Capabilities: Range 35000, first label: 100500 + 0x04, 0x0b, 0x00, 0x03, 0x01, 0x02, 0x03, // SR ALgorithm [1 2 3] + 0x04, 0x0c, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x88, 0xb8, 0x04, 0x89, 0x00, 0x03, 0x01, 0x88, 0x94, // Local block: Range 35000, first label: 100500 + 0xde, 0xad, 0x00, 0x01, 0xFF, // Unknown TLV + }, + "{LsAttributes: {Node Flags: XXVRBETO} {Opaque attribute: [1 2 3]} {Node Name: rtr} {ISIS Area ID: [114 116 114]} {Local RouterID IPv4: 1.1.1.1} {Local RouterID IPv6: 2001:db8::beef} {SR Capabilities: Flags:0 SRGB Ranges: 100500:135500 } {SR Algorithms: [1 2 3]} {SR LocalBlock: Flags:0 SRGB Ranges: 100500:135500 } }", + `{"type":41,"flags":128,"node":{"flags":{"overload":true,"attached":true,"external":true,"abr":true,"router":true,"v6":true},"opaque":"AQID","name":"rtr","isis_area":"cnRy","local_router_id_ipv4":"1.1.1.1","local_router_id_ipv6":"2001:db8::beef","sr_capabilities":{"ipv4_supported":false,"ipv6_supported":false,"ranges":[{"begin":100500,"end":135500}]},"sr_algorithms":"AQID","sr_local_block":{"ranges":[{"begin":100500,"end":135500}]}},"link":{"local_router_id_ipv4":"1.1.1.1","local_router_id_ipv6":"2001:db8::beef"},"prefix":{}}`, + false, false}, + {[]byte{ + // LS Attribute with all Node-related TLVs. + 0x80, 0x29, 0x5d, // Optional attribute, BGP_ATTR_TYPE_LS, correct length + 0x04, 0x00, 0x00, 0x01, 0xFF, // Node flags (all set) + 0x04, 0x01, 0x00, 0x03, 0x01, 0x02, 0x03, // Opaque Node Attr [1 2 3] + 0x04, 0x02, 0x00, 0x03, 0x72, 0x74, 0x72, // Node name: "rtr" + 0x04, 0x03, 0x00, 0x03, 0x72, 0x74, 0x72, // ISIS area: [114 116 114] + 0x04, 0x04, 0x00, 0x04, 0x01, 0x01, 0x01, 0x01, // Local RouterID 1.1.1.1 + 0x04, 0x05, 0x00, 0x10, 0x20, 0x01, 0x0d, 0xb8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xBE, 0xEF, // Local Router ID 2001:db8::beef + 0x04, 0x0a, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x88, 0xb8, 0x04, 0x89, 0x00, 0x03, 0x01, 0x88, 0x94, // Capabilities: Range 35000, first label: 100500 + 0x04, 0x0b, 0x00, 0x03, 0x01, 0x02, 0x03, // SR Algorithm [1 2 3] + 0x04, 0x0c, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x88, 0xb8, 0x04, 0x89, 0x00, 0x03, 0x01, 0x88, 0x94, // Local block: Range 35000, first label: 100500 + }, + "{LsAttributes: {Node Flags: XXVRBETO} {Opaque attribute: [1 2 3]} {Node Name: rtr} {ISIS Area ID: [114 116 114]} {Local RouterID IPv4: 1.1.1.1} {Local RouterID IPv6: 2001:db8::beef} {SR Capabilities: Flags:0 SRGB Ranges: 100500:135500 } {SR Algorithms: [1 2 3]} {SR LocalBlock: Flags:0 SRGB Ranges: 100500:135500 } }", + `{"type":41,"flags":128,"node":{"flags":{"overload":true,"attached":true,"external":true,"abr":true,"router":true,"v6":true},"opaque":"AQID","name":"rtr","isis_area":"cnRy","local_router_id_ipv4":"1.1.1.1","local_router_id_ipv6":"2001:db8::beef","sr_capabilities":{"ipv4_supported":false,"ipv6_supported":false,"ranges":[{"begin":100500,"end":135500}]},"sr_algorithms":"AQID","sr_local_block":{"ranges":[{"begin":100500,"end":135500}]}},"link":{"local_router_id_ipv4":"1.1.1.1","local_router_id_ipv6":"2001:db8::beef"},"prefix":{}}`, + true, false}, + {[]byte{ + // LS Attribute with truncated length + 0x80, 0x29, 0x04, // Optional attribute, BGP_ATTR_TYPE_LS, truncated length + 0x04, 0x00, 0x00, 0x01, 0xFF, // Node flags (all set) + }, "", "", false, true}, + {[]byte{ + // LS Attribute with all Link-related TLVs. + 0x80, 0x29, 0x9a, // Optional attribute, BGP_ATTR_TYPE_LS, correct length + 0x04, 0x04, 0x00, 0x04, 0x01, 0x01, 0x01, 0x01, // Local RouterID 1.1.1.1 + 0x04, 0x05, 0x00, 0x10, 0x20, 0x01, 0x0d, 0xb8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xBE, 0xEF, // Local Router ID 2001:db8::beef + 0x04, 0x06, 0x00, 0x04, 0x02, 0x02, 0x02, 0x02, // Local RouterID 2.2.2.2 + 0x04, 0x07, 0x00, 0x10, 0x20, 0x01, 0x0d, 0xb8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xDE, 0xAD, // Local Router ID 2001:db8::dead + 0x04, 0x40, 0x00, 0x04, 0x07, 0x07, 0x07, 0x07, // Admin Group 0x07070707 + 0x04, 0x41, 0x00, 0x04, 0x43, 0xA4, 0xB2, 0x00, // Max Link Bandwidth 329.39062 + 0x04, 0x42, 0x00, 0x04, 0x43, 0xA4, 0xB2, 0x00, // Max Reservable Bandwidth 329.39062 + 0x04, 0x43, 0x00, 0x20, 0x43, 0xA4, 0xB2, 0x00, 0x43, 0xA4, 0xB2, 0x00, 0x43, 0xA4, 0xB2, 0x00, 0x43, 0xA4, 0xB2, 0x00, 0x43, 0xA4, 0xB2, 0x00, 0x43, 0xA4, 0xB2, 0x00, 0x43, 0xA4, 0xB2, 0x00, 0x43, 0xA4, 0xB2, 0x00, // Unreserved Bandwidth 329.39062 + 0x04, 0x44, 0x00, 0x04, 0x07, 0x07, 0x07, 0x07, // TE Default Metric: 117901063 + 0x04, 0x47, 0x00, 0x01, 0x01, // IGP Metric 1 + 0x04, 0x49, 0x00, 0x03, 0x01, 0x02, 0x03, // Opaque Link Attr: [1 2 3] + 0x04, 0x4a, 0x00, 0x03, 0x72, 0x74, 0x72, // Link Name: "rtr" + 0x04, 0x4b, 0x00, 0x07, 0x01, 0x01, 0x00, 0x00, 0x01, 0x88, 0x94, // Adjacency SID: 100500 + }, + "{LsAttributes: {Local RouterID IPv4: 1.1.1.1} {Local RouterID IPv6: 2001:db8::beef} {Remote RouterID IPv4: 2.2.2.2} {Remote RouterID IPv6: 2001:db8::dead} {Admin Group: 07070707} {Max Link BW: 329.39062} {Max Reservable Link BW: 329.39062} {Unreserved BW: [329.39062 329.39062 329.39062 329.39062 329.39062 329.39062 329.39062 329.39062]} {TE Default metric: 117901063} {IGP metric: 1} {Opaque link attribute: [1 2 3]} {Link Name: rtr} {Adjacency SID: 100500} }", + `{"type":41,"flags":128,"node":{"local_router_id_ipv4":"1.1.1.1","local_router_id_ipv6":"2001:db8::beef"},"link":{"name":"rtr","local_router_id_ipv4":"1.1.1.1","local_router_id_ipv6":"2001:db8::beef","remote_router_id_ipv4":"2.2.2.2","remote_router_id_ipv6":"2001:db8::dead","admin_group":117901063,"default_te_metric":117901063,"igp_metric":1,"opaque":"AQID","bandwidth":329.39062,"reservable_bandwidth":329.39062,"unreserved_bandwidth":[329.39062,329.39062,329.39062,329.39062,329.39062,329.39062,329.39062,329.39062],"adjacency_sid":100500},"prefix":{}}`, + true, false}, + {[]byte{ + // LS Attribute with all Link-related TLVs. + 0x80, 0x29, 0x17, // Optional attribute, BGP_ATTR_TYPE_LS, correct length + 0x04, 0x80, 0x00, 0x01, 0xFF, // IGP Flags: PLND + 0x04, 0x85, 0x00, 0x03, 0x01, 0x02, 0x03, // Opaque prefix: [1 2 3] + 0x04, 0x86, 0x00, 0x07, 0x01, 0x01, 0x00, 0x00, 0x01, 0x88, 0x94, // Prefix SID: 100500 + }, + "{LsAttributes: {IGP Flags: XXXXPLND} {Prefix opaque attribute: [1 2 3]} {Prefix SID: 100500} }", + `{"type":41,"flags":128,"node":{},"link":{},"prefix":{"igp_flags":{"down":true,"no_unicast":true,"local_address":true,"propagate_nssa":true},"opaque":"AQID","sr_prefix_sid":100500}}`, + true, false}, + } + + for _, test := range tests { + attr := PathAttributeLs{} + if test.err { + assert.Error(attr.DecodeFromBytes(test.in)) + } else { + assert.NoError(attr.DecodeFromBytes(test.in)) + got, err := attr.MarshalJSON() + assert.NoError(err) + assert.Equal(test.json, string(got)) + assert.Equal(test.str, attr.String()) + + if test.serialize { + got, err := attr.Serialize() + assert.NoError(err) + assert.Equal(test.in, got) + } + } + } +} diff --git a/tools/pyang_plugins/gobgp.yang b/tools/pyang_plugins/gobgp.yang index 639edd10..fd75bef3 100644 --- a/tools/pyang_plugins/gobgp.yang +++ b/tools/pyang_plugins/gobgp.yang @@ -148,6 +148,13 @@ module gobgp { reference "https://tools.ietf.org/html/draft-lapukhov-bgp-opaque-signaling-01"; } + identity LS { + base bgp-types:afi-safi-type; + description + "Linkstate (AFI,SAFI = 16388,71)"; + reference "RFC7752"; + } + grouping gobgp-message-counter { description "Counters for all BGPMessage types"; diff --git a/tools/spell-check/dictionary.txt b/tools/spell-check/dictionary.txt index fd4897ee..b3dab1dc 100644 --- a/tools/spell-check/dictionary.txt +++ b/tools/spell-check/dictionary.txt @@ -16,6 +16,7 @@ gobgpd grpc ibgp ipproto +isis keepalive keepalives llgr @@ -28,12 +29,15 @@ mututally nexthop nexthops nlri +ospf pmsi prepend reachability +reservable rpki sadb safi +srgb subcode syscall syslog -- cgit v1.2.3