LCOV - code coverage report
Current view: top level - vnsw/agent/oper - mpls.cc (source / functions) Hit Total Coverage
Test: OpenSDN C/C++ coverage (all TARGET_SET jobs) Lines: 0 308 0.0 %
Date: 2026-06-22 02:21:21 Functions: 0 40 0.0 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /*
       2             :  * Copyright (c) 2013 Juniper Networks, Inc. All rights reserved.
       3             :  */
       4             : 
       5             : #include <boost/uuid/uuid_io.hpp>
       6             : #include <cmn/agent_cmn.h>
       7             : #include <init/agent_param.h>
       8             : #include <base/task_annotations.h>
       9             : #include <oper/interface_common.h>
      10             : #include <oper/vrf.h>
      11             : #include <oper/nexthop.h>
      12             : #include <oper/mpls.h>
      13             : #include <oper/mirror_table.h>
      14             : #include <oper/agent_sandesh.h>
      15             : #include <resource_manager/resource_manager.h>
      16             : #include <resource_manager/resource_table.h>
      17             : #include <resource_manager/mpls_index.h>
      18             : 
      19             : using namespace std;
      20             : 
      21             : SandeshTraceBufferPtr MplsTraceBuf(SandeshTraceBufferCreate("MplsTrace", 1000));
      22             : 
      23             : /****************************************************************************
      24             :  * MplsLabel routines
      25             :  ***************************************************************************/
      26           0 : MplsLabel::MplsLabel(Agent *agent, uint32_t label) :
      27           0 :     agent_(agent), label_(label), free_label_(false) {
      28           0 : }
      29             : 
      30           0 : MplsLabel::~MplsLabel() {
      31           0 :     if (free_label_) {
      32           0 :         if (label_ != MplsTable::kInvalidLabel) {
      33           0 :             MplsTable *table = static_cast<MplsTable *>(get_table());
      34           0 :             table->FreeMplsLabelIndex(label_);
      35             :         }
      36           0 :         agent_->resource_manager()->Release(Resource::MPLS_INDEX, label_);
      37             :     }
      38           0 : }
      39             : 
      40           0 : bool MplsLabel::IsLess(const DBEntry &rhs) const {
      41           0 :         const MplsLabel &mpls = static_cast<const MplsLabel &>(rhs);
      42           0 :         return label_ < mpls.label_;
      43             : }
      44             : 
      45           0 : std::string MplsLabel::ToString() const {
      46           0 :     return "MPLS";
      47             : }
      48             : 
      49           0 : DBEntryBase::KeyPtr MplsLabel::GetDBRequestKey() const {
      50           0 :     MplsLabelKey *key = new MplsLabelKey(label_);
      51           0 :     return DBEntryBase::KeyPtr(key);
      52             : }
      53             : 
      54           0 : void MplsLabel::SetKey(const DBRequestKey *k) {
      55           0 :     const MplsLabelKey *key = static_cast<const MplsLabelKey *>(k);
      56           0 :     label_ = key->label();
      57           0 : }
      58             : 
      59           0 : uint32_t MplsLabel::GetRefCount() const {
      60           0 :     return AgentRefCount<MplsLabel>::GetRefCount();
      61             : }
      62             : 
      63           0 : void MplsLabel::Add(const DBRequest *req) {
      64           0 :     free_label_ = true;
      65           0 :     ChangeInternal(req);
      66           0 :     SendObjectLog(agent_->mpls_table(), AgentLogEvent::ADD);
      67           0 :     return;
      68             : }
      69             : 
      70           0 : bool MplsLabel::Change(const DBRequest *req) {
      71           0 :     const AgentDBTable *table = static_cast<const AgentDBTable *>(get_table());
      72           0 :     bool ret = ChangeInternal(req);
      73           0 :     SendObjectLog(table, AgentLogEvent::CHANGE);
      74           0 :     return ret;
      75             : }
      76             : 
      77           0 : void MplsLabel::Delete(const DBRequest *req) {
      78           0 :     const AgentDBTable *table = static_cast<const AgentDBTable *>(get_table());
      79           0 :     SendObjectLog(table, AgentLogEvent::DEL);
      80           0 :     return;
      81             : }
      82             : 
      83           0 : bool MplsLabel::ChangeInternal(const DBRequest *req) {
      84           0 :     NextHopTable *nh_table = agent_->nexthop_table();
      85           0 :     MplsLabelData *data = static_cast<MplsLabelData *>(req->data.get());
      86             :     NextHop *nh =
      87           0 :         static_cast<NextHop *>(nh_table->FindActiveEntry(data->nh_key()));
      88           0 :     if (!nh) {
      89             :         // NextHop not found, point mpls label to discard
      90           0 :         DiscardNH key;
      91           0 :         nh = static_cast<NextHop *>(nh_table->FindActiveEntry(&key));
      92           0 :     }
      93             : 
      94           0 :     return ChangeNH(nh);
      95             : }
      96             : 
      97           0 : bool MplsLabel::ChangeNH(NextHop *nh) {
      98           0 :     if (nh_ == nh)
      99           0 :         return false;
     100             : 
     101           0 :     assert(nh);
     102           0 :     nh_ = nh;
     103             : 
     104           0 :     if (IsFabricMulticastReservedLabel()) {
     105           0 :         CompositeNH *cnh = dynamic_cast<CompositeNH*>(nh);
     106           0 :         if (cnh && cnh->vrf()) {
     107           0 :             FmgVrfNhMap::iterator it = fmg_nh_list_.begin();
     108           0 :             while( it != fmg_nh_list_.end()) {
     109           0 :                 if (it->first != cnh->vrf()->GetName()) {
     110           0 :                     FmgVrfNhMap::iterator temp_it;
     111           0 :                     temp_it = it;
     112           0 :                     it++;
     113           0 :                     fmg_nh_list_.erase(temp_it);
     114             :                 } else {
     115           0 :                     it++;
     116             :                 }
     117             :             }
     118           0 :             fmg_nh_list_[cnh->vrf()->GetName()] = nh;
     119             :         }
     120             :     }
     121             : 
     122           0 :     SyncDependentPath();
     123           0 :     return true;
     124             : }
     125             : 
     126           0 : void MplsLabel::SyncDependentPath() {
     127           0 :     MPLS_TRACE(MplsTrace, "Syncing routes for label ", label());
     128           0 :     for (DependentPathList::iterator iter =
     129           0 :          mpls_label_.begin(); iter != mpls_label_.end(); iter++) {
     130           0 :         AgentRoute *rt = iter.operator->();
     131           0 :         rt->EnqueueRouteResync();
     132             :     }
     133           0 : }
     134             : 
     135           0 : bool MplsLabel::IsFabricMulticastReservedLabel() const {
     136             :     //MplsTable *table = static_cast<MplsTable *>(get_table());
     137           0 :     MplsTable *table = static_cast<MplsTable *>(agent_->mpls_table());
     138           0 :     return table->IsFabricMulticastLabel(label_);
     139             : }
     140             : 
     141             : /****************************************************************************
     142             :  * MplsLabel Sandesh routines
     143             :  ***************************************************************************/
     144           0 : bool MplsLabel::DBEntrySandesh(Sandesh *sresp, std::string &name) const {
     145           0 :     MplsResp *resp = static_cast<MplsResp *>(sresp);
     146             : 
     147           0 :     MplsSandeshData data;
     148           0 :     data.set_label(label_);
     149           0 :     nh_->SetNHSandeshData(data.nh);
     150             :     std::vector<MplsSandeshData> &list =
     151           0 :             const_cast<std::vector<MplsSandeshData>&>(resp->get_mpls_list());
     152           0 :     list.push_back(data);
     153             : 
     154           0 :     return true;
     155           0 : }
     156             : 
     157           0 : void MplsLabel::SendObjectLog(const AgentDBTable *table,
     158             :                               AgentLogEvent::type event) const {
     159           0 :     MplsObjectLogInfo info;
     160           0 :     string str, type_str, nh_type;
     161           0 :     info.set_type(type_str);
     162           0 :     info.set_label((int)label_);
     163           0 :     switch (event) {
     164           0 :     case AgentLogEvent::ADD:
     165           0 :         str.assign("Addition ");
     166           0 :         break;
     167           0 :     case AgentLogEvent::DEL:
     168           0 :         str.assign("Deletion ");
     169           0 :         info.set_event(str);
     170           0 :         OPER_TRACE_ENTRY(Mpls, table, info);
     171           0 :         return;
     172           0 :     case AgentLogEvent::CHANGE:
     173           0 :         str.assign("Modification ");
     174           0 :         break;
     175           0 :     default:
     176           0 :         str.assign("Unknown");
     177           0 :         break;
     178             :     }
     179           0 :     info.set_event(str);
     180           0 :     const NextHop *nh = nexthop();
     181           0 :     const Interface *intf = NULL;
     182             :     /* Mpls is not expected to have any other nexthop apart from Interface
     183             :        or Vlan */
     184           0 :     if (nh != NULL) {
     185           0 :         string policy_str("Disabled");
     186             :         const InterfaceNH *if_nh;
     187             :         const VlanNH *vlan_nh;
     188             : 
     189           0 :         switch(nh->GetType()) {
     190           0 :         case NextHop::INTERFACE:
     191           0 :             nh_type.assign("INTERFACE");
     192           0 :             if_nh = static_cast<const InterfaceNH *>(nh);
     193           0 :             intf = if_nh->GetInterface();
     194           0 :             if (if_nh->PolicyEnabled()) {
     195           0 :                 policy_str.assign("Enabled");
     196             :             }
     197           0 :             info.set_policy(policy_str);
     198           0 :             break;
     199           0 :         case NextHop::VLAN:
     200           0 :             nh_type.assign("VLAN");
     201           0 :             vlan_nh = static_cast<const VlanNH *>(nh);
     202           0 :             intf = vlan_nh->GetInterface();
     203           0 :             info.set_vlan_tag(vlan_nh->GetVlanTag());
     204           0 :             break;
     205           0 :         case NextHop::COMPOSITE:
     206           0 :             nh_type.assign("Composite");
     207           0 :             break;
     208           0 :         default:
     209           0 :             nh_type.assign("unknown");
     210           0 :             break;
     211             :         }
     212           0 :     }
     213           0 :     info.set_nh_type(nh_type);
     214             :     /* Interface Nexthop pointed by Mpls object will always be of type VMPORT */
     215           0 :     if (intf) {
     216           0 :         string if_type_str;
     217           0 :         switch(intf->type()) {
     218           0 :         case Interface::VM_INTERFACE:
     219           0 :             if_type_str.assign("VM_INTERFACE");
     220           0 :             break;
     221           0 :         default:
     222           0 :             if_type_str.assign("Invalid");
     223           0 :             break;
     224             :         }
     225           0 :         info.set_intf_type(if_type_str);
     226           0 :         info.set_intf_uuid(UuidToString(intf->GetUuid()));
     227           0 :         info.set_intf_name(intf->name());
     228           0 :     }
     229           0 :     OPER_TRACE_ENTRY(Mpls, table, info);
     230           0 : }
     231             : 
     232             : /****************************************************************************
     233             :  * MplsTable routines
     234             :  ***************************************************************************/
     235           0 : MplsTable::MplsTable(DB *db, const std::string &name) :
     236           0 :     AgentDBTable(db, name) {
     237           0 : }
     238             : 
     239           0 : MplsTable::~MplsTable() {
     240           0 : }
     241             : 
     242           0 : DBTableBase *MplsTable::CreateTable(DB *db, const std::string &name) {
     243           0 :     MplsTable *table = new MplsTable(db, name);
     244           0 :     table->Init();
     245           0 :     return table;
     246             : };
     247             : 
     248           0 : void MplsTable::Process(DBRequest &req) {
     249           0 :     agent()->ConcurrencyCheck();
     250             :     DBTablePartition *tpart =
     251           0 :         static_cast<DBTablePartition *>(GetTablePartition(req.key.get()));
     252           0 :     tpart->Process(NULL, &req);
     253           0 : }
     254             : 
     255             : /*
     256             :  * Allocates label from resource manager, currently used for evpn and
     257             :  * ecmp labels.
     258             :  */
     259           0 : uint32_t MplsTable::AllocLabel(ResourceManager::KeyPtr key) {
     260             :     uint32_t label = ((static_cast<IndexResourceData *>(agent()->resource_manager()->
     261           0 :                                       Allocate(key).get()))->index());
     262           0 :     assert(label != MplsTable::kInvalidLabel);
     263           0 :     return label;
     264             : }
     265             : 
     266             : //Free label from resource manager and delete db entry
     267           0 : void MplsTable::FreeLabel(uint32_t label) {
     268           0 :     FreeLabel(label, std::string());
     269           0 : }
     270             : 
     271           0 : void MplsTable::FreeLabel(uint32_t label, const std::string &vrf_name) {
     272           0 :     DBRequest req;
     273           0 :     req.oper = DBRequest::DB_ENTRY_DELETE;
     274             : 
     275           0 :     MplsLabelKey *key = new MplsLabelKey(label);
     276           0 :     MplsLabelData *data = new MplsLabelData(NULL);
     277           0 :     data->set_vrf_name(vrf_name);
     278           0 :     req.key.reset(key);
     279           0 :     req.data.reset(data);
     280             : 
     281           0 :     Process(req);
     282           0 : }
     283             : 
     284           0 : std::unique_ptr<DBEntry> MplsTable::AllocEntry(const DBRequestKey *k) const {
     285           0 :     const MplsLabelKey *key = static_cast<const MplsLabelKey *>(k);
     286           0 :     MplsLabel *mpls = new MplsLabel(agent(), key->label());
     287           0 :     return std::unique_ptr<DBEntry>(static_cast<DBEntry *>(mpls));
     288             : }
     289             : 
     290           0 : DBEntry *MplsTable::Add(const DBRequest *req) {
     291           0 :     CheckVrLabelLimit();
     292           0 :     MplsLabelKey *key = static_cast<MplsLabelKey *>(req->key.get());
     293           0 :     assert(key->label() != MplsTable::kInvalidLabel);
     294             : 
     295           0 :     MplsLabel *mpls = new MplsLabel(agent(), key->label());
     296           0 :     label_table_.InsertAtIndex(mpls->label(), mpls);
     297           0 :     mpls->Add(req);
     298           0 :     return mpls;
     299             : }
     300             : 
     301           0 : bool MplsTable::OnChange(DBEntry *entry, const DBRequest *req) {
     302           0 :     MplsLabel *mpls = static_cast<MplsLabel *>(entry);
     303           0 :     return mpls->Change(req);
     304             : }
     305             : 
     306           0 : bool MplsTable::Delete(DBEntry *entry, const DBRequest *req) {
     307           0 :     MplsLabel *mpls = static_cast<MplsLabel *>(entry);
     308           0 :     if (IsFabricMulticastLabel(mpls->label())) {
     309           0 :         MplsLabelData *data = static_cast<MplsLabelData *>(req->data.get());
     310             :         // For multicast labels we not expect to be here
     311             :         // via MplsTable::OnZeroRefcount where data is not set.
     312           0 :         assert(data);
     313           0 :         if (mpls->fmg_nh_list().find(data->vrf_name()) !=
     314           0 :                 mpls->fmg_nh_list().end()) {
     315           0 :             mpls->fmg_nh_list().erase(data->vrf_name());
     316             :         }
     317           0 :         if (mpls->fmg_nh_list().empty() == false) {
     318           0 :             if (mpls->ChangeNH(mpls->fmg_nh_list().begin()->second.get())) {
     319             :                 DBTablePartBase *tpart =
     320           0 :                     static_cast<DBTablePartition *>(GetTablePartition(mpls));
     321           0 :                 tpart->Notify(mpls);
     322             :             }
     323           0 :             return false;
     324             :         }
     325             :     }
     326           0 :     mpls->Delete(req);
     327           0 :     CheckVrLabelLimit();
     328           0 :     return true;
     329             : }
     330             : 
     331           0 : void MplsTable::OnZeroRefcount(AgentDBEntry *e) {
     332           0 :     agent()->ConcurrencyCheck();
     333             : 
     334             :     //Delete db entry
     335           0 :     DBRequest req(DBRequest::DB_ENTRY_DELETE);
     336           0 :     req.key = e->GetDBRequestKey();
     337           0 :     req.data.reset(NULL);
     338           0 :     Process(req);
     339           0 : }
     340             : 
     341           0 : uint32_t MplsTable::CreateRouteLabel(uint32_t label, const NextHopKey *nh_key,
     342             :                                 const std::string &vrf_name,
     343             :                                 const std::string &route) {
     344           0 :     if (label == MplsTable::kInvalidLabel) {
     345             :         ResourceManager::KeyPtr key(new RouteMplsResourceKey(agent()->
     346           0 :                                 resource_manager(), vrf_name,
     347           0 :                                 route));
     348             :         label = ((static_cast<IndexResourceData *>(agent()->resource_manager()->
     349           0 :                                       Allocate(key).get()))->index());
     350           0 :         assert(label != MplsTable::kInvalidLabel);
     351           0 :         assert(FindMplsLabel(label) == NULL);
     352           0 :     }
     353             : 
     354           0 :     DBRequest req;
     355           0 :     req.oper = DBRequest::DB_ENTRY_ADD_CHANGE;
     356             : 
     357           0 :     MplsLabelKey *key = new MplsLabelKey(label);
     358           0 :     req.key.reset(key);
     359             : 
     360           0 :     MplsLabelData *data = new MplsLabelData(nh_key->Clone());
     361           0 :     data->set_vrf_name(vrf_name);
     362           0 :     req.data.reset(data);
     363             : 
     364           0 :     Process(req);
     365           0 :     return label;
     366           0 : }
     367             : 
     368           0 : bool MplsTable::IsFabricMulticastLabel(uint32_t label) const {
     369           0 :     for (uint8_t count = 0; count < MAX_XMPP_SERVERS; count++) {
     370           0 :         if ((label >= multicast_label_start_[count]) &&
     371           0 :             (label <= multicast_label_end_[count])) return true;
     372             :     }
     373           0 :     return false;
     374             : }
     375             : 
     376           0 : void MplsTable::ReserveLabel(uint32_t start, uint32_t end) {
     377             :     // We want to allocate labels from an offset
     378             :     // Pre-allocate entries
     379           0 :     for (uint32_t i = start; i <= end;  i++) {
     380           0 :         agent()->resource_manager()->ReserveIndex(Resource::MPLS_INDEX, i);
     381             :     }
     382           0 : }
     383             : 
     384           0 : void MplsTable::FreeReserveLabel(uint32_t start, uint32_t end) {
     385             :     // We want to allocate labels from an offset
     386             :     // Pre-allocate entries
     387           0 :     for (uint32_t i = start; i <= end;  i++) {
     388           0 :         agent()->resource_manager()->ReleaseIndex(Resource::MPLS_INDEX, i);
     389             :     }
     390           0 : }
     391             : 
     392           0 : void MplsTable::ReserveMulticastLabel(uint32_t start, uint32_t end,
     393             :                                       uint8_t idx) {
     394           0 :     multicast_label_start_[idx] = start;
     395           0 :     multicast_label_end_[idx] = end;
     396           0 :     ReserveLabel(start, end);
     397           0 : }
     398             : 
     399           0 : MplsLabel *MplsTable::FindMplsLabel(uint32_t label) {
     400           0 :     MplsLabelKey key(label);
     401           0 :     return static_cast<MplsLabel *>(Find(&key, false));
     402           0 : }
     403             : 
     404             : // Allocate label for next-hop(interface, vrf, vlan)
     405           0 : MplsLabel *MplsTable::AllocLabel(const NextHopKey *nh_key) {
     406           0 :     switch(nh_key->GetType()) {
     407           0 :     case NextHop::INTERFACE:
     408             :     case NextHop::VLAN:
     409             :     case NextHop::VRF:
     410           0 :         break;
     411           0 :     default:
     412           0 :         assert(0);
     413             :     }
     414             : 
     415             :     // Allocate label from resource manager
     416             :     ResourceManager::KeyPtr rkey(new NexthopIndexResourceKey(
     417           0 :                                          agent()->resource_manager(),
     418           0 :                                          nh_key->Clone()));
     419             :     uint32_t label = ((static_cast<IndexResourceData *>(agent()->resource_manager()->
     420           0 :                                       Allocate(rkey).get()))->index());
     421           0 :     assert(label != MplsTable::kInvalidLabel);
     422             : 
     423             :     // Add MplsLabel db entry
     424           0 :     DBRequest req;
     425           0 :     req.oper = DBRequest::DB_ENTRY_ADD_CHANGE;
     426             : 
     427           0 :     MplsLabelKey *key = new MplsLabelKey(label);
     428           0 :     req.key.reset(key);
     429             : 
     430           0 :     MplsLabelData *data = new MplsLabelData(nh_key->Clone());
     431           0 :     req.data.reset(data);
     432             : 
     433           0 :     agent()->mpls_table()->Process(req);
     434             : 
     435             :     // Return MplsLabel db entry for nh to hold reference
     436           0 :     MplsLabel *mpls_label = static_cast<MplsLabel *>
     437           0 :         (agent()->mpls_table()->FindActiveEntry(key));
     438           0 :     assert(mpls_label);
     439             : 
     440           0 :     return mpls_label;
     441             : }
     442             : 
     443           0 : void MplsTable::CheckVrLabelLimit() {
     444           0 :     VrLimitExceeded &vr_limits = agent()->get_vr_limits_exceeded_map();
     445           0 :     VrLimitExceeded::iterator vr_limit_itr = vr_limits.find("vr_mpls_labels");
     446           0 :     if (vr_limit_itr->second == "Normal") {
     447           0 :         if (label_table_.InUseIndexCount() >= ((agent()->vr_limit_high_watermark() *
     448           0 :             agent()->vrouter_max_labels())/100) ) {
     449           0 :             vr_limit_itr->second.assign(std::string("Exceeded"));
     450           0 :             LOG(ERROR, "Vrouter Mpls Labels Exceeded.");
     451             :         }
     452           0 :     } else if ( vr_limit_itr->second == "Exceeded") {
     453           0 :         if (label_table_.InUseIndexCount() >= agent()->vrouter_max_labels()) {
     454           0 :             vr_limit_itr->second.assign(std::string("TableLimit"));
     455           0 :             LOG(ERROR, "Vrouter Mpls Lablels Table Limit Reached. Skip Label Add.");
     456           0 :         } else if ( label_table_.InUseIndexCount() < ((agent()->vr_limit_low_watermark() *
     457           0 :             agent()->vrouter_max_labels())/100) ) {
     458           0 :             vr_limit_itr->second.assign(std::string("Normal"));
     459             :         }
     460           0 :     } else if ( vr_limit_itr->second == "TableLimit" ) {
     461           0 :         if (label_table_.InUseIndexCount() <
     462           0 :             ((agent()->vrouter_max_labels()*95)/100) ) {
     463           0 :             vr_limit_itr->second.assign(std::string("Exceeded"));
     464           0 :             LOG(ERROR, "Vrouter Mpls Labels Exceeded.");
     465             :         }
     466             :     }
     467           0 :     agent()->set_vr_limits_exceeded_map(vr_limits);
     468           0 : }
     469             : 
     470           0 : AgentSandeshPtr MplsTable::GetAgentSandesh(const AgentSandeshArguments *args,
     471             :                                            const std::string &context) {
     472             :     return AgentSandeshPtr(new AgentMplsSandesh
     473           0 :                            (context, args->GetString("type"),
     474           0 :                             args->GetString("label")));
     475             : }
     476             : 
     477           0 : void MplsReq::HandleRequest() const {
     478           0 :     AgentSandeshPtr sand(new AgentMplsSandesh(context(), get_type(),
     479           0 :                                               get_label()));
     480           0 :     sand->DoSandesh(sand);
     481           0 : }

Generated by: LCOV version 1.14