LCOV - code coverage report
Current view: top level - vnsw/agent/controller - controller_route_path.cc (source / functions) Hit Total Coverage
Test: OpenSDN C/C++ coverage (all TARGET_SET jobs) Lines: 120 504 23.8 %
Date: 2026-08-03 02:19:58 Functions: 7 15 46.7 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /*
       2             :  * Copyright (c) 2014-2024 Juniper Networks, Inc. All rights reserved.
       3             :  * Copyright (c) 2024 Elena Zizganova
       4             :  */
       5             : 
       6             : #include <boost/uuid/uuid_io.hpp>
       7             : #include <boost/lexical_cast.hpp>
       8             : 
       9             : #include <cmn/agent_cmn.h>
      10             : #include <route/route.h>
      11             : 
      12             : #include <cmn/agent_cmn.h>
      13             : #include <oper/ecmp_load_balance.h>
      14             : #include <oper/ecmp.h>
      15             : #include <oper/route_common.h>
      16             : #include <oper/vrf.h>
      17             : #include <oper/tunnel_nh.h>
      18             : #include <oper/mpls.h>
      19             : #include <oper/mirror_table.h>
      20             : #include <oper/peer.h>
      21             : #include <oper/agent_route.h>
      22             : #include <controller/controller_route_path.h>
      23             : #include <controller/controller_peer.h>
      24             : #include <controller/controller_init.h>
      25             : #include <controller/controller_export.h>
      26             : #include <controller/controller_types.h>
      27             : #include <oper/vxlan_routing_manager.h>
      28             : #include <oper/agent_sandesh.h>
      29             : #include <xmpp/xmpp_channel.h>
      30             : #include <xmpp_enet_types.h>
      31             : #include <xmpp_unicast_types.h>
      32             : 
      33             : using namespace std;
      34             : using namespace boost::asio;
      35             : 
      36          19 : ControllerPeerPath::ControllerPeerPath(const BgpPeer *peer) :
      37          19 :     AgentRouteData(AgentRouteData::ADD_DEL_CHANGE, false, 0), peer_(peer) {
      38          19 :     sequence_number_ = 0;
      39          19 :     if (peer)
      40          19 :         sequence_number_ = peer->GetAgentXmppChannel()->
      41          19 :             sequence_number();
      42          19 : }
      43             : 
      44           1 : bool ControllerEcmpRoute::CopyToPath(AgentPath *path) {
      45           1 :     bool ret = false;
      46             : 
      47           1 :     path->set_peer_sequence_number(sequence_number());
      48           1 :     if (path->ecmp_load_balance() != ecmp_load_balance_) {
      49           0 :         path->UpdateEcmpHashFields(agent_, ecmp_load_balance_,
      50           0 :                                           nh_req_);
      51           0 :         ret = true;
      52             :     }
      53             : 
      54           1 :     return ret;
      55             : }
      56             : 
      57           1 : bool ControllerEcmpRoute::AddChangePathExtended(Agent *agent, AgentPath *path,
      58             :                                                 const AgentRoute *rt) {
      59           1 :     bool path_unresolved = false;
      60           1 :     path->set_copy_local_path(copy_local_path_);
      61             : 
      62             :     // check if tunnel type is mpls and vrf is non default
      63           1 :     if ((tunnel_bmap_ == (1 << TunnelType::MPLS_OVER_MPLS)) &&
      64           0 :             (vrf_name_ != agent->fabric_vrf_name())) {
      65             : 
      66             :         // this path depends on inet.3 route table,
      67             :         // update dependent_table if it is not set already.
      68           0 :         if (!path->GetDependentTable()) {
      69           0 :             InetUnicastAgentRouteTable *table = NULL;
      70             :             table = static_cast<InetUnicastAgentRouteTable *>
      71           0 :                 (agent->fabric_inet4_mpls_table());
      72           0 :             assert(table != NULL);
      73           0 :             path->SetDependentTable(table);
      74             :         }
      75             :         InetUnicastAgentRouteTable *table =
      76           0 :             (InetUnicastAgentRouteTable *)path->GetDependentTable();
      77           0 :         assert(table != NULL);
      78           0 :         AgentPathEcmpComponentPtrList new_list;
      79           0 :         ComponentNHKeyList comp_nh_list;
      80           0 :         bool comp_nh_policy = false;
      81           0 :         for (uint32_t i = 0; i < tunnel_dest_list_.size(); i++) {
      82             :             // step1: update ecmpcomponent list
      83           0 :             IpAddress addr = tunnel_dest_list_[i];
      84           0 :             uint32_t label = label_list_[i];
      85             :             AgentPathEcmpComponentPtr member(new AgentPathEcmpComponent(
      86           0 :                                     addr, label, path->GetParentRoute()));
      87           0 :             InetUnicastRouteEntry *uc_rt = table->FindRoute(addr);
      88             :             const NextHop *anh;
      89           0 :             if (uc_rt == NULL || uc_rt->prefix_length() == 0 || (anh = uc_rt->GetActiveNextHop()) == NULL) {
      90           0 :                 member->SetUnresolved(true);
      91           0 :                 if (!path_unresolved) {
      92           0 :                     path_unresolved  = true;
      93             :                     DBEntryBase::KeyPtr key =
      94           0 :                      agent->nexthop_table()->discard_nh()->GetDBRequestKey();
      95             :                     NextHopKey *nh_key =
      96           0 :                         static_cast<NextHopKey *>(key.release());
      97           0 :                     std::unique_ptr<const NextHopKey> nh_key_ptr(nh_key);
      98             :                     ComponentNHKeyPtr component_nh_key(new ComponentNHKey(label,
      99           0 :                                                    std::move(nh_key_ptr)));
     100           0 :                     comp_nh_list.push_back(component_nh_key);
     101           0 :                 }
     102             :             } else {
     103             :                 DBEntryBase::KeyPtr key =
     104           0 :                     anh->GetDBRequestKey();
     105           0 :                 NextHopKey *nh_key = static_cast<NextHopKey *>(key.release());
     106           0 :                 if (nh_key->GetType() != NextHop::COMPOSITE) {
     107             :                     //By default all component members of composite NH
     108             :                     //will be policy disabled, except for component NH
     109             :                     //of type composite
     110           0 :                     nh_key->SetPolicy(false);
     111             :                 }
     112           0 :                 std::unique_ptr<const NextHopKey> nh_key_ptr(nh_key);
     113             :                 ComponentNHKeyPtr component_nh_key(new ComponentNHKey(label,
     114           0 :                                                    std::move(nh_key_ptr)));
     115           0 :                 comp_nh_list.push_back(component_nh_key);
     116             :                 //Reset to new gateway route, no nexthop for indirect route
     117           0 :                 member->UpdateDependentRoute(uc_rt);
     118           0 :                 member->SetUnresolved(false);
     119           0 :             }
     120           0 :             new_list.push_back(member);
     121           0 :         }
     122           0 :         DBRequest nh_req(DBRequest::DB_ENTRY_ADD_CHANGE);
     123           0 :         nh_req.key.reset(new CompositeNHKey(Composite::ECMP, comp_nh_policy,
     124           0 :                                     comp_nh_list, vrf_name_));
     125           0 :         nh_req.data.reset(new CompositeNHData());
     126           0 :         nh_req_.Swap(&nh_req);
     127           0 :         path->ResetEcmpMemberList(new_list);
     128           0 :     }
     129           1 :     path->set_vrf_name(vrf_name_);
     130             : 
     131           1 :     CompositeNHKey *comp_key = static_cast<CompositeNHKey *>(nh_req_.key.get());
     132           1 :     bool ret = false;
     133             : 
     134           1 :     if (tunnel_bmap_ == TunnelType::VxlanType() && vxlan_id_ != 0) {
     135           0 :         path->set_vxlan_id(vxlan_id_);
     136             :     }
     137             : 
     138             :     //Reorder the component NH list, and add a reference to local composite mpls
     139             :     //label if any
     140           1 :     bool comp_nh_policy = comp_key->GetPolicy();
     141           1 :     bool new_comp_nh_policy = false;
     142           3 :     if (path->ReorderCompositeNH(agent, comp_key, new_comp_nh_policy,
     143           1 :                                  rt->FindLocalVmPortPath()) == false) {
     144           0 :         return false;
     145             :     }
     146           1 :     if (!comp_nh_policy) {
     147           1 :         comp_key->SetPolicy(new_comp_nh_policy);
     148             :     }
     149           1 :     ret |= CopyToPath(path);
     150             : 
     151           1 :     EcmpData ecmp_data(agent, rt->vrf()->GetName(), rt->ToString(),
     152           1 :                        path, false);
     153           1 :     ret |= ecmp_data.UpdateWithParams(sg_list_, tag_list_, CommunityList(),
     154           1 :                                 path_preference_, tunnel_bmap_,
     155           1 :                                 ecmp_load_balance_, vn_list_, nh_req_);
     156           1 :     path->set_unresolved(path_unresolved);
     157             : 
     158             :     // Set dest vn
     159           1 :     path->set_dest_vn_list(vn_list_);
     160             : 
     161           1 :     return ret;
     162           1 : }
     163             : 
     164             : template <typename TYPE>
     165           0 : ControllerEcmpRoute::ControllerEcmpRoute(const BgpPeer *peer,
     166             :                                          const VnListType &vn_list,
     167             :                                          const EcmpLoadBalance &ecmp_load_balance,
     168             :                                          const TagList &tag_list,
     169             :                                          const TYPE *item,
     170             :                                          const AgentRouteTable *rt_table,
     171             :                                          const std::string &prefix_str) :
     172           0 :         ControllerPeerPath(peer), vn_list_(vn_list),
     173           0 :         ecmp_load_balance_(ecmp_load_balance), tag_list_(tag_list),
     174           0 :         copy_local_path_(false), vxlan_id_(0) {
     175           0 :     const AgentXmppChannel *channel = peer->GetAgentXmppChannel();
     176           0 :     std::string bgp_peer_name = channel->GetBgpPeerName();
     177           0 :     std::string vrf_name = rt_table->vrf_name();
     178           0 :     agent_ = rt_table->agent();
     179           0 :     vrf_name_  = vrf_name;
     180           0 :     uint32_t label = item->entry.next_hops.next_hop[0].label;
     181           0 :     Composite::Type composite_nh_type = Composite::ECMP;
     182             : 
     183             :     // use LOW PathPreference if local preference attribute is not set
     184           0 :     uint32_t preference = PathPreference::LOW;
     185           0 :     TunnelType::TypeBmap encap = TunnelType::AllType(); //default
     186           0 :     if (item->entry.local_preference != 0) {
     187           0 :         preference = item->entry.local_preference;
     188             :     }
     189             : 
     190             :     //Override encap type for fabric VRF routes
     191             :     //only type supported is underlay
     192           0 :     if (vrf_name == agent_->fabric_vrf_name()) {
     193           0 :         encap = TunnelType::NativeType();
     194             :     }
     195             : 
     196           0 :     const bool is_routing_vrf = VxlanRoutingManager::IsVxlanAvailable(agent_)
     197           0 :         && VxlanRoutingManager::IsRoutingVrf(vrf_name, agent_);
     198             :     // Override encap type for routing VRF routes
     199           0 :     if (is_routing_vrf) {
     200           0 :         encap = TunnelType::VxlanType();
     201           0 :         vxlan_id_ = label;
     202             :     }
     203             : 
     204           0 :     std::vector<std::string> peer_sources;
     205           0 :     for (const auto &peer_addr : item->entry.peers.peer) {
     206           0 :         peer_sources.push_back(peer_addr);
     207             :     }
     208             : 
     209           0 :     PathPreference rp(item->entry.sequence_number, preference, false, false);
     210           0 :     path_preference_ = rp;
     211             : 
     212           0 :     sg_list_ = item->entry.security_group_list.security_group;
     213             : 
     214           0 :     ComponentNHKeyList comp_nh_list;
     215           0 :     bool intf_exist = false;
     216           0 :     bool tun_exist = false;
     217           0 :     bool comp_nh_policy = false;
     218           0 :     for (uint32_t i = 0; i < item->entry.next_hops.next_hop.size(); i++) {
     219           0 :         std::string nexthop_addr =
     220           0 :             item->entry.next_hops.next_hop[i].address;
     221           0 :         boost::system::error_code ec;
     222           0 :         IpAddress addr = IpAddress::from_string(nexthop_addr, ec);
     223           0 :         if (ec.value() != 0) {
     224           0 :             CONTROLLER_TRACE(Trace, bgp_peer_name, vrf_name,
     225             :                              "Error parsing nexthop ip address");
     226           0 :             continue;
     227             :         }
     228           0 :         if (!addr.is_v4()) {
     229           0 :             CONTROLLER_TRACE(Trace, bgp_peer_name, vrf_name,
     230             :                              "Non IPv4 address not supported as nexthop");
     231           0 :             continue;
     232             :         }
     233             : 
     234           0 :         if (comp_nh_list.size() >= maximum_ecmp_paths) {
     235           0 :             std::stringstream msg;
     236             :             msg << "Nexthop paths for prefix "
     237             :                 << prefix_str
     238           0 :                 << " (" << item->entry.next_hops.next_hop.size()
     239           0 :                 << ") exceed the maximum supported, ignoring them";
     240           0 :             CONTROLLER_TRACE(Trace, bgp_peer_name, vrf_name, msg.str());
     241           0 :             break;
     242           0 :         }
     243             : 
     244           0 :         uint32_t label = item->entry.next_hops.next_hop[i].label;
     245           0 :         if (agent_->router_id() == addr.to_v4()) {
     246           0 :             encap = agent_->controller()->GetTypeBitmap
     247           0 :               (item->entry.next_hops.next_hop[i].tunnel_encapsulation_list);
     248             :             //Get local list of interface and append to the list
     249             :             MplsLabel *mpls =
     250           0 :                 agent_->mpls_table()->FindMplsLabel(label);
     251           0 :             if (mpls != NULL && !is_routing_vrf) {
     252           0 :                 if (mpls->nexthop()->GetType() == NextHop::VRF) {
     253           0 :                     ClonedLocalPath *data =
     254           0 :                         new ClonedLocalPath(label, vn_list,
     255           0 :                                 item->entry.security_group_list.security_group,
     256           0 :                                 tag_list, sequence_number());
     257           0 :                     cloned_data_list_.push_back(data);
     258           0 :                     continue;
     259           0 :                 }
     260             : 
     261           0 :                 const NextHop *mpls_nh = mpls->nexthop();
     262           0 :                 DBEntryBase::KeyPtr key = mpls_nh->GetDBRequestKey();
     263           0 :                 NextHopKey *nh_key = static_cast<NextHopKey *>(key.release());
     264           0 :                 if (nh_key->GetType() != NextHop::COMPOSITE) {
     265             :                     //By default all component members of composite NH
     266             :                     //will be policy disabled, except for component NH
     267             :                     //of type composite
     268           0 :                     nh_key->SetPolicy(false);
     269             :                 }
     270           0 :                 std::unique_ptr<const NextHopKey> nh_key_ptr(nh_key);
     271           0 :                 ComponentNHKeyPtr component_nh_key(new ComponentNHKey(label,
     272           0 :                                                    std::move(nh_key_ptr)));
     273           0 :                 comp_nh_list.push_back(component_nh_key);
     274           0 :                 if (!comp_nh_policy) {
     275           0 :                     comp_nh_policy = mpls_nh->NexthopToInterfacePolicy();
     276             :                 }
     277           0 :                 tunnel_dest_list_.push_back(addr);
     278           0 :                 label_list_.push_back(label);
     279           0 :             } else {
     280           0 :                 if (label == 0) {
     281           0 :                     copy_local_path_ = true;
     282             :                 }
     283           0 :                 if (is_routing_vrf) {
     284           0 :                     encap = TunnelType::VxlanType();
     285           0 :                     VxlanRoutingManager::AddInterfaceComponentToList(item->entry.nlri.address,
     286             :                         vrf_name,
     287           0 :                         item->entry.next_hops.next_hop[i],
     288             :                         comp_nh_list,
     289             :                         peer_sources);
     290           0 :                     intf_exist = true;
     291             :                 }
     292             :             }
     293             :         } else {
     294           0 :             encap = agent_->controller()->GetTypeBitmap
     295           0 :                 (item->entry.next_hops.next_hop[i].tunnel_encapsulation_list);
     296           0 :             if (is_routing_vrf){
     297           0 :                 encap = TunnelType::VxlanType();
     298             :             }
     299           0 :             if (vrf_name == agent_->fabric_vrf_name()) {
     300           0 :                 if (label != MplsTable::kInvalidLabel &&
     301           0 :                         label != MplsTable::kInvalidExportLabel) {
     302           0 :                     encap = TunnelType::MplsoMplsType();
     303             :                 } else {
     304           0 :                     encap = TunnelType::NativeType();
     305             :                 }
     306             :             }
     307           0 :             MacAddress mac = agent_->controller()->GetTunnelMac
     308           0 :                 (item->entry.next_hops.next_hop[i]);
     309           0 :             if (encap == TunnelType::MplsoMplsType() &&
     310           0 :                     vrf_name == agent_->fabric_vrf_name()) {
     311           0 :                 composite_nh_type = Composite::LU_ECMP;
     312           0 :                 LabelledTunnelNHKey *nh_key = new LabelledTunnelNHKey(
     313           0 :                                             agent_->fabric_vrf_name(),
     314           0 :                                             agent_->router_id(),
     315             :                                             addr.to_v4(),
     316             :                                             false,
     317             :                                             TunnelType::ComputeType(encap),
     318             :                                             mac,
     319             :                                             label);
     320           0 :                 std::unique_ptr<const NextHopKey> nh_key_ptr(nh_key);
     321           0 :                 ComponentNHKeyPtr component_nh_key(new ComponentNHKey(label,
     322           0 :                                                                     std::move(nh_key_ptr)));
     323           0 :                 comp_nh_list.push_back(component_nh_key);
     324           0 :             } else if (encap == TunnelType::MplsoMplsType()) {
     325             :                 // copy ecmp nexthop list
     326           0 :                 tunnel_dest_list_.push_back(addr);
     327           0 :                 label_list_.push_back(label);
     328             :             } else {
     329           0 :                 TunnelNHKey *nh_key = NULL;
     330           0 :                 if (is_routing_vrf) {
     331           0 :                     nh_key = agent_->oper_db()->vxlan_routing_manager()->
     332           0 :                         AllocateTunnelNextHopKey(addr, mac);
     333           0 :                     tun_exist = true;
     334             :                 } else {
     335           0 :                     nh_key = new TunnelNHKey(agent_->fabric_vrf_name(),
     336           0 :                         agent_->router_id(),
     337             :                         addr.to_v4(),
     338             :                         false,
     339             :                         TunnelType::ComputeType(encap),
     340             :                         mac);
     341             :                 }
     342             : 
     343           0 :                 std::unique_ptr<const NextHopKey> nh_key_ptr(nh_key);
     344           0 :                 ComponentNHKeyPtr component_nh_key(new ComponentNHKey(label,
     345           0 :                                                                     std::move(nh_key_ptr)));
     346           0 :                 comp_nh_list.push_back(component_nh_key);
     347           0 :             }
     348             :         }
     349             :     }
     350             : 
     351           0 :     if (intf_exist && tun_exist) {
     352           0 :         for (auto &comp_nh_ptr : comp_nh_list) {
     353           0 :             if (comp_nh_ptr == nullptr) {
     354           0 :                 continue;
     355             :             }
     356           0 :             if (comp_nh_ptr->nh_key()->GetType() != NextHop::INTERFACE)
     357             :             {
     358           0 :                 comp_nh_ptr.reset();
     359             :             }
     360             :         }
     361             :     }
     362           0 :     if (intf_exist) {
     363           0 :         comp_nh_policy = true;
     364           0 :         composite_nh_type = Composite::LOCAL_ECMP;
     365             :     }
     366             : 
     367           0 :     tunnel_bmap_ = encap;
     368           0 :     if ((encap != TunnelType::MplsoMplsType()) ||
     369           0 :             ((encap == TunnelType::MplsoMplsType()) &&
     370           0 :              (vrf_name_ == agent_->fabric_vrf_name())))  {
     371             :         // Build the NH request and then create route data to be passed
     372           0 :         DBRequest nh_req(DBRequest::DB_ENTRY_ADD_CHANGE);
     373           0 :         nh_req.key.reset(new CompositeNHKey(composite_nh_type, comp_nh_policy,
     374             :                                             comp_nh_list, vrf_name));
     375           0 :         nh_req.data.reset(new CompositeNHData());
     376           0 :         nh_req_.Swap(&nh_req);
     377           0 :     }
     378           0 :  }
     379             : 
     380           1 : ControllerEcmpRoute::ControllerEcmpRoute(const BgpPeer *peer,
     381             :                         const VnListType &vn_list,
     382             :                         const EcmpLoadBalance &ecmp_load_balance,
     383             :                         const TagList &tag_list,
     384             :                         const SecurityGroupList &sg_list,
     385             :                         const PathPreference &path_pref,
     386             :                         TunnelType::TypeBmap tunnel_bmap,
     387             :                         DBRequest &nh_req,
     388             :                         const std::string &prefix_str,
     389           1 :                         const std::string vrf_name) :
     390           1 :     ControllerPeerPath(peer), vn_list_(vn_list), sg_list_(sg_list),
     391           1 :     ecmp_load_balance_(ecmp_load_balance), tag_list_(tag_list),
     392           1 :     path_preference_(path_pref), tunnel_bmap_(tunnel_bmap),
     393           2 :     copy_local_path_(false), vxlan_id_(0) {
     394           1 :     nh_req_.Swap(&nh_req);
     395           1 :     agent_ = peer->agent();
     396           1 :     if (vrf_name.size() == 0) {
     397           1 :         vrf_name_ = agent_->fabric_vrf_name();
     398             :     } else {
     399           0 :         vrf_name_ = vrf_name;
     400             :     }
     401           3 :     const bool is_routing_vrf = VxlanRoutingManager::IsVxlanAvailable(agent_) && VxlanRoutingManager::IsRoutingVrf(vrf_name,
     402           2 :        agent_);
     403           1 :     if (is_routing_vrf || tunnel_bmap == TunnelType::VxlanType()) {
     404           0 :         tunnel_bmap_ = TunnelType::VxlanType();
     405           0 :         vxlan_id_ = agent_->vrf_table()->
     406           0 :             FindVrfFromName(vrf_name)->vxlan_id();
     407             :     }
     408           1 : }
     409             : 
     410           0 : ControllerEcmpRoute::ControllerEcmpRoute(const BgpPeer *peer,
     411             :                         const VnListType &vn_list,
     412             :                         const EcmpLoadBalance &ecmp_load_balance,
     413             :                         const TagList &tag_list,
     414             :                         const SecurityGroupList &sg_list,
     415             :                         const PathPreference &path_pref,
     416             :                         TunnelType::TypeBmap tunnel_bmap,
     417             :                         std::vector<IpAddress> &tunnel_dest_list,
     418             :                         std::vector<uint32_t> &label_list,
     419             :                         const std::string &prefix_str,
     420           0 :                         const std::string &vrf_name):
     421           0 :     ControllerPeerPath(peer), vn_list_(vn_list), sg_list_(sg_list),
     422           0 :     ecmp_load_balance_(ecmp_load_balance), tag_list_(tag_list),
     423           0 :     path_preference_(path_pref), tunnel_bmap_(tunnel_bmap),
     424           0 :     copy_local_path_(false), tunnel_dest_list_(tunnel_dest_list),
     425           0 :     label_list_(label_list), vrf_name_(vrf_name), vxlan_id_(0) {
     426           0 :     agent_ = peer->agent();
     427           0 : }
     428             : 
     429           9 : ControllerVmRoute *ControllerVmRoute::MakeControllerVmRoute(
     430             :                                          const BgpPeer *bgp_peer,
     431             :                                          const string &default_vrf,
     432             :                                          const Ip4Address &router_id,
     433             :                                          const string &vrf_name,
     434             :                                          const Ip4Address &tunnel_dest,
     435             :                                          TunnelType::TypeBmap bmap,
     436             :                                          uint32_t label,
     437             :                                          const MacAddress rewrite_dmac,
     438             :                                          const VnListType &dest_vn_list,
     439             :                                          const SecurityGroupList &sg_list,
     440             :                                          const TagList &tag_list,
     441             :                                          const PathPreference &path_preference,
     442             :                                          bool ecmp_suppressed,
     443             :                                          const EcmpLoadBalance &ecmp_load_balance,
     444             :                                          bool etree_leaf) {
     445             : 
     446           9 :     DBRequest nh_req(DBRequest::DB_ENTRY_ADD_CHANGE);
     447             :     // Make Tunnel-NH request
     448          18 :     nh_req.key.reset(new TunnelNHKey(default_vrf, router_id, tunnel_dest, false,
     449             :                                     TunnelType::ComputeType(bmap),
     450           9 :                                     rewrite_dmac));
     451           9 :     nh_req.data.reset(new TunnelNHData());
     452             : 
     453             :     // Make route request pointing to Tunnel-NH created above
     454             :     ControllerVmRoute *data =
     455             :         new ControllerVmRoute(bgp_peer, default_vrf, tunnel_dest, label,
     456             :                               dest_vn_list, bmap, sg_list, tag_list, path_preference,
     457             :                               nh_req, ecmp_suppressed,
     458           9 :                               ecmp_load_balance, etree_leaf, rewrite_dmac);
     459           9 :     return data;
     460           9 : }
     461             : 
     462           0 : ControllerMplsRoute *ControllerMplsRoute::MakeControllerMplsRoute(
     463             :                                          const BgpPeer *bgp_peer,
     464             :                                          const string &default_vrf,
     465             :                                          const Ip4Address &router_id,
     466             :                                          const string &vrf_name,
     467             :                                          const Ip4Address &tunnel_dest,
     468             :                                          TunnelType::TypeBmap bmap,
     469             :                                          uint32_t label,
     470             :                                          const MacAddress rewrite_dmac,
     471             :                                          const VnListType &dest_vn_list,
     472             :                                          const SecurityGroupList &sg_list,
     473             :                                          const TagList &tag_list,
     474             :                                          const PathPreference &path_preference,
     475             :                                          bool ecmp_suppressed,
     476             :                                          const EcmpLoadBalance &ecmp_load_balance,
     477             :                                          bool etree_leaf) {
     478             :  
     479           0 :     DBRequest nh_req(DBRequest::DB_ENTRY_ADD_CHANGE);
     480             :     // Make Labelled Tunnel-NH request
     481           0 :     nh_req.key.reset(new LabelledTunnelNHKey(default_vrf, router_id, tunnel_dest, false,
     482             :                                     TunnelType::MPLS_OVER_MPLS,
     483           0 :                                     rewrite_dmac, label));
     484           0 :     nh_req.data.reset(new LabelledTunnelNHData());
     485             : 
     486             :     // Make route request pointing to Labelled Tunnel-NH created above
     487             :     ControllerMplsRoute *data =
     488             :         new ControllerMplsRoute(bgp_peer, default_vrf, tunnel_dest, label,
     489             :                               dest_vn_list, bmap, sg_list, tag_list, path_preference,
     490             :                               nh_req, ecmp_suppressed,
     491           0 :                               ecmp_load_balance, etree_leaf, rewrite_dmac);
     492           0 :     return data;
     493           0 : }
     494           9 : bool ControllerVmRoute::UpdateRoute(AgentRoute *rt) {
     495           9 :     bool ret = false;
     496             :     // For IP subnet routes with Tunnel NH, update arp_flood_ and
     497             :     // local_host_flag_ flags
     498          15 :     if ((rt->GetTableType() == Agent::INET4_UNICAST) ||
     499           6 :         (rt->GetTableType() == Agent::INET6_UNICAST)) {
     500           3 :         InetUnicastRouteEntry *inet_rt =
     501             :             static_cast<InetUnicastRouteEntry *>(rt);
     502             :         //If its the IPAM route then no change required neither
     503             :         //super net needs to be searched.
     504           3 :         if (inet_rt->ipam_subnet_route())
     505           0 :             return ret;
     506             : 
     507           3 :         bool ipam_subnet_route = inet_rt->IpamSubnetRouteAvailable();
     508           3 :         ret = inet_rt->UpdateIpamHostFlags(ipam_subnet_route);
     509             :     }
     510           9 :     return ret;
     511             : }
     512             : 
     513           9 : bool ControllerVmRoute::AddChangePathExtended(Agent *agent, AgentPath *path,
     514             :                                               const AgentRoute *rt) {
     515           9 :     bool ret = false;
     516           9 :     NextHop *nh = NULL;
     517           9 :     SecurityGroupList path_sg_list;
     518             : 
     519           9 :     path->set_peer_sequence_number(sequence_number());
     520           9 :     if (path->tunnel_bmap() != tunnel_bmap_) {
     521           8 :         path->set_tunnel_bmap(tunnel_bmap_);
     522           8 :         ret = true;
     523             :     }
     524             : 
     525           9 :     TunnelType::Type new_tunnel_type = TunnelType::ComputeType(tunnel_bmap_);
     526           9 :     if (new_tunnel_type == TunnelType::MPLS_OVER_MPLS) {
     527             :         // this path depends on inet.3 route table,
     528             :         // update dependent_table if it is not set already.
     529           0 :         if (!path->GetDependentTable()) {
     530           0 :             InetUnicastAgentRouteTable *table = NULL;
     531             :             table = static_cast<InetUnicastAgentRouteTable *>
     532           0 :                 (agent->fabric_inet4_mpls_table());
     533           0 :             assert(table != NULL);
     534           0 :             path->SetDependentTable(table);
     535             :         }
     536             :         InetUnicastAgentRouteTable *table =
     537           0 :             (InetUnicastAgentRouteTable *)path->GetDependentTable();
     538             : 
     539           0 :         AgentPathEcmpComponentPtrList new_list; 
     540             :         AgentPathEcmpComponentPtr member( new AgentPathEcmpComponent(
     541           0 :                                         tunnel_dest_, label_,
     542           0 :                                         path->GetParentRoute()));
     543           0 :         InetUnicastRouteEntry *uc_rt = table->FindRoute(tunnel_dest_);
     544             :         const NextHop *anh;
     545           0 :         if (uc_rt == NULL || uc_rt->prefix_length() == 0 || (anh = uc_rt->GetActiveNextHop()) == NULL) {
     546           0 :             path->set_unresolved(true);
     547           0 :             member->SetUnresolved(false);
     548             :         } else {
     549           0 :             path->set_unresolved(false);
     550           0 :             DBEntryBase::KeyPtr key = anh->GetDBRequestKey();
     551             :             const NextHopKey *nh_key =
     552           0 :                     static_cast<const NextHopKey*>(key.get());
     553           0 :             nh = static_cast<NextHop *>(agent->nexthop_table()->
     554           0 :                                 FindActiveEntry(nh_key));
     555           0 :             assert(nh !=NULL);
     556             :             //Reset to new gateway route, no nexthop for indirect route
     557           0 :             member->UpdateDependentRoute(uc_rt);
     558           0 :             member->SetUnresolved(false);
     559           0 :             path->set_gw_ip(tunnel_dest_);
     560           0 :             path->set_nexthop(NULL);
     561           0 :         }
     562           0 :         new_list.push_back(member);
     563           0 :         path->ResetEcmpMemberList(new_list);
     564             : 
     565           0 :     } else {
     566             : 
     567           9 :         if ((tunnel_bmap_ == (1 << TunnelType::VXLAN) &&
     568           9 :             (new_tunnel_type != TunnelType::VXLAN)) ||
     569           9 :             (tunnel_bmap_ != (1 << TunnelType::VXLAN) &&
     570             :             (new_tunnel_type == TunnelType::VXLAN))) {
     571           0 :             new_tunnel_type = TunnelType::INVALID;
     572           0 :             nh_req_.key.reset(new TunnelNHKey(agent->fabric_vrf_name(),
     573           0 :                                             agent->router_id(), tunnel_dest_,
     574             :                                             false, new_tunnel_type,
     575           0 :                                             rewrite_dmac_));
     576             :         }
     577           9 :         agent->nexthop_table()->Process(nh_req_);
     578          18 :         TunnelNHKey key(agent->fabric_vrf_name(), agent->router_id(), tunnel_dest_,
     579          18 :                         false, new_tunnel_type, rewrite_dmac_);
     580           9 :         nh = static_cast<NextHop *>(agent->nexthop_table()->FindActiveEntry(&key));
     581             : 
     582           9 :         path->set_unresolved(false);
     583           9 :     }
     584           9 :     path->set_tunnel_dest(tunnel_dest_);
     585             : 
     586           9 :     if (path->tunnel_type() != new_tunnel_type) {
     587           5 :         path->set_tunnel_type(new_tunnel_type);
     588           5 :         ret = true;
     589             :     }
     590             : 
     591             :     //Interpret label sent by control node
     592           9 :     if (tunnel_bmap_ == TunnelType::VxlanType()) {
     593             :         // Only VXLAN encap is sent, so label is VXLAN
     594             :         // For vxlan routing vn external route label can change , add path change
     595          16 :         if (rt->vrf() && rt->vrf()->vn() &&
     596          16 :             rt->vrf()->vn()->vxlan_routing_vn() && path->vxlan_id() != label_) {
     597           0 :             ret = true;
     598             :         }
     599           6 :         path->set_vxlan_id(label_);
     600           6 :         if (path->label() != MplsTable::kInvalidLabel) {
     601           0 :             path->set_label(MplsTable::kInvalidLabel);
     602           0 :             ret = true;
     603             :         }
     604           6 :     } else if ((tunnel_bmap_ == TunnelType::MplsType())||
     605           3 :             (tunnel_bmap_ == TunnelType::MplsoMplsType())) {
     606             :         //MPLS (GRE/UDP) is the only encap sent,
     607             :         //so label is MPLS.
     608           0 :         if (path->label() != label_) {
     609           0 :             path->set_label(label_);
     610           0 :             ret = true;
     611             :         }
     612           0 :         path->set_vxlan_id(VxLanTable::kInvalidvxlan_id);
     613             :     } else {
     614             :         //Got a mix of Vxlan and Mpls, so interpret label
     615             :         //as per the computed tunnel type.
     616           3 :         if (new_tunnel_type == TunnelType::VXLAN) {
     617           0 :             if (path->vxlan_id() != label_) {
     618           0 :                 path->set_vxlan_id(label_);
     619           0 :                 path->set_label(MplsTable::kInvalidLabel);
     620           0 :                 ret = true;
     621             :             }
     622             :         } else {
     623           3 :             if (path->label() != label_) {
     624           3 :                 path->set_label(label_);
     625           3 :                 path->set_vxlan_id(VxLanTable::kInvalidvxlan_id);
     626           3 :                 ret = true;
     627             :             }
     628             :         }
     629             :     }
     630             : 
     631           9 :     if (path->dest_vn_list() != dest_vn_list_) {
     632           8 :         path->set_dest_vn_list(dest_vn_list_);
     633           8 :         ret = true;
     634             :     }
     635             : 
     636           9 :     if (nh != NULL) {
     637           9 :         if (path->ChangeNH(agent, nh) == true)
     638           8 :         ret = true;
     639             :     }
     640             : 
     641           9 :     path_sg_list = path->sg_list();
     642           9 :     if (path_sg_list != sg_list_) {
     643           9 :         path->set_sg_list(sg_list_);
     644           9 :         ret = true;
     645             :     }
     646             : 
     647           9 :     if (tag_list_ != path->tag_list()) {
     648           0 :         path->set_tag_list(tag_list_);
     649           0 :         ret = true;
     650             :     }
     651             : 
     652           9 :     if (path->path_preference() != path_preference_) {
     653           0 :         path->set_path_preference(path_preference_);
     654           0 :         ret = true;
     655             :     }
     656             : 
     657             :     //If a transition of path happens from ECMP to non ECMP
     658             :     //reset local mpls label reference and composite nh key
     659           9 :     if (path->composite_nh_key()) {
     660           0 :         path->set_composite_nh_key(NULL);
     661           0 :         path->set_local_ecmp_mpls_label(NULL);
     662             :     }
     663             : 
     664           9 :     if (path->ecmp_suppressed() != ecmp_suppressed_) {
     665           0 :         path->set_ecmp_suppressed(ecmp_suppressed_);
     666           0 :         ret = true;
     667             :     }
     668             : 
     669           9 :     if (ecmp_load_balance_ != path->ecmp_load_balance()) {
     670           0 :         path->set_ecmp_load_balance(ecmp_load_balance_);
     671           0 :         ret = true;
     672             :     }
     673             : 
     674           9 :     if (path->etree_leaf() != etree_leaf_) {
     675           0 :         path->set_etree_leaf(etree_leaf_);
     676           0 :         ret = true;
     677             :     }
     678             : 
     679           9 :     return ret;
     680           9 : }
     681           0 : bool ControllerMplsRoute::AddChangePathExtended(Agent *agent, AgentPath *path,
     682             :                                               const AgentRoute *rt) {
     683           0 :     bool ret = false;
     684           0 :     NextHop *nh = NULL;
     685           0 :     SecurityGroupList path_sg_list;
     686             : 
     687           0 :     path->set_peer_sequence_number(sequence_number());
     688           0 :     if (path->tunnel_bmap() != tunnel_bmap_) {
     689           0 :         path->set_tunnel_bmap(tunnel_bmap_);
     690           0 :         ret = true;
     691             :     }
     692             :  
     693           0 :     agent->nexthop_table()->Process(nh_req_);
     694           0 :     LabelledTunnelNHKey key(agent->fabric_vrf_name(), agent->router_id(), tunnel_dest_,
     695           0 :                     false, TunnelType::MPLS_OVER_MPLS, rewrite_dmac_, label_);
     696           0 :     nh = static_cast<NextHop *>(agent->nexthop_table()->FindActiveEntry(&key));
     697           0 :     path->set_tunnel_dest(tunnel_dest_);
     698             : 
     699           0 :     if (path->label() != label_) {
     700           0 :         path->set_label(label_);
     701           0 :         ret = true;
     702             :     }
     703             : 
     704           0 :     if (path->dest_vn_list() != dest_vn_list_) {
     705           0 :         path->set_dest_vn_list(dest_vn_list_);
     706           0 :         ret = true;
     707             :     }
     708             : 
     709           0 :     path->set_unresolved(false);
     710           0 :     if (path->ChangeNH(agent, nh) == true)
     711           0 :         ret = true;
     712             : 
     713           0 :     path_sg_list = path->sg_list();
     714           0 :     if (path_sg_list != sg_list_) {
     715           0 :         path->set_sg_list(sg_list_);
     716           0 :         ret = true;
     717             :     }
     718             : 
     719           0 :     if (tag_list_ != path->tag_list()) {
     720           0 :         path->set_tag_list(tag_list_);
     721           0 :         ret = true;
     722             :     }
     723             : 
     724           0 :     if (path->path_preference() != path_preference_) {
     725           0 :         path->set_path_preference(path_preference_);
     726           0 :         ret = true;
     727             :     }
     728             : 
     729             :     //If a transition of path happens from ECMP to non ECMP
     730             :     //reset local mpls label reference and composite nh key
     731           0 :     if (path->composite_nh_key()) {
     732           0 :         path->set_composite_nh_key(NULL);
     733           0 :         path->set_local_ecmp_mpls_label(NULL);
     734             :     }
     735             : 
     736           0 :     if (path->ecmp_suppressed() != ecmp_suppressed_) {
     737           0 :         path->set_ecmp_suppressed(ecmp_suppressed_);
     738           0 :         ret = true;
     739             :     }
     740             : 
     741           0 :     if (ecmp_load_balance_ != path->ecmp_load_balance()) {
     742           0 :         path->set_ecmp_load_balance(ecmp_load_balance_);
     743           0 :         ret = true;
     744             :     }
     745             : 
     746           0 :     if (path->etree_leaf() != etree_leaf_) {
     747           0 :         path->set_etree_leaf(etree_leaf_);
     748           0 :         ret = true;
     749             :     }
     750             : 
     751           0 :     return ret;
     752           0 : }
     753             : 
     754           0 : bool ClonedLocalPath::AddChangePathExtended(Agent *agent, AgentPath *path,
     755             :                                             const AgentRoute *rt) {
     756           0 :     bool ret = false;
     757             : 
     758           0 :     AgentPath *local_path = NULL;
     759           0 :     if (mpls_label_ == MplsTable::kInvalidExportLabel) {
     760           0 :         local_path = rt->FindPath(agent->fabric_rt_export_peer());
     761           0 :         if (local_path == NULL) {
     762           0 :             local_path = rt->FindLocalVmPortPath();
     763             :         }
     764           0 :         path->set_copy_local_path(true);
     765             :     } else {
     766           0 :         MplsLabel *mpls = agent->mpls_table()->FindMplsLabel(mpls_label_);
     767           0 :         if (!mpls) {
     768           0 :             return ret;
     769             :         }
     770             : 
     771           0 :         assert(mpls->nexthop()->GetType() == NextHop::VRF);
     772           0 :         const VrfNH *vrf_nh = static_cast<const VrfNH *>(mpls->nexthop());
     773           0 :         const InetUnicastRouteEntry *uc_rt =
     774             :             static_cast<const InetUnicastRouteEntry *>(rt);
     775             :         const AgentRoute *mpls_vrf_uc_rt =
     776           0 :             vrf_nh->GetVrf()->GetUcRoute(uc_rt->prefix_address());
     777           0 :         if (mpls_vrf_uc_rt == NULL) {
     778           0 :             return ret;
     779             :         }
     780           0 :         local_path = mpls_vrf_uc_rt->FindLocalVmPortPath();
     781             :     }
     782             : 
     783           0 :     path->set_peer_sequence_number(sequence_number_);
     784             : 
     785           0 :     if (!local_path) {
     786           0 :         return ret;
     787             :     }
     788             : 
     789           0 :     if (path->dest_vn_list() != vn_list_) {
     790           0 :         path->set_dest_vn_list(vn_list_);
     791           0 :         ret = true;
     792             :     }
     793           0 :     path->set_unresolved(false);
     794             : 
     795           0 :     if (path->sg_list() != sg_list_) {
     796           0 :         path->set_sg_list(sg_list_);
     797           0 :         ret = true;
     798             :     }
     799             : 
     800           0 :     path->set_tunnel_bmap(local_path->tunnel_bmap());
     801             :     TunnelType::Type new_tunnel_type =
     802           0 :         TunnelType::ComputeType(path->tunnel_bmap());
     803           0 :     if (new_tunnel_type == TunnelType::VXLAN &&
     804           0 :         local_path->vxlan_id() == VxLanTable::kInvalidvxlan_id) {
     805           0 :         new_tunnel_type = TunnelType::ComputeType(TunnelType::MplsType());
     806             :     }
     807             : 
     808           0 :     if (path->tunnel_type() != new_tunnel_type) {
     809           0 :         path->set_tunnel_type(new_tunnel_type);
     810           0 :         ret = true;
     811             :     }
     812             : 
     813             :     // If policy force-enabled in request, enable policy
     814           0 :     path->set_force_policy(local_path->force_policy());
     815             : 
     816           0 :     if (path->label() != local_path->label()) {
     817           0 :         path->set_label(local_path->label());
     818           0 :         ret = true;
     819             :     }
     820             : 
     821           0 :     if (path->vxlan_id() != local_path->vxlan_id()) {
     822           0 :         path->set_vxlan_id(local_path->vxlan_id());
     823           0 :         ret = true;
     824             :     }
     825             : 
     826           0 :     if (path->path_preference() != local_path->path_preference()) {
     827           0 :         path->set_path_preference(local_path->path_preference());
     828           0 :         ret = true;
     829             :     }
     830             : 
     831           0 :     NextHop *nh = const_cast<NextHop *>(local_path->ComputeNextHop(agent));
     832           0 :     if (path->ChangeNH(agent, nh) == true) {
     833           0 :         ret = true;
     834             :     }
     835           0 :     DBEntryBase::KeyPtr key = nh->GetDBRequestKey();
     836           0 :     CompositeNHKey *nh_key = dynamic_cast<CompositeNHKey *>(key.release());
     837           0 :     path->set_composite_nh_key(nh_key);
     838             : 
     839           0 :     return ret;
     840           0 : }
     841             : 
     842           0 : bool StalePathData::AddChangePathExtended(Agent *agent, AgentPath *path,
     843             :                                           const AgentRoute *route) {
     844           0 :     if (path->peer_sequence_number() >= sequence_number_)
     845           0 :         return false;
     846             : 
     847           0 :     if (route->IsDeleted())
     848           0 :         return false;
     849             : 
     850             :     //Delete old stale path
     851           0 :     DBRequest req(DBRequest::DB_ENTRY_DELETE);
     852             :     AgentRouteKey *key = (static_cast<AgentRouteKey *>(route->
     853           0 :                                       GetDBRequestKey().get()))->Clone();
     854           0 :     key->set_peer(path->peer());
     855           0 :     req.key.reset(key);
     856           0 :     req.data.reset();
     857           0 :     AgentRouteTable *table = static_cast<AgentRouteTable *>(route->get_table());
     858           0 :     table->Process(req);
     859           0 :     return true;
     860           0 : }
     861             : 
     862           0 : bool StalePathData::CanDeletePath(Agent *agent, AgentPath *path,
     863             :                                   const AgentRoute *route) const {
     864           0 :     if (path->peer_sequence_number() >= sequence_number_)
     865           0 :        return false;
     866           0 :    return true;
     867             : }
     868             : 
     869             : //Force instantiation
     870             : template ControllerEcmpRoute::ControllerEcmpRoute(const BgpPeer *peer,
     871             :  const VnListType &vn_list,
     872             :  const EcmpLoadBalance &ecmp_load_balance,
     873             :  const TagList &tag_list, const autogen::ItemType *item,
     874             :  const AgentRouteTable *rt_table, const std::string &prefix_str);
     875             : template ControllerEcmpRoute::ControllerEcmpRoute(const BgpPeer *peer,
     876             :  const VnListType &vn_list,
     877             :  const EcmpLoadBalance &ecmp_load_balance,
     878             :  const TagList &tag_list, const autogen::EnetItemType *item,
     879             :  const AgentRouteTable *rt_table, const std::string &prefix_str);

Generated by: LCOV version 1.14