LCOV - code coverage report
Current view: top level - vnsw/agent/oper - vxlan_xmpp_routes.cc (source / functions) Hit Total Coverage
Test: OpenSDN C/C++ coverage (all TARGET_SET jobs) Lines: 0 194 0.0 %
Date: 2026-08-03 02:19:58 Functions: 0 11 0.0 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /*
       2             :  * Copyright (c) 2018 Juniper Networks, Inc. All rights reserved.
       3             :  * Copyright (c) 2022 - 2026 Matvey Kraposhin.
       4             :  * Copyright (c) 2024 - 2026 Elena Zizganova.
       5             :  */
       6             : 
       7             : #include <oper/operdb_init.h>
       8             : #include <oper/route_common.h>
       9             : #include <oper/vrf.h>
      10             : #include <oper/bridge_route.h>
      11             : #include <oper/inet_unicast_route.h>
      12             : #include <oper/evpn_route.h>
      13             : #include <oper/agent_route.h>
      14             : #include <oper/vn.h>
      15             : #include <oper/vrf.h>
      16             : #include <controller/controller_route_path.h>
      17             : #include <oper/vxlan_routing_manager.h>
      18             : #include <oper/tunnel_nh.h>
      19             : #include <oper/bgp_as_service.h>
      20             : 
      21             : template<class RouteTable, class RouteEntry>
      22             : static const AgentPath *LocalVmExportInterface(Agent* agent,
      23             :     RouteTable *table, RouteEntry *route);
      24             : 
      25           0 : TunnelNHKey* VxlanRoutingManager::AllocateTunnelNextHopKey(
      26             :     const IpAddress& dip, const MacAddress& dmac) const {
      27             : 
      28           0 :     const Ip4Address rtr_dip = dip.to_v4();
      29             : 
      30           0 :     const std::vector<IpAddress> nh_addresses(1, dip);
      31           0 :     bool is_zero_mac = dmac.IsZero();
      32             : 
      33           0 :     MacAddress rtr_dmac;
      34           0 :     if (!is_zero_mac) {
      35           0 :         rtr_dmac = dmac;
      36             :     } else {
      37           0 :         rtr_dmac = NbComputeMac(rtr_dip, agent_);
      38             :     }
      39             : 
      40           0 :     TunnelNHKey *tun_nh_key = new TunnelNHKey(agent_->fabric_vrf_name(),
      41           0 :         agent_->router_id(),
      42             :         rtr_dip,
      43             :         false,
      44           0 :         TunnelType(TunnelType::VXLAN),
      45           0 :         rtr_dmac);
      46           0 :     return tun_nh_key;
      47           0 : }
      48             : 
      49           0 : void VxlanRoutingManager::XmppAdvertiseEvpnRoute(const IpAddress& prefix_ip,
      50             : const int prefix_len, uint32_t vxlan_id, const std::string vrf_name,
      51             : const RouteParameters& params, const Peer *bgp_peer,
      52             : const std::vector<std::string> &peer_sources) {
      53           0 :     VrfEntry* vrf = agent_->vrf_table()->FindVrfFromName(vrf_name);
      54             :     EvpnAgentRouteTable *evpn_table =
      55           0 :         dynamic_cast<EvpnAgentRouteTable*>(vrf->GetEvpnRouteTable());
      56           0 :     if (evpn_table == NULL) {
      57           0 :         return;
      58             :     }
      59             : 
      60             :     // If route is a tunnel
      61           0 :     if (agent_->router_id() != params.nh_addr_.to_v4()) {
      62           0 :         XmppAdvertiseEvpnTunnel(evpn_table,
      63             :             prefix_ip, prefix_len, vxlan_id, vrf_name, params, bgp_peer);
      64           0 :         return;
      65             :     }
      66             : 
      67             :     // Or this is an interface
      68           0 :     XmppAdvertiseEvpnInterface(evpn_table,
      69             :             prefix_ip, prefix_len, vxlan_id, vrf_name, params, bgp_peer, peer_sources);
      70             : }
      71             : 
      72           0 : void VxlanRoutingManager::XmppAdvertiseInetRoute(const IpAddress& prefix_ip,
      73             :     const int prefix_len, const std::string vrf_name,
      74             :     const AgentPath* path) {
      75             : 
      76           0 :     VrfEntry* vrf = agent_->vrf_table()->FindVrfFromName(vrf_name);
      77             :     InetUnicastAgentRouteTable *inet_table =
      78           0 :         vrf->GetInetUnicastRouteTable(prefix_ip);
      79             : 
      80           0 :     if (path->nexthop() && path->nexthop()->GetType() ==
      81             :         NextHop::TUNNEL) {
      82           0 :             XmppAdvertiseInetTunnel(inet_table,
      83             :                 prefix_ip, prefix_len, vrf_name, path);
      84           0 :         return;
      85             :     }
      86             : 
      87           0 :     if (path->nexthop() &&
      88           0 :         (path->nexthop()->GetType() == NextHop::INTERFACE ||
      89           0 :         path->nexthop()->GetType() == NextHop::COMPOSITE)) {
      90           0 :         XmppAdvertiseInetInterfaceOrComposite(inet_table,
      91             :             prefix_ip, prefix_len, vrf_name, path);
      92             :     }
      93             : }
      94             : 
      95           0 : void VxlanRoutingManager::XmppAdvertiseEvpnTunnel(
      96             :     EvpnAgentRouteTable *evpn_table, const IpAddress& prefix_ip,
      97             :     const int prefix_len, uint32_t vxlan_id, const std::string vrf_name,
      98             :     const RouteParameters& params, const Peer *peer
      99             : ) {
     100           0 :     const BgpPeer *bgp_peer = dynamic_cast<const BgpPeer*>(peer);
     101           0 :     if (bgp_peer == NULL) {
     102           0 :         return;
     103             :     }
     104           0 :     DBRequest nh_req(DBRequest::DB_ENTRY_ADD_CHANGE);
     105             :     std::unique_ptr<TunnelNHKey> tun_nh_key (AllocateTunnelNextHopKey(
     106           0 :         params.nh_addr_, params.nh_mac_));
     107             : 
     108             :     ControllerVmRoute *data =
     109           0 :         ControllerVmRoute::MakeControllerVmRoute(dynamic_cast<const BgpPeer*>(bgp_peer),
     110           0 :         agent_->fabric_vrf_name(),
     111           0 :         agent_->router_id(),
     112             :         vrf_name,
     113             :         tun_nh_key->dip(),
     114             :         TunnelType::VxlanType(),
     115             :         vxlan_id,
     116             :         tun_nh_key->rewrite_dmac(),
     117             :         params.vn_list_,
     118             :         params.sg_list_,
     119             :         params.tag_list_,
     120             :         params.path_preference_,
     121             :         true,
     122           0 :         EcmpLoadBalance(),
     123             :         false);
     124           0 :     evpn_table->AddRemoteVmRouteReq(bgp_peer,
     125             :         vrf_name,
     126           0 :         MacAddress(),
     127             :         prefix_ip,
     128             :         prefix_len,
     129             :         0,  // ethernet_tag is zero for Type5
     130             :         data);
     131           0 : }
     132             : 
     133           0 : void VxlanRoutingManager::XmppAdvertiseEvpnBgpaasInterface(
     134             :     EvpnAgentRouteTable *evpn_table, const IpAddress& prefix_ip,
     135             :     const int prefix_len, uint32_t vxlan_id, const std::string vrf_name,
     136             :     const RouteParameters& params, const Peer *bgp_peer,  const NextHop *nh
     137             : ) {
     138           0 :     const InterfaceNH *intf_nh = dynamic_cast<const InterfaceNH *>(nh);
     139           0 :     const Interface *intf = intf_nh->GetInterface();
     140           0 :     if (intf->type() != Interface::VM_INTERFACE) {
     141           0 :         return;
     142             :     }
     143           0 :     const VmInterface *vm_intf = dynamic_cast<const VmInterface*>
     144           0 :         (intf);
     145           0 :     DBEntryBase::KeyPtr tintf_key_ptr = vm_intf->GetDBRequestKey();
     146             :     const VmInterfaceKey* intf_key_ptr =
     147           0 :         dynamic_cast<const VmInterfaceKey *>(tintf_key_ptr.get());
     148             : 
     149             :     LocalVmRoute *loc_rt_ptr = new LocalVmRoute(
     150             :         *intf_key_ptr,
     151             :         MplsTable::kInvalidLabel,  // mpls_label
     152             :         vxlan_id,
     153             :         false,
     154             :         params.vn_list_,
     155           0 :         intf_nh->GetFlags(),  // flags
     156             :         params.sg_list_,
     157             :         params.tag_list_,
     158             :         params.communities_,
     159             :         params.path_preference_,
     160           0 :         Ip4Address(0),
     161             :         params.ecmp_load_balance_,
     162             :         false,
     163             :         false,
     164           0 :         params.sequence_number_,
     165             :         false,
     166           0 :         false);  // native_encap
     167           0 :         loc_rt_ptr->set_tunnel_bmap(TunnelType::VxlanType());
     168             : 
     169             :     {
     170           0 :         DBRequest req(DBRequest::DB_ENTRY_ADD_CHANGE);
     171             : 
     172           0 :         req.key.reset(new EvpnRouteKey(bgp_peer,
     173           0 :             evpn_table->vrf_entry()->GetName(),
     174           0 :             MacAddress(),
     175             :             prefix_ip,
     176             :             prefix_len,
     177           0 :             0));
     178           0 :         req.data.reset(loc_rt_ptr);
     179           0 :         evpn_table->Enqueue(&req);
     180           0 :     }
     181           0 : }
     182             : 
     183           0 : void VxlanRoutingManager::XmppAdvertiseEvpnBgpaasComposite(
     184             :     EvpnAgentRouteTable *evpn_table, const IpAddress& prefix_ip,
     185             :     const int prefix_len, uint32_t vxlan_id, const std::string vrf_name,
     186             :     const RouteParameters& params, const Peer *bgp_peer,
     187             :     ComponentNHKeyList &comp_nh_list ) {
     188           0 :     DBRequest nh_req(DBRequest::DB_ENTRY_ADD_CHANGE);
     189           0 :     const bool comp_nh_policy = true;
     190             :     CompositeNHKey *new_comp_nh_key =
     191             :         new CompositeNHKey(Composite::LOCAL_ECMP,
     192           0 :             comp_nh_policy, comp_nh_list, vrf_name);
     193             : 
     194           0 :     nh_req.key.reset(new_comp_nh_key);
     195           0 :     nh_req.data.reset(new CompositeNHData());
     196           0 :     const BgpPeer *bgp_peer_ecmp = dynamic_cast<const BgpPeer*>(bgp_peer);
     197           0 :     std::stringstream prefix_str;
     198           0 :     prefix_str << prefix_ip.to_string();
     199           0 :     prefix_str << "/";
     200           0 :     prefix_str << prefix_len;
     201             : 
     202             :     ControllerEcmpRoute *rt_data = new ControllerEcmpRoute(
     203             :         bgp_peer_ecmp,
     204             :         params.vn_list_,
     205             :         params.ecmp_load_balance_,
     206             :         params.tag_list_,
     207             :         params.sg_list_,
     208             :         params.path_preference_,
     209           0 :         TunnelType::VxlanType(),
     210             :         nh_req,
     211           0 :         prefix_str.str(),
     212           0 :         evpn_table->vrf_name());
     213             : 
     214             :     ControllerEcmpRoute::ClonedLocalPathListIter iter =
     215           0 :         rt_data->cloned_local_path_list().begin();
     216           0 :     while (iter != rt_data->cloned_local_path_list().end()) {
     217           0 :         evpn_table->AddClonedLocalPathReq(bgp_peer_ecmp, vrf_name,
     218           0 :             MacAddress(), prefix_ip, 0, (*iter));
     219           0 :         iter++;
     220             :     }
     221             : 
     222           0 :     evpn_table->AddRemoteVmRouteReq(bgp_peer_ecmp,
     223           0 :         vrf_name, MacAddress(),
     224             :         prefix_ip,
     225             :         prefix_len,
     226             :         0,  // ethernet tag is 0 for VxLAN
     227             :         rt_data);
     228           0 : }
     229             : 
     230           0 : void VxlanRoutingManager::XmppAdvertiseEvpnBgpaas(
     231             :     EvpnAgentRouteTable *evpn_table, const IpAddress& prefix_ip,
     232             :     const int prefix_len, uint32_t vxlan_id, const std::string vrf_name,
     233             :     const RouteParameters& params, const Peer *bgp_peer,
     234             :     const std::vector<std::string> &peer_sources
     235             : ) {
     236           0 :         const NextHop *first_intf_nh = nullptr;
     237           0 :         NextHopKey *nh_key = nullptr;
     238             :         // Create a new composite
     239           0 :         ComponentNHKeyList new_comp_nh_list;
     240           0 :         for (auto &nexthop_addr : peer_sources) {
     241           0 :             IpAddress nh_ip;
     242           0 :             boost::system::error_code ec;
     243             :             int nh_ip_len;
     244           0 :             if (is_ipv4_string(nexthop_addr)) {
     245           0 :                 nh_ip = Ip4Address::from_string(ipv4_prefix(nexthop_addr), ec);
     246           0 :                 nh_ip_len = ipv4_prefix_len(nexthop_addr);
     247           0 :             } else if (is_ipv6_string(nexthop_addr)) {
     248           0 :                 nh_ip = Ip6Address::from_string(ipv6_prefix(nexthop_addr), ec);
     249           0 :                 nh_ip_len = ipv6_prefix_len(nexthop_addr);
     250             :             } else {
     251           0 :                 LOG(ERROR, "Error in VxlanRoutingManager::AddInterfaceComponentToList"
     252             :                     << ", nexthop_addr = " << nexthop_addr
     253             :                     << " is not an IPv4 or IPv6 prefix");
     254           0 :                 return;
     255             :             }
     256           0 :             if (ec) {
     257           0 :                 continue;
     258             :             }
     259           0 :             EvpnRouteEntry *route =evpn_table->FindRoute(MacAddress(),
     260             :                 nh_ip, nh_ip_len, 0);
     261             :             const AgentPath *loc_path =
     262           0 :                 LocalVmExportInterface(agent_, evpn_table, route);
     263           0 :             if (loc_path == nullptr) {
     264           0 :                 continue;
     265             :             }
     266           0 :             if (loc_path->nexthop() == nullptr) {
     267           0 :                 continue;
     268             :             }
     269           0 :             if (IsBgpaasInterfaceNexthop(agent_, loc_path->nexthop())) {
     270           0 :                 if (first_intf_nh == NULL) {
     271           0 :                     first_intf_nh = loc_path->nexthop();
     272             :                 }
     273           0 :                 DBEntryBase::KeyPtr key = loc_path->nexthop()->
     274           0 :                     GetDBRequestKey();
     275           0 :                 nh_key = static_cast<NextHopKey *>(key.release());
     276             : 
     277           0 :                 std::unique_ptr<const NextHopKey> nh_key_ptr(nh_key);
     278             :                 ComponentNHKeyPtr component_nh_key(new ComponentNHKey(
     279           0 :                     MplsTable::kInvalidLabel, std::move(nh_key_ptr)));
     280           0 :                 new_comp_nh_list.push_back(component_nh_key);
     281           0 :             } else if (IsBgpaasCompositeNexthop(agent_, loc_path->nexthop())) {
     282           0 :                 const CompositeNH *composite_nh = dynamic_cast<const CompositeNH*>(
     283           0 :                     loc_path->nexthop());
     284           0 :                 const ComponentNHList &components = composite_nh->component_nh_list();
     285           0 :                 for (auto &component : components) {
     286           0 :                     if (component.get() &&
     287           0 :                         component->nh() &&
     288           0 :                         component->nh()->GetType() == NextHop::INTERFACE) {
     289           0 :                         if (first_intf_nh == nullptr) {
     290           0 :                             first_intf_nh = component->nh();
     291             :                         }
     292           0 :                         DBEntryBase::KeyPtr key = component->nh()->
     293           0 :                             GetDBRequestKey();
     294           0 :                         nh_key = static_cast<NextHopKey *>(key.release());
     295             : 
     296           0 :                         std::unique_ptr<const NextHopKey> nh_key_ptr(nh_key);
     297             :                         ComponentNHKeyPtr component_nh_key(new ComponentNHKey(
     298           0 :                             MplsTable::kInvalidLabel, std::move(nh_key_ptr)));
     299           0 :                         new_comp_nh_list.push_back(component_nh_key);
     300           0 :                     }
     301             :                 }
     302             :             }
     303             :         }
     304             : 
     305           0 :         if (new_comp_nh_list.size() < 1) {
     306           0 :             return;
     307           0 :         } else if (new_comp_nh_list.size() == 1) {
     308           0 :             XmppAdvertiseEvpnBgpaasInterface(evpn_table, prefix_ip, prefix_len,
     309             :             vxlan_id, vrf_name, params, bgp_peer, first_intf_nh);
     310             :         } else {
     311           0 :             XmppAdvertiseEvpnBgpaasComposite(evpn_table, prefix_ip, prefix_len,
     312             :             vxlan_id, vrf_name, params, bgp_peer, new_comp_nh_list);
     313             :         }
     314             : 
     315           0 : }
     316             : 
     317           0 : void VxlanRoutingManager::XmppAdvertiseEvpnInterface(
     318             :     EvpnAgentRouteTable *evpn_table, const IpAddress& prefix_ip,
     319             :     const int prefix_len, uint32_t vxlan_id, const std::string vrf_name,
     320             :     const RouteParameters& params, const Peer *bgp_peer,
     321             :     const std::vector<std::string> &peer_sources ) {
     322           0 :     EvpnRouteEntry *route = evpn_table->FindRoute(MacAddress(),
     323             :         prefix_ip, prefix_len, 0);
     324           0 :     if (RoutePrefixIsEqualTo(route, prefix_ip, prefix_len) == false) {
     325           0 :         XmppAdvertiseEvpnBgpaas(evpn_table, prefix_ip, prefix_len, vxlan_id,
     326             :                                 vrf_name, params, bgp_peer, peer_sources);
     327           0 :         return;
     328             :     }
     329             :     const AgentPath * path =
     330           0 :         LocalVmExportInterface(agent_, evpn_table, route);
     331             : 
     332           0 :     if (!path ) {
     333           0 :         XmppAdvertiseEvpnBgpaas(evpn_table, prefix_ip, prefix_len, vxlan_id,
     334             :                                 vrf_name, params, bgp_peer, peer_sources);
     335           0 :         return;
     336             :     }
     337             : 
     338           0 :     CopyInterfacePathToEvpnTable(path,
     339             :         prefix_ip,
     340             :         prefix_len,
     341             :         bgp_peer,
     342           0 :         RouteParameters(IpAddress(),  // NH address, not needed here
     343           0 :             MacAddress(),
     344             :             params.vn_list_,
     345             :             params.sg_list_,
     346             :             params.communities_,
     347             :             params.tag_list_,
     348             :             params.path_preference_,
     349             :             params.ecmp_load_balance_,
     350           0 :             params.sequence_number_),
     351             :         evpn_table);
     352             : }
     353             : 
     354           0 : void VxlanRoutingManager::XmppAdvertiseInetTunnel(
     355             :         InetUnicastAgentRouteTable *inet_table, const IpAddress& prefix_ip,
     356             :         const int prefix_len, const std::string vrf_name,
     357             :         const AgentPath* path) {
     358             : 
     359           0 :     DBRequest nh_req(DBRequest::DB_ENTRY_ADD_CHANGE);
     360           0 :     TunnelNH *tun_nh = dynamic_cast<TunnelNH*>(path->nexthop());
     361             : 
     362           0 :     TunnelNHKey *tun_nh_key = AllocateTunnelNextHopKey(*(tun_nh->GetDip()),
     363             :         tun_nh->rewrite_dmac());
     364           0 :     std::string origin_vn = "";
     365             : 
     366           0 :     nh_req.key.reset(tun_nh_key);
     367           0 :     nh_req.data.reset(new TunnelNHData);
     368             : 
     369           0 :     inet_table->AddEvpnRoutingRoute(prefix_ip,
     370             :         prefix_len,
     371           0 :         inet_table->vrf_entry(),
     372             :         routing_vrf_vxlan_bgp_peer_,
     373             :         path->sg_list(),
     374             :         path->communities(),
     375             :         path->path_preference(),
     376             :         path->ecmp_load_balance(),
     377             :         path->tag_list(),
     378             :         nh_req,
     379             :         path->vxlan_id(),
     380             :         path->dest_vn_list(),
     381             :         origin_vn);
     382           0 : }
     383             : 
     384           0 : void VxlanRoutingManager::XmppAdvertiseInetInterfaceOrComposite(
     385             :         InetUnicastAgentRouteTable *inet_table, const IpAddress& prefix_ip,
     386             :         const int prefix_len, const std::string vrf_name,
     387             :         const AgentPath* path) {
     388             : 
     389           0 :     CopyPathToInetTable(path,
     390             :         prefix_ip,
     391             :         prefix_len,
     392             :         routing_vrf_vxlan_bgp_peer_,
     393           0 :         RouteParameters(IpAddress(),
     394           0 :             MacAddress(),
     395             :             path->dest_vn_list(),
     396             :             path->sg_list(),
     397             :             path->communities(),
     398             :             path->tag_list(),
     399             :             path->path_preference(),
     400             :             path->ecmp_load_balance(),
     401             :             path->peer_sequence_number()),
     402             :         inet_table);
     403           0 : }
     404             : 
     405             : template<class RouteTable, class RouteEntry>
     406           0 : static const AgentPath *LocalVmExportInterface(Agent* agent,
     407             :     RouteTable *table, RouteEntry *route) {
     408           0 :     if (table == NULL || agent == NULL || route == NULL) {
     409           0 :         return NULL;
     410             :     }
     411             : 
     412           0 :     const AgentPath *tm_path = NULL;
     413           0 :     const AgentPath *rt_path = NULL;
     414             : 
     415           0 :     for (Route::PathList::const_iterator it =
     416           0 :         route->GetPathList().begin();
     417           0 :         it != route->GetPathList().end(); it++) {
     418             :         tm_path =
     419           0 :             static_cast<const AgentPath *>(it.operator->());
     420           0 :         if (tm_path == NULL || tm_path->peer() == NULL) {
     421           0 :             continue;
     422             :         }
     423           0 :         if (tm_path->peer()->GetType() ==
     424           0 :             agent->local_vm_export_peer()->GetType()) {
     425           0 :             if (tm_path->nexthop() &&
     426           0 :                 tm_path->nexthop()->GetType() == NextHop::INTERFACE) {
     427           0 :                 rt_path = tm_path;
     428           0 :             } else if (tm_path->nexthop() &&
     429           0 :                 tm_path->nexthop()->GetType() == NextHop::COMPOSITE) {
     430           0 :                 return tm_path;
     431             :             }
     432             :         }
     433             :     }
     434           0 :     return rt_path;
     435             : }
     436             : 
     437             : //
     438             : //END-OF-FILE
     439             : //
     440             : 

Generated by: LCOV version 1.14