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

Generated by: LCOV version 1.14