LCOV - code coverage report
Current view: top level - bgp - bgp_config.cc (source / functions) Hit Total Coverage
Test: OpenSDN C/C++ coverage (all TARGET_SET jobs) Lines: 335 391 85.7 %
Date: 2026-11-09 02:10:49 Functions: 49 57 86.0 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /*
       2             :  * Copyright (c) 2014 Juniper Networks, Inc. All rights reserved.
       3             :  * Copyright Contributors to the OpenSDN project
       4             :  */
       5             : #include "bgp/bgp_config.h"
       6             : 
       7             : #include <boost/foreach.hpp>
       8             : 
       9             : #include <sstream>
      10             : 
      11             : #include "base/string_util.h"
      12             : #include "base/time_util.h"
      13             : 
      14             : using std::copy;
      15             : using std::endl;
      16             : using std::ostringstream;
      17             : using std::ostream_iterator;
      18             : using std::sort;
      19             : using std::string;
      20             : using std::swap;
      21             : using std::vector;
      22             : 
      23             : const char *BgpConfigManager::kMasterNetwork =
      24             :         "default-domain:default-project:ip-fabric";
      25             : const char *BgpConfigManager::kMasterInstance =
      26             :         "default-domain:default-project:ip-fabric:__default__";
      27             : const char *BgpConfigManager::kFabricInstance =
      28             :         "default-domain:default-project:ip-fabric:ip-fabric";
      29             : const int BgpConfigManager::kDefaultPort = 179;
      30             : const uint32_t BgpConfigManager::kDefaultAutonomousSystem = 64512;
      31             : 
      32        3410 : static int CompareTo(const AuthenticationKey &lhs,
      33             :                      const AuthenticationKey &rhs) {
      34        3410 :     KEY_COMPARE(lhs.id, rhs.id);
      35        3410 :     KEY_COMPARE(lhs.value, rhs.value);
      36        3303 :     KEY_COMPARE(lhs.start_time, rhs.start_time);
      37        3303 :     return 0;
      38             : }
      39             : 
      40        3195 : bool AuthenticationKey::operator<(const AuthenticationKey &rhs) const {
      41        3195 :     int cmp = CompareTo(*this, rhs);
      42        3195 :     return cmp < 0;
      43             : }
      44             : 
      45         215 : bool AuthenticationKey::operator==(const AuthenticationKey &rhs) const {
      46         215 :     int cmp = CompareTo(*this, rhs);
      47         215 :     return cmp == 0;
      48             : }
      49             : 
      50      101702 : AuthenticationData::AuthenticationData() : key_type_(NIL) {
      51      101702 : }
      52             : 
      53           0 : AuthenticationData::AuthenticationData(KeyType type,
      54           0 :         const AuthenticationKeyChain &chain) :
      55           0 :     key_type_(type), key_chain_(chain) {
      56           0 : }
      57             : 
      58       42040 : bool AuthenticationData::operator<(const AuthenticationData &rhs) const {
      59       42040 :     BOOL_KEY_COMPARE(key_type_, rhs.key_type());
      60       42021 :     BOOL_KEY_COMPARE(key_chain_, rhs.key_chain());
      61       41964 :     return false;
      62             : }
      63             : 
      64       20418 : bool AuthenticationData::operator==(const AuthenticationData &rhs) const {
      65       40668 :     if ((key_chain_.size() != rhs.key_chain().size()) ||
      66       20250 :         (key_type_ != rhs.key_type())) {
      67         168 :         return false;
      68             :     }
      69             : 
      70       20425 :     for (size_t ocnt = 0; ocnt < rhs.key_chain().size(); ++ocnt) {
      71         215 :         bool found = false;
      72         255 :         for (size_t icnt = 0; icnt < key_chain_.size(); ++icnt) {
      73         215 :             if (key_chain_[icnt] == rhs.key_chain()[ocnt]) {
      74         175 :                 found = true;
      75         175 :                 break;
      76             :             }
      77             :         }
      78         215 :         if (!found) {
      79          40 :             return false;
      80             :         }
      81             :     }
      82       20210 :     return true;
      83             : }
      84             : 
      85       59521 : AuthenticationData &AuthenticationData::operator=(
      86             :         const AuthenticationData &rhs) {
      87       59521 :     set_key_type(rhs.key_type());
      88       59521 :     set_key_chain(rhs.key_chain());
      89       59521 :     return *this;
      90             : }
      91             : 
      92         657 : void AuthenticationData::AddKeyToKeyChain(const AuthenticationKey &key) {
      93         657 :     key_chain_.push_back(key);
      94         657 : }
      95             : 
      96           0 : const AuthenticationKey *AuthenticationData::Find(int key_id) const {
      97             :     const AuthenticationKey *item;
      98           0 :     for (size_t i = 0; i < key_chain_.size(); ++i) {
      99           0 :         item = &key_chain_[i];
     100           0 :         if (item->id == key_id) {
     101           0 :             return item;
     102             :         }
     103             :     }
     104           0 :     return NULL;
     105             : }
     106             : 
     107       30771 : bool AuthenticationData::Empty() const {
     108       30771 :     return key_chain_.empty();
     109             : }
     110             : 
     111           0 : void AuthenticationData::Clear() {
     112           0 :     key_chain_.clear();
     113           0 : }
     114             : 
     115       13397 : string AuthenticationData::KeyTypeToString() const {
     116       13397 :     switch (key_type_) {
     117         344 :         case MD5:
     118         344 :             return "MD5";
     119       13053 :         default:
     120       13053 :             return "NIL";
     121             :     }
     122             : }
     123             : 
     124        1725 : string AuthenticationData::KeyTypeToString(KeyType key_type) {
     125        1725 :     switch (key_type) {
     126        1613 :         case MD5:
     127        1613 :             return "MD5";
     128         112 :         default:
     129         112 :             return "NIL";
     130             :     }
     131             : }
     132             : 
     133       13392 : vector<string> AuthenticationData::KeysToString() const {
     134       13392 :     AuthenticationKeyChain::const_iterator iter;
     135       13392 :     vector<string> auth_keys;
     136       13736 :     for (iter = key_chain_.begin(); iter != key_chain_.end(); ++iter) {
     137         344 :         AuthenticationKey key = *iter;
     138         344 :         auth_keys.push_back(integerToString(key.id));
     139         344 :     }
     140       26784 :     return auth_keys;
     141           0 : }
     142             : 
     143             : // NOTE: This prints the actual key too. Use with care.
     144           0 : vector<string> AuthenticationData::KeysToStringDetail() const {
     145           0 :     AuthenticationKeyChain::const_iterator iter;
     146           0 :     vector<string> auth_keys;
     147           0 :     for (iter = key_chain_.begin(); iter != key_chain_.end(); ++iter) {
     148           0 :         AuthenticationKey key = *iter;
     149           0 :         auth_keys.push_back(integerToString(key.id) + ":" + key.value);
     150           0 :     }
     151           0 :     return auth_keys;
     152           0 : }
     153             : 
     154       32032 : BgpNeighborConfig::OriginOverrideConfig::OriginOverrideConfig()
     155       32032 :         : origin_override(false), origin("IGP") {
     156       32032 : }
     157             : 
     158       43032 : bool BgpNeighborConfig::OriginOverrideConfig::operator<(
     159             :                 const OriginOverrideConfig &rhs) const {
     160       43032 :     if (origin_override == rhs.origin_override) {
     161       43032 :         if (origin_override) {
     162             :             // chek origin value only if override is set
     163           6 :             return origin < rhs.origin;
     164             :         }
     165       43026 :         return false;
     166             :     }
     167             : 
     168           0 :     return origin_override < rhs.origin_override;
     169             : }
     170             : 
     171           1 : bool BgpFamilyAttributesConfig::operator==(
     172             :         const BgpFamilyAttributesConfig &rhs) const {
     173           1 :     if (family != rhs.family)
     174           0 :         return false;
     175           1 :     if (loop_count != rhs.loop_count)
     176           0 :         return false;
     177           1 :     if (prefix_limit != rhs.prefix_limit)
     178           0 :         return false;
     179           1 :     if (idle_timeout != rhs.idle_timeout)
     180           0 :         return false;
     181           1 :     if (default_tunnel_encap_list != rhs.default_tunnel_encap_list)
     182           0 :         return false;
     183           1 :     return true;
     184             : }
     185             : 
     186       32032 : BgpNeighborConfig::BgpNeighborConfig()
     187       32032 :         : type_(UNSPECIFIED),
     188       32032 :           admin_down_(false),
     189       32032 :           passive_(false),
     190       32032 :           as_override_(false),
     191       32032 :           cluster_id_(0),
     192       32032 :           peer_as_(0),
     193       32032 :           identifier_(0),
     194       32032 :           port_(BgpConfigManager::kDefaultPort),
     195       32032 :           source_port_(0),
     196       32032 :           hold_time_(0),
     197       32032 :           loop_count_(0),
     198       32032 :           local_as_(0),
     199       32032 :           local_identifier_(0),
     200       32032 :           last_change_at_(UTCTimestampUsec()) {
     201       32032 : }
     202             : 
     203           1 : void BgpNeighborConfig::CopyValues(const BgpNeighborConfig &rhs) {
     204           1 :     instance_name_ = rhs.instance_name_;
     205           1 :     group_name_ = rhs.group_name_;
     206           1 :     type_ = rhs.type_;
     207           1 :     admin_down_ = rhs.admin_down_;
     208           1 :     passive_ = rhs.passive_;
     209           1 :     as_override_ = rhs.as_override_;
     210           1 :     private_as_action_  = rhs.private_as_action_;
     211           1 :     cluster_id_ = rhs.cluster_id_;
     212           1 :     peer_as_ = rhs.peer_as_;
     213           1 :     identifier_ = rhs.identifier_;
     214           1 :     address_ = rhs.address_;
     215           1 :     inet_gateway_address_ = rhs.inet_gateway_address_;
     216           1 :     inet6_gateway_address_ = rhs.inet6_gateway_address_;
     217           1 :     port_ = rhs.port_;
     218           1 :     source_port_ = rhs.source_port_;
     219           1 :     hold_time_ = rhs.hold_time_;
     220           1 :     loop_count_ = rhs.loop_count_;
     221           1 :     local_as_ = rhs.local_as_;
     222           1 :     local_identifier_ = rhs.local_identifier_;
     223           1 :     auth_data_ = rhs.auth_data_;
     224           1 :     family_attributes_list_ = rhs.family_attributes_list_;
     225           1 :     origin_override_ = rhs.origin_override_;
     226           1 : }
     227             : 
     228       21662 : int BgpNeighborConfig::CompareTo(const BgpNeighborConfig &rhs) const {
     229       21662 :     KEY_COMPARE(name_, rhs.name_);
     230       21662 :     KEY_COMPARE(uuid_, rhs.uuid_);
     231       21662 :     KEY_COMPARE(instance_name_, rhs.instance_name_);
     232       21662 :     KEY_COMPARE(type_, rhs.type_);
     233       21662 :     KEY_COMPARE(admin_down_, rhs.admin_down_);
     234       21542 :     KEY_COMPARE(passive_, rhs.passive_);
     235       21518 :     KEY_COMPARE(as_override_, rhs.as_override_);
     236       21516 :     KEY_COMPARE(origin_override_, rhs.origin_override_);
     237       21516 :     KEY_COMPARE(private_as_action_, rhs.private_as_action_);
     238       21513 :     KEY_COMPARE(cluster_id_, rhs.cluster_id_);
     239       21513 :     KEY_COMPARE(peer_as_, rhs.peer_as_);
     240       21318 :     KEY_COMPARE(identifier_, rhs.identifier_);
     241       21261 :     KEY_COMPARE(address_, rhs.address_);
     242       21261 :     KEY_COMPARE(inet_gateway_address_, rhs.inet_gateway_address_);
     243       21259 :     KEY_COMPARE(inet6_gateway_address_, rhs.inet6_gateway_address_);
     244       21259 :     KEY_COMPARE(port_, rhs.port_);
     245       21258 :     KEY_COMPARE(source_port_, rhs.source_port_);
     246       21250 :     KEY_COMPARE(hold_time_, rhs.hold_time_);
     247       21142 :     KEY_COMPARE(loop_count_, rhs.loop_count_);
     248       21142 :     KEY_COMPARE(local_as_, rhs.local_as_);
     249       21053 :     KEY_COMPARE(local_identifier_, rhs.local_identifier_);
     250       21043 :     KEY_COMPARE(auth_data_, rhs.auth_data_);
     251       20982 :     return STLSortedCompare(
     252             :         family_attributes_list_.begin(), family_attributes_list_.end(),
     253             :         rhs.family_attributes_list_.begin(), rhs.family_attributes_list_.end(),
     254       20982 :         BgpFamilyAttributesConfigCompare());
     255             : }
     256             : 
     257       29194 : void BgpNeighborConfig::SetOriginOverride(bool origin_override,
     258             :                                           std::string origin) {
     259       29194 :     origin_override_.origin_override = origin_override;
     260       29194 :     origin_override_.origin = origin;
     261       29194 : }
     262             : 
     263         407 : const IpAddress &BgpNeighborConfig::gateway_address(
     264             :     Address::Family family) const {
     265         407 :     assert(family == Address::INET || family == Address::INET6);
     266         407 :     if (family == Address::INET) {
     267         207 :         return inet_gateway_address_;
     268             :     } else {
     269         200 :         return inet6_gateway_address_;
     270             :     }
     271             : }
     272             : 
     273        1022 : void BgpNeighborConfig::set_gateway_address(Address::Family family,
     274             :     const IpAddress &address) {
     275        1022 :     assert(family == Address::INET || family == Address::INET6);
     276        1022 :     if (family == Address::INET) {
     277         511 :         inet_gateway_address_ = address;
     278             :     } else {
     279         511 :         inet6_gateway_address_ = address;
     280             :     }
     281        1022 : }
     282             : 
     283             : BgpNeighborConfig::AddressFamilyList
     284       33815 : BgpNeighborConfig::GetAddressFamilies() const {
     285       33815 :     BgpNeighborConfig::AddressFamilyList family_list;
     286       85826 :     for (const auto& family_config : family_attributes_list_) {
     287       52011 :         family_list.push_back(family_config.family);
     288             :     }
     289       33815 :     sort(family_list.begin(), family_list.end());
     290       33815 :     return family_list;
     291           0 : }
     292             : 
     293       13392 : string BgpNeighborConfig::AuthKeyTypeToString() const {
     294       13392 :     return auth_data_.KeyTypeToString();
     295             : }
     296             : 
     297             : // Return the key's id concatenated with its type.
     298       13392 : vector<string> BgpNeighborConfig::AuthKeysToString() const {
     299       13392 :     return auth_data_.KeysToString();
     300             : }
     301             : 
     302             : 
     303         415 : bool StaticRouteConfig::operator<(const StaticRouteConfig &rhs) const {
     304         415 :     BOOL_KEY_COMPARE(address, rhs.address);
     305          14 :     BOOL_KEY_COMPARE(prefix_length, rhs.prefix_length);
     306          14 :     BOOL_KEY_COMPARE(nexthop, rhs.nexthop);
     307           0 :     return false;
     308             : }
     309             : 
     310        8596 : BgpProtocolConfig::BgpProtocolConfig(const string &instance_name)
     311        8596 :     : instance_name_(instance_name),
     312        8596 :       admin_down_(false),
     313        8596 :       cluster_id_(0),
     314        8596 :       autonomous_system_(0),
     315        8596 :       local_autonomous_system_(0),
     316        8596 :       identifier_(0),
     317        8596 :       port_(0),
     318        8596 :       hold_time_(0),
     319        8596 :       last_change_at_(UTCTimestampUsec()) {
     320        8596 : }
     321             : 
     322           0 : int BgpProtocolConfig::CompareTo(const BgpProtocolConfig &rhs) const {
     323           0 :     KEY_COMPARE(instance_name_, rhs.instance_name_);
     324           0 :     KEY_COMPARE(admin_down_, rhs.admin_down_);
     325           0 :     KEY_COMPARE(autonomous_system_, rhs.autonomous_system_);
     326           0 :     KEY_COMPARE(identifier_, rhs.identifier_);
     327           0 :     KEY_COMPARE(port_, rhs.port_);
     328           0 :     KEY_COMPARE(hold_time_, rhs.hold_time_);
     329           0 :     return 0;
     330             : }
     331             : 
     332       51340 : BgpInstanceConfig::BgpInstanceConfig(const string &name)
     333       51340 :     : name_(name),
     334       51340 :       has_pnf_(false),
     335       51340 :       virtual_network_index_(0),
     336       51340 :       virtual_network_allow_transit_(false),
     337       51340 :       virtual_network_pbb_evpn_enable_(false),
     338       51340 :       index_(-1),
     339       51340 :       vxlan_id_(0),
     340       51340 :       last_change_at_(UTCTimestampUsec()) {
     341       51340 : }
     342             : 
     343       51353 : BgpInstanceConfig::~BgpInstanceConfig() {
     344       51353 : }
     345             : 
     346      124446 : void BgpInstanceConfig::Clear() {
     347      124446 :     import_list_.clear();
     348      124446 :     export_list_.clear();
     349      124446 :     has_pnf_ = false;
     350      124446 :     virtual_network_.clear();
     351      124446 :     virtual_network_index_ = 0;
     352      124446 :     virtual_network_allow_transit_ = false;
     353      124446 :     virtual_network_pbb_evpn_enable_ = false;
     354      124446 :     vxlan_id_ = 0;
     355      124446 :     inet_static_routes_.clear();
     356      124446 :     inet6_static_routes_.clear();
     357      124446 :     service_chain_list_.clear();
     358      124446 : }
     359             : 
     360       99535 : const BgpInstanceConfig::StaticRouteList &BgpInstanceConfig::static_routes(
     361             :     Address::Family family) const {
     362       99535 :     assert(family == Address::INET || family == Address::INET6);
     363       99535 :     if (family == Address::INET) {
     364       49786 :         return inet_static_routes_;
     365             :     } else {
     366       49749 :         return inet6_static_routes_;
     367             :     }
     368             : }
     369             : 
     370        8442 : void BgpInstanceConfig::swap_static_routes(Address::Family family,
     371             :     StaticRouteList *list) {
     372        8442 :     assert(family == Address::INET || family == Address::INET6);
     373        8442 :     if (family == Address::INET) {
     374        4221 :         swap(inet_static_routes_, *list);
     375             :     } else {
     376        4221 :         swap(inet6_static_routes_, *list);
     377             :     }
     378        8442 : }
     379             : 
     380      591492 : const ServiceChainConfig *BgpInstanceConfig::service_chain_info(
     381             :     SCAddress::Family family) const {
     382      591492 :     for (ServiceChainList::const_iterator it = service_chain_list_.begin();
     383      601024 :          it != service_chain_list_.end(); ++it) {
     384       16887 :         if (it->family == family)
     385        7355 :             return it.operator->();
     386             :     }
     387      584120 :     return NULL;
     388             : }
     389             : 
     390             : const BgpInstanceConfig::AggregateRouteList &
     391       99587 : BgpInstanceConfig::aggregate_routes(Address::Family family) const {
     392       99587 :     assert(family == Address::INET || family == Address::INET6);
     393       99587 :     if (family == Address::INET) {
     394       49884 :         return inet_aggregate_routes_;
     395             :     } else {
     396       49703 :         return inet6_aggregate_routes_;
     397             :     }
     398             : }
     399             : 
     400      248892 : void BgpInstanceConfig::swap_aggregate_routes(Address::Family family,
     401             :                                               AggregateRouteList *list) {
     402      248892 :     assert(family == Address::INET || family == Address::INET6);
     403      248892 :     if (family == Address::INET) {
     404      124446 :         swap(inet_aggregate_routes_, *list);
     405             :     } else {
     406      124446 :         swap(inet6_aggregate_routes_, *list);
     407             :     }
     408      248892 : }
     409             : 
     410         161 : BgpRoutingPolicyConfig::BgpRoutingPolicyConfig(const string &name)
     411         161 :         : name_(name),
     412         161 :           last_change_at_(UTCTimestampUsec()) {
     413         161 : }
     414             : 
     415         161 : BgpRoutingPolicyConfig::~BgpRoutingPolicyConfig() {
     416         161 : }
     417             : 
     418         396 : void BgpRoutingPolicyConfig::Clear() {
     419         396 :     terms_.clear();
     420         396 : }
     421             : 
     422          10 : string RoutingPolicyMatchConfig::ToString() const {
     423          10 :     ostringstream oss;
     424          10 :     oss << "from {" << endl;
     425          10 :     if (!protocols_match.empty()) {
     426           0 :         oss << "    protocol [ ";
     427           0 :         for (const auto &protocol : protocols_match) {
     428           0 :             oss << protocol << ",";
     429             :         }
     430           0 :         oss.seekp(-1, oss.cur);
     431           0 :         oss << " ]";
     432             :     }
     433          10 :     if (!community_match.empty()) {
     434           4 :         if (community_match_all) {
     435           0 :             oss << "    community (all) [ ";
     436             :         } else {
     437           4 :             oss << "    community (any) [ ";
     438             :         }
     439           8 :         for (const auto &community : community_match) {
     440           4 :             oss << community << ",";
     441             :         }
     442           4 :         oss.seekp(-1, oss.cur);
     443           4 :         oss << " ]";
     444             :     }
     445          10 :     if (!prefixes_to_match.empty()) {
     446          16 :         for (const auto &match : prefixes_to_match) {
     447          10 :             oss << "    prefix " << match.prefix_to_match << " "
     448          10 :                 << match.prefix_match_type << endl;
     449             :         }
     450             :     }
     451          10 :     oss << "}" << endl;
     452          20 :     return oss.str();
     453          10 : }
     454             : 
     455           0 : static void PutAsnList(ostringstream *oss, const AsnList &list) {
     456           0 :     copy(list.begin(), list.end(), ostream_iterator<uint16_t>(*oss, ","));
     457           0 :     oss->seekp(-1, oss->cur);
     458           0 : }
     459             : 
     460           6 : static void PutCommunityList(ostringstream *oss, const CommunityList &list) {
     461           6 :     copy(list.begin(), list.end(), ostream_iterator<string>(*oss, ","));
     462           6 :     oss->seekp(-1, oss->cur);
     463           6 : }
     464             : 
     465          10 : string RoutingPolicyActionConfig::ToString() const {
     466          10 :     ostringstream oss;
     467          10 :     oss << "then {" << endl;
     468          10 :     if (!update.aspath_expand.empty()) {
     469           0 :         oss << "    as-path expand [ ";
     470           0 :         PutAsnList(&oss, update.aspath_expand);
     471           0 :         oss << " ]" << endl;
     472             :     }
     473          10 :     if (!update.community_set.empty()) {
     474           2 :         oss << "    community set [ ";
     475           2 :         PutCommunityList(&oss, update.community_set);
     476           2 :         oss << " ]" << endl;
     477             :     }
     478          10 :     if (!update.community_add.empty()) {
     479           0 :         oss << "    community add [ ";
     480           0 :         PutCommunityList(&oss, update.community_add);
     481           0 :         oss << " ]" << endl;
     482             :     }
     483          10 :     if (!update.community_remove.empty()) {
     484           4 :         oss << "    community remove [ ";
     485           4 :         PutCommunityList(&oss, update.community_remove);
     486           4 :         oss << " ]" << endl;
     487             :     }
     488          10 :     if (update.local_pref) {
     489           6 :         oss << "    local-preference " << update.local_pref << endl;
     490             :     }
     491          10 :     if (update.med) {
     492           0 :         oss << "    med " << update.med << endl;
     493             :     }
     494             : 
     495          10 :     if (action == ACCEPT) {
     496           2 :         oss << "    accept" << endl;
     497           8 :     } else if (action == REJECT) {
     498           4 :         oss << "    reject" << endl;
     499           4 :     } else if (action == NEXT_TERM) {
     500           4 :         oss << "    next-term" << endl;
     501             :     }
     502          10 :     oss << "}" << endl;
     503          20 :     return oss.str();
     504          10 : }
     505             : 
     506        9743 : BgpConfigManager::BgpConfigManager(BgpServer *server)
     507        9743 :         : server_(server) {
     508        9743 : }
     509             : 
     510        9743 : BgpConfigManager::~BgpConfigManager() {
     511        9743 : }
     512             : 
     513             : template<>
     514      161085 : void BgpConfigManager::Notify<BgpInstanceConfig>(
     515             :         const BgpInstanceConfig *config, EventType event) {
     516      161085 :     config->set_last_change_at(UTCTimestampUsec());
     517      358065 :     for (auto obs : obs_) {
     518      196980 :         if (obs.instance) {
     519      161085 :             (obs.instance)(config, event);
     520             :         }
     521      196980 :     }
     522      161085 : }
     523             : 
     524             : template<>
     525         439 : void BgpConfigManager::Notify<BgpRoutingPolicyConfig>(
     526             :         const BgpRoutingPolicyConfig *config, EventType event) {
     527         439 :     config->set_last_change_at(UTCTimestampUsec());
     528         888 :     for (auto obs : obs_) {
     529         449 :         if (obs.policy) {
     530         439 :             (obs.policy)(config, event);
     531             :         }
     532         449 :     }
     533         439 : }
     534             : 
     535             : template<>
     536        9050 : void BgpConfigManager::Notify<BgpProtocolConfig>(
     537             :         const BgpProtocolConfig *config, EventType event) {
     538        9050 :     config->set_last_change_at(UTCTimestampUsec());
     539       20786 :     for (auto obs : obs_) {
     540       11736 :         if (obs.protocol) {
     541       11736 :             (obs.protocol)(config, event);
     542             :         }
     543       11736 :     }
     544        9050 : }
     545             : 
     546             : template<>
     547       16900 : void BgpConfigManager::Notify<BgpNeighborConfig>(
     548             :         const BgpNeighborConfig *config, EventType event) {
     549       16900 :     config->set_last_change_at(UTCTimestampUsec());
     550       37162 :     for (auto obs : obs_) {
     551       20262 :         if (obs.neighbor) {
     552       16900 :             (obs.neighbor)(config, event);
     553             :         }
     554       20262 :     }
     555       16900 : }
     556             : 
     557             : template<>
     558         840 : void BgpConfigManager::Notify<BgpGlobalSystemConfig>(
     559             :         const BgpGlobalSystemConfig *config, EventType event) {
     560         840 :     config->set_last_change_at(UTCTimestampUsec());
     561        2147 :     for (auto obs : obs_) {
     562        1307 :         if (obs.system) {
     563        1307 :             (obs.system)(config, event);
     564             :         }
     565        1307 :     }
     566         840 : }
     567             : 
     568             : template<>
     569           9 : void BgpConfigManager::Notify<BgpGlobalQosConfig>(
     570             :         const BgpGlobalQosConfig *config, EventType event) {
     571           9 :     config->set_last_change_at(UTCTimestampUsec());
     572          25 :     for (auto obs : obs_) {
     573          16 :         if (obs.qos) {
     574           9 :             (obs.qos)(config, event);
     575             :         }
     576          16 :     }
     577           9 : }

Generated by: LCOV version 1.14