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 101733 : AuthenticationData::AuthenticationData() : key_type_(NIL) {
50 101733 : }
51 :
52 0 : AuthenticationData::AuthenticationData(KeyType type,
53 0 : const AuthenticationKeyChain &chain) :
54 0 : key_type_(type), key_chain_(chain) {
55 0 : }
56 :
57 42046 : bool AuthenticationData::operator<(const AuthenticationData &rhs) const {
58 42046 : BOOL_KEY_COMPARE(key_type_, rhs.key_type());
59 42027 : BOOL_KEY_COMPARE(key_chain_, rhs.key_chain());
60 41970 : return false;
61 : }
62 :
63 20430 : bool AuthenticationData::operator==(const AuthenticationData &rhs) const {
64 40692 : if ((key_chain_.size() != rhs.key_chain().size()) ||
65 20262 : (key_type_ != rhs.key_type())) {
66 168 : return false;
67 : }
68 :
69 20437 : 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 20222 : return true;
82 : }
83 :
84 59539 : AuthenticationData &AuthenticationData::operator=(
85 : const AuthenticationData &rhs) {
86 59539 : set_key_type(rhs.key_type());
87 59539 : set_key_chain(rhs.key_chain());
88 59539 : 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 30777 : bool AuthenticationData::Empty() const {
107 30777 : return key_chain_.empty();
108 : }
109 :
110 0 : void AuthenticationData::Clear() {
111 0 : key_chain_.clear();
112 0 : }
113 :
114 13411 : string AuthenticationData::KeyTypeToString() const {
115 13411 : switch (key_type_) {
116 344 : case MD5:
117 344 : return "MD5";
118 13067 : default:
119 13067 : return "NIL";
120 : }
121 : }
122 :
123 1738 : string AuthenticationData::KeyTypeToString(KeyType key_type) {
124 1738 : switch (key_type) {
125 1626 : case MD5:
126 1626 : return "MD5";
127 112 : default:
128 112 : return "NIL";
129 : }
130 : }
131 :
132 13406 : vector<string> AuthenticationData::KeysToString() const {
133 13406 : AuthenticationKeyChain::const_iterator iter;
134 13406 : vector<string> auth_keys;
135 13750 : 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 26812 : 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 32045 : BgpNeighborConfig::OriginOverrideConfig::OriginOverrideConfig()
154 32045 : : origin_override(false), origin("IGP") {
155 32045 : }
156 :
157 43044 : bool BgpNeighborConfig::OriginOverrideConfig::operator<(
158 : const OriginOverrideConfig &rhs) const {
159 43044 : if (origin_override == rhs.origin_override) {
160 43044 : if (origin_override) {
161 : // chek origin value only if override is set
162 6 : return origin < rhs.origin;
163 : }
164 43038 : 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 32045 : BgpNeighborConfig::BgpNeighborConfig()
186 32045 : : type_(UNSPECIFIED),
187 32045 : admin_down_(false),
188 32045 : passive_(false),
189 32045 : as_override_(false),
190 32045 : cluster_id_(0),
191 32045 : peer_as_(0),
192 32045 : identifier_(0),
193 32045 : port_(BgpConfigManager::kDefaultPort),
194 32045 : source_port_(0),
195 32045 : hold_time_(0),
196 32045 : loop_count_(0),
197 32045 : local_as_(0),
198 32045 : local_identifier_(0),
199 32045 : last_change_at_(UTCTimestampUsec()) {
200 32045 : }
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 21675 : int BgpNeighborConfig::CompareTo(const BgpNeighborConfig &rhs) const {
228 21675 : KEY_COMPARE(name_, rhs.name_);
229 21675 : KEY_COMPARE(uuid_, rhs.uuid_);
230 21675 : KEY_COMPARE(instance_name_, rhs.instance_name_);
231 21675 : KEY_COMPARE(type_, rhs.type_);
232 21675 : KEY_COMPARE(admin_down_, rhs.admin_down_);
233 21555 : KEY_COMPARE(passive_, rhs.passive_);
234 21524 : KEY_COMPARE(as_override_, rhs.as_override_);
235 21522 : KEY_COMPARE(origin_override_, rhs.origin_override_);
236 21522 : KEY_COMPARE(private_as_action_, rhs.private_as_action_);
237 21519 : KEY_COMPARE(cluster_id_, rhs.cluster_id_);
238 21519 : KEY_COMPARE(peer_as_, rhs.peer_as_);
239 21324 : KEY_COMPARE(identifier_, rhs.identifier_);
240 21267 : KEY_COMPARE(address_, rhs.address_);
241 21267 : KEY_COMPARE(inet_gateway_address_, rhs.inet_gateway_address_);
242 21265 : KEY_COMPARE(inet6_gateway_address_, rhs.inet6_gateway_address_);
243 21265 : KEY_COMPARE(port_, rhs.port_);
244 21264 : KEY_COMPARE(source_port_, rhs.source_port_);
245 21256 : KEY_COMPARE(hold_time_, rhs.hold_time_);
246 21148 : KEY_COMPARE(loop_count_, rhs.loop_count_);
247 21148 : KEY_COMPARE(local_as_, rhs.local_as_);
248 21059 : KEY_COMPARE(local_identifier_, rhs.local_identifier_);
249 21046 : KEY_COMPARE(auth_data_, rhs.auth_data_);
250 20985 : return STLSortedCompare(
251 : family_attributes_list_.begin(), family_attributes_list_.end(),
252 : rhs.family_attributes_list_.begin(), rhs.family_attributes_list_.end(),
253 20985 : BgpFamilyAttributesConfigCompare());
254 : }
255 :
256 29206 : void BgpNeighborConfig::SetOriginOverride(bool origin_override,
257 : std::string origin) {
258 29206 : origin_override_.origin_override = origin_override;
259 29206 : origin_override_.origin = origin;
260 29206 : }
261 :
262 423 : const IpAddress &BgpNeighborConfig::gateway_address(
263 : Address::Family family) const {
264 423 : assert(family == Address::INET || family == Address::INET6);
265 423 : if (family == Address::INET) {
266 215 : return inet_gateway_address_;
267 : } else {
268 208 : return inet6_gateway_address_;
269 : }
270 : }
271 :
272 1034 : void BgpNeighborConfig::set_gateway_address(Address::Family family,
273 : const IpAddress &address) {
274 1034 : assert(family == Address::INET || family == Address::INET6);
275 1034 : if (family == Address::INET) {
276 517 : inet_gateway_address_ = address;
277 : } else {
278 517 : inet6_gateway_address_ = address;
279 : }
280 1034 : }
281 :
282 : BgpNeighborConfig::AddressFamilyList
283 33841 : BgpNeighborConfig::GetAddressFamilies() const {
284 33841 : BgpNeighborConfig::AddressFamilyList family_list;
285 85898 : for (const auto& family_config : family_attributes_list_) {
286 52057 : family_list.push_back(family_config.family);
287 : }
288 33841 : sort(family_list.begin(), family_list.end());
289 33841 : return family_list;
290 0 : }
291 :
292 13406 : string BgpNeighborConfig::AuthKeyTypeToString() const {
293 13406 : return auth_data_.KeyTypeToString();
294 : }
295 :
296 : // Return the key's id concatenated with its type.
297 13406 : vector<string> BgpNeighborConfig::AuthKeysToString() const {
298 13406 : 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 8595 : BgpProtocolConfig::BgpProtocolConfig(const string &instance_name)
310 8595 : : instance_name_(instance_name),
311 8595 : admin_down_(false),
312 8595 : cluster_id_(0),
313 8595 : autonomous_system_(0),
314 8595 : local_autonomous_system_(0),
315 8595 : identifier_(0),
316 8595 : port_(0),
317 8595 : hold_time_(0),
318 8595 : last_change_at_(UTCTimestampUsec()) {
319 8595 : }
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 51334 : BgpInstanceConfig::BgpInstanceConfig(const string &name)
332 51334 : : name_(name),
333 51334 : has_pnf_(false),
334 51334 : virtual_network_index_(0),
335 51334 : virtual_network_allow_transit_(false),
336 51334 : virtual_network_pbb_evpn_enable_(false),
337 51334 : index_(-1),
338 51334 : vxlan_id_(0),
339 51334 : last_change_at_(UTCTimestampUsec()) {
340 51334 : }
341 :
342 51347 : BgpInstanceConfig::~BgpInstanceConfig() {
343 51347 : }
344 :
345 124459 : void BgpInstanceConfig::Clear() {
346 124459 : import_list_.clear();
347 124459 : export_list_.clear();
348 124459 : has_pnf_ = false;
349 124459 : virtual_network_.clear();
350 124459 : virtual_network_index_ = 0;
351 124459 : virtual_network_allow_transit_ = false;
352 124459 : virtual_network_pbb_evpn_enable_ = false;
353 124459 : vxlan_id_ = 0;
354 124459 : inet_static_routes_.clear();
355 124459 : inet6_static_routes_.clear();
356 124459 : service_chain_list_.clear();
357 124459 : }
358 :
359 100103 : const BgpInstanceConfig::StaticRouteList &BgpInstanceConfig::static_routes(
360 : Address::Family family) const {
361 100103 : assert(family == Address::INET || family == Address::INET6);
362 100103 : if (family == Address::INET) {
363 50071 : return inet_static_routes_;
364 : } else {
365 50032 : return inet6_static_routes_;
366 : }
367 : }
368 :
369 8444 : void BgpInstanceConfig::swap_static_routes(Address::Family family,
370 : StaticRouteList *list) {
371 8444 : assert(family == Address::INET || family == Address::INET6);
372 8444 : if (family == Address::INET) {
373 4222 : swap(inet_static_routes_, *list);
374 : } else {
375 4222 : swap(inet6_static_routes_, *list);
376 : }
377 8444 : }
378 :
379 592392 : const ServiceChainConfig *BgpInstanceConfig::service_chain_info(
380 : SCAddress::Family family) const {
381 592392 : for (ServiceChainList::const_iterator it = service_chain_list_.begin();
382 601955 : it != service_chain_list_.end(); ++it) {
383 16837 : if (it->family == family)
384 7305 : return it.operator->();
385 : }
386 585107 : return NULL;
387 : }
388 :
389 : const BgpInstanceConfig::AggregateRouteList &
390 100169 : BgpInstanceConfig::aggregate_routes(Address::Family family) const {
391 100169 : assert(family == Address::INET || family == Address::INET6);
392 100169 : if (family == Address::INET) {
393 50175 : return inet_aggregate_routes_;
394 : } else {
395 49994 : return inet6_aggregate_routes_;
396 : }
397 : }
398 :
399 248918 : void BgpInstanceConfig::swap_aggregate_routes(Address::Family family,
400 : AggregateRouteList *list) {
401 248918 : assert(family == Address::INET || family == Address::INET6);
402 248918 : if (family == Address::INET) {
403 124459 : swap(inet_aggregate_routes_, *list);
404 : } else {
405 124459 : swap(inet6_aggregate_routes_, *list);
406 : }
407 248918 : }
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 396 : void BgpRoutingPolicyConfig::Clear() {
418 396 : terms_.clear();
419 396 : }
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 9742 : BgpConfigManager::BgpConfigManager(BgpServer *server)
506 9742 : : server_(server) {
507 9742 : }
508 :
509 9742 : BgpConfigManager::~BgpConfigManager() {
510 9742 : }
511 :
512 : template<>
513 160847 : void BgpConfigManager::Notify<BgpInstanceConfig>(
514 : const BgpInstanceConfig *config, EventType event) {
515 160847 : config->set_last_change_at(UTCTimestampUsec());
516 357489 : for (auto obs : obs_) {
517 196642 : if (obs.instance) {
518 160847 : (obs.instance)(config, event);
519 : }
520 196642 : }
521 160847 : }
522 :
523 : template<>
524 439 : void BgpConfigManager::Notify<BgpRoutingPolicyConfig>(
525 : const BgpRoutingPolicyConfig *config, EventType event) {
526 439 : config->set_last_change_at(UTCTimestampUsec());
527 888 : for (auto obs : obs_) {
528 449 : if (obs.policy) {
529 439 : (obs.policy)(config, event);
530 : }
531 449 : }
532 439 : }
533 :
534 : template<>
535 9049 : void BgpConfigManager::Notify<BgpProtocolConfig>(
536 : const BgpProtocolConfig *config, EventType event) {
537 9049 : config->set_last_change_at(UTCTimestampUsec());
538 20784 : for (auto obs : obs_) {
539 11735 : if (obs.protocol) {
540 11735 : (obs.protocol)(config, event);
541 : }
542 11735 : }
543 9049 : }
544 :
545 : template<>
546 16910 : void BgpConfigManager::Notify<BgpNeighborConfig>(
547 : const BgpNeighborConfig *config, EventType event) {
548 16910 : config->set_last_change_at(UTCTimestampUsec());
549 37182 : for (auto obs : obs_) {
550 20272 : if (obs.neighbor) {
551 16910 : (obs.neighbor)(config, event);
552 : }
553 20272 : }
554 16910 : }
555 :
556 : template<>
557 850 : void BgpConfigManager::Notify<BgpGlobalSystemConfig>(
558 : const BgpGlobalSystemConfig *config, EventType event) {
559 850 : config->set_last_change_at(UTCTimestampUsec());
560 2168 : for (auto obs : obs_) {
561 1318 : if (obs.system) {
562 1318 : (obs.system)(config, event);
563 : }
564 1318 : }
565 850 : }
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 : }
|