Add unit tests

This commit is contained in:
Mayuresh Gaitonde
2020-12-17 17:25:53 -08:00
parent 3702339f44
commit 6be4d69d02
705 changed files with 120529 additions and 150051 deletions

File diff suppressed because it is too large Load Diff

View File

@@ -26,221 +26,214 @@ import "gobgp.proto";
package gobgpapi;
message OriginAttribute {
uint32 origin = 1;
}
message OriginAttribute { uint32 origin = 1; }
message AsSegment {
uint32 type = 1;
repeated uint32 numbers = 2;
uint32 type = 1;
repeated uint32 numbers = 2;
}
message AsPathAttribute {
repeated AsSegment segments = 1;
}
message AsPathAttribute { repeated AsSegment segments = 1; }
message NextHopAttribute {
string next_hop = 1;
}
message NextHopAttribute { string next_hop = 1; }
message MultiExitDiscAttribute {
uint32 med = 1;
}
message MultiExitDiscAttribute { uint32 med = 1; }
message LocalPrefAttribute {
uint32 local_pref = 1;
}
message LocalPrefAttribute { uint32 local_pref = 1; }
message AtomicAggregateAttribute {
}
message AtomicAggregateAttribute {}
message AggregatorAttribute {
uint32 as = 2;
string address = 3;
uint32 as = 2;
string address = 3;
}
message CommunitiesAttribute {
repeated uint32 communities = 1;
}
message CommunitiesAttribute { repeated uint32 communities = 1; }
message OriginatorIdAttribute {
string id = 1;
}
message OriginatorIdAttribute { string id = 1; }
message ClusterListAttribute {
repeated string ids = 1;
}
message ClusterListAttribute { repeated string ids = 1; }
// IPAddressPrefix represents the NLRI for:
// - AFI=1, SAFI=1
// - AFI=2, SAFI=1
message IPAddressPrefix {
uint32 prefix_len = 1;
string prefix = 2;
uint32 prefix_len = 1;
string prefix = 2;
}
// LabeledIPAddressPrefix represents the NLRI for:
// - AFI=1, SAFI=4
// - AFI=2, SAFI=4
message LabeledIPAddressPrefix {
repeated uint32 labels = 1;
uint32 prefix_len = 2;
string prefix = 3;
repeated uint32 labels = 1;
uint32 prefix_len = 2;
string prefix = 3;
}
// EncapsulationNLRI represents the NLRI for:
// - AFI=1, SAFI=7
// - AFI=2, SAFI=7
message EncapsulationNLRI {
string address = 1;
}
message EncapsulationNLRI { string address = 1; }
message RouteDistinguisherTwoOctetAS {
uint32 admin = 1;
uint32 assigned = 2;
uint32 admin = 1;
uint32 assigned = 2;
}
message RouteDistinguisherIPAddress {
string admin = 1;
uint32 assigned = 2;
string admin = 1;
uint32 assigned = 2;
}
message RouteDistinguisherFourOctetAS {
uint32 admin = 1;
uint32 assigned = 2;
uint32 admin = 1;
uint32 assigned = 2;
}
message EthernetSegmentIdentifier {
uint32 type = 1;
bytes value = 2;
uint32 type = 1;
bytes value = 2;
}
// EVPNEthernetAutoDiscoveryRoute represents the NLRI for:
// - AFI=25, SAFI=70, RouteType=1
message EVPNEthernetAutoDiscoveryRoute {
// One of:
// - RouteDistinguisherTwoOctetAS
// - RouteDistinguisherIPAddressAS
// - RouteDistinguisherFourOctetAS
google.protobuf.Any rd = 1;
EthernetSegmentIdentifier esi = 2;
uint32 ethernet_tag = 3;
uint32 label = 4;
// One of:
// - RouteDistinguisherTwoOctetAS
// - RouteDistinguisherIPAddressAS
// - RouteDistinguisherFourOctetAS
google.protobuf.Any rd = 1;
EthernetSegmentIdentifier esi = 2;
uint32 ethernet_tag = 3;
uint32 label = 4;
}
// EVPNMACIPAdvertisementRoute represents the NLRI for:
// - AFI=25, SAFI=70, RouteType=2
message EVPNMACIPAdvertisementRoute {
// One of:
// - RouteDistinguisherTwoOctetAS
// - RouteDistinguisherIPAddressAS
// - RouteDistinguisherFourOctetAS
google.protobuf.Any rd = 1;
EthernetSegmentIdentifier esi = 2;
uint32 ethernet_tag = 3;
string mac_address = 4;
string ip_address = 5;
repeated uint32 labels = 6;
// One of:
// - RouteDistinguisherTwoOctetAS
// - RouteDistinguisherIPAddressAS
// - RouteDistinguisherFourOctetAS
google.protobuf.Any rd = 1;
EthernetSegmentIdentifier esi = 2;
uint32 ethernet_tag = 3;
string mac_address = 4;
string ip_address = 5;
repeated uint32 labels = 6;
}
// EVPNInclusiveMulticastEthernetTagRoute represents the NLRI for:
// - AFI=25, SAFI=70, RouteType=3
message EVPNInclusiveMulticastEthernetTagRoute {
// One of:
// - RouteDistinguisherTwoOctetAS
// - RouteDistinguisherIPAddressAS
// - RouteDistinguisherFourOctetAS
google.protobuf.Any rd = 1;
uint32 ethernet_tag = 2;
string ip_address = 3;
// One of:
// - RouteDistinguisherTwoOctetAS
// - RouteDistinguisherIPAddressAS
// - RouteDistinguisherFourOctetAS
google.protobuf.Any rd = 1;
uint32 ethernet_tag = 2;
string ip_address = 3;
}
// EVPNEthernetSegmentRoute represents the NLRI for:
// - AFI=25, SAFI=70, RouteType=4
message EVPNEthernetSegmentRoute {
// One of:
// - RouteDistinguisherTwoOctetAS
// - RouteDistinguisherIPAddressAS
// - RouteDistinguisherFourOctetAS
google.protobuf.Any rd = 1;
EthernetSegmentIdentifier esi = 2;
string ip_address = 3;
// One of:
// - RouteDistinguisherTwoOctetAS
// - RouteDistinguisherIPAddressAS
// - RouteDistinguisherFourOctetAS
google.protobuf.Any rd = 1;
EthernetSegmentIdentifier esi = 2;
string ip_address = 3;
}
// EVPNIPPrefixRoute represents the NLRI for:
// - AFI=25, SAFI=70, RouteType=5
message EVPNIPPrefixRoute {
// One of:
// - RouteDistinguisherTwoOctetAS
// - RouteDistinguisherIPAddressAS
// - RouteDistinguisherFourOctetAS
google.protobuf.Any rd = 1;
EthernetSegmentIdentifier esi = 2;
uint32 ethernet_tag = 3;
string ip_prefix = 4;
uint32 ip_prefix_len = 5;
string gw_address = 6;
uint32 label = 7;
// One of:
// - RouteDistinguisherTwoOctetAS
// - RouteDistinguisherIPAddressAS
// - RouteDistinguisherFourOctetAS
google.protobuf.Any rd = 1;
EthernetSegmentIdentifier esi = 2;
uint32 ethernet_tag = 3;
string ip_prefix = 4;
uint32 ip_prefix_len = 5;
string gw_address = 6;
uint32 label = 7;
}
// EVPNIPMSIRoute represents the NLRI for:
// - AFI=25, SAFI=70, RouteType=9
message EVPNIPMSIRoute {
// One of:
// - RouteDistinguisherTwoOctetAS
// - RouteDistinguisherIPAddressAS
// - RouteDistinguisherFourOctetAS
google.protobuf.Any rd = 1;
uint32 ethernet_tag = 2;
google.protobuf.Any rt = 3;
}
// LabeledVPNIPAddressPrefix represents the NLRI for:
// - AFI=1, SAFI=128
// - AFI=2, SAFI=128
message LabeledVPNIPAddressPrefix {
repeated uint32 labels = 1;
// One of:
// - TwoOctetAsSpecificExtended
// - IPv4AddressSpecificExtended
// - FourOctetAsSpecificExtended
google.protobuf.Any rd = 2;
uint32 prefix_len = 3;
string prefix = 4;
repeated uint32 labels = 1;
// One of:
// - TwoOctetAsSpecificExtended
// - IPv4AddressSpecificExtended
// - FourOctetAsSpecificExtended
google.protobuf.Any rd = 2;
uint32 prefix_len = 3;
string prefix = 4;
}
// RouteTargetMembershipNLRI represents the NLRI for:
// - AFI=1, SAFI=132
message RouteTargetMembershipNLRI {
uint32 as = 1;
// One of:
// - TwoOctetAsSpecificExtended
// - IPv4AddressSpecificExtended
// - FourOctetAsSpecificExtended
google.protobuf.Any rt = 2;
uint32 as = 1;
// One of:
// - TwoOctetAsSpecificExtended
// - IPv4AddressSpecificExtended
// - FourOctetAsSpecificExtended
google.protobuf.Any rt = 2;
}
message FlowSpecIPPrefix {
uint32 type = 1;
uint32 prefix_len = 2;
string prefix = 3;
// IPv6 only
uint32 offset = 4;
uint32 type = 1;
uint32 prefix_len = 2;
string prefix = 3;
// IPv6 only
uint32 offset = 4;
}
message FlowSpecMAC {
uint32 type = 1;
string address = 2;
uint32 type = 1;
string address = 2;
}
message FlowSpecComponentItem {
// Operator for Numeric type, Operand for Bitmask type
uint32 op = 1;
uint64 value = 2;
// Operator for Numeric type, Operand for Bitmask type
uint32 op = 1;
uint64 value = 2;
}
message FlowSpecComponent {
uint32 type = 1;
repeated FlowSpecComponentItem items = 2;
uint32 type = 1;
repeated FlowSpecComponentItem items = 2;
}
// FlowSpecNLRI represents the NLRI for:
// - AFI=1, SAFI=133
// - AFI=2, SAFI=133
message FlowSpecNLRI {
// One of:
// - FlowSpecIPPrefix
// - FlowSpecMAC
// - FlowSpecComponent
repeated google.protobuf.Any rules = 1;
// One of:
// - FlowSpecIPPrefix
// - FlowSpecMAC
// - FlowSpecComponent
repeated google.protobuf.Any rules = 1;
}
// VPNFlowSpecNLRI represents the NLRI for:
@@ -248,258 +241,414 @@ message FlowSpecNLRI {
// - AFI=2, SAFI=134
// - AFI=25, SAFI=134
message VPNFlowSpecNLRI {
// One of:
// - RouteDistinguisherTwoOctetAS
// - RouteDistinguisherIPAddressAS
// - RouteDistinguisherFourOctetAS
google.protobuf.Any rd = 1;
// One of:
// - FlowSpecIPPrefix
// - FlowSpecMAC
// - FlowSpecComponent
repeated google.protobuf.Any rules = 2;
// One of:
// - RouteDistinguisherTwoOctetAS
// - RouteDistinguisherIPAddressAS
// - RouteDistinguisherFourOctetAS
google.protobuf.Any rd = 1;
// One of:
// - FlowSpecIPPrefix
// - FlowSpecMAC
// - FlowSpecComponent
repeated google.protobuf.Any rules = 2;
}
// OpaqueNLRI represents the NLRI for:
// - AFI=16397, SAFI=241
message OpaqueNLRI {
bytes key = 1;
bytes value = 2;
bytes key = 1;
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;
// Each NLRI must be one of:
// - IPAddressPrefix
// - LabeledIPAddressPrefix
// - EncapsulationNLRI
// - EVPNEthernetAutoDiscoveryRoute
// - EVPNMACIPAdvertisementRoute
// - EVPNInclusiveMulticastEthernetTagRoute
// - EVPNEthernetSegmentRoute
// - EVPNIPPrefixRoute
// - LabeledVPNIPAddressPrefix
// - RouteTargetMembershipNLRI
// - FlowSpecNLRI
// - VPNFlowSpecNLRI
// - OpaqueNLRI
repeated google.protobuf.Any nlris = 3;
gobgpapi.Family family = 1;
repeated string next_hops = 2;
// Each NLRI must be one of:
// - IPAddressPrefix
// - LabeledIPAddressPrefix
// - EncapsulationNLRI
// - EVPNEthernetAutoDiscoveryRoute
// - EVPNMACIPAdvertisementRoute
// - EVPNInclusiveMulticastEthernetTagRoute
// - EVPNEthernetSegmentRoute
// - EVPNIPPrefixRoute
// - EVPNIPMSIRoute
// - LabeledVPNIPAddressPrefix
// - RouteTargetMembershipNLRI
// - FlowSpecNLRI
// - VPNFlowSpecNLRI
// - OpaqueNLRI
// - LsAddrPrefix
repeated google.protobuf.Any nlris = 3;
}
message MpUnreachNLRIAttribute {
gobgpapi.Family family = 1;
// The same as NLRI field of MpReachNLRIAttribute
repeated google.protobuf.Any nlris = 3;
gobgpapi.Family family = 1;
// The same as NLRI field of MpReachNLRIAttribute
repeated google.protobuf.Any nlris = 3;
}
message TwoOctetAsSpecificExtended {
bool is_transitive = 1;
uint32 sub_type = 2;
uint32 as = 3;
uint32 local_admin = 4;
bool is_transitive = 1;
uint32 sub_type = 2;
uint32 as = 3;
uint32 local_admin = 4;
}
message IPv4AddressSpecificExtended {
bool is_transitive = 1;
uint32 sub_type = 2;
string address = 3;
uint32 local_admin = 4;
bool is_transitive = 1;
uint32 sub_type = 2;
string address = 3;
uint32 local_admin = 4;
}
message FourOctetAsSpecificExtended {
bool is_transitive = 1;
uint32 sub_type = 2;
uint32 as = 3;
uint32 local_admin = 4;
bool is_transitive = 1;
uint32 sub_type = 2;
uint32 as = 3;
uint32 local_admin = 4;
}
message ValidationExtended {
uint32 state = 1;
}
message ValidationExtended { uint32 state = 1; }
message ColorExtended {
uint32 color = 1;
}
message ColorExtended { uint32 color = 1; }
message EncapExtended {
uint32 tunnel_type = 1;
}
message EncapExtended { uint32 tunnel_type = 1; }
message DefaultGatewayExtended {
}
message DefaultGatewayExtended {}
message OpaqueExtended {
bool is_transitive = 1;
bytes value = 3;
bool is_transitive = 1;
bytes value = 3;
}
message ESILabelExtended {
bool is_single_active = 1;
uint32 label = 2;
bool is_single_active = 1;
uint32 label = 2;
}
message ESImportRouteTarget {
string es_import = 1;
}
message ESImportRouteTarget { string es_import = 1; }
message MacMobilityExtended {
bool is_sticky = 1;
uint32 sequence_num = 2;
bool is_sticky = 1;
uint32 sequence_num = 2;
}
message RouterMacExtended {
string mac = 1;
}
message RouterMacExtended { string mac = 1; }
message TrafficRateExtended {
uint32 as = 1;
float rate = 2;
uint32 as = 1;
float rate = 2;
}
message TrafficActionExtended {
bool terminal = 1;
bool sample = 2;
bool terminal = 1;
bool sample = 2;
}
message RedirectTwoOctetAsSpecificExtended {
uint32 as = 1;
uint32 local_admin = 2;
uint32 as = 1;
uint32 local_admin = 2;
}
message RedirectIPv4AddressSpecificExtended {
string address = 1;
uint32 local_admin = 2;
string address = 1;
uint32 local_admin = 2;
}
message RedirectFourOctetAsSpecificExtended {
uint32 as = 1;
uint32 local_admin = 2;
uint32 as = 1;
uint32 local_admin = 2;
}
message TrafficRemarkExtended {
uint32 dscp = 1;
}
message TrafficRemarkExtended { uint32 dscp = 1; }
message UnknownExtended {
uint32 type = 1;
bytes value = 2;
uint32 type = 1;
bytes value = 2;
}
message ExtendedCommunitiesAttribute {
// Each Community must be one of:
// - TwoOctetAsSpecificExtended
// - IPv4AddressSpecificExtended
// - FourOctetAsSpecificExtended
// - OpaqueExtended
// - ESILabelExtended
// - MacMobilityExtended
// - RouterMacExtended
// - TrafficRateExtended
// - TrafficActionExtended
// - RedirectTwoOctetAsSpecificExtended
// - RedirectIPv4AddressSpecificExtended
// - RedirectFourOctetAsSpecificExtended
// - TrafficRemarkExtended
// - UnknownExtended
repeated google.protobuf.Any communities = 1;
// Each Community must be one of:
// - TwoOctetAsSpecificExtended
// - IPv4AddressSpecificExtended
// - FourOctetAsSpecificExtended
// - OpaqueExtended
// - ESILabelExtended
// - MacMobilityExtended
// - RouterMacExtended
// - TrafficRateExtended
// - TrafficActionExtended
// - RedirectTwoOctetAsSpecificExtended
// - RedirectIPv4AddressSpecificExtended
// - RedirectFourOctetAsSpecificExtended
// - TrafficRemarkExtended
// - UnknownExtended
repeated google.protobuf.Any communities = 1;
}
message As4PathAttribute {
repeated AsSegment segments = 1;
}
message As4PathAttribute { repeated AsSegment segments = 1; }
message As4AggregatorAttribute {
uint32 as = 2;
string address = 3;
uint32 as = 2;
string address = 3;
}
message PmsiTunnelAttribute {
uint32 flags = 1;
uint32 type = 2;
uint32 label = 3;
bytes id = 4;
uint32 flags = 1;
uint32 type = 2;
uint32 label = 3;
bytes id = 4;
}
message TunnelEncapSubTLVEncapsulation {
uint32 key = 1;
bytes cookie = 2;
uint32 key = 1;
bytes cookie = 2;
}
message TunnelEncapSubTLVProtocol {
uint32 protocol = 1;
}
message TunnelEncapSubTLVProtocol { uint32 protocol = 1; }
message TunnelEncapSubTLVColor {
uint32 color = 1;
}
message TunnelEncapSubTLVColor { uint32 color = 1; }
message TunnelEncapSubTLVUnknown {
uint32 type = 1;
bytes value = 2;
uint32 type = 1;
bytes value = 2;
}
message TunnelEncapTLV {
uint32 type = 1;
// Each TLV must be one of:
// - TunnelEncapSubTLVEncapsulation
// - TunnelEncapSubTLVProtocol
// - TunnelEncapSubTLVColor
// - TunnelEncapSubTLVUnknown
repeated google.protobuf.Any tlvs = 2;
uint32 type = 1;
// Each TLV must be one of:
// - TunnelEncapSubTLVEncapsulation
// - TunnelEncapSubTLVProtocol
// - TunnelEncapSubTLVColor
// - TunnelEncapSubTLVUnknown
repeated google.protobuf.Any tlvs = 2;
}
message TunnelEncapAttribute {
repeated TunnelEncapTLV tlvs = 1;
}
message TunnelEncapAttribute { repeated TunnelEncapTLV tlvs = 1; }
message IPv6AddressSpecificExtended {
bool is_transitive = 1;
uint32 sub_type = 2;
string address = 3;
uint32 local_admin = 4;
bool is_transitive = 1;
uint32 sub_type = 2;
string address = 3;
uint32 local_admin = 4;
}
message RedirectIPv6AddressSpecificExtended {
string address = 1;
uint32 local_admin = 2;
string address = 1;
uint32 local_admin = 2;
}
message IP6ExtendedCommunitiesAttribute {
// Each Community must be one of:
// - IPv6AddressSpecificExtended
// - RedirectIPv6AddressSpecificExtended
repeated google.protobuf.Any communities = 1;
// Each Community must be one of:
// - IPv6AddressSpecificExtended
// - RedirectIPv6AddressSpecificExtended
repeated google.protobuf.Any communities = 1;
}
message AigpTLVIGPMetric {
uint64 metric = 1;
}
message AigpTLVIGPMetric { uint64 metric = 1; }
message AigpTLVUnknown {
uint32 type = 1;
bytes value = 2;
uint32 type = 1;
bytes value = 2;
}
message AigpAttribute {
// Each TLV must be one of:
// - AigpTLVIGPMetric
// - AigpTLVUnknown
repeated google.protobuf.Any tlvs = 1;
// Each TLV must be one of:
// - AigpTLVIGPMetric
// - AigpTLVUnknown
repeated google.protobuf.Any tlvs = 1;
}
message LargeCommunity {
uint32 global_admin = 1;
uint32 local_data1 = 2;
uint32 local_data2 = 3;
uint32 global_admin = 1;
uint32 local_data1 = 2;
uint32 local_data2 = 3;
}
message LargeCommunitiesAttribute {
repeated LargeCommunity communities = 1;
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;
repeated uint32 srlgs = 14;
}
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;
bytes value = 3;
uint32 flags = 1;
uint32 type = 2;
bytes value = 3;
}
// https://tools.ietf.org/html/draft-dawra-bess-srv6-services-02#section-2.1.1
message SRv6StructureSubSubTLV {
uint32 local_block_length = 1;
uint32 local_node_length = 2;
uint32 function_length = 3;
uint32 argument_length = 4;
uint32 transposition_length = 5;
uint32 transposition_offset = 6;
}
message SRv6SIDFlags {
// Placeholder for future sid flags
bool flag_1 = 1;
}
message SRv6TLV { repeated google.protobuf.Any tlv = 1; }
// https://tools.ietf.org/html/draft-dawra-bess-srv6-services-02#section-2.1.1
message SRv6InformationSubTLV {
bytes sid = 1;
SRv6SIDFlags flags = 2;
uint32 endpoint_behavior = 3;
// SRv6TLV is one of:
// - SRv6StructureSubSubTLV
map<uint32, SRv6TLV> sub_sub_tlvs = 4;
}
// https://tools.ietf.org/html/draft-dawra-bess-srv6-services-02#section-2
message SRv6L3ServiceTLV {
// SRv6TLV is one of:
// - SRv6InformationSubTLV
map<uint32, SRv6TLV> sub_tlvs = 1;
}
// https://tools.ietf.org/html/rfc8669
message PrefixSID {
// tlv is one of:
// - IndexLabelTLV Type 1 (not yet implemented)
// - OriginatorSRGBTLV Type 3 (not yet implemented)
// - SRv6L3ServiceTLV Type 5
// - SRv6L2ServiceTLV Type 6 (not yet implemented)
repeated google.protobuf.Any tlvs = 1;
}

View File

@@ -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
@@ -38,7 +37,7 @@ var AddPathMode_value = map[string]int32{
func (x AddPathMode) String() string {
return proto.EnumName(AddPathMode_name, int32(x))
}
func (AddPathMode) EnumDescriptor() ([]byte, []int) { return fileDescriptor2, []int{0} }
func (AddPathMode) EnumDescriptor() ([]byte, []int) { return fileDescriptor1, []int{0} }
type MultiProtocolCapability struct {
Family *Family `protobuf:"bytes,1,opt,name=family" json:"family,omitempty"`
@@ -47,7 +46,7 @@ type MultiProtocolCapability struct {
func (m *MultiProtocolCapability) Reset() { *m = MultiProtocolCapability{} }
func (m *MultiProtocolCapability) String() string { return proto.CompactTextString(m) }
func (*MultiProtocolCapability) ProtoMessage() {}
func (*MultiProtocolCapability) Descriptor() ([]byte, []int) { return fileDescriptor2, []int{0} }
func (*MultiProtocolCapability) Descriptor() ([]byte, []int) { return fileDescriptor1, []int{0} }
func (m *MultiProtocolCapability) GetFamily() *Family {
if m != nil {
@@ -62,7 +61,7 @@ type RouteRefreshCapability struct {
func (m *RouteRefreshCapability) Reset() { *m = RouteRefreshCapability{} }
func (m *RouteRefreshCapability) String() string { return proto.CompactTextString(m) }
func (*RouteRefreshCapability) ProtoMessage() {}
func (*RouteRefreshCapability) Descriptor() ([]byte, []int) { return fileDescriptor2, []int{1} }
func (*RouteRefreshCapability) Descriptor() ([]byte, []int) { return fileDescriptor1, []int{1} }
type CarryingLabelInfoCapability struct {
}
@@ -70,7 +69,7 @@ type CarryingLabelInfoCapability struct {
func (m *CarryingLabelInfoCapability) Reset() { *m = CarryingLabelInfoCapability{} }
func (m *CarryingLabelInfoCapability) String() string { return proto.CompactTextString(m) }
func (*CarryingLabelInfoCapability) ProtoMessage() {}
func (*CarryingLabelInfoCapability) Descriptor() ([]byte, []int) { return fileDescriptor2, []int{2} }
func (*CarryingLabelInfoCapability) Descriptor() ([]byte, []int) { return fileDescriptor1, []int{2} }
type ExtendedNexthopCapabilityTuple struct {
NlriFamily *Family `protobuf:"bytes,1,opt,name=nlri_family,json=nlriFamily" json:"nlri_family,omitempty"`
@@ -83,7 +82,7 @@ type ExtendedNexthopCapabilityTuple struct {
func (m *ExtendedNexthopCapabilityTuple) Reset() { *m = ExtendedNexthopCapabilityTuple{} }
func (m *ExtendedNexthopCapabilityTuple) String() string { return proto.CompactTextString(m) }
func (*ExtendedNexthopCapabilityTuple) ProtoMessage() {}
func (*ExtendedNexthopCapabilityTuple) Descriptor() ([]byte, []int) { return fileDescriptor2, []int{3} }
func (*ExtendedNexthopCapabilityTuple) Descriptor() ([]byte, []int) { return fileDescriptor1, []int{3} }
func (m *ExtendedNexthopCapabilityTuple) GetNlriFamily() *Family {
if m != nil {
@@ -106,7 +105,7 @@ type ExtendedNexthopCapability struct {
func (m *ExtendedNexthopCapability) Reset() { *m = ExtendedNexthopCapability{} }
func (m *ExtendedNexthopCapability) String() string { return proto.CompactTextString(m) }
func (*ExtendedNexthopCapability) ProtoMessage() {}
func (*ExtendedNexthopCapability) Descriptor() ([]byte, []int) { return fileDescriptor2, []int{4} }
func (*ExtendedNexthopCapability) Descriptor() ([]byte, []int) { return fileDescriptor1, []int{4} }
func (m *ExtendedNexthopCapability) GetTuples() []*ExtendedNexthopCapabilityTuple {
if m != nil {
@@ -123,7 +122,7 @@ type GracefulRestartCapabilityTuple struct {
func (m *GracefulRestartCapabilityTuple) Reset() { *m = GracefulRestartCapabilityTuple{} }
func (m *GracefulRestartCapabilityTuple) String() string { return proto.CompactTextString(m) }
func (*GracefulRestartCapabilityTuple) ProtoMessage() {}
func (*GracefulRestartCapabilityTuple) Descriptor() ([]byte, []int) { return fileDescriptor2, []int{5} }
func (*GracefulRestartCapabilityTuple) Descriptor() ([]byte, []int) { return fileDescriptor1, []int{5} }
func (m *GracefulRestartCapabilityTuple) GetFamily() *Family {
if m != nil {
@@ -148,7 +147,7 @@ type GracefulRestartCapability struct {
func (m *GracefulRestartCapability) Reset() { *m = GracefulRestartCapability{} }
func (m *GracefulRestartCapability) String() string { return proto.CompactTextString(m) }
func (*GracefulRestartCapability) ProtoMessage() {}
func (*GracefulRestartCapability) Descriptor() ([]byte, []int) { return fileDescriptor2, []int{6} }
func (*GracefulRestartCapability) Descriptor() ([]byte, []int) { return fileDescriptor1, []int{6} }
func (m *GracefulRestartCapability) GetFlags() uint32 {
if m != nil {
@@ -178,7 +177,7 @@ type FourOctetASNumberCapability struct {
func (m *FourOctetASNumberCapability) Reset() { *m = FourOctetASNumberCapability{} }
func (m *FourOctetASNumberCapability) String() string { return proto.CompactTextString(m) }
func (*FourOctetASNumberCapability) ProtoMessage() {}
func (*FourOctetASNumberCapability) Descriptor() ([]byte, []int) { return fileDescriptor2, []int{7} }
func (*FourOctetASNumberCapability) Descriptor() ([]byte, []int) { return fileDescriptor1, []int{7} }
func (m *FourOctetASNumberCapability) GetAs() uint32 {
if m != nil {
@@ -195,7 +194,7 @@ type AddPathCapabilityTuple struct {
func (m *AddPathCapabilityTuple) Reset() { *m = AddPathCapabilityTuple{} }
func (m *AddPathCapabilityTuple) String() string { return proto.CompactTextString(m) }
func (*AddPathCapabilityTuple) ProtoMessage() {}
func (*AddPathCapabilityTuple) Descriptor() ([]byte, []int) { return fileDescriptor2, []int{8} }
func (*AddPathCapabilityTuple) Descriptor() ([]byte, []int) { return fileDescriptor1, []int{8} }
func (m *AddPathCapabilityTuple) GetFamily() *Family {
if m != nil {
@@ -218,7 +217,7 @@ type AddPathCapability struct {
func (m *AddPathCapability) Reset() { *m = AddPathCapability{} }
func (m *AddPathCapability) String() string { return proto.CompactTextString(m) }
func (*AddPathCapability) ProtoMessage() {}
func (*AddPathCapability) Descriptor() ([]byte, []int) { return fileDescriptor2, []int{9} }
func (*AddPathCapability) Descriptor() ([]byte, []int) { return fileDescriptor1, []int{9} }
func (m *AddPathCapability) GetTuples() []*AddPathCapabilityTuple {
if m != nil {
@@ -230,10 +229,12 @@ func (m *AddPathCapability) GetTuples() []*AddPathCapabilityTuple {
type EnhancedRouteRefreshCapability struct {
}
func (m *EnhancedRouteRefreshCapability) Reset() { *m = EnhancedRouteRefreshCapability{} }
func (m *EnhancedRouteRefreshCapability) String() string { return proto.CompactTextString(m) }
func (*EnhancedRouteRefreshCapability) ProtoMessage() {}
func (*EnhancedRouteRefreshCapability) Descriptor() ([]byte, []int) { return fileDescriptor2, []int{10} }
func (m *EnhancedRouteRefreshCapability) Reset() { *m = EnhancedRouteRefreshCapability{} }
func (m *EnhancedRouteRefreshCapability) String() string { return proto.CompactTextString(m) }
func (*EnhancedRouteRefreshCapability) ProtoMessage() {}
func (*EnhancedRouteRefreshCapability) Descriptor() ([]byte, []int) {
return fileDescriptor1, []int{10}
}
type LongLivedGracefulRestartCapabilityTuple struct {
Family *Family `protobuf:"bytes,1,opt,name=family" json:"family,omitempty"`
@@ -247,7 +248,7 @@ func (m *LongLivedGracefulRestartCapabilityTuple) Reset() {
func (m *LongLivedGracefulRestartCapabilityTuple) String() string { return proto.CompactTextString(m) }
func (*LongLivedGracefulRestartCapabilityTuple) ProtoMessage() {}
func (*LongLivedGracefulRestartCapabilityTuple) Descriptor() ([]byte, []int) {
return fileDescriptor2, []int{11}
return fileDescriptor1, []int{11}
}
func (m *LongLivedGracefulRestartCapabilityTuple) GetFamily() *Family {
@@ -279,7 +280,7 @@ func (m *LongLivedGracefulRestartCapability) Reset() { *m = LongLivedGra
func (m *LongLivedGracefulRestartCapability) String() string { return proto.CompactTextString(m) }
func (*LongLivedGracefulRestartCapability) ProtoMessage() {}
func (*LongLivedGracefulRestartCapability) Descriptor() ([]byte, []int) {
return fileDescriptor2, []int{12}
return fileDescriptor1, []int{12}
}
func (m *LongLivedGracefulRestartCapability) GetTuples() []*LongLivedGracefulRestartCapabilityTuple {
@@ -295,7 +296,7 @@ type RouteRefreshCiscoCapability struct {
func (m *RouteRefreshCiscoCapability) Reset() { *m = RouteRefreshCiscoCapability{} }
func (m *RouteRefreshCiscoCapability) String() string { return proto.CompactTextString(m) }
func (*RouteRefreshCiscoCapability) ProtoMessage() {}
func (*RouteRefreshCiscoCapability) Descriptor() ([]byte, []int) { return fileDescriptor2, []int{13} }
func (*RouteRefreshCiscoCapability) Descriptor() ([]byte, []int) { return fileDescriptor1, []int{13} }
type UnknownCapability struct {
Code uint32 `protobuf:"varint,1,opt,name=code" json:"code,omitempty"`
@@ -305,7 +306,7 @@ type UnknownCapability struct {
func (m *UnknownCapability) Reset() { *m = UnknownCapability{} }
func (m *UnknownCapability) String() string { return proto.CompactTextString(m) }
func (*UnknownCapability) ProtoMessage() {}
func (*UnknownCapability) Descriptor() ([]byte, []int) { return fileDescriptor2, []int{14} }
func (*UnknownCapability) Descriptor() ([]byte, []int) { return fileDescriptor1, []int{14} }
func (m *UnknownCapability) GetCode() uint32 {
if m != nil {
@@ -340,9 +341,9 @@ func init() {
proto.RegisterEnum("gobgpapi.AddPathMode", AddPathMode_name, AddPathMode_value)
}
func init() { proto.RegisterFile("capability.proto", fileDescriptor2) }
func init() { proto.RegisterFile("capability.proto", fileDescriptor1) }
var fileDescriptor2 = []byte{
var fileDescriptor1 = []byte{
// 520 bytes of a gzipped FileDescriptorProto
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xb4, 0x54, 0x4d, 0x6f, 0xd3, 0x40,
0x10, 0xc5, 0x49, 0x88, 0x60, 0xd2, 0x44, 0xee, 0x0a, 0x4a, 0x4a, 0xd4, 0x28, 0xda, 0x0b, 0x01,

File diff suppressed because it is too large Load Diff

View File

@@ -23,6 +23,7 @@ syntax = "proto3";
import "google/protobuf/any.proto";
import "google/protobuf/empty.proto";
import "google/protobuf/timestamp.proto";
package gobgpapi;
@@ -199,7 +200,7 @@ message AddDynamicNeighborRequest {
}
message AddPathRequest {
Resource resource = 1;
TableType table_type = 1;
string vrf_id = 2;
Path path = 3;
}
@@ -209,7 +210,7 @@ message AddPathResponse {
}
message DeletePathRequest {
Resource resource = 1;
TableType table_type = 1;
string vrf_id = 2;
Family family = 3;
Path path = 4;
@@ -217,10 +218,16 @@ message DeletePathRequest {
}
message ListPathRequest {
Resource type = 1;
TableType table_type = 1;
string name = 2;
Family family = 3;
repeated TableLookupPrefix prefixes = 4;
enum SortType {
NONE = 0;
PREFIX = 1;
}
SortType sort_type = 5;
bool enable_filtered = 6;
}
message ListPathResponse {
@@ -228,13 +235,13 @@ message ListPathResponse {
}
message AddPathStreamRequest {
Resource resource = 1;
TableType table_type = 1;
string vrf_id = 2;
repeated Path paths = 3;
}
message GetTableRequest {
Resource type = 1;
TableType table_type = 1;
Family family = 2;
string name = 3;
}
@@ -246,7 +253,7 @@ message GetTableResponse {
}
message MonitorTableRequest {
Resource type = 1;
TableType table_type = 1;
string name = 2;
Family family = 3;
bool current = 4;
@@ -312,7 +319,7 @@ message DeleteDefinedSetRequest {
}
message ListDefinedSetRequest {
DefinedType type = 1;
DefinedType defined_type = 1;
string name = 2;
}
@@ -408,12 +415,15 @@ message EnableZebraRequest {
uint32 version = 3;
bool nexthop_trigger_enable = 4;
uint32 nexthop_trigger_delay = 5;
uint32 mpls_label_range_size = 6;
string software_name = 7;
}
message EnableMrtRequest {
int32 dump_type = 1;
string filename = 2;
uint64 interval = 3;
uint64 dump_interval = 3;
uint64 rotation_interval = 4;
}
message DisableMrtRequest {
@@ -429,7 +439,10 @@ message AddBmpRequest {
LOCAL = 3;
ALL = 4;
}
MonitoringPolicy type = 3;
MonitoringPolicy policy = 3;
int32 StatisticsTimeout = 4;
string SysName = 5;
string SysDescr = 6;
}
message DeleteBmpRequest {
@@ -443,6 +456,7 @@ message Family {
AFI_IP = 1;
AFI_IP6 = 2;
AFI_L2VPN = 25;
AFI_LS = 16388;
AFI_OPAQUE = 16397;
}
@@ -454,6 +468,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;
@@ -466,7 +481,7 @@ message Family {
Safi safi = 2;
}
enum Resource {
enum TableType {
GLOBAL = 0;
LOCAL = 1;
ADJ_IN = 2;
@@ -474,7 +489,7 @@ enum Resource {
VRF = 4;
}
message RPKIValidation{
message Validation {
enum State {
STATE_NONE = 0;
STATE_NOT_FOUND = 1;
@@ -496,12 +511,30 @@ message RPKIValidation{
}
message Path {
bytes nlri = 1;
repeated bytes pattrs = 2;
int64 age = 3;
// One of the following defined in "api/attribute.proto":
// - IPAddressPrefix
// - LabeledIPAddressPrefix
// - EncapsulationNLRI
// - EVPNEthernetAutoDiscoveryRoute
// - EVPNMACIPAdvertisementRoute
// - EVPNInclusiveMulticastEthernetTagRoute
// - EVPNEthernetSegmentRoute
// - EVPNIPPrefixRoute
// - EVPNIPMSIRoute
// - LabeledVPNIPAddressPrefix
// - RouteTargetMembershipNLRI
// - FlowSpecNLRI
// - VPNFlowSpecNLRI
// - OpaqueNLRI
// - LsAddrPrefix
google.protobuf.Any nlri = 1;
// Each attribute must be one of *Attribute defined in
// "api/attribute.proto".
repeated google.protobuf.Any pattrs = 2;
google.protobuf.Timestamp age = 3;
bool best = 4;
bool is_withdraw = 5;
RPKIValidation validation_detail = 7;
Validation validation = 7;
bool no_implicit_withdraw = 8;
Family family = 9;
uint32 source_asn = 10;
@@ -514,24 +547,8 @@ message Path {
bool is_nexthop_invalid = 17;
uint32 identifier = 18;
uint32 local_identifier = 19;
// One of the following defined in "api/attribute.proto":
// - IPAddressPrefix
// - LabeledIPAddressPrefix
// - EncapsulationNLRI
// - EVPNEthernetAutoDiscoveryRoute
// - EVPNMACIPAdvertisementRoute
// - EVPNInclusiveMulticastEthernetTagRoute
// - EVPNEthernetSegmentRoute
// - EVPNIPPrefixRoute
// - LabeledVPNIPAddressPrefix
// - RouteTargetMembershipNLRI
// - FlowSpecNLRI
// - VPNFlowSpecNLRI
// - OpaqueNLRI
google.protobuf.Any any_nlri = 20;
// Each attribute must be one of *Attribute defined in
// "api/attribute.proto".
repeated google.protobuf.Any any_pattrs = 21;
bytes nlri_binary = 20;
repeated bytes pattrs_binary = 21;
}
message Destination {
@@ -563,7 +580,6 @@ message Peer {
RouteServer route_server = 8;
GracefulRestart graceful_restart = 9;
repeated AfiSafi afi_safis = 10;
AddPaths add_paths = 11;
}
message PeerGroup {
@@ -577,7 +593,6 @@ message PeerGroup {
RouteServer route_server = 8;
GracefulRestart graceful_restart = 9;
repeated AfiSafi afi_safis = 10;
AddPaths add_paths = 11;
}
message DynamicNeighbor {
@@ -613,15 +628,11 @@ message PeerConf {
RemovePrivateAs remove_private_as = 8;
bool route_flap_damping = 9;
uint32 send_community = 10;
// Each attribute must be one of *Capability defined in
// "api/capability.proto".
repeated google.protobuf.Any remote_cap = 11;
repeated google.protobuf.Any local_cap = 12;
string id = 13;
string neighbor_interface = 14;
string vrf = 15;
uint32 allow_own_as = 16;
bool replace_peer_as = 17;
string neighbor_interface = 11;
string vrf = 12;
uint32 allow_own_as = 13;
bool replace_peer_as = 14;
bool admin_down = 15;
}
message PeerGroupConf {
@@ -693,18 +704,19 @@ message PeerState {
ESTABLISHED = 6;
}
SessionState session_state = 13;
repeated string supported_capabilities = 14;
enum AdminState {
UP = 0;
DOWN = 1;
PFX_CT = 2; // prefix counter over limit
}
AdminState admin_state = 15;
uint32 received = 16;
uint32 accepted = 17;
uint32 advertised = 18;
uint32 out_q = 19;
uint32 flops = 20;
uint32 out_q = 16;
uint32 flops = 17;
// Each attribute must be one of *Capability defined in
// "api/capability.proto".
repeated google.protobuf.Any remote_cap = 18;
repeated google.protobuf.Any local_cap = 19;
string router_id = 20;
}
message Messages {
@@ -720,6 +732,8 @@ message Message {
uint64 refresh = 5;
uint64 discarded = 6;
uint64 total = 7;
uint64 withdraw_update = 8;
uint64 withdraw_prefix = 9;
}
message Queues {
@@ -737,6 +751,7 @@ message TimersConfig{
uint64 hold_time = 2;
uint64 keepalive_interval = 3;
uint64 minimum_advertisement_interval = 4;
uint64 idle_hold_time_after_reset = 5;
}
message TimersState{
@@ -745,8 +760,8 @@ message TimersState{
uint64 keepalive_interval = 3;
uint64 minimum_advertisement_interval = 4;
uint64 negotiated_hold_time = 5;
uint64 uptime = 6;
uint64 downtime = 7;
google.protobuf.Timestamp uptime = 6;
google.protobuf.Timestamp downtime = 7;
}
message Transport {
@@ -757,10 +772,12 @@ message Transport {
string remote_address = 5;
uint32 remote_port = 6;
uint32 tcp_mss = 7;
string bind_interface = 8;
}
message RouteServer {
bool route_server_client = 1;
bool secondary_route = 2;
}
message GracefulRestart {
@@ -801,8 +818,9 @@ message AfiSafiConfig {
message AfiSafiState {
Family family = 1;
bool enabled = 2;
uint32 total_paths = 3;
uint32 total_prefixes = 4;
uint64 received = 3;
uint64 accepted = 4;
uint64 advertised = 5;
}
message RouteSelectionOptionsConfig {
@@ -907,7 +925,8 @@ message LongLivedGracefulRestart {
message AfiSafi {
MpGracefulRestart mp_graceful_restart = 1;
AfiSafiConfig config = 2;
ApplyPolicy apply_policy = 3;
AfiSafiState state = 3;
ApplyPolicy apply_policy = 4;
// TODO:
// Support the following structures:
// - Ipv4Unicast
@@ -920,12 +939,12 @@ message AfiSafi {
// - L3vpnIpv6Multicast
// - L2vpnVpls
// - L2vpnEvpn
RouteSelectionOptions route_selection_options = 4;
UseMultiplePaths use_multiple_paths = 5;
PrefixLimit prefix_limits = 6;
RouteTargetMembership route_target_membership = 7;
LongLivedGracefulRestart long_lived_graceful_restart = 8;
AddPaths add_paths = 9;
RouteSelectionOptions route_selection_options = 5;
UseMultiplePaths use_multiple_paths = 6;
PrefixLimit prefix_limits = 7;
RouteTargetMembership route_target_membership = 8;
LongLivedGracefulRestart long_lived_graceful_restart = 9;
AddPaths add_paths = 10;
}
message AddPathsConfig {
@@ -961,7 +980,7 @@ enum DefinedType {
}
message DefinedSet {
DefinedType type = 1;
DefinedType defined_type = 1;
string name = 2;
repeated string list = 3;
repeated Prefix prefixes = 4;
@@ -974,7 +993,7 @@ enum MatchType {
}
message MatchSet {
MatchType type = 1;
MatchType match_type = 1;
string name = 2;
}
@@ -985,7 +1004,7 @@ enum AsPathLengthType {
}
message AsPathLength {
AsPathLengthType type = 1;
AsPathLengthType length_type = 1;
uint32 length = 2;
}
@@ -1022,7 +1041,7 @@ enum CommunityActionType {
}
message CommunityAction {
CommunityActionType type = 1;
CommunityActionType action_type = 1;
repeated string communities = 2;
}
@@ -1032,7 +1051,7 @@ enum MedActionType {
}
message MedAction {
MedActionType type = 1;
MedActionType action_type = 1;
int64 value = 2;
}
@@ -1150,8 +1169,8 @@ message RPKIConf {
}
message RPKIState {
int64 uptime = 1;
int64 downtime = 2;
google.protobuf.Timestamp uptime = 1;
google.protobuf.Timestamp downtime = 2;
bool up = 3;
uint32 record_ipv4 = 4;
uint32 record_ipv6 = 5;

View File

@@ -45,7 +45,9 @@ func UnmarshalAttribute(an *any.Any) (bgp.PathAttributeInterface, error) {
case *api.NextHopAttribute:
nexthop := net.ParseIP(a.NextHop).To4()
if nexthop == nil {
return nil, fmt.Errorf("invalid nexthop address: %s", a.NextHop)
if nexthop = net.ParseIP(a.NextHop).To16(); nexthop == nil {
return nil, fmt.Errorf("invalid nexthop address: %s", a.NextHop)
}
}
return bgp.NewPathAttributeNextHop(a.NextHop), nil
case *api.MultiExitDiscAttribute:
@@ -73,6 +75,8 @@ func UnmarshalAttribute(an *any.Any) (bgp.PathAttributeInterface, error) {
}
}
return bgp.NewPathAttributeClusterList(a.Ids), nil
case *api.PrefixSID:
return bgp.NewPathAttributePrefixSID(a)
}
return nil, errors.New("unexpected object")
}
@@ -147,6 +151,114 @@ func NewClusterListAttributeFromNative(a *bgp.PathAttributeClusterList) *api.Clu
}
}
func NewPrefixSIDAttributeFromNative(a *bgp.PathAttributePrefixSID) *api.PrefixSID {
psid := &api.PrefixSID{}
psid.Tlvs = MarshalSRv6TLVs(a.TLVs)
return psid
}
func MarshalSRv6TLVs(tlvs []bgp.PrefixSIDTLVInterface) []*any.Any {
mtlvs := make([]*any.Any, len(tlvs))
for i, tlv := range tlvs {
var r proto.Message
switch t := tlv.(type) {
case *bgp.SRv6L3ServiceAttribute:
o := &api.SRv6L3ServiceTLV{}
o.SubTlvs = MarshalSRv6SubTLVs(t.SubTLVs)
r = o
default:
log.WithFields(log.Fields{
"Topic": "protobuf",
"SRv6": t,
}).Warn("invalid prefix sid tlv type to marshal")
return nil
}
a, _ := ptypes.MarshalAny(r)
mtlvs[i] = a
}
return mtlvs
}
func MarshalSRv6SubTLVs(tlvs []bgp.PrefixSIDTLVInterface) map[uint32]*api.SRv6TLV {
mtlvs := make(map[uint32]*api.SRv6TLV)
var key uint32
for _, tlv := range tlvs {
var r proto.Message
switch t := tlv.(type) {
case *bgp.SRv6InformationSubTLV:
o := &api.SRv6InformationSubTLV{
EndpointBehavior: uint32(t.EndpointBehavior),
// TODO Once flags are used in RFC, add processing.
Flags: &api.SRv6SIDFlags{},
}
o.Sid = make([]byte, len(t.SID))
copy(o.Sid, t.SID)
o.SubSubTlvs = MarshalSRv6SubSubTLVs(t.SubSubTLVs)
// SRv6 Information Sub TLV is type 1 Sub TLV
key = 1
r = o
default:
log.WithFields(log.Fields{
"Topic": "protobuf",
"SRv6": t,
}).Warn("invalid prefix sid sub tlv type to marshal")
return nil
}
a, _ := ptypes.MarshalAny(r)
tlvs, ok := mtlvs[key]
if !ok {
tlvs = &api.SRv6TLV{
Tlv: make([]*any.Any, 0),
}
mtlvs[key] = tlvs
}
tlvs.Tlv = append(tlvs.Tlv, a)
}
return mtlvs
}
func MarshalSRv6SubSubTLVs(tlvs []bgp.PrefixSIDTLVInterface) map[uint32]*api.SRv6TLV {
mtlvs := make(map[uint32]*api.SRv6TLV)
var key uint32
for _, tlv := range tlvs {
var r proto.Message
switch t := tlv.(type) {
case *bgp.SRv6SIDStructureSubSubTLV:
o := &api.SRv6StructureSubSubTLV{
LocalBlockLength: uint32(t.LocalBlockLength),
LocalNodeLength: uint32(t.LocatorNodeLength),
FunctionLength: uint32(t.FunctionLength),
ArgumentLength: uint32(t.ArgumentLength),
TranspositionLength: uint32(t.TranspositionLength),
TranspositionOffset: uint32(t.TranspositionOffset),
}
// SRv6 SID Structure Sub Sub TLV is type 1 Sub Sub TLV
key = 1
r = o
default:
log.WithFields(log.Fields{
"Topic": "protobuf",
"SRv6": t,
}).Warn("invalid prefix sid sub sub tlv type to marshal")
return nil
}
a, _ := ptypes.MarshalAny(r)
tlvs, ok := mtlvs[key]
if !ok {
tlvs = &api.SRv6TLV{
Tlv: make([]*any.Any, 0),
}
mtlvs[key] = tlvs
}
tlvs.Tlv = append(tlvs.Tlv, a)
}
return mtlvs
}
func MarshalRD(rd bgp.RouteDistinguisherInterface) *any.Any {
var r proto.Message
switch v := rd.(type) {
@@ -319,6 +431,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 +630,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 +1231,133 @@ 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.Link.Srlgs != nil {
apiAttr.Link.Srlgs = append(apiAttr.Link.Srlgs, *attr.Link.Srlgs...)
}
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 +1430,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)
@@ -1125,7 +1475,9 @@ func unmarshalAttribute(an *any.Any) (bgp.PathAttributeInterface, error) {
case *api.NextHopAttribute:
nexthop := net.ParseIP(a.NextHop).To4()
if nexthop == nil {
return nil, fmt.Errorf("invalid nexthop address: %s", a.NextHop)
if nexthop = net.ParseIP(a.NextHop).To16(); nexthop == nil {
return nil, fmt.Errorf("invalid nexthop address: %s", a.NextHop)
}
}
return bgp.NewPathAttributeNextHop(a.NextHop), nil
case *api.MultiExitDiscAttribute:
@@ -1295,7 +1647,8 @@ func unmarshalAttribute(an *any.Any) (bgp.PathAttributeInterface, error) {
communities = append(communities, bgp.NewLargeCommunity(c.GlobalAdmin, c.LocalData1, c.LocalData2))
}
return bgp.NewPathAttributeLargeCommunities(communities), nil
case *api.PrefixSID:
return bgp.NewPathAttributePrefixSID(a)
case *api.UnknownAttribute:
return bgp.NewPathAttributeUnknown(bgp.BGPAttrFlag(a.Flags), bgp.BGPAttrType(a.Type), a.Value), nil
}

View File

@@ -17,9 +17,11 @@ package apiutil
import (
"encoding/json"
"fmt"
"net"
"time"
"github.com/golang/protobuf/ptypes"
api "github.com/osrg/gobgp/api"
"github.com/osrg/gobgp/pkg/packet/bgp"
)
@@ -49,9 +51,10 @@ func NewDestination(dst *api.Destination) *Destination {
for _, p := range dst.Paths {
nlri, _ := GetNativeNlri(p)
attrs, _ := GetNativePathAttributes(p)
t, _ := ptypes.Timestamp(p.Age)
l = append(l, &Path{
Nlri: nlri,
Age: p.Age,
Age: t.Unix(),
Best: p.Best,
Attrs: attrs,
Stale: p.Stale,
@@ -64,10 +67,11 @@ func NewDestination(dst *api.Destination) *Destination {
}
func NewPath(nlri bgp.AddrPrefixInterface, isWithdraw bool, attrs []bgp.PathAttributeInterface, age time.Time) *api.Path {
t, _ := ptypes.TimestampProto(age)
return &api.Path{
AnyNlri: MarshalNLRI(nlri),
AnyPattrs: MarshalPathAttributes(attrs),
Age: age.Unix(),
Nlri: MarshalNLRI(nlri),
Pattrs: MarshalPathAttributes(attrs),
Age: t,
IsWithdraw: isWithdraw,
Family: ToApiFamily(nlri.AFI(), nlri.SAFI()),
Identifier: nlri.PathIdentifier(),
@@ -87,17 +91,20 @@ func getNLRI(family bgp.RouteFamily, buf []byte) (bgp.AddrPrefixInterface, error
}
func GetNativeNlri(p *api.Path) (bgp.AddrPrefixInterface, error) {
if len(p.Nlri) > 0 {
return getNLRI(ToRouteFamily(p.Family), p.Nlri)
if p.Family == nil {
return nil, fmt.Errorf("family cannot be nil")
}
return UnmarshalNLRI(ToRouteFamily(p.Family), p.AnyNlri)
if len(p.NlriBinary) > 0 {
return getNLRI(ToRouteFamily(p.Family), p.NlriBinary)
}
return UnmarshalNLRI(ToRouteFamily(p.Family), p.Nlri)
}
func GetNativePathAttributes(p *api.Path) ([]bgp.PathAttributeInterface, error) {
pattrsLen := len(p.Pattrs)
pattrsLen := len(p.PattrsBinary)
if pattrsLen > 0 {
pattrs := make([]bgp.PathAttributeInterface, 0, pattrsLen)
for _, attr := range p.Pattrs {
for _, attr := range p.PattrsBinary {
a, err := bgp.GetPathAttribute(attr)
if err != nil {
return nil, err
@@ -110,7 +117,7 @@ func GetNativePathAttributes(p *api.Path) ([]bgp.PathAttributeInterface, error)
}
return pattrs, nil
}
return UnmarshalPathAttributes(p.AnyPattrs)
return UnmarshalPathAttributes(p.Pattrs)
}
func ToRouteFamily(f *api.Family) bgp.RouteFamily {

View File

@@ -1,7 +1,7 @@
// DO NOT EDIT
// generated by pyang using OpenConfig https://github.com/openconfig/public
//
// Copyright (C) 2014-2016 Nippon Telegraph and Telephone Corporation.
// Copyright (C) 2014-2019 Nippon Telegraph and Telephone Corporation.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
@@ -16,6 +16,8 @@
// See the License for the specific language governing permissions and
// limitations under the License.
// Code generated by pyang. DO NOT EDIT.
package config
import (
@@ -55,14 +57,6 @@ var RemovePrivateAsOptionToIntMap = map[RemovePrivateAsOption]int{
REMOVE_PRIVATE_AS_OPTION_REPLACE: 1,
}
func (v RemovePrivateAsOption) ToInt() int {
i, ok := RemovePrivateAsOptionToIntMap[v]
if !ok {
return -1
}
return i
}
var IntToRemovePrivateAsOptionMap = map[int]RemovePrivateAsOption{
0: REMOVE_PRIVATE_AS_OPTION_ALL,
1: REMOVE_PRIVATE_AS_OPTION_REPLACE,
@@ -75,6 +69,14 @@ func (v RemovePrivateAsOption) Validate() error {
return nil
}
func (v RemovePrivateAsOption) ToInt() int {
i, ok := RemovePrivateAsOptionToIntMap[v]
if !ok {
return -1
}
return i
}
// typedef for typedef bgp-types:bgp-community-regexp-type.
type BgpCommunityRegexpType StdRegexp
@@ -99,14 +101,6 @@ var CommunityTypeToIntMap = map[CommunityType]int{
COMMUNITY_TYPE_NONE: 3,
}
func (v CommunityType) ToInt() int {
i, ok := CommunityTypeToIntMap[v]
if !ok {
return -1
}
return i
}
var IntToCommunityTypeMap = map[int]CommunityType{
0: COMMUNITY_TYPE_STANDARD,
1: COMMUNITY_TYPE_EXTENDED,
@@ -121,6 +115,14 @@ func (v CommunityType) Validate() error {
return nil
}
func (v CommunityType) ToInt() int {
i, ok := CommunityTypeToIntMap[v]
if !ok {
return -1
}
return i
}
// typedef for typedef bgp-types:bgp-ext-community-type.
type BgpExtCommunityType string
@@ -142,14 +144,6 @@ var PeerTypeToIntMap = map[PeerType]int{
PEER_TYPE_EXTERNAL: 1,
}
func (v PeerType) ToInt() int {
i, ok := PeerTypeToIntMap[v]
if !ok {
return -1
}
return i
}
var IntToPeerTypeMap = map[int]PeerType{
0: PEER_TYPE_INTERNAL,
1: PEER_TYPE_EXTERNAL,
@@ -162,6 +156,14 @@ func (v PeerType) Validate() error {
return nil
}
func (v PeerType) ToInt() int {
i, ok := PeerTypeToIntMap[v]
if !ok {
return -1
}
return i
}
// typedef for identity bgp-types:bgp-session-direction.
// Type to describe the direction of NLRI transmission.
type BgpSessionDirection string
@@ -176,14 +178,6 @@ var BgpSessionDirectionToIntMap = map[BgpSessionDirection]int{
BGP_SESSION_DIRECTION_OUTBOUND: 1,
}
func (v BgpSessionDirection) ToInt() int {
i, ok := BgpSessionDirectionToIntMap[v]
if !ok {
return -1
}
return i
}
var IntToBgpSessionDirectionMap = map[int]BgpSessionDirection{
0: BGP_SESSION_DIRECTION_INBOUND,
1: BGP_SESSION_DIRECTION_OUTBOUND,
@@ -196,6 +190,14 @@ func (v BgpSessionDirection) Validate() error {
return nil
}
func (v BgpSessionDirection) ToInt() int {
i, ok := BgpSessionDirectionToIntMap[v]
if !ok {
return -1
}
return i
}
// typedef for identity bgp-types:bgp-origin-attr-type.
// Type definition for standard BGP origin attribute.
type BgpOriginAttrType string
@@ -212,14 +214,6 @@ var BgpOriginAttrTypeToIntMap = map[BgpOriginAttrType]int{
BGP_ORIGIN_ATTR_TYPE_INCOMPLETE: 2,
}
func (v BgpOriginAttrType) ToInt() int {
i, ok := BgpOriginAttrTypeToIntMap[v]
if !ok {
return -1
}
return i
}
var IntToBgpOriginAttrTypeMap = map[int]BgpOriginAttrType{
0: BGP_ORIGIN_ATTR_TYPE_IGP,
1: BGP_ORIGIN_ATTR_TYPE_EGP,
@@ -233,6 +227,14 @@ func (v BgpOriginAttrType) Validate() error {
return nil
}
func (v BgpOriginAttrType) ToInt() int {
i, ok := BgpOriginAttrTypeToIntMap[v]
if !ok {
return -1
}
return i
}
// typedef for identity bgp-types:afi-safi-type.
// Base identity type for AFI,SAFI tuples for BGP-4.
type AfiSafiType string
@@ -259,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{
@@ -283,14 +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,
}
func (v AfiSafiType) ToInt() int {
i, ok := AfiSafiTypeToIntMap[v]
if !ok {
return -1
}
return i
AFI_SAFI_TYPE_LS: 21,
}
var IntToAfiSafiTypeMap = map[int]AfiSafiType{
@@ -315,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 {
@@ -324,6 +321,14 @@ func (v AfiSafiType) Validate() error {
return nil
}
func (v AfiSafiType) ToInt() int {
i, ok := AfiSafiTypeToIntMap[v]
if !ok {
return -1
}
return i
}
// typedef for identity bgp-types:bgp-capability.
// Base identity for a BGP capability.
type BgpCapability string
@@ -344,14 +349,6 @@ var BgpCapabilityToIntMap = map[BgpCapability]int{
BGP_CAPABILITY_ADD_PATHS: 4,
}
func (v BgpCapability) ToInt() int {
i, ok := BgpCapabilityToIntMap[v]
if !ok {
return -1
}
return i
}
var IntToBgpCapabilityMap = map[int]BgpCapability{
0: BGP_CAPABILITY_MPBGP,
1: BGP_CAPABILITY_ROUTE_REFRESH,
@@ -367,6 +364,14 @@ func (v BgpCapability) Validate() error {
return nil
}
func (v BgpCapability) ToInt() int {
i, ok := BgpCapabilityToIntMap[v]
if !ok {
return -1
}
return i
}
// typedef for identity bgp-types:bgp-well-known-std-community.
// Reserved communities within the standard community space
// defined by RFC1997. These communities must fall within the
@@ -387,14 +392,6 @@ var BgpWellKnownStdCommunityToIntMap = map[BgpWellKnownStdCommunity]int{
BGP_WELL_KNOWN_STD_COMMUNITY_NOPEER: 3,
}
func (v BgpWellKnownStdCommunity) ToInt() int {
i, ok := BgpWellKnownStdCommunityToIntMap[v]
if !ok {
return -1
}
return i
}
var IntToBgpWellKnownStdCommunityMap = map[int]BgpWellKnownStdCommunity{
0: BGP_WELL_KNOWN_STD_COMMUNITY_NO_EXPORT,
1: BGP_WELL_KNOWN_STD_COMMUNITY_NO_ADVERTISE,
@@ -409,6 +406,14 @@ func (v BgpWellKnownStdCommunity) Validate() error {
return nil
}
func (v BgpWellKnownStdCommunity) ToInt() int {
i, ok := BgpWellKnownStdCommunityToIntMap[v]
if !ok {
return -1
}
return i
}
// typedef for identity ptypes:match-set-options-restricted-type.
// Options that govern the behavior of a match statement. The
// default behavior is ANY, i.e., the given value matches any
@@ -426,14 +431,6 @@ var MatchSetOptionsRestrictedTypeToIntMap = map[MatchSetOptionsRestrictedType]in
MATCH_SET_OPTIONS_RESTRICTED_TYPE_INVERT: 1,
}
func (v MatchSetOptionsRestrictedType) ToInt() int {
i, ok := MatchSetOptionsRestrictedTypeToIntMap[v]
if !ok {
return -1
}
return i
}
var IntToMatchSetOptionsRestrictedTypeMap = map[int]MatchSetOptionsRestrictedType{
0: MATCH_SET_OPTIONS_RESTRICTED_TYPE_ANY,
1: MATCH_SET_OPTIONS_RESTRICTED_TYPE_INVERT,
@@ -456,6 +453,14 @@ func (v MatchSetOptionsRestrictedType) DefaultAsNeeded() MatchSetOptionsRestrict
}
return v
}
func (v MatchSetOptionsRestrictedType) ToInt() int {
_v := v.DefaultAsNeeded()
i, ok := MatchSetOptionsRestrictedTypeToIntMap[_v]
if !ok {
return -1
}
return i
}
// typedef for identity ptypes:match-set-options-type.
// Options that govern the behavior of a match statement. The
@@ -475,14 +480,6 @@ var MatchSetOptionsTypeToIntMap = map[MatchSetOptionsType]int{
MATCH_SET_OPTIONS_TYPE_INVERT: 2,
}
func (v MatchSetOptionsType) ToInt() int {
i, ok := MatchSetOptionsTypeToIntMap[v]
if !ok {
return -1
}
return i
}
var IntToMatchSetOptionsTypeMap = map[int]MatchSetOptionsType{
0: MATCH_SET_OPTIONS_TYPE_ANY,
1: MATCH_SET_OPTIONS_TYPE_ALL,
@@ -506,6 +503,14 @@ func (v MatchSetOptionsType) DefaultAsNeeded() MatchSetOptionsType {
}
return v
}
func (v MatchSetOptionsType) ToInt() int {
_v := v.DefaultAsNeeded()
i, ok := MatchSetOptionsTypeToIntMap[_v]
if !ok {
return -1
}
return i
}
// typedef for typedef ptypes:tag-type.
type TagType string
@@ -535,14 +540,6 @@ var InstallProtocolTypeToIntMap = map[InstallProtocolType]int{
INSTALL_PROTOCOL_TYPE_LOCAL_AGGREGATE: 6,
}
func (v InstallProtocolType) ToInt() int {
i, ok := InstallProtocolTypeToIntMap[v]
if !ok {
return -1
}
return i
}
var IntToInstallProtocolTypeMap = map[int]InstallProtocolType{
0: INSTALL_PROTOCOL_TYPE_BGP,
1: INSTALL_PROTOCOL_TYPE_ISIS,
@@ -560,6 +557,14 @@ func (v InstallProtocolType) Validate() error {
return nil
}
func (v InstallProtocolType) ToInt() int {
i, ok := InstallProtocolTypeToIntMap[v]
if !ok {
return -1
}
return i
}
// typedef for identity ptypes:attribute-comparison.
// base type for supported comparison operators on route
// attributes.
@@ -583,14 +588,6 @@ var AttributeComparisonToIntMap = map[AttributeComparison]int{
ATTRIBUTE_COMPARISON_LE: 5,
}
func (v AttributeComparison) ToInt() int {
i, ok := AttributeComparisonToIntMap[v]
if !ok {
return -1
}
return i
}
var IntToAttributeComparisonMap = map[int]AttributeComparison{
0: ATTRIBUTE_COMPARISON_ATTRIBUTE_EQ,
1: ATTRIBUTE_COMPARISON_ATTRIBUTE_GE,
@@ -607,6 +604,14 @@ func (v AttributeComparison) Validate() error {
return nil
}
func (v AttributeComparison) ToInt() int {
i, ok := AttributeComparisonToIntMap[v]
if !ok {
return -1
}
return i
}
// typedef for identity rpol:route-disposition.
// Select the final disposition for the route, either
// accept or reject.
@@ -624,14 +629,6 @@ var RouteDispositionToIntMap = map[RouteDisposition]int{
ROUTE_DISPOSITION_REJECT_ROUTE: 2,
}
func (v RouteDisposition) ToInt() int {
i, ok := RouteDispositionToIntMap[v]
if !ok {
return -1
}
return i
}
var IntToRouteDispositionMap = map[int]RouteDisposition{
0: ROUTE_DISPOSITION_NONE,
1: ROUTE_DISPOSITION_ACCEPT_ROUTE,
@@ -645,6 +642,14 @@ func (v RouteDisposition) Validate() error {
return nil
}
func (v RouteDisposition) ToInt() int {
i, ok := RouteDispositionToIntMap[v]
if !ok {
return -1
}
return i
}
// typedef for identity rpol:route-type.
// Condition to check the route type in the route update.
type RouteType string
@@ -663,14 +668,6 @@ var RouteTypeToIntMap = map[RouteType]int{
ROUTE_TYPE_LOCAL: 3,
}
func (v RouteType) ToInt() int {
i, ok := RouteTypeToIntMap[v]
if !ok {
return -1
}
return i
}
var IntToRouteTypeMap = map[int]RouteType{
0: ROUTE_TYPE_NONE,
1: ROUTE_TYPE_INTERNAL,
@@ -685,6 +682,14 @@ func (v RouteType) Validate() error {
return nil
}
func (v RouteType) ToInt() int {
i, ok := RouteTypeToIntMap[v]
if !ok {
return -1
}
return i
}
// typedef for identity rpol:default-policy-type.
// type used to specify default route disposition in
// a policy chain.
@@ -700,14 +705,6 @@ var DefaultPolicyTypeToIntMap = map[DefaultPolicyType]int{
DEFAULT_POLICY_TYPE_REJECT_ROUTE: 1,
}
func (v DefaultPolicyType) ToInt() int {
i, ok := DefaultPolicyTypeToIntMap[v]
if !ok {
return -1
}
return i
}
var IntToDefaultPolicyTypeMap = map[int]DefaultPolicyType{
0: DEFAULT_POLICY_TYPE_ACCEPT_ROUTE,
1: DEFAULT_POLICY_TYPE_REJECT_ROUTE,
@@ -720,6 +717,14 @@ func (v DefaultPolicyType) Validate() error {
return nil
}
func (v DefaultPolicyType) ToInt() int {
i, ok := DefaultPolicyTypeToIntMap[v]
if !ok {
return -1
}
return i
}
// typedef for identity bgp:session-state.
// Operational state of the BGP peer.
type SessionState string
@@ -742,14 +747,6 @@ var SessionStateToIntMap = map[SessionState]int{
SESSION_STATE_ESTABLISHED: 5,
}
func (v SessionState) ToInt() int {
i, ok := SessionStateToIntMap[v]
if !ok {
return -1
}
return i
}
var IntToSessionStateMap = map[int]SessionState{
0: SESSION_STATE_IDLE,
1: SESSION_STATE_CONNECT,
@@ -766,6 +763,14 @@ func (v SessionState) Validate() error {
return nil
}
func (v SessionState) ToInt() int {
i, ok := SessionStateToIntMap[v]
if !ok {
return -1
}
return i
}
// typedef for identity bgp:admin-state.
type AdminState string
@@ -781,14 +786,6 @@ var AdminStateToIntMap = map[AdminState]int{
ADMIN_STATE_PFX_CT: 2,
}
func (v AdminState) ToInt() int {
i, ok := AdminStateToIntMap[v]
if !ok {
return -1
}
return i
}
var IntToAdminStateMap = map[int]AdminState{
0: ADMIN_STATE_UP,
1: ADMIN_STATE_DOWN,
@@ -802,6 +799,14 @@ func (v AdminState) Validate() error {
return nil
}
func (v AdminState) ToInt() int {
i, ok := AdminStateToIntMap[v]
if !ok {
return -1
}
return i
}
// typedef for identity bgp:mode.
// Ths leaf indicates the mode of operation of BGP graceful
// restart with the peer.
@@ -819,14 +824,6 @@ var ModeToIntMap = map[Mode]int{
MODE_REMOTE_HELPER: 2,
}
func (v Mode) ToInt() int {
i, ok := ModeToIntMap[v]
if !ok {
return -1
}
return i
}
var IntToModeMap = map[int]Mode{
0: MODE_HELPER_ONLY,
1: MODE_BILATERAL,
@@ -840,6 +837,14 @@ func (v Mode) Validate() error {
return nil
}
func (v Mode) ToInt() int {
i, ok := ModeToIntMap[v]
if !ok {
return -1
}
return i
}
// typedef for typedef bgp-pol:bgp-next-hop-type.
type BgpNextHopType string
@@ -866,14 +871,6 @@ var BgpSetCommunityOptionTypeToIntMap = map[BgpSetCommunityOptionType]int{
BGP_SET_COMMUNITY_OPTION_TYPE_REPLACE: 2,
}
func (v BgpSetCommunityOptionType) ToInt() int {
i, ok := BgpSetCommunityOptionTypeToIntMap[v]
if !ok {
return -1
}
return i
}
var IntToBgpSetCommunityOptionTypeMap = map[int]BgpSetCommunityOptionType{
0: BGP_SET_COMMUNITY_OPTION_TYPE_ADD,
1: BGP_SET_COMMUNITY_OPTION_TYPE_REMOVE,
@@ -887,6 +884,14 @@ func (v BgpSetCommunityOptionType) Validate() error {
return nil
}
func (v BgpSetCommunityOptionType) ToInt() int {
i, ok := BgpSetCommunityOptionTypeToIntMap[v]
if !ok {
return -1
}
return i
}
// typedef for identity gobgp:bmp-route-monitoring-policy-type.
type BmpRouteMonitoringPolicyType string
@@ -906,14 +911,6 @@ var BmpRouteMonitoringPolicyTypeToIntMap = map[BmpRouteMonitoringPolicyType]int{
BMP_ROUTE_MONITORING_POLICY_TYPE_ALL: 4,
}
func (v BmpRouteMonitoringPolicyType) ToInt() int {
i, ok := BmpRouteMonitoringPolicyTypeToIntMap[v]
if !ok {
return -1
}
return i
}
var IntToBmpRouteMonitoringPolicyTypeMap = map[int]BmpRouteMonitoringPolicyType{
0: BMP_ROUTE_MONITORING_POLICY_TYPE_PRE_POLICY,
1: BMP_ROUTE_MONITORING_POLICY_TYPE_POST_POLICY,
@@ -929,6 +926,14 @@ func (v BmpRouteMonitoringPolicyType) Validate() error {
return nil
}
func (v BmpRouteMonitoringPolicyType) ToInt() int {
i, ok := BmpRouteMonitoringPolicyTypeToIntMap[v]
if !ok {
return -1
}
return i
}
// typedef for identity gobgp:mrt-type.
type MrtType string
@@ -942,14 +947,6 @@ var MrtTypeToIntMap = map[MrtType]int{
MRT_TYPE_TABLE: 1,
}
func (v MrtType) ToInt() int {
i, ok := MrtTypeToIntMap[v]
if !ok {
return -1
}
return i
}
var IntToMrtTypeMap = map[int]MrtType{
0: MRT_TYPE_UPDATES,
1: MRT_TYPE_TABLE,
@@ -962,6 +959,14 @@ func (v MrtType) Validate() error {
return nil
}
func (v MrtType) ToInt() int {
i, ok := MrtTypeToIntMap[v]
if !ok {
return -1
}
return i
}
// typedef for identity gobgp:rpki-validation-result-type.
// indicate the validation result of RPKI based on ROA.
type RpkiValidationResultType string
@@ -980,14 +985,6 @@ var RpkiValidationResultTypeToIntMap = map[RpkiValidationResultType]int{
RPKI_VALIDATION_RESULT_TYPE_INVALID: 3,
}
func (v RpkiValidationResultType) ToInt() int {
i, ok := RpkiValidationResultTypeToIntMap[v]
if !ok {
return -1
}
return i
}
var IntToRpkiValidationResultTypeMap = map[int]RpkiValidationResultType{
0: RPKI_VALIDATION_RESULT_TYPE_NONE,
1: RPKI_VALIDATION_RESULT_TYPE_NOT_FOUND,
@@ -1002,6 +999,14 @@ func (v RpkiValidationResultType) Validate() error {
return nil
}
func (v RpkiValidationResultType) ToInt() int {
i, ok := RpkiValidationResultTypeToIntMap[v]
if !ok {
return -1
}
return i
}
// struct for container gobgp:state.
type DynamicNeighborState struct {
// original -> gobgp:prefix
@@ -1116,13 +1121,22 @@ type ZebraState struct {
// original -> gobgp:redistribute-route-type
RedistributeRouteTypeList []string `mapstructure:"redistribute-route-type-list" json:"redistribute-route-type-list,omitempty"`
// original -> gobgp:version
// Configure version of zebra protocol. Default is 2. Supported up to 3.
// Configure version of zebra protocol. Default is 2.
// Supported version are 2 or 3 for Quagga and 4, 5 or 6 for FRRouting.
Version uint8 `mapstructure:"version" json:"version,omitempty"`
// original -> gobgp:nexthop-trigger-enable
// gobgp:nexthop-trigger-enable's original type is boolean.
NexthopTriggerEnable bool `mapstructure:"nexthop-trigger-enable" json:"nexthop-trigger-enable,omitempty"`
// original -> gobgp:nexthop-trigger-delay
NexthopTriggerDelay uint8 `mapstructure:"nexthop-trigger-delay" json:"nexthop-trigger-delay,omitempty"`
// original -> gobgp:mpls-label-range-size
// Configure MPLS label range size which will be requested to
// FRR/Zebra.
MplsLabelRangeSize uint32 `mapstructure:"mpls-label-range-size" json:"mpls-label-range-size,omitempty"`
// original -> gobgp:software-name
// Configure zebra software name.
// quagga, frr3, frr4, frr5, frr6, frr7 can be used.
SoftwareName string `mapstructure:"software-name" json:"software-name,omitempty"`
}
// struct for container gobgp:config.
@@ -1137,13 +1151,22 @@ type ZebraConfig struct {
// original -> gobgp:redistribute-route-type
RedistributeRouteTypeList []string `mapstructure:"redistribute-route-type-list" json:"redistribute-route-type-list,omitempty"`
// original -> gobgp:version
// Configure version of zebra protocol. Default is 2. Supported up to 3.
// Configure version of zebra protocol. Default is 2.
// Supported version are 2 or 3 for Quagga and 4, 5 or 6 for FRRouting.
Version uint8 `mapstructure:"version" json:"version,omitempty"`
// original -> gobgp:nexthop-trigger-enable
// gobgp:nexthop-trigger-enable's original type is boolean.
NexthopTriggerEnable bool `mapstructure:"nexthop-trigger-enable" json:"nexthop-trigger-enable,omitempty"`
// original -> gobgp:nexthop-trigger-delay
NexthopTriggerDelay uint8 `mapstructure:"nexthop-trigger-delay" json:"nexthop-trigger-delay,omitempty"`
// original -> gobgp:mpls-label-range-size
// Configure MPLS label range size which will be requested to
// FRR/Zebra.
MplsLabelRangeSize uint32 `mapstructure:"mpls-label-range-size" json:"mpls-label-range-size,omitempty"`
// original -> gobgp:software-name
// Configure zebra software name.
// quagga, frr3, frr4, frr5, frr6, frr7 can be used.
SoftwareName string `mapstructure:"software-name" json:"software-name,omitempty"`
}
func (lhs *ZebraConfig) Equal(rhs *ZebraConfig) bool {
@@ -1173,6 +1196,12 @@ func (lhs *ZebraConfig) Equal(rhs *ZebraConfig) bool {
if lhs.NexthopTriggerDelay != rhs.NexthopTriggerDelay {
return false
}
if lhs.MplsLabelRangeSize != rhs.MplsLabelRangeSize {
return false
}
if lhs.SoftwareName != rhs.SoftwareName {
return false
}
return true
}
@@ -1376,6 +1405,12 @@ type BmpServerState struct {
// Enable feature for mirroring of received BGP messages
// mainly for debugging purpose.
RouteMirroringEnabled bool `mapstructure:"route-mirroring-enabled" json:"route-mirroring-enabled,omitempty"`
// original -> gobgp:sys-name
// Reference to the SysName of the BMP server.
SysName string `mapstructure:"sys-name" json:"sys-name,omitempty"`
// original -> gobgp:sys-descr
// Reference to the SysDescr of the BMP server.
SysDescr string `mapstructure:"sys-descr" json:"sys-descr,omitempty"`
}
// struct for container gobgp:config.
@@ -1399,6 +1434,12 @@ type BmpServerConfig struct {
// Enable feature for mirroring of received BGP messages
// mainly for debugging purpose.
RouteMirroringEnabled bool `mapstructure:"route-mirroring-enabled" json:"route-mirroring-enabled,omitempty"`
// original -> gobgp:sys-name
// Reference to the SysName of the BMP server.
SysName string `mapstructure:"sys-name" json:"sys-name,omitempty"`
// original -> gobgp:sys-descr
// Reference to the SysDescr of the BMP server.
SysDescr string `mapstructure:"sys-descr" json:"sys-descr,omitempty"`
}
func (lhs *BmpServerConfig) Equal(rhs *BmpServerConfig) bool {
@@ -1420,6 +1461,12 @@ func (lhs *BmpServerConfig) Equal(rhs *BmpServerConfig) bool {
if lhs.RouteMirroringEnabled != rhs.RouteMirroringEnabled {
return false
}
if lhs.SysName != rhs.SysName {
return false
}
if lhs.SysDescr != rhs.SysDescr {
return false
}
return true
}
@@ -1984,6 +2031,12 @@ type RouteServerState struct {
// gobgp:route-server-client's original type is boolean.
// Configure the neighbor as a route server client.
RouteServerClient bool `mapstructure:"route-server-client" json:"route-server-client,omitempty"`
// original -> gobgp:secondary-route
// gobgp:secondary-route's original type is boolean.
// if an export policy rejects a selected route, try the next route in
// order until one that is accepted is found or all routes for the peer
// are rejected.
SecondaryRoute bool `mapstructure:"secondary-route" json:"secondary-route,omitempty"`
}
// struct for container gobgp:config.
@@ -1994,6 +2047,12 @@ type RouteServerConfig struct {
// gobgp:route-server-client's original type is boolean.
// Configure the neighbor as a route server client.
RouteServerClient bool `mapstructure:"route-server-client" json:"route-server-client,omitempty"`
// original -> gobgp:secondary-route
// gobgp:secondary-route's original type is boolean.
// if an export policy rejects a selected route, try the next route in
// order until one that is accepted is found or all routes for the peer
// are rejected.
SecondaryRoute bool `mapstructure:"secondary-route" json:"secondary-route,omitempty"`
}
func (lhs *RouteServerConfig) Equal(rhs *RouteServerConfig) bool {
@@ -2003,6 +2062,9 @@ func (lhs *RouteServerConfig) Equal(rhs *RouteServerConfig) bool {
if lhs.RouteServerClient != rhs.RouteServerClient {
return false
}
if lhs.SecondaryRoute != rhs.SecondaryRoute {
return false
}
return true
}
@@ -2518,6 +2580,9 @@ type TransportConfig struct {
// original -> gobgp:ttl
// TTL value for BGP packets.
Ttl uint8 `mapstructure:"ttl" json:"ttl,omitempty"`
// original -> gobgp:bind-interface
// Interface name for binding.
BindInterface string `mapstructure:"bind-interface" json:"bind-interface,omitempty"`
}
func (lhs *TransportConfig) Equal(rhs *TransportConfig) bool {
@@ -2542,6 +2607,9 @@ func (lhs *TransportConfig) Equal(rhs *TransportConfig) bool {
if lhs.Ttl != rhs.Ttl {
return false
}
if lhs.BindInterface != rhs.BindInterface {
return false
}
return true
}
@@ -2620,7 +2688,7 @@ type TimersState struct {
// BGP last transitioned out of the Established state.
Downtime int64 `mapstructure:"downtime" json:"downtime,omitempty"`
// original -> gobgp:update-recv-time
// The number of seconds elasped since January 1, 1970 UTC
// The number of seconds elapsed since January 1, 1970 UTC
// last time the BGP session received an UPDATE message.
UpdateRecvTime int64 `mapstructure:"update-recv-time" json:"update-recv-time,omitempty"`
}

View File

@@ -8,6 +8,7 @@ import (
"reflect"
"strconv"
"github.com/osrg/gobgp/internal/pkg/zebra"
"github.com/osrg/gobgp/pkg/packet/bgp"
"github.com/osrg/gobgp/pkg/packet/bmp"
"github.com/osrg/gobgp/pkg/packet/rtr"
@@ -197,11 +198,15 @@ func setDefaultNeighborConfigValuesWithViper(v *viper.Viper, n *Neighbor, g *Glo
}
n.AfiSafis[i].MpGracefulRestart.State.Enabled = n.AfiSafis[i].MpGracefulRestart.Config.Enabled
if !vv.IsSet("afi-safi.add-paths.config.receive") {
n.AfiSafis[i].AddPaths.Config.Receive = n.AddPaths.Config.Receive
if n.AddPaths.Config.Receive {
n.AfiSafis[i].AddPaths.Config.Receive = n.AddPaths.Config.Receive
}
}
n.AfiSafis[i].AddPaths.State.Receive = n.AfiSafis[i].AddPaths.Config.Receive
if !vv.IsSet("afi-safi.add-paths.config.send-max") {
n.AfiSafis[i].AddPaths.Config.SendMax = n.AddPaths.Config.SendMax
if n.AddPaths.Config.SendMax != 0 {
n.AfiSafis[i].AddPaths.Config.SendMax = n.AddPaths.Config.SendMax
}
}
n.AfiSafis[i].AddPaths.State.SendMax = n.AfiSafis[i].AddPaths.Config.SendMax
}
@@ -344,7 +349,14 @@ func setDefaultConfigValuesWithViper(v *viper.Viper, b *BgpConfigSet) error {
return err
}
bmpSysPrefix := "Gobgp-R"
for idx, server := range b.BmpServers {
if server.Config.SysName == "" {
server.Config.SysName = bmpSysPrefix + strconv.Itoa(idx)
}
if server.Config.SysDescr == "" {
server.Config.SysDescr = "Gobgp Version: master"
}
if server.Config.Port == 0 {
server.Config.Port = bmp.BMP_DEFAULT_PORT
}
@@ -396,11 +408,12 @@ func setDefaultConfigValuesWithViper(v *viper.Viper, b *BgpConfigSet) error {
if b.Zebra.Config.Url == "" {
b.Zebra.Config.Url = "unix:/var/run/quagga/zserv.api"
}
if b.Zebra.Config.Version < 2 {
b.Zebra.Config.Version = 2
} else if b.Zebra.Config.Version > 5 {
b.Zebra.Config.Version = 5
if b.Zebra.Config.Version < zebra.MinZapiVer {
b.Zebra.Config.Version = zebra.MinZapiVer
} else if b.Zebra.Config.Version > zebra.MaxZapiVer {
b.Zebra.Config.Version = zebra.MaxZapiVer
}
if !v.IsSet("zebra.config.nexthop-trigger-enable") && !b.Zebra.Config.NexthopTriggerEnable && b.Zebra.Config.Version > 2 {
b.Zebra.Config.NexthopTriggerEnable = true
}
@@ -408,6 +421,10 @@ func setDefaultConfigValuesWithViper(v *viper.Viper, b *BgpConfigSet) error {
b.Zebra.Config.NexthopTriggerDelay = 5
}
if !zebra.IsAllowableSoftwareName(b.Zebra.Config.Version, b.Zebra.Config.SoftwareName) {
b.Zebra.Config.SoftwareName = ""
}
list, err := extractArray(v.Get("neighbors"))
if err != nil {
return err
@@ -495,7 +512,7 @@ func OverwriteNeighborConfigWithPeerGroup(c *Neighbor, pg *PeerGroup) error {
overwriteConfig(&c.TtlSecurity.Config, &pg.TtlSecurity.Config, "neighbor.ttl-security.config", v)
if !v.IsSet("neighbor.afi-safis") {
c.AfiSafis = append(c.AfiSafis, pg.AfiSafis...)
c.AfiSafis = append([]AfiSafi{}, pg.AfiSafis...)
}
return nil

View File

@@ -1,10 +1,6 @@
package config
import (
"os"
"os/signal"
"syscall"
log "github.com/sirupsen/logrus"
"github.com/spf13/viper"
)
@@ -24,55 +20,25 @@ type BgpConfigSet struct {
DynamicNeighbors []DynamicNeighbor `mapstructure:"dynamic-neighbors"`
}
func ReadConfigfileServe(path, format string, configCh chan *BgpConfigSet) {
sigCh := make(chan os.Signal, 1)
signal.Notify(sigCh, syscall.SIGHUP)
func ReadConfigfile(path, format string) (*BgpConfigSet, error) {
// Update config file type, if detectable
format = detectConfigFileType(path, format)
cnt := 0
for {
c := &BgpConfigSet{}
v := viper.New()
v.SetConfigFile(path)
v.SetConfigType(format)
var err error
if err = v.ReadInConfig(); err != nil {
goto ERROR
}
if err = v.UnmarshalExact(c); err != nil {
goto ERROR
}
if err = setDefaultConfigValuesWithViper(v, c); err != nil {
goto ERROR
}
if cnt == 0 {
log.WithFields(log.Fields{
"Topic": "Config",
}).Info("Finished reading the config file")
}
cnt++
configCh <- c
goto NEXT
ERROR:
if cnt == 0 {
log.WithFields(log.Fields{
"Topic": "Config",
"Error": err,
}).Fatalf("Can't read config file %s", path)
} else {
log.WithFields(log.Fields{
"Topic": "Config",
"Error": err,
}).Warningf("Can't read config file %s", path)
}
NEXT:
<-sigCh
log.WithFields(log.Fields{
"Topic": "Config",
}).Info("Reload the config file")
config := &BgpConfigSet{}
v := viper.New()
v.SetConfigFile(path)
v.SetConfigType(format)
var err error
if err = v.ReadInConfig(); err != nil {
return nil, err
}
if err = v.UnmarshalExact(config); err != nil {
return nil, err
}
if err = setDefaultConfigValuesWithViper(v, config); err != nil {
return nil, err
}
return config, nil
}
func ConfigSetToRoutingPolicy(c *BgpConfigSet) *RoutingPolicy {

View File

@@ -21,7 +21,13 @@ import (
"path/filepath"
"regexp"
"strconv"
"strings"
"time"
"github.com/golang/protobuf/ptypes"
"github.com/golang/protobuf/ptypes/timestamp"
api "github.com/osrg/gobgp/api"
"github.com/osrg/gobgp/internal/pkg/apiutil"
"github.com/osrg/gobgp/pkg/packet/bgp"
)
@@ -203,12 +209,12 @@ func isAfiSafiChanged(x, y []AfiSafi) bool {
if len(x) != len(y) {
return true
}
m := make(map[string]bool)
for _, e := range x {
m[string(e.Config.AfiSafiName)] = true
m := make(map[string]AfiSafi)
for i, e := range x {
m[string(e.Config.AfiSafiName)] = x[i]
}
for _, e := range y {
if !m[string(e.Config.AfiSafiName)] {
if v, ok := m[string(e.Config.AfiSafiName)]; !ok || !v.Config.Equal(&e.Config) || !v.AddPaths.Config.Equal(&e.AddPaths.Config) || !v.MpGracefulRestart.Config.Equal(&e.MpGracefulRestart.Config) {
return true
}
}
@@ -219,6 +225,7 @@ func (n *Neighbor) NeedsResendOpenMessage(new *Neighbor) bool {
return !n.Config.Equal(&new.Config) ||
!n.Transport.Config.Equal(&new.Transport.Config) ||
!n.AddPaths.Config.Equal(&new.AddPaths.Config) ||
!n.AsPathOptions.Config.Equal(&new.AsPathOptions.Config) ||
!n.GracefulRestart.Config.Equal(&new.GracefulRestart.Config) ||
isAfiSafiChanged(n.AfiSafis, new.AfiSafis)
}
@@ -262,3 +269,470 @@ func ParseMaskLength(prefix, mask string) (int, int, error) {
}
return int(min), int(max), nil
}
func extractFamilyFromConfigAfiSafi(c *AfiSafi) uint32 {
if c == nil {
return 0
}
// If address family value is already stored in AfiSafiState structure,
// we prefer to use this value.
if c.State.Family != 0 {
return uint32(c.State.Family)
}
// In case that Neighbor structure came from CLI or gRPC, address family
// value in AfiSafiState structure can be omitted.
// Here extracts value from AfiSafiName field in AfiSafiConfig structure.
if rf, err := bgp.GetRouteFamily(string(c.Config.AfiSafiName)); err == nil {
return uint32(rf)
}
// Ignores invalid address family name
return 0
}
func newAfiSafiConfigFromConfigStruct(c *AfiSafi) *api.AfiSafiConfig {
rf := extractFamilyFromConfigAfiSafi(c)
afi, safi := bgp.RouteFamilyToAfiSafi(bgp.RouteFamily(rf))
return &api.AfiSafiConfig{
Family: &api.Family{Afi: api.Family_Afi(afi), Safi: api.Family_Safi(safi)},
Enabled: c.Config.Enabled,
}
}
func newApplyPolicyFromConfigStruct(c *ApplyPolicy) *api.ApplyPolicy {
applyPolicy := &api.ApplyPolicy{
ImportPolicy: &api.PolicyAssignment{
Direction: api.PolicyDirection_IMPORT,
DefaultAction: api.RouteAction(c.Config.DefaultImportPolicy.ToInt()),
},
ExportPolicy: &api.PolicyAssignment{
Direction: api.PolicyDirection_EXPORT,
DefaultAction: api.RouteAction(c.Config.DefaultExportPolicy.ToInt()),
},
}
for _, pname := range c.Config.ImportPolicyList {
applyPolicy.ImportPolicy.Policies = append(applyPolicy.ImportPolicy.Policies, &api.Policy{Name: pname})
}
for _, pname := range c.Config.ExportPolicyList {
applyPolicy.ExportPolicy.Policies = append(applyPolicy.ExportPolicy.Policies, &api.Policy{Name: pname})
}
return applyPolicy
}
func newPrefixLimitFromConfigStruct(c *AfiSafi) *api.PrefixLimit {
if c.PrefixLimit.Config.MaxPrefixes == 0 {
return nil
}
afi, safi := bgp.RouteFamilyToAfiSafi(bgp.RouteFamily(c.State.Family))
return &api.PrefixLimit{
Family: &api.Family{Afi: api.Family_Afi(afi), Safi: api.Family_Safi(safi)},
MaxPrefixes: c.PrefixLimit.Config.MaxPrefixes,
ShutdownThresholdPct: uint32(c.PrefixLimit.Config.ShutdownThresholdPct),
}
}
func newRouteTargetMembershipFromConfigStruct(c *RouteTargetMembership) *api.RouteTargetMembership {
return &api.RouteTargetMembership{
Config: &api.RouteTargetMembershipConfig{
DeferralTime: uint32(c.Config.DeferralTime),
},
}
}
func newLongLivedGracefulRestartFromConfigStruct(c *LongLivedGracefulRestart) *api.LongLivedGracefulRestart {
return &api.LongLivedGracefulRestart{
Config: &api.LongLivedGracefulRestartConfig{
Enabled: c.Config.Enabled,
RestartTime: c.Config.RestartTime,
},
}
}
func newAddPathsFromConfigStruct(c *AddPaths) *api.AddPaths {
return &api.AddPaths{
Config: &api.AddPathsConfig{
Receive: c.Config.Receive,
SendMax: uint32(c.Config.SendMax),
},
}
}
func newRouteSelectionOptionsFromConfigStruct(c *RouteSelectionOptions) *api.RouteSelectionOptions {
return &api.RouteSelectionOptions{
Config: &api.RouteSelectionOptionsConfig{
AlwaysCompareMed: c.Config.AlwaysCompareMed,
IgnoreAsPathLength: c.Config.IgnoreAsPathLength,
ExternalCompareRouterId: c.Config.ExternalCompareRouterId,
AdvertiseInactiveRoutes: c.Config.AdvertiseInactiveRoutes,
EnableAigp: c.Config.EnableAigp,
IgnoreNextHopIgpMetric: c.Config.IgnoreNextHopIgpMetric,
},
}
}
func newMpGracefulRestartFromConfigStruct(c *MpGracefulRestart) *api.MpGracefulRestart {
return &api.MpGracefulRestart{
Config: &api.MpGracefulRestartConfig{
Enabled: c.Config.Enabled,
},
}
}
func newUseMultiplePathsFromConfigStruct(c *UseMultiplePaths) *api.UseMultiplePaths {
return &api.UseMultiplePaths{
Config: &api.UseMultiplePathsConfig{
Enabled: c.Config.Enabled,
},
Ebgp: &api.Ebgp{
Config: &api.EbgpConfig{
AllowMultipleAs: c.Ebgp.Config.AllowMultipleAs,
MaximumPaths: c.Ebgp.Config.MaximumPaths,
},
},
Ibgp: &api.Ibgp{
Config: &api.IbgpConfig{
MaximumPaths: c.Ibgp.Config.MaximumPaths,
},
},
}
}
func newAfiSafiFromConfigStruct(c *AfiSafi) *api.AfiSafi {
return &api.AfiSafi{
MpGracefulRestart: newMpGracefulRestartFromConfigStruct(&c.MpGracefulRestart),
Config: newAfiSafiConfigFromConfigStruct(c),
ApplyPolicy: newApplyPolicyFromConfigStruct(&c.ApplyPolicy),
RouteSelectionOptions: newRouteSelectionOptionsFromConfigStruct(&c.RouteSelectionOptions),
UseMultiplePaths: newUseMultiplePathsFromConfigStruct(&c.UseMultiplePaths),
PrefixLimits: newPrefixLimitFromConfigStruct(c),
RouteTargetMembership: newRouteTargetMembershipFromConfigStruct(&c.RouteTargetMembership),
LongLivedGracefulRestart: newLongLivedGracefulRestartFromConfigStruct(&c.LongLivedGracefulRestart),
AddPaths: newAddPathsFromConfigStruct(&c.AddPaths),
}
}
func ProtoTimestamp(secs int64) *timestamp.Timestamp {
if secs == 0 {
return nil
}
t, _ := ptypes.TimestampProto(time.Unix(secs, 0))
return t
}
func NewPeerFromConfigStruct(pconf *Neighbor) *api.Peer {
afiSafis := make([]*api.AfiSafi, 0, len(pconf.AfiSafis))
for _, f := range pconf.AfiSafis {
if afiSafi := newAfiSafiFromConfigStruct(&f); afiSafi != nil {
afiSafis = append(afiSafis, afiSafi)
}
}
timer := pconf.Timers
s := pconf.State
localAddress := pconf.Transport.Config.LocalAddress
if pconf.Transport.State.LocalAddress != "" {
localAddress = pconf.Transport.State.LocalAddress
}
remoteCap, err := apiutil.MarshalCapabilities(pconf.State.RemoteCapabilityList)
if err != nil {
return nil
}
localCap, err := apiutil.MarshalCapabilities(pconf.State.LocalCapabilityList)
if err != nil {
return nil
}
var removePrivateAs api.PeerConf_RemovePrivateAs
switch pconf.Config.RemovePrivateAs {
case REMOVE_PRIVATE_AS_OPTION_ALL:
removePrivateAs = api.PeerConf_ALL
case REMOVE_PRIVATE_AS_OPTION_REPLACE:
removePrivateAs = api.PeerConf_REPLACE
}
return &api.Peer{
ApplyPolicy: newApplyPolicyFromConfigStruct(&pconf.ApplyPolicy),
Conf: &api.PeerConf{
NeighborAddress: pconf.Config.NeighborAddress,
PeerAs: pconf.Config.PeerAs,
LocalAs: pconf.Config.LocalAs,
PeerType: uint32(pconf.Config.PeerType.ToInt()),
AuthPassword: pconf.Config.AuthPassword,
RouteFlapDamping: pconf.Config.RouteFlapDamping,
Description: pconf.Config.Description,
PeerGroup: pconf.Config.PeerGroup,
NeighborInterface: pconf.Config.NeighborInterface,
Vrf: pconf.Config.Vrf,
AllowOwnAs: uint32(pconf.AsPathOptions.Config.AllowOwnAs),
RemovePrivateAs: removePrivateAs,
ReplacePeerAs: pconf.AsPathOptions.Config.ReplacePeerAs,
AdminDown: pconf.Config.AdminDown,
},
State: &api.PeerState{
SessionState: api.PeerState_SessionState(api.PeerState_SessionState_value[strings.ToUpper(string(s.SessionState))]),
AdminState: api.PeerState_AdminState(s.AdminState.ToInt()),
Messages: &api.Messages{
Received: &api.Message{
Notification: s.Messages.Received.Notification,
Update: s.Messages.Received.Update,
Open: s.Messages.Received.Open,
Keepalive: s.Messages.Received.Keepalive,
Refresh: s.Messages.Received.Refresh,
Discarded: s.Messages.Received.Discarded,
Total: s.Messages.Received.Total,
WithdrawUpdate: uint64(s.Messages.Received.WithdrawUpdate),
WithdrawPrefix: uint64(s.Messages.Received.WithdrawPrefix),
},
Sent: &api.Message{
Notification: s.Messages.Sent.Notification,
Update: s.Messages.Sent.Update,
Open: s.Messages.Sent.Open,
Keepalive: s.Messages.Sent.Keepalive,
Refresh: s.Messages.Sent.Refresh,
Discarded: s.Messages.Sent.Discarded,
Total: s.Messages.Sent.Total,
},
},
PeerAs: s.PeerAs,
PeerType: uint32(s.PeerType.ToInt()),
NeighborAddress: pconf.State.NeighborAddress,
Queues: &api.Queues{},
RemoteCap: remoteCap,
LocalCap: localCap,
RouterId: s.RemoteRouterId,
},
EbgpMultihop: &api.EbgpMultihop{
Enabled: pconf.EbgpMultihop.Config.Enabled,
MultihopTtl: uint32(pconf.EbgpMultihop.Config.MultihopTtl),
},
Timers: &api.Timers{
Config: &api.TimersConfig{
ConnectRetry: uint64(timer.Config.ConnectRetry),
HoldTime: uint64(timer.Config.HoldTime),
KeepaliveInterval: uint64(timer.Config.KeepaliveInterval),
IdleHoldTimeAfterReset: uint64(timer.Config.IdleHoldTimeAfterReset),
},
State: &api.TimersState{
KeepaliveInterval: uint64(timer.State.KeepaliveInterval),
NegotiatedHoldTime: uint64(timer.State.NegotiatedHoldTime),
Uptime: ProtoTimestamp(timer.State.Uptime),
Downtime: ProtoTimestamp(timer.State.Downtime),
},
},
RouteReflector: &api.RouteReflector{
RouteReflectorClient: pconf.RouteReflector.Config.RouteReflectorClient,
RouteReflectorClusterId: string(pconf.RouteReflector.State.RouteReflectorClusterId),
},
RouteServer: &api.RouteServer{
RouteServerClient: pconf.RouteServer.Config.RouteServerClient,
SecondaryRoute: pconf.RouteServer.Config.SecondaryRoute,
},
GracefulRestart: &api.GracefulRestart{
Enabled: pconf.GracefulRestart.Config.Enabled,
RestartTime: uint32(pconf.GracefulRestart.Config.RestartTime),
HelperOnly: pconf.GracefulRestart.Config.HelperOnly,
DeferralTime: uint32(pconf.GracefulRestart.Config.DeferralTime),
NotificationEnabled: pconf.GracefulRestart.Config.NotificationEnabled,
LonglivedEnabled: pconf.GracefulRestart.Config.LongLivedEnabled,
LocalRestarting: pconf.GracefulRestart.State.LocalRestarting,
},
Transport: &api.Transport{
RemotePort: uint32(pconf.Transport.Config.RemotePort),
LocalAddress: localAddress,
PassiveMode: pconf.Transport.Config.PassiveMode,
BindInterface: pconf.Transport.Config.BindInterface,
},
AfiSafis: afiSafis,
}
}
func NewPeerGroupFromConfigStruct(pconf *PeerGroup) *api.PeerGroup {
afiSafis := make([]*api.AfiSafi, 0, len(pconf.AfiSafis))
for _, f := range pconf.AfiSafis {
if afiSafi := newAfiSafiFromConfigStruct(&f); afiSafi != nil {
afiSafis = append(afiSafis, afiSafi)
}
}
timer := pconf.Timers
s := pconf.State
return &api.PeerGroup{
ApplyPolicy: newApplyPolicyFromConfigStruct(&pconf.ApplyPolicy),
Conf: &api.PeerGroupConf{
PeerAs: pconf.Config.PeerAs,
LocalAs: pconf.Config.LocalAs,
PeerType: uint32(pconf.Config.PeerType.ToInt()),
AuthPassword: pconf.Config.AuthPassword,
RouteFlapDamping: pconf.Config.RouteFlapDamping,
Description: pconf.Config.Description,
PeerGroupName: pconf.Config.PeerGroupName,
},
Info: &api.PeerGroupState{
PeerAs: s.PeerAs,
PeerType: uint32(s.PeerType.ToInt()),
TotalPaths: s.TotalPaths,
TotalPrefixes: s.TotalPrefixes,
},
EbgpMultihop: &api.EbgpMultihop{
Enabled: pconf.EbgpMultihop.Config.Enabled,
MultihopTtl: uint32(pconf.EbgpMultihop.Config.MultihopTtl),
},
Timers: &api.Timers{
Config: &api.TimersConfig{
ConnectRetry: uint64(timer.Config.ConnectRetry),
HoldTime: uint64(timer.Config.HoldTime),
KeepaliveInterval: uint64(timer.Config.KeepaliveInterval),
IdleHoldTimeAfterReset: uint64(timer.Config.IdleHoldTimeAfterReset),
},
State: &api.TimersState{
KeepaliveInterval: uint64(timer.State.KeepaliveInterval),
NegotiatedHoldTime: uint64(timer.State.NegotiatedHoldTime),
Uptime: ProtoTimestamp(timer.State.Uptime),
Downtime: ProtoTimestamp(timer.State.Downtime),
},
},
RouteReflector: &api.RouteReflector{
RouteReflectorClient: pconf.RouteReflector.Config.RouteReflectorClient,
RouteReflectorClusterId: string(pconf.RouteReflector.Config.RouteReflectorClusterId),
},
RouteServer: &api.RouteServer{
RouteServerClient: pconf.RouteServer.Config.RouteServerClient,
SecondaryRoute: pconf.RouteServer.Config.SecondaryRoute,
},
GracefulRestart: &api.GracefulRestart{
Enabled: pconf.GracefulRestart.Config.Enabled,
RestartTime: uint32(pconf.GracefulRestart.Config.RestartTime),
HelperOnly: pconf.GracefulRestart.Config.HelperOnly,
DeferralTime: uint32(pconf.GracefulRestart.Config.DeferralTime),
NotificationEnabled: pconf.GracefulRestart.Config.NotificationEnabled,
LonglivedEnabled: pconf.GracefulRestart.Config.LongLivedEnabled,
LocalRestarting: pconf.GracefulRestart.State.LocalRestarting,
},
Transport: &api.Transport{
RemotePort: uint32(pconf.Transport.Config.RemotePort),
LocalAddress: pconf.Transport.Config.LocalAddress,
PassiveMode: pconf.Transport.Config.PassiveMode,
},
AfiSafis: afiSafis,
}
}
func NewGlobalFromConfigStruct(c *Global) *api.Global {
families := make([]uint32, 0, len(c.AfiSafis))
for _, f := range c.AfiSafis {
families = append(families, uint32(AfiSafiTypeToIntMap[f.Config.AfiSafiName]))
}
applyPolicy := newApplyPolicyFromConfigStruct(&c.ApplyPolicy)
return &api.Global{
As: c.Config.As,
RouterId: c.Config.RouterId,
ListenPort: c.Config.Port,
ListenAddresses: c.Config.LocalAddressList,
Families: families,
UseMultiplePaths: c.UseMultiplePaths.Config.Enabled,
RouteSelectionOptions: &api.RouteSelectionOptionsConfig{
AlwaysCompareMed: c.RouteSelectionOptions.Config.AlwaysCompareMed,
IgnoreAsPathLength: c.RouteSelectionOptions.Config.IgnoreAsPathLength,
ExternalCompareRouterId: c.RouteSelectionOptions.Config.ExternalCompareRouterId,
AdvertiseInactiveRoutes: c.RouteSelectionOptions.Config.AdvertiseInactiveRoutes,
EnableAigp: c.RouteSelectionOptions.Config.EnableAigp,
IgnoreNextHopIgpMetric: c.RouteSelectionOptions.Config.IgnoreNextHopIgpMetric,
DisableBestPathSelection: c.RouteSelectionOptions.Config.DisableBestPathSelection,
},
DefaultRouteDistance: &api.DefaultRouteDistance{
ExternalRouteDistance: uint32(c.DefaultRouteDistance.Config.ExternalRouteDistance),
InternalRouteDistance: uint32(c.DefaultRouteDistance.Config.InternalRouteDistance),
},
Confederation: &api.Confederation{
Enabled: c.Confederation.Config.Enabled,
Identifier: c.Confederation.Config.Identifier,
MemberAsList: c.Confederation.Config.MemberAsList,
},
GracefulRestart: &api.GracefulRestart{
Enabled: c.GracefulRestart.Config.Enabled,
RestartTime: uint32(c.GracefulRestart.Config.RestartTime),
StaleRoutesTime: uint32(c.GracefulRestart.Config.StaleRoutesTime),
HelperOnly: c.GracefulRestart.Config.HelperOnly,
DeferralTime: uint32(c.GracefulRestart.Config.DeferralTime),
NotificationEnabled: c.GracefulRestart.Config.NotificationEnabled,
LonglivedEnabled: c.GracefulRestart.Config.LongLivedEnabled,
},
ApplyPolicy: applyPolicy,
}
}
func newAPIPrefixFromConfigStruct(c Prefix) (*api.Prefix, error) {
min, max, err := ParseMaskLength(c.IpPrefix, c.MasklengthRange)
if err != nil {
return nil, err
}
return &api.Prefix{
IpPrefix: c.IpPrefix,
MaskLengthMin: uint32(min),
MaskLengthMax: uint32(max),
}, nil
}
func NewAPIDefinedSetsFromConfigStruct(t *DefinedSets) ([]*api.DefinedSet, error) {
definedSets := make([]*api.DefinedSet, 0)
for _, ps := range t.PrefixSets {
prefixes := make([]*api.Prefix, 0)
for _, p := range ps.PrefixList {
ap, err := newAPIPrefixFromConfigStruct(p)
if err != nil {
return nil, err
}
prefixes = append(prefixes, ap)
}
definedSets = append(definedSets, &api.DefinedSet{
DefinedType: api.DefinedType_PREFIX,
Name: ps.PrefixSetName,
Prefixes: prefixes,
})
}
for _, ns := range t.NeighborSets {
definedSets = append(definedSets, &api.DefinedSet{
DefinedType: api.DefinedType_NEIGHBOR,
Name: ns.NeighborSetName,
List: ns.NeighborInfoList,
})
}
bs := t.BgpDefinedSets
for _, cs := range bs.CommunitySets {
definedSets = append(definedSets, &api.DefinedSet{
DefinedType: api.DefinedType_COMMUNITY,
Name: cs.CommunitySetName,
List: cs.CommunityList,
})
}
for _, es := range bs.ExtCommunitySets {
definedSets = append(definedSets, &api.DefinedSet{
DefinedType: api.DefinedType_EXT_COMMUNITY,
Name: es.ExtCommunitySetName,
List: es.ExtCommunityList,
})
}
for _, ls := range bs.LargeCommunitySets {
definedSets = append(definedSets, &api.DefinedSet{
DefinedType: api.DefinedType_LARGE_COMMUNITY,
Name: ls.LargeCommunitySetName,
List: ls.LargeCommunityList,
})
}
for _, as := range bs.AsPathSets {
definedSets = append(definedSets, &api.DefinedSet{
DefinedType: api.DefinedType_AS_PATH,
Name: as.AsPathSetName,
List: as.AsPathList,
})
}
return definedSets, nil
}

View File

@@ -23,16 +23,16 @@ import (
type AdjRib struct {
accepted map[bgp.RouteFamily]int
table map[bgp.RouteFamily]map[string]*Path
table map[bgp.RouteFamily]*Table
}
func NewAdjRib(rfList []bgp.RouteFamily) *AdjRib {
table := make(map[bgp.RouteFamily]map[string]*Path)
for _, rf := range rfList {
table[rf] = make(map[string]*Path)
m := make(map[bgp.RouteFamily]*Table)
for _, f := range rfList {
m[f] = NewTable(f)
}
return &AdjRib{
table: table,
table: m,
accepted: make(map[bgp.RouteFamily]int),
}
}
@@ -43,56 +43,100 @@ func (adj *AdjRib) Update(pathList []*Path) {
continue
}
rf := path.GetRouteFamily()
key := fmt.Sprintf("%d:%s", path.GetNlri().PathIdentifier(), path.getPrefix())
t := adj.table[path.GetRouteFamily()]
d := t.getOrCreateDest(path.GetNlri(), 0)
var old *Path
idx := -1
for i, p := range d.knownPathList {
if p.GetNlri().PathIdentifier() == path.GetNlri().PathIdentifier() {
idx = i
break
}
}
if idx != -1 {
old = d.knownPathList[idx]
}
old, found := adj.table[rf][key]
if path.IsWithdraw {
if found {
delete(adj.table[rf], key)
if !old.IsAsLooped() {
if idx != -1 {
d.knownPathList = append(d.knownPathList[:idx], d.knownPathList[idx+1:]...)
if len(d.knownPathList) == 0 {
t.deleteDest(d)
}
if !old.IsRejected() {
adj.accepted[rf]--
}
}
path.SetDropped(true)
} else {
if found {
if old.IsAsLooped() && !path.IsAsLooped() {
if idx != -1 {
if old.IsRejected() && !path.IsRejected() {
adj.accepted[rf]++
} else if !old.IsAsLooped() && path.IsAsLooped() {
} else if !old.IsRejected() && path.IsRejected() {
adj.accepted[rf]--
}
if old.Equal(path) {
path.setTimestamp(old.GetTimestamp())
}
d.knownPathList[idx] = path
} else {
if !path.IsAsLooped() {
d.knownPathList = append(d.knownPathList, path)
if !path.IsRejected() {
adj.accepted[rf]++
}
}
if found && old.Equal(path) {
path.setTimestamp(old.GetTimestamp())
}
}
}
/* The provided pathList is expected to be the real candidate routes after policy evaluation.
For routes that are filtered by policy, there could be a mismatch between display
and actual rib sent to the peer (if softreset out was not run).
Only used to display adj-out because we do not maintain a separate adj-out table
*/
func (adj *AdjRib) UpdateAdjRibOut(pathList []*Path) {
for _, path := range pathList {
if path == nil || path.IsEOR() {
continue
}
t := adj.table[path.GetRouteFamily()]
d := t.getOrCreateDest(path.GetNlri(), 0)
d.knownPathList = append(d.knownPathList, path)
}
}
func (adj *AdjRib) walk(families []bgp.RouteFamily, fn func(*Destination) bool) {
for _, f := range families {
if t, ok := adj.table[f]; ok {
for _, d := range t.destinations {
if fn(d) {
return
}
}
adj.table[rf][key] = path
}
}
}
func (adj *AdjRib) PathList(rfList []bgp.RouteFamily, accepted bool) []*Path {
pathList := make([]*Path, 0, adj.Count(rfList))
for _, rf := range rfList {
for _, rr := range adj.table[rf] {
if accepted && rr.IsAsLooped() {
adj.walk(rfList, func(d *Destination) bool {
for _, p := range d.knownPathList {
if accepted && p.IsRejected() {
continue
}
pathList = append(pathList, rr)
pathList = append(pathList, p)
}
}
return false
})
return pathList
}
func (adj *AdjRib) Count(rfList []bgp.RouteFamily) int {
count := 0
for _, rf := range rfList {
if table, ok := adj.table[rf]; ok {
count += len(table)
}
}
adj.walk(rfList, func(d *Destination) bool {
count += len(d.knownPathList)
return false
})
return count
}
@@ -106,70 +150,88 @@ func (adj *AdjRib) Accepted(rfList []bgp.RouteFamily) int {
return count
}
func (adj *AdjRib) Drop(rfList []bgp.RouteFamily) {
for _, rf := range rfList {
if _, ok := adj.table[rf]; ok {
adj.table[rf] = make(map[string]*Path)
adj.accepted[rf] = 0
func (adj *AdjRib) Drop(rfList []bgp.RouteFamily) []*Path {
l := make([]*Path, 0, adj.Count(rfList))
adj.walk(rfList, func(d *Destination) bool {
for _, p := range d.knownPathList {
w := p.Clone(true)
w.SetDropped(true)
l = append(l, w)
}
return false
})
for _, rf := range rfList {
adj.table[rf] = NewTable(rf)
adj.accepted[rf] = 0
}
return l
}
func (adj *AdjRib) DropStale(rfList []bgp.RouteFamily) []*Path {
pathList := make([]*Path, 0, adj.Count(rfList))
for _, rf := range rfList {
if table, ok := adj.table[rf]; ok {
for k, p := range table {
if p.IsStale() {
delete(table, k)
if !p.IsAsLooped() {
adj.accepted[rf]--
}
pathList = append(pathList, p.Clone(true))
}
adj.walk(rfList, func(d *Destination) bool {
for _, p := range d.knownPathList {
if p.IsStale() {
w := p.Clone(true)
w.SetDropped(true)
pathList = append(pathList, w)
}
}
}
return false
})
adj.Update(pathList)
return pathList
}
func (adj *AdjRib) StaleAll(rfList []bgp.RouteFamily) []*Path {
pathList := make([]*Path, 0)
for _, rf := range rfList {
if table, ok := adj.table[rf]; ok {
l := make([]*Path, 0, len(table))
for k, p := range table {
n := p.Clone(false)
n.MarkStale(true)
table[k] = n
l = append(l, n)
}
if len(l) > 0 {
pathList = append(pathList, l...)
pathList := make([]*Path, 0, adj.Count(rfList))
adj.walk(rfList, func(d *Destination) bool {
for i, p := range d.knownPathList {
n := p.Clone(false)
n.MarkStale(true)
n.SetRejected(p.IsRejected())
d.knownPathList[i] = n
if !n.IsRejected() {
pathList = append(pathList, n)
}
}
}
return false
})
return pathList
}
func (adj *AdjRib) MarkLLGRStaleOrDrop(rfList []bgp.RouteFamily) []*Path {
pathList := make([]*Path, 0, adj.Count(rfList))
adj.walk(rfList, func(d *Destination) bool {
for i, p := range d.knownPathList {
if p.HasNoLLGR() {
n := p.Clone(true)
n.SetDropped(true)
pathList = append(pathList, n)
} else {
n := p.Clone(false)
n.SetRejected(p.IsRejected())
n.SetCommunities([]uint32{uint32(bgp.COMMUNITY_LLGR_STALE)}, false)
if p.IsRejected() {
d.knownPathList[i] = n
} else {
pathList = append(pathList, n)
}
}
}
return false
})
adj.Update(pathList)
return pathList
}
func (adj *AdjRib) Select(family bgp.RouteFamily, accepted bool, option ...TableSelectOption) (*Table, error) {
m := make(map[string][]*Path)
pl := adj.PathList([]bgp.RouteFamily{family}, accepted)
for _, path := range pl {
key := path.GetNlri().String()
if _, y := m[key]; y {
m[key] = append(m[key], path)
} else {
m[key] = []*Path{path}
}
t, ok := adj.table[family]
if !ok {
t = NewTable(family)
}
d := make([]*Destination, 0, len(pl))
for _, l := range m {
d = append(d, NewDestination(l[0].GetNlri(), 0, l...))
}
tbl := NewTable(family, d...)
option = append(option, TableSelectOption{adj: true})
return tbl.Select(option...)
return t.Select(option...)
}
func (adj *AdjRib) TableInfo(family bgp.RouteFamily) (*TableInfo, error) {

View File

@@ -74,38 +74,6 @@ func (r *BestPathReason) String() string {
return BestPathReasonStringMap[*r]
}
func IpToRadixkey(b []byte, max uint8) string {
var buffer bytes.Buffer
for i := 0; i < len(b) && i < int(max); i++ {
fmt.Fprintf(&buffer, "%08b", b[i])
}
return buffer.String()[:max]
}
func CidrToRadixkey(cidr string) string {
_, n, _ := net.ParseCIDR(cidr)
ones, _ := n.Mask.Size()
return IpToRadixkey(n.IP, uint8(ones))
}
func AddrToRadixkey(addr bgp.AddrPrefixInterface) string {
var (
ip net.IP
size uint8
)
switch T := addr.(type) {
case *bgp.IPAddrPrefix:
mask := net.CIDRMask(int(T.Length), net.IPv4len*8)
ip, size = T.Prefix.Mask(mask).To4(), uint8(T.Length)
case *bgp.IPv6AddrPrefix:
mask := net.CIDRMask(int(T.Length), net.IPv6len*8)
ip, size = T.Prefix.Mask(mask).To16(), uint8(T.Length)
default:
return CidrToRadixkey(addr.String())
}
return IpToRadixkey(ip, size)
}
type PeerInfo struct {
AS uint32
ID net.IP
@@ -265,7 +233,7 @@ func (dest *Destination) Calculate(newPath *Path) *Update {
if newPath.IsWithdraw {
p := dest.explicitWithdraw(newPath)
if p != nil {
if p != nil && newPath.IsDropped() {
if id := p.GetNlri().PathLocalIdentifier(); id != 0 {
dest.localIdMap.Unflag(uint(id))
}
@@ -405,17 +373,19 @@ func (dest *Destination) computeKnownBestPath() (*Path, BestPathReason, error) {
}
return dest.knownPathList[0], BPR_ONLY_PATH, nil
}
dest.sort()
reason := dest.sort()
newBest := dest.knownPathList[0]
// If the first path has the invalidated next-hop, which evaluated by IGP,
// returns no path with the reason of the next-hop reachability.
if dest.knownPathList[0].IsNexthopInvalid {
return nil, BPR_REACHABLE_NEXT_HOP, nil
}
return newBest, newBest.reason, nil
return newBest, reason, nil
}
func (dst *Destination) sort() {
func (dst *Destination) sort() BestPathReason {
reason := BPR_UNKNOWN
sort.SliceStable(dst.knownPathList, func(i, j int) bool {
//Compares given paths and returns best path.
//
@@ -451,7 +421,6 @@ func (dst *Destination) sort() {
path2 := dst.knownPathList[j]
var better *Path
reason := BPR_UNKNOWN
// draft-uttaro-idr-bgp-persistence-02
if better == nil {
@@ -501,7 +470,7 @@ func (dst *Destination) sort() {
reason = BPR_OLDER
}
if better == nil {
var e error = nil
var e error
better, e = compareByRouterID(path1, path2)
if e != nil {
log.WithFields(log.Fields{
@@ -515,11 +484,9 @@ func (dst *Destination) sort() {
reason = BPR_UNKNOWN
better = path1
}
better.reason = reason
return better == path1
})
return reason
}
type Update struct {
@@ -933,7 +900,7 @@ func compareByRouterID(path1, path2 *Path) (*Path, error) {
}
if !SelectionOptions.ExternalCompareRouterId && path1.IsIBGP() != path2.IsIBGP() {
return nil, fmt.Errorf("This method does not support comparing ebgp with ibgp path")
return nil, fmt.Errorf("this method does not support comparing ebgp with ibgp path")
}
// At least one path is not coming from NC, so we get local bgp id.

View File

@@ -85,9 +85,9 @@ func UpdatePathAttrs4ByteAs(msg *bgp.BGPUpdate) error {
asAttrPos := 0
as4AttrPos := 0
for i, attr := range msg.PathAttributes {
switch attr.(type) {
switch a := attr.(type) {
case *bgp.PathAttributeAsPath:
asAttr = attr.(*bgp.PathAttributeAsPath)
asAttr = a
for j, param := range asAttr.Value {
as2Param, ok := param.(*bgp.AsPathParam)
if ok {
@@ -103,7 +103,7 @@ func UpdatePathAttrs4ByteAs(msg *bgp.BGPUpdate) error {
msg.PathAttributes[i] = asAttr
case *bgp.PathAttributeAs4Path:
as4AttrPos = i
as4Attr = attr.(*bgp.PathAttributeAs4Path)
as4Attr = a
}
}
@@ -130,8 +130,9 @@ func UpdatePathAttrs4ByteAs(msg *bgp.BGPUpdate) error {
}
as4Len := 0
as4Params := make([]bgp.AsPathParamInterface, 0, len(as4Attr.Value))
var as4Params []bgp.AsPathParamInterface
if as4Attr != nil {
as4Params = make([]bgp.AsPathParamInterface, 0, len(as4Attr.Value))
for _, p := range as4Attr.Value {
// RFC 6793 6. Error Handling
//
@@ -211,9 +212,8 @@ func UpdatePathAggregator2ByteAs(msg *bgp.BGPUpdate) {
as := uint32(0)
var addr string
for i, attr := range msg.PathAttributes {
switch attr.(type) {
switch agg := attr.(type) {
case *bgp.PathAttributeAggregator:
agg := attr.(*bgp.PathAttributeAggregator)
addr = agg.Value.Address.String()
if agg.Value.AS > (1<<16)-1 {
as = agg.Value.AS
@@ -233,15 +233,15 @@ func UpdatePathAggregator4ByteAs(msg *bgp.BGPUpdate) error {
var agg4Attr *bgp.PathAttributeAs4Aggregator
agg4AttrPos := 0
for i, attr := range msg.PathAttributes {
switch attr.(type) {
switch agg := attr.(type) {
case *bgp.PathAttributeAggregator:
attr := attr.(*bgp.PathAttributeAggregator)
attr := agg
if attr.Value.Askind == reflect.Uint16 {
aggAttr = attr
aggAttr.Value.Askind = reflect.Uint32
}
case *bgp.PathAttributeAs4Aggregator:
agg4Attr = attr.(*bgp.PathAttributeAs4Aggregator)
agg4Attr = agg
agg4AttrPos = i
}
}

View File

@@ -89,7 +89,6 @@ type originInfo struct {
nlri bgp.AddrPrefixInterface
source *PeerInfo
timestamp int64
validation *Validation
noImplicitWithdraw bool
isFromExternal bool
eor bool
@@ -138,15 +137,21 @@ type Path struct {
pathAttrs []bgp.PathAttributeInterface
dels []bgp.BGPAttrType
attrsHash uint32
aslooped bool
reason BestPathReason
rejected bool
// doesn't exist in the adj
dropped bool
// For BGP Nexthop Tracking, this field shows if nexthop is invalidated by IGP.
IsNexthopInvalid bool
IsWithdraw bool
}
var localSource = &PeerInfo{}
func NewPath(source *PeerInfo, nlri bgp.AddrPrefixInterface, isWithdraw bool, pattrs []bgp.PathAttributeInterface, timestamp time.Time, noImplicitWithdraw bool) *Path {
if source == nil {
source = localSource
}
if !isWithdraw && pattrs == nil {
log.WithFields(log.Fields{
"Topic": "Table",
@@ -323,7 +328,8 @@ func (path *Path) IsLocal() bool {
}
func (path *Path) IsIBGP() bool {
return path.GetSource().AS == path.GetSource().LocalAS
as := path.GetSource().AS
return (as == path.GetSource().LocalAS) && as != 0
}
// create new PathAttributes
@@ -352,22 +358,6 @@ func (path *Path) NoImplicitWithdraw() bool {
return path.OriginInfo().noImplicitWithdraw
}
func (path *Path) Validation() *Validation {
return path.OriginInfo().validation
}
func (path *Path) ValidationStatus() config.RpkiValidationResultType {
if v := path.OriginInfo().validation; v != nil {
return v.Status
} else {
return config.RPKI_VALIDATION_RESULT_TYPE_NONE
}
}
func (path *Path) SetValidation(v *Validation) {
path.OriginInfo().validation = v
}
func (path *Path) IsFromExternal() bool {
return path.OriginInfo().isFromExternal
}
@@ -380,9 +370,6 @@ func (path *Path) GetRouteFamily() bgp.RouteFamily {
return bgp.AfiSafiToRouteFamily(path.OriginInfo().nlri.AFI(), path.OriginInfo().nlri.SAFI())
}
func (path *Path) SetSource(source *PeerInfo) {
path.OriginInfo().source = source
}
func (path *Path) GetSource() *PeerInfo {
return path.OriginInfo().source
}
@@ -395,12 +382,29 @@ func (path *Path) IsStale() bool {
return path.OriginInfo().stale
}
func (path *Path) IsAsLooped() bool {
return path.aslooped
func (path *Path) IsRejected() bool {
return path.rejected
}
func (path *Path) SetAsLooped(y bool) {
path.aslooped = y
func (path *Path) SetRejected(y bool) {
path.rejected = y
}
func (path *Path) IsDropped() bool {
return path.dropped
}
func (path *Path) SetDropped(y bool) {
path.dropped = y
}
func (path *Path) HasNoLLGR() bool {
for _, c := range path.GetCommunities() {
if c == uint32(bgp.COMMUNITY_NO_LLGR) {
return true
}
}
return false
}
func (path *Path) IsLLGRStale() bool {
@@ -897,6 +901,12 @@ func (path *Path) GetLargeCommunities() []*bgp.LargeCommunity {
}
func (path *Path) SetLargeCommunities(cs []*bgp.LargeCommunity, doReplace bool) {
if len(cs) == 0 && doReplace {
// clear large communities
path.delPathAttr(bgp.BGP_ATTR_TYPE_LARGE_COMMUNITY)
return
}
a := path.getPathAttr(bgp.BGP_ATTR_TYPE_LARGE_COMMUNITY)
if a == nil || doReplace {
path.setPathAttr(bgp.NewPathAttributeLargeCommunities(cs))
@@ -1016,7 +1026,6 @@ func (path *Path) MarshalJSON() ([]byte, error) {
PathAttrs: path.GetPathAttrs(),
Age: path.GetTimestamp().Unix(),
Withdrawal: path.IsWithdraw,
Validation: string(path.ValidationStatus()),
SourceID: path.GetSource().ID,
NeighborIP: path.GetSource().Address,
Stale: path.IsStale(),
@@ -1066,12 +1075,22 @@ func (v *Vrf) ToGlobalPath(path *Path) error {
case bgp.RF_IPv4_UC:
n := nlri.(*bgp.IPAddrPrefix)
pathIdentifier := path.GetNlri().PathIdentifier()
path.OriginInfo().nlri = bgp.NewLabeledVPNIPAddrPrefix(n.Length, n.Prefix.String(), *bgp.NewMPLSLabelStack(0), v.Rd)
path.OriginInfo().nlri = bgp.NewLabeledVPNIPAddrPrefix(n.Length, n.Prefix.String(), *bgp.NewMPLSLabelStack(v.MplsLabel), v.Rd)
path.GetNlri().SetPathIdentifier(pathIdentifier)
case bgp.RF_FS_IPv4_UC:
n := nlri.(*bgp.FlowSpecIPv4Unicast)
pathIdentifier := path.GetNlri().PathIdentifier()
path.OriginInfo().nlri = bgp.NewFlowSpecIPv4VPN(v.Rd, n.FlowSpecNLRI.Value)
path.GetNlri().SetPathIdentifier(pathIdentifier)
case bgp.RF_IPv6_UC:
n := nlri.(*bgp.IPv6AddrPrefix)
pathIdentifier := path.GetNlri().PathIdentifier()
path.OriginInfo().nlri = bgp.NewLabeledVPNIPv6AddrPrefix(n.Length, n.Prefix.String(), *bgp.NewMPLSLabelStack(0), v.Rd)
path.OriginInfo().nlri = bgp.NewLabeledVPNIPv6AddrPrefix(n.Length, n.Prefix.String(), *bgp.NewMPLSLabelStack(v.MplsLabel), v.Rd)
path.GetNlri().SetPathIdentifier(pathIdentifier)
case bgp.RF_FS_IPv6_UC:
n := nlri.(*bgp.FlowSpecIPv6Unicast)
pathIdentifier := path.GetNlri().PathIdentifier()
path.OriginInfo().nlri = bgp.NewFlowSpecIPv6VPN(v.Rd, n.FlowSpecNLRI.Value)
path.GetNlri().SetPathIdentifier(pathIdentifier)
case bgp.RF_EVPN:
n := nlri.(*bgp.EVPNNLRI)
@@ -1095,11 +1114,11 @@ func (p *Path) ToGlobal(vrf *Vrf) *Path {
switch rf := p.GetRouteFamily(); rf {
case bgp.RF_IPv4_UC:
n := nlri.(*bgp.IPAddrPrefix)
nlri = bgp.NewLabeledVPNIPAddrPrefix(n.Length, n.Prefix.String(), *bgp.NewMPLSLabelStack(0), vrf.Rd)
nlri = bgp.NewLabeledVPNIPAddrPrefix(n.Length, n.Prefix.String(), *bgp.NewMPLSLabelStack(vrf.MplsLabel), vrf.Rd)
nlri.SetPathIdentifier(pathId)
case bgp.RF_IPv6_UC:
n := nlri.(*bgp.IPv6AddrPrefix)
nlri = bgp.NewLabeledVPNIPv6AddrPrefix(n.Length, n.Prefix.String(), *bgp.NewMPLSLabelStack(0), vrf.Rd)
nlri = bgp.NewLabeledVPNIPv6AddrPrefix(n.Length, n.Prefix.String(), *bgp.NewMPLSLabelStack(vrf.MplsLabel), vrf.Rd)
nlri.SetPathIdentifier(pathId)
case bgp.RF_EVPN:
n := nlri.(*bgp.EVPNNLRI)
@@ -1134,7 +1153,6 @@ func (p *Path) ToGlobal(vrf *Vrf) *Path {
path.SetExtCommunities(vrf.ExportRt, false)
path.delPathAttr(bgp.BGP_ATTR_TYPE_NEXT_HOP)
path.setPathAttr(bgp.NewPathAttributeMpReachNLRI(nh.String(), []bgp.AddrPrefixInterface{nlri}))
path.IsNexthopInvalid = p.IsNexthopInvalid
return path
}
@@ -1149,17 +1167,39 @@ func (p *Path) ToLocal() *Path {
ones, _ := c.Mask.Size()
nlri = bgp.NewIPAddrPrefix(uint8(ones), c.IP.String())
nlri.SetPathLocalIdentifier(pathId)
case bgp.RF_FS_IPv4_VPN:
n := nlri.(*bgp.FlowSpecIPv4VPN)
nlri = bgp.NewFlowSpecIPv4Unicast(n.FlowSpecNLRI.Value)
nlri.SetPathLocalIdentifier(pathId)
case bgp.RF_IPv6_VPN:
n := nlri.(*bgp.LabeledVPNIPv6AddrPrefix)
_, c, _ := net.ParseCIDR(n.IPPrefix())
ones, _ := c.Mask.Size()
nlri = bgp.NewIPv6AddrPrefix(uint8(ones), c.IP.String())
nlri.SetPathLocalIdentifier(pathId)
case bgp.RF_FS_IPv6_VPN:
n := nlri.(*bgp.FlowSpecIPv6VPN)
nlri = bgp.NewFlowSpecIPv6Unicast(n.FlowSpecNLRI.Value)
nlri.SetPathLocalIdentifier(pathId)
default:
return p
}
path := NewPath(p.OriginInfo().source, nlri, p.IsWithdraw, p.GetPathAttrs(), p.GetTimestamp(), false)
path.delPathAttr(bgp.BGP_ATTR_TYPE_EXTENDED_COMMUNITIES)
switch f {
case bgp.RF_IPv4_VPN, bgp.RF_IPv6_VPN:
path.delPathAttr(bgp.BGP_ATTR_TYPE_EXTENDED_COMMUNITIES)
case bgp.RF_FS_IPv4_VPN, bgp.RF_FS_IPv6_VPN:
extcomms := path.GetExtCommunities()
newExtComms := make([]bgp.ExtendedCommunityInterface, 0, len(extcomms))
for _, extComm := range extcomms {
_, subType := extComm.GetTypes()
if subType == bgp.EC_SUBTYPE_ROUTE_TARGET {
continue
}
newExtComms = append(newExtComms, extComm)
}
path.SetExtCommunities(newExtComms, true)
}
if f == bgp.RF_IPv4_VPN {
nh := path.GetNexthop()
@@ -1177,3 +1217,29 @@ func (p *Path) SetHash(v uint32) {
func (p *Path) GetHash() uint32 {
return p.attrsHash
}
func nlriToIPNet(nlri bgp.AddrPrefixInterface) *net.IPNet {
switch T := nlri.(type) {
case *bgp.IPAddrPrefix:
return &net.IPNet{
IP: net.IP(T.Prefix.To4()),
Mask: net.CIDRMask(int(T.Length), 32),
}
case *bgp.IPv6AddrPrefix:
return &net.IPNet{
IP: net.IP(T.Prefix.To16()),
Mask: net.CIDRMask(int(T.Length), 128),
}
case *bgp.LabeledIPAddrPrefix:
return &net.IPNet{
IP: net.IP(T.Prefix.To4()),
Mask: net.CIDRMask(int(T.Length), 32),
}
case *bgp.LabeledIPv6AddrPrefix:
return &net.IPNet{
IP: net.IP(T.Prefix.To4()),
Mask: net.CIDRMask(int(T.Length), 128),
}
}
return nil
}

View File

@@ -16,7 +16,6 @@
package table
import (
"bytes"
"encoding/json"
"fmt"
"net"
@@ -27,17 +26,17 @@ import (
"strings"
"sync"
"github.com/k-sone/critbitgo"
api "github.com/osrg/gobgp/api"
"github.com/osrg/gobgp/internal/pkg/config"
"github.com/osrg/gobgp/pkg/packet/bgp"
radix "github.com/armon/go-radix"
log "github.com/sirupsen/logrus"
)
type PolicyOptions struct {
Info *PeerInfo
ValidationResult *Validation
OldNextHop net.IP
Info *PeerInfo
OldNextHop net.IP
Validate func(*Path) *Validation
}
type DefinedType int
@@ -353,7 +352,7 @@ func NewPrefix(c config.Prefix) (*Prefix, error) {
type PrefixSet struct {
name string
tree *radix.Tree
tree *critbitgo.Net
family bgp.RouteFamily
}
@@ -370,29 +369,25 @@ func (lhs *PrefixSet) Append(arg DefinedSet) error {
if !ok {
return fmt.Errorf("type cast failed")
}
// if either is empty, family can be ignored.
if lhs.tree.Len() != 0 && rhs.tree.Len() != 0 {
_, w, _ := lhs.tree.Minimum()
l := w.([]*Prefix)
_, v, _ := rhs.tree.Minimum()
r := v.([]*Prefix)
if l[0].AddressFamily != r[0].AddressFamily {
return fmt.Errorf("can't append different family")
}
if rhs.tree.Size() == 0 {
// if try to append an empty set, then return directly
return nil
} else if lhs.tree.Size() != 0 && rhs.family != lhs.family {
return fmt.Errorf("can't append different family")
}
rhs.tree.Walk(func(key string, v interface{}) bool {
w, ok := lhs.tree.Get(key)
rhs.tree.Walk(nil, func(r *net.IPNet, v interface{}) bool {
w, ok, _ := lhs.tree.Get(r)
if ok {
r := v.([]*Prefix)
l := w.([]*Prefix)
lhs.tree.Insert(key, append(l, r...))
rp := v.([]*Prefix)
lp := w.([]*Prefix)
lhs.tree.Add(r, append(lp, rp...))
} else {
lhs.tree.Insert(key, v)
lhs.tree.Add(r, v)
}
return false
return true
})
_, w, _ := lhs.tree.Minimum()
lhs.family = w.([]*Prefix)[0].AddressFamily
lhs.family = rhs.family
return nil
}
@@ -401,17 +396,17 @@ func (lhs *PrefixSet) Remove(arg DefinedSet) error {
if !ok {
return fmt.Errorf("type cast failed")
}
rhs.tree.Walk(func(key string, v interface{}) bool {
w, ok := lhs.tree.Get(key)
rhs.tree.Walk(nil, func(r *net.IPNet, v interface{}) bool {
w, ok, _ := lhs.tree.Get(r)
if !ok {
return false
return true
}
r := v.([]*Prefix)
l := w.([]*Prefix)
new := make([]*Prefix, 0, len(l))
for _, lp := range l {
rp := v.([]*Prefix)
lp := w.([]*Prefix)
new := make([]*Prefix, 0, len(lp))
for _, lp := range lp {
delete := false
for _, rp := range r {
for _, rp := range rp {
if lp.Equal(rp) {
delete = true
break
@@ -422,11 +417,11 @@ func (lhs *PrefixSet) Remove(arg DefinedSet) error {
}
}
if len(new) == 0 {
lhs.tree.Delete(key)
lhs.tree.Delete(r)
} else {
lhs.tree.Insert(key, new)
lhs.tree.Add(r, new)
}
return false
return true
})
return nil
}
@@ -443,24 +438,24 @@ func (lhs *PrefixSet) Replace(arg DefinedSet) error {
func (s *PrefixSet) List() []string {
var list []string
s.tree.Walk(func(s string, v interface{}) bool {
s.tree.Walk(nil, func(_ *net.IPNet, v interface{}) bool {
ps := v.([]*Prefix)
for _, p := range ps {
list = append(list, fmt.Sprintf("%s %d..%d", p.PrefixString(), p.MasklengthRangeMin, p.MasklengthRangeMax))
}
return false
return true
})
return list
}
func (s *PrefixSet) ToConfig() *config.PrefixSet {
list := make([]config.Prefix, 0, s.tree.Len())
s.tree.Walk(func(s string, v interface{}) bool {
list := make([]config.Prefix, 0, s.tree.Size())
s.tree.Walk(nil, func(_ *net.IPNet, v interface{}) bool {
ps := v.([]*Prefix)
for _, p := range ps {
list = append(list, config.Prefix{IpPrefix: p.PrefixString(), MasklengthRange: fmt.Sprintf("%d..%d", p.MasklengthRangeMin, p.MasklengthRangeMax)})
}
return false
return true
})
return &config.PrefixSet{
PrefixSetName: s.name,
@@ -480,7 +475,7 @@ func NewPrefixSetFromApiStruct(name string, prefixes []*Prefix) (*PrefixSet, err
if name == "" {
return nil, fmt.Errorf("empty prefix set name")
}
tree := radix.New()
tree := critbitgo.NewNet()
var family bgp.RouteFamily
for i, x := range prefixes {
if i == 0 {
@@ -488,13 +483,12 @@ func NewPrefixSetFromApiStruct(name string, prefixes []*Prefix) (*PrefixSet, err
} else if family != x.AddressFamily {
return nil, fmt.Errorf("multiple families")
}
key := CidrToRadixkey(x.Prefix.String())
d, ok := tree.Get(key)
d, ok, _ := tree.Get(x.Prefix)
if ok {
ps := d.([]*Prefix)
tree.Insert(key, append(ps, x))
tree.Add(x.Prefix, append(ps, x))
} else {
tree.Insert(key, []*Prefix{x})
tree.Add(x.Prefix, []*Prefix{x})
}
}
return &PrefixSet{
@@ -512,7 +506,7 @@ func NewPrefixSet(c config.PrefixSet) (*PrefixSet, error) {
}
return nil, fmt.Errorf("empty prefix set name")
}
tree := radix.New()
tree := critbitgo.NewNet()
var family bgp.RouteFamily
for i, x := range c.PrefixList {
y, err := NewPrefix(x)
@@ -524,13 +518,12 @@ func NewPrefixSet(c config.PrefixSet) (*PrefixSet, error) {
} else if family != y.AddressFamily {
return nil, fmt.Errorf("multiple families")
}
key := CidrToRadixkey(y.Prefix.String())
d, ok := tree.Get(key)
d, ok, _ := tree.Get(y.Prefix)
if ok {
ps := d.([]*Prefix)
tree.Insert(key, append(ps, y))
tree.Add(y.Prefix, append(ps, y))
} else {
tree.Insert(key, []*Prefix{y})
tree.Add(y.Prefix, []*Prefix{y})
}
}
return &PrefixSet{
@@ -819,7 +812,7 @@ func (m *singleAsPathMatch) Match(aspath []uint32) bool {
}
var (
_regexpLeftMostRe = regexp.MustCompile(`$\^([0-9]+)_^`)
_regexpLeftMostRe = regexp.MustCompile(`^\^([0-9]+)_$`)
_regexpOriginRe = regexp.MustCompile(`^_([0-9]+)\$$`)
_regexpIncludeRe = regexp.MustCompile("^_([0-9]+)_$")
_regexpOnlyRe = regexp.MustCompile(`^\^([0-9]+)\$$`)
@@ -1446,33 +1439,15 @@ func (c *PrefixCondition) Option() MatchOption {
// subsequent comparison is skipped if that matches the conditions.
// If PrefixList's length is zero, return true.
func (c *PrefixCondition) Evaluate(path *Path, _ *PolicyOptions) bool {
var key string
var masklen uint8
keyf := func(ip net.IP, ones int) string {
var buffer bytes.Buffer
for i := 0; i < len(ip) && i < ones; i++ {
buffer.WriteString(fmt.Sprintf("%08b", ip[i]))
}
return buffer.String()[:ones]
}
family := path.GetRouteFamily()
switch family {
case bgp.RF_IPv4_UC:
masklen = path.GetNlri().(*bgp.IPAddrPrefix).Length
key = keyf(path.GetNlri().(*bgp.IPAddrPrefix).Prefix, int(masklen))
case bgp.RF_IPv6_UC:
masklen = path.GetNlri().(*bgp.IPv6AddrPrefix).Length
key = keyf(path.GetNlri().(*bgp.IPv6AddrPrefix).Prefix, int(masklen))
default:
return false
}
if family != c.set.family {
if path.GetRouteFamily() != c.set.family {
return false
}
r := nlriToIPNet(path.GetNlri())
ones, _ := r.Mask.Size()
masklen := uint8(ones)
result := false
_, ps, ok := c.set.tree.LongestPrefix(key)
if ok {
if _, ps, _ := c.set.tree.Match(r); ps != nil {
for _, p := range ps.([]*Prefix) {
if p.MasklengthRangeMin <= masklen && masklen <= p.MasklengthRangeMax {
result = true
@@ -1899,8 +1874,8 @@ func (c *RpkiValidationCondition) Type() ConditionType {
}
func (c *RpkiValidationCondition) Evaluate(path *Path, options *PolicyOptions) bool {
if options != nil && options.ValidationResult != nil {
return c.result == options.ValidationResult.Status
if options != nil && options.Validate != nil {
return c.result == options.Validate(path).Status
}
return false
}
@@ -2536,7 +2511,7 @@ func (a *AsPathPrependAction) Apply(path *Path, option *PolicyOptions) *Path {
asn = a.asn
}
confed := option != nil && option.Info.Confederation
confed := option != nil && option.Info != nil && option.Info.Confederation
path.PrependAsn(asn, a.repeat, confed)
return path
@@ -2580,7 +2555,7 @@ func NewAsPathPrependAction(action config.SetAsPathPrepend) (*AsPathPrependActio
default:
asn, err := strconv.ParseUint(action.As, 10, 32)
if err != nil {
return nil, fmt.Errorf("As number string invalid")
return nil, fmt.Errorf("AS number string invalid")
}
a.asn = uint32(asn)
}
@@ -2686,39 +2661,28 @@ func (s *Statement) ToConfig() *config.Statement {
Conditions: func() config.Conditions {
cond := config.Conditions{}
for _, c := range s.Conditions {
switch c.(type) {
switch v := c.(type) {
case *PrefixCondition:
v := c.(*PrefixCondition)
cond.MatchPrefixSet = config.MatchPrefixSet{PrefixSet: v.set.Name(), MatchSetOptions: v.option.ConvertToMatchSetOptionsRestrictedType()}
case *NeighborCondition:
v := c.(*NeighborCondition)
cond.MatchNeighborSet = config.MatchNeighborSet{NeighborSet: v.set.Name(), MatchSetOptions: v.option.ConvertToMatchSetOptionsRestrictedType()}
case *AsPathLengthCondition:
v := c.(*AsPathLengthCondition)
cond.BgpConditions.AsPathLength = config.AsPathLength{Operator: config.IntToAttributeComparisonMap[int(v.operator)], Value: v.length}
case *AsPathCondition:
v := c.(*AsPathCondition)
cond.BgpConditions.MatchAsPathSet = config.MatchAsPathSet{AsPathSet: v.set.Name(), MatchSetOptions: config.IntToMatchSetOptionsTypeMap[int(v.option)]}
case *CommunityCondition:
v := c.(*CommunityCondition)
cond.BgpConditions.MatchCommunitySet = config.MatchCommunitySet{CommunitySet: v.set.Name(), MatchSetOptions: config.IntToMatchSetOptionsTypeMap[int(v.option)]}
case *ExtCommunityCondition:
v := c.(*ExtCommunityCondition)
cond.BgpConditions.MatchExtCommunitySet = config.MatchExtCommunitySet{ExtCommunitySet: v.set.Name(), MatchSetOptions: config.IntToMatchSetOptionsTypeMap[int(v.option)]}
case *LargeCommunityCondition:
v := c.(*LargeCommunityCondition)
cond.BgpConditions.MatchLargeCommunitySet = config.MatchLargeCommunitySet{LargeCommunitySet: v.set.Name(), MatchSetOptions: config.IntToMatchSetOptionsTypeMap[int(v.option)]}
case *NextHopCondition:
v := c.(*NextHopCondition)
cond.BgpConditions.NextHopInList = v.set.List()
case *RpkiValidationCondition:
v := c.(*RpkiValidationCondition)
cond.BgpConditions.RpkiValidationResult = v.result
case *RouteTypeCondition:
v := c.(*RouteTypeCondition)
cond.BgpConditions.RouteType = v.typ
case *AfiSafiInCondition:
v := c.(*AfiSafiInCondition)
res := make([]config.AfiSafiType, 0, len(v.routeFamilies))
for _, rf := range v.routeFamilies {
res = append(res, config.AfiSafiType(rf.String()))
@@ -2741,21 +2705,21 @@ func (s *Statement) ToConfig() *config.Statement {
act.RouteDisposition = config.ROUTE_DISPOSITION_NONE
}
for _, a := range s.ModActions {
switch a.(type) {
switch v := a.(type) {
case *AsPathPrependAction:
act.BgpActions.SetAsPathPrepend = *a.(*AsPathPrependAction).ToConfig()
act.BgpActions.SetAsPathPrepend = *v.ToConfig()
case *CommunityAction:
act.BgpActions.SetCommunity = *a.(*CommunityAction).ToConfig()
act.BgpActions.SetCommunity = *v.ToConfig()
case *ExtCommunityAction:
act.BgpActions.SetExtCommunity = *a.(*ExtCommunityAction).ToConfig()
act.BgpActions.SetExtCommunity = *v.ToConfig()
case *LargeCommunityAction:
act.BgpActions.SetLargeCommunity = *a.(*LargeCommunityAction).ToConfig()
act.BgpActions.SetLargeCommunity = *v.ToConfig()
case *MedAction:
act.BgpActions.SetMed = a.(*MedAction).ToConfig()
act.BgpActions.SetMed = v.ToConfig()
case *LocalPrefAction:
act.BgpActions.SetLocalPref = a.(*LocalPrefAction).ToConfig()
act.BgpActions.SetLocalPref = v.ToConfig()
case *NexthopAction:
act.BgpActions.SetNextHop = a.(*NexthopAction).ToConfig()
act.BgpActions.SetNextHop = v.ToConfig()
}
}
return act
@@ -3114,9 +3078,6 @@ type RoutingPolicy struct {
}
func (r *RoutingPolicy) ApplyPolicy(id string, dir PolicyDirection, before *Path, options *PolicyOptions) *Path {
r.mu.RLock()
defer r.mu.RUnlock()
if before == nil {
return nil
}
@@ -3126,6 +3087,10 @@ func (r *RoutingPolicy) ApplyPolicy(id string, dir PolicyDirection, before *Path
}
result := ROUTE_TYPE_NONE
after := before
r.mu.RLock()
defer r.mu.RUnlock()
for _, p := range r.getPolicy(id, dir) {
result, after = p.Apply(after, options)
if result != ROUTE_TYPE_NONE {
@@ -3408,13 +3373,13 @@ func (r *RoutingPolicy) reload(c config.RoutingPolicy) error {
return err
}
if _, ok := pmap[y.Name]; ok {
return fmt.Errorf("duplicated policy name. policy name must be unique.")
return fmt.Errorf("duplicated policy name. policy name must be unique")
}
pmap[y.Name] = y
for _, s := range y.Statements {
_, ok := smap[s.Name]
if ok {
return fmt.Errorf("duplicated statement name. statement name must be unique.")
return fmt.Errorf("duplicated statement name. statement name must be unique")
}
smap[s.Name] = s
}
@@ -3445,18 +3410,24 @@ func (r *RoutingPolicy) reload(c config.RoutingPolicy) error {
}
func (r *RoutingPolicy) GetDefinedSet(typ DefinedType, name string) (*config.DefinedSets, error) {
r.mu.RLock()
dl, err := func() (DefinedSetList, error) {
r.mu.RLock()
defer r.mu.RUnlock()
set, ok := r.definedSetMap[typ]
if !ok {
return nil, fmt.Errorf("invalid defined-set type: %d", typ)
}
set, ok := r.definedSetMap[typ]
if !ok {
return nil, fmt.Errorf("invalid defined-set type: %d", typ)
}
var dl DefinedSetList
for _, s := range set {
dl = append(dl, s)
var dl DefinedSetList
for _, s := range set {
dl = append(dl, s)
}
return dl, nil
}()
if err != nil {
return nil, err
}
r.mu.RUnlock()
sort.Sort(dl)
@@ -3474,19 +3445,19 @@ func (r *RoutingPolicy) GetDefinedSet(typ DefinedType, name string) (*config.Def
if name != "" && s.Name() != name {
continue
}
switch s.(type) {
switch v := s.(type) {
case *PrefixSet:
sets.PrefixSets = append(sets.PrefixSets, *s.(*PrefixSet).ToConfig())
sets.PrefixSets = append(sets.PrefixSets, *v.ToConfig())
case *NeighborSet:
sets.NeighborSets = append(sets.NeighborSets, *s.(*NeighborSet).ToConfig())
sets.NeighborSets = append(sets.NeighborSets, *v.ToConfig())
case *CommunitySet:
sets.BgpDefinedSets.CommunitySets = append(sets.BgpDefinedSets.CommunitySets, *s.(*CommunitySet).ToConfig())
sets.BgpDefinedSets.CommunitySets = append(sets.BgpDefinedSets.CommunitySets, *v.ToConfig())
case *ExtCommunitySet:
sets.BgpDefinedSets.ExtCommunitySets = append(sets.BgpDefinedSets.ExtCommunitySets, *s.(*ExtCommunitySet).ToConfig())
sets.BgpDefinedSets.ExtCommunitySets = append(sets.BgpDefinedSets.ExtCommunitySets, *v.ToConfig())
case *LargeCommunitySet:
sets.BgpDefinedSets.LargeCommunitySets = append(sets.BgpDefinedSets.LargeCommunitySets, *s.(*LargeCommunitySet).ToConfig())
sets.BgpDefinedSets.LargeCommunitySets = append(sets.BgpDefinedSets.LargeCommunitySets, *v.ToConfig())
case *AsPathSet:
sets.BgpDefinedSets.AsPathSets = append(sets.BgpDefinedSets.AsPathSets, *s.(*AsPathSet).ToConfig())
sets.BgpDefinedSets.AsPathSets = append(sets.BgpDefinedSets.AsPathSets, *v.ToConfig())
}
}
return sets, nil
@@ -3591,16 +3562,19 @@ func (r *RoutingPolicy) DeleteStatement(st *Statement, all bool) (err error) {
}
func (r *RoutingPolicy) GetPolicy(name string) []*config.PolicyDefinition {
r.mu.RLock()
ps := func() Policies {
r.mu.RLock()
defer r.mu.RUnlock()
var ps Policies
for _, p := range r.policyMap {
if name != "" && name != p.Name {
continue
var ps Policies
for _, p := range r.policyMap {
if name != "" && name != p.Name {
continue
}
ps = append(ps, p)
}
ps = append(ps, p)
}
r.mu.RUnlock()
return ps
}()
sort.Sort(ps)
@@ -3827,32 +3801,59 @@ func (r *RoutingPolicy) SetPolicyAssignment(id string, dir PolicyDirection, poli
return err
}
func (r *RoutingPolicy) Reset(rp *config.RoutingPolicy, ap map[string]config.ApplyPolicy) error {
func (r *RoutingPolicy) Initialize() error {
r.mu.Lock()
defer r.mu.Unlock()
if rp != nil {
if err := r.reload(*rp); err != nil {
if err := r.reload(config.RoutingPolicy{}); err != nil {
log.WithFields(log.Fields{
"Topic": "Policy",
}).Errorf("failed to create routing policy: %s", err)
return err
}
return nil
}
func (r *RoutingPolicy) setPeerPolicy(id string, c config.ApplyPolicy) {
for _, dir := range []PolicyDirection{POLICY_DIRECTION_IMPORT, POLICY_DIRECTION_EXPORT} {
ps, def, err := r.getAssignmentFromConfig(dir, c)
if err != nil {
log.WithFields(log.Fields{
"Topic": "Policy",
}).Errorf("failed to create routing policy: %s", err)
return err
"Dir": dir,
}).Errorf("failed to get policy info: %s", err)
continue
}
r.setDefaultPolicy(id, dir, def)
r.setPolicy(id, dir, ps)
}
}
func (r *RoutingPolicy) SetPeerPolicy(peerId string, c config.ApplyPolicy) error {
r.mu.Lock()
defer r.mu.Unlock()
r.setPeerPolicy(peerId, c)
return nil
}
func (r *RoutingPolicy) Reset(rp *config.RoutingPolicy, ap map[string]config.ApplyPolicy) error {
if rp == nil {
return fmt.Errorf("routing Policy is nil in call to Reset")
}
r.mu.Lock()
defer r.mu.Unlock()
if err := r.reload(*rp); err != nil {
log.WithFields(log.Fields{
"Topic": "Policy",
}).Errorf("failed to create routing policy: %s", err)
return err
}
for id, c := range ap {
for _, dir := range []PolicyDirection{POLICY_DIRECTION_IMPORT, POLICY_DIRECTION_EXPORT} {
ps, def, err := r.getAssignmentFromConfig(dir, c)
if err != nil {
log.WithFields(log.Fields{
"Topic": "Policy",
"Dir": dir,
}).Errorf("failed to get policy info: %s", err)
continue
}
r.setDefaultPolicy(id, dir, def)
r.setPolicy(id, dir, ps)
}
r.setPeerPolicy(id, c)
}
return nil
}
@@ -3893,3 +3894,237 @@ type PolicyAssignment struct {
Policies []*Policy
Default RouteType
}
var _regexpMedActionType = regexp.MustCompile(`([+-]?)(\d+)`)
func toStatementApi(s *config.Statement) *api.Statement {
cs := &api.Conditions{}
o, _ := NewMatchOption(s.Conditions.MatchPrefixSet.MatchSetOptions)
if s.Conditions.MatchPrefixSet.PrefixSet != "" {
cs.PrefixSet = &api.MatchSet{
MatchType: api.MatchType(o),
Name: s.Conditions.MatchPrefixSet.PrefixSet,
}
}
if s.Conditions.MatchNeighborSet.NeighborSet != "" {
o, _ := NewMatchOption(s.Conditions.MatchNeighborSet.MatchSetOptions)
cs.NeighborSet = &api.MatchSet{
MatchType: api.MatchType(o),
Name: s.Conditions.MatchNeighborSet.NeighborSet,
}
}
if s.Conditions.BgpConditions.AsPathLength.Operator != "" {
cs.AsPathLength = &api.AsPathLength{
Length: s.Conditions.BgpConditions.AsPathLength.Value,
LengthType: api.AsPathLengthType(s.Conditions.BgpConditions.AsPathLength.Operator.ToInt()),
}
}
if s.Conditions.BgpConditions.MatchAsPathSet.AsPathSet != "" {
cs.AsPathSet = &api.MatchSet{
MatchType: api.MatchType(s.Conditions.BgpConditions.MatchAsPathSet.MatchSetOptions.ToInt()),
Name: s.Conditions.BgpConditions.MatchAsPathSet.AsPathSet,
}
}
if s.Conditions.BgpConditions.MatchCommunitySet.CommunitySet != "" {
cs.CommunitySet = &api.MatchSet{
MatchType: api.MatchType(s.Conditions.BgpConditions.MatchCommunitySet.MatchSetOptions.ToInt()),
Name: s.Conditions.BgpConditions.MatchCommunitySet.CommunitySet,
}
}
if s.Conditions.BgpConditions.MatchExtCommunitySet.ExtCommunitySet != "" {
cs.ExtCommunitySet = &api.MatchSet{
MatchType: api.MatchType(s.Conditions.BgpConditions.MatchExtCommunitySet.MatchSetOptions.ToInt()),
Name: s.Conditions.BgpConditions.MatchExtCommunitySet.ExtCommunitySet,
}
}
if s.Conditions.BgpConditions.MatchLargeCommunitySet.LargeCommunitySet != "" {
cs.LargeCommunitySet = &api.MatchSet{
MatchType: api.MatchType(s.Conditions.BgpConditions.MatchLargeCommunitySet.MatchSetOptions.ToInt()),
Name: s.Conditions.BgpConditions.MatchLargeCommunitySet.LargeCommunitySet,
}
}
if s.Conditions.BgpConditions.RouteType != "" {
cs.RouteType = api.Conditions_RouteType(s.Conditions.BgpConditions.RouteType.ToInt())
}
if len(s.Conditions.BgpConditions.NextHopInList) > 0 {
cs.NextHopInList = s.Conditions.BgpConditions.NextHopInList
}
if s.Conditions.BgpConditions.AfiSafiInList != nil {
afiSafiIn := make([]*api.Family, 0)
for _, afiSafiType := range s.Conditions.BgpConditions.AfiSafiInList {
if mapped, ok := bgp.AddressFamilyValueMap[string(afiSafiType)]; ok {
afi, safi := bgp.RouteFamilyToAfiSafi(mapped)
afiSafiIn = append(afiSafiIn, &api.Family{Afi: api.Family_Afi(afi), Safi: api.Family_Safi(safi)})
}
}
cs.AfiSafiIn = afiSafiIn
}
cs.RpkiResult = int32(s.Conditions.BgpConditions.RpkiValidationResult.ToInt())
as := &api.Actions{
RouteAction: func() api.RouteAction {
switch s.Actions.RouteDisposition {
case config.ROUTE_DISPOSITION_ACCEPT_ROUTE:
return api.RouteAction_ACCEPT
case config.ROUTE_DISPOSITION_REJECT_ROUTE:
return api.RouteAction_REJECT
}
return api.RouteAction_NONE
}(),
Community: func() *api.CommunityAction {
if len(s.Actions.BgpActions.SetCommunity.SetCommunityMethod.CommunitiesList) == 0 {
return nil
}
return &api.CommunityAction{
ActionType: api.CommunityActionType(config.BgpSetCommunityOptionTypeToIntMap[config.BgpSetCommunityOptionType(s.Actions.BgpActions.SetCommunity.Options)]),
Communities: s.Actions.BgpActions.SetCommunity.SetCommunityMethod.CommunitiesList}
}(),
Med: func() *api.MedAction {
medStr := strings.TrimSpace(string(s.Actions.BgpActions.SetMed))
if len(medStr) == 0 {
return nil
}
matches := _regexpMedActionType.FindStringSubmatch(medStr)
if len(matches) == 0 {
return nil
}
action := api.MedActionType_MED_REPLACE
switch matches[1] {
case "+", "-":
action = api.MedActionType_MED_MOD
}
value, err := strconv.ParseInt(matches[1]+matches[2], 10, 64)
if err != nil {
return nil
}
return &api.MedAction{
Value: value,
ActionType: action,
}
}(),
AsPrepend: func() *api.AsPrependAction {
if len(s.Actions.BgpActions.SetAsPathPrepend.As) == 0 {
return nil
}
var asn uint64
useleft := false
if s.Actions.BgpActions.SetAsPathPrepend.As != "last-as" {
asn, _ = strconv.ParseUint(s.Actions.BgpActions.SetAsPathPrepend.As, 10, 32)
} else {
useleft = true
}
return &api.AsPrependAction{
Asn: uint32(asn),
Repeat: uint32(s.Actions.BgpActions.SetAsPathPrepend.RepeatN),
UseLeftMost: useleft,
}
}(),
ExtCommunity: func() *api.CommunityAction {
if len(s.Actions.BgpActions.SetExtCommunity.SetExtCommunityMethod.CommunitiesList) == 0 {
return nil
}
return &api.CommunityAction{
ActionType: api.CommunityActionType(config.BgpSetCommunityOptionTypeToIntMap[config.BgpSetCommunityOptionType(s.Actions.BgpActions.SetExtCommunity.Options)]),
Communities: s.Actions.BgpActions.SetExtCommunity.SetExtCommunityMethod.CommunitiesList,
}
}(),
LargeCommunity: func() *api.CommunityAction {
if len(s.Actions.BgpActions.SetLargeCommunity.SetLargeCommunityMethod.CommunitiesList) == 0 {
return nil
}
return &api.CommunityAction{
ActionType: api.CommunityActionType(config.BgpSetCommunityOptionTypeToIntMap[config.BgpSetCommunityOptionType(s.Actions.BgpActions.SetLargeCommunity.Options)]),
Communities: s.Actions.BgpActions.SetLargeCommunity.SetLargeCommunityMethod.CommunitiesList,
}
}(),
Nexthop: func() *api.NexthopAction {
if len(string(s.Actions.BgpActions.SetNextHop)) == 0 {
return nil
}
if string(s.Actions.BgpActions.SetNextHop) == "self" {
return &api.NexthopAction{
Self: true,
}
}
return &api.NexthopAction{
Address: string(s.Actions.BgpActions.SetNextHop),
}
}(),
LocalPref: func() *api.LocalPrefAction {
if s.Actions.BgpActions.SetLocalPref == 0 {
return nil
}
return &api.LocalPrefAction{Value: s.Actions.BgpActions.SetLocalPref}
}(),
}
return &api.Statement{
Name: s.Name,
Conditions: cs,
Actions: as,
}
}
func NewAPIPolicyFromTableStruct(p *Policy) *api.Policy {
return ToPolicyApi(p.ToConfig())
}
func ToPolicyApi(p *config.PolicyDefinition) *api.Policy {
return &api.Policy{
Name: p.Name,
Statements: func() []*api.Statement {
l := make([]*api.Statement, 0)
for _, s := range p.Statements {
l = append(l, toStatementApi(&s))
}
return l
}(),
}
}
func NewAPIPolicyAssignmentFromTableStruct(t *PolicyAssignment) *api.PolicyAssignment {
return &api.PolicyAssignment{
Direction: func() api.PolicyDirection {
switch t.Type {
case POLICY_DIRECTION_IMPORT:
return api.PolicyDirection_IMPORT
case POLICY_DIRECTION_EXPORT:
return api.PolicyDirection_EXPORT
}
log.Errorf("invalid policy-type: %s", t.Type)
return api.PolicyDirection_UNKNOWN
}(),
DefaultAction: func() api.RouteAction {
switch t.Default {
case ROUTE_TYPE_ACCEPT:
return api.RouteAction_ACCEPT
case ROUTE_TYPE_REJECT:
return api.RouteAction_REJECT
}
return api.RouteAction_NONE
}(),
Name: t.Name,
Policies: func() []*api.Policy {
l := make([]*api.Policy, 0)
for _, p := range t.Policies {
l = append(l, NewAPIPolicyFromTableStruct(p))
}
return l
}(),
}
}
func NewAPIRoutingPolicyFromConfigStruct(c *config.RoutingPolicy) (*api.RoutingPolicy, error) {
definedSets, err := config.NewAPIDefinedSetsFromConfigStruct(&c.DefinedSets)
if err != nil {
return nil, err
}
policies := make([]*api.Policy, 0, len(c.PolicyDefinitions))
for _, policy := range c.PolicyDefinitions {
policies = append(policies, ToPolicyApi(&policy))
}
return &api.RoutingPolicy{
DefinedSets: definedSets,
Policies: policies,
}, nil
}

View File

@@ -1,4 +1,4 @@
// Copyright (C) 2016 Nippon Telegraph and Telephone Corporation.
// Copyright (C) 2016-2019 Nippon Telegraph and Telephone Corporation.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
@@ -16,35 +16,35 @@
package table
import (
"fmt"
"net"
"sort"
"github.com/k-sone/critbitgo"
"github.com/osrg/gobgp/internal/pkg/config"
"github.com/osrg/gobgp/pkg/packet/bgp"
log "github.com/sirupsen/logrus"
)
type IPPrefix struct {
Prefix net.IP
Length uint8
}
func (p *IPPrefix) String() string {
return fmt.Sprintf("%s/%d", p.Prefix, p.Length)
}
type ROA struct {
Family int
Prefix *IPPrefix
MaxLen uint8
AS uint32
Src string
Family int
Network *net.IPNet
MaxLen uint8
AS uint32
Src string
}
func NewROA(family int, prefixByte []byte, prefixLen uint8, maxLen uint8, as uint32, src string) *ROA {
p := make([]byte, len(prefixByte))
bits := net.IPv4len * 8
if family == bgp.AFI_IP6 {
bits = net.IPv6len * 8
}
copy(p, prefixByte)
return &ROA{
Family: family,
Prefix: &IPPrefix{
Prefix: p,
Length: prefixLen,
Network: &net.IPNet{
IP: p,
Mask: net.CIDRMask(int(prefixLen), bits),
},
MaxLen: maxLen,
AS: as,
@@ -58,3 +58,240 @@ func (r *ROA) Equal(roa *ROA) bool {
}
return false
}
type roaBucket struct {
network *net.IPNet
entries []*ROA
}
func (r *roaBucket) GetEntries() []*ROA {
return r.entries
}
type ROATable struct {
trees map[bgp.RouteFamily]*critbitgo.Net
}
func NewROATable() *ROATable {
m := make(map[bgp.RouteFamily]*critbitgo.Net)
m[bgp.RF_IPv4_UC] = critbitgo.NewNet()
m[bgp.RF_IPv6_UC] = critbitgo.NewNet()
return &ROATable{
trees: m,
}
}
func (rt *ROATable) roa2tree(roa *ROA) *critbitgo.Net {
tree := rt.trees[bgp.RF_IPv4_UC]
if roa.Family == bgp.AFI_IP6 {
tree = rt.trees[bgp.RF_IPv6_UC]
}
return tree
}
func (rt *ROATable) getBucket(roa *ROA) *roaBucket {
tree := rt.roa2tree(roa)
b, ok, _ := tree.Get(roa.Network)
if !ok {
b := &roaBucket{
network: roa.Network,
entries: make([]*ROA, 0),
}
tree.Add(roa.Network, b)
return b
}
return b.(*roaBucket)
}
func (rt *ROATable) Add(roa *ROA) {
b := rt.getBucket(roa)
for _, r := range b.entries {
if r.Equal(roa) {
// we already have the same one
return
}
}
b.entries = append(b.entries, roa)
sort.Slice(b.entries, func(i, j int) bool {
r1 := b.entries[i]
r2 := b.entries[j]
if r1.MaxLen < r2.MaxLen {
return true
} else if r1.MaxLen > r2.MaxLen {
return false
}
if r1.AS < r2.AS {
return true
}
return false
})
}
func (rt *ROATable) Delete(roa *ROA) {
tree := rt.roa2tree(roa)
if b, ok, _ := tree.Get(roa.Network); ok {
bucket := b.(*roaBucket)
for i, r := range bucket.entries {
if r.Equal(roa) {
bucket.entries = append(bucket.entries[:i], bucket.entries[i+1:]...)
return
}
}
}
log.WithFields(log.Fields{
"Topic": "rpki",
"Network": roa.Network.String(),
"AS": roa.AS,
"Max Length": roa.MaxLen,
}).Info("Can't withdraw a ROA")
}
func (rt *ROATable) DeleteAll(network string) {
for _, tree := range rt.trees {
deleteNetworks := make([]*net.IPNet, 0, tree.Size())
tree.Walk(nil, func(n *net.IPNet, v interface{}) bool {
b, _ := v.(*roaBucket)
newEntries := make([]*ROA, 0, len(b.entries))
for _, r := range b.entries {
if r.Src != network {
newEntries = append(newEntries, r)
}
}
if len(newEntries) > 0 {
b.entries = newEntries
} else {
deleteNetworks = append(deleteNetworks, n)
}
return true
})
for _, key := range deleteNetworks {
tree.Delete(key)
}
}
}
func (rt *ROATable) Validate(path *Path) *Validation {
if path.IsWithdraw || path.IsEOR() {
// RPKI isn't enabled or invalid path
return nil
}
tree, ok := rt.trees[path.GetRouteFamily()]
if !ok {
return nil
}
ownAs := path.OriginInfo().source.LocalAS
asPath := path.GetAsPath()
var as uint32
validation := &Validation{
Status: config.RPKI_VALIDATION_RESULT_TYPE_NOT_FOUND,
Reason: RPKI_VALIDATION_REASON_TYPE_NONE,
Matched: make([]*ROA, 0),
UnmatchedLength: make([]*ROA, 0),
UnmatchedAs: make([]*ROA, 0),
}
if asPath == nil || len(asPath.Value) == 0 {
as = ownAs
} else {
param := asPath.Value[len(asPath.Value)-1]
switch param.GetType() {
case bgp.BGP_ASPATH_ATTR_TYPE_SEQ:
asList := param.GetAS()
if len(asList) == 0 {
as = ownAs
} else {
as = asList[len(asList)-1]
}
case bgp.BGP_ASPATH_ATTR_TYPE_CONFED_SET, bgp.BGP_ASPATH_ATTR_TYPE_CONFED_SEQ:
as = ownAs
default:
return validation
}
}
r := nlriToIPNet(path.GetNlri())
prefixLen, _ := r.Mask.Size()
var bucket *roaBucket
tree.WalkMatch(r, func(r *net.IPNet, v interface{}) bool {
bucket, _ = v.(*roaBucket)
for _, r := range bucket.entries {
if prefixLen <= int(r.MaxLen) {
if r.AS != 0 && r.AS == as {
validation.Matched = append(validation.Matched, r)
} else {
validation.UnmatchedAs = append(validation.UnmatchedAs, r)
}
} else {
validation.UnmatchedLength = append(validation.UnmatchedLength, r)
}
}
return true
})
if len(validation.Matched) != 0 {
validation.Status = config.RPKI_VALIDATION_RESULT_TYPE_VALID
validation.Reason = RPKI_VALIDATION_REASON_TYPE_NONE
} else if len(validation.UnmatchedAs) != 0 {
validation.Status = config.RPKI_VALIDATION_RESULT_TYPE_INVALID
validation.Reason = RPKI_VALIDATION_REASON_TYPE_AS
} else if len(validation.UnmatchedLength) != 0 {
validation.Status = config.RPKI_VALIDATION_RESULT_TYPE_INVALID
validation.Reason = RPKI_VALIDATION_REASON_TYPE_LENGTH
} else {
validation.Status = config.RPKI_VALIDATION_RESULT_TYPE_NOT_FOUND
validation.Reason = RPKI_VALIDATION_REASON_TYPE_NONE
}
return validation
}
func (rt *ROATable) Info(family bgp.RouteFamily) (map[string]uint32, map[string]uint32) {
records := make(map[string]uint32)
prefixes := make(map[string]uint32)
if tree, ok := rt.trees[family]; ok {
tree.Walk(nil, func(_ *net.IPNet, v interface{}) bool {
b, _ := v.(*roaBucket)
tmpRecords := make(map[string]uint32)
for _, roa := range b.entries {
tmpRecords[roa.Src]++
}
for src, r := range tmpRecords {
if r > 0 {
records[src] += r
prefixes[src]++
}
}
return true
})
}
return records, prefixes
}
func (rt *ROATable) List(family bgp.RouteFamily) ([]*ROA, error) {
var rfList []bgp.RouteFamily
switch family {
case bgp.RF_IPv4_UC:
rfList = []bgp.RouteFamily{bgp.RF_IPv4_UC}
case bgp.RF_IPv6_UC:
rfList = []bgp.RouteFamily{bgp.RF_IPv6_UC}
default:
rfList = []bgp.RouteFamily{bgp.RF_IPv4_UC, bgp.RF_IPv6_UC}
}
l := make([]*ROA, 0)
for _, rf := range rfList {
if tree, ok := rt.trees[rf]; ok {
tree.Walk(nil, func(_ *net.IPNet, v interface{}) bool {
b, _ := v.(*roaBucket)
l = append(l, b.entries...)
return true
})
}
}
return l, nil
}

View File

@@ -17,11 +17,12 @@ package table
import (
"fmt"
"math/bits"
"net"
"strings"
"unsafe"
"github.com/armon/go-radix"
"github.com/k-sone/critbitgo"
"github.com/osrg/gobgp/pkg/packet/bgp"
log "github.com/sirupsen/logrus"
)
@@ -75,13 +76,13 @@ func (t *Table) deletePathsByVrf(vrf *Vrf) []*Path {
for _, p := range dest.knownPathList {
var rd bgp.RouteDistinguisherInterface
nlri := p.GetNlri()
switch nlri.(type) {
switch v := nlri.(type) {
case *bgp.LabeledVPNIPAddrPrefix:
rd = nlri.(*bgp.LabeledVPNIPAddrPrefix).RD
rd = v.RD
case *bgp.LabeledVPNIPv6AddrPrefix:
rd = nlri.(*bgp.LabeledVPNIPv6AddrPrefix).RD
rd = v.RD
case *bgp.EVPNNLRI:
rd = nlri.(*bgp.EVPNNLRI).RD()
rd = v.RD()
default:
return pathList
}
@@ -117,15 +118,14 @@ func (t *Table) deleteRTCPathsByVrf(vrf *Vrf, vrfs map[string]*Vrf) []*Path {
return pathList
}
func (t *Table) deleteDestByNlri(nlri bgp.AddrPrefixInterface) *Destination {
if dst := t.GetDestination(nlri); dst != nil {
t.deleteDest(dst)
return dst
}
return nil
}
func (t *Table) deleteDest(dest *Destination) {
count := 0
for _, v := range dest.localIdMap.bitmap {
count += bits.OnesCount64(v)
}
if len(dest.localIdMap.bitmap) != 0 && count != 1 {
return
}
destinations := t.GetDestinations()
delete(destinations, t.tableKey(dest.GetNlri()))
if len(destinations) == 0 {
@@ -175,7 +175,7 @@ func (t *Table) validatePath(path *Path) {
}
}
func (t *Table) getOrCreateDest(nlri bgp.AddrPrefixInterface) *Destination {
func (t *Table) getOrCreateDest(nlri bgp.AddrPrefixInterface, size int) *Destination {
dest := t.GetDestination(nlri)
// If destination for given prefix does not exist we create it.
if dest == nil {
@@ -183,7 +183,7 @@ func (t *Table) getOrCreateDest(nlri bgp.AddrPrefixInterface) *Destination {
"Topic": "Table",
"Nlri": nlri,
}).Debugf("create Destination")
dest = NewDestination(nlri, 64)
dest = NewDestination(nlri, size)
t.setDestination(dest)
}
return dest
@@ -212,14 +212,13 @@ func (t *Table) GetLongerPrefixDestinations(key string) ([]*Destination, error)
if err != nil {
return nil, err
}
k := CidrToRadixkey(prefix.String())
r := radix.New()
r := critbitgo.NewNet()
for _, dst := range t.GetDestinations() {
r.Insert(AddrToRadixkey(dst.nlri), dst)
r.Add(nlriToIPNet(dst.nlri), dst)
}
r.WalkPrefix(k, func(s string, v interface{}) bool {
r.WalkPrefix(prefix, func(_ *net.IPNet, v interface{}) bool {
results = append(results, v.(*Destination))
return false
return true
})
default:
for _, dst := range t.GetDestinations() {
@@ -435,13 +434,45 @@ type TableInfo struct {
NumAccepted int
}
func (t *Table) Info(id string, as uint32) *TableInfo {
type TableInfoOptions struct {
ID string
AS uint32
VRF *Vrf
}
func (t *Table) Info(option ...TableInfoOptions) *TableInfo {
var numD, numP int
id := GLOBAL_RIB_NAME
var vrf *Vrf
as := uint32(0)
for _, o := range option {
if o.ID != "" {
id = o.ID
}
if o.VRF != nil {
vrf = o.VRF
}
as = o.AS
}
for _, d := range t.destinations {
ps := d.GetKnownPathList(id, as)
if len(ps) > 0 {
numD += 1
numP += len(ps)
paths := d.GetKnownPathList(id, as)
n := len(paths)
if vrf != nil {
ps := make([]*Path, 0, len(paths))
for _, p := range paths {
if CanImportToVrf(vrf, p) {
ps = append(ps, p.ToLocal())
}
}
n = len(ps)
}
if n != 0 {
numD++
numP += n
}
}
return &TableInfo{

View File

@@ -166,11 +166,12 @@ func (manager *TableManager) DeleteVrf(name string) ([]*Path, error) {
msgs = append(msgs, t.deletePathsByVrf(vrf)...)
}
log.WithFields(log.Fields{
"Topic": "Vrf",
"Key": vrf.Name,
"Rd": vrf.Rd,
"ImportRt": vrf.ImportRt,
"ExportRt": vrf.ExportRt,
"Topic": "Vrf",
"Key": vrf.Name,
"Rd": vrf.Rd,
"ImportRt": vrf.ImportRt,
"ExportRt": vrf.ExportRt,
"MplsLabel": vrf.MplsLabel,
}).Debugf("delete vrf")
delete(manager.Vrfs, name)
rtcTable := manager.Tables[bgp.RF_RTC_UC]
@@ -181,7 +182,7 @@ func (manager *TableManager) DeleteVrf(name string) ([]*Path, error) {
func (tm *TableManager) update(newPath *Path) *Update {
t := tm.Tables[newPath.GetRouteFamily()]
t.validatePath(newPath)
dst := t.getOrCreateDest(newPath.GetNlri())
dst := t.getOrCreateDest(newPath.GetNlri(), 64)
u := dst.Calculate(newPath)
if len(dst.knownPathList) == 0 {
t.deleteDest(dst)
@@ -189,21 +190,6 @@ func (tm *TableManager) update(newPath *Path) *Update {
return u
}
func (manager *TableManager) GetPathListByPeer(info *PeerInfo, rf bgp.RouteFamily) []*Path {
if t, ok := manager.Tables[rf]; ok {
pathList := make([]*Path, 0, len(t.destinations))
for _, dst := range t.destinations {
for _, p := range dst.knownPathList {
if p.GetSource().Equal(info) {
pathList = append(pathList, p)
}
}
}
return pathList
}
return nil
}
func (manager *TableManager) Update(newPath *Path) []*Update {
if newPath == nil || newPath.IsEOR() {
return nil
@@ -232,6 +218,12 @@ func (manager *TableManager) Update(newPath *Path) []*Update {
// different Ethernet segment identifier and a higher sequence number
// than that which it had previously advertised withdraws its MAC/IP
// Advertisement route.
// ......
// If the PE is the originator of the MAC route and it receives the same
// MAC address with the same sequence number that it generated, it will
// compare its own IP address with the IP address of the remote PE and
// will select the lowest IP. If its own route is not the best one, it
// will withdraw the route.
func (manager *TableManager) handleMacMobility(path *Path) []*Path {
pathList := make([]*Path, 0)
nlri := path.GetNlri().(*bgp.EVPNNLRI)
@@ -242,7 +234,7 @@ func (manager *TableManager) handleMacMobility(path *Path) []*Path {
if !path2.IsLocal() || path2.GetNlri().(*bgp.EVPNNLRI).RouteType != bgp.EVPN_ROUTE_TYPE_MAC_IP_ADVERTISEMENT {
continue
}
f := func(p *Path) (bgp.EthernetSegmentIdentifier, net.HardwareAddr, int) {
f := func(p *Path) (bgp.EthernetSegmentIdentifier, uint32, net.HardwareAddr, int, net.IP) {
nlri := p.GetNlri().(*bgp.EVPNNLRI)
d := nlri.RouteTypeData.(*bgp.EVPNMacIPAdvertisementRoute)
ecs := p.GetExtCommunities()
@@ -253,12 +245,14 @@ func (manager *TableManager) handleMacMobility(path *Path) []*Path {
break
}
}
return d.ESI, d.MacAddress, seq
return d.ESI, d.ETag, d.MacAddress, seq, p.info.source.Address
}
e1, m1, s1 := f(path)
e2, m2, s2 := f(path2)
if bytes.Equal(m1, m2) && !bytes.Equal(e1.Value, e2.Value) && s1 > s2 {
pathList = append(pathList, path2.Clone(true))
e1, et1, m1, s1, i1 := f(path)
e2, et2, m2, s2, i2 := f(path2)
if et1 == et2 && bytes.Equal(m1, m2) && !bytes.Equal(e1.Value, e2.Value) {
if s1 > s2 || s1 == s2 && bytes.Compare(i1, i2) < 0 {
pathList = append(pathList, path2.Clone(true))
}
}
}
return pathList
@@ -360,11 +354,3 @@ func (manager *TableManager) GetDestination(path *Path) *Destination {
}
return t.GetDestination(path.GetNlri())
}
func (manager *TableManager) TableInfo(id string, as uint32, family bgp.RouteFamily) (*TableInfo, error) {
t, ok := manager.Tables[family]
if !ok {
return nil, fmt.Errorf("address family %s is not configured", family)
}
return t.Info(id, as), nil
}

View File

@@ -20,11 +20,12 @@ import (
)
type Vrf struct {
Name string
Id uint32
Rd bgp.RouteDistinguisherInterface
ImportRt []bgp.ExtendedCommunityInterface
ExportRt []bgp.ExtendedCommunityInterface
Name string
Id uint32
Rd bgp.RouteDistinguisherInterface
ImportRt []bgp.ExtendedCommunityInterface
ExportRt []bgp.ExtendedCommunityInterface
MplsLabel uint32
}
func (v *Vrf) Clone() *Vrf {
@@ -33,11 +34,12 @@ func (v *Vrf) Clone() *Vrf {
return append(l, rt...)
}
return &Vrf{
Name: v.Name,
Id: v.Id,
Rd: v.Rd,
ImportRt: f(v.ImportRt),
ExportRt: f(v.ExportRt),
Name: v.Name,
Id: v.Id,
Rd: v.Rd,
ImportRt: f(v.ImportRt),
ExportRt: f(v.ExportRt),
MplsLabel: v.MplsLabel,
}
}

View File

@@ -1,17 +1,27 @@
// Code generated by "stringer -type=AFI"; DO NOT EDIT.
// Code generated by "stringer -type=afi"; DO NOT EDIT.
package zebra
import "strconv"
const _AFI_name = "AFI_IPAFI_IP6AFI_ETHERAFI_MAX"
var _AFI_index = [...]uint8{0, 6, 13, 22, 29}
func (i AFI) String() string {
i -= 1
if i >= AFI(len(_AFI_index)-1) {
return "AFI(" + strconv.FormatInt(int64(i+1), 10) + ")"
}
return _AFI_name[_AFI_index[i]:_AFI_index[i+1]]
func _() {
// An "invalid array index" compiler error signifies that the constant values have changed.
// Re-run the stringer command to generate them again.
var x [1]struct{}
_ = x[afiIP-1]
_ = x[afiIP6-2]
_ = x[afiEther-3]
_ = x[afiMax-4]
}
const _afi_name = "afiIPafiIP6afiEtherafiMax"
var _afi_index = [...]uint8{0, 5, 11, 19, 25}
func (i afi) String() string {
i -= 1
if i >= afi(len(_afi_index)-1) {
return "afi(" + strconv.FormatInt(int64(i+1), 10) + ")"
}
return _afi_name[_afi_index[i]:_afi_index[i+1]]
}

View File

@@ -1,16 +0,0 @@
// Code generated by "stringer -type=API_TYPE"; DO NOT EDIT.
package zebra
import "strconv"
const _API_TYPE_name = "FRR_ZAPI5_INTERFACE_ADDFRR_ZAPI5_INTERFACE_DELETEFRR_ZAPI5_INTERFACE_ADDRESS_ADDFRR_ZAPI5_INTERFACE_ADDRESS_DELETEFRR_ZAPI5_INTERFACE_UPFRR_ZAPI5_INTERFACE_DOWNFRR_ZAPI5_INTERFACE_SET_MASTERFRR_ZAPI5_ROUTE_ADDFRR_ZAPI5_ROUTE_DELETEFRR_ZAPI5_ROUTE_NOTIFY_OWNERFRR_ZAPI5_IPV4_ROUTE_ADDFRR_ZAPI5_IPV4_ROUTE_DELETEFRR_ZAPI5_IPV6_ROUTE_ADDFRR_ZAPI5_IPV6_ROUTE_DELETEFRR_ZAPI5_REDISTRIBUTE_ADDFRR_ZAPI5_REDISTRIBUTE_DELETEFRR_ZAPI5_REDISTRIBUTE_DEFAULT_ADDFRR_ZAPI5_REDISTRIBUTE_DEFAULT_DELETEFRR_ZAPI5_ROUTER_ID_ADDFRR_ZAPI5_ROUTER_ID_DELETEFRR_ZAPI5_ROUTER_ID_UPDATEFRR_ZAPI5_HELLOFRR_ZAPI5_CAPABILITIESFRR_ZAPI5_NEXTHOP_REGISTERFRR_ZAPI5_NEXTHOP_UNREGISTERFRR_ZAPI5_NEXTHOP_UPDATEFRR_ZAPI5_INTERFACE_NBR_ADDRESS_ADDFRR_ZAPI5_INTERFACE_NBR_ADDRESS_DELETEFRR_ZAPI5_INTERFACE_BFD_DEST_UPDATEFRR_ZAPI5_IMPORT_ROUTE_REGISTERFRR_ZAPI5_IMPORT_ROUTE_UNREGISTERFRR_ZAPI5_IMPORT_CHECK_UPDATEFRR_ZAPI5_IPV4_ROUTE_IPV6_NEXTHOP_ADDFRR_ZAPI5_BFD_DEST_REGISTERFRR_ZAPI5_BFD_DEST_DEREGISTERFRR_ZAPI5_BFD_DEST_UPDATEFRR_ZAPI5_BFD_DEST_REPLAYFRR_ZAPI5_REDISTRIBUTE_ROUTE_ADDFRR_ZAPI5_REDISTRIBUTE_ROUTE_DELFRR_ZAPI5_VRF_UNREGISTERFRR_ZAPI5_VRF_ADDFRR_ZAPI5_VRF_DELETEFRR_ZAPI5_VRF_LABELFRR_ZAPI5_INTERFACE_VRF_UPDATEFRR_ZAPI5_BFD_CLIENT_REGISTERFRR_ZAPI5_INTERFACE_ENABLE_RADVFRR_ZAPI5_INTERFACE_DISABLE_RADVFRR_ZAPI5_IPV4_NEXTHOP_LOOKUP_MRIBFRR_ZAPI5_INTERFACE_LINK_PARAMSFRR_ZAPI5_MPLS_LABELS_ADDFRR_ZAPI5_MPLS_LABELS_DELETEFRR_ZAPI5_IPMR_ROUTE_STATSFRR_ZAPI5_LABEL_MANAGER_CONNECTFRR_ZAPI5_GET_LABEL_CHUNKFRR_ZAPI5_RELEASE_LABEL_CHUNKFRR_ZAPI5_FEC_REGISTERFRR_ZAPI5_FEC_UNREGISTERFRR_ZAPI5_FEC_UPDATEFRR_ZAPI5_ADVERTISE_DEFAULT_GWFRR_ZAPI5_ADVERTISE_SUBNETFRR_ZAPI5_ADVERTISE_ALL_VNIFRR_ZAPI5_VNI_ADDFRR_ZAPI5_VNI_DELFRR_ZAPI5_L3VNI_ADDFRR_ZAPI5_L3VNI_DELFRR_ZAPI5_REMOTE_VTEP_ADDFRR_ZAPI5_REMOTE_VTEP_DELFRR_ZAPI5_MACIP_ADDFRR_ZAPI5_MACIP_DELFRR_ZAPI5_IP_PREFIX_ROUTE_ADDFRR_ZAPI5_IP_PREFIX_ROUTE_DELFRR_ZAPI5_REMOTE_MACIP_ADDFRR_ZAPI5_REMOTE_MACIP_DELFRR_ZAPI5_PW_ADDFRR_ZAPI5_PW_DELETEFRR_ZAPI5_PW_SETFRR_ZAPI5_PW_UNSETFRR_ZAPI5_PW_STATUS_UPDATEFRR_ZAPI5_RULE_ADDFRR_ZAPI5_RULE_DELETEFRR_ZAPI5_RULE_NOTIFY_OWNERFRR_ZAPI5_TABLE_MANAGER_CONNECTFRR_ZAPI5_GET_TABLE_CHUNKFRR_ZAPI5_RELEASE_TABLE_CHUNKFRR_ZAPI5_IPSET_CREATEFRR_ZAPI5_IPSET_DESTROYFRR_ZAPI5_IPSET_ENTRY_ADDFRR_ZAPI5_IPSET_ENTRY_DELETEFRR_ZAPI5_IPSET_NOTIFY_OWNERFRR_ZAPI5_IPSET_ENTRY_NOTIFY_OWNERFRR_ZAPI5_IPTABLE_ADDFRR_ZAPI5_IPTABLE_DELETEFRR_ZAPI5_IPTABLE_NOTIFY_OWNER"
var _API_TYPE_index = [...]uint16{0, 23, 49, 80, 114, 136, 160, 190, 209, 231, 259, 283, 310, 334, 361, 387, 416, 450, 487, 510, 536, 562, 577, 599, 625, 653, 677, 712, 750, 785, 816, 849, 878, 915, 942, 971, 996, 1021, 1053, 1085, 1109, 1126, 1146, 1165, 1195, 1224, 1255, 1287, 1321, 1352, 1377, 1405, 1431, 1462, 1487, 1516, 1538, 1562, 1582, 1612, 1638, 1665, 1682, 1699, 1718, 1737, 1762, 1787, 1806, 1825, 1854, 1883, 1909, 1935, 1951, 1970, 1986, 2004, 2030, 2048, 2069, 2096, 2127, 2152, 2181, 2203, 2226, 2251, 2279, 2307, 2341, 2362, 2386, 2416}
func (i API_TYPE) String() string {
if i >= API_TYPE(len(_API_TYPE_index)-1) {
return "API_TYPE(" + strconv.FormatInt(int64(i), 10) + ")"
}
return _API_TYPE_name[_API_TYPE_index[i]:_API_TYPE_index[i+1]]
}

View File

@@ -0,0 +1,224 @@
// Code generated by "stringer -type=APIType"; DO NOT EDIT.
package zebra
import "strconv"
func _() {
// An "invalid array index" compiler error signifies that the constant values have changed.
// Re-run the stringer command to generate them again.
var x [1]struct{}
_ = x[interfaceAdd-0]
_ = x[interfaceDelete-1]
_ = x[interfaceAddressAdd-2]
_ = x[interfaceAddressDelete-3]
_ = x[interfaceUp-4]
_ = x[interfaceDown-5]
_ = x[_interfaceSetMaster-6]
_ = x[_interfaceSetProtoDown-7]
_ = x[RouteAdd-8]
_ = x[RouteDelete-9]
_ = x[_routeNotifyOwner-10]
_ = x[redistributeAdd-11]
_ = x[_redistributeDelete-12]
_ = x[_redistributeDefaultAdd-13]
_ = x[_redistributeDefaultDelete-14]
_ = x[routerIDAdd-15]
_ = x[_routerIDDelete-16]
_ = x[routerIDUpdate-17]
_ = x[hello-18]
_ = x[_capabilities-19]
_ = x[nexthopRegister-20]
_ = x[nexthopUnregister-21]
_ = x[nexthopUpdate-22]
_ = x[_interfaceNBRAddressAdd-23]
_ = x[_interfaceNBRAddressDelete-24]
_ = x[_interfaceBFDDestUpdate-25]
_ = x[_importRouteRegister-26]
_ = x[_importRouteUnregister-27]
_ = x[_importCheckUpdate-28]
_ = x[_bfdDestRegister-29]
_ = x[_bfdDestDeregister-30]
_ = x[_bfdDestUpdate-31]
_ = x[_bfdDestReplay-32]
_ = x[redistributeRouteAdd-33]
_ = x[redistributeRouteDel-34]
_ = x[_vrfUnregister-35]
_ = x[_vrfAdd-36]
_ = x[_vrfDelete-37]
_ = x[vrfLabel-38]
_ = x[_interfaceVRFUpdate-39]
_ = x[_bfdClientRegister-40]
_ = x[_bfdClientDeregister-41]
_ = x[_interfaceEnableRADV-42]
_ = x[_interfaceDisableRADV-43]
_ = x[ipv4NexthopLookupMRIB-44]
_ = x[_interfaceLinkParams-45]
_ = x[_mplsLabelsAdd-46]
_ = x[_mplsLabelsDelete-47]
_ = x[_mplsLabelsReplace-48]
_ = x[_ipmrRouteStats-49]
_ = x[labelManagerConnect-50]
_ = x[labelManagerConnectAsync-51]
_ = x[getLabelChunk-52]
_ = x[releaseLabelChunk-53]
_ = x[_fecRegister-54]
_ = x[_fecUnregister-55]
_ = x[_fecUpdate-56]
_ = x[_advertiseDefaultGW-57]
_ = x[_advertiseSviMACIP-58]
_ = x[_advertiseSubnet-59]
_ = x[_advertiseAllVNI-60]
_ = x[_localESAdd-61]
_ = x[_localESDel-62]
_ = x[_vniAdd-63]
_ = x[_vniDel-64]
_ = x[_l3VNIAdd-65]
_ = x[_l3VNIDel-66]
_ = x[_remoteVTEPAdd-67]
_ = x[_remoteVTEPDel-68]
_ = x[_macIPAdd-69]
_ = x[_macIPDel-70]
_ = x[_ipPrefixRouteAdd-71]
_ = x[_ipPrefixRouteDel-72]
_ = x[_remoteMACIPAdd-73]
_ = x[_remoteMACIPDel-74]
_ = x[_duplicateAddrDetection-75]
_ = x[_pwAdd-76]
_ = x[_pwDelete-77]
_ = x[_pwSet-78]
_ = x[_pwUnset-79]
_ = x[_pwStatusUpdate-80]
_ = x[_ruleAdd-81]
_ = x[_ruleDelete-82]
_ = x[_ruleNotifyOwner-83]
_ = x[_tableManagerConnect-84]
_ = x[_getTableChunk-85]
_ = x[_releaseTableChunk-86]
_ = x[_ipSetCreate-87]
_ = x[_ipSetDestroy-88]
_ = x[_ipSetEntryAdd-89]
_ = x[_ipSetEntryDelete-90]
_ = x[_ipSetNotifyOwner-91]
_ = x[_ipSetEntryNotifyOwner-92]
_ = x[_ipTableAdd-93]
_ = x[_ipTableDelete-94]
_ = x[_ipTableNotifyOwner-95]
_ = x[_vxlanFloodControl-96]
_ = x[_vxlanSgAdd-97]
_ = x[_vxlanSgDel-98]
_ = x[_vxlanSgReplay-99]
_ = x[_mlagProcessUp-100]
_ = x[_mlagProcessDown-101]
_ = x[_mlagClientRegister-102]
_ = x[_mlagClientUnregister-103]
_ = x[_mlagClientForwardMsg-104]
_ = x[zebraError-105]
_ = x[_clientCapabilities-106]
_ = x[BackwardIPv6RouteAdd-107]
_ = x[BackwardIPv6RouteDelete-108]
_ = x[zapi6Frr7dot2MinDifferentAPIType-48]
_ = x[zapi5ClMinDifferentAPIType-19]
_ = x[zapi5MinDifferentAPIType-7]
_ = x[zapi4MinDifferentAPIType-6]
_ = x[zapi3MinDifferentAPIType-0]
_ = x[zapi6Frr7dot2LabelManagerConnect-49]
_ = x[zapi6Frr7dot2LabelManagerConnectAsync-50]
_ = x[zapi6Frr7dot2GetLabelChunk-51]
_ = x[zapi6Frr7dot2ReleaseLabelChunk-52]
_ = x[zapi6Frr7RouteAdd-7]
_ = x[zapi6Frr7RouteDelete-8]
_ = x[zapi6Frr7RedistributAdd-10]
_ = x[zapi6Frr7RouterIDAdd-14]
_ = x[zapi6Frr7RouterIDUpdate-16]
_ = x[zapi6Frr7Hello-17]
_ = x[zapi6Frr7NexthopRegister-19]
_ = x[zapi6Frr7NexthopUnregister-20]
_ = x[zapi6Frr7NexthopUpdate-21]
_ = x[zapi6Frr7RedistributeRouteAdd-32]
_ = x[zapi6Frr7RedistributeRouteDel-33]
_ = x[zapi6Frr7VrfLabel-37]
_ = x[zapi6Frr7Ipv4NexthopLookupMRIB-43]
_ = x[zapi6Frr7LabelManagerConnect-48]
_ = x[zapi6Frr7LabelManagerConnectAsync-49]
_ = x[zapi6Frr7GetLabelChunk-50]
_ = x[zapi6Frr7ReleaseLabelChunk-51]
_ = x[zapi5ClIpv4NexthopLookupMRIB-42]
_ = x[zapi5ClLabelManagerConnect-47]
_ = x[zapi5ClGetLabelChunk-48]
_ = x[zapi5ClReleaseLabelChunk-49]
_ = x[zapi5RedistributAdd-14]
_ = x[zapi5RouterIDAdd-18]
_ = x[zapi5RouterIDUpdate-20]
_ = x[zapi5Hello-21]
_ = x[zapi5Frr5NexthopRegister-23]
_ = x[zapi5Frr5NexthopUnregister-24]
_ = x[zapi5Frr5NexthopUpdate-25]
_ = x[zapi5Frr5RedistributeRouteAdd-37]
_ = x[zapi5Frr5RedistributeRouteDel-38]
_ = x[zapi5Frr5VrfLabel-42]
_ = x[zapi5Frr5Ipv4NexthopLookupMRIB-47]
_ = x[zapi5Frr5LabelManagerConnect-52]
_ = x[zapi5Frr5LabelManagerConnectAsync-53]
_ = x[zapi5Frr5GetLabelChunk-54]
_ = x[zapi5Frr5ReleaseLabelChunk-55]
_ = x[zapi5Frr4NexthopRegister-22]
_ = x[zapi5Frr4NexthopUnregister-23]
_ = x[zapi5Frr4NexthopUpdate-24]
_ = x[zapi5Frr4RedistributeRouteAdd-36]
_ = x[zapi5Frr4RedistributeRouteDel-37]
_ = x[zapi5Frr4Ipv4NexthopLookupMRIB-45]
_ = x[zapi5Frr4LabelManagerConnect-50]
_ = x[zapi5Frr4GetLabelChunk-51]
_ = x[zapi5Frr4ReleaseLabelChunk-52]
_ = x[zapi4IPv4RouteAdd-6]
_ = x[zapi4IPv4RouteDelete-7]
_ = x[zapi4IPv6RouteAdd-8]
_ = x[zapi4IPv6RouteDelete-9]
_ = x[zapi4RedistributAdd-10]
_ = x[zapi4RouterIDAdd-14]
_ = x[zapi4RouterIDUpdate-16]
_ = x[zapi4Hello-17]
_ = x[zapi4NexthopRegister-18]
_ = x[zapi4NexthopUnregister-19]
_ = x[zapi4NexthopUpdate-20]
_ = x[zapi4RedistributeIPv4Add-32]
_ = x[zapi4RedistributeIPv4Del-33]
_ = x[zapi4RedistributeIPv6Add-34]
_ = x[zapi4RedistributeIPv6Del-35]
_ = x[zapi4LabelManagerConnect-52]
_ = x[zapi4GetLabelChunk-53]
_ = x[zapi4ReleaseLabelChunk-54]
_ = x[zapi3InterfaceAdd-1]
_ = x[zapi3InterfaceDelete-2]
_ = x[zapi3InterfaceAddressAdd-3]
_ = x[zapi3InterfaceAddressDelete-4]
_ = x[zapi3InterfaceUp-5]
_ = x[zapi3InterfaceDown-6]
_ = x[zapi3IPv4RouteAdd-7]
_ = x[zapi3IPv4RouteDelete-8]
_ = x[zapi3IPv6RouteAdd-9]
_ = x[zapi3IPv6RouteDelete-10]
_ = x[zapi3RedistributeAdd-11]
_ = x[zapi3IPv4NexthopLookup-15]
_ = x[zapi3IPv6NexthopLookup-16]
_ = x[zapi3IPv4ImportLookup-17]
_ = x[zapi3RouterIDAdd-20]
_ = x[zapi3RouterIDUpdate-22]
_ = x[zapi3Hello-23]
_ = x[zapi3Ipv4NexthopLookupMRIB-24]
_ = x[zapi3NexthopRegister-27]
_ = x[zapi3NexthopUnregister-28]
_ = x[zapi3NexthopUpdate-29]
}
const _APIType_name = "interfaceAddinterfaceDeleteinterfaceAddressAddinterfaceAddressDeleteinterfaceUpinterfaceDown_interfaceSetMaster_interfaceSetProtoDownRouteAddRouteDelete_routeNotifyOwnerredistributeAdd_redistributeDelete_redistributeDefaultAdd_redistributeDefaultDeleterouterIDAdd_routerIDDeleterouterIDUpdatehello_capabilitiesnexthopRegisternexthopUnregisternexthopUpdate_interfaceNBRAddressAdd_interfaceNBRAddressDelete_interfaceBFDDestUpdate_importRouteRegister_importRouteUnregister_importCheckUpdate_bfdDestRegister_bfdDestDeregister_bfdDestUpdate_bfdDestReplayredistributeRouteAddredistributeRouteDel_vrfUnregister_vrfAdd_vrfDeletevrfLabel_interfaceVRFUpdate_bfdClientRegister_bfdClientDeregister_interfaceEnableRADV_interfaceDisableRADVipv4NexthopLookupMRIB_interfaceLinkParams_mplsLabelsAdd_mplsLabelsDelete_mplsLabelsReplace_ipmrRouteStatslabelManagerConnectlabelManagerConnectAsyncgetLabelChunkreleaseLabelChunk_fecRegister_fecUnregister_fecUpdate_advertiseDefaultGW_advertiseSviMACIP_advertiseSubnet_advertiseAllVNI_localESAdd_localESDel_vniAdd_vniDel_l3VNIAdd_l3VNIDel_remoteVTEPAdd_remoteVTEPDel_macIPAdd_macIPDel_ipPrefixRouteAdd_ipPrefixRouteDel_remoteMACIPAdd_remoteMACIPDel_duplicateAddrDetection_pwAdd_pwDelete_pwSet_pwUnset_pwStatusUpdate_ruleAdd_ruleDelete_ruleNotifyOwner_tableManagerConnect_getTableChunk_releaseTableChunk_ipSetCreate_ipSetDestroy_ipSetEntryAdd_ipSetEntryDelete_ipSetNotifyOwner_ipSetEntryNotifyOwner_ipTableAdd_ipTableDelete_ipTableNotifyOwner_vxlanFloodControl_vxlanSgAdd_vxlanSgDel_vxlanSgReplay_mlagProcessUp_mlagProcessDown_mlagClientRegister_mlagClientUnregister_mlagClientForwardMsgzebraError_clientCapabilitiesBackwardIPv6RouteAddBackwardIPv6RouteDelete"
var _APIType_index = [...]uint16{0, 12, 27, 46, 68, 79, 92, 111, 133, 141, 152, 169, 184, 203, 226, 252, 263, 278, 292, 297, 310, 325, 342, 355, 378, 404, 427, 447, 469, 487, 503, 521, 535, 549, 569, 589, 603, 610, 620, 628, 647, 665, 685, 705, 726, 747, 767, 781, 798, 816, 831, 850, 874, 887, 904, 916, 930, 940, 959, 977, 993, 1009, 1020, 1031, 1038, 1045, 1054, 1063, 1077, 1091, 1100, 1109, 1126, 1143, 1158, 1173, 1196, 1202, 1211, 1217, 1225, 1240, 1248, 1259, 1275, 1295, 1309, 1327, 1339, 1352, 1366, 1383, 1400, 1422, 1433, 1447, 1466, 1484, 1495, 1506, 1520, 1534, 1550, 1569, 1590, 1611, 1621, 1640, 1660, 1683}
func (i APIType) String() string {
if i >= APIType(len(_APIType_index)-1) {
return "APIType(" + strconv.FormatInt(int64(i), 10) + ")"
}
return _APIType_name[_APIType_index[i]:_APIType_index[i+1]]
}

View File

@@ -1,16 +0,0 @@
// Code generated by "stringer -type=LINK_TYPE"; DO NOT EDIT.
package zebra
import "strconv"
const _LINK_TYPE_name = "LINK_TYPE_UNKNOWNLINK_TYPE_ETHERLINK_TYPE_EETHERLINK_TYPE_AX25LINK_TYPE_PRONETLINK_TYPE_IEEE802LINK_TYPE_ARCNETLINK_TYPE_APPLETLKLINK_TYPE_DLCILINK_TYPE_ATMLINK_TYPE_METRICOMLINK_TYPE_IEEE1394LINK_TYPE_EUI64LINK_TYPE_INFINIBANDLINK_TYPE_SLIPLINK_TYPE_CSLIPLINK_TYPE_SLIP6LINK_TYPE_CSLIP6LINK_TYPE_RSRVDLINK_TYPE_ADAPTLINK_TYPE_ROSELINK_TYPE_X25LINK_TYPE_PPPLINK_TYPE_CHDLCLINK_TYPE_LAPBLINK_TYPE_RAWHDLCLINK_TYPE_IPIPLINK_TYPE_IPIP6LINK_TYPE_FRADLINK_TYPE_SKIPLINK_TYPE_LOOPBACKLINK_TYPE_LOCALTLKLINK_TYPE_FDDILINK_TYPE_SITLINK_TYPE_IPDDPLINK_TYPE_IPGRELINK_TYPE_IP6GRELINK_TYPE_PIMREGLINK_TYPE_HIPPILINK_TYPE_ECONETLINK_TYPE_IRDALINK_TYPE_FCPPLINK_TYPE_FCALLINK_TYPE_FCPLLINK_TYPE_FCFABRICLINK_TYPE_IEEE802_TRLINK_TYPE_IEEE80211LINK_TYPE_IEEE80211_RADIOTAPLINK_TYPE_IEEE802154LINK_TYPE_IEEE802154_PHY"
var _LINK_TYPE_index = [...]uint16{0, 17, 32, 48, 62, 78, 95, 111, 129, 143, 156, 174, 192, 207, 227, 241, 256, 271, 287, 302, 317, 331, 344, 357, 372, 386, 403, 417, 432, 446, 460, 478, 496, 510, 523, 538, 553, 569, 585, 600, 616, 630, 644, 658, 672, 690, 710, 729, 757, 777, 801}
func (i LINK_TYPE) String() string {
if i >= LINK_TYPE(len(_LINK_TYPE_index)-1) {
return "LINK_TYPE(" + strconv.FormatInt(int64(i), 10) + ")"
}
return _LINK_TYPE_name[_LINK_TYPE_index[i]:_LINK_TYPE_index[i+1]]
}

View File

@@ -0,0 +1,72 @@
// Code generated by "stringer -type=linkType"; DO NOT EDIT.
package zebra
import "strconv"
func _() {
// An "invalid array index" compiler error signifies that the constant values have changed.
// Re-run the stringer command to generate them again.
var x [1]struct{}
_ = x[linkTypeUnknown-0]
_ = x[linkTypeEther-1]
_ = x[linkTypeEEther-2]
_ = x[linkTypeAX25-3]
_ = x[linkTypePRONET-4]
_ = x[linkTypeIeee802-5]
_ = x[linkTypeARCNET-6]
_ = x[linkTypeAPPLETLK-7]
_ = x[linkTypeDLCI-8]
_ = x[linkTypeATM-9]
_ = x[linkTypeMetricOM-10]
_ = x[linkTypeIeee1394-11]
_ = x[linkTypeEUI64-12]
_ = x[linkTypeINFINIBAND-13]
_ = x[linkTypeSLIP-14]
_ = x[linkTypeCSLIP-15]
_ = x[linkTypeSLIP6-16]
_ = x[linkTypeCSLIP6-17]
_ = x[linkTypeRSRVD-18]
_ = x[linkTypeADAPT-19]
_ = x[linkTypeROSE-20]
_ = x[linkTypeX25-21]
_ = x[linkTypePPP-22]
_ = x[linkTypeCHDLC-23]
_ = x[linkTypeLAPB-24]
_ = x[linkTypeRAWHDLC-25]
_ = x[linkTypeIPIP-26]
_ = x[linkTypeIPIP6-27]
_ = x[linkTypeFRAD-28]
_ = x[linkTypeSKIP-29]
_ = x[linkTypeLOOPBACK-30]
_ = x[linkTypeLOCALTLK-31]
_ = x[linkTypeFDDI-32]
_ = x[linkTypeSIT-33]
_ = x[linkTypeIPDDP-34]
_ = x[linkTypeIPGRE-35]
_ = x[linkTypeIP6GRE-36]
_ = x[linkTypePIMREG-37]
_ = x[linkTypeHIPPI-38]
_ = x[linkTypeECONET-39]
_ = x[linkTypeIRDA-40]
_ = x[linkTypeFCPP-41]
_ = x[linkTypeFCAL-42]
_ = x[linkTypeFCPL-43]
_ = x[linkTypeFCFABRIC-44]
_ = x[linkTypeIeee802Tr-45]
_ = x[linkTypeIeee80211-46]
_ = x[linkTypeIeee80211RadioTap-47]
_ = x[linkTypeIeee802154-48]
_ = x[linkTypeIeee802154Phy-49]
}
const _linkType_name = "linkTypeUnknownlinkTypeEtherlinkTypeEEtherlinkTypeAX25linkTypePRONETlinkTypeIeee802linkTypeARCNETlinkTypeAPPLETLKlinkTypeDLCIlinkTypeATMlinkTypeMetricOMlinkTypeIeee1394linkTypeEUI64linkTypeINFINIBANDlinkTypeSLIPlinkTypeCSLIPlinkTypeSLIP6linkTypeCSLIP6linkTypeRSRVDlinkTypeADAPTlinkTypeROSElinkTypeX25linkTypePPPlinkTypeCHDLClinkTypeLAPBlinkTypeRAWHDLClinkTypeIPIPlinkTypeIPIP6linkTypeFRADlinkTypeSKIPlinkTypeLOOPBACKlinkTypeLOCALTLKlinkTypeFDDIlinkTypeSITlinkTypeIPDDPlinkTypeIPGRElinkTypeIP6GRElinkTypePIMREGlinkTypeHIPPIlinkTypeECONETlinkTypeIRDAlinkTypeFCPPlinkTypeFCALlinkTypeFCPLlinkTypeFCFABRIClinkTypeIeee802TrlinkTypeIeee80211linkTypeIeee80211RadioTaplinkTypeIeee802154linkTypeIeee802154Phy"
var _linkType_index = [...]uint16{0, 15, 28, 42, 54, 68, 83, 97, 113, 125, 136, 152, 168, 181, 199, 211, 224, 237, 251, 264, 277, 289, 300, 311, 324, 336, 351, 363, 376, 388, 400, 416, 432, 444, 455, 468, 481, 495, 509, 522, 536, 548, 560, 572, 584, 600, 617, 634, 659, 677, 698}
func (i linkType) String() string {
if i >= linkType(len(_linkType_index)-1) {
return "linkType(" + strconv.FormatInt(int64(i), 10) + ")"
}
return _linkType_name[_linkType_index[i]:_linkType_index[i+1]]
}

View File

@@ -0,0 +1,28 @@
// Code generated by "stringer -type=lspTYPE"; DO NOT EDIT.
package zebra
import "strconv"
func _() {
// An "invalid array index" compiler error signifies that the constant values have changed.
// Re-run the stringer command to generate them again.
var x [1]struct{}
_ = x[lspNone-0]
_ = x[lspStatic-1]
_ = x[lspLDP-2]
_ = x[lspBGP-3]
_ = x[lspSR-4]
_ = x[lspSHARP-5]
}
const _lspTYPE_name = "lspNonelspStaticlspLDPlspBGPlspSRlspSHARP"
var _lspTYPE_index = [...]uint8{0, 7, 16, 22, 28, 33, 41}
func (i lspTYPE) String() string {
if i >= lspTYPE(len(_lspTYPE_index)-1) {
return "lspTYPE(" + strconv.FormatInt(int64(i), 10) + ")"
}
return _lspTYPE_name[_lspTYPE_index[i]:_lspTYPE_index[i+1]]
}

View File

@@ -1,41 +0,0 @@
// Code generated by "stringer -type=NEXTHOP_FLAG"; DO NOT EDIT.
package zebra
import "strconv"
const (
_NEXTHOP_FLAG_name_0 = "NEXTHOP_FLAG_ACTIVENEXTHOP_FLAG_FIB"
_NEXTHOP_FLAG_name_1 = "NEXTHOP_FLAG_RECURSIVE"
_NEXTHOP_FLAG_name_2 = "NEXTHOP_FLAG_ONLINK"
_NEXTHOP_FLAG_name_3 = "NEXTHOP_FLAG_MATCHED"
_NEXTHOP_FLAG_name_4 = "NEXTHOP_FLAG_FILTERED"
_NEXTHOP_FLAG_name_5 = "NEXTHOP_FLAG_DUPLICATE"
_NEXTHOP_FLAG_name_6 = "NEXTHOP_FLAG_EVPN_RVTEP"
)
var (
_NEXTHOP_FLAG_index_0 = [...]uint8{0, 19, 35}
)
func (i NEXTHOP_FLAG) String() string {
switch {
case 1 <= i && i <= 2:
i -= 1
return _NEXTHOP_FLAG_name_0[_NEXTHOP_FLAG_index_0[i]:_NEXTHOP_FLAG_index_0[i+1]]
case i == 4:
return _NEXTHOP_FLAG_name_1
case i == 8:
return _NEXTHOP_FLAG_name_2
case i == 16:
return _NEXTHOP_FLAG_name_3
case i == 32:
return _NEXTHOP_FLAG_name_4
case i == 64:
return _NEXTHOP_FLAG_name_5
case i == 128:
return _NEXTHOP_FLAG_name_6
default:
return "NEXTHOP_FLAG(" + strconv.FormatInt(int64(i), 10) + ")"
}
}

View File

@@ -1,17 +0,0 @@
// Code generated by "stringer -type=NEXTHOP_TYPE"; DO NOT EDIT.
package zebra
import "strconv"
const _NEXTHOP_TYPE_name = "FRR_NEXTHOP_TYPE_IFINDEXFRR_NEXTHOP_TYPE_IPV4FRR_NEXTHOP_TYPE_IPV4_IFINDEXFRR_NEXTHOP_TYPE_IPV6FRR_NEXTHOP_TYPE_IPV6_IFINDEXFRR_NEXTHOP_TYPE_BLACKHOLENEXTHOP_TYPE_IPV6_IFINDEXNEXTHOP_TYPE_IPV6_IFNAMENEXTHOP_TYPE_BLACKHOLE"
var _NEXTHOP_TYPE_index = [...]uint8{0, 24, 45, 74, 95, 124, 150, 175, 199, 221}
func (i NEXTHOP_TYPE) String() string {
i -= 1
if i >= NEXTHOP_TYPE(len(_NEXTHOP_TYPE_index)-1) {
return "NEXTHOP_TYPE(" + strconv.FormatInt(int64(i+1), 10) + ")"
}
return _NEXTHOP_TYPE_name[_NEXTHOP_TYPE_index[i]:_NEXTHOP_TYPE_index[i+1]]
}

View File

@@ -0,0 +1,55 @@
// Code generated by "stringer -type=nexthopFlag"; DO NOT EDIT.
package zebra
import "strconv"
func _() {
// An "invalid array index" compiler error signifies that the constant values have changed.
// Re-run the stringer command to generate them again.
var x [1]struct{}
_ = x[nexthopFlagActive-1]
_ = x[nexthopFlagFIB-2]
_ = x[nexthopFlagRecursive-4]
_ = x[nexthopFlagOnlink-8]
_ = x[nexthopFlagMatched-16]
_ = x[nexthopFlagFiltered-32]
_ = x[nexthopFlagDuplicate-64]
_ = x[nexthopFlagEvpnRvtep-128]
}
const (
_nexthopFlag_name_0 = "nexthopFlagActivenexthopFlagFIB"
_nexthopFlag_name_1 = "nexthopFlagRecursive"
_nexthopFlag_name_2 = "nexthopFlagOnlink"
_nexthopFlag_name_3 = "nexthopFlagMatched"
_nexthopFlag_name_4 = "nexthopFlagFiltered"
_nexthopFlag_name_5 = "nexthopFlagDuplicate"
_nexthopFlag_name_6 = "nexthopFlagEvpnRvtep"
)
var (
_nexthopFlag_index_0 = [...]uint8{0, 17, 31}
)
func (i nexthopFlag) String() string {
switch {
case 1 <= i && i <= 2:
i -= 1
return _nexthopFlag_name_0[_nexthopFlag_index_0[i]:_nexthopFlag_index_0[i+1]]
case i == 4:
return _nexthopFlag_name_1
case i == 8:
return _nexthopFlag_name_2
case i == 16:
return _nexthopFlag_name_3
case i == 32:
return _nexthopFlag_name_4
case i == 64:
return _nexthopFlag_name_5
case i == 128:
return _nexthopFlag_name_6
default:
return "nexthopFlag(" + strconv.FormatInt(int64(i), 10) + ")"
}
}

View File

@@ -0,0 +1,37 @@
// Code generated by "stringer -type=nexthopType"; DO NOT EDIT.
package zebra
import "strconv"
func _() {
// An "invalid array index" compiler error signifies that the constant values have changed.
// Re-run the stringer command to generate them again.
var x [1]struct{}
_ = x[nexthopTypeIFIndex-1]
_ = x[nexthopTypeIPv4-2]
_ = x[nexthopTypeIPv4IFIndex-3]
_ = x[nexthopTypeIPv6-4]
_ = x[nexthopTypeIPv6IFIndex-5]
_ = x[nexthopTypeBlackhole-6]
_ = x[nexthopTypeIFName-2]
_ = x[backwardNexthopTypeIPv4-3]
_ = x[backwardNexthopTypeIPv4IFIndex-4]
_ = x[nexthopTypeIPv4IFName-5]
_ = x[backwardNexthopTypeIPv6-6]
_ = x[backwardNexthopTypeIPv6IFIndex-7]
_ = x[nexthopTypeIPv6IFName-8]
_ = x[backwardNexthopTypeBlackhole-9]
}
const _nexthopType_name = "nexthopTypeIFIndexnexthopTypeIPv4nexthopTypeIPv4IFIndexnexthopTypeIPv6nexthopTypeIPv6IFIndexnexthopTypeBlackholebackwardNexthopTypeIPv6IFIndexnexthopTypeIPv6IFNamebackwardNexthopTypeBlackhole"
var _nexthopType_index = [...]uint8{0, 18, 33, 55, 70, 92, 112, 142, 163, 191}
func (i nexthopType) String() string {
i -= 1
if i >= nexthopType(len(_nexthopType_index)-1) {
return "nexthopType(" + strconv.FormatInt(int64(i+1), 10) + ")"
}
return _nexthopType_name[_nexthopType_index[i]:_nexthopType_index[i+1]]
}

View File

@@ -1,16 +0,0 @@
// Code generated by "stringer -type=PTM_ENABLE"; DO NOT EDIT.
package zebra
import "strconv"
const _PTM_ENABLE_name = "PTM_ENABLE_OFFPTM_ENABLE_ONPTM_ENABLE_UNSPEC"
var _PTM_ENABLE_index = [...]uint8{0, 14, 27, 44}
func (i PTM_ENABLE) String() string {
if i >= PTM_ENABLE(len(_PTM_ENABLE_index)-1) {
return "PTM_ENABLE(" + strconv.FormatInt(int64(i), 10) + ")"
}
return _PTM_ENABLE_name[_PTM_ENABLE_index[i]:_PTM_ENABLE_index[i+1]]
}

View File

@@ -1,16 +0,0 @@
// Code generated by "stringer -type=PTM_STATUS"; DO NOT EDIT.
package zebra
import "strconv"
const _PTM_STATUS_name = "PTM_STATUS_DOWNPTM_STATUS_UPPTM_STATUS_UNKNOWN"
var _PTM_STATUS_index = [...]uint8{0, 15, 28, 46}
func (i PTM_STATUS) String() string {
if i >= PTM_STATUS(len(_PTM_STATUS_index)-1) {
return "PTM_STATUS(" + strconv.FormatInt(int64(i), 10) + ")"
}
return _PTM_STATUS_name[_PTM_STATUS_index[i]:_PTM_STATUS_index[i+1]]
}

View File

@@ -0,0 +1,25 @@
// Code generated by "stringer -type=ptmEnable"; DO NOT EDIT.
package zebra
import "strconv"
func _() {
// An "invalid array index" compiler error signifies that the constant values have changed.
// Re-run the stringer command to generate them again.
var x [1]struct{}
_ = x[ptmEnableOff-0]
_ = x[ptmEnableOn-1]
_ = x[ptmEnableUnspec-2]
}
const _ptmEnable_name = "ptmEnableOffptmEnableOnptmEnableUnspec"
var _ptmEnable_index = [...]uint8{0, 12, 23, 38}
func (i ptmEnable) String() string {
if i >= ptmEnable(len(_ptmEnable_index)-1) {
return "ptmEnable(" + strconv.FormatInt(int64(i), 10) + ")"
}
return _ptmEnable_name[_ptmEnable_index[i]:_ptmEnable_index[i+1]]
}

View File

@@ -0,0 +1,25 @@
// Code generated by "stringer -type=ptmStatus"; DO NOT EDIT.
package zebra
import "strconv"
func _() {
// An "invalid array index" compiler error signifies that the constant values have changed.
// Re-run the stringer command to generate them again.
var x [1]struct{}
_ = x[ptmStatusDown-0]
_ = x[ptmStatusUp-1]
_ = x[ptmStatusUnknown-2]
}
const _ptmStatus_name = "ptmStatusDownptmStatusUpptmStatusUnknown"
var _ptmStatus_index = [...]uint8{0, 13, 24, 40}
func (i ptmStatus) String() string {
if i >= ptmStatus(len(_ptmStatus_index)-1) {
return "ptmStatus(" + strconv.FormatInt(int64(i), 10) + ")"
}
return _ptmStatus_name[_ptmStatus_index[i]:_ptmStatus_index[i+1]]
}

View File

@@ -1,16 +0,0 @@
// Code generated by "stringer -type=ROUTE_TYPE"; DO NOT EDIT.
package zebra
import "strconv"
const _ROUTE_TYPE_name = "FRR_ZAPI5_ROUTE_SYSTEMFRR_ZAPI5_ROUTE_KERNELFRR_ZAPI5_ROUTE_CONNECTFRR_ZAPI5_ROUTE_STATICFRR_ZAPI5_ROUTE_RIPFRR_ZAPI5_ROUTE_RIPNGFRR_ZAPI5_ROUTE_OSPFFRR_ZAPI5_ROUTE_OSPF6FRR_ZAPI5_ROUTE_ISISFRR_ZAPI5_ROUTE_BGPFRR_ZAPI5_ROUTE_PIMFRR_ZAPI5_ROUTE_EIGRPFRR_ZAPI5_ROUTE_NHRPFRR_ZAPI5_ROUTE_HSLSFRR_ZAPI5_ROUTE_OLSRFRR_ZAPI5_ROUTE_TABLEFRR_ZAPI5_ROUTE_LDPFRR_ZAPI5_ROUTE_VNCFRR_ZAPI5_ROUTE_VNC_DIRECTFRR_ZAPI5_ROUTE_VNC_DIRECT_RHFRR_ZAPI5_ROUTE_BGP_DIRECTFRR_ZAPI5_ROUTE_BGP_DIRECT_EXTFRR_ZAPI5_ROUTE_BABELFRR_ZAPI5_ROUTE_SHARPFRR_ZAPI5_ROUTE_PBRFRR_ZAPI5_ROUTE_ALLFRR_ZAPI5_ROUTE_MAX"
var _ROUTE_TYPE_index = [...]uint16{0, 22, 44, 67, 89, 108, 129, 149, 170, 190, 209, 228, 249, 269, 289, 309, 330, 349, 368, 394, 423, 449, 479, 500, 521, 540, 559, 578}
func (i ROUTE_TYPE) String() string {
if i >= ROUTE_TYPE(len(_ROUTE_TYPE_index)-1) {
return "ROUTE_TYPE(" + strconv.FormatInt(int64(i), 10) + ")"
}
return _ROUTE_TYPE_name[_ROUTE_TYPE_index[i]:_ROUTE_TYPE_index[i+1]]
}

View File

@@ -0,0 +1,73 @@
// Code generated by "stringer -type=RouteType"; DO NOT EDIT.
package zebra
import "strconv"
func _() {
// An "invalid array index" compiler error signifies that the constant values have changed.
// Re-run the stringer command to generate them again.
var x [1]struct{}
_ = x[routeSystem-0]
_ = x[routeKernel-1]
_ = x[routeConnect-2]
_ = x[RouteStatic-3]
_ = x[routeRIP-4]
_ = x[routeRIPNG-5]
_ = x[routeOSPF-6]
_ = x[routeOSPF6-7]
_ = x[routeISIS-8]
_ = x[RouteBGP-9]
_ = x[routePIM-10]
_ = x[routeEIGRP-11]
_ = x[routeNHRP-12]
_ = x[routeHSLS-13]
_ = x[routeOLSR-14]
_ = x[routeTABLE-15]
_ = x[routeLDP-16]
_ = x[routeVNC-17]
_ = x[routeVNCDirect-18]
_ = x[routeVNCDirectRH-19]
_ = x[routeBGPDirect-20]
_ = x[routeBGPDirectEXT-21]
_ = x[routeBABEL-22]
_ = x[routeSHARP-23]
_ = x[routePBR-24]
_ = x[routeBFD-25]
_ = x[routeOpenfabric-26]
_ = x[routeVRRP-27]
_ = x[routeNHG-28]
_ = x[routeAll-29]
_ = x[routeMax-30]
_ = x[zapi5Frr4RouteAll-24]
_ = x[zapi5Frr5RouteAll-25]
_ = x[zapi6Frr6RouteAll-26]
_ = x[zapi6Frr7RouteAll-27]
_ = x[zapi6Frr7dot2RouteAll-28]
_ = x[zapi4RouteNHRP-11]
_ = x[zapi4RouteHSLS-12]
_ = x[zapi4RouteOLSR-13]
_ = x[zapi4RouteTABLE-14]
_ = x[zapi4RouteLDP-15]
_ = x[zapi4RouteVNC-16]
_ = x[zapi4RouteVNCDirect-17]
_ = x[zapi4RouteVNCDirectRH-18]
_ = x[zapi4RouteBGPDixrect-19]
_ = x[zapi4RouteBGPDirectEXT-20]
_ = x[zapi4RouteAll-21]
_ = x[zapi3RouteHSLS-11]
_ = x[zapi3RouteOLSR-12]
_ = x[zapi3RouteBABEL-13]
_ = x[zapi3RouteNHRP-14]
}
const _RouteType_name = "routeSystemrouteKernelrouteConnectRouteStaticrouteRIProuteRIPNGrouteOSPFrouteOSPF6routeISISRouteBGProutePIMrouteEIGRProuteNHRProuteHSLSrouteOLSRrouteTABLErouteLDProuteVNCrouteVNCDirectrouteVNCDirectRHrouteBGPDirectrouteBGPDirectEXTrouteBABELrouteSHARProutePBRrouteBFDrouteOpenfabricrouteVRRProuteNHGrouteAllrouteMax"
var _RouteType_index = [...]uint16{0, 11, 22, 34, 45, 53, 63, 72, 82, 91, 99, 107, 117, 126, 135, 144, 154, 162, 170, 184, 200, 214, 231, 241, 251, 259, 267, 282, 291, 299, 307, 315}
func (i RouteType) String() string {
if i >= RouteType(len(_RouteType_index)-1) {
return "RouteType(" + strconv.FormatInt(int64(i), 10) + ")"
}
return _RouteType_name[_RouteType_index[i]:_RouteType_index[i+1]]
}

View File

@@ -1,17 +1,36 @@
// Code generated by "stringer -type=SAFI"; DO NOT EDIT.
// Code generated by "stringer -type=Safi"; DO NOT EDIT.
package zebra
import "strconv"
const _SAFI_name = "SAFI_UNICASTSAFI_MULTICASTSAFI_RESERVED_3SAFI_MPLS_VPNSAFI_MAX"
var _SAFI_index = [...]uint8{0, 12, 26, 41, 54, 62}
func (i SAFI) String() string {
i -= 1
if i >= SAFI(len(_SAFI_index)-1) {
return "SAFI(" + strconv.FormatInt(int64(i+1), 10) + ")"
}
return _SAFI_name[_SAFI_index[i]:_SAFI_index[i+1]]
func _() {
// An "invalid array index" compiler error signifies that the constant values have changed.
// Re-run the stringer command to generate them again.
var x [1]struct{}
_ = x[safiUnspec-0]
_ = x[SafiUnicast-1]
_ = x[safiMulticast-2]
_ = x[safiMplsVpn-3]
_ = x[safiEncap-4]
_ = x[safiEvpn-5]
_ = x[safiLabeledUnicast-6]
_ = x[safiFlowspec-7]
_ = x[safiMax-8]
_ = x[zapi4SafiMplsVpn-3]
_ = x[zapi3SafiMplsVpn-4]
_ = x[zapi4SafiEncap-5]
_ = x[zapi4SafiEvpn-6]
_ = x[zapi3SafiEncap-7]
}
const _Safi_name = "safiUnspecSafiUnicastsafiMulticastsafiMplsVpnsafiEncapsafiEvpnsafiLabeledUnicastsafiFlowspecsafiMax"
var _Safi_index = [...]uint8{0, 10, 21, 34, 45, 54, 62, 80, 92, 99}
func (i Safi) String() string {
if i >= Safi(len(_Safi_index)-1) {
return "Safi(" + strconv.FormatInt(int64(i), 10) + ")"
}
return _Safi_name[_Safi_index[i]:_Safi_index[i+1]]
}

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -1,17 +1,50 @@
// generated by stringer -type BGPAttrType bgp.go; DO NOT EDIT
// Code generated by "stringer -type=BGPAttrType"; DO NOT EDIT.
package bgp
import "fmt"
import "strconv"
func _() {
// An "invalid array index" compiler error signifies that the constant values have changed.
// Re-run the stringer command to generate them again.
var x [1]struct{}
_ = x[BGP_ATTR_TYPE_ORIGIN-1]
_ = x[BGP_ATTR_TYPE_AS_PATH-2]
_ = x[BGP_ATTR_TYPE_NEXT_HOP-3]
_ = x[BGP_ATTR_TYPE_MULTI_EXIT_DISC-4]
_ = x[BGP_ATTR_TYPE_LOCAL_PREF-5]
_ = x[BGP_ATTR_TYPE_ATOMIC_AGGREGATE-6]
_ = x[BGP_ATTR_TYPE_AGGREGATOR-7]
_ = x[BGP_ATTR_TYPE_COMMUNITIES-8]
_ = x[BGP_ATTR_TYPE_ORIGINATOR_ID-9]
_ = x[BGP_ATTR_TYPE_CLUSTER_LIST-10]
_ = x[BGP_ATTR_TYPE_MP_REACH_NLRI-14]
_ = x[BGP_ATTR_TYPE_MP_UNREACH_NLRI-15]
_ = x[BGP_ATTR_TYPE_EXTENDED_COMMUNITIES-16]
_ = x[BGP_ATTR_TYPE_AS4_PATH-17]
_ = x[BGP_ATTR_TYPE_AS4_AGGREGATOR-18]
_ = x[BGP_ATTR_TYPE_PMSI_TUNNEL-22]
_ = x[BGP_ATTR_TYPE_TUNNEL_ENCAP-23]
_ = x[BGP_ATTR_TYPE_IP6_EXTENDED_COMMUNITIES-25]
_ = x[BGP_ATTR_TYPE_AIGP-26]
_ = x[BGP_ATTR_TYPE_LS-29]
_ = x[BGP_ATTR_TYPE_LARGE_COMMUNITY-32]
}
const (
_BGPAttrType_name_0 = "BGP_ATTR_TYPE_ORIGINBGP_ATTR_TYPE_AS_PATHBGP_ATTR_TYPE_NEXT_HOPBGP_ATTR_TYPE_MULTI_EXIT_DISCBGP_ATTR_TYPE_LOCAL_PREFBGP_ATTR_TYPE_ATOMIC_AGGREGATEBGP_ATTR_TYPE_AGGREGATORBGP_ATTR_TYPE_COMMUNITIESBGP_ATTR_TYPE_ORIGINATOR_IDBGP_ATTR_TYPE_CLUSTER_LIST"
_BGPAttrType_name_1 = "BGP_ATTR_TYPE_MP_REACH_NLRIBGP_ATTR_TYPE_MP_UNREACH_NLRIBGP_ATTR_TYPE_EXTENDED_COMMUNITIESBGP_ATTR_TYPE_AS4_PATHBGP_ATTR_TYPE_AS4_AGGREGATOR"
_BGPAttrType_name_2 = "BGP_ATTR_TYPE_PMSI_TUNNELBGP_ATTR_TYPE_TUNNEL_ENCAP"
_BGPAttrType_name_3 = "BGP_ATTR_TYPE_IP6_EXTENDED_COMMUNITIESBGP_ATTR_TYPE_AIGP"
_BGPAttrType_name_4 = "BGP_ATTR_TYPE_LS"
_BGPAttrType_name_5 = "BGP_ATTR_TYPE_LARGE_COMMUNITY"
)
var (
_BGPAttrType_index_0 = [...]uint8{0, 20, 41, 63, 92, 116, 146, 170, 195, 222, 248}
_BGPAttrType_index_1 = [...]uint8{0, 27, 56, 90, 112, 140}
_BGPAttrType_index_2 = [...]uint8{0, 25, 51}
_BGPAttrType_index_3 = [...]uint8{0, 38, 56}
)
func (i BGPAttrType) String() string {
@@ -22,7 +55,17 @@ func (i BGPAttrType) String() string {
case 14 <= i && i <= 18:
i -= 14
return _BGPAttrType_name_1[_BGPAttrType_index_1[i]:_BGPAttrType_index_1[i+1]]
case 22 <= i && i <= 23:
i -= 22
return _BGPAttrType_name_2[_BGPAttrType_index_2[i]:_BGPAttrType_index_2[i+1]]
case 25 <= i && i <= 26:
i -= 25
return _BGPAttrType_name_3[_BGPAttrType_index_3[i]:_BGPAttrType_index_3[i+1]]
case i == 29:
return _BGPAttrType_name_4
case i == 32:
return _BGPAttrType_name_5
default:
return fmt.Sprintf("BGPAttrType(%d)", i)
return "BGPAttrType(" + strconv.FormatInt(int64(i), 10) + ")"
}
}

View File

@@ -16,7 +16,7 @@
package bgp
import (
"fmt"
"strconv"
"strings"
)
@@ -24,6 +24,7 @@ const AS_TRANS = 23456
const BGP_PORT = 179
//go:generate stringer -type=FSMState
type FSMState int
const (
@@ -73,7 +74,7 @@ var ProtocolNameMap = map[Protocol]string{
func (p Protocol) String() string {
name, ok := ProtocolNameMap[p]
if !ok {
return fmt.Sprintf("%d", p)
return strconv.Itoa(int(p))
}
return name
}
@@ -161,7 +162,7 @@ var BitmaskFlagOpValueMap = map[string]BitmaskFlagOp{
}
func (f BitmaskFlagOp) String() string {
ops := make([]string, 0)
ops := make([]string, 0, 3)
if f&BITMASK_FLAG_OP_AND > 0 {
ops = append(ops, BitmaskFlagOpNameMap[BITMASK_FLAG_OP_AND])
} else {
@@ -323,5 +324,5 @@ func (t EthernetType) String() string {
if name, ok := EthernetTypeNameMap[t]; ok {
return name
}
return fmt.Sprintf("%d", t)
return strconv.Itoa(int(t))
}

View File

@@ -1,16 +1,28 @@
// generated by stringer -type=ESIType bgp.go validate.go; DO NOT EDIT
// Code generated by "stringer -type=ESIType"; DO NOT EDIT.
package bgp
import "fmt"
import "strconv"
func _() {
// An "invalid array index" compiler error signifies that the constant values have changed.
// Re-run the stringer command to generate them again.
var x [1]struct{}
_ = x[ESI_ARBITRARY-0]
_ = x[ESI_LACP-1]
_ = x[ESI_MSTP-2]
_ = x[ESI_MAC-3]
_ = x[ESI_ROUTERID-4]
_ = x[ESI_AS-5]
}
const _ESIType_name = "ESI_ARBITRARYESI_LACPESI_MSTPESI_MACESI_ROUTERIDESI_AS"
var _ESIType_index = [...]uint8{0, 13, 21, 29, 36, 48, 54}
func (i ESIType) String() string {
if i+1 >= ESIType(len(_ESIType_index)) {
return fmt.Sprintf("ESIType(%d)", i)
if i >= ESIType(len(_ESIType_index)-1) {
return "ESIType(" + strconv.FormatInt(int64(i), 10) + ")"
}
return _ESIType_name[_ESIType_index[i]:_ESIType_index[i+1]]
}

View File

@@ -1,8 +1,20 @@
// generated by stringer -type=FSMState -output=fsmstate_string.go bgp.go validate.go mrt.go rtr.go constant.go bmp.go esitype_string.go bgpattrtype_string.go; DO NOT EDIT
// Code generated by "stringer -type=FSMState"; DO NOT EDIT.
package bgp
import "fmt"
import "strconv"
func _() {
// An "invalid array index" compiler error signifies that the constant values have changed.
// Re-run the stringer command to generate them again.
var x [1]struct{}
_ = x[BGP_FSM_IDLE-0]
_ = x[BGP_FSM_CONNECT-1]
_ = x[BGP_FSM_ACTIVE-2]
_ = x[BGP_FSM_OPENSENT-3]
_ = x[BGP_FSM_OPENCONFIRM-4]
_ = x[BGP_FSM_ESTABLISHED-5]
}
const _FSMState_name = "BGP_FSM_IDLEBGP_FSM_CONNECTBGP_FSM_ACTIVEBGP_FSM_OPENSENTBGP_FSM_OPENCONFIRMBGP_FSM_ESTABLISHED"
@@ -10,7 +22,7 @@ var _FSMState_index = [...]uint8{0, 12, 27, 41, 57, 76, 95}
func (i FSMState) String() string {
if i < 0 || i >= FSMState(len(_FSMState_index)-1) {
return fmt.Sprintf("FSMState(%d)", i)
return "FSMState(" + strconv.FormatInt(int64(i), 10) + ")"
}
return _FSMState_name[_FSMState_index[i]:_FSMState_index[i+1]]
}

View File

@@ -0,0 +1,677 @@
package bgp
import (
"bytes"
"encoding/binary"
"encoding/json"
"fmt"
"net"
"github.com/golang/protobuf/ptypes"
api "github.com/osrg/gobgp/api"
)
const (
prefixSIDtlvHdrLen = 4
)
type TLVType uint8
type TLV struct {
Type TLVType
Length uint16
}
func (s *TLV) Len() int {
return int(s.Length) + tlvHdrLen - 1 // Extra reserved byte in the header
}
func (s *TLV) Serialize(value []byte) ([]byte, error) {
if len(value) != int(s.Length)-1 {
return nil, malformedAttrListErr("serialization failed: Prefix SID TLV malformed")
}
buf := make([]byte, prefixSIDtlvHdrLen+len(value))
p := 0
buf[p] = byte(s.Type)
p++
binary.BigEndian.PutUint16(buf[p:p+2], uint16(s.Length))
p += 2
// Reserved byte
p++
copy(buf[p:], value)
return buf, nil
}
func (s *TLV) DecodeFromBytes(data []byte) ([]byte, error) {
if len(data) < prefixSIDtlvHdrLen {
return nil, malformedAttrListErr("decoding failed: Prefix SID TLV malformed")
}
p := 0
s.Type = TLVType(data[p])
p++
s.Length = binary.BigEndian.Uint16(data[p : p+2])
if len(data) < s.Len() {
return nil, malformedAttrListErr("decoding failed: Prefix SID TLV malformed")
}
return data[prefixSIDtlvHdrLen:s.Len()], nil
}
// PrefixSIDTLVInterface defines standard set of methods to handle Prefix SID attribute's TLVs
type PrefixSIDTLVInterface interface {
Len() int
DecodeFromBytes([]byte) error
Serialize() ([]byte, error)
String() string
MarshalJSON() ([]byte, error)
}
type PrefixSIDAttribute struct {
TLVs []PrefixSIDTLVInterface
}
type PathAttributePrefixSID struct {
PathAttribute
TLVs []PrefixSIDTLVInterface
}
func (p *PathAttributePrefixSID) DecodeFromBytes(data []byte, options ...*MarshallingOption) error {
tlvs, err := p.PathAttribute.DecodeFromBytes(data)
if err != nil {
return err
}
for len(tlvs) >= prefixSIDtlvHdrLen {
t := &TLV{}
_, err := t.DecodeFromBytes(tlvs)
if err != nil {
return err
}
var tlv PrefixSIDTLVInterface
switch t.Type {
case 5:
tlv = &SRv6L3ServiceAttribute{
SubTLVs: make([]PrefixSIDTLVInterface, 0),
}
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 *PathAttributePrefixSID) Serialize(options ...*MarshallingOption) ([]byte, error) {
buf := make([]byte, 0)
for _, tlv := range p.TLVs {
s, err := tlv.Serialize()
if err != nil {
return nil, err
}
buf = append(buf, s...)
}
return p.PathAttribute.Serialize(buf)
}
func (p *PathAttributePrefixSID) String() string {
var buf bytes.Buffer
for _, tlv := range p.TLVs {
buf.WriteString(fmt.Sprintf("%s ", tlv.String()))
}
return fmt.Sprintf("{Prefix SID attributes: %s}", buf.String())
}
func (p *PathAttributePrefixSID) MarshalJSON() ([]byte, error) {
return json.Marshal(struct {
Type BGPAttrType `json:"type"`
Flags BGPAttrFlag `json:"flags"`
PrefixSIDAttribute
}{
p.GetType(),
p.GetFlags(),
*p.Extract(),
})
}
func (p *PathAttributePrefixSID) Extract() *PrefixSIDAttribute {
psid := &PrefixSIDAttribute{
TLVs: make([]PrefixSIDTLVInterface, 0),
}
psid.TLVs = append(psid.TLVs, p.TLVs...)
return psid
}
// SRv6L3Service defines the structure of SRv6 L3 Service object
type SRv6L3Service struct {
SubTLVs []PrefixSIDTLVInterface
}
// SRv6L3ServiceAttribute defines the structure of SRv6 L3 Service attribute
type SRv6L3ServiceAttribute struct {
TLV
SubTLVs []PrefixSIDTLVInterface
}
func (s *SRv6L3ServiceAttribute) Len() int {
return int(s.Length) + prefixSIDtlvHdrLen
}
func (s *SRv6L3ServiceAttribute) Serialize() ([]byte, error) {
buf := make([]byte, 0)
for _, tlv := range s.SubTLVs {
s, err := tlv.Serialize()
if err != nil {
return nil, err
}
buf = append(buf, s...)
}
return s.TLV.Serialize(buf)
}
func (s *SRv6L3ServiceAttribute) DecodeFromBytes(data []byte) error {
stlvs, err := s.TLV.DecodeFromBytes(data)
if err != nil {
return err
}
for len(stlvs) >= subTLVHdrLen {
t := &SubTLV{}
_, err := t.DecodeFromBytes(stlvs)
if err != nil {
return err
}
var stlv PrefixSIDTLVInterface
switch t.Type {
case 1:
stlv = &SRv6InformationSubTLV{
SubSubTLVs: make([]PrefixSIDTLVInterface, 0),
}
default:
data = data[t.Len():]
continue
}
if err := stlv.DecodeFromBytes(stlvs); err != nil {
return err
}
stlvs = stlvs[t.Len():]
s.SubTLVs = append(s.SubTLVs, stlv)
}
return nil
}
func (s *SRv6L3ServiceAttribute) MarshalJSON() ([]byte, error) {
return json.Marshal(struct {
Type TLVType `json:"type"`
SRv6L3Service
}{
s.Type,
*s.Extract(),
})
}
func (s *SRv6L3ServiceAttribute) String() string {
var buf bytes.Buffer
for _, tlv := range s.SubTLVs {
buf.WriteString(fmt.Sprintf("%s ", tlv.String()))
}
return fmt.Sprintf("{SRv6 L3 Service Attribute: %s}", buf.String())
}
func (s *SRv6L3ServiceAttribute) Extract() *SRv6L3Service {
l3 := &SRv6L3Service{
SubTLVs: make([]PrefixSIDTLVInterface, 0),
}
l3.SubTLVs = append(l3.SubTLVs, s.SubTLVs...)
return l3
}
const (
subTLVHdrLen = 3
)
type SubTLVType uint8
type SubTLV struct {
Type SubTLVType
Length uint16
}
func (s *SubTLV) Len() int {
return int(s.Length) + subTLVHdrLen
}
func (s *SubTLV) Serialize(value []byte) ([]byte, error) {
if len(value) != int(s.Length) {
return nil, malformedAttrListErr("serialization failed: Prefix SID TLV malformed")
}
// Extra byte is reserved
buf := make([]byte, subTLVHdrLen+len(value))
buf[0] = byte(s.Type)
binary.BigEndian.PutUint16(buf[1:4], uint16(s.Length))
// 4th reserved byte
copy(buf[4:], value)
return buf, nil
}
func (s *SubTLV) DecodeFromBytes(data []byte) ([]byte, error) {
if len(data) < subTLVHdrLen {
return nil, malformedAttrListErr("decoding failed: Prefix SID TLV malformed")
}
s.Type = SubTLVType(data[0])
s.Length = binary.BigEndian.Uint16(data[1:3])
if len(data) < s.Len() {
return nil, malformedAttrListErr("decoding failed: Prefix SID TLV malformed")
}
return data[subTLVHdrLen:s.Len()], nil
}
type SRv6InformationSTLV struct {
SID []byte `json:"sid"`
Flags uint8 `json:"flags"`
EndpointBehavior uint16 `json:"endpoint_behavior"`
SubSubTLVs []PrefixSIDTLVInterface `json:"sub_sub_tlvs,omitempty"`
}
// SRv6InformationSubTLV defines a structure of SRv6 Information Sub TLV (type 1) object
// https://tools.ietf.org/html/draft-dawra-bess-srv6-services-02#section-2.1.1
type SRv6InformationSubTLV struct {
SubTLV
SID []byte
Flags uint8
EndpointBehavior uint16
SubSubTLVs []PrefixSIDTLVInterface
}
func (s *SRv6InformationSubTLV) Len() int {
return int(s.Length) + subTLVHdrLen
}
func (s *SRv6InformationSubTLV) Serialize() ([]byte, error) {
buf := make([]byte, s.Length)
p := 0
copy(buf[p:], s.SID)
p += len(s.SID)
buf[p] = byte(s.Flags)
p++
binary.BigEndian.PutUint16(buf[p:p+2], uint16(s.EndpointBehavior))
p += 2
// Reserved byte
buf[p] = 0x0
p++
for _, sstlv := range s.SubSubTLVs {
sbuf, err := sstlv.Serialize()
if err != nil {
return nil, err
}
copy(buf[p:], sbuf)
p += len(sbuf)
}
return s.SubTLV.Serialize(buf)
}
func (s *SRv6InformationSubTLV) DecodeFromBytes(data []byte) error {
if len(data) < subTLVHdrLen {
return malformedAttrListErr("decoding failed: Prefix SID TLV malformed")
}
s.Type = SubTLVType(data[0])
s.Length = binary.BigEndian.Uint16(data[1:3])
// 4th reserved byte
p := 4
s.SID = make([]byte, 16)
copy(s.SID, data[p:p+16])
p += 16
s.Flags = uint8(data[p])
p++
s.EndpointBehavior = binary.BigEndian.Uint16(data[p : p+2])
p += 2
// reserved byte
p++
if p+3 > len(data) {
// There is no Sub Sub TLVs detected, returning
return nil
}
stlvs := data[p:]
for len(stlvs) >= prefixSIDtlvHdrLen {
t := &SubSubTLV{}
_, err := t.DecodeFromBytes(stlvs)
if err != nil {
return err
}
var sstlv PrefixSIDTLVInterface
switch t.Type {
case 1:
sstlv = &SRv6SIDStructureSubSubTLV{}
default:
stlvs = stlvs[t.Len():]
continue
}
if err := sstlv.DecodeFromBytes(stlvs); err != nil {
return err
}
stlvs = stlvs[t.Len():]
s.SubSubTLVs = append(s.SubSubTLVs, sstlv)
}
return nil
}
func (s *SRv6InformationSubTLV) MarshalJSON() ([]byte, error) {
return json.Marshal(struct {
Type SubTLVType `json:"type"`
SRv6InformationSTLV
}{
s.Type,
*s.Extract(),
})
}
func (s *SRv6InformationSubTLV) String() string {
var buf bytes.Buffer
buf.WriteString(fmt.Sprintf("SID: %s ", net.IP(s.SID).To16().String()))
buf.WriteString(fmt.Sprintf("Flag: %d ", s.Flags))
buf.WriteString(fmt.Sprintf("Endpoint Behavior: %d ", s.EndpointBehavior))
for _, tlv := range s.SubSubTLVs {
buf.WriteString(fmt.Sprintf("%s ", tlv.String()))
}
return fmt.Sprintf("{SRv6 Information Sub TLV: %s}", buf.String())
}
func (s *SRv6InformationSubTLV) Extract() *SRv6InformationSTLV {
info := &SRv6InformationSTLV{
SID: s.SID,
Flags: s.Flags,
EndpointBehavior: s.EndpointBehavior,
SubSubTLVs: make([]PrefixSIDTLVInterface, 0),
}
info.SubSubTLVs = append(info.SubSubTLVs, s.SubSubTLVs...)
return info
}
const (
subSubTLVHdrLen = 3
)
type SubSubTLVType uint8
type SubSubTLV struct {
Type SubSubTLVType
Length uint16
}
func (s *SubSubTLV) Len() int {
return int(s.Length) + subSubTLVHdrLen
}
func (s *SubSubTLV) Serialize(value []byte) ([]byte, error) {
if len(value) != int(s.Length) {
return nil, malformedAttrListErr("serialization failed: Prefix SID TLV malformed")
}
// Extra byte is reserved
buf := make([]byte, subSubTLVHdrLen+len(value))
p := 0
buf[p] = byte(s.Type)
p++
binary.BigEndian.PutUint16(buf[p:p+2], uint16(s.Length))
p += 2
copy(buf[p:], value)
return buf, nil
}
func (s *SubSubTLV) DecodeFromBytes(data []byte) ([]byte, error) {
if len(data) < prefixSIDtlvHdrLen {
return nil, malformedAttrListErr("decoding failed: Prefix SID Sub Sub TLV malformed")
}
s.Type = SubSubTLVType(data[0])
s.Length = binary.BigEndian.Uint16(data[1:3])
if len(data) < s.Len() {
return nil, malformedAttrListErr("decoding failed: Prefix SID Sub Sub TLV malformed")
}
return data[prefixSIDtlvHdrLen:s.Len()], nil
}
// SRv6SIDStructureSubSubTLV defines a structure of SRv6 SID Structure Sub Sub TLV (type 1) object
// https://tools.ietf.org/html/draft-dawra-bess-srv6-services-02#section-2.1.2.1
type SRv6SIDStructureSubSubTLV struct {
SubSubTLV
LocalBlockLength uint8
LocatorNodeLength uint8
FunctionLength uint8
ArgumentLength uint8
TranspositionLength uint8
TranspositionOffset uint8
}
func (s *SRv6SIDStructureSubSubTLV) Len() int {
return int(s.Length) + subSubTLVHdrLen
}
func (s *SRv6SIDStructureSubSubTLV) Serialize() ([]byte, error) {
buf := make([]byte, s.Length)
p := 0
buf[p] = s.LocalBlockLength
p++
buf[p] = s.LocatorNodeLength
p++
buf[p] = s.FunctionLength
p++
buf[p] = s.ArgumentLength
p++
buf[p] = s.TranspositionLength
p++
buf[p] = s.TranspositionOffset
return s.SubSubTLV.Serialize(buf)
}
func (s *SRv6SIDStructureSubSubTLV) DecodeFromBytes(data []byte) error {
if len(data) < subSubTLVHdrLen {
return malformedAttrListErr("decoding failed: Prefix SID Sub Sub TLV malformed")
}
s.Type = SubSubTLVType(data[0])
s.Length = binary.BigEndian.Uint16(data[1:3])
s.LocalBlockLength = data[3]
s.LocatorNodeLength = data[4]
s.FunctionLength = data[5]
s.ArgumentLength = data[6]
s.TranspositionLength = data[7]
s.TranspositionOffset = data[8]
return nil
}
func (s *SRv6SIDStructureSubSubTLV) MarshalJSON() ([]byte, error) {
return json.Marshal(struct {
Type SubSubTLVType `json:"type"`
LocalBlockLength uint8 `json:"local_block_length"`
LocatorNodeLength uint8 `json:"locator_node_length"`
FunctionLength uint8 `json:"function_length"`
ArgumentLength uint8 `json:"argument_length"`
TranspositionLength uint8 `json:"transposition_length"`
TranspositionOffset uint8 `json:"transposition_offset"`
}{
Type: s.Type,
LocalBlockLength: s.LocalBlockLength,
LocatorNodeLength: s.LocatorNodeLength,
FunctionLength: s.FunctionLength,
ArgumentLength: s.ArgumentLength,
TranspositionLength: s.TranspositionLength,
TranspositionOffset: s.TranspositionOffset,
})
}
func (s *SRv6SIDStructureSubSubTLV) String() string {
return fmt.Sprintf("{SRv6 Structure Sub Sub TLV: [ Local Block Length: %d, Locator Node Length: %d, Function Length: %d, Argument Length: %d, Transposition Length: %d, Transposition Offset: %d] }",
s.LocalBlockLength,
s.LocatorNodeLength,
s.FunctionLength,
s.ArgumentLength,
s.TranspositionLength,
s.TranspositionOffset,
)
}
func NewPathAttributePrefixSID(psid *api.PrefixSID) (*PathAttributePrefixSID, error) {
t := BGP_ATTR_TYPE_PREFIX_SID
s := &PathAttributePrefixSID{
PathAttribute: PathAttribute{
Flags: PathAttrFlags[t],
Type: t,
},
TLVs: make([]PrefixSIDTLVInterface, 0),
}
for _, raw := range psid.Tlvs {
var tlv ptypes.DynamicAny
if err := ptypes.UnmarshalAny(raw, &tlv); err != nil {
return nil, err
}
switch v := tlv.Message.(type) {
case *api.SRv6L3ServiceTLV:
tlvLength, tlvs, err := UnmarshalSubTLVs(v.SubTlvs)
if err != nil {
return nil, err
}
o := &SRv6L3ServiceAttribute{
TLV: TLV{
Type: TLVType(5),
Length: tlvLength,
},
}
s.PathAttribute.Length += tlvLength
// Storing Sub TLVs in a Service TLV
o.SubTLVs = append(o.SubTLVs, tlvs...)
// Adding Service TLV to Path Attribute TLV slice.
s.TLVs = append(s.TLVs, o)
default:
return nil, fmt.Errorf("unknown or not implemented Prefix SID type: %+v", v)
}
}
// Final Path Attribute Length is 3 bytes of the header and 1 byte Reserved1
s.PathAttribute.Length += (3 + 1)
return s, nil
}
func UnmarshalSubTLVs(stlvs map[uint32]*api.SRv6TLV) (uint16, []PrefixSIDTLVInterface, error) {
p := make([]PrefixSIDTLVInterface, 0, len(stlvs))
l := uint16(0)
// v.SubTlvs is a map by sub tlv type and the value is a slice of sub tlvs of the specific type
for t, tlv := range stlvs {
switch t {
case 1:
// Sub TLV Type 1 is SRv6 Informational Sub TLV
for _, stlvRaw := range tlv.Tlv {
// Instantiating Information Sub TLV
info := &SRv6InformationSubTLV{
SubTLV: SubTLV{
Type: SubTLVType(1),
},
SubSubTLVs: make([]PrefixSIDTLVInterface, 0),
}
var raw ptypes.DynamicAny
if err := ptypes.UnmarshalAny(stlvRaw, &raw); err != nil {
return 0, nil, err
}
infoProto := raw.Message.(*api.SRv6InformationSubTLV)
info.SID = make([]byte, len(infoProto.Sid))
copy(info.SID, infoProto.Sid)
// TODO Once RFC is published add processing of flags
info.Flags = 0
info.EndpointBehavior = uint16(infoProto.EndpointBehavior)
var sstlvslength uint16
var sstlvs []PrefixSIDTLVInterface
if len(infoProto.SubSubTlvs) != 0 {
// Processing Sub Sub TLVs
var err error
sstlvslength, sstlvs, err = UnmarshalSubSubTLVs(infoProto.SubSubTlvs)
if err != nil {
return 0, nil, err
}
info.SubSubTLVs = append(info.SubSubTLVs, sstlvs...)
}
// SRv6 Information Sub TLV length consists 1 byte Resrved2, 16 bytes SID, 1 byte flags, 2 bytes Endpoint Behavior
// 1 byte Reserved3 and length of Sub Sub TLVs
info.SubTLV.Length = 1 + 16 + 1 + 2 + 1 + sstlvslength
// For total Srv6 Information Sub TLV length, adding 3 bytes of the Sub TLV header
l += info.SubTLV.Length + 4
p = append(p, info)
}
default:
return 0, nil, fmt.Errorf("unknown or not implemented Prefix SID Sub TLV type: %d", t)
}
}
return l, p, nil
}
func UnmarshalSubSubTLVs(stlvs map[uint32]*api.SRv6TLV) (uint16, []PrefixSIDTLVInterface, error) {
p := make([]PrefixSIDTLVInterface, 0)
l := uint16(0)
// v.SubTlvs is a map by sub tlv type and the value is a slice of sub tlvs of the specific type
for t, tlv := range stlvs {
switch t {
case 1:
// Sub Sub TLV Type 1 is SRv6 Structure Sub Sub TLV
for _, stlvRaw := range tlv.Tlv {
// Instantiating Information Sub TLV
structure := &SRv6SIDStructureSubSubTLV{
SubSubTLV: SubSubTLV{
Type: SubSubTLVType(1),
Length: 6,
},
}
var raw ptypes.DynamicAny
if err := ptypes.UnmarshalAny(stlvRaw, &raw); err != nil {
return 0, nil, err
}
structureProto := raw.Message.(*api.SRv6StructureSubSubTLV)
structure.LocalBlockLength = uint8(structureProto.LocalBlockLength)
structure.LocatorNodeLength = uint8(structureProto.LocalNodeLength)
structure.FunctionLength = uint8(structureProto.FunctionLength)
structure.ArgumentLength = uint8(structureProto.ArgumentLength)
structure.TranspositionLength = uint8(structureProto.TranspositionLength)
structure.TranspositionOffset = uint8(structureProto.TranspositionOffset)
// SRv6 Structure Sub Sub TLV length consists of header 3 bytes, 6 bytes of value
l += (3 + 6)
p = append(p, structure)
}
default:
return 0, nil, fmt.Errorf("unknown or not implemented Prefix SID Sub TLV type: %d", t)
}
}
return l, p, nil
}

View File

@@ -33,17 +33,18 @@ func ValidateUpdateMsg(m *BGPUpdate, rfs map[RouteFamily]BGPAddPathMode, isEBGP
//check specific path attribute
ok, err := ValidateAttribute(a, rfs, isEBGP, isConfed)
if !ok {
if err.(*MessageError).ErrorHandling == ERROR_HANDLING_SESSION_RESET {
msgErr := err.(*MessageError)
if msgErr.ErrorHandling == ERROR_HANDLING_SESSION_RESET {
return false, err
} else if err.(*MessageError).Stronger(strongestError) {
} else if msgErr.Stronger(strongestError) {
strongestError = err
}
}
} else if a.GetType() == BGP_ATTR_TYPE_MP_REACH_NLRI || a.GetType() == BGP_ATTR_TYPE_MP_UNREACH_NLRI {
eMsg := "the path attribute apears twice. Type : " + strconv.Itoa(int(a.GetType()))
eMsg := "the path attribute appears twice. Type : " + strconv.Itoa(int(a.GetType()))
return false, NewMessageError(eCode, eSubCodeAttrList, nil, eMsg)
} else {
eMsg := "the path attribute apears twice. Type : " + strconv.Itoa(int(a.GetType()))
eMsg := "the path attribute appears twice. Type : " + strconv.Itoa(int(a.GetType()))
e := NewMessageErrorWithErrorHandling(eCode, eSubCodeAttrList, nil, ERROR_HANDLING_ATTRIBUTE_DISCARD, nil, eMsg)
if e.(*MessageError).Stronger(strongestError) {
strongestError = e
@@ -159,6 +160,10 @@ func ValidateAttribute(a PathAttributeInterface, rfs map[RouteFamily]BGPAddPathM
}
isClassDorE := func(ip net.IP) bool {
if ip.To4() == nil {
// needs to verify ipv6 too?
return false
}
res := ip[0] & 0xe0
return res == 0xe0
}
@@ -197,7 +202,7 @@ func ValidateAttribute(a PathAttributeInterface, rfs map[RouteFamily]BGPAddPathM
for _, x := range p.Values {
found := false
for _, y := range uniq {
if x.String() == y.String() {
if x.Eq(y) {
found = true
break
}

View File

@@ -344,8 +344,21 @@ func (body *BMPStatisticsReport) ParseBody(msg *BMPMessage, data []byte) error {
s = &BMPStatsTLV64{BMPStatsTLV: tl}
case BMP_STAT_TYPE_PER_AFI_SAFI_ADJ_RIB_IN, BMP_STAT_TYPE_PER_AFI_SAFI_LOC_RIB:
s = &BMPStatsTLVPerAfiSafi64{BMPStatsTLV: tl}
default:
case BMP_STAT_TYPE_REJECTED, BMP_STAT_TYPE_DUPLICATE_PREFIX,
BMP_STAT_TYPE_DUPLICATE_WITHDRAW, BMP_STAT_TYPE_INV_UPDATE_DUE_TO_CLUSTER_LIST_LOOP,
BMP_STAT_TYPE_INV_UPDATE_DUE_TO_AS_PATH_LOOP, BMP_STAT_TYPE_INV_UPDATE_DUE_TO_ORIGINATOR_ID,
BMP_STAT_TYPE_INV_UPDATE_DUE_TO_AS_CONFED_LOOP, BMP_STAT_TYPE_WITHDRAW_UPDATE,
BMP_STAT_TYPE_WITHDRAW_PREFIX, BMP_STAT_TYPE_DUPLICATE_UPDATE:
s = &BMPStatsTLV32{BMPStatsTLV: tl}
default:
switch tl.Length {
case 4:
s = &BMPStatsTLV32{BMPStatsTLV: tl}
case 8:
s = &BMPStatsTLV64{BMPStatsTLV: tl}
default:
return fmt.Errorf("value length %d is not known for unknown stat type %d", tl.Length, tl.Type)
}
}
if err := s.ParseValue(data); err != nil {
return err
@@ -371,7 +384,7 @@ func (body *BMPStatisticsReport) Serialize() ([]byte, error) {
}
const (
BMP_PEER_DOWN_REASON_UNKNOWN = iota
BMP_peerDownByUnknownReason = iota
BMP_PEER_DOWN_REASON_LOCAL_BGP_NOTIFICATION
BMP_PEER_DOWN_REASON_LOCAL_NO_NOTIFICATION
BMP_PEER_DOWN_REASON_REMOTE_BGP_NOTIFICATION

View File

@@ -18,6 +18,7 @@ package mrt
import (
"bytes"
"encoding/binary"
"errors"
"fmt"
"math"
"net"
@@ -198,10 +199,11 @@ type Peer struct {
AS uint32
}
var errNotAllPeerBytesAvailable = errors.New("not all Peer bytes are available")
func (p *Peer) DecodeFromBytes(data []byte) ([]byte, error) {
notAllBytesAvail := fmt.Errorf("not all Peer bytes are available")
if len(data) < 5 {
return nil, notAllBytesAvail
return nil, errNotAllPeerBytesAvailable
}
p.Type = uint8(data[0])
p.BgpId = net.IP(data[1:5])
@@ -209,13 +211,13 @@ func (p *Peer) DecodeFromBytes(data []byte) ([]byte, error) {
if p.Type&1 > 0 {
if len(data) < 16 {
return nil, notAllBytesAvail
return nil, errNotAllPeerBytesAvailable
}
p.IpAddress = net.IP(data[:16])
data = data[16:]
} else {
if len(data) < 4 {
return nil, notAllBytesAvail
return nil, errNotAllPeerBytesAvailable
}
p.IpAddress = net.IP(data[:4])
data = data[4:]
@@ -223,13 +225,13 @@ func (p *Peer) DecodeFromBytes(data []byte) ([]byte, error) {
if p.Type&(1<<1) > 0 {
if len(data) < 4 {
return nil, notAllBytesAvail
return nil, errNotAllPeerBytesAvailable
}
p.AS = binary.BigEndian.Uint32(data[:4])
data = data[4:]
} else {
if len(data) < 2 {
return nil, notAllBytesAvail
return nil, errNotAllPeerBytesAvailable
}
p.AS = uint32(binary.BigEndian.Uint16(data[:2]))
data = data[2:]
@@ -291,22 +293,23 @@ type PeerIndexTable struct {
Peers []*Peer
}
var errNnotAllPeerIndexBytesAvailable = errors.New("not all PeerIndexTable bytes are available")
func (t *PeerIndexTable) DecodeFromBytes(data []byte) error {
notAllBytesAvail := fmt.Errorf("not all PeerIndexTable bytes are available")
if len(data) < 6 {
return notAllBytesAvail
return errNnotAllPeerIndexBytesAvailable
}
t.CollectorBgpId = net.IP(data[:4])
viewLen := binary.BigEndian.Uint16(data[4:6])
if len(data) < 6+int(viewLen) {
return notAllBytesAvail
return errNnotAllPeerIndexBytesAvailable
}
t.ViewName = string(data[6 : 6+viewLen])
data = data[6+viewLen:]
if len(data) < 2 {
return notAllBytesAvail
return errNnotAllPeerIndexBytesAvailable
}
peerNum := binary.BigEndian.Uint16(data[:2])
data = data[2:]
@@ -360,10 +363,11 @@ type RibEntry struct {
isAddPath bool
}
var errNotAllRibEntryBytesAvailable = errors.New("not all RibEntry bytes are available")
func (e *RibEntry) DecodeFromBytes(data []byte) ([]byte, error) {
notAllBytesAvail := fmt.Errorf("not all RibEntry bytes are available")
if len(data) < 8 {
return nil, notAllBytesAvail
return nil, errNotAllRibEntryBytesAvailable
}
e.PeerIndex = binary.BigEndian.Uint16(data[:2])
e.OriginatedTime = binary.BigEndian.Uint32(data[2:6])
@@ -386,7 +390,7 @@ func (e *RibEntry) DecodeFromBytes(data []byte) ([]byte, error) {
}
attrLen -= uint16(p.Len())
if len(data) < p.Len() {
return nil, notAllBytesAvail
return nil, errNotAllRibEntryBytesAvailable
}
data = data[p.Len():]
e.PathAttributes = append(e.PathAttributes, p)
@@ -417,13 +421,13 @@ func (e *RibEntry) Serialize() ([]byte, error) {
}
var buf []byte
if e.isAddPath {
buf = make([]byte, 12)
buf = make([]byte, 12, 12+len(pbuf))
binary.BigEndian.PutUint16(buf, e.PeerIndex)
binary.BigEndian.PutUint32(buf[2:], e.OriginatedTime)
binary.BigEndian.PutUint32(buf[6:], e.PathIdentifier)
binary.BigEndian.PutUint16(buf[10:], uint16(totalLen))
} else {
buf = make([]byte, 8)
buf = make([]byte, 8, 8+len(pbuf))
binary.BigEndian.PutUint16(buf, e.PeerIndex)
binary.BigEndian.PutUint32(buf[2:], e.OriginatedTime)
binary.BigEndian.PutUint16(buf[6:], uint16(totalLen))
@@ -461,7 +465,7 @@ type Rib struct {
func (u *Rib) DecodeFromBytes(data []byte) error {
if len(data) < 4 {
return fmt.Errorf("Not all RibIpv4Unicast message bytes available")
return fmt.Errorf("not all RibIpv4Unicast message bytes available")
}
u.SequenceNumber = binary.BigEndian.Uint32(data[:4])
data = data[4:]
@@ -504,9 +508,9 @@ func (u *Rib) Serialize() ([]byte, error) {
switch rf {
case bgp.RF_IPv4_UC, bgp.RF_IPv4_MC, bgp.RF_IPv6_UC, bgp.RF_IPv6_MC:
default:
bbuf := make([]byte, 2)
binary.BigEndian.PutUint16(bbuf, u.Prefix.AFI())
buf = append(buf, bbuf...)
var bbuf [2]byte
binary.BigEndian.PutUint16(bbuf[:], u.Prefix.AFI())
buf = append(buf, bbuf[:]...)
buf = append(buf, u.Prefix.SAFI())
}
bbuf, err := u.Prefix.Serialize()
@@ -665,9 +669,9 @@ type BGP4MPHeader struct {
func (m *BGP4MPHeader) decodeFromBytes(data []byte) ([]byte, error) {
if m.isAS4 && len(data) < 8 {
return nil, fmt.Errorf("Not all BGP4MPMessageAS4 bytes available")
return nil, errors.New("not all BGP4MPMessageAS4 bytes available")
} else if !m.isAS4 && len(data) < 4 {
return nil, fmt.Errorf("Not all BGP4MPMessageAS bytes available")
return nil, errors.New("not all BGP4MPMessageAS bytes available")
}
if m.isAS4 {
@@ -735,7 +739,7 @@ func newBGP4MPHeader(peeras, localas uint32, intfindex uint16, peerip, localip s
if paddr != nil && laddr != nil {
af = bgp.AFI_IP6
} else {
return nil, fmt.Errorf("Peer IP Address and Local IP Address must have the same address family")
return nil, fmt.Errorf("peer IP Address and Local IP Address must have the same address family")
}
}
return &BGP4MPHeader{
@@ -761,7 +765,7 @@ func (m *BGP4MPStateChange) DecodeFromBytes(data []byte) error {
return err
}
if len(rest) < 4 {
return fmt.Errorf("Not all BGP4MPStateChange bytes available")
return fmt.Errorf("not all BGP4MPStateChange bytes available")
}
m.OldState = BGPState(binary.BigEndian.Uint16(rest[:2]))
m.NewState = BGPState(binary.BigEndian.Uint16(rest[2:4]))
@@ -804,7 +808,7 @@ func (m *BGP4MPMessage) DecodeFromBytes(data []byte) error {
}
if len(rest) < bgp.BGP_HEADER_LENGTH {
return fmt.Errorf("Not all BGP4MPMessageAS4 bytes available")
return fmt.Errorf("not all BGP4MPMessageAS4 bytes available")
}
msg, err := bgp.ParseBGPMessage(rest)
@@ -903,7 +907,7 @@ func SplitMrt(data []byte, atEOF bool) (advance int, token []byte, err error) {
func ParseMRTBody(h *MRTHeader, data []byte) (*MRTMessage, error) {
if len(data) < int(h.Len) {
return nil, fmt.Errorf("Not all MRT message bytes available. expected: %d, actual: %d", int(h.Len), len(data))
return nil, fmt.Errorf("not all MRT message bytes available. expected: %d, actual: %d", int(h.Len), len(data))
}
msg := &MRTMessage{Header: *h}
switch h.Type {
@@ -940,7 +944,7 @@ func ParseMRTBody(h *MRTHeader, data []byte) (*MRTMessage, error) {
case RIB_GENERIC_ADDPATH:
isAddPath = true
default:
return nil, fmt.Errorf("unsupported table dumpv2 subtype: %v\n", subType)
return nil, fmt.Errorf("unsupported table dumpv2 subtype: %v", subType)
}
if msg.Body == nil {
@@ -993,10 +997,10 @@ func ParseMRTBody(h *MRTHeader, data []byte) (*MRTMessage, error) {
isAddPath: true,
}
default:
return nil, fmt.Errorf("unsupported bgp4mp subtype: %v\n", subType)
return nil, fmt.Errorf("unsupported bgp4mp subtype: %v", subType)
}
default:
return nil, fmt.Errorf("unsupported type: %v\n", h.Type)
return nil, fmt.Errorf("unsupported type: %v", h.Type)
}
err := msg.Body.DecodeFromBytes(data)
if err != nil {

View File

@@ -355,7 +355,7 @@ func SplitRTR(data []byte, atEOF bool) (advance int, token []byte, err error) {
totalLen := binary.BigEndian.Uint32(data[4:8])
if totalLen < RTR_MIN_LEN {
return 0, nil, fmt.Errorf("Invalid length: %d", totalLen)
return 0, nil, fmt.Errorf("invalid length: %d", totalLen)
}
if uint32(len(data)) < totalLen {
return 0, nil, nil
@@ -385,7 +385,7 @@ func ParseRTR(data []byte) (RTRMessage, error) {
case RTR_ERROR_REPORT:
msg = &RTRErrorReport{}
default:
return nil, fmt.Errorf("unknown RTR message type %d:", data[1])
return nil, fmt.Errorf("unknown RTR message type %d", data[1])
}
err := msg.DecodeFromBytes(data)
return msg, err

View File

@@ -16,11 +16,13 @@
package server
import (
"context"
"fmt"
"net"
"strconv"
"time"
api "github.com/osrg/gobgp/api"
"github.com/osrg/gobgp/internal/pkg/config"
"github.com/osrg/gobgp/internal/pkg/table"
"github.com/osrg/gobgp/pkg/packet/bgp"
@@ -113,25 +115,25 @@ func (b *bmpClient) loop() {
}
if func() bool {
ops := []WatchOption{WatchPeerState(true)}
ops := []watchOption{watchPeerState(true)}
if b.c.RouteMonitoringPolicy == config.BMP_ROUTE_MONITORING_POLICY_TYPE_BOTH {
log.WithFields(
log.Fields{"Topic": "bmp"},
).Warn("both option for route-monitoring-policy is obsoleted")
}
if b.c.RouteMonitoringPolicy == config.BMP_ROUTE_MONITORING_POLICY_TYPE_PRE_POLICY || b.c.RouteMonitoringPolicy == config.BMP_ROUTE_MONITORING_POLICY_TYPE_ALL {
ops = append(ops, WatchUpdate(true))
ops = append(ops, watchUpdate(true))
}
if b.c.RouteMonitoringPolicy == config.BMP_ROUTE_MONITORING_POLICY_TYPE_POST_POLICY || b.c.RouteMonitoringPolicy == config.BMP_ROUTE_MONITORING_POLICY_TYPE_ALL {
ops = append(ops, WatchPostUpdate(true))
ops = append(ops, watchPostUpdate(true))
}
if b.c.RouteMonitoringPolicy == config.BMP_ROUTE_MONITORING_POLICY_TYPE_LOCAL_RIB || b.c.RouteMonitoringPolicy == config.BMP_ROUTE_MONITORING_POLICY_TYPE_ALL {
ops = append(ops, WatchBestPath(true))
ops = append(ops, watchBestPath(true))
}
if b.c.RouteMirroringEnabled {
ops = append(ops, WatchMessage(false))
ops = append(ops, watchMessage(false))
}
w := b.s.Watch(ops...)
w := b.s.watch(ops...)
defer w.Stop()
var tickerCh <-chan time.Time
@@ -152,7 +154,12 @@ func (b *bmpClient) loop() {
return err
}
if err := write(bmp.NewBMPInitiation([]bmp.BMPInfoTLVInterface{})); err != nil {
tlv := []bmp.BMPInfoTLVInterface{
bmp.NewBMPInfoTLVString(bmp.BMP_INIT_TLV_TYPE_SYS_NAME, b.c.SysName),
bmp.NewBMPInfoTLVString(bmp.BMP_INIT_TLV_TYPE_SYS_DESCR, b.c.SysDescr),
}
if err := write(bmp.NewBMPInitiation(tlv)); err != nil {
return false
}
@@ -160,7 +167,7 @@ func (b *bmpClient) loop() {
select {
case ev := <-w.Event():
switch msg := ev.(type) {
case *WatchEventUpdate:
case *watchEventUpdate:
info := &table.PeerInfo{
Address: msg.PeerAddress,
AS: msg.PeerAS,
@@ -180,17 +187,15 @@ func (b *bmpClient) loop() {
for _, path := range pathList {
for _, u := range table.CreateUpdateMsgFromPaths([]*table.Path{path}) {
payload, _ := u.Serialize()
if err := write(bmpPeerRoute(bmp.BMP_PEER_TYPE_GLOBAL, msg.PostPolicy, 0, true, info, msg.Timestamp.Unix(), payload)); err != nil {
if err := write(bmpPeerRoute(bmp.BMP_PEER_TYPE_GLOBAL, msg.PostPolicy, 0, true, info, path.GetTimestamp().Unix(), payload)); err != nil {
return false
}
}
}
} else {
if err := write(bmpPeerRoute(bmp.BMP_PEER_TYPE_GLOBAL, msg.PostPolicy, 0, msg.FourBytesAs, info, msg.Timestamp.Unix(), msg.Payload)); err != nil {
return false
}
} else if err := write(bmpPeerRoute(bmp.BMP_PEER_TYPE_GLOBAL, msg.PostPolicy, 0, msg.FourBytesAs, info, msg.Timestamp.Unix(), msg.Payload)); err != nil {
return false
}
case *WatchEventBestPath:
case *watchEventBestPath:
info := &table.PeerInfo{
Address: net.ParseIP("0.0.0.0").To4(),
AS: b.s.bgpConfig.Global.Config.As,
@@ -204,7 +209,7 @@ func (b *bmpClient) loop() {
return false
}
}
case *WatchEventPeerState:
case *watchEventPeerState:
if msg.State == bgp.BGP_FSM_ESTABLISHED {
if err := write(bmpPeerUp(msg, bmp.BMP_PEER_TYPE_GLOBAL, false, 0)); err != nil {
return false
@@ -214,7 +219,7 @@ func (b *bmpClient) loop() {
return false
}
}
case *WatchEventMessage:
case *watchEventMessage:
info := &table.PeerInfo{
Address: msg.PeerAddress,
AS: msg.PeerAS,
@@ -225,14 +230,15 @@ func (b *bmpClient) loop() {
}
}
case <-tickerCh:
neighborList := b.s.getNeighbor("", true)
for _, n := range neighborList {
if n.State.SessionState != config.SESSION_STATE_ESTABLISHED {
continue
}
if err := write(bmpPeerStats(bmp.BMP_PEER_TYPE_GLOBAL, 0, 0, n)); err != nil {
return false
}
var err error
b.s.ListPeer(context.Background(), &api.ListPeerRequest{EnableAdvertised: true},
func(peer *api.Peer) {
if err == nil && peer.State.SessionState == api.PeerState_ESTABLISHED {
err = write(bmpPeerStats(bmp.BMP_PEER_TYPE_GLOBAL, 0, time.Now().Unix(), peer))
}
})
if err != nil {
return false
}
case <-b.dead:
term := bmp.NewBMPTermination([]bmp.BMPTermTLVInterface{
@@ -259,7 +265,7 @@ type bmpClient struct {
ribout ribout
}
func bmpPeerUp(ev *WatchEventPeerState, t uint8, policy bool, pd uint64) *bmp.BMPMessage {
func bmpPeerUp(ev *watchEventPeerState, t uint8, policy bool, pd uint64) *bmp.BMPMessage {
var flags uint8 = 0
if policy {
flags |= bmp.BMP_PEER_FLAG_POST_POLICY
@@ -268,13 +274,27 @@ func bmpPeerUp(ev *WatchEventPeerState, t uint8, policy bool, pd uint64) *bmp.BM
return bmp.NewBMPPeerUpNotification(*ph, ev.LocalAddress.String(), ev.LocalPort, ev.PeerPort, ev.SentOpen, ev.RecvOpen)
}
func bmpPeerDown(ev *WatchEventPeerState, t uint8, policy bool, pd uint64) *bmp.BMPMessage {
func bmpPeerDown(ev *watchEventPeerState, t uint8, policy bool, pd uint64) *bmp.BMPMessage {
var flags uint8 = 0
if policy {
flags |= bmp.BMP_PEER_FLAG_POST_POLICY
}
ph := bmp.NewBMPPeerHeader(t, flags, pd, ev.PeerAddress.String(), ev.PeerAS, ev.PeerID.String(), float64(ev.Timestamp.Unix()))
return bmp.NewBMPPeerDownNotification(*ph, uint8(ev.StateReason.PeerDownReason), ev.StateReason.BGPNotification, ev.StateReason.Data)
reasonCode := bmp.BMP_peerDownByUnknownReason
switch ev.StateReason.Type {
case fsmDying, fsmInvalidMsg, fsmNotificationSent, fsmHoldTimerExpired, fsmIdleTimerExpired, fsmRestartTimerExpired:
reasonCode = bmp.BMP_PEER_DOWN_REASON_LOCAL_BGP_NOTIFICATION
case fsmAdminDown:
reasonCode = bmp.BMP_PEER_DOWN_REASON_LOCAL_NO_NOTIFICATION
case fsmNotificationRecv, fsmGracefulRestart, fsmHardReset:
reasonCode = bmp.BMP_PEER_DOWN_REASON_REMOTE_BGP_NOTIFICATION
case fsmReadFailed, fsmWriteFailed:
reasonCode = bmp.BMP_PEER_DOWN_REASON_REMOTE_NO_NOTIFICATION
case fsmDeConfigured:
reasonCode = bmp.BMP_PEER_DOWN_REASON_PEER_DE_CONFIGURED
}
return bmp.NewBMPPeerDownNotification(*ph, uint8(reasonCode), ev.StateReason.BGPNotification, ev.StateReason.Data)
}
func bmpPeerRoute(t uint8, policy bool, pd uint64, fourBytesAs bool, peeri *table.PeerInfo, timestamp int64, payload []byte) *bmp.BMPMessage {
@@ -292,16 +312,22 @@ func bmpPeerRoute(t uint8, policy bool, pd uint64, fourBytesAs bool, peeri *tabl
return m
}
func bmpPeerStats(peerType uint8, peerDist uint64, timestamp int64, neighConf *config.Neighbor) *bmp.BMPMessage {
func bmpPeerStats(peerType uint8, peerDist uint64, timestamp int64, peer *api.Peer) *bmp.BMPMessage {
var peerFlags uint8 = 0
ph := bmp.NewBMPPeerHeader(peerType, peerFlags, peerDist, neighConf.State.NeighborAddress, neighConf.State.PeerAs, neighConf.State.RemoteRouterId, float64(timestamp))
ph := bmp.NewBMPPeerHeader(peerType, peerFlags, peerDist, peer.State.NeighborAddress, peer.State.PeerAs, peer.State.RouterId, float64(timestamp))
received := uint64(0)
accepted := uint64(0)
for _, a := range peer.AfiSafis {
received += a.State.Received
accepted += a.State.Accepted
}
return bmp.NewBMPStatisticsReport(
*ph,
[]bmp.BMPStatsTLVInterface{
bmp.NewBMPStatsTLV64(bmp.BMP_STAT_TYPE_ADJ_RIB_IN, uint64(neighConf.State.AdjTable.Accepted)),
bmp.NewBMPStatsTLV64(bmp.BMP_STAT_TYPE_LOC_RIB, uint64(neighConf.State.AdjTable.Advertised+neighConf.State.AdjTable.Filtered)),
bmp.NewBMPStatsTLV32(bmp.BMP_STAT_TYPE_WITHDRAW_UPDATE, neighConf.State.Messages.Received.WithdrawUpdate),
bmp.NewBMPStatsTLV32(bmp.BMP_STAT_TYPE_WITHDRAW_PREFIX, neighConf.State.Messages.Received.WithdrawPrefix),
bmp.NewBMPStatsTLV64(bmp.BMP_STAT_TYPE_ADJ_RIB_IN, received),
bmp.NewBMPStatsTLV64(bmp.BMP_STAT_TYPE_LOC_RIB, accepted),
bmp.NewBMPStatsTLV32(bmp.BMP_STAT_TYPE_WITHDRAW_UPDATE, uint32(peer.State.Messages.Received.WithdrawUpdate)),
bmp.NewBMPStatsTLV32(bmp.BMP_STAT_TYPE_WITHDRAW_PREFIX, uint32(peer.State.Messages.Received.WithdrawPrefix)),
},
)
}

View File

@@ -1,222 +0,0 @@
// Copyright (C) 2016 Nippon Telegraph and Telephone Corporation.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
// implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package server
import (
"fmt"
"time"
"github.com/influxdata/influxdb/client/v2"
"github.com/osrg/gobgp/internal/pkg/table"
"github.com/osrg/gobgp/pkg/packet/bgp"
log "github.com/sirupsen/logrus"
)
type Collector struct {
s *BgpServer
url string
dbName string
interval uint64
client client.Client
}
const (
MEATUREMENT_UPDATE = "update"
MEATUREMENT_PEER = "peer"
MEATUREMENT_TABLE = "table"
)
func (c *Collector) writePoints(points []*client.Point) error {
bp, _ := client.NewBatchPoints(client.BatchPointsConfig{
Database: c.dbName,
Precision: "ms",
})
bp.AddPoints(points)
return c.client.Write(bp)
}
func (c *Collector) writePeer(msg *WatchEventPeerState) error {
var state string
switch msg.State {
case bgp.BGP_FSM_ESTABLISHED:
state = "Established"
case bgp.BGP_FSM_IDLE:
state = "Idle"
default:
return fmt.Errorf("unexpected fsm state %v", msg.State)
}
tags := map[string]string{
"PeerAddress": msg.PeerAddress.String(),
"PeerAS": fmt.Sprintf("%v", msg.PeerAS),
"State": state,
}
fields := map[string]interface{}{
"PeerID": msg.PeerID.String(),
}
pt, err := client.NewPoint(MEATUREMENT_PEER, tags, fields, msg.Timestamp)
if err != nil {
return err
}
return c.writePoints([]*client.Point{pt})
}
func path2data(path *table.Path) (map[string]interface{}, map[string]string) {
fields := map[string]interface{}{
"RouterID": path.GetSource().ID,
}
if asPath := path.GetAsPath(); asPath != nil {
fields["ASPath"] = asPath.String()
}
if origin, err := path.GetOrigin(); err == nil {
typ := "-"
switch origin {
case bgp.BGP_ORIGIN_ATTR_TYPE_IGP:
typ = "i"
case bgp.BGP_ORIGIN_ATTR_TYPE_EGP:
typ = "e"
case bgp.BGP_ORIGIN_ATTR_TYPE_INCOMPLETE:
typ = "?"
}
fields["Origin"] = typ
}
if med, err := path.GetMed(); err == nil {
fields["Med"] = med
}
tags := map[string]string{
"PeerAddress": path.GetSource().Address.String(),
"PeerAS": fmt.Sprintf("%v", path.GetSource().AS),
"Timestamp": path.GetTimestamp().String(),
}
if nexthop := path.GetNexthop(); len(nexthop) > 0 {
fields["NextHop"] = nexthop.String()
}
if originAS := path.GetSourceAs(); originAS != 0 {
fields["OriginAS"] = fmt.Sprintf("%v", originAS)
}
if err := bgp.FlatUpdate(tags, path.GetNlri().Flat()); err != nil {
log.WithFields(log.Fields{"Type": "collector", "Error": err}).Error("NLRI FlatUpdate failed")
}
for _, p := range path.GetPathAttrs() {
if err := bgp.FlatUpdate(tags, p.Flat()); err != nil {
log.WithFields(log.Fields{"Type": "collector", "Error": err}).Error("PathAttr FlatUpdate failed")
}
}
return fields, tags
}
func (c *Collector) writeUpdate(msg *WatchEventUpdate) error {
if len(msg.PathList) == 0 {
// EOR
return nil
}
now := time.Now()
points := make([]*client.Point, 0, len(msg.PathList))
for _, path := range msg.PathList {
fields, tags := path2data(path)
tags["Withdraw"] = fmt.Sprintf("%v", path.IsWithdraw)
pt, err := client.NewPoint(MEATUREMENT_UPDATE, tags, fields, now)
if err != nil {
return fmt.Errorf("failed to write update, %v", err)
}
points = append(points, pt)
}
return c.writePoints(points)
}
func (c *Collector) writeTable(msg *WatchEventAdjIn) error {
now := time.Now()
points := make([]*client.Point, 0, len(msg.PathList))
for _, path := range msg.PathList {
fields, tags := path2data(path)
pt, err := client.NewPoint(MEATUREMENT_TABLE, tags, fields, now)
if err != nil {
return fmt.Errorf("failed to write table, %v", err)
}
points = append(points, pt)
}
return c.writePoints(points)
}
func (c *Collector) loop() {
w := c.s.Watch(WatchPeerState(true), WatchUpdate(false))
defer w.Stop()
ticker := func() *time.Ticker {
if c.interval == 0 {
return &time.Ticker{}
}
return time.NewTicker(time.Second * time.Duration(c.interval))
}()
for {
select {
case <-ticker.C:
w.Generate(WATCH_EVENT_TYPE_PRE_UPDATE)
case ev := <-w.Event():
switch msg := ev.(type) {
case *WatchEventUpdate:
if err := c.writeUpdate(msg); err != nil {
log.WithFields(log.Fields{"Type": "collector", "Error": err}).Error("Failed to write update event message")
}
case *WatchEventPeerState:
if err := c.writePeer(msg); err != nil {
log.WithFields(log.Fields{"Type": "collector", "Error": err}).Error("Failed to write state changed event message")
}
case *WatchEventAdjIn:
if err := c.writeTable(msg); err != nil {
log.WithFields(log.Fields{"Type": "collector", "Error": err}).Error("Failed to write Adj-In event message")
}
}
}
}
}
func NewCollector(s *BgpServer, url, dbName string, interval uint64) (*Collector, error) {
c, err := client.NewHTTPClient(client.HTTPConfig{
Addr: url,
})
if err != nil {
return nil, err
}
_, _, err = c.Ping(0)
if err != nil {
log.Error("can not connect to InfluxDB")
log.WithFields(log.Fields{"Type": "collector", "Error": err}).Error("Failed to connect to InfluxDB")
return nil, err
}
q := client.NewQuery("CREATE DATABASE "+dbName, "", "")
if response, err := c.Query(q); err != nil || response.Error() != nil {
log.WithFields(log.Fields{"Type": "collector", "Error": err}).Errorf("Failed to create database:%s", dbName)
return nil, err
}
collector := &Collector{
s: s,
url: url,
dbName: dbName,
interval: interval,
client: c,
}
go collector.loop()
return collector, nil
}

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -30,8 +30,8 @@ import (
)
const (
MIN_ROTATION_INTERVAL = 60
MIN_DUMP_INTERVAL = 60
minRotationInterval = 60
minDumpInterval = 60
)
type mrtWriter struct {
@@ -48,16 +48,16 @@ func (m *mrtWriter) Stop() {
}
func (m *mrtWriter) loop() error {
ops := []WatchOption{}
ops := []watchOption{}
switch m.c.DumpType {
case config.MRT_TYPE_UPDATES:
ops = append(ops, WatchUpdate(false))
ops = append(ops, watchUpdate(false))
case config.MRT_TYPE_TABLE:
if len(m.c.TableName) > 0 {
ops = append(ops, WatchTableName(m.c.TableName))
ops = append(ops, watchTableName(m.c.TableName))
}
}
w := m.s.Watch(ops...)
w := m.s.watch(ops...)
rotator := func() *time.Ticker {
if m.rotationInterval == 0 {
return &time.Ticker{}
@@ -85,10 +85,10 @@ func (m *mrtWriter) loop() error {
}()
for {
serialize := func(ev WatchEvent) []*mrt.MRTMessage {
serialize := func(ev watchEvent) []*mrt.MRTMessage {
msg := make([]*mrt.MRTMessage, 0, 1)
switch e := ev.(type) {
case *WatchEventUpdate:
case *watchEventUpdate:
if e.Init {
return nil
}
@@ -113,7 +113,7 @@ func (m *mrtWriter) loop() error {
} else {
msg = append(msg, bm)
}
case *WatchEventTable:
case *watchEventTable:
t := uint32(time.Now().Unix())
peers := make([]*mrt.Peer, 1, len(e.Neighbor)+1)
@@ -125,7 +125,7 @@ func (m *mrtWriter) loop() error {
neighborMap[pconf.State.NeighborAddress] = pconf
}
if bm, err := mrt.NewMRTMessage(t, mrt.TABLE_DUMPv2, mrt.PEER_INDEX_TABLE, mrt.NewPeerIndexTable(e.RouterId, "", peers)); err != nil {
if bm, err := mrt.NewMRTMessage(t, mrt.TABLE_DUMPv2, mrt.PEER_INDEX_TABLE, mrt.NewPeerIndexTable(e.RouterID, "", peers)); err != nil {
log.WithFields(log.Fields{
"Topic": "mrt",
"Data": e,
@@ -137,12 +137,12 @@ func (m *mrtWriter) loop() error {
}
idx := func(p *table.Path) uint16 {
for i, pconf := range e.Neighbor {
if p.GetSource().Address.String() == pconf.State.NeighborAddress {
for i, peer := range peers {
if peer.IpAddress.String() == p.GetSource().Address.String() {
return uint16(i)
}
}
return uint16(len(e.Neighbor))
return uint16(len(peers))
}
subtype := func(p *table.Path, isAddPath bool) mrt.MRTSubTypeTableDumpv2 {
@@ -205,8 +205,8 @@ func (m *mrtWriter) loop() error {
return msg
}
drain := func(ev WatchEvent) {
events := make([]WatchEvent, 0, 1+len(w.Event()))
drain := func(ev watchEvent) {
events := make([]watchEvent, 0, 1+len(w.Event()))
if ev != nil {
events = append(events, ev)
}
@@ -274,23 +274,23 @@ func (m *mrtWriter) loop() error {
if m.c.DumpType == config.MRT_TYPE_UPDATES {
rotate()
} else {
w.Generate(WATCH_EVENT_TYPE_TABLE)
w.Generate(watchEventTypeTable)
}
case <-dump.C:
w.Generate(WATCH_EVENT_TYPE_TABLE)
w.Generate(watchEventTypeTable)
}
}
}
func mrtFileOpen(filename string, interval uint64) (*os.File, error) {
func mrtFileOpen(filename string, rInterval uint64) (*os.File, error) {
realname := filename
if interval != 0 {
if rInterval != 0 {
realname = time.Now().Format(filename)
}
log.WithFields(log.Fields{
"Topic": "mrt",
"Filename": realname,
"Dump Interval": interval,
"Topic": "mrt",
"Filename": realname,
"RotationInterval": rInterval,
}).Debug("Setting new MRT destination file")
i := len(realname)
@@ -354,21 +354,21 @@ func (m *mrtManager) enable(c *config.MrtConfig) error {
dInterval := c.DumpInterval
setRotationMin := func() {
if rInterval < MIN_ROTATION_INTERVAL {
if rInterval < minRotationInterval {
log.WithFields(log.Fields{
"Topic": "MRT",
}).Infof("minimum mrt rotation interval is %d seconds", MIN_ROTATION_INTERVAL)
rInterval = MIN_ROTATION_INTERVAL
}).Infof("minimum mrt rotation interval is %d seconds", minRotationInterval)
rInterval = minRotationInterval
}
}
if c.DumpType == config.MRT_TYPE_TABLE {
if rInterval == 0 {
if dInterval < MIN_DUMP_INTERVAL {
if dInterval < minDumpInterval {
log.WithFields(log.Fields{
"Topic": "MRT",
}).Infof("minimum mrt dump interval is %d seconds", MIN_DUMP_INTERVAL)
dInterval = MIN_DUMP_INTERVAL
}).Infof("minimum mrt dump interval is %d seconds", minDumpInterval)
dInterval = minDumpInterval
}
} else if dInterval == 0 {
setRotationMin()

View File

@@ -24,42 +24,40 @@ import (
"github.com/osrg/gobgp/internal/pkg/table"
"github.com/osrg/gobgp/pkg/packet/bgp"
"github.com/eapache/channels"
log "github.com/sirupsen/logrus"
)
const (
FLOP_THRESHOLD = time.Second * 30
MIN_CONNECT_RETRY = 10
flopThreshold = time.Second * 30
)
type PeerGroup struct {
type peerGroup struct {
Conf *config.PeerGroup
members map[string]config.Neighbor
dynamicNeighbors map[string]*config.DynamicNeighbor
}
func NewPeerGroup(c *config.PeerGroup) *PeerGroup {
return &PeerGroup{
func newPeerGroup(c *config.PeerGroup) *peerGroup {
return &peerGroup{
Conf: c,
members: make(map[string]config.Neighbor),
dynamicNeighbors: make(map[string]*config.DynamicNeighbor),
}
}
func (pg *PeerGroup) AddMember(c config.Neighbor) {
func (pg *peerGroup) AddMember(c config.Neighbor) {
pg.members[c.State.NeighborAddress] = c
}
func (pg *PeerGroup) DeleteMember(c config.Neighbor) {
func (pg *peerGroup) DeleteMember(c config.Neighbor) {
delete(pg.members, c.State.NeighborAddress)
}
func (pg *PeerGroup) AddDynamicNeighbor(c *config.DynamicNeighbor) {
func (pg *peerGroup) AddDynamicNeighbor(c *config.DynamicNeighbor) {
pg.dynamicNeighbors[c.Config.Prefix] = c
}
func newDynamicPeer(g *config.Global, neighborAddress string, pg *config.PeerGroup, loc *table.TableManager, policy *table.RoutingPolicy) *Peer {
func newDynamicPeer(g *config.Global, neighborAddress string, pg *config.PeerGroup, loc *table.TableManager, policy *table.RoutingPolicy) *peer {
conf := config.Neighbor{
Config: config.NeighborConfig{
PeerGroup: pg.Config.PeerGroupName,
@@ -87,30 +85,28 @@ func newDynamicPeer(g *config.Global, neighborAddress string, pg *config.PeerGro
}).Debugf("Can't set default config: %s", err)
return nil
}
peer := NewPeer(g, &conf, loc, policy)
peer := newPeer(g, &conf, loc, policy)
peer.fsm.lock.Lock()
peer.fsm.state = bgp.BGP_FSM_ACTIVE
peer.fsm.lock.Unlock()
return peer
}
type Peer struct {
type peer struct {
tableId string
fsm *FSM
fsm *fsm
adjRibIn *table.AdjRib
outgoing *channels.InfiniteChannel
policy *table.RoutingPolicy
localRib *table.TableManager
prefixLimitWarned map[bgp.RouteFamily]bool
llgrEndChs []chan struct{}
}
func NewPeer(g *config.Global, conf *config.Neighbor, loc *table.TableManager, policy *table.RoutingPolicy) *Peer {
peer := &Peer{
outgoing: channels.NewInfiniteChannel(),
func newPeer(g *config.Global, conf *config.Neighbor, loc *table.TableManager, policy *table.RoutingPolicy) *peer {
peer := &peer{
localRib: loc,
policy: policy,
fsm: NewFSM(g, conf, policy),
fsm: newFSM(g, conf),
prefixLimitWarned: make(map[bgp.RouteFamily]bool),
}
if peer.isRouteServerClient() {
@@ -123,45 +119,53 @@ func NewPeer(g *config.Global, conf *config.Neighbor, loc *table.TableManager, p
return peer
}
func (peer *Peer) AS() uint32 {
func (peer *peer) AS() uint32 {
peer.fsm.lock.RLock()
defer peer.fsm.lock.RUnlock()
return peer.fsm.pConf.State.PeerAs
}
func (peer *Peer) ID() string {
func (peer *peer) ID() string {
peer.fsm.lock.RLock()
defer peer.fsm.lock.RUnlock()
return peer.fsm.pConf.State.NeighborAddress
}
func (peer *Peer) TableID() string {
func (peer *peer) TableID() string {
return peer.tableId
}
func (peer *Peer) isIBGPPeer() bool {
return peer.fsm.pConf.State.PeerAs == peer.fsm.gConf.Config.As
func (peer *peer) isIBGPPeer() bool {
peer.fsm.lock.RLock()
defer peer.fsm.lock.RUnlock()
return peer.fsm.pConf.State.PeerType == config.PEER_TYPE_INTERNAL
}
func (peer *Peer) isRouteServerClient() bool {
func (peer *peer) isRouteServerClient() bool {
peer.fsm.lock.RLock()
defer peer.fsm.lock.RUnlock()
return peer.fsm.pConf.RouteServer.Config.RouteServerClient
}
func (peer *Peer) isRouteReflectorClient() bool {
func (peer *peer) isSecondaryRouteEnabled() bool {
peer.fsm.lock.RLock()
defer peer.fsm.lock.RUnlock()
return peer.fsm.pConf.RouteServer.Config.RouteServerClient && peer.fsm.pConf.RouteServer.Config.SecondaryRoute
}
func (peer *peer) isRouteReflectorClient() bool {
peer.fsm.lock.RLock()
defer peer.fsm.lock.RUnlock()
return peer.fsm.pConf.RouteReflector.Config.RouteReflectorClient
}
func (peer *Peer) isGracefulRestartEnabled() bool {
func (peer *peer) isGracefulRestartEnabled() bool {
peer.fsm.lock.RLock()
defer peer.fsm.lock.RUnlock()
return peer.fsm.pConf.GracefulRestart.State.Enabled
}
func (peer *Peer) getAddPathMode(family bgp.RouteFamily) bgp.BGPAddPathMode {
func (peer *peer) getAddPathMode(family bgp.RouteFamily) bgp.BGPAddPathMode {
peer.fsm.lock.RLock()
defer peer.fsm.lock.RUnlock()
if mode, y := peer.fsm.rfMap[family]; y {
@@ -170,21 +174,21 @@ func (peer *Peer) getAddPathMode(family bgp.RouteFamily) bgp.BGPAddPathMode {
return bgp.BGP_ADD_PATH_NONE
}
func (peer *Peer) isAddPathReceiveEnabled(family bgp.RouteFamily) bool {
func (peer *peer) isAddPathReceiveEnabled(family bgp.RouteFamily) bool {
return (peer.getAddPathMode(family) & bgp.BGP_ADD_PATH_RECEIVE) > 0
}
func (peer *Peer) isAddPathSendEnabled(family bgp.RouteFamily) bool {
func (peer *peer) isAddPathSendEnabled(family bgp.RouteFamily) bool {
return (peer.getAddPathMode(family) & bgp.BGP_ADD_PATH_SEND) > 0
}
func (peer *Peer) isDynamicNeighbor() bool {
func (peer *peer) isDynamicNeighbor() bool {
peer.fsm.lock.RLock()
defer peer.fsm.lock.RUnlock()
return peer.fsm.pConf.Config.NeighborAddress == "" && peer.fsm.pConf.Config.NeighborInterface == ""
}
func (peer *Peer) recvedAllEOR() bool {
func (peer *peer) recvedAllEOR() bool {
peer.fsm.lock.RLock()
defer peer.fsm.lock.RUnlock()
for _, a := range peer.fsm.pConf.AfiSafis {
@@ -195,14 +199,14 @@ func (peer *Peer) recvedAllEOR() bool {
return true
}
func (peer *Peer) configuredRFlist() []bgp.RouteFamily {
func (peer *peer) configuredRFlist() []bgp.RouteFamily {
peer.fsm.lock.RLock()
defer peer.fsm.lock.RUnlock()
rfs, _ := config.AfiSafis(peer.fsm.pConf.AfiSafis).ToRfList()
return rfs
}
func (peer *Peer) negotiatedRFList() []bgp.RouteFamily {
func (peer *peer) negotiatedRFList() []bgp.RouteFamily {
peer.fsm.lock.RLock()
defer peer.fsm.lock.RUnlock()
l := make([]bgp.RouteFamily, 0, len(peer.fsm.rfMap))
@@ -212,7 +216,8 @@ func (peer *Peer) negotiatedRFList() []bgp.RouteFamily {
return l
}
func (peer *Peer) toGlobalFamilies(families []bgp.RouteFamily) []bgp.RouteFamily {
func (peer *peer) toGlobalFamilies(families []bgp.RouteFamily) []bgp.RouteFamily {
id := peer.ID()
peer.fsm.lock.RLock()
defer peer.fsm.lock.RUnlock()
if peer.fsm.pConf.Config.Vrf != "" {
@@ -223,10 +228,14 @@ func (peer *Peer) toGlobalFamilies(families []bgp.RouteFamily) []bgp.RouteFamily
fs = append(fs, bgp.RF_IPv4_VPN)
case bgp.RF_IPv6_UC:
fs = append(fs, bgp.RF_IPv6_VPN)
case bgp.RF_FS_IPv4_UC:
fs = append(fs, bgp.RF_FS_IPv4_VPN)
case bgp.RF_FS_IPv6_UC:
fs = append(fs, bgp.RF_FS_IPv6_VPN)
default:
log.WithFields(log.Fields{
"Topic": "Peer",
"Key": peer.ID(),
"Key": id,
"Family": f,
"VRF": peer.fsm.pConf.Config.Vrf,
}).Warn("invalid family configured for neighbor with vrf")
@@ -256,7 +265,7 @@ func classifyFamilies(all, part []bgp.RouteFamily) ([]bgp.RouteFamily, []bgp.Rou
return a, b
}
func (peer *Peer) forwardingPreservedFamilies() ([]bgp.RouteFamily, []bgp.RouteFamily) {
func (peer *peer) forwardingPreservedFamilies() ([]bgp.RouteFamily, []bgp.RouteFamily) {
peer.fsm.lock.RLock()
list := []bgp.RouteFamily{}
for _, a := range peer.fsm.pConf.AfiSafis {
@@ -268,7 +277,7 @@ func (peer *Peer) forwardingPreservedFamilies() ([]bgp.RouteFamily, []bgp.RouteF
return classifyFamilies(peer.configuredRFlist(), list)
}
func (peer *Peer) llgrFamilies() ([]bgp.RouteFamily, []bgp.RouteFamily) {
func (peer *peer) llgrFamilies() ([]bgp.RouteFamily, []bgp.RouteFamily) {
peer.fsm.lock.RLock()
list := []bgp.RouteFamily{}
for _, a := range peer.fsm.pConf.AfiSafis {
@@ -280,7 +289,7 @@ func (peer *Peer) llgrFamilies() ([]bgp.RouteFamily, []bgp.RouteFamily) {
return classifyFamilies(peer.configuredRFlist(), list)
}
func (peer *Peer) isLLGREnabledFamily(family bgp.RouteFamily) bool {
func (peer *peer) isLLGREnabledFamily(family bgp.RouteFamily) bool {
peer.fsm.lock.RLock()
llgrEnabled := peer.fsm.pConf.GracefulRestart.Config.LongLivedEnabled
peer.fsm.lock.RUnlock()
@@ -296,7 +305,7 @@ func (peer *Peer) isLLGREnabledFamily(family bgp.RouteFamily) bool {
return false
}
func (peer *Peer) llgrRestartTime(family bgp.RouteFamily) uint32 {
func (peer *peer) llgrRestartTime(family bgp.RouteFamily) uint32 {
peer.fsm.lock.RLock()
defer peer.fsm.lock.RUnlock()
for _, a := range peer.fsm.pConf.AfiSafis {
@@ -307,7 +316,7 @@ func (peer *Peer) llgrRestartTime(family bgp.RouteFamily) uint32 {
return 0
}
func (peer *Peer) llgrRestartTimerExpired(family bgp.RouteFamily) bool {
func (peer *peer) llgrRestartTimerExpired(family bgp.RouteFamily) bool {
peer.fsm.lock.RLock()
defer peer.fsm.lock.RUnlock()
all := true
@@ -323,27 +332,11 @@ func (peer *Peer) llgrRestartTimerExpired(family bgp.RouteFamily) bool {
return all
}
func (peer *Peer) markLLGRStale(fs []bgp.RouteFamily) []*table.Path {
paths := peer.adjRibIn.PathList(fs, true)
for i, p := range paths {
doStale := true
for _, c := range p.GetCommunities() {
if c == uint32(bgp.COMMUNITY_NO_LLGR) {
doStale = false
p = p.Clone(true)
break
}
}
if doStale {
p = p.Clone(false)
p.SetCommunities([]uint32{uint32(bgp.COMMUNITY_LLGR_STALE)}, false)
}
paths[i] = p
}
return paths
func (peer *peer) markLLGRStale(fs []bgp.RouteFamily) []*table.Path {
return peer.adjRibIn.MarkLLGRStaleOrDrop(fs)
}
func (peer *Peer) stopPeerRestarting() {
func (peer *peer) stopPeerRestarting() {
peer.fsm.lock.Lock()
defer peer.fsm.lock.Unlock()
peer.fsm.pConf.GracefulRestart.State.PeerRestarting = false
@@ -354,7 +347,7 @@ func (peer *Peer) stopPeerRestarting() {
}
func (peer *Peer) filterPathFromSourcePeer(path, old *table.Path) *table.Path {
func (peer *peer) filterPathFromSourcePeer(path, old *table.Path) *table.Path {
if peer.ID() != path.GetSource().Address.String() {
return path
}
@@ -389,7 +382,7 @@ func (peer *Peer) filterPathFromSourcePeer(path, old *table.Path) *table.Path {
return nil
}
func (peer *Peer) doPrefixLimit(k bgp.RouteFamily, c *config.PrefixLimitConfig) *bgp.BGPMessage {
func (peer *peer) doPrefixLimit(k bgp.RouteFamily, c *config.PrefixLimitConfig) *bgp.BGPMessage {
if maxPrefixes := int(c.MaxPrefixes); maxPrefixes > 0 {
count := peer.adjRibIn.Count([]bgp.RouteFamily{k})
pct := int(c.ShutdownThresholdPct)
@@ -414,7 +407,7 @@ func (peer *Peer) doPrefixLimit(k bgp.RouteFamily, c *config.PrefixLimitConfig)
}
func (peer *Peer) updatePrefixLimitConfig(c []config.AfiSafi) error {
func (peer *peer) updatePrefixLimitConfig(c []config.AfiSafi) error {
peer.fsm.lock.RLock()
x := peer.fsm.pConf.AfiSafis
peer.fsm.lock.RUnlock()
@@ -441,7 +434,7 @@ func (peer *Peer) updatePrefixLimitConfig(c []config.AfiSafi) error {
}).Warnf("update prefix limit configuration")
peer.prefixLimitWarned[e.State.Family] = false
if msg := peer.doPrefixLimit(e.State.Family, &e.PrefixLimit.Config); msg != nil {
sendFsmOutgoingMsg(peer, nil, msg, true)
sendfsmOutgoingMsg(peer, nil, msg, true)
}
}
}
@@ -451,7 +444,7 @@ func (peer *Peer) updatePrefixLimitConfig(c []config.AfiSafi) error {
return nil
}
func (peer *Peer) handleUpdate(e *FsmMsg) ([]*table.Path, []bgp.RouteFamily, *bgp.BGPMessage) {
func (peer *peer) handleUpdate(e *fsmMsg) ([]*table.Path, []bgp.RouteFamily, *bgp.BGPMessage) {
m := e.MsgData.(*bgp.BGPMessage)
update := m.Body.(*bgp.BGPUpdate)
log.WithFields(log.Fields{
@@ -488,15 +481,15 @@ func (peer *Peer) handleUpdate(e *FsmMsg) ([]*table.Path, []bgp.RouteFamily, *bg
allowOwnAS := int(peer.fsm.pConf.AsPathOptions.Config.AllowOwnAs)
peer.fsm.lock.RUnlock()
if hasOwnASLoop(localAS, allowOwnAS, aspath) {
path.SetAsLooped(true)
path.SetRejected(true)
continue
}
}
// RFC4456 8. Avoiding Routing Information Loops
// A router that recognizes the ORIGINATOR_ID attribute SHOULD
// ignore a route received with its BGP Identifier as the ORIGINATOR_ID.
peer.fsm.lock.RLock()
isIBGPPeer := peer.isIBGPPeer()
peer.fsm.lock.RLock()
routerId := peer.fsm.gConf.Config.RouterId
peer.fsm.lock.RUnlock()
if isIBGPPeer {
@@ -507,6 +500,7 @@ func (peer *Peer) handleUpdate(e *FsmMsg) ([]*table.Path, []bgp.RouteFamily, *bg
"OriginatorID": id,
"Data": path,
}).Debug("Originator ID is mine, ignore")
path.SetRejected(true)
continue
}
}
@@ -526,18 +520,18 @@ func (peer *Peer) handleUpdate(e *FsmMsg) ([]*table.Path, []bgp.RouteFamily, *bg
return nil, nil, nil
}
func (peer *Peer) startFSMHandler(incoming *channels.InfiniteChannel, stateCh chan *FsmMsg) {
handler := NewFSMHandler(peer.fsm, incoming, stateCh, peer.outgoing)
func (peer *peer) startFSMHandler() {
handler := newFSMHandler(peer.fsm, peer.fsm.outgoingCh)
peer.fsm.lock.Lock()
peer.fsm.h = handler
peer.fsm.lock.Unlock()
}
func (peer *Peer) StaleAll(rfList []bgp.RouteFamily) []*table.Path {
func (peer *peer) StaleAll(rfList []bgp.RouteFamily) []*table.Path {
return peer.adjRibIn.StaleAll(rfList)
}
func (peer *Peer) PassConn(conn *net.TCPConn) {
func (peer *peer) PassConn(conn *net.TCPConn) {
select {
case peer.fsm.connCh <- conn:
default:
@@ -549,48 +543,6 @@ func (peer *Peer) PassConn(conn *net.TCPConn) {
}
}
func (peer *Peer) DropAll(rfList []bgp.RouteFamily) {
peer.adjRibIn.Drop(rfList)
}
func (peer *Peer) stopFSM() error {
failed := false
peer.fsm.lock.RLock()
addr := peer.fsm.pConf.State.NeighborAddress
peer.fsm.lock.RUnlock()
t1 := time.AfterFunc(time.Minute*5, func() {
log.WithFields(log.Fields{
"Topic": "Peer",
}).Warnf("Failed to free the fsm.h.t for %s", addr)
failed = true
})
peer.fsm.h.t.Kill(nil)
peer.fsm.h.t.Wait()
t1.Stop()
if !failed {
log.WithFields(log.Fields{
"Topic": "Peer",
"Key": addr,
}).Debug("freed fsm.h.t")
cleanInfiniteChannel(peer.outgoing)
}
failed = false
t2 := time.AfterFunc(time.Minute*5, func() {
log.WithFields(log.Fields{
"Topic": "Peer",
}).Warnf("Failed to free the fsm.t for %s", addr)
failed = true
})
peer.fsm.t.Kill(nil)
peer.fsm.t.Wait()
t2.Stop()
if !failed {
log.WithFields(log.Fields{
"Topic": "Peer",
"Key": addr,
}).Debug("freed fsm.t")
return nil
}
return fmt.Errorf("Failed to free FSM for %s", addr)
func (peer *peer) DropAll(rfList []bgp.RouteFamily) []*table.Path {
return peer.adjRibIn.Drop(rfList)
}

View File

@@ -20,7 +20,6 @@ import (
"fmt"
"io"
"net"
"sort"
"strconv"
"time"
@@ -29,99 +28,51 @@ import (
"github.com/osrg/gobgp/pkg/packet/bgp"
"github.com/osrg/gobgp/pkg/packet/rtr"
"github.com/armon/go-radix"
log "github.com/sirupsen/logrus"
"golang.org/x/net/context"
)
const (
CONNECT_RETRY_INTERVAL = 30
connectRetryInterval = 30
)
func before(a, b uint32) bool {
return int32(a-b) < 0
}
type RoaBucket struct {
Prefix *table.IPPrefix
entries []*table.ROA
}
func (r *RoaBucket) GetEntries() []*table.ROA {
return r.entries
}
type roas []*table.ROA
func (r roas) Len() int {
return len(r)
}
func (r roas) Swap(i, j int) {
r[i], r[j] = r[j], r[i]
}
func (r roas) Less(i, j int) bool {
r1 := r[i]
r2 := r[j]
if r1.MaxLen < r2.MaxLen {
return true
} else if r1.MaxLen > r2.MaxLen {
return false
}
if r1.AS < r2.AS {
return true
}
return false
}
type ROAEventType uint8
type roaEventType uint8
const (
CONNECTED ROAEventType = iota
DISCONNECTED
RTR
LIFETIMEOUT
roaConnected roaEventType = iota
roaDisconnected
roaRTR
roaLifetimeout
)
type ROAEvent struct {
EventType ROAEventType
type roaEvent struct {
EventType roaEventType
Src string
Data []byte
conn *net.TCPConn
}
type roaManager struct {
AS uint32
Roas map[bgp.RouteFamily]*radix.Tree
eventCh chan *ROAEvent
eventCh chan *roaEvent
clientMap map[string]*roaClient
table *table.ROATable
}
func NewROAManager(as uint32) (*roaManager, error) {
func newROAManager(table *table.ROATable) *roaManager {
m := &roaManager{
AS: as,
Roas: make(map[bgp.RouteFamily]*radix.Tree),
eventCh: make(chan *roaEvent),
clientMap: make(map[string]*roaClient),
table: table,
}
m.Roas[bgp.RF_IPv4_UC] = radix.New()
m.Roas[bgp.RF_IPv6_UC] = radix.New()
m.eventCh = make(chan *ROAEvent)
m.clientMap = make(map[string]*roaClient)
return m, nil
return m
}
func (c *roaManager) enabled() bool {
return len(c.clientMap) != 0
}
func (m *roaManager) SetAS(as uint32) error {
if m.AS != 0 {
return fmt.Errorf("AS was already configured")
}
m.AS = as
return nil
func (m *roaManager) enabled() bool {
return len(m.clientMap) != 0
}
func (m *roaManager) AddServer(host string, lifetime int64) error {
@@ -135,7 +86,7 @@ func (m *roaManager) AddServer(host string, lifetime int64) error {
if _, ok := m.clientMap[host]; ok {
return fmt.Errorf("ROA server exists %s", host)
}
m.clientMap[host] = NewRoaClient(address, port, m.eventCh, lifetime)
m.clientMap[host] = newRoaClient(address, port, m.eventCh, lifetime)
return nil
}
@@ -145,35 +96,11 @@ func (m *roaManager) DeleteServer(host string) error {
return fmt.Errorf("ROA server doesn't exists %s", host)
}
client.stop()
m.deleteAllROA(host)
m.table.DeleteAll(host)
delete(m.clientMap, host)
return nil
}
func (m *roaManager) deleteAllROA(network string) {
for _, tree := range m.Roas {
deleteKeys := make([]string, 0, tree.Len())
tree.Walk(func(s string, v interface{}) bool {
b, _ := v.(*RoaBucket)
newEntries := make([]*table.ROA, 0, len(b.entries))
for _, r := range b.entries {
if r.Src != network {
newEntries = append(newEntries, r)
}
}
if len(newEntries) > 0 {
b.entries = newEntries
} else {
deleteKeys = append(deleteKeys, s)
}
return false
})
for _, key := range deleteKeys {
tree.Delete(key)
}
}
}
func (m *roaManager) Enable(address string) error {
for network, client := range m.clientMap {
add, _, _ := net.SplitHostPort(network)
@@ -190,7 +117,7 @@ func (m *roaManager) Disable(address string) error {
add, _, _ := net.SplitHostPort(network)
if add == address {
client.reset()
m.deleteAllROA(add)
m.table.DeleteAll(add)
return nil
}
}
@@ -206,35 +133,35 @@ func (m *roaManager) SoftReset(address string) error {
add, _, _ := net.SplitHostPort(network)
if add == address {
client.softReset()
m.deleteAllROA(network)
m.table.DeleteAll(network)
return nil
}
}
return fmt.Errorf("ROA server not found %s", address)
}
func (c *roaManager) ReceiveROA() chan *ROAEvent {
return c.eventCh
func (m *roaManager) ReceiveROA() chan *roaEvent {
return m.eventCh
}
func (c *roaClient) lifetimeout() {
c.eventCh <- &ROAEvent{
EventType: LIFETIMEOUT,
c.eventCh <- &roaEvent{
EventType: roaLifetimeout,
Src: c.host,
}
}
func (m *roaManager) HandleROAEvent(ev *ROAEvent) {
func (m *roaManager) HandleROAEvent(ev *roaEvent) {
client, y := m.clientMap[ev.Src]
if !y {
if ev.EventType == CONNECTED {
if ev.EventType == roaConnected {
ev.conn.Close()
}
log.WithFields(log.Fields{"Topic": "rpki"}).Errorf("Can't find %s ROA server configuration", ev.Src)
return
}
switch ev.EventType {
case DISCONNECTED:
case roaDisconnected:
log.WithFields(log.Fields{"Topic": "rpki"}).Infof("ROA server %s is disconnected", ev.Src)
client.state.Downtime = time.Now().Unix()
// clear state
@@ -245,14 +172,14 @@ func (m *roaManager) HandleROAEvent(ev *ROAEvent) {
go client.tryConnect()
client.timer = time.AfterFunc(time.Duration(client.lifetime)*time.Second, client.lifetimeout)
client.oldSessionID = client.sessionID
case CONNECTED:
case roaConnected:
log.WithFields(log.Fields{"Topic": "rpki"}).Infof("ROA server %s is connected", ev.Src)
client.conn = ev.conn
client.state.Uptime = time.Now().Unix()
go client.established()
case RTR:
case roaRTR:
m.handleRTRMsg(client, &client.state, ev.Data)
case LIFETIMEOUT:
case roaLifetimeout:
// a) already reconnected but hasn't received
// EndOfData -> needs to delete stale ROAs
// b) not reconnected -> needs to delete stale ROAs
@@ -264,83 +191,17 @@ func (m *roaManager) HandleROAEvent(ev *ROAEvent) {
log.WithFields(log.Fields{"Topic": "rpki"}).Infof("Reconnected to %s. Ignore timeout", client.host)
} else {
log.WithFields(log.Fields{"Topic": "rpki"}).Infof("Deleting all ROAs due to timeout with:%s", client.host)
m.deleteAllROA(client.host)
m.table.DeleteAll(client.host)
}
}
}
func (m *roaManager) roa2tree(roa *table.ROA) (*radix.Tree, string) {
tree := m.Roas[bgp.RF_IPv4_UC]
if roa.Family == bgp.AFI_IP6 {
tree = m.Roas[bgp.RF_IPv6_UC]
}
return tree, table.IpToRadixkey(roa.Prefix.Prefix, roa.Prefix.Length)
}
func (m *roaManager) deleteROA(roa *table.ROA) {
tree, key := m.roa2tree(roa)
b, _ := tree.Get(key)
if b != nil {
bucket := b.(*RoaBucket)
newEntries := make([]*table.ROA, 0, len(bucket.entries))
for _, r := range bucket.entries {
if !r.Equal(roa) {
newEntries = append(newEntries, r)
}
}
if len(newEntries) != len(bucket.entries) {
bucket.entries = newEntries
if len(newEntries) == 0 {
tree.Delete(key)
}
return
}
}
log.WithFields(log.Fields{
"Topic": "rpki",
"Prefix": roa.Prefix.Prefix.String(),
"Prefix Length": roa.Prefix.Length,
"AS": roa.AS,
"Max Length": roa.MaxLen,
}).Info("Can't withdraw a ROA")
}
func (m *roaManager) DeleteROA(roa *table.ROA) {
m.deleteROA(roa)
}
func (m *roaManager) addROA(roa *table.ROA) {
tree, key := m.roa2tree(roa)
b, _ := tree.Get(key)
var bucket *RoaBucket
if b == nil {
bucket = &RoaBucket{
Prefix: roa.Prefix,
entries: make([]*table.ROA, 0),
}
tree.Insert(key, bucket)
} else {
bucket = b.(*RoaBucket)
for _, r := range bucket.entries {
if r.Equal(roa) {
// we already have the same one
return
}
}
}
bucket.entries = append(bucket.entries, roa)
}
func (m *roaManager) AddROA(roa *table.ROA) {
m.addROA(roa)
}
func (c *roaManager) handleRTRMsg(client *roaClient, state *config.RpkiServerState, buf []byte) {
func (m *roaManager) handleRTRMsg(client *roaClient, state *config.RpkiServerState, buf []byte) {
received := &state.RpkiMessages.RpkiReceived
m, err := rtr.ParseRTR(buf)
m1, err := rtr.ParseRTR(buf)
if err == nil {
switch msg := m.(type) {
switch msg := m1.(type) {
case *rtr.RTRSerialNotify:
if before(client.serialNumber, msg.RTRCommon.SerialNumber) {
client.enable(client.serialNumber)
@@ -367,19 +228,19 @@ func (c *roaManager) handleRTRMsg(client *roaClient, state *config.RpkiServerSta
roa := table.NewROA(family, msg.Prefix, msg.PrefixLen, msg.MaxLen, msg.AS, client.host)
if (msg.Flags & 1) == 1 {
if client.endOfData {
c.addROA(roa)
m.table.Add(roa)
} else {
client.pendingROAs = append(client.pendingROAs, roa)
}
} else {
c.deleteROA(roa)
m.table.Delete(roa)
}
case *rtr.RTREndOfData:
received.EndOfData++
if client.sessionID != msg.RTRCommon.SessionID {
// remove all ROAs related with the
// previous session
c.deleteAllROA(client.host)
m.table.DeleteAll(client.host)
}
client.sessionID = msg.RTRCommon.SessionID
client.serialNumber = msg.RTRCommon.SerialNumber
@@ -389,7 +250,7 @@ func (c *roaManager) handleRTRMsg(client *roaClient, state *config.RpkiServerSta
client.timer = nil
}
for _, roa := range client.pendingROAs {
c.addROA(roa)
m.table.Add(roa)
}
client.pendingROAs = make([]*table.ROA, 0)
case *rtr.RTRCacheReset:
@@ -407,34 +268,12 @@ func (c *roaManager) handleRTRMsg(client *roaClient, state *config.RpkiServerSta
}
}
func (c *roaManager) GetServers() []*config.RpkiServer {
f := func(tree *radix.Tree) (map[string]uint32, map[string]uint32) {
records := make(map[string]uint32)
prefixes := make(map[string]uint32)
func (m *roaManager) GetServers() []*config.RpkiServer {
recordsV4, prefixesV4 := m.table.Info(bgp.RF_IPv4_UC)
recordsV6, prefixesV6 := m.table.Info(bgp.RF_IPv6_UC)
tree.Walk(func(s string, v interface{}) bool {
b, _ := v.(*RoaBucket)
tmpRecords := make(map[string]uint32)
for _, roa := range b.entries {
tmpRecords[roa.Src]++
}
for src, r := range tmpRecords {
if r > 0 {
records[src] += r
prefixes[src]++
}
}
return false
})
return records, prefixes
}
recordsV4, prefixesV4 := f(c.Roas[bgp.RF_IPv4_UC])
recordsV6, prefixesV6 := f(c.Roas[bgp.RF_IPv6_UC])
l := make([]*config.RpkiServer, 0, len(c.clientMap))
for _, client := range c.clientMap {
l := make([]*config.RpkiServer, 0, len(m.clientMap))
for _, client := range m.clientMap {
state := &client.state
if client.conn == nil {
@@ -468,128 +307,11 @@ func (c *roaManager) GetServers() []*config.RpkiServer {
return l
}
func (c *roaManager) GetRoa(family bgp.RouteFamily) ([]*table.ROA, error) {
if len(c.clientMap) == 0 {
return []*table.ROA{}, fmt.Errorf("RPKI server isn't configured.")
}
var rfList []bgp.RouteFamily
switch family {
case bgp.RF_IPv4_UC:
rfList = []bgp.RouteFamily{bgp.RF_IPv4_UC}
case bgp.RF_IPv6_UC:
rfList = []bgp.RouteFamily{bgp.RF_IPv6_UC}
default:
rfList = []bgp.RouteFamily{bgp.RF_IPv4_UC, bgp.RF_IPv6_UC}
}
l := make([]*table.ROA, 0)
for _, rf := range rfList {
if tree, ok := c.Roas[rf]; ok {
tree.Walk(func(s string, v interface{}) bool {
b, _ := v.(*RoaBucket)
var roaList roas
for _, r := range b.entries {
roaList = append(roaList, r)
}
sort.Sort(roaList)
for _, roa := range roaList {
l = append(l, roa)
}
return false
})
}
}
return l, nil
}
func ValidatePath(ownAs uint32, tree *radix.Tree, cidr string, asPath *bgp.PathAttributeAsPath) *table.Validation {
var as uint32
validation := &table.Validation{
Status: config.RPKI_VALIDATION_RESULT_TYPE_NOT_FOUND,
Reason: table.RPKI_VALIDATION_REASON_TYPE_NONE,
Matched: make([]*table.ROA, 0),
UnmatchedLength: make([]*table.ROA, 0),
UnmatchedAs: make([]*table.ROA, 0),
}
if asPath == nil || len(asPath.Value) == 0 {
as = ownAs
} else {
param := asPath.Value[len(asPath.Value)-1]
switch param.GetType() {
case bgp.BGP_ASPATH_ATTR_TYPE_SEQ:
asList := param.GetAS()
if len(asList) == 0 {
as = ownAs
} else {
as = asList[len(asList)-1]
}
case bgp.BGP_ASPATH_ATTR_TYPE_CONFED_SET, bgp.BGP_ASPATH_ATTR_TYPE_CONFED_SEQ:
as = ownAs
default:
return validation
}
}
_, n, _ := net.ParseCIDR(cidr)
ones, _ := n.Mask.Size()
prefixLen := uint8(ones)
key := table.IpToRadixkey(n.IP, prefixLen)
_, b, _ := tree.LongestPrefix(key)
if b == nil {
return validation
}
var bucket *RoaBucket
fn := radix.WalkFn(func(k string, v interface{}) bool {
bucket, _ = v.(*RoaBucket)
for _, r := range bucket.entries {
if prefixLen <= r.MaxLen {
if r.AS != 0 && r.AS == as {
validation.Matched = append(validation.Matched, r)
} else {
validation.UnmatchedAs = append(validation.UnmatchedAs, r)
}
} else {
validation.UnmatchedLength = append(validation.UnmatchedLength, r)
}
}
return false
})
tree.WalkPath(key, fn)
if len(validation.Matched) != 0 {
validation.Status = config.RPKI_VALIDATION_RESULT_TYPE_VALID
validation.Reason = table.RPKI_VALIDATION_REASON_TYPE_NONE
} else if len(validation.UnmatchedAs) != 0 {
validation.Status = config.RPKI_VALIDATION_RESULT_TYPE_INVALID
validation.Reason = table.RPKI_VALIDATION_REASON_TYPE_AS
} else if len(validation.UnmatchedLength) != 0 {
validation.Status = config.RPKI_VALIDATION_RESULT_TYPE_INVALID
validation.Reason = table.RPKI_VALIDATION_REASON_TYPE_LENGTH
} else {
validation.Status = config.RPKI_VALIDATION_RESULT_TYPE_NOT_FOUND
validation.Reason = table.RPKI_VALIDATION_REASON_TYPE_NONE
}
return validation
}
func (c *roaManager) validate(path *table.Path) *table.Validation {
if len(c.clientMap) == 0 || path.IsWithdraw || path.IsEOR() {
// RPKI isn't enabled or invalid path
return nil
}
if tree, ok := c.Roas[path.GetRouteFamily()]; ok {
return ValidatePath(c.AS, tree, path.GetNlri().String(), path.GetAsPath())
}
return nil
}
type roaClient struct {
host string
conn *net.TCPConn
state config.RpkiServerState
eventCh chan *ROAEvent
eventCh chan *roaEvent
sessionID uint16
oldSessionID uint16
serialNumber uint32
@@ -601,7 +323,7 @@ type roaClient struct {
ctx context.Context
}
func NewRoaClient(address, port string, ch chan *ROAEvent, lifetime int64) *roaClient {
func newRoaClient(address, port string, ch chan *roaEvent, lifetime int64) *roaClient {
ctx, cancel := context.WithCancel(context.Background())
c := &roaClient{
host: net.JoinHostPort(address, port),
@@ -663,10 +385,10 @@ func (c *roaClient) tryConnect() {
}
if conn, err := net.Dial("tcp", c.host); err != nil {
// better to use context with timeout
time.Sleep(CONNECT_RETRY_INTERVAL * time.Second)
time.Sleep(connectRetryInterval * time.Second)
} else {
c.eventCh <- &ROAEvent{
EventType: CONNECTED,
c.eventCh <- &roaEvent{
EventType: roaConnected,
Src: c.host,
conn: conn.(*net.TCPConn),
}
@@ -678,8 +400,8 @@ func (c *roaClient) tryConnect() {
func (c *roaClient) established() (err error) {
defer func() {
c.conn.Close()
c.eventCh <- &ROAEvent{
EventType: DISCONNECTED,
c.eventCh <- &roaEvent{
EventType: roaDisconnected,
Src: c.host,
}
}()
@@ -703,8 +425,8 @@ func (c *roaClient) established() (err error) {
return
}
c.eventCh <- &ROAEvent{
EventType: RTR,
c.eventCh <- &roaEvent{
EventType: roaRTR,
Src: c.host,
Data: append(header, body...),
}

File diff suppressed because it is too large Load Diff

View File

@@ -17,74 +17,46 @@
package server
import (
"fmt"
"net"
"syscall"
log "github.com/sirupsen/logrus"
)
func SetTcpMD5SigSockopt(l *net.TCPListener, address string, key string) error {
func setTCPMD5SigSockopt(l *net.TCPListener, address string, key string) error {
return setTcpMD5SigSockopt(l, address, key)
}
func SetListenTcpTTLSockopt(l *net.TCPListener, ttl int) error {
func setListenTCPTTLSockopt(l *net.TCPListener, ttl int) error {
return setListenTcpTTLSockopt(l, ttl)
}
func SetTcpTTLSockopt(conn *net.TCPConn, ttl int) error {
func setTCPTTLSockopt(conn *net.TCPConn, ttl int) error {
return setTcpTTLSockopt(conn, ttl)
}
func SetTcpMinTTLSockopt(conn *net.TCPConn, ttl int) error {
func setTCPMinTTLSockopt(conn *net.TCPConn, ttl int) error {
return setTcpMinTTLSockopt(conn, ttl)
}
type TCPDialer struct {
net.Dialer
// MD5 authentication password.
AuthPassword string
// The TTL value to set outgoing connection.
Ttl uint8
// The minimum TTL value for incoming packets.
TtlMin uint8
}
func (d *TCPDialer) DialTCP(addr string, port int) (*net.TCPConn, error) {
if d.AuthPassword != "" {
func dialerControl(network, address string, c syscall.RawConn, ttl, ttlMin uint8, password string, bindInterface string) error {
if password != "" {
log.WithFields(log.Fields{
"Topic": "Peer",
"Key": addr,
"Key": address,
}).Warn("setting md5 for active connection is not supported")
}
if d.Ttl != 0 {
if ttl != 0 {
log.WithFields(log.Fields{
"Topic": "Peer",
"Key": addr,
"Key": address,
}).Warn("setting ttl for active connection is not supported")
}
if d.TtlMin != 0 {
if ttlMin != 0 {
log.WithFields(log.Fields{
"Topic": "Peer",
"Key": addr,
"Key": address,
}).Warn("setting min ttl for active connection is not supported")
}
raddr, err := net.ResolveTCPAddr("tcp", net.JoinHostPort(addr, fmt.Sprintf("%d", port)))
if err != nil {
return nil, fmt.Errorf("invalid remote address: %s", err)
}
laddr, err := net.ResolveTCPAddr("tcp", d.LocalAddr.String())
if err != nil {
return nil, fmt.Errorf("invalid local address: %s", err)
}
dialer := net.Dialer{LocalAddr: laddr, Timeout: d.Timeout}
conn, err := dialer.Dial("tcp", raddr.String())
if err != nil {
return nil, err
}
return conn.(*net.TCPConn), nil
return nil
}

View File

@@ -22,8 +22,8 @@ import (
)
const (
TCP_MD5SIG = 0x10 // TCP MD5 Signature (RFC2385)
IPV6_MINHOPCOUNT = 73 // Generalized TTL Security Mechanism (RFC5082)
tcpMD5SIG = 0x10 // TCP MD5 Signature (RFC2385)
ipv6MinHopCount = 73 // Generalized TTL Security Mechanism (RFC5082)
)
func setTcpMD5SigSockopt(l *net.TCPListener, address string, key string) error {
@@ -32,7 +32,7 @@ func setTcpMD5SigSockopt(l *net.TCPListener, address string, key string) error {
return err
}
// always enable and assumes that the configuration is done by setkey()
return setsockOptInt(sc, syscall.IPPROTO_TCP, TCP_MD5SIG, 1)
return setsockOptInt(sc, syscall.IPPROTO_TCP, tcpMD5SIG, 1)
}
func setListenTcpTTLSockopt(l *net.TCPListener, ttl int) error {
@@ -63,7 +63,7 @@ func setTcpMinTTLSockopt(conn *net.TCPConn, ttl int) error {
name := syscall.IP_MINTTL
if family == syscall.AF_INET6 {
level = syscall.IPPROTO_IPV6
name = IPV6_MINHOPCOUNT
name = ipv6MinHopCount
}
return setsockOptInt(sc, level, name, ttl)
}

View File

@@ -17,7 +17,6 @@
package server
import (
"fmt"
"net"
"os"
"syscall"
@@ -25,8 +24,8 @@ import (
)
const (
TCP_MD5SIG = 14 // TCP MD5 Signature (RFC2385)
IPV6_MINHOPCOUNT = 73 // Generalized TTL Security Mechanism (RFC5082)
tcpMD5SIG = 14 // TCP MD5 Signature (RFC2385)
ipv6MinHopCount = 73 // Generalized TTL Security Mechanism (RFC5082)
)
type tcpmd5sig struct {
@@ -40,7 +39,7 @@ type tcpmd5sig struct {
key [80]byte
}
func buildTcpMD5Sig(address string, key string) (tcpmd5sig, error) {
func buildTcpMD5Sig(address, key string) (tcpmd5sig, error) {
t := tcpmd5sig{}
addr := net.ParseIP(address)
if addr.To4() != nil {
@@ -57,7 +56,7 @@ func buildTcpMD5Sig(address string, key string) (tcpmd5sig, error) {
return t, nil
}
func SetTcpMD5SigSockopt(l *net.TCPListener, address string, key string) error {
func setTCPMD5SigSockopt(l *net.TCPListener, address string, key string) error {
t, err := buildTcpMD5Sig(address, key)
if err != nil {
return err
@@ -68,10 +67,10 @@ func SetTcpMD5SigSockopt(l *net.TCPListener, address string, key string) error {
if err != nil {
return err
}
return setsockOptString(sc, syscall.IPPROTO_TCP, TCP_MD5SIG, string(b[:]))
return setsockOptString(sc, syscall.IPPROTO_TCP, tcpMD5SIG, string(b[:]))
}
func SetListenTcpTTLSockopt(l *net.TCPListener, ttl int) error {
func setListenTCPTTLSockopt(l *net.TCPListener, ttl int) error {
family := extractFamilyFromTCPListener(l)
sc, err := l.SyscallConn()
if err != nil {
@@ -80,7 +79,7 @@ func SetListenTcpTTLSockopt(l *net.TCPListener, ttl int) error {
return setsockoptIpTtl(sc, family, ttl)
}
func SetTcpTTLSockopt(conn *net.TCPConn, ttl int) error {
func setTCPTTLSockopt(conn *net.TCPConn, ttl int) error {
family := extractFamilyFromTCPConn(conn)
sc, err := conn.SyscallConn()
if err != nil {
@@ -89,7 +88,7 @@ func SetTcpTTLSockopt(conn *net.TCPConn, ttl int) error {
return setsockoptIpTtl(sc, family, ttl)
}
func SetTcpMinTTLSockopt(conn *net.TCPConn, ttl int) error {
func setTCPMinTTLSockopt(conn *net.TCPConn, ttl int) error {
family := extractFamilyFromTCPConn(conn)
sc, err := conn.SyscallConn()
if err != nil {
@@ -99,191 +98,78 @@ func SetTcpMinTTLSockopt(conn *net.TCPConn, ttl int) error {
name := syscall.IP_MINTTL
if family == syscall.AF_INET6 {
level = syscall.IPPROTO_IPV6
name = IPV6_MINHOPCOUNT
name = ipv6MinHopCount
}
return setsockOptInt(sc, level, name, ttl)
}
func setsockoptTcpMD5Sig(fd int, address string, key string) error {
t, err := buildTcpMD5Sig(address, key)
if err != nil {
return err
}
b := *(*[unsafe.Sizeof(t)]byte)(unsafe.Pointer(&t))
return os.NewSyscallError("setsockopt", syscall.SetsockoptString(fd, syscall.IPPROTO_TCP, TCP_MD5SIG, string(b[:])))
}
func setsockoptIpTtl2(fd int, family int, value int) error {
level := syscall.IPPROTO_IP
name := syscall.IP_TTL
if family == syscall.AF_INET6 {
level = syscall.IPPROTO_IPV6
name = syscall.IPV6_UNICAST_HOPS
}
return os.NewSyscallError("setsockopt", syscall.SetsockoptInt(fd, level, name, value))
}
func setsockoptIpMinTtl(fd int, family int, value int) error {
level := syscall.IPPROTO_IP
name := syscall.IP_MINTTL
if family == syscall.AF_INET6 {
level = syscall.IPPROTO_IPV6
name = IPV6_MINHOPCOUNT
}
return os.NewSyscallError("setsockopt", syscall.SetsockoptInt(fd, level, name, value))
}
type TCPDialer struct {
net.Dialer
// MD5 authentication password.
AuthPassword string
// The TTL value to set outgoing connection.
Ttl uint8
// The minimum TTL value for incoming packets.
TtlMin uint8
}
func (d *TCPDialer) DialTCP(addr string, port int) (*net.TCPConn, error) {
var family int
var ra, la syscall.Sockaddr
raddr, err := net.ResolveTCPAddr("tcp", net.JoinHostPort(addr, fmt.Sprintf("%d", port)))
if err != nil {
return nil, fmt.Errorf("invalid remote address: %s", err)
}
laddr, err := net.ResolveTCPAddr("tcp", d.LocalAddr.String())
if err != nil {
return nil, fmt.Errorf("invalid local address: %s", err)
}
if raddr.IP.To4() != nil {
family = syscall.AF_INET
rsockaddr := &syscall.SockaddrInet4{Port: port}
copy(rsockaddr.Addr[:], raddr.IP.To4())
ra = rsockaddr
lsockaddr := &syscall.SockaddrInet4{}
copy(lsockaddr.Addr[:], laddr.IP.To4())
la = lsockaddr
} else {
func dialerControl(network, address string, c syscall.RawConn, ttl, minTtl uint8, password string, bindInterface string) error {
family := syscall.AF_INET
raddr, _ := net.ResolveTCPAddr("tcp", address)
if raddr.IP.To4() == nil {
family = syscall.AF_INET6
rsockaddr := &syscall.SockaddrInet6{Port: port}
copy(rsockaddr.Addr[:], raddr.IP.To16())
ra = rsockaddr
var zone uint32
if laddr.Zone != "" {
if intf, err := net.InterfaceByName(laddr.Zone); err != nil {
return nil, err
} else {
zone = uint32(intf.Index)
}
var sockerr error
if password != "" {
addr, _, _ := net.SplitHostPort(address)
t, err := buildTcpMD5Sig(addr, password)
if err != nil {
return err
}
b := *(*[unsafe.Sizeof(t)]byte)(unsafe.Pointer(&t))
if err := c.Control(func(fd uintptr) {
sockerr = os.NewSyscallError("setsockopt", syscall.SetsockoptString(int(fd), syscall.IPPROTO_TCP, tcpMD5SIG, string(b[:])))
}); err != nil {
return err
}
if sockerr != nil {
return sockerr
}
}
if ttl != 0 {
if err := c.Control(func(fd uintptr) {
level := syscall.IPPROTO_IP
name := syscall.IP_TTL
if family == syscall.AF_INET6 {
level = syscall.IPPROTO_IPV6
name = syscall.IPV6_UNICAST_HOPS
}
sockerr = os.NewSyscallError("setsockopt", syscall.SetsockoptInt(int(fd), level, name, int(ttl)))
}); err != nil {
return err
}
lsockaddr := &syscall.SockaddrInet6{ZoneId: zone}
copy(lsockaddr.Addr[:], laddr.IP.To16())
la = lsockaddr
}
sockType := syscall.SOCK_STREAM | syscall.SOCK_CLOEXEC | syscall.SOCK_NONBLOCK
proto := 0
fd, err := syscall.Socket(family, sockType, proto)
if err != nil {
return nil, err
}
fi := os.NewFile(uintptr(fd), "")
defer fi.Close()
// A new socket was created so we must close it before this
// function returns either on failure or success. On success,
// net.FileConn() in newTCPConn() increases the refcount of
// the socket so this fi.Close() doesn't destroy the socket.
// The caller must call Close() with the file later.
// Note that the above os.NewFile() doesn't play with the
// refcount.
if err = syscall.SetsockoptInt(fd, syscall.SOL_SOCKET, syscall.SO_BROADCAST, 1); err != nil {
return nil, os.NewSyscallError("setsockopt", err)
}
if err = syscall.SetsockoptInt(fd, syscall.IPPROTO_TCP, syscall.TCP_NODELAY, 1); err != nil {
return nil, os.NewSyscallError("setsockopt", err)
}
if d.AuthPassword != "" {
if err = setsockoptTcpMD5Sig(fd, addr, d.AuthPassword); err != nil {
return nil, err
if sockerr != nil {
return sockerr
}
}
if d.Ttl != 0 {
if err = setsockoptIpTtl2(fd, family, int(d.Ttl)); err != nil {
return nil, err
}
}
if d.TtlMin != 0 {
if err = setsockoptIpMinTtl(fd, family, int(d.Ttl)); err != nil {
return nil, err
}
}
if err = syscall.Bind(fd, la); err != nil {
return nil, os.NewSyscallError("bind", err)
}
newTCPConn := func(fi *os.File) (*net.TCPConn, error) {
if conn, err := net.FileConn(fi); err != nil {
return nil, err
} else {
return conn.(*net.TCPConn), err
}
}
err = syscall.Connect(fd, ra)
switch err {
case syscall.EINPROGRESS, syscall.EALREADY, syscall.EINTR:
// do timeout handling
case nil, syscall.EISCONN:
return newTCPConn(fi)
default:
return nil, os.NewSyscallError("connect", err)
}
epfd, e := syscall.EpollCreate1(syscall.EPOLL_CLOEXEC)
if e != nil {
return nil, e
}
defer syscall.Close(epfd)
var event syscall.EpollEvent
events := make([]syscall.EpollEvent, 1)
event.Events = syscall.EPOLLIN | syscall.EPOLLOUT | syscall.EPOLLPRI
event.Fd = int32(fd)
if e = syscall.EpollCtl(epfd, syscall.EPOLL_CTL_ADD, fd, &event); e != nil {
return nil, e
}
for {
nevents, e := syscall.EpollWait(epfd, events, int(d.Timeout/1000000) /*msec*/)
if e != nil {
return nil, e
}
if nevents == 0 {
return nil, fmt.Errorf("timeout")
} else if nevents == 1 && events[0].Fd == int32(fd) {
nerr, err := syscall.GetsockoptInt(fd, syscall.SOL_SOCKET, syscall.SO_ERROR)
if err != nil {
return nil, os.NewSyscallError("getsockopt", err)
if minTtl != 0 {
if err := c.Control(func(fd uintptr) {
level := syscall.IPPROTO_IP
name := syscall.IP_MINTTL
if family == syscall.AF_INET6 {
level = syscall.IPPROTO_IPV6
name = ipv6MinHopCount
}
switch err := syscall.Errno(nerr); err {
case syscall.EINPROGRESS, syscall.EALREADY, syscall.EINTR:
case syscall.Errno(0), syscall.EISCONN:
return newTCPConn(fi)
default:
return nil, os.NewSyscallError("getsockopt", err)
}
} else {
return nil, fmt.Errorf("unexpected epoll behavior")
sockerr = os.NewSyscallError("setsockopt", syscall.SetsockoptInt(int(fd), level, name, int(minTtl)))
}); err != nil {
return err
}
if sockerr != nil {
return sockerr
}
}
if bindInterface != "" {
if err := c.Control(func(fd uintptr) {
sockerr = os.NewSyscallError("setsockopt", syscall.SetsockoptString(int(fd), syscall.SOL_SOCKET, syscall.SO_BINDTODEVICE, bindInterface))
}); err != nil {
return err
}
if sockerr != nil {
return sockerr
}
}
return nil
}

View File

@@ -60,7 +60,7 @@ type sadbMsg struct {
func (s *sadbMsg) DecodeFromBytes(data []byte) error {
if len(data) < SADB_MSG_SIZE {
fmt.Errorf("too short for sadbMsg %d", len(data))
return fmt.Errorf("too short for sadbMsg %d", len(data))
}
s.sadbMsgVersion = data[0]
s.sadbMsgType = data[1]
@@ -348,12 +348,12 @@ func saDelete(address string) error {
}
const (
TCP_MD5SIG = 0x4 // TCP MD5 Signature (RFC2385)
IPV6_MINHOPCOUNT = 73 // Generalized TTL Security Mechanism (RFC5082)
tcpMD5SIG = 0x4 // TCP MD5 Signature (RFC2385)
ipv6MinHopCount = 73 // Generalized TTL Security Mechanism (RFC5082)
)
func setsockoptTcpMD5Sig(sc syscall.RawConn, address string, key string) error {
if err := setsockOptInt(sc, syscall.IPPROTO_TCP, TCP_MD5SIG, 1); err != nil {
if err := setsockOptInt(sc, syscall.IPPROTO_TCP, tcpMD5SIG, 1); err != nil {
return err
}
if len(key) > 0 {
@@ -362,7 +362,7 @@ func setsockoptTcpMD5Sig(sc syscall.RawConn, address string, key string) error {
return saDelete(address)
}
func SetTcpMD5SigSockopt(l *net.TCPListener, address string, key string) error {
func setTCPMD5SigSockopt(l *net.TCPListener, address string, key string) error {
sc, err := l.SyscallConn()
if err != nil {
return err
@@ -370,7 +370,7 @@ func SetTcpMD5SigSockopt(l *net.TCPListener, address string, key string) error {
return setsockoptTcpMD5Sig(sc, address, key)
}
func SetListenTcpTTLSockopt(l *net.TCPListener, ttl int) error {
func setListenTCPTTLSockopt(l *net.TCPListener, ttl int) error {
family := extractFamilyFromTCPListener(l)
sc, err := l.SyscallConn()
if err != nil {
@@ -379,7 +379,7 @@ func SetListenTcpTTLSockopt(l *net.TCPListener, ttl int) error {
return setsockoptIpTtl(sc, family, ttl)
}
func SetTcpTTLSockopt(conn *net.TCPConn, ttl int) error {
func setTCPTTLSockopt(conn *net.TCPConn, ttl int) error {
family := extractFamilyFromTCPConn(conn)
sc, err := conn.SyscallConn()
if err != nil {
@@ -388,7 +388,7 @@ func SetTcpTTLSockopt(conn *net.TCPConn, ttl int) error {
return setsockoptIpTtl(sc, family, ttl)
}
func SetTcpMinTTLSockopt(conn *net.TCPConn, ttl int) error {
func setTCPMinTTLSockopt(conn *net.TCPConn, ttl int) error {
family := extractFamilyFromTCPConn(conn)
sc, err := conn.SyscallConn()
if err != nil {
@@ -398,57 +398,29 @@ func SetTcpMinTTLSockopt(conn *net.TCPConn, ttl int) error {
name := syscall.IP_MINTTL
if family == syscall.AF_INET6 {
level = syscall.IPPROTO_IPV6
name = IPV6_MINHOPCOUNT
name = ipv6MinHopCount
}
return setsockOptInt(sc, level, name, ttl)
}
type TCPDialer struct {
net.Dialer
// MD5 authentication password.
AuthPassword string
// The TTL value to set outgoing connection.
Ttl uint8
// The minimum TTL value for incoming packets.
TtlMin uint8
}
func (d *TCPDialer) DialTCP(addr string, port int) (*net.TCPConn, error) {
if d.AuthPassword != "" {
func dialerControl(network, address string, c syscall.RawConn, ttl, minTtl uint8, password string, bindInterface string) error {
if password != "" {
log.WithFields(log.Fields{
"Topic": "Peer",
"Key": addr,
"Key": address,
}).Warn("setting md5 for active connection is not supported")
}
if d.Ttl != 0 {
if ttl != 0 {
log.WithFields(log.Fields{
"Topic": "Peer",
"Key": addr,
"Key": address,
}).Warn("setting ttl for active connection is not supported")
}
if d.TtlMin != 0 {
if minTtl != 0 {
log.WithFields(log.Fields{
"Topic": "Peer",
"Key": addr,
"Key": address,
}).Warn("setting min ttl for active connection is not supported")
}
raddr, err := net.ResolveTCPAddr("tcp", net.JoinHostPort(addr, fmt.Sprintf("%d", port)))
if err != nil {
return nil, fmt.Errorf("invalid remote address: %s", err)
}
laddr, err := net.ResolveTCPAddr("tcp", d.LocalAddr.String())
if err != nil {
return nil, fmt.Errorf("invalid local address: %s", err)
}
dialer := net.Dialer{LocalAddr: laddr, Timeout: d.Timeout}
conn, err := dialer.Dial("tcp", raddr.String())
if err != nil {
return nil, err
}
return conn.(*net.TCPConn), nil
return nil
}

View File

@@ -25,10 +25,6 @@ func setTcpMD5SigSockopt(l *net.TCPListener, address string, key string) error {
return fmt.Errorf("setting md5 is not supported")
}
func setListenTcpTTLSockopt(l *net.TCPListener, ttl int) error {
return fmt.Errorf("setting ttl is not supported")
}
func setTcpTTLSockopt(conn *net.TCPConn, ttl int) error {
return fmt.Errorf("setting ttl is not supported")
}

View File

@@ -116,7 +116,27 @@ func filterOutExternalPath(paths []*table.Path) []*table.Path {
return filteredPaths
}
func newIPRouteBody(dst []*table.Path) (body *zebra.IPRouteBody, isWithdraw bool) {
func addLabelToNexthop(path *table.Path, z *zebraClient, msgFlags *zebra.MessageFlag, nexthop *zebra.Nexthop) {
rf := path.GetRouteFamily()
if rf == bgp.RF_IPv4_VPN || rf == bgp.RF_IPv6_VPN {
z.client.SetLabelFlag(msgFlags, nexthop)
switch rf {
case bgp.RF_IPv4_VPN:
for _, label := range path.GetNlri().(*bgp.LabeledVPNIPAddrPrefix).Labels.Labels {
nexthop.LabelNum++
nexthop.MplsLabels = append(nexthop.MplsLabels, label)
}
case bgp.RF_IPv6_VPN:
for _, label := range path.GetNlri().(*bgp.LabeledVPNIPv6AddrPrefix).Labels.Labels {
nexthop.LabelNum++
nexthop.MplsLabels = append(nexthop.MplsLabels, label)
}
}
}
}
func newIPRouteBody(dst []*table.Path, vrfID uint32, z *zebraClient) (body *zebra.IPRouteBody, isWithdraw bool) {
version := z.client.Version
paths := filterOutExternalPath(dst)
if len(paths) == 0 {
return nil, false
@@ -125,50 +145,53 @@ func newIPRouteBody(dst []*table.Path) (body *zebra.IPRouteBody, isWithdraw bool
l := strings.SplitN(path.GetNlri().String(), "/", 2)
var prefix net.IP
//nexthops := make([]net.IP, 0, len(paths))
var nexthop zebra.Nexthop
nexthops := make([]zebra.Nexthop, 0, len(paths))
msgFlags := zebra.MessageNexthop
switch path.GetRouteFamily() {
case bgp.RF_IPv4_UC, bgp.RF_IPv4_VPN:
if path.GetRouteFamily() == bgp.RF_IPv4_UC {
prefix = path.GetNlri().(*bgp.IPAddrPrefix).IPAddrPrefixDefault.Prefix.To4()
} else {
prefix = path.GetNlri().(*bgp.LabeledVPNIPAddrPrefix).IPAddrPrefixDefault.Prefix.To4()
}
for _, p := range paths {
nexthop.Gate = p.GetNexthop().To4()
nexthops = append(nexthops, nexthop)
}
case bgp.RF_IPv6_UC, bgp.RF_IPv6_VPN:
if path.GetRouteFamily() == bgp.RF_IPv6_UC {
prefix = path.GetNlri().(*bgp.IPv6AddrPrefix).IPAddrPrefixDefault.Prefix.To16()
} else {
prefix = path.GetNlri().(*bgp.LabeledVPNIPv6AddrPrefix).IPAddrPrefixDefault.Prefix.To16()
}
for _, p := range paths {
nexthop.Gate = p.GetNexthop().To16()
nexthops = append(nexthops, nexthop)
}
case bgp.RF_IPv4_UC:
prefix = path.GetNlri().(*bgp.IPAddrPrefix).IPAddrPrefixDefault.Prefix.To4()
case bgp.RF_IPv4_VPN:
prefix = path.GetNlri().(*bgp.LabeledVPNIPAddrPrefix).IPAddrPrefixDefault.Prefix.To4()
case bgp.RF_IPv6_UC:
prefix = path.GetNlri().(*bgp.IPv6AddrPrefix).IPAddrPrefixDefault.Prefix.To16()
case bgp.RF_IPv6_VPN:
prefix = path.GetNlri().(*bgp.LabeledVPNIPv6AddrPrefix).IPAddrPrefixDefault.Prefix.To16()
default:
return nil, false
}
msgFlags := zebra.MESSAGE_NEXTHOP
nhVrfID := uint32(zebra.DefaultVrf)
for vrfPath, pathVrfID := range z.pathVrfMap {
if path.Equal(vrfPath) {
nhVrfID = pathVrfID
break
} else {
continue
}
}
for _, p := range paths {
nexthop.Gate = p.GetNexthop()
nexthop.VrfID = nhVrfID
if nhVrfID != vrfID {
addLabelToNexthop(path, z, &msgFlags, &nexthop)
}
nexthops = append(nexthops, nexthop)
}
plen, _ := strconv.ParseUint(l[1], 10, 8)
med, err := path.GetMed()
if err == nil {
msgFlags |= zebra.MESSAGE_METRIC
msgFlags |= zebra.MessageMetric.ToEach(version)
}
var flags zebra.FLAG
info := path.GetSource()
if info.AS == info.LocalAS {
flags = zebra.FLAG_IBGP | zebra.FLAG_INTERNAL
} else if info.MultihopTtl > 0 {
flags = zebra.FLAG_INTERNAL
var flags zebra.Flag
if path.IsIBGP() {
flags = zebra.FlagIBGP.ToEach(z.client.Version, z.client.SoftwareName) | zebra.FlagAllowRecursion
} else if path.GetSource().MultihopTtl > 0 {
flags = zebra.FlagAllowRecursion // 0x01
}
return &zebra.IPRouteBody{
Type: zebra.ROUTE_BGP,
Type: zebra.RouteBGP,
Flags: flags,
SAFI: zebra.SAFI_UNICAST,
Safi: zebra.SafiUnicast,
Message: msgFlags,
Prefix: zebra.Prefix{
Prefix: prefix,
@@ -228,11 +251,11 @@ func newNexthopUnregisterBody(family uint16, prefix net.IP) *zebra.NexthopRegist
}
}
func newPathFromIPRouteMessage(m *zebra.Message, version uint8) *table.Path {
func newPathFromIPRouteMessage(m *zebra.Message, version uint8, software string) *table.Path {
header := m.Header
body := m.Body.(*zebra.IPRouteBody)
family := body.RouteFamily(version)
isWithdraw := body.IsWithdraw(version)
family := body.RouteFamily(version, software)
isWithdraw := body.IsWithdraw(version, software)
var nlri bgp.AddrPrefixInterface
pattr := make([]bgp.PathAttributeInterface, 0)
@@ -242,7 +265,7 @@ func newPathFromIPRouteMessage(m *zebra.Message, version uint8) *table.Path {
log.WithFields(log.Fields{
"Topic": "Zebra",
"RouteType": body.Type.String(),
"Flag": body.Flags.String(),
"Flag": body.Flags.String(version, software),
"Message": body.Message,
"Family": body.Prefix.Family,
"Prefix": body.Prefix.Prefix,
@@ -282,10 +305,18 @@ func newPathFromIPRouteMessage(m *zebra.Message, version uint8) *table.Path {
return path
}
type mplsLabelParameter struct {
rangeSize uint32
maps map[uint64]*table.Bitmap
unassignedVrf []*table.Vrf //Vrfs which are not assigned MPLS label
}
type zebraClient struct {
client *zebra.Client
server *BgpServer
nexthopCache nexthopStateCache
pathVrfMap map[*table.Path]uint32 //vpn paths and nexthop vpn id
mplsLabel mplsLabelParameter
dead chan struct{}
}
@@ -331,9 +362,9 @@ func (z *zebraClient) updatePathByNexthopCache(paths []*table.Path) {
}
func (z *zebraClient) loop() {
w := z.server.Watch([]WatchOption{
WatchBestPath(true),
WatchPostUpdate(true),
w := z.server.watch([]watchOption{
watchBestPath(true),
watchPostUpdate(true),
}...)
defer w.Stop()
@@ -342,9 +373,12 @@ func (z *zebraClient) loop() {
case <-z.dead:
return
case msg := <-z.client.Receive():
if msg == nil {
break
}
switch body := msg.Body.(type) {
case *zebra.IPRouteBody:
if path := newPathFromIPRouteMessage(msg, z.client.Version); path != nil {
if path := newPathFromIPRouteMessage(msg, z.client.Version, z.client.SoftwareName); path != nil {
if err := z.server.addPathList("", []*table.Path{path}); err != nil {
log.WithFields(log.Fields{
"Topic": "Zebra",
@@ -361,36 +395,52 @@ func (z *zebraClient) loop() {
if len(paths) == 0 {
// If there is no path bound for the given nexthop, send
// NEXTHOP_UNREGISTER message.
z.client.SendNexthopRegister(msg.Header.VrfId, newNexthopUnregisterBody(uint16(body.Prefix.Family), body.Prefix.Prefix), true)
z.client.SendNexthopRegister(msg.Header.VrfID, newNexthopUnregisterBody(uint16(body.Prefix.Family), body.Prefix.Prefix), true)
delete(z.nexthopCache, body.Prefix.Prefix.String())
}
z.updatePathByNexthopCache(paths)
case *zebra.GetLabelChunkBody:
log.WithFields(log.Fields{
"Topic": "Zebra",
"Start": body.Start,
"End": body.End,
}).Debugf("zebra GetLabelChunkBody is received")
startEnd := uint64(body.Start)<<32 | uint64(body.End)
z.mplsLabel.maps[startEnd] = table.NewBitmap(int(body.End - body.Start + 1))
for _, vrf := range z.mplsLabel.unassignedVrf {
if err := z.assignAndSendVrfMplsLabel(vrf); err != nil {
log.WithFields(log.Fields{
"Topic": "Zebra",
"Error": err,
}).Error("zebra failed to assign and send vrf mpls label")
}
}
z.mplsLabel.unassignedVrf = nil
}
case ev := <-w.Event():
switch msg := ev.(type) {
case *WatchEventBestPath:
case *watchEventBestPath:
if table.UseMultiplePaths.Enabled {
for _, paths := range msg.MultiPathList {
z.updatePathByNexthopCache(paths)
if body, isWithdraw := newIPRouteBody(paths); body != nil {
z.client.SendIPRoute(0, body, isWithdraw)
}
if body := newNexthopRegisterBody(paths, z.nexthopCache); body != nil {
z.client.SendNexthopRegister(0, body, false)
for i := range msg.Vrf {
if body, isWithdraw := newIPRouteBody(paths, i, z); body != nil {
z.client.SendIPRoute(i, body, isWithdraw)
}
if body := newNexthopRegisterBody(paths, z.nexthopCache); body != nil {
z.client.SendNexthopRegister(i, body, false)
}
}
}
} else {
z.updatePathByNexthopCache(msg.PathList)
for _, path := range msg.PathList {
vrfs := []uint32{0}
if msg.Vrf != nil {
if v, ok := msg.Vrf[path.GetNlri().String()]; ok {
vrfs = append(vrfs, v)
}
}
for _, i := range vrfs {
if body, isWithdraw := newIPRouteBody([]*table.Path{path}); body != nil {
z.client.SendIPRoute(i, body, isWithdraw)
for i := range msg.Vrf {
if body, isWithdraw := newIPRouteBody([]*table.Path{path}, i, z); body != nil {
err := z.client.SendIPRoute(i, body, isWithdraw)
if err != nil {
continue
}
}
if body := newNexthopRegisterBody([]*table.Path{path}, z.nexthopCache); body != nil {
z.client.SendNexthopRegister(i, body, false)
@@ -398,7 +448,7 @@ func (z *zebraClient) loop() {
}
}
}
case *WatchEventUpdate:
case *watchEventUpdate:
if body := newNexthopRegisterBody(msg.PathList, z.nexthopCache); body != nil {
vrfID := uint32(0)
for _, vrf := range z.server.listVrf() {
@@ -413,44 +463,120 @@ func (z *zebraClient) loop() {
}
}
func newZebraClient(s *BgpServer, url string, protos []string, version uint8, nhtEnable bool, nhtDelay uint8) (*zebraClient, error) {
func newZebraClient(s *BgpServer, url string, protos []string, version uint8, nhtEnable bool, nhtDelay uint8, mplsLabelRangeSize uint32, softwareName string) (*zebraClient, error) {
l := strings.SplitN(url, ":", 2)
if len(l) != 2 {
return nil, fmt.Errorf("unsupported url: %s", url)
}
var cli *zebra.Client
var err error
for _, ver := range []uint8{version, 2, 3, 4, 5} {
cli, err = zebra.NewClient(l[0], l[1], zebra.ROUTE_BGP, ver)
if err == nil {
var usingVersion uint8
var zapivers [zebra.MaxZapiVer - zebra.MinZapiVer + 1]uint8
zapivers[0] = version
for elem, ver := 1, zebra.MinZapiVer; elem < len(zapivers) && ver <= zebra.MaxZapiVer; elem++ {
if version == ver && ver < zebra.MaxZapiVer {
ver++
}
zapivers[elem] = ver
ver++
}
for elem, ver := range zapivers {
cli, err = zebra.NewClient(l[0], l[1], zebra.RouteBGP, ver, softwareName, mplsLabelRangeSize)
if cli != nil && err == nil {
usingVersion = ver
break
}
// Retry with another Zebra message version
log.WithFields(log.Fields{
"Topic": "Zebra",
}).Warnf("cannot connect to Zebra with message version %d. going to retry another version...", ver)
}).Warnf("cannot connect to Zebra with message version %d.", ver)
if elem < len(zapivers)-1 {
log.WithFields(log.Fields{
"Topic": "Zebra",
}).Warnf("going to retry another version %d.", zapivers[elem+1])
}
}
if cli == nil {
if cli == nil || err != nil {
return nil, err
}
log.WithFields(log.Fields{
"Topic": "Zebra",
}).Infof("success to connect to Zebra with message version %d.", usingVersion)
// Note: HELLO/ROUTER_ID_ADD messages are automatically sent to negotiate
// the Zebra message version in zebra.NewClient().
// cli.SendHello()
// cli.SendRouterIDAdd()
cli.SendInterfaceAdd()
for _, typ := range protos {
t, err := zebra.RouteTypeFromString(typ, version)
t, err := zebra.RouteTypeFromString(typ, version, softwareName)
if err != nil {
return nil, err
}
cli.SendRedistribute(t, zebra.VRF_DEFAULT)
cli.SendRedistribute(t, zebra.DefaultVrf)
}
w := &zebraClient{
client: cli,
server: s,
nexthopCache: make(nexthopStateCache),
dead: make(chan struct{}),
pathVrfMap: make(map[*table.Path]uint32),
mplsLabel: mplsLabelParameter{
rangeSize: mplsLabelRangeSize,
maps: make(map[uint64]*table.Bitmap),
},
dead: make(chan struct{}),
}
go w.loop()
if mplsLabelRangeSize > 0 && cli.SupportMpls() {
if err = cli.SendGetLabelChunk(&zebra.GetLabelChunkBody{ChunkSize: mplsLabelRangeSize}); err != nil {
return nil, err
}
}
return w, nil
}
func (z *zebraClient) assignMplsLabel() (uint32, error) {
if z.mplsLabel.maps == nil {
return 0, nil
}
var label uint32
for startEnd, bitmap := range z.mplsLabel.maps {
start := uint32(startEnd >> 32)
end := uint32(startEnd & 0xffffffff)
l, err := bitmap.FindandSetZeroBit()
if err == nil && start+uint32(l) <= end {
label = start + uint32(l)
break
}
}
if label == 0 {
return 0, fmt.Errorf("failed to assign new MPLS label")
}
return label, nil
}
func (z *zebraClient) assignAndSendVrfMplsLabel(vrf *table.Vrf) error {
var err error
if vrf.MplsLabel, err = z.assignMplsLabel(); vrf.MplsLabel > 0 { // success
if err = z.client.SendVrfLabel(vrf.MplsLabel, vrf.Id); err != nil {
return err
}
} else if vrf.MplsLabel == 0 { // GetLabelChunk is not performed
z.mplsLabel.unassignedVrf = append(z.mplsLabel.unassignedVrf, vrf)
}
return err
}
func (z *zebraClient) releaseMplsLabel(label uint32) {
if z.mplsLabel.maps == nil {
return
}
for startEnd, bitmap := range z.mplsLabel.maps {
start := uint32(startEnd >> 32)
end := uint32(startEnd & 0xffffffff)
if start <= label && label <= end {
bitmap.Unflag(uint(label - start))
return
}
}
}