Line data Source code
1 : /*
2 : * Copyright (c) 2014 Juniper Networks, Inc. All rights reserved.
3 : */
4 : #include "bgp/bgp_config.h"
5 :
6 : #include <boost/foreach.hpp>
7 :
8 : #include <sstream>
9 :
10 : #include "base/string_util.h"
11 : #include "base/time_util.h"
12 :
13 : using std::copy;
14 : using std::endl;
15 : using std::ostringstream;
16 : using std::ostream_iterator;
17 : using std::sort;
18 : using std::string;
19 : using std::swap;
20 : using std::vector;
21 :
22 : const char *BgpConfigManager::kMasterNetwork =
23 : "default-domain:default-project:ip-fabric";
24 : const char *BgpConfigManager::kMasterInstance =
25 : "default-domain:default-project:ip-fabric:__default__";
26 : const char *BgpConfigManager::kFabricInstance =
27 : "default-domain:default-project:ip-fabric:ip-fabric";
28 : const int BgpConfigManager::kDefaultPort = 179;
29 : const uint32_t BgpConfigManager::kDefaultAutonomousSystem = 64512;
30 :
31 3410 : static int CompareTo(const AuthenticationKey &lhs,
32 : const AuthenticationKey &rhs) {
33 3410 : KEY_COMPARE(lhs.id, rhs.id);
34 3410 : KEY_COMPARE(lhs.value, rhs.value);
35 3303 : KEY_COMPARE(lhs.start_time, rhs.start_time);
36 3303 : return 0;
37 : }
38 :
39 3195 : bool AuthenticationKey::operator<(const AuthenticationKey &rhs) const {
40 3195 : int cmp = CompareTo(*this, rhs);
41 3195 : return cmp < 0;
42 : }
43 :
44 215 : bool AuthenticationKey::operator==(const AuthenticationKey &rhs) const {
45 215 : int cmp = CompareTo(*this, rhs);
46 215 : return cmp == 0;
47 : }
48 :
49 101757 : AuthenticationData::AuthenticationData() : key_type_(NIL) {
50 101757 : }
51 :
52 0 : AuthenticationData::AuthenticationData(KeyType type,
53 0 : const AuthenticationKeyChain &chain) :
54 0 : key_type_(type), key_chain_(chain) {
55 0 : }
56 :
57 42058 : bool AuthenticationData::operator<(const AuthenticationData &rhs) const {
58 42058 : BOOL_KEY_COMPARE(key_type_, rhs.key_type());
59 42039 : BOOL_KEY_COMPARE(key_chain_, rhs.key_chain());
60 41982 : return false;
61 : }
62 :
63 20447 : bool AuthenticationData::operator==(const AuthenticationData &rhs) const {
64 40726 : if ((key_chain_.size() != rhs.key_chain().size()) ||
65 20279 : (key_type_ != rhs.key_type())) {
66 168 : return false;
67 : }
68 :
69 20454 : for (size_t ocnt = 0; ocnt < rhs.key_chain().size(); ++ocnt) {
70 215 : bool found = false;
71 255 : for (size_t icnt = 0; icnt < key_chain_.size(); ++icnt) {
72 215 : if (key_chain_[icnt] == rhs.key_chain()[ocnt]) {
73 175 : found = true;
74 175 : break;
75 : }
76 : }
77 215 : if (!found) {
78 40 : return false;
79 : }
80 : }
81 20239 : return true;
82 : }
83 :
84 59551 : AuthenticationData &AuthenticationData::operator=(
85 : const AuthenticationData &rhs) {
86 59551 : set_key_type(rhs.key_type());
87 59551 : set_key_chain(rhs.key_chain());
88 59551 : return *this;
89 : }
90 :
91 657 : void AuthenticationData::AddKeyToKeyChain(const AuthenticationKey &key) {
92 657 : key_chain_.push_back(key);
93 657 : }
94 :
95 0 : const AuthenticationKey *AuthenticationData::Find(int key_id) const {
96 : const AuthenticationKey *item;
97 0 : for (size_t i = 0; i < key_chain_.size(); ++i) {
98 0 : item = &key_chain_[i];
99 0 : if (item->id == key_id) {
100 0 : return item;
101 : }
102 : }
103 0 : return NULL;
104 : }
105 :
106 30780 : bool AuthenticationData::Empty() const {
107 30780 : return key_chain_.empty();
108 : }
109 :
110 0 : void AuthenticationData::Clear() {
111 0 : key_chain_.clear();
112 0 : }
113 :
114 13417 : string AuthenticationData::KeyTypeToString() const {
115 13417 : switch (key_type_) {
116 344 : case MD5:
117 344 : return "MD5";
118 13073 : default:
119 13073 : return "NIL";
120 : }
121 : }
122 :
123 1695 : string AuthenticationData::KeyTypeToString(KeyType key_type) {
124 1695 : switch (key_type) {
125 1583 : case MD5:
126 1583 : return "MD5";
127 112 : default:
128 112 : return "NIL";
129 : }
130 : }
131 :
132 13412 : vector<string> AuthenticationData::KeysToString() const {
133 13412 : AuthenticationKeyChain::const_iterator iter;
134 13412 : vector<string> auth_keys;
135 13756 : for (iter = key_chain_.begin(); iter != key_chain_.end(); ++iter) {
136 344 : AuthenticationKey key = *iter;
137 344 : auth_keys.push_back(integerToString(key.id));
138 344 : }
139 26824 : return auth_keys;
140 0 : }
141 :
142 : // NOTE: This prints the actual key too. Use with care.
143 0 : vector<string> AuthenticationData::KeysToStringDetail() const {
144 0 : AuthenticationKeyChain::const_iterator iter;
145 0 : vector<string> auth_keys;
146 0 : for (iter = key_chain_.begin(); iter != key_chain_.end(); ++iter) {
147 0 : AuthenticationKey key = *iter;
148 0 : auth_keys.push_back(integerToString(key.id) + ":" + key.value);
149 0 : }
150 0 : return auth_keys;
151 0 : }
152 :
153 32053 : BgpNeighborConfig::OriginOverrideConfig::OriginOverrideConfig()
154 32053 : : origin_override(false), origin("IGP") {
155 32053 : }
156 :
157 43050 : bool BgpNeighborConfig::OriginOverrideConfig::operator<(
158 : const OriginOverrideConfig &rhs) const {
159 43050 : if (origin_override == rhs.origin_override) {
160 43050 : if (origin_override) {
161 : // chek origin value only if override is set
162 6 : return origin < rhs.origin;
163 : }
164 43044 : return false;
165 : }
166 :
167 0 : return origin_override < rhs.origin_override;
168 : }
169 :
170 1 : bool BgpFamilyAttributesConfig::operator==(
171 : const BgpFamilyAttributesConfig &rhs) const {
172 1 : if (family != rhs.family)
173 0 : return false;
174 1 : if (loop_count != rhs.loop_count)
175 0 : return false;
176 1 : if (prefix_limit != rhs.prefix_limit)
177 0 : return false;
178 1 : if (idle_timeout != rhs.idle_timeout)
179 0 : return false;
180 1 : if (default_tunnel_encap_list != rhs.default_tunnel_encap_list)
181 0 : return false;
182 1 : return true;
183 : }
184 :
185 32053 : BgpNeighborConfig::BgpNeighborConfig()
186 32053 : : type_(UNSPECIFIED),
187 32053 : admin_down_(false),
188 32053 : passive_(false),
189 32053 : as_override_(false),
190 32053 : cluster_id_(0),
191 32053 : peer_as_(0),
192 32053 : identifier_(0),
193 32053 : port_(BgpConfigManager::kDefaultPort),
194 32053 : source_port_(0),
195 32053 : hold_time_(0),
196 32053 : loop_count_(0),
197 32053 : local_as_(0),
198 32053 : local_identifier_(0),
199 32053 : last_change_at_(UTCTimestampUsec()) {
200 32053 : }
201 :
202 1 : void BgpNeighborConfig::CopyValues(const BgpNeighborConfig &rhs) {
203 1 : instance_name_ = rhs.instance_name_;
204 1 : group_name_ = rhs.group_name_;
205 1 : type_ = rhs.type_;
206 1 : admin_down_ = rhs.admin_down_;
207 1 : passive_ = rhs.passive_;
208 1 : as_override_ = rhs.as_override_;
209 1 : private_as_action_ = rhs.private_as_action_;
210 1 : cluster_id_ = rhs.cluster_id_;
211 1 : peer_as_ = rhs.peer_as_;
212 1 : identifier_ = rhs.identifier_;
213 1 : address_ = rhs.address_;
214 1 : inet_gateway_address_ = rhs.inet_gateway_address_;
215 1 : inet6_gateway_address_ = rhs.inet6_gateway_address_;
216 1 : port_ = rhs.port_;
217 1 : source_port_ = rhs.source_port_;
218 1 : hold_time_ = rhs.hold_time_;
219 1 : loop_count_ = rhs.loop_count_;
220 1 : local_as_ = rhs.local_as_;
221 1 : local_identifier_ = rhs.local_identifier_;
222 1 : auth_data_ = rhs.auth_data_;
223 1 : family_attributes_list_ = rhs.family_attributes_list_;
224 1 : origin_override_ = rhs.origin_override_;
225 1 : }
226 :
227 21681 : int BgpNeighborConfig::CompareTo(const BgpNeighborConfig &rhs) const {
228 21681 : KEY_COMPARE(name_, rhs.name_);
229 21681 : KEY_COMPARE(uuid_, rhs.uuid_);
230 21681 : KEY_COMPARE(instance_name_, rhs.instance_name_);
231 21681 : KEY_COMPARE(type_, rhs.type_);
232 21681 : KEY_COMPARE(admin_down_, rhs.admin_down_);
233 21561 : KEY_COMPARE(passive_, rhs.passive_);
234 21527 : KEY_COMPARE(as_override_, rhs.as_override_);
235 21525 : KEY_COMPARE(origin_override_, rhs.origin_override_);
236 21525 : KEY_COMPARE(private_as_action_, rhs.private_as_action_);
237 21522 : KEY_COMPARE(cluster_id_, rhs.cluster_id_);
238 21522 : KEY_COMPARE(peer_as_, rhs.peer_as_);
239 21327 : KEY_COMPARE(identifier_, rhs.identifier_);
240 21270 : KEY_COMPARE(address_, rhs.address_);
241 21270 : KEY_COMPARE(inet_gateway_address_, rhs.inet_gateway_address_);
242 21268 : KEY_COMPARE(inet6_gateway_address_, rhs.inet6_gateway_address_);
243 21268 : KEY_COMPARE(port_, rhs.port_);
244 21267 : KEY_COMPARE(source_port_, rhs.source_port_);
245 21259 : KEY_COMPARE(hold_time_, rhs.hold_time_);
246 21151 : KEY_COMPARE(loop_count_, rhs.loop_count_);
247 21151 : KEY_COMPARE(local_as_, rhs.local_as_);
248 21062 : KEY_COMPARE(local_identifier_, rhs.local_identifier_);
249 21052 : KEY_COMPARE(auth_data_, rhs.auth_data_);
250 20991 : return STLSortedCompare(
251 : family_attributes_list_.begin(), family_attributes_list_.end(),
252 : rhs.family_attributes_list_.begin(), rhs.family_attributes_list_.end(),
253 20991 : BgpFamilyAttributesConfigCompare());
254 : }
255 :
256 29215 : void BgpNeighborConfig::SetOriginOverride(bool origin_override,
257 : std::string origin) {
258 29215 : origin_override_.origin_override = origin_override;
259 29215 : origin_override_.origin = origin;
260 29215 : }
261 :
262 456 : const IpAddress &BgpNeighborConfig::gateway_address(
263 : Address::Family family) const {
264 456 : assert(family == Address::INET || family == Address::INET6);
265 456 : if (family == Address::INET) {
266 232 : return inet_gateway_address_;
267 : } else {
268 224 : return inet6_gateway_address_;
269 : }
270 : }
271 :
272 1046 : void BgpNeighborConfig::set_gateway_address(Address::Family family,
273 : const IpAddress &address) {
274 1046 : assert(family == Address::INET || family == Address::INET6);
275 1046 : if (family == Address::INET) {
276 523 : inet_gateway_address_ = address;
277 : } else {
278 523 : inet6_gateway_address_ = address;
279 : }
280 1046 : }
281 :
282 : BgpNeighborConfig::AddressFamilyList
283 33864 : BgpNeighborConfig::GetAddressFamilies() const {
284 33864 : BgpNeighborConfig::AddressFamilyList family_list;
285 85988 : for (const auto& family_config : family_attributes_list_) {
286 52124 : family_list.push_back(family_config.family);
287 : }
288 33864 : sort(family_list.begin(), family_list.end());
289 33864 : return family_list;
290 0 : }
291 :
292 13412 : string BgpNeighborConfig::AuthKeyTypeToString() const {
293 13412 : return auth_data_.KeyTypeToString();
294 : }
295 :
296 : // Return the key's id concatenated with its type.
297 13412 : vector<string> BgpNeighborConfig::AuthKeysToString() const {
298 13412 : return auth_data_.KeysToString();
299 : }
300 :
301 :
302 415 : bool StaticRouteConfig::operator<(const StaticRouteConfig &rhs) const {
303 415 : BOOL_KEY_COMPARE(address, rhs.address);
304 14 : BOOL_KEY_COMPARE(prefix_length, rhs.prefix_length);
305 14 : BOOL_KEY_COMPARE(nexthop, rhs.nexthop);
306 0 : return false;
307 : }
308 :
309 8596 : BgpProtocolConfig::BgpProtocolConfig(const string &instance_name)
310 8596 : : instance_name_(instance_name),
311 8596 : admin_down_(false),
312 8596 : cluster_id_(0),
313 8596 : autonomous_system_(0),
314 8596 : local_autonomous_system_(0),
315 8596 : identifier_(0),
316 8596 : port_(0),
317 8596 : hold_time_(0),
318 8596 : last_change_at_(UTCTimestampUsec()) {
319 8596 : }
320 :
321 0 : int BgpProtocolConfig::CompareTo(const BgpProtocolConfig &rhs) const {
322 0 : KEY_COMPARE(instance_name_, rhs.instance_name_);
323 0 : KEY_COMPARE(admin_down_, rhs.admin_down_);
324 0 : KEY_COMPARE(autonomous_system_, rhs.autonomous_system_);
325 0 : KEY_COMPARE(identifier_, rhs.identifier_);
326 0 : KEY_COMPARE(port_, rhs.port_);
327 0 : KEY_COMPARE(hold_time_, rhs.hold_time_);
328 0 : return 0;
329 : }
330 :
331 51338 : BgpInstanceConfig::BgpInstanceConfig(const string &name)
332 51338 : : name_(name),
333 51338 : has_pnf_(false),
334 51338 : virtual_network_index_(0),
335 51338 : virtual_network_allow_transit_(false),
336 51338 : virtual_network_pbb_evpn_enable_(false),
337 51338 : index_(-1),
338 51338 : vxlan_id_(0),
339 51338 : last_change_at_(UTCTimestampUsec()) {
340 51338 : }
341 :
342 51351 : BgpInstanceConfig::~BgpInstanceConfig() {
343 51351 : }
344 :
345 124505 : void BgpInstanceConfig::Clear() {
346 124505 : import_list_.clear();
347 124505 : export_list_.clear();
348 124505 : has_pnf_ = false;
349 124505 : virtual_network_.clear();
350 124505 : virtual_network_index_ = 0;
351 124505 : virtual_network_allow_transit_ = false;
352 124505 : virtual_network_pbb_evpn_enable_ = false;
353 124505 : vxlan_id_ = 0;
354 124505 : inet_static_routes_.clear();
355 124505 : inet6_static_routes_.clear();
356 124505 : service_chain_list_.clear();
357 124505 : }
358 :
359 100019 : const BgpInstanceConfig::StaticRouteList &BgpInstanceConfig::static_routes(
360 : Address::Family family) const {
361 100019 : assert(family == Address::INET || family == Address::INET6);
362 100019 : if (family == Address::INET) {
363 50028 : return inet_static_routes_;
364 : } else {
365 49991 : return inet6_static_routes_;
366 : }
367 : }
368 :
369 8450 : void BgpInstanceConfig::swap_static_routes(Address::Family family,
370 : StaticRouteList *list) {
371 8450 : assert(family == Address::INET || family == Address::INET6);
372 8450 : if (family == Address::INET) {
373 4225 : swap(inet_static_routes_, *list);
374 : } else {
375 4225 : swap(inet6_static_routes_, *list);
376 : }
377 8450 : }
378 :
379 591639 : const ServiceChainConfig *BgpInstanceConfig::service_chain_info(
380 : SCAddress::Family family) const {
381 591639 : for (ServiceChainList::const_iterator it = service_chain_list_.begin();
382 601172 : it != service_chain_list_.end(); ++it) {
383 16845 : if (it->family == family)
384 7313 : return it.operator->();
385 : }
386 584322 : return NULL;
387 : }
388 :
389 : const BgpInstanceConfig::AggregateRouteList &
390 100081 : BgpInstanceConfig::aggregate_routes(Address::Family family) const {
391 100081 : assert(family == Address::INET || family == Address::INET6);
392 100081 : if (family == Address::INET) {
393 50135 : return inet_aggregate_routes_;
394 : } else {
395 49946 : return inet6_aggregate_routes_;
396 : }
397 : }
398 :
399 249010 : void BgpInstanceConfig::swap_aggregate_routes(Address::Family family,
400 : AggregateRouteList *list) {
401 249010 : assert(family == Address::INET || family == Address::INET6);
402 249010 : if (family == Address::INET) {
403 124505 : swap(inet_aggregate_routes_, *list);
404 : } else {
405 124505 : swap(inet6_aggregate_routes_, *list);
406 : }
407 249010 : }
408 :
409 161 : BgpRoutingPolicyConfig::BgpRoutingPolicyConfig(const string &name)
410 161 : : name_(name),
411 161 : last_change_at_(UTCTimestampUsec()) {
412 161 : }
413 :
414 161 : BgpRoutingPolicyConfig::~BgpRoutingPolicyConfig() {
415 161 : }
416 :
417 397 : void BgpRoutingPolicyConfig::Clear() {
418 397 : terms_.clear();
419 397 : }
420 :
421 10 : string RoutingPolicyMatchConfig::ToString() const {
422 10 : ostringstream oss;
423 10 : oss << "from {" << endl;
424 10 : if (!protocols_match.empty()) {
425 0 : oss << " protocol [ ";
426 0 : for (const auto &protocol : protocols_match) {
427 0 : oss << protocol << ",";
428 : }
429 0 : oss.seekp(-1, oss.cur);
430 0 : oss << " ]";
431 : }
432 10 : if (!community_match.empty()) {
433 4 : if (community_match_all) {
434 0 : oss << " community (all) [ ";
435 : } else {
436 4 : oss << " community (any) [ ";
437 : }
438 8 : for (const auto &community : community_match) {
439 4 : oss << community << ",";
440 : }
441 4 : oss.seekp(-1, oss.cur);
442 4 : oss << " ]";
443 : }
444 10 : if (!prefixes_to_match.empty()) {
445 16 : for (const auto &match : prefixes_to_match) {
446 10 : oss << " prefix " << match.prefix_to_match << " "
447 10 : << match.prefix_match_type << endl;
448 : }
449 : }
450 10 : oss << "}" << endl;
451 20 : return oss.str();
452 10 : }
453 :
454 0 : static void PutAsnList(ostringstream *oss, const AsnList &list) {
455 0 : copy(list.begin(), list.end(), ostream_iterator<uint16_t>(*oss, ","));
456 0 : oss->seekp(-1, oss->cur);
457 0 : }
458 :
459 6 : static void PutCommunityList(ostringstream *oss, const CommunityList &list) {
460 6 : copy(list.begin(), list.end(), ostream_iterator<string>(*oss, ","));
461 6 : oss->seekp(-1, oss->cur);
462 6 : }
463 :
464 10 : string RoutingPolicyActionConfig::ToString() const {
465 10 : ostringstream oss;
466 10 : oss << "then {" << endl;
467 10 : if (!update.aspath_expand.empty()) {
468 0 : oss << " as-path expand [ ";
469 0 : PutAsnList(&oss, update.aspath_expand);
470 0 : oss << " ]" << endl;
471 : }
472 10 : if (!update.community_set.empty()) {
473 2 : oss << " community set [ ";
474 2 : PutCommunityList(&oss, update.community_set);
475 2 : oss << " ]" << endl;
476 : }
477 10 : if (!update.community_add.empty()) {
478 0 : oss << " community add [ ";
479 0 : PutCommunityList(&oss, update.community_add);
480 0 : oss << " ]" << endl;
481 : }
482 10 : if (!update.community_remove.empty()) {
483 4 : oss << " community remove [ ";
484 4 : PutCommunityList(&oss, update.community_remove);
485 4 : oss << " ]" << endl;
486 : }
487 10 : if (update.local_pref) {
488 6 : oss << " local-preference " << update.local_pref << endl;
489 : }
490 10 : if (update.med) {
491 0 : oss << " med " << update.med << endl;
492 : }
493 :
494 10 : if (action == ACCEPT) {
495 2 : oss << " accept" << endl;
496 8 : } else if (action == REJECT) {
497 4 : oss << " reject" << endl;
498 4 : } else if (action == NEXT_TERM) {
499 4 : oss << " next-term" << endl;
500 : }
501 10 : oss << "}" << endl;
502 20 : return oss.str();
503 10 : }
504 :
505 9743 : BgpConfigManager::BgpConfigManager(BgpServer *server)
506 9743 : : server_(server) {
507 9743 : }
508 :
509 9743 : BgpConfigManager::~BgpConfigManager() {
510 9743 : }
511 :
512 : template<>
513 160004 : void BgpConfigManager::Notify<BgpInstanceConfig>(
514 : const BgpInstanceConfig *config, EventType event) {
515 160004 : config->set_last_change_at(UTCTimestampUsec());
516 355725 : for (auto obs : obs_) {
517 195721 : if (obs.instance) {
518 160004 : (obs.instance)(config, event);
519 : }
520 195721 : }
521 160004 : }
522 :
523 : template<>
524 440 : void BgpConfigManager::Notify<BgpRoutingPolicyConfig>(
525 : const BgpRoutingPolicyConfig *config, EventType event) {
526 440 : config->set_last_change_at(UTCTimestampUsec());
527 890 : for (auto obs : obs_) {
528 450 : if (obs.policy) {
529 440 : (obs.policy)(config, event);
530 : }
531 450 : }
532 440 : }
533 :
534 : template<>
535 9051 : void BgpConfigManager::Notify<BgpProtocolConfig>(
536 : const BgpProtocolConfig *config, EventType event) {
537 9051 : config->set_last_change_at(UTCTimestampUsec());
538 20789 : for (auto obs : obs_) {
539 11738 : if (obs.protocol) {
540 11738 : (obs.protocol)(config, event);
541 : }
542 11738 : }
543 9051 : }
544 :
545 : template<>
546 16914 : void BgpConfigManager::Notify<BgpNeighborConfig>(
547 : const BgpNeighborConfig *config, EventType event) {
548 16914 : config->set_last_change_at(UTCTimestampUsec());
549 37192 : for (auto obs : obs_) {
550 20278 : if (obs.neighbor) {
551 16914 : (obs.neighbor)(config, event);
552 : }
553 20278 : }
554 16914 : }
555 :
556 : template<>
557 867 : void BgpConfigManager::Notify<BgpGlobalSystemConfig>(
558 : const BgpGlobalSystemConfig *config, EventType event) {
559 867 : config->set_last_change_at(UTCTimestampUsec());
560 2206 : for (auto obs : obs_) {
561 1339 : if (obs.system) {
562 1339 : (obs.system)(config, event);
563 : }
564 1339 : }
565 867 : }
566 :
567 : template<>
568 9 : void BgpConfigManager::Notify<BgpGlobalQosConfig>(
569 : const BgpGlobalQosConfig *config, EventType event) {
570 9 : config->set_last_change_at(UTCTimestampUsec());
571 25 : for (auto obs : obs_) {
572 16 : if (obs.qos) {
573 9 : (obs.qos)(config, event);
574 : }
575 16 : }
576 9 : }
|