LCOV - code coverage report
Current view: top level - bgp - bgp_config_ifmap.cc (source / functions) Hit Total Coverage
Test: OpenSDN C/C++ coverage (all TARGET_SET jobs) Lines: 1380 1455 94.8 %
Date: 2026-06-18 01:51:13 Functions: 126 131 96.2 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /*
       2             :  * Copyright (c) 2013 Juniper Networks, Inc. All rights reserved.
       3             :  */
       4             : 
       5             : #include "bgp/bgp_config_ifmap.h"
       6             : 
       7             : #include <boost/foreach.hpp>
       8             : 
       9             : #include <algorithm>
      10             : 
      11             : #include "base/string_util.h"
      12             : #include "base/task_annotations.h"
      13             : #include "bgp/bgp_common.h"
      14             : #include "bgp/bgp_config_listener.h"
      15             : #include "bgp/bgp_log.h"
      16             : #include "bgp/routing-instance/iservice_chain_mgr.h"
      17             : #include "ifmap/ifmap_node.h"
      18             : #include "ifmap/ifmap_table.h"
      19             : 
      20             : #include "schema/bgp_schema_types.h"
      21             : #include "schema/vnc_cfg_types.h"
      22             : 
      23             : using std::unique_ptr;
      24             : using std::find;
      25             : using std::make_pair;
      26             : using std::pair;
      27             : using std::set;
      28             : using std::sort;
      29             : using std::string;
      30             : using std::vector;
      31             : using boost::iequals;
      32             : 
      33             : const int BgpIfmapConfigManager::kConfigTaskInstanceId = 0;
      34             : 
      35             : static BgpNeighborConfig::AddressFamilyList default_addr_family_list;
      36             : 
      37         125 : void DefaultAddressFamilyInit() {
      38         125 :     default_addr_family_list.push_back("inet");
      39         125 :     default_addr_family_list.push_back("inet-vpn");
      40         125 : }
      41             : 
      42             : MODULE_INITIALIZER(DefaultAddressFamilyInit);
      43             : 
      44       70737 : static string IdentifierParent(const string &identifier) {
      45       70737 :     string parent;
      46             :     size_t last;
      47       70737 :     last = identifier.rfind(':');
      48       70737 :     if (last == 0 || last == string::npos) {
      49           0 :         return parent;
      50             :     }
      51       70737 :     parent = identifier.substr(0, last);
      52       70737 :     return parent;
      53           0 : }
      54             : 
      55       69810 : static uint32_t IpAddressToBgpIdentifier(const IpAddress &address) {
      56       69810 :     return htonl(address.to_v4().to_ulong());
      57             : }
      58             : 
      59       13392 : static string BgpIdentifierToString(uint32_t identifier) {
      60       13392 :     Ip4Address addr(ntohl(identifier));
      61       26784 :     return addr.to_string();
      62             : }
      63             : 
      64        4312 : BgpIfmapPeeringConfig::BgpIfmapPeeringConfig(BgpIfmapInstanceConfig *instance)
      65        4312 :     : instance_(instance) {
      66        4312 : }
      67             : 
      68        4312 : BgpIfmapPeeringConfig::~BgpIfmapPeeringConfig() {
      69        4312 :     STLDeleteElements(&neighbors_);
      70        4312 : }
      71             : 
      72        4312 : void BgpIfmapPeeringConfig::SetNodeProxy(IFMapNodeProxy *proxy) {
      73        4312 :     if (proxy != NULL) {
      74        4312 :         node_proxy_.Swap(proxy);
      75        4312 :         name_ = node_proxy_.node()->name();
      76             :     }
      77        4312 : }
      78             : 
      79         165 : BgpIfmapRoutingPolicyLinkConfig::BgpIfmapRoutingPolicyLinkConfig(
      80         165 :     BgpIfmapInstanceConfig *rti, BgpIfmapRoutingPolicyConfig *rtp) :
      81         165 :      instance_(rti), policy_(rtp) {
      82         165 : }
      83             : 
      84         165 : BgpIfmapRoutingPolicyLinkConfig::~BgpIfmapRoutingPolicyLinkConfig() {
      85         165 : }
      86             : 
      87         165 : void BgpIfmapRoutingPolicyLinkConfig::SetNodeProxy(IFMapNodeProxy *proxy) {
      88         165 :     if (proxy != NULL) {
      89         165 :         node_proxy_.Swap(proxy);
      90         165 :         name_ = node_proxy_.node()->name();
      91             :     }
      92         165 : }
      93             : 
      94         165 : bool BgpIfmapRoutingPolicyLinkConfig::GetInstancePolicyPair(
      95             :     DBGraph *graph, IFMapNode *node, pair<IFMapNode *, IFMapNode *> *pair) {
      96         165 :     IFMapNode *routing_instance = NULL;
      97         165 :     IFMapNode *routing_policy = NULL;
      98             : 
      99         165 :     for (DBGraphVertex::adjacency_iterator iter = node->begin(graph);
     100         495 :          iter != node->end(graph); ++iter) {
     101         330 :         IFMapNode *adj = static_cast<IFMapNode *>(iter.operator->());
     102         330 :         if (strcmp(adj->table()->Typename(), "routing-instance") == 0)
     103         165 :             routing_instance = adj;
     104         330 :         if (strcmp(adj->table()->Typename(), "routing-policy") == 0)
     105         165 :             routing_policy = adj;
     106             :     }
     107         165 :     if (routing_policy == NULL || routing_instance == NULL) {
     108           0 :         return false;
     109             :     }
     110             : 
     111         165 :     pair->first = routing_instance;
     112         165 :     pair->second = routing_policy;
     113         165 :     return true;
     114             : }
     115             : 
     116         190 : void BgpIfmapRoutingPolicyLinkConfig::Update(BgpIfmapConfigManager *manager,
     117             :     const autogen::RoutingPolicyRoutingInstance *ri_rp) {
     118         190 :     ri_rp_link_.reset(ri_rp);
     119         190 : }
     120             : 
     121           0 : void BgpIfmapRoutingPolicyLinkConfig::Delete(BgpIfmapConfigManager *manager) {
     122           0 :     ri_rp_link_.reset();
     123           0 : }
     124             : 
     125       59308 : static AuthenticationData::KeyType KeyChainType(const string &value) {
     126             :     // Case-insensitive comparison
     127       59308 :     if (boost::iequals(value, "md5")) {
     128         761 :         return AuthenticationData::MD5;
     129             :     }
     130       58547 :     return AuthenticationData::NIL;
     131             : }
     132             : 
     133       59308 : static void BuildKeyChain(BgpNeighborConfig *neighbor,
     134             :     const autogen::AuthenticationData &values) {
     135       59308 :     AuthenticationData keydata;
     136       59308 :     keydata.set_key_type(KeyChainType(values.key_type));
     137             : 
     138       59308 :     AuthenticationKey key;
     139       59308 :     for (vector<autogen::AuthenticationKeyItem>::const_iterator iter =
     140      119273 :             values.key_items.begin(); iter != values.key_items.end(); ++iter) {
     141         657 :         key.id = iter->key_id;
     142         657 :         key.value = iter->key;
     143         657 :         key.start_time = 0;
     144         657 :         keydata.AddKeyToKeyChain(key);
     145             :     }
     146       59308 :     neighbor->set_keydata(keydata);
     147       59308 : }
     148             : 
     149             : //
     150             : // Check if the family is allowed to be configured for BgpNeighborConfig.
     151             : // Only families inet and inet6 are allowed on non-master instances.
     152             : //
     153        9461 : static bool AddressFamilyIsValid(BgpNeighborConfig *neighbor,
     154             :     const string &family) {
     155        9461 :     if (neighbor->instance_name() == BgpConfigManager::kMasterInstance)
     156        8263 :         return true;
     157        1198 :     return (family == "inet" || family == "inet6");
     158             : }
     159             : 
     160             : //
     161             : // Build list of BgpFamilyAttributesConfig elements from the list of address
     162             : // families. This is provided for backward compatibility with configurations
     163             : // that represent each family with a simple string.
     164             : //
     165        3583 : static void BuildFamilyAttributesList(BgpNeighborConfig *neighbor,
     166             :     const BgpNeighborConfig::AddressFamilyList &family_list,
     167             :     const vector<string> &remote_family_list) {
     168        3583 :     BgpNeighborConfig::FamilyAttributesList family_attributes_list;
     169       17561 :     BOOST_FOREACH(const string &family, family_list) {
     170             :         // Skip families that are not valid/supported for the neighbor.
     171        6989 :         if (!AddressFamilyIsValid(neighbor, family))
     172          26 :             continue;
     173             : 
     174             :         // Skip families that are not configured on remote bgp-router.
     175        6971 :         if (!remote_family_list.empty()) {
     176        4971 :             vector<string>::const_iterator it = find(
     177             :                 remote_family_list.begin(), remote_family_list.end(), family);
     178        4971 :             if (it == remote_family_list.end())
     179           8 :                 continue;
     180             :         }
     181             : 
     182        6963 :         BgpFamilyAttributesConfig family_attributes(family);
     183        6963 :         family_attributes_list.push_back(family_attributes);
     184        6963 :     }
     185             : 
     186        3583 :     neighbor->set_family_attributes_list(family_attributes_list);
     187        3583 : }
     188             : 
     189             : //
     190             : // Build list of BgpFamilyAttributesConfig elements from BgpFamilyAttributes
     191             : // list in BgpSessionAttributes.
     192             : //
     193             : // Implement backward compatibility by also adding BgpFamilyAttributesConfig
     194             : // elements for families that are not in BgpFamilyAttributes list but are in
     195             : // the address_families list.
     196             : //
     197       29180 : static void BuildFamilyAttributesList(BgpNeighborConfig *neighbor,
     198             :     const autogen::BgpSessionAttributes *attributes) {
     199       29180 :     set<string> family_set;
     200       29180 :     BgpNeighborConfig::FamilyAttributesList family_attributes_list;
     201       34124 :     BOOST_FOREACH(const autogen::BgpFamilyAttributes &family_config,
     202             :         attributes->family_attributes) {
     203        2472 :         if (!AddressFamilyIsValid(neighbor, family_config.address_family))
     204         166 :             continue;
     205             :         BgpFamilyAttributesConfig family_attributes(
     206        2306 :             family_config.address_family);
     207        2306 :         family_attributes.loop_count = family_config.loop_count;
     208        2306 :         family_attributes.prefix_limit = family_config.prefix_limit.maximum;
     209        2306 :         family_attributes.idle_timeout =
     210        2306 :             family_config.prefix_limit.idle_timeout;
     211             :         family_attributes.default_tunnel_encap_list =
     212        2306 :             family_config.default_tunnel_encap;
     213        2306 :         family_attributes_list.push_back(family_attributes);
     214        2306 :         family_set.insert(family_config.address_family);
     215        2306 :     }
     216             : 
     217      100558 :     BOOST_FOREACH(const string &family, attributes->address_families.family) {
     218       35689 :         if (family_set.find(family) != family_set.end())
     219           0 :             continue;
     220       35689 :         BgpFamilyAttributesConfig family_attributes(family);
     221       35689 :         family_attributes_list.push_back(family_attributes);
     222       35689 :     }
     223             : 
     224       29180 :     neighbor->set_family_attributes_list(family_attributes_list);
     225       29180 : }
     226             : 
     227             : //
     228             : // Set the autogen::BgpSessionAttributes for this BgpNeighborConfig.
     229             : //
     230             : // The autogen::BgpSession will have up to 3 session attributes - one that
     231             : // applies to the local router, one that applies the remote router and one
     232             : // that applies to both.
     233             : //
     234       30696 : static void NeighborSetSessionAttributes(
     235             :     BgpNeighborConfig *neighbor, const string &localname,
     236             :     const autogen::BgpSession *session) {
     237             :     typedef vector<autogen::BgpSessionAttributes> AttributeVec;
     238       30696 :     const autogen::BgpSessionAttributes *common = NULL;
     239       30696 :     const autogen::BgpSessionAttributes *local = NULL;
     240       30696 :     for (AttributeVec::const_iterator iter = session->attributes.begin();
     241       88567 :          iter != session->attributes.end(); ++iter) {
     242       57871 :         const autogen::BgpSessionAttributes *attr = iter.operator->();
     243       57871 :         if (attr->bgp_router.empty()) {
     244         197 :             common = attr;
     245      114352 :         } else if (neighbor->router_type() != "bgpaas-client" &&
     246       56678 :             attr->bgp_router == localname) {
     247       28485 :             local = attr;
     248       30185 :         } else if (neighbor->router_type() == "bgpaas-client" &&
     249         996 :             attr->bgp_router == "bgpaas-server") {
     250         498 :             local = attr;
     251             :         }
     252             :     }
     253             : 
     254             :     // TODO(nsheth): local should override rather than replace common.
     255       30696 :     const autogen::BgpSessionAttributes *attributes = NULL;
     256       30696 :     if (common != NULL) {
     257         197 :         attributes = common;
     258       30499 :     } else if (local != NULL) {
     259       28983 :         attributes = local;
     260             :     }
     261       30696 :     if (attributes != NULL) {
     262       29180 :         neighbor->set_passive(attributes->passive);
     263       29180 :         neighbor->set_as_override(attributes->as_override);
     264       29180 :         neighbor->set_private_as_action(attributes->private_as_action);
     265       29180 :         neighbor->set_loop_count(attributes->loop_count);
     266       29180 :         if (attributes->admin_down) {
     267         108 :             neighbor->set_admin_down(true);
     268             :         }
     269       29180 :         if (attributes->local_autonomous_system) {
     270         184 :             neighbor->set_local_as(attributes->local_autonomous_system);
     271             :         }
     272       29180 :         if (attributes->hold_time) {
     273         312 :             neighbor->set_hold_time(attributes->hold_time);
     274             :         }
     275       29180 :         BuildFamilyAttributesList(neighbor, attributes);
     276       29180 :         BuildKeyChain(neighbor, attributes->auth_data);
     277       29180 :         const autogen::RouteOriginOverride &origin_override =
     278             :                 attributes->route_origin_override;
     279       29180 :         neighbor->SetOriginOverride(origin_override.origin_override,
     280       29180 :                                     origin_override.origin);
     281             :     }
     282       30696 : }
     283             : 
     284       31077 : static BgpNeighborConfig *MakeBgpNeighborConfig(
     285             :     const BgpIfmapInstanceConfig *instance,
     286             :     const BgpIfmapInstanceConfig *master_instance,
     287             :     const string &local_name,
     288             :     const string &remote_name,
     289             :     const autogen::BgpRouter *local_router,
     290             :     const autogen::BgpRouter *remote_router,
     291             :     const autogen::BgpSession *session) {
     292       31077 :     BgpNeighborConfig *neighbor = new BgpNeighborConfig();
     293             : 
     294       31077 :     neighbor->set_instance_name(instance->name());
     295             : 
     296             :     // If the autogen::BgpSession has a uuid, we append it to the remote
     297             :     // bgp-router's name to make the BgpNeighborConfig's name unique.
     298       31077 :     if (session && !session->uuid.empty()) {
     299       30692 :         neighbor->set_uuid(session->uuid);
     300       30692 :         neighbor->set_name(remote_name + ":" + session->uuid);
     301             :     } else {
     302         385 :         neighbor->set_name(remote_name);
     303             :     }
     304             : 
     305             :     // Store a copy of the remote bgp-router's autogen::BgpRouterParams and
     306             :     // derive the autogen::BgpSessionAttributes for the session.
     307       31077 :     const autogen::BgpRouterParams &params = remote_router->parameters();
     308       31077 :     neighbor->set_router_type(params.router_type);
     309       31077 :     if (params.admin_down) {
     310          78 :         neighbor->set_admin_down(true);
     311             :     }
     312       31077 :     if (params.local_autonomous_system) {
     313        4259 :         neighbor->set_peer_as(params.local_autonomous_system);
     314             :     } else {
     315       26818 :         neighbor->set_peer_as(params.autonomous_system);
     316             :     }
     317       31077 :     boost::system::error_code err;
     318       31077 :     neighbor->set_peer_address(
     319       31077 :         IpAddress::from_string(params.address, err));
     320       31077 :     if (err) {
     321          12 :         BGP_LOG_WARNING_STR(BgpConfig, BGP_LOG_FLAG_ALL,
     322             :                             "Invalid peer address " << params.address <<
     323             :                             " for neighbor " << neighbor->name());
     324             :     }
     325             : 
     326       31077 :     Ip4Address identifier = Ip4Address::from_string(params.identifier, err);
     327       31077 :     if (err) {
     328           0 :         BGP_LOG_WARNING_STR(BgpConfig, BGP_LOG_FLAG_ALL,
     329             :                             "Invalid peer identifier " << params.identifier <<
     330             :                             " for neighbor " << neighbor->name());
     331             :     }
     332       31077 :     neighbor->set_peer_identifier(IpAddressToBgpIdentifier(identifier));
     333             : 
     334       31077 :     if (params.router_type == "bgpaas-client") {
     335             :         IpAddress inet_gw_address =
     336         510 :             Ip4Address::from_string(params.gateway_address, err);
     337         510 :         if (!params.gateway_address.empty() && err) {
     338           0 :             BGP_LOG_WARNING_STR(BgpConfig, BGP_LOG_FLAG_ALL,
     339             :                                 "Invalid gateway address " <<
     340             :                                 params.gateway_address <<
     341             :                                 " for neighbor " << neighbor->name());
     342             :         } else {
     343         510 :             neighbor->set_gateway_address(Address::INET, inet_gw_address);
     344             :         }
     345             : 
     346             :         IpAddress inet6_gw_address =
     347         510 :             Ip6Address::from_string(params.ipv6_gateway_address, err);
     348         510 :         if (!params.ipv6_gateway_address.empty() && err) {
     349           0 :             BGP_LOG_WARNING_STR(BgpConfig, BGP_LOG_FLAG_ALL,
     350             :                 "Invalid ipv6 gateway address " <<
     351             :                 params.ipv6_gateway_address <<
     352             :                 " for neighbor " << neighbor->name());
     353             :         } else {
     354         510 :             neighbor->set_gateway_address(Address::INET6, inet6_gw_address);
     355             :         }
     356             :     }
     357             : 
     358       31077 :     neighbor->set_port(params.port);
     359       31077 :     neighbor->set_source_port(params.source_port);
     360       31077 :     neighbor->set_hold_time(params.hold_time);
     361             : 
     362       31077 :     if (session != NULL) {
     363       30696 :         NeighborSetSessionAttributes(neighbor, local_name, session);
     364             :     }
     365             : 
     366             :     // Get the local identifier and local as from the master protocol config.
     367             :     const BgpIfmapProtocolConfig *master_protocol =
     368       31077 :         master_instance->protocol_config();
     369       31077 :     if (master_protocol && master_protocol->bgp_router()) {
     370             :         const autogen::BgpRouterParams &master_params =
     371       31077 :             master_protocol->router_params();
     372       31077 :         if (master_params.admin_down) {
     373          78 :             neighbor->set_admin_down(true);
     374             :         }
     375             :         Ip4Address localid =
     376       31077 :             Ip4Address::from_string(master_params.identifier, err);
     377       31077 :         if (!err) {
     378       31064 :             neighbor->set_local_identifier(IpAddressToBgpIdentifier(localid));
     379             :         }
     380       31077 :         if (!neighbor->local_as()) {
     381       30893 :             if (master_params.local_autonomous_system) {
     382        4267 :                 neighbor->set_local_as(master_params.local_autonomous_system);
     383             :             } else {
     384       26626 :                 neighbor->set_local_as(master_params.autonomous_system);
     385             :             }
     386             :         }
     387       31077 :         if (instance != master_instance) {
     388         516 :             neighbor->set_passive(true);
     389             :         }
     390             :     }
     391             : 
     392             :     // Get other parameters from the instance protocol config.
     393             :     // Note that there's no instance protocol config for non-master instances.
     394       31077 :     const BgpIfmapProtocolConfig *protocol = instance->protocol_config();
     395       31077 :     if (protocol && protocol->bgp_router()) {
     396             :         const autogen::BgpRouterParams &protocol_params =
     397       30561 :             protocol->router_params();
     398       30561 :         if (neighbor->family_attributes_list().empty()) {
     399        2574 :             BuildFamilyAttributesList(neighbor,
     400        2574 :                 protocol_params.address_families.family,
     401        2574 :                 params.address_families.family);
     402             :         }
     403       30561 :         if (neighbor->auth_data().Empty()) {
     404             :             const autogen::BgpRouterParams &local_params =
     405       30128 :                 local_router->parameters();
     406       30128 :             BuildKeyChain(neighbor, local_params.auth_data);
     407             :         }
     408             :     }
     409             : 
     410       31077 :     if (neighbor->family_attributes_list().empty()) {
     411        1009 :         BuildFamilyAttributesList(neighbor, default_addr_family_list,
     412        1009 :             params.address_families.family);
     413             :     }
     414             : 
     415       31077 :     return neighbor;
     416             : }
     417             : 
     418             : //
     419             : // Build map of BgpNeighborConfigs based on the data in autogen::BgpPeering.
     420             : //
     421       13691 : void BgpIfmapPeeringConfig::BuildNeighbors(BgpIfmapConfigManager *manager,
     422             :     const autogen::BgpRouter *local_rt_config,
     423             :     const string &peername, const autogen::BgpRouter *remote_rt_config,
     424             :     const autogen::BgpPeering *peering, NeighborMap *map) {
     425             :     const BgpIfmapInstanceConfig *master_instance =
     426       13691 :         manager->config()->FindInstance(BgpConfigManager::kMasterInstance);
     427             : 
     428             :     // If there are one or more autogen::BgpSessions for the peering, use
     429             :     // those to create the BgpNeighborConfigs.
     430       13691 :     const autogen::BgpPeeringAttributes &attr = peering->data();
     431       13691 :     for (autogen::BgpPeeringAttributes::const_iterator iter = attr.begin();
     432       44387 :          iter != attr.end(); ++iter) {
     433       30696 :         BgpNeighborConfig *neighbor = MakeBgpNeighborConfig(
     434       30696 :             instance_, master_instance, manager->localname(), peername,
     435       30696 :             local_rt_config, remote_rt_config, iter.operator->());
     436       30696 :         map->insert(make_pair(neighbor->name(), neighbor));
     437             :     }
     438             : 
     439             :     // When no sessions are present, create a single BgpNeighborConfig with
     440             :     // no per-session configuration.
     441       13691 :     if (map->empty()) {
     442        1143 :         BgpNeighborConfig *neighbor = MakeBgpNeighborConfig(
     443         381 :             instance_, master_instance, manager->localname(), peername,
     444         381 :             local_rt_config, remote_rt_config, NULL);
     445         381 :         map->insert(make_pair(neighbor->name(), neighbor));
     446             :     }
     447       13691 : }
     448             : 
     449             : //
     450             : // Update BgpIfmapPeeringConfig based on updated autogen::BgpPeering.
     451             : //
     452             : // This mainly involves building future BgpNeighborConfigs and doing a diff of
     453             : // the current and future BgpNeighborConfigs.  Note that BgpIfmapInstanceConfig
     454             : // also has references to BgpNeighborConfigs, so it also needs to be updated as
     455             : // part of the process.
     456             : //
     457       15731 : void BgpIfmapPeeringConfig::Update(BgpIfmapConfigManager *manager,
     458             :     const autogen::BgpPeering *peering) {
     459       15731 :     IFMapNode *node = node_proxy_.node();
     460       15731 :     assert(node != NULL);
     461       15731 :     bgp_peering_.reset(peering);
     462             : 
     463             :     // Build the future NeighborMap.  The future map should be empty if the
     464             :     // bgp-peering is deleted or if the parameters for the remote bgp-router
     465             :     // are not available.
     466       15731 :     NeighborMap future;
     467       15731 :     pair<IFMapNode *, IFMapNode *> routers;
     468       29430 :     if (!node->IsDeleted() &&
     469       13699 :         GetRouterPair(manager->graph(), manager->localname(), node, &routers)) {
     470             :         const autogen::BgpRouter *local_rt_config =
     471             :                 static_cast<const autogen::BgpRouter *>(
     472       13691 :                     routers.first->GetObject());
     473             :         const autogen::BgpRouter *remote_rt_config =
     474             :                 static_cast<const autogen::BgpRouter *>(
     475       13691 :                     routers.second->GetObject());
     476       27382 :         if (local_rt_config &&
     477       13691 :             local_rt_config->IsPropertySet(autogen::BgpRouter::PARAMETERS) &&
     478       27382 :             remote_rt_config &&
     479       13691 :             remote_rt_config->IsPropertySet(autogen::BgpRouter::PARAMETERS)) {
     480       13691 :             BuildNeighbors(manager, local_rt_config, routers.second->name(),
     481             :                            remote_rt_config, peering, &future);
     482             :         }
     483             :     }
     484             : 
     485             :     // Swap out the NeighborMap in preparation for doing a diff.
     486       15731 :     NeighborMap current;
     487       15731 :     current.swap(neighbors_);
     488             : 
     489             :     // Do a diff on the current and future BgpNeighborConfigs, making sure
     490             :     // that the BgpIfmapInstanceConfig is updated accordingly.  We add any new
     491             :     // BgpNeighborConfigs to our NeighborMap.
     492       15731 :     NeighborMap::iterator it1 = current.begin();
     493       15731 :     NeighborMap::iterator it2 = future.begin();
     494       42013 :     while (it1 != current.end() && it2 != future.end()) {
     495       26282 :         if (it1->first < it2->first) {
     496        2311 :             BgpNeighborConfig *prev = it1->second;
     497        2311 :             instance_->DeleteNeighbor(manager, prev);
     498        2311 :             ++it1;
     499       23971 :         } else if (it1->first > it2->first) {
     500        2311 :             BgpNeighborConfig *neighbor = it2->second;
     501        2311 :             instance_->AddNeighbor(manager, neighbor);
     502        2311 :             neighbors_.insert(*it2);
     503        2311 :             it2->second = NULL;
     504        2311 :             ++it2;
     505             :         } else {
     506       21660 :             BgpNeighborConfig *neighbor = it1->second;
     507       21660 :             BgpNeighborConfig *update = it2->second;
     508       21660 :             if (*neighbor != *update) {
     509         764 :                 instance_->ChangeNeighbor(manager, update);
     510         764 :                 neighbors_.insert(*it2);
     511         764 :                 it2->second = NULL;
     512             :             } else {
     513       20896 :                 neighbors_.insert(*it1);
     514       20896 :                 it1->second = NULL;
     515             :             }
     516       21660 :             ++it1;
     517       21660 :             ++it2;
     518             :         }
     519             :     }
     520       20050 :     for (; it1 != current.end(); ++it1) {
     521        4319 :         BgpNeighborConfig *prev = it1->second;
     522        4319 :         instance_->DeleteNeighbor(manager, prev);
     523             :     }
     524       22837 :     for (; it2 != future.end(); ++it2) {
     525        7106 :         BgpNeighborConfig *neighbor = it2->second;
     526        7106 :         instance_->AddNeighbor(manager, neighbor);
     527        7106 :         neighbors_.insert(*it2);
     528        7106 :         it2->second = NULL;
     529             :     }
     530             : 
     531             :     // Get rid of the current and future NeighborMaps and destroy any mapped
     532             :     // BgpNeighborConfigs. Note that we have carefully reset mapped values to
     533             :     // NULL above when we don't want a BgpNeighborConfig to get destroyed.
     534       15731 :     STLDeleteElements(&current);
     535       15731 :     STLDeleteElements(&future);
     536       15731 : }
     537             : 
     538             : //
     539             : // Delete all state for the given BgpPeeringConfig.
     540             : //
     541             : // This mainly involves getting rid of BgpNeighborConfigs in the NeighborMap.
     542             : //
     543        2121 : void BgpIfmapPeeringConfig::Delete(BgpIfmapConfigManager *manager) {
     544        2121 :     NeighborMap current;
     545        2121 :     current.swap(neighbors_);
     546        2121 :     for (NeighborMap::iterator iter = current.begin();
     547        2210 :          iter != current.end(); ++iter) {
     548          89 :         instance_->DeleteNeighbor(manager, iter->second);
     549             :     }
     550        2121 :     STLDeleteElements(&current);
     551        2121 :     bgp_peering_.reset();
     552        2121 : }
     553             : 
     554             : //
     555             : // Find the IFMapNodes for a bgp-peering.
     556             : //
     557             : // The "node" is the IFMapNode for the bgp-peering link.  The bgp-peering is
     558             : // interesting only if one of the bgp-routers is the local node.
     559             : //
     560             : // Return true if both bgp-routers for the bgp-peering exist and one of them
     561             : // is the local one. Also fill in the local and remote IFMapNode pointers if
     562             : // we return true.
     563             : //
     564       19877 : bool BgpIfmapPeeringConfig::GetRouterPair(DBGraph *db_graph,
     565             :     const string  &localname, IFMapNode *node,
     566             :     pair<IFMapNode *, IFMapNode *> *pair) {
     567       19877 :     IFMapNode *local = NULL;
     568       19877 :     IFMapNode *remote = NULL;
     569       19877 :     string local_router_type;
     570       19877 :     string remote_router_type;
     571       19877 :     string local_instance;
     572       19877 :     string remote_instance;
     573             : 
     574       19877 :     for (DBGraphVertex::adjacency_iterator iter = node->begin(db_graph);
     575       59631 :          iter != node->end(db_graph); ++iter) {
     576       39754 :         IFMapNode *adj = static_cast<IFMapNode *>(iter.operator->());
     577       39754 :         if (strcmp(adj->table()->Typename(), "bgp-router") != 0)
     578          23 :             continue;
     579             :         autogen::BgpRouter *router =
     580       39754 :             static_cast<autogen::BgpRouter *>(adj->GetObject());
     581       39754 :         if (!router)
     582          23 :             continue;
     583       39731 :         const autogen::BgpRouterParams &params = router->parameters();
     584       39731 :         string instance_name(IdentifierParent(adj->name()));
     585       39731 :         string name = adj->name().substr(instance_name.size() + 1);
     586       39731 :         if (name == localname && params.router_type != "bgpaas-client") {
     587       17387 :             local = adj;
     588       17387 :             local_router_type = params.router_type;
     589       17387 :             local_instance = instance_name;
     590       23616 :         } else if (instance_name != BgpConfigManager::kMasterInstance &&
     591        1272 :             params.router_type == "bgpaas-server") {
     592         632 :             local = adj;
     593         632 :             local_router_type = params.router_type;
     594         632 :             local_instance = instance_name;
     595             :         } else {
     596       21712 :             remote = adj;
     597       21712 :             remote_router_type = params.router_type;
     598       21712 :             remote_instance = instance_name;
     599             :         }
     600       39731 :     }
     601             : 
     602       18019 :     if ((local == NULL || remote == NULL) || (local_router_type ==
     603       18637 :          "bgpaas-server" && remote_router_type != "bgpaas-client") ||
     604       35379 :         (local_router_type != "bgpaas-server" && remote_router_type ==
     605       37896 :          "bgpaas-client") || (local_instance != remote_instance)) {
     606        1874 :         BGP_LOG_STR(BgpConfig, SandeshLevel::SYS_DEBUG, BGP_LOG_FLAG_SYSLOG,
     607             :                  "localname: " << localname <<
     608             :                  ((local == NULL) ? " Local node not present" :
     609             :                                   " Local node present") <<
     610             :                  ((remote == NULL) ? " Remote node not present" :
     611             :                                   " Remote node present") <<
     612             :                  " local_router_type: " << local_router_type <<
     613             :                  " remote_router_type: " << remote_router_type <<
     614             :                  " local instance: " << local_instance <<
     615             :                  " remote instance: " << remote_instance);
     616        1874 :         return false;
     617             :     }
     618             : 
     619       18003 :     pair->first = local;
     620       18003 :     pair->second = remote;
     621       18003 :     return true;
     622       19877 : }
     623             : 
     624             : //
     625             : // Constructor for BgpIfmapProtocolConfig.
     626             : //
     627        8595 : BgpIfmapProtocolConfig::BgpIfmapProtocolConfig(BgpIfmapInstanceConfig *instance)
     628        8595 :     : instance_(instance),
     629        8595 :       data_(instance->name()) {
     630        8595 : }
     631             : 
     632             : //
     633             : // Destructor for BgpIfmapProtocolConfig.
     634             : //
     635        8595 : BgpIfmapProtocolConfig::~BgpIfmapProtocolConfig() {
     636        8595 : }
     637             : 
     638      161388 : const autogen::BgpRouterParams &BgpIfmapProtocolConfig::router_params() const {
     639      161388 :     return bgp_router_->parameters();
     640             : }
     641             : 
     642             : //
     643             : // Set the IFMapNodeProxy for the BgpIfmapProtocolConfig.
     644             : //
     645        5899 : void BgpIfmapProtocolConfig::SetNodeProxy(IFMapNodeProxy *proxy) {
     646        5899 :     if (proxy != NULL) {
     647        5899 :         node_proxy_.Swap(proxy);
     648             :     }
     649        5899 : }
     650             : 
     651             : //
     652             : // Update autogen::BgpRouter object for this BgpIfmapProtocolConfig.
     653             : //
     654       15700 : void BgpIfmapProtocolConfig::Update(BgpIfmapConfigManager *manager,
     655             :     const autogen::BgpRouter *router) {
     656       15700 :     bgp_router_.reset(router);
     657       15700 :     const autogen::BgpRouterParams &params = router->parameters();
     658       15700 :     data_.set_admin_down(params.admin_down);
     659       15700 :     data_.set_cluster_id(params.cluster_id);
     660       15700 :     data_.set_autonomous_system(params.autonomous_system);
     661       15700 :     data_.set_local_autonomous_system(params.local_autonomous_system);
     662       15700 :     data_.set_port(params.port ?: BgpConfigManager::kDefaultPort);
     663       15700 :     boost::system::error_code err;
     664       15700 :     IpAddress identifier = IpAddress::from_string(params.identifier, err);
     665       15700 :     if (!err) {
     666        7669 :         data_.set_identifier(IpAddressToBgpIdentifier(identifier));
     667             :     }
     668       15700 :     data_.set_hold_time(params.hold_time);
     669             : 
     670             :     // reset subcluster name and id,
     671             :     // will be set again if mapping is found in schema
     672       15700 :     data_.reset_subcluster_name();
     673       15700 :     data_.reset_subcluster_id();
     674             :     // get subcluster name this router is associated with
     675       15700 :     IFMapNode *node = node_proxy_.node();
     676       15700 :     if (!node)
     677        8030 :         return;
     678        7670 :     DBGraph *graph = manager->graph();
     679        7670 :     for (DBGraphVertex::adjacency_iterator iter = node->begin(graph);
     680       20488 :          iter != node->end(graph); ++iter) {
     681       12832 :         IFMapNode *adj = static_cast<IFMapNode *>(iter.operator->());
     682       12832 :         if (strcmp(adj->table()->Typename(), "sub-cluster") == 0) {
     683          14 :             data_.set_subcluster_name(adj->name());
     684             :             const autogen::SubCluster *sc =
     685          14 :                 static_cast<autogen::SubCluster *>(adj->GetObject());
     686          14 :             if (sc) {
     687          12 :                 data_.set_subcluster_id(sc->id());
     688             :             }
     689          14 :             break;
     690             :         }
     691             :     }
     692             : }
     693             : 
     694             : //
     695             : // Delete autogen::BgpRouter object for this BgpIfmapProtocolConfig.
     696             : //
     697        1379 : void BgpIfmapProtocolConfig::Delete(BgpIfmapConfigManager *manager) {
     698        1379 :     manager->Notify(&data_, BgpConfigManager::CFG_DELETE);
     699        1379 :     bgp_router_.reset();
     700        1379 : }
     701             : 
     702           0 : const string &BgpIfmapProtocolConfig::InstanceName() const {
     703           0 :     return instance_->name();
     704             : }
     705             : 
     706             : //
     707             : // Constructor for BgpIfmapInstanceConfig.
     708             : //
     709       50598 : BgpIfmapInstanceConfig::BgpIfmapInstanceConfig(const string &name)
     710       50598 :     : name_(name),
     711       50598 :       data_(name),
     712       50598 :       index_(-1),
     713      101196 :       protocol_(NULL) {
     714       50598 : }
     715             : 
     716             : //
     717             : // Destructor for BgpIfmapInstanceConfig.
     718             : //
     719       50598 : BgpIfmapInstanceConfig::~BgpIfmapInstanceConfig() {
     720       50598 : }
     721             : 
     722             : //
     723             : // Set the IFMapNodeProxy for the BgpIfmapInstanceConfig.
     724             : //
     725       48408 : void BgpIfmapInstanceConfig::SetNodeProxy(IFMapNodeProxy *proxy) {
     726       48408 :     if (proxy != NULL) {
     727       48408 :         node_proxy_.Swap(proxy);
     728             :     }
     729       48408 : }
     730             : 
     731             : //
     732             : // Get the BgpIfmapProtocolConfig for this BgpIfmapInstanceConfig, create
     733             : // it if needed.
     734             : //
     735        8595 : BgpIfmapProtocolConfig *BgpIfmapInstanceConfig::LocateProtocol() {
     736        8595 :     if (protocol_.get() == NULL) {
     737        8595 :         protocol_.reset(new BgpIfmapProtocolConfig(this));
     738             :     }
     739        8595 :     return protocol_.get();
     740             : }
     741             : 
     742             : //
     743             : // Delete the BgpIfmapProtocolConfig for this BgpIfmapInstanceConfig.
     744             : //
     745        1379 : void BgpIfmapInstanceConfig::ResetProtocol() {
     746        1379 :     protocol_.reset();
     747        1379 : }
     748             : 
     749             : //
     750             : // Get the route-target for an instance-target. The input IFMapNode is the
     751             : // midnode that represents the instance-target link. We traverse the graph
     752             : // the graph edges till we find the adjacency to the route-target.
     753             : //
     754             : // Return true and fill in the target string if we find the route-target.
     755             : //
     756      551089 : static bool GetInstanceTargetRouteTarget(DBGraph *graph, IFMapNode *node,
     757             :     string *target) {
     758      551089 :     for (DBGraphVertex::adjacency_iterator iter = node->begin(graph);
     759     1102178 :          iter != node->end(graph); ++iter) {
     760     1102178 :         IFMapNode *adj = static_cast<IFMapNode *>(iter.operator->());
     761     1102178 :         if (strcmp(adj->table()->Typename(), "route-target") == 0) {
     762      551089 :             *target = adj->name();
     763      551089 :             return true;
     764             :         }
     765             :     }
     766           0 :     return false;
     767             : }
     768             : 
     769             : //
     770             : // Fill in all the export route targets for a routing-instance.  The input
     771             : // IFMapNode represents the routing-instance.  We traverse the graph edges
     772             : // and look for instance-target adjacencies. If the instance-target is an
     773             : // export and import target, add it to the vector.
     774             : //
     775             : // Note that we purposely skip adding export only targets to the vector.
     776             : // Reasoning is that export only targets are manually configured by users
     777             : // and hence should not be imported based on policy.
     778             : //
     779       28157 : static void GetRoutingInstanceExportTargets(DBGraph *graph, IFMapNode *node,
     780             :     vector<string> *target_list) {
     781       28157 :     for (DBGraphVertex::adjacency_iterator iter = node->begin(graph);
     782      115205 :          iter != node->end(graph); ++iter) {
     783       87048 :         IFMapNode *adj = static_cast<IFMapNode *>(iter.operator->());
     784       87048 :         string target;
     785      115159 :         if ((strcmp(adj->table()->Typename(), "instance-target") == 0) &&
     786       28111 :             (GetInstanceTargetRouteTarget(graph, adj, &target))) {
     787             :             const autogen::InstanceTarget *itarget =
     788       28111 :                     dynamic_cast<autogen::InstanceTarget *>(adj->GetObject());
     789       28111 :             if (!itarget)
     790           0 :                 continue;
     791       28111 :             const autogen::InstanceTargetType &itt = itarget->data();
     792       28111 :             if (itt.import_export.empty())
     793       28107 :                 target_list->push_back(target);
     794             :         }
     795       87048 :     }
     796       28157 : }
     797             : 
     798             : //
     799             : // Fill in all the export route targets of the routing-instance at the other
     800             : // end of a connection.  The src_node is the routing-instance from which we
     801             : // reached the connection node. The name of the source routing-instance is
     802             : // src_instance.
     803             : //
     804             : // If the connection is unidirectional and the destination-instance for the
     805             : // connection is not the routing-instance from which we started, we should
     806             : // not get any targets from this connection.  This is what a unidirectional
     807             : // connection means.
     808             : //
     809       28161 : static void GetConnectionExportTargets(DBGraph *graph, IFMapNode *src_node,
     810             :     const string &src_instance, IFMapNode *node,
     811             :     vector<string> *target_list) {
     812             :     const autogen::Connection *conn =
     813       28161 :         dynamic_cast<autogen::Connection *>(node->GetObject());
     814       28161 :     if (!conn)
     815           0 :         return;
     816       28161 :     const autogen::ConnectionType &conn_type = conn->data();
     817       28169 :     if (!conn_type.destination_instance.empty() &&
     818           8 :          conn_type.destination_instance != src_instance)
     819           4 :         return;
     820       28157 :     for (DBGraphVertex::adjacency_iterator iter = node->begin(graph);
     821       84471 :          iter != node->end(graph); ++iter) {
     822       56314 :         IFMapNode *adj = static_cast<IFMapNode *>(iter.operator->());
     823       56314 :         if (adj == src_node)
     824       28157 :             continue;
     825       28157 :         if (strcmp(adj->table()->Typename(), "routing-instance") != 0)
     826           0 :             continue;
     827       28157 :         GetRoutingInstanceExportTargets(graph, adj, target_list);
     828             :     }
     829             : }
     830             : 
     831             : //
     832             : // Fill in all the routing-policies for a routing-instance.  The input
     833             : // IFMapNode represents the routing-policy-routing-instance.  We traverse to
     834             : // graph edges and look for routing-policy adjacency
     835             : //
     836         530 : static bool GetRoutingInstanceRoutingPolicy(DBGraph *graph, IFMapNode *node,
     837             :     RoutingPolicyAttachInfo *ri_rp_link) {
     838         530 :     string sequence;
     839             :     const autogen::RoutingPolicyRoutingInstance *policy =
     840         530 :         static_cast<autogen::RoutingPolicyRoutingInstance *>(node->GetObject());
     841         530 :     const autogen::RoutingPolicyType &attach_info = policy->data();
     842             : 
     843         530 :     ri_rp_link->sequence_ = attach_info.sequence;
     844             : 
     845         530 :     for (DBGraphVertex::adjacency_iterator iter = node->begin(graph);
     846        1060 :          iter != node->end(graph); ++iter) {
     847        1060 :         IFMapNode *adj = static_cast<IFMapNode *>(iter.operator->());
     848        1060 :         if (strcmp(adj->table()->Typename(), "routing-policy") == 0) {
     849         530 :             ri_rp_link->routing_policy_ = adj->name();
     850         530 :             return true;
     851             :         }
     852             :     }
     853           0 :     return false;
     854         530 : }
     855             : 
     856             : //
     857             : // Fill in all the route-aggregation for a routing-instance.
     858             : //
     859         728 : static bool GetRouteAggregateConfig(DBGraph *graph, IFMapNode *node,
     860             :     BgpInstanceConfig::AggregateRouteList *inet_list,
     861             :     BgpInstanceConfig::AggregateRouteList *inet6_list) {
     862             :     const autogen::RouteAggregate *ra =
     863         728 :         static_cast<autogen::RouteAggregate *>(node->GetObject());
     864         728 :     if (ra == NULL) return false;
     865             : 
     866         727 :     boost::system::error_code ec;
     867             :     IpAddress nexthop =
     868         727 :         IpAddress::from_string(ra->aggregate_route_nexthop(), ec);
     869         727 :     if (ec.failed()) return false;
     870             : 
     871        2467 :     BOOST_FOREACH(const string &route, ra->aggregate_route_entries()) {
     872         870 :         AggregateRouteConfig aggregate;
     873         870 :         aggregate.nexthop = nexthop;
     874             : 
     875         870 :         Ip4Address address;
     876         870 :         ec = Ip4SubnetParse(route, &address, &aggregate.prefix_length);
     877         870 :         if (!ec) {
     878         843 :             if (!nexthop.is_v4()) continue;
     879         837 :             aggregate.aggregate = address;
     880         837 :             inet_list->push_back(aggregate);
     881             :         } else {
     882          30 :             if (!nexthop.is_v6()) continue;
     883          27 :             Ip6Address address;
     884          27 :             ec = Inet6SubnetParse(route, &address, &aggregate.prefix_length);
     885          27 :             if (ec.failed()) continue;
     886          27 :             aggregate.aggregate = address;
     887          27 :             inet6_list->push_back(aggregate);
     888             :         }
     889             :     }
     890             : 
     891         727 :     return true;
     892             : }
     893             : 
     894             : //
     895             : // Get the network id for a virtual-network.  The input IFMapNode represents
     896             : // the virtual-network.
     897             : //
     898       74116 : static int GetVirtualNetworkIndex(DBGraph *graph, IFMapNode *node) {
     899             :     const autogen::VirtualNetwork *vn =
     900       74116 :         static_cast<autogen::VirtualNetwork *>(node->GetObject());
     901       74116 :     if (vn && vn->IsPropertySet(autogen::VirtualNetwork::NETWORK_ID))
     902         112 :         return vn->network_id();
     903       74004 :     if (vn && vn->IsPropertySet(autogen::VirtualNetwork::PROPERTIES))
     904       73929 :         return vn->properties().network_id;
     905          75 :     return 0;
     906             : }
     907             : 
     908             : //
     909             : // Check if a virtual-network allows transit. The input IFMapNode represents
     910             : // the virtual-network.
     911             : //
     912       74116 : static bool GetVirtualNetworkAllowTransit(DBGraph *graph, IFMapNode *node) {
     913             :     const autogen::VirtualNetwork *vn =
     914       74116 :         static_cast<autogen::VirtualNetwork *>(node->GetObject());
     915       74116 :     if (vn && vn->IsPropertySet(autogen::VirtualNetwork::PROPERTIES))
     916       73959 :         return vn->properties().allow_transit;
     917         157 :     return false;
     918             : }
     919             : 
     920             : 
     921             : //
     922             : // Check if a virtual-network has pbb-evpn enabled.
     923             : // The input IFMapNode represents the virtual-network.
     924             : //
     925       74116 : static bool GetVirtualNetworkPbbEvpnEnable(DBGraph *graph, IFMapNode *node) {
     926             :     const autogen::VirtualNetwork *vn =
     927       74116 :         static_cast<autogen::VirtualNetwork *>(node->GetObject());
     928       74116 :     if (vn && vn->IsPropertySet(autogen::VirtualNetwork::PBB_EVPN_ENABLE))
     929       15240 :         return vn->pbb_evpn_enable();
     930       58876 :     return false;
     931             : }
     932             : 
     933             : 
     934             : //
     935             : // Get the vxlan id for a virtual-network.  The input IFMapNode represents
     936             : // the virtual-network.
     937             : //
     938             : // The vxlan_network_identifier is 0 when automatic mode is in use. In that
     939             : // case, the network_id is used as vxlan id.
     940             : //
     941       74116 : static int GetVirtualNetworkVxlanId(DBGraph *graph, IFMapNode *node) {
     942             :     const autogen::VirtualNetwork *vn =
     943       74116 :         static_cast<autogen::VirtualNetwork *>(node->GetObject());
     944       74116 :     if (vn && vn->IsPropertySet(autogen::VirtualNetwork::PROPERTIES)) {
     945       73959 :         if (vn->properties().vxlan_network_identifier) {
     946           0 :             return vn->properties().vxlan_network_identifier;
     947             :         } else {
     948       73959 :             return vn->properties().network_id;
     949             :         }
     950             :     }
     951         157 :     return 0;
     952             : }
     953             : 
     954        4216 : static void SetStaticRouteConfig(BgpInstanceConfig *rti,
     955             :     const autogen::RoutingInstance *config) {
     956        4216 :     BgpInstanceConfig::StaticRouteList inet_list;
     957        4216 :     BgpInstanceConfig::StaticRouteList inet6_list;
     958        4966 :     BOOST_FOREACH(const autogen::StaticRouteType &route,
     959             :                   config->static_route_entries()) {
     960         375 :         boost::system::error_code ec;
     961         375 :         StaticRouteConfig item;
     962         375 :         item.nexthop = IpAddress::from_string(route.next_hop, ec);
     963         375 :         if (ec.failed())
     964           4 :             continue;
     965             : 
     966         371 :         item.route_targets = route.route_target;
     967         371 :         item.communities = route.community;
     968         371 :         if (item.nexthop.is_v4()) {
     969         290 :             Ip4Address address;
     970         290 :             ec = Ip4SubnetParse(route.prefix, &address, &item.prefix_length);
     971         290 :             if (ec.failed())
     972           3 :                 continue;
     973         287 :             item.address = address;
     974             :             std::pair<BgpInstanceConfig::StaticRouteList::iterator, bool> ret =
     975         287 :                 inet_list.insert(item);
     976         287 :             if (!ret.second) {
     977           0 :                 BGP_LOG_WARNING_STR(BgpConfig, BGP_LOG_FLAG_ALL,
     978             :                     "Duplicate static route prefix " << route.prefix <<
     979             :                     " with nexthop " << route.next_hop <<
     980             :                     " for routing instance " << rti->name());
     981             :             }
     982             :         } else {
     983          81 :             Ip6Address address;
     984          81 :             ec = Inet6SubnetParse(route.prefix, &address, &item.prefix_length);
     985          81 :             if (ec.failed())
     986           3 :                 continue;
     987          78 :             item.address = address;
     988             :             std::pair<BgpInstanceConfig::StaticRouteList::iterator, bool> ret =
     989          78 :                 inet6_list.insert(item);
     990          78 :             if (!ret.second) {
     991           0 :                 BGP_LOG_WARNING_STR(BgpConfig, BGP_LOG_FLAG_ALL,
     992             :                     "Duplicate static route prefix " << route.prefix <<
     993             :                     " with nexthop " << route.next_hop <<
     994             :                     " for routing instance " << rti->name());
     995             :             }
     996             :         }
     997         375 :     }
     998        4216 :     rti->swap_static_routes(Address::INET, &inet_list);
     999        4216 :     rti->swap_static_routes(Address::INET6, &inet6_list);
    1000        4216 : }
    1001             : 
    1002        4216 : static void SetServiceChainConfig(BgpInstanceConfig *rti,
    1003             :     const autogen::RoutingInstance *config) {
    1004        4216 :     BgpInstanceConfig::ServiceChainList list;
    1005             :     const autogen::ServiceChainInfo &inet_chain =
    1006        4216 :         config->service_chain_information();
    1007        4216 :     if (config->IsPropertySet(
    1008             :         autogen::RoutingInstance::SERVICE_CHAIN_INFORMATION)) {
    1009        1179 :         ServiceChainConfig item = {
    1010             :             SCAddress::INET,
    1011        1179 :             inet_chain.routing_instance,
    1012        1179 :             inet_chain.prefix,
    1013        1179 :             inet_chain.service_chain_address,
    1014        1179 :             inet_chain.service_instance,
    1015        1179 :             inet_chain.source_routing_instance,
    1016        1179 :             inet_chain.service_chain_id,
    1017        1179 :             inet_chain.sc_head,
    1018        1179 :             inet_chain.retain_as_path,
    1019        1179 :         };
    1020        1179 :         list.push_back(item);
    1021        1179 :     }
    1022             : 
    1023             :     const autogen::ServiceChainInfo &inet6_chain =
    1024        4216 :         config->ipv6_service_chain_information();
    1025        4216 :     if (config->IsPropertySet(
    1026             :         autogen::RoutingInstance::IPV6_SERVICE_CHAIN_INFORMATION)) {
    1027        1048 :         ServiceChainConfig item = {
    1028             :             SCAddress::INET6,
    1029        1048 :             inet6_chain.routing_instance,
    1030        1048 :             inet6_chain.prefix,
    1031        1048 :             inet6_chain.service_chain_address,
    1032        1048 :             inet6_chain.service_instance,
    1033        1048 :             inet6_chain.source_routing_instance,
    1034        1048 :             inet6_chain.service_chain_id,
    1035        1048 :             inet6_chain.sc_head,
    1036        1048 :             inet6_chain.retain_as_path,
    1037        1048 :         };
    1038        1048 :         list.push_back(item);
    1039        1048 :     }
    1040             : 
    1041             :     const autogen::ServiceChainInfo &evpn_chain =
    1042        4216 :         config->evpn_service_chain_information();
    1043        4216 :     if (config->IsPropertySet(
    1044             :         autogen::RoutingInstance::EVPN_SERVICE_CHAIN_INFORMATION)) {
    1045         718 :         ServiceChainConfig item = {
    1046             :             SCAddress::EVPN,
    1047         718 :             evpn_chain.routing_instance,
    1048         718 :             evpn_chain.prefix,
    1049         718 :             evpn_chain.service_chain_address,
    1050         718 :             evpn_chain.service_instance,
    1051         718 :             evpn_chain.source_routing_instance,
    1052         718 :             evpn_chain.service_chain_id,
    1053         718 :             evpn_chain.sc_head,
    1054         718 :             evpn_chain.retain_as_path,
    1055         718 :         };
    1056         718 :         list.push_back(item);
    1057         718 :     }
    1058             : 
    1059             :     const autogen::ServiceChainInfo &evpnv6_chain =
    1060        4216 :         config->evpn_ipv6_service_chain_information();
    1061        4216 :     if (config->IsPropertySet(
    1062             :         autogen::RoutingInstance::EVPN_IPV6_SERVICE_CHAIN_INFORMATION)) {
    1063         720 :         ServiceChainConfig item = {
    1064             :             SCAddress::EVPN6,
    1065         720 :             evpnv6_chain.routing_instance,
    1066         720 :             evpnv6_chain.prefix,
    1067         720 :             evpnv6_chain.service_chain_address,
    1068         720 :             evpnv6_chain.service_instance,
    1069         720 :             evpnv6_chain.source_routing_instance,
    1070         720 :             evpnv6_chain.service_chain_id,
    1071         720 :             evpnv6_chain.sc_head,
    1072         720 :             evpnv6_chain.retain_as_path,
    1073         720 :         };
    1074         720 :         list.push_back(item);
    1075         720 :     }
    1076             : 
    1077        4216 :     rti->swap_service_chain_list(&list);
    1078        4216 : }
    1079             : 
    1080             : // Get name of vxlan RI for bridge RI
    1081             : 
    1082          14 : static string GetConnectedVxlanRiVn(DBGraph *graph, IFMapNode *node) {
    1083             :     const autogen::VirtualNetwork *vn_vxlan =
    1084          14 :         static_cast<autogen::VirtualNetwork *>(node->GetObject());
    1085          14 :     if (!vn_vxlan)
    1086           0 :         return "";
    1087          14 :     for (DBGraphVertex::adjacency_iterator iter_ri = node->begin(graph);
    1088         112 :         iter_ri != node->end(graph); ++iter_ri) {
    1089         112 :         IFMapNode *adj_ri = static_cast<IFMapNode *>(iter_ri.operator->());
    1090         112 :         if (strcmp(adj_ri->table()->Typename(), "routing-instance") == 0)  {
    1091             :             const autogen::RoutingInstance *iri =
    1092          14 :                     dynamic_cast<autogen::RoutingInstance *>(adj_ri->GetObject());
    1093          14 :             if (!iri)
    1094           0 :                 continue;
    1095          28 :             return adj_ri->name();
    1096             :         }
    1097             :     }
    1098           0 :     return "";
    1099             : }
    1100             : 
    1101          14 : static string GetConnectedVxlanRiLr(DBGraph *graph, IFMapNode *node) {
    1102          14 :     std::string ri_name = "";
    1103          14 :     for (DBGraphVertex::adjacency_iterator iter_lr = node->begin(graph);
    1104          84 :         iter_lr != node->end(graph); ++iter_lr) {
    1105          84 :         IFMapNode *adj_lr = static_cast<IFMapNode *>(iter_lr.operator->());
    1106          84 :         if (strcmp(adj_lr->table()->Typename(),
    1107          84 :                    "logical-router-virtual-network") == 0)  {
    1108          14 :             for (DBGraphVertex::adjacency_iterator iter_vn = adj_lr->begin(graph);
    1109          28 :                 iter_vn != adj_lr->end(graph); ++iter_vn) {
    1110          28 :                 IFMapNode *adj_vn = static_cast<IFMapNode *>(iter_vn.operator->());
    1111          28 :                 if (strcmp(adj_vn->table()->Typename(), "virtual-network") == 0)  {
    1112          14 :                     ri_name = GetConnectedVxlanRiVn(graph, adj_vn);
    1113          14 :                     if (ri_name != "") {
    1114          14 :                         return ri_name;
    1115             :                     }
    1116             :                 }
    1117             :             }
    1118             :         }
    1119             :     }
    1120           0 :     return "";
    1121          14 : }
    1122             : 
    1123             : 
    1124       74116 : static string GetConnectedVxlanRi(DBGraph *graph, IFMapNode *node) {
    1125       74116 :     std::string ri_name = "";
    1126             :     const autogen::VirtualNetwork *vn =
    1127       74116 :         static_cast<autogen::VirtualNetwork *>(node->GetObject());
    1128       74116 :     if (!vn) {
    1129          70 :         return "";
    1130             :     }
    1131       74046 :     for (DBGraphVertex::adjacency_iterator iter_vmi = node->begin(graph);
    1132      162166 :          iter_vmi != node->end(graph); ++iter_vmi) {
    1133       88134 :         IFMapNode *adj_vmi = static_cast<IFMapNode *>(iter_vmi.operator->());
    1134       88134 :         if (strcmp(adj_vmi->table()->Typename(),
    1135       88134 :                    "virtual-machine-interface") == 0) {
    1136         130 :             for (DBGraphVertex::adjacency_iterator iter_lr = adj_vmi->begin(graph);
    1137         881 :                 iter_lr != adj_vmi->end(graph); ++iter_lr) {
    1138         765 :                 IFMapNode *adj_lr = static_cast<IFMapNode *>(iter_lr.operator->());
    1139         765 :                 if (strcmp(adj_lr->table()->Typename(), "logical-router") == 0)  {
    1140          14 :                     ri_name = GetConnectedVxlanRiLr(graph, adj_lr);
    1141          14 :                     if (ri_name != "") {
    1142          14 :                         return ri_name;
    1143             :                     }
    1144             :                 }
    1145             :             }
    1146             :         }
    1147             :     }
    1148       74032 :     return "";
    1149       74116 : }
    1150             : 
    1151             : 
    1152         236 : void BgpIfmapConfigManager::ProcessRoutingPolicyLink(
    1153             :     const BgpConfigDelta &delta) {
    1154         236 :     CHECK_CONCURRENCY("bgp::Config");
    1155             : 
    1156             :     BgpIfmapRoutingPolicyLinkConfig *ri_rp_link
    1157         236 :         = config_->FindRoutingPolicyLink(delta.id_name);
    1158         236 :     if (ri_rp_link == NULL) {
    1159         165 :         IFMapNodeProxy *proxy = delta.node.get();
    1160         165 :         if (proxy == NULL) {
    1161           0 :             return;
    1162             :         }
    1163         165 :         IFMapNode *node = proxy->node();
    1164         165 :         if (node == NULL || delta.obj.get() == NULL) {
    1165           0 :             return;
    1166             :         }
    1167             : 
    1168         165 :         pair<IFMapNode *, IFMapNode *> ri_rp_pair;
    1169         165 :         if (!BgpIfmapRoutingPolicyLinkConfig::GetInstancePolicyPair(db_graph_,
    1170             :             node, &ri_rp_pair)) {
    1171           0 :             return;
    1172             :         }
    1173             : 
    1174         165 :         string instance_name = ri_rp_pair.first->name();
    1175         165 :         string policy_name = ri_rp_pair.second->name();
    1176             : 
    1177             :         BgpIfmapInstanceConfig *rti  =
    1178         165 :             config_->FindInstance(instance_name);
    1179             :         BgpIfmapRoutingPolicyConfig *rtp  =
    1180         165 :             config_->FindRoutingPolicy(policy_name);
    1181         165 :         if (!rti || !rtp) {
    1182           0 :             return;
    1183             :         }
    1184             : 
    1185         165 :         ri_rp_link = config_->CreateRoutingPolicyLink(rti, rtp, proxy);
    1186         165 :     } else {
    1187          71 :         const IFMapNode *node = ri_rp_link->node();
    1188          71 :         assert(node != NULL);
    1189          71 :         if (delta.obj.get() == NULL) {
    1190          46 :             BgpIfmapRoutingPolicyConfig *rtp = ri_rp_link->policy();
    1191          46 :             BgpIfmapInstanceConfig *rti = ri_rp_link->instance();
    1192          46 :             config_->DeleteRoutingPolicyLink(ri_rp_link);
    1193          46 :             if (rtp->DeleteIfEmpty(this)) {
    1194          38 :                 config_->DeleteRoutingPolicy(rtp);
    1195             :             }
    1196          46 :             if (rti->DeleteIfEmpty(this)) {
    1197           1 :                 BGP_CONFIG_LOG_INSTANCE(Delete, server(), rti,
    1198             :                     SandeshLevel::SYS_DEBUG, BGP_LOG_FLAG_ALL);
    1199           1 :                 config_->DeleteInstance(rti);
    1200             :             }
    1201          46 :             return;
    1202             :         }
    1203             :     }
    1204             : 
    1205             :     autogen::RoutingPolicyRoutingInstance *ri_rp_link_cfg =
    1206         190 :         static_cast<autogen::RoutingPolicyRoutingInstance *>(delta.obj.get());
    1207             : 
    1208         190 :     ri_rp_link->Update(this, ri_rp_link_cfg);
    1209             : }
    1210             : 
    1211         151 : static bool CompareRoutingPolicyOrder(const RoutingPolicyAttachInfo &lhs,
    1212             :                                       const RoutingPolicyAttachInfo &rhs) {
    1213         151 :     return (lhs.sequence_ < rhs.sequence_);
    1214             : }
    1215             : 
    1216       18014 : void BgpIfmapInstanceConfig::ProcessIdentifierUpdate(uint32_t new_id,
    1217             :                                                      uint32_t old_id) {
    1218       18014 :     BgpInstanceConfig::RouteTargetList import_list = data_.import_list();
    1219       18014 :     if (old_id > 0) {
    1220         183 :         string old_vit = "target:" + GetVitFromId(ntohl(old_id));
    1221         183 :         import_list.erase(old_vit);
    1222         183 :     }
    1223       18014 :     if (new_id > 0) {
    1224       18014 :         string new_vit = "target:" + GetVitFromId(ntohl(new_id));
    1225       18014 :         import_list.insert(new_vit);
    1226       18014 :     }
    1227       18014 :     data_.set_import_list(import_list);
    1228       18014 : }
    1229             : 
    1230       12306 : void BgpIfmapInstanceConfig::ProcessASUpdate(uint32_t new_as, uint32_t old_as) {
    1231       12306 :     BgpInstanceConfig::RouteTargetList import_list = data_.import_list();
    1232       12306 :     if (old_as > 0) {
    1233       11557 :         string old_es_rtarget = "target:" + GetESRouteTarget(old_as);
    1234       11557 :         import_list.erase(old_es_rtarget);
    1235       11557 :     }
    1236       12306 :     if (new_as > 0) {
    1237       12305 :         string new_es_rtarget = "target:" + GetESRouteTarget(new_as);
    1238       12305 :         import_list.insert(new_es_rtarget);
    1239       12305 :     }
    1240       12306 :     data_.set_import_list(import_list);
    1241       12306 : }
    1242             : 
    1243       97079 : string BgpIfmapInstanceConfig::GetVitFromId(uint32_t identifier) const {
    1244       97079 :     if (identifier == 0)
    1245           0 :         return "";
    1246      194158 :     return Ip4Address(identifier).to_string() + ":" + integerToString(index());
    1247             : }
    1248             : 
    1249      147791 : string BgpIfmapInstanceConfig::GetESRouteTarget(uint32_t as) const {
    1250      147791 :     if (as == 0)
    1251           0 :         return "";
    1252      147791 :     if (as > 0xffFF)
    1253          80 :         return integerToString(as) + ":" +
    1254         120 :             integerToString(EVPN_ES_IMPORT_ROUTE_TARGET_AS4);
    1255      295502 :     return integerToString(as) + ":" +
    1256      443253 :         integerToString(EVPN_ES_IMPORT_ROUTE_TARGET_AS2);
    1257             : }
    1258             : 
    1259             : // Populate vrf import route-target (used for MVPN) and ES route target in
    1260             : // import list.
    1261      124494 : void BgpIfmapInstanceConfig::InsertVitAndESRTargetInImportList(
    1262             :                          BgpIfmapConfigManager *mgr,
    1263             :                          BgpInstanceConfig::RouteTargetList& import_list) {
    1264             :     const BgpIfmapInstanceConfig *master_instance =
    1265      124494 :         mgr->config()->FindInstance(BgpConfigManager::kMasterInstance);
    1266      124494 :     uint32_t bgp_identifier = 0;
    1267      124494 :     uint32_t as = 0;
    1268      124494 :     if (master_instance) {
    1269             :         const BgpIfmapProtocolConfig *master_protocol =
    1270      124494 :             master_instance->protocol_config();
    1271      124494 :         if (master_protocol) {
    1272      123929 :             if (master_protocol->protocol_config()) {
    1273             :                 bgp_identifier =
    1274      123929 :                     master_protocol->protocol_config()->identifier();
    1275      123929 :                 as = master_protocol->protocol_config()->autonomous_system();
    1276             :             }
    1277             :         }
    1278             :     }
    1279      124494 :     if (bgp_identifier > 0)
    1280       78882 :         import_list.insert("target:" + GetVitFromId(ntohl(bgp_identifier)));
    1281      124494 :     if (as > 0)
    1282      123929 :         import_list.insert("target:" + GetESRouteTarget(as));
    1283      124494 : }
    1284             : 
    1285             : //
    1286             : // Update BgpIfmapInstanceConfig based on a new autogen::RoutingInstance object.
    1287             : //
    1288             : // Rebuild the import and export route target lists and update the virtual
    1289             : // network information.
    1290             : //
    1291             : // Targets that are configured on this routing-instance (which corresponds
    1292             : // to all adjacencies to instance-target) are added to the import list or
    1293             : // export list or both depending on the import_export attribute.
    1294             : //
    1295             : // Export targets for all other routing-instances that we are connected to
    1296             : // are added to our import list.
    1297             : //
    1298      124494 : void BgpIfmapInstanceConfig::Update(BgpIfmapConfigManager *manager,
    1299             :     const autogen::RoutingInstance *config) {
    1300      124494 :     BgpInstanceConfig::RouteTargetList import_list, export_list;
    1301      124494 :     BgpInstanceConfig::AggregateRouteList inet6_aggregate_list;
    1302      124494 :     BgpInstanceConfig::AggregateRouteList inet_aggregate_list;
    1303      124494 :     RoutingPolicyConfigList policy_list;
    1304      124494 :     data_.Clear();
    1305             : 
    1306      124494 :     DBGraph *graph = manager->graph();
    1307      124494 :     IFMapNode *node = node_proxy_.node();
    1308      124494 :     for (DBGraphVertex::adjacency_iterator iter = node->begin(graph);
    1309      761918 :          iter != node->end(graph); ++iter) {
    1310      637424 :         IFMapNode *adj = static_cast<IFMapNode *>(iter.operator->());
    1311      637424 :         if (strcmp(adj->table()->Typename(), "instance-target") == 0) {
    1312      522978 :             string target;
    1313      522978 :             if (GetInstanceTargetRouteTarget(graph, adj, &target)) {
    1314             :                 const autogen::InstanceTarget *itarget =
    1315      522978 :                     dynamic_cast<autogen::InstanceTarget *>(adj->GetObject());
    1316      522978 :                 if (!itarget)
    1317           0 :                     continue;
    1318      522978 :                 const autogen::InstanceTargetType &itt = itarget->data();
    1319      522978 :                 if (itt.import_export == "import") {
    1320       10858 :                     import_list.insert(target);
    1321      512120 :                 } else if (itt.import_export == "export") {
    1322         888 :                     export_list.insert(target);
    1323             :                 } else {
    1324      511232 :                     import_list.insert(target);
    1325      511232 :                     export_list.insert(target);
    1326             :                 }
    1327             :             }
    1328      637424 :         } else if (strcmp(adj->table()->Typename(),
    1329      114446 :                           "routing-policy-routing-instance") == 0) {
    1330         530 :             RoutingPolicyAttachInfo policy_info;
    1331         530 :             if (GetRoutingInstanceRoutingPolicy(graph, adj, &policy_info)) {
    1332         530 :                 policy_list.push_back(policy_info);
    1333             :             }
    1334      114446 :         } else if (strcmp(adj->table()->Typename(), "route-aggregate") == 0) {
    1335         728 :             GetRouteAggregateConfig(graph, adj, &inet_aggregate_list,
    1336             :                                     &inet6_aggregate_list);
    1337      113188 :         } else if (strcmp(adj->table()->Typename(), "connection") == 0) {
    1338       28161 :             vector<string> target_list;
    1339       28161 :             GetConnectionExportTargets(graph, node, name_, adj, &target_list);
    1340       84375 :             BOOST_FOREACH(string target, target_list) {
    1341       28107 :                 import_list.insert(target);
    1342       28107 :             }
    1343      113188 :         } else if (strcmp(adj->table()->Typename(), "virtual-network") == 0) {
    1344       74116 :             data_.set_virtual_network(adj->name());
    1345       74116 :             data_.set_virtual_network_index(GetVirtualNetworkIndex(graph, adj));
    1346      148232 :             data_.set_virtual_network_allow_transit(
    1347       74116 :                 GetVirtualNetworkAllowTransit(graph, adj));
    1348       74116 :             data_.set_vxlan_id(GetVirtualNetworkVxlanId(graph, adj));
    1349      148232 :             data_.set_virtual_network_pbb_evpn_enable(
    1350       74116 :                 GetVirtualNetworkPbbEvpnEnable(graph, adj));
    1351       74116 :             data_.set_routing_instance_vxlan(GetConnectedVxlanRi(graph, adj));
    1352             :         }
    1353             :     }
    1354             : 
    1355      124494 :     InsertVitAndESRTargetInImportList(manager, import_list);
    1356      124494 :     data_.set_import_list(import_list);
    1357      124494 :     data_.set_export_list(export_list);
    1358             : 
    1359      124494 :     sort(policy_list.begin(), policy_list.end(), CompareRoutingPolicyOrder);
    1360      124494 :     data_.swap_routing_policy_list(&policy_list);
    1361      124494 :     data_.swap_aggregate_routes(Address::INET, &inet_aggregate_list);
    1362      124494 :     data_.swap_aggregate_routes(Address::INET6, &inet6_aggregate_list);
    1363             : 
    1364      124494 :     if (config) {
    1365        4216 :         data_.set_has_pnf(config->has_pnf());
    1366        4216 :         SetStaticRouteConfig(&data_, config);
    1367        4216 :         SetServiceChainConfig(&data_, config);
    1368             :     }
    1369      124494 : }
    1370             : 
    1371             : //
    1372             : // Reset IFMap related state in the BgpIfmapInstanceConfig.
    1373             : //
    1374       11642 : void BgpIfmapInstanceConfig::ResetConfig() {
    1375       11642 :     node_proxy_.Clear();
    1376       11642 : }
    1377             : 
    1378             : //
    1379             : // Return true if the BgpIfmapInstanceConfig is ready to be deleted.  The
    1380             : // caller is responsible for actually deleting it.
    1381             : //
    1382       15188 : bool BgpIfmapInstanceConfig::DeleteIfEmpty(BgpConfigManager *manager) {
    1383       15188 :     if (name_ == BgpConfigManager::kMasterInstance) {
    1384        4770 :         return false;
    1385             :     }
    1386       10418 :     if (node() != NULL || protocol_.get() != NULL) {
    1387          52 :         return false;
    1388             :     }
    1389       20689 :     if (!neighbors_.empty() || !peerings_.empty() ||
    1390       10323 :         !routing_policies_.empty()) {
    1391          44 :         return false;
    1392             :     }
    1393             : 
    1394       10322 :     manager->Notify(&data_, BgpConfigManager::CFG_DELETE);
    1395       10322 :     return true;
    1396             : }
    1397             : 
    1398             : //
    1399             : // Add a BgpNeighborConfig to this BgpIfmapInstanceConfig.
    1400             : //
    1401             : // The BgpNeighborConfig is added to the NeighborMap and the BgpConfigManager
    1402             : // is notified.
    1403             : //
    1404        9417 : void BgpIfmapInstanceConfig::AddNeighbor(BgpConfigManager *manager,
    1405             :     BgpNeighborConfig *neighbor) {
    1406        9417 :     BGP_CONFIG_LOG_NEIGHBOR(
    1407             :         Create, manager->server(), neighbor, SandeshLevel::SYS_DEBUG,
    1408             :         BGP_LOG_FLAG_ALL,
    1409             :         neighbor->admin_down(),
    1410             :         neighbor->passive(),
    1411             :         BgpIdentifierToString(neighbor->local_identifier()),
    1412             :         neighbor->local_as(),
    1413             :         neighbor->peer_address().to_string(), neighbor->peer_as(),
    1414             :         neighbor->GetAddressFamilies(), neighbor->AuthKeyTypeToString(),
    1415             :         neighbor->AuthKeysToString());
    1416        9417 :     neighbors_.insert(make_pair(neighbor->name(), neighbor));
    1417        9417 :     data_.add_neighbor(neighbor->name());
    1418        9417 :     manager->Notify(neighbor, BgpConfigManager::CFG_ADD);
    1419        9417 : }
    1420             : 
    1421             : //
    1422             : // Change a BgpNeighborConfig that's already in this BgpIfmapInstanceConfig.
    1423             : //
    1424         764 : void BgpIfmapInstanceConfig::ChangeNeighbor(BgpConfigManager *manager,
    1425             :     BgpNeighborConfig *neighbor) {
    1426         764 :     NeighborMap::iterator loc = neighbors_.find(neighbor->name());
    1427         764 :     assert(loc != neighbors_.end());
    1428         764 :     loc->second = neighbor;
    1429             : 
    1430         764 :     BGP_CONFIG_LOG_NEIGHBOR(
    1431             :         Update, manager->server(), neighbor,
    1432             :         SandeshLevel::SYS_DEBUG, BGP_LOG_FLAG_ALL,
    1433             :         neighbor->admin_down(),
    1434             :         neighbor->passive(),
    1435             :         BgpIdentifierToString(neighbor->local_identifier()),
    1436             :         neighbor->local_as(),
    1437             :         neighbor->peer_address().to_string(), neighbor->peer_as(),
    1438             :         neighbor->GetAddressFamilies(), neighbor->AuthKeyTypeToString(),
    1439             :         neighbor->AuthKeysToString());
    1440         764 :     manager->Notify(neighbor, BgpConfigManager::CFG_CHANGE);
    1441         764 : }
    1442             : 
    1443             : //
    1444             : // Delete a BgpNeighborConfig from this BgpIfmapInstanceConfig.
    1445             : //
    1446             : // The BgpConfigManager is notified and BgpNeighborConfig is removed from the
    1447             : // NeighborMap. Note that the caller is responsible for actually deleting the
    1448             : // BgpNeighborConfig object.
    1449             : //
    1450        6719 : void BgpIfmapInstanceConfig::DeleteNeighbor(BgpConfigManager *manager,
    1451             :     BgpNeighborConfig *neighbor) {
    1452        6719 :     BGP_CONFIG_LOG_NEIGHBOR(Delete, manager->server(), neighbor,
    1453             :         SandeshLevel::SYS_DEBUG, BGP_LOG_FLAG_ALL);
    1454        6719 :     manager->Notify(neighbor, BgpConfigManager::CFG_DELETE);
    1455        6719 :     neighbors_.erase(neighbor->name());
    1456        6719 :     data_.delete_neighbor(neighbor->name());
    1457        6719 : }
    1458             : 
    1459             : //
    1460             : // Find the BgpNeighborConfig by name in this BgpIfmapInstanceConfig.
    1461             : //
    1462        6802 : const BgpNeighborConfig *BgpIfmapInstanceConfig::FindNeighbor(
    1463             :     const string &name) const {
    1464        6802 :     NeighborMap::const_iterator loc;
    1465             : 
    1466        6802 :     if (name.find(name_) == string::npos) {
    1467           7 :         string fqn(name_);
    1468           7 :         fqn += ":";
    1469           7 :         fqn += name;
    1470           7 :         loc = neighbors_.find(fqn);
    1471           7 :     } else {
    1472        6795 :         loc = neighbors_.find(name);
    1473             :     }
    1474             : 
    1475        6802 :     return loc != neighbors_.end() ? loc->second : NULL;
    1476             : }
    1477             : 
    1478             : //
    1479             : // Add a BgpPeeringConfig to this BgpIfmapInstanceConfig.
    1480             : //
    1481        4312 : void BgpIfmapInstanceConfig::AddPeering(BgpIfmapPeeringConfig *peering) {
    1482        4312 :     peerings_.insert(make_pair(peering->name(), peering));
    1483        4312 : }
    1484             : 
    1485             : //
    1486             : // Delete a BgpPeeringConfig from this BgpIfmapInstanceConfig.
    1487             : //
    1488        2121 : void BgpIfmapInstanceConfig::DeletePeering(BgpIfmapPeeringConfig *peering) {
    1489        2121 :     peerings_.erase(peering->name());
    1490        2121 : }
    1491             : 
    1492             : //
    1493             : // Add a BgpIfmapRoutingPolicyConfig to this BgpIfmapInstanceConfig.
    1494             : //
    1495         165 : void BgpIfmapInstanceConfig::AddRoutingPolicy(
    1496             :     BgpIfmapRoutingPolicyConfig *rtp) {
    1497         165 :     routing_policies_.insert(make_pair(rtp->name(), rtp));
    1498         165 : }
    1499             : 
    1500             : //
    1501             : // Delete a BgpIfmapRoutingPolicyConfig from this BgpIfmapInstanceConfig.
    1502             : //
    1503          46 : void BgpIfmapInstanceConfig::DeleteRoutingPolicy(
    1504             :     BgpIfmapRoutingPolicyConfig *rtp) {
    1505          46 :     routing_policies_.erase(rtp->name());
    1506          46 : }
    1507             : 
    1508        6022 : void BgpIfmapConfigData::ProcessIdentifierAndASUpdate(
    1509             :                             BgpIfmapConfigManager* manager,
    1510             :                             uint32_t new_id, uint32_t old_id,
    1511             :                             uint32_t new_as, uint32_t old_as) {
    1512        6022 :     assert(new_id != old_id || new_as != old_as);
    1513       24139 :     for (unsigned int i = 0; i < instances_.size(); i++) {
    1514       18117 :         BgpIfmapInstanceConfig * ifmap_config = instances_.At(i);
    1515       18117 :         if (!ifmap_config)
    1516           0 :             continue;
    1517       18117 :         if (new_id != old_id)
    1518       18014 :             ifmap_config->ProcessIdentifierUpdate(new_id, old_id);
    1519       18117 :         if (new_as != old_as)
    1520       12306 :             ifmap_config->ProcessASUpdate(new_as, old_as);
    1521       18117 :         manager->UpdateInstanceConfig(ifmap_config,
    1522             :                                       BgpConfigManager::CFG_CHANGE);
    1523             :     }
    1524        6022 : }
    1525             : 
    1526             : //
    1527             : // Constructor for BgpIfmapConfigData.
    1528             : //
    1529        8048 : BgpIfmapConfigData::BgpIfmapConfigData() {
    1530             :     // Reserve bit 0 for master instance
    1531        8048 :     instances_.ReserveBit(0);
    1532        8048 : }
    1533             : 
    1534             : //
    1535             : // Destructor for BgpConfigData.
    1536             : //
    1537        8048 : BgpIfmapConfigData::~BgpIfmapConfigData() {
    1538        8048 :     instances_.clear();
    1539        8048 :     STLDeleteElements(&peerings_);
    1540        8048 :     STLDeleteElements(&routing_policies_);
    1541        8048 :     STLDeleteElements(&ri_rp_links_);
    1542        8048 : }
    1543             : 
    1544             : //
    1545             : // Locate the BgpIfmapInstanceConfig by name, create it if not found.  The newly
    1546             : // created BgpIfmapInstanceConfig gets added to the IfmapInstanceMap.
    1547             : //
    1548             : // Note that we do not have the IFMapNode representing the routing-instance
    1549             : // at this point.
    1550             : //
    1551       50598 : BgpIfmapInstanceConfig *BgpIfmapConfigData::LocateInstance(const string &name) {
    1552       50598 :     BgpIfmapInstanceConfig *rti = FindInstance(name);
    1553       50598 :     if (rti != NULL) {
    1554           0 :         return rti;
    1555             :     }
    1556       50598 :     rti = new BgpIfmapInstanceConfig(name);
    1557       50598 :     int index = -1;
    1558       50598 :     if (name == BgpConfigManager::kMasterInstance) {
    1559        8030 :         index = 0;
    1560             :     }
    1561       50598 :     index = instances_.Insert(name, rti, index);
    1562       50598 :     rti->set_index(index);
    1563             :     pair<BgpInstanceMap::iterator, bool> result2 =
    1564       50598 :             instance_config_map_.insert(
    1565      101196 :                 make_pair(name, rti->instance_config()));
    1566       50598 :     assert(result2.second);
    1567       50598 :     return rti;
    1568             : }
    1569             : 
    1570             : //
    1571             : // Remove the given BgpIfmapInstanceConfig from the IfmapInstanceMap
    1572             : // and delete it.
    1573             : //
    1574       10322 : void BgpIfmapConfigData::DeleteInstance(BgpIfmapInstanceConfig *rti) {
    1575       10322 :     BgpInstanceMap::iterator loc2 = instance_config_map_.find(rti->name());
    1576       10322 :     assert(loc2 != instance_config_map_.end());
    1577       10322 :     instance_config_map_.erase(loc2);
    1578       10322 :     instances_.Remove(rti->name(), rti->index(), false);
    1579       10322 : }
    1580             : 
    1581             : //
    1582             : // Find the BgpIfmapInstanceConfig by name.
    1583             : //
    1584      487703 : BgpIfmapInstanceConfig *BgpIfmapConfigData::FindInstance(const string &name) {
    1585      487703 :     return instances_.Find(name);
    1586             : }
    1587             : 
    1588             : //
    1589             : // Find the BgpIfmapInstanceConfig by name.
    1590             : // Const version.
    1591             : //
    1592           7 : const BgpIfmapInstanceConfig *BgpIfmapConfigData::FindInstance(
    1593             :     const string &name) const {
    1594           7 :     return instances_.Find(name);
    1595             : }
    1596             : 
    1597             : BgpConfigManager::NeighborMapRange
    1598         202 : BgpIfmapInstanceConfig::NeighborMapItems() const {
    1599         202 :     return make_pair(neighbors_.begin(), neighbors_.end());
    1600             : }
    1601             : 
    1602             : //
    1603             : // Create a new BgpIfmapRoutingPolicyLinkConfig.
    1604             : //
    1605             : // The IFMapNodeProxy is a proxy for the IFMapNode which is the midnode that
    1606             : // represents the routing-policy-routing-instance. The newly created
    1607             : // BgpIfmapRoutingPolicyLinkConfig gets added to the IfmapRoutingPolicyLinkMap.
    1608             : //
    1609         165 : BgpIfmapRoutingPolicyLinkConfig *BgpIfmapConfigData::CreateRoutingPolicyLink(
    1610             :     BgpIfmapInstanceConfig *rti, BgpIfmapRoutingPolicyConfig *rtp,
    1611             :     IFMapNodeProxy *proxy) {
    1612             :     BgpIfmapRoutingPolicyLinkConfig *ri_rp_link =
    1613         165 :         new BgpIfmapRoutingPolicyLinkConfig(rti, rtp);
    1614         165 :     ri_rp_link->SetNodeProxy(proxy);
    1615             :     pair<IfmapRoutingPolicyLinkMap::iterator, bool> result =
    1616         165 :         ri_rp_links_.insert(make_pair(ri_rp_link->node()->name(), ri_rp_link));
    1617         165 :     assert(result.second);
    1618         165 :     ri_rp_link->instance()->AddRoutingPolicy(rtp);
    1619         165 :     ri_rp_link->policy()->AddInstance(rti);
    1620         165 :     return ri_rp_link;
    1621             : }
    1622             : 
    1623             : //
    1624             : // Delete a BgpIfmapRoutingPolicyLinkConfig.
    1625             : //
    1626             : // The BgpIfmapRoutingPolicyLinkConfig is erased from IfmapRoutingPolicyLinkMap
    1627             : // and then deleted.
    1628             : // Note that the reference to the IFMapNode for routing-policy-routing-instance
    1629             : // gets released via the destructor when the IFMapNodeProxy is destroyed.
    1630             : //
    1631          46 : void BgpIfmapConfigData::DeleteRoutingPolicyLink(
    1632             :     BgpIfmapRoutingPolicyLinkConfig *ri_rp_link) {
    1633          46 :     ri_rp_links_.erase(ri_rp_link->node()->name());
    1634          46 :     ri_rp_link->instance()->DeleteRoutingPolicy(ri_rp_link->policy());
    1635          46 :     ri_rp_link->policy()->RemoveInstance(ri_rp_link->instance());
    1636          46 :     delete ri_rp_link;
    1637          46 : }
    1638             : 
    1639             : //
    1640             : // Find the BgpIfmapRoutingPolicyLinkConfig by name.
    1641             : //
    1642         236 : BgpIfmapRoutingPolicyLinkConfig *BgpIfmapConfigData::FindRoutingPolicyLink(
    1643             :     const string &name) {
    1644         236 :     IfmapRoutingPolicyLinkMap::iterator loc = ri_rp_links_.find(name);
    1645         236 :     if (loc != ri_rp_links_.end()) {
    1646          71 :         return loc->second;
    1647             :     }
    1648         165 :     return NULL;
    1649             : }
    1650             : 
    1651             : //
    1652             : // Find the BgpIfmapRoutingPolicyLinkConfig by name.
    1653             : // Const version.
    1654             : //
    1655             : const BgpIfmapRoutingPolicyLinkConfig *
    1656           0 : BgpIfmapConfigData::FindRoutingPolicyLink(const string &name) const {
    1657           0 :     IfmapRoutingPolicyLinkMap::const_iterator loc = ri_rp_links_.find(name);
    1658           0 :     if (loc != ri_rp_links_.end()) {
    1659           0 :         return loc->second;
    1660             :     }
    1661           0 :     return NULL;
    1662             : }
    1663             : 
    1664             : //
    1665             : // Create a new BgpIfmapPeeringConfig.
    1666             : //
    1667             : // The IFMapNodeProxy is a proxy for the IFMapNode which is the
    1668             : // midnode that represents the bgp-peering. The newly created
    1669             : // BgpIfmapPeeringConfig gets added to the IfmapPeeringMap.
    1670             : //
    1671        4312 : BgpIfmapPeeringConfig *BgpIfmapConfigData::CreatePeering(
    1672             :     BgpIfmapInstanceConfig *rti, IFMapNodeProxy *proxy) {
    1673        4312 :     BgpIfmapPeeringConfig *peering = new BgpIfmapPeeringConfig(rti);
    1674        4312 :     peering->SetNodeProxy(proxy);
    1675             :     pair<IfmapPeeringMap::iterator, bool> result =
    1676        4312 :             peerings_.insert(make_pair(peering->node()->name(), peering));
    1677        4312 :     assert(result.second);
    1678        4312 :     peering->instance()->AddPeering(peering);
    1679        4312 :     BGP_LOG_STR(BgpConfig, SandeshLevel::SYS_DEBUG, BGP_LOG_FLAG_SYSLOG,
    1680             :          "Creating BgpIfmapPeering " << peering->node()->name());
    1681        4312 :     return peering;
    1682             : }
    1683             : 
    1684             : //
    1685             : // Delete a BgpPeeringConfig.
    1686             : //
    1687             : // The BgpPeeringConfig is removed from the IfmapPeeringMap and then deleted.
    1688             : // Note that the reference to the IFMapNode for the bgp-peering gets released
    1689             : // via the destructor when the IFMapNodeProxy is destroyed.
    1690             : //
    1691        2121 : void BgpIfmapConfigData::DeletePeering(BgpIfmapPeeringConfig *peering) {
    1692        2121 :     BGP_LOG_STR(BgpConfig, SandeshLevel::SYS_DEBUG, BGP_LOG_FLAG_SYSLOG,
    1693             :          "Deleting BgpIfmapPeering " << peering->node()->name());
    1694        2121 :     peering->instance()->DeletePeering(peering);
    1695        2121 :     peerings_.erase(peering->node()->name());
    1696        2121 :     delete peering;
    1697        2121 : }
    1698             : 
    1699             : //
    1700             : // Find the BgpPeeringConfig by name.
    1701             : //
    1702       20900 : BgpIfmapPeeringConfig *BgpIfmapConfigData::FindPeering(const string &name) {
    1703       20900 :     IfmapPeeringMap::iterator loc = peerings_.find(name);
    1704       20900 :     if (loc != peerings_.end()) {
    1705       12879 :         return loc->second;
    1706             :     }
    1707        8021 :     return NULL;
    1708             : }
    1709             : 
    1710             : //
    1711             : // Find the BgpPeeringConfig by name.
    1712             : // Const version.
    1713             : //
    1714           0 : const BgpIfmapPeeringConfig *BgpIfmapConfigData::FindPeering(
    1715             :     const string &name) const {
    1716           0 :     IfmapPeeringMap::const_iterator loc = peerings_.find(name);
    1717           0 :     if (loc != peerings_.end()) {
    1718           0 :         return loc->second;
    1719             :     }
    1720           0 :     return NULL;
    1721             : }
    1722             : 
    1723             : BgpConfigManager::InstanceMapRange
    1724          59 : BgpIfmapConfigData::InstanceMapItems(const string &start_name) const {
    1725          59 :     return make_pair(instance_config_map_.lower_bound(start_name),
    1726         118 :         instance_config_map_.end());
    1727             : }
    1728             : 
    1729             : BgpConfigManager::RoutingPolicyMapRange
    1730           2 : BgpIfmapConfigData::RoutingPolicyMapItems(const string &start_name) const {
    1731           2 :     return make_pair(routing_policy_config_map_.lower_bound(start_name),
    1732           4 :         routing_policy_config_map_.end());
    1733             : }
    1734             : 
    1735             : //
    1736             : // Locate the BgpIfmapRoutingPolicyConfig by name, create it if not found.
    1737             : // The newly created BgpIfmapRoutingPolicyConfig gets added to the
    1738             : // IfmapRoutingPolicyMap.
    1739             : //
    1740         161 : BgpIfmapRoutingPolicyConfig *BgpIfmapConfigData::LocateRoutingPolicy(
    1741             :     const string &name) {
    1742         161 :     BgpIfmapRoutingPolicyConfig *rtp = FindRoutingPolicy(name);
    1743         161 :     if (rtp != NULL) {
    1744           0 :         return rtp;
    1745             :     }
    1746         161 :     rtp = new BgpIfmapRoutingPolicyConfig(name);
    1747             :     pair<IfmapRoutingPolicyMap::iterator, bool> result =
    1748         161 :             routing_policies_.insert(make_pair(name, rtp));
    1749         161 :     assert(result.second);
    1750             :     pair<BgpRoutingPolicyMap::iterator, bool> result2 =
    1751         161 :             routing_policy_config_map_.insert(
    1752         322 :                 make_pair(name, rtp->routing_policy_config()));
    1753         161 :     assert(result2.second);
    1754         161 :     return rtp;
    1755             : }
    1756             : 
    1757             : //
    1758             : // Remove the given BgpIfmapRoutingPolicyConfig from the IfmapRoutingPolicyMap
    1759             : // and delete it.
    1760             : //
    1761          43 : void BgpIfmapConfigData::DeleteRoutingPolicy(BgpIfmapRoutingPolicyConfig *rtp) {
    1762          43 :     IfmapRoutingPolicyMap::iterator loc = routing_policies_.find(rtp->name());
    1763          43 :     assert(loc != routing_policies_.end());
    1764          43 :     routing_policies_.erase(loc);
    1765             :     BgpRoutingPolicyMap::iterator loc2 =
    1766          43 :         routing_policy_config_map_.find(rtp->name());
    1767          43 :     assert(loc2 != routing_policy_config_map_.end());
    1768          43 :     routing_policy_config_map_.erase(loc2);
    1769          43 :     delete rtp;
    1770          43 : }
    1771             : 
    1772         830 : BgpIfmapRoutingPolicyConfig *BgpIfmapConfigData::FindRoutingPolicy(
    1773             :     const string &name) {
    1774         830 :     IfmapRoutingPolicyMap::iterator loc = routing_policies_.find(name);
    1775         830 :     if (loc != routing_policies_.end()) {
    1776         457 :         return loc->second;
    1777             :     }
    1778         373 :     return NULL;
    1779             : }
    1780             : 
    1781           0 : const BgpIfmapRoutingPolicyConfig *BgpIfmapConfigData::FindRoutingPolicy(
    1782             :     const string &name) const {
    1783           0 :     IfmapRoutingPolicyMap::const_iterator loc = routing_policies_.find(name);
    1784           0 :     if (loc != routing_policies_.end()) {
    1785           0 :         return loc->second;
    1786             :     }
    1787           0 :     return NULL;
    1788             : }
    1789             : 
    1790             : //
    1791             : // Constructor for BgpIfmapConfigManager.
    1792             : //
    1793        8048 : BgpIfmapConfigManager::BgpIfmapConfigManager(BgpServer *server)
    1794             :     : BgpConfigManager(server),
    1795        8048 :       db_(NULL),
    1796        8048 :       db_graph_(NULL),
    1797        8048 :       trigger_(boost::bind(&BgpIfmapConfigManager::ConfigHandler, this),
    1798             :           TaskScheduler::GetInstance()->GetTaskId("bgp::Config"),
    1799             :           kConfigTaskInstanceId),
    1800        8048 :       listener_(new BgpConfigListener(this)),
    1801       16096 :       config_(new BgpIfmapConfigData()) {
    1802        8048 :     IdentifierMapInit();
    1803        8048 : }
    1804             : 
    1805             : //
    1806             : // Destructor for BgpIfmapConfigManager.
    1807             : //
    1808       16096 : BgpIfmapConfigManager::~BgpIfmapConfigManager() {
    1809       16096 : }
    1810             : 
    1811             : //
    1812             : // Initialize the BgpConfigManager.
    1813             : //
    1814        8030 : void BgpIfmapConfigManager::Initialize(DB *db, DBGraph *db_graph,
    1815             :                                        const string &localname) {
    1816        8030 :     db_ = db;
    1817        8030 :     db_graph_ = db_graph;
    1818        8030 :     localname_ = localname;
    1819        8030 :     listener_->Initialize();
    1820        8030 :     DefaultConfig();
    1821        8030 : }
    1822             : 
    1823             : //
    1824             : // Used to trigger a build and subsequent evaluation of the ChangeList.
    1825             : //
    1826      219976 : void BgpIfmapConfigManager::OnChange() {
    1827      219976 :     CHECK_CONCURRENCY("db::IFMapTable");
    1828      219976 :     trigger_.Set();
    1829      219976 : }
    1830             : 
    1831             : BgpConfigManager::InstanceMapRange
    1832          59 : BgpIfmapConfigManager::InstanceMapItems(const string &start_name) const {
    1833          59 :     return config_->InstanceMapItems(start_name);
    1834             : }
    1835             : 
    1836             : BgpConfigManager::RoutingPolicyMapRange
    1837           2 : BgpIfmapConfigManager::RoutingPolicyMapItems(const string &start_name) const {
    1838           2 :     return config_->RoutingPolicyMapItems(start_name);
    1839             : }
    1840             : 
    1841             : BgpConfigManager::NeighborMapRange
    1842         202 : BgpIfmapConfigManager::NeighborMapItems(
    1843             :     const string &instance_name) const {
    1844         202 :     static BgpConfigManager::NeighborMap nilMap;
    1845         202 :     BgpIfmapInstanceConfig *rti = config_->FindInstance(instance_name);
    1846         202 :     if (rti == NULL) {
    1847           0 :         return make_pair(nilMap.begin(), nilMap.end());
    1848             :     }
    1849         202 :     return rti->NeighborMapItems();
    1850             : }
    1851             : 
    1852       50475 : void BgpIfmapConfigManager::ResetRoutingInstanceIndexBit(int index) {
    1853       50475 :     config()->instances().ResetBit(index);
    1854       50475 : }
    1855             : 
    1856          14 : int BgpIfmapConfigManager::NeighborCount(
    1857             :     const string &instance_name) const {
    1858          14 :     BgpIfmapInstanceConfig *rti = config_->FindInstance(instance_name);
    1859          14 :     if (rti == NULL) {
    1860           2 :         return 0;
    1861             :     }
    1862          12 :     return rti->neighbors().size();
    1863             : }
    1864             : 
    1865             : //
    1866             : // Constructor for BgpIfmapRoutingPolicyConfig.
    1867             : //
    1868         161 : BgpIfmapRoutingPolicyConfig::BgpIfmapRoutingPolicyConfig(
    1869         161 :     const string &name)
    1870         161 :     : name_(name),
    1871         161 :       data_(name) {
    1872         161 : }
    1873             : 
    1874             : //
    1875             : // Destructor for BgpIfmapRoutingPolicyConfig.
    1876             : //
    1877         161 : BgpIfmapRoutingPolicyConfig::~BgpIfmapRoutingPolicyConfig() {
    1878         161 : }
    1879             : 
    1880             : //
    1881             : // Set the IFMapNodeProxy for the BgpIfmapRoutingPolicyConfig.
    1882             : //
    1883         161 : void BgpIfmapRoutingPolicyConfig::SetNodeProxy(IFMapNodeProxy *proxy) {
    1884         161 :     if (proxy != NULL) {
    1885         161 :         node_proxy_.Swap(proxy);
    1886             :     }
    1887         161 : }
    1888             : 
    1889          43 : void BgpIfmapRoutingPolicyConfig::Delete(BgpConfigManager *manager) {
    1890          43 :     manager->Notify(&data_, BgpConfigManager::CFG_DELETE);
    1891          43 :     routing_policy_.reset();
    1892          43 : }
    1893             : 
    1894             : //
    1895             : // Return true if the BgpIfmapRoutingPolicyConfig is ready to be deleted.
    1896             : // The caller is responsible for actually deleting it.
    1897             : //
    1898          89 : bool BgpIfmapRoutingPolicyConfig::DeleteIfEmpty(BgpConfigManager *manager) {
    1899          89 :     if (node() != NULL) {
    1900           5 :         return false;
    1901             :     }
    1902          84 :     if (!instances_.empty()) {
    1903          41 :         return false;
    1904             :     }
    1905             : 
    1906          43 :     Delete(manager);
    1907          43 :     return true;
    1908             : }
    1909             : 
    1910             : //
    1911             : // Add a BgpIfmapInstanceConfig to BgpIfmapRoutingPolicyConfig.
    1912             : //
    1913         165 : void BgpIfmapRoutingPolicyConfig::AddInstance(BgpIfmapInstanceConfig *rti) {
    1914         165 :     instances_.insert(make_pair(rti->name(), rti));
    1915         165 : }
    1916             : 
    1917             : //
    1918             : // Remove a BgpIfmapInstanceConfig to BgpIfmapRoutingPolicyConfig.
    1919             : //
    1920          46 : void BgpIfmapRoutingPolicyConfig::RemoveInstance(BgpIfmapInstanceConfig *rti) {
    1921          46 :     instances_.erase(rti->name());
    1922          46 : }
    1923             : 
    1924             : 
    1925         477 : static void BuildPolicyTermConfig(autogen::PolicyTermType cfg_term,
    1926             :     RoutingPolicyTermConfig *term) {
    1927         477 :     term->match.protocols_match = cfg_term.term_match_condition.protocol;
    1928         933 :     BOOST_FOREACH(const autogen::PrefixMatchType &prefix_match,
    1929             :                   cfg_term.term_match_condition.prefix) {
    1930         228 :         string prefix_type(prefix_match.prefix_type);
    1931         228 :         PrefixMatchConfig match(prefix_match.prefix,
    1932         456 :             prefix_type.empty() ? "exact" : prefix_type);
    1933         228 :         term->match.prefixes_to_match.push_back(match);
    1934         228 :     }
    1935         477 :     term->match.community_match_all =
    1936         477 :         cfg_term.term_match_condition.community_match_all;
    1937         477 :     if (!cfg_term.term_match_condition.community_list.empty()) {
    1938             :         term->match.community_match =
    1939          24 :             cfg_term.term_match_condition.community_list;
    1940             :     }
    1941         477 :     if (!cfg_term.term_match_condition.community.empty()) {
    1942         272 :         term->match.community_match.push_back(
    1943         272 :             cfg_term.term_match_condition.community);
    1944             :     }
    1945         477 :     term->match.ext_community_match_all =
    1946         477 :         cfg_term.term_match_condition.extcommunity_match_all;
    1947         477 :     if (!cfg_term.term_match_condition.extcommunity_list.empty()) {
    1948             :         term->match.ext_community_match =
    1949          12 :             cfg_term.term_match_condition.extcommunity_list;
    1950             :     }
    1951             : 
    1952         493 :     BOOST_FOREACH(uint32_t asn,
    1953             :         cfg_term.term_action_list.update.as_path.expand.asn_list) {
    1954           8 :         term->action.update.aspath_expand.push_back(asn);
    1955             :     }
    1956         645 :     BOOST_FOREACH(const string community,
    1957             :                   cfg_term.term_action_list.update.community.add.community) {
    1958          84 :         term->action.update.community_add.push_back(community);
    1959          84 :     }
    1960         549 :     BOOST_FOREACH(const string community,
    1961             :                   cfg_term.term_action_list.update.community.remove.community) {
    1962          36 :         term->action.update.community_remove.push_back(community);
    1963          36 :     }
    1964         589 :     BOOST_FOREACH(const string community,
    1965             :                   cfg_term.term_action_list.update.community.set.community) {
    1966          56 :         term->action.update.community_set.push_back(community);
    1967          56 :     }
    1968         509 :     BOOST_FOREACH(const string community,
    1969             :                   cfg_term.term_action_list.update.extcommunity.add.community) {
    1970          16 :         term->action.update.ext_community_add.push_back(community);
    1971          16 :     }
    1972         521 :     BOOST_FOREACH(const string community,
    1973             :                   cfg_term.term_action_list.update.extcommunity.remove.community) {
    1974          22 :         term->action.update.ext_community_remove.push_back(community);
    1975          22 :     }
    1976         493 :     BOOST_FOREACH(const string community,
    1977             :                   cfg_term.term_action_list.update.extcommunity.set.community) {
    1978           8 :         term->action.update.ext_community_set.push_back(community);
    1979           8 :     }
    1980         477 :     term->action.update.local_pref =
    1981         477 :         cfg_term.term_action_list.update.local_pref;
    1982         477 :     term->action.update.med = cfg_term.term_action_list.update.med;
    1983             : 
    1984         477 :     term->action.action = RoutingPolicyActionConfig::NEXT_TERM;
    1985         477 :     if (strcmp(cfg_term.term_action_list.action.c_str(), "reject") == 0) {
    1986         134 :         term->action.action = RoutingPolicyActionConfig::REJECT;
    1987         343 :     } else if (
    1988         343 :         strcmp(cfg_term.term_action_list.action.c_str(), "accept") == 0) {
    1989         241 :         term->action.action = RoutingPolicyActionConfig::ACCEPT;
    1990             :     }
    1991         477 : }
    1992             : 
    1993         396 : static void BuildPolicyTermsConfig(BgpRoutingPolicyConfig *policy_cfg,
    1994             :     const autogen::RoutingPolicy *policy) {
    1995         396 :     vector<autogen::PolicyTermType> terms = policy->entries();
    1996        1350 :     BOOST_FOREACH(autogen::PolicyTermType cfg_term, terms) {
    1997         477 :         RoutingPolicyTermConfig policy_term_cfg;
    1998         477 :         BuildPolicyTermConfig(cfg_term, &policy_term_cfg);
    1999         477 :         policy_cfg->add_term(policy_term_cfg);
    2000         954 :     }
    2001         396 : }
    2002             : 
    2003         396 : void BgpIfmapRoutingPolicyConfig::Update(BgpIfmapConfigManager *manager,
    2004             :     const autogen::RoutingPolicy *policy) {
    2005         396 :     routing_policy_.reset(policy);
    2006         396 :     data_.Clear();
    2007         396 :     if (policy) {
    2008         396 :         BuildPolicyTermsConfig(&data_, policy);
    2009             :     }
    2010         396 : }
    2011             : 
    2012             : //
    2013             : // Reset IFMap related state in the BgpIfmapRoutingPolicyConfig.
    2014             : //
    2015          43 : void BgpIfmapRoutingPolicyConfig::ResetConfig() {
    2016          43 :     node_proxy_.Clear();
    2017          43 : }
    2018             : 
    2019          65 : const BgpRoutingPolicyConfig *BgpIfmapConfigManager::FindRoutingPolicy(
    2020             :     const string &name) const {
    2021          65 :     BgpIfmapRoutingPolicyConfig *rtp = config_->FindRoutingPolicy(name);
    2022          65 :     if (rtp == NULL) {
    2023          51 :         return NULL;
    2024             :     }
    2025          14 :     return rtp->routing_policy_config();
    2026             : }
    2027             : 
    2028       79204 : const BgpInstanceConfig *BgpIfmapConfigManager::FindInstance(
    2029             :     const string &name) const {
    2030       79204 :     BgpIfmapInstanceConfig *rti = config_->FindInstance(name);
    2031       79231 :     if (rti == NULL) {
    2032       10204 :         return NULL;
    2033             :     }
    2034       69027 :     return rti->instance_config();
    2035             : }
    2036             : 
    2037       62495 : const BgpProtocolConfig *BgpIfmapConfigManager::GetProtocolConfig(
    2038             :     const string &instance_name) const {
    2039       62495 :     BgpIfmapInstanceConfig *rti = config_->FindInstance(instance_name);
    2040       62486 :     if (rti == NULL) {
    2041        1023 :         return NULL;
    2042             :     }
    2043       61463 :     const BgpIfmapProtocolConfig *proto = rti->protocol_config();
    2044       61464 :     if (proto == NULL) {
    2045          50 :         return NULL;
    2046             :     }
    2047       61414 :     return proto->protocol_config();
    2048             : }
    2049             : 
    2050        6802 : const BgpNeighborConfig *BgpIfmapConfigManager::FindNeighbor(
    2051             :     const string &instance_name, const string &name) const {
    2052        6802 :     BgpIfmapInstanceConfig *rti = config_->FindInstance(instance_name);
    2053        6802 :     if (rti == NULL) {
    2054           0 :         return NULL;
    2055             :     }
    2056        6802 :     return rti->FindNeighbor(name);
    2057             : }
    2058             : 
    2059             : //
    2060             : // Initialize autogen::BgpRouterParams with default values.
    2061             : //
    2062        8030 : void BgpIfmapConfigManager::DefaultBgpRouterParams(
    2063             :     autogen::BgpRouterParams *param) {
    2064        8030 :     param->Clear();
    2065        8030 :     param->autonomous_system = BgpConfigManager::kDefaultAutonomousSystem;
    2066        8030 :     param->port = BgpConfigManager::kDefaultPort;
    2067        8030 : }
    2068             : 
    2069             : //
    2070             : // Create BgpInsatnceConfig for master routing-instance.  This
    2071             : // includes the BgpIfmapProtocolConfig for the local bgp-router in the
    2072             : // master routing-instance.
    2073             : //
    2074        8030 : void BgpIfmapConfigManager::DefaultConfig() {
    2075        8030 :     BgpIfmapInstanceConfig *rti = config_->LocateInstance(kMasterInstance);
    2076        8030 :     unique_ptr<autogen::BgpRouter> router(new autogen::BgpRouter());
    2077        8030 :     autogen::BgpRouterParams param;
    2078        8030 :     DefaultBgpRouterParams(&param);
    2079        8030 :     router->SetProperty("bgp-router-parameters", &param);
    2080        8030 :     BgpIfmapProtocolConfig *protocol = rti->LocateProtocol();
    2081        8030 :     protocol->Update(this, router.release());
    2082        8030 :     Notify(rti->instance_config(), BgpConfigManager::CFG_ADD);
    2083             : 
    2084        8030 :     vector<string> import_list;
    2085        8030 :     vector<string> export_list;
    2086        8030 :     BGP_CONFIG_LOG_INSTANCE(
    2087             :         Create, server(), rti, SandeshLevel::SYS_DEBUG, BGP_LOG_FLAG_ALL,
    2088             :         import_list, export_list,
    2089             :         rti->virtual_network(), rti->virtual_network_index());
    2090             : 
    2091        8030 :     BGP_CONFIG_LOG_PROTOCOL(
    2092             :         Create, server(), protocol,
    2093             :         SandeshLevel::SYS_DEBUG, BGP_LOG_FLAG_ALL,
    2094             :         protocol->router_params().admin_down,
    2095             :         protocol->router_params().autonomous_system,
    2096             :         protocol->router_params().identifier,
    2097             :         protocol->router_params().address,
    2098             :         protocol->router_params().hold_time,
    2099             :         vector<string>());
    2100        8030 : }
    2101             : 
    2102        1137 : bool BgpIfmapGlobalSystemConfig::Update(BgpIfmapConfigManager *manager,
    2103             :         const autogen::GlobalSystemConfig *system) {
    2104        1137 :     bool changed = false;
    2105             : 
    2106        1137 :     if (data_.gr_enable() != system->graceful_restart_parameters().enable) {
    2107         564 :         data_.set_gr_enable(system->graceful_restart_parameters().enable);
    2108         564 :         changed |= true;
    2109             :     }
    2110             : 
    2111        1137 :     if (data_.gr_time() != system->graceful_restart_parameters().restart_time) {
    2112         784 :         data_.set_gr_time(system->graceful_restart_parameters().restart_time);
    2113         784 :         changed |= true;
    2114             :     }
    2115             : 
    2116        1137 :     if (data_.llgr_time() != static_cast<uint32_t>(
    2117        1137 :             system->graceful_restart_parameters().long_lived_restart_time)) {
    2118        1568 :         data_.set_llgr_time(
    2119         784 :             system->graceful_restart_parameters().long_lived_restart_time);
    2120         784 :         changed |= true;
    2121             :     }
    2122             : 
    2123        1137 :     if (data_.end_of_rib_timeout() !=
    2124        1137 :             system->graceful_restart_parameters().end_of_rib_timeout) {
    2125        1126 :         data_.set_end_of_rib_timeout(
    2126         563 :             system->graceful_restart_parameters().end_of_rib_timeout);
    2127         563 :         changed |= true;
    2128             :     }
    2129             : 
    2130        1137 :     if (data_.gr_bgp_helper() !=
    2131        1137 :             system->graceful_restart_parameters().bgp_helper_enable) {
    2132        1122 :         data_.set_gr_bgp_helper(
    2133         561 :             system->graceful_restart_parameters().bgp_helper_enable);
    2134         561 :         changed |= true;
    2135             :     }
    2136             : 
    2137        1137 :     if (data_.gr_xmpp_helper() !=
    2138        1137 :             system->graceful_restart_parameters().xmpp_helper_enable) {
    2139        1122 :         data_.set_gr_xmpp_helper(
    2140         561 :             system->graceful_restart_parameters().xmpp_helper_enable);
    2141         561 :         changed |= true;
    2142             :     }
    2143             : 
    2144        1137 :     if (data_.enable_4byte_as() != system->enable_4byte_as()) {
    2145          16 :         data_.set_enable_4byte_as(system->enable_4byte_as());
    2146          16 :         changed |= true;
    2147             :     }
    2148             : 
    2149        1137 :     if (data_.always_compare_med() != system->bgp_always_compare_med()) {
    2150           5 :         data_.set_always_compare_med(system->bgp_always_compare_med());
    2151           5 :         changed |= true;
    2152             :     }
    2153             : 
    2154        1137 :     if (data_.rd_cluster_seed() != system->rd_cluster_seed()) {
    2155          25 :         data_.set_rd_cluster_seed(system->rd_cluster_seed());
    2156          25 :         changed |= true;
    2157             :     }
    2158             : 
    2159        1137 :     if (data_.xmpp_hold_time() !=
    2160        1137 :             system->fast_convergence_parameters().xmpp_hold_time) {
    2161          22 :         data_.set_xmpp_hold_time(
    2162          11 :             system->fast_convergence_parameters().xmpp_hold_time);
    2163          11 :         changed |= true;
    2164             :     }
    2165             : 
    2166        1137 :     if (data_.bgpaas_port_start() != system->bgpaas_parameters().port_start) {
    2167         677 :         data_.set_bgpaas_port_start(system->bgpaas_parameters().port_start);
    2168         677 :         changed |= true;
    2169             :     }
    2170             : 
    2171        1137 :     if (data_.bgpaas_port_end() != system->bgpaas_parameters().port_end) {
    2172         677 :         data_.set_bgpaas_port_end(system->bgpaas_parameters().port_end);
    2173         677 :         changed |= true;
    2174             :     }
    2175             : 
    2176        1137 :     if (data_.fc_enabled() != system->fast_convergence_parameters().enable) {
    2177           9 :         data_.set_fc_enabled(system->fast_convergence_parameters().enable);
    2178           9 :         changed |= true;
    2179             :     }
    2180             : 
    2181        1137 :     if (data_.nh_check_enabled() !=
    2182        1137 :           system->fast_convergence_parameters().nh_reachability_check) {
    2183           4 :         data_.set_nh_check_enabled(
    2184           2 :             system->fast_convergence_parameters().nh_reachability_check);
    2185           2 :         changed |= true;
    2186             :     }
    2187             : 
    2188        1137 :     if (data_.all_tags_are_global() != system->bgp_all_tags_are_global()) {
    2189           4 :         data_.set_all_tags_are_global(system->bgp_all_tags_are_global());
    2190           4 :         changed |= true;
    2191             :     }
    2192             : 
    2193        1137 :     return changed;
    2194             : }
    2195             : 
    2196          11 : bool BgpIfmapGlobalQosConfig::Update(BgpIfmapConfigManager *manager,
    2197             :         const autogen::GlobalQosConfig *qos) {
    2198          11 :     bool changed = false;
    2199          11 :     const autogen::ControlTrafficDscpType &dscp = qos->control_traffic_dscp();
    2200             : 
    2201          11 :     if (data_.control_dscp() != dscp.control) {
    2202           9 :         data_.set_control_dscp(dscp.control);
    2203           9 :         Sandesh::SetDscpValue(dscp.control);
    2204           9 :         changed = true;
    2205             :     }
    2206          11 :     if (data_.analytics_dscp() != dscp.analytics) {
    2207           3 :         data_.set_analytics_dscp(dscp.analytics);
    2208           3 :         changed = true;
    2209             :     }
    2210          11 :     return changed;
    2211             : }
    2212             : 
    2213             : //
    2214             : // Initialize IdentifierMap with handlers for interesting identifier types.
    2215             : //
    2216             : // The IdentifierMap is used when processing BgpConfigDeltas generated by
    2217             : // the BgpConfigListener.
    2218             : //
    2219        8048 : void BgpIfmapConfigManager::IdentifierMapInit() {
    2220        8048 :     id_map_.insert(make_pair("routing-instance",
    2221        8048 :             boost::bind(&BgpIfmapConfigManager::ProcessRoutingInstance,
    2222             :                         this, _1)));
    2223        8048 :     id_map_.insert(make_pair("routing-policy",
    2224        8048 :         boost::bind(&BgpIfmapConfigManager::ProcessRoutingPolicy, this, _1)));
    2225        8048 :     id_map_.insert(make_pair("routing-policy-routing-instance",
    2226        8048 :         boost::bind(&BgpIfmapConfigManager::ProcessRoutingPolicyLink, this,
    2227             :             _1)));
    2228        8048 :     id_map_.insert(make_pair("bgp-router",
    2229        8048 :         boost::bind(&BgpIfmapConfigManager::ProcessBgpRouter, this, _1)));
    2230        8048 :     id_map_.insert(make_pair("bgp-peering",
    2231        8048 :         boost::bind(&BgpIfmapConfigManager::ProcessBgpPeering, this, _1)));
    2232        8048 :     id_map_.insert(make_pair("global-system-config",
    2233        8048 :         boost::bind(&BgpIfmapConfigManager::ProcessGlobalSystemConfig, this,
    2234             :                     _1)));
    2235        8048 :     id_map_.insert(make_pair("global-qos-config",
    2236        8048 :         boost::bind(&BgpIfmapConfigManager::ProcessGlobalQosConfig, this,
    2237             :                     _1)));
    2238        8048 : }
    2239             : 
    2240      142613 : void BgpIfmapConfigManager::UpdateInstanceConfig(BgpIfmapInstanceConfig *rti,
    2241             :         BgpConfigManager::EventType event) {
    2242      142613 :     if (!rti) {
    2243           0 :         return;
    2244             :     }
    2245             : 
    2246             :     // in case of id change, update import list and call subsequent code
    2247      142613 :     Notify(rti->instance_config(), event);
    2248             : 
    2249      142613 :     vector<string> import_rt(rti->import_list().begin(),
    2250      285226 :                              rti->import_list().end());
    2251      142613 :     vector<string> export_rt(rti->export_list().begin(),
    2252      285226 :                              rti->export_list().end());
    2253      142613 :     if (event == BgpConfigManager::CFG_ADD) {
    2254       42568 :         BGP_CONFIG_LOG_INSTANCE(Create, server(), rti,
    2255             :             SandeshLevel::SYS_DEBUG, BGP_LOG_FLAG_ALL,
    2256             :             import_rt, export_rt,
    2257             :             rti->virtual_network(), rti->virtual_network_index());
    2258             :     } else {
    2259      100045 :         BGP_CONFIG_LOG_INSTANCE(Update, server(), rti,
    2260             :             SandeshLevel::SYS_DEBUG, BGP_LOG_FLAG_ALL,
    2261             :             import_rt, export_rt,
    2262             :             rti->virtual_network(), rti->virtual_network_index());
    2263             :     }
    2264      142613 : }
    2265             : 
    2266             : //
    2267             : // Handler for routing-instance objects.
    2268             : //
    2269             : // Note that BgpIfmapInstanceConfig object for the master instance is created
    2270             : // before we have received any configuration for it i.e. there's no IFMapNode
    2271             : // or autogen::RoutingInstance for it. However, we will eventually receive a
    2272             : // delta for the master.  The IFMapNodeProxy and autogen::RoutingInstance are
    2273             : // set at that time.
    2274             : //
    2275             : // For other routing-instances BgpIfmapConfigInstance can get created before we
    2276             : // see the IFMapNode for the routing-instance if we see the IFMapNode for the
    2277             : // local bgp-router in the routing-instance.  In this case, the IFMapNodeProxy
    2278             : // and autogen::RoutingInstance are set when we later see the IFMapNode for the
    2279             : // routing-instance.
    2280             : //
    2281             : // In all other cases, BgpIfmapConfigInstance is created when we see IFMapNode
    2282             : // for the routing-instance.  The IFMapNodeProxy and autogen::RoutingInstance
    2283             : // are set right away.
    2284             : //
    2285             : // References to the IFMapNode and the autogen::RoutingInstance are
    2286             : // released when the IFMapNode is marked deleted.  However the
    2287             : // BgpIfmapInstanceConfig does not get deleted till the NeighborMap is
    2288             : // empty and the BgpIfmapProtocolConfig is gone.
    2289             : //
    2290      136136 : void BgpIfmapConfigManager::ProcessRoutingInstance(
    2291             :     const BgpConfigDelta &delta) {
    2292      136136 :     CHECK_CONCURRENCY("bgp::Config");
    2293             : 
    2294      136136 :     BgpConfigManager::EventType event = BgpConfigManager::CFG_CHANGE;
    2295      136136 :     string instance_name = delta.id_name;
    2296      136136 :     BgpIfmapInstanceConfig *rti = config_->FindInstance(instance_name);
    2297      136136 :     if (rti == NULL) {
    2298       42566 :         IFMapNodeProxy *proxy = delta.node.get();
    2299       42566 :         if (proxy == NULL) {
    2300           0 :             return;
    2301             :         }
    2302       42566 :         IFMapNode *node = proxy->node();
    2303       42566 :         if (node == NULL || node->IsDeleted()) {
    2304           0 :             return;
    2305             :         }
    2306       42566 :         event = BgpConfigManager::CFG_ADD;
    2307       42566 :         rti = config_->LocateInstance(instance_name);
    2308       42566 :         rti->SetNodeProxy(proxy);
    2309             :     } else {
    2310       93570 :         IFMapNode *node = rti->node();
    2311       93570 :         if (node == NULL) {
    2312        5842 :             IFMapNodeProxy *proxy = delta.node.get();
    2313        5842 :             if (proxy == NULL) {
    2314           0 :                 return;
    2315             :             }
    2316        5842 :             rti->SetNodeProxy(proxy);
    2317       87728 :         } else if (node->IsDeleted()) {
    2318       11642 :             rti->ResetConfig();
    2319       11642 :             if (rti->DeleteIfEmpty(this)) {
    2320       10299 :                 BGP_CONFIG_LOG_INSTANCE(
    2321             :                     Delete, server(), rti,
    2322             :                     SandeshLevel::SYS_DEBUG, BGP_LOG_FLAG_ALL);
    2323       10299 :                 config_->DeleteInstance(rti);
    2324             :             }
    2325       11642 :             return;
    2326             :         }
    2327             :     }
    2328             : 
    2329             :     autogen::RoutingInstance *rti_config =
    2330      124494 :         static_cast<autogen::RoutingInstance *>(delta.obj.get());
    2331      124494 :     if (rti->index() != -1)
    2332      124494 :         rti->instance_config()->set_index(rti->index());
    2333      124494 :     rti->Update(this, rti_config);
    2334      124494 :     UpdateInstanceConfig(rti, event);
    2335      136136 : }
    2336             : 
    2337             : //
    2338             : // Handler for bgp protocol config.
    2339             : //
    2340             : // Note that there's no underlying IFMap object for the bgp protocol config.
    2341             : // This is called by the handler for bgp-router objects. The BgpConfigDelta
    2342             : // is a delta for the bgp-router object.
    2343             : //
    2344        9584 : void BgpIfmapConfigManager::ProcessBgpProtocol(const BgpConfigDelta &delta) {
    2345        9584 :     CHECK_CONCURRENCY("bgp::Config");
    2346             : 
    2347        9584 :     BgpConfigManager::EventType event = BgpConfigManager::CFG_CHANGE;
    2348        9584 :     string instance_name(IdentifierParent(delta.id_name));
    2349        9584 :     BgpIfmapInstanceConfig *rti = config_->FindInstance(instance_name);
    2350        9584 :     BgpIfmapProtocolConfig *protocol = NULL;
    2351        9584 :     if (rti != NULL) {
    2352        9584 :         protocol = rti->protocol_config_mutable();
    2353             :     }
    2354             : 
    2355        9584 :     if (protocol == NULL) {
    2356         565 :         IFMapNodeProxy *proxy = delta.node.get();
    2357         565 :         if (proxy == NULL) {
    2358           0 :             return;
    2359             :         }
    2360             :         // ignore identifier with no properties
    2361         565 :         if (delta.obj.get() == NULL) {
    2362           0 :             return;
    2363             :         }
    2364         565 :         IFMapNode *node = proxy->node();
    2365         565 :         if (node == NULL || node->IsDeleted()) {
    2366           0 :             return;
    2367             :         }
    2368         565 :         event = BgpConfigManager::CFG_ADD;
    2369         565 :         if (rti == NULL) {
    2370           0 :             rti = config_->LocateInstance(instance_name);
    2371           0 :             UpdateInstanceConfig(rti, event);
    2372             :         }
    2373         565 :         protocol = rti->LocateProtocol();
    2374         565 :         protocol->SetNodeProxy(proxy);
    2375             :     } else {
    2376        9019 :         IFMapNode *node = protocol->node();
    2377        9019 :         if (node == NULL) {
    2378             :             // The master instance creates a BgpRouter node internally. Ignore
    2379             :             // an update that doesn't specify any content.
    2380        5869 :             if (delta.obj.get() == NULL) {
    2381         535 :                 return;
    2382             :             }
    2383        5334 :             protocol->SetNodeProxy(delta.node.get());
    2384        3150 :         } else if (delta.obj.get() == NULL) {
    2385        1379 :             BGP_CONFIG_LOG_PROTOCOL(Delete, server(), protocol,
    2386             :                 SandeshLevel::SYS_DEBUG, BGP_LOG_FLAG_ALL);
    2387        1379 :             protocol->Delete(this);
    2388        1379 :             rti->ResetProtocol();
    2389        1379 :             if (rti->DeleteIfEmpty(this)) {
    2390           0 :                 BGP_CONFIG_LOG_INSTANCE(Delete, server(), rti,
    2391             :                     SandeshLevel::SYS_DEBUG, BGP_LOG_FLAG_ALL);
    2392           0 :                 config_->DeleteInstance(rti);
    2393             :             }
    2394        1379 :             return;
    2395             :         }
    2396             :     }
    2397             : 
    2398             :     autogen::BgpRouter *rt_config =
    2399        7670 :         static_cast<autogen::BgpRouter *>(delta.obj.get());
    2400        7670 :     uint32_t old_id = protocol->protocol_config()->identifier();
    2401        7670 :     uint32_t old_as = protocol->protocol_config()->autonomous_system();
    2402        7670 :     protocol->Update(this, rt_config);
    2403        7670 :     uint32_t new_id = protocol->protocol_config()->identifier();
    2404        7670 :     uint32_t new_as = protocol->protocol_config()->autonomous_system();
    2405        7670 :     if (new_id != old_id || new_as != old_as) {
    2406        6022 :         config_->ProcessIdentifierAndASUpdate(this, new_id, old_id, new_as,
    2407             :                                               old_as);
    2408             :     }
    2409        7670 :     Notify(protocol->protocol_config(), event);
    2410             : 
    2411        7670 :     if (!rt_config) {
    2412           0 :         return;
    2413             :     }
    2414             : 
    2415             :     vector<string> families(
    2416        7670 :         protocol->router_params().address_families.begin(),
    2417       15340 :         protocol->router_params().address_families.end());
    2418        7670 :     if (event == BgpConfigManager::CFG_ADD) {
    2419         565 :         BGP_CONFIG_LOG_PROTOCOL(Create, server(), protocol,
    2420             :             SandeshLevel::SYS_DEBUG, BGP_LOG_FLAG_ALL,
    2421             :             protocol->router_params().admin_down,
    2422             :             protocol->router_params().autonomous_system,
    2423             :             protocol->router_params().identifier,
    2424             :             protocol->router_params().address,
    2425             :             protocol->router_params().hold_time,
    2426             :             families);
    2427             :     } else {
    2428        7105 :         BGP_CONFIG_LOG_PROTOCOL(Update, server(), protocol,
    2429             :             SandeshLevel::SYS_DEBUG, BGP_LOG_FLAG_ALL,
    2430             :             protocol->router_params().admin_down,
    2431             :             protocol->router_params().autonomous_system,
    2432             :             protocol->router_params().identifier,
    2433             :             protocol->router_params().address,
    2434             :             protocol->router_params().hold_time,
    2435             :             families);
    2436             :     }
    2437        9584 : }
    2438             : 
    2439             : //
    2440             : // Handler for routing policy objects.
    2441             : //
    2442             : // BgpConfigListener::DependencyTracker ensures associated routing instances
    2443             : // are present in the change list.
    2444             : //
    2445         439 : void BgpIfmapConfigManager::ProcessRoutingPolicy(const BgpConfigDelta &delta) {
    2446         439 :     CHECK_CONCURRENCY("bgp::Config");
    2447             : 
    2448         439 :     BgpConfigManager::EventType event = BgpConfigManager::CFG_CHANGE;
    2449         439 :     string policy_name = delta.id_name;
    2450         439 :     BgpIfmapRoutingPolicyConfig *rtp = config_->FindRoutingPolicy(policy_name);
    2451         439 :     if (rtp == NULL) {
    2452         161 :         IFMapNodeProxy *proxy = delta.node.get();
    2453         161 :         if (proxy == NULL) {
    2454           0 :             return;
    2455             :         }
    2456         161 :         IFMapNode *node = proxy->node();
    2457         161 :         if (node == NULL || node->IsDeleted()) {
    2458           0 :             return;
    2459             :         }
    2460         161 :         event = BgpConfigManager::CFG_ADD;
    2461         161 :         rtp = config_->LocateRoutingPolicy(policy_name);
    2462         161 :         rtp->SetNodeProxy(proxy);
    2463             :     } else {
    2464         278 :         IFMapNode *node = rtp->node();
    2465         278 :         if (node == NULL) {
    2466           0 :             IFMapNodeProxy *proxy = delta.node.get();
    2467           0 :             if (proxy == NULL) {
    2468           0 :                 return;
    2469             :             }
    2470           0 :             rtp->SetNodeProxy(proxy);
    2471         278 :         } else if (node->IsDeleted()) {
    2472          43 :             rtp->ResetConfig();
    2473          43 :             if (rtp->DeleteIfEmpty(this)) {
    2474           5 :                 config_->DeleteRoutingPolicy(rtp);
    2475             :             }
    2476          43 :             return;
    2477             :         }
    2478             :     }
    2479             : 
    2480             :     autogen::RoutingPolicy *rtp_config =
    2481         396 :         static_cast<autogen::RoutingPolicy *>(delta.obj.get());
    2482         396 :     rtp->Update(this, rtp_config);
    2483         396 :     Notify(rtp->routing_policy_config(), event);
    2484         439 : }
    2485             : 
    2486             : 
    2487             : //
    2488             : // Handler for bgp-router objects.
    2489             : //
    2490       17110 : void BgpIfmapConfigManager::ProcessBgpRouter(const BgpConfigDelta &delta) {
    2491       17110 :     CHECK_CONCURRENCY("bgp::Config");
    2492             : 
    2493       17110 :     string instance_name(IdentifierParent(delta.id_name));
    2494       34220 :     if (instance_name.empty() ||
    2495       17110 :         instance_name != BgpConfigManager::kMasterInstance) {
    2496         468 :         return;
    2497             :     }
    2498             : 
    2499             :     // Ignore if this change is not for the local router.
    2500       16642 :     string name = delta.id_name.substr(instance_name.size() + 1);
    2501       16642 :     if (name != localname_) {
    2502        7058 :         return;
    2503             :     }
    2504             : 
    2505        9584 :     ProcessBgpProtocol(delta);
    2506             : 
    2507             :     // Update all peerings since we use local asn and identifier from master
    2508             :     // instance for all neighbors, including those in non-master instances.
    2509       17076 :     BOOST_FOREACH(const BgpIfmapConfigData::IfmapPeeringMap::value_type &value,
    2510             :         config_->peerings()) {
    2511        3746 :         BgpIfmapPeeringConfig *peering = value.second;
    2512        3746 :         peering->Update(this, peering->bgp_peering());
    2513             :     }
    2514       24168 : }
    2515             : 
    2516             : //
    2517             : // Handler for bgp-peering objects.
    2518             : //
    2519             : // We are only interested in this bgp-peering if it is adjacent to the local
    2520             : // router node.
    2521             : //
    2522             : // The BgpPeeringConfig is created the first time we see the bgp-peering.  It
    2523             : // is updated on subsequent changes and is deleted when the IFMapNode midnode
    2524             : // for the bgp-peering is deleted.
    2525             : //
    2526             : // Note that we are guaranteed that the IFMapNodes for the 2
    2527             : // bgp-routers for the bgp-peering already exist when we see the
    2528             : // bgp-peering. IFMap creates the nodes for the bgp-routers before
    2529             : // creating the midnode. This in turn guarantees that the
    2530             : // BgpIfmapInstanceConfig for the routing-instance also exists since we
    2531             : // create the BgpIfmapInstanceConfig before creating the
    2532             : // BgpIfmapProtocolConfig for a local bgp-router.
    2533             : //
    2534       17815 : void BgpIfmapConfigManager::ProcessBgpPeering(const BgpConfigDelta &delta) {
    2535       17815 :     CHECK_CONCURRENCY("bgp::Config");
    2536             : 
    2537       17815 :     BgpConfigManager::EventType event = BgpConfigManager::CFG_CHANGE;
    2538       17815 :     BgpIfmapPeeringConfig *peering = config_->FindPeering(delta.id_name);
    2539       17815 :     if (peering == NULL) {
    2540        8021 :         IFMapNodeProxy *proxy = delta.node.get();
    2541        8021 :         if (proxy == NULL) {
    2542        1843 :             BGP_LOG_STR(BgpConfig, SandeshLevel::SYS_DEBUG, BGP_LOG_FLAG_SYSLOG,
    2543             :                  "ProcessBgpPeering failed. Cannot find proxy " <<
    2544             :                  delta.id_name);
    2545        3709 :             return;
    2546             :         }
    2547        6178 :         IFMapNode *node = proxy->node();
    2548        6178 :         if (node == NULL || delta.obj.get() == NULL) {
    2549           0 :             BGP_LOG_STR(BgpConfig, SandeshLevel::SYS_DEBUG, BGP_LOG_FLAG_SYSLOG,
    2550             :                  "ProcessBgpPeering failed. Cannot find node/obj " <<
    2551             :                   delta.id_name);
    2552           0 :             return;
    2553             :         }
    2554             : 
    2555        6178 :         pair<IFMapNode *, IFMapNode *> routers;
    2556        6178 :         if (!BgpIfmapPeeringConfig::GetRouterPair(db_graph_, localname_, node,
    2557             :                                                   &routers)) {
    2558        1866 :             return;
    2559             :         }
    2560             : 
    2561        4312 :         string instance_name(IdentifierParent(routers.first->name()));
    2562        4312 :         BgpIfmapInstanceConfig *rti = config_->FindInstance(instance_name);
    2563        4312 :         event = BgpConfigManager::CFG_ADD;
    2564             :         // Create rti if not present.
    2565        4312 :         if (rti == NULL) {
    2566           2 :             rti = config_->LocateInstance(instance_name);
    2567           2 :             UpdateInstanceConfig(rti, event);
    2568             :         }
    2569        4312 :         peering = config_->CreatePeering(rti, proxy);
    2570        4312 :     } else {
    2571        9794 :         const IFMapNode *node = peering->node();
    2572        9794 :         assert(node != NULL);
    2573        9794 :         if (delta.obj.get() == NULL) {
    2574        2121 :             BGP_CONFIG_LOG_PEERING(Delete, server(), peering,
    2575             :                 SandeshLevel::SYS_DEBUG, BGP_LOG_FLAG_ALL);
    2576        2121 :             BgpIfmapInstanceConfig *rti = peering->instance();
    2577        2121 :             peering->Delete(this);
    2578        2121 :             config_->DeletePeering(peering);
    2579        2121 :             if (rti->DeleteIfEmpty(this)) {
    2580          22 :                 BGP_CONFIG_LOG_INSTANCE(Delete, server(), rti,
    2581             :                     SandeshLevel::SYS_DEBUG, BGP_LOG_FLAG_ALL);
    2582          22 :                 config_->DeleteInstance(rti);
    2583             :             }
    2584        2121 :             return;
    2585             :         }
    2586             :     }
    2587             : 
    2588       11985 :     if (event == BgpConfigManager::CFG_ADD) {
    2589        4312 :         BGP_CONFIG_LOG_PEERING(Create, server(), peering,
    2590             :             SandeshLevel::SYS_DEBUG, BGP_LOG_FLAG_ALL);
    2591             :     } else {
    2592        7673 :         BGP_CONFIG_LOG_PEERING(Update, server(), peering,
    2593             :             SandeshLevel::SYS_DEBUG, BGP_LOG_FLAG_ALL);
    2594             :     }
    2595             :     autogen::BgpPeering *peering_config =
    2596       11985 :             static_cast<autogen::BgpPeering *>(delta.obj.get());
    2597       11985 :     peering->Update(this, peering_config);
    2598             : }
    2599             : 
    2600        1137 : void BgpIfmapConfigManager::ProcessGlobalSystemConfig(
    2601             :         const BgpConfigDelta &delta) {
    2602        1137 :     IFMapNodeProxy *proxy = delta.node.get();
    2603        1137 :     if (proxy == NULL)
    2604           0 :         return;
    2605             : 
    2606        1137 :     IFMapNode *node = proxy->node();
    2607        1137 :     autogen::GlobalSystemConfig *config, default_config;
    2608        1137 :     if (node == NULL || node->IsDeleted() || delta.obj.get() == NULL) {
    2609           0 :         config = &default_config;
    2610             :     } else {
    2611        1137 :         config = static_cast<autogen::GlobalSystemConfig *>(delta.obj.get());
    2612             :     }
    2613             : 
    2614        1137 :     if (config_->global_config()->Update(this, config))
    2615         841 :         Notify(config_->global_config()->config(), BgpConfigManager::CFG_ADD);
    2616        1137 : }
    2617             : 
    2618          11 : void BgpIfmapConfigManager::ProcessGlobalQosConfig(
    2619             :         const BgpConfigDelta &delta) {
    2620          11 :     IFMapNodeProxy *proxy = delta.node.get();
    2621          11 :     if (proxy == NULL)
    2622           0 :         return;
    2623             : 
    2624          11 :     IFMapNode *node = proxy->node();
    2625          11 :     autogen::GlobalQosConfig *config, default_config;
    2626          11 :     if (node == NULL || node->IsDeleted() || delta.obj.get() == NULL) {
    2627           0 :         config = &default_config;
    2628             :     } else {
    2629          11 :         config = static_cast<autogen::GlobalQosConfig *>(delta.obj.get());
    2630             :     }
    2631             : 
    2632          11 :     if (config_->global_qos()->Update(this, config))
    2633           9 :         Notify(config_->global_qos()->config(), BgpConfigManager::CFG_ADD);
    2634          11 : }
    2635             : 
    2636             : //
    2637             : // Process the BgpConfigDeltas on the change list. We simply call the handler
    2638             : // for each delta based on the object's identifier type.
    2639             : //
    2640       26620 : void BgpIfmapConfigManager::ProcessChanges(const ChangeList &change_list) {
    2641       26620 :     CHECK_CONCURRENCY("bgp::Config");
    2642             : 
    2643       26620 :     for (ChangeList::const_iterator iter = change_list.begin();
    2644      223351 :          iter != change_list.end(); ++iter) {
    2645      196731 :         IdentifierMap::iterator loc = id_map_.find(iter->id_type);
    2646      196731 :         if (loc != id_map_.end()) {
    2647      172884 :             (loc->second)(*iter);
    2648             :         }
    2649             :     }
    2650       26620 : }
    2651             : 
    2652             : //
    2653             : // Build and process the change list of BgpConfigDeltas.  The logic to build
    2654             : // the list is in BgpConfigListener and BgpConfigListener::DependencyTracker.
    2655             : //
    2656       26620 : bool BgpIfmapConfigManager::ConfigHandler() {
    2657       26620 :     CHECK_CONCURRENCY("bgp::Config");
    2658             : 
    2659       26620 :     BgpConfigListener::ChangeList change_list;
    2660       26620 :     listener_->GetChangeList(&change_list);
    2661       26620 :     ProcessChanges(change_list);
    2662       26620 :     return true;
    2663       26620 : }
    2664             : 
    2665             : //
    2666             : // Terminate the BgpConfigManager.
    2667             : //
    2668        8048 : void BgpIfmapConfigManager::Terminate() {
    2669        8048 :     listener_->Terminate();
    2670        8048 :     config_.reset();
    2671        8048 : }

Generated by: LCOV version 1.14