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