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

Generated by: LCOV version 1.14