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 <boost/bind/bind.hpp>
7 : #include <base/logging.h>
8 : #include <db/db.h>
9 : #include <db/db_entry.h>
10 : #include <db/db_table.h>
11 :
12 : #include <cmn/agent_cmn.h>
13 : #include <init/agent_param.h>
14 : #include "oper/route_common.h"
15 : #include "oper/nexthop.h"
16 : #include "oper/tunnel_nh.h"
17 : #include "oper/vrf.h"
18 : #include "oper/mirror_table.h"
19 : #include "oper/agent_sandesh.h"
20 : #include <resource_manager/mirror_index.h>
21 : using namespace std;
22 : using namespace boost::asio;
23 : using namespace boost::placeholders;
24 : MirrorTable *MirrorTable::mirror_table_;
25 :
26 4 : MirrorTable::~MirrorTable() {
27 2 : boost::system::error_code err;
28 2 : if (udp_sock_.get()) {
29 2 : udp_sock_->close(err);
30 : }
31 4 : }
32 :
33 0 : bool MirrorEntry::IsLess(const DBEntry &rhs) const {
34 0 : const MirrorEntry &a = static_cast<const MirrorEntry &>(rhs);
35 0 : return (analyzer_name_ < a.GetAnalyzerName());
36 : }
37 :
38 0 : DBEntryBase::KeyPtr MirrorEntry::GetDBRequestKey() const {
39 0 : MirrorEntryKey *key = new MirrorEntryKey(analyzer_name_);
40 0 : return DBEntryBase::KeyPtr(key);
41 : }
42 :
43 0 : void MirrorEntry::SetKey(const DBRequestKey *k) {
44 0 : const MirrorEntryKey *key = static_cast<const MirrorEntryKey *>(k);
45 0 : analyzer_name_ = key->analyzer_name_;
46 0 : }
47 :
48 1327 : std::unique_ptr<DBEntry> MirrorTable::AllocEntry(const DBRequestKey *k) const {
49 1327 : const MirrorEntryKey *key = static_cast<const MirrorEntryKey *>(k);
50 1327 : MirrorEntry *mirror_entry = new MirrorEntry(key->analyzer_name_);
51 1327 : return std::unique_ptr<DBEntry>(static_cast<DBEntry *>(mirror_entry));
52 : }
53 :
54 0 : DBEntry *MirrorTable::Add(const DBRequest *req) {
55 0 : const MirrorEntryKey *key = static_cast<const MirrorEntryKey *>(req->key.get());
56 0 : MirrorEntry *mirror_entry = new MirrorEntry(key->analyzer_name_);
57 : ResourceManager::KeyPtr rkey(new MirrorIndexResourceKey
58 0 : (agent()->resource_manager(),
59 0 : key->analyzer_name_));
60 : uint32_t index = static_cast<IndexResourceData *>
61 0 : (agent()->resource_manager()->Allocate(rkey).get())->index();
62 0 : mirror_entry->set_mirror_index(index);
63 : //Get Mirror NH
64 0 : OnChange(mirror_entry, req);
65 0 : return mirror_entry;
66 0 : }
67 :
68 0 : bool MirrorTable::OnChange(MirrorEntry *mirror_entry) {
69 0 : bool ret = false;
70 0 : NextHop *nh = NULL;
71 0 : bool valid_nh = false;
72 0 : if (mirror_entry->mirror_flags_ ==
73 : MirrorEntryData::DynamicNH_Without_JuniperHdr) {
74 0 : VrfEntry *vrf = agent()->vrf_table()->FindVrfFromName(mirror_entry->vrf_name_);
75 : // mirror vrf should have been created
76 0 : if(vrf != NULL) {
77 0 : BridgeRouteKey key(agent()->evpn_peer(), mirror_entry->vrf_name_,
78 0 : mirror_entry->mac_);
79 : BridgeRouteEntry *rt = static_cast<BridgeRouteEntry *>
80 : (static_cast<BridgeAgentRouteTable *>
81 0 : (vrf->GetBridgeRouteTable())->FindActiveEntry(&key));
82 :
83 : // if route entry is preset assign the active nexthop to mirror entry
84 : // if route entry & active apath is not preset create discard nh
85 : // and add it unresolved entry
86 0 : if (rt != NULL) {
87 0 : const AgentPath *path = rt->GetActivePath();
88 0 : nh = path->nexthop();
89 0 : if (nh != NULL) {
90 0 : mirror_entry->vni_ = rt->GetActiveLabel();
91 0 : AddResolvedVrfMirrorEntry(mirror_entry);
92 0 : valid_nh = true;
93 : }
94 : }
95 0 : }
96 : } else { //StaticNH Without Juniper Hdr
97 : InetUnicastRouteEntry *rt =
98 0 : agent()->fabric_inet4_unicast_table()->FindLPM(mirror_entry->dip_);
99 : //if route entry is preset add the active next hop else add discard nh
100 0 : if (rt != NULL) {
101 0 : DBRequest nh_req;
102 0 : nh_req.oper = DBRequest::DB_ENTRY_ADD_CHANGE;
103 : // Do this only for v4, until we add support for v6
104 : // Typecast on v6 would cause an exception and would
105 : // assert in task.cc.
106 0 : if (mirror_entry->sip_.is_v4() && mirror_entry->dip_.is_v4()) {
107 : TunnelNHKey *nh_key =
108 0 : new TunnelNHKey(agent()->fabric_vrf_name(),
109 0 : mirror_entry->sip_.to_v4(),
110 0 : mirror_entry->dip_.to_v4(),
111 0 : false, TunnelType::VXLAN);
112 0 : nh_req.key.reset(nh_key);
113 0 : nh_req.data.reset(NULL);
114 0 : agent()->nexthop_table()->Process(nh_req);
115 0 : nh = static_cast<NextHop *>
116 0 : (agent()->nexthop_table()->FindActiveEntry(nh_key));
117 0 : if (nh != NULL) {
118 0 : valid_nh = true;
119 0 : AddResolvedVrfMirrorEntry(mirror_entry);
120 : }
121 : }
122 0 : }
123 : }
124 :
125 : // if there is no Valid nh point it to discard nh
126 0 : if (!valid_nh) {
127 0 : DiscardNH key;
128 0 : nh = static_cast<NextHop *>
129 0 : (agent()->nexthop_table()->FindActiveEntry(&key));
130 0 : AddUnresolved(mirror_entry);
131 0 : }
132 :
133 0 : if (mirror_entry->nh_ != nh) {
134 0 : ret = true;
135 0 : mirror_entry->nh_ = nh;
136 : }
137 0 : return ret;
138 : }
139 :
140 0 : bool MirrorTable::OnChange(DBEntry *entry, const DBRequest *req) {
141 0 : bool ret = false;
142 0 : bool vrf_changed = false;
143 0 : MirrorEntry *mirror_entry = static_cast<MirrorEntry *>(entry);
144 0 : MirrorEntryData *data = static_cast<MirrorEntryData *>(req->data.get());
145 :
146 : // Check for nic assisted supported ignore creating NH.
147 : // if there is any change from non nic to nic assited mirroring.
148 : // delete if there are any previously allocated resources for mirror entry.
149 0 : if (data->nic_assisted_mirroring_ !=
150 0 : mirror_entry->nic_assisted_mirroring_) {
151 0 : if (!mirror_entry->nic_assisted_mirroring_) {
152 0 : DeleteMirrorVrf(mirror_entry, true);
153 0 : mirror_entry->nh_ = NULL;
154 0 : mirror_entry->vrf_ = NULL;
155 : }
156 0 : mirror_entry->nic_assisted_mirroring_ =
157 0 : data->nic_assisted_mirroring_;
158 0 : mirror_entry->nic_assisted_mirroring_vlan_ =
159 0 : data->nic_assisted_mirroring_vlan_;
160 0 : if (mirror_entry->nic_assisted_mirroring_)
161 0 : return true;
162 0 : } else if (data->nic_assisted_mirroring_){
163 0 : mirror_entry->nic_assisted_mirroring_vlan_ =
164 0 : data->nic_assisted_mirroring_vlan_;
165 0 : return true;
166 : }
167 :
168 0 : if (mirror_entry->vrf_name_ != data->vrf_name_) {
169 0 : vrf_changed = true;
170 : }
171 0 : if (vrf_changed || (mirror_entry->mirror_flags_ != data->mirror_flags_)) {
172 0 : DeleteMirrorVrf(mirror_entry, vrf_changed);
173 0 : mirror_entry->vrf_name_ = data->vrf_name_;
174 : }
175 :
176 0 : mirror_entry->sip_ = data->sip_;
177 0 : mirror_entry->sport_ = data->sport_;
178 0 : mirror_entry->dip_ = data->dip_;
179 0 : mirror_entry->dport_ = data->dport_;
180 0 : mirror_entry->mirror_flags_ = data->mirror_flags_;
181 : // Check for any Vxlan changes.
182 0 : if (mirror_entry->vni_ != data->vni_) {
183 0 : mirror_entry->vni_ = data->vni_;
184 0 : ret = true;
185 : }
186 0 : mirror_entry->mac_ = data->mac_;
187 0 : if (!mirror_entry->createdvrf_) {
188 0 : mirror_entry->createdvrf_ = data->createdvrf_;
189 : }
190 0 : if (mirror_entry->mirror_flags_ == MirrorEntryData::DynamicNH_Without_JuniperHdr ||
191 0 : mirror_entry->mirror_flags_ == MirrorEntryData::StaticNH_Without_JuniperHdr)
192 : {
193 0 : ret |= OnChange(mirror_entry);
194 0 : return ret;
195 : }
196 :
197 0 : DBRequest nh_req;
198 0 : nh_req.oper = DBRequest::DB_ENTRY_ADD_CHANGE;
199 0 : MirrorNHKey *nh_key = new MirrorNHKey(data->vrf_name_, data->sip_,
200 0 : data->sport_, data->dip_, data->dport_);
201 0 : nh_req.key.reset(nh_key);
202 0 : nh_req.data.reset(NULL);
203 0 : agent()->nexthop_table()->Process(nh_req);
204 :
205 : /* For service-chain based mirroring, vrf will always be empty. In this
206 : * case we should create MirrorNH even when VRF is NULL */
207 0 : bool check_for_vrf = false;
208 0 : VrfEntry *vrf = NULL;
209 0 : if (!data->vrf_name_.empty()) {
210 0 : VrfKey key(data->vrf_name_);
211 0 : vrf = static_cast<VrfEntry *>(agent()->vrf_table()->
212 0 : FindActiveEntry(&key));
213 0 : check_for_vrf = true;
214 0 : }
215 :
216 0 : NextHop *nh = static_cast<NextHop *>
217 0 : (agent()->nexthop_table()->FindActiveEntry(nh_key));
218 0 : if (nh == NULL || (check_for_vrf && vrf == NULL)) {
219 : //Make the mirror NH point to discard
220 : //and change the nexthop once the VRF is
221 : //available
222 0 : AddUnresolved(mirror_entry);
223 0 : DiscardNH key;
224 0 : nh = static_cast<NextHop *>
225 0 : (agent()->nexthop_table()->FindActiveEntry(&key));
226 0 : } else {
227 0 : AddResolvedVrfMirrorEntry(mirror_entry);
228 : }
229 :
230 0 : if (mirror_entry->nh_ != nh) {
231 0 : mirror_entry->nh_ = nh;
232 : mirror_entry->vrf_ =
233 0 : agent()->vrf_table()->FindVrfFromName(data->vrf_name_);
234 0 : ret = true;
235 : }
236 0 : return ret;
237 0 : }
238 :
239 0 : bool MirrorTable::Delete(DBEntry *entry, const DBRequest *request) {
240 0 : MirrorEntry *mirror_entry = static_cast<MirrorEntry *>(entry);
241 0 : agent()->resource_manager()->Release(Resource::MIRROR_INDEX,
242 : mirror_entry->mirror_index());
243 0 : DeleteMirrorVrf(mirror_entry, true);
244 0 : return true;
245 : }
246 :
247 0 : void MirrorTable::DeleteMirrorVrf(MirrorEntry *entry, bool del_from_vrf_list) {
248 0 : if (del_from_vrf_list) {
249 0 : RemoveUnresolved(entry);
250 0 : DeleteResolvedVrfMirrorEntry(entry);
251 : }
252 0 : if (entry->mirror_flags_ == MirrorEntryData::DynamicNH_Without_JuniperHdr) {
253 : VrfEntry *vrf =
254 0 : agent()->vrf_table()->FindVrfFromName(entry->vrf_name_);
255 0 : if (vrf) {
256 0 : bool confvrf = vrf->flags() & VrfData::ConfigVrf;
257 0 : bool gwvrf = vrf->flags() & VrfData::GwVrf;
258 0 : if (entry->createdvrf_ && !confvrf && !gwvrf)
259 0 : agent()->vrf_table()->DeleteVrfReq(entry->vrf_name_,
260 : VrfData::MirrorVrf);
261 : }
262 : }
263 0 : }
264 :
265 0 : void MirrorTable::Add(VrfMirrorEntryList &vrf_entry_map, MirrorEntry *entry) {
266 0 : VrfMirrorEntryList::iterator it = vrf_entry_map.find(entry->vrf_name_);
267 :
268 0 : if (it != vrf_entry_map.end()) {
269 0 : MirrorEntryList::const_iterator list_it = it->second.begin();
270 0 : for (; list_it != it->second.end(); list_it++) {
271 0 : if (*list_it == entry) {
272 : //Entry already present
273 0 : return;
274 : }
275 : }
276 0 : it->second.push_back(entry);
277 0 : return;
278 : }
279 :
280 0 : MirrorEntryList list;
281 0 : list.push_back(entry);
282 0 : vrf_entry_map.insert(VrfMirrorEntry(entry->vrf_name_, list));
283 0 : }
284 :
285 0 : void MirrorTable::Delete(VrfMirrorEntryList &list, MirrorEntry *entry) {
286 0 : VrfMirrorEntryList::iterator it = list.find(entry->vrf_name_);
287 0 : if (it == list.end()) {
288 0 : return;
289 : }
290 :
291 0 : MirrorEntryList::iterator list_it = it->second.begin();
292 0 : for(;list_it != it->second.end(); list_it++) {
293 0 : if (*list_it == entry) {
294 0 : it->second.erase(list_it);
295 0 : break;
296 : }
297 : }
298 : }
299 :
300 683 : void MirrorTable::ResyncMirrorEntry(VrfMirrorEntryList &list,
301 : const VrfEntry *vrf) {
302 683 : VrfMirrorEntryList::iterator it = list.find(vrf->GetName());
303 683 : if (it == list.end()) {
304 683 : return;
305 : }
306 :
307 0 : MirrorEntryList::iterator list_it = it->second.begin();
308 0 : for(;list_it != it->second.end(); list_it++) {
309 0 : DBRequest req;
310 0 : req.oper = DBRequest::DB_ENTRY_ADD_CHANGE;
311 :
312 0 : MirrorEntryKey *key = new MirrorEntryKey((*list_it)->GetAnalyzerName());
313 0 : key->sub_op_ = AgentKey::RESYNC;
314 0 : MirrorEntryData *data = new MirrorEntryData((*list_it)->vrf_name(),
315 0 : *((*list_it)->GetSip()),
316 0 : (*list_it)->GetSPort(),
317 0 : *((*list_it)->GetDip()),
318 0 : (*list_it)->GetDPort(), (*list_it)->GetMirrorFlag(),
319 0 : (*list_it)->GetVni(), *((*list_it)->GetMac()),
320 0 : (*list_it)->GetCreatedVrf());
321 0 : req.key.reset(key);
322 0 : req.data.reset(data);
323 0 : Enqueue(&req);
324 0 : }
325 0 : list.erase(it);
326 : }
327 :
328 0 : void MirrorTable::AddUnresolved(MirrorEntry *entry) {
329 0 : Add(unresolved_entry_list_, entry);
330 0 : }
331 :
332 0 : void MirrorTable::RemoveUnresolved(MirrorEntry *entry) {
333 0 : Delete(unresolved_entry_list_, entry);
334 0 : }
335 :
336 0 : void MirrorTable::AddResolvedVrfMirrorEntry(MirrorEntry *entry) {
337 0 : Add(resolved_entry_list_, entry);
338 0 : }
339 :
340 0 : void MirrorTable::DeleteResolvedVrfMirrorEntry(MirrorEntry *entry) {
341 0 : Delete(resolved_entry_list_, entry);
342 0 : }
343 :
344 541 : void MirrorTable::ResyncResolvedMirrorEntry(const VrfEntry *vrf) {
345 541 : ResyncMirrorEntry(resolved_entry_list_, vrf);
346 541 : }
347 :
348 142 : void MirrorTable::ResyncUnresolvedMirrorEntry(const VrfEntry *vrf) {
349 142 : ResyncMirrorEntry(unresolved_entry_list_, vrf);
350 142 : }
351 :
352 :
353 0 : void MirrorTable::AddMirrorEntry(const std::string &analyzer_name,
354 : const std::string &vrf_name,
355 : const IpAddress &sip, uint16_t sport,
356 : const IpAddress &dip, uint16_t dport,
357 : uint32_t vni, uint8_t mirror_flag,
358 : const MacAddress &mac) {
359 0 : Agent *agent = Agent::GetInstance();
360 0 : bool createdvrf = false;
361 0 : DBRequest req;
362 :
363 0 : if (dip.is_v6() && vrf_name == mirror_table_->agent()->fabric_vrf_name()) {
364 0 : LOG(ERROR, "Ipv6 as destination not supported on Fabric VRF: " <<
365 : dip.to_string());
366 0 : return;
367 : }
368 : // if Mirror VRF is not preset create the vrf.
369 : // creatation of VRF ensures all the routes will be dowloaded from control node.
370 0 : if (mirror_flag == MirrorEntryData::DynamicNH_Without_JuniperHdr) {
371 0 : VrfEntry *vrf = agent->vrf_table()->FindVrfFromName(vrf_name);
372 0 : if (vrf == NULL) {
373 0 : agent->vrf_table()->CreateVrfReq(vrf_name, VrfData::MirrorVrf);
374 0 : createdvrf = true;
375 : }
376 : }
377 0 : MirrorEntryKey *key = new MirrorEntryKey(analyzer_name);
378 : MirrorEntryData *data = new MirrorEntryData(vrf_name, sip, sport, dip,
379 : dport, mirror_flag, vni, mac,
380 0 : createdvrf);
381 0 : req.oper = DBRequest::DB_ENTRY_ADD_CHANGE;
382 0 : req.key.reset(key);
383 0 : req.data.reset(data);
384 0 : mirror_table_->Enqueue(&req);
385 0 : }
386 :
387 0 : void MirrorTable::AddMirrorEntry(const std::string &analyzer_name,
388 : const std::string &vrf_name,
389 : const IpAddress &sip, uint16_t sport,
390 : const IpAddress &dip, uint16_t dport) {
391 :
392 0 : DBRequest req;
393 :
394 0 : if (dip.is_v6() && vrf_name == mirror_table_->agent()->fabric_vrf_name()) {
395 0 : LOG(ERROR, "Ipv6 as destination not supported on Fabric VRF: " <<
396 : dip.to_string());
397 0 : return;
398 : }
399 : // First enqueue request to add Mirror NH
400 0 : req.oper = DBRequest::DB_ENTRY_ADD_CHANGE;
401 :
402 0 : MirrorNHKey *nh_key = new MirrorNHKey(vrf_name, sip, sport, dip, dport);
403 0 : req.key.reset(nh_key);
404 0 : req.data.reset(NULL);
405 0 : mirror_table_->agent()->nexthop_table()->Enqueue(&req);
406 :
407 0 : req.oper = DBRequest::DB_ENTRY_ADD_CHANGE;
408 0 : MirrorEntryKey *key = new MirrorEntryKey(analyzer_name);
409 : MirrorEntryData *data = new MirrorEntryData(vrf_name, sip,
410 : sport, dip, dport, 1, 0 ,
411 0 : MacAddress::ZeroMac(), false);
412 0 : req.key.reset(key);
413 0 : req.data.reset(data);
414 0 : mirror_table_->Enqueue(&req);
415 0 : }
416 :
417 0 : void MirrorTable::AddMirrorEntry(const std::string &analyzer_name,
418 : uint32_t nic_assisted_mirroring_vlan) {
419 0 : DBRequest req;
420 0 : req.oper = DBRequest::DB_ENTRY_ADD_CHANGE;
421 0 : MirrorEntryKey *key = new MirrorEntryKey(analyzer_name);
422 0 : MirrorEntryData *data = new MirrorEntryData(true, nic_assisted_mirroring_vlan);
423 0 : req.key.reset(key);
424 0 : req.data.reset(data);
425 0 : mirror_table_->Enqueue(&req);
426 0 : }
427 :
428 :
429 0 : void MirrorTable::DelMirrorEntry(const std::string &analyzer_name) {
430 0 : DBRequest req;
431 0 : req.oper = DBRequest::DB_ENTRY_DELETE;
432 0 : MirrorEntryKey *key = new MirrorEntryKey(analyzer_name);
433 0 : req.key.reset(key);
434 0 : req.data.reset(NULL);
435 0 : mirror_table_->Enqueue(&req);
436 0 : }
437 :
438 0 : void MirrorTable::OnZeroRefcount(AgentDBEntry *e) {
439 0 : const MirrorEntry *mirr_entry = static_cast<const MirrorEntry *>(e);
440 0 : DelMirrorEntry(mirr_entry->GetAnalyzerName());
441 0 : }
442 :
443 2 : DBTableBase *MirrorTable::CreateTable(DB *db, const std::string &name) {
444 2 : mirror_table_ = new MirrorTable(db, name);
445 2 : mirror_table_->Init();
446 2 : return mirror_table_;
447 : };
448 :
449 2 : void MirrorTable::Initialize() {
450 2 : VrfListenerInit();
451 2 : }
452 :
453 2 : void MirrorTable::VrfListenerInit() {
454 2 : vrf_listener_id_ = agent()->vrf_table()->
455 2 : Register(boost::bind(&MirrorTable::VrfNotify,
456 : this, _1, _2));
457 2 : }
458 :
459 683 : void MirrorTable::VrfNotify(DBTablePartBase *base, DBEntryBase *entry) {
460 683 : VrfEntry *vrf = static_cast<VrfEntry *>(entry);
461 : MirrorVrfState *state = static_cast<MirrorVrfState *>
462 683 : (vrf->GetState(base->parent(), vrf_listener_id_));
463 683 : if (vrf->IsDeleted()) {
464 541 : if (state) {
465 0 : UnRegisterBridgeRouteTableListener(vrf, state);
466 0 : vrf->ClearState(base->parent(), vrf_listener_id_);
467 0 : delete state;
468 : }
469 : //VRF is getting deleted remove all the mirror nexthop
470 541 : ResyncResolvedMirrorEntry(vrf);
471 541 : return;
472 : }
473 :
474 : // This will be for dynamic witout juniper header, to resolve the
475 : // bridge entry lookup
476 142 : bool miror_vrf = UnresolvedMirrorVrf(vrf, unresolved_entry_list_);
477 142 : if (state == NULL && miror_vrf) {
478 0 : state = new MirrorVrfState();
479 0 : state->seen_ = true;
480 0 : vrf->SetState(base->parent(), vrf_listener_id_, state);
481 0 : if (state->bridge_rt_table_listener_id_ == DBTableBase::kInvalidId) {
482 : BridgeAgentRouteTable *bridge_table =
483 : static_cast<BridgeAgentRouteTable *>
484 0 : (vrf->GetBridgeRouteTable());
485 0 : state->bridge_rt_table_listener_id_ =
486 0 : bridge_table->Register(boost::bind(&MirrorTable::BridgeRouteTableNotify,
487 : this, _1, _2));
488 : }
489 : }
490 142 : ResyncUnresolvedMirrorEntry(vrf);
491 : }
492 :
493 142 : bool MirrorTable::UnresolvedMirrorVrf(const VrfEntry *vrf,
494 : VrfMirrorEntryList &list){
495 142 : VrfMirrorEntryList::iterator it = list.find(vrf->GetName());
496 142 : if (it == list.end()) {
497 142 : return false;
498 : }
499 : // Need to check if there are any entries with DynamicNH_Without_JuniperHdr
500 0 : MirrorEntryList::iterator list_it = it->second.begin();
501 0 : for(;list_it != it->second.end(); list_it++) {
502 0 : if ((*list_it)->GetMirrorFlag() ==
503 : MirrorEntryData::DynamicNH_Without_JuniperHdr) {
504 0 : return true;
505 : }
506 : }
507 0 : return false;
508 : }
509 : // if the Unresolved remote mac is present it will return the entry
510 : MirrorEntry*
511 0 : MirrorTable::GetMirrorEntry(VrfEntry *vrf, const MacAddress & mac,
512 : VrfMirrorEntryList &list) {
513 0 : VrfMirrorEntryList::iterator it = list.find(vrf->GetName());
514 0 : if (it == list.end()) {
515 0 : return NULL;
516 : }
517 0 : MirrorEntryList::iterator list_it = it->second.begin();
518 0 : for(;list_it != it->second.end(); list_it++) {
519 0 : const MacAddress &remote_vm_mac = *((*list_it)->GetMac());
520 0 : if (remote_vm_mac == mac) {
521 0 : return (*list_it);
522 : }
523 : }
524 0 : return NULL;
525 : }
526 :
527 :
528 0 : void MirrorTable::BridgeRouteTableNotify(DBTablePartBase *partition,
529 : DBEntryBase *entry) {
530 0 : const BridgeRouteEntry *bridge_rt = static_cast<const BridgeRouteEntry *>(entry);
531 0 : if (bridge_rt->IsDeleted()) {
532 0 : ResyncResolvedMirrorEntry(bridge_rt->vrf());
533 : } else {
534 0 : MirrorEntry *unresolved_mirror_entry = GetMirrorEntry(bridge_rt->vrf(),
535 0 : bridge_rt->prefix_address(),
536 0 : unresolved_entry_list_);
537 0 : MirrorEntry *resolved_mirror_entry = GetMirrorEntry(bridge_rt->vrf(),
538 0 : bridge_rt->prefix_address(),
539 0 : resolved_entry_list_);
540 : // Check for Both resolved and unresolved list for Change in route
541 0 : if (unresolved_mirror_entry &&
542 0 : unresolved_mirror_entry->mirror_flags_ ==
543 : MirrorEntryData::DynamicNH_Without_JuniperHdr) {
544 0 : ResyncUnresolvedMirrorEntry(bridge_rt->vrf());
545 0 : } else if (resolved_mirror_entry &&
546 0 : ((resolved_mirror_entry->vni_ != bridge_rt->GetActiveLabel()) ||
547 0 : (resolved_mirror_entry->nh_ !=
548 : bridge_rt->GetActivePath()->nexthop()))) {
549 0 : ResyncResolvedMirrorEntry(bridge_rt->vrf());
550 : }
551 : }
552 0 : }
553 :
554 0 : void MirrorTable::UnRegisterBridgeRouteTableListener(const VrfEntry *vrf,
555 : MirrorVrfState *state) {
556 0 : if (state->bridge_rt_table_listener_id_ == DBTableBase::kInvalidId)
557 0 : return;
558 : BridgeAgentRouteTable *bridge_table = static_cast<BridgeAgentRouteTable *>
559 0 : (vrf->GetBridgeRouteTable());
560 0 : bridge_table->Unregister(state->bridge_rt_table_listener_id_);
561 0 : state->bridge_rt_table_listener_id_ = DBTableBase::kInvalidId;
562 : }
563 :
564 0 : void MirrorTable::ReadHandler(const boost::system::error_code &ec,
565 : size_t bytes_transferred) {
566 :
567 0 : if (ec) {
568 0 : LOG(ERROR, "Error reading from Mirror sock. Error : " <<
569 : boost::system::system_error(ec).what());
570 0 : return;
571 : }
572 :
573 0 : udp_sock_->async_receive(boost::asio::buffer(rx_buff_, sizeof(rx_buff_)),
574 0 : boost::bind(&MirrorTable::ReadHandler, this,
575 : boost::asio::placeholders::error,
576 : boost::asio::placeholders::bytes_transferred));
577 : }
578 :
579 2 : void MirrorTable::MirrorSockInit(void) {
580 : EventManager *event_mgr;
581 :
582 2 : event_mgr = agent()->event_manager();
583 2 : boost::asio::io_service &io = *event_mgr->io_service();
584 4 : ip::udp::endpoint ep(ip::udp::v4(),
585 2 : agent()->params()->mirror_client_port());
586 :
587 2 : udp_sock_.reset(new ip::udp::socket(io));
588 :
589 2 : boost::system::error_code ec;
590 2 : udp_sock_->open(ip::udp::v4(), ec);
591 2 : assert(ec.value() == 0);
592 :
593 2 : udp_sock_->bind(ep, ec);
594 2 : if (ec.value() != 0) {
595 0 : ep.port(0);
596 0 : udp_sock_->bind(ep, ec);
597 0 : assert(ec.value() == 0);
598 : }
599 :
600 2 : ip::udp::endpoint sock_ep = udp_sock_->local_endpoint(ec);
601 2 : assert(ec.value() == 0);
602 2 : agent()->set_mirror_port(sock_ep.port());
603 :
604 4 : udp_sock_->async_receive(boost::asio::buffer(rx_buff_, sizeof(rx_buff_)),
605 2 : boost::bind(&MirrorTable::ReadHandler, this,
606 : boost::asio::placeholders::error,
607 : boost::asio::placeholders::bytes_transferred));
608 2 : }
609 :
610 0 : VrfEntry *MirrorTable::FindVrfEntry(const string &vrf_name) const {
611 0 : return agent()->vrf_table()->FindVrfFromName(vrf_name);
612 : }
613 :
614 2 : void MirrorTable::Shutdown() {
615 2 : agent()->vrf_table()->Unregister(vrf_listener_id_);
616 2 : }
617 :
618 0 : bool MirrorTable::IsConfigured() {
619 0 : VrfMirrorEntryList::iterator it;
620 0 : for (it = resolved_entry_list_.begin(); it != resolved_entry_list_.end(); ++it) {
621 0 : if (it->second.size() > 0) {
622 0 : return true;
623 : }
624 : }
625 0 : return false;
626 : }
627 :
628 0 : uint32_t MirrorEntry::vrf_id() const {
629 0 : return vrf_ ? vrf_->vrf_id() : uint32_t(-1);
630 : }
631 :
632 0 : const VrfEntry *MirrorEntry::GetVrf() const {
633 0 : return vrf_ ? vrf_.get() : NULL;
634 : }
635 :
636 0 : void MirrorEntry::set_mirror_entrySandeshData(MirrorEntrySandeshData &data) const {
637 0 : data.set_analyzer_name(GetAnalyzerName());
638 0 : data.set_sip(GetSip()->to_string());
639 0 : data.set_dip(GetDip()->to_string());
640 0 : data.set_vrf(GetVrf() ? GetVrf()->GetName() : "");
641 0 : data.set_sport(GetSPort());
642 0 : data.set_dport(GetDPort());
643 0 : data.set_ref_count(GetRefCount());
644 0 : if (nh_) {
645 0 : nh_->SetNHSandeshData(data.nh);
646 : }
647 0 : }
648 :
649 0 : bool MirrorEntry::DBEntrySandesh(Sandesh *sresp, std::string &name) const {
650 0 : MirrorEntryResp *resp = static_cast<MirrorEntryResp *>(sresp);
651 :
652 0 : MirrorEntrySandeshData data;
653 0 : set_mirror_entrySandeshData(data);
654 : std::vector<MirrorEntrySandeshData> &list =
655 : const_cast<std::vector<MirrorEntrySandeshData>&>
656 0 : (resp->get_mirror_entry_list());
657 0 : list.push_back(data);
658 :
659 0 : return true;
660 0 : }
661 :
662 0 : void MirrorEntryReq::HandleRequest() const {
663 0 : AgentSandeshPtr sand(new AgentMirrorSandesh(context(), get_analyzer_name()));
664 0 : sand->DoSandesh(sand);
665 0 : }
666 :
667 0 : AgentSandeshPtr MirrorTable::GetAgentSandesh(const AgentSandeshArguments *args,
668 : const std::string &context) {
669 : return AgentSandeshPtr(new AgentMirrorSandesh(context,
670 0 : args->GetString("analyzer_name")));
671 : }
672 :
673 : MirrorEntryData::MirrorEntryFlags
674 0 : MirrorTable::DecodeMirrorFlag (const std::string &nh_mode, bool juniper_header) {
675 0 : std::string str = "static";
676 0 : if (juniper_header) {
677 0 : if (boost::iequals(nh_mode, str))
678 0 : return MirrorEntryData::StaticNH_With_JuniperHdr;
679 0 : return MirrorEntryData::DynamicNH_With_JuniperHdr;
680 : } else {
681 0 : if (boost::iequals(nh_mode, str))
682 0 : return MirrorEntryData::StaticNH_Without_JuniperHdr;
683 0 : return MirrorEntryData::DynamicNH_Without_JuniperHdr;
684 : }
685 0 : }
|