github.com/osrg/gobgp/v3@v3.30.0/internal/pkg/table/path.go (about)

     1  // Copyright (C) 2014 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 table
    17  
    18  import (
    19  	"bytes"
    20  	"encoding/json"
    21  	"fmt"
    22  	"math"
    23  	"net"
    24  	"sort"
    25  	"time"
    26  
    27  	"github.com/osrg/gobgp/v3/pkg/config/oc"
    28  	"github.com/osrg/gobgp/v3/pkg/log"
    29  	"github.com/osrg/gobgp/v3/pkg/packet/bgp"
    30  )
    31  
    32  const (
    33  	DEFAULT_LOCAL_PREF = 100
    34  )
    35  
    36  type Bitmap struct {
    37  	bitmap []uint64
    38  }
    39  
    40  func (b *Bitmap) Flag(i uint) {
    41  	b.bitmap[i/64] |= 1 << uint(i%64)
    42  }
    43  
    44  func (b *Bitmap) Unflag(i uint) {
    45  	b.bitmap[i/64] &^= 1 << uint(i%64)
    46  }
    47  
    48  func (b *Bitmap) GetFlag(i uint) bool {
    49  	return b.bitmap[i/64]&(1<<uint(i%64)) > 0
    50  }
    51  
    52  func (b *Bitmap) FindandSetZeroBit() (uint, error) {
    53  	for i := 0; i < len(b.bitmap); i++ {
    54  		if b.bitmap[i] == math.MaxUint64 {
    55  			continue
    56  		}
    57  		// replace this with TrailingZero64() when gobgp drops go 1.8 support.
    58  		for j := 0; j < 64; j++ {
    59  			v := ^b.bitmap[i]
    60  			if v&(1<<uint64(j)) > 0 {
    61  				r := i*64 + j
    62  				b.Flag(uint(r))
    63  				return uint(r), nil
    64  			}
    65  		}
    66  	}
    67  	return 0, fmt.Errorf("no space")
    68  }
    69  
    70  func (b *Bitmap) Expand() {
    71  	old := b.bitmap
    72  	new := make([]uint64, len(old)+1)
    73  	copy(new, old)
    74  	b.bitmap = new
    75  }
    76  
    77  func NewBitmap(size int) *Bitmap {
    78  	b := &Bitmap{}
    79  	if size != 0 {
    80  		b.bitmap = make([]uint64, (size+64-1)/64)
    81  	}
    82  	return b
    83  }
    84  
    85  type originInfo struct {
    86  	nlri               bgp.AddrPrefixInterface
    87  	source             *PeerInfo
    88  	timestamp          int64
    89  	noImplicitWithdraw bool
    90  	isFromExternal     bool
    91  	eor                bool
    92  	stale              bool
    93  }
    94  
    95  type RpkiValidationReasonType string
    96  
    97  const (
    98  	RPKI_VALIDATION_REASON_TYPE_NONE   RpkiValidationReasonType = "none"
    99  	RPKI_VALIDATION_REASON_TYPE_AS     RpkiValidationReasonType = "as"
   100  	RPKI_VALIDATION_REASON_TYPE_LENGTH RpkiValidationReasonType = "length"
   101  )
   102  
   103  var RpkiValidationReasonTypeToIntMap = map[RpkiValidationReasonType]int{
   104  	RPKI_VALIDATION_REASON_TYPE_NONE:   0,
   105  	RPKI_VALIDATION_REASON_TYPE_AS:     1,
   106  	RPKI_VALIDATION_REASON_TYPE_LENGTH: 2,
   107  }
   108  
   109  func (v RpkiValidationReasonType) ToInt() int {
   110  	i, ok := RpkiValidationReasonTypeToIntMap[v]
   111  	if !ok {
   112  		return -1
   113  	}
   114  	return i
   115  }
   116  
   117  var IntToRpkiValidationReasonTypeMap = map[int]RpkiValidationReasonType{
   118  	0: RPKI_VALIDATION_REASON_TYPE_NONE,
   119  	1: RPKI_VALIDATION_REASON_TYPE_AS,
   120  	2: RPKI_VALIDATION_REASON_TYPE_LENGTH,
   121  }
   122  
   123  type Validation struct {
   124  	Status          oc.RpkiValidationResultType
   125  	Reason          RpkiValidationReasonType
   126  	Matched         []*ROA
   127  	UnmatchedAs     []*ROA
   128  	UnmatchedLength []*ROA
   129  }
   130  
   131  type Path struct {
   132  	info      *originInfo
   133  	parent    *Path
   134  	pathAttrs []bgp.PathAttributeInterface
   135  	dels      []bgp.BGPAttrType
   136  	attrsHash uint32
   137  	rejected  bool
   138  	// doesn't exist in the adj
   139  	dropped bool
   140  
   141  	// For BGP Nexthop Tracking, this field shows if nexthop is invalidated by IGP.
   142  	IsNexthopInvalid bool
   143  	IsWithdraw       bool
   144  }
   145  
   146  type FilteredType uint8
   147  
   148  const (
   149  	NotFiltered FilteredType = 1 << iota
   150  	PolicyFiltered
   151  	SendMaxFiltered
   152  )
   153  
   154  type PathDestLocalKey struct {
   155  	Family bgp.RouteFamily
   156  	Prefix string
   157  }
   158  type PathLocalKey struct {
   159  	PathDestLocalKey
   160  	Id uint32
   161  }
   162  
   163  func NewPathDestLocalKey(f bgp.RouteFamily, destPrefix string) *PathDestLocalKey {
   164  	return &PathDestLocalKey{
   165  		Family: f,
   166  		Prefix: destPrefix,
   167  	}
   168  }
   169  
   170  var localSource = &PeerInfo{}
   171  
   172  func NewPath(source *PeerInfo, nlri bgp.AddrPrefixInterface, isWithdraw bool, pattrs []bgp.PathAttributeInterface, timestamp time.Time, noImplicitWithdraw bool) *Path {
   173  	if source == nil {
   174  		source = localSource
   175  	}
   176  	if !isWithdraw && pattrs == nil {
   177  		return nil
   178  	}
   179  
   180  	return &Path{
   181  		info: &originInfo{
   182  			nlri:               nlri,
   183  			source:             source,
   184  			timestamp:          timestamp.Unix(),
   185  			noImplicitWithdraw: noImplicitWithdraw,
   186  		},
   187  		IsWithdraw: isWithdraw,
   188  		pathAttrs:  pattrs,
   189  	}
   190  }
   191  
   192  func NewEOR(family bgp.RouteFamily) *Path {
   193  	afi, safi := bgp.RouteFamilyToAfiSafi(family)
   194  	nlri, _ := bgp.NewPrefixFromRouteFamily(afi, safi)
   195  	return &Path{
   196  		info: &originInfo{
   197  			nlri: nlri,
   198  			eor:  true,
   199  		},
   200  	}
   201  }
   202  
   203  func (path *Path) IsEOR() bool {
   204  	if path.info != nil && path.info.eor {
   205  		return true
   206  	}
   207  	return false
   208  }
   209  
   210  func cloneAsPath(asAttr *bgp.PathAttributeAsPath) *bgp.PathAttributeAsPath {
   211  	newASparams := make([]bgp.AsPathParamInterface, len(asAttr.Value))
   212  	for i, param := range asAttr.Value {
   213  		asList := param.GetAS()
   214  		as := make([]uint32, len(asList))
   215  		copy(as, asList)
   216  		newASparams[i] = bgp.NewAs4PathParam(param.GetType(), as)
   217  	}
   218  	return bgp.NewPathAttributeAsPath(newASparams)
   219  }
   220  
   221  func UpdatePathAttrs(logger log.Logger, global *oc.Global, peer *oc.Neighbor, info *PeerInfo, original *Path) *Path {
   222  	if peer.RouteServer.Config.RouteServerClient {
   223  		return original
   224  	}
   225  	path := original.Clone(original.IsWithdraw)
   226  
   227  	for _, a := range path.GetPathAttrs() {
   228  		if _, y := bgp.PathAttrFlags[a.GetType()]; !y {
   229  			if a.GetFlags()&bgp.BGP_ATTR_FLAG_TRANSITIVE == 0 {
   230  				path.delPathAttr(a.GetType())
   231  			}
   232  		} else {
   233  			switch a.GetType() {
   234  			case bgp.BGP_ATTR_TYPE_CLUSTER_LIST, bgp.BGP_ATTR_TYPE_ORIGINATOR_ID:
   235  				if !(peer.State.PeerType == oc.PEER_TYPE_INTERNAL && peer.RouteReflector.Config.RouteReflectorClient) {
   236  					// send these attributes to only rr clients
   237  					path.delPathAttr(a.GetType())
   238  				}
   239  			}
   240  		}
   241  	}
   242  
   243  	localAddress := info.LocalAddress
   244  	nexthop := path.GetNexthop()
   245  	if peer.State.PeerType == oc.PEER_TYPE_EXTERNAL {
   246  		// NEXTHOP handling
   247  		if !path.IsLocal() || nexthop.IsUnspecified() {
   248  			path.SetNexthop(localAddress)
   249  		}
   250  
   251  		// remove-private-as handling
   252  		path.RemovePrivateAS(peer.Config.LocalAs, peer.State.RemovePrivateAs)
   253  
   254  		// AS_PATH handling
   255  		confed := peer.IsConfederationMember(global)
   256  		path.PrependAsn(peer.Config.LocalAs, 1, confed)
   257  		if !confed {
   258  			path.removeConfedAs()
   259  		}
   260  
   261  		// MED Handling
   262  		if med := path.getPathAttr(bgp.BGP_ATTR_TYPE_MULTI_EXIT_DISC); med != nil && !path.IsLocal() {
   263  			path.delPathAttr(bgp.BGP_ATTR_TYPE_MULTI_EXIT_DISC)
   264  		}
   265  
   266  	} else if peer.State.PeerType == oc.PEER_TYPE_INTERNAL {
   267  		// NEXTHOP handling for iBGP
   268  		// if the path generated locally set local address as nexthop.
   269  		// if not, don't modify it.
   270  		// TODO: NEXT-HOP-SELF support
   271  		if path.IsLocal() && nexthop.IsUnspecified() {
   272  			path.SetNexthop(localAddress)
   273  		}
   274  
   275  		// AS_PATH handling for iBGP
   276  		// if the path has AS_PATH path attribute, don't modify it.
   277  		// if not, attach *empty* AS_PATH path attribute.
   278  		if nh := path.getPathAttr(bgp.BGP_ATTR_TYPE_AS_PATH); nh == nil {
   279  			path.PrependAsn(0, 0, false)
   280  		}
   281  
   282  		// For iBGP peers we are required to send local-pref attribute
   283  		// for connected or local prefixes.
   284  		// We set default local-pref 100.
   285  		if pref := path.getPathAttr(bgp.BGP_ATTR_TYPE_LOCAL_PREF); pref == nil {
   286  			path.setPathAttr(bgp.NewPathAttributeLocalPref(DEFAULT_LOCAL_PREF))
   287  		}
   288  
   289  		// RFC4456: BGP Route Reflection
   290  		// 8. Avoiding Routing Information Loops
   291  		info := path.GetSource()
   292  		if peer.RouteReflector.Config.RouteReflectorClient {
   293  			// This attribute will carry the BGP Identifier of the originator of the route in the local AS.
   294  			// A BGP speaker SHOULD NOT create an ORIGINATOR_ID attribute if one already exists.
   295  			//
   296  			// RFC4684 3.2 Intra-AS VPN Route Distribution
   297  			// When advertising RT membership NLRI to a route-reflector client,
   298  			// the Originator attribute shall be set to the router-id of the
   299  			// advertiser, and the Next-hop attribute shall be set of the local
   300  			// address for that session.
   301  			if path.GetRouteFamily() == bgp.RF_RTC_UC {
   302  				path.SetNexthop(localAddress)
   303  				path.setPathAttr(bgp.NewPathAttributeOriginatorId(info.LocalID.String()))
   304  			} else if path.getPathAttr(bgp.BGP_ATTR_TYPE_ORIGINATOR_ID) == nil {
   305  				if path.IsLocal() {
   306  					path.setPathAttr(bgp.NewPathAttributeOriginatorId(global.Config.RouterId))
   307  				} else {
   308  					path.setPathAttr(bgp.NewPathAttributeOriginatorId(info.ID.String()))
   309  				}
   310  			}
   311  			// When an RR reflects a route, it MUST prepend the local CLUSTER_ID to the CLUSTER_LIST.
   312  			// If the CLUSTER_LIST is empty, it MUST create a new one.
   313  			clusterID := string(peer.RouteReflector.State.RouteReflectorClusterId)
   314  			if p := path.getPathAttr(bgp.BGP_ATTR_TYPE_CLUSTER_LIST); p == nil {
   315  				path.setPathAttr(bgp.NewPathAttributeClusterList([]string{clusterID}))
   316  			} else {
   317  				clusterList := p.(*bgp.PathAttributeClusterList)
   318  				newClusterList := make([]string, 0, len(clusterList.Value))
   319  				for _, ip := range clusterList.Value {
   320  					newClusterList = append(newClusterList, ip.String())
   321  				}
   322  				path.setPathAttr(bgp.NewPathAttributeClusterList(append([]string{clusterID}, newClusterList...)))
   323  			}
   324  		}
   325  
   326  	} else {
   327  		logger.Warn("invalid peer type",
   328  			log.Fields{
   329  				"Topic": "Peer",
   330  				"Key":   peer.State.NeighborAddress,
   331  				"Type":  peer.State.PeerType})
   332  	}
   333  	return path
   334  }
   335  
   336  func (path *Path) GetTimestamp() time.Time {
   337  	return time.Unix(path.OriginInfo().timestamp, 0)
   338  }
   339  
   340  func (path *Path) setTimestamp(t time.Time) {
   341  	path.OriginInfo().timestamp = t.Unix()
   342  }
   343  
   344  func (path *Path) IsLocal() bool {
   345  	return path.GetSource().Address == nil
   346  }
   347  
   348  func (path *Path) IsIBGP() bool {
   349  	as := path.GetSource().AS
   350  	return (as == path.GetSource().LocalAS) && as != 0
   351  }
   352  
   353  // create new PathAttributes
   354  func (path *Path) Clone(isWithdraw bool) *Path {
   355  	return &Path{
   356  		parent:           path,
   357  		IsWithdraw:       isWithdraw,
   358  		IsNexthopInvalid: path.IsNexthopInvalid,
   359  		attrsHash:        path.attrsHash,
   360  	}
   361  }
   362  
   363  func (path *Path) root() *Path {
   364  	p := path
   365  	for p.parent != nil {
   366  		p = p.parent
   367  	}
   368  	return p
   369  }
   370  
   371  func (path *Path) OriginInfo() *originInfo {
   372  	return path.root().info
   373  }
   374  
   375  func (path *Path) NoImplicitWithdraw() bool {
   376  	return path.OriginInfo().noImplicitWithdraw
   377  }
   378  
   379  func (path *Path) IsFromExternal() bool {
   380  	return path.OriginInfo().isFromExternal
   381  }
   382  
   383  func (path *Path) SetIsFromExternal(y bool) {
   384  	path.OriginInfo().isFromExternal = y
   385  }
   386  
   387  func (path *Path) GetRouteFamily() bgp.RouteFamily {
   388  	return bgp.AfiSafiToRouteFamily(path.OriginInfo().nlri.AFI(), path.OriginInfo().nlri.SAFI())
   389  }
   390  
   391  func (path *Path) GetSource() *PeerInfo {
   392  	return path.OriginInfo().source
   393  }
   394  
   395  func (path *Path) MarkStale(s bool) {
   396  	path.OriginInfo().stale = s
   397  }
   398  
   399  func (path *Path) IsStale() bool {
   400  	return path.OriginInfo().stale
   401  }
   402  
   403  func (path *Path) IsRejected() bool {
   404  	return path.rejected
   405  }
   406  
   407  func (path *Path) SetRejected(y bool) {
   408  	path.rejected = y
   409  }
   410  
   411  func (path *Path) IsDropped() bool {
   412  	return path.dropped
   413  }
   414  
   415  func (path *Path) SetDropped(y bool) {
   416  	path.dropped = y
   417  }
   418  
   419  func (path *Path) HasNoLLGR() bool {
   420  	for _, c := range path.GetCommunities() {
   421  		if c == uint32(bgp.COMMUNITY_NO_LLGR) {
   422  			return true
   423  		}
   424  	}
   425  	return false
   426  }
   427  
   428  func (path *Path) IsLLGRStale() bool {
   429  	for _, c := range path.GetCommunities() {
   430  		if c == uint32(bgp.COMMUNITY_LLGR_STALE) {
   431  			return true
   432  		}
   433  	}
   434  	return false
   435  }
   436  
   437  func (path *Path) GetSourceAs() uint32 {
   438  	attr := path.getPathAttr(bgp.BGP_ATTR_TYPE_AS_PATH)
   439  	if attr != nil {
   440  		asPathParam := attr.(*bgp.PathAttributeAsPath).Value
   441  		if len(asPathParam) == 0 {
   442  			return 0
   443  		}
   444  		asList := asPathParam[len(asPathParam)-1].GetAS()
   445  		if len(asList) == 0 {
   446  			return 0
   447  		}
   448  		return asList[len(asList)-1]
   449  	}
   450  	return 0
   451  }
   452  
   453  func (path *Path) GetNexthop() net.IP {
   454  	attr := path.getPathAttr(bgp.BGP_ATTR_TYPE_NEXT_HOP)
   455  	if attr != nil {
   456  		return attr.(*bgp.PathAttributeNextHop).Value
   457  	}
   458  	attr = path.getPathAttr(bgp.BGP_ATTR_TYPE_MP_REACH_NLRI)
   459  	if attr != nil {
   460  		return attr.(*bgp.PathAttributeMpReachNLRI).Nexthop
   461  	}
   462  	return net.IP{}
   463  }
   464  
   465  func (path *Path) SetNexthop(nexthop net.IP) {
   466  	if path.GetRouteFamily() == bgp.RF_IPv4_UC && nexthop.To4() == nil {
   467  		path.delPathAttr(bgp.BGP_ATTR_TYPE_NEXT_HOP)
   468  		mpreach := bgp.NewPathAttributeMpReachNLRI(nexthop.String(), []bgp.AddrPrefixInterface{path.GetNlri()})
   469  		path.setPathAttr(mpreach)
   470  		return
   471  	}
   472  	attr := path.getPathAttr(bgp.BGP_ATTR_TYPE_NEXT_HOP)
   473  	if attr != nil {
   474  		path.setPathAttr(bgp.NewPathAttributeNextHop(nexthop.String()))
   475  	}
   476  	attr = path.getPathAttr(bgp.BGP_ATTR_TYPE_MP_REACH_NLRI)
   477  	if attr != nil {
   478  		oldNlri := attr.(*bgp.PathAttributeMpReachNLRI)
   479  		path.setPathAttr(bgp.NewPathAttributeMpReachNLRI(nexthop.String(), oldNlri.Value))
   480  	}
   481  }
   482  
   483  func (path *Path) GetNlri() bgp.AddrPrefixInterface {
   484  	return path.OriginInfo().nlri
   485  }
   486  
   487  type PathAttrs []bgp.PathAttributeInterface
   488  
   489  func (a PathAttrs) Len() int {
   490  	return len(a)
   491  }
   492  
   493  func (a PathAttrs) Swap(i, j int) {
   494  	a[i], a[j] = a[j], a[i]
   495  }
   496  
   497  func (a PathAttrs) Less(i, j int) bool {
   498  	return a[i].GetType() < a[j].GetType()
   499  }
   500  
   501  func (path *Path) GetPathAttrs() []bgp.PathAttributeInterface {
   502  	deleted := NewBitmap(math.MaxUint8)
   503  	modified := make(map[uint]bgp.PathAttributeInterface)
   504  	p := path
   505  	for {
   506  		for _, t := range p.dels {
   507  			deleted.Flag(uint(t))
   508  		}
   509  		if p.parent == nil {
   510  			list := PathAttrs(make([]bgp.PathAttributeInterface, 0, len(p.pathAttrs)))
   511  			// we assume that the original pathAttrs are
   512  			// in order, that is, other bgp speakers send
   513  			// attributes in order.
   514  			for _, a := range p.pathAttrs {
   515  				typ := uint(a.GetType())
   516  				if m, ok := modified[typ]; ok {
   517  					list = append(list, m)
   518  					delete(modified, typ)
   519  				} else if !deleted.GetFlag(typ) {
   520  					list = append(list, a)
   521  				}
   522  			}
   523  			if len(modified) > 0 {
   524  				// Huh, some attributes were newly
   525  				// added. So we need to sort...
   526  				for _, m := range modified {
   527  					list = append(list, m)
   528  				}
   529  				sort.Sort(list)
   530  			}
   531  			return list
   532  		} else {
   533  			for _, a := range p.pathAttrs {
   534  				typ := uint(a.GetType())
   535  				if _, ok := modified[typ]; !deleted.GetFlag(typ) && !ok {
   536  					modified[typ] = a
   537  				}
   538  			}
   539  		}
   540  		p = p.parent
   541  	}
   542  }
   543  
   544  func (path *Path) getPathAttr(typ bgp.BGPAttrType) bgp.PathAttributeInterface {
   545  	p := path
   546  	for {
   547  		for _, t := range p.dels {
   548  			if t == typ {
   549  				return nil
   550  			}
   551  		}
   552  		for _, a := range p.pathAttrs {
   553  			if a.GetType() == typ {
   554  				return a
   555  			}
   556  		}
   557  		if p.parent == nil {
   558  			return nil
   559  		}
   560  		p = p.parent
   561  	}
   562  }
   563  
   564  func (path *Path) setPathAttr(a bgp.PathAttributeInterface) {
   565  	if len(path.pathAttrs) == 0 {
   566  		path.pathAttrs = []bgp.PathAttributeInterface{a}
   567  	} else {
   568  		for i, b := range path.pathAttrs {
   569  			if a.GetType() == b.GetType() {
   570  				path.pathAttrs[i] = a
   571  				return
   572  			}
   573  		}
   574  		path.pathAttrs = append(path.pathAttrs, a)
   575  	}
   576  }
   577  
   578  func (path *Path) delPathAttr(typ bgp.BGPAttrType) {
   579  	if len(path.dels) == 0 {
   580  		path.dels = []bgp.BGPAttrType{typ}
   581  	} else {
   582  		path.dels = append(path.dels, typ)
   583  	}
   584  }
   585  
   586  // return Path's string representation
   587  func (path *Path) String() string {
   588  	s := bytes.NewBuffer(make([]byte, 0, 64))
   589  	if path.IsEOR() {
   590  		s.WriteString(fmt.Sprintf("{ %s EOR | src: %s }", path.GetRouteFamily(), path.GetSource()))
   591  		return s.String()
   592  	}
   593  	s.WriteString(fmt.Sprintf("{ %s | ", path.GetPrefix()))
   594  	s.WriteString(fmt.Sprintf("src: %s", path.GetSource()))
   595  	s.WriteString(fmt.Sprintf(", nh: %s", path.GetNexthop()))
   596  	if path.IsNexthopInvalid {
   597  		s.WriteString(" (not reachable)")
   598  	}
   599  	if path.IsWithdraw {
   600  		s.WriteString(", withdraw")
   601  	}
   602  	s.WriteString(" }")
   603  	return s.String()
   604  }
   605  
   606  // GetLocalKey identifies the path in the local BGP server.
   607  func (path *Path) GetLocalKey() PathLocalKey {
   608  	return PathLocalKey{
   609  		PathDestLocalKey: path.GetDestLocalKey(),
   610  		Id:               path.GetNlri().PathLocalIdentifier(),
   611  	}
   612  }
   613  
   614  // GetDestLocalKey identifies the path destination in the local BGP server.
   615  func (path *Path) GetDestLocalKey() PathDestLocalKey {
   616  	return PathDestLocalKey{
   617  		Family: path.GetRouteFamily(),
   618  		Prefix: path.GetNlri().String(),
   619  	}
   620  }
   621  
   622  func (path *Path) GetPrefix() string {
   623  	return path.GetNlri().String()
   624  }
   625  
   626  func (path *Path) GetAsPath() *bgp.PathAttributeAsPath {
   627  	attr := path.getPathAttr(bgp.BGP_ATTR_TYPE_AS_PATH)
   628  	if attr != nil {
   629  		return attr.(*bgp.PathAttributeAsPath)
   630  	}
   631  	return nil
   632  }
   633  
   634  // GetAsPathLen returns the number of AS_PATH
   635  func (path *Path) GetAsPathLen() int {
   636  
   637  	var length int = 0
   638  	if aspath := path.GetAsPath(); aspath != nil {
   639  		for _, as := range aspath.Value {
   640  			length += as.ASLen()
   641  		}
   642  	}
   643  	return length
   644  }
   645  
   646  func (path *Path) GetAsString() string {
   647  	s := bytes.NewBuffer(make([]byte, 0, 64))
   648  	if aspath := path.GetAsPath(); aspath != nil {
   649  		return bgp.AsPathString(aspath)
   650  	}
   651  	return s.String()
   652  }
   653  
   654  func (path *Path) GetAsList() []uint32 {
   655  	return path.getAsListOfSpecificType(true, true)
   656  
   657  }
   658  
   659  func (path *Path) GetAsSeqList() []uint32 {
   660  	return path.getAsListOfSpecificType(true, false)
   661  }
   662  
   663  func (path *Path) getAsListOfSpecificType(getAsSeq, getAsSet bool) []uint32 {
   664  	asList := []uint32{}
   665  	if aspath := path.GetAsPath(); aspath != nil {
   666  		for _, param := range aspath.Value {
   667  			segType := param.GetType()
   668  			if getAsSeq && segType == bgp.BGP_ASPATH_ATTR_TYPE_SEQ {
   669  				asList = append(asList, param.GetAS()...)
   670  				continue
   671  			}
   672  			if getAsSet && segType == bgp.BGP_ASPATH_ATTR_TYPE_SET {
   673  				asList = append(asList, param.GetAS()...)
   674  			} else {
   675  				asList = append(asList, 0)
   676  			}
   677  		}
   678  	}
   679  	return asList
   680  }
   681  
   682  func (path *Path) GetLabelString() string {
   683  	return bgp.LabelString(path.GetNlri())
   684  }
   685  
   686  // PrependAsn prepends AS number.
   687  // This function updates the AS_PATH attribute as follows.
   688  // (If the peer is in the confederation member AS,
   689  //
   690  //	replace AS_SEQUENCE in the following sentence with AS_CONFED_SEQUENCE.)
   691  //	1) if the first path segment of the AS_PATH is of type
   692  //	   AS_SEQUENCE, the local system prepends the specified AS num as
   693  //	   the last element of the sequence (put it in the left-most
   694  //	   position with respect to the position of  octets in the
   695  //	   protocol message) the specified number of times.
   696  //	   If the act of prepending will cause an overflow in the AS_PATH
   697  //	   segment (i.e.,  more than 255 ASes),
   698  //	   it SHOULD prepend a new segment of type AS_SEQUENCE
   699  //	   and prepend its own AS number to this new segment.
   700  //
   701  //	2) if the first path segment of the AS_PATH is of other than type
   702  //	   AS_SEQUENCE, the local system prepends a new path segment of type
   703  //	   AS_SEQUENCE to the AS_PATH, including the specified AS number in
   704  //	   that segment.
   705  //
   706  //	3) if the AS_PATH is empty, the local system creates a path
   707  //	   segment of type AS_SEQUENCE, places the specified AS number
   708  //	   into that segment, and places that segment into the AS_PATH.
   709  func (path *Path) PrependAsn(asn uint32, repeat uint8, confed bool) {
   710  	var segType uint8
   711  	if confed {
   712  		segType = bgp.BGP_ASPATH_ATTR_TYPE_CONFED_SEQ
   713  	} else {
   714  		segType = bgp.BGP_ASPATH_ATTR_TYPE_SEQ
   715  	}
   716  
   717  	original := path.GetAsPath()
   718  
   719  	asns := make([]uint32, repeat)
   720  	for i := range asns {
   721  		asns[i] = asn
   722  	}
   723  
   724  	var asPath *bgp.PathAttributeAsPath
   725  	if original == nil {
   726  		asPath = bgp.NewPathAttributeAsPath([]bgp.AsPathParamInterface{})
   727  	} else {
   728  		asPath = cloneAsPath(original)
   729  	}
   730  
   731  	if len(asPath.Value) > 0 {
   732  		param := asPath.Value[0]
   733  		asList := param.GetAS()
   734  		if param.GetType() == segType {
   735  			if int(repeat)+len(asList) > 255 {
   736  				repeat = uint8(255 - len(asList))
   737  			}
   738  			newAsList := append(asns[:int(repeat)], asList...)
   739  			asPath.Value[0] = bgp.NewAs4PathParam(segType, newAsList)
   740  			asns = asns[int(repeat):]
   741  		}
   742  	}
   743  
   744  	if len(asns) > 0 {
   745  		p := bgp.NewAs4PathParam(segType, asns)
   746  		asPath.Value = append([]bgp.AsPathParamInterface{p}, asPath.Value...)
   747  	}
   748  	path.setPathAttr(asPath)
   749  }
   750  
   751  func isPrivateAS(as uint32) bool {
   752  	return (64512 <= as && as <= 65534) || (4200000000 <= as && as <= 4294967294)
   753  }
   754  
   755  func (path *Path) RemovePrivateAS(localAS uint32, option oc.RemovePrivateAsOption) {
   756  	original := path.GetAsPath()
   757  	if original == nil {
   758  		return
   759  	}
   760  	switch option {
   761  	case oc.REMOVE_PRIVATE_AS_OPTION_ALL, oc.REMOVE_PRIVATE_AS_OPTION_REPLACE:
   762  		newASParams := make([]bgp.AsPathParamInterface, 0, len(original.Value))
   763  		for _, param := range original.Value {
   764  			asList := param.GetAS()
   765  			newASParam := make([]uint32, 0, len(asList))
   766  			for _, as := range asList {
   767  				if isPrivateAS(as) {
   768  					if option == oc.REMOVE_PRIVATE_AS_OPTION_REPLACE {
   769  						newASParam = append(newASParam, localAS)
   770  					}
   771  				} else {
   772  					newASParam = append(newASParam, as)
   773  				}
   774  			}
   775  			if len(newASParam) > 0 {
   776  				newASParams = append(newASParams, bgp.NewAs4PathParam(param.GetType(), newASParam))
   777  			}
   778  		}
   779  		path.setPathAttr(bgp.NewPathAttributeAsPath(newASParams))
   780  	}
   781  }
   782  
   783  func (path *Path) removeConfedAs() {
   784  	original := path.GetAsPath()
   785  	if original == nil {
   786  		return
   787  	}
   788  	newAsParams := make([]bgp.AsPathParamInterface, 0, len(original.Value))
   789  	for _, param := range original.Value {
   790  		switch param.GetType() {
   791  		case bgp.BGP_ASPATH_ATTR_TYPE_SEQ, bgp.BGP_ASPATH_ATTR_TYPE_SET:
   792  			newAsParams = append(newAsParams, param)
   793  		}
   794  	}
   795  	path.setPathAttr(bgp.NewPathAttributeAsPath(newAsParams))
   796  }
   797  
   798  func (path *Path) ReplaceAS(localAS, peerAS uint32) *Path {
   799  	original := path.GetAsPath()
   800  	if original == nil {
   801  		return path
   802  	}
   803  	newASParams := make([]bgp.AsPathParamInterface, 0, len(original.Value))
   804  	changed := false
   805  	for _, param := range original.Value {
   806  		segType := param.GetType()
   807  		asList := param.GetAS()
   808  		newASParam := make([]uint32, 0, len(asList))
   809  		for _, as := range asList {
   810  			if as == peerAS {
   811  				as = localAS
   812  				changed = true
   813  			}
   814  			newASParam = append(newASParam, as)
   815  		}
   816  		newASParams = append(newASParams, bgp.NewAs4PathParam(segType, newASParam))
   817  	}
   818  	if changed {
   819  		path = path.Clone(path.IsWithdraw)
   820  		path.setPathAttr(bgp.NewPathAttributeAsPath(newASParams))
   821  	}
   822  	return path
   823  }
   824  
   825  func (path *Path) GetCommunities() []uint32 {
   826  	communityList := []uint32{}
   827  	if attr := path.getPathAttr(bgp.BGP_ATTR_TYPE_COMMUNITIES); attr != nil {
   828  		communities := attr.(*bgp.PathAttributeCommunities)
   829  		communityList = append(communityList, communities.Value...)
   830  	}
   831  	return communityList
   832  }
   833  
   834  // SetCommunities adds or replaces communities with new ones.
   835  // If the length of communities is 0 and doReplace is true, it clears communities.
   836  func (path *Path) SetCommunities(communities []uint32, doReplace bool) {
   837  
   838  	if len(communities) == 0 && doReplace {
   839  		// clear communities
   840  		path.delPathAttr(bgp.BGP_ATTR_TYPE_COMMUNITIES)
   841  		return
   842  	}
   843  
   844  	newList := make([]uint32, 0)
   845  	attr := path.getPathAttr(bgp.BGP_ATTR_TYPE_COMMUNITIES)
   846  	if attr != nil {
   847  		c := attr.(*bgp.PathAttributeCommunities)
   848  		if doReplace {
   849  			newList = append(newList, communities...)
   850  		} else {
   851  			newList = append(newList, c.Value...)
   852  			newList = append(newList, communities...)
   853  		}
   854  	} else {
   855  		newList = append(newList, communities...)
   856  	}
   857  	path.setPathAttr(bgp.NewPathAttributeCommunities(newList))
   858  
   859  }
   860  
   861  // RemoveCommunities removes specific communities.
   862  // If the length of communities is 0, it does nothing.
   863  // If all communities are removed, it removes Communities path attribute itself.
   864  func (path *Path) RemoveCommunities(communities []uint32) int {
   865  
   866  	if len(communities) == 0 {
   867  		// do nothing
   868  		return 0
   869  	}
   870  
   871  	find := func(val uint32) bool {
   872  		for _, com := range communities {
   873  			if com == val {
   874  				return true
   875  			}
   876  		}
   877  		return false
   878  	}
   879  
   880  	count := 0
   881  	attr := path.getPathAttr(bgp.BGP_ATTR_TYPE_COMMUNITIES)
   882  	if attr != nil {
   883  		newList := make([]uint32, 0)
   884  		c := attr.(*bgp.PathAttributeCommunities)
   885  
   886  		for _, value := range c.Value {
   887  			if find(value) {
   888  				count += 1
   889  			} else {
   890  				newList = append(newList, value)
   891  			}
   892  		}
   893  
   894  		if len(newList) != 0 {
   895  			path.setPathAttr(bgp.NewPathAttributeCommunities(newList))
   896  		} else {
   897  			path.delPathAttr(bgp.BGP_ATTR_TYPE_COMMUNITIES)
   898  		}
   899  	}
   900  	return count
   901  }
   902  
   903  func (path *Path) GetExtCommunities() []bgp.ExtendedCommunityInterface {
   904  	eCommunityList := make([]bgp.ExtendedCommunityInterface, 0)
   905  	if attr := path.getPathAttr(bgp.BGP_ATTR_TYPE_EXTENDED_COMMUNITIES); attr != nil {
   906  		eCommunities := attr.(*bgp.PathAttributeExtendedCommunities).Value
   907  		eCommunityList = append(eCommunityList, eCommunities...)
   908  	}
   909  	return eCommunityList
   910  }
   911  
   912  func (path *Path) SetExtCommunities(exts []bgp.ExtendedCommunityInterface, doReplace bool) {
   913  	attr := path.getPathAttr(bgp.BGP_ATTR_TYPE_EXTENDED_COMMUNITIES)
   914  	if attr != nil {
   915  		l := attr.(*bgp.PathAttributeExtendedCommunities).Value
   916  		if doReplace {
   917  			l = exts
   918  		} else {
   919  			l = append(l, exts...)
   920  		}
   921  		path.setPathAttr(bgp.NewPathAttributeExtendedCommunities(l))
   922  	} else {
   923  		path.setPathAttr(bgp.NewPathAttributeExtendedCommunities(exts))
   924  	}
   925  }
   926  
   927  func (path *Path) GetRouteTargets() []bgp.ExtendedCommunityInterface {
   928  	rts := make([]bgp.ExtendedCommunityInterface, 0)
   929  	for _, ec := range path.GetExtCommunities() {
   930  		if t, st := ec.GetTypes(); t <= bgp.EC_TYPE_TRANSITIVE_FOUR_OCTET_AS_SPECIFIC && st == bgp.EC_SUBTYPE_ROUTE_TARGET {
   931  			rts = append(rts, ec)
   932  		}
   933  	}
   934  	return rts
   935  }
   936  
   937  func (path *Path) GetLargeCommunities() []*bgp.LargeCommunity {
   938  	if a := path.getPathAttr(bgp.BGP_ATTR_TYPE_LARGE_COMMUNITY); a != nil {
   939  		v := a.(*bgp.PathAttributeLargeCommunities).Values
   940  		ret := make([]*bgp.LargeCommunity, 0, len(v))
   941  		ret = append(ret, v...)
   942  		return ret
   943  	}
   944  	return nil
   945  }
   946  
   947  func (path *Path) SetLargeCommunities(cs []*bgp.LargeCommunity, doReplace bool) {
   948  	if len(cs) == 0 && doReplace {
   949  		// clear large communities
   950  		path.delPathAttr(bgp.BGP_ATTR_TYPE_LARGE_COMMUNITY)
   951  		return
   952  	}
   953  
   954  	a := path.getPathAttr(bgp.BGP_ATTR_TYPE_LARGE_COMMUNITY)
   955  	if a == nil || doReplace {
   956  		path.setPathAttr(bgp.NewPathAttributeLargeCommunities(cs))
   957  	} else {
   958  		l := a.(*bgp.PathAttributeLargeCommunities).Values
   959  		path.setPathAttr(bgp.NewPathAttributeLargeCommunities(append(l, cs...)))
   960  	}
   961  }
   962  
   963  func (path *Path) GetMed() (uint32, error) {
   964  	attr := path.getPathAttr(bgp.BGP_ATTR_TYPE_MULTI_EXIT_DISC)
   965  	if attr == nil {
   966  		return 0, fmt.Errorf("no med path attr")
   967  	}
   968  	return attr.(*bgp.PathAttributeMultiExitDisc).Value, nil
   969  }
   970  
   971  // SetMed replace, add or subtraction med with new ones.
   972  func (path *Path) SetMed(med int64, doReplace bool) error {
   973  	parseMed := func(orgMed uint32, med int64, doReplace bool) (*bgp.PathAttributeMultiExitDisc, error) {
   974  		if doReplace {
   975  			return bgp.NewPathAttributeMultiExitDisc(uint32(med)), nil
   976  		}
   977  
   978  		medVal := int64(orgMed) + med
   979  		if medVal < 0 {
   980  			return nil, fmt.Errorf("med value invalid. it's underflow threshold: %v", medVal)
   981  		} else if medVal > int64(math.MaxUint32) {
   982  			return nil, fmt.Errorf("med value invalid. it's overflow threshold: %v", medVal)
   983  		}
   984  
   985  		return bgp.NewPathAttributeMultiExitDisc(uint32(int64(orgMed) + med)), nil
   986  	}
   987  
   988  	m := uint32(0)
   989  	if attr := path.getPathAttr(bgp.BGP_ATTR_TYPE_MULTI_EXIT_DISC); attr != nil {
   990  		m = attr.(*bgp.PathAttributeMultiExitDisc).Value
   991  	}
   992  	newMed, err := parseMed(m, med, doReplace)
   993  	if err != nil {
   994  		return err
   995  	}
   996  	path.setPathAttr(newMed)
   997  	return nil
   998  }
   999  
  1000  func (path *Path) RemoveLocalPref() {
  1001  	if path.getPathAttr(bgp.BGP_ATTR_TYPE_LOCAL_PREF) != nil {
  1002  		path.delPathAttr(bgp.BGP_ATTR_TYPE_LOCAL_PREF)
  1003  	}
  1004  }
  1005  
  1006  func (path *Path) GetOriginatorID() net.IP {
  1007  	if attr := path.getPathAttr(bgp.BGP_ATTR_TYPE_ORIGINATOR_ID); attr != nil {
  1008  		return attr.(*bgp.PathAttributeOriginatorId).Value
  1009  	}
  1010  	return nil
  1011  }
  1012  
  1013  func (path *Path) GetClusterList() []net.IP {
  1014  	if attr := path.getPathAttr(bgp.BGP_ATTR_TYPE_CLUSTER_LIST); attr != nil {
  1015  		return attr.(*bgp.PathAttributeClusterList).Value
  1016  	}
  1017  	return nil
  1018  }
  1019  
  1020  func (path *Path) GetOrigin() (uint8, error) {
  1021  	if attr := path.getPathAttr(bgp.BGP_ATTR_TYPE_ORIGIN); attr != nil {
  1022  		return attr.(*bgp.PathAttributeOrigin).Value, nil
  1023  	}
  1024  	return 0, fmt.Errorf("no origin path attr")
  1025  }
  1026  
  1027  func (path *Path) GetLocalPref() (uint32, error) {
  1028  	lp := uint32(DEFAULT_LOCAL_PREF)
  1029  	attr := path.getPathAttr(bgp.BGP_ATTR_TYPE_LOCAL_PREF)
  1030  	if attr != nil {
  1031  		lp = attr.(*bgp.PathAttributeLocalPref).Value
  1032  	}
  1033  	return lp, nil
  1034  }
  1035  
  1036  func (lhs *Path) Equal(rhs *Path) bool {
  1037  	if rhs == nil {
  1038  		return false
  1039  	}
  1040  
  1041  	if !lhs.GetSource().Equal(rhs.GetSource()) {
  1042  		return false
  1043  	}
  1044  
  1045  	pattrs := func(arg []bgp.PathAttributeInterface) []byte {
  1046  		ret := make([]byte, 0)
  1047  		for _, a := range arg {
  1048  			aa, _ := a.Serialize()
  1049  			ret = append(ret, aa...)
  1050  		}
  1051  		return ret
  1052  	}
  1053  	return bytes.Equal(pattrs(lhs.GetPathAttrs()), pattrs(rhs.GetPathAttrs()))
  1054  }
  1055  
  1056  func (path *Path) MarshalJSON() ([]byte, error) {
  1057  	return json.Marshal(struct {
  1058  		Nlri       bgp.AddrPrefixInterface      `json:"nlri"`
  1059  		PathAttrs  []bgp.PathAttributeInterface `json:"attrs"`
  1060  		Age        int64                        `json:"age"`
  1061  		Withdrawal bool                         `json:"withdrawal,omitempty"`
  1062  		Validation string                       `json:"validation,omitempty"`
  1063  		SourceID   net.IP                       `json:"source-id,omitempty"`
  1064  		NeighborIP net.IP                       `json:"neighbor-ip,omitempty"`
  1065  		Stale      bool                         `json:"stale,omitempty"`
  1066  		UUID       string                       `json:"uuid,omitempty"`
  1067  		ID         uint32                       `json:"id,omitempty"`
  1068  	}{
  1069  		Nlri:       path.GetNlri(),
  1070  		PathAttrs:  path.GetPathAttrs(),
  1071  		Age:        path.GetTimestamp().Unix(),
  1072  		Withdrawal: path.IsWithdraw,
  1073  		SourceID:   path.GetSource().ID,
  1074  		NeighborIP: path.GetSource().Address,
  1075  		Stale:      path.IsStale(),
  1076  		ID:         path.GetNlri().PathIdentifier(),
  1077  	})
  1078  }
  1079  
  1080  func (lhs *Path) Compare(rhs *Path) int {
  1081  	if lhs.IsLocal() && !rhs.IsLocal() {
  1082  		return 1
  1083  	} else if !lhs.IsLocal() && rhs.IsLocal() {
  1084  		return -1
  1085  	}
  1086  
  1087  	if !lhs.IsIBGP() && rhs.IsIBGP() {
  1088  		return 1
  1089  	} else if lhs.IsIBGP() && !rhs.IsIBGP() {
  1090  		return -1
  1091  	}
  1092  
  1093  	lp1, _ := lhs.GetLocalPref()
  1094  	lp2, _ := rhs.GetLocalPref()
  1095  	if lp1 != lp2 {
  1096  		return int(lp1 - lp2)
  1097  	}
  1098  
  1099  	l1 := lhs.GetAsPathLen()
  1100  	l2 := rhs.GetAsPathLen()
  1101  	if l1 != l2 {
  1102  		return int(l2 - l1)
  1103  	}
  1104  
  1105  	o1, _ := lhs.GetOrigin()
  1106  	o2, _ := rhs.GetOrigin()
  1107  	if o1 != o2 {
  1108  		return int(o2 - o1)
  1109  	}
  1110  
  1111  	m1, _ := lhs.GetMed()
  1112  	m2, _ := rhs.GetMed()
  1113  	return int(m2 - m1)
  1114  }
  1115  
  1116  func (v *Vrf) ToGlobalPath(path *Path) error {
  1117  	nlri := path.GetNlri()
  1118  	switch rf := path.GetRouteFamily(); rf {
  1119  	case bgp.RF_IPv4_UC:
  1120  		n := nlri.(*bgp.IPAddrPrefix)
  1121  		pathIdentifier := path.GetNlri().PathIdentifier()
  1122  		path.OriginInfo().nlri = bgp.NewLabeledVPNIPAddrPrefix(n.Length, n.Prefix.String(), *bgp.NewMPLSLabelStack(v.MplsLabel), v.Rd)
  1123  		path.GetNlri().SetPathIdentifier(pathIdentifier)
  1124  	case bgp.RF_FS_IPv4_UC:
  1125  		n := nlri.(*bgp.FlowSpecIPv4Unicast)
  1126  		pathIdentifier := path.GetNlri().PathIdentifier()
  1127  		path.OriginInfo().nlri = bgp.NewFlowSpecIPv4VPN(v.Rd, n.FlowSpecNLRI.Value)
  1128  		path.GetNlri().SetPathIdentifier(pathIdentifier)
  1129  	case bgp.RF_IPv6_UC:
  1130  		n := nlri.(*bgp.IPv6AddrPrefix)
  1131  		pathIdentifier := path.GetNlri().PathIdentifier()
  1132  		path.OriginInfo().nlri = bgp.NewLabeledVPNIPv6AddrPrefix(n.Length, n.Prefix.String(), *bgp.NewMPLSLabelStack(v.MplsLabel), v.Rd)
  1133  		path.GetNlri().SetPathIdentifier(pathIdentifier)
  1134  	case bgp.RF_FS_IPv6_UC:
  1135  		n := nlri.(*bgp.FlowSpecIPv6Unicast)
  1136  		pathIdentifier := path.GetNlri().PathIdentifier()
  1137  		path.OriginInfo().nlri = bgp.NewFlowSpecIPv6VPN(v.Rd, n.FlowSpecNLRI.Value)
  1138  		path.GetNlri().SetPathIdentifier(pathIdentifier)
  1139  	case bgp.RF_EVPN:
  1140  		n := nlri.(*bgp.EVPNNLRI)
  1141  		switch n.RouteType {
  1142  		case bgp.EVPN_ROUTE_TYPE_MAC_IP_ADVERTISEMENT:
  1143  			n.RouteTypeData.(*bgp.EVPNMacIPAdvertisementRoute).RD = v.Rd
  1144  		case bgp.EVPN_INCLUSIVE_MULTICAST_ETHERNET_TAG:
  1145  			n.RouteTypeData.(*bgp.EVPNMulticastEthernetTagRoute).RD = v.Rd
  1146  		}
  1147  	case bgp.RF_MUP_IPv4, bgp.RF_MUP_IPv6:
  1148  		n := nlri.(*bgp.MUPNLRI)
  1149  		switch n.RouteType {
  1150  		case bgp.MUP_ROUTE_TYPE_INTERWORK_SEGMENT_DISCOVERY:
  1151  			n.RouteTypeData.(*bgp.MUPInterworkSegmentDiscoveryRoute).RD = v.Rd
  1152  		case bgp.MUP_ROUTE_TYPE_DIRECT_SEGMENT_DISCOVERY:
  1153  			n.RouteTypeData.(*bgp.MUPDirectSegmentDiscoveryRoute).RD = v.Rd
  1154  		case bgp.MUP_ROUTE_TYPE_TYPE_1_SESSION_TRANSFORMED:
  1155  			n.RouteTypeData.(*bgp.MUPType1SessionTransformedRoute).RD = v.Rd
  1156  		case bgp.MUP_ROUTE_TYPE_TYPE_2_SESSION_TRANSFORMED:
  1157  			n.RouteTypeData.(*bgp.MUPType2SessionTransformedRoute).RD = v.Rd
  1158  		}
  1159  	default:
  1160  		return fmt.Errorf("unsupported route family for vrf: %s", rf)
  1161  	}
  1162  	path.SetExtCommunities(v.ExportRt, false)
  1163  	return nil
  1164  }
  1165  
  1166  func (p *Path) ToGlobal(vrf *Vrf) *Path {
  1167  	nlri := p.GetNlri()
  1168  	nh := p.GetNexthop()
  1169  	pathId := nlri.PathIdentifier()
  1170  	switch rf := p.GetRouteFamily(); rf {
  1171  	case bgp.RF_IPv4_UC:
  1172  		n := nlri.(*bgp.IPAddrPrefix)
  1173  		nlri = bgp.NewLabeledVPNIPAddrPrefix(n.Length, n.Prefix.String(), *bgp.NewMPLSLabelStack(vrf.MplsLabel), vrf.Rd)
  1174  		nlri.SetPathIdentifier(pathId)
  1175  	case bgp.RF_IPv6_UC:
  1176  		n := nlri.(*bgp.IPv6AddrPrefix)
  1177  		nlri = bgp.NewLabeledVPNIPv6AddrPrefix(n.Length, n.Prefix.String(), *bgp.NewMPLSLabelStack(vrf.MplsLabel), vrf.Rd)
  1178  		nlri.SetPathIdentifier(pathId)
  1179  	case bgp.RF_EVPN:
  1180  		n := nlri.(*bgp.EVPNNLRI)
  1181  		switch n.RouteType {
  1182  		case bgp.EVPN_ROUTE_TYPE_MAC_IP_ADVERTISEMENT:
  1183  			old := n.RouteTypeData.(*bgp.EVPNMacIPAdvertisementRoute)
  1184  			new := &bgp.EVPNMacIPAdvertisementRoute{
  1185  				RD:               vrf.Rd,
  1186  				ESI:              old.ESI,
  1187  				ETag:             old.ETag,
  1188  				MacAddressLength: old.MacAddressLength,
  1189  				MacAddress:       old.MacAddress,
  1190  				IPAddressLength:  old.IPAddressLength,
  1191  				IPAddress:        old.IPAddress,
  1192  				Labels:           old.Labels,
  1193  			}
  1194  			nlri = bgp.NewEVPNNLRI(n.RouteType, new)
  1195  		case bgp.EVPN_INCLUSIVE_MULTICAST_ETHERNET_TAG:
  1196  			old := n.RouteTypeData.(*bgp.EVPNMulticastEthernetTagRoute)
  1197  			new := &bgp.EVPNMulticastEthernetTagRoute{
  1198  				RD:              vrf.Rd,
  1199  				ETag:            old.ETag,
  1200  				IPAddressLength: old.IPAddressLength,
  1201  				IPAddress:       old.IPAddress,
  1202  			}
  1203  			nlri = bgp.NewEVPNNLRI(n.RouteType, new)
  1204  		}
  1205  	case bgp.RF_MUP_IPv4, bgp.RF_MUP_IPv6:
  1206  		n := nlri.(*bgp.MUPNLRI)
  1207  		switch n.RouteType {
  1208  		case bgp.MUP_ROUTE_TYPE_INTERWORK_SEGMENT_DISCOVERY:
  1209  			old := n.RouteTypeData.(*bgp.MUPInterworkSegmentDiscoveryRoute)
  1210  			nlri = bgp.NewMUPInterworkSegmentDiscoveryRoute(vrf.Rd, old.Prefix)
  1211  		case bgp.MUP_ROUTE_TYPE_DIRECT_SEGMENT_DISCOVERY:
  1212  			old := n.RouteTypeData.(*bgp.MUPDirectSegmentDiscoveryRoute)
  1213  			nlri = bgp.NewMUPDirectSegmentDiscoveryRoute(vrf.Rd, old.Address)
  1214  		case bgp.MUP_ROUTE_TYPE_TYPE_1_SESSION_TRANSFORMED:
  1215  			old := n.RouteTypeData.(*bgp.MUPType1SessionTransformedRoute)
  1216  			nlri = bgp.NewMUPType1SessionTransformedRoute(vrf.Rd, old.Prefix, old.TEID, old.QFI, old.EndpointAddress, old.SourceAddress)
  1217  		case bgp.MUP_ROUTE_TYPE_TYPE_2_SESSION_TRANSFORMED:
  1218  			old := n.RouteTypeData.(*bgp.MUPType2SessionTransformedRoute)
  1219  			nlri = bgp.NewMUPType2SessionTransformedRoute(vrf.Rd, old.EndpointAddressLength, old.EndpointAddress, old.TEID)
  1220  		}
  1221  	default:
  1222  		return p
  1223  	}
  1224  	path := NewPath(p.OriginInfo().source, nlri, p.IsWithdraw, p.GetPathAttrs(), p.GetTimestamp(), false)
  1225  	path.SetExtCommunities(vrf.ExportRt, false)
  1226  	path.delPathAttr(bgp.BGP_ATTR_TYPE_NEXT_HOP)
  1227  	path.setPathAttr(bgp.NewPathAttributeMpReachNLRI(nh.String(), []bgp.AddrPrefixInterface{nlri}))
  1228  	return path
  1229  }
  1230  
  1231  func (p *Path) ToLocal() *Path {
  1232  	nlri := p.GetNlri()
  1233  	f := p.GetRouteFamily()
  1234  	localPathId := nlri.PathLocalIdentifier()
  1235  	pathId := nlri.PathIdentifier()
  1236  	switch f {
  1237  	case bgp.RF_IPv4_VPN:
  1238  		n := nlri.(*bgp.LabeledVPNIPAddrPrefix)
  1239  		_, c, _ := net.ParseCIDR(n.IPPrefix())
  1240  		ones, _ := c.Mask.Size()
  1241  		nlri = bgp.NewIPAddrPrefix(uint8(ones), c.IP.String())
  1242  		nlri.SetPathLocalIdentifier(localPathId)
  1243  		nlri.SetPathIdentifier(pathId)
  1244  	case bgp.RF_FS_IPv4_VPN:
  1245  		n := nlri.(*bgp.FlowSpecIPv4VPN)
  1246  		nlri = bgp.NewFlowSpecIPv4Unicast(n.FlowSpecNLRI.Value)
  1247  		nlri.SetPathLocalIdentifier(localPathId)
  1248  		nlri.SetPathIdentifier(pathId)
  1249  	case bgp.RF_IPv6_VPN:
  1250  		n := nlri.(*bgp.LabeledVPNIPv6AddrPrefix)
  1251  		_, c, _ := net.ParseCIDR(n.IPPrefix())
  1252  		ones, _ := c.Mask.Size()
  1253  		nlri = bgp.NewIPv6AddrPrefix(uint8(ones), c.IP.String())
  1254  		nlri.SetPathLocalIdentifier(localPathId)
  1255  		nlri.SetPathIdentifier(pathId)
  1256  	case bgp.RF_FS_IPv6_VPN:
  1257  		n := nlri.(*bgp.FlowSpecIPv6VPN)
  1258  		nlri = bgp.NewFlowSpecIPv6Unicast(n.FlowSpecNLRI.Value)
  1259  		nlri.SetPathLocalIdentifier(localPathId)
  1260  		nlri.SetPathIdentifier(pathId)
  1261  	default:
  1262  		return p
  1263  	}
  1264  	path := NewPath(p.OriginInfo().source, nlri, p.IsWithdraw, p.GetPathAttrs(), p.GetTimestamp(), false)
  1265  	switch f {
  1266  	case bgp.RF_IPv4_VPN, bgp.RF_IPv6_VPN:
  1267  		path.delPathAttr(bgp.BGP_ATTR_TYPE_EXTENDED_COMMUNITIES)
  1268  	case bgp.RF_FS_IPv4_VPN, bgp.RF_FS_IPv6_VPN:
  1269  		extcomms := path.GetExtCommunities()
  1270  		newExtComms := make([]bgp.ExtendedCommunityInterface, 0, len(extcomms))
  1271  		for _, extComm := range extcomms {
  1272  			_, subType := extComm.GetTypes()
  1273  			if subType == bgp.EC_SUBTYPE_ROUTE_TARGET {
  1274  				continue
  1275  			}
  1276  			newExtComms = append(newExtComms, extComm)
  1277  		}
  1278  		path.SetExtCommunities(newExtComms, true)
  1279  	}
  1280  
  1281  	if f == bgp.RF_IPv4_VPN {
  1282  		nh := path.GetNexthop()
  1283  		path.delPathAttr(bgp.BGP_ATTR_TYPE_MP_REACH_NLRI)
  1284  		path.setPathAttr(bgp.NewPathAttributeNextHop(nh.String()))
  1285  	}
  1286  	path.IsNexthopInvalid = p.IsNexthopInvalid
  1287  	return path
  1288  }
  1289  
  1290  func (p *Path) SetHash(v uint32) {
  1291  	p.attrsHash = v
  1292  }
  1293  
  1294  func (p *Path) GetHash() uint32 {
  1295  	return p.attrsHash
  1296  }
  1297  
  1298  func (p *Path) SetSource(peerInfo *PeerInfo) {
  1299  	if p.info != nil {
  1300  		p.info.source = peerInfo
  1301  	}
  1302  }
  1303  
  1304  func nlriToIPNet(nlri bgp.AddrPrefixInterface) *net.IPNet {
  1305  	switch T := nlri.(type) {
  1306  	case *bgp.IPAddrPrefix:
  1307  		return &net.IPNet{
  1308  			IP:   net.IP(T.Prefix.To4()),
  1309  			Mask: net.CIDRMask(int(T.Length), 32),
  1310  		}
  1311  	case *bgp.IPv6AddrPrefix:
  1312  		return &net.IPNet{
  1313  			IP:   net.IP(T.Prefix.To16()),
  1314  			Mask: net.CIDRMask(int(T.Length), 128),
  1315  		}
  1316  	case *bgp.LabeledIPAddrPrefix:
  1317  		return &net.IPNet{
  1318  			IP:   net.IP(T.Prefix.To4()),
  1319  			Mask: net.CIDRMask(int(T.Length)-T.Labels.Len()*8, 32),
  1320  		}
  1321  	case *bgp.LabeledIPv6AddrPrefix:
  1322  		return &net.IPNet{
  1323  			IP:   net.IP(T.Prefix.To16()),
  1324  			Mask: net.CIDRMask(int(T.Length)-T.Labels.Len()*8, 128),
  1325  		}
  1326  	case *bgp.LabeledVPNIPAddrPrefix:
  1327  		return &net.IPNet{
  1328  			IP:   net.IP(T.Prefix.To4()),
  1329  			Mask: net.CIDRMask(int(T.Length)-T.Labels.Len()*8-T.RD.Len()*8, 32),
  1330  		}
  1331  	case *bgp.LabeledVPNIPv6AddrPrefix:
  1332  		return &net.IPNet{
  1333  			IP:   net.IP(T.Prefix.To16()),
  1334  			Mask: net.CIDRMask(int(T.Length)-T.Labels.Len()*8-T.RD.Len()*8, 128),
  1335  		}
  1336  	}
  1337  	return nil
  1338  }