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

Generated by: LCOV version 1.14