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

Generated by: LCOV version 1.14