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 0 : static int CompareTo(const AuthenticationKey &lhs,
32 : const AuthenticationKey &rhs) {
33 0 : KEY_COMPARE(lhs.id, rhs.id);
34 0 : KEY_COMPARE(lhs.value, rhs.value);
35 0 : KEY_COMPARE(lhs.start_time, rhs.start_time);
36 0 : return 0;
37 : }
38 :
39 0 : bool AuthenticationKey::operator<(const AuthenticationKey &rhs) const {
40 0 : int cmp = CompareTo(*this, rhs);
41 0 : return cmp < 0;
42 : }
43 :
44 0 : bool AuthenticationKey::operator==(const AuthenticationKey &rhs) const {
45 0 : int cmp = CompareTo(*this, rhs);
46 0 : return cmp == 0;
47 : }
48 :
49 256 : AuthenticationData::AuthenticationData() : key_type_(NIL) {
50 256 : }
51 :
52 0 : AuthenticationData::AuthenticationData(KeyType type,
53 0 : const AuthenticationKeyChain &chain) :
54 0 : key_type_(type), key_chain_(chain) {
55 0 : }
56 :
57 64 : bool AuthenticationData::operator<(const AuthenticationData &rhs) const {
58 64 : BOOL_KEY_COMPARE(key_type_, rhs.key_type());
59 64 : BOOL_KEY_COMPARE(key_chain_, rhs.key_chain());
60 64 : return false;
61 : }
62 :
63 112 : bool AuthenticationData::operator==(const AuthenticationData &rhs) const {
64 224 : if ((key_chain_.size() != rhs.key_chain().size()) ||
65 112 : (key_type_ != rhs.key_type())) {
66 0 : return false;
67 : }
68 :
69 112 : for (size_t ocnt = 0; ocnt < rhs.key_chain().size(); ++ocnt) {
70 0 : bool found = false;
71 0 : for (size_t icnt = 0; icnt < key_chain_.size(); ++icnt) {
72 0 : if (key_chain_[icnt] == rhs.key_chain()[ocnt]) {
73 0 : found = true;
74 0 : break;
75 : }
76 : }
77 0 : if (!found) {
78 0 : return false;
79 : }
80 : }
81 112 : return true;
82 : }
83 :
84 64 : AuthenticationData &AuthenticationData::operator=(
85 : const AuthenticationData &rhs) {
86 64 : set_key_type(rhs.key_type());
87 64 : set_key_chain(rhs.key_chain());
88 64 : return *this;
89 : }
90 :
91 0 : void AuthenticationData::AddKeyToKeyChain(const AuthenticationKey &key) {
92 0 : key_chain_.push_back(key);
93 0 : }
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 64 : bool AuthenticationData::Empty() const {
107 64 : return key_chain_.empty();
108 : }
109 :
110 0 : void AuthenticationData::Clear() {
111 0 : key_chain_.clear();
112 0 : }
113 :
114 0 : string AuthenticationData::KeyTypeToString() const {
115 0 : switch (key_type_) {
116 0 : case MD5:
117 0 : return "MD5";
118 0 : default:
119 0 : return "NIL";
120 : }
121 : }
122 :
123 0 : string AuthenticationData::KeyTypeToString(KeyType key_type) {
124 0 : switch (key_type) {
125 0 : case MD5:
126 0 : return "MD5";
127 0 : default:
128 0 : return "NIL";
129 : }
130 : }
131 :
132 0 : vector<string> AuthenticationData::KeysToString() const {
133 0 : AuthenticationKeyChain::const_iterator iter;
134 0 : vector<string> auth_keys;
135 0 : for (iter = key_chain_.begin(); iter != key_chain_.end(); ++iter) {
136 0 : AuthenticationKey key = *iter;
137 0 : auth_keys.push_back(integerToString(key.id));
138 0 : }
139 0 : 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 112 : BgpNeighborConfig::OriginOverrideConfig::OriginOverrideConfig()
154 112 : : origin_override(false), origin("IGP") {
155 112 : }
156 :
157 64 : bool BgpNeighborConfig::OriginOverrideConfig::operator<(
158 : const OriginOverrideConfig &rhs) const {
159 64 : if (origin_override == rhs.origin_override) {
160 64 : if (origin_override) {
161 : // chek origin value only if override is set
162 0 : return origin < rhs.origin;
163 : }
164 64 : return false;
165 : }
166 :
167 0 : return origin_override < rhs.origin_override;
168 : }
169 :
170 0 : bool BgpFamilyAttributesConfig::operator==(
171 : const BgpFamilyAttributesConfig &rhs) const {
172 0 : if (family != rhs.family)
173 0 : return false;
174 0 : if (loop_count != rhs.loop_count)
175 0 : return false;
176 0 : if (prefix_limit != rhs.prefix_limit)
177 0 : return false;
178 0 : if (idle_timeout != rhs.idle_timeout)
179 0 : return false;
180 0 : if (default_tunnel_encap_list != rhs.default_tunnel_encap_list)
181 0 : return false;
182 0 : return true;
183 : }
184 :
185 112 : BgpNeighborConfig::BgpNeighborConfig()
186 112 : : type_(UNSPECIFIED),
187 112 : admin_down_(false),
188 112 : passive_(false),
189 112 : as_override_(false),
190 112 : cluster_id_(0),
191 112 : peer_as_(0),
192 112 : identifier_(0),
193 112 : port_(BgpConfigManager::kDefaultPort),
194 112 : source_port_(0),
195 112 : hold_time_(0),
196 112 : loop_count_(0),
197 112 : local_as_(0),
198 112 : local_identifier_(0),
199 112 : last_change_at_(UTCTimestampUsec()) {
200 112 : }
201 :
202 0 : void BgpNeighborConfig::CopyValues(const BgpNeighborConfig &rhs) {
203 0 : instance_name_ = rhs.instance_name_;
204 0 : group_name_ = rhs.group_name_;
205 0 : type_ = rhs.type_;
206 0 : admin_down_ = rhs.admin_down_;
207 0 : passive_ = rhs.passive_;
208 0 : as_override_ = rhs.as_override_;
209 0 : private_as_action_ = rhs.private_as_action_;
210 0 : cluster_id_ = rhs.cluster_id_;
211 0 : peer_as_ = rhs.peer_as_;
212 0 : identifier_ = rhs.identifier_;
213 0 : address_ = rhs.address_;
214 0 : inet_gateway_address_ = rhs.inet_gateway_address_;
215 0 : inet6_gateway_address_ = rhs.inet6_gateway_address_;
216 0 : port_ = rhs.port_;
217 0 : source_port_ = rhs.source_port_;
218 0 : hold_time_ = rhs.hold_time_;
219 0 : loop_count_ = rhs.loop_count_;
220 0 : local_as_ = rhs.local_as_;
221 0 : local_identifier_ = rhs.local_identifier_;
222 0 : auth_data_ = rhs.auth_data_;
223 0 : family_attributes_list_ = rhs.family_attributes_list_;
224 0 : origin_override_ = rhs.origin_override_;
225 0 : }
226 :
227 32 : int BgpNeighborConfig::CompareTo(const BgpNeighborConfig &rhs) const {
228 32 : KEY_COMPARE(name_, rhs.name_);
229 32 : KEY_COMPARE(uuid_, rhs.uuid_);
230 32 : KEY_COMPARE(instance_name_, rhs.instance_name_);
231 32 : KEY_COMPARE(type_, rhs.type_);
232 32 : KEY_COMPARE(admin_down_, rhs.admin_down_);
233 32 : KEY_COMPARE(passive_, rhs.passive_);
234 32 : KEY_COMPARE(as_override_, rhs.as_override_);
235 32 : KEY_COMPARE(origin_override_, rhs.origin_override_);
236 32 : KEY_COMPARE(private_as_action_, rhs.private_as_action_);
237 32 : KEY_COMPARE(cluster_id_, rhs.cluster_id_);
238 32 : KEY_COMPARE(peer_as_, rhs.peer_as_);
239 32 : KEY_COMPARE(identifier_, rhs.identifier_);
240 32 : KEY_COMPARE(address_, rhs.address_);
241 32 : KEY_COMPARE(inet_gateway_address_, rhs.inet_gateway_address_);
242 32 : KEY_COMPARE(inet6_gateway_address_, rhs.inet6_gateway_address_);
243 32 : KEY_COMPARE(port_, rhs.port_);
244 32 : KEY_COMPARE(source_port_, rhs.source_port_);
245 32 : KEY_COMPARE(hold_time_, rhs.hold_time_);
246 32 : KEY_COMPARE(loop_count_, rhs.loop_count_);
247 32 : KEY_COMPARE(local_as_, rhs.local_as_);
248 32 : KEY_COMPARE(local_identifier_, rhs.local_identifier_);
249 32 : KEY_COMPARE(auth_data_, rhs.auth_data_);
250 32 : return STLSortedCompare(
251 : family_attributes_list_.begin(), family_attributes_list_.end(),
252 : rhs.family_attributes_list_.begin(), rhs.family_attributes_list_.end(),
253 32 : BgpFamilyAttributesConfigCompare());
254 : }
255 :
256 0 : void BgpNeighborConfig::SetOriginOverride(bool origin_override,
257 : std::string origin) {
258 0 : origin_override_.origin_override = origin_override;
259 0 : origin_override_.origin = origin;
260 0 : }
261 :
262 0 : const IpAddress &BgpNeighborConfig::gateway_address(
263 : Address::Family family) const {
264 0 : assert(family == Address::INET || family == Address::INET6);
265 0 : if (family == Address::INET) {
266 0 : return inet_gateway_address_;
267 : } else {
268 0 : return inet6_gateway_address_;
269 : }
270 : }
271 :
272 0 : void BgpNeighborConfig::set_gateway_address(Address::Family family,
273 : const IpAddress &address) {
274 0 : assert(family == Address::INET || family == Address::INET6);
275 0 : if (family == Address::INET) {
276 0 : inet_gateway_address_ = address;
277 : } else {
278 0 : inet6_gateway_address_ = address;
279 : }
280 0 : }
281 :
282 : BgpNeighborConfig::AddressFamilyList
283 112 : BgpNeighborConfig::GetAddressFamilies() const {
284 112 : BgpNeighborConfig::AddressFamilyList family_list;
285 304 : for (const auto& family_config : family_attributes_list_) {
286 192 : family_list.push_back(family_config.family);
287 : }
288 112 : sort(family_list.begin(), family_list.end());
289 112 : return family_list;
290 0 : }
291 :
292 0 : string BgpNeighborConfig::AuthKeyTypeToString() const {
293 0 : return auth_data_.KeyTypeToString();
294 : }
295 :
296 : // Return the key's id concatenated with its type.
297 0 : vector<string> BgpNeighborConfig::AuthKeysToString() const {
298 0 : return auth_data_.KeysToString();
299 : }
300 :
301 :
302 0 : bool StaticRouteConfig::operator<(const StaticRouteConfig &rhs) const {
303 0 : BOOL_KEY_COMPARE(address, rhs.address);
304 0 : BOOL_KEY_COMPARE(prefix_length, rhs.prefix_length);
305 0 : BOOL_KEY_COMPARE(nexthop, rhs.nexthop);
306 0 : return false;
307 : }
308 :
309 32 : BgpProtocolConfig::BgpProtocolConfig(const string &instance_name)
310 32 : : instance_name_(instance_name),
311 32 : admin_down_(false),
312 32 : cluster_id_(0),
313 32 : autonomous_system_(0),
314 32 : local_autonomous_system_(0),
315 32 : identifier_(0),
316 32 : port_(0),
317 32 : hold_time_(0),
318 32 : last_change_at_(UTCTimestampUsec()) {
319 32 : }
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 128 : BgpInstanceConfig::BgpInstanceConfig(const string &name)
332 128 : : name_(name),
333 128 : has_pnf_(false),
334 128 : virtual_network_index_(0),
335 128 : virtual_network_allow_transit_(false),
336 128 : virtual_network_pbb_evpn_enable_(false),
337 128 : index_(-1),
338 128 : vxlan_id_(0),
339 128 : last_change_at_(UTCTimestampUsec()) {
340 128 : }
341 :
342 128 : BgpInstanceConfig::~BgpInstanceConfig() {
343 128 : }
344 :
345 224 : void BgpInstanceConfig::Clear() {
346 224 : import_list_.clear();
347 224 : export_list_.clear();
348 224 : has_pnf_ = false;
349 224 : virtual_network_.clear();
350 224 : virtual_network_index_ = 0;
351 224 : virtual_network_allow_transit_ = false;
352 224 : virtual_network_pbb_evpn_enable_ = false;
353 224 : vxlan_id_ = 0;
354 224 : inet_static_routes_.clear();
355 224 : inet6_static_routes_.clear();
356 224 : service_chain_list_.clear();
357 224 : }
358 :
359 192 : const BgpInstanceConfig::StaticRouteList &BgpInstanceConfig::static_routes(
360 : Address::Family family) const {
361 192 : assert(family == Address::INET || family == Address::INET6);
362 192 : if (family == Address::INET) {
363 96 : return inet_static_routes_;
364 : } else {
365 96 : return inet6_static_routes_;
366 : }
367 : }
368 :
369 0 : void BgpInstanceConfig::swap_static_routes(Address::Family family,
370 : StaticRouteList *list) {
371 0 : assert(family == Address::INET || family == Address::INET6);
372 0 : if (family == Address::INET) {
373 0 : swap(inet_static_routes_, *list);
374 : } else {
375 0 : swap(inet6_static_routes_, *list);
376 : }
377 0 : }
378 :
379 423 : const ServiceChainConfig *BgpInstanceConfig::service_chain_info(
380 : SCAddress::Family family) const {
381 423 : for (ServiceChainList::const_iterator it = service_chain_list_.begin();
382 423 : it != service_chain_list_.end(); ++it) {
383 0 : if (it->family == family)
384 0 : return it.operator->();
385 : }
386 422 : return NULL;
387 : }
388 :
389 : const BgpInstanceConfig::AggregateRouteList &
390 192 : BgpInstanceConfig::aggregate_routes(Address::Family family) const {
391 192 : assert(family == Address::INET || family == Address::INET6);
392 192 : if (family == Address::INET) {
393 96 : return inet_aggregate_routes_;
394 : } else {
395 96 : return inet6_aggregate_routes_;
396 : }
397 : }
398 :
399 448 : void BgpInstanceConfig::swap_aggregate_routes(Address::Family family,
400 : AggregateRouteList *list) {
401 448 : assert(family == Address::INET || family == Address::INET6);
402 448 : if (family == Address::INET) {
403 224 : swap(inet_aggregate_routes_, *list);
404 : } else {
405 224 : swap(inet6_aggregate_routes_, *list);
406 : }
407 448 : }
408 :
409 0 : BgpRoutingPolicyConfig::BgpRoutingPolicyConfig(const string &name)
410 0 : : name_(name),
411 0 : last_change_at_(UTCTimestampUsec()) {
412 0 : }
413 :
414 0 : BgpRoutingPolicyConfig::~BgpRoutingPolicyConfig() {
415 0 : }
416 :
417 0 : void BgpRoutingPolicyConfig::Clear() {
418 0 : terms_.clear();
419 0 : }
420 :
421 0 : string RoutingPolicyMatchConfig::ToString() const {
422 0 : ostringstream oss;
423 0 : oss << "from {" << endl;
424 0 : 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 0 : if (!community_match.empty()) {
433 0 : if (community_match_all) {
434 0 : oss << " community (all) [ ";
435 : } else {
436 0 : oss << " community (any) [ ";
437 : }
438 0 : for (const auto &community : community_match) {
439 0 : oss << community << ",";
440 : }
441 0 : oss.seekp(-1, oss.cur);
442 0 : oss << " ]";
443 : }
444 0 : if (!prefixes_to_match.empty()) {
445 0 : for (const auto &match : prefixes_to_match) {
446 0 : oss << " prefix " << match.prefix_to_match << " "
447 0 : << match.prefix_match_type << endl;
448 : }
449 : }
450 0 : oss << "}" << endl;
451 0 : return oss.str();
452 0 : }
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 0 : static void PutCommunityList(ostringstream *oss, const CommunityList &list) {
460 0 : copy(list.begin(), list.end(), ostream_iterator<string>(*oss, ","));
461 0 : oss->seekp(-1, oss->cur);
462 0 : }
463 :
464 0 : string RoutingPolicyActionConfig::ToString() const {
465 0 : ostringstream oss;
466 0 : oss << "then {" << endl;
467 0 : if (!update.aspath_expand.empty()) {
468 0 : oss << " as-path expand [ ";
469 0 : PutAsnList(&oss, update.aspath_expand);
470 0 : oss << " ]" << endl;
471 : }
472 0 : if (!update.community_set.empty()) {
473 0 : oss << " community set [ ";
474 0 : PutCommunityList(&oss, update.community_set);
475 0 : oss << " ]" << endl;
476 : }
477 0 : if (!update.community_add.empty()) {
478 0 : oss << " community add [ ";
479 0 : PutCommunityList(&oss, update.community_add);
480 0 : oss << " ]" << endl;
481 : }
482 0 : if (!update.community_remove.empty()) {
483 0 : oss << " community remove [ ";
484 0 : PutCommunityList(&oss, update.community_remove);
485 0 : oss << " ]" << endl;
486 : }
487 0 : if (update.local_pref) {
488 0 : oss << " local-preference " << update.local_pref << endl;
489 : }
490 0 : if (update.med) {
491 0 : oss << " med " << update.med << endl;
492 : }
493 :
494 0 : if (action == ACCEPT) {
495 0 : oss << " accept" << endl;
496 0 : } else if (action == REJECT) {
497 0 : oss << " reject" << endl;
498 0 : } else if (action == NEXT_TERM) {
499 0 : oss << " next-term" << endl;
500 : }
501 0 : oss << "}" << endl;
502 0 : return oss.str();
503 0 : }
504 :
505 32 : BgpConfigManager::BgpConfigManager(BgpServer *server)
506 32 : : server_(server) {
507 32 : }
508 :
509 32 : BgpConfigManager::~BgpConfigManager() {
510 32 : }
511 :
512 : template<>
513 384 : void BgpConfigManager::Notify<BgpInstanceConfig>(
514 : const BgpInstanceConfig *config, EventType event) {
515 384 : config->set_last_change_at(UTCTimestampUsec());
516 768 : for (auto obs : obs_) {
517 384 : if (obs.instance) {
518 384 : (obs.instance)(config, event);
519 : }
520 384 : }
521 384 : }
522 :
523 : template<>
524 0 : void BgpConfigManager::Notify<BgpRoutingPolicyConfig>(
525 : const BgpRoutingPolicyConfig *config, EventType event) {
526 0 : config->set_last_change_at(UTCTimestampUsec());
527 0 : for (auto obs : obs_) {
528 0 : if (obs.policy) {
529 0 : (obs.policy)(config, event);
530 : }
531 0 : }
532 0 : }
533 :
534 : template<>
535 32 : void BgpConfigManager::Notify<BgpProtocolConfig>(
536 : const BgpProtocolConfig *config, EventType event) {
537 32 : config->set_last_change_at(UTCTimestampUsec());
538 64 : for (auto obs : obs_) {
539 32 : if (obs.protocol) {
540 32 : (obs.protocol)(config, event);
541 : }
542 32 : }
543 32 : }
544 :
545 : template<>
546 32 : void BgpConfigManager::Notify<BgpNeighborConfig>(
547 : const BgpNeighborConfig *config, EventType event) {
548 32 : config->set_last_change_at(UTCTimestampUsec());
549 64 : for (auto obs : obs_) {
550 32 : if (obs.neighbor) {
551 32 : (obs.neighbor)(config, event);
552 : }
553 32 : }
554 32 : }
555 :
556 : template<>
557 0 : void BgpConfigManager::Notify<BgpGlobalSystemConfig>(
558 : const BgpGlobalSystemConfig *config, EventType event) {
559 0 : config->set_last_change_at(UTCTimestampUsec());
560 0 : for (auto obs : obs_) {
561 0 : if (obs.system) {
562 0 : (obs.system)(config, event);
563 : }
564 0 : }
565 0 : }
566 :
567 : template<>
568 0 : void BgpConfigManager::Notify<BgpGlobalQosConfig>(
569 : const BgpGlobalQosConfig *config, EventType event) {
570 0 : config->set_last_change_at(UTCTimestampUsec());
571 0 : for (auto obs : obs_) {
572 0 : if (obs.qos) {
573 0 : (obs.qos)(config, event);
574 : }
575 0 : }
576 0 : }
|