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 }