(peer *peer, path, old *table.Path)
| 582 | } |
| 583 | |
| 584 | func (s *BgpServer) prePolicyFilterpath(peer *peer, path, old *table.Path) (*table.Path, *table.PolicyOptions, bool) { |
| 585 | // Special handling for RTM NLRI. |
| 586 | if path != nil && path.GetFamily() == bgp.RF_RTC_UC && !path.IsWithdraw { |
| 587 | // If the given "path" is locally generated and the same with "old", we |
| 588 | // assumes "path" was already sent before. This assumption avoids the |
| 589 | // infinite UPDATE loop between Route Reflector and its clients. |
| 590 | if path.IsLocal() && path.Equal(old) { |
| 591 | s.logger.Debug("given rtm nlri is already sent, skipping to advertise", slog.Any("Path", path)) |
| 592 | return nil, nil, true |
| 593 | } |
| 594 | |
| 595 | if old != nil && old.IsLocal() { |
| 596 | // If it is vrf or rtc route deleting, it will work via explicitWithdraw |
| 597 | // and make old.Clone(true). The only way to get path != nil and old != nil |
| 598 | // is to change the path without changing rt. Then we need to update path or |
| 599 | // do nothing if path == old. |
| 600 | } else if peer.isRouteReflectorClient() { |
| 601 | // We need to send the path even if the peer is originator of the |
| 602 | // path in order to signal that the client should distribute route |
| 603 | // with the given RT. |
| 604 | } else { |
| 605 | // We send a path even if it is not the best path. See comments in |
| 606 | // (*Destination) GetChanges(). |
| 607 | dst := peer.localRib.GetDestination(path) |
| 608 | path = nil |
| 609 | for _, p := range dst.GetKnownPathList(peer.TableID(), peer.AS()) { |
| 610 | srcPeer := p.GetSource() |
| 611 | if peer.ID() != srcPeer.Address.String() { |
| 612 | if srcPeer.RouteReflectorClient { |
| 613 | // The path from a RR client is preferred than others |
| 614 | // for the case that RR and non RR client peering |
| 615 | // (e.g., peering of different RR clusters). |
| 616 | path = p |
| 617 | break |
| 618 | } else if path == nil { |
| 619 | path = p |
| 620 | } |
| 621 | } |
| 622 | } |
| 623 | } |
| 624 | } |
| 625 | |
| 626 | // only allow vpnv4 and vpnv6 paths to be advertised to VRFed neighbors. |
| 627 | // also check we can import this path using table.CanImportToVrf() |
| 628 | // if we can, make it local path by calling (*Path).ToLocal() |
| 629 | conf := peer.fsm.pConf.ReadOnly() |
| 630 | peerVrf := conf.Config.Vrf |
| 631 | if path != nil && peerVrf != "" { |
| 632 | if f := path.GetFamily(); f != bgp.RF_IPv4_VPN && f != bgp.RF_IPv6_VPN && f != bgp.RF_FS_IPv4_VPN && f != bgp.RF_FS_IPv6_VPN { |
| 633 | return nil, nil, true |
| 634 | } |
| 635 | vrf, ok := peer.localRib.GetVrf(peerVrf) |
| 636 | if !ok { |
| 637 | return nil, nil, true |
| 638 | } |
| 639 | if table.CanImportToVrf(vrf, path) { |
| 640 | path = path.ToLocal() |
| 641 | } else { |
no test coverage detected