OpenSDN source code
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
bgp_config_parser.cc
Go to the documentation of this file.
1 /*
2  * Copyright (c) 2013 Juniper Networks, Inc. All rights reserved.
3  */
4 
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"
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 static void MapObjectSetProperty(const string &ltype, const string &lname,
47  const string &propname,
48  AutogenProperty *property,
49  BgpConfigParser::RequestList *requests) {
50  DBRequest *request = new DBRequest;
53  request->key.reset(key);
54  key->id_type = ltype;
55  key->id_name = lname;
57  request->data.reset(data);
58  data->metadata = propname;
59  data->content.reset(property);
61  requests->push_back(request);
62 }
63 
64 static void MapObjectClearProperty(const string &ltype, const string &lname,
65  const string &propname,
66  BgpConfigParser::RequestList *requests) {
67  DBRequest *request = new DBRequest;
70  request->key.reset(key);
71  key->id_type = ltype;
72  key->id_name = lname;
74  request->data.reset(data);
75  data->metadata = propname;
77  requests->push_back(request);
78 }
79 
80 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  DBRequest *request = new DBRequest;
87  request->key.reset(key);
88  key->id_type = ltype;
89  key->id_name = lname;
91  request->data.reset(data);
92  data->metadata = linkname;
93  data->id_type = rtype;
94  data->id_name = rname;
96  requests->push_back(request);
97 }
98 
99 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  DBRequest *request = new DBRequest;
104  request->oper = DBRequest::DB_ENTRY_DELETE;
106  request->key.reset(key);
107  key->id_type = ltype;
108  key->id_name = lname;
110  request->data.reset(data);
111  data->metadata = linkname;
112  data->id_type = rtype;
113  data->id_name = rname;
115  requests->push_back(request);
116 }
117 
118 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  DBRequest *request = new DBRequest;
125  request->key.reset(key);
126  key->id_type = ltype;
127  key->id_name = lname;
129  request->data.reset(data);
130  data->metadata = linkname;
131  data->id_type = rtype;
132  data->id_name = rname;
133  data->content.reset(attr);
135  requests->push_back(request);
136 }
137 
138 static autogen::BgpSessionAttributes *GetPeeringSessionAttribute(
139  const pair<string, string> &key, autogen::BgpPeeringAttributes *peer,
140  int session_id, const string config_uuid) {
141  string uuid;
142  if (!config_uuid.empty()) {
143  uuid = config_uuid;
144  } else {
145  uuid = BgpConfigParser::session_uuid(key.first, key.second, session_id);
146  }
147 
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->();
154  break;
155  }
156  }
157  if (session == NULL) {
158  peer->session.push_back(autogen::BgpSession());
159  session = &peer->session.back();
160  session->uuid = uuid;
161  }
162  session->attributes.push_back(autogen::BgpSessionAttributes());
163  autogen::BgpSessionAttributes *sattr = &session->attributes.back();
164  return sattr;
165 }
166 
167 static void MaybeMergeBidirectionalSessionParams(
168  autogen::BgpPeeringAttributes *peer) {
169 }
170 
171 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  PeeringMap peerings;
177 
178  pair<string, string> sprev;
179  int session_id = 0;
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;
185  if (left <= right) {
186  key = make_pair(left, right);
187  } else {
188  key = make_pair(right, left);
189  }
190 
191  string config_uuid = iter->second.second;
192  if ((sprev.first == left) && (sprev.second == right)) {
193  session_id++;
194  } else {
195  session_id = 1;
196  sprev = make_pair(left, right);
197  }
198 
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));
204  } else {
205  peer = loc->second;
206  }
207  // add uni-directional attributes for this session.
208  autogen::BgpSessionAttributes *attrp =
209  GetPeeringSessionAttribute(key, peer, session_id, config_uuid);
210  attrp->Copy(iter->second.first);
211  attrp->bgp_router = left;
212  }
213 
214  // generate the links.
215  // merging uni-directional attributes into a common attribute when they
216  // are the same.
217  for (PeeringMap::iterator iter = peerings.begin(); iter != peerings.end();
218  ++iter) {
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);
226  }
227 }
228 
229 static void RemovePeeringLinks(const string &instance,
230  const SessionMap &sessions,
231  BgpConfigParser::RequestList *requests) {
232  set<pair<string, string> > key_set;
233 
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;
239  if (left <= right) {
240  key = make_pair(left, right);
241  } else {
242  key = make_pair(right, left);
243  }
244  if (key_set.count(key) > 0) {
245  continue;
246  }
247  key_set.insert(key);
248  string id_left(instance + ':'), id_right(instance + ':');
249  id_left.append(key.first);
250  id_right.append(key.second);
251 
252  MapObjectUnlink("bgp-router", id_left, "bgp-router", id_right,
253  "bgp-peering", requests);
254  }
255 }
256 
257 static bool ParseSession(const string &identifier, const xml_node &node,
258  SessionMap *sessions) {
259  autogen::BgpSessionAttributes attr;
260  attr.Clear();
261  xml_attribute to = node.attribute("to");
262  assert(to);
263  assert(attr.XmlParse(node));
264 
265  string to_value = to.value();
266  string to_name, uuid;
267  size_t pos = to_value.find(':');
268  if (pos == string::npos) {
269  to_name = to_value;
270  } else {
271  to_name = to_value.substr(0, pos);
272  uuid = string(to_value, pos + 1);
273  }
274 
275  sessions->insert(
276  make_pair(make_pair(identifier, to_name), make_pair(attr, uuid)));
277  return true;
278 }
279 
280 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  new autogen::ServiceChainInfo());
285  property->sc_head = true;
286  assert(property->XmlParse(node));
287 
288  if (add_change) {
289  MapObjectSetProperty("routing-instance", instance,
290  sc_info, property.release(), requests);
291  } else {
292  MapObjectClearProperty("routing-instance", instance,
293  sc_info, requests);
294  }
295 
296  return true;
297 }
298 
299 static bool ParseInstanceRouteAggregate(const string &instance,
300  const xml_node &node, bool add_change,
301  BgpConfigParser::RequestList *requests) {
302 
303  xml_attribute to = node.attribute("to");
304  assert(to);
305  string aggregate_name = to.value();
306  if (add_change) {
307  MapObjectLinkAttr("routing-instance", instance,
308  "route-aggregate", aggregate_name,
309  "route-aggregate-routing-instance", NULL, requests);
310  } else {
311  MapObjectUnlink("routing-instance", instance,
312  "route-aggregate", aggregate_name,
313  "route-aggregate-routing-instance", requests);
314  }
315 
316  return true;
317 }
318 
319 static bool ParseInstanceRoutingPolicy(const string &instance,
320  const xml_node &node, bool add_change,
321  BgpConfigParser::RequestList *requests) {
322 
323  xml_attribute to = node.attribute("to");
324  assert(to);
325  string policy_name = to.value();
326  unique_ptr<autogen::RoutingPolicyType> attr(
327  new autogen::RoutingPolicyType());
328  assert(attr->XmlParse(node));
329  if (add_change) {
330  MapObjectLinkAttr("routing-instance", instance,
331  "routing-policy", policy_name,
332  "routing-policy-routing-instance", attr.release(), requests);
333  } else {
334  MapObjectUnlink("routing-instance", instance,
335  "routing-policy", policy_name,
336  "routing-policy-routing-instance", requests);
337  }
338 
339  return true;
340 }
341 
342 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  new autogen::StaticRouteEntriesType());
347  assert(property->XmlParse(node));
348 
349  if (add_change) {
350  MapObjectSetProperty("routing-instance", instance,
351  "static-route-entries", property.release(), requests);
352  } else {
353  MapObjectClearProperty("routing-instance", instance,
354  "static-route-entries", requests);
355  }
356 
357  return true;
358 }
359 
360 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  new autogen::RoutingInstance::OolProperty);
364  property->data = (string(node.child_value()) == "true");
365  if (add_change) {
366  MapObjectSetProperty("routing-instance", instance,
367  "routing-instance-has-pnf", property.release(), requests);
368  } else {
369  MapObjectClearProperty("routing-instance", instance,
370  "routing-instance-has-pnf", requests);
371  }
372 
373  return true;
374 }
375 
376 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  new autogen::BgpRouterParams());
382  xml_attribute name = node.attribute("name");
383  assert(name);
384  string identifier = name.value();
385  assert(property->XmlParse(node));
386 
387  if (property->autonomous_system == 0) {
388  property->autonomous_system =
390  }
391  if (property->identifier.empty()) {
392  property->identifier = property->address;
393  }
394 
395  bool has_sessions = false;
396  for (xml_node xsession = node.child("session"); xsession;
397  xsession = xsession.next_sibling("session")) {
398  has_sessions = true;
399  ParseSession(identifier, xsession, sessions);
400  }
401 
402  string fqname(instance + ":" + identifier);
403  if (!has_sessions) {
404  *nodename = fqname;
405  }
406 
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());
412  }
413 
414  if (add_change) {
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);
422  }
423  } else {
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);
431  }
432  }
433 
434  return true;
435 }
436 
437 // Creates a full-mesh of links between all the routers that have been
438 // defined.
439 static void AddNeighborMesh(const list<string> &routers,
440  BgpConfigParser::RequestList *requests) {
441  for (list<string>::const_iterator iter = routers.begin();
442  iter != routers.end(); ) {
443  const string &left = *iter;
444  ++iter;
445  for (list<string>::const_iterator tgt = iter;
446  tgt != routers.end(); ++tgt) {
447  MapObjectLink("bgp-router", left, "bgp-router", *tgt, "bgp-peering",
448  requests);
449  }
450  }
451 }
452 
453 static void DeleteNeighborMesh(const list<string> &routers,
454  BgpConfigParser::RequestList *requests) {
455  for (list<string>::const_iterator iter = routers.begin();
456  iter != routers.end(); ) {
457  const string &left = *iter;
458  ++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);
463  }
464  }
465 }
466 
467 static bool ParseInstanceTarget(const string &instance, const xml_node &node,
468  bool add_change,
469  BgpConfigParser::RequestList *requests) {
470  string rtarget(node.child_value());
471  boost::trim(rtarget);
472  boost::system::error_code parse_err;
473  RouteTarget::FromString(rtarget, &parse_err);
474  assert(!parse_err);
475 
476  unique_ptr<autogen::InstanceTargetType> params(
477  new autogen::InstanceTargetType());
478  assert(params->XmlParse(node));
479 
480  if (add_change) {
481  MapObjectLinkAttr("routing-instance", instance, "route-target", rtarget,
482  "instance-target", params.release(), requests);
483  } else {
484  MapObjectUnlink("routing-instance", instance, "route-target", rtarget,
485  "instance-target", requests);
486  }
487 
488  return true;
489 }
490 
491 static bool ParseInstanceVirtualNetwork(const string &instance,
492  const xml_node &node, bool add_change,
493  BgpConfigParser::RequestList *requests) {
494  string vn_name = node.child_value();
495  if (add_change) {
496  MapObjectLink("routing-instance", instance,
497  "virtual-network", vn_name,
498  "virtual-network-routing-instance", requests);
499  } else {
500  MapObjectUnlink("routing-instance", instance,
501  "virtual-network", vn_name,
502  "virtual-network-routing-instance", requests);
503  }
504 
505  return true;
506 }
507 
508 } // namespace
509 
511  : db_(db) {
512 }
513 
514 bool BgpConfigParser::ParseRoutingInstance(const xml_node &parent,
515  bool add_change,
516  RequestList *requests) const {
517  string instance(parent.attribute("name").value());
518  assert(!instance.empty());
519 
520  SessionMap sessions;
521  list<string> routers;
522 
523  for (xml_node node = parent.first_child(); node;
524  node = node.next_sibling()) {
525  if (strcmp(node.name(), "bgp-router") == 0) {
526  string router_name;
527  ParseBgpRouter(instance, node, add_change, &router_name,
528  &sessions, requests);
529  if (!router_name.empty()) {
530  routers.push_back(router_name);
531  }
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);
556  }
557  }
558 
559  if (add_change) {
560  BuildPeeringLinks(instance, sessions, requests);
561  // Generate a full mesh of peering sessions for neighbors that do not
562  // specify session attributes.
563  AddNeighborMesh(routers, requests);
564  } else {
565  RemovePeeringLinks(instance, sessions, requests);
566  DeleteNeighborMesh(routers, requests);
567  }
568  return true;
569 }
570 
571 bool BgpConfigParser::ParseVirtualNetwork(const xml_node &node,
572  bool add_change,
573  RequestList *requests) const {
574  // vn name
575  string vn_name(node.attribute("name").value());
576  assert(!vn_name.empty());
577 
578  unique_ptr<autogen::VirtualNetwork::OolProperty> pbb_property(
579  new autogen::VirtualNetwork::OolProperty);
580  pbb_property->data = false;
581 
582  if (node.attribute("pbb-evpn-enable")) {
583  pbb_property->data =
584  (string(node.attribute("pbb-evpn-enable").value()) == "true");
585  }
586 
587  unique_ptr<autogen::VirtualNetworkType> property(
588  new autogen::VirtualNetworkType());
589  assert(property->XmlParse(node));
590 
591  if (add_change) {
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);
596  } else {
597  MapObjectClearProperty("virtual-network", vn_name,
598  "virtual-network-properties", requests);
599  MapObjectClearProperty("virtual-network", vn_name,
600  "pbb-evpn-enable", requests);
601  }
602 
603  return true;
604 }
605 
606 bool BgpConfigParser::ParseSubCluster(const xml_node &node,
607  bool add_change,
608  RequestList *requests) const {
609  string subcluster_name(node.attribute("name").value());
610  assert(!subcluster_name.empty());
611 
612  unique_ptr<autogen::SubCluster::StringProperty> subcluster_property(
613  new autogen::SubCluster::StringProperty);
614 
615  if (node.child("sub-cluster-asn"))
616  subcluster_property->data = string(node.child_value("sub-cluster-asn"));
617 
618  if (add_change) {
619  MapObjectSetProperty("sub-cluster", subcluster_name,
620  "sub-cluster-asn", subcluster_property.release(), requests);
621  } else {
622  MapObjectClearProperty("sub-cluster", subcluster_name,
623  "sub-cluster-asn", requests);
624  }
625 
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;
632  }
633  if (add_change) {
634  MapObjectSetProperty("sub-cluster", subcluster_name,
635  "sub-cluster-id", id_property.release(), requests);
636  } else {
637  MapObjectClearProperty("sub-cluster", subcluster_name,
638  "sub-cluster-id", requests);
639  }
640  return true;
641 }
642 
643 bool BgpConfigParser::ParseRouteAggregate(const xml_node &node,
644  bool add_change,
645  RequestList *requests) const {
646  // policy name
647  string aggregate_name(node.attribute("name").value());
648  assert(!aggregate_name.empty());
649 
650 
651  for (xml_node child = node.first_child(); child;
652  child = child.next_sibling()) {
653  if (strcmp(child.name(), "aggregate-route-entries") == 0) {
654  if (add_change) {
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);
661  } else {
662  MapObjectClearProperty("route-aggregate", aggregate_name,
663  "aggregate-route-entries", requests);
664  }
665  } else if (strcmp(child.name(), "nexthop") == 0) {
666  if (add_change) {
667  string nexthop = child.child_value();
668 
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);
675  } else {
676  MapObjectClearProperty("route-aggregate", aggregate_name,
677  "aggregate-route-nexthop", requests);
678  }
679  }
680  }
681 
682  return true;
683 }
684 
685 bool BgpConfigParser::ParseRoutingPolicy(const xml_node &node,
686  bool add_change,
687  RequestList *requests) const {
688  // policy name
689  string policy_name(node.attribute("name").value());
690  assert(!policy_name.empty());
691 
692  unique_ptr<autogen::PolicyStatementType> policy_statement(
693  new autogen::PolicyStatementType());
694  assert(policy_statement->XmlParse(node));
695 
696  if (add_change) {
697  MapObjectSetProperty("routing-policy", policy_name,
698  "routing-policy-entries", policy_statement.release(), requests);
699  } else {
700  MapObjectClearProperty("routing-policy", policy_name,
701  "routing-policy-entries", requests);
702  }
703 
704  return true;
705 }
706 
708  bool add_change,
709  RequestList *requests) const {
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));
716 
717  if (add_change) {
718  MapObjectSetProperty("global-system-config", "",
719  "graceful-restart-parameters",
720  gr_config.release(), requests);
721  } else {
722  MapObjectClearProperty("global-system-config", "",
723  "graceful-restart-parameters", requests);
724  }
725  }
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));
730 
731  if (add_change) {
732  MapObjectSetProperty("global-system-config", "",
733  "bgpaas-parameters", bgpaas_config.release(), requests);
734  } else {
735  MapObjectClearProperty("global-system-config", "",
736  "bgpaas-parameters", requests);
737  }
738  }
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");
743  if (add_change) {
744  MapObjectSetProperty("global-system-config", "",
745  "bgp-always-compare-med", property.release(), requests);
746  } else {
747  MapObjectClearProperty("global-system-config", "",
748  "bgp-always-compare-med", requests);
749  }
750  }
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");
755  if (add_change) {
756  MapObjectSetProperty("global-system-config", "",
757  "enable-4byte-as", property.release(), requests);
758  } else {
759  MapObjectClearProperty("global-system-config", "",
760  "enable-4byte-as", requests);
761  }
762  }
763  if (strcmp(child.name(), "fast-convergence-parameters") == 0) {
764  unique_ptr<autogen::FastConvergenceParametersType> property(
765  new autogen::FastConvergenceParametersType());
766  assert(property->XmlParse(child));
767  if (add_change) {
768  MapObjectSetProperty("global-system-config", "",
769  "fast-convergence-parameters", property.release(), requests);
770  } else {
771  MapObjectClearProperty("global-system-config", "",
772  "fast-convergence-parameters", requests);
773  }
774  }
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());
779  if (add_change) {
780  MapObjectSetProperty("global-system-config", "",
781  "rd-cluster-seed", property.release(), requests);
782  } else {
783  MapObjectClearProperty("global-system-config", "",
784  "rd-cluster-seed", requests);
785  }
786  }
787  }
788  return true;
789 }
790 
791 bool BgpConfigParser::ParseGlobalQosConfig(const xml_node &node,
792  bool add_change,
793  RequestList *requests) const {
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));
800 
801  if (add_change) {
802  MapObjectSetProperty("global-qos-config", "",
803  "control-traffic-dscp", cfg.release(), requests);
804  } else {
805  MapObjectClearProperty("global-qos-config", "",
806  "control-traffic-dscp", requests);
807  }
808  }
809  }
810  return true;
811 }
812 
813 bool BgpConfigParser::ParseConfig(const xml_node &root, bool add_change,
814  RequestList *requests) const {
815  SessionMap sessions;
816  list<string> routers;
817 
818  for (xml_node node = root.first_child(); node; node = node.next_sibling()) {
819  if (strcmp(node.name(), "bgp-router") == 0) {
820  string router_name;
821  ParseBgpRouter(BgpConfigManager::kMasterInstance, node, add_change,
822  &router_name, &sessions, requests);
823  if (!router_name.empty()) {
824  routers.push_back(router_name);
825  }
826  }
827  if (strcmp(node.name(), "routing-instance") == 0) {
828  ParseRoutingInstance(node, add_change, requests);
829  }
830  if (strcmp(node.name(), "virtual-network") == 0) {
831  ParseVirtualNetwork(node, add_change, requests);
832  }
833  if (strcmp(node.name(), "sub-cluster") == 0) {
834  ParseSubCluster(node, add_change, requests);
835  }
836  if (strcmp(node.name(), "route-aggregate") == 0) {
837  ParseRouteAggregate(node, add_change, requests);
838  }
839  if (strcmp(node.name(), "routing-policy") == 0) {
840  ParseRoutingPolicy(node, add_change, requests);
841  }
842  if (strcmp(node.name(), "global-system-config") == 0) {
843  ParseGlobalSystemConfig(node, add_change, requests);
844  }
845  if (strcmp(node.name(), "global-qos-config") == 0) {
846  ParseGlobalQosConfig(node, add_change, requests);
847  }
848  }
849 
850  if (add_change) {
851  BuildPeeringLinks(BgpConfigManager::kMasterInstance, sessions,
852  requests);
853  // Generate a full mesh of peering sessions for neighbors that do not
854  // specify session attributes.
855  AddNeighborMesh(routers, requests);
856  } else {
857  RemovePeeringLinks(BgpConfigManager::kMasterInstance, sessions,
858  requests);
859  DeleteNeighborMesh(routers, requests);
860  }
861 
862  return true;
863 }
864 
865 bool BgpConfigParser::Parse(const string &content) {
866  istringstream sstream(content);
867  xml_document xdoc;
868  xml_parse_result result = xdoc.load(sstream);
869  assert(result);
870 
871  RequestList requests;
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);
876  assert(ParseConfig(node, add_change, &requests));
877  }
878 
879  while (!requests.empty()) {
880  unique_ptr<DBRequest> req(requests.front());
881  requests.pop_front();
882 
884  static_cast<IFMapTable::RequestKey *>(req->key.get());
885 
887  assert(table);
888  table->Enqueue(req.get());
889  }
890 
891  return true;
892 }
893 
894 string BgpConfigParser::session_uuid(const string &left, const string &right,
895  int index) {
896  boost::uuids::nil_generator nil;
897  boost::uuids::name_generator gen(nil());
899  ostringstream oss;
900  oss << left << ":" << right << ":" << index;
901  uuid = gen(oss.str());
902  return boost::uuids::to_string(uuid);
903 }
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
Definition: bgp_config.h:764
bool ParseRouteAggregate(const pugi::xml_node &parent, bool add_change, RequestList *requests) const
std::unique_ptr< DBRequestData > data
Definition: db_table.h:49
bool Enqueue(DBRequest *req)
Definition: db_table.cc:194
boost::uuids::uuid uuid
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
Definition: db.h:24
void set_origin(Origin in_origin)
Definition: ifmap_origin.h:21
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
Definition: db_table.h:48
DBOperation oper
Definition: db_table.h:42
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)
Definition: ifmap_table.cc:39
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
Definition: bgp_config.h:767