summaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
-rw-r--r--api/attribute.go1306
-rw-r--r--api/attribute.pb.go2086
-rw-r--r--api/attribute.proto504
-rw-r--r--api/attribute_test.go1416
-rw-r--r--api/gobgp.pb.go73
-rw-r--r--tools/spell-check/ignore.txt2
6 files changed, 5387 insertions, 0 deletions
diff --git a/api/attribute.go b/api/attribute.go
new file mode 100644
index 00000000..a4f5734e
--- /dev/null
+++ b/api/attribute.go
@@ -0,0 +1,1306 @@
+// 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:
+ 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:
+ return nil
+ }
+ a, _ := ptypes.MarshalAny(r)
+ return a
+}
+
+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 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 --git a/api/attribute.pb.go b/api/attribute.pb.go
new file mode 100644
index 00000000..79535b7c
--- /dev/null
+++ b/api/attribute.pb.go
@@ -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 --git a/api/attribute.proto b/api/attribute.proto
new file mode 100644
index 00000000..dea22b4f
--- /dev/null
+++ b/api/attribute.proto
@@ -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 --git a/api/attribute_test.go b/api/attribute_test.go
new file mode 100644
index 00000000..271b0191
--- /dev/null
+++ b/api/attribute_test.go
@@ -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 --git a/api/gobgp.pb.go b/api/gobgp.pb.go
index b6364c31..622d76ed 100644
--- a/api/gobgp.pb.go
+++ b/api/gobgp.pb.go
@@ -6,6 +6,7 @@ Package gobgpapi is a generated protocol buffer package.
It is generated from these files:
gobgp.proto
+ attribute.proto
It has these top-level messages:
GetNeighborRequest
@@ -180,6 +181,78 @@ It has these top-level messages:
TableInfo
GetRibInfoRequest
GetRibInfoResponse
+ 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
*/
package gobgpapi
diff --git a/tools/spell-check/ignore.txt b/tools/spell-check/ignore.txt
index 4163d941..4ad36108 100644
--- a/tools/spell-check/ignore.txt
+++ b/tools/spell-check/ignore.txt
@@ -15,6 +15,8 @@ itoa
setsockopt
Sprintf
strconv
+Unmarshal
+unmarshal
# Implementation specific
dumpv2