LCOV - code coverage report
Current view: top level - vnsw/agent/mac_learning - mac_aging.cc (source / functions) Hit Total Coverage
Test: OpenSDN C/C++ coverage (all TARGET_SET jobs) Lines: 21 151 13.9 %
Date: 2026-08-03 02:19:58 Functions: 6 22 27.3 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /*
       2             :  * Copyright (c) 2017 Juniper Networks, Inc. All rights reserved.
       3             :  */
       4             : #include <oper/vn.h>
       5             : #include <oper/sg.h>
       6             : #include <oper/vm.h>
       7             : #include <oper/vrf.h>
       8             : #include <oper/nexthop.h>
       9             : #include <oper/interface_common.h>
      10             : #include <oper/route_common.h>
      11             : #include "mac_learning_proto.h"
      12             : #include "mac_learning_proto_handler.h"
      13             : #include "mac_learning_init.h"
      14             : #include "mac_learning.h"
      15             : #include "mac_aging.h"
      16             : #include "mac_learning_mgmt.h"
      17             : #include "vr_bridge.h"
      18             : #include "vrouter/ksync/ksync_init.h"
      19             : #include "vrouter/ksync/ksync_bridge_table.h"
      20             : 
      21           0 : MacAgingEntry::MacAgingEntry(MacLearningEntryPtr ptr):
      22           0 :     mac_learning_entry_(ptr), packets_(0), deleted_(false) {
      23           0 :     last_modified_time_ = UTCTimestampUsec();
      24           0 :     addition_time_ = UTCTimestampUsec();
      25           0 : }
      26             : 
      27           0 : void MacAgingEntry::FillSandesh(SandeshMacEntry *smac) const {
      28             :     MacPbbLearningEntry *entry =
      29           0 :         dynamic_cast<MacPbbLearningEntry *>(mac_learning_entry_.get());
      30           0 :     smac->set_vrf(mac_learning_entry_->vrf()->GetName());
      31           0 :     smac->set_mac(entry->mac().ToString());
      32           0 :     smac->set_index(entry->index());
      33           0 :     smac->set_packets(packets_);
      34             :     std::string time_since_addition =
      35           0 :         duration_usecs_to_string(UTCTimestampUsec() - addition_time_);
      36           0 :     smac->set_time_since_add(time_since_addition);
      37             :     std::string last_stats_change =
      38           0 :         duration_usecs_to_string(UTCTimestampUsec() - last_modified_time_);
      39           0 :     smac->set_last_stats_change(last_stats_change);
      40           0 : }
      41             : 
      42           0 : MacAgingTable::MacAgingTable(Agent *agent, const VrfEntry *vrf) :
      43           0 :     agent_(agent), timeout_msec_(kDefaultAgingTimeout), vrf_(vrf) {
      44           0 : }
      45             : 
      46           0 : MacAgingTable::~MacAgingTable() {
      47           0 : }
      48             : 
      49           0 : void MacAgingTable::Add(MacLearningEntryPtr ptr) {
      50           0 :     MacAgingEntryTable::iterator it = aging_table_.find(ptr.get());
      51           0 :     if (it != aging_table_.end()) {
      52           0 :        it->second->set_deleted(false);
      53           0 :        return;
      54             :     }
      55             : 
      56           0 :     MacAgingEntryPtr aging_entry_ptr(new MacAgingEntry(ptr));
      57           0 :     aging_table_.insert(MacAgingPair(ptr.get(), aging_entry_ptr));
      58           0 :     Trace("Adding MAC entry", aging_entry_ptr.get());
      59           0 : }
      60             : 
      61           0 : void MacAgingTable::Delete(MacLearningEntryPtr ptr) {
      62           0 :     MacAgingEntryTable::iterator it = aging_table_.find(ptr.get());
      63           0 :     if (it != aging_table_.end()) {
      64           0 :         Trace("Deleting MAC entry", it->second.get());
      65           0 :         aging_table_.erase(it);
      66             :     }
      67           0 : }
      68             : 
      69           0 : void MacAgingTable::ReadStats(MacAgingEntry *ptr) {
      70             :     MacPbbLearningEntry *entry =
      71           0 :         dynamic_cast<MacPbbLearningEntry *>(ptr->mac_learning_entry().get());
      72           0 :     uint32_t index = entry->index();
      73           0 :     vr_bridge_entry *vr_entry = agent_->ksync()->ksync_bridge_memory()->
      74           0 :                                     GetBridgeEntry(index);
      75           0 :     if (vr_entry == NULL) {
      76           0 :         ptr->set_packets(0);
      77             :     } else {
      78           0 :         ptr->set_packets(vr_entry->be_packets);
      79             :     }
      80           0 : }
      81             : 
      82             : 
      83           0 : bool MacAgingTable::ShouldBeAged(MacAgingEntry *ptr,
      84             :                                  uint64_t curr_time) {
      85           0 :     uint64_t packets = ptr->packets();
      86             : 
      87           0 :     ReadStats(ptr);
      88             : 
      89           0 :     if (packets == ptr->packets()) {
      90           0 :         if (curr_time - ptr->last_modified_time() > timeout_in_usecs()) {
      91           0 :             return true;
      92             :         }
      93           0 :         return false;
      94             :     }
      95             : 
      96           0 :     ptr->set_last_modified_time(curr_time);
      97           0 :     return false;
      98             : }
      99             : 
     100           0 : void MacAgingTable::Trace(const std::string &str, MacAgingEntry *ptr) {
     101           0 :     std::string vrf = "";
     102           0 :     if (ptr->mac_learning_entry()->vrf() != NULL) {
     103           0 :         vrf = ptr->mac_learning_entry()->vrf()->GetName();
     104             :     }
     105             :     MacPbbLearningEntry *entry =
     106           0 :         dynamic_cast<MacPbbLearningEntry *>(ptr->mac_learning_entry().get());
     107           0 :     MAC_AGING_TRACE(MacLearningTraceBuf, vrf,
     108             :                     entry->mac().ToString(),
     109             :                     entry->index(),
     110             :                     ptr->packets(), str);
     111           0 : }
     112             : 
     113           0 : void MacAgingTable::SendDeleteMsg(MacAgingEntry *ptr) {
     114           0 :     Trace("Aging", ptr);
     115           0 :     ptr->set_deleted(true);
     116             :     MacLearningEntryRequestPtr req(new MacLearningEntryRequest(
     117           0 :                 MacLearningEntryRequest::DELETE_MAC, ptr->mac_learning_entry()));
     118           0 :     ptr->mac_learning_entry()->EnqueueToTable(req);
     119           0 : }
     120             : 
     121             : uint32_t
     122           0 : MacAgingTable::CalculateEntriesPerIteration(uint32_t aging_table_entry_count) {
     123           0 :     uint32_t entry_count = aging_table_entry_count;
     124             : 
     125           0 :     if (vrf_) {
     126           0 :         timeout_msec_ = vrf_->mac_aging_time() * 1000;
     127             :     }
     128             : 
     129           0 :     if (timeout_msec_ == 0) {
     130           0 :         return 0;
     131             :     }
     132             : 
     133             :     //We want to scan all the entries 2 times before aging timeout
     134           0 :     uint32_t table_scan_time = timeout_msec_ / 10;
     135             : 
     136           0 :     uint32_t no_of_iteration = table_scan_time /
     137             :                                    MacAgingPartition::kMinIterationTimeout;
     138             : 
     139           0 :     if (no_of_iteration == 0) {
     140           0 :         no_of_iteration = 1;
     141             :     }
     142             : 
     143           0 :     uint32_t entry_count_per_iteration = entry_count / no_of_iteration;
     144             : 
     145           0 :     if (entry_count_per_iteration < kMinEntriesPerScan) {
     146           0 :         entry_count_per_iteration = kMinEntriesPerScan;
     147             :     }
     148           0 :     return entry_count_per_iteration;
     149             : }
     150             : 
     151           0 : bool MacAgingTable::Run() {
     152           0 :     uint64_t curr_time = UTCTimestampUsec();
     153             : 
     154           0 :     MacAgingEntryTable::const_iterator it = aging_table_.upper_bound(last_key_);
     155           0 :     if (it == aging_table_.end()) {
     156           0 :         it = aging_table_.begin();
     157             :     }
     158             : 
     159           0 :     uint32_t i = 0;
     160           0 :     uint32_t entries = CalculateEntriesPerIteration(aging_table_.size());
     161           0 :     while (it != aging_table_.end() && i < entries) {
     162           0 :         if (it->second->deleted() == false &&
     163           0 :                 ShouldBeAged(it->second.get(), curr_time)) {
     164           0 :             SendDeleteMsg(it->second.get());
     165             :         }
     166           0 :         last_key_ = it->first;
     167           0 :         it++;
     168           0 :         i++;
     169             :     }
     170             : 
     171           0 :     if (aging_table_.size() == 0) {
     172           0 :         return false;
     173             :     }
     174             : 
     175           0 :     return true;
     176             : }
     177             : 
     178           3 : MacAgingPartition::MacAgingPartition(Agent *agent, uint32_t partition_id) :
     179           3 :     agent_(agent), partition_id_(partition_id),
     180           3 :     request_queue_(agent_->task_scheduler()->GetTaskId(kTaskMacAging),
     181             :                            partition_id,
     182             :                            boost::bind(&MacAgingPartition::RequestHandler,
     183             :                                        this, _1)),
     184           3 :     timer_(TimerManager::CreateTimer(*(agent->event_manager()->io_service()),
     185             :                                        "MacAgingTimer",
     186             :                                        agent->task_scheduler()->
     187           6 :                                        GetTaskId(kTaskMacAging), partition_id)) {
     188           3 : }
     189             : 
     190           6 : MacAgingPartition::~MacAgingPartition() {
     191           3 :     TimerManager::DeleteTimer(timer_);
     192           6 : }
     193             : 
     194          12 : void MacAgingPartition::Enqueue(MacLearningEntryRequestPtr req) {
     195          12 :     request_queue_.Enqueue(req);
     196          12 : }
     197             : 
     198           0 : void MacAgingPartition::Add(MacLearningEntryPtr mle) {
     199           0 :     uint32_t vrf_id = mle->vrf_id();
     200             : 
     201           0 :     if (aging_table_map_[vrf_id] == NULL) {
     202           0 :         const VrfEntry *vrf = agent_->vrf_table()->FindVrfFromId(vrf_id);
     203           0 :         assert(vrf->IsActive() == true);
     204           0 :         MacAgingTablePtr aging_table(new MacAgingTable(agent_, vrf));
     205           0 :         aging_table_map_[vrf_id] = aging_table;
     206           0 :     }
     207             : 
     208           0 :     aging_table_map_[vrf_id]->Add(mle);
     209             : 
     210           0 :     if (timer_->running() == false) {
     211           0 :         timer_->Start(kMinIterationTimeout,
     212             :                 boost::bind(&MacAgingPartition::Run, this));
     213             :     }
     214           0 : }
     215             : 
     216           0 : void MacAgingPartition::Delete(MacLearningEntryPtr mle) {
     217           0 :     uint32_t vrf_id = mle->vrf_id();
     218           0 :     if (aging_table_map_[vrf_id] != NULL) {
     219           0 :         aging_table_map_[vrf_id]->Delete(mle);
     220             :     }
     221           0 : }
     222             : 
     223           0 : bool MacAgingPartition::Run() {
     224           0 :     bool ret = false;
     225           0 :     MacAgingTableMap::iterator it = aging_table_map_.begin();
     226           0 :     for (;it != aging_table_map_.end(); it++) {
     227           0 :         if (it->second.get() && it->second->Run()) {
     228           0 :             ret = true;
     229             :         }
     230             :     }
     231             : 
     232           0 :     return ret;
     233             : }
     234             : 
     235          12 : void MacAgingPartition::DeleteVrf(uint32_t id) {
     236          12 :     aging_table_map_[id].reset();
     237          12 : }
     238             : 
     239          12 : bool MacAgingPartition::RequestHandler(MacLearningEntryRequestPtr req) {
     240          12 :     switch(req->event()) {
     241           0 :     case MacLearningEntryRequest::ADD_MAC:
     242           0 :         Add(req->mac_learning_entry());
     243           0 :         break;
     244             : 
     245           0 :     case MacLearningEntryRequest::DELETE_MAC:
     246           0 :         Delete(req->mac_learning_entry());
     247           0 :         break;
     248             : 
     249          12 :     case MacLearningEntryRequest::DELETE_VRF:
     250          12 :         DeleteVrf(req->vrf_id());
     251          12 :         break;
     252             : 
     253           0 :     default:
     254           0 :         assert(0);
     255             :     }
     256          12 :     return true;
     257             : }

Generated by: LCOV version 1.14