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 64 : static void MapObjectSetProperty(const string <ype, const string &lname,
47 : const string &propname,
48 : AutogenProperty *property,
49 : BgpConfigParser::RequestList *requests) {
50 64 : DBRequest *request = new DBRequest;
51 64 : request->oper = DBRequest::DB_ENTRY_ADD_CHANGE;
52 64 : IFMapTable::RequestKey *key = new IFMapTable::RequestKey();
53 64 : request->key.reset(key);
54 64 : key->id_type = ltype;
55 64 : key->id_name = lname;
56 64 : IFMapServerTable::RequestData *data = new IFMapServerTable::RequestData();
57 64 : request->data.reset(data);
58 64 : data->metadata = propname;
59 64 : data->content.reset(property);
60 64 : data->origin.set_origin(IFMapOrigin::MAP_SERVER);
61 64 : requests->push_back(request);
62 64 : }
63 :
64 0 : static void MapObjectClearProperty(const string <ype, const string &lname,
65 : const string &propname,
66 : BgpConfigParser::RequestList *requests) {
67 0 : DBRequest *request = new DBRequest;
68 0 : request->oper = DBRequest::DB_ENTRY_DELETE;
69 0 : IFMapTable::RequestKey *key = new IFMapTable::RequestKey();
70 0 : request->key.reset(key);
71 0 : key->id_type = ltype;
72 0 : key->id_name = lname;
73 0 : IFMapServerTable::RequestData *data = new IFMapServerTable::RequestData();
74 0 : request->data.reset(data);
75 0 : data->metadata = propname;
76 0 : data->origin.set_origin(IFMapOrigin::MAP_SERVER);
77 0 : requests->push_back(request);
78 0 : }
79 :
80 96 : static void MapObjectLink(const string <ype, const string &lname,
81 : const string &rtype, const string &rname,
82 : const string &linkname,
83 : BgpConfigParser::RequestList *requests) {
84 96 : DBRequest *request = new DBRequest;
85 96 : request->oper = DBRequest::DB_ENTRY_ADD_CHANGE;
86 96 : IFMapTable::RequestKey *key = new IFMapTable::RequestKey();
87 96 : request->key.reset(key);
88 96 : key->id_type = ltype;
89 96 : key->id_name = lname;
90 96 : IFMapServerTable::RequestData *data = new IFMapServerTable::RequestData();
91 96 : request->data.reset(data);
92 96 : data->metadata = linkname;
93 96 : data->id_type = rtype;
94 96 : data->id_name = rname;
95 96 : data->origin.set_origin(IFMapOrigin::MAP_SERVER);
96 96 : requests->push_back(request);
97 96 : }
98 :
99 0 : static void MapObjectUnlink(const string <ype, const string &lname,
100 : const string &rtype, const string &rname,
101 : const string &linkname,
102 : BgpConfigParser::RequestList *requests) {
103 0 : DBRequest *request = new DBRequest;
104 0 : request->oper = DBRequest::DB_ENTRY_DELETE;
105 0 : IFMapTable::RequestKey *key = new IFMapTable::RequestKey();
106 0 : request->key.reset(key);
107 0 : key->id_type = ltype;
108 0 : key->id_name = lname;
109 0 : IFMapServerTable::RequestData *data = new IFMapServerTable::RequestData();
110 0 : request->data.reset(data);
111 0 : data->metadata = linkname;
112 0 : data->id_type = rtype;
113 0 : data->id_name = rname;
114 0 : data->origin.set_origin(IFMapOrigin::MAP_SERVER);
115 0 : requests->push_back(request);
116 0 : }
117 :
118 96 : static void MapObjectLinkAttr(const string <ype, const string &lname,
119 : const string &rtype, const string &rname,
120 : const string &linkname, AutogenProperty *attr,
121 : BgpConfigParser::RequestList *requests) {
122 96 : DBRequest *request = new DBRequest;
123 96 : request->oper = DBRequest::DB_ENTRY_ADD_CHANGE;
124 96 : IFMapTable::RequestKey *key = new IFMapTable::RequestKey();
125 96 : request->key.reset(key);
126 96 : key->id_type = ltype;
127 96 : key->id_name = lname;
128 96 : IFMapServerTable::RequestData *data = new IFMapServerTable::RequestData();
129 96 : request->data.reset(data);
130 96 : data->metadata = linkname;
131 96 : data->id_type = rtype;
132 96 : data->id_name = rname;
133 96 : data->content.reset(attr);
134 96 : data->origin.set_origin(IFMapOrigin::MAP_SERVER);
135 96 : requests->push_back(request);
136 96 : }
137 :
138 0 : static autogen::BgpSessionAttributes *GetPeeringSessionAttribute(
139 : const pair<string, string> &key, autogen::BgpPeeringAttributes *peer,
140 : int session_id, const string config_uuid) {
141 0 : string uuid;
142 0 : if (!config_uuid.empty()) {
143 0 : uuid = config_uuid;
144 : } else {
145 0 : uuid = BgpConfigParser::session_uuid(key.first, key.second, session_id);
146 : }
147 :
148 0 : autogen::BgpSession *session = NULL;
149 0 : for (vector<autogen::BgpSession>::iterator iter =
150 0 : peer->session.begin();
151 0 : iter != peer->session.end(); ++iter) {
152 0 : if (iter->uuid == uuid) {
153 0 : session = iter.operator->();
154 0 : break;
155 : }
156 : }
157 0 : if (session == NULL) {
158 0 : peer->session.push_back(autogen::BgpSession());
159 0 : session = &peer->session.back();
160 0 : session->uuid = uuid;
161 : }
162 0 : session->attributes.push_back(autogen::BgpSessionAttributes());
163 0 : autogen::BgpSessionAttributes *sattr = &session->attributes.back();
164 0 : return sattr;
165 0 : }
166 :
167 0 : static void MaybeMergeBidirectionalSessionParams(
168 : autogen::BgpPeeringAttributes *peer) {
169 0 : }
170 :
171 160 : 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 160 : PeeringMap peerings;
177 :
178 160 : pair<string, string> sprev;
179 160 : int session_id = 0;
180 160 : for (SessionMap::const_iterator iter = sessions.begin();
181 160 : iter != sessions.end(); ++iter) {
182 0 : const string &left = iter->first.first;
183 0 : const string &right = iter->first.second;
184 0 : pair<string, string> key;
185 0 : if (left <= right) {
186 0 : key = make_pair(left, right);
187 : } else {
188 0 : key = make_pair(right, left);
189 : }
190 :
191 0 : string config_uuid = iter->second.second;
192 0 : if ((sprev.first == left) && (sprev.second == right)) {
193 0 : session_id++;
194 : } else {
195 0 : session_id = 1;
196 0 : sprev = make_pair(left, right);
197 : }
198 :
199 0 : autogen::BgpPeeringAttributes *peer = NULL;
200 0 : PeeringMap::iterator loc = peerings.find(key);
201 0 : if (loc == peerings.end()) {
202 0 : peer = new autogen::BgpPeeringAttributes();
203 0 : peerings.insert(make_pair(key, peer));
204 : } else {
205 0 : peer = loc->second;
206 : }
207 : // add uni-directional attributes for this session.
208 : autogen::BgpSessionAttributes *attrp =
209 0 : GetPeeringSessionAttribute(key, peer, session_id, config_uuid);
210 0 : attrp->Copy(iter->second.first);
211 0 : attrp->bgp_router = left;
212 0 : }
213 :
214 : // generate the links.
215 : // merging uni-directional attributes into a common attribute when they
216 : // are the same.
217 160 : for (PeeringMap::iterator iter = peerings.begin(); iter != peerings.end();
218 0 : ++iter) {
219 0 : autogen::BgpPeeringAttributes *peer = iter->second;
220 0 : MaybeMergeBidirectionalSessionParams(peer);
221 0 : string left(instance + ':'), right(instance + ':');
222 0 : left.append(iter->first.first);
223 0 : right.append(iter->first.second);
224 0 : MapObjectLinkAttr("bgp-router", left, "bgp-router", right,
225 : "bgp-peering", peer, requests);
226 0 : }
227 160 : }
228 :
229 0 : static void RemovePeeringLinks(const string &instance,
230 : const SessionMap &sessions,
231 : BgpConfigParser::RequestList *requests) {
232 0 : set<pair<string, string> > key_set;
233 :
234 0 : for (SessionMap::const_iterator iter = sessions.begin();
235 0 : iter != sessions.end(); ++iter) {
236 0 : const string &left = iter->first.first;
237 0 : const string &right = iter->first.second;
238 0 : pair<string, string> key;
239 0 : if (left <= right) {
240 0 : key = make_pair(left, right);
241 : } else {
242 0 : key = make_pair(right, left);
243 : }
244 0 : if (key_set.count(key) > 0) {
245 0 : continue;
246 : }
247 0 : key_set.insert(key);
248 0 : string id_left(instance + ':'), id_right(instance + ':');
249 0 : id_left.append(key.first);
250 0 : id_right.append(key.second);
251 :
252 0 : MapObjectUnlink("bgp-router", id_left, "bgp-router", id_right,
253 : "bgp-peering", requests);
254 0 : }
255 0 : }
256 :
257 0 : static bool ParseSession(const string &identifier, const xml_node &node,
258 : SessionMap *sessions) {
259 0 : autogen::BgpSessionAttributes attr;
260 0 : attr.Clear();
261 0 : xml_attribute to = node.attribute("to");
262 0 : assert(to);
263 0 : assert(attr.XmlParse(node));
264 :
265 0 : string to_value = to.value();
266 0 : string to_name, uuid;
267 0 : size_t pos = to_value.find(':');
268 0 : if (pos == string::npos) {
269 0 : 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 0 : sessions->insert(
276 0 : make_pair(make_pair(identifier, to_name), make_pair(attr, uuid)));
277 0 : return true;
278 0 : }
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 64 : 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 64 : new autogen::BgpRouterParams());
382 64 : xml_attribute name = node.attribute("name");
383 64 : assert(name);
384 64 : string identifier = name.value();
385 64 : assert(property->XmlParse(node));
386 :
387 64 : if (property->autonomous_system == 0) {
388 0 : property->autonomous_system =
389 0 : BgpConfigManager::kDefaultAutonomousSystem;
390 : }
391 64 : if (property->identifier.empty()) {
392 0 : property->identifier = property->address;
393 : }
394 :
395 64 : bool has_sessions = false;
396 64 : for (xml_node xsession = node.child("session"); xsession;
397 0 : xsession = xsession.next_sibling("session")) {
398 0 : has_sessions = true;
399 0 : ParseSession(identifier, xsession, sessions);
400 : }
401 :
402 64 : string fqname(instance + ":" + identifier);
403 64 : if (!has_sessions) {
404 64 : *nodename = fqname;
405 : }
406 :
407 64 : string subcluster_name;
408 64 : 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 64 : if (add_change) {
415 64 : MapObjectLink("routing-instance", instance,
416 : "bgp-router", fqname, "instance-bgp-router", requests);
417 64 : MapObjectSetProperty("bgp-router", fqname,
418 64 : "bgp-router-parameters", property.release(), requests);
419 64 : if (!subcluster_name.empty()) {
420 0 : MapObjectLink("bgp-router", fqname, "sub-cluster", subcluster_name,
421 : "bgp-router-sub-cluster", requests);
422 : }
423 : } else {
424 0 : MapObjectClearProperty("bgp-router", fqname,
425 : "bgp-router-parameters", requests);
426 0 : MapObjectUnlink("routing-instance", instance,
427 : "bgp-router", fqname, "instance-bgp-router", requests);
428 0 : if (!subcluster_name.empty()) {
429 0 : MapObjectUnlink("bgp-router", fqname, "sub-cluster",
430 : subcluster_name, "bgp-router-sub-cluster", requests);
431 : }
432 : }
433 :
434 64 : return true;
435 64 : }
436 :
437 : // Creates a full-mesh of links between all the routers that have been
438 : // defined.
439 160 : static void AddNeighborMesh(const list<string> &routers,
440 : BgpConfigParser::RequestList *requests) {
441 160 : for (list<string>::const_iterator iter = routers.begin();
442 224 : iter != routers.end(); ) {
443 64 : const string &left = *iter;
444 64 : ++iter;
445 64 : for (list<string>::const_iterator tgt = iter;
446 96 : tgt != routers.end(); ++tgt) {
447 32 : MapObjectLink("bgp-router", left, "bgp-router", *tgt, "bgp-peering",
448 : requests);
449 : }
450 : }
451 160 : }
452 :
453 0 : static void DeleteNeighborMesh(const list<string> &routers,
454 : BgpConfigParser::RequestList *requests) {
455 0 : for (list<string>::const_iterator iter = routers.begin();
456 0 : 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 0 : }
466 :
467 96 : static bool ParseInstanceTarget(const string &instance, const xml_node &node,
468 : bool add_change,
469 : BgpConfigParser::RequestList *requests) {
470 96 : string rtarget(node.child_value());
471 96 : boost::trim(rtarget);
472 96 : boost::system::error_code parse_err;
473 96 : RouteTarget::FromString(rtarget, &parse_err);
474 96 : assert(!parse_err);
475 :
476 : unique_ptr<autogen::InstanceTargetType> params(
477 96 : new autogen::InstanceTargetType());
478 96 : assert(params->XmlParse(node));
479 :
480 96 : if (add_change) {
481 96 : MapObjectLinkAttr("routing-instance", instance, "route-target", rtarget,
482 96 : "instance-target", params.release(), requests);
483 : } else {
484 0 : MapObjectUnlink("routing-instance", instance, "route-target", rtarget,
485 : "instance-target", requests);
486 : }
487 :
488 96 : return true;
489 96 : }
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 32 : BgpConfigParser::BgpConfigParser(DB *db)
511 32 : : db_(db) {
512 32 : }
513 :
514 128 : bool BgpConfigParser::ParseRoutingInstance(const xml_node &parent,
515 : bool add_change,
516 : RequestList *requests) const {
517 128 : string instance(parent.attribute("name").value());
518 128 : assert(!instance.empty());
519 :
520 128 : SessionMap sessions;
521 128 : list<string> routers;
522 :
523 352 : for (xml_node node = parent.first_child(); node;
524 224 : node = node.next_sibling()) {
525 224 : if (strcmp(node.name(), "bgp-router") == 0) {
526 64 : string router_name;
527 64 : ParseBgpRouter(instance, node, add_change, &router_name,
528 : &sessions, requests);
529 64 : if (!router_name.empty()) {
530 64 : routers.push_back(router_name);
531 : }
532 224 : } else if (strcmp(node.name(), "vrf-target") == 0) {
533 96 : ParseInstanceTarget(instance, node, add_change, requests);
534 64 : } else if (strcmp(node.name(), "virtual-network") == 0) {
535 0 : ParseInstanceVirtualNetwork(instance, node, add_change, requests);
536 64 : } else if (strcmp(node.name(), "service-chain-info") == 0) {
537 0 : ParseServiceChain(instance, node, add_change,
538 : "service-chain-information", requests);
539 64 : } else if (strcmp(node.name(), "ipv6-service-chain-info") == 0) {
540 0 : ParseServiceChain(instance, node, add_change,
541 : "ipv6-service-chain-information", requests);
542 64 : } else if (strcmp(node.name(), "evpn-service-chain-info") == 0) {
543 0 : ParseServiceChain(instance, node, add_change,
544 : "evpn-service-chain-information", requests);
545 64 : } 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 64 : } else if (strcmp(node.name(), "route-aggregate") == 0) {
549 0 : ParseInstanceRouteAggregate(instance, node, add_change, requests);
550 64 : } else if (strcmp(node.name(), "routing-policy") == 0) {
551 0 : ParseInstanceRoutingPolicy(instance, node, add_change, requests);
552 64 : } else if (strcmp(node.name(), "static-route-entries") == 0) {
553 0 : ParseStaticRoute(instance, node, add_change, requests);
554 64 : } else if (strcmp(node.name(), "routing-instance-has-pnf") == 0) {
555 0 : ParseInstanceHasPnf(instance, node, add_change, requests);
556 : }
557 : }
558 :
559 128 : if (add_change) {
560 128 : BuildPeeringLinks(instance, sessions, requests);
561 : // Generate a full mesh of peering sessions for neighbors that do not
562 : // specify session attributes.
563 128 : AddNeighborMesh(routers, requests);
564 : } else {
565 0 : RemovePeeringLinks(instance, sessions, requests);
566 0 : DeleteNeighborMesh(routers, requests);
567 : }
568 128 : return true;
569 128 : }
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 0 : bool BgpConfigParser::ParseGlobalSystemConfig(const xml_node &node,
708 : bool add_change,
709 : RequestList *requests) const {
710 0 : for (xml_node child = node.first_child(); child;
711 0 : child = child.next_sibling()) {
712 0 : if (strcmp(child.name(), "graceful-restart-parameters") == 0) {
713 : unique_ptr<autogen::GracefulRestartParametersType> gr_config(
714 0 : new autogen::GracefulRestartParametersType());
715 0 : assert(gr_config->XmlParse(child));
716 :
717 0 : if (add_change) {
718 0 : MapObjectSetProperty("global-system-config", "",
719 : "graceful-restart-parameters",
720 0 : gr_config.release(), requests);
721 : } else {
722 0 : MapObjectClearProperty("global-system-config", "",
723 : "graceful-restart-parameters", requests);
724 : }
725 0 : }
726 0 : 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 0 : 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 0 : 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 0 : if (strcmp(child.name(), "enable-4byte-as") == 0) {
764 : unique_ptr<autogen::GlobalSystemConfig::OolProperty> property(
765 0 : new autogen::GlobalSystemConfig::OolProperty);
766 0 : property->data = (string(child.child_value()) == "true");
767 0 : if (add_change) {
768 0 : MapObjectSetProperty("global-system-config", "",
769 0 : "enable-4byte-as", property.release(), requests);
770 : } else {
771 0 : MapObjectClearProperty("global-system-config", "",
772 : "enable-4byte-as", requests);
773 : }
774 0 : }
775 0 : 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 0 : 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 0 : 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 32 : bool BgpConfigParser::ParseConfig(const xml_node &root, bool add_change,
826 : RequestList *requests) const {
827 32 : SessionMap sessions;
828 32 : list<string> routers;
829 :
830 192 : for (xml_node node = root.first_child(); node; node = node.next_sibling()) {
831 160 : if (strcmp(node.name(), "bgp-router") == 0) {
832 0 : string router_name;
833 0 : ParseBgpRouter(BgpConfigManager::kMasterInstance, node, add_change,
834 : &router_name, &sessions, requests);
835 0 : if (!router_name.empty()) {
836 0 : routers.push_back(router_name);
837 : }
838 0 : }
839 160 : if (strcmp(node.name(), "routing-instance") == 0) {
840 128 : ParseRoutingInstance(node, add_change, requests);
841 : }
842 160 : if (strcmp(node.name(), "virtual-network") == 0) {
843 0 : ParseVirtualNetwork(node, add_change, requests);
844 : }
845 160 : if (strcmp(node.name(), "sub-cluster") == 0) {
846 0 : ParseSubCluster(node, add_change, requests);
847 : }
848 160 : if (strcmp(node.name(), "route-aggregate") == 0) {
849 0 : ParseRouteAggregate(node, add_change, requests);
850 : }
851 160 : if (strcmp(node.name(), "routing-policy") == 0) {
852 0 : ParseRoutingPolicy(node, add_change, requests);
853 : }
854 160 : if (strcmp(node.name(), "global-system-config") == 0) {
855 0 : ParseGlobalSystemConfig(node, add_change, requests);
856 : }
857 160 : if (strcmp(node.name(), "global-qos-config") == 0) {
858 0 : ParseGlobalQosConfig(node, add_change, requests);
859 : }
860 : }
861 :
862 32 : if (add_change) {
863 32 : BuildPeeringLinks(BgpConfigManager::kMasterInstance, sessions,
864 : requests);
865 : // Generate a full mesh of peering sessions for neighbors that do not
866 : // specify session attributes.
867 32 : AddNeighborMesh(routers, requests);
868 : } else {
869 0 : RemovePeeringLinks(BgpConfigManager::kMasterInstance, sessions,
870 : requests);
871 0 : DeleteNeighborMesh(routers, requests);
872 : }
873 :
874 32 : return true;
875 32 : }
876 :
877 32 : bool BgpConfigParser::Parse(const string &content) {
878 32 : istringstream sstream(content);
879 32 : xml_document xdoc;
880 32 : xml_parse_result result = xdoc.load(sstream);
881 32 : if (result.status == pugi::status_no_document_element) {
882 0 : return true;
883 : }
884 :
885 32 : if (result.status == pugi::status_ok) {
886 32 : RequestList requests;
887 64 : for (xml_node node = xdoc.first_child(); node; node = node.next_sibling()) {
888 32 : const char *oper = node.name();
889 32 : assert((strcmp(oper, "config") == 0) || (strcmp(oper, "delete") == 0));
890 32 : bool add_change = (strcmp(oper, "config") == 0);
891 32 : assert(ParseConfig(node, add_change, &requests));
892 : }
893 :
894 288 : while (!requests.empty()) {
895 256 : unique_ptr<DBRequest> req(requests.front());
896 256 : requests.pop_front();
897 :
898 : IFMapTable::RequestKey *key =
899 256 : static_cast<IFMapTable::RequestKey *>(req->key.get());
900 :
901 256 : IFMapTable *table = IFMapTable::FindTable(db_, key->id_type);
902 256 : assert(table);
903 256 : table->Enqueue(req.get());
904 256 : }
905 :
906 32 : return true;
907 32 : }
908 0 : return false;
909 32 : }
910 :
911 0 : string BgpConfigParser::session_uuid(const string &left, const string &right,
912 : int index) {
913 : boost::uuids::nil_generator nil;
914 0 : boost::uuids::name_generator gen(nil());
915 : boost::uuids::uuid uuid;
916 0 : ostringstream oss;
917 0 : oss << left << ":" << right << ":" << index;
918 0 : uuid = gen(oss.str());
919 0 : return boost::uuids::to_string(uuid);
920 0 : }
|