diff -Nru gobgp-1.32/api/attribute.go gobgp-1.33/api/attribute.go --- gobgp-1.32/api/attribute.go 1970-01-01 00:00:00.000000000 +0000 +++ gobgp-1.33/api/attribute.go 2018-07-01 12:06:57.000000000 +0000 @@ -0,0 +1,1334 @@ +// Copyright (C) 2018 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 gobgpapi + +import ( + "fmt" + "net" + + "github.com/golang/protobuf/proto" + "github.com/golang/protobuf/ptypes" + "github.com/golang/protobuf/ptypes/any" + log "github.com/sirupsen/logrus" + + "github.com/osrg/gobgp/packet/bgp" +) + +func NewOriginAttributeFromNative(a *bgp.PathAttributeOrigin) *OriginAttribute { + return &OriginAttribute{ + Origin: uint32(a.Value), + } +} + +func (a *OriginAttribute) ToNative() (*bgp.PathAttributeOrigin, error) { + return bgp.NewPathAttributeOrigin(uint8(a.Origin)), nil +} + +func NewAsPathAttributeFromNative(a *bgp.PathAttributeAsPath) *AsPathAttribute { + segments := make([]*AsSegment, 0, len(a.Value)) + for _, param := range a.Value { + segments = append(segments, &AsSegment{ + Type: uint32(param.GetType()), + Numbers: param.GetAS(), + }) + } + return &AsPathAttribute{ + Segments: segments, + } +} + +func (a *AsPathAttribute) ToNative() (*bgp.PathAttributeAsPath, error) { + params := make([]bgp.AsPathParamInterface, 0, len(a.Segments)) + for _, segment := range a.Segments { + params = append(params, bgp.NewAs4PathParam(uint8(segment.Type), segment.Numbers)) + } + return bgp.NewPathAttributeAsPath(params), nil +} + +func NewNextHopAttributeFromNative(a *bgp.PathAttributeNextHop) *NextHopAttribute { + return &NextHopAttribute{ + NextHop: a.Value.String(), + } +} + +func (a *NextHopAttribute) ToNative() (*bgp.PathAttributeNextHop, error) { + nexthop := net.ParseIP(a.NextHop).To4() + if nexthop == nil { + return nil, fmt.Errorf("invalid nexthop address: %s", a.NextHop) + } + return bgp.NewPathAttributeNextHop(a.NextHop), nil +} + +func NewMultiExitDiscAttributeFromNative(a *bgp.PathAttributeMultiExitDisc) *MultiExitDiscAttribute { + return &MultiExitDiscAttribute{ + Med: a.Value, + } +} + +func (a *MultiExitDiscAttribute) ToNative() (*bgp.PathAttributeMultiExitDisc, error) { + return bgp.NewPathAttributeMultiExitDisc(a.Med), nil +} + +func NewLocalPrefAttributeFromNative(a *bgp.PathAttributeLocalPref) *LocalPrefAttribute { + return &LocalPrefAttribute{ + LocalPref: a.Value, + } +} + +func (a *LocalPrefAttribute) ToNative() (*bgp.PathAttributeLocalPref, error) { + return bgp.NewPathAttributeLocalPref(a.LocalPref), nil +} + +func NewAtomicAggregateAttributeFromNative(a *bgp.PathAttributeAtomicAggregate) *AtomicAggregateAttribute { + return &AtomicAggregateAttribute{} +} + +func (a *AtomicAggregateAttribute) ToNative() (*bgp.PathAttributeAtomicAggregate, error) { + return bgp.NewPathAttributeAtomicAggregate(), nil +} + +func NewAggregatorAttributeFromNative(a *bgp.PathAttributeAggregator) *AggregatorAttribute { + return &AggregatorAttribute{ + As: a.Value.AS, + Address: a.Value.Address.String(), + } +} + +func (a *AggregatorAttribute) ToNative() (*bgp.PathAttributeAggregator, error) { + if net.ParseIP(a.Address).To4() == nil { + return nil, fmt.Errorf("invalid aggregator address: %s", a.Address) + } + return bgp.NewPathAttributeAggregator(a.As, a.Address), nil +} + +func NewCommunitiesAttributeFromNative(a *bgp.PathAttributeCommunities) *CommunitiesAttribute { + return &CommunitiesAttribute{ + Communities: a.Value, + } +} + +func (a *CommunitiesAttribute) ToNative() (*bgp.PathAttributeCommunities, error) { + return bgp.NewPathAttributeCommunities(a.Communities), nil +} + +func NewOriginatorIdAttributeFromNative(a *bgp.PathAttributeOriginatorId) *OriginatorIdAttribute { + return &OriginatorIdAttribute{ + Id: a.Value.String(), + } +} + +func (a *OriginatorIdAttribute) ToNative() (*bgp.PathAttributeOriginatorId, error) { + if net.ParseIP(a.Id).To4() == nil { + return nil, fmt.Errorf("invalid originator id: %s", a.Id) + } + return bgp.NewPathAttributeOriginatorId(a.Id), nil +} + +func NewClusterListAttributeFromNative(a *bgp.PathAttributeClusterList) *ClusterListAttribute { + ids := make([]string, 0, len(a.Value)) + for _, id := range a.Value { + ids = append(ids, id.String()) + } + return &ClusterListAttribute{ + Ids: ids, + } +} + +func (a *ClusterListAttribute) ToNative() (*bgp.PathAttributeClusterList, error) { + for _, id := range a.Ids { + if net.ParseIP(id).To4() == nil { + return nil, fmt.Errorf("invalid cluster list: %s", a.Ids) + } + } + return bgp.NewPathAttributeClusterList(a.Ids), nil +} + +func MarshalRD(rd bgp.RouteDistinguisherInterface) *any.Any { + var r proto.Message + switch v := rd.(type) { + case *bgp.RouteDistinguisherTwoOctetAS: + r = &RouteDistinguisherTwoOctetAS{ + Admin: uint32(v.Admin), + Assigned: v.Assigned, + } + case *bgp.RouteDistinguisherIPAddressAS: + r = &RouteDistinguisherIPAddress{ + Admin: v.Admin.String(), + Assigned: uint32(v.Assigned), + } + case *bgp.RouteDistinguisherFourOctetAS: + r = &RouteDistinguisherFourOctetAS{ + Admin: v.Admin, + Assigned: uint32(v.Assigned), + } + default: + log.WithFields(log.Fields{ + "Topic": "protobuf", + "RD": rd, + }).Warn("invalid rd type to marshal") + return nil + } + a, _ := ptypes.MarshalAny(r) + return a +} + +func UnmarshalRD(a *any.Any) (bgp.RouteDistinguisherInterface, error) { + var value ptypes.DynamicAny + if err := ptypes.UnmarshalAny(a, &value); err != nil { + return nil, fmt.Errorf("failed to unmarshal route distinguisher: %s", err) + } + switch v := value.Message.(type) { + case *RouteDistinguisherTwoOctetAS: + return bgp.NewRouteDistinguisherTwoOctetAS(uint16(v.Admin), v.Assigned), nil + case *RouteDistinguisherIPAddress: + rd := bgp.NewRouteDistinguisherIPAddressAS(v.Admin, uint16(v.Assigned)) + if rd == nil { + return nil, fmt.Errorf("invalid address for route distinguisher: %s", v.Admin) + } + return rd, nil + case *RouteDistinguisherFourOctetAS: + return bgp.NewRouteDistinguisherFourOctetAS(v.Admin, uint16(v.Assigned)), nil + } + return nil, fmt.Errorf("invalid route distinguisher type: %s", a.TypeUrl) +} + +func NewEthernetSegmentIdentifierFromNative(a *bgp.EthernetSegmentIdentifier) *EthernetSegmentIdentifier { + return &EthernetSegmentIdentifier{ + Type: uint32(a.Type), + Value: a.Value, + } +} + +func (a *EthernetSegmentIdentifier) ToNative() (*bgp.EthernetSegmentIdentifier, error) { + return &bgp.EthernetSegmentIdentifier{ + Type: bgp.ESIType(a.Type), + Value: a.Value, + }, nil +} + +func MarshalFlowSpecRules(values []bgp.FlowSpecComponentInterface) []*any.Any { + rules := make([]*any.Any, 0, len(values)) + for _, value := range values { + var rule proto.Message + switch v := value.(type) { + case *bgp.FlowSpecDestinationPrefix: + rule = &FlowSpecIPPrefix{ + Type: uint32(bgp.FLOW_SPEC_TYPE_DST_PREFIX), + PrefixLen: uint32(v.Prefix.(*bgp.IPAddrPrefix).Length), + Prefix: v.Prefix.(*bgp.IPAddrPrefix).Prefix.String(), + } + case *bgp.FlowSpecSourcePrefix: + rule = &FlowSpecIPPrefix{ + Type: uint32(bgp.FLOW_SPEC_TYPE_SRC_PREFIX), + PrefixLen: uint32(v.Prefix.(*bgp.IPAddrPrefix).Length), + Prefix: v.Prefix.(*bgp.IPAddrPrefix).Prefix.String(), + } + case *bgp.FlowSpecDestinationPrefix6: + rule = &FlowSpecIPPrefix{ + Type: uint32(bgp.FLOW_SPEC_TYPE_DST_PREFIX), + PrefixLen: uint32(v.Prefix.(*bgp.IPv6AddrPrefix).Length), + Prefix: v.Prefix.(*bgp.IPv6AddrPrefix).Prefix.String(), + Offset: uint32(v.Offset), + } + case *bgp.FlowSpecSourcePrefix6: + rule = &FlowSpecIPPrefix{ + Type: uint32(bgp.FLOW_SPEC_TYPE_SRC_PREFIX), + PrefixLen: uint32(v.Prefix.(*bgp.IPv6AddrPrefix).Length), + Prefix: v.Prefix.(*bgp.IPv6AddrPrefix).Prefix.String(), + Offset: uint32(v.Offset), + } + case *bgp.FlowSpecSourceMac: + rule = &FlowSpecMAC{ + Type: uint32(bgp.FLOW_SPEC_TYPE_SRC_MAC), + Address: v.Mac.String(), + } + case *bgp.FlowSpecDestinationMac: + rule = &FlowSpecMAC{ + Type: uint32(bgp.FLOW_SPEC_TYPE_DST_MAC), + Address: v.Mac.String(), + } + case *bgp.FlowSpecComponent: + items := make([]*FlowSpecComponentItem, 0, len(v.Items)) + for _, i := range v.Items { + items = append(items, &FlowSpecComponentItem{ + Op: uint32(i.Op), + Value: i.Value, + }) + } + rule = &FlowSpecComponent{ + Type: uint32(v.Type()), + Items: items, + } + } + a, _ := ptypes.MarshalAny(rule) + rules = append(rules, a) + } + return rules +} + +func UnmarshalFlowSpecRules(values []*any.Any) ([]bgp.FlowSpecComponentInterface, error) { + rules := make([]bgp.FlowSpecComponentInterface, 0, len(values)) + for _, an := range values { + var rule bgp.FlowSpecComponentInterface + var value ptypes.DynamicAny + if err := ptypes.UnmarshalAny(an, &value); err != nil { + return nil, fmt.Errorf("failed to unmarshal flow spec component: %s", err) + } + switch v := value.Message.(type) { + case *FlowSpecIPPrefix: + typ := bgp.BGPFlowSpecType(v.Type) + isIPv4 := net.ParseIP(v.Prefix).To4() != nil + switch { + case typ == bgp.FLOW_SPEC_TYPE_DST_PREFIX && isIPv4: + rule = bgp.NewFlowSpecDestinationPrefix(bgp.NewIPAddrPrefix(uint8(v.PrefixLen), v.Prefix)) + case typ == bgp.FLOW_SPEC_TYPE_SRC_PREFIX && isIPv4: + rule = bgp.NewFlowSpecSourcePrefix(bgp.NewIPAddrPrefix(uint8(v.PrefixLen), v.Prefix)) + case typ == bgp.FLOW_SPEC_TYPE_DST_PREFIX && !isIPv4: + rule = bgp.NewFlowSpecDestinationPrefix6(bgp.NewIPv6AddrPrefix(uint8(v.PrefixLen), v.Prefix), uint8(v.Offset)) + case typ == bgp.FLOW_SPEC_TYPE_SRC_PREFIX && !isIPv4: + rule = bgp.NewFlowSpecSourcePrefix6(bgp.NewIPv6AddrPrefix(uint8(v.PrefixLen), v.Prefix), uint8(v.Offset)) + } + case *FlowSpecMAC: + typ := bgp.BGPFlowSpecType(v.Type) + mac, err := net.ParseMAC(v.Address) + if err != nil { + return nil, fmt.Errorf("invalid mac address for %s flow spec component: %s", typ.String(), v.Address) + } + switch typ { + case bgp.FLOW_SPEC_TYPE_SRC_MAC: + rule = bgp.NewFlowSpecSourceMac(mac) + case bgp.FLOW_SPEC_TYPE_DST_MAC: + rule = bgp.NewFlowSpecDestinationMac(mac) + } + case *FlowSpecComponent: + items := make([]*bgp.FlowSpecComponentItem, 0, len(v.Items)) + for _, item := range v.Items { + items = append(items, bgp.NewFlowSpecComponentItem(uint8(item.Op), item.Value)) + } + rule = bgp.NewFlowSpecComponent(bgp.BGPFlowSpecType(v.Type), items) + } + if rule == nil { + return nil, fmt.Errorf("invalid flow spec component: %v", value.Message) + } + rules = append(rules, rule) + } + return rules, nil +} + +func MarshalNLRI(value bgp.AddrPrefixInterface) *any.Any { + var nlri proto.Message + + switch v := value.(type) { + case *bgp.IPAddrPrefix: + nlri = &IPAddressPrefix{ + PrefixLen: uint32(v.Length), + Prefix: v.Prefix.String(), + } + case *bgp.IPv6AddrPrefix: + nlri = &IPAddressPrefix{ + PrefixLen: uint32(v.Length), + Prefix: v.Prefix.String(), + } + case *bgp.LabeledIPAddrPrefix: + nlri = &LabeledIPAddressPrefix{ + Labels: v.Labels.Labels, + PrefixLen: uint32(v.IPPrefixLen()), + Prefix: v.Prefix.String(), + } + case *bgp.LabeledIPv6AddrPrefix: + nlri = &LabeledIPAddressPrefix{ + Labels: v.Labels.Labels, + PrefixLen: uint32(v.IPPrefixLen()), + Prefix: v.Prefix.String(), + } + case *bgp.EncapNLRI: + nlri = &EncapsulationNLRI{ + Address: v.String(), + } + case *bgp.Encapv6NLRI: + nlri = &EncapsulationNLRI{ + Address: v.String(), + } + case *bgp.EVPNNLRI: + switch r := v.RouteTypeData.(type) { + case *bgp.EVPNEthernetAutoDiscoveryRoute: + nlri = &EVPNEthernetAutoDiscoveryRoute{ + Rd: MarshalRD(r.RD), + Esi: NewEthernetSegmentIdentifierFromNative(&r.ESI), + EthernetTag: r.ETag, + Label: r.Label, + } + case *bgp.EVPNMacIPAdvertisementRoute: + nlri = &EVPNMACIPAdvertisementRoute{ + Rd: MarshalRD(r.RD), + Esi: NewEthernetSegmentIdentifierFromNative(&r.ESI), + EthernetTag: r.ETag, + MacAddress: r.MacAddress.String(), + IpAddress: r.IPAddress.String(), + Labels: r.Labels, + } + case *bgp.EVPNMulticastEthernetTagRoute: + nlri = &EVPNInclusiveMulticastEthernetTagRoute{ + Rd: MarshalRD(r.RD), + EthernetTag: r.ETag, + IpAddress: r.IPAddress.String(), + } + case *bgp.EVPNEthernetSegmentRoute: + nlri = &EVPNEthernetSegmentRoute{ + Rd: MarshalRD(r.RD), + Esi: NewEthernetSegmentIdentifierFromNative(&r.ESI), + IpAddress: r.IPAddress.String(), + } + case *bgp.EVPNIPPrefixRoute: + nlri = &EVPNIPPrefixRoute{ + Rd: MarshalRD(r.RD), + Esi: NewEthernetSegmentIdentifierFromNative(&r.ESI), + EthernetTag: r.ETag, + IpPrefix: r.IPPrefix.String(), + IpPrefixLen: uint32(r.IPPrefixLength), + Label: r.Label, + } + } + case *bgp.LabeledVPNIPAddrPrefix: + nlri = &LabeledVPNIPAddressPrefix{ + Labels: v.Labels.Labels, + Rd: MarshalRD(v.RD), + PrefixLen: uint32(v.IPPrefixLen()), + Prefix: v.Prefix.String(), + } + case *bgp.LabeledVPNIPv6AddrPrefix: + nlri = &LabeledVPNIPAddressPrefix{ + Labels: v.Labels.Labels, + Rd: MarshalRD(v.RD), + PrefixLen: uint32(v.IPPrefixLen()), + Prefix: v.Prefix.String(), + } + case *bgp.RouteTargetMembershipNLRI: + nlri = &RouteTargetMembershipNLRI{ + As: v.AS, + Rt: MarshalRT(v.RouteTarget), + } + case *bgp.FlowSpecIPv4Unicast: + nlri = &FlowSpecNLRI{ + Rules: MarshalFlowSpecRules(v.Value), + } + case *bgp.FlowSpecIPv6Unicast: + nlri = &FlowSpecNLRI{ + Rules: MarshalFlowSpecRules(v.Value), + } + case *bgp.FlowSpecIPv4VPN: + nlri = &VPNFlowSpecNLRI{ + Rd: MarshalRD(v.RD()), + Rules: MarshalFlowSpecRules(v.Value), + } + case *bgp.FlowSpecIPv6VPN: + nlri = &VPNFlowSpecNLRI{ + Rd: MarshalRD(v.RD()), + Rules: MarshalFlowSpecRules(v.Value), + } + case *bgp.FlowSpecL2VPN: + nlri = &VPNFlowSpecNLRI{ + Rd: MarshalRD(v.RD()), + Rules: MarshalFlowSpecRules(v.Value), + } + } + + an, _ := ptypes.MarshalAny(nlri) + return an +} + +func MarshalNLRIs(values []bgp.AddrPrefixInterface) []*any.Any { + nlris := make([]*any.Any, 0, len(values)) + for _, value := range values { + nlris = append(nlris, MarshalNLRI(value)) + } + return nlris +} + +func UnmarshalNLRI(rf bgp.RouteFamily, an *any.Any) (bgp.AddrPrefixInterface, error) { + var nlri bgp.AddrPrefixInterface + + var value ptypes.DynamicAny + if err := ptypes.UnmarshalAny(an, &value); err != nil { + return nil, fmt.Errorf("failed to unmarshal nlri: %s", err) + } + + switch v := value.Message.(type) { + case *IPAddressPrefix: + switch rf { + case bgp.RF_IPv4_UC: + nlri = bgp.NewIPAddrPrefix(uint8(v.PrefixLen), v.Prefix) + case bgp.RF_IPv6_UC: + nlri = bgp.NewIPv6AddrPrefix(uint8(v.PrefixLen), v.Prefix) + } + case *LabeledIPAddressPrefix: + switch rf { + case bgp.RF_IPv4_MPLS: + nlri = bgp.NewLabeledIPAddrPrefix(uint8(v.PrefixLen), v.Prefix, *bgp.NewMPLSLabelStack(v.Labels...)) + case bgp.RF_IPv6_MPLS: + nlri = bgp.NewLabeledIPv6AddrPrefix(uint8(v.PrefixLen), v.Prefix, *bgp.NewMPLSLabelStack(v.Labels...)) + } + case *EncapsulationNLRI: + switch rf { + case bgp.RF_IPv4_ENCAP: + nlri = bgp.NewEncapNLRI(v.Address) + case bgp.RF_IPv6_ENCAP: + nlri = bgp.NewEncapv6NLRI(v.Address) + } + case *EVPNEthernetAutoDiscoveryRoute: + if rf == bgp.RF_EVPN { + rd, err := UnmarshalRD(v.Rd) + if err != nil { + return nil, err + } + esi, err := v.Esi.ToNative() + if err != nil { + return nil, err + } + nlri = bgp.NewEVPNEthernetAutoDiscoveryRoute(rd, *esi, v.EthernetTag, v.Label) + } + case *EVPNMACIPAdvertisementRoute: + if rf == bgp.RF_EVPN { + rd, err := UnmarshalRD(v.Rd) + if err != nil { + return nil, err + } + esi, err := v.Esi.ToNative() + if err != nil { + return nil, err + } + nlri = bgp.NewEVPNMacIPAdvertisementRoute(rd, *esi, v.EthernetTag, v.MacAddress, v.IpAddress, v.Labels) + } + case *EVPNInclusiveMulticastEthernetTagRoute: + if rf == bgp.RF_EVPN { + rd, err := UnmarshalRD(v.Rd) + if err != nil { + return nil, err + } + nlri = bgp.NewEVPNMulticastEthernetTagRoute(rd, v.EthernetTag, v.IpAddress) + } + case *EVPNEthernetSegmentRoute: + if rf == bgp.RF_EVPN { + rd, err := UnmarshalRD(v.Rd) + if err != nil { + return nil, err + } + esi, err := v.Esi.ToNative() + if err != nil { + return nil, err + } + nlri = bgp.NewEVPNEthernetSegmentRoute(rd, *esi, v.IpAddress) + } + case *EVPNIPPrefixRoute: + if rf == bgp.RF_EVPN { + rd, err := UnmarshalRD(v.Rd) + if err != nil { + return nil, err + } + esi, err := v.Esi.ToNative() + if err != nil { + return nil, err + } + nlri = bgp.NewEVPNIPPrefixRoute(rd, *esi, v.EthernetTag, uint8(v.IpPrefixLen), v.IpPrefix, v.GwAddress, v.Label) + } + case *LabeledVPNIPAddressPrefix: + rd, err := UnmarshalRD(v.Rd) + if err != nil { + return nil, err + } + switch rf { + case bgp.RF_IPv4_VPN: + nlri = bgp.NewLabeledVPNIPAddrPrefix(uint8(v.PrefixLen), v.Prefix, *bgp.NewMPLSLabelStack(v.Labels...), rd) + case bgp.RF_IPv6_VPN: + nlri = bgp.NewLabeledVPNIPv6AddrPrefix(uint8(v.PrefixLen), v.Prefix, *bgp.NewMPLSLabelStack(v.Labels...), rd) + } + case *RouteTargetMembershipNLRI: + rt, err := UnmarshalRT(v.Rt) + if err != nil { + return nil, err + } + nlri = bgp.NewRouteTargetMembershipNLRI(v.As, rt) + case *FlowSpecNLRI: + rules, err := UnmarshalFlowSpecRules(v.Rules) + if err != nil { + return nil, err + } + switch rf { + case bgp.RF_FS_IPv4_UC: + nlri = bgp.NewFlowSpecIPv4Unicast(rules) + case bgp.RF_FS_IPv6_UC: + nlri = bgp.NewFlowSpecIPv6Unicast(rules) + } + case *VPNFlowSpecNLRI: + rd, err := UnmarshalRD(v.Rd) + if err != nil { + return nil, err + } + rules, err := UnmarshalFlowSpecRules(v.Rules) + if err != nil { + return nil, err + } + switch rf { + case bgp.RF_FS_IPv4_VPN: + nlri = bgp.NewFlowSpecIPv4VPN(rd, rules) + case bgp.RF_FS_IPv6_VPN: + nlri = bgp.NewFlowSpecIPv6VPN(rd, rules) + case bgp.RF_FS_L2_VPN: + nlri = bgp.NewFlowSpecL2VPN(rd, rules) + } + } + + if nlri == nil { + return nil, fmt.Errorf("invalid nlri for %s family: %s", rf.String(), value.Message) + } + + return nlri, nil +} + +func UnmarshalNLRIs(rf bgp.RouteFamily, values []*any.Any) ([]bgp.AddrPrefixInterface, error) { + nlris := make([]bgp.AddrPrefixInterface, 0, len(values)) + for _, an := range values { + nlri, err := UnmarshalNLRI(rf, an) + if err != nil { + return nil, err + } + nlris = append(nlris, nlri) + } + return nlris, nil +} + +func NewMpReachNLRIAttributeFromNative(a *bgp.PathAttributeMpReachNLRI) *MpReachNLRIAttribute { + var nexthops []string + if a.SAFI == bgp.SAFI_FLOW_SPEC_UNICAST || a.SAFI == bgp.SAFI_FLOW_SPEC_VPN { + nexthops = nil + } else { + nexthops = []string{a.Nexthop.String()} + if a.LinkLocalNexthop != nil { + nexthops = append(nexthops, a.LinkLocalNexthop.String()) + } + } + return &MpReachNLRIAttribute{ + Family: uint32(bgp.AfiSafiToRouteFamily(a.AFI, a.SAFI)), + NextHops: nexthops, + Nlris: MarshalNLRIs(a.Value), + } +} + +func (a *MpReachNLRIAttribute) ToNative() (*bgp.PathAttributeMpReachNLRI, error) { + rf := bgp.RouteFamily(a.Family) + nlris, err := UnmarshalNLRIs(rf, a.Nlris) + if err != nil { + return nil, err + } + afi, safi := bgp.RouteFamilyToAfiSafi(rf) + nexthop := "0.0.0.0" + var linkLocalNexthop net.IP + if afi == bgp.AFI_IP6 { + nexthop = "::" + if len(a.NextHops) > 1 { + linkLocalNexthop = net.ParseIP(a.NextHops[1]).To16() + if linkLocalNexthop == nil { + return nil, fmt.Errorf("invalid nexthop: %s", a.NextHops[1]) + } + } + } + if safi == bgp.SAFI_FLOW_SPEC_UNICAST || safi == bgp.SAFI_FLOW_SPEC_VPN { + nexthop = "" + } else if len(a.NextHops) > 0 { + nexthop = a.NextHops[0] + if net.ParseIP(nexthop) == nil { + return nil, fmt.Errorf("invalid nexthop: %s", nexthop) + } + } + attr := bgp.NewPathAttributeMpReachNLRI(nexthop, nlris) + attr.LinkLocalNexthop = linkLocalNexthop + return attr, nil +} + +func NewMpUnreachNLRIAttributeFromNative(a *bgp.PathAttributeMpUnreachNLRI) *MpUnreachNLRIAttribute { + return &MpUnreachNLRIAttribute{ + Family: uint32(bgp.AfiSafiToRouteFamily(a.AFI, a.SAFI)), + Nlris: MarshalNLRIs(a.Value), + } +} + +func (a *MpUnreachNLRIAttribute) ToNative() (*bgp.PathAttributeMpUnreachNLRI, error) { + rf := bgp.RouteFamily(a.Family) + nlris, err := UnmarshalNLRIs(rf, a.Nlris) + if err != nil { + return nil, err + } + return bgp.NewPathAttributeMpUnreachNLRI(nlris), nil +} + +func MarshalRT(rt bgp.ExtendedCommunityInterface) *any.Any { + var r proto.Message + switch v := rt.(type) { + case *bgp.TwoOctetAsSpecificExtended: + r = &TwoOctetAsSpecificExtended{ + IsTransitive: true, + SubType: uint32(bgp.EC_SUBTYPE_ROUTE_TARGET), + As: uint32(v.AS), + LocalAdmin: uint32(v.LocalAdmin), + } + case *bgp.IPv4AddressSpecificExtended: + r = &IPv4AddressSpecificExtended{ + IsTransitive: true, + SubType: uint32(bgp.EC_SUBTYPE_ROUTE_TARGET), + Address: v.IPv4.String(), + LocalAdmin: uint32(v.LocalAdmin), + } + case *bgp.FourOctetAsSpecificExtended: + r = &FourOctetAsSpecificExtended{ + IsTransitive: true, + SubType: uint32(bgp.EC_SUBTYPE_ROUTE_TARGET), + As: uint32(v.AS), + LocalAdmin: uint32(v.LocalAdmin), + } + default: + log.WithFields(log.Fields{ + "Topic": "protobuf", + "RT": rt, + }).Warn("invalid rt type to marshal") + return nil + } + a, _ := ptypes.MarshalAny(r) + return a +} + +func MarshalRTs(values []bgp.ExtendedCommunityInterface) []*any.Any { + rts := make([]*any.Any, 0, len(values)) + for _, rt := range values { + rts = append(rts, MarshalRT(rt)) + } + return rts +} + +func UnmarshalRT(a *any.Any) (bgp.ExtendedCommunityInterface, error) { + var value ptypes.DynamicAny + if err := ptypes.UnmarshalAny(a, &value); err != nil { + return nil, fmt.Errorf("failed to unmarshal route target: %s", err) + } + switch v := value.Message.(type) { + case *TwoOctetAsSpecificExtended: + return bgp.NewTwoOctetAsSpecificExtended(bgp.ExtendedCommunityAttrSubType(v.SubType), uint16(v.As), v.LocalAdmin, v.IsTransitive), nil + case *IPv4AddressSpecificExtended: + rt := bgp.NewIPv4AddressSpecificExtended(bgp.ExtendedCommunityAttrSubType(v.SubType), v.Address, uint16(v.LocalAdmin), v.IsTransitive) + if rt == nil { + return nil, fmt.Errorf("invalid address for ipv4 address specific route target: %s", v.Address) + } + return rt, nil + case *FourOctetAsSpecificExtended: + return bgp.NewFourOctetAsSpecificExtended(bgp.ExtendedCommunityAttrSubType(v.SubType), v.As, uint16(v.LocalAdmin), v.IsTransitive), nil + } + return nil, fmt.Errorf("invalid route target type: %s", a.TypeUrl) +} + +func UnmarshalRTs(values []*any.Any) ([]bgp.ExtendedCommunityInterface, error) { + rts := make([]bgp.ExtendedCommunityInterface, 0, len(values)) + for _, an := range values { + rt, err := UnmarshalRT(an) + if err != nil { + return nil, err + } + rts = append(rts, rt) + } + return rts, nil +} + +func NewExtendedCommunitiesAttributeFromNative(a *bgp.PathAttributeExtendedCommunities) *ExtendedCommunitiesAttribute { + communities := make([]*any.Any, 0, len(a.Value)) + for _, value := range a.Value { + var community proto.Message + switch v := value.(type) { + case *bgp.TwoOctetAsSpecificExtended: + community = &TwoOctetAsSpecificExtended{ + IsTransitive: v.IsTransitive, + SubType: uint32(v.SubType), + As: uint32(v.AS), + LocalAdmin: uint32(v.LocalAdmin), + } + case *bgp.IPv4AddressSpecificExtended: + community = &IPv4AddressSpecificExtended{ + IsTransitive: v.IsTransitive, + SubType: uint32(v.SubType), + Address: v.IPv4.String(), + LocalAdmin: uint32(v.LocalAdmin), + } + case *bgp.FourOctetAsSpecificExtended: + community = &FourOctetAsSpecificExtended{ + IsTransitive: v.IsTransitive, + SubType: uint32(v.SubType), + As: uint32(v.AS), + LocalAdmin: uint32(v.LocalAdmin), + } + case *bgp.ValidationExtended: + community = &ValidationExtended{ + State: uint32(v.State), + } + case *bgp.ColorExtended: + community = &ColorExtended{ + Color: v.Color, + } + case *bgp.EncapExtended: + community = &EncapExtended{ + TunnelType: uint32(v.TunnelType), + } + case *bgp.DefaultGatewayExtended: + community = &DefaultGatewayExtended{} + case *bgp.OpaqueExtended: + community = &OpaqueExtended{ + IsTransitive: v.IsTransitive, + Value: v.Value, + } + case *bgp.ESILabelExtended: + community = &ESILabelExtended{ + IsSingleActive: v.IsSingleActive, + Label: v.Label, + } + case *bgp.ESImportRouteTarget: + community = &ESImportRouteTarget{ + EsImport: v.ESImport.String(), + } + case *bgp.MacMobilityExtended: + community = &MacMobilityExtended{ + IsSticky: v.IsSticky, + SequenceNum: v.Sequence, + } + case *bgp.RouterMacExtended: + community = &RouterMacExtended{ + Mac: v.Mac.String(), + } + case *bgp.TrafficRateExtended: + community = &TrafficRateExtended{ + As: uint32(v.AS), + Rate: v.Rate, + } + case *bgp.TrafficActionExtended: + community = &TrafficActionExtended{ + Terminal: v.Terminal, + Sample: v.Sample, + } + case *bgp.RedirectTwoOctetAsSpecificExtended: + community = &RedirectTwoOctetAsSpecificExtended{ + As: uint32(v.AS), + LocalAdmin: v.LocalAdmin, + } + case *bgp.RedirectIPv4AddressSpecificExtended: + community = &RedirectIPv4AddressSpecificExtended{ + Address: v.IPv4.String(), + LocalAdmin: uint32(v.LocalAdmin), + } + case *bgp.RedirectFourOctetAsSpecificExtended: + community = &RedirectFourOctetAsSpecificExtended{ + As: v.AS, + LocalAdmin: uint32(v.LocalAdmin), + } + case *bgp.TrafficRemarkExtended: + community = &TrafficRemarkExtended{ + Dscp: uint32(v.DSCP), + } + case *bgp.UnknownExtended: + community = &UnknownExtended{ + Type: uint32(v.Type), + Value: v.Value, + } + default: + log.WithFields(log.Fields{ + "Topic": "protobuf", + "Community": value, + }).Warn("unsupported extended community") + return nil + } + an, _ := ptypes.MarshalAny(community) + communities = append(communities, an) + } + return &ExtendedCommunitiesAttribute{ + Communities: communities, + } +} + +func (a *ExtendedCommunitiesAttribute) ToNative() (*bgp.PathAttributeExtendedCommunities, error) { + communities := make([]bgp.ExtendedCommunityInterface, 0, len(a.Communities)) + for _, an := range a.Communities { + var community bgp.ExtendedCommunityInterface + var value ptypes.DynamicAny + if err := ptypes.UnmarshalAny(an, &value); err != nil { + return nil, fmt.Errorf("failed to unmarshal extended community: %s", err) + } + switch v := value.Message.(type) { + case *TwoOctetAsSpecificExtended: + community = bgp.NewTwoOctetAsSpecificExtended(bgp.ExtendedCommunityAttrSubType(v.SubType), uint16(v.As), v.LocalAdmin, v.IsTransitive) + case *IPv4AddressSpecificExtended: + community = bgp.NewIPv4AddressSpecificExtended(bgp.ExtendedCommunityAttrSubType(v.SubType), v.Address, uint16(v.LocalAdmin), v.IsTransitive) + case *FourOctetAsSpecificExtended: + community = bgp.NewFourOctetAsSpecificExtended(bgp.ExtendedCommunityAttrSubType(v.SubType), v.As, uint16(v.LocalAdmin), v.IsTransitive) + case *ValidationExtended: + community = bgp.NewValidationExtended(bgp.ValidationState(v.State)) + case *ColorExtended: + community = bgp.NewColorExtended(v.Color) + case *EncapExtended: + community = bgp.NewEncapExtended(bgp.TunnelType(v.TunnelType)) + case *DefaultGatewayExtended: + community = bgp.NewDefaultGatewayExtended() + case *OpaqueExtended: + community = bgp.NewOpaqueExtended(v.IsTransitive, v.Value) + case *ESILabelExtended: + community = bgp.NewESILabelExtended(v.Label, v.IsSingleActive) + case *ESImportRouteTarget: + community = bgp.NewESImportRouteTarget(v.EsImport) + case *MacMobilityExtended: + community = bgp.NewMacMobilityExtended(v.SequenceNum, v.IsSticky) + case *RouterMacExtended: + community = bgp.NewRoutersMacExtended(v.Mac) + case *TrafficRateExtended: + community = bgp.NewTrafficRateExtended(uint16(v.As), v.Rate) + case *TrafficActionExtended: + community = bgp.NewTrafficActionExtended(v.Terminal, v.Sample) + case *RedirectTwoOctetAsSpecificExtended: + community = bgp.NewRedirectTwoOctetAsSpecificExtended(uint16(v.As), v.LocalAdmin) + case *RedirectIPv4AddressSpecificExtended: + community = bgp.NewRedirectIPv4AddressSpecificExtended(v.Address, uint16(v.LocalAdmin)) + case *RedirectFourOctetAsSpecificExtended: + community = bgp.NewRedirectFourOctetAsSpecificExtended(v.As, uint16(v.LocalAdmin)) + case *TrafficRemarkExtended: + community = bgp.NewTrafficRemarkExtended(uint8(v.Dscp)) + case *UnknownExtended: + community = bgp.NewUnknownExtended(bgp.ExtendedCommunityAttrType(v.Type), v.Value) + } + if community == nil { + return nil, fmt.Errorf("invalid extended community: %v", value.Message) + } + communities = append(communities, community) + } + return bgp.NewPathAttributeExtendedCommunities(communities), nil +} + +func NewAs4PathAttributeFromNative(a *bgp.PathAttributeAs4Path) *As4PathAttribute { + segments := make([]*AsSegment, 0, len(a.Value)) + for _, param := range a.Value { + segments = append(segments, &AsSegment{ + Type: uint32(param.Type), + Numbers: param.AS, + }) + } + return &As4PathAttribute{ + Segments: segments, + } +} + +func (a *As4PathAttribute) ToNative() (*bgp.PathAttributeAs4Path, error) { + params := make([]*bgp.As4PathParam, 0, len(a.Segments)) + for _, segment := range a.Segments { + params = append(params, bgp.NewAs4PathParam(uint8(segment.Type), segment.Numbers)) + } + return bgp.NewPathAttributeAs4Path(params), nil +} + +func NewAs4AggregatorAttributeFromNative(a *bgp.PathAttributeAs4Aggregator) *As4AggregatorAttribute { + return &As4AggregatorAttribute{ + As: a.Value.AS, + Address: a.Value.Address.String(), + } +} + +func (a *As4AggregatorAttribute) ToNative() (*bgp.PathAttributeAs4Aggregator, error) { + if net.ParseIP(a.Address).To4() == nil { + return nil, fmt.Errorf("invalid as4 aggregator address: %s", a.Address) + } + return bgp.NewPathAttributeAs4Aggregator(a.As, a.Address), nil +} + +func NewPmsiTunnelAttributeFromNative(a *bgp.PathAttributePmsiTunnel) *PmsiTunnelAttribute { + var flags uint32 + if a.IsLeafInfoRequired { + flags |= 0x01 + } + id, _ := a.TunnelID.Serialize() + return &PmsiTunnelAttribute{ + Flags: flags, + Type: uint32(a.TunnelType), + Label: a.Label, + Id: id, + } +} + +func (a *PmsiTunnelAttribute) ToNative() (*bgp.PathAttributePmsiTunnel, error) { + typ := bgp.PmsiTunnelType(a.Type) + var isLeafInfoRequired bool + if a.Flags&0x01 > 0 { + isLeafInfoRequired = true + } + var id bgp.PmsiTunnelIDInterface + switch typ { + case bgp.PMSI_TUNNEL_TYPE_INGRESS_REPL: + ip := net.IP(a.Id) + if ip.To4() == nil && ip.To16() == nil { + return nil, fmt.Errorf("invalid pmsi tunnel identifier: %s", a.Id) + } + id = bgp.NewIngressReplTunnelID(ip.String()) + default: + id = bgp.NewDefaultPmsiTunnelID(a.Id) + } + return bgp.NewPathAttributePmsiTunnel(typ, isLeafInfoRequired, a.Label, id), nil +} + +func NewTunnelEncapAttributeFromNative(a *bgp.PathAttributeTunnelEncap) *TunnelEncapAttribute { + tlvs := make([]*TunnelEncapTLV, 0, len(a.Value)) + for _, v := range a.Value { + subTlvs := make([]*any.Any, 0, len(v.Value)) + for _, s := range v.Value { + var subTlv proto.Message + switch sv := s.(type) { + case *bgp.TunnelEncapSubTLVEncapsulation: + subTlv = &TunnelEncapSubTLVEncapsulation{ + Key: sv.Key, + Cookie: sv.Cookie, + } + case *bgp.TunnelEncapSubTLVProtocol: + subTlv = &TunnelEncapSubTLVProtocol{ + Protocol: uint32(sv.Protocol), + } + case *bgp.TunnelEncapSubTLVColor: + subTlv = &TunnelEncapSubTLVColor{ + Color: sv.Color, + } + case *bgp.TunnelEncapSubTLVUnknown: + subTlv = &TunnelEncapSubTLVUnknown{ + Type: uint32(sv.Type), + Value: sv.Value, + } + } + an, _ := ptypes.MarshalAny(subTlv) + subTlvs = append(subTlvs, an) + } + tlvs = append(tlvs, &TunnelEncapTLV{ + Type: uint32(v.Type), + Tlvs: subTlvs, + }) + } + return &TunnelEncapAttribute{ + Tlvs: tlvs, + } +} + +func (a *TunnelEncapAttribute) ToNative() (*bgp.PathAttributeTunnelEncap, error) { + tlvs := make([]*bgp.TunnelEncapTLV, 0, len(a.Tlvs)) + for _, tlv := range a.Tlvs { + subTlvs := make([]bgp.TunnelEncapSubTLVInterface, 0, len(tlv.Tlvs)) + for _, an := range tlv.Tlvs { + var subTlv bgp.TunnelEncapSubTLVInterface + var subValue ptypes.DynamicAny + if err := ptypes.UnmarshalAny(an, &subValue); err != nil { + return nil, fmt.Errorf("failed to unmarshal tunnel encapsulation attribute sub tlv: %s", err) + } + switch sv := subValue.Message.(type) { + case *TunnelEncapSubTLVEncapsulation: + subTlv = bgp.NewTunnelEncapSubTLVEncapsulation(sv.Key, sv.Cookie) + case *TunnelEncapSubTLVProtocol: + subTlv = bgp.NewTunnelEncapSubTLVProtocol(uint16(sv.Protocol)) + case *TunnelEncapSubTLVColor: + subTlv = bgp.NewTunnelEncapSubTLVColor(sv.Color) + case *TunnelEncapSubTLVUnknown: + subTlv = bgp.NewTunnelEncapSubTLVUnknown(bgp.EncapSubTLVType(sv.Type), sv.Value) + default: + return nil, fmt.Errorf("invalid tunnel encapsulation attribute sub tlv: %v", subValue.Message) + } + subTlvs = append(subTlvs, subTlv) + } + tlvs = append(tlvs, bgp.NewTunnelEncapTLV(bgp.TunnelType(tlv.Type), subTlvs)) + } + return bgp.NewPathAttributeTunnelEncap(tlvs), nil +} + +func NewIP6ExtendedCommunitiesAttributeFromNative(a *bgp.PathAttributeIP6ExtendedCommunities) *IP6ExtendedCommunitiesAttribute { + communities := make([]*any.Any, 0, len(a.Value)) + for _, value := range a.Value { + var community proto.Message + switch v := value.(type) { + case *bgp.IPv6AddressSpecificExtended: + community = &IPv6AddressSpecificExtended{ + IsTransitive: v.IsTransitive, + SubType: uint32(v.SubType), + Address: v.IPv6.String(), + LocalAdmin: uint32(v.LocalAdmin), + } + case *bgp.RedirectIPv6AddressSpecificExtended: + community = &RedirectIPv6AddressSpecificExtended{ + Address: v.IPv6.String(), + LocalAdmin: uint32(v.LocalAdmin), + } + default: + log.WithFields(log.Fields{ + "Topic": "protobuf", + "Attribute": value, + }).Warn("invalid ipv6 extended community") + return nil + } + an, _ := ptypes.MarshalAny(community) + communities = append(communities, an) + } + return &IP6ExtendedCommunitiesAttribute{ + Communities: communities, + } +} + +func (a *IP6ExtendedCommunitiesAttribute) ToNative() (*bgp.PathAttributeIP6ExtendedCommunities, error) { + communities := make([]bgp.ExtendedCommunityInterface, 0, len(a.Communities)) + for _, an := range a.Communities { + var community bgp.ExtendedCommunityInterface + var value ptypes.DynamicAny + if err := ptypes.UnmarshalAny(an, &value); err != nil { + return nil, fmt.Errorf("failed to unmarshal ipv6 extended community: %s", err) + } + switch v := value.Message.(type) { + case *IPv6AddressSpecificExtended: + community = bgp.NewIPv6AddressSpecificExtended(bgp.ExtendedCommunityAttrSubType(v.SubType), v.Address, uint16(v.LocalAdmin), v.IsTransitive) + case *RedirectIPv6AddressSpecificExtended: + community = bgp.NewRedirectIPv6AddressSpecificExtended(v.Address, uint16(v.LocalAdmin)) + } + if community == nil { + return nil, fmt.Errorf("invalid ipv6 extended community: %v", value.Message) + } + communities = append(communities, community) + } + return bgp.NewPathAttributeIP6ExtendedCommunities(communities), nil +} + +func NewAigpAttributeFromNative(a *bgp.PathAttributeAigp) *AigpAttribute { + tlvs := make([]*any.Any, 0, len(a.Values)) + for _, value := range a.Values { + var tlv proto.Message + switch v := value.(type) { + case *bgp.AigpTLVIgpMetric: + tlv = &AigpTLVIGPMetric{ + Metric: v.Metric, + } + case *bgp.AigpTLVDefault: + tlv = &AigpTLVUnknown{ + Type: uint32(v.Type()), + Value: v.Value, + } + } + an, _ := ptypes.MarshalAny(tlv) + tlvs = append(tlvs, an) + } + return &AigpAttribute{ + Tlvs: tlvs, + } +} + +func (a *AigpAttribute) ToNative() (*bgp.PathAttributeAigp, error) { + tlvs := make([]bgp.AigpTLVInterface, 0, len(a.Tlvs)) + for _, an := range a.Tlvs { + var tlv bgp.AigpTLVInterface + var value ptypes.DynamicAny + if err := ptypes.UnmarshalAny(an, &value); err != nil { + return nil, fmt.Errorf("failed to unmarshal aigp attribute tlv: %s", err) + } + switch v := value.Message.(type) { + case *AigpTLVIGPMetric: + tlv = bgp.NewAigpTLVIgpMetric(v.Metric) + case *AigpTLVUnknown: + tlv = bgp.NewAigpTLVDefault(bgp.AigpTLVType(v.Type), v.Value) + } + if tlv == nil { + return nil, fmt.Errorf("invalid aigp attribute tlv: %v", value.Message) + } + tlvs = append(tlvs, tlv) + } + return bgp.NewPathAttributeAigp(tlvs), nil +} + +func NewLargeCommunitiesAttributeFromNative(a *bgp.PathAttributeLargeCommunities) *LargeCommunitiesAttribute { + communities := make([]*LargeCommunity, 0, len(a.Values)) + for _, v := range a.Values { + communities = append(communities, &LargeCommunity{ + GlobalAdmin: v.ASN, + LocalData1: v.LocalData1, + LocalData2: v.LocalData2, + }) + } + return &LargeCommunitiesAttribute{ + Communities: communities, + } +} + +func (a *LargeCommunitiesAttribute) ToNative() (*bgp.PathAttributeLargeCommunities, error) { + communities := make([]*bgp.LargeCommunity, 0, len(a.Communities)) + for _, c := range a.Communities { + communities = append(communities, bgp.NewLargeCommunity(c.GlobalAdmin, c.LocalData1, c.LocalData2)) + } + return bgp.NewPathAttributeLargeCommunities(communities), nil +} + +func NewUnknownAttributeFromNative(a *bgp.PathAttributeUnknown) *UnknownAttribute { + return &UnknownAttribute{ + Flags: uint32(a.Flags), + Type: uint32(a.Type), + Value: a.Value, + } +} + +func (a *UnknownAttribute) ToNative() (*bgp.PathAttributeUnknown, error) { + return bgp.NewPathAttributeUnknown(bgp.BGPAttrFlag(a.Flags), bgp.BGPAttrType(a.Type), a.Value), nil +} + +func MarshalPathAttributes(attrList []bgp.PathAttributeInterface) []*any.Any { + anyList := make([]*any.Any, 0, len(attrList)) + for _, attr := range attrList { + switch a := attr.(type) { + case *bgp.PathAttributeOrigin: + n, _ := ptypes.MarshalAny(NewOriginAttributeFromNative(a)) + anyList = append(anyList, n) + case *bgp.PathAttributeAsPath: + n, _ := ptypes.MarshalAny(NewAsPathAttributeFromNative(a)) + anyList = append(anyList, n) + case *bgp.PathAttributeNextHop: + n, _ := ptypes.MarshalAny(NewNextHopAttributeFromNative(a)) + anyList = append(anyList, n) + case *bgp.PathAttributeMultiExitDisc: + n, _ := ptypes.MarshalAny(NewMultiExitDiscAttributeFromNative(a)) + anyList = append(anyList, n) + case *bgp.PathAttributeLocalPref: + n, _ := ptypes.MarshalAny(NewLocalPrefAttributeFromNative(a)) + anyList = append(anyList, n) + case *bgp.PathAttributeAtomicAggregate: + n, _ := ptypes.MarshalAny(NewAtomicAggregateAttributeFromNative(a)) + anyList = append(anyList, n) + case *bgp.PathAttributeAggregator: + n, _ := ptypes.MarshalAny(NewAggregatorAttributeFromNative(a)) + anyList = append(anyList, n) + case *bgp.PathAttributeCommunities: + n, _ := ptypes.MarshalAny(NewCommunitiesAttributeFromNative(a)) + anyList = append(anyList, n) + case *bgp.PathAttributeOriginatorId: + n, _ := ptypes.MarshalAny(NewOriginatorIdAttributeFromNative(a)) + anyList = append(anyList, n) + case *bgp.PathAttributeClusterList: + n, _ := ptypes.MarshalAny(NewClusterListAttributeFromNative(a)) + anyList = append(anyList, n) + case *bgp.PathAttributeMpReachNLRI: + n, _ := ptypes.MarshalAny(NewMpReachNLRIAttributeFromNative(a)) + anyList = append(anyList, n) + case *bgp.PathAttributeMpUnreachNLRI: + n, _ := ptypes.MarshalAny(NewMpUnreachNLRIAttributeFromNative(a)) + anyList = append(anyList, n) + case *bgp.PathAttributeExtendedCommunities: + n, _ := ptypes.MarshalAny(NewExtendedCommunitiesAttributeFromNative(a)) + anyList = append(anyList, n) + case *bgp.PathAttributeAs4Path: + n, _ := ptypes.MarshalAny(NewAs4PathAttributeFromNative(a)) + anyList = append(anyList, n) + case *bgp.PathAttributeAs4Aggregator: + n, _ := ptypes.MarshalAny(NewAs4AggregatorAttributeFromNative(a)) + anyList = append(anyList, n) + case *bgp.PathAttributePmsiTunnel: + n, _ := ptypes.MarshalAny(NewPmsiTunnelAttributeFromNative(a)) + anyList = append(anyList, n) + case *bgp.PathAttributeTunnelEncap: + n, _ := ptypes.MarshalAny(NewTunnelEncapAttributeFromNative(a)) + anyList = append(anyList, n) + case *bgp.PathAttributeIP6ExtendedCommunities: + n, _ := ptypes.MarshalAny(NewIP6ExtendedCommunitiesAttributeFromNative(a)) + anyList = append(anyList, n) + case *bgp.PathAttributeAigp: + n, _ := ptypes.MarshalAny(NewAigpAttributeFromNative(a)) + anyList = append(anyList, n) + case *bgp.PathAttributeLargeCommunities: + n, _ := ptypes.MarshalAny(NewLargeCommunitiesAttributeFromNative(a)) + anyList = append(anyList, n) + case *bgp.PathAttributeUnknown: + n, _ := ptypes.MarshalAny(NewUnknownAttributeFromNative(a)) + anyList = append(anyList, n) + } + } + return anyList +} + +func UnmarshalPathAttributes(values []*any.Any) ([]bgp.PathAttributeInterface, error) { + attrList := make([]bgp.PathAttributeInterface, 0, len(values)) + typeMap := make(map[bgp.BGPAttrType]struct{}) + for _, an := range values { + var attr bgp.PathAttributeInterface + var value ptypes.DynamicAny + err := ptypes.UnmarshalAny(an, &value) + if err != nil { + return nil, fmt.Errorf("failed to unmarshal path attribute: %s", err) + } + switch v := value.Message.(type) { + case *OriginAttribute: + attr, err = v.ToNative() + case *AsPathAttribute: + attr, err = v.ToNative() + case *NextHopAttribute: + attr, err = v.ToNative() + case *MultiExitDiscAttribute: + attr, err = v.ToNative() + case *LocalPrefAttribute: + attr, err = v.ToNative() + case *AtomicAggregateAttribute: + attr, err = v.ToNative() + case *AggregatorAttribute: + attr, err = v.ToNative() + case *CommunitiesAttribute: + attr, err = v.ToNative() + case *OriginatorIdAttribute: + attr, err = v.ToNative() + case *ClusterListAttribute: + attr, err = v.ToNative() + case *MpReachNLRIAttribute: + var nlri *bgp.PathAttributeMpReachNLRI + nlri, err = v.ToNative() + if len(nlri.Value) > 1 { + return nil, fmt.Errorf("multiple nlri in a single mp_reach_nlri are not supported") + } + attr = nlri + case *MpUnreachNLRIAttribute: + attr, err = v.ToNative() + case *ExtendedCommunitiesAttribute: + attr, err = v.ToNative() + case *As4PathAttribute: + attr, err = v.ToNative() + case *As4AggregatorAttribute: + attr, err = v.ToNative() + case *PmsiTunnelAttribute: + attr, err = v.ToNative() + case *TunnelEncapAttribute: + attr, err = v.ToNative() + case *IP6ExtendedCommunitiesAttribute: + attr, err = v.ToNative() + case *AigpAttribute: + attr, err = v.ToNative() + case *LargeCommunitiesAttribute: + attr, err = v.ToNative() + case *UnknownAttribute: + attr, err = v.ToNative() + } + if err != nil { + return nil, err + } + if attr == nil { + return nil, fmt.Errorf("invalid value type for path attribute: %s", value.Message) + } + if _, ok := typeMap[attr.GetType()]; ok { + return nil, fmt.Errorf("duplicated path attribute type: %d", attr.GetType()) + } + typeMap[attr.GetType()] = struct{}{} + attrList = append(attrList, attr) + } + return attrList, nil +} diff -Nru gobgp-1.32/api/attribute.pb.go gobgp-1.33/api/attribute.pb.go --- gobgp-1.32/api/attribute.pb.go 1970-01-01 00:00:00.000000000 +0000 +++ gobgp-1.33/api/attribute.pb.go 2018-07-01 12:06:57.000000000 +0000 @@ -0,0 +1,2086 @@ +// Code generated by protoc-gen-go. DO NOT EDIT. +// source: attribute.proto + +package gobgpapi + +import proto "github.com/golang/protobuf/proto" +import fmt "fmt" +import math "math" +import google_protobuf "github.com/golang/protobuf/ptypes/any" + +// Reference imports to suppress errors if they are not otherwise used. +var _ = proto.Marshal +var _ = fmt.Errorf +var _ = math.Inf + +type OriginAttribute struct { + Origin uint32 `protobuf:"varint,1,opt,name=origin" json:"origin,omitempty"` +} + +func (m *OriginAttribute) Reset() { *m = OriginAttribute{} } +func (m *OriginAttribute) String() string { return proto.CompactTextString(m) } +func (*OriginAttribute) ProtoMessage() {} +func (*OriginAttribute) Descriptor() ([]byte, []int) { return fileDescriptor1, []int{0} } + +func (m *OriginAttribute) GetOrigin() uint32 { + if m != nil { + return m.Origin + } + return 0 +} + +type AsSegment struct { + Type uint32 `protobuf:"varint,1,opt,name=type" json:"type,omitempty"` + Numbers []uint32 `protobuf:"varint,2,rep,packed,name=numbers" json:"numbers,omitempty"` +} + +func (m *AsSegment) Reset() { *m = AsSegment{} } +func (m *AsSegment) String() string { return proto.CompactTextString(m) } +func (*AsSegment) ProtoMessage() {} +func (*AsSegment) Descriptor() ([]byte, []int) { return fileDescriptor1, []int{1} } + +func (m *AsSegment) GetType() uint32 { + if m != nil { + return m.Type + } + return 0 +} + +func (m *AsSegment) GetNumbers() []uint32 { + if m != nil { + return m.Numbers + } + return nil +} + +type AsPathAttribute struct { + Segments []*AsSegment `protobuf:"bytes,1,rep,name=segments" json:"segments,omitempty"` +} + +func (m *AsPathAttribute) Reset() { *m = AsPathAttribute{} } +func (m *AsPathAttribute) String() string { return proto.CompactTextString(m) } +func (*AsPathAttribute) ProtoMessage() {} +func (*AsPathAttribute) Descriptor() ([]byte, []int) { return fileDescriptor1, []int{2} } + +func (m *AsPathAttribute) GetSegments() []*AsSegment { + if m != nil { + return m.Segments + } + return nil +} + +type NextHopAttribute struct { + NextHop string `protobuf:"bytes,1,opt,name=next_hop,json=nextHop" json:"next_hop,omitempty"` +} + +func (m *NextHopAttribute) Reset() { *m = NextHopAttribute{} } +func (m *NextHopAttribute) String() string { return proto.CompactTextString(m) } +func (*NextHopAttribute) ProtoMessage() {} +func (*NextHopAttribute) Descriptor() ([]byte, []int) { return fileDescriptor1, []int{3} } + +func (m *NextHopAttribute) GetNextHop() string { + if m != nil { + return m.NextHop + } + return "" +} + +type MultiExitDiscAttribute struct { + Med uint32 `protobuf:"varint,1,opt,name=med" json:"med,omitempty"` +} + +func (m *MultiExitDiscAttribute) Reset() { *m = MultiExitDiscAttribute{} } +func (m *MultiExitDiscAttribute) String() string { return proto.CompactTextString(m) } +func (*MultiExitDiscAttribute) ProtoMessage() {} +func (*MultiExitDiscAttribute) Descriptor() ([]byte, []int) { return fileDescriptor1, []int{4} } + +func (m *MultiExitDiscAttribute) GetMed() uint32 { + if m != nil { + return m.Med + } + return 0 +} + +type LocalPrefAttribute struct { + LocalPref uint32 `protobuf:"varint,1,opt,name=local_pref,json=localPref" json:"local_pref,omitempty"` +} + +func (m *LocalPrefAttribute) Reset() { *m = LocalPrefAttribute{} } +func (m *LocalPrefAttribute) String() string { return proto.CompactTextString(m) } +func (*LocalPrefAttribute) ProtoMessage() {} +func (*LocalPrefAttribute) Descriptor() ([]byte, []int) { return fileDescriptor1, []int{5} } + +func (m *LocalPrefAttribute) GetLocalPref() uint32 { + if m != nil { + return m.LocalPref + } + return 0 +} + +type AtomicAggregateAttribute struct { +} + +func (m *AtomicAggregateAttribute) Reset() { *m = AtomicAggregateAttribute{} } +func (m *AtomicAggregateAttribute) String() string { return proto.CompactTextString(m) } +func (*AtomicAggregateAttribute) ProtoMessage() {} +func (*AtomicAggregateAttribute) Descriptor() ([]byte, []int) { return fileDescriptor1, []int{6} } + +type AggregatorAttribute struct { + As uint32 `protobuf:"varint,2,opt,name=as" json:"as,omitempty"` + Address string `protobuf:"bytes,3,opt,name=address" json:"address,omitempty"` +} + +func (m *AggregatorAttribute) Reset() { *m = AggregatorAttribute{} } +func (m *AggregatorAttribute) String() string { return proto.CompactTextString(m) } +func (*AggregatorAttribute) ProtoMessage() {} +func (*AggregatorAttribute) Descriptor() ([]byte, []int) { return fileDescriptor1, []int{7} } + +func (m *AggregatorAttribute) GetAs() uint32 { + if m != nil { + return m.As + } + return 0 +} + +func (m *AggregatorAttribute) GetAddress() string { + if m != nil { + return m.Address + } + return "" +} + +type CommunitiesAttribute struct { + Communities []uint32 `protobuf:"varint,1,rep,packed,name=communities" json:"communities,omitempty"` +} + +func (m *CommunitiesAttribute) Reset() { *m = CommunitiesAttribute{} } +func (m *CommunitiesAttribute) String() string { return proto.CompactTextString(m) } +func (*CommunitiesAttribute) ProtoMessage() {} +func (*CommunitiesAttribute) Descriptor() ([]byte, []int) { return fileDescriptor1, []int{8} } + +func (m *CommunitiesAttribute) GetCommunities() []uint32 { + if m != nil { + return m.Communities + } + return nil +} + +type OriginatorIdAttribute struct { + Id string `protobuf:"bytes,1,opt,name=id" json:"id,omitempty"` +} + +func (m *OriginatorIdAttribute) Reset() { *m = OriginatorIdAttribute{} } +func (m *OriginatorIdAttribute) String() string { return proto.CompactTextString(m) } +func (*OriginatorIdAttribute) ProtoMessage() {} +func (*OriginatorIdAttribute) Descriptor() ([]byte, []int) { return fileDescriptor1, []int{9} } + +func (m *OriginatorIdAttribute) GetId() string { + if m != nil { + return m.Id + } + return "" +} + +type ClusterListAttribute struct { + Ids []string `protobuf:"bytes,1,rep,name=ids" json:"ids,omitempty"` +} + +func (m *ClusterListAttribute) Reset() { *m = ClusterListAttribute{} } +func (m *ClusterListAttribute) String() string { return proto.CompactTextString(m) } +func (*ClusterListAttribute) ProtoMessage() {} +func (*ClusterListAttribute) Descriptor() ([]byte, []int) { return fileDescriptor1, []int{10} } + +func (m *ClusterListAttribute) GetIds() []string { + if m != nil { + return m.Ids + } + return nil +} + +// IPAddressPrefix represents the NLRI for: +// - AFI=1, SAFI=1 +// - AFI=2, SAFI=1 +type IPAddressPrefix struct { + PrefixLen uint32 `protobuf:"varint,1,opt,name=prefix_len,json=prefixLen" json:"prefix_len,omitempty"` + Prefix string `protobuf:"bytes,2,opt,name=prefix" json:"prefix,omitempty"` +} + +func (m *IPAddressPrefix) Reset() { *m = IPAddressPrefix{} } +func (m *IPAddressPrefix) String() string { return proto.CompactTextString(m) } +func (*IPAddressPrefix) ProtoMessage() {} +func (*IPAddressPrefix) Descriptor() ([]byte, []int) { return fileDescriptor1, []int{11} } + +func (m *IPAddressPrefix) GetPrefixLen() uint32 { + if m != nil { + return m.PrefixLen + } + return 0 +} + +func (m *IPAddressPrefix) GetPrefix() string { + if m != nil { + return m.Prefix + } + return "" +} + +// LabeledIPAddressPrefix represents the NLRI for: +// - AFI=1, SAFI=4 +// - AFI=2, SAFI=4 +type LabeledIPAddressPrefix struct { + Labels []uint32 `protobuf:"varint,1,rep,packed,name=labels" json:"labels,omitempty"` + PrefixLen uint32 `protobuf:"varint,2,opt,name=prefix_len,json=prefixLen" json:"prefix_len,omitempty"` + Prefix string `protobuf:"bytes,3,opt,name=prefix" json:"prefix,omitempty"` +} + +func (m *LabeledIPAddressPrefix) Reset() { *m = LabeledIPAddressPrefix{} } +func (m *LabeledIPAddressPrefix) String() string { return proto.CompactTextString(m) } +func (*LabeledIPAddressPrefix) ProtoMessage() {} +func (*LabeledIPAddressPrefix) Descriptor() ([]byte, []int) { return fileDescriptor1, []int{12} } + +func (m *LabeledIPAddressPrefix) GetLabels() []uint32 { + if m != nil { + return m.Labels + } + return nil +} + +func (m *LabeledIPAddressPrefix) GetPrefixLen() uint32 { + if m != nil { + return m.PrefixLen + } + return 0 +} + +func (m *LabeledIPAddressPrefix) GetPrefix() string { + if m != nil { + return m.Prefix + } + return "" +} + +// EncapsulationNLRI represents the NLRI for: +// - AFI=1, SAFI=7 +// - AFI=2, SAFI=7 +type EncapsulationNLRI struct { + Address string `protobuf:"bytes,1,opt,name=address" json:"address,omitempty"` +} + +func (m *EncapsulationNLRI) Reset() { *m = EncapsulationNLRI{} } +func (m *EncapsulationNLRI) String() string { return proto.CompactTextString(m) } +func (*EncapsulationNLRI) ProtoMessage() {} +func (*EncapsulationNLRI) Descriptor() ([]byte, []int) { return fileDescriptor1, []int{13} } + +func (m *EncapsulationNLRI) GetAddress() string { + if m != nil { + return m.Address + } + return "" +} + +type RouteDistinguisherTwoOctetAS struct { + Admin uint32 `protobuf:"varint,1,opt,name=admin" json:"admin,omitempty"` + Assigned uint32 `protobuf:"varint,2,opt,name=assigned" json:"assigned,omitempty"` +} + +func (m *RouteDistinguisherTwoOctetAS) Reset() { *m = RouteDistinguisherTwoOctetAS{} } +func (m *RouteDistinguisherTwoOctetAS) String() string { return proto.CompactTextString(m) } +func (*RouteDistinguisherTwoOctetAS) ProtoMessage() {} +func (*RouteDistinguisherTwoOctetAS) Descriptor() ([]byte, []int) { return fileDescriptor1, []int{14} } + +func (m *RouteDistinguisherTwoOctetAS) GetAdmin() uint32 { + if m != nil { + return m.Admin + } + return 0 +} + +func (m *RouteDistinguisherTwoOctetAS) GetAssigned() uint32 { + if m != nil { + return m.Assigned + } + return 0 +} + +type RouteDistinguisherIPAddress struct { + Admin string `protobuf:"bytes,1,opt,name=admin" json:"admin,omitempty"` + Assigned uint32 `protobuf:"varint,2,opt,name=assigned" json:"assigned,omitempty"` +} + +func (m *RouteDistinguisherIPAddress) Reset() { *m = RouteDistinguisherIPAddress{} } +func (m *RouteDistinguisherIPAddress) String() string { return proto.CompactTextString(m) } +func (*RouteDistinguisherIPAddress) ProtoMessage() {} +func (*RouteDistinguisherIPAddress) Descriptor() ([]byte, []int) { return fileDescriptor1, []int{15} } + +func (m *RouteDistinguisherIPAddress) GetAdmin() string { + if m != nil { + return m.Admin + } + return "" +} + +func (m *RouteDistinguisherIPAddress) GetAssigned() uint32 { + if m != nil { + return m.Assigned + } + return 0 +} + +type RouteDistinguisherFourOctetAS struct { + Admin uint32 `protobuf:"varint,1,opt,name=admin" json:"admin,omitempty"` + Assigned uint32 `protobuf:"varint,2,opt,name=assigned" json:"assigned,omitempty"` +} + +func (m *RouteDistinguisherFourOctetAS) Reset() { *m = RouteDistinguisherFourOctetAS{} } +func (m *RouteDistinguisherFourOctetAS) String() string { return proto.CompactTextString(m) } +func (*RouteDistinguisherFourOctetAS) ProtoMessage() {} +func (*RouteDistinguisherFourOctetAS) Descriptor() ([]byte, []int) { return fileDescriptor1, []int{16} } + +func (m *RouteDistinguisherFourOctetAS) GetAdmin() uint32 { + if m != nil { + return m.Admin + } + return 0 +} + +func (m *RouteDistinguisherFourOctetAS) GetAssigned() uint32 { + if m != nil { + return m.Assigned + } + return 0 +} + +type EthernetSegmentIdentifier struct { + Type uint32 `protobuf:"varint,1,opt,name=type" json:"type,omitempty"` + Value []byte `protobuf:"bytes,2,opt,name=value,proto3" json:"value,omitempty"` +} + +func (m *EthernetSegmentIdentifier) Reset() { *m = EthernetSegmentIdentifier{} } +func (m *EthernetSegmentIdentifier) String() string { return proto.CompactTextString(m) } +func (*EthernetSegmentIdentifier) ProtoMessage() {} +func (*EthernetSegmentIdentifier) Descriptor() ([]byte, []int) { return fileDescriptor1, []int{17} } + +func (m *EthernetSegmentIdentifier) GetType() uint32 { + if m != nil { + return m.Type + } + return 0 +} + +func (m *EthernetSegmentIdentifier) GetValue() []byte { + if m != nil { + return m.Value + } + return nil +} + +// EVPNEthernetAutoDiscoveryRoute represents the NLRI for: +// - AFI=25, SAFI=70, RouteType=1 +type EVPNEthernetAutoDiscoveryRoute struct { + // One of: + // - RouteDistinguisherTwoOctetAS + // - RouteDistinguisherIPAddressAS + // - RouteDistinguisherFourOctetAS + Rd *google_protobuf.Any `protobuf:"bytes,1,opt,name=rd" json:"rd,omitempty"` + Esi *EthernetSegmentIdentifier `protobuf:"bytes,2,opt,name=esi" json:"esi,omitempty"` + EthernetTag uint32 `protobuf:"varint,3,opt,name=ethernet_tag,json=ethernetTag" json:"ethernet_tag,omitempty"` + Label uint32 `protobuf:"varint,4,opt,name=label" json:"label,omitempty"` +} + +func (m *EVPNEthernetAutoDiscoveryRoute) Reset() { *m = EVPNEthernetAutoDiscoveryRoute{} } +func (m *EVPNEthernetAutoDiscoveryRoute) String() string { return proto.CompactTextString(m) } +func (*EVPNEthernetAutoDiscoveryRoute) ProtoMessage() {} +func (*EVPNEthernetAutoDiscoveryRoute) Descriptor() ([]byte, []int) { return fileDescriptor1, []int{18} } + +func (m *EVPNEthernetAutoDiscoveryRoute) GetRd() *google_protobuf.Any { + if m != nil { + return m.Rd + } + return nil +} + +func (m *EVPNEthernetAutoDiscoveryRoute) GetEsi() *EthernetSegmentIdentifier { + if m != nil { + return m.Esi + } + return nil +} + +func (m *EVPNEthernetAutoDiscoveryRoute) GetEthernetTag() uint32 { + if m != nil { + return m.EthernetTag + } + return 0 +} + +func (m *EVPNEthernetAutoDiscoveryRoute) GetLabel() uint32 { + if m != nil { + return m.Label + } + return 0 +} + +// EVPNMACIPAdvertisementRoute represents the NLRI for: +// - AFI=25, SAFI=70, RouteType=2 +type EVPNMACIPAdvertisementRoute struct { + // One of: + // - RouteDistinguisherTwoOctetAS + // - RouteDistinguisherIPAddressAS + // - RouteDistinguisherFourOctetAS + Rd *google_protobuf.Any `protobuf:"bytes,1,opt,name=rd" json:"rd,omitempty"` + Esi *EthernetSegmentIdentifier `protobuf:"bytes,2,opt,name=esi" json:"esi,omitempty"` + EthernetTag uint32 `protobuf:"varint,3,opt,name=ethernet_tag,json=ethernetTag" json:"ethernet_tag,omitempty"` + MacAddress string `protobuf:"bytes,4,opt,name=mac_address,json=macAddress" json:"mac_address,omitempty"` + IpAddress string `protobuf:"bytes,5,opt,name=ip_address,json=ipAddress" json:"ip_address,omitempty"` + Labels []uint32 `protobuf:"varint,6,rep,packed,name=labels" json:"labels,omitempty"` +} + +func (m *EVPNMACIPAdvertisementRoute) Reset() { *m = EVPNMACIPAdvertisementRoute{} } +func (m *EVPNMACIPAdvertisementRoute) String() string { return proto.CompactTextString(m) } +func (*EVPNMACIPAdvertisementRoute) ProtoMessage() {} +func (*EVPNMACIPAdvertisementRoute) Descriptor() ([]byte, []int) { return fileDescriptor1, []int{19} } + +func (m *EVPNMACIPAdvertisementRoute) GetRd() *google_protobuf.Any { + if m != nil { + return m.Rd + } + return nil +} + +func (m *EVPNMACIPAdvertisementRoute) GetEsi() *EthernetSegmentIdentifier { + if m != nil { + return m.Esi + } + return nil +} + +func (m *EVPNMACIPAdvertisementRoute) GetEthernetTag() uint32 { + if m != nil { + return m.EthernetTag + } + return 0 +} + +func (m *EVPNMACIPAdvertisementRoute) GetMacAddress() string { + if m != nil { + return m.MacAddress + } + return "" +} + +func (m *EVPNMACIPAdvertisementRoute) GetIpAddress() string { + if m != nil { + return m.IpAddress + } + return "" +} + +func (m *EVPNMACIPAdvertisementRoute) GetLabels() []uint32 { + if m != nil { + return m.Labels + } + return nil +} + +// EVPNInclusiveMulticastEthernetTagRoute represents the NLRI for: +// - AFI=25, SAFI=70, RouteType=3 +type EVPNInclusiveMulticastEthernetTagRoute struct { + // One of: + // - RouteDistinguisherTwoOctetAS + // - RouteDistinguisherIPAddressAS + // - RouteDistinguisherFourOctetAS + Rd *google_protobuf.Any `protobuf:"bytes,1,opt,name=rd" json:"rd,omitempty"` + EthernetTag uint32 `protobuf:"varint,2,opt,name=ethernet_tag,json=ethernetTag" json:"ethernet_tag,omitempty"` + IpAddress string `protobuf:"bytes,3,opt,name=ip_address,json=ipAddress" json:"ip_address,omitempty"` +} + +func (m *EVPNInclusiveMulticastEthernetTagRoute) Reset() { + *m = EVPNInclusiveMulticastEthernetTagRoute{} +} +func (m *EVPNInclusiveMulticastEthernetTagRoute) String() string { return proto.CompactTextString(m) } +func (*EVPNInclusiveMulticastEthernetTagRoute) ProtoMessage() {} +func (*EVPNInclusiveMulticastEthernetTagRoute) Descriptor() ([]byte, []int) { + return fileDescriptor1, []int{20} +} + +func (m *EVPNInclusiveMulticastEthernetTagRoute) GetRd() *google_protobuf.Any { + if m != nil { + return m.Rd + } + return nil +} + +func (m *EVPNInclusiveMulticastEthernetTagRoute) GetEthernetTag() uint32 { + if m != nil { + return m.EthernetTag + } + return 0 +} + +func (m *EVPNInclusiveMulticastEthernetTagRoute) GetIpAddress() string { + if m != nil { + return m.IpAddress + } + return "" +} + +// EVPNEthernetSegmentRoute represents the NLRI for: +// - AFI=25, SAFI=70, RouteType=4 +type EVPNEthernetSegmentRoute struct { + // One of: + // - RouteDistinguisherTwoOctetAS + // - RouteDistinguisherIPAddressAS + // - RouteDistinguisherFourOctetAS + Rd *google_protobuf.Any `protobuf:"bytes,1,opt,name=rd" json:"rd,omitempty"` + Esi *EthernetSegmentIdentifier `protobuf:"bytes,2,opt,name=esi" json:"esi,omitempty"` + IpAddress string `protobuf:"bytes,3,opt,name=ip_address,json=ipAddress" json:"ip_address,omitempty"` +} + +func (m *EVPNEthernetSegmentRoute) Reset() { *m = EVPNEthernetSegmentRoute{} } +func (m *EVPNEthernetSegmentRoute) String() string { return proto.CompactTextString(m) } +func (*EVPNEthernetSegmentRoute) ProtoMessage() {} +func (*EVPNEthernetSegmentRoute) Descriptor() ([]byte, []int) { return fileDescriptor1, []int{21} } + +func (m *EVPNEthernetSegmentRoute) GetRd() *google_protobuf.Any { + if m != nil { + return m.Rd + } + return nil +} + +func (m *EVPNEthernetSegmentRoute) GetEsi() *EthernetSegmentIdentifier { + if m != nil { + return m.Esi + } + return nil +} + +func (m *EVPNEthernetSegmentRoute) GetIpAddress() string { + if m != nil { + return m.IpAddress + } + return "" +} + +// EVPNIPPrefixRoute represents the NLRI for: +// - AFI=25, SAFI=70, RouteType=5 +type EVPNIPPrefixRoute struct { + // One of: + // - RouteDistinguisherTwoOctetAS + // - RouteDistinguisherIPAddressAS + // - RouteDistinguisherFourOctetAS + Rd *google_protobuf.Any `protobuf:"bytes,1,opt,name=rd" json:"rd,omitempty"` + Esi *EthernetSegmentIdentifier `protobuf:"bytes,2,opt,name=esi" json:"esi,omitempty"` + EthernetTag uint32 `protobuf:"varint,3,opt,name=ethernet_tag,json=ethernetTag" json:"ethernet_tag,omitempty"` + IpPrefix string `protobuf:"bytes,4,opt,name=ip_prefix,json=ipPrefix" json:"ip_prefix,omitempty"` + IpPrefixLen uint32 `protobuf:"varint,5,opt,name=ip_prefix_len,json=ipPrefixLen" json:"ip_prefix_len,omitempty"` + GwAddress string `protobuf:"bytes,6,opt,name=gw_address,json=gwAddress" json:"gw_address,omitempty"` + Label uint32 `protobuf:"varint,7,opt,name=label" json:"label,omitempty"` +} + +func (m *EVPNIPPrefixRoute) Reset() { *m = EVPNIPPrefixRoute{} } +func (m *EVPNIPPrefixRoute) String() string { return proto.CompactTextString(m) } +func (*EVPNIPPrefixRoute) ProtoMessage() {} +func (*EVPNIPPrefixRoute) Descriptor() ([]byte, []int) { return fileDescriptor1, []int{22} } + +func (m *EVPNIPPrefixRoute) GetRd() *google_protobuf.Any { + if m != nil { + return m.Rd + } + return nil +} + +func (m *EVPNIPPrefixRoute) GetEsi() *EthernetSegmentIdentifier { + if m != nil { + return m.Esi + } + return nil +} + +func (m *EVPNIPPrefixRoute) GetEthernetTag() uint32 { + if m != nil { + return m.EthernetTag + } + return 0 +} + +func (m *EVPNIPPrefixRoute) GetIpPrefix() string { + if m != nil { + return m.IpPrefix + } + return "" +} + +func (m *EVPNIPPrefixRoute) GetIpPrefixLen() uint32 { + if m != nil { + return m.IpPrefixLen + } + return 0 +} + +func (m *EVPNIPPrefixRoute) GetGwAddress() string { + if m != nil { + return m.GwAddress + } + return "" +} + +func (m *EVPNIPPrefixRoute) GetLabel() uint32 { + if m != nil { + return m.Label + } + return 0 +} + +// LabeledVPNIPAddressPrefix represents the NLRI for: +// - AFI=1, SAFI=128 +// - AFI=2, SAFI=128 +type LabeledVPNIPAddressPrefix struct { + Labels []uint32 `protobuf:"varint,1,rep,packed,name=labels" json:"labels,omitempty"` + // One of: + // - TwoOctetAsSpecificExtended + // - IPv4AddressSpecificExtended + // - FourOctetAsSpecificExtended + Rd *google_protobuf.Any `protobuf:"bytes,2,opt,name=rd" json:"rd,omitempty"` + PrefixLen uint32 `protobuf:"varint,3,opt,name=prefix_len,json=prefixLen" json:"prefix_len,omitempty"` + Prefix string `protobuf:"bytes,4,opt,name=prefix" json:"prefix,omitempty"` +} + +func (m *LabeledVPNIPAddressPrefix) Reset() { *m = LabeledVPNIPAddressPrefix{} } +func (m *LabeledVPNIPAddressPrefix) String() string { return proto.CompactTextString(m) } +func (*LabeledVPNIPAddressPrefix) ProtoMessage() {} +func (*LabeledVPNIPAddressPrefix) Descriptor() ([]byte, []int) { return fileDescriptor1, []int{23} } + +func (m *LabeledVPNIPAddressPrefix) GetLabels() []uint32 { + if m != nil { + return m.Labels + } + return nil +} + +func (m *LabeledVPNIPAddressPrefix) GetRd() *google_protobuf.Any { + if m != nil { + return m.Rd + } + return nil +} + +func (m *LabeledVPNIPAddressPrefix) GetPrefixLen() uint32 { + if m != nil { + return m.PrefixLen + } + return 0 +} + +func (m *LabeledVPNIPAddressPrefix) GetPrefix() string { + if m != nil { + return m.Prefix + } + return "" +} + +// RouteTargetMembershipNLRI represents the NLRI for: +// - AFI=1, SAFI=132 +type RouteTargetMembershipNLRI struct { + As uint32 `protobuf:"varint,1,opt,name=as" json:"as,omitempty"` + // One of: + // - TwoOctetAsSpecificExtended + // - IPv4AddressSpecificExtended + // - FourOctetAsSpecificExtended + Rt *google_protobuf.Any `protobuf:"bytes,2,opt,name=rt" json:"rt,omitempty"` +} + +func (m *RouteTargetMembershipNLRI) Reset() { *m = RouteTargetMembershipNLRI{} } +func (m *RouteTargetMembershipNLRI) String() string { return proto.CompactTextString(m) } +func (*RouteTargetMembershipNLRI) ProtoMessage() {} +func (*RouteTargetMembershipNLRI) Descriptor() ([]byte, []int) { return fileDescriptor1, []int{24} } + +func (m *RouteTargetMembershipNLRI) GetAs() uint32 { + if m != nil { + return m.As + } + return 0 +} + +func (m *RouteTargetMembershipNLRI) GetRt() *google_protobuf.Any { + if m != nil { + return m.Rt + } + return nil +} + +type FlowSpecIPPrefix struct { + Type uint32 `protobuf:"varint,1,opt,name=type" json:"type,omitempty"` + PrefixLen uint32 `protobuf:"varint,2,opt,name=prefix_len,json=prefixLen" json:"prefix_len,omitempty"` + Prefix string `protobuf:"bytes,3,opt,name=prefix" json:"prefix,omitempty"` + // IPv6 only + Offset uint32 `protobuf:"varint,4,opt,name=offset" json:"offset,omitempty"` +} + +func (m *FlowSpecIPPrefix) Reset() { *m = FlowSpecIPPrefix{} } +func (m *FlowSpecIPPrefix) String() string { return proto.CompactTextString(m) } +func (*FlowSpecIPPrefix) ProtoMessage() {} +func (*FlowSpecIPPrefix) Descriptor() ([]byte, []int) { return fileDescriptor1, []int{25} } + +func (m *FlowSpecIPPrefix) GetType() uint32 { + if m != nil { + return m.Type + } + return 0 +} + +func (m *FlowSpecIPPrefix) GetPrefixLen() uint32 { + if m != nil { + return m.PrefixLen + } + return 0 +} + +func (m *FlowSpecIPPrefix) GetPrefix() string { + if m != nil { + return m.Prefix + } + return "" +} + +func (m *FlowSpecIPPrefix) GetOffset() uint32 { + if m != nil { + return m.Offset + } + return 0 +} + +type FlowSpecMAC struct { + Type uint32 `protobuf:"varint,1,opt,name=type" json:"type,omitempty"` + Address string `protobuf:"bytes,2,opt,name=address" json:"address,omitempty"` +} + +func (m *FlowSpecMAC) Reset() { *m = FlowSpecMAC{} } +func (m *FlowSpecMAC) String() string { return proto.CompactTextString(m) } +func (*FlowSpecMAC) ProtoMessage() {} +func (*FlowSpecMAC) Descriptor() ([]byte, []int) { return fileDescriptor1, []int{26} } + +func (m *FlowSpecMAC) GetType() uint32 { + if m != nil { + return m.Type + } + return 0 +} + +func (m *FlowSpecMAC) GetAddress() string { + if m != nil { + return m.Address + } + return "" +} + +type FlowSpecComponentItem struct { + // Operator for Numeric type, Operand for Bitmask type + Op uint32 `protobuf:"varint,1,opt,name=op" json:"op,omitempty"` + Value uint64 `protobuf:"varint,2,opt,name=value" json:"value,omitempty"` +} + +func (m *FlowSpecComponentItem) Reset() { *m = FlowSpecComponentItem{} } +func (m *FlowSpecComponentItem) String() string { return proto.CompactTextString(m) } +func (*FlowSpecComponentItem) ProtoMessage() {} +func (*FlowSpecComponentItem) Descriptor() ([]byte, []int) { return fileDescriptor1, []int{27} } + +func (m *FlowSpecComponentItem) GetOp() uint32 { + if m != nil { + return m.Op + } + return 0 +} + +func (m *FlowSpecComponentItem) GetValue() uint64 { + if m != nil { + return m.Value + } + return 0 +} + +type FlowSpecComponent struct { + Type uint32 `protobuf:"varint,1,opt,name=type" json:"type,omitempty"` + Items []*FlowSpecComponentItem `protobuf:"bytes,2,rep,name=items" json:"items,omitempty"` +} + +func (m *FlowSpecComponent) Reset() { *m = FlowSpecComponent{} } +func (m *FlowSpecComponent) String() string { return proto.CompactTextString(m) } +func (*FlowSpecComponent) ProtoMessage() {} +func (*FlowSpecComponent) Descriptor() ([]byte, []int) { return fileDescriptor1, []int{28} } + +func (m *FlowSpecComponent) GetType() uint32 { + if m != nil { + return m.Type + } + return 0 +} + +func (m *FlowSpecComponent) GetItems() []*FlowSpecComponentItem { + if m != nil { + return m.Items + } + return nil +} + +// FlowSpecNLRI represents the NLRI for: +// - AFI=1, SAFI=133 +// - AFI=2, SAFI=133 +type FlowSpecNLRI struct { + // One of: + // - FlowSpecIPPrefix + // - FlowSpecMAC + // - FlowSpecComponent + Rules []*google_protobuf.Any `protobuf:"bytes,1,rep,name=rules" json:"rules,omitempty"` +} + +func (m *FlowSpecNLRI) Reset() { *m = FlowSpecNLRI{} } +func (m *FlowSpecNLRI) String() string { return proto.CompactTextString(m) } +func (*FlowSpecNLRI) ProtoMessage() {} +func (*FlowSpecNLRI) Descriptor() ([]byte, []int) { return fileDescriptor1, []int{29} } + +func (m *FlowSpecNLRI) GetRules() []*google_protobuf.Any { + if m != nil { + return m.Rules + } + return nil +} + +// VPNFlowSpecNLRI represents the NLRI for: +// - AFI=1, SAFI=134 +// - AFI=2, SAFI=134 +// - AFI=25, SAFI=134 +type VPNFlowSpecNLRI struct { + // One of: + // - RouteDistinguisherTwoOctetAS + // - RouteDistinguisherIPAddressAS + // - RouteDistinguisherFourOctetAS + Rd *google_protobuf.Any `protobuf:"bytes,1,opt,name=rd" json:"rd,omitempty"` + // One of: + // - FlowSpecIPPrefix + // - FlowSpecMAC + // - FlowSpecComponent + Rules []*google_protobuf.Any `protobuf:"bytes,2,rep,name=rules" json:"rules,omitempty"` +} + +func (m *VPNFlowSpecNLRI) Reset() { *m = VPNFlowSpecNLRI{} } +func (m *VPNFlowSpecNLRI) String() string { return proto.CompactTextString(m) } +func (*VPNFlowSpecNLRI) ProtoMessage() {} +func (*VPNFlowSpecNLRI) Descriptor() ([]byte, []int) { return fileDescriptor1, []int{30} } + +func (m *VPNFlowSpecNLRI) GetRd() *google_protobuf.Any { + if m != nil { + return m.Rd + } + return nil +} + +func (m *VPNFlowSpecNLRI) GetRules() []*google_protobuf.Any { + if m != nil { + return m.Rules + } + return nil +} + +// OpaqueNLRI represents the NLRI for: +// - AFI=16397, SAFI=241 +type OpaqueNLRI struct { + Key []byte `protobuf:"bytes,1,opt,name=key,proto3" json:"key,omitempty"` + Value []byte `protobuf:"bytes,2,opt,name=value,proto3" json:"value,omitempty"` +} + +func (m *OpaqueNLRI) Reset() { *m = OpaqueNLRI{} } +func (m *OpaqueNLRI) String() string { return proto.CompactTextString(m) } +func (*OpaqueNLRI) ProtoMessage() {} +func (*OpaqueNLRI) Descriptor() ([]byte, []int) { return fileDescriptor1, []int{31} } + +func (m *OpaqueNLRI) GetKey() []byte { + if m != nil { + return m.Key + } + return nil +} + +func (m *OpaqueNLRI) GetValue() []byte { + if m != nil { + return m.Value + } + return nil +} + +type MpReachNLRIAttribute struct { + Family uint32 `protobuf:"varint,1,opt,name=family" json:"family,omitempty"` + NextHops []string `protobuf:"bytes,2,rep,name=next_hops,json=nextHops" json:"next_hops,omitempty"` + // Each NLRI must be one of: + // - IPAddressPrefix + // - LabeledIPAddressPrefix + // - EncapsulationNLRI + // - EVPNEthernetAutoDiscoveryRoute + // - EVPNMACIPAdvertisementRoute + // - EVPNInclusiveMulticastEthernetTagRoute + // - EVPNEthernetSegmentRoute + // - EVPNIPPrefixRoute + // - LabeledVPNIPAddressPrefix + // - RouteTargetMembershipNLRI + // - FlowSpecNLRI + // - VPNFlowSpecNLRI + // - OpaqueNLRI + Nlris []*google_protobuf.Any `protobuf:"bytes,3,rep,name=nlris" json:"nlris,omitempty"` +} + +func (m *MpReachNLRIAttribute) Reset() { *m = MpReachNLRIAttribute{} } +func (m *MpReachNLRIAttribute) String() string { return proto.CompactTextString(m) } +func (*MpReachNLRIAttribute) ProtoMessage() {} +func (*MpReachNLRIAttribute) Descriptor() ([]byte, []int) { return fileDescriptor1, []int{32} } + +func (m *MpReachNLRIAttribute) GetFamily() uint32 { + if m != nil { + return m.Family + } + return 0 +} + +func (m *MpReachNLRIAttribute) GetNextHops() []string { + if m != nil { + return m.NextHops + } + return nil +} + +func (m *MpReachNLRIAttribute) GetNlris() []*google_protobuf.Any { + if m != nil { + return m.Nlris + } + return nil +} + +type MpUnreachNLRIAttribute struct { + Family uint32 `protobuf:"varint,1,opt,name=family" json:"family,omitempty"` + // The same as NLRI field of MpReachNLRIAttribute + Nlris []*google_protobuf.Any `protobuf:"bytes,3,rep,name=nlris" json:"nlris,omitempty"` +} + +func (m *MpUnreachNLRIAttribute) Reset() { *m = MpUnreachNLRIAttribute{} } +func (m *MpUnreachNLRIAttribute) String() string { return proto.CompactTextString(m) } +func (*MpUnreachNLRIAttribute) ProtoMessage() {} +func (*MpUnreachNLRIAttribute) Descriptor() ([]byte, []int) { return fileDescriptor1, []int{33} } + +func (m *MpUnreachNLRIAttribute) GetFamily() uint32 { + if m != nil { + return m.Family + } + return 0 +} + +func (m *MpUnreachNLRIAttribute) GetNlris() []*google_protobuf.Any { + if m != nil { + return m.Nlris + } + return nil +} + +type TwoOctetAsSpecificExtended struct { + IsTransitive bool `protobuf:"varint,1,opt,name=is_transitive,json=isTransitive" json:"is_transitive,omitempty"` + SubType uint32 `protobuf:"varint,2,opt,name=sub_type,json=subType" json:"sub_type,omitempty"` + As uint32 `protobuf:"varint,3,opt,name=as" json:"as,omitempty"` + LocalAdmin uint32 `protobuf:"varint,4,opt,name=local_admin,json=localAdmin" json:"local_admin,omitempty"` +} + +func (m *TwoOctetAsSpecificExtended) Reset() { *m = TwoOctetAsSpecificExtended{} } +func (m *TwoOctetAsSpecificExtended) String() string { return proto.CompactTextString(m) } +func (*TwoOctetAsSpecificExtended) ProtoMessage() {} +func (*TwoOctetAsSpecificExtended) Descriptor() ([]byte, []int) { return fileDescriptor1, []int{34} } + +func (m *TwoOctetAsSpecificExtended) GetIsTransitive() bool { + if m != nil { + return m.IsTransitive + } + return false +} + +func (m *TwoOctetAsSpecificExtended) GetSubType() uint32 { + if m != nil { + return m.SubType + } + return 0 +} + +func (m *TwoOctetAsSpecificExtended) GetAs() uint32 { + if m != nil { + return m.As + } + return 0 +} + +func (m *TwoOctetAsSpecificExtended) GetLocalAdmin() uint32 { + if m != nil { + return m.LocalAdmin + } + return 0 +} + +type IPv4AddressSpecificExtended struct { + IsTransitive bool `protobuf:"varint,1,opt,name=is_transitive,json=isTransitive" json:"is_transitive,omitempty"` + SubType uint32 `protobuf:"varint,2,opt,name=sub_type,json=subType" json:"sub_type,omitempty"` + Address string `protobuf:"bytes,3,opt,name=address" json:"address,omitempty"` + LocalAdmin uint32 `protobuf:"varint,4,opt,name=local_admin,json=localAdmin" json:"local_admin,omitempty"` +} + +func (m *IPv4AddressSpecificExtended) Reset() { *m = IPv4AddressSpecificExtended{} } +func (m *IPv4AddressSpecificExtended) String() string { return proto.CompactTextString(m) } +func (*IPv4AddressSpecificExtended) ProtoMessage() {} +func (*IPv4AddressSpecificExtended) Descriptor() ([]byte, []int) { return fileDescriptor1, []int{35} } + +func (m *IPv4AddressSpecificExtended) GetIsTransitive() bool { + if m != nil { + return m.IsTransitive + } + return false +} + +func (m *IPv4AddressSpecificExtended) GetSubType() uint32 { + if m != nil { + return m.SubType + } + return 0 +} + +func (m *IPv4AddressSpecificExtended) GetAddress() string { + if m != nil { + return m.Address + } + return "" +} + +func (m *IPv4AddressSpecificExtended) GetLocalAdmin() uint32 { + if m != nil { + return m.LocalAdmin + } + return 0 +} + +type FourOctetAsSpecificExtended struct { + IsTransitive bool `protobuf:"varint,1,opt,name=is_transitive,json=isTransitive" json:"is_transitive,omitempty"` + SubType uint32 `protobuf:"varint,2,opt,name=sub_type,json=subType" json:"sub_type,omitempty"` + As uint32 `protobuf:"varint,3,opt,name=as" json:"as,omitempty"` + LocalAdmin uint32 `protobuf:"varint,4,opt,name=local_admin,json=localAdmin" json:"local_admin,omitempty"` +} + +func (m *FourOctetAsSpecificExtended) Reset() { *m = FourOctetAsSpecificExtended{} } +func (m *FourOctetAsSpecificExtended) String() string { return proto.CompactTextString(m) } +func (*FourOctetAsSpecificExtended) ProtoMessage() {} +func (*FourOctetAsSpecificExtended) Descriptor() ([]byte, []int) { return fileDescriptor1, []int{36} } + +func (m *FourOctetAsSpecificExtended) GetIsTransitive() bool { + if m != nil { + return m.IsTransitive + } + return false +} + +func (m *FourOctetAsSpecificExtended) GetSubType() uint32 { + if m != nil { + return m.SubType + } + return 0 +} + +func (m *FourOctetAsSpecificExtended) GetAs() uint32 { + if m != nil { + return m.As + } + return 0 +} + +func (m *FourOctetAsSpecificExtended) GetLocalAdmin() uint32 { + if m != nil { + return m.LocalAdmin + } + return 0 +} + +type ValidationExtended struct { + State uint32 `protobuf:"varint,1,opt,name=state" json:"state,omitempty"` +} + +func (m *ValidationExtended) Reset() { *m = ValidationExtended{} } +func (m *ValidationExtended) String() string { return proto.CompactTextString(m) } +func (*ValidationExtended) ProtoMessage() {} +func (*ValidationExtended) Descriptor() ([]byte, []int) { return fileDescriptor1, []int{37} } + +func (m *ValidationExtended) GetState() uint32 { + if m != nil { + return m.State + } + return 0 +} + +type ColorExtended struct { + Color uint32 `protobuf:"varint,1,opt,name=color" json:"color,omitempty"` +} + +func (m *ColorExtended) Reset() { *m = ColorExtended{} } +func (m *ColorExtended) String() string { return proto.CompactTextString(m) } +func (*ColorExtended) ProtoMessage() {} +func (*ColorExtended) Descriptor() ([]byte, []int) { return fileDescriptor1, []int{38} } + +func (m *ColorExtended) GetColor() uint32 { + if m != nil { + return m.Color + } + return 0 +} + +type EncapExtended struct { + TunnelType uint32 `protobuf:"varint,1,opt,name=tunnel_type,json=tunnelType" json:"tunnel_type,omitempty"` +} + +func (m *EncapExtended) Reset() { *m = EncapExtended{} } +func (m *EncapExtended) String() string { return proto.CompactTextString(m) } +func (*EncapExtended) ProtoMessage() {} +func (*EncapExtended) Descriptor() ([]byte, []int) { return fileDescriptor1, []int{39} } + +func (m *EncapExtended) GetTunnelType() uint32 { + if m != nil { + return m.TunnelType + } + return 0 +} + +type DefaultGatewayExtended struct { +} + +func (m *DefaultGatewayExtended) Reset() { *m = DefaultGatewayExtended{} } +func (m *DefaultGatewayExtended) String() string { return proto.CompactTextString(m) } +func (*DefaultGatewayExtended) ProtoMessage() {} +func (*DefaultGatewayExtended) Descriptor() ([]byte, []int) { return fileDescriptor1, []int{40} } + +type OpaqueExtended struct { + IsTransitive bool `protobuf:"varint,1,opt,name=is_transitive,json=isTransitive" json:"is_transitive,omitempty"` + Value []byte `protobuf:"bytes,3,opt,name=value,proto3" json:"value,omitempty"` +} + +func (m *OpaqueExtended) Reset() { *m = OpaqueExtended{} } +func (m *OpaqueExtended) String() string { return proto.CompactTextString(m) } +func (*OpaqueExtended) ProtoMessage() {} +func (*OpaqueExtended) Descriptor() ([]byte, []int) { return fileDescriptor1, []int{41} } + +func (m *OpaqueExtended) GetIsTransitive() bool { + if m != nil { + return m.IsTransitive + } + return false +} + +func (m *OpaqueExtended) GetValue() []byte { + if m != nil { + return m.Value + } + return nil +} + +type ESILabelExtended struct { + IsSingleActive bool `protobuf:"varint,1,opt,name=is_single_active,json=isSingleActive" json:"is_single_active,omitempty"` + Label uint32 `protobuf:"varint,2,opt,name=label" json:"label,omitempty"` +} + +func (m *ESILabelExtended) Reset() { *m = ESILabelExtended{} } +func (m *ESILabelExtended) String() string { return proto.CompactTextString(m) } +func (*ESILabelExtended) ProtoMessage() {} +func (*ESILabelExtended) Descriptor() ([]byte, []int) { return fileDescriptor1, []int{42} } + +func (m *ESILabelExtended) GetIsSingleActive() bool { + if m != nil { + return m.IsSingleActive + } + return false +} + +func (m *ESILabelExtended) GetLabel() uint32 { + if m != nil { + return m.Label + } + return 0 +} + +type ESImportRouteTarget struct { + EsImport string `protobuf:"bytes,1,opt,name=es_import,json=esImport" json:"es_import,omitempty"` +} + +func (m *ESImportRouteTarget) Reset() { *m = ESImportRouteTarget{} } +func (m *ESImportRouteTarget) String() string { return proto.CompactTextString(m) } +func (*ESImportRouteTarget) ProtoMessage() {} +func (*ESImportRouteTarget) Descriptor() ([]byte, []int) { return fileDescriptor1, []int{43} } + +func (m *ESImportRouteTarget) GetEsImport() string { + if m != nil { + return m.EsImport + } + return "" +} + +type MacMobilityExtended struct { + IsSticky bool `protobuf:"varint,1,opt,name=is_sticky,json=isSticky" json:"is_sticky,omitempty"` + SequenceNum uint32 `protobuf:"varint,2,opt,name=sequence_num,json=sequenceNum" json:"sequence_num,omitempty"` +} + +func (m *MacMobilityExtended) Reset() { *m = MacMobilityExtended{} } +func (m *MacMobilityExtended) String() string { return proto.CompactTextString(m) } +func (*MacMobilityExtended) ProtoMessage() {} +func (*MacMobilityExtended) Descriptor() ([]byte, []int) { return fileDescriptor1, []int{44} } + +func (m *MacMobilityExtended) GetIsSticky() bool { + if m != nil { + return m.IsSticky + } + return false +} + +func (m *MacMobilityExtended) GetSequenceNum() uint32 { + if m != nil { + return m.SequenceNum + } + return 0 +} + +type RouterMacExtended struct { + Mac string `protobuf:"bytes,1,opt,name=mac" json:"mac,omitempty"` +} + +func (m *RouterMacExtended) Reset() { *m = RouterMacExtended{} } +func (m *RouterMacExtended) String() string { return proto.CompactTextString(m) } +func (*RouterMacExtended) ProtoMessage() {} +func (*RouterMacExtended) Descriptor() ([]byte, []int) { return fileDescriptor1, []int{45} } + +func (m *RouterMacExtended) GetMac() string { + if m != nil { + return m.Mac + } + return "" +} + +type TrafficRateExtended struct { + As uint32 `protobuf:"varint,1,opt,name=as" json:"as,omitempty"` + Rate float32 `protobuf:"fixed32,2,opt,name=rate" json:"rate,omitempty"` +} + +func (m *TrafficRateExtended) Reset() { *m = TrafficRateExtended{} } +func (m *TrafficRateExtended) String() string { return proto.CompactTextString(m) } +func (*TrafficRateExtended) ProtoMessage() {} +func (*TrafficRateExtended) Descriptor() ([]byte, []int) { return fileDescriptor1, []int{46} } + +func (m *TrafficRateExtended) GetAs() uint32 { + if m != nil { + return m.As + } + return 0 +} + +func (m *TrafficRateExtended) GetRate() float32 { + if m != nil { + return m.Rate + } + return 0 +} + +type TrafficActionExtended struct { + Terminal bool `protobuf:"varint,1,opt,name=terminal" json:"terminal,omitempty"` + Sample bool `protobuf:"varint,2,opt,name=sample" json:"sample,omitempty"` +} + +func (m *TrafficActionExtended) Reset() { *m = TrafficActionExtended{} } +func (m *TrafficActionExtended) String() string { return proto.CompactTextString(m) } +func (*TrafficActionExtended) ProtoMessage() {} +func (*TrafficActionExtended) Descriptor() ([]byte, []int) { return fileDescriptor1, []int{47} } + +func (m *TrafficActionExtended) GetTerminal() bool { + if m != nil { + return m.Terminal + } + return false +} + +func (m *TrafficActionExtended) GetSample() bool { + if m != nil { + return m.Sample + } + return false +} + +type RedirectTwoOctetAsSpecificExtended struct { + As uint32 `protobuf:"varint,1,opt,name=as" json:"as,omitempty"` + LocalAdmin uint32 `protobuf:"varint,2,opt,name=local_admin,json=localAdmin" json:"local_admin,omitempty"` +} + +func (m *RedirectTwoOctetAsSpecificExtended) Reset() { *m = RedirectTwoOctetAsSpecificExtended{} } +func (m *RedirectTwoOctetAsSpecificExtended) String() string { return proto.CompactTextString(m) } +func (*RedirectTwoOctetAsSpecificExtended) ProtoMessage() {} +func (*RedirectTwoOctetAsSpecificExtended) Descriptor() ([]byte, []int) { + return fileDescriptor1, []int{48} +} + +func (m *RedirectTwoOctetAsSpecificExtended) GetAs() uint32 { + if m != nil { + return m.As + } + return 0 +} + +func (m *RedirectTwoOctetAsSpecificExtended) GetLocalAdmin() uint32 { + if m != nil { + return m.LocalAdmin + } + return 0 +} + +type RedirectIPv4AddressSpecificExtended struct { + Address string `protobuf:"bytes,1,opt,name=address" json:"address,omitempty"` + LocalAdmin uint32 `protobuf:"varint,2,opt,name=local_admin,json=localAdmin" json:"local_admin,omitempty"` +} + +func (m *RedirectIPv4AddressSpecificExtended) Reset() { *m = RedirectIPv4AddressSpecificExtended{} } +func (m *RedirectIPv4AddressSpecificExtended) String() string { return proto.CompactTextString(m) } +func (*RedirectIPv4AddressSpecificExtended) ProtoMessage() {} +func (*RedirectIPv4AddressSpecificExtended) Descriptor() ([]byte, []int) { + return fileDescriptor1, []int{49} +} + +func (m *RedirectIPv4AddressSpecificExtended) GetAddress() string { + if m != nil { + return m.Address + } + return "" +} + +func (m *RedirectIPv4AddressSpecificExtended) GetLocalAdmin() uint32 { + if m != nil { + return m.LocalAdmin + } + return 0 +} + +type RedirectFourOctetAsSpecificExtended struct { + As uint32 `protobuf:"varint,1,opt,name=as" json:"as,omitempty"` + LocalAdmin uint32 `protobuf:"varint,2,opt,name=local_admin,json=localAdmin" json:"local_admin,omitempty"` +} + +func (m *RedirectFourOctetAsSpecificExtended) Reset() { *m = RedirectFourOctetAsSpecificExtended{} } +func (m *RedirectFourOctetAsSpecificExtended) String() string { return proto.CompactTextString(m) } +func (*RedirectFourOctetAsSpecificExtended) ProtoMessage() {} +func (*RedirectFourOctetAsSpecificExtended) Descriptor() ([]byte, []int) { + return fileDescriptor1, []int{50} +} + +func (m *RedirectFourOctetAsSpecificExtended) GetAs() uint32 { + if m != nil { + return m.As + } + return 0 +} + +func (m *RedirectFourOctetAsSpecificExtended) GetLocalAdmin() uint32 { + if m != nil { + return m.LocalAdmin + } + return 0 +} + +type TrafficRemarkExtended struct { + Dscp uint32 `protobuf:"varint,1,opt,name=dscp" json:"dscp,omitempty"` +} + +func (m *TrafficRemarkExtended) Reset() { *m = TrafficRemarkExtended{} } +func (m *TrafficRemarkExtended) String() string { return proto.CompactTextString(m) } +func (*TrafficRemarkExtended) ProtoMessage() {} +func (*TrafficRemarkExtended) Descriptor() ([]byte, []int) { return fileDescriptor1, []int{51} } + +func (m *TrafficRemarkExtended) GetDscp() uint32 { + if m != nil { + return m.Dscp + } + return 0 +} + +type UnknownExtended struct { + Type uint32 `protobuf:"varint,1,opt,name=type" json:"type,omitempty"` + Value []byte `protobuf:"bytes,2,opt,name=value,proto3" json:"value,omitempty"` +} + +func (m *UnknownExtended) Reset() { *m = UnknownExtended{} } +func (m *UnknownExtended) String() string { return proto.CompactTextString(m) } +func (*UnknownExtended) ProtoMessage() {} +func (*UnknownExtended) Descriptor() ([]byte, []int) { return fileDescriptor1, []int{52} } + +func (m *UnknownExtended) GetType() uint32 { + if m != nil { + return m.Type + } + return 0 +} + +func (m *UnknownExtended) GetValue() []byte { + if m != nil { + return m.Value + } + return nil +} + +type ExtendedCommunitiesAttribute struct { + // Each Community must be one of: + // - TwoOctetAsSpecificExtended + // - IPv4AddressSpecificExtended + // - FourOctetAsSpecificExtended + // - OpaqueExtended + // - ESILabelExtended + // - MacMobilityExtended + // - RouterMacExtended + // - TrafficRateExtended + // - TrafficActionExtended + // - RedirectTwoOctetAsSpecificExtended + // - RedirectIPv4AddressSpecificExtended + // - RedirectFourOctetAsSpecificExtended + // - TrafficRemarkExtended + // - UnknownExtended + Communities []*google_protobuf.Any `protobuf:"bytes,1,rep,name=communities" json:"communities,omitempty"` +} + +func (m *ExtendedCommunitiesAttribute) Reset() { *m = ExtendedCommunitiesAttribute{} } +func (m *ExtendedCommunitiesAttribute) String() string { return proto.CompactTextString(m) } +func (*ExtendedCommunitiesAttribute) ProtoMessage() {} +func (*ExtendedCommunitiesAttribute) Descriptor() ([]byte, []int) { return fileDescriptor1, []int{53} } + +func (m *ExtendedCommunitiesAttribute) GetCommunities() []*google_protobuf.Any { + if m != nil { + return m.Communities + } + return nil +} + +type As4PathAttribute struct { + Segments []*AsSegment `protobuf:"bytes,1,rep,name=segments" json:"segments,omitempty"` +} + +func (m *As4PathAttribute) Reset() { *m = As4PathAttribute{} } +func (m *As4PathAttribute) String() string { return proto.CompactTextString(m) } +func (*As4PathAttribute) ProtoMessage() {} +func (*As4PathAttribute) Descriptor() ([]byte, []int) { return fileDescriptor1, []int{54} } + +func (m *As4PathAttribute) GetSegments() []*AsSegment { + if m != nil { + return m.Segments + } + return nil +} + +type As4AggregatorAttribute struct { + As uint32 `protobuf:"varint,2,opt,name=as" json:"as,omitempty"` + Address string `protobuf:"bytes,3,opt,name=address" json:"address,omitempty"` +} + +func (m *As4AggregatorAttribute) Reset() { *m = As4AggregatorAttribute{} } +func (m *As4AggregatorAttribute) String() string { return proto.CompactTextString(m) } +func (*As4AggregatorAttribute) ProtoMessage() {} +func (*As4AggregatorAttribute) Descriptor() ([]byte, []int) { return fileDescriptor1, []int{55} } + +func (m *As4AggregatorAttribute) GetAs() uint32 { + if m != nil { + return m.As + } + return 0 +} + +func (m *As4AggregatorAttribute) GetAddress() string { + if m != nil { + return m.Address + } + return "" +} + +type PmsiTunnelAttribute struct { + Flags uint32 `protobuf:"varint,1,opt,name=flags" json:"flags,omitempty"` + Type uint32 `protobuf:"varint,2,opt,name=type" json:"type,omitempty"` + Label uint32 `protobuf:"varint,3,opt,name=label" json:"label,omitempty"` + Id []byte `protobuf:"bytes,4,opt,name=id,proto3" json:"id,omitempty"` +} + +func (m *PmsiTunnelAttribute) Reset() { *m = PmsiTunnelAttribute{} } +func (m *PmsiTunnelAttribute) String() string { return proto.CompactTextString(m) } +func (*PmsiTunnelAttribute) ProtoMessage() {} +func (*PmsiTunnelAttribute) Descriptor() ([]byte, []int) { return fileDescriptor1, []int{56} } + +func (m *PmsiTunnelAttribute) GetFlags() uint32 { + if m != nil { + return m.Flags + } + return 0 +} + +func (m *PmsiTunnelAttribute) GetType() uint32 { + if m != nil { + return m.Type + } + return 0 +} + +func (m *PmsiTunnelAttribute) GetLabel() uint32 { + if m != nil { + return m.Label + } + return 0 +} + +func (m *PmsiTunnelAttribute) GetId() []byte { + if m != nil { + return m.Id + } + return nil +} + +type TunnelEncapSubTLVEncapsulation struct { + Key uint32 `protobuf:"varint,1,opt,name=key" json:"key,omitempty"` + Cookie []byte `protobuf:"bytes,2,opt,name=cookie,proto3" json:"cookie,omitempty"` +} + +func (m *TunnelEncapSubTLVEncapsulation) Reset() { *m = TunnelEncapSubTLVEncapsulation{} } +func (m *TunnelEncapSubTLVEncapsulation) String() string { return proto.CompactTextString(m) } +func (*TunnelEncapSubTLVEncapsulation) ProtoMessage() {} +func (*TunnelEncapSubTLVEncapsulation) Descriptor() ([]byte, []int) { return fileDescriptor1, []int{57} } + +func (m *TunnelEncapSubTLVEncapsulation) GetKey() uint32 { + if m != nil { + return m.Key + } + return 0 +} + +func (m *TunnelEncapSubTLVEncapsulation) GetCookie() []byte { + if m != nil { + return m.Cookie + } + return nil +} + +type TunnelEncapSubTLVProtocol struct { + Protocol uint32 `protobuf:"varint,1,opt,name=protocol" json:"protocol,omitempty"` +} + +func (m *TunnelEncapSubTLVProtocol) Reset() { *m = TunnelEncapSubTLVProtocol{} } +func (m *TunnelEncapSubTLVProtocol) String() string { return proto.CompactTextString(m) } +func (*TunnelEncapSubTLVProtocol) ProtoMessage() {} +func (*TunnelEncapSubTLVProtocol) Descriptor() ([]byte, []int) { return fileDescriptor1, []int{58} } + +func (m *TunnelEncapSubTLVProtocol) GetProtocol() uint32 { + if m != nil { + return m.Protocol + } + return 0 +} + +type TunnelEncapSubTLVColor struct { + Color uint32 `protobuf:"varint,1,opt,name=color" json:"color,omitempty"` +} + +func (m *TunnelEncapSubTLVColor) Reset() { *m = TunnelEncapSubTLVColor{} } +func (m *TunnelEncapSubTLVColor) String() string { return proto.CompactTextString(m) } +func (*TunnelEncapSubTLVColor) ProtoMessage() {} +func (*TunnelEncapSubTLVColor) Descriptor() ([]byte, []int) { return fileDescriptor1, []int{59} } + +func (m *TunnelEncapSubTLVColor) GetColor() uint32 { + if m != nil { + return m.Color + } + return 0 +} + +type TunnelEncapSubTLVUnknown struct { + Type uint32 `protobuf:"varint,1,opt,name=type" json:"type,omitempty"` + Value []byte `protobuf:"bytes,2,opt,name=value,proto3" json:"value,omitempty"` +} + +func (m *TunnelEncapSubTLVUnknown) Reset() { *m = TunnelEncapSubTLVUnknown{} } +func (m *TunnelEncapSubTLVUnknown) String() string { return proto.CompactTextString(m) } +func (*TunnelEncapSubTLVUnknown) ProtoMessage() {} +func (*TunnelEncapSubTLVUnknown) Descriptor() ([]byte, []int) { return fileDescriptor1, []int{60} } + +func (m *TunnelEncapSubTLVUnknown) GetType() uint32 { + if m != nil { + return m.Type + } + return 0 +} + +func (m *TunnelEncapSubTLVUnknown) GetValue() []byte { + if m != nil { + return m.Value + } + return nil +} + +type TunnelEncapTLV struct { + Type uint32 `protobuf:"varint,1,opt,name=type" json:"type,omitempty"` + // Each TLV must be one of: + // - TunnelEncapSubTLVEncapsulation + // - TunnelEncapSubTLVProtocol + // - TunnelEncapSubTLVColor + // - TunnelEncapSubTLVUnknown + Tlvs []*google_protobuf.Any `protobuf:"bytes,2,rep,name=tlvs" json:"tlvs,omitempty"` +} + +func (m *TunnelEncapTLV) Reset() { *m = TunnelEncapTLV{} } +func (m *TunnelEncapTLV) String() string { return proto.CompactTextString(m) } +func (*TunnelEncapTLV) ProtoMessage() {} +func (*TunnelEncapTLV) Descriptor() ([]byte, []int) { return fileDescriptor1, []int{61} } + +func (m *TunnelEncapTLV) GetType() uint32 { + if m != nil { + return m.Type + } + return 0 +} + +func (m *TunnelEncapTLV) GetTlvs() []*google_protobuf.Any { + if m != nil { + return m.Tlvs + } + return nil +} + +type TunnelEncapAttribute struct { + Tlvs []*TunnelEncapTLV `protobuf:"bytes,1,rep,name=tlvs" json:"tlvs,omitempty"` +} + +func (m *TunnelEncapAttribute) Reset() { *m = TunnelEncapAttribute{} } +func (m *TunnelEncapAttribute) String() string { return proto.CompactTextString(m) } +func (*TunnelEncapAttribute) ProtoMessage() {} +func (*TunnelEncapAttribute) Descriptor() ([]byte, []int) { return fileDescriptor1, []int{62} } + +func (m *TunnelEncapAttribute) GetTlvs() []*TunnelEncapTLV { + if m != nil { + return m.Tlvs + } + return nil +} + +type IPv6AddressSpecificExtended struct { + IsTransitive bool `protobuf:"varint,1,opt,name=is_transitive,json=isTransitive" json:"is_transitive,omitempty"` + SubType uint32 `protobuf:"varint,2,opt,name=sub_type,json=subType" json:"sub_type,omitempty"` + Address string `protobuf:"bytes,3,opt,name=address" json:"address,omitempty"` + LocalAdmin uint32 `protobuf:"varint,4,opt,name=local_admin,json=localAdmin" json:"local_admin,omitempty"` +} + +func (m *IPv6AddressSpecificExtended) Reset() { *m = IPv6AddressSpecificExtended{} } +func (m *IPv6AddressSpecificExtended) String() string { return proto.CompactTextString(m) } +func (*IPv6AddressSpecificExtended) ProtoMessage() {} +func (*IPv6AddressSpecificExtended) Descriptor() ([]byte, []int) { return fileDescriptor1, []int{63} } + +func (m *IPv6AddressSpecificExtended) GetIsTransitive() bool { + if m != nil { + return m.IsTransitive + } + return false +} + +func (m *IPv6AddressSpecificExtended) GetSubType() uint32 { + if m != nil { + return m.SubType + } + return 0 +} + +func (m *IPv6AddressSpecificExtended) GetAddress() string { + if m != nil { + return m.Address + } + return "" +} + +func (m *IPv6AddressSpecificExtended) GetLocalAdmin() uint32 { + if m != nil { + return m.LocalAdmin + } + return 0 +} + +type RedirectIPv6AddressSpecificExtended struct { + Address string `protobuf:"bytes,1,opt,name=address" json:"address,omitempty"` + LocalAdmin uint32 `protobuf:"varint,2,opt,name=local_admin,json=localAdmin" json:"local_admin,omitempty"` +} + +func (m *RedirectIPv6AddressSpecificExtended) Reset() { *m = RedirectIPv6AddressSpecificExtended{} } +func (m *RedirectIPv6AddressSpecificExtended) String() string { return proto.CompactTextString(m) } +func (*RedirectIPv6AddressSpecificExtended) ProtoMessage() {} +func (*RedirectIPv6AddressSpecificExtended) Descriptor() ([]byte, []int) { + return fileDescriptor1, []int{64} +} + +func (m *RedirectIPv6AddressSpecificExtended) GetAddress() string { + if m != nil { + return m.Address + } + return "" +} + +func (m *RedirectIPv6AddressSpecificExtended) GetLocalAdmin() uint32 { + if m != nil { + return m.LocalAdmin + } + return 0 +} + +type IP6ExtendedCommunitiesAttribute struct { + // Each Community must be one of: + // - IPv6AddressSpecificExtended + // - RedirectIPv6AddressSpecificExtended + Communities []*google_protobuf.Any `protobuf:"bytes,1,rep,name=communities" json:"communities,omitempty"` +} + +func (m *IP6ExtendedCommunitiesAttribute) Reset() { *m = IP6ExtendedCommunitiesAttribute{} } +func (m *IP6ExtendedCommunitiesAttribute) String() string { return proto.CompactTextString(m) } +func (*IP6ExtendedCommunitiesAttribute) ProtoMessage() {} +func (*IP6ExtendedCommunitiesAttribute) Descriptor() ([]byte, []int) { + return fileDescriptor1, []int{65} +} + +func (m *IP6ExtendedCommunitiesAttribute) GetCommunities() []*google_protobuf.Any { + if m != nil { + return m.Communities + } + return nil +} + +type AigpTLVIGPMetric struct { + Metric uint64 `protobuf:"varint,1,opt,name=metric" json:"metric,omitempty"` +} + +func (m *AigpTLVIGPMetric) Reset() { *m = AigpTLVIGPMetric{} } +func (m *AigpTLVIGPMetric) String() string { return proto.CompactTextString(m) } +func (*AigpTLVIGPMetric) ProtoMessage() {} +func (*AigpTLVIGPMetric) Descriptor() ([]byte, []int) { return fileDescriptor1, []int{66} } + +func (m *AigpTLVIGPMetric) GetMetric() uint64 { + if m != nil { + return m.Metric + } + return 0 +} + +type AigpTLVUnknown struct { + Type uint32 `protobuf:"varint,1,opt,name=type" json:"type,omitempty"` + Value []byte `protobuf:"bytes,2,opt,name=value,proto3" json:"value,omitempty"` +} + +func (m *AigpTLVUnknown) Reset() { *m = AigpTLVUnknown{} } +func (m *AigpTLVUnknown) String() string { return proto.CompactTextString(m) } +func (*AigpTLVUnknown) ProtoMessage() {} +func (*AigpTLVUnknown) Descriptor() ([]byte, []int) { return fileDescriptor1, []int{67} } + +func (m *AigpTLVUnknown) GetType() uint32 { + if m != nil { + return m.Type + } + return 0 +} + +func (m *AigpTLVUnknown) GetValue() []byte { + if m != nil { + return m.Value + } + return nil +} + +type AigpAttribute struct { + // Each TLV must be one of: + // - AigpTLVIGPMetric + // - AigpTLVUnknown + Tlvs []*google_protobuf.Any `protobuf:"bytes,1,rep,name=tlvs" json:"tlvs,omitempty"` +} + +func (m *AigpAttribute) Reset() { *m = AigpAttribute{} } +func (m *AigpAttribute) String() string { return proto.CompactTextString(m) } +func (*AigpAttribute) ProtoMessage() {} +func (*AigpAttribute) Descriptor() ([]byte, []int) { return fileDescriptor1, []int{68} } + +func (m *AigpAttribute) GetTlvs() []*google_protobuf.Any { + if m != nil { + return m.Tlvs + } + return nil +} + +type LargeCommunity struct { + GlobalAdmin uint32 `protobuf:"varint,1,opt,name=global_admin,json=globalAdmin" json:"global_admin,omitempty"` + LocalData1 uint32 `protobuf:"varint,2,opt,name=local_data1,json=localData1" json:"local_data1,omitempty"` + LocalData2 uint32 `protobuf:"varint,3,opt,name=local_data2,json=localData2" json:"local_data2,omitempty"` +} + +func (m *LargeCommunity) Reset() { *m = LargeCommunity{} } +func (m *LargeCommunity) String() string { return proto.CompactTextString(m) } +func (*LargeCommunity) ProtoMessage() {} +func (*LargeCommunity) Descriptor() ([]byte, []int) { return fileDescriptor1, []int{69} } + +func (m *LargeCommunity) GetGlobalAdmin() uint32 { + if m != nil { + return m.GlobalAdmin + } + return 0 +} + +func (m *LargeCommunity) GetLocalData1() uint32 { + if m != nil { + return m.LocalData1 + } + return 0 +} + +func (m *LargeCommunity) GetLocalData2() uint32 { + if m != nil { + return m.LocalData2 + } + return 0 +} + +type LargeCommunitiesAttribute struct { + Communities []*LargeCommunity `protobuf:"bytes,1,rep,name=communities" json:"communities,omitempty"` +} + +func (m *LargeCommunitiesAttribute) Reset() { *m = LargeCommunitiesAttribute{} } +func (m *LargeCommunitiesAttribute) String() string { return proto.CompactTextString(m) } +func (*LargeCommunitiesAttribute) ProtoMessage() {} +func (*LargeCommunitiesAttribute) Descriptor() ([]byte, []int) { return fileDescriptor1, []int{70} } + +func (m *LargeCommunitiesAttribute) GetCommunities() []*LargeCommunity { + if m != nil { + return m.Communities + } + return nil +} + +type UnknownAttribute struct { + Flags uint32 `protobuf:"varint,1,opt,name=flags" json:"flags,omitempty"` + Type uint32 `protobuf:"varint,2,opt,name=type" json:"type,omitempty"` + Value []byte `protobuf:"bytes,3,opt,name=value,proto3" json:"value,omitempty"` +} + +func (m *UnknownAttribute) Reset() { *m = UnknownAttribute{} } +func (m *UnknownAttribute) String() string { return proto.CompactTextString(m) } +func (*UnknownAttribute) ProtoMessage() {} +func (*UnknownAttribute) Descriptor() ([]byte, []int) { return fileDescriptor1, []int{71} } + +func (m *UnknownAttribute) GetFlags() uint32 { + if m != nil { + return m.Flags + } + return 0 +} + +func (m *UnknownAttribute) GetType() uint32 { + if m != nil { + return m.Type + } + return 0 +} + +func (m *UnknownAttribute) GetValue() []byte { + if m != nil { + return m.Value + } + return nil +} + +func init() { + proto.RegisterType((*OriginAttribute)(nil), "gobgpapi.OriginAttribute") + proto.RegisterType((*AsSegment)(nil), "gobgpapi.AsSegment") + proto.RegisterType((*AsPathAttribute)(nil), "gobgpapi.AsPathAttribute") + proto.RegisterType((*NextHopAttribute)(nil), "gobgpapi.NextHopAttribute") + proto.RegisterType((*MultiExitDiscAttribute)(nil), "gobgpapi.MultiExitDiscAttribute") + proto.RegisterType((*LocalPrefAttribute)(nil), "gobgpapi.LocalPrefAttribute") + proto.RegisterType((*AtomicAggregateAttribute)(nil), "gobgpapi.AtomicAggregateAttribute") + proto.RegisterType((*AggregatorAttribute)(nil), "gobgpapi.AggregatorAttribute") + proto.RegisterType((*CommunitiesAttribute)(nil), "gobgpapi.CommunitiesAttribute") + proto.RegisterType((*OriginatorIdAttribute)(nil), "gobgpapi.OriginatorIdAttribute") + proto.RegisterType((*ClusterListAttribute)(nil), "gobgpapi.ClusterListAttribute") + proto.RegisterType((*IPAddressPrefix)(nil), "gobgpapi.IPAddressPrefix") + proto.RegisterType((*LabeledIPAddressPrefix)(nil), "gobgpapi.LabeledIPAddressPrefix") + proto.RegisterType((*EncapsulationNLRI)(nil), "gobgpapi.EncapsulationNLRI") + proto.RegisterType((*RouteDistinguisherTwoOctetAS)(nil), "gobgpapi.RouteDistinguisherTwoOctetAS") + proto.RegisterType((*RouteDistinguisherIPAddress)(nil), "gobgpapi.RouteDistinguisherIPAddress") + proto.RegisterType((*RouteDistinguisherFourOctetAS)(nil), "gobgpapi.RouteDistinguisherFourOctetAS") + proto.RegisterType((*EthernetSegmentIdentifier)(nil), "gobgpapi.EthernetSegmentIdentifier") + proto.RegisterType((*EVPNEthernetAutoDiscoveryRoute)(nil), "gobgpapi.EVPNEthernetAutoDiscoveryRoute") + proto.RegisterType((*EVPNMACIPAdvertisementRoute)(nil), "gobgpapi.EVPNMACIPAdvertisementRoute") + proto.RegisterType((*EVPNInclusiveMulticastEthernetTagRoute)(nil), "gobgpapi.EVPNInclusiveMulticastEthernetTagRoute") + proto.RegisterType((*EVPNEthernetSegmentRoute)(nil), "gobgpapi.EVPNEthernetSegmentRoute") + proto.RegisterType((*EVPNIPPrefixRoute)(nil), "gobgpapi.EVPNIPPrefixRoute") + proto.RegisterType((*LabeledVPNIPAddressPrefix)(nil), "gobgpapi.LabeledVPNIPAddressPrefix") + proto.RegisterType((*RouteTargetMembershipNLRI)(nil), "gobgpapi.RouteTargetMembershipNLRI") + proto.RegisterType((*FlowSpecIPPrefix)(nil), "gobgpapi.FlowSpecIPPrefix") + proto.RegisterType((*FlowSpecMAC)(nil), "gobgpapi.FlowSpecMAC") + proto.RegisterType((*FlowSpecComponentItem)(nil), "gobgpapi.FlowSpecComponentItem") + proto.RegisterType((*FlowSpecComponent)(nil), "gobgpapi.FlowSpecComponent") + proto.RegisterType((*FlowSpecNLRI)(nil), "gobgpapi.FlowSpecNLRI") + proto.RegisterType((*VPNFlowSpecNLRI)(nil), "gobgpapi.VPNFlowSpecNLRI") + proto.RegisterType((*OpaqueNLRI)(nil), "gobgpapi.OpaqueNLRI") + proto.RegisterType((*MpReachNLRIAttribute)(nil), "gobgpapi.MpReachNLRIAttribute") + proto.RegisterType((*MpUnreachNLRIAttribute)(nil), "gobgpapi.MpUnreachNLRIAttribute") + proto.RegisterType((*TwoOctetAsSpecificExtended)(nil), "gobgpapi.TwoOctetAsSpecificExtended") + proto.RegisterType((*IPv4AddressSpecificExtended)(nil), "gobgpapi.IPv4AddressSpecificExtended") + proto.RegisterType((*FourOctetAsSpecificExtended)(nil), "gobgpapi.FourOctetAsSpecificExtended") + proto.RegisterType((*ValidationExtended)(nil), "gobgpapi.ValidationExtended") + proto.RegisterType((*ColorExtended)(nil), "gobgpapi.ColorExtended") + proto.RegisterType((*EncapExtended)(nil), "gobgpapi.EncapExtended") + proto.RegisterType((*DefaultGatewayExtended)(nil), "gobgpapi.DefaultGatewayExtended") + proto.RegisterType((*OpaqueExtended)(nil), "gobgpapi.OpaqueExtended") + proto.RegisterType((*ESILabelExtended)(nil), "gobgpapi.ESILabelExtended") + proto.RegisterType((*ESImportRouteTarget)(nil), "gobgpapi.ESImportRouteTarget") + proto.RegisterType((*MacMobilityExtended)(nil), "gobgpapi.MacMobilityExtended") + proto.RegisterType((*RouterMacExtended)(nil), "gobgpapi.RouterMacExtended") + proto.RegisterType((*TrafficRateExtended)(nil), "gobgpapi.TrafficRateExtended") + proto.RegisterType((*TrafficActionExtended)(nil), "gobgpapi.TrafficActionExtended") + proto.RegisterType((*RedirectTwoOctetAsSpecificExtended)(nil), "gobgpapi.RedirectTwoOctetAsSpecificExtended") + proto.RegisterType((*RedirectIPv4AddressSpecificExtended)(nil), "gobgpapi.RedirectIPv4AddressSpecificExtended") + proto.RegisterType((*RedirectFourOctetAsSpecificExtended)(nil), "gobgpapi.RedirectFourOctetAsSpecificExtended") + proto.RegisterType((*TrafficRemarkExtended)(nil), "gobgpapi.TrafficRemarkExtended") + proto.RegisterType((*UnknownExtended)(nil), "gobgpapi.UnknownExtended") + proto.RegisterType((*ExtendedCommunitiesAttribute)(nil), "gobgpapi.ExtendedCommunitiesAttribute") + proto.RegisterType((*As4PathAttribute)(nil), "gobgpapi.As4PathAttribute") + proto.RegisterType((*As4AggregatorAttribute)(nil), "gobgpapi.As4AggregatorAttribute") + proto.RegisterType((*PmsiTunnelAttribute)(nil), "gobgpapi.PmsiTunnelAttribute") + proto.RegisterType((*TunnelEncapSubTLVEncapsulation)(nil), "gobgpapi.TunnelEncapSubTLVEncapsulation") + proto.RegisterType((*TunnelEncapSubTLVProtocol)(nil), "gobgpapi.TunnelEncapSubTLVProtocol") + proto.RegisterType((*TunnelEncapSubTLVColor)(nil), "gobgpapi.TunnelEncapSubTLVColor") + proto.RegisterType((*TunnelEncapSubTLVUnknown)(nil), "gobgpapi.TunnelEncapSubTLVUnknown") + proto.RegisterType((*TunnelEncapTLV)(nil), "gobgpapi.TunnelEncapTLV") + proto.RegisterType((*TunnelEncapAttribute)(nil), "gobgpapi.TunnelEncapAttribute") + proto.RegisterType((*IPv6AddressSpecificExtended)(nil), "gobgpapi.IPv6AddressSpecificExtended") + proto.RegisterType((*RedirectIPv6AddressSpecificExtended)(nil), "gobgpapi.RedirectIPv6AddressSpecificExtended") + proto.RegisterType((*IP6ExtendedCommunitiesAttribute)(nil), "gobgpapi.IP6ExtendedCommunitiesAttribute") + proto.RegisterType((*AigpTLVIGPMetric)(nil), "gobgpapi.AigpTLVIGPMetric") + proto.RegisterType((*AigpTLVUnknown)(nil), "gobgpapi.AigpTLVUnknown") + proto.RegisterType((*AigpAttribute)(nil), "gobgpapi.AigpAttribute") + proto.RegisterType((*LargeCommunity)(nil), "gobgpapi.LargeCommunity") + proto.RegisterType((*LargeCommunitiesAttribute)(nil), "gobgpapi.LargeCommunitiesAttribute") + proto.RegisterType((*UnknownAttribute)(nil), "gobgpapi.UnknownAttribute") +} + +func init() { proto.RegisterFile("attribute.proto", fileDescriptor1) } + +var fileDescriptor1 = []byte{ + // 1868 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xcc, 0x58, 0xeb, 0x6f, 0x1b, 0xc7, + 0x11, 0x07, 0x8f, 0x94, 0x4c, 0x0e, 0x45, 0x49, 0xa6, 0x64, 0x81, 0x92, 0xe2, 0xc8, 0x5d, 0x37, + 0xad, 0xea, 0x36, 0x72, 0xab, 0x38, 0x6e, 0xed, 0xa0, 0x28, 0x18, 0x49, 0x49, 0xd8, 0x88, 0x32, + 0x73, 0x92, 0x55, 0x14, 0x28, 0xca, 0x2e, 0xef, 0x96, 0xa7, 0x85, 0xee, 0x95, 0xdb, 0x3d, 0x3d, + 0xfe, 0x84, 0x7e, 0x68, 0x91, 0x4f, 0x45, 0xff, 0x92, 0xfe, 0x67, 0xfd, 0x5e, 0xec, 0xeb, 0x1e, + 0xa2, 0xa8, 0x87, 0x53, 0x03, 0xfe, 0xb6, 0xb3, 0x9c, 0x9d, 0x99, 0xfd, 0xed, 0xcc, 0x6f, 0x86, + 0x07, 0x0b, 0x98, 0xf3, 0x84, 0x8e, 0x52, 0x4e, 0xb6, 0xe2, 0x24, 0xe2, 0x51, 0xbb, 0xee, 0x45, + 0x23, 0x2f, 0xc6, 0x31, 0x5d, 0x5b, 0xf5, 0xa2, 0xc8, 0xf3, 0xc9, 0x73, 0xb9, 0x3f, 0x4a, 0xc7, + 0xcf, 0x71, 0x78, 0xa9, 0x94, 0xd0, 0x2f, 0x60, 0xe1, 0x4d, 0x42, 0x3d, 0x1a, 0x76, 0xcd, 0xe9, + 0xf6, 0x0a, 0xcc, 0x46, 0x72, 0xab, 0x53, 0x79, 0x52, 0xd9, 0x6c, 0xd9, 0x5a, 0x42, 0xaf, 0xa0, + 0xd1, 0x65, 0x87, 0xc4, 0x0b, 0x48, 0xc8, 0xdb, 0x6d, 0xa8, 0xf1, 0xcb, 0x98, 0x68, 0x15, 0xb9, + 0x6e, 0x77, 0xe0, 0x41, 0x98, 0x06, 0x23, 0x92, 0xb0, 0x8e, 0xf5, 0xa4, 0xba, 0xd9, 0xb2, 0x8d, + 0x88, 0xbe, 0x84, 0x85, 0x2e, 0x1b, 0x60, 0x7e, 0x92, 0x7b, 0x79, 0x0e, 0x75, 0xa6, 0x6c, 0xb1, + 0x4e, 0xe5, 0x49, 0x75, 0xb3, 0xb9, 0xbd, 0xb4, 0x65, 0x02, 0xde, 0xca, 0xfc, 0xd8, 0x99, 0x12, + 0xfa, 0x14, 0x16, 0x0f, 0xc8, 0x05, 0xff, 0x26, 0x8a, 0x73, 0x23, 0xab, 0x50, 0x0f, 0xc9, 0x05, + 0x1f, 0x9e, 0x44, 0xb1, 0x8c, 0xa4, 0x61, 0x3f, 0x08, 0x95, 0x0e, 0x7a, 0x06, 0x2b, 0xfd, 0xd4, + 0xe7, 0x74, 0xef, 0x82, 0xf2, 0x5d, 0xca, 0x9c, 0xfc, 0xd0, 0x22, 0x54, 0x03, 0xe2, 0xea, 0xc8, + 0xc5, 0x12, 0x7d, 0x06, 0xed, 0xfd, 0xc8, 0xc1, 0xfe, 0x20, 0x21, 0xe3, 0x5c, 0xef, 0x31, 0x80, + 0x2f, 0x76, 0x87, 0x71, 0x42, 0xc6, 0x5a, 0xbd, 0xe1, 0x1b, 0x3d, 0xb4, 0x06, 0x9d, 0x2e, 0x8f, + 0x02, 0xea, 0x74, 0x3d, 0x2f, 0x21, 0x1e, 0xe6, 0x24, 0x3b, 0x8a, 0xfe, 0x00, 0x4b, 0x66, 0x37, + 0x4a, 0x72, 0x8b, 0xf3, 0x60, 0x61, 0x81, 0x8d, 0xb0, 0x64, 0x61, 0x26, 0x00, 0xc3, 0xae, 0x9b, + 0x10, 0xc6, 0x3a, 0x55, 0x15, 0xbd, 0x16, 0xd1, 0xef, 0x60, 0x79, 0x27, 0x0a, 0x82, 0x34, 0xa4, + 0x9c, 0x12, 0x96, 0x5b, 0x78, 0x02, 0x4d, 0x27, 0xdf, 0x97, 0xc0, 0xb5, 0xec, 0xe2, 0x16, 0xfa, + 0x39, 0x3c, 0x52, 0x0f, 0x2a, 0x5c, 0xf7, 0xdc, 0x92, 0x73, 0xea, 0x6a, 0x94, 0x2c, 0xea, 0xa2, + 0x4d, 0x58, 0xde, 0xf1, 0x53, 0xc6, 0x49, 0xb2, 0x4f, 0x19, 0x2f, 0xc1, 0x43, 0x5d, 0x65, 0xba, + 0x61, 0x8b, 0x25, 0xfa, 0x06, 0x16, 0x7a, 0x83, 0xae, 0x8a, 0x4c, 0x5c, 0x9d, 0x5e, 0x08, 0x6c, + 0x62, 0xb9, 0x1a, 0xfa, 0xc4, 0xe4, 0x49, 0x43, 0xed, 0xec, 0x93, 0x50, 0xa4, 0x90, 0x12, 0xe4, + 0x65, 0x1b, 0xb6, 0x96, 0x90, 0x07, 0x2b, 0xfb, 0x78, 0x44, 0x7c, 0xe2, 0x5e, 0x35, 0xb8, 0x02, + 0xb3, 0xbe, 0xf8, 0xc5, 0xdc, 0x49, 0x4b, 0x57, 0x1c, 0x59, 0xd3, 0x1d, 0x55, 0x4b, 0x8e, 0x3e, + 0x85, 0x87, 0x7b, 0xa1, 0x83, 0x63, 0x96, 0xfa, 0x98, 0xd3, 0x28, 0x3c, 0xd8, 0xb7, 0x7b, 0x45, + 0xb8, 0x2b, 0x65, 0xb8, 0x07, 0xf0, 0x91, 0x1d, 0xa5, 0x9c, 0xec, 0x52, 0xc6, 0x69, 0xe8, 0xa5, + 0x94, 0x9d, 0x90, 0xe4, 0xe8, 0x3c, 0x7a, 0xe3, 0x70, 0xc2, 0xbb, 0x87, 0xed, 0x65, 0x98, 0xc1, + 0x6e, 0x90, 0x55, 0x84, 0x12, 0xda, 0x6b, 0x50, 0xc7, 0x8c, 0x51, 0x2f, 0x24, 0xae, 0x8e, 0x2c, + 0x93, 0xd1, 0x1b, 0x58, 0x9f, 0xb4, 0x98, 0x5d, 0xba, 0x6c, 0xb0, 0x71, 0x17, 0x83, 0xdf, 0xc1, + 0xe3, 0x49, 0x83, 0x5f, 0x45, 0x69, 0xf2, 0xee, 0x31, 0xee, 0xc1, 0xea, 0x1e, 0x3f, 0x21, 0x49, + 0x48, 0xb8, 0x2e, 0xb7, 0x9e, 0x4b, 0x42, 0x4e, 0xc7, 0x94, 0x24, 0xd7, 0x16, 0xf8, 0x32, 0xcc, + 0x9c, 0x61, 0x3f, 0x25, 0xd2, 0xd2, 0x9c, 0xad, 0x04, 0xf4, 0x9f, 0x0a, 0x7c, 0xbc, 0x77, 0x3c, + 0x38, 0x30, 0xb6, 0xba, 0x29, 0x8f, 0x44, 0xc5, 0x45, 0x67, 0x24, 0xb9, 0x94, 0x31, 0xb7, 0x7f, + 0x0a, 0x56, 0xa2, 0x72, 0xaf, 0xb9, 0xbd, 0xbc, 0xa5, 0xd8, 0x68, 0xcb, 0xb0, 0xd1, 0x56, 0x37, + 0xbc, 0xb4, 0xad, 0xc4, 0x6d, 0x7f, 0x0e, 0x55, 0xc2, 0xa8, 0x34, 0xde, 0xdc, 0x7e, 0x9a, 0xb3, + 0xc1, 0xd4, 0x20, 0x6d, 0xa1, 0xdf, 0xfe, 0x09, 0xcc, 0x11, 0xad, 0x31, 0xe4, 0xd8, 0x93, 0x99, + 0xd0, 0xb2, 0x9b, 0x66, 0xef, 0x08, 0x7b, 0x22, 0x70, 0x99, 0x4f, 0x9d, 0x9a, 0xc2, 0x46, 0x0a, + 0xe8, 0xbf, 0x15, 0x58, 0x17, 0x81, 0xf7, 0xbb, 0x3b, 0xe2, 0x65, 0xce, 0x48, 0xc2, 0x29, 0x23, + 0x92, 0x76, 0x3e, 0x88, 0xa8, 0x37, 0xa0, 0x19, 0x60, 0x67, 0x68, 0x72, 0xb6, 0x26, 0x53, 0x05, + 0x02, 0xec, 0x98, 0x2c, 0x7a, 0x0c, 0x40, 0xe3, 0xec, 0xf7, 0x19, 0xf9, 0x7b, 0x83, 0xc6, 0xe6, + 0xe7, 0xbc, 0xa6, 0x66, 0x8b, 0x35, 0x85, 0x7e, 0xa8, 0xc0, 0xcf, 0xc4, 0xbd, 0x7b, 0xa1, 0xe3, + 0xa7, 0x8c, 0x9e, 0x11, 0x49, 0x94, 0x0e, 0x66, 0x7c, 0x2f, 0xf7, 0x7e, 0x1f, 0x08, 0xae, 0xde, + 0xc5, 0x9a, 0xbc, 0x4b, 0x39, 0xd4, 0xea, 0x95, 0x50, 0xd1, 0xbf, 0x2a, 0xd0, 0x29, 0xe6, 0x90, + 0xa1, 0xff, 0xf7, 0xff, 0x0e, 0xb7, 0x04, 0xf6, 0x77, 0x0b, 0x1e, 0x4a, 0xac, 0x06, 0x8a, 0xa8, + 0x3e, 0x8c, 0xcc, 0x58, 0x87, 0x06, 0x8d, 0x87, 0x9a, 0xf9, 0x54, 0x5e, 0xd4, 0x69, 0xac, 0xa9, + 0x14, 0x41, 0x2b, 0xfb, 0x51, 0xb2, 0xe6, 0x8c, 0x32, 0x60, 0x14, 0x04, 0x6f, 0x3e, 0x06, 0xf0, + 0xce, 0xb3, 0x5b, 0xcf, 0xaa, 0x5b, 0x7b, 0xe7, 0x05, 0x7a, 0x52, 0xf5, 0xf2, 0xa0, 0x58, 0x2f, + 0x3f, 0x54, 0x60, 0x55, 0xd3, 0xb7, 0x44, 0xe4, 0x6e, 0x0c, 0xae, 0xb0, 0xb2, 0x6e, 0xc1, 0xaa, + 0xcc, 0xf3, 0xd5, 0xe9, 0x3c, 0x5f, 0x2b, 0xf1, 0xfc, 0x77, 0xb0, 0x2a, 0x5f, 0xe4, 0x08, 0x27, + 0x1e, 0xe1, 0x7d, 0x22, 0xc7, 0x8d, 0x13, 0x1a, 0x4b, 0xbe, 0x57, 0xed, 0xb6, 0x92, 0xb5, 0x5b, + 0x11, 0x09, 0xbf, 0x25, 0x12, 0x8e, 0x52, 0x58, 0xfc, 0xca, 0x8f, 0xce, 0x0f, 0x63, 0xe2, 0x98, + 0x47, 0xbf, 0x96, 0x0c, 0xdf, 0xad, 0x33, 0xc9, 0xe9, 0x6a, 0x3c, 0x66, 0x84, 0x6b, 0x2e, 0xd2, + 0x12, 0xfa, 0x02, 0x9a, 0xc6, 0x6d, 0xbf, 0xbb, 0x33, 0x6d, 0xbe, 0x32, 0x2f, 0x66, 0x95, 0xfb, + 0xd7, 0xef, 0xe1, 0x91, 0x39, 0xbc, 0x13, 0x05, 0x71, 0x14, 0x8a, 0xb4, 0xe2, 0x24, 0x10, 0x10, + 0xe8, 0xd1, 0xa8, 0x65, 0x5b, 0x51, 0x5c, 0x66, 0xf0, 0x9a, 0x61, 0xf0, 0xbf, 0xc2, 0xc3, 0x89, + 0xe3, 0xd7, 0x46, 0xf0, 0x39, 0xcc, 0x50, 0x4e, 0x02, 0x35, 0xdf, 0x35, 0xb7, 0x37, 0xf2, 0x9c, + 0xbe, 0xd6, 0xbd, 0xad, 0xb4, 0xd1, 0x6b, 0x98, 0x33, 0xbf, 0xcb, 0x87, 0x79, 0x06, 0x33, 0x49, + 0xea, 0x13, 0x33, 0xf8, 0x5d, 0xff, 0x16, 0x4a, 0x05, 0x39, 0xb0, 0x70, 0x3c, 0x38, 0x28, 0x1d, + 0xbf, 0x5b, 0xf5, 0x65, 0x4e, 0xac, 0xdb, 0x9d, 0xbc, 0x00, 0x78, 0x13, 0xe3, 0xef, 0x53, 0x22, + 0xed, 0x2f, 0x42, 0xf5, 0x94, 0x5c, 0x4a, 0x07, 0x73, 0xb6, 0x58, 0x4e, 0x69, 0x7c, 0xe7, 0xb0, + 0xdc, 0x8f, 0x6d, 0x82, 0x9d, 0x13, 0x71, 0xac, 0x34, 0x40, 0x8f, 0x71, 0x40, 0xfd, 0x4b, 0x33, + 0x40, 0x2b, 0x49, 0x54, 0xad, 0x99, 0x56, 0x55, 0x54, 0x0d, 0xbb, 0xae, 0xc7, 0x55, 0x26, 0xc2, + 0x0d, 0xfd, 0x84, 0x0a, 0x0a, 0xba, 0x21, 0x5c, 0xa9, 0x82, 0xfe, 0x02, 0x2b, 0xfd, 0xf8, 0x6d, + 0x98, 0xdc, 0xdd, 0xf5, 0x7d, 0xac, 0xff, 0xa3, 0x02, 0x6b, 0xd9, 0xec, 0xc3, 0x04, 0xea, 0x74, + 0x4c, 0x9d, 0xbd, 0x0b, 0x4e, 0x42, 0x97, 0xb8, 0xed, 0xa7, 0xd0, 0xa2, 0x6c, 0xc8, 0x13, 0x1c, + 0x32, 0xca, 0xe9, 0x99, 0x4a, 0x90, 0xba, 0x3d, 0x47, 0xd9, 0x51, 0xb6, 0x27, 0x06, 0x73, 0x96, + 0x8e, 0x86, 0x32, 0x81, 0x54, 0x69, 0x3c, 0x60, 0xe9, 0xe8, 0x48, 0xe4, 0x90, 0xaa, 0xca, 0x6a, + 0x56, 0x95, 0x1b, 0xd0, 0x54, 0x63, 0xb6, 0x9a, 0x5e, 0x54, 0x55, 0xa8, 0xc9, 0xbb, 0x2b, 0x76, + 0xd0, 0xbf, 0x2b, 0xb0, 0xde, 0x1b, 0x9c, 0xbd, 0xd0, 0x74, 0xf3, 0x7f, 0x0f, 0x68, 0xea, 0x14, + 0x7e, 0x7b, 0x68, 0xff, 0xac, 0xc0, 0x7a, 0x3e, 0x83, 0x7d, 0x00, 0x58, 0x3d, 0x83, 0xf6, 0x31, + 0xf6, 0xa9, 0x2b, 0x87, 0xde, 0x2c, 0x8c, 0x65, 0x98, 0x61, 0x1c, 0x73, 0x53, 0xcb, 0x4a, 0x40, + 0x9f, 0x40, 0x6b, 0x27, 0xf2, 0xa3, 0xa4, 0xa8, 0xe6, 0x88, 0x0d, 0xa3, 0x26, 0x05, 0xf4, 0x6b, + 0x68, 0xc9, 0x51, 0x3a, 0x53, 0xdb, 0x80, 0x26, 0x4f, 0xc3, 0x90, 0xf8, 0xc3, 0x02, 0x3f, 0x80, + 0xda, 0x12, 0x51, 0xa3, 0x0e, 0xac, 0xec, 0x92, 0x31, 0x4e, 0x7d, 0xfe, 0x35, 0xe6, 0xe4, 0x1c, + 0x5f, 0x9a, 0xa3, 0xe8, 0x5b, 0x98, 0x57, 0x75, 0x76, 0x3f, 0x84, 0xb2, 0xf2, 0xab, 0x16, 0xcb, + 0xcf, 0x86, 0xc5, 0xbd, 0xc3, 0x9e, 0x6c, 0x48, 0x99, 0xb9, 0x4d, 0x58, 0xa4, 0x6c, 0xc8, 0x68, + 0xe8, 0xf9, 0x64, 0x88, 0x9d, 0x82, 0xc5, 0x79, 0xca, 0x0e, 0xe5, 0x76, 0xd7, 0x31, 0x36, 0x55, + 0x8b, 0xb3, 0x8a, 0x2d, 0x6e, 0x1b, 0x96, 0xf6, 0x0e, 0x7b, 0x41, 0x1c, 0x25, 0xbc, 0xd0, 0x57, + 0x44, 0xe5, 0x12, 0x36, 0xa4, 0x72, 0x5f, 0x8f, 0xec, 0x75, 0xc2, 0x94, 0x1e, 0x7a, 0x0b, 0x4b, + 0x7d, 0xec, 0xf4, 0xa3, 0x11, 0xf5, 0x29, 0xcf, 0xee, 0x2a, 0x7b, 0x34, 0x1b, 0x32, 0x4e, 0x9d, + 0xd3, 0x4b, 0x1d, 0x43, 0x9d, 0xb2, 0x43, 0x29, 0x8b, 0x1e, 0xcf, 0xc8, 0xf7, 0x29, 0x09, 0x1d, + 0x32, 0x0c, 0xd3, 0xc0, 0x4c, 0x4c, 0x66, 0xef, 0x20, 0x0d, 0xd0, 0x27, 0xf0, 0x50, 0x86, 0x90, + 0xf4, 0x71, 0x9e, 0x50, 0xe2, 0xbf, 0x2b, 0x76, 0x74, 0x08, 0x62, 0x89, 0x5e, 0xc1, 0xd2, 0x51, + 0x82, 0xc7, 0x63, 0xea, 0xd8, 0x98, 0xe7, 0xb8, 0x5e, 0xed, 0x7d, 0x6d, 0xa8, 0x25, 0x22, 0x03, + 0x84, 0x23, 0xcb, 0x96, 0x6b, 0xf4, 0x2d, 0x3c, 0xd2, 0x47, 0x05, 0x26, 0x85, 0x7c, 0x59, 0x83, + 0x3a, 0x27, 0x49, 0x40, 0x43, 0xec, 0x9b, 0xc8, 0x8d, 0x2c, 0x18, 0x86, 0xe1, 0x20, 0xf6, 0x95, + 0xa9, 0xba, 0xad, 0x25, 0xf4, 0x16, 0x90, 0x4d, 0x5c, 0x9a, 0x10, 0x87, 0xdf, 0x40, 0x1e, 0x57, + 0xc3, 0xba, 0x92, 0xd0, 0xd6, 0x44, 0x42, 0xff, 0x0d, 0x9e, 0x1a, 0xb3, 0x37, 0x71, 0xc0, 0xd4, + 0xbf, 0x76, 0xb7, 0x7b, 0x38, 0xce, 0x3d, 0xdc, 0x54, 0xca, 0xf7, 0x8e, 0xfc, 0x97, 0x19, 0xba, + 0x36, 0x09, 0x70, 0x72, 0x9a, 0x59, 0x6a, 0x43, 0xcd, 0x65, 0x8e, 0xe9, 0xca, 0x72, 0x8d, 0xbe, + 0x80, 0x85, 0xb7, 0xe1, 0x69, 0x18, 0x9d, 0x87, 0x45, 0xb5, 0x3b, 0xfe, 0x01, 0x3b, 0x86, 0x8f, + 0xcc, 0xa9, 0x6b, 0x3f, 0x1a, 0xbc, 0x9c, 0xfc, 0x68, 0x30, 0xad, 0x05, 0x94, 0x3e, 0x25, 0xec, + 0xc0, 0x62, 0x97, 0xbd, 0xf8, 0x91, 0x9f, 0x6d, 0xbe, 0x84, 0x95, 0x2e, 0x7b, 0xf1, 0xe3, 0xbe, + 0x86, 0x10, 0x58, 0x1a, 0x04, 0x8c, 0x1e, 0x49, 0x8a, 0xc9, 0x0d, 0x2c, 0xc3, 0xcc, 0xd8, 0xc7, + 0x9e, 0x79, 0x15, 0x25, 0x64, 0xb8, 0x59, 0x65, 0xdc, 0x54, 0xb1, 0x57, 0x0b, 0xc5, 0xae, 0xbf, + 0x88, 0xd4, 0x24, 0x94, 0x16, 0x75, 0xd1, 0x1f, 0xe1, 0x63, 0xe5, 0x42, 0xf2, 0xdd, 0x61, 0x3a, + 0x3a, 0xda, 0x3f, 0x2e, 0x7d, 0x45, 0x28, 0x4e, 0x06, 0x2d, 0x35, 0x19, 0xac, 0xc0, 0xac, 0x13, + 0x45, 0xa7, 0xd4, 0x3c, 0x89, 0x96, 0xd0, 0x6f, 0x61, 0x75, 0xc2, 0xd6, 0x40, 0x20, 0xed, 0x44, + 0xbe, 0xa8, 0xaf, 0x58, 0xaf, 0xb5, 0xad, 0x4c, 0x46, 0x5b, 0xb0, 0x32, 0x71, 0x50, 0xd2, 0xf4, + 0x14, 0x7a, 0xde, 0x85, 0xce, 0x84, 0xbe, 0x4e, 0xa5, 0x7b, 0xa4, 0xd0, 0x01, 0xcc, 0x17, 0xac, + 0x1c, 0xed, 0x1f, 0x5f, 0x7b, 0x76, 0x13, 0x6a, 0xdc, 0x3f, 0xbb, 0x79, 0xa2, 0x92, 0x1a, 0x68, + 0x17, 0x96, 0x0b, 0xf6, 0xf2, 0x27, 0xfb, 0x95, 0xb6, 0xa0, 0x52, 0xa7, 0x93, 0xa7, 0x4e, 0xd9, + 0xbb, 0xb6, 0xa2, 0x3b, 0xff, 0xcb, 0x0f, 0xb0, 0xf3, 0x97, 0x79, 0xe9, 0xe5, 0x7b, 0xe0, 0xa5, + 0x3f, 0xc3, 0x46, 0x6f, 0xf0, 0xf2, 0xbd, 0x14, 0xf6, 0x33, 0x58, 0xec, 0x52, 0x4f, 0x00, 0xdd, + 0xfb, 0x7a, 0xd0, 0x27, 0x3c, 0xa1, 0x8e, 0x48, 0xe4, 0x40, 0xae, 0x64, 0xa0, 0x35, 0x5b, 0x4b, + 0xe8, 0x35, 0xcc, 0x6b, 0xdd, 0xfb, 0x67, 0xd5, 0x2b, 0x68, 0x89, 0xb3, 0x79, 0xc0, 0x9b, 0xa5, + 0xe7, 0xbf, 0x29, 0x81, 0x52, 0x98, 0xdf, 0x17, 0xbd, 0xd7, 0xdc, 0x5b, 0xb6, 0x4c, 0xcf, 0x8f, + 0x46, 0x19, 0x62, 0xca, 0x7d, 0x53, 0xed, 0x49, 0xc8, 0x72, 0x4c, 0x5d, 0xcc, 0xf1, 0x6f, 0x4a, + 0x98, 0xee, 0x8a, 0x9d, 0xb2, 0xc2, 0xb6, 0x66, 0x83, 0x5c, 0x61, 0x1b, 0xfd, 0x49, 0xfc, 0xc3, + 0x2d, 0xb8, 0x2d, 0xc1, 0xfd, 0xfa, 0x3a, 0xb8, 0x0b, 0x39, 0x5c, 0x0e, 0xb8, 0x0c, 0xb9, 0x0d, + 0x8b, 0x1a, 0xbf, 0x77, 0xe4, 0xaf, 0xc9, 0x01, 0x68, 0x34, 0x2b, 0x71, 0xfb, 0xec, 0x7f, 0x01, + 0x00, 0x00, 0xff, 0xff, 0xf2, 0x23, 0xd6, 0xcf, 0xfa, 0x17, 0x00, 0x00, +} diff -Nru gobgp-1.32/api/attribute.proto gobgp-1.33/api/attribute.proto --- gobgp-1.32/api/attribute.proto 1970-01-01 00:00:00.000000000 +0000 +++ gobgp-1.33/api/attribute.proto 2018-07-01 12:06:57.000000000 +0000 @@ -0,0 +1,504 @@ +// Copyright (C) 2018 Nippon Telegraph and Telephone Corporation. +// +// Permission is hereby granted, free of charge, to any person +// obtaining a copy of this software and associated documentation files +// (the "Software"), to deal in the Software without restriction, +// including without limitation the rights to use, copy, modify, merge, +// publish, distribute, sublicense, and/or sell copies of the Software, +// and to permit persons to whom the Software is furnished to do so, +// subject to the following conditions: +// +// The above copyright notice and this permission notice shall be +// included in all copies or substantial portions of the Software. + +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +syntax = "proto3"; + +import "google/protobuf/any.proto"; + +package gobgpapi; + +message OriginAttribute { + uint32 origin = 1; +} + +message AsSegment { + uint32 type = 1; + repeated uint32 numbers = 2; +} + +message AsPathAttribute { + repeated AsSegment segments = 1; +} + +message NextHopAttribute { + string next_hop = 1; +} + +message MultiExitDiscAttribute { + uint32 med = 1; +} + +message LocalPrefAttribute { + uint32 local_pref = 1; +} + +message AtomicAggregateAttribute { +} + +message AggregatorAttribute { + uint32 as = 2; + string address = 3; +} + +message CommunitiesAttribute { + repeated uint32 communities = 1; +} + +message OriginatorIdAttribute { + string id = 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; +} + +// 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; +} + +// EncapsulationNLRI represents the NLRI for: +// - AFI=1, SAFI=7 +// - AFI=2, SAFI=7 +message EncapsulationNLRI { + string address = 1; +} + +message RouteDistinguisherTwoOctetAS { + uint32 admin = 1; + uint32 assigned = 2; +} + +message RouteDistinguisherIPAddress { + string admin = 1; + uint32 assigned = 2; +} + +message RouteDistinguisherFourOctetAS { + uint32 admin = 1; + uint32 assigned = 2; +} + +message EthernetSegmentIdentifier { + 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; +} + +// 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; +} + +// 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; +} + +// 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; +} + +// 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; +} + +// 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; +} + +// RouteTargetMembershipNLRI represents the NLRI for: +// - AFI=1, SAFI=132 +message RouteTargetMembershipNLRI { + 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; +} + +message FlowSpecMAC { + uint32 type = 1; + string address = 2; +} + +message FlowSpecComponentItem { + // Operator for Numeric type, Operand for Bitmask type + uint32 op = 1; + uint64 value = 2; +} + +message FlowSpecComponent { + 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; +} + +// VPNFlowSpecNLRI represents the NLRI for: +// - AFI=1, SAFI=134 +// - 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; +} + +// OpaqueNLRI represents the NLRI for: +// - AFI=16397, SAFI=241 +message OpaqueNLRI { + bytes key = 1; + bytes value = 2; +} + +message MpReachNLRIAttribute { + uint32 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; +} + +message MpUnreachNLRIAttribute { + uint32 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; +} + +message IPv4AddressSpecificExtended { + 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; +} + +message ValidationExtended { + uint32 state = 1; +} + +message ColorExtended { + uint32 color = 1; +} + +message EncapExtended { + uint32 tunnel_type = 1; +} + +message DefaultGatewayExtended { +} + +message OpaqueExtended { + bool is_transitive = 1; + bytes value = 3; +} + +message ESILabelExtended { + bool is_single_active = 1; + uint32 label = 2; +} + +message ESImportRouteTarget { + string es_import = 1; +} + +message MacMobilityExtended { + bool is_sticky = 1; + uint32 sequence_num = 2; +} + +message RouterMacExtended { + string mac = 1; +} + +message TrafficRateExtended { + uint32 as = 1; + float rate = 2; +} + +message TrafficActionExtended { + bool terminal = 1; + bool sample = 2; +} + +message RedirectTwoOctetAsSpecificExtended { + uint32 as = 1; + uint32 local_admin = 2; +} + +message RedirectIPv4AddressSpecificExtended { + string address = 1; + uint32 local_admin = 2; +} + +message RedirectFourOctetAsSpecificExtended { + uint32 as = 1; + uint32 local_admin = 2; +} + +message TrafficRemarkExtended { + uint32 dscp = 1; +} + +message UnknownExtended { + 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; +} + +message As4PathAttribute { + repeated AsSegment segments = 1; +} + +message As4AggregatorAttribute { + uint32 as = 2; + string address = 3; +} + +message PmsiTunnelAttribute { + uint32 flags = 1; + uint32 type = 2; + uint32 label = 3; + bytes id = 4; +} + +message TunnelEncapSubTLVEncapsulation { + uint32 key = 1; + bytes cookie = 2; +} + +message TunnelEncapSubTLVProtocol { + uint32 protocol = 1; +} + +message TunnelEncapSubTLVColor { + uint32 color = 1; +} + +message TunnelEncapSubTLVUnknown { + 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; +} + +message TunnelEncapAttribute { + repeated TunnelEncapTLV tlvs = 1; +} + +message IPv6AddressSpecificExtended { + bool is_transitive = 1; + uint32 sub_type = 2; + string address = 3; + uint32 local_admin = 4; +} + +message RedirectIPv6AddressSpecificExtended { + string address = 1; + uint32 local_admin = 2; +} + +message IP6ExtendedCommunitiesAttribute { + // Each Community must be one of: + // - IPv6AddressSpecificExtended + // - RedirectIPv6AddressSpecificExtended + repeated google.protobuf.Any communities = 1; +} + +message AigpTLVIGPMetric { + uint64 metric = 1; +} + +message AigpTLVUnknown { + uint32 type = 1; + bytes value = 2; +} + +message AigpAttribute { + // 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; +} + +message LargeCommunitiesAttribute { + repeated LargeCommunity communities = 1; +} + +message UnknownAttribute { + uint32 flags = 1; + uint32 type = 2; + bytes value = 3; +} diff -Nru gobgp-1.32/api/attribute_test.go gobgp-1.33/api/attribute_test.go --- gobgp-1.32/api/attribute_test.go 1970-01-01 00:00:00.000000000 +0000 +++ gobgp-1.33/api/attribute_test.go 2018-07-01 12:06:57.000000000 +0000 @@ -0,0 +1,1416 @@ +// 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 gobgpapi + +import ( + "net" + "testing" + + "github.com/osrg/gobgp/packet/bgp" + + "github.com/golang/protobuf/ptypes" + "github.com/golang/protobuf/ptypes/any" + "github.com/stretchr/testify/assert" +) + +func Test_OriginAttribute(t *testing.T) { + assert := assert.New(t) + + input := &OriginAttribute{ + Origin: 0, // IGP + } + + n, err := input.ToNative() + assert.Nil(err) + + output := NewOriginAttributeFromNative(n) + assert.Equal(input.Origin, output.Origin) +} + +func Test_AsPathAttribute(t *testing.T) { + assert := assert.New(t) + + input := &AsPathAttribute{ + Segments: []*AsSegment{ + { + Type: 1, // SET + Numbers: []uint32{100, 200}, + }, + { + Type: 2, // SEQ + Numbers: []uint32{300, 400}, + }, + }, + } + + n, err := input.ToNative() + assert.Nil(err) + + output := NewAsPathAttributeFromNative(n) + assert.Equal(2, len(output.Segments)) + assert.Equal(input.Segments, output.Segments) +} + +func Test_NextHopAttribute(t *testing.T) { + assert := assert.New(t) + + input := &NextHopAttribute{ + NextHop: "192.168.0.1", + } + + n, err := input.ToNative() + assert.Nil(err) + + output := NewNextHopAttributeFromNative(n) + assert.Equal(input.NextHop, output.NextHop) +} + +func Test_MultiExitDiscAttribute(t *testing.T) { + assert := assert.New(t) + + input := &MultiExitDiscAttribute{ + Med: 100, + } + + n, err := input.ToNative() + assert.Nil(err) + + output := NewMultiExitDiscAttributeFromNative(n) + assert.Equal(input.Med, output.Med) +} + +func Test_LocalPrefAttribute(t *testing.T) { + assert := assert.New(t) + + input := &LocalPrefAttribute{ + LocalPref: 100, + } + + n, err := input.ToNative() + assert.Nil(err) + + output := NewLocalPrefAttributeFromNative(n) + assert.Equal(input.LocalPref, output.LocalPref) +} + +func Test_AtomicAggregateAttribute(t *testing.T) { + assert := assert.New(t) + + input := &AtomicAggregateAttribute{} + + n, err := input.ToNative() + assert.Nil(err) + + output := NewAtomicAggregateAttributeFromNative(n) + // AtomicAggregateAttribute has no value + assert.NotNil(output) +} + +func Test_AggregatorAttribute(t *testing.T) { + assert := assert.New(t) + + input := &AggregatorAttribute{ + As: 65000, + Address: "1.1.1.1", + } + + n, err := input.ToNative() + assert.Nil(err) + + output := NewAggregatorAttributeFromNative(n) + assert.Equal(input.As, output.As) + assert.Equal(input.Address, output.Address) +} + +func Test_CommunitiesAttribute(t *testing.T) { + assert := assert.New(t) + + input := &CommunitiesAttribute{ + Communities: []uint32{100, 200}, + } + + n, err := input.ToNative() + assert.Nil(err) + + output := NewCommunitiesAttributeFromNative(n) + assert.Equal(input.Communities, output.Communities) +} + +func Test_OriginatorIdAttribute(t *testing.T) { + assert := assert.New(t) + + input := &OriginatorIdAttribute{ + Id: "1.1.1.1", + } + + n, err := input.ToNative() + assert.Nil(err) + + output := NewOriginatorIdAttributeFromNative(n) + assert.Equal(input.Id, output.Id) +} + +func Test_ClusterListAttribute(t *testing.T) { + assert := assert.New(t) + + input := &ClusterListAttribute{ + Ids: []string{"1.1.1.1", "2.2.2.2"}, + } + + n, err := input.ToNative() + assert.Nil(err) + + output := NewClusterListAttributeFromNative(n) + assert.Equal(input.Ids, output.Ids) +} + +func Test_MpReachNLRIAttribute_IPv4_UC(t *testing.T) { + assert := assert.New(t) + + nlris := make([]*any.Any, 0, 2) + a, err := ptypes.MarshalAny(&IPAddressPrefix{ + PrefixLen: 24, + Prefix: "192.168.101.0", + }) + assert.Nil(err) + nlris = append(nlris, a) + a, err = ptypes.MarshalAny(&IPAddressPrefix{ + PrefixLen: 24, + Prefix: "192.168.201.0", + }) + assert.Nil(err) + nlris = append(nlris, a) + + input := &MpReachNLRIAttribute{ + Family: uint32(bgp.RF_IPv4_UC), + NextHops: []string{"192.168.1.1"}, + Nlris: nlris, + } + + n, err := input.ToNative() + assert.Nil(err) + + output := NewMpReachNLRIAttributeFromNative(n) + assert.Equal(input.Family, output.Family) + assert.Equal(input.NextHops, output.NextHops) + assert.Equal(2, len(output.Nlris)) + for idx, inputNLRI := range input.Nlris { + outputNLRI := output.Nlris[idx] + assert.Equal(inputNLRI.TypeUrl, outputNLRI.TypeUrl) + assert.Equal(inputNLRI.Value, outputNLRI.Value) + } +} + +func Test_MpReachNLRIAttribute_IPv6_UC(t *testing.T) { + assert := assert.New(t) + + nlris := make([]*any.Any, 0, 2) + a, err := ptypes.MarshalAny(&IPAddressPrefix{ + PrefixLen: 64, + Prefix: "2001:db8:1::", + }) + assert.Nil(err) + nlris = append(nlris, a) + a, err = ptypes.MarshalAny(&IPAddressPrefix{ + PrefixLen: 64, + Prefix: "2001:db8:2::", + }) + assert.Nil(err) + nlris = append(nlris, a) + + input := &MpReachNLRIAttribute{ + Family: uint32(bgp.RF_IPv6_UC), + NextHops: []string{"2001:db8::1", "2001:db8::2"}, + Nlris: nlris, + } + + n, err := input.ToNative() + assert.Nil(err) + + output := NewMpReachNLRIAttributeFromNative(n) + assert.Equal(input.Family, output.Family) + assert.Equal(input.NextHops, output.NextHops) + assert.Equal(2, len(output.Nlris)) + for idx, inputNLRI := range input.Nlris { + outputNLRI := output.Nlris[idx] + assert.Equal(inputNLRI.TypeUrl, outputNLRI.TypeUrl) + assert.Equal(inputNLRI.Value, outputNLRI.Value) + } +} + +func Test_MpReachNLRIAttribute_IPv4_MPLS(t *testing.T) { + assert := assert.New(t) + + nlris := make([]*any.Any, 0, 2) + a, err := ptypes.MarshalAny(&LabeledIPAddressPrefix{ + Labels: []uint32{100}, + PrefixLen: 24, + Prefix: "192.168.101.0", + }) + assert.Nil(err) + nlris = append(nlris, a) + a, err = ptypes.MarshalAny(&LabeledIPAddressPrefix{ + Labels: []uint32{200}, + PrefixLen: 24, + Prefix: "192.168.201.0", + }) + assert.Nil(err) + nlris = append(nlris, a) + + input := &MpReachNLRIAttribute{ + Family: uint32(bgp.RF_IPv4_MPLS), + NextHops: []string{"192.168.1.1"}, + Nlris: nlris, + } + + n, err := input.ToNative() + assert.Nil(err) + + output := NewMpReachNLRIAttributeFromNative(n) + assert.Equal(input.Family, output.Family) + assert.Equal(input.NextHops, output.NextHops) + assert.Equal(2, len(output.Nlris)) + for idx, inputNLRI := range input.Nlris { + outputNLRI := output.Nlris[idx] + assert.Equal(inputNLRI.TypeUrl, outputNLRI.TypeUrl) + assert.Equal(inputNLRI.Value, outputNLRI.Value) + } +} + +func Test_MpReachNLRIAttribute_IPv6_MPLS(t *testing.T) { + assert := assert.New(t) + + nlris := make([]*any.Any, 0, 2) + a, err := ptypes.MarshalAny(&LabeledIPAddressPrefix{ + Labels: []uint32{100}, + PrefixLen: 64, + Prefix: "2001:db8:1::", + }) + assert.Nil(err) + nlris = append(nlris, a) + a, err = ptypes.MarshalAny(&LabeledIPAddressPrefix{ + Labels: []uint32{200}, + PrefixLen: 64, + Prefix: "2001:db8:2::", + }) + assert.Nil(err) + nlris = append(nlris, a) + + input := &MpReachNLRIAttribute{ + Family: uint32(bgp.RF_IPv6_MPLS), + NextHops: []string{"2001:db8::1"}, + Nlris: nlris, + } + + n, err := input.ToNative() + assert.Nil(err) + + output := NewMpReachNLRIAttributeFromNative(n) + assert.Equal(input.Family, output.Family) + assert.Equal(input.NextHops, output.NextHops) + assert.Equal(2, len(output.Nlris)) + for idx, inputNLRI := range input.Nlris { + outputNLRI := output.Nlris[idx] + assert.Equal(inputNLRI.TypeUrl, outputNLRI.TypeUrl) + assert.Equal(inputNLRI.Value, outputNLRI.Value) + } +} + +func Test_MpReachNLRIAttribute_IPv4_ENCAP(t *testing.T) { + assert := assert.New(t) + + nlris := make([]*any.Any, 0, 2) + a, err := ptypes.MarshalAny(&EncapsulationNLRI{ + Address: "192.168.101.1", + }) + assert.Nil(err) + nlris = append(nlris, a) + a, err = ptypes.MarshalAny(&EncapsulationNLRI{ + Address: "192.168.201.1", + }) + assert.Nil(err) + nlris = append(nlris, a) + + input := &MpReachNLRIAttribute{ + Family: uint32(bgp.RF_IPv4_ENCAP), + NextHops: []string{"192.168.1.1"}, + Nlris: nlris, + } + + n, err := input.ToNative() + assert.Nil(err) + + output := NewMpReachNLRIAttributeFromNative(n) + assert.Equal(input.Family, output.Family) + assert.Equal(input.NextHops, output.NextHops) + assert.Equal(2, len(output.Nlris)) + for idx, inputNLRI := range input.Nlris { + outputNLRI := output.Nlris[idx] + assert.Equal(inputNLRI.TypeUrl, outputNLRI.TypeUrl) + assert.Equal(inputNLRI.Value, outputNLRI.Value) + } +} + +func Test_MpReachNLRIAttribute_IPv6_ENCAP(t *testing.T) { + assert := assert.New(t) + + nlris := make([]*any.Any, 0, 2) + a, err := ptypes.MarshalAny(&EncapsulationNLRI{ + Address: "2001:db8:1::1", + }) + assert.Nil(err) + nlris = append(nlris, a) + a, err = ptypes.MarshalAny(&EncapsulationNLRI{ + Address: "2001:db8:2::1", + }) + assert.Nil(err) + nlris = append(nlris, a) + + input := &MpReachNLRIAttribute{ + Family: uint32(bgp.RF_IPv6_ENCAP), + NextHops: []string{"2001:db8::1"}, + Nlris: nlris, + } + + n, err := input.ToNative() + assert.Nil(err) + + output := NewMpReachNLRIAttributeFromNative(n) + assert.Equal(input.Family, output.Family) + assert.Equal(input.NextHops, output.NextHops) + assert.Equal(2, len(output.Nlris)) + for idx, inputNLRI := range input.Nlris { + outputNLRI := output.Nlris[idx] + assert.Equal(inputNLRI.TypeUrl, outputNLRI.TypeUrl) + assert.Equal(inputNLRI.Value, outputNLRI.Value) + } +} + +func Test_MpReachNLRIAttribute_EVPN_AD_Route(t *testing.T) { + assert := assert.New(t) + + nlris := make([]*any.Any, 0, 1) + rd, err := ptypes.MarshalAny(&RouteDistinguisherTwoOctetAS{ + Admin: 65000, + Assigned: 100, + }) + assert.Nil(err) + esi := &EthernetSegmentIdentifier{ + Type: 0, + Value: []byte{1, 2, 3, 4, 5, 6, 7, 8, 9}, + } + a, err := ptypes.MarshalAny(&EVPNEthernetAutoDiscoveryRoute{ + Rd: rd, + Esi: esi, + EthernetTag: 100, + Label: 200, + }) + assert.Nil(err) + nlris = append(nlris, a) + + input := &MpReachNLRIAttribute{ + Family: uint32(bgp.RF_EVPN), + NextHops: []string{"192.168.1.1"}, + Nlris: nlris, + } + + n, err := input.ToNative() + assert.Nil(err) + + output := NewMpReachNLRIAttributeFromNative(n) + assert.Equal(input.Family, output.Family) + assert.Equal(input.NextHops, output.NextHops) + assert.Equal(1, len(output.Nlris)) + for idx, inputNLRI := range input.Nlris { + outputNLRI := output.Nlris[idx] + assert.Equal(inputNLRI.TypeUrl, outputNLRI.TypeUrl) + assert.Equal(inputNLRI.Value, outputNLRI.Value) + } +} + +func Test_MpReachNLRIAttribute_EVPN_MAC_IP_Route(t *testing.T) { + assert := assert.New(t) + + nlris := make([]*any.Any, 0, 1) + rd, err := ptypes.MarshalAny(&RouteDistinguisherIPAddress{ + Admin: "1.1.1.1", + Assigned: 100, + }) + assert.Nil(err) + esi := &EthernetSegmentIdentifier{ + Type: 0, + Value: []byte{1, 2, 3, 4, 5, 6, 7, 8, 9}, + } + a, err := ptypes.MarshalAny(&EVPNMACIPAdvertisementRoute{ + Rd: rd, + Esi: esi, + EthernetTag: 100, + MacAddress: "aa:bb:cc:dd:ee:ff", + IpAddress: "192.168.101.1", + Labels: []uint32{200}, + }) + assert.Nil(err) + nlris = append(nlris, a) + + input := &MpReachNLRIAttribute{ + Family: uint32(bgp.RF_EVPN), + NextHops: []string{"192.168.1.1"}, + Nlris: nlris, + } + + n, err := input.ToNative() + assert.Nil(err) + + output := NewMpReachNLRIAttributeFromNative(n) + assert.Equal(input.Family, output.Family) + assert.Equal(input.NextHops, output.NextHops) + assert.Equal(1, len(output.Nlris)) + for idx, inputNLRI := range input.Nlris { + outputNLRI := output.Nlris[idx] + assert.Equal(inputNLRI.TypeUrl, outputNLRI.TypeUrl) + assert.Equal(inputNLRI.Value, outputNLRI.Value) + } +} + +func Test_MpReachNLRIAttribute_EVPN_MC_Route(t *testing.T) { + assert := assert.New(t) + + nlris := make([]*any.Any, 0, 1) + rd, err := ptypes.MarshalAny(&RouteDistinguisherFourOctetAS{ + Admin: 65000, + Assigned: 100, + }) + assert.Nil(err) + a, err := ptypes.MarshalAny(&EVPNInclusiveMulticastEthernetTagRoute{ + Rd: rd, + EthernetTag: 100, + IpAddress: "192.168.101.1", + }) + assert.Nil(err) + nlris = append(nlris, a) + + input := &MpReachNLRIAttribute{ + Family: uint32(bgp.RF_EVPN), + NextHops: []string{"192.168.1.1"}, + Nlris: nlris, + } + + n, err := input.ToNative() + assert.Nil(err) + + output := NewMpReachNLRIAttributeFromNative(n) + assert.Equal(input.Family, output.Family) + assert.Equal(input.NextHops, output.NextHops) + assert.Equal(1, len(output.Nlris)) + for idx, inputNLRI := range input.Nlris { + outputNLRI := output.Nlris[idx] + assert.Equal(inputNLRI.TypeUrl, outputNLRI.TypeUrl) + assert.Equal(inputNLRI.Value, outputNLRI.Value) + } +} + +func Test_MpReachNLRIAttribute_EVPN_ES_Route(t *testing.T) { + assert := assert.New(t) + + nlris := make([]*any.Any, 0, 1) + rd, err := ptypes.MarshalAny(&RouteDistinguisherIPAddress{ + Admin: "1.1.1.1", + Assigned: 100, + }) + assert.Nil(err) + esi := &EthernetSegmentIdentifier{ + Type: 0, + Value: []byte{1, 2, 3, 4, 5, 6, 7, 8, 9}, + } + a, err := ptypes.MarshalAny(&EVPNEthernetSegmentRoute{ + Rd: rd, + Esi: esi, + IpAddress: "192.168.101.1", + }) + assert.Nil(err) + nlris = append(nlris, a) + + input := &MpReachNLRIAttribute{ + Family: uint32(bgp.RF_EVPN), + NextHops: []string{"192.168.1.1"}, + Nlris: nlris, + } + + n, err := input.ToNative() + assert.Nil(err) + + output := NewMpReachNLRIAttributeFromNative(n) + assert.Equal(input.Family, output.Family) + assert.Equal(input.NextHops, output.NextHops) + assert.Equal(1, len(output.Nlris)) + for idx, inputNLRI := range input.Nlris { + outputNLRI := output.Nlris[idx] + assert.Equal(inputNLRI.TypeUrl, outputNLRI.TypeUrl) + assert.Equal(inputNLRI.Value, outputNLRI.Value) + } +} + +func Test_MpReachNLRIAttribute_EVPN_Prefix_Route(t *testing.T) { + assert := assert.New(t) + + nlris := make([]*any.Any, 0, 1) + rd, err := ptypes.MarshalAny(&RouteDistinguisherIPAddress{ + Admin: "1.1.1.1", + Assigned: 100, + }) + assert.Nil(err) + esi := &EthernetSegmentIdentifier{ + Type: 0, + Value: []byte{1, 2, 3, 4, 5, 6, 7, 8, 9}, + } + a, err := ptypes.MarshalAny(&EVPNIPPrefixRoute{ + Rd: rd, + Esi: esi, + EthernetTag: 100, + IpPrefixLen: 24, + IpPrefix: "192.168.101.0", + Label: 200, + }) + assert.Nil(err) + nlris = append(nlris, a) + + input := &MpReachNLRIAttribute{ + Family: uint32(bgp.RF_EVPN), + NextHops: []string{"192.168.1.1"}, + Nlris: nlris, + } + + n, err := input.ToNative() + assert.Nil(err) + + output := NewMpReachNLRIAttributeFromNative(n) + assert.Equal(input.Family, output.Family) + assert.Equal(input.NextHops, output.NextHops) + assert.Equal(1, len(output.Nlris)) + for idx, inputNLRI := range input.Nlris { + outputNLRI := output.Nlris[idx] + assert.Equal(inputNLRI.TypeUrl, outputNLRI.TypeUrl) + assert.Equal(inputNLRI.Value, outputNLRI.Value) + } +} + +func Test_MpReachNLRIAttribute_IPv4_VPN(t *testing.T) { + assert := assert.New(t) + + nlris := make([]*any.Any, 0, 1) + rd, err := ptypes.MarshalAny(&RouteDistinguisherIPAddress{ + Admin: "1.1.1.1", + Assigned: 100, + }) + assert.Nil(err) + a, err := ptypes.MarshalAny(&LabeledVPNIPAddressPrefix{ + Labels: []uint32{100, 200}, + Rd: rd, + PrefixLen: 24, + Prefix: "192.168.101.0", + }) + assert.Nil(err) + nlris = append(nlris, a) + + input := &MpReachNLRIAttribute{ + Family: uint32(bgp.RF_IPv4_VPN), + NextHops: []string{"192.168.1.1"}, + Nlris: nlris, + } + + n, err := input.ToNative() + assert.Nil(err) + + output := NewMpReachNLRIAttributeFromNative(n) + assert.Equal(input.Family, output.Family) + assert.Equal(input.NextHops, output.NextHops) + assert.Equal(1, len(output.Nlris)) + for idx, inputNLRI := range input.Nlris { + outputNLRI := output.Nlris[idx] + assert.Equal(inputNLRI.TypeUrl, outputNLRI.TypeUrl) + assert.Equal(inputNLRI.Value, outputNLRI.Value) + } +} + +func Test_MpReachNLRIAttribute_IPv6_VPN(t *testing.T) { + assert := assert.New(t) + + nlris := make([]*any.Any, 0, 1) + rd, err := ptypes.MarshalAny(&RouteDistinguisherIPAddress{ + Admin: "1.1.1.1", + Assigned: 100, + }) + assert.Nil(err) + a, err := ptypes.MarshalAny(&LabeledVPNIPAddressPrefix{ + Labels: []uint32{100, 200}, + Rd: rd, + PrefixLen: 64, + Prefix: "2001:db8:1::", + }) + assert.Nil(err) + nlris = append(nlris, a) + + input := &MpReachNLRIAttribute{ + Family: uint32(bgp.RF_IPv6_VPN), + NextHops: []string{"2001:db8::1"}, + Nlris: nlris, + } + + n, err := input.ToNative() + assert.Nil(err) + + output := NewMpReachNLRIAttributeFromNative(n) + assert.Equal(input.Family, output.Family) + assert.Equal(input.NextHops, output.NextHops) + assert.Equal(1, len(output.Nlris)) + for idx, inputNLRI := range input.Nlris { + outputNLRI := output.Nlris[idx] + assert.Equal(inputNLRI.TypeUrl, outputNLRI.TypeUrl) + assert.Equal(inputNLRI.Value, outputNLRI.Value) + } +} + +func Test_MpReachNLRIAttribute_RTC_UC(t *testing.T) { + assert := assert.New(t) + + nlris := make([]*any.Any, 0, 1) + rt, err := ptypes.MarshalAny(&IPv4AddressSpecificExtended{ + IsTransitive: true, + SubType: 0x02, // Route Target + Address: "1.1.1.1", + LocalAdmin: 100, + }) + assert.Nil(err) + a, err := ptypes.MarshalAny(&RouteTargetMembershipNLRI{ + As: 65000, + Rt: rt, + }) + assert.Nil(err) + nlris = append(nlris, a) + + input := &MpReachNLRIAttribute{ + Family: uint32(bgp.RF_RTC_UC), + NextHops: []string{"192.168.1.1"}, + Nlris: nlris, + } + + n, err := input.ToNative() + assert.Nil(err) + + output := NewMpReachNLRIAttributeFromNative(n) + assert.Equal(input.Family, output.Family) + assert.Equal(input.NextHops, output.NextHops) + assert.Equal(1, len(output.Nlris)) + for idx, inputNLRI := range input.Nlris { + outputNLRI := output.Nlris[idx] + assert.Equal(inputNLRI.TypeUrl, outputNLRI.TypeUrl) + assert.Equal(inputNLRI.Value, outputNLRI.Value) + } +} + +func Test_MpReachNLRIAttribute_FS_IPv4_UC(t *testing.T) { + assert := assert.New(t) + + rules := make([]*any.Any, 0, 3) + rule, err := ptypes.MarshalAny(&FlowSpecIPPrefix{ + Type: 1, // Destination Prefix + PrefixLen: 24, + Prefix: "192.168.101.0", + }) + assert.Nil(err) + rules = append(rules, rule) + rule, err = ptypes.MarshalAny(&FlowSpecIPPrefix{ + Type: 2, // Source Prefix + PrefixLen: 24, + Prefix: "192.168.201.0", + }) + assert.Nil(err) + rules = append(rules, rule) + rule, err = ptypes.MarshalAny(&FlowSpecComponent{ + Type: 3, // IP Protocol + Items: []*FlowSpecComponentItem{ + { + Op: 0x80 | 0x01, // End, EQ + Value: 6, // TCP + }, + }, + }) + assert.Nil(err) + rules = append(rules, rule) + + nlris := make([]*any.Any, 0, 1) + a, err := ptypes.MarshalAny(&FlowSpecNLRI{ + Rules: rules, + }) + assert.Nil(err) + nlris = append(nlris, a) + + input := &MpReachNLRIAttribute{ + Family: uint32(bgp.RF_FS_IPv4_UC), + // NextHops: // No nexthop required + Nlris: nlris, + } + + n, err := input.ToNative() + assert.Nil(err) + + output := NewMpReachNLRIAttributeFromNative(n) + assert.Equal(input.Family, output.Family) + assert.Equal(input.NextHops, output.NextHops) + assert.Equal(1, len(output.Nlris)) + for idx, inputNLRI := range input.Nlris { + outputNLRI := output.Nlris[idx] + assert.Equal(inputNLRI.TypeUrl, outputNLRI.TypeUrl) + assert.Equal(inputNLRI.Value, outputNLRI.Value) + } +} + +func Test_MpReachNLRIAttribute_FS_IPv4_VPN(t *testing.T) { + assert := assert.New(t) + + rd, err := ptypes.MarshalAny(&RouteDistinguisherIPAddress{ + Admin: "1.1.1.1", + Assigned: 100, + }) + assert.Nil(err) + + rules := make([]*any.Any, 0, 3) + rule, err := ptypes.MarshalAny(&FlowSpecIPPrefix{ + Type: 1, // Destination Prefix + PrefixLen: 24, + Prefix: "192.168.101.0", + }) + assert.Nil(err) + rules = append(rules, rule) + rule, err = ptypes.MarshalAny(&FlowSpecIPPrefix{ + Type: 2, // Source Prefix + PrefixLen: 24, + Prefix: "192.168.201.0", + }) + assert.Nil(err) + rules = append(rules, rule) + rule, err = ptypes.MarshalAny(&FlowSpecComponent{ + Type: 3, // IP Protocol + Items: []*FlowSpecComponentItem{ + { + Op: 0x80 | 0x01, // End, EQ + Value: 6, // TCP + }, + }, + }) + assert.Nil(err) + rules = append(rules, rule) + + nlris := make([]*any.Any, 0, 1) + a, err := ptypes.MarshalAny(&VPNFlowSpecNLRI{ + Rd: rd, + Rules: rules, + }) + assert.Nil(err) + nlris = append(nlris, a) + + input := &MpReachNLRIAttribute{ + Family: uint32(bgp.RF_FS_IPv4_VPN), + // NextHops: // No nexthop required + Nlris: nlris, + } + + n, err := input.ToNative() + assert.Nil(err) + + output := NewMpReachNLRIAttributeFromNative(n) + assert.Equal(input.Family, output.Family) + assert.Equal(input.NextHops, output.NextHops) + assert.Equal(1, len(output.Nlris)) + for idx, inputNLRI := range input.Nlris { + outputNLRI := output.Nlris[idx] + assert.Equal(inputNLRI.TypeUrl, outputNLRI.TypeUrl) + assert.Equal(inputNLRI.Value, outputNLRI.Value) + } +} + +func Test_MpReachNLRIAttribute_FS_IPv6_UC(t *testing.T) { + assert := assert.New(t) + + rules := make([]*any.Any, 0, 3) + rule, err := ptypes.MarshalAny(&FlowSpecIPPrefix{ + Type: 1, // Destination Prefix + PrefixLen: 64, + Prefix: "2001:db8:1::", + }) + assert.Nil(err) + rules = append(rules, rule) + rule, err = ptypes.MarshalAny(&FlowSpecIPPrefix{ + Type: 2, // Source Prefix + PrefixLen: 64, + Prefix: "2001:db8:2::", + }) + assert.Nil(err) + rules = append(rules, rule) + rule, err = ptypes.MarshalAny(&FlowSpecComponent{ + Type: 3, // Next Header + Items: []*FlowSpecComponentItem{ + { + Op: 0x80 | 0x01, // End, EQ + Value: 6, // TCP + }, + }, + }) + assert.Nil(err) + rules = append(rules, rule) + + nlris := make([]*any.Any, 0, 1) + a, err := ptypes.MarshalAny(&FlowSpecNLRI{ + Rules: rules, + }) + assert.Nil(err) + nlris = append(nlris, a) + + input := &MpReachNLRIAttribute{ + Family: uint32(bgp.RF_FS_IPv6_UC), + // NextHops: // No nexthop required + Nlris: nlris, + } + + n, err := input.ToNative() + assert.Nil(err) + + output := NewMpReachNLRIAttributeFromNative(n) + assert.Equal(input.Family, output.Family) + assert.Equal(input.NextHops, output.NextHops) + assert.Equal(1, len(output.Nlris)) + for idx, inputNLRI := range input.Nlris { + outputNLRI := output.Nlris[idx] + assert.Equal(inputNLRI.TypeUrl, outputNLRI.TypeUrl) + assert.Equal(inputNLRI.Value, outputNLRI.Value) + } +} + +func Test_MpReachNLRIAttribute_FS_IPv6_VPN(t *testing.T) { + assert := assert.New(t) + + rd, err := ptypes.MarshalAny(&RouteDistinguisherIPAddress{ + Admin: "1.1.1.1", + Assigned: 100, + }) + assert.Nil(err) + + rules := make([]*any.Any, 0, 3) + rule, err := ptypes.MarshalAny(&FlowSpecIPPrefix{ + Type: 1, // Destination Prefix + PrefixLen: 64, + Prefix: "2001:db8:1::", + }) + assert.Nil(err) + rules = append(rules, rule) + rule, err = ptypes.MarshalAny(&FlowSpecIPPrefix{ + Type: 2, // Source Prefix + PrefixLen: 64, + Prefix: "2001:db8:2::", + }) + assert.Nil(err) + rules = append(rules, rule) + rule, err = ptypes.MarshalAny(&FlowSpecComponent{ + Type: 3, // Next Header + Items: []*FlowSpecComponentItem{ + { + Op: 0x80 | 0x01, // End, EQ + Value: 6, // TCP + }, + }, + }) + assert.Nil(err) + rules = append(rules, rule) + + nlris := make([]*any.Any, 0, 1) + a, err := ptypes.MarshalAny(&VPNFlowSpecNLRI{ + Rd: rd, + Rules: rules, + }) + assert.Nil(err) + nlris = append(nlris, a) + + input := &MpReachNLRIAttribute{ + Family: uint32(bgp.RF_FS_IPv6_VPN), + // NextHops: // No nexthop required + Nlris: nlris, + } + + n, err := input.ToNative() + assert.Nil(err) + + output := NewMpReachNLRIAttributeFromNative(n) + assert.Equal(input.Family, output.Family) + assert.Equal(input.NextHops, output.NextHops) + assert.Equal(1, len(output.Nlris)) + for idx, inputNLRI := range input.Nlris { + outputNLRI := output.Nlris[idx] + assert.Equal(inputNLRI.TypeUrl, outputNLRI.TypeUrl) + assert.Equal(inputNLRI.Value, outputNLRI.Value) + } +} + +func Test_MpReachNLRIAttribute_FS_L2_VPN(t *testing.T) { + assert := assert.New(t) + + rd, err := ptypes.MarshalAny(&RouteDistinguisherIPAddress{ + Admin: "1.1.1.1", + Assigned: 100, + }) + assert.Nil(err) + + rules := make([]*any.Any, 0, 3) + rule, err := ptypes.MarshalAny(&FlowSpecMAC{ + Type: 15, // Source MAC + Address: "aa:bb:cc:11:22:33", + }) + assert.Nil(err) + rules = append(rules, rule) + rule, err = ptypes.MarshalAny(&FlowSpecMAC{ + Type: 16, // Destination MAC + Address: "dd:ee:ff:11:22:33", + }) + assert.Nil(err) + rules = append(rules, rule) + rule, err = ptypes.MarshalAny(&FlowSpecComponent{ + Type: 21, // VLAN ID + Items: []*FlowSpecComponentItem{ + { + Op: 0x80 | 0x01, // End, EQ + Value: 100, + }, + }, + }) + assert.Nil(err) + rules = append(rules, rule) + + nlris := make([]*any.Any, 0, 1) + a, err := ptypes.MarshalAny(&VPNFlowSpecNLRI{ + Rd: rd, + Rules: rules, + }) + assert.Nil(err) + nlris = append(nlris, a) + + input := &MpReachNLRIAttribute{ + Family: uint32(bgp.RF_FS_L2_VPN), + // NextHops: // No nexthop required + Nlris: nlris, + } + + n, err := input.ToNative() + assert.Nil(err) + + output := NewMpReachNLRIAttributeFromNative(n) + assert.Equal(input.Family, output.Family) + assert.Equal(input.NextHops, output.NextHops) + assert.Equal(1, len(output.Nlris)) + for idx, inputNLRI := range input.Nlris { + outputNLRI := output.Nlris[idx] + assert.Equal(inputNLRI.TypeUrl, outputNLRI.TypeUrl) + assert.Equal(inputNLRI.Value, outputNLRI.Value) + } +} + +func Test_MpUnreachNLRIAttribute_IPv4_UC(t *testing.T) { + assert := assert.New(t) + + nlris := make([]*any.Any, 0, 2) + a, err := ptypes.MarshalAny(&IPAddressPrefix{ + PrefixLen: 24, + Prefix: "192.168.101.0", + }) + assert.Nil(err) + nlris = append(nlris, a) + a, err = ptypes.MarshalAny(&IPAddressPrefix{ + PrefixLen: 24, + Prefix: "192.168.201.0", + }) + assert.Nil(err) + nlris = append(nlris, a) + + input := &MpUnreachNLRIAttribute{ + Family: uint32(bgp.RF_IPv4_UC), + Nlris: nlris, + } + + n, err := input.ToNative() + assert.Nil(err) + + output := NewMpUnreachNLRIAttributeFromNative(n) + assert.Equal(input.Family, output.Family) + assert.Equal(2, len(output.Nlris)) + for idx, inputNLRI := range input.Nlris { + outputNLRI := output.Nlris[idx] + assert.Equal(inputNLRI.TypeUrl, outputNLRI.TypeUrl) + assert.Equal(inputNLRI.Value, outputNLRI.Value) + } +} + +func Test_ExtendedCommunitiesAttribute(t *testing.T) { + assert := assert.New(t) + + communities := make([]*any.Any, 0, 19) + a, err := ptypes.MarshalAny(&TwoOctetAsSpecificExtended{ + IsTransitive: true, + SubType: 0x02, // ROUTE_TARGET + As: 65001, + LocalAdmin: 100, + }) + assert.Nil(err) + communities = append(communities, a) + a, err = ptypes.MarshalAny(&IPv4AddressSpecificExtended{ + IsTransitive: true, + SubType: 0x02, // ROUTE_TARGET + Address: "2.2.2.2", + LocalAdmin: 200, + }) + assert.Nil(err) + communities = append(communities, a) + a, err = ptypes.MarshalAny(&FourOctetAsSpecificExtended{ + IsTransitive: true, + SubType: 0x02, // ROUTE_TARGET + As: 65003, + LocalAdmin: 300, + }) + assert.Nil(err) + communities = append(communities, a) + a, err = ptypes.MarshalAny(&ValidationExtended{ + State: 0, // VALID + }) + assert.Nil(err) + communities = append(communities, a) + a, err = ptypes.MarshalAny(&ColorExtended{ + Color: 400, + }) + assert.Nil(err) + communities = append(communities, a) + a, err = ptypes.MarshalAny(&EncapExtended{ + TunnelType: 8, // VXLAN + }) + assert.Nil(err) + communities = append(communities, a) + a, err = ptypes.MarshalAny(&DefaultGatewayExtended{ + // No value + }) + assert.Nil(err) + communities = append(communities, a) + a, err = ptypes.MarshalAny(&OpaqueExtended{ + IsTransitive: true, + Value: []byte{0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77}, + }) + assert.Nil(err) + communities = append(communities, a) + a, err = ptypes.MarshalAny(&ESILabelExtended{ + IsSingleActive: true, + Label: 500, + }) + assert.Nil(err) + communities = append(communities, a) + a, err = ptypes.MarshalAny(&ESImportRouteTarget{ + EsImport: "aa:bb:cc:dd:ee:ff", + }) + assert.Nil(err) + communities = append(communities, a) + a, err = ptypes.MarshalAny(&MacMobilityExtended{ + IsSticky: true, + SequenceNum: 1, + }) + assert.Nil(err) + communities = append(communities, a) + a, err = ptypes.MarshalAny(&RouterMacExtended{ + Mac: "ff:ee:dd:cc:bb:aa", + }) + assert.Nil(err) + communities = append(communities, a) + a, err = ptypes.MarshalAny(&TrafficRateExtended{ + As: 65004, + Rate: 100.0, + }) + assert.Nil(err) + communities = append(communities, a) + a, err = ptypes.MarshalAny(&TrafficActionExtended{ + Terminal: true, + Sample: false, + }) + assert.Nil(err) + communities = append(communities, a) + a, err = ptypes.MarshalAny(&RedirectTwoOctetAsSpecificExtended{ + As: 65005, + LocalAdmin: 500, + }) + assert.Nil(err) + communities = append(communities, a) + a, err = ptypes.MarshalAny(&RedirectIPv4AddressSpecificExtended{ + Address: "6.6.6.6", + LocalAdmin: 600, + }) + assert.Nil(err) + communities = append(communities, a) + a, err = ptypes.MarshalAny(&RedirectFourOctetAsSpecificExtended{ + As: 65007, + LocalAdmin: 700, + }) + assert.Nil(err) + communities = append(communities, a) + a, err = ptypes.MarshalAny(&TrafficRemarkExtended{ + Dscp: 0x0a, // AF11 + }) + assert.Nil(err) + communities = append(communities, a) + a, err = ptypes.MarshalAny(&UnknownExtended{ + Type: 0xff, // Max of uint8 + Value: []byte{1, 2, 3, 4, 5, 6, 7}, + }) + assert.Nil(err) + communities = append(communities, a) + + input := &ExtendedCommunitiesAttribute{ + Communities: communities, + } + + n, err := input.ToNative() + assert.Nil(err) + + output := NewExtendedCommunitiesAttributeFromNative(n) + assert.Equal(19, len(output.Communities)) + for idx, inputCommunity := range input.Communities { + outputCommunity := output.Communities[idx] + assert.Equal(inputCommunity.TypeUrl, outputCommunity.TypeUrl) + assert.Equal(inputCommunity.Value, outputCommunity.Value) + } +} + +func Test_As4PathAttribute(t *testing.T) { + assert := assert.New(t) + + input := &As4PathAttribute{ + Segments: []*AsSegment{ + { + Type: 1, // SET + Numbers: []uint32{100, 200}, + }, + { + Type: 2, // SEQ + Numbers: []uint32{300, 400}, + }, + }, + } + + n, err := input.ToNative() + assert.Nil(err) + + output := NewAs4PathAttributeFromNative(n) + assert.Equal(2, len(output.Segments)) + assert.Equal(input.Segments, output.Segments) +} + +func Test_As4AggregatorAttribute(t *testing.T) { + assert := assert.New(t) + + input := &As4AggregatorAttribute{ + As: 65000, + Address: "1.1.1.1", + } + + n, err := input.ToNative() + assert.Nil(err) + + output := NewAs4AggregatorAttributeFromNative(n) + assert.Equal(input.As, output.As) + assert.Equal(input.Address, output.Address) +} + +func Test_PmsiTunnelAttribute(t *testing.T) { + assert := assert.New(t) + + input := &PmsiTunnelAttribute{ + Flags: 0x01, // IsLeafInfoRequired = true + Type: 6, // INGRESS_REPL + Label: 100, + Id: net.ParseIP("1.1.1.1").To4(), // IngressReplTunnelID with IPv4 + } + + n, err := input.ToNative() + assert.Nil(err) + + output := NewPmsiTunnelAttributeFromNative(n) + assert.Equal(input.Flags, output.Flags) + assert.Equal(input.Type, output.Type) + assert.Equal(input.Label, output.Label) + assert.Equal(input.Id, output.Id) +} + +func Test_TunnelEncapAttribute(t *testing.T) { + assert := assert.New(t) + + subTlvs := make([]*any.Any, 0, 4) + a, err := ptypes.MarshalAny(&TunnelEncapSubTLVEncapsulation{ + Key: 100, + Cookie: []byte{0x11, 0x22, 0x33, 0x44}, + }) + assert.Nil(err) + subTlvs = append(subTlvs, a) + a, err = ptypes.MarshalAny(&TunnelEncapSubTLVProtocol{ + Protocol: 200, + }) + assert.Nil(err) + subTlvs = append(subTlvs, a) + a, err = ptypes.MarshalAny(&TunnelEncapSubTLVColor{ + Color: 300, + }) + assert.Nil(err) + subTlvs = append(subTlvs, a) + a, err = ptypes.MarshalAny(&TunnelEncapSubTLVUnknown{ + Type: 0xff, // Max of uint8 + Value: []byte{0x55, 0x66, 0x77, 0x88}, + }) + assert.Nil(err) + subTlvs = append(subTlvs, a) + + input := &TunnelEncapAttribute{ + Tlvs: []*TunnelEncapTLV{ + { + Type: 8, // VXLAN + Tlvs: subTlvs, + }, + }, + } + + n, err := input.ToNative() + assert.Nil(err) + + output := NewTunnelEncapAttributeFromNative(n) + assert.Equal(1, len(output.Tlvs)) + assert.Equal(input.Tlvs[0].Type, output.Tlvs[0].Type) + assert.Equal(len(output.Tlvs[0].Tlvs), len(output.Tlvs[0].Tlvs)) + for idx, inputSubTlv := range input.Tlvs[0].Tlvs { + outputSubTlv := output.Tlvs[0].Tlvs[idx] + assert.Equal(inputSubTlv.TypeUrl, outputSubTlv.TypeUrl) + assert.Equal(inputSubTlv.Value, outputSubTlv.Value) + } +} + +func Test_IP6ExtendedCommunitiesAttribute(t *testing.T) { + assert := assert.New(t) + + communities := make([]*any.Any, 0, 2) + a, err := ptypes.MarshalAny(&IPv6AddressSpecificExtended{ + IsTransitive: true, + SubType: 0xff, // Max of uint8 + Address: "2001:db8:1::1", + LocalAdmin: 100, + }) + assert.Nil(err) + communities = append(communities, a) + a, err = ptypes.MarshalAny(&RedirectIPv6AddressSpecificExtended{ + Address: "2001:db8:2::1", + LocalAdmin: 200, + }) + assert.Nil(err) + communities = append(communities, a) + + input := &IP6ExtendedCommunitiesAttribute{ + Communities: communities, + } + + n, err := input.ToNative() + assert.Nil(err) + + output := NewIP6ExtendedCommunitiesAttributeFromNative(n) + assert.Equal(2, len(output.Communities)) + for idx, inputCommunity := range input.Communities { + outputCommunity := output.Communities[idx] + assert.Equal(inputCommunity.TypeUrl, outputCommunity.TypeUrl) + assert.Equal(inputCommunity.Value, outputCommunity.Value) + } +} + +func Test_AigpAttribute(t *testing.T) { + assert := assert.New(t) + + tlvs := make([]*any.Any, 0, 2) + a, err := ptypes.MarshalAny(&AigpTLVIGPMetric{ + Metric: 50, + }) + assert.Nil(err) + tlvs = append(tlvs, a) + a, err = ptypes.MarshalAny(&AigpTLVUnknown{ + Type: 0xff, // Max of uint8 + Value: []byte{0x11, 0x22, 0x33, 0x44}, + }) + assert.Nil(err) + tlvs = append(tlvs, a) + + input := &AigpAttribute{ + Tlvs: tlvs, + } + + n, err := input.ToNative() + assert.Nil(err) + + output := NewAigpAttributeFromNative(n) + assert.Equal(2, len(output.Tlvs)) + for idx, inputTlv := range input.Tlvs { + outputTlv := output.Tlvs[idx] + assert.Equal(inputTlv.TypeUrl, outputTlv.TypeUrl) + assert.Equal(inputTlv.Value, outputTlv.Value) + } +} + +func Test_LargeCommunitiesAttribute(t *testing.T) { + assert := assert.New(t) + + input := &LargeCommunitiesAttribute{ + Communities: []*LargeCommunity{ + { + GlobalAdmin: 65001, + LocalData1: 100, + LocalData2: 200, + }, + { + GlobalAdmin: 65002, + LocalData1: 300, + LocalData2: 400, + }, + }, + } + + n, err := input.ToNative() + assert.Nil(err) + + output := NewLargeCommunitiesAttributeFromNative(n) + assert.Equal(2, len(output.Communities)) + assert.Equal(input.Communities, output.Communities) +} + +func Test_UnknownAttribute(t *testing.T) { + assert := assert.New(t) + + input := &UnknownAttribute{ + Flags: (1 << 6) | (1 << 7), // OPTIONAL and TRANSITIVE + Type: 0xff, + Value: []byte{0x11, 0x22, 0x33, 0x44}, + } + + n, err := input.ToNative() + assert.Nil(err) + + output := NewUnknownAttributeFromNative(n) + assert.Equal(input.Flags, output.Flags) + assert.Equal(input.Type, output.Type) + assert.Equal(input.Value, output.Value) +} diff -Nru gobgp-1.32/api/capability.go gobgp-1.33/api/capability.go --- gobgp-1.32/api/capability.go 1970-01-01 00:00:00.000000000 +0000 +++ gobgp-1.33/api/capability.go 2018-07-01 12:06:57.000000000 +0000 @@ -0,0 +1,288 @@ +// Copyright (C) 2018 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 gobgpapi + +import ( + "fmt" + + proto "github.com/golang/protobuf/proto" + "github.com/golang/protobuf/ptypes" + "github.com/golang/protobuf/ptypes/any" + + "github.com/osrg/gobgp/packet/bgp" +) + +func NewMultiProtocolCapability(a *bgp.CapMultiProtocol) *MultiProtocolCapability { + return &MultiProtocolCapability{ + Family: Family(a.CapValue), + } +} + +func (a *MultiProtocolCapability) ToNative() (*bgp.CapMultiProtocol, error) { + return bgp.NewCapMultiProtocol(bgp.RouteFamily(a.Family)), nil +} + +func NewRouteRefreshCapability(a *bgp.CapRouteRefresh) *RouteRefreshCapability { + return &RouteRefreshCapability{} +} + +func (a *RouteRefreshCapability) ToNative() (*bgp.CapRouteRefresh, error) { + return bgp.NewCapRouteRefresh(), nil +} + +func NewCarryingLabelInfoCapability(a *bgp.CapCarryingLabelInfo) *CarryingLabelInfoCapability { + return &CarryingLabelInfoCapability{} +} + +func (a *CarryingLabelInfoCapability) ToNative() (*bgp.CapCarryingLabelInfo, error) { + return bgp.NewCapCarryingLabelInfo(), nil +} + +func NewExtendedNexthopCapability(a *bgp.CapExtendedNexthop) *ExtendedNexthopCapability { + tuples := make([]*ExtendedNexthopCapabilityTuple, 0, len(a.Tuples)) + for _, t := range a.Tuples { + tuples = append(tuples, &ExtendedNexthopCapabilityTuple{ + NlriFamily: Family(bgp.AfiSafiToRouteFamily(t.NLRIAFI, uint8(t.NLRISAFI))), + NexthopFamily: Family(bgp.AfiSafiToRouteFamily(t.NexthopAFI, bgp.SAFI_UNICAST)), + }) + } + return &ExtendedNexthopCapability{ + Tuples: tuples, + } +} + +func (a *ExtendedNexthopCapability) ToNative() (*bgp.CapExtendedNexthop, error) { + tuples := make([]*bgp.CapExtendedNexthopTuple, 0, len(a.Tuples)) + for _, t := range a.Tuples { + var nhAfi uint16 + switch t.NexthopFamily { + case Family_IPv4: + nhAfi = bgp.AFI_IP + case Family_IPv6: + nhAfi = bgp.AFI_IP6 + default: + return nil, fmt.Errorf("invalid address family for nexthop afi in extended nexthop capability: %s", t.NexthopFamily) + } + tuples = append(tuples, bgp.NewCapExtendedNexthopTuple(bgp.RouteFamily(t.NlriFamily), nhAfi)) + } + return bgp.NewCapExtendedNexthop(tuples), nil +} + +func NewGracefulRestartCapability(a *bgp.CapGracefulRestart) *GracefulRestartCapability { + tuples := make([]*GracefulRestartCapabilityTuple, 0, len(a.Tuples)) + for _, t := range a.Tuples { + tuples = append(tuples, &GracefulRestartCapabilityTuple{ + Family: Family(bgp.AfiSafiToRouteFamily(t.AFI, uint8(t.SAFI))), + Flags: uint32(t.Flags), + }) + } + return &GracefulRestartCapability{ + Flags: uint32(a.Flags), + Time: uint32(a.Time), + Tuples: tuples, + } +} + +func (a *GracefulRestartCapability) ToNative() (*bgp.CapGracefulRestart, error) { + tuples := make([]*bgp.CapGracefulRestartTuple, 0, len(a.Tuples)) + for _, t := range a.Tuples { + var forward bool + if t.Flags&0x80 > 0 { + forward = true + } + tuples = append(tuples, bgp.NewCapGracefulRestartTuple(bgp.RouteFamily(t.Family), forward)) + } + var restarting bool + if a.Flags&0x08 > 0 { + restarting = true + } + var notification bool + if a.Flags&0x04 > 0 { + notification = true + } + return bgp.NewCapGracefulRestart(restarting, notification, uint16(a.Time), tuples), nil +} + +func NewFourOctetASNumberCapability(a *bgp.CapFourOctetASNumber) *FourOctetASNumberCapability { + return &FourOctetASNumberCapability{ + As: a.CapValue, + } +} + +func (a *FourOctetASNumberCapability) ToNative() (*bgp.CapFourOctetASNumber, error) { + return bgp.NewCapFourOctetASNumber(a.As), nil +} + +func NewAddPathCapability(a *bgp.CapAddPath) *AddPathCapability { + tuples := make([]*AddPathCapabilityTuple, 0, len(a.Tuples)) + for _, t := range a.Tuples { + tuples = append(tuples, &AddPathCapabilityTuple{ + Family: Family(t.RouteFamily), + Mode: AddPathMode(t.Mode), + }) + } + return &AddPathCapability{ + Tuples: tuples, + } +} + +func (a *AddPathCapability) ToNative() (*bgp.CapAddPath, error) { + tuples := make([]*bgp.CapAddPathTuple, 0, len(a.Tuples)) + for _, t := range a.Tuples { + tuples = append(tuples, bgp.NewCapAddPathTuple(bgp.RouteFamily(t.Family), bgp.BGPAddPathMode(t.Mode))) + } + return bgp.NewCapAddPath(tuples), nil +} + +func NewEnhancedRouteRefreshCapability(a *bgp.CapEnhancedRouteRefresh) *EnhancedRouteRefreshCapability { + return &EnhancedRouteRefreshCapability{} +} + +func (a *EnhancedRouteRefreshCapability) ToNative() (*bgp.CapEnhancedRouteRefresh, error) { + return bgp.NewCapEnhancedRouteRefresh(), nil +} + +func NewLongLivedGracefulRestartCapability(a *bgp.CapLongLivedGracefulRestart) *LongLivedGracefulRestartCapability { + tuples := make([]*LongLivedGracefulRestartCapabilityTuple, 0, len(a.Tuples)) + for _, t := range a.Tuples { + tuples = append(tuples, &LongLivedGracefulRestartCapabilityTuple{ + Family: Family(bgp.AfiSafiToRouteFamily(t.AFI, uint8(t.SAFI))), + Flags: uint32(t.Flags), + Time: t.RestartTime, + }) + } + return &LongLivedGracefulRestartCapability{ + Tuples: tuples, + } +} + +func (a *LongLivedGracefulRestartCapability) ToNative() (*bgp.CapLongLivedGracefulRestart, error) { + tuples := make([]*bgp.CapLongLivedGracefulRestartTuple, 0, len(a.Tuples)) + for _, t := range a.Tuples { + var forward bool + if t.Flags&0x80 > 0 { + forward = true + } + tuples = append(tuples, bgp.NewCapLongLivedGracefulRestartTuple(bgp.RouteFamily(t.Family), forward, t.Time)) + } + return bgp.NewCapLongLivedGracefulRestart(tuples), nil +} + +func NewRouteRefreshCiscoCapability(a *bgp.CapRouteRefreshCisco) *RouteRefreshCiscoCapability { + return &RouteRefreshCiscoCapability{} +} + +func (a *RouteRefreshCiscoCapability) ToNative() (*bgp.CapRouteRefreshCisco, error) { + return bgp.NewCapRouteRefreshCisco(), nil +} + +func NewUnknownCapability(a *bgp.CapUnknown) *UnknownCapability { + return &UnknownCapability{ + Code: uint32(a.CapCode), + Value: a.CapValue, + } +} + +func (a *UnknownCapability) ToNative() (*bgp.CapUnknown, error) { + return bgp.NewCapUnknown(bgp.BGPCapabilityCode(a.Code), a.Value), nil +} + +func MarshalCapability(value bgp.ParameterCapabilityInterface) (*any.Any, error) { + var m proto.Message + switch n := value.(type) { + case *bgp.CapMultiProtocol: + m = NewMultiProtocolCapability(n) + case *bgp.CapRouteRefresh: + m = NewRouteRefreshCapability(n) + case *bgp.CapCarryingLabelInfo: + m = NewCarryingLabelInfoCapability(n) + case *bgp.CapExtendedNexthop: + m = NewExtendedNexthopCapability(n) + case *bgp.CapGracefulRestart: + m = NewGracefulRestartCapability(n) + case *bgp.CapFourOctetASNumber: + m = NewFourOctetASNumberCapability(n) + case *bgp.CapAddPath: + m = NewAddPathCapability(n) + case *bgp.CapEnhancedRouteRefresh: + m = NewEnhancedRouteRefreshCapability(n) + case *bgp.CapLongLivedGracefulRestart: + m = NewLongLivedGracefulRestartCapability(n) + case *bgp.CapRouteRefreshCisco: + m = NewRouteRefreshCiscoCapability(n) + case *bgp.CapUnknown: + m = NewUnknownCapability(n) + default: + return nil, fmt.Errorf("invalid capability type to marshal: %+v", value) + } + return ptypes.MarshalAny(m) +} + +func MarshalCapabilities(values []bgp.ParameterCapabilityInterface) ([]*any.Any, error) { + caps := make([]*any.Any, 0, len(values)) + for _, value := range values { + a, err := MarshalCapability(value) + if err != nil { + return nil, err + } + caps = append(caps, a) + } + return caps, nil +} + +func UnmarshalCapability(a *any.Any) (bgp.ParameterCapabilityInterface, error) { + var value ptypes.DynamicAny + if err := ptypes.UnmarshalAny(a, &value); err != nil { + return nil, fmt.Errorf("failed to unmarshal capability: %s", err) + } + switch v := value.Message.(type) { + case *MultiProtocolCapability: + return v.ToNative() + case *RouteRefreshCapability: + return v.ToNative() + case *CarryingLabelInfoCapability: + return v.ToNative() + case *ExtendedNexthopCapability: + return v.ToNative() + case *GracefulRestartCapability: + return v.ToNative() + case *FourOctetASNumberCapability: + return v.ToNative() + case *AddPathCapability: + return v.ToNative() + case *EnhancedRouteRefreshCapability: + return v.ToNative() + case *LongLivedGracefulRestartCapability: + return v.ToNative() + case *RouteRefreshCiscoCapability: + return v.ToNative() + case *UnknownCapability: + return v.ToNative() + } + return nil, fmt.Errorf("invalid capability type to unmarshal: %s", a.TypeUrl) +} + +func UnmarshalCapabilities(values []*any.Any) ([]bgp.ParameterCapabilityInterface, error) { + caps := make([]bgp.ParameterCapabilityInterface, 0, len(values)) + for _, value := range values { + c, err := UnmarshalCapability(value) + if err != nil { + return nil, err + } + caps = append(caps, c) + } + return caps, nil +} diff -Nru gobgp-1.32/api/capability.pb.go gobgp-1.33/api/capability.pb.go --- gobgp-1.32/api/capability.pb.go 1970-01-01 00:00:00.000000000 +0000 +++ gobgp-1.33/api/capability.pb.go 2018-07-01 12:06:57.000000000 +0000 @@ -0,0 +1,379 @@ +// Code generated by protoc-gen-go. DO NOT EDIT. +// source: capability.proto + +package gobgpapi + +import proto "github.com/golang/protobuf/proto" +import fmt "fmt" +import math "math" + +// Reference imports to suppress errors if they are not otherwise used. +var _ = proto.Marshal +var _ = fmt.Errorf +var _ = math.Inf + +type AddPathMode int32 + +const ( + AddPathMode_MODE_NONE AddPathMode = 0 + AddPathMode_MODE_RECEIVE AddPathMode = 1 + AddPathMode_MODE_SEND AddPathMode = 2 + AddPathMode_MODE_BOTH AddPathMode = 3 +) + +var AddPathMode_name = map[int32]string{ + 0: "MODE_NONE", + 1: "MODE_RECEIVE", + 2: "MODE_SEND", + 3: "MODE_BOTH", +} +var AddPathMode_value = map[string]int32{ + "MODE_NONE": 0, + "MODE_RECEIVE": 1, + "MODE_SEND": 2, + "MODE_BOTH": 3, +} + +func (x AddPathMode) String() string { + return proto.EnumName(AddPathMode_name, int32(x)) +} +func (AddPathMode) EnumDescriptor() ([]byte, []int) { return fileDescriptor2, []int{0} } + +type MultiProtocolCapability struct { + Family Family `protobuf:"varint,1,opt,name=family,enum=gobgpapi.Family" json:"family,omitempty"` +} + +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 (m *MultiProtocolCapability) GetFamily() Family { + if m != nil { + return m.Family + } + return Family_RESERVED +} + +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} } + +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} } + +type ExtendedNexthopCapabilityTuple struct { + NlriFamily Family `protobuf:"varint,1,opt,name=nlri_family,json=nlriFamily,enum=gobgpapi.Family" json:"nlri_family,omitempty"` + // Nexthop AFI must be either + // gobgp.IPv4 or + // gobgp.IPv6. + NexthopFamily Family `protobuf:"varint,2,opt,name=nexthop_family,json=nexthopFamily,enum=gobgpapi.Family" json:"nexthop_family,omitempty"` +} + +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 (m *ExtendedNexthopCapabilityTuple) GetNlriFamily() Family { + if m != nil { + return m.NlriFamily + } + return Family_RESERVED +} + +func (m *ExtendedNexthopCapabilityTuple) GetNexthopFamily() Family { + if m != nil { + return m.NexthopFamily + } + return Family_RESERVED +} + +type ExtendedNexthopCapability struct { + Tuples []*ExtendedNexthopCapabilityTuple `protobuf:"bytes,1,rep,name=tuples" json:"tuples,omitempty"` +} + +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 (m *ExtendedNexthopCapability) GetTuples() []*ExtendedNexthopCapabilityTuple { + if m != nil { + return m.Tuples + } + return nil +} + +type GracefulRestartCapabilityTuple struct { + Family Family `protobuf:"varint,1,opt,name=family,enum=gobgpapi.Family" json:"family,omitempty"` + Flags uint32 `protobuf:"varint,2,opt,name=flags" json:"flags,omitempty"` +} + +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 (m *GracefulRestartCapabilityTuple) GetFamily() Family { + if m != nil { + return m.Family + } + return Family_RESERVED +} + +func (m *GracefulRestartCapabilityTuple) GetFlags() uint32 { + if m != nil { + return m.Flags + } + return 0 +} + +type GracefulRestartCapability struct { + Flags uint32 `protobuf:"varint,1,opt,name=flags" json:"flags,omitempty"` + Time uint32 `protobuf:"varint,2,opt,name=time" json:"time,omitempty"` + Tuples []*GracefulRestartCapabilityTuple `protobuf:"bytes,3,rep,name=tuples" json:"tuples,omitempty"` +} + +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 (m *GracefulRestartCapability) GetFlags() uint32 { + if m != nil { + return m.Flags + } + return 0 +} + +func (m *GracefulRestartCapability) GetTime() uint32 { + if m != nil { + return m.Time + } + return 0 +} + +func (m *GracefulRestartCapability) GetTuples() []*GracefulRestartCapabilityTuple { + if m != nil { + return m.Tuples + } + return nil +} + +type FourOctetASNumberCapability struct { + As uint32 `protobuf:"varint,1,opt,name=as" json:"as,omitempty"` +} + +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 (m *FourOctetASNumberCapability) GetAs() uint32 { + if m != nil { + return m.As + } + return 0 +} + +type AddPathCapabilityTuple struct { + Family Family `protobuf:"varint,1,opt,name=family,enum=gobgpapi.Family" json:"family,omitempty"` + Mode AddPathMode `protobuf:"varint,2,opt,name=mode,enum=gobgpapi.AddPathMode" json:"mode,omitempty"` +} + +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 (m *AddPathCapabilityTuple) GetFamily() Family { + if m != nil { + return m.Family + } + return Family_RESERVED +} + +func (m *AddPathCapabilityTuple) GetMode() AddPathMode { + if m != nil { + return m.Mode + } + return AddPathMode_MODE_NONE +} + +type AddPathCapability struct { + Tuples []*AddPathCapabilityTuple `protobuf:"bytes,1,rep,name=tuples" json:"tuples,omitempty"` +} + +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 (m *AddPathCapability) GetTuples() []*AddPathCapabilityTuple { + if m != nil { + return m.Tuples + } + return nil +} + +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} } + +type LongLivedGracefulRestartCapabilityTuple struct { + Family Family `protobuf:"varint,1,opt,name=family,enum=gobgpapi.Family" json:"family,omitempty"` + Flags uint32 `protobuf:"varint,2,opt,name=flags" json:"flags,omitempty"` + Time uint32 `protobuf:"varint,3,opt,name=time" json:"time,omitempty"` +} + +func (m *LongLivedGracefulRestartCapabilityTuple) Reset() { + *m = LongLivedGracefulRestartCapabilityTuple{} +} +func (m *LongLivedGracefulRestartCapabilityTuple) String() string { return proto.CompactTextString(m) } +func (*LongLivedGracefulRestartCapabilityTuple) ProtoMessage() {} +func (*LongLivedGracefulRestartCapabilityTuple) Descriptor() ([]byte, []int) { + return fileDescriptor2, []int{11} +} + +func (m *LongLivedGracefulRestartCapabilityTuple) GetFamily() Family { + if m != nil { + return m.Family + } + return Family_RESERVED +} + +func (m *LongLivedGracefulRestartCapabilityTuple) GetFlags() uint32 { + if m != nil { + return m.Flags + } + return 0 +} + +func (m *LongLivedGracefulRestartCapabilityTuple) GetTime() uint32 { + if m != nil { + return m.Time + } + return 0 +} + +type LongLivedGracefulRestartCapability struct { + Tuples []*LongLivedGracefulRestartCapabilityTuple `protobuf:"bytes,1,rep,name=tuples" json:"tuples,omitempty"` +} + +func (m *LongLivedGracefulRestartCapability) Reset() { *m = LongLivedGracefulRestartCapability{} } +func (m *LongLivedGracefulRestartCapability) String() string { return proto.CompactTextString(m) } +func (*LongLivedGracefulRestartCapability) ProtoMessage() {} +func (*LongLivedGracefulRestartCapability) Descriptor() ([]byte, []int) { + return fileDescriptor2, []int{12} +} + +func (m *LongLivedGracefulRestartCapability) GetTuples() []*LongLivedGracefulRestartCapabilityTuple { + if m != nil { + return m.Tuples + } + return nil +} + +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} } + +type UnknownCapability struct { + Code uint32 `protobuf:"varint,1,opt,name=code" json:"code,omitempty"` + Value []byte `protobuf:"bytes,2,opt,name=value,proto3" json:"value,omitempty"` +} + +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 (m *UnknownCapability) GetCode() uint32 { + if m != nil { + return m.Code + } + return 0 +} + +func (m *UnknownCapability) GetValue() []byte { + if m != nil { + return m.Value + } + return nil +} + +func init() { + proto.RegisterType((*MultiProtocolCapability)(nil), "gobgpapi.MultiProtocolCapability") + proto.RegisterType((*RouteRefreshCapability)(nil), "gobgpapi.RouteRefreshCapability") + proto.RegisterType((*CarryingLabelInfoCapability)(nil), "gobgpapi.CarryingLabelInfoCapability") + proto.RegisterType((*ExtendedNexthopCapabilityTuple)(nil), "gobgpapi.ExtendedNexthopCapabilityTuple") + proto.RegisterType((*ExtendedNexthopCapability)(nil), "gobgpapi.ExtendedNexthopCapability") + proto.RegisterType((*GracefulRestartCapabilityTuple)(nil), "gobgpapi.GracefulRestartCapabilityTuple") + proto.RegisterType((*GracefulRestartCapability)(nil), "gobgpapi.GracefulRestartCapability") + proto.RegisterType((*FourOctetASNumberCapability)(nil), "gobgpapi.FourOctetASNumberCapability") + proto.RegisterType((*AddPathCapabilityTuple)(nil), "gobgpapi.AddPathCapabilityTuple") + proto.RegisterType((*AddPathCapability)(nil), "gobgpapi.AddPathCapability") + proto.RegisterType((*EnhancedRouteRefreshCapability)(nil), "gobgpapi.EnhancedRouteRefreshCapability") + proto.RegisterType((*LongLivedGracefulRestartCapabilityTuple)(nil), "gobgpapi.LongLivedGracefulRestartCapabilityTuple") + proto.RegisterType((*LongLivedGracefulRestartCapability)(nil), "gobgpapi.LongLivedGracefulRestartCapability") + proto.RegisterType((*RouteRefreshCiscoCapability)(nil), "gobgpapi.RouteRefreshCiscoCapability") + proto.RegisterType((*UnknownCapability)(nil), "gobgpapi.UnknownCapability") + proto.RegisterEnum("gobgpapi.AddPathMode", AddPathMode_name, AddPathMode_value) +} + +func init() { proto.RegisterFile("capability.proto", fileDescriptor2) } + +var fileDescriptor2 = []byte{ + // 520 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xb4, 0x54, 0xcd, 0x6f, 0xd3, 0x4e, + 0x10, 0xfd, 0x39, 0xc9, 0x2f, 0x82, 0x49, 0x13, 0xb9, 0x2b, 0x28, 0x29, 0x51, 0xa3, 0x68, 0x2f, + 0x04, 0x24, 0x22, 0xb5, 0x1c, 0xe0, 0x82, 0x44, 0x49, 0x5d, 0x88, 0x94, 0x8f, 0xca, 0x2d, 0xdc, + 0x50, 0xd9, 0xd8, 0x6b, 0x67, 0xc5, 0x7a, 0xd7, 0xb2, 0xd7, 0xa5, 0x39, 0x70, 0xe6, 0xc2, 0x1f, + 0x8d, 0xfc, 0x11, 0xdb, 0xa4, 0x72, 0x5b, 0x21, 0x71, 0x9b, 0xf1, 0xce, 0xbc, 0x79, 0x6f, 0xde, + 0xae, 0x41, 0xb7, 0x88, 0x4f, 0x96, 0x8c, 0x33, 0xb5, 0x1e, 0xf9, 0x81, 0x54, 0x12, 0x3d, 0x70, + 0xe5, 0xd2, 0xf5, 0x89, 0xcf, 0x9e, 0xb6, 0x92, 0x28, 0xfd, 0x8c, 0xc7, 0xf0, 0x64, 0x16, 0x71, + 0xc5, 0xce, 0xe2, 0xcc, 0x92, 0x7c, 0x9c, 0xf7, 0xa1, 0x21, 0x34, 0x1d, 0xe2, 0x31, 0xbe, 0xee, + 0x6a, 0x03, 0x6d, 0xd8, 0x39, 0xd2, 0x47, 0x1b, 0x88, 0xd1, 0x69, 0xf2, 0xdd, 0xcc, 0xce, 0x71, + 0x17, 0xf6, 0x4c, 0x19, 0x29, 0x6a, 0x52, 0x27, 0xa0, 0xe1, 0xaa, 0xc0, 0xc0, 0x07, 0xd0, 0x1b, + 0x93, 0x20, 0x58, 0x33, 0xe1, 0x4e, 0xc9, 0x92, 0xf2, 0x89, 0x70, 0x64, 0xe9, 0xf8, 0x97, 0x06, + 0x7d, 0xe3, 0x5a, 0x51, 0x61, 0x53, 0x7b, 0x4e, 0xaf, 0xd5, 0x4a, 0xfa, 0xc5, 0xe9, 0x45, 0xe4, + 0x73, 0x8a, 0x0e, 0xa1, 0x25, 0x78, 0xc0, 0x2e, 0xef, 0xa0, 0x02, 0x71, 0x51, 0x1a, 0xa3, 0xd7, + 0xd0, 0x11, 0x29, 0xd8, 0xa6, 0xab, 0x56, 0xd1, 0xd5, 0xce, 0xea, 0xd2, 0x14, 0x7f, 0x81, 0xfd, + 0x4a, 0x36, 0xe8, 0x1d, 0x34, 0x55, 0xcc, 0x28, 0xec, 0x6a, 0x83, 0xfa, 0xb0, 0x75, 0x34, 0x2c, + 0xd0, 0x6e, 0x97, 0x60, 0x66, 0x7d, 0xf8, 0x2b, 0xf4, 0x3f, 0x04, 0xc4, 0xa2, 0x4e, 0xc4, 0x4d, + 0x1a, 0x2a, 0x12, 0xa8, 0x6d, 0xb1, 0xf7, 0x5e, 0x39, 0x7a, 0x04, 0xff, 0x3b, 0x9c, 0xb8, 0x61, + 0x22, 0xad, 0x6d, 0xa6, 0x09, 0xfe, 0xa9, 0xc1, 0x7e, 0xe5, 0x88, 0xa2, 0x47, 0x2b, 0xf5, 0x20, + 0x04, 0x0d, 0xc5, 0x3c, 0x9a, 0x01, 0x25, 0x71, 0x49, 0x6b, 0x7d, 0x5b, 0xeb, 0xed, 0x0a, 0x72, + 0xad, 0x2f, 0xa1, 0x77, 0x2a, 0xa3, 0x60, 0x61, 0x29, 0xaa, 0x8e, 0xcf, 0xe7, 0x91, 0xb7, 0xa4, + 0x41, 0x89, 0x4a, 0x07, 0x6a, 0x64, 0xc3, 0xa3, 0x46, 0x42, 0xec, 0xc1, 0xde, 0xb1, 0x6d, 0x9f, + 0x11, 0xb5, 0xfa, 0xfb, 0x95, 0x3c, 0x87, 0x86, 0x27, 0x6d, 0x9a, 0x99, 0xfd, 0xb8, 0xa8, 0xcb, + 0x90, 0x67, 0xd2, 0xa6, 0x66, 0x52, 0x82, 0x67, 0xb0, 0x7b, 0x63, 0x1c, 0x7a, 0xb3, 0x65, 0xf0, + 0xe0, 0x06, 0x42, 0x95, 0xd8, 0x01, 0xf4, 0x0d, 0xb1, 0x22, 0xc2, 0xa2, 0x76, 0xc5, 0x3b, 0xf8, + 0x01, 0xcf, 0xa6, 0x52, 0xb8, 0x53, 0x76, 0x45, 0xed, 0x7f, 0x7b, 0x07, 0x72, 0x3f, 0xeb, 0x85, + 0x9f, 0x58, 0x02, 0xbe, 0x7b, 0x3c, 0x9a, 0x6c, 0x2d, 0xe0, 0xb0, 0x98, 0x7c, 0x4f, 0xf2, 0xf9, + 0x46, 0x0e, 0xa0, 0xf7, 0xc7, 0x26, 0x58, 0x68, 0x95, 0xdf, 0xfd, 0x5b, 0xd8, 0xfd, 0x24, 0xbe, + 0x09, 0xf9, 0x5d, 0x94, 0xc6, 0x23, 0x68, 0x58, 0xb1, 0x7f, 0xe9, 0xad, 0x48, 0xe2, 0x58, 0xe2, + 0x15, 0xe1, 0x51, 0x6a, 0xea, 0x8e, 0x99, 0x26, 0x2f, 0xa6, 0xd0, 0x2a, 0x79, 0x8a, 0xda, 0xf0, + 0x70, 0xb6, 0x38, 0x31, 0x2e, 0xe7, 0x8b, 0xb9, 0xa1, 0xff, 0x87, 0x74, 0xd8, 0x49, 0x52, 0xd3, + 0x18, 0x1b, 0x93, 0xcf, 0x86, 0xae, 0xe5, 0x05, 0xe7, 0xc6, 0xfc, 0x44, 0xaf, 0xe5, 0xe9, 0xfb, + 0xc5, 0xc5, 0x47, 0xbd, 0xbe, 0x6c, 0x26, 0x7f, 0xc2, 0x57, 0xbf, 0x03, 0x00, 0x00, 0xff, 0xff, + 0xd6, 0xbd, 0xd3, 0xc3, 0x34, 0x05, 0x00, 0x00, +} diff -Nru gobgp-1.32/api/capability.proto gobgp-1.33/api/capability.proto --- gobgp-1.32/api/capability.proto 1970-01-01 00:00:00.000000000 +0000 +++ gobgp-1.33/api/capability.proto 2018-07-01 12:06:57.000000000 +0000 @@ -0,0 +1,100 @@ +// Copyright (C) 2018 Nippon Telegraph and Telephone Corporation. +// +// Permission is hereby granted, free of charge, to any person +// obtaining a copy of this software and associated documentation files +// (the "Software"), to deal in the Software without restriction, +// including without limitation the rights to use, copy, modify, merge, +// publish, distribute, sublicense, and/or sell copies of the Software, +// and to permit persons to whom the Software is furnished to do so, +// subject to the following conditions: +// +// The above copyright notice and this permission notice shall be +// included in all copies or substantial portions of the Software. + +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +syntax = "proto3"; + +import "gobgp.proto"; + +package gobgpapi; + +enum AddPathMode { + MODE_NONE = 0; + MODE_RECEIVE = 1; + MODE_SEND = 2; + MODE_BOTH = 3; +} + +message MultiProtocolCapability { + gobgpapi.Family family = 1; +} + +message RouteRefreshCapability { +} + +message CarryingLabelInfoCapability { +} + +message ExtendedNexthopCapabilityTuple { + gobgpapi.Family nlri_family = 1; + // Nexthop AFI must be either + // gobgp.IPv4 or + // gobgp.IPv6. + gobgpapi.Family nexthop_family = 2; +} + +message ExtendedNexthopCapability { + repeated ExtendedNexthopCapabilityTuple tuples = 1; +} + +message GracefulRestartCapabilityTuple { + gobgpapi.Family family = 1; + uint32 flags = 2; +} + +message GracefulRestartCapability { + uint32 flags = 1; + uint32 time = 2; + repeated GracefulRestartCapabilityTuple tuples = 3; +} + +message FourOctetASNumberCapability { + uint32 as = 1; +} + +message AddPathCapabilityTuple { + gobgpapi.Family family = 1; + AddPathMode mode = 2; +} + +message AddPathCapability { + repeated AddPathCapabilityTuple tuples = 1; +} + +message EnhancedRouteRefreshCapability { +} + +message LongLivedGracefulRestartCapabilityTuple { + gobgpapi.Family family = 1; + uint32 flags = 2; + uint32 time = 3; +} + +message LongLivedGracefulRestartCapability { + repeated LongLivedGracefulRestartCapabilityTuple tuples = 1; +} + +message RouteRefreshCiscoCapability { +} + +message UnknownCapability { + uint32 code = 1; + bytes value = 2; +} \ No newline at end of file diff -Nru gobgp-1.32/api/capability_test.go gobgp-1.33/api/capability_test.go --- gobgp-1.32/api/capability_test.go 1970-01-01 00:00:00.000000000 +0000 +++ gobgp-1.33/api/capability_test.go 2018-07-01 12:06:57.000000000 +0000 @@ -0,0 +1,216 @@ +// Copyright (C) 2018 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 gobgpapi + +import ( + "testing" + + "github.com/stretchr/testify/assert" + + "github.com/osrg/gobgp/packet/bgp" +) + +func Test_MultiProtocolCapability(t *testing.T) { + assert := assert.New(t) + + input := &MultiProtocolCapability{ + Family: Family_IPv4, + } + + n, err := input.ToNative() + assert.Nil(err) + assert.Equal(bgp.RF_IPv4_UC, n.CapValue) + + output := NewMultiProtocolCapability(n) + assert.Equal(input, output) +} + +func Test_RouteRefreshCapability(t *testing.T) { + assert := assert.New(t) + + input := &RouteRefreshCapability{} + + n, err := input.ToNative() + assert.Nil(err) + + output := NewRouteRefreshCapability(n) + assert.Equal(input, output) +} + +func Test_CarryingLabelInfoCapability(t *testing.T) { + assert := assert.New(t) + + input := &CarryingLabelInfoCapability{} + + n, err := input.ToNative() + assert.Nil(err) + + output := NewCarryingLabelInfoCapability(n) + assert.Equal(input, output) +} + +func Test_ExtendedNexthopCapability(t *testing.T) { + assert := assert.New(t) + + input := &ExtendedNexthopCapability{ + Tuples: []*ExtendedNexthopCapabilityTuple{ + { + NlriFamily: Family_IPv4, + NexthopFamily: Family_IPv6, + }, + }, + } + + n, err := input.ToNative() + assert.Nil(err) + assert.Equal(1, len(n.Tuples)) + assert.Equal(uint16(bgp.AFI_IP), n.Tuples[0].NLRIAFI) + assert.Equal(uint16(bgp.SAFI_UNICAST), n.Tuples[0].NLRISAFI) + assert.Equal(uint16(bgp.AFI_IP6), n.Tuples[0].NexthopAFI) + + output := NewExtendedNexthopCapability(n) + assert.Equal(input, output) +} + +func Test_GracefulRestartCapability(t *testing.T) { + assert := assert.New(t) + + input := &GracefulRestartCapability{ + Flags: 0x08 | 0x04, // restarting|notification + Time: 90, + Tuples: []*GracefulRestartCapabilityTuple{ + { + Family: Family_IPv4, + Flags: 0x80, // forward + }, + }, + } + + n, err := input.ToNative() + assert.Nil(err) + assert.Equal(1, len(n.Tuples)) + assert.Equal(uint8(0x08|0x04), n.Flags) + assert.Equal(uint16(90), n.Time) + assert.Equal(uint16(bgp.AFI_IP), n.Tuples[0].AFI) + assert.Equal(uint8(bgp.SAFI_UNICAST), n.Tuples[0].SAFI) + assert.Equal(uint8(0x80), n.Tuples[0].Flags) + + output := NewGracefulRestartCapability(n) + assert.Equal(input, output) +} + +func Test_FourOctetASNumberCapability(t *testing.T) { + assert := assert.New(t) + + input := &FourOctetASNumberCapability{ + As: 100, + } + + n, err := input.ToNative() + assert.Nil(err) + assert.Equal(uint32(100), n.CapValue) + + output := NewFourOctetASNumberCapability(n) + assert.Equal(input, output) +} + +func Test_AddPathCapability(t *testing.T) { + assert := assert.New(t) + + input := &AddPathCapability{ + Tuples: []*AddPathCapabilityTuple{ + { + Family: Family_IPv4, + Mode: AddPathMode_MODE_BOTH, + }, + }, + } + + n, err := input.ToNative() + assert.Nil(err) + assert.Equal(1, len(n.Tuples)) + assert.Equal(bgp.RF_IPv4_UC, n.Tuples[0].RouteFamily) + assert.Equal(bgp.BGP_ADD_PATH_BOTH, n.Tuples[0].Mode) + + output := NewAddPathCapability(n) + assert.Equal(input, output) +} + +func Test_EnhancedRouteRefreshCapability(t *testing.T) { + assert := assert.New(t) + + input := &EnhancedRouteRefreshCapability{} + + n, err := input.ToNative() + assert.Nil(err) + + output := NewEnhancedRouteRefreshCapability(n) + assert.Equal(input, output) +} + +func Test_LongLivedGracefulRestartCapability(t *testing.T) { + assert := assert.New(t) + + input := &LongLivedGracefulRestartCapability{ + Tuples: []*LongLivedGracefulRestartCapabilityTuple{ + { + Family: Family_IPv4, + Flags: 0x80, // forward + Time: 90, + }, + }, + } + + n, err := input.ToNative() + assert.Nil(err) + assert.Equal(1, len(n.Tuples)) + assert.Equal(uint16(bgp.AFI_IP), n.Tuples[0].AFI) + assert.Equal(uint8(bgp.SAFI_UNICAST), n.Tuples[0].SAFI) + assert.Equal(uint8(0x80), n.Tuples[0].Flags) + assert.Equal(uint32(90), n.Tuples[0].RestartTime) + + output := NewLongLivedGracefulRestartCapability(n) + assert.Equal(input, output) +} + +func Test_RouteRefreshCiscoCapability(t *testing.T) { + assert := assert.New(t) + + input := &RouteRefreshCiscoCapability{} + + n, err := input.ToNative() + assert.Nil(err) + + output := NewRouteRefreshCiscoCapability(n) + assert.Equal(input, output) +} + +func Test_UnknownCapability(t *testing.T) { + assert := assert.New(t) + + input := &UnknownCapability{ + Code: 0xff, + Value: []byte{0x11, 0x22, 0x33, 0x44}, + } + + n, err := input.ToNative() + assert.Nil(err) + assert.Equal(bgp.BGPCapabilityCode(0xff), n.CapCode) + assert.Equal([]byte{0x11, 0x22, 0x33, 0x44}, n.CapValue) + + output := NewUnknownCapability(n) + assert.Equal(input, output) +} diff -Nru gobgp-1.32/api/gobgp.pb.go gobgp-1.33/api/gobgp.pb.go --- gobgp-1.32/api/gobgp.pb.go 2018-06-01 11:32:28.000000000 +0000 +++ gobgp-1.33/api/gobgp.pb.go 2018-07-01 12:06:57.000000000 +0000 @@ -6,6 +6,8 @@ It is generated from these files: gobgp.proto + attribute.proto + capability.proto It has these top-level messages: GetNeighborRequest @@ -21,6 +23,14 @@ DeleteNeighborResponse UpdateNeighborRequest UpdateNeighborResponse + AddPeerGroupRequest + AddPeerGroupResponse + DeletePeerGroupRequest + DeletePeerGroupResponse + UpdatePeerGroupRequest + UpdatePeerGroupResponse + AddDynamicNeighborRequest + AddDynamicNeighborResponse ResetNeighborRequest ResetNeighborResponse SoftResetNeighborRequest @@ -31,6 +41,8 @@ EnableNeighborResponse DisableNeighborRequest DisableNeighborResponse + UpdatePolicyRequest + UpdatePolicyResponse EnableMrtRequest EnableMrtResponse DisableMrtRequest @@ -116,9 +128,13 @@ ValidateRibRequest ValidateRibResponse Peer + PeerGroup + DynamicNeighbor ApplyPolicy PrefixLimit PeerConf + PeerGroupConf + PeerGroupState EbgpMultihop RouteReflector PeerState @@ -172,20 +188,115 @@ Statement Policy PolicyAssignment + RoutingPolicy Roa GetRoaRequest GetRoaResponse Vrf + DefaultRouteDistance Global + Confederation TableInfo GetRibInfoRequest GetRibInfoResponse + AddCollectorRequest + AddCollectorResponse + ShutdownRequest + ShutdownResponse + OriginAttribute + AsSegment + AsPathAttribute + NextHopAttribute + MultiExitDiscAttribute + LocalPrefAttribute + AtomicAggregateAttribute + AggregatorAttribute + CommunitiesAttribute + OriginatorIdAttribute + ClusterListAttribute + IPAddressPrefix + LabeledIPAddressPrefix + EncapsulationNLRI + RouteDistinguisherTwoOctetAS + RouteDistinguisherIPAddress + RouteDistinguisherFourOctetAS + EthernetSegmentIdentifier + EVPNEthernetAutoDiscoveryRoute + EVPNMACIPAdvertisementRoute + EVPNInclusiveMulticastEthernetTagRoute + EVPNEthernetSegmentRoute + EVPNIPPrefixRoute + LabeledVPNIPAddressPrefix + RouteTargetMembershipNLRI + FlowSpecIPPrefix + FlowSpecMAC + FlowSpecComponentItem + FlowSpecComponent + FlowSpecNLRI + VPNFlowSpecNLRI + OpaqueNLRI + MpReachNLRIAttribute + MpUnreachNLRIAttribute + TwoOctetAsSpecificExtended + IPv4AddressSpecificExtended + FourOctetAsSpecificExtended + ValidationExtended + ColorExtended + EncapExtended + DefaultGatewayExtended + OpaqueExtended + ESILabelExtended + ESImportRouteTarget + MacMobilityExtended + RouterMacExtended + TrafficRateExtended + TrafficActionExtended + RedirectTwoOctetAsSpecificExtended + RedirectIPv4AddressSpecificExtended + RedirectFourOctetAsSpecificExtended + TrafficRemarkExtended + UnknownExtended + ExtendedCommunitiesAttribute + As4PathAttribute + As4AggregatorAttribute + PmsiTunnelAttribute + TunnelEncapSubTLVEncapsulation + TunnelEncapSubTLVProtocol + TunnelEncapSubTLVColor + TunnelEncapSubTLVUnknown + TunnelEncapTLV + TunnelEncapAttribute + IPv6AddressSpecificExtended + RedirectIPv6AddressSpecificExtended + IP6ExtendedCommunitiesAttribute + AigpTLVIGPMetric + AigpTLVUnknown + AigpAttribute + LargeCommunity + LargeCommunitiesAttribute + UnknownAttribute + MultiProtocolCapability + RouteRefreshCapability + CarryingLabelInfoCapability + ExtendedNexthopCapabilityTuple + ExtendedNexthopCapability + GracefulRestartCapabilityTuple + GracefulRestartCapability + FourOctetASNumberCapability + AddPathCapabilityTuple + AddPathCapability + EnhancedRouteRefreshCapability + LongLivedGracefulRestartCapabilityTuple + LongLivedGracefulRestartCapability + RouteRefreshCiscoCapability + UnknownCapability */ package gobgpapi import proto "github.com/golang/protobuf/proto" import fmt "fmt" import math "math" +import google_protobuf "github.com/golang/protobuf/ptypes/any" import ( context "golang.org/x/net/context" @@ -207,7 +318,7 @@ type Family int32 const ( - Family__ Family = 0 + Family_RESERVED Family = 0 Family_IPv4 Family = 65537 Family_IPv6 Family = 131073 Family_IPv4_MC Family = 65538 @@ -232,7 +343,7 @@ ) var Family_name = map[int32]string{ - 0: "_", + 0: "RESERVED", 65537: "IPv4", 131073: "IPv6", 65538: "IPv4_MC", @@ -256,7 +367,7 @@ 1074594033: "OPAQUE", } var Family_value = map[string]int32{ - "_": 0, + "RESERVED": 0, "IPv4": 65537, "IPv6": 131073, "IPv4_MC": 65538, @@ -350,6 +461,7 @@ DefinedType_COMMUNITY DefinedType = 4 DefinedType_EXT_COMMUNITY DefinedType = 5 DefinedType_LARGE_COMMUNITY DefinedType = 6 + DefinedType_NEXT_HOP DefinedType = 7 ) var DefinedType_name = map[int32]string{ @@ -360,6 +472,7 @@ 4: "COMMUNITY", 5: "EXT_COMMUNITY", 6: "LARGE_COMMUNITY", + 7: "NEXT_HOP", } var DefinedType_value = map[string]int32{ "PREFIX": 0, @@ -369,6 +482,7 @@ "COMMUNITY": 4, "EXT_COMMUNITY": 5, "LARGE_COMMUNITY": 6, + "NEXT_HOP": 7, } func (x DefinedType) String() string { @@ -540,7 +654,7 @@ return proto.EnumName(SoftResetNeighborRequest_SoftResetDirection_name, int32(x)) } func (SoftResetNeighborRequest_SoftResetDirection) EnumDescriptor() ([]byte, []int) { - return fileDescriptor0, []int{15, 0} + return fileDescriptor0, []int{23, 0} } type AddBmpRequest_MonitoringPolicy int32 @@ -572,7 +686,7 @@ return proto.EnumName(AddBmpRequest_MonitoringPolicy_name, int32(x)) } func (AddBmpRequest_MonitoringPolicy) EnumDescriptor() ([]byte, []int) { - return fileDescriptor0, []int{29, 0} + return fileDescriptor0, []int{39, 0} } type RPKIValidation_State int32 @@ -600,7 +714,7 @@ func (x RPKIValidation_State) String() string { return proto.EnumName(RPKIValidation_State_name, int32(x)) } -func (RPKIValidation_State) EnumDescriptor() ([]byte, []int) { return fileDescriptor0, []int{97, 0} } +func (RPKIValidation_State) EnumDescriptor() ([]byte, []int) { return fileDescriptor0, []int{107, 0} } type RPKIValidation_Reason int32 @@ -624,7 +738,7 @@ func (x RPKIValidation_Reason) String() string { return proto.EnumName(RPKIValidation_Reason_name, int32(x)) } -func (RPKIValidation_Reason) EnumDescriptor() ([]byte, []int) { return fileDescriptor0, []int{97, 1} } +func (RPKIValidation_Reason) EnumDescriptor() ([]byte, []int) { return fileDescriptor0, []int{107, 1} } type PeerConf_RemovePrivateAs int32 @@ -649,7 +763,59 @@ return proto.EnumName(PeerConf_RemovePrivateAs_name, int32(x)) } func (PeerConf_RemovePrivateAs) EnumDescriptor() ([]byte, []int) { - return fileDescriptor0, []int{110, 0} + return fileDescriptor0, []int{122, 0} +} + +type PeerGroupConf_RemovePrivateAs int32 + +const ( + PeerGroupConf_NONE PeerGroupConf_RemovePrivateAs = 0 + PeerGroupConf_ALL PeerGroupConf_RemovePrivateAs = 1 + PeerGroupConf_REPLACE PeerGroupConf_RemovePrivateAs = 2 +) + +var PeerGroupConf_RemovePrivateAs_name = map[int32]string{ + 0: "NONE", + 1: "ALL", + 2: "REPLACE", +} +var PeerGroupConf_RemovePrivateAs_value = map[string]int32{ + "NONE": 0, + "ALL": 1, + "REPLACE": 2, +} + +func (x PeerGroupConf_RemovePrivateAs) String() string { + return proto.EnumName(PeerGroupConf_RemovePrivateAs_name, int32(x)) +} +func (PeerGroupConf_RemovePrivateAs) EnumDescriptor() ([]byte, []int) { + return fileDescriptor0, []int{123, 0} +} + +type PeerGroupState_RemovePrivateAs int32 + +const ( + PeerGroupState_NONE PeerGroupState_RemovePrivateAs = 0 + PeerGroupState_ALL PeerGroupState_RemovePrivateAs = 1 + PeerGroupState_REPLACE PeerGroupState_RemovePrivateAs = 2 +) + +var PeerGroupState_RemovePrivateAs_name = map[int32]string{ + 0: "NONE", + 1: "ALL", + 2: "REPLACE", +} +var PeerGroupState_RemovePrivateAs_value = map[string]int32{ + "NONE": 0, + "ALL": 1, + "REPLACE": 2, +} + +func (x PeerGroupState_RemovePrivateAs) String() string { + return proto.EnumName(PeerGroupState_RemovePrivateAs_name, int32(x)) +} +func (PeerGroupState_RemovePrivateAs) EnumDescriptor() ([]byte, []int) { + return fileDescriptor0, []int{124, 0} } type PeerState_AdminState int32 @@ -674,7 +840,7 @@ func (x PeerState_AdminState) String() string { return proto.EnumName(PeerState_AdminState_name, int32(x)) } -func (PeerState_AdminState) EnumDescriptor() ([]byte, []int) { return fileDescriptor0, []int{113, 0} } +func (PeerState_AdminState) EnumDescriptor() ([]byte, []int) { return fileDescriptor0, []int{127, 0} } type Conditions_RouteType int32 @@ -701,7 +867,7 @@ func (x Conditions_RouteType) String() string { return proto.EnumName(Conditions_RouteType_name, int32(x)) } -func (Conditions_RouteType) EnumDescriptor() ([]byte, []int) { return fileDescriptor0, []int{154, 0} } +func (Conditions_RouteType) EnumDescriptor() ([]byte, []int) { return fileDescriptor0, []int{168, 0} } type GetNeighborRequest struct { EnableAdvertised bool `protobuf:"varint,1,opt,name=enableAdvertised" json:"enableAdvertised,omitempty"` @@ -980,6 +1146,118 @@ return false } +type AddPeerGroupRequest struct { + PeerGroup *PeerGroup `protobuf:"bytes,1,opt,name=peer_group,json=peerGroup" json:"peer_group,omitempty"` +} + +func (m *AddPeerGroupRequest) Reset() { *m = AddPeerGroupRequest{} } +func (m *AddPeerGroupRequest) String() string { return proto.CompactTextString(m) } +func (*AddPeerGroupRequest) ProtoMessage() {} +func (*AddPeerGroupRequest) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{13} } + +func (m *AddPeerGroupRequest) GetPeerGroup() *PeerGroup { + if m != nil { + return m.PeerGroup + } + return nil +} + +type AddPeerGroupResponse struct { +} + +func (m *AddPeerGroupResponse) Reset() { *m = AddPeerGroupResponse{} } +func (m *AddPeerGroupResponse) String() string { return proto.CompactTextString(m) } +func (*AddPeerGroupResponse) ProtoMessage() {} +func (*AddPeerGroupResponse) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{14} } + +type DeletePeerGroupRequest struct { + PeerGroup *PeerGroup `protobuf:"bytes,1,opt,name=peer_group,json=peerGroup" json:"peer_group,omitempty"` +} + +func (m *DeletePeerGroupRequest) Reset() { *m = DeletePeerGroupRequest{} } +func (m *DeletePeerGroupRequest) String() string { return proto.CompactTextString(m) } +func (*DeletePeerGroupRequest) ProtoMessage() {} +func (*DeletePeerGroupRequest) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{15} } + +func (m *DeletePeerGroupRequest) GetPeerGroup() *PeerGroup { + if m != nil { + return m.PeerGroup + } + return nil +} + +type DeletePeerGroupResponse struct { +} + +func (m *DeletePeerGroupResponse) Reset() { *m = DeletePeerGroupResponse{} } +func (m *DeletePeerGroupResponse) String() string { return proto.CompactTextString(m) } +func (*DeletePeerGroupResponse) ProtoMessage() {} +func (*DeletePeerGroupResponse) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{16} } + +type UpdatePeerGroupRequest struct { + PeerGroup *PeerGroup `protobuf:"bytes,1,opt,name=peer_group,json=peerGroup" json:"peer_group,omitempty"` + DoSoftResetIn bool `protobuf:"varint,2,opt,name=do_soft_reset_in,json=doSoftResetIn" json:"do_soft_reset_in,omitempty"` +} + +func (m *UpdatePeerGroupRequest) Reset() { *m = UpdatePeerGroupRequest{} } +func (m *UpdatePeerGroupRequest) String() string { return proto.CompactTextString(m) } +func (*UpdatePeerGroupRequest) ProtoMessage() {} +func (*UpdatePeerGroupRequest) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{17} } + +func (m *UpdatePeerGroupRequest) GetPeerGroup() *PeerGroup { + if m != nil { + return m.PeerGroup + } + return nil +} + +func (m *UpdatePeerGroupRequest) GetDoSoftResetIn() bool { + if m != nil { + return m.DoSoftResetIn + } + return false +} + +type UpdatePeerGroupResponse struct { + NeedsSoftResetIn bool `protobuf:"varint,1,opt,name=needs_soft_reset_in,json=needsSoftResetIn" json:"needs_soft_reset_in,omitempty"` +} + +func (m *UpdatePeerGroupResponse) Reset() { *m = UpdatePeerGroupResponse{} } +func (m *UpdatePeerGroupResponse) String() string { return proto.CompactTextString(m) } +func (*UpdatePeerGroupResponse) ProtoMessage() {} +func (*UpdatePeerGroupResponse) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{18} } + +func (m *UpdatePeerGroupResponse) GetNeedsSoftResetIn() bool { + if m != nil { + return m.NeedsSoftResetIn + } + return false +} + +type AddDynamicNeighborRequest struct { + DynamicNeighbor *DynamicNeighbor `protobuf:"bytes,1,opt,name=dynamic_neighbor,json=dynamicNeighbor" json:"dynamic_neighbor,omitempty"` +} + +func (m *AddDynamicNeighborRequest) Reset() { *m = AddDynamicNeighborRequest{} } +func (m *AddDynamicNeighborRequest) String() string { return proto.CompactTextString(m) } +func (*AddDynamicNeighborRequest) ProtoMessage() {} +func (*AddDynamicNeighborRequest) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{19} } + +func (m *AddDynamicNeighborRequest) GetDynamicNeighbor() *DynamicNeighbor { + if m != nil { + return m.DynamicNeighbor + } + return nil +} + +type AddDynamicNeighborResponse struct { +} + +func (m *AddDynamicNeighborResponse) Reset() { *m = AddDynamicNeighborResponse{} } +func (m *AddDynamicNeighborResponse) String() string { return proto.CompactTextString(m) } +func (*AddDynamicNeighborResponse) ProtoMessage() {} +func (*AddDynamicNeighborResponse) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{20} } + type ResetNeighborRequest struct { Address string `protobuf:"bytes,1,opt,name=address" json:"address,omitempty"` Communication string `protobuf:"bytes,2,opt,name=communication" json:"communication,omitempty"` @@ -988,7 +1266,7 @@ func (m *ResetNeighborRequest) Reset() { *m = ResetNeighborRequest{} } func (m *ResetNeighborRequest) String() string { return proto.CompactTextString(m) } func (*ResetNeighborRequest) ProtoMessage() {} -func (*ResetNeighborRequest) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{13} } +func (*ResetNeighborRequest) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{21} } func (m *ResetNeighborRequest) GetAddress() string { if m != nil { @@ -1010,7 +1288,7 @@ func (m *ResetNeighborResponse) Reset() { *m = ResetNeighborResponse{} } func (m *ResetNeighborResponse) String() string { return proto.CompactTextString(m) } func (*ResetNeighborResponse) ProtoMessage() {} -func (*ResetNeighborResponse) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{14} } +func (*ResetNeighborResponse) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{22} } type SoftResetNeighborRequest struct { Address string `protobuf:"bytes,1,opt,name=address" json:"address,omitempty"` @@ -1020,7 +1298,7 @@ func (m *SoftResetNeighborRequest) Reset() { *m = SoftResetNeighborRequest{} } func (m *SoftResetNeighborRequest) String() string { return proto.CompactTextString(m) } func (*SoftResetNeighborRequest) ProtoMessage() {} -func (*SoftResetNeighborRequest) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{15} } +func (*SoftResetNeighborRequest) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{23} } func (m *SoftResetNeighborRequest) GetAddress() string { if m != nil { @@ -1042,7 +1320,7 @@ func (m *SoftResetNeighborResponse) Reset() { *m = SoftResetNeighborResponse{} } func (m *SoftResetNeighborResponse) String() string { return proto.CompactTextString(m) } func (*SoftResetNeighborResponse) ProtoMessage() {} -func (*SoftResetNeighborResponse) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{16} } +func (*SoftResetNeighborResponse) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{24} } type ShutdownNeighborRequest struct { Address string `protobuf:"bytes,1,opt,name=address" json:"address,omitempty"` @@ -1052,7 +1330,7 @@ func (m *ShutdownNeighborRequest) Reset() { *m = ShutdownNeighborRequest{} } func (m *ShutdownNeighborRequest) String() string { return proto.CompactTextString(m) } func (*ShutdownNeighborRequest) ProtoMessage() {} -func (*ShutdownNeighborRequest) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{17} } +func (*ShutdownNeighborRequest) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{25} } func (m *ShutdownNeighborRequest) GetAddress() string { if m != nil { @@ -1074,7 +1352,7 @@ func (m *ShutdownNeighborResponse) Reset() { *m = ShutdownNeighborResponse{} } func (m *ShutdownNeighborResponse) String() string { return proto.CompactTextString(m) } func (*ShutdownNeighborResponse) ProtoMessage() {} -func (*ShutdownNeighborResponse) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{18} } +func (*ShutdownNeighborResponse) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{26} } type EnableNeighborRequest struct { Address string `protobuf:"bytes,1,opt,name=address" json:"address,omitempty"` @@ -1083,7 +1361,7 @@ func (m *EnableNeighborRequest) Reset() { *m = EnableNeighborRequest{} } func (m *EnableNeighborRequest) String() string { return proto.CompactTextString(m) } func (*EnableNeighborRequest) ProtoMessage() {} -func (*EnableNeighborRequest) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{19} } +func (*EnableNeighborRequest) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{27} } func (m *EnableNeighborRequest) GetAddress() string { if m != nil { @@ -1098,7 +1376,7 @@ func (m *EnableNeighborResponse) Reset() { *m = EnableNeighborResponse{} } func (m *EnableNeighborResponse) String() string { return proto.CompactTextString(m) } func (*EnableNeighborResponse) ProtoMessage() {} -func (*EnableNeighborResponse) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{20} } +func (*EnableNeighborResponse) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{28} } type DisableNeighborRequest struct { Address string `protobuf:"bytes,1,opt,name=address" json:"address,omitempty"` @@ -1108,7 +1386,7 @@ func (m *DisableNeighborRequest) Reset() { *m = DisableNeighborRequest{} } func (m *DisableNeighborRequest) String() string { return proto.CompactTextString(m) } func (*DisableNeighborRequest) ProtoMessage() {} -func (*DisableNeighborRequest) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{21} } +func (*DisableNeighborRequest) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{29} } func (m *DisableNeighborRequest) GetAddress() string { if m != nil { @@ -1130,7 +1408,39 @@ func (m *DisableNeighborResponse) Reset() { *m = DisableNeighborResponse{} } func (m *DisableNeighborResponse) String() string { return proto.CompactTextString(m) } func (*DisableNeighborResponse) ProtoMessage() {} -func (*DisableNeighborResponse) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{22} } +func (*DisableNeighborResponse) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{30} } + +type UpdatePolicyRequest struct { + Sets []*DefinedSet `protobuf:"bytes,1,rep,name=sets" json:"sets,omitempty"` + Policies []*Policy `protobuf:"bytes,2,rep,name=policies" json:"policies,omitempty"` +} + +func (m *UpdatePolicyRequest) Reset() { *m = UpdatePolicyRequest{} } +func (m *UpdatePolicyRequest) String() string { return proto.CompactTextString(m) } +func (*UpdatePolicyRequest) ProtoMessage() {} +func (*UpdatePolicyRequest) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{31} } + +func (m *UpdatePolicyRequest) GetSets() []*DefinedSet { + if m != nil { + return m.Sets + } + return nil +} + +func (m *UpdatePolicyRequest) GetPolicies() []*Policy { + if m != nil { + return m.Policies + } + return nil +} + +type UpdatePolicyResponse struct { +} + +func (m *UpdatePolicyResponse) Reset() { *m = UpdatePolicyResponse{} } +func (m *UpdatePolicyResponse) String() string { return proto.CompactTextString(m) } +func (*UpdatePolicyResponse) ProtoMessage() {} +func (*UpdatePolicyResponse) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{32} } type EnableMrtRequest struct { DumpType int32 `protobuf:"varint,1,opt,name=dump_type,json=dumpType" json:"dump_type,omitempty"` @@ -1141,7 +1451,7 @@ func (m *EnableMrtRequest) Reset() { *m = EnableMrtRequest{} } func (m *EnableMrtRequest) String() string { return proto.CompactTextString(m) } func (*EnableMrtRequest) ProtoMessage() {} -func (*EnableMrtRequest) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{23} } +func (*EnableMrtRequest) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{33} } func (m *EnableMrtRequest) GetDumpType() int32 { if m != nil { @@ -1170,7 +1480,7 @@ func (m *EnableMrtResponse) Reset() { *m = EnableMrtResponse{} } func (m *EnableMrtResponse) String() string { return proto.CompactTextString(m) } func (*EnableMrtResponse) ProtoMessage() {} -func (*EnableMrtResponse) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{24} } +func (*EnableMrtResponse) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{34} } type DisableMrtRequest struct { } @@ -1178,7 +1488,7 @@ func (m *DisableMrtRequest) Reset() { *m = DisableMrtRequest{} } func (m *DisableMrtRequest) String() string { return proto.CompactTextString(m) } func (*DisableMrtRequest) ProtoMessage() {} -func (*DisableMrtRequest) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{25} } +func (*DisableMrtRequest) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{35} } type DisableMrtResponse struct { } @@ -1186,7 +1496,7 @@ func (m *DisableMrtResponse) Reset() { *m = DisableMrtResponse{} } func (m *DisableMrtResponse) String() string { return proto.CompactTextString(m) } func (*DisableMrtResponse) ProtoMessage() {} -func (*DisableMrtResponse) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{26} } +func (*DisableMrtResponse) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{36} } type InjectMrtRequest struct { Resource Resource `protobuf:"varint,1,opt,name=resource,enum=gobgpapi.Resource" json:"resource,omitempty"` @@ -1197,7 +1507,7 @@ func (m *InjectMrtRequest) Reset() { *m = InjectMrtRequest{} } func (m *InjectMrtRequest) String() string { return proto.CompactTextString(m) } func (*InjectMrtRequest) ProtoMessage() {} -func (*InjectMrtRequest) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{27} } +func (*InjectMrtRequest) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{37} } func (m *InjectMrtRequest) GetResource() Resource { if m != nil { @@ -1226,7 +1536,7 @@ func (m *InjectMrtResponse) Reset() { *m = InjectMrtResponse{} } func (m *InjectMrtResponse) String() string { return proto.CompactTextString(m) } func (*InjectMrtResponse) ProtoMessage() {} -func (*InjectMrtResponse) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{28} } +func (*InjectMrtResponse) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{38} } type AddBmpRequest struct { Address string `protobuf:"bytes,1,opt,name=address" json:"address,omitempty"` @@ -1237,7 +1547,7 @@ func (m *AddBmpRequest) Reset() { *m = AddBmpRequest{} } func (m *AddBmpRequest) String() string { return proto.CompactTextString(m) } func (*AddBmpRequest) ProtoMessage() {} -func (*AddBmpRequest) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{29} } +func (*AddBmpRequest) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{39} } func (m *AddBmpRequest) GetAddress() string { if m != nil { @@ -1266,7 +1576,7 @@ func (m *AddBmpResponse) Reset() { *m = AddBmpResponse{} } func (m *AddBmpResponse) String() string { return proto.CompactTextString(m) } func (*AddBmpResponse) ProtoMessage() {} -func (*AddBmpResponse) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{30} } +func (*AddBmpResponse) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{40} } type DeleteBmpRequest struct { Address string `protobuf:"bytes,1,opt,name=address" json:"address,omitempty"` @@ -1276,7 +1586,7 @@ func (m *DeleteBmpRequest) Reset() { *m = DeleteBmpRequest{} } func (m *DeleteBmpRequest) String() string { return proto.CompactTextString(m) } func (*DeleteBmpRequest) ProtoMessage() {} -func (*DeleteBmpRequest) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{31} } +func (*DeleteBmpRequest) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{41} } func (m *DeleteBmpRequest) GetAddress() string { if m != nil { @@ -1298,7 +1608,7 @@ func (m *DeleteBmpResponse) Reset() { *m = DeleteBmpResponse{} } func (m *DeleteBmpResponse) String() string { return proto.CompactTextString(m) } func (*DeleteBmpResponse) ProtoMessage() {} -func (*DeleteBmpResponse) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{32} } +func (*DeleteBmpResponse) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{42} } type MonitorRibRequest struct { Table *Table `protobuf:"bytes,1,opt,name=table" json:"table,omitempty"` @@ -1308,7 +1618,7 @@ func (m *MonitorRibRequest) Reset() { *m = MonitorRibRequest{} } func (m *MonitorRibRequest) String() string { return proto.CompactTextString(m) } func (*MonitorRibRequest) ProtoMessage() {} -func (*MonitorRibRequest) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{33} } +func (*MonitorRibRequest) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{43} } func (m *MonitorRibRequest) GetTable() *Table { if m != nil { @@ -1332,7 +1642,7 @@ func (m *RPKIConf) Reset() { *m = RPKIConf{} } func (m *RPKIConf) String() string { return proto.CompactTextString(m) } func (*RPKIConf) ProtoMessage() {} -func (*RPKIConf) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{34} } +func (*RPKIConf) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{44} } func (m *RPKIConf) GetAddress() string { if m != nil { @@ -1371,7 +1681,7 @@ func (m *RPKIState) Reset() { *m = RPKIState{} } func (m *RPKIState) String() string { return proto.CompactTextString(m) } func (*RPKIState) ProtoMessage() {} -func (*RPKIState) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{35} } +func (*RPKIState) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{45} } func (m *RPKIState) GetUptime() int64 { if m != nil { @@ -1500,7 +1810,7 @@ func (m *Rpki) Reset() { *m = Rpki{} } func (m *Rpki) String() string { return proto.CompactTextString(m) } func (*Rpki) ProtoMessage() {} -func (*Rpki) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{36} } +func (*Rpki) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{46} } func (m *Rpki) GetConf() *RPKIConf { if m != nil { @@ -1523,7 +1833,7 @@ func (m *GetRpkiRequest) Reset() { *m = GetRpkiRequest{} } func (m *GetRpkiRequest) String() string { return proto.CompactTextString(m) } func (*GetRpkiRequest) ProtoMessage() {} -func (*GetRpkiRequest) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{37} } +func (*GetRpkiRequest) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{47} } func (m *GetRpkiRequest) GetFamily() uint32 { if m != nil { @@ -1539,7 +1849,7 @@ func (m *GetRpkiResponse) Reset() { *m = GetRpkiResponse{} } func (m *GetRpkiResponse) String() string { return proto.CompactTextString(m) } func (*GetRpkiResponse) ProtoMessage() {} -func (*GetRpkiResponse) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{38} } +func (*GetRpkiResponse) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{48} } func (m *GetRpkiResponse) GetServers() []*Rpki { if m != nil { @@ -1557,7 +1867,7 @@ func (m *AddRpkiRequest) Reset() { *m = AddRpkiRequest{} } func (m *AddRpkiRequest) String() string { return proto.CompactTextString(m) } func (*AddRpkiRequest) ProtoMessage() {} -func (*AddRpkiRequest) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{39} } +func (*AddRpkiRequest) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{49} } func (m *AddRpkiRequest) GetAddress() string { if m != nil { @@ -1586,7 +1896,7 @@ func (m *AddRpkiResponse) Reset() { *m = AddRpkiResponse{} } func (m *AddRpkiResponse) String() string { return proto.CompactTextString(m) } func (*AddRpkiResponse) ProtoMessage() {} -func (*AddRpkiResponse) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{40} } +func (*AddRpkiResponse) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{50} } type DeleteRpkiRequest struct { Address string `protobuf:"bytes,1,opt,name=address" json:"address,omitempty"` @@ -1596,7 +1906,7 @@ func (m *DeleteRpkiRequest) Reset() { *m = DeleteRpkiRequest{} } func (m *DeleteRpkiRequest) String() string { return proto.CompactTextString(m) } func (*DeleteRpkiRequest) ProtoMessage() {} -func (*DeleteRpkiRequest) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{41} } +func (*DeleteRpkiRequest) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{51} } func (m *DeleteRpkiRequest) GetAddress() string { if m != nil { @@ -1618,7 +1928,7 @@ func (m *DeleteRpkiResponse) Reset() { *m = DeleteRpkiResponse{} } func (m *DeleteRpkiResponse) String() string { return proto.CompactTextString(m) } func (*DeleteRpkiResponse) ProtoMessage() {} -func (*DeleteRpkiResponse) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{42} } +func (*DeleteRpkiResponse) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{52} } type EnableRpkiRequest struct { Address string `protobuf:"bytes,1,opt,name=address" json:"address,omitempty"` @@ -1627,7 +1937,7 @@ func (m *EnableRpkiRequest) Reset() { *m = EnableRpkiRequest{} } func (m *EnableRpkiRequest) String() string { return proto.CompactTextString(m) } func (*EnableRpkiRequest) ProtoMessage() {} -func (*EnableRpkiRequest) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{43} } +func (*EnableRpkiRequest) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{53} } func (m *EnableRpkiRequest) GetAddress() string { if m != nil { @@ -1642,7 +1952,7 @@ func (m *EnableRpkiResponse) Reset() { *m = EnableRpkiResponse{} } func (m *EnableRpkiResponse) String() string { return proto.CompactTextString(m) } func (*EnableRpkiResponse) ProtoMessage() {} -func (*EnableRpkiResponse) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{44} } +func (*EnableRpkiResponse) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{54} } type DisableRpkiRequest struct { Address string `protobuf:"bytes,1,opt,name=address" json:"address,omitempty"` @@ -1651,7 +1961,7 @@ func (m *DisableRpkiRequest) Reset() { *m = DisableRpkiRequest{} } func (m *DisableRpkiRequest) String() string { return proto.CompactTextString(m) } func (*DisableRpkiRequest) ProtoMessage() {} -func (*DisableRpkiRequest) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{45} } +func (*DisableRpkiRequest) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{55} } func (m *DisableRpkiRequest) GetAddress() string { if m != nil { @@ -1666,7 +1976,7 @@ func (m *DisableRpkiResponse) Reset() { *m = DisableRpkiResponse{} } func (m *DisableRpkiResponse) String() string { return proto.CompactTextString(m) } func (*DisableRpkiResponse) ProtoMessage() {} -func (*DisableRpkiResponse) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{46} } +func (*DisableRpkiResponse) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{56} } type ResetRpkiRequest struct { Address string `protobuf:"bytes,1,opt,name=address" json:"address,omitempty"` @@ -1675,7 +1985,7 @@ func (m *ResetRpkiRequest) Reset() { *m = ResetRpkiRequest{} } func (m *ResetRpkiRequest) String() string { return proto.CompactTextString(m) } func (*ResetRpkiRequest) ProtoMessage() {} -func (*ResetRpkiRequest) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{47} } +func (*ResetRpkiRequest) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{57} } func (m *ResetRpkiRequest) GetAddress() string { if m != nil { @@ -1690,7 +2000,7 @@ func (m *ResetRpkiResponse) Reset() { *m = ResetRpkiResponse{} } func (m *ResetRpkiResponse) String() string { return proto.CompactTextString(m) } func (*ResetRpkiResponse) ProtoMessage() {} -func (*ResetRpkiResponse) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{48} } +func (*ResetRpkiResponse) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{58} } type SoftResetRpkiRequest struct { Address string `protobuf:"bytes,1,opt,name=address" json:"address,omitempty"` @@ -1699,7 +2009,7 @@ func (m *SoftResetRpkiRequest) Reset() { *m = SoftResetRpkiRequest{} } func (m *SoftResetRpkiRequest) String() string { return proto.CompactTextString(m) } func (*SoftResetRpkiRequest) ProtoMessage() {} -func (*SoftResetRpkiRequest) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{49} } +func (*SoftResetRpkiRequest) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{59} } func (m *SoftResetRpkiRequest) GetAddress() string { if m != nil { @@ -1714,7 +2024,7 @@ func (m *SoftResetRpkiResponse) Reset() { *m = SoftResetRpkiResponse{} } func (m *SoftResetRpkiResponse) String() string { return proto.CompactTextString(m) } func (*SoftResetRpkiResponse) ProtoMessage() {} -func (*SoftResetRpkiResponse) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{50} } +func (*SoftResetRpkiResponse) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{60} } type EnableZebraRequest struct { Url string `protobuf:"bytes,1,opt,name=url" json:"url,omitempty"` @@ -1727,7 +2037,7 @@ func (m *EnableZebraRequest) Reset() { *m = EnableZebraRequest{} } func (m *EnableZebraRequest) String() string { return proto.CompactTextString(m) } func (*EnableZebraRequest) ProtoMessage() {} -func (*EnableZebraRequest) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{51} } +func (*EnableZebraRequest) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{61} } func (m *EnableZebraRequest) GetUrl() string { if m != nil { @@ -1770,7 +2080,7 @@ func (m *EnableZebraResponse) Reset() { *m = EnableZebraResponse{} } func (m *EnableZebraResponse) String() string { return proto.CompactTextString(m) } func (*EnableZebraResponse) ProtoMessage() {} -func (*EnableZebraResponse) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{52} } +func (*EnableZebraResponse) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{62} } type GetVrfRequest struct { } @@ -1778,7 +2088,7 @@ func (m *GetVrfRequest) Reset() { *m = GetVrfRequest{} } func (m *GetVrfRequest) String() string { return proto.CompactTextString(m) } func (*GetVrfRequest) ProtoMessage() {} -func (*GetVrfRequest) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{53} } +func (*GetVrfRequest) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{63} } type GetVrfResponse struct { Vrfs []*Vrf `protobuf:"bytes,1,rep,name=vrfs" json:"vrfs,omitempty"` @@ -1787,7 +2097,7 @@ func (m *GetVrfResponse) Reset() { *m = GetVrfResponse{} } func (m *GetVrfResponse) String() string { return proto.CompactTextString(m) } func (*GetVrfResponse) ProtoMessage() {} -func (*GetVrfResponse) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{54} } +func (*GetVrfResponse) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{64} } func (m *GetVrfResponse) GetVrfs() []*Vrf { if m != nil { @@ -1803,7 +2113,7 @@ func (m *AddVrfRequest) Reset() { *m = AddVrfRequest{} } func (m *AddVrfRequest) String() string { return proto.CompactTextString(m) } func (*AddVrfRequest) ProtoMessage() {} -func (*AddVrfRequest) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{55} } +func (*AddVrfRequest) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{65} } func (m *AddVrfRequest) GetVrf() *Vrf { if m != nil { @@ -1818,7 +2128,7 @@ func (m *AddVrfResponse) Reset() { *m = AddVrfResponse{} } func (m *AddVrfResponse) String() string { return proto.CompactTextString(m) } func (*AddVrfResponse) ProtoMessage() {} -func (*AddVrfResponse) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{56} } +func (*AddVrfResponse) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{66} } type DeleteVrfRequest struct { Vrf *Vrf `protobuf:"bytes,1,opt,name=vrf" json:"vrf,omitempty"` @@ -1827,7 +2137,7 @@ func (m *DeleteVrfRequest) Reset() { *m = DeleteVrfRequest{} } func (m *DeleteVrfRequest) String() string { return proto.CompactTextString(m) } func (*DeleteVrfRequest) ProtoMessage() {} -func (*DeleteVrfRequest) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{57} } +func (*DeleteVrfRequest) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{67} } func (m *DeleteVrfRequest) GetVrf() *Vrf { if m != nil { @@ -1842,7 +2152,7 @@ func (m *DeleteVrfResponse) Reset() { *m = DeleteVrfResponse{} } func (m *DeleteVrfResponse) String() string { return proto.CompactTextString(m) } func (*DeleteVrfResponse) ProtoMessage() {} -func (*DeleteVrfResponse) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{58} } +func (*DeleteVrfResponse) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{68} } type GetDefinedSetRequest struct { Type DefinedType `protobuf:"varint,1,opt,name=type,enum=gobgpapi.DefinedType" json:"type,omitempty"` @@ -1852,7 +2162,7 @@ func (m *GetDefinedSetRequest) Reset() { *m = GetDefinedSetRequest{} } func (m *GetDefinedSetRequest) String() string { return proto.CompactTextString(m) } func (*GetDefinedSetRequest) ProtoMessage() {} -func (*GetDefinedSetRequest) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{59} } +func (*GetDefinedSetRequest) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{69} } func (m *GetDefinedSetRequest) GetType() DefinedType { if m != nil { @@ -1875,7 +2185,7 @@ func (m *GetDefinedSetResponse) Reset() { *m = GetDefinedSetResponse{} } func (m *GetDefinedSetResponse) String() string { return proto.CompactTextString(m) } func (*GetDefinedSetResponse) ProtoMessage() {} -func (*GetDefinedSetResponse) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{60} } +func (*GetDefinedSetResponse) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{70} } func (m *GetDefinedSetResponse) GetSets() []*DefinedSet { if m != nil { @@ -1891,7 +2201,7 @@ func (m *AddDefinedSetRequest) Reset() { *m = AddDefinedSetRequest{} } func (m *AddDefinedSetRequest) String() string { return proto.CompactTextString(m) } func (*AddDefinedSetRequest) ProtoMessage() {} -func (*AddDefinedSetRequest) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{61} } +func (*AddDefinedSetRequest) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{71} } func (m *AddDefinedSetRequest) GetSet() *DefinedSet { if m != nil { @@ -1906,7 +2216,7 @@ func (m *AddDefinedSetResponse) Reset() { *m = AddDefinedSetResponse{} } func (m *AddDefinedSetResponse) String() string { return proto.CompactTextString(m) } func (*AddDefinedSetResponse) ProtoMessage() {} -func (*AddDefinedSetResponse) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{62} } +func (*AddDefinedSetResponse) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{72} } type DeleteDefinedSetRequest struct { Set *DefinedSet `protobuf:"bytes,1,opt,name=set" json:"set,omitempty"` @@ -1916,7 +2226,7 @@ func (m *DeleteDefinedSetRequest) Reset() { *m = DeleteDefinedSetRequest{} } func (m *DeleteDefinedSetRequest) String() string { return proto.CompactTextString(m) } func (*DeleteDefinedSetRequest) ProtoMessage() {} -func (*DeleteDefinedSetRequest) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{63} } +func (*DeleteDefinedSetRequest) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{73} } func (m *DeleteDefinedSetRequest) GetSet() *DefinedSet { if m != nil { @@ -1938,7 +2248,7 @@ func (m *DeleteDefinedSetResponse) Reset() { *m = DeleteDefinedSetResponse{} } func (m *DeleteDefinedSetResponse) String() string { return proto.CompactTextString(m) } func (*DeleteDefinedSetResponse) ProtoMessage() {} -func (*DeleteDefinedSetResponse) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{64} } +func (*DeleteDefinedSetResponse) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{74} } type ReplaceDefinedSetRequest struct { Set *DefinedSet `protobuf:"bytes,1,opt,name=set" json:"set,omitempty"` @@ -1947,7 +2257,7 @@ func (m *ReplaceDefinedSetRequest) Reset() { *m = ReplaceDefinedSetRequest{} } func (m *ReplaceDefinedSetRequest) String() string { return proto.CompactTextString(m) } func (*ReplaceDefinedSetRequest) ProtoMessage() {} -func (*ReplaceDefinedSetRequest) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{65} } +func (*ReplaceDefinedSetRequest) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{75} } func (m *ReplaceDefinedSetRequest) GetSet() *DefinedSet { if m != nil { @@ -1962,7 +2272,7 @@ func (m *ReplaceDefinedSetResponse) Reset() { *m = ReplaceDefinedSetResponse{} } func (m *ReplaceDefinedSetResponse) String() string { return proto.CompactTextString(m) } func (*ReplaceDefinedSetResponse) ProtoMessage() {} -func (*ReplaceDefinedSetResponse) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{66} } +func (*ReplaceDefinedSetResponse) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{76} } type GetStatementRequest struct { } @@ -1970,7 +2280,7 @@ func (m *GetStatementRequest) Reset() { *m = GetStatementRequest{} } func (m *GetStatementRequest) String() string { return proto.CompactTextString(m) } func (*GetStatementRequest) ProtoMessage() {} -func (*GetStatementRequest) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{67} } +func (*GetStatementRequest) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{77} } type GetStatementResponse struct { Statements []*Statement `protobuf:"bytes,1,rep,name=statements" json:"statements,omitempty"` @@ -1979,7 +2289,7 @@ func (m *GetStatementResponse) Reset() { *m = GetStatementResponse{} } func (m *GetStatementResponse) String() string { return proto.CompactTextString(m) } func (*GetStatementResponse) ProtoMessage() {} -func (*GetStatementResponse) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{68} } +func (*GetStatementResponse) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{78} } func (m *GetStatementResponse) GetStatements() []*Statement { if m != nil { @@ -1995,7 +2305,7 @@ func (m *AddStatementRequest) Reset() { *m = AddStatementRequest{} } func (m *AddStatementRequest) String() string { return proto.CompactTextString(m) } func (*AddStatementRequest) ProtoMessage() {} -func (*AddStatementRequest) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{69} } +func (*AddStatementRequest) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{79} } func (m *AddStatementRequest) GetStatement() *Statement { if m != nil { @@ -2010,7 +2320,7 @@ func (m *AddStatementResponse) Reset() { *m = AddStatementResponse{} } func (m *AddStatementResponse) String() string { return proto.CompactTextString(m) } func (*AddStatementResponse) ProtoMessage() {} -func (*AddStatementResponse) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{70} } +func (*AddStatementResponse) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{80} } type DeleteStatementRequest struct { Statement *Statement `protobuf:"bytes,1,opt,name=statement" json:"statement,omitempty"` @@ -2020,7 +2330,7 @@ func (m *DeleteStatementRequest) Reset() { *m = DeleteStatementRequest{} } func (m *DeleteStatementRequest) String() string { return proto.CompactTextString(m) } func (*DeleteStatementRequest) ProtoMessage() {} -func (*DeleteStatementRequest) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{71} } +func (*DeleteStatementRequest) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{81} } func (m *DeleteStatementRequest) GetStatement() *Statement { if m != nil { @@ -2042,7 +2352,7 @@ func (m *DeleteStatementResponse) Reset() { *m = DeleteStatementResponse{} } func (m *DeleteStatementResponse) String() string { return proto.CompactTextString(m) } func (*DeleteStatementResponse) ProtoMessage() {} -func (*DeleteStatementResponse) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{72} } +func (*DeleteStatementResponse) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{82} } type ReplaceStatementRequest struct { Statement *Statement `protobuf:"bytes,1,opt,name=statement" json:"statement,omitempty"` @@ -2051,7 +2361,7 @@ func (m *ReplaceStatementRequest) Reset() { *m = ReplaceStatementRequest{} } func (m *ReplaceStatementRequest) String() string { return proto.CompactTextString(m) } func (*ReplaceStatementRequest) ProtoMessage() {} -func (*ReplaceStatementRequest) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{73} } +func (*ReplaceStatementRequest) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{83} } func (m *ReplaceStatementRequest) GetStatement() *Statement { if m != nil { @@ -2066,7 +2376,7 @@ func (m *ReplaceStatementResponse) Reset() { *m = ReplaceStatementResponse{} } func (m *ReplaceStatementResponse) String() string { return proto.CompactTextString(m) } func (*ReplaceStatementResponse) ProtoMessage() {} -func (*ReplaceStatementResponse) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{74} } +func (*ReplaceStatementResponse) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{84} } type GetPolicyRequest struct { } @@ -2074,7 +2384,7 @@ func (m *GetPolicyRequest) Reset() { *m = GetPolicyRequest{} } func (m *GetPolicyRequest) String() string { return proto.CompactTextString(m) } func (*GetPolicyRequest) ProtoMessage() {} -func (*GetPolicyRequest) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{75} } +func (*GetPolicyRequest) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{85} } type GetPolicyResponse struct { Policies []*Policy `protobuf:"bytes,1,rep,name=policies" json:"policies,omitempty"` @@ -2083,7 +2393,7 @@ func (m *GetPolicyResponse) Reset() { *m = GetPolicyResponse{} } func (m *GetPolicyResponse) String() string { return proto.CompactTextString(m) } func (*GetPolicyResponse) ProtoMessage() {} -func (*GetPolicyResponse) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{76} } +func (*GetPolicyResponse) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{86} } func (m *GetPolicyResponse) GetPolicies() []*Policy { if m != nil { @@ -2102,7 +2412,7 @@ func (m *AddPolicyRequest) Reset() { *m = AddPolicyRequest{} } func (m *AddPolicyRequest) String() string { return proto.CompactTextString(m) } func (*AddPolicyRequest) ProtoMessage() {} -func (*AddPolicyRequest) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{77} } +func (*AddPolicyRequest) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{87} } func (m *AddPolicyRequest) GetPolicy() *Policy { if m != nil { @@ -2124,7 +2434,7 @@ func (m *AddPolicyResponse) Reset() { *m = AddPolicyResponse{} } func (m *AddPolicyResponse) String() string { return proto.CompactTextString(m) } func (*AddPolicyResponse) ProtoMessage() {} -func (*AddPolicyResponse) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{78} } +func (*AddPolicyResponse) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{88} } type DeletePolicyRequest struct { Policy *Policy `protobuf:"bytes,1,opt,name=policy" json:"policy,omitempty"` @@ -2137,7 +2447,7 @@ func (m *DeletePolicyRequest) Reset() { *m = DeletePolicyRequest{} } func (m *DeletePolicyRequest) String() string { return proto.CompactTextString(m) } func (*DeletePolicyRequest) ProtoMessage() {} -func (*DeletePolicyRequest) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{79} } +func (*DeletePolicyRequest) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{89} } func (m *DeletePolicyRequest) GetPolicy() *Policy { if m != nil { @@ -2166,7 +2476,7 @@ func (m *DeletePolicyResponse) Reset() { *m = DeletePolicyResponse{} } func (m *DeletePolicyResponse) String() string { return proto.CompactTextString(m) } func (*DeletePolicyResponse) ProtoMessage() {} -func (*DeletePolicyResponse) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{80} } +func (*DeletePolicyResponse) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{90} } type ReplacePolicyRequest struct { Policy *Policy `protobuf:"bytes,1,opt,name=policy" json:"policy,omitempty"` @@ -2181,7 +2491,7 @@ func (m *ReplacePolicyRequest) Reset() { *m = ReplacePolicyRequest{} } func (m *ReplacePolicyRequest) String() string { return proto.CompactTextString(m) } func (*ReplacePolicyRequest) ProtoMessage() {} -func (*ReplacePolicyRequest) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{81} } +func (*ReplacePolicyRequest) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{91} } func (m *ReplacePolicyRequest) GetPolicy() *Policy { if m != nil { @@ -2210,7 +2520,7 @@ func (m *ReplacePolicyResponse) Reset() { *m = ReplacePolicyResponse{} } func (m *ReplacePolicyResponse) String() string { return proto.CompactTextString(m) } func (*ReplacePolicyResponse) ProtoMessage() {} -func (*ReplacePolicyResponse) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{82} } +func (*ReplacePolicyResponse) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{92} } type GetPolicyAssignmentRequest struct { Assignment *PolicyAssignment `protobuf:"bytes,1,opt,name=assignment" json:"assignment,omitempty"` @@ -2219,7 +2529,7 @@ func (m *GetPolicyAssignmentRequest) Reset() { *m = GetPolicyAssignmentRequest{} } func (m *GetPolicyAssignmentRequest) String() string { return proto.CompactTextString(m) } func (*GetPolicyAssignmentRequest) ProtoMessage() {} -func (*GetPolicyAssignmentRequest) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{83} } +func (*GetPolicyAssignmentRequest) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{93} } func (m *GetPolicyAssignmentRequest) GetAssignment() *PolicyAssignment { if m != nil { @@ -2235,7 +2545,7 @@ func (m *GetPolicyAssignmentResponse) Reset() { *m = GetPolicyAssignmentResponse{} } func (m *GetPolicyAssignmentResponse) String() string { return proto.CompactTextString(m) } func (*GetPolicyAssignmentResponse) ProtoMessage() {} -func (*GetPolicyAssignmentResponse) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{84} } +func (*GetPolicyAssignmentResponse) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{94} } func (m *GetPolicyAssignmentResponse) GetAssignment() *PolicyAssignment { if m != nil { @@ -2251,7 +2561,7 @@ func (m *AddPolicyAssignmentRequest) Reset() { *m = AddPolicyAssignmentRequest{} } func (m *AddPolicyAssignmentRequest) String() string { return proto.CompactTextString(m) } func (*AddPolicyAssignmentRequest) ProtoMessage() {} -func (*AddPolicyAssignmentRequest) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{85} } +func (*AddPolicyAssignmentRequest) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{95} } func (m *AddPolicyAssignmentRequest) GetAssignment() *PolicyAssignment { if m != nil { @@ -2266,7 +2576,7 @@ func (m *AddPolicyAssignmentResponse) Reset() { *m = AddPolicyAssignmentResponse{} } func (m *AddPolicyAssignmentResponse) String() string { return proto.CompactTextString(m) } func (*AddPolicyAssignmentResponse) ProtoMessage() {} -func (*AddPolicyAssignmentResponse) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{86} } +func (*AddPolicyAssignmentResponse) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{96} } type DeletePolicyAssignmentRequest struct { Assignment *PolicyAssignment `protobuf:"bytes,1,opt,name=assignment" json:"assignment,omitempty"` @@ -2276,7 +2586,7 @@ func (m *DeletePolicyAssignmentRequest) Reset() { *m = DeletePolicyAssignmentRequest{} } func (m *DeletePolicyAssignmentRequest) String() string { return proto.CompactTextString(m) } func (*DeletePolicyAssignmentRequest) ProtoMessage() {} -func (*DeletePolicyAssignmentRequest) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{87} } +func (*DeletePolicyAssignmentRequest) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{97} } func (m *DeletePolicyAssignmentRequest) GetAssignment() *PolicyAssignment { if m != nil { @@ -2298,7 +2608,7 @@ func (m *DeletePolicyAssignmentResponse) Reset() { *m = DeletePolicyAssignmentResponse{} } func (m *DeletePolicyAssignmentResponse) String() string { return proto.CompactTextString(m) } func (*DeletePolicyAssignmentResponse) ProtoMessage() {} -func (*DeletePolicyAssignmentResponse) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{88} } +func (*DeletePolicyAssignmentResponse) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{98} } type ReplacePolicyAssignmentRequest struct { Assignment *PolicyAssignment `protobuf:"bytes,1,opt,name=assignment" json:"assignment,omitempty"` @@ -2307,7 +2617,7 @@ func (m *ReplacePolicyAssignmentRequest) Reset() { *m = ReplacePolicyAssignmentRequest{} } func (m *ReplacePolicyAssignmentRequest) String() string { return proto.CompactTextString(m) } func (*ReplacePolicyAssignmentRequest) ProtoMessage() {} -func (*ReplacePolicyAssignmentRequest) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{89} } +func (*ReplacePolicyAssignmentRequest) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{99} } func (m *ReplacePolicyAssignmentRequest) GetAssignment() *PolicyAssignment { if m != nil { @@ -2323,7 +2633,7 @@ func (m *ReplacePolicyAssignmentResponse) String() string { return proto.CompactTextString(m) } func (*ReplacePolicyAssignmentResponse) ProtoMessage() {} func (*ReplacePolicyAssignmentResponse) Descriptor() ([]byte, []int) { - return fileDescriptor0, []int{90} + return fileDescriptor0, []int{100} } type GetServerRequest struct { @@ -2332,7 +2642,7 @@ func (m *GetServerRequest) Reset() { *m = GetServerRequest{} } func (m *GetServerRequest) String() string { return proto.CompactTextString(m) } func (*GetServerRequest) ProtoMessage() {} -func (*GetServerRequest) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{91} } +func (*GetServerRequest) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{101} } type GetServerResponse struct { Global *Global `protobuf:"bytes,1,opt,name=global" json:"global,omitempty"` @@ -2341,7 +2651,7 @@ func (m *GetServerResponse) Reset() { *m = GetServerResponse{} } func (m *GetServerResponse) String() string { return proto.CompactTextString(m) } func (*GetServerResponse) ProtoMessage() {} -func (*GetServerResponse) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{92} } +func (*GetServerResponse) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{102} } func (m *GetServerResponse) GetGlobal() *Global { if m != nil { @@ -2357,7 +2667,7 @@ func (m *StartServerRequest) Reset() { *m = StartServerRequest{} } func (m *StartServerRequest) String() string { return proto.CompactTextString(m) } func (*StartServerRequest) ProtoMessage() {} -func (*StartServerRequest) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{93} } +func (*StartServerRequest) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{103} } func (m *StartServerRequest) GetGlobal() *Global { if m != nil { @@ -2372,7 +2682,7 @@ func (m *StartServerResponse) Reset() { *m = StartServerResponse{} } func (m *StartServerResponse) String() string { return proto.CompactTextString(m) } func (*StartServerResponse) ProtoMessage() {} -func (*StartServerResponse) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{94} } +func (*StartServerResponse) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{104} } type StopServerRequest struct { } @@ -2380,7 +2690,7 @@ func (m *StopServerRequest) Reset() { *m = StopServerRequest{} } func (m *StopServerRequest) String() string { return proto.CompactTextString(m) } func (*StopServerRequest) ProtoMessage() {} -func (*StopServerRequest) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{95} } +func (*StopServerRequest) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{105} } type StopServerResponse struct { } @@ -2388,7 +2698,7 @@ func (m *StopServerResponse) Reset() { *m = StopServerResponse{} } func (m *StopServerResponse) String() string { return proto.CompactTextString(m) } func (*StopServerResponse) ProtoMessage() {} -func (*StopServerResponse) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{96} } +func (*StopServerResponse) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{106} } type RPKIValidation struct { State RPKIValidation_State `protobuf:"varint,1,opt,name=state,enum=gobgpapi.RPKIValidation_State" json:"state,omitempty"` @@ -2401,7 +2711,7 @@ func (m *RPKIValidation) Reset() { *m = RPKIValidation{} } func (m *RPKIValidation) String() string { return proto.CompactTextString(m) } func (*RPKIValidation) ProtoMessage() {} -func (*RPKIValidation) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{97} } +func (*RPKIValidation) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{107} } func (m *RPKIValidation) GetState() RPKIValidation_State { if m != nil { @@ -2458,12 +2768,30 @@ IsNexthopInvalid bool `protobuf:"varint,17,opt,name=is_nexthop_invalid,json=isNexthopInvalid" json:"is_nexthop_invalid,omitempty"` Identifier uint32 `protobuf:"varint,18,opt,name=identifier" json:"identifier,omitempty"` LocalIdentifier uint32 `protobuf:"varint,19,opt,name=local_identifier,json=localIdentifier" json:"local_identifier,omitempty"` + // One of the following defined in "api/attribute.proto": + // - IPAddressPrefix + // - LabeledIPAddressPrefix + // - EncapsulationNLRI + // - EVPNEthernetAutoDiscoveryRoute + // - EVPNMACIPAdvertisementRoute + // - EVPNInclusiveMulticastEthernetTagRoute + // - EVPNEthernetSegmentRoute + // - EVPNIPPrefixRoute + // - LabeledVPNIPAddressPrefix + // - RouteTargetMembershipNLRI + // - FlowSpecNLRI + // - VPNFlowSpecNLRI + // - OpaqueNLRI + AnyNlri *google_protobuf.Any `protobuf:"bytes,20,opt,name=any_nlri,json=anyNlri" json:"any_nlri,omitempty"` + // Each attribute must be one of *Attribute defined in + // "api/attribute.proto". + AnyPattrs []*google_protobuf.Any `protobuf:"bytes,21,rep,name=any_pattrs,json=anyPattrs" json:"any_pattrs,omitempty"` } func (m *Path) Reset() { *m = Path{} } func (m *Path) String() string { return proto.CompactTextString(m) } func (*Path) ProtoMessage() {} -func (*Path) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{98} } +func (*Path) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{108} } func (m *Path) GetNlri() []byte { if m != nil { @@ -2598,6 +2926,20 @@ return 0 } +func (m *Path) GetAnyNlri() *google_protobuf.Any { + if m != nil { + return m.AnyNlri + } + return nil +} + +func (m *Path) GetAnyPattrs() []*google_protobuf.Any { + if m != nil { + return m.AnyPattrs + } + return nil +} + type Destination struct { Prefix string `protobuf:"bytes,1,opt,name=prefix" json:"prefix,omitempty"` Paths []*Path `protobuf:"bytes,2,rep,name=paths" json:"paths,omitempty"` @@ -2608,7 +2950,7 @@ func (m *Destination) Reset() { *m = Destination{} } func (m *Destination) String() string { return proto.CompactTextString(m) } func (*Destination) ProtoMessage() {} -func (*Destination) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{99} } +func (*Destination) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{109} } func (m *Destination) GetPrefix() string { if m != nil { @@ -2649,7 +2991,7 @@ func (m *Table) Reset() { *m = Table{} } func (m *Table) String() string { return proto.CompactTextString(m) } func (*Table) ProtoMessage() {} -func (*Table) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{100} } +func (*Table) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{110} } func (m *Table) GetType() Resource { if m != nil { @@ -2693,7 +3035,7 @@ func (m *GetRibRequest) Reset() { *m = GetRibRequest{} } func (m *GetRibRequest) String() string { return proto.CompactTextString(m) } func (*GetRibRequest) ProtoMessage() {} -func (*GetRibRequest) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{101} } +func (*GetRibRequest) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{111} } func (m *GetRibRequest) GetTable() *Table { if m != nil { @@ -2709,7 +3051,7 @@ func (m *GetRibResponse) Reset() { *m = GetRibResponse{} } func (m *GetRibResponse) String() string { return proto.CompactTextString(m) } func (*GetRibResponse) ProtoMessage() {} -func (*GetRibResponse) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{102} } +func (*GetRibResponse) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{112} } func (m *GetRibResponse) GetTable() *Table { if m != nil { @@ -2727,7 +3069,7 @@ func (m *TableLookupPrefix) Reset() { *m = TableLookupPrefix{} } func (m *TableLookupPrefix) String() string { return proto.CompactTextString(m) } func (*TableLookupPrefix) ProtoMessage() {} -func (*TableLookupPrefix) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{103} } +func (*TableLookupPrefix) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{113} } func (m *TableLookupPrefix) GetPrefix() string { if m != nil { @@ -2753,7 +3095,7 @@ func (m *GetPathRequest) Reset() { *m = GetPathRequest{} } func (m *GetPathRequest) String() string { return proto.CompactTextString(m) } func (*GetPathRequest) ProtoMessage() {} -func (*GetPathRequest) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{104} } +func (*GetPathRequest) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{114} } func (m *GetPathRequest) GetType() Resource { if m != nil { @@ -2792,7 +3134,7 @@ func (m *ValidateRibRequest) Reset() { *m = ValidateRibRequest{} } func (m *ValidateRibRequest) String() string { return proto.CompactTextString(m) } func (*ValidateRibRequest) ProtoMessage() {} -func (*ValidateRibRequest) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{105} } +func (*ValidateRibRequest) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{115} } func (m *ValidateRibRequest) GetType() Resource { if m != nil { @@ -2821,7 +3163,7 @@ func (m *ValidateRibResponse) Reset() { *m = ValidateRibResponse{} } func (m *ValidateRibResponse) String() string { return proto.CompactTextString(m) } func (*ValidateRibResponse) ProtoMessage() {} -func (*ValidateRibResponse) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{106} } +func (*ValidateRibResponse) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{116} } type Peer struct { // Note: Regarding to the consistency with OpenConfig model, a list of @@ -2844,7 +3186,7 @@ func (m *Peer) Reset() { *m = Peer{} } func (m *Peer) String() string { return proto.CompactTextString(m) } func (*Peer) ProtoMessage() {} -func (*Peer) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{107} } +func (*Peer) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{117} } func (m *Peer) GetFamilies() []uint32 { if m != nil { @@ -2930,6 +3272,137 @@ return nil } +type PeerGroup struct { + // Note: Regarding to the consistency with OpenConfig model, a list of + // address family should be removed from here, and should be configured with + // the list of AfiSafi instead. + Families []uint32 `protobuf:"varint,1,rep,packed,name=families" json:"families,omitempty"` + ApplyPolicy *ApplyPolicy `protobuf:"bytes,2,opt,name=apply_policy,json=applyPolicy" json:"apply_policy,omitempty"` + Conf *PeerGroupConf `protobuf:"bytes,3,opt,name=conf" json:"conf,omitempty"` + EbgpMultihop *EbgpMultihop `protobuf:"bytes,4,opt,name=ebgp_multihop,json=ebgpMultihop" json:"ebgp_multihop,omitempty"` + RouteReflector *RouteReflector `protobuf:"bytes,5,opt,name=route_reflector,json=routeReflector" json:"route_reflector,omitempty"` + Info *PeerGroupState `protobuf:"bytes,6,opt,name=info" json:"info,omitempty"` + Timers *Timers `protobuf:"bytes,7,opt,name=timers" json:"timers,omitempty"` + Transport *Transport `protobuf:"bytes,8,opt,name=transport" json:"transport,omitempty"` + RouteServer *RouteServer `protobuf:"bytes,9,opt,name=route_server,json=routeServer" json:"route_server,omitempty"` + GracefulRestart *GracefulRestart `protobuf:"bytes,10,opt,name=graceful_restart,json=gracefulRestart" json:"graceful_restart,omitempty"` + AfiSafis []*AfiSafi `protobuf:"bytes,11,rep,name=afi_safis,json=afiSafis" json:"afi_safis,omitempty"` + AddPaths *AddPaths `protobuf:"bytes,12,opt,name=add_paths,json=addPaths" json:"add_paths,omitempty"` +} + +func (m *PeerGroup) Reset() { *m = PeerGroup{} } +func (m *PeerGroup) String() string { return proto.CompactTextString(m) } +func (*PeerGroup) ProtoMessage() {} +func (*PeerGroup) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{118} } + +func (m *PeerGroup) GetFamilies() []uint32 { + if m != nil { + return m.Families + } + return nil +} + +func (m *PeerGroup) GetApplyPolicy() *ApplyPolicy { + if m != nil { + return m.ApplyPolicy + } + return nil +} + +func (m *PeerGroup) GetConf() *PeerGroupConf { + if m != nil { + return m.Conf + } + return nil +} + +func (m *PeerGroup) GetEbgpMultihop() *EbgpMultihop { + if m != nil { + return m.EbgpMultihop + } + return nil +} + +func (m *PeerGroup) GetRouteReflector() *RouteReflector { + if m != nil { + return m.RouteReflector + } + return nil +} + +func (m *PeerGroup) GetInfo() *PeerGroupState { + if m != nil { + return m.Info + } + return nil +} + +func (m *PeerGroup) GetTimers() *Timers { + if m != nil { + return m.Timers + } + return nil +} + +func (m *PeerGroup) GetTransport() *Transport { + if m != nil { + return m.Transport + } + return nil +} + +func (m *PeerGroup) GetRouteServer() *RouteServer { + if m != nil { + return m.RouteServer + } + return nil +} + +func (m *PeerGroup) GetGracefulRestart() *GracefulRestart { + if m != nil { + return m.GracefulRestart + } + return nil +} + +func (m *PeerGroup) GetAfiSafis() []*AfiSafi { + if m != nil { + return m.AfiSafis + } + return nil +} + +func (m *PeerGroup) GetAddPaths() *AddPaths { + if m != nil { + return m.AddPaths + } + return nil +} + +type DynamicNeighbor struct { + Prefix string `protobuf:"bytes,1,opt,name=prefix" json:"prefix,omitempty"` + PeerGroup string `protobuf:"bytes,2,opt,name=peer_group,json=peerGroup" json:"peer_group,omitempty"` +} + +func (m *DynamicNeighbor) Reset() { *m = DynamicNeighbor{} } +func (m *DynamicNeighbor) String() string { return proto.CompactTextString(m) } +func (*DynamicNeighbor) ProtoMessage() {} +func (*DynamicNeighbor) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{119} } + +func (m *DynamicNeighbor) GetPrefix() string { + if m != nil { + return m.Prefix + } + return "" +} + +func (m *DynamicNeighbor) GetPeerGroup() string { + if m != nil { + return m.PeerGroup + } + return "" +} + type ApplyPolicy struct { InPolicy *PolicyAssignment `protobuf:"bytes,1,opt,name=in_policy,json=inPolicy" json:"in_policy,omitempty"` ExportPolicy *PolicyAssignment `protobuf:"bytes,2,opt,name=export_policy,json=exportPolicy" json:"export_policy,omitempty"` @@ -2939,7 +3412,7 @@ func (m *ApplyPolicy) Reset() { *m = ApplyPolicy{} } func (m *ApplyPolicy) String() string { return proto.CompactTextString(m) } func (*ApplyPolicy) ProtoMessage() {} -func (*ApplyPolicy) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{108} } +func (*ApplyPolicy) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{120} } func (m *ApplyPolicy) GetInPolicy() *PolicyAssignment { if m != nil { @@ -2971,7 +3444,7 @@ func (m *PrefixLimit) Reset() { *m = PrefixLimit{} } func (m *PrefixLimit) String() string { return proto.CompactTextString(m) } func (*PrefixLimit) ProtoMessage() {} -func (*PrefixLimit) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{109} } +func (*PrefixLimit) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{121} } func (m *PrefixLimit) GetFamily() uint32 { if m != nil { @@ -3005,9 +3478,11 @@ RemovePrivateAs PeerConf_RemovePrivateAs `protobuf:"varint,8,opt,name=remove_private_as,json=removePrivateAs,enum=gobgpapi.PeerConf_RemovePrivateAs" json:"remove_private_as,omitempty"` RouteFlapDamping bool `protobuf:"varint,9,opt,name=route_flap_damping,json=routeFlapDamping" json:"route_flap_damping,omitempty"` SendCommunity uint32 `protobuf:"varint,10,opt,name=send_community,json=sendCommunity" json:"send_community,omitempty"` - RemoteCap [][]byte `protobuf:"bytes,11,rep,name=remote_cap,json=remoteCap,proto3" json:"remote_cap,omitempty"` - LocalCap [][]byte `protobuf:"bytes,12,rep,name=local_cap,json=localCap,proto3" json:"local_cap,omitempty"` - Id string `protobuf:"bytes,13,opt,name=id" json:"id,omitempty"` + // Each attribute must be one of *Capability defined in + // "api/capability.proto". + RemoteCap []*google_protobuf.Any `protobuf:"bytes,11,rep,name=remote_cap,json=remoteCap" json:"remote_cap,omitempty"` + LocalCap []*google_protobuf.Any `protobuf:"bytes,12,rep,name=local_cap,json=localCap" json:"local_cap,omitempty"` + Id string `protobuf:"bytes,13,opt,name=id" json:"id,omitempty"` // Note: Regarding to the consistency with OpenConfig model, list of // PrefixLimit should be removed from here, and list of PrefixLimit in // AfiSafi should be used instead. @@ -3022,7 +3497,7 @@ func (m *PeerConf) Reset() { *m = PeerConf{} } func (m *PeerConf) String() string { return proto.CompactTextString(m) } func (*PeerConf) ProtoMessage() {} -func (*PeerConf) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{110} } +func (*PeerConf) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{122} } func (m *PeerConf) GetAuthPassword() string { if m != nil { @@ -3094,14 +3569,14 @@ return 0 } -func (m *PeerConf) GetRemoteCap() [][]byte { +func (m *PeerConf) GetRemoteCap() []*google_protobuf.Any { if m != nil { return m.RemoteCap } return nil } -func (m *PeerConf) GetLocalCap() [][]byte { +func (m *PeerConf) GetLocalCap() []*google_protobuf.Any { if m != nil { return m.LocalCap } @@ -3157,6 +3632,182 @@ return false } +type PeerGroupConf struct { + AuthPassword string `protobuf:"bytes,1,opt,name=auth_password,json=authPassword" json:"auth_password,omitempty"` + Description string `protobuf:"bytes,2,opt,name=description" json:"description,omitempty"` + LocalAs uint32 `protobuf:"varint,3,opt,name=local_as,json=localAs" json:"local_as,omitempty"` + PeerAs uint32 `protobuf:"varint,5,opt,name=peer_as,json=peerAs" json:"peer_as,omitempty"` + PeerGroupName string `protobuf:"bytes,6,opt,name=peer_group_name,json=peerGroupName" json:"peer_group_name,omitempty"` + PeerType uint32 `protobuf:"varint,7,opt,name=peer_type,json=peerType" json:"peer_type,omitempty"` + RemovePrivateAs PeerGroupConf_RemovePrivateAs `protobuf:"varint,8,opt,name=remove_private_as,json=removePrivateAs,enum=gobgpapi.PeerGroupConf_RemovePrivateAs" json:"remove_private_as,omitempty"` + RouteFlapDamping bool `protobuf:"varint,9,opt,name=route_flap_damping,json=routeFlapDamping" json:"route_flap_damping,omitempty"` + SendCommunity uint32 `protobuf:"varint,10,opt,name=send_community,json=sendCommunity" json:"send_community,omitempty"` +} + +func (m *PeerGroupConf) Reset() { *m = PeerGroupConf{} } +func (m *PeerGroupConf) String() string { return proto.CompactTextString(m) } +func (*PeerGroupConf) ProtoMessage() {} +func (*PeerGroupConf) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{123} } + +func (m *PeerGroupConf) GetAuthPassword() string { + if m != nil { + return m.AuthPassword + } + return "" +} + +func (m *PeerGroupConf) GetDescription() string { + if m != nil { + return m.Description + } + return "" +} + +func (m *PeerGroupConf) GetLocalAs() uint32 { + if m != nil { + return m.LocalAs + } + return 0 +} + +func (m *PeerGroupConf) GetPeerAs() uint32 { + if m != nil { + return m.PeerAs + } + return 0 +} + +func (m *PeerGroupConf) GetPeerGroupName() string { + if m != nil { + return m.PeerGroupName + } + return "" +} + +func (m *PeerGroupConf) GetPeerType() uint32 { + if m != nil { + return m.PeerType + } + return 0 +} + +func (m *PeerGroupConf) GetRemovePrivateAs() PeerGroupConf_RemovePrivateAs { + if m != nil { + return m.RemovePrivateAs + } + return PeerGroupConf_NONE +} + +func (m *PeerGroupConf) GetRouteFlapDamping() bool { + if m != nil { + return m.RouteFlapDamping + } + return false +} + +func (m *PeerGroupConf) GetSendCommunity() uint32 { + if m != nil { + return m.SendCommunity + } + return 0 +} + +type PeerGroupState struct { + AuthPassword string `protobuf:"bytes,1,opt,name=auth_password,json=authPassword" json:"auth_password,omitempty"` + Description string `protobuf:"bytes,2,opt,name=description" json:"description,omitempty"` + LocalAs uint32 `protobuf:"varint,3,opt,name=local_as,json=localAs" json:"local_as,omitempty"` + PeerAs uint32 `protobuf:"varint,5,opt,name=peer_as,json=peerAs" json:"peer_as,omitempty"` + PeerGroupName string `protobuf:"bytes,6,opt,name=peer_group_name,json=peerGroupName" json:"peer_group_name,omitempty"` + PeerType uint32 `protobuf:"varint,7,opt,name=peer_type,json=peerType" json:"peer_type,omitempty"` + RemovePrivateAs PeerGroupState_RemovePrivateAs `protobuf:"varint,8,opt,name=remove_private_as,json=removePrivateAs,enum=gobgpapi.PeerGroupState_RemovePrivateAs" json:"remove_private_as,omitempty"` + RouteFlapDamping bool `protobuf:"varint,9,opt,name=route_flap_damping,json=routeFlapDamping" json:"route_flap_damping,omitempty"` + SendCommunity uint32 `protobuf:"varint,10,opt,name=send_community,json=sendCommunity" json:"send_community,omitempty"` + TotalPaths uint32 `protobuf:"varint,11,opt,name=total_paths,json=totalPaths" json:"total_paths,omitempty"` + TotalPrefixes uint32 `protobuf:"varint,12,opt,name=total_prefixes,json=totalPrefixes" json:"total_prefixes,omitempty"` +} + +func (m *PeerGroupState) Reset() { *m = PeerGroupState{} } +func (m *PeerGroupState) String() string { return proto.CompactTextString(m) } +func (*PeerGroupState) ProtoMessage() {} +func (*PeerGroupState) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{124} } + +func (m *PeerGroupState) GetAuthPassword() string { + if m != nil { + return m.AuthPassword + } + return "" +} + +func (m *PeerGroupState) GetDescription() string { + if m != nil { + return m.Description + } + return "" +} + +func (m *PeerGroupState) GetLocalAs() uint32 { + if m != nil { + return m.LocalAs + } + return 0 +} + +func (m *PeerGroupState) GetPeerAs() uint32 { + if m != nil { + return m.PeerAs + } + return 0 +} + +func (m *PeerGroupState) GetPeerGroupName() string { + if m != nil { + return m.PeerGroupName + } + return "" +} + +func (m *PeerGroupState) GetPeerType() uint32 { + if m != nil { + return m.PeerType + } + return 0 +} + +func (m *PeerGroupState) GetRemovePrivateAs() PeerGroupState_RemovePrivateAs { + if m != nil { + return m.RemovePrivateAs + } + return PeerGroupState_NONE +} + +func (m *PeerGroupState) GetRouteFlapDamping() bool { + if m != nil { + return m.RouteFlapDamping + } + return false +} + +func (m *PeerGroupState) GetSendCommunity() uint32 { + if m != nil { + return m.SendCommunity + } + return 0 +} + +func (m *PeerGroupState) GetTotalPaths() uint32 { + if m != nil { + return m.TotalPaths + } + return 0 +} + +func (m *PeerGroupState) GetTotalPrefixes() uint32 { + if m != nil { + return m.TotalPrefixes + } + return 0 +} + type EbgpMultihop struct { Enabled bool `protobuf:"varint,1,opt,name=enabled" json:"enabled,omitempty"` MultihopTtl uint32 `protobuf:"varint,2,opt,name=multihop_ttl,json=multihopTtl" json:"multihop_ttl,omitempty"` @@ -3165,7 +3816,7 @@ func (m *EbgpMultihop) Reset() { *m = EbgpMultihop{} } func (m *EbgpMultihop) String() string { return proto.CompactTextString(m) } func (*EbgpMultihop) ProtoMessage() {} -func (*EbgpMultihop) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{111} } +func (*EbgpMultihop) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{125} } func (m *EbgpMultihop) GetEnabled() bool { if m != nil { @@ -3189,7 +3840,7 @@ func (m *RouteReflector) Reset() { *m = RouteReflector{} } func (m *RouteReflector) String() string { return proto.CompactTextString(m) } func (*RouteReflector) ProtoMessage() {} -func (*RouteReflector) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{112} } +func (*RouteReflector) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{126} } func (m *RouteReflector) GetRouteReflectorClient() bool { if m != nil { @@ -3232,7 +3883,7 @@ func (m *PeerState) Reset() { *m = PeerState{} } func (m *PeerState) String() string { return proto.CompactTextString(m) } func (*PeerState) ProtoMessage() {} -func (*PeerState) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{113} } +func (*PeerState) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{127} } func (m *PeerState) GetAuthPassword() string { if m != nil { @@ -3389,7 +4040,7 @@ func (m *Messages) Reset() { *m = Messages{} } func (m *Messages) String() string { return proto.CompactTextString(m) } func (*Messages) ProtoMessage() {} -func (*Messages) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{114} } +func (*Messages) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{128} } func (m *Messages) GetReceived() *Message { if m != nil { @@ -3418,7 +4069,7 @@ func (m *Message) Reset() { *m = Message{} } func (m *Message) String() string { return proto.CompactTextString(m) } func (*Message) ProtoMessage() {} -func (*Message) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{115} } +func (*Message) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{129} } func (m *Message) GetNOTIFICATION() uint64 { if m != nil { @@ -3477,7 +4128,7 @@ func (m *Queues) Reset() { *m = Queues{} } func (m *Queues) String() string { return proto.CompactTextString(m) } func (*Queues) ProtoMessage() {} -func (*Queues) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{116} } +func (*Queues) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{130} } func (m *Queues) GetInput() uint32 { if m != nil { @@ -3501,7 +4152,7 @@ func (m *Timers) Reset() { *m = Timers{} } func (m *Timers) String() string { return proto.CompactTextString(m) } func (*Timers) ProtoMessage() {} -func (*Timers) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{117} } +func (*Timers) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{131} } func (m *Timers) GetConfig() *TimersConfig { if m != nil { @@ -3527,7 +4178,7 @@ func (m *TimersConfig) Reset() { *m = TimersConfig{} } func (m *TimersConfig) String() string { return proto.CompactTextString(m) } func (*TimersConfig) ProtoMessage() {} -func (*TimersConfig) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{118} } +func (*TimersConfig) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{132} } func (m *TimersConfig) GetConnectRetry() uint64 { if m != nil { @@ -3570,7 +4221,7 @@ func (m *TimersState) Reset() { *m = TimersState{} } func (m *TimersState) String() string { return proto.CompactTextString(m) } func (*TimersState) ProtoMessage() {} -func (*TimersState) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{119} } +func (*TimersState) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{133} } func (m *TimersState) GetConnectRetry() uint64 { if m != nil { @@ -3634,7 +4285,7 @@ func (m *Transport) Reset() { *m = Transport{} } func (m *Transport) String() string { return proto.CompactTextString(m) } func (*Transport) ProtoMessage() {} -func (*Transport) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{120} } +func (*Transport) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{134} } func (m *Transport) GetLocalAddress() string { if m != nil { @@ -3692,7 +4343,7 @@ func (m *RouteServer) Reset() { *m = RouteServer{} } func (m *RouteServer) String() string { return proto.CompactTextString(m) } func (*RouteServer) ProtoMessage() {} -func (*RouteServer) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{121} } +func (*RouteServer) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{135} } func (m *RouteServer) GetRouteServerClient() bool { if m != nil { @@ -3708,12 +4359,17 @@ DeferralTime uint32 `protobuf:"varint,4,opt,name=deferral_time,json=deferralTime" json:"deferral_time,omitempty"` NotificationEnabled bool `protobuf:"varint,5,opt,name=notification_enabled,json=notificationEnabled" json:"notification_enabled,omitempty"` LonglivedEnabled bool `protobuf:"varint,6,opt,name=longlived_enabled,json=longlivedEnabled" json:"longlived_enabled,omitempty"` + StaleRoutesTime uint32 `protobuf:"varint,7,opt,name=stale_routes_time,json=staleRoutesTime" json:"stale_routes_time,omitempty"` + PeerRestartTime uint32 `protobuf:"varint,8,opt,name=peer_restart_time,json=peerRestartTime" json:"peer_restart_time,omitempty"` + PeerRestarting bool `protobuf:"varint,9,opt,name=peer_restarting,json=peerRestarting" json:"peer_restarting,omitempty"` + LocalRestarting bool `protobuf:"varint,10,opt,name=local_restarting,json=localRestarting" json:"local_restarting,omitempty"` + Mode string `protobuf:"bytes,11,opt,name=mode" json:"mode,omitempty"` } func (m *GracefulRestart) Reset() { *m = GracefulRestart{} } func (m *GracefulRestart) String() string { return proto.CompactTextString(m) } func (*GracefulRestart) ProtoMessage() {} -func (*GracefulRestart) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{122} } +func (*GracefulRestart) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{136} } func (m *GracefulRestart) GetEnabled() bool { if m != nil { @@ -3757,6 +4413,41 @@ return false } +func (m *GracefulRestart) GetStaleRoutesTime() uint32 { + if m != nil { + return m.StaleRoutesTime + } + return 0 +} + +func (m *GracefulRestart) GetPeerRestartTime() uint32 { + if m != nil { + return m.PeerRestartTime + } + return 0 +} + +func (m *GracefulRestart) GetPeerRestarting() bool { + if m != nil { + return m.PeerRestarting + } + return false +} + +func (m *GracefulRestart) GetLocalRestarting() bool { + if m != nil { + return m.LocalRestarting + } + return false +} + +func (m *GracefulRestart) GetMode() string { + if m != nil { + return m.Mode + } + return "" +} + type MpGracefulRestartConfig struct { Enabled bool `protobuf:"varint,1,opt,name=enabled" json:"enabled,omitempty"` } @@ -3764,7 +4455,7 @@ func (m *MpGracefulRestartConfig) Reset() { *m = MpGracefulRestartConfig{} } func (m *MpGracefulRestartConfig) String() string { return proto.CompactTextString(m) } func (*MpGracefulRestartConfig) ProtoMessage() {} -func (*MpGracefulRestartConfig) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{123} } +func (*MpGracefulRestartConfig) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{137} } func (m *MpGracefulRestartConfig) GetEnabled() bool { if m != nil { @@ -3784,7 +4475,7 @@ func (m *MpGracefulRestartState) Reset() { *m = MpGracefulRestartState{} } func (m *MpGracefulRestartState) String() string { return proto.CompactTextString(m) } func (*MpGracefulRestartState) ProtoMessage() {} -func (*MpGracefulRestartState) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{124} } +func (*MpGracefulRestartState) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{138} } func (m *MpGracefulRestartState) GetEnabled() bool { if m != nil { @@ -3829,7 +4520,7 @@ func (m *MpGracefulRestart) Reset() { *m = MpGracefulRestart{} } func (m *MpGracefulRestart) String() string { return proto.CompactTextString(m) } func (*MpGracefulRestart) ProtoMessage() {} -func (*MpGracefulRestart) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{125} } +func (*MpGracefulRestart) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{139} } func (m *MpGracefulRestart) GetConfig() *MpGracefulRestartConfig { if m != nil { @@ -3853,7 +4544,7 @@ func (m *AfiSafiConfig) Reset() { *m = AfiSafiConfig{} } func (m *AfiSafiConfig) String() string { return proto.CompactTextString(m) } func (*AfiSafiConfig) ProtoMessage() {} -func (*AfiSafiConfig) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{126} } +func (*AfiSafiConfig) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{140} } func (m *AfiSafiConfig) GetFamily() uint32 { if m != nil { @@ -3879,7 +4570,7 @@ func (m *AfiSafiState) Reset() { *m = AfiSafiState{} } func (m *AfiSafiState) String() string { return proto.CompactTextString(m) } func (*AfiSafiState) ProtoMessage() {} -func (*AfiSafiState) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{127} } +func (*AfiSafiState) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{141} } func (m *AfiSafiState) GetFamily() uint32 { if m != nil { @@ -3910,18 +4601,19 @@ } type RouteSelectionOptionsConfig struct { - AlwaysCompareMed bool `protobuf:"varint,1,opt,name=always_compare_med,json=alwaysCompareMed" json:"always_compare_med,omitempty"` - IgnoreAsPathLength bool `protobuf:"varint,2,opt,name=ignore_as_path_length,json=ignoreAsPathLength" json:"ignore_as_path_length,omitempty"` - ExternalCompareRouterId bool `protobuf:"varint,3,opt,name=external_compare_router_id,json=externalCompareRouterId" json:"external_compare_router_id,omitempty"` - AdvertiseInactiveRoutes bool `protobuf:"varint,4,opt,name=advertise_inactive_routes,json=advertiseInactiveRoutes" json:"advertise_inactive_routes,omitempty"` - EnableAigp bool `protobuf:"varint,5,opt,name=enable_aigp,json=enableAigp" json:"enable_aigp,omitempty"` - IgnoreNextHopIgpMetric bool `protobuf:"varint,6,opt,name=ignore_next_hop_igp_metric,json=ignoreNextHopIgpMetric" json:"ignore_next_hop_igp_metric,omitempty"` + AlwaysCompareMed bool `protobuf:"varint,1,opt,name=always_compare_med,json=alwaysCompareMed" json:"always_compare_med,omitempty"` + IgnoreAsPathLength bool `protobuf:"varint,2,opt,name=ignore_as_path_length,json=ignoreAsPathLength" json:"ignore_as_path_length,omitempty"` + ExternalCompareRouterId bool `protobuf:"varint,3,opt,name=external_compare_router_id,json=externalCompareRouterId" json:"external_compare_router_id,omitempty"` + AdvertiseInactiveRoutes bool `protobuf:"varint,4,opt,name=advertise_inactive_routes,json=advertiseInactiveRoutes" json:"advertise_inactive_routes,omitempty"` + EnableAigp bool `protobuf:"varint,5,opt,name=enable_aigp,json=enableAigp" json:"enable_aigp,omitempty"` + IgnoreNextHopIgpMetric bool `protobuf:"varint,6,opt,name=ignore_next_hop_igp_metric,json=ignoreNextHopIgpMetric" json:"ignore_next_hop_igp_metric,omitempty"` + DisableBestPathSelection bool `protobuf:"varint,7,opt,name=disable_best_path_selection,json=disableBestPathSelection" json:"disable_best_path_selection,omitempty"` } func (m *RouteSelectionOptionsConfig) Reset() { *m = RouteSelectionOptionsConfig{} } func (m *RouteSelectionOptionsConfig) String() string { return proto.CompactTextString(m) } func (*RouteSelectionOptionsConfig) ProtoMessage() {} -func (*RouteSelectionOptionsConfig) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{128} } +func (*RouteSelectionOptionsConfig) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{142} } func (m *RouteSelectionOptionsConfig) GetAlwaysCompareMed() bool { if m != nil { @@ -3965,19 +4657,27 @@ return false } +func (m *RouteSelectionOptionsConfig) GetDisableBestPathSelection() bool { + if m != nil { + return m.DisableBestPathSelection + } + return false +} + type RouteSelectionOptionsState struct { - AlwaysCompareMed bool `protobuf:"varint,1,opt,name=always_compare_med,json=alwaysCompareMed" json:"always_compare_med,omitempty"` - IgnoreAsPathLength bool `protobuf:"varint,2,opt,name=ignore_as_path_length,json=ignoreAsPathLength" json:"ignore_as_path_length,omitempty"` - ExternalCompareRouterId bool `protobuf:"varint,3,opt,name=external_compare_router_id,json=externalCompareRouterId" json:"external_compare_router_id,omitempty"` - AdvertiseInactiveRoutes bool `protobuf:"varint,4,opt,name=advertise_inactive_routes,json=advertiseInactiveRoutes" json:"advertise_inactive_routes,omitempty"` - EnableAigp bool `protobuf:"varint,5,opt,name=enable_aigp,json=enableAigp" json:"enable_aigp,omitempty"` - IgnoreNextHopIgpMetric bool `protobuf:"varint,6,opt,name=ignore_next_hop_igp_metric,json=ignoreNextHopIgpMetric" json:"ignore_next_hop_igp_metric,omitempty"` + AlwaysCompareMed bool `protobuf:"varint,1,opt,name=always_compare_med,json=alwaysCompareMed" json:"always_compare_med,omitempty"` + IgnoreAsPathLength bool `protobuf:"varint,2,opt,name=ignore_as_path_length,json=ignoreAsPathLength" json:"ignore_as_path_length,omitempty"` + ExternalCompareRouterId bool `protobuf:"varint,3,opt,name=external_compare_router_id,json=externalCompareRouterId" json:"external_compare_router_id,omitempty"` + AdvertiseInactiveRoutes bool `protobuf:"varint,4,opt,name=advertise_inactive_routes,json=advertiseInactiveRoutes" json:"advertise_inactive_routes,omitempty"` + EnableAigp bool `protobuf:"varint,5,opt,name=enable_aigp,json=enableAigp" json:"enable_aigp,omitempty"` + IgnoreNextHopIgpMetric bool `protobuf:"varint,6,opt,name=ignore_next_hop_igp_metric,json=ignoreNextHopIgpMetric" json:"ignore_next_hop_igp_metric,omitempty"` + DisableBestPathSelection bool `protobuf:"varint,7,opt,name=disable_best_path_selection,json=disableBestPathSelection" json:"disable_best_path_selection,omitempty"` } func (m *RouteSelectionOptionsState) Reset() { *m = RouteSelectionOptionsState{} } func (m *RouteSelectionOptionsState) String() string { return proto.CompactTextString(m) } func (*RouteSelectionOptionsState) ProtoMessage() {} -func (*RouteSelectionOptionsState) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{129} } +func (*RouteSelectionOptionsState) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{143} } func (m *RouteSelectionOptionsState) GetAlwaysCompareMed() bool { if m != nil { @@ -4021,6 +4721,13 @@ return false } +func (m *RouteSelectionOptionsState) GetDisableBestPathSelection() bool { + if m != nil { + return m.DisableBestPathSelection + } + return false +} + type RouteSelectionOptions struct { Config *RouteSelectionOptionsConfig `protobuf:"bytes,1,opt,name=config" json:"config,omitempty"` State *RouteSelectionOptionsState `protobuf:"bytes,2,opt,name=state" json:"state,omitempty"` @@ -4029,7 +4736,7 @@ func (m *RouteSelectionOptions) Reset() { *m = RouteSelectionOptions{} } func (m *RouteSelectionOptions) String() string { return proto.CompactTextString(m) } func (*RouteSelectionOptions) ProtoMessage() {} -func (*RouteSelectionOptions) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{130} } +func (*RouteSelectionOptions) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{144} } func (m *RouteSelectionOptions) GetConfig() *RouteSelectionOptionsConfig { if m != nil { @@ -4052,7 +4759,7 @@ func (m *UseMultiplePathsConfig) Reset() { *m = UseMultiplePathsConfig{} } func (m *UseMultiplePathsConfig) String() string { return proto.CompactTextString(m) } func (*UseMultiplePathsConfig) ProtoMessage() {} -func (*UseMultiplePathsConfig) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{131} } +func (*UseMultiplePathsConfig) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{145} } func (m *UseMultiplePathsConfig) GetEnabled() bool { if m != nil { @@ -4068,7 +4775,7 @@ func (m *UseMultiplePathsState) Reset() { *m = UseMultiplePathsState{} } func (m *UseMultiplePathsState) String() string { return proto.CompactTextString(m) } func (*UseMultiplePathsState) ProtoMessage() {} -func (*UseMultiplePathsState) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{132} } +func (*UseMultiplePathsState) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{146} } func (m *UseMultiplePathsState) GetEnabled() bool { if m != nil { @@ -4085,7 +4792,7 @@ func (m *EbgpConfig) Reset() { *m = EbgpConfig{} } func (m *EbgpConfig) String() string { return proto.CompactTextString(m) } func (*EbgpConfig) ProtoMessage() {} -func (*EbgpConfig) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{133} } +func (*EbgpConfig) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{147} } func (m *EbgpConfig) GetAllowMultipleAs() bool { if m != nil { @@ -4109,7 +4816,7 @@ func (m *EbgpState) Reset() { *m = EbgpState{} } func (m *EbgpState) String() string { return proto.CompactTextString(m) } func (*EbgpState) ProtoMessage() {} -func (*EbgpState) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{134} } +func (*EbgpState) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{148} } func (m *EbgpState) GetAllowMultipleAs() bool { if m != nil { @@ -4133,7 +4840,7 @@ func (m *Ebgp) Reset() { *m = Ebgp{} } func (m *Ebgp) String() string { return proto.CompactTextString(m) } func (*Ebgp) ProtoMessage() {} -func (*Ebgp) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{135} } +func (*Ebgp) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{149} } func (m *Ebgp) GetConfig() *EbgpConfig { if m != nil { @@ -4156,7 +4863,7 @@ func (m *IbgpConfig) Reset() { *m = IbgpConfig{} } func (m *IbgpConfig) String() string { return proto.CompactTextString(m) } func (*IbgpConfig) ProtoMessage() {} -func (*IbgpConfig) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{136} } +func (*IbgpConfig) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{150} } func (m *IbgpConfig) GetMaximumPaths() uint32 { if m != nil { @@ -4172,7 +4879,7 @@ func (m *IbgpState) Reset() { *m = IbgpState{} } func (m *IbgpState) String() string { return proto.CompactTextString(m) } func (*IbgpState) ProtoMessage() {} -func (*IbgpState) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{137} } +func (*IbgpState) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{151} } func (m *IbgpState) GetMaximumPaths() uint32 { if m != nil { @@ -4189,7 +4896,7 @@ func (m *Ibgp) Reset() { *m = Ibgp{} } func (m *Ibgp) String() string { return proto.CompactTextString(m) } func (*Ibgp) ProtoMessage() {} -func (*Ibgp) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{138} } +func (*Ibgp) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{152} } func (m *Ibgp) GetConfig() *IbgpConfig { if m != nil { @@ -4215,7 +4922,7 @@ func (m *UseMultiplePaths) Reset() { *m = UseMultiplePaths{} } func (m *UseMultiplePaths) String() string { return proto.CompactTextString(m) } func (*UseMultiplePaths) ProtoMessage() {} -func (*UseMultiplePaths) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{139} } +func (*UseMultiplePaths) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{153} } func (m *UseMultiplePaths) GetConfig() *UseMultiplePathsConfig { if m != nil { @@ -4252,7 +4959,7 @@ func (m *RouteTargetMembershipConfig) Reset() { *m = RouteTargetMembershipConfig{} } func (m *RouteTargetMembershipConfig) String() string { return proto.CompactTextString(m) } func (*RouteTargetMembershipConfig) ProtoMessage() {} -func (*RouteTargetMembershipConfig) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{140} } +func (*RouteTargetMembershipConfig) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{154} } func (m *RouteTargetMembershipConfig) GetDeferralTime() uint32 { if m != nil { @@ -4268,7 +4975,7 @@ func (m *RouteTargetMembershipState) Reset() { *m = RouteTargetMembershipState{} } func (m *RouteTargetMembershipState) String() string { return proto.CompactTextString(m) } func (*RouteTargetMembershipState) ProtoMessage() {} -func (*RouteTargetMembershipState) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{141} } +func (*RouteTargetMembershipState) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{155} } func (m *RouteTargetMembershipState) GetDeferralTime() uint32 { if m != nil { @@ -4285,7 +4992,7 @@ func (m *RouteTargetMembership) Reset() { *m = RouteTargetMembership{} } func (m *RouteTargetMembership) String() string { return proto.CompactTextString(m) } func (*RouteTargetMembership) ProtoMessage() {} -func (*RouteTargetMembership) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{142} } +func (*RouteTargetMembership) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{156} } func (m *RouteTargetMembership) GetConfig() *RouteTargetMembershipConfig { if m != nil { @@ -4310,7 +5017,7 @@ func (m *LongLivedGracefulRestartConfig) String() string { return proto.CompactTextString(m) } func (*LongLivedGracefulRestartConfig) ProtoMessage() {} func (*LongLivedGracefulRestartConfig) Descriptor() ([]byte, []int) { - return fileDescriptor0, []int{143} + return fileDescriptor0, []int{157} } func (m *LongLivedGracefulRestartConfig) GetEnabled() bool { @@ -4338,7 +5045,7 @@ func (m *LongLivedGracefulRestartState) Reset() { *m = LongLivedGracefulRestartState{} } func (m *LongLivedGracefulRestartState) String() string { return proto.CompactTextString(m) } func (*LongLivedGracefulRestartState) ProtoMessage() {} -func (*LongLivedGracefulRestartState) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{144} } +func (*LongLivedGracefulRestartState) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{158} } func (m *LongLivedGracefulRestartState) GetEnabled() bool { if m != nil { @@ -4383,7 +5090,7 @@ func (m *LongLivedGracefulRestart) Reset() { *m = LongLivedGracefulRestart{} } func (m *LongLivedGracefulRestart) String() string { return proto.CompactTextString(m) } func (*LongLivedGracefulRestart) ProtoMessage() {} -func (*LongLivedGracefulRestart) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{145} } +func (*LongLivedGracefulRestart) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{159} } func (m *LongLivedGracefulRestart) GetConfig() *LongLivedGracefulRestartConfig { if m != nil { @@ -4426,7 +5133,7 @@ func (m *AfiSafi) Reset() { *m = AfiSafi{} } func (m *AfiSafi) String() string { return proto.CompactTextString(m) } func (*AfiSafi) ProtoMessage() {} -func (*AfiSafi) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{146} } +func (*AfiSafi) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{160} } func (m *AfiSafi) GetMpGracefulRestart() *MpGracefulRestart { if m != nil { @@ -4499,7 +5206,7 @@ func (m *AddPathsConfig) Reset() { *m = AddPathsConfig{} } func (m *AddPathsConfig) String() string { return proto.CompactTextString(m) } func (*AddPathsConfig) ProtoMessage() {} -func (*AddPathsConfig) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{147} } +func (*AddPathsConfig) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{161} } func (m *AddPathsConfig) GetReceive() bool { if m != nil { @@ -4523,7 +5230,7 @@ func (m *AddPathsState) Reset() { *m = AddPathsState{} } func (m *AddPathsState) String() string { return proto.CompactTextString(m) } func (*AddPathsState) ProtoMessage() {} -func (*AddPathsState) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{148} } +func (*AddPathsState) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{162} } func (m *AddPathsState) GetReceive() bool { if m != nil { @@ -4547,7 +5254,7 @@ func (m *AddPaths) Reset() { *m = AddPaths{} } func (m *AddPaths) String() string { return proto.CompactTextString(m) } func (*AddPaths) ProtoMessage() {} -func (*AddPaths) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{149} } +func (*AddPaths) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{163} } func (m *AddPaths) GetConfig() *AddPathsConfig { if m != nil { @@ -4572,7 +5279,7 @@ func (m *Prefix) Reset() { *m = Prefix{} } func (m *Prefix) String() string { return proto.CompactTextString(m) } func (*Prefix) ProtoMessage() {} -func (*Prefix) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{150} } +func (*Prefix) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{164} } func (m *Prefix) GetIpPrefix() string { if m != nil { @@ -4605,7 +5312,7 @@ func (m *DefinedSet) Reset() { *m = DefinedSet{} } func (m *DefinedSet) String() string { return proto.CompactTextString(m) } func (*DefinedSet) ProtoMessage() {} -func (*DefinedSet) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{151} } +func (*DefinedSet) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{165} } func (m *DefinedSet) GetType() DefinedType { if m != nil { @@ -4643,7 +5350,7 @@ func (m *MatchSet) Reset() { *m = MatchSet{} } func (m *MatchSet) String() string { return proto.CompactTextString(m) } func (*MatchSet) ProtoMessage() {} -func (*MatchSet) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{152} } +func (*MatchSet) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{166} } func (m *MatchSet) GetType() MatchType { if m != nil { @@ -4667,7 +5374,7 @@ func (m *AsPathLength) Reset() { *m = AsPathLength{} } func (m *AsPathLength) String() string { return proto.CompactTextString(m) } func (*AsPathLength) ProtoMessage() {} -func (*AsPathLength) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{153} } +func (*AsPathLength) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{167} } func (m *AsPathLength) GetType() AsPathLengthType { if m != nil { @@ -4693,12 +5400,14 @@ RpkiResult int32 `protobuf:"varint,7,opt,name=rpki_result,json=rpkiResult" json:"rpki_result,omitempty"` RouteType Conditions_RouteType `protobuf:"varint,8,opt,name=route_type,json=routeType,enum=gobgpapi.Conditions_RouteType" json:"route_type,omitempty"` LargeCommunitySet *MatchSet `protobuf:"bytes,9,opt,name=large_community_set,json=largeCommunitySet" json:"large_community_set,omitempty"` + NextHopInList []string `protobuf:"bytes,10,rep,name=next_hop_in_list,json=nextHopInList" json:"next_hop_in_list,omitempty"` + AfiSafiIn []Family `protobuf:"varint,11,rep,packed,name=afi_safi_in,json=afiSafiIn,enum=gobgpapi.Family" json:"afi_safi_in,omitempty"` } func (m *Conditions) Reset() { *m = Conditions{} } func (m *Conditions) String() string { return proto.CompactTextString(m) } func (*Conditions) ProtoMessage() {} -func (*Conditions) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{154} } +func (*Conditions) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{168} } func (m *Conditions) GetPrefixSet() *MatchSet { if m != nil { @@ -4749,16 +5458,30 @@ return 0 } -func (m *Conditions) GetRouteType() Conditions_RouteType { +func (m *Conditions) GetRouteType() Conditions_RouteType { + if m != nil { + return m.RouteType + } + return Conditions_ROUTE_TYPE_NONE +} + +func (m *Conditions) GetLargeCommunitySet() *MatchSet { + if m != nil { + return m.LargeCommunitySet + } + return nil +} + +func (m *Conditions) GetNextHopInList() []string { if m != nil { - return m.RouteType + return m.NextHopInList } - return Conditions_ROUTE_TYPE_NONE + return nil } -func (m *Conditions) GetLargeCommunitySet() *MatchSet { +func (m *Conditions) GetAfiSafiIn() []Family { if m != nil { - return m.LargeCommunitySet + return m.AfiSafiIn } return nil } @@ -4771,7 +5494,7 @@ func (m *CommunityAction) Reset() { *m = CommunityAction{} } func (m *CommunityAction) String() string { return proto.CompactTextString(m) } func (*CommunityAction) ProtoMessage() {} -func (*CommunityAction) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{155} } +func (*CommunityAction) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{169} } func (m *CommunityAction) GetType() CommunityActionType { if m != nil { @@ -4795,7 +5518,7 @@ func (m *MedAction) Reset() { *m = MedAction{} } func (m *MedAction) String() string { return proto.CompactTextString(m) } func (*MedAction) ProtoMessage() {} -func (*MedAction) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{156} } +func (*MedAction) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{170} } func (m *MedAction) GetType() MedActionType { if m != nil { @@ -4820,7 +5543,7 @@ func (m *AsPrependAction) Reset() { *m = AsPrependAction{} } func (m *AsPrependAction) String() string { return proto.CompactTextString(m) } func (*AsPrependAction) ProtoMessage() {} -func (*AsPrependAction) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{157} } +func (*AsPrependAction) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{171} } func (m *AsPrependAction) GetAsn() uint32 { if m != nil { @@ -4851,7 +5574,7 @@ func (m *NexthopAction) Reset() { *m = NexthopAction{} } func (m *NexthopAction) String() string { return proto.CompactTextString(m) } func (*NexthopAction) ProtoMessage() {} -func (*NexthopAction) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{158} } +func (*NexthopAction) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{172} } func (m *NexthopAction) GetAddress() string { if m != nil { @@ -4874,7 +5597,7 @@ func (m *LocalPrefAction) Reset() { *m = LocalPrefAction{} } func (m *LocalPrefAction) String() string { return proto.CompactTextString(m) } func (*LocalPrefAction) ProtoMessage() {} -func (*LocalPrefAction) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{159} } +func (*LocalPrefAction) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{173} } func (m *LocalPrefAction) GetValue() uint32 { if m != nil { @@ -4897,7 +5620,7 @@ func (m *Actions) Reset() { *m = Actions{} } func (m *Actions) String() string { return proto.CompactTextString(m) } func (*Actions) ProtoMessage() {} -func (*Actions) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{160} } +func (*Actions) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{174} } func (m *Actions) GetRouteAction() RouteAction { if m != nil { @@ -4964,7 +5687,7 @@ func (m *Statement) Reset() { *m = Statement{} } func (m *Statement) String() string { return proto.CompactTextString(m) } func (*Statement) ProtoMessage() {} -func (*Statement) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{161} } +func (*Statement) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{175} } func (m *Statement) GetName() string { if m != nil { @@ -4995,7 +5718,7 @@ func (m *Policy) Reset() { *m = Policy{} } func (m *Policy) String() string { return proto.CompactTextString(m) } func (*Policy) ProtoMessage() {} -func (*Policy) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{162} } +func (*Policy) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{176} } func (m *Policy) GetName() string { if m != nil { @@ -5022,7 +5745,7 @@ func (m *PolicyAssignment) Reset() { *m = PolicyAssignment{} } func (m *PolicyAssignment) String() string { return proto.CompactTextString(m) } func (*PolicyAssignment) ProtoMessage() {} -func (*PolicyAssignment) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{163} } +func (*PolicyAssignment) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{177} } func (m *PolicyAssignment) GetType() PolicyType { if m != nil { @@ -5059,6 +5782,30 @@ return RouteAction_NONE } +type RoutingPolicy struct { + DefinedSet []*DefinedSet `protobuf:"bytes,1,rep,name=defined_set,json=definedSet" json:"defined_set,omitempty"` + PolicyDefinition []*Policy `protobuf:"bytes,2,rep,name=policy_definition,json=policyDefinition" json:"policy_definition,omitempty"` +} + +func (m *RoutingPolicy) Reset() { *m = RoutingPolicy{} } +func (m *RoutingPolicy) String() string { return proto.CompactTextString(m) } +func (*RoutingPolicy) ProtoMessage() {} +func (*RoutingPolicy) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{178} } + +func (m *RoutingPolicy) GetDefinedSet() []*DefinedSet { + if m != nil { + return m.DefinedSet + } + return nil +} + +func (m *RoutingPolicy) GetPolicyDefinition() []*Policy { + if m != nil { + return m.PolicyDefinition + } + return nil +} + type Roa struct { As uint32 `protobuf:"varint,1,opt,name=as" json:"as,omitempty"` Prefixlen uint32 `protobuf:"varint,2,opt,name=prefixlen" json:"prefixlen,omitempty"` @@ -5070,7 +5817,7 @@ func (m *Roa) Reset() { *m = Roa{} } func (m *Roa) String() string { return proto.CompactTextString(m) } func (*Roa) ProtoMessage() {} -func (*Roa) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{164} } +func (*Roa) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{179} } func (m *Roa) GetAs() uint32 { if m != nil { @@ -5114,7 +5861,7 @@ func (m *GetRoaRequest) Reset() { *m = GetRoaRequest{} } func (m *GetRoaRequest) String() string { return proto.CompactTextString(m) } func (*GetRoaRequest) ProtoMessage() {} -func (*GetRoaRequest) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{165} } +func (*GetRoaRequest) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{180} } func (m *GetRoaRequest) GetFamily() uint32 { if m != nil { @@ -5130,7 +5877,7 @@ func (m *GetRoaResponse) Reset() { *m = GetRoaResponse{} } func (m *GetRoaResponse) String() string { return proto.CompactTextString(m) } func (*GetRoaResponse) ProtoMessage() {} -func (*GetRoaResponse) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{166} } +func (*GetRoaResponse) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{181} } func (m *GetRoaResponse) GetRoas() []*Roa { if m != nil { @@ -5140,17 +5887,29 @@ } type Vrf struct { - Name string `protobuf:"bytes,1,opt,name=name" json:"name,omitempty"` - Rd []byte `protobuf:"bytes,2,opt,name=rd,proto3" json:"rd,omitempty"` - ImportRt [][]byte `protobuf:"bytes,3,rep,name=import_rt,json=importRt,proto3" json:"import_rt,omitempty"` - ExportRt [][]byte `protobuf:"bytes,4,rep,name=export_rt,json=exportRt,proto3" json:"export_rt,omitempty"` - Id uint32 `protobuf:"varint,5,opt,name=id" json:"id,omitempty"` + Name string `protobuf:"bytes,1,opt,name=name" json:"name,omitempty"` + // Route Distinguisher must be one of + // RouteDistinguisherTwoOctetAS, + // RouteDistinguisherIPAddressAS, + // or RouteDistinguisherFourOctetAS. + Rd *google_protobuf.Any `protobuf:"bytes,2,opt,name=rd" json:"rd,omitempty"` + // List of the Import Route Targets. Each must be one of + // TwoOctetAsSpecificExtended, + // IPv4AddressSpecificExtended, + // or FourOctetAsSpecificExtended. + ImportRt []*google_protobuf.Any `protobuf:"bytes,3,rep,name=import_rt,json=importRt" json:"import_rt,omitempty"` + // List of the Export Route Targets. Each must be one of + // TwoOctetAsSpecificExtended, + // IPv4AddressSpecificExtended, + // or FourOctetAsSpecificExtended. + ExportRt []*google_protobuf.Any `protobuf:"bytes,4,rep,name=export_rt,json=exportRt" json:"export_rt,omitempty"` + Id uint32 `protobuf:"varint,5,opt,name=id" json:"id,omitempty"` } func (m *Vrf) Reset() { *m = Vrf{} } func (m *Vrf) String() string { return proto.CompactTextString(m) } func (*Vrf) ProtoMessage() {} -func (*Vrf) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{167} } +func (*Vrf) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{182} } func (m *Vrf) GetName() string { if m != nil { @@ -5159,21 +5918,21 @@ return "" } -func (m *Vrf) GetRd() []byte { +func (m *Vrf) GetRd() *google_protobuf.Any { if m != nil { return m.Rd } return nil } -func (m *Vrf) GetImportRt() [][]byte { +func (m *Vrf) GetImportRt() []*google_protobuf.Any { if m != nil { return m.ImportRt } return nil } -func (m *Vrf) GetExportRt() [][]byte { +func (m *Vrf) GetExportRt() []*google_protobuf.Any { if m != nil { return m.ExportRt } @@ -5187,19 +5946,48 @@ return 0 } +type DefaultRouteDistance struct { + ExternalRouteDistance uint32 `protobuf:"varint,1,opt,name=external_route_distance,json=externalRouteDistance" json:"external_route_distance,omitempty"` + InternalRouteDistance uint32 `protobuf:"varint,2,opt,name=internal_route_distance,json=internalRouteDistance" json:"internal_route_distance,omitempty"` +} + +func (m *DefaultRouteDistance) Reset() { *m = DefaultRouteDistance{} } +func (m *DefaultRouteDistance) String() string { return proto.CompactTextString(m) } +func (*DefaultRouteDistance) ProtoMessage() {} +func (*DefaultRouteDistance) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{183} } + +func (m *DefaultRouteDistance) GetExternalRouteDistance() uint32 { + if m != nil { + return m.ExternalRouteDistance + } + return 0 +} + +func (m *DefaultRouteDistance) GetInternalRouteDistance() uint32 { + if m != nil { + return m.InternalRouteDistance + } + return 0 +} + type Global struct { - As uint32 `protobuf:"varint,1,opt,name=as" json:"as,omitempty"` - RouterId string `protobuf:"bytes,2,opt,name=router_id,json=routerId" json:"router_id,omitempty"` - ListenPort int32 `protobuf:"varint,3,opt,name=listen_port,json=listenPort" json:"listen_port,omitempty"` - ListenAddresses []string `protobuf:"bytes,4,rep,name=listen_addresses,json=listenAddresses" json:"listen_addresses,omitempty"` - Families []uint32 `protobuf:"varint,5,rep,packed,name=families" json:"families,omitempty"` - UseMultiplePaths bool `protobuf:"varint,6,opt,name=use_multiple_paths,json=useMultiplePaths" json:"use_multiple_paths,omitempty"` + As uint32 `protobuf:"varint,1,opt,name=as" json:"as,omitempty"` + RouterId string `protobuf:"bytes,2,opt,name=router_id,json=routerId" json:"router_id,omitempty"` + ListenPort int32 `protobuf:"varint,3,opt,name=listen_port,json=listenPort" json:"listen_port,omitempty"` + ListenAddresses []string `protobuf:"bytes,4,rep,name=listen_addresses,json=listenAddresses" json:"listen_addresses,omitempty"` + Families []uint32 `protobuf:"varint,5,rep,packed,name=families" json:"families,omitempty"` + UseMultiplePaths bool `protobuf:"varint,6,opt,name=use_multiple_paths,json=useMultiplePaths" json:"use_multiple_paths,omitempty"` + RouteSelectionOptions *RouteSelectionOptionsConfig `protobuf:"bytes,7,opt,name=route_selection_options,json=routeSelectionOptions" json:"route_selection_options,omitempty"` + DefaultRouteDistance *DefaultRouteDistance `protobuf:"bytes,8,opt,name=default_route_distance,json=defaultRouteDistance" json:"default_route_distance,omitempty"` + Confederation *Confederation `protobuf:"bytes,9,opt,name=confederation" json:"confederation,omitempty"` + GracefulRestart *GracefulRestart `protobuf:"bytes,10,opt,name=graceful_restart,json=gracefulRestart" json:"graceful_restart,omitempty"` + ApplyPolicy *ApplyPolicy `protobuf:"bytes,11,opt,name=apply_policy,json=applyPolicy" json:"apply_policy,omitempty"` } func (m *Global) Reset() { *m = Global{} } func (m *Global) String() string { return proto.CompactTextString(m) } func (*Global) ProtoMessage() {} -func (*Global) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{168} } +func (*Global) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{184} } func (m *Global) GetAs() uint32 { if m != nil { @@ -5243,6 +6031,73 @@ return false } +func (m *Global) GetRouteSelectionOptions() *RouteSelectionOptionsConfig { + if m != nil { + return m.RouteSelectionOptions + } + return nil +} + +func (m *Global) GetDefaultRouteDistance() *DefaultRouteDistance { + if m != nil { + return m.DefaultRouteDistance + } + return nil +} + +func (m *Global) GetConfederation() *Confederation { + if m != nil { + return m.Confederation + } + return nil +} + +func (m *Global) GetGracefulRestart() *GracefulRestart { + if m != nil { + return m.GracefulRestart + } + return nil +} + +func (m *Global) GetApplyPolicy() *ApplyPolicy { + if m != nil { + return m.ApplyPolicy + } + return nil +} + +type Confederation struct { + Enabled bool `protobuf:"varint,1,opt,name=enabled" json:"enabled,omitempty"` + Identifier uint32 `protobuf:"varint,2,opt,name=identifier" json:"identifier,omitempty"` + MemberAsList []uint32 `protobuf:"varint,3,rep,packed,name=member_as_list,json=memberAsList" json:"member_as_list,omitempty"` +} + +func (m *Confederation) Reset() { *m = Confederation{} } +func (m *Confederation) String() string { return proto.CompactTextString(m) } +func (*Confederation) ProtoMessage() {} +func (*Confederation) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{185} } + +func (m *Confederation) GetEnabled() bool { + if m != nil { + return m.Enabled + } + return false +} + +func (m *Confederation) GetIdentifier() uint32 { + if m != nil { + return m.Identifier + } + return 0 +} + +func (m *Confederation) GetMemberAsList() []uint32 { + if m != nil { + return m.MemberAsList + } + return nil +} + type TableInfo struct { Type Resource `protobuf:"varint,1,opt,name=type,enum=gobgpapi.Resource" json:"type,omitempty"` Name string `protobuf:"bytes,2,opt,name=name" json:"name,omitempty"` @@ -5255,7 +6110,7 @@ func (m *TableInfo) Reset() { *m = TableInfo{} } func (m *TableInfo) String() string { return proto.CompactTextString(m) } func (*TableInfo) ProtoMessage() {} -func (*TableInfo) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{169} } +func (*TableInfo) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{186} } func (m *TableInfo) GetType() Resource { if m != nil { @@ -5306,7 +6161,7 @@ func (m *GetRibInfoRequest) Reset() { *m = GetRibInfoRequest{} } func (m *GetRibInfoRequest) String() string { return proto.CompactTextString(m) } func (*GetRibInfoRequest) ProtoMessage() {} -func (*GetRibInfoRequest) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{170} } +func (*GetRibInfoRequest) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{187} } func (m *GetRibInfoRequest) GetInfo() *TableInfo { if m != nil { @@ -5322,7 +6177,7 @@ func (m *GetRibInfoResponse) Reset() { *m = GetRibInfoResponse{} } func (m *GetRibInfoResponse) String() string { return proto.CompactTextString(m) } func (*GetRibInfoResponse) ProtoMessage() {} -func (*GetRibInfoResponse) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{171} } +func (*GetRibInfoResponse) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{188} } func (m *GetRibInfoResponse) GetInfo() *TableInfo { if m != nil { @@ -5331,6 +6186,62 @@ return nil } +type AddCollectorRequest struct { + Url string `protobuf:"bytes,1,opt,name=url" json:"url,omitempty"` + DbName string `protobuf:"bytes,2,opt,name=db_name,json=dbName" json:"db_name,omitempty"` + TableDumpInterval uint64 `protobuf:"varint,3,opt,name=table_dump_interval,json=tableDumpInterval" json:"table_dump_interval,omitempty"` +} + +func (m *AddCollectorRequest) Reset() { *m = AddCollectorRequest{} } +func (m *AddCollectorRequest) String() string { return proto.CompactTextString(m) } +func (*AddCollectorRequest) ProtoMessage() {} +func (*AddCollectorRequest) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{189} } + +func (m *AddCollectorRequest) GetUrl() string { + if m != nil { + return m.Url + } + return "" +} + +func (m *AddCollectorRequest) GetDbName() string { + if m != nil { + return m.DbName + } + return "" +} + +func (m *AddCollectorRequest) GetTableDumpInterval() uint64 { + if m != nil { + return m.TableDumpInterval + } + return 0 +} + +type AddCollectorResponse struct { +} + +func (m *AddCollectorResponse) Reset() { *m = AddCollectorResponse{} } +func (m *AddCollectorResponse) String() string { return proto.CompactTextString(m) } +func (*AddCollectorResponse) ProtoMessage() {} +func (*AddCollectorResponse) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{190} } + +type ShutdownRequest struct { +} + +func (m *ShutdownRequest) Reset() { *m = ShutdownRequest{} } +func (m *ShutdownRequest) String() string { return proto.CompactTextString(m) } +func (*ShutdownRequest) ProtoMessage() {} +func (*ShutdownRequest) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{191} } + +type ShutdownResponse struct { +} + +func (m *ShutdownResponse) Reset() { *m = ShutdownResponse{} } +func (m *ShutdownResponse) String() string { return proto.CompactTextString(m) } +func (*ShutdownResponse) ProtoMessage() {} +func (*ShutdownResponse) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{192} } + func init() { proto.RegisterType((*GetNeighborRequest)(nil), "gobgpapi.GetNeighborRequest") proto.RegisterType((*GetNeighborResponse)(nil), "gobgpapi.GetNeighborResponse") @@ -5345,6 +6256,14 @@ proto.RegisterType((*DeleteNeighborResponse)(nil), "gobgpapi.DeleteNeighborResponse") proto.RegisterType((*UpdateNeighborRequest)(nil), "gobgpapi.UpdateNeighborRequest") proto.RegisterType((*UpdateNeighborResponse)(nil), "gobgpapi.UpdateNeighborResponse") + proto.RegisterType((*AddPeerGroupRequest)(nil), "gobgpapi.AddPeerGroupRequest") + proto.RegisterType((*AddPeerGroupResponse)(nil), "gobgpapi.AddPeerGroupResponse") + proto.RegisterType((*DeletePeerGroupRequest)(nil), "gobgpapi.DeletePeerGroupRequest") + proto.RegisterType((*DeletePeerGroupResponse)(nil), "gobgpapi.DeletePeerGroupResponse") + proto.RegisterType((*UpdatePeerGroupRequest)(nil), "gobgpapi.UpdatePeerGroupRequest") + proto.RegisterType((*UpdatePeerGroupResponse)(nil), "gobgpapi.UpdatePeerGroupResponse") + proto.RegisterType((*AddDynamicNeighborRequest)(nil), "gobgpapi.AddDynamicNeighborRequest") + proto.RegisterType((*AddDynamicNeighborResponse)(nil), "gobgpapi.AddDynamicNeighborResponse") proto.RegisterType((*ResetNeighborRequest)(nil), "gobgpapi.ResetNeighborRequest") proto.RegisterType((*ResetNeighborResponse)(nil), "gobgpapi.ResetNeighborResponse") proto.RegisterType((*SoftResetNeighborRequest)(nil), "gobgpapi.SoftResetNeighborRequest") @@ -5355,6 +6274,8 @@ proto.RegisterType((*EnableNeighborResponse)(nil), "gobgpapi.EnableNeighborResponse") proto.RegisterType((*DisableNeighborRequest)(nil), "gobgpapi.DisableNeighborRequest") proto.RegisterType((*DisableNeighborResponse)(nil), "gobgpapi.DisableNeighborResponse") + proto.RegisterType((*UpdatePolicyRequest)(nil), "gobgpapi.UpdatePolicyRequest") + proto.RegisterType((*UpdatePolicyResponse)(nil), "gobgpapi.UpdatePolicyResponse") proto.RegisterType((*EnableMrtRequest)(nil), "gobgpapi.EnableMrtRequest") proto.RegisterType((*EnableMrtResponse)(nil), "gobgpapi.EnableMrtResponse") proto.RegisterType((*DisableMrtRequest)(nil), "gobgpapi.DisableMrtRequest") @@ -5440,9 +6361,13 @@ proto.RegisterType((*ValidateRibRequest)(nil), "gobgpapi.ValidateRibRequest") proto.RegisterType((*ValidateRibResponse)(nil), "gobgpapi.ValidateRibResponse") proto.RegisterType((*Peer)(nil), "gobgpapi.Peer") + proto.RegisterType((*PeerGroup)(nil), "gobgpapi.PeerGroup") + proto.RegisterType((*DynamicNeighbor)(nil), "gobgpapi.DynamicNeighbor") proto.RegisterType((*ApplyPolicy)(nil), "gobgpapi.ApplyPolicy") proto.RegisterType((*PrefixLimit)(nil), "gobgpapi.PrefixLimit") proto.RegisterType((*PeerConf)(nil), "gobgpapi.PeerConf") + proto.RegisterType((*PeerGroupConf)(nil), "gobgpapi.PeerGroupConf") + proto.RegisterType((*PeerGroupState)(nil), "gobgpapi.PeerGroupState") proto.RegisterType((*EbgpMultihop)(nil), "gobgpapi.EbgpMultihop") proto.RegisterType((*RouteReflector)(nil), "gobgpapi.RouteReflector") proto.RegisterType((*PeerState)(nil), "gobgpapi.PeerState") @@ -5496,14 +6421,21 @@ proto.RegisterType((*Statement)(nil), "gobgpapi.Statement") proto.RegisterType((*Policy)(nil), "gobgpapi.Policy") proto.RegisterType((*PolicyAssignment)(nil), "gobgpapi.PolicyAssignment") + proto.RegisterType((*RoutingPolicy)(nil), "gobgpapi.RoutingPolicy") proto.RegisterType((*Roa)(nil), "gobgpapi.Roa") proto.RegisterType((*GetRoaRequest)(nil), "gobgpapi.GetRoaRequest") proto.RegisterType((*GetRoaResponse)(nil), "gobgpapi.GetRoaResponse") proto.RegisterType((*Vrf)(nil), "gobgpapi.Vrf") + proto.RegisterType((*DefaultRouteDistance)(nil), "gobgpapi.DefaultRouteDistance") proto.RegisterType((*Global)(nil), "gobgpapi.Global") + proto.RegisterType((*Confederation)(nil), "gobgpapi.Confederation") proto.RegisterType((*TableInfo)(nil), "gobgpapi.TableInfo") proto.RegisterType((*GetRibInfoRequest)(nil), "gobgpapi.GetRibInfoRequest") proto.RegisterType((*GetRibInfoResponse)(nil), "gobgpapi.GetRibInfoResponse") + proto.RegisterType((*AddCollectorRequest)(nil), "gobgpapi.AddCollectorRequest") + proto.RegisterType((*AddCollectorResponse)(nil), "gobgpapi.AddCollectorResponse") + proto.RegisterType((*ShutdownRequest)(nil), "gobgpapi.ShutdownRequest") + proto.RegisterType((*ShutdownResponse)(nil), "gobgpapi.ShutdownResponse") proto.RegisterEnum("gobgpapi.Family", Family_name, Family_value) proto.RegisterEnum("gobgpapi.Resource", Resource_name, Resource_value) proto.RegisterEnum("gobgpapi.TableLookupOption", TableLookupOption_name, TableLookupOption_value) @@ -5519,6 +6451,8 @@ proto.RegisterEnum("gobgpapi.RPKIValidation_State", RPKIValidation_State_name, RPKIValidation_State_value) proto.RegisterEnum("gobgpapi.RPKIValidation_Reason", RPKIValidation_Reason_name, RPKIValidation_Reason_value) proto.RegisterEnum("gobgpapi.PeerConf_RemovePrivateAs", PeerConf_RemovePrivateAs_name, PeerConf_RemovePrivateAs_value) + proto.RegisterEnum("gobgpapi.PeerGroupConf_RemovePrivateAs", PeerGroupConf_RemovePrivateAs_name, PeerGroupConf_RemovePrivateAs_value) + proto.RegisterEnum("gobgpapi.PeerGroupState_RemovePrivateAs", PeerGroupState_RemovePrivateAs_name, PeerGroupState_RemovePrivateAs_value) proto.RegisterEnum("gobgpapi.PeerState_AdminState", PeerState_AdminState_name, PeerState_AdminState_value) proto.RegisterEnum("gobgpapi.Conditions_RouteType", Conditions_RouteType_name, Conditions_RouteType_value) } @@ -5582,11 +6516,18 @@ AddPolicy(ctx context.Context, in *AddPolicyRequest, opts ...grpc.CallOption) (*AddPolicyResponse, error) DeletePolicy(ctx context.Context, in *DeletePolicyRequest, opts ...grpc.CallOption) (*DeletePolicyResponse, error) ReplacePolicy(ctx context.Context, in *ReplacePolicyRequest, opts ...grpc.CallOption) (*ReplacePolicyResponse, error) + UpdatePolicy(ctx context.Context, in *UpdatePolicyRequest, opts ...grpc.CallOption) (*UpdatePolicyResponse, error) GetPolicyAssignment(ctx context.Context, in *GetPolicyAssignmentRequest, opts ...grpc.CallOption) (*GetPolicyAssignmentResponse, error) AddPolicyAssignment(ctx context.Context, in *AddPolicyAssignmentRequest, opts ...grpc.CallOption) (*AddPolicyAssignmentResponse, error) DeletePolicyAssignment(ctx context.Context, in *DeletePolicyAssignmentRequest, opts ...grpc.CallOption) (*DeletePolicyAssignmentResponse, error) ReplacePolicyAssignment(ctx context.Context, in *ReplacePolicyAssignmentRequest, opts ...grpc.CallOption) (*ReplacePolicyAssignmentResponse, error) GetRibInfo(ctx context.Context, in *GetRibInfoRequest, opts ...grpc.CallOption) (*GetRibInfoResponse, error) + AddPeerGroup(ctx context.Context, in *AddPeerGroupRequest, opts ...grpc.CallOption) (*AddPeerGroupResponse, error) + DeletePeerGroup(ctx context.Context, in *DeletePeerGroupRequest, opts ...grpc.CallOption) (*DeletePeerGroupResponse, error) + UpdatePeerGroup(ctx context.Context, in *UpdatePeerGroupRequest, opts ...grpc.CallOption) (*UpdatePeerGroupResponse, error) + AddDynamicNeighbor(ctx context.Context, in *AddDynamicNeighborRequest, opts ...grpc.CallOption) (*AddDynamicNeighborResponse, error) + AddCollector(ctx context.Context, in *AddCollectorRequest, opts ...grpc.CallOption) (*AddCollectorResponse, error) + Shutdown(ctx context.Context, in *ShutdownRequest, opts ...grpc.CallOption) (*ShutdownResponse, error) } type gobgpApiClient struct { @@ -6123,6 +7064,15 @@ return out, nil } +func (c *gobgpApiClient) UpdatePolicy(ctx context.Context, in *UpdatePolicyRequest, opts ...grpc.CallOption) (*UpdatePolicyResponse, error) { + out := new(UpdatePolicyResponse) + err := grpc.Invoke(ctx, "/gobgpapi.GobgpApi/UpdatePolicy", in, out, c.cc, opts...) + if err != nil { + return nil, err + } + return out, nil +} + func (c *gobgpApiClient) GetPolicyAssignment(ctx context.Context, in *GetPolicyAssignmentRequest, opts ...grpc.CallOption) (*GetPolicyAssignmentResponse, error) { out := new(GetPolicyAssignmentResponse) err := grpc.Invoke(ctx, "/gobgpapi.GobgpApi/GetPolicyAssignment", in, out, c.cc, opts...) @@ -6168,6 +7118,60 @@ return out, nil } +func (c *gobgpApiClient) AddPeerGroup(ctx context.Context, in *AddPeerGroupRequest, opts ...grpc.CallOption) (*AddPeerGroupResponse, error) { + out := new(AddPeerGroupResponse) + err := grpc.Invoke(ctx, "/gobgpapi.GobgpApi/AddPeerGroup", in, out, c.cc, opts...) + if err != nil { + return nil, err + } + return out, nil +} + +func (c *gobgpApiClient) DeletePeerGroup(ctx context.Context, in *DeletePeerGroupRequest, opts ...grpc.CallOption) (*DeletePeerGroupResponse, error) { + out := new(DeletePeerGroupResponse) + err := grpc.Invoke(ctx, "/gobgpapi.GobgpApi/DeletePeerGroup", in, out, c.cc, opts...) + if err != nil { + return nil, err + } + return out, nil +} + +func (c *gobgpApiClient) UpdatePeerGroup(ctx context.Context, in *UpdatePeerGroupRequest, opts ...grpc.CallOption) (*UpdatePeerGroupResponse, error) { + out := new(UpdatePeerGroupResponse) + err := grpc.Invoke(ctx, "/gobgpapi.GobgpApi/UpdatePeerGroup", in, out, c.cc, opts...) + if err != nil { + return nil, err + } + return out, nil +} + +func (c *gobgpApiClient) AddDynamicNeighbor(ctx context.Context, in *AddDynamicNeighborRequest, opts ...grpc.CallOption) (*AddDynamicNeighborResponse, error) { + out := new(AddDynamicNeighborResponse) + err := grpc.Invoke(ctx, "/gobgpapi.GobgpApi/AddDynamicNeighbor", in, out, c.cc, opts...) + if err != nil { + return nil, err + } + return out, nil +} + +func (c *gobgpApiClient) AddCollector(ctx context.Context, in *AddCollectorRequest, opts ...grpc.CallOption) (*AddCollectorResponse, error) { + out := new(AddCollectorResponse) + err := grpc.Invoke(ctx, "/gobgpapi.GobgpApi/AddCollector", in, out, c.cc, opts...) + if err != nil { + return nil, err + } + return out, nil +} + +func (c *gobgpApiClient) Shutdown(ctx context.Context, in *ShutdownRequest, opts ...grpc.CallOption) (*ShutdownResponse, error) { + out := new(ShutdownResponse) + err := grpc.Invoke(ctx, "/gobgpapi.GobgpApi/Shutdown", in, out, c.cc, opts...) + if err != nil { + return nil, err + } + return out, nil +} + // Server API for GobgpApi service type GobgpApiServer interface { @@ -6219,11 +7223,18 @@ AddPolicy(context.Context, *AddPolicyRequest) (*AddPolicyResponse, error) DeletePolicy(context.Context, *DeletePolicyRequest) (*DeletePolicyResponse, error) ReplacePolicy(context.Context, *ReplacePolicyRequest) (*ReplacePolicyResponse, error) + UpdatePolicy(context.Context, *UpdatePolicyRequest) (*UpdatePolicyResponse, error) GetPolicyAssignment(context.Context, *GetPolicyAssignmentRequest) (*GetPolicyAssignmentResponse, error) AddPolicyAssignment(context.Context, *AddPolicyAssignmentRequest) (*AddPolicyAssignmentResponse, error) DeletePolicyAssignment(context.Context, *DeletePolicyAssignmentRequest) (*DeletePolicyAssignmentResponse, error) ReplacePolicyAssignment(context.Context, *ReplacePolicyAssignmentRequest) (*ReplacePolicyAssignmentResponse, error) GetRibInfo(context.Context, *GetRibInfoRequest) (*GetRibInfoResponse, error) + AddPeerGroup(context.Context, *AddPeerGroupRequest) (*AddPeerGroupResponse, error) + DeletePeerGroup(context.Context, *DeletePeerGroupRequest) (*DeletePeerGroupResponse, error) + UpdatePeerGroup(context.Context, *UpdatePeerGroupRequest) (*UpdatePeerGroupResponse, error) + AddDynamicNeighbor(context.Context, *AddDynamicNeighborRequest) (*AddDynamicNeighborResponse, error) + AddCollector(context.Context, *AddCollectorRequest) (*AddCollectorResponse, error) + Shutdown(context.Context, *ShutdownRequest) (*ShutdownResponse, error) } func RegisterGobgpApiServer(s *grpc.Server, srv GobgpApiServer) { @@ -7111,6 +8122,24 @@ return interceptor(ctx, in, info, handler) } +func _GobgpApi_UpdatePolicy_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(UpdatePolicyRequest) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(GobgpApiServer).UpdatePolicy(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: "/gobgpapi.GobgpApi/UpdatePolicy", + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(GobgpApiServer).UpdatePolicy(ctx, req.(*UpdatePolicyRequest)) + } + return interceptor(ctx, in, info, handler) +} + func _GobgpApi_GetPolicyAssignment_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { in := new(GetPolicyAssignmentRequest) if err := dec(in); err != nil { @@ -7201,6 +8230,114 @@ return interceptor(ctx, in, info, handler) } +func _GobgpApi_AddPeerGroup_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(AddPeerGroupRequest) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(GobgpApiServer).AddPeerGroup(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: "/gobgpapi.GobgpApi/AddPeerGroup", + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(GobgpApiServer).AddPeerGroup(ctx, req.(*AddPeerGroupRequest)) + } + return interceptor(ctx, in, info, handler) +} + +func _GobgpApi_DeletePeerGroup_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(DeletePeerGroupRequest) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(GobgpApiServer).DeletePeerGroup(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: "/gobgpapi.GobgpApi/DeletePeerGroup", + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(GobgpApiServer).DeletePeerGroup(ctx, req.(*DeletePeerGroupRequest)) + } + return interceptor(ctx, in, info, handler) +} + +func _GobgpApi_UpdatePeerGroup_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(UpdatePeerGroupRequest) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(GobgpApiServer).UpdatePeerGroup(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: "/gobgpapi.GobgpApi/UpdatePeerGroup", + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(GobgpApiServer).UpdatePeerGroup(ctx, req.(*UpdatePeerGroupRequest)) + } + return interceptor(ctx, in, info, handler) +} + +func _GobgpApi_AddDynamicNeighbor_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(AddDynamicNeighborRequest) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(GobgpApiServer).AddDynamicNeighbor(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: "/gobgpapi.GobgpApi/AddDynamicNeighbor", + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(GobgpApiServer).AddDynamicNeighbor(ctx, req.(*AddDynamicNeighborRequest)) + } + return interceptor(ctx, in, info, handler) +} + +func _GobgpApi_AddCollector_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(AddCollectorRequest) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(GobgpApiServer).AddCollector(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: "/gobgpapi.GobgpApi/AddCollector", + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(GobgpApiServer).AddCollector(ctx, req.(*AddCollectorRequest)) + } + return interceptor(ctx, in, info, handler) +} + +func _GobgpApi_Shutdown_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(ShutdownRequest) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(GobgpApiServer).Shutdown(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: "/gobgpapi.GobgpApi/Shutdown", + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(GobgpApiServer).Shutdown(ctx, req.(*ShutdownRequest)) + } + return interceptor(ctx, in, info, handler) +} + var _GobgpApi_serviceDesc = grpc.ServiceDesc{ ServiceName: "gobgpapi.GobgpApi", HandlerType: (*GobgpApiServer)(nil), @@ -7382,6 +8519,10 @@ Handler: _GobgpApi_ReplacePolicy_Handler, }, { + MethodName: "UpdatePolicy", + Handler: _GobgpApi_UpdatePolicy_Handler, + }, + { MethodName: "GetPolicyAssignment", Handler: _GobgpApi_GetPolicyAssignment_Handler, }, @@ -7401,6 +8542,30 @@ MethodName: "GetRibInfo", Handler: _GobgpApi_GetRibInfo_Handler, }, + { + MethodName: "AddPeerGroup", + Handler: _GobgpApi_AddPeerGroup_Handler, + }, + { + MethodName: "DeletePeerGroup", + Handler: _GobgpApi_DeletePeerGroup_Handler, + }, + { + MethodName: "UpdatePeerGroup", + Handler: _GobgpApi_UpdatePeerGroup_Handler, + }, + { + MethodName: "AddDynamicNeighbor", + Handler: _GobgpApi_AddDynamicNeighbor_Handler, + }, + { + MethodName: "AddCollector", + Handler: _GobgpApi_AddCollector_Handler, + }, + { + MethodName: "Shutdown", + Handler: _GobgpApi_Shutdown_Handler, + }, }, Streams: []grpc.StreamDesc{ { @@ -7430,474 +8595,526 @@ func init() { proto.RegisterFile("gobgp.proto", fileDescriptor0) } var fileDescriptor0 = []byte{ - // 7489 bytes of a gzipped FileDescriptorProto - 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x09, 0x6e, 0x88, 0x02, 0xff, 0xec, 0x7d, 0xcd, 0x6f, 0x23, 0x47, - 0x76, 0xb8, 0xf8, 0x21, 0x8a, 0x7c, 0x24, 0xc5, 0x56, 0xe9, 0x8b, 0x23, 0x79, 0xbe, 0x7a, 0x3d, - 0x9e, 0xb1, 0x6c, 0x8f, 0x3d, 0x63, 0x5b, 0xf6, 0x7a, 0xd6, 0x5e, 0x73, 0x24, 0x8e, 0x86, 0x6b, - 0x49, 0xa4, 0x5b, 0x9c, 0xf1, 0x78, 0x7f, 0xbb, 0xbf, 0x4e, 0x8b, 0x5d, 0xa4, 0x3a, 0x6e, 0x76, - 0xb7, 0xbb, 0x9b, 0xb2, 0x06, 0x01, 0x92, 0x99, 0xcd, 0xee, 0x26, 0x40, 0xb0, 0x97, 0x5c, 0x93, - 0x20, 0x87, 0xdc, 0x16, 0xc8, 0x21, 0x40, 0x80, 0x00, 0x39, 0x25, 0x40, 0x76, 0x11, 0x60, 0x81, - 0x5c, 0x92, 0x73, 0xf2, 0x07, 0xe4, 0x90, 0x04, 0xc9, 0x21, 0x87, 0x3d, 0x04, 0xf5, 0xd1, 0xdd, - 0xd5, 0x1f, 0x94, 0x34, 0xb3, 0xe3, 0x04, 0x01, 0x72, 0x12, 0xeb, 0xbd, 0x57, 0xaf, 0x5e, 0x55, - 0xbd, 0x7a, 0xf5, 0xea, 0x55, 0xf5, 0x13, 0x54, 0x47, 0xf6, 0xe1, 0xc8, 0xb9, 0xe9, 0xb8, 0xb6, - 0x6f, 0xa3, 0x32, 0x2d, 0x68, 0x8e, 0x21, 0x7f, 0x17, 0xd0, 0x0e, 0xf6, 0xf7, 0xb1, 0x31, 0x3a, - 0x3a, 0xb4, 0x5d, 0x05, 0x7f, 0x39, 0xc1, 0x9e, 0x8f, 0x36, 0x40, 0xc2, 0x96, 0x76, 0x68, 0xe2, - 0x96, 0x7e, 0x8c, 0x5d, 0xdf, 0xf0, 0xb0, 0xde, 0xcc, 0x5d, 0xc9, 0xdd, 0x28, 0x2b, 0x29, 0x38, - 0x6a, 0xc2, 0x9c, 0xa6, 0xeb, 0x2e, 0xf6, 0xbc, 0x66, 0xfe, 0x4a, 0xee, 0x46, 0x45, 0x09, 0x8a, - 0xf2, 0x1d, 0x58, 0x8c, 0xf1, 0xf6, 0x1c, 0xdb, 0xf2, 0x30, 0x7a, 0x19, 0x66, 0x1d, 0x8c, 0x5d, - 0xaf, 0x99, 0xbb, 0x52, 0xb8, 0x51, 0xbd, 0x3d, 0x7f, 0x33, 0x10, 0xe6, 0x66, 0x0f, 0x63, 0x57, - 0x61, 0x48, 0xf9, 0x69, 0x0e, 0x2a, 0x2d, 0x77, 0x34, 0x19, 0x63, 0xcb, 0xf7, 0xd0, 0x4d, 0x28, - 0xbb, 0xd8, 0xb3, 0x27, 0xee, 0x00, 0x53, 0x41, 0xe6, 0x6f, 0xa3, 0xa8, 0x9a, 0xc2, 0x31, 0x4a, - 0x48, 0x83, 0x56, 0xa0, 0x34, 0xd4, 0xc6, 0x86, 0xf9, 0x98, 0xca, 0x54, 0x57, 0x78, 0x09, 0x21, - 0x28, 0x5a, 0xda, 0x18, 0x37, 0x0b, 0x54, 0x52, 0xfa, 0x9b, 0x74, 0x60, 0x30, 0x71, 0x5d, 0x6c, - 0xf9, 0xcd, 0x22, 0xed, 0x63, 0x50, 0x94, 0x7f, 0x03, 0xe6, 0x5b, 0xba, 0xde, 0xd3, 0xfc, 0xa3, - 0x60, 0x60, 0x9e, 0x55, 0x8e, 0x65, 0x28, 0x1d, 0xbb, 0x43, 0xd5, 0xd0, 0xf9, 0xd8, 0xcc, 0x1e, - 0xbb, 0xc3, 0x8e, 0x8e, 0x64, 0x28, 0x3a, 0x9a, 0x7f, 0x44, 0xc5, 0x88, 0x8f, 0x00, 0x69, 0x8b, - 0xe2, 0xe4, 0x6b, 0xd0, 0x08, 0x1b, 0xe7, 0x23, 0x87, 0xa0, 0x38, 0x99, 0x18, 0x6c, 0x2a, 0x6a, - 0x0a, 0xfd, 0x2d, 0xff, 0x34, 0x07, 0x0b, 0xdb, 0xd8, 0xc4, 0x3e, 0xfe, 0x1a, 0xe4, 0x8c, 0x86, - 0xb1, 0x10, 0x1b, 0xc6, 0x40, 0xfe, 0xe2, 0x74, 0xf9, 0x43, 0x61, 0x67, 0x05, 0x61, 0x97, 0x00, - 0x89, 0xb2, 0xb2, 0x6e, 0xc9, 0xef, 0x03, 0x6a, 0xe9, 0x7a, 0x52, 0x07, 0x49, 0x1b, 0x18, 0xbb, - 0x54, 0xfc, 0xb4, 0x96, 0x50, 0x9c, 0xbc, 0x0c, 0x8b, 0xb1, 0x9a, 0x9c, 0xe1, 0x1d, 0x58, 0x66, - 0xcd, 0x3c, 0x0f, 0xcf, 0x26, 0xac, 0x24, 0x2b, 0x73, 0xb6, 0x3a, 0x2c, 0x3f, 0x70, 0x74, 0xed, - 0xb9, 0xd8, 0xa2, 0xeb, 0x20, 0xe9, 0xb6, 0xea, 0xd9, 0x43, 0x5f, 0x75, 0xb1, 0x87, 0x7d, 0xd5, - 0xb0, 0xe8, 0x58, 0x97, 0x95, 0xba, 0x6e, 0x1f, 0xd8, 0x43, 0x5f, 0x21, 0xd0, 0x8e, 0x25, 0xef, - 0xc0, 0x4a, 0xb2, 0x15, 0x3e, 0xfd, 0x6f, 0xc0, 0xa2, 0x85, 0xb1, 0xee, 0x25, 0xb8, 0xf0, 0x85, - 0x49, 0x51, 0x22, 0xa3, 0x87, 0xb0, 0x44, 0x7f, 0x26, 0xa5, 0x15, 0x16, 0x6c, 0x2e, 0xb6, 0x60, - 0xd1, 0xcb, 0x50, 0x1f, 0xd8, 0xe3, 0xf1, 0xc4, 0x32, 0x06, 0x9a, 0x6f, 0xd8, 0x16, 0x57, 0x86, - 0x38, 0x50, 0x5e, 0x85, 0xe5, 0x04, 0x5f, 0x3e, 0x3e, 0x7f, 0x99, 0x83, 0x66, 0x28, 0xc0, 0xf9, - 0x5b, 0x3d, 0x80, 0x8a, 0x6e, 0xb8, 0x78, 0x10, 0xb6, 0x38, 0x7f, 0xfb, 0xdd, 0x68, 0x08, 0xa7, - 0x31, 0x8c, 0x10, 0xdb, 0x41, 0x65, 0x25, 0xe2, 0x23, 0xbf, 0x09, 0x28, 0x4d, 0x80, 0x4a, 0x90, - 0xef, 0xec, 0x4b, 0x33, 0x68, 0x0e, 0x0a, 0xdd, 0x07, 0x7d, 0x29, 0x87, 0xca, 0x50, 0xbc, 0xdb, - 0xed, 0xdf, 0x97, 0xf2, 0xf2, 0x3a, 0x5c, 0xc8, 0x68, 0x8a, 0xf7, 0xec, 0x73, 0x58, 0x3d, 0x38, - 0x9a, 0xf8, 0xba, 0xfd, 0x95, 0xf5, 0xa2, 0x47, 0x73, 0x0d, 0x9a, 0x69, 0xd6, 0xbc, 0xd9, 0x5b, - 0xb0, 0xdc, 0xa6, 0xe6, 0xf6, 0xdc, 0x8d, 0x12, 0xed, 0x4d, 0x56, 0xe1, 0xcc, 0x1e, 0xc1, 0xca, - 0xb6, 0xe1, 0x3d, 0x13, 0xb7, 0x73, 0x76, 0xe1, 0x02, 0xac, 0xa6, 0x38, 0xf3, 0x46, 0x47, 0x20, - 0x31, 0x71, 0xf6, 0x5c, 0x3f, 0x68, 0x6e, 0x1d, 0x2a, 0xfa, 0x64, 0xec, 0xa8, 0xfe, 0x63, 0x87, - 0x19, 0xa7, 0x59, 0xa5, 0x4c, 0x00, 0xfd, 0xc7, 0x0e, 0x46, 0x6b, 0x50, 0x1e, 0x1a, 0x26, 0xa6, - 0x46, 0x9a, 0x35, 0x16, 0x96, 0x09, 0xce, 0xb0, 0x7c, 0xec, 0x1e, 0x6b, 0x26, 0xb5, 0x47, 0x45, - 0x25, 0x2c, 0xcb, 0x8b, 0xb0, 0x20, 0x34, 0xc4, 0x5b, 0x5f, 0x84, 0x05, 0x2e, 0x58, 0xd4, 0x3c, - 0xb5, 0x41, 0x02, 0x90, 0x93, 0xfe, 0x16, 0x48, 0x1d, 0xeb, 0xd7, 0xf1, 0xc0, 0x17, 0x04, 0x7d, - 0x41, 0x46, 0x94, 0xec, 0x77, 0x9a, 0x7f, 0xe4, 0x35, 0x0b, 0xa9, 0xfd, 0x8e, 0x58, 0x41, 0x86, - 0x24, 0xb2, 0x0a, 0x02, 0x70, 0xa9, 0xfe, 0x2a, 0x07, 0xf5, 0x96, 0xae, 0xdf, 0x1d, 0x3b, 0x67, - 0xcf, 0x15, 0x82, 0xa2, 0x63, 0xbb, 0x3e, 0xdf, 0xf0, 0xe8, 0x6f, 0xf4, 0x2d, 0x28, 0xd2, 0x51, - 0x2e, 0x50, 0xe9, 0x6f, 0x44, 0x2d, 0xc7, 0x98, 0xde, 0xdc, 0xb3, 0x2d, 0xc3, 0xb7, 0x5d, 0xc3, - 0x1a, 0xf5, 0x6c, 0xd3, 0x18, 0x3c, 0x56, 0x68, 0x2d, 0x79, 0x0b, 0xa4, 0x24, 0x86, 0xac, 0x9c, - 0x9e, 0xd2, 0x96, 0x66, 0xc8, 0xca, 0xe9, 0x75, 0x0f, 0x62, 0x6b, 0x08, 0x55, 0x60, 0x76, 0xb7, - 0xbb, 0xd5, 0xda, 0x95, 0x0a, 0x84, 0xae, 0xb5, 0xbb, 0x2b, 0x15, 0x65, 0x89, 0xee, 0xa1, 0xb4, - 0x31, 0xde, 0xa9, 0x8f, 0x41, 0x62, 0x06, 0xf6, 0x79, 0xbb, 0x45, 0xe7, 0x35, 0xe2, 0xc0, 0xd9, - 0xf6, 0x61, 0x81, 0x4b, 0xab, 0x18, 0x87, 0x01, 0xdf, 0x6b, 0x30, 0xeb, 0x93, 0xa9, 0xe6, 0xa6, - 0xb9, 0x11, 0x8d, 0x40, 0x9f, 0x80, 0x15, 0x86, 0x15, 0x5d, 0x80, 0x7c, 0xdc, 0x05, 0x68, 0x43, - 0x59, 0xe9, 0x7d, 0xd2, 0xd9, 0xb2, 0xad, 0xe1, 0x29, 0x42, 0x5e, 0x86, 0xaa, 0x8b, 0xc7, 0xb6, - 0x8f, 0xd5, 0x50, 0xd6, 0x8a, 0x02, 0x0c, 0xd4, 0x23, 0x12, 0xff, 0x61, 0x11, 0x2a, 0x84, 0xcf, - 0x81, 0xaf, 0xf9, 0xd4, 0x3b, 0x99, 0x38, 0xbe, 0x31, 0x66, 0x62, 0x15, 0x14, 0x5e, 0x22, 0x0a, - 0x4e, 0xec, 0x00, 0xc5, 0xe4, 0x29, 0x26, 0x2c, 0xa3, 0x79, 0xc8, 0x4f, 0x1c, 0x3a, 0x91, 0x65, - 0x25, 0x3f, 0x71, 0x58, 0x93, 0x03, 0xdb, 0xd5, 0x55, 0xc3, 0x39, 0x7e, 0x87, 0xee, 0xc4, 0x75, - 0xd2, 0x24, 0x01, 0x75, 0x9c, 0xe3, 0x77, 0xe2, 0x04, 0x9b, 0x74, 0x1b, 0x16, 0x09, 0x36, 0x09, - 0x81, 0xe3, 0xe2, 0xa1, 0x71, 0xc2, 0x38, 0x94, 0x18, 0x01, 0x03, 0x05, 0x1c, 0x22, 0x82, 0xcd, - 0xe6, 0x5c, 0x82, 0x60, 0x93, 0xf4, 0xc3, 0xc3, 0xae, 0xa1, 0x99, 0xcd, 0x32, 0x73, 0x0f, 0x58, - 0x09, 0x7d, 0x03, 0xea, 0x2e, 0x1e, 0x60, 0xe3, 0x18, 0x73, 0xe9, 0x2a, 0xb4, 0x33, 0xb5, 0x00, - 0x48, 0xb9, 0x27, 0x88, 0x36, 0x9b, 0x90, 0x22, 0xda, 0x24, 0x44, 0x8c, 0xa7, 0x6a, 0xd9, 0xbe, - 0x31, 0x7c, 0xdc, 0xac, 0x32, 0x22, 0x06, 0xdc, 0xa7, 0x30, 0x22, 0xe7, 0x40, 0x1b, 0x1c, 0x61, - 0xb6, 0x25, 0x36, 0x6b, 0x94, 0x04, 0x28, 0x88, 0x9a, 0x73, 0x74, 0x0d, 0xe6, 0x43, 0x02, 0xaa, - 0x2c, 0xcd, 0x3a, 0xa5, 0xa9, 0x07, 0x34, 0x6c, 0x7f, 0xbd, 0x04, 0x55, 0x6c, 0xe9, 0xaa, 0x3d, - 0x54, 0x75, 0xcd, 0xd7, 0x9a, 0xf3, 0x94, 0xa6, 0x82, 0x2d, 0xbd, 0x3b, 0xdc, 0xd6, 0x7c, 0x0d, - 0x2d, 0xc1, 0x2c, 0x76, 0x5d, 0xdb, 0x6d, 0x36, 0x28, 0x86, 0x15, 0xd0, 0x55, 0xe0, 0xd2, 0xa8, - 0x5f, 0x4e, 0xb0, 0xfb, 0xb8, 0x29, 0x51, 0x64, 0x95, 0xc1, 0x3e, 0x25, 0x20, 0x36, 0x15, 0x64, - 0xb7, 0x66, 0x14, 0x0b, 0x4c, 0x40, 0x0a, 0xa2, 0x04, 0xf2, 0xe7, 0x50, 0x54, 0x9c, 0x2f, 0x0c, - 0xf4, 0x0a, 0x14, 0x07, 0xb6, 0x35, 0xe4, 0xda, 0x2a, 0x5a, 0x1b, 0xae, 0x83, 0x0a, 0xc5, 0xa3, - 0x57, 0x61, 0xd6, 0x23, 0x9a, 0x44, 0xb5, 0xa4, 0x7a, 0x7b, 0x31, 0x4e, 0x48, 0x95, 0x4c, 0x61, - 0x14, 0xf2, 0x0d, 0x98, 0xdf, 0xc1, 0x3e, 0xe1, 0x1e, 0xac, 0x89, 0xc8, 0xa9, 0xcb, 0x89, 0x4e, - 0x9d, 0x7c, 0x07, 0x1a, 0x21, 0x25, 0x1f, 0x91, 0x1b, 0x30, 0xe7, 0x61, 0xf7, 0x38, 0xd3, 0x59, - 0xa7, 0x84, 0x01, 0x5a, 0xfe, 0x2e, 0x5d, 0xe6, 0x62, 0x33, 0xcf, 0x66, 0xa9, 0xd6, 0xa0, 0x6c, - 0x1a, 0x43, 0x4c, 0x55, 0xbf, 0xc0, 0x54, 0x3f, 0x28, 0xcb, 0x0b, 0xd4, 0x13, 0x16, 0x05, 0x93, - 0x5b, 0x81, 0x05, 0x78, 0xee, 0x16, 0x23, 0x5f, 0x34, 0xc6, 0xf8, 0x8d, 0x60, 0x1f, 0x39, 0x17, - 0x63, 0xc2, 0x44, 0x24, 0xe7, 0x4c, 0x6e, 0x86, 0x5b, 0xcc, 0xf9, 0xb8, 0x2c, 0xc3, 0x62, 0x8c, - 0x9e, 0xb3, 0x79, 0x1d, 0x24, 0xaa, 0xbf, 0xe7, 0x63, 0xb2, 0x08, 0x0b, 0x02, 0x35, 0x67, 0xf1, - 0x16, 0x2c, 0x85, 0x5e, 0xcd, 0xf9, 0xd8, 0xac, 0xc2, 0x72, 0xa2, 0x06, 0x67, 0xf5, 0x8b, 0x5c, - 0xd0, 0xd7, 0xef, 0xe2, 0x43, 0x57, 0x0b, 0x38, 0x49, 0x50, 0x98, 0xb8, 0x26, 0xe7, 0x42, 0x7e, - 0x52, 0x6d, 0xb7, 0x27, 0x3e, 0xa6, 0x1b, 0x3c, 0x39, 0x14, 0x16, 0xa8, 0x31, 0x24, 0x20, 0xb2, - 0xc5, 0x7b, 0xa4, 0x71, 0xa2, 0x33, 0xc4, 0x9f, 0x60, 0xc7, 0x8a, 0xa0, 0x88, 0xde, 0x81, 0x15, - 0x0b, 0x9f, 0xf8, 0x47, 0xb6, 0xa3, 0xfa, 0xae, 0x31, 0x1a, 0x61, 0x57, 0x65, 0xe7, 0x4d, 0x7e, - 0x32, 0x5b, 0xe2, 0xd8, 0x3e, 0x43, 0x32, 0x71, 0xd0, 0x6d, 0x58, 0x4e, 0xd6, 0xd2, 0xb1, 0xa9, - 0x3d, 0xe6, 0x36, 0x6f, 0x31, 0x5e, 0x69, 0x9b, 0xa0, 0xc8, 0x90, 0xc7, 0x3a, 0xc3, 0x3b, 0xd9, - 0x80, 0xfa, 0x0e, 0xf6, 0x1f, 0xba, 0xc3, 0xc0, 0x5b, 0x78, 0x9b, 0x2e, 0x1f, 0x0a, 0xe0, 0x6b, - 0xe2, 0x2a, 0x14, 0x8f, 0xdd, 0x61, 0xb0, 0x20, 0xea, 0xd1, 0x82, 0x20, 0x44, 0x14, 0x25, 0xbf, - 0x45, 0x77, 0xed, 0x88, 0x0b, 0xba, 0x0c, 0x85, 0x63, 0x37, 0x58, 0xd6, 0x89, 0x2a, 0x04, 0xc3, - 0x77, 0x49, 0xa1, 0x19, 0xf9, 0xed, 0x60, 0x97, 0x7c, 0x16, 0x36, 0xe1, 0xc6, 0x28, 0x72, 0x7a, - 0x00, 0x4b, 0x3b, 0xd8, 0xdf, 0xc6, 0x43, 0xc3, 0xc2, 0xfa, 0x01, 0x0e, 0xdd, 0x9b, 0x57, 0xb9, - 0x73, 0xc0, 0x5c, 0x9b, 0xe5, 0x88, 0x1d, 0x27, 0x25, 0x93, 0xc5, 0x3c, 0x81, 0xf0, 0xd8, 0x9c, - 0x8f, 0x8e, 0xcd, 0x72, 0x0b, 0x96, 0x13, 0x6c, 0x43, 0xa3, 0x51, 0xf4, 0xb0, 0x1f, 0x0c, 0xd0, - 0x52, 0x8a, 0x2f, 0xa1, 0xa5, 0x14, 0xf2, 0x47, 0xb0, 0xd4, 0xd2, 0xf5, 0xb4, 0x64, 0xaf, 0x40, - 0x81, 0x18, 0x72, 0xd6, 0xcf, 0x6c, 0x06, 0x84, 0x80, 0xe8, 0x6a, 0xa2, 0x3e, 0xef, 0xf2, 0x01, - 0xac, 0xb2, 0x71, 0x78, 0x6e, 0xde, 0x44, 0xaf, 0x35, 0xd3, 0xe4, 0xee, 0x00, 0xf9, 0x49, 0x3c, - 0xf5, 0x34, 0x53, 0xde, 0xe0, 0x5d, 0x68, 0x2a, 0xd8, 0x31, 0xb5, 0xc1, 0xf3, 0xb7, 0x48, 0x4e, - 0x20, 0x19, 0x3c, 0x78, 0x03, 0xcb, 0x34, 0x96, 0x42, 0x2d, 0xfb, 0x18, 0x5b, 0xa1, 0x33, 0xfb, - 0x09, 0x9d, 0x5b, 0x01, 0xcc, 0xe7, 0xe0, 0x6d, 0x00, 0x2f, 0x00, 0x06, 0x33, 0x21, 0xec, 0x12, - 0x51, 0x05, 0x81, 0x4c, 0xbe, 0x4f, 0x4f, 0xd3, 0xc9, 0x36, 0xd0, 0x2d, 0xa8, 0x84, 0x44, 0xbc, - 0x17, 0x99, 0xac, 0x22, 0x2a, 0x79, 0x85, 0x4e, 0x6c, 0x4a, 0x2c, 0xf9, 0xfb, 0xc1, 0xd9, 0xfa, - 0x05, 0x34, 0x92, 0x31, 0x43, 0x17, 0x82, 0x69, 0x4f, 0xb7, 0xbc, 0x0b, 0xab, 0x7c, 0x70, 0x5f, - 0x44, 0xff, 0xd6, 0xc2, 0xe9, 0x4e, 0xb7, 0x84, 0x40, 0xda, 0xc1, 0x3e, 0x77, 0xa4, 0xf9, 0x34, - 0xb5, 0x60, 0x41, 0x80, 0xf1, 0x39, 0x7a, 0x1d, 0xca, 0x0e, 0x81, 0x18, 0x38, 0x98, 0x21, 0x49, - 0x38, 0x1a, 0x30, 0xda, 0x90, 0x42, 0x3e, 0x01, 0xa9, 0xa5, 0xeb, 0x31, 0xb6, 0xe8, 0x06, 0x94, - 0x28, 0xfe, 0x31, 0x17, 0x3b, 0x5d, 0x9f, 0xe3, 0xd1, 0x07, 0x70, 0xc1, 0xc5, 0x43, 0x62, 0x4e, - 0x4f, 0x0c, 0xcf, 0x37, 0xac, 0x91, 0x2a, 0xa8, 0x07, 0x1b, 0xc1, 0x55, 0x4a, 0xd0, 0xe6, 0xf8, - 0x83, 0x48, 0x2d, 0x16, 0x61, 0x41, 0x68, 0x99, 0xf7, 0xf2, 0x07, 0x39, 0x58, 0xe4, 0xa1, 0x9c, - 0xe7, 0x14, 0xe9, 0x4d, 0x58, 0x74, 0x88, 0x0b, 0xe4, 0x1e, 0xe3, 0xb4, 0x30, 0x28, 0x40, 0x45, - 0x72, 0x04, 0xf3, 0x5d, 0x88, 0xe6, 0x7b, 0x05, 0x96, 0xe2, 0x32, 0x70, 0xe1, 0xfe, 0x34, 0x07, - 0x4b, 0x7c, 0x7e, 0xfe, 0x07, 0x06, 0x6c, 0x5a, 0xcf, 0x0a, 0xd3, 0x7a, 0xc6, 0x22, 0x2a, 0x31, - 0x71, 0xc3, 0x33, 0xfb, 0x5a, 0xa8, 0x37, 0x2d, 0xcf, 0x33, 0x46, 0x96, 0xa8, 0xb8, 0x1f, 0x00, - 0x68, 0x21, 0x90, 0xf7, 0x68, 0x2d, 0xd9, 0x23, 0xa1, 0x9a, 0x40, 0x2d, 0x7f, 0x0e, 0xeb, 0x99, - 0x9c, 0xb9, 0x6e, 0xfe, 0x2a, 0xac, 0x1f, 0xc1, 0x5a, 0xa8, 0x2f, 0x2f, 0x56, 0xe8, 0x8b, 0xb0, - 0x9e, 0xc9, 0x99, 0x8f, 0xd6, 0x18, 0x2e, 0x8a, 0xea, 0xf0, 0x42, 0xdb, 0xce, 0xb0, 0x36, 0x57, - 0xe0, 0xd2, 0xb4, 0xe6, 0xb8, 0x40, 0xdf, 0x83, 0x4b, 0xb1, 0x79, 0x7d, 0xb1, 0xa3, 0x71, 0x15, - 0x2e, 0x4f, 0xe5, 0x1e, 0xb3, 0x45, 0x07, 0xd4, 0x47, 0x0f, 0x6c, 0xd1, 0x87, 0xd4, 0x16, 0x05, - 0xb0, 0x70, 0xcf, 0x2e, 0x8d, 0x4c, 0xfb, 0x50, 0x33, 0xd3, 0x0b, 0x63, 0x87, 0xc2, 0x15, 0x8e, - 0x97, 0x3f, 0x02, 0x74, 0xe0, 0x6b, 0x6e, 0x9c, 0xe9, 0x33, 0xd4, 0x5f, 0x86, 0xc5, 0x58, 0xfd, - 0x28, 0x54, 0x73, 0xe0, 0xdb, 0x4e, 0x5c, 0xd4, 0x25, 0xd2, 0x56, 0x04, 0xe4, 0xa4, 0x7f, 0x52, - 0x80, 0x79, 0x72, 0xcc, 0x79, 0xa8, 0x99, 0x86, 0x4e, 0x23, 0x50, 0xe8, 0x9d, 0xe0, 0x3c, 0xc4, - 0x7c, 0x99, 0x4b, 0xf1, 0xf3, 0x50, 0x44, 0x78, 0x53, 0x3c, 0x1a, 0xa1, 0xf7, 0xa0, 0xe4, 0x62, - 0xcd, 0x0b, 0xa3, 0x8e, 0x97, 0xa7, 0x56, 0x53, 0x28, 0x99, 0xc2, 0xc9, 0xd1, 0x75, 0x98, 0x1b, - 0x6b, 0xfe, 0xe0, 0x08, 0xeb, 0x3c, 0xa6, 0x23, 0xf8, 0x62, 0x8a, 0xad, 0x29, 0x01, 0x16, 0xbd, - 0x05, 0xb5, 0x89, 0xc5, 0x0b, 0xaa, 0xe6, 0x35, 0x8b, 0x59, 0xd4, 0xd5, 0x90, 0xa4, 0xe5, 0xa1, - 0xf7, 0x41, 0x8a, 0x6a, 0x98, 0xd8, 0x1a, 0xf9, 0x47, 0xcd, 0xd9, 0xac, 0x5a, 0x8d, 0x90, 0x6c, - 0x97, 0x52, 0xc9, 0x3d, 0x98, 0x65, 0xd1, 0x85, 0x79, 0x80, 0x83, 0x7e, 0xab, 0xdf, 0x56, 0xf7, - 0xbb, 0xfb, 0x6d, 0x69, 0x06, 0x2d, 0x42, 0x23, 0x28, 0xf7, 0xd5, 0x7b, 0xdd, 0x07, 0xfb, 0xdb, - 0x52, 0x0e, 0x35, 0xa0, 0xca, 0x80, 0x0f, 0x5b, 0xbb, 0x9d, 0x6d, 0x29, 0x8f, 0x16, 0xa0, 0xce, - 0x00, 0x9d, 0x7d, 0x06, 0x2a, 0xc8, 0x77, 0xa0, 0xc4, 0x3a, 0x4e, 0xa8, 0x95, 0x76, 0xeb, 0xa0, - 0xdb, 0x0f, 0x78, 0xd6, 0xa1, 0x42, 0x01, 0xfb, 0x6a, 0xeb, 0x40, 0xca, 0x91, 0xca, 0xbc, 0xb8, - 0xdb, 0xde, 0xdf, 0xa1, 0xf1, 0xd4, 0x7f, 0x2d, 0x42, 0xb1, 0xc7, 0xef, 0x01, 0x2c, 0xd3, 0x35, - 0x82, 0x4b, 0x0b, 0xf2, 0x9b, 0x1c, 0x41, 0x1d, 0xcd, 0xf7, 0x5d, 0x76, 0x3a, 0xa8, 0x29, 0xbc, - 0x44, 0x17, 0xd9, 0x28, 0x38, 0x00, 0x92, 0x9f, 0xa4, 0xf6, 0x21, 0xf6, 0x82, 0x9b, 0x19, 0xfa, - 0x9b, 0x1c, 0x30, 0x0c, 0x4f, 0xfd, 0xca, 0xf0, 0x8f, 0x74, 0x57, 0xfb, 0x8a, 0x7a, 0xf9, 0x65, - 0x05, 0x0c, 0xef, 0x33, 0x0e, 0x41, 0x97, 0x00, 0x8e, 0xc3, 0xc9, 0xa3, 0x81, 0x8d, 0x59, 0x45, - 0x80, 0xa0, 0x36, 0x2c, 0x44, 0x25, 0x55, 0xc7, 0xbe, 0x66, 0x98, 0x34, 0xbc, 0x51, 0xbd, 0xdd, - 0x9c, 0xa6, 0x03, 0x8a, 0x14, 0x55, 0xd9, 0xa6, 0x35, 0xd0, 0x5b, 0xb0, 0x64, 0xd9, 0xaa, 0x31, - 0x76, 0xc8, 0x16, 0xed, 0x47, 0x02, 0x95, 0x99, 0xa1, 0xb7, 0xec, 0x0e, 0x47, 0x85, 0x82, 0x45, - 0x47, 0xef, 0x4a, 0xec, 0x3e, 0xe5, 0x22, 0x00, 0x8b, 0x21, 0xaa, 0x9a, 0x67, 0xd1, 0x40, 0x48, - 0x5d, 0xa9, 0x30, 0x48, 0xcb, 0xb3, 0xd0, 0x3a, 0xf0, 0x82, 0x6a, 0xe8, 0x34, 0x02, 0x52, 0x51, - 0xca, 0x0c, 0xd0, 0xd1, 0x79, 0xc4, 0xd4, 0xc7, 0x2e, 0xd6, 0x69, 0xe8, 0xa3, 0xac, 0x84, 0x65, - 0xb4, 0x44, 0xd7, 0x85, 0xc9, 0xe2, 0x1d, 0x65, 0x85, 0x15, 0xd0, 0x0d, 0x90, 0x0c, 0x4f, 0x1d, - 0xba, 0xf6, 0x58, 0xc5, 0x27, 0x3e, 0x76, 0x2d, 0xcd, 0xa4, 0xc1, 0x8e, 0xb2, 0x32, 0x6f, 0x78, - 0xf7, 0x5c, 0x7b, 0xdc, 0xe6, 0x50, 0x32, 0xd2, 0x16, 0x0f, 0xe9, 0xaa, 0x86, 0x43, 0xe3, 0x1e, - 0x15, 0x05, 0x02, 0x50, 0xc7, 0x09, 0x2f, 0x79, 0xa4, 0xe8, 0x92, 0x07, 0xbd, 0x0e, 0xc8, 0xf0, - 0xd4, 0xe0, 0x44, 0x66, 0x58, 0x74, 0xdc, 0x68, 0xd0, 0xa3, 0xac, 0x48, 0x86, 0xb7, 0xcf, 0x10, - 0x1d, 0x06, 0x27, 0x73, 0x65, 0xe8, 0xd8, 0xf2, 0x8d, 0xa1, 0x81, 0xdd, 0x26, 0x62, 0x31, 0xa6, - 0x08, 0x82, 0x5e, 0x05, 0xc9, 0xb4, 0x07, 0x9a, 0xa9, 0x0a, 0x54, 0x8b, 0x94, 0xaa, 0x41, 0xe1, - 0x9d, 0x10, 0x2c, 0xff, 0x71, 0x0e, 0xaa, 0xdb, 0x98, 0xec, 0xc6, 0x6c, 0x9a, 0x89, 0x96, 0xd1, - 0x60, 0x15, 0x3f, 0x9d, 0xf2, 0x52, 0x14, 0x90, 0xcd, 0x9f, 0x12, 0x90, 0x45, 0xd7, 0xa1, 0x61, - 0xda, 0x16, 0x39, 0x4c, 0xb2, 0x6a, 0x38, 0xd8, 0xc1, 0xe7, 0x19, 0xb8, 0xc7, 0xa1, 0x44, 0x42, - 0xef, 0xc8, 0x76, 0x7d, 0x91, 0x92, 0xa9, 0x6b, 0x83, 0xc3, 0x03, 0x52, 0xf9, 0x2f, 0x72, 0x30, - 0x4b, 0x03, 0x8f, 0xe8, 0x95, 0xd8, 0xe1, 0x2b, 0x2b, 0xae, 0x3c, 0xf5, 0xe4, 0x35, 0xf5, 0x56, - 0xee, 0x9b, 0x50, 0xd3, 0xa3, 0xee, 0x07, 0xd6, 0x26, 0x76, 0xb0, 0x0b, 0xb1, 0x4a, 0x8c, 0x94, - 0x86, 0xfa, 0x6c, 0xcf, 0x57, 0xb9, 0x77, 0xc4, 0x97, 0x14, 0x01, 0xb1, 0xbd, 0x45, 0xde, 0xa4, - 0x07, 0xe3, 0x67, 0x8e, 0xac, 0xca, 0xef, 0xb1, 0xf0, 0x13, 0xa9, 0xc7, 0xb7, 0x9a, 0x73, 0x56, - 0x1c, 0xc3, 0x02, 0x2d, 0xef, 0xda, 0xf6, 0x17, 0x13, 0x87, 0x8d, 0xe0, 0xd4, 0x19, 0xfd, 0x18, - 0xea, 0x26, 0xa5, 0x53, 0x6d, 0x47, 0xb8, 0x46, 0x5a, 0x4f, 0xf0, 0x66, 0xbc, 0xba, 0x0e, 0x1b, - 0x00, 0x53, 0x28, 0xc9, 0x7f, 0x94, 0xa3, 0x82, 0x8a, 0x77, 0xa8, 0x5f, 0xc7, 0x14, 0xbd, 0x07, - 0x65, 0x41, 0x47, 0xc8, 0xf4, 0x64, 0xcb, 0xc8, 0xfa, 0xab, 0x84, 0xc4, 0xb2, 0x09, 0x88, 0xdb, - 0x22, 0x2c, 0x4c, 0xc2, 0x79, 0x45, 0x9c, 0x76, 0x1d, 0x1e, 0x8d, 0x67, 0x41, 0x1c, 0x4f, 0xb2, - 0x49, 0xc7, 0x5a, 0xe3, 0x3b, 0xef, 0x3f, 0x13, 0x9b, 0x8e, 0xb1, 0x4b, 0x6d, 0x0e, 0xe1, 0x10, - 0x1c, 0x5d, 0xea, 0x4a, 0x58, 0x46, 0xef, 0x43, 0x4d, 0x73, 0x1c, 0xf3, 0x71, 0xa0, 0x4b, 0x2c, - 0x44, 0x29, 0x68, 0x61, 0x8b, 0x60, 0xb9, 0xa3, 0x5b, 0xd5, 0xa2, 0x42, 0x18, 0xfd, 0x2c, 0x24, - 0xa3, 0x9f, 0xa4, 0x4d, 0x21, 0xfa, 0x79, 0x07, 0xea, 0xf8, 0x70, 0xe4, 0xa8, 0xe3, 0x89, 0xe9, - 0x1b, 0x47, 0xb6, 0xc3, 0xaf, 0xa1, 0x57, 0xa2, 0x0a, 0xed, 0xc3, 0x91, 0xb3, 0xc7, 0xb1, 0x4a, - 0x0d, 0x0b, 0x25, 0xd4, 0x82, 0x06, 0x8b, 0x4e, 0xb9, 0x78, 0x68, 0xe2, 0x81, 0x6f, 0xbb, 0x54, - 0xdb, 0xe3, 0x96, 0x9f, 0x10, 0x28, 0x01, 0x5e, 0x99, 0x77, 0x63, 0x65, 0x74, 0x1d, 0x8a, 0x86, - 0x35, 0xb4, 0xe9, 0xc6, 0x12, 0x3b, 0x2b, 0x12, 0x39, 0x99, 0x87, 0x41, 0x09, 0x88, 0x57, 0xe4, - 0x1b, 0x63, 0xec, 0x7a, 0x7c, 0x73, 0x11, 0xbc, 0xa2, 0x3e, 0x85, 0x2b, 0x1c, 0x4f, 0xce, 0xa0, - 0xbe, 0xab, 0x59, 0x1e, 0x8d, 0x52, 0x96, 0x93, 0x7c, 0xfb, 0x01, 0x4a, 0x89, 0xa8, 0xc8, 0x38, - 0xb3, 0x8e, 0xb0, 0x10, 0x2c, 0xdd, 0x51, 0x62, 0xe3, 0x4c, 0x7b, 0xc1, 0x7d, 0x27, 0x16, 0x91, - 0x63, 0x05, 0xb4, 0x0d, 0xd2, 0xc8, 0xd5, 0x06, 0x78, 0x38, 0x31, 0x55, 0x17, 0x7b, 0xc4, 0x1b, - 0xa3, 0x7b, 0x4e, 0xf5, 0xf6, 0x05, 0xc1, 0x6d, 0xe3, 0x14, 0x0a, 0x23, 0x50, 0x1a, 0xa3, 0x38, - 0x00, 0xdd, 0x84, 0x8a, 0x36, 0x34, 0x54, 0x4f, 0x1b, 0x1a, 0x5e, 0xb3, 0x4a, 0x75, 0x79, 0x41, - 0x98, 0xe4, 0xa1, 0x71, 0xa0, 0x0d, 0x0d, 0xa5, 0xac, 0xb1, 0x1f, 0xe4, 0x54, 0x54, 0xd1, 0x74, - 0x5d, 0x65, 0x96, 0xb7, 0x96, 0x9c, 0x62, 0xfe, 0xd4, 0xc1, 0x53, 0xca, 0x1a, 0xff, 0x25, 0xff, - 0x6d, 0x0e, 0xaa, 0x82, 0xae, 0xa0, 0xf7, 0xa0, 0x62, 0x58, 0x6a, 0xec, 0xfc, 0x76, 0x9a, 0xab, - 0x5c, 0x36, 0x2c, 0x5e, 0xf1, 0xdb, 0x50, 0xc7, 0x27, 0x64, 0xcc, 0xe2, 0x2a, 0x79, 0x5a, 0xe5, - 0x1a, 0xab, 0x10, 0x31, 0x30, 0xc6, 0x22, 0x83, 0xc2, 0xd9, 0x0c, 0x58, 0x05, 0x6e, 0x3d, 0x7f, - 0x13, 0xaa, 0x6c, 0x45, 0xef, 0x1a, 0x63, 0x63, 0x6a, 0x04, 0x1e, 0x5d, 0x85, 0xda, 0x58, 0x3b, - 0x89, 0x76, 0x11, 0xb6, 0x58, 0xab, 0x63, 0xed, 0x24, 0xdc, 0x6c, 0xde, 0x81, 0x15, 0x8f, 0x5f, - 0x17, 0xab, 0xfe, 0x91, 0x8b, 0xbd, 0x23, 0xdb, 0xd4, 0x55, 0x67, 0xe0, 0x73, 0x43, 0xb3, 0x14, - 0x60, 0xfb, 0x01, 0xb2, 0x37, 0xf0, 0xe5, 0x5f, 0xce, 0x42, 0x39, 0x58, 0x44, 0xe8, 0x1b, 0x50, - 0xd7, 0x26, 0xfe, 0x91, 0xea, 0x68, 0x9e, 0xf7, 0x95, 0xed, 0xea, 0xdc, 0x96, 0xd6, 0x08, 0xb0, - 0xc7, 0x61, 0xe8, 0x0a, 0x54, 0x75, 0xec, 0x0d, 0x5c, 0xc3, 0x11, 0xee, 0x7d, 0x45, 0x10, 0xba, - 0x00, 0x65, 0xb6, 0x31, 0x6b, 0x5e, 0x10, 0xc6, 0xa5, 0xe5, 0x16, 0xdd, 0x11, 0x43, 0xb7, 0x21, - 0x08, 0x33, 0x17, 0x29, 0x87, 0x46, 0x00, 0x6f, 0xf1, 0xc8, 0xfc, 0x2a, 0xcc, 0x39, 0x18, 0xbb, - 0x84, 0x09, 0x8b, 0xd6, 0x96, 0x48, 0xb1, 0xe5, 0x11, 0x97, 0x88, 0x22, 0x46, 0xae, 0x3d, 0x71, - 0xe8, 0x52, 0xab, 0x28, 0x15, 0x02, 0xd9, 0x21, 0x00, 0xe2, 0x12, 0x51, 0x34, 0x35, 0x7f, 0xec, - 0x66, 0xaa, 0x4c, 0x00, 0xf4, 0x12, 0x79, 0x1f, 0x16, 0x5c, 0x3c, 0xb6, 0x8f, 0xb1, 0xea, 0xb8, - 0xc6, 0xb1, 0xe6, 0x13, 0xb7, 0x8a, 0xae, 0xaa, 0xf9, 0xdb, 0x72, 0xda, 0xaa, 0xdc, 0x54, 0x28, - 0x6d, 0x8f, 0x91, 0xb6, 0x3c, 0xa5, 0xe1, 0xc6, 0x01, 0xc4, 0xa3, 0x61, 0x4b, 0x6d, 0x68, 0x6a, - 0x8e, 0xaa, 0x6b, 0x63, 0xc7, 0xb0, 0x46, 0x74, 0xc1, 0x95, 0x15, 0x89, 0x62, 0xee, 0x99, 0x9a, - 0xb3, 0xcd, 0xe0, 0xe8, 0x1a, 0xcc, 0x7b, 0xd8, 0xd2, 0x55, 0x7e, 0x49, 0xee, 0x3f, 0xe6, 0x0e, - 0x5d, 0x9d, 0x40, 0xb7, 0x02, 0x20, 0xe9, 0x20, 0xbf, 0x33, 0x1c, 0x68, 0x0e, 0x5d, 0x40, 0x35, - 0xa5, 0xc2, 0x20, 0x5b, 0x1a, 0xed, 0x20, 0x1b, 0x5e, 0x82, 0xad, 0x51, 0x2c, 0x1b, 0x6f, 0x82, - 0x9c, 0x87, 0xbc, 0xa1, 0x53, 0xa7, 0xae, 0xa2, 0xe4, 0x0d, 0x1d, 0x7d, 0x00, 0x75, 0x7e, 0x53, - 0x67, 0x12, 0x05, 0xf3, 0x9a, 0xf3, 0xc9, 0xad, 0x5f, 0x50, 0x3f, 0xa5, 0xe6, 0x44, 0x05, 0x8f, - 0xa8, 0x03, 0x9f, 0x47, 0x3e, 0x53, 0xcc, 0xcb, 0xab, 0xb1, 0xc9, 0xe4, 0xd3, 0xf4, 0x06, 0xa0, - 0xc8, 0x11, 0xb4, 0x7c, 0xec, 0x0e, 0xb5, 0x01, 0xa6, 0x5e, 0x5f, 0x45, 0x59, 0x08, 0xfd, 0xc1, - 0x00, 0x41, 0xfc, 0xf8, 0x63, 0x77, 0x48, 0x7d, 0xbe, 0x0a, 0x8d, 0x4c, 0xa3, 0x2b, 0x50, 0xd3, - 0x4c, 0xd3, 0xfe, 0x4a, 0x25, 0x8a, 0xab, 0x79, 0x81, 0xa3, 0x47, 0x61, 0xdd, 0xaf, 0xac, 0x96, - 0x87, 0x5e, 0x81, 0x86, 0xcb, 0x8e, 0xb3, 0x6a, 0xa0, 0x11, 0x8b, 0xec, 0x7d, 0x0c, 0x07, 0xf7, - 0xa8, 0x62, 0xc8, 0xb7, 0xa0, 0x91, 0x98, 0x30, 0x54, 0x86, 0x22, 0x3f, 0x97, 0xf0, 0x6b, 0xe7, - 0x1c, 0xaa, 0xc2, 0x9c, 0xd2, 0xee, 0xed, 0xb6, 0xb6, 0xda, 0x52, 0x5e, 0xfe, 0x04, 0x6a, 0xe2, - 0x8e, 0x80, 0x9a, 0x30, 0xc7, 0xae, 0x15, 0x82, 0x57, 0x6d, 0x41, 0x91, 0xae, 0x40, 0x4e, 0xa5, - 0xfa, 0xbe, 0x19, 0xae, 0x40, 0x0e, 0xeb, 0xfb, 0xa6, 0xfc, 0xdb, 0x39, 0x98, 0x8f, 0x6f, 0x10, - 0x64, 0x51, 0x26, 0xf6, 0x14, 0x75, 0x60, 0x1a, 0xc1, 0x89, 0xbe, 0xac, 0x2c, 0xc5, 0x37, 0x90, - 0x2d, 0x8a, 0x43, 0x77, 0x60, 0x2d, 0x5d, 0x6b, 0xe2, 0x11, 0x3f, 0x32, 0x7c, 0x42, 0xb0, 0x9a, - 0xac, 0x49, 0xf1, 0x1d, 0x5d, 0xfe, 0xb3, 0x12, 0x54, 0xc2, 0xed, 0xe6, 0xbf, 0x61, 0x49, 0xdf, - 0x84, 0xf2, 0x18, 0x7b, 0x9e, 0x36, 0xe2, 0xce, 0x6d, 0xcc, 0x78, 0xef, 0x71, 0x8c, 0x12, 0xd2, - 0x64, 0x9a, 0x80, 0xd9, 0x33, 0x4d, 0x40, 0xe9, 0x14, 0x13, 0x30, 0x77, 0xaa, 0x09, 0x28, 0x27, - 0x4c, 0xc0, 0x0d, 0x28, 0x7d, 0x39, 0xc1, 0x13, 0xec, 0xf1, 0x7d, 0x51, 0xd8, 0x7a, 0x3f, 0xa5, - 0x70, 0x85, 0xe3, 0xd1, 0x46, 0x96, 0xb1, 0x60, 0x2b, 0xf6, 0x9c, 0x86, 0xa0, 0x7a, 0x6e, 0x43, - 0x50, 0xcb, 0x32, 0x04, 0xf4, 0x8e, 0xdb, 0xf3, 0xc8, 0x51, 0x94, 0x05, 0x31, 0xea, 0x94, 0xaa, - 0xc6, 0x81, 0x6c, 0x86, 0xdf, 0x85, 0x15, 0x6f, 0xe2, 0x90, 0x2d, 0x05, 0xeb, 0xc4, 0x24, 0x68, - 0x87, 0x86, 0x69, 0xf8, 0xc4, 0xff, 0x9a, 0xa7, 0xf7, 0x6b, 0xcb, 0x21, 0x76, 0x4b, 0x40, 0x92, - 0x31, 0x22, 0x9e, 0x12, 0xe3, 0xcb, 0x16, 0x76, 0xf9, 0x70, 0xe4, 0x30, 0x9e, 0xdf, 0x86, 0xaa, - 0xa6, 0x8f, 0x8d, 0xa0, 0x59, 0x29, 0x19, 0x3b, 0x09, 0xf5, 0xeb, 0x66, 0x8b, 0x90, 0x31, 0xcf, - 0x06, 0xb4, 0xf0, 0x37, 0x71, 0x03, 0x83, 0xdb, 0x7a, 0xba, 0xd6, 0xeb, 0x4a, 0x58, 0x26, 0x38, - 0x6d, 0x30, 0xc0, 0x8e, 0x8f, 0x75, 0xbe, 0xd8, 0xc3, 0x32, 0x39, 0xf3, 0x69, 0xd1, 0xc3, 0xd2, - 0x45, 0x6e, 0x0a, 0xa2, 0x27, 0xa5, 0x8b, 0x30, 0x6b, 0x4f, 0x7c, 0xf5, 0xcb, 0xe6, 0x12, 0xbb, - 0xaf, 0xb5, 0x27, 0xfe, 0xa7, 0xe4, 0x2c, 0x3b, 0x34, 0x6d, 0xc7, 0x6b, 0x2e, 0x53, 0x20, 0x2b, - 0xc8, 0x1b, 0x00, 0x91, 0x70, 0xa8, 0x04, 0xf9, 0x07, 0x3d, 0xf6, 0x38, 0x65, 0xbb, 0xfb, 0xd9, - 0xbe, 0x94, 0x43, 0x00, 0xa5, 0xde, 0xbd, 0x47, 0xea, 0x56, 0x5f, 0xca, 0xcb, 0xbf, 0x06, 0xe5, - 0x40, 0x53, 0xd1, 0x1b, 0x82, 0xe8, 0xcc, 0x97, 0x58, 0x48, 0xe9, 0xb3, 0xd0, 0x9b, 0x6b, 0x50, - 0xf4, 0x82, 0xd7, 0x21, 0x99, 0xa4, 0x14, 0x2d, 0xff, 0x2c, 0x07, 0x73, 0x1c, 0x82, 0x64, 0xa8, - 0xed, 0x77, 0xfb, 0x9d, 0x7b, 0x9d, 0xad, 0x56, 0xbf, 0xd3, 0xdd, 0xa7, 0xad, 0x14, 0x95, 0x18, - 0x8c, 0x38, 0x02, 0x0f, 0x7a, 0xdb, 0xad, 0x7e, 0x9b, 0x32, 0x2e, 0x2a, 0xbc, 0x44, 0x8e, 0x14, - 0xdd, 0x5e, 0x7b, 0x9f, 0xbf, 0x72, 0xa2, 0xbf, 0xd1, 0x4b, 0x50, 0xf9, 0xa4, 0xdd, 0xee, 0xb5, - 0x76, 0x3b, 0x0f, 0xdb, 0x74, 0x09, 0x16, 0x95, 0x08, 0x40, 0x4c, 0x9a, 0xd2, 0xbe, 0xa7, 0xb4, - 0x0f, 0xee, 0xd3, 0x65, 0x56, 0x54, 0x82, 0x22, 0xa9, 0xb7, 0xdd, 0x39, 0xd8, 0x6a, 0x29, 0xdb, - 0xed, 0x6d, 0xba, 0xc0, 0x8a, 0x4a, 0x04, 0x20, 0xa3, 0xda, 0xef, 0xf6, 0x5b, 0xbb, 0x74, 0x79, - 0x15, 0x15, 0x56, 0x90, 0x37, 0xa1, 0xc4, 0x56, 0x09, 0xc1, 0x1b, 0x96, 0x33, 0xf1, 0xb9, 0xa7, - 0xc2, 0x0a, 0x44, 0x6e, 0x7b, 0xe2, 0x13, 0x30, 0x3f, 0x4f, 0xb0, 0x92, 0x8c, 0xa1, 0xc4, 0x1c, - 0x5b, 0x74, 0x13, 0x4a, 0xc4, 0x57, 0x37, 0x46, 0x7c, 0x74, 0x57, 0x92, 0xae, 0xef, 0x16, 0xc5, - 0x2a, 0x9c, 0x0a, 0xbd, 0x16, 0x7f, 0xd1, 0xb0, 0x9c, 0x24, 0x8f, 0xbd, 0x69, 0xf8, 0x59, 0x0e, - 0x6a, 0x22, 0x17, 0xb2, 0x84, 0x06, 0xb6, 0x65, 0xe1, 0x81, 0xaf, 0xba, 0xd8, 0x77, 0x1f, 0x07, - 0x83, 0xcd, 0x81, 0x0a, 0x81, 0x91, 0xb5, 0x40, 0x9d, 0xa5, 0xf0, 0x79, 0x4d, 0x51, 0x29, 0x13, - 0x00, 0xe1, 0x44, 0x36, 0xb8, 0x2f, 0x30, 0x76, 0x34, 0xd3, 0x38, 0xc6, 0x6a, 0xe2, 0x95, 0xd9, - 0x42, 0x88, 0xe9, 0x70, 0x04, 0xda, 0x86, 0x4b, 0x63, 0xc3, 0x32, 0xc6, 0x93, 0xb1, 0x1a, 0xea, - 0x2d, 0xf1, 0xfb, 0xa2, 0xaa, 0x6c, 0x86, 0x5e, 0xe2, 0x54, 0x2d, 0x91, 0x28, 0xe0, 0x22, 0xff, - 0x34, 0x0f, 0x55, 0xa1, 0x7b, 0xff, 0x4b, 0xbb, 0x41, 0xe3, 0x60, 0x78, 0x64, 0xfb, 0x86, 0x46, - 0x8c, 0x53, 0x24, 0x1c, 0x53, 0x44, 0x14, 0xe1, 0xee, 0x07, 0x62, 0x46, 0x0f, 0xa0, 0x98, 0x42, - 0x66, 0x3d, 0x80, 0x62, 0x0a, 0x19, 0x96, 0xe5, 0xff, 0xcc, 0x41, 0x25, 0x3c, 0x08, 0xa5, 0xbd, - 0x96, 0x5c, 0x86, 0xd7, 0x72, 0x11, 0x80, 0x11, 0x09, 0x8f, 0x3f, 0x98, 0x57, 0xd5, 0xe3, 0x3c, - 0xc6, 0xfe, 0x44, 0xd5, 0x0d, 0x6f, 0x60, 0x1f, 0x63, 0xf7, 0x31, 0x8f, 0xef, 0xd4, 0xc6, 0xfe, - 0x64, 0x3b, 0x80, 0x11, 0x8f, 0x80, 0xec, 0xaa, 0x64, 0x3c, 0xc7, 0xb6, 0x1e, 0x3c, 0x44, 0xa8, - 0x72, 0xd8, 0x9e, 0xad, 0x63, 0x62, 0xe7, 0xb9, 0x27, 0x17, 0xdf, 0xe9, 0xea, 0x0c, 0xda, 0xca, - 0x7e, 0x24, 0x56, 0x0a, 0x1e, 0x64, 0x05, 0x8f, 0xc4, 0xc8, 0x46, 0xe8, 0x0f, 0x1c, 0x75, 0xec, - 0x79, 0xdc, 0xa3, 0x2d, 0xf9, 0x03, 0x67, 0xcf, 0xf3, 0xe4, 0x0f, 0xa1, 0x2a, 0x1c, 0xe6, 0xd0, - 0x4d, 0x58, 0x14, 0x4f, 0x7e, 0x71, 0x5f, 0x63, 0x41, 0x38, 0xe9, 0x31, 0x47, 0x43, 0xfe, 0x8f, - 0x1c, 0x34, 0x12, 0xc7, 0xb9, 0xd3, 0x5d, 0x20, 0x7e, 0x28, 0x8c, 0x54, 0xac, 0xae, 0x54, 0x39, - 0x8c, 0x4e, 0xdf, 0x65, 0xa8, 0x1e, 0x61, 0xd3, 0xc1, 0xae, 0x6a, 0x5b, 0x66, 0x30, 0x6c, 0xc0, - 0x40, 0x5d, 0xcb, 0xa4, 0x5b, 0x9a, 0x8e, 0x87, 0xd8, 0x75, 0x35, 0x93, 0x31, 0x61, 0xcf, 0xd3, - 0x6a, 0x01, 0x90, 0x72, 0xb9, 0x05, 0x4b, 0xf4, 0x51, 0x17, 0x7f, 0x46, 0xaa, 0x06, 0xf2, 0xb0, - 0xe0, 0xd3, 0xa2, 0x88, 0x6b, 0x73, 0xd9, 0x5e, 0x83, 0x05, 0xd3, 0xb6, 0x46, 0x26, 0x7d, 0x34, - 0x16, 0xd0, 0x97, 0xd8, 0xf6, 0x1b, 0x22, 0x38, 0xb1, 0xfc, 0x36, 0xac, 0xee, 0x39, 0x89, 0x7e, - 0x73, 0x7b, 0x31, 0xb5, 0xf7, 0xf2, 0xdf, 0xe4, 0x60, 0x25, 0x55, 0x8b, 0xad, 0xce, 0xe9, 0x43, - 0x26, 0xee, 0x83, 0xec, 0x82, 0x28, 0xda, 0x39, 0xe2, 0x7b, 0x1d, 0x1f, 0x2a, 0x61, 0xaf, 0x7b, - 0x03, 0x16, 0xf9, 0xa3, 0x33, 0xd7, 0x38, 0x54, 0x43, 0x36, 0xc5, 0xe0, 0x6b, 0x0b, 0xbd, 0x3b, - 0xa4, 0x21, 0x98, 0x70, 0x23, 0x6a, 0x08, 0xe4, 0x74, 0x4f, 0x62, 0xe3, 0x55, 0x0b, 0x48, 0x0f, - 0xc8, 0x94, 0xff, 0x38, 0x07, 0x0b, 0xa9, 0x6e, 0xa0, 0x6f, 0x26, 0x8c, 0xf2, 0x55, 0x61, 0x1f, - 0xcb, 0x1e, 0xa9, 0xd0, 0x3e, 0x6f, 0xc6, 0xed, 0xf3, 0x95, 0x53, 0x6a, 0xc6, 0x4c, 0x75, 0x0b, - 0xea, 0x3c, 0x14, 0xc0, 0x87, 0x7e, 0xda, 0xd9, 0x57, 0x18, 0xdd, 0x7c, 0x7c, 0x4a, 0x7e, 0x37, - 0x07, 0x35, 0xce, 0x23, 0x7c, 0x3e, 0xf9, 0x6c, 0x2c, 0x88, 0xc2, 0xfa, 0xb6, 0x4f, 0x0c, 0x01, - 0x7f, 0x88, 0x4b, 0x97, 0x1e, 0x05, 0xd1, 0x58, 0x03, 0x59, 0xc2, 0x9c, 0x40, 0x8c, 0xe0, 0xd6, - 0x95, 0x3a, 0xa3, 0x09, 0xa2, 0x70, 0xff, 0x90, 0x87, 0x75, 0xbe, 0x12, 0x4d, 0xf6, 0xa4, 0x9c, - 0x85, 0x0f, 0x83, 0x7d, 0xe8, 0x75, 0x40, 0x9a, 0xf9, 0x95, 0xf6, 0xd8, 0x23, 0x3e, 0x9f, 0xa3, - 0xb9, 0x58, 0x1d, 0x47, 0x5f, 0xce, 0x30, 0xcc, 0x16, 0x43, 0xec, 0x61, 0x1d, 0xdd, 0x82, 0x65, - 0x63, 0x64, 0xd9, 0x2e, 0xf1, 0x38, 0xa9, 0x64, 0xc1, 0x85, 0x0f, 0xbf, 0x03, 0x67, 0xc8, 0x96, - 0x47, 0x44, 0x64, 0x97, 0x3c, 0xe4, 0xcc, 0x10, 0x84, 0xec, 0xc3, 0x26, 0xe8, 0x82, 0xa7, 0x67, - 0x06, 0xa6, 0x5d, 0xab, 0x01, 0x05, 0x6f, 0x8a, 0x0a, 0xec, 0x76, 0xc8, 0x29, 0xf1, 0x42, 0xa8, - 0x78, 0xaa, 0x61, 0x69, 0x03, 0x9f, 0x58, 0x35, 0x5a, 0x3d, 0x88, 0x58, 0xaf, 0x86, 0x04, 0x1d, - 0x8e, 0xa7, 0xb5, 0xa9, 0xf1, 0x62, 0x83, 0xa9, 0x6a, 0xc6, 0xc8, 0x09, 0x02, 0xc4, 0xfc, 0x63, - 0x20, 0x63, 0xe4, 0xa0, 0x0f, 0x60, 0x8d, 0x77, 0xc6, 0xc2, 0x27, 0xbe, 0x4a, 0x43, 0xff, 0x23, - 0x47, 0x1d, 0x63, 0xdf, 0x35, 0x06, 0x7c, 0x8d, 0xae, 0x30, 0x8a, 0x7d, 0x7c, 0xe2, 0xdf, 0xb7, - 0x9d, 0xce, 0xc8, 0xd9, 0xa3, 0x58, 0xf9, 0xef, 0xf3, 0xb0, 0x96, 0x39, 0xac, 0x6c, 0xbe, 0xff, - 0x6f, 0x54, 0x9f, 0x6b, 0x54, 0x7f, 0x3f, 0x07, 0xcb, 0x99, 0xa3, 0x8a, 0x3e, 0x4c, 0xd8, 0x81, - 0x6b, 0xa9, 0xa0, 0x61, 0x96, 0x76, 0x87, 0xb6, 0xe0, 0x83, 0xb8, 0x2d, 0x78, 0xf9, 0x8c, 0xda, - 0x31, 0x7b, 0x70, 0x1b, 0x56, 0x1e, 0x78, 0x98, 0x9e, 0xc4, 0x1d, 0x93, 0x7e, 0x06, 0xe4, 0x9d, - 0x69, 0x93, 0x6f, 0xc1, 0x72, 0xb2, 0xce, 0x19, 0x16, 0x59, 0xfe, 0x3e, 0x00, 0x39, 0xf1, 0x73, - 0xd6, 0x1b, 0xb0, 0xc0, 0x82, 0x0f, 0x63, 0xce, 0x83, 0x1c, 0xf1, 0x58, 0x8d, 0x06, 0x45, 0x04, - 0xbc, 0x5b, 0x34, 0x1c, 0x32, 0xd6, 0x4e, 0xa8, 0x4b, 0x14, 0x5c, 0x12, 0xd1, 0xad, 0x8b, 0x03, - 0x59, 0x68, 0xf2, 0x7b, 0x50, 0x69, 0x87, 0xc7, 0xa8, 0x17, 0xce, 0x5d, 0x85, 0x22, 0xe1, 0x8e, - 0x5e, 0x4f, 0x4c, 0xd3, 0x52, 0x3c, 0xc0, 0x9d, 0x98, 0x95, 0xe9, 0x6f, 0x82, 0x43, 0x51, 0x83, - 0x49, 0xb8, 0x05, 0xd0, 0x89, 0x46, 0x27, 0x25, 0x53, 0x2e, 0x43, 0xa6, 0xb7, 0xa0, 0xd2, 0x09, - 0x7b, 0x7c, 0xae, 0x1a, 0x2a, 0x14, 0x3b, 0x67, 0xf4, 0xa2, 0xf3, 0x2c, 0xbd, 0xe8, 0x24, 0x7b, - 0xf1, 0x8b, 0x1c, 0x48, 0x49, 0xbd, 0x40, 0xef, 0x27, 0x5a, 0x13, 0x36, 0xaa, 0x6c, 0xbd, 0x0b, - 0x5b, 0x7e, 0x37, 0xde, 0xf2, 0xe5, 0xe9, 0x15, 0x63, 0x8f, 0x08, 0x64, 0x28, 0xe2, 0xc3, 0x91, - 0x93, 0xfe, 0x94, 0x8f, 0x8c, 0xba, 0x42, 0x71, 0x84, 0xc6, 0x20, 0x34, 0xa9, 0xcf, 0xe5, 0x3a, - 0x94, 0x86, 0xe0, 0xe4, 0xbb, 0x7c, 0x67, 0xe9, 0x6b, 0xee, 0x08, 0xfb, 0x7b, 0x78, 0x7c, 0x88, - 0x5d, 0xef, 0xc8, 0x10, 0x26, 0x29, 0xee, 0x51, 0xe5, 0xd2, 0x1e, 0x95, 0xdc, 0xe2, 0x66, 0x34, - 0xc9, 0x23, 0x9c, 0xb5, 0xb3, 0x59, 0x84, 0x46, 0x23, 0xc9, 0xe3, 0x4c, 0xa3, 0x91, 0x2d, 0xf8, - 0x79, 0x8d, 0x46, 0xa6, 0xc8, 0xc1, 0x4c, 0x7f, 0x1f, 0x2e, 0xed, 0xda, 0xd6, 0x68, 0x97, 0x78, - 0x40, 0xcf, 0xe8, 0xd0, 0x9d, 0xc3, 0x9d, 0x95, 0xff, 0x31, 0x07, 0x17, 0xa7, 0xf1, 0xff, 0x3a, - 0x5d, 0xbf, 0x0d, 0x58, 0xa0, 0x01, 0xac, 0x98, 0x7c, 0xcc, 0xef, 0x68, 0x10, 0x84, 0x22, 0xb8, - 0xdc, 0x77, 0x60, 0x2d, 0x45, 0xeb, 0xaa, 0xf8, 0xc4, 0x31, 0xdc, 0xd0, 0x65, 0x5e, 0x4d, 0x54, - 0x72, 0xdb, 0x0c, 0x2d, 0xff, 0x41, 0x0e, 0x9a, 0xd3, 0x3a, 0x88, 0x3e, 0x4e, 0xcc, 0xab, 0xf0, - 0x95, 0xd0, 0xe9, 0x83, 0x1e, 0x4e, 0xed, 0x87, 0xf1, 0xa9, 0xbd, 0x7e, 0x36, 0x83, 0xd8, 0xec, - 0xfe, 0x64, 0x16, 0xe6, 0xb8, 0x7f, 0x87, 0x3e, 0x81, 0xc5, 0xb1, 0xa3, 0xa6, 0x6e, 0xa7, 0x98, - 0x64, 0xeb, 0xa7, 0x38, 0x9d, 0xca, 0xc2, 0x38, 0xe5, 0xee, 0xbe, 0x19, 0xf6, 0x8c, 0x09, 0xb6, - 0x9a, 0xba, 0x9e, 0x4a, 0x74, 0x24, 0x79, 0x75, 0x59, 0x38, 0xf7, 0xd5, 0xe5, 0x67, 0xb0, 0x1a, - 0x1c, 0xc9, 0xf8, 0xe6, 0xc7, 0x6f, 0xa2, 0x83, 0x68, 0xe9, 0xe5, 0x33, 0x36, 0x49, 0x65, 0xd9, - 0xcd, 0xdc, 0xaa, 0xef, 0x03, 0x9a, 0x78, 0x38, 0xda, 0x5a, 0x98, 0xbd, 0x9d, 0x4d, 0xde, 0x3f, - 0x25, 0x4d, 0x94, 0x22, 0x4d, 0x92, 0x96, 0x31, 0x75, 0x47, 0x50, 0x4a, 0xf6, 0x6e, 0xfa, 0x1d, - 0x41, 0xd8, 0x3d, 0x9f, 0x2e, 0x53, 0x75, 0x1c, 0xae, 0x53, 0x7e, 0xb3, 0x79, 0xf9, 0x8c, 0xe5, - 0xcc, 0xbb, 0x97, 0x32, 0x2a, 0x1a, 0xac, 0x93, 0x73, 0x9b, 0xca, 0x4e, 0x74, 0xa9, 0x79, 0x67, - 0x37, 0xa1, 0xf2, 0xd9, 0x0a, 0xa5, 0x34, 0xcd, 0x69, 0xfa, 0x1d, 0xbb, 0x77, 0xac, 0x9c, 0xe3, - 0xde, 0xb1, 0x1d, 0x7e, 0xf5, 0x2d, 0xb8, 0x26, 0x7c, 0x51, 0x07, 0xcb, 0x9f, 0x17, 0xd1, 0x05, - 0x28, 0xd3, 0x10, 0xef, 0x58, 0x3b, 0xe1, 0x96, 0x65, 0x8e, 0x94, 0xf7, 0xb4, 0x13, 0x79, 0x9b, - 0x7e, 0x04, 0x10, 0xf7, 0x56, 0x9e, 0x9d, 0xcb, 0x17, 0x50, 0x0e, 0xb8, 0xa0, 0xb7, 0x12, 0x2b, - 0xb5, 0x99, 0xee, 0x46, 0x42, 0xa1, 0xdf, 0x88, 0xaf, 0xcc, 0xd5, 0x74, 0x85, 0xd8, 0x4a, 0x9c, - 0x40, 0x89, 0x3f, 0xb4, 0x58, 0x87, 0x8a, 0xe1, 0xa8, 0xb1, 0xb7, 0x16, 0x65, 0x23, 0x78, 0x85, - 0xf1, 0x0a, 0x34, 0xc6, 0x9a, 0xf7, 0x05, 0xf7, 0xab, 0xd5, 0x31, 0xff, 0x92, 0xb9, 0xae, 0xd4, - 0x09, 0x98, 0xf9, 0xd4, 0x7b, 0x86, 0x95, 0xa2, 0xd3, 0x4e, 0xf8, 0xc9, 0x4b, 0xa4, 0xd3, 0x4e, - 0xe4, 0x9f, 0xe4, 0x00, 0xa2, 0x27, 0xef, 0xbf, 0xe2, 0x77, 0x09, 0x04, 0x66, 0x1a, 0x9e, 0x4f, - 0x5f, 0xe6, 0x55, 0x14, 0xfa, 0x9b, 0x3e, 0xb5, 0x8e, 0x3f, 0xbb, 0x90, 0x92, 0x6a, 0x2f, 0xbc, - 0xb5, 0xd8, 0x81, 0xf2, 0x9e, 0xe6, 0x0f, 0x8e, 0x88, 0x30, 0xd7, 0x63, 0xc2, 0x08, 0xee, 0x08, - 0xa5, 0x38, 0xe3, 0x13, 0x89, 0x87, 0x50, 0x8b, 0x9d, 0x33, 0x6e, 0xc6, 0x98, 0x09, 0xcb, 0x57, - 0xa4, 0x12, 0x78, 0xae, 0x40, 0x49, 0x38, 0xbb, 0xd4, 0x15, 0x5e, 0x92, 0xff, 0xa5, 0x08, 0xb0, - 0x65, 0x5b, 0xba, 0xc1, 0x6c, 0xc4, 0x2d, 0xe0, 0x1f, 0xe5, 0xa9, 0xd1, 0x77, 0x06, 0x28, 0x21, - 0xe9, 0x01, 0xf6, 0x95, 0x0a, 0xa3, 0x22, 0xdd, 0x7a, 0x17, 0x6a, 0xe1, 0xf5, 0x0c, 0xa9, 0x94, - 0x9f, 0x5a, 0x29, 0x7c, 0x00, 0x46, 0xaa, 0x7d, 0x0b, 0xe6, 0x13, 0x87, 0xaa, 0x42, 0x32, 0xba, - 0x2b, 0x76, 0x45, 0xa9, 0x69, 0x62, 0xf7, 0x6f, 0x43, 0x35, 0xa8, 0x4d, 0xda, 0x2c, 0x4e, 0x17, - 0x94, 0x55, 0x23, 0x2d, 0xbe, 0x17, 0x7e, 0x81, 0xec, 0x3f, 0xa6, 0xb5, 0x66, 0xa7, 0xd6, 0xaa, - 0x85, 0x84, 0xa4, 0xe2, 0x47, 0xb0, 0x40, 0x4e, 0x4c, 0xf1, 0xca, 0xa5, 0xa9, 0x95, 0x1b, 0xf8, - 0xc4, 0xdf, 0x12, 0xeb, 0x5f, 0x86, 0xaa, 0xeb, 0x7c, 0x61, 0x10, 0x53, 0x34, 0x31, 0x7d, 0x6a, - 0xe6, 0x66, 0x15, 0x70, 0xd9, 0x17, 0x51, 0x13, 0xd3, 0x47, 0x1f, 0x02, 0x44, 0x9f, 0x39, 0xf1, - 0xdb, 0x65, 0xe1, 0xf2, 0x24, 0x9a, 0x1f, 0x6e, 0x11, 0xc9, 0xb4, 0x56, 0xc2, 0xaf, 0xa0, 0xd0, - 0x5d, 0x58, 0x34, 0x89, 0x35, 0x4c, 0x48, 0x58, 0x99, 0x2a, 0xe1, 0x02, 0x25, 0x17, 0x65, 0x94, - 0x8f, 0xa0, 0x12, 0xf2, 0x46, 0x8b, 0xd0, 0x50, 0xba, 0x0f, 0xfa, 0x6d, 0xb5, 0xff, 0x79, 0x2f, - 0x7c, 0xfb, 0xb9, 0x0a, 0x8b, 0x02, 0xb0, 0xb3, 0xdf, 0x6f, 0x2b, 0xfb, 0xad, 0x5d, 0x29, 0x97, - 0x40, 0xb4, 0x1f, 0x71, 0x44, 0x1e, 0x2d, 0x81, 0x24, 0x20, 0xf8, 0xe7, 0xbc, 0xf2, 0x10, 0x1a, - 0x61, 0xcb, 0x2d, 0xf6, 0x2d, 0xfd, 0xad, 0x98, 0x32, 0x5f, 0x14, 0x7b, 0x1e, 0x23, 0x14, 0xf4, - 0xf9, 0x0a, 0x54, 0x83, 0xde, 0x1a, 0xe1, 0x97, 0x61, 0x22, 0x48, 0xde, 0x87, 0xca, 0x1e, 0xd6, - 0x79, 0x0b, 0xaf, 0xc5, 0x5a, 0x58, 0x15, 0x2f, 0x5d, 0xf4, 0x14, 0xef, 0x25, 0x98, 0x3d, 0xd6, - 0xcc, 0x49, 0xf0, 0xe1, 0x2c, 0x2b, 0xc8, 0x2a, 0x34, 0x5a, 0x5e, 0xcf, 0xc5, 0x0e, 0xb6, 0x02, - 0xae, 0x12, 0x14, 0x34, 0xcf, 0xe2, 0xce, 0x2f, 0xf9, 0x49, 0x96, 0x19, 0xa1, 0xd0, 0xc2, 0xdb, - 0x0c, 0x56, 0x42, 0x32, 0xd4, 0xc9, 0xde, 0x6b, 0xe2, 0xa1, 0xaf, 0x8e, 0x6d, 0xcf, 0xe7, 0x2e, - 0x5c, 0x75, 0xe2, 0xe1, 0x5d, 0x3c, 0xf4, 0xf7, 0x6c, 0xfa, 0x9a, 0xba, 0xce, 0x1f, 0x34, 0x72, - 0xf6, 0xa7, 0x7e, 0x84, 0xe8, 0x61, 0x73, 0xc8, 0xdd, 0x44, 0xfa, 0x5b, 0xbe, 0x0e, 0x8d, 0x5d, - 0x1a, 0x8f, 0x76, 0xf1, 0x90, 0x33, 0x08, 0x3b, 0xc2, 0x6f, 0x5c, 0x58, 0x47, 0xfe, 0xae, 0x00, - 0x73, 0x8c, 0xc0, 0x8b, 0x5e, 0xfe, 0x68, 0x2c, 0x67, 0x42, 0xca, 0x50, 0x52, 0xa5, 0x60, 0xd4, - 0xfc, 0xe5, 0x0f, 0xe7, 0xfd, 0x1e, 0x54, 0xa2, 0xcb, 0xc8, 0x7c, 0xf2, 0xc9, 0x4f, 0x62, 0xe2, - 0x94, 0x88, 0x16, 0x5d, 0x83, 0xc2, 0x98, 0xfb, 0xb0, 0xb1, 0x43, 0x59, 0x38, 0x13, 0x0a, 0xc1, - 0xa3, 0xf7, 0x01, 0xc8, 0x0a, 0x67, 0xe3, 0xcd, 0x17, 0xf8, 0x85, 0x98, 0x6d, 0x10, 0xa7, 0x82, - 0xae, 0x73, 0x06, 0x40, 0x1f, 0x41, 0x3d, 0xb6, 0x5c, 0xf9, 0x3a, 0x3f, 0x45, 0xba, 0x9a, 0xb8, - 0x62, 0xd1, 0x2d, 0x98, 0xe3, 0x2f, 0x4e, 0xf9, 0x22, 0x17, 0xd4, 0x25, 0x36, 0x41, 0x4a, 0x40, - 0x47, 0x84, 0xe5, 0xb7, 0x03, 0x2e, 0x1e, 0x72, 0x3f, 0xe6, 0x82, 0xe8, 0x6a, 0xc4, 0xe6, 0x25, - 0xb8, 0x38, 0x70, 0xf1, 0x10, 0xdd, 0x85, 0x46, 0x62, 0xed, 0x72, 0x4f, 0xe5, 0x14, 0x71, 0xe7, - 0xe3, 0xcb, 0x57, 0xfe, 0x41, 0x0e, 0x2a, 0xe1, 0x27, 0x20, 0xe1, 0xee, 0x91, 0x13, 0x36, 0xb2, - 0x77, 0x00, 0x06, 0xa1, 0x11, 0xe1, 0xb3, 0xb5, 0x94, 0x65, 0x60, 0x14, 0x81, 0x0e, 0xbd, 0x06, - 0x73, 0x4c, 0x2d, 0x3c, 0x3e, 0x5b, 0xe2, 0xa3, 0x2c, 0x86, 0x50, 0x02, 0x0a, 0xf9, 0x53, 0x28, - 0x71, 0x07, 0x36, 0x4b, 0x80, 0xf8, 0x47, 0x64, 0xf9, 0xf3, 0x7d, 0x44, 0xf6, 0x4f, 0x39, 0x90, - 0x92, 0xaf, 0xa1, 0xd0, 0x8d, 0xd8, 0x4a, 0x5e, 0x4a, 0xbe, 0x9b, 0x12, 0x96, 0xb1, 0x98, 0x73, - 0x21, 0x7f, 0x8e, 0x9c, 0x0b, 0x59, 0x09, 0x7d, 0xc4, 0x0f, 0xab, 0x8a, 0x67, 0x7d, 0x58, 0x85, - 0xde, 0x84, 0x39, 0x1d, 0x0f, 0x35, 0x62, 0xe4, 0x67, 0x4f, 0x5b, 0x48, 0x01, 0x95, 0xfc, 0x7b, - 0x39, 0x28, 0x28, 0xb6, 0x86, 0xe6, 0x21, 0xaf, 0x05, 0xa1, 0x8f, 0xbc, 0xe6, 0xa1, 0x97, 0x80, - 0x6f, 0xb0, 0x26, 0x0e, 0x1c, 0xa2, 0x08, 0x40, 0x8c, 0xcc, 0x58, 0xa3, 0x28, 0xfe, 0x22, 0x94, - 0x95, 0x84, 0x27, 0x98, 0xc5, 0xd8, 0x93, 0xd6, 0xe0, 0x31, 0xe4, 0xec, 0xe9, 0x9f, 0x82, 0xcb, - 0xd7, 0xd9, 0xc3, 0x5c, 0x5b, 0x3b, 0xeb, 0xf3, 0x6e, 0xf6, 0x25, 0x2b, 0x25, 0x8c, 0xbe, 0x64, - 0x75, 0x6d, 0x2d, 0xe3, 0x4b, 0x56, 0x42, 0x44, 0x51, 0xb2, 0x07, 0x85, 0x87, 0xee, 0x30, 0x53, - 0x3b, 0xe6, 0x21, 0xef, 0xb2, 0x33, 0x6f, 0x4d, 0xc9, 0xbb, 0x3a, 0x75, 0x19, 0xd9, 0x23, 0x39, - 0x97, 0x39, 0x5f, 0x35, 0xa5, 0xcc, 0x00, 0x0a, 0xcd, 0xf9, 0xc1, 0x9f, 0xe0, 0xb9, 0x3e, 0x9d, - 0x93, 0x9a, 0x52, 0x66, 0x00, 0xc5, 0xe7, 0xaf, 0x99, 0xd8, 0xf3, 0xaf, 0xbc, 0xa1, 0xcb, 0xbf, - 0xc8, 0x41, 0x89, 0x7d, 0x35, 0x92, 0x1a, 0xe3, 0x75, 0xa8, 0x44, 0x81, 0x59, 0x9e, 0x1f, 0xc4, - 0x0d, 0x22, 0xb1, 0x97, 0xa1, 0x4a, 0xbc, 0x3d, 0x6c, 0xb1, 0x0b, 0xb6, 0x02, 0xdb, 0xb2, 0x19, - 0x88, 0x5e, 0xb0, 0xbd, 0x0a, 0x12, 0x27, 0xe0, 0x36, 0x99, 0x2b, 0x48, 0x45, 0x69, 0x30, 0x78, - 0x2b, 0x00, 0xc7, 0x5e, 0xb8, 0xce, 0x26, 0x5e, 0xb8, 0xbe, 0x9e, 0x79, 0x26, 0xe3, 0xd7, 0x50, - 0xc9, 0x73, 0x97, 0xfc, 0xf3, 0x1c, 0x54, 0xe8, 0xcb, 0xde, 0x8e, 0x35, 0xb4, 0xbf, 0x96, 0x47, - 0xc5, 0xd7, 0xa1, 0x61, 0x4d, 0xc6, 0xaa, 0xf0, 0xa0, 0x9b, 0x5f, 0xdb, 0xce, 0x5b, 0x93, 0xb1, - 0xf8, 0x20, 0xfe, 0x02, 0x94, 0x2d, 0x1e, 0xb3, 0x0b, 0x5e, 0x09, 0x58, 0x2c, 0x5c, 0x87, 0xae, - 0x42, 0x8d, 0xa0, 0xc2, 0x27, 0x1b, 0xec, 0x5e, 0xb6, 0x6a, 0x4d, 0xc6, 0x2d, 0x0e, 0x92, 0xbf, - 0x45, 0x3f, 0x1c, 0x52, 0x8c, 0x43, 0xd2, 0x91, 0x40, 0xdb, 0x82, 0xb7, 0xb0, 0xa9, 0xef, 0x26, - 0xc3, 0x2e, 0xb3, 0xb7, 0xb0, 0xf2, 0x87, 0x34, 0xd1, 0x58, 0x58, 0x9b, 0xab, 0xe0, 0x79, 0xab, - 0x6f, 0xfc, 0x32, 0x0f, 0xa5, 0x7b, 0xac, 0xbb, 0xb3, 0x90, 0x53, 0xa5, 0x19, 0x04, 0x50, 0xec, - 0xf4, 0x8e, 0xdf, 0x91, 0x9e, 0x3e, 0x29, 0xf2, 0xdf, 0x9b, 0xd2, 0xd3, 0x27, 0x65, 0x54, 0x87, - 0x39, 0x02, 0x57, 0xf7, 0xb6, 0xa4, 0x1f, 0x3c, 0x29, 0xf2, 0xe2, 0x26, 0x2b, 0x96, 0x51, 0x03, - 0x2a, 0x0c, 0xdb, 0xdb, 0x3d, 0x90, 0x7e, 0xf8, 0xa4, 0xc8, 0x01, 0x9b, 0x01, 0xa0, 0x8c, 0xe6, - 0xa1, 0x4c, 0x29, 0x1e, 0xf6, 0xf6, 0xa5, 0x27, 0x4f, 0x8b, 0xbc, 0xbc, 0xc9, 0xcb, 0x65, 0xb4, - 0x00, 0xd5, 0x00, 0x4f, 0x98, 0x3e, 0x7d, 0x5a, 0xe4, 0xa0, 0xcd, 0x08, 0x54, 0x26, 0x12, 0x3d, - 0x24, 0x1c, 0xff, 0xfa, 0x89, 0x4e, 0x7e, 0xb7, 0x49, 0xed, 0x9f, 0x3f, 0xd1, 0x51, 0x05, 0x0a, - 0x4a, 0x7f, 0x4b, 0xfa, 0xe1, 0xd3, 0x22, 0x92, 0x00, 0x28, 0xa3, 0xf6, 0xfe, 0x56, 0xab, 0x27, - 0xfd, 0xce, 0x93, 0x00, 0xb2, 0x19, 0x42, 0xca, 0x68, 0x09, 0xe6, 0xef, 0xed, 0x76, 0x3f, 0x53, - 0x0f, 0x7a, 0xed, 0x2d, 0x95, 0x76, 0xf7, 0x47, 0x4f, 0x8b, 0x29, 0xe8, 0xa6, 0xf4, 0xa3, 0xa7, - 0x65, 0xd4, 0x04, 0x14, 0xa7, 0xa5, 0x22, 0xff, 0xf8, 0x69, 0x31, 0x85, 0xd9, 0xe4, 0x98, 0x32, - 0x5a, 0x01, 0x29, 0xc2, 0xec, 0xde, 0xe6, 0x70, 0x1d, 0xcd, 0x43, 0xa9, 0xdb, 0x6b, 0x7d, 0xfa, - 0xa0, 0x2d, 0xfd, 0xdb, 0xd3, 0x3f, 0x7f, 0x52, 0xdc, 0xd8, 0x82, 0x72, 0xa0, 0xa0, 0x08, 0xa0, - 0xb4, 0xb3, 0xdb, 0xbd, 0xdb, 0xda, 0x95, 0x66, 0xa2, 0x8c, 0x2f, 0xf4, 0xa5, 0x4d, 0x6b, 0xfb, - 0x3b, 0x6a, 0x67, 0x5f, 0xca, 0xa3, 0x2a, 0xcc, 0x91, 0xdf, 0xdd, 0x07, 0x7d, 0x96, 0x0a, 0xe6, - 0xa1, 0x72, 0x4f, 0x2a, 0x6e, 0xec, 0xc6, 0x9e, 0xf4, 0xb3, 0x08, 0x07, 0x92, 0xa0, 0xb6, 0xdb, - 0xed, 0x7e, 0xf2, 0xa0, 0xa7, 0xb6, 0x1f, 0xb5, 0xb6, 0xfa, 0xd2, 0x0c, 0x5a, 0x80, 0x3a, 0x87, - 0xec, 0x76, 0xf7, 0x77, 0xda, 0x8a, 0x94, 0x43, 0x08, 0xe6, 0x39, 0xe8, 0xe0, 0x7e, 0x57, 0xe9, - 0xb7, 0x15, 0x29, 0xbf, 0xe1, 0x43, 0x55, 0x38, 0x10, 0xd2, 0x87, 0x3e, 0x4a, 0xfb, 0x5e, 0xe7, - 0x91, 0x34, 0x83, 0x6a, 0x50, 0xde, 0x6f, 0x77, 0x76, 0xee, 0xdf, 0xed, 0x92, 0xca, 0x73, 0x50, - 0xe8, 0xb7, 0x76, 0xb8, 0x54, 0x07, 0x6a, 0xaf, 0xd5, 0xbf, 0x2f, 0x15, 0x50, 0x1d, 0x2a, 0x5b, - 0xdd, 0xbd, 0xbd, 0x07, 0xfb, 0x9d, 0xfe, 0xe7, 0x12, 0x99, 0xc2, 0x7a, 0xfb, 0x51, 0x5f, 0x8d, - 0x40, 0xb3, 0xc4, 0xa1, 0xde, 0x6d, 0x29, 0x3b, 0x6d, 0x01, 0x58, 0xda, 0x78, 0x15, 0x2a, 0xe1, - 0xc9, 0x8f, 0xbe, 0x36, 0xdc, 0xff, 0x5c, 0x7c, 0x76, 0x08, 0x50, 0xea, 0xec, 0x3f, 0x6c, 0x2b, - 0x7d, 0x29, 0xbf, 0xb1, 0x01, 0x52, 0xf2, 0x5c, 0x87, 0x4a, 0x90, 0x6f, 0x7f, 0x2a, 0xcd, 0x90, - 0xbf, 0x3b, 0x6d, 0x29, 0x47, 0xfe, 0xee, 0xb6, 0xa5, 0xfc, 0xc6, 0x9b, 0xfc, 0x86, 0x9f, 0xfb, - 0x69, 0xd1, 0x83, 0x46, 0x32, 0xaa, 0x5b, 0x5b, 0xed, 0x5e, 0x9f, 0x31, 0x57, 0xda, 0xdf, 0x69, - 0x6f, 0x11, 0xe6, 0x0f, 0x60, 0x31, 0xc3, 0xcf, 0x26, 0xdd, 0x08, 0xa5, 0x55, 0x5b, 0xdb, 0xdb, - 0xd2, 0x0c, 0x71, 0xe8, 0x23, 0x90, 0xd2, 0xde, 0xeb, 0x3e, 0x24, 0x0d, 0x2f, 0xc3, 0x82, 0x08, - 0xe5, 0x2f, 0x25, 0x37, 0xde, 0x80, 0x7a, 0xcc, 0xb9, 0x26, 0x63, 0xb6, 0xd7, 0xde, 0x56, 0xf7, - 0xba, 0x84, 0x55, 0x03, 0xaa, 0xa4, 0x10, 0x90, 0xe7, 0x36, 0x5e, 0x07, 0x88, 0x76, 0xf0, 0x30, - 0xbb, 0x16, 0x19, 0x84, 0xbd, 0x5e, 0x57, 0xe1, 0x32, 0xb7, 0x1f, 0xd1, 0xdf, 0xf9, 0xdb, 0xff, - 0x7e, 0x05, 0xca, 0x3b, 0x64, 0x81, 0xb7, 0x1c, 0x03, 0xed, 0x42, 0x55, 0xf8, 0x0e, 0x10, 0xbd, - 0x14, 0xf3, 0x2b, 0x12, 0x9f, 0x17, 0xae, 0x5d, 0x9c, 0x82, 0xe5, 0xdf, 0x25, 0xcc, 0xa0, 0x0e, - 0x40, 0xf4, 0xa5, 0x20, 0x5a, 0x17, 0xc9, 0x13, 0x1f, 0x15, 0xae, 0xbd, 0x94, 0x8d, 0x0c, 0x59, - 0xdd, 0x83, 0x4a, 0xf8, 0x7d, 0x24, 0x12, 0xce, 0xe8, 0xc9, 0x0f, 0x29, 0xd7, 0xd6, 0x33, 0x71, - 0x21, 0x9f, 0x5d, 0xa8, 0x0a, 0xb9, 0xe9, 0xc4, 0x0e, 0xa6, 0x93, 0xdd, 0x89, 0x1d, 0xcc, 0x4a, - 0x68, 0x37, 0x83, 0x1e, 0xc0, 0x7c, 0x3c, 0x2b, 0x1d, 0xba, 0x2c, 0x06, 0x46, 0x32, 0x92, 0xdd, - 0xad, 0x5d, 0x99, 0x4e, 0x20, 0xb2, 0x8d, 0x27, 0x9b, 0x13, 0xd9, 0x66, 0x26, 0xbb, 0x13, 0xd9, - 0x66, 0xe7, 0xa9, 0x63, 0x7d, 0x17, 0x32, 0x3f, 0x8a, 0x7d, 0x4f, 0x27, 0x9b, 0x14, 0xfb, 0x9e, - 0x91, 0x2e, 0x52, 0x9e, 0x41, 0x0a, 0xd4, 0x63, 0x69, 0xd9, 0xd0, 0xa5, 0xd8, 0xb6, 0x99, 0xe6, - 0x78, 0x79, 0x2a, 0x3e, 0xe4, 0xf9, 0xff, 0x61, 0x21, 0x95, 0xee, 0x0d, 0xc9, 0x67, 0xa7, 0x9d, - 0x5b, 0xfb, 0xc6, 0xa9, 0x34, 0x21, 0xff, 0xff, 0x07, 0x52, 0x32, 0xad, 0x1b, 0x12, 0x9e, 0x5b, - 0x4c, 0xc9, 0x26, 0xb7, 0x26, 0x9f, 0x46, 0x22, 0xce, 0x5a, 0x3c, 0xc9, 0x9b, 0x38, 0x6b, 0x99, - 0x19, 0xe3, 0xc4, 0x59, 0x9b, 0x92, 0x1f, 0x6e, 0x06, 0x3d, 0x82, 0x46, 0x22, 0x8f, 0x1b, 0x12, - 0x75, 0x28, 0x33, 0x79, 0xdc, 0xda, 0xd5, 0x53, 0x28, 0x42, 0xce, 0x1f, 0x42, 0x89, 0x6d, 0xfe, - 0x68, 0x35, 0x36, 0xd9, 0xd1, 0xa7, 0x4c, 0x6b, 0xcd, 0x34, 0x22, 0xac, 0xfe, 0x1e, 0xcc, 0xf1, - 0x6f, 0xb3, 0x50, 0x9c, 0x4c, 0xf8, 0x5c, 0x6b, 0x2d, 0xf1, 0x19, 0x9f, 0x3c, 0xf3, 0x56, 0x8e, - 0xe8, 0xa1, 0xf0, 0x1d, 0x93, 0xa8, 0x87, 0xe9, 0x8f, 0xa9, 0x44, 0x3d, 0xcc, 0xfa, 0xf8, 0x69, - 0x06, 0x7d, 0x0c, 0x73, 0x3c, 0x6c, 0x8a, 0xd2, 0xa1, 0xd7, 0x80, 0xcb, 0x85, 0x0c, 0x8c, 0x68, - 0xa6, 0xa2, 0xfc, 0x97, 0xa2, 0x99, 0x4a, 0x65, 0xf0, 0x14, 0xcd, 0x54, 0x46, 0xca, 0xcc, 0x19, - 0xb4, 0x0d, 0x10, 0xa5, 0x3b, 0x13, 0x59, 0xa5, 0x92, 0xa0, 0xad, 0x65, 0x7f, 0x01, 0x48, 0x07, - 0xe8, 0x4e, 0x98, 0xe2, 0x2d, 0x7a, 0x4c, 0x2e, 0x78, 0x61, 0x61, 0x02, 0xd6, 0xb5, 0x44, 0x52, - 0x4b, 0x5a, 0xf9, 0x1e, 0x54, 0xc2, 0x9c, 0x7b, 0xa2, 0xa5, 0x4c, 0x66, 0xfc, 0x13, 0x2d, 0x65, - 0x3a, 0x49, 0x1f, 0x1b, 0x95, 0x30, 0x23, 0x5f, 0x6c, 0x54, 0x92, 0xc9, 0xfb, 0x62, 0xa3, 0x92, - 0x4e, 0xe2, 0x37, 0x83, 0xee, 0x43, 0x25, 0xcc, 0xa2, 0x27, 0x8a, 0x94, 0xcc, 0xed, 0x27, 0x8a, - 0x94, 0x4e, 0xbb, 0x37, 0x73, 0x23, 0x47, 0x54, 0x96, 0xe5, 0xad, 0x43, 0xab, 0x53, 0xd2, 0xe6, - 0xad, 0x35, 0xd3, 0x08, 0x71, 0x17, 0x09, 0x53, 0xd4, 0x89, 0x82, 0x24, 0x33, 0xdf, 0xad, 0xad, - 0x67, 0xe2, 0x44, 0x9d, 0xe3, 0x49, 0xb9, 0x12, 0xaa, 0x2f, 0x64, 0x73, 0x12, 0x75, 0x2e, 0x91, - 0xc1, 0x2b, 0xd4, 0xda, 0x24, 0x87, 0x78, 0xb2, 0xae, 0x84, 0xd6, 0x26, 0x38, 0x84, 0x5a, 0x4b, - 0x99, 0xa4, 0x04, 0x16, 0xf9, 0xbc, 0x94, 0x8d, 0x14, 0x59, 0x45, 0xf9, 0xb2, 0x50, 0x4a, 0x2f, - 0xa6, 0xb0, 0xca, 0x48, 0xb1, 0x45, 0xf7, 0x18, 0x21, 0x69, 0x16, 0x4a, 0x6b, 0x86, 0xc8, 0xec, - 0xe2, 0x14, 0xac, 0x38, 0x5f, 0x61, 0xca, 0x2b, 0x71, 0xbe, 0x92, 0x99, 0xb3, 0xc4, 0xf9, 0x4a, - 0xe7, 0xc8, 0xa2, 0x7b, 0x55, 0x2c, 0x7d, 0x96, 0xb8, 0x57, 0x65, 0x65, 0xe2, 0x12, 0xf7, 0xaa, - 0xec, 0xbc, 0x5b, 0xa1, 0xf5, 0xb4, 0xb5, 0xa4, 0xf5, 0x0c, 0x0f, 0xfd, 0x49, 0xeb, 0x19, 0x1d, - 0xf2, 0xd9, 0x40, 0x09, 0xa9, 0xae, 0x50, 0x6a, 0x5c, 0xc5, 0x74, 0x5e, 0xe2, 0x40, 0x65, 0xe5, - 0xc7, 0x9a, 0xe1, 0xeb, 0xe2, 0xa1, 0x3b, 0x4c, 0xac, 0x8b, 0x28, 0x4d, 0x55, 0x62, 0x5d, 0x88, - 0xa9, 0xa8, 0x84, 0x75, 0x41, 0x38, 0xa4, 0xd6, 0x85, 0xc0, 0x64, 0x3d, 0x13, 0x97, 0x18, 0x93, - 0x84, 0x18, 0xb1, 0xd4, 0x5d, 0x89, 0x31, 0x89, 0x57, 0x57, 0x68, 0xd4, 0x44, 0xb8, 0x74, 0xba, - 0x14, 0x23, 0x4e, 0x25, 0x71, 0x12, 0xa7, 0x29, 0x33, 0xeb, 0x15, 0xe3, 0x19, 0xcb, 0x46, 0x25, - 0xf2, 0xcc, 0x4a, 0x73, 0x25, 0xf2, 0xcc, 0x4e, 0x63, 0x45, 0xdd, 0x88, 0x64, 0xce, 0x29, 0xd1, - 0x8d, 0x98, 0x92, 0xe4, 0x4a, 0x74, 0x23, 0xa6, 0xa6, 0xac, 0xa2, 0x3e, 0x50, 0x2a, 0xe1, 0x94, - 0xe8, 0x03, 0x4d, 0xcb, 0x68, 0x25, 0xfa, 0x40, 0xd3, 0x33, 0x56, 0xcd, 0xa0, 0x2e, 0xd4, 0xc4, - 0xe4, 0x54, 0x28, 0xee, 0xe8, 0x25, 0xf3, 0x30, 0xad, 0x5d, 0x9a, 0x86, 0x16, 0x19, 0x8a, 0x69, - 0xa5, 0x50, 0xdc, 0x6b, 0x3e, 0x8d, 0x61, 0x66, 0x36, 0x2a, 0xe6, 0xf1, 0xc4, 0x13, 0x46, 0xa1, - 0x94, 0xd7, 0x9c, 0x62, 0x7b, 0xf5, 0x14, 0x0a, 0x71, 0xe2, 0x92, 0x19, 0xa2, 0xc4, 0x89, 0x9b, - 0x92, 0x8b, 0x6a, 0x4d, 0x3e, 0x8d, 0x24, 0x71, 0x44, 0xe1, 0x91, 0xdb, 0xf8, 0x11, 0x25, 0x96, - 0xef, 0x28, 0x71, 0x44, 0x49, 0x24, 0x17, 0xa2, 0x7c, 0xc2, 0x7c, 0x3a, 0x22, 0x9f, 0x64, 0xa2, - 0x29, 0x91, 0x4f, 0x3a, 0x15, 0x14, 0x9d, 0x17, 0x31, 0x13, 0x8e, 0x38, 0x2f, 0x19, 0x39, 0xa2, - 0xc4, 0x79, 0xc9, 0x4c, 0xdf, 0xc4, 0x3d, 0x7e, 0x21, 0xb5, 0x4d, 0xdc, 0xe3, 0x4f, 0x27, 0x76, - 0x8a, 0x7b, 0xfc, 0x59, 0x99, 0x94, 0x66, 0x90, 0x4e, 0x33, 0xa8, 0xa5, 0x42, 0xd3, 0x2f, 0x67, - 0x0c, 0x51, 0x2a, 0x4f, 0xcf, 0xda, 0xb5, 0x33, 0xa8, 0xc4, 0x56, 0x32, 0x52, 0x14, 0x89, 0xad, - 0x4c, 0xcf, 0x8d, 0x24, 0xb6, 0x72, 0x5a, 0x9e, 0xa3, 0x19, 0x34, 0x0e, 0xf2, 0xa8, 0xa5, 0x1a, - 0xba, 0x9e, 0x3d, 0xb6, 0xe9, 0xb6, 0x6e, 0x9c, 0x4d, 0x18, 0x36, 0xe7, 0x84, 0xc9, 0xd3, 0xd2, - 0x91, 0xfd, 0x29, 0x03, 0x9f, 0x6e, 0xf0, 0xd5, 0x73, 0x50, 0x8a, 0x7e, 0x42, 0x14, 0x2d, 0x44, - 0xeb, 0xc9, 0xb3, 0x81, 0x10, 0x81, 0x5c, 0x7b, 0x29, 0x1b, 0x19, 0xb0, 0x3a, 0x2c, 0xd1, 0x7f, - 0x79, 0xf0, 0xf6, 0x7f, 0x05, 0x00, 0x00, 0xff, 0xff, 0x81, 0x03, 0x42, 0x0e, 0x01, 0x61, 0x00, - 0x00, + // 8330 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xec, 0x7d, 0x4d, 0x6f, 0x24, 0x47, + 0x96, 0x18, 0xeb, 0x83, 0xc5, 0xaa, 0x57, 0x55, 0xac, 0x64, 0x90, 0x6c, 0x56, 0x93, 0xea, 0xaf, + 0x1c, 0xb5, 0xba, 0xd5, 0x92, 0x28, 0x75, 0x4b, 0xa2, 0xb4, 0xd2, 0xf4, 0xec, 0x54, 0x93, 0xd5, + 0xec, 0x5a, 0x91, 0xac, 0x52, 0xb2, 0xba, 0xa7, 0x35, 0xde, 0x71, 0x3a, 0x59, 0x19, 0x55, 0x4c, + 0xab, 0x2a, 0x33, 0x27, 0x33, 0x8b, 0x22, 0x61, 0xc0, 0xee, 0x9e, 0xdd, 0x19, 0x1b, 0x30, 0xf6, + 0x62, 0x1f, 0x6d, 0xc3, 0x07, 0x5f, 0x8c, 0x85, 0x7d, 0x30, 0xb0, 0x86, 0x01, 0x5f, 0xfc, 0x01, + 0xef, 0xc2, 0xf0, 0x02, 0x3e, 0xfa, 0x68, 0xff, 0x00, 0x9f, 0x7c, 0x31, 0x0c, 0x9f, 0x8c, 0xf8, + 0xca, 0x8c, 0xfc, 0x28, 0x92, 0xdd, 0xdb, 0x5a, 0x79, 0x81, 0x39, 0xb1, 0xf2, 0xbd, 0x17, 0x2f, + 0x5e, 0x44, 0xbc, 0x88, 0xf7, 0x5e, 0x7c, 0x3c, 0x42, 0x75, 0xe4, 0x1c, 0x8d, 0xdc, 0x4d, 0xd7, + 0x73, 0x02, 0x07, 0x95, 0xe9, 0x87, 0xe1, 0x5a, 0xeb, 0x57, 0x47, 0x8e, 0x33, 0x1a, 0xe3, 0x0f, + 0x29, 0xfc, 0x68, 0x3a, 0xfc, 0xd0, 0xb0, 0xcf, 0x18, 0x91, 0xfa, 0x73, 0x40, 0xbb, 0x38, 0x38, + 0xc0, 0xd6, 0xe8, 0xf8, 0xc8, 0xf1, 0x34, 0xfc, 0xcb, 0x29, 0xf6, 0x03, 0x74, 0x0f, 0x14, 0x6c, + 0x1b, 0x47, 0x63, 0xdc, 0x32, 0x4f, 0xb0, 0x17, 0x58, 0x3e, 0x36, 0x9b, 0xb9, 0x9b, 0xb9, 0xbb, + 0x65, 0x2d, 0x05, 0x47, 0x4d, 0x58, 0x30, 0x4c, 0xd3, 0xc3, 0xbe, 0xdf, 0xcc, 0xdf, 0xcc, 0xdd, + 0xad, 0x68, 0xe2, 0x53, 0xfd, 0x12, 0x96, 0x63, 0xbc, 0x7d, 0xd7, 0xb1, 0x7d, 0x8c, 0xde, 0x86, + 0x79, 0x17, 0x63, 0xcf, 0x6f, 0xe6, 0x6e, 0x16, 0xee, 0x56, 0x1f, 0x2c, 0x6e, 0x0a, 0x39, 0x37, + 0x7b, 0x18, 0x7b, 0x1a, 0x43, 0xaa, 0x2f, 0x73, 0x50, 0x69, 0x79, 0xa3, 0xe9, 0x04, 0xdb, 0x81, + 0x8f, 0x36, 0xa1, 0xec, 0x61, 0xdf, 0x99, 0x7a, 0x03, 0x4c, 0x05, 0x59, 0x7c, 0x80, 0xa2, 0x62, + 0x1a, 0xc7, 0x68, 0x21, 0x0d, 0xba, 0x02, 0xa5, 0xa1, 0x31, 0xb1, 0xc6, 0x67, 0x54, 0xa6, 0xba, + 0xc6, 0xbf, 0x10, 0x82, 0xa2, 0x6d, 0x4c, 0x70, 0xb3, 0x40, 0x25, 0xa5, 0xbf, 0x49, 0x03, 0x06, + 0x53, 0xcf, 0xc3, 0x76, 0xd0, 0x2c, 0xd2, 0x36, 0x8a, 0x4f, 0xf5, 0x6f, 0xc1, 0x62, 0xcb, 0x34, + 0x7b, 0x46, 0x70, 0x2c, 0x3a, 0xe6, 0x55, 0xe5, 0x58, 0x85, 0xd2, 0x89, 0x37, 0xd4, 0x2d, 0x93, + 0xf7, 0xcd, 0xfc, 0x89, 0x37, 0xec, 0x98, 0x48, 0x85, 0xa2, 0x6b, 0x04, 0xc7, 0x54, 0x8c, 0x78, + 0x0f, 0x90, 0xba, 0x28, 0x4e, 0xbd, 0x0d, 0x8d, 0xb0, 0x72, 0xde, 0x73, 0x08, 0x8a, 0xd3, 0xa9, + 0xc5, 0x86, 0xa2, 0xa6, 0xd1, 0xdf, 0xea, 0x1f, 0xe7, 0x60, 0x69, 0x07, 0x8f, 0x71, 0x80, 0xbf, + 0x07, 0x39, 0xa3, 0x6e, 0x2c, 0xc4, 0xba, 0x51, 0xc8, 0x5f, 0x9c, 0x2d, 0x7f, 0x28, 0xec, 0xbc, + 0x24, 0xec, 0x0a, 0x20, 0x59, 0x56, 0xd6, 0x2c, 0xf5, 0x73, 0x40, 0x2d, 0xd3, 0x4c, 0xea, 0x20, + 0xa9, 0x03, 0x63, 0x8f, 0x8a, 0x9f, 0xd6, 0x12, 0x8a, 0x53, 0x57, 0x61, 0x39, 0x56, 0x92, 0x33, + 0xfc, 0x12, 0x56, 0x59, 0x35, 0xaf, 0xc3, 0xb3, 0x09, 0x57, 0x92, 0x85, 0x39, 0x5b, 0x13, 0x56, + 0x9f, 0xba, 0xa6, 0xf1, 0x5a, 0x6c, 0xd1, 0x1d, 0x50, 0x4c, 0x47, 0xf7, 0x9d, 0x61, 0xa0, 0x7b, + 0xd8, 0xc7, 0x81, 0x6e, 0xd9, 0xb4, 0xaf, 0xcb, 0x5a, 0xdd, 0x74, 0x0e, 0x9d, 0x61, 0xa0, 0x11, + 0x68, 0xc7, 0x56, 0x77, 0xe1, 0x4a, 0xb2, 0x16, 0x3e, 0xfc, 0x1f, 0xc0, 0xb2, 0x8d, 0xb1, 0xe9, + 0x27, 0xb8, 0xf0, 0x89, 0x49, 0x51, 0x32, 0xa3, 0x0e, 0xed, 0x1c, 0x22, 0xc2, 0xae, 0xe7, 0x4c, + 0x5d, 0x21, 0xec, 0x03, 0x00, 0x22, 0x90, 0x3e, 0x22, 0x40, 0x2e, 0xf2, 0x72, 0x5c, 0x64, 0x46, + 0x5f, 0x71, 0xc5, 0x4f, 0xf5, 0x0a, 0xac, 0xc4, 0x59, 0xf1, 0x1e, 0xd9, 0x13, 0x7d, 0xf5, 0x46, + 0x6a, 0xb9, 0x0a, 0x6b, 0x29, 0x6e, 0xbc, 0xa2, 0xa9, 0xe8, 0x94, 0x37, 0x51, 0xd1, 0xe5, 0xc7, + 0xe2, 0x09, 0xac, 0xa5, 0xaa, 0x7d, 0xbd, 0xc1, 0x30, 0xe0, 0x6a, 0xcb, 0x34, 0x77, 0xce, 0x6c, + 0x63, 0x62, 0x0d, 0x92, 0xfa, 0xb3, 0x03, 0x8a, 0xc9, 0x30, 0xba, 0xcd, 0x51, 0xbc, 0x25, 0x57, + 0xa3, 0x96, 0x24, 0xcb, 0x36, 0xcc, 0x38, 0x40, 0x7d, 0x0b, 0xd6, 0xb3, 0xaa, 0xe0, 0x3d, 0xf8, + 0x0c, 0x56, 0xa8, 0x2c, 0xc9, 0xba, 0xa5, 0xe5, 0x3b, 0x17, 0x5b, 0xbe, 0xd1, 0xdb, 0x50, 0x1f, + 0x38, 0x93, 0xc9, 0xd4, 0xb6, 0x06, 0x46, 0x60, 0x39, 0x36, 0x5f, 0x1a, 0xe2, 0x40, 0x75, 0x0d, + 0x56, 0x13, 0x7c, 0x79, 0x85, 0xff, 0x36, 0x07, 0xcd, 0xb0, 0x07, 0x2e, 0x5f, 0xeb, 0x21, 0x54, + 0x4c, 0xcb, 0xc3, 0x83, 0xb0, 0xc6, 0xc5, 0x07, 0x9f, 0x46, 0x9d, 0x30, 0x8b, 0x61, 0x84, 0xd8, + 0x11, 0x85, 0xb5, 0x88, 0x8f, 0xfa, 0x21, 0xa0, 0x34, 0x01, 0x2a, 0x41, 0xbe, 0x73, 0xa0, 0xcc, + 0xa1, 0x05, 0x28, 0x74, 0x9f, 0xf6, 0x95, 0x1c, 0x2a, 0x43, 0xf1, 0x51, 0xb7, 0xff, 0x44, 0xc9, + 0xab, 0x1b, 0x70, 0x35, 0xa3, 0x2a, 0xde, 0xb2, 0x6f, 0x60, 0xed, 0xf0, 0x78, 0x1a, 0x98, 0xce, + 0x77, 0xf6, 0x9b, 0xee, 0xcd, 0x75, 0x68, 0xa6, 0x59, 0xf3, 0x6a, 0xef, 0xc3, 0x6a, 0x9b, 0x1a, + 0xdf, 0x4b, 0x57, 0x4a, 0xd6, 0xb2, 0x64, 0x11, 0xce, 0xec, 0x39, 0x5c, 0xd9, 0xb1, 0xfc, 0x57, + 0xe2, 0x76, 0xc9, 0x26, 0x90, 0x59, 0x9c, 0xe4, 0xcc, 0x2b, 0x9d, 0xc0, 0x32, 0x9f, 0x4e, 0xce, + 0xd8, 0x1a, 0x9c, 0x89, 0x1a, 0xef, 0x42, 0xd1, 0xc7, 0x81, 0xf0, 0x07, 0x56, 0x24, 0x95, 0xc7, + 0x43, 0xcb, 0xc6, 0xe6, 0x21, 0x0e, 0x34, 0x4a, 0x81, 0xde, 0x87, 0xb2, 0x4b, 0x8a, 0x5a, 0x98, + 0x38, 0x1b, 0x84, 0x5a, 0x91, 0xa6, 0x3a, 0x63, 0x1a, 0x52, 0x90, 0x55, 0x2b, 0x5e, 0x1d, 0x17, + 0x63, 0x04, 0x0a, 0xeb, 0x95, 0x7d, 0x2f, 0x10, 0x32, 0x6c, 0x40, 0xc5, 0x9c, 0x4e, 0x5c, 0x3d, + 0x38, 0x73, 0x99, 0xc5, 0x9c, 0xd7, 0xca, 0x04, 0xd0, 0x3f, 0x73, 0x31, 0x5a, 0x87, 0xf2, 0xd0, + 0x1a, 0x63, 0xea, 0x39, 0xb0, 0x36, 0x87, 0xdf, 0x04, 0x67, 0xd9, 0x01, 0xf6, 0x4e, 0x8c, 0x31, + 0x35, 0x92, 0x45, 0x2d, 0xfc, 0x56, 0x97, 0x61, 0x49, 0xaa, 0x88, 0xd7, 0xbe, 0x0c, 0x4b, 0xbc, + 0x7f, 0xa2, 0xea, 0xa9, 0x61, 0x94, 0x80, 0x9c, 0xf4, 0xef, 0x80, 0xd2, 0xb1, 0xff, 0x26, 0x1e, + 0x04, 0x92, 0xa0, 0x6f, 0xc8, 0xb2, 0x13, 0x27, 0xcc, 0x08, 0x8e, 0xfd, 0x66, 0x21, 0xe5, 0x84, + 0x11, 0xd3, 0xcc, 0x90, 0x44, 0x56, 0x49, 0x00, 0x2e, 0xd5, 0xbf, 0xcf, 0x41, 0xbd, 0x65, 0x9a, + 0x8f, 0x26, 0xee, 0xc5, 0x2a, 0x83, 0xa0, 0xe8, 0x3a, 0x5e, 0xc0, 0xbd, 0x30, 0xfa, 0x1b, 0xfd, + 0x18, 0x8a, 0xb4, 0x97, 0x0b, 0x54, 0xfa, 0xbb, 0x51, 0xcd, 0x31, 0xa6, 0x9b, 0xfb, 0x8e, 0x6d, + 0x05, 0x8e, 0x67, 0xd9, 0x23, 0x3e, 0x7c, 0xb4, 0x94, 0xba, 0x0d, 0x4a, 0x12, 0x43, 0x26, 0x70, + 0x4f, 0x6b, 0x2b, 0x73, 0x64, 0x02, 0xf7, 0xba, 0x87, 0xb1, 0xa9, 0x8c, 0x2a, 0x30, 0xbf, 0xd7, + 0xdd, 0x6e, 0xed, 0x29, 0x05, 0x42, 0xd7, 0xda, 0xdb, 0x53, 0x8a, 0xaa, 0x42, 0x1d, 0x3b, 0x5a, + 0x19, 0x6f, 0xd4, 0x4f, 0x41, 0x61, 0xb6, 0xe7, 0x75, 0x9b, 0x45, 0xc7, 0x35, 0xe2, 0xc0, 0xd9, + 0xf6, 0x61, 0x89, 0x4b, 0xab, 0x59, 0x47, 0x82, 0xef, 0x6d, 0x98, 0x0f, 0xc8, 0x50, 0xf3, 0x35, + 0xbe, 0x11, 0xf5, 0x40, 0x9f, 0x80, 0x35, 0x86, 0x95, 0xfd, 0xd2, 0x7c, 0xdc, 0x2f, 0x6d, 0x43, + 0x59, 0xeb, 0x7d, 0xd5, 0xd9, 0x76, 0xec, 0xe1, 0x39, 0x42, 0xde, 0x80, 0xaa, 0x87, 0x27, 0x4e, + 0x80, 0xf5, 0x50, 0xd6, 0x8a, 0x06, 0x0c, 0xd4, 0x23, 0x12, 0xff, 0xe3, 0x22, 0x54, 0x08, 0x9f, + 0xc3, 0xc0, 0x08, 0xa8, 0xcb, 0x3c, 0x75, 0x03, 0x6b, 0xc2, 0xc4, 0x2a, 0x68, 0xfc, 0x8b, 0x28, + 0x38, 0x59, 0x8e, 0x28, 0x26, 0x4f, 0x31, 0xe1, 0x37, 0x5a, 0x84, 0xfc, 0xd4, 0xa5, 0x03, 0x59, + 0xd6, 0xf2, 0x53, 0x97, 0x55, 0x39, 0x70, 0x3c, 0x53, 0xb7, 0xdc, 0x93, 0x4f, 0xa8, 0x7b, 0x58, + 0x27, 0x55, 0x12, 0x50, 0xc7, 0x3d, 0xf9, 0x24, 0x4e, 0xb0, 0x45, 0x7d, 0x43, 0x99, 0x60, 0x8b, + 0x10, 0xb8, 0x1e, 0x1e, 0x5a, 0xa7, 0x8c, 0x43, 0x89, 0x11, 0x30, 0x90, 0xe0, 0x10, 0x11, 0x6c, + 0x35, 0x17, 0x12, 0x04, 0x5b, 0xa4, 0x1d, 0x3e, 0xf6, 0x2c, 0x63, 0xdc, 0x2c, 0x33, 0x9f, 0x95, + 0x7d, 0xa1, 0x1f, 0x41, 0xdd, 0xc3, 0x03, 0x6c, 0x9d, 0x60, 0x2e, 0x5d, 0x85, 0x36, 0xa6, 0x26, + 0x80, 0x94, 0x7b, 0x82, 0x68, 0xab, 0x09, 0x29, 0xa2, 0x2d, 0x42, 0xc4, 0x78, 0xea, 0xb6, 0x13, + 0x58, 0xc3, 0xb3, 0x66, 0x95, 0x11, 0x31, 0xe0, 0x01, 0x85, 0x11, 0x39, 0x07, 0xc6, 0xe0, 0x18, + 0x33, 0xd7, 0xa0, 0x59, 0xa3, 0x24, 0x40, 0x41, 0xd4, 0xaa, 0xa0, 0xdb, 0xb0, 0x18, 0x12, 0x50, + 0x65, 0x69, 0xd6, 0x29, 0x4d, 0x5d, 0xd0, 0x30, 0x3f, 0xe3, 0x3a, 0x54, 0xb1, 0x6d, 0xea, 0xce, + 0x50, 0x37, 0x8d, 0xc0, 0x68, 0x2e, 0x52, 0x9a, 0x0a, 0xb6, 0xcd, 0xee, 0x70, 0xc7, 0x08, 0x0c, + 0xb4, 0x02, 0xf3, 0xd8, 0xf3, 0x1c, 0xaf, 0xd9, 0xa0, 0x18, 0xf6, 0x81, 0x6e, 0x01, 0x97, 0x46, + 0xff, 0xe5, 0x14, 0x7b, 0x67, 0x4d, 0x85, 0x22, 0xab, 0x0c, 0xf6, 0x35, 0x01, 0xb1, 0xa1, 0x20, + 0x5e, 0x0b, 0xa3, 0x58, 0x62, 0x02, 0x52, 0x10, 0x25, 0x50, 0xbf, 0x81, 0xa2, 0xe6, 0x7e, 0x6b, + 0xa1, 0x77, 0xa0, 0x38, 0x70, 0xec, 0x21, 0xd7, 0x56, 0x79, 0xb5, 0xe1, 0x3a, 0xa8, 0x51, 0x3c, + 0x7a, 0x17, 0xe6, 0x7d, 0xa2, 0x49, 0x54, 0x4b, 0x62, 0x4e, 0x58, 0xa8, 0x64, 0x1a, 0xa3, 0x50, + 0xef, 0xc2, 0xe2, 0x2e, 0x0e, 0x08, 0x77, 0x31, 0x27, 0xa2, 0x48, 0x23, 0x27, 0x47, 0x1a, 0xea, + 0x97, 0xd0, 0x08, 0x29, 0x79, 0x8f, 0xdc, 0x85, 0x05, 0x1f, 0x7b, 0x27, 0x99, 0x11, 0x24, 0x25, + 0x14, 0x68, 0xf5, 0xe7, 0x74, 0x9a, 0xcb, 0xd5, 0xbc, 0xda, 0x4a, 0xb5, 0x0e, 0xe5, 0xb1, 0x35, + 0xc4, 0x54, 0xf5, 0x0b, 0x4c, 0xf5, 0xc5, 0xb7, 0xba, 0x44, 0xc3, 0x33, 0x59, 0x30, 0xb5, 0x25, + 0x56, 0x80, 0xd7, 0xae, 0x31, 0x0a, 0x90, 0x62, 0x8c, 0x3f, 0x10, 0x76, 0xe4, 0x52, 0x8c, 0x09, + 0x13, 0x99, 0x9c, 0x33, 0xd9, 0x0c, 0x4d, 0xcc, 0xe5, 0xb8, 0xac, 0xc2, 0x72, 0x8c, 0x9e, 0xb3, + 0x79, 0x1f, 0x14, 0xaa, 0xbf, 0x97, 0x63, 0xb2, 0x0c, 0x4b, 0x12, 0x35, 0x67, 0xf1, 0x11, 0xac, + 0x84, 0xce, 0xd5, 0xe5, 0xd8, 0xac, 0xc1, 0x6a, 0xa2, 0x04, 0x67, 0xf5, 0xe7, 0x39, 0xd1, 0xd6, + 0x9f, 0xe3, 0x23, 0xcf, 0x10, 0x9c, 0x14, 0x28, 0x4c, 0xbd, 0x31, 0xe7, 0x42, 0x7e, 0x52, 0x6d, + 0x77, 0xa6, 0x01, 0xa6, 0x06, 0x9e, 0x39, 0x0f, 0x64, 0x31, 0x24, 0x20, 0x62, 0xe2, 0x7d, 0x52, + 0x39, 0xd1, 0x19, 0xe2, 0xd6, 0xb0, 0x58, 0x57, 0x7c, 0xa2, 0x4f, 0xe0, 0x8a, 0x8d, 0x4f, 0x83, + 0x63, 0xc7, 0xd5, 0x03, 0xcf, 0x1a, 0x8d, 0xb0, 0xa7, 0xb3, 0x4d, 0x10, 0xbe, 0x5d, 0xb0, 0xc2, + 0xb1, 0x7d, 0x86, 0x64, 0xe2, 0xa0, 0x07, 0xb0, 0x9a, 0x2c, 0x65, 0xe2, 0xb1, 0x71, 0xc6, 0xd7, + 0xbc, 0xe5, 0x78, 0xa1, 0x1d, 0x82, 0x22, 0x5d, 0x1e, 0x6b, 0x0c, 0x6f, 0x64, 0x03, 0xea, 0xbb, + 0x38, 0x78, 0xe6, 0x0d, 0x85, 0xb7, 0xf0, 0x31, 0x9d, 0x3e, 0x14, 0xc0, 0xe7, 0xc4, 0x2d, 0x28, + 0x9e, 0x78, 0x43, 0x31, 0x21, 0xea, 0xd1, 0x84, 0x20, 0x44, 0x14, 0xa5, 0x7e, 0x44, 0xad, 0x76, + 0xc4, 0x05, 0xdd, 0x80, 0xc2, 0x89, 0x27, 0xa6, 0x75, 0xa2, 0x08, 0xc1, 0x70, 0x2b, 0x29, 0x55, + 0xa3, 0x7e, 0x2c, 0xac, 0xe4, 0xab, 0xb0, 0x09, 0x0d, 0xa3, 0xcc, 0xe9, 0x29, 0xac, 0xec, 0xe2, + 0x40, 0x72, 0xf0, 0x38, 0xb7, 0x77, 0xb9, 0x73, 0xc0, 0x5c, 0x9b, 0xd5, 0x94, 0x2f, 0x48, 0x06, + 0x8b, 0x79, 0x02, 0xe1, 0x5e, 0x4e, 0x3e, 0xda, 0xcb, 0x51, 0x5b, 0xb0, 0x9a, 0x60, 0x1b, 0x2e, + 0x1a, 0x97, 0xf4, 0x31, 0xd5, 0x9f, 0xd0, 0x58, 0x37, 0x2d, 0xd9, 0x3b, 0x50, 0x20, 0x0b, 0x39, + 0x6b, 0x67, 0x36, 0x03, 0x42, 0x40, 0x74, 0x35, 0x51, 0x9e, 0x37, 0xf9, 0x50, 0x84, 0xb7, 0xaf, + 0xcd, 0x9b, 0xe8, 0xb5, 0x31, 0x1e, 0x73, 0x77, 0x80, 0xfc, 0x24, 0x01, 0x43, 0x9a, 0x29, 0xaf, + 0xf0, 0x11, 0x34, 0x35, 0xec, 0x8e, 0x8d, 0xc1, 0xeb, 0xd7, 0x48, 0x02, 0xa1, 0x0c, 0x1e, 0xbc, + 0x82, 0x55, 0xba, 0xc1, 0x47, 0x57, 0xf6, 0x09, 0xb6, 0x43, 0x67, 0xf6, 0x2b, 0x3a, 0xb6, 0x12, + 0x98, 0x8f, 0xc1, 0xc7, 0x00, 0xbe, 0x00, 0x8a, 0x91, 0x90, 0xac, 0x44, 0x54, 0x40, 0x22, 0x53, + 0x9f, 0xd0, 0x5d, 0x8c, 0x64, 0x1d, 0xe8, 0x3e, 0x54, 0x42, 0xa2, 0x74, 0xd4, 0x1f, 0x91, 0x47, + 0x54, 0x7c, 0x13, 0x23, 0x25, 0x96, 0xfa, 0x0b, 0xb1, 0x89, 0xf1, 0x06, 0x2a, 0xc9, 0x18, 0xa1, + 0x70, 0x57, 0x23, 0x5d, 0xf3, 0x1e, 0xac, 0xf1, 0xce, 0x7d, 0x13, 0xed, 0x5b, 0x0f, 0x87, 0x3b, + 0x5d, 0x13, 0x02, 0x65, 0x17, 0x07, 0xb1, 0xb0, 0x8b, 0x98, 0x2b, 0x09, 0xc6, 0xc7, 0x48, 0x8e, + 0xb0, 0x72, 0x17, 0x46, 0x58, 0xa7, 0xa0, 0xb4, 0x4c, 0x33, 0x19, 0xcd, 0x95, 0x28, 0xfe, 0x8c, + 0x8b, 0x9d, 0x2e, 0xcf, 0xf1, 0xe8, 0x0b, 0xb8, 0xea, 0xe1, 0x21, 0x59, 0x4e, 0x4f, 0x2d, 0x3f, + 0xb0, 0xec, 0x91, 0x2e, 0xa9, 0x07, 0xeb, 0xc1, 0x35, 0x4a, 0xd0, 0xe6, 0xf8, 0xc3, 0x48, 0x2d, + 0x96, 0x61, 0x49, 0xaa, 0x99, 0xb7, 0xf2, 0x57, 0x39, 0x58, 0xe6, 0x3b, 0x48, 0xaf, 0x29, 0xd2, + 0x87, 0xb0, 0xec, 0x12, 0x17, 0xc8, 0x3b, 0xc1, 0x69, 0x61, 0x90, 0x40, 0x45, 0x72, 0x88, 0xf1, + 0x2e, 0x44, 0xe3, 0x7d, 0x05, 0x56, 0xe2, 0x32, 0x70, 0xe1, 0xfe, 0x65, 0x0e, 0x56, 0xf8, 0xf8, + 0xfc, 0x00, 0x1d, 0x36, 0xab, 0x65, 0x85, 0x59, 0x2d, 0x63, 0x1b, 0x3b, 0x31, 0x71, 0xc3, 0xad, + 0x83, 0xf5, 0x50, 0x6f, 0x5a, 0xbe, 0x6f, 0x8d, 0x6c, 0x59, 0x71, 0xbf, 0x00, 0x30, 0x42, 0x20, + 0x6f, 0xd1, 0x7a, 0xb2, 0x45, 0x52, 0x31, 0x89, 0x5a, 0xfd, 0x06, 0x36, 0x32, 0x39, 0x73, 0xdd, + 0xfc, 0x8b, 0xb0, 0x7e, 0x4e, 0x37, 0xc7, 0xbe, 0x0f, 0xa1, 0xaf, 0xc1, 0x46, 0x26, 0xe7, 0x70, + 0xcf, 0xe3, 0x9a, 0xac, 0x0e, 0x6f, 0xb4, 0xee, 0x8c, 0xd5, 0xe6, 0x26, 0x5c, 0x9f, 0x55, 0x1d, + 0x17, 0xe8, 0xf7, 0xe1, 0x7a, 0x6c, 0x5c, 0xdf, 0x6c, 0x6f, 0xdc, 0x82, 0x1b, 0x33, 0xb9, 0xc7, + 0xd6, 0xa2, 0x43, 0xea, 0xa3, 0x8b, 0xb5, 0xe8, 0x21, 0x5d, 0x8b, 0x04, 0x2c, 0xb4, 0xd9, 0xa5, + 0xd1, 0xd8, 0x39, 0x32, 0xc6, 0xe9, 0x89, 0xb1, 0x4b, 0xe1, 0x1a, 0xc7, 0xab, 0x3f, 0x01, 0x74, + 0x18, 0x18, 0x5e, 0x9c, 0xe9, 0x2b, 0x94, 0x5f, 0x85, 0xe5, 0x58, 0xf9, 0x68, 0xab, 0xe6, 0x30, + 0x70, 0xdc, 0xb8, 0xa8, 0x2b, 0xa4, 0xae, 0x08, 0xc8, 0x49, 0xff, 0x59, 0x01, 0x16, 0x49, 0x98, + 0xf3, 0xcc, 0x18, 0x5b, 0x26, 0xdd, 0x08, 0x43, 0x9f, 0x88, 0x78, 0x88, 0xf9, 0x32, 0xd7, 0xe3, + 0xf1, 0x50, 0x44, 0xb8, 0x29, 0x87, 0x46, 0xe8, 0x33, 0x28, 0x79, 0xd8, 0xf0, 0xc3, 0xcd, 0xcf, + 0x1b, 0x33, 0x8b, 0x69, 0x94, 0x4c, 0xe3, 0xe4, 0xe8, 0x0e, 0x2c, 0x4c, 0x8c, 0x60, 0x70, 0x8c, + 0x4d, 0xbe, 0xa7, 0x23, 0xf9, 0x62, 0x9a, 0x63, 0x68, 0x02, 0x8b, 0x3e, 0x82, 0xda, 0xd4, 0xe6, + 0x1f, 0xba, 0xe1, 0x37, 0x8b, 0x59, 0xd4, 0xd5, 0x90, 0xa4, 0xe5, 0xa3, 0xcf, 0x41, 0x89, 0x4a, + 0x8c, 0xb1, 0x3d, 0x0a, 0x8e, 0x9b, 0xf3, 0x59, 0xa5, 0x1a, 0x21, 0xd9, 0x1e, 0xa5, 0x52, 0x7b, + 0x30, 0xcf, 0x76, 0x17, 0x16, 0x01, 0x0e, 0xfb, 0xad, 0x7e, 0x5b, 0x3f, 0xe8, 0x1e, 0xb4, 0x95, + 0x39, 0xb4, 0x0c, 0x0d, 0xf1, 0xdd, 0xd7, 0x1f, 0x77, 0x9f, 0x1e, 0xec, 0x28, 0x39, 0xd4, 0x80, + 0x2a, 0x03, 0x3e, 0x6b, 0xed, 0x75, 0x76, 0x94, 0x3c, 0x5a, 0x82, 0x3a, 0x03, 0x74, 0x0e, 0x18, + 0xa8, 0xa0, 0x7e, 0x09, 0x25, 0xd6, 0x70, 0x42, 0xad, 0xb5, 0x5b, 0x87, 0xdd, 0xbe, 0xe0, 0x59, + 0x87, 0x0a, 0x05, 0x1c, 0xe8, 0xad, 0x43, 0x25, 0x47, 0x0a, 0xf3, 0xcf, 0xbd, 0xf6, 0xc1, 0x2e, + 0xdd, 0xd6, 0xfd, 0x6f, 0xf3, 0x50, 0xec, 0xf1, 0xc3, 0x29, 0x7b, 0xec, 0x59, 0xe2, 0x24, 0x8d, + 0xfc, 0x26, 0x21, 0xa8, 0x6b, 0x04, 0x81, 0xc7, 0xa2, 0x83, 0x9a, 0xc6, 0xbf, 0xe8, 0x24, 0x1b, + 0x89, 0x00, 0x90, 0xfc, 0x24, 0xa5, 0x8f, 0xb0, 0x2f, 0x8e, 0x0b, 0xe9, 0x6f, 0x12, 0x60, 0x58, + 0xbe, 0xfe, 0x9d, 0x15, 0x1c, 0x9b, 0x9e, 0xf1, 0x1d, 0xf5, 0xf2, 0xcb, 0x1a, 0x58, 0xfe, 0xcf, + 0x38, 0x04, 0x5d, 0x07, 0x38, 0x09, 0x07, 0x8f, 0x6e, 0x6c, 0xcc, 0x6b, 0x12, 0x04, 0xb5, 0x61, + 0x29, 0xfa, 0xd2, 0x4d, 0x1c, 0x18, 0xd6, 0x98, 0x6e, 0x6f, 0x54, 0x1f, 0x34, 0x67, 0xe9, 0x80, + 0xa6, 0x44, 0x45, 0x76, 0x68, 0x09, 0xf4, 0x11, 0xac, 0xd8, 0x8e, 0x6e, 0x4d, 0x5c, 0x62, 0xa2, + 0x83, 0x48, 0xa0, 0x32, 0x5b, 0xe8, 0x6d, 0xa7, 0xc3, 0x51, 0xa1, 0x60, 0x51, 0xe8, 0x5d, 0x89, + 0x1d, 0xf2, 0x5d, 0x03, 0x60, 0x7b, 0x88, 0xba, 0xe1, 0xdb, 0x74, 0x23, 0xa4, 0xae, 0x55, 0x18, + 0xa4, 0xe5, 0xdb, 0x68, 0x03, 0xf8, 0x87, 0x6e, 0x99, 0x74, 0x07, 0xa4, 0xa2, 0x95, 0x19, 0xa0, + 0x63, 0xf2, 0x1d, 0xd3, 0x00, 0x7b, 0xd8, 0xa4, 0x5b, 0x1f, 0x65, 0x2d, 0xfc, 0x46, 0x2b, 0x74, + 0x5e, 0x8c, 0xd9, 0x7e, 0x47, 0x59, 0x63, 0x1f, 0xe8, 0x2e, 0x28, 0x96, 0xaf, 0x0f, 0x3d, 0x67, + 0xa2, 0xe3, 0xd3, 0x00, 0x7b, 0xb6, 0x31, 0xa6, 0x9b, 0x1d, 0x65, 0x6d, 0xd1, 0xf2, 0x1f, 0x7b, + 0xce, 0xa4, 0xcd, 0xa1, 0xa4, 0xa7, 0xc5, 0x29, 0x89, 0x6e, 0xb9, 0x74, 0xdf, 0xa3, 0xa2, 0x81, + 0x00, 0x75, 0xdc, 0xf0, 0xe4, 0x51, 0x89, 0x4e, 0x1e, 0xd1, 0xfb, 0x80, 0x2c, 0x5f, 0x17, 0x11, + 0x99, 0x65, 0xd3, 0x7e, 0xa3, 0x9b, 0x1e, 0x65, 0x4d, 0xb1, 0xfc, 0x03, 0x86, 0xe8, 0x30, 0x38, + 0x19, 0x2b, 0xcb, 0xc4, 0x76, 0x60, 0x0d, 0x2d, 0xec, 0x35, 0x11, 0xdb, 0x63, 0x8a, 0x20, 0xe8, + 0x5d, 0x50, 0xc6, 0xce, 0xc0, 0x18, 0xeb, 0x12, 0xd5, 0x32, 0xa5, 0x6a, 0x50, 0x78, 0x27, 0x22, + 0xfd, 0x10, 0xca, 0x86, 0x7d, 0xa6, 0x53, 0x6d, 0x5b, 0x09, 0xbd, 0x6d, 0x67, 0x34, 0xc6, 0x9b, + 0xe2, 0x38, 0x7e, 0xb3, 0x65, 0x9f, 0x69, 0x0b, 0x86, 0x7d, 0x76, 0x40, 0xd4, 0xf0, 0x63, 0x00, + 0x52, 0x80, 0xab, 0xe2, 0x6a, 0x18, 0xaf, 0xa4, 0x8b, 0x54, 0x0c, 0xfb, 0xac, 0x47, 0xc9, 0xd4, + 0x7f, 0x9a, 0x83, 0xea, 0x0e, 0x26, 0x36, 0x9f, 0x29, 0x13, 0xd1, 0x65, 0xba, 0x25, 0xc6, 0x63, + 0x60, 0xfe, 0x15, 0x6d, 0xfb, 0xe6, 0xcf, 0xd9, 0xf6, 0x45, 0x77, 0xa0, 0x31, 0x76, 0x6c, 0x12, + 0xb2, 0xb2, 0x62, 0x58, 0xf8, 0x09, 0x8b, 0x0c, 0xdc, 0xe3, 0x50, 0xd2, 0x0f, 0xfe, 0xb1, 0xe3, + 0x05, 0x32, 0x25, 0x9b, 0x14, 0x0d, 0x0e, 0x17, 0xa4, 0xea, 0xbf, 0xc9, 0xc1, 0x3c, 0xdd, 0xde, + 0x44, 0xef, 0xc4, 0x42, 0xbc, 0xac, 0xdd, 0xeb, 0x99, 0xf1, 0xdd, 0xcc, 0x03, 0xe9, 0xdf, 0x81, + 0x9a, 0x19, 0x35, 0x5f, 0xac, 0x69, 0xb1, 0xf0, 0x31, 0xc4, 0x6a, 0x31, 0x52, 0xba, 0xa1, 0xe8, + 0xf8, 0x81, 0xce, 0x7d, 0x30, 0x3e, 0x71, 0x09, 0x88, 0x59, 0x30, 0x75, 0x8b, 0x86, 0xdf, 0xaf, + 0xbc, 0x7f, 0xab, 0x7e, 0xc6, 0x36, 0xb9, 0x48, 0x39, 0x6e, 0xd0, 0x2e, 0x59, 0x70, 0x02, 0x4b, + 0xf4, 0x7b, 0xcf, 0x71, 0xbe, 0x9d, 0xba, 0xac, 0x07, 0x67, 0x8e, 0xe8, 0x4f, 0xa1, 0x3e, 0xa6, + 0x74, 0xba, 0xe3, 0x4a, 0x67, 0x66, 0x1b, 0x09, 0xde, 0x8c, 0x57, 0xd7, 0x65, 0x1d, 0x30, 0x96, + 0xbe, 0xd4, 0x7f, 0x92, 0xa3, 0x82, 0xca, 0xd7, 0x07, 0xbe, 0x8f, 0x21, 0xfa, 0x0c, 0xca, 0x92, + 0x8e, 0x90, 0xe1, 0xc9, 0x96, 0x91, 0xb5, 0x57, 0x0b, 0x89, 0xd5, 0x31, 0x20, 0xbe, 0xe2, 0x61, + 0x69, 0x10, 0x2e, 0x2b, 0xe2, 0xac, 0x9b, 0x20, 0x51, 0x7f, 0x16, 0xe4, 0xfe, 0x24, 0xae, 0x40, + 0xac, 0x36, 0x6e, 0xdf, 0xff, 0x67, 0x11, 0x8a, 0x3d, 0x8c, 0x3d, 0xba, 0xb2, 0x11, 0x0e, 0x22, + 0x40, 0xaa, 0x6b, 0xe1, 0x37, 0xfa, 0x1c, 0x6a, 0x86, 0xeb, 0x8e, 0xcf, 0x84, 0x2e, 0xb1, 0x8d, + 0x50, 0x49, 0x0b, 0x5b, 0x04, 0xcb, 0xdd, 0xe9, 0xaa, 0x11, 0x7d, 0x84, 0x7b, 0xac, 0x85, 0xe4, + 0x1e, 0x2b, 0xa9, 0x53, 0xda, 0x63, 0xfd, 0x12, 0xea, 0xf8, 0x68, 0xe4, 0xea, 0x93, 0xe9, 0x38, + 0xb0, 0x8e, 0x1d, 0x97, 0xdf, 0xc0, 0xb8, 0x12, 0x15, 0x68, 0x1f, 0x8d, 0xdc, 0x7d, 0x8e, 0xd5, + 0x6a, 0x58, 0xfa, 0x42, 0x2d, 0x68, 0xb0, 0x3d, 0x30, 0x0f, 0x0f, 0xc7, 0x78, 0x10, 0x38, 0x1e, + 0xd5, 0xf6, 0xb8, 0x7d, 0x21, 0x04, 0x9a, 0xc0, 0x6b, 0x8b, 0x5e, 0xec, 0x1b, 0xdd, 0x81, 0xa2, + 0x65, 0x0f, 0x1d, 0x6a, 0xbe, 0x52, 0xe7, 0xec, 0xcc, 0x8f, 0xa1, 0x04, 0xc4, 0xf7, 0x0a, 0xac, + 0x09, 0xf6, 0x7c, 0x6e, 0xc2, 0x24, 0xdf, 0xab, 0x4f, 0xe1, 0x1a, 0xc7, 0x93, 0x48, 0x37, 0xf0, + 0x0c, 0xdb, 0xa7, 0x7b, 0xa1, 0xe5, 0x24, 0xdf, 0xbe, 0x40, 0x69, 0x11, 0x15, 0xe9, 0x67, 0xd6, + 0x10, 0xb6, 0xd1, 0x4b, 0xed, 0x56, 0xac, 0x9f, 0x69, 0x2b, 0xb8, 0x87, 0xc6, 0xf6, 0xfd, 0xd8, + 0x07, 0xda, 0x01, 0x65, 0xe4, 0x19, 0x03, 0x3c, 0x9c, 0x8e, 0x75, 0x0f, 0xfb, 0xc4, 0xe7, 0xa3, + 0x96, 0x2d, 0x76, 0xd2, 0xbe, 0xcb, 0x29, 0x34, 0x46, 0xa0, 0x35, 0x46, 0x71, 0x00, 0xda, 0x84, + 0x8a, 0x31, 0xb4, 0x74, 0xdf, 0x18, 0x5a, 0x7e, 0xb3, 0x4a, 0x75, 0x79, 0x49, 0x1a, 0xe4, 0xa1, + 0x75, 0x68, 0x0c, 0x2d, 0xad, 0x6c, 0xb0, 0x1f, 0x24, 0xf6, 0xaa, 0x18, 0xa6, 0xa9, 0xb3, 0x95, + 0xb7, 0x96, 0x1c, 0x62, 0x7e, 0xcb, 0xc7, 0xd7, 0xca, 0x06, 0xff, 0xa5, 0xfe, 0xdf, 0x22, 0x54, + 0xc2, 0x2b, 0x07, 0xdf, 0x93, 0xca, 0xbd, 0x17, 0x53, 0xb9, 0xb5, 0x8c, 0x2b, 0x13, 0xff, 0x1f, + 0xe9, 0xdd, 0xfb, 0x31, 0xbd, 0x6b, 0x66, 0x08, 0xfb, 0x5b, 0xe5, 0x7b, 0x53, 0xca, 0xf7, 0x04, + 0x1a, 0x89, 0x4b, 0x24, 0x33, 0x8d, 0xcf, 0xb5, 0xd8, 0xe5, 0x1b, 0x66, 0x05, 0xa4, 0x0b, 0x3d, + 0xff, 0x39, 0x07, 0x55, 0x49, 0xff, 0xd0, 0x67, 0x50, 0xb1, 0x6c, 0x3d, 0xb6, 0xd9, 0x71, 0x5e, + 0x5c, 0x59, 0xb6, 0x6c, 0x5e, 0xf0, 0x77, 0xa1, 0x8e, 0x4f, 0x49, 0xef, 0xc7, 0xd5, 0xfc, 0xbc, + 0xc2, 0x35, 0x56, 0x20, 0x62, 0x60, 0x4d, 0x64, 0x06, 0x85, 0x8b, 0x19, 0xb0, 0x02, 0xdc, 0x09, + 0xf8, 0xdb, 0x50, 0x65, 0x86, 0x69, 0xcf, 0x9a, 0x58, 0x33, 0x8f, 0xab, 0xd0, 0x2d, 0xa8, 0x4d, + 0x8c, 0xd3, 0xc8, 0x19, 0x62, 0x36, 0xa7, 0x3a, 0x31, 0x4e, 0x43, 0x9f, 0xe9, 0x13, 0xb8, 0xe2, + 0xf3, 0x2b, 0x1e, 0x7a, 0x70, 0xec, 0x61, 0xff, 0xd8, 0x19, 0x9b, 0xba, 0x3b, 0x08, 0xb8, 0xbd, + 0x5c, 0x11, 0xd8, 0xbe, 0x40, 0xf6, 0x06, 0x81, 0xfa, 0xcf, 0x4b, 0x50, 0x16, 0xb6, 0x00, 0xfd, + 0x08, 0xea, 0xc6, 0x34, 0x38, 0xd6, 0x5d, 0xc3, 0xf7, 0xbf, 0x73, 0x3c, 0x93, 0x8f, 0x4a, 0x8d, + 0x00, 0x7b, 0x1c, 0x86, 0x6e, 0x42, 0xd5, 0xc4, 0xfe, 0xc0, 0xb3, 0x5c, 0xe9, 0xae, 0x86, 0x0c, + 0x42, 0x57, 0xa1, 0xcc, 0xbc, 0x58, 0xc3, 0x17, 0x67, 0x1e, 0xf4, 0xbb, 0x45, 0x1d, 0xbb, 0xd0, + 0xc7, 0x16, 0x67, 0x32, 0x45, 0xca, 0xa1, 0x21, 0xe0, 0x2d, 0x7e, 0x8c, 0xb5, 0x06, 0x0b, 0x54, + 0x07, 0x0c, 0x9f, 0x1f, 0x6d, 0x94, 0xc8, 0x67, 0xcb, 0x4f, 0x28, 0x47, 0x29, 0xa1, 0x1c, 0x24, + 0x7e, 0xa0, 0x68, 0x6a, 0xc5, 0xd9, 0x31, 0x6e, 0x99, 0x00, 0xe8, 0x8d, 0x8b, 0x03, 0x58, 0xf2, + 0xf0, 0xc4, 0x39, 0xc1, 0xba, 0xeb, 0x59, 0x27, 0x46, 0x40, 0x62, 0x10, 0x3a, 0x3f, 0x17, 0x1f, + 0xa8, 0x69, 0xe3, 0xb8, 0xa9, 0x51, 0xda, 0x1e, 0x23, 0x6d, 0xf9, 0x5a, 0xc3, 0x8b, 0x03, 0x88, + 0xfb, 0xcf, 0x26, 0xed, 0x70, 0x6c, 0xb8, 0xba, 0x69, 0x4c, 0x5c, 0xcb, 0x1e, 0xd1, 0xa9, 0x5b, + 0xd6, 0x14, 0x8a, 0x79, 0x3c, 0x36, 0xdc, 0x1d, 0x06, 0x47, 0xb7, 0x61, 0xd1, 0xc7, 0xb6, 0xa9, + 0xf3, 0x8b, 0x2d, 0xc1, 0x19, 0x8f, 0x7e, 0xea, 0x04, 0xba, 0x2d, 0x80, 0xc4, 0x53, 0xe7, 0x07, + 0xec, 0x03, 0xc3, 0xe5, 0x53, 0x71, 0x86, 0xa7, 0xce, 0xe8, 0xb6, 0x0d, 0x97, 0xac, 0x38, 0xac, + 0xd3, 0x49, 0x99, 0xda, 0x39, 0x65, 0xd8, 0xd8, 0x90, 0x22, 0x8b, 0x90, 0xb7, 0x4c, 0x1a, 0x2d, + 0x55, 0xb4, 0xbc, 0x65, 0xa2, 0x2f, 0xa0, 0xce, 0x8f, 0xc0, 0xc7, 0x44, 0x19, 0xfd, 0xe6, 0x62, + 0xd2, 0xdb, 0x95, 0x54, 0x55, 0xab, 0xb9, 0xd1, 0x87, 0x4f, 0x54, 0x87, 0x8f, 0x39, 0x1f, 0x55, + 0x16, 0x3e, 0xd5, 0xd8, 0xc0, 0xf3, 0x21, 0xfd, 0x00, 0x50, 0x14, 0x61, 0xd9, 0x01, 0xf6, 0x86, + 0xc6, 0x00, 0xd3, 0x70, 0xaa, 0xa2, 0x2d, 0x85, 0x81, 0x96, 0x40, 0x90, 0x00, 0xf9, 0xc4, 0x1b, + 0xd2, 0x60, 0xaa, 0x42, 0x8f, 0x7c, 0xd0, 0x4d, 0xa8, 0x19, 0xe3, 0xb1, 0xf3, 0x9d, 0x4e, 0x94, + 0xdc, 0xf0, 0x45, 0x04, 0x45, 0x61, 0xdd, 0xef, 0xec, 0x96, 0x8f, 0xde, 0x81, 0x86, 0xc7, 0xf6, + 0x89, 0x74, 0xa1, 0x3d, 0xcb, 0xec, 0x06, 0x1e, 0x07, 0xf7, 0xa8, 0x12, 0xa9, 0xf7, 0xa1, 0x91, + 0x18, 0x5c, 0x54, 0x86, 0x22, 0x0f, 0xf8, 0xf9, 0x7d, 0x8e, 0x1c, 0xaa, 0xc2, 0x82, 0xd6, 0xee, + 0xed, 0xb5, 0xb6, 0xdb, 0x4a, 0x5e, 0xfd, 0x17, 0x05, 0xa8, 0xc7, 0x6c, 0xd8, 0x5f, 0xc2, 0x7c, + 0x99, 0x39, 0x09, 0xde, 0x81, 0x46, 0x34, 0x09, 0x74, 0xea, 0x2c, 0xb3, 0x99, 0x50, 0x0f, 0x67, + 0xc2, 0x01, 0xf1, 0x9a, 0xcf, 0x9d, 0x0d, 0x87, 0xb3, 0x67, 0xc3, 0x9d, 0x19, 0x76, 0xfb, 0x87, + 0x99, 0x12, 0xaf, 0x33, 0x5c, 0xff, 0xbb, 0x00, 0x8b, 0x71, 0x2b, 0xfe, 0x57, 0x7e, 0xbc, 0xfa, + 0xb3, 0xc7, 0xeb, 0xee, 0x2c, 0xd7, 0xe5, 0x07, 0x5a, 0xc3, 0x6e, 0x40, 0x35, 0x70, 0x02, 0x63, + 0xcc, 0xfd, 0x83, 0x2a, 0x9b, 0xa8, 0x14, 0x44, 0xbd, 0x01, 0xc2, 0x87, 0x13, 0x08, 0x9b, 0x56, + 0x63, 0x7c, 0x18, 0x8d, 0x08, 0xd2, 0x5e, 0x63, 0xe0, 0xbf, 0x82, 0x9a, 0xec, 0x34, 0xa2, 0x26, + 0x2c, 0xb0, 0x73, 0x75, 0xf1, 0xd6, 0x40, 0x7c, 0x52, 0xab, 0xca, 0xa9, 0xf4, 0x20, 0x18, 0x87, + 0x56, 0x95, 0xc3, 0xfa, 0xc1, 0x58, 0xfd, 0x83, 0x1c, 0x2c, 0xc6, 0x7d, 0x48, 0x62, 0x68, 0x13, + 0x6e, 0xa7, 0x3e, 0x18, 0x5b, 0x62, 0x4b, 0xbb, 0xac, 0xad, 0xc4, 0x7d, 0xcc, 0x6d, 0x8a, 0x43, + 0x5f, 0xc2, 0x7a, 0xba, 0xd4, 0xd4, 0x0f, 0xb0, 0x17, 0xdd, 0xa1, 0x5b, 0x4b, 0x96, 0xa4, 0xf8, + 0x8e, 0xa9, 0xfe, 0xab, 0x12, 0xf3, 0xdb, 0xff, 0xb2, 0xd4, 0x78, 0x13, 0xca, 0x13, 0xec, 0xfb, + 0xc6, 0x88, 0xef, 0xbb, 0xc4, 0x5c, 0xbb, 0x7d, 0x8e, 0xd1, 0x42, 0x9a, 0x4c, 0xb3, 0x3e, 0x7f, + 0xa1, 0x59, 0x2f, 0x9d, 0x63, 0xd6, 0x17, 0xce, 0x35, 0xeb, 0xe5, 0xc4, 0xc4, 0xb8, 0x0b, 0xa5, + 0x5f, 0x4e, 0xf1, 0x14, 0xfb, 0xdc, 0x6b, 0x96, 0x1c, 0xf3, 0xaf, 0x29, 0x5c, 0xe3, 0x78, 0x74, + 0x2f, 0x6b, 0x0a, 0x31, 0x0d, 0xbe, 0xe4, 0xc4, 0xa8, 0x5e, 0x7a, 0x62, 0xd4, 0xb2, 0x26, 0x06, + 0xbd, 0xe4, 0xe5, 0xfb, 0x96, 0x63, 0xb3, 0xe3, 0x32, 0x6a, 0x7f, 0xeb, 0x5a, 0x8d, 0x03, 0xd9, + 0x08, 0x7f, 0x0a, 0x57, 0xfc, 0xa9, 0x4b, 0xdc, 0x44, 0x6c, 0x12, 0x83, 0x6e, 0x1c, 0x59, 0x63, + 0x2b, 0x20, 0x71, 0xda, 0x22, 0xbd, 0x60, 0xb2, 0x1a, 0x62, 0xb7, 0x25, 0x24, 0xe9, 0x23, 0x12, + 0x4c, 0x31, 0xbe, 0xcc, 0x00, 0x97, 0x8f, 0x46, 0x7c, 0xf1, 0xfb, 0x5d, 0xa8, 0x1a, 0xe6, 0xc4, + 0x12, 0xd5, 0x2a, 0xc9, 0xc3, 0x83, 0x50, 0xbf, 0x36, 0x5b, 0x84, 0x8c, 0xc5, 0x3d, 0x60, 0x84, + 0xbf, 0x49, 0xb8, 0x28, 0xae, 0xab, 0x51, 0x9b, 0x5c, 0xd7, 0xc2, 0x6f, 0x82, 0x33, 0x06, 0x03, + 0xec, 0x06, 0xd8, 0xe4, 0x46, 0x39, 0xfc, 0x46, 0xd7, 0x01, 0x8c, 0xe8, 0xb9, 0xcf, 0x32, 0x37, + 0xd9, 0xd1, 0x43, 0x9f, 0x65, 0x98, 0x77, 0xa6, 0x81, 0xfe, 0x4b, 0xba, 0x8d, 0x59, 0xd7, 0x8a, + 0xce, 0x34, 0xf8, 0x1a, 0xad, 0xc0, 0xfc, 0x70, 0xec, 0xb8, 0x7e, 0x73, 0x95, 0x02, 0xd9, 0x87, + 0x7a, 0x0f, 0x20, 0x12, 0x0e, 0x95, 0x20, 0xff, 0xb4, 0xc7, 0x6e, 0x67, 0xee, 0x74, 0x7f, 0x76, + 0xa0, 0xe4, 0x10, 0x40, 0xa9, 0xf7, 0xf8, 0xb9, 0xbe, 0xdd, 0x57, 0xf2, 0xea, 0xdf, 0x80, 0xb2, + 0xd0, 0x54, 0xf4, 0x81, 0x24, 0x3a, 0x8b, 0x0f, 0x96, 0x52, 0xfa, 0x2c, 0xb5, 0xe6, 0x36, 0x14, + 0x7d, 0x71, 0x3d, 0x32, 0x93, 0x94, 0xa2, 0xd5, 0x3f, 0xcd, 0xc1, 0x02, 0x87, 0x20, 0x15, 0x6a, + 0x07, 0xdd, 0x7e, 0xe7, 0x71, 0x67, 0xbb, 0xd5, 0xef, 0x74, 0x0f, 0x68, 0x2d, 0x45, 0x2d, 0x06, + 0x23, 0xce, 0xfd, 0xd3, 0xde, 0x4e, 0xab, 0xdf, 0xa6, 0x8c, 0x8b, 0x1a, 0xff, 0x42, 0x08, 0x8a, + 0xdd, 0x5e, 0xfb, 0x80, 0x5f, 0xf3, 0xa5, 0xbf, 0xd1, 0x5b, 0x50, 0xf9, 0xaa, 0xdd, 0xee, 0xb5, + 0xf6, 0x3a, 0xcf, 0xda, 0x74, 0x0a, 0x16, 0xb5, 0x08, 0x40, 0x96, 0x34, 0xad, 0xfd, 0x58, 0x6b, + 0x1f, 0x3e, 0xa1, 0xd3, 0xac, 0xa8, 0x89, 0x4f, 0x52, 0x6e, 0xa7, 0x73, 0xb8, 0xdd, 0xd2, 0x76, + 0xda, 0x3b, 0x74, 0x82, 0x15, 0xb5, 0x08, 0x40, 0x7a, 0xb5, 0xdf, 0xed, 0xb7, 0xf6, 0xe8, 0xf4, + 0x2a, 0x6a, 0xec, 0x43, 0xdd, 0x82, 0x12, 0x9b, 0x25, 0x04, 0x6f, 0xd9, 0xee, 0x34, 0xe0, 0xd1, + 0x07, 0xfb, 0x20, 0x72, 0x3b, 0xd3, 0x80, 0x80, 0xf9, 0x56, 0x17, 0xfb, 0x52, 0x31, 0x94, 0x58, + 0xd8, 0x8b, 0x36, 0xa1, 0x44, 0xc2, 0x79, 0x6b, 0xc4, 0x7b, 0xf7, 0x4a, 0x32, 0x30, 0xde, 0xa6, + 0x58, 0x8d, 0x53, 0xa1, 0xf7, 0xe2, 0x57, 0xfa, 0x56, 0x93, 0xe4, 0xb1, 0x4b, 0x7d, 0x7f, 0x9a, + 0x83, 0x9a, 0xcc, 0x85, 0x4c, 0xa1, 0x81, 0x63, 0xdb, 0x78, 0x10, 0xe8, 0x1e, 0x0e, 0xbc, 0x33, + 0xd1, 0xd9, 0x1c, 0xa8, 0x11, 0x18, 0x99, 0x0b, 0x34, 0x00, 0x0a, 0xef, 0x97, 0x16, 0xb5, 0x32, + 0x01, 0x10, 0x4e, 0xc4, 0x11, 0xfd, 0x16, 0x63, 0xd7, 0x18, 0x5b, 0x27, 0x58, 0x4f, 0x5c, 0xb3, + 0x5e, 0x0a, 0x31, 0x1d, 0x8e, 0x40, 0x3b, 0x70, 0x7d, 0x62, 0xd9, 0xd6, 0x64, 0x3a, 0xd1, 0x43, + 0xbd, 0x25, 0xb1, 0x5c, 0x54, 0x94, 0x8d, 0xd0, 0x5b, 0x9c, 0xaa, 0x25, 0x13, 0x09, 0x2e, 0xea, + 0x1f, 0xe7, 0xa1, 0x2a, 0x35, 0xef, 0xaf, 0x68, 0x33, 0xe8, 0x41, 0x10, 0x1e, 0x39, 0x81, 0x65, + 0x90, 0xc5, 0x29, 0x12, 0x8e, 0x29, 0x22, 0x8a, 0x70, 0x4f, 0x84, 0x98, 0xd1, 0x0d, 0x60, 0xa6, + 0x90, 0x59, 0x37, 0x80, 0x99, 0x42, 0x86, 0xdf, 0xea, 0xff, 0xc9, 0x41, 0x25, 0xdc, 0x26, 0x49, + 0x47, 0x17, 0xb9, 0x8c, 0xe8, 0xe2, 0x1a, 0x00, 0x23, 0x92, 0x6e, 0x3f, 0xb2, 0x98, 0xa8, 0xc7, + 0x79, 0x4c, 0x82, 0xa9, 0x6e, 0x5a, 0xfe, 0xc0, 0x39, 0xc1, 0xde, 0x19, 0x3f, 0x7a, 0xa8, 0x4d, + 0x82, 0xe9, 0x8e, 0x80, 0x11, 0x8f, 0x80, 0x58, 0x55, 0xd2, 0x9f, 0x13, 0xc7, 0x14, 0x37, 0xf1, + 0xaa, 0x1c, 0xb6, 0xef, 0x98, 0x98, 0xac, 0xf3, 0x3c, 0x3a, 0x8b, 0x5b, 0xba, 0x3a, 0x83, 0xb6, + 0xb2, 0x6f, 0x49, 0x97, 0xc4, 0x8d, 0x64, 0x71, 0x4b, 0x9a, 0x18, 0xc2, 0x60, 0xe0, 0xea, 0x13, + 0xdf, 0xe7, 0x7e, 0x5e, 0x29, 0x18, 0xb8, 0xfb, 0xbe, 0xaf, 0x3e, 0x84, 0xaa, 0xb4, 0xd5, 0x83, + 0x36, 0x61, 0x59, 0xde, 0x17, 0x8a, 0xfb, 0x1a, 0x4b, 0xd2, 0x3e, 0x10, 0x73, 0x34, 0xd4, 0x3f, + 0x29, 0x40, 0x23, 0xb1, 0xd9, 0x73, 0xbe, 0x0b, 0xc4, 0xb7, 0x8c, 0x22, 0x15, 0xab, 0x6b, 0x55, + 0x0e, 0xa3, 0xc3, 0x77, 0x03, 0xaa, 0xc7, 0x78, 0xec, 0x62, 0x4f, 0x77, 0xec, 0xb1, 0xe8, 0x36, + 0x60, 0xa0, 0xae, 0x3d, 0xa6, 0x26, 0xcd, 0xc4, 0x43, 0xec, 0x79, 0xc6, 0x98, 0x31, 0x61, 0xf7, + 0xb3, 0x6b, 0x02, 0x48, 0xb9, 0xdc, 0x87, 0x15, 0x7a, 0xab, 0x99, 0x3f, 0xe7, 0xd0, 0x85, 0x3c, + 0xec, 0x5c, 0x64, 0x59, 0xc6, 0xb5, 0xb9, 0x6c, 0xef, 0xc1, 0xd2, 0xd8, 0xb1, 0x47, 0x63, 0x7a, + 0x6b, 0x5a, 0xd0, 0x97, 0x98, 0xf9, 0x0d, 0x11, 0x82, 0xf8, 0x1e, 0x2c, 0xd1, 0x03, 0x3f, 0x9d, + 0xf6, 0x88, 0xaf, 0x87, 0x5a, 0x55, 0xd7, 0x1a, 0x14, 0x41, 0xfb, 0xd4, 0xa7, 0xb2, 0xdc, 0x83, + 0x25, 0xea, 0x4b, 0xc4, 0x5a, 0xce, 0x7c, 0x0a, 0xea, 0xa5, 0x6b, 0x52, 0xeb, 0xef, 0x70, 0xc7, + 0x9d, 0xd3, 0x46, 0xae, 0xf1, 0xa2, 0x44, 0x49, 0xec, 0x7f, 0x78, 0x76, 0x27, 0x51, 0x02, 0x3b, + 0xb3, 0xa2, 0x70, 0x89, 0x14, 0x41, 0x91, 0x6a, 0x17, 0x3b, 0xdd, 0xa4, 0xbf, 0xd5, 0x8f, 0x61, + 0x6d, 0xdf, 0x4d, 0x8c, 0x1b, 0x5f, 0xef, 0x66, 0x8e, 0x9e, 0xfa, 0x9f, 0x72, 0x70, 0x25, 0x55, + 0x8a, 0xad, 0x2e, 0xb3, 0x87, 0x5c, 0xb6, 0xe3, 0xec, 0x86, 0x47, 0x64, 0xf9, 0xe2, 0xb6, 0x9a, + 0x0f, 0xb5, 0x64, 0xab, 0x3f, 0x80, 0x65, 0x7e, 0x6b, 0xdc, 0xb3, 0x8e, 0xf4, 0x90, 0x4d, 0x51, + 0xbc, 0xe1, 0x35, 0xbb, 0x43, 0x7a, 0xba, 0x11, 0x1a, 0xd2, 0x86, 0x44, 0x4e, 0x6d, 0x2a, 0x1b, + 0xef, 0x9a, 0x20, 0x3d, 0x24, 0x2a, 0xfb, 0x9b, 0x1c, 0x2c, 0xa5, 0x9a, 0x81, 0x7e, 0x27, 0x61, + 0x54, 0x6e, 0x49, 0x76, 0x38, 0xbb, 0xa7, 0x42, 0xfb, 0xb2, 0x15, 0xb7, 0x2f, 0x37, 0xcf, 0x29, + 0x19, 0x33, 0x35, 0x2d, 0xa8, 0xf3, 0x8d, 0x4e, 0xde, 0xf5, 0xb3, 0xf6, 0xe3, 0xa4, 0xde, 0xcd, + 0xc7, 0x87, 0xe4, 0xef, 0xe5, 0xa0, 0xc6, 0x79, 0x84, 0xef, 0x1f, 0x5e, 0x8d, 0x45, 0x32, 0x76, + 0x2a, 0x5c, 0x22, 0x76, 0x2a, 0x66, 0xc5, 0x4e, 0xff, 0xb0, 0x00, 0x1b, 0x7c, 0x25, 0x19, 0xb3, + 0xa7, 0x69, 0xec, 0x64, 0x4e, 0xd8, 0xd1, 0xf7, 0x01, 0x19, 0xe3, 0xef, 0x8c, 0x33, 0x9f, 0xf8, + 0xac, 0xae, 0xe1, 0x61, 0x7d, 0x12, 0xbd, 0xc7, 0x66, 0x98, 0x6d, 0x86, 0xd8, 0xc7, 0x26, 0xba, + 0x0f, 0xab, 0xd6, 0xc8, 0x76, 0x3c, 0xe2, 0x31, 0x53, 0xc9, 0xc4, 0x8d, 0x0d, 0x7e, 0x89, 0x8d, + 0x21, 0x5b, 0x3e, 0x11, 0x91, 0xdd, 0xd2, 0x20, 0x31, 0x8f, 0x38, 0x73, 0x0f, 0xab, 0xa0, 0xd3, + 0x93, 0xc6, 0x3c, 0x4c, 0xbb, 0xd6, 0x04, 0x05, 0xaf, 0x8a, 0x0a, 0xec, 0x75, 0x4c, 0xf4, 0x05, + 0x5c, 0x0d, 0x15, 0x4f, 0xb7, 0x6c, 0x63, 0x10, 0x90, 0x55, 0x99, 0xcd, 0x6e, 0xae, 0x70, 0x6b, + 0x21, 0x41, 0x87, 0xe3, 0xd9, 0x24, 0x27, 0x3d, 0xc8, 0x3a, 0x53, 0x37, 0xac, 0x91, 0x2b, 0xce, + 0x5e, 0xf9, 0x13, 0x73, 0x6b, 0xe4, 0xa2, 0x2f, 0x60, 0x9d, 0x37, 0xc6, 0xc6, 0xa7, 0x81, 0x4e, + 0xcf, 0xee, 0x47, 0xae, 0x3e, 0xc1, 0x81, 0x67, 0x0d, 0xf8, 0x1a, 0x73, 0x85, 0x51, 0x1c, 0xe0, + 0xd3, 0xe0, 0x89, 0xe3, 0x76, 0x46, 0xee, 0x3e, 0xc5, 0xa2, 0x87, 0xb0, 0x61, 0xb2, 0x0b, 0xec, + 0xfa, 0x11, 0xf6, 0x03, 0xd6, 0x17, 0xbe, 0xe8, 0x62, 0xba, 0xe6, 0x94, 0xb5, 0x26, 0x27, 0x79, + 0x84, 0x7d, 0x7a, 0x02, 0x1a, 0x0e, 0x81, 0xfa, 0x0f, 0x0a, 0xb0, 0x9e, 0x39, 0x2a, 0x4c, 0x5d, + 0x7e, 0x3b, 0x28, 0x3f, 0xc8, 0xa0, 0xe4, 0x60, 0x35, 0x73, 0x50, 0xd0, 0xc3, 0xc4, 0x2a, 0x74, + 0x3b, 0x75, 0x20, 0x93, 0x35, 0xb7, 0xc2, 0x95, 0xe8, 0x8b, 0xf8, 0x4a, 0xf4, 0xf6, 0x05, 0xa5, + 0x63, 0xab, 0xd1, 0x03, 0xb8, 0xf2, 0xd4, 0xc7, 0x74, 0x1f, 0xc3, 0x1d, 0xd3, 0xa7, 0xed, 0xfe, + 0x85, 0x16, 0xe1, 0x3e, 0xac, 0x26, 0xcb, 0x5c, 0x60, 0x0f, 0xd4, 0x5f, 0x00, 0xb4, 0x8f, 0x46, + 0x2e, 0x67, 0x7d, 0x0f, 0x96, 0xd8, 0x16, 0xeb, 0x84, 0xf3, 0x20, 0x01, 0x32, 0x2b, 0xd1, 0xa0, + 0x08, 0xc1, 0xbb, 0x45, 0x37, 0x7d, 0x27, 0xc6, 0x29, 0x75, 0x28, 0xc5, 0xed, 0x0f, 0x6a, 0xf8, + 0x39, 0x90, 0x1d, 0xfb, 0xfc, 0x3e, 0x54, 0xda, 0x61, 0x10, 0xfa, 0xc6, 0xb9, 0xeb, 0x50, 0x24, + 0xdc, 0xd1, 0xfb, 0x89, 0x61, 0x5a, 0x89, 0x9f, 0x20, 0x26, 0x46, 0x65, 0xf6, 0x93, 0xa2, 0x50, + 0x54, 0x31, 0x08, 0xf7, 0x01, 0x3a, 0x51, 0xef, 0xa4, 0x64, 0xca, 0x65, 0xc8, 0xf4, 0x11, 0x54, + 0x3a, 0x61, 0x8b, 0x2f, 0x55, 0x42, 0x87, 0x62, 0xe7, 0x82, 0x56, 0x74, 0x5e, 0xa5, 0x15, 0x9d, + 0x64, 0x2b, 0xfe, 0x3c, 0x07, 0x4a, 0x52, 0x2f, 0xd0, 0xe7, 0x89, 0xda, 0x24, 0x33, 0x99, 0xad, + 0x77, 0x61, 0xcd, 0x9f, 0xc6, 0x6b, 0xbe, 0x31, 0xbb, 0x60, 0xec, 0x0e, 0xa2, 0x0a, 0x45, 0x7c, + 0x34, 0x72, 0xd3, 0xe9, 0x29, 0x48, 0xaf, 0x6b, 0x14, 0x47, 0x68, 0x2c, 0x42, 0x93, 0x4a, 0x01, + 0xd1, 0xa1, 0x34, 0x04, 0xa7, 0x3e, 0xe2, 0x76, 0xad, 0x6f, 0x78, 0x23, 0x1c, 0xec, 0xe3, 0xc9, + 0x11, 0xf6, 0xfc, 0x63, 0x4b, 0x1a, 0xa4, 0xb8, 0x3f, 0x9a, 0x4b, 0xfb, 0xa3, 0x6a, 0x8b, 0xaf, + 0xc2, 0x49, 0x1e, 0xe1, 0xa8, 0x5d, 0xcc, 0x22, 0x5c, 0x34, 0x92, 0x3c, 0x2e, 0x5c, 0x34, 0xb2, + 0x05, 0xbf, 0xec, 0xa2, 0x91, 0x29, 0xb2, 0x18, 0xe9, 0x5f, 0xc0, 0xf5, 0x3d, 0xc7, 0x1e, 0xed, + 0x11, 0xff, 0xeb, 0x15, 0xdd, 0xc9, 0x4b, 0x04, 0x03, 0xea, 0x7f, 0xcf, 0xc1, 0xb5, 0x59, 0xfc, + 0xbf, 0x4f, 0xc7, 0x33, 0xd3, 0x65, 0x2f, 0x66, 0xbb, 0xec, 0x5f, 0xc2, 0x7a, 0x8a, 0xd6, 0xd3, + 0xf1, 0xa9, 0x6b, 0x79, 0x61, 0xc0, 0xb1, 0x96, 0x28, 0xe4, 0xb5, 0x19, 0x5a, 0xfd, 0x47, 0x39, + 0x68, 0xce, 0x6a, 0x20, 0xfa, 0x69, 0x62, 0x5c, 0xa5, 0x5d, 0xf7, 0xf3, 0x3b, 0x3d, 0x1c, 0xda, + 0x87, 0xf1, 0xa1, 0xbd, 0x73, 0x31, 0x83, 0xd8, 0xe8, 0xfe, 0xd1, 0x3c, 0x2c, 0x70, 0xef, 0x12, + 0x7d, 0x05, 0xcb, 0x13, 0x57, 0x4f, 0x9d, 0xfc, 0x33, 0xc9, 0x36, 0xce, 0x71, 0x79, 0xb5, 0xa5, + 0x49, 0xca, 0xd9, 0xfe, 0x30, 0x6c, 0x59, 0x3e, 0x79, 0x6f, 0x23, 0xe6, 0x11, 0x87, 0x0d, 0x49, + 0x5e, 0x10, 0x29, 0x5c, 0xfa, 0x82, 0xc8, 0xcf, 0x60, 0x4d, 0x04, 0xb4, 0xdc, 0xf8, 0xf1, 0x2b, + 0x66, 0x62, 0xaf, 0xf9, 0xc6, 0x05, 0x46, 0x52, 0x5b, 0xf5, 0x32, 0x4d, 0xf5, 0x13, 0x40, 0x53, + 0x1f, 0x47, 0xa6, 0x85, 0xad, 0xb7, 0xf3, 0xc9, 0x13, 0xf9, 0xe4, 0x12, 0xa5, 0x29, 0xd3, 0xe4, + 0xca, 0x98, 0x3a, 0x09, 0x2d, 0x25, 0x5b, 0x37, 0xfb, 0x24, 0x34, 0x6c, 0x5e, 0x40, 0xa7, 0xa9, + 0x3e, 0x09, 0xe7, 0x29, 0xbf, 0x35, 0x72, 0xe3, 0x82, 0xe9, 0xcc, 0x9b, 0x97, 0x5a, 0x54, 0x0c, + 0xd8, 0x20, 0x51, 0xaf, 0xce, 0xe2, 0xe1, 0xd4, 0xb8, 0xb3, 0x5b, 0x26, 0xea, 0xc5, 0x0a, 0xa5, + 0x35, 0xc7, 0xb3, 0xf4, 0x3b, 0x76, 0xa7, 0xa3, 0x72, 0x89, 0x3b, 0x1d, 0xed, 0x30, 0x93, 0x91, + 0xe4, 0x9a, 0xf0, 0x49, 0x2d, 0xa6, 0x3f, 0xff, 0x44, 0x57, 0xa1, 0x4c, 0x37, 0xc8, 0x27, 0xc6, + 0x29, 0x5f, 0x59, 0x16, 0xc8, 0xf7, 0xbe, 0x71, 0xaa, 0xee, 0xd0, 0x37, 0x84, 0x71, 0x6f, 0xe5, + 0xd5, 0xb9, 0x7c, 0x0b, 0x65, 0xc1, 0x05, 0x7d, 0x94, 0x98, 0xa9, 0xcd, 0x74, 0x33, 0x12, 0x0a, + 0xfd, 0x41, 0x7c, 0x66, 0xae, 0xa5, 0x0b, 0xc4, 0x66, 0xe2, 0x14, 0x4a, 0xfc, 0x06, 0xe5, 0x06, + 0x54, 0x2c, 0x57, 0x8f, 0xdd, 0x63, 0x29, 0x5b, 0xe2, 0x7a, 0xe5, 0x3b, 0xd0, 0x98, 0x18, 0xfe, + 0xb7, 0xdc, 0x2d, 0xd7, 0x27, 0x3c, 0x23, 0x4c, 0x5d, 0xab, 0x13, 0x30, 0x73, 0xc9, 0xf7, 0x2d, + 0x3b, 0x45, 0x67, 0x9c, 0xf2, 0xb8, 0x4f, 0xa6, 0x33, 0x4e, 0xd5, 0x3f, 0xca, 0x01, 0x44, 0x2f, + 0xe6, 0xfe, 0x82, 0xcf, 0x1a, 0x09, 0x6c, 0x6c, 0xf9, 0x01, 0xbd, 0xd8, 0x5f, 0xd1, 0xe8, 0x6f, + 0xfa, 0x52, 0x2b, 0x7e, 0x9f, 0x52, 0x49, 0xaa, 0xbd, 0x74, 0x89, 0x72, 0x17, 0xca, 0xfb, 0x46, + 0x30, 0x38, 0x26, 0xc2, 0xdc, 0x89, 0x09, 0x23, 0xb9, 0x23, 0x94, 0xe2, 0x82, 0x17, 0x96, 0xcf, + 0xa0, 0x16, 0x0b, 0x53, 0x36, 0x63, 0xcc, 0xa4, 0xe9, 0x2b, 0x53, 0x49, 0x3c, 0xaf, 0x40, 0x49, + 0x0a, 0x7d, 0xea, 0x1a, 0xff, 0x52, 0xff, 0xcb, 0x3c, 0xc0, 0xb6, 0x63, 0x9b, 0x16, 0x5b, 0x23, + 0xee, 0x03, 0x7f, 0xd3, 0xaf, 0x47, 0xcf, 0x14, 0x51, 0x42, 0xd2, 0x43, 0x1c, 0x68, 0x15, 0x46, + 0x45, 0x9a, 0xf5, 0x29, 0xd4, 0xc2, 0xc3, 0x2d, 0x52, 0x28, 0x3f, 0xb3, 0x50, 0x78, 0x7f, 0x9c, + 0x14, 0xfb, 0x31, 0x2c, 0x26, 0x62, 0xb2, 0x42, 0x72, 0x6f, 0x5c, 0x6e, 0x8a, 0x56, 0x33, 0xe4, + 0xe6, 0x3f, 0x80, 0xaa, 0x28, 0x4d, 0xea, 0x2c, 0xce, 0x16, 0x94, 0x15, 0x23, 0x35, 0x7e, 0x16, + 0xe6, 0x51, 0x09, 0xce, 0x68, 0xa9, 0xf9, 0x99, 0xa5, 0x6a, 0x21, 0x21, 0x29, 0xf8, 0x13, 0x58, + 0x22, 0x01, 0x57, 0xbc, 0x70, 0x69, 0x66, 0xe1, 0x06, 0x3e, 0x0d, 0xb6, 0xe5, 0xf2, 0x37, 0xa0, + 0xea, 0xb9, 0xdf, 0x5a, 0x64, 0x29, 0x9a, 0x8e, 0x03, 0xba, 0xcc, 0xcd, 0x6b, 0xe0, 0xb1, 0x07, + 0xd5, 0xd3, 0x71, 0x80, 0x1e, 0x02, 0x44, 0xaf, 0xa4, 0xf9, 0x89, 0xb5, 0x74, 0xf4, 0x14, 0x8d, + 0x0f, 0x5f, 0x11, 0xc9, 0xb0, 0x56, 0xc2, 0x47, 0xd4, 0xe8, 0x11, 0x2c, 0x8f, 0xc9, 0x6a, 0x98, + 0x90, 0xb0, 0x32, 0x53, 0xc2, 0x25, 0x4a, 0x1e, 0x93, 0xf1, 0x0e, 0x28, 0x51, 0x54, 0x69, 0xeb, + 0x54, 0xed, 0x81, 0xaa, 0x7d, 0xdd, 0xe6, 0xc1, 0xa4, 0xbd, 0x47, 0xf4, 0xff, 0x23, 0xa8, 0x8a, + 0x7b, 0x70, 0xba, 0x65, 0xd3, 0xeb, 0x37, 0x8b, 0xf2, 0x14, 0x78, 0x4c, 0xb7, 0x6f, 0xb4, 0x0a, + 0xbf, 0x08, 0xd7, 0xb1, 0xd5, 0x63, 0xa8, 0x84, 0x62, 0xa3, 0x65, 0x68, 0x68, 0xdd, 0xa7, 0xfd, + 0xb6, 0xde, 0xff, 0xa6, 0x17, 0xbe, 0x4a, 0x59, 0x83, 0x65, 0x09, 0xd8, 0x39, 0xe8, 0xb7, 0xb5, + 0x83, 0xd6, 0x9e, 0x92, 0x4b, 0x20, 0xda, 0xcf, 0x39, 0x22, 0x8f, 0x56, 0x40, 0x91, 0x10, 0x3c, + 0xd1, 0x88, 0x3a, 0x84, 0x46, 0xd8, 0xa8, 0x16, 0x4b, 0x36, 0x74, 0x3f, 0x36, 0x4f, 0xae, 0xc9, + 0x9d, 0x1a, 0x23, 0x94, 0xa6, 0xca, 0x4d, 0xa8, 0x8a, 0x8e, 0xb4, 0xc2, 0x37, 0xeb, 0x32, 0x48, + 0x3d, 0x80, 0xca, 0x3e, 0x36, 0x79, 0x0d, 0xef, 0xc5, 0x6a, 0x58, 0x93, 0x4f, 0xc3, 0xcc, 0x14, + 0xef, 0x15, 0x98, 0x3f, 0x31, 0xc6, 0x53, 0x91, 0xd2, 0x83, 0x7d, 0xa8, 0x3a, 0x34, 0x5a, 0x7e, + 0xcf, 0xc3, 0x2e, 0xb6, 0x05, 0x57, 0x05, 0x0a, 0x86, 0x6f, 0x73, 0xbf, 0x9a, 0xfc, 0x24, 0x33, + 0x98, 0x50, 0x18, 0xe1, 0x31, 0x13, 0xfb, 0x42, 0x2a, 0xd4, 0x89, 0x59, 0x1f, 0xe3, 0x61, 0xa0, + 0x4f, 0x1c, 0x3f, 0xe0, 0xde, 0x61, 0x75, 0xea, 0xe3, 0x3d, 0x3c, 0x0c, 0xf6, 0x1d, 0xfa, 0xce, + 0xab, 0xce, 0x9f, 0x5a, 0x70, 0xf6, 0xe7, 0xa6, 0x47, 0xf0, 0xf1, 0x78, 0xc8, 0x3d, 0x50, 0xfa, + 0x5b, 0xbd, 0x03, 0x8d, 0x3d, 0x7a, 0x50, 0xe0, 0xe1, 0x21, 0x67, 0x10, 0x36, 0x84, 0x1f, 0x85, + 0xb1, 0x86, 0xfc, 0xd7, 0x02, 0x2c, 0x30, 0x02, 0x3f, 0xba, 0xb0, 0x69, 0xb0, 0x3d, 0x86, 0xd4, + 0x1a, 0x4c, 0x95, 0x82, 0x51, 0xf3, 0x0b, 0x9b, 0x9c, 0xf7, 0x67, 0x50, 0x89, 0x4e, 0x89, 0xf3, + 0xc9, 0x9b, 0x9a, 0x89, 0x81, 0xd3, 0x22, 0x5a, 0x74, 0x1b, 0x0a, 0x13, 0xee, 0x1e, 0xc7, 0xe2, + 0xbd, 0x70, 0x24, 0x34, 0x82, 0x47, 0x9f, 0x03, 0x90, 0xc5, 0x83, 0xf5, 0x37, 0x5f, 0x3b, 0xae, + 0xc6, 0x96, 0x1d, 0x79, 0x28, 0xe8, 0x12, 0xc2, 0x00, 0xe8, 0x27, 0x50, 0x8f, 0xad, 0x04, 0x7c, + 0x09, 0x39, 0x47, 0xba, 0x9a, 0xbc, 0x18, 0xa0, 0xfb, 0xb0, 0xc0, 0xdf, 0xc2, 0xf0, 0xf5, 0x43, + 0x52, 0x97, 0xd8, 0x00, 0x69, 0x82, 0x8e, 0x08, 0xcb, 0x8f, 0x6d, 0x3c, 0x3c, 0xe4, 0x2e, 0xd2, + 0x55, 0xd9, 0x8b, 0x89, 0x8d, 0x8b, 0x38, 0xd1, 0xf1, 0xf0, 0x10, 0x3d, 0x82, 0x46, 0x62, 0x59, + 0xe0, 0x4e, 0xd0, 0x39, 0xe2, 0x2e, 0xc6, 0x57, 0x06, 0xf5, 0x57, 0x39, 0xa8, 0x84, 0x8f, 0x53, + 0x43, 0xc3, 0x94, 0x93, 0x6c, 0xe4, 0x27, 0x00, 0x83, 0x70, 0x7d, 0xe2, 0xa3, 0xb5, 0x92, 0xb5, + 0x76, 0x69, 0x12, 0x1d, 0x7a, 0x0f, 0x16, 0x98, 0x5a, 0xf8, 0x7c, 0xb4, 0xe4, 0xbb, 0xb4, 0x0c, + 0xa1, 0x09, 0x0a, 0xf5, 0x6b, 0x28, 0x71, 0xdf, 0x38, 0x4b, 0x80, 0xf8, 0xf3, 0xf6, 0xfc, 0xe5, + 0x9e, 0xb7, 0xff, 0x8f, 0x1c, 0x28, 0xc9, 0xab, 0xa7, 0xe8, 0x6e, 0x6c, 0x26, 0xaf, 0x24, 0x2f, + 0xa9, 0x4a, 0xd3, 0x58, 0xce, 0x06, 0x95, 0xbf, 0x44, 0x36, 0xa8, 0xac, 0xfc, 0x97, 0xf2, 0x93, + 0xef, 0xe2, 0x45, 0x4f, 0xbe, 0xd1, 0x87, 0xb0, 0x60, 0xe2, 0xa1, 0x41, 0xec, 0xc7, 0xfc, 0x79, + 0x13, 0x49, 0x50, 0xa9, 0xbf, 0xce, 0x41, 0x9d, 0x20, 0xa2, 0x74, 0x4d, 0x9f, 0x42, 0xd5, 0x64, + 0x6e, 0x0f, 0x37, 0xee, 0xb3, 0x53, 0x32, 0x80, 0x19, 0xf9, 0x50, 0x0f, 0x61, 0x89, 0xc5, 0x30, + 0x3a, 0x05, 0x5a, 0xfc, 0xbe, 0x4c, 0xb6, 0xc0, 0x0a, 0x23, 0xdd, 0x09, 0x29, 0xd5, 0xbf, 0x9f, + 0x83, 0x82, 0xe6, 0x18, 0x68, 0x11, 0xf2, 0x86, 0xd8, 0xdd, 0xc9, 0x1b, 0x3e, 0x7a, 0x0b, 0xb8, + 0x0f, 0x31, 0xc6, 0xc2, 0xe7, 0x8b, 0x00, 0x64, 0xb1, 0x9b, 0x18, 0x14, 0xc5, 0x5f, 0xb3, 0xb0, + 0x2f, 0xe9, 0x46, 0x74, 0x31, 0x76, 0x23, 0x5a, 0x3c, 0xe4, 0x98, 0x3f, 0x3f, 0x59, 0x8e, 0x7a, + 0x87, 0x3d, 0x2a, 0x72, 0x8c, 0x8b, 0x12, 0xe0, 0xb0, 0x5c, 0x1f, 0x94, 0x30, 0xca, 0xf5, 0xe1, + 0x39, 0x46, 0x46, 0xae, 0x0f, 0x42, 0x44, 0x51, 0xea, 0xbf, 0xce, 0x41, 0xe1, 0x99, 0x37, 0xcc, + 0x54, 0xd3, 0xb7, 0x21, 0xef, 0x99, 0xd2, 0xfc, 0x48, 0xdf, 0x3c, 0xcd, 0x7b, 0x26, 0xba, 0x0f, + 0x15, 0x7e, 0x61, 0xda, 0x0b, 0xf8, 0x7b, 0xd2, 0x19, 0xd7, 0x54, 0x19, 0x99, 0x46, 0x53, 0x16, + 0xf0, 0x4b, 0xda, 0x5e, 0xc0, 0x15, 0x69, 0x46, 0x11, 0x46, 0xa6, 0x05, 0xfc, 0x66, 0x2b, 0xbb, + 0x81, 0x97, 0xb7, 0x4c, 0xf5, 0x37, 0x39, 0x58, 0xd9, 0x61, 0x7a, 0x43, 0x75, 0x69, 0xc7, 0xf2, + 0x03, 0xc3, 0x1e, 0x60, 0xb4, 0x05, 0xe1, 0x56, 0x37, 0xdb, 0xc5, 0xd6, 0x4d, 0x8e, 0xe2, 0xdd, + 0xb5, 0x2a, 0xd0, 0xa9, 0x72, 0xf4, 0xd0, 0x3c, 0xa3, 0x1c, 0x1b, 0xea, 0x55, 0x81, 0x8e, 0x95, + 0x53, 0xff, 0x5d, 0x11, 0x4a, 0xec, 0x8d, 0x70, 0x4a, 0x5f, 0x36, 0xa0, 0x12, 0x6d, 0xc3, 0xf3, + 0x6c, 0x70, 0x9e, 0xd8, 0x77, 0xbf, 0x01, 0x55, 0xe2, 0xb1, 0x60, 0x9b, 0x9d, 0x26, 0x17, 0x98, + 0x87, 0xc5, 0x40, 0xf4, 0x34, 0xf9, 0x5d, 0x50, 0x38, 0x01, 0xb7, 0x73, 0x7c, 0xd2, 0x55, 0xb4, + 0x06, 0x83, 0xb7, 0x04, 0x38, 0xf6, 0xec, 0x63, 0x3e, 0xf1, 0xec, 0xe3, 0xfd, 0xcc, 0x10, 0x9a, + 0x9f, 0xb9, 0xa6, 0xc2, 0xe4, 0x5f, 0xcc, 0x8e, 0xe4, 0x17, 0x5e, 0x65, 0xb3, 0x7c, 0x46, 0x3c, + 0xdf, 0x87, 0x2b, 0x7c, 0xb2, 0x27, 0xfb, 0x98, 0x2d, 0xf3, 0xd7, 0x63, 0x53, 0x3b, 0x35, 0xb8, + 0xda, 0x8a, 0x99, 0x35, 0xe4, 0x0f, 0xe9, 0xb5, 0x8b, 0x21, 0x36, 0xb1, 0xc7, 0x9e, 0xcc, 0x56, + 0x92, 0x86, 0x6a, 0x5b, 0x46, 0x6b, 0x71, 0xea, 0x37, 0xf4, 0xd8, 0x22, 0xb9, 0x7b, 0x52, 0xbd, + 0xec, 0xee, 0x89, 0xea, 0x40, 0x3d, 0x26, 0xdf, 0x39, 0xfb, 0x6d, 0xf1, 0xd7, 0xa6, 0xf9, 0xd4, + 0x6b, 0xd3, 0xb7, 0x61, 0x91, 0x6d, 0x4e, 0xe8, 0x86, 0xaf, 0x87, 0x71, 0x60, 0x5d, 0xab, 0x31, + 0x68, 0xcb, 0x27, 0xfe, 0xb0, 0xfa, 0x67, 0x39, 0xa8, 0xd0, 0x67, 0x74, 0x1d, 0x7b, 0xe8, 0x7c, + 0x2f, 0x2f, 0xf8, 0xee, 0x40, 0xc3, 0x9e, 0x4e, 0x74, 0xe9, 0xf5, 0x24, 0xbf, 0x88, 0xb2, 0x68, + 0x4f, 0x27, 0xf2, 0xeb, 0xd3, 0xab, 0x50, 0xb6, 0xf9, 0x3e, 0xba, 0xb8, 0xf7, 0x64, 0xb3, 0x2d, + 0x74, 0x74, 0x0b, 0x6a, 0x04, 0x15, 0x5e, 0x42, 0x63, 0x37, 0x4d, 0xaa, 0xf6, 0x74, 0xd2, 0xe2, + 0x20, 0xf5, 0xc7, 0x34, 0x17, 0x80, 0x66, 0x1d, 0x91, 0x86, 0x88, 0xe5, 0x51, 0x3c, 0x3c, 0x4b, + 0xa5, 0x42, 0x09, 0x9b, 0xcc, 0xde, 0xfe, 0xa8, 0x0f, 0x69, 0x42, 0xeb, 0xb0, 0x34, 0x5f, 0x33, + 0x2f, 0x5d, 0xdc, 0xa5, 0xe9, 0x66, 0xb6, 0x9d, 0x31, 0x7f, 0x88, 0x34, 0x33, 0xa1, 0xd4, 0x1a, + 0x2c, 0x98, 0x47, 0xba, 0xd4, 0x77, 0x25, 0xf3, 0x88, 0xde, 0x0c, 0xde, 0x84, 0x65, 0xfa, 0x8c, + 0x53, 0xa7, 0xf9, 0x24, 0x93, 0xb7, 0x7d, 0x28, 0x6a, 0x67, 0x3a, 0x71, 0xc3, 0xeb, 0x46, 0x2c, + 0x2d, 0x8d, 0x54, 0x23, 0x7f, 0x71, 0xb8, 0x04, 0x0d, 0x91, 0x0a, 0x54, 0xa4, 0x1e, 0x40, 0xa0, + 0x44, 0x20, 0x46, 0x76, 0xef, 0x0f, 0x0a, 0x50, 0x62, 0xa1, 0x0e, 0xaa, 0x41, 0x59, 0x6b, 0x1f, + 0xb6, 0xb5, 0x67, 0xed, 0x1d, 0x65, 0x0e, 0x01, 0x14, 0x3b, 0xbd, 0x93, 0x4f, 0x94, 0x97, 0x2f, + 0x8a, 0xfc, 0xf7, 0x96, 0xf2, 0xf2, 0x45, 0x19, 0xd5, 0x61, 0x81, 0xc0, 0xf5, 0xfd, 0x6d, 0xe5, + 0x57, 0x2f, 0x8a, 0xfc, 0x73, 0x8b, 0x7d, 0x96, 0x51, 0x03, 0x2a, 0x0c, 0xdb, 0xdb, 0x3b, 0x54, + 0xfe, 0xf0, 0x45, 0x91, 0x03, 0xb6, 0x04, 0xa0, 0x8c, 0x16, 0xa1, 0x4c, 0x29, 0x9e, 0xf5, 0x0e, + 0x94, 0x17, 0x2f, 0x8b, 0xfc, 0x7b, 0x8b, 0x7f, 0x97, 0xd1, 0x12, 0x54, 0x05, 0x9e, 0x30, 0x7d, + 0xf9, 0xb2, 0xc8, 0x41, 0x5b, 0x11, 0xa8, 0x4c, 0x24, 0x7a, 0x46, 0x38, 0xfe, 0x87, 0x17, 0x26, + 0xf9, 0xdd, 0x26, 0xa5, 0xff, 0xec, 0x85, 0x89, 0x2a, 0x50, 0xd0, 0xfa, 0xdb, 0xca, 0x1f, 0xbe, + 0x2c, 0x22, 0x05, 0x80, 0x32, 0x6a, 0x1f, 0x6c, 0xb7, 0x7a, 0xca, 0xdf, 0x7d, 0x21, 0x20, 0x5b, + 0x21, 0xa4, 0x8c, 0x56, 0x60, 0xf1, 0xf1, 0x5e, 0xf7, 0x67, 0xfa, 0x61, 0xaf, 0xbd, 0xad, 0xd3, + 0xe6, 0xfe, 0xfa, 0x65, 0x31, 0x05, 0xdd, 0x52, 0x7e, 0xfd, 0xb2, 0x8c, 0x9a, 0x80, 0xe2, 0xb4, + 0x54, 0xe4, 0xdf, 0xbc, 0x2c, 0xa6, 0x30, 0x5b, 0x1c, 0x53, 0x46, 0x57, 0x40, 0x89, 0x30, 0x7b, + 0x0f, 0x38, 0xdc, 0x44, 0x8b, 0x50, 0xea, 0xf6, 0x5a, 0x5f, 0x3f, 0x6d, 0x2b, 0xff, 0xeb, 0xe5, + 0x9f, 0xbc, 0x28, 0xde, 0xdb, 0x86, 0xb2, 0x98, 0x58, 0x08, 0xa0, 0xb4, 0xbb, 0xd7, 0x7d, 0xd4, + 0xda, 0x53, 0xe6, 0xa2, 0xe4, 0x93, 0xf4, 0xce, 0x63, 0x6b, 0xe7, 0xf7, 0xf4, 0xce, 0x81, 0x92, + 0x47, 0x55, 0x58, 0x20, 0xbf, 0xbb, 0x4f, 0xfb, 0x2c, 0x2b, 0xe5, 0x33, 0xed, 0xb1, 0x52, 0xbc, + 0xb7, 0x17, 0x7b, 0xf7, 0xcb, 0x56, 0x57, 0xa4, 0x40, 0x6d, 0xaf, 0xdb, 0xfd, 0xea, 0x69, 0x4f, + 0x6f, 0x3f, 0x6f, 0x6d, 0xf7, 0x95, 0x39, 0xb4, 0x04, 0x75, 0x0e, 0xd9, 0xeb, 0x1e, 0xec, 0xb6, + 0x35, 0x25, 0x87, 0x10, 0x2c, 0x72, 0xd0, 0xe1, 0x93, 0xae, 0xd6, 0x6f, 0x6b, 0x4a, 0xfe, 0xde, + 0xaf, 0xe8, 0x93, 0xf0, 0x70, 0x77, 0x89, 0xde, 0xb9, 0xd4, 0xda, 0x8f, 0x3b, 0xcf, 0x95, 0x39, + 0xa2, 0x29, 0x07, 0xed, 0xce, 0xee, 0x93, 0x47, 0x5d, 0x52, 0x7a, 0x01, 0x0a, 0xfd, 0xd6, 0x2e, + 0x17, 0xeb, 0x50, 0xef, 0xb5, 0xfa, 0x4f, 0x94, 0x02, 0xaa, 0x43, 0x65, 0xbb, 0xbb, 0xbf, 0xff, + 0xf4, 0xa0, 0xd3, 0xff, 0x46, 0x21, 0x63, 0x58, 0x6f, 0x3f, 0xef, 0xeb, 0x11, 0x68, 0x9e, 0x84, + 0xd0, 0x7b, 0x2d, 0x6d, 0xb7, 0x2d, 0x01, 0x4b, 0x8c, 0xf5, 0xf3, 0xbe, 0xfe, 0xa4, 0xdb, 0x53, + 0x16, 0xee, 0xbd, 0x0b, 0x95, 0x70, 0x53, 0x89, 0x5e, 0x03, 0x3f, 0xf8, 0x46, 0xbe, 0x0f, 0x0e, + 0x50, 0xea, 0x1c, 0x3c, 0x6b, 0x6b, 0x7d, 0x25, 0x7f, 0xef, 0x1e, 0x28, 0xc9, 0x2d, 0x23, 0x54, + 0x82, 0x7c, 0xfb, 0x6b, 0x65, 0x8e, 0xfc, 0xdd, 0x6d, 0x2b, 0x39, 0xf2, 0x77, 0xaf, 0xad, 0xe4, + 0xef, 0x7d, 0xc8, 0xaf, 0x5e, 0xf1, 0x38, 0x2d, 0xba, 0x69, 0x4e, 0x3a, 0x79, 0x7b, 0xbb, 0xdd, + 0xeb, 0x33, 0xe6, 0x5a, 0xfb, 0xf7, 0xda, 0xdb, 0x84, 0xf9, 0x53, 0x58, 0xce, 0x88, 0xb3, 0x49, + 0xa3, 0x42, 0xd9, 0xf5, 0xd6, 0x0e, 0x99, 0x36, 0x2b, 0xa0, 0x44, 0x20, 0xad, 0xbd, 0xdf, 0x7d, + 0x46, 0x2a, 0x5e, 0x85, 0x25, 0x19, 0xca, 0xaf, 0xb0, 0xdf, 0xfb, 0x00, 0xea, 0xb1, 0xe0, 0x9a, + 0xf4, 0xe0, 0x7e, 0x7b, 0x47, 0xdf, 0xef, 0x12, 0x56, 0x0d, 0xa8, 0x92, 0x0f, 0x41, 0x9e, 0xbb, + 0xf7, 0x3e, 0x40, 0xe4, 0xc1, 0x87, 0xe9, 0x87, 0x49, 0x27, 0xec, 0xf7, 0xba, 0x1a, 0x97, 0xb9, + 0xfd, 0x9c, 0xfe, 0xce, 0x3f, 0xf8, 0x8f, 0xb7, 0xa1, 0xbc, 0x4b, 0xd6, 0xa9, 0x96, 0x6b, 0xa1, + 0x3d, 0xa8, 0x4a, 0x19, 0x4a, 0xd0, 0x5b, 0xb1, 0xb8, 0x22, 0x91, 0xf8, 0x64, 0xfd, 0xda, 0x0c, + 0x2c, 0x5f, 0x59, 0xe6, 0x50, 0x07, 0x20, 0xca, 0x61, 0x82, 0x36, 0x64, 0xf2, 0x44, 0xba, 0x93, + 0xf5, 0xb7, 0xb2, 0x91, 0x21, 0xab, 0xc7, 0x50, 0x09, 0x33, 0xb7, 0x20, 0x69, 0xfb, 0x2f, 0x99, + 0xe2, 0x65, 0x7d, 0x23, 0x13, 0x17, 0xf2, 0xd9, 0x83, 0xaa, 0x94, 0xca, 0x5d, 0x6e, 0x60, 0x3a, + 0x37, 0xbc, 0xdc, 0xc0, 0xac, 0xfc, 0xef, 0x73, 0xe8, 0x29, 0x2c, 0xc6, 0x93, 0xb8, 0xa3, 0x1b, + 0xb2, 0x13, 0x92, 0x91, 0x1b, 0x7e, 0xfd, 0xe6, 0x6c, 0x02, 0x99, 0x6d, 0x3c, 0x37, 0xbb, 0xcc, + 0x36, 0x33, 0x37, 0xbc, 0xcc, 0x36, 0x3b, 0xad, 0x3b, 0x6b, 0xbb, 0xf4, 0x8f, 0x12, 0xe4, 0xb6, + 0xa7, 0xff, 0x37, 0x83, 0xdc, 0xf6, 0x8c, 0xff, 0xae, 0xa0, 0xce, 0x21, 0x0d, 0xea, 0xb1, 0xbc, + 0xd5, 0xe8, 0x7a, 0xcc, 0xfa, 0xa7, 0x39, 0xde, 0x98, 0x89, 0x0f, 0x79, 0xfe, 0x75, 0x58, 0x4a, + 0xe5, 0xc3, 0x46, 0xea, 0xc5, 0x79, 0xb9, 0xd7, 0x7f, 0x74, 0x2e, 0x4d, 0xc8, 0xff, 0xaf, 0x45, + 0x96, 0x2d, 0x64, 0x2f, 0xdd, 0x23, 0x9b, 0x91, 0x6e, 0x7b, 0x5d, 0x3d, 0x8f, 0x44, 0x1e, 0xb5, + 0x78, 0x16, 0x6c, 0x79, 0xd4, 0x32, 0x53, 0x6a, 0xcb, 0xa3, 0x36, 0x23, 0x81, 0xf6, 0x1c, 0x7a, + 0x0e, 0x8d, 0x44, 0xa2, 0x6b, 0x24, 0xeb, 0x50, 0x66, 0x76, 0xed, 0xf5, 0x5b, 0xe7, 0x50, 0x84, + 0x9c, 0x1f, 0x42, 0x89, 0xf9, 0x30, 0x68, 0x2d, 0x36, 0xd8, 0x51, 0xfa, 0x83, 0xf5, 0x66, 0x1a, + 0x11, 0x16, 0xff, 0x0c, 0x16, 0x78, 0x3e, 0x07, 0x14, 0x27, 0x93, 0x52, 0x3c, 0xac, 0x27, 0x52, + 0x7f, 0xa8, 0x73, 0x1f, 0xe5, 0x88, 0x1e, 0x4a, 0xb9, 0x0f, 0x64, 0x3d, 0x4c, 0x27, 0x60, 0x90, + 0xf5, 0x30, 0x2b, 0x61, 0xc2, 0x1c, 0xfa, 0x29, 0x2c, 0xf0, 0x13, 0x19, 0x94, 0x3e, 0xd5, 0x11, + 0x5c, 0xae, 0x66, 0x60, 0xe4, 0x65, 0x2a, 0xfa, 0x77, 0x11, 0xf2, 0x32, 0x95, 0xfa, 0x87, 0x17, + 0xf2, 0x32, 0x95, 0xf1, 0x1f, 0x26, 0xe6, 0xd0, 0x0e, 0x40, 0x94, 0x88, 0x59, 0x66, 0x95, 0x4a, + 0xcf, 0xbc, 0x9e, 0x9d, 0x35, 0x84, 0x76, 0xd0, 0x97, 0x61, 0xf2, 0xe9, 0xe8, 0x95, 0x8f, 0xe4, + 0x4c, 0x86, 0xff, 0xaf, 0x64, 0x3d, 0xf1, 0x3f, 0x20, 0x68, 0xe1, 0xc7, 0x50, 0x09, 0xb3, 0x81, + 0xcb, 0x2b, 0x65, 0x32, 0x17, 0xb9, 0xbc, 0x52, 0xa6, 0xd3, 0x87, 0xb3, 0x5e, 0x09, 0x73, 0x85, + 0xc7, 0x7a, 0x25, 0x99, 0x56, 0x3c, 0xd6, 0x2b, 0xe9, 0xf4, 0xe2, 0x73, 0xe8, 0x09, 0x54, 0xc2, + 0xfc, 0xde, 0xb2, 0x48, 0xc9, 0xac, 0xe3, 0xb2, 0x48, 0xe9, 0x84, 0xe0, 0x73, 0x77, 0x73, 0x44, + 0x65, 0x59, 0x46, 0x6d, 0xb4, 0x36, 0x23, 0xa1, 0xf7, 0x7a, 0x33, 0x8d, 0x90, 0xad, 0x48, 0x98, + 0x3c, 0x5b, 0x16, 0x24, 0x99, 0x93, 0x7b, 0x7d, 0x23, 0x13, 0x27, 0xeb, 0x1c, 0x4f, 0x17, 0x9c, + 0x50, 0x7d, 0x29, 0xcf, 0xac, 0xac, 0x73, 0x89, 0xdc, 0xc2, 0xa1, 0xd6, 0x26, 0x39, 0xc4, 0xd3, + 0x08, 0x27, 0xb4, 0x36, 0xc1, 0x21, 0xd4, 0x5a, 0xca, 0x24, 0x25, 0xb0, 0xcc, 0xe7, 0xad, 0x6c, + 0xa4, 0xcc, 0x2a, 0xca, 0xe4, 0x8b, 0x52, 0x7a, 0x31, 0x83, 0x55, 0x46, 0xf2, 0x5f, 0x6a, 0x63, + 0xa4, 0x74, 0xbe, 0x28, 0xad, 0x19, 0x32, 0xb3, 0x6b, 0x33, 0xb0, 0xf2, 0x78, 0x85, 0xc9, 0x78, + 0xe5, 0xf1, 0x4a, 0xe6, 0xf4, 0x95, 0xc7, 0x2b, 0x9d, 0xbd, 0x97, 0xda, 0xaa, 0x58, 0x62, 0x5f, + 0xd9, 0x56, 0x65, 0xe5, 0x08, 0x96, 0x6d, 0x55, 0x76, 0x46, 0xe0, 0x70, 0xf5, 0x74, 0x8c, 0xe4, + 0xea, 0x19, 0x6e, 0xb6, 0x25, 0x57, 0xcf, 0x68, 0x73, 0x8d, 0x75, 0x94, 0x94, 0x84, 0x17, 0xa5, + 0xfa, 0x55, 0x4e, 0x34, 0x2c, 0x77, 0x54, 0x56, 0xe6, 0xde, 0x39, 0x3e, 0x2f, 0x9e, 0x79, 0xc3, + 0xc4, 0xbc, 0x88, 0x12, 0xe8, 0x26, 0xe6, 0x85, 0x9c, 0x24, 0x57, 0x9a, 0x17, 0x84, 0x43, 0x6a, + 0x5e, 0x48, 0x4c, 0x36, 0x32, 0x71, 0x89, 0x3e, 0x49, 0x88, 0x11, 0x4b, 0x2a, 0x9c, 0xe8, 0x93, + 0x78, 0x71, 0x8d, 0xee, 0x56, 0x4a, 0xe7, 0xd9, 0xd7, 0x63, 0xc4, 0xa9, 0xf4, 0xb2, 0xf2, 0x30, + 0x65, 0xe6, 0xe3, 0x65, 0x3c, 0x63, 0x79, 0x72, 0x65, 0x9e, 0x59, 0x09, 0x78, 0x65, 0x9e, 0xd9, + 0x09, 0x76, 0xa9, 0x1b, 0x91, 0xcc, 0x86, 0x2b, 0xbb, 0x11, 0x33, 0xd2, 0xef, 0xca, 0x6e, 0xc4, + 0xcc, 0x64, 0xba, 0xd4, 0x07, 0x4a, 0xa5, 0xc2, 0x95, 0x7d, 0xa0, 0x59, 0xb9, 0x76, 0x65, 0x1f, + 0x68, 0x76, 0x2e, 0xdd, 0x39, 0xd4, 0x85, 0x9a, 0x9c, 0x36, 0x17, 0xc5, 0x1d, 0xbd, 0x64, 0x86, + 0xd8, 0xf5, 0xeb, 0xb3, 0xd0, 0x32, 0x43, 0x39, 0xe1, 0x2d, 0x8a, 0x7b, 0xcd, 0xe7, 0x31, 0xcc, + 0xcc, 0x93, 0xcb, 0x3c, 0x9e, 0x78, 0x2a, 0x5b, 0x94, 0xf2, 0x9a, 0x53, 0x6c, 0x6f, 0x9d, 0x43, + 0x21, 0x0f, 0x5c, 0x32, 0x77, 0xad, 0x3c, 0x70, 0x33, 0xb2, 0xe4, 0xae, 0xab, 0xe7, 0x91, 0x24, + 0x42, 0x14, 0x7e, 0xf8, 0x10, 0x0f, 0x51, 0x62, 0x99, 0x58, 0x13, 0x21, 0x4a, 0x22, 0xed, 0x29, + 0xe5, 0x13, 0x66, 0xfa, 0x94, 0xf9, 0x24, 0x53, 0xe0, 0xca, 0x7c, 0xd2, 0x49, 0x6a, 0xe9, 0xb8, + 0xc8, 0x39, 0x3a, 0xe5, 0x71, 0xc9, 0xc8, 0x5e, 0xbb, 0x7e, 0x7d, 0x16, 0x3a, 0xee, 0xf1, 0x4b, + 0x49, 0x37, 0xe3, 0x1e, 0x7f, 0x3a, 0xe5, 0x6c, 0xdc, 0xe3, 0xcf, 0xca, 0xf1, 0x4a, 0x85, 0x94, + 0xff, 0x79, 0x8a, 0x2c, 0x64, 0xc6, 0xff, 0x70, 0x91, 0x85, 0xcc, 0xfc, 0x9f, 0x2b, 0x73, 0xc8, + 0xa4, 0xc9, 0xa2, 0x53, 0x67, 0x5d, 0x6f, 0x67, 0xf4, 0x79, 0x2a, 0x25, 0xe9, 0xfa, 0xed, 0x0b, + 0xa8, 0xe4, 0x5a, 0x32, 0xb2, 0xb1, 0xca, 0xb5, 0xcc, 0x4e, 0x03, 0x2b, 0xd7, 0x72, 0x5e, 0x4a, + 0xd7, 0x39, 0x34, 0x09, 0xff, 0xef, 0x55, 0xb2, 0xa2, 0x3b, 0xd9, 0x83, 0x95, 0xae, 0xeb, 0xee, + 0xc5, 0x84, 0x61, 0x75, 0x6e, 0x98, 0x27, 0x3a, 0x7d, 0x54, 0x38, 0x63, 0x24, 0xd3, 0x15, 0xbe, + 0x7b, 0x09, 0x4a, 0xd9, 0xf1, 0x88, 0x76, 0x51, 0xd1, 0x46, 0x32, 0xd8, 0x90, 0x76, 0x66, 0xd7, + 0xdf, 0xca, 0x46, 0x26, 0x56, 0xa1, 0x28, 0x9b, 0x55, 0x7c, 0x15, 0x4a, 0xfe, 0x3f, 0xaf, 0xc4, + 0x2a, 0x94, 0xfe, 0x4f, 0x60, 0xd2, 0x2a, 0x14, 0xf1, 0x4c, 0xad, 0x42, 0x29, 0xb6, 0xb7, 0xce, + 0xa1, 0x90, 0x39, 0x27, 0xfe, 0xdd, 0x17, 0x4a, 0x85, 0xef, 0xe7, 0x71, 0x9e, 0xf1, 0xbf, 0xc2, + 0xd4, 0x39, 0x64, 0xd0, 0x7f, 0x71, 0x97, 0x4c, 0xab, 0xf4, 0xa3, 0xb8, 0x45, 0xcb, 0xfc, 0xe7, + 0x60, 0xeb, 0x6f, 0x9f, 0x4f, 0x94, 0xe8, 0xe7, 0x70, 0x1f, 0x39, 0xd1, 0xcf, 0xc9, 0x1d, 0xed, + 0x44, 0x3f, 0xa7, 0xb7, 0x9f, 0xe7, 0xd0, 0x36, 0x94, 0x45, 0x50, 0x8d, 0xae, 0xa6, 0x03, 0x6d, + 0xc1, 0x68, 0x3d, 0x0b, 0x25, 0x98, 0x1c, 0x95, 0xe8, 0xc9, 0xdf, 0xc7, 0xff, 0x2f, 0x00, 0x00, + 0xff, 0xff, 0xaf, 0xa4, 0x81, 0xd6, 0x9a, 0x72, 0x00, 0x00, } diff -Nru gobgp-1.32/api/gobgp.proto gobgp-1.33/api/gobgp.proto --- gobgp-1.32/api/gobgp.proto 2018-06-01 11:32:28.000000000 +0000 +++ gobgp-1.33/api/gobgp.proto 2018-07-01 12:06:57.000000000 +0000 @@ -21,6 +21,8 @@ syntax = "proto3"; +import "google/protobuf/any.proto"; + package gobgpapi; // Interface exported by the server. @@ -74,16 +76,23 @@ rpc AddPolicy(AddPolicyRequest) returns (AddPolicyResponse) {} rpc DeletePolicy(DeletePolicyRequest) returns (DeletePolicyResponse) {} rpc ReplacePolicy(ReplacePolicyRequest) returns (ReplacePolicyResponse) {} + rpc UpdatePolicy(UpdatePolicyRequest) returns (UpdatePolicyResponse) {} rpc GetPolicyAssignment(GetPolicyAssignmentRequest) returns (GetPolicyAssignmentResponse) {} rpc AddPolicyAssignment(AddPolicyAssignmentRequest) returns (AddPolicyAssignmentResponse) {} rpc DeletePolicyAssignment(DeletePolicyAssignmentRequest) returns (DeletePolicyAssignmentResponse) {} rpc ReplacePolicyAssignment(ReplacePolicyAssignmentRequest) returns (ReplacePolicyAssignmentResponse) {} rpc GetRibInfo(GetRibInfoRequest) returns (GetRibInfoResponse) {} + rpc AddPeerGroup(AddPeerGroupRequest) returns (AddPeerGroupResponse) {} + rpc DeletePeerGroup(DeletePeerGroupRequest) returns (DeletePeerGroupResponse) {} + rpc UpdatePeerGroup(UpdatePeerGroupRequest) returns (UpdatePeerGroupResponse) {} + rpc AddDynamicNeighbor(AddDynamicNeighborRequest) returns (AddDynamicNeighborResponse) {} + rpc AddCollector(AddCollectorRequest) returns (AddCollectorResponse) {} + rpc Shutdown(ShutdownRequest) returns (ShutdownResponse) {} } // Constants for address families enum Family { - _ = 0; + RESERVED = 0; IPv4 = 65537; IPv6 = 131073; IPv4_MC = 65538; @@ -172,6 +181,36 @@ bool needs_soft_reset_in = 1; } +message AddPeerGroupRequest { + PeerGroup peer_group = 1; +} + +message AddPeerGroupResponse { +} + +message DeletePeerGroupRequest { + PeerGroup peer_group = 1; +} + +message DeletePeerGroupResponse { +} + +message UpdatePeerGroupRequest { + PeerGroup peer_group = 1; + bool do_soft_reset_in = 2; +} + +message UpdatePeerGroupResponse { + bool needs_soft_reset_in = 1; +} + +message AddDynamicNeighborRequest { + DynamicNeighbor dynamic_neighbor = 1; +} + +message AddDynamicNeighborResponse { +} + message ResetNeighborRequest { string address = 1; string communication = 2; @@ -216,6 +255,14 @@ message DisableNeighborResponse { } +message UpdatePolicyRequest { + repeated DefinedSet sets = 1; + repeated Policy policies = 2; +} + +message UpdatePolicyResponse { +} + message EnableMrtRequest { int32 dump_type = 1; string filename = 2; @@ -584,6 +631,24 @@ 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; } message Destination { @@ -656,6 +721,29 @@ AddPaths add_paths = 12; } +message PeerGroup { + // Note: Regarding to the consistency with OpenConfig model, a list of + // address family should be removed from here, and should be configured with + // the list of AfiSafi instead. + repeated uint32 families = 1; + ApplyPolicy apply_policy = 2; + PeerGroupConf conf = 3; + EbgpMultihop ebgp_multihop = 4; + RouteReflector route_reflector = 5; + PeerGroupState info = 6; + Timers timers = 7; + Transport transport = 8; + RouteServer route_server = 9; + GracefulRestart graceful_restart = 10; + repeated AfiSafi afi_safis = 11; + AddPaths add_paths = 12; +} + +message DynamicNeighbor { + string prefix = 1; + string peer_group = 2; +} + message ApplyPolicy { PolicyAssignment in_policy = 1; PolicyAssignment export_policy = 2; @@ -684,8 +772,10 @@ RemovePrivateAs remove_private_as = 8; bool route_flap_damping = 9; uint32 send_community = 10; - repeated bytes remote_cap = 11; - repeated bytes local_cap = 12; + // 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; // Note: Regarding to the consistency with OpenConfig model, list of // PrefixLimit should be removed from here, and list of PrefixLimit in @@ -698,6 +788,42 @@ bool replace_peer_as = 19; } +message PeerGroupConf { + string auth_password = 1; + string description = 2; + uint32 local_as = 3; + uint32 peer_as = 5; + string peer_group_name = 6; + uint32 peer_type = 7; + enum RemovePrivateAs { + NONE = 0; + ALL = 1; + REPLACE = 2; + } + RemovePrivateAs remove_private_as = 8; + bool route_flap_damping = 9; + uint32 send_community = 10; +} + +message PeerGroupState { + string auth_password = 1; + string description = 2; + uint32 local_as = 3; + uint32 peer_as = 5; + string peer_group_name = 6; + uint32 peer_type = 7; + enum RemovePrivateAs { + NONE = 0; + ALL = 1; + REPLACE = 2; + } + RemovePrivateAs remove_private_as = 8; + bool route_flap_damping = 9; + uint32 send_community = 10; + uint32 total_paths = 11; + uint32 total_prefixes = 12; +} + message EbgpMultihop { bool enabled = 1; uint32 multihop_ttl = 2; @@ -800,6 +926,11 @@ uint32 deferral_time = 4; bool notification_enabled = 5; bool longlived_enabled = 6; + uint32 stale_routes_time = 7; + uint32 peer_restart_time = 8; + bool peer_restarting = 9; + bool local_restarting = 10; + string mode = 11; } message MpGracefulRestartConfig { @@ -837,6 +968,7 @@ bool advertise_inactive_routes = 4; bool enable_aigp = 5; bool ignore_next_hop_igp_metric = 6; + bool disable_best_path_selection = 7; } message RouteSelectionOptionsState { @@ -846,6 +978,7 @@ bool advertise_inactive_routes = 4; bool enable_aigp = 5; bool ignore_next_hop_igp_metric = 6; + bool disable_best_path_selection = 7; } message RouteSelectionOptions { @@ -980,6 +1113,7 @@ COMMUNITY = 4; EXT_COMMUNITY = 5; LARGE_COMMUNITY = 6; + NEXT_HOP = 7; } message DefinedSet { @@ -1027,6 +1161,8 @@ } RouteType route_type = 8; MatchSet large_community_set = 9; + repeated string next_hop_in_list = 10; + repeated Family afi_safi_in = 11; } enum RouteAction { @@ -1107,6 +1243,11 @@ RouteAction default = 5; } +message RoutingPolicy { + repeated DefinedSet defined_set = 1; + repeated Policy policy_definition = 2; +} + message Roa { uint32 as = 1; uint32 prefixlen = 2; @@ -1125,12 +1266,29 @@ message Vrf { string name = 1; - bytes rd = 2; - repeated bytes import_rt = 3; - repeated bytes export_rt = 4; + // Route Distinguisher must be one of + // RouteDistinguisherTwoOctetAS, + // RouteDistinguisherIPAddressAS, + // or RouteDistinguisherFourOctetAS. + google.protobuf.Any rd = 2; + // List of the Import Route Targets. Each must be one of + // TwoOctetAsSpecificExtended, + // IPv4AddressSpecificExtended, + // or FourOctetAsSpecificExtended. + repeated google.protobuf.Any import_rt = 3; + // List of the Export Route Targets. Each must be one of + // TwoOctetAsSpecificExtended, + // IPv4AddressSpecificExtended, + // or FourOctetAsSpecificExtended. + repeated google.protobuf.Any export_rt = 4; uint32 id = 5; } +message DefaultRouteDistance { + uint32 external_route_distance = 1; + uint32 internal_route_distance = 2; +} + message Global { uint32 as = 1; string router_id = 2; @@ -1138,6 +1296,17 @@ repeated string listen_addresses = 4; repeated uint32 families = 5; bool use_multiple_paths = 6; + RouteSelectionOptionsConfig route_selection_options = 7; + DefaultRouteDistance default_route_distance = 8; + Confederation confederation = 9; + GracefulRestart graceful_restart = 10; + ApplyPolicy apply_policy = 11; +} + +message Confederation { + bool enabled = 1; + uint32 identifier = 2; + repeated uint32 member_as_list = 3; } message TableInfo { @@ -1156,3 +1325,18 @@ message GetRibInfoResponse { TableInfo info = 1; } + +message AddCollectorRequest { + string url = 1; + string db_name = 2; + uint64 table_dump_interval = 3; +} + +message AddCollectorResponse { +} + +message ShutdownRequest{ +} + +message ShutdownResponse{ +} \ No newline at end of file diff -Nru gobgp-1.32/api/grpc_server.go gobgp-1.33/api/grpc_server.go --- gobgp-1.32/api/grpc_server.go 2018-06-01 11:32:28.000000000 +0000 +++ gobgp-1.33/api/grpc_server.go 2018-07-01 12:06:57.000000000 +0000 @@ -28,6 +28,7 @@ "time" farm "github.com/dgryski/go-farm" + "github.com/golang/protobuf/ptypes/any" log "github.com/sirupsen/logrus" "golang.org/x/net/context" "google.golang.org/grpc" @@ -36,6 +37,7 @@ "github.com/osrg/gobgp/packet/bgp" "github.com/osrg/gobgp/server" "github.com/osrg/gobgp/table" + "github.com/osrg/gobgp/zebra" ) type Server struct { @@ -67,7 +69,7 @@ serve := func(host string) { defer wg.Done() - lis, err := net.Listen("tcp", fmt.Sprintf(host)) + lis, err := net.Listen("tcp", host) if err != nil { log.WithFields(log.Fields{ "Topic": "grpc", @@ -239,14 +241,13 @@ if pconf.Transport.State.LocalAddress != "" { localAddress = pconf.Transport.State.LocalAddress } - var remoteCap, localCap [][]byte - for _, c := range pconf.State.RemoteCapabilityList { - cBuf, _ := c.Serialize() - remoteCap = append(remoteCap, cBuf) - } - for _, c := range pconf.State.LocalCapabilityList { - cBuf, _ := c.Serialize() - localCap = append(localCap, cBuf) + remoteCap, err := MarshalCapabilities(pconf.State.RemoteCapabilityList) + if err != nil { + return nil + } + localCap, err := MarshalCapabilities(pconf.State.LocalCapabilityList) + if err != nil { + return nil } var removePrivateAs PeerConf_RemovePrivateAs switch pconf.Config.RemovePrivateAs { @@ -323,6 +324,75 @@ }, RouteReflector: &RouteReflector{ RouteReflectorClient: pconf.RouteReflector.Config.RouteReflectorClient, + RouteReflectorClusterId: string(pconf.RouteReflector.State.RouteReflectorClusterId), + }, + RouteServer: &RouteServer{ + RouteServerClient: pconf.RouteServer.Config.RouteServerClient, + }, + GracefulRestart: &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: &Transport{ + RemotePort: uint32(pconf.Transport.Config.RemotePort), + LocalAddress: pconf.Transport.Config.LocalAddress, + PassiveMode: pconf.Transport.Config.PassiveMode, + }, + AfiSafis: afiSafis, + AddPaths: NewAddPathsFromConfigStruct(&pconf.AddPaths), + } +} + +func NewPeerGroupFromConfigStruct(pconf *config.PeerGroup) *PeerGroup { + families := make([]uint32, 0, len(pconf.AfiSafis)) + afiSafis := make([]*AfiSafi, 0, len(pconf.AfiSafis)) + for _, f := range pconf.AfiSafis { + families = append(families, extractFamilyFromConfigAfiSafi(&f)) + if afiSafi := NewAfiSafiFromConfigStruct(&f); afiSafi != nil { + afiSafis = append(afiSafis, afiSafi) + } + } + + timer := pconf.Timers + s := pconf.State + return &PeerGroup{ + Families: families, + ApplyPolicy: NewApplyPolicyFromConfigStruct(&pconf.ApplyPolicy), + Conf: &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: &PeerGroupState{ + PeerAs: s.PeerAs, + PeerType: uint32(s.PeerType.ToInt()), + TotalPaths: s.TotalPaths, + TotalPrefixes: s.TotalPrefixes, + }, + Timers: &Timers{ + Config: &TimersConfig{ + ConnectRetry: uint64(timer.Config.ConnectRetry), + HoldTime: uint64(timer.Config.HoldTime), + KeepaliveInterval: uint64(timer.Config.KeepaliveInterval), + }, + State: &TimersState{ + KeepaliveInterval: uint64(timer.State.KeepaliveInterval), + NegotiatedHoldTime: uint64(timer.State.NegotiatedHoldTime), + Uptime: uint64(timer.State.Uptime), + Downtime: uint64(timer.State.Downtime), + }, + }, + RouteReflector: &RouteReflector{ + RouteReflectorClient: pconf.RouteReflector.Config.RouteReflectorClient, RouteReflectorClusterId: string(pconf.RouteReflector.Config.RouteReflectorClusterId), }, RouteServer: &RouteServer{ @@ -335,10 +405,12 @@ DeferralTime: uint32(pconf.GracefulRestart.Config.DeferralTime), NotificationEnabled: pconf.GracefulRestart.Config.NotificationEnabled, LonglivedEnabled: pconf.GracefulRestart.Config.LongLivedEnabled, + LocalRestarting: pconf.GracefulRestart.State.LocalRestarting, }, Transport: &Transport{ RemotePort: uint32(pconf.Transport.Config.RemotePort), LocalAddress: pconf.Transport.Config.LocalAddress, + PassiveMode: pconf.Transport.Config.PassiveMode, }, AfiSafis: afiSafis, AddPaths: NewAddPathsFromConfigStruct(&pconf.AddPaths), @@ -369,26 +441,16 @@ } } -func ToPathApi(path *table.Path, v *table.Validation) *Path { +func toPathAPI(binNlri []byte, binPattrs [][]byte, anyNlri *any.Any, anyPattrs []*any.Any, path *table.Path, v *table.Validation) *Path { nlri := path.GetNlri() - n, _ := nlri.Serialize() - family := uint32(bgp.AfiSafiToRouteFamily(nlri.AFI(), nlri.SAFI())) - pattrs := func(arg []bgp.PathAttributeInterface) [][]byte { - ret := make([][]byte, 0, len(arg)) - for _, a := range arg { - aa, _ := a.Serialize() - ret = append(ret, aa) - } - return ret - }(path.GetPathAttrs()) + family := uint32(path.GetRouteFamily()) vv := config.RPKI_VALIDATION_RESULT_TYPE_NONE.ToInt() if v != nil { vv = v.Status.ToInt() } - p := &Path{ - Nlri: n, - Pattrs: pattrs, + Nlri: binNlri, + Pattrs: binPattrs, Age: path.GetTimestamp().Unix(), IsWithdraw: path.IsWithdraw, Validation: int32(vv), @@ -400,6 +462,8 @@ IsNexthopInvalid: path.IsNexthopInvalid, Identifier: nlri.PathIdentifier(), LocalIdentifier: nlri.PathLocalIdentifier(), + AnyNlri: anyNlri, + AnyPattrs: anyPattrs, } if s := path.GetSource(); s != nil { p.SourceAsn = s.AS @@ -409,6 +473,33 @@ return p } +func ToPathApiInBin(path *table.Path, v *table.Validation) *Path { + nlri := path.GetNlri() + binNlri, _ := nlri.Serialize() + if path.IsWithdraw { + return toPathAPI(binNlri, nil, nil, nil, path, v) + } + binPattrs := func(attrs []bgp.PathAttributeInterface) [][]byte { + bufList := make([][]byte, 0, len(attrs)) + for _, a := range attrs { + buf, _ := a.Serialize() + bufList = append(bufList, buf) + } + return bufList + }(path.GetPathAttrs()) + return toPathAPI(binNlri, binPattrs, nil, nil, path, v) +} + +func ToPathApi(path *table.Path, v *table.Validation) *Path { + nlri := path.GetNlri() + anyNlri := MarshalNLRI(nlri) + if path.IsWithdraw { + return toPathAPI(nil, nil, anyNlri, nil, path, v) + } + anyPattrs := MarshalPathAttributes(path.GetPathAttrs()) + return toPathAPI(nil, nil, anyNlri, anyPattrs, path, v) +} + func getValidation(v []*table.Validation, i int) *table.Validation { if v == nil { return nil @@ -596,31 +687,30 @@ } return nil } - for { - select { - case ev := <-w.Event(): - switch msg := ev.(type) { - case *server.WatchEventBestPath: - if err := sendPath(func() []*table.Path { - if len(msg.MultiPathList) > 0 { - l := make([]*table.Path, 0) - for _, p := range msg.MultiPathList { - l = append(l, p...) - } - return l - } else { - return msg.PathList + + for ev := range w.Event() { + switch msg := ev.(type) { + case *server.WatchEventBestPath: + if err := sendPath(func() []*table.Path { + if len(msg.MultiPathList) > 0 { + l := make([]*table.Path, 0) + for _, p := range msg.MultiPathList { + l = append(l, p...) } - }()); err != nil { - return err - } - case *server.WatchEventUpdate: - if err := sendPath(msg.PathList); err != nil { - return err + return l + } else { + return msg.PathList } + }()); err != nil { + return err + } + case *server.WatchEventUpdate: + if err := sendPath(msg.PathList); err != nil { + return err } } } + return nil }() } @@ -632,40 +722,38 @@ w := s.bgpServer.Watch(server.WatchPeerState(arg.Current)) defer func() { w.Stop() }() - for { - select { - case ev := <-w.Event(): - switch msg := ev.(type) { - case *server.WatchEventPeerState: - if len(arg.Name) > 0 && arg.Name != msg.PeerAddress.String() && arg.Name != msg.PeerInterface { - continue - } - if err := stream.Send(&Peer{ - Conf: &PeerConf{ - PeerAs: msg.PeerAS, - LocalAs: msg.LocalAS, - NeighborAddress: msg.PeerAddress.String(), - Id: msg.PeerID.String(), - NeighborInterface: msg.PeerInterface, - }, - Info: &PeerState{ - PeerAs: msg.PeerAS, - LocalAs: msg.LocalAS, - NeighborAddress: msg.PeerAddress.String(), - BgpState: msg.State.String(), - AdminState: PeerState_AdminState(msg.AdminState), - }, - Transport: &Transport{ - LocalAddress: msg.LocalAddress.String(), - LocalPort: uint32(msg.LocalPort), - RemotePort: uint32(msg.PeerPort), - }, - }); err != nil { - return err - } + for ev := range w.Event() { + switch msg := ev.(type) { + case *server.WatchEventPeerState: + if len(arg.Name) > 0 && arg.Name != msg.PeerAddress.String() && arg.Name != msg.PeerInterface { + continue + } + if err := stream.Send(&Peer{ + Conf: &PeerConf{ + PeerAs: msg.PeerAS, + LocalAs: msg.LocalAS, + NeighborAddress: msg.PeerAddress.String(), + Id: msg.PeerID.String(), + NeighborInterface: msg.PeerInterface, + }, + Info: &PeerState{ + PeerAs: msg.PeerAS, + LocalAs: msg.LocalAS, + NeighborAddress: msg.PeerAddress.String(), + BgpState: msg.State.String(), + AdminState: PeerState_AdminState(msg.AdminState), + }, + Transport: &Transport{ + LocalAddress: msg.LocalAddress.String(), + LocalPort: uint32(msg.LocalPort), + RemotePort: uint32(msg.PeerPort), + }, + }); err != nil { + return err } } } + return nil }() } @@ -703,18 +791,58 @@ return &DisableNeighborResponse{}, s.bgpServer.DisableNeighbor(arg.Address, arg.Communication) } +func (s *Server) UpdatePolicy(ctx context.Context, arg *UpdatePolicyRequest) (*UpdatePolicyResponse, error) { + rp, err := NewRoutingPolicyFromApiStruct(arg) + if err != nil { + return nil, err + } + return &UpdatePolicyResponse{}, s.bgpServer.UpdatePolicy(*rp) +} + +func NewAPIRoutingPolicyFromConfigStruct(c *config.RoutingPolicy) (*RoutingPolicy, error) { + definedSets, err := NewAPIDefinedSetsFromConfigStruct(&c.DefinedSets) + if err != nil { + return nil, err + } + policies := make([]*Policy, 0, len(c.PolicyDefinitions)) + for _, policy := range c.PolicyDefinitions { + policies = append(policies, toPolicyApi(&policy)) + } + + return &RoutingPolicy{ + DefinedSet: definedSets, + PolicyDefinition: policies, + }, nil +} + +func NewRoutingPolicyFromApiStruct(arg *UpdatePolicyRequest) (*config.RoutingPolicy, error) { + policyDefinitions := make([]config.PolicyDefinition, 0, len(arg.Policies)) + for _, p := range arg.Policies { + pd, err := NewConfigPolicyFromApiStruct(p) + if err != nil { + return nil, err + } + policyDefinitions = append(policyDefinitions, *pd) + } + + definedSets, err := NewConfigDefinedSetsFromApiStruct(arg.Sets) + if err != nil { + return nil, err + } + + return &config.RoutingPolicy{ + DefinedSets: *definedSets, + PolicyDefinitions: policyDefinitions, + }, nil +} + func (s *Server) api2PathList(resource Resource, ApiPathList []*Path) ([]*table.Path, error) { - var nlri bgp.AddrPrefixInterface - var nexthop string var pi *table.PeerInfo - var err error pathList := make([]*table.Path, 0, len(ApiPathList)) for _, path := range ApiPathList { - seen := make(map[bgp.BGPAttrType]bool) - - pattr := make([]bgp.PathAttributeInterface, 0) - extcomms := make([]bgp.ExtendedCommunityInterface, 0) + var nlri bgp.AddrPrefixInterface + var nexthop string if path.SourceAsn != 0 { pi = &table.PeerInfo{ @@ -723,69 +851,52 @@ } } - if len(path.Nlri) > 0 { - afi, safi := bgp.RouteFamilyToAfiSafi(bgp.RouteFamily(path.Family)) - if nlri, err = bgp.NewPrefixFromRouteFamily(afi, safi); err != nil { - return nil, err - } - err := nlri.DecodeFromBytes(path.Nlri) - if err != nil { - return nil, err - } - nlri.SetPathIdentifier(path.Identifier) + nlri, err := path.GetNativeNlri() + if err != nil { + return nil, err } + nlri.SetPathIdentifier(path.Identifier) - for _, attr := range path.Pattrs { - p, err := bgp.GetPathAttribute(attr) - if err != nil { - return nil, err - } - - err = p.DecodeFromBytes(attr) - if err != nil { - return nil, err - } + attrList, err := path.GetNativePathAttributes() + if err != nil { + return nil, err + } - if _, ok := seen[p.GetType()]; !ok { - seen[p.GetType()] = true + pattrs := make([]bgp.PathAttributeInterface, 0) + seen := make(map[bgp.BGPAttrType]struct{}) + for _, attr := range attrList { + attrType := attr.GetType() + if _, ok := seen[attrType]; !ok { + seen[attrType] = struct{}{} } else { - return nil, fmt.Errorf("the path attribute appears twice. Type : " + strconv.Itoa(int(p.GetType()))) + return nil, fmt.Errorf("duplicated path attribute type: %d", attrType) } - switch p.GetType() { - case bgp.BGP_ATTR_TYPE_NEXT_HOP: - nexthop = p.(*bgp.PathAttributeNextHop).Value.String() - case bgp.BGP_ATTR_TYPE_EXTENDED_COMMUNITIES: - value := p.(*bgp.PathAttributeExtendedCommunities).Value - if len(value) > 0 { - extcomms = append(extcomms, value...) - } - case bgp.BGP_ATTR_TYPE_MP_REACH_NLRI: - mpreach := p.(*bgp.PathAttributeMpReachNLRI) - if len(mpreach.Value) != 1 { - return nil, fmt.Errorf("include only one route in mp_reach_nlri") - } - nlri = mpreach.Value[0] - nexthop = mpreach.Nexthop.String() + + switch a := attr.(type) { + case *bgp.PathAttributeNextHop: + nexthop = a.Value.String() + case *bgp.PathAttributeMpReachNLRI: + nlri = a.Value[0] + nexthop = a.Nexthop.String() default: - pattr = append(pattr, p) + pattrs = append(pattrs, attr) } } - if nlri == nil || (!path.IsWithdraw && nexthop == "") { - return nil, fmt.Errorf("not found nlri or nexthop") + if nlri == nil { + return nil, fmt.Errorf("nlri not found") + } else if !path.IsWithdraw && nexthop == "" { + return nil, fmt.Errorf("nexthop not found") } if resource != Resource_VRF && bgp.RouteFamily(path.Family) == bgp.RF_IPv4_UC && net.ParseIP(nexthop).To4() != nil { - pattr = append(pattr, bgp.NewPathAttributeNextHop(nexthop)) + pattrs = append(pattrs, bgp.NewPathAttributeNextHop(nexthop)) } else { - pattr = append(pattr, bgp.NewPathAttributeMpReachNLRI(nexthop, []bgp.AddrPrefixInterface{nlri})) + pattrs = append(pattrs, bgp.NewPathAttributeMpReachNLRI(nexthop, []bgp.AddrPrefixInterface{nlri})) } - if len(extcomms) > 0 { - pattr = append(pattr, bgp.NewPathAttributeExtendedCommunities(extcomms)) - } - newPath := table.NewPath(pi, nlri, path.IsWithdraw, pattr, time.Now(), path.NoImplicitWithdraw) - if path.IsWithdraw == false { + newPath := table.NewPath(pi, nlri, path.IsWithdraw, pattrs, time.Now(), path.NoImplicitWithdraw) + if !path.IsWithdraw { total := bytes.NewBuffer(make([]byte, 0)) for _, a := range newPath.GetPathAttrs() { if a.GetType() == bgp.BGP_ATTR_TYPE_MP_REACH_NLRI { @@ -972,17 +1083,14 @@ } func (s *Server) EnableZebra(ctx context.Context, arg *EnableZebraRequest) (*EnableZebraResponse, error) { - l := make([]config.InstallProtocolType, 0, len(arg.RouteTypes)) for _, p := range arg.RouteTypes { - if err := config.InstallProtocolType(p).Validate(); err != nil { + if _, err := zebra.RouteTypeFromString(p); err != nil { return &EnableZebraResponse{}, err - } else { - l = append(l, config.InstallProtocolType(p)) } } return &EnableZebraResponse{}, s.bgpServer.StartZebraClient(&config.ZebraConfig{ Url: arg.Url, - RedistributeRouteTypeList: l, + RedistributeRouteTypeList: arg.RouteTypes, Version: uint8(arg.Version), NexthopTriggerEnable: arg.NexthopTriggerEnable, NexthopTriggerDelay: uint8(arg.NexthopTriggerDelay), @@ -991,21 +1099,12 @@ func (s *Server) GetVrf(ctx context.Context, arg *GetVrfRequest) (*GetVrfResponse, error) { toApi := func(v *table.Vrf) *Vrf { - f := func(rts []bgp.ExtendedCommunityInterface) [][]byte { - ret := make([][]byte, 0, len(rts)) - for _, rt := range rts { - b, _ := rt.Serialize() - ret = append(ret, b) - } - return ret - } - rd, _ := v.Rd.Serialize() return &Vrf{ Name: v.Name, - Rd: rd, + Rd: MarshalRD(v.Rd), Id: v.Id, - ImportRt: f(v.ImportRt), - ExportRt: f(v.ExportRt), + ImportRt: MarshalRTs(v.ImportRt), + ExportRt: MarshalRTs(v.ExportRt), } } vrfs := s.bgpServer.GetVrf() @@ -1020,25 +1119,17 @@ if arg == nil || arg.Vrf == nil { return nil, fmt.Errorf("invalid request") } - rd := bgp.GetRouteDistinguisher(arg.Vrf.Rd) - f := func(bufs [][]byte) ([]bgp.ExtendedCommunityInterface, error) { - ret := make([]bgp.ExtendedCommunityInterface, 0, len(bufs)) - for _, rt := range bufs { - r, err := bgp.ParseExtended(rt) - if err != nil { - return nil, err - } - ret = append(ret, r) - } - return ret, nil + rd, err := UnmarshalRD(arg.Vrf.Rd) + if err != nil { + return nil, err } - im, err := f(arg.Vrf.ImportRt) + im, err := UnmarshalRTs(arg.Vrf.ImportRt) if err != nil { - return &AddVrfResponse{}, err + return nil, err } - ex, err := f(arg.Vrf.ExportRt) + ex, err := UnmarshalRTs(arg.Vrf.ExportRt) if err != nil { - return &AddVrfResponse{}, err + return nil, err } return &AddVrfResponse{}, s.bgpServer.AddVrf(arg.Vrf.Name, arg.Vrf.Id, rd, im, ex) } @@ -1183,6 +1274,7 @@ pconf.Config.RouteFlapDamping = a.Conf.RouteFlapDamping pconf.Config.Description = a.Conf.Description pconf.Config.PeerGroup = a.Conf.PeerGroup + pconf.Config.PeerType = config.IntToPeerTypeMap[int(a.Conf.PeerType)] pconf.Config.NeighborAddress = a.Conf.NeighborAddress pconf.Config.NeighborInterface = a.Conf.NeighborInterface pconf.Config.Vrf = a.Conf.Vrf @@ -1196,23 +1288,11 @@ pconf.Config.RemovePrivateAs = config.REMOVE_PRIVATE_AS_OPTION_REPLACE } - f := func(bufs [][]byte) ([]bgp.ParameterCapabilityInterface, error) { - var caps []bgp.ParameterCapabilityInterface - for _, buf := range bufs { - c, err := bgp.DecodeCapability(buf) - if err != nil { - return nil, err - } - caps = append(caps, c) - } - return caps, nil - } - - localCaps, err := f(a.Conf.LocalCap) + localCaps, err := UnmarshalCapabilities(a.Conf.LocalCap) if err != nil { return nil, err } - remoteCaps, err := f(a.Conf.RemoteCap) + remoteCaps, err := UnmarshalCapabilities(a.Conf.RemoteCap) if err != nil { return nil, err } @@ -1299,6 +1379,7 @@ pconf.GracefulRestart.Config.DeferralTime = uint16(a.GracefulRestart.DeferralTime) pconf.GracefulRestart.Config.NotificationEnabled = a.GracefulRestart.NotificationEnabled pconf.GracefulRestart.Config.LongLivedEnabled = a.GracefulRestart.LonglivedEnabled + pconf.GracefulRestart.State.LocalRestarting = a.GracefulRestart.LocalRestarting } ReadApplyPolicyFromAPIStruct(&pconf.ApplyPolicy, a.ApplyPolicy) if a.Transport != nil { @@ -1345,6 +1426,112 @@ return pconf, nil } +func NewPeerGroupFromAPIStruct(a *PeerGroup) (*config.PeerGroup, error) { + pconf := &config.PeerGroup{} + if a.Conf != nil { + pconf.Config.PeerAs = a.Conf.PeerAs + pconf.Config.LocalAs = a.Conf.LocalAs + pconf.Config.AuthPassword = a.Conf.AuthPassword + pconf.Config.RouteFlapDamping = a.Conf.RouteFlapDamping + pconf.Config.Description = a.Conf.Description + pconf.Config.PeerGroupName = a.Conf.PeerGroupName + + switch a.Conf.RemovePrivateAs { + case PeerGroupConf_ALL: + pconf.Config.RemovePrivateAs = config.REMOVE_PRIVATE_AS_OPTION_ALL + case PeerGroupConf_REPLACE: + pconf.Config.RemovePrivateAs = config.REMOVE_PRIVATE_AS_OPTION_REPLACE + } + + for _, af := range a.AfiSafis { + afiSafi := config.AfiSafi{} + ReadMpGracefulRestartFromAPIStruct(&afiSafi.MpGracefulRestart, af.MpGracefulRestart) + ReadAfiSafiConfigFromAPIStruct(&afiSafi.Config, af.Config) + ReadAfiSafiStateFromAPIStruct(&afiSafi.State, af.Config) + ReadApplyPolicyFromAPIStruct(&afiSafi.ApplyPolicy, af.ApplyPolicy) + ReadRouteSelectionOptionsFromAPIStruct(&afiSafi.RouteSelectionOptions, af.RouteSelectionOptions) + ReadUseMultiplePathsFromAPIStruct(&afiSafi.UseMultiplePaths, af.UseMultiplePaths) + ReadPrefixLimitFromAPIStruct(&afiSafi.PrefixLimit, af.PrefixLimits) + ReadRouteTargetMembershipFromAPIStruct(&afiSafi.RouteTargetMembership, af.RouteTargetMembership) + ReadLongLivedGracefulRestartFromAPIStruct(&afiSafi.LongLivedGracefulRestart, af.LongLivedGracefulRestart) + ReadAddPathsFromAPIStruct(&afiSafi.AddPaths, af.AddPaths) + pconf.AfiSafis = append(pconf.AfiSafis, afiSafi) + } + // For the backward compatibility, we override AfiSafi configurations + // with Peer.Families. + for _, family := range a.Families { + found := false + for _, afiSafi := range pconf.AfiSafis { + if uint32(afiSafi.State.Family) == family { + // If Peer.Families contains the same address family, + // we enable this address family. + afiSafi.Config.Enabled = true + found = true + } + } + if !found { + // If Peer.Families does not contain the same address family, + // we append AfiSafi structure with the default value. + pconf.AfiSafis = append(pconf.AfiSafis, config.AfiSafi{ + Config: config.AfiSafiConfig{ + AfiSafiName: config.AfiSafiType(bgp.RouteFamily(family).String()), + Enabled: true, + }, + }) + } + } + } + + if a.Timers != nil { + if a.Timers.Config != nil { + pconf.Timers.Config.ConnectRetry = float64(a.Timers.Config.ConnectRetry) + pconf.Timers.Config.HoldTime = float64(a.Timers.Config.HoldTime) + pconf.Timers.Config.KeepaliveInterval = float64(a.Timers.Config.KeepaliveInterval) + pconf.Timers.Config.MinimumAdvertisementInterval = float64(a.Timers.Config.MinimumAdvertisementInterval) + } + if a.Timers.State != nil { + pconf.Timers.State.KeepaliveInterval = float64(a.Timers.State.KeepaliveInterval) + pconf.Timers.State.NegotiatedHoldTime = float64(a.Timers.State.NegotiatedHoldTime) + pconf.Timers.State.Uptime = int64(a.Timers.State.Uptime) + pconf.Timers.State.Downtime = int64(a.Timers.State.Downtime) + } + } + if a.RouteReflector != nil { + pconf.RouteReflector.Config.RouteReflectorClusterId = config.RrClusterIdType(a.RouteReflector.RouteReflectorClusterId) + pconf.RouteReflector.Config.RouteReflectorClient = a.RouteReflector.RouteReflectorClient + } + if a.RouteServer != nil { + pconf.RouteServer.Config.RouteServerClient = a.RouteServer.RouteServerClient + } + if a.GracefulRestart != nil { + pconf.GracefulRestart.Config.Enabled = a.GracefulRestart.Enabled + pconf.GracefulRestart.Config.RestartTime = uint16(a.GracefulRestart.RestartTime) + pconf.GracefulRestart.Config.HelperOnly = a.GracefulRestart.HelperOnly + pconf.GracefulRestart.Config.DeferralTime = uint16(a.GracefulRestart.DeferralTime) + pconf.GracefulRestart.Config.NotificationEnabled = a.GracefulRestart.NotificationEnabled + pconf.GracefulRestart.Config.LongLivedEnabled = a.GracefulRestart.LonglivedEnabled + pconf.GracefulRestart.State.LocalRestarting = a.GracefulRestart.LocalRestarting + } + ReadApplyPolicyFromAPIStruct(&pconf.ApplyPolicy, a.ApplyPolicy) + if a.Transport != nil { + pconf.Transport.Config.LocalAddress = a.Transport.LocalAddress + pconf.Transport.Config.PassiveMode = a.Transport.PassiveMode + pconf.Transport.Config.RemotePort = uint16(a.Transport.RemotePort) + } + if a.EbgpMultihop != nil { + pconf.EbgpMultihop.Config.Enabled = a.EbgpMultihop.Enabled + pconf.EbgpMultihop.Config.MultihopTtl = uint8(a.EbgpMultihop.MultihopTtl) + } + if a.Info != nil { + pconf.State.TotalPaths = a.Info.TotalPaths + pconf.State.TotalPrefixes = a.Info.TotalPrefixes + pconf.State.PeerAs = a.Info.PeerAs + pconf.State.PeerType = config.IntToPeerTypeMap[int(a.Info.PeerType)] + } + ReadAddPathsFromAPIStruct(&pconf.AddPaths, a.AddPaths) + return pconf, nil +} + func (s *Server) AddNeighbor(ctx context.Context, arg *AddNeighborRequest) (*AddNeighborResponse, error) { c, err := NewNeighborFromAPIStruct(arg.Peer) if err != nil { @@ -1375,6 +1562,42 @@ return &UpdateNeighborResponse{NeedsSoftResetIn: needsSoftResetIn}, nil } +func (s *Server) AddPeerGroup(ctx context.Context, arg *AddPeerGroupRequest) (*AddPeerGroupResponse, error) { + c, err := NewPeerGroupFromAPIStruct(arg.PeerGroup) + if err != nil { + return nil, err + } + return &AddPeerGroupResponse{}, s.bgpServer.AddPeerGroup(c) +} + +func (s *Server) DeletePeerGroup(ctx context.Context, arg *DeletePeerGroupRequest) (*DeletePeerGroupResponse, error) { + return &DeletePeerGroupResponse{}, s.bgpServer.DeletePeerGroup(&config.PeerGroup{Config: config.PeerGroupConfig{ + PeerGroupName: arg.PeerGroup.Conf.PeerGroupName, + }}) +} + +func (s *Server) UpdatePeerGroup(ctx context.Context, arg *UpdatePeerGroupRequest) (*UpdatePeerGroupResponse, error) { + c, err := NewPeerGroupFromAPIStruct(arg.PeerGroup) + if err != nil { + return nil, err + } + needsSoftResetIn, err := s.bgpServer.UpdatePeerGroup(c) + if err != nil { + return nil, err + } + if arg.DoSoftResetIn && needsSoftResetIn { + return &UpdatePeerGroupResponse{NeedsSoftResetIn: false}, s.bgpServer.SoftResetIn("", bgp.RouteFamily(0)) + } + return &UpdatePeerGroupResponse{NeedsSoftResetIn: needsSoftResetIn}, nil +} + +func (s *Server) AddDynamicNeighbor(ctx context.Context, arg *AddDynamicNeighborRequest) (*AddDynamicNeighborResponse, error) { + return &AddDynamicNeighborResponse{}, s.bgpServer.AddDynamicNeighbor(&config.DynamicNeighbor{Config: config.DynamicNeighborConfig{ + Prefix: arg.DynamicNeighbor.Prefix, + PeerGroup: arg.DynamicNeighbor.PeerGroup, + }}) +} + func NewPrefixFromApiStruct(a *Prefix) (*table.Prefix, error) { _, prefix, err := net.ParseCIDR(a.IpPrefix) if err != nil { @@ -1392,6 +1615,17 @@ }, nil } +func NewConfigPrefixFromAPIStruct(a *Prefix) (*config.Prefix, error) { + _, prefix, err := net.ParseCIDR(a.IpPrefix) + if err != nil { + return nil, err + } + return &config.Prefix{ + IpPrefix: prefix.String(), + MasklengthRange: fmt.Sprintf("%d..%d", a.MaskLengthMin, a.MaskLengthMax), + }, nil +} + func NewAPIPrefixFromConfigStruct(c config.Prefix) (*Prefix, error) { min, max, err := config.ParseMaskLength(c.IpPrefix, c.MasklengthRange) if err != nil { @@ -1423,39 +1657,160 @@ case table.DEFINED_TYPE_NEIGHBOR: s := t.(*table.NeighborSet) c := s.ToConfig() - for _, n := range c.NeighborInfoList { - a.List = append(a.List, n) - } + a.List = append(a.List, c.NeighborInfoList...) case table.DEFINED_TYPE_AS_PATH: s := t.(*table.AsPathSet) c := s.ToConfig() - for _, n := range c.AsPathList { - a.List = append(a.List, n) - } + a.List = append(a.List, c.AsPathList...) case table.DEFINED_TYPE_COMMUNITY: s := t.(*table.CommunitySet) c := s.ToConfig() - for _, n := range c.CommunityList { - a.List = append(a.List, n) - } + a.List = append(a.List, c.CommunityList...) case table.DEFINED_TYPE_EXT_COMMUNITY: s := t.(*table.ExtCommunitySet) c := s.ToConfig() - for _, n := range c.ExtCommunityList { - a.List = append(a.List, n) - } + a.List = append(a.List, c.ExtCommunityList...) case table.DEFINED_TYPE_LARGE_COMMUNITY: s := t.(*table.LargeCommunitySet) c := s.ToConfig() - for _, n := range c.LargeCommunityList { - a.List = append(a.List, n) - } + a.List = append(a.List, c.LargeCommunityList...) default: return nil, fmt.Errorf("invalid defined type") } return a, nil } +func NewAPIDefinedSetsFromConfigStruct(t *config.DefinedSets) ([]*DefinedSet, error) { + definedSets := make([]*DefinedSet, 0) + + for _, ps := range t.PrefixSets { + prefixes := make([]*Prefix, 0) + for _, p := range ps.PrefixList { + ap, err := NewAPIPrefixFromConfigStruct(p) + if err != nil { + return nil, err + } + prefixes = append(prefixes, ap) + } + definedSets = append(definedSets, &DefinedSet{ + Type: DefinedType_PREFIX, + Name: ps.PrefixSetName, + Prefixes: prefixes, + }) + } + + for _, ns := range t.NeighborSets { + definedSets = append(definedSets, &DefinedSet{ + Type: DefinedType_NEIGHBOR, + Name: ns.NeighborSetName, + List: ns.NeighborInfoList, + }) + } + + bs := t.BgpDefinedSets + for _, cs := range bs.CommunitySets { + definedSets = append(definedSets, &DefinedSet{ + Type: DefinedType_COMMUNITY, + Name: cs.CommunitySetName, + List: cs.CommunityList, + }) + } + + for _, es := range bs.ExtCommunitySets { + definedSets = append(definedSets, &DefinedSet{ + Type: DefinedType_EXT_COMMUNITY, + Name: es.ExtCommunitySetName, + List: es.ExtCommunityList, + }) + } + + for _, ls := range bs.LargeCommunitySets { + definedSets = append(definedSets, &DefinedSet{ + Type: DefinedType_LARGE_COMMUNITY, + Name: ls.LargeCommunitySetName, + List: ls.LargeCommunityList, + }) + } + + for _, as := range bs.AsPathSets { + definedSets = append(definedSets, &DefinedSet{ + Type: DefinedType_AS_PATH, + Name: as.AsPathSetName, + List: as.AsPathList, + }) + } + + return definedSets, nil +} + +func NewConfigDefinedSetsFromApiStruct(a []*DefinedSet) (*config.DefinedSets, error) { + ps := make([]config.PrefixSet, 0) + ns := make([]config.NeighborSet, 0) + as := make([]config.AsPathSet, 0) + cs := make([]config.CommunitySet, 0) + es := make([]config.ExtCommunitySet, 0) + ls := make([]config.LargeCommunitySet, 0) + + for _, ds := range a { + if ds.Name == "" { + return nil, fmt.Errorf("empty neighbor set name") + } + switch table.DefinedType(ds.Type) { + case table.DEFINED_TYPE_PREFIX: + prefixes := make([]config.Prefix, 0, len(ds.Prefixes)) + for _, p := range ds.Prefixes { + prefix, err := NewConfigPrefixFromAPIStruct(p) + if err != nil { + return nil, err + } + prefixes = append(prefixes, *prefix) + } + ps = append(ps, config.PrefixSet{ + PrefixSetName: ds.Name, + PrefixList: prefixes, + }) + case table.DEFINED_TYPE_NEIGHBOR: + ns = append(ns, config.NeighborSet{ + NeighborSetName: ds.Name, + NeighborInfoList: ds.List, + }) + case table.DEFINED_TYPE_AS_PATH: + as = append(as, config.AsPathSet{ + AsPathSetName: ds.Name, + AsPathList: ds.List, + }) + case table.DEFINED_TYPE_COMMUNITY: + cs = append(cs, config.CommunitySet{ + CommunitySetName: ds.Name, + CommunityList: ds.List, + }) + case table.DEFINED_TYPE_EXT_COMMUNITY: + es = append(es, config.ExtCommunitySet{ + ExtCommunitySetName: ds.Name, + ExtCommunityList: ds.List, + }) + case table.DEFINED_TYPE_LARGE_COMMUNITY: + ls = append(ls, config.LargeCommunitySet{ + LargeCommunitySetName: ds.Name, + LargeCommunityList: ds.List, + }) + default: + return nil, fmt.Errorf("invalid defined type") + } + } + + return &config.DefinedSets{ + PrefixSets: ps, + NeighborSets: ns, + BgpDefinedSets: config.BgpDefinedSets{ + AsPathSets: as, + CommunitySets: cs, + ExtCommunitySets: es, + LargeCommunitySets: ls, + }, + }, nil +} + func NewDefinedSetFromApiStruct(a *DefinedSet) (table.DefinedSet, error) { if a.Name == "" { return nil, fmt.Errorf("empty neighbor set name") @@ -1506,6 +1861,8 @@ } } +var _regexpPrefixMaskLengthRange = regexp.MustCompile(`(\d+)\.\.(\d+)`) + func (s *Server) GetDefinedSet(ctx context.Context, arg *GetDefinedSetRequest) (*GetDefinedSetResponse, error) { cd, err := s.bgpServer.GetDefinedSet(table.DefinedType(arg.Type), arg.Name) if err != nil { @@ -1519,8 +1876,7 @@ Prefixes: func() []*Prefix { l := make([]*Prefix, 0, len(cs.PrefixList)) for _, p := range cs.PrefixList { - exp := regexp.MustCompile("(\\d+)\\.\\.(\\d+)") - elems := exp.FindStringSubmatch(p.MasklengthRange) + elems := _regexpPrefixMaskLengthRange.FindStringSubmatch(p.MasklengthRange) min, _ := strconv.ParseUint(elems[1], 10, 32) max, _ := strconv.ParseUint(elems[2], 10, 32) @@ -1613,6 +1969,8 @@ return toStatementApi(t.ToConfig()) } +var _regexpMedActionType = regexp.MustCompile(`([+-]?)(\d+)`) + func toStatementApi(s *config.Statement) *Statement { cs := &Conditions{} if s.Conditions.MatchPrefixSet.PrefixSet != "" { @@ -1662,6 +2020,18 @@ if s.Conditions.BgpConditions.RouteType != "" { cs.RouteType = 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([]Family, 0) + for _, afiSafiType := range s.Conditions.BgpConditions.AfiSafiInList { + if mapped, ok := bgp.AddressFamilyValueMap[string(afiSafiType)]; ok { + afiSafiIn = append(afiSafiIn, Family(mapped)) + } + } + cs.AfiSafiIn = afiSafiIn + } cs.RpkiResult = int32(s.Conditions.BgpConditions.RpkiValidationResult.ToInt()) as := &Actions{ RouteAction: func() RouteAction { @@ -1686,8 +2056,7 @@ if len(medStr) == 0 { return nil } - re := regexp.MustCompile("([+-]?)(\\d+)") - matches := re.FindStringSubmatch(medStr) + matches := _regexpMedActionType.FindStringSubmatch(medStr) if len(matches) == 0 { return nil } @@ -1914,6 +2283,29 @@ return table.NewLargeCommunityCondition(c) } +func NewNextHopConditionFromApiStruct(a []string) (*table.NextHopCondition, error) { + if a == nil { + return nil, nil + } + + return table.NewNextHopCondition(a) +} + +func NewAfiSafiInConditionFromApiStruct(a []Family) (*table.AfiSafiInCondition, error) { + if a == nil { + return nil, nil + } + afiSafiTypes := make([]config.AfiSafiType, 0, len(a)) + for _, aType := range a { + if configType, ok := bgp.AddressFamilyNameMap[bgp.RouteFamily(aType)]; ok { + afiSafiTypes = append(afiSafiTypes, config.AfiSafiType(configType)) + } else { + return nil, fmt.Errorf("unknown afi-safi-in type value: %d", aType) + } + } + return table.NewAfiSafiInCondition(afiSafiTypes) +} + func NewRoutingActionFromApiStruct(a RouteAction) (*table.RoutingAction, error) { if a == RouteAction_NONE { return nil, nil @@ -2043,6 +2435,12 @@ func() (table.Condition, error) { return NewLargeCommunityConditionFromApiStruct(a.Conditions.LargeCommunitySet) }, + func() (table.Condition, error) { + return NewNextHopConditionFromApiStruct(a.Conditions.NextHopInList) + }, + func() (table.Condition, error) { + return NewAfiSafiInConditionFromApiStruct(a.Conditions.AfiSafiIn) + }, } cs = make([]table.Condition, 0, len(cfs)) for _, f := range cfs { @@ -2198,6 +2596,28 @@ } } +func NewConfigPolicyFromApiStruct(a *Policy) (*config.PolicyDefinition, error) { + if a.Name == "" { + return nil, fmt.Errorf("empty policy name") + } + stmts := make([]config.Statement, 0, len(a.Statements)) + for idx, x := range a.Statements { + if x.Name == "" { + x.Name = fmt.Sprintf("%s_stmt%d", a.Name, idx) + } + y, err := NewStatementFromApiStruct(x) + if err != nil { + return nil, err + } + stmt := y.ToConfig() + stmts = append(stmts, *stmt) + } + return &config.PolicyDefinition{ + Name: a.Name, + Statements: stmts, + }, nil +} + func NewPolicyFromApiStruct(a *Policy) (*table.Policy, error) { if a.Name == "" { return nil, fmt.Errorf("empty policy name") @@ -2398,17 +2818,11 @@ }, nil } -func (s *Server) StartServer(ctx context.Context, arg *StartServerRequest) (*StartServerResponse, error) { - if arg == nil || arg.Global == nil { - return nil, fmt.Errorf("invalid request") - } - g := arg.Global - if net.ParseIP(g.RouterId) == nil { - return nil, fmt.Errorf("invalid router-id format: %s", g.RouterId) - } - families := make([]config.AfiSafi, 0, len(g.Families)) - for _, f := range g.Families { - name := config.AfiSafiType(bgp.RouteFamily(f).String()) +func NewGlobalFromAPIStruct(a *Global) *config.Global { + families := make([]config.AfiSafi, 0, len(a.Families)) + for _, f := range a.Families { + name := config.IntToAfiSafiTypeMap[int(f)] + rf, _ := bgp.GetRouteFamily(string(name)) families = append(families, config.AfiSafi{ Config: config.AfiSafiConfig{ AfiSafiName: name, @@ -2416,26 +2830,134 @@ }, State: config.AfiSafiState{ AfiSafiName: name, + Enabled: true, + Family: rf, }, }) } - b := &config.BgpConfigSet{ - Global: config.Global{ - Config: config.GlobalConfig{ - As: g.As, - RouterId: g.RouterId, - Port: g.ListenPort, - LocalAddressList: g.ListenAddresses, - }, - AfiSafis: families, - UseMultiplePaths: config.UseMultiplePaths{ - Config: config.UseMultiplePathsConfig{ - Enabled: g.UseMultiplePaths, - }, + + applyPolicy := &config.ApplyPolicy{} + ReadApplyPolicyFromAPIStruct(applyPolicy, a.ApplyPolicy) + + global := &config.Global{ + Config: config.GlobalConfig{ + As: a.As, + RouterId: a.RouterId, + Port: a.ListenPort, + LocalAddressList: a.ListenAddresses, + }, + ApplyPolicy: *applyPolicy, + AfiSafis: families, + UseMultiplePaths: config.UseMultiplePaths{ + Config: config.UseMultiplePathsConfig{ + Enabled: a.UseMultiplePaths, + }, + }, + } + if a.RouteSelectionOptions != nil { + global.RouteSelectionOptions = config.RouteSelectionOptions{ + Config: config.RouteSelectionOptionsConfig{ + AlwaysCompareMed: a.RouteSelectionOptions.AlwaysCompareMed, + IgnoreAsPathLength: a.RouteSelectionOptions.IgnoreAsPathLength, + ExternalCompareRouterId: a.RouteSelectionOptions.ExternalCompareRouterId, + AdvertiseInactiveRoutes: a.RouteSelectionOptions.AdvertiseInactiveRoutes, + EnableAigp: a.RouteSelectionOptions.EnableAigp, + IgnoreNextHopIgpMetric: a.RouteSelectionOptions.IgnoreNextHopIgpMetric, + DisableBestPathSelection: a.RouteSelectionOptions.DisableBestPathSelection, + }, + } + } + if a.DefaultRouteDistance != nil { + global.DefaultRouteDistance = config.DefaultRouteDistance{ + Config: config.DefaultRouteDistanceConfig{ + ExternalRouteDistance: uint8(a.DefaultRouteDistance.ExternalRouteDistance), + InternalRouteDistance: uint8(a.DefaultRouteDistance.InternalRouteDistance), + }, + } + } + if a.Confederation != nil { + global.Confederation = config.Confederation{ + Config: config.ConfederationConfig{ + Enabled: a.Confederation.Enabled, + Identifier: a.Confederation.Identifier, + MemberAsList: a.Confederation.MemberAsList, }, + } + } + if a.GracefulRestart != nil { + global.GracefulRestart = config.GracefulRestart{ + Config: config.GracefulRestartConfig{ + Enabled: a.GracefulRestart.Enabled, + RestartTime: uint16(a.GracefulRestart.RestartTime), + StaleRoutesTime: float64(a.GracefulRestart.StaleRoutesTime), + HelperOnly: a.GracefulRestart.HelperOnly, + DeferralTime: uint16(a.GracefulRestart.DeferralTime), + NotificationEnabled: a.GracefulRestart.NotificationEnabled, + LongLivedEnabled: a.GracefulRestart.LonglivedEnabled, + }, + } + } + return global +} + +func NewGlobalFromConfigStruct(c *config.Global) *Global { + families := make([]uint32, 0, len(c.AfiSafis)) + for _, f := range c.AfiSafis { + families = append(families, uint32(config.AfiSafiTypeToIntMap[f.Config.AfiSafiName])) + } + + applyPolicy := NewApplyPolicyFromConfigStruct(&c.ApplyPolicy) + + return &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: &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: &DefaultRouteDistance{ + ExternalRouteDistance: uint32(c.DefaultRouteDistance.Config.ExternalRouteDistance), + InternalRouteDistance: uint32(c.DefaultRouteDistance.Config.InternalRouteDistance), + }, + Confederation: &Confederation{ + Enabled: c.Confederation.Config.Enabled, + Identifier: c.Confederation.Config.Identifier, + MemberAsList: c.Confederation.Config.MemberAsList, + }, + GracefulRestart: &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 (s *Server) StartServer(ctx context.Context, arg *StartServerRequest) (*StartServerResponse, error) { + if arg == nil || arg.Global == nil { + return nil, fmt.Errorf("invalid request") + } + g := arg.Global + if net.ParseIP(g.RouterId) == nil { + return nil, fmt.Errorf("invalid router-id format: %s", g.RouterId) } - return &StartServerResponse{}, s.bgpServer.Start(&b.Global) + + global := NewGlobalFromAPIStruct(arg.Global) + + return &StartServerResponse{}, s.bgpServer.Start(global) } func (s *Server) StopServer(ctx context.Context, arg *StopServerRequest) (*StopServerResponse, error) { @@ -2476,5 +2998,17 @@ NumAccepted: uint64(info.NumAccepted), }, }, nil +} + +func (s *Server) AddCollector(ctx context.Context, arg *AddCollectorRequest) (*AddCollectorResponse, error) { + return &AddCollectorResponse{}, s.bgpServer.AddCollector(&config.CollectorConfig{ + Url: arg.Url, + DbName: arg.DbName, + TableDumpInterval: arg.TableDumpInterval, + }) +} +func (s *Server) Shutdown(ctx context.Context, arg *ShutdownRequest) (*ShutdownResponse, error) { + s.bgpServer.Shutdown() + return &ShutdownResponse{}, nil } diff -Nru gobgp-1.32/api/util.go gobgp-1.33/api/util.go --- gobgp-1.32/api/util.go 2018-06-01 11:32:28.000000000 +0000 +++ gobgp-1.33/api/util.go 2018-07-01 12:06:57.000000000 +0000 @@ -61,7 +61,7 @@ if len(d.Paths) == 0 { return nil, fmt.Errorf("no path in destination") } - nlri, err := getNLRI(bgp.RouteFamily(d.Paths[0].Family), d.Paths[0].Nlri) + nlri, err := d.Paths[0].GetNativeNlri() if err != nil { return nil, err } @@ -86,7 +86,30 @@ } func (p *Path) GetNativeNlri() (bgp.AddrPrefixInterface, error) { - return getNLRI(bgp.RouteFamily(p.Family), p.Nlri) + if len(p.Nlri) > 0 { + return getNLRI(bgp.RouteFamily(p.Family), p.Nlri) + } + return UnmarshalNLRI(bgp.RouteFamily(p.Family), p.AnyNlri) +} + +func (p *Path) GetNativePathAttributes() ([]bgp.PathAttributeInterface, error) { + pattrsLen := len(p.Pattrs) + if pattrsLen > 0 { + pattrs := make([]bgp.PathAttributeInterface, 0, pattrsLen) + for _, attr := range p.Pattrs { + a, err := bgp.GetPathAttribute(attr) + if err != nil { + return nil, err + } + err = a.DecodeFromBytes(attr) + if err != nil { + return nil, err + } + pattrs = append(pattrs, a) + } + return pattrs, nil + } + return UnmarshalPathAttributes(p.AnyPattrs) } func (p *Path) ToNativePath(option ...ToNativeOption) (*table.Path, error) { @@ -105,22 +128,14 @@ } if nlri == nil { var err error - nlri, err = getNLRI(bgp.RouteFamily(p.Family), p.Nlri) + nlri, err = p.GetNativeNlri() if err != nil { return nil, err } } - pattr := make([]bgp.PathAttributeInterface, 0, len(p.Pattrs)) - for _, attr := range p.Pattrs { - p, err := bgp.GetPathAttribute(attr) - if err != nil { - return nil, err - } - err = p.DecodeFromBytes(attr) - if err != nil { - return nil, err - } - pattr = append(pattr, p) + pattr, err := p.GetNativePathAttributes() + if err != nil { + return nil, err } t := time.Unix(p.Age, 0) nlri.SetPathIdentifier(p.Identifier) diff -Nru gobgp-1.32/client/client.go gobgp-1.33/client/client.go --- gobgp-1.32/client/client.go 2018-06-01 11:32:28.000000000 +0000 +++ gobgp-1.33/client/client.go 2018-07-01 12:06:57.000000000 +0000 @@ -357,7 +357,7 @@ func (c *AddPathByStreamClient) Send(paths ...*table.Path) error { ps := make([]*api.Path, 0, len(paths)) for _, p := range paths { - ps = append(ps, api.ToPathApi(p, nil)) + ps = append(ps, api.ToPathApiInBin(p, nil)) } return c.stream.Send(&api.InjectMrtRequest{ Resource: api.Resource_GLOBAL, @@ -419,21 +419,10 @@ switch { case len(pathList) != 0: for _, path := range pathList { - nlri := path.GetNlri() - n, err := nlri.Serialize() - if err != nil { - return err - } - p := &api.Path{ - Nlri: n, - Family: uint32(path.GetRouteFamily()), - Identifier: nlri.PathIdentifier(), - LocalIdentifier: nlri.PathLocalIdentifier(), - } reqs = append(reqs, &api.DeletePathRequest{ Resource: resource, VrfId: vrfID, - Path: p, + Path: api.ToPathApi(path, nil), }) } default: @@ -472,83 +461,25 @@ return cli.deletePath(nil, family, "", nil) } -func (cli *Client) GetVRF() ([]*table.Vrf, error) { +func (cli *Client) GetVRF() ([]*api.Vrf, error) { ret, err := cli.cli.GetVrf(context.Background(), &api.GetVrfRequest{}) if err != nil { return nil, err } - var vrfs []*table.Vrf - - f := func(bufs [][]byte) ([]bgp.ExtendedCommunityInterface, error) { - ret := make([]bgp.ExtendedCommunityInterface, 0, len(bufs)) - for _, rt := range bufs { - r, err := bgp.ParseExtended(rt) - if err != nil { - return nil, err - } - ret = append(ret, r) - } - return ret, nil - } - - for _, vrf := range ret.Vrfs { - importRT, err := f(vrf.ImportRt) - if err != nil { - return nil, err - } - exportRT, err := f(vrf.ExportRt) - if err != nil { - return nil, err - } - vrfs = append(vrfs, &table.Vrf{ - Name: vrf.Name, - Id: vrf.Id, - Rd: bgp.GetRouteDistinguisher(vrf.Rd), - ImportRt: importRT, - ExportRt: exportRT, - }) - } - - return vrfs, nil + return ret.Vrfs, nil } func (cli *Client) AddVRF(name string, id int, rd bgp.RouteDistinguisherInterface, im, ex []bgp.ExtendedCommunityInterface) error { - buf, err := rd.Serialize() - if err != nil { - return err - } - - f := func(comms []bgp.ExtendedCommunityInterface) ([][]byte, error) { - var bufs [][]byte - for _, c := range comms { - buf, err := c.Serialize() - if err != nil { - return nil, err - } - bufs = append(bufs, buf) - } - return bufs, err - } - - importRT, err := f(im) - if err != nil { - return err - } - exportRT, err := f(ex) - if err != nil { - return err - } - arg := &api.AddVrfRequest{ Vrf: &api.Vrf{ Name: name, - Rd: buf, + Rd: api.MarshalRD(rd), Id: uint32(id), - ImportRt: importRT, - ExportRt: exportRT, + ImportRt: api.MarshalRTs(im), + ExportRt: api.MarshalRTs(ex), }, } - _, err = cli.cli.AddVrf(context.Background(), arg) + _, err := cli.cli.AddVrf(context.Background(), arg) return err } diff -Nru gobgp-1.32/config/bgp_configs.go gobgp-1.33/config/bgp_configs.go --- gobgp-1.32/config/bgp_configs.go 2018-06-01 11:32:28.000000000 +0000 +++ gobgp-1.33/config/bgp_configs.go 2018-07-01 12:06:57.000000000 +0000 @@ -1114,7 +1114,7 @@ // Configure url for zebra. Url string `mapstructure:"url" json:"url,omitempty"` // original -> gobgp:redistribute-route-type - RedistributeRouteTypeList []InstallProtocolType `mapstructure:"redistribute-route-type-list" json:"redistribute-route-type-list,omitempty"` + 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. Version uint8 `mapstructure:"version" json:"version,omitempty"` @@ -1135,7 +1135,7 @@ // Configure url for zebra. Url string `mapstructure:"url" json:"url,omitempty"` // original -> gobgp:redistribute-route-type - RedistributeRouteTypeList []InstallProtocolType `mapstructure:"redistribute-route-type-list" json:"redistribute-route-type-list,omitempty"` + 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. Version uint8 `mapstructure:"version" json:"version,omitempty"` diff -Nru gobgp-1.32/config/bgp_configs_test.go gobgp-1.33/config/bgp_configs_test.go --- gobgp-1.32/config/bgp_configs_test.go 2018-06-01 11:32:28.000000000 +0000 +++ gobgp-1.33/config/bgp_configs_test.go 2018-07-01 12:06:57.000000000 +0000 @@ -90,10 +90,7 @@ } fTomlWriter.Flush() - if err := scanner.Err(); err != nil { - return err - } - return nil + return scanner.Err() } func TestConfigExample(t *testing.T) { diff -Nru gobgp-1.32/config/default.go gobgp-1.33/config/default.go --- gobgp-1.32/config/default.go 2018-06-01 11:32:28.000000000 +0000 +++ gobgp-1.33/config/default.go 2018-07-01 12:06:57.000000000 +0000 @@ -1,10 +1,12 @@ package config import ( + "encoding/binary" "fmt" "math" "net" "reflect" + "strconv" "github.com/spf13/viper" @@ -28,7 +30,7 @@ func RegisterConfiguredFields(addr string, n interface{}) { if configuredFields == nil { - configuredFields = make(map[string]interface{}, 0) + configuredFields = make(map[string]interface{}) } configuredFields[addr] = n } @@ -185,11 +187,11 @@ if len(afs) > i { vv.Set("afi-safi", afs[i]) } - if rf, err := bgp.GetRouteFamily(string(n.AfiSafis[i].Config.AfiSafiName)); err != nil { + rf, err := bgp.GetRouteFamily(string(n.AfiSafis[i].Config.AfiSafiName)) + if err != nil { return err - } else { - n.AfiSafis[i].State.Family = rf } + n.AfiSafis[i].State.Family = rf n.AfiSafis[i].State.AfiSafiName = n.AfiSafis[i].Config.AfiSafiName if !vv.IsSet("afi-safi.config.enabled") { n.AfiSafis[i].Config.Enabled = true @@ -240,9 +242,18 @@ if n.RouteReflector.Config.RouteReflectorClient { if n.RouteReflector.Config.RouteReflectorClusterId == "" { - n.RouteReflector.Config.RouteReflectorClusterId = RrClusterIdType(g.Config.RouterId) - } else if id := net.ParseIP(string(n.RouteReflector.Config.RouteReflectorClusterId)).To4(); id == nil { - return fmt.Errorf("route-reflector-cluster-id should be specified in IPv4 address format") + n.RouteReflector.State.RouteReflectorClusterId = RrClusterIdType(g.Config.RouterId) + } else { + id := string(n.RouteReflector.Config.RouteReflectorClusterId) + if ip := net.ParseIP(id).To4(); ip != nil { + n.RouteReflector.State.RouteReflectorClusterId = n.RouteReflector.Config.RouteReflectorClusterId + } else if num, err := strconv.ParseUint(id, 10, 32); err == nil { + ip = make(net.IP, 4) + binary.BigEndian.PutUint32(ip, uint32(num)) + n.RouteReflector.State.RouteReflectorClusterId = RrClusterIdType(ip.String()) + } else { + return fmt.Errorf("route-reflector-cluster-id should be specified as IPv4 address or 32-bit unsigned integer") + } } } @@ -252,7 +263,7 @@ func SetDefaultGlobalConfigValues(g *Global) error { if len(g.AfiSafis) == 0 { g.AfiSafis = []AfiSafi{} - for k, _ := range AfiSafiTypeToIntMap { + for k := range AfiSafiTypeToIntMap { g.AfiSafis = append(g.AfiSafis, defaultAfiSafi(k, true)) } } @@ -313,7 +324,7 @@ if err != nil { return err } - for i, _ := range p.Statements { + for i := range p.Statements { vv := viper.New() if len(stmts) > i { vv.Set("statement", stmts[i]) diff -Nru gobgp-1.32/config/default_linux.go gobgp-1.33/config/default_linux.go --- gobgp-1.32/config/default_linux.go 2018-06-01 11:32:28.000000000 +0000 +++ gobgp-1.33/config/default_linux.go 2018-07-01 12:06:57.000000000 +0000 @@ -18,8 +18,9 @@ import ( "fmt" - "github.com/vishvananda/netlink" "net" + + "github.com/vishvananda/netlink" ) func GetIPv6LinkLocalNeighborAddress(ifname string) (string, error) { @@ -40,7 +41,7 @@ } if neigh.State&netlink.NUD_FAILED == 0 && neigh.IP.IsLinkLocalUnicast() && !local { addr = neigh.IP - cnt += 1 + cnt++ } } @@ -52,3 +53,20 @@ return fmt.Sprintf("%s%%%s", addr, ifname), nil } + +func isLocalLinkLocalAddress(ifindex int, addr net.IP) (bool, error) { + ifi, err := net.InterfaceByIndex(ifindex) + if err != nil { + return false, err + } + addrs, err := ifi.Addrs() + if err != nil { + return false, err + } + for _, a := range addrs { + if ip, _, _ := net.ParseCIDR(a.String()); addr.Equal(ip) { + return true, nil + } + } + return false, nil +} diff -Nru gobgp-1.32/config/serve.go gobgp-1.33/config/serve.go --- gobgp-1.32/config/serve.go 2018-06-01 11:32:28.000000000 +0000 +++ gobgp-1.33/config/serve.go 2018-07-01 12:06:57.000000000 +0000 @@ -68,12 +68,10 @@ }).Warningf("Can't read config file %s", path) } NEXT: - select { - case <-sigCh: - log.WithFields(log.Fields{ - "Topic": "Config", - }).Info("Reload the config file") - } + <-sigCh + log.WithFields(log.Fields{ + "Topic": "Config", + }).Info("Reload the config file") } } @@ -147,9 +145,8 @@ "Topic": "Config", }).Debugf("New policy:%s", newPolicy) - var result bool = false + var result bool if currentPolicy == nil && newPolicy == nil { - result = false } else { if currentPolicy != nil && newPolicy != nil { diff -Nru gobgp-1.32/config/util.go gobgp-1.33/config/util.go --- gobgp-1.32/config/util.go 2018-06-01 11:32:28.000000000 +0000 +++ gobgp-1.33/config/util.go 2018-07-01 12:06:57.000000000 +0000 @@ -81,23 +81,6 @@ return "", fmt.Errorf("no ipv6 link local address for %s", ifname) } -func isLocalLinkLocalAddress(ifindex int, addr net.IP) (bool, error) { - ifi, err := net.InterfaceByIndex(ifindex) - if err != nil { - return false, err - } - addrs, err := ifi.Addrs() - if err != nil { - return false, err - } - for _, a := range addrs { - if ip, _, _ := net.ParseCIDR(a.String()); addr.Equal(ip) { - return true, nil - } - } - return false, nil -} - func (b *BgpConfigSet) getPeerGroup(n string) (*PeerGroup, error) { if n == "" { return nil, nil @@ -240,6 +223,9 @@ isAfiSafiChanged(n.AfiSafis, new.AfiSafis) } +// TODO: these regexp are duplicated in api +var _regexpPrefixMaskLengthRange = regexp.MustCompile(`(\d+)\.\.(\d+)`) + func ParseMaskLength(prefix, mask string) (int, int, error) { _, ipNet, err := net.ParseCIDR(prefix) if err != nil { @@ -249,8 +235,7 @@ l, _ := ipNet.Mask.Size() return l, l, nil } - exp := regexp.MustCompile("(\\d+)\\.\\.(\\d+)") - elems := exp.FindStringSubmatch(mask) + elems := _regexpPrefixMaskLengthRange.FindStringSubmatch(mask) if len(elems) != 3 { return 0, 0, fmt.Errorf("invalid mask length range: %s", mask) } diff -Nru gobgp-1.32/config/util_test.go gobgp-1.33/config/util_test.go --- gobgp-1.32/config/util_test.go 2018-06-01 11:32:28.000000000 +0000 +++ gobgp-1.33/config/util_test.go 2018-07-01 12:06:57.000000000 +0000 @@ -16,8 +16,9 @@ package config import ( - "github.com/stretchr/testify/assert" "testing" + + "github.com/stretchr/testify/assert" ) func TestDetectConfigFileType(t *testing.T) { diff -Nru gobgp-1.32/debian/changelog gobgp-1.33/debian/changelog --- gobgp-1.32/debian/changelog 2018-06-05 13:32:26.000000000 +0000 +++ gobgp-1.33/debian/changelog 2018-07-05 06:50:20.000000000 +0000 @@ -1,3 +1,11 @@ +gobgp (1.33-1) unstable; urgency=medium + + * New upstream release. + * d/rules: fix rebuild of protobuf generated files. + * d/patches: disable RPKI test requiring network access. + + -- Vincent Bernat Thu, 05 Jul 2018 08:50:20 +0200 + gobgp (1.32-1) unstable; urgency=medium * New upstream release. diff -Nru gobgp-1.32/debian/patches/0001-Compatibility-with-current-versions-of-satori-go.uui.patch gobgp-1.33/debian/patches/0001-Compatibility-with-current-versions-of-satori-go.uui.patch --- gobgp-1.32/debian/patches/0001-Compatibility-with-current-versions-of-satori-go.uui.patch 2018-06-05 13:32:26.000000000 +0000 +++ gobgp-1.33/debian/patches/0001-Compatibility-with-current-versions-of-satori-go.uui.patch 2018-07-05 06:50:20.000000000 +0000 @@ -11,15 +11,15 @@ 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/server/server.go b/server/server.go -index a15c342..8495855 100644 +index 2293756..97494ea 100644 --- a/server/server.go +++ b/server/server.go -@@ -1590,7 +1590,7 @@ func (s *BgpServer) AddPath(vrfId string, pathList []*table.Path) (uuidBytes []b +@@ -1600,7 +1600,7 @@ func (s *BgpServer) AddPath(vrfId string, pathList []*table.Path) (uuidBytes []b } if len(pathList) == 1 { path := pathList[0] - id, _ := uuid.NewV4() + id := uuid.NewV4() s.uuidMap[id] = pathTokey(path) + uuidBytes = id.Bytes() } - s.propagateUpdate(nil, pathList) diff -Nru gobgp-1.32/debian/patches/0002-Disable-RPKI-test-using-network.patch gobgp-1.33/debian/patches/0002-Disable-RPKI-test-using-network.patch --- gobgp-1.32/debian/patches/0002-Disable-RPKI-test-using-network.patch 1970-01-01 00:00:00.000000000 +0000 +++ gobgp-1.33/debian/patches/0002-Disable-RPKI-test-using-network.patch 2018-07-05 06:50:20.000000000 +0000 @@ -0,0 +1,20 @@ +From: Vincent Bernat +Date: Thu, 5 Jul 2018 10:49:30 +0200 +Subject: Disable RPKI test using network + +--- + gobgp/cmd/rpki_test.go | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/gobgp/cmd/rpki_test.go b/gobgp/cmd/rpki_test.go +index 985681e..18e4466 100644 +--- a/gobgp/cmd/rpki_test.go ++++ b/gobgp/cmd/rpki_test.go +@@ -27,6 +27,7 @@ import ( + ) + + func TestShowRPKITable(test *testing.T) { ++ test.Skip("no network") + assert := assert.New(test) + + s := server.NewBgpServer() diff -Nru gobgp-1.32/debian/patches/series gobgp-1.33/debian/patches/series --- gobgp-1.32/debian/patches/series 2018-06-05 13:32:26.000000000 +0000 +++ gobgp-1.33/debian/patches/series 2018-07-05 06:50:20.000000000 +0000 @@ -1 +1,2 @@ 0001-Compatibility-with-current-versions-of-satori-go.uui.patch +0002-Disable-RPKI-test-using-network.patch diff -Nru gobgp-1.32/debian/rules gobgp-1.33/debian/rules --- gobgp-1.32/debian/rules 2018-06-05 13:32:26.000000000 +0000 +++ gobgp-1.33/debian/rules 2018-07-05 06:50:20.000000000 +0000 @@ -5,9 +5,7 @@ %: dh $@ --buildsystem=golang --with=golang,bash-completion,systemd -PB_GO_FILES = $(patsubst %.proto, %.pb.go, $(wildcard */*.proto)) -$(PB_GO_FILES): - protoc -I$(dir $@) --go_out=plugins=grpc:$(dir $@) $(@:.pb.go=.proto) - -override_dh_auto_configure: $(PB_GO_FILES) +PB_GO_FILES = $(patsubst %.proto, %.pb.go, $(wildcard api/*.proto)) +override_dh_auto_configure: + protoc -Iapi/ --go_out=plugins=grpc:api/ $(PB_GO_FILES:.pb.go=.proto) dh_auto_configure diff -Nru gobgp-1.32/docs/sources/cli-command-syntax.md gobgp-1.33/docs/sources/cli-command-syntax.md --- gobgp-1.32/docs/sources/cli-command-syntax.md 2018-06-01 11:32:28.000000000 +0000 +++ gobgp-1.33/docs/sources/cli-command-syntax.md 2018-07-01 12:06:57.000000000 +0000 @@ -464,7 +464,7 @@ # mod statement % gobgp policy statement { add | del } # mod a condition to a statement -% gobgp policy statement { add | del | set } condition { { prefix | neighbor | as-path | community | ext-community | large-community } [{ any | all | invert }] | as-path-length { eq | ge | le } | rpki { valid | invalid | not-found } } +% gobgp policy statement { add | del | set } condition { { prefix | neighbor | as-path | community | ext-community | large-community } [{ any | all | invert }] | as-path-length { eq | ge | le } | rpki { valid | invalid | not-found } | next-hop-in-list [, , ...] | afi-safi-in { ... } } # mod an action to a statement % gobgp policy statement { add | del | set } action { reject | accept | { community | ext-community | large-community } { add | remove | replace } ... | med { add | sub | set } | local-pref | as-prepend { | last-as } } # show all statements diff -Nru gobgp-1.32/docs/sources/configuration.md gobgp-1.33/docs/sources/configuration.md --- gobgp-1.32/docs/sources/configuration.md 2018-06-01 11:32:28.000000000 +0000 +++ gobgp-1.33/docs/sources/configuration.md 2018-07-01 12:06:57.000000000 +0000 @@ -262,6 +262,13 @@ options = "remove" [policy-definitions.statements.actions.bgp-actions.set-ext-community.set-ext-community-method] communities-list = ["soo:500:600", "rt:700:800"] + [[policy-definitions.statements]] + [policy-definitions.statements.conditions.bgp-conditions] + next-hop-in-list = [ + "10.0.100.1/32" + ] + [policy-definitions.statements.actions] + route-disposition = "accept-route" [[policy-definitions]] name = "route-type-policy" diff -Nru gobgp-1.32/docs/sources/policy.md gobgp-1.33/docs/sources/policy.md --- gobgp-1.32/docs/sources/policy.md 2018-06-01 11:32:28.000000000 +0000 +++ gobgp-1.33/docs/sources/policy.md 2018-07-01 12:06:57.000000000 +0000 @@ -92,6 +92,7 @@ - rpki validation result - route type (internal/external/local) - large community +- afi-safi in As showed in the figure above, some of the conditions point to defined sets, which are a container for each condition item (e.g. prefixes). @@ -516,6 +517,8 @@ [policy-definitions.statements.conditions.bgp-conditions.as-path-length] operator = "eq" value = 2 + [policy-definitions.statements.conditions.bgp-conditions] + afi-safi-in = ["l3vpn-ipv4-unicast", "ipv4-unicast"] [policy-definitions.statements.actions] route-disposition = "accept-route" [policy-definitions.statements.actions.bgp-actions] diff -Nru gobgp-1.32/gobgp/cmd/common.go gobgp-1.33/gobgp/cmd/common.go --- gobgp-1.32/gobgp/cmd/common.go 2018-06-01 11:32:28.000000000 +0000 +++ gobgp-1.33/gobgp/cmd/common.go 2018-07-01 12:06:57.000000000 +0000 @@ -29,10 +29,10 @@ "google.golang.org/grpc" "google.golang.org/grpc/credentials" + api "github.com/osrg/gobgp/api" cli "github.com/osrg/gobgp/client" "github.com/osrg/gobgp/config" "github.com/osrg/gobgp/packet/bgp" - "github.com/osrg/gobgp/table" ) const ( @@ -97,23 +97,6 @@ Transport string `short:"t" long:"transport" description:"specifying a transport protocol"` } -var conditionOpts struct { - Prefix string `long:"prefix" description:"specifying a prefix set name of policy"` - Neighbor string `long:"neighbor" description:"specifying a neighbor set name of policy"` - AsPath string `long:"aspath" description:"specifying an as set name of policy"` - Community string `long:"community" description:"specifying a community set name of policy"` - ExtCommunity string `long:"extcommunity" description:"specifying a extended community set name of policy"` - AsPathLength string `long:"aspath-len" description:"specifying an as path length of policy (,)"` -} - -var actionOpts struct { - RouteAction string `long:"route-action" description:"specifying a route action of policy (accept | reject)"` - CommunityAction string `long:"community" description:"specifying a community action of policy"` - MedAction string `long:"med" description:"specifying a med action of policy"` - AsPathPrependAction string `long:"as-prepend" description:"specifying a as-prepend action of policy"` - NexthopAction string `long:"next-hop" description:"specifying a next-hop action of policy"` -} - var mrtOpts struct { OutputDir string FileFormat string @@ -142,9 +125,8 @@ if days == 0 { return fmt.Sprintf("%02d:%02d:%02d", hours, mins, secs) - } else { - return fmt.Sprintf("%dd ", days) + fmt.Sprintf("%02d:%02d:%02d", hours, mins, secs) } + return fmt.Sprintf("%dd ", days) + fmt.Sprintf("%02d:%02d:%02d", hours, mins, secs) } func cidr2prefix(cidr string) string { @@ -217,10 +199,7 @@ p1Isv4 := !strings.Contains(p1, ":") p2Isv4 := !strings.Contains(p2, ":") if p1Isv4 != p2Isv4 { - if p1Isv4 { - return true - } - return false + return p1Isv4 } addrlen := 128 if p1Isv4 { @@ -245,7 +224,7 @@ return c[i].Code() < c[j].Code() } -type vrfs []*table.Vrf +type vrfs []*api.Vrf func (v vrfs) Len() int { return len(v) diff -Nru gobgp-1.32/gobgp/cmd/common_test.go gobgp-1.33/gobgp/cmd/common_test.go --- gobgp-1.32/gobgp/cmd/common_test.go 2018-06-01 11:32:28.000000000 +0000 +++ gobgp-1.33/gobgp/cmd/common_test.go 2018-07-01 12:06:57.000000000 +0000 @@ -16,10 +16,10 @@ package cmd import ( - "fmt" - "github.com/stretchr/testify/assert" "strings" "testing" + + "github.com/stretchr/testify/assert" ) func Test_ExtractReserved(t *testing.T) { @@ -32,7 +32,6 @@ "aigp": PARAM_LIST, "local-pref": PARAM_SINGLE} m, _ := extractReserved(args, keys) - fmt.Println(m) assert.True(len(m["rt"]) == 1) assert.True(len(m["med"]) == 1) assert.True(len(m["nexthop"]) == 1) diff -Nru gobgp-1.32/gobgp/cmd/global.go gobgp-1.33/gobgp/cmd/global.go --- gobgp-1.32/gobgp/cmd/global.go 2018-06-01 11:32:28.000000000 +0000 +++ gobgp-1.33/gobgp/cmd/global.go 2018-07-01 12:06:57.000000000 +0000 @@ -877,18 +877,21 @@ return uint32(i), nil } +var ( + _regexpASPathGroups = regexp.MustCompile("[{}]") + _regexpASPathSegment = regexp.MustCompile(`,|\s+`) +) + func newAsPath(aspath string) (bgp.PathAttributeInterface, error) { // For the first step, parses "aspath" into a list of uint32 list. // e.g.) "10 20 {30,40} 50" -> [][]uint32{{10, 20}, {30, 40}, {50}} - exp := regexp.MustCompile("[{}]") - segments := exp.Split(aspath, -1) + segments := _regexpASPathGroups.Split(aspath, -1) asPathPrams := make([]bgp.AsPathParamInterface, 0, len(segments)) - exp = regexp.MustCompile(",|\\s+") for idx, segment := range segments { if segment == "" { continue } - nums := exp.Split(segment, -1) + nums := _regexpASPathSegment.Split(segment, -1) asNums := make([]uint32, 0, len(nums)) for _, n := range nums { if n == "" { @@ -1071,22 +1074,6 @@ return args, nil, nil } -func extractRouteDistinguisher(args []string) ([]string, bgp.RouteDistinguisherInterface, error) { - for idx, arg := range args { - if arg == "rd" { - if len(args) < (idx + 1) { - return nil, nil, fmt.Errorf("invalid rd format") - } - rd, err := bgp.ParseRouteDistinguisher(args[idx+1]) - if err != nil { - return nil, nil, err - } - return append(args[:idx], args[idx+2:]...), rd, nil - } - } - return args, nil, nil -} - func ParsePath(rf bgp.RouteFamily, args []string) (*table.Path, error) { var nlri bgp.AddrPrefixInterface var extcomms []string @@ -1250,7 +1237,7 @@ attrs = append(attrs, mpreach) } - if extcomms != nil && len(extcomms) > 0 { + if extcomms != nil { extcomms, err := ParseExtendedCommunities(extcomms) if err != nil { return nil, err diff -Nru gobgp-1.32/gobgp/cmd/global_test.go gobgp-1.33/gobgp/cmd/global_test.go --- gobgp-1.32/gobgp/cmd/global_test.go 2018-06-01 11:32:28.000000000 +0000 +++ gobgp-1.33/gobgp/cmd/global_test.go 2018-07-01 12:06:57.000000000 +0000 @@ -16,11 +16,12 @@ package cmd import ( - "fmt" - "github.com/osrg/gobgp/packet/bgp" - "github.com/stretchr/testify/assert" "strings" "testing" + + "github.com/stretchr/testify/assert" + + "github.com/osrg/gobgp/packet/bgp" ) func Test_ParsePath(t *testing.T) { @@ -29,7 +30,6 @@ path, err := ParsePath(bgp.RF_IPv4_UC, strings.Split(buf, " ")) assert.Nil(err) - fmt.Println(path) i := 0 for _, a := range path.GetPathAttrs() { assert.True(i < int(a.GetType())) diff -Nru gobgp-1.32/gobgp/cmd/mrt.go gobgp-1.33/gobgp/cmd/mrt.go --- gobgp-1.32/gobgp/cmd/mrt.go 2018-06-01 11:32:28.000000000 +0000 +++ gobgp-1.33/gobgp/cmd/mrt.go 2018-07-01 12:06:57.000000000 +0000 @@ -142,7 +142,7 @@ } if mrtOpts.Best { - dst := table.NewDestination(nlri, 0, paths...) + dst := table.NewDestination(nlri, 0, paths[1:]...) best, _, _ := dst.Calculate(paths[0]).GetChanges(table.GLOBAL_RIB_NAME, 0, false) if best == nil { exitWithError(fmt.Errorf("Can't find the best %v", nlri)) diff -Nru gobgp-1.32/gobgp/cmd/neighbor.go gobgp-1.33/gobgp/cmd/neighbor.go --- gobgp-1.32/gobgp/cmd/neighbor.go 2018-06-01 11:32:28.000000000 +0000 +++ gobgp-1.33/gobgp/cmd/neighbor.go 2018-07-01 12:06:57.000000000 +0000 @@ -129,11 +129,11 @@ } timedelta = append(timedelta, timeStr) } - var format string - format = "%-" + fmt.Sprint(maxaddrlen) + "s" + " %" + fmt.Sprint(maxaslen) + "s" + " %" + fmt.Sprint(maxtimelen) + "s" + + format := "%-" + fmt.Sprint(maxaddrlen) + "s" + " %" + fmt.Sprint(maxaslen) + "s" + " %" + fmt.Sprint(maxtimelen) + "s" format += " %-11s |%9s %9s\n" fmt.Printf(format, "Peer", "AS", "Up/Down", "State", "#Received", "Accepted") - format_fsm := func(admin config.AdminState, fsm config.SessionState) string { + formatFsm := func(admin config.AdminState, fsm config.SessionState) string { switch admin { case config.ADMIN_STATE_DOWN: return "Idle(Admin)" @@ -164,7 +164,7 @@ if n.Config.NeighborInterface != "" { neigh = n.Config.NeighborInterface } - fmt.Printf(format, neigh, getASN(n), timedelta[i], format_fsm(n.State.AdminState, n.State.SessionState), fmt.Sprint(n.State.AdjTable.Received), fmt.Sprint(n.State.AdjTable.Accepted)) + fmt.Printf(format, neigh, getASN(n), timedelta[i], formatFsm(n.State.AdminState, n.State.SessionState), fmt.Sprint(n.State.AdjTable.Received), fmt.Sprint(n.State.AdjTable.Accepted)) } return nil @@ -196,7 +196,12 @@ id = p.State.RemoteRouterId } fmt.Printf(" BGP version 4, remote router ID %s\n", id) - fmt.Printf(" BGP state = %s, up for %s\n", p.State.SessionState, formatTimedelta(int64(p.Timers.State.Uptime)-time.Now().Unix())) + fmt.Printf(" BGP state = %s", p.State.SessionState) + if p.Timers.State.Uptime > 0 { + fmt.Printf(", up for %s\n", formatTimedelta(int64(p.Timers.State.Uptime)-time.Now().Unix())) + } else { + fmt.Print("\n") + } fmt.Printf(" BGP OutQ = %d, Flops = %d\n", p.State.Queues.Output, p.State.Flops) fmt.Printf(" Hold time is %d, keepalive interval is %d seconds\n", int(p.Timers.State.NegotiatedHoldTime), int(p.Timers.State.KeepaliveInterval)) fmt.Printf(" Configured hold time is %d, keepalive interval is %d seconds\n", int(p.Timers.Config.HoldTime), int(p.Timers.Config.KeepaliveInterval)) @@ -417,11 +422,7 @@ return nil } -type AsPathFormat struct { - start string - end string - separator string -} +type AsPathFormat struct{} func getPathSymbolString(p *table.Path, idx int, showBest bool) string { symbols := "" @@ -820,9 +821,7 @@ var ps []*table.Path switch r { case CMD_ACCEPTED: - for _, p := range d.GetAllKnownPathList() { - ps = append(ps, p) - } + ps = append(ps, d.GetAllKnownPathList()...) case CMD_REJECTED: // always nothing default: diff -Nru gobgp-1.32/gobgp/cmd/policy.go gobgp-1.33/gobgp/cmd/policy.go --- gobgp-1.32/gobgp/cmd/policy.go 2018-06-01 11:32:28.000000000 +0000 +++ gobgp-1.33/gobgp/cmd/policy.go 2018-07-01 12:06:57.000000000 +0000 @@ -31,6 +31,8 @@ "github.com/osrg/gobgp/table" ) +var _regexpCommunity = regexp.MustCompile(`\^\^(\S+)\$\$`) + func formatDefinedSet(head bool, typ string, indent int, list []table.DefinedSet) string { if len(list) == 0 { return "Nothing defined yet\n" @@ -59,13 +61,12 @@ } for i, x := range l { if typ == "COMMUNITY" || typ == "EXT-COMMUNITY" || typ == "LARGE-COMMUNITY" { - exp := regexp.MustCompile("\\^\\^(\\S+)\\$\\$") - x = exp.ReplaceAllString(x, "$1") + x = _regexpCommunity.ReplaceAllString(x, "$1") } if i == 0 { buff.WriteString(fmt.Sprintf(format, s.Name(), x)) } else { - buff.WriteString(fmt.Sprintf(sIndent)) + buff.WriteString(fmt.Sprint(sIndent)) buff.WriteString(fmt.Sprintf(format, "", x)) } } @@ -333,12 +334,16 @@ fmt.Printf("%sExtCommunitySet: %s %s\n", ind, t.Option(), t.Name()) case *table.LargeCommunityCondition: fmt.Printf("%sLargeCommunitySet: %s %s\n", ind, t.Option(), t.Name()) + case *table.NextHopCondition: + fmt.Printf("%sNextHopInList: %s\n", ind, t.String()) case *table.AsPathLengthCondition: fmt.Printf("%sAsPathLength: %s\n", ind, t.String()) case *table.RpkiValidationCondition: fmt.Printf("%sRPKI result: %s\n", ind, t.String()) case *table.RouteTypeCondition: fmt.Printf("%sRoute Type: %s\n", ind, t.String()) + case *table.AfiSafiInCondition: + fmt.Printf("%sAFI SAFI In: %s\n", ind, t.String()) } } @@ -480,7 +485,7 @@ } usage := fmt.Sprintf("usage: gobgp policy statement %s %s condition", name, op) if len(args) < 1 { - return fmt.Errorf("%s { prefix | neighbor | as-path | community | ext-community | large-community | as-path-length | rpki | route-type }", usage) + return fmt.Errorf("%s { prefix | neighbor | as-path | community | ext-community | large-community | as-path-length | rpki | route-type | next-hop-in-list | afi-safi-in }", usage) } typ := args[0] args = args[1:] @@ -637,8 +642,20 @@ default: return err } + case "next-hop-in-list": + stmt.Conditions.BgpConditions.NextHopInList = args + case "afi-safi-in": + afiSafisInList := make([]config.AfiSafiType, 0, len(args)) + for _, arg := range args { + afiSafi := config.AfiSafiType(arg) + if err := afiSafi.Validate(); err != nil { + return err + } + afiSafisInList = append(afiSafisInList, afiSafi) + } + stmt.Conditions.BgpConditions.AfiSafiInList = afiSafisInList default: - return fmt.Errorf("%s { prefix | neighbor | as-path | community | ext-community | large-community | as-path-length | rpki | route-type }", usage) + return fmt.Errorf("%s { prefix | neighbor | as-path | community | ext-community | large-community | as-path-length | rpki | route-type | next-hop-in-list | afi-safi-in }", usage) } t, err := table.NewStatement(stmt) @@ -762,6 +779,9 @@ stmt.Actions.BgpActions.SetNextHop = config.BgpNextHopType(args[0]) } t, err := table.NewStatement(stmt) + if err != nil { + return err + } switch op { case CMD_ADD: err = client.AddStatement(t) diff -Nru gobgp-1.32/gobgp/cmd/root.go gobgp-1.33/gobgp/cmd/root.go --- gobgp-1.32/gobgp/cmd/root.go 2018-06-01 11:32:28.000000000 +0000 +++ gobgp-1.33/gobgp/cmd/root.go 2018-07-01 12:06:57.000000000 +0000 @@ -37,7 +37,6 @@ CaFile string } -var cmds []string var client *cli.Client func NewRootCmd() *cobra.Command { diff -Nru gobgp-1.32/gobgp/cmd/rpki.go gobgp-1.33/gobgp/cmd/rpki.go --- gobgp-1.32/gobgp/cmd/rpki.go 2018-06-01 11:32:28.000000000 +0000 +++ gobgp-1.33/gobgp/cmd/rpki.go 2018-07-01 12:06:57.000000000 +0000 @@ -36,36 +36,37 @@ for _, r := range servers { s := "Down" uptime := "never" - if r.State.Up == true { + if r.State.Up { s = "Up" - uptime = fmt.Sprint(formatTimedelta(int64(time.Now().Sub(time.Unix(r.State.Uptime, 0)).Seconds()))) + uptime = fmt.Sprint(formatTimedelta(int64(time.Since(time.Unix(r.State.Uptime, 0)).Seconds()))) } fmt.Printf(format, net.JoinHostPort(r.Config.Address, fmt.Sprintf("%d", r.Config.Port)), s, uptime, fmt.Sprintf("%d/%d", r.State.RecordsV4, r.State.RecordsV6)) } - } else { - for _, r := range servers { - if r.Config.Address == args[0] { - up := "Down" - if r.State.Up == true { - up = "Up" - } - fmt.Printf("Session: %s, State: %s\n", r.Config.Address, up) - fmt.Println(" Port:", r.Config.Port) - fmt.Println(" Serial:", r.State.SerialNumber) - fmt.Printf(" Prefix: %d/%d\n", r.State.PrefixesV4, r.State.PrefixesV6) - fmt.Printf(" Record: %d/%d\n", r.State.RecordsV4, r.State.RecordsV6) - fmt.Println(" Message statistics:") - fmt.Printf(" Receivedv4: %10d\n", r.State.RpkiMessages.RpkiReceived.Ipv4Prefix) - fmt.Printf(" Receivedv6: %10d\n", r.State.RpkiMessages.RpkiReceived.Ipv4Prefix) - fmt.Printf(" SerialNotify: %10d\n", r.State.RpkiMessages.RpkiReceived.SerialNotify) - fmt.Printf(" CacheReset: %10d\n", r.State.RpkiMessages.RpkiReceived.CacheReset) - fmt.Printf(" CacheResponse: %10d\n", r.State.RpkiMessages.RpkiReceived.CacheResponse) - fmt.Printf(" EndOfData: %10d\n", r.State.RpkiMessages.RpkiReceived.EndOfData) - fmt.Printf(" Error: %10d\n", r.State.RpkiMessages.RpkiReceived.Error) - fmt.Printf(" SerialQuery: %10d\n", r.State.RpkiMessages.RpkiSent.SerialQuery) - fmt.Printf(" ResetQuery: %10d\n", r.State.RpkiMessages.RpkiSent.ResetQuery) + return nil + } + + for _, r := range servers { + if r.Config.Address == args[0] { + up := "Down" + if r.State.Up { + up = "Up" } + fmt.Printf("Session: %s, State: %s\n", r.Config.Address, up) + fmt.Println(" Port:", r.Config.Port) + fmt.Println(" Serial:", r.State.SerialNumber) + fmt.Printf(" Prefix: %d/%d\n", r.State.PrefixesV4, r.State.PrefixesV6) + fmt.Printf(" Record: %d/%d\n", r.State.RecordsV4, r.State.RecordsV6) + fmt.Println(" Message statistics:") + fmt.Printf(" Receivedv4: %10d\n", r.State.RpkiMessages.RpkiReceived.Ipv4Prefix) + fmt.Printf(" Receivedv6: %10d\n", r.State.RpkiMessages.RpkiReceived.Ipv4Prefix) + fmt.Printf(" SerialNotify: %10d\n", r.State.RpkiMessages.RpkiReceived.SerialNotify) + fmt.Printf(" CacheReset: %10d\n", r.State.RpkiMessages.RpkiReceived.CacheReset) + fmt.Printf(" CacheResponse: %10d\n", r.State.RpkiMessages.RpkiReceived.CacheResponse) + fmt.Printf(" EndOfData: %10d\n", r.State.RpkiMessages.RpkiReceived.EndOfData) + fmt.Printf(" Error: %10d\n", r.State.RpkiMessages.RpkiReceived.Error) + fmt.Printf(" SerialQuery: %10d\n", r.State.RpkiMessages.RpkiSent.SerialQuery) + fmt.Printf(" ResetQuery: %10d\n", r.State.RpkiMessages.RpkiSent.ResetQuery) } } return nil diff -Nru gobgp-1.32/gobgp/cmd/rpki_test.go gobgp-1.33/gobgp/cmd/rpki_test.go --- gobgp-1.32/gobgp/cmd/rpki_test.go 1970-01-01 00:00:00.000000000 +0000 +++ gobgp-1.33/gobgp/cmd/rpki_test.go 2018-07-01 12:06:57.000000000 +0000 @@ -0,0 +1,78 @@ +// Copyright (C) 2018 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 cmd + +import ( + "testing" + "time" + + "github.com/stretchr/testify/assert" + + api "github.com/osrg/gobgp/api" + "github.com/osrg/gobgp/config" + "github.com/osrg/gobgp/server" +) + +func TestShowRPKITable(test *testing.T) { + assert := assert.New(test) + + s := server.NewBgpServer() + go s.Serve() + + g := api.NewGrpcServer(s, ":50051") + go g.Serve() + + err := s.Start(&config.Global{ + Config: config.GlobalConfig{ + As: 1, + RouterId: "1.1.1.1", + Port: -1, + }, + }) + assert.Nil(err) + defer s.Stop() + + // MF RPKI Project + // http://www.mfeed.ad.jp/rpki/en/roa_cache/technical_info.html + rpki := &config.RpkiServerConfig{ + Address: "210.173.170.254", + Port: 323, + } + err = s.AddRpki(rpki) + assert.Nil(err) + + globalOpts.Host = "127.0.0.1" + globalOpts.Port = 50051 + client = newClient() + defer client.Close() + + // Wait for downloading ROA info + for i := 0; ; i++ { + if servers, err := s.GetRpki(); err == nil && len(servers) > 0 { + if servers[0].State.RecordsV4 > 0 { + break + } + } + if i > 10 { + test.Error("timeout to download ROA info") + break + } + time.Sleep(1 * time.Second) + } + + err = showRPKITable(nil) + assert.Nil(err) +} diff -Nru gobgp-1.32/gobgp/cmd/vrf.go gobgp-1.33/gobgp/cmd/vrf.go --- gobgp-1.32/gobgp/cmd/vrf.go 2018-06-01 11:32:28.000000000 +0000 +++ gobgp-1.33/gobgp/cmd/vrf.go 2018-07-01 12:06:57.000000000 +0000 @@ -22,9 +22,11 @@ "strconv" "strings" - "github.com/spf13/cobra" - + api "github.com/osrg/gobgp/api" "github.com/osrg/gobgp/packet/bgp" + + "github.com/golang/protobuf/ptypes/any" + "github.com/spf13/cobra" ) func getVrfs() (vrfs, error) { @@ -56,21 +58,35 @@ lines := make([][]string, 0, len(vrfs)) for _, v := range vrfs { name := v.Name - rd := v.Rd.String() + rd, err := api.UnmarshalRD(v.Rd) + if err != nil { + return err + } + rdStr := rd.String() - f := func(rts []bgp.ExtendedCommunityInterface) (string, error) { + f := func(rts []*any.Any) (string, error) { ret := make([]string, 0, len(rts)) - for _, rt := range rts { + for _, an := range rts { + rt, err := api.UnmarshalRT(an) + if err != nil { + return "", err + } ret = append(ret, rt.String()) } return strings.Join(ret, ", "), nil } - importRts, _ := f(v.ImportRt) - exportRts, _ := f(v.ExportRt) - lines = append(lines, []string{name, rd, importRts, exportRts, fmt.Sprintf("%d", v.Id)}) + importRts, err := f(v.ImportRt) + if err != nil { + return err + } + exportRts, err := f(v.ExportRt) + if err != nil { + return err + } + lines = append(lines, []string{name, rdStr, importRts, exportRts, fmt.Sprintf("%d", v.Id)}) - for i, v := range []int{len(name), len(rd), len(importRts), len(exportRts)} { + for i, v := range []int{len(name), len(rdStr), len(importRts), len(exportRts)} { if v > maxLens[i] { maxLens[i] = v + 4 } @@ -137,7 +153,9 @@ return err } } - err = client.AddVRF(name, int(id), rd, importRt, exportRt) + if err := client.AddVRF(name, int(id), rd, importRt, exportRt); err != nil { + return err + } case CMD_DEL: if len(args) != 1 { return fmt.Errorf("Usage: gobgp vrf del ") @@ -148,7 +166,6 @@ } func NewVrfCmd() *cobra.Command { - ribCmd := &cobra.Command{ Use: CMD_RIB, Run: func(cmd *cobra.Command, args []string) { diff -Nru gobgp-1.32/gobgp/lib/path.go gobgp-1.33/gobgp/lib/path.go --- gobgp-1.32/gobgp/lib/path.go 2018-06-01 11:32:28.000000000 +0000 +++ gobgp-1.33/gobgp/lib/path.go 2018-07-01 12:06:57.000000000 +0000 @@ -36,7 +36,6 @@ "encoding/json" "strings" - api "github.com/osrg/gobgp/api" "github.com/osrg/gobgp/gobgp/cmd" "github.com/osrg/gobgp/packet/bgp" ) @@ -53,18 +52,19 @@ //export serialize_path func serialize_path(rf C.int, input *C.char) *C.path { args := strings.Split(C.GoString(input), " ") - pp, err := cmd.ParsePath(bgp.RouteFamily(rf), args) + p, err := cmd.ParsePath(bgp.RouteFamily(rf), args) if err != nil { return nil } path := C.new_path() - p := api.ToPathApi(pp, nil) - if len(p.Nlri) > 0 { - path.nlri.len = C.int(len(p.Nlri)) - path.nlri.value = C.CString(string(p.Nlri)) + if nlri := p.GetNlri(); nlri != nil { + buf, _ := nlri.Serialize() + path.nlri.len = C.int(len(buf)) + path.nlri.value = C.CString(string(buf)) } - for _, attr := range p.Pattrs { - C.append_path_attribute(path, C.int(len(attr)), C.CString(string(attr))) + for _, attr := range p.GetPathAttrs() { + buf, _ := attr.Serialize() + C.append_path_attribute(path, C.int(len(buf)), C.CString(string(buf))) } return path } diff -Nru gobgp-1.32/gobgpd/main.go gobgp-1.33/gobgpd/main.go --- gobgp-1.32/gobgpd/main.go 2018-06-01 11:32:28.000000000 +0000 +++ gobgp-1.33/gobgpd/main.go 2018-07-01 12:06:57.000000000 +0000 @@ -26,9 +26,11 @@ "runtime" "syscall" + "github.com/golang/protobuf/ptypes/any" "github.com/jessevdk/go-flags" "github.com/kr/pretty" log "github.com/sirupsen/logrus" + "golang.org/x/net/context" "google.golang.org/grpc" "google.golang.org/grpc/credentials" @@ -41,6 +43,18 @@ var version = "master" +func marshalRouteTargets(l []string) ([]*any.Any, error) { + rtList := make([]*any.Any, 0, len(l)) + for _, rtString := range l { + rt, err := bgp.ParseRouteTarget(rtString) + if err != nil { + return nil, err + } + rtList = append(rtList, api.MarshalRT(rt)) + } + return rtList, nil +} + func main() { sigCh := make(chan os.Signal, 1) signal.Notify(sigCh, syscall.SIGTERM) @@ -99,7 +113,7 @@ log.SetLevel(log.InfoLevel) } - if opts.DisableStdlog == true { + if opts.DisableStdlog { log.SetOutput(ioutil.Discard) } else { log.SetOutput(os.Stdout) @@ -155,185 +169,282 @@ go config.ReadConfigfileServe(opts.ConfigFile, opts.ConfigType, configCh) } - var c *config.BgpConfigSet = nil - for { - select { - case newConfig := <-configCh: - var added, deleted, updated []config.Neighbor - var addedPg, deletedPg, updatedPg []config.PeerGroup - var updatePolicy bool - - if c == nil { - c = newConfig - if err := bgpServer.Start(&newConfig.Global); err != nil { - log.Fatalf("failed to set global config: %s", err) - } - if newConfig.Zebra.Config.Enabled { - if err := bgpServer.StartZebraClient(&newConfig.Zebra.Config); err != nil { - log.Fatalf("failed to set zebra config: %s", err) - } - } - if len(newConfig.Collector.Config.Url) > 0 { - if err := bgpServer.StartCollector(&newConfig.Collector.Config); err != nil { - log.Fatalf("failed to set collector config: %s", err) + loop := func() { + var c *config.BgpConfigSet + for { + select { + case <-sigCh: + apiServer.Shutdown(context.Background(), &api.ShutdownRequest{}) + return + case newConfig := <-configCh: + var added, deleted, updated []config.Neighbor + var addedPg, deletedPg, updatedPg []config.PeerGroup + var updatePolicy bool + + if c == nil { + c = newConfig + if _, err := apiServer.StartServer(context.Background(), &api.StartServerRequest{ + Global: api.NewGlobalFromConfigStruct(&c.Global), + }); err != nil { + log.Fatalf("failed to set global config: %s", err) + } + + if newConfig.Zebra.Config.Enabled { + tps := c.Zebra.Config.RedistributeRouteTypeList + l := make([]string, 0, len(tps)) + for _, t := range tps { + l = append(l, string(t)) + } + if _, err := apiServer.EnableZebra(context.Background(), &api.EnableZebraRequest{ + Url: c.Zebra.Config.Url, + RouteTypes: l, + Version: uint32(c.Zebra.Config.Version), + NexthopTriggerEnable: c.Zebra.Config.NexthopTriggerEnable, + NexthopTriggerDelay: uint32(c.Zebra.Config.NexthopTriggerDelay), + }); err != nil { + log.Fatalf("failed to set zebra config: %s", err) + } } - } - for i, _ := range newConfig.RpkiServers { - if err := bgpServer.AddRpki(&newConfig.RpkiServers[i].Config); err != nil { - log.Fatalf("failed to set rpki config: %s", err) + + if len(newConfig.Collector.Config.Url) > 0 { + if _, err := apiServer.AddCollector(context.Background(), &api.AddCollectorRequest{ + Url: c.Collector.Config.Url, + DbName: c.Collector.Config.DbName, + TableDumpInterval: c.Collector.Config.TableDumpInterval, + }); err != nil { + log.Fatalf("failed to set collector config: %s", err) + } } - } - for i, _ := range newConfig.BmpServers { - if err := bgpServer.AddBmp(&newConfig.BmpServers[i].Config); err != nil { - log.Fatalf("failed to set bmp config: %s", err) + + for _, c := range newConfig.RpkiServers { + if _, err := apiServer.AddRpki(context.Background(), &api.AddRpkiRequest{ + Address: c.Config.Address, + Port: c.Config.Port, + Lifetime: c.Config.RecordLifetime, + }); err != nil { + log.Fatalf("failed to set rpki config: %s", err) + } } - } - for _, vrf := range newConfig.Vrfs { - rd, err := bgp.ParseRouteDistinguisher(vrf.Config.Rd) - if err != nil { - log.Fatalf("failed to load vrf rd config: %s", err) + for _, c := range newConfig.BmpServers { + if _, err := apiServer.AddBmp(context.Background(), &api.AddBmpRequest{ + Address: c.Config.Address, + Port: c.Config.Port, + Type: api.AddBmpRequest_MonitoringPolicy(c.Config.RouteMonitoringPolicy.ToInt()), + }); err != nil { + log.Fatalf("failed to set bmp config: %s", err) + } } - importRtList := make([]bgp.ExtendedCommunityInterface, 0, len(vrf.Config.ImportRtList)) - for _, rtString := range vrf.Config.ImportRtList { - rt, err := bgp.ParseRouteTarget(rtString) + for _, vrf := range newConfig.Vrfs { + rd, err := bgp.ParseRouteDistinguisher(vrf.Config.Rd) + if err != nil { + log.Fatalf("failed to load vrf rd config: %s", err) + } + + importRtList, err := marshalRouteTargets(vrf.Config.ImportRtList) if err != nil { log.Fatalf("failed to load vrf import rt config: %s", err) } - importRtList = append(importRtList, rt) - } - exportRtList := make([]bgp.ExtendedCommunityInterface, 0, len(vrf.Config.ExportRtList)) - for _, rtString := range vrf.Config.ExportRtList { - rt, err := bgp.ParseRouteTarget(rtString) + exportRtList, err := marshalRouteTargets(vrf.Config.ExportRtList) if err != nil { log.Fatalf("failed to load vrf export rt config: %s", err) } - exportRtList = append(exportRtList, rt) - } - if err := bgpServer.AddVrf(vrf.Config.Name, vrf.Config.Id, rd, importRtList, exportRtList); err != nil { - log.Fatalf("failed to set vrf config: %s", err) + + if _, err := apiServer.AddVrf(context.Background(), &api.AddVrfRequest{ + Vrf: &api.Vrf{ + Name: vrf.Config.Name, + Rd: api.MarshalRD(rd), + Id: uint32(vrf.Config.Id), + ImportRt: importRtList, + ExportRt: exportRtList, + }, + }); err != nil { + log.Fatalf("failed to set vrf config: %s", err) + } } - } - for i, _ := range newConfig.MrtDump { - if len(newConfig.MrtDump[i].Config.FileName) == 0 { - continue + for _, c := range newConfig.MrtDump { + if len(c.Config.FileName) == 0 { + continue + } + if _, err := apiServer.EnableMrt(context.Background(), &api.EnableMrtRequest{ + DumpType: int32(c.Config.DumpType.ToInt()), + Filename: c.Config.FileName, + Interval: c.Config.DumpInterval, + }); err != nil { + log.Fatalf("failed to set mrt config: %s", err) + } } - if err := bgpServer.EnableMrt(&newConfig.MrtDump[i].Config); err != nil { - log.Fatalf("failed to set mrt config: %s", err) + p := config.ConfigSetToRoutingPolicy(newConfig) + rp, err := api.NewAPIRoutingPolicyFromConfigStruct(p) + if err != nil { + log.Warn(err) + } else { + apiServer.UpdatePolicy(context.Background(), &api.UpdatePolicyRequest{ + Sets: rp.DefinedSet, + Policies: rp.PolicyDefinition, + }) } - } - p := config.ConfigSetToRoutingPolicy(newConfig) - if err := bgpServer.UpdatePolicy(*p); err != nil { - log.Fatalf("failed to set routing policy: %s", err) - } - added = newConfig.Neighbors - addedPg = newConfig.PeerGroups - if opts.GracefulRestart { - for i, n := range added { - if n.GracefulRestart.Config.Enabled { - added[i].GracefulRestart.State.LocalRestarting = true + added = newConfig.Neighbors + addedPg = newConfig.PeerGroups + if opts.GracefulRestart { + for i, n := range added { + if n.GracefulRestart.Config.Enabled { + added[i].GracefulRestart.State.LocalRestarting = true + } } } - } - } else { - addedPg, deletedPg, updatedPg = config.UpdatePeerGroupConfig(c, newConfig) - added, deleted, updated = config.UpdateNeighborConfig(c, newConfig) - updatePolicy = config.CheckPolicyDifference(config.ConfigSetToRoutingPolicy(c), config.ConfigSetToRoutingPolicy(newConfig)) - - if updatePolicy { - log.Info("Policy config is updated") - p := config.ConfigSetToRoutingPolicy(newConfig) - bgpServer.UpdatePolicy(*p) - } - // global policy update - if !newConfig.Global.ApplyPolicy.Config.Equal(&c.Global.ApplyPolicy.Config) { - a := newConfig.Global.ApplyPolicy.Config - toDefaultTable := func(r config.DefaultPolicyType) table.RouteType { - var def table.RouteType - switch r { - case config.DEFAULT_POLICY_TYPE_ACCEPT_ROUTE: - def = table.ROUTE_TYPE_ACCEPT - case config.DEFAULT_POLICY_TYPE_REJECT_ROUTE: - def = table.ROUTE_TYPE_REJECT - } - return def - } - toPolicyDefinitions := func(r []string) []*config.PolicyDefinition { - p := make([]*config.PolicyDefinition, 0, len(r)) - for _, n := range r { - p = append(p, &config.PolicyDefinition{ - Name: n, + } else { + addedPg, deletedPg, updatedPg = config.UpdatePeerGroupConfig(c, newConfig) + added, deleted, updated = config.UpdateNeighborConfig(c, newConfig) + updatePolicy = config.CheckPolicyDifference(config.ConfigSetToRoutingPolicy(c), config.ConfigSetToRoutingPolicy(newConfig)) + + if updatePolicy { + log.Info("Policy config is updated") + p := config.ConfigSetToRoutingPolicy(newConfig) + rp, err := api.NewAPIRoutingPolicyFromConfigStruct(p) + if err != nil { + log.Warn(err) + } else { + apiServer.UpdatePolicy(context.Background(), &api.UpdatePolicyRequest{ + Sets: rp.DefinedSet, + Policies: rp.PolicyDefinition, }) } - return p } + // global policy update + if !newConfig.Global.ApplyPolicy.Config.Equal(&c.Global.ApplyPolicy.Config) { + a := newConfig.Global.ApplyPolicy.Config + toDefaultTable := func(r config.DefaultPolicyType) table.RouteType { + var def table.RouteType + switch r { + case config.DEFAULT_POLICY_TYPE_ACCEPT_ROUTE: + def = table.ROUTE_TYPE_ACCEPT + case config.DEFAULT_POLICY_TYPE_REJECT_ROUTE: + def = table.ROUTE_TYPE_REJECT + } + return def + } + toPolicies := func(r []string) []*table.Policy { + p := make([]*table.Policy, 0, len(r)) + for _, n := range r { + p = append(p, &table.Policy{ + Name: n, + }) + } + return p + } - def := toDefaultTable(a.DefaultImportPolicy) - ps := toPolicyDefinitions(a.ImportPolicyList) - bgpServer.ReplacePolicyAssignment("", table.POLICY_DIRECTION_IMPORT, ps, def) - - def = toDefaultTable(a.DefaultExportPolicy) - ps = toPolicyDefinitions(a.ExportPolicyList) - bgpServer.ReplacePolicyAssignment("", table.POLICY_DIRECTION_EXPORT, ps, def) - - updatePolicy = true - - } - c = newConfig - } - for i, pg := range addedPg { - log.Infof("PeerGroup %s is added", pg.Config.PeerGroupName) - if err := bgpServer.AddPeerGroup(&addedPg[i]); err != nil { - log.Warn(err) - } - } - for i, pg := range deletedPg { - log.Infof("PeerGroup %s is deleted", pg.Config.PeerGroupName) - if err := bgpServer.DeletePeerGroup(&deletedPg[i]); err != nil { - log.Warn(err) - } - } - for i, pg := range updatedPg { - log.Infof("PeerGroup %s is updated", pg.Config.PeerGroupName) - u, err := bgpServer.UpdatePeerGroup(&updatedPg[i]) - if err != nil { - log.Warn(err) - } - updatePolicy = updatePolicy || u - } - for i, dn := range newConfig.DynamicNeighbors { - log.Infof("Dynamic Neighbor %s is added to PeerGroup %s", dn.Config.Prefix, dn.Config.PeerGroup) - if err := bgpServer.AddDynamicNeighbor(&newConfig.DynamicNeighbors[i]); err != nil { - log.Warn(err) - } - } - for i, p := range added { - log.Infof("Peer %v is added", p.State.NeighborAddress) - if err := bgpServer.AddNeighbor(&added[i]); err != nil { - log.Warn(err) - } - } - for i, p := range deleted { - log.Infof("Peer %v is deleted", p.State.NeighborAddress) - if err := bgpServer.DeleteNeighbor(&deleted[i]); err != nil { - log.Warn(err) - } - } - for i, p := range updated { - log.Infof("Peer %v is updated", p.State.NeighborAddress) - u, err := bgpServer.UpdateNeighbor(&updated[i]) - if err != nil { - log.Warn(err) + def := toDefaultTable(a.DefaultImportPolicy) + ps := toPolicies(a.ImportPolicyList) + apiServer.ReplacePolicyAssignment(context.Background(), &api.ReplacePolicyAssignmentRequest{ + Assignment: api.NewAPIPolicyAssignmentFromTableStruct(&table.PolicyAssignment{ + Name: "", + Type: table.POLICY_DIRECTION_IMPORT, + Policies: ps, + Default: def, + }), + }) + + def = toDefaultTable(a.DefaultExportPolicy) + ps = toPolicies(a.ExportPolicyList) + apiServer.ReplacePolicyAssignment(context.Background(), &api.ReplacePolicyAssignmentRequest{ + Assignment: api.NewAPIPolicyAssignmentFromTableStruct(&table.PolicyAssignment{ + Name: "", + Type: table.POLICY_DIRECTION_EXPORT, + Policies: ps, + Default: def, + }), + }) + + updatePolicy = true + + } + c = newConfig + } + for _, pg := range addedPg { + log.Infof("PeerGroup %s is added", pg.Config.PeerGroupName) + if _, err := apiServer.AddPeerGroup(context.Background(), &api.AddPeerGroupRequest{ + PeerGroup: api.NewPeerGroupFromConfigStruct(&pg), + }); err != nil { + log.Warn(err) + } + } + for _, pg := range deletedPg { + log.Infof("PeerGroup %s is deleted", pg.Config.PeerGroupName) + if _, err := apiServer.DeletePeerGroup(context.Background(), &api.DeletePeerGroupRequest{ + PeerGroup: api.NewPeerGroupFromConfigStruct(&pg), + }); err != nil { + log.Warn(err) + } + } + for _, pg := range updatedPg { + log.Infof("PeerGroup %v is updated", pg.State.PeerGroupName) + if u, err := apiServer.UpdatePeerGroup(context.Background(), &api.UpdatePeerGroupRequest{ + PeerGroup: api.NewPeerGroupFromConfigStruct(&pg), + }); err != nil { + log.Warn(err) + } else { + updatePolicy = updatePolicy || u.NeedsSoftResetIn + } + } + for _, pg := range updatedPg { + log.Infof("PeerGroup %s is updated", pg.Config.PeerGroupName) + if _, err := apiServer.UpdatePeerGroup(context.Background(), &api.UpdatePeerGroupRequest{ + PeerGroup: api.NewPeerGroupFromConfigStruct(&pg), + }); err != nil { + log.Warn(err) + } + } + for _, dn := range newConfig.DynamicNeighbors { + log.Infof("Dynamic Neighbor %s is added to PeerGroup %s", dn.Config.Prefix, dn.Config.PeerGroup) + if _, err := apiServer.AddDynamicNeighbor(context.Background(), &api.AddDynamicNeighborRequest{ + DynamicNeighbor: &api.DynamicNeighbor{ + Prefix: dn.Config.Prefix, + PeerGroup: dn.Config.PeerGroup, + }, + }); err != nil { + log.Warn(err) + } + } + for _, p := range added { + log.Infof("Peer %v is added", p.State.NeighborAddress) + if _, err := apiServer.AddNeighbor(context.Background(), &api.AddNeighborRequest{ + Peer: api.NewPeerFromConfigStruct(&p), + }); err != nil { + log.Warn(err) + } + } + for _, p := range deleted { + log.Infof("Peer %v is deleted", p.State.NeighborAddress) + if _, err := apiServer.DeleteNeighbor(context.Background(), &api.DeleteNeighborRequest{ + Peer: api.NewPeerFromConfigStruct(&p), + }); err != nil { + log.Warn(err) + } + } + for _, p := range updated { + log.Infof("Peer %v is updated", p.State.NeighborAddress) + if u, err := apiServer.UpdateNeighbor(context.Background(), &api.UpdateNeighborRequest{ + Peer: api.NewPeerFromConfigStruct(&p), + }); err != nil { + log.Warn(err) + } else { + updatePolicy = updatePolicy || u.NeedsSoftResetIn + } } - updatePolicy = updatePolicy || u - } - if updatePolicy { - bgpServer.SoftResetIn("", bgp.RouteFamily(0)) + if updatePolicy { + if _, err := apiServer.SoftResetNeighbor(context.Background(), &api.SoftResetNeighborRequest{ + Address: "", + Direction: api.SoftResetNeighborRequest_IN, + }); err != nil { + log.Warn(err) + } + } } - case <-sigCh: - bgpServer.Shutdown() } } + + loop() } diff -Nru gobgp-1.32/packet/bgp/bgp.go gobgp-1.33/packet/bgp/bgp.go --- gobgp-1.32/packet/bgp/bgp.go 2018-06-01 11:32:28.000000000 +0000 +++ gobgp-1.33/packet/bgp/bgp.go 2018-07-01 12:06:57.000000000 +0000 @@ -263,8 +263,8 @@ BGP_CAP_FOUR_OCTET_AS_NUMBER BGPCapabilityCode = 65 BGP_CAP_ADD_PATH BGPCapabilityCode = 69 BGP_CAP_ENHANCED_ROUTE_REFRESH BGPCapabilityCode = 70 + BGP_CAP_LONG_LIVED_GRACEFUL_RESTART BGPCapabilityCode = 71 BGP_CAP_ROUTE_REFRESH_CISCO BGPCapabilityCode = 128 - BGP_CAP_LONG_LIVED_GRACEFUL_RESTART BGPCapabilityCode = 129 ) var CapNameMap = map[BGPCapabilityCode]string{ @@ -287,6 +287,51 @@ return fmt.Sprintf("UnknownCapability(%d)", c) } +var ( + // Used parsing RouteDistinguisher + _regexpRouteDistinguisher = regexp.MustCompile(`^((\d+)\.(\d+)\.(\d+)\.(\d+)|((\d+)\.)?(\d+)|([\w]+:[\w:]*:[\w]+)):(\d+)$`) + + // Used for operator and value for the FlowSpec numeric type + // Example: + // re.FindStringSubmatch("&==80") + // >>> ["&==80" "&" "==" "80"] + _regexpFlowSpecNumericType = regexp.MustCompile(`(&?)(==|=|>|>=|<|<=|!|!=|=!)?(\d+|-\d|true|false)`) + + // - "=!" is used in the old style format of "tcp-flags" and "fragment". + // - The value field should be one of the followings: + // * Decimal value (e.g., 80) + // * Combination of the small letters, decimals, "-" and "+" + // (e.g., tcp, ipv4, is-fragment+first-fragment) + // * Capital letters (e.g., SA) + _regexpFlowSpecOperator = regexp.MustCompile(`&|=|>|<|!|[\w\-+]+`) + _regexpFlowSpecOperatorValue = regexp.MustCompile(`[\w\-+]+`) + + // Note: "(-*)" and "(.*)" catch the invalid flags + // Example: In this case, "Z" is unsupported flag type. + // re.FindStringSubmatch("&==-SZU") + // >>> ["&==-SZU" "&" "==" "-" "S" "ZU"] + _regexpFlowSpecTCPFlag = regexp.MustCompile("(&?)(==|=|!|!=|=!)?(-*)([FSRPAUCE]+)(.*)") + + // Note: "(.*)" catches the invalid flags + // re.FindStringSubmatch("&!=+first-fragment+last-fragment+invalid-fragment") + // >>> ["&!=+first-fragment+last-fragment+invalid-fragment" "&" "!=" "+first-fragment+last-fragment" "+last-fragment" "+" "last" "+invalid-fragment"] + _regexpFlowSpecFragment = regexp.MustCompile(`(&?)(==|=|!|!=|=!)?(((\+)?(dont|is|first|last|not-a)-fragment)+)(.*)`) + + // re.FindStringSubmatch("192.168.0.0/24") + // >>> ["192.168.0.0/24" "192.168.0.0" "/24" "24"] + // re.FindStringSubmatch("192.168.0.1") + // >>> ["192.168.0.1" "192.168.0.1" "" ""] + _regexpFindIPv4Prefix = regexp.MustCompile(`^([\d.]+)(/(\d{1,2}))?`) + + // re.FindStringSubmatch("2001:dB8::/64") + // >>> ["2001:dB8::/64" "2001:dB8::" "/64" "64" "" ""] + // re.FindStringSubmatch("2001:dB8::/64/8") + // >>> ["2001:dB8::/64/8" "2001:dB8::" "/64" "64" "/8" "8"] + // re.FindStringSubmatch("2001:dB8::1") + // >>> ["2001:dB8::1" "2001:dB8::1" "" "" "" ""] + _regexpFindIPv6Prefix = regexp.MustCompile(`^([a-fA-F\d:.]+)(/(\d{1,3}))?(/(\d{1,3}))?`) +) + type ParameterCapabilityInterface interface { DecodeFromBytes([]byte) error Serialize() ([]byte, error) @@ -388,6 +433,14 @@ DefaultParameterCapability } +func NewCapCarryingLabelInfo() *CapCarryingLabelInfo { + return &CapCarryingLabelInfo{ + DefaultParameterCapability{ + CapCode: BGP_CAP_CARRYING_LABEL_INFO, + }, + } +} + type CapExtendedNexthopTuple struct { NLRIAFI uint16 NLRISAFI uint16 @@ -836,6 +889,15 @@ DefaultParameterCapability } +func NewCapUnknown(code BGPCapabilityCode, value []byte) *CapUnknown { + return &CapUnknown{ + DefaultParameterCapability{ + CapCode: code, + CapValue: value, + }, + } +} + func DecodeCapability(data []byte) (ParameterCapabilityInterface, error) { if len(data) < 2 { return nil, NewMessageError(BGP_ERROR_OPEN_MESSAGE_ERROR, BGP_ERROR_SUB_UNSUPPORTED_CAPABILITY, nil, "Not all ParameterCapability bytes available") @@ -1430,8 +1492,7 @@ } func parseRdAndRt(input string) ([]string, error) { - exp := regexp.MustCompile("^((\\d+)\\.(\\d+)\\.(\\d+)\\.(\\d+)|((\\d+)\\.)?(\\d+)|([\\w]+:[\\w:]*:[\\w]+)):(\\d+)$") - elems := exp.FindStringSubmatch(input) + elems := _regexpRouteDistinguisher.FindStringSubmatch(input) if len(elems) != 11 { return nil, fmt.Errorf("failed to parse") } @@ -1511,7 +1572,8 @@ break } } - if foundBottom == false { + + if !foundBottom { l.Labels = []uint32{} return nil } @@ -1788,13 +1850,13 @@ l.Length = uint8(data[0]) data = data[1:] l.Labels.DecodeFromBytes(data) + if int(l.Length)-8*(l.Labels.Len()) < 0 { l.Labels.Labels = []uint32{} } restbits := int(l.Length) - 8*(l.Labels.Len()) data = data[l.Labels.Len():] - l.decodePrefix(data, uint8(restbits), l.addrlen) - return nil + return l.decodePrefix(data, uint8(restbits), l.addrlen) } func (l *LabeledIPAddrPrefix) Serialize(options ...*MarshallingOption) ([]byte, error) { @@ -1894,7 +1956,7 @@ return NewMessageError(uint8(BGP_ERROR_UPDATE_MESSAGE_ERROR), uint8(BGP_ERROR_SUB_MALFORMED_ATTRIBUTE_LIST), nil, "prefix misses length field") } n.Length = data[0] - data = data[1:] + data = data[1 : n.Length/8+1] if len(data) == 0 { return nil } else if len(data) != 12 { @@ -1923,7 +1985,7 @@ } offset := len(buf) buf = append(buf, make([]byte, 5)...) - buf[offset] = 12 * 8 + buf[offset] = 96 binary.BigEndian.PutUint32(buf[offset+1:], n.AS) ebuf, err := n.RouteTarget.Serialize() if err != nil { @@ -2100,7 +2162,7 @@ } invalidEsiValuesError := fmt.Errorf("invalid esi values for type %s: %s", esi.Type.String(), args[1:]) - esi.Value = make([]byte, 9, 9) + esi.Value = make([]byte, 9) switch esi.Type { case ESI_LACP: fallthrough @@ -2135,7 +2197,7 @@ if err != nil { return esi, invalidEsiValuesError } - iBuf := make([]byte, 4, 4) + iBuf := make([]byte, 4) binary.BigEndian.PutUint32(iBuf, uint32(i)) copy(esi.Value[6:9], iBuf[1:4]) case ESI_ROUTERID: @@ -2217,7 +2279,7 @@ if label > 0xffffff { return nil, NewMessageError(BGP_ERROR_UPDATE_MESSAGE_ERROR, BGP_ERROR_SUB_MALFORMED_ATTRIBUTE_LIST, nil, fmt.Sprintf("Out of range Label: %d", label)) } - buf := make([]byte, 3, 3) + buf := make([]byte, 3) buf[0] = byte((label >> 16) & 0xff) buf[1] = byte((label >> 8) & 0xff) buf[2] = byte(label & 0xff) @@ -3142,22 +3204,12 @@ // fmt.Printf("%q", normalizeFlowSpecOpValues(args)) // >>> ["<=80" "tcp" "!=udp" "=!SA" "&=U" "!F" "=is-fragment+last-fragment"] func normalizeFlowSpecOpValues(args []string) []string { - // Note: - // - "=!" is used in the old style format of "tcp-flags" and "fragment". - // - The value field should be one of the followings: - // * Decimal value (e.g., 80) - // * Combination of the small letters, decimals, "-" and "+" - // (e.g., tcp, ipv4, is-fragment+first-fragment) - // * Capital letters (e.g., SA) - re := regexp.MustCompile("&|=|>|<|!|[\\w\\-+]+") - reValue := regexp.MustCompile("[\\w\\-+]+") - // Extracts keywords from the given args. sub := "" subs := make([]string, 0) - for _, s := range re.FindAllString(strings.Join(args, " "), -1) { + for _, s := range _regexpFlowSpecOperator.FindAllString(strings.Join(args, " "), -1) { sub += s - if reValue.MatchString(s) { + if _regexpFlowSpecOperatorValue.MatchString(s) { subs = append(subs, sub) sub = "" } @@ -3195,12 +3247,8 @@ func parseFlowSpecNumericOpValues(typ BGPFlowSpecType, args []string, validationFunc func(uint64) error) (FlowSpecComponentInterface, error) { argsLen := len(args) items := make([]*FlowSpecComponentItem, 0, argsLen) - re := regexp.MustCompile("(&?)(==|=|>|>=|<|<=|!|!=|=!)?(\\d+|-\\d|true|false)") for idx, arg := range args { - // Example: - // re.FindStringSubmatch("&==80") - // >>> ["&==80" "&" "==" "80"] - m := re.FindStringSubmatch(arg) + m := _regexpFlowSpecNumericType.FindStringSubmatch(arg) if len(m) < 4 { return nil, fmt.Errorf("invalid argument for %s: %s in %q", typ.String(), arg, args) } @@ -3298,12 +3346,7 @@ return nil, fmt.Errorf("cannot specify offset for ipv4 prefix") } invalidIPv4PrefixError := fmt.Errorf("invalid ipv4 prefix: %s", args[0]) - re := regexp.MustCompile("^([\\d.]+)(/(\\d{1,2}))?") - // re.FindStringSubmatch("192.168.0.0/24") - // >>> ["192.168.0.0/24" "192.168.0.0" "/24" "24"] - // re.FindStringSubmatch("192.168.0.1") - // >>> ["192.168.0.1" "192.168.0.1" "" ""] - m := re.FindStringSubmatch(args[0]) + m := _regexpFindIPv4Prefix.FindStringSubmatch(args[0]) if len(m) < 4 { return nil, invalidIPv4PrefixError } @@ -3331,14 +3374,7 @@ return nil, fmt.Errorf("invalid arguments for ipv6 prefix: %q", args) } invalidIPv6PrefixError := fmt.Errorf("invalid ipv6 prefix: %s", args[0]) - re := regexp.MustCompile("^([a-fA-F\\d:.]+)(/(\\d{1,3}))?(/(\\d{1,3}))?") - // re.FindStringSubmatch("2001:dB8::/64") - // >>> ["2001:dB8::/64" "2001:dB8::" "/64" "64" "" ""] - // re.FindStringSubmatch("2001:dB8::/64/8") - // >>> ["2001:dB8::/64/8" "2001:dB8::" "/64" "64" "/8" "8"] - // re.FindStringSubmatch("2001:dB8::1") - // >>> ["2001:dB8::1" "2001:dB8::1" "" "" "" ""] - m := re.FindStringSubmatch(args[0]) + m := _regexpFindIPv6Prefix.FindStringSubmatch(args[0]) if len(m) < 4 { return nil, invalidIPv6PrefixError } @@ -3419,13 +3455,9 @@ argsLen := len(args) items := make([]*FlowSpecComponentItem, 0, argsLen) - // Note: "(-*)" and "(.*)" catch the invalid flags - re := regexp.MustCompile("(&?)(==|=|!|!=|=!)?(-*)([FSRPAUCE]+)(.*)") + for _, arg := range args { - // Example: In this case, "Z" is unsupported flag type. - // re.FindStringSubmatch("&==-SZU") - // >>> ["&==-SZU" "&" "==" "-" "S" "ZU"] - m := re.FindStringSubmatch(arg) + m := _regexpFlowSpecTCPFlag.FindStringSubmatch(arg) if len(m) < 6 { return nil, fmt.Errorf("invalid argument for %s: %s in %q", typ.String(), arg, args) } else if mLast := m[len(m)-1]; mLast != "" || m[3] != "" { @@ -3475,13 +3507,9 @@ argsLen := len(args) items := make([]*FlowSpecComponentItem, 0, argsLen) - // Note: "(.*)" catches the invalid flags - re := regexp.MustCompile("(&?)(==|=|!|!=|=!)?(((\\+)?(dont|is|first|last|not-a)-fragment)+)(.*)") + for _, arg := range args { - // Example: - // re.FindStringSubmatch("&!=+first-fragment+last-fragment+invalid-fragment") - // >>> ["&!=+first-fragment+last-fragment+invalid-fragment" "&" "!=" "+first-fragment+last-fragment" "+last-fragment" "+" "last" "+invalid-fragment"] - m := re.FindStringSubmatch(arg) + m := _regexpFlowSpecFragment.FindStringSubmatch(arg) if len(m) < 4 { return nil, fmt.Errorf("invalid argument for %s: %s in %q", typ.String(), arg, args) } else if mLast := m[len(m)-1]; mLast != "" { @@ -3924,13 +3952,10 @@ } func (v *FlowSpecComponentItem) Serialize() ([]byte, error) { - if v.Value < 0 { - return nil, fmt.Errorf("invalid value size(too small): %d", v.Value) - } - if v.Op < 0 || v.Op > math.MaxUint8 { + if v.Op > math.MaxUint8 { return nil, fmt.Errorf("invalid op size: %d", v.Op) - } + order := uint32(math.Log2(float64(v.Len()))) buf := make([]byte, 1+(1< 0 { var tuple AsPathParamInterface - if isAs4 == true { + if isAs4 { tuple = &As4PathParam{} } else { tuple = &AsPathParam{} @@ -5471,9 +5496,6 @@ return err } p.Value = append(p.Value, tuple) - if tuple.Len() > len(value) { - - } value = value[tuple.Len():] } return nil @@ -5850,19 +5872,19 @@ const ( COMMUNITY_INTERNET WellKnownCommunity = 0x00000000 - COMMUNITY_PLANNED_SHUT = 0xffff0000 - COMMUNITY_ACCEPT_OWN = 0xffff0001 - COMMUNITY_ROUTE_FILTER_TRANSLATED_v4 = 0xffff0002 - COMMUNITY_ROUTE_FILTER_v4 = 0xffff0003 - COMMUNITY_ROUTE_FILTER_TRANSLATED_v6 = 0xffff0004 - COMMUNITY_ROUTE_FILTER_v6 = 0xffff0005 - COMMUNITY_LLGR_STALE = 0xffff0006 - COMMUNITY_NO_LLGR = 0xffff0007 - COMMUNITY_BLACKHOLE = 0xffff029a - COMMUNITY_NO_EXPORT = 0xffffff01 - COMMUNITY_NO_ADVERTISE = 0xffffff02 - COMMUNITY_NO_EXPORT_SUBCONFED = 0xffffff03 - COMMUNITY_NO_PEER = 0xffffff04 + COMMUNITY_PLANNED_SHUT WellKnownCommunity = 0xffff0000 + COMMUNITY_ACCEPT_OWN WellKnownCommunity = 0xffff0001 + COMMUNITY_ROUTE_FILTER_TRANSLATED_v4 WellKnownCommunity = 0xffff0002 + COMMUNITY_ROUTE_FILTER_v4 WellKnownCommunity = 0xffff0003 + COMMUNITY_ROUTE_FILTER_TRANSLATED_v6 WellKnownCommunity = 0xffff0004 + COMMUNITY_ROUTE_FILTER_v6 WellKnownCommunity = 0xffff0005 + COMMUNITY_LLGR_STALE WellKnownCommunity = 0xffff0006 + COMMUNITY_NO_LLGR WellKnownCommunity = 0xffff0007 + COMMUNITY_BLACKHOLE WellKnownCommunity = 0xffff029a + COMMUNITY_NO_EXPORT WellKnownCommunity = 0xffffff01 + COMMUNITY_NO_ADVERTISE WellKnownCommunity = 0xffffff02 + COMMUNITY_NO_EXPORT_SUBCONFED WellKnownCommunity = 0xffffff03 + COMMUNITY_NO_PEER WellKnownCommunity = 0xffffff04 ) var WellKnownCommunityNameMap = map[WellKnownCommunity]string{ @@ -5969,7 +5991,7 @@ } func (p *PathAttributeOriginatorId) Serialize(options ...*MarshallingOption) ([]byte, error) { - buf := make([]byte, 4, 4) + buf := make([]byte, 4) copy(buf, p.Value) return p.PathAttribute.Serialize(buf, options...) } @@ -6645,6 +6667,19 @@ return ParseExtendedCommunity(EC_SUBTYPE_ROUTE_TARGET, rt) } +func SerializeExtendedCommunities(comms []ExtendedCommunityInterface) ([][]byte, error) { + var bufs [][]byte + var err error + for _, c := range comms { + buf, err := c.Serialize() + if err != nil { + return nil, err + } + bufs = append(bufs, buf) + } + return bufs, err +} + type ValidationState uint8 const ( @@ -6670,7 +6705,7 @@ } func (e *ValidationExtended) Serialize() ([]byte, error) { - buf := make([]byte, 8, 8) + buf := make([]byte, 8) typ, subType := e.GetTypes() buf[0] = byte(typ) buf[1] = byte(subType) @@ -6710,7 +6745,7 @@ } func (e *ColorExtended) Serialize() ([]byte, error) { - buf := make([]byte, 8, 8) + buf := make([]byte, 8) typ, subType := e.GetTypes() buf[0] = byte(typ) buf[1] = byte(subType) @@ -6750,7 +6785,7 @@ } func (e *EncapExtended) Serialize() ([]byte, error) { - buf := make([]byte, 8, 8) + buf := make([]byte, 8) typ, subType := e.GetTypes() buf[0] = byte(typ) buf[1] = byte(subType) @@ -6810,7 +6845,7 @@ } func (e *DefaultGatewayExtended) Serialize() ([]byte, error) { - buf := make([]byte, 8, 8) + buf := make([]byte, 8) typ, subType := e.GetTypes() buf[0] = byte(typ) buf[1] = byte(subType) @@ -6849,7 +6884,7 @@ if len(e.Value) != 7 { return nil, fmt.Errorf("invalid value length for opaque extended community: %d", len(e.Value)) } - buf := make([]byte, 8, 8) + buf := make([]byte, 8) if e.IsTransitive { buf[0] = byte(EC_TYPE_TRANSITIVE_OPAQUE) } else { @@ -6860,7 +6895,7 @@ } func (e *OpaqueExtended) String() string { - buf := make([]byte, 8, 8) + buf := make([]byte, 8) copy(buf[1:], e.Value) return fmt.Sprintf("%d", binary.BigEndian.Uint64(buf)) } @@ -6891,7 +6926,7 @@ } func NewOpaqueExtended(isTransitive bool, value []byte) *OpaqueExtended { - v := make([]byte, 7, 7) + v := make([]byte, 7) copy(v, value) return &OpaqueExtended{ IsTransitive: isTransitive, @@ -7512,7 +7547,7 @@ if len(e.Value) != 7 { return nil, fmt.Errorf("invalid value length for unknown extended community: %d", len(e.Value)) } - buf := make([]byte, 8, 8) + buf := make([]byte, 8) buf[0] = uint8(e.Type) copy(buf[1:], e.Value) return buf, nil @@ -7547,7 +7582,7 @@ } func NewUnknownExtended(typ ExtendedCommunityAttrType, value []byte) *UnknownExtended { - v := make([]byte, 7, 7) + v := make([]byte, 7) copy(v, value) return &UnknownExtended{ Type: typ, @@ -7691,9 +7726,11 @@ if err != nil { return err } - if isAs4 == false { + + if !isAs4 { return NewMessageError(eCode, eSubCode, nil, "AS4 PATH param is malformed") } + for len(value) > 0 { tuple := &As4PathParam{} tuple.DecodeFromBytes(value) @@ -8109,7 +8146,7 @@ } func (p *TunnelEncapTLV) String() string { - tlvList := make([]string, len(p.Value), len(p.Value)) + tlvList := make([]string, len(p.Value)) for i, v := range p.Value { tlvList[i] = v.String() } @@ -8168,7 +8205,7 @@ } func (p *PathAttributeTunnelEncap) String() string { - tlvList := make([]string, len(p.Value), len(p.Value)) + tlvList := make([]string, len(p.Value)) for i, v := range p.Value { tlvList[i] = v.String() } @@ -9221,10 +9258,12 @@ if uint16(len(data)) < BGP_HEADER_LENGTH { return NewMessageError(BGP_ERROR_MESSAGE_HEADER_ERROR, BGP_ERROR_SUB_BAD_MESSAGE_LENGTH, nil, "not all BGP message header") } + msg.Len = binary.BigEndian.Uint16(data[16:18]) if int(msg.Len) < BGP_HEADER_LENGTH { return NewMessageError(BGP_ERROR_MESSAGE_HEADER_ERROR, BGP_ERROR_SUB_BAD_MESSAGE_LENGTH, nil, "unknown message type") } + msg.Type = data[18] return nil } diff -Nru gobgp-1.32/packet/bgp/bgp_test.go gobgp-1.33/packet/bgp/bgp_test.go --- gobgp-1.32/packet/bgp/bgp_test.go 2018-06-01 11:32:28.000000000 +0000 +++ gobgp-1.33/packet/bgp/bgp_test.go 2018-07-01 12:06:57.000000000 +0000 @@ -24,6 +24,7 @@ "testing" "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" ) func keepalive() *BGPMessage { @@ -38,25 +39,32 @@ return NewBGPRouteRefreshMessage(1, 2, 10) } +var result []string + +func BenchmarkNormalizeFlowSpecOpValues(b *testing.B) { + var r []string + for n := 0; n < b.N; n++ { + r = normalizeFlowSpecOpValues([]string{"&<=80"}) + } + result = r +} + func Test_Message(t *testing.T) { l := []*BGPMessage{keepalive(), notification(), refresh(), NewTestBGPOpenMessage(), NewTestBGPUpdateMessage()} + for _, m1 := range l { - buf1, _ := m1.Serialize() + buf1, err := m1.Serialize() + assert.NoError(t, err) + t.Log("LEN =", len(buf1)) m2, err := ParseBGPMessage(buf1) - if err != nil { - t.Error(err) - } + assert.NoError(t, err) + // FIXME: shouldn't but workaround for some structs. - buf2, _ := m2.Serialize() + _, err = m2.Serialize() + assert.NoError(t, err) - if reflect.DeepEqual(m1, m2) == true { - t.Log("OK") - } else { - t.Error("Something wrong") - t.Error(len(buf1), m1, buf1) - t.Error(len(buf2), m2, buf2) - } + assert.True(t, reflect.DeepEqual(m1, m2)) } } @@ -81,7 +89,7 @@ // TwoOctetAsSpecificExtended buf := make([]byte, 13) - buf[0] = 12 + buf[0] = 96 // in bit length binary.BigEndian.PutUint32(buf[1:5], 65546) buf[5] = byte(EC_TYPE_TRANSITIVE_TWO_OCTET_AS_SPECIFIC) // typehigh binary.BigEndian.PutUint16(buf[7:9], 65000) @@ -98,6 +106,7 @@ // IPv4AddressSpecificExtended buf = make([]byte, 13) + buf[0] = 96 // in bit length binary.BigEndian.PutUint32(buf[1:5], 65546) buf[5] = byte(EC_TYPE_TRANSITIVE_IP4_SPECIFIC) // typehigh ip := net.ParseIP("10.0.0.1").To4() @@ -115,6 +124,7 @@ // FourOctetAsSpecificExtended buf = make([]byte, 13) + buf[0] = 96 // in bit length binary.BigEndian.PutUint32(buf[1:5], 65546) buf[5] = byte(EC_TYPE_TRANSITIVE_FOUR_OCTET_AS_SPECIFIC) // typehigh buf[6] = byte(EC_SUBTYPE_ROUTE_TARGET) // subtype @@ -132,6 +142,7 @@ // OpaqueExtended buf = make([]byte, 13) + buf[0] = 96 // in bit length binary.BigEndian.PutUint32(buf[1:5], 65546) buf[5] = byte(EC_TYPE_TRANSITIVE_OPAQUE) // typehigh binary.BigEndian.PutUint32(buf[9:], 1000000) @@ -147,6 +158,7 @@ // Unknown buf = make([]byte, 13) + buf[0] = 96 // in bit length binary.BigEndian.PutUint32(buf[1:5], 65546) buf[5] = 0x04 // typehigh binary.BigEndian.PutUint32(buf[9:], 1000000) @@ -381,26 +393,24 @@ lastFragment := uint64(0x08) item5 := NewFlowSpecComponentItem(BITMASK_FLAG_OP_MATCH, isFragment) item6 := NewFlowSpecComponentItem(BITMASK_FLAG_OP_AND, lastFragment) + cmp = append(cmp, NewFlowSpecComponent(FLOW_SPEC_TYPE_FRAGMENT, []*FlowSpecComponentItem{item5, item6})) item7 := NewFlowSpecComponentItem(0, TCP_FLAG_ACK) item8 := NewFlowSpecComponentItem(BITMASK_FLAG_OP_AND|BITMASK_FLAG_OP_NOT, TCP_FLAG_URGENT) + cmp = append(cmp, NewFlowSpecComponent(FLOW_SPEC_TYPE_TCP_FLAG, []*FlowSpecComponentItem{item7, item8})) n1 := NewFlowSpecIPv4Unicast(cmp) + buf1, err := n1.Serialize() assert.Nil(err) + n2, err := NewPrefixFromRouteFamily(RouteFamilyToAfiSafi(RF_FS_IPv4_UC)) assert.Nil(err) + err = n2.DecodeFromBytes(buf1) assert.Nil(err) - buf2, _ := n2.Serialize() - if reflect.DeepEqual(n1, n2) == true { - t.Log("OK") - } else { - t.Error("Something wrong") - t.Error(len(buf1), n1, buf1) - t.Error(len(buf2), n2, buf2) - t.Log(bytes.Equal(buf1, buf2)) - } + // should be equal + assert.Equal(n1, n2) } func Test_FlowSpecExtended(t *testing.T) { @@ -414,42 +424,36 @@ exts = append(exts, NewTrafficRemarkExtended(10)) m1 := NewPathAttributeExtendedCommunities(exts) buf1, err := m1.Serialize() - assert.Nil(err) + require.NoError(t, err) + m2 := NewPathAttributeExtendedCommunities(nil) err = m2.DecodeFromBytes(buf1) - assert.Nil(err) - buf2, _ := m2.Serialize() - if reflect.DeepEqual(m1, m2) == true { - t.Log("OK") - } else { - t.Error("Something wrong") - t.Error(len(buf1), m1, buf1) - t.Error(len(buf2), m2, buf2) - } + require.NoError(t, err) + + _, err = m2.Serialize() + require.NoError(t, err) + + assert.Equal(m1, m2) } func Test_IP6FlowSpecExtended(t *testing.T) { - assert := assert.New(t) exts := make([]ExtendedCommunityInterface, 0) exts = append(exts, NewRedirectIPv6AddressSpecificExtended("2001:db8::68", 1000)) m1 := NewPathAttributeIP6ExtendedCommunities(exts) buf1, err := m1.Serialize() - assert.Nil(err) + require.NoError(t, err) + m2 := NewPathAttributeIP6ExtendedCommunities(nil) err = m2.DecodeFromBytes(buf1) - assert.Nil(err) - buf2, _ := m2.Serialize() - if reflect.DeepEqual(m1, m2) == true { - t.Log("OK") - } else { - t.Error("Something wrong") - t.Error(len(buf1), m1, buf1) - t.Error(len(buf2), m2, buf2) - } + require.NoError(t, err) + + _, err = m2.Serialize() + require.NoError(t, err) + + assert.Equal(t, m1, m2) } func Test_FlowSpecNlriv6(t *testing.T) { - assert := assert.New(t) cmp := make([]FlowSpecComponentInterface, 0) cmp = append(cmp, NewFlowSpecDestinationPrefix6(NewIPv6AddrPrefix(64, "2001::"), 12)) cmp = append(cmp, NewFlowSpecSourcePrefix6(NewIPv6AddrPrefix(64, "2001::"), 12)) @@ -474,20 +478,18 @@ cmp = append(cmp, NewFlowSpecComponent(FLOW_SPEC_TYPE_TCP_FLAG, []*FlowSpecComponentItem{item6, item7})) n1 := NewFlowSpecIPv6Unicast(cmp) buf1, err := n1.Serialize() - assert.Nil(err) + require.NoError(t, err) + n2, err := NewPrefixFromRouteFamily(RouteFamilyToAfiSafi(RF_FS_IPv6_UC)) - assert.Nil(err) + require.NoError(t, err) + err = n2.DecodeFromBytes(buf1) - assert.Nil(err) - buf2, _ := n2.Serialize() - if reflect.DeepEqual(n1, n2) == true { - t.Log("OK") - } else { - t.Error("Something wrong") - t.Error(len(buf1), n1, buf1) - t.Error(len(buf2), n2, buf2) - t.Log(bytes.Equal(buf1, buf2)) - } + require.NoError(t, err) + + _, err = n2.Serialize() + require.NoError(t, err) + + assert.Equal(t, n1, n2) } func Test_Aigp(t *testing.T) { @@ -495,19 +497,13 @@ m := NewAigpTLVIgpMetric(1000) a1 := NewPathAttributeAigp([]AigpTLVInterface{m}) buf1, err := a1.Serialize() - assert.Nil(err) + require.NoError(t, err) + a2 := NewPathAttributeAigp(nil) err = a2.DecodeFromBytes(buf1) - assert.Nil(err) - buf2, _ := a2.Serialize() - if reflect.DeepEqual(a1, a2) == true { - t.Log("OK") - } else { - t.Error("Something wrong") - t.Error(len(buf1), a1, buf1) - t.Error(len(buf2), a2, buf2) - t.Log(bytes.Equal(buf1, buf2)) - } + require.NoError(t, err) + + assert.Equal(a1, a2) } func Test_FlowSpecNlriL2(t *testing.T) { @@ -526,15 +522,8 @@ assert.Nil(err) err = n2.DecodeFromBytes(buf1) assert.Nil(err) - buf2, _ := n2.Serialize() - if reflect.DeepEqual(n1, n2) == true { - t.Log("OK") - } else { - t.Error("Something wrong") - t.Error(len(buf1), n1, buf1) - t.Error(len(buf2), n2, buf2) - t.Log(bytes.Equal(buf1, buf2)) - } + + assert.Equal(n1, n2) } func Test_NotificationErrorCode(t *testing.T) { @@ -558,16 +547,9 @@ n2, err := NewPrefixFromRouteFamily(RouteFamilyToAfiSafi(RF_FS_IPv4_VPN)) assert.Nil(err) err = n2.DecodeFromBytes(buf1) - assert.Nil(err) - buf2, _ := n2.Serialize() - if reflect.DeepEqual(n1, n2) == true { - t.Log("OK") - } else { - t.Error("Something wrong") - t.Error(len(buf1), n1, buf1) - t.Error(len(buf2), n2, buf2) - t.Log(bytes.Equal(buf1, buf2)) - } + require.NoError(t, err) + + assert.Equal(n1, n2) } func Test_EVPNIPPrefixRoute(t *testing.T) { @@ -592,17 +574,8 @@ assert.Nil(err) err = n2.DecodeFromBytes(buf1) assert.Nil(err) - buf2, _ := n2.Serialize() - t.Log(n1.RouteTypeData.(*EVPNIPPrefixRoute).ESI.Value, n2.(*EVPNNLRI).RouteTypeData.(*EVPNIPPrefixRoute).ESI.Value) - t.Log(reflect.DeepEqual(n1.RouteTypeData.(*EVPNIPPrefixRoute).ESI.Value, n2.(*EVPNNLRI).RouteTypeData.(*EVPNIPPrefixRoute).ESI.Value)) - if reflect.DeepEqual(n1, n2) { - t.Log("OK") - } else { - t.Error("Something wrong") - t.Error(len(buf1), n1, buf1) - t.Error(len(buf2), n2, buf2) - t.Log(bytes.Equal(buf1, buf2)) - } + + assert.Equal(n1, n2) } func Test_CapExtendedNexthop(t *testing.T) { @@ -613,15 +586,8 @@ assert.Nil(err) n2, err := DecodeCapability(buf1) assert.Nil(err) - buf2, _ := n2.Serialize() - if reflect.DeepEqual(n1, n2) { - t.Log("OK") - } else { - t.Error("Something wrong") - t.Error(len(buf1), n1, buf1) - t.Error(len(buf2), n2, buf2) - t.Log(bytes.Equal(buf1, buf2)) - } + + assert.Equal(n1, n2) } func Test_AddPath(t *testing.T) { @@ -801,15 +767,8 @@ assert.Nil(err) err = n2.DecodeFromBytes(buf1) assert.Nil(err) - buf2, _ := n2.Serialize() - if reflect.DeepEqual(n1, n2) { - t.Log("OK") - } else { - t.Error("Something wrong") - t.Error(len(buf1), n1, buf1) - t.Error(len(buf2), n2, buf2) - t.Log(bytes.Equal(buf1, buf2)) - } + + assert.Equal(n1, n2) label := NewMPLSLabelStack(2) @@ -820,16 +779,8 @@ assert.Nil(err) err = n4.DecodeFromBytes(buf1) assert.Nil(err) - buf2, _ = n3.Serialize() - t.Log(n3, n4) - if reflect.DeepEqual(n3, n4) { - t.Log("OK") - } else { - t.Error("Something wrong") - t.Error(len(buf1), n3, buf1) - t.Error(len(buf2), n4, buf2) - t.Log(bytes.Equal(buf1, buf2)) - } + + assert.Equal(n3, n4) } func Test_MpReachNLRIWithIPv6PrefixWithIPv4Peering(t *testing.T) { @@ -1119,7 +1070,7 @@ // "single-homed" esiZero := EthernetSegmentIdentifier{} - args := make([]string, 0, 0) + args := make([]string, 0) esi, err := ParseEthernetSegmentIdentifier(args) assert.Nil(err) assert.Equal(esiZero, esi) @@ -1215,3 +1166,29 @@ ParseBGPMessage([]byte(f)) } } + +func TestNormalizeFlowSpecOpValues(t *testing.T) { + tests := []struct { + msg string + args []string + want []string + }{ + { + msg: "valid match", + args: []string{" & <=80", " tcp != udp ", " =! SA & =U! F", " = is-fragment+last-fragment"}, + want: []string{"<=80", "tcp", "!=udp", "=!SA", "&=U", "!F", "=is-fragment+last-fragment"}, + }, + { + msg: "RFC5575 trims & prefix", + args: []string{"&<=80"}, + want: []string{"<=80"}, + }, + } + + for _, tt := range tests { + t.Run(tt.msg, func(t *testing.T) { + got := normalizeFlowSpecOpValues(tt.args) + assert.Equal(t, tt.want, got) + }) + } +} diff -Nru gobgp-1.32/packet/bgp/validate.go gobgp-1.33/packet/bgp/validate.go --- gobgp-1.32/packet/bgp/validate.go 2018-06-01 11:32:28.000000000 +0000 +++ gobgp-1.33/packet/bgp/validate.go 2018-07-01 12:06:57.000000000 +0000 @@ -274,7 +274,7 @@ return false, NewMessageError(eCode, eSubCode, nil, "AS PATH the number of AS is incorrect") } segLength := int(asNum) - if use4byte == true { + if use4byte { segLength *= 4 } else { segLength *= 2 diff -Nru gobgp-1.32/packet/bgp/validate_test.go gobgp-1.33/packet/bgp/validate_test.go --- gobgp-1.32/packet/bgp/validate_test.go 2018-06-01 11:32:28.000000000 +0000 +++ gobgp-1.33/packet/bgp/validate_test.go 2018-07-01 12:06:57.000000000 +0000 @@ -6,6 +6,7 @@ "testing" "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" ) func bgpupdate() *BGPMessage { @@ -47,6 +48,7 @@ assert.Error(err) res, err = ValidateUpdateMsg(message, map[RouteFamily]BGPAddPathMode{RF_IPv4_UC: BGP_ADD_PATH_BOTH}, false, false) + require.NoError(t, err) assert.Equal(true, res) } @@ -54,11 +56,12 @@ assert := assert.New(t) message := bgpupdateV6().Body.(*BGPUpdate) res, err := ValidateUpdateMsg(message, map[RouteFamily]BGPAddPathMode{RF_IPv6_UC: BGP_ADD_PATH_BOTH}, false, false) - assert.Equal(true, res) assert.NoError(err) + assert.True(res) res, err = ValidateUpdateMsg(message, map[RouteFamily]BGPAddPathMode{RF_IPv4_UC: BGP_ADD_PATH_BOTH}, false, false) - assert.Equal(false, res) + assert.Error(err) + assert.False(res) } func Test_Validate_OK(t *testing.T) { @@ -295,12 +298,12 @@ } func Test_Validate_aspath(t *testing.T) { - assert := assert.New(t) message := bgpupdate().Body.(*BGPUpdate) // VALID AS_PATH res, err := ValidateUpdateMsg(message, map[RouteFamily]BGPAddPathMode{RF_IPv4_UC: BGP_ADD_PATH_BOTH}, true, false) + require.NoError(t, err) assert.Equal(true, res) // CONFED_SET @@ -360,6 +363,7 @@ assert.Nil(e.Data) res, err = ValidateUpdateMsg(message, map[RouteFamily]BGPAddPathMode{RF_IPv4_UC: BGP_ADD_PATH_BOTH}, true, true) + require.NoError(t, err) assert.Equal(true, res) } diff -Nru gobgp-1.32/packet/bmp/bmp_test.go gobgp-1.33/packet/bmp/bmp_test.go --- gobgp-1.32/packet/bmp/bmp_test.go 2018-06-01 11:32:28.000000000 +0000 +++ gobgp-1.33/packet/bmp/bmp_test.go 2018-07-01 12:06:57.000000000 +0000 @@ -16,27 +16,21 @@ package bmp import ( + "testing" + + "github.com/stretchr/testify/require" + "github.com/osrg/gobgp/packet/bgp" + "github.com/stretchr/testify/assert" - "reflect" - "testing" ) func verify(t *testing.T, m1 *BMPMessage) { buf1, _ := m1.Serialize() m2, err := ParseBMPMessage(buf1) - if err != nil { - t.Error(err) - } - buf2, _ := m2.Serialize() - - if reflect.DeepEqual(m1, m2) == true { - t.Log("OK") - } else { - t.Error("Something wrong") - t.Error(len(buf1), m1, buf1) - t.Error(len(buf2), m2, buf2) - } + require.NoError(t, err) + + assert.Equal(t, m1, m2) } func Test_Initiation(t *testing.T) { diff -Nru gobgp-1.32/packet/rtr/rtr_test.go gobgp-1.33/packet/rtr/rtr_test.go --- gobgp-1.32/packet/rtr/rtr_test.go 2018-06-01 11:32:28.000000000 +0000 +++ gobgp-1.33/packet/rtr/rtr_test.go 2018-07-01 12:06:57.000000000 +0000 @@ -19,26 +19,22 @@ "encoding/hex" "math/rand" "net" - "reflect" "testing" "time" + + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" ) func verifyRTRMessage(t *testing.T, m1 RTRMessage) { buf1, _ := m1.Serialize() m2, err := ParseRTR(buf1) - if err != nil { - t.Error(err) - } - buf2, _ := m2.Serialize() + require.NoError(t, err) + + buf2, err := m2.Serialize() + require.NoError(t, err) - if reflect.DeepEqual(buf1, buf2) == true { - t.Log("OK") - } else { - t.Errorf("Something wrong") - t.Error(len(buf1), m1, hex.EncodeToString(buf1)) - t.Error(len(buf2), m2, hex.EncodeToString(buf2)) - } + assert.Equal(t, buf1, buf2, "buf1: %v buf2: %v", hex.EncodeToString(buf1), hex.EncodeToString(buf2)) } func randUint32() uint32 { diff -Nru gobgp-1.32/server/fsm.go gobgp-1.33/server/fsm.go --- gobgp-1.32/server/fsm.go 2018-06-01 11:32:28.000000000 +0000 +++ gobgp-1.33/server/fsm.go 2018-07-01 12:06:57.000000000 +0000 @@ -23,14 +23,14 @@ "strconv" "time" - "github.com/eapache/channels" - log "github.com/sirupsen/logrus" - "gopkg.in/tomb.v2" - "github.com/osrg/gobgp/config" "github.com/osrg/gobgp/packet/bgp" "github.com/osrg/gobgp/packet/bmp" "github.com/osrg/gobgp/table" + + "github.com/eapache/channels" + log "github.com/sirupsen/logrus" + "gopkg.in/tomb.v2" ) type PeerDownReason int @@ -1048,9 +1048,7 @@ if caps, y := capMap[bgp.BGP_CAP_ADD_PATH]; y { items := make([]*bgp.CapAddPathTuple, 0, len(caps)) for _, c := range caps { - for _, i := range c.(*bgp.CapAddPath).Tuples { - items = append(items, i) - } + items = append(items, c.(*bgp.CapAddPath).Tuples...) } capMap[bgp.BGP_CAP_ADD_PATH] = []bgp.ParameterCapabilityInterface{bgp.NewCapAddPath(items)} } diff -Nru gobgp-1.32/server/peer.go gobgp-1.33/server/peer.go --- gobgp-1.32/server/peer.go 2018-06-01 11:32:28.000000000 +0000 +++ gobgp-1.33/server/peer.go 2018-07-01 12:06:57.000000000 +0000 @@ -42,8 +42,8 @@ func NewPeerGroup(c *config.PeerGroup) *PeerGroup { return &PeerGroup{ Conf: c, - members: make(map[string]config.Neighbor, 0), - dynamicNeighbors: make(map[string]*config.DynamicNeighbor, 0), + members: make(map[string]config.Neighbor), + dynamicNeighbors: make(map[string]*config.DynamicNeighbor), } } @@ -293,7 +293,7 @@ for i, p := range paths { doStale := true for _, c := range p.GetCommunities() { - if c == bgp.COMMUNITY_NO_LLGR { + if c == uint32(bgp.COMMUNITY_NO_LLGR) { doStale = false p = p.Clone(true) break @@ -301,7 +301,7 @@ } if doStale { p = p.Clone(false) - p.SetCommunities([]uint32{bgp.COMMUNITY_LLGR_STALE}, false) + p.SetCommunities([]uint32{uint32(bgp.COMMUNITY_LLGR_STALE)}, false) } paths[i] = p } @@ -317,10 +317,6 @@ } -func (peer *Peer) getAccepted(rfList []bgp.RouteFamily) []*table.Path { - return peer.adjRibIn.PathList(rfList, true) -} - func (peer *Peer) filterPathFromSourcePeer(path, old *table.Path) *table.Path { if peer.ID() != path.GetSource().Address.String() { return path diff -Nru gobgp-1.32/server/server.go gobgp-1.33/server/server.go --- gobgp-1.32/server/server.go 2018-06-01 11:32:28.000000000 +0000 +++ gobgp-1.33/server/server.go 2018-07-01 12:06:57.000000000 +0000 @@ -19,8 +19,8 @@ "bytes" "fmt" "net" - "os" "strconv" + "sync" "time" "github.com/eapache/channels" @@ -111,7 +111,7 @@ globalRib *table.TableManager rsRib *table.TableManager roaManager *roaManager - shutdown bool + shutdownWG *sync.WaitGroup watcherMap map[WatchEventType][]*Watcher zclient *zebraClient bmpManager *bmpClientManager @@ -242,10 +242,12 @@ } return true }(peer.fsm.pConf.Transport.Config.LocalAddress) - if localAddrValid == false { + + if !localAddrValid { conn.Close() return } + log.WithFields(log.Fields{ "Topic": "Peer", }).Debugf("Accepted a new passive connection from:%s", remoteAddr) @@ -531,11 +533,12 @@ return nil } - path = table.UpdatePathAttrs(peer.fsm.gConf, peer.fsm.pConf, peer.fsm.peerInfo, path) - options := &table.PolicyOptions{ - Info: peer.fsm.peerInfo, + Info: peer.fsm.peerInfo, + OldNextHop: path.GetNexthop(), } + path = table.UpdatePathAttrs(peer.fsm.gConf, peer.fsm.pConf, peer.fsm.peerInfo, path) + if v := s.roaManager.validate(path); v != nil { options.ValidationResult = v } @@ -1230,7 +1233,7 @@ } } } else { - if server.shutdown && nextState == bgp.BGP_FSM_IDLE { + if server.shutdownWG != nil && nextState == bgp.BGP_FSM_IDLE { die := true for _, p := range server.neighborMap { if p.fsm.state != bgp.BGP_FSM_IDLE { @@ -1239,7 +1242,7 @@ } } if die { - os.Exit(0) + server.shutdownWG.Done() } } peer.fsm.pConf.Timers.State.Downtime = time.Now().Unix() @@ -1374,10 +1377,9 @@ }).Panic("unknown msg type") } } - return } -func (s *BgpServer) StartCollector(c *config.CollectorConfig) error { +func (s *BgpServer) AddCollector(c *config.CollectorConfig) error { return s.mgmtOperation(func() error { _, err := NewCollector(s, c.Url, c.DbName, c.TableDumpInterval) return err @@ -1413,18 +1415,26 @@ func (s *BgpServer) Shutdown() { s.mgmtOperation(func() error { - s.shutdown = true - stateOp := AdminStateOperation{ADMIN_STATE_DOWN, nil} + s.shutdownWG = new(sync.WaitGroup) + s.shutdownWG.Add(1) + stateOp := AdminStateOperation{ + State: ADMIN_STATE_DOWN, + Communication: nil, + } for _, p := range s.neighborMap { p.fsm.adminStateCh <- stateOp } - // the main goroutine waits for peers' goroutines to stop but if no peer is configured, needs to die immediately. - if len(s.neighborMap) == 0 { - os.Exit(0) - } // TODO: call fsmincomingCh.Close() return nil }, false) + + // Waits for all goroutines per peer to stop. + // Note: This should not be wrapped with s.mgmtOperation() in order to + // avoid the deadlock in the main goroutine of BgpServer. + if s.shutdownWG != nil { + s.shutdownWG.Wait() + s.shutdownWG = nil + } } func (s *BgpServer) UpdatePolicy(policy config.RoutingPolicy) error { @@ -1592,6 +1602,7 @@ path := pathList[0] id, _ := uuid.NewV4() s.uuidMap[id] = pathTokey(path) + uuidBytes = id.Bytes() } s.propagateUpdate(nil, pathList) return nil @@ -1708,8 +1719,8 @@ AS: s.bgpConfig.Global.Config.As, LocalID: net.ParseIP(s.bgpConfig.Global.Config.RouterId).To4(), } - if pathList, e := s.globalRib.AddVrf(name, id, rd, im, ex, pi); e != nil { - return e + if pathList, err := s.globalRib.AddVrf(name, id, rd, im, ex, pi); err != nil { + return err } else if len(pathList) > 0 { s.propagateUpdate(nil, pathList) } @@ -1751,16 +1762,28 @@ }, true) } +func familiesForSoftreset(peer *Peer, family bgp.RouteFamily) []bgp.RouteFamily { + if family == bgp.RouteFamily(0) { + configured := peer.configuredRFlist() + families := make([]bgp.RouteFamily, 0, len(configured)) + for _, f := range configured { + if f != bgp.RF_RTC_UC { + families = append(families, f) + } + } + return families + } + return []bgp.RouteFamily{family} +} + func (s *BgpServer) softResetIn(addr string, family bgp.RouteFamily) error { peers, err := s.addrToPeers(addr) if err != nil { return err } for _, peer := range peers { - families := []bgp.RouteFamily{family} - if family == bgp.RouteFamily(0) { - families = peer.configuredRFlist() - } + families := familiesForSoftreset(peer, family) + pathList := make([]*table.Path, 0, peer.adjRibIn.Count(families)) for _, path := range peer.adjRibIn.PathList(families, false) { // RFC4271 9.1.2 Phase 2: Route Selection @@ -1796,11 +1819,7 @@ if peer.fsm.state != bgp.BGP_FSM_ESTABLISHED { continue } - - families := []bgp.RouteFamily{family} - if family == bgp.RouteFamily(0) { - families = peer.negotiatedRFList() - } + families := familiesForSoftreset(peer, family) if deferral { _, y := peer.fsm.rfMap[bgp.RF_RTC_UC] @@ -1826,7 +1845,7 @@ if len(pathList) > 0 { sendFsmOutgoingMsg(peer, pathList, nil, false) } - if deferral == false && len(filtered) > 0 { + if !deferral && len(filtered) > 0 { withdrawnList := make([]*table.Path, 0, len(filtered)) for _, p := range filtered { withdrawnList = append(withdrawnList, p.Clone(true)) @@ -1873,7 +1892,7 @@ func (s *BgpServer) validateTable(r *table.Table) (v []*table.Validation) { if s.roaManager.enabled() { - v := make([]*table.Validation, 0, len(r.GetDestinations())) + v = make([]*table.Validation, 0, len(r.GetDestinations())) for _, d := range r.GetDestinations() { for _, p := range d.GetAllKnownPathList() { v = append(v, s.roaManager.validate(p)) @@ -2291,7 +2310,8 @@ if original.Config.AdminDown != c.Config.AdminDown { sub = bgp.BGP_ERROR_SUB_ADMINISTRATIVE_SHUTDOWN state := "Admin Down" - if c.Config.AdminDown == false { + + if !c.Config.AdminDown { state = "Admin Up" } log.WithFields(log.Fields{ @@ -2732,7 +2752,6 @@ initPeerState bool tableName string recvMessage bool - sentMessage bool } type WatchOption func(*watchOptions) @@ -2857,16 +2876,10 @@ } func (w *Watcher) loop() { - for { - select { - case ev, ok := <-w.ch.Out(): - if !ok { - close(w.realCh) - return - } - w.realCh <- ev.(WatchEvent) - } + for ev := range w.ch.Out() { + w.realCh <- ev.(WatchEvent) } + close(w.realCh) } func (w *Watcher) Stop() { diff -Nru gobgp-1.32/server/server_test.go gobgp-1.33/server/server_test.go --- gobgp-1.32/server/server_test.go 2018-06-01 11:32:28.000000000 +0000 +++ gobgp-1.33/server/server_test.go 2018-07-01 12:06:57.000000000 +0000 @@ -16,11 +16,14 @@ package server import ( + "context" "net" "runtime" "testing" "time" + "github.com/stretchr/testify/require" + log "github.com/sirupsen/logrus" "github.com/stretchr/testify/assert" @@ -169,7 +172,7 @@ if len(rib.GetKnownPathList("", 0)) > 0 { break } - time.Sleep(1) + time.Sleep(100 * time.Millisecond) } // Test WatchUpdate with "current" flag. @@ -277,14 +280,8 @@ if len(news) != 1 { panic("can't handle multiple paths") } - for idx, path := range news { - var old *table.Path - if olds != nil { - old = olds[idx] - } - return path, old - } - return nil, nil + + return news[0], olds[0] } func TestFilterpathWitheBGP(t *testing.T) { @@ -597,7 +594,7 @@ GracefulRestart: config.GracefulRestart{ Config: config.GracefulRestartConfig{ Enabled: true, - RestartTime: 10, + RestartTime: 1, }, }, } @@ -613,7 +610,7 @@ Port: -1, }, }) - assert.Nil(err) + require.NoError(t, err) defer s2.Stop() m := &config.Neighbor{ @@ -629,7 +626,7 @@ GracefulRestart: config.GracefulRestart{ Config: config.GracefulRestartConfig{ Enabled: true, - RestartTime: 10, + RestartTime: 1, }, }, } @@ -656,22 +653,55 @@ // Create dummy session which does NOT send BGP OPEN message in order to // cause Graceful Restart timer expired. var conn net.Conn - for { - time.Sleep(time.Second) - var err error - conn, err = net.Dial("tcp", "127.0.0.1:10179") - if err != nil { - log.Warn("net.Dial:", err) - } - break - } + + conn, err = net.Dial("tcp", "127.0.0.1:10179") + require.NoError(t, err) defer conn.Close() + // this seems to take around 22 seconds... need to address this whole thing + ctx, cancel := context.WithTimeout(context.Background(), 30*time.Second) + defer cancel() + // Waiting for Graceful Restart timer expired and moving on to IDLE state. for { - time.Sleep(time.Second) if s1.GetNeighbor("", false)[0].State.SessionState == config.SESSION_STATE_IDLE { break } + + select { + case <-time.After(time.Second): + case <-ctx.Done(): + t.Fatalf("failed to enter IDLE state in the deadline") + return + } + } +} + +func TestFamiliesForSoftreset(t *testing.T) { + f := func(f bgp.RouteFamily) config.AfiSafi { + return config.AfiSafi{ + State: config.AfiSafiState{ + Family: f, + }, + } } + peer := &Peer{ + fsm: &FSM{ + pConf: &config.Neighbor{ + AfiSafis: []config.AfiSafi{f(bgp.RF_RTC_UC), f(bgp.RF_IPv4_UC), f(bgp.RF_IPv6_UC)}, + }, + }, + } + + families := familiesForSoftreset(peer, bgp.RF_IPv4_UC) + assert.Equal(t, len(families), 1) + assert.Equal(t, families[0], bgp.RF_IPv4_UC) + + families = familiesForSoftreset(peer, bgp.RF_RTC_UC) + assert.Equal(t, len(families), 1) + assert.Equal(t, families[0], bgp.RF_RTC_UC) + + families = familiesForSoftreset(peer, bgp.RouteFamily(0)) + assert.Equal(t, len(families), 2) + assert.NotContains(t, families, bgp.RF_RTC_UC) } diff -Nru gobgp-1.32/server/sockopt_darwin.go gobgp-1.33/server/sockopt_darwin.go --- gobgp-1.32/server/sockopt_darwin.go 2018-06-01 11:32:28.000000000 +0000 +++ gobgp-1.33/server/sockopt_darwin.go 2018-07-01 12:06:57.000000000 +0000 @@ -39,19 +39,23 @@ func setListenTcpTTLSockopt(l *net.TCPListener, ttl int) error { fi, family, err := extractFileAndFamilyFromTCPListener(l) - defer fi.Close() if err != nil { return err } + + defer fi.Close() + return setsockoptIpTtl(int(fi.Fd()), family, ttl) } func setTcpTTLSockopt(conn *net.TCPConn, ttl int) error { fi, family, err := extractFileAndFamilyFromTCPConn(conn) - defer fi.Close() if err != nil { return err } + + defer fi.Close() + return setsockoptIpTtl(int(fi.Fd()), family, ttl) } diff -Nru gobgp-1.32/server/sockopt_linux.go gobgp-1.33/server/sockopt_linux.go --- gobgp-1.32/server/sockopt_linux.go 2018-06-01 11:32:28.000000000 +0000 +++ gobgp-1.33/server/sockopt_linux.go 2018-07-01 12:06:57.000000000 +0000 @@ -32,10 +32,12 @@ type tcpmd5sig struct { ss_family uint16 ss [126]byte - pad1 uint16 - keylen uint16 - pad2 uint32 - key [80]byte + // padding the struct + _ uint16 + keylen uint16 + // padding the struct + _ uint32 + key [80]byte } func buildTcpMD5Sig(address string, key string) (tcpmd5sig, error) { @@ -66,10 +68,11 @@ func SetTcpMD5SigSockopt(l *net.TCPListener, address string, key string) error { fi, _, err := extractFileAndFamilyFromTCPListener(l) - defer fi.Close() if err != nil { return err } + defer fi.Close() + return setsockoptTcpMD5Sig(int(fi.Fd()), address, key) } @@ -85,19 +88,21 @@ func SetListenTcpTTLSockopt(l *net.TCPListener, ttl int) error { fi, family, err := extractFileAndFamilyFromTCPListener(l) - defer fi.Close() if err != nil { return err } + defer fi.Close() + return setsockoptIpTtl(int(fi.Fd()), family, ttl) } func SetTcpTTLSockopt(conn *net.TCPConn, ttl int) error { fi, family, err := extractFileAndFamilyFromTCPConn(conn) - defer fi.Close() if err != nil { return err } + defer fi.Close() + return setsockoptIpTtl(int(fi.Fd()), family, ttl) } @@ -113,10 +118,11 @@ func SetTcpMinTTLSockopt(conn *net.TCPConn, ttl int) error { fi, family, err := extractFileAndFamilyFromTCPConn(conn) - defer fi.Close() if err != nil { return err } + defer fi.Close() + return setsockoptIpMinTtl(int(fi.Fd()), family, ttl) } diff -Nru gobgp-1.32/server/sockopt_linux_test.go gobgp-1.33/server/sockopt_linux_test.go --- gobgp-1.32/server/sockopt_linux_test.go 2018-06-01 11:32:28.000000000 +0000 +++ gobgp-1.33/server/sockopt_linux_test.go 2018-07-01 12:06:57.000000000 +0000 @@ -42,7 +42,7 @@ buf2 := []uint8{2, 0, 0, 0, 1, 2, 3, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 5, 0, 0, 0, 0, 0, 104, 101, 108, 108, 111, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} - if bytes.Compare(buf1, buf2) == 0 { + if bytes.Equal(buf1, buf2) { t.Log("OK") } else { t.Error("Something wrong v4") @@ -62,7 +62,7 @@ buf2[0] = syscall.AF_INET6 - if bytes.Compare(buf1, buf2) == 0 { + if bytes.Equal(buf1, buf2) { t.Log("OK") } else { t.Error("Something wrong v6") diff -Nru gobgp-1.32/server/zclient.go gobgp-1.33/server/zclient.go --- gobgp-1.32/server/zclient.go 2018-06-01 11:32:28.000000000 +0000 +++ gobgp-1.33/server/zclient.go 2018-07-01 12:06:57.000000000 +0000 @@ -283,10 +283,6 @@ dead chan struct{} } -func (z *zebraClient) stop() { - close(z.dead) -} - func (z *zebraClient) getPathListWithNexthopUpdate(body *zebra.NexthopUpdateBody) []*table.Path { rib := &table.TableManager{ Tables: make(map[bgp.RouteFamily]*table.Table), @@ -326,7 +322,6 @@ }).Error("failed to update nexthop reachability") } } - return } func (z *zebraClient) loop() { diff -Nru gobgp-1.32/table/destination.go gobgp-1.33/table/destination.go --- gobgp-1.32/table/destination.go 2018-06-01 11:32:28.000000000 +0000 +++ gobgp-1.33/table/destination.go 2018-07-01 12:06:57.000000000 +0000 @@ -150,7 +150,7 @@ } func NewPeerInfo(g *config.Global, p *config.Neighbor) *PeerInfo { - id := net.ParseIP(string(p.RouteReflector.Config.RouteReflectorClusterId)).To4() + clusterID := net.ParseIP(string(p.RouteReflector.State.RouteReflectorClusterId)).To4() // exclude zone info naddr, _ := net.ResolveIPAddr("ip", p.State.NeighborAddress) return &PeerInfo{ @@ -159,7 +159,7 @@ LocalID: net.ParseIP(g.Config.RouterId).To4(), RouteReflectorClient: p.RouteReflector.Config.RouteReflectorClient, Address: naddr.IP, - RouteReflectorClusterID: id, + RouteReflectorClusterID: clusterID, MultihopTtl: p.EbgpMultihop.Config.MultihopTtl, Confederation: p.IsConfederationMember(g), } @@ -255,18 +255,6 @@ return getMultiBestPath(id, dd.knownPathList) } -func (dd *Destination) validatePath(path *Path) { - if path == nil || path.GetRouteFamily() != dd.routeFamily { - - log.WithFields(log.Fields{ - "Topic": "Table", - "Key": dd.GetNlri().String(), - "Path": path, - "ExpectedRF": dd.routeFamily, - }).Error("path is nil or invalid route family") - } -} - // Calculates best-path among known paths for this destination. // // Modifies destination's state related to stored paths. Removes withdrawn @@ -530,10 +518,7 @@ better.reason = reason - if better == path1 { - return true - } - return false + return better == path1 }) } diff -Nru gobgp-1.32/table/message.go gobgp-1.33/table/message.go --- gobgp-1.32/table/message.go 2018-06-01 11:32:28.000000000 +0000 +++ gobgp-1.33/table/message.go 2018-07-01 12:06:57.000000000 +0000 @@ -201,9 +201,7 @@ } newIntfParams := make([]bgp.AsPathParamInterface, 0, len(asAttr.Value)) - for _, p := range newParams { - newIntfParams = append(newIntfParams, p) - } + newIntfParams = append(newIntfParams, newParams...) msg.PathAttributes[asAttrPos] = bgp.NewPathAttributeAsPath(newIntfParams) return nil @@ -384,7 +382,7 @@ if cages, y := p.hashmap[key]; y { added := false for _, c := range cages { - if bytes.Compare(c.attrsBytes, attrsB.Bytes()) == 0 { + if bytes.Equal(c.attrsBytes, attrsB.Bytes()) { c.paths = append(c.paths, path) added = true break diff -Nru gobgp-1.32/table/message_test.go gobgp-1.33/table/message_test.go --- gobgp-1.32/table/message_test.go 2018-06-01 11:32:28.000000000 +0000 +++ gobgp-1.33/table/message_test.go 2018-07-01 12:06:57.000000000 +0000 @@ -578,9 +578,7 @@ for _, msg := range msgs { u := msg.Body.(*bgp.BGPUpdate) assert.Equal(t, len(u.PathAttributes), 3) - for _, n := range u.NLRI { - l = append(l, n) - } + l = append(l, u.NLRI...) } assert.Equal(t, len(l), nr) @@ -651,9 +649,7 @@ for _, msg := range msgs { u := msg.Body.(*bgp.BGPUpdate) assert.Equal(t, len(u.PathAttributes), 0) - for _, n := range u.WithdrawnRoutes { - l = append(l, n) - } + l = append(l, u.WithdrawnRoutes...) } assert.Equal(t, len(l), nr) for i, addr := range addrs { diff -Nru gobgp-1.32/table/path.go gobgp-1.33/table/path.go --- gobgp-1.32/table/path.go 2018-06-01 11:32:28.000000000 +0000 +++ gobgp-1.33/table/path.go 2018-07-01 12:06:57.000000000 +0000 @@ -135,16 +135,17 @@ } type Path struct { - info *originInfo - IsWithdraw bool - pathAttrs []bgp.PathAttributeInterface - attrsHash uint32 - reason BestPathReason - parent *Path - dels []bgp.BGPAttrType + info *originInfo + parent *Path + pathAttrs []bgp.PathAttributeInterface + dels []bgp.BGPAttrType + attrsHash uint32 + aslooped bool + reason BestPathReason + // For BGP Nexthop Tracking, this field shows if nexthop is invalidated by IGP. IsNexthopInvalid bool - aslooped bool + IsWithdraw bool } func NewPath(source *PeerInfo, nlri bgp.AddrPrefixInterface, isWithdraw bool, pattrs []bgp.PathAttributeInterface, timestamp time.Time, noImplicitWithdraw bool) *Path { @@ -289,16 +290,16 @@ } // When an RR reflects a route, it MUST prepend the local CLUSTER_ID to the CLUSTER_LIST. // If the CLUSTER_LIST is empty, it MUST create a new one. - id := string(peer.RouteReflector.Config.RouteReflectorClusterId) + clusterID := string(peer.RouteReflector.State.RouteReflectorClusterId) if p := path.getPathAttr(bgp.BGP_ATTR_TYPE_CLUSTER_LIST); p == nil { - path.setPathAttr(bgp.NewPathAttributeClusterList([]string{id})) + path.setPathAttr(bgp.NewPathAttributeClusterList([]string{clusterID})) } else { clusterList := p.(*bgp.PathAttributeClusterList) newClusterList := make([]string, 0, len(clusterList.Value)) for _, ip := range clusterList.Value { newClusterList = append(newClusterList, ip.String()) } - path.setPathAttr(bgp.NewPathAttributeClusterList(append([]string{id}, newClusterList...))) + path.setPathAttr(bgp.NewPathAttributeClusterList(append([]string{clusterID}, newClusterList...))) } } @@ -333,6 +334,7 @@ parent: path, IsWithdraw: isWithdraw, IsNexthopInvalid: path.IsNexthopInvalid, + attrsHash: path.attrsHash, } } @@ -405,7 +407,7 @@ func (path *Path) IsLLGRStale() bool { for _, c := range path.GetCommunities() { - if c == bgp.COMMUNITY_LLGR_STALE { + if c == uint32(bgp.COMMUNITY_LLGR_STALE) { return true } } @@ -796,7 +798,6 @@ } path.setPathAttr(bgp.NewPathAttributeAsPath(newASParams)) } - return } func (path *Path) removeConfedAs() { @@ -923,9 +924,7 @@ eCommunityList := make([]bgp.ExtendedCommunityInterface, 0) if attr := path.getPathAttr(bgp.BGP_ATTR_TYPE_EXTENDED_COMMUNITIES); attr != nil { eCommunities := attr.(*bgp.PathAttributeExtendedCommunities).Value - for _, eCommunity := range eCommunities { - eCommunityList = append(eCommunityList, eCommunity) - } + eCommunityList = append(eCommunityList, eCommunities...) } return eCommunityList } @@ -949,9 +948,7 @@ if a := path.getPathAttr(bgp.BGP_ATTR_TYPE_LARGE_COMMUNITY); a != nil { v := a.(*bgp.PathAttributeLargeCommunities).Values ret := make([]*bgp.LargeCommunity, 0, len(v)) - for _, c := range v { - ret = append(ret, c) - } + ret = append(ret, v...) return ret } return nil @@ -977,20 +974,19 @@ // SetMed replace, add or subtraction med with new ones. func (path *Path) SetMed(med int64, doReplace bool) error { - parseMed := func(orgMed uint32, med int64, doReplace bool) (*bgp.PathAttributeMultiExitDisc, error) { - newMed := &bgp.PathAttributeMultiExitDisc{} if doReplace { - newMed = bgp.NewPathAttributeMultiExitDisc(uint32(med)) - } else { - if int64(orgMed)+med < 0 { - return nil, fmt.Errorf("med value invalid. it's underflow threshold.") - } else if int64(orgMed)+med > int64(math.MaxUint32) { - return nil, fmt.Errorf("med value invalid. it's overflow threshold.") - } - newMed = bgp.NewPathAttributeMultiExitDisc(uint32(int64(orgMed) + med)) + return bgp.NewPathAttributeMultiExitDisc(uint32(med)), nil + } + + medVal := int64(orgMed) + med + if medVal < 0 { + return nil, fmt.Errorf("med value invalid. it's underflow threshold: %v", medVal) + } else if medVal > int64(math.MaxUint32) { + return nil, fmt.Errorf("med value invalid. it's overflow threshold: %v", medVal) } - return newMed, nil + + return bgp.NewPathAttributeMultiExitDisc(uint32(int64(orgMed) + med)), nil } m := uint32(0) diff -Nru gobgp-1.32/table/policy.go gobgp-1.33/table/policy.go --- gobgp-1.32/table/policy.go 2018-06-01 11:32:28.000000000 +0000 +++ gobgp-1.33/table/policy.go 2018-07-01 12:06:57.000000000 +0000 @@ -26,17 +26,17 @@ "strings" "sync" - log "github.com/sirupsen/logrus" - - radix "github.com/armon/go-radix" - "github.com/osrg/gobgp/config" "github.com/osrg/gobgp/packet/bgp" + + radix "github.com/armon/go-radix" + log "github.com/sirupsen/logrus" ) type PolicyOptions struct { Info *PeerInfo ValidationResult *Validation + OldNextHop net.IP } type DefinedType int @@ -49,6 +49,7 @@ DEFINED_TYPE_COMMUNITY DEFINED_TYPE_EXT_COMMUNITY DEFINED_TYPE_LARGE_COMMUNITY + DEFINED_TYPE_NEXT_HOP ) type RouteType int @@ -154,6 +155,8 @@ CONDITION_RPKI CONDITION_ROUTE_TYPE CONDITION_LARGE_COMMUNITY + CONDITION_NEXT_HOP + CONDITION_AFI_SAFI_IN ) type ActionType int @@ -306,6 +309,8 @@ return p.Prefix.String() } +var _regexpPrefixRange = regexp.MustCompile(`(\d+)\.\.(\d+)`) + func NewPrefix(c config.Prefix) (*Prefix, error) { _, prefix, err := net.ParseCIDR(c.IpPrefix) if err != nil { @@ -321,28 +326,30 @@ AddressFamily: rf, } maskRange := c.MasklengthRange + if maskRange == "" { l, _ := prefix.Mask.Size() maskLength := uint8(l) p.MasklengthRangeMax = maskLength p.MasklengthRangeMin = maskLength - } else { - exp := regexp.MustCompile("(\\d+)\\.\\.(\\d+)") - elems := exp.FindStringSubmatch(maskRange) - if len(elems) != 3 { - log.WithFields(log.Fields{ - "Topic": "Policy", - "Type": "Prefix", - "MaskRangeFormat": maskRange, - }).Warn("mask length range format is invalid.") - return nil, fmt.Errorf("mask length range format is invalid") - } - // we've already checked the range is sane by regexp - min, _ := strconv.ParseUint(elems[1], 10, 8) - max, _ := strconv.ParseUint(elems[2], 10, 8) - p.MasklengthRangeMin = uint8(min) - p.MasklengthRangeMax = uint8(max) + return p, nil + } + + elems := _regexpPrefixRange.FindStringSubmatch(maskRange) + if len(elems) != 3 { + log.WithFields(log.Fields{ + "Topic": "Policy", + "Type": "Prefix", + "MaskRangeFormat": maskRange, + }).Warn("mask length range format is invalid.") + return nil, fmt.Errorf("mask length range format is invalid") } + + // we've already checked the range is sane by regexp + min, _ := strconv.ParseUint(elems[1], 10, 8) + max, _ := strconv.ParseUint(elems[2], 10, 8) + p.MasklengthRangeMin = uint8(min) + p.MasklengthRangeMax = uint8(max) return p, nil } @@ -535,6 +542,109 @@ }, nil } +type NextHopSet struct { + list []net.IPNet +} + +func (s *NextHopSet) Name() string { + return "NextHopSet: NO NAME" +} + +func (s *NextHopSet) Type() DefinedType { + return DEFINED_TYPE_NEXT_HOP +} + +func (lhs *NextHopSet) Append(arg DefinedSet) error { + rhs, ok := arg.(*NextHopSet) + if !ok { + return fmt.Errorf("type cast failed") + } + lhs.list = append(lhs.list, rhs.list...) + return nil +} + +func (lhs *NextHopSet) Remove(arg DefinedSet) error { + rhs, ok := arg.(*NextHopSet) + if !ok { + return fmt.Errorf("type cast failed") + } + ps := make([]net.IPNet, 0, len(lhs.list)) + for _, x := range lhs.list { + found := false + for _, y := range rhs.list { + if x.String() == y.String() { + found = true + break + } + } + if !found { + ps = append(ps, x) + } + } + lhs.list = ps + return nil +} + +func (lhs *NextHopSet) Replace(arg DefinedSet) error { + rhs, ok := arg.(*NextHopSet) + if !ok { + return fmt.Errorf("type cast failed") + } + lhs.list = rhs.list + return nil +} + +func (s *NextHopSet) List() []string { + list := make([]string, 0, len(s.list)) + for _, n := range s.list { + list = append(list, n.String()) + } + return list +} + +func (s *NextHopSet) ToConfig() []string { + return s.List() +} + +func (s *NextHopSet) String() string { + return "[ " + strings.Join(s.List(), ", ") + " ]" +} + +func (s *NextHopSet) MarshalJSON() ([]byte, error) { + return json.Marshal(s.ToConfig()) +} + +func NewNextHopSetFromApiStruct(name string, list []net.IPNet) (*NextHopSet, error) { + return &NextHopSet{ + list: list, + }, nil +} + +func NewNextHopSet(c []string) (*NextHopSet, error) { + list := make([]net.IPNet, 0, len(c)) + for _, x := range c { + _, cidr, err := net.ParseCIDR(x) + if err != nil { + addr := net.ParseIP(x) + if addr == nil { + return nil, fmt.Errorf("invalid address or prefix: %s", x) + } + mask := net.CIDRMask(32, 32) + if addr.To4() == nil { + mask = net.CIDRMask(128, 128) + } + cidr = &net.IPNet{ + IP: addr, + Mask: mask, + } + } + list = append(list, *cidr) + } + return &NextHopSet{ + list: list, + }, nil +} + type NeighborSet struct { name string list []net.IPNet @@ -710,32 +820,35 @@ return false } +var ( + _regexpLeftMostRe = regexp.MustCompile(`$\^([0-9]+)_^`) + _regexpOriginRe = regexp.MustCompile(`^_([0-9]+)\$$`) + _regexpIncludeRe = regexp.MustCompile("^_([0-9]+)_$") + _regexpOnlyRe = regexp.MustCompile(`^\^([0-9]+)\$$`) +) + func NewSingleAsPathMatch(arg string) *singleAsPathMatch { - leftMostRe := regexp.MustCompile("$\\^([0-9]+)_^") - originRe := regexp.MustCompile("^_([0-9]+)\\$$") - includeRe := regexp.MustCompile("^_([0-9]+)_$") - onlyRe := regexp.MustCompile("^\\^([0-9]+)\\$$") switch { - case leftMostRe.MatchString(arg): - asn, _ := strconv.ParseUint(leftMostRe.FindStringSubmatch(arg)[1], 10, 32) + case _regexpLeftMostRe.MatchString(arg): + asn, _ := strconv.ParseUint(_regexpLeftMostRe.FindStringSubmatch(arg)[1], 10, 32) return &singleAsPathMatch{ asn: uint32(asn), mode: LEFT_MOST, } - case originRe.MatchString(arg): - asn, _ := strconv.ParseUint(originRe.FindStringSubmatch(arg)[1], 10, 32) + case _regexpOriginRe.MatchString(arg): + asn, _ := strconv.ParseUint(_regexpOriginRe.FindStringSubmatch(arg)[1], 10, 32) return &singleAsPathMatch{ asn: uint32(asn), mode: ORIGIN, } - case includeRe.MatchString(arg): - asn, _ := strconv.ParseUint(includeRe.FindStringSubmatch(arg)[1], 10, 32) + case _regexpIncludeRe.MatchString(arg): + asn, _ := strconv.ParseUint(_regexpIncludeRe.FindStringSubmatch(arg)[1], 10, 32) return &singleAsPathMatch{ asn: uint32(asn), mode: INCLUDE, } - case onlyRe.MatchString(arg): - asn, _ := strconv.ParseUint(onlyRe.FindStringSubmatch(arg)[1], 10, 32) + case _regexpOnlyRe.MatchString(arg): + asn, _ := strconv.ParseUint(_regexpOnlyRe.FindStringSubmatch(arg)[1], 10, 32) return &singleAsPathMatch{ asn: uint32(asn), mode: ONLY, @@ -978,13 +1091,15 @@ return json.Marshal(s.ToConfig()) } +var _regexpCommunity = regexp.MustCompile(`(\d+):(\d+)`) + func ParseCommunity(arg string) (uint32, error) { i, err := strconv.ParseUint(arg, 10, 32) if err == nil { return uint32(i), nil } - exp := regexp.MustCompile("(\\d+):(\\d+)") - elems := exp.FindStringSubmatch(arg) + + elems := _regexpCommunity.FindStringSubmatch(arg) if len(elems) == 3 { fst, _ := strconv.ParseUint(elems[1], 10, 16) snd, _ := strconv.ParseUint(elems[2], 10, 16) @@ -1029,24 +1144,25 @@ return bgp.ParseExtendedCommunity(subtype, value) } +var _regexpCommunity2 = regexp.MustCompile(`(\d+.)*\d+:\d+`) + func ParseCommunityRegexp(arg string) (*regexp.Regexp, error) { i, err := strconv.ParseUint(arg, 10, 32) if err == nil { - return regexp.MustCompile(fmt.Sprintf("^%d:%d$", i>>16, i&0x0000ffff)), nil + return regexp.Compile(fmt.Sprintf("^%d:%d$", i>>16, i&0x0000ffff)) } - if regexp.MustCompile("(\\d+.)*\\d+:\\d+").MatchString(arg) { - return regexp.MustCompile(fmt.Sprintf("^%s$", arg)), nil + + if _regexpCommunity2.MatchString(arg) { + return regexp.Compile(fmt.Sprintf("^%s$", arg)) } + for i, v := range bgp.WellKnownCommunityNameMap { if strings.Replace(strings.ToLower(arg), "_", "-", -1) == v { - return regexp.MustCompile(fmt.Sprintf("^%d:%d$", i>>16, i&0x0000ffff)), nil + return regexp.Compile(fmt.Sprintf("^%d:%d$", i>>16, i&0x0000ffff)) } } - exp, err := regexp.Compile(arg) - if err != nil { - return nil, fmt.Errorf("invalid community format: %s", arg) - } - return exp, nil + + return regexp.Compile(arg) } func ParseExtCommunityRegexp(arg string) (bgp.ExtendedCommunityAttrSubType, *regexp.Regexp, error) { @@ -1197,14 +1313,17 @@ return json.Marshal(s.ToConfig()) } +var _regexpCommunityLarge = regexp.MustCompile(`\d+:\d+:\d+`) + func ParseLargeCommunityRegexp(arg string) (*regexp.Regexp, error) { - if regexp.MustCompile("\\d+:\\d+:\\d+").MatchString(arg) { - return regexp.MustCompile(fmt.Sprintf("^%s$", arg)), nil + if _regexpCommunityLarge.MatchString(arg) { + return regexp.Compile(fmt.Sprintf("^%s$", arg)) } exp, err := regexp.Compile(arg) if err != nil { - return nil, fmt.Errorf("invalid large-community format: %s", arg) + return nil, fmt.Errorf("invalid large-community format: %v", err) } + return exp, nil } @@ -1240,6 +1359,74 @@ Set() DefinedSet } +type NextHopCondition struct { + set *NextHopSet +} + +func (c *NextHopCondition) Type() ConditionType { + return CONDITION_NEXT_HOP +} + +func (c *NextHopCondition) Set() DefinedSet { + return c.set +} + +func (c *NextHopCondition) Name() string { return "" } + +func (c *NextHopCondition) String() string { + return c.set.String() +} + +// compare next-hop ipaddress of this condition and source address of path +// and, subsequent comparisons are skipped if that matches the conditions. +// If NextHopSet's length is zero, return true. +func (c *NextHopCondition) Evaluate(path *Path, options *PolicyOptions) bool { + if len(c.set.list) == 0 { + log.WithFields(log.Fields{ + "Topic": "Policy", + }).Debug("NextHop doesn't have elements") + return true + } + + nexthop := path.GetNexthop() + + // In cases where we advertise routes from iBGP to eBGP, we want to filter + // on the "original" nexthop. The current paths' nexthop has already been + // set and is ready to be advertised as per: + // https://tools.ietf.org/html/rfc4271#section-5.1.3 + if options != nil && options.OldNextHop != nil && + !options.OldNextHop.IsUnspecified() && !options.OldNextHop.Equal(nexthop) { + nexthop = options.OldNextHop + } + + if nexthop == nil { + return false + } + + for _, n := range c.set.list { + if n.Contains(nexthop) { + return true + } + } + + return false +} + +func NewNextHopCondition(c []string) (*NextHopCondition, error) { + if len(c) == 0 { + return nil, nil + } + + list, err := NewNextHopSet(c) + if err != nil { + return nil, nil + } + + return &NextHopCondition{ + set: list, + }, nil +} + type PrefixCondition struct { set *PrefixSet option MatchOption @@ -1781,6 +1968,58 @@ }, nil } +type AfiSafiInCondition struct { + routeFamilies []bgp.RouteFamily +} + +func (c *AfiSafiInCondition) Type() ConditionType { + return CONDITION_AFI_SAFI_IN +} + +func (c *AfiSafiInCondition) Evaluate(path *Path, _ *PolicyOptions) bool { + for _, rf := range c.routeFamilies { + if path.GetRouteFamily() == rf { + return true + } + } + return false +} + +func (c *AfiSafiInCondition) Set() DefinedSet { + return nil +} + +func (c *AfiSafiInCondition) Name() string { return "" } + +func (c *AfiSafiInCondition) String() string { + tmp := make([]string, 0, len(c.routeFamilies)) + for _, afiSafi := range c.routeFamilies { + tmp = append(tmp, afiSafi.String()) + } + return strings.Join(tmp, " ") +} + +func NewAfiSafiInCondition(afiSafInConfig []config.AfiSafiType) (*AfiSafiInCondition, error) { + if afiSafInConfig == nil { + return nil, nil + } + + routeFamilies := make([]bgp.RouteFamily, 0, len(afiSafInConfig)) + for _, afiSafiValue := range afiSafInConfig { + if err := afiSafiValue.Validate(); err != nil { + return nil, err + } + rf, err := bgp.GetRouteFamily(string(afiSafiValue)) + if err != nil { + return nil, err + } + routeFamilies = append(routeFamilies, rf) + } + return &AfiSafiInCondition{ + routeFamilies: routeFamilies, + }, nil +} + type Action interface { Type() ActionType Apply(*Path, *PolicyOptions) *Path @@ -1845,7 +2084,7 @@ break } } - if match == false { + if !match { newComms = append(newComms, comm) } } @@ -1868,7 +2107,7 @@ break } } - if match == false { + if !match { newComms = append(newComms, comm) } } @@ -1887,7 +2126,7 @@ break } } - if match == false { + if !match { newComms = append(newComms, comm) } } @@ -1929,10 +2168,12 @@ return json.Marshal(a.ToConfig()) } +// TODO: this is not efficient use of regexp, probably slow +var _regexpCommunityReplaceString = regexp.MustCompile(`[\^\$]`) + func (a *CommunityAction) String() string { list := a.ToConfig().SetCommunityMethod.CommunitiesList - exp := regexp.MustCompile("[\\^\\$]") - l := exp.ReplaceAllString(strings.Join(list, ", "), "") + l := _regexpCommunityReplaceString.ReplaceAllString(strings.Join(list, ", "), "") return fmt.Sprintf("%s[%s]", a.action, l) } @@ -2026,8 +2267,7 @@ func (a *ExtCommunityAction) String() string { list := a.ToConfig().SetExtCommunityMethod.CommunitiesList - exp := regexp.MustCompile("[\\^\\$]") - l := exp.ReplaceAllString(strings.Join(list, ", "), "") + l := _regexpCommunityReplaceString.ReplaceAllString(strings.Join(list, ", "), "") return fmt.Sprintf("%s[%s]", a.action, l) } @@ -2115,8 +2355,7 @@ func (a *LargeCommunityAction) String() string { list := a.ToConfig().SetLargeCommunityMethod.CommunitiesList - exp := regexp.MustCompile("[\\^\\$]") - l := exp.ReplaceAllString(strings.Join(list, ", "), "") + l := _regexpCommunityReplaceString.ReplaceAllString(strings.Join(list, ", "), "") return fmt.Sprintf("%s[%s]", a.action, l) } @@ -2205,12 +2444,14 @@ return json.Marshal(a.ToConfig()) } +var _regexpParseMedAction = regexp.MustCompile(`^(\+|\-)?(\d+)$`) + func NewMedAction(c config.BgpSetMedType) (*MedAction, error) { if string(c) == "" { return nil, nil } - exp := regexp.MustCompile("^(\\+|\\-)?(\\d+)$") - elems := exp.FindStringSubmatch(string(c)) + + elems := _regexpParseMedAction.FindStringSubmatch(string(c)) if len(elems) != 3 { return nil, fmt.Errorf("invalid med action format") } @@ -2469,12 +2710,22 @@ 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())) + } + cond.BgpConditions.AfiSafiInList = res } } return cond @@ -2673,6 +2924,12 @@ func() (Condition, error) { return NewLargeCommunityCondition(c.Conditions.BgpConditions.MatchLargeCommunitySet) }, + func() (Condition, error) { + return NewNextHopCondition(c.Conditions.BgpConditions.NextHopInList) + }, + func() (Condition, error) { + return NewAfiSafiInCondition(c.Conditions.BgpConditions.AfiSafiInList) + }, } cs = make([]Condition, 0, len(cfs)) for _, f := range cfs { @@ -3046,6 +3303,8 @@ c := v.(*LargeCommunityCondition) c.set = i.(*LargeCommunitySet) } + case CONDITION_NEXT_HOP: + case CONDITION_AFI_SAFI_IN: case CONDITION_AS_PATH_LENGTH: case CONDITION_RPKI: } @@ -3155,6 +3414,7 @@ } dmap[DEFINED_TYPE_LARGE_COMMUNITY][y.Name()] = y } + pmap := make(map[string]*Policy) smap := make(map[string]*Statement) for _, x := range c.PolicyDefinitions { diff -Nru gobgp-1.32/table/policy_test.go gobgp-1.33/table/policy_test.go --- gobgp-1.32/table/policy_test.go 2018-06-01 11:32:28.000000000 +0000 +++ gobgp-1.33/table/policy_test.go 2018-07-01 12:06:57.000000000 +0000 @@ -24,11 +24,12 @@ "testing" "time" - log "github.com/sirupsen/logrus" - "github.com/stretchr/testify/assert" - "github.com/osrg/gobgp/config" "github.com/osrg/gobgp/packet/bgp" + + log "github.com/sirupsen/logrus" + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" ) func TestPrefixCalcurateNoRange(t *testing.T) { @@ -501,6 +502,70 @@ assert.Equal(t, false, c.Evaluate(path, nil)) } +func TestPolicyMatchAndAcceptNextHop(t *testing.T) { + // create path + peer := &PeerInfo{AS: 65001, Address: net.ParseIP("10.0.0.1")} + origin := bgp.NewPathAttributeOrigin(0) + aspathParam := []bgp.AsPathParamInterface{bgp.NewAsPathParam(2, []uint16{65001})} + aspath := bgp.NewPathAttributeAsPath(aspathParam) + nexthop := bgp.NewPathAttributeNextHop("10.0.0.1") + med := bgp.NewPathAttributeMultiExitDisc(0) + pathAttributes := []bgp.PathAttributeInterface{origin, aspath, nexthop, med} + nlri := []*bgp.IPAddrPrefix{bgp.NewIPAddrPrefix(24, "10.10.0.101")} + updateMsg := bgp.NewBGPUpdateMessage(nil, pathAttributes, nlri) + path := ProcessMessage(updateMsg, peer, time.Now())[0] + + // create policy + ps := createPrefixSet("ps1", "10.10.0.0/16", "21..24") + ns := createNeighborSet("ns1", "10.0.0.1") + ds := config.DefinedSets{} + ds.PrefixSets = []config.PrefixSet{ps} + ds.NeighborSets = []config.NeighborSet{ns} + s := createStatement("statement1", "ps1", "ns1", true) + s.Conditions.BgpConditions.NextHopInList = []string{"10.0.0.1/32"} + pd := createPolicyDefinition("pd1", s) + pl := createRoutingPolicy(ds, pd) + + r := NewRoutingPolicy() + err := r.reload(pl) + assert.Nil(t, err) + pType, newPath := r.policyMap["pd1"].Apply(path, nil) + assert.Equal(t, ROUTE_TYPE_ACCEPT, pType) + assert.Equal(t, newPath, path) +} + +func TestPolicyMatchAndRejectNextHop(t *testing.T) { + // create path + peer := &PeerInfo{AS: 65001, Address: net.ParseIP("10.0.0.1")} + origin := bgp.NewPathAttributeOrigin(0) + aspathParam := []bgp.AsPathParamInterface{bgp.NewAsPathParam(2, []uint16{65001})} + aspath := bgp.NewPathAttributeAsPath(aspathParam) + nexthop := bgp.NewPathAttributeNextHop("10.0.0.1") + med := bgp.NewPathAttributeMultiExitDisc(0) + pathAttributes := []bgp.PathAttributeInterface{origin, aspath, nexthop, med} + nlri := []*bgp.IPAddrPrefix{bgp.NewIPAddrPrefix(24, "10.10.0.101")} + updateMsg := bgp.NewBGPUpdateMessage(nil, pathAttributes, nlri) + path := ProcessMessage(updateMsg, peer, time.Now())[0] + + // create policy + ps := createPrefixSet("ps1", "10.10.0.0/16", "21..24") + ns := createNeighborSet("ns1", "10.0.0.1") + ds := config.DefinedSets{} + ds.PrefixSets = []config.PrefixSet{ps} + ds.NeighborSets = []config.NeighborSet{ns} + s := createStatement("statement1", "ps1", "ns1", true) + s.Conditions.BgpConditions.NextHopInList = []string{"10.0.0.12"} + pd := createPolicyDefinition("pd1", s) + pl := createRoutingPolicy(ds, pd) + + r := NewRoutingPolicy() + err := r.reload(pl) + assert.Nil(t, err) + pType, newPath := r.policyMap["pd1"].Apply(path, nil) + assert.Equal(t, ROUTE_TYPE_NONE, pType) + assert.Equal(t, newPath, path) +} + func TestAsPathLengthConditionWithOtherCondition(t *testing.T) { // setup // create path @@ -2994,6 +3059,41 @@ assert.Equal(t, m.Evaluate(p, nil), true) } +func TestAfiSafiInMatchPath(t *testing.T) { + condition, err := NewAfiSafiInCondition([]config.AfiSafiType{config.AFI_SAFI_TYPE_L3VPN_IPV4_UNICAST, config.AFI_SAFI_TYPE_L3VPN_IPV6_UNICAST}) + require.NoError(t, err) + + rtExtCom, err := bgp.ParseExtendedCommunity(bgp.EC_SUBTYPE_ROUTE_TARGET, "100:100") + assert.NoError(t, err) + + prefixVPNv4 := bgp.NewLabeledVPNIPAddrPrefix(0, "1.1.1.0/24", *bgp.NewMPLSLabelStack(), bgp.NewRouteDistinguisherTwoOctetAS(100, 100)) + prefixVPNv6 := bgp.NewLabeledVPNIPv6AddrPrefix(0, "2001:0db8:85a3:0000:0000:8a2e:0370:7334", *bgp.NewMPLSLabelStack(), bgp.NewRouteDistinguisherTwoOctetAS(200, 200)) + prefixRTC := bgp.NewRouteTargetMembershipNLRI(100, nil) + prefixv4 := bgp.NewIPAddrPrefix(0, "1.1.1.0/24") + prefixv6 := bgp.NewIPv6AddrPrefix(0, "2001:0db8:85a3:0000:0000:8a2e:0370:7334") + + pathVPNv4 := NewPath(nil, prefixVPNv4, false, []bgp.PathAttributeInterface{bgp.NewPathAttributeExtendedCommunities([]bgp.ExtendedCommunityInterface{rtExtCom})}, time.Time{}, false) + pathVPNv6 := NewPath(nil, prefixVPNv6, false, []bgp.PathAttributeInterface{bgp.NewPathAttributeExtendedCommunities([]bgp.ExtendedCommunityInterface{rtExtCom})}, time.Time{}, false) + pathv4 := NewPath(nil, prefixv4, false, []bgp.PathAttributeInterface{}, time.Time{}, false) + pathv6 := NewPath(nil, prefixv6, false, []bgp.PathAttributeInterface{}, time.Time{}, false) + pathRTC := NewPath(nil, prefixRTC, false, []bgp.PathAttributeInterface{}, time.Time{}, false) + + type Entry struct { + path *Path + shouldMatch bool + } + + for _, entry := range []Entry{ + {pathVPNv4, true}, + {pathVPNv6, true}, + {pathv4, false}, + {pathv6, false}, + {pathRTC, false}, + } { + assert.Equal(t, condition.Evaluate(entry.path, nil), entry.shouldMatch) + } +} + func TestMultipleStatementPolicy(t *testing.T) { r := NewRoutingPolicy() rp := config.RoutingPolicy{ diff -Nru gobgp-1.32/table/table.go gobgp-1.33/table/table.go --- gobgp-1.32/table/table.go 2018-06-01 11:32:28.000000000 +0000 +++ gobgp-1.33/table/table.go 2018-07-01 12:06:57.000000000 +0000 @@ -291,18 +291,16 @@ } func (t *Table) tableKey(nlri bgp.AddrPrefixInterface) string { - switch t.routeFamily { - case bgp.RF_IPv4_UC: + switch T := nlri.(type) { + case *bgp.IPAddrPrefix: b := make([]byte, 5) - ip := nlri.(*bgp.IPAddrPrefix) - copy(b, ip.Prefix.To4()) - b[4] = ip.Length + copy(b, T.Prefix.To4()) + b[4] = T.Length return *(*string)(unsafe.Pointer(&b)) - case bgp.RF_IPv6_UC: + case *bgp.IPv6AddrPrefix: b := make([]byte, 17) - ip := nlri.(*bgp.IPv6AddrPrefix) - copy(b, ip.Prefix.To16()) - b[16] = ip.Length + copy(b, T.Prefix.To16()) + b[16] = T.Length return *(*string)(unsafe.Pointer(&b)) } return nlri.String() diff -Nru gobgp-1.32/table/table_manager.go gobgp-1.33/table/table_manager.go --- gobgp-1.32/table/table_manager.go 2018-06-01 11:32:28.000000000 +0000 +++ gobgp-1.33/table/table_manager.go 2018-07-01 12:06:57.000000000 +0000 @@ -57,9 +57,7 @@ reach = a case *bgp.PathAttributeMpUnreachNLRI: l := make([]bgp.AddrPrefixInterface, 0, len(a.Value)) - for _, nlri := range a.Value { - l = append(l, nlri) - } + l = append(l, a.Value...) dels = append(dels, l...) default: attrs = append(attrs, attr) diff -Nru gobgp-1.32/table/table_manager_test.go gobgp-1.33/table/table_manager_test.go --- gobgp-1.32/table/table_manager_test.go 2018-06-01 11:32:28.000000000 +0000 +++ gobgp-1.33/table/table_manager_test.go 2018-07-01 12:06:57.000000000 +0000 @@ -18,12 +18,10 @@ import ( _ "fmt" "net" - "os" "testing" "time" "github.com/osrg/gobgp/packet/bgp" - log "github.com/sirupsen/logrus" "github.com/stretchr/testify/assert" ) @@ -42,16 +40,6 @@ return pathList, nil } -func getLogger(lv log.Level) *log.Logger { - var l *log.Logger = &log.Logger{ - Out: os.Stderr, - Formatter: new(log.JSONFormatter), - Hooks: make(map[log.Level][]log.Hook), - Level: lv, - } - return l -} - func peerR1() *PeerInfo { peer := &PeerInfo{ AS: 65000, diff -Nru gobgp-1.32/table/vrf.go gobgp-1.33/table/vrf.go --- gobgp-1.32/table/vrf.go 2018-06-01 11:32:28.000000000 +0000 +++ gobgp-1.33/table/vrf.go 2018-07-01 12:06:57.000000000 +0000 @@ -30,10 +30,7 @@ func (v *Vrf) Clone() *Vrf { f := func(rt []bgp.ExtendedCommunityInterface) []bgp.ExtendedCommunityInterface { l := make([]bgp.ExtendedCommunityInterface, 0, len(rt)) - for _, v := range rt { - l = append(l, v) - } - return l + return append(l, rt...) } return &Vrf{ Name: v.Name, diff -Nru gobgp-1.32/test/scenario_test/route_reflector_test.py gobgp-1.33/test/scenario_test/route_reflector_test.py --- gobgp-1.32/test/scenario_test/route_reflector_test.py 2018-06-01 11:32:28.000000000 +0000 +++ gobgp-1.33/test/scenario_test/route_reflector_test.py 2018-07-01 12:06:57.000000000 +0000 @@ -44,6 +44,14 @@ class GoBGPTestBase(unittest.TestCase): + def assert_adv_count(self, src, dst, rf, count): + self.assertEqual(count, len(src.get_adj_rib_out(dst, rf=rf))) + self.assertEqual(count, len(dst.get_adj_rib_in(src, rf=rf))) + + def assert_upd_count(self, src, dst, sent, received): + messages = src.get_neighbor(dst)['state']['messages'] + self.assertEqual(messages['sent'].get('update', 0), sent) + self.assertEqual(messages['received'].get('update', 0), received) @classmethod def setUpClass(cls): @@ -119,6 +127,137 @@ else: self.assertFalse(p in paths) + def test_10_setup_rr_rtc_isolation_policy(self): + # +-------+ + # | rr | + # +----------------+----| (RR) |---+----------------+ + # | | +-------+ | | + # | | | | + # (iBGP) (iBGP) (iBGP) (iBGP) + # | | | | + # +-------------+ +-------------+ +-------------+ +-------------+ + # | acme1 | | acme2 | | tyrell1 | | tyrell2 | + # | (RR Client) | | (RR Client) | | (RR Client) | | (RR Client) | + # +-------------+ +-------------+ +-------------+ +-------------+ + + + gobgp_ctn_image_name = parser_option.gobgp_image + rr = GoBGPContainer(name='rr', asn=65000, router_id='192.168.1.1', + ctn_image_name=gobgp_ctn_image_name, + log_level=parser_option.gobgp_log_level) + acme1 = GoBGPContainer(name='acme1', asn=65000, router_id='192.168.1.101', + ctn_image_name=gobgp_ctn_image_name, + log_level=parser_option.gobgp_log_level) + acme2 = GoBGPContainer(name='acme2', asn=65000, router_id='192.168.1.102', + ctn_image_name=gobgp_ctn_image_name, + log_level=parser_option.gobgp_log_level) + + tyrell1 = GoBGPContainer(name='tyrell1', asn=65000, router_id='192.168.1.201', + ctn_image_name=gobgp_ctn_image_name, + log_level=parser_option.gobgp_log_level) + + tyrell2 = GoBGPContainer(name='tyrell2', asn=65000, router_id='192.168.1.202', + ctn_image_name=gobgp_ctn_image_name, + log_level=parser_option.gobgp_log_level) + + time.sleep(max(ctn.run() for ctn in [rr, acme1, acme2, tyrell1, tyrell2])) + + rr.add_peer(acme1, vpn=True, addpath=True, graceful_restart=True, llgr=True, is_rr_client=True) + acme1.add_peer(rr, vpn=True, addpath=True, graceful_restart=True, llgr=True) + + rr.add_peer(acme2, vpn=True, addpath=True, graceful_restart=True, llgr=True, is_rr_client=True) + acme2.add_peer(rr, vpn=True, addpath=True, graceful_restart=True, llgr=True) + + rr.add_peer(tyrell1, vpn=True, addpath=True, graceful_restart=True, llgr=True, is_rr_client=True) + tyrell1.add_peer(rr, vpn=True, addpath=True, graceful_restart=True, llgr=True) + + rr.add_peer(tyrell2, vpn=True, addpath=True, graceful_restart=True, llgr=True, is_rr_client=True) + tyrell2.add_peer(rr, vpn=True, addpath=True, graceful_restart=True, llgr=True) + + self.__class__.rr = rr + self.__class__.acme1 = acme1 + self.__class__.acme2 = acme2 + self.__class__.tyrell1 = tyrell1 + self.__class__.tyrell2 = tyrell2 + + # add import/export policy to allow peers exchange routes within specific RTs + # later tests should not break due to RTC Updates being filtered-out + + rr.local("gobgp policy neighbor add clients-acme {} {}".format( + rr.peer_name(acme1), + rr.peer_name(acme2))) + + rr.local("gobgp policy neighbor add clients-tyrell {} {}".format( + rr.peer_name(tyrell1), + rr.peer_name(tyrell2))) + + rr.local("gobgp policy ext-community add rts-acme rt:^100:.*$") + rr.local("gobgp policy ext-community add rts-tyrell rt:^200:.*$") + + rr.local('gobgp policy statement add allow-rtc') + rr.local('gobgp policy statement allow-rtc add condition afi-safi-in rtc') + rr.local('gobgp policy statement allow-rtc add action accept') + + rr.local('gobgp policy statement add allow-acme') + rr.local('gobgp policy statement allow-acme add condition neighbor clients-acme') + rr.local('gobgp policy statement allow-acme add condition ext-community rts-acme') + rr.local('gobgp policy statement allow-acme add action accept') + + rr.local('gobgp policy statement add allow-tyrell') + rr.local('gobgp policy statement allow-tyrell add condition neighbor clients-tyrell') + rr.local('gobgp policy statement allow-tyrell add condition ext-community rts-tyrell') + rr.local('gobgp policy statement allow-tyrell add action accept') + rr.local('gobgp policy add tenancy allow-rtc allow-acme allow-tyrell') + + rr.local('gobgp global policy import add tenancy default reject') + rr.local('gobgp global policy export add tenancy default reject') + + acme1.local("gobgp vrf add a1 rd 100:100 rt both 100:100") + acme2.local("gobgp vrf add a1 rd 100:100 rt both 100:100") + + tyrell1.local("gobgp vrf add t1 rd 200:100 rt both 200:100") + tyrell2.local("gobgp vrf add t1 rd 200:100 rt both 200:100") + + rr.wait_for(expected_state=BGP_FSM_ESTABLISHED, peer=acme1) + rr.wait_for(expected_state=BGP_FSM_ESTABLISHED, peer=acme2) + rr.wait_for(expected_state=BGP_FSM_ESTABLISHED, peer=tyrell1) + rr.wait_for(expected_state=BGP_FSM_ESTABLISHED, peer=tyrell2) + + def test_11_routes_in_allowed_acme_rts_are_exchanged(self): + self.acme1.local("gobgp vrf a1 rib add 10.10.0.0/16 local-pref 100") + self.acme2.local("gobgp vrf a1 rib add 10.20.0.0/16") + self.tyrell1.local("gobgp vrf t1 rib add 20.10.0.0/16") + self.tyrell2.local("gobgp vrf t1 rib add 20.20.0.0/16") + time.sleep(1) + + self.assert_adv_count(self.rr, self.acme1, 'rtc', 2) + self.assert_adv_count(self.rr, self.acme1, 'ipv4-l3vpn', 1) + self.assert_adv_count(self.rr, self.acme2, 'rtc', 2) + self.assert_adv_count(self.rr, self.acme2, 'ipv4-l3vpn', 1) + self.assert_adv_count(self.rr, self.tyrell1, 'rtc', 2) + self.assert_adv_count(self.rr, self.tyrell1, 'ipv4-l3vpn', 1) + self.assert_adv_count(self.rr, self.tyrell2, 'rtc', 2) + self.assert_adv_count(self.rr, self.tyrell2, 'ipv4-l3vpn', 1) + + def test_12_routes_from_separate_rts_peers_are_isolated_by_rr(self): + self.tyrell1.local("gobgp vrf add a1 rd 100:100 rt both 100:100") + self.tyrell1.local("gobgp vrf a1 rib add 10.10.0.0/16 local-pref 200") + self.tyrell1.local("gobgp vrf a1 rib add 10.30.0.0/16") + time.sleep(1) + + rr_t2_in = self.rr.get_adj_rib_in(self.tyrell1, rf='ipv4-l3vpn') + self.assertEqual(3, len(rr_t2_in)) + + rr_a2_out = self.rr.get_adj_rib_out(self.acme2, rf='ipv4-l3vpn') + self.assertEqual(1, len(rr_a2_out)) + + a2_routes = self.acme2.get_adj_rib_in(self.rr, rf='ipv4-l3vpn') + self.assertEqual(1, len(a2_routes)) + ar0 = a2_routes[0] + self.assertEqual('10.10.0.0/16', ar0['prefix']) + self.assertEqual(self.rr.peer_name(self.acme1), ar0['nexthop']) + self.assertEqual(100, ar0['local-pref']) + if __name__ == '__main__': output = local("which docker 2>&1 > /dev/null ; echo $?", capture=True) diff -Nru gobgp-1.32/tools/pyang_plugins/gobgp.yang gobgp-1.33/tools/pyang_plugins/gobgp.yang --- gobgp-1.32/tools/pyang_plugins/gobgp.yang 2018-06-01 11:32:28.000000000 +0000 +++ gobgp-1.33/tools/pyang_plugins/gobgp.yang 2018-07-01 12:06:57.000000000 +0000 @@ -1191,9 +1191,7 @@ "Configure url for zebra."; } leaf-list redistribute-route-type { - type identityref { - base ptypes:install-protocol-type; - } + type string; } leaf version { type uint8; diff -Nru gobgp-1.32/tools/route-server/quagga-rsconfig.go gobgp-1.33/tools/route-server/quagga-rsconfig.go --- gobgp-1.32/tools/route-server/quagga-rsconfig.go 2018-06-01 11:32:28.000000000 +0000 +++ gobgp-1.33/tools/route-server/quagga-rsconfig.go 2018-07-01 12:06:57.000000000 +0000 @@ -45,8 +45,6 @@ } func create_config_files(nr int, outputDir string) { - quaggaConfigList := make([]*QuaggaConfig, 0) - gobgpConf := config.Bgp{} gobgpConf.Global.Config.As = 65000 gobgpConf.Global.Config.RouterId = "192.168.255.1" @@ -60,21 +58,24 @@ gobgpConf.Neighbors = append(gobgpConf.Neighbors, c) q := NewQuaggaConfig(i, &gobgpConf.Global, &c, net.ParseIP("10.0.255.1")) - quaggaConfigList = append(quaggaConfigList, q) - os.Mkdir(fmt.Sprintf("%s/q%d", outputDir, i), 0755) - err := ioutil.WriteFile(fmt.Sprintf("%s/q%d/bgpd.conf", outputDir, i), q.Config().Bytes(), 0644) - if err != nil { + + if err := os.Mkdir(fmt.Sprintf("%s/q%d", outputDir, i), 0755); err != nil { + log.Fatalf("failed to make directory: %v", err) + } + + if err := ioutil.WriteFile(fmt.Sprintf("%s/q%d/bgpd.conf", outputDir, i), q.Config().Bytes(), 0644); err != nil { log.Fatal(err) } } var buffer bytes.Buffer encoder := toml.NewEncoder(&buffer) - encoder.Encode(gobgpConf) + if err := encoder.Encode(gobgpConf); err != nil { + log.Fatalf("failed to encode config: %v", err) + } - err := ioutil.WriteFile(fmt.Sprintf("%s/gobgpd.conf", outputDir), buffer.Bytes(), 0644) - if err != nil { - log.Fatal(err) + if err := ioutil.WriteFile(fmt.Sprintf("%s/gobgpd.conf", outputDir), buffer.Bytes(), 0644); err != nil { + log.Fatalf("failed to write config file: %v", err) } } diff -Nru gobgp-1.32/tools/spell-check/ignore.txt gobgp-1.33/tools/spell-check/ignore.txt --- gobgp-1.32/tools/spell-check/ignore.txt 2018-06-01 11:32:28.000000000 +0000 +++ gobgp-1.33/tools/spell-check/ignore.txt 2018-07-01 12:06:57.000000000 +0000 @@ -15,6 +15,8 @@ setsockopt Sprintf strconv +Unmarshal +unmarshal # Implementation specific dumpv2 diff -Nru gobgp-1.32/.travis.yml gobgp-1.33/.travis.yml --- gobgp-1.32/.travis.yml 2018-06-01 11:32:28.000000000 +0000 +++ gobgp-1.33/.travis.yml 2018-07-01 12:06:57.000000000 +0000 @@ -8,10 +8,8 @@ _unittest: &_unittest <<: *_dep_ensure script: - - go test $(go list ./... | grep -v '/vendor/') + - go test $(go list ./... | grep -v '/vendor/') -timeout 120s - if [ "$(go env GOARCH)" = "amd64" ]; then go test -race github.com/osrg/gobgp/packet/bgp -run ^Test_RaceCondition$; else echo 'skip'; fi - - go build -o ./gobgp/gobgp ./gobgp/ - - go build -o ./gobgpd/gobgpd ./gobgpd/ _build: &_build <<: *_dep_ensure @@ -52,13 +50,14 @@ matrix: allow_failures: - go: tip + include: # # Unit Tests # - <<: *_unittest env: - - DESCRIPTION="Unit Tests" + - DESCRIPTION="Unit Tests Tip" go: tip - <<: *_unittest env: @@ -66,16 +65,20 @@ go: 1.9 - <<: *_unittest env: - - DESCRIPTION="Unit Tests + goreleaser" + - DESCRIPTION="Tests + goreleaser + cover" go: "1.10" + script: + - go test $(go list ./... | grep -v '/vendor/') -coverprofile=coverage.txt -covermode=atomic after_success: - test -n "$TRAVIS_TAG" && curl -sL https://git.io/goreleaser | bash + - bash <(curl -s https://codecov.io/bash) - <<: *_unittest env: - DESCRIPTION="Unit Tests on i386" before_script: - export GOARCH="386" - go env + # # Cross-compile # @@ -105,12 +108,12 @@ # - <<: *_dep_ensure env: - - DESCRIPTION="go fmt" - script: test -z "$(go fmt $(go list ./... | grep -v '/vendor/'))" - - <<: *_dep_ensure - env: - - DESCRIPTION="go vet" - script: test -z "$(go vet $(go list ./... | grep -v '/vendor/'))" + - DESCRIPTION="go fmt + vet + megacheck" + before_script: go get -u honnef.co/go/tools/cmd/megacheck + script: + - test -z "$(go fmt $(go list ./... | grep -v '/vendor/'))" + - test -z "$(go vet $(go list ./... | grep -v '/vendor/'))" + - megacheck $(go list ./... | grep -v '/vendor/') - <<: *_dep_ensure env: - DESCRIPTION="build_embeded_go.py" diff -Nru gobgp-1.32/VERSION gobgp-1.33/VERSION --- gobgp-1.32/VERSION 2018-06-01 11:32:28.000000000 +0000 +++ gobgp-1.33/VERSION 2018-07-01 12:06:57.000000000 +0000 @@ -1 +1 @@ -1.32 +1.33 diff -Nru gobgp-1.32/zebra/zapi.go gobgp-1.33/zebra/zapi.go --- gobgp-1.32/zebra/zapi.go 2018-06-01 11:32:28.000000000 +0000 +++ gobgp-1.33/zebra/zapi.go 2018-07-01 12:06:57.000000000 +0000 @@ -546,7 +546,7 @@ if err != nil { log.WithFields(log.Fields{ "Topic": "Zebra", - }).Warnf("failed to serialize: %s", m) + }).Warnf("failed to serialize: %v", m) continue } @@ -907,7 +907,7 @@ if version <= 3 { return []byte{uint8(b.RedistDefault)}, nil } else { // version >= 4 - buf := make([]byte, 3, 3) + buf := make([]byte, 3) buf[0] = uint8(b.RedistDefault) binary.BigEndian.PutUint16(buf[1:3], b.Instance) return buf, nil @@ -942,7 +942,7 @@ if version <= 3 { return []byte{uint8(b.Redist)}, nil } else { // version >= 4 - buf := make([]byte, 4, 4) + buf := make([]byte, 4) buf[0] = uint8(b.Afi) buf[1] = uint8(b.Redist) binary.BigEndian.PutUint16(buf[2:4], b.Instance) @@ -1407,71 +1407,6 @@ return s } -func serializeNexthops(nexthops []*Nexthop, isV4 bool, version uint8) ([]byte, error) { - buf := make([]byte, 0) - if len(nexthops) == 0 { - return buf, nil - } - buf = append(buf, byte(len(nexthops))) - - nhIfindex := NEXTHOP_IFINDEX - nhIfname := NEXTHOP_IFNAME - nhIPv4 := NEXTHOP_IPV4 - nhIPv4Ifindex := NEXTHOP_IPV4_IFINDEX - nhIPv4Ifname := NEXTHOP_IPV4_IFNAME - nhIPv6 := NEXTHOP_IPV6 - nhIPv6Ifindex := NEXTHOP_IPV6_IFINDEX - nhIPv6Ifname := NEXTHOP_IPV6_IFNAME - if version >= 4 { - nhIfindex = FRR_NEXTHOP_IFINDEX - nhIfname = NEXTHOP_FLAG(0) - nhIPv4 = FRR_NEXTHOP_IPV4 - nhIPv4Ifindex = FRR_NEXTHOP_IPV4_IFINDEX - nhIPv4Ifname = NEXTHOP_FLAG(0) - nhIPv6 = FRR_NEXTHOP_IPV6 - nhIPv6Ifindex = FRR_NEXTHOP_IPV6_IFINDEX - nhIPv6Ifname = NEXTHOP_FLAG(0) - } - - for _, nh := range nexthops { - buf = append(buf, byte(nh.Type)) - - switch nh.Type { - case nhIfindex, nhIfname: - bbuf := make([]byte, 4) - binary.BigEndian.PutUint32(bbuf, nh.Ifindex) - buf = append(buf, bbuf...) - - case nhIPv4, nhIPv6: - if isV4 { - buf = append(buf, nh.Addr.To4()...) - } else { - buf = append(buf, nh.Addr.To16()...) - } - if version >= 4 { - // On FRRouting version 3.0 or later, NEXTHOP_IPV4 and - // NEXTHOP_IPV6 have the same structure with - // NEXTHOP_TYPE_IPV4_IFINDEX and NEXTHOP_TYPE_IPV6_IFINDEX. - bbuf := make([]byte, 4) - binary.BigEndian.PutUint32(bbuf, nh.Ifindex) - buf = append(buf, bbuf...) - } - - case nhIPv4Ifindex, nhIPv4Ifname, nhIPv6Ifindex, nhIPv6Ifname: - if isV4 { - buf = append(buf, nh.Addr.To4()...) - } else { - buf = append(buf, nh.Addr.To16()...) - } - bbuf := make([]byte, 4) - binary.BigEndian.PutUint32(bbuf, nh.Ifindex) - buf = append(buf, bbuf...) - } - } - - return buf, nil -} - func decodeNexthopsFromBytes(nexthops *[]*Nexthop, data []byte, isV4 bool, version uint8) (int, error) { addrLen := net.IPv4len if !isV4 { diff -Nru gobgp-1.32/zebra/zapi_test.go gobgp-1.33/zebra/zapi_test.go --- gobgp-1.32/zebra/zapi_test.go 2018-06-01 11:32:28.000000000 +0000 +++ gobgp-1.33/zebra/zapi_test.go 2018-07-01 12:06:57.000000000 +0000 @@ -21,6 +21,8 @@ "syscall" "testing" + "github.com/stretchr/testify/require" + "github.com/stretchr/testify/assert" ) @@ -113,6 +115,8 @@ b := &InterfaceAddressUpdateBody{} err := b.DecodeFromBytes(buf, 2) + require.NoError(t, err) + assert.Equal(uint32(0), b.Index) assert.Equal(INTERFACE_ADDRESS_FLAG(1), b.Flags) assert.Equal("192.168.100.1", b.Prefix.String())