github.com/osrg/gobgp@v2.0.0+incompatible/internal/pkg/apiutil/attribute.go (about)

     1  // Copyright (C) 2018 Nippon Telegraph and Telephone Corporation.
     2  //
     3  // Licensed under the Apache License, Version 2.0 (the "License");
     4  // you may not use this file except in compliance with the License.
     5  // You may obtain a copy of the License at
     6  //
     7  //    http://www.apache.org/licenses/LICENSE-2.0
     8  //
     9  // Unless required by applicable law or agreed to in writing, software
    10  // distributed under the License is distributed on an "AS IS" BASIS,
    11  // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
    12  // implied.
    13  // See the License for the specific language governing permissions and
    14  // limitations under the License.
    15  
    16  package apiutil
    17  
    18  import (
    19  	"errors"
    20  	"fmt"
    21  	"net"
    22  
    23  	"github.com/golang/protobuf/proto"
    24  	"github.com/golang/protobuf/ptypes"
    25  	"github.com/golang/protobuf/ptypes/any"
    26  	api "github.com/osrg/gobgp/api"
    27  	"github.com/osrg/gobgp/pkg/packet/bgp"
    28  	log "github.com/sirupsen/logrus"
    29  )
    30  
    31  func UnmarshalAttribute(an *any.Any) (bgp.PathAttributeInterface, error) {
    32  	var value ptypes.DynamicAny
    33  	if err := ptypes.UnmarshalAny(an, &value); err != nil {
    34  		return nil, fmt.Errorf("failed to unmarshal route distinguisher: %s", err)
    35  	}
    36  	switch a := value.Message.(type) {
    37  	case *api.OriginAttribute:
    38  		return bgp.NewPathAttributeOrigin(uint8(a.Origin)), nil
    39  	case *api.AsPathAttribute:
    40  		params := make([]bgp.AsPathParamInterface, 0, len(a.Segments))
    41  		for _, segment := range a.Segments {
    42  			params = append(params, bgp.NewAs4PathParam(uint8(segment.Type), segment.Numbers))
    43  		}
    44  		return bgp.NewPathAttributeAsPath(params), nil
    45  	case *api.NextHopAttribute:
    46  		nexthop := net.ParseIP(a.NextHop).To4()
    47  		if nexthop == nil {
    48  			return nil, fmt.Errorf("invalid nexthop address: %s", a.NextHop)
    49  		}
    50  		return bgp.NewPathAttributeNextHop(a.NextHop), nil
    51  	case *api.MultiExitDiscAttribute:
    52  		return bgp.NewPathAttributeMultiExitDisc(a.Med), nil
    53  	case *api.LocalPrefAttribute:
    54  		return bgp.NewPathAttributeLocalPref(a.LocalPref), nil
    55  	case *api.AtomicAggregateAttribute:
    56  		return bgp.NewPathAttributeAtomicAggregate(), nil
    57  	case *api.AggregatorAttribute:
    58  		if net.ParseIP(a.Address).To4() == nil {
    59  			return nil, fmt.Errorf("invalid aggregator address: %s", a.Address)
    60  		}
    61  		return bgp.NewPathAttributeAggregator(a.As, a.Address), nil
    62  	case *api.CommunitiesAttribute:
    63  		return bgp.NewPathAttributeCommunities(a.Communities), nil
    64  	case *api.OriginatorIdAttribute:
    65  		if net.ParseIP(a.Id).To4() == nil {
    66  			return nil, fmt.Errorf("invalid originator id: %s", a.Id)
    67  		}
    68  		return bgp.NewPathAttributeOriginatorId(a.Id), nil
    69  	case *api.ClusterListAttribute:
    70  		for _, id := range a.Ids {
    71  			if net.ParseIP(id).To4() == nil {
    72  				return nil, fmt.Errorf("invalid cluster list: %s", a.Ids)
    73  			}
    74  		}
    75  		return bgp.NewPathAttributeClusterList(a.Ids), nil
    76  	}
    77  	return nil, errors.New("unexpected object")
    78  }
    79  
    80  func NewOriginAttributeFromNative(a *bgp.PathAttributeOrigin) *api.OriginAttribute {
    81  	return &api.OriginAttribute{
    82  		Origin: uint32(a.Value),
    83  	}
    84  }
    85  
    86  func NewAsPathAttributeFromNative(a *bgp.PathAttributeAsPath) *api.AsPathAttribute {
    87  	segments := make([]*api.AsSegment, 0, len(a.Value))
    88  	for _, param := range a.Value {
    89  		segments = append(segments, &api.AsSegment{
    90  			Type:    uint32(param.GetType()),
    91  			Numbers: param.GetAS(),
    92  		})
    93  	}
    94  	return &api.AsPathAttribute{
    95  		Segments: segments,
    96  	}
    97  }
    98  
    99  func NewNextHopAttributeFromNative(a *bgp.PathAttributeNextHop) *api.NextHopAttribute {
   100  	return &api.NextHopAttribute{
   101  		NextHop: a.Value.String(),
   102  	}
   103  }
   104  
   105  func NewMultiExitDiscAttributeFromNative(a *bgp.PathAttributeMultiExitDisc) *api.MultiExitDiscAttribute {
   106  	return &api.MultiExitDiscAttribute{
   107  		Med: a.Value,
   108  	}
   109  }
   110  
   111  func NewLocalPrefAttributeFromNative(a *bgp.PathAttributeLocalPref) *api.LocalPrefAttribute {
   112  	return &api.LocalPrefAttribute{
   113  		LocalPref: a.Value,
   114  	}
   115  }
   116  
   117  func NewAtomicAggregateAttributeFromNative(a *bgp.PathAttributeAtomicAggregate) *api.AtomicAggregateAttribute {
   118  	return &api.AtomicAggregateAttribute{}
   119  }
   120  
   121  func NewAggregatorAttributeFromNative(a *bgp.PathAttributeAggregator) *api.AggregatorAttribute {
   122  	return &api.AggregatorAttribute{
   123  		As:      a.Value.AS,
   124  		Address: a.Value.Address.String(),
   125  	}
   126  }
   127  
   128  func NewCommunitiesAttributeFromNative(a *bgp.PathAttributeCommunities) *api.CommunitiesAttribute {
   129  	return &api.CommunitiesAttribute{
   130  		Communities: a.Value,
   131  	}
   132  }
   133  
   134  func NewOriginatorIdAttributeFromNative(a *bgp.PathAttributeOriginatorId) *api.OriginatorIdAttribute {
   135  	return &api.OriginatorIdAttribute{
   136  		Id: a.Value.String(),
   137  	}
   138  }
   139  
   140  func NewClusterListAttributeFromNative(a *bgp.PathAttributeClusterList) *api.ClusterListAttribute {
   141  	ids := make([]string, 0, len(a.Value))
   142  	for _, id := range a.Value {
   143  		ids = append(ids, id.String())
   144  	}
   145  	return &api.ClusterListAttribute{
   146  		Ids: ids,
   147  	}
   148  }
   149  
   150  func MarshalRD(rd bgp.RouteDistinguisherInterface) *any.Any {
   151  	var r proto.Message
   152  	switch v := rd.(type) {
   153  	case *bgp.RouteDistinguisherTwoOctetAS:
   154  		r = &api.RouteDistinguisherTwoOctetAS{
   155  			Admin:    uint32(v.Admin),
   156  			Assigned: v.Assigned,
   157  		}
   158  	case *bgp.RouteDistinguisherIPAddressAS:
   159  		r = &api.RouteDistinguisherIPAddress{
   160  			Admin:    v.Admin.String(),
   161  			Assigned: uint32(v.Assigned),
   162  		}
   163  	case *bgp.RouteDistinguisherFourOctetAS:
   164  		r = &api.RouteDistinguisherFourOctetAS{
   165  			Admin:    v.Admin,
   166  			Assigned: uint32(v.Assigned),
   167  		}
   168  	default:
   169  		log.WithFields(log.Fields{
   170  			"Topic": "protobuf",
   171  			"RD":    rd,
   172  		}).Warn("invalid rd type to marshal")
   173  		return nil
   174  	}
   175  	a, _ := ptypes.MarshalAny(r)
   176  	return a
   177  }
   178  
   179  func UnmarshalRD(a *any.Any) (bgp.RouteDistinguisherInterface, error) {
   180  	var value ptypes.DynamicAny
   181  	if err := ptypes.UnmarshalAny(a, &value); err != nil {
   182  		return nil, fmt.Errorf("failed to unmarshal route distinguisher: %s", err)
   183  	}
   184  	switch v := value.Message.(type) {
   185  	case *api.RouteDistinguisherTwoOctetAS:
   186  		return bgp.NewRouteDistinguisherTwoOctetAS(uint16(v.Admin), v.Assigned), nil
   187  	case *api.RouteDistinguisherIPAddress:
   188  		rd := bgp.NewRouteDistinguisherIPAddressAS(v.Admin, uint16(v.Assigned))
   189  		if rd == nil {
   190  			return nil, fmt.Errorf("invalid address for route distinguisher: %s", v.Admin)
   191  		}
   192  		return rd, nil
   193  	case *api.RouteDistinguisherFourOctetAS:
   194  		return bgp.NewRouteDistinguisherFourOctetAS(v.Admin, uint16(v.Assigned)), nil
   195  	}
   196  	return nil, fmt.Errorf("invalid route distinguisher type: %s", a.TypeUrl)
   197  }
   198  
   199  func NewEthernetSegmentIdentifierFromNative(a *bgp.EthernetSegmentIdentifier) *api.EthernetSegmentIdentifier {
   200  	return &api.EthernetSegmentIdentifier{
   201  		Type:  uint32(a.Type),
   202  		Value: a.Value,
   203  	}
   204  }
   205  
   206  func unmarshalESI(a *api.EthernetSegmentIdentifier) (*bgp.EthernetSegmentIdentifier, error) {
   207  	return &bgp.EthernetSegmentIdentifier{
   208  		Type:  bgp.ESIType(a.Type),
   209  		Value: a.Value,
   210  	}, nil
   211  }
   212  
   213  func MarshalFlowSpecRules(values []bgp.FlowSpecComponentInterface) []*any.Any {
   214  	rules := make([]*any.Any, 0, len(values))
   215  	for _, value := range values {
   216  		var rule proto.Message
   217  		switch v := value.(type) {
   218  		case *bgp.FlowSpecDestinationPrefix:
   219  			rule = &api.FlowSpecIPPrefix{
   220  				Type:      uint32(bgp.FLOW_SPEC_TYPE_DST_PREFIX),
   221  				PrefixLen: uint32(v.Prefix.(*bgp.IPAddrPrefix).Length),
   222  				Prefix:    v.Prefix.(*bgp.IPAddrPrefix).Prefix.String(),
   223  			}
   224  		case *bgp.FlowSpecSourcePrefix:
   225  			rule = &api.FlowSpecIPPrefix{
   226  				Type:      uint32(bgp.FLOW_SPEC_TYPE_SRC_PREFIX),
   227  				PrefixLen: uint32(v.Prefix.(*bgp.IPAddrPrefix).Length),
   228  				Prefix:    v.Prefix.(*bgp.IPAddrPrefix).Prefix.String(),
   229  			}
   230  		case *bgp.FlowSpecDestinationPrefix6:
   231  			rule = &api.FlowSpecIPPrefix{
   232  				Type:      uint32(bgp.FLOW_SPEC_TYPE_DST_PREFIX),
   233  				PrefixLen: uint32(v.Prefix.(*bgp.IPv6AddrPrefix).Length),
   234  				Prefix:    v.Prefix.(*bgp.IPv6AddrPrefix).Prefix.String(),
   235  				Offset:    uint32(v.Offset),
   236  			}
   237  		case *bgp.FlowSpecSourcePrefix6:
   238  			rule = &api.FlowSpecIPPrefix{
   239  				Type:      uint32(bgp.FLOW_SPEC_TYPE_SRC_PREFIX),
   240  				PrefixLen: uint32(v.Prefix.(*bgp.IPv6AddrPrefix).Length),
   241  				Prefix:    v.Prefix.(*bgp.IPv6AddrPrefix).Prefix.String(),
   242  				Offset:    uint32(v.Offset),
   243  			}
   244  		case *bgp.FlowSpecSourceMac:
   245  			rule = &api.FlowSpecMAC{
   246  				Type:    uint32(bgp.FLOW_SPEC_TYPE_SRC_MAC),
   247  				Address: v.Mac.String(),
   248  			}
   249  		case *bgp.FlowSpecDestinationMac:
   250  			rule = &api.FlowSpecMAC{
   251  				Type:    uint32(bgp.FLOW_SPEC_TYPE_DST_MAC),
   252  				Address: v.Mac.String(),
   253  			}
   254  		case *bgp.FlowSpecComponent:
   255  			items := make([]*api.FlowSpecComponentItem, 0, len(v.Items))
   256  			for _, i := range v.Items {
   257  				items = append(items, &api.FlowSpecComponentItem{
   258  					Op:    uint32(i.Op),
   259  					Value: i.Value,
   260  				})
   261  			}
   262  			rule = &api.FlowSpecComponent{
   263  				Type:  uint32(v.Type()),
   264  				Items: items,
   265  			}
   266  		}
   267  		a, _ := ptypes.MarshalAny(rule)
   268  		rules = append(rules, a)
   269  	}
   270  	return rules
   271  }
   272  
   273  func UnmarshalFlowSpecRules(values []*any.Any) ([]bgp.FlowSpecComponentInterface, error) {
   274  	rules := make([]bgp.FlowSpecComponentInterface, 0, len(values))
   275  	for _, an := range values {
   276  		var rule bgp.FlowSpecComponentInterface
   277  		var value ptypes.DynamicAny
   278  		if err := ptypes.UnmarshalAny(an, &value); err != nil {
   279  			return nil, fmt.Errorf("failed to unmarshal flow spec component: %s", err)
   280  		}
   281  		switch v := value.Message.(type) {
   282  		case *api.FlowSpecIPPrefix:
   283  			typ := bgp.BGPFlowSpecType(v.Type)
   284  			isIPv4 := net.ParseIP(v.Prefix).To4() != nil
   285  			switch {
   286  			case typ == bgp.FLOW_SPEC_TYPE_DST_PREFIX && isIPv4:
   287  				rule = bgp.NewFlowSpecDestinationPrefix(bgp.NewIPAddrPrefix(uint8(v.PrefixLen), v.Prefix))
   288  			case typ == bgp.FLOW_SPEC_TYPE_SRC_PREFIX && isIPv4:
   289  				rule = bgp.NewFlowSpecSourcePrefix(bgp.NewIPAddrPrefix(uint8(v.PrefixLen), v.Prefix))
   290  			case typ == bgp.FLOW_SPEC_TYPE_DST_PREFIX && !isIPv4:
   291  				rule = bgp.NewFlowSpecDestinationPrefix6(bgp.NewIPv6AddrPrefix(uint8(v.PrefixLen), v.Prefix), uint8(v.Offset))
   292  			case typ == bgp.FLOW_SPEC_TYPE_SRC_PREFIX && !isIPv4:
   293  				rule = bgp.NewFlowSpecSourcePrefix6(bgp.NewIPv6AddrPrefix(uint8(v.PrefixLen), v.Prefix), uint8(v.Offset))
   294  			}
   295  		case *api.FlowSpecMAC:
   296  			typ := bgp.BGPFlowSpecType(v.Type)
   297  			mac, err := net.ParseMAC(v.Address)
   298  			if err != nil {
   299  				return nil, fmt.Errorf("invalid mac address for %s flow spec component: %s", typ.String(), v.Address)
   300  			}
   301  			switch typ {
   302  			case bgp.FLOW_SPEC_TYPE_SRC_MAC:
   303  				rule = bgp.NewFlowSpecSourceMac(mac)
   304  			case bgp.FLOW_SPEC_TYPE_DST_MAC:
   305  				rule = bgp.NewFlowSpecDestinationMac(mac)
   306  			}
   307  		case *api.FlowSpecComponent:
   308  			items := make([]*bgp.FlowSpecComponentItem, 0, len(v.Items))
   309  			for _, item := range v.Items {
   310  				items = append(items, bgp.NewFlowSpecComponentItem(uint8(item.Op), item.Value))
   311  			}
   312  			rule = bgp.NewFlowSpecComponent(bgp.BGPFlowSpecType(v.Type), items)
   313  		}
   314  		if rule == nil {
   315  			return nil, fmt.Errorf("invalid flow spec component: %v", value.Message)
   316  		}
   317  		rules = append(rules, rule)
   318  	}
   319  	return rules, nil
   320  }
   321  
   322  func MarshalNLRI(value bgp.AddrPrefixInterface) *any.Any {
   323  	var nlri proto.Message
   324  
   325  	switch v := value.(type) {
   326  	case *bgp.IPAddrPrefix:
   327  		nlri = &api.IPAddressPrefix{
   328  			PrefixLen: uint32(v.Length),
   329  			Prefix:    v.Prefix.String(),
   330  		}
   331  	case *bgp.IPv6AddrPrefix:
   332  		nlri = &api.IPAddressPrefix{
   333  			PrefixLen: uint32(v.Length),
   334  			Prefix:    v.Prefix.String(),
   335  		}
   336  	case *bgp.LabeledIPAddrPrefix:
   337  		nlri = &api.LabeledIPAddressPrefix{
   338  			Labels:    v.Labels.Labels,
   339  			PrefixLen: uint32(v.IPPrefixLen()),
   340  			Prefix:    v.Prefix.String(),
   341  		}
   342  	case *bgp.LabeledIPv6AddrPrefix:
   343  		nlri = &api.LabeledIPAddressPrefix{
   344  			Labels:    v.Labels.Labels,
   345  			PrefixLen: uint32(v.IPPrefixLen()),
   346  			Prefix:    v.Prefix.String(),
   347  		}
   348  	case *bgp.EncapNLRI:
   349  		nlri = &api.EncapsulationNLRI{
   350  			Address: v.String(),
   351  		}
   352  	case *bgp.Encapv6NLRI:
   353  		nlri = &api.EncapsulationNLRI{
   354  			Address: v.String(),
   355  		}
   356  	case *bgp.EVPNNLRI:
   357  		switch r := v.RouteTypeData.(type) {
   358  		case *bgp.EVPNEthernetAutoDiscoveryRoute:
   359  			nlri = &api.EVPNEthernetAutoDiscoveryRoute{
   360  				Rd:          MarshalRD(r.RD),
   361  				Esi:         NewEthernetSegmentIdentifierFromNative(&r.ESI),
   362  				EthernetTag: r.ETag,
   363  				Label:       r.Label,
   364  			}
   365  		case *bgp.EVPNMacIPAdvertisementRoute:
   366  			nlri = &api.EVPNMACIPAdvertisementRoute{
   367  				Rd:          MarshalRD(r.RD),
   368  				Esi:         NewEthernetSegmentIdentifierFromNative(&r.ESI),
   369  				EthernetTag: r.ETag,
   370  				MacAddress:  r.MacAddress.String(),
   371  				IpAddress:   r.IPAddress.String(),
   372  				Labels:      r.Labels,
   373  			}
   374  		case *bgp.EVPNMulticastEthernetTagRoute:
   375  			nlri = &api.EVPNInclusiveMulticastEthernetTagRoute{
   376  				Rd:          MarshalRD(r.RD),
   377  				EthernetTag: r.ETag,
   378  				IpAddress:   r.IPAddress.String(),
   379  			}
   380  		case *bgp.EVPNEthernetSegmentRoute:
   381  			nlri = &api.EVPNEthernetSegmentRoute{
   382  				Rd:        MarshalRD(r.RD),
   383  				Esi:       NewEthernetSegmentIdentifierFromNative(&r.ESI),
   384  				IpAddress: r.IPAddress.String(),
   385  			}
   386  		case *bgp.EVPNIPPrefixRoute:
   387  			nlri = &api.EVPNIPPrefixRoute{
   388  				Rd:          MarshalRD(r.RD),
   389  				Esi:         NewEthernetSegmentIdentifierFromNative(&r.ESI),
   390  				EthernetTag: r.ETag,
   391  				IpPrefix:    r.IPPrefix.String(),
   392  				IpPrefixLen: uint32(r.IPPrefixLength),
   393  				Label:       r.Label,
   394  				GwAddress:   r.GWIPAddress.String(),
   395  			}
   396  		}
   397  	case *bgp.LabeledVPNIPAddrPrefix:
   398  		nlri = &api.LabeledVPNIPAddressPrefix{
   399  			Labels:    v.Labels.Labels,
   400  			Rd:        MarshalRD(v.RD),
   401  			PrefixLen: uint32(v.IPPrefixLen()),
   402  			Prefix:    v.Prefix.String(),
   403  		}
   404  	case *bgp.LabeledVPNIPv6AddrPrefix:
   405  		nlri = &api.LabeledVPNIPAddressPrefix{
   406  			Labels:    v.Labels.Labels,
   407  			Rd:        MarshalRD(v.RD),
   408  			PrefixLen: uint32(v.IPPrefixLen()),
   409  			Prefix:    v.Prefix.String(),
   410  		}
   411  	case *bgp.RouteTargetMembershipNLRI:
   412  		nlri = &api.RouteTargetMembershipNLRI{
   413  			As: v.AS,
   414  			Rt: MarshalRT(v.RouteTarget),
   415  		}
   416  	case *bgp.FlowSpecIPv4Unicast:
   417  		nlri = &api.FlowSpecNLRI{
   418  			Rules: MarshalFlowSpecRules(v.Value),
   419  		}
   420  	case *bgp.FlowSpecIPv6Unicast:
   421  		nlri = &api.FlowSpecNLRI{
   422  			Rules: MarshalFlowSpecRules(v.Value),
   423  		}
   424  	case *bgp.FlowSpecIPv4VPN:
   425  		nlri = &api.VPNFlowSpecNLRI{
   426  			Rd:    MarshalRD(v.RD()),
   427  			Rules: MarshalFlowSpecRules(v.Value),
   428  		}
   429  	case *bgp.FlowSpecIPv6VPN:
   430  		nlri = &api.VPNFlowSpecNLRI{
   431  			Rd:    MarshalRD(v.RD()),
   432  			Rules: MarshalFlowSpecRules(v.Value),
   433  		}
   434  	case *bgp.FlowSpecL2VPN:
   435  		nlri = &api.VPNFlowSpecNLRI{
   436  			Rd:    MarshalRD(v.RD()),
   437  			Rules: MarshalFlowSpecRules(v.Value),
   438  		}
   439  	}
   440  
   441  	an, _ := ptypes.MarshalAny(nlri)
   442  	return an
   443  }
   444  
   445  func MarshalNLRIs(values []bgp.AddrPrefixInterface) []*any.Any {
   446  	nlris := make([]*any.Any, 0, len(values))
   447  	for _, value := range values {
   448  		nlris = append(nlris, MarshalNLRI(value))
   449  	}
   450  	return nlris
   451  }
   452  
   453  func UnmarshalNLRI(rf bgp.RouteFamily, an *any.Any) (bgp.AddrPrefixInterface, error) {
   454  	var nlri bgp.AddrPrefixInterface
   455  
   456  	var value ptypes.DynamicAny
   457  	if err := ptypes.UnmarshalAny(an, &value); err != nil {
   458  		return nil, fmt.Errorf("failed to unmarshal nlri: %s", err)
   459  	}
   460  
   461  	switch v := value.Message.(type) {
   462  	case *api.IPAddressPrefix:
   463  		switch rf {
   464  		case bgp.RF_IPv4_UC:
   465  			nlri = bgp.NewIPAddrPrefix(uint8(v.PrefixLen), v.Prefix)
   466  		case bgp.RF_IPv6_UC:
   467  			nlri = bgp.NewIPv6AddrPrefix(uint8(v.PrefixLen), v.Prefix)
   468  		}
   469  	case *api.LabeledIPAddressPrefix:
   470  		switch rf {
   471  		case bgp.RF_IPv4_MPLS:
   472  			nlri = bgp.NewLabeledIPAddrPrefix(uint8(v.PrefixLen), v.Prefix, *bgp.NewMPLSLabelStack(v.Labels...))
   473  		case bgp.RF_IPv6_MPLS:
   474  			nlri = bgp.NewLabeledIPv6AddrPrefix(uint8(v.PrefixLen), v.Prefix, *bgp.NewMPLSLabelStack(v.Labels...))
   475  		}
   476  	case *api.EncapsulationNLRI:
   477  		switch rf {
   478  		case bgp.RF_IPv4_ENCAP:
   479  			nlri = bgp.NewEncapNLRI(v.Address)
   480  		case bgp.RF_IPv6_ENCAP:
   481  			nlri = bgp.NewEncapv6NLRI(v.Address)
   482  		}
   483  	case *api.EVPNEthernetAutoDiscoveryRoute:
   484  		if rf == bgp.RF_EVPN {
   485  			rd, err := UnmarshalRD(v.Rd)
   486  			if err != nil {
   487  				return nil, err
   488  			}
   489  			esi, err := unmarshalESI(v.Esi)
   490  			if err != nil {
   491  				return nil, err
   492  			}
   493  			nlri = bgp.NewEVPNEthernetAutoDiscoveryRoute(rd, *esi, v.EthernetTag, v.Label)
   494  		}
   495  	case *api.EVPNMACIPAdvertisementRoute:
   496  		if rf == bgp.RF_EVPN {
   497  			rd, err := UnmarshalRD(v.Rd)
   498  			if err != nil {
   499  				return nil, err
   500  			}
   501  			esi, err := unmarshalESI(v.Esi)
   502  			if err != nil {
   503  				return nil, err
   504  			}
   505  			nlri = bgp.NewEVPNMacIPAdvertisementRoute(rd, *esi, v.EthernetTag, v.MacAddress, v.IpAddress, v.Labels)
   506  		}
   507  	case *api.EVPNInclusiveMulticastEthernetTagRoute:
   508  		if rf == bgp.RF_EVPN {
   509  			rd, err := UnmarshalRD(v.Rd)
   510  			if err != nil {
   511  				return nil, err
   512  			}
   513  			nlri = bgp.NewEVPNMulticastEthernetTagRoute(rd, v.EthernetTag, v.IpAddress)
   514  		}
   515  	case *api.EVPNEthernetSegmentRoute:
   516  		if rf == bgp.RF_EVPN {
   517  			rd, err := UnmarshalRD(v.Rd)
   518  			if err != nil {
   519  				return nil, err
   520  			}
   521  			esi, err := unmarshalESI(v.Esi)
   522  			if err != nil {
   523  				return nil, err
   524  			}
   525  			nlri = bgp.NewEVPNEthernetSegmentRoute(rd, *esi, v.IpAddress)
   526  		}
   527  	case *api.EVPNIPPrefixRoute:
   528  		if rf == bgp.RF_EVPN {
   529  			rd, err := UnmarshalRD(v.Rd)
   530  			if err != nil {
   531  				return nil, err
   532  			}
   533  			esi, err := unmarshalESI(v.Esi)
   534  			if err != nil {
   535  				return nil, err
   536  			}
   537  			nlri = bgp.NewEVPNIPPrefixRoute(rd, *esi, v.EthernetTag, uint8(v.IpPrefixLen), v.IpPrefix, v.GwAddress, v.Label)
   538  		}
   539  	case *api.LabeledVPNIPAddressPrefix:
   540  		rd, err := UnmarshalRD(v.Rd)
   541  		if err != nil {
   542  			return nil, err
   543  		}
   544  		switch rf {
   545  		case bgp.RF_IPv4_VPN:
   546  			nlri = bgp.NewLabeledVPNIPAddrPrefix(uint8(v.PrefixLen), v.Prefix, *bgp.NewMPLSLabelStack(v.Labels...), rd)
   547  		case bgp.RF_IPv6_VPN:
   548  			nlri = bgp.NewLabeledVPNIPv6AddrPrefix(uint8(v.PrefixLen), v.Prefix, *bgp.NewMPLSLabelStack(v.Labels...), rd)
   549  		}
   550  	case *api.RouteTargetMembershipNLRI:
   551  		rt, err := UnmarshalRT(v.Rt)
   552  		if err != nil {
   553  			return nil, err
   554  		}
   555  		nlri = bgp.NewRouteTargetMembershipNLRI(v.As, rt)
   556  	case *api.FlowSpecNLRI:
   557  		rules, err := UnmarshalFlowSpecRules(v.Rules)
   558  		if err != nil {
   559  			return nil, err
   560  		}
   561  		switch rf {
   562  		case bgp.RF_FS_IPv4_UC:
   563  			nlri = bgp.NewFlowSpecIPv4Unicast(rules)
   564  		case bgp.RF_FS_IPv6_UC:
   565  			nlri = bgp.NewFlowSpecIPv6Unicast(rules)
   566  		}
   567  	case *api.VPNFlowSpecNLRI:
   568  		rd, err := UnmarshalRD(v.Rd)
   569  		if err != nil {
   570  			return nil, err
   571  		}
   572  		rules, err := UnmarshalFlowSpecRules(v.Rules)
   573  		if err != nil {
   574  			return nil, err
   575  		}
   576  		switch rf {
   577  		case bgp.RF_FS_IPv4_VPN:
   578  			nlri = bgp.NewFlowSpecIPv4VPN(rd, rules)
   579  		case bgp.RF_FS_IPv6_VPN:
   580  			nlri = bgp.NewFlowSpecIPv6VPN(rd, rules)
   581  		case bgp.RF_FS_L2_VPN:
   582  			nlri = bgp.NewFlowSpecL2VPN(rd, rules)
   583  		}
   584  	}
   585  
   586  	if nlri == nil {
   587  		return nil, fmt.Errorf("invalid nlri for %s family: %s", rf.String(), value.Message)
   588  	}
   589  
   590  	return nlri, nil
   591  }
   592  
   593  func UnmarshalNLRIs(rf bgp.RouteFamily, values []*any.Any) ([]bgp.AddrPrefixInterface, error) {
   594  	nlris := make([]bgp.AddrPrefixInterface, 0, len(values))
   595  	for _, an := range values {
   596  		nlri, err := UnmarshalNLRI(rf, an)
   597  		if err != nil {
   598  			return nil, err
   599  		}
   600  		nlris = append(nlris, nlri)
   601  	}
   602  	return nlris, nil
   603  }
   604  
   605  func NewMpReachNLRIAttributeFromNative(a *bgp.PathAttributeMpReachNLRI) *api.MpReachNLRIAttribute {
   606  	var nexthops []string
   607  	if a.SAFI == bgp.SAFI_FLOW_SPEC_UNICAST || a.SAFI == bgp.SAFI_FLOW_SPEC_VPN {
   608  		nexthops = nil
   609  	} else {
   610  		nexthops = []string{a.Nexthop.String()}
   611  		if a.LinkLocalNexthop != nil {
   612  			nexthops = append(nexthops, a.LinkLocalNexthop.String())
   613  		}
   614  	}
   615  	return &api.MpReachNLRIAttribute{
   616  		Family:   ToApiFamily(a.AFI, a.SAFI),
   617  		NextHops: nexthops,
   618  		Nlris:    MarshalNLRIs(a.Value),
   619  	}
   620  }
   621  
   622  func NewMpUnreachNLRIAttributeFromNative(a *bgp.PathAttributeMpUnreachNLRI) *api.MpUnreachNLRIAttribute {
   623  	return &api.MpUnreachNLRIAttribute{
   624  		Family: ToApiFamily(a.AFI, a.SAFI),
   625  		Nlris:  MarshalNLRIs(a.Value),
   626  	}
   627  }
   628  
   629  func MarshalRT(rt bgp.ExtendedCommunityInterface) *any.Any {
   630  	var r proto.Message
   631  	switch v := rt.(type) {
   632  	case *bgp.TwoOctetAsSpecificExtended:
   633  		r = &api.TwoOctetAsSpecificExtended{
   634  			IsTransitive: true,
   635  			SubType:      uint32(bgp.EC_SUBTYPE_ROUTE_TARGET),
   636  			As:           uint32(v.AS),
   637  			LocalAdmin:   uint32(v.LocalAdmin),
   638  		}
   639  	case *bgp.IPv4AddressSpecificExtended:
   640  		r = &api.IPv4AddressSpecificExtended{
   641  			IsTransitive: true,
   642  			SubType:      uint32(bgp.EC_SUBTYPE_ROUTE_TARGET),
   643  			Address:      v.IPv4.String(),
   644  			LocalAdmin:   uint32(v.LocalAdmin),
   645  		}
   646  	case *bgp.FourOctetAsSpecificExtended:
   647  		r = &api.FourOctetAsSpecificExtended{
   648  			IsTransitive: true,
   649  			SubType:      uint32(bgp.EC_SUBTYPE_ROUTE_TARGET),
   650  			As:           uint32(v.AS),
   651  			LocalAdmin:   uint32(v.LocalAdmin),
   652  		}
   653  	default:
   654  		log.WithFields(log.Fields{
   655  			"Topic": "protobuf",
   656  			"RT":    rt,
   657  		}).Warn("invalid rt type to marshal")
   658  		return nil
   659  	}
   660  	a, _ := ptypes.MarshalAny(r)
   661  	return a
   662  }
   663  
   664  func MarshalRTs(values []bgp.ExtendedCommunityInterface) []*any.Any {
   665  	rts := make([]*any.Any, 0, len(values))
   666  	for _, rt := range values {
   667  		rts = append(rts, MarshalRT(rt))
   668  	}
   669  	return rts
   670  }
   671  
   672  func UnmarshalRT(a *any.Any) (bgp.ExtendedCommunityInterface, error) {
   673  	var value ptypes.DynamicAny
   674  	if err := ptypes.UnmarshalAny(a, &value); err != nil {
   675  		return nil, fmt.Errorf("failed to unmarshal route target: %s", err)
   676  	}
   677  	switch v := value.Message.(type) {
   678  	case *api.TwoOctetAsSpecificExtended:
   679  		return bgp.NewTwoOctetAsSpecificExtended(bgp.ExtendedCommunityAttrSubType(v.SubType), uint16(v.As), v.LocalAdmin, v.IsTransitive), nil
   680  	case *api.IPv4AddressSpecificExtended:
   681  		rt := bgp.NewIPv4AddressSpecificExtended(bgp.ExtendedCommunityAttrSubType(v.SubType), v.Address, uint16(v.LocalAdmin), v.IsTransitive)
   682  		if rt == nil {
   683  			return nil, fmt.Errorf("invalid address for ipv4 address specific route target: %s", v.Address)
   684  		}
   685  		return rt, nil
   686  	case *api.FourOctetAsSpecificExtended:
   687  		return bgp.NewFourOctetAsSpecificExtended(bgp.ExtendedCommunityAttrSubType(v.SubType), v.As, uint16(v.LocalAdmin), v.IsTransitive), nil
   688  	}
   689  	return nil, fmt.Errorf("invalid route target type: %s", a.TypeUrl)
   690  }
   691  
   692  func UnmarshalRTs(values []*any.Any) ([]bgp.ExtendedCommunityInterface, error) {
   693  	rts := make([]bgp.ExtendedCommunityInterface, 0, len(values))
   694  	for _, an := range values {
   695  		rt, err := UnmarshalRT(an)
   696  		if err != nil {
   697  			return nil, err
   698  		}
   699  		rts = append(rts, rt)
   700  	}
   701  	return rts, nil
   702  }
   703  
   704  func NewExtendedCommunitiesAttributeFromNative(a *bgp.PathAttributeExtendedCommunities) *api.ExtendedCommunitiesAttribute {
   705  	communities := make([]*any.Any, 0, len(a.Value))
   706  	for _, value := range a.Value {
   707  		var community proto.Message
   708  		switch v := value.(type) {
   709  		case *bgp.TwoOctetAsSpecificExtended:
   710  			community = &api.TwoOctetAsSpecificExtended{
   711  				IsTransitive: v.IsTransitive,
   712  				SubType:      uint32(v.SubType),
   713  				As:           uint32(v.AS),
   714  				LocalAdmin:   uint32(v.LocalAdmin),
   715  			}
   716  		case *bgp.IPv4AddressSpecificExtended:
   717  			community = &api.IPv4AddressSpecificExtended{
   718  				IsTransitive: v.IsTransitive,
   719  				SubType:      uint32(v.SubType),
   720  				Address:      v.IPv4.String(),
   721  				LocalAdmin:   uint32(v.LocalAdmin),
   722  			}
   723  		case *bgp.FourOctetAsSpecificExtended:
   724  			community = &api.FourOctetAsSpecificExtended{
   725  				IsTransitive: v.IsTransitive,
   726  				SubType:      uint32(v.SubType),
   727  				As:           uint32(v.AS),
   728  				LocalAdmin:   uint32(v.LocalAdmin),
   729  			}
   730  		case *bgp.ValidationExtended:
   731  			community = &api.ValidationExtended{
   732  				State: uint32(v.State),
   733  			}
   734  		case *bgp.ColorExtended:
   735  			community = &api.ColorExtended{
   736  				Color: v.Color,
   737  			}
   738  		case *bgp.EncapExtended:
   739  			community = &api.EncapExtended{
   740  				TunnelType: uint32(v.TunnelType),
   741  			}
   742  		case *bgp.DefaultGatewayExtended:
   743  			community = &api.DefaultGatewayExtended{}
   744  		case *bgp.OpaqueExtended:
   745  			community = &api.OpaqueExtended{
   746  				IsTransitive: v.IsTransitive,
   747  				Value:        v.Value,
   748  			}
   749  		case *bgp.ESILabelExtended:
   750  			community = &api.ESILabelExtended{
   751  				IsSingleActive: v.IsSingleActive,
   752  				Label:          v.Label,
   753  			}
   754  		case *bgp.ESImportRouteTarget:
   755  			community = &api.ESImportRouteTarget{
   756  				EsImport: v.ESImport.String(),
   757  			}
   758  		case *bgp.MacMobilityExtended:
   759  			community = &api.MacMobilityExtended{
   760  				IsSticky:    v.IsSticky,
   761  				SequenceNum: v.Sequence,
   762  			}
   763  		case *bgp.RouterMacExtended:
   764  			community = &api.RouterMacExtended{
   765  				Mac: v.Mac.String(),
   766  			}
   767  		case *bgp.TrafficRateExtended:
   768  			community = &api.TrafficRateExtended{
   769  				As:   uint32(v.AS),
   770  				Rate: v.Rate,
   771  			}
   772  		case *bgp.TrafficActionExtended:
   773  			community = &api.TrafficActionExtended{
   774  				Terminal: v.Terminal,
   775  				Sample:   v.Sample,
   776  			}
   777  		case *bgp.RedirectTwoOctetAsSpecificExtended:
   778  			community = &api.RedirectTwoOctetAsSpecificExtended{
   779  				As:         uint32(v.AS),
   780  				LocalAdmin: v.LocalAdmin,
   781  			}
   782  		case *bgp.RedirectIPv4AddressSpecificExtended:
   783  			community = &api.RedirectIPv4AddressSpecificExtended{
   784  				Address:    v.IPv4.String(),
   785  				LocalAdmin: uint32(v.LocalAdmin),
   786  			}
   787  		case *bgp.RedirectFourOctetAsSpecificExtended:
   788  			community = &api.RedirectFourOctetAsSpecificExtended{
   789  				As:         v.AS,
   790  				LocalAdmin: uint32(v.LocalAdmin),
   791  			}
   792  		case *bgp.TrafficRemarkExtended:
   793  			community = &api.TrafficRemarkExtended{
   794  				Dscp: uint32(v.DSCP),
   795  			}
   796  		case *bgp.UnknownExtended:
   797  			community = &api.UnknownExtended{
   798  				Type:  uint32(v.Type),
   799  				Value: v.Value,
   800  			}
   801  		default:
   802  			log.WithFields(log.Fields{
   803  				"Topic":     "protobuf",
   804  				"Community": value,
   805  			}).Warn("unsupported extended community")
   806  			return nil
   807  		}
   808  		an, _ := ptypes.MarshalAny(community)
   809  		communities = append(communities, an)
   810  	}
   811  	return &api.ExtendedCommunitiesAttribute{
   812  		Communities: communities,
   813  	}
   814  }
   815  
   816  func unmarshalExComm(a *api.ExtendedCommunitiesAttribute) (*bgp.PathAttributeExtendedCommunities, error) {
   817  	communities := make([]bgp.ExtendedCommunityInterface, 0, len(a.Communities))
   818  	for _, an := range a.Communities {
   819  		var community bgp.ExtendedCommunityInterface
   820  		var value ptypes.DynamicAny
   821  		if err := ptypes.UnmarshalAny(an, &value); err != nil {
   822  			return nil, fmt.Errorf("failed to unmarshal extended community: %s", err)
   823  		}
   824  		switch v := value.Message.(type) {
   825  		case *api.TwoOctetAsSpecificExtended:
   826  			community = bgp.NewTwoOctetAsSpecificExtended(bgp.ExtendedCommunityAttrSubType(v.SubType), uint16(v.As), v.LocalAdmin, v.IsTransitive)
   827  		case *api.IPv4AddressSpecificExtended:
   828  			community = bgp.NewIPv4AddressSpecificExtended(bgp.ExtendedCommunityAttrSubType(v.SubType), v.Address, uint16(v.LocalAdmin), v.IsTransitive)
   829  		case *api.FourOctetAsSpecificExtended:
   830  			community = bgp.NewFourOctetAsSpecificExtended(bgp.ExtendedCommunityAttrSubType(v.SubType), v.As, uint16(v.LocalAdmin), v.IsTransitive)
   831  		case *api.ValidationExtended:
   832  			community = bgp.NewValidationExtended(bgp.ValidationState(v.State))
   833  		case *api.ColorExtended:
   834  			community = bgp.NewColorExtended(v.Color)
   835  		case *api.EncapExtended:
   836  			community = bgp.NewEncapExtended(bgp.TunnelType(v.TunnelType))
   837  		case *api.DefaultGatewayExtended:
   838  			community = bgp.NewDefaultGatewayExtended()
   839  		case *api.OpaqueExtended:
   840  			community = bgp.NewOpaqueExtended(v.IsTransitive, v.Value)
   841  		case *api.ESILabelExtended:
   842  			community = bgp.NewESILabelExtended(v.Label, v.IsSingleActive)
   843  		case *api.ESImportRouteTarget:
   844  			community = bgp.NewESImportRouteTarget(v.EsImport)
   845  		case *api.MacMobilityExtended:
   846  			community = bgp.NewMacMobilityExtended(v.SequenceNum, v.IsSticky)
   847  		case *api.RouterMacExtended:
   848  			community = bgp.NewRoutersMacExtended(v.Mac)
   849  		case *api.TrafficRateExtended:
   850  			community = bgp.NewTrafficRateExtended(uint16(v.As), v.Rate)
   851  		case *api.TrafficActionExtended:
   852  			community = bgp.NewTrafficActionExtended(v.Terminal, v.Sample)
   853  		case *api.RedirectTwoOctetAsSpecificExtended:
   854  			community = bgp.NewRedirectTwoOctetAsSpecificExtended(uint16(v.As), v.LocalAdmin)
   855  		case *api.RedirectIPv4AddressSpecificExtended:
   856  			community = bgp.NewRedirectIPv4AddressSpecificExtended(v.Address, uint16(v.LocalAdmin))
   857  		case *api.RedirectFourOctetAsSpecificExtended:
   858  			community = bgp.NewRedirectFourOctetAsSpecificExtended(v.As, uint16(v.LocalAdmin))
   859  		case *api.TrafficRemarkExtended:
   860  			community = bgp.NewTrafficRemarkExtended(uint8(v.Dscp))
   861  		case *api.UnknownExtended:
   862  			community = bgp.NewUnknownExtended(bgp.ExtendedCommunityAttrType(v.Type), v.Value)
   863  		}
   864  		if community == nil {
   865  			return nil, fmt.Errorf("invalid extended community: %v", value.Message)
   866  		}
   867  		communities = append(communities, community)
   868  	}
   869  	return bgp.NewPathAttributeExtendedCommunities(communities), nil
   870  }
   871  
   872  func NewAs4PathAttributeFromNative(a *bgp.PathAttributeAs4Path) *api.As4PathAttribute {
   873  	segments := make([]*api.AsSegment, 0, len(a.Value))
   874  	for _, param := range a.Value {
   875  		segments = append(segments, &api.AsSegment{
   876  			Type:    uint32(param.Type),
   877  			Numbers: param.AS,
   878  		})
   879  	}
   880  	return &api.As4PathAttribute{
   881  		Segments: segments,
   882  	}
   883  }
   884  
   885  func NewAs4AggregatorAttributeFromNative(a *bgp.PathAttributeAs4Aggregator) *api.As4AggregatorAttribute {
   886  	return &api.As4AggregatorAttribute{
   887  		As:      a.Value.AS,
   888  		Address: a.Value.Address.String(),
   889  	}
   890  }
   891  
   892  func NewPmsiTunnelAttributeFromNative(a *bgp.PathAttributePmsiTunnel) *api.PmsiTunnelAttribute {
   893  	var flags uint32
   894  	if a.IsLeafInfoRequired {
   895  		flags |= 0x01
   896  	}
   897  	id, _ := a.TunnelID.Serialize()
   898  	return &api.PmsiTunnelAttribute{
   899  		Flags: flags,
   900  		Type:  uint32(a.TunnelType),
   901  		Label: a.Label,
   902  		Id:    id,
   903  	}
   904  }
   905  
   906  func NewTunnelEncapAttributeFromNative(a *bgp.PathAttributeTunnelEncap) *api.TunnelEncapAttribute {
   907  	tlvs := make([]*api.TunnelEncapTLV, 0, len(a.Value))
   908  	for _, v := range a.Value {
   909  		subTlvs := make([]*any.Any, 0, len(v.Value))
   910  		for _, s := range v.Value {
   911  			var subTlv proto.Message
   912  			switch sv := s.(type) {
   913  			case *bgp.TunnelEncapSubTLVEncapsulation:
   914  				subTlv = &api.TunnelEncapSubTLVEncapsulation{
   915  					Key:    sv.Key,
   916  					Cookie: sv.Cookie,
   917  				}
   918  			case *bgp.TunnelEncapSubTLVProtocol:
   919  				subTlv = &api.TunnelEncapSubTLVProtocol{
   920  					Protocol: uint32(sv.Protocol),
   921  				}
   922  			case *bgp.TunnelEncapSubTLVColor:
   923  				subTlv = &api.TunnelEncapSubTLVColor{
   924  					Color: sv.Color,
   925  				}
   926  			case *bgp.TunnelEncapSubTLVUnknown:
   927  				subTlv = &api.TunnelEncapSubTLVUnknown{
   928  					Type:  uint32(sv.Type),
   929  					Value: sv.Value,
   930  				}
   931  			}
   932  			an, _ := ptypes.MarshalAny(subTlv)
   933  			subTlvs = append(subTlvs, an)
   934  		}
   935  		tlvs = append(tlvs, &api.TunnelEncapTLV{
   936  			Type: uint32(v.Type),
   937  			Tlvs: subTlvs,
   938  		})
   939  	}
   940  	return &api.TunnelEncapAttribute{
   941  		Tlvs: tlvs,
   942  	}
   943  }
   944  
   945  func NewIP6ExtendedCommunitiesAttributeFromNative(a *bgp.PathAttributeIP6ExtendedCommunities) *api.IP6ExtendedCommunitiesAttribute {
   946  	communities := make([]*any.Any, 0, len(a.Value))
   947  	for _, value := range a.Value {
   948  		var community proto.Message
   949  		switch v := value.(type) {
   950  		case *bgp.IPv6AddressSpecificExtended:
   951  			community = &api.IPv6AddressSpecificExtended{
   952  				IsTransitive: v.IsTransitive,
   953  				SubType:      uint32(v.SubType),
   954  				Address:      v.IPv6.String(),
   955  				LocalAdmin:   uint32(v.LocalAdmin),
   956  			}
   957  		case *bgp.RedirectIPv6AddressSpecificExtended:
   958  			community = &api.RedirectIPv6AddressSpecificExtended{
   959  				Address:    v.IPv6.String(),
   960  				LocalAdmin: uint32(v.LocalAdmin),
   961  			}
   962  		default:
   963  			log.WithFields(log.Fields{
   964  				"Topic":     "protobuf",
   965  				"Attribute": value,
   966  			}).Warn("invalid ipv6 extended community")
   967  			return nil
   968  		}
   969  		an, _ := ptypes.MarshalAny(community)
   970  		communities = append(communities, an)
   971  	}
   972  	return &api.IP6ExtendedCommunitiesAttribute{
   973  		Communities: communities,
   974  	}
   975  }
   976  
   977  func NewAigpAttributeFromNative(a *bgp.PathAttributeAigp) *api.AigpAttribute {
   978  	tlvs := make([]*any.Any, 0, len(a.Values))
   979  	for _, value := range a.Values {
   980  		var tlv proto.Message
   981  		switch v := value.(type) {
   982  		case *bgp.AigpTLVIgpMetric:
   983  			tlv = &api.AigpTLVIGPMetric{
   984  				Metric: v.Metric,
   985  			}
   986  		case *bgp.AigpTLVDefault:
   987  			tlv = &api.AigpTLVUnknown{
   988  				Type:  uint32(v.Type()),
   989  				Value: v.Value,
   990  			}
   991  		}
   992  		an, _ := ptypes.MarshalAny(tlv)
   993  		tlvs = append(tlvs, an)
   994  	}
   995  	return &api.AigpAttribute{
   996  		Tlvs: tlvs,
   997  	}
   998  }
   999  
  1000  func NewLargeCommunitiesAttributeFromNative(a *bgp.PathAttributeLargeCommunities) *api.LargeCommunitiesAttribute {
  1001  	communities := make([]*api.LargeCommunity, 0, len(a.Values))
  1002  	for _, v := range a.Values {
  1003  		communities = append(communities, &api.LargeCommunity{
  1004  			GlobalAdmin: v.ASN,
  1005  			LocalData1:  v.LocalData1,
  1006  			LocalData2:  v.LocalData2,
  1007  		})
  1008  	}
  1009  	return &api.LargeCommunitiesAttribute{
  1010  		Communities: communities,
  1011  	}
  1012  }
  1013  
  1014  func NewUnknownAttributeFromNative(a *bgp.PathAttributeUnknown) *api.UnknownAttribute {
  1015  	return &api.UnknownAttribute{
  1016  		Flags: uint32(a.Flags),
  1017  		Type:  uint32(a.Type),
  1018  		Value: a.Value,
  1019  	}
  1020  }
  1021  
  1022  func MarshalPathAttributes(attrList []bgp.PathAttributeInterface) []*any.Any {
  1023  	anyList := make([]*any.Any, 0, len(attrList))
  1024  	for _, attr := range attrList {
  1025  		switch a := attr.(type) {
  1026  		case *bgp.PathAttributeOrigin:
  1027  			n, _ := ptypes.MarshalAny(NewOriginAttributeFromNative(a))
  1028  			anyList = append(anyList, n)
  1029  		case *bgp.PathAttributeAsPath:
  1030  			n, _ := ptypes.MarshalAny(NewAsPathAttributeFromNative(a))
  1031  			anyList = append(anyList, n)
  1032  		case *bgp.PathAttributeNextHop:
  1033  			n, _ := ptypes.MarshalAny(NewNextHopAttributeFromNative(a))
  1034  			anyList = append(anyList, n)
  1035  		case *bgp.PathAttributeMultiExitDisc:
  1036  			n, _ := ptypes.MarshalAny(NewMultiExitDiscAttributeFromNative(a))
  1037  			anyList = append(anyList, n)
  1038  		case *bgp.PathAttributeLocalPref:
  1039  			n, _ := ptypes.MarshalAny(NewLocalPrefAttributeFromNative(a))
  1040  			anyList = append(anyList, n)
  1041  		case *bgp.PathAttributeAtomicAggregate:
  1042  			n, _ := ptypes.MarshalAny(NewAtomicAggregateAttributeFromNative(a))
  1043  			anyList = append(anyList, n)
  1044  		case *bgp.PathAttributeAggregator:
  1045  			n, _ := ptypes.MarshalAny(NewAggregatorAttributeFromNative(a))
  1046  			anyList = append(anyList, n)
  1047  		case *bgp.PathAttributeCommunities:
  1048  			n, _ := ptypes.MarshalAny(NewCommunitiesAttributeFromNative(a))
  1049  			anyList = append(anyList, n)
  1050  		case *bgp.PathAttributeOriginatorId:
  1051  			n, _ := ptypes.MarshalAny(NewOriginatorIdAttributeFromNative(a))
  1052  			anyList = append(anyList, n)
  1053  		case *bgp.PathAttributeClusterList:
  1054  			n, _ := ptypes.MarshalAny(NewClusterListAttributeFromNative(a))
  1055  			anyList = append(anyList, n)
  1056  		case *bgp.PathAttributeMpReachNLRI:
  1057  			n, _ := ptypes.MarshalAny(NewMpReachNLRIAttributeFromNative(a))
  1058  			anyList = append(anyList, n)
  1059  		case *bgp.PathAttributeMpUnreachNLRI:
  1060  			n, _ := ptypes.MarshalAny(NewMpUnreachNLRIAttributeFromNative(a))
  1061  			anyList = append(anyList, n)
  1062  		case *bgp.PathAttributeExtendedCommunities:
  1063  			n, _ := ptypes.MarshalAny(NewExtendedCommunitiesAttributeFromNative(a))
  1064  			anyList = append(anyList, n)
  1065  		case *bgp.PathAttributeAs4Path:
  1066  			n, _ := ptypes.MarshalAny(NewAs4PathAttributeFromNative(a))
  1067  			anyList = append(anyList, n)
  1068  		case *bgp.PathAttributeAs4Aggregator:
  1069  			n, _ := ptypes.MarshalAny(NewAs4AggregatorAttributeFromNative(a))
  1070  			anyList = append(anyList, n)
  1071  		case *bgp.PathAttributePmsiTunnel:
  1072  			n, _ := ptypes.MarshalAny(NewPmsiTunnelAttributeFromNative(a))
  1073  			anyList = append(anyList, n)
  1074  		case *bgp.PathAttributeTunnelEncap:
  1075  			n, _ := ptypes.MarshalAny(NewTunnelEncapAttributeFromNative(a))
  1076  			anyList = append(anyList, n)
  1077  		case *bgp.PathAttributeIP6ExtendedCommunities:
  1078  			n, _ := ptypes.MarshalAny(NewIP6ExtendedCommunitiesAttributeFromNative(a))
  1079  			anyList = append(anyList, n)
  1080  		case *bgp.PathAttributeAigp:
  1081  			n, _ := ptypes.MarshalAny(NewAigpAttributeFromNative(a))
  1082  			anyList = append(anyList, n)
  1083  		case *bgp.PathAttributeLargeCommunities:
  1084  			n, _ := ptypes.MarshalAny(NewLargeCommunitiesAttributeFromNative(a))
  1085  			anyList = append(anyList, n)
  1086  		case *bgp.PathAttributeUnknown:
  1087  			n, _ := ptypes.MarshalAny(NewUnknownAttributeFromNative(a))
  1088  			anyList = append(anyList, n)
  1089  		}
  1090  	}
  1091  	return anyList
  1092  }
  1093  
  1094  func UnmarshalPathAttributes(values []*any.Any) ([]bgp.PathAttributeInterface, error) {
  1095  	attrList := make([]bgp.PathAttributeInterface, 0, len(values))
  1096  	typeMap := make(map[bgp.BGPAttrType]struct{})
  1097  	for _, an := range values {
  1098  		attr, err := unmarshalAttribute(an)
  1099  		if err != nil {
  1100  			return nil, err
  1101  		}
  1102  		if _, ok := typeMap[attr.GetType()]; ok {
  1103  			return nil, fmt.Errorf("duplicated path attribute type: %d", attr.GetType())
  1104  		}
  1105  		typeMap[attr.GetType()] = struct{}{}
  1106  		attrList = append(attrList, attr)
  1107  	}
  1108  	return attrList, nil
  1109  }
  1110  
  1111  func unmarshalAttribute(an *any.Any) (bgp.PathAttributeInterface, error) {
  1112  	var value ptypes.DynamicAny
  1113  	if err := ptypes.UnmarshalAny(an, &value); err != nil {
  1114  		return nil, fmt.Errorf("failed to unmarshal route distinguisher: %s", err)
  1115  	}
  1116  	switch a := value.Message.(type) {
  1117  	case *api.OriginAttribute:
  1118  		return bgp.NewPathAttributeOrigin(uint8(a.Origin)), nil
  1119  	case *api.AsPathAttribute:
  1120  		params := make([]bgp.AsPathParamInterface, 0, len(a.Segments))
  1121  		for _, segment := range a.Segments {
  1122  			params = append(params, bgp.NewAs4PathParam(uint8(segment.Type), segment.Numbers))
  1123  		}
  1124  		return bgp.NewPathAttributeAsPath(params), nil
  1125  	case *api.NextHopAttribute:
  1126  		nexthop := net.ParseIP(a.NextHop).To4()
  1127  		if nexthop == nil {
  1128  			return nil, fmt.Errorf("invalid nexthop address: %s", a.NextHop)
  1129  		}
  1130  		return bgp.NewPathAttributeNextHop(a.NextHop), nil
  1131  	case *api.MultiExitDiscAttribute:
  1132  		return bgp.NewPathAttributeMultiExitDisc(a.Med), nil
  1133  	case *api.LocalPrefAttribute:
  1134  		return bgp.NewPathAttributeLocalPref(a.LocalPref), nil
  1135  	case *api.AtomicAggregateAttribute:
  1136  		return bgp.NewPathAttributeAtomicAggregate(), nil
  1137  	case *api.AggregatorAttribute:
  1138  		if net.ParseIP(a.Address).To4() == nil {
  1139  			return nil, fmt.Errorf("invalid aggregator address: %s", a.Address)
  1140  		}
  1141  		return bgp.NewPathAttributeAggregator(a.As, a.Address), nil
  1142  	case *api.CommunitiesAttribute:
  1143  		return bgp.NewPathAttributeCommunities(a.Communities), nil
  1144  	case *api.OriginatorIdAttribute:
  1145  		if net.ParseIP(a.Id).To4() == nil {
  1146  			return nil, fmt.Errorf("invalid originator id: %s", a.Id)
  1147  		}
  1148  		return bgp.NewPathAttributeOriginatorId(a.Id), nil
  1149  	case *api.ClusterListAttribute:
  1150  		for _, id := range a.Ids {
  1151  			if net.ParseIP(id).To4() == nil {
  1152  				return nil, fmt.Errorf("invalid cluster list: %s", a.Ids)
  1153  			}
  1154  		}
  1155  		return bgp.NewPathAttributeClusterList(a.Ids), nil
  1156  	case *api.MpReachNLRIAttribute:
  1157  		rf := ToRouteFamily(a.Family)
  1158  		nlris, err := UnmarshalNLRIs(rf, a.Nlris)
  1159  		if err != nil {
  1160  			return nil, err
  1161  		}
  1162  		afi, safi := bgp.RouteFamilyToAfiSafi(rf)
  1163  		nexthop := "0.0.0.0"
  1164  		var linkLocalNexthop net.IP
  1165  		if afi == bgp.AFI_IP6 {
  1166  			nexthop = "::"
  1167  			if len(a.NextHops) > 1 {
  1168  				linkLocalNexthop = net.ParseIP(a.NextHops[1]).To16()
  1169  				if linkLocalNexthop == nil {
  1170  					return nil, fmt.Errorf("invalid nexthop: %s", a.NextHops[1])
  1171  				}
  1172  			}
  1173  		}
  1174  		if safi == bgp.SAFI_FLOW_SPEC_UNICAST || safi == bgp.SAFI_FLOW_SPEC_VPN {
  1175  			nexthop = ""
  1176  		} else if len(a.NextHops) > 0 {
  1177  			nexthop = a.NextHops[0]
  1178  			if net.ParseIP(nexthop) == nil {
  1179  				return nil, fmt.Errorf("invalid nexthop: %s", nexthop)
  1180  			}
  1181  		}
  1182  		attr := bgp.NewPathAttributeMpReachNLRI(nexthop, nlris)
  1183  		attr.LinkLocalNexthop = linkLocalNexthop
  1184  		return attr, nil
  1185  	case *api.MpUnreachNLRIAttribute:
  1186  		rf := ToRouteFamily(a.Family)
  1187  		nlris, err := UnmarshalNLRIs(rf, a.Nlris)
  1188  		if err != nil {
  1189  			return nil, err
  1190  		}
  1191  		return bgp.NewPathAttributeMpUnreachNLRI(nlris), nil
  1192  	case *api.ExtendedCommunitiesAttribute:
  1193  		return unmarshalExComm(a)
  1194  	case *api.As4PathAttribute:
  1195  		params := make([]*bgp.As4PathParam, 0, len(a.Segments))
  1196  		for _, segment := range a.Segments {
  1197  			params = append(params, bgp.NewAs4PathParam(uint8(segment.Type), segment.Numbers))
  1198  		}
  1199  		return bgp.NewPathAttributeAs4Path(params), nil
  1200  	case *api.As4AggregatorAttribute:
  1201  		if net.ParseIP(a.Address).To4() == nil {
  1202  			return nil, fmt.Errorf("invalid as4 aggregator address: %s", a.Address)
  1203  		}
  1204  		return bgp.NewPathAttributeAs4Aggregator(a.As, a.Address), nil
  1205  	case *api.PmsiTunnelAttribute:
  1206  		typ := bgp.PmsiTunnelType(a.Type)
  1207  		var isLeafInfoRequired bool
  1208  		if a.Flags&0x01 > 0 {
  1209  			isLeafInfoRequired = true
  1210  		}
  1211  		var id bgp.PmsiTunnelIDInterface
  1212  		switch typ {
  1213  		case bgp.PMSI_TUNNEL_TYPE_INGRESS_REPL:
  1214  			ip := net.IP(a.Id)
  1215  			if ip.To4() == nil && ip.To16() == nil {
  1216  				return nil, fmt.Errorf("invalid pmsi tunnel identifier: %s", a.Id)
  1217  			}
  1218  			id = bgp.NewIngressReplTunnelID(ip.String())
  1219  		default:
  1220  			id = bgp.NewDefaultPmsiTunnelID(a.Id)
  1221  		}
  1222  		return bgp.NewPathAttributePmsiTunnel(typ, isLeafInfoRequired, a.Label, id), nil
  1223  	case *api.TunnelEncapAttribute:
  1224  		tlvs := make([]*bgp.TunnelEncapTLV, 0, len(a.Tlvs))
  1225  		for _, tlv := range a.Tlvs {
  1226  			subTlvs := make([]bgp.TunnelEncapSubTLVInterface, 0, len(tlv.Tlvs))
  1227  			for _, an := range tlv.Tlvs {
  1228  				var subTlv bgp.TunnelEncapSubTLVInterface
  1229  				var subValue ptypes.DynamicAny
  1230  				if err := ptypes.UnmarshalAny(an, &subValue); err != nil {
  1231  					return nil, fmt.Errorf("failed to unmarshal tunnel encapsulation attribute sub tlv: %s", err)
  1232  				}
  1233  				switch sv := subValue.Message.(type) {
  1234  				case *api.TunnelEncapSubTLVEncapsulation:
  1235  					subTlv = bgp.NewTunnelEncapSubTLVEncapsulation(sv.Key, sv.Cookie)
  1236  				case *api.TunnelEncapSubTLVProtocol:
  1237  					subTlv = bgp.NewTunnelEncapSubTLVProtocol(uint16(sv.Protocol))
  1238  				case *api.TunnelEncapSubTLVColor:
  1239  					subTlv = bgp.NewTunnelEncapSubTLVColor(sv.Color)
  1240  				case *api.TunnelEncapSubTLVUnknown:
  1241  					subTlv = bgp.NewTunnelEncapSubTLVUnknown(bgp.EncapSubTLVType(sv.Type), sv.Value)
  1242  				default:
  1243  					return nil, fmt.Errorf("invalid tunnel encapsulation attribute sub tlv: %v", subValue.Message)
  1244  				}
  1245  				subTlvs = append(subTlvs, subTlv)
  1246  			}
  1247  			tlvs = append(tlvs, bgp.NewTunnelEncapTLV(bgp.TunnelType(tlv.Type), subTlvs))
  1248  		}
  1249  		return bgp.NewPathAttributeTunnelEncap(tlvs), nil
  1250  	case *api.IP6ExtendedCommunitiesAttribute:
  1251  		communities := make([]bgp.ExtendedCommunityInterface, 0, len(a.Communities))
  1252  		for _, an := range a.Communities {
  1253  			var community bgp.ExtendedCommunityInterface
  1254  			var value ptypes.DynamicAny
  1255  			if err := ptypes.UnmarshalAny(an, &value); err != nil {
  1256  				return nil, fmt.Errorf("failed to unmarshal ipv6 extended community: %s", err)
  1257  			}
  1258  			switch v := value.Message.(type) {
  1259  			case *api.IPv6AddressSpecificExtended:
  1260  				community = bgp.NewIPv6AddressSpecificExtended(bgp.ExtendedCommunityAttrSubType(v.SubType), v.Address, uint16(v.LocalAdmin), v.IsTransitive)
  1261  			case *api.RedirectIPv6AddressSpecificExtended:
  1262  				community = bgp.NewRedirectIPv6AddressSpecificExtended(v.Address, uint16(v.LocalAdmin))
  1263  			}
  1264  			if community == nil {
  1265  				return nil, fmt.Errorf("invalid ipv6 extended community: %v", value.Message)
  1266  			}
  1267  			communities = append(communities, community)
  1268  		}
  1269  		return bgp.NewPathAttributeIP6ExtendedCommunities(communities), nil
  1270  
  1271  	case *api.AigpAttribute:
  1272  		tlvs := make([]bgp.AigpTLVInterface, 0, len(a.Tlvs))
  1273  		for _, an := range a.Tlvs {
  1274  			var tlv bgp.AigpTLVInterface
  1275  			var value ptypes.DynamicAny
  1276  			if err := ptypes.UnmarshalAny(an, &value); err != nil {
  1277  				return nil, fmt.Errorf("failed to unmarshal aigp attribute tlv: %s", err)
  1278  			}
  1279  			switch v := value.Message.(type) {
  1280  			case *api.AigpTLVIGPMetric:
  1281  				tlv = bgp.NewAigpTLVIgpMetric(v.Metric)
  1282  			case *api.AigpTLVUnknown:
  1283  				tlv = bgp.NewAigpTLVDefault(bgp.AigpTLVType(v.Type), v.Value)
  1284  			}
  1285  			if tlv == nil {
  1286  				return nil, fmt.Errorf("invalid aigp attribute tlv: %v", value.Message)
  1287  			}
  1288  			tlvs = append(tlvs, tlv)
  1289  		}
  1290  		return bgp.NewPathAttributeAigp(tlvs), nil
  1291  
  1292  	case *api.LargeCommunitiesAttribute:
  1293  		communities := make([]*bgp.LargeCommunity, 0, len(a.Communities))
  1294  		for _, c := range a.Communities {
  1295  			communities = append(communities, bgp.NewLargeCommunity(c.GlobalAdmin, c.LocalData1, c.LocalData2))
  1296  		}
  1297  		return bgp.NewPathAttributeLargeCommunities(communities), nil
  1298  
  1299  	case *api.UnknownAttribute:
  1300  		return bgp.NewPathAttributeUnknown(bgp.BGPAttrFlag(a.Flags), bgp.BGPAttrType(a.Type), a.Value), nil
  1301  	}
  1302  	return nil, errors.New("unknown path attribute")
  1303  }