Line data Source code
1 : /*
2 : * Copyright (c) 2013 Juniper Networks, Inc. All rights reserved.
3 : */
4 :
5 : #include <pkt/pkt_sandesh_flow.h>
6 : #include <pkt/flow_mgmt.h>
7 : #include <pkt/flow_mgmt/flow_entry_info.h>
8 : #include <pkt/flow_mgmt/flow_mgmt_entry.h>
9 : #include <vector>
10 : #include <boost/date_time/posix_time/posix_time.hpp>
11 : #include <sstream>
12 : #include <algorithm>
13 :
14 : #include <cmn/agent_stats.h>
15 : #include <uve/agent_uve.h>
16 : #include <vrouter/flow_stats/flow_stats_collector.h>
17 : #include <vrouter/ksync/ksync_init.h>
18 : #include <vrouter/ksync/ksync_flow_index_manager.h>
19 :
20 0 : static string InetRouteFlowMgmtKeyToString(uint16_t id,
21 : InetRouteFlowMgmtKey *key) {
22 0 : std::stringstream ss;
23 0 : uint16_t plen = key->plen();
24 0 : ss << id << PktSandeshFlow::kDelimiter;
25 0 : ss << key->vrf_id() << PktSandeshFlow::kDelimiter;
26 0 : ss << key->ip().to_string() << PktSandeshFlow::kDelimiter;
27 0 : ss << plen;
28 0 : return ss.str();
29 0 : }
30 :
31 : #define SET_SANDESH_FLOW_DATA(agent, data, fe, info) \
32 : data.set_vrf(fe->data().vrf); \
33 : data.set_sip(fe->key().src_addr.to_string()); \
34 : data.set_dip(fe->key().dst_addr.to_string()); \
35 : data.set_src_port((unsigned)fe->key().src_port); \
36 : data.set_dst_port((unsigned)fe->key().dst_port); \
37 : data.set_protocol(fe->key().protocol); \
38 : data.set_dest_vrf(fe->data().dest_vrf); \
39 : data.set_uuid(UuidToString(fe->uuid())); \
40 : data.set_action(fe->match_p().action_info.action); \
41 : std::vector<ActionStr> action_str_l; \
42 : SetActionStr(fe->match_p().action_info, action_str_l); \
43 : if ((fe->match_p().action_info.action & TrafficAction::DROP_FLAGS) != 0) {\
44 : data.set_drop_reason(fe->DropReasonStr(fe->data().drop_reason)); \
45 : } \
46 : data.set_action_str(action_str_l); \
47 : std::vector<MirrorActionSpec>::const_iterator mait; \
48 : std::vector<MirrorInfo> mirror_l; \
49 : for (mait = fe->match_p().action_info.mirror_l.begin(); \
50 : mait != fe->match_p().action_info.mirror_l.end(); \
51 : ++mait) { \
52 : MirrorInfo minfo; \
53 : minfo.set_mirror_destination((*mait).ip.to_string()); \
54 : minfo.set_mirror_port((*mait).port); \
55 : mirror_l.push_back(minfo); \
56 : } \
57 : data.set_mirror_l(mirror_l); \
58 : if (fe->is_flags_set(FlowEntry::IngressDir)) { \
59 : data.set_direction("ingress"); \
60 : } else { \
61 : data.set_direction("egress"); \
62 : } \
63 : if (info) { \
64 : data.set_stats_bytes(info->bytes()); \
65 : data.set_stats_packets(info->packets()); \
66 : } \
67 : if (fe->is_flags_set(FlowEntry::NatFlow)) { \
68 : data.set_nat("enabled"); \
69 : } else { \
70 : data.set_nat("disabled"); \
71 : } \
72 : data.set_gen_id(fe->gen_id()); \
73 : data.set_flow_handle(fe->flow_handle()); \
74 : data.set_refcount(fe->GetRefCount()); \
75 : data.set_implicit_deny(fe->ImplicitDenyFlow() ? "yes" : "no"); \
76 : data.set_short_flow( \
77 : fe->is_flags_set(FlowEntry::ShortFlow) ? \
78 : string("yes (") + fe->DropReasonStr(fe->short_flow_reason()) + \
79 : ")": "no"); \
80 : data.set_local_flow(fe->is_flags_set(FlowEntry::LocalFlow) ? "yes" : "no"); \
81 : if (!fe->data().OriginVnSrcList().empty()) { \
82 : data.set_src_vn_list(fe->data().OriginVnSrcList()); \
83 : } else { \
84 : data.set_src_vn_list(fe->data().SourceVnList()); \
85 : } \
86 : if (!fe->data().OriginVnDstList().empty()) { \
87 : data.set_dst_vn_list(fe->data().OriginVnDstList()); \
88 : } else { \
89 : data.set_dst_vn_list(fe->data().DestinationVnList()); \
90 : } \
91 : if (!fe->data().origin_vn_src.empty()) { \
92 : data.set_src_vn_match(fe->data().origin_vn_src); \
93 : } else { \
94 : data.set_src_vn_match(fe->data().source_vn_match); \
95 : } \
96 : if (!fe->data().origin_vn_dst.empty()) { \
97 : data.set_dst_vn_match(fe->data().origin_vn_dst); \
98 : } else { \
99 : data.set_dst_vn_match(fe->data().dest_vn_match); \
100 : } \
101 : if (fe->is_flags_set(FlowEntry::EcmpFlow) && \
102 : fe->data().component_nh_idx != CompositeNH::kInvalidComponentNHIdx) { \
103 : data.set_ecmp_index(fe->data().component_nh_idx); \
104 : } \
105 : data.set_reverse_flow(fe->is_flags_set(FlowEntry::ReverseFlow) ? "yes" : "no"); \
106 : Ip4Address fip(fe->fip()); \
107 : data.set_fip(fip.to_string()); \
108 : uint32_t fip_intf_id = fe->InterfaceKeyToId(agent, fe->fip_vmi()); \
109 : data.set_fip_vm_interface_idx(fip_intf_id); \
110 : SetAclInfo(data, fe); \
111 : data.set_nh(fe->key().nh); \
112 : if (fe->data().src_ip_nh.get() != NULL) { \
113 : data.set_src_ip_nh(fe->data().src_ip_nh.get()->id()); \
114 : } \
115 : if (fe->data().rpf_nh.get() != NULL) { \
116 : data.set_rpf_nh(fe->data().rpf_nh.get()->id()); \
117 : } \
118 : data.set_peer_vrouter(fe->peer_vrouter()); \
119 : data.set_tunnel_type(fe->tunnel_type().ToString()); \
120 : data.set_enable_rpf(fe->data().enable_rpf);\
121 : if (fe->fsc()) {\
122 : data.set_aging_protocol(fe->fsc()->flow_aging_key().proto);\
123 : data.set_aging_port(fe->fsc()->flow_aging_key().port);\
124 : }\
125 : data.set_l3_flow(fe->l3_flow());\
126 : uint16_t id = fe->flow_table()? fe->flow_table()->table_index() : 0xFFFF;\
127 : data.set_table_id(id);\
128 : data.set_deleted(fe->deleted());\
129 : SandeshFlowIndexInfo flow_index_info;\
130 : fe->SetEventSandeshData(&flow_index_info);\
131 : data.set_flow_index_info(flow_index_info); \
132 : data.set_fw_policy_match(fe->fw_policy_name_uuid()); \
133 : FlowEntryInfo *mgmt_info = fe->flow_mgmt_info(); \
134 : if (mgmt_info) {\
135 : const FlowMgmtKeyTree &key_tree = mgmt_info->tree(); \
136 : FlowMgmtKeyTree::const_iterator kt_it = key_tree.begin(); \
137 : std::vector<SandeshInetRouteFlowMgmtEntryLink> key_list;\
138 : while (kt_it != key_tree.end()) { \
139 : InetRouteFlowMgmtKey *key = dynamic_cast<InetRouteFlowMgmtKey *> \
140 : (kt_it->first);\
141 : ++kt_it;\
142 : if (!key) {\
143 : continue;\
144 : }\
145 : if (id == 0xFFFF) {\
146 : continue;\
147 : }\
148 : string key_str = InetRouteFlowMgmtKeyToString(id, key);\
149 : SandeshInetRouteFlowMgmtEntryLink entry;\
150 : entry.set_inet_route_flow_mgmt_key(key_str);\
151 : key_list.push_back(entry);\
152 : }\
153 : data.set_inet_rt_keys(key_list);\
154 : }\
155 : data.set_local_tag_list(fe->local_tagset());\
156 : data.set_remote_tag_list(fe->remote_tagset());\
157 : data.set_remote_prefix(fe->RemotePrefix());\
158 : const Interface *itfe = fe->intf_entry();\
159 : if (itfe && (itfe->type() == Interface::VM_INTERFACE)) {\
160 : const VmInterface *vmi_e = static_cast<const VmInterface *>(itfe);\
161 : data.set_vmi(vmi_e->cfg_name());\
162 : }\
163 : data.set_underlay_gw_index(fe->data().underlay_gw_index_);\
164 :
165 : const std::string PktSandeshFlow::start_key = "0-0-0-0-0-0.0.0.0-0.0.0.0";
166 :
167 : ////////////////////////////////////////////////////////////////////////////////
168 :
169 0 : static void SetOneAclInfo(FlowAclInfo *policy, uint32_t action,
170 : const MatchAclParamsList &acl_list) {
171 0 : MatchAclParamsList::const_iterator it;
172 0 : std::vector<FlowAclUuid> acl;
173 :
174 0 : for (it = acl_list.begin(); it != acl_list.end(); it++) {
175 0 : FlowAclUuid f;
176 0 : f.uuid = UuidToString(it->acl->GetUuid());
177 0 : acl.push_back(f);
178 0 : }
179 0 : policy->set_acl(acl);
180 0 : policy->set_action(action);
181 :
182 0 : std::vector<ActionStr> action_str_l;
183 0 : for (it = acl_list.begin(); it != acl_list.end(); it++) {
184 0 : FlowAction action_info = it->action_info;
185 0 : action_info.action = action;
186 0 : SetActionStr(action_info, action_str_l);
187 0 : }
188 0 : policy->set_action_str(action_str_l);
189 0 : }
190 :
191 0 : static void SetAclInfo(SandeshFlowData &data, FlowEntry *fe) {
192 0 : FlowAclInfo policy;
193 :
194 0 : SetOneAclInfo(&policy, fe->match_p().policy_action, fe->match_p().m_acl_l);
195 0 : data.set_policy(policy);
196 :
197 0 : SetOneAclInfo(&policy, fe->match_p().out_policy_action,
198 0 : fe->match_p().m_out_acl_l);
199 0 : data.set_out_policy(policy);
200 :
201 0 : SetOneAclInfo(&policy, fe->match_p().sg_policy.action, fe->match_p().sg_policy.m_acl_l);
202 0 : data.set_sg(policy);
203 :
204 0 : SetOneAclInfo(&policy, fe->match_p().sg_policy.out_action,
205 0 : fe->match_p().sg_policy.m_out_acl_l);
206 0 : data.set_out_sg(policy);
207 :
208 0 : SetOneAclInfo(&policy, fe->match_p().sg_policy.reverse_action,
209 0 : fe->match_p().sg_policy.m_reverse_acl_l);
210 0 : data.set_reverse_sg(policy);
211 :
212 0 : SetOneAclInfo(&policy, fe->match_p().sg_policy.reverse_out_action,
213 0 : fe->match_p().sg_policy.m_reverse_out_acl_l);
214 0 : data.set_reverse_out_sg(policy);
215 :
216 0 : SetOneAclInfo(&policy, fe->match_p().vrf_assign_acl_action,
217 0 : fe->match_p().m_vrf_assign_acl_l);
218 0 : data.set_vrf_assign_acl(policy);
219 :
220 0 : FlowAction action_info;
221 0 : action_info.action = fe->match_p().sg_policy.action_summary;
222 0 : std::vector<ActionStr> action_str_l;
223 0 : SetActionStr(action_info, action_str_l);
224 0 : data.set_sg_action_summary(action_str_l);
225 :
226 0 : SetOneAclInfo(&policy, fe->match_p().mirror_action,
227 0 : fe->match_p().m_mirror_acl_l);
228 0 : data.set_mirror(policy);
229 :
230 0 : SetOneAclInfo(&policy, fe->match_p().out_mirror_action,
231 0 : fe->match_p().m_out_mirror_acl_l);
232 0 : data.set_out_mirror(policy);
233 :
234 0 : SetOneAclInfo(&policy, fe->match_p().aps_policy.action,
235 0 : fe->match_p().aps_policy.m_acl_l);
236 0 : data.set_policy_set(policy);
237 :
238 0 : SetOneAclInfo(&policy, fe->match_p().aps_policy.out_action,
239 0 : fe->match_p().aps_policy.m_out_acl_l);
240 0 : data.set_out_policy_set(policy);
241 :
242 0 : SetOneAclInfo(&policy, fe->match_p().aps_policy.reverse_action,
243 0 : fe->match_p().aps_policy.m_reverse_acl_l);
244 0 : data.set_reverse_policy_set(policy);
245 :
246 0 : SetOneAclInfo(&policy, fe->match_p().aps_policy.reverse_out_action,
247 0 : fe->match_p().aps_policy.m_reverse_out_acl_l);
248 0 : data.set_reverse_out_policy_set(policy);
249 :
250 0 : action_info.action = fe->match_p().aps_policy.action_summary;
251 0 : action_str_l.clear();
252 0 : SetActionStr(action_info, action_str_l);
253 0 : data.set_aps_action_summary(action_str_l);
254 :
255 0 : SetOneAclInfo(&policy, fe->match_p().fwaas_policy.action,
256 0 : fe->match_p().fwaas_policy.m_acl_l);
257 0 : data.set_fwaas_policy_set(policy);
258 :
259 0 : SetOneAclInfo(&policy, fe->match_p().fwaas_policy.out_action,
260 0 : fe->match_p().fwaas_policy.m_out_acl_l);
261 0 : data.set_fwaas_out_policy_set(policy);
262 :
263 0 : SetOneAclInfo(&policy, fe->match_p().fwaas_policy.reverse_action,
264 0 : fe->match_p().fwaas_policy.m_reverse_acl_l);
265 0 : data.set_fwaas_reverse_policy_set(policy);
266 :
267 0 : SetOneAclInfo(&policy, fe->match_p().fwaas_policy.reverse_out_action,
268 0 : fe->match_p().fwaas_policy.m_reverse_out_acl_l);
269 0 : data.set_fwaas_reverse_out_policy_set(policy);
270 :
271 0 : action_info.action = fe->match_p().fwaas_policy.action_summary;
272 0 : action_str_l.clear();
273 0 : SetActionStr(action_info, action_str_l);
274 0 : data.set_fwaas_action_summary(action_str_l);
275 :
276 0 : data.set_sg_rule_uuid(fe->sg_rule_uuid());
277 0 : data.set_nw_ace_uuid(fe->nw_ace_uuid());
278 0 : }
279 :
280 : ////////////////////////////////////////////////////////////////////////////////
281 :
282 0 : PktSandeshFlow::PktSandeshFlow(Agent *agent, FlowRecordsResp *obj,
283 0 : std::string resp_ctx, std::string key):
284 : Task((TaskScheduler::GetInstance()->GetTaskId("Agent::PktFlowResponder")),
285 0 : 0), resp_obj_(obj), resp_data_(resp_ctx),
286 0 : flow_iteration_key_(), key_valid_(false), delete_op_(false), agent_(agent),
287 0 : partition_id_(0) {
288 0 : if (key != agent_->NullString()) {
289 0 : if (SetFlowKey(key)) {
290 0 : key_valid_ = true;
291 : }
292 : }
293 0 : }
294 :
295 0 : PktSandeshFlow::~PktSandeshFlow() {
296 0 : }
297 :
298 0 : void PktSandeshFlow::SetSandeshFlowData(std::vector<SandeshFlowData> &list,
299 : FlowEntry *fe, const FlowExportInfo *info) {
300 0 : SandeshFlowData data;
301 0 : SET_SANDESH_FLOW_DATA(agent_, data, fe, info);
302 0 : list.push_back(data);
303 0 : }
304 :
305 0 : void PktSandeshFlow::SendResponse(SandeshResponse *resp) {
306 0 : resp->set_context(resp_data_);
307 0 : resp->set_more(false);
308 0 : resp->Response();
309 0 : }
310 :
311 0 : string PktSandeshFlow::GetFlowKey(const FlowKey &key, uint16_t partition_id) {
312 0 : std::stringstream ss;
313 0 : ss << partition_id << kDelimiter;
314 0 : ss << key.nh << kDelimiter;
315 0 : ss << key.src_port << kDelimiter;
316 0 : ss << key.dst_port << kDelimiter;
317 0 : ss << (uint16_t)key.protocol << kDelimiter;
318 0 : ss << key.src_addr.to_string() << kDelimiter;
319 0 : ss << key.dst_addr.to_string();
320 0 : return ss.str();
321 0 : }
322 :
323 0 : bool PktSandeshFlow::SetFlowKey(string key) {
324 : using std::istringstream;
325 :
326 0 : const char ch = kDelimiter;
327 0 : size_t n = std::count(key.begin(), key.end(), ch);
328 0 : if (n != 6) {
329 0 : return false;
330 : }
331 0 : std::stringstream ss(key);
332 0 : string item, sip, dip;
333 0 : uint32_t proto = 0;
334 :
335 0 : if (getline(ss, item, ch)) {
336 0 : istringstream(item) >> partition_id_;
337 : }
338 0 : if (getline(ss, item, ch)) {
339 0 : istringstream(item) >> flow_iteration_key_.nh;
340 : }
341 0 : if (getline(ss, item, ch)) {
342 0 : istringstream(item) >> flow_iteration_key_.src_port;
343 : }
344 0 : if (getline(ss, item, ch)) {
345 0 : istringstream(item) >> flow_iteration_key_.dst_port;
346 : }
347 0 : if (getline(ss, item, ch)) {
348 0 : istringstream(item) >> proto;
349 : }
350 0 : if (getline(ss, item, ch)) {
351 0 : sip = item;
352 : }
353 0 : if (getline(ss, item, ch)) {
354 0 : dip = item;
355 : }
356 0 : boost::system::error_code ec;
357 0 : flow_iteration_key_.src_addr = IpAddress::from_string(sip.c_str(), ec);
358 0 : flow_iteration_key_.dst_addr = IpAddress::from_string(dip.c_str(), ec);
359 0 : if (flow_iteration_key_.src_addr.is_v4()) {
360 0 : flow_iteration_key_.family = Address::INET;
361 0 : } else if (flow_iteration_key_.src_addr.is_v6()) {
362 0 : flow_iteration_key_.family = Address::INET6;
363 : }
364 0 : flow_iteration_key_.protocol = proto;
365 0 : return true;
366 0 : }
367 :
368 0 : bool PktSandeshFlow::Run() {
369 0 : FlowTable::FlowEntryMap::iterator it;
370 : std::vector<SandeshFlowData>& list =
371 0 : const_cast<std::vector<SandeshFlowData>&>(resp_obj_->get_flow_list());
372 0 : int count = 0;
373 0 : bool flow_key_set = false;
374 :
375 0 : if (partition_id_ >= agent_->flow_thread_count()) {
376 0 : FlowErrorResp *resp = new FlowErrorResp();
377 0 : SendResponse(resp);
378 0 : return true;
379 : }
380 :
381 0 : FlowTable *flow_obj = agent_->pkt()->flow_table(partition_id_);
382 :
383 0 : if (delete_op_) {
384 0 : for (int i =0; i < agent_->flow_thread_count(); i++){
385 0 : flow_obj = agent_->pkt()->flow_table(i);
386 0 : flow_obj->DeleteAll();
387 : }
388 0 : SendResponse(resp_obj_);
389 0 : return true;
390 : }
391 :
392 0 : if (key_valid_) {
393 0 : it = flow_obj->flow_entry_map_.upper_bound(flow_iteration_key_);
394 : } else {
395 0 : FlowErrorResp *resp = new FlowErrorResp();
396 0 : SendResponse(resp);
397 0 : return true;
398 : }
399 :
400 0 : while (it == flow_obj->flow_entry_map_.end() &&
401 0 : ++partition_id_ < agent_->flow_thread_count()) {
402 0 : flow_obj = agent_->pkt()->flow_table(partition_id_);
403 0 : it = flow_obj->flow_entry_map_.begin();
404 : }
405 :
406 0 : while (it != flow_obj->flow_entry_map_.end()) {
407 0 : FlowEntry *fe = it->second;
408 0 : FlowStatsCollector *fec = fe->fsc();
409 0 : const FlowExportInfo *info = NULL;
410 0 : if (fec) {
411 0 : info = fec->FindFlowExportInfo(fe);
412 : }
413 0 : SetSandeshFlowData(list, fe, info);
414 0 : ++it;
415 0 : count++;
416 0 : if (count == kMaxFlowResponse) {
417 0 : if (it != flow_obj->flow_entry_map_.end()) {
418 0 : resp_obj_->set_flow_key(GetFlowKey(fe->key(), partition_id_));
419 0 : flow_key_set = true;
420 :
421 : } else {
422 0 : FlowKey key;
423 0 : resp_obj_->set_flow_key(GetFlowKey(key, ++partition_id_));
424 0 : flow_key_set = true;
425 : }
426 0 : break;
427 : }
428 :
429 0 : while (it == flow_obj->flow_entry_map_.end()) {
430 0 : if (++partition_id_ < agent_->flow_thread_count()) {
431 0 : flow_obj = agent_->pkt()->flow_table(partition_id_);
432 0 : it = flow_obj->flow_entry_map_.begin();
433 0 : if (it != flow_obj->flow_entry_map_.end()) {
434 0 : break;
435 : }
436 : } else {
437 0 : break;
438 : }
439 : }
440 : }
441 :
442 0 : if (!flow_key_set) {
443 0 : resp_obj_->set_flow_key(PktSandeshFlow::start_key);
444 : }
445 :
446 0 : SendResponse(resp_obj_);
447 0 : return true;
448 : }
449 :
450 : ////////////////////////////////////////////////////////////////////////////////
451 :
452 0 : void NextFlowRecordsSet::HandleRequest() const {
453 0 : Agent *agent = Agent::GetInstance();
454 0 : FlowRecordsResp *resp = new FlowRecordsResp();
455 0 : PktSandeshFlow *task = new PktSandeshFlow(agent, resp, context(),
456 0 : get_flow_key());
457 0 : TaskScheduler *scheduler = TaskScheduler::GetInstance();
458 0 : scheduler->Enqueue(task);
459 0 : }
460 :
461 0 : void FetchAllFlowRecords::HandleRequest() const {
462 0 : Agent *agent = Agent::GetInstance();
463 0 : FlowRecordsResp *resp = new FlowRecordsResp();
464 0 : PktSandeshFlow *task = new PktSandeshFlow(agent, resp, context(),
465 0 : PktSandeshFlow::start_key);
466 0 : TaskScheduler *scheduler = TaskScheduler::GetInstance();
467 0 : scheduler->Enqueue(task);
468 0 : }
469 :
470 0 : void DeleteAllFlowRecords::HandleRequest() const {
471 0 : FlowRecordsResp *resp = new FlowRecordsResp();
472 :
473 0 : PktSandeshFlow *task = new PktSandeshFlow(Agent::GetInstance(), resp,
474 0 : context(),
475 0 : PktSandeshFlow::start_key);
476 0 : task->set_delete_op(true);
477 0 : TaskScheduler *scheduler = TaskScheduler::GetInstance();
478 0 : scheduler->Enqueue(task);
479 0 : }
480 :
481 0 : void FetchFlowRecord::HandleRequest() const {
482 0 : FlowKey key;
483 0 : Agent *agent = Agent::GetInstance();
484 0 : FlowTable *flow_obj = NULL;
485 :
486 0 : key.nh = get_nh();
487 0 : boost::system::error_code ec;
488 0 : key.src_addr = IpAddress::from_string(get_sip(), ec);
489 0 : key.dst_addr = IpAddress::from_string(get_dip(), ec);
490 0 : if (key.src_addr.is_v4()) {
491 0 : key.family = Address::INET;
492 0 : } else if (key.src_addr.is_v6()) {
493 0 : key.family = Address::INET6;
494 : }
495 0 : key.src_port = (unsigned)get_src_port();
496 0 : key.dst_port = (unsigned)get_dst_port();
497 0 : key.protocol = get_protocol();
498 :
499 0 : FlowTable::FlowEntryMap::iterator it;
500 0 : for (int i = 0; i < agent->flow_thread_count(); i++) {
501 0 : flow_obj = agent->pkt()->flow_table(i);
502 0 : it = flow_obj->flow_entry_map_.find(key);
503 0 : if (it != flow_obj->flow_entry_map_.end())
504 0 : break;
505 : }
506 :
507 : SandeshResponse *resp;
508 0 : if (flow_obj && it != flow_obj->flow_entry_map_.end()) {
509 0 : FlowRecordResp *flow_resp = new FlowRecordResp();
510 0 : FlowEntry *fe = it->second;
511 0 : FlowStatsCollector *fec = fe->fsc();
512 0 : const FlowExportInfo *info = NULL;
513 0 : if (fec) {
514 0 : info = fec->FindFlowExportInfo(fe);
515 : }
516 0 : SandeshFlowData data;
517 0 : SET_SANDESH_FLOW_DATA(agent, data, fe, info);
518 0 : flow_resp->set_record(data);
519 0 : resp = flow_resp;
520 0 : } else {
521 0 : resp = new FlowErrorResp();
522 : }
523 :
524 0 : resp->set_context(context());
525 0 : resp->set_more(false);
526 0 : resp->Response();
527 0 : }
528 :
529 : // Sandesh interface to modify flow aging interval
530 : // Intended for use in testing only
531 0 : void FlowAgeTimeReq::HandleRequest() const {
532 0 : Agent *agent = Agent::GetInstance();
533 0 : uint32_t age_time = get_new_age_time();
534 :
535 : FlowStatsCollectorObject *obj =
536 0 : agent->flow_stats_manager()->default_flow_stats_collector_obj();
537 :
538 0 : FlowAgeTimeResp *resp = new FlowAgeTimeResp();
539 0 : if (obj == NULL) {
540 0 : goto done;
541 : }
542 0 : resp->set_old_age_time(obj->GetAgeTimeInSeconds());
543 :
544 0 : if (age_time && age_time != resp->get_old_age_time()) {
545 0 : obj->UpdateAgeTimeInSeconds(age_time);
546 0 : resp->set_new_age_time(age_time);
547 : } else {
548 0 : resp->set_new_age_time(resp->get_old_age_time());
549 : }
550 0 : done:
551 0 : resp->set_context(context());
552 0 : resp->set_more(false);
553 0 : resp->Response();
554 0 : }
555 :
556 0 : void FetchLinkLocalFlowInfo::HandleRequest() const {
557 0 : LinkLocalFlowInfoResp *resp = new LinkLocalFlowInfoResp();
558 : std::vector<LinkLocalFlowInfo> &list =
559 : const_cast<std::vector<LinkLocalFlowInfo>&>
560 0 : (resp->get_linklocal_flow_list());
561 :
562 : const FlowTable::LinkLocalFlowInfoMap &flow_map =
563 0 : Agent::GetInstance()->pkt()->flow_table(0)->linklocal_flow_info_map();
564 0 : FlowTable::LinkLocalFlowInfoMap::const_iterator it = flow_map.begin();
565 0 : while (it != flow_map.end()) {
566 0 : LinkLocalFlowInfo info;
567 0 : info.fd = it->first;
568 0 : info.flow_index = it->second.flow_index;
569 0 : info.source_addr = it->second.flow_key.src_addr.to_string();
570 0 : info.dest_addr = it->second.flow_key.dst_addr.to_string();
571 0 : info.protocol = it->second.flow_key.protocol;
572 0 : info.source_port = it->second.flow_key.src_port;
573 0 : info.dest_port = it->second.flow_key.dst_port;
574 0 : info.timestamp = integerToString(UTCUsecToPTime(it->second.timestamp));
575 0 : list.push_back(info);
576 0 : ++it;
577 0 : }
578 :
579 0 : resp->set_context(context());
580 0 : resp->set_more(false);
581 0 : resp->Response();
582 0 : }
583 :
584 0 : bool PktSandeshFlowStats::Run() {
585 : std::vector<SandeshFlowData>& list =
586 0 : const_cast<std::vector<SandeshFlowData>&>(resp_->get_flow_list());
587 0 : int count = 0;
588 0 : bool flow_key_set = false;
589 :
590 0 : if (partition_id_ > agent_->flow_thread_count()) {
591 0 : FlowErrorResp *resp = new FlowErrorResp();
592 0 : SendResponse(resp);
593 0 : return true;
594 : }
595 :
596 0 : FlowTable *flow_obj = agent_->pkt()->flow_table(partition_id_);
597 0 : FlowStatsManager *fm = agent_->flow_stats_manager();
598 0 : const FlowStatsCollectorObject *fsc_obj = fm->Find(proto_, port_);
599 0 : if (!fsc_obj) {
600 0 : FlowErrorResp *resp = new FlowErrorResp();
601 0 : SendResponse(resp);
602 0 : return true;
603 : }
604 :
605 0 : FlowTable::FlowEntryMap::iterator it;
606 0 : if (key_valid_) {
607 0 : it = flow_obj->flow_entry_map_.upper_bound(flow_iteration_key_);
608 : } else {
609 0 : FlowErrorResp *resp = new FlowErrorResp();
610 0 : SendResponse(resp);
611 0 : return true;
612 : }
613 :
614 0 : while (it == flow_obj->flow_entry_map_.end() &&
615 0 : ++partition_id_ < agent_->flow_thread_count()) {
616 0 : flow_obj = agent_->pkt()->flow_table(partition_id_);
617 0 : it = flow_obj->flow_entry_map_.begin();
618 : }
619 :
620 0 : while (it != flow_obj->flow_entry_map_.end()) {
621 0 : FlowEntry *fe = it->second;
622 0 : const FlowExportInfo *info = NULL;
623 0 : if (fe->fsc()) {
624 0 : info = fe->fsc()->FindFlowExportInfo(fe);
625 : }
626 0 : SetSandeshFlowData(list, fe, info);
627 0 : ++it;
628 0 : count++;
629 0 : if (count == kMaxFlowResponse) {
630 0 : if (it != flow_obj->flow_entry_map_.end()) {
631 0 : std::ostringstream ostr;
632 0 : ostr << proto_ << ":" << port_ << ":"
633 0 : << GetFlowKey(fe->key(), partition_id_);
634 0 : resp_->set_flow_key(ostr.str());
635 0 : flow_key_set = true;
636 0 : } else {
637 0 : std::ostringstream ostr;
638 0 : FlowKey key;
639 0 : ostr << proto_ << ":" << port_ << ":"
640 0 : << GetFlowKey(key, ++partition_id_);
641 0 : resp_->set_flow_key(ostr.str());
642 0 : flow_key_set = true;
643 0 : }
644 0 : break;
645 : }
646 :
647 0 : while (it == flow_obj->flow_entry_map_.end()) {
648 0 : if (++partition_id_ < agent_->flow_thread_count()) {
649 0 : flow_obj = agent_->pkt()->flow_table(partition_id_);
650 0 : it = flow_obj->flow_entry_map_.begin();
651 0 : if (it != flow_obj->flow_entry_map_.end()) {
652 0 : break;
653 : }
654 : } else {
655 0 : break;
656 : }
657 : }
658 :
659 : }
660 :
661 0 : if (!flow_key_set) {
662 0 : std::ostringstream ostr;
663 0 : ostr << proto_ << ":" << port_ << ":" <<PktSandeshFlow::start_key;
664 0 : resp_->set_flow_key(ostr.str());
665 0 : }
666 0 : SendResponse(resp_);
667 0 : return true;
668 : }
669 :
670 0 : bool PktSandeshFlowStats::SetProto(string &key) {
671 0 : size_t n = std::count(key.begin(), key.end(), ':');
672 0 : if (n != 2) {
673 0 : return false;
674 : }
675 0 : std::stringstream ss(key);
676 0 : string item;
677 0 : if (getline(ss, item, ':')) {
678 0 : std::istringstream(item) >> proto_;
679 : }
680 0 : if (getline(ss, item, ':')) {
681 0 : std::istringstream(item) >> port_;
682 : }
683 0 : if (getline(ss, item)) {
684 0 : SetFlowKey(item);
685 : }
686 0 : return true;
687 0 : }
688 :
689 0 : PktSandeshFlowStats::PktSandeshFlowStats(Agent *agent, FlowStatsCollectorRecordsResp *obj,
690 0 : std::string resp_ctx, std::string key):
691 0 : PktSandeshFlow(agent, NULL, resp_ctx, key), resp_(obj) {
692 0 : if (key != agent_->NullString()) {
693 0 : if (SetProto(key)) {
694 0 : key_valid_ = true;
695 : }
696 : }
697 0 : }
698 :
699 0 : void ShowFlowStatsCollector::HandleRequest() const {
700 0 : Agent *agent = Agent::GetInstance();
701 0 : FlowStatsCollectorRecordsResp *resp = new FlowStatsCollectorRecordsResp();
702 :
703 0 : std::ostringstream ostr;
704 0 : ostr << get_protocol() << ":" << get_port() << ":" <<
705 0 : PktSandeshFlow::start_key;
706 0 : PktSandeshFlowStats *task = new PktSandeshFlowStats(agent, resp, context(),
707 0 : ostr.str());
708 0 : TaskScheduler *scheduler = TaskScheduler::GetInstance();
709 0 : scheduler->Enqueue(task);
710 0 : }
711 :
712 0 : void NextFlowStatsRecordsSet::HandleRequest() const {
713 0 : Agent *agent = Agent::GetInstance();
714 0 : FlowStatsCollectorRecordsResp *resp = new FlowStatsCollectorRecordsResp();
715 :
716 0 : PktSandeshFlow *task = new PktSandeshFlowStats(agent, resp, context(),
717 0 : get_flow_key());
718 0 : TaskScheduler *scheduler = TaskScheduler::GetInstance();
719 0 : scheduler->Enqueue(task);
720 0 : }
721 :
722 :
723 0 : void SandeshFlowTableInfoRequest::HandleRequest() const {
724 0 : Agent *agent = Agent::GetInstance();
725 0 : FlowProto *proto = agent->pkt()->get_flow_proto();
726 0 : SandeshFlowTableInfoResp *resp = new SandeshFlowTableInfoResp();
727 0 : resp->set_flow_count(proto->FlowCount());
728 0 : resp->set_total_added(agent->stats()->flow_created());
729 0 : resp->set_max_flows(agent->stats()->max_flow_count());
730 0 : resp->set_total_deleted(agent->stats()->flow_aged());
731 0 : std::vector<SandeshFlowTableInfo> info_list;
732 0 : for (uint16_t i = 0; i < proto->flow_table_count(); i++) {
733 0 : FlowTable *table = proto->GetTable(i);
734 0 : SandeshFlowTableInfo info;
735 0 : info.set_index(table->table_index());
736 0 : info.set_count(table->Size());
737 0 : info.set_total_add(table->free_list()->total_alloc());
738 0 : info.set_total_del(table->free_list()->total_free());
739 0 : info.set_freelist_count(table->free_list()->free_count());
740 0 : info_list.push_back(info);
741 0 : }
742 0 : resp->set_table_list(info_list);
743 0 : resp->set_context(context());
744 0 : resp->set_more(false);
745 0 : resp->Response();
746 0 : }
747 : ////////////////////////////////////////////////////////////////////////////////
748 :
749 0 : static InetRouteFlowMgmtKey* StringToInetRouteFlowMgmtKey(const string &key,
750 : uint16_t *id) {
751 : using std::istringstream;
752 :
753 0 : Agent *agent = Agent::GetInstance();
754 0 : const char ch = PktSandeshFlow::kDelimiter;
755 0 : size_t n = std::count(key.begin(), key.end(), ch);
756 0 : if (n != 3) {
757 0 : return NULL;
758 : }
759 0 : std::stringstream ss(key);
760 0 : string item, ip_str;
761 0 : uint32_t vrf_id = 0;
762 0 : uint16_t plen = 0, mgr_id = 0;
763 :
764 0 : if (getline(ss, item, ch)) {
765 0 : istringstream(item) >> mgr_id;
766 : }
767 0 : if (mgr_id >= agent->pkt()->flow_mgmt_manager_list().size()) {
768 0 : return NULL;
769 : }
770 0 : *id = mgr_id;
771 0 : if (getline(ss, item, ch)) {
772 0 : istringstream(item) >> vrf_id;
773 : }
774 0 : if (getline(ss, item, ch)) {
775 0 : ip_str = item;
776 : }
777 0 : if (getline(ss, item, ch)) {
778 0 : istringstream(item) >> plen;
779 : }
780 0 : boost::system::error_code ec;
781 0 : IpAddress ip = IpAddress::from_string(ip_str.c_str(), ec);
782 0 : if (ec) {
783 0 : return NULL;
784 : }
785 0 : InetRouteFlowMgmtKey* ret = new InetRouteFlowMgmtKey(vrf_id, ip, plen);
786 0 : return ret;
787 0 : }
788 :
789 0 : void FlowsPerInetRouteFlowMgmtKeyReq::HandleRequest() const {
790 : FlowsPerInetRouteFlowMgmtKeyResp *resp= new
791 0 : FlowsPerInetRouteFlowMgmtKeyResp();
792 0 : resp->set_context(context());
793 0 : resp->set_more(false);
794 : std::vector<SandeshFlowData> &resp_list =
795 0 : const_cast<std::vector<SandeshFlowData>&>(resp->get_flow_list());
796 0 : Agent *agent = Agent::GetInstance();
797 0 : uint16_t mgr_id = 0;
798 0 : FlowMgmtManager *mgr = NULL;
799 0 : InetRouteFlowMgmtKey *ikey = StringToInetRouteFlowMgmtKey(get_key(),
800 : &mgr_id);
801 0 : if (!ikey) {
802 0 : resp->Response();
803 0 : return;
804 : }
805 0 : mgr = agent->pkt()->flow_mgmt_manager(mgr_id);
806 0 : InetRouteFlowMgmtTree* tree = mgr->ip4_route_flow_mgmt_tree();
807 0 : FlowMgmtEntry *entry = tree->Find(ikey);
808 0 : delete ikey;
809 0 : if (!entry) {
810 0 : resp->Response();
811 0 : return;
812 : }
813 0 : if (entry->Size() == 0) {
814 0 : resp->Response();
815 0 : return;
816 : }
817 0 : const FlowMgmtEntry::FlowList &flow_list = entry->flow_list();
818 0 : FlowMgmtEntry::FlowList::const_iterator it = flow_list.begin();
819 0 : while (it != flow_list.end()) {
820 0 : const FlowMgmtKeyNode *node = &(*it);
821 0 : FlowEntry *fe = node->flow_entry();
822 0 : SandeshFlowData data;
823 0 : const FlowExportInfo *info = NULL;
824 0 : SET_SANDESH_FLOW_DATA(agent, data, fe, info);
825 0 : resp_list.push_back(data);
826 0 : it++;
827 0 : }
828 0 : resp->Response();
829 : }
830 :
831 0 : void Inet4FlowTreeReq::HandleRequest() const {
832 0 : Agent *agent = Agent::GetInstance();
833 : std::vector<FlowMgmtManager *>::const_iterator it =
834 0 : agent->pkt()->flow_mgmt_manager_iterator_begin();
835 0 : Inet4FlowTreeResponse *resp = new Inet4FlowTreeResponse();
836 : std::vector<SandeshInetRouteFlowMgmtEntryLink> &resp_list =
837 : const_cast<std::vector<SandeshInetRouteFlowMgmtEntryLink>&>
838 0 : (resp->get_keys());
839 0 : uint16_t mgr_idx = 0;
840 0 : while (it != agent->pkt()->flow_mgmt_manager_iterator_end()) {
841 0 : FlowMgmtManager *mgr = *it;
842 0 : it++;
843 0 : InetRouteFlowMgmtTree* tree = mgr->ip4_route_flow_mgmt_tree();
844 0 : FlowMgmtTree::Tree &list = tree->tree();
845 0 : FlowMgmtTree::Tree::iterator tree_it = list.begin();
846 0 : while(tree_it != list.end()) {
847 : InetRouteFlowMgmtKey *key = static_cast<InetRouteFlowMgmtKey *>
848 0 : (tree_it->first);
849 0 : string key_str = InetRouteFlowMgmtKeyToString(mgr_idx, key);
850 0 : SandeshInetRouteFlowMgmtEntryLink entry;
851 0 : entry.set_inet_route_flow_mgmt_key(key_str);
852 0 : resp_list.push_back(entry);
853 0 : ++tree_it;
854 0 : }
855 0 : ++mgr_idx;
856 : }
857 0 : resp->set_context(context());
858 0 : resp->set_more(false);
859 0 : resp->Response();
860 0 : }
861 :
862 0 : void SNatPortConfigRequest::HandleRequest() const {
863 0 : Agent *agent = Agent::GetInstance();
864 : PortTableManager *pm =
865 0 : agent->pkt()->get_flow_proto()->port_table_manager();
866 :
867 0 : SNatPortResponse *resp = new SNatPortResponse();
868 : std::vector<PortConfigData> &config_list =
869 0 : const_cast<std::vector<PortConfigData>&>(resp->get_port_config_list());
870 :
871 0 : for(uint16_t protocol = 0; protocol < IPPROTO_MAX; protocol++) {
872 0 : const PortTable *pt = pm->GetPortTable(protocol);
873 0 : if (pt == NULL) {
874 0 : continue;
875 : }
876 :
877 0 : const PortConfig *pc = pt->port_config();
878 : //Only count specified
879 0 : PortConfigData spc;
880 0 : spc.port_count = pc->port_count;
881 0 : spc.protocol = protocol;
882 :
883 : std::vector<PortConfig::PortRange>::const_iterator it =
884 0 : pc->port_range.begin();
885 0 : for(;it != pc->port_range.end(); it++) {
886 0 : PortConfigRange pcr;
887 0 : pcr.port_start = it->port_start;
888 0 : pcr.port_end = it->port_end;
889 0 : spc.port_range.push_back(pcr);
890 0 : }
891 :
892 0 : spc.set_bound_port_list((pt->GetPortList()));
893 0 : config_list.push_back(spc);
894 0 : }
895 0 : resp->set_context(context());
896 0 : resp->set_more(false);
897 0 : resp->Response();
898 0 : }
899 :
900 0 : static void HandlePortFlowReq(uint16_t protocol, uint16_t port,
901 : bool match_proto, bool match_port,
902 : std::string context) {
903 0 : Agent *agent = Agent::GetInstance();
904 : PortTableManager *pm =
905 0 : agent->pkt()->get_flow_proto()->port_table_manager();
906 :
907 0 : SNatPortFlowResponse *resp = new SNatPortFlowResponse();
908 : std::vector<SNatPortFlow> &list =
909 0 : const_cast<std::vector<SNatPortFlow>&>(resp->get_port_flow_list());
910 :
911 0 : uint16_t flow_count = 0;
912 0 : uint16_t next_port = 0;
913 0 : uint16_t proto = 0;
914 0 : for(; proto < IPPROTO_MAX; proto++) {
915 0 : const PortTable *pt = pm->GetPortTable(proto);
916 0 : next_port = 0;
917 0 : if (match_proto && proto != protocol) {
918 0 : continue;
919 : }
920 :
921 0 : if (proto < protocol) {
922 0 : continue;
923 : }
924 :
925 0 : if (pt == NULL) {
926 0 : continue;
927 : }
928 :
929 0 : std::vector<uint16_t> ports = pt->GetPortList();
930 0 : std::vector<uint16_t>::const_iterator it = ports.begin();
931 0 : for(; it != ports.end(); it++) {
932 0 : if (match_port && port != *it) {
933 0 : continue;
934 : }
935 :
936 0 : if (match_port && port > *it) {
937 0 : break;
938 : }
939 :
940 0 : if (port > *it) {
941 0 : continue;
942 : }
943 :
944 0 : std::vector<FlowKey> flow_list;
945 0 : pt->GetFlowKeyList(*it, flow_list);
946 0 : flow_count += flow_list.size();
947 :
948 0 : SNatPortFlow snf;
949 0 : snf.port = *it;
950 0 : snf.protocol = proto;
951 0 : std::vector<FlowKey>::iterator flow_it = flow_list.begin();
952 0 : for (; flow_it != flow_list.end(); flow_it++) {
953 0 : SNatFlowKey flow_key;
954 0 : flow_key.nh = flow_it->nh;
955 0 : flow_key.sip = flow_it->src_addr.to_string();
956 0 : flow_key.dip = flow_it->dst_addr.to_string();
957 0 : flow_key.src_port = flow_it->src_port;
958 0 : flow_key.dst_port = flow_it->dst_port;
959 0 : flow_key.protocol = flow_it->protocol;
960 0 : snf.flows.push_back(flow_key);
961 0 : }
962 :
963 0 : list.push_back(snf);
964 :
965 0 : if (flow_count >= 1) {
966 0 : break;
967 : }
968 0 : }
969 :
970 0 : if (it != ports.end() && match_port == false) {
971 0 : next_port = *it + 1;
972 : }
973 :
974 0 : if (match_port == false) {
975 0 : port = 0;
976 : }
977 :
978 0 : if (flow_count >= 1) {
979 0 : break;
980 : }
981 0 : }
982 :
983 0 : bool next = true;
984 0 : if (match_proto && next_port == 0) {
985 0 : next = false;
986 : }
987 :
988 0 : if (proto == IPPROTO_MAX) {
989 0 : next = false;
990 : }
991 :
992 0 : if (next) {
993 0 : std::stringstream str;
994 0 : str << proto << ":" << next_port << ":" << match_proto
995 0 : << ":" << match_port;
996 0 : resp->set_flow_key(str.str());
997 0 : }
998 :
999 0 : resp->set_context(context);
1000 0 : resp->set_more(false);
1001 0 : resp->Response();
1002 0 : }
1003 :
1004 0 : void SNatPerPortFlowList::HandleRequest() const {
1005 0 : bool match_proto = false;
1006 0 : if (protocol != 0) {
1007 0 : match_proto = true;
1008 : }
1009 :
1010 0 : bool match_port = false;
1011 0 : if (port != 0) {
1012 0 : match_port = true;
1013 : }
1014 :
1015 0 : HandlePortFlowReq(protocol, port, match_proto, match_port,
1016 0 : context());
1017 0 : }
1018 :
1019 0 : void NextPerPortFlowList::HandleRequest() const {
1020 : using std::istringstream;
1021 :
1022 0 : uint16_t proto = 0;
1023 0 : uint16_t port = 0;
1024 0 : bool match_proto = false;
1025 0 : bool match_port = false;
1026 0 : std::string colon;
1027 :
1028 0 : std::stringstream ss(port_key);
1029 0 : string item;
1030 0 : const char ch = ':';
1031 :
1032 0 : size_t n = std::count(port_key.begin(), port_key.end(), ch);
1033 0 : if (n != 3) {
1034 0 : goto fail;
1035 : }
1036 :
1037 0 : if (getline(ss, item, ch)) {
1038 0 : istringstream(item) >> proto;
1039 : }
1040 0 : if (getline(ss, item, ch)) {
1041 0 : istringstream(item) >> port;
1042 : }
1043 0 : if (getline(ss, item, ch)) {
1044 0 : istringstream(item) >> match_proto;
1045 : }
1046 0 : if (getline(ss, item, ch)) {
1047 0 : istringstream(item) >> match_port;
1048 : }
1049 :
1050 0 : HandlePortFlowReq(proto, port, match_proto, match_port,
1051 0 : context());
1052 :
1053 0 : fail:
1054 0 : FlowErrorResp *resp = new FlowErrorResp();
1055 0 : resp->set_context(context());
1056 0 : resp->set_more(false);
1057 0 : resp->Response();
1058 0 : }
|