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

Generated by: LCOV version 1.14