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

Generated by: LCOV version 1.14