7 #include <boost/uuid/name_generator.hpp>
8 #include <pugixml/pugixml.hpp>
21 #include "schema/bgp_schema_types.h"
22 #include "schema/vnc_cfg_types.h"
24 using pugi::xml_attribute;
25 using pugi::xml_document;
27 using pugi::xml_parse_result;
28 using std::unique_ptr;
29 using std::istringstream;
31 using std::ostringstream;
42 pair<autogen::BgpSessionAttributes, string> >
SessionMap;
46 static void MapObjectSetProperty(
const string <ype,
const string &lname,
47 const string &propname,
53 request->
key.reset(key);
57 request->
data.reset(data);
61 requests->push_back(request);
64 static void MapObjectClearProperty(
const string <ype,
const string &lname,
65 const string &propname,
70 request->
key.reset(key);
74 request->
data.reset(data);
77 requests->push_back(request);
80 static void MapObjectLink(
const string <ype,
const string &lname,
81 const string &rtype,
const string &rname,
82 const string &linkname,
87 request->
key.reset(key);
91 request->
data.reset(data);
96 requests->push_back(request);
99 static void MapObjectUnlink(
const string <ype,
const string &lname,
100 const string &rtype,
const string &rname,
101 const string &linkname,
106 request->
key.reset(key);
110 request->
data.reset(data);
115 requests->push_back(request);
118 static void MapObjectLinkAttr(
const string <ype,
const string &lname,
119 const string &rtype,
const string &rname,
125 request->
key.reset(key);
129 request->
data.reset(data);
135 requests->push_back(request);
138 static autogen::BgpSessionAttributes *GetPeeringSessionAttribute(
139 const pair<string, string> &key, autogen::BgpPeeringAttributes *peer,
140 int session_id,
const string config_uuid) {
142 if (!config_uuid.empty()) {
148 autogen::BgpSession *session = NULL;
149 for (vector<autogen::BgpSession>::iterator iter =
150 peer->session.begin();
151 iter != peer->session.end(); ++iter) {
152 if (iter->uuid == uuid) {
153 session = iter.operator->();
157 if (session == NULL) {
158 peer->session.push_back(autogen::BgpSession());
159 session = &peer->session.back();
160 session->uuid =
uuid;
162 session->attributes.push_back(autogen::BgpSessionAttributes());
163 autogen::BgpSessionAttributes *sattr = &session->attributes.back();
167 static void MaybeMergeBidirectionalSessionParams(
168 autogen::BgpPeeringAttributes *peer) {
171 static void BuildPeeringLinks(
const string &instance,
174 typedef map<pair<string, string>, autogen::BgpPeeringAttributes *>
178 pair<string, string> sprev;
180 for (SessionMap::const_iterator iter = sessions.begin();
181 iter != sessions.end(); ++iter) {
182 const string &left = iter->first.first;
183 const string &right = iter->first.second;
184 pair<string, string> key;
186 key = make_pair(left, right);
188 key = make_pair(right, left);
191 string config_uuid = iter->second.second;
192 if ((sprev.first == left) && (sprev.second == right)) {
196 sprev = make_pair(left, right);
199 autogen::BgpPeeringAttributes *peer = NULL;
200 PeeringMap::iterator loc = peerings.find(key);
201 if (loc == peerings.end()) {
202 peer =
new autogen::BgpPeeringAttributes();
203 peerings.insert(make_pair(key, peer));
208 autogen::BgpSessionAttributes *attrp =
209 GetPeeringSessionAttribute(key, peer, session_id, config_uuid);
210 attrp->Copy(iter->second.first);
211 attrp->bgp_router = left;
217 for (PeeringMap::iterator iter = peerings.begin(); iter != peerings.end();
219 autogen::BgpPeeringAttributes *peer = iter->second;
220 MaybeMergeBidirectionalSessionParams(peer);
221 string left(instance +
':'), right(instance +
':');
222 left.append(iter->first.first);
223 right.append(iter->first.second);
224 MapObjectLinkAttr(
"bgp-router", left,
"bgp-router", right,
225 "bgp-peering", peer, requests);
229 static void RemovePeeringLinks(
const string &instance,
232 set<pair<string, string> > key_set;
234 for (SessionMap::const_iterator iter = sessions.begin();
235 iter != sessions.end(); ++iter) {
236 const string &left = iter->first.first;
237 const string &right = iter->first.second;
238 pair<string, string> key;
240 key = make_pair(left, right);
242 key = make_pair(right, left);
244 if (key_set.count(key) > 0) {
248 string id_left(instance +
':'), id_right(instance +
':');
249 id_left.append(key.first);
250 id_right.append(key.second);
252 MapObjectUnlink(
"bgp-router", id_left,
"bgp-router", id_right,
253 "bgp-peering", requests);
257 static bool ParseSession(
const string &identifier,
const xml_node &node,
259 autogen::BgpSessionAttributes attr;
261 xml_attribute to = node.attribute(
"to");
263 assert(attr.XmlParse(node));
265 string to_value = to.value();
266 string to_name,
uuid;
267 size_t pos = to_value.find(
':');
268 if (pos == string::npos) {
271 to_name = to_value.substr(0, pos);
272 uuid = string(to_value, pos + 1);
276 make_pair(make_pair(identifier, to_name), make_pair(attr, uuid)));
280 static bool ParseServiceChain(
const string &instance,
const xml_node &node,
281 bool add_change,
const string &sc_info,
283 unique_ptr<autogen::ServiceChainInfo> property(
284 new autogen::ServiceChainInfo());
285 property->sc_head =
true;
286 assert(property->XmlParse(node));
289 MapObjectSetProperty(
"routing-instance", instance,
290 sc_info, property.release(), requests);
292 MapObjectClearProperty(
"routing-instance", instance,
299 static bool ParseInstanceRouteAggregate(
const string &instance,
300 const xml_node &node,
bool add_change,
303 xml_attribute to = node.attribute(
"to");
305 string aggregate_name = to.value();
307 MapObjectLinkAttr(
"routing-instance", instance,
308 "route-aggregate", aggregate_name,
309 "route-aggregate-routing-instance", NULL, requests);
311 MapObjectUnlink(
"routing-instance", instance,
312 "route-aggregate", aggregate_name,
313 "route-aggregate-routing-instance", requests);
319 static bool ParseInstanceRoutingPolicy(
const string &instance,
320 const xml_node &node,
bool add_change,
323 xml_attribute to = node.attribute(
"to");
325 string policy_name = to.value();
326 unique_ptr<autogen::RoutingPolicyType> attr(
327 new autogen::RoutingPolicyType());
328 assert(attr->XmlParse(node));
330 MapObjectLinkAttr(
"routing-instance", instance,
331 "routing-policy", policy_name,
332 "routing-policy-routing-instance", attr.release(), requests);
334 MapObjectUnlink(
"routing-instance", instance,
335 "routing-policy", policy_name,
336 "routing-policy-routing-instance", requests);
342 static bool ParseStaticRoute(
const string &instance,
const xml_node &node,
345 unique_ptr<autogen::StaticRouteEntriesType> property(
346 new autogen::StaticRouteEntriesType());
347 assert(property->XmlParse(node));
350 MapObjectSetProperty(
"routing-instance", instance,
351 "static-route-entries", property.release(), requests);
353 MapObjectClearProperty(
"routing-instance", instance,
354 "static-route-entries", requests);
360 static bool ParseInstanceHasPnf(
const string &instance,
const xml_node &node,
362 unique_ptr<autogen::RoutingInstance::OolProperty> property(
363 new autogen::RoutingInstance::OolProperty);
364 property->data = (string(node.child_value()) ==
"true");
366 MapObjectSetProperty(
"routing-instance", instance,
367 "routing-instance-has-pnf", property.release(), requests);
369 MapObjectClearProperty(
"routing-instance", instance,
370 "routing-instance-has-pnf", requests);
376 static bool ParseBgpRouter(
const string &instance,
const xml_node &node,
377 bool add_change,
string *nodename,
380 unique_ptr<autogen::BgpRouterParams> property(
381 new autogen::BgpRouterParams());
382 xml_attribute name = node.attribute(
"name");
384 string identifier = name.value();
385 assert(property->XmlParse(node));
387 if (property->autonomous_system == 0) {
388 property->autonomous_system =
391 if (property->identifier.empty()) {
392 property->identifier =
property->address;
395 bool has_sessions =
false;
396 for (xml_node xsession = node.child(
"session"); xsession;
397 xsession = xsession.next_sibling(
"session")) {
399 ParseSession(identifier, xsession, sessions);
402 string fqname(instance +
":" + identifier);
407 string subcluster_name;
408 if (node.child(
"sub-cluster")) {
409 xml_attribute sc = node.child(
"sub-cluster").attribute(
"name");
410 subcluster_name = sc.value();
411 assert(!subcluster_name.empty());
415 MapObjectLink(
"routing-instance", instance,
416 "bgp-router", fqname,
"instance-bgp-router", requests);
417 MapObjectSetProperty(
"bgp-router", fqname,
418 "bgp-router-parameters", property.release(), requests);
419 if (!subcluster_name.empty()) {
420 MapObjectLink(
"bgp-router", fqname,
"sub-cluster", subcluster_name,
421 "bgp-router-sub-cluster", requests);
424 MapObjectClearProperty(
"bgp-router", fqname,
425 "bgp-router-parameters", requests);
426 MapObjectUnlink(
"routing-instance", instance,
427 "bgp-router", fqname,
"instance-bgp-router", requests);
428 if (!subcluster_name.empty()) {
429 MapObjectUnlink(
"bgp-router", fqname,
"sub-cluster",
430 subcluster_name,
"bgp-router-sub-cluster", requests);
439 static void AddNeighborMesh(
const list<string> &routers,
441 for (list<string>::const_iterator iter = routers.begin();
442 iter != routers.end(); ) {
443 const string &left = *iter;
445 for (list<string>::const_iterator tgt = iter;
446 tgt != routers.end(); ++tgt) {
447 MapObjectLink(
"bgp-router", left,
"bgp-router", *tgt,
"bgp-peering",
453 static void DeleteNeighborMesh(
const list<string> &routers,
455 for (list<string>::const_iterator iter = routers.begin();
456 iter != routers.end(); ) {
457 const string &left = *iter;
459 for (list<string>::const_iterator tgt = iter;
460 tgt != routers.end(); ++tgt) {
461 MapObjectUnlink(
"bgp-router", left,
"bgp-router", *tgt,
462 "bgp-peering", requests);
467 static bool ParseInstanceTarget(
const string &instance,
const xml_node &node,
470 string rtarget(node.child_value());
471 boost::trim(rtarget);
472 boost::system::error_code parse_err;
476 unique_ptr<autogen::InstanceTargetType> params(
477 new autogen::InstanceTargetType());
478 assert(params->XmlParse(node));
481 MapObjectLinkAttr(
"routing-instance", instance,
"route-target", rtarget,
482 "instance-target", params.release(), requests);
484 MapObjectUnlink(
"routing-instance", instance,
"route-target", rtarget,
485 "instance-target", requests);
491 static bool ParseInstanceVirtualNetwork(
const string &instance,
492 const xml_node &node,
bool add_change,
494 string vn_name = node.child_value();
496 MapObjectLink(
"routing-instance", instance,
497 "virtual-network", vn_name,
498 "virtual-network-routing-instance", requests);
500 MapObjectUnlink(
"routing-instance", instance,
501 "virtual-network", vn_name,
502 "virtual-network-routing-instance", requests);
517 string instance(parent.attribute(
"name").value());
518 assert(!instance.empty());
521 list<string> routers;
523 for (xml_node node = parent.first_child(); node;
524 node = node.next_sibling()) {
525 if (strcmp(node.name(),
"bgp-router") == 0) {
527 ParseBgpRouter(instance, node, add_change, &router_name,
528 &sessions, requests);
529 if (!router_name.empty()) {
530 routers.push_back(router_name);
532 }
else if (strcmp(node.name(),
"vrf-target") == 0) {
533 ParseInstanceTarget(instance, node, add_change, requests);
534 }
else if (strcmp(node.name(),
"virtual-network") == 0) {
535 ParseInstanceVirtualNetwork(instance, node, add_change, requests);
536 }
else if (strcmp(node.name(),
"service-chain-info") == 0) {
537 ParseServiceChain(instance, node, add_change,
538 "service-chain-information", requests);
539 }
else if (strcmp(node.name(),
"ipv6-service-chain-info") == 0) {
540 ParseServiceChain(instance, node, add_change,
541 "ipv6-service-chain-information", requests);
542 }
else if (strcmp(node.name(),
"evpn-service-chain-info") == 0) {
543 ParseServiceChain(instance, node, add_change,
544 "evpn-service-chain-information", requests);
545 }
else if (strcmp(node.name(),
"evpn-ipv6-service-chain-info") == 0) {
546 ParseServiceChain(instance, node, add_change,
547 "evpn-ipv6-service-chain-information", requests);
548 }
else if (strcmp(node.name(),
"route-aggregate") == 0) {
549 ParseInstanceRouteAggregate(instance, node, add_change, requests);
550 }
else if (strcmp(node.name(),
"routing-policy") == 0) {
551 ParseInstanceRoutingPolicy(instance, node, add_change, requests);
552 }
else if (strcmp(node.name(),
"static-route-entries") == 0) {
553 ParseStaticRoute(instance, node, add_change, requests);
554 }
else if (strcmp(node.name(),
"routing-instance-has-pnf") == 0) {
555 ParseInstanceHasPnf(instance, node, add_change, requests);
560 BuildPeeringLinks(instance, sessions, requests);
563 AddNeighborMesh(routers, requests);
565 RemovePeeringLinks(instance, sessions, requests);
566 DeleteNeighborMesh(routers, requests);
575 string vn_name(node.attribute(
"name").value());
576 assert(!vn_name.empty());
578 unique_ptr<autogen::VirtualNetwork::OolProperty> pbb_property(
579 new autogen::VirtualNetwork::OolProperty);
580 pbb_property->data =
false;
582 if (node.attribute(
"pbb-evpn-enable")) {
584 (string(node.attribute(
"pbb-evpn-enable").value()) ==
"true");
587 unique_ptr<autogen::VirtualNetworkType> property(
588 new autogen::VirtualNetworkType());
589 assert(property->XmlParse(node));
592 MapObjectSetProperty(
"virtual-network", vn_name,
593 "virtual-network-properties", property.release(), requests);
594 MapObjectSetProperty(
"virtual-network", vn_name,
595 "pbb-evpn-enable", pbb_property.release(), requests);
597 MapObjectClearProperty(
"virtual-network", vn_name,
598 "virtual-network-properties", requests);
599 MapObjectClearProperty(
"virtual-network", vn_name,
600 "pbb-evpn-enable", requests);
609 string subcluster_name(node.attribute(
"name").value());
610 assert(!subcluster_name.empty());
612 unique_ptr<autogen::SubCluster::StringProperty> subcluster_property(
613 new autogen::SubCluster::StringProperty);
615 if (node.child(
"sub-cluster-asn"))
616 subcluster_property->data =
string(node.child_value(
"sub-cluster-asn"));
619 MapObjectSetProperty(
"sub-cluster", subcluster_name,
620 "sub-cluster-asn", subcluster_property.release(), requests);
622 MapObjectClearProperty(
"sub-cluster", subcluster_name,
623 "sub-cluster-asn", requests);
626 unique_ptr<autogen::SubCluster::NtProperty> id_property(
627 new autogen::SubCluster::NtProperty);
628 if (node.child(
"sub-cluster-id")) {
629 std::stringstream sub_cluster_id(
630 string(node.child_value(
"sub-cluster-id")));
631 sub_cluster_id >> id_property->data;
634 MapObjectSetProperty(
"sub-cluster", subcluster_name,
635 "sub-cluster-id", id_property.release(), requests);
637 MapObjectClearProperty(
"sub-cluster", subcluster_name,
638 "sub-cluster-id", requests);
647 string aggregate_name(node.attribute(
"name").value());
648 assert(!aggregate_name.empty());
651 for (xml_node child = node.first_child(); child;
652 child = child.next_sibling()) {
653 if (strcmp(child.name(),
"aggregate-route-entries") == 0) {
655 unique_ptr<autogen::RouteListType>
656 aggregate_routes(
new autogen::RouteListType());
657 assert(aggregate_routes->XmlParse(child));
658 MapObjectSetProperty(
"route-aggregate", aggregate_name,
659 "aggregate-route-entries",
660 aggregate_routes.release(), requests);
662 MapObjectClearProperty(
"route-aggregate", aggregate_name,
663 "aggregate-route-entries", requests);
665 }
else if (strcmp(child.name(),
"nexthop") == 0) {
667 string nexthop = child.child_value();
669 autogen::RouteAggregate::StringProperty *nexthop_property =
670 new autogen::RouteAggregate::StringProperty();
671 nexthop_property->data = nexthop;
672 MapObjectSetProperty(
"route-aggregate", aggregate_name,
673 "aggregate-route-nexthop",
674 nexthop_property, requests);
676 MapObjectClearProperty(
"route-aggregate", aggregate_name,
677 "aggregate-route-nexthop", requests);
689 string policy_name(node.attribute(
"name").value());
690 assert(!policy_name.empty());
692 unique_ptr<autogen::PolicyStatementType> policy_statement(
693 new autogen::PolicyStatementType());
694 assert(policy_statement->XmlParse(node));
697 MapObjectSetProperty(
"routing-policy", policy_name,
698 "routing-policy-entries", policy_statement.release(), requests);
700 MapObjectClearProperty(
"routing-policy", policy_name,
701 "routing-policy-entries", requests);
710 for (xml_node child = node.first_child(); child;
711 child = child.next_sibling()) {
712 if (strcmp(child.name(),
"graceful-restart-parameters") == 0) {
713 unique_ptr<autogen::GracefulRestartParametersType> gr_config(
714 new autogen::GracefulRestartParametersType());
715 assert(gr_config->XmlParse(child));
718 MapObjectSetProperty(
"global-system-config",
"",
719 "graceful-restart-parameters",
720 gr_config.release(), requests);
722 MapObjectClearProperty(
"global-system-config",
"",
723 "graceful-restart-parameters", requests);
726 if (strcmp(child.name(),
"bgpaas-parameters") == 0) {
727 unique_ptr<autogen::BGPaaServiceParametersType> bgpaas_config(
728 new autogen::BGPaaServiceParametersType());
729 assert(bgpaas_config->XmlParse(child));
732 MapObjectSetProperty(
"global-system-config",
"",
733 "bgpaas-parameters", bgpaas_config.release(), requests);
735 MapObjectClearProperty(
"global-system-config",
"",
736 "bgpaas-parameters", requests);
739 if (strcmp(child.name(),
"bgp-always-compare-med") == 0) {
740 unique_ptr<autogen::GlobalSystemConfig::OolProperty> property(
741 new autogen::GlobalSystemConfig::OolProperty);
742 property->data = (string(child.child_value()) ==
"true");
744 MapObjectSetProperty(
"global-system-config",
"",
745 "bgp-always-compare-med", property.release(), requests);
747 MapObjectClearProperty(
"global-system-config",
"",
748 "bgp-always-compare-med", requests);
751 if (strcmp(child.name(),
"enable-4byte-as") == 0) {
752 unique_ptr<autogen::GlobalSystemConfig::OolProperty> property(
753 new autogen::GlobalSystemConfig::OolProperty);
754 property->data = (string(child.child_value()) ==
"true");
756 MapObjectSetProperty(
"global-system-config",
"",
757 "enable-4byte-as", property.release(), requests);
759 MapObjectClearProperty(
"global-system-config",
"",
760 "enable-4byte-as", requests);
763 if (strcmp(child.name(),
"fast-convergence-parameters") == 0) {
764 unique_ptr<autogen::FastConvergenceParametersType> property(
765 new autogen::FastConvergenceParametersType());
766 assert(property->XmlParse(child));
768 MapObjectSetProperty(
"global-system-config",
"",
769 "fast-convergence-parameters", property.release(), requests);
771 MapObjectClearProperty(
"global-system-config",
"",
772 "fast-convergence-parameters", requests);
775 if (strcmp(child.name(),
"rd-cluster-seed") == 0) {
776 unique_ptr<autogen::GlobalSystemConfig::NtProperty> property(
777 new autogen::GlobalSystemConfig::NtProperty);
778 property->data = atoi(child.child_value());
780 MapObjectSetProperty(
"global-system-config",
"",
781 "rd-cluster-seed", property.release(), requests);
783 MapObjectClearProperty(
"global-system-config",
"",
784 "rd-cluster-seed", requests);
794 for (xml_node child = node.first_child(); child;
795 child = child.next_sibling()) {
796 if (strcmp(child.name(),
"control-traffic-dscp") == 0) {
797 unique_ptr<autogen::ControlTrafficDscpType> cfg(
798 new autogen::ControlTrafficDscpType());
799 assert(cfg->XmlParse(child));
802 MapObjectSetProperty(
"global-qos-config",
"",
803 "control-traffic-dscp", cfg.release(), requests);
805 MapObjectClearProperty(
"global-qos-config",
"",
806 "control-traffic-dscp", requests);
816 list<string> routers;
818 for (xml_node node = root.first_child(); node; node = node.next_sibling()) {
819 if (strcmp(node.name(),
"bgp-router") == 0) {
822 &router_name, &sessions, requests);
823 if (!router_name.empty()) {
824 routers.push_back(router_name);
827 if (strcmp(node.name(),
"routing-instance") == 0) {
830 if (strcmp(node.name(),
"virtual-network") == 0) {
833 if (strcmp(node.name(),
"sub-cluster") == 0) {
836 if (strcmp(node.name(),
"route-aggregate") == 0) {
839 if (strcmp(node.name(),
"routing-policy") == 0) {
842 if (strcmp(node.name(),
"global-system-config") == 0) {
845 if (strcmp(node.name(),
"global-qos-config") == 0) {
855 AddNeighborMesh(routers, requests);
859 DeleteNeighborMesh(routers, requests);
866 istringstream sstream(content);
868 xml_parse_result result = xdoc.load(sstream);
872 for (xml_node node = xdoc.first_child(); node; node = node.next_sibling()) {
873 const char *oper = node.name();
874 assert((strcmp(oper,
"config") == 0) || (strcmp(oper,
"delete") == 0));
875 bool add_change = (strcmp(oper,
"config") == 0);
879 while (!requests.empty()) {
880 unique_ptr<DBRequest> req(requests.front());
881 requests.pop_front();
896 boost::uuids::nil_generator nil;
897 boost::uuids::name_generator gen(nil());
900 oss << left <<
":" << right <<
":" << index;
901 uuid = gen(oss.str());
902 return boost::uuids::to_string(uuid);
static std::string session_uuid(const std::string &left, const std::string &right, int index)
bool ParseSubCluster(const pugi::xml_node &parent, bool add_change, RequestList *requests) const
static const char * kMasterInstance
bool ParseRouteAggregate(const pugi::xml_node &parent, bool add_change, RequestList *requests) const
std::unique_ptr< DBRequestData > data
bool Enqueue(DBRequest *req)
bool ParseGlobalQosConfig(const pugi::xml_node &parent, bool add_change, RequestList *requests) const
std::unique_ptr< AutogenProperty > content
bool ParseRoutingInstance(const pugi::xml_node &parent, bool add_change, RequestList *requests) const
void set_origin(Origin in_origin)
bool Parse(const std::string &content)
std::list< DBRequest * > RequestList
bool ParseVirtualNetwork(const pugi::xml_node &parent, bool add_change, RequestList *requests) const
std::unique_ptr< DBRequestKey > key
bool ParseGlobalSystemConfig(const pugi::xml_node &parent, bool add_change, RequestList *requests) const
static RouteTarget FromString(const std::string &str, boost::system::error_code *error=NULL)
multimap< pair< string, string >, pair< autogen::BgpSessionAttributes, string > > SessionMap
static IFMapTable * FindTable(DB *db, const std::string &element_type)
bool ParseRoutingPolicy(const pugi::xml_node &parent, bool add_change, RequestList *requests) const
bool ParseConfig(const pugi::xml_node &root, bool add_change, RequestList *requests) const
static const uint32_t kDefaultAutonomousSystem