Line data Source code
1 : /*
2 : * Copyright (c) 2016 Juniper Networks, Inc. All rights reserved.
3 : * Copyright Contributors to the OpenSDN project
4 : */
5 :
6 : #include <string>
7 : #include <vector>
8 : #include <boost/uuid/uuid_io.hpp>
9 :
10 : #include <vnc_cfg_types.h>
11 : #include <base/logging.h>
12 : #include <base/string_util.h>
13 : #include <base/bgp_as_service_utils.h>
14 : #include <base/address_util.h>
15 : #include <cmn/agent_cmn.h>
16 : #include <init/agent_param.h>
17 : #include <ifmap/ifmap_node.h>
18 : #include <ifmap/ifmap_link.h>
19 : #include <cfg/cfg_init.h>
20 : #include <cmn/agent.h>
21 : #include <oper/operdb_init.h>
22 : #include <oper/bgp_as_service.h>
23 : #include <oper/bgp_router.h>
24 : #include <oper/audit_list.h>
25 : #include <oper/agent_sandesh.h>
26 : #include <oper/config_manager.h>
27 : #include <oper/vn.h>
28 : #include <bgp_schema_types.h>
29 :
30 : #include <arpa/inet.h>
31 : #include <netinet/in.h>
32 : #include <fcntl.h>
33 : #include "oper/global_system_config.h"
34 : #include <resource_manager/resource_manager.h>
35 : #include <resource_manager/resource_table.h>
36 : #include <resource_manager/bgp_as_service_index.h>
37 :
38 : SandeshTraceBufferPtr BgpAsAServiceTraceBuf(SandeshTraceBufferCreate
39 : ("BgpAsAService", 500));
40 :
41 2 : BgpAsAService::BgpAsAService(const Agent *agent) :
42 2 : agent_(agent),
43 2 : bgp_as_a_service_entry_map_(),
44 2 : bgp_as_a_service_port_map_(),
45 2 : service_delete_cb_list_(), health_check_cb_list_() {
46 2 : }
47 :
48 2 : BgpAsAService::~BgpAsAService() {
49 2 : }
50 :
51 0 : const BgpAsAService::BgpAsAServiceEntryMap &BgpAsAService::bgp_as_a_service_map() const {
52 0 : return bgp_as_a_service_entry_map_;
53 : }
54 :
55 0 : const BgpAsAService::BgpAsAServicePortMap &BgpAsAService::bgp_as_a_service_port_map() const {
56 0 : return bgp_as_a_service_port_map_;
57 : }
58 :
59 0 : void BgpAsAService::BgpAsAServiceList::Insert(const BgpAsAServiceEntry *rhs) {
60 0 : if (rhs->health_check_configured_)
61 0 : rhs->new_health_check_add_ = true;
62 0 : list_.insert(*rhs);
63 0 : }
64 :
65 0 : void BgpAsAService::BgpAsAServiceList::Update(const BgpAsAServiceEntry *lhs,
66 : const BgpAsAServiceEntry *rhs) {
67 0 : lhs->dest_port_ = rhs->dest_port_;
68 0 : lhs->primary_control_node_zone_ = rhs->primary_control_node_zone_;
69 0 : lhs->secondary_control_node_zone_ = rhs->secondary_control_node_zone_;
70 0 : if (rhs->health_check_configured_) {
71 0 : if (lhs->hc_delay_usecs_ != rhs->hc_delay_usecs_ ||
72 0 : lhs->hc_timeout_usecs_ != rhs->hc_timeout_usecs_ ||
73 0 : lhs->hc_retries_ != rhs->hc_retries_) {
74 : // if HC properties change, trigger update
75 0 : lhs->new_health_check_add_ = true;
76 0 : lhs->hc_delay_usecs_ = rhs->hc_delay_usecs_;
77 0 : lhs->hc_timeout_usecs_ = rhs->hc_timeout_usecs_;
78 0 : lhs->hc_retries_ = rhs->hc_retries_;
79 : }
80 : }
81 0 : if (lhs->health_check_configured_ != rhs->health_check_configured_) {
82 0 : lhs->health_check_configured_ = rhs->health_check_configured_;
83 0 : if (lhs->health_check_configured_) {
84 0 : lhs->old_health_check_delete_ = false;
85 0 : lhs->new_health_check_add_ = true;
86 0 : lhs->old_health_check_uuid_ = boost::uuids::nil_uuid();
87 0 : lhs->health_check_uuid_ = rhs->health_check_uuid_;
88 : } else {
89 0 : lhs->old_health_check_delete_ = true;
90 0 : lhs->new_health_check_add_ = false;
91 0 : lhs->old_health_check_uuid_ = lhs->health_check_uuid_;
92 0 : lhs->health_check_uuid_ = boost::uuids::nil_uuid();
93 : }
94 0 : return;
95 : }
96 0 : if (lhs->health_check_uuid_ != rhs->health_check_uuid_) {
97 : // delete old health check and add new
98 0 : lhs->new_health_check_add_ = true;
99 0 : lhs->old_health_check_delete_ = true;
100 0 : lhs->old_health_check_uuid_ = lhs->health_check_uuid_;
101 0 : lhs->health_check_uuid_ = rhs->health_check_uuid_;
102 : }
103 : }
104 :
105 0 : void BgpAsAService::BgpAsAServiceList::Remove(BgpAsAServiceEntryListIterator &it) {
106 0 : it->set_del_pending(true);
107 0 : }
108 :
109 0 : void BgpAsAService::BgpAsAServiceList::Flush() {
110 0 : list_.clear();
111 0 : }
112 :
113 0 : void BgpAsAService::StartHealthCheck(const boost::uuids::uuid &vm_uuid,
114 : const BgpAsAServiceEntryList &list) {
115 0 : for (BgpAsAServiceEntryListConstIterator iter = list.begin();
116 0 : iter != list.end(); ++iter) {
117 0 : if (!health_check_cb_list_.empty() && iter->new_health_check_add_ &&
118 0 : iter->health_check_uuid_ != boost::uuids::nil_uuid()) {
119 : std::vector<HealthCheckCb>::iterator hcb_it =
120 0 : health_check_cb_list_.begin();
121 0 : while (hcb_it != health_check_cb_list_.end()) {
122 0 : (*hcb_it)(vm_uuid, iter->source_port_,
123 0 : iter->health_check_uuid_, true);
124 0 : hcb_it++;
125 : }
126 : }
127 0 : iter->new_health_check_add_ = false;
128 : }
129 0 : }
130 :
131 0 : static const std::string GetBgpRouterVrfName(const Agent *agent,
132 : IFMapNode *node) {
133 0 : IFMapAgentTable *table = static_cast<IFMapAgentTable *>(node->table());
134 0 : for (DBGraphVertex::adjacency_iterator it = node->begin(table->GetGraph());
135 0 : it != node->end(table->GetGraph()); ++it) {
136 0 : IFMapNode *vrf_node = static_cast<IFMapNode *>(it.operator->());
137 0 : if (agent->config_manager()->SkipNode
138 0 : (vrf_node, agent->cfg()->cfg_vrf_table())) {
139 0 : continue;
140 : }
141 0 : return vrf_node->name();
142 : }
143 0 : return std::string();
144 : }
145 :
146 0 : static const std::string GetControlNodeZoneName(IFMapNode *node) {
147 : IFMapAgentTable *table =
148 0 : static_cast<IFMapAgentTable *>(node->table());
149 0 : for (DBGraphVertex::adjacency_iterator it = node->begin(table->GetGraph());
150 0 : it != node->end(table->GetGraph()); ++it) {
151 0 : IFMapNode *adj_node = static_cast<IFMapNode *>(it.operator->());
152 0 : if (strcmp(adj_node->table()->Typename(),
153 0 : CONTROL_NODE_ZONE_CONFIG_NAME) == 0) {
154 0 : return adj_node->name();
155 : }
156 : }
157 0 : return std::string();
158 : }
159 :
160 0 : void BgpAsAService::BuildBgpAsAServiceInfo(IFMapNode *bgp_as_a_service_node,
161 : std::list<IFMapNode *> &bgp_router_nodes,
162 : BgpAsAServiceEntryList &new_list,
163 : const std::string &vm_vrf_name,
164 : const boost::uuids::uuid &vm_uuid) {
165 : IFMapAgentTable *table =
166 0 : static_cast<IFMapAgentTable *>(bgp_as_a_service_node->table());
167 : autogen::BgpAsAService *bgp_as_a_service =
168 0 : dynamic_cast<autogen::BgpAsAService *>(bgp_as_a_service_node->GetObject());
169 0 : assert(bgp_as_a_service);
170 :
171 0 : IpAddress peer_ip;
172 0 : uint32_t source_port = 0;
173 0 : bool health_check_configured = false;
174 0 : boost::uuids::uuid health_check_uuid = boost::uuids::nil_uuid();
175 0 : uint64_t hc_delay_usecs = 0;
176 0 : uint64_t hc_timeout_usecs = 0;
177 0 : uint32_t hc_retries = 0;
178 0 : std::string primary_control_node_zone;
179 0 : std::string secondary_control_node_zone;
180 :
181 : // Find the health check config first
182 0 : for (DBGraphVertex::adjacency_iterator it = bgp_as_a_service_node->begin(table->GetGraph());
183 0 : it != bgp_as_a_service_node->end(table->GetGraph()); ++it) {
184 0 : IFMapNode *adj_node = static_cast<IFMapNode *>(it.operator->());
185 :
186 0 : if (adj_node->table() == agent_->cfg()->cfg_health_check_table()) {
187 0 : if (agent_->config_manager()->SkipNode(adj_node)) {
188 0 : continue;
189 : }
190 : autogen::ServiceHealthCheck *hc =
191 0 : static_cast<autogen::ServiceHealthCheck *> (adj_node->GetObject());
192 0 : assert(hc);
193 : // consider only BFD health check for BGPaaS
194 0 : if (hc->properties().monitor_type.find("BFD") == std::string::npos)
195 0 : continue;
196 0 : health_check_configured = true;
197 0 : autogen::IdPermsType id_perms = hc->id_perms();
198 0 : CfgUuidSet(id_perms.uuid.uuid_mslong, id_perms.uuid.uuid_lslong,
199 : health_check_uuid);
200 0 : hc_delay_usecs = hc->properties().delay * 1000000 +
201 0 : hc->properties().delayUsecs;
202 0 : hc_timeout_usecs = hc->properties().timeout * 1000000 +
203 0 : hc->properties().timeoutUsecs;
204 0 : hc_retries = hc->properties().max_retries;
205 0 : }
206 :
207 0 : if (strcmp(adj_node->table()->Typename(),
208 0 : BGPAAS_CONTROL_NODE_ZONE_CONFIG_NAME) == 0) {
209 : autogen::BgpaasControlNodeZone
210 : *bgpaas_cnz = static_cast<autogen::BgpaasControlNodeZone *>
211 0 : (adj_node->GetObject());
212 : const autogen::BGPaaSControlNodeZoneAttributes &attr =
213 : static_cast<autogen::BGPaaSControlNodeZoneAttributes>
214 0 : (bgpaas_cnz->data());
215 0 : const std::string cnz_name = GetControlNodeZoneName(adj_node);
216 0 : if (cnz_name.size()) {
217 0 : if (strcmp(attr.bgpaas_control_node_zone_type.c_str(),
218 0 : "primary") == 0) {
219 0 : primary_control_node_zone = cnz_name;
220 0 : continue;
221 : }
222 0 : if (strcmp(attr.bgpaas_control_node_zone_type.c_str(),
223 0 : "secondary") == 0) {
224 0 : secondary_control_node_zone = cnz_name;
225 0 : continue;
226 : }
227 : }
228 0 : }
229 : }
230 :
231 : //Look for neighbour bgp-router to take the source port
232 0 : for (DBGraphVertex::adjacency_iterator it = bgp_as_a_service_node->begin(table->GetGraph());
233 0 : it != bgp_as_a_service_node->end(table->GetGraph()); ++it) {
234 0 : IFMapNode *adj_node = static_cast<IFMapNode *>(it.operator->());
235 0 : if (strcmp(adj_node->table()->Typename(), BGP_ROUTER_CONFIG_NAME) == 0) {
236 : //Verify that bgp-router object is of use for this VMI.
237 : //List of valid bgp-router for vmi is in bgp_router_nodes.
238 0 : if (std::find(bgp_router_nodes.begin(), bgp_router_nodes.end(),
239 0 : adj_node) == bgp_router_nodes.end()) {
240 0 : continue;
241 : }
242 : autogen::BgpRouter *bgp_router=
243 0 : dynamic_cast<autogen::BgpRouter *>(adj_node->GetObject());
244 : const std::string &vrf_name =
245 0 : GetBgpRouterVrfName(agent_, adj_node);
246 0 : if (vrf_name.empty() || (vrf_name != vm_vrf_name) ||
247 0 : (strcmp(bgp_router->parameters().router_type.c_str(),
248 : VALID_BGP_ROUTER_TYPE) != 0))
249 0 : continue; //Skip the node with no VRF, notification will come.
250 0 : boost::system::error_code ec;
251 : peer_ip =
252 0 : IpAddress::from_string(bgp_router->parameters().address, ec);
253 0 : if (ec.value() != 0) {
254 0 : std::stringstream ss;
255 0 : ss << "Ip address parsing failed for ";
256 0 : ss << bgp_router->parameters().address;
257 0 : BGPASASERVICETRACE(Trace, ss.str().c_str());
258 0 : continue;
259 0 : }
260 :
261 : BgpAsAServiceEntryMapIterator old_bgp_as_a_service_entry_list_iter =
262 0 : bgp_as_a_service_entry_map_.find(vm_uuid);
263 0 : source_port = 0;
264 : /*
265 : * verify the same session is added again here
266 : */
267 0 : if (old_bgp_as_a_service_entry_list_iter !=
268 0 : bgp_as_a_service_entry_map_.end()) {
269 0 : BgpAsAServiceEntryList temp_bgp_as_a_service_entry_list;
270 0 : temp_bgp_as_a_service_entry_list.insert(
271 0 : BgpAsAServiceEntry(peer_ip,
272 0 : bgp_router->parameters().source_port,
273 0 : bgp_router->parameters().port,
274 : health_check_configured,
275 : health_check_uuid,
276 0 : bgp_as_a_service->bgpaas_shared(),
277 : hc_delay_usecs,
278 : hc_timeout_usecs,
279 : hc_retries,
280 : primary_control_node_zone,
281 : secondary_control_node_zone));
282 : /*
283 : * if it is same session then retain original source port
284 : */
285 0 : if (temp_bgp_as_a_service_entry_list ==
286 0 : old_bgp_as_a_service_entry_list_iter->second->list_) {
287 0 : source_port = bgp_router->parameters().source_port;
288 : }
289 0 : }
290 0 : if (!source_port) {
291 0 : if (bgp_as_a_service->bgpaas_shared()) {
292 0 : source_port = AddBgpVmiServicePortIndex(
293 0 : bgp_router->parameters().source_port,
294 : vm_uuid);
295 : } else {
296 0 : source_port = bgp_router->parameters().source_port;
297 : }
298 : }
299 0 : if (source_port) {
300 0 : new_list.insert(BgpAsAServiceEntry(peer_ip, source_port,
301 0 : bgp_router->parameters().port,
302 : health_check_configured,
303 : health_check_uuid,
304 0 : bgp_as_a_service->bgpaas_shared(),
305 : hc_delay_usecs,
306 : hc_timeout_usecs,
307 : hc_retries,
308 : primary_control_node_zone,
309 : secondary_control_node_zone));
310 : }
311 0 : }
312 : }
313 :
314 0 : }
315 :
316 1202 : void BgpAsAService::ProcessConfig(const std::string &vrf_name,
317 : std::list<IFMapNode *> &bgp_router_node_map,
318 : std::list<IFMapNode *> &bgp_as_service_node_map,
319 : const boost::uuids::uuid &vm_uuid) {
320 : std::list<IFMapNode *>::const_iterator it =
321 1202 : bgp_as_service_node_map.begin();
322 1202 : BgpAsAServiceEntryList new_bgp_as_a_service_entry_list;
323 :
324 1202 : while (it != bgp_as_service_node_map.end()) {
325 0 : BuildBgpAsAServiceInfo(*it, bgp_router_node_map,
326 : new_bgp_as_a_service_entry_list,
327 : vrf_name, vm_uuid);
328 0 : it++;
329 : }
330 :
331 : //Audit and enqueue updates/deletes of flow
332 : BgpAsAServiceEntryMapIterator old_bgp_as_a_service_entry_list_iter =
333 1202 : bgp_as_a_service_entry_map_.find(vm_uuid);
334 1202 : bool changed = false;
335 1202 : if (old_bgp_as_a_service_entry_list_iter !=
336 2404 : bgp_as_a_service_entry_map_.end()) {
337 : //Audit
338 : changed = AuditList<BgpAsAServiceList, BgpAsAServiceEntryListIterator>
339 0 : (*(old_bgp_as_a_service_entry_list_iter->second),
340 0 : old_bgp_as_a_service_entry_list_iter->second->list_.begin(),
341 0 : old_bgp_as_a_service_entry_list_iter->second->list_.end(),
342 : new_bgp_as_a_service_entry_list.begin(),
343 : new_bgp_as_a_service_entry_list.end());
344 1202 : } else if (new_bgp_as_a_service_entry_list.size() != 0) {
345 0 : StartHealthCheck(vm_uuid, new_bgp_as_a_service_entry_list);
346 0 : bgp_as_a_service_entry_map_[vm_uuid] =
347 0 : new BgpAsAServiceList(new_bgp_as_a_service_entry_list);
348 : }
349 :
350 1202 : if (changed && !service_delete_cb_list_.empty()) {
351 : //Enqueue flow handler request.
352 : BgpAsAServiceEntryListIterator iter =
353 0 : old_bgp_as_a_service_entry_list_iter->second->list_.begin();
354 0 : while (iter !=
355 0 : old_bgp_as_a_service_entry_list_iter->second->list_.end()) {
356 0 : BgpAsAServiceEntryListIterator prev = iter++;
357 0 : if (prev->del_pending_) {
358 : std::vector<ServiceDeleteCb>::iterator scb_it =
359 0 : service_delete_cb_list_.begin();
360 0 : while (scb_it != service_delete_cb_list_.end()) {
361 0 : (*scb_it)(vm_uuid, prev->source_port_);
362 0 : scb_it++;
363 : }
364 0 : InterfaceConstRef vm_intf = agent_->interface_table()->FindVmi(vm_uuid);
365 0 : const VmInterface *vmi = dynamic_cast<const VmInterface *>(vm_intf.get());
366 0 : if ((prev->is_shared_ && vmi==NULL) || (prev->is_shared_ && vmi && vmi->IsDeleted())) {
367 0 : FreeBgpVmiServicePortIndex(prev->source_port_);
368 : }
369 0 : else if(vmi && !(vmi->IsDeleted())){
370 0 : LOG(DEBUG, "Undeleted vmi might have active bgp session with source port");
371 : }
372 :
373 0 : old_bgp_as_a_service_entry_list_iter->second->list_.erase(prev);
374 0 : continue;
375 0 : }
376 0 : if (prev->old_health_check_delete_) {
377 0 : if (!health_check_cb_list_.empty() &&
378 0 : prev->old_health_check_uuid_ != boost::uuids::nil_uuid()) {
379 : std::vector<HealthCheckCb>::iterator hcb_it =
380 0 : health_check_cb_list_.begin();
381 0 : while (hcb_it != health_check_cb_list_.end()) {
382 0 : (*hcb_it)(vm_uuid, prev->source_port_,
383 0 : prev->old_health_check_uuid_, false);
384 0 : hcb_it++;
385 : }
386 : }
387 0 : prev->old_health_check_delete_ = false;
388 0 : prev->old_health_check_uuid_ = boost::uuids::nil_uuid();
389 : }
390 0 : if (prev->new_health_check_add_) {
391 0 : if (!health_check_cb_list_.empty() &&
392 0 : prev->health_check_uuid_ != boost::uuids::nil_uuid()) {
393 : std::vector<HealthCheckCb>::iterator hcb_it =
394 0 : health_check_cb_list_.begin();
395 0 : while (hcb_it != health_check_cb_list_.end()) {
396 0 : (*hcb_it)(vm_uuid, prev->source_port_,
397 0 : prev->health_check_uuid_, true);
398 0 : hcb_it++;
399 : }
400 : }
401 0 : prev->new_health_check_add_ = false;
402 : }
403 : }
404 : }
405 1202 : }
406 :
407 285 : void BgpAsAService::DeleteVmInterface(const boost::uuids::uuid &vm_uuid) {
408 285 : if (service_delete_cb_list_.empty())
409 285 : return;
410 :
411 : BgpAsAServiceEntryMapIterator iter =
412 285 : bgp_as_a_service_entry_map_.find(vm_uuid);
413 285 : if (iter == bgp_as_a_service_entry_map_.end())
414 285 : return;
415 :
416 0 : BgpAsAServiceEntryList list = iter->second->list_;
417 0 : BgpAsAServiceEntryListIterator list_iter = list.begin();
418 0 : while (list_iter != list.end()) {
419 : std::vector<ServiceDeleteCb>::iterator scb_it =
420 0 : service_delete_cb_list_.begin();
421 0 : while (scb_it != service_delete_cb_list_.end()) {
422 0 : (*scb_it)(vm_uuid, (*list_iter).source_port_);
423 0 : scb_it++;
424 : }
425 0 : if ((*list_iter).is_shared_) {
426 0 : FreeBgpVmiServicePortIndex((*list_iter).source_port_);
427 : }
428 0 : list_iter++;
429 : }
430 0 : delete iter->second;
431 0 : bgp_as_a_service_entry_map_.erase(iter);
432 0 : }
433 :
434 :
435 0 : bool BgpAsAService::IsBgpService(const VmInterface *vm_intf,
436 : const IpAddress &source_ip,
437 : const IpAddress &dest_ip) const {
438 0 : bool ret = false;
439 : BgpAsAServiceEntryMapConstIterator iter =
440 0 : bgp_as_a_service_entry_map_.find(vm_intf->GetUuid());
441 0 : if (iter == bgp_as_a_service_entry_map_.end()) {
442 0 : return false;
443 : }
444 :
445 0 : while (iter != bgp_as_a_service_entry_map_.end()) {
446 : BgpAsAService::BgpAsAServiceEntryListIterator it =
447 0 : iter->second->list_.begin();
448 0 : while (it != iter->second->list_.end()) {
449 0 : if ((*it).local_peer_ip_ == source_ip)
450 0 : return true;
451 0 : it++;
452 : }
453 0 : iter++;
454 : }
455 :
456 0 : const VnEntry *vn = vm_intf->vn();
457 0 : if (vn == NULL) return false;
458 :
459 0 : const IpAddress &vm_ip = vm_intf->primary_ip_addr();
460 0 : if ((vn->GetGatewayFromIpam(vm_ip) == dest_ip) ||
461 0 : (vn->GetDnsFromIpam(vm_ip) == dest_ip)) {
462 0 : ret = true;
463 : }
464 0 : return ret;
465 : }
466 :
467 0 : void BgpAsAService::FreeBgpVmiServicePortIndex(const uint32_t sport) {
468 : BGPaaServiceParameters:: BGPaaServicePortRangePair ports =
469 0 : bgp_as_a_service_port_range();
470 : BGPaaSUtils::BgpAsServicePortIndexPair portinfo =
471 0 : BGPaaSUtils::DecodeBgpaasServicePort(sport,
472 0 : ports.first, ports.second);
473 :
474 : BgpAsAServicePortMapIterator port_map_it =
475 0 : bgp_as_a_service_port_map_.find(portinfo.first);
476 0 : if (port_map_it == bgp_as_a_service_port_map_.end()) {
477 0 : return;
478 : }
479 :
480 0 : size_t vmi_service_port_index = portinfo.second;
481 0 : agent_->resource_manager()->Release(Resource::BGP_AS_SERVICE_INDEX,
482 : vmi_service_port_index);
483 0 : port_map_it->second->Remove(vmi_service_port_index);
484 :
485 0 : if (port_map_it->second->NoneIndexSet()) {
486 0 : delete port_map_it->second;
487 0 : bgp_as_a_service_port_map_.erase(port_map_it);
488 : }
489 : }
490 :
491 0 : size_t BgpAsAService::AllocateBgpVmiServicePortIndex(const uint32_t sport,
492 : const boost::uuids::uuid vm_uuid) {
493 : BgpAsAServicePortMapIterator port_map_it =
494 0 : bgp_as_a_service_port_map_.find(sport);
495 0 : if (port_map_it == bgp_as_a_service_port_map_.end()) {
496 0 : bgp_as_a_service_port_map_[sport] = new IndexVector<boost::uuids::uuid>();
497 : }
498 : ResourceManager::KeyPtr rkey(new BgpAsServiceIndexResourceKey
499 0 : (agent_->resource_manager(), vm_uuid));
500 : uint32_t index = static_cast<IndexResourceData *>
501 0 : (agent_->resource_manager()->Allocate(rkey).get())->index();
502 0 : bgp_as_a_service_port_map_[sport]->InsertAtIndex(index, vm_uuid);
503 0 : return index;
504 0 : }
505 :
506 0 : uint32_t BgpAsAService::AddBgpVmiServicePortIndex(const uint32_t source_port,
507 : const boost::uuids::uuid vm_uuid) {
508 : BGPaaServiceParameters:: BGPaaServicePortRangePair ports =
509 0 : bgp_as_a_service_port_range();
510 :
511 0 : size_t vmi_service_port_index = AllocateBgpVmiServicePortIndex(source_port,
512 : vm_uuid);
513 0 : if (vmi_service_port_index == BitSet::npos) {
514 0 : std::stringstream ss;
515 0 : ss << "Service Port Index is not available for ";
516 0 : ss << source_port;
517 0 : BGPASASERVICETRACE(Trace, ss.str().c_str());
518 0 : return 0;
519 0 : }
520 0 : return BGPaaSUtils::EncodeBgpaasServicePort(
521 : source_port,
522 : vmi_service_port_index,
523 0 : ports.first, ports.second);
524 : }
525 :
526 0 : bool BgpAsAService::GetBgpRouterServiceDestination(
527 : const VmInterface *vm_intf, const IpAddress &source_ip,
528 : const IpAddress &dest, IpAddress *nat_server,
529 : uint32_t *sport, uint32_t *dport) const {
530 0 : const VnEntry *vn = vm_intf->vn();
531 0 : if (vn == NULL) return false;
532 :
533 0 : const IpAddress &vm_ip = vm_intf->primary_ip_addr();
534 0 : const IpAddress &gw = vn->GetGatewayFromIpam(vm_ip);
535 0 : const IpAddress &dns = vn->GetDnsFromIpam(vm_ip);
536 :
537 0 : std::stringstream ss;
538 : BgpAsAServiceEntryMapConstIterator map_it =
539 0 : bgp_as_a_service_entry_map_.find(vm_intf->GetUuid());
540 0 : if (map_it == bgp_as_a_service_entry_map_.end()) {
541 0 : ss << "vmi-uuid:" << vm_intf->GetUuid() << " not found";
542 0 : BGPASASERVICETRACE(Trace, ss.str().c_str());
543 0 : return false;
544 : }
545 :
546 0 : BgpRouterConfig *bgp_router_cfg = agent_->oper_db()->bgp_router_config();
547 0 : BgpAsAServiceEntryListConstIterator it = map_it->second->list_.begin();
548 0 : while (it != map_it->second->list_.end()) {
549 0 : bool cnz_configured = it->IsControlNodeZoneConfigured();
550 0 : BgpRouterPtr bgp_router;
551 0 : IpAddress ip_address;
552 0 : std::string xmpp_server;
553 0 : std::string control_node_zone;
554 : std::string *bgp_router_name;
555 0 : if (dest == gw) {
556 0 : if (cnz_configured) {
557 : bgp_router = bgp_router_cfg->
558 0 : GetBgpRouterFromControlNodeZone(
559 0 : it->primary_control_node_zone_);
560 0 : control_node_zone = it->primary_control_node_zone_;
561 : } else {
562 0 : xmpp_server = agent_->controller_ifmap_xmpp_server(0);
563 0 : if (xmpp_server.size())
564 : bgp_router = bgp_router_cfg->
565 0 : GetBgpRouterFromXmppServer(xmpp_server);
566 : }
567 0 : bgp_router_name = &it->primary_bgp_peer_;
568 0 : } else if (dest == dns) {
569 0 : if (cnz_configured) {
570 : bgp_router = bgp_router_cfg->
571 0 : GetBgpRouterFromControlNodeZone(
572 0 : it->secondary_control_node_zone_);
573 0 : control_node_zone = it->secondary_control_node_zone_;
574 : } else {
575 0 : xmpp_server = agent_->controller_ifmap_xmpp_server(1);
576 0 : if (xmpp_server.size())
577 : bgp_router = bgp_router_cfg->
578 0 : GetBgpRouterFromXmppServer(xmpp_server);
579 : }
580 0 : bgp_router_name = &it->secondary_bgp_peer_;
581 : } else {
582 0 : it++;
583 0 : continue;
584 : }
585 0 : if (bgp_router.get() == NULL) {
586 0 : ss << "BgpRouter not found.";
587 0 : ss << " bgpaas-source-ip:" << source_ip.to_string();
588 0 : ss << " bgpaas-destination-ip:" << dest.to_string();
589 0 : ss << " control-node-zone:" << control_node_zone;
590 0 : ss << " xmpp-server:" << xmpp_server;
591 0 : BGPASASERVICETRACE(Trace, ss.str().c_str());
592 : //reset bgp_router for sandesh
593 0 : *bgp_router_name = "";
594 0 : return false;
595 : }
596 0 : *nat_server = bgp_router->ipv4_address();
597 0 : *sport = it->source_port_;
598 0 : *dport = it->dest_port_?it->dest_port_:bgp_router->port();
599 : //update bgp_router for sandesh
600 0 : *bgp_router_name = bgp_router->name();
601 0 : return true;
602 0 : }
603 0 : ss << "BgpRouter not found ";
604 0 : ss << " bgpaas-source-ip:" << source_ip.to_string();
605 0 : ss << " bgpaas-destination-ip" << dest.to_string();
606 0 : BGPASASERVICETRACE(Trace, ss.str().c_str());
607 0 : return false;
608 0 : }
609 :
610 0 : bool BgpAsAService::GetBgpHealthCheck(const VmInterface *vm_intf,
611 : boost::uuids::uuid *health_check_uuid) const {
612 : BgpAsAServiceEntryMapConstIterator found =
613 0 : bgp_as_a_service_entry_map_.find(vm_intf->GetUuid());
614 :
615 0 : if (found != bgp_as_a_service_entry_map_.end()) {
616 : BgpAsAService::BgpAsAServiceEntryListIterator it =
617 0 : found->second->list_.begin();
618 0 : while (it != found->second->list_.end()) {
619 0 : if (it->health_check_configured_) {
620 0 : *health_check_uuid = it->health_check_uuid_;
621 0 : std::ostringstream ss;
622 0 : ss<<"searched for vm_intf_uuid: "<<boost::uuids::to_string(vm_intf->GetUuid())
623 0 : <<" - found: "<<boost::uuids::to_string(*health_check_uuid);
624 0 : BGPASASERVICETRACE(Trace, ss.str().c_str());
625 0 : return true;
626 0 : }
627 0 : it++;
628 : }
629 : }
630 0 : std::ostringstream ss;
631 0 : ss<<"vm_intf_uuid: "<<boost::uuids::to_string(vm_intf->GetUuid())+" - not found in BgpAaS entry map";
632 0 : BGPASASERVICETRACE(Trace, ss.str().c_str());
633 0 : return false;
634 0 : }
635 :
636 0 : void BgpAsAService::UpdateBgpAsAServiceSessionInfo() {
637 0 : if (service_delete_cb_list_.empty())
638 0 : return;
639 0 : unsigned int source_port = 0;
640 0 : unsigned int index = 0;
641 : BGPaaServiceParameters:: BGPaaServicePortRangePair old_ports =
642 0 : bgp_as_a_service_port_range();
643 : BGPaaServiceParameters:: BGPaaServicePortRangePair new_ports =
644 0 : agent_->oper_db()->global_system_config()->bgpaas_port_range();
645 0 : std::pair<BgpAsAServiceEntryListIterator, bool> ret;
646 : BgpAsAServiceEntryMapIterator iter =
647 0 : bgp_as_a_service_entry_map_.begin();
648 0 : while (iter != bgp_as_a_service_entry_map_.end()) {
649 0 : BgpAsAServiceEntryList list = iter->second->list_;
650 0 : BgpAsAServiceEntryListIterator list_iter = list.begin();
651 0 : while (list_iter != list.end()) {
652 : BGPaaSUtils::BgpAsServicePortIndexPair portinfo =
653 0 : BGPaaSUtils::DecodeBgpaasServicePort(
654 0 : list_iter->source_port_,
655 0 : old_ports.first,
656 0 : old_ports.second);
657 0 : source_port = portinfo.first;
658 0 : index = portinfo.second;
659 : // encode source port with new port range
660 : source_port =
661 0 : BGPaaSUtils::EncodeBgpaasServicePort(source_port,
662 : index,
663 0 : new_ports.first,
664 0 : new_ports.second);
665 : // if old source port is not same as new source pott
666 : // delte the flow and entry from the list
667 : // and then insert the entry with the new source port
668 0 : if (list_iter->source_port_ != source_port) {
669 0 : BgpAsAServiceEntry temp(list_iter->local_peer_ip_,
670 : source_port,
671 0 : list_iter->dest_port_,
672 0 : list_iter->health_check_configured_,
673 0 : list_iter->health_check_uuid_,
674 0 : list_iter->is_shared_,
675 0 : list_iter->hc_delay_usecs_,
676 0 : list_iter->hc_timeout_usecs_,
677 0 : list_iter->hc_retries_,
678 0 : list_iter->primary_control_node_zone_,
679 0 : list_iter->secondary_control_node_zone_);
680 : std::vector<ServiceDeleteCb>::iterator scb_it =
681 0 : service_delete_cb_list_.begin();
682 0 : while (scb_it != service_delete_cb_list_.end()) {
683 0 : (*scb_it)(iter->first, list_iter->source_port_);
684 0 : scb_it++;
685 : }
686 0 : iter->second->list_.erase(*list_iter);
687 0 : iter->second->list_.insert(temp);
688 0 : }
689 0 : list_iter++;
690 : }
691 0 : iter++;
692 0 : }
693 : //update BgpaaS port range
694 0 : bgp_as_a_service_parameters_.port_start = new_ports.first;
695 0 : bgp_as_a_service_parameters_.port_end = new_ports.second;
696 : }
697 :
698 : ////////////////////////////////////////////////////////////////////////////
699 : // BGP as a service routines.
700 : ////////////////////////////////////////////////////////////////////////////
701 1202 : BgpAsAService::BgpAsAServiceEntry::BgpAsAServiceEntry() :
702 1202 : VmInterface::ListEntry(), installed_(false),
703 2404 : local_peer_ip_(), source_port_(0), dest_port_(0),
704 1202 : health_check_configured_(false), health_check_uuid_(),
705 1202 : new_health_check_add_(false),old_health_check_delete_(false),
706 1202 : old_health_check_uuid_(),hc_delay_usecs_(0),
707 1202 : hc_timeout_usecs_(0), hc_retries_(0), is_shared_(false),
708 1202 : primary_control_node_zone_(), secondary_control_node_zone_() {
709 1202 : }
710 :
711 0 : BgpAsAService::BgpAsAServiceEntry::BgpAsAServiceEntry
712 0 : (const BgpAsAService::BgpAsAServiceEntry &rhs) :
713 0 : VmInterface::ListEntry(rhs.del_pending_),
714 0 : installed_(rhs.installed_),
715 0 : local_peer_ip_(rhs.local_peer_ip_),
716 0 : source_port_(rhs.source_port_),
717 0 : dest_port_(rhs.dest_port_),
718 0 : health_check_configured_(rhs.health_check_configured_),
719 0 : health_check_uuid_(rhs.health_check_uuid_),
720 0 : new_health_check_add_(rhs.new_health_check_add_),
721 0 : old_health_check_delete_(rhs.old_health_check_delete_),
722 0 : old_health_check_uuid_(rhs.old_health_check_uuid_),
723 0 : hc_delay_usecs_(rhs.hc_delay_usecs_),
724 0 : hc_timeout_usecs_(rhs.hc_timeout_usecs_),
725 0 : hc_retries_(rhs.hc_retries_), is_shared_(rhs.is_shared_),
726 0 : primary_control_node_zone_(rhs.primary_control_node_zone_),
727 0 : secondary_control_node_zone_(rhs.secondary_control_node_zone_) {
728 0 : }
729 :
730 0 : BgpAsAService::BgpAsAServiceEntry::BgpAsAServiceEntry
731 : (const IpAddress &local_peer_ip, uint32_t source_port, uint32_t dest_port,
732 : bool health_check_configured, const boost::uuids::uuid &health_check_uuid,
733 : bool is_shared, uint64_t hc_delay_usecs, uint64_t hc_timeout_usecs,
734 : uint32_t hc_retries, const std::string &primary_control_node_zone,
735 0 : const std::string &secondary_control_node_zone) :
736 : VmInterface::ListEntry(),
737 0 : installed_(false),
738 0 : local_peer_ip_(local_peer_ip),
739 0 : source_port_(source_port),
740 0 : dest_port_(dest_port),
741 0 : health_check_configured_(health_check_configured),
742 0 : health_check_uuid_(health_check_uuid),
743 0 : new_health_check_add_(health_check_configured),
744 0 : old_health_check_delete_(false), old_health_check_uuid_(),
745 0 : hc_delay_usecs_(hc_delay_usecs), hc_timeout_usecs_(hc_timeout_usecs),
746 0 : hc_retries_(hc_retries), is_shared_(is_shared),
747 0 : primary_control_node_zone_(primary_control_node_zone),
748 0 : secondary_control_node_zone_(secondary_control_node_zone) {
749 0 : }
750 :
751 1202 : BgpAsAService::BgpAsAServiceEntry::~BgpAsAServiceEntry() {
752 1202 : }
753 :
754 0 : bool BgpAsAService::BgpAsAServiceEntry::operator ==
755 : (const BgpAsAServiceEntry &rhs) const {
756 0 : return ((source_port_ == rhs.source_port_) &&
757 0 : (local_peer_ip_ == rhs.local_peer_ip_) &&
758 0 : (is_shared_ == rhs.is_shared_));
759 : }
760 :
761 0 : bool BgpAsAService::BgpAsAServiceEntry::operator()
762 : (const BgpAsAServiceEntry &lhs, const BgpAsAServiceEntry &rhs) const {
763 0 : return lhs.IsLess(&rhs);
764 : }
765 :
766 0 : bool BgpAsAService::BgpAsAServiceEntry::IsLess
767 : (const BgpAsAServiceEntry *rhs) const {
768 0 : if (source_port_ != rhs->source_port_)
769 0 : return source_port_ < rhs->source_port_;
770 0 : if (local_peer_ip_ != rhs->local_peer_ip_)
771 0 : return local_peer_ip_ < rhs->local_peer_ip_;
772 0 : if (primary_control_node_zone_ != rhs->primary_control_node_zone_)
773 0 : return primary_control_node_zone_ < rhs->primary_control_node_zone_;
774 0 : if (secondary_control_node_zone_ != rhs->secondary_control_node_zone_)
775 0 : return secondary_control_node_zone_ < rhs->secondary_control_node_zone_;
776 0 : return is_shared_ < rhs->is_shared_;
777 : }
778 :
779 0 : void BgpAsAServiceSandeshReq::HandleRequest() const {
780 0 : BgpAsAServiceSandeshResp *resp = new BgpAsAServiceSandeshResp();
781 0 : resp->set_context(context());
782 :
783 0 : Agent *agent = Agent::GetInstance();
784 :
785 : BgpAsAService::BgpAsAServiceEntryMap map_entry =
786 0 : agent->oper_db()->bgp_as_a_service()->bgp_as_a_service_map();
787 : BgpAsAService::BgpAsAServiceEntryMapIterator map_it =
788 0 : map_entry.begin();
789 0 : std::vector<BgpAsAServiceSandeshList> bgpaas_map;
790 0 : std::string vmi_uuid_str = get_vmi_uuid();
791 0 : while (map_it != map_entry.end()) {
792 0 : if (vmi_uuid_str.empty() == false) {
793 0 : boost::uuids::uuid vmi_uuid = StringToUuid(vmi_uuid_str);
794 0 : if (vmi_uuid != map_it->first) {
795 0 : map_it++;
796 0 : continue;
797 : }
798 : }
799 : BgpAsAService::BgpAsAServiceEntryListIterator it =
800 0 : map_it->second->list_.begin();
801 0 : while (it != map_it->second->list_.end()) {
802 0 : BgpAsAServiceSandeshList entry;
803 0 : entry.set_vm_bgp_peer_ip((*it).local_peer_ip_.to_string());
804 0 : entry.set_vm_nat_source_port((*it).source_port_);
805 0 : entry.set_vmi_uuid(UuidToString(map_it->first));
806 0 : entry.set_health_check_configured((*it).health_check_configured_);
807 0 : entry.set_health_check_uuid(UuidToString((*it).health_check_uuid_));
808 0 : entry.set_health_check_delay_usecs((*it).hc_delay_usecs_);
809 0 : entry.set_health_check_timeout_usecs((*it).hc_timeout_usecs_);
810 0 : entry.set_health_check_retries((*it).hc_retries_);
811 0 : entry.set_is_shared((*it).is_shared_);
812 0 : entry.set_primary_control_node_zone(
813 0 : (*it).primary_control_node_zone_);
814 0 : entry.set_secondary_control_node_zone(
815 0 : (*it).secondary_control_node_zone_);
816 0 : entry.set_primary_bgp_peer((*it).primary_bgp_peer_);
817 0 : entry.set_secondary_bgp_peer((*it).secondary_bgp_peer_);
818 0 : bgpaas_map.push_back(entry);
819 0 : it++;
820 0 : }
821 0 : map_it++;
822 : }
823 0 : resp->set_bgp_as_a_service_list(bgpaas_map);
824 0 : resp->Response();
825 0 : }
|