LCOV - code coverage report
Current view: top level - vnsw/agent/oper - metadata_ip.cc (source / functions) Hit Total Coverage
Test: OpenSDN C/C++ coverage (all TARGET_SET jobs) Lines: 102 154 66.2 %
Date: 2026-11-09 02:10:49 Functions: 17 26 65.4 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /*
       2             :  * Copyright (c) 2016 Juniper Networks, Inc. All rights reserved.
       3             :  * Copyright Contributors to the OpenSDN project
       4             :  */
       5             : 
       6             : #include <oper/route_common.h>
       7             : #include <oper/ecmp_load_balance.h>
       8             : #include <oper/interface_common.h>
       9             : #include <oper/vm_interface.h>
      10             : #include <oper/inet_unicast_route.h>
      11             : #include <oper/metadata_ip.h>
      12             : 
      13             : const IpAddress MetaDataIp::kDefaultIp;
      14             : 
      15           0 : MetaDataIp::MetaDataIp(MetaDataIpAllocator *allocator, VmInterface *intf,
      16           0 :                        MetaDataIpType type, bool insert_metadata_ip, bool ipv4) :
      17           0 :     allocator_(allocator), index_(-1), intf_(intf),
      18           0 :     intf_label_(MplsTable::kInvalidLabel), service_ip_(), destination_ip_(),
      19           0 :     active_(false), type_(type), insert_metadata_ip_(insert_metadata_ip),
      20           0 :     ipv4_(ipv4) {
      21           0 :     if (insert_metadata_ip_) {
      22           0 :         index_ = allocator_->AllocateIndex(this);
      23           0 :         intf->InsertMetaDataIpInfo(this);
      24             :     }
      25           0 : }
      26             : 
      27         330 : MetaDataIp::MetaDataIp(MetaDataIpAllocator *allocator, VmInterface *intf,
      28         330 :                        uint16_t index, bool ipv4) :
      29         330 :     allocator_(allocator), index_(index), intf_(intf),
      30         330 :     intf_label_(MplsTable::kInvalidLabel), service_ip_(), destination_ip_(),
      31         330 :     active_(false), type_(LINKLOCAL), ipv4_(ipv4) {
      32         330 :     allocator_->AllocateIndex(this, index_);
      33         330 :     intf_->InsertMetaDataIpInfo(this);
      34         330 : }
      35             : 
      36         330 : MetaDataIp::~MetaDataIp() {
      37         330 :     if (type_ == HEALTH_CHECK) {
      38           0 :         if (insert_metadata_ip_) {
      39           0 :             intf_->DeleteMetaDataIpInfo(this);
      40           0 :             allocator_->ReleaseIndex(this);
      41             :         }
      42             :     } else {
      43         330 :         intf_->DeleteMetaDataIpInfo(this);
      44         330 :         allocator_->ReleaseIndex(this);
      45             :     }
      46         330 :     set_active(false);
      47         330 : }
      48             : 
      49             : template<>
      50         825 : Ip4Address MetaDataIp::IndexToIpAddress<Ip4Address>(uint32_t idx) {
      51         825 :     uint32_t ip = METADATA_IP_ADDR & 0xFFFF0000;
      52         825 :     ip += (((uint32_t)idx) & 0xFFFF);
      53         825 :     return Ip4Address(ip);
      54             : }
      55             : 
      56             : template<>
      57         990 : Ip6Address MetaDataIp::IndexToIpAddress<Ip6Address>(uint32_t idx) {
      58         990 :     Ip6Address::bytes_type ip_bytes =
      59             :         {0xFE, 0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
      60             :         (uint32_t)idx & 0xFF00,
      61         990 :         (uint32_t)idx & 0x00FF};
      62         990 :     return Ip6Address(ip_bytes);
      63             : }
      64             : 
      65             : template<>
      66           0 : uint32_t MetaDataIp::IpAddressToIndex<Ip4Address>(const Ip4Address& ip) {
      67           0 :     uint32_t idx = ip.to_ulong();
      68           0 :     if ((idx & 0xFFFF0000) != (METADATA_IP_ADDR & 0xFFFF0000))
      69           0 :         return (0xFFFF + 1);
      70           0 :     idx &= 0xFFFF;
      71           0 :     return idx;
      72             : }
      73             : 
      74             : template<>
      75           0 : uint32_t MetaDataIp::IpAddressToIndex<Ip6Address>(const Ip6Address& ip) {
      76           0 :     uint32_t idx = ip.to_bytes()[15] + (ip.to_bytes()[14] << 8);
      77           0 :     return idx;
      78             : }
      79             : 
      80        1650 : IpAddress MetaDataIp::GetLinkLocalIp() const {
      81        1650 :     if (ipv4_) {
      82         825 :         return GetLinkLocalIp4();
      83             :     }
      84         825 :     return GetLinkLocalIp6();
      85             : }
      86             : 
      87         825 : Ip4Address MetaDataIp::GetLinkLocalIp4() const {
      88         825 :     return IndexToIpAddress<Ip4Address>(index_);
      89             : }
      90             : 
      91         990 : Ip6Address MetaDataIp::GetLinkLocalIp6() const {
      92         990 :     return IndexToIpAddress<Ip6Address>(index_);
      93             : }
      94             : 
      95           0 : IpAddress MetaDataIp::service_ip() const {
      96             :     // check if explicit configuration of service ip is present for
      97             :     // this metadata ip
      98           0 :     if (service_ip_ == kDefaultIp) {
      99           0 :         IpAddress service_ip;
     100           0 :         if (type_ == HEALTH_CHECK) {
     101             :             // for metadata IP type Health Check first verify
     102             :             // if service health check ip is available on interface
     103           0 :             service_ip =  intf_->service_health_check_ip();
     104           0 :             if (service_ip != kDefaultIp) {
     105           0 :                 return service_ip;
     106             :             }
     107             :         }
     108             :         // check if service ip on the primary ip addr of interface
     109             :         // is available
     110           0 :         service_ip = intf_->GetServiceIp(intf_->primary_ip_addr());
     111           0 :         if (service_ip != kDefaultIp) {
     112           0 :             return service_ip;
     113             :         }
     114             :         // if service IP is not available fallback to MetaData IP
     115           0 :         return Ip4Address(METADATA_IP_ADDR);
     116             :     }
     117           0 :     return service_ip_;
     118             : }
     119             : 
     120           0 : IpAddress MetaDataIp::destination_ip() const {
     121           0 :     if (destination_ip_.to_v4() == kDefaultIp) {
     122           0 :         return intf_->primary_ip_addr();
     123             :     }
     124           0 :     return destination_ip_;
     125             : }
     126             : 
     127           0 : void MetaDataIp::set_destination_ip(const IpAddress &dst_ip) {
     128           0 :     destination_ip_ = dst_ip;
     129           0 : }
     130             : 
     131        2644 : void MetaDataIp::set_active(bool active) {
     132        2644 :     if (active_ == active) {
     133        1984 :         return;
     134             :     }
     135         660 :     active_ = active;
     136         660 :     UpdateRoute();
     137             : }
     138             : 
     139        4463 : void MetaDataIp::UpdateInterfaceCb() {
     140        4463 :     if (intf_label_ != intf_->label()) {
     141         330 :         intf_label_ = intf_->label();
     142         330 :         UpdateRoute();
     143             :     }
     144        4463 : }
     145             : 
     146           0 : const Interface *MetaDataIp::GetInterface() const {
     147           0 :     return intf_;
     148             : }
     149             : 
     150         990 : void MetaDataIp::UpdateRoute() {
     151         990 :     if (active_ && intf_->label() != MplsTable::kInvalidLabel) {
     152         330 :         intf_label_ = intf_->label();
     153         330 :         allocator_->AddFabricRoute(this);
     154             :     } else {
     155         660 :         allocator_->DelFabricRoute(this);
     156         660 :         intf_label_ = MplsTable::kInvalidLabel;
     157             :     }
     158         990 : }
     159             : 
     160           4 : MetaDataIpAllocator::MetaDataIpAllocator(Agent *agent, uint16_t start,
     161           4 :                                          uint16_t end) :
     162           4 :     agent_(agent), index_table_(), start_(start), end_(end) {
     163           4 : }
     164             : 
     165           4 : MetaDataIpAllocator::~MetaDataIpAllocator() {
     166           4 : }
     167             : 
     168           0 : MetaDataIp *MetaDataIpAllocator::FindIndex(uint16_t id) {
     169           0 :     uint16_t index = end_ - id;
     170           0 :     return index_table_.At(index);
     171             : }
     172             : 
     173           0 : uint16_t MetaDataIpAllocator::AllocateIndex(MetaDataIp *ip) {
     174           0 :     uint16_t index = index_table_.Insert(ip);
     175           0 :     assert(index <= end_ && (end_ - index) >= start_);
     176           0 :     return (end_ - index);
     177             : }
     178             : 
     179         330 : void MetaDataIpAllocator::AllocateIndex(MetaDataIp *ip, uint16_t id) {
     180         330 :     assert(id <= end_ && id >= start_);
     181         330 :     uint16_t index = end_ - id;
     182         330 :     assert(index == index_table_.InsertAtIndex(index, ip));
     183         330 : }
     184             : 
     185         330 : void MetaDataIpAllocator::ReleaseIndex(MetaDataIp *ip) {
     186         330 :     uint16_t index = end_ - ip->index_;
     187         330 :     index_table_.Remove(index);
     188         330 : }
     189             : 
     190         330 : bool MetaDataIpAllocator::CanAddRoute(MetaDataIp* ip) {
     191         660 :     if (ip->intf_->vmi_type() == VmInterface::VHOST ||
     192         660 :         ip->intf_->vn() == NULL || ip->intf_->vrf() == NULL) {
     193           0 :         return false;
     194             :     }
     195             : 
     196         330 :     return true;
     197             : }
     198             : 
     199         330 : void MetaDataIpAllocator::AddFabricRoute(MetaDataIp *ip) {
     200         330 :     if (!CanAddRoute(ip)) {
     201           0 :         return;
     202             :     }
     203         330 :     PathPreference path_preference;
     204         330 :     EcmpLoadBalance ecmp_load_balance;
     205         330 :     ip->intf_->SetPathPreference(&path_preference, false, Ip4Address(0));
     206             : 
     207         330 :     VnListType vn_list;
     208         330 :     vn_list.insert(ip->intf_->vn()->GetName());
     209             : 
     210         330 :     if (ip->ipv4_) {
     211             :         InetUnicastAgentRouteTable *table =
     212             :             static_cast<InetUnicastAgentRouteTable*>
     213         330 :             (agent_->vrf_table()->GetInet4UnicastRouteTable(
     214         165 :                                             agent_->fabric_vrf_name()));
     215             : 
     216         330 :         table->AddLocalVmRouteReq(
     217         165 :             agent_->link_local_peer(), agent_->fabric_vrf_name(),
     218         165 :             ip->GetLinkLocalIp(), 32, ip->intf_->GetUuid(),
     219         330 :             vn_list, ip->intf_->label(), SecurityGroupList(),
     220         330 :             TagList(), CommunityList(), true, path_preference,
     221         330 :             Ip4Address(0), ecmp_load_balance, false, false, false,
     222         165 :             ip->intf_->name());
     223             :     } else {
     224             :         InetUnicastAgentRouteTable *table =
     225             :             static_cast<InetUnicastAgentRouteTable*>
     226         330 :             (agent_->vrf_table()->GetInet6UnicastRouteTable(
     227         165 :                                             agent_->fabric_vrf_name()));
     228             : 
     229         330 :         table->AddLocalVmRouteReq(
     230         165 :             agent_->link_local_peer(), agent_->fabric_vrf_name(),
     231         165 :             ip->GetLinkLocalIp(), 128, ip->intf_->GetUuid(),
     232         330 :             vn_list, ip->intf_->label(), SecurityGroupList(),
     233         330 :             TagList(), CommunityList(), true, path_preference,
     234         330 :             Ip6Address(), ecmp_load_balance, false, false, false,
     235         165 :             ip->intf_->name());
     236             :     }
     237         330 : }
     238             : 
     239         660 : void MetaDataIpAllocator::DelFabricRoute(MetaDataIp *ip) {
     240         660 :     if (ip->ipv4_) {
     241         330 :         InetUnicastAgentRouteTable::Delete(agent_->link_local_peer(),
     242         330 :             agent_->fabric_vrf_name(),
     243         660 :             ip->GetLinkLocalIp(), 32);
     244             :     } else {
     245         330 :         InetUnicastAgentRouteTable::Delete(agent_->link_local_peer(),
     246         330 :             agent_->fabric_vrf_name(),
     247         660 :             ip->GetLinkLocalIp(), 128);
     248             :     }
     249         660 : }
     250             : 

Generated by: LCOV version 1.14