LCOV - code coverage report
Current view: top level - bgp - bgp_config_parser.cc (source / functions) Hit Total Coverage
Test: OpenSDN C/C++ coverage (all TARGET_SET jobs) Lines: 535 543 98.5 %
Date: 2026-06-11 01:56:02 Functions: 31 31 100.0 %
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_parser.h"
       6             : 
       7             : #include <boost/uuid/name_generator.hpp>
       8             : #include <pugixml/pugixml.hpp>
       9             : 
      10             : #include <map>
      11             : #include <set>
      12             : #include <sstream>
      13             : #include <utility>
      14             : #include <vector>
      15             : 
      16             : #include "bgp/bgp_config.h"
      17             : #include "bgp/bgp_log.h"
      18             : #include "bgp/rtarget/rtarget_address.h"
      19             : #include "ifmap/ifmap_server_table.h"
      20             : 
      21             : #include "schema/bgp_schema_types.h"
      22             : #include "schema/vnc_cfg_types.h"
      23             : 
      24             : using pugi::xml_attribute;
      25             : using pugi::xml_document;
      26             : using pugi::xml_node;
      27             : using pugi::xml_parse_result;
      28             : using std::unique_ptr;
      29             : using std::istringstream;
      30             : using std::list;
      31             : using std::ostringstream;
      32             : using std::make_pair;
      33             : using std::map;
      34             : using std::multimap;
      35             : using std::pair;
      36             : using std::set;
      37             : using std::string;
      38             : using std::vector;
      39             : 
      40             : typedef multimap<
      41             :     pair<string, string>,
      42             :     pair<autogen::BgpSessionAttributes, string> > SessionMap;
      43             : 
      44             : namespace {
      45             : 
      46       24473 : static void MapObjectSetProperty(const string &ltype, const string &lname,
      47             :                                  const string &propname,
      48             :                                  AutogenProperty *property,
      49             :                                  BgpConfigParser::RequestList *requests) {
      50       24473 :     DBRequest *request = new DBRequest;
      51       24473 :     request->oper = DBRequest::DB_ENTRY_ADD_CHANGE;
      52       24473 :     IFMapTable::RequestKey *key = new IFMapTable::RequestKey();
      53       24473 :     request->key.reset(key);
      54       24473 :     key->id_type = ltype;
      55       24473 :     key->id_name = lname;
      56       24473 :     IFMapServerTable::RequestData *data = new IFMapServerTable::RequestData();
      57       24473 :     request->data.reset(data);
      58       24473 :     data->metadata = propname;
      59       24473 :     data->content.reset(property);
      60       24473 :     data->origin.set_origin(IFMapOrigin::MAP_SERVER);
      61       24473 :     requests->push_back(request);
      62       24473 : }
      63             : 
      64        5603 : static void MapObjectClearProperty(const string &ltype, const string &lname,
      65             :                                    const string &propname,
      66             :                                    BgpConfigParser::RequestList *requests) {
      67        5603 :     DBRequest *request = new DBRequest;
      68        5603 :     request->oper = DBRequest::DB_ENTRY_DELETE;
      69        5603 :     IFMapTable::RequestKey *key = new IFMapTable::RequestKey();
      70        5603 :     request->key.reset(key);
      71        5603 :     key->id_type = ltype;
      72        5603 :     key->id_name = lname;
      73        5603 :     IFMapServerTable::RequestData *data = new IFMapServerTable::RequestData();
      74        5603 :     request->data.reset(data);
      75        5603 :     data->metadata = propname;
      76        5603 :     data->origin.set_origin(IFMapOrigin::MAP_SERVER);
      77        5603 :     requests->push_back(request);
      78        5603 : }
      79             : 
      80       19275 : static void MapObjectLink(const string &ltype, const string &lname,
      81             :                          const string &rtype, const string &rname,
      82             :                          const string &linkname,
      83             :                          BgpConfigParser::RequestList *requests) {
      84       19275 :     DBRequest *request = new DBRequest;
      85       19275 :     request->oper = DBRequest::DB_ENTRY_ADD_CHANGE;
      86       19275 :     IFMapTable::RequestKey *key = new IFMapTable::RequestKey();
      87       19275 :     request->key.reset(key);
      88       19275 :     key->id_type = ltype;
      89       19275 :     key->id_name = lname;
      90       19275 :     IFMapServerTable::RequestData *data = new IFMapServerTable::RequestData();
      91       19275 :     request->data.reset(data);
      92       19275 :     data->metadata = linkname;
      93       19275 :     data->id_type = rtype;
      94       19275 :     data->id_name = rname;
      95       19275 :     data->origin.set_origin(IFMapOrigin::MAP_SERVER);
      96       19275 :     requests->push_back(request);
      97       19275 : }
      98             : 
      99       17916 : static void MapObjectUnlink(const string &ltype, const string &lname,
     100             :                             const string &rtype, const string &rname,
     101             :                             const string &linkname,
     102             :                             BgpConfigParser::RequestList *requests) {
     103       17916 :     DBRequest *request = new DBRequest;
     104       17916 :     request->oper = DBRequest::DB_ENTRY_DELETE;
     105       17916 :     IFMapTable::RequestKey *key = new IFMapTable::RequestKey();
     106       17916 :     request->key.reset(key);
     107       17916 :     key->id_type = ltype;
     108       17916 :     key->id_name = lname;
     109       17916 :     IFMapServerTable::RequestData *data = new IFMapServerTable::RequestData();
     110       17916 :     request->data.reset(data);
     111       17916 :     data->metadata = linkname;
     112       17916 :     data->id_type = rtype;
     113       17916 :     data->id_name = rname;
     114       17916 :     data->origin.set_origin(IFMapOrigin::MAP_SERVER);
     115       17916 :     requests->push_back(request);
     116       17916 : }
     117             : 
     118       43190 : static void MapObjectLinkAttr(const string &ltype, const string &lname,
     119             :                              const string &rtype, const string &rname,
     120             :                              const string &linkname, AutogenProperty *attr,
     121             :                              BgpConfigParser::RequestList *requests) {
     122       43190 :     DBRequest *request = new DBRequest;
     123       43190 :     request->oper = DBRequest::DB_ENTRY_ADD_CHANGE;
     124       43190 :     IFMapTable::RequestKey *key = new IFMapTable::RequestKey();
     125       43190 :     request->key.reset(key);
     126       43190 :     key->id_type = ltype;
     127       43190 :     key->id_name = lname;
     128       43190 :     IFMapServerTable::RequestData *data = new IFMapServerTable::RequestData();
     129       43190 :     request->data.reset(data);
     130       43190 :     data->metadata = linkname;
     131       43190 :     data->id_type = rtype;
     132       43190 :     data->id_name = rname;
     133       43190 :     data->content.reset(attr);
     134       43190 :     data->origin.set_origin(IFMapOrigin::MAP_SERVER);
     135       43190 :     requests->push_back(request);
     136       43190 : }
     137             : 
     138       25571 : static autogen::BgpSessionAttributes *GetPeeringSessionAttribute(
     139             :         const pair<string, string> &key, autogen::BgpPeeringAttributes *peer,
     140             :         int session_id, const string config_uuid) {
     141       25571 :     string uuid;
     142       25571 :     if (!config_uuid.empty()) {
     143       14480 :         uuid = config_uuid;
     144             :     } else {
     145       11091 :         uuid = BgpConfigParser::session_uuid(key.first, key.second, session_id);
     146             :     }
     147             : 
     148       25571 :     autogen::BgpSession *session = NULL;
     149       25571 :     for (vector<autogen::BgpSession>::iterator iter =
     150       25571 :             peer->session.begin();
     151       60213 :          iter != peer->session.end(); ++iter) {
     152       46235 :         if (iter->uuid == uuid) {
     153       11593 :             session = iter.operator->();
     154       11593 :             break;
     155             :         }
     156             :     }
     157       25571 :     if (session == NULL) {
     158       13978 :         peer->session.push_back(autogen::BgpSession());
     159       13978 :         session = &peer->session.back();
     160       13978 :         session->uuid = uuid;
     161             :     }
     162       25571 :     session->attributes.push_back(autogen::BgpSessionAttributes());
     163       25571 :     autogen::BgpSessionAttributes *sattr = &session->attributes.back();
     164       25571 :     return sattr;
     165       25571 : }
     166             : 
     167        7500 : static void MaybeMergeBidirectionalSessionParams(
     168             :         autogen::BgpPeeringAttributes *peer) {
     169        7500 : }
     170             : 
     171       38743 : static void BuildPeeringLinks(const string &instance,
     172             :                               const SessionMap &sessions,
     173             :                               BgpConfigParser::RequestList *requests) {
     174             :     typedef map<pair<string, string>, autogen::BgpPeeringAttributes *>
     175             :         PeeringMap;
     176       38743 :     PeeringMap peerings;
     177             : 
     178       38743 :     pair<string, string> sprev;
     179       38743 :     int session_id = 0;
     180       38743 :     for (SessionMap::const_iterator iter = sessions.begin();
     181       64314 :          iter != sessions.end(); ++iter) {
     182       25571 :         const string &left = iter->first.first;
     183       25571 :         const string &right = iter->first.second;
     184       25571 :         pair<string, string> key;
     185       25571 :         if (left <= right) {
     186       13978 :             key = make_pair(left, right);
     187             :         } else {
     188       11593 :             key = make_pair(right, left);
     189             :         }
     190             : 
     191       25571 :         string config_uuid = iter->second.second;
     192       25571 :         if ((sprev.first == left) && (sprev.second == right)) {
     193       12956 :             session_id++;
     194             :         } else {
     195       12615 :             session_id = 1;
     196       12615 :             sprev = make_pair(left, right);
     197             :         }
     198             : 
     199       25571 :         autogen::BgpPeeringAttributes *peer = NULL;
     200       25571 :         PeeringMap::iterator loc = peerings.find(key);
     201       25571 :         if (loc == peerings.end()) {
     202        7500 :             peer = new autogen::BgpPeeringAttributes();
     203        7500 :             peerings.insert(make_pair(key, peer));
     204             :         } else {
     205       18071 :             peer = loc->second;
     206             :         }
     207             :         // add uni-directional attributes for this session.
     208             :         autogen::BgpSessionAttributes *attrp =
     209       25571 :             GetPeeringSessionAttribute(key, peer, session_id, config_uuid);
     210       25571 :         attrp->Copy(iter->second.first);
     211       25571 :         attrp->bgp_router = left;
     212       25571 :     }
     213             : 
     214             :     // generate the links.
     215             :     // merging uni-directional attributes into a common attribute when they
     216             :     // are the same.
     217       46243 :     for (PeeringMap::iterator iter = peerings.begin(); iter != peerings.end();
     218        7500 :          ++iter) {
     219        7500 :         autogen::BgpPeeringAttributes *peer = iter->second;
     220        7500 :         MaybeMergeBidirectionalSessionParams(peer);
     221        7500 :         string left(instance + ':'), right(instance  + ':');
     222        7500 :         left.append(iter->first.first);
     223        7500 :         right.append(iter->first.second);
     224        7500 :         MapObjectLinkAttr("bgp-router", left, "bgp-router", right,
     225             :                           "bgp-peering", peer, requests);
     226        7500 :     }
     227       38743 : }
     228             : 
     229       14600 : static void RemovePeeringLinks(const string &instance,
     230             :                                const SessionMap &sessions,
     231             :                                BgpConfigParser::RequestList *requests) {
     232       14600 :     set<pair<string, string> > key_set;
     233             : 
     234       14600 :     for (SessionMap::const_iterator iter = sessions.begin();
     235       18820 :          iter != sessions.end(); ++iter) {
     236        4220 :         const string &left = iter->first.first;
     237        4220 :         const string &right = iter->first.second;
     238        4220 :         pair<string, string> key;
     239        4220 :         if (left <= right) {
     240        2112 :             key = make_pair(left, right);
     241             :         } else {
     242        2108 :             key = make_pair(right, left);
     243             :         }
     244        4220 :         if (key_set.count(key) > 0) {
     245        3647 :             continue;
     246             :         }
     247         573 :         key_set.insert(key);
     248         573 :         string id_left(instance + ':'), id_right(instance  + ':');
     249         573 :         id_left.append(key.first);
     250         573 :         id_right.append(key.second);
     251             : 
     252         573 :         MapObjectUnlink("bgp-router", id_left, "bgp-router", id_right,
     253             :                         "bgp-peering", requests);
     254        4220 :     }
     255       14600 : }
     256             : 
     257       29791 : static bool ParseSession(const string &identifier, const xml_node &node,
     258             :                          SessionMap *sessions) {
     259       29791 :     autogen::BgpSessionAttributes attr;
     260       29791 :     attr.Clear();
     261       29791 :     xml_attribute to = node.attribute("to");
     262       29791 :     assert(to);
     263       29791 :     assert(attr.XmlParse(node));
     264             : 
     265       29791 :     string to_value = to.value();
     266       29791 :     string to_name, uuid;
     267       29791 :     size_t pos = to_value.find(':');
     268       29791 :     if (pos == string::npos) {
     269       11110 :         to_name = to_value;
     270             :     } else {
     271       18681 :         to_name = to_value.substr(0, pos);
     272       18681 :         uuid = string(to_value, pos + 1);
     273             :     }
     274             : 
     275       29791 :     sessions->insert(
     276       59582 :         make_pair(make_pair(identifier, to_name), make_pair(attr, uuid)));
     277       29791 :     return true;
     278       29791 : }
     279             : 
     280         443 : static bool ParseServiceChain(const string &instance, const xml_node &node,
     281             :                               bool add_change, const string &sc_info,
     282             :                               BgpConfigParser::RequestList *requests) {
     283             :     unique_ptr<autogen::ServiceChainInfo> property(
     284         443 :         new autogen::ServiceChainInfo());
     285         443 :     property->sc_head = true;
     286         443 :     assert(property->XmlParse(node));
     287             : 
     288         443 :     if (add_change) {
     289         409 :         MapObjectSetProperty("routing-instance", instance,
     290         409 :             sc_info, property.release(), requests);
     291             :     } else {
     292          34 :         MapObjectClearProperty("routing-instance", instance,
     293             :             sc_info, requests);
     294             :     }
     295             : 
     296         443 :     return true;
     297         443 : }
     298             : 
     299         346 : static bool ParseInstanceRouteAggregate(const string &instance,
     300             :     const xml_node &node, bool add_change,
     301             :     BgpConfigParser::RequestList *requests) {
     302             : 
     303         346 :     xml_attribute to = node.attribute("to");
     304         346 :     assert(to);
     305         346 :     string aggregate_name = to.value();
     306         346 :     if (add_change) {
     307         222 :         MapObjectLinkAttr("routing-instance", instance,
     308             :             "route-aggregate", aggregate_name,
     309             :             "route-aggregate-routing-instance", NULL, requests);
     310             :     } else {
     311         124 :         MapObjectUnlink("routing-instance", instance,
     312             :             "route-aggregate", aggregate_name,
     313             :             "route-aggregate-routing-instance", requests);
     314             :     }
     315             : 
     316         346 :     return true;
     317         346 : }
     318             : 
     319         235 : static bool ParseInstanceRoutingPolicy(const string &instance,
     320             :     const xml_node &node, bool add_change,
     321             :     BgpConfigParser::RequestList *requests) {
     322             : 
     323         235 :     xml_attribute to = node.attribute("to");
     324         235 :     assert(to);
     325         235 :     string policy_name = to.value();
     326             :     unique_ptr<autogen::RoutingPolicyType> attr(
     327         235 :         new autogen::RoutingPolicyType());
     328         235 :     assert(attr->XmlParse(node));
     329         235 :     if (add_change) {
     330         187 :         MapObjectLinkAttr("routing-instance", instance,
     331             :             "routing-policy", policy_name,
     332         187 :             "routing-policy-routing-instance", attr.release(), requests);
     333             :     } else {
     334          48 :         MapObjectUnlink("routing-instance", instance,
     335             :             "routing-policy", policy_name,
     336             :             "routing-policy-routing-instance", requests);
     337             :     }
     338             : 
     339         235 :     return true;
     340         235 : }
     341             : 
     342          67 : static bool ParseStaticRoute(const string &instance, const xml_node &node,
     343             :                               bool add_change,
     344             :                               BgpConfigParser::RequestList *requests) {
     345             :     unique_ptr<autogen::StaticRouteEntriesType> property(
     346          67 :         new autogen::StaticRouteEntriesType());
     347          67 :     assert(property->XmlParse(node));
     348             : 
     349          67 :     if (add_change) {
     350          34 :         MapObjectSetProperty("routing-instance", instance,
     351          34 :             "static-route-entries", property.release(), requests);
     352             :     } else {
     353          33 :         MapObjectClearProperty("routing-instance", instance,
     354             :             "static-route-entries", requests);
     355             :     }
     356             : 
     357          67 :     return true;
     358          67 : }
     359             : 
     360          96 : static bool ParseInstanceHasPnf(const string &instance, const xml_node &node,
     361             :     bool add_change, BgpConfigParser::RequestList *requests) {
     362             :     unique_ptr<autogen::RoutingInstance::OolProperty> property(
     363          96 :         new autogen::RoutingInstance::OolProperty);
     364          96 :     property->data = (string(node.child_value()) == "true");
     365          96 :     if (add_change) {
     366          64 :         MapObjectSetProperty("routing-instance", instance,
     367          64 :             "routing-instance-has-pnf", property.release(), requests);
     368             :     } else {
     369          32 :         MapObjectClearProperty("routing-instance", instance,
     370             :             "routing-instance-has-pnf", requests);
     371             :     }
     372             : 
     373          96 :     return true;
     374          96 : }
     375             : 
     376       17905 : static bool ParseBgpRouter(const string &instance, const xml_node &node,
     377             :                            bool add_change, string *nodename,
     378             :                            SessionMap *sessions,
     379             :                            BgpConfigParser::RequestList *requests) {
     380             :     unique_ptr<autogen::BgpRouterParams> property(
     381       17905 :         new autogen::BgpRouterParams());
     382       17905 :     xml_attribute name = node.attribute("name");
     383       17905 :     assert(name);
     384       17905 :     string identifier = name.value();
     385       17905 :     assert(property->XmlParse(node));
     386             : 
     387       17905 :     if (property->autonomous_system == 0) {
     388        5113 :         property->autonomous_system =
     389        5113 :             BgpConfigManager::kDefaultAutonomousSystem;
     390             :     }
     391       17905 :     if (property->identifier.empty()) {
     392        8168 :         property->identifier = property->address;
     393             :     }
     394             : 
     395       17905 :     bool has_sessions = false;
     396       47696 :     for (xml_node xsession = node.child("session"); xsession;
     397       29791 :          xsession = xsession.next_sibling("session")) {
     398       29791 :         has_sessions = true;
     399       29791 :         ParseSession(identifier, xsession, sessions);
     400             :     }
     401             : 
     402       17905 :     string fqname(instance + ":" + identifier);
     403       17905 :     if (!has_sessions) {
     404        6691 :         *nodename = fqname;
     405             :     }
     406             : 
     407       17905 :     string subcluster_name;
     408       17905 :     if (node.child("sub-cluster")) {
     409          16 :         xml_attribute sc = node.child("sub-cluster").attribute("name");
     410          16 :         subcluster_name = sc.value();
     411          16 :         assert(!subcluster_name.empty());
     412             :     }
     413             : 
     414       17905 :     if (add_change) {
     415       14483 :         MapObjectLink("routing-instance", instance,
     416             :             "bgp-router", fqname, "instance-bgp-router", requests);
     417       14483 :         MapObjectSetProperty("bgp-router", fqname,
     418       14483 :             "bgp-router-parameters", property.release(), requests);
     419       14483 :         if (!subcluster_name.empty()) {
     420          16 :             MapObjectLink("bgp-router", fqname, "sub-cluster", subcluster_name,
     421             :                           "bgp-router-sub-cluster", requests);
     422             :         }
     423             :     } else {
     424        3422 :         MapObjectClearProperty("bgp-router", fqname,
     425             :             "bgp-router-parameters", requests);
     426        3422 :         MapObjectUnlink("routing-instance", instance,
     427             :             "bgp-router", fqname, "instance-bgp-router", requests);
     428        3422 :         if (!subcluster_name.empty()) {
     429           0 :             MapObjectUnlink("bgp-router", fqname, "sub-cluster",
     430             :                     subcluster_name, "bgp-router-sub-cluster", requests);
     431             :         }
     432             :     }
     433             : 
     434       17905 :     return true;
     435       17905 : }
     436             : 
     437             : // Creates a full-mesh of links between all the routers that have been
     438             : // defined.
     439       38743 : static void AddNeighborMesh(const list<string> &routers,
     440             :                             BgpConfigParser::RequestList *requests) {
     441       38743 :     for (list<string>::const_iterator iter = routers.begin();
     442       43124 :          iter != routers.end(); ) {
     443        4381 :         const string &left = *iter;
     444        4381 :         ++iter;
     445        4381 :         for (list<string>::const_iterator tgt = iter;
     446        4633 :              tgt != routers.end(); ++tgt) {
     447         252 :             MapObjectLink("bgp-router", left, "bgp-router", *tgt, "bgp-peering",
     448             :                          requests);
     449             :         }
     450             :     }
     451       38743 : }
     452             : 
     453       14600 : static void DeleteNeighborMesh(const list<string> &routers,
     454             :                                BgpConfigParser::RequestList *requests) {
     455       14600 :     for (list<string>::const_iterator iter = routers.begin();
     456       16910 :          iter != routers.end(); ) {
     457        2310 :         const string &left = *iter;
     458        2310 :         ++iter;
     459        2310 :         for (list<string>::const_iterator tgt = iter;
     460        4571 :              tgt != routers.end(); ++tgt) {
     461        2261 :             MapObjectUnlink("bgp-router", left, "bgp-router", *tgt,
     462             :                 "bgp-peering", requests);
     463             :         }
     464             :     }
     465       14600 : }
     466             : 
     467       45880 : static bool ParseInstanceTarget(const string &instance, const xml_node &node,
     468             :                                 bool add_change,
     469             :                                 BgpConfigParser::RequestList *requests) {
     470       45880 :     string rtarget(node.child_value());
     471       45880 :     boost::trim(rtarget);
     472       45880 :     boost::system::error_code parse_err;
     473       45880 :     RouteTarget::FromString(rtarget, &parse_err);
     474       45880 :     assert(!parse_err);
     475             : 
     476             :     unique_ptr<autogen::InstanceTargetType> params(
     477       45880 :         new autogen::InstanceTargetType());
     478       45880 :     assert(params->XmlParse(node));
     479             : 
     480       45880 :     if (add_change) {
     481       35281 :         MapObjectLinkAttr("routing-instance", instance, "route-target", rtarget,
     482       35281 :             "instance-target", params.release(), requests);
     483             :     } else {
     484       10599 :         MapObjectUnlink("routing-instance", instance, "route-target", rtarget,
     485             :             "instance-target", requests);
     486             :     }
     487             : 
     488       45880 :     return true;
     489       45880 : }
     490             : 
     491        5413 : static bool ParseInstanceVirtualNetwork(const string &instance,
     492             :     const xml_node &node, bool add_change,
     493             :     BgpConfigParser::RequestList *requests) {
     494        5413 :     string vn_name = node.child_value();
     495        5413 :     if (add_change) {
     496        4524 :         MapObjectLink("routing-instance", instance,
     497             :             "virtual-network", vn_name,
     498             :             "virtual-network-routing-instance", requests);
     499             :     } else {
     500         889 :         MapObjectUnlink("routing-instance", instance,
     501             :             "virtual-network", vn_name,
     502             :             "virtual-network-routing-instance", requests);
     503             :     }
     504             : 
     505        5413 :     return true;
     506        5413 : }
     507             : 
     508             : }  // namespace
     509             : 
     510       14665 : BgpConfigParser::BgpConfigParser(DB *db)
     511       14665 :         : db_(db) {
     512       14665 : }
     513             : 
     514       37452 : bool BgpConfigParser::ParseRoutingInstance(const xml_node &parent,
     515             :                                            bool add_change,
     516             :                                            RequestList *requests) const {
     517       37452 :     string instance(parent.attribute("name").value());
     518       37452 :     assert(!instance.empty());
     519             : 
     520       37452 :     SessionMap sessions;
     521       37452 :     list<string> routers;
     522             : 
     523       92248 :     for (xml_node node = parent.first_child(); node;
     524       54796 :          node = node.next_sibling()) {
     525       54796 :         if (strcmp(node.name(), "bgp-router") == 0) {
     526        2252 :             string router_name;
     527        2252 :             ParseBgpRouter(instance, node, add_change, &router_name,
     528             :                            &sessions, requests);
     529        2252 :             if (!router_name.empty()) {
     530         961 :                 routers.push_back(router_name);
     531             :             }
     532       54796 :         } else if (strcmp(node.name(), "vrf-target") == 0) {
     533       45880 :             ParseInstanceTarget(instance, node, add_change, requests);
     534        6664 :         } else if (strcmp(node.name(), "virtual-network") == 0) {
     535        5413 :             ParseInstanceVirtualNetwork(instance, node, add_change, requests);
     536        1251 :         } else if (strcmp(node.name(), "service-chain-info") == 0) {
     537         167 :             ParseServiceChain(instance, node, add_change,
     538             :                               "service-chain-information", requests);
     539        1084 :         } else if (strcmp(node.name(), "ipv6-service-chain-info") == 0) {
     540          92 :             ParseServiceChain(instance, node, add_change,
     541             :                               "ipv6-service-chain-information", requests);
     542         992 :         } else if (strcmp(node.name(), "evpn-service-chain-info") == 0) {
     543          92 :             ParseServiceChain(instance, node, add_change,
     544             :                               "evpn-service-chain-information", requests);
     545         900 :         } else if (strcmp(node.name(), "evpn-ipv6-service-chain-info") == 0) {
     546          92 :             ParseServiceChain(instance, node, add_change,
     547             :                               "evpn-ipv6-service-chain-information", requests);
     548         808 :         } else if (strcmp(node.name(), "route-aggregate") == 0) {
     549         346 :             ParseInstanceRouteAggregate(instance, node, add_change, requests);
     550         462 :         } else if (strcmp(node.name(), "routing-policy") == 0) {
     551         235 :             ParseInstanceRoutingPolicy(instance, node, add_change, requests);
     552         227 :         } else if (strcmp(node.name(), "static-route-entries") == 0) {
     553          67 :             ParseStaticRoute(instance, node, add_change, requests);
     554         160 :         } else if (strcmp(node.name(), "routing-instance-has-pnf") == 0) {
     555          96 :             ParseInstanceHasPnf(instance, node, add_change, requests);
     556             :         }
     557             :     }
     558             : 
     559       37452 :     if (add_change) {
     560       27118 :         BuildPeeringLinks(instance, sessions, requests);
     561             :         // Generate a full mesh of peering sessions for neighbors that do not
     562             :         // specify session attributes.
     563       27118 :         AddNeighborMesh(routers, requests);
     564             :     } else {
     565       10334 :         RemovePeeringLinks(instance, sessions, requests);
     566       10334 :         DeleteNeighborMesh(routers, requests);
     567             :     }
     568       37452 :     return true;
     569       37452 : }
     570             : 
     571        4593 : bool BgpConfigParser::ParseVirtualNetwork(const xml_node &node,
     572             :                                           bool add_change,
     573             :                                           RequestList *requests) const {
     574             :     // vn name
     575        4593 :     string vn_name(node.attribute("name").value());
     576        4593 :     assert(!vn_name.empty());
     577             : 
     578             :     unique_ptr<autogen::VirtualNetwork::OolProperty> pbb_property(
     579        4593 :         new autogen::VirtualNetwork::OolProperty);
     580        4593 :     pbb_property->data = false;
     581             : 
     582        4593 :     if (node.attribute("pbb-evpn-enable")) {
     583         132 :         pbb_property->data =
     584         264 :             (string(node.attribute("pbb-evpn-enable").value()) == "true");
     585             :     }
     586             : 
     587             :     unique_ptr<autogen::VirtualNetworkType> property(
     588        4593 :         new autogen::VirtualNetworkType());
     589        4593 :     assert(property->XmlParse(node));
     590             : 
     591        4593 :     if (add_change) {
     592        3704 :         MapObjectSetProperty("virtual-network", vn_name,
     593        3704 :             "virtual-network-properties", property.release(), requests);
     594        3704 :         MapObjectSetProperty("virtual-network", vn_name,
     595        3704 :             "pbb-evpn-enable", pbb_property.release(), requests);
     596             :     } else {
     597         889 :         MapObjectClearProperty("virtual-network", vn_name,
     598             :             "virtual-network-properties", requests);
     599         889 :         MapObjectClearProperty("virtual-network", vn_name,
     600             :             "pbb-evpn-enable", requests);
     601             :     }
     602             : 
     603        4593 :     return true;
     604        4593 : }
     605             : 
     606          16 : bool BgpConfigParser::ParseSubCluster(const xml_node &node,
     607             :                                       bool add_change,
     608             :                                       RequestList *requests) const {
     609          16 :     string subcluster_name(node.attribute("name").value());
     610          16 :     assert(!subcluster_name.empty());
     611             : 
     612             :     unique_ptr<autogen::SubCluster::StringProperty> subcluster_property(
     613          16 :         new autogen::SubCluster::StringProperty);
     614             : 
     615          16 :     if (node.child("sub-cluster-asn"))
     616          16 :         subcluster_property->data = string(node.child_value("sub-cluster-asn"));
     617             : 
     618          16 :     if (add_change) {
     619          16 :         MapObjectSetProperty("sub-cluster", subcluster_name,
     620          16 :             "sub-cluster-asn", subcluster_property.release(), requests);
     621             :     } else {
     622           0 :         MapObjectClearProperty("sub-cluster", subcluster_name,
     623             :                                "sub-cluster-asn", requests);
     624             :     }
     625             : 
     626             :     unique_ptr<autogen::SubCluster::NtProperty> id_property(
     627          16 :         new autogen::SubCluster::NtProperty);
     628          16 :     if (node.child("sub-cluster-id")) {
     629             :         std::stringstream sub_cluster_id(
     630           0 :                 string(node.child_value("sub-cluster-id")));
     631           0 :         sub_cluster_id >> id_property->data;
     632           0 :     }
     633          16 :     if (add_change) {
     634          16 :         MapObjectSetProperty("sub-cluster", subcluster_name,
     635          16 :             "sub-cluster-id", id_property.release(), requests);
     636             :     } else {
     637           0 :         MapObjectClearProperty("sub-cluster", subcluster_name,
     638             :                                "sub-cluster-id", requests);
     639             :     }
     640          16 :     return true;
     641          16 : }
     642             : 
     643         344 : bool BgpConfigParser::ParseRouteAggregate(const xml_node &node,
     644             :                                           bool add_change,
     645             :                                           RequestList *requests) const {
     646             :     // policy name
     647         344 :     string aggregate_name(node.attribute("name").value());
     648         344 :     assert(!aggregate_name.empty());
     649             : 
     650             : 
     651        1032 :     for (xml_node child = node.first_child(); child;
     652         688 :          child = child.next_sibling()) {
     653         688 :         if (strcmp(child.name(), "aggregate-route-entries") == 0) {
     654         344 :             if (add_change) {
     655             :                 unique_ptr<autogen::RouteListType>
     656         222 :                     aggregate_routes(new autogen::RouteListType());
     657         222 :                 assert(aggregate_routes->XmlParse(child));
     658         222 :                 MapObjectSetProperty("route-aggregate", aggregate_name,
     659             :                                      "aggregate-route-entries",
     660         222 :                                      aggregate_routes.release(), requests);
     661         222 :             } else {
     662         122 :                 MapObjectClearProperty("route-aggregate", aggregate_name,
     663             :                                        "aggregate-route-entries", requests);
     664             :             }
     665         344 :         } else if (strcmp(child.name(), "nexthop") == 0) {
     666         344 :             if (add_change) {
     667         222 :                 string nexthop = child.child_value();
     668             : 
     669             :                 autogen::RouteAggregate::StringProperty *nexthop_property =
     670         222 :                     new autogen::RouteAggregate::StringProperty();
     671         222 :                 nexthop_property->data = nexthop;
     672         222 :                 MapObjectSetProperty("route-aggregate", aggregate_name,
     673             :                                      "aggregate-route-nexthop",
     674             :                                      nexthop_property, requests);
     675         222 :             } else {
     676         122 :                 MapObjectClearProperty("route-aggregate", aggregate_name,
     677             :                                        "aggregate-route-nexthop", requests);
     678             :             }
     679             :         }
     680             :     }
     681             : 
     682         344 :     return true;
     683         344 : }
     684             : 
     685         230 : bool BgpConfigParser::ParseRoutingPolicy(const xml_node &node,
     686             :                                           bool add_change,
     687             :                                           RequestList *requests) const {
     688             :     // policy name
     689         230 :     string policy_name(node.attribute("name").value());
     690         230 :     assert(!policy_name.empty());
     691             : 
     692             :     unique_ptr<autogen::PolicyStatementType> policy_statement(
     693         230 :         new autogen::PolicyStatementType());
     694         230 :     assert(policy_statement->XmlParse(node));
     695             : 
     696         230 :     if (add_change) {
     697         187 :         MapObjectSetProperty("routing-policy", policy_name,
     698         187 :             "routing-policy-entries", policy_statement.release(), requests);
     699             :     } else {
     700          43 :         MapObjectClearProperty("routing-policy", policy_name,
     701             :             "routing-policy-entries", requests);
     702             :     }
     703             : 
     704         230 :     return true;
     705         230 : }
     706             : 
     707        1137 : bool BgpConfigParser::ParseGlobalSystemConfig(const xml_node &node,
     708             :                                               bool add_change,
     709             :                                               RequestList *requests) const {
     710        2560 :     for (xml_node child = node.first_child(); child;
     711        1423 :             child = child.next_sibling()) {
     712        1423 :         if (strcmp(child.name(), "graceful-restart-parameters") == 0) {
     713             :             unique_ptr<autogen::GracefulRestartParametersType> gr_config(
     714         697 :                     new autogen::GracefulRestartParametersType());
     715         697 :             assert(gr_config->XmlParse(child));
     716             : 
     717         697 :             if (add_change) {
     718         694 :                 MapObjectSetProperty("global-system-config", "",
     719             :                     "graceful-restart-parameters",
     720         694 :                     gr_config.release(), requests);
     721             :             } else {
     722           3 :                 MapObjectClearProperty("global-system-config", "",
     723             :                                        "graceful-restart-parameters", requests);
     724             :             }
     725         697 :         }
     726        1423 :         if (strcmp(child.name(), "bgpaas-parameters") == 0) {
     727             :             unique_ptr<autogen::BGPaaServiceParametersType> bgpaas_config(
     728         278 :                     new autogen::BGPaaServiceParametersType());
     729         278 :             assert(bgpaas_config->XmlParse(child));
     730             : 
     731         278 :             if (add_change) {
     732         274 :                 MapObjectSetProperty("global-system-config", "",
     733         274 :                     "bgpaas-parameters", bgpaas_config.release(), requests);
     734             :             } else {
     735           4 :                 MapObjectClearProperty("global-system-config", "",
     736             :                                        "bgpaas-parameters", requests);
     737             :             }
     738         278 :         }
     739        1423 :         if (strcmp(child.name(), "bgp-always-compare-med") == 0) {
     740             :             unique_ptr<autogen::GlobalSystemConfig::OolProperty> property(
     741           8 :                 new autogen::GlobalSystemConfig::OolProperty);
     742           8 :             property->data = (string(child.child_value()) == "true");
     743           8 :             if (add_change) {
     744           5 :                 MapObjectSetProperty("global-system-config", "",
     745           5 :                     "bgp-always-compare-med", property.release(), requests);
     746             :             } else {
     747           3 :                 MapObjectClearProperty("global-system-config", "",
     748             :                     "bgp-always-compare-med", requests);
     749             :             }
     750           8 :         }
     751        1423 :         if (strcmp(child.name(), "bgp-all-tags-are-global") == 0) {
     752             :             unique_ptr<autogen::GlobalSystemConfig::OolProperty> property(
     753           5 :                 new autogen::GlobalSystemConfig::OolProperty);
     754           5 :             property->data = (string(child.child_value()) == "true");
     755           5 :             if (add_change) {
     756           4 :                 MapObjectSetProperty("global-system-config", "",
     757           4 :                     "bgp-all-tags-are-global", property.release(), requests);
     758             :             } else {
     759           1 :                 MapObjectClearProperty("global-system-config", "",
     760             :                     "bgp-all-tags-are-global", requests);
     761             :             }
     762           5 :         }
     763        1423 :         if (strcmp(child.name(), "enable-4byte-as") == 0) {
     764             :             unique_ptr<autogen::GlobalSystemConfig::OolProperty> property(
     765         384 :                 new autogen::GlobalSystemConfig::OolProperty);
     766         384 :             property->data = (string(child.child_value()) == "true");
     767         384 :             if (add_change) {
     768         382 :                 MapObjectSetProperty("global-system-config", "",
     769         382 :                     "enable-4byte-as", property.release(), requests);
     770             :             } else {
     771           2 :                 MapObjectClearProperty("global-system-config", "",
     772             :                     "enable-4byte-as", requests);
     773             :             }
     774         384 :         }
     775        1423 :         if (strcmp(child.name(), "fast-convergence-parameters") == 0) {
     776             :             unique_ptr<autogen::FastConvergenceParametersType> property(
     777          20 :                     new autogen::FastConvergenceParametersType());
     778          20 :             assert(property->XmlParse(child));
     779          20 :             if (add_change) {
     780          19 :                 MapObjectSetProperty("global-system-config", "",
     781          19 :                     "fast-convergence-parameters", property.release(), requests);
     782             :             } else {
     783           1 :                 MapObjectClearProperty("global-system-config", "",
     784             :                     "fast-convergence-parameters", requests);
     785             :             }
     786          20 :         }
     787        1423 :         if (strcmp(child.name(), "rd-cluster-seed") == 0) {
     788             :             unique_ptr<autogen::GlobalSystemConfig::NtProperty> property(
     789          27 :                 new autogen::GlobalSystemConfig::NtProperty);
     790          27 :             property->data = atoi(child.child_value());
     791          27 :             if (add_change) {
     792          25 :                 MapObjectSetProperty("global-system-config", "",
     793          25 :                     "rd-cluster-seed", property.release(), requests);
     794             :             } else {
     795           2 :                 MapObjectClearProperty("global-system-config", "",
     796             :                     "rd-cluster-seed", requests);
     797             :             }
     798          27 :         }
     799             :     }
     800        1137 :     return true;
     801             : }
     802             : 
     803          10 : bool BgpConfigParser::ParseGlobalQosConfig(const xml_node &node,
     804             :                                            bool add_change,
     805             :                                            RequestList *requests) const {
     806          20 :     for (xml_node child = node.first_child(); child;
     807          10 :             child = child.next_sibling()) {
     808          10 :         if (strcmp(child.name(), "control-traffic-dscp") == 0) {
     809             :             unique_ptr<autogen::ControlTrafficDscpType> cfg(
     810          10 :                     new autogen::ControlTrafficDscpType());
     811          10 :             assert(cfg->XmlParse(child));
     812             : 
     813          10 :             if (add_change) {
     814           9 :                 MapObjectSetProperty("global-qos-config", "",
     815           9 :                     "control-traffic-dscp", cfg.release(), requests);
     816             :             } else {
     817           1 :                 MapObjectClearProperty("global-qos-config", "",
     818             :                                        "control-traffic-dscp", requests);
     819             :             }
     820          10 :         }
     821             :     }
     822          10 :     return true;
     823             : }
     824             : 
     825       15891 : bool BgpConfigParser::ParseConfig(const xml_node &root, bool add_change,
     826             :                                   RequestList *requests) const {
     827       15891 :     SessionMap sessions;
     828       15891 :     list<string> routers;
     829             : 
     830       75358 :     for (xml_node node = root.first_child(); node; node = node.next_sibling()) {
     831       59467 :         if (strcmp(node.name(), "bgp-router") == 0) {
     832       15653 :             string router_name;
     833       15653 :             ParseBgpRouter(BgpConfigManager::kMasterInstance, node, add_change,
     834             :                            &router_name, &sessions, requests);
     835       15653 :             if (!router_name.empty()) {
     836        5730 :                 routers.push_back(router_name);
     837             :             }
     838       15653 :         }
     839       59467 :         if (strcmp(node.name(), "routing-instance") == 0) {
     840       37452 :             ParseRoutingInstance(node, add_change, requests);
     841             :         }
     842       59467 :         if (strcmp(node.name(), "virtual-network") == 0) {
     843        4593 :             ParseVirtualNetwork(node, add_change, requests);
     844             :         }
     845       59467 :         if (strcmp(node.name(), "sub-cluster") == 0) {
     846          16 :             ParseSubCluster(node, add_change, requests);
     847             :         }
     848       59467 :         if (strcmp(node.name(), "route-aggregate") == 0) {
     849         344 :             ParseRouteAggregate(node, add_change, requests);
     850             :         }
     851       59467 :         if (strcmp(node.name(), "routing-policy") == 0) {
     852         230 :             ParseRoutingPolicy(node, add_change, requests);
     853             :         }
     854       59467 :         if (strcmp(node.name(), "global-system-config") == 0) {
     855        1137 :             ParseGlobalSystemConfig(node, add_change, requests);
     856             :         }
     857       59467 :         if (strcmp(node.name(), "global-qos-config") == 0) {
     858          10 :             ParseGlobalQosConfig(node, add_change, requests);
     859             :         }
     860             :     }
     861             : 
     862       15891 :     if (add_change) {
     863       11625 :         BuildPeeringLinks(BgpConfigManager::kMasterInstance, sessions,
     864             :                           requests);
     865             :         // Generate a full mesh of peering sessions for neighbors that do not
     866             :         // specify session attributes.
     867       11625 :         AddNeighborMesh(routers, requests);
     868             :     } else {
     869        4266 :         RemovePeeringLinks(BgpConfigManager::kMasterInstance, sessions,
     870             :                            requests);
     871        4266 :         DeleteNeighborMesh(routers, requests);
     872             :     }
     873             : 
     874       15891 :     return true;
     875       15891 : }
     876             : 
     877       15891 : bool BgpConfigParser::Parse(const string &content)  {
     878       15891 :     istringstream sstream(content);
     879       15891 :     xml_document xdoc;
     880       15891 :     xml_parse_result result = xdoc.load(sstream);
     881       15891 :     if (result.status == pugi::status_no_document_element) {
     882           0 :         return true;
     883             :     }
     884             : 
     885       15891 :     if (result.status == pugi::status_ok) {
     886       15891 :         RequestList requests;
     887       31782 :         for (xml_node node = xdoc.first_child(); node; node = node.next_sibling()) {
     888       15891 :             const char *oper = node.name();
     889       15891 :             assert((strcmp(oper, "config") == 0) || (strcmp(oper, "delete") == 0));
     890       15891 :             bool add_change = (strcmp(oper, "config") == 0);
     891       15891 :             assert(ParseConfig(node, add_change, &requests));
     892             :         }
     893             : 
     894      126348 :         while (!requests.empty()) {
     895      110457 :             unique_ptr<DBRequest> req(requests.front());
     896      110457 :             requests.pop_front();
     897             : 
     898             :             IFMapTable::RequestKey *key =
     899      110457 :                     static_cast<IFMapTable::RequestKey *>(req->key.get());
     900             : 
     901      110457 :             IFMapTable *table = IFMapTable::FindTable(db_, key->id_type);
     902      110457 :             assert(table);
     903      110457 :             table->Enqueue(req.get());
     904      110457 :         }
     905             : 
     906       15891 :         return true;
     907       15891 :     }
     908           0 :     return false;
     909       15891 : }
     910             : 
     911       13529 : string BgpConfigParser::session_uuid(const string &left, const string &right,
     912             :                                      int index) {
     913             :     boost::uuids::nil_generator nil;
     914       13529 :     boost::uuids::name_generator gen(nil());
     915             :     boost::uuids::uuid uuid;
     916       13529 :     ostringstream oss;
     917       13529 :     oss << left << ":" << right << ":" << index;
     918       13529 :     uuid = gen(oss.str());
     919       27058 :     return boost::uuids::to_string(uuid);
     920       13529 : }

Generated by: LCOV version 1.14