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