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