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