Line data Source code
1 : /*
2 : * Copyright (c) 2013 Juniper Networks, Inc. All rights reserved.
3 : */
4 :
5 : #include "bgp/routing-instance/peer_manager.h"
6 :
7 : #include "base/task_annotations.h"
8 : #include "base/address_util.h"
9 : #include "bgp/bgp_factory.h"
10 : #include "bgp/bgp_log.h"
11 : #include "bgp/bgp_peer.h"
12 : #include "bgp/bgp_peer_types.h"
13 : #include "bgp/bgp_server.h"
14 : #include "bgp/routing-instance/routing_instance.h"
15 : #include "bgp/routing-instance/routing_instance_log.h"
16 :
17 : struct BgpSandeshContext;
18 :
19 : using std::make_pair;
20 : using std::string;
21 : using std::vector;
22 :
23 : //
24 : // Find or create a BgpPeer for the given BgpNeighborConfig.
25 : // Return NULL if the peer already exists and is being deleted. The BgpPeer
26 : // will eventually get created in this case via PeerResurrect.
27 : //
28 10335 : BgpPeer *PeerManager::PeerLocate(BgpServer *server,
29 : const BgpNeighborConfig *config) {
30 10335 : BgpPeerKey key(config);
31 :
32 10335 : BgpPeerNameMap::iterator loc = peers_by_name_.find(config->name());
33 10335 : if (loc != peers_by_name_.end()) {
34 768 : if (loc->second->IsDeleted())
35 6 : return NULL;
36 762 : RemovePeerByKey(loc->second->peer_key(), loc->second);
37 762 : InsertPeerByKey(key, loc->second);
38 762 : return loc->second;
39 : }
40 :
41 : BgpPeer *peer =
42 9567 : BgpStaticObjectFactory::Create<BgpPeer>(server, instance(), config);
43 9567 : peer->Initialize();
44 9567 : InsertPeerByKey(key, peer);
45 9567 : InsertPeerByName(config->name(), peer);
46 9567 : RoutingInstanceInfo info = instance_->GetDataCollection("Add");
47 9567 : info.set_peer(peer->ToString());
48 9567 : ROUTING_INSTANCE_COLLECTOR_INFO(info);
49 :
50 9567 : BGP_LOG_PEER(Config, peer, SandeshLevel::SYS_INFO, BGP_LOG_FLAG_ALL,
51 : BGP_PEER_DIR_NA, "Created peer");
52 9567 : RTINSTANCE_LOG_PEER(Create, instance_, peer,
53 : SandeshLevel::SYS_DEBUG, RTINSTANCE_LOG_FLAG_ALL);
54 9567 : return peer;
55 9567 : }
56 :
57 : //
58 : // Resurrect the BgpPeer with given name if we have configuration for it.
59 : // Also insert it into the BgpServer's EndpointPeerList - in case it is
60 : // a BGPaaS peer. This needs to happen here since we would not have been
61 : // able to do it from BgpServer::ConfigUpdater::ProcessNeighborConfig since
62 : // old incarnation of the BgpPeer still existed at that point.
63 : //
64 9674 : void PeerManager::PeerResurrect(string name) {
65 9674 : CHECK_CONCURRENCY("bgp::Config");
66 :
67 9674 : if (instance_->deleted())
68 2891 : return;
69 :
70 : const BgpConfigManager *config_manager =
71 6783 : instance_->manager()->server()->config_manager();
72 : const BgpNeighborConfig *config =
73 6783 : config_manager->FindNeighbor(instance_->name(), name);
74 6783 : if (!config)
75 6672 : return;
76 :
77 111 : BgpPeer *peer = PeerLocate(server(), config);
78 111 : assert(peer);
79 111 : server()->InsertPeer(peer->endpoint(), peer);
80 : }
81 :
82 : //
83 : // Delete the BgpPeer corresponding to the given BgpNeighborConfig.
84 : //
85 6713 : BgpPeer *PeerManager::TriggerPeerDeletion(const BgpNeighborConfig *config) {
86 6713 : CHECK_CONCURRENCY("bgp::Config");
87 :
88 6713 : BgpPeerNameMap::iterator loc = peers_by_name_.find(config->name());
89 6713 : if (loc == peers_by_name_.end())
90 2 : return NULL;
91 :
92 6711 : BgpPeer *peer = loc->second;
93 6711 : peer->ManagedDelete();
94 :
95 6711 : RoutingInstanceInfo info = instance_->GetDataCollection("Delete");
96 6711 : info.set_peer(peer->ToString());
97 6711 : ROUTING_INSTANCE_COLLECTOR_INFO(info);
98 :
99 6711 : RTINSTANCE_LOG_PEER(Delete, instance_, peer,
100 : SandeshLevel::SYS_DEBUG, RTINSTANCE_LOG_FLAG_ALL);
101 :
102 : // Configuration is deleted by the config manager (parser)
103 : // Do not hold reference to it any more
104 6711 : peer->ClearConfig();
105 6711 : return peer;
106 6711 : }
107 :
108 : //
109 : // Concurrency: Called from bgp config task
110 : //
111 : // Complete the deletion process of a peer. Remove it from BgpPeerKeyMap and
112 : // BgpPeerNameMap.
113 : //
114 9567 : void PeerManager::DestroyIPeer(IPeer *ipeer) {
115 9567 : CHECK_CONCURRENCY("bgp::Config");
116 :
117 9567 : BgpPeer *peer = static_cast<BgpPeer *>(ipeer);
118 9567 : string peer_name = peer->peer_name();
119 9567 : BGP_LOG_PEER(Config, peer, SandeshLevel::SYS_INFO, BGP_LOG_FLAG_ALL,
120 : BGP_PEER_DIR_NA, "Destroyed peer");
121 9567 : RTINSTANCE_LOG_PEER(Destroy, instance_, peer,
122 : SandeshLevel::SYS_DEBUG, RTINSTANCE_LOG_FLAG_ALL);
123 9567 : RemovePeerByKey(peer->peer_key(), peer);
124 9567 : RemovePeerByName(peer->peer_name(), peer);
125 9567 : delete peer;
126 :
127 9567 : PeerResurrect(peer_name);
128 9567 : }
129 :
130 : //
131 : // Insert the BgpPeer info the BgpPeerKeyMap.
132 : //
133 10329 : void PeerManager::InsertPeerByKey(const BgpPeerKey key, BgpPeer *peer) {
134 10329 : peers_by_key_.insert(make_pair(key, peer));
135 10329 : }
136 :
137 : //
138 : // Remove the BgpPeer from the BgpPeerKeyMap. There may be more than
139 : // one BgpPeer with the same key, so we need to find the right one.
140 : //
141 10329 : void PeerManager::RemovePeerByKey(const BgpPeerKey key, BgpPeer *peer) {
142 10329 : for (BgpPeerKeyMap::iterator loc = peers_by_key_.find(key);
143 17194 : loc != peers_by_key_.end() && loc->first == key; ++loc) {
144 17194 : if (loc->second == peer) {
145 10329 : peers_by_key_.erase(loc);
146 10329 : return;
147 : }
148 : }
149 0 : assert(false);
150 : }
151 :
152 : //
153 : // Insert the BgpPeer info the BgpPeerNameMap.
154 : //
155 9567 : void PeerManager::InsertPeerByName(const string name, BgpPeer *peer) {
156 9567 : peers_by_name_.insert(make_pair(name, peer));
157 9567 : }
158 :
159 : //
160 : // Remove the BgpPeer from the BgpPeerNameMap.
161 : //
162 9567 : void PeerManager::RemovePeerByName(const string name, BgpPeer *peer) {
163 9567 : BgpPeerNameMap::iterator loc = peers_by_name_.find(name);
164 9567 : assert(loc != peers_by_name_.end() && loc->second == peer);
165 9567 : peers_by_name_.erase(loc);
166 9567 : }
167 :
168 5 : BgpPeer *PeerManager::PeerFind(string ip_address) const {
169 5 : if (ip_address.empty())
170 0 : return NULL;
171 :
172 5 : boost::system::error_code ec;
173 5 : boost::asio::ip::tcp::endpoint endpoint;
174 5 : endpoint.address(AddressFromString(ip_address, &ec));
175 5 : if (ec)
176 0 : return NULL;
177 :
178 5 : return PeerLookup(endpoint);
179 : }
180 :
181 274 : BgpPeer *PeerManager::PeerLookup(string name) const {
182 274 : BgpPeerNameMap::const_iterator loc = peers_by_name_.find(name);
183 274 : return (loc != peers_by_name_.end() ? loc->second : NULL);
184 : }
185 :
186 3 : size_t PeerManager::GetNeighborCount(string up_or_down) {
187 3 : size_t count = 0;
188 3 : BgpPeerNameMap::iterator iter;
189 :
190 6 : for (iter = peers_by_name_.begin(); iter != peers_by_name_.end(); iter++) {
191 3 : BgpPeer *peer = iter->second;
192 3 : if (boost::iequals(up_or_down, "up") && !peer->IsReady())
193 0 : continue;
194 3 : if (boost::iequals(up_or_down, "down") && peer->IsReady())
195 1 : continue;
196 2 : count += 1;
197 : }
198 :
199 3 : return count;
200 : }
201 :
202 812 : void PeerManager::ClearAllPeers() {
203 812 : BgpPeerNameMap::iterator iter;
204 :
205 1056 : for (iter = peers_by_name_.begin(); iter != peers_by_name_.end(); iter++) {
206 244 : BgpPeer *peer = iter->second;
207 244 : peer->Clear(BgpProto::Notification::OtherConfigChange);
208 : }
209 812 : }
210 :
211 2 : void PeerManager::ClearAllInternalPeers() {
212 2 : BgpPeerNameMap::iterator iter;
213 :
214 6 : for (iter = peers_by_name_.begin(); iter != peers_by_name_.end(); iter++) {
215 4 : BgpPeer *peer = iter->second;
216 4 : if (peer->PeerType() == BgpProto::IBGP)
217 4 : peer->Clear(BgpProto::Notification::OtherConfigChange);
218 : }
219 2 : }
220 :
221 : //
222 : // Concurrency: Called from state machine thread
223 : //
224 36 : BgpPeer *PeerManager::PeerLookup(TcpSession::Endpoint remote_endpoint) const {
225 36 : BgpPeer *peer = NULL;
226 36 : BgpPeerKey peer_key;
227 :
228 : // Bail if the instance is undergoing deletion.
229 36 : if (instance_->deleted())
230 0 : return NULL;
231 :
232 36 : peer_key.endpoint.address(remote_endpoint.address());
233 :
234 : // Do a partial match, as we do not know the peer's port yet.
235 36 : BgpPeerKeyMap::const_iterator loc = peers_by_key_.lower_bound(peer_key);
236 36 : while (loc != peers_by_key_.end()) {
237 : // Check if the address does indeed match as we are doing a partial
238 : // match here
239 32 : if (loc->second->peer_key().endpoint.address() !=
240 64 : peer_key.endpoint.address()) {
241 0 : break;
242 : }
243 :
244 : // This peer certainly matches with the IP address. If we do not find
245 : // an exact match with the peer-id, then just use this.
246 32 : peer = loc->second;
247 32 : break;
248 : }
249 :
250 36 : return peer;
251 : }
252 :
253 333 : const BgpPeer *PeerManager::NextPeer(const BgpPeerKey &peer_key) const {
254 : // Do a partial match
255 333 : BgpPeerKeyMap::const_iterator loc = peers_by_key_.upper_bound(peer_key);
256 333 : if (loc != peers_by_key_.end()) {
257 150 : return loc->second;
258 : }
259 :
260 183 : return NULL;
261 : }
262 :
263 0 : const string &PeerManager::name() const {
264 0 : return instance_->name();
265 : }
266 :
267 6556 : BgpServer *PeerManager::server() const {
268 6556 : return instance_->server();
269 : }
|